~ubuntu-branches/ubuntu/trusty/util-linux/trusty-proposed

« back to all changes in this revision

Viewing changes to libblkid/src/probe.c

  • Committer: Package Import Robot
  • Author(s): LaMont Jones
  • Date: 2011-11-03 15:38:23 UTC
  • mto: (4.5.5 sid) (1.6.4)
  • mto: This revision was merged to the branch mainline in revision 85.
  • Revision ID: package-import@ubuntu.com-20111103153823-10sx16jprzxlhkqf
ImportĀ upstreamĀ versionĀ 2.20.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * Low-level libblkid probing API
 
3
 *
 
4
 * Copyright (C) 2008-2009 Karel Zak <kzak@redhat.com>
 
5
 *
 
6
 * This file may be redistributed under the terms of the
 
7
 * GNU Lesser General Public License.
 
8
 */
 
9
 
 
10
/**
 
11
 * SECTION: lowprobe
 
12
 * @title: Low-level probing
 
13
 * @short_description: low-level prober initialization
 
14
 *
 
15
 * The low-level probing routines always and directly read information from
 
16
 * the selected (see blkid_probe_set_device()) device.
 
17
 *
 
18
 * The probing routines are grouped together into separate chains. Currently,
 
19
 * the library provides superblocks, partitions and topology chains.
 
20
 *
 
21
 * The probing routines is possible to filter (enable/disable) by type (e.g.
 
22
 * fstype "vfat" or partype "gpt") or by usage flags (e.g. BLKID_USAGE_RAID).
 
23
 * These filters are per-chain. Note that always when you touch the chain
 
24
 * filter the current probing position is reseted and probing starts from
 
25
 * scratch.  It means that the chain filter should not be modified during
 
26
 * probing, for example in loop where you call blkid_do_probe().
 
27
 *
 
28
 * For more details see the chain specific documentation.
 
29
 *
 
30
 * The low-level API provides two ways how access to probing results.
 
31
 *
 
32
 *   1. The NAME=value (tag) interface. This interface is older and returns all data
 
33
 *      as strings. This interface is generic for all chains.
 
34
 *
 
35
 *   2. The binary interfaces. These interfaces return data in the native formats.
 
36
 *      The interface is always specific to the probing chain.
 
37
 *
 
38
 *  Note that the previous probing result (binary or NAME=value) is always
 
39
 *  zeroized when a chain probing function is called. For example
 
40
 *
 
41
 * <informalexample>
 
42
 *   <programlisting>
 
43
 *     blkid_probe_enable_partitions(pr, TRUE);
 
44
 *     blkid_probe_enable_superblocks(pr, FALSE);
 
45
 *
 
46
 *     blkid_do_safeprobe(pr);
 
47
 *   </programlisting>
 
48
 * </informalexample>
 
49
 *
 
50
 * overwrites the previous probing result for the partitions chain, the superblocks
 
51
 * result is not modified.
 
52
 */
 
53
 
 
54
/**
 
55
 * SECTION: lowprobe-tags
 
56
 * @title: Low-level tags
 
57
 * @short_description: generic NAME=value interface.
 
58
 *
 
59
 * The probing routines inside the chain are mutually exclusive by default --
 
60
 * only few probing routines are marked as "tolerant". The "tolerant" probing
 
61
 * routines are used for filesystem which can share the same device with any
 
62
 * other filesystem. The blkid_do_safeprobe() checks for the "tolerant" flag.
 
63
 *
 
64
 * The SUPERBLOCKS chain is enabled by default. The all others chains is
 
65
 * necessary to enable by blkid_probe_enable_'CHAINNAME'(). See chains specific
 
66
 * documentation.
 
67
 *
 
68
 * The blkid_do_probe() function returns a result from only one probing
 
69
 * routine, and the next call from the next probing routine. It means you need
 
70
 * to call the function in loop, for example:
 
71
 *
 
72
 * <informalexample>
 
73
 *   <programlisting>
 
74
 *      while((blkid_do_probe(pr) == 0)
 
75
 *              ... use result ...
 
76
 *   </programlisting>
 
77
 * </informalexample>
 
78
 *
 
79
 * The blkid_do_safeprobe() is the same as blkid_do_probe(), but returns only
 
80
 * first probing result for every enabled chain. This function checks for
 
81
 * ambivalent results (e.g. more "intolerant" filesystems superblocks on the
 
82
 * device).
 
83
 *
 
84
 * The probing result is set of NAME=value pairs (the NAME is always unique).
 
85
 */
 
86
 
 
87
#include <stdio.h>
 
88
#include <string.h>
 
89
#include <stdlib.h>
 
90
#include <unistd.h>
 
91
#include <fcntl.h>
 
92
#include <ctype.h>
 
93
#include <sys/types.h>
 
94
#ifdef HAVE_LINUX_CDROM_H
 
95
#include <linux/cdrom.h>
 
96
#endif
 
97
#ifdef HAVE_SYS_STAT_H
 
98
#include <sys/stat.h>
 
99
#endif
 
100
#ifdef HAVE_ERRNO_H
 
101
#include <errno.h>
 
102
#endif
 
103
#include <inttypes.h>
 
104
#include <stdint.h>
 
105
#include <stdarg.h>
 
106
 
 
107
#ifdef HAVE_LIBUUID
 
108
# include <uuid.h>
 
109
#endif
 
110
 
 
111
#include "blkidP.h"
 
112
 
 
113
/* chains */
 
114
extern const struct blkid_chaindrv superblocks_drv;
 
115
extern const struct blkid_chaindrv topology_drv;
 
116
extern const struct blkid_chaindrv partitions_drv;
 
117
 
 
118
/*
 
119
 * All supported chains
 
120
 */
 
121
static const struct blkid_chaindrv *chains_drvs[] = {
 
122
        [BLKID_CHAIN_SUBLKS] = &superblocks_drv,
 
123
        [BLKID_CHAIN_TOPLGY] = &topology_drv,
 
124
        [BLKID_CHAIN_PARTS] = &partitions_drv
 
125
};
 
126
 
 
127
static void blkid_probe_reset_vals(blkid_probe pr);
 
128
static void blkid_probe_reset_buffer(blkid_probe pr);
 
129
 
 
130
/**
 
131
 * blkid_new_probe:
 
132
 *
 
133
 * Returns: a pointer to the newly allocated probe struct.
 
134
 */
 
135
blkid_probe blkid_new_probe(void)
 
136
{
 
137
        int i;
 
138
        blkid_probe pr;
 
139
 
 
140
        blkid_init_debug(0);
 
141
        pr = calloc(1, sizeof(struct blkid_struct_probe));
 
142
        if (!pr)
 
143
                return NULL;
 
144
 
 
145
        DBG(DEBUG_LOWPROBE, printf("allocate a new probe %p\n", pr));
 
146
 
 
147
        /* initialize chains */
 
148
        for (i = 0; i < BLKID_NCHAINS; i++) {
 
149
                pr->chains[i].driver = chains_drvs[i];
 
150
                pr->chains[i].flags = chains_drvs[i]->dflt_flags;
 
151
                pr->chains[i].enabled = chains_drvs[i]->dflt_enabled;
 
152
        }
 
153
        INIT_LIST_HEAD(&pr->buffers);
 
154
        return pr;
 
155
}
 
156
 
 
157
/*
 
158
 * Clone @parent, the new clone shares all, but except:
 
159
 *
 
160
 *      - probing result
 
161
 *      - bufferes if another device (or offset) is set to the prober
 
162
 */
 
163
blkid_probe blkid_clone_probe(blkid_probe parent)
 
