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 /* First, as access to locked OPAL region triggers IO errors */
109 &highpoint45x_idinfo
,
110 &highpoint37x_idinfo
,
119 &drbdproxy_datalog_idinfo
,
161 &scoutfs_meta_idinfo
,
162 &scoutfs_data_idinfo
,
190 const struct blkid_chaindrv superblocks_drv
= {
191 .id
= BLKID_CHAIN_SUBLKS
,
192 .name
= "superblocks",
193 .dflt_enabled
= TRUE
,
194 .dflt_flags
= BLKID_SUBLKS_DEFAULT
,
196 .nidinfos
= ARRAY_SIZE(idinfos
),
198 .probe
= superblocks_probe
,
199 .safeprobe
= superblocks_safeprobe
,
203 * blkid_probe_enable_superblocks:
205 * @enable: TRUE/FALSE
207 * Enables/disables the superblocks probing for non-binary interface.
209 * Returns: 0 on success, or -1 in case of error.
211 int blkid_probe_enable_superblocks(blkid_probe pr
, int enable
)
213 pr
->chains
[BLKID_CHAIN_SUBLKS
].enabled
= enable
;
218 * blkid_probe_set_superblocks_flags:
220 * @flags: BLKID_SUBLKS_* flags
222 * Sets probing flags to the superblocks prober. This function is optional, the
223 * default are BLKID_SUBLKS_DEFAULTS flags.
225 * Returns: 0 on success, or -1 in case of error.
227 int blkid_probe_set_superblocks_flags(blkid_probe pr
, int flags
)
229 pr
->chains
[BLKID_CHAIN_SUBLKS
].flags
= flags
;
234 * blkid_probe_reset_superblocks_filter:
237 * Resets superblocks probing filter
239 * Returns: 0 on success, or -1 in case of error.
241 int blkid_probe_reset_superblocks_filter(blkid_probe pr
)
243 return __blkid_probe_reset_filter(pr
, BLKID_CHAIN_SUBLKS
);
247 * blkid_probe_invert_superblocks_filter:
250 * Inverts superblocks probing filter
252 * Returns: 0 on success, or -1 in case of error.
254 int blkid_probe_invert_superblocks_filter(blkid_probe pr
)
256 return __blkid_probe_invert_filter(pr
, BLKID_CHAIN_SUBLKS
);
260 * blkid_probe_filter_superblocks_type:
262 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
263 * @names: NULL terminated array of probing function names (e.g. "vfat").
265 * %BLKID_FLTR_NOTIN - probe for all items which are NOT IN @names;
267 * %BLKID_FLTR_ONLYIN - probe for items which are IN @names
269 * Returns: 0 on success, or -1 in case of error.
271 int blkid_probe_filter_superblocks_type(blkid_probe pr
, int flag
, char *names
[])
273 return __blkid_probe_filter_types(pr
, BLKID_CHAIN_SUBLKS
, flag
, names
);
277 * blkid_probe_filter_superblocks_usage:
279 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
280 * @usage: BLKID_USAGE_* flags
282 * %BLKID_FLTR_NOTIN - probe for all items which are NOT IN @usage;
284 * %BLKID_FLTR_ONLYIN - probe for items which are IN @usage
286 * Returns: 0 on success, or -1 in case of error.
288 int blkid_probe_filter_superblocks_usage(blkid_probe pr
, int flag
, int usage
)
291 struct blkid_chain
*chn
;
294 fltr
= blkid_probe_get_filter(pr
, BLKID_CHAIN_SUBLKS
, TRUE
);
298 chn
= &pr
->chains
[BLKID_CHAIN_SUBLKS
];
300 for (i
= 0; i
< chn
->driver
->nidinfos
; i
++) {
301 const struct blkid_idinfo
*id
= chn
->driver
->idinfos
[i
];
303 if (id
->usage
& usage
) {
304 if (flag
& BLKID_FLTR_NOTIN
)
305 blkid_bmp_set_item(chn
->fltr
, i
);
306 } else if (flag
& BLKID_FLTR_ONLYIN
)
307 blkid_bmp_set_item(chn
->fltr
, i
);
309 DBG(LOWPROBE
, ul_debug("a new probing usage-filter initialized"));
314 * blkid_known_fstype:
315 * @fstype: filesystem name
317 * Returns: 1 for known filesystems, or 0 for unknown filesystem.
319 int blkid_known_fstype(const char *fstype
)
323 for (i
= 0; i
< ARRAY_SIZE(idinfos
); i
++) {
324 const struct blkid_idinfo
*id
= idinfos
[i
];
325 if (strcmp(id
->name
, fstype
) == 0)
332 * blkid_superblocks_get_name:
334 * @name: returns name of supported filesystem/raid (optional)
335 * @usage: returns BLKID_USAGE_* flags, (optional)
337 * Returns: -1 if @idx is out of range, or 0 on success.
339 int blkid_superblocks_get_name(size_t idx
, const char **name
, int *usage
)
341 if (idx
< ARRAY_SIZE(idinfos
)) {
343 *name
= idinfos
[idx
]->name
;
345 *usage
= idinfos
[idx
]->usage
;
352 * The blkid_do_probe() backend.
354 static int superblocks_probe(blkid_probe pr
, struct blkid_chain
*chn
)
357 int rc
= BLKID_PROBE_NONE
;
362 blkid_probe_chain_reset_values(pr
, chn
);
364 if (pr
->flags
& BLKID_FL_NOSCAN_DEV
) {
365 DBG(LOWPROBE
, ul_debug("*** ignore (noscan flag)"));
366 return BLKID_PROBE_NONE
;
369 if (pr
->size
<= 0 || (pr
->size
<= 1024 && !S_ISCHR(pr
->mode
))) {
370 /* Ignore very very small block devices or regular files (e.g.
371 * extended partitions). Note that size of the UBI char devices
373 DBG(LOWPROBE
, ul_debug("*** ignore (size <= 1024)"));
374 return BLKID_PROBE_NONE
;
377 DBG(LOWPROBE
, ul_debug("--> starting probing loop [SUBLKS idx=%d]",
380 i
= chn
->idx
< 0 ? 0 : chn
->idx
+ 1U;
382 for ( ; i
< ARRAY_SIZE(idinfos
); i
++) {
383 const struct blkid_idinfo
*id
;
384 const struct blkid_idmag
*mag
= NULL
;
390 if (chn
->fltr
&& blkid_bmp_get_item(chn
->fltr
, i
)) {
391 DBG(LOWPROBE
, ul_debug("filter out: %s", id
->name
));
392 rc
= BLKID_PROBE_NONE
;
396 if (id
->minsz
&& (unsigned)id
->minsz
> pr
->size
) {
397 rc
= BLKID_PROBE_NONE
;
398 continue; /* the device is too small */
401 /* don't probe for RAIDs, swap or journal on CD/DVDs */
402 if ((id
->usage
& (BLKID_USAGE_RAID
| BLKID_USAGE_OTHER
)) &&
403 blkid_probe_is_cdrom(pr
)) {
404 rc
= BLKID_PROBE_NONE
;
408 /* don't probe for RAIDs on floppies */
409 if ((id
->usage
& BLKID_USAGE_RAID
) && blkid_probe_is_tiny(pr
)) {
410 rc
= BLKID_PROBE_NONE
;
414 DBG(LOWPROBE
, ul_debug("[%zd] %s:", i
, id
->name
));
416 rc
= blkid_probe_get_idmag(pr
, id
, &off
, &mag
);
419 if (rc
!= BLKID_PROBE_OK
)
422 /* final check by probing function */
424 DBG(LOWPROBE
, ul_debug("\tcall probefunc()"));
426 rc
= id
->probefunc(pr
, mag
);
427 blkid_probe_prune_buffers(pr
);
428 if (rc
!= BLKID_PROBE_OK
) {
429 blkid_probe_chain_reset_values(pr
, chn
);
436 /* all checks passed */
437 if (chn
->flags
& BLKID_SUBLKS_TYPE
)
438 rc
= blkid_probe_set_value(pr
, "TYPE",
439 (const unsigned char *) id
->name
,
440 strlen(id
->name
) + 1);
443 rc
= blkid_probe_set_usage(pr
, id
->usage
);
446 rc
= blkid_probe_set_magic(pr
, off
, mag
->len
,
447 (const unsigned char *) mag
->magic
);
449 blkid_probe_chain_reset_values(pr
, chn
);
450 DBG(LOWPROBE
, ul_debug("failed to set result -- ignore"));
454 DBG(LOWPROBE
, ul_debug("<-- leaving probing loop (type=%s) [SUBLKS idx=%d]",
455 id
->name
, chn
->idx
));
456 return BLKID_PROBE_OK
;
459 DBG(LOWPROBE
, ul_debug("<-- leaving probing loop (failed=%d) [SUBLKS idx=%d]",
465 * This is the same function as blkid_do_probe(), but returns only one result
466 * (cannot be used in while()) and checks for ambivalent results (more
467 * filesystems on the device) -- in such case returns -2.
469 * The function does not check for filesystems when a RAID or crypto signature
470 * is detected. The function also does not check for collision between RAIDs
471 * and crypto devices. The first detected RAID or crypto device is returned.
473 * The function does not probe for ambivalent results on very small devices
474 * (e.g. floppies), on small devices the first detected filesystem is returned.
476 static int superblocks_safeprobe(blkid_probe pr
, struct blkid_chain
*chn
)
478 struct list_head vals
;
484 INIT_LIST_HEAD(&vals
);
486 if (pr
->flags
& BLKID_FL_NOSCAN_DEV
)
487 return BLKID_PROBE_NONE
;
489 while ((rc
= superblocks_probe(pr
, chn
)) == 0) {
491 if (blkid_probe_is_tiny(pr
) && !count
)
492 return BLKID_PROBE_OK
; /* floppy or so -- returns the first result. */
497 idinfos
[chn
->idx
]->usage
& (BLKID_USAGE_RAID
| BLKID_USAGE_CRYPTO
))
501 !(idinfos
[chn
->idx
]->flags
& BLKID_IDINFO_TOLERANT
))
505 /* save the first result */
506 blkid_probe_chain_save_values(pr
, chn
, &vals
);
512 goto done
; /* error */
514 if (count
> 1 && intol
) {
515 DBG(LOWPROBE
, ul_debug("ERROR: superblocks chain: "
516 "ambivalent result detected (%d filesystems)!",
518 rc
= BLKID_PROBE_AMBIGUOUS
; /* error, ambivalent result (more FS) */
522 rc
= BLKID_PROBE_NONE
;
527 /* restore the first result */
528 blkid_probe_chain_reset_values(pr
, chn
);
529 blkid_probe_append_values_list(pr
, &vals
);
534 * The RAID device could be partitioned. The problem are RAID1 devices
535 * where the partition table is visible from underlying devices. We
536 * have to ignore such partition tables.
538 if (chn
->idx
>= 0 && idinfos
[chn
->idx
]->usage
& BLKID_USAGE_RAID
)
539 pr
->prob_flags
|= BLKID_PROBE_FL_IGNORE_PT
;
543 blkid_probe_free_values_list(&vals
);
547 int blkid_probe_set_version(blkid_probe pr
, const char *version
)
549 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
551 if (chn
->flags
& BLKID_SUBLKS_VERSION
)
552 return blkid_probe_set_value(pr
, "VERSION",
553 (const unsigned char *) version
,
554 strlen(version
) + 1);
559 int blkid_probe_sprintf_version(blkid_probe pr
, const char *fmt
, ...)
561 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
564 if (chn
->flags
& BLKID_SUBLKS_VERSION
) {
568 rc
= blkid_probe_vsprintf_value(pr
, "VERSION", fmt
, ap
);
574 int blkid_probe_set_block_size(blkid_probe pr
, unsigned block_size
)
576 return blkid_probe_sprintf_value(pr
, "BLOCK_SIZE", "%u", block_size
);
579 static int blkid_probe_set_usage(blkid_probe pr
, int usage
)
581 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
582 const char *u
= NULL
;
584 if (!(chn
->flags
& BLKID_SUBLKS_USAGE
))
587 if (usage
& BLKID_USAGE_FILESYSTEM
)
589 else if (usage
& BLKID_USAGE_RAID
)
591 else if (usage
& BLKID_USAGE_CRYPTO
)
593 else if (usage
& BLKID_USAGE_OTHER
)
598 return blkid_probe_set_value(pr
, "USAGE",
599 (const unsigned char *) u
, strlen(u
) + 1);
602 /* size used by filesystem for data */
603 int blkid_probe_set_fssize(blkid_probe pr
, uint64_t size
)
605 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
607 if (!(chn
->flags
& BLKID_SUBLKS_FSINFO
))
610 return blkid_probe_sprintf_value(pr
, "FSSIZE", "%" PRIu64
, size
);
613 int blkid_probe_set_fslastblock(blkid_probe pr
, uint64_t lastblock
)
615 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
617 if (!(chn
->flags
& BLKID_SUBLKS_FSINFO
))
620 return blkid_probe_sprintf_value(pr
, "FSLASTBLOCK", "%" PRIu64
,
624 int blkid_probe_set_fsblocksize(blkid_probe pr
, uint32_t block_size
)
626 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
628 if (!(chn
->flags
& BLKID_SUBLKS_FSINFO
))
631 return blkid_probe_sprintf_value(pr
, "FSBLOCKSIZE", "%" PRIu32
,
635 int blkid_probe_set_fsendianness(blkid_probe pr
, enum blkid_endianness endianness
)
637 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
640 if (!(chn
->flags
& BLKID_SUBLKS_FSINFO
))
643 switch (endianness
) {
644 case BLKID_ENDIANNESS_LITTLE
:
647 case BLKID_ENDIANNESS_BIG
:
654 return blkid_probe_set_value(pr
, "ENDIANNESS",
655 (const unsigned char *) value
, strlen(value
) + 1);
659 int blkid_probe_set_id_label(blkid_probe pr
, const char *name
,
660 const unsigned char *data
, size_t len
)
662 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
663 struct blkid_prval
*v
;
666 if (!(chn
->flags
& BLKID_SUBLKS_LABEL
))
669 v
= blkid_probe_assign_value(pr
, name
);
673 rc
= blkid_probe_value_set_data(v
, data
, len
);
675 /* remove white spaces */
676 v
->len
= blkid_rtrim_whitespace(v
->data
) + 1;
678 v
->len
= blkid_ltrim_whitespace(v
->data
) + 1;
683 blkid_probe_free_value(v
);
688 int blkid_probe_set_utf8_id_label(blkid_probe pr
, const char *name
,
689 const unsigned char *data
, size_t len
, int enc
)
691 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
692 struct blkid_prval
*v
;
695 if (!(chn
->flags
& BLKID_SUBLKS_LABEL
))
698 v
= blkid_probe_assign_value(pr
, name
);
702 v
->len
= (len
* 3) + 1;
703 v
->data
= calloc(1, v
->len
);
708 ul_encode_to_utf8(enc
, v
->data
, v
->len
, data
, len
);
709 v
->len
= blkid_rtrim_whitespace(v
->data
) + 1;
711 v
->len
= blkid_ltrim_whitespace(v
->data
) + 1;
716 blkid_probe_free_value(v
);
720 int blkid_probe_set_label(blkid_probe pr
, const unsigned char *label
, size_t len
)
722 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
723 struct blkid_prval
*v
;
726 if ((chn
->flags
& BLKID_SUBLKS_LABELRAW
) &&
727 (rc
= blkid_probe_set_value(pr
, "LABEL_RAW", label
, len
)) < 0)
730 if (!(chn
->flags
& BLKID_SUBLKS_LABEL
))
733 v
= blkid_probe_assign_value(pr
, "LABEL");
737 rc
= blkid_probe_value_set_data(v
, label
, len
);
739 v
->len
= blkid_rtrim_whitespace(v
->data
) + 1;
744 blkid_probe_free_value(v
);
748 int blkid_probe_set_utf8label(blkid_probe pr
, const unsigned char *label
,
751 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
752 struct blkid_prval
*v
;
755 if ((chn
->flags
& BLKID_SUBLKS_LABELRAW
) &&
756 (rc
= blkid_probe_set_value(pr
, "LABEL_RAW", label
, len
)) < 0)
759 if (!(chn
->flags
& BLKID_SUBLKS_LABEL
))
762 v
= blkid_probe_assign_value(pr
, "LABEL");
766 v
->len
= (len
* 3) + 1;
767 v
->data
= calloc(1, v
->len
);
771 ul_encode_to_utf8(enc
, v
->data
, v
->len
, label
, len
);
772 v
->len
= blkid_rtrim_whitespace(v
->data
) + 1;
777 blkid_probe_free_value(v
);
781 int blkid_probe_sprintf_uuid(blkid_probe pr
, const unsigned char *uuid
,
782 size_t len
, const char *fmt
, ...)
784 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
788 if (blkid_uuid_is_empty(uuid
, len
))
791 if ((chn
->flags
& BLKID_SUBLKS_UUIDRAW
) &&
792 (rc
= blkid_probe_set_value(pr
, "UUID_RAW", uuid
, len
)) < 0)
795 if (!(chn
->flags
& BLKID_SUBLKS_UUID
))
799 rc
= blkid_probe_vsprintf_value(pr
, "UUID", fmt
, ap
);
805 /* function to set UUIDs that are in superblocks stored as strings */
806 int blkid_probe_strncpy_uuid(blkid_probe pr
, const unsigned char *str
, size_t len
)
808 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
809 struct blkid_prval
*v
;
812 if (str
== NULL
|| *str
== '\0')
816 len
= strlen((const char *) str
);
818 if ((chn
->flags
& BLKID_SUBLKS_UUIDRAW
) &&
819 (rc
= blkid_probe_set_value(pr
, "UUID_RAW", str
, len
)) < 0)
822 if (!(chn
->flags
& BLKID_SUBLKS_UUID
))
825 v
= blkid_probe_assign_value(pr
, "UUID");
829 rc
= blkid_probe_value_set_data(v
, str
, len
);
831 v
->len
= blkid_rtrim_whitespace(v
->data
) + 1;
836 blkid_probe_free_value(v
);
840 /* default _set_uuid function to set DCE UUIDs */
841 int blkid_probe_set_uuid_as(blkid_probe pr
, const unsigned char *uuid
, const char *name
)
843 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
844 struct blkid_prval
*v
;
847 if (blkid_uuid_is_empty(uuid
, 16))
851 if ((chn
->flags
& BLKID_SUBLKS_UUIDRAW
) &&
852 (rc
= blkid_probe_set_value(pr
, "UUID_RAW", uuid
, 16)) < 0)
855 if (!(chn
->flags
& BLKID_SUBLKS_UUID
))
858 v
= blkid_probe_assign_value(pr
, "UUID");
860 v
= blkid_probe_assign_value(pr
, name
);
865 v
->len
= UUID_STR_LEN
;
866 v
->data
= calloc(1, v
->len
);
871 blkid_unparse_uuid(uuid
, (char *) v
->data
, v
->len
);
875 blkid_probe_free_value(v
);
879 int blkid_probe_set_uuid(blkid_probe pr
, const unsigned char *uuid
)
881 return blkid_probe_set_uuid_as(pr
, uuid
, NULL
);
885 * blkid_probe_set_request:
887 * @flags: BLKID_PROBREQ_* (deprecated) or BLKID_SUBLKS_* flags
889 * Returns: 0 on success, or -1 in case of error.
891 * Deprecated: Use blkid_probe_set_superblocks_flags().
893 int blkid_probe_set_request(blkid_probe pr
, int flags
)
895 return blkid_probe_set_superblocks_flags(pr
, flags
);
899 * blkid_probe_reset_filter:
902 * Returns: 0 on success, or -1 in case of error.
904 * Deprecated: Use blkid_probe_reset_superblocks_filter().
906 int blkid_probe_reset_filter(blkid_probe pr
)
908 return __blkid_probe_reset_filter(pr
, BLKID_CHAIN_SUBLKS
);
912 * blkid_probe_invert_filter:
915 * Returns: 0 on success, or -1 in case of error.
917 * Deprecated: Use blkid_probe_invert_superblocks_filter().
919 int blkid_probe_invert_filter(blkid_probe pr
)
921 return __blkid_probe_invert_filter(pr
, BLKID_CHAIN_SUBLKS
);
925 * blkid_probe_filter_types
927 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
928 * @names: NULL terminated array of probing function names (e.g. "vfat").
930 * Returns: 0 on success, or -1 in case of error.
932 * Deprecated: Use blkid_probe_filter_superblocks_type().
934 int blkid_probe_filter_types(blkid_probe pr
, int flag
, char *names
[])
936 return __blkid_probe_filter_types(pr
, BLKID_CHAIN_SUBLKS
, flag
, names
);
940 * blkid_probe_filter_usage
942 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
943 * @usage: BLKID_USAGE_* flags
945 * Returns: 0 on success, or -1 in case of error.
947 * Deprecated: Use blkid_probe_filter_superblocks_usage().
949 int blkid_probe_filter_usage(blkid_probe pr
, int flag
, int usage
)
951 return blkid_probe_filter_superblocks_usage(pr
, flag
, usage
);