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 originaly 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 controled 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
* @UUID_RAW: raw UUID from FS superblock
54
* @EXT_JOURNAL: external journal UUID
56
* @USAGE: usage string: "raid", "filesystem", ...
58
* @VERSION: filesystem version
60
* @MOUNT: cluster mount name (?) -- ocfs only
62
* @SBMAGIC: super block magic string
64
* @SBMAGIC_OFFSET: offset of SBMAGIC
66
* @FSSIZE: size of filessystem [not-implemented yet]
69
static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn);
70
static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn);
72
static int blkid_probe_set_usage(blkid_probe pr, int usage);
76
* Superblocks chains probing functions
78
static const struct blkid_idinfo *idinfos[] =
147
const struct blkid_chaindrv superblocks_drv = {
148
.id = BLKID_CHAIN_SUBLKS,
149
.name = "superblocks",
150
.dflt_enabled = TRUE,
151
.dflt_flags = BLKID_SUBLKS_DEFAULT,
153
.nidinfos = ARRAY_SIZE(idinfos),
155
.probe = superblocks_probe,
156
.safeprobe = superblocks_safeprobe,
160
* blkid_probe_enable_superblocks:
162
* @enable: TRUE/FALSE
164
* Enables/disables the superblocks probing for non-binary interface.
166
* Returns: 0 on success, or -1 in case of error.
168
int blkid_probe_enable_superblocks(blkid_probe pr, int enable)
172
pr->chains[BLKID_CHAIN_SUBLKS].enabled = enable;
177
* blkid_probe_set_superblocks_flags:
179
* @flags: BLKID_SUBLKS_* flags
181
* Sets probing flags to the superblocks prober. This function is optional, the
182
* default are BLKID_SUBLKS_DEFAULTS flags.
184
* Returns: 0 on success, or -1 in case of error.
186
int blkid_probe_set_superblocks_flags(blkid_probe pr, int flags)
191
pr->chains[BLKID_CHAIN_SUBLKS].flags = flags;
196
* blkid_probe_reset_superblocks_filter:
199
* Resets superblocks probing filter
201
* Returns: 0 on success, or -1 in case of error.
203
int blkid_probe_reset_superblocks_filter(blkid_probe pr)
205
return __blkid_probe_reset_filter(pr, BLKID_CHAIN_SUBLKS);
209
* blkid_probe_invert_superblocks_filter:
212
* Inverts superblocks probing filter
214
* Returns: 0 on success, or -1 in case of error.
216
int blkid_probe_invert_superblocks_filter(blkid_probe pr)
218
return __blkid_probe_invert_filter(pr, BLKID_CHAIN_SUBLKS);
222
* blkid_probe_filter_superblocks_type:
224
* @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
225
* @names: NULL terminated array of probing function names (e.g. "vfat").
227
* BLKID_FLTR_NOTIN - probe for all items which are NOT IN @names
228
* BLKID_FLTR_ONLYIN - probe for items which are IN @names
230
* Returns: 0 on success, or -1 in case of error.
232
int blkid_probe_filter_superblocks_type(blkid_probe pr, int flag, char *names[])
234
return __blkid_probe_filter_types(pr, BLKID_CHAIN_SUBLKS, flag, names);
238
* blkid_probe_filter_superblocks_usage:
240
* @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
241
* @usage: BLKID_USAGE_* flags
243
* BLKID_FLTR_NOTIN - probe for all items which are NOT IN @usage
244
* BLKID_FLTR_ONLYIN - probe for items which are IN @usage
246
* Returns: 0 on success, or -1 in case of error.
248
int blkid_probe_filter_superblocks_usage(blkid_probe pr, int flag, int usage)
251
struct blkid_chain *chn;
257
fltr = blkid_probe_get_filter(pr, BLKID_CHAIN_SUBLKS, TRUE);
261
chn = &pr->chains[BLKID_CHAIN_SUBLKS];
263
for (i = 0; i < chn->driver->nidinfos; i++) {
264
const struct blkid_idinfo *id = chn->driver->idinfos[i];
266
if (id->usage & usage) {
267
if (flag & BLKID_FLTR_NOTIN)
268
blkid_bmp_set_item(chn->fltr, i);
269
} else if (flag & BLKID_FLTR_ONLYIN)
270
blkid_bmp_set_item(chn->fltr, i);
272
DBG(DEBUG_LOWPROBE, printf("a new probing usage-filter initialized\n"));
277
* blkid_known_fstype:
278
* @fstype: filesystem name
280
* Returns: 1 for known filesytems, or 0 for unknown filesystem.
282
int blkid_known_fstype(const char *fstype)
289
for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
290
const struct blkid_idinfo *id = idinfos[i];
291
if (strcmp(id->name, fstype) == 0)
298
* The blkid_do_probe() backend.
300
static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn)
304
if (!pr || chn->idx < -1)
306
blkid_probe_chain_reset_vals(pr, chn);
309
printf("--> starting probing loop [SUBLKS idx=%d]\n",
312
if (pr->size <= 0 || (pr->size <= 1024 && !S_ISCHR(pr->mode)))
313
/* Ignore very very small block devices or regular files (e.g.
314
* extended partitions). Note that size of the UBI char devices
320
for ( ; i < ARRAY_SIZE(idinfos); i++) {
321
const struct blkid_idinfo *id;
322
const struct blkid_idmag *mag = NULL;
323
blkid_loff_t off = 0;
327
if (chn->fltr && blkid_bmp_get_item(chn->fltr, i))
332
if (id->minsz && id->minsz > pr->size)
333
continue; /* the device is too small */
335
mag = id->magics ? &id->magics[0] : NULL;
337
/* don't probe for RAIDs, swap or journal on CD/DVDs */
338
if ((id->usage & (BLKID_USAGE_RAID | BLKID_USAGE_OTHER)) &&
339
blkid_probe_is_cdrom(pr))
342
/* don't probe for RAIDs on floppies */
343
if ((id->usage & BLKID_USAGE_RAID) && blkid_probe_is_tiny(pr))
346
DBG(DEBUG_LOWPROBE, printf("[%d] %s:\n", i, id->name));
348
if (blkid_probe_get_idmag(pr, id, &off, &mag))
351
/* final check by probing function */
353
DBG(DEBUG_LOWPROBE, printf("\tcall probefunc()\n"));
354
if (id->probefunc(pr, mag) != 0) {
355
blkid_probe_chain_reset_vals(pr, chn);
360
/* all cheks passed */
361
if (chn->flags & BLKID_SUBLKS_TYPE)
362
blkid_probe_set_value(pr, "TYPE",
363
(unsigned char *) id->name,
364
strlen(id->name) + 1);
366
blkid_probe_set_usage(pr, id->usage);
369
blkid_probe_set_magic(pr, off, mag->len,
370
(unsigned char *) mag->magic);
373
printf("<-- leaving probing loop (type=%s) [SUBLKS idx=%d]\n",
374
id->name, chn->idx));
380
printf("<-- leaving probing loop (failed) [SUBLKS idx=%d]\n",
386
* This is the same function as blkid_do_probe(), but returns only one result
387
* (cannot be used in while()) and checks for ambivalen results (more
388
* filesystems on the device) -- in such case returns -2.
390
* The function does not check for filesystems when a RAID or crypto signature
391
* is detected. The function also does not check for collision between RAIDs
392
* and crypto devices. The first detected RAID or crypto device is returned.
394
* The function does not probe for ambivalent results on very small devices
395
* (e.g. floppies), on small devices the first detected filesystem is returned.
397
static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn)
399
struct blkid_prval vals[BLKID_NVALS_SUBLKS];
400
int nvals = BLKID_NVALS_SUBLKS;
406
while ((rc = superblocks_probe(pr, chn)) == 0) {
408
if (blkid_probe_is_tiny(pr) && !count)
409
/* floppy or so -- returns the first result. */
414
if (idinfos[chn->idx]->usage & (BLKID_USAGE_RAID | BLKID_USAGE_CRYPTO))
417
if (!(idinfos[chn->idx]->flags & BLKID_IDINFO_TOLERANT))
421
/* save the first result */
422
nvals = blkid_probe_chain_copy_vals(pr, chn, vals, nvals);
428
return rc; /* error */
430
if (count > 1 && intol) {
432
printf("ERROR: superblocks chain: "
433
"ambivalent result detected (%d filesystems)!\n",
435
return -2; /* error, ambivalent result (more FS) */
438
return 1; /* nothing detected */
441
/* restore the first result */
442
blkid_probe_chain_reset_vals(pr, chn);
443
blkid_probe_append_vals(pr, vals, nvals);
448
* The RAID device could be partitioned. The problem are RAID1 devices
449
* where the partition table is visible from underlaying devices. We
450
* have to ignore such partition tables.
452
if (chn->idx >= 0 && idinfos[chn->idx]->usage & BLKID_USAGE_RAID)
453
pr->prob_flags |= BLKID_PARTS_IGNORE_PT;
458
int blkid_probe_set_magic(blkid_probe pr, blkid_loff_t offset,
459
size_t len, unsigned char *magic)
462
struct blkid_chain *chn = blkid_probe_get_chain(pr);
464
if (magic && len && (chn->flags & BLKID_SUBLKS_MAGIC)) {
465
rc = blkid_probe_set_value(pr, "SBMAGIC", magic, len);
467
rc = blkid_probe_sprintf_value(pr, "SBMAGIC_OFFSET",
473
int blkid_probe_set_version(blkid_probe pr, const char *version)
475
struct blkid_chain *chn = blkid_probe_get_chain(pr);
477
if (chn->flags & BLKID_SUBLKS_VERSION)
478
return blkid_probe_set_value(pr, "VERSION",
479
(unsigned char *) version, strlen(version) + 1);
483
int blkid_probe_sprintf_version(blkid_probe pr, const char *fmt, ...)
485
struct blkid_chain *chn = blkid_probe_get_chain(pr);
488
if (chn->flags & BLKID_SUBLKS_VERSION) {
492
rc = blkid_probe_vsprintf_value(pr, "VERSION", fmt, ap);
498
static int blkid_probe_set_usage(blkid_probe pr, int usage)
500
struct blkid_chain *chn = blkid_probe_get_chain(pr);
503
if (!(chn->flags & BLKID_SUBLKS_USAGE))
506
if (usage & BLKID_USAGE_FILESYSTEM)
508
else if (usage & BLKID_USAGE_RAID)
510
else if (usage & BLKID_USAGE_CRYPTO)
512
else if (usage & BLKID_USAGE_OTHER)
517
return blkid_probe_set_value(pr, "USAGE", (unsigned char *) u, strlen(u) + 1);
520
int blkid_probe_set_label(blkid_probe pr, unsigned char *label, size_t len)
522
struct blkid_chain *chn = blkid_probe_get_chain(pr);
523
struct blkid_prval *v;
524
if (len > BLKID_PROBVAL_BUFSIZ)
525
len = BLKID_PROBVAL_BUFSIZ;
527
if ((chn->flags & BLKID_SUBLKS_LABELRAW) &&
528
blkid_probe_set_value(pr, "LABEL_RAW", label, len) < 0)
530
if (!(chn->flags & BLKID_SUBLKS_LABEL))
532
v = blkid_probe_assign_value(pr, "LABEL");
536
if (len == BLKID_PROBVAL_BUFSIZ)
537
len--; /* make a space for \0 */
539
memcpy(v->data, label, len);
542
v->len = blkid_rtrim_whitespace(v->data) + 1;
544
blkid_probe_reset_last_value(pr);
548
int blkid_probe_set_utf8label(blkid_probe pr, unsigned char *label,
551
struct blkid_chain *chn = blkid_probe_get_chain(pr);
552
struct blkid_prval *v;
554
if ((chn->flags & BLKID_SUBLKS_LABELRAW) &&
555
blkid_probe_set_value(pr, "LABEL_RAW", label, len) < 0)
557
if (!(chn->flags & BLKID_SUBLKS_LABEL))
559
v = blkid_probe_assign_value(pr, "LABEL");
563
blkid_encode_to_utf8(enc, v->data, sizeof(v->data), label, len);
564
v->len = blkid_rtrim_whitespace(v->data) + 1;
566
blkid_probe_reset_last_value(pr);
570
/* like uuid_is_null() from libuuid, but works with arbitrary size of UUID */
571
static int uuid_is_empty(const unsigned char *buf, size_t len)
575
for (i = 0; i < len; i++)
581
int blkid_probe_sprintf_uuid(blkid_probe pr, unsigned char *uuid,
582
size_t len, const char *fmt, ...)
584
struct blkid_chain *chn = blkid_probe_get_chain(pr);
588
if (len > BLKID_PROBVAL_BUFSIZ)
589
len = BLKID_PROBVAL_BUFSIZ;
591
if (uuid_is_empty(uuid, len))
594
if ((chn->flags & BLKID_SUBLKS_UUIDRAW) &&
595
blkid_probe_set_value(pr, "UUID_RAW", uuid, len) < 0)
597
if (!(chn->flags & BLKID_SUBLKS_UUID))
601
rc = blkid_probe_vsprintf_value(pr, "UUID", fmt, ap);
604
/* convert to lower case (..be paranoid) */
607
struct blkid_prval *v = __blkid_probe_get_value(pr,
608
blkid_probe_numof_values(pr));
610
for (i = 0; i < v->len; i++)
611
if (v->data[i] >= 'A' && v->data[i] <= 'F')
612
v->data[i] = (v->data[i] - 'A') + 'a';
618
/* function to set UUIDs that are in suberblocks stored as strings */
619
int blkid_probe_strncpy_uuid(blkid_probe pr, unsigned char *str, size_t len)
621
struct blkid_chain *chn = blkid_probe_get_chain(pr);
622
struct blkid_prval *v;
624
if (str == NULL || *str == '\0')
627
len = strlen((char *) str);
628
if (len > BLKID_PROBVAL_BUFSIZ)
629
len = BLKID_PROBVAL_BUFSIZ;
631
if ((chn->flags & BLKID_SUBLKS_UUIDRAW) &&
632
blkid_probe_set_value(pr, "UUID_RAW", str, len) < 0)
634
if (!(chn->flags & BLKID_SUBLKS_UUID))
637
v = blkid_probe_assign_value(pr, "UUID");
639
if (len == BLKID_PROBVAL_BUFSIZ)
640
len--; /* make a space for \0 */
642
memcpy((char *) v->data, str, len);
650
/* default _set_uuid function to set DCE UUIDs */
651
int blkid_probe_set_uuid_as(blkid_probe pr, unsigned char *uuid, const char *name)
653
struct blkid_chain *chn = blkid_probe_get_chain(pr);
654
struct blkid_prval *v;
656
if (uuid_is_empty(uuid, 16))
660
if ((chn->flags & BLKID_SUBLKS_UUIDRAW) &&
661
blkid_probe_set_value(pr, "UUID_RAW", uuid, 16) < 0)
663
if (!(chn->flags & BLKID_SUBLKS_UUID))
666
v = blkid_probe_assign_value(pr, "UUID");
668
v = blkid_probe_assign_value(pr, name);
670
blkid_unparse_uuid(uuid, (char *) v->data, sizeof(v->data));
676
int blkid_probe_set_uuid(blkid_probe pr, unsigned char *uuid)
678
return blkid_probe_set_uuid_as(pr, uuid, NULL);
682
* DEPRECATED FUNCTIONS
686
* blkid_probe_set_request:
688
* @flags: BLKID_PROBREQ_* (deprecated) or BLKID_SUBLKS_* flags
690
* Returns: 0 on success, or -1 in case of error.
692
* Deprecated: Use blkid_probe_set_superblocks_flags().
694
int blkid_probe_set_request(blkid_probe pr, int flags)
696
return blkid_probe_set_superblocks_flags(pr, flags);
700
* blkid_probe_reset_filter:
703
* Returns: 0 on success, or -1 in case of error.
705
* Deprecated: Use blkid_probe_reset_superblocks_filter().
707
int blkid_probe_reset_filter(blkid_probe pr)
709
return __blkid_probe_reset_filter(pr, BLKID_CHAIN_SUBLKS);
713
* blkid_probe_invert_filter:
716
* Returns: 0 on success, or -1 in case of error.
718
* Deprecated: Use blkid_probe_invert_superblocks_filter().
720
int blkid_probe_invert_filter(blkid_probe pr)
722
return __blkid_probe_invert_filter(pr, BLKID_CHAIN_SUBLKS);
726
* blkid_probe_filter_types
728
* @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
729
* @names: NULL terminated array of probing function names (e.g. "vfat").
731
* Returns: 0 on success, or -1 in case of error.
733
* Deprecated: Use blkid_probe_filter_superblocks_types().
735
int blkid_probe_filter_types(blkid_probe pr, int flag, char *names[])
737
return __blkid_probe_filter_types(pr, BLKID_CHAIN_SUBLKS, flag, names);
741
* blkid_probe_filter_usage
743
* @flag: filter BLKID_FLTR_{NOTIN,ONLYIN} flag
744
* @usage: BLKID_USAGE_* flags
746
* Returns: 0 on success, or -1 in case of error.
748
* Deprecated: Use blkid_probe_filter_superblocks_usage().
750
int blkid_probe_filter_usage(blkid_probe pr, int flag, int usage)
752
return blkid_probe_filter_superblocks_usage(pr, flag, usage);