164
{
 
165
        blkid_probe pr;
 
166
 
 
167
        if (!parent)
 
168
                return NULL;
 
169
 
 
170
        DBG(DEBUG_LOWPROBE, printf("allocate a probe clone\n"));
 
171
 
 
172
        pr = blkid_new_probe();
 
173
        if (!pr)
 
174
                return NULL;
 
175
 
 
176
        pr->fd = parent->fd;
 
177
        pr->off = parent->off;
 
178
        pr->size = parent->size;
 
179
        pr->devno = parent->devno;
 
180
        pr->disk_devno = parent->disk_devno;
 
181
        pr->blkssz = parent->blkssz;
 
182
        pr->flags = parent->flags;
 
183
        pr->parent = parent;
 
184
 
 
185
        return pr;
 
186
}
 
187
 
 
188
 
 
189
 
 
190
/**
 
191
 * blkid_new_probe_from_filename:
 
192
 * @filename: device or regular file
 
193
 *
 
194
 * This function is same as call open(filename), blkid_new_probe() and
 
195
 * blkid_probe_set_device(pr, fd, 0, 0).
 
196
 *
 
197
 * The @filename is closed by blkid_free_probe() or by the
 
198
 * blkid_probe_set_device() call.
 
199
 *
 
200
 * Returns: a pointer to the newly allocated probe struct or NULL in case of
 
201
 * error.
 
202
 */
 
203
blkid_probe blkid_new_probe_from_filename(const char *filename)
 
204
{
 
205
        int fd = -1;
 
206
        blkid_probe pr = NULL;
 
207
 
 
208
        if (!filename)
 
209
                return NULL;
 
210
 
 
211
        fd = open(filename, O_RDONLY);
 
212
        if (fd < 0)
 
213
                return NULL;
 
214
 
 
215
        pr = blkid_new_probe();
 
216
        if (!pr)
 
217
                goto err;
 
218
 
 
219
        if (blkid_probe_set_device(pr, fd, 0, 0))
 
220
                goto err;
 
221
 
 
222
        pr->flags |= BLKID_FL_PRIVATE_FD;
 
223
        return pr;
 
224
err:
 
225
        if (fd >= 0)
 
226
                close(fd);
 
227
        blkid_free_probe(pr);
 
228
        return NULL;
 
229
}
 
230
 
 
231
/**
 
232
 * blkid_free_probe:
 
233
 * @pr: probe
 
234
 *
 
235
 * Deallocates the probe struct, buffers and all allocated
 
236
 * data that are associated with this probing control struct.
 
237
 */
 
238
void blkid_free_probe(blkid_probe pr)
 
239
{
 
240
        int i;
 
241
 
 
242
        if (!pr)
 
243
                return;
 
244
 
 
245
        for (i = 0; i < BLKID_NCHAINS; i++) {
 
246
                struct blkid_chain *ch = &pr->chains[i];
 
247
 
 
248
                if (ch->driver->free_data)
 
249
                        ch->driver->free_data(pr, ch->data);
 
250
                free(ch->fltr);
 
251
        }
 
252
 
 
253
        if ((pr->flags & BLKID_FL_PRIVATE_FD) && pr->fd >= 0)
 
254
                close(pr->fd);
 
255
        blkid_probe_reset_buffer(pr);
 
256
        blkid_free_probe(pr->disk_probe);
 
257
 
 
258
        DBG(DEBUG_LOWPROBE, printf("free probe %p\n", pr));
 
259
        free(pr);
 
260
}
 
261
 
 
262
 
 
263
/*
 
264
 * Removes chain values from probing result.
 
265
 */
 
266
void blkid_probe_chain_reset_vals(blkid_probe pr, struct blkid_chain *chn)
 
267
{
 
268
        int nvals = pr->nvals;
 
269
        int i, x;
 
270
 
 
271
        for (x = 0, i = 0; i < pr->nvals; i++) {
 
272
                struct blkid_prval *v = &pr->vals[i];
 
273
 
 
274
                if (v->chain != chn && x == i) {
 
275
                        x++;
 
276
                        continue;
 
277
                }
 
278
                if (v->chain == chn) {
 
279
                        --nvals;
 
280
                        continue;
 
281
                }
 
282
                memcpy(&pr->vals[x++], v, sizeof(struct blkid_prval));
 
283
        }
 
284
        pr->nvals = nvals;
 
285
}
 
286
 
 
287
static void blkid_probe_chain_reset_position(struct blkid_chain *chn)
 
288
{
 
289
        if (chn)
 
290
                chn->idx = -1;
 
291
}
 
292
 
 
293
/*
 
294
 * Copies chain values from probing result to @vals, the max size of @vals is
 
295
 * @nvals and returns real number of values.
 
296
 */
 
297
int blkid_probe_chain_copy_vals(blkid_probe pr, struct blkid_chain *chn,
 
298
                struct blkid_prval *vals, int nvals)
 
299
{
 
300
        int i, x;
 
301
 
 
302
        for (x = 0, i = 0; i < pr->nvals && x < nvals; i++) {
 
303
                struct blkid_prval *v = &pr->vals[i];
 
304
 
 
305
                if (v->chain != chn)
 
306
                        continue;
 
307
                memcpy(&vals[x++], v, sizeof(struct blkid_prval));
 
308
        }
 
309
        return x;
 
310
}
 
311
 
 
312
/*
 
313
 * Appends values from @vals to the probing result
 
314
 */
 
315
void blkid_probe_append_vals(blkid_probe pr, struct blkid_prval *vals, int nvals)
 
316
{
 
317
        int i = 0;
 
318
 
 
319
        while (i < nvals && pr->nvals < BLKID_NVALS) {
 
320
                memcpy(&pr->vals[pr->nvals++], &vals[i++],
 
321
                                sizeof(struct blkid_prval));
 
322
        }
 
323
}
 
324
 
 
325
static void blkid_probe_reset_vals(blkid_probe pr)
 
326
{
 
327
        memset(pr->vals, 0, sizeof(pr->vals));
 
328
        pr->nvals = 0;
 
329
}
 
330
 
 
331
struct blkid_chain *blkid_probe_get_chain(blkid_probe pr)
 
332
{
 
333
        return pr->cur_chain;
 
334
}
 
335
 
 
336
void *blkid_probe_get_binary_data(blkid_probe pr, struct blkid_chain *chn)
 
337
{
 
338
        int rc, org_prob_flags;
 
339
        struct blkid_chain *org_chn;
 
340
 
 
341
        if (!pr || !chn)
 
342
                return NULL;
 
343
 
 
344
        /* save the current setting -- the binary API has to be completely
 
345
         * independent on the current probing status
 
346
         */
 
347
        org_chn = pr->cur_chain;
 
348
        org_prob_flags = pr->prob_flags;
 
349
 
 
350
        pr->cur_chain = chn;
 
351
        pr->prob_flags = 0;
 
352
        chn->binary = TRUE;
 
353
        blkid_probe_chain_reset_position(chn);
 
354
 
 
355
        rc = chn->driver->probe(pr, chn);
 
356
 
 
357
        chn->binary = FALSE;
 
358
        blkid_probe_chain_reset_position(chn);
 
359
 
 
360
        /* restore the original setting
 
361
         */
 
362
        pr->cur_chain = org_chn;
 
363
        pr->prob_flags = org_prob_flags;
 
364
 
 
365
        if (rc != 0)
 
366
                return NULL;
 
367
 
 
368
        DBG(DEBUG_LOWPROBE,
 
369
                printf("returning %s binary data\n", chn->driver->name));
 
370
        return chn->data;
 
371
}
 
372
 
 
373
 
 
374
/**
 
375
 * blkid_reset_probe:
 
376
 * @pr: probe
 
377
 *
 
378
 * Zeroize probing results and resets the current probing (this has impact to
 
379
 * blkid_do_probe() only). This function does not touch probing filters and
 
380
 * keeps assigned device.
 
381
 */
 
