Signed-off-by: Kay Sievers <kay.sievers@xxxxxxxx> Signed-off-by: Karel Zak <kzak@xxxxxxxxxx> --- mount/Makefile.am | 15 +-- mount/fsprobe.c | 164 ++++++++++++++++++++++++++++++++ mount/fsprobe.h | 17 ++++ mount/fsprobe_blkid.c | 11 ++ mount/mount.c | 43 +++++++-- mount/mount_guess_fstype.c | 225 -------------------------------------------- mount/mount_guess_fstype.h | 16 --- mount/mount_paths.h | 3 + 8 files changed, 232 insertions(+), 262 deletions(-) diff --git a/mount/Makefile.am b/mount/Makefile.am index 6f63dcf..b5b21b5 100644 --- a/mount/Makefile.am +++ b/mount/Makefile.am @@ -7,24 +7,17 @@ sbin_PROGRAMS = losetup swapon man_MANS = fstab.5 mount.8 swapoff.8 swapon.8 umount.8 losetup.8 MNTHDRS = fstab.h linux_fs.h mount_mntent.h mount_constants.h my_dev_t.h \ - mount_paths.h lomount.h fsprobe.h \ - mount_guess_fstype.h realpath.h xmalloc.h \ - getusername.h loop.h mount_guess_rootdev.h \ - sundries.h + mount_paths.h lomount.h fsprobe.h realpath.h xmalloc.h \ + getusername.h loop.h mount_guess_rootdev.h sundries.h mount_SOURCES = mount.c fstab.c sundries.c xmalloc.c realpath.c mount_mntent.c \ - mount_guess_fstype.c \ - getusername.c \ - lomount.c \ - $(MNTHDRS) + fsprobe.c getusername.c lomount.c $(MNTHDRS) mount_LDADD = $(top_srcdir)/lib/libenv.a $(top_srcdir)/lib/libsetproctitle.a mount_CFLAGS = $(SUID_CFLAGS) umount_SOURCES = umount.c fstab.c sundries.c xmalloc.c realpath.c mount_mntent.c \ - getusername.c \ - lomount.c \ - $(MNTHDRS) + getusername.c fsprobe.c lomount.c $(MNTHDRS) umount_LDADD = $(top_srcdir)/lib/libenv.a umount_CFLAGS = $(SUID_CFLAGS) diff --git a/mount/fsprobe.c b/mount/fsprobe.c new file mode 100644 index 0000000..4b57802 --- /dev/null +++ b/mount/fsprobe.c @@ -0,0 +1,164 @@ +#include <stdio.h> +#include <string.h> +#include <fcntl.h> +#include <errno.h> +#include <unistd.h> +#include <sys/stat.h> +#include <sys/types.h> +#include "mount_paths.h" +#include "linux_fs.h" +#include "fsprobe.h" +#include "sundries.h" /* for xstrdup */ +#include "nls.h" + +/* list of already tested filesystems by fsprobe_procfsloop_mount() */ +static struct tried { + struct tried *next; + char *type; +} *tried = NULL; + +static int +was_tested(const char *fstype) { + struct tried *t; + + if (fsprobe_known_fstype(fstype)) + return 1; + for (t = tried; t; t = t->next) { + if (!strcmp(t->type, fstype)) + return 1; + } + return 0; +} + +static void +set_tested(const char *fstype) { + struct tried *t = xmalloc(sizeof(struct tried)); + + t->next = tried; + t->type = xstrdup(fstype); + tried = t; +} + +static void +free_tested(void) { + struct tried *t, *tt; + + t = tried; + while(t) { + free(t->type); + tt = t->next; + free(t); + t = tt; + } + tried = NULL; +} + +static char * +procfsnext(FILE *procfs) { + char line[100]; + char fsname[100]; + + while (fgets(line, sizeof(line), procfs)) { + if (sscanf (line, "nodev %[^\n]\n", fsname) == 1) continue; + if (sscanf (line, " %[^ \n]\n", fsname) != 1) continue; + return xstrdup(fsname); + } + return 0; +} + +/* Only use /proc/filesystems here, this is meant to test what + the kernel knows about, so /etc/filesystems is irrelevant. + Return: 1: yes, 0: no, -1: cannot open procfs */ +int +fsprobe_known_fstype_in_procfs(const char *type) +{ + FILE *procfs; + char *fsname; + int ret = -1; + + procfs = fopen(PROC_FILESYSTEMS, "r"); + if (procfs) { + ret = 0; + while ((fsname = procfsnext(procfs)) != NULL) + if (!strcmp(fsname, type)) { + ret = 1; + break; + } + fclose(procfs); + procfs = NULL; + } + return ret; +} + +/* Try all types in FILESYSTEMS, except those in *types, + in case *types starts with "no" */ +/* return: 0: OK, -1: error in errno, 1: type not found */ +/* when 0 or -1 is returned, *types contains the type used */ +/* when 1 is returned, *types is NULL */ +int +fsprobe_procfsloop_mount( int (*mount_fn)(struct mountargs *), + struct mountargs *args, + const char **types) +{ + char *files[2] = { ETC_FILESYSTEMS, PROC_FILESYSTEMS }; + FILE *procfs; + char *fsname; + const char *notypes = NULL; + int no = 0; + int ret = 1; + int errsv = 0; + int i; + + if (*types && !strncmp(*types, "no", 2)) { + no = 1; + notypes = (*types) + 2; + } + *types = NULL; + + /* Use PROC_FILESYSTEMS only when ETC_FILESYSTEMS does not exist. + In some cases trying a filesystem that the kernel knows about + on the wrong data will crash the kernel; in such cases + ETC_FILESYSTEMS can be used to list the filesystems that we + are allowed to try, and in the order they should be tried. + End ETC_FILESYSTEMS with a line containing a single '*' only, + if PROC_FILESYSTEMS should be tried afterwards. */ + + for (i=0; i<2; i++) { + procfs = fopen(files[i], "r"); + if (!procfs) + continue; + while ((fsname = procfsnext(procfs)) != NULL) { + if (!strcmp(fsname, "*")) { + fclose(procfs); + goto nexti; + } + if (was_tested (fsname)) + continue; + if (no && matching_type(fsname, notypes)) + continue; + set_tested (fsname); + args->type = fsname; + if (verbose) { + printf(_("Trying %s\n"), fsname); + fflush(stdout); + } + if ((*mount_fn) (args) == 0) { + *types = fsname; + ret = 0; + break; + } else if (errno != EINVAL && + fsprobe_known_fstype_in_procfs(fsname) == 1) { + *types = "guess"; + ret = -1; + errsv = errno; + break; + } + } + free_tested(); + fclose(procfs); + errno = errsv; + return ret; + nexti:; + } + return 1; +} diff --git a/mount/fsprobe.h b/mount/fsprobe.h index c96ff8c..cc429e1 100644 --- a/mount/fsprobe.h +++ b/mount/fsprobe.h @@ -10,3 +10,20 @@ extern const char *mount_get_devname_by_label(const char *label); extern const char *mount_get_volume_label_by_spec(const char *spec); extern const char *mount_get_devname(const char *spec); extern const char *mount_get_devname_for_mounting(const char *spec); +extern int fsprobe_known_fstype(const char *fstype); +extern const char *fsprobe_get_fstype_by_devname(const char *devname); + +struct mountargs { + const char *spec; + const char *node; + const char *type; + int flags; + void *data; +}; + +extern int fsprobe_known_fstype_in_procfs(const char *type); + +extern int fsprobe_procfsloop_mount(int (*mount_fn)(struct mountargs *), + struct mountargs *args, + const char **types); + diff --git a/mount/fsprobe_blkid.c b/mount/fsprobe_blkid.c index 9ff4e31..7f8c362 100644 --- a/mount/fsprobe_blkid.c +++ b/mount/fsprobe_blkid.c @@ -41,4 +41,15 @@ mount_get_devname_for_mounting(const char *spec) { return blkid_get_devname(blkid, spec, 0); } +int +fsprobe_known_fstype(const char *fstype) +{ + return blkid_known_fstype(fstype); +} + +const char * +fsprobe_get_fstype_by_devname(const char *devname) { + return blkid_get_tag_value(blkid, "TYPE", devname); +} + #endif diff --git a/mount/mount.c b/mount/mount.c index 309e41e..be9e409 100644 --- a/mount/mount.c +++ b/mount/mount.c @@ -39,7 +39,6 @@ #include "loop.h" #include "linux_fs.h" /* for BLKGETSIZE */ #include "mount_guess_rootdev.h" -#include "mount_guess_fstype.h" #include "getusername.h" #include "mount_paths.h" #include "env.h" @@ -656,6 +655,26 @@ check_special_mountprog(const char *spec, const char *node, const char *type, in return 0; } + +static const char * +guess_fstype_by_devname(const char *devname) +{ + const char *type = fsprobe_get_fstype_by_devname(devname); + + if (verbose) { + printf (_("mount: you didn't specify a filesystem type for %s\n"), devname); + + 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; +} + /* * guess_fstype_and_mount() * Mount a single file system. Guess the type when unknown. @@ -675,7 +694,7 @@ guess_fstype_and_mount(const char *spec, const char *node, const char **types, *types = "none"; /* random, but not "bind" */ if (!*types && !(flags & MS_REMOUNT)) { - *types = guess_fstype(spec); + *types = guess_fstype_by_devname(spec); if (*types) { if (!strcmp(*types, "swap")) { error(_("%s looks like swapspace - not mounted"), spec); @@ -711,7 +730,7 @@ guess_fstype_and_mount(const char *spec, const char *node, const char **types, return do_mount_syscall (&args); } - return procfsloop(do_mount_syscall, &args, types); + return fsprobe_procfsloop_mount(do_mount_syscall, &args, types); } /* @@ -1147,8 +1166,10 @@ try_mount_one (const char *spec0, const char *node0, const char *types0, case EIO: error (_("mount: %s: can't read superblock"), spec); break; case ENODEV: - { int pfs; - if ((pfs = is_in_procfs(types)) == 1 || !strcmp(types, "guess")) + { + int pfs = fsprobe_known_fstype_in_procfs(types); + + if (pfs == 1 || !strcmp(types, "guess")) error(_("mount: %s: unknown device"), spec); else if (pfs == 0) { char *lowtype, *p; @@ -1165,11 +1186,13 @@ try_mount_one (const char *spec0, const char *node0, const char *types0, u++; } } - if (u && is_in_procfs(lowtype) == 1) + if (u && fsprobe_known_fstype_in_procfs(lowtype) == 1) error (_("mount: probably you meant %s"), lowtype); - else if (!strncmp(lowtype, "iso", 3) && is_in_procfs("iso9660") == 1) + else if (!strncmp(lowtype, "iso", 3) && + fsprobe_known_fstype_in_procfs("iso9660") == 1) error (_("mount: maybe you meant 'iso9660'?")); - else if (!strncmp(lowtype, "fat", 3) && is_in_procfs("vfat") == 1) + else if (!strncmp(lowtype, "fat", 3) && + fsprobe_known_fstype_in_procfs("vfat") == 1) error (_("mount: maybe you meant 'vfat'?")); free(lowtype); } else @@ -1741,8 +1764,8 @@ main(int argc, char *argv[]) { use only for testing purposes - the guessing is not reliable at all */ { - char *fstype; - fstype = do_guess_fstype(optarg); + const char *fstype; + fstype = fsprobe_get_fstype_by_devname(optarg); printf("%s\n", fstype ? fstype : "unknown"); exit(fstype ? 0 : EX_FAIL); } diff --git a/mount/mount_guess_fstype.c b/mount/mount_guess_fstype.c deleted file mode 100644 index 01c3fc7..0000000 --- a/mount/mount_guess_fstype.c +++ /dev/null @@ -1,225 +0,0 @@ -/* - * Thu Jul 14 07:32:40 1994: faith@xxxxxxxxxx added changes from Adam - * J. Richter (adam@xxxxxxxxxxxxxxxxxx) so that /proc/filesystems is used - * if no -t option is given. I modified his patches so that, if - * /proc/filesystems is not available, the behavior of mount is the same as - * it was previously. - * - * Wed Feb 8 09:23:18 1995: Mike Grupenhoff <kashmir@xxxxxxxxxxxxxx> added - * a probe of the superblock for the type before /proc/filesystems is - * checked. - * - * Fri Apr 5 01:13:33 1996: quinlan@xxxxxxxxxxxx, fixed up iso9660 autodetect - * - * Wed Nov 11 11:33:55 1998: K.Garloff@xxxxxxx, 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@xxxxxxxxxx> - * added Native Language Support - * - * 2000-12-01 Sepp Wijnands <mrrazz@xxxxxxxxxxxxxxxxxx> - * added probes for cramfs, hfs, hpfs and adfs. - * - * 2001-10-26 Tim Launchbury - * added sysv magic. - * - * aeb - many changes. - * - */ - -#include <stdio.h> -#include <string.h> -#include <fcntl.h> -#include <errno.h> -#include <unistd.h> -#include <sys/stat.h> -#include <sys/types.h> -#include "linux_fs.h" -#include "fsprobe.h" -#include "mount_guess_fstype.h" -#include "sundries.h" /* for xstrdup */ -#include "nls.h" - -#define ETC_FILESYSTEMS "/etc/filesystems" -#define PROC_FILESYSTEMS "/proc/filesystems" - -char * -do_guess_fstype(const char *device) -{ - return blkid_get_tag_value(blkid, "TYPE", device); -} - -static int -known_fstype(const char *fstype) -{ - return blkid_known_fstype(fstype); -} - - -static struct tried { - struct tried *next; - char *type; -} *tried = NULL; - -static int -was_tested(const char *fstype) { - struct tried *t; - - if (known_fstype(fstype)) - return 1; - for (t = tried; t; t = t->next) { - if (!strcmp(t->type, fstype)) - return 1; - } - return 0; -} - -static void -set_tested(const char *fstype) { - struct tried *t = xmalloc(sizeof(struct tried)); - - t->next = tried; - t->type = xstrdup(fstype); - tried = t; -} - -static void -free_tested(void) { - struct tried *t, *tt; - - t = tried; - while(t) { - free(t->type); - tt = t->next; - free(t); - t = tt; - } - tried = NULL; -} - -char * -guess_fstype(const char *spec) { - char *type = do_guess_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 char * -procfsnext(FILE *procfs) { - char line[100]; - char fsname[100]; - - while (fgets(line, sizeof(line), procfs)) { - if (sscanf (line, "nodev %[^\n]\n", fsname) == 1) continue; - if (sscanf (line, " %[^ \n]\n", fsname) != 1) continue; - return xstrdup(fsname); - } - return 0; -} - -/* Only use /proc/filesystems here, this is meant to test what - the kernel knows about, so /etc/filesystems is irrelevant. - Return: 1: yes, 0: no, -1: cannot open procfs */ -int -is_in_procfs(const char *type) { - FILE *procfs; - char *fsname; - int ret = -1; - - procfs = fopen(PROC_FILESYSTEMS, "r"); - if (procfs) { - ret = 0; - while ((fsname = procfsnext(procfs)) != NULL) - if (!strcmp(fsname, type)) { - ret = 1; - break; - } - fclose(procfs); - procfs = NULL; - } - return ret; -} - -/* Try all types in FILESYSTEMS, except those in *types, - in case *types starts with "no" */ -/* return: 0: OK, -1: error in errno, 1: type not found */ -/* when 0 or -1 is returned, *types contains the type used */ -/* when 1 is returned, *types is NULL */ -int -procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args, - const char **types) { - char *files[2] = { ETC_FILESYSTEMS, PROC_FILESYSTEMS }; - FILE *procfs; - char *fsname; - const char *notypes = NULL; - int no = 0; - int ret = 1; - int errsv = 0; - int i; - - if (*types && !strncmp(*types, "no", 2)) { - no = 1; - notypes = (*types) + 2; - } - *types = NULL; - - /* Use PROC_FILESYSTEMS only when ETC_FILESYSTEMS does not exist. - In some cases trying a filesystem that the kernel knows about - on the wrong data will crash the kernel; in such cases - ETC_FILESYSTEMS can be used to list the filesystems that we - are allowed to try, and in the order they should be tried. - End ETC_FILESYSTEMS with a line containing a single '*' only, - if PROC_FILESYSTEMS should be tried afterwards. */ - - for (i=0; i<2; i++) { - procfs = fopen(files[i], "r"); - if (!procfs) - continue; - while ((fsname = procfsnext(procfs)) != NULL) { - if (!strcmp(fsname, "*")) { - fclose(procfs); - goto nexti; - } - if (was_tested (fsname)) - continue; - if (no && matching_type(fsname, notypes)) - continue; - set_tested (fsname); - args->type = fsname; - if (verbose) { - printf(_("Trying %s\n"), fsname); - fflush(stdout); - } - if ((*mount_fn) (args) == 0) { - *types = fsname; - ret = 0; - break; - } else if (errno != EINVAL && - is_in_procfs(fsname) == 1) { - *types = "guess"; - ret = -1; - errsv = errno; - break; - } - } - free_tested(); - fclose(procfs); - errno = errsv; - return ret; - nexti:; - } - return 1; -} diff --git a/mount/mount_guess_fstype.h b/mount/mount_guess_fstype.h deleted file mode 100644 index 63cb678..0000000 --- a/mount/mount_guess_fstype.h +++ /dev/null @@ -1,16 +0,0 @@ -struct mountargs { - const char *spec; - const char *node; - const char *type; - int flags; - void *data; -}; - -extern int verbose; - -char *guess_fstype(const char *device); -char *do_guess_fstype(const char *device); -int procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args, - const char **type); -int is_in_procfs(const char *fstype); - diff --git a/mount/mount_paths.h b/mount/mount_paths.h index fe84e1d..9093b10 100644 --- a/mount/mount_paths.h +++ b/mount/mount_paths.h @@ -12,4 +12,7 @@ #endif #define LOCK_TIMEOUT 10 +#define ETC_FILESYSTEMS "/etc/filesystems" +#define PROC_FILESYSTEMS "/proc/filesystems" + #endif /* MOUNT_PATHS_H */ -- 1.5.0.6 - To unsubscribe from this list: send the line "unsubscribe util-linux-ng" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html