]> git.ipfire.org Git - thirdparty/xfsprogs-dev.git/commitdiff
update libdisk
authorEric Sandeen <sandeen@sgi.com>
Wed, 28 Aug 2002 22:31:45 +0000 (22:31 +0000)
committerEric Sandeen <sandeen@sgi.com>
Wed, 28 Aug 2002 22:31:45 +0000 (22:31 +0000)
doc/CHANGES
libdisk/fstype.c
libdisk/fstype.h

index 5f47f7bd3f69c47402e65e7c6fe048ce670d9de9..8d0122b030f5b1ad1671dc0481efe433a113a559 100644 (file)
@@ -1,4 +1,5 @@
 xfsprogs-2.2.3 (28 August 2002)
+       - Update libdisk for a few other filesystems.
        - Fix call to lvdisplay on LVM volumes so that lvdisplay
          always gets the full, real path to the volume, as required.
 
index 51795d621fff1c9778d25e7c4f5b312d7ea4a6d6..a527be91b9c08fc16c17c44a28dcb4591f95c680 100644 (file)
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000-2001 Silicon Graphics, Inc.  All Rights Reserved.
+ * Copyright (c) 2000-2002 Silicon Graphics, Inc.  All Rights Reserved.
  * 
  * This program is free software; you can redistribute it and/or modify it
  * under the terms of version 2 of the GNU General Public License as
  *     - util-linux-2.10o ... 06 Sep 00
  *     - util-linux-2.10r ... 06 Dec 00
  *     - util-linux-2.11g ... 02 Jul 01
+ *     - util-linux-2.11u ... 24 Aug 02
  */
 
 #define SIZE(a) (sizeof(a)/sizeof(a[0]))
 
+/* Most file system types can be recognized by a `magic' number
+   in the superblock.  Note that the order of the tests is
+   significant: by coincidence a filesystem can have the
+   magic numbers for several file system types simultaneously.
+   For example, the romfs magic lives in the 1st sector;
+   xiafs does not touch the 1st sector and has its magic in
+   the 2nd sector; ext2 does not touch the first two sectors. */
+
 static inline unsigned short
 swapped(unsigned short a) {
      return (a>>8) | (a<<8);
 }
 
-static inline int
-assemble4le(unsigned char *p) {
-       return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
-}
-
 /*
     Probes the device and attempts to determine the type of filesystem
     contained within.
 
     Original routine by <jmorriso@bogomips.ww.ubc.ca>; made into a function
     for mount(8) by Mike Grupenhoff <kashmir@umiacs.umd.edu>.
+    Corrected the test for xiafs - aeb
     Read the superblock only once - aeb
-    Added iso9660, romfs, qnx4, udf, swap - aeb
+    Added a very weak heuristic for vfat - aeb
+    Added iso9660, minix-v2, romfs, qnx4, udf, vxfs, swap - aeb
     Added a test for high sierra (iso9660) - quinlan@bucknell.edu
-    Corrected the test for xiafs - aeb
     Added ufs from a patch by jj. But maybe there are several types of ufs?
     Added ntfs from a patch by Richard Russon.
-    Added a very weak heuristic for vfat - aeb
     Added xfs - 2000-03-21 Martin K. Petersen <mkp@linuxcare.com>
     Added cramfs, hfs, hpfs, adfs - Sepp Wijnands <mrrazz@garbage-coderz.net>
     Added ext3 - Andrew Morton
+    Added jfs - Christoph Hellwig
+    Added sysv - Tim Launchbury
+    Added udf - Bryce Nesbitt
 */
 
-/* udf magic - I find that trying to mount garbage as an udf fs
-   causes a very large kernel delay, almost killing the machine.
-   So, we do not try udf unless there is positive evidence that it
-   might work. Try iso9660 first, it is much more likely.
-   Strings below taken from ECMA 167. */
+/*
+ * udf magic - I find that trying to mount garbage as an udf fs
+ * causes a very large kernel delay, almost killing the machine.
+ * So, we do not try udf unless there is positive evidence that it
+ * might work. Strings below taken from ECMA 167.
+ */
+/*
+ * It seems that before udf 2.00 the volume descriptor was not well
+ * defined.  For 2.00 you're supposed to keep scanning records until
+ * you find one NOT in this list.  (See ECMA 2/8.3.1).
+ */
 static char
 *udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
                 "NSR03", "TEA01" };
 
