diff options
Diffstat (limited to 'mount/mount_guess_fstype.c')
-rw-r--r-- | mount/mount_guess_fstype.c | 109 |
1 files changed, 90 insertions, 19 deletions
diff --git a/mount/mount_guess_fstype.c b/mount/mount_guess_fstype.c index 8e8207223..9e3a54a48 100644 --- a/mount/mount_guess_fstype.c +++ b/mount/mount_guess_fstype.c @@ -13,6 +13,9 @@ * * Wed Nov 11 11:33:55 1998: K.Garloff@ping.de, try /etc/filesystems before * /proc/filesystems + * [This was mainly in order to specify vfat before fat; these days we often + * detect *fat and then assume vfat, so perhaps /etc/filesystems isnt + * so useful anymore.] * * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org> * - added Native Language Support @@ -67,12 +70,17 @@ swapped(unsigned short a) { 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 qnx4 - aeb + Added swap - aeb - Currently supports: minix, ext, ext2, xiafs, iso9660, romfs, ufs, ntfs, vfat + Currently supports: minix, ext, ext2, xiafs, iso9660, romfs, + ufs, ntfs, vfat, qnx4, bfs */ static char *magic_known[] = { "minix", "ext", "ext2", "xiafs", "iso9660", "romfs", - "ufs", "ntfs" }; + "ufs", "ntfs", "qnx4", "bfs", "udf", + "swap" /* last - just to warn the user */ +}; static int tested(const char *device) { @@ -84,6 +92,32 @@ tested(const char *device) { return 0; } +/* 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. */ +static char +*udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02", + "NSR03", "TEA01" }; + +static int +may_be_udf(const char *id) { + char **m; + + for (m = udf_magic; m - udf_magic < SIZE(udf_magic); m++) + if (!strncmp(*m, id, 5)) + return 1; + return 0; +} + +static int +may_be_swap(const char *s) { + return (strncmp(s-10, "SWAP-SPACE", 10) == 0 || + strncmp(s-10, "SWAPSPACE2", 10) == 0); +} + static char * fstype(const char *device) { int fd; @@ -96,6 +130,8 @@ fstype(const char *device) { union { struct xiafs_super_block xiasb; char romfs_magic[8]; + char qnx4fs_magic[10]; /* ignore first 4 bytes */ + long bfs_magic; struct ntfs_super_block ntfssb; struct fat_super_block fatsb; } xsb; @@ -141,11 +177,17 @@ fstype(const char *device) { type = "xiafs"; else if(!strncmp(xsb.romfs_magic, "-rom1fs-", 8)) type = "romfs"; + else if(!strncmp(xsb.qnx4fs_magic+4, "QNX4FS", 6)) + type = "qnx4fs"; + else if(xsb.bfs_magic == 0x1badface) + type = "bfs"; else if(!strncmp(xsb.ntfssb.s_magic, NTFS_SUPER_MAGIC, sizeof(xsb.ntfssb.s_magic))) type = "ntfs"; else if ((!strncmp(xsb.fatsb.s_os, "MSDOS", 5) || - !strncmp(xsb.fatsb.s_os, "MSWIN", 5)) + !strncmp(xsb.fatsb.s_os, "MSWIN", 5) || + !strncmp(xsb.fatsb.s_os, "MTOOL", 5) || + !strncmp(xsb.fatsb.s_os, "mkdosfs", 7)) && (!strncmp(xsb.fatsb.s_fs, "FAT12 ", 8) || !strncmp(xsb.fatsb.s_fs, "FAT16 ", 8) || !strncmp(xsb.fatsb.s_fs2, "FAT32 ", 8))) @@ -169,6 +211,28 @@ fstype(const char *device) { 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"; + } + + if (!type) { + /* perhaps the user tries to mount the swap space + on a new disk; warn her before she does mke2fs on it */ + int pagesize = getpagesize(); + int rd; + char buf[32768]; + + rd = pagesize; + if (rd < 8192) + rd = 8192; + if (rd > sizeof(buf)) + rd = sizeof(buf); + if (lseek(fd, 0, SEEK_SET) != 0 + || read(fd, buf, rd) != rd) + goto io_error; + if (may_be_swap(buf+pagesize) || + may_be_swap(buf+4096) || may_be_swap(buf+8192)) + type = "swap"; } close (fd); @@ -182,17 +246,19 @@ io_error: char * guess_fstype_from_superblock(const char *spec) { - char *type = fstype(spec); - if (verbose) { - printf (_("mount: you didn't specify a filesystem type for %s\n"), - spec); - if (type) - printf (_(" I will try type %s\n"), type); - else - printf (_(" I will try all types mentioned in %s or %s\n"), - ETC_FILESYSTEMS, PROC_FILESYSTEMS); - } - return type; + char *type = fstype(spec); + if (verbose) { + printf (_("mount: you didn't specify a filesystem type for %s\n"), + spec); + if (!type) + printf (_(" I will try all types mentioned in %s or %s\n"), + ETC_FILESYSTEMS, PROC_FILESYSTEMS); + else if (!strcmp(type, "swap")) + printf (_(" and it looks like this is swapspace\n")); + else + printf (_(" I will try type %s\n"), type); + } + return type; } static FILE *procfs; @@ -237,17 +303,24 @@ is_in_procfs(const char *type) { return 0; } +/* return: 0: OK, -1: error in errno, 1: type not found */ +/* when 1 is returned, *type is NULL */ int procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args, char **type) { char *fsname; + *type = NULL; if (!procfsopen()) - return -1; + return 1; while ((fsname = procfsnext()) != NULL) { if (tested (fsname)) continue; args->type = fsname; + if (verbose) { + printf(_("Trying %s\n"), fsname); + fflush(stdout); + } if ((*mount_fn) (args) == 0) { *type = xstrdup(fsname); procfsclose(); @@ -255,13 +328,11 @@ procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args, } else if (errno != EINVAL) { *type = "guess"; procfsclose(); - return 1; + return -1; } } procfsclose(); - *type = NULL; - - return -1; + return 1; } int |