]> err.no Git - util-linux/commitdiff
blkid: add blkid_do_safeprobe()
authorKarel Zak <kzak@redhat.com>
Tue, 27 Jan 2009 16:25:06 +0000 (17:25 +0100)
committerKarel Zak <kzak@redhat.com>
Wed, 11 Feb 2009 22:35:25 +0000 (23:35 +0100)
The function blkid_do_probe() is able to detect more filesystems on
the device

while(blkid_do_probe(pr) == 0)
...

but in many cases we need only one exact answer, and we also need to
be sure that there is not any other FS on the device.

For example it's possible to create valid LUKS (or vfat, ...) header
and valid linux swap header on the same device -- in such case the
device can be interpreted (by mount/swapon) in two completely
different ways. An ambivalent result is always error -- the library
never returns such result.

Signed-off-by: Karel Zak <kzak@redhat.com>
libs/blkid/bin/blkid.c
libs/blkid/src/blkid.h
libs/blkid/src/blkid.sym
libs/blkid/src/blkidP.h
libs/blkid/src/probe.c
libs/blkid/src/probers/iso9660.c
libs/blkid/src/probers/udf.c
libs/blkid/src/verify.c

index e65fdaff3683770450e76f311a1120d625548687..f7b43a496685671f583e4e12f6c9f5cbbb9b7ca6 100644 (file)
@@ -319,6 +319,7 @@ static int lowprobe_device(blkid_probe pr, const char *devname, int output,
        int nvals, n;
        size_t len;
        int fd;
+       int rc = 0;
 
        fd = open(devname, O_RDONLY);
        if (fd < 0) {
@@ -328,7 +329,8 @@ static int lowprobe_device(blkid_probe pr, const char *devname, int output,
 
        if (blkid_probe_set_device(pr, fd, offset, size))
                goto error;
-       if (blkid_do_probe(pr))
+       rc = blkid_do_safeprobe(pr);
+       if (rc)
                goto error;
 
        nvals = blkid_probe_numof_values(pr);
@@ -341,8 +343,13 @@ static int lowprobe_device(blkid_probe pr, const char *devname, int output,
                print_value(output, n + 1, NULL, (char *) data, name, len);
        }
 
+       close(fd);
        return 0;
 error:
+       if (rc == -2)
+               fprintf(stderr, "%s: ambivalent result "
+                               "(probably more filesystems on the device)\n",
+                               devname);
        close(fd);
        return -1;
 }
index 26f04b897673cf9cd6c6ea623cc776eafc4aa65e..823eaeb35d9dc911ce064f46b78546ae663b6c7e 100644 (file)
@@ -150,6 +150,8 @@ extern int blkid_probe_invert_filter(blkid_probe pr);
 extern int blkid_probe_reset_filter(blkid_probe pr);
 
 extern int blkid_do_probe(blkid_probe pr);
+extern int blkid_do_safeprobe(blkid_probe pr);
+
 extern int blkid_probe_numof_values(blkid_probe pr);
 extern int blkid_probe_get_value(blkid_probe pr, int num, const char **name,
                         unsigned char **data, size_t *len);
index 105f3ff9b52936c0c01d36c88972c72775a3e45f..257d7c1abc89aa30d627dafa14b7d6a7d1594bbf 100644 (file)
@@ -7,6 +7,7 @@
        blkid_devno_to_devname;
        blkid_dev_set_search;
        blkid_do_probe;
+       blkid_do_safeprobe;
        blkid_encode_string;
        blkid_find_dev_with_tag;
        blkid_free_probe;
index 2631966a119432b9247ad54d29f399e1d141c731..f10c7474970d6cb94e167ccfc67e29dcc9c885ad 100644 (file)
@@ -134,10 +134,11 @@ struct blkid_idmag
  */
 struct blkid_idinfo
 {
-       const char      *name;                  /* FS/RAID name */
-       int             usage;                  /* BLKID_USAGE_* flag */
+       const char      *name;          /* FS/RAID name */
+       int             usage;          /* BLKID_USAGE_* flag */
+       int             flags;          /* BLKID_IDINFO_* flags */
 
-                                               /* probe function */
+                                       /* probe function */
        int             (*probefunc)(blkid_probe pr, const struct blkid_idmag *mag);
 
        struct blkid_idmag      magics[];       /* NULL or array with magic strings */
@@ -145,6 +146,13 @@ struct blkid_idinfo
 
 #define BLKID_NONE_MAGIC       {{ NULL }}
 
+/*
+ * tolerant FS - can share the same device with more filesystems (e.g. typical
+ * on CD-ROMs). We need this flag to detect ambivalent results (e.g. valid fat
+ * and valid linux swap on the same device).
+ */
+#define BLKID_IDINFO_TOLERANT  (1 << 1)
+
 /*
  * Minimum number of seconds between device probes, even when reading
  * from the cache.  This is to avoid re-probing all devices which were
index c9f88b058f013e8d6b5877859305d0d73ba1c3cd..c8731ded0e6d3f1e351fc35fddb0476dc027816e 100644 (file)
@@ -169,6 +169,7 @@ void blkid_reset_probe(blkid_probe pr)
                memset(pr->buf, 0, pr->buf_max);
        pr->buf_off = 0;
        pr->buf_len = 0;
+       pr->idx = 0;
        if (pr->sbbuf)
                memset(pr->sbbuf, 0, BLKID_SB_BUFSIZ);
        pr->sbbuf_len = 0;
@@ -448,7 +449,7 @@ int blkid_do_probe(blkid_probe pr)
 
        DBG(DEBUG_LOWPROBE, printf("*** starting probing loop\n"));
 
-       for (i = 0; i < ARRAY_SIZE(idinfos); i++) {
+       for ( ; i < ARRAY_SIZE(idinfos); i++) {
                const struct blkid_idinfo *id;
                const struct blkid_idmag *mag;
                int hasmag = 0;
@@ -510,6 +511,44 @@ int blkid_do_probe(blkid_probe pr)
        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.
+ */
+int blkid_do_safeprobe(blkid_probe pr)
+{
+       struct blkid_struct_probe first;
+       int count = 0;
+       int intol = 0;
+       int rc;
+
+       while ((rc = blkid_do_probe(pr)) == 0) {
+               if (!count) {
+                       /* store the fist result */
+                       memcpy(first.vals, pr->vals, sizeof(first.vals));
+                       first.nvals = pr->nvals;
+                       first.idx = pr->idx;
+               }
+               if (!(idinfos[pr->idx]->flags & BLKID_IDINFO_TOLERANT))
+                       intol++;
+               count++;
+       }
+       if (rc < 0)
+               return rc;              /* error */
+       if (count > 1 && intol)
+               return -2;              /* error, ambivalent result (more FS) */
+       if (!count)
+               return 1;               /* nothing detected */
+
+       /* restore the first result */
+       memcpy(pr->vals, first.vals, sizeof(first.vals));
+       pr->nvals = first.nvals;
+       pr->idx = first.idx;
+
+       return 0;
+}
+
 int blkid_probe_numof_values(blkid_probe pr)
 {
        if (!pr)
index 759b6aea4b9ec901220e05325f4dde6bcfcedb75..ca53e3ae444f520102c62dcc56d4f808d86e4170 100644 (file)
@@ -122,6 +122,7 @@ const struct blkid_idinfo iso9660_idinfo =
        .name           = "iso9660",
        .usage          = BLKID_USAGE_FILESYSTEM,
        .probefunc      = probe_iso9660,
+       .flags          = BLKID_IDINFO_TOLERANT,
        .magics         =
        {
                { .magic = "CD001", .len = 5, .kboff = 32, .sboff = 1 },
index de35b1a0e0f7edb197cc39f995e889e5e485a798..5f4046d6d952d32544257fefd25d6f683c7e694a 100644 (file)
@@ -144,6 +144,7 @@ const struct blkid_idinfo udf_idinfo =
        .name           = "udf",
        .usage          = BLKID_USAGE_FILESYSTEM,
        .probefunc      = probe_udf,
+       .flags          = BLKID_IDINFO_TOLERANT,
        .magics         =
        {
                { .magic = "BEA01", .len = 5, .kboff = 32, .sboff = 1 },
index 8892820d38e359cae3e6adb66dde67c2b2be03a0..7f795a4266293cf46c9834fcc3b783c9e08131a1 100644 (file)
@@ -141,8 +141,8 @@ blkid_dev blkid_verify(blkid_cache cache, blkid_dev dev)
        /*
         * Probe for all types.
         */
-       if (blkid_do_probe(cache->probe)) {
-               /* found nothing */
+       if (blkid_do_safeprobe(cache->probe)) {
+               /* found nothing or error */
                blkid_free_dev(dev);
                dev = NULL;
        }