+
 static int
 may_be_udf(const char *id) {
     char **m;
@@ -95,6 +109,43 @@ may_be_udf(const char *id) {
     return 0;
 }
 
+/* we saw "CD001" - may be iso9660 or udf - Bryce Nesbitt */
+static int
+is_really_udf(int fd) {
+       int j, bs;
+       struct iso_volume_descriptor isosb;
+
+       /* determine the block size by scanning in 2K increments
+          (block sizes larger than 2K will be null padded) */
+       for (bs = 1; bs < 16; bs++) {
+               lseek(fd, bs*2048+32768, SEEK_SET);
+               if (read(fd, (char *)&isosb, sizeof(isosb)) != sizeof(isosb))
+                       return 0;
+               if (isosb.id[0])
+                       break;
+       }
+
+       /* Scan up to another 64 blocks looking for additional VSD's */
+       for (j = 1; j < 64; j++) {
+               if (j > 1) {
+                       lseek(fd, j*bs*2048+32768, SEEK_SET);
+                       if (read(fd, (char *)&isosb, sizeof(isosb))
+                           != sizeof(isosb))
+                               return 0;
+               }
+               /* If we find NSR0x then call it udf:
+                  NSR01 for UDF 1.00
+                  NSR02 for UDF 1.50
+                  NSR03 for UDF 2.00 */
+               if (!strncmp(isosb.id, "NSR0", 4))
+                       return 1;
+               if (!may_be_udf(isosb.id))
+                       return 0;
+       }
+
+       return 0;
+}
+
 static int
 may_be_swap(const char *s) {
        return (strncmp(s-10, "SWAP-SPACE", 10) == 0 ||
@@ -131,8 +182,8 @@ fstype(const char *device) {
        struct minix_super_block ms;
        struct ext_super_block es;
        struct ext2_super_block e2s;
-       struct reiserfs_super_block rs;
-    } sb;
+       struct vxfs_super_block vs;
+    } sb;                      /* stuff at 1024 */
     union {
        struct xiafs_super_block xiasb;
        char romfs_magic[8];
@@ -148,67 +199,30 @@ fstype(const char *device) {
        struct iso_volume_descriptor iso;
        struct hs_volume_descriptor hs;
     } isosb;
+    struct reiserfs_super_block reiserfssb;    /* block 64 or 8 */
+    struct jfs_super_block jfssb;              /* block 32 */
     struct hfs_super_block hfssb;
     struct hpfs_super_block hpfssb;
     struct adfs_super_block adfssb;
+    struct sysv_super_block svsb;
     struct stat statbuf;
 
     /* opening and reading an arbitrary unknown path can have
        undesired side effects - first check that `device' refers
-       to a block device */
-    if (stat (device, &statbuf) || !S_ISBLK(statbuf.st_mode))
+       to a block device or ordinary file */
+    if (stat (device, &statbuf) ||
+       !(S_ISBLK(statbuf.st_mode) || S_ISREG(statbuf.st_mode)))
       return 0;
 
     fd = open(device, O_RDONLY);
     if (fd < 0)
       return 0;
 
-    if (lseek(fd, 1024, SEEK_SET) != 1024
-       || read(fd, (char *) &sb, sizeof(sb)) != sizeof(sb))
-        goto io_error;
-
-    /* ext2 has magic in little-endian on disk, so "swapped" is
-       superfluous; however, there have existed strange byteswapped
-       PPC ext2 systems */
-    if (ext2magic(sb.e2s) == EXT2_SUPER_MAGIC
-       || ext2magic(sb.e2s) == EXT2_PRE_02B_MAGIC
-       || ext2magic(sb.e2s) == swapped(EXT2_SUPER_MAGIC)) {
-        type = "ext2";
-
-        /* maybe even ext3? */
-        if ((assemble4le(sb.e2s.s_feature_compat)
-             & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
-            assemble4le(sb.e2s.s_journal_inum) != 0)
-                type = "ext3,ext2";
-    }
-
-    else if (minixmagic(sb.ms) == MINIX_SUPER_MAGIC
-            || minixmagic(sb.ms) == MINIX_SUPER_MAGIC2
-            || minixmagic(sb.ms) == swapped(MINIX_SUPER_MAGIC2))
-        type = "minix";
-
-    else if (extmagic(sb.es) == EXT_SUPER_MAGIC)
-        type = "ext";
-
-    if (!type) {
-       if (lseek(fd, REISERFS_DISK_OFFSET_IN_BYTES, SEEK_SET) !=
-                               REISERFS_DISK_OFFSET_IN_BYTES
-               || read(fd, (char *) &sb, sizeof(sb)) != sizeof(sb))
-           goto io_error;
-       if (is_reiserfs_magic_string(&sb.rs))
-           type = "reiserfs";
-    }
-
-    if (!type) {
-       if (lseek(fd, REISERFS_OLD_DISK_OFFSET_IN_BYTES, SEEK_SET) !=
-                               REISERFS_OLD_DISK_OFFSET_IN_BYTES
-               || read(fd, (char *) &sb, sizeof(sb)) != sizeof(sb))
-           goto io_error;
-       if (is_reiserfs_magic_string(&sb.rs))
-           type = "reiserfs";
-    }
+    /* do seeks and reads in disk order, otherwise a very short
+       partition may cause a failure because of read error */
 
     if (!type) {
+        /* block 0 */
         if (lseek(fd, 0, SEEK_SET) != 0
             || read(fd, (char *) &xsb, sizeof(xsb)) != sizeof(xsb))
              goto io_error;
@@ -220,7 +234,7 @@ fstype(const char *device) {
         else if(!strncmp(xsb.xfsb.s_magic, XFS_SUPER_MAGIC, 4))
              type = "xfs";
         else if(!strncmp(xsb.qnx4fs_magic+4, "QNX4FS", 6))
-             type = "qnx4fs";
+             type = "qnx4";
         else if(xsb.bfs_magic == 0x1badface)
              type = "bfs";
         else if(!strncmp(xsb.ntfssb.s_magic, NTFS_SUPER_MAGIC,
@@ -243,27 +257,51 @@ fstype(const char *device) {
     }
 
     if (!type) {
-        if (lseek(fd, 8192, SEEK_SET) != 8192
-            || read(fd, (char *) &ufssb, sizeof(ufssb)) != sizeof(ufssb))
-             goto io_error;
-
-        if (ufsmagic(ufssb) == UFS_SUPER_MAGIC) /* also test swapped version? */
-             type = "ufs";
+           /* sector 1 */
+           if (lseek(fd, 512 , SEEK_SET) != 512
+               || read(fd, (char *) &svsb, sizeof(svsb)) != sizeof(svsb))
+                   goto io_error;
+           if (sysvmagic(svsb) == SYSV_SUPER_MAGIC )
+                   type = "sysv";
     }
 
     if (!type) {
-        if (lseek(fd, 0x8000, SEEK_SET) != 0x8000
-            || read(fd, (char *) &isosb, sizeof(isosb)) != sizeof(isosb))
-             goto io_error;
-
-        if(strncmp(isosb.iso.id, ISO_STANDARD_ID, sizeof(isosb.iso.id)) == 0
-           || strncmp(isosb.hs.id, HS_STANDARD_ID, sizeof(isosb.hs.id)) == 0)
-             type = "iso9660";
-        else if (may_be_udf(isosb.iso.id))
-             type = "udf";
+       /* block 1 */
+       if (lseek(fd, 1024, SEEK_SET) != 1024 ||
+           read(fd, (char *) &sb, sizeof(sb)) != sizeof(sb))
+               goto io_error;
+
+       /* ext2 has magic in little-endian on disk, so "swapped" is
+          superfluous; however, there have existed strange byteswapped
+          PPC ext2 systems */
+       if (ext2magic(sb.e2s) == EXT2_SUPER_MAGIC ||
+           ext2magic(sb.e2s) == EXT2_PRE_02B_MAGIC ||
+           ext2magic(sb.e2s) == swapped(EXT2_SUPER_MAGIC)) {
+               type = "ext2";
+
+            /* maybe even ext3? */
+            if ((assemble4le(sb.e2s.s_feature_compat)
+                 & EXT3_FEATURE_COMPAT_HAS_JOURNAL) &&
+                assemble4le(sb.e2s.s_journal_inum) != 0)
+                    type = "ext3";     /* "ext3,ext2" */
+       }
+
+       else if (minixmagic(sb.ms) == MINIX_SUPER_MAGIC ||
+                minixmagic(sb.ms) == MINIX_SUPER_MAGIC2 ||
+                minixmagic(sb.ms) == swapped(MINIX_SUPER_MAGIC2) ||
+                minixmagic(sb.ms) == MINIX2_SUPER_MAGIC ||
+                minixmagic(sb.ms) == MINIX2_SUPER_MAGIC2)
+               type = "minix";
+
+       else if (extmagic(sb.es) == EXT_SUPER_MAGIC)
+               type = "ext";
+
+       else if (vxfsmagic(sb.vs) == VXFS_SUPER_MAGIC)
+               type = "vxfs";
     }
 
     if (!type) {
+       /* block 1 */
         if (lseek(fd, 0x400, SEEK_SET) != 0x400
             || read(fd, (char *) &hfssb, sizeof(hfssb)) != sizeof(hfssb))
              goto io_error;
@@ -280,6 +318,44 @@ fstype(const char *device) {
     }
 
     if (!type) {
+       /* block 3 */
+        if (lseek(fd, 0xc00, SEEK_SET) != 0xc00
+            || read(fd, (char *) &adfssb, sizeof(adfssb)) != sizeof(adfssb))
+             goto io_error;
+
+       /* only a weak test */
+        if (may_be_adfs((u_char *) &adfssb)
+            && (adfsblksize(adfssb) >= 8 &&
+                adfsblksize(adfssb) <= 10))
+             type = "adfs";
+    }
+
+    if (!type) {
+        int mag;
+
+        /* block 8 */
+        if (lseek(fd, 8192, SEEK_SET) != 8192
+            || read(fd, (char *) &ufssb, sizeof(ufssb)) != sizeof(ufssb))
+             goto io_error;
+
+        mag = ufsmagic(ufssb);
+        if (mag == UFS_SUPER_MAGIC_LE || mag == UFS_SUPER_MAGIC_BE)
+             type = "ufs";
+    }
+
+    if (!type) {
+       /* block 8 */
+       if (lseek(fd, REISERFS_OLD_DISK_OFFSET_IN_BYTES, SEEK_SET) !=
+                               REISERFS_OLD_DISK_OFFSET_IN_BYTES
+           || read(fd, (char *) &reiserfssb, sizeof(reiserfssb)) !=
+               sizeof(reiserfssb))
+           goto io_error;
+       if (is_reiserfs_magic_string(&reiserfssb))
+           type = "reiserfs";
+    }
+
+    if (!type) {
+       /* block 8 */
         if (lseek(fd, 0x2000, SEEK_SET) != 0x2000
             || read(fd, (char *) &hpfssb, sizeof(hpfssb)) != sizeof(hpfssb))
              goto io_error;
@@ -289,20 +365,47 @@ fstype(const char *device) {
     }
 
     if (!type) {
-        if (lseek(fd, 0xc00, SEEK_SET) != 0xc00
-            || read(fd, (char *) &adfssb, sizeof(adfssb)) != sizeof(adfssb))
-             goto io_error;
+        /* block 32 */
+        if (lseek(fd, JFS_SUPER1_OFF, SEEK_SET) != JFS_SUPER1_OFF
+            || read(fd, (char *) &jfssb, sizeof(jfssb)) != sizeof(jfssb))
+             goto io_error;
+        if (!strncmp(jfssb.s_magic, JFS_MAGIC, 4))
+             type = "jfs";
+    }
 
-       /* only a weak test */
-        if (may_be_adfs((u_char *) &adfssb)
-            && (adfsblksize(adfssb) >= 8 &&
-                adfsblksize(adfssb) <= 10))
-             type = "adfs";
+    if (!type) {
+        /* block 32 */
+        if (lseek(fd, 0x8000, SEEK_SET) != 0x8000
+            || read(fd, (char *) &isosb, sizeof(isosb)) != sizeof(isosb))
+             goto io_error;
+
+        if (strncmp(isosb.hs.id, HS_STANDARD_ID, sizeof(isosb.hs.id)) == 0) {
+                /* "CDROM" */
+                type = "iso9660";
+        } else if (strncmp(isosb.iso.id, ISO_STANDARD_ID,
+                         sizeof(isosb.iso.id)) == 0) {
+                /* CD001 */
+                type = "iso9660";
+                if (is_really_udf(fd))
+                        type = "udf";
+        } else if (may_be_udf(isosb.iso.id))
+                type = "udf";
+    }
+
+    if (!type) {
+       /* block 64 */
+       if (lseek(fd, REISERFS_DISK_OFFSET_IN_BYTES, SEEK_SET) !=
+               REISERFS_DISK_OFFSET_IN_BYTES
+           || read(fd, (char *) &reiserfssb, sizeof(reiserfssb)) !=
+               sizeof(reiserfssb))
+           goto io_error;
+       if (is_reiserfs_magic_string(&reiserfssb))
+           type = "reiserfs";
     }
 
     if (!type) {
            /* perhaps the user tries to mount the swap space
-              on a new disk; warn her before she does mkfs on it */
+              on a new disk; warn her before she does mke2fs on it */
            int pagesize = getpagesize();
            int rd;
            char buf[32768];
index 35579da7fcf540d3d8c27ffc5dbad7896f1a2707..f94a27c1431e906df518a8e9a8048511587d14d7 100644 (file)
@@ -38,6 +38,7 @@
  *      - util-linux-2.10o ... 06 Sep 00
  *      - util-linux-2.10r ... 06 Dec 00
  *      - util-linux-2.11g ... 02 Jul 01
+ *      - util-linux-2.11u ... 24 Aug 02
  */
 
 /* Including <linux/fs.h> became more and more painful.
    only designed to be able to check a magic number
    in case no filesystem type was given. */
 
-#define MINIX_SUPER_MAGIC   0x137F         /* original minix fs */
-#define MINIX_SUPER_MAGIC2  0x138F         /* minix fs, 30 char names */
+#define MINIX_SUPER_MAGIC   0x137F         /* minix v1, 14 char names */
+#define MINIX_SUPER_MAGIC2  0x138F         /* minix v1, 30 char names */
+#define MINIX2_SUPER_MAGIC  0x2468        /* minix v2, 14 char names */
+#define MINIX2_SUPER_MAGIC2 0x2478         /* minix v2, 30 char names */
 struct minix_super_block {
        u_char   s_dummy[16];
        u_char   s_magic[2];
 };
-#define minixmagic(s)  ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8))
+#define minixmagic(s)  assemble2le(s.s_magic)
 
 #define ISODCL(from, to) (to - from + 1)
 #define ISO_STANDARD_ID "CD001"
@@ -76,7 +79,7 @@ struct ext_super_block {
        u_char   s_dummy[56];
        u_char   s_magic[2];
 };
-#define extmagic(s)    ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8))
+#define extmagic(s)    assemble2le(s.s_magic)
 
 #define EXT2_PRE_02B_MAGIC  0xEF51
 #define EXT2_SUPER_MAGIC    0xEF53
@@ -93,7 +96,7 @@ struct ext2_super_block {
        u_char  s_dummy3[88];
        u_char  s_journal_inum[4];      /* ext3 only */
 };
-#define ext2magic(s)   ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8))
+#define ext2magic(s)   assemble2le(s.s_magic)
 
 struct reiserfs_super_block
 {
@@ -126,19 +129,16 @@ struct xiafs_super_block {
     u_char     s_dummy[60];
     u_char     s_magic[4];
 };
-#define xiafsmagic(s)  ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8) + \
-                       (((uint) s.s_magic[2]) << 16) + \
-                       (((uint) s.s_magic[3]) << 24))
+#define xiafsmagic(s)  assemble4le(s.s_magic)
 
 /* From jj@sunsite.ms.mff.cuni.cz Mon Mar 23 15:19:05 1998 */
-#define UFS_SUPER_MAGIC 0x00011954
+#define UFS_SUPER_MAGIC_LE 0x00011954
+#define UFS_SUPER_MAGIC_BE 0x54190100
 struct ufs_super_block {
     u_char     s_dummy[0x55c];
     u_char     s_magic[4];
 };
-#define ufsmagic(s)    ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8) + \
-                        (((uint) s.s_magic[2]) << 16) + \
-                        (((uint) s.s_magic[3]) << 24))
+#define ufsmagic(s)    assemble4le(s.s_magic)
 
 /* From Richard.Russon@ait.co.uk Wed Feb 24 08:05:27 1999 */
 #define NTFS_SUPER_MAGIC "NTFS"
@@ -179,9 +179,7 @@ struct cramfs_super_block {
        u_char    s_dummy[12];
        u_char    s_id[16];
 };
-#define cramfsmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8) + \
-                        (((uint) s.s_magic[2]) << 16) + \
-                        (((uint) s.s_magic[3]) << 24))
+#define cramfsmagic(s) assemble4le(s.s_magic)
 
 #define HFS_SUPER_MAGIC 0x4244
 struct hfs_super_block {
@@ -189,20 +187,15 @@ struct hfs_super_block {
        u_char    s_dummy[18];
        u_char    s_blksize[4];
 };
-#define hfsmagic(s)    ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8))
-#define hfsblksize(s)  ((uint) s.s_blksize[0] + \
-                        (((uint) s.s_blksize[1]) << 8) + \
-                        (((uint) s.s_blksize[2]) << 16) + \
-                        (((uint) s.s_blksize[3]) << 24))
+#define hfsmagic(s)    assemble2le(s.s_magic)
+#define hfsblksize(s)  assemble4le(s.s_blksize)
 
 #define HPFS_SUPER_MAGIC 0xf995e849
 struct hpfs_super_block {
        u_char    s_magic[4];
        u_char    s_magic2[4];
 };
-#define hpfsmagic(s)   ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8) + \
-                        (((uint) s.s_magic[2]) << 16) + \
-                        (((uint) s.s_magic[3]) << 24))
+#define hpfsmagic(s)   assemble4le(s.s_magic)
 
 struct adfs_super_block {
        u_char    s_dummy[448];
@@ -211,3 +204,46 @@ struct adfs_super_block {
        u_char    s_checksum[1];
 };
 #define adfsblksize(s) ((uint) s.s_blksize[0])
+
+/* found in first 4 bytes of block 1 */
+struct vxfs_super_block {
+       u_char  s_magic[4];
+};
+#define vxfsmagic(s)   assemble4le(s.s_magic)
+#define VXFS_SUPER_MAGIC 0xa501FCF5
+
+struct jfs_super_block {
+       char    s_magic[4];
+       u_char  s_version[4];
+       u_char  s_dummy1[93];
+       char    s_fpack[11];
+       u_char  s_dummy2[24];
+       u_char  s_uuid[16];
+       char    s_label[16];
+};
+#define JFS_SUPER1_OFF 0x8000
+#define JFS_MAGIC "JFS1"
+
+struct sysv_super_block {
+       u_char  s_dummy1[504];
+       u_char  s_magic[4];
+       u_char  type[4];
+};
+#define sysvmagic(s)           assemble4le(s.s_magic)
+#define SYSV_SUPER_MAGIC       0xfd187e20
+
+struct mdp_super_block {
+       u_char  md_magic[4];
+};
+#define MD_SB_MAGIC    0xa92b4efc
+#define mdsbmagic(s)   assemble4le(s.md_magic)
+
+static inline int
+assemble2le(unsigned char *p) {
+       return (p[0] | (p[1] << 8));
+}
+
+static inline int
+assemble4le(unsigned char *p) {
+       return (p[0] | (p[1] << 8) | (p[2] << 16) | (p[3] << 24));
+}