382
void blkid_reset_probe(blkid_probe pr)
 
383
{
 
384
        int i;
 
385
 
 
386
        if (!pr)
 
387
                return;
 
388
 
 
389
        blkid_probe_reset_vals(pr);
 
390
 
 
391
        pr->cur_chain = NULL;
 
392
 
 
393
        for (i = 0; i < BLKID_NCHAINS; i++)
 
394
                blkid_probe_chain_reset_position(&pr->chains[i]);
 
395
}
 
396
 
 
397
/***
 
398
static int blkid_probe_dump_filter(blkid_probe pr, int chain)
 
399
{
 
400
        struct blkid_chain *chn;
 
401
        int i;
 
402
 
 
403
        if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
 
404
                return -1;
 
405
 
 
406
        chn = &pr->chains[chain];
 
407
 
 
408
        if (!chn->fltr)
 
409
                return -1;
 
410
 
 
411
        for (i = 0; i < chn->driver->nidinfos; i++) {
 
412
                const struct blkid_idinfo *id = chn->driver->idinfos[i];
 
413
 
 
414
                DBG(DEBUG_LOWPROBE, printf("%d: %s: %s\n",
 
415
                        i,
 
416
                        id->name,
 
417
                        blkid_bmp_get_item(chn->fltr, i)
 
418
                                ? "disabled" : "enabled <--"));
 
419
        }
 
420
        return 0;
 
421
}
 
422
***/
 
423
 
 
424
/*
 
425
 * Returns properly initialized chain filter
 
426
 */
 
427
unsigned long *blkid_probe_get_filter(blkid_probe pr, int chain, int create)
 
428
{
 
429
        struct blkid_chain *chn;
 
430
 
 
431
        if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
 
432
                return NULL;
 
433
 
 
434
        chn = &pr->chains[chain];
 
435
 
 
436
        /* always when you touch the chain filter all indexes are reseted and
 
437
         * probing starts from scratch
 
438
         */
 
439
        blkid_probe_chain_reset_position(chn);
 
440
        pr->cur_chain = NULL;
 
441
 
 
442
        if (!chn->driver->has_fltr || (!chn->fltr && !create))
 
443
                return NULL;
 
444
 
 
445
        if (!chn->fltr)
 
446
                chn->fltr = calloc(1, blkid_bmp_nbytes(chn->driver->nidinfos));
 
447
        else
 
448
                memset(chn->fltr, 0, blkid_bmp_nbytes(chn->driver->nidinfos));
 
449
 
 
450
        /* blkid_probe_dump_filter(pr, chain); */
 
451
        return chn->fltr;
 
452
}
 
453
 
 
454
/*
 
455
 * Generic private functions for filter setting
 
456
 */
 
457
int __blkid_probe_invert_filter(blkid_probe pr, int chain)
 
458
{
 
459
        size_t i;
 
460
        struct blkid_chain *chn;
 
461
 
 
462
        chn = &pr->chains[chain];
 
463
 
 
464
        if (!chn->driver->has_fltr || !chn->fltr)
 
465
                return -1;
 
466
 
 
467
        for (i = 0; i < blkid_bmp_nwords(chn->driver->nidinfos); i++)
 
468
                chn->fltr[i] = ~chn->fltr[i];
 
469
 
 
470
        DBG(DEBUG_LOWPROBE, printf("probing filter inverted\n"));
 
471
        /* blkid_probe_dump_filter(pr, chain); */
 
472
        return 0;
 
473
}
 
474
 
 
475
int __blkid_probe_reset_filter(blkid_probe pr, int chain)
 
476
{
 
477
        return blkid_probe_get_filter(pr, chain, FALSE) ? 0 : -1;
 
478
}
 
479
 
 
480
int __blkid_probe_filter_types(blkid_probe pr, int chain, int flag, char *names[])
 
481
{
 
482
        unsigned long *fltr;
 
483
        struct blkid_chain *chn;
 
484
        size_t i;
 
485
 
 
486
        fltr = blkid_probe_get_filter(pr, chain, TRUE);
 
487
        if (!fltr)
 
488
                return -1;
 
489
 
 
490
        chn = &pr->chains[chain];
 
491
 
 
492
        for (i = 0; i < chn->driver->nidinfos; i++) {
 
493
                int has = 0;
 
494
                const struct blkid_idinfo *id = chn->driver->idinfos[i];
 
495
                char **n;
 
496
 
 
497
                for (n = names; *n; n++) {
 
498
                        if (!strcmp(id->name, *n)) {
 
499
                                has = 1;
 
500
                                break;
 
501
                        }
 
502
                }
 
503
                if (flag & BLKID_FLTR_ONLYIN) {
 
504
                       if (!has)
 
505
                                blkid_bmp_set_item(fltr, i);
 
506
                } else if (flag & BLKID_FLTR_NOTIN) {
 
507
                        if (has)
 
508
                                blkid_bmp_set_item(fltr, i);
 
509
                }
 
510
        }
 
511
 
 
512
        DBG(DEBUG_LOWPROBE,
 
513
                printf("%s: a new probing type-filter initialized\n",
 
514
                chn->driver->name));
 
515
        /* blkid_probe_dump_filter(pr, chain); */
 
516
        return 0;
 
517
}
 
518
 
 
519
unsigned char *blkid_probe_get_buffer(blkid_probe pr,
 
520
                                blkid_loff_t off, blkid_loff_t len)
 
521
{
 
522
        struct list_head *p;
 
523
        struct blkid_bufinfo *bf = NULL;
 
524
 
 
525
        if (pr->size <= 0)
 
526
                return NULL;
 
527
 
 
528
        if (pr->parent &&
 
529
            pr->parent->devno == pr->devno &&
 
530
            pr->parent->off <= pr->off &&
 
531
            pr->parent->off + pr->parent->size >= pr->off + pr->size) {
 
532
                /*
 
533
                 * This is a cloned prober and points to the same area as
 
534
                 * parent. Let's use parent's buffers.
 
535
                 *
 
536
                 * Note that pr->off (and pr->parent->off) is always from the
 
537
                 * beginig of the device.
 
538
                 */
 
539
                return blkid_probe_get_buffer(pr->parent,
 
540
                                pr->off + off - pr->parent->off, len);
 
541
        }
 
542
 
 
543
        list_for_each(p, &pr->buffers) {
 
544
                struct blkid_bufinfo *x =
 
545
                                list_entry(p, struct blkid_bufinfo, bufs);
 
546
 
 
547
                if (x->off <= off && off + len <= x->off + x->len) {
 
548
                        DBG(DEBUG_LOWPROBE,
 
549
                                printf("\treuse buffer: off=%jd len=%jd pr=%p\n",
 
550
                                                        x->off, x->len, pr));
 
551
                        bf = x;
 
552
                        break;
 
553
                }
 
554
        }
 
555
        if (!bf) {
 
556
                ssize_t ret;
 
557
 
 
558
                if (blkid_llseek(pr->fd, pr->off + off, SEEK_SET) < 0)
 
559
                        return NULL;
 
560
 
 
561
                /* allocate info and space for data by why call */
 
562
                bf = calloc(1, sizeof(struct blkid_bufinfo) + len);
 
563
                if (!bf)
 
564
                        return NULL;
 
565
 
 
566
                bf->data = ((unsigned char *) bf) + sizeof(struct blkid_bufinfo);
 
567
                bf->len = len;
 
568
                bf->off = off;
 
569
                INIT_LIST_HEAD(&bf->bufs);
 
570
 
 
571
                DBG(DEBUG_LOWPROBE,
 
572
                        printf("\tbuffer read: off=%jd len=%jd pr=%p\n",
 
573
                                off, len, pr));
 
574
 
 
575
                ret = read(pr->fd, bf->data, len);
 
576
                if (ret != (ssize_t) len) {
 
577
                        free(bf);
 
578
                        return NULL;
 
579
                }
 
580
                list_add_tail(&bf->bufs, &pr->buffers);
 
581
        }
 
582
 
 
583
        return off ? bf->data + (off - bf->off) : bf->data;
 
584
}
 
