]> err.no Git - util-linux/commitdiff
libblkid: more robust minix probing
authorKarel Zak <kzak@redhat.com>
Wed, 27 Jan 2010 14:01:13 +0000 (15:01 +0100)
committerKarel Zak <kzak@redhat.com>
Tue, 16 Feb 2010 08:58:57 +0000 (09:58 +0100)
Signed-off-by: Karel Zak <kzak@redhat.com>
shlibs/blkid/src/superblocks/minix.c

index 784f0758a03ca43fa62bdfdbe4d86a28420f7f12..7b314abc9e548e7d55be05eed0f47775ca6991ae 100644 (file)
 
 #include "superblocks.h"
 
+struct minix_super_block {
+        uint16_t s_ninodes;
+        uint16_t s_nzones;
+        uint16_t s_imap_blocks;
+        uint16_t s_zmap_blocks;
+        uint16_t s_firstdatazone;
+        uint16_t s_log_zone_size;
+        uint32_t s_max_size;
+        uint16_t s_magic;
+        uint16_t s_state;
+        uint32_t s_zones;
+};
+
+struct minix3_super_block {
+       uint32_t s_ninodes;
+       uint16_t s_pad0;
+       uint16_t s_imap_blocks;
+       uint16_t s_zmap_blocks;
+       uint16_t s_firstdatazone;
+       uint16_t s_log_zone_size;
+       uint16_t s_pad1;
+       uint32_t s_max_size;
+       uint32_t s_zones;
+       uint16_t s_magic;
+       uint16_t s_pad2;
+       uint16_t s_blocksize;
+       uint8_t  s_disk_version;
+};
+
+#define MINIX_BLOCK_SIZE_BITS 10
+#define MINIX_BLOCK_SIZE (1 << MINIX_BLOCK_SIZE_BITS)
+
 static int probe_minix(blkid_probe pr, const struct blkid_idmag *mag)
 {
+       int version;
+
        /* for more details see magic strings below */
        switch(mag->magic[1]) {
        case '\023':
-               blkid_probe_set_version(pr, "1");
+               version = 1;
                break;
        case '\044':
-               blkid_probe_set_version(pr, "2");
+               version = 2;
                break;
        case '\115':
-               blkid_probe_set_version(pr, "3");
+               version = 3;
                break;
+       default:
+               return -1;
+               break;
+       }
+
+       if (version <= 2) {
+               struct minix_super_block *sb;
+               uint32_t zones;
+
+               sb = blkid_probe_get_sb(pr, mag, struct minix_super_block);
+               if (!sb || sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
+                       return -1;
+
+               zones = version == 2 ? sb->s_zones : sb->s_nzones;
+
+               /* sanity checks to be sure that the FS is really minix */
+               if (sb->s_imap_blocks * MINIX_BLOCK_SIZE * 8 < sb->s_ninodes + 1)
+                       return -1;
+               if (sb->s_zmap_blocks * MINIX_BLOCK_SIZE * 8 < zones - sb->s_firstdatazone + 1)
+                       return -1;
+
+       } else if (version == 3) {
+               struct minix3_super_block *sb;
+
+               sb = blkid_probe_get_sb(pr, mag, struct minix3_super_block);
+               if (!sb || sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
+                       return -1;
+
        }
+
+       blkid_probe_sprintf_version(pr, "%d", version);
        return 0;
 }