diff options
author | Karel Zak | 2006-12-07 00:26:24 +0100 |
---|---|---|
committer | Karel Zak | 2006-12-07 00:26:24 +0100 |
commit | d162fcb550a77875c8f58fda0e0a0bd91f211c99 (patch) | |
tree | bd984959acd465b3058bd805f216d29dc0c3c1a6 /mount | |
parent | Imported from util-linux-2.12i tarball. (diff) | |
download | kernel-qcow2-util-linux-d162fcb550a77875c8f58fda0e0a0bd91f211c99.tar.gz kernel-qcow2-util-linux-d162fcb550a77875c8f58fda0e0a0bd91f211c99.tar.xz kernel-qcow2-util-linux-d162fcb550a77875c8f58fda0e0a0bd91f211c99.zip |
Imported from util-linux-2.12j tarball.
Diffstat (limited to 'mount')
-rw-r--r-- | mount/fstab.c | 2 | ||||
-rw-r--r-- | mount/lomount.c | 126 | ||||
-rw-r--r-- | mount/losetup.8 | 52 | ||||
-rw-r--r-- | mount/mount.8 | 20 | ||||
-rw-r--r-- | mount/mount.c | 183 | ||||
-rw-r--r-- | mount/mount_blkid.c | 2 | ||||
-rw-r--r-- | mount/mount_by_label.c | 6 | ||||
-rw-r--r-- | mount/mount_guess_fstype.c | 2 | ||||
-rw-r--r-- | mount/mount_guess_rootdev.c | 2 | ||||
-rw-r--r-- | mount/swapon.8 | 4 | ||||
-rw-r--r-- | mount/swapon.c | 9 | ||||
-rw-r--r-- | mount/umount.8 | 3 | ||||
-rw-r--r-- | mount/umount.c | 145 |
13 files changed, 357 insertions, 199 deletions
diff --git a/mount/fstab.c b/mount/fstab.c index b1343f32b..09b5f584d 100644 --- a/mount/fstab.c +++ b/mount/fstab.c @@ -105,7 +105,7 @@ static void discard_mntentchn(struct mntentchn *mc0) { struct mntentchn *mc, *mc1; - for (mc = mc0->nxt; mc != mc0; mc = mc1) { + for (mc = mc0->nxt; mc && mc != mc0; mc = mc1) { mc1 = mc->nxt; my_free(mc->m.mnt_fsname); my_free(mc->m.mnt_dir); diff --git a/mount/lomount.c b/mount/lomount.c index ea8d4a4ae..b7ac356e1 100644 --- a/mount/lomount.c +++ b/mount/lomount.c @@ -1,17 +1,4 @@ -/* Taken from Ted's losetup.c - Mitch <m.dsouza@mrc-apu.cam.ac.uk> */ -/* Added vfs mount options - aeb - 960223 */ -/* Removed lomount - aeb - 960224 */ - -/* - * 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@pld.ORG.PL> - * - added Native Language Support - * 1999-03-21 Arnaldo Carvalho de Melo <acme@conectiva.com.br> - * - fixed strerr(errno) in gettext calls - * 2000-09-24 Marc Mutz <Marc@Mutz.com> - * - added -p option to pass passphrases via fd's to losetup/mount. - * Used for encryption in non-interactive environments. - * The idea behind xgetpass() is stolen from GnuPG, v.1.0.3. - */ +/* Originally from Ted's losetup.c */ #define LOOPMAJOR 7 @@ -37,6 +24,7 @@ #include "nls.h" extern int verbose; +extern char *progname; extern char *xstrdup (const char *s); /* not: #include "sundries.h" */ extern void error (const char *fmt, ...); /* idem */ @@ -186,15 +174,15 @@ find_unused_loop_device (void) { } if (!somedev) - error(_("mount: could not find any device /dev/loop#")); - else if (!someloop) { + error(_("%s: could not find any device /dev/loop#"), progname); + else if (!someloop) error(_( - "mount: Could not find any loop device. Maybe this kernel " + "%s: Could not find any loop device. Maybe this kernel " "does not know\n" " about the loop device? (If so, recompile or " - "`modprobe loop'.)")); - } else - error(_("mount: could not find any free loop device")); + "`modprobe loop'.)"), progname); + else + error(_("%s: could not find any free loop device"), progname); return 0; } @@ -226,15 +214,16 @@ xgetpass(int pfd, const char *prompt) { break; } } - if (read(pfd, pass+i, 1) != 1 || pass[i] == '\n') + if (read(pfd, pass+i, 1) != 1 || + pass[i] == '\n' || pass[i] == 0) break; } + if (pass == NULL) return ""; - else { - pass[i] = 0; - return pass; - } + + pass[i] = 0; + return pass; } static int @@ -249,7 +238,7 @@ int set_loop(const char *device, const char *file, unsigned long long offset, const char *encryption, int pfd, int *loopro) { struct loop_info64 loopinfo64; - int fd, ffd, mode, i; + int fd, ffd, mode, i, n; char *pass; mode = (*loopro ? O_RDONLY : O_RDWR); @@ -302,16 +291,15 @@ set_loop(const char *device, const char *file, unsigned long long offset, break; case LO_CRYPT_XOR: pass = getpass(_("Password: ")); - xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE); - memset(pass, 0, strlen(pass)); - loopinfo64.lo_encrypt_key_size = - strlen(loopinfo64.lo_encrypt_key); - break; + goto gotpass; default: pass = xgetpass(pfd, _("Password: ")); + gotpass: xstrncpy(loopinfo64.lo_encrypt_key, pass, LO_KEY_SIZE); - memset(pass, 0, strlen(pass)); - loopinfo64.lo_encrypt_key_size = LO_KEY_SIZE; + n = strlen(pass); + memset(pass, 0, n); + loopinfo64.lo_encrypt_key_size = + (n < LO_KEY_SIZE) ? n : LO_KEY_SIZE; } if (ioctl(fd, LOOP_SET_FD, ffd) < 0) { @@ -413,10 +401,11 @@ static char *progname; static void usage(void) { fprintf(stderr, _("usage:\n\ - %s loop_device # give info\n\ - %s -d loop_device # delete\n\ - %s [ -e encryption ] [ -o offset ] loop_device file # setup\n"), - progname, progname, progname); + %s loop_device # give info\n\ + %s -d loop_device # delete\n\ + %s -f # find unused\n\ + %s [-e encryption] [-o offset] {-f|loop_device} file # setup\n"), + progname, progname, progname, progname); exit(1); } @@ -449,8 +438,8 @@ error (const char *fmt, ...) { int main(int argc, char **argv) { - char *offset, *encryption, *passfd; - int delete, c; + char *p, *offset, *encryption, *passfd, *device, *file; + int delete, find, c; int res = 0; int ro = 0; int pfd = -1; @@ -460,10 +449,15 @@ main(int argc, char **argv) { bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); - delete = off = 0; + delete = find = 0; + off = 0; offset = encryption = passfd = NULL; + progname = argv[0]; - while ((c = getopt(argc,argv,"de:E:o:p:v")) != -1) { + if ((p = strrchr(progname, '/')) != NULL) + progname = p+1; + + while ((c = getopt(argc, argv, "de:E:fo:p:v")) != -1) { switch (c) { case 'd': delete = 1; @@ -472,6 +466,9 @@ main(int argc, char **argv) { case 'e': encryption = optarg; break; + case 'f': + find = 1; + break; case 'o': offset = optarg; break; @@ -485,22 +482,49 @@ main(int argc, char **argv) { usage(); } } - if (argc == 1) usage(); - if ((delete && (argc != optind+1 || encryption || offset)) || - (!delete && (argc < optind+1 || argc > optind+2))) + + if (argc == 1) { usage(); - if (argc == optind+1) { - if (delete) - res = del_loop(argv[optind]); - else - res = show_loop(argv[optind]); + } else if (delete) { + if (argc != optind+1 || encryption || offset || find) + usage(); + } else if (find) { + if (argc < optind || argc > optind+1) + usage(); + } else { + if (argc < optind+1 || argc > optind+2) + usage(); + } + + if (find) { + device = find_unused_loop_device(); + if (device == NULL) + return -1; + if (verbose) + printf("Loop device is %s\n", device); + if (argc == optind) { + printf("%s\n", device); + return 0; + } + file = argv[optind]; } else { + device = argv[optind]; + if (argc == optind+1) + file = NULL; + else + file = argv[optind+1]; + } + + if (delete) + res = del_loop(device); + else if (file == NULL) + res = show_loop(device); + else { if (offset && sscanf(offset, "%llu", &off) != 1) usage(); if (passfd && sscanf(passfd, "%d", &pfd) != 1) usage(); - res = set_loop(argv[optind], argv[optind+1], off, - encryption, pfd, &ro); + res = set_loop(device, file, off, encryption, pfd, &ro); } return res; } diff --git a/mount/losetup.8 b/mount/losetup.8 index 9a42d70a0..06022ef4e 100644 --- a/mount/losetup.8 +++ b/mount/losetup.8 @@ -3,24 +3,40 @@ losetup \- set up and control loop devices .SH SYNOPSIS .ad l +Get info: +.sp +.in +5 .B losetup -[ -.RB [ \-e | \-E ] -.I encryption -] [ -.B \-o -.I offset -] [ -.B \-p -.I pfd -] -.I loop_device file -.br -.B losetup -[ -.B \-d -] .I loop_device +.sp +.in -5 +Delete loop: +.sp +.in +5 +.B "losetup \-d" +.I loop_device +.sp +.in -5 +Print name of first unused loop device: +.sp +.in +5 +.B "losetup \-f" +.sp +.in -5 +Setup loop device: +.sp +.in +5 +.B losetup +.RB [{\-e | \-E} +.IR encryption ] +.RB [ \-o +.IR offset ] +.RB [ \-p +.IR pfd ] +.in +8 +.RB { \-f | \fIloop_device\fP } +.I file +.in -13 .ad b .SH DESCRIPTION .B losetup @@ -56,6 +72,10 @@ Detach the file or device associated with the specified loop device. Enable data encryption with specified number. .IP "\fB\-e \fIencryption_name\fP" Enable data encryption with specified name. +.IP "\fB\-f\fP" +Find the first unused loop device. If a +.I file +argument is present, use this device. Otherwise, print its name. .IP "\fB\-o \fIoffset\fP" The data start is moved \fIoffset\fP bytes into the specified file or device. diff --git a/mount/mount.8 b/mount/mount.8 index a4b6a51ac..f6bf2b438 100644 --- a/mount/mount.8 +++ b/mount/mount.8 @@ -216,6 +216,10 @@ option, with the restriction that the user must be the owner of the special file. This may be useful e.g. for .I /dev/fd if a login script makes the console user owner of this device. +The +.B group +option is similar, with the restriction that the user must be +member of the group of the special file. The programs .B mount @@ -551,6 +555,14 @@ Interpret character or block special devices on the file system. .B exec Permit execution of binaries. .TP +.B group +Allow an ordinary (i.e., non-root) user to mount the file system if one +of his groups matches the group of the device. +This option implies the options +.BR nosuid " and " nodev +(unless overridden by subsequent options, as in the option line +.BR group,dev,suid ). +.TP .B _netdev The filesystem resides on a device that requires network access (used to prevent the system from attempting to mount these filesystems @@ -583,6 +595,14 @@ suidperl(1) installed.) Forbid an ordinary (i.e., non-root) user to mount the file system. This is the default. .TP +.B owner +Allow an ordinary (i.e., non-root) user to mount the file system if he +is the owner of the device. +This option implies the options +.BR nosuid " and " nodev +(unless overridden by subsequent options, as in the option line +.BR owner,dev,suid ). +.TP .B remount Attempt to remount an already-mounted file system. This is commonly used to change the mount flags for a file system, especially to make a diff --git a/mount/mount.c b/mount/mount.c index a9ee637d8..f598e8f80 100644 --- a/mount/mount.c +++ b/mount/mount.c @@ -96,6 +96,7 @@ struct opt_map { #define MS_USERS 0x40000000 #define MS_USER 0x20000000 #define MS_OWNER 0x10000000 +#define MS_GROUP 0x08000000 #define MS_COMMENT 0x00020000 #define MS_LOOP 0x00010000 @@ -135,6 +136,8 @@ static const struct opt_map opt_map[] = { { "nouser", 0, 1, MS_USER }, /* Forbid ordinary user to mount */ { "owner", 0, 0, MS_OWNER }, /* Let the owner of the device mount */ { "noowner", 0, 1, MS_OWNER }, /* Device owner has no special privs */ + { "group", 0, 0, MS_GROUP }, /* Let the group of the device mount */ + { "nogroup", 0, 1, MS_GROUP }, /* Device group has no special privs */ { "_netdev", 0, 0, MS_COMMENT}, /* Device requires network */ { "comment", 0, 0, MS_COMMENT}, /* fstab comment only (kudzu,_netdev)*/ @@ -263,7 +266,8 @@ parse_opt (const char *opt, int *mask, char *extra_opts) { if ((om->mask == MS_USER || om->mask == MS_USERS) && !om->inv) *mask |= MS_SECURE; - if ((om->mask == MS_OWNER) && !om->inv) + if ((om->mask == MS_OWNER || om->mask == MS_GROUP) + && !om->inv) *mask |= MS_OWNERSECURE; #ifdef MS_SILENT if (om->mask == MS_SILENT && om->inv) { @@ -507,20 +511,47 @@ guess_fstype_and_mount(const char *spec, const char *node, const char **types, static void suid_check(const char *spec, const char *node, int *flags, char **user) { if (suid) { - /* RedHat patch: allow owners to mount when fstab contains - the owner option. Note that this should never be used - in a high security environment, but may be useful to give - people at the console the possibility of mounting a floppy. */ - if (*flags & MS_OWNER) { - if (!strncmp(spec, "/dev/", 5)) { - struct stat sb; - - if (!stat(spec, &sb)) { + /* + * MS_OWNER: Allow owners to mount when fstab contains + * the owner option. Note that this should never be used + * in a high security environment, but may be useful to give + * people at the console the possibility of mounting a floppy. + * MS_GROUP: Allow members of device group to mount. (Martin Dickopp) + */ + if (*flags & (MS_OWNER | MS_GROUP)) { + struct stat sb; + + if (!strncmp(spec, "/dev/", 5) && stat(spec, &sb) == 0) { + + if (*flags & MS_OWNER) { if (getuid() == sb.st_uid) *flags |= MS_USER; } + + if (*flags & MS_GROUP) { + if (getgid() == sb.st_gid) + *flags |= MS_USER; + else { + int n = getgroups(0, NULL); + + if (n > 0) { + gid_t *groups = xmalloc(n * sizeof(*groups)); + if (getgroups(n, groups) == n) { + int i; + for (i = 0; i < n; i++) { + if (groups[i] == sb.st_gid) { + *flags |= MS_USER; + break; + } + } + } + free(groups); + } + } + } } } + /* James Kehl <mkehl@gil.com.au> came with a similar patch: allow an arbitrary user to mount when he is the owner of the mount-point and has write-access to the device. @@ -537,8 +568,7 @@ suid_check(const char *spec, const char *node, int *flags, char **user) { *user = getusername(); } - if (*flags & MS_OWNER) - *flags &= ~MS_OWNER; + *flags &= ~(MS_OWNER | MS_GROUP); } static int @@ -927,13 +957,13 @@ retry_nfs: error (_("mount: %s not mounted already, or bad option"), node); } else { error (_("mount: wrong fs type, bad option, bad superblock on %s,\n" - " or too many mounted file systems"), + " missing codepage, or too many mounted file systems"), spec); if (stat(spec, &statbuf) == 0 && S_ISBLK(statbuf.st_mode) && (fd = open(spec, O_RDONLY | O_NONBLOCK)) >= 0) { if (ioctl(fd, BLKGETSIZE, &size) == 0) { - if (size == 0) { + if (size == 0 && !loop) { warned++; error (" (could this be the IDE device where you in fact use\n" " ide-scsi so that sr0 or sda or so is needed?)"); @@ -1111,61 +1141,63 @@ is_existing_file (const char *s) { static int mount_one (const char *spec, const char *node, const char *types, const char *opts, char *cmdlineopts, int freq, int pass) { - int status, status2; - const char *nspec; - - /* Substitute values in opts, if required */ - opts = usersubst(opts); - - /* Merge the fstab and command line options. */ - if (opts == NULL) - opts = cmdlineopts; - else if (cmdlineopts != NULL) - opts = xstrconcat3(opts, ",", cmdlineopts); - - /* Handle possible LABEL= and UUID= forms of spec */ - nspec = mount_get_devname_for_mounting(spec); - if (nspec) - spec = nspec; - - if (types == NULL && !mounttype && !is_existing_file(spec)) { - if (strchr (spec, ':') != NULL) { - types = "nfs"; - if (verbose) - printf(_("mount: no type was given - " - "I'll assume nfs because of the colon\n")); - } else if(!strncmp(spec, "//", 2)) { - types = "smbfs"; - if (verbose) - printf(_("mount: no type was given - " - "I'll assume smbfs because of the // prefix\n")); - } - } - - /* - * Try to mount the file system. When the exit status is EX_BG, - * we will retry in the background. Otherwise, we're done. - */ - status = try_mount_one (spec, node, types, opts, freq, pass, 0, 0); - if (status != EX_BG) - return status; + int status, status2; + const char *nspec; + + /* Substitute values in opts, if required */ + opts = usersubst(opts); + + /* Merge the fstab and command line options. */ + if (opts == NULL) + opts = cmdlineopts; + else if (cmdlineopts != NULL) + opts = xstrconcat3(opts, ",", cmdlineopts); + + /* Handle possible LABEL= and UUID= forms of spec */ + nspec = mount_get_devname_for_mounting(spec); + if (nspec) + spec = nspec; + + if (types == NULL && !mounttype && !is_existing_file(spec)) { + if (strchr (spec, ':') != NULL) { + types = "nfs"; + if (verbose) + printf(_("mount: no type was given - " + "I'll assume nfs because of " + "the colon\n")); + } else if(!strncmp(spec, "//", 2)) { + types = "smbfs"; + if (verbose) + printf(_("mount: no type was given - " + "I'll assume smbfs because of " + "the // prefix\n")); + } + } - /* - * Retry in the background. - */ - printf (_("mount: backgrounding \"%s\"\n"), spec); - fflush( stdout ); /* prevent duplicate output */ - if (fork() > 0) - return 0; /* parent returns "success" */ - spec = xstrdup(spec); /* arguments will be destroyed */ - node = xstrdup(node); /* by set_proc_name() */ - types = xstrdup(types); - opts = xstrdup(opts); - set_proc_name (spec); /* make a nice "ps" listing */ - status2 = try_mount_one (spec, node, types, opts, freq, pass, 1, 0); - if (verbose && status2) - printf (_("mount: giving up \"%s\"\n"), spec); - exit (0); /* child stops here */ + /* + * Try to mount the file system. When the exit status is EX_BG, + * we will retry in the background. Otherwise, we're done. + */ + status = try_mount_one (spec, node, types, opts, freq, pass, 0, 0); + if (status != EX_BG) + return status; + + /* + * Retry in the background. + */ + printf (_("mount: backgrounding \"%s\"\n"), spec); + fflush( stdout ); /* prevent duplicate output */ + if (fork() > 0) + return 0; /* parent returns "success" */ + spec = xstrdup(spec); /* arguments will be destroyed */ + node = xstrdup(node); /* by set_proc_name() */ + types = xstrdup(types); + opts = xstrdup(opts); + set_proc_name (spec); /* make a nice "ps" listing */ + status2 = try_mount_one (spec, node, types, opts, freq, pass, 1, 0); + if (verbose && status2) + printf (_("mount: giving up \"%s\"\n"), spec); + exit (0); /* child stops here */ } /* Check if an fsname/dir pair was already in the old mtab. */ @@ -1177,6 +1209,8 @@ mounted (const char *spec0, const char *node0) { /* Handle possible UUID= and LABEL= in spec */ spec0 = mount_get_devname(spec0); + if (!spec0) + return ret; spec = canonicalize(spec0); node = canonicalize(node0); @@ -1189,8 +1223,8 @@ mounted (const char *spec0, const char *node0) { break; } - free(spec); - free(node); + my_free(spec); + my_free(node); return ret; } @@ -1407,14 +1441,17 @@ usage (FILE *fp, int n) { exit (n); } +char *progname; + int -main (int argc, char *argv[]) { +main(int argc, char *argv[]) { int c, result = 0, specseen; char *options = NULL, *test_opts = NULL, *node; const char *spec; char *volumelabel = NULL; char *uuid = NULL; char *types = NULL; + char *p; struct mntentchn *mc; int fd; @@ -1423,6 +1460,10 @@ main (int argc, char *argv[]) { bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); + progname = argv[0]; + if ((p = strrchr(progname, '/')) != NULL) + progname = p+1; + umask(033); /* People report that a mount called from init without console diff --git a/mount/mount_blkid.c b/mount/mount_blkid.c index 7abadec29..47c48b39e 100644 --- a/mount/mount_blkid.c +++ b/mount/mount_blkid.c @@ -57,7 +57,7 @@ mount_blkid_put_cache(void) { const char * mount_get_volume_label_by_spec(const char *spec) { - return strdup(get_volume_label_by_spec(spec)); + return xstrdup(get_volume_label_by_spec(spec)); } const char * diff --git a/mount/mount_by_label.c b/mount/mount_by_label.c index 80d252ca7..c804e2031 100644 --- a/mount/mount_by_label.c +++ b/mount/mount_by_label.c @@ -94,7 +94,7 @@ uuidcache_init_lvm(void) { sprintf(lvm_device, "%s/%s/%s", DEVLABELDIR, vg_iter->d_name, lv_iter->d_name); if (!get_label_uuid(lvm_device, &label, uuid)) - uuidcache_addentry(strdup(lvm_device), + uuidcache_addentry(xstrdup(lvm_device), label, uuid); } closedir(lv_list); @@ -117,7 +117,7 @@ uuidcache_init_evms(void) { while (fgets(line, sizeof(line), procvol)) { if (sscanf(line, "%*d %*d %*d %*s %*s %[^\n]", volname) == 1) { if (!get_label_uuid(volname, &label, uuid)) - uuidcache_addentry(strdup(volname), label, uuid); + uuidcache_addentry(xstrdup(volname), label, uuid); } } @@ -243,7 +243,7 @@ uuidcache_init(void) { */ sprintf(device, "%s/%s", DEVLABELDIR, ptname); if (!get_label_uuid(device, &label, uuid)) - uuidcache_addentry(strdup(device), label, uuid); + uuidcache_addentry(xstrdup(device), label, uuid); } } } diff --git a/mount/mount_guess_fstype.c b/mount/mount_guess_fstype.c index 96220db35..54ff3b8d5 100644 --- a/mount/mount_guess_fstype.c +++ b/mount/mount_guess_fstype.c @@ -559,7 +559,7 @@ procfsnext(FILE *procfs) { while (fgets(line, sizeof(line), procfs)) { if (sscanf (line, "nodev %[^\n]\n", fsname) == 1) continue; if (sscanf (line, " %[^ \n]\n", fsname) != 1) continue; - return strdup(fsname); + return xstrdup(fsname); } return 0; } diff --git a/mount/mount_guess_rootdev.c b/mount/mount_guess_rootdev.c index 1c63cd7c1..c0f0f5034 100644 --- a/mount/mount_guess_rootdev.c +++ b/mount/mount_guess_rootdev.c @@ -60,7 +60,7 @@ rootdev(char *p) { sprintf(devname, "/dev/%s%c", type, let); else sprintf(devname, "/dev/%s%c%d", type, let, mi); - return strdup(devname); + return xstrdup(devname); } return NULL; } diff --git a/mount/swapon.8 b/mount/swapon.8 index 6dca7eb3d..223ea5064 100644 --- a/mount/swapon.8 +++ b/mount/swapon.8 @@ -80,8 +80,8 @@ Not available before Linux 2.1.25. .B \-a All devices marked as ``swap'' swap devices in .I /etc/fstab -are made available. Devices that are already running as swap are silently -skipped. +are made available, except for those with the ``noauto'' option. +Devices that are already running as swap are silently skipped. .TP .B \-e When diff --git a/mount/swapon.c b/mount/swapon.c index 71b251508..f347c2c79 100644 --- a/mount/swapon.c +++ b/mount/swapon.c @@ -315,6 +315,7 @@ main_swapon(int argc, char *argv[]) { } while ((fstab = getmntent(fp)) != NULL) { char *special = fstab->mnt_fsname; + int skip = 0; if (streq(fstab->mnt_type, MNTTYPE_SWAP) && !is_in_proc_swaps(special) @@ -323,10 +324,14 @@ main_swapon(int argc, char *argv[]) { char *opt, *opts = strdup(fstab->mnt_opts); for (opt = strtok(opts, ","); opt != NULL; - opt = strtok(NULL, ",")) + opt = strtok(NULL, ",")) { if (strncmp(opt, "pri=", 4) == 0) priority = atoi(opt+4); - status |= do_swapon(special, priority); + if (strcmp(opt, "noauto") == 0) + skip = 1; + } + if (!skip) + status |= do_swapon(special, priority); } } fclose(fp); diff --git a/mount/umount.8 b/mount/umount.8 index 3449779e2..fafbff269 100644 --- a/mount/umount.8 +++ b/mount/umount.8 @@ -74,6 +74,9 @@ In case unmounting fails, try to remount read-only. In case the unmounted device was a loop device, also free this loop device. .TP +.B \-i +Don't call the /sbin/umount.<filesystem> helper even if it exists. By default /sbin/umount.<filesystem> helper is called if one exists. +.TP .B \-a All of the file systems described in .I /etc/mtab diff --git a/mount/umount.c b/mount/umount.c index c26246c52..bebc8ad79 100644 --- a/mount/umount.c +++ b/mount/umount.c @@ -1,32 +1,5 @@ /* - * A umount(8) for Linux 0.99. - * umount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp - * - * Wed Sep 14 22:43:54 1994: Sebastian Lederer - * (lederer@next-pc.informatik.uni-bonn.de) added support for sending an - * unmount RPC call to the server when an NFS-filesystem is unmounted. - * - * Tue Sep 26 16:33:09 1995: Added patches from Greg Page (greg@caldera.com) - * so that NetWare filesystems can be unmounted. - * - * 951213: Marek Michalkiewicz <marekm@i17linuxb.ists.pwr.wroc.pl>: - * Ignore any RPC errors, so that you can umount an nfs mounted filesystem - * if the server is down. - * - * 960223: aeb - several minor changes - * 960324: aeb - added some changes from Rob Leslie <rob@mars.org> - * 960823: aeb - also try umount(spec) when umount(node) fails - * 970307: aeb - canonicalise names from fstab - * 970726: aeb - remount read-only in cases where umount fails - * 980810: aeb - umount2 support - * 981222: aeb - If mount point or special file occurs several times - * in mtab, try them all, with last one tried first - * - Differentiate "user" and "users" key words in fstab - * 001202: aeb - remove at most one line from /etc/mtab - * 010716: Michael K. Johnson <johnsonm@redhat.com: -a -O - * 010914: Jamie Strandboge - use tcp if that was used for mount - * 011005: hch - add lazy umount support - * 020105: aeb - permission test owner umount + * umount(8) for Linux 0.99 - jrs, 1993 */ #include <stdio.h> @@ -36,6 +9,7 @@ #include <errno.h> #include <ctype.h> #include <sys/stat.h> +#include <sys/wait.h> #include <sys/mount.h> #include "mount_constants.h" #include "sundries.h" @@ -91,6 +65,10 @@ umount2(const char *path, int flags) { #define MNT_DETACH 2 #endif + +/* True if we are allowed to call /sbin/umount.${FSTYPE} */ +int external_allowed = 1; + /* Nonzero for force umount (-f). There is kernel support since 2.1.116. */ int force = 0; @@ -112,15 +90,61 @@ int verbose = 0; /* True if ruid != euid. */ int suid = 0; -#ifdef USE_SPECIAL_UMOUNTPROG -/* unimplemented so far */ +/* + * check_special_umountprog() + * If there is a special umount program for this type, exec it. + * returns: 0: no exec was done, 1: exec was done, status has result + */ static int -check_special_umountprog() { - /* find type from command line or /etc/mtab; - stat /sbin/umount.%s - if it exists, use it */ +check_special_umountprog(const char *spec, const char *node, + const char *type, int *status) { + char umountprog[120]; + struct stat statbuf; + int res; + + if (!external_allowed) + return 0; + + if (type && strlen(type) < 100) { + sprintf(umountprog, "/sbin/umount.%s", type); + if (stat(umountprog, &statbuf) == 0) { + res = fork(); + if (res == 0) { + char *umountargs[8]; + int i = 0; + + setuid(getuid()); + setgid(getgid()); + umountargs[i++] = umountprog; + umountargs[i++] = xstrdup(node); + if (nomtab) + umountargs[i++] = "-n"; + if (lazy) + umountargs[i++] = "-l"; + if (force) + umountargs[i++] = "-f"; + if (verbose) + umountargs[i++] = "-v"; + if (remount) + umountargs[i++] = "-r"; + umountargs[i] = NULL; + execv(umountprog, umountargs); + exit(1); /* exec failed */ + } else if (res != -1) { + int st; + wait(&st); + *status = (WIFEXITED(st) ? WEXITSTATUS(st) + : EX_SYSERR); + return 1; + } else { + int errsv = errno; + error(_("umount: cannot fork: %s"), + strerror(errsv)); + } + } + } + return 0; } -#endif #ifdef HAVE_NFS static int xdr_dir(XDR *xdrsp, char *dirp) @@ -248,6 +272,7 @@ umount_one (const char *spec, const char *node, const char *type, int umnt_err, umnt_err2; int isroot; int res; + int status; const char *loopdev; /* Special case for root. As of 0.99pl10 we can (almost) unmount root; @@ -260,6 +285,13 @@ umount_one (const char *spec, const char *node, const char *type, || streq (node, "rootfs")); if (isroot) nomtab++; + + /* + * Call umount.TYPE for types that require a separate umount program. + * All such special things must occur isolated in the types string. + */ + if (check_special_umountprog(spec, node, type, &status)) + return status; #ifdef HAVE_NFS /* Ignore any RPC errors, so that you can umount the filesystem @@ -322,7 +354,7 @@ umount_one (const char *spec, const char *node, const char *type, spec); remnt.mnt_type = remnt.mnt_fsname = NULL; remnt.mnt_dir = xstrdup(node); - remnt.mnt_opts = "ro"; + remnt.mnt_opts = xstrdup("ro"); update_mtab(node, &remnt); return 0; } else if (errno != EBUSY) { /* hmm ... */ @@ -514,7 +546,8 @@ static int umount_file (char *arg) { struct mntentchn *mc, *fs; const char *file, *options; - int fstab_has_user, fstab_has_users, fstab_has_owner, ok; + int fstab_has_user, fstab_has_users, fstab_has_owner, fstab_has_group; + int ok; file = canonicalize(arg); /* mtab paths are canonicalized */ if (verbose > 1) @@ -556,16 +589,17 @@ umount_file (char *arg) { "the fstab"), file); } - /* User mounting and unmounting is allowed only - if fstab contains one of the options `user', - `users' or `owner'. */ - /* The option `users' allows arbitrary users to mount - and unmount - this may be a security risk. */ - /* The option `user' only allows unmounting by the user - that mounted. */ - /* The option `owner' only allows (un)mounting by the owner. */ - /* A convenient side effect is that the user who mounted - is visible in mtab. */ + /* + * User mounting and unmounting is allowed only + * if fstab contains one of the options `user', + * `users' or `owner' or `group'. + * + * The option `users' allows arbitrary users to mount + * and unmount - this may be a security risk. + * + * The options `user', `owner' and `group' only allow + * unmounting by the user that mounted (visible in mtab). + */ options = fs->m.mnt_opts; if (!options) @@ -573,12 +607,14 @@ umount_file (char *arg) { fstab_has_user = contains(options, "user"); fstab_has_users = contains(options, "users"); fstab_has_owner = contains(options, "owner"); + fstab_has_group = contains(options, "group"); ok = 0; if (fstab_has_users) ok = 1; - if (!ok && (fstab_has_user || fstab_has_owner)) { + if (!ok && (fstab_has_user || fstab_has_owner || + fstab_has_group)) { char *user = getusername(); options = mc->m.mnt_opts; @@ -601,11 +637,13 @@ umount_file (char *arg) { return umount_one (arg, arg, arg, arg, NULL); } +char *progname; + int main (int argc, char *argv[]) { int c; int all = 0; - char *types = NULL, *test_opts = NULL; + char *types = NULL, *test_opts = NULL, *p; int result = 0; sanitize_env(); @@ -613,9 +651,13 @@ main (int argc, char *argv[]) { bindtextdomain(PACKAGE, LOCALEDIR); textdomain(PACKAGE); + progname = argv[0]; + if ((p = strrchr(progname, '/')) != NULL) + progname = p+1; + umask(033); - while ((c = getopt_long (argc, argv, "adfhlnrt:O:vV", + while ((c = getopt_long (argc, argv, "adfhlnrit:O:vV", longopts, NULL)) != -1) switch (c) { case 'a': /* umount everything */ @@ -652,6 +694,9 @@ main (int argc, char *argv[]) { case 't': /* specify file system type */ types = optarg; break; + case 'i': + external_allowed = 0; + break; case 0: break; case '?': |