585
 
 
586
 
 
587
static void blkid_probe_reset_buffer(blkid_probe pr)
 
588
{
 
589
        uint64_t read_ct = 0, len_ct = 0;
 
590
 
 
591
        if (!pr || list_empty(&pr->buffers))
 
592
                return;
 
593
 
 
594
        DBG(DEBUG_LOWPROBE, printf("reseting probing buffers pr=%p\n", pr));
 
595
 
 
596
        while (!list_empty(&pr->buffers)) {
 
597
                struct blkid_bufinfo *bf = list_entry(pr->buffers.next,
 
598
                                                struct blkid_bufinfo, bufs);
 
599
                read_ct++;
 
600
                len_ct += bf->len;
 
601
                list_del(&bf->bufs);
 
602
                free(bf);
 
603
        }
 
604
 
 
605
        DBG(DEBUG_LOWPROBE,
 
606
                printf("buffers summary: %"PRIu64" bytes "
 
607
                        "by %"PRIu64" read() call(s)\n",
 
608
                        len_ct, read_ct));
 
609
 
 
610
        INIT_LIST_HEAD(&pr->buffers);
 
611
}
 
612
 
 
613
/*
 
614
 * Small devices need a special care.
 
615
 */
 
616
int blkid_probe_is_tiny(blkid_probe pr)
 
617
{
 
618
        return pr && (pr->flags & BLKID_FL_TINY_DEV);
 
619
}
 
620
 
 
621
/*
 
622
 * CDROMs may fail when probed for RAID (last sector problem)
 
623
 */
 
624
int blkid_probe_is_cdrom(blkid_probe pr)
 
625
{
 
626
        return pr && (pr->flags & BLKID_FL_CDROM_DEV);
 
627
}
 
628
 
 
629
/**
 
630
 * blkid_probe_set_device:
 
631
 * @pr: probe
 
632
 * @fd: device file descriptor
 
633
 * @off: begin of probing area
 
634
 * @size: size of probing area (zero means whole device/file)
 
635
 *
 
636
 * Assigns the device to probe control struct, resets internal buffers and
 
637
 * resets the current probing.
 
638
 *
 
639
 * Returns: -1 in case of failure, or 0 on success.
 
640
 */
 
641
int blkid_probe_set_device(blkid_probe pr, int fd,
 
642
                blkid_loff_t off, blkid_loff_t size)
 
643
{
 
644
        struct stat sb;
 
645
 
 
646
        if (!pr)
 
647
                return -1;
 
648
 
 
649
        blkid_reset_probe(pr);
 
650
        blkid_probe_reset_buffer(pr);
 
651
 
 
652
        if ((pr->flags & BLKID_FL_PRIVATE_FD) && pr->fd >= 0)
 
653
                close(pr->fd);
 
654
 
 
655
        pr->flags &= ~BLKID_FL_PRIVATE_FD;
 
656
        pr->flags &= ~BLKID_FL_TINY_DEV;
 
657
        pr->flags &= ~BLKID_FL_CDROM_DEV;
 
658
        pr->prob_flags = 0;
 
659
        pr->fd = fd;
 
660
        pr->off = off;
 
661
        pr->size = 0;
 
662
        pr->devno = 0;
 
663
        pr->disk_devno = 0;
 
664
        pr->mode = 0;
 
665
        pr->blkssz = 0;
 
666
        pr->wipe_off = 0;
 
667
        pr->wipe_size = 0;
 
668
        pr->wipe_chain = NULL;
 
669
 
 
670
#if defined(POSIX_FADV_RANDOM) && defined(HAVE_POSIX_FADVISE)
 
671
        /* Disable read-ahead */
 
672
        posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM);
 
673
#endif
 
674
        if (fstat(fd, &sb))
 
675
                goto err;
 
676
 
 
677
        if (!S_ISBLK(sb.st_mode) && !S_ISCHR(sb.st_mode) && !S_ISREG(sb.st_mode))
 
678
                goto err;
 
679
 
 
680
        pr->mode = sb.st_mode;
 
681
        if (S_ISBLK(sb.st_mode) || S_ISCHR(sb.st_mode))
 
682
                pr->devno = sb.st_rdev;
 
683
 
 
684
        if (size)
 
685
                pr->size = size;
 
686
        else {
 
687
                if (S_ISBLK(sb.st_mode)) {
 
688
                        if (blkdev_get_size(fd, (unsigned long long *) &pr->size)) {
 
689
                                DBG(DEBUG_LOWPROBE, printf(
 
690
                                        "failed to get device size\n"));
 
691
                                goto err;
 
692
                        }
 
693
                } else if (S_ISCHR(sb.st_mode))
 
694
                        pr->size = 1;           /* UBI devices are char... */
 
695
                else if (S_ISREG(sb.st_mode))
 
696
                        pr->size = sb.st_size;  /* regular file */
 
697
 
 
698
                if (pr->off > pr->size)
 
699
                        goto err;
 
700
 
 
701
                /* The probing area cannot be larger than whole device, pr->off
 
702
                 * is offset within the device */
 
703
                pr->size -= pr->off;
 
704
        }
 
705
 
 
706
        if (pr->size <= 1440 * 1024 && !S_ISCHR(sb.st_mode))
 
707
                pr->flags |= BLKID_FL_TINY_DEV;
 
708
 
 
709
#ifdef CDROM_GET_CAPABILITY
 
710
        if (S_ISBLK(sb.st_mode) && ioctl(fd, CDROM_GET_CAPABILITY, NULL) >= 0)
 
711
                pr->flags |= BLKID_FL_CDROM_DEV;
 
712
#endif
 
713
 
 
714
        DBG(DEBUG_LOWPROBE, printf("ready for low-probing, offset=%jd, size=%jd\n",
 
715
                                pr->off, pr->size));
 
716
        DBG(DEBUG_LOWPROBE, printf("whole-disk: %s, regfile: %s\n",
 
717
                blkid_probe_is_wholedisk(pr) ?"YES" : "NO",
 
718
                S_ISREG(pr->mode) ? "YES" : "NO"));
 
719
 
 
720
        return 0;
 
721
err:
 
722
        DBG(DEBUG_LOWPROBE,
 
723
                printf("failed to prepare a device for low-probing\n"));
 
724
        return -1;
 
725
 
 
726
}
 
727
 
 
728
int blkid_probe_get_dimension(blkid_probe pr,
 
729
                blkid_loff_t *off, blkid_loff_t *size)
 
730
{
 
731
        if (!pr)
 
732
                return -1;
 
733
 
 
734
        *off = pr->off;
 
735
        *size = pr->size;
 
736
        return 0;
 
737
}
 
738
 
 
739
int blkid_probe_set_dimension(blkid_probe pr,
 
740
                blkid_loff_t off, blkid_loff_t size)
 
