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.
16 #include <sys/types.h>
22 #include "superblocks.h"
26 * @title: Superblocks probing
27 * @short_description: filesystems and raids superblocks probing.
29 * The library API has been originally designed for superblocks probing only.
30 * This is reason why some *deprecated* superblock specific functions don't use
31 * '_superblocks_' namespace in the function name. Please, don't use these
32 * functions in new code.
34 * The 'superblocks' probers support NAME=value (tags) interface only. The
35 * superblocks probing is enabled by default (and controlled by
36 * blkid_probe_enable_superblocks()).
38 * Currently supported tags:
40 * @TYPE: filesystem type
42 * @SEC_TYPE: secondary filesystem type
44 * @LABEL: filesystem label
46 * @LABEL_RAW: raw label from FS superblock
48 * @UUID: filesystem UUID (lower case)
50 * @UUID_SUB: subvolume uuid (e.g. btrfs)
52 * @LOGUUID: external log UUID (e.g. xfs)
54 * @UUID_RAW: raw UUID from FS superblock
56 * @EXT_JOURNAL: external journal UUID
58 * @USAGE: usage string: "raid", "filesystem", ...
60 * @VERSION: filesystem version
62 * @MOUNT: cluster mount name (?) -- ocfs only
64 * @SBMAGIC: super block magic string
66 * @SBMAGIC_OFFSET: offset of SBMAGIC
68 * @FSSIZE: size of filessystem [not-implemented yet]
70 * @SYSTEM_ID: ISO9660 system identifier
72 * @PUBLISHER_ID: ISO9660 publisher identifier
74 * @APPLICATION_ID: ISO9660 application identifier
76 * @BOOT_SYSTEM_ID: ISO9660 boot system identifier
79 static int superblocks_probe(blkid_probe pr
, struct blkid_chain
*chn
);
80 static int superblocks_safeprobe(blkid_probe pr
, struct blkid_chain
*chn
);
82 static int blkid_probe_set_usage(blkid_probe pr
, int usage
);
86 * Superblocks chains probing functions
88 static const struct blkid_idinfo
*idinfos
[] =
100 &highpoint37x_idinfo
,
107 &drbdproxy_datalog_idinfo
,
165 const struct blkid_chaindrv superblocks_drv
= {
166 .id
= BLKID_CHAIN_SUBLKS
,
167 .name
= "superblocks",
168 .dflt_enabled
= TRUE
,
169 .dflt_flags
= BLKID_SUBLKS_DEFAULT
,
171 .nidinfos
= ARRAY_SIZE(idinfos
),
173 .probe
= superblocks_probe
,
174 .safeprobe
= superblocks_safeprobe
,
178 * blkid_probe_enable_superblocks:
180 * @enable: TRUE/FALSE
182 * Enables/disables the superblocks probing for non-binary interface.
184 * Returns: 0 on success, or -1 in case of error.
186 int blkid_probe_enable_superblocks(blkid_probe pr
, int enable
)
190 pr
->chains
[BLKID_CHAIN_SUBLKS
].enabled
= enable
;
195 * blkid_probe_set_superblocks_flags:
197 * @flags: BLKID_SUBLKS_* flags
199 * Sets probing flags to the superblocks prober. This function is optional, the
200 * default are BLKID_SUBLKS_DEFAULTS flags.
202 * Returns: 0 on success, or -1 in case of error.
204 int blkid_probe_set_superblocks_flags(blkid_probe pr
, int flags
)
209 pr
->chains
[BLKID_CHAIN_SUBLKS
].flags
= flags
;
214 * blkid_probe_reset_superblocks_filter:
217 * Resets superblocks probing filter
219 * Returns: 0 on success, or -1 in case of error.
221 int blkid_probe_reset_superblocks_filter(blkid_probe pr
)
223 return __blkid_probe_reset_filter(pr
, BLKID_CHAIN_SUBLKS
);
227 * blkid_probe_invert_superblocks_filter:
230 * Inverts superblocks probing filter
232 * Returns: 0 on success, or -1 in case of error.
234 int blkid_probe_invert_superblocks_filter(blkid_probe pr
)
236 return __blkid_probe_invert_filter(pr
, BLKID_CHAIN_SUBLKS
);
240 * blkid_probe_filter_superblocks_type:
242 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
243 * @names: NULL terminated array of probing function names (e.g. "vfat").
245 * %BLKID_FLTR_NOTIN - probe for all items which are NOT IN @names;
247 * %BLKID_FLTR_ONLYIN - probe for items which are IN @names
249 * Returns: 0 on success, or -1 in case of error.
251 int blkid_probe_filter_superblocks_type(blkid_probe pr
, int flag
, char *names
[])
253 return __blkid_probe_filter_types(pr
, BLKID_CHAIN_SUBLKS
, flag
, names
);
257 * blkid_probe_filter_superblocks_usage:
259 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
260 * @usage: BLKID_USAGE_* flags
262 * %BLKID_FLTR_NOTIN - probe for all items which are NOT IN @usage;
264 * %BLKID_FLTR_ONLYIN - probe for items which are IN @usage
266 * Returns: 0 on success, or -1 in case of error.
268 int blkid_probe_filter_superblocks_usage(blkid_probe pr
, int flag
, int usage
)
271 struct blkid_chain
*chn
;
274 fltr
= blkid_probe_get_filter(pr
, BLKID_CHAIN_SUBLKS
, TRUE
);
278 chn
= &pr
->chains
[BLKID_CHAIN_SUBLKS
];
280 for (i
= 0; i
< chn
->driver
->nidinfos
; i
++) {
281 const struct blkid_idinfo
*id
= chn
->driver
->idinfos
[i
];
283 if (id
->usage
& usage
) {
284 if (flag
& BLKID_FLTR_NOTIN
)
285 blkid_bmp_set_item(chn
->fltr
, i
);
286 } else if (flag
& BLKID_FLTR_ONLYIN
)
287 blkid_bmp_set_item(chn
->fltr
, i
);
289 DBG(LOWPROBE
, ul_debug("a new probing usage-filter initialized"));
294 * blkid_known_fstype:
295 * @fstype: filesystem name
297 * Returns: 1 for known filesytems, or 0 for unknown filesystem.
299 int blkid_known_fstype(const char *fstype
)
306 for (i
= 0; i
< ARRAY_SIZE(idinfos
); i
++) {
307 const struct blkid_idinfo
*id
= idinfos
[i
];
308 if (strcmp(id
->name
, fstype
) == 0)
315 * blkid_superblocks_get_name:
317 * @name: returns name of supported filesystem/raid (optional)
318 * @usage: returns BLKID_USAGE_* flags, (optional)
320 * Returns: -1 if @idx is out of range, or 0 on success.
322 int blkid_superblocks_get_name(size_t idx
, const char **name
, int *usage
)
324 if (idx
< ARRAY_SIZE(idinfos
)) {
326 *name
= idinfos
[idx
]->name
;
328 *usage
= idinfos
[idx
]->usage
;
335 * The blkid_do_probe() backend.
337 static int superblocks_probe(blkid_probe pr
, struct blkid_chain
*chn
)
340 int rc
= BLKID_PROBE_NONE
;
342 if (!pr
|| chn
->idx
< -1)
345 blkid_probe_chain_reset_values(pr
, chn
);
347 if (pr
->flags
& BLKID_FL_NOSCAN_DEV
)
348 return BLKID_PROBE_NONE
;
350 if (pr
->size
<= 0 || (pr
->size
<= 1024 && !S_ISCHR(pr
->mode
)))
351 /* Ignore very very small block devices or regular files (e.g.
352 * extended partitions). Note that size of the UBI char devices
354 return BLKID_PROBE_NONE
;
356 DBG(LOWPROBE
, ul_debug("--> starting probing loop [SUBLKS idx=%d]",
359 i
= chn
->idx
< 0 ? 0 : chn
->idx
+ 1U;
361 for ( ; i
< ARRAY_SIZE(idinfos
); i
++) {
362 const struct blkid_idinfo
*id
;
363 const struct blkid_idmag
*mag
= NULL
;
369 if (chn
->fltr
&& blkid_bmp_get_item(chn
->fltr
, i
)) {
370 DBG(LOWPROBE
, ul_debug("filter out: %s", id
->name
));
371 rc
= BLKID_PROBE_NONE
;
375 if (id
->minsz
&& (unsigned)id
->minsz
> pr
->size
) {
376 rc
= BLKID_PROBE_NONE
;
377 continue; /* the device is too small */
380 /* don't probe for RAIDs, swap or journal on CD/DVDs */
381 if ((id
->usage
& (BLKID_USAGE_RAID
| BLKID_USAGE_OTHER
)) &&
382 blkid_probe_is_cdrom(pr
)) {
383 rc
= BLKID_PROBE_NONE
;
387 /* don't probe for RAIDs on floppies */
388 if ((id
->usage
& BLKID_USAGE_RAID
) && blkid_probe_is_tiny(pr
)) {
389 rc
= BLKID_PROBE_NONE
;
393 DBG(LOWPROBE
, ul_debug("[%zd] %s:", i
, id
->name
));
395 rc
= blkid_probe_get_idmag(pr
, id
, &off
, &mag
);
398 if (rc
!= BLKID_PROBE_OK
)
401 /* final check by probing function */
403 DBG(LOWPROBE
, ul_debug("\tcall probefunc()"));
404 rc
= id
->probefunc(pr
, mag
);
405 if (rc
!= BLKID_PROBE_OK
) {
406 blkid_probe_chain_reset_values(pr
, chn
);
413 /* all cheks passed */
414 if (chn
->flags
& BLKID_SUBLKS_TYPE
)
415 rc
= blkid_probe_set_value(pr
, "TYPE",
416 (unsigned char *) id
->name
,
417 strlen(id
->name
) + 1);
420 rc
= blkid_probe_set_usage(pr
, id
->usage
);
423 rc
= blkid_probe_set_magic(pr
, off
, mag
->len
,
424 (unsigned char *) mag
->magic
);
426 blkid_probe_chain_reset_values(pr
, chn
);
427 DBG(LOWPROBE
, ul_debug("failed to set result -- ignore"));
431 DBG(LOWPROBE
, ul_debug("<-- leaving probing loop (type=%s) [SUBLKS idx=%d]",
432 id
->name
, chn
->idx
));
433 return BLKID_PROBE_OK
;
436 DBG(LOWPROBE
, ul_debug("<-- leaving probing loop (failed=%d) [SUBLKS idx=%d]",
442 * This is the same function as blkid_do_probe(), but returns only one result
443 * (cannot be used in while()) and checks for ambivalen results (more
444 * filesystems on the device) -- in such case returns -2.
446 * The function does not check for filesystems when a RAID or crypto signature
447 * is detected. The function also does not check for collision between RAIDs
448 * and crypto devices. The first detected RAID or crypto device is returned.
450 * The function does not probe for ambivalent results on very small devices
451 * (e.g. floppies), on small devices the first detected filesystem is returned.
453 static int superblocks_safeprobe(blkid_probe pr
, struct blkid_chain
*chn
)
455 struct list_head vals
;
461 INIT_LIST_HEAD(&vals
);
463 if (pr
->flags
& BLKID_FL_NOSCAN_DEV
)
464 return BLKID_PROBE_NONE
;
466 while ((rc
= superblocks_probe(pr
, chn
)) == 0) {
468 if (blkid_probe_is_tiny(pr
) && !count
)
469 return BLKID_PROBE_OK
; /* floppy or so -- returns the first result. */
474 idinfos
[chn
->idx
]->usage
& (BLKID_USAGE_RAID
| BLKID_USAGE_CRYPTO
))
478 !(idinfos
[chn
->idx
]->flags
& BLKID_IDINFO_TOLERANT
))
482 /* save the first result */
483 blkid_probe_chain_save_values(pr
, chn
, &vals
);
489 goto done
; /* error */
491 if (count
> 1 && intol
) {
492 DBG(LOWPROBE
, ul_debug("ERROR: superblocks chain: "
493 "ambivalent result detected (%d filesystems)!",
495 rc
= -2; /* error, ambivalent result (more FS) */
499 rc
= BLKID_PROBE_NONE
;
504 /* restore the first result */
505 blkid_probe_chain_reset_values(pr
, chn
);
506 blkid_probe_append_values_list(pr
, &vals
);
511 * The RAID device could be partitioned. The problem are RAID1 devices
512 * where the partition table is visible from underlaying devices. We
513 * have to ignore such partition tables.
515 if (chn
->idx
>= 0 && idinfos
[chn
->idx
]->usage
& BLKID_USAGE_RAID
)
516 pr
->prob_flags
|= BLKID_PROBE_FL_IGNORE_PT
;
520 blkid_probe_free_values_list(&vals
);
524 int blkid_probe_set_version(blkid_probe pr
, const char *version
)
526 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
528 if (chn
->flags
& BLKID_SUBLKS_VERSION
)
529 return blkid_probe_set_value(pr
, "VERSION",
530 (unsigned char *) version
, strlen(version
) + 1);
535 int blkid_probe_sprintf_version(blkid_probe pr
, const char *fmt
, ...)
537 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
540 if (chn
->flags
& BLKID_SUBLKS_VERSION
) {
544 rc
= blkid_probe_vsprintf_value(pr
, "VERSION", fmt
, ap
);
550 static int blkid_probe_set_usage(blkid_probe pr
, int usage
)
552 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
555 if (!(chn
->flags
& BLKID_SUBLKS_USAGE
))
558 if (usage
& BLKID_USAGE_FILESYSTEM
)
560 else if (usage
& BLKID_USAGE_RAID
)
562 else if (usage
& BLKID_USAGE_CRYPTO
)
564 else if (usage
& BLKID_USAGE_OTHER
)
569 return blkid_probe_set_value(pr
, "USAGE", (unsigned char *) u
, strlen(u
) + 1);
572 int blkid_probe_set_id_label(blkid_probe pr
, const char *name
,
573 unsigned char *data
, size_t len
)
575 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
576 struct blkid_prval
*v
;
579 if (!(chn
->flags
& BLKID_SUBLKS_LABEL
))
582 v
= blkid_probe_assign_value(pr
, name
);
586 rc
= blkid_probe_value_set_data(v
, data
, len
);
588 /* remove white spaces */
589 v
->len
= blkid_rtrim_whitespace(v
->data
) + 1;
591 v
->len
= blkid_ltrim_whitespace(v
->data
) + 1;
596 blkid_probe_free_value(v
);
601 int blkid_probe_set_utf8_id_label(blkid_probe pr
, const char *name
,
602 unsigned char *data
, size_t len
, int enc
)
604 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
605 struct blkid_prval
*v
;
608 if (!(chn
->flags
& BLKID_SUBLKS_LABEL
))
611 v
= blkid_probe_assign_value(pr
, name
);
615 v
->data
= blkid_encode_alloc(len
, &v
->len
);
620 blkid_encode_to_utf8(enc
, v
->data
, v
->len
, data
, len
);
621 v
->len
= blkid_rtrim_whitespace(v
->data
) + 1;
623 v
->len
= blkid_ltrim_whitespace(v
->data
) + 1;
628 blkid_probe_free_value(v
);
632 int blkid_probe_set_label(blkid_probe pr
, unsigned char *label
, size_t len
)
634 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
635 struct blkid_prval
*v
;
638 if ((chn
->flags
& BLKID_SUBLKS_LABELRAW
) &&
639 (rc
= blkid_probe_set_value(pr
, "LABEL_RAW", label
, len
)) < 0)
642 if (!(chn
->flags
& BLKID_SUBLKS_LABEL
))
645 v
= blkid_probe_assign_value(pr
, "LABEL");
649 rc
= blkid_probe_value_set_data(v
, label
, len
);
651 v
->len
= blkid_rtrim_whitespace(v
->data
) + 1;
656 blkid_probe_free_value(v
);
660 int blkid_probe_set_utf8label(blkid_probe pr
, unsigned char *label
,
663 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
664 struct blkid_prval
*v
;
667 if ((chn
->flags
& BLKID_SUBLKS_LABELRAW
) &&
668 (rc
= blkid_probe_set_value(pr
, "LABEL_RAW", label
, len
)) < 0)
671 if (!(chn
->flags
& BLKID_SUBLKS_LABEL
))
674 v
= blkid_probe_assign_value(pr
, "LABEL");
678 v
->data
= blkid_encode_alloc(len
, &v
->len
);
682 blkid_encode_to_utf8(enc
, v
->data
, v
->len
, label
, len
);
683 v
->len
= blkid_rtrim_whitespace(v
->data
) + 1;
688 blkid_probe_free_value(v
);
692 int blkid_probe_sprintf_uuid(blkid_probe pr
, unsigned char *uuid
,
693 size_t len
, const char *fmt
, ...)
695 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
699 if (blkid_uuid_is_empty(uuid
, len
))
702 if ((chn
->flags
& BLKID_SUBLKS_UUIDRAW
) &&
703 (rc
= blkid_probe_set_value(pr
, "UUID_RAW", uuid
, len
)) < 0)
706 if (!(chn
->flags
& BLKID_SUBLKS_UUID
))
710 rc
= blkid_probe_vsprintf_value(pr
, "UUID", fmt
, ap
);
716 /* function to set UUIDs that are in suberblocks stored as strings */
717 int blkid_probe_strncpy_uuid(blkid_probe pr
, unsigned char *str
, size_t len
)
719 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
720 struct blkid_prval
*v
;
723 if (str
== NULL
|| *str
== '\0')
727 len
= strlen((char *) str
);
729 if ((chn
->flags
& BLKID_SUBLKS_UUIDRAW
) &&
730 (rc
= blkid_probe_set_value(pr
, "UUID_RAW", str
, len
)) < 0)
733 if (!(chn
->flags
& BLKID_SUBLKS_UUID
))
736 v
= blkid_probe_assign_value(pr
, "UUID");
740 rc
= blkid_probe_value_set_data(v
, str
, len
);
742 v
->len
= blkid_rtrim_whitespace(v
->data
) + 1;
747 blkid_probe_free_value(v
);
751 /* default _set_uuid function to set DCE UUIDs */
752 int blkid_probe_set_uuid_as(blkid_probe pr
, unsigned char *uuid
, const char *name
)
754 struct blkid_chain
*chn
= blkid_probe_get_chain(pr
);
755 struct blkid_prval
*v
;
758 if (blkid_uuid_is_empty(uuid
, 16))
762 if ((chn
->flags
& BLKID_SUBLKS_UUIDRAW
) &&
763 (rc
= blkid_probe_set_value(pr
, "UUID_RAW", uuid
, 16)) < 0)
766 if (!(chn
->flags
& BLKID_SUBLKS_UUID
))
769 v
= blkid_probe_assign_value(pr
, "UUID");
771 v
= blkid_probe_assign_value(pr
, name
);
777 v
->data
= calloc(1, v
->len
);
782 blkid_unparse_uuid(uuid
, (char *) v
->data
, v
->len
);
786 blkid_probe_free_value(v
);
790 int blkid_probe_set_uuid(blkid_probe pr
, unsigned char *uuid
)
792 return blkid_probe_set_uuid_as(pr
, uuid
, NULL
);
796 * blkid_probe_set_request:
798 * @flags: BLKID_PROBREQ_* (deprecated) or BLKID_SUBLKS_* flags
800 * Returns: 0 on success, or -1 in case of error.
802 * Deprecated: Use blkid_probe_set_superblocks_flags().
804 int blkid_probe_set_request(blkid_probe pr
, int flags
)
806 return blkid_probe_set_superblocks_flags(pr
, flags
);
810 * blkid_probe_reset_filter:
813 * Returns: 0 on success, or -1 in case of error.
815 * Deprecated: Use blkid_probe_reset_superblocks_filter().
817 int blkid_probe_reset_filter(blkid_probe pr
)
819 return __blkid_probe_reset_filter(pr
, BLKID_CHAIN_SUBLKS
);
823 * blkid_probe_invert_filter:
826 * Returns: 0 on success, or -1 in case of error.
828 * Deprecated: Use blkid_probe_invert_superblocks_filter().
830 int blkid_probe_invert_filter(blkid_probe pr
)
832 return __blkid_probe_invert_filter(pr
, BLKID_CHAIN_SUBLKS
);
836 * blkid_probe_filter_types
838 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
839 * @names: NULL terminated array of probing function names (e.g. "vfat").
841 * Returns: 0 on success, or -1 in case of error.
843 * Deprecated: Use blkid_probe_filter_superblocks_types().
845 int blkid_probe_filter_types(blkid_probe pr
, int flag
, char *names
[])
847 return __blkid_probe_filter_types(pr
, BLKID_CHAIN_SUBLKS
, flag
, names
);
851 * blkid_probe_filter_usage
853 * @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
854 * @usage: BLKID_USAGE_* flags
856 * Returns: 0 on success, or -1 in case of error.
858 * Deprecated: Use blkid_probe_filter_superblocks_usage().
860 int blkid_probe_filter_usage(blkid_probe pr
, int flag
, int usage
)
862 return blkid_probe_filter_superblocks_usage(pr
, flag
, usage
);