summaryrefslogtreecommitdiffstats
path: root/mount
diff options
context:
space:
mode:
authorKarel Zak2006-12-07 00:25:44 +0100
committerKarel Zak2006-12-07 00:25:44 +0100
commit66ee8158b69525e12060ef558cb5d77feadab1dc (patch)
tree08b30f2d07df9213f5647bc6f60b5090a263ef43 /mount
parentImported from util-linux-2.10m tarball. (diff)
downloadkernel-qcow2-util-linux-66ee8158b69525e12060ef558cb5d77feadab1dc.tar.gz
kernel-qcow2-util-linux-66ee8158b69525e12060ef558cb5d77feadab1dc.tar.xz
kernel-qcow2-util-linux-66ee8158b69525e12060ef558cb5d77feadab1dc.zip
Imported from util-linux-2.10s tarball.
Diffstat (limited to 'mount')
-rw-r--r--mount/Makefile11
-rw-r--r--mount/README.mount2
-rw-r--r--mount/bind.c11
-rw-r--r--mount/fstab.c350
-rw-r--r--mount/fstab.h8
-rw-r--r--mount/linux_fs.h49
-rw-r--r--mount/lomount.c51
-rw-r--r--mount/lomount.h1
-rw-r--r--mount/losetup.811
-rw-r--r--mount/mount.811
-rw-r--r--mount/mount.c666
-rw-r--r--mount/mount_by_label.c51
-rw-r--r--mount/mount_constants.h19
-rw-r--r--mount/mount_guess_fstype.c170
-rw-r--r--mount/mount_guess_fstype.h2
-rw-r--r--mount/mount_guess_rootdev.c90
-rw-r--r--mount/mount_guess_rootdev.h1
-rw-r--r--mount/nfs_mount4.h1
-rw-r--r--mount/nfsmount.c20
-rw-r--r--mount/pivot_root.c2
-rw-r--r--mount/umount.87
-rw-r--r--mount/umount.c297
22 files changed, 1147 insertions, 684 deletions
diff --git a/mount/Makefile b/mount/Makefile
index 6f72413db..18e30cde6 100644
--- a/mount/Makefile
+++ b/mount/Makefile
@@ -1,15 +1,13 @@
include ../make_include
include ../MCONFIG
-CFLAGS = -I$(LIB) $(OPT)
-WARNFLAGS = -Wall -Wstrict-prototypes -Wmissing-prototypes
DEFINES = -DHAVE_NFS
RPCSVCDIR = rpcsvc
RPC_CFLAGS = -Wno-unused
RPCGEN = rpcgen
-COMPILE = $(CC) -c $(WARNFLAGS) $(CFLAGS) $(DEFINES)
+COMPILE = $(CC) -c $(CFLAGS) $(DEFINES)
LINK = $(CC) $(LDFLAGS)
SUID_PROGS = mount umount
@@ -24,6 +22,8 @@ endif
PROGS = $(SUID_PROGS) $(NOSUID_PROGS)
+MAYBE = pivot_root swapoff
+
# comment these out if you are not compiling in NFS support
NFS_OBJS = nfsmount.o nfsmount_xdr.o nfsmount_clnt.o
# uncomment this if you don't have libc-4.2 but do have the rpclib
@@ -59,8 +59,7 @@ swapon: swapon.o version.o
$(LINK) $^ -o $@
losetup.o: lomount.c
- $(COMPILE) -DMAIN lomount.c
- mv lomount.o losetup.o
+ $(COMPILE) -DMAIN lomount.c -o $@
losetup: losetup.o
$(LINK) $^ -o $@
@@ -117,7 +116,7 @@ loop.h:
sh mk_loop_h
clean:
- rm -f a.out core *~ *.o swapargs.h $(PROGS) swapoff
+ rm -f a.out core *~ *.o swapargs.h $(PROGS) $(MAYBE)
rm -f loop.h nfs_mountversion.h
clobber distclean realclean: clean
diff --git a/mount/README.mount b/mount/README.mount
index 2a8fae1c1..f010a1bd8 100644
--- a/mount/README.mount
+++ b/mount/README.mount
@@ -6,5 +6,5 @@ Rick Sladkey <jrs@world.std.com>,
Stephen Tweedie <sct@dcs.ed.ac.uk>.
Presently maintained by Andries Brouwer <aeb@cwi.nl>.
-Ftp site: ftp.win.tue.nl:/pub/linux/util .
+Ftp site: ftp.win.tue.nl:/pub/linux/utils/util-linux
diff --git a/mount/bind.c b/mount/bind.c
new file mode 100644
index 000000000..4af72a9c3
--- /dev/null
+++ b/mount/bind.c
@@ -0,0 +1,11 @@
+#include <stdio.h>
+#include <sys/mount.h>
+
+main(int argc, char **argv) {
+ int ret;
+
+ ret = mount(argv[1], argv[2], "bind", MS_MGC_VAL, NULL);
+ if (ret)
+ perror("bind");
+ return ret;
+}
diff --git a/mount/fstab.c b/mount/fstab.c
index aef26d90c..3ee1f36a1 100644
--- a/mount/fstab.c
+++ b/mount/fstab.c
@@ -99,21 +99,19 @@ read_mntentchn(mntFILE *mfp, const char *fnam, struct mntentchn *mc0) {
struct mntent *mnt;
while ((mnt = my_getmntent (mfp)) != NULL) {
- if (!streq (mnt->mnt_type, MNTTYPE_IGNORE)) {
- mc->nxt = (struct mntentchn *) xmalloc(sizeof(*mc));
- mc->nxt->prev = mc;
- mc = mc->nxt;
- mc->mnt_fsname = mnt->mnt_fsname;
- mc->mnt_dir = mnt->mnt_dir;
- mc->mnt_type = mnt->mnt_type;
- mc->mnt_opts = mnt->mnt_opts;
- mc->nxt = NULL;
- }
+ if (!streq (mnt->mnt_type, MNTTYPE_IGNORE)) {
+ mc->nxt = (struct mntentchn *) xmalloc(sizeof(*mc));
+ mc->nxt->prev = mc;
+ mc = mc->nxt;
+ mc->m = *mnt;
+ mc->nxt = mc0;
+ }
}
mc0->prev = mc;
if (ferror (mfp->mntent_fp)) {
int errsv = errno;
- error(_("warning: error reading %s: %s"), fnam, strerror (errsv));
+ error(_("warning: error reading %s: %s"),
+ fnam, strerror (errsv));
mc0->nxt = mc0->prev = NULL;
}
my_endmntent(mfp);
@@ -163,7 +161,8 @@ read_fstab() {
mfp = my_setmntent (fnam, "r");
if (mfp == NULL || mfp->mntent_fp == NULL) {
int errsv = errno;
- error(_("warning: can't open %s: %s"), _PATH_FSTAB, strerror (errsv));
+ error(_("warning: can't open %s: %s"),
+ _PATH_FSTAB, strerror (errsv));
return;
}
read_mntentchn(mfp, fnam, mc);
@@ -173,13 +172,14 @@ read_fstab() {
/* Given the name NAME, try to find it in mtab. */
struct mntentchn *
getmntfile (const char *name) {
- struct mntentchn *mc;
-
- for (mc = mtab_head()->nxt; mc; mc = mc->nxt)
- if (streq (mc->mnt_dir, name) || (streq (mc->mnt_fsname, name)))
- break;
-
- return mc;
+ struct mntentchn *mc, *mc0;
+
+ mc0 = mtab_head();
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+ if (streq (mc->m.mnt_dir, name) ||
+ streq (mc->m.mnt_fsname, name))
+ return mc;
+ return NULL;
}
/*
@@ -188,110 +188,108 @@ getmntfile (const char *name) {
*/
struct mntentchn *
getmntfilesbackward (const char *name, struct mntentchn *mcprev) {
- struct mntentchn *mc, *mh;
-
- mh = mtab_head();
- if (!mcprev)
- mcprev = mh;
- for (mc = mcprev->prev; mc && mc != mh; mc = mc->prev)
- if (streq (mc->mnt_dir, name) || (streq (mc->mnt_fsname, name)))
- return mc;
-
- return NULL;
+ struct mntentchn *mc, *mc0;
+
+ mc0 = mtab_head();
+ if (!mcprev)
+ mcprev = mc0;
+ for (mc = mcprev->prev; mc && mc != mc0; mc = mc->prev)
+ if (streq (mc->m.mnt_dir, name) ||
+ streq (mc->m.mnt_fsname, name))
+ return mc;
+ return NULL;
}
/* Given the name FILE, try to find the option "loop=FILE" in mtab. */
struct mntentchn *
-getmntoptfile (const char *file)
-{
- struct mntentchn *mc;
- char *opts, *s;
- int l;
-
- if (!file)
- return NULL;
-
- l = strlen(file);
-
- for (mc = mtab_head()->nxt; mc; mc = mc->nxt)
- if ((opts = mc->mnt_opts) != NULL
- && (s = strstr(opts, "loop="))
- && !strncmp(s+5, file, l)
- && (s == opts || s[-1] == ',')
- && (s[l+5] == 0 || s[l+5] == ','))
- return mc;
-
- return NULL;
+getmntoptfile (const char *file) {
+ struct mntentchn *mc, *mc0;
+ char *opts, *s;
+ int l;
+
+ if (!file)
+ return NULL;
+
+ l = strlen(file);
+
+ mc0 = mtab_head();
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+ if ((opts = mc->m.mnt_opts) != NULL
+ && (s = strstr(opts, "loop="))
+ && !strncmp(s+5, file, l)
+ && (s == opts || s[-1] == ',')
+ && (s[l+5] == 0 || s[l+5] == ','))
+ return mc;
+ return NULL;
}
/* Find the entry (SPEC,FILE) in fstab */
struct mntentchn *
getfsspecfile (const char *spec, const char *file) {
- struct mntentchn *mc;
-
- for (mc = fstab_head()->nxt; mc; mc = mc->nxt)
- if (streq (mc->mnt_dir, file) && streq (mc->mnt_fsname, spec))
- return mc;
- for (mc = fstab_head()->nxt; mc; mc = mc->nxt)
- if ((streq (mc->mnt_dir, file) ||
- streq (canonicalize(mc->mnt_dir), file))
- && (streq (mc->mnt_fsname, spec) ||
- streq (canonicalize(mc->mnt_fsname), spec)))
- break;
- return mc;
+ struct mntentchn *mc, *mc0;
+
+ mc0 = fstab_head();
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+ if (streq (mc->m.mnt_dir, file) &&
+ streq (mc->m.mnt_fsname, spec))
+ return mc;
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+ if ((streq (mc->m.mnt_dir, file) ||
+ streq (canonicalize(mc->m.mnt_dir), file))
+ && (streq (mc->m.mnt_fsname, spec) ||
+ streq (canonicalize(mc->m.mnt_fsname), spec)))
+ return mc;
+ return NULL;
}
/* Find the dir FILE in fstab. */
struct mntentchn *
getfsfile (const char *file) {
- struct mntentchn *mc;
-
- for (mc = fstab_head()->nxt; mc; mc = mc->nxt)
- if (streq (mc->mnt_dir, file))
- break;
+ struct mntentchn *mc, *mc0;
- return mc;
+ mc0 = fstab_head();
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+ if (streq (mc->m.mnt_dir, file))
+ return mc;
+ return NULL;
}
/* Find the device SPEC in fstab. */
struct mntentchn *
-getfsspec (const char *spec)
-{
- struct mntentchn *mc;
-
- for (mc = fstab_head()->nxt; mc; mc = mc->nxt)
- if (streq (mc->mnt_fsname, spec))
- break;
-
- return mc;
+getfsspec (const char *spec) {
+ struct mntentchn *mc, *mc0;
+
+ mc0 = fstab_head();
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+ if (streq (mc->m.mnt_fsname, spec))
+ return mc;
+ return NULL;
}
/* Find the uuid UUID in fstab. */
struct mntentchn *
-getfsuuidspec (const char *uuid)
-{
- struct mntentchn *mc;
-
- for (mc = fstab_head()->nxt; mc; mc = mc->nxt)
- if (strncmp (mc->mnt_fsname, "UUID=", 5) == 0
- && streq(mc->mnt_fsname + 5, uuid))
- break;
-
- return mc;
+getfsuuidspec (const char *uuid) {
+ struct mntentchn *mc, *mc0;
+
+ mc0 = fstab_head();
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+ if (strncmp (mc->m.mnt_fsname, "UUID=", 5) == 0
+ && streq(mc->m.mnt_fsname + 5, uuid))
+ return mc;
+ return NULL;
}
/* Find the label LABEL in fstab. */
struct mntentchn *
-getfsvolspec (const char *label)
-{
- struct mntentchn *mc;
-
- for (mc = fstab_head()->nxt; mc; mc = mc->nxt)
- if (strncmp (mc->mnt_fsname, "LABEL=", 6) == 0
- && streq(mc->mnt_fsname + 6, label))
- break;
-
- return mc;
+getfsvolspec (const char *label) {
+ struct mntentchn *mc, *mc0;
+
+ mc0 = fstab_head();
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+ if (strncmp (mc->m.mnt_fsname, "LABEL=", 6) == 0
+ && streq(mc->m.mnt_fsname + 6, label))
+ return mc;
+ return NULL;
}
/* Updating mtab ----------------------------------------------*/
@@ -371,7 +369,8 @@ lock_mtab (void) {
int errsv = errno;
/* linktargetfile does not exist (as a file)
and we cannot create it. Read-only filesystem?
- Too many files open in the system? Filesystem full? */
+ Too many files open in the system?
+ Filesystem full? */
die (EX_FILEIO, _("can't create lock file %s: %s "
"(use -n flag to override)"),
linktargetfile, strerror (errsv));
@@ -455,7 +454,7 @@ unlock_mtab (void) {
/*
* Update the mtab.
- * Used by umount with null INSTEAD: remove any DIR entries.
+ * Used by umount with null INSTEAD: remove the last DIR entry.
* Used by mount upon a remount: update option part,
* and complain if a wrong device or type was given.
* [Note that often a remount will be a rw remount of /
@@ -465,90 +464,87 @@ unlock_mtab (void) {
void
update_mtab (const char *dir, struct mntent *instead) {
- struct mntent *mnt;
- struct mntent *next;
- struct mntent remnt;
- int added = 0;
- mntFILE *mfp, *mftmp;
+ mntFILE *mfp, *mftmp;
+ const char *fnam = MOUNTED;
+ struct mntentchn mtabhead; /* dummy */
+ struct mntentchn *mc, *mc0, absent;
- if (mtab_does_not_exist() || mtab_is_a_symlink())
- return;
+ if (mtab_does_not_exist() || mtab_is_a_symlink())
+ return;
- lock_mtab();
+ lock_mtab();
- mfp = my_setmntent(MOUNTED, "r");
- if (mfp == NULL || mfp->mntent_fp == NULL) {
- int errsv = errno;
- error (_("cannot open %s (%s) - mtab not updated"),
- MOUNTED, strerror (errsv));
- goto leave;
- }
+ /* having locked mtab, read it again */
+ mc0 = mc = &mtabhead;
+ mc->nxt = mc->prev = NULL;
- mftmp = my_setmntent (MOUNTED_TEMP, "w");
- if (mftmp == NULL || mfp->mntent_fp == NULL) {
- int errsv = errno;
- error (_("cannot open %s (%s) - mtab not updated"),
- MOUNTED_TEMP, strerror (errsv));
- goto leave;
- }
-
- while ((mnt = my_getmntent (mfp))) {
- if (streq (mnt->mnt_dir, dir)
-#if 0
- /* Matthew Wilcox <willy@odie.barnet.ac.uk> */
- /* This is meant for Patch 212 on Jitterbug,
- still in incoming, to allow remounting
- on a different directory. */
- || (instead && instead->mnt_fsname &&
- (!streq (instead->mnt_fsname, "none")) &&
- (streq (mnt->mnt_fsname, instead->mnt_fsname)))
-#endif
- ) {
- added++;
- if (instead) { /* a remount */
- remnt = *instead;
- next = &remnt;
- remnt.mnt_fsname = mnt->mnt_fsname;
- remnt.mnt_type = mnt->mnt_type;
- if (instead->mnt_fsname
- && !streq(mnt->mnt_fsname, instead->mnt_fsname))
- printf(_("mount: warning: cannot change "
- "mounted device with a remount\n"));
- else if (instead->mnt_type
- && !streq(instead->mnt_type, "unknown")
- && !streq(mnt->mnt_type, instead->mnt_type))
- printf(_("mount: warning: cannot change "
- "filesystem type with a remount\n"));
- } else
- next = NULL;
- } else
- next = mnt;
- if (next && my_addmntent(mftmp, next) == 1) {
- int errsv = errno;
- die (EX_FILEIO, _("error writing %s: %s"),
- MOUNTED_TEMP, strerror (errsv));
- }
- }
- if (instead && !added && my_addmntent(mftmp, instead) == 1) {
- int errsv = errno;
- die (EX_FILEIO, _("error writing %s: %s"),
- MOUNTED_TEMP, strerror (errsv));
- }
+ mfp = my_setmntent(fnam, "r");
+ if (mfp == NULL || mfp->mntent_fp == NULL) {
+ int errsv = errno;
+ error (_("cannot open %s (%s) - mtab not updated"),
+ fnam, strerror (errsv));
+ goto leave;
+ }
- my_endmntent (mfp);
- if (fchmod (fileno (mftmp->mntent_fp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
- int errsv = errno;
- fprintf(stderr, _("error changing mode of %s: %s\n"), MOUNTED_TEMP,
- strerror (errsv));
- }
- my_endmntent (mftmp);
+ read_mntentchn(mfp, fnam, mc);
+
+ /* find last occurrence of dir */
+ for (mc = mc0->prev; mc && mc != mc0; mc = mc->prev)
+ if (streq (mc->m.mnt_dir, dir))
+ break;
+ if (mc && mc != mc0) {
+ if (instead == NULL) {
+ /* An umount - remove entry */
+ if (mc && mc != mc0) {
+ mc->prev->nxt = mc->nxt;
+ mc->nxt->prev = mc->prev;
+ }
+ } else {
+ /* A remount */
+ mc->m.mnt_opts = instead->mnt_opts;
+ }
+ } else if (instead) {
+ /* not found, add a new entry */
+ absent.m = *instead;
+ absent.nxt = mc0;
+ absent.prev = mc0->prev;
+ mc0->prev = &absent;
+ if (mc0->nxt == NULL)
+ mc0->nxt = &absent;
+ }
- if (rename (MOUNTED_TEMP, MOUNTED) < 0) {
- int errsv = errno;
- fprintf(stderr, _("can't rename %s to %s: %s\n"), MOUNTED_TEMP, MOUNTED,
- strerror(errsv));
- }
+ /* write chain to mtemp */
+ mftmp = my_setmntent (MOUNTED_TEMP, "w");
+ if (mftmp == NULL || mfp->mntent_fp == NULL) {
+ int errsv = errno;
+ error (_("cannot open %s (%s) - mtab not updated"),
+ MOUNTED_TEMP, strerror (errsv));
+ goto leave;
+ }
+
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) {
+ if (my_addmntent(mftmp, &(mc->m)) == 1) {
+ int errsv = errno;
+ die (EX_FILEIO, _("error writing %s: %s"),
+ MOUNTED_TEMP, strerror (errsv));
+ }
+ }
+
+ if (fchmod (fileno (mftmp->mntent_fp),
+ S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) {
+ int errsv = errno;
+ fprintf(stderr, _("error changing mode of %s: %s\n"),
+ MOUNTED_TEMP, strerror (errsv));
+ }
+ my_endmntent (mftmp);
+
+ /* rename mtemp to mtab */
+ if (rename (MOUNTED_TEMP, MOUNTED) < 0) {
+ int errsv = errno;
+ fprintf(stderr, _("can't rename %s to %s: %s\n"),
+ MOUNTED_TEMP, MOUNTED, strerror(errsv));
+ }
-leave:
- unlock_mtab();
+ leave:
+ unlock_mtab();
}
diff --git a/mount/fstab.h b/mount/fstab.h
index 65bf5dba6..820f418a0 100644
--- a/mount/fstab.h
+++ b/mount/fstab.h
@@ -1,3 +1,4 @@
+#include <mntent.h>
#define _PATH_FSTAB "/etc/fstab"
#ifdef _PATH_MOUNTED
#define MOUNTED_LOCK _PATH_MOUNTED "~"
@@ -13,11 +14,8 @@ int mtab_does_not_exist(void);
int mtab_is_a_symlink(void);
struct mntentchn {
- struct mntentchn *nxt, *prev;
- char *mnt_fsname;
- char *mnt_dir;
- char *mnt_type;
- char *mnt_opts;
+ struct mntentchn *nxt, *prev;
+ struct mntent m;
};
struct mntentchn *mtab_head (void);
diff --git a/mount/linux_fs.h b/mount/linux_fs.h
index 635389a01..043ac16a7 100644
--- a/mount/linux_fs.h
+++ b/mount/linux_fs.h
@@ -100,3 +100,52 @@ struct fat_super_block {
u_char s_label2[11]; /* for Windows? */
u_char s_fs2[8]; /* garbage or "FAT32 " */
};
+
+#define XFS_SUPER_MAGIC "XFSB"
+#define XFS_SUPER_MAGIC2 "BSFX"
+struct xfs_super_block {
+ u_char s_magic[4];
+ u_char s_dummy[28];
+ u_char s_uuid[16];
+ u_char s_dummy2[60];
+ u_char s_fname[12];
+};
+
+#define CRAMFS_SUPER_MAGIC 0x28cd3d45
+struct cramfs_super_block {
+ u_char s_magic[4];
+ u_char s_dummy[12];
+ u_char s_id[16];
+};
+#define cramfsmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8) + \
+ (((uint) s.s_magic[2]) << 16) + \
+ (((uint) s.s_magic[3]) << 24))
+
+#define HFS_SUPER_MAGIC 0x4244
+struct hfs_super_block {
+ u_char s_magic[2];
+ u_char s_dummy[18];
+ u_char s_blksize[4];
+};
+#define hfsmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8))
+#define hfsblksize(s) ((uint) s.s_blksize[0] + \
+ (((uint) s.s_blksize[1]) << 8) + \
+ (((uint) s.s_blksize[2]) << 16) + \
+ (((uint) s.s_blksize[3]) << 24))
+
+#define HPFS_SUPER_MAGIC 0xf995e849
+struct hpfs_super_block {
+ u_char s_magic[4];
+ u_char s_magic2[4];
+};
+#define hpfsmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8) + \
+ (((uint) s.s_magic[2]) << 16) + \
+ (((uint) s.s_magic[3]) << 24))
+
+struct adfs_super_block {
+ u_char s_dummy[448];
+ u_char s_blksize[1];
+ u_char s_dummy2[62];
+ u_char s_checksum[1];
+};
+#define adfsblksize(s) ((uint) s.s_blksize[0])
diff --git a/mount/lomount.c b/mount/lomount.c
index 52157a14a..cabc44461 100644
--- a/mount/lomount.c
+++ b/mount/lomount.c
@@ -68,7 +68,7 @@ crypt_name (int id) {
return "undefined";
}
-static void
+static int
show_loop (char *device) {
struct loop_info loopinfo;
int fd;
@@ -77,36 +77,69 @@ show_loop (char *device) {
int errsv = errno;
fprintf(stderr, _("loop: can't open device %s: %s\n"),
device, strerror (errsv));
- return;
+ return 2;
}
if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) < 0) {
int errsv = errno;
fprintf(stderr, _("loop: can't get info on device %s: %s\n"),
device, strerror (errsv));
close (fd);
- return;
+ return 1;
}
printf (_("%s: [%04x]:%ld (%s) offset %d, %s encryption\n"),
device, loopinfo.lo_device, loopinfo.lo_inode,
loopinfo.lo_name, loopinfo.lo_offset,
crypt_name (loopinfo.lo_encrypt_type));
close (fd);
+
+ return 0;
}
#endif
+int
+is_loop_device (const char *device) {
+ struct stat statbuf;
+ int loopmajor;
+#if 1
+ loopmajor = 7;
+#else
+ FILE *procdev;
+ char line[100], *cp;
+
+ loopmajor = 0;
+ if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) {
+ while (fgets (line, sizeof(line), procdev)) {
+ if ((cp = strstr (line, " loop\n")) != NULL) {
+ *cp='\0';
+ loopmajor=atoi(line);
+ break;
+ }
+ }
+ fclose(procdev);
+ }
+#endif
+ return (loopmajor && stat(device, &statbuf) == 0 &&
+ S_ISBLK(statbuf.st_mode) &&
+ (statbuf.st_rdev>>8) == loopmajor);
+}
+
+#define SIZE(a) (sizeof(a)/sizeof(a[0]))
+
char *
find_unused_loop_device (void) {
/* Just creating a device, say in /tmp, is probably a bad idea -
people might have problems with backup or so.
So, we just try /dev/loop[0-7]. */
char dev[20];
- int i, fd, somedev = 0, someloop = 0, loop_known = 0;
+ char *loop_formats[] = { "/dev/loop%d", "/dev/loop/%d" };
+ int i, j, fd, somedev = 0, someloop = 0, loop_known = 0;
struct stat statbuf;
struct loop_info loopinfo;
FILE *procdev;
- for(i = 0; i < 256; i++) {
- sprintf(dev, "/dev/loop%d", i);
+ for (j = 0; j < SIZE(loop_formats); j++) {
+ for(i = 0; i < 256; i++) {
+ sprintf(dev, loop_formats[j], i);
if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
somedev++;
fd = open (dev, O_RDONLY);
@@ -121,8 +154,8 @@ find_unused_loop_device (void) {
}
continue;/* continue trying as long as devices exist */
}
- if (i >= 7)
- break;
+ break;
+ }
}
/* Nothing found. Why not? */
@@ -393,7 +426,7 @@ main(int argc, char **argv) {
if (delete)
res = del_loop(argv[optind]);
else
- show_loop(argv[optind]);
+ res = show_loop(argv[optind]);
} else {
if (offset && sscanf(offset,"%d",&off) != 1)
usage();
diff --git a/mount/lomount.h b/mount/lomount.h
index 00a49f558..1a93c693f 100644
--- a/mount/lomount.h
+++ b/mount/lomount.h
@@ -1,4 +1,5 @@
extern int verbose;
extern int set_loop (const char *, const char *, int, const char *, int *);
extern int del_loop (const char *);
+extern int is_loop_device (const char *);
extern char * find_unused_loop_device (void);
diff --git a/mount/losetup.8 b/mount/losetup.8
index c2e41307d..d364f4f1e 100644
--- a/mount/losetup.8
+++ b/mount/losetup.8
@@ -46,6 +46,15 @@ attacks.
.IP "\fB\-o \fIoffset\fP"
the data start is moved \fIoffset\fP bytes into the specified file or
device.
+.SH RETURN VALUE
+.B losetup
+returns 0 on success, nonzero on failure. When
+.B losetup
+displays the status of a loop device, it returns 1 if the device
+is not configured and 2 if an error occurred which prevented
+.B losetup
+from determining the status of the device.
+
.SH FILES
.nf
/dev/loop0,/dev/loop1,... loop devices (major=7)
@@ -81,7 +90,5 @@ DES encryption is painfully slow. On the other hand, XOR is terribly weak.
.SH AUTHORS
.nf
Original version: Theodore Ts'o <tytso@athena.mit.edu>
-Maintained by: Werner Almesberger <almesber@bernina.ethz.ch>
Original DES by: Eric Young <eay@psych.psy.uq.oz.au>
-Modularized and updated 28-5-94: Mitch DSouza <m.dsouza@mrc-apu.cam.ac.uk>
.fi
diff --git a/mount/mount.8 b/mount/mount.8
index 7016ee535..f90341198 100644
--- a/mount/mount.8
+++ b/mount/mount.8
@@ -98,6 +98,14 @@ lists all mounted file systems (of type
The option \-l adds the (ext2) labels in this listing.
See below.
+.\" In fact since 2.3.99. At first the syntax was mount -t bind.
+Since Linux 2.4.0 it is possible to remount part of the
+file hierarchy somewhere else. The call is
+.RS
+.br
+.B "mount --bind olddir newdir"
+.RE
+
The
.I proc
file system is not associated with a special device, and when
@@ -367,7 +375,8 @@ necessary. The nfs ad hoc code is built in, but smbfs and ncpfs
have a separate mount program. In order to make it possible to
treat all types in a uniform way, mount will execute the program
.I /sbin/mount.TYPE
-(if that exists) when called with type smb or ncp.
+(if that exists) when called with type
+.IR TYPE .
Since various versions of the
.I smbmount
program have different calling conventions,
diff --git a/mount/mount.c b/mount/mount.c
index b8ee2ebec..39ccd3e63 100644
--- a/mount/mount.c
+++ b/mount/mount.c
@@ -36,6 +36,7 @@
* - added `owner' mount option
* 2000-05-11 Mark A. Peloquin <peloquin@us.ibm.com>
* - check_special_mountprog now returns correct status
+ * 2000-11-08 aeb: accept nonnumeric uid=, gid= options
*/
#include <unistd.h>
@@ -45,6 +46,9 @@
#include <getopt.h>
#include <stdio.h>
+#include <pwd.h>
+#include <grp.h>
+
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
@@ -58,6 +62,7 @@
#include "lomount.h"
#include "loop.h"
#include "linux_fs.h" /* for BLKGETSIZE */
+#include "mount_guess_rootdev.h"
#include "mount_guess_fstype.h"
#include "mount_by_label.h"
#include "getusername.h"
@@ -96,6 +101,12 @@ static int optfork = 0;
/* Add volumelabel in a listing of mounted devices (-l). */
static int list_with_volumelabel = 0;
+/* Nonzero for mount --bind */
+static int bind = 0;
+
+/* Nonzero for mount {--replace|--before|--after|--over} */
+static int mounttype = 0;
+
/* True if ruid != euid. */
static int suid = 0;
@@ -108,8 +119,7 @@ struct opt_map {
};
/* Custom mount options for our own purposes. */
-/* We can use the high-order 16 bits, since the mount call
- has MS_MGC_VAL there. */
+/* Maybe these should now be freed for kernel use again */
#define MS_NOAUTO 0x80000000
#define MS_USERS 0x40000000
#define MS_USER 0x20000000
@@ -141,6 +151,7 @@ static const struct opt_map opt_map[] = {
{ "sync", 0, 0, MS_SYNCHRONOUS}, /* synchronous I/O */
{ "async", 0, 1, MS_SYNCHRONOUS}, /* asynchronous I/O */
{ "remount", 0, 0, MS_REMOUNT}, /* Alter flags of mounted FS */
+ { "bind", 0, 0, MS_BIND }, /* Remount part of tree elsewhere */
{ "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 */
@@ -217,17 +228,17 @@ int mount_quiet=0;
/* Report on a single mount. */
static void
-print_one (const struct mntentchn *mc) {
+print_one (const struct mntent *me) {
if (mount_quiet)
return;
- printf ("%s on %s", mc->mnt_fsname, mc->mnt_dir);
- if (mc->mnt_type != NULL && *(mc->mnt_type) != '\0')
- printf (" type %s", mc->mnt_type);
- if (mc->mnt_opts != NULL)
- printf (" (%s)", mc->mnt_opts);
+ printf ("%s on %s", me->mnt_fsname, me->mnt_dir);
+ if (me->mnt_type != NULL && *(me->mnt_type) != '\0')
+ printf (" type %s", me->mnt_type);
+ if (me->mnt_opts != NULL)
+ printf (" (%s)", me->mnt_opts);
if (list_with_volumelabel) {
const char *label;
- label = get_volume_label_by_spec(mc->mnt_fsname);
+ label = get_volume_label_by_spec(me->mnt_fsname);
if (label)
printf (" [%s]", label);
}
@@ -237,18 +248,22 @@ print_one (const struct mntentchn *mc) {
/* Report on everything in mtab (of the specified types if any). */
static int
print_all (string_list types) {
- struct mntentchn *mc;
+ struct mntentchn *mc, *mc0;
- for (mc = mtab_head()->nxt; mc; mc = mc->nxt) {
- if (matching_type (mc->mnt_type, types))
- print_one (mc);
+ mc0 = mtab_head();
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) {
+ if (matching_type (mc->m.mnt_type, types))
+ print_one (&(mc->m));
}
exit (0);
}
-/* Look for OPT in opt_map table and return mask value. If OPT isn't found,
- tack it onto extra_opts (which is non-NULL). */
+/*
+ * Look for OPT in opt_map table and return mask value.
+ * If OPT isn't found, tack it onto extra_opts (which is non-NULL).
+ * For the options uid= and gid= replace user or group name by its value.
+ */
static inline void
parse_opt (const char *opt, int *mask, char *extra_opts) {
const struct opt_map *om;
@@ -272,36 +287,62 @@ parse_opt (const char *opt, int *mask, char *extra_opts) {
#endif
return;
}
+
if (*extra_opts)
strcat(extra_opts, ",");
+
+ /* convert nonnumeric ids to numeric */
+ if (!strncmp(opt, "uid=", 4) && !isdigit(opt[4])) {
+ struct passwd *pw = getpwnam(opt+4);
+ char uidbuf[20];
+
+ if (pw) {
+ sprintf(uidbuf, "uid=%d", pw->pw_uid);
+ strcat(extra_opts, uidbuf);
+ return;
+ }
+ }
+ if (!strncmp(opt, "gid=", 4) && !isdigit(opt[4])) {
+ struct group *gr = getgrnam(opt+4);
+ char gidbuf[20];
+
+ if (gr) {
+ sprintf(gidbuf, "gid=%d", gr->gr_gid);
+ strcat(extra_opts, gidbuf);
+ return;
+ }
+ }
+
strcat(extra_opts, opt);
}
/* Take -o options list and compute 4th and 5th args to mount(2). flags
- gets the standard options and extra_opts anything we don't recognize. */
+ gets the standard options (indicated by bits) and extra_opts all the rest */
static void
parse_opts (char *opts, int *flags, char **extra_opts) {
- char *opt;
+ char *opt;
- *flags = 0;
- *extra_opts = NULL;
+ *flags = 0;
+ *extra_opts = NULL;
- clear_string_opts();
+ clear_string_opts();
- if (opts != NULL)
- {
- *extra_opts = xmalloc (strlen (opts) + 1);
- **extra_opts = '\0';
+ if (opts != NULL) {
+ *extra_opts = xmalloc (strlen (opts) + 1);
+ **extra_opts = '\0';
- for (opt = strtok (opts, ","); opt; opt = strtok (NULL, ","))
- if (!parse_string_opt (opt))
- parse_opt (opt, flags, *extra_opts);
- }
+ for (opt = strtok (opts, ","); opt; opt = strtok (NULL, ","))
+ if (!parse_string_opt (opt))
+ parse_opt (opt, flags, *extra_opts);
+ }
- if (readonly)
- *flags |= MS_RDONLY;
- if (readwrite)
- *flags &= ~MS_RDONLY;
+ if (readonly)
+ *flags |= MS_RDONLY;
+ if (readwrite)
+ *flags &= ~MS_RDONLY;
+ *flags |= mounttype;
+ if (bind)
+ *flags |= MS_BIND;
}
/* Try to build a canonical options string. */
@@ -340,10 +381,11 @@ already (const char *spec, const char *node) {
if ((mc = getmntfile(node)) != NULL)
error (_("mount: according to mtab, %s is already mounted on %s"),
- mc->mnt_fsname, node);
- else if ((mc = getmntfile(spec)) != NULL)
+ mc->m.mnt_fsname, node);
+ else if (spec && strcmp (spec, "none") &&
+ (mc = getmntfile(spec)) != NULL)
error (_("mount: according to mtab, %s is mounted on %s"),
- spec, mc->mnt_dir);
+ spec, mc->m.mnt_dir);
else
ret = 0;
return ret;
@@ -369,10 +411,10 @@ create_mtab (void) {
/* Find the root entry by looking it up in fstab */
if ((fstab = getfsfile ("/")) || (fstab = getfsfile ("root"))) {
- parse_opts (xstrdup (fstab->mnt_opts), &flags, &extra_opts);
+ parse_opts (xstrdup (fstab->m.mnt_opts), &flags, &extra_opts);
mnt.mnt_dir = "/";
- mnt.mnt_fsname = canonicalize (fstab->mnt_fsname);
- mnt.mnt_type = fstab->mnt_type;
+ mnt.mnt_fsname = canonicalize (fstab->m.mnt_fsname);
+ mnt.mnt_type = fstab->m.mnt_type;
mnt.mnt_opts = fix_opts_string (flags, extra_opts, NULL);
mnt.mnt_freq = mnt.mnt_passno = 0;
@@ -424,6 +466,9 @@ guess_fstype_and_mount (char *spec, char *node, char **type,
if (*type && strcasecmp (*type, "auto") == 0)
*type = NULL;
+ if (!*type && (flags & MS_BIND))
+ *type = "none"; /* random, but not "bind" */
+
if (!*type && !(flags & MS_REMOUNT)) {
*type = guess_fstype_from_superblock(spec);
if (*type && !strcmp(*type, "swap")) {
@@ -547,21 +592,19 @@ loop_check(char **spec, char **type, int *flags,
static void
update_mtab_entry(char *spec, char *node, char *type, char *opts,
int flags, int freq, int pass) {
- struct mntentchn mcn;
struct mntent mnt;
- mcn.mnt_fsname = mnt.mnt_fsname = canonicalize (spec);
- mcn.mnt_dir = mnt.mnt_dir = canonicalize (node);
- mcn.mnt_type = mnt.mnt_type = type;
- mcn.mnt_opts = mnt.mnt_opts = opts;
- mcn.nxt = 0;
+ mnt.mnt_fsname = canonicalize (spec);
+ mnt.mnt_dir = canonicalize (node);
+ mnt.mnt_type = type;
+ mnt.mnt_opts = opts;
mnt.mnt_freq = freq;
mnt.mnt_passno = pass;
/* We get chatty now rather than after the update to mtab since the
mount succeeded, even if the write to /etc/mtab should fail. */
if (verbose)
- print_one (&mcn);
+ print_one (&mnt);
if (!nomtab && mtab_is_writable()) {
if (flags & MS_REMOUNT)
@@ -610,6 +653,8 @@ cdrom_setspeed(char *spec) {
* If there is a special mount program for this type, exec it.
* returns: 0: no exec was done, 1: exec was done, status has result
*/
+#define ALWAYS_STAT
+
static int
check_special_mountprog(char *spec, char *node, char *type, int flags,
char *extra_opts, int *status) {
@@ -708,9 +753,15 @@ try_mount_one (const char *spec0, const char *node0, char *type0,
if (opt_speed)
cdrom_setspeed(spec);
- res = loop_check (&spec, &type, &flags, &loop, &loopdev, &loopfile);
- if (res)
+ if (!(flags & MS_REMOUNT)) {
+ /* don't set up a (new) loop device if we only remount - this left
+ * stale assignments of files to loop devices. Nasty when used for
+ * encryption.
+ */
+ res = loop_check (&spec, &type, &flags, &loop, &loopdev, &loopfile);
+ if (res)
return res;
+ }
/*
* Call mount.TYPE for types that require a separate mount program.
@@ -836,6 +887,7 @@ retry_nfs:
case EINVAL:
{ int fd;
long size;
+ int warned=0;
if (flags & MS_REMOUNT) {
error (_("mount: %s not mounted already, or bad option"), node);
@@ -846,10 +898,29 @@ retry_nfs:
if (stat (spec, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)
&& (fd = open(spec, O_RDONLY | O_NONBLOCK)) >= 0) {
- if(ioctl(fd, BLKGETSIZE, &size) == 0 && size <= 2)
+ if(ioctl(fd, BLKGETSIZE, &size) == 0) {
+ if (size == 0) {
+ 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?)");
+ }
+ if (size && size <= 2) {
+ warned++;
error (" (aren't you trying to mount an extended partition,\n"
" instead of some logical partition inside?)");
+ }
close(fd);
+ }
+#if 0
+ /* 0xf for SCSI, 0x3f for IDE. One might check /proc/partitions
+ to see whether this thing really is partitioned.
+ Do not suggest partitions for /dev/fd0. */
+ if (!warned && (statbuf.st_rdev & 0xf) == 0) {
+ warned++;
+ error (" (could this be the whole disk device\n"
+ " where you need a partition?)");
+ }
+#endif
}
}
break;
@@ -859,9 +930,10 @@ retry_nfs:
case EIO:
error (_("mount: %s: can't read superblock"), spec); break;
case ENODEV:
- if (is_in_procfs(type) || !strcmp(type, "guess"))
- error(_("mount: %s has wrong major or minor number"), spec);
- else if (have_procfs()) {
+ { int pfs;
+ if ((pfs = is_in_procfs(type)) == 1 || !strcmp(type, "guess"))
+ error(_("mount: %s: unknown device"), spec);
+ else if (pfs == 0) {
char *lowtype, *p;
int u;
@@ -876,15 +948,16 @@ retry_nfs:
u++;
}
}
- if (u && is_in_procfs(lowtype))
+ if (u && is_in_procfs(lowtype) == 1)
error (_("mount: probably you meant %s"), lowtype);
- else if (!strncmp(lowtype, "iso", 3) && is_in_procfs("iso9660"))
+ else if (!strncmp(lowtype, "iso", 3) && is_in_procfs("iso9660") == 1)
error (_("mount: maybe you meant iso9660 ?"));
free(lowtype);
} else
error (_("mount: %s has wrong device number or fs type %s not supported"),
spec, type);
break;
+ }
case ENOTBLK:
if (stat (spec, &statbuf)) /* strange ... */
error (_("mount: %s is not a block device, and stat fails?"), spec);
@@ -902,8 +975,8 @@ retry_nfs:
case EACCES: /* pre-linux 1.1.38, 1.1.41 and later */
case EROFS: /* linux 1.1.38 and later */
{ char *bd = (loop ? "" : _("block device "));
- if (ro) {
- error (_("mount: %s%s is not permitted on its filesystem"),
+ if (ro || (flags & MS_RDONLY)) {
+ error (_("mount: cannot mount %s%s read-only"),
bd, spec);
break;
} else if (readwrite) {
@@ -1011,15 +1084,15 @@ mount_one (const char *spec, const char *node, char *type, const char *opts,
if (specset) {
if (nspec) {
spec = nspec;
- if (verbose)
- printf(_("mount: consider mounting %s by %s\n"), spec,
+ if (verbose > 1)
+ printf(_("mount: going to mount %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 (type == NULL && !bind) {
if (strchr (spec, ':') != NULL) {
type = "nfs";
if (verbose)
@@ -1057,7 +1130,7 @@ mount_one (const char *spec, const char *node, char *type, const char *opts,
/* Check if an fsname/dir pair was already in the old mtab. */
static int
mounted (char *spec, char *node) {
- struct mntentchn *mc;
+ struct mntentchn *mc, *mc0;
char *nspec = NULL;
if (!strncmp(spec, "UUID=", 5))
@@ -1071,8 +1144,9 @@ mounted (char *spec, char *node) {
spec = canonicalize (spec);
node = canonicalize (node);
- for (mc = mtab_head()->nxt; mc; mc = mc->nxt)
- if (streq (spec, mc->mnt_fsname) && streq (node, mc->mnt_dir))
+ mc0 = mtab_head();
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt)
+ if (streq (spec, mc->m.mnt_fsname) && streq (node, mc->m.mnt_dir))
return 1;
return 0;
}
@@ -1085,7 +1159,7 @@ mounted (char *spec, char *node) {
static int
mount_all (string_list types, char *options) {
- struct mntentchn *mc, *mtmp;
+ struct mntentchn *mc, *mc0, *mtmp;
int status = 0;
struct stat statbuf;
struct child {
@@ -1102,28 +1176,29 @@ mount_all (string_list types, char *options) {
several chains, one for each major or NFS host */
childhead.nxt = 0;
childtail = &childhead;
- for (mc = fstab_head()->nxt; mc; mc = mc->nxt) {
- if (matching_type (mc->mnt_type, types)
- && !streq (mc->mnt_dir, "/")
- && !streq (mc->mnt_dir, "root")) {
- if (mounted (mc->mnt_fsname, mc->mnt_dir)) {
+ mc0 = fstab_head();
+ for (mc = mc0->nxt; mc && mc != mc0; mc = mc->nxt) {
+ if (matching_type (mc->m.mnt_type, types)
+ && !streq (mc->m.mnt_dir, "/")
+ && !streq (mc->m.mnt_dir, "root")) {
+ if (mounted (mc->m.mnt_fsname, mc->m.mnt_dir)) {
if (verbose)
printf(_("mount: %s already mounted on %s\n"),
- mc->mnt_fsname, mc->mnt_dir);
+ mc->m.mnt_fsname, mc->m.mnt_dir);
} else {
mtmp = (struct mntentchn *) xmalloc(sizeof(*mtmp));
*mtmp = *mc;
mtmp->nxt = 0;
g = NULL;
if (optfork) {
- if (stat(mc->mnt_fsname, &statbuf) == 0 &&
+ if (stat(mc->m.mnt_fsname, &statbuf) == 0 &&
S_ISBLK(statbuf.st_mode)) {
sprintf(major, "#%x", DISKMAJOR(statbuf.st_rdev));
g = major;
}
#ifdef HAVE_NFS
- if (strcmp(mc->mnt_type, "nfs") == 0) {
- g = xstrdup(mc->mnt_fsname);
+ if (strcmp(mc->m.mnt_type, "nfs") == 0) {
+ g = xstrdup(mc->m.mnt_fsname);
colon = strchr(g, ':');
if (colon)
*colon = '\0';
@@ -1166,8 +1241,8 @@ mount_all (string_list types, char *options) {
/* if child, or not forked, do the mounting */
if (p == 0 || p == -1) {
for (mc = cp->mec; mc; mc = mc->nxt)
- status |= mount_one (mc->mnt_fsname, mc->mnt_dir,
- mc->mnt_type, mc->mnt_opts,
+ status |= mount_one (mc->m.mnt_fsname, mc->m.mnt_dir,
+ mc->m.mnt_type, mc->m.mnt_opts,
options, 0, 0);
if (mountcount)
status |= EX_SOMEOK;
@@ -1198,222 +1273,271 @@ mount_all (string_list types, char *options) {
}
extern char version[];
-static struct option longopts[] =
-{
- { "all", 0, 0, 'a' },
- { "fake", 0, 0, 'f' },
- { "fork", 0, 0, 'F' },
- { "help", 0, 0, 'h' },
- { "no-mtab", 0, 0, 'n' },
- { "read-only", 0, 0, 'r' },
- { "ro", 0, 0, 'r' },
- { "verbose", 0, 0, 'v' },
- { "version", 0, 0, 'V' },
- { "read-write", 0, 0, 'w' },
- { "rw", 0, 0, 'w' },
- { "options", 1, 0, 'o' },
- { "types", 1, 0, 't' },
- { NULL, 0, 0, 0 }
+static struct option longopts[] = {
+ { "all", 0, 0, 'a' },
+ { "fake", 0, 0, 'f' },
+ { "fork", 0, 0, 'F' },
+ { "help", 0, 0, 'h' },
+ { "no-mtab", 0, 0, 'n' },
+ { "read-only", 0, 0, 'r' },
+ { "ro", 0, 0, 'r' },
+ { "verbose", 0, 0, 'v' },
+ { "version", 0, 0, 'V' },
+ { "read-write", 0, 0, 'w' },
+ { "rw", 0, 0, 'w' },
+ { "options", 1, 0, 'o' },
+ { "types", 1, 0, 't' },
+ { "bind", 0, 0, 128 },
+ { "replace", 0, 0, 129 },
+ { "after", 0, 0, 130 },
+ { "before", 0, 0, 131 },
+ { "over", 0, 0, 132 },
+ { NULL, 0, 0, 0 }
};
+/* Keep the usage message at max 22 lines, each at most 70 chars long.
+ The user should not need a pager to read it. */
static void
-usage (FILE *fp, int n)
-{
- fprintf (fp, _("Usage: mount [-lhV]\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 .\n"));
- unlock_mtab();
- exit (n);
+usage (FILE *fp, int n) {
+ fprintf(fp, _(
+ "Usage: mount -V : print version\n"
+ " mount -h : print this help\n"
+ " mount : list mounted filesystems\n"
+ " mount -l : idem, including volume labels\n"
+ "So far the informational part. Next the mounting.\n"
+ "The command is `mount [-t fstype] something somewhere'.\n"
+ "Details found in /etc/fstab may be omitted.\n"
+ " mount -a : mount all stuff from /etc/fstab\n"
+ " mount device : mount device at the known place\n"
+ " mount directory : mount known device here\n"
+ " mount -t type dev dir : ordinary mount command\n"
+ "Note that one does not really mount a device, one mounts\n"
+ "a filesystem (of the given type) found on the device.\n"
+ "One can also mount an already visible directory tree elsewhere:\n"
+ " mount --bind olddir newdir\n"
+ "A device can be given by name, say /dev/hda1 or /dev/cdrom,\n"
+ "or by label, using -L label or by uuid, using -U uuid .\n"
+ "Union or stack mounts are specified using one of\n"
+ " --replace, --after, --before, --over\n"
+ "Other options: [-nfFrsvw] [-o options].\n"
+ "For many more details, say man 8 mount .\n"
+ ));
+ unlock_mtab();
+ exit (n);
}
int
main (int argc, char *argv[]) {
- 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;
-
- setlocale(LC_ALL, "");
- bindtextdomain(PACKAGE, LOCALEDIR);
- textdomain(PACKAGE);
-
- /* 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);
+ 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;
+
+ setlocale(LC_ALL, "");
+ bindtextdomain(PACKAGE, LOCALEDIR);
+ textdomain(PACKAGE);
+
+ /* 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
- initproctitle(argc, argv);
+ initproctitle(argc, argv);
#endif
- while ((c = getopt_long (argc, argv, "afFhlL:no:rsU:vVwt:", longopts, NULL))
- != EOF)
- switch (c) {
- case 'a': /* mount everything in fstab */
- ++all;
- break;
- case 'f': /* fake (don't actually do mount(2) call) */
- ++fake;
- break;
- case 'F':
- ++optfork;
- break;
- case 'h': /* help */
- usage (stdout, 0);
- break;
- case 'l':
- list_with_volumelabel = 1;
- break;
- case 'L':
- volumelabel = optarg;
- break;
- case 'n': /* mount without writing in /etc/mtab */
- ++nomtab;
- break;
- case 'o': /* specify mount options */
- if (options)
- options = xstrconcat3(options, ",", optarg);
- else
- options = xstrdup(optarg);
- break;
- case 'r': /* mount readonly */
- readonly = 1;
- readwrite = 0;
- break;
- case 's': /* allow sloppy mount options */
- sloppy = 1;
- break;
- 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;
- case 'V': /* version */
- printf ("mount: %s\n", version);
- exit (0);
- case 'w': /* mount read/write */
- readwrite = 1;
- readonly = 0;
- break;
- case 0:
- break;
- case '?':
- default:
- usage (stderr, EX_USAGE);
- }
-
- argc -= optind;
- argv += optind;
-
- specseen = (uuid || volumelabel) ? 1 : 0; /* yes, .. i know */
+ while ((c = getopt_long (argc, argv, "afFhlL:no:rsU:vVwt:",
+ longopts, NULL)) != EOF) {
+ switch (c) {
+ case 'a': /* mount everything in fstab */
+ ++all;
+ break;
+ case 'f': /* fake: don't actually call mount(2) */
+ ++fake;
+ break;
+ case 'F':
+ ++optfork;
+ break;
+ case 'h': /* help */
+ usage (stdout, 0);
+ break;
+ case 'l':
+ list_with_volumelabel = 1;
+ break;
+ case 'L':
+ volumelabel = optarg;
+ break;
+ case 'n': /* do not write /etc/mtab */
+ ++nomtab;
+ break;
+ case 'o': /* specify mount options */
+ if (options)
+ options = xstrconcat3(options, ",", optarg);
+ else
+ options = xstrdup(optarg);
+ break;
+ case 'r': /* mount readonly */
+ readonly = 1;
+ readwrite = 0;
+ break;
+ case 's': /* allow sloppy mount options */
+ sloppy = 1;
+ break;
+ case 't': /* specify file system types */
+ types = parse_list (optarg);
+ break;
+ case 'U':
+ uuid = optarg;
+ break;
+ case 'v': /* be chatty - more so if repeated */
+ ++verbose;
+ break;
+ case 'V': /* version */
+ printf ("mount: %s\n", version);
+ exit (0);
+ case 'w': /* mount read/write */
+ readwrite = 1;
+ readonly = 0;
+ break;
+ case 0:
+ break;
+
+ case 128: /* bind */
+ ++bind;
+ break;
+ case 129: /* replace */
+ mounttype = MS_REPLACE;
+ break;
+ case 130: /* after */
+ mounttype = MS_AFTER;
+ break;
+ case 131: /* before */
+ mounttype = MS_BEFORE;
+ break;
+ case 132: /* over */
+ mounttype = MS_OVER;
+ break;
+
+ case '?':
+ default:
+ usage (stderr, EX_USAGE);
+ }
+ }
- if (argc+specseen == 0 && !all) {
- if (options)
- usage (stderr, EX_USAGE);
- return print_all (types);
- }
+ argc -= optind;
+ argv += optind;
- if (getuid () != geteuid ()) {
- suid = 1;
- if (types || options || readwrite || nomtab || all || fake ||
- (argc + specseen) != 1)
- die (EX_USAGE, _("mount: only root can do that"));
- }
+ specseen = (uuid || volumelabel) ? 1 : 0; /* yes, .. i know */
- if (!nomtab && mtab_does_not_exist()) {
- if (verbose > 1)
- printf(_("mount: no %s found - creating it..\n"), MOUNTED);
- create_mtab ();
- }
+ if (argc+specseen == 0 && !all) {
+ if (options || mounttype || bind)
+ usage (stderr, EX_USAGE);
+ return print_all (types);
+ }
- 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);
- if (result == 0 && verbose)
- error(_("not mounted anything"));
- break;
+ if (getuid () != geteuid ()) {
+ suid = 1;
+ if (types || options || readwrite || nomtab || all || fake ||
+ bind || mounttype || (argc + specseen) != 1)
+ die (EX_USAGE, _("mount: only root can do that"));
+ }
- case 1:
- /* mount [-nfrvw] [-o options] special | node */
- if (types != NULL)
- usage (stderr, EX_USAGE);
- 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. */
- }
+ if (!nomtab && mtab_does_not_exist()) {
+ if (verbose > 1)
+ printf(_("mount: no %s found - creating it..\n"),
+ MOUNTED);
+ create_mtab ();
+ }
- result = mount_one (xstrdup (mc->mnt_fsname), xstrdup (mc->mnt_dir),
- xstrdup (mc->mnt_type), mc->mnt_opts, options, 0, 0);
- break;
+ 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);
+ if (result == 0 && verbose)
+ error(_("not mounted anything"));
+ break;
+
+ case 1:
+ /* mount [-nfrvw] [-o options] special | node */
+ if (types != NULL)
+ usage (stderr, EX_USAGE);
+ 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->m.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. */
+ }
- 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 (spec, node, NULL, NULL, options, 0, 0);
- else if (cdr (types) == NULL)
- result = mount_one (spec, node, car (types), NULL, options, 0, 0);
- else
- usage (stderr, EX_USAGE);
- break;
+ result = mount_one (xstrdup (mc->m.mnt_fsname),
+ xstrdup (mc->m.mnt_dir),
+ xstrdup (mc->m.mnt_type),
+ mc->m.mnt_opts, options, 0, 0);
+ break;
+
+ 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 (spec, node, NULL, NULL,
+ options, 0, 0);
+ else if (cdr (types) == NULL)
+ result = mount_one (spec, node, car (types), NULL,
+ options, 0, 0);
+ else
+ usage (stderr, EX_USAGE);
+ break;
- default:
- usage (stderr, EX_USAGE);
- }
+ default:
+ usage (stderr, EX_USAGE);
+ }
- if (result == EX_SOMEOK)
- result = 0;
- exit (result);
+ if (result == EX_SOMEOK)
+ result = 0;
+ exit (result);
}
diff --git a/mount/mount_by_label.c b/mount/mount_by_label.c
index 1567bfb18..e24d880d2 100644
--- a/mount/mount_by_label.c
+++ b/mount/mount_by_label.c
@@ -7,6 +7,8 @@
* - Added error message if /proc/partitions cannot be opened
* 2000-05-09 Erik Troan <ewt@redhat.com>
* - Added cache for UUID and disk labels
+ * 2000-11-07 Nathan Scott <nathans@sgi.com>
+ * - Added XFS support
*/
#include <stdio.h>
@@ -29,33 +31,44 @@ static struct uuidCache_s {
char *device;
} *uuidCache = NULL;
-/* for now, only ext2 is supported */
+/* for now, only ext2 and xfs are supported */
static int
get_label_uuid(const char *device, char **label, char *uuid) {
- /* start with a test for ext2, taken from mount_guess_fstype */
+ /* start with ext2 and xfs tests, taken from mount_guess_fstype */
/* should merge these later */
int fd;
+ int rv = 1;
+ size_t namesize;
struct ext2_super_block e2sb;
+ struct xfs_super_block xfsb;
fd = open(device, O_RDONLY);
if (fd < 0)
- return 1;
-
- if (lseek(fd, 1024, SEEK_SET) != 1024
- || read(fd, (char *) &e2sb, sizeof(e2sb)) != sizeof(e2sb)
- || (ext2magic(e2sb) != EXT2_SUPER_MAGIC)) {
- close(fd);
- return 1;
+ return rv;
+
+ if (lseek(fd, 1024, SEEK_SET) == 1024
+ && read(fd, (char *) &e2sb, sizeof(e2sb)) == sizeof(e2sb)
+ && (ext2magic(e2sb) == EXT2_SUPER_MAGIC)) {
+ memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid));
+ namesize = sizeof(e2sb.s_volume_name);
+ if ((*label = calloc(namesize + 1, 1)) != NULL)
+ memcpy(*label, e2sb.s_volume_name, namesize);
+ rv = 0;
+ }
+ else if (lseek(fd, 0, SEEK_SET) == 0
+ && read(fd, (char *) &xfsb, sizeof(xfsb)) == sizeof(xfsb)
+ && (strncmp((char *) &xfsb.s_magic, XFS_SUPER_MAGIC, 4) == 0 ||
+ strncmp((char *) &xfsb.s_magic, XFS_SUPER_MAGIC2,4) == 0)) {
+ memcpy(uuid, xfsb.s_uuid, sizeof(xfsb.s_uuid));
+ namesize = sizeof(xfsb.s_fname);
+ if ((*label = calloc(namesize + 1, 1)) != NULL)
+ memcpy(*label, xfsb.s_fname, namesize);
+ rv = 0;
}
close(fd);
-
- /* superblock is ext2 - now what is its label? */
- memcpy(uuid, e2sb.s_uuid, sizeof(e2sb.s_uuid));
- *label = strdup(e2sb.s_volume_name);
-
- return 0;
+ return rv;
}
static void
@@ -91,8 +104,14 @@ uuidcache_init(void) {
return;
procpt = fopen(PROC_PARTITIONS, "r");
- if (!procpt)
+ if (!procpt) {
+ static int warn = 0;
+ if (!warn++)
+ error (_("mount: could not open %s, so UUID and LABEL "
+ "conversion cannot be done.\n"),
+ PROC_PARTITIONS);
return;
+ }
for (firstPass = 1; firstPass >= 0; firstPass--) {
fseek(procpt, 0, SEEK_SET);
diff --git a/mount/mount_constants.h b/mount/mount_constants.h
index aeb7edfb3..5fd290829 100644
--- a/mount/mount_constants.h
+++ b/mount/mount_constants.h
@@ -19,12 +19,31 @@
#ifndef MS_MANDLOCK
#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */
#endif
+#ifndef MS_ACTION_MASK
+#define MS_ACTION_MASK 0x380
+/* Remount, but new filesystem may be different from old. Atomic
+ (i.e. there is no interval when nothing is mounted at the mountpoint).
+ If new fs differs from the old one and old is busy - -EBUSY. */
+#define MS_REPLACE 0x080 /* 128 */
+/* After, Before: as soon as we get unions these will add a new member
+ in the end or beginning of the chain. Fail if there is a stack
+ on the mountpoint. */
+#define MS_AFTER 0x100 /* 256 */
+#define MS_BEFORE 0x180
+/* Over: if nothing mounted on a mountpoint - same as if none of these
+flags had been set; if we have a union with more than one element - fail;
+if we have a stack or plain mount - mount atop of it, forming a stack. */
+#define MS_OVER 0x200 /* 512 */
+#endif
#ifndef MS_NOATIME
#define MS_NOATIME 1024 /* Do not update access times. */
#endif
#ifndef MS_NODIRATIME
#define MS_NODIRATIME 2048 /* Do not update directory access times */
#endif
+#ifndef MS_BIND
+#define MS_BIND 4096
+#endif
/*
* Magic mount flag number. Has to be or-ed to the flag values.
*/
diff --git a/mount/mount_guess_fstype.c b/mount/mount_guess_fstype.c
index ec39c531a..5a3733f98 100644
--- a/mount/mount_guess_fstype.c
+++ b/mount/mount_guess_fstype.c
@@ -20,6 +20,9 @@
* 1999-02-22 Arkadiusz Mi¶kiewicz <misiek@misiek.eu.org>
* - added Native Language Support
*
+ * Fri Dec 1 23:31:00 2000: Sepp Wijnands <mrrazz@garbage-coderz.net>
+ * added probes for cramfs, hfs, hpfs and adfs.
+ *
* aeb - many changes.
*
*/
@@ -63,24 +66,21 @@ swapped(unsigned short a) {
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 iso9660, romfs, qnx4, udf, swap - aeb
Added a test for high sierra (iso9660) - quinlan@bucknell.edu
Corrected the test for xiafs - aeb
- Added romfs - aeb
Added ufs from a patch by jj. But maybe there are several types of ufs?
Added ntfs from a patch by Richard Russon.
Added a very weak heuristic for vfat - aeb
- Added qnx4 - aeb
- Added swap - aeb
Added xfs - 2000-03-21 Martin K. Petersen <mkp@linuxcare.com>
-
- Currently supports: minix, ext, ext2, xiafs, iso9660, romfs,
- ufs, ntfs, vfat, qnx4, bfs, xfs
+ Added cramfs, hfs, hpfs, adfs - Sepp Wijnands <mrrazz@garbage-coderz.net>
*/
static char
-*magic_known[] = { "minix", "ext", "ext2", "xiafs", "iso9660", "romfs",
- "ufs", "ntfs", "qnx4", "bfs", "udf", "xfs",
- "swap" /* last - just to warn the user */
+*magic_known[] = {
+ "adfs", "bfs", "cramfs", "ext", "ext2",
+ "hfs", "hpfs", "iso9660", "minix", "ntfs",
+ "qnx4", "romfs", "swap", "udf", "ufs",
+ "xfs", "xiafs"
};
static int
@@ -97,7 +97,6 @@ tested(const char *device) {
causes a very large kernel delay, almost killing the machine.
So, we do not try udf unless there is positive evidence that it
might work. Try iso9660 first, it is much more likely.
-
Strings below taken from ECMA 167. */
static char
*udf_magic[] = { "BEA01", "BOOT2", "CD001", "CDW02", "NSR02",
@@ -119,6 +118,20 @@ may_be_swap(const char *s) {
strncmp(s-10, "SWAPSPACE2", 10) == 0);
}
+/* rather weak necessary condition */
+static int
+may_be_adfs(const u_char *s) {
+ u_char *p;
+ int sum;
+
+ p = (u_char *) s + 511;
+ sum = 0;
+ while(--p != s)
+ sum = (sum >> 8) + (sum & 0xff) + *p;
+
+ return (sum == p[511]);
+}
+
static char *
fstype(const char *device) {
int fd;
@@ -131,17 +144,21 @@ fstype(const char *device) {
union {
struct xiafs_super_block xiasb;
char romfs_magic[8];
- char xfs_magic[4];
char qnx4fs_magic[10]; /* ignore first 4 bytes */
long bfs_magic;
struct ntfs_super_block ntfssb;
struct fat_super_block fatsb;
+ struct xfs_super_block xfsb;
+ struct cramfs_super_block cramfssb;
} xsb;
struct ufs_super_block ufssb;
union {
struct iso_volume_descriptor iso;
struct hs_volume_descriptor hs;
} isosb;
+ struct hfs_super_block hfssb;
+ struct hpfs_super_block hpfssb;
+ struct adfs_super_block adfssb;
struct stat statbuf;
/* opening and reading an arbitrary unknown path can have
@@ -164,7 +181,8 @@ fstype(const char *device) {
type = "ext2";
else if (minixmagic(sb.ms) == MINIX_SUPER_MAGIC
- || minixmagic(sb.ms) == MINIX_SUPER_MAGIC2)
+ || minixmagic(sb.ms) == MINIX_SUPER_MAGIC2
+ || minixmagic(sb.ms) == swapped(MINIX_SUPER_MAGIC2))
type = "minix";
else if (extmagic(sb.es) == EXT_SUPER_MAGIC)
@@ -179,8 +197,8 @@ fstype(const char *device) {
type = "xiafs";
else if(!strncmp(xsb.romfs_magic, "-rom1fs-", 8))
type = "romfs";
- else if(!strncmp(xsb.xfs_magic, "XFSB", 4) ||
- !strncmp(xsb.xfs_magic, "BSFX", 4))
+ else if(!strncmp(xsb.xfsb.s_magic, XFS_SUPER_MAGIC, 4) ||
+ !strncmp(xsb.xfsb.s_magic, XFS_SUPER_MAGIC2, 4))
type = "xfs";
else if(!strncmp(xsb.qnx4fs_magic+4, "QNX4FS", 6))
type = "qnx4fs";
@@ -189,6 +207,8 @@ fstype(const char *device) {
else if(!strncmp(xsb.ntfssb.s_magic, NTFS_SUPER_MAGIC,
sizeof(xsb.ntfssb.s_magic)))
type = "ntfs";
+ else if(cramfsmagic(xsb.cramfssb) == CRAMFS_SUPER_MAGIC)
+ type = "cramfs";
else if ((!strncmp(xsb.fatsb.s_os, "MSDOS", 5) ||
!strncmp(xsb.fatsb.s_os, "MSWIN", 5) ||
!strncmp(xsb.fatsb.s_os, "MTOOL", 5) ||
@@ -222,6 +242,43 @@ fstype(const char *device) {
}
if (!type) {
+ if (lseek(fd, 0x400, SEEK_SET) != 0x400
+ || read(fd, (char *) &hfssb, sizeof(hfssb)) != sizeof(hfssb))
+ goto io_error;
+
+ /* also check if block size is equal to 512 bytes,
+ since the hfs driver currently only has support
+ for block sizes of 512 bytes long, and to be
+ more accurate (sb magic is only a short int) */
+ if ((hfsmagic(hfssb) == HFS_SUPER_MAGIC &&
+ hfsblksize(hfssb) == 0x20000) ||
+ (swapped(hfsmagic(hfssb)) == HFS_SUPER_MAGIC &&
+ hfsblksize(hfssb) == 0x200))
+ type = "hfs";
+ }
+
+ if (!type) {
+ if (lseek(fd, 0x2000, SEEK_SET) != 0x2000
+ || read(fd, (char *) &hpfssb, sizeof(hpfssb)) != sizeof(hpfssb))
+ goto io_error;
+
+ if (hpfsmagic(hpfssb) == HPFS_SUPER_MAGIC)
+ type = "hpfs";
+ }
+
+ if (!type) {
+ if (lseek(fd, 0xc00, SEEK_SET) != 0xc00
+ || read(fd, (char *) &adfssb, sizeof(adfssb)) != sizeof(adfssb))
+ goto io_error;
+
+ /* only a weak test */
+ if (may_be_adfs((u_char *) &adfssb)
+ && (adfsblksize(adfssb) >= 8 &&
+ adfsblksize(adfssb) <= 10))
+ type = "adfs";
+ }
+
+ if (!type) {
/* perhaps the user tries to mount the swap space
on a new disk; warn her before she does mke2fs on it */
int pagesize = getpagesize();
@@ -267,46 +324,40 @@ guess_fstype_from_superblock(const char *spec) {
return type;
}
-static FILE *procfs;
-
-static void
-procfsclose(void) {
- if (procfs)
- fclose (procfs);
- procfs = 0;
-}
-
-static int
-procfsopen(void) {
- procfs = fopen(ETC_FILESYSTEMS, "r");
- if (!procfs)
- procfs = fopen(PROC_FILESYSTEMS, "r");
- return (procfs != NULL);
-}
-
static char *
-procfsnext(void) {
+procfsnext(FILE *procfs) {
char line[100];
- static char fsname[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 fsname;
+ return strdup(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;
-
- if (procfsopen()) {
- while ((fsname = procfsnext()) != NULL)
- if (!strcmp(fsname, type))
- return 1;
+ 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 0;
+ return ret;
}
/* return: 0: OK, -1: error in errno, 1: type not found */
@@ -314,12 +365,20 @@ is_in_procfs(const char *type) {
int
procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args,
char **type) {
+ FILE *procfs;
char *fsname;
+ int ret = 1;
+ int errsv = 0;
*type = NULL;
- if (!procfsopen())
- return 1;
- while ((fsname = procfsnext()) != NULL) {
+
+ procfs = fopen(ETC_FILESYSTEMS, "r");
+ if (!procfs) {
+ procfs = fopen(PROC_FILESYSTEMS, "r");
+ if (!procfs)
+ return 1;
+ }
+ while ((fsname = procfsnext(procfs)) != NULL) {
if (tested (fsname))
continue;
args->type = fsname;
@@ -328,20 +387,17 @@ procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args,
fflush(stdout);
}
if ((*mount_fn) (args) == 0) {
- *type = xstrdup(fsname);
- procfsclose();
- return 0;
- } else if (errno != EINVAL) {
+ *type = fsname;
+ ret = 0;
+ break;
+ } else if (errno != EINVAL && is_in_procfs(fsname) == 1) {
*type = "guess";
- procfsclose();
- return -1;
+ ret = -1;
+ errsv = errno;
+ break;
}
}
- procfsclose();
- return 1;
-}
-
-int
-have_procfs(void) {
- return procfs != NULL;
+ fclose(procfs);
+ errno = errsv;
+ return ret;
}
diff --git a/mount/mount_guess_fstype.h b/mount/mount_guess_fstype.h
index 3663f74ca..9c0903b54 100644
--- a/mount/mount_guess_fstype.h
+++ b/mount/mount_guess_fstype.h
@@ -12,4 +12,4 @@ char *guess_fstype_from_superblock(const char *device);
int procfsloop(int (*mount_fn)(struct mountargs *), struct mountargs *args,
char **type);
int is_in_procfs(const char *fstype);
-int have_procfs(void);
+
diff --git a/mount/mount_guess_rootdev.c b/mount/mount_guess_rootdev.c
new file mode 100644
index 000000000..072c09fc4
--- /dev/null
+++ b/mount/mount_guess_rootdev.c
@@ -0,0 +1,90 @@
+/*
+ * Having the wrong rootdevice listed in mtab is slightly inconvenient.
+ * Try to guess what it could be...
+ * In case /proc/cmdline exists, and has the format
+ * stuff root=R more stuff...
+ * and we think we understand the number R, decode it as a root device.
+ *
+ * Another possibility:
+ * Erik Andersen writes:
+ * I did a similar find_real_root_device_name() in busybox some time back.
+ * Basically, do a stat("/", &rootstat) then walk /dev stat'ing each file
+ * and if (statbuf.st_rdev == rootstat.st_rdev) then you have a match.
+ * Works fine.
+ */
+#include <stdio.h>
+#include <string.h>
+#include "mount_guess_rootdev.h"
+
+#define PROC_CMDLINE "/proc/cmdline"
+
+static char *
+rootdev(char *p) {
+ unsigned long devno;
+ char *ep;
+ char *type = "hd";
+ char let;
+ int ma, mi;
+ char devname[8];
+
+ devno = strtoul(p, &ep, 16);
+ if ((ep == p+3 || ep == p+4) && (*ep == ' ' || *ep == 0)) {
+ ma = (devno >> 8);
+ mi = (devno & 0xff);
+ switch(ma) {
+ case 8:
+ type = "sd";
+ let = 'a'+(mi/16);
+ mi = mi%16;
+ break;
+ case 3:
+ let = 'a'; break;
+ case 0x16:
+ let = 'c'; break;
+ case 0x21:
+ let = 'e'; break;
+ case 0x22:
+ let = 'g'; break;
+ case 0x38:
+ let = 'i'; break;
+ case 0x39:
+ let = 'k'; break;
+ default:
+ return NULL;
+ }
+ if (mi & 0x40) {
+ mi -= 0x40;
+ let++;
+ }
+ if (mi == 0)
+ sprintf(devname, "/dev/%s%c", type, let);
+ else
+ sprintf(devname, "/dev/%s%c%d", type, let, mi);
+ return strdup(devname);
+ }
+ return NULL;
+}
+
+char *
+mount_guess_rootdev() {
+ FILE *cf;
+ char line[1024];
+ char *p;
+
+ cf = fopen(PROC_CMDLINE, "r");
+ if (cf && fgets(line, sizeof(line), cf)) {
+ for (p = line; *p; p++)
+ if (!strncmp(p, " root=", 6))
+ return rootdev(p+6);
+ }
+ return NULL;
+}
+
+#if 0
+main(){
+ char *p = mount_guess_rootdev();
+ if (!p)
+ p = "/dev/root";
+ printf("%s\n", p);
+}
+#endif
diff --git a/mount/mount_guess_rootdev.h b/mount/mount_guess_rootdev.h
new file mode 100644
index 000000000..41b327037
--- /dev/null
+++ b/mount/mount_guess_rootdev.h
@@ -0,0 +1 @@
+extern char *mount_guess_rootdev(void);
diff --git a/mount/nfs_mount4.h b/mount/nfs_mount4.h
index 0e3b052bd..85650773a 100644
--- a/mount/nfs_mount4.h
+++ b/mount/nfs_mount4.h
@@ -50,4 +50,5 @@ struct nfs_mount_data {
#define NFS_MOUNT_VER3 0x0080 /* 3 */
#define NFS_MOUNT_KERBEROS 0x0100 /* 3 */
#define NFS_MOUNT_NONLM 0x0200 /* 3 */
+#define NFS_MOUNT_BROKEN_SUID 0x0400 /* 4 */
diff --git a/mount/nfsmount.c b/mount/nfsmount.c
index bf4be6369..6fc917db5 100644
--- a/mount/nfsmount.c
+++ b/mount/nfsmount.c
@@ -58,6 +58,13 @@
#include "../defines.h" /* for HAVE_inet_aton */
+#ifndef NFS_PORT
+#define NFS_PORT 2049
+#endif
+#ifndef NFS_FHSIZE
+#define NFS_FHSIZE 32
+#endif
+
static char *nfs_strerror(int stat);
#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
@@ -90,7 +97,6 @@ int nfs_mount_version = NFS_MOUNT_VERSION;
* and figure out what version the kernel expects.
*
* Variables:
- * KERNEL_NFS_MOUNT_VERSION: kernel sources at compile time
* NFS_MOUNT_VERSION: these nfsmount sources at compile time
* nfs_mount_version: version this source and running kernel can handle
*/
@@ -106,6 +112,10 @@ find_kernel_nfs_mount_version(void) {
if (kernel_version) {
if (kernel_version < MAKE_VERSION(2,1,32))
nfs_mount_version = 1;
+ else if (kernel_version < MAKE_VERSION(2,2,18))
+ nfs_mount_version = 3;
+ else if (kernel_version < MAKE_VERSION(2,3,0))
+ nfs_mount_version = 4; /* since 2.2.18pre9 */
else if (kernel_version < MAKE_VERSION(2,3,99))
nfs_mount_version = 3;
else
@@ -201,6 +211,7 @@ int nfsmount(const char *spec, const char *node, int *flags,
int nocto;
int noac;
int nolock;
+ int broken_suid;
int retry;
int tcp;
int mountprog;
@@ -297,6 +308,7 @@ int nfsmount(const char *spec, const char *node, int *flags,
posix = 0;
nocto = 0;
nolock = 0;
+ broken_suid = 0;
noac = 0;
retry = 10000; /* 10000 minutes ~ 1 week */
tcp = 0;
@@ -407,6 +419,8 @@ int nfsmount(const char *spec, const char *node, int *flags,
nolock = !val;
else
printf(_("Warning: option nolock is not supported.\n"));
+ } else if (!strcmp(opt, "broken_suid")) {
+ broken_suid = val;
} else {
if (!sloppy) {
printf(_("unknown nfs mount option: "
@@ -431,6 +445,10 @@ int nfsmount(const char *spec, const char *node, int *flags,
if (nfs_mount_version >= 3)
data.flags |= (nolock ? NFS_MOUNT_NONLM : 0);
#endif
+#if NFS_MOUNT_VERSION >= 4
+ if (nfs_mount_version >= 4)
+ data.flags |= (broken_suid ? NFS_MOUNT_BROKEN_SUID : 0);
+#endif
if (nfsvers > MAX_NFSPROT) {
fprintf(stderr, "NFSv%d not supported!\n", nfsvers);
return 0;
diff --git a/mount/pivot_root.c b/mount/pivot_root.c
index 4ab8be853..fd4bef9df 100644
--- a/mount/pivot_root.c
+++ b/mount/pivot_root.c
@@ -6,7 +6,7 @@
#include <stdio.h>
#include <linux/unistd.h>
-
+static
_syscall2(int,pivot_root,const char *,new_root,const char *,put_old)
diff --git a/mount/umount.8 b/mount/umount.8
index 08d39888d..0b67314c5 100644
--- a/mount/umount.8
+++ b/mount/umount.8
@@ -67,6 +67,10 @@ Unmount without writing in
.B \-r
In case unmounting fails, try to remount read-only.
.TP
+.B \-d
+In case the unmounted device was a loop device, also
+free this loop device.
+.TP
.B \-a
All of the file systems described in
.I /etc/mtab
@@ -92,7 +96,8 @@ The
.B umount
command will free the loop device (if any) associated
with the mount, in case it finds the option `loop=...' in
-.IR /etc/mtab .
+.IR /etc/mtab ,
+or when the \-d option was given.
Any pending loop devices can be freed using `losetup -d', see
.BR losetup (8).
diff --git a/mount/umount.c b/mount/umount.c
index 98a1d330a..24622bc98 100644
--- a/mount/umount.c
+++ b/mount/umount.c
@@ -16,18 +16,21 @@
* 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 - canonise names from fstab
+ * 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
*/
+#include <stdio.h>
#include <unistd.h>
#include <getopt.h>
#include <string.h>
#include <errno.h>
+#include <ctype.h>
#include <sys/stat.h>
#include <sys/mount.h>
#include "mount_constants.h"
@@ -88,7 +91,10 @@ int remount = 0;
/* Don't write a entry in /etc/mtab (-n). */
int nomtab = 0;
-/* Nonzero for chatty (-v). This is a nonstandard flag (not in BSD). */
+/* Call losetup -d for each unmounted loop device. */
+int delloop = 0;
+
+/* Nonzero for chatty (-v). */
int verbose = 0;
/* True if ruid != euid. */
@@ -107,6 +113,7 @@ nfs_umount_rpc_call(const char *spec, const char *opts)
struct sockaddr_in saddr;
struct timeval pertry, try;
enum clnt_stat clnt_stat;
+ int port = 0;
int so = RPC_ANYSOCK;
struct hostent *hostp;
char *hostname;
@@ -131,6 +138,9 @@ nfs_umount_rpc_call(const char *spec, const char *opts)
hostname = xstrndup(p,q-p);
}
+ if (opts && (p = strstr(opts, "mountport=")) && isdigit(*(p+10)))
+ port = atoi(p+10);
+
if (hostname[0] >= '0' && hostname[0] <= '9')
saddr.sin_addr.s_addr = inet_addr(hostname);
else {
@@ -147,7 +157,7 @@ nfs_umount_rpc_call(const char *spec, const char *opts)
}
saddr.sin_family = AF_INET;
- saddr.sin_port = 0;
+ saddr.sin_port = htons(port);
pertry.tv_sec = 3;
pertry.tv_usec = 0;
if ((clp = clntudp_create(&saddr, MOUNTPROG, MOUNTVERS,
@@ -202,134 +212,147 @@ static void complain(int err, const char *dev) {
on a non-fatal error. We lock/unlock around each umount. */
static int
umount_one (const char *spec, const char *node, const char *type,
- const char *opts, struct mntentchn *mc)
-{
- int umnt_err, umnt_err2;
- int isroot;
- int res;
-
- /* Special case for root. As of 0.99pl10 we can (almost) unmount root;
- the kernel will remount it readonly so that we can carry on running
- afterwards. The readonly remount is illegal if any files are opened
- for writing at the time, so we can't update mtab for an unmount of
- root. As it is only really a remount, this doesn't matter too
- much. [sct May 29, 1993] */
- isroot = (streq (node, "/") || streq (node, "root")
- || streq (node, "rootfs"));
- if (isroot)
- nomtab++;
+ const char *opts, struct mntentchn *mc) {
+ int umnt_err, umnt_err2;
+ int isroot;
+ int res;
+ const char *loopdev;
+
+ /* Special case for root. As of 0.99pl10 we can (almost) unmount root;
+ the kernel will remount it readonly so that we can carry on running
+ afterwards. The readonly remount is illegal if any files are opened
+ for writing at the time, so we can't update mtab for an unmount of
+ root. As it is only really a remount, this doesn't matter too
+ much. [sct May 29, 1993] */
+ isroot = (streq (node, "/") || streq (node, "root")
+ || streq (node, "rootfs"));
+ if (isroot)
+ nomtab++;
#ifdef HAVE_NFS
- /* Ignore any RPC errors, so that you can umount the filesystem
- if the server is down. */
- if (strcasecmp(type, "nfs") == 0)
- nfs_umount_rpc_call(spec, opts);
+ /* Ignore any RPC errors, so that you can umount the filesystem
+ if the server is down. */
+ if (strcasecmp(type, "nfs") == 0)
+ nfs_umount_rpc_call(spec, opts);
#endif
- umnt_err = umnt_err2 = 0;
- if (force) {
- /* completely untested - 2.1.116 only has some support in nfs case */
- /* probably this won't work */
- int flags = MNT_FORCE;
-
- res = umount2 (node, flags);
- if (res == -1) {
- perror("umount2");
- if (errno == ENOSYS) {
- if (verbose)
- printf(_("no umount2, trying umount...\n"));
- res = umount (node);
- }
- }
- } else
- res = umount (node);
- if (res < 0) {
- umnt_err = errno;
- /* A device might have been mounted on a node that has since
- been deleted or renamed, so if node fails, also try spec. */
- /* if (umnt_err == ENOENT || umnt_err == EINVAL) */
- if (umnt_err != EBUSY && strcmp(node, spec)) {
- if (verbose)
- printf (_("could not umount %s - trying %s instead\n"),
- node, spec);
- res = umount (spec);
- if (res < 0)
- umnt_err2 = errno;
- /* Do not complain about remote NFS mount points */
- if (errno == ENOENT && index(spec, ':'))
- umnt_err2 = 0;
- }
- }
-
- if (res < 0 && remount && (umnt_err == EBUSY || umnt_err2 == EBUSY)) {
- /* Umount failed - let us try a remount */
- res=mount(spec, node, NULL, MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
- if (res == 0) {
- struct mntent remnt;
- fprintf(stderr, _("umount: %s busy - remounted read-only\n"), spec);
- remnt.mnt_type = remnt.mnt_fsname = NULL;
- remnt.mnt_dir = xstrdup(node);
- remnt.mnt_opts = "ro";
- update_mtab(node, &remnt);
- return 0;
- } else if (errno != EBUSY) { /* hmm ... */
- perror("remount");
- fprintf(stderr, _("umount: could not remount %s read-only\n"),
- spec);
- }
- }
-
- if (res >= 0) {
- /* Umount succeeded, update mtab. */
- if (verbose)
- printf (_("%s umounted\n"), spec);
-
- if (!nomtab && mtab_is_writable()) {
- /* Special stuff for loop devices */
- if (mc) {
- char *optl;
-
- /* old style mtab line? */
- if (streq(mc->mnt_type, "loop"))
- if (del_loop(spec))
- goto fail;
-
- /* new style mtab line? */
- optl = mc->mnt_opts ? xstrdup(mc->mnt_opts) : "";
- for (optl = strtok (optl, ","); optl; optl = strtok (NULL, ",")) {
- if (!strncmp(optl, "loop=", 5)) {
- if (del_loop(optl+5))
- goto fail;
- break;
- }
- }
- } else {
- /* maybe spec is a loop device? */
- /* no del_loop() - just delete it from mtab */
- if ((mc = getmntoptfile (spec)) != NULL)
- node = mc->mnt_dir;
- }
-
- /* Non-loop stuff */
- update_mtab (node, NULL);
- }
- return 0;
- }
-
-fail:
- /* Umount or del_loop failed, complain, but don't die. */
- if (!nomtab) {
- /* remove obsolete entry */
- if (umnt_err == EINVAL || umnt_err == ENOENT)
- update_mtab (node, NULL);
- }
+ umnt_err = umnt_err2 = 0;
+ if (force) {
+ /* completely untested;
+ 2.1.116 only has some support in nfs case */
+ /* probably this won't work */
+ int flags = MNT_FORCE;
+
+ res = umount2 (node, flags);
+ if (res == -1) {
+ perror("umount2");
+ if (errno == ENOSYS) {
+ if (verbose)
+ printf(_("no umount2, trying umount...\n"));
+ res = umount (node);
+ }
+ }
+ } else
+ res = umount (node);
+
+ if (res < 0) {
+ umnt_err = errno;
+ /* A device might have been mounted on a node that has since
+ been deleted or renamed, so if node fails, also try spec. */
+ /* Note that this is incorrect in case spec was mounted
+ several times. */
+ /* if (umnt_err == ENOENT || umnt_err == EINVAL) */
+ if (umnt_err != EBUSY && strcmp(node, spec)) {
+ if (verbose)
+ printf (_("could not umount %s - trying %s instead\n"),
+ node, spec);
+ res = umount (spec);
+ if (res < 0)
+ umnt_err2 = errno;
+ /* Do not complain about remote NFS mount points */
+ if (errno == ENOENT && index(spec, ':'))
+ umnt_err2 = 0;
+ }
+ }
+
+ if (res < 0 && remount && (umnt_err == EBUSY || umnt_err2 == EBUSY)) {
+ /* Umount failed - let us try a remount */
+ res = mount(spec, node, NULL,
+ MS_MGC_VAL | MS_REMOUNT | MS_RDONLY, NULL);
+ if (res == 0) {
+ struct mntent remnt;
+ fprintf(stderr,
+ _("umount: %s busy - remounted read-only\n"),
+ spec);
+ remnt.mnt_type = remnt.mnt_fsname = NULL;
+ remnt.mnt_dir = xstrdup(node);
+ remnt.mnt_opts = "ro";
+ update_mtab(node, &remnt);
+ return 0;
+ } else if (errno != EBUSY) { /* hmm ... */
+ perror("remount");
+ fprintf(stderr,
+ _("umount: could not remount %s read-only\n"),
+ spec);
+ }
+ }
+
+ loopdev = 0;
+ if (res >= 0) {
+ /* Umount succeeded */
+ if (verbose)
+ printf (_("%s umounted\n"), spec);
+
+ /* Free any loop devices that we allocated ourselves */
+ if (mc) {
+ char *optl;
+
+ /* old style mtab line? */
+ if (streq(mc->m.mnt_type, "loop")) {
+ loopdev = spec;
+ goto gotloop;
+ }
+
+ /* new style mtab line? */
+ optl = mc->m.mnt_opts ? xstrdup(mc->m.mnt_opts) : "";
+ for (optl = strtok (optl, ","); optl;
+ optl = strtok (NULL, ",")) {
+ if (!strncmp(optl, "loop=", 5)) {
+ loopdev = optl+5;
+ goto gotloop;
+ }
+ }
+ } else {
+ /*
+ * If option "-o loop=spec" occurs in mtab,
+ * note the mount point, and delete mtab line.
+ */
+ if ((mc = getmntoptfile (spec)) != NULL)
+ node = mc->m.mnt_dir;
+ }
+
+ /* Also free loop devices when -d flag is given */
+ if (delloop && is_loop_device(spec))
+ loopdev = spec;
+ }
+ gotloop:
+ if (loopdev)
+ del_loop(loopdev);
+
+ if (!nomtab && mtab_is_writable() &&
+ (umnt_err == 0 || umnt_err == EINVAL || umnt_err == ENOENT)) {
+ update_mtab (node, NULL);
+ }
+
+ if (res >= 0)
+ return 0;
- if (umnt_err2)
- complain(umnt_err2, spec);
- if (umnt_err && umnt_err != umnt_err2)
- complain(umnt_err, node);
- return 1;
+ if (umnt_err2)
+ complain(umnt_err2, spec);
+ if (umnt_err && umnt_err != umnt_err2)
+ complain(umnt_err, node);
+ return 1;
}
/*
@@ -347,8 +370,8 @@ umount_one_bw (const char *file, struct mntentchn *mc) {
int res = 1;
while (res && mc) {
- res = umount_one(mc->mnt_fsname, mc->mnt_dir,
- mc->mnt_type, mc->mnt_opts, mc);
+ res = umount_one(mc->m.mnt_fsname, mc->m.mnt_dir,
+ mc->m.mnt_type, mc->m.mnt_opts, mc);
mc = getmntfilesbackward (file, mc);
}
return res;
@@ -368,9 +391,9 @@ umount_all (string_list types) {
if (!hd->prev)
die (2, _("umount: cannot find list of filesystems to unmount"));
for (mc = hd->prev; mc != hd; mc = mc->prev) {
- if (matching_type (mc->mnt_type, types)) {
- errors |= umount_one (mc->mnt_fsname, mc->mnt_dir,
- mc->mnt_type, mc->mnt_opts, mc);
+ if (matching_type (mc->m.mnt_type, types)) {
+ errors |= umount_one (mc->m.mnt_fsname, mc->m.mnt_dir,
+ mc->m.mnt_type, mc->m.mnt_opts, mc);
}
}
@@ -424,6 +447,10 @@ main (int argc, char *argv[])
case 'a': /* umount everything */
++all;
break;
+ /* fall through? */
+ case 'd': /* do losetup -d for unmounted loop devices */
+ ++delloop;
+ break;
case 'f': /* force umount */
++force;
break;
@@ -489,7 +516,7 @@ main (int argc, char *argv[])
then "mount /dev/sda4" followed by "umount /mnt/zip"
used to fail. So, we must not look for file, but for
the pair (spec,file) in fstab. */
- fs = getfsspecfile(mc->mnt_fsname, mc->mnt_dir);
+ fs = getfsspecfile(mc->m.mnt_fsname, mc->m.mnt_dir);
if (!fs) {
if (!getfsspec (file) && !getfsfile (file))
die (2,
@@ -508,7 +535,7 @@ main (int argc, char *argv[])
/* The option `owner' only allows (un)mounting by the owner. */
/* A convenient side effect is that the user who mounted
is visible in mtab. */
- options = parse_list (fs->mnt_opts);
+ options = parse_list (fs->m.mnt_opts);
while (options) {
if (streq (car (options), "user") ||
streq (car (options), "users") ||
@@ -518,18 +545,18 @@ main (int argc, char *argv[])
}
if (!options)
die (2, _("umount: only root can unmount %s from %s"),
- fs->mnt_fsname, fs->mnt_dir);
+ fs->m.mnt_fsname, fs->m.mnt_dir);
if (streq (car (options), "user") ||
streq (car (options), "owner")) {
char *user = getusername();
- options = parse_list (mc->mnt_opts);
+ options = parse_list (mc->m.mnt_opts);
while (options) {
char *co = car (options);
if (!strncmp(co, "user=", 5)) {
if (!user || !streq(co+5,user))
die(2, _("umount: only %s can unmount %s from %s"),
- co+5, fs->mnt_fsname, fs->mnt_dir);
+ co+5, fs->m.mnt_fsname, fs->m.mnt_dir);
break;
}
options = cdr (options);