741
{
 
742
        if (!pr)
 
743
                return -1;
 
744
 
 
745
        DBG(DEBUG_LOWPROBE, printf(
 
746
                "changing probing area pr=%p: size=%llu, off=%llu "
 
747
                "-to-> size=%llu, off=%llu\n",
 
748
                pr,
 
749
                (unsigned long long) pr->size,
 
750
                (unsigned long long) pr->off,
 
751
                (unsigned long long) size,
 
752
                (unsigned long long) off));
 
753
 
 
754
        pr->off = off;
 
755
        pr->size = size;
 
756
        pr->flags &= ~BLKID_FL_TINY_DEV;
 
757
 
 
758
        if (pr->size <= 1440 * 1024 && !S_ISCHR(pr->mode))
 
759
                pr->flags |= BLKID_FL_TINY_DEV;
 
760
 
 
761
        blkid_probe_reset_buffer(pr);
 
762
 
 
763
        return 0;
 
764
}
 
765
 
 
766
int blkid_probe_get_idmag(blkid_probe pr, const struct blkid_idinfo *id,
 
767
                        blkid_loff_t *offset, const struct blkid_idmag **res)
 
768
{
 
769
        const struct blkid_idmag *mag = NULL;
 
770
        blkid_loff_t off = 0;
 
771
 
 
772
        if (id)
 
773
                mag = id->magics ? &id->magics[0] : NULL;
 
774
        if (res)
 
775
                *res = NULL;
 
776
 
 
777
        /* try to detect by magic string */
 
778
        while(mag && mag->magic) {
 
779
                unsigned char *buf;
 
780
 
 
781
                off = (mag->kboff + (mag->sboff >> 10)) << 10;
 
782
                buf = blkid_probe_get_buffer(pr, off, 1024);
 
783
 
 
784
                if (buf && !memcmp(mag->magic,
 
785
                                buf + (mag->sboff & 0x3ff), mag->len)) {
 
786
                        DBG(DEBUG_LOWPROBE, printf(
 
787
                                "\tmagic sboff=%u, kboff=%ld\n",
 
788
                                mag->sboff, mag->kboff));
 
789
                        if (offset)
 
790
                                *offset = off + (mag->sboff & 0x3ff);
 
791
                        if (res)
 
792
                                *res = mag;
 
793
                        return 0;
 
794
                }
 
795
                mag++;
 
796
        }
 
797
 
 
798
        if (id->magics && id->magics[0].magic)
 
799
                /* magic string(s) defined, but not found */
 
800
                return 1;
 
801
 
 
802
        return 0;
 
803
}
 
804
 
 
805
static inline void blkid_probe_start(blkid_probe pr)
 
806
{
 
807
        if (pr) {
 
808
                pr->cur_chain = NULL;
 
809
                pr->prob_flags = 0;
 
810
                blkid_probe_set_wiper(pr, 0, 0);
 
811
        }
 
812
}
 
813
 
 
814
static inline void blkid_probe_end(blkid_probe pr)
 
815
{
 
816
        if (pr) {
 
817
                pr->cur_chain = NULL;
 
818
                pr->prob_flags = 0;
 
819
                blkid_probe_set_wiper(pr, 0, 0);
 
820
        }
 
821
}
 
822
 
 
823
/**
 
824
 * blkid_do_probe:
 
825
 * @pr: prober
 
826
 *
 
827
 * Calls probing functions in all enabled chains. The superblocks chain is
 
828
 * enabled by default. The blkid_do_probe() stores result from only one
 
829
 * probing function. It's necessary to call this routine in a loop to get
 
830
 * results from all probing functions in all chains. The probing is reseted
 
831
 * by blkid_reset_probe() or by filter functions.
 
832
 *
 
833
 * This is string-based NAME=value interface only.
 
834
 *
 
835
 * <example>
 
836
 *   <title>basic case - use the first result only</title>
 
837
 *   <programlisting>
 
838
 *
 
839
 *      if (blkid_do_probe(pr) == 0) {
 
840
 *              int nvals = blkid_probe_numof_values(pr);
 
841
 *              for (n = 0; n < nvals; n++) {
 
842
 *                      if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
 
843
 *                              printf("%s = %s\n", name, data);
 
844
 *              }
 
845
 *      }
 
846
 *  </programlisting>
 
847
 * </example>
 
848
 *
 
849
 * <example>
 
850
 *   <title>advanced case - probe for all signatures</title>
 
851
 *   <programlisting>
 
852
 *
 
853
 *      while (blkid_do_probe(pr) == 0) {
 
854
 *              int nvals = blkid_probe_numof_values(pr);
 
855
 *              ...
 
856
 *      }
 
857
 *  </programlisting>
 
858
 * </example>
 
859
 *
 
860
 * See also blkid_reset_probe().
 
861
 *
 
862
 * Returns: 0 on success, 1 when probing is done and -1 in case of error.
 
863
 */
 
864
int blkid_do_probe(blkid_probe pr)
 
865
{
 
866
        int rc = 1;
 
867
 
 
868
        if (!pr)
 
869
                return -1;
 
870
 
 
871
        do {
 
872
                struct blkid_chain *chn = pr->cur_chain;
 
873
 
 
874
                if (!chn) {
 
875
                        blkid_probe_start(pr);
 
876
                        chn = pr->cur_chain = &pr->chains[0];
 
877
                }
 
878
                /* we go to the next chain only when the previous probing
 
879
                 * result was nothing (rc == 1) and when the current chain is
 
880
                 * disabled or we are at end of the current chain (chain->idx +
 
881
                 * 1 == sizeof chain) or the current chain bailed out right at
 
882
                 * the start (chain->idx == -1)
 
883
                 */
 
884
                else if (rc == 1 && (chn->enabled == FALSE ||
 
885
                                     chn->idx + 1 == (int) chn->driver->nidinfos ||
 
886
                                     chn->idx == -1)) {
 
887
 
 
888
                        size_t idx = chn->driver->id + 1;
 
889
 
 
890
                        if (idx < BLKID_NCHAINS)
 
891
                                chn = pr->cur_chain = &pr->chains[idx];
 
892
                        else {
 
893
                                blkid_probe_end(pr);
 
894
                                return 1;       /* all chains already probed */
 
895
                        }
 
896
                }
 
897
 
 
898
                chn->binary = FALSE;            /* for sure... */
 
899
 
 
900
                DBG(DEBUG_LOWPROBE, printf("chain probe %s %s (idx=%d)\n",
 
901
                                chn->driver->name,
 
902
                                chn->enabled? "ENABLED" : "DISABLED",
 
903
                                chn->idx));
 
904
 
 
905
                if (!chn->enabled)
 
906
                        continue;
 
907
 
 
908
                /* rc: -1 = error, 0 = success, 1 = no result */
 
909
                rc = chn->driver->probe(pr, chn);
 
910
 
 
911
        } while (rc == 1);
 
912
 
 
913
        return rc;
 
914
}
 
915
 
 
916
/**
 
917
 * blkid_do_safeprobe:
 
918
 * @pr: prober
 
919
 *
 
920
 * This function gathers probing results from all enabled chains and checks
 
921
 * for ambivalent results (e.g. more filesystems on the device).
 
922
 *
 
923
 * This is string-based NAME=value interface only.
 
924
 *
 
925
 * Note about suberblocks chain -- the function does not check for filesystems
 
926
 * when a RAID signature is detected.  The function also does not check for
 
927
 * collision between RAIDs. The first detected RAID is returned. The function
 
928
 * checks for collision between partition table and RAID signature -- it's
 
929
 * recommended to enable partitions chain together with superblocks chain.
 
930
 *
 
931
 * Returns: 0 on success, 1 if nothing is detected, -2 if ambivalen result is
 
932
 * detected and -1 on case of error.
 
933
 */
 
934
int blkid_do_safeprobe(blkid_probe pr)
 
