]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: arch independent minix detection
authorKarel Zak <kzak@redhat.com>
Mon, 15 Apr 2013 13:14:33 +0000 (15:14 +0200)
committerKarel Zak <kzak@redhat.com>
Mon, 15 Apr 2013 13:14:33 +0000 (15:14 +0200)
It seems that on-disk MINIX FS superblock is native-endian.

Addresses: https://bugzilla.redhat.com/show_bug.cgi?id=833841
Signed-off-by: Karel Zak <kzak@redhat.com>
include/minix.h
libblkid/src/superblocks/minix.c

index 57be23921cbbf6ea3ac011f9d2e9381d53761a9c..f28991ce9a18149844dcb4f936cbbb4057e4a4bd 100644 (file)
@@ -73,10 +73,13 @@ struct minix3_super_block {
 #define MINIX_VALID_FS       0x0001          /* Clean fs. */
 #define MINIX_ERROR_FS       0x0002          /* fs has errors. */
 
-#define MINIX_SUPER_MAGIC    0x137F          /* original minix fs */
-#define MINIX_SUPER_MAGIC2   0x138F          /* minix fs, 30 char names */
-#define MINIX2_SUPER_MAGIC   0x2468         /* minix V2 fs */
+
+#define MINIX_SUPER_MAGIC    0x137F          /* minix V1 fs, 14 char names */
+#define MINIX_SUPER_MAGIC2   0x138F          /* minix V1 fs, 30 char names */
+
+#define MINIX2_SUPER_MAGIC   0x2468         /* minix V2 fs, 14 char names */
 #define MINIX2_SUPER_MAGIC2  0x2478         /* minix V2 fs, 30 char names */
+
 #define MINIX3_SUPER_MAGIC   0x4d5a          /* minix V3 fs (60 char names) */
 
 #endif /* UTIL_LINUX_MINIX_H */
index 54e71396bf79f734e9143c97c2b42fcf93207575..0e7cd934f7016aa5c3236c2558262faeb9918dc1 100644 (file)
@@ -3,7 +3,7 @@
  * Copyright (C) 1999, 2000, 2003 by Theodore Ts'o
  * Copyright (C) 2001 by Andreas Dilger
  * Copyright (C) 2004 Kay Sievers <kay.sievers@vrfy.org>
- * Copyright (C) 2008 Karel Zak <kzak@redhat.com>
+ * Copyright (C) 2008-2013 Karel Zak <kzak@redhat.com>
  *
  * This file may be redistributed under the terms of the
  * GNU Lesser General Public License.
 #include "superblocks.h"
 #include "minix.h"
 
-static int probe_minix(blkid_probe pr, const struct blkid_idmag *mag)
+#define minix_swab16(doit, num)        ((uint16_t) (doit ? swab16(num) : num))
+#define minix_swab32(doit, num)        ((uint32_t) (doit ? swab32(num) : num))
+
+static int get_minix_version(const unsigned char *data, int *other_endian)
 {
-       unsigned char *ext;
-       int version;
+       struct minix_super_block *sb = (struct minix_super_block *) data;
+       struct minix3_super_block *sb3 = (struct minix3_super_block *) data;
+       int version = 0;
 
-       /* for more details see magic strings below */
-       switch(mag->magic[1]) {
-       case '\023':
+       *other_endian = 0;
+
+       switch (sb->s_magic) {
+       case MINIX_SUPER_MAGIC:
+       case MINIX_SUPER_MAGIC2:
                version = 1;
                break;
-       case '\044':
+       case MINIX2_SUPER_MAGIC:
+       case MINIX2_SUPER_MAGIC2:
                version = 2;
                break;
-       case '\115':
-               version = 3;
-               break;
        default:
-               return -1;
+               if (sb3->s_magic == MINIX3_SUPER_MAGIC)
+                       version = 3;
                break;
        }
 
+       if (!version) {
+               *other_endian = 1;
+
+               switch (swab16(sb->s_magic)) {
+               case MINIX_SUPER_MAGIC:
+               case MINIX_SUPER_MAGIC2:
+                       version = 1;
+                       break;
+               case MINIX2_SUPER_MAGIC:
+               case MINIX2_SUPER_MAGIC2:
+                       version = 2;
+                       break;
+               default:
+                       if (sb3->s_magic == MINIX3_SUPER_MAGIC)
+                               version = 3;
+                       break;
+               }
+       }
+       if (!version)
+               return -1;
+
+       DBG(LOWPROBE, blkid_debug("minix version %d detected [%s]", version,
+#if defined(WORDS_BIGENDIAN)
+       *other_endian ? "LE" : "BE"
+#else
+       *other_endian ? "BE" : "LE"
+#endif
+       ));
+       return version;
+}
+
+static int probe_minix(blkid_probe pr, const struct blkid_idmag *mag)
+{
+       unsigned char *ext;
+       const unsigned char *data;
+       int version = 0, swabme = 0;
+
+       data = blkid_probe_get_buffer(pr, 1024,
+                       max(sizeof(struct minix_super_block),
+                           sizeof(struct minix3_super_block)));
+       if (!data)
+               return -1;
+       version = get_minix_version(data, &swabme);
+       if (version < 1)
+               return -1;
+
        if (version <= 2) {
-               struct minix_super_block *sb;
-               uint32_t zones;
+               struct minix_super_block *sb = (struct minix_super_block *) data;
+               int zones, ninodes, imaps, zmaps, firstz;
 
-               sb = blkid_probe_get_sb(pr, mag, struct minix_super_block);
-               if (!sb || sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
+               if (sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
                        return -1;
 
-               zones = version == 2 ? sb->s_zones : sb->s_nzones;
+               zones = version == 2 ? minix_swab32(swabme, sb->s_zones) :
+                                      minix_swab16(swabme, sb->s_nzones);
+               ninodes = minix_swab16(swabme, sb->s_ninodes);
+               imaps   = minix_swab16(swabme, sb->s_imap_blocks);
+               zmaps   = minix_swab16(swabme, sb->s_zmap_blocks);
+               firstz  = minix_swab16(swabme, sb->s_firstdatazone);
 
                /* sanity checks to be sure that the FS is really minix */
-               if (sb->s_imap_blocks * MINIX_BLOCK_SIZE * 8 < sb->s_ninodes + 1)
+               if (imaps * MINIX_BLOCK_SIZE * 8 < ninodes + 1)
                        return -1;
-               if (sb->s_zmap_blocks * MINIX_BLOCK_SIZE * 8 < zones - sb->s_firstdatazone + 1)
+               if (zmaps * MINIX_BLOCK_SIZE * 8 < zones - firstz + 1)
                        return -1;
 
        } else if (version == 3) {
-               struct minix3_super_block *sb;
+               struct minix3_super_block *sb = (struct minix3_super_block *) data;
 
-               sb = blkid_probe_get_sb(pr, mag, struct minix3_super_block);
-               if (!sb || sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
+               if (sb->s_imap_blocks == 0 || sb->s_zmap_blocks == 0)
                        return -1;
-
        }
 
        /* unfortunately, some parts of ext3 is sometimes possible to
@@ -78,16 +131,28 @@ const struct blkid_idinfo minix_idinfo =
        .probefunc      = probe_minix,
        .magics         =
        {
-               /* version 1 */
+               /* version 1 - LE */
                { .magic = "\177\023", .len = 2, .kboff = 1, .sboff = 0x10 },
                { .magic = "\217\023", .len = 2, .kboff = 1, .sboff = 0x10 },
 
-               /* version 2 */
+               /* version 1 - BE */
+               { .magic = "\023\177", .len = 2, .kboff = 1, .sboff = 0x10 },
+               { .magic = "\023\217", .len = 2, .kboff = 1, .sboff = 0x10 },
+
+               /* version 2 - LE */
                { .magic = "\150\044", .len = 2, .kboff = 1, .sboff = 0x10 },
                { .magic = "\170\044", .len = 2, .kboff = 1, .sboff = 0x10 },
 
-               /* version 3 */
+               /* version 2 - BE */
+               { .magic = "\044\150", .len = 2, .kboff = 1, .sboff = 0x10 },
+               { .magic = "\044\170", .len = 2, .kboff = 1, .sboff = 0x10 },
+
+               /* version 3 - LE */
                { .magic = "\132\115", .len = 2, .kboff = 1, .sboff = 0x18 },
+
+               /* version 3 - BE */
+               { .magic = "\115\132", .len = 2, .kboff = 1, .sboff = 0x18 },
+
                { NULL }
        }
 };