diff options
Diffstat (limited to 'mount/mount.c')
-rw-r--r-- | mount/mount.c | 534 |
1 files changed, 231 insertions, 303 deletions
diff --git a/mount/mount.c b/mount/mount.c index 19c50764..5ee247da 100644 --- a/mount/mount.c +++ b/mount/mount.c @@ -2,12 +2,6 @@ * A mount(8) for Linux 0.99. * mount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp * - * Thu Jul 14 07:32:40 1994: faith@cs.unc.edu added changes from Adam - * J. Richter (adam@adam.yggdrasil.com) 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 Sep 14 22:43:00 1994: Mitchum DSouza * (mitch@mrc-applied-psychology.cambridge.ac.uk) added support for mounting * the "loop" device. @@ -15,21 +9,22 @@ * Wed Sep 14 22:55:10 1994: Sander van Malssen (svm@kozmix.hacktic.nl) * added support for remounting readonly file systems readonly. * - * Wed Feb 8 09:23:18 1995: Mike Grupenhoff <kashmir@umiacs.UMD.EDU> added - * a probe of the superblock for the type before /proc/filesystems is - * checked. - * * Wed Feb 8 12:27:00 1995: Andries.Brouwer@cwi.nl fixed up error messages. * Sat Jun 3 20:44:38 1995: Patches from Andries.Brouwer@cwi.nl applied. * Tue Sep 26 22:38:20 1995: aeb@cwi.nl, many changes * Fri Feb 23 13:47:00 1996: aeb@cwi.nl, loop device related changes * - * Fri Apr 5 01:13:33 1996: quinlan@bucknell.edu, fixed up iso9660 autodetect - * * Since then, many changes - aeb. * * Wed Oct 1 23:55:28 1997: Dick Streefland <dick_streefland@tasking.com> * Implemented the "bg", "fg" and "retry" mount options for NFS. + * + * Tue Aug 4 15:54:31 1998: aeb@cwi.nl: + * Open fd 0,1,2 so that printf's do not clobber /etc/mtab or so. + * Mangle filenames with embedded spaces. Add ufsmagic. Add locking. + * Avoid unnecessary error messages about /proc. + * Improve support for noncanonical names in /etc/fstab. + * Add support for volume labels and UUIDs. */ #include <unistd.h> @@ -47,22 +42,19 @@ #include "mount_constants.h" #include "sundries.h" +#include "mntent.h" #include "fstab.h" #include "lomount.h" #include "loop.h" -#include "linux_fs.h" - -#define PROC_FILESYSTEMS "/proc/filesystems" -#define SIZE(a) (sizeof(a)/sizeof(a[0])) +#include "linux_fs.h" /* for BLKGETSIZE */ +#include "mount_guess_fstype.h" +#include "mount_by_label.h" +#include "getusername.h" #define DO_PS_FIDDLING #ifdef DO_PS_FIDDLING -#define PROC_NAME "mount: " -static int argc0; -static char** argv0; -static char** envp0; -extern char** environ; +#include "setproctitle.h" #endif /* True for fake mount (-f). */ @@ -105,14 +97,15 @@ struct opt_map /* We can use the high-order 16 bits, since the mount call has MS_MGC_VAL there. */ #define MS_NOAUTO 0x80000000 -#define MS_USER 0x40000000 +#define MS_USERS 0x40000000 +#define MS_USER 0x20000000 #define MS_LOOP 0x00010000 /* Options that we keep the mount system call from seeing. */ -#define MS_NOSYS (MS_NOAUTO|MS_USER|MS_LOOP) +#define MS_NOSYS (MS_NOAUTO|MS_USERS|MS_USER|MS_LOOP) /* Options that we keep from appearing in the options field in the mtab. */ -#define MS_NOMTAB (MS_REMOUNT|MS_NOAUTO|MS_USER) +#define MS_NOMTAB (MS_REMOUNT|MS_NOAUTO|MS_USERS|MS_USER) /* OPTIONS that we make ordinary users have by default. */ #define MS_SECURE (MS_NOEXEC|MS_NOSUID|MS_NODEV) @@ -132,6 +125,8 @@ const struct opt_map opt_map[] = { { "remount", 0, 0, MS_REMOUNT}, /* Alter flags of mounted FS */ { "auto", 0, 1, MS_NOAUTO }, /* Can be mounted using -a */ { "noauto", 0, 0, MS_NOAUTO }, /* Can only be mounted explicitly */ + { "users", 0, 0, MS_USERS }, /* Allow ordinary user to mount */ + { "nousers", 0, 1, MS_USERS }, /* Forbid ordinary user to mount */ { "user", 0, 0, MS_USER }, /* Allow ordinary user to mount */ { "nouser", 0, 1, MS_USER }, /* Forbid ordinary user to mount */ /* add new options here */ @@ -159,7 +154,7 @@ const struct opt_map opt_map[] = { { NULL, 0, 0, 0 } }; -char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption; +static char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption; struct string_opt_map { char *tag; @@ -233,13 +228,12 @@ parse_opt (const char *opt, int *mask, char *extra_opts) const struct opt_map *om; for (om = opt_map; om->opt != NULL; om++) - if (streq (opt, om->opt)) - { + if (streq (opt, om->opt)) { if (om->inv) *mask &= ~om->mask; else *mask |= om->mask; - if (om->mask == MS_USER) + if (om->mask == MS_USER || om->mask == MS_USERS) *mask |= MS_SECURE; #ifdef MS_SILENT if (om->mask == MS_SILENT && om->inv) { @@ -284,8 +278,7 @@ parse_opts (char *opts, int *flags, char **extra_opts) /* Try to build a canonical options string. */ static char * -fix_opts_string (int flags, char *extra_opts) -{ +fix_opts_string (int flags, const char *extra_opts, const char *user) { const struct opt_map *om; const struct string_opt_map *m; char *new_opts; @@ -306,167 +299,14 @@ fix_opts_string (int flags, char *extra_opts) if (extra_opts && *extra_opts) { new_opts = xstrconcat3(new_opts, ",", extra_opts); } + if (user) { + new_opts = xstrconcat3(new_opts, ",user=", user); + } return new_opts; } -/* 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); -} - -/* - char *fstype(const char *device); - - 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>. - Read the superblock only once - aeb - Added a test for iso9660 - aeb - Added a test for high sierra (iso9660) - quinlan@bucknell.edu - Corrected the test for xiafs - aeb - Added romfs - aeb - - Currently supports: minix, ext, ext2, xiafs, iso9660, romfs -*/ -char *magic_known[] = { "minix", "ext", "ext2", "xiafs", "iso9660", "romfs" }; - static int -tested(const char *device) { - char **m; - - for (m = magic_known; m - magic_known < SIZE(magic_known); m++) - if (!strcmp(*m, device)) - return 1; - return 0; -} - -static char * -fstype(const char *device) -{ - int fd; - char *type = NULL; - union { - struct minix_super_block ms; - struct ext_super_block es; - struct ext2_super_block e2s; - } sb; - union { - struct xiafs_super_block xiasb; - char romfs_magic[8]; - } xsb; - union { - struct iso_volume_descriptor iso; - struct hs_volume_descriptor hs; - } isosb; - 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)) - 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; - - if (ext2magic(sb.e2s) == EXT2_SUPER_MAGIC - || ext2magic(sb.e2s) == EXT2_PRE_02B_MAGIC - || ext2magic(sb.e2s) == swapped(EXT2_SUPER_MAGIC)) - type = "ext2"; - - else if (minixmagic(sb.ms) == MINIX_SUPER_MAGIC - || minixmagic(sb.ms) == MINIX_SUPER_MAGIC2) - type = "minix"; - - else if (extmagic(sb.es) == EXT_SUPER_MAGIC) - type = "ext"; - - if (!type) { - if (lseek(fd, 0, SEEK_SET) != 0 - || read(fd, (char *) &xsb, sizeof(xsb)) != sizeof(xsb)) - goto io_error; - - if (xiafsmagic(xsb.xiasb) == _XIAFS_SUPER_MAGIC) - type = "xiafs"; - else if(!strncmp(xsb.romfs_magic, "-rom1fs-", 8)) - type = "romfs"; - } - - 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"; - } - - close (fd); - return(type); - -io_error: - perror(device); - close(fd); - return 0; -} - -FILE *procfs; - -static void -procclose(void) { - if (procfs) - fclose (procfs); - procfs = 0; -} - -static int -procopen(void) { - return ((procfs = fopen(PROC_FILESYSTEMS, "r")) != NULL); -} - -static char * -procnext(void) { - char line[100]; - static char fsname[50]; - - while (fgets(line, sizeof(line), procfs)) { - if (sscanf (line, "nodev %[^\n]\n", fsname) == 1) continue; - if (sscanf (line, " %[^ \n]\n", fsname) != 1) continue; - return fsname; - } - return 0; -} - -static int -is_in_proc(char *type) { - char *fsname; - - if (procopen()) { - while ((fsname = procnext()) != NULL) - if (!strcmp(fsname, type)) - return 1; - } - return 0; -} - -static int -already (char *spec, char *node) { +already (const char *spec, const char *node) { struct mntentchn *mc; int ret = 1; @@ -488,11 +328,12 @@ create_mtab (void) { struct mntent mnt; int flags; char *extra_opts; - FILE *fp; + mntFILE *mfp; lock_mtab(); - if ((fp = setmntent (MOUNTED, "a+")) == NULL) + mfp = my_setmntent (MOUNTED, "a+"); + if (mfp == NULL || mfp->mntent_fp == NULL) die (EX_FILEIO, "mount: can't open %s for writing: %s", MOUNTED, strerror (errno)); @@ -502,18 +343,18 @@ create_mtab (void) { mnt.mnt_dir = "/"; mnt.mnt_fsname = canonicalize (fstab->mnt_fsname); mnt.mnt_type = fstab->mnt_type; - mnt.mnt_opts = fix_opts_string (flags, extra_opts); + mnt.mnt_opts = fix_opts_string (flags, extra_opts, NULL); mnt.mnt_freq = mnt.mnt_passno = 0; - if (addmntent (fp, &mnt) == 1) + if (my_addmntent (mfp, &mnt) == 1) die (EX_FILEIO, "mount: error writing %s: %s", MOUNTED, strerror (errno)); } - if (fchmod (fileno (fp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) + if (fchmod (fileno (mfp->mntent_fp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) if (errno != EROFS) die (EX_FILEIO, "mount: error changing mode of %s: %s", MOUNTED, strerror (errno)); - endmntent (fp); + my_endmntent (mfp); unlock_mtab(); } @@ -522,8 +363,9 @@ create_mtab (void) { static int mountcount = 0; static int -mount5 (char *special, char *dir, char *type, int flags, void *data) { - int ret = mount (special, dir, type, 0xC0ED0000 | (flags), data); +mount5 (struct mountargs *args) { + int ret = mount (args->spec, args->node, args->type, + MS_MGC_VAL | (args->flags), args->data); if (ret == 0) mountcount++; return ret; @@ -534,46 +376,20 @@ mount5 (char *special, char *dir, char *type, int flags, void *data) { static int try_mount5 (char *spec, char *node, char **type, int flags, char *mount_opts) { - char *fsname; + struct mountargs args = { spec, node, NULL, flags & ~MS_NOSYS, mount_opts }; if (*type && strcasecmp (*type, "auto") == 0) *type = NULL; - if (!*type && !(flags & MS_REMOUNT)) { - *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\n", - PROC_FILESYSTEMS); - } - } + if (!*type && !(flags & MS_REMOUNT)) + *type = guess_fstype_from_superblock(spec); - if (*type || (flags & MS_REMOUNT)) - return mount5 (spec, node, *type, flags & ~MS_NOSYS, mount_opts); - - if (!procopen()) - return -1; - while ((fsname = procnext()) != NULL) { - if (tested (fsname)) - continue; - if (mount5 (spec, node, fsname, flags & ~MS_NOSYS, mount_opts) == 0) { - *type = xstrdup(fsname); - procclose(); - return 0; - } else if (errno != EINVAL) { - *type = "guess"; - procclose(); - return 1; - } + if (*type || (flags & MS_REMOUNT)) { + args.type = *type; + return mount5 (&args); } - procclose(); - *type = NULL; - return -1; + return procfsloop(mount5, &args, type); } /* @@ -584,9 +400,8 @@ try_mount5 (char *spec, char *node, char **type, int flags, char *mount_opts) { * background. */ static int -try_mount_one (char *spec0, char *node0, char *type0, char *opts0, - int freq, int pass, int bg) -{ +try_mount_one (const char *spec0, const char *node0, char *type0, + const char *opts0, int freq, int pass, int bg) { struct mntentchn mcn; struct mntent mnt; int mnt_err; @@ -595,7 +410,9 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, char *mount_opts; /* actually used on system call */ static int added_ro = 0; int loop, looptype, offset; - char *spec, *node, *type, *opts, *loopdev, *loopfile; + const char *opts; + char *spec, *node, *type, *loopdev, *loopfile; + char *user = 0; struct stat statbuf; spec = xstrdup(spec0); @@ -606,11 +423,15 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, parse_opts (xstrdup (opts), &flags, &extra_opts); /* root may allow certain types of mounts by ordinary users */ - if (suid && !(flags & MS_USER)) { - if (already (spec, node)) - die (EX_USAGE, "mount failed"); - else - die (EX_USAGE, "mount: only root can mount %s on %s", spec, node); + if (suid) { + if (!(flags & (MS_USER | MS_USERS))) { + if (already (spec, node)) + die (EX_USAGE, "mount failed"); + else + die (EX_USAGE, "mount: only root can mount %s on %s", spec, node); + } + if (flags & MS_USER) + user = getusername(); } /* quietly succeed for fstab entries that don't get mounted automatically */ @@ -661,8 +482,13 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, if (verbose) printf("mount: going to use the loop device %s\n", loopdev); offset = opt_offset ? strtoul(opt_offset, NULL, 0) : 0; - if (set_loop (loopdev, loopfile, offset, opt_encryption, &loopro)) + if (set_loop (loopdev, loopfile, offset, opt_encryption, &loopro)) { + if (verbose) + printf("mount: failed setting up loop device\n"); return EX_FAIL; + } + if (verbose > 1) + printf("mount: setup loop device successfully\n"); spec = loopdev; if (loopro) flags |= MS_RDONLY; @@ -686,7 +512,9 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, */ if (type) #ifndef ALWAYS_STAT - if (streq (type, "smb") || streq (type, "ncp")) + if (streq (type, "smb") || streq (type, "ncp") + /* || streq (type, "smbfs") || streq (type, "ncpfs") */ + ) #else if (strlen (type) < 100) #endif @@ -701,7 +529,7 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, setuid(getuid()); setgid(getgid()); - oo = fix_opts_string (flags, extra_opts); + oo = fix_opts_string (flags, extra_opts, NULL); mountargs[i++] = mountprog; mountargs[i++] = spec; mountargs[i++] = node; @@ -721,7 +549,7 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, wait(&status); return status; } else - error("cannot fork: %s", strerror(errno)); + error("mount: cannot fork: %s", strerror(errno)); } } @@ -737,7 +565,8 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, mcn.mnt_fsname = mnt.mnt_fsname = canonicalize (loop ? loopfile : spec); mcn.mnt_dir = mnt.mnt_dir = canonicalize (node); mcn.mnt_type = mnt.mnt_type = type ? type : "unknown"; - mcn.mnt_opts = mnt.mnt_opts = fix_opts_string (flags & ~MS_NOMTAB, extra_opts); + mcn.mnt_opts = mnt.mnt_opts = fix_opts_string (flags & ~MS_NOMTAB, + extra_opts, user); mcn.nxt = 0; mnt.mnt_freq = freq; mnt.mnt_passno = pass; @@ -751,16 +580,20 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, if (flags & MS_REMOUNT) update_mtab (mnt.mnt_dir, &mnt); else { - FILE *fp = setmntent(MOUNTED, "a+"); - if (fp == NULL) + mntFILE *mfp; + + lock_mtab(); + mfp = my_setmntent(MOUNTED, "a+"); + if (mfp == NULL || mfp->mntent_fp == NULL) { error("mount: can't open %s: %s", MOUNTED, strerror (errno)); - else { - if ((addmntent (fp, &mnt)) == 1) + } else { + if ((my_addmntent (mfp, &mnt)) == 1) error("mount: error writing %s: %s", MOUNTED, strerror (errno)); - endmntent(fp); + my_endmntent(mfp); } + unlock_mtab(); } } @@ -794,6 +627,12 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, case EBUSY: if (flags & MS_REMOUNT) { error ("mount: %s is busy", node); + } else if (!strcmp(type, "proc") && !strcmp(node, "/proc")) { + /* heuristic: if /proc/version exists, then probably proc is mounted */ + if (stat ("/proc/version", &statbuf)) /* proc mounted? */ + error ("mount: %s is busy", node); /* no */ + else if(!all || verbose) /* yes, don't mention it */ + error ("mount: proc already mounted"); } else { error ("mount: %s already mounted or %s busy", spec, node); already (spec, node); @@ -826,7 +665,7 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, spec); if (stat (spec, &statbuf) == 0 && S_ISBLK(statbuf.st_mode) - && (fd = open(spec, O_RDONLY)) >= 0) { + && (fd = open(spec, O_RDONLY | O_NONBLOCK)) >= 0) { if(ioctl(fd, BLKGETSIZE, &size) == 0 && size <= 2) error (" (aren't you trying to mount an extended partition,\n" " instead of some logical partition inside?)"); @@ -840,9 +679,9 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, case EIO: error ("mount: %s: can't read superblock", spec); break; case ENODEV: - if (is_in_proc(type) || !strcmp(type, "guess")) + if (is_in_procfs(type) || !strcmp(type, "guess")) error("mount: %s has wrong major or minor number", spec); - else if (procfs) { + else if (have_procfs()) { char *lowtype, *p; int u; @@ -857,9 +696,9 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, u++; } } - if (u && is_in_proc(lowtype)) + if (u && is_in_procfs(lowtype)) error ("mount: probably you meant %s", lowtype); - else if (!strncmp(lowtype, "iso", 3) && is_in_proc("iso9660")) + else if (!strncmp(lowtype, "iso", 3) && is_in_procfs("iso9660")) error ("mount: maybe you meant iso9660 ?"); free(lowtype); } else @@ -893,8 +732,9 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, type = type0; } if (opts) { - opts = realloc(xstrdup(opts), strlen(opts)+4); - strcat(opts, ",ro"); + char *opts1 = realloc(xstrdup(opts), strlen(opts)+4); + strcat(opts1, ",ro"); + opts = opts1; } else opts = "ro"; if (type && !strcmp(type, "guess")) @@ -916,42 +756,56 @@ try_mount_one (char *spec0, char *node0, char *type0, char *opts0, * identified in a "ps" listing. */ static void -set_proc_name (char *spec) +set_proc_name (const char *spec) { #ifdef DO_PS_FIDDLING - int i, l; - - /* - * Move the environment so we can reuse the memory. - * (Code borrowed from sendmail.) - * WARNING: ugly assumptions on memory layout here; if this ever causes - * problems, #undef DO_PS_FIDDLING - */ - for (i = 0; envp0[i] != NULL; i++) - continue; - environ = (char **) xmalloc(sizeof(char *) * (i + 1)); - for (i = 0; envp0[i] != NULL; i++) - environ[i] = xstrdup(envp0[i]); - environ[i] = NULL; - - if (i > 0) - l = envp0[i-1] + strlen(envp0[i-1]) - argv0[0]; - else - l = argv0[argc0-1] + strlen(argv0[argc0-1]) - argv0[0]; - if (l > sizeof(PROC_NAME)) { - strcpy(argv0[0], PROC_NAME); - strncpy(argv0[0] + sizeof(PROC_NAME) - 1, spec, l - sizeof(PROC_NAME) - 1); - argv0[1] = NULL; - } + setproctitle ("mount", spec); #endif } +static char * +subst_string(const char *s, const char *sub, int sublen, const char *repl) { + char *n; + + n = (char *) xmalloc(strlen(s)-sublen+strlen(repl)+1); + strncpy (n, s, sub-s); + strcpy (n + (sub-s), repl); + strcat (n, sub+sublen); + return n; +} + +static const char * +usersubst(const char *opts) { + char *s, *w; + char id[40]; + + s = "uid=useruid"; + if (opts && (w = strstr(opts, s)) != NULL) { + sprintf(id, "uid=%d", getuid()); + opts = subst_string(opts, w, strlen(s), id); + } + s = "gid=usergid"; + if (opts && (w = strstr(opts, s)) != NULL) { + sprintf(id, "gid=%d", getgid()); + opts = subst_string(opts, w, strlen(s), id); + } + return opts; +} + + +/* + * Return 0 for success (either mounted sth or -a and NOAUTO was given) + */ static int -mount_one (char *spec, char *node, char *type, char *opts, char *cmdlineopts, - int freq, int pass) -{ +mount_one (const char *spec, const char *node, char *type, const char *opts, + char *cmdlineopts, int freq, int pass) { int status; int status2; + int specset = 0; + char *nspec; + + /* Substitute values in opts, if required */ + opts = usersubst(opts); /* Merge the fstab and command line options. */ if (opts == NULL) @@ -959,6 +813,26 @@ mount_one (char *spec, char *node, char *type, char *opts, char *cmdlineopts, else if (cmdlineopts != NULL) opts = xstrconcat3(opts, ",", cmdlineopts); + if (!strncmp(spec, "UUID=", 5)) { + nspec = get_spec_by_uuid(spec+5); + specset = 1; + } else if (!strncmp(spec, "LABEL=", 6)) { + nspec = get_spec_by_volume_label(spec+6); + specset = 2; + } else + nspec = 0; /* just for gcc */ + + if (specset) { + if (nspec) { + spec = nspec; + if (verbose) + printf("mount: consider mounting %s by %s\n", spec, + (specset==1) ? "UUID" : "label"); + } else if(!all) + die (EX_USAGE, "mount: no such partition found"); + /* if -a then we may be rescued by a noauto option */ + } + if (type == NULL) { if (strchr (spec, ':') != NULL) { type = "nfs"; @@ -1146,10 +1020,11 @@ static struct option longopts[] = }; const char *usage_string = "\ -usage: mount [-hV]\n\ +Usage: mount [-hV]\n\ mount -a [-nfFrsvw] [-t vfstypes]\n\ mount [-nfrsvw] [-o options] special | node\n\ mount [-nfrsvw] [-t vfstype] [-o options] special node\n\ +A special device can be indicated by -L label or -U uuid . "; static void @@ -1162,18 +1037,26 @@ usage (FILE *fp, int n) int main (int argc, char *argv[]) { - int c, result = 0; - char *options = NULL, *spec; + int c, result = 0, specseen; + char *options = NULL, *spec, *node; + char *volumelabel = NULL; + char *uuid = NULL; string_list types = NULL; struct mntentchn *mc; + int fd; + + /* People report that a mount called from init without console + writes error messages to /etc/mtab + Let us try to avoid getting fd's 0,1,2 */ + while((fd = open("/dev/null", O_RDWR)) == 0 || fd == 1 || fd == 2) ; + if (fd > 2) + close(fd); #ifdef DO_PS_FIDDLING - argc0 = argc; - argv0 = argv; - envp0 = environ; + initproctitle(argc, argv); #endif - while ((c = getopt_long (argc, argv, "afFhno:rsvVwt:", longopts, NULL)) + while ((c = getopt_long (argc, argv, "afFhL:no:rsU:vVwt:", longopts, NULL)) != EOF) switch (c) { case 'a': /* mount everything in fstab */ @@ -1188,6 +1071,9 @@ main (int argc, char *argv[]) { case 'h': /* help */ usage (stdout, 0); break; + case 'L': + volumelabel = optarg; + break; case 'n': /* mount without writing in /etc/mtab */ ++nomtab; break; @@ -1207,6 +1093,9 @@ main (int argc, char *argv[]) { case 't': /* specify file system types */ types = parse_list (optarg); break; + case 'U': + uuid = optarg; + break; case 'v': /* be chatty - very chatty if repeated */ ++verbose; break; @@ -1227,7 +1116,9 @@ main (int argc, char *argv[]) { argc -= optind; argv += optind; - if (argc == 0 && !all) { + specseen = (uuid || volumelabel) ? 1 : 0; /* yes, .. i know */ + + if (argc+specseen == 0 && !all) { if (options) usage (stderr, EX_USAGE); return print_all (types); @@ -1235,7 +1126,8 @@ main (int argc, char *argv[]) { if (getuid () != geteuid ()) { suid = 1; - if (types || options || readwrite || nomtab || all || fake || argc != 1) + if (types || options || readwrite || nomtab || all || fake || + (argc + specseen) != 1) die (EX_USAGE, "mount: only root can do that"); } @@ -1245,7 +1137,19 @@ main (int argc, char *argv[]) { create_mtab (); } - switch (argc) { + if (specseen) { + if (uuid) + spec = get_spec_by_uuid(uuid); + else + spec = get_spec_by_volume_label(volumelabel); + if (!spec) + die (EX_USAGE, "mount: no such partition found"); + if (verbose) + printf("mount: mounting %s\n", spec); + } else + spec = NULL; /* just for gcc */ + + switch (argc+specseen) { case 0: /* mount -a */ result = mount_all (types, options); @@ -1257,13 +1161,32 @@ main (int argc, char *argv[]) { /* mount [-nfrvw] [-o options] special | node */ if (types != NULL) usage (stderr, EX_USAGE); - - /* Try to find the other pathname in fstab. */ - spec = canonicalize (*argv); - if ((mc = getmntfile (spec)) == NULL && - (mc = getfsspec (spec)) == NULL && (mc = getfsfile (spec)) == NULL) - die (EX_USAGE, "mount: can't find %s in %s or %s", - spec, MOUNTED, _PATH_FSTAB); + if (specseen) { + /* We know the device. Where shall we mount it? */ + mc = (uuid ? getfsuuidspec (uuid) : getfsvolspec (volumelabel)); + if (mc == NULL) + mc = getfsspec (spec); + if (mc == NULL) + die (EX_USAGE, "mount: cannot find %s in %s", + spec, _PATH_FSTAB); + mc->mnt_fsname = spec; + } else { + /* Try to find the other pathname in fstab. */ + spec = canonicalize (*argv); + if ((mc = getfsspec (spec)) == NULL && + (mc = getfsfile (spec)) == NULL && + /* Try noncanonical name in fstab + perhaps /dev/cdrom or /dos is a symlink */ + (mc = getfsspec (*argv)) == NULL && + (mc = getfsfile (*argv)) == NULL && + /* Try mtab - maybe this was a remount */ + (mc = getmntfile (spec)) == NULL) + die (EX_USAGE, "mount: can't find %s in %s or %s", + spec, _PATH_FSTAB, MOUNTED); + /* Earlier mtab was tried first, but this would + sometimes try the wrong mount in case mtab had + the root device entry wrong. */ + } result = mount_one (xstrdup (mc->mnt_fsname), xstrdup (mc->mnt_dir), xstrdup (mc->mnt_type), mc->mnt_opts, options, 0, 0); @@ -1271,12 +1194,17 @@ main (int argc, char *argv[]) { case 2: /* mount [-nfrvw] [-t vfstype] [-o options] special node */ + if (specseen) { + /* we have spec already */ + node = argv[0]; + } else { + spec = argv[0]; + node = argv[1]; + } if (types == NULL) - result = mount_one (argv[0], argv[1], - NULL, NULL, options, 0, 0); + result = mount_one (spec, node, NULL, NULL, options, 0, 0); else if (cdr (types) == NULL) - result = mount_one (argv[0], argv[1], - car (types), NULL, options, 0, 0); + result = mount_one (spec, node, car (types), NULL, options, 0, 0); else usage (stderr, EX_USAGE); break; |