935
{
 
936
        int i, count = 0, rc = 0;
 
937
 
 
938
        if (!pr)
 
939
                return -1;
 
940
 
 
941
        blkid_probe_start(pr);
 
942
 
 
943
        for (i = 0; i < BLKID_NCHAINS; i++) {
 
944
                struct blkid_chain *chn;
 
945
 
 
946
                chn = pr->cur_chain = &pr->chains[i];
 
947
                chn->binary = FALSE;            /* for sure... */
 
948
 
 
949
                DBG(DEBUG_LOWPROBE, printf("chain safeprobe %s %s\n",
 
950
                                chn->driver->name,
 
951
                                chn->enabled? "ENABLED" : "DISABLED"));
 
952
 
 
953
                if (!chn->enabled)
 
954
                        continue;
 
955
 
 
956
                blkid_probe_chain_reset_position(chn);
 
957
 
 
958
                rc = chn->driver->safeprobe(pr, chn);
 
959
 
 
960
                blkid_probe_chain_reset_position(chn);
 
961
 
 
962
                /* rc: -2 ambivalent, -1 = error, 0 = success, 1 = no result */
 
963
                if (rc < 0)
 
964
                        goto done;      /* error */
 
965
                if (rc == 0)
 
966
                        count++;        /* success */
 
967
        }
 
968
 
 
969
done:
 
970
        blkid_probe_end(pr);
 
971
        if (rc < 0)
 
972
                return rc;
 
973
        return count ? 0 : 1;
 
974
}
 
975
 
 
976
/**
 
977
 * blkid_do_fullprobe:
 
978
 * @pr: prober
 
979
 *
 
980
 * This function gathers probing results from all enabled chains. Same as
 
981
 * blkid_do_safeprobe() but does not check for collision between probing
 
982
 * result.
 
983
 *
 
984
 * This is string-based NAME=value interface only.
 
985
 *
 
986
 * Returns: 0 on success, 1 if nothing is detected or -1 on case of error.
 
987
 */
 
988
int blkid_do_fullprobe(blkid_probe pr)
 
989
{
 
990
        int i, count = 0, rc = 0;
 
991
 
 
992
        if (!pr)
 
993
                return -1;
 
994
 
 
995
        blkid_probe_start(pr);
 
996
 
 
997
        for (i = 0; i < BLKID_NCHAINS; i++) {
 
998
                int rc;
 
999
                struct blkid_chain *chn;
 
1000
 
 
1001
                chn = pr->cur_chain = &pr->chains[i];
 
1002
                chn->binary = FALSE;            /* for sure... */
 
1003
 
 
1004
                DBG(DEBUG_LOWPROBE, printf("chain fullprobe %s: %s\n",
 
1005
                                chn->driver->name,
 
1006
                                chn->enabled? "ENABLED" : "DISABLED"));
 
1007
 
 
1008
                if (!chn->enabled)
 
1009
                        continue;
 
1010
 
 
1011
                blkid_probe_chain_reset_position(chn);
 
1012
 
 
1013
                rc = chn->driver->probe(pr, chn);
 
1014
 
 
1015
                blkid_probe_chain_reset_position(chn);
 
1016
 
 
1017
                /* rc: -1 = error, 0 = success, 1 = no result */
 
1018
                if (rc < 0)
 
1019
                        goto done;      /* error */
 
1020
                if (rc == 0)
 
1021
                        count++;        /* success */
 
1022
        }
 
1023
 
 
1024
done:
 
1025
        blkid_probe_end(pr);
 
1026
        if (rc < 0)
 
1027
                return rc;
 
1028
        return count ? 0 : 1;
 
1029
}
 
1030
 
 
1031
/* same sa blkid_probe_get_buffer() but works with 512-sectors */
 
1032
unsigned char *blkid_probe_get_sector(blkid_probe pr, unsigned int sector)
 
1033
{
 
1034
        return pr ? blkid_probe_get_buffer(pr,
 
1035
                        ((blkid_loff_t) sector) << 9, 0x200) : NULL;
 
1036
}
 
1037
 
 
1038
struct blkid_prval *blkid_probe_assign_value(
 
1039
                        blkid_probe pr, const char *name)
 
1040
{
 
1041
        struct blkid_prval *v;
 
1042
 
 
1043
        if (!name)
 
1044
                return NULL;
 
1045
        if (pr->nvals >= BLKID_NVALS)
 
1046
                return NULL;
 
1047
 
 
1048
        v = &pr->vals[pr->nvals];
 
1049
        v->name = name;
 
1050
        v->chain = pr->cur_chain;
 
1051
        pr->nvals++;
 
1052
 
 
1053
        DBG(DEBUG_LOWPROBE,
 
1054
                printf("assigning %s [%s]\n", name, v->chain->driver->name));
 
1055
        return v;
 
1056
}
 
1057
 
 
1058
int blkid_probe_reset_last_value(blkid_probe pr)
 
1059
{
 
1060
        struct blkid_prval *v;
 
1061
 
 
1062
        if (pr == NULL || pr->nvals == 0)
 
1063
                return -1;
 
1064
 
 
1065
        v = &pr->vals[pr->nvals - 1];
 
1066
 
 
1067
        DBG(DEBUG_LOWPROBE,
 
1068
                printf("un-assigning %s [%s]\n", v->name, v->chain->driver->name));
 
1069
 
 
1070
        memset(v, 0, sizeof(struct blkid_prval));
 
1071
        pr->nvals--;
 
1072
 
 
1073
        return 0;
 
1074
 
 
1075
}
 
1076
 
 
1077
int blkid_probe_set_value(blkid_probe pr, const char *name,
 
1078
                unsigned char *data, size_t len)
 
1079
{
 
1080
        struct blkid_prval *v;
 
1081
 
 
1082
        if (len > BLKID_PROBVAL_BUFSIZ)
 
1083
                len = BLKID_PROBVAL_BUFSIZ;
 
1084
 
 
1085
        v = blkid_probe_assign_value(pr, name);
 
1086
        if (!v)
 
1087
                return -1;
 
1088
 
 
1089
        memcpy(v->data, data, len);
 
1090
        v->len = len;
 
1091
        return 0;
 
1092
}
 
1093
 
 
1094
int blkid_probe_vsprintf_value(blkid_probe pr, const char *name,
 
1095
                const char *fmt, va_list ap)
 
1096
{
 
1097
        struct blkid_prval *v;
 
1098
        size_t len;
 
1099
 
 
1100
        v = blkid_probe_assign_value(pr, name);
 
1101
        if (!v)
 
1102
                return -1;
 
1103
 
 
1104
        len = vsnprintf((char *) v->data, sizeof(v->data), fmt, ap);
 
1105
 
 
1106
        if (len <= 0) {
 
1107
                blkid_probe_reset_last_value(pr);
 
1108
                return -1;
 
1109
        }
 
1110
        v->len = len + 1;
 
1111
        return 0;
 
1112
}
 
1113
 
 
1114
int blkid_probe_sprintf_value(blkid_probe pr, const char *name,
 
1115
                const char *fmt, ...)
 
1116
{
 
1117
        int rc;
 
1118
        va_list ap;
 
1119
 
 
1120
        va_start(ap, fmt);
 
1121
        rc = blkid_probe_vsprintf_value(pr, name, fmt, ap);
 
1122
        va_end(ap);
 
1123
 
 
1124
        return rc;
 
1125
}
 
1126
 
 
1127
/**
 
1128
 * blkid_probe_get_devno:
 
1129
 * @pr: probe
 
1130
 *
 
1131
 * Returns: block device number, or 0 for regilar files.
 
1132
 */
 
1133
dev_t blkid_probe_get_devno(blkid_probe pr)
 
1134
{
 
1135
        return pr->devno;
 
1136
}
 
1137
 
 
1138
/**
 
1139
 * blkid_probe_get_wholedisk_devno:
 
1140
 * @pr: probe
 
1141
 *
 
1142
 * Returns: device number of the wholedisk, or 0 for regilar files.
 
1143
 */
 
