2 * Low-level libblkid probing API
4 * Copyright (C) 2008-2009 Karel Zak <kzak@redhat.com>
6 * This file may be redistributed under the terms of the
7 * GNU Lesser General Public License.
12 * @title: Low-level probing
13 * @short_description: low-level prober initialization
15 * The low-level probing routines always and directly read information from
16 * the selected (see blkid_probe_set_device()) device.
18 * The probing routines are grouped together into separate chains. Currently,
19 * the librray provides superblocks, partitions and topology chains.
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. For more details see the chain specific
26 * The low-level API provides two ways how access to probing results.
28 * 1. The NAME=value (tag) interface. This interface is older and returns all data
29 * as strings. This interface is generic for all chains.
31 * 2. The binary interfaces. These interfaces return data in the native formats.
32 * The interface is always specific to the probing chain.
36 * SECTION: lowprobe-tags
37 * @title: Low-level tags
38 * @short_description: generic NAME=value interface.
40 * The probing routines inside the chain are mutually exclusive by default --
41 * only few probing routines are marked as "tolerant". The "tolerant" probing
42 * routines are used for filesystem which can share the same device with any
43 * other filesystem. The blkid_do_safeprobe() checks for the "tolerant" flag.
45 * The SUPERBLOCKS chain is enabled by default. The all others chains is
46 * necessary to enable by blkid_probe_enable_'CHAINNAME'(). See chains specific
49 * The blkid_do_probe() function returns a result from only one probing
50 * routine, and the next call from the next probing routine. It means you need
51 * to call the function in loop, for example:
55 * while((blkid_do_probe(pr) == 0)
60 * The blkid_do_safeprobe() is the same as blkid_do_probe(), but returns only
61 * first probing result for every enabled chain. This function checks for
62 * ambivalent results (e.g. more "intolerant" filesystems superblocks on the
65 * The probing result is set of NAME=value pairs (the NAME is always unique).
74 #include <sys/types.h>
75 #ifdef HAVE_SYS_STAT_H
78 #ifdef HAVE_SYS_MKDEV_H
79 #include <sys/mkdev.h>
88 # ifdef HAVE_UUID_UUID_H
89 # include <uuid/uuid.h>
99 extern const struct blkid_chaindrv superblocks_drv
;
102 * All supported chains
104 static const struct blkid_chaindrv
*chains_drvs
[] = {
105 [BLKID_CHAIN_SUBLKS
] = &superblocks_drv
,
108 static void blkid_probe_reset_vals(blkid_probe pr
);
113 * Returns: a pointer to the newly allocated probe struct.
115 blkid_probe
blkid_new_probe(void)
121 pr
= calloc(1, sizeof(struct blkid_struct_probe
));
125 /* initialize chains */
126 for (i
= 0; i
< BLKID_NCHAINS
; i
++) {
127 pr
->chains
[i
].driver
= chains_drvs
[i
];
128 pr
->chains
[i
].flags
= chains_drvs
[i
]->dflt_flags
;
129 pr
->chains
[i
].enabled
= chains_drvs
[i
]->dflt_enabled
;
138 * Deallocates the probe struct, buffers and all allocated
139 * data that are associated with this probing control struct.
141 void blkid_free_probe(blkid_probe pr
)
148 for (i
= 0; i
< BLKID_NCHAINS
; i
++) {
149 struct blkid_chain
*ch
= &pr
->chains
[i
];
151 if (ch
->driver
->free_data
)
152 ch
->driver
->free_data(pr
, ch
->data
);
160 static void blkid_probe_reset_buffer(blkid_probe pr
)
162 DBG(DEBUG_LOWPROBE
, printf("reseting blkid probe buffer\n"));
164 memset(pr
->buf
, 0, pr
->buf_max
);
168 memset(pr
->sbbuf
, 0, BLKID_SB_BUFSIZ
);
174 * Removes chain values from probing result.
176 void blkid_probe_chain_reset_vals(blkid_probe pr
, struct blkid_chain
*chn
)
178 int nvals
= pr
->nvals
;
181 for (x
= 0, i
= 0; i
< pr
->nvals
; i
++) {
182 struct blkid_prval
*v
= &pr
->vals
[i
];
184 if (v
->chain
!= chn
&& x
== i
) {
188 if (v
->chain
== chn
) {
192 memcpy(&pr
->vals
[x
++], v
, sizeof(struct blkid_prval
));
198 * Copies chain values from probing result to @vals, the max size of @vals is
199 * @nvals and returns real number of values.
201 int blkid_probe_chain_copy_vals(blkid_probe pr
, struct blkid_chain
*chn
,
202 struct blkid_prval
*vals
, int nvals
)
206 for (x
= 0, i
= 0; i
< pr
->nvals
&& x
< nvals
; i
++) {
207 struct blkid_prval
*v
= &pr
->vals
[i
];
211 memcpy(&vals
[x
++], v
, sizeof(struct blkid_prval
));
217 * Appends values from @vals to the probing result
219 void blkid_probe_append_vals(blkid_probe pr
, struct blkid_prval
*vals
, int nvals
)
223 while (i
< nvals
&& pr
->nvals
< BLKID_NVALS
) {
224 memcpy(&pr
->vals
[pr
->nvals
++], &vals
[i
++],
225 sizeof(struct blkid_prval
));
229 static void blkid_probe_reset_vals(blkid_probe pr
)
231 memset(pr
->vals
, 0, sizeof(pr
->vals
));
235 struct blkid_chain
*blkid_probe_get_chain(blkid_probe pr
)
237 return pr
->cur_chain
;
244 * Cleanup probing result. This function does not touch probing filters
245 * and keeps assigned device.
247 void blkid_reset_probe(blkid_probe pr
)
254 blkid_probe_reset_buffer(pr
);
255 blkid_probe_reset_vals(pr
);
257 for (i
= 0; i
< BLKID_NCHAINS
; i
++)
258 pr
->chains
[i
].idx
= -1;
262 static int blkid_probe_dump_filter(blkid_probe pr, int chain)
264 struct blkid_chain *chn;
267 if (!pr || chain < 0 || chain >= BLKID_NCHAINS)
270 chn = &pr->chains[chain];
275 for (i = 0; i < chn->driver->nidinfos; i++) {
276 const struct blkid_idinfo *id = chn->driver->idinfos[i];
278 DBG(DEBUG_LOWPROBE, printf("%d: %s: %s\n",
281 blkid_bmp_get_item(chn->fltr, i)
282 ? "disabled" : "enabled <--"));
289 * Returns properly initialized chain filter
291 unsigned long *blkid_probe_get_filter(blkid_probe pr
, int chain
, int create
)
293 struct blkid_chain
*chn
;
295 if (!pr
|| chain
< 0 || chain
>= BLKID_NCHAINS
)
298 chn
= &pr
->chains
[chain
];
300 /* always when you touch the chain filter all indexes are reseted and
301 * probing starts from scratch
304 pr
->cur_chain
= NULL
;
306 if (!chn
->driver
->has_fltr
|| (!chn
->fltr
&& !create
))
310 chn
->fltr
= calloc(1, blkid_bmp_nbytes(chn
->driver
->nidinfos
));
312 memset(chn
->fltr
, 0, blkid_bmp_nbytes(chn
->driver
->nidinfos
));
314 /* blkid_probe_dump_filter(pr, chain); */
319 * Generic private functions for filter setting
321 int __blkid_probe_invert_filter(blkid_probe pr
, int chain
)
324 struct blkid_chain
*chn
;
327 fltr
= blkid_probe_get_filter(pr
, chain
, FALSE
);
331 chn
= &pr
->chains
[chain
];
333 for (i
= 0; i
< blkid_bmp_nwords(chn
->driver
->nidinfos
); i
++)
336 DBG(DEBUG_LOWPROBE
, printf("probing filter inverted\n"));
337 /* blkid_probe_dump_filter(pr, chain); */
341 int __blkid_probe_reset_filter(blkid_probe pr
, int chain
)
343 return blkid_probe_get_filter(pr
, chain
, FALSE
) ? 0 : -1;
346 int __blkid_probe_filter_types(blkid_probe pr
, int chain
, int flag
, char *names
[])
349 struct blkid_chain
*chn
;
352 fltr
= blkid_probe_get_filter(pr
, chain
, TRUE
);
356 chn
= &pr
->chains
[chain
];
358 for (i
= 0; i
< chn
->driver
->nidinfos
; i
++) {
360 const struct blkid_idinfo
*id
= chn
->driver
->idinfos
[i
];
363 for (n
= names
; *n
; n
++) {
364 if (!strcmp(id
->name
, *n
)) {
369 if (flag
& BLKID_FLTR_ONLYIN
) {
371 blkid_bmp_set_item(fltr
, i
);
372 } else if (flag
& BLKID_FLTR_NOTIN
) {
374 blkid_bmp_set_item(fltr
, i
);
379 printf("%s: a new probing type-filter initialized\n",
381 /* blkid_probe_dump_filter(pr, chain); */
386 * Note that we have two offsets:
388 * 1/ general device offset (pr->off), that's useful for example when we
389 * probe a partition from whole disk image:
390 * blkid-low --offset <partition_position> disk.img
392 * 2/ buffer offset (the 'off' argument), that useful for offsets in
395 * That means never use lseek(fd, 0, SEEK_SET), the zero position is always
396 * pr->off, so lseek(fd, pr->off, SEEK_SET).
399 unsigned char *blkid_probe_get_buffer(blkid_probe pr
,
400 blkid_loff_t off
, blkid_loff_t len
)
402 ssize_t ret_read
= 0;
404 if (off
< 0 || len
< 0) {
406 printf("unexpected offset or length of buffer requested\n"));
409 if (off
+ len
<= BLKID_SB_BUFSIZ
) {
411 pr
->sbbuf
= malloc(BLKID_SB_BUFSIZ
);
415 if (!pr
->sbbuf_len
) {
416 if (lseek(pr
->fd
, pr
->off
, SEEK_SET
) < 0)
418 ret_read
= read(pr
->fd
, pr
->sbbuf
, BLKID_SB_BUFSIZ
);
421 pr
->sbbuf_len
= ret_read
;
423 if (off
+ len
> pr
->sbbuf_len
)
425 return pr
->sbbuf
+ off
;
427 unsigned char *newbuf
= NULL
;
429 if (len
> pr
->buf_max
) {
430 newbuf
= realloc(pr
->buf
, len
);
438 if (newbuf
|| off
< pr
->buf_off
||
439 off
+ len
> pr
->buf_off
+ pr
->buf_len
) {
441 if (blkid_llseek(pr
->fd
, pr
->off
+ off
, SEEK_SET
) < 0)
444 ret_read
= read(pr
->fd
, pr
->buf
, len
);
445 if (ret_read
!= (ssize_t
) len
)
450 return off
? pr
->buf
+ (off
- pr
->buf_off
) : pr
->buf
;
455 * blkid_probe_set_device:
457 * @fd: device file descriptor
458 * @off: begin of probing area
459 * @size: size of probing area
461 * Assigns the device to probe control struct, resets internal buffers and
462 * reads 512 bytes from device to the buffers.
464 * Returns: -1 in case of failure, or 0 on success.
466 int blkid_probe_set_device(blkid_probe pr
, int fd
,
467 blkid_loff_t off
, blkid_loff_t size
)
472 blkid_reset_probe(pr
);
489 pr
->mode
= sb
.st_mode
;
491 if (S_ISBLK(sb
.st_mode
)) {
492 blkdev_get_size(fd
, (unsigned long long *) &pr
->size
);
493 pr
->devno
= sb
.st_rdev
;
495 pr
->size
= sb
.st_size
;
500 /* read SB to test if the device is readable */
501 if (!blkid_probe_get_buffer(pr
, 0, 0x200)) {
503 printf("failed to prepare a device for low-probing\n"));
507 DBG(DEBUG_LOWPROBE
, printf("ready for low-probing, offset=%zd, size=%zd\n",
516 * Calls probing functions in all enabled chains. The superblocks chain is
517 * enabled by default. The blkid_do_probe() stores result from only one
518 * probing function. It's necessary to call this routine in a loop to get
519 * resuluts from all probing functions in all chains.
521 * This is string-based NAME=value interface only.
524 * <title>basic case - use the first result only</title>
527 * if (blkid_do_probe(pr) == 0) {
528 * int nvals = blkid_probe_numof_values(pr);
529 * for (n = 0; n < nvals; n++) {
530 * if (blkid_probe_get_value(pr, n, &name, &data, &len) == 0)
531 * printf("%s = %s\n", name, data);
538 * <title>advanced case - probe for all signatures</title>
541 * while (blkid_do_probe(pr) == 0) {
542 * int nvals = blkid_probe_numof_values(pr);
548 * See also blkid_reset_probe().
550 * Returns: 0 on success, 1 when probing is done and -1 in case of error.
552 int blkid_do_probe(blkid_probe pr
)
560 struct blkid_chain
*chn
;
563 pr
->cur_chain
= &pr
->chains
[0];
564 else if (pr
->cur_chain
< &pr
->chains
[BLKID_NCHAINS
- 1])
565 pr
->cur_chain
+= sizeof(struct blkid_chain
);
567 return 1; /* all chains already probed */
570 chn
->binary
= FALSE
; /* for sure... */
572 DBG(DEBUG_LOWPROBE
, printf("chain probe %s %s\n",
574 chn
->enabled
? "ENABLED" : "DISABLED"));
579 /* rc: -1 = error, 0 = success, 1 = no result */
580 rc
= chn
->driver
->probe(pr
, chn
);
588 * blkid_do_safeprobe:
591 * This function gathers probing results from all enabled chains and checks
592 * for ambivalent results (e.g. more filesystems on the device).
594 * This is string-based NAME=value interface only.
596 * Note about suberblocks chain -- the function does not check for filesystems
597 * when a RAID signature is detected. The function also does not check for
598 * collision between RAIDs. The first detected RAID is returned.
600 * Returns: 0 on success, 1 if nothing is detected, -2 if ambivalen result is
601 * detected and -1 on case of error.
603 int blkid_do_safeprobe(blkid_probe pr
)
605 int i
, count
= 0, rc
= 0;
610 for (i
= 0; i
< BLKID_NCHAINS
; i
++) {
611 struct blkid_chain
*chn
;
613 chn
= pr
->cur_chain
= &pr
->chains
[i
];
614 chn
->binary
= FALSE
; /* for sure... */
616 DBG(DEBUG_LOWPROBE
, printf("chain safeprobe %s %s\n",
618 chn
->enabled
? "ENABLED" : "DISABLED"));
625 /* rc: -2 ambivalent, -1 = error, 0 = success, 1 = no result */
626 rc
= chn
->driver
->safeprobe(pr
, chn
);
628 goto done
; /* error */
630 count
++; /* success */
634 pr
->cur_chain
= NULL
;
637 return count
? 0 : 1;
641 * blkid_do_fullprobe:
644 * This function gathers probing results from all enabled chains. Same as
645 * blkid_so_safeprobe() but does not check for collision between probing
648 * This is string-based NAME=value interface only.
650 * Returns: 0 on success, 1 if nothing is detected or -1 on case of error.
652 int blkid_do_fullprobe(blkid_probe pr
)
654 int i
, count
= 0, rc
= 0;
659 for (i
= 0; i
< BLKID_NCHAINS
; i
++) {
661 struct blkid_chain
*chn
;
663 chn
= pr
->cur_chain
= &pr
->chains
[i
];
664 chn
->binary
= FALSE
; /* for sure... */
666 DBG(DEBUG_LOWPROBE
, printf("chain fullprobe %s: %s\n",
668 chn
->enabled
? "ENABLED" : "DISABLED"));
675 /* rc: -1 = error, 0 = success, 1 = no result */
676 rc
= chn
->driver
->probe(pr
, chn
);
678 goto done
; /* error */
680 count
++; /* success */
684 pr
->cur_chain
= NULL
;
687 return count
? 0 : 1;
690 struct blkid_prval
*blkid_probe_assign_value(
691 blkid_probe pr
, const char *name
)
693 struct blkid_prval
*v
;
697 if (pr
->nvals
>= BLKID_NVALS
)
700 v
= &pr
->vals
[pr
->nvals
];
702 v
->chain
= pr
->cur_chain
;
706 printf("assigning %s [%s]\n", name
, v
->chain
->driver
->name
));
710 int blkid_probe_set_value(blkid_probe pr
, const char *name
,
711 unsigned char *data
, size_t len
)
713 struct blkid_prval
*v
;
715 if (len
> BLKID_PROBVAL_BUFSIZ
)
716 len
= BLKID_PROBVAL_BUFSIZ
;
718 v
= blkid_probe_assign_value(pr
, name
);
722 memcpy(v
->data
, data
, len
);
727 int blkid_probe_vsprintf_value(blkid_probe pr
, const char *name
,
728 const char *fmt
, va_list ap
)
730 struct blkid_prval
*v
;
733 v
= blkid_probe_assign_value(pr
, name
);
737 len
= vsnprintf((char *) v
->data
, sizeof(v
->data
), fmt
, ap
);
740 pr
->nvals
--; /* reset the latest assigned value */
748 * blkid_probe_numof_values:
751 * Returns: number of values in probing result or -1 in case of error.
753 int blkid_probe_numof_values(blkid_probe pr
)
761 * blkid_probe_get_value:
763 * @num: wanted value in range 0..N, where N is blkid_probe_numof_values() - 1
764 * @name: pointer to return value name or NULL
765 * @data: pointer to return value data or NULL
766 * @len: pointer to return value length or NULL
768 * Returns: 0 on success, or -1 in case of error.
770 int blkid_probe_get_value(blkid_probe pr
, int num
, const char **name
,
771 const char **data
, size_t *len
)
773 struct blkid_prval
*v
= __blkid_probe_get_value(pr
, num
);
780 *data
= (char *) v
->data
;
784 DBG(DEBUG_LOWPROBE
, printf("returning %s value\n", v
->name
));
789 * blkid_probe_lookup_value:
791 * @name: name of value
792 * @data: pointer to return value data or NULL
793 * @len: pointer to return value length or NULL
795 * Returns: 0 on success, or -1 in case of error.
797 int blkid_probe_lookup_value(blkid_probe pr
, const char *name
,
798 const char **data
, size_t *len
)
800 struct blkid_prval
*v
= __blkid_probe_lookup_value(pr
, name
);
805 *data
= (char *) v
->data
;
808 DBG(DEBUG_LOWPROBE
, printf("returning %s value\n", v
->name
));
813 * blkid_probe_has_value:
815 * @name: name of value
817 * Returns: 1 if value exist in probing result, otherwise 0.
819 int blkid_probe_has_value(blkid_probe pr
, const char *name
)
821 if (blkid_probe_lookup_value(pr
, name
, NULL
, NULL
) == 0)
826 struct blkid_prval
*__blkid_probe_get_value(blkid_probe pr
, int num
)
828 if (pr
== NULL
|| num
< 0 || num
>= pr
->nvals
)
831 return &pr
->vals
[num
];
834 struct blkid_prval
*__blkid_probe_lookup_value(blkid_probe pr
, const char *name
)
838 if (pr
== NULL
|| pr
->nvals
== 0 || name
== NULL
)
841 for (i
= 0; i
< pr
->nvals
; i
++) {
842 struct blkid_prval
*v
= &pr
->vals
[i
];
844 if (v
->name
&& strcmp(name
, v
->name
) == 0) {
845 DBG(DEBUG_LOWPROBE
, printf("returning %s value\n", v
->name
));
853 /* converts DCE UUID (uuid[16]) to human readable string
854 * - the @len should be always 37 */
855 void blkid_unparse_uuid(const unsigned char *uuid
, char *str
, size_t len
)
858 uuid_unparse(uuid
, str
);
861 "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
862 uuid
[0], uuid
[1], uuid
[2], uuid
[3],
866 uuid
[10], uuid
[11], uuid
[12], uuid
[13], uuid
[14],uuid
[15]);