From: Eric Sandeen Date: Wed, 28 Aug 2002 22:31:45 +0000 (+0000) Subject: update libdisk X-Git-Tag: v2.3.0~4 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=ebf3db3ae73626f0c32fee9dd523947a485a19e8;p=thirdparty%2Fxfsprogs-dev.git update libdisk --- diff --git a/doc/CHANGES b/doc/CHANGES index 5f47f7bd3..8d0122b03 100644 --- a/doc/CHANGES +++ b/doc/CHANGES @@ -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. diff --git a/libdisk/fstype.c b/libdisk/fstype.c index 51795d621..a527be91b 100644 --- a/libdisk/fstype.c +++ b/libdisk/fstype.c @@ -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 @@ -44,47 +44,61 @@ * - 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 ; made into a function for mount(8) by Mike Grupenhoff . + 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 Added cramfs, hfs, hpfs, adfs - Sepp Wijnands 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]; diff --git a/libdisk/fstype.h b/libdisk/fstype.h index 35579da7f..f94a27c14 100644 --- a/libdisk/fstype.h +++ b/libdisk/fstype.h @@ -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 became more and more painful. @@ -45,13 +46,15 @@ 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)); +}