1144
dev_t blkid_probe_get_wholedisk_devno(blkid_probe pr)
 
1145
{
 
1146
        if (!pr->disk_devno) {
 
1147
                dev_t devno, disk_devno = 0;
 
1148
 
 
1149
                devno = blkid_probe_get_devno(pr);
 
1150
                if (!devno)
 
1151
                        return 0;
 
1152
 
 
1153
                 if (blkid_devno_to_wholedisk(devno, NULL, 0, &disk_devno) == 0)
 
1154
                        pr->disk_devno = disk_devno;
 
1155
        }
 
1156
        return pr->disk_devno;
 
1157
}
 
1158
 
 
1159
/**
 
1160
 * blkid_probe_is_wholedisk:
 
1161
 * @pr: probe
 
1162
 *
 
1163
 * Returns: 1 if the device is whole-disk or 0.
 
1164
 */
 
1165
int blkid_probe_is_wholedisk(blkid_probe pr)
 
1166
{
 
1167
        dev_t devno, disk_devno;
 
1168
 
 
1169
        devno = blkid_probe_get_devno(pr);
 
1170
        if (!devno)
 
1171
                return 0;
 
1172
 
 
1173
        disk_devno = blkid_probe_get_wholedisk_devno(pr);
 
1174
        if (!disk_devno)
 
1175
                return 0;
 
1176
 
 
1177
        return devno == disk_devno;
 
1178
}
 
1179
 
 
1180
blkid_probe blkid_probe_get_wholedisk_probe(blkid_probe pr)
 
1181
{
 
1182
        dev_t disk;
 
1183
 
 
1184
        if (blkid_probe_is_wholedisk(pr))
 
1185
                return NULL;                    /* this is not partition */
 
1186
 
 
1187
        if (pr->parent)
 
1188
                /* this is cloned blkid_probe, use parent's stuff */
 
1189
                return blkid_probe_get_wholedisk_probe(pr->parent);
 
1190
 
 
1191
        disk = blkid_probe_get_wholedisk_devno(pr);
 
1192
 
 
1193
        if (pr->disk_probe && pr->disk_probe->devno != disk) {
 
1194
                /* we have disk prober, but for another disk... close it */
 
1195
                blkid_free_probe(pr->disk_probe);
 
1196
                pr->disk_probe = NULL;
 
1197
        }
 
1198
 
 
1199
        if (!pr->disk_probe) {
 
1200
                /* Open a new disk prober */
 
1201
                char *disk_path = blkid_devno_to_devname(disk);
 
1202
 
 
1203
                if (!disk_path)
 
1204
                        return NULL;
 
1205
 
 
1206
                DBG(DEBUG_LOWPROBE, printf("allocate a wholedisk probe\n"));
 
1207
 
 
1208
                pr->disk_probe = blkid_new_probe_from_filename(disk_path);
 
1209
                if (!pr->disk_probe)
 
1210
                        return NULL;    /* ENOMEM? */
 
1211
        }
 
1212
 
 
1213
        return pr->disk_probe;
 
1214
}
 
1215
 
 
1216
/**
 
1217
 * blkid_probe_get_size:
 
1218
 * @pr: probe
 
1219
 *
 
1220
 * This function returns size of probing area as defined by blkid_probe_set_device().
 
1221
 * If the size of the probing area is unrestricted then this function returns
 
1222
 * the real size of device. See also blkid_get_dev_size().
 
1223
 *
 
1224
 * Returns: size in bytes or -1 in case of error.
 
1225
 */
 
1226
blkid_loff_t blkid_probe_get_size(blkid_probe pr)
 
1227
{
 
1228
        return pr ? pr->size : -1;
 
1229
}
 
1230
 
 
1231
/**
 
1232
 * blkid_probe_get_offset:
 
1233
 * @pr: probe
 
1234
 *
 
1235
 * This function returns offset of probing area as defined by blkid_probe_set_device().
 
1236
 *
 
1237
 * Returns: offset in bytes or -1 in case of error.
 
1238
 */
 
1239
blkid_loff_t blkid_probe_get_offset(blkid_probe pr)
 
1240
{
 
1241
        return pr ? pr->off : -1;
 
1242
}
 
1243
 
 
1244
/**
 
1245
 * blkid_probe_get_fd:
 
1246
 * @pr: probe
 
1247
 *
 
1248
 * Returns: file descriptor for assigned device/file.
 
1249
 */
 
1250
int blkid_probe_get_fd(blkid_probe pr)
 
1251
{
 
1252
        return pr ? pr->fd : -1;
 
1253
}
 
1254
 
 
1255
/**
 
1256
 * blkid_probe_get_sectorsize:
 
1257
 * @pr: probe or NULL (for NULL returns 512)
 
1258
 *
 
1259
 * Returns: block device logical sector size (BLKSSZGET ioctl, default 512).
 
1260
 */
 
1261
unsigned int blkid_probe_get_sectorsize(blkid_probe pr)
 
1262
{
 
1263
        if (!pr)
 
1264
                return DEFAULT_SECTOR_SIZE;  /*... and good luck! */
 
1265
 
 
1266
        if (pr->blkssz)
 
1267
                return pr->blkssz;
 
1268
 
 
1269
        if (S_ISBLK(pr->mode) &&
 
1270
            blkdev_get_sector_size(pr->fd, (int *) &pr->blkssz) == 0)
 
1271
                return pr->blkssz;
 
1272
 
 
1273
        pr->blkssz = DEFAULT_SECTOR_SIZE;
 
1274
        return pr->blkssz;
 
1275
}
 
1276
 
 
1277
/**
 
1278
 * blkid_probe_get_sectors:
 
1279
 * @pr: probe
 
1280
 *
 
1281
 * Returns: 512-byte sector count or -1 in case of error.
 
1282
 */
 
1283
blkid_loff_t blkid_probe_get_sectors(blkid_probe pr)
 
1284
{
 
1285
        return pr ? pr->size >> 9 : -1;
 
1286
}
 
1287
 
 
1288
/**
 
1289
 * blkid_probe_numof_values:
 
1290
 * @pr: probe
 
1291
 *
 
1292
 * Returns: number of values in probing result or -1 in case of error.
 
1293
 */
 
1294
int blkid_probe_numof_values(blkid_probe pr)
 
1295
{
 
1296
        if (!pr)
 
1297
                return -1;
 
1298
        return pr->nvals;
 
1299
}
 
1300
 
 
1301
/**
 
1302
 * blkid_probe_get_value:
 
1303
 * @pr: probe
 
1304
 * @num: wanted value in range 0..N, where N is blkid_probe_numof_values() - 1
 
1305
 * @name: pointer to return value name or NULL
 
1306
 * @data: pointer to return value data or NULL
 
1307
 * @len: pointer to return value length or NULL
 
1308
 *
 
1309
 * Note, the @len returns length of the @data, including the terminating
 
1310
 * '\0' character.
 
1311
 *
 
1312
 * Returns: 0 on success, or -1 in case of error.
 
1313
 */
 
1314
int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
 
1315
                        const char **data, size_t *len)
 
1316
{
 
1317
        struct blkid_prval *v = __blkid_probe_get_value(pr, num);
 
1318
 
 
1319
        if (!v)
 
1320
                return -1;
 
1321
        if (name)
 
1322
                *name = v->name;
 
1323
        if (data)
 
1324
                *data = (char *) v->data;
 
1325
        if (len)
 
1326
                *len = v->len;
 
1327
 
 
1328
        DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
 
1329
        return 0;
 
1330
}
 
