From: Karel Zak Date: Tue, 27 Jan 2009 16:25:06 +0000 (+0100) Subject: blkid: add blkid_do_safeprobe() X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=a2f01a1c0ba7e8d6f546133195ee759715ef42f7;p=util-linux blkid: add blkid_do_safeprobe() 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 --- diff --git a/libs/blkid/bin/blkid.c b/libs/blkid/bin/blkid.c index e65fdaff..f7b43a49 100644 --- a/libs/blkid/bin/blkid.c +++ b/libs/blkid/bin/blkid.c @@ -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; } diff --git a/libs/blkid/src/blkid.h b/libs/blkid/src/blkid.h index 26f04b89..823eaeb3 100644 --- a/libs/blkid/src/blkid.h +++ b/libs/blkid/src/blkid.h @@ -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); diff --git a/libs/blkid/src/blkid.sym b/libs/blkid/src/blkid.sym index 105f3ff9..257d7c1a 100644 --- a/libs/blkid/src/blkid.sym +++ b/libs/blkid/src/blkid.sym @@ -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; diff --git a/libs/blkid/src/blkidP.h b/libs/blkid/src/blkidP.h index 2631966a..f10c7474 100644 --- a/libs/blkid/src/blkidP.h +++ b/libs/blkid/src/blkidP.h @@ -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 diff --git a/libs/blkid/src/probe.c b/libs/blkid/src/probe.c index c9f88b05..c8731ded 100644 --- a/libs/blkid/src/probe.c +++ b/libs/blkid/src/probe.c @@ -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) diff --git a/libs/blkid/src/probers/iso9660.c b/libs/blkid/src/probers/iso9660.c index 759b6aea..ca53e3ae 100644 --- a/libs/blkid/src/probers/iso9660.c +++ b/libs/blkid/src/probers/iso9660.c @@ -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 }, diff --git a/libs/blkid/src/probers/udf.c b/libs/blkid/src/probers/udf.c index de35b1a0..5f4046d6 100644 --- a/libs/blkid/src/probers/udf.c +++ b/libs/blkid/src/probers/udf.c @@ -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 }, diff --git a/libs/blkid/src/verify.c b/libs/blkid/src/verify.c index 8892820d..7f795a42 100644 --- a/libs/blkid/src/verify.c +++ b/libs/blkid/src/verify.c @@ -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; }