]> err.no Git - util-linux/commitdiff
libblkid: add superblocks chain
authorKarel Zak <kzak@redhat.com>
Tue, 15 Sep 2009 19:38:46 +0000 (21:38 +0200)
committerKarel Zak <kzak@redhat.com>
Wed, 16 Sep 2009 08:56:46 +0000 (10:56 +0200)
Signed-off-by: Karel Zak <kzak@redhat.com>
shlibs/blkid/src/superblocks/Makefile.am
shlibs/blkid/src/superblocks/superblocks.c [new file with mode: 0644]

index 07508702fdcb0c8b05d1fb57702929282ae88d4e..16e8d1b569791a696d7a59c3eccb2e670bb7b619 100644 (file)
@@ -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 (file)
index 0000000..31c601d
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * superblocks.c - reads information from filesystem and raid superblocks
+ *
+ * Copyright (C) 2008-2009 Karel Zak <kzak@redhat.com>
+ *
+ * This file may be redistributed under the terms of the
+ * GNU Lesser General Public License.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <stdint.h>
+#include <stdarg.h>
+
+#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);
+}