1331
 
 
1332
/**
 
1333
 * blkid_probe_lookup_value:
 
1334
 * @pr: probe
 
1335
 * @name: name of value
 
1336
 * @data: pointer to return value data or NULL
 
1337
 * @len: pointer to return value length or NULL
 
1338
 *
 
1339
 * Note, the @len returns length of the @data, including the terminating
 
1340
 * '\0' character.
 
1341
 *
 
1342
 * Returns: 0 on success, or -1 in case of error.
 
1343
 */
 
1344
int blkid_probe_lookup_value(blkid_probe pr, const char *name,
 
1345
                        const char **data, size_t *len)
 
1346
{
 
1347
        struct blkid_prval *v = __blkid_probe_lookup_value(pr, name);
 
1348
 
 
1349
        if (!v)
 
1350
                return -1;
 
1351
        if (data)
 
1352
                *data = (char *) v->data;
 
1353
        if (len)
 
1354
                *len = v->len;
 
1355
        return 0;
 
1356
}
 
1357
 
 
1358
/**
 
1359
 * blkid_probe_has_value:
 
1360
 * @pr: probe
 
1361
 * @name: name of value
 
1362
 *
 
1363
 * Returns: 1 if value exist in probing result, otherwise 0.
 
1364
 */
 
1365
int blkid_probe_has_value(blkid_probe pr, const char *name)
 
1366
{
 
1367
        if (blkid_probe_lookup_value(pr, name, NULL, NULL) == 0)
 
1368
                return 1;
 
1369
        return 0;
 
1370
}
 
1371
 
 
1372
struct blkid_prval *__blkid_probe_get_value(blkid_probe pr, int num)
 
1373
{
 
1374
        if (pr == NULL || num < 0 || num >= pr->nvals)
 
1375
                return NULL;
 
1376
 
 
1377
        return &pr->vals[num];
 
1378
}
 
1379
 
 
1380
struct blkid_prval *__blkid_probe_lookup_value(blkid_probe pr, const char *name)
 
1381
{
 
1382
        int i;
 
1383
 
 
1384
        if (pr == NULL || pr->nvals == 0 || name == NULL)
 
1385
                return NULL;
 
1386
 
 
1387
        for (i = 0; i < pr->nvals; i++) {
 
1388
                struct blkid_prval *v = &pr->vals[i];
 
1389
 
 
1390
                if (v->name && strcmp(name, v->name) == 0) {
 
1391
                        DBG(DEBUG_LOWPROBE, printf("returning %s value\n", v->name));
 
1392
                        return v;
 
1393
                }
 
1394
        }
 
1395
        return NULL;
 
1396
}
 
1397
 
 
1398
 
 
1399
/* converts DCE UUID (uuid[16]) to human readable string
 
1400
 * - the @len should be always 37 */
 
1401
#ifdef HAVE_LIBUUID
 
1402
void blkid_unparse_uuid(const unsigned char *uuid, char *str,
 
1403
                        size_t len __attribute__((__unused__)))
 
1404
{
 
1405
        uuid_unparse(uuid, str);
 
1406
}
 
1407
#else
 
1408
void blkid_unparse_uuid(const unsigned char *uuid, char *str, size_t len)
 
1409
{
 
1410
        snprintf(str, len,
 
1411
                "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
 
1412
                uuid[0], uuid[1], uuid[2], uuid[3],
 
1413
                uuid[4], uuid[5],
 
1414
                uuid[6], uuid[7],
 
1415
                uuid[8], uuid[9],
 
1416
                uuid[10], uuid[11], uuid[12], uuid[13], uuid[14],uuid[15]);
 
1417
}
 
1418
#endif
 
1419
 
 
1420
 
 
1421
/* Removes whitespace from the right-hand side of a string (trailing
 
1422
 * whitespace).
 
1423
 *
 
1424
 * Returns size of the new string (without \0).
 
1425
 */
 
1426
size_t blkid_rtrim_whitespace(unsigned char *str)
 
1427
{
 
1428
        size_t i = strlen((char *) str);
 
1429
 
 
1430
        while (i--) {
 
1431
                if (!isspace(str[i]))
 
1432
                        break;
 
1433
        }
 
1434
        str[++i] = '\0';
 
1435
        return i;
 
1436
}
 
1437
 
 
1438
/*
 
1439
 * Some mkfs-like utils wipe some parts (usually begin) of the device.
 
1440
 * For example LVM (pvcreate) or mkswap(8). This information could be used
 
1441
 * for later resolution to conflicts between superblocks.
 
1442
 *
 
1443
 * For example we found valid LVM superblock, LVM wipes 8KiB at the begin of
 
1444
 * the device. If we found another signature (for example MBR) this wiped area
 
1445
 * then the signature has been added later and LVM superblock should be ignore.
 
1446
 *
 
1447
 * Note that this heuristic is not 100% reliable, for example "pvcreate --zero
 
1448
 * n" allows to keep the begin of the device unmodified. It's probably better
 
1449
 * to use this heuristic for conflicts between superblocks and partition tables
 
1450
 * than for conflicts between filesystem superblocks -- existence of unwanted
 
1451
 * partition table is very unusual, because PT is pretty visible (parsed and
 
1452
 * interpreted by kernel).
 
1453
 */
 
1454
void blkid_probe_set_wiper(blkid_probe pr, blkid_loff_t off, blkid_loff_t size)
 
1455
{
 
1456
        struct blkid_chain *chn;
 
1457
 
 
1458
        if (!pr)
 
1459
                return;
 
1460
 
 
1461
        if (!size) {
 
1462
                DBG(DEBUG_LOWPROBE, printf("zeroize wiper\n"));
 
1463
                pr->wipe_size = pr->wipe_off = 0;
 
1464
                pr->wipe_chain = NULL;
 
1465
                return;
 
1466
        }
 
1467
 
 
1468
        chn = pr->cur_chain;
 
1469
 
 
1470
        if (!chn || !chn->driver ||
 
1471
            chn->idx < 0 || (size_t) chn->idx >= chn->driver->nidinfos)
 
1472
                return;
 
1473
 
 
1474
        pr->wipe_size = size;
 
1475
        pr->wipe_off = off;
 
1476
        pr->wipe_chain = chn;
 
1477
 
 
1478
        DBG(DEBUG_LOWPROBE,
 
1479
                printf("wiper set to %s::%s off=%jd size=%jd\n",
 
1480
                        chn->driver->name,
 
1481
                        chn->driver->idinfos[chn->idx]->name,
 
1482
                        pr->wipe_off, pr->wipe_size));
 
1483
        return;
 
1484
}
 
1485
 
 
1486
/*
 
1487
 * Returns 1 if the <@off,@size> area was wiped
 
1488
 */
 
1489
int blkid_probe_is_wiped(blkid_probe pr, struct blkid_chain **chn,
 
1490
                     blkid_loff_t off, blkid_loff_t size)
 
1491
{
 
1492
        if (!pr || !size)
 
1493
                return 0;
 
1494
 
 
1495
        if (pr->wipe_off <= off && off + size <= pr->wipe_off + pr->wipe_size) {
 
1496
                if (chn)
 
1497
                        *chn = pr->wipe_chain;
 
1498
                return 1;
 
1499
        }
 
1500
        return 0;
 
1501
}
 
1502
 
 
1503
void blkid_probe_use_wiper(blkid_probe pr, blkid_loff_t off, blkid_loff_t size)
 
1504
{
 
1505
        struct blkid_chain *chn = NULL;
 
1506
 
 
1507
        if (blkid_probe_is_wiped(pr, &chn, off, size) && chn) {
 
1508
                DBG(DEBUG_LOWPROBE, printf("wiped area detected -- ignore previous results\n"));
 
1509
                blkid_probe_set_wiper(pr, 0, 0);
 
1510
                blkid_probe_chain_reset_vals(pr, chn);
 
1511
        }
 
1512
}
 
1513