From 0e89abac8b8ba5badbea987fc3a578c31a6fe3c4 Mon Sep 17 00:00:00 2001 From: Karel Zak Date: Tue, 15 Sep 2009 21:38:46 +0200 Subject: [PATCH] libblkid: add superblocks chain Signed-off-by: Karel Zak --- shlibs/blkid/src/superblocks/Makefile.am | 1 + shlibs/blkid/src/superblocks/superblocks.c | 301 +++++++++++++++++++++ 2 files changed, 302 insertions(+) create mode 100644 shlibs/blkid/src/superblocks/superblocks.c diff --git a/shlibs/blkid/src/superblocks/Makefile.am b/shlibs/blkid/src/superblocks/Makefile.am index 07508702..16e8d1b5 100644 --- a/shlibs/blkid/src/superblocks/Makefile.am +++ b/shlibs/blkid/src/superblocks/Makefile.am @@ -5,6 +5,7 @@ AM_CPPFLAGS += -I$(ul_libblkid_srcdir) noinst_LTLIBRARIES = libblkid_superblocks.la libblkid_superblocks_la_SOURCES = \ superblocks.h \ + superblocks.c \ cramfs.c \ swap.c \ adaptec_raid.c \ diff --git a/shlibs/blkid/src/superblocks/superblocks.c b/shlibs/blkid/src/superblocks/superblocks.c new file mode 100644 index 00000000..31c601d4 --- /dev/null +++ b/shlibs/blkid/src/superblocks/superblocks.c @@ -0,0 +1,301 @@ +/* + * superblocks.c - reads information from filesystem and raid superblocks + * + * Copyright (C) 2008-2009 Karel Zak + * + * This file may be redistributed under the terms of the + * GNU Lesser General Public License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "blkdev.h" +#include "blkidP.h" + +#include "superblocks.h" + +/** + * SECTION:superblocks + * @title: Superblocks probing + * @short_description: filesystems and raids superblocks probing. + * + * The library API has been originaly designed for superblocks probing only. + * This is reason why some *deprecated* superblock specific functions don't use + * '_superblocks_' namespace in the function name. Please, don't use these + * functions in new code. + * + * The 'superblocks' probers support NAME=value (tags) interface only. The + * superblocks probing is enabled by default (and controled by + * blkid_probe_enable_superblocks()). + * + * Currently supported tags: + * + * @TYPE: filesystem type + * + * @SEC_TYPE: secondary filesystem type + * + * @LABEL: filesystem label + * + * @LABEL_RAW: raw label from FS superblock + * + * @UUID: filesystem UUID (lower case) + * + * @UUID_RAW: raw UUID from FS superblock + * + * @EXT_JOURNAL: external journal UUID + * + * @USAGE: usage string: "raid", "filesystem", ... + * + * @VERSION: filesystem version + * + * @MOUNT: cluster mount name (?) -- ocfs only + * + * @SBMAGIC: super block magic string [not-implemented yet] + * + * @SBOFFSET: offset of superblock [not-implemented yet] + * + * @FSSIZE: size of filessystem [not-implemented yet] + */ + +static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn); +static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn); + +static int blkid_probe_set_usage(blkid_probe pr, int usage); + + +/* + * Superblocks chains probing functions + */ +static const struct blkid_idinfo *idinfos[] = +{ + /* RAIDs */ + &linuxraid_idinfo, + &ddfraid_idinfo, + &iswraid_idinfo, + &lsiraid_idinfo, + &viaraid_idinfo, + &silraid_idinfo, + &nvraid_idinfo, + &pdcraid_idinfo, + &highpoint45x_idinfo, + &highpoint37x_idinfo, + &adraid_idinfo, + &jmraid_idinfo, + &lvm2_idinfo, + &lvm1_idinfo, + &snapcow_idinfo, + &luks_idinfo, + + /* Filesystems */ + &vfat_idinfo, + &swsuspend_idinfo, + &swap_idinfo, + &xfs_idinfo, + &ext4dev_idinfo, + &ext4_idinfo, + &ext3_idinfo, + &ext2_idinfo, + &jbd_idinfo, + &reiser_idinfo, + &reiser4_idinfo, + &jfs_idinfo, + &udf_idinfo, + &iso9660_idinfo, + &zfs_idinfo, + &hfsplus_idinfo, + &hfs_idinfo, + &ufs_idinfo, + &hpfs_idinfo, + &sysv_idinfo, + &xenix_idinfo, + &ntfs_idinfo, + &cramfs_idinfo, + &romfs_idinfo, + &minix_idinfo, + &gfs_idinfo, + &gfs2_idinfo, + &ocfs_idinfo, + &ocfs2_idinfo, + &oracleasm_idinfo, + &vxfs_idinfo, + &squashfs_idinfo, + &netware_idinfo, + &btrfs_idinfo +}; + +/* + * Driver definition + */ +const struct blkid_chaindrv superblocks_drv = { + .id = BLKID_CHAIN_SUBLKS, + .name = "superblocks", + .dflt_enabled = TRUE, + .dflt_flags = BLKID_SUBLKS_DEFAULT, + .idinfos = idinfos, + .nidinfos = ARRAY_SIZE(idinfos), + .has_fltr = TRUE, + .probe = superblocks_probe, + .safeprobe = superblocks_safeprobe +}; + + +/* + * The blkid_do_probe() backend. + */ +static int superblocks_probe(blkid_probe pr, struct blkid_chain *chn) +{ + int i = 0; + + if (!pr || chn->idx < -1) + return -1; + if (chn->idx < -1) + return -1; + blkid_probe_chain_reset_vals(pr, chn); + + DBG(DEBUG_LOWPROBE, + printf("--> starting probing loop [SUBLKS idx=%d]\n", + chn->idx)); + + i = chn->idx + 1; + + for ( ; i < ARRAY_SIZE(idinfos); i++) { + const struct blkid_idinfo *id; + const struct blkid_idmag *mag; + int hasmag = 0; + + chn->idx = i; + + if (chn->fltr && blkid_bmp_get_item(chn->fltr, i)) + continue; + + id = idinfos[i]; + mag = id->magics ? &id->magics[0] : NULL; + + /* try to detect by magic string */ + while(mag && mag->magic) { + blkid_loff_t off; + unsigned char *buf; + + off = mag->kboff + ((blkid_loff_t) mag->sboff >> 10); + buf = blkid_probe_get_buffer(pr, off << 10, 1024); + + if (buf && !memcmp(mag->magic, + buf + (mag->sboff & 0x3ff), mag->len)) { + DBG(DEBUG_LOWPROBE, printf( + "%s: magic sboff=%u, kboff=%ld\n", + id->name, mag->sboff, mag->kboff)); + hasmag = 1; + break; + } + mag++; + } + + if (hasmag == 0 && id->magics && id->magics[0].magic) + /* magic string(s) defined, but not found */ + continue; + + /* final check by probing function */ + if (id->probefunc) { + DBG(DEBUG_LOWPROBE, printf( + "%s: call probefunc()\n", id->name)); + if (id->probefunc(pr, mag) != 0) + continue; + } + + /* all cheks passed */ + if (chn->flags & BLKID_SUBLKS_TYPE) + blkid_probe_set_value(pr, "TYPE", + (unsigned char *) id->name, + strlen(id->name) + 1); + if (chn->flags & BLKID_SUBLKS_USAGE) + blkid_probe_set_usage(pr, id->usage); + + DBG(DEBUG_LOWPROBE, + printf("<-- leaving probing loop (type=%s) [SUBLKS idx=%d]\n", + id->name, chn->idx)); + return 0; + } + DBG(DEBUG_LOWPROBE, + printf("<-- leaving probing loop (failed) [SUBLKS idx=%d]\n", + chn->idx)); + return 1; +} + +/* + * This is the same function as blkid_do_probe(), but returns only one result + * (cannot be used in while()) and checks for ambivalen results (more + * filesystems on the device) -- in such case returns -2. + * + * The function does not check for filesystems when a RAID signature is + * detected. The function also does not check for collision between RAIDs. The + * first detected RAID is returned. + */ +static int superblocks_safeprobe(blkid_probe pr, struct blkid_chain *chn) +{ + struct blkid_prval vals[BLKID_NVALS_SUBLKS]; + int nvals = BLKID_NVALS_SUBLKS; + int idx = -1; + int count = 0; + int intol = 0; + int rc; + + while ((rc = superblocks_probe(pr, chn)) == 0) { + if (!count) { + /* save the first result */ + nvals = blkid_probe_chain_copy_vals(pr, chn, vals, nvals); + idx = chn->idx; + } + count++; + + if (idinfos[chn->idx]->usage & BLKID_USAGE_RAID) + break; + if (!(idinfos[chn->idx]->flags & BLKID_IDINFO_TOLERANT)) + intol++; + } + if (rc < 0) + return rc; /* error */ + if (count > 1 && intol) { + DBG(DEBUG_LOWPROBE, + printf("ERROR: superblocks chain: " + "ambivalent result detected (%d filesystems)!\n", + count)); + return -2; /* error, ambivalent result (more FS) */ + } + if (!count) + return 1; /* nothing detected */ + + /* restore the first result */ + blkid_probe_chain_reset_vals(pr, chn); + blkid_probe_append_vals(pr, vals, nvals); + chn->idx = idx; + + return 0; +} + +static int blkid_probe_set_usage(blkid_probe pr, int usage) +{ + char *u = NULL; + + if (usage & BLKID_USAGE_FILESYSTEM) + u = "filesystem"; + else if (usage & BLKID_USAGE_RAID) + u = "raid"; + else if (usage & BLKID_USAGE_CRYPTO) + u = "crypto"; + else if (usage & BLKID_USAGE_OTHER) + u = "other"; + else + u = "unknown"; + + return blkid_probe_set_value(pr, "USAGE", (unsigned char *) u, strlen(u) + 1); +} -- 2.39.5