diff options
Diffstat (limited to 'extras/volume_id')
-rw-r--r-- | extras/volume_id/lib/fat.c | 3 | ||||
-rw-r--r-- | extras/volume_id/lib/libvolume_id-private.h | 1 | ||||
-rw-r--r-- | extras/volume_id/lib/linux_swap.c | 2 | ||||
-rw-r--r-- | extras/volume_id/lib/volume_id.c | 52 |
4 files changed, 52 insertions, 6 deletions
diff --git a/extras/volume_id/lib/fat.c b/extras/volume_id/lib/fat.c index e30318cf09..2d98b65b50 100644 --- a/extras/volume_id/lib/fat.c +++ b/extras/volume_id/lib/fat.c @@ -497,6 +497,7 @@ fat32: found: volume_id_set_usage(id, VOLUME_ID_FILESYSTEM); id->type = "vfat"; - + /* we think this is fat, but we make sure no other signatures are found */ + id->force_unique_result = 1; return 0; } diff --git a/extras/volume_id/lib/libvolume_id-private.h b/extras/volume_id/lib/libvolume_id-private.h index 14f7568fec..1b4a782b65 100644 --- a/extras/volume_id/lib/libvolume_id-private.h +++ b/extras/volume_id/lib/libvolume_id-private.h @@ -120,6 +120,7 @@ struct volume_id { uint8_t *seekbuf; uint64_t seekbuf_off; size_t seekbuf_len; + int force_unique_result; }; /* utils */ diff --git a/extras/volume_id/lib/linux_swap.c b/extras/volume_id/lib/linux_swap.c index c4beeab978..1698e9dbf7 100644 --- a/extras/volume_id/lib/linux_swap.c +++ b/extras/volume_id/lib/linux_swap.c @@ -97,5 +97,7 @@ found_label: found: volume_id_set_usage(id, VOLUME_ID_OTHER); + /* we think this is swap, but we make sure no other signatures are found */ + id->force_unique_result = 1; return 0; } diff --git a/extras/volume_id/lib/volume_id.c b/extras/volume_id/lib/volume_id.c index 8f22509ca6..e4d2ed4cfa 100644 --- a/extras/volume_id/lib/volume_id.c +++ b/extras/volume_id/lib/volume_id.c @@ -369,9 +369,12 @@ int volume_id_probe_raid(struct volume_id *id, uint64_t off, uint64_t size) info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size); - for (i = 0; i < ARRAY_SIZE(prober_raid); i++) - if (prober_raid[i].prober(id, off, size) == 0) + for (i = 0; i < ARRAY_SIZE(prober_raid); i++) { + if (prober_raid[i].prober(id, off, size) == 0) { + info("signature '%s' detected\n", id->type); goto found; + } + } return -1; found: @@ -402,11 +405,50 @@ int volume_id_probe_filesystem(struct volume_id *id, uint64_t off, uint64_t size info("probing at offset 0x%" PRIx64 ", size 0x%" PRIx64 "\n", off, size); - for (i = 0; i < ARRAY_SIZE(prober_filesystem); i++) - if (prober_filesystem[i].prober(id, off, size) == 0) + /* + * We probe for all known filesystems to find conflicting signatures. If + * we find multiple matching signatures and one of the detected filesystem + * types claims that it can not co-exist with any other filesystem type, + * we do not return a probing result. + * + * We can not afford to mount a volume with the wrong filesystem code and + * possibly corrupt it. Linux ssytems have the problem of dozens of possible + * filesystem types, and volumes with left-over signatures from former + * filesystem types. Invalid signature need to be removed from the volume + * to make the filesystem detection successful. + * + * We do not want to read that many bytes from probed floppies, skip volumes + * smaller than a usual floppy disk + */ + if (size > 1440 * 1024) { + int found = 0; + int force_unique_result = 0; + + for (i = 0; i < ARRAY_SIZE(prober_filesystem); i++) { + int match; + + match = (prober_filesystem[i].prober(id, off, size) == 0); + if (match) { + info("signature '%s' detected\n", id->type); + if (id->force_unique_result) + force_unique_result = id->force_unique_result; + if (found && force_unique_result) { + info("conflicting signatures found, skip results\n"); + return -1; + } + found = 1; + } + } + } + + /* return the first match */ + for (i = 0; i < ARRAY_SIZE(prober_filesystem); i++) { + if (prober_filesystem[i].prober(id, off, size) == 0) { + info("signature '%s' detected\n", id->type); goto found; + } + } return -1; - found: /* If recognized, we free the allocated buffers */ volume_id_free_buffer(id); |