summaryrefslogtreecommitdiffstats
path: root/mount
diff options
context:
space:
mode:
authorKarel Zak2006-12-07 00:26:24 +0100
committerKarel Zak2006-12-07 00:26:24 +0100
commitd162fcb550a77875c8f58fda0e0a0bd91f211c99 (patch)
treebd984959acd465b3058bd805f216d29dc0c3c1a6 /mount
parentImported from util-linux-2.12i tarball. (diff)
downloadkernel-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.c2
-rw-r--r--mount/lomount.c126
-rw-r--r--mount/losetup.852
-rw-r--r--mount/mount.820
-rw-r--r--mount/mount.c183
-rw-r--r--mount/mount_blkid.c2
-rw-r--r--mount/mount_by_label.c6
-rw-r--r--mount/mount_guess_fstype.c2
-rw-r--r--mount/mount_guess_rootdev.c2
-rw-r--r--mount/swapon.84
-rw-r--r--mount/swapon.c9
-rw-r--r--mount/umount.83
-rw-r--r--mount/umount.c145
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 '?':