2 * superblocks.c - reads information from filesystem and raid superblocks
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.
17 #include <sys/types.h>
23 #include "superblocks.h"
27 * @title: Superblocks probing
28 * @short_description: filesystems and raids superblocks probing.
30 * The library API has been originally designed for superblocks probing only.
31 * This is reason why some *deprecated* superblock specific functions don't use
32 * '_superblocks_' namespace in the function name. Please, don't use these
33 * functions in new code.
35 * The 'superblocks' probers support NAME=value (tags) interface only. The
36 * superblocks probing is enabled by default (and controlled by
37 * blkid_probe_enable_superblocks()).
39 * Currently supported tags:
41 * @TYPE: filesystem type
43 * @SEC_TYPE: secondary filesystem type
45 * @LABEL: filesystem label
47 * @LABEL_RAW: raw label from FS superblock
49 * @UUID: filesystem UUID (lower case)
51 * @UUID_SUB: subvolume uuid (e.g. btrfs)
53 * @LOGUUID: external log UUID (e.g. xfs)
55 * @UUID_RAW: raw UUID from FS superblock
57 * @EXT_JOURNAL: external journal UUID
59 * @USAGE: usage string: "raid", "filesystem", ...
61 * @VERSION: filesystem version
63 * @MOUNT: cluster mount name (?) -- ocfs only
65 * @SBMAGIC: super block magic string
67 * @SBMAGIC_OFFSET: offset of SBMAGIC
69 * @FSSIZE: size of filesystem (implemented for XFS/BTRFS/Ext only)
71 * @FSLASTBLOCK: last fsblock/total number of fsblocks
73 * @FSBLOCKSIZE: file system block size
75 * @SYSTEM_ID: ISO9660 system identifier
77 * @PUBLISHER_ID: ISO9660 publisher identifier
79 * @APPLICATION_ID: ISO9660 application identifier
81 * @BOOT_SYSTEM_ID: ISO9660 boot system identifier
83 * @BLOCK_SIZE: minimal block size accessible by file system
86 static int superblocks_probe(blkid_probe pr
, struct blkid_chain
*chn
);
87 static int superblocks_safeprobe(blkid_probe pr
, struct blkid_chain
*chn
);
89 static int blkid_probe_set_usage(blkid_probe pr
, int usage
);
93 * Superblocks chains probing functions
95 static const struct blkid_idinfo
*idinfos
[] =
97 /* In case the volume is locked with OPAL we are going to get
98 * an I/O error when reading past the LUKS header, so try it
111 &highpoint45x_idinfo
,
112 &highpoint37x_idinfo
,
121 &drbdproxy_datalog_idinfo
,
189 const struct blkid_chaindrv superblocks_drv
= {
190 .id
= BLKID_CHAIN_SUBLKS
,
191 .name
= "superblocks",
192 .dflt_enabled
= TRUE
,
193 .dflt_flags
= BLKID_SUBLKS_DEFAULT
,
195 .nidinfos
= ARRAY_SIZE(idinfos
),
197 .probe
= superblocks_probe
,
198 .safeprobe
= superblocks_safeprobe
,
202 * blkid_probe_enable_superblocks:
204 * @enable: TRUE/FALSE
206 * Enables/disables the superblocks probing for non-binary interface.
208 * Returns: 0 on success, or -1 in case of error.
210 int blkid_probe_enable_superblocks(blkid_probe pr
, int enable
)
212 pr
->chains
[BLKID_CHAIN_SUBLKS
].enabled
= enable
;
217 * blkid_probe_set_superblocks_flags:
219 * @flags: BLKID_SUBLKS_* flags
221 * Sets probing flags to the superblocks prober. This function is optional, the
222 * default are BLKID_SUBLKS_DEFAULTS flags.
224 * Returns: 0 on success, or -1 in case of error.
226 int blkid_probe_set_superblocks_flags(blkid_probe pr
, int flags
)
228 pr
->chains
[BLKID_CHAIN_SUBLKS
].flags
= flags
;
233 * blkid_probe_reset_superblocks_filter:
236 * Resets superblocks probing filter
238 * Returns: 0 on success, or -1 in case of error.
240 int blkid_probe_reset_superblocks_filter(blkid_probe pr
)
242 return __blkid_probe_reset_filter(pr
, BLKID_CHAIN_SUBLKS
);
246 * blkid_probe_invert_superblocks_filter:
249 * Inverts superblocks probing filter
251 * Returns: 0 on success, or -1 in case of error.
253 int blkid_probe_invert_superblocks_filter(blkid_probe pr
)
255 return __blkid_probe_invert_filter(pr
, BLKID_CHAIN_SUBLKS
);
259 * blkid_probe_filter_superblocks_type:
261 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
262 * @names: NULL terminated array of probing function names (e.g. "vfat").
264 * %BLKID_FLTR_NOTIN - probe for all items which are NOT IN @names;
266 * %BLKID_FLTR_ONLYIN - probe for items which are IN @names
268 * Returns: 0 on success, or -1 in case of error.
270 int blkid_probe_filter_superblocks_type(blkid_probe pr
, int flag
, char *names
[])
272 return __blkid_probe_filter_types(pr
, BLKID_CHAIN_SUBLKS
, flag
, names
);
276 * blkid_probe_filter_superblocks_usage:
278 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
279 * @usage: BLKID_USAGE_* flags
281 * %BLKID_FLTR_NOTIN - probe for all items which are NOT IN @usage;
283 * %BLKID_FLTR_ONLYIN - probe for items which are IN @usage
285 * Returns: 0 on success, or -1 in case of error.
287 int blkid_probe_filter_superblocks_usage(blkid_probe pr
, int flag
, int usage
)
290 struct blkid_chain
*chn
;
293 fltr
= blkid_probe_get_filter(pr
, BLKID_CHAIN_SUBLKS
, TRUE
);
297 chn
= &pr
->chains
[BLKID_CHAIN_SUBLKS
];
299 for (i
= 0; i
< chn
->driver
->nidinfos
; i
++) {
300 const struct blkid_idinfo
*id
= chn
->driver
->idinfos
[i
];
302 if (id
->usage
& usage
) {
303 if (flag
& BLKID_FLTR_NOTIN
)
304 blkid_bmp_set_item(chn
->fltr
, i
);
305 } else if (flag
& BLKID_FLTR_ONLYIN
)
306 blkid_bmp_set_item(chn
->fltr
, i
);
308 DBG(LOWPROBE
, ul_debug("a new probing usage-filter initialized"));
313 * blkid_known_fstype:
314 * @fstype: filesystem name
316 * Returns: 1 for known filesystems, or 0 for unknown filesystem.
318 int blkid_known_fstype(const char *fstype
)
322 for (i
= 0; i
< ARRAY_SIZE(idinfos
); i
++) {
323 const struct blkid_idinfo
*id
= idinfos
[i
];
324 if (strcmp(id
->name
, fstype
) == 0)
331 * blkid_superblocks_get_name:
333 * @name: returns name of supported filesystem/raid (optional)
334 * @usage: returns BLKID_USAGE_* flags, (optional)
336 * Returns: -1 if @idx is out of range, or 0 on success.
338 int blkid_superblocks_get_name(size_t idx
, const char **name
, int *usage
)
340 if (idx
< ARRAY_SIZE(idinfos
)) {
342 *name
= idinfos
[idx
]->name
;
344 *usage
= idinfos
[idx
]->usage
;
351 * The blkid_do_probe() backend.
353 static int superblocks_probe(blkid_probe pr
, struct blkid_chain
*chn
)
356 int rc
= BLKID_PROBE_NONE
;
361 blkid_probe_chain_reset_values(pr
, chn
);
363 if (pr
->flags
& BLKID_FL_NOSCAN_DEV
) {
364 DBG(LOWPROBE
, ul_debug("*** ignore (noscan flag)"));
365 return BLKID_PROBE_NONE
;
368 if (pr
->size
<= 0 || (pr
->size
<= 1024 && !S_ISCHR(pr
->mode
))) {
369 /* Ignore very very small block devices or regular files (e.g.
370 * extended partitions). Note that size of the UBI char devices
372 DBG(LOWPROBE
, ul_debug("*** ignore (size <= 1024)"));
373 return BLKID_PROBE_NONE
;
376 DBG(LOWPROBE
, ul_debug("--> starting probing loop [SUBLKS idx=%d]",
379 i
= chn
->idx
< 0 ? 0 : chn
->idx
+ 1U;
381 for ( ; i
< ARRAY_SIZE(idinfos
); i
++) {
382 const struct blkid_idinfo
*id
;
383 const struct blkid_idmag
*mag
= NULL
;
389 if (chn
->fltr
&& blkid_bmp_get_item(chn
->fltr
, i
)) {
390 DBG(LOWPROBE
, ul_debug("filter out: %s", id
->name
));
391 rc
= BLKID_PROBE_NONE
;
395 if (id
->minsz
&& (unsigned)id
->minsz
> pr
->size
) {
396 rc
= BLKID_PROBE_NONE
;
397 continue; /* the device is too small */
400 /* don't probe for RAIDs, swap or journal on CD/DVDs */
401 if ((id
->usage
& (BLKID_USAGE_RAID
| BLKID_USAGE_OTHER
)) &&
402 blkid_probe_is_cdrom(pr
)) {
403 rc
= BLKID_PROBE_NONE
;
407 /* don't probe for RAIDs on floppies */
408 if ((id
->usage
& BLKID_USAGE_RAID
) && blkid_probe_is_tiny(pr
)) {
409 rc
= BLKID_PROBE_NONE
;
413 DBG(LOWPROBE
, ul_debug("[%zd] %s:", i
, id
->name
));
415 rc
= blkid_probe_get_idmag(pr
, id
, &off
, &mag
);
418 if (rc
!= BLKID_PROBE_OK
)
421 /* final check by probing function */
423 DBG(LOWPROBE
, ul_debug("\tcall probefunc()"));
424 rc
= id
->probefunc(pr
, mag
);
425 if (rc
!= BLKID_PROBE_OK
) {
426 blkid_probe_chain_reset_values(pr
, chn
);
433 /* all checks passed */
434 if (chn
->flags
& BLKID_SUBLKS_TYPE
)
435 rc
= blkid_probe_set_value(pr
, "TYPE",
436 (const unsigned char *) id
->name
,
437 strlen(id
->name
) + 1);
440 rc
= blkid_probe_set_usage(pr
, id
->usage
);
443 rc
= blkid_probe_set_magic(pr
, off
, mag
->len
,
444 (const unsigned char *) mag
->magic
);
446 blkid_probe_chain_reset_values(pr
, chn
);
447 DBG(LOWPROBE
, ul_debug("failed to set result -- ignore"));
451 DBG(LOWPROBE
, ul_debug("<-- leaving probing loop (type=%s) [SUBLKS idx=%d]",
452 id
->name
, chn
->idx
));
453 return BLKID_PROBE_OK
;
456 DBG(LOWPROBE
, ul_debug("<-- leaving probing loop (failed=%d) [SUBLKS idx=%d]",
462 * This is the same function as blkid_do_probe(), but returns only one result
463 * (cannot be used in while()) and checks for ambivalent results (more
464 * filesystems on the device) -- in such case returns -2.
466 * The function does not check for filesystems when a RAID or crypto signature
467 * is detected. The function also does not check for collision between RAIDs
468 * and crypto devices. The first detected RAID or crypto device is returned.
470 * The function does not probe for ambivalent results on very small devices
471 * (e.g. floppies), on small devices the first detected filesystem is returned.
473 static int superblocks_safeprobe(blkid_probe pr
, struct blkid_chain
*chn
)
475 struct list_head vals
;
481 INIT_LIST_HEAD(&vals
);
483 if (pr
->flags
& BLKID_FL_NOSCAN_DEV
)
484 return BLKID_PROBE_NONE
;
486 while ((rc
= superblocks_probe(pr
, chn
)) == 0) {
488 if (blkid_probe_is_tiny(pr
) && !count
)
489 return BLKID_PROBE_OK
; /* floppy or so -- returns the first result. */
494 idinfos
[chn
->idx
]->usage
& (BLKID_USAGE_RAID
| BLKID_USAGE_CRYPTO
))
498 !(idinfos
[chn
->idx
]->flags
& BLKID_IDINFO_TOLERANT
))
502 /* save the first result */
503 blkid_probe_chain_save_values(pr
, chn
, &vals
);
509 goto done
; /* error */
511 if (count
> 1 && intol
) {
512 DBG(LOWPROBE
, ul_debug("ERROR: superblocks chain: "
513 "ambivalent result detected (%d filesystems)!",
515 rc
= BLKID_PROBE_AMBIGUOUS
; /* error, ambivalent result (more FS) */
519 rc
= BLKID_PROBE_NONE
;
524 /* restore the first result */
525 blkid_probe_chain_reset_values(pr
, chn
);
526 blkid_probe_append_values_list(pr
, &vals
);
531 * The RAID device could be partitioned. The problem are RAID1 devices
532 * where the partition table is visible from underlying devices. We
533 * have to ignore such partition tables.
535 if (chn
->idx
>= 0 && idinfos
[chn
->idx
]->usage
& BLKID_USAGE_RAID
)
536 pr
->prob_flags
|= BLKID_PROBE_FL_IGNORE_PT
;
540 blkid_probe_free_values_list(&vals
);
544 int blkid_probe_set_version(blkid_probe pr
, const char *version
)
546 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
548 if (chn
->flags
& BLKID_SUBLKS_VERSION
)
549 return blkid_probe_set_value(pr
, "VERSION",
550 (const unsigned char *) version
,
551 strlen(version
) + 1);
556 int blkid_probe_sprintf_version(blkid_probe pr
, const char *fmt
, ...)
558 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
561 if (chn
->flags
& BLKID_SUBLKS_VERSION
) {
565 rc
= blkid_probe_vsprintf_value(pr
, "VERSION", fmt
, ap
);
571 int blkid_probe_set_block_size(blkid_probe pr
, unsigned block_size
)
573 return blkid_probe_sprintf_value(pr
, "BLOCK_SIZE", "%u", block_size
);
576 static int blkid_probe_set_usage(blkid_probe pr
, int usage
)
578 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
579 const char *u
= NULL
;
581 if (!(chn
->flags
& BLKID_SUBLKS_USAGE
))
584 if (usage
& BLKID_USAGE_FILESYSTEM
)
586 else if (usage
& BLKID_USAGE_RAID
)
588 else if (usage
& BLKID_USAGE_CRYPTO
)
590 else if (usage
& BLKID_USAGE_OTHER
)
595 return blkid_probe_set_value(pr
, "USAGE",
596 (const unsigned char *) u
, strlen(u
) + 1);
599 int blkid_probe_set_fssize(blkid_probe pr
, uint64_t size
)
601 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
603 if (!(chn
->flags
& BLKID_SUBLKS_FSINFO
))
606 return blkid_probe_sprintf_value(pr
, "FSSIZE", "%" PRIu64
, size
);
609 int blkid_probe_set_fslastblock(blkid_probe pr
, uint64_t lastblock
)
611 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
613 if (!(chn
->flags
& BLKID_SUBLKS_FSINFO
))
616 return blkid_probe_sprintf_value(pr
, "FSLASTBLOCK", "%" PRIu64
,
620 int blkid_probe_set_fsblocksize(blkid_probe pr
, uint32_t block_size
)
622 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
624 if (!(chn
->flags
& BLKID_SUBLKS_FSINFO
))
627 return blkid_probe_sprintf_value(pr
, "FSBLOCKSIZE", "%" PRIu32
,
631 int blkid_probe_set_fsendianness(blkid_probe pr
, enum BLKID_ENDIANNESS endianness
)
633 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
636 if (!(chn
->flags
& BLKID_SUBLKS_FSINFO
))
639 switch (endianness
) {
640 case BLKID_ENDIANNESS_LITTLE
:
643 case BLKID_ENDIANNESS_BIG
:
650 return blkid_probe_set_value(pr
, "ENDIANNESS",
651 (const unsigned char *) value
, strlen(value
) + 1);
655 int blkid_probe_set_id_label(blkid_probe pr
, const char *name
,
656 const unsigned char *data
, size_t len
)
658 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
659 struct blkid_prval
*v
;
662 if (!(chn
->flags
& BLKID_SUBLKS_LABEL
))
665 v
= blkid_probe_assign_value(pr
, name
);
669 rc
= blkid_probe_value_set_data(v
, data
, len
);
671 /* remove white spaces */
672 v
->len
= blkid_rtrim_whitespace(v
->data
) + 1;
674 v
->len
= blkid_ltrim_whitespace(v
->data
) + 1;
679 blkid_probe_free_value(v
);
684 int blkid_probe_set_utf8_id_label(blkid_probe pr
, const char *name
,
685 const unsigned char *data
, size_t len
, int enc
)
687 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
688 struct blkid_prval
*v
;
691 if (!(chn
->flags
& BLKID_SUBLKS_LABEL
))
694 v
= blkid_probe_assign_value(pr
, name
);
698 v
->len
= (len
* 3) + 1;
699 v
->data
= calloc(1, v
->len
);
704 ul_encode_to_utf8(enc
, v
->data
, v
->len
, data
, len
);
705 v
->len
= blkid_rtrim_whitespace(v
->data
) + 1;
707 v
->len
= blkid_ltrim_whitespace(v
->data
) + 1;
712 blkid_probe_free_value(v
);
716 int blkid_probe_set_label(blkid_probe pr
, const unsigned char *label
, size_t len
)
718 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
719 struct blkid_prval
*v
;
722 if ((chn
->flags
& BLKID_SUBLKS_LABELRAW
) &&
723 (rc
= blkid_probe_set_value(pr
, "LABEL_RAW", label
, len
)) < 0)
726 if (!(chn
->flags
& BLKID_SUBLKS_LABEL
))
729 v
= blkid_probe_assign_value(pr
, "LABEL");
733 rc
= blkid_probe_value_set_data(v
, label
, len
);
735 v
->len
= blkid_rtrim_whitespace(v
->data
) + 1;
740 blkid_probe_free_value(v
);
744 int blkid_probe_set_utf8label(blkid_probe pr
, const unsigned char *label
,
747 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
748 struct blkid_prval
*v
;
751 if ((chn
->flags
& BLKID_SUBLKS_LABELRAW
) &&
752 (rc
= blkid_probe_set_value(pr
, "LABEL_RAW", label
, len
)) < 0)
755 if (!(chn
->flags
& BLKID_SUBLKS_LABEL
))
758 v
= blkid_probe_assign_value(pr
, "LABEL");
762 v
->len
= (len
* 3) + 1;
763 v
->data
= calloc(1, v
->len
);
767 ul_encode_to_utf8(enc
, v
->data
, v
->len
, label
, len
);
768 v
->len
= blkid_rtrim_whitespace(v
->data
) + 1;
773 blkid_probe_free_value(v
);
777 int blkid_probe_sprintf_uuid(blkid_probe pr
, const unsigned char *uuid
,
778 size_t len
, const char *fmt
, ...)
780 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
784 if (blkid_uuid_is_empty(uuid
, len
))
787 if ((chn
->flags
& BLKID_SUBLKS_UUIDRAW
) &&
788 (rc
= blkid_probe_set_value(pr
, "UUID_RAW", uuid
, len
)) < 0)
791 if (!(chn
->flags
& BLKID_SUBLKS_UUID
))
795 rc
= blkid_probe_vsprintf_value(pr
, "UUID", fmt
, ap
);
801 /* function to set UUIDs that are in superblocks stored as strings */
802 int blkid_probe_strncpy_uuid(blkid_probe pr
, const unsigned char *str
, size_t len
)
804 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
805 struct blkid_prval
*v
;
808 if (str
== NULL
|| *str
== '\0')
812 len
= strlen((const char *) str
);
814 if ((chn
->flags
& BLKID_SUBLKS_UUIDRAW
) &&
815 (rc
= blkid_probe_set_value(pr
, "UUID_RAW", str
, len
)) < 0)
818 if (!(chn
->flags
& BLKID_SUBLKS_UUID
))
821 v
= blkid_probe_assign_value(pr
, "UUID");
825 rc
= blkid_probe_value_set_data(v
, str
, len
);
827 v
->len
= blkid_rtrim_whitespace(v
->data
) + 1;
832 blkid_probe_free_value(v
);
836 /* default _set_uuid function to set DCE UUIDs */
837 int blkid_probe_set_uuid_as(blkid_probe pr
, const unsigned char *uuid
, const char *name
)
839 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
840 struct blkid_prval
*v
;
843 if (blkid_uuid_is_empty(uuid
, 16))
847 if ((chn
->flags
& BLKID_SUBLKS_UUIDRAW
) &&
848 (rc
= blkid_probe_set_value(pr
, "UUID_RAW", uuid
, 16)) < 0)
851 if (!(chn
->flags
& BLKID_SUBLKS_UUID
))
854 v
= blkid_probe_assign_value(pr
, "UUID");
856 v
= blkid_probe_assign_value(pr
, name
);
861 v
->len
= UUID_STR_LEN
;
862 v
->data
= calloc(1, v
->len
);
867 blkid_unparse_uuid(uuid
, (char *) v
->data
, v
->len
);
871 blkid_probe_free_value(v
);
875 int blkid_probe_set_uuid(blkid_probe pr
, const unsigned char *uuid
)
877 return blkid_probe_set_uuid_as(pr
, uuid
, NULL
);
881 * blkid_probe_set_request:
883 * @flags: BLKID_PROBREQ_* (deprecated) or BLKID_SUBLKS_* flags
885 * Returns: 0 on success, or -1 in case of error.
887 * Deprecated: Use blkid_probe_set_superblocks_flags().
889 int blkid_probe_set_request(blkid_probe pr
, int flags
)
891 return blkid_probe_set_superblocks_flags(pr
, flags
);
895 * blkid_probe_reset_filter:
898 * Returns: 0 on success, or -1 in case of error.
900 * Deprecated: Use blkid_probe_reset_superblocks_filter().
902 int blkid_probe_reset_filter(blkid_probe pr
)
904 return __blkid_probe_reset_filter(pr
, BLKID_CHAIN_SUBLKS
);
908 * blkid_probe_invert_filter:
911 * Returns: 0 on success, or -1 in case of error.
913 * Deprecated: Use blkid_probe_invert_superblocks_filter().
915 int blkid_probe_invert_filter(blkid_probe pr
)
917 return __blkid_probe_invert_filter(pr
, BLKID_CHAIN_SUBLKS
);
921 * blkid_probe_filter_types
923 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
924 * @names: NULL terminated array of probing function names (e.g. "vfat").
926 * Returns: 0 on success, or -1 in case of error.
928 * Deprecated: Use blkid_probe_filter_superblocks_type().
930 int blkid_probe_filter_types(blkid_probe pr
, int flag
, char *names
[])
932 return __blkid_probe_filter_types(pr
, BLKID_CHAIN_SUBLKS
, flag
, names
);
936 * blkid_probe_filter_usage
938 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
939 * @usage: BLKID_USAGE_* flags
941 * Returns: 0 on success, or -1 in case of error.
943 * Deprecated: Use blkid_probe_filter_superblocks_usage().
945 int blkid_probe_filter_usage(blkid_probe pr
, int flag
, int usage
)
947 return blkid_probe_filter_superblocks_usage(pr
, flag
, usage
);