/*
- * 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;
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 ||
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];
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;
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,
}
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;
}
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;
}
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];
* - 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"
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
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
{
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"
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 {
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];
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));
+}