summaryrefslogtreecommitdiffstats
path: root/mount
diff options
context:
space:
mode:
authorKarel Zak2006-12-07 00:25:34 +0100
committerKarel Zak2006-12-07 00:25:34 +0100
commitfd6b7a7ffc50400704beb41d5a23af5f9edb1eed (patch)
tree997c0ca2abc018369babd7da59bcd0afe492068e /mount
parentImported from util-linux-2.5 tarball. (diff)
downloadkernel-qcow2-util-linux-fd6b7a7ffc50400704beb41d5a23af5f9edb1eed.tar.gz
kernel-qcow2-util-linux-fd6b7a7ffc50400704beb41d5a23af5f9edb1eed.tar.xz
kernel-qcow2-util-linux-fd6b7a7ffc50400704beb41d5a23af5f9edb1eed.zip
Imported from util-linux-2.7.1 tarball.
Diffstat (limited to 'mount')
-rw-r--r--mount/Makefile110
-rw-r--r--mount/Makefile.standalone143
-rw-r--r--mount/README.mount153
-rw-r--r--mount/fstab.55
-rw-r--r--mount/fstab.c419
-rw-r--r--mount/fstab.h45
-rw-r--r--mount/h/loop.h (renamed from mount/loop.h)36
-rw-r--r--mount/h/swap.h5
-rw-r--r--mount/lomount.c232
-rw-r--r--mount/lomount.h4
-rw-r--r--mount/losetup.887
-rw-r--r--mount/losetup.c225
-rw-r--r--mount/mount.81184
-rw-r--r--mount/mount.c1023
-rw-r--r--mount/mount.x161
-rw-r--r--mount/mount_clnt.c94
-rw-r--r--mount/mount_constants.h17
-rw-r--r--mount/mount_xdr.c150
-rw-r--r--mount/nfs_mount3.h57
-rw-r--r--mount/nfsmount.c197
-rw-r--r--mount/nfsmount.h (renamed from mount/rpcsvc/mount.h)123
-rw-r--r--mount/nfsmount.x259
-rw-r--r--mount/nfsmount_clnt.c255
-rw-r--r--mount/nfsmount_xdr.c351
-rw-r--r--mount/realpath.c10
-rw-r--r--mount/rpcsvc/mount.x161
-rw-r--r--mount/rpcsvc/mount_clnt.c94
-rw-r--r--mount/rpcsvc/mount_xdr.c150
-rw-r--r--mount/rpcsvc/nfsmount.h (renamed from mount/mount.h)123
-rw-r--r--mount/rpcsvc/nfsmount.x259
-rw-r--r--mount/rpcsvc/nfsmount_clnt.c255
-rw-r--r--mount/rpcsvc/nfsmount_xdr.c351
-rw-r--r--mount/sundries.c410
-rw-r--r--mount/sundries.h58
-rw-r--r--mount/swap.configure22
-rw-r--r--mount/swapon.815
-rw-r--r--mount/swapon.c162
-rw-r--r--mount/umount.8109
-rw-r--r--mount/umount.c459
-rw-r--r--mount/version.c2
40 files changed, 5407 insertions, 2568 deletions
diff --git a/mount/Makefile b/mount/Makefile
index 22c146ce0..cfbedd59d 100644
--- a/mount/Makefile
+++ b/mount/Makefile
@@ -1,19 +1,13 @@
-# To make "ext" the default file system type for mount
-# (used when no other type is specified), replace \"minix\" by \"ext2\".
-# Use iso9660 instead, since CDROMs are popular.
-DEFAULT_FSTYPE=\"iso9660\"
-
-# you need rpcgen and libc-4.2 or rpclib to compile in the NFS support
-DEFINES = -DHAVE_NFS -DFSTYPE_DEFAULT=$(DEFAULT_FSTYPE)
-
+ifeq (../MCONFIG,$(wildcard ../MCONFIG))
include ../MCONFIG
-#CC = gcc
-#OPTFLAGS= -O2 -m486 -fomit-frame-pointer
-##OPTFLAGS= -O2 -fomit-frame-pointer # or change on make's command line
-#CFLAGS = -pipe $(OPTFLAGS)
+endif
+
+CC = gcc
+CFLAGS = -O2
WARNFLAGS = -Wall -Wstrict-prototypes -Wmissing-prototypes
-#LDFLAGS = -s -N
-LDLIBS =
+DEFINES = -DHAVE_NFS
+LDFLAGS =
+
RPCSVCDIR = rpcsvc
RPC_CFLAGS = -Wno-unused
RPCGEN = rpcgen
@@ -21,12 +15,11 @@ RPCGEN = rpcgen
#INSTALL_SUID = $(INSTALL) -m 4755 -o root
#INSTALL_PROG = $(INSTALL) -m 755
#INSTALL_DATA = $(INSTALL) -m 644
-#prefix = /usr
## for suid progs (mount, umount)
#BINDIR = /bin
## for nosuid progs (swapon)
-#SBINDIR = /etc
+#SBINDIR = /sbin
# End of configuration section.
@@ -34,15 +27,15 @@ COMPILE = $(CC) -c $(WARNFLAGS) $(CFLAGS) $(DEFINES)
LINK = $(CC) $(LDFLAGS)
SUID_PROGS = mount umount
-NOSUID_PROGS = swapon
+NOSUID_PROGS = swapon losetup
PROGS = $(SUID_PROGS) $(NOSUID_PROGS)
MAN5 = fstab.5 nfs.5
-MAN8 = mount.8 swapoff.8 swapon.8 umount.8
+MAN8 = mount.8 swapoff.8 swapon.8 umount.8 losetup.8
# comment these out if you are not compiling in NFS support
-NFS_OBJS = nfsmount.o mount_xdr.o mount_clnt.o
+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
-GEN_FILES = mount.x mount.h mount_xdr.c mount_clnt.c
+GEN_FILES = nfsmount.x nfsmount.h nfsmount_xdr.c nfsmount_clnt.c
# comment these out if you are not compiling in loop support
LO_OBJS=lomount.o
@@ -61,34 +54,75 @@ install: $(PROGS)
%.o: %.c
$(COMPILE) $<
-mount: mount.o fstab.o sundries.o version.o $(NFS_OBJS) $(LO_OBJS)
+mount: mount.o fstab.o sundries.o realpath.o version.o $(NFS_OBJS) $(LO_OBJS)
$(LINK) $^ $(LDLIBS) -o $@
-umount: umount.o fstab.o sundries.o version.o $(LO_OBJS)
+umount: umount.o fstab.o sundries.o realpath.o version.o $(LO_OBJS)
$(LINK) $^ $(LDLIBS) -o $@
-swapon: swapon.o fstab.o version.o
+swapon: swapon.o version.o
$(LINK) $^ $(LDLIBS) -o $@
-nfsmount.o mount_xdr.o mount_clnt.o: mount.h
+losetup: losetup.o
+ $(LINK) $^ $(LDLIBS) -o $@
+
+mount.o umount.o nfsmount.o losetup.o fstab.o sundries.o: sundries.h
+
+mount.o umount.o fstab.o sundries.o: fstab.h
+
+mount.o umount.o losetup.o: lomount.h loop.h
+
+swapon.o: swap.h swapargs.h
-mount_clnt.o: mount_clnt.c
- $(COMPILE) $(RPC_CFLAGS) mount_clnt.c
+sundries.o nfsmount.o nfsmount_xdr.o nfsmount_clnt.o: nfsmount.h
-mount_xdr.o: mount_xdr.c
- $(COMPILE) $(RPC_CFLAGS) mount_xdr.c
+nfsmount_clnt.o: nfsmount_clnt.c
+ $(COMPILE) $(RPC_CFLAGS) nfsmount_clnt.c
-mount.h mount_xdr.c mount_clnt.c: mount.x
- rm -f mount.h mount_xdr.c mount_clnt.c
- $(RPCGEN) -h -o mount.h mount.x
- $(RPCGEN) -c -o mount_xdr.c mount.x
- $(RPCGEN) -l -o mount_clnt.c mount.x
+nfsmount_xdr.o: nfsmount_xdr.c
+ $(COMPILE) $(RPC_CFLAGS) nfsmount_xdr.c
-mount.x:
- cp $(RPCSVCDIR)/mount.x .
+# rpcgen generates files that do not compile - use the pregenerated ones
+# nfsmount.h nfsmount_xdr.c nfsmount_clnt.c: nfsmount.x
+# rm -f nfsmount.h nfsmount_xdr.c nfsmount_clnt.c
+# $(RPCGEN) -h -o nfsmount.h nfsmount.x
+# $(RPCGEN) -c -o nfsmount_xdr.c nfsmount.x
+# $(RPCGEN) -l -o nfsmount_clnt.c nfsmount.x
+
+nfsmount.x:
+ cp $(RPCSVCDIR)/nfsmount.x .
+
+nfsmount.o: nfs_mountversion.h nfs_mount3.h
+
+NFSMOUNTH=/usr/include/linux/nfs_mount.h
+SWAPH=/usr/include/linux/swap.h
+LOOPH=/usr/include/linux/loop.h
+
+nfs_mountversion.h:
+ rm -f nfs_mountversion.h
+ if [ -f $(NFSMOUNTH) ]; then \
+ grep NFS_MOUNT_VERSION $(NFSMOUNTH) \
+ | sed -e 's/NFS/KERNEL_NFS/'; \
+ else \
+ echo '#define KERNEL_NFS_MOUNT_VERSION 0'; \
+ fi > nfs_mountversion.h
+
+swap.h:
+ rm -f swap.h
+ if [ -f $(SWAPH) ]; then cp $(SWAPH) .; else touch swap.h; fi
+
+swapargs.h:
+ sh swap.configure
+
+loop.h:
+ rm -f loop.h
+ if [ -f $(LOOPH) ]; then cp $(LOOPH) .; else touch loop.h; fi
clean:
- rm -f a.out core *~ *.o $(PROGS)
+ rm -f a.out core *~ *.o swapargs.h $(PROGS)
+
+cleaner: clean
+ rm -f swap.h loop.h nfs_mountversion.h
-clobber: clean
- rm -f $(PROGS) $(GEN_FILES)
+clobber distclean realclean: cleaner
+# rm -f $(GEN_FILES)
diff --git a/mount/Makefile.standalone b/mount/Makefile.standalone
new file mode 100644
index 000000000..9576cdb1d
--- /dev/null
+++ b/mount/Makefile.standalone
@@ -0,0 +1,143 @@
+# ifeq (../MCONFIG,$(wildcard ../MCONFIG))
+# include ../MCONFIG
+# endif
+
+# For now: a standalone version
+
+CC = gcc
+CFLAGS = -O2
+
+#WARNFLAGS = -Wall -Wstrict-prototypes
+# We really want
+WARNFLAGS = -Wall -Wstrict-prototypes -Wmissing-prototypes
+# but at the moment that yields
+#<linux/socket.h>:72: warning: no previous prototype for `cmsg_nxthdr'
+
+# you need rpcgen and libc-4.2 or rpclib to compile in the NFS support
+# pregenerated files are included.
+# Make sure nfsmount_clnt.c is newer than nfsmount.x to avoid gcc complaints.
+DEFINES = -DHAVE_NFS
+
+RPCSVCDIR = rpcsvc
+RPC_CFLAGS = -Wno-unused
+RPCGEN = rpcgen
+
+INSTALL = install
+INSTALL_SUID = $(INSTALL) -m 4755 -o root
+INSTALL_PROG = $(INSTALL) -m 755
+INSTALL_DATA = $(INSTALL) -m 644
+INSTALL_DIR = mkdir -p
+INSTALL_MAN = $(INSTALL_DATA)
+
+MANDIR = /usr/man
+## for suid progs (mount, umount)
+BINDIR = /bin
+## for nosuid progs (swapon)
+SBINDIR = /sbin
+
+# End of configuration section.
+
+COMPILE = $(CC) -c $(WARNFLAGS) $(CFLAGS) $(DEFINES)
+LINK = $(CC) $(LDFLAGS)
+
+SUID_PROGS = mount umount
+NOSUID_PROGS = swapon losetup
+PROGS = $(SUID_PROGS) $(NOSUID_PROGS)
+MAN5 = fstab.5 nfs.5
+MAN8 = mount.8 swapoff.8 swapon.8 umount.8 losetup.8
+
+# 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
+GEN_FILES = nfsmount.x nfsmount.h nfsmount_xdr.c nfsmount_clnt.c
+
+# comment these out if you are not compiling in loop support
+LO_OBJS=lomount.o
+
+all: $(PROGS)
+
+install: $(PROGS)
+ $(INSTALL_DIR) $(BINDIR) $(SBINDIR)
+ $(INSTALL_SUID) -s $(SUID_PROGS) $(BINDIR)
+ $(INSTALL_PROG) -s $(NOSUID_PROGS) $(SBINDIR)
+ (cd $(SBINDIR); ln -sf swapon swapoff)
+ $(INSTALL_DIR) $(MANDIR)/man5 $(MANDIR)/man8
+ $(INSTALL_MAN) $(MAN5) $(MANDIR)/man5
+ $(INSTALL_MAN) $(MAN8) $(MANDIR)/man8
+
+%.o: %.c
+ $(COMPILE) $<
+
+mount: mount.o fstab.o sundries.o realpath.o version.o $(NFS_OBJS) $(LO_OBJS)
+ $(LINK) $^ -o $@
+
+umount: umount.o fstab.o sundries.o realpath.o version.o $(LO_OBJS)
+ $(LINK) $^ -o $@
+
+swapon: swapon.o version.o
+ $(LINK) $^ -o $@
+
+losetup: losetup.o
+ $(LINK) $^ -o $@
+
+mount.o umount.o nfsmount.o losetup.o fstab.o sundries.o: sundries.h
+
+mount.o umount.o fstab.o sundries.o: fstab.h
+
+mount.o umount.o losetup.o: lomount.h loop.h
+
+swapon.o: swap.h swapargs.h
+
+sundries.o nfsmount.o nfsmount_xdr.o nfsmount_clnt.o: nfsmount.h
+
+umount.o: mount_constants.h
+
+nfsmount_clnt.o: nfsmount_clnt.c
+ $(COMPILE) $(RPC_CFLAGS) nfsmount_clnt.c
+
+nfsmount_xdr.o: nfsmount_xdr.c
+ $(COMPILE) $(RPC_CFLAGS) nfsmount_xdr.c
+
+nfsmount.h nfsmount_xdr.c nfsmount_clnt.c: nfsmount.x
+ rm -f nfsmount.h nfsmount_xdr.c nfsmount_clnt.c
+ $(RPCGEN) -h -o nfsmount.h nfsmount.x
+ $(RPCGEN) -c -o nfsmount_xdr.c nfsmount.x
+ $(RPCGEN) -l -o nfsmount_clnt.c nfsmount.x
+
+nfsmount.x:
+ cp $(RPCSVCDIR)/nfsmount.x .
+
+nfsmount.o: nfs_mountversion.h nfs_mount3.h
+
+NFSMOUNTH=/usr/include/linux/nfs_mount.h
+SWAPH=/usr/include/linux/swap.h
+LOOPH=/usr/include/linux/loop.h
+
+nfs_mountversion.h:
+ rm -f nfs_mountversion.h
+ if [ -f $(NFSMOUNTH) ]; then \
+ grep NFS_MOUNT_VERSION $(NFSMOUNTH) \
+ | sed -e 's/NFS/KERNEL_NFS/'; \
+ else \
+ echo '#define KERNEL_NFS_MOUNT_VERSION 0'; \
+ fi > nfs_mountversion.h
+
+swap.h:
+ rm -f swap.h
+ if [ -f $(SWAPH) ]; then cp $(SWAPH) .; else touch swap.h; fi
+
+swapargs.h:
+ sh swap.configure
+
+loop.h:
+ rm -f loop.h
+ if [ -f $(LOOPH) ]; then cp $(LOOPH) .; else touch loop.h; fi
+
+clean:
+ rm -f a.out core *~ *.o swapargs.h $(PROGS) swapoff
+
+cleaner: clean
+ rm -f swap.h loop.h nfs_mountversion.h
+
+clobber distclean realclean: cleaner
+ rm -f $(GEN_FILES)
diff --git a/mount/README.mount b/mount/README.mount
index 9bea2dc2e..2a8fae1c1 100644
--- a/mount/README.mount
+++ b/mount/README.mount
@@ -1,147 +1,10 @@
-mount/umount for Linux 0.99.14
-==============================
+mount/umount for Linux 0.97.3 and later.
+Authors:
+Doug Quale <quale@saavik.cs.wisc.edu>,
+H.J. Lu <hlu@eecs.wsu.edu>,
+Rick Sladkey <jrs@world.std.com>,
+Stephen Tweedie <sct@dcs.ed.ac.uk>.
-Enhance nfsmount.c to allow the program number or port number
-to be specified for both the mount daemon and the nfs daemon.
-Also anticipate tcp and namelen support.
+Presently maintained by Andries Brouwer <aeb@cwi.nl>.
+Ftp site: ftp.win.tue.nl:/pub/linux/util .
-Rewrite canonicalize in terms of realpath. Don't be obsessive about
-the path pre-existing for nfs, ifs, none, etc.
-
-Fix memory overwriting bug in the new remount code.
-
-Fix mtab handling in the new remount code so entries appear
-exactly once and in their proper mounting order.
-
-Fix defaults, remount and noauto so these options don't appear in the mtab.
-
-Repair extra options handling that got damaged with the remount code.
-
-Handle combining -o from the command line with options specified
-in /etc/mtab or /etc/fstab.
-
-Fix completely broken file-locking.
-
-Beautify the options field so it contains no duplicates or redundancies.
-
-Added long-style options to all programs.
-
-Added version and help options to all programs.
-
-Brought the Makefile up to GNU standards regarding CFLAGS and LDLFLAGS.
-
-Added support for the `user' option where mount and umount run suid to root.
-
-Rick Sladkey <jrs@world.std.com>
-
-mount/umount for Linux 0.99.10
-==============================
-
-[Stephen Tweedie <sct@dcs.ed.ac.uk>]
-
-A number of changes introduced to cater for new kernel facilities.
-mount can now remount an already-mounted filesystem, and umount
-attempts to unmount even root filesystems. Supercedes the [u]mount
-previously available in the bootutils-0.1 collection.
-
-Fixed a minor bug in canonicalise().
-
-mount/umount/swapon/swapoff(8) for Linux 0.99.6
-===============================================
-
-Here is a minor update to the previous version that fixes
-a longstanding "off by one" bug in parsing fs-specific
-options. No other real changes.
-
-mount/umount/swapon/swapoff(8) for Linux 0.99.2
-===============================================
-
-Here is a new version of Doug Quale's mount/umount package that
-includes support for mounting and unmount NFS filesystems. It is
-still possible to compile it without NFS support by modifying the
-Makefile. Even if you don't have rpcgen, but do have libc-4.2
-you can "cp -p" the pre-generated files in the rpcsvc directory
-into the mount source directory.
-
-The primary difference besides the actual NFS mounting code is that
-mount understands hostname:/path syntax for the "device" as well as
-the new keyword "none" which is useful for the proc filesystem. Also,
-umount had to be trained to specify the mount-point instead of the
-device when unmounting such filesystems. For compatibility,
-filesystems with true devices are unmounted using their device name
-which will still work with older kernels. However, all umounts could
-just as well be done by specifying the mount point instead of the
-device.
-
-Other changes since the beta NFS mount are:
-
-* incorportated H.J. Lu's changes for mtab permissions and errno handling
-* corrected the error message for unhandled errors from mount and umount
-* improved (a little :-) the reporting of handled mount and umount errors
-* added the ability to NFS mount from a IP address as well as a hostname
-* added a string error message instead of numeric for failed NFS mounts
-* changed 32 to _NSIG when setting all signals (should be using sigismember)
-* eliminated the obsolete HAVE_MOUNT5 and HAVE_SWAPOFF ifdefs
-* added support for the sync and async mount options
-* added the noauto option for fstab entries that shouldn't get mounted with -a
-* changed mount -a to check the mtab for already mounted filesystems
-* eliminated a few new warning messages from gcc 2.3.3
-* wrote an nfs man page
-
-Features still missing:
-
-* ability to background NFS mounts that have timed out
-* notify the NFS server of umounts (but addr=ip-addr support is in there)
-* add the possibility of interrupting an in-progress mount
-* man pages for the other Linux filesystem types
-
-Rick Sladkey
-jrs@world.std.com
-===============================================
-mount/umount/swapon/swapoff(8) for Linux 0.98.5
-===============================================
-
-This version fixed the umask of root. fchmod () is called
-before close /etc/mtab. This version should work with
-0.97.3 or above, although I only tested it under 0.98.5.
-I also fixed the error report.
-
-H.J. Lu
-hlu@eecs.wsu.edu
-11/25/92
-===============================================
-mount/umount/swapon/swapoff(8) for Linux 0.97.3
-===============================================
-
-The most significant improvement over the first release is the repair of
-at least a half dozen really dumb bugs, mostly involving null pointers.
-These bugs caused frequent core dumps and really made the code unusable.
-
-Some race conditions in the lock handling code have been removed.
-
-Swapoff is available for 0.97.3 and later kernels.
-
-Swapon supports multiple swap files. In particular, swapon -a will try
-to enable swapping on all the swap entries in /etc/fstab.
-
-File system specific mount options are now supported. This is of particular
-utility with Werner Almesberger's msdos fs.
-
-Umount -a now reads /etc/mtab instead of /etc/fstab (thanks to David
-Engel for a valuable discussion on this and other points). In addition,
-it umounts the entries in reverse order, ensuring that it tries to umount
-/usr/spool before /usr, for instance.
-
-Mount will now print mtab for ordinary users as well as for the superuser.
-Several people pointed out this deficiency, and it was a real no-brainer
-that broke it in the first release.
-
-Thanks to Linus, for another great release. 0.97.3 compiled the first time
-out and is working flawlessly. Thanks also to Ross Biro, for his work on
-Linux TCP/IP which has made it much easier to get this little thing off my
-machine. Special thanks to everyone who put up with my bugs.
-
-Brickbats etc. to
-
-Doug Quale
-quale@saavik.cs.wisc.edu
diff --git a/mount/fstab.5 b/mount/fstab.5
index 82bf0f4c1..e276350c2 100644
--- a/mount/fstab.5
+++ b/mount/fstab.5
@@ -70,8 +70,9 @@ field should be specified as ``none''.
The third field,
.RI ( fs_vfstype ),
-describes the type of the filesystem. The system currently supports three
-types of filesystems:
+describes the type of the filesystem. The system currently supports these
+types of filesystems (and possibly others - consult
+.IR /proc/filesystems ):
.TP
.I minix
a local filesystem, supporting filenames of length 14 or 30 characters.
diff --git a/mount/fstab.c b/mount/fstab.c
index d13280f8f..524779a63 100644
--- a/mount/fstab.c
+++ b/mount/fstab.c
@@ -1,92 +1,385 @@
-/* $Header: /home/faith/cvs/util-linux/mount/fstab.c,v 1.2 1995/10/07 01:32:03 faith Exp $ */
-
-#include "fstab.h"
+#include <unistd.h>
+#include <mntent.h>
+#include <errno.h>
#include <stdio.h>
+#include <string.h>
+#include <sys/stat.h>
+#include "fstab.h"
+#include "sundries.h" /* for xmalloc() etc */
+
#define streq(s, t) (strcmp ((s), (t)) == 0)
-/* These routines are superseded by mntent(3), but I use them for
- convenience. Mntent(3) is used in the implementation, so be
- very careful about the static buffers that are returned. */
+#define PROC_MOUNTS "/proc/mounts"
+
+/* Information about mtab. ------------------------------------*/
+static int have_mtab_info = 0;
+static int var_mtab_does_not_exist = 0;
+static int var_mtab_is_a_symlink = 0;
-static FILE *F_fstab = NULL;
+static void
+get_mtab_info(void) {
+ struct stat mtab_stat;
+
+ if (!have_mtab_info) {
+ if (lstat(MOUNTED, &mtab_stat))
+ var_mtab_does_not_exist = 1;
+ else if (S_ISLNK(mtab_stat.st_mode))
+ var_mtab_is_a_symlink = 1;
+ have_mtab_info = 1;
+ }
+}
-/* Open fstab or rewind if already open. */
int
-setfsent (void)
-{
- if (F_fstab)
- return (fseek (F_fstab, 0L, SEEK_SET) == 0);
+mtab_does_not_exist(void) {
+ get_mtab_info();
+ return var_mtab_does_not_exist;
+}
- F_fstab = setmntent (_PATH_FSTAB, "r");
- return (F_fstab != NULL);
+int
+mtab_is_a_symlink(void) {
+ get_mtab_info();
+ return var_mtab_is_a_symlink;
}
-/* Close fstab. */
-void
-endfsent (void)
-{
- endmntent (F_fstab);
+int
+mtab_is_writable() {
+ static int ret = -1;
+
+ /* Should we write to /etc/mtab upon an update?
+ Probably not if it is a symlink to /proc/mounts, since that
+ would create a file /proc/mounts in case the proc filesystem
+ is not mounted. */
+ if (mtab_is_a_symlink())
+ return 0;
+
+ if (ret == -1) {
+ int fd = open(MOUNTED, O_RDWR | O_CREAT, 0644);
+ if (fd >= 0) {
+ close(fd);
+ ret = 1;
+ } else
+ ret = 0;
+ }
+ return ret;
}
-/* Return next entry in fstab, skipping ignore entries. I also put
- in some ugly hacks here to skip comments and blank lines. */
-struct mntent *
-getfsent (void)
-{
- struct mntent *fstab;
-
- if (!F_fstab && !setfsent())
- return 0;
-
- for (;;)
- {
- fstab = getmntent (F_fstab);
- if (fstab == NULL)
- {
- if (!feof (F_fstab) && !ferror (F_fstab))
- continue;
- else
+/* Contents of mtab and fstab ---------------------------------*/
+
+struct mntentchn mounttable, fstab;
+static int got_mtab = 0;
+static int got_fstab = 0;
+
+static void read_mounttable(void), read_fstab(void);
+
+struct mntentchn *
+mtab_head() {
+ if (!got_mtab)
+ read_mounttable();
+ return &mounttable;
+}
+
+struct mntentchn *
+fstab_head() {
+ if (!got_fstab)
+ read_fstab();
+ return &fstab;
+}
+
+static void
+read_mntentchn(FILE *fp, const char *fnam, struct mntentchn *mc0) {
+ struct mntentchn *mc = mc0;
+ struct mntent *mnt;
+
+ while (!feof(fp) && !ferror(fp)) {
+ if ((mnt = getmntent (fp)) != NULL /* ignore blank lines */
+ && *mnt->mnt_fsname != '#' /* and comment lines */
+ && !streq (mnt->mnt_type, MNTTYPE_IGNORE)) {
+ mc->nxt = (struct mntentchn *) xmalloc(sizeof(*mc));
+ mc->nxt->prev = mc;
+ mc = mc->nxt;
+ mc->mnt_fsname = xstrdup(mnt->mnt_fsname);
+ mc->mnt_dir = xstrdup(mnt->mnt_dir);
+ mc->mnt_type = xstrdup(mnt->mnt_type);
+ mc->mnt_opts = xstrdup(mnt->mnt_opts);
+ mc->nxt = NULL;
+ }
+ }
+ mc0->prev = mc;
+ if (ferror (fp)) {
+ error("warning: error reading %s: %s", fnam, strerror (errno));
+ mc0->nxt = mc0->prev = NULL;
+ }
+ endmntent(fp);
+}
+
+/*
+ * Read /etc/mtab. If that fails, try /proc/mounts.
+ * This produces a linked list. The list head mounttable is a dummy.
+ * Return 0 on success.
+ */
+static void
+read_mounttable() {
+ FILE *fp = NULL;
+ const char *fnam;
+ struct mntentchn *mc = &mounttable;
+
+ got_mtab = 1;
+ mc->nxt = mc->prev = NULL;
+
+ fnam = MOUNTED;
+ if ((fp = setmntent (fnam, "r")) == NULL) {
+ int errsv = errno;
+ fnam = PROC_MOUNTS;
+ if ((fp = setmntent (fnam, "r")) == NULL) {
+ error("warning: can't open %s: %s", MOUNTED, strerror (errsv));
+ return;
+ }
+ if (verbose)
+ printf ("mount: could not open %s - using %s instead\n",
+ MOUNTED, PROC_MOUNTS);
+ }
+ read_mntentchn(fp, fnam, mc);
+}
+
+static void
+read_fstab() {
+ FILE *fp = NULL;
+ const char *fnam;
+ struct mntentchn *mc = &fstab;
+
+ got_fstab = 1;
+ mc->nxt = mc->prev = NULL;
+
+ fnam = _PATH_FSTAB;
+ if ((fp = setmntent (fnam, "r")) == NULL) {
+ error("warning: can't open %s: %s", _PATH_FSTAB, strerror (errno));
+ return;
+ }
+ read_mntentchn(fp, fnam, mc);
+}
+
+
+/* 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;
- }
- else if ((*fstab->mnt_fsname != '#')
- && !streq (fstab->mnt_type, MNTTYPE_IGNORE))
- break;
- }
- return fstab;
+
+ return mc;
}
-/* Find the dir FILE in fstab. */
-struct mntent *
-getfsfile (const char *file)
+/* Given the name FILE, try to find the option "loop=FILE" in mtab. */
+struct mntentchn *
+getmntoptfile (const char *file)
{
- struct mntent *fstab;
+ struct mntentchn *mc;
+ char *opts, *s;
+ int l;
- /* Open or rewind fstab. */
- if (!setfsent ())
- return 0;
+ if (!file)
+ return NULL;
- while ((fstab = getfsent ()))
- if (streq (fstab->mnt_dir, file))
- break;
+ l = strlen(file);
- return fstab;
+ 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;
+}
+
+/* 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;
+
+ return mc;
}
/* Find the device SPEC in fstab. */
-struct mntent *
+struct mntentchn *
getfsspec (const char *spec)
{
- struct mntent *fstab;
+ struct mntentchn *mc;
+
+ for (mc = fstab_head()->nxt; mc; mc = mc->nxt)
+ if (streq (mc->mnt_fsname, spec))
+ break;
+
+ return mc;
+}
+
+/* Updating mtab ----------------------------------------------*/
+
+/* File descriptor for lock. Value tested in unlock_mtab() to remove race. */
+static int lock = -1;
+
+/* Flag for already existing lock file. */
+static int old_lockfile = 1;
+
+/* Ensure that the lock is released if we are interrupted. */
+static void
+handler (int sig) {
+ die (EX_USER, "%s", sys_siglist[sig]);
+}
+
+static void
+setlkw_timeout (int sig) {
+ /* nothing, fcntl will fail anyway */
+}
+
+/* Create the lock file. The lock file will be removed if we catch a signal
+ or when we exit. The value of lock is tested to remove the race. */
+void
+lock_mtab (void) {
+ int sig = 0;
+ struct sigaction sa;
+ struct flock flock;
+
+ /* If this is the first time, ensure that the lock will be removed. */
+ if (lock < 0) {
+ struct stat st;
+ sa.sa_handler = handler;
+ sa.sa_flags = 0;
+ sigfillset (&sa.sa_mask);
+
+ while (sigismember (&sa.sa_mask, ++sig) != -1 && sig != SIGCHLD) {
+ if (sig == SIGALRM)
+ sa.sa_handler = setlkw_timeout;
+ else
+ sa.sa_handler = handler;
+ sigaction (sig, &sa, (struct sigaction *) 0);
+ }
+
+ /* This stat is performed so we know when not to be overly eager
+ when cleaning up after signals. The window between stat and
+ open is not significant. */
+ if (lstat (MOUNTED_LOCK, &st) < 0 && errno == ENOENT)
+ old_lockfile = 0;
+
+ lock = open (MOUNTED_LOCK, O_WRONLY|O_CREAT, 0);
+ if (lock < 0) {
+ die (EX_FILEIO, "can't create lock file %s: %s "
+ "(use -n flag to override)",
+ MOUNTED_LOCK, strerror (errno));
+ }
+
+ flock.l_type = F_WRLCK;
+ flock.l_whence = SEEK_SET;
+ flock.l_start = 0;
+ flock.l_len = 0;
+
+ alarm(LOCK_BUSY);
+ if (fcntl (lock, F_SETLKW, &flock) < 0) {
+ close (lock);
+ /* The file should not be removed */
+ lock = -1;
+ die (EX_FILEIO, "can't lock lock file %s: %s",
+ MOUNTED_LOCK,
+ errno == EINTR ? "timed out" : strerror (errno));
+ }
+ /* We have now access to the lock, and it can always be removed */
+ old_lockfile = 0;
+ }
+}
+
+/* Remove lock file. */
+void
+unlock_mtab (void) {
+ if (lock != -1) {
+ close (lock);
+ if (!old_lockfile)
+ unlink (MOUNTED_LOCK);
+ }
+}
+
+/*
+ * Update the mtab.
+ * Used by umount with null INSTEAD: remove any DIR entries.
+ * 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 /
+ * where there was no entry before, and we'll have to believe
+ * the values given in INSTEAD.]
+ */
+
+void
+update_mtab (const char *dir, struct mntent *instead) {
+ struct mntent *mnt;
+ struct mntent *next;
+ struct mntent remnt;
+ int added = 0;
+ FILE *fp, *ftmp;
+
+ if (mtab_does_not_exist() || mtab_is_a_symlink())
+ return;
+
+ lock_mtab();
+
+ if ((fp = setmntent(MOUNTED, "r")) == NULL) {
+ error ("cannot open %s (%s) - mtab not updated",
+ MOUNTED, strerror (errno));
+ goto leave;
+ }
+
+ if ((ftmp = setmntent (MOUNTED_TEMP, "w")) == NULL) {
+ error ("can't open %s (%s) - mtab not updated",
+ MOUNTED_TEMP, strerror (errno));
+ goto leave;
+ }
+
+ while ((mnt = getmntent (fp))) {
+ if (streq (mnt->mnt_dir, dir)) {
+ 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 && addmntent(ftmp, next) == 1)
+ die (EX_FILEIO, "error writing %s: %s",
+ MOUNTED_TEMP, strerror (errno));
+ }
+ if (instead && !added && addmntent(ftmp, instead) == 1)
+ die (EX_FILEIO, "error writing %s: %s",
+ MOUNTED_TEMP, strerror (errno));
- /* Open or rewind fstab. */
- if (!setfsent())
- return 0;
+ endmntent (fp);
+ if (fchmod (fileno (ftmp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0)
+ fprintf(stderr, "error changing mode of %s: %s", MOUNTED_TEMP,
+ strerror (errno));
+ endmntent (ftmp);
- while ((fstab = getfsent ()))
- if (streq (fstab->mnt_fsname, spec))
- break;
+ if (rename (MOUNTED_TEMP, MOUNTED) < 0)
+ fprintf(stderr, "can't rename %s to %s: %s", MOUNTED_TEMP, MOUNTED,
+ strerror(errno));
- return fstab;
+leave:
+ unlock_mtab();
}
diff --git a/mount/fstab.h b/mount/fstab.h
index 825822591..f22f2e7cb 100644
--- a/mount/fstab.h
+++ b/mount/fstab.h
@@ -1,26 +1,29 @@
-/* The fsent(3) routines are obsoleted by mntent(3). I use them for
- convenience. Since the implementation uses mntent(3), be very
- careful with the static buffers returned.
- $Header: /home/faith/cvs/util-linux/mount/fstab.h,v 1.2 1995/09/25 20:57:42 faith Exp $ */
+#define _PATH_FSTAB "/etc/fstab"
+#define MOUNTED_LOCK "/etc/mtab~"
+#define MOUNTED_TEMP "/etc/mtab.tmp"
+#define LOCK_BUSY 10
-#ifndef _FSTAB_H
-#include <stdio.h>
-#include <mntent.h>
+int mtab_is_writable(void);
+int mtab_does_not_exist(void);
+int mtab_is_a_symlink(void);
-#define _PATH_FSTAB "/etc/fstab"
+struct mntentchn {
+ struct mntentchn *nxt, *prev;
+ char *mnt_fsname;
+ char *mnt_dir;
+ char *mnt_type;
+ char *mnt_opts;
+};
-/* Translate fsent(3) stuff into mntent(3) stuff.
- In general this won't work, but it's good enough here. */
-#define fstab mntent
-#define fs_type mnt_type
-#define fs_spec mnt_fsname
-#define fs_mntopts mnt_opts
-#define FSTAB_SW MNTTYPE_SWAP
+struct mntentchn *mtab_head (void);
+struct mntentchn *getmntfile (const char *name);
+struct mntentchn *getmntoptfile (const char *file);
-struct fstab *getfsent (void);
-struct fstab *getfsspec (const char *spec);
-struct fstab *getfsfile (const char *file);
-int setfsent (void);
-void endfsent (void);
+struct mntentchn *fstab_head (void);
+struct mntentchn *getfsfile (const char *file);
+struct mntentchn *getfsspec (const char *spec);
-#endif /* _FSTAB_H */
+#include <mntent.h>
+void lock_mtab (void);
+void unlock_mtab (void);
+void update_mtab (const char *special, struct mntent *with);
diff --git a/mount/loop.h b/mount/h/loop.h
index 81ee7611e..a78dff721 100644
--- a/mount/loop.h
+++ b/mount/h/loop.h
@@ -1,6 +1,3 @@
-#ifndef _LINUX_LOOP_H
-#define _LINUX_LOOP_H
-
/*
* include/linux/loop.h
*
@@ -13,33 +10,6 @@
#define LO_NAME_SIZE 64
#define LO_KEY_SIZE 32
-struct loop_device {
- int lo_number;
- struct inode *lo_inode;
- int lo_refcnt;
- dev_t lo_device;
- int lo_offset;
- int lo_encrypt_type;
- int lo_encrypt_key_size;
- int lo_flags;
- int (*transfer)(struct loop_device *, int cmd,
- char *raw_buf, char *loop_buf, int size);
- char lo_name[LO_NAME_SIZE];
- char lo_encrypt_key[LO_KEY_SIZE];
-#ifdef DES_AVAILABLE
- des_key_schedule lo_des_key;
- unsigned long lo_des_init[2];
-#endif
-};
-
-typedef int (* transfer_proc_t)(struct loop_device *, int cmd,
- char *raw_buf, char *loop_buf, int size);
-
-/*
- * Loop flags
- */
-#define LO_FLAGS_DO_BMAP 0x00000001
-
struct loop_info {
int lo_number; /* ioctl r/o */
dev_t lo_device; /* ioctl r/o */
@@ -62,8 +32,8 @@ struct loop_info {
#define LO_CRYPT_NONE 0
#define LO_CRYPT_XOR 1
#define LO_CRYPT_DES 2
-#define LO_CRYPT_IDEA 4
-#define MAX_LO_CRYPT 3
+#define LO_CRYPT_IDEA 3
+#define MAX_LO_CRYPT 4
/*
* IOCTL commands --- we will commandeer 0x4C ('L')
@@ -73,5 +43,3 @@ struct loop_info {
#define LOOP_CLR_FD 0x4C01
#define LOOP_SET_STATUS 0x4C02
#define LOOP_GET_STATUS 0x4C03
-
-#endif
diff --git a/mount/h/swap.h b/mount/h/swap.h
new file mode 100644
index 000000000..db3fc404c
--- /dev/null
+++ b/mount/h/swap.h
@@ -0,0 +1,5 @@
+#define SWAP_FLAG_PREFER 0x8000 /* set if swap priority specified */
+#define SWAP_FLAG_PRIO_MASK 0x7fff
+#define SWAP_FLAG_PRIO_SHIFT 0
+
+#define MAX_SWAPFILES 8
diff --git a/mount/lomount.c b/mount/lomount.c
index 5dd02d8bb..a6ad187ae 100644
--- a/mount/lomount.c
+++ b/mount/lomount.c
@@ -1,4 +1,8 @@
/* Taken from Ted's losetup.c - Mitch <m.dsouza@mrc-apu.cam.ac.uk> */
+/* Added vfs mount options - aeb - 960223 */
+/* Removed lomount - aeb - 960224 */
+
+#define PROC_DEVICES "/proc/devices"
/*
* losetup.c - setup and control loop devices
@@ -8,71 +12,62 @@
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
+#include <errno.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
-#include <linux/fs.h>
-#include "loop.h"
+#include <sys/stat.h>
-char *crypt_name (int);
-int crypt_type (char *);
-void show_loop (char *);
-int del_loop (const char *);
-int set_loop (const char *, const char *, int offset, char *);
-int lomount (const char *, const char *, const char *, char **,
- int *, char **, char **);
+#if defined(__GLIBC__)
+#define _SOCKETBITS_H
+#endif /* __GLIBC */
+#include "sundries.h" /* for xstrdup */
+#include "loop.h"
+#include "lomount.h"
+#ifdef LOOP_SET_FD
struct crypt_type_struct {
int id;
char *name;
} crypt_type_tbl[] = {
-
- {
- LO_CRYPT_NONE, "no"
- },
- {
- LO_CRYPT_NONE, "none"
- },
- {
- LO_CRYPT_XOR, "xor"
- },
- {
- LO_CRYPT_DES, "DES"
- },
- {
- -1, NULL
- }
+ { LO_CRYPT_NONE, "no" },
+ { LO_CRYPT_NONE, "none" },
+ { LO_CRYPT_XOR, "xor" },
+ { LO_CRYPT_DES, "DES" },
+ { -1, NULL }
};
-char *
-crypt_name (int id)
+static int
+crypt_type (const char *name)
{
int i;
- for (i = 0; crypt_type_tbl[i].id != -1; i++)
- if (id == crypt_type_tbl[i].id)
- return crypt_type_tbl[i].name;
- return "undefined";
+ if (name)
+ for (i = 0; crypt_type_tbl[i].id != -1; i++)
+ if (!strcasecmp (name, crypt_type_tbl[i].name))
+ return crypt_type_tbl[i].id;
+ return -1;
}
-int
-crypt_type (char *name)
+#if 0
+static char *
+crypt_name (int id)
{
int i;
for (i = 0; crypt_type_tbl[i].id != -1; i++)
- if (!strcasecmp (name, crypt_type_tbl[i].name))
- return crypt_type_tbl[i].id;
- return -1;
+ if (id == crypt_type_tbl[i].id)
+ return crypt_type_tbl[i].name;
+ return "undefined";
}
-void
+static void
show_loop (char *device)
{
struct loop_info loopinfo;
int fd;
- if ((fd = open (device, O_RDWR)) < 0) {
+ if ((fd = open (device, O_RDONLY)) < 0) {
fprintf(stderr, "loop: can't open device %s: %s\n",
device, strerror (errno));
return;
@@ -89,24 +84,97 @@ show_loop (char *device)
crypt_name (loopinfo.lo_encrypt_type));
close (fd);
}
+#endif
+
+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;
+ struct stat statbuf;
+ struct loop_info loopinfo;
+ FILE *procdev;
+
+ for(i = 0; i < 256; i++) {
+ sprintf(dev, "/dev/loop%d", i);
+ if (stat (dev, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)) {
+ somedev++;
+ fd = open (dev, O_RDONLY);
+ if (fd >= 0) {
+ if(ioctl (fd, LOOP_GET_STATUS, &loopinfo) == 0)
+ someloop++; /* in use */
+ else if (errno == ENXIO) {
+ close (fd);
+ return xstrdup(dev); /* probably free */
+ }
+ close (fd);
+ }
+ continue; /* continue trying as long as devices exist */
+ }
+ if (i >= 7)
+ break;
+ }
+
+ /* Nothing found. Why not? */
+ if ((procdev = fopen(PROC_DEVICES, "r")) != NULL) {
+ char line[100];
+ while (fgets (line, sizeof(line), procdev))
+ if (strstr (line, " loop\n")) {
+ loop_known = 1;
+ break;
+ }
+ fclose(procdev);
+ if (!loop_known)
+ loop_known = -1;
+ }
+
+ if (!somedev)
+ error("mount: could not find any device /dev/loop#");
+ else if(!someloop) {
+ if (loop_known == 1)
+ error(
+"mount: Could not find any loop device.\n"
+" Maybe /dev/loop# has a wrong major number?\n");
+ else if (loop_known == -1)
+ error(
+"mount: Could not find any loop device, and, according to %s,\n"
+" this kernel does not know about the loop device.\n"
+" (If so, then recompile or `insmod loop.o'.)\n", PROC_DEVICES);
+ else
+ error(
+"mount: Could not find any loop device. Maybe this kernel does not know\n"
+" about the loop device (then recompile or `insmod loop.o'), or\n"
+" maybe /dev/loop# has the wrong major number?\n");
+ } else
+ error("mount: could not find any free loop device");
+ return 0;
+}
int
-set_loop (const char *device, const char *file, int offset, char *encryption)
+set_loop (const char *device, const char *file, int offset,
+ const char *encryption, int *loopro)
{
struct loop_info loopinfo;
- int fd,
- ffd,
- i;
+ int fd, ffd, mode, i;
char *pass;
- if ((fd = open (device, O_RDWR)) < 0) {
- perror (device);
- return 1;
+ mode = (*loopro ? O_RDONLY : O_RDWR);
+ if ((ffd = open (file, mode)) < 0) {
+ if (!*loopro && errno == EROFS)
+ ffd = open (file, mode = O_RDONLY);
+ if (ffd < 0) {
+ perror (file);
+ return 1;
+ }
}
- if ((ffd = open (file, O_RDWR)) < 0) {
- perror (file);
+ if ((fd = open (device, mode)) < 0) {
+ perror (device);
return 1;
}
+ *loopro = (mode == O_RDONLY);
memset (&loopinfo, 0, sizeof (loopinfo));
strncpy (loopinfo.lo_name, file, LO_NAME_SIZE);
loopinfo.lo_name[LO_NAME_SIZE - 1] = 0;
@@ -159,6 +227,8 @@ set_loop (const char *device, const char *file, int offset, char *encryption)
}
close (fd);
close (ffd);
+ if (verbose > 1)
+ printf("set_loop(%s,%s,%d): success\n", device, file, offset);
return 0;
}
@@ -173,51 +243,39 @@ del_loop (const char *device)
return 1;
}
if (ioctl (fd, LOOP_CLR_FD, 0) < 0) {
-#if 0
perror ("ioctl: LOOP_CLR_FD");
-#endif
return 1;
}
+ close (fd);
+ if (verbose > 1)
+ printf("del_loop(%s): success\n", device);
return 0;
}
+#else /* no LOOP_SET_FD defined */
+static void
+mutter(void) {
+ fprintf(stderr,
+ "This mount was compiled without loop support. Please recompile.\n");
+}
-int
-lomount (const char *spec, const char *node, const char *device, char **type,
- int *flags, char **extra_opts, char **mount_opts)
-{
- char *opt,
- *opteq;
- int val;
- char *encryption = NULL, *vfs = NULL;
- int offset = 0, err;
- char new_opts[1024];
-
- for (opt = strtok (*extra_opts, ","); opt; opt = strtok (NULL, ",")) {
- if ((opteq = strchr (opt, '='))) {
- val = atoi (opteq + 1);
- *opteq = '\0';
- if (!strcmp (opt, "encryption"))
- encryption = strdup(opteq + 1);
- else if (!strcmp (opt, "vfs"))
- vfs = strdup(opteq + 1);
- else if (!strcmp (opt, "offset"))
- offset = val;
- else {
- printf ("unknown loop mount parameter: "
- "%s=%d (%s)\n", opt, val, opteq+1);
- return 1;
- }
- } else {
- printf ("unknown loop mount parameter: "
- "%s\n", opt);
- return 1;
- }
- }
- err = set_loop (device, spec, offset, encryption);
- sprintf(new_opts, "vfs=%s,offset=%d,encryption=%s",
- *type = vfs ? vfs : FSTYPE_DEFAULT, offset,
- encryption=crypt_type(encryption)<0?"none":encryption);
- *extra_opts=strdup(new_opts);
- return err;
+int
+set_loop (const char *device, const char *file, int offset,
+ const char *encryption, int *loopro) {
+ mutter();
+ return 1;
+}
+
+int
+del_loop (const char *device) {
+ mutter();
+ return 1;
}
+
+char *
+find_unused_loop_device (void) {
+ mutter();
+ return 0;
+}
+
+#endif
diff --git a/mount/lomount.h b/mount/lomount.h
new file mode 100644
index 000000000..00a49f558
--- /dev/null
+++ b/mount/lomount.h
@@ -0,0 +1,4 @@
+extern int verbose;
+extern int set_loop (const char *, const char *, int, const char *, int *);
+extern int del_loop (const char *);
+extern char * find_unused_loop_device (void);
diff --git a/mount/losetup.8 b/mount/losetup.8
new file mode 100644
index 000000000..c2e41307d
--- /dev/null
+++ b/mount/losetup.8
@@ -0,0 +1,87 @@
+.TH LOSETUP 8 "Nov 24 1993" "Linux" "MAINTENANCE COMMANDS"
+.SH NAME
+losetup \- set up and control loop devices
+.SH SYNOPSIS
+.ad l
+.B losetup
+[
+.B \-e
+.I encryption
+] [
+.B \-o
+.I offset
+]
+.I loop_device file
+.br
+.B losetup
+[
+.B \-d
+]
+.I loop_device
+.ad b
+.SH DESCRIPTION
+.B losetup
+is used to associate loop devices with regular files or block devices,
+to detach loop devices and to query the status of a loop device. If only the
+\fIloop_device\fP argument is given, the status of the corresponding loop
+device is shown.
+.SH OPTIONS
+.IP \fB\-d\fP
+detach the file or device associated with the specified loop device.
+.IP "\fB\-e \fIencryption\fP"
+.RS
+enable data encryption. The following keywords are recognized:
+.IP \fBNONE\fP
+use no encryption (default).
+.PD 0
+.IP \fBXOR\fP
+use a simple XOR encryption.
+.IP \fBDES\fP
+use DES encryption. DES encryption is only available if the optional
+DES package has been added to the kernel. DES encryption uses an additional
+start value that is used to protect passwords against dictionary
+attacks.
+.PD
+.RE
+.IP "\fB\-o \fIoffset\fP"
+the data start is moved \fIoffset\fP bytes into the specified file or
+device.
+.SH FILES
+.nf
+/dev/loop0,/dev/loop1,... loop devices (major=7)
+.fi
+.SH EXAMPLE
+If you are using the loadable module you must have the module loaded
+first with the command
+.IP
+# insmod loop.o
+.LP
+The following commands can be used as an example of using the loop device.
+.nf
+.IP
+dd if=/dev/zero of=/file bs=1k count=100
+losetup -e des /dev/loop0 /file
+Password:
+Init (up to 16 hex digits):
+mkfs -t ext2 /dev/loop0 100
+mount -t ext2 /dev/loop0 /mnt
+ ...
+umount /dev/loop0
+losetup -d /dev/loop0
+.fi
+.LP
+If you are using the loadable module you may remove the module with
+the command
+.IP
+# rmmod loop
+.LP
+.fi
+.SH RESTRICTION
+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/losetup.c b/mount/losetup.c
new file mode 100644
index 000000000..ae5886ac4
--- /dev/null
+++ b/mount/losetup.c
@@ -0,0 +1,225 @@
+/*
+ * losetup.c - setup and control loop devices
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <getopt.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+
+#include "loop.h"
+#include "lomount.h"
+
+#ifdef LOOP_SET_FD
+
+static char *progname;
+
+struct crypt_type_struct {
+ int id;
+ char *name;
+} crypt_type_tbl[] = {
+ { LO_CRYPT_NONE,"no" },
+ { LO_CRYPT_NONE,"none" },
+ { LO_CRYPT_XOR, "xor" },
+ { LO_CRYPT_DES, "DES" },
+ { -1, NULL }
+};
+
+
+static char *crypt_name(int id)
+{
+ int i;
+
+ for (i = 0; crypt_type_tbl[i].id != -1; i++)
+ if (id == crypt_type_tbl[i].id)
+ return crypt_type_tbl[i].name;
+ return "undefined";
+}
+
+
+static int crypt_type(const char *name)
+{
+ int i;
+
+ for (i = 0; crypt_type_tbl[i].id != -1; i++)
+ if (!strcasecmp(name, crypt_type_tbl[i].name))
+ return crypt_type_tbl[i].id;
+ return -1;
+}
+
+
+static void show_loop(const char *device)
+{
+ struct loop_info loopinfo;
+ int fd;
+
+ if ((fd = open(device, O_RDWR)) < 0) {
+ perror(device);
+ return;
+ }
+ if (ioctl(fd, LOOP_GET_STATUS, &loopinfo) < 0) {
+ perror("Cannot get loop info");
+ close(fd);
+ return;
+ }
+ 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);
+}
+
+
+int set_loop(const char *device, const char *file, int offset,
+ const char *encryption, int *loopro)
+{
+ struct loop_info loopinfo;
+ int fd, ffd, mode, i;
+ char *pass;
+
+ mode = *loopro ? O_RDONLY : O_RDWR;
+ if ((ffd = open (file, mode)) < 0 && !*loopro
+ && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) {
+ perror (file);
+ return 1;
+ }
+ if ((fd = open (device, mode)) < 0) {
+ perror (device);
+ return 1;
+ }
+ *loopro = (mode == O_RDONLY);
+
+ memset(&loopinfo, 0, sizeof(loopinfo));
+ strncpy(loopinfo.lo_name, file, LO_NAME_SIZE);
+ loopinfo.lo_name[LO_NAME_SIZE-1] = 0;
+ if (encryption && (loopinfo.lo_encrypt_type = crypt_type(encryption))
+ < 0) {
+ fprintf(stderr,"Unsupported encryption type %s",encryption);
+ exit(1);
+ }
+ loopinfo.lo_offset = offset;
+ switch (loopinfo.lo_encrypt_type) {
+ case LO_CRYPT_NONE:
+ loopinfo.lo_encrypt_key_size = 0;
+ break;
+ case LO_CRYPT_XOR:
+ pass = getpass("Password: ");
+ strncpy(loopinfo.lo_encrypt_key, pass, LO_KEY_SIZE);
+ loopinfo.lo_encrypt_key[LO_KEY_SIZE-1] = 0;
+ loopinfo.lo_encrypt_key_size = strlen(loopinfo.lo_encrypt_key);
+ break;
+ case LO_CRYPT_DES:
+ pass = getpass("Password: ");
+ strncpy(loopinfo.lo_encrypt_key, pass, 8);
+ loopinfo.lo_encrypt_key[8] = 0;
+ loopinfo.lo_encrypt_key_size = 8;
+ pass = getpass("Init (up to 16 hex digits): ");
+ for (i = 0; i < 16 && pass[i]; i++)
+ if (isxdigit(pass[i]))
+ loopinfo.lo_init[i >> 3] |= (pass[i] > '9' ?
+ (islower(pass[i]) ? toupper(pass[i]) :
+ pass[i])-'A'+10 : pass[i]-'0') << (i & 7)*4;
+ else {
+ fprintf(stderr,"Non-hex digit '%c'.\n",pass[i]);
+ exit(1);
+ }
+ break;
+ default:
+ fprintf(stderr,
+ "Don't know how to get key for encryption system %d\n",
+ loopinfo.lo_encrypt_type);
+ exit(1);
+ }
+ if (ioctl(fd, LOOP_SET_FD, ffd) < 0) {
+ perror("ioctl: LOOP_SET_FD");
+ exit(1);
+ }
+ if (ioctl(fd, LOOP_SET_STATUS, &loopinfo) < 0) {
+ (void) ioctl(fd, LOOP_CLR_FD, 0);
+ perror("ioctl: LOOP_SET_STATUS");
+ exit(1);
+ }
+ close(fd);
+ close(ffd);
+ return 0;
+}
+
+int del_loop(const char *device)
+{
+ int fd;
+
+ if ((fd = open(device, O_RDONLY)) < 0) {
+ perror(device);
+ exit(1);
+ }
+ if (ioctl(fd, LOOP_CLR_FD, 0) < 0) {
+ perror("ioctl: LOOP_CLR_FD");
+ exit(1);
+ }
+ return(0);
+}
+
+
+static int 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);
+ exit(1);
+}
+
+int main(int argc, char **argv)
+{
+ char *offset,*encryption;
+ int delete,off,c;
+ int ro = 0;
+
+ delete = off = 0;
+ offset = encryption = NULL;
+ progname = argv[0];
+ while ((c = getopt(argc,argv,"de:o:")) != EOF) {
+ switch (c) {
+ case 'd':
+ delete = 1;
+ break;
+ case 'e':
+ encryption = optarg;
+ break;
+ case 'o':
+ offset = optarg;
+ break;
+ default:
+ usage();
+ }
+ }
+ if (argc == 1) usage();
+ if ((delete && (argc != optind+1 || encryption || offset)) ||
+ (!delete && (argc < optind+1 || argc > optind+2)))
+ usage();
+ if (argc == optind+1)
+ if (delete)
+ del_loop(argv[optind]);
+ else
+ show_loop(argv[optind]);
+ else {
+ if (offset && sscanf(offset,"%d",&off) != 1)
+ usage();
+ set_loop(argv[optind],argv[optind+1],off,encryption,&ro);
+ }
+ return 0;
+}
+
+#else /* LOOP_SET_FD not defined */
+
+int main(int argc, char **argv) {
+ fprintf(stderr,
+ "No loop support was available at compile time. Please recompile.\n");
+ return -1;
+}
+#endif
diff --git a/mount/mount.8 b/mount/mount.8
index 4c197f467..e1ed6f4a3 100644
--- a/mount/mount.8
+++ b/mount/mount.8
@@ -1,111 +1,237 @@
-.\" Copyright (c) 1980, 1989, 1991 The Regents of the University of California.
-.\" All rights reserved.
+.\" Copyright (c) 1996 Andries Brouwer
.\"
-.\" Redistribution and use in source and binary forms, with or without
-.\" modification, are permitted provided that the following conditions
-.\" are met:
-.\" 1. Redistributions of source code must retain the above copyright
-.\" notice, this list of conditions and the following disclaimer.
-.\" 2. Redistributions in binary form must reproduce the above copyright
-.\" notice, this list of conditions and the following disclaimer in the
-.\" documentation and/or other materials provided with the distribution.
-.\" 3. All advertising materials mentioning features or use of this software
-.\" must display the following acknowledgement:
-.\" This product includes software developed by the University of
-.\" California, Berkeley and its contributors.
-.\" 4. Neither the name of the University nor the names of its contributors
-.\" may be used to endorse or promote products derived from this software
-.\" without specific prior written permission.
+.\" This page is somewhat derived from a page that was
+.\" (c) 1980, 1989, 1991 The Regents of the University of California
+.\" and had been heavily modified by Rik Faith and myself.
+.\" (Probably no BSD text remains.)
+.\" Fragments of text were written by Werner Almesberger, Remy Card,
+.\" Stephen Tweedie and Eric Youngdale.
.\"
-.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
-.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
-.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
-.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
-.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
-.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
-.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
-.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
-.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
-.\" SUCH DAMAGE.
+.\" This is free documentation; you can redistribute it and/or
+.\" modify it under the terms of the GNU General Public License as
+.\" published by the Free Software Foundation; either version 2 of
+.\" the License, or (at your option) any later version.
.\"
-.\" @(#)mount.8 6.17 (Berkeley) 8/5/91
+.\" The GNU General Public License's references to "object code"
+.\" and "executables" are to be interpreted as the output of any
+.\" document formatting or typesetting system, including
+.\" intermediate and printed output.
.\"
-.\" When you change this file, please add an update notice to the ones below:
+.\" This manual is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
.\"
-.\" Sun Dec 27 12:10:38 1992: Updated by faith@cs.unc.edu
-.\" Thu Jan 14 21:15:06 1993: Updated by faith@cs.unc.edu
-.\" Mon Feb 1 21:18:21 1993: Updated by faith@cs.unc.edu
-.\" Sat Mar 6 20:46:29 1993: Updated by faith@cs.unc.edu
-.\" Sat Oct 9 08:56:26 1993: Updated by faith@cs.unc.edu
-.\" based on changes by Stephen Tweedie (sct@dcs.ed.ac.uk)
-.\" Sat Oct 9 08:59:46 1993: Converted to man format by faith@cs.unc.edu
-.\" Sat Nov 27 20:04:28 1993: File-system specific options documented by Rik
-.\" Faith (faith@cs.unc.edu), using extensive additions taken from
-.\" documentation written by Werner Almesberger
-.\" (almesber@nessie.cs.id.ethz.ch), and email written by Eric
-.\" Youngdale (eric@tantalus.nrl.navy.mil) and Remy Card
-.\" (Remy.Card@masi.ibp.fr).
-.\" Sun Apr 24 19:25:59 1994: Updated per information supplied by Remy Card.
-.\" Thu Jul 14 07:44:36 1994: Updated absence of -t option.
-.\" (faith@cs.unc.edu)
-.\" Thu Jul 14 07:49:14 1994: Updated list of valid filesystems.
-.\" Wed Feb 8 09:25:48 1995: Updated man pages for Mike Grupenhoff's changes.
-.\" Sat Jul 22 01:45:58 1995: Updated list of binary extensions for
-.\" msdos conversion. (sl14@cornell.edu)
-.\" Wed Jul 26 00:00:00 1995: Updated by Martin Schulze.
-.\" (joey@infodrom.north.de)
-.\" Tue Sep 26 12:02:03 1995: Updated umount, nfs, proc parts of page.
-.\" (aeb@cwi.nl)
+.\" You should have received a copy of the GNU General Public
+.\" License along with this manual; if not, write to the Free
+.\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+.\" USA.
.\"
-.TH MOUNT 8 "26 September 1995" "Linux 1.3" "Linux Programmer's Manual"
+.\" 960705, aeb: version for mount-2.5k
+.\" 970114, aeb: xiafs and ext are dead; romfs is new
+.\" 970623, aeb: -F option
+.\"
+.TH MOUNT 8 "5 July 1996" "Linux 2.0" "Linux Programmer's Manual"
.SH NAME
-mount, umount \- mount and dismount file systems
+mount \- mount a file system
.SH SYNOPSIS
-.BI "mount [\-afrwuvn] [\-t " vfstype ]
+.BI "mount [\-hV]"
+.LP
+.BI "mount \-a [\-fFnrvw] [\-t " vfstype ]
.br
-.BI "mount [\-frwuvn] [\-o " remount " [,...]] " "special " | " node"
+.BI "mount [\-fnrvw] [\-o " options " [,...]] " "device " | " dir"
.br
-.BI "mount [\-frwun] [\-t " vfstype "] [\-o " options "] " "special node"
+.BI "mount [\-fnrvw] [\-t " vfstype "] [\-o " options "] " "device dir"
+.SH DESCRIPTION
+All files accessible in a Unix system are arranged in one big
+tree, the file hierarchy, rooted at
+.BR / .
+These files can be spread out over several devices. The
+.B mount
+command serves to attach the file system found on some device
+to the big file tree. Conversely, the
+.BR umount (8)
+command will detach it again.
+
+The standard form of the
+.B mount
+command, is
+.RS
+.br
+.BI "mount \-t" " type device dir"
+.RE
+This tells the kernel to attach the file system found on
+.I device
+(which is of type
+.IR type )
+at the directory
+.IR dir .
+The previous contents (if any) and owner and mode of
+.I dir
+become invisible, and as long as this file system remains mounted,
+the pathname
+.I dir
+refers to the root of the file system on
+.IR device .
+
+Three forms of invocation do not actually mount anything:
+.RS
.br
-.BI "umount [\-ahvV] [\-t " vfstype ]
+.B "mount \-h"
+.RE
+prints a help message;
+.RS
.br
-.BI "umount [\-v] " "special " | " node " [...]
-.\" " for hilit19
-.SH DESCRIPTION
+.B "mount \-V"
+.RE
+prints a version string; and just
+.RS
+.BI "mount [-t" " type" ]
+.RE
+lists all mounted file systems (of type
+.IR type )
+- see below.
+
The
-.B mount
-command calls the
-.BR mount (2)
-system call to prepare and graft a
-.I special
-device on to the file system tree at the point
-.IR node .
-If either
-.IR special " or " node
-are not provided, the appropriate information is taken from the
-.BR fstab (5)
-file. The
.I proc
file system is not associated with a special device, and when
mounting it, an arbitrary keyword, such as
.I proc
-can be used instead of a path or
-.I node
-specification. (The customary choice
+can be used instead of a device specification.
+(The customary choice
.I none
-is less fortunate: the error message `none busy' from umount
+is less fortunate: the error message `none busy' from
+.B umount
can be confusing.)
-The system maintains a list of currently mounted file systems. If no
-arguments are given to
+Most devices are indicated by a file name (of a block special device), like
+.IR /dev/sda1 ,
+but there are other possibilities. For example, in the case of an NFS mount,
+.I device
+may look like
+.IR knuth.cwi.nl:/dir .
+
+The file
+.I /etc/fstab
+(see
+.BR fstab (5)),
+may contain lines describing what devices are usually
+mounted where, using which options. This file is used in three ways:
+.LP
+(i) The command
+.RS
+.br
+.BI "mount \-a [-t" " type" ]
+.RE
+(usually given in a bootscript) causes all file systems mentioned in
+.I fstab
+(of the proper type) to be mounted as indicated, except for those
+whose line contains the
+.B noauto
+keyword. Adding the
+.B \-F
+option will make mount fork, so that the
+filesystems are mounted simultaneously.
+.LP
+(ii) When mounting a file system mentioned in
+.IR fstab ,
+it suffices to give only the device, or only the mount point.
+.LP
+(iii) Normally, only the superuser can mount file systems.
+However, when
+.I fstab
+contains the
+.B user
+option on a line, then anybody can mount the corresponding system.
+.LP
+Thus, given a line
+.RS
+.br
+.B "/dev/cdrom /cd iso9660 ro,user,noauto,unhide"
+.RE
+any user can mount the iso9660 file system found on his CDROM
+using the command
+.RS
+.br
+.B "mount /dev/cdrom"
+.RE
+or
+.RS
+.br
+.B "mount /cd"
+.RE
+For more details, see
+.BR fstab (5).
+
+The programs
+.B mount
+and
+.B umount
+maintain a list of currently mounted file systems in the file
+.IR /etc/mtab .
+If no arguments are given to
.BR mount ,
this list is printed.
+When the
+.I proc
+filesystem is mounted (say at
+.IR /proc ),
+the files
+.I /etc/mtab
+and
+.I /proc/mounts
+have very similar contents. The former has somewhat
+more information, such as the mount options used,
+but is not necessarily up-to-date (cf. the
+.B \-n
+option below). It is possible to replace
+.I /etc/mtab
+by a symbolic link to
+.IR /proc/mounts ,
+but some information is lost that way, and in particular
+working with the loop device will be less convenient.
+
+.SH OPTIONS
+The full set of options used by an invocation of
+.B mount
+is determined by first extracting the
+options for the file system from the
+.I fstab
+table, then applying any options specified by the
+.B \-o
+argument, and finally applying a
+.BR \-r " or " \-w
+option, when present.
Options available for the
.B mount
command:
.TP
+.B \-V
+Output version.
+.TP
+.B \-h
+Print a help message.
+.TP
+.B \-v
+Verbose mode.
+.TP
+.B \-a
+Mount all filesystems (of the given types) mentioned in
+.IR fstab .
+.TP
+.B \-F
+(Used in conjunction with
+.BR \-a .)
+Fork off a new incarnation of mount for each device.
+This will do the mounts on different devices in parallel.
+This has the advantage that it is faster; also NFS timeouts go in
+parallel. A disadvantage is that the mounts are done in undefined order.
+Thus, you cannot use this option if you want to mount both
+.I /usr
+and
+.IR /usr/spool .
+.TP
.B \-f
Causes everything to be done except for the actual system call; if it's not
obvious, this ``fakes'' mounting the file system. This option is useful in
@@ -113,14 +239,94 @@ conjunction with the
.B \-v
flag to determine what the
.B mount
-command is trying to do.
+command is trying to do. It can also be used to add entries for devices
+that were mounted earlier with the -n option.
+.TP
+.B \-n
+Mount without writing in
+.IR /etc/mtab .
+This is necessary for example when
+.I /etc
+is on a read-only file system.
+.TP
+.B \-r
+Mount the file system read-only. A synonym is
+.BR "\-o ro" .
+.TP
+.B \-w
+Mount the file system read/write. This is the default. A synonym is
+.BR "\-o rw" .
+.TP
+.BI \-t " vfstype"
+The argument following the
+.B \-t
+is used to indicate the file system type. The file system types which are
+currently supported are listed in
+.IR linux/fs/filesystems.c :
+.IR minix ", " ext ", " ext2 ", " xiafs ", " hpfs ,
+.IR msdos ", " umsdos ", " vfat ,
+.IR proc ", " nfs ", " iso9660 ", " smbfs ", " ncpfs ,
+.IR affs ", " ufs ", " romfs ,
+.IR sysv ", " xenix ", " coherent .
+Note that the last three are equivalent and that
+.I xenix
+and
+.I coherent
+will be removed at some point in the future \(em use
+.I sysv
+instead. Since kernel version 2.1.21 the types
+.I ext
+and
+.I xiafs
+do not exist anymore.
+
+The type
+.I iso9660
+is the default. If no
+.B \-t
+option is given, or if the
+.B auto
+type is specified, the superblock is probed for the filesystem type
+.RI ( minix ", " ext ", " ext2 ", " xiafs ", " iso9660 ", " romfs
+are supported).
+If this probe fails and
+.I /proc/filesystems
+exists, then all of the filesystems listed there will be tried,
+except for those that are labeled "nodev" (e.g.,
+.I proc
+and
+.IR nfs ).
+
+Note that the
+.B auto
+type may be useful for user-mounted floppies.
+Warning: the probing uses a heuristic (the presence of appropriate `magic'),
+and could recognize the wrong filesystem type.
+
+More than one type may be specified in a comma separated
+list. The list of file system types can be prefixed with
+.B no
+to specify the file system types on which no action should be taken.
+(This can be meaningful with the
+.B \-a
+option.)
+
+For example, the command:
+.RS
+.RS
+.B "mount \-a \-t nomsdos,ext"
+.RE
+mounts all file systems except those of type
+.I msdos
+and
+.IR ext .
+.RE
.TP
.B \-o
Options are specified with a
.B \-o
flag followed by a comma separated string of options.
-.B N.B.,
-many of these options are only useful when they appear in the
+Some of these options are only useful when they appear in the
.I /etc/fstab
file. The following options apply to any file system that is being
mounted:
@@ -129,6 +335,9 @@ mounted:
.B async
All I/O to the file system should be done asynchronously.
.TP
+.B atime
+Update inode access time for each access. This is the default.
+.TP
.B auto
Can be mounted with the
.B \-a
@@ -144,6 +353,10 @@ Interpret character or block special devices on the file system.
.B exec
Permit execution of binaries.
.TP
+.B noatime
+Do not update inode access times on this file system (e.g, for faster
+access on the news spool to speed up news servers).
+.TP
.B noauto
Can only be mounted explicitly (i.e., the
.B \-a
@@ -151,12 +364,11 @@ option will not cause the file system to be mounted).
.TP
.B nodev
Do not interpret character or block special devices on the file
-system. This options is useful for a server that has file systems
-containing special devices for architectures other than its own.
+system.
.TP
.B noexec
Do not allow execution of any binaries on the mounted file system.
-This options is useful for a server that has file systems containing
+This option might be useful for a server that has file systems containing
binaries for architectures other than its own.
.TP
.B nosuid
@@ -165,6 +377,7 @@ effect.
.TP
.B nouser
Forbid an ordinary (i.e., non-root) user to mount the file system.
+This is the default.
.TP
.B remount
Attempt to remount an already-mounted file system. This is commonly
@@ -185,210 +398,294 @@ effect.
All I/O to the file system should be done synchronously.
.TP
.B user
-Allow an ordinary user to mount the file system. Ordinary users always
-have the following options activated:
+Allow an ordinary user to mount the file system. This option implies
+the options
.BR noexec ", " nosuid ", and " nodev
-(unless overridden by the superuser by using, for example, the following
-option line:
-.BR user,exec,dev,suid .
-.PP
-The following options apply only to certain file systems:
+(unless overridden by subsequent options, as in the option line
+.BR user,exec,dev,suid ).
+.RE
+
+.SH "FILESYSTEM SPECIFIC MOUNT OPTIONS"
+The following options apply only to certain file systems.
+We sort them by file system. They all follow the
+.B \-o
+flag.
+
+.SH "Mount options for affs"
.TP
-.BI case= value
-For the
-.I hpfs
-file system, specify case as
-.I lower
+\fBuid=\fP\fIvalue\fP and \fBgid=\fP\fIvalue\fP
+Set the owner and group of the root of the file system (default: uid=gid=0,
+but with option
+.B uid
or
-.IR asis .
-.TP
-.BI check= value
-Tells the
-.I ext2
-file sysem kernel code to do some more checks while the file system is
-mounted. Currently (1.3.11), the following values can be specified with
-this option:
-.RS
+.B gid
+without specified value, the uid and gid of the current process are taken).
.TP
-.I none
-no extra check is performed by the kernel code
+\fBsetuid=\fP\fIvalue\fP and \fBsetgid=\fP\fIvalue\fP
+Set the owner and group of all files.
+.TP
+.BI mode= value
+Set the mode of all files to
+.IR value " & 0777"
+disregarding the original permissions.
+Add search permission to directories that have read permission.
+The value is given in octal.
+.TP
+.B protect
+Do not allow any changes to the protection bits on the file system.
+.TP
+.B usemp
+Set uid and gid of the root of the file system to the uid and gid
+of the mount point upon the first sync or umount, and then
+clear this option. Strange...
+.TP
+.B verbose
+Print an informational message for each successful mount.
+.TP
+.BI prefix= string
+Prefix used before volume name, when following a link.
+.TP
+.BI volume= string
+Prefix (of length at most 30) used before '/' when following a symbolic link.
+.TP
+.BI reserved= value
+(Default: 2.) Number of unused blocks at the start of the device.
+.TP
+.BI root= value
+Give explicitly the location of the root block.
.TP
-.I normal
-The inodes and blocks bitmaps are checked when the file system is mounted
-(this is the default)
+.BI bs= value
+Give blocksize. Allowed values are 512, 1024, 2048, 4096.
.TP
-.I strict
-In addition to the
-.I normal
-checks, block deallocation checks that the block to free is in the data
-zone.
+.BR grpquota " / " noquota " / " quota " / " usrquota
+These options are accepted but ignored.
+
+.SH "Mount options for coherent"
+None.
+
+.SH "Mount options for ext"
+None.
+Note that the `ext' file system is obsolete. Don't use it.
+Since Linux version 2.1.21 extfs is no longer part of the kernel source.
+
+.SH "Mount options for ext2"
+The `ext2' file system is the standard Linux file system.
+Due to a kernel bug, it may be mounted with random mount options
+(fixed in Linux 2.0.4).
+.TP
+.BR bsddf " / " minixdf
+Set the behaviour for the
+.I statfs
+system call. The
+.B minixdf
+behaviour is to return in the
+.I f_blocks
+field the total number of blocks of the file system, while the
+.B bsddf
+behaviour (which is the default) is to subtract the overhead blocks
+used by the ext2 file system and not available for file storage. Thus
.RE
+.nf
+
+% mount /k -o minixdf; df /k; umount /k
+Filesystem 1024-blocks Used Available Capacity Mounted on
+/dev/sda6 2630655 86954 2412169 3% /k
+% mount /k -o bsddf; df /k; umount /k
+Filesystem 1024-blocks Used Available Capacity Mounted on
+/dev/sda6 2543714 13 2412169 0% /k
+
+.fi
+(Note that this example shows that one can add command line options
+to the options given in
+.IR /etc/fstab .)
+
.TP
-.BI check= value
-For the
-.I msdos
-file system, three different levels of pickyness can be chosen:
+.BR check " / " check=normal " / " check=strict
+Set checking level. When at least one of these options is set (and
+.B check=normal
+is set by default) the inodes and blocks bitmaps are checked upon mount
+(which can take half a minute or so on a big disk).
+With strict checking, block deallocation checks that the block to free
+is in the data zone.
+.TP
+.BR check=none " / " nocheck
+No checking is done.
+.TP
+.B debug
+Print debugging info upon each (re)mount.
+.TP
+.BR errors=continue " / " errors=remount-ro " / " errors=panic
+Define the behaviour when an error is encountered.
+(Either ignore errors and just mark the file system erroneous and continue,
+or remount the file system read-only, or panic and halt the system.)
+The default is set in the filesystem superblock, and can be
+changed using
+.BR tune2fs (8).
+.TP
+.BR grpid " or " bsdgroups " / " nogrpid " or " sysvgroups
+These options define what group id a newly created file gets.
+When
+.BR grpid
+is set, it takes the group id of the directory in which it is created;
+otherwise (the default) it takes the fsgid of the current process, unless
+the directory has the setgid bit set, in which case it takes the gid
+from the parent directory, and also gets the setgid bit set
+if it is a directory itself.
+.TP
+\fBresgid=\fP\fIn\fP and \fBresuid=\fP\fIn\fP
+The ext2 file system reserves a certain percentage of the available
+space (by default 5%, see
+.BR mke2fs (8)
+and
+.BR tune2fs (8)).
+These options determine who can use the reserved blocks.
+(Roughly: whoever has the specified uid, or belongs to the specified group.)
+.TP
+.BI sb= n
+Instead of block 1, use block
+.I n
+as superblock. This could be useful when the filesystem has been damaged.
+Usually, copies of the superblock are found every 8192 blocks: in
+block 1, 8193, 16385, ...
+(Thus, one gets hundreds or even thousands of copies of the superblock
+on a big filesystem. I do not know of options to mke2fs that would
+cause fewer copies to be written.)
+.TP
+.BR grpquota " / " noquota " / " quota " / " usrquota
+These options are accepted but ignored.
+
+.SH "Mount options for fat"
+(Note:
+.I fat
+is not a separate filesystem, but a common part of the
+.IR msdos ,
+.I umsdos
+and
+.I vfat
+filesystems.)
+.TP
+.BR blocksize=512 " / " blocksize=1024
+Set blocksize (default 512).
+.TP
+\fBuid=\fP\fIvalue\fP and \fBgid=\fP\fIvalue\fP
+Set the owner and group of all files. (Default: the uid and gid
+of the current process.)
+.TP
+.BI umask= value
+Set the umask (the bitmask of the permissions that are
+.B not
+present). The default is the umask of the current process.
+The value is given in octal.
+.TP
+.BI check= value
+Three different levels of pickyness can be chosen:
.RS
.TP
-.I relaxed
+.B r[elaxed]
Upper and lower case are accepted and equivalent, long name parts are
-truncated (e.g. verlongname.foobar becomes verylong.foo), leading and
-embedded spaces are accepted in each name part (name and extension).
+truncated (e.g.
+.I verylongname.foobar
+becomes
+.IR verylong.foo ),
+leading and embedded spaces are accepted in each name part (name and extension).
.TP
-.I normal
+.B n[ormal]
Like "relaxed", but many special characters (*, ?, <, spaces, etc.) are
rejected. This is the default.
.TP
-.I strict
+.B s[trict]
Like "normal", but names may not contain long parts and special characters
that are sometimes used on Linux, but are not accepted by MS-DOS are
rejected. (+, =, spaces, etc.)
.RE
.TP
-.BI conv= value
-For the
-.IR msdos ,
-.IR hpfs ,
-and
-.I iso9660
-file systems, specify file conversion as
-.IR binary ", " text ", or " auto .
+.BR conv=b[inary] " / " conv=t[ext] " / " conv=a[uto]
The
-.I iso9660
-file system also allows
-.I value
-to be
-.IR mtext .
-
-The
-.I msdos
+.I fat
file system can perform CRLF<-->NL (MS-DOS text format to UNIX text
format) conversion in the kernel. The following conversion modes are
available:
.RS
.TP
-.I binary
+.B binary
no translation is performed. This is the default.
.TP
-.I text
+.B text
CRLF<-->NL translation is performed on all files.
.TP
-.I auto
+.B auto
CRLF<-->NL translation is performed on all files that don't have a
"well-known binary" extension. The list of known extensions can be found at
the beginning of
-.I fs/msdos/misc.c
-(as of 1.3.11, the list is: exe, com, bin, app, sys, drv, ovl, ovr, obj,
+.I fs/fat/misc.c
+(as of 2.0, the list is: exe, com, bin, app, sys, drv, ovl, ovr, obj,
lib, dll, pif, arc, zip, lha, lzh, zoo, tar, z, arj, tz, taz, tzp, tpz,
gz, tgz, deb, gif, bmp, tif, gl, jpg, pcx, tfm, vf, gf, pk, pxl, dvi).
.PP
Programs that do computed lseeks won't like in-kernel text conversion.
Several people have had their data ruined by this translation. Beware!
-For file systems mounted in
-.B binary
-mode, a conversion tool (fromdos/todos) is available.
+For file systems mounted in binary mode, a conversion tool
+(fromdos/todos) is available.
.RE
.TP
-.BI block= value
-For the
-.I iso9660
-file system, set the blocksize.
-.TP
-.B bsdgroups
-See
-.B grpid
-.TP
-.B cruft
-For the
-.I iso9660
-file system, set the
-.I cruft
-flag to 'y'. This option is available because there are buggy premastering
-programs out there that leave junk in the top byte of the file size. This
-option clears the top byte, but restricts files to 16Mb maximum in the
-process.
-.TP
.B debug
-For the
-.I msdos
-file system, turn on the
+Turn on the
.I debug
flag. A version string and a list of file system parameters will be
printed (these data are also printed if the parameters appear to be
inconsistent).
.TP
-.B debug
-For the
-.I ext2fs
-file system, causes the kernel code to display the file system parameters
-when the file system is mounted.
-.TP
-.BI errors= value
-For the
-.I ext2fs
-file system, specifies the error behavior:
-.RS
-.TP
-.B continue
-No special action is taken on errors (except marking the file system as
-erroneous). This is the default.
-.TP
-.B remount
+.BR fat=12 " / " fat=16
+Specify either a 12 bit fat or a 16 bit fat. This overrides
+the automatic FAT type detection routine. Use with caution!
.TP
-.B ro
-The file system is remounted read only, and subsequent writes are refused.
+.B quiet
+Turn on the
+.I quiet
+flag. Attempts to chown or chmod files do not return errors,
+although they fail. Use with caution!
.TP
-.B panic
-When an error is detected, the system panics.
-.RE
+.B "sys_immutable, showexec, dots, nodots, dotsOK=[yes|no]"
+Various misguided attempts to force Unix or DOS conventions
+onto a FAT file system.
+
+.SH "Mount options for hpfs"
.TP
-.BI fat= value
-For the
-.I msdos
-file system, specify either a 12 bit fat or a 16 bit fat. This overrides
-the automatic FAT type detection routine. Use with caution!
+\fBuid=\fP\fIvalue\fP and \fBgid=\fP\fIvalue\fP
+Set the owner and group of all files. (Default: the uid and gid
+of the current process.)
.TP
-.BI gid= value
-For the
-.I msdos
-and
-.I hpfs
-file systems, give every file a gid equal to
-.IR value .
-.TP
-.B grpid
-Causes the
-.I ext2fs
-to use the BSD behavior when creating files: file are created with the
-group id of their parent directory.
-.TP
-.BI map= value
-For the
-.I iso9660
-file system, specify mapping as
-.IR off " or " normal .
-In general, non-Rock Ridge discs have all of the filenames in upper case,
-and all of the filenames have a ";1" appended. The map option strips the
-";1" and makes the name lower case. C.f.
-.BR norock .
+.BI umask= value
+Set the umask (the bitmask of the permissions that are
+.B not
+present). The default is the umask of the current process.
+The value is given in octal.
+.TP
+.BR case=lower " / " case=asis
+Convert all files names to lower case, or leave them.
+(Default:
+.BR case=lower .)
+.TP
+.BR conv=binary " / " conv=text " / " conv=auto
+For
+.BR conv=text ,
+delete some random CRs (in particular, all followed by NL)
+when reading a file.
+For
+.BR conv=auto ,
+choose more or less at random between
+.BR conv=binary " and " conv=text .
+For
+.BR conv=binary ,
+just read what is in the file. This is the default.
.TP
.B nocheck
-For the
-.IR ext2fs ,
-turns of checking (see
-.BR check=none ).
-.TP
-.B nogrpid
-Causes the
-.I ext2fs
-to use the System V behaviour when creating files: files are created with
-the group id of the creating process, unless the setgid bit is set on the
-parent directory. This is the default for all Linux file systems.
-.TP
-.B norock
+Do not abort mounting when certain consistency checks fail.
+
+.SH "Mount options for iso9660"
Normal
-.I iso9600
+.I iso9660
filenames appear in a 8.3 format (i.e., DOS-like restrictions on filename
length), and in addition all characters are in upper case. Also there is
no field for file ownership, protection, number of links, provision for
@@ -399,186 +696,281 @@ features. Basically there are extensions to each directory record that
supply all of the additional information, and when Rock Ridge is in use,
the filesystem is indistinguishable from a normal UNIX file system (except
that it is read-only, of course).
-
-The
+.TP
.B norock
-switch disables the use of Rock Ridge extensions, even if available. C.f.
+Disable the use of Rock Ridge extensions, even if available. Cf.\&
.BR map .
.TP
-.B quiet
-For the
-.I msdos
-file system, turn on the
-.I quiet
-flag. Attempts to chown or chmod files do not yield errors, although they
-fail. Use with caution!
-.TP
-.B soft
-For the
-.IR nfs
-file system this allows the kernel to time out if the nfs server is not
-responding for some time, otherwise it will try forever. The time can be
-specified with
-.BR timeo=time .
-For more information look at
-.IR nfs (5).
-
-This option is useful if your nfs server sometimes doesn't respond or will
-be rebooted while some process tries to get a file from the server.
-.TP
-.BI sb= value
-For the
-.I ext2
-file system, use an alternate superblock located at block
-.IR value .
-.I value
-is numbered in 1024 bytes blocks. An
-.I ext2
-file system usually has backups of the super block at blocks 1, 8193, 16385
-and so on.
-.TP
-.BI sysvgroups
-See
-.B nogrpid
-.TP
-.BI uid= value
-For the
-.I msdos
+.BR check=r[elaxed] " / " check=s[trict]
+With
+.BR check=relaxed ,
+a filename is first converted to lower case before doing the lookup.
+This is probably only meaningful together with
+.B norock
and
-.I hpfs
-file systems, give every file a uid equal to
-.IR value .
+.BR map=normal .
+(Default:
+.BR check=strict .)
+.TP
+\fBuid=\fP\fIvalue\fP and \fBgid=\fP\fIvalue\fP
+Give all files in the file system the indicated user or group id,
+possibly overriding the information found in the Rock Ridge extensions.
+(Default:
+.BR uid=0,gid=0 .)
+.TP
+.BR map=n[ormal] " / " map=o[ff]
+For non-Rock Ridge volumes, normal name translation maps upper
+to lower case ASCII, drops a trailing `;1', and converts `;' to `.'.
+With
+.B map=off
+no name translation is done. See
+.BR norock .
+(Default:
+.BR map=normal .)
+.TP
+.BI mode= value
+For non-Rock Ridge volumes, give all files the indicated mode.
+(Default: read permission for everybody.)
+Since Linux 2.1.37 one no longer needs to specify the mode in
+decimal. (Octal is indicated by a leading 0.)
+.TP
+.B unhide
+Also show hidden and associated files.
+.TP
+.B block=[512|1024|2048]
+Set the block size to the indicated value.
+(Default:
+.BR block=1024 .)
+.TP
+.BR conv=a[uto] " / " conv=b[inary] " / " conv=m[text] " / " conv=t[ext]
+(Default:
+.BR conv=binary .)
+Since Linux 1.3.54 this option has no effect anymore.
+(And non-binary settings used to be very dangerous,
+often leading to silent data corruption.)
.TP
-.BI umask= value
-For the
-.I msdos
-and
-.I hpfs
-file systems, give every file a umask of
-.IR value .
-The radix defaults to octal.
-.PP
-The full set of options applied is determined by first extracting the
-options for the file system from the
-.B fstab
-table, then applying any options specified by the
-.B \-o
-argument, and finally applying the
-.BR \-r " or " \-w
-option.
+.B cruft
+If the high byte of the file length contains other garbage,
+set this mount option to ignore the high order bits of the file length.
+This implies that a file cannot be larger than 16MB.
+The `cruft' option is set automatically if the entire CDROM
+has a weird size (negative, or more than 800MB). It is also
+set when volume sequence numbers other than 0 or 1 are seen.
+
+.SH "Mount options for minix"
+None.
+.SH "Mount options for msdos"
+See mount options for fat.
If the
.I msdos
file system detects an inconsistency, it reports an error and sets the file
system read-only. The file system can be made writeable again by remounting
it.
-.RE
-.TP
-.B \-r
-The file system object is to be mounted read-only.
-.TP
-.BI \-t " vfstype"
-The argument following the
-.B \-t
-is used to indicate the file system type. The file system types which are
-currently supported are listed in
-.IR linux/fs/filesystems.c :
-.IR minix ", " ext ", " ext2 ", " xiafs ", " msdos ", " umsdos ,
-.IR hpfs ", " proc ", " nfs ", " iso9660 ", " smbfs ,
-.IR sysv ", " xenix ", " coherent .
-Note that that last three are equivalent and that "xenix" and "coherent"
-will be removed at some point in the future \(em use "sysv" instead.
-The type
-.I minix
-is the default. If no
-.B \-t
-option is given, or if the "auto" type is specified, the superblock is
-probed for the filesystem type (minix, ext, ext2, xia are supported). If
-this probe fails and
-.I /proc/filesystems
-exists, then all of the filesystems listed will be tried,
-.I except
-for those that are labeled "nodev" (e.g., "proc" and "nfs").
-
-Note that the "auto" type may be useful for user-mounted floppies.
-
-For example, the
+.SH "Mount options for ncp"
+Just like
+.IR nfs ", the " ncp
+implementation expects a binary argument (a
+.IR "struct ncp_mount_data" )
+to the mount system call. This argument is constructed by
+.BR ncpmount (8)
+and the current version of
.B mount
-command:
-.RS
+(2.6h) does not know anything about ncp.
-.RS
-mount -a -t nomsdos,ext
-.RE
+.SH "Mount options for nfs"
+Instead of a textual option string, parsed by the kernel, the
+.I nfs
+file system expects a binary argument of type
+.IR "struct nfs_mount_data" .
+The program
+.B mount
+itself parses the following options of the form `tag=value',
+and puts them in the structure mentioned:
+.BI rsize= n,
+.BI wsize= n,
+.BI timeo= n,
+.BI retrans= n,
+.BI acregmin= n,
+.BI acregmax= n,
+.BI acdirmin= n,
+.BI acdirmax= n,
+.BI actimeo= n,
+.BI retry= n,
+.BI port= n,
+.BI mountport= n,
+.BI mounthost= name,
+.BI mountprog= n,
+.BI mountvers= n,
+.BI nfsprog= n,
+.BI nfsvers= n,
+.BI namlen= n.
+The option
+.BI addr= n
+is accepted but ignored.
+Also the following Boolean options, possibly preceded by
+.B no
+are recognized:
+.BR bg ,
+.BR fg ,
+.BR soft ,
+.BR hard ,
+.BR intr ,
+.BR posix ,
+.BR cto ,
+.BR ac ,
+.BR tcp ,
+.BR udp ,
+.BR lock .
+For details, see
+.BR nfs (5).
-mounts all file systems except those of type
-.I msdos
-and
-.IR ext .
-.RE
+Especially useful options include
.TP
-.B \-v
-Verbose mode.
+.B rsize=8192,wsize=8192
+This will make your nfs connection much faster than with the default
+buffer size of 1024.
.TP
-.B \-w
-The file system object is to be read and write.
+.B hard
+The program accessing a file on a NFS mounted file system will hang
+when the server crashes. The process cannot be interrupted or
+killed unless you also specify
+.BR intr .
+When the NFS server is back online the program will continue undisturbed
+from where it was. This is probably what you want.
.TP
-.B \-n
-Mount without writing in
-.IR /etc/mtab .
-.PP
-.B Umount
-removes the
-.I special
-device, or the device grafted at point
-.IR node ,
-from the file system tree.
-
-Options for the
-.B umount
-command:
+.B soft
+This option allows the kernel to time out if the nfs server is not
+responding for some time. The time can be
+specified with
+.BR timeo=time .
+This option might be useful if your nfs server sometimes doesn't respond
+or will be rebooted while some process tries to get a file from the server.
+Usually it just causes lots of trouble.
.TP
-.B \-a
-All of the file systems described in
-.I /etc/mtab
-are unmounted.
+.B nolock
+Do not use locking. Do not start lockd.
+
+.SH "Mount options for proc"
.TP
-.BI \-t " vfstype"
-Is used to indicate the actions should only be taken on file systems of the
-specified type. More than one type may be specified in a comma separated
-list. The list of file system types can be prefixed with ``no'' to specify
-the file system types on which no action should be taken. (See example
-above for the
+\fBuid=\fP\fIvalue\fP and \fBgid=\fP\fIvalue\fP
+These options are recognized, but have no effect as far as I can see.
+
+.SH "Mount options for romfs"
+None.
+
+.SH "Mount options for smbfs"
+Just like
+.IR nfs ", the " smb
+implementation expects a binary argument (a
+.IR "struct smb_mount_data" )
+to the mount system call. This argument is constructed by
+.BR smbmount (8)
+and the current version of
.B mount
-command.)
-.TP
-.B \-V
-Print version and exit.
-.TP
-.B \-h
-Print help message and exit.
-.TP
-.B \-v
-Verbose mode.
+(2.6c) does not know anything about smb.
+
+.SH "Mount options for sysv"
+None.
+
+.SH "Mount options for ufs"
+None.
+
+.SH "Mount options for umsdos"
+See mount options for msdos.
+The
+.B dotsOK
+option is explicitly killed by
+.IR umsdos .
+
+.SH "Mount options for vfat"
+First of all, the mount options for
+.I fat
+are recognized.
+The
+.B dotsOK
+option is explicitly killed by
+.IR vfat .
+Furthermore, there are
+.TP
+.B uni_xlate
+Translate unhandled Unicode characters to special escaped sequences.
+This lets you backup and restore filenames that are created with any
+Unicode characters. Without this option, a '?' is used when no
+translation is possible. The escape character is ':' because it is
+otherwise illegal on the vfat filesystem. The escape sequence
+that gets used, where u is the unicode character,
+is: ':', (u & 0x3f), ((u>>6) & 0x3f), (u>>12).
+.TP
+.B posix
+Allow two files with names that only differ in case.
+.TP
+.B nonumtail
+First try to make a short name without sequence number,
+before trying
+.IR name~num.ext .
+
+.SH "Mount options for xenix"
+None.
+
+.SH "Mount options for xiafs"
+None. Although nothing is wrong with xiafs, it is not used much,
+and is not maintained. Probably one shouldn't use it.
+Since Linux version 2.1.21 xiafs is no longer part of the kernel source.
+
+.SH "THE LOOP DEVICE"
+One further possible type is a mount via the loop device. For example,
+the command
+
+.nf
+.B " mount /tmp/fdimage /mnt -t msdos -o loop=/dev/loop3,blocksize=1024"
+.fi
+
+will set up the loop device
+.I /dev/loop3
+to correspond to the file
+.IR /tmp/fdimage ,
+and then mount this device on
+.IR /mnt .
+This type of mount knows about three options, namely
+.BR loop ", " offset " and " encryption ,
+that are really options to
+.BR losetup (8).
+If no explicit loop device is mentioned
+(but just an option `\fB\-o loop\fP' is given), then
+.B mount
+will try to find some unused loop device and use that.
.SH FILES
.I /etc/fstab
file system table
.br
+.I /etc/mtab
+table of mounted file systems
+.br
.I /etc/mtab~
lock file
.br
.I /etc/mtab.tmp
temporary file
.SH "SEE ALSO"
-.BR mount "(2), " umount "(2), " fstab "(5), " swapon "(8), " nfs (5),
-.BR mountd "(8), " nfsd (8)
+.BR mount (2),
+.BR umount (2),
+.BR fstab (5),
+.BR umount (8),
+.BR swapon (8),
+.BR nfs (5),
+.BR mountd (8),
+.BR nfsd (8),
+.BR mke2fs (8),
+.BR tune2fs (8),
+.BR losetup (8)
.SH BUGS
It is possible for a corrupted file system to cause a crash.
.PP
Some Linux file systems don't support
-.BI \-o " synchronous"
+.B "\-o sync"
(the ext2fs
.I does
support synchronous updates (a la BSD) when mounted with the
@@ -586,9 +978,9 @@ support synchronous updates (a la BSD) when mounted with the
option).
.PP
The
-.BI \-o " remount"
+.B "\-o remount"
may not be able to change mount parameters (all
-.I ext2fs
+.IR ext2fs -specific
parameters, except
.BR sb ,
are changeable with a remount, for example, but you can't change
@@ -596,32 +988,8 @@ are changeable with a remount, for example, but you can't change
or
.B umask
for the
-.IR dosfs ).
+.IR fatfs ).
.SH HISTORY
A
.B mount
command appeared in Version 6 AT&T UNIX.
-.SH "AUTHORS AND CONTRIBUTORS"
-.na
-The Linux
-.B mount
-command has a long and continuing history. Major releases are noted below,
-with the name of the primary modifier noted:
-.sp
-0.97.3: Doug Quale (quale@saavik.cs.wisc.edu).
-.br
-0.98.5: H. J. Lu (hlu@eecs.wsu.edu).
-.br
-0.99.2: Rick Sladkey (jrs@world.std.com).
-.br
-0.99.6: Rick Sladkey (jrs@world.std.com).
-.br
-0.99.10: Stephen Tweedie (sct@dcs.ed.ac.uk).
-.br
-0.99.14: Rick Sladkey (jrs@world.std.com).
-.sp
-(File-system specific information added to man page on 27 November 1993 by
-Rik Faith with lots of information
-.I and text
-from the following file system authors: Werner Almesberger, Eric Youngdale,
-and Remy Card.)
diff --git a/mount/mount.c b/mount/mount.c
index 028848ac5..98093956c 100644
--- a/mount/mount.c
+++ b/mount/mount.c
@@ -22,42 +22,67 @@
* Wed Feb 8 12:27:00 1995: Andries.Brouwer@cwi.nl fixed up error messages.
* Sat Jun 3 20:44:38 1995: Patches from Andries.Brouwer@cwi.nl applied.
* Tue Sep 26 22:38:20 1995: aeb@cwi.nl, many changes
+ * Fri Feb 23 13:47:00 1996: aeb@cwi.nl, loop device related changes
*
+ * Fri Apr 5 01:13:33 1996: quinlan@bucknell.edu, fixed up iso9660 autodetect
+ *
+ * Since then, many changes - aeb.
*/
-#include "sundries.h"
+#include <unistd.h>
+#include <ctype.h>
+#include <errno.h>
+#include <string.h>
+#include <getopt.h>
+#include <sys/types.h>
+#include <sys/ioctl.h>
+#include <sys/stat.h>
+#include <sys/wait.h>
+#include <sys/mount.h>
+
+#if !defined(__GLIBC__)
+#define _LINUX_TYPES_H /* kludge to prevent inclusion */
+#endif /* __GLIBC */
+#define _LINUX_WAIT_H /* idem */
+#define _I386_BITOPS_H /* idem */
#include <linux/fs.h>
#include <linux/minix_fs.h>
-#include <linux/ext_fs.h>
#include <linux/ext2_fs.h>
-#include <linux/xia_fs.h>
-#include <sys/stat.h>
-#include <unistd.h>
+#include <linux/iso_fs.h>
+
+#if defined(__GLIBC__)
+#define _SOCKETBITS_H
+#endif /* __GLIBC */
+#include "sundries.h"
+#include "fstab.h"
+#include "lomount.h"
+#include "loop.h"
#define PROC_FILESYSTEMS "/proc/filesystems"
#define SIZE(a) (sizeof(a)/sizeof(a[0]))
-int del_loop (const char *);
-
/* True for fake mount (-f). */
int fake = 0;
/* Don't write a entry in /etc/mtab (-n). */
int nomtab = 0;
-/* True for readonly (-r). */
+/* True for explicit readonly (-r). */
int readonly = 0;
/* Nonzero for chatty (-v). */
int verbose = 0;
-/* True for read/write (-w). */
+/* True for explicit read/write (-w). */
int readwrite = 0;
/* True for all mount (-a). */
int all = 0;
+/* True for fork() during all mount (-F). */
+int optfork = 0;
+
/* True if ruid != euid. */
int suid = 0;
@@ -65,16 +90,20 @@ int suid = 0;
struct opt_map
{
const char *opt; /* option name */
+ int skip; /* skip in mtab option string */
int inv; /* true if flag value should be inverted */
int mask; /* flag mask value */
};
/* Custom mount options for our own purposes. */
+/* We can use the high-order 16 bits, since the mount call
+ has MS_MGC_VAL there. */
#define MS_NOAUTO 0x80000000
#define MS_USER 0x40000000
+#define MS_LOOP 0x00010000
/* Options that we keep the mount system call from seeing. */
-#define MS_NOSYS (MS_NOAUTO|MS_USER)
+#define MS_NOSYS (MS_NOAUTO|MS_USER|MS_LOOP)
/* Options that we keep from appearing in the options field in the mtab. */
#define MS_NOMTAB (MS_REMOUNT|MS_NOAUTO|MS_USER)
@@ -82,72 +111,112 @@ struct opt_map
/* OPTIONS that we make ordinary users have by default. */
#define MS_SECURE (MS_NOEXEC|MS_NOSUID|MS_NODEV)
-const struct opt_map opt_map[] =
-{
- { "defaults", 0, 0 }, /* default options */
- { "ro", 0, MS_RDONLY }, /* read-only */
- { "rw", 1, MS_RDONLY }, /* read-write */
- { "exec", 1, MS_NOEXEC }, /* permit execution of binaries */
- { "noexec", 0, MS_NOEXEC }, /* don't execute binaries */
- { "suid", 1, MS_NOSUID }, /* honor suid executables */
- { "nosuid", 0, MS_NOSUID }, /* don't honor suid executables */
- { "dev", 1, MS_NODEV }, /* interpret device files */
- { "nodev", 0, MS_NODEV }, /* don't interpret devices */
- { "sync", 0, MS_SYNCHRONOUS}, /* synchronous I/O */
- { "async", 1, MS_SYNCHRONOUS}, /* asynchronous I/O */
- { "remount", 0, MS_REMOUNT }, /* Alter flags of mounted FS */
- { "auto", 1, MS_NOAUTO }, /* Can be mounted using -a */
- { "noauto", 0, MS_NOAUTO }, /* Can only be mounted explicitly */
- { "user", 0, MS_USER }, /* Allow ordinary user to mount */
- { "nouser", 1, MS_USER }, /* Forbid ordinary user to mount */
+const struct opt_map opt_map[] = {
+ { "defaults", 0, 0, 0 }, /* default options */
+ { "ro", 1, 0, MS_RDONLY }, /* read-only */
+ { "rw", 1, 1, MS_RDONLY }, /* read-write */
+ { "exec", 0, 1, MS_NOEXEC }, /* permit execution of binaries */
+ { "noexec", 0, 0, MS_NOEXEC }, /* don't execute binaries */
+ { "suid", 0, 1, MS_NOSUID }, /* honor suid executables */
+ { "nosuid", 0, 0, MS_NOSUID }, /* don't honor suid executables */
+ { "dev", 0, 1, MS_NODEV }, /* interpret device files */
+ { "nodev", 0, 0, MS_NODEV }, /* don't interpret devices */
+ { "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 */
+ { "auto", 0, 1, MS_NOAUTO }, /* Can be mounted using -a */
+ { "noauto", 0, 0, MS_NOAUTO }, /* Can only be mounted explicitly */
+ { "user", 0, 0, MS_USER }, /* Allow ordinary user to mount */
+ { "nouser", 0, 1, MS_USER }, /* Forbid ordinary user to mount */
/* add new options here */
#ifdef MS_NOSUB
- { "sub", 1, MS_NOSUB }, /* allow submounts */
- { "nosub", 0, MS_NOSUB }, /* don't allow submounts */
+ { "sub", 0, 1, MS_NOSUB }, /* allow submounts */
+ { "nosub", 0, 0, MS_NOSUB }, /* don't allow submounts */
+#endif
+#ifdef MS_SILENT
+ { "quiet", 0, 0, MS_SILENT }, /* be quiet */
+ { "loud", 0, 1, MS_SILENT }, /* print out messages. */
#endif
-#ifdef MS_SILENT
- { "quiet", 0, MS_SILENT }, /* be quiet */
- { "loud", 1, MS_SILENT }, /* print out messages. */
+#ifdef MS_MANDLOCK
+ { "mand", 0, 0, MS_MANDLOCK }, /* Allow mandatory locks on this FS */
+ { "nomand", 0, 1, MS_MANDLOCK }, /* Forbid mandatory locks on this FS */
#endif
- { NULL, 0, 0 }
+ { "loop", 1, 0, MS_LOOP }, /* use a loop device */
+#ifdef MS_NOATIME
+ { "atime", 0, 1, MS_NOATIME }, /* Update access time */
+ { "noatime", 0, 0, MS_NOATIME }, /* Do not update access time */
+#endif
+ { NULL, 0, 0, 0 }
+};
+
+char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption;
+
+struct string_opt_map {
+ char *tag;
+ int skip;
+ char **valptr;
+} string_opt_map[] = {
+ { "loop=", 0, &opt_loopdev },
+ { "vfs=", 1, &opt_vfstype },
+ { "offset=", 0, &opt_offset },
+ { "encryption=", 0, &opt_encryption },
+ { NULL, 0, NULL }
};
+static void
+clear_string_opts(void) {
+ struct string_opt_map *m;
+
+ for (m = &string_opt_map[0]; m->tag; m++)
+ *(m->valptr) = NULL;
+}
+
+static int
+parse_string_opt(char *s) {
+ struct string_opt_map *m;
+ int lth;
+
+ for (m = &string_opt_map[0]; m->tag; m++) {
+ lth = strlen(m->tag);
+ if (!strncmp(s, m->tag, lth)) {
+ *(m->valptr) = xstrdup(s + lth);
+ return 1;
+ }
+ }
+ return 0;
+}
+
int mount_quiet=0;
/* Report on a single mount. */
static void
-print_one (const struct mntent *mnt)
-{
- if (mount_quiet) return;
- printf ("%s on %s", mnt->mnt_fsname, mnt->mnt_dir);
- if ((mnt->mnt_type != NULL) && *mnt->mnt_type != '\0')
- printf (" type %s", mnt->mnt_type);
- if (mnt->mnt_opts != NULL)
- printf (" (%s)", mnt->mnt_opts);
- printf ("\n");
+print_one (const struct mntentchn *mc) {
+ 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 ("\n");
}
/* Report on everything in mtab (of the specified types if any). */
static int
print_all (string_list types)
{
- struct mntent *mnt;
-
- open_mtab ("r");
-
- while ((mnt = getmntent (F_mtab)) != NULL)
- if (matching_type (mnt->mnt_type, types))
- print_one (mnt);
+ struct mntentchn *mc;
- if (ferror (F_mtab))
- die (1, "mount: error reading %s: %s", MOUNTED, strerror (errno));
-
- exit (0);
+ for (mc = mtab_head()->nxt; mc; mc = mc->nxt) {
+ if (matching_type (mc->mnt_type, types))
+ print_one (mc);
+ }
+ exit (0);
}
/* Look for OPT in opt_map table and return mask value. If OPT isn't found,
- tack it onto extra_opts. */
+ tack it onto extra_opts (which is non-NULL). */
static inline void
parse_opt (const char *opt, int *mask, char *extra_opts)
{
@@ -185,15 +254,16 @@ parse_opts (char *opts, int *flags, char **extra_opts)
*flags = 0;
*extra_opts = NULL;
+ clear_string_opts();
+
if (opts != NULL)
{
*extra_opts = xmalloc (strlen (opts) + 1);
**extra_opts = '\0';
- for (opt = strtok (opts, ",");
- opt != NULL;
- opt = strtok (NULL, ","))
- 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)
@@ -207,30 +277,64 @@ static char *
fix_opts_string (int flags, char *extra_opts)
{
const struct opt_map *om;
+ const struct string_opt_map *m;
char *new_opts;
- char *tmp;
new_opts = (flags & MS_RDONLY) ? "ro" : "rw";
- for (om = opt_map; om->opt != NULL; om++)
- {
- if (om->mask & MS_RDONLY)
+ for (om = opt_map; om->opt != NULL; om++) {
+ if (om->skip)
continue;
if (om->inv || !om->mask || (flags & om->mask) != om->mask)
continue;
- tmp = xmalloc(strlen(new_opts) + strlen(om->opt) + 2);
- sprintf(tmp, "%s,%s", new_opts, om->opt);
- new_opts = tmp;
+ new_opts = xstrconcat3(new_opts, ",", om->opt);
flags &= ~om->mask;
- }
- if (extra_opts && *extra_opts)
- {
- tmp = xmalloc(strlen(new_opts) + strlen(extra_opts) + 2);
- sprintf(tmp, "%s,%s", new_opts, extra_opts);
- new_opts = tmp;
- }
+ }
+ for (m = &string_opt_map[0]; m->tag; m++) {
+ if (!m->skip && *(m->valptr))
+ new_opts = xstrconcat4(new_opts, ",", m->tag, *(m->valptr));
+ }
+ if (extra_opts && *extra_opts) {
+ new_opts = xstrconcat3(new_opts, ",", extra_opts);
+ }
return new_opts;
}
+/* Most file system types can be recognized by a `magic' number
+ in the superblock. Note that the order of the tests is
+ significant: by coincidence a filesystem can have the
+ magic numbers for several file system types simultaneously.
+ For example, the romfs magic lives in the 1st sector;
+ xiafs does not touch the 1st sector and has its magic in
+ the 2nd sector; ext2 does not touch the first two sectors. */
+
+/* ext definitions - required since 2.1.21 */
+#ifndef EXT_SUPER_MAGIC
+#define EXT_SUPER_MAGIC 0x137D
+struct ext_super_block {
+ unsigned long s_dummy[14];
+ unsigned short s_magic;
+};
+#endif
+
+/* xiafs definitions - required since they were removed from
+ the kernel since 2.1.21 */
+#ifndef _XIAFS_SUPER_MAGIC
+#define _XIAFS_SUPER_MAGIC 0x012FD16D
+struct xiafs_super_block {
+ u_char s_boot_segment[512]; /* 1st sector reserved for boot */
+ u_long s_dummy[15];
+ u_long s_magic; /* 15: magic number for xiafs */
+};
+#endif
+
+#ifndef EXT2_PRE_02B_MAGIC
+#define EXT2_PRE_02B_MAGIC 0xEF51
+#endif
+
+static inline unsigned short
+swapped(unsigned short a) {
+ return (a>>8) | (a<<8);
+}
/*
char *fstype(const char *device);
@@ -242,10 +346,13 @@ fix_opts_string (int flags, char *extra_opts)
for mount(8) by Mike Grupenhoff <kashmir@umiacs.umd.edu>.
Read the superblock only once - aeb
Added a test for iso9660 - aeb
+ Added a test for high sierra (iso9660) - quinlan@bucknell.edu
+ Corrected the test for xiafs - aeb
+ added romfs - aeb
- Currently supports: minix, ext, ext2, xiafs, iso9660
+ Currently supports: minix, ext, ext2, xiafs, iso9660, romfs
*/
-char *magic_known[] = { "minix", "ext", "ext2", "xiafs", "iso9660" };
+char *magic_known[] = { "minix", "ext", "ext2", "xiafs", "iso9660", "romfs" };
static int
tested(const char *device) {
@@ -261,65 +368,76 @@ static char *
fstype(const char *device)
{
int fd;
- char ifs_magic[8];
+ char *type = NULL;
union {
struct minix_super_block ms;
struct ext_super_block es;
struct ext2_super_block e2s;
- struct xiafs_super_block xfs;
} sb;
+ union {
+ struct xiafs_super_block xiasb;
+ char romfs_magic[8];
+ } xsb;
+ union {
+ struct iso_volume_descriptor iso;
+ struct hs_volume_descriptor hs;
+ } isosb;
struct stat statbuf;
/* opening and reading an arbitrary unknown path can have
undesired side effects - first check that `device' refers
to a block device */
- if (stat (device, &statbuf))
- error("mount: %s does not exist", device);
- if (!S_ISBLK(statbuf.st_mode))
- error("mount: %s is not a block device", device);
+ if (stat (device, &statbuf) || !S_ISBLK(statbuf.st_mode))
+ return 0;
fd = open(device, O_RDONLY);
- if (fd < 0
- || lseek(fd, BLOCK_SIZE, SEEK_SET) < 0
- || read(fd, (char *) &sb, sizeof(sb)) < 0) {
- perror(device);
- return 0;
- }
+ if (fd < 0)
+ return 0;
- if (sb.ms.s_magic == MINIX_SUPER_MAGIC
- || sb.ms.s_magic == MINIX_SUPER_MAGIC2) {
- close (fd);
- return("minix");
- }
+ if (lseek(fd, BLOCK_SIZE, SEEK_SET) != BLOCK_SIZE
+ || read(fd, (char *) &sb, sizeof(sb)) != sizeof(sb))
+ goto io_error;
- if (sb.es.s_magic == EXT_SUPER_MAGIC) {
- close (fd);
- return("ext");
- }
-
-#ifndef EXT2_PRE_02B_MAGIC
-#define EXT2_PRE_02B_MAGIC 0xEF51
-#endif
if (sb.e2s.s_magic == EXT2_SUPER_MAGIC
- || sb.e2s.s_magic == EXT2_PRE_02B_MAGIC) {
- close (fd);
- return("ext2");
+ || sb.e2s.s_magic == EXT2_PRE_02B_MAGIC
+ || sb.e2s.s_magic == swapped(EXT2_SUPER_MAGIC))
+ type = "ext2";
+
+ else if (sb.ms.s_magic == MINIX_SUPER_MAGIC
+ || sb.ms.s_magic == MINIX_SUPER_MAGIC2)
+ type = "minix";
+
+ else if (sb.es.s_magic == EXT_SUPER_MAGIC)
+ type = "ext";
+
+ if (!type) {
+ if (lseek(fd, 0, SEEK_SET) != 0
+ || read(fd, (char *) &xsb, sizeof(xsb)) != sizeof(xsb))
+ goto io_error;
+
+ if (xsb.xiasb.s_magic == _XIAFS_SUPER_MAGIC)
+ type = "xiafs";
+ else if(!strncmp(xsb.romfs_magic, "-rom1fs-", 8))
+ type = "romfs";
}
- if (sb.xfs.s_magic == _XIAFS_SUPER_MAGIC) {
- close (fd);
- return("xiafs");
- }
+ if (!type) {
+ if (lseek(fd, 0x8000, SEEK_SET) != 0x8000
+ || read(fd, (char *) &isosb, sizeof(isosb)) != sizeof(isosb))
+ goto io_error;
- if (lseek (fd, 0100000, SEEK_SET) != -1
- && read (fd, ifs_magic, 8) == 8
- && !strncmp(ifs_magic, "\001CD001\001", 8)) { /* ECMA 119 */
- close (fd);
- return("iso9660");
+ if(strncmp(isosb.iso.id, ISO_STANDARD_ID, sizeof(isosb.iso.id)) == 0
+ || strncmp(isosb.hs.id, HS_STANDARD_ID, sizeof(isosb.hs.id)) == 0)
+ type = "iso9660";
}
close (fd);
- return(0);
+ return(type);
+
+io_error:
+ perror(device);
+ close(fd);
+ return 0;
}
FILE *procfs;
@@ -363,20 +481,68 @@ is_in_proc(char *type) {
static int
already (char *spec, char *node) {
- struct mntent *me;
+ struct mntentchn *mc;
int ret = 1;
- if ((me = getmntfile(node)) != NULL)
+ if ((mc = getmntfile(node)) != NULL)
error ("mount: according to mtab, %s is already mounted on %s",
- me->mnt_fsname, node);
- else if ((me = getmntfile(spec)) != NULL)
+ mc->mnt_fsname, node);
+ else if ((mc = getmntfile(spec)) != NULL)
error ("mount: according to mtab, %s is mounted on %s",
- spec, me->mnt_dir);
+ spec, mc->mnt_dir);
else
ret = 0;
return ret;
}
+/* Create mtab with a root entry. */
+static void
+create_mtab (void) {
+ struct mntentchn *fstab;
+ struct mntent mnt;
+ int flags;
+ char *extra_opts;
+ FILE *fp;
+
+ lock_mtab();
+
+ if ((fp = setmntent (MOUNTED, "a+")) == NULL)
+ die (EX_FILEIO, "mount: can't open %s for writing: %s",
+ MOUNTED, strerror (errno));
+
+ /* 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);
+ mnt.mnt_dir = "/";
+ mnt.mnt_fsname = canonicalize (fstab->mnt_fsname);
+ mnt.mnt_type = fstab->mnt_type;
+ mnt.mnt_opts = fix_opts_string (flags, extra_opts);
+ mnt.mnt_freq = mnt.mnt_passno = 0;
+
+ if (addmntent (fp, &mnt) == 1)
+ die (EX_FILEIO, "mount: error writing %s: %s",
+ MOUNTED, strerror (errno));
+ }
+ if (fchmod (fileno (fp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0)
+ if (errno != EROFS)
+ die (EX_FILEIO, "mount: error changing mode of %s: %s",
+ MOUNTED, strerror (errno));
+ endmntent (fp);
+
+ unlock_mtab();
+}
+
+/* count successful mount system calls */
+static int mountcount = 0;
+
+static int
+mount5 (char *special, char *dir, char *type, int flags, void *data) {
+ int ret = mount (special, dir, type, 0xC0ED0000 | (flags), data);
+ if (ret == 0)
+ mountcount++;
+ return ret;
+}
+
/* Mount a single file system. Return status,
so don't exit on non-fatal errors. */
@@ -384,13 +550,11 @@ static int
try_mount5 (char *spec, char *node, char **type, int flags, char *mount_opts) {
char *fsname;
- if (strcasecmp (*type, "auto") == 0)
+ if (*type && strcasecmp (*type, "auto") == 0)
*type = NULL;
- if (!*type) {
+ if (!*type && !(flags & MS_REMOUNT)) {
*type = fstype(spec);
- if (!*type && !procopen())
- *type = FSTYPE_DEFAULT;
if (verbose) {
printf ("mount: you didn't specify a filesystem type for %s\n",
spec);
@@ -402,9 +566,11 @@ try_mount5 (char *spec, char *node, char **type, int flags, char *mount_opts) {
}
}
- if (*type)
+ if (*type || (flags & MS_REMOUNT))
return mount5 (spec, node, *type, flags & ~MS_NOSYS, mount_opts);
+ if (!procopen())
+ return -1;
while ((fsname = procnext()) != NULL) {
if (tested (fsname))
continue;
@@ -424,32 +590,52 @@ try_mount5 (char *spec, char *node, char **type, int flags, char *mount_opts) {
return -1;
}
-
static int
-mount_one (char *spec, char *node, char *type, char *opts, int freq, int pass)
+mount_one (char *spec0, char *node0, char *type0, char *opts0,
+ int freq, int pass)
{
+ struct mntentchn mcn;
struct mntent mnt;
int mnt_err;
int flags;
- char *extra_opts;
- char *mount_opts;
+ char *extra_opts; /* written in mtab */
+ char *mount_opts; /* actually used on system call */
static int added_ro = 0;
- int loop=0;
+ int loop, looptype, offset;
+ char *spec, *node, *type, *opts, *loopdev, *loopfile;
- if (type == NULL)
- {
- if (strchr (spec, ':') != NULL)
+ spec = xstrdup(spec0);
+ node = xstrdup(node0);
+ type = xstrdup(type0);
+ opts = xstrdup(opts0);
+
+/*
+ * There are two special cases: nfs mounts and loop mounts.
+ * In the case of nfs mounts spec is probably of the form machine:path.
+ * In the case of a loop mount, either type is of the form lo@/dev/loop5
+ * or the option "-o loop=/dev/loop5" or just "-o loop" is given, or
+ * mount just has to figure things out for itself from the fact that
+ * spec is not a block device. We do not test for a block device
+ * immediately: maybe later other types of mountable objects will occur.
+ */
+
+ if (type == NULL) {
+ if (strchr (spec, ':') != NULL) {
type = "nfs";
- }
+ if (verbose)
+ printf("mount: no type was given - "
+ "I'll assume nfs because of the colon\n");
+ }
+ }
parse_opts (xstrdup (opts), &flags, &extra_opts);
/* root may allow certain types of mounts by ordinary users */
if (suid && !(flags & MS_USER)) {
if (already (spec, node))
- die (3, "mount failed");
+ die (EX_USAGE, "mount failed");
else
- die (3, "mount: only root can mount %s on %s", spec, node);
+ die (EX_USAGE, "mount: only root can mount %s on %s", spec, node);
}
/* quietly succeed for fstab entries that don't get mounted automatically */
@@ -458,69 +644,156 @@ mount_one (char *spec, char *node, char *type, char *opts, int freq, int pass)
mount_opts = extra_opts;
- if (!fake && type && strncmp("lo@", type, 3)==0) {
- extern int lomount (char *, char *, char *, char **,
- int *, char **, char **);
- char *dev=type+3;
+ /*
+ * A loop mount?
+ * Only test for explicitly specified loop here,
+ * and try implicit loop if the mount fails.
+ */
+ loopdev = opt_loopdev;
+
+ looptype = (type && strncmp("lo@", type, 3) == 0);
+ if (looptype) {
+ if (loopdev)
+ error("mount: loop device specified twice");
+ loopdev = type+3;
+ type = opt_vfstype;
+ }
+ else if (opt_vfstype) {
+ if (type)
+ error("mount: type specified twice");
+ else
+ type = opt_vfstype;
+ }
- loop=1;
- if (lomount (spec, node, dev, &type,
- &flags, &opts, &mount_opts) != 0)
- return 1;
- spec=dev;
- mount_opts=NULL;
+ loop = ((flags & MS_LOOP) || loopdev || opt_offset || opt_encryption);
+ loopfile = spec;
+
+ if (loop) {
+ flags |= MS_LOOP;
+ if (fake) {
+ if (verbose)
+ printf("mount: skipping the setup of a loop device\n");
+ } else {
+ int loopro = (flags & MS_RDONLY);
+
+ if (!loopdev || !*loopdev)
+ loopdev = find_unused_loop_device();
+ if (!loopdev)
+ return EX_SYSERR; /* no more loop devices */
+ if (verbose)
+ printf("mount: going to use the loop device %s\n", loopdev);
+ offset = opt_offset ? strtoul(opt_offset, NULL, 0) : 0;
+ if (set_loop (loopdev, loopfile, offset, opt_encryption, &loopro))
+ return EX_FAIL;
+ spec = loopdev;
+ if (loopro)
+ flags |= MS_RDONLY;
+ }
}
if (!fake && type && streq (type, "nfs"))
#ifdef HAVE_NFS
if (nfsmount (spec, node, &flags, &extra_opts, &mount_opts) != 0)
- return 1;
+ return EX_FAIL;
#else
- die (1, "mount: this version was compiled without support for the type `nfs'");
+ die (EX_SOFTWARE, "mount: this version was compiled "
+ "without support for the type `nfs'");
#endif
+ /*
+ * Call mount.TYPE for types that require a separate
+ * mount program. For the moment these types are ncp and smb.
+ */
+ if (type)
+#ifndef ALWAYS_STAT
+ if (streq (type, "smb") || streq (type, "ncp"))
+#else
+ if (strlen (type) < 100)
+#endif
+ {
+ struct stat statbuf;
+ char mountprog[120];
+
+ sprintf(mountprog, "/sbin/mount.%s", type);
+ if (stat(mountprog, &statbuf) == 0) {
+ if (fork() == 0) {
+ char *oo, *mountargs[10];
+ int i = 0;
+
+ setuid(getuid());
+ setgid(getgid());
+ oo = fix_opts_string (flags, extra_opts);
+ mountargs[i++] = mountprog;
+ mountargs[i++] = spec;
+ mountargs[i++] = node;
+ if (nomtab)
+ mountargs[i++] = "-n";
+ if (verbose)
+ mountargs[i++] = "-v";
+ if (oo && *oo) {
+ mountargs[i++] = "-o";
+ mountargs[i++] = oo;
+ }
+ mountargs[i] = NULL;
+ execv(mountprog, mountargs);
+ exit(1); /* exec failed */
+ } else if (fork() != -1) {
+ int status;
+ wait(&status);
+ return status;
+ } else
+ error("cannot fork: %s", strerror(errno));
+ }
+ }
+
block_signals (SIG_BLOCK);
if (fake
|| (try_mount5 (spec, node, &type, flags & ~MS_NOSYS, mount_opts)) == 0)
- /* Mount succeeded, write mtab entry. */
+ /* Mount succeeded, report this (if verbose) and write mtab entry. */
{
- if (!nomtab)
- {
- mnt.mnt_fsname = canonicalize (spec);
- mnt.mnt_dir = canonicalize (node);
- mnt.mnt_type = loop ? "loop" : type;
- mnt.mnt_opts = fix_opts_string (flags & ~MS_NOMTAB,
- loop?opts:extra_opts);
- mnt.mnt_freq = freq;
- mnt.mnt_passno = pass;
+ if (loop)
+ opt_loopdev = loopdev;
+
+ mcn.mnt_fsname = mnt.mnt_fsname = canonicalize (loop ? loopfile : spec);
+ mcn.mnt_dir = mnt.mnt_dir = canonicalize (node);
+ mcn.mnt_type = mnt.mnt_type = type ? type : "unknown";
+ mcn.mnt_opts = mnt.mnt_opts = fix_opts_string (flags & ~MS_NOMTAB, extra_opts);
+ mcn.nxt = 0;
+ 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 (&mnt);
+ /* 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);
+ if (!nomtab && mtab_is_writable()) {
if (flags & MS_REMOUNT)
- {
- close_mtab ();
- update_mtab (mnt.mnt_dir, &mnt);
- open_mtab ("a+");
- }
- else
- if ((addmntent (F_mtab, &mnt)) == 1)
- die (1, "mount: error writing %s: %s",
- MOUNTED, strerror (errno));
- }
+ update_mtab (mnt.mnt_dir, &mnt);
+ else {
+ FILE *fp = setmntent(MOUNTED, "a+");
+ if (fp == NULL)
+ error("mount: can't open %s: %s", MOUNTED,
+ strerror (errno));
+ else {
+ if ((addmntent (fp, &mnt)) == 1)
+ error("mount: error writing %s: %s", MOUNTED,
+ strerror (errno));
+ endmntent(fp);
+ }
+ }
+ }
block_signals (SIG_UNBLOCK);
return 0;
}
+ mnt_err = errno;
+
if (loop)
del_loop(spec);
- mnt_err = errno; /* work around for errno bug in sigprocmask */
-
block_signals (SIG_UNBLOCK);
/* Mount failed, complain, but don't die. */
@@ -531,14 +804,22 @@ mount_one (char *spec, char *node, char *type, char *opts, int freq, int pass)
switch (mnt_err)
{
case EPERM:
- if (geteuid() == 0)
- error ("mount: mount point %s is not a directory", node);
- else
+ if (geteuid() == 0) {
+ struct stat statbuf;
+ if (stat (node, &statbuf) || !S_ISDIR(statbuf.st_mode))
+ error ("mount: mount point %s is not a directory", node);
+ else
+ error ("mount: permission denied");
+ } else
error ("mount: must be superuser to use mount");
break;
case EBUSY:
- error ("mount: %s already mounted or %s busy", spec, node);
- already (spec, node);
+ if (flags & MS_REMOUNT) {
+ error ("mount: %s is busy", node);
+ } else {
+ error ("mount: %s already mounted or %s busy", spec, node);
+ already (spec, node);
+ }
break;
case ENOENT:
{ struct stat statbuf;
@@ -556,27 +837,78 @@ mount_one (char *spec, char *node, char *type, char *opts, int freq, int pass)
break;
}
case ENOTDIR:
- error ("mount: mount point %s is not a directory", node); break;
+ error ("mount: mount point %s is not a directory", node);
+ break;
case EINVAL:
- error ("mount: wrong fs type or bad superblock on %s", spec); break;
+ { int fd, size;
+ struct stat statbuf;
+
+ if (flags & MS_REMOUNT) {
+ error ("mount: %s not mounted already, or bad option\n", node);
+ } else {
+ error ("mount: wrong fs type, bad option, bad superblock on %s,\n"
+ " or too many mounted file systems",
+ spec);
+
+ if (stat (spec, &statbuf) == 0 && S_ISBLK(statbuf.st_mode)
+ && (fd = open(spec, O_RDONLY)) >= 0) {
+ if(ioctl(fd, BLKGETSIZE, &size) == 0 && size <= 2)
+ error (" (aren't you trying to mount an extended partition,\n"
+ " instead of some logical partition inside?)\n");
+ close(fd);
+ }
+ }
+ break;
+ }
case EMFILE:
error ("mount table full"); break;
case EIO:
error ("mount: %s: can't read superblock", spec); break;
case ENODEV:
- if (is_in_proc(type))
+ if (is_in_proc(type) || !strcmp(type, "guess"))
error("mount: %s has wrong major or minor number", spec);
- else if (procfs)
+ else if (procfs) {
+ char *lowtype, *p;
+ int u;
+
error ("mount: fs type %s not supported by kernel", type);
- else
+
+ /* maybe this loser asked for FAT or ISO9660 or isofs */
+ lowtype = xstrdup(type);
+ u = 0;
+ for(p=lowtype; *p; p++) {
+ if(tolower(*p) != *p) {
+ *p = tolower(*p);
+ u++;
+ }
+ }
+ if (u && is_in_proc(lowtype))
+ error ("mount: probably you meant %s", lowtype);
+ else if (!strncmp(lowtype, "iso", 3) && is_in_proc("iso9660"))
+ 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:
- error ("mount: %s is not a block device", spec); break;
+ { struct stat statbuf;
+
+ if (stat (spec, &statbuf)) /* strange ... */
+ error ("mount: %s is not a block device, and stat fails?", spec);
+ else if (S_ISBLK(statbuf.st_mode))
+ error ("mount: the kernel does not recognize %s as a block device\n"
+ " (maybe `insmod driver'?)", spec);
+ else if (S_ISREG(statbuf.st_mode))
+ error ("mount: %s is not a block device (maybe try `-o loop'?)",
+ spec);
+ else
+ error ("mount: %s is not a block device", spec);
+ }
+ break;
case ENXIO:
error ("mount: %s is not a valid block device", spec); break;
- case EACCES: /* pre-linux 1.1.38 */
+ case EACCES: /* pre-linux 1.1.38, 1.1.41 and later */
case EROFS: /* linux 1.1.38 and later */
if (added_ro) {
error ("mount: block device %s is not permitted on its filesystem",
@@ -584,6 +916,10 @@ mount_one (char *spec, char *node, char *type, char *opts, int freq, int pass)
break;
} else {
added_ro = 1;
+ if (loop) {
+ opts = opts0;
+ type = type0;
+ }
if (opts) {
opts = realloc(xstrdup(opts), strlen(opts)+4);
strcat(opts, ",ro");
@@ -591,104 +927,132 @@ mount_one (char *spec, char *node, char *type, char *opts, int freq, int pass)
opts = "ro";
if (type && !strcmp(type, "guess"))
type = 0;
- error ("mount: block device %s is write-protected, "
- "mounting read-only", spec);
- return mount_one (spec, node, type, opts, freq, pass);
+ error ("mount: %s%s is write-protected, mounting read-only",
+ loop ? "" : "block device ", spec0);
+ return mount_one (spec0, node0, type, opts, freq, pass);
}
break;
default:
error ("mount: %s", strerror (mnt_err)); break;
}
- return 1;
+ return EX_FAIL;
}
/* Check if an fsname/dir pair was already in the old mtab. */
static int
-mounted (char *spec, char *node, string_list spec_list, string_list node_list)
-{
- spec = canonicalize (spec);
- node = canonicalize (node);
-
- while (spec_list != NULL)
- {
- if (streq (spec, car (spec_list)) && streq (node, car (node_list)))
- return 1;
- spec_list = cdr (spec_list);
- node_list = cdr (node_list);
- }
- return 0;
-}
-
-/* Mount all filesystems of the specified types except swap and root. */
-static int
-mount_all (string_list types)
-{
- struct mntent *fstab;
- struct mntent *mnt;
- string_list spec_list = NULL;
- string_list node_list = NULL;
- int status;
-
- rewind (F_mtab);
-
- while ((mnt = getmntent (F_mtab)))
- if (matching_type (mnt->mnt_type, types)
- && !streq (mnt->mnt_dir, "/")
- && !streq (mnt->mnt_dir, "root"))
- {
- spec_list = cons (xstrdup (mnt->mnt_fsname), spec_list);
- node_list = cons (xstrdup (mnt->mnt_dir), node_list);
- }
+mounted (char *spec, char *node) {
+ struct mntentchn *mc;
- status = 0;
- if (!setfsent()) return 1;
- while ((fstab = getfsent ()) != NULL)
- if (matching_type (fstab->mnt_type, types)
- && !streq (fstab->mnt_dir, "/")
- && !streq (fstab->mnt_dir, "root"))
- if (mounted (fstab->mnt_fsname, fstab->mnt_dir, spec_list, node_list))
- {
- if (verbose)
- printf("mount: %s already mounted on %s\n",
- fstab->mnt_fsname, fstab->mnt_dir);
- }
- else
- status |= mount_one (fstab->mnt_fsname, fstab->mnt_dir,
- fstab->mnt_type, fstab->mnt_opts,
- fstab->mnt_freq, fstab->mnt_passno);
+ spec = canonicalize (spec);
+ node = canonicalize (node);
- return status;
+ for (mc = mtab_head()->nxt; mc; mc = mc->nxt)
+ if (streq (spec, mc->mnt_fsname) && streq (node, mc->mnt_dir))
+ return 1;
+ return 0;
}
-/* Create mtab with a root entry. */
-static void
-create_mtab (void)
-{
- struct mntent *fstab;
- struct mntent mnt;
- int flags;
- char *extra_opts;
-
- if ((F_mtab = setmntent (MOUNTED, "a+")) == NULL)
- die (1, "mount: can't open %s for writing: %s", MOUNTED, strerror (errno));
-
- /* Find the root entry by looking it up in fstab, which might be wrong.
- We could statfs "/" followed by a slew of stats on /dev/ but then
- we'd have to unparse the mount options as well.... */
- if ((fstab = getfsfile ("/")) || (fstab = getfsfile ("root")))
- {
- parse_opts (xstrdup (fstab->mnt_opts), &flags, &extra_opts);
- mnt = *fstab;
- mnt.mnt_fsname = canonicalize (fstab->mnt_fsname);
- mnt.mnt_dir = "/";
- mnt.mnt_opts = fix_opts_string (flags, extra_opts);
+/* Mount all filesystems of the specified types except swap and root. */
+/* With the --fork option: fork and let different incarnations of
+ mount handle different filesystems. However, try to avoid several
+ simultaneous mounts on the same physical disk, since that is very slow. */
+#define DISKMAJOR(m) ((m) & ~0xf)
- if (addmntent (F_mtab, &mnt) == 1)
- die (1, "mount: error writing %s: %s", MOUNTED, strerror (errno));
- }
- if (fchmod (fileno (F_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0)
- die (1, "mount: error changing mode of %s: %s", MOUNTED, strerror (errno));
- endmntent (F_mtab);
+static int
+mount_all (string_list types) {
+ struct mntentchn *mc, *mtmp;
+ int status = 0, m;
+ struct stat statbuf;
+ struct child {
+ pid_t pid;
+ dev_t major;
+ struct mntentchn *mec;
+ struct mntentchn *meclast;
+ struct child *nxt;
+ } childhead, *childtail, *cp;
+
+ /* build a chain of what we have to do, or maybe
+ several chains, one for each major */
+ 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)) {
+ if (verbose)
+ printf("mount: %s already mounted on %s\n",
+ mc->mnt_fsname, mc->mnt_dir);
+ } else {
+ mtmp = (struct mntentchn *) xmalloc(sizeof(*mtmp));
+ *mtmp = *mc;
+ mtmp->nxt = 0;
+ m = 0;
+ if (optfork && stat(mc->mnt_fsname, &statbuf) == 0
+ && S_ISBLK(statbuf.st_mode))
+ m = DISKMAJOR(statbuf.st_rdev);
+ if (m) {
+ for (cp = childhead.nxt; cp; cp = cp->nxt)
+ if (cp->major == m) {
+ cp->meclast->nxt = mtmp;
+ cp->meclast = mtmp;
+ goto fnd;
+ }
+ }
+ cp = (struct child *) xmalloc(sizeof *cp);
+ cp->nxt = 0;
+ cp->mec = cp->meclast = mtmp;
+ cp->major = m;
+ cp->pid = 0;
+ childtail->nxt = cp;
+ childtail = cp;
+ fnd:;
+ }
+ }
+ }
+
+ /* now do everything */
+ for (cp = childhead.nxt; cp; cp = cp->nxt) {
+ pid_t p = -1;
+ if (optfork) {
+ p = fork();
+ if (p == -1)
+ error("mount: cannot fork: %s", strerror (errno));
+ else if (p != 0)
+ cp->pid = p;
+ }
+
+ /* 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, 0, 0);
+ if (mountcount)
+ status |= EX_SOMEOK;
+ if (p == 0)
+ exit(status);
+ }
+ }
+
+ /* wait for children, if any */
+ while ((cp = childhead.nxt) != NULL) {
+ childhead.nxt = cp->nxt;
+ if (cp->pid) {
+ int ret;
+ keep_waiting:
+ if(waitpid(cp->pid, &ret, 0) == -1) {
+ if (errno == EINTR)
+ goto keep_waiting;
+ perror("waitpid");
+ } else if (WIFEXITED(ret))
+ status |= WEXITSTATUS(ret);
+ else
+ status |= EX_SYSERR;
+ }
+ }
+ if (mountcount)
+ status |= EX_SOMEOK;
+ return status;
}
extern char version[];
@@ -696,6 +1060,7 @@ 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' },
@@ -711,7 +1076,7 @@ static struct option longopts[] =
const char *usage_string = "\
usage: mount [-hV]\n\
- mount -a [-nfrvw] [-t vfstypes]\n\
+ mount -a [-nfFrvw] [-t vfstypes]\n\
mount [-nfrvw] [-o options] special | node\n\
mount [-nfrvw] [-t vfstype] [-o options] special node\n\
";
@@ -725,118 +1090,110 @@ usage (FILE *fp, int n)
}
int
-main (int argc, char *argv[])
-{
- int c;
- char *options = NULL;
+main (int argc, char *argv[]) {
+ int c, result = 0;
+ char *options = NULL, *spec;
string_list types = NULL;
- struct mntent *fs;
- char *spec;
- int result = 0;
- struct stat statbuf;
+ struct mntentchn *mc;
- while ((c = getopt_long (argc, argv, "afhnrvVwt:o:", longopts, NULL)) != EOF)
- switch (c)
- {
+ while ((c = getopt_long (argc, argv, "afFhno:rvVwt:", 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 '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;
+ readonly = 1;
readwrite = 0;
break;
- case 'v': /* be chatty */
+ case 't': /* specify file system types */
+ types = parse_list (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;
+ readwrite = 1;
readonly = 0;
break;
- case 't': /* specify file system types */
- types = parse_list (optarg);
- break;
- case 'o': /* specify mount options */
- options = optarg;
- break;
case 0:
break;
case '?':
default:
- usage (stderr, 1);
- break;
- }
+ usage (stderr, EX_USAGE);
+ }
argc -= optind;
argv += optind;
- if (argc == 0)
- {
+ if (argc == 0) {
if (options)
- usage (stderr, 1);
+ usage (stderr, EX_USAGE);
if (!all)
return print_all (types);
- }
+ }
- if (getuid () != geteuid ())
- {
+ if (getuid () != geteuid ()) {
suid = 1;
if (types || options || readwrite || nomtab || all || fake || argc != 1)
- die (2, "mount: only root can do that");
- }
-
- if (!nomtab)
- {
- lock_mtab ();
- if (stat(MOUNTED, &statbuf) < 0)
- create_mtab ();
- open_mtab ("a+");
- }
- else if (stat(MOUNTED, &statbuf) >= 0)
- open_mtab ("r");
+ die (EX_USAGE, "mount: only root can do that");
+ }
+ if (!nomtab && mtab_does_not_exist()) {
+ if (verbose > 1)
+ printf("mount: no %s found - creating it..\n", MOUNTED);
+ create_mtab ();
+ }
- switch (argc)
- {
+ switch (argc) {
case 0:
/* mount -a */
result = mount_all (types);
+ if (result == 0 && verbose)
+ error("not mounted anything");
break;
case 1:
/* mount [-nfrvw] [-o options] special | node */
if (types != NULL)
- usage (stderr, 1);
+ usage (stderr, EX_USAGE);
+
/* Try to find the other pathname in fstab. */
spec = canonicalize (*argv);
- if (!(fs = getmntfile (spec))
- && !(fs = getfsspec (spec)) && !(fs = getfsfile (spec)))
- die (2, "mount: can't find %s in %s or %s",
- spec, MOUNTED, _PATH_FSTAB);
+ if ((mc = getmntfile (spec)) == NULL &&
+ (mc = getfsspec (spec)) == NULL && (mc = getfsfile (spec)) == NULL)
+ die (EX_USAGE, "mount: can't find %s in %s or %s",
+ spec, MOUNTED, _PATH_FSTAB);
+
/* Merge the fstab and command line options. */
if (options == NULL)
- options = fs->mnt_opts;
+ options = mc->mnt_opts;
else
- {
- char *tmp = xmalloc(strlen(fs->mnt_opts) + strlen(options) + 2);
+ options = xstrconcat3(mc->mnt_opts, ",", options);
- sprintf (tmp, "%s,%s", fs->mnt_opts, options);
- options = tmp;
- }
- result = mount_one (xstrdup (fs->mnt_fsname), xstrdup (fs->mnt_dir),
- xstrdup (fs->mnt_type), options,
- fs->mnt_freq, fs->mnt_passno);
+ result = mount_one (xstrdup (mc->mnt_fsname), xstrdup (mc->mnt_dir),
+ xstrdup (mc->mnt_type), options, 0, 0);
break;
case 2:
@@ -846,18 +1203,14 @@ main (int argc, char *argv[])
else if (cdr (types) == NULL)
result = mount_one (argv[0], argv[1], car (types), options, 0, 0);
else
- usage (stderr, 2);
+ usage (stderr, EX_USAGE);
break;
default:
- usage (stderr, 2);
- }
-
- if (!nomtab)
- {
- endmntent (F_mtab);
- unlock_mtab ();
- }
+ usage (stderr, EX_USAGE);
+ }
+ if (result == EX_SOMEOK)
+ result = 0;
exit (result);
}
diff --git a/mount/mount.x b/mount/mount.x
deleted file mode 100644
index 7e0d7f3ad..000000000
--- a/mount/mount.x
+++ /dev/null
@@ -1,161 +0,0 @@
-/* @(#)mount.x 2.1 88/08/01 4.0 RPCSRC */
-/* @(#)mount.x 1.2 87/09/18 Copyr 1987 Sun Micro */
-
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-
-/*
- * Protocol description for the mount program
- */
-
-
-const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */
-const MNTNAMLEN = 255; /* maximum bytes in a name argument */
-const FHSIZE = 32; /* size in bytes of a file handle */
-
-/*
- * The fhandle is the file handle that the server passes to the client.
- * All file operations are done using the file handles to refer to a file
- * or a directory. The file handle can contain whatever information the
- * server needs to distinguish an individual file.
- */
-typedef opaque fhandle[FHSIZE];
-
-/*
- * If a status of zero is returned, the call completed successfully, and
- * a file handle for the directory follows. A non-zero status indicates
- * some sort of error. The status corresponds with UNIX error numbers.
- */
-union fhstatus switch (unsigned fhs_status) {
-case 0:
- fhandle fhs_fhandle;
-default:
- void;
-};
-
-/*
- * The type dirpath is the pathname of a directory
- */
-typedef string dirpath<MNTPATHLEN>;
-
-/*
- * The type name is used for arbitrary names (hostnames, groupnames)
- */
-typedef string name<MNTNAMLEN>;
-
-/*
- * A list of who has what mounted
- */
-typedef struct mountbody *mountlist;
-struct mountbody {
- name ml_hostname;
- dirpath ml_directory;
- mountlist ml_next;
-};
-
-/*
- * A list of netgroups
- */
-typedef struct groupnode *groups;
-struct groupnode {
- name gr_name;
- groups gr_next;
-};
-
-/*
- * A list of what is exported and to whom
- */
-typedef struct exportnode *exports;
-struct exportnode {
- dirpath ex_dir;
- groups ex_groups;
- exports ex_next;
-};
-
-program MOUNTPROG {
- /*
- * Version one of the mount protocol communicates with version two
- * of the NFS protocol. The only connecting point is the fhandle
- * structure, which is the same for both protocols.
- */
- version MOUNTVERS {
- /*
- * Does no work. It is made available in all RPC services
- * to allow server reponse testing and timing
- */
- void
- MOUNTPROC_NULL(void) = 0;
-
- /*
- * If fhs_status is 0, then fhs_fhandle contains the
- * file handle for the directory. This file handle may
- * be used in the NFS protocol. This procedure also adds
- * a new entry to the mount list for this client mounting
- * the directory.
- * Unix authentication required.
- */
- fhstatus
- MOUNTPROC_MNT(dirpath) = 1;
-
- /*
- * Returns the list of remotely mounted filesystems. The
- * mountlist contains one entry for each hostname and
- * directory pair.
- */
- mountlist
- MOUNTPROC_DUMP(void) = 2;
-
- /*
- * Removes the mount list entry for the directory
- * Unix authentication required.
- */
- void
- MOUNTPROC_UMNT(dirpath) = 3;
-
- /*
- * Removes all of the mount list entries for this client
- * Unix authentication required.
- */
- void
- MOUNTPROC_UMNTALL(void) = 4;
-
- /*
- * Returns a list of all the exported filesystems, and which
- * machines are allowed to import it.
- */
- exports
- MOUNTPROC_EXPORT(void) = 5;
-
- /*
- * Identical to MOUNTPROC_EXPORT above
- */
- exports
- MOUNTPROC_EXPORTALL(void) = 6;
- } = 1;
-} = 100005;
diff --git a/mount/mount_clnt.c b/mount/mount_clnt.c
deleted file mode 100644
index bc6e5122b..000000000
--- a/mount/mount_clnt.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Please do not edit this file.
- * It was generated using rpcgen.
- */
-
-#include <memory.h> /* for memset */
-#include "mount.h"
-
-/* Default timeout can be changed using clnt_control() */
-static struct timeval TIMEOUT = { 25, 0 };
-
-void *
-mountproc_null_1(void *argp, CLIENT *clnt)
-{
- static char clnt_res;
-
- memset((char *)&clnt_res, 0, sizeof(clnt_res));
- if (clnt_call(clnt, MOUNTPROC_NULL, xdr_void, argp, xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
- return (NULL);
- }
- return ((void *)&clnt_res);
-}
-
-fhstatus *
-mountproc_mnt_1(dirpath *argp, CLIENT *clnt)
-{
- static fhstatus clnt_res;
-
- memset((char *)&clnt_res, 0, sizeof(clnt_res));
- if (clnt_call(clnt, MOUNTPROC_MNT, xdr_dirpath, argp, xdr_fhstatus, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
- return (NULL);
- }
- return (&clnt_res);
-}
-
-mountlist *
-mountproc_dump_1(void *argp, CLIENT *clnt)
-{
- static mountlist clnt_res;
-
- memset((char *)&clnt_res, 0, sizeof(clnt_res));
- if (clnt_call(clnt, MOUNTPROC_DUMP, xdr_void, argp, xdr_mountlist, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
- return (NULL);
- }
- return (&clnt_res);
-}
-
-void *
-mountproc_umnt_1(dirpath *argp, CLIENT *clnt)
-{
- static char clnt_res;
-
- memset((char *)&clnt_res, 0, sizeof(clnt_res));
- if (clnt_call(clnt, MOUNTPROC_UMNT, xdr_dirpath, argp, xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
- return (NULL);
- }
- return ((void *)&clnt_res);
-}
-
-void *
-mountproc_umntall_1(void *argp, CLIENT *clnt)
-{
- static char clnt_res;
-
- memset((char *)&clnt_res, 0, sizeof(clnt_res));
- if (clnt_call(clnt, MOUNTPROC_UMNTALL, xdr_void, argp, xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
- return (NULL);
- }
- return ((void *)&clnt_res);
-}
-
-exports *
-mountproc_export_1(void *argp, CLIENT *clnt)
-{
- static exports clnt_res;
-
- memset((char *)&clnt_res, 0, sizeof(clnt_res));
- if (clnt_call(clnt, MOUNTPROC_EXPORT, xdr_void, argp, xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
- return (NULL);
- }
- return (&clnt_res);
-}
-
-exports *
-mountproc_exportall_1(void *argp, CLIENT *clnt)
-{
- static exports clnt_res;
-
- memset((char *)&clnt_res, 0, sizeof(clnt_res));
- if (clnt_call(clnt, MOUNTPROC_EXPORTALL, xdr_void, argp, xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
- return (NULL);
- }
- return (&clnt_res);
-}
diff --git a/mount/mount_constants.h b/mount/mount_constants.h
new file mode 100644
index 000000000..c0ae49849
--- /dev/null
+++ b/mount/mount_constants.h
@@ -0,0 +1,17 @@
+#define MS_RDONLY 1 /* Mount read-only */
+#define MS_NOSUID 2 /* Ignore suid and sgid bits */
+#define MS_NODEV 4 /* Disallow access to device special files */
+#define MS_NOEXEC 8 /* Disallow program execution */
+#define MS_SYNCHRONOUS 16 /* Writes are synced at once */
+#define MS_REMOUNT 32 /* Alter flags of a mounted FS */
+#define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */
+#define S_WRITE 128 /* Write on file/directory/symlink */
+#define S_APPEND 256 /* Append-only file */
+#define S_IMMUTABLE 512 /* Immutable file */
+#define MS_NOATIME 1024 /* Do not update access times. */
+
+/*
+ * Magic mount flag number. Has to be or-ed to the flag values.
+ */
+#define MS_MGC_VAL 0xC0ED0000 /* magic flag number to indicate "new" flags */
+#define MS_MGC_MSK 0xffff0000 /* magic flag number mask */
diff --git a/mount/mount_xdr.c b/mount/mount_xdr.c
deleted file mode 100644
index be5eb41f1..000000000
--- a/mount/mount_xdr.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Please do not edit this file.
- * It was generated using rpcgen.
- */
-
-#include "mount.h"
-
-bool_t
-xdr_fhandle(XDR *xdrs, fhandle objp)
-{
-
- register long *buf;
-
- if (!xdr_opaque(xdrs, objp, FHSIZE)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_fhstatus(XDR *xdrs, fhstatus *objp)
-{
-
- register long *buf;
-
- if (!xdr_u_int(xdrs, &objp->fhs_status)) {
- return (FALSE);
- }
- switch (objp->fhs_status) {
- case 0:
- if (!xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle)) {
- return (FALSE);
- }
- break;
- default:
- break;
- }
- return (TRUE);
-}
-
-bool_t
-xdr_dirpath(XDR *xdrs, dirpath *objp)
-{
-
- register long *buf;
-
- if (!xdr_string(xdrs, objp, MNTPATHLEN)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_name(XDR *xdrs, name *objp)
-{
-
- register long *buf;
-
- if (!xdr_string(xdrs, objp, MNTNAMLEN)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_mountlist(XDR *xdrs, mountlist *objp)
-{
-
- register long *buf;
-
- if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct mountbody), (xdrproc_t)xdr_mountbody)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_mountbody(XDR *xdrs, mountbody *objp)
-{
-
- register long *buf;
-
- if (!xdr_name(xdrs, &objp->ml_hostname)) {
- return (FALSE);
- }
- if (!xdr_dirpath(xdrs, &objp->ml_directory)) {
- return (FALSE);
- }
- if (!xdr_mountlist(xdrs, &objp->ml_next)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_groups(XDR *xdrs, groups *objp)
-{
-
- register long *buf;
-
- if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct groupnode), (xdrproc_t)xdr_groupnode)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_groupnode(XDR *xdrs, groupnode *objp)
-{
-
- register long *buf;
-
- if (!xdr_name(xdrs, &objp->gr_name)) {
- return (FALSE);
- }
- if (!xdr_groups(xdrs, &objp->gr_next)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_exports(XDR *xdrs, exports *objp)
-{
-
- register long *buf;
-
- if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct exportnode), (xdrproc_t)xdr_exportnode)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_exportnode(XDR *xdrs, exportnode *objp)
-{
-
- register long *buf;
-
- if (!xdr_dirpath(xdrs, &objp->ex_dir)) {
- return (FALSE);
- }
- if (!xdr_groups(xdrs, &objp->ex_groups)) {
- return (FALSE);
- }
- if (!xdr_exports(xdrs, &objp->ex_next)) {
- return (FALSE);
- }
- return (TRUE);
-}
diff --git a/mount/nfs_mount3.h b/mount/nfs_mount3.h
new file mode 100644
index 000000000..e5c2b2fe4
--- /dev/null
+++ b/mount/nfs_mount3.h
@@ -0,0 +1,57 @@
+/*
+ * We want to be able to compile mount on old kernels in such a way
+ * that the binary will work well on more recent kernels.
+ * Thus, if necessary we teach nfsmount.c the structure of new fields
+ * that will come later.
+ */
+#include "nfs_mountversion.h"
+
+#if KERNEL_NFS_MOUNT_VERSION >= 3
+
+/*
+ * The kernel includes are at least as good as this file.
+ * Use them.
+ */
+#include <linux/nfs_mount.h>
+
+#else /* KERNEL_NFS_MOUNT_VERSION < 3 */
+
+/*
+ * We know more than the kernel. Override the kernel defines.
+ * Check at runtime whether the running kernel can handle the new stuff.
+ */
+#define NFS_MOUNT_VERSION 3
+
+struct nfs_mount_data {
+ int version; /* 1 */
+ int fd; /* 1 */
+ struct nfs_fh root; /* 1 */
+ int flags; /* 1 */
+ int rsize; /* 1 */
+ int wsize; /* 1 */
+ int timeo; /* 1 */
+ int retrans; /* 1 */
+ int acregmin; /* 1 */
+ int acregmax; /* 1 */
+ int acdirmin; /* 1 */
+ int acdirmax; /* 1 */
+ struct sockaddr_in addr; /* 1 */
+ char hostname[256]; /* 1 */
+ int namlen; /* 2 */
+ unsigned int bsize; /* 3 */
+};
+
+/* bits in the flags field */
+
+#define NFS_MOUNT_SOFT 0x0001 /* 1 */
+#define NFS_MOUNT_INTR 0x0002 /* 1 */
+#define NFS_MOUNT_SECURE 0x0004 /* 1 */
+#define NFS_MOUNT_POSIX 0x0008 /* 1 */
+#define NFS_MOUNT_NOCTO 0x0010 /* 1 */
+#define NFS_MOUNT_NOAC 0x0020 /* 1 */
+#define NFS_MOUNT_TCP 0x0040 /* 2 */
+#define NFS_MOUNT_VER3 0x0080 /* 3 */
+#define NFS_MOUNT_KERBEROS 0x0100 /* 3 */
+#define NFS_MOUNT_NONLM 0x0200 /* 3 */
+
+#endif
diff --git a/mount/nfsmount.c b/mount/nfsmount.c
index 9be51be02..ee869dc44 100644
--- a/mount/nfsmount.c
+++ b/mount/nfsmount.c
@@ -14,44 +14,87 @@
*
* Wed Feb 8 12:51:48 1995, biro@yggdrasil.com (Ross Biro): allow all port
* numbers to be specified on the command line.
+ *
+ * Fri, 8 Mar 1996 18:01:39, Swen Thuemmler <swen@uni-paderborn.de>:
+ * Omit the call to connect() for Linux version 1.3.11 or later.
*/
/*
* nfsmount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
*/
+#include <unistd.h>
#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <netdb.h>
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <rpc/pmap_clnt.h>
#include <sys/socket.h>
#include <sys/time.h>
-#include <string.h>
-#include <netdb.h>
+#include <sys/utsname.h>
#include <arpa/inet.h>
-#include <errno.h>
#include "sundries.h"
+#include "nfsmount.h"
-#include "mount.h"
-
+#if defined(__GLIBC__)
+#define _LINUX_SOCKET_H
+#endif /* __GLIBC__ */
+#define _I386_BITOPS_H
#include <linux/fs.h>
#include <linux/nfs.h>
-#include <linux/nfs_mount.h>
-
-static char *strndup (char *str, int n) {
- char *ret;
- ret = malloc (n+1);
- if (ret == NULL) {
- perror ("malloc");
- return (NULL);
- }
- strncpy (ret, str, n);
- return (ret);
-}
+#include "nfs_mount3.h"
static char *nfs_strerror(int stat);
+#define MAKE_VERSION(p,q,r) (65536*(p) + 256*(q) + (r))
+
+static int
+linux_version_code(void) {
+ struct utsname my_utsname;
+ int p, q, r;
+
+ if (uname(&my_utsname) == 0) {
+ p = atoi(strtok(my_utsname.release, "."));
+ q = atoi(strtok(NULL, "."));
+ r = atoi(strtok(NULL, "."));
+ return MAKE_VERSION(p,q,r);
+ }
+ return 0;
+}
+
+/*
+ * nfs_mount_version according to the kernel sources seen at compile time.
+ */
+static int nfs_mount_version = KERNEL_NFS_MOUNT_VERSION;
+
+/*
+ * Unfortunately, the kernel prints annoying console messages
+ * in case of an unexpected nfs mount version (instead of
+ * just returning some error). Therefore we'll have to try
+ * 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
+ */
+static void
+find_kernel_nfs_mount_version(void) {
+ int kernel_version = linux_version_code();
+
+ if (kernel_version) {
+ if (kernel_version < MAKE_VERSION(2,1,32))
+ nfs_mount_version = 1;
+ else
+ nfs_mount_version = 3;
+ }
+ if (nfs_mount_version > NFS_MOUNT_VERSION)
+ nfs_mount_version = NFS_MOUNT_VERSION;
+}
+
int nfsmount(const char *spec, const char *node, int *flags,
char **extra_opts, char **mount_opts)
{
@@ -83,6 +126,7 @@ int nfsmount(const char *spec, const char *node, int *flags,
int posix;
int nocto;
int noac;
+ int nolock;
int retry;
int tcp;
int mountprog;
@@ -90,8 +134,15 @@ int nfsmount(const char *spec, const char *node, int *flags,
int nfsprog;
int nfsvers;
+ find_kernel_nfs_mount_version();
+
msock = fsock = -1;
mclient = NULL;
+ if (strlen(spec) >= sizeof(hostdir)) {
+ fprintf(stderr, "mount: "
+ "excessively long host:dir argument\n");
+ goto fail;
+ }
strcpy(hostdir, spec);
if ((s = (strchr(hostdir, ':')))) {
hostname = hostdir;
@@ -104,36 +155,38 @@ int nfsmount(const char *spec, const char *node, int *flags,
goto fail;
}
- if (hostname[0] >= '0' && hostname[0] <= '9') {
- server_addr.sin_family = AF_INET;
- server_addr.sin_addr.s_addr = inet_addr(hostname);
- }
- else if ((hp = gethostbyname(hostname)) == NULL) {
- fprintf(stderr, "mount: can't get address for %s\n", hostname);
- goto fail;
- }
- else {
- server_addr.sin_family = AF_INET;
- memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
+ server_addr.sin_family = AF_INET;
+ if (!inet_aton(hostname, &server_addr.sin_addr)) {
+ if ((hp = gethostbyname(hostname)) == NULL) {
+ fprintf(stderr, "mount: can't get address for %s\n",
+ hostname);
+ goto fail;
+ } else
+ memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length);
}
memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr));
/* add IP address to mtab options for use when unmounting */
+ s = inet_ntoa(server_addr.sin_addr);
old_opts = *extra_opts;
if (!old_opts)
old_opts = "";
+ if (strlen(old_opts) + strlen(s) + 10 >= sizeof(new_opts)) {
+ fprintf(stderr, "mount: "
+ "excessively long option argument\n");
+ goto fail;
+ }
sprintf(new_opts, "%s%saddr=%s",
- old_opts, *old_opts ? "," : "",
- inet_ntoa(server_addr.sin_addr));
- *extra_opts = strdup(new_opts);
-
- /* set default options */
-
- data.rsize = 0; /* let kernel decide */
- data.wsize = 0; /* let kernel decide */
- data.timeo = 7;
+ old_opts, *old_opts ? "," : "", s);
+ *extra_opts = xstrdup(new_opts);
+
+ /* Set default options.
+ * rsize/wsize (and bsize, for ver >= 3) are left 0 in order to
+ * let the kernel decide.
+ * timeo is filled in after we know whether it'll be TCP or UDP. */
+ memset(&data, 0, sizeof(data));
data.retrans = 3;
data.acregmin = 3;
data.acregmax = 60;
@@ -148,6 +201,7 @@ int nfsmount(const char *spec, const char *node, int *flags,
intr = 0;
posix = 0;
nocto = 0;
+ nolock = 0;
noac = 0;
retry = 10000;
tcp = 0;
@@ -194,7 +248,7 @@ int nfsmount(const char *spec, const char *node, int *flags,
else if (!strcmp(opt, "mountport"))
mountport = val;
else if (!strcmp(opt, "mounthost"))
- mounthost=strndup(opteq+1,
+ mounthost=xstrndup(opteq+1,
strcspn(opteq+1," \t\n\r,"));
else if (!strcmp(opt, "mountprog"))
mountprog = val;
@@ -206,10 +260,11 @@ int nfsmount(const char *spec, const char *node, int *flags,
nfsvers = val;
else if (!strcmp(opt, "namlen")) {
#if NFS_MOUNT_VERSION >= 2
- data.namlen = val;
-#else
- printf("Warning: Option namlen is not supported.\n");
+ if (nfs_mount_version >= 2)
+ data.namlen = val;
+ else
#endif
+ printf("Warning: Option namlen is not supported.\n");
}
else if (!strcmp(opt, "addr"))
/* ignore */;
@@ -245,7 +300,12 @@ int nfsmount(const char *spec, const char *node, int *flags,
tcp = val;
else if (!strcmp(opt, "udp"))
tcp = !val;
- else {
+ else if (!strcmp(opt, "lock")) {
+ if (nfs_mount_version >= 3)
+ nolock = !val;
+ else
+ printf("Warning: option nolock is not supported.\n");
+ } else {
printf("unknown nfs mount option: "
"%s%s\n", val ? "" : "no", opt);
goto fail;
@@ -258,9 +318,18 @@ int nfsmount(const char *spec, const char *node, int *flags,
| (nocto ? NFS_MOUNT_NOCTO : 0)
| (noac ? NFS_MOUNT_NOAC : 0);
#if NFS_MOUNT_VERSION >= 2
- data.flags |= (tcp ? NFS_MOUNT_TCP : 0);
+ if (nfs_mount_version >= 2)
+ data.flags |= (tcp ? NFS_MOUNT_TCP : 0);
+#endif
+#if NFS_MOUNT_VERSION >= 3
+ if (nfs_mount_version >= 3)
+ data.flags |= (nolock ? NFS_MOUNT_NONLM : 0);
#endif
+ /* Adjust options if none specified */
+ if (!data.timeo)
+ data.timeo = tcp ? 70 : 7;
+
#ifdef NFS_MOUNT_DEBUG
printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n",
data.rsize, data.wsize, data.timeo, data.retrans);
@@ -285,7 +354,7 @@ int nfsmount(const char *spec, const char *node, int *flags,
#endif
#endif
- data.version = NFS_MOUNT_VERSION;
+ data.version = nfs_mount_version;
*mount_opts = (char *) &data;
if (*flags & MS_REMOUNT)
@@ -336,8 +405,8 @@ int nfsmount(const char *spec, const char *node, int *flags,
/* try to mount hostname:dirname */
clnt_stat = clnt_call(mclient, MOUNTPROC_MNT,
- xdr_dirpath, &dirname,
- xdr_fhstatus, &status,
+ (xdrproc_t) xdr_dirpath, &dirname,
+ (xdrproc_t) xdr_fhstatus, &status,
total_timeout);
if (clnt_stat != RPC_SUCCESS) {
clnt_perror(mclient, "rpc mount");
@@ -355,14 +424,12 @@ int nfsmount(const char *spec, const char *node, int *flags,
/* create nfs socket for kernel */
if (tcp) {
-#if NFS_MOUNT_VERSION >= 2
+ if (nfs_mount_version < 3) {
+ printf("NFS over TCP is not supported.\n");
+ goto fail;
+ }
fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
-#else
- printf("NFS over TCP is not supported.\n");
- goto fail;
-#endif
- }
- else
+ } else
fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (fsock < 0) {
perror("nfs socket");
@@ -387,8 +454,14 @@ int nfsmount(const char *spec, const char *node, int *flags,
printf("using port %d for nfs deamon\n", port);
#endif
server_addr.sin_port = htons(port);
- if (connect(fsock, (struct sockaddr *) &server_addr,
- sizeof (server_addr)) < 0) {
+ /*
+ * connect() the socket for kernels 1.3.10 and below only,
+ * to avoid problems with multihomed hosts.
+ * --Swen
+ */
+ if (linux_version_code() <= 66314
+ && connect(fsock, (struct sockaddr *) &server_addr,
+ sizeof (server_addr)) < 0) {
perror("nfs connect");
goto fail;
}
@@ -418,12 +491,17 @@ fail:
}
if (fsock != -1)
close(fsock);
- return 1;}
+ return 1;
+}
/*
* We need to translate between nfs status return values and
* the local errno values which may not be the same.
+ *
+ * Andreas Schwab <schwab@LS5.informatik.uni-dortmund.de>: change errno:
+ * "after #include <errno.h> the symbol errno is reserved for any use,
+ * it cannot even be used as a struct tag or field name".
*/
#ifndef EDQUOT
@@ -432,7 +510,7 @@ fail:
static struct {
enum nfs_stat stat;
- int errno;
+ int errnum;
} nfs_errtbl[] = {
{ NFS_OK, 0 },
{ NFSERR_PERM, EPERM },
@@ -457,6 +535,9 @@ static struct {
#ifdef EWFLUSH
{ NFSERR_WFLUSH, EWFLUSH },
#endif
+ /* Throw in some NFSv3 values for even more fun (HP returns these) */
+ { 71, EREMOTE },
+
{ -1, EIO }
};
@@ -467,7 +548,7 @@ static char *nfs_strerror(int stat)
for (i = 0; nfs_errtbl[i].stat != -1; i++) {
if (nfs_errtbl[i].stat == stat)
- return strerror(nfs_errtbl[i].errno);
+ return strerror(nfs_errtbl[i].errnum);
}
sprintf(buf, "unknown nfs status return value: %d", stat);
return buf;
diff --git a/mount/rpcsvc/mount.h b/mount/nfsmount.h
index d70ccaf9d..73c71fc68 100644
--- a/mount/rpcsvc/mount.h
+++ b/mount/nfsmount.h
@@ -3,11 +3,47 @@
* It was generated using rpcgen.
*/
-#ifndef _MOUNT_H_RPCGEN
-#define _MOUNT_H_RPCGEN
+#ifndef _NFSMOUNT_H_RPCGEN
+#define _NFSMOUNT_H_RPCGEN
#include <rpc/rpc.h>
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+ */
+
+/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
+#ifndef _rpcsvc_mount_h
+#define _rpcsvc_mount_h
#define MNTPATHLEN 1024
#define MNTNAMLEN 255
#define FHSIZE 32
@@ -132,6 +168,28 @@ bool_t xdr_exportnode();
#endif /* Old Style C */
+struct ppathcnf {
+ int pc_link_max;
+ short pc_max_canon;
+ short pc_max_input;
+ short pc_name_max;
+ short pc_path_max;
+ short pc_pipe_buf;
+ u_char pc_vdisable;
+ char pc_xxx;
+ short pc_mask[2];
+};
+typedef struct ppathcnf ppathcnf;
+#ifdef __cplusplus
+extern "C" bool_t xdr_ppathcnf(XDR *, ppathcnf*);
+#elif __STDC__
+extern bool_t xdr_ppathcnf(XDR *, ppathcnf*);
+#else /* Old Style C */
+bool_t xdr_ppathcnf();
+#endif /* Old Style C */
+
+#endif /*!_rpcsvc_mount_h*/
+
#define MOUNTPROG ((u_long)100005)
#define MOUNTVERS ((u_long)1)
@@ -204,5 +262,64 @@ extern exports * mountproc_export_1_svc();
extern exports * mountproc_exportall_1();
extern exports * mountproc_exportall_1_svc();
#endif /* Old Style C */
+#define MOUNTVERS_POSIX ((u_long)2)
+
+#ifdef __cplusplus
+extern "C" void * mountproc_null_2(void *, CLIENT *);
+extern "C" void * mountproc_null_2_svc(void *, struct svc_req *);
+extern "C" fhstatus * mountproc_mnt_2(dirpath *, CLIENT *);
+extern "C" fhstatus * mountproc_mnt_2_svc(dirpath *, struct svc_req *);
+extern "C" mountlist * mountproc_dump_2(void *, CLIENT *);
+extern "C" mountlist * mountproc_dump_2_svc(void *, struct svc_req *);
+extern "C" void * mountproc_umnt_2(dirpath *, CLIENT *);
+extern "C" void * mountproc_umnt_2_svc(dirpath *, struct svc_req *);
+extern "C" void * mountproc_umntall_2(void *, CLIENT *);
+extern "C" void * mountproc_umntall_2_svc(void *, struct svc_req *);
+extern "C" exports * mountproc_export_2(void *, CLIENT *);
+extern "C" exports * mountproc_export_2_svc(void *, struct svc_req *);
+extern "C" exports * mountproc_exportall_2(void *, CLIENT *);
+extern "C" exports * mountproc_exportall_2_svc(void *, struct svc_req *);
+#define MOUNTPROC_PATHCONF ((u_long)7)
+extern "C" ppathcnf * mountproc_pathconf_2(dirpath *, CLIENT *);
+extern "C" ppathcnf * mountproc_pathconf_2_svc(dirpath *, struct svc_req *);
+
+#elif __STDC__
+extern void * mountproc_null_2(void *, CLIENT *);
+extern void * mountproc_null_2_svc(void *, struct svc_req *);
+extern fhstatus * mountproc_mnt_2(dirpath *, CLIENT *);
+extern fhstatus * mountproc_mnt_2_svc(dirpath *, struct svc_req *);
+extern mountlist * mountproc_dump_2(void *, CLIENT *);
+extern mountlist * mountproc_dump_2_svc(void *, struct svc_req *);
+extern void * mountproc_umnt_2(dirpath *, CLIENT *);
+extern void * mountproc_umnt_2_svc(dirpath *, struct svc_req *);
+extern void * mountproc_umntall_2(void *, CLIENT *);
+extern void * mountproc_umntall_2_svc(void *, struct svc_req *);
+extern exports * mountproc_export_2(void *, CLIENT *);
+extern exports * mountproc_export_2_svc(void *, struct svc_req *);
+extern exports * mountproc_exportall_2(void *, CLIENT *);
+extern exports * mountproc_exportall_2_svc(void *, struct svc_req *);
+#define MOUNTPROC_PATHCONF ((u_long)7)
+extern ppathcnf * mountproc_pathconf_2(dirpath *, CLIENT *);
+extern ppathcnf * mountproc_pathconf_2_svc(dirpath *, struct svc_req *);
+
+#else /* Old Style C */
+extern void * mountproc_null_2();
+extern void * mountproc_null_2_svc();
+extern fhstatus * mountproc_mnt_2();
+extern fhstatus * mountproc_mnt_2_svc();
+extern mountlist * mountproc_dump_2();
+extern mountlist * mountproc_dump_2_svc();
+extern void * mountproc_umnt_2();
+extern void * mountproc_umnt_2_svc();
+extern void * mountproc_umntall_2();
+extern void * mountproc_umntall_2_svc();
+extern exports * mountproc_export_2();
+extern exports * mountproc_export_2_svc();
+extern exports * mountproc_exportall_2();
+extern exports * mountproc_exportall_2_svc();
+#define MOUNTPROC_PATHCONF ((u_long)7)
+extern ppathcnf * mountproc_pathconf_2();
+extern ppathcnf * mountproc_pathconf_2_svc();
+#endif /* Old Style C */
-#endif /* !_MOUNT_H_RPCGEN */
+#endif /* !_NFSMOUNT_H_RPCGEN */
diff --git a/mount/nfsmount.x b/mount/nfsmount.x
new file mode 100644
index 000000000..90590eb2c
--- /dev/null
+++ b/mount/nfsmount.x
@@ -0,0 +1,259 @@
+%/*
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part. Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user or with the express written consent of
+% * Sun Microsystems, Inc.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California 94043
+% */
+
+%/*
+% * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+% */
+%
+%/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
+
+/*
+ * Protocol description for the mount program
+ */
+
+#ifdef RPC_HDR
+%#ifndef _rpcsvc_mount_h
+%#define _rpcsvc_mount_h
+#endif
+
+#ifdef RPC_CLNT
+%#include <string.h> /* for memset() */
+#endif
+
+const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */
+const MNTNAMLEN = 255; /* maximum bytes in a name argument */
+const FHSIZE = 32; /* size in bytes of a file handle */
+
+/*
+ * The fhandle is the file handle that the server passes to the client.
+ * All file operations are done using the file handles to refer to a file
+ * or a directory. The file handle can contain whatever information the
+ * server needs to distinguish an individual file.
+ */
+typedef opaque fhandle[FHSIZE];
+
+/*
+ * If a status of zero is returned, the call completed successfully, and
+ * a file handle for the directory follows. A non-zero status indicates
+ * some sort of error. The status corresponds with UNIX error numbers.
+ */
+union fhstatus switch (unsigned fhs_status) {
+case 0:
+ fhandle fhs_fhandle;
+default:
+ void;
+};
+
+/*
+ * The type dirpath is the pathname of a directory
+ */
+typedef string dirpath<MNTPATHLEN>;
+
+/*
+ * The type name is used for arbitrary names (hostnames, groupnames)
+ */
+typedef string name<MNTNAMLEN>;
+
+/*
+ * A list of who has what mounted
+ */
+typedef struct mountbody *mountlist;
+struct mountbody {
+ name ml_hostname;
+ dirpath ml_directory;
+ mountlist ml_next;
+};
+
+/*
+ * A list of netgroups
+ */
+typedef struct groupnode *groups;
+struct groupnode {
+ name gr_name;
+ groups gr_next;
+};
+
+/*
+ * A list of what is exported and to whom
+ */
+typedef struct exportnode *exports;
+struct exportnode {
+ dirpath ex_dir;
+ groups ex_groups;
+ exports ex_next;
+};
+
+/*
+ * POSIX pathconf information
+ */
+struct ppathcnf {
+ int pc_link_max; /* max links allowed */
+ short pc_max_canon; /* max line len for a tty */
+ short pc_max_input; /* input a tty can eat all at once */
+ short pc_name_max; /* max file name length (dir entry) */
+ short pc_path_max; /* max path name length (/x/y/x/.. ) */
+ short pc_pipe_buf; /* size of a pipe (bytes) */
+ u_char pc_vdisable; /* safe char to turn off c_cc[i] */
+ char pc_xxx; /* alignment padding; cc_t == char */
+ short pc_mask[2]; /* validity and boolean bits */
+};
+
+program MOUNTPROG {
+ /*
+ * Version one of the mount protocol communicates with version two
+ * of the NFS protocol. The only connecting point is the fhandle
+ * structure, which is the same for both protocols.
+ */
+ version MOUNTVERS {
+ /*
+ * Does no work. It is made available in all RPC services
+ * to allow server reponse testing and timing
+ */
+ void
+ MOUNTPROC_NULL(void) = 0;
+
+ /*
+ * If fhs_status is 0, then fhs_fhandle contains the
+ * file handle for the directory. This file handle may
+ * be used in the NFS protocol. This procedure also adds
+ * a new entry to the mount list for this client mounting
+ * the directory.
+ * Unix authentication required.
+ */
+ fhstatus
+ MOUNTPROC_MNT(dirpath) = 1;
+
+ /*
+ * Returns the list of remotely mounted filesystems. The
+ * mountlist contains one entry for each hostname and
+ * directory pair.
+ */
+ mountlist
+ MOUNTPROC_DUMP(void) = 2;
+
+ /*
+ * Removes the mount list entry for the directory
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNT(dirpath) = 3;
+
+ /*
+ * Removes all of the mount list entries for this client
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNTALL(void) = 4;
+
+ /*
+ * Returns a list of all the exported filesystems, and which
+ * machines are allowed to import it.
+ */
+ exports
+ MOUNTPROC_EXPORT(void) = 5;
+
+ /*
+ * Identical to MOUNTPROC_EXPORT above
+ */
+ exports
+ MOUNTPROC_EXPORTALL(void) = 6;
+ } = 1;
+
+ /*
+ * Version two of the mount protocol communicates with version two
+ * of the NFS protocol.
+ * The only difference from version one is the addition of a POSIX
+ * pathconf call.
+ */
+ version MOUNTVERS_POSIX {
+ /*
+ * Does no work. It is made available in all RPC services
+ * to allow server reponse testing and timing
+ */
+ void
+ MOUNTPROC_NULL(void) = 0;
+
+ /*
+ * If fhs_status is 0, then fhs_fhandle contains the
+ * file handle for the directory. This file handle may
+ * be used in the NFS protocol. This procedure also adds
+ * a new entry to the mount list for this client mounting
+ * the directory.
+ * Unix authentication required.
+ */
+ fhstatus
+ MOUNTPROC_MNT(dirpath) = 1;
+
+ /*
+ * Returns the list of remotely mounted filesystems. The
+ * mountlist contains one entry for each hostname and
+ * directory pair.
+ */
+ mountlist
+ MOUNTPROC_DUMP(void) = 2;
+
+ /*
+ * Removes the mount list entry for the directory
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNT(dirpath) = 3;
+
+ /*
+ * Removes all of the mount list entries for this client
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNTALL(void) = 4;
+
+ /*
+ * Returns a list of all the exported filesystems, and which
+ * machines are allowed to import it.
+ */
+ exports
+ MOUNTPROC_EXPORT(void) = 5;
+
+ /*
+ * Identical to MOUNTPROC_EXPORT above
+ */
+ exports
+ MOUNTPROC_EXPORTALL(void) = 6;
+
+ /*
+ * POSIX pathconf info (Sun hack)
+ */
+ ppathcnf
+ MOUNTPROC_PATHCONF(dirpath) = 7;
+ } = 2;
+} = 100005;
+
+#ifdef RPC_HDR
+%#endif /*!_rpcsvc_mount_h*/
+#endif
diff --git a/mount/nfsmount_clnt.c b/mount/nfsmount_clnt.c
new file mode 100644
index 000000000..a77f4c5eb
--- /dev/null
+++ b/mount/nfsmount_clnt.c
@@ -0,0 +1,255 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "nfsmount.h"
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+ */
+
+/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
+
+#include <string.h> /* for memset() */
+
+/* Default timeout can be changed using clnt_control() */
+static struct timeval TIMEOUT = { 25, 0 };
+
+void *
+mountproc_null_1(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static char clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((void *)&clnt_res);
+}
+
+fhstatus *
+mountproc_mnt_1(argp, clnt)
+ dirpath *argp;
+ CLIENT *clnt;
+{
+ static fhstatus clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, argp, (xdrproc_t) xdr_fhstatus, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+mountlist *
+mountproc_dump_1(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static mountlist clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_mountlist, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+void *
+mountproc_umnt_1(argp, clnt)
+ dirpath *argp;
+ CLIENT *clnt;
+{
+ static char clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((void *)&clnt_res);
+}
+
+void *
+mountproc_umntall_1(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static char clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((void *)&clnt_res);
+}
+
+exports *
+mountproc_export_1(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static exports clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+exports *
+mountproc_exportall_1(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static exports clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+void *
+mountproc_null_2(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static char clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((void *)&clnt_res);
+}
+
+fhstatus *
+mountproc_mnt_2(argp, clnt)
+ dirpath *argp;
+ CLIENT *clnt;
+{
+ static fhstatus clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, argp, (xdrproc_t) xdr_fhstatus, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+mountlist *
+mountproc_dump_2(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static mountlist clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_mountlist, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+void *
+mountproc_umnt_2(argp, clnt)
+ dirpath *argp;
+ CLIENT *clnt;
+{
+ static char clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((void *)&clnt_res);
+}
+
+void *
+mountproc_umntall_2(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static char clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((void *)&clnt_res);
+}
+
+exports *
+mountproc_export_2(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static exports clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+exports *
+mountproc_exportall_2(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static exports clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+ppathcnf *
+mountproc_pathconf_2(argp, clnt)
+ dirpath *argp;
+ CLIENT *clnt;
+{
+ static ppathcnf clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_PATHCONF, (xdrproc_t) xdr_dirpath, argp, (xdrproc_t) xdr_ppathcnf, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
diff --git a/mount/nfsmount_xdr.c b/mount/nfsmount_xdr.c
new file mode 100644
index 000000000..6f539c24f
--- /dev/null
+++ b/mount/nfsmount_xdr.c
@@ -0,0 +1,351 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "nfsmount.h"
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+ */
+
+/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
+
+bool_t
+xdr_fhandle(xdrs, objp)
+ XDR *xdrs;
+ fhandle objp;
+{
+
+ register long *buf;
+
+ if (!xdr_opaque(xdrs, objp, FHSIZE)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_fhstatus(xdrs, objp)
+ XDR *xdrs;
+ fhstatus *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_u_int(xdrs, &objp->fhs_status)) {
+ return (FALSE);
+ }
+ switch (objp->fhs_status) {
+ case 0:
+ if (!xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle)) {
+ return (FALSE);
+ }
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_dirpath(xdrs, objp)
+ XDR *xdrs;
+ dirpath *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_string(xdrs, objp, MNTPATHLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_name(xdrs, objp)
+ XDR *xdrs;
+ name *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_string(xdrs, objp, MNTNAMLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_mountlist(xdrs, objp)
+ XDR *xdrs;
+ mountlist *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct mountbody), (xdrproc_t)xdr_mountbody)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_mountbody(xdrs, objp)
+ XDR *xdrs;
+ mountbody *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_name(xdrs, &objp->ml_hostname)) {
+ return (FALSE);
+ }
+ if (!xdr_dirpath(xdrs, &objp->ml_directory)) {
+ return (FALSE);
+ }
+ if (!xdr_mountlist(xdrs, &objp->ml_next)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_groups(xdrs, objp)
+ XDR *xdrs;
+ groups *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct groupnode), (xdrproc_t)xdr_groupnode)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_groupnode(xdrs, objp)
+ XDR *xdrs;
+ groupnode *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_name(xdrs, &objp->gr_name)) {
+ return (FALSE);
+ }
+ if (!xdr_groups(xdrs, &objp->gr_next)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_exports(xdrs, objp)
+ XDR *xdrs;
+ exports *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct exportnode), (xdrproc_t)xdr_exportnode)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_exportnode(xdrs, objp)
+ XDR *xdrs;
+ exportnode *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_dirpath(xdrs, &objp->ex_dir)) {
+ return (FALSE);
+ }
+ if (!xdr_groups(xdrs, &objp->ex_groups)) {
+ return (FALSE);
+ }
+ if (!xdr_exports(xdrs, &objp->ex_next)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_ppathcnf(xdrs, objp)
+ XDR *xdrs;
+ ppathcnf *objp;
+{
+
+ register long *buf;
+
+ int i;
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ buf = XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_int(xdrs, &objp->pc_link_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_canon)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_input)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_name_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_path_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ IXDR_PUT_LONG(buf,objp->pc_link_max);
+ IXDR_PUT_SHORT(buf,objp->pc_max_canon);
+ IXDR_PUT_SHORT(buf,objp->pc_max_input);
+ IXDR_PUT_SHORT(buf,objp->pc_name_max);
+ IXDR_PUT_SHORT(buf,objp->pc_path_max);
+ IXDR_PUT_SHORT(buf,objp->pc_pipe_buf);
+ }
+ if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
+ return (FALSE);
+ }
+ if (!xdr_char(xdrs, &objp->pc_xxx)) {
+ return (FALSE);
+ }
+ buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ { register short *genp;
+ for ( i = 0,genp=objp->pc_mask;
+ i < 2; i++){
+ IXDR_PUT_SHORT(buf,*genp++);
+ }
+ };
+ }
+
+ return (TRUE);
+ } else if (xdrs->x_op == XDR_DECODE) {
+ buf = XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_int(xdrs, &objp->pc_link_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_canon)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_input)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_name_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_path_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ objp->pc_link_max = IXDR_GET_LONG(buf);
+ objp->pc_max_canon = IXDR_GET_SHORT(buf);
+ objp->pc_max_input = IXDR_GET_SHORT(buf);
+ objp->pc_name_max = IXDR_GET_SHORT(buf);
+ objp->pc_path_max = IXDR_GET_SHORT(buf);
+ objp->pc_pipe_buf = IXDR_GET_SHORT(buf);
+ }
+ if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
+ return (FALSE);
+ }
+ if (!xdr_char(xdrs, &objp->pc_xxx)) {
+ return (FALSE);
+ }
+ buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ { register short *genp;
+ for ( i = 0,genp=objp->pc_mask;
+ i < 2; i++){
+ *genp++ = IXDR_GET_SHORT(buf);
+ }
+ };
+ }
+ return(TRUE);
+ }
+
+ if (!xdr_int(xdrs, &objp->pc_link_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_canon)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_input)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_name_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_path_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
+ return (FALSE);
+ }
+ if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
+ return (FALSE);
+ }
+ if (!xdr_char(xdrs, &objp->pc_xxx)) {
+ return (FALSE);
+ }
+ if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
diff --git a/mount/realpath.c b/mount/realpath.c
index 4ea46a311..4214cad72 100644
--- a/mount/realpath.c
+++ b/mount/realpath.c
@@ -13,8 +13,11 @@
* GNU Library Public License for more details.
*/
+#define HAVE_GETCWD
+
/*
- * realpath.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
+ * This routine is part of libc. We include it nevertheless,
+ * since the libc version has some security flaws.
*/
#ifdef __linux__
@@ -79,9 +82,14 @@ char *resolved_path;
int n;
/* Make a copy of the source path since we may need to modify it. */
+ if (strlen(path) >= PATH_MAX) {
+ errno = ENAMETOOLONG;
+ return NULL;
+ }
strcpy(copy_path, path);
path = copy_path;
max_path = copy_path + PATH_MAX - 2;
+
/* If it's a relative pathname use getwd for starters. */
if (*path != '/') {
#ifdef HAVE_GETCWD
diff --git a/mount/rpcsvc/mount.x b/mount/rpcsvc/mount.x
deleted file mode 100644
index 7e0d7f3ad..000000000
--- a/mount/rpcsvc/mount.x
+++ /dev/null
@@ -1,161 +0,0 @@
-/* @(#)mount.x 2.1 88/08/01 4.0 RPCSRC */
-/* @(#)mount.x 1.2 87/09/18 Copyr 1987 Sun Micro */
-
-/*
- * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
- * unrestricted use provided that this legend is included on all tape
- * media and as a part of the software program in whole or part. Users
- * may copy or modify Sun RPC without charge, but are not authorized
- * to license or distribute it to anyone else except as part of a product or
- * program developed by the user.
- *
- * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
- * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
- *
- * Sun RPC is provided with no support and without any obligation on the
- * part of Sun Microsystems, Inc. to assist in its use, correction,
- * modification or enhancement.
- *
- * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
- * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
- * OR ANY PART THEREOF.
- *
- * In no event will Sun Microsystems, Inc. be liable for any lost revenue
- * or profits or other special, indirect and consequential damages, even if
- * Sun has been advised of the possibility of such damages.
- *
- * Sun Microsystems, Inc.
- * 2550 Garcia Avenue
- * Mountain View, California 94043
- */
-
-/*
- * Protocol description for the mount program
- */
-
-
-const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */
-const MNTNAMLEN = 255; /* maximum bytes in a name argument */
-const FHSIZE = 32; /* size in bytes of a file handle */
-
-/*
- * The fhandle is the file handle that the server passes to the client.
- * All file operations are done using the file handles to refer to a file
- * or a directory. The file handle can contain whatever information the
- * server needs to distinguish an individual file.
- */
-typedef opaque fhandle[FHSIZE];
-
-/*
- * If a status of zero is returned, the call completed successfully, and
- * a file handle for the directory follows. A non-zero status indicates
- * some sort of error. The status corresponds with UNIX error numbers.
- */
-union fhstatus switch (unsigned fhs_status) {
-case 0:
- fhandle fhs_fhandle;
-default:
- void;
-};
-
-/*
- * The type dirpath is the pathname of a directory
- */
-typedef string dirpath<MNTPATHLEN>;
-
-/*
- * The type name is used for arbitrary names (hostnames, groupnames)
- */
-typedef string name<MNTNAMLEN>;
-
-/*
- * A list of who has what mounted
- */
-typedef struct mountbody *mountlist;
-struct mountbody {
- name ml_hostname;
- dirpath ml_directory;
- mountlist ml_next;
-};
-
-/*
- * A list of netgroups
- */
-typedef struct groupnode *groups;
-struct groupnode {
- name gr_name;
- groups gr_next;
-};
-
-/*
- * A list of what is exported and to whom
- */
-typedef struct exportnode *exports;
-struct exportnode {
- dirpath ex_dir;
- groups ex_groups;
- exports ex_next;
-};
-
-program MOUNTPROG {
- /*
- * Version one of the mount protocol communicates with version two
- * of the NFS protocol. The only connecting point is the fhandle
- * structure, which is the same for both protocols.
- */
- version MOUNTVERS {
- /*
- * Does no work. It is made available in all RPC services
- * to allow server reponse testing and timing
- */
- void
- MOUNTPROC_NULL(void) = 0;
-
- /*
- * If fhs_status is 0, then fhs_fhandle contains the
- * file handle for the directory. This file handle may
- * be used in the NFS protocol. This procedure also adds
- * a new entry to the mount list for this client mounting
- * the directory.
- * Unix authentication required.
- */
- fhstatus
- MOUNTPROC_MNT(dirpath) = 1;
-
- /*
- * Returns the list of remotely mounted filesystems. The
- * mountlist contains one entry for each hostname and
- * directory pair.
- */
- mountlist
- MOUNTPROC_DUMP(void) = 2;
-
- /*
- * Removes the mount list entry for the directory
- * Unix authentication required.
- */
- void
- MOUNTPROC_UMNT(dirpath) = 3;
-
- /*
- * Removes all of the mount list entries for this client
- * Unix authentication required.
- */
- void
- MOUNTPROC_UMNTALL(void) = 4;
-
- /*
- * Returns a list of all the exported filesystems, and which
- * machines are allowed to import it.
- */
- exports
- MOUNTPROC_EXPORT(void) = 5;
-
- /*
- * Identical to MOUNTPROC_EXPORT above
- */
- exports
- MOUNTPROC_EXPORTALL(void) = 6;
- } = 1;
-} = 100005;
diff --git a/mount/rpcsvc/mount_clnt.c b/mount/rpcsvc/mount_clnt.c
deleted file mode 100644
index bc6e5122b..000000000
--- a/mount/rpcsvc/mount_clnt.c
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * Please do not edit this file.
- * It was generated using rpcgen.
- */
-
-#include <memory.h> /* for memset */
-#include "mount.h"
-
-/* Default timeout can be changed using clnt_control() */
-static struct timeval TIMEOUT = { 25, 0 };
-
-void *
-mountproc_null_1(void *argp, CLIENT *clnt)
-{
- static char clnt_res;
-
- memset((char *)&clnt_res, 0, sizeof(clnt_res));
- if (clnt_call(clnt, MOUNTPROC_NULL, xdr_void, argp, xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
- return (NULL);
- }
- return ((void *)&clnt_res);
-}
-
-fhstatus *
-mountproc_mnt_1(dirpath *argp, CLIENT *clnt)
-{
- static fhstatus clnt_res;
-
- memset((char *)&clnt_res, 0, sizeof(clnt_res));
- if (clnt_call(clnt, MOUNTPROC_MNT, xdr_dirpath, argp, xdr_fhstatus, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
- return (NULL);
- }
- return (&clnt_res);
-}
-
-mountlist *
-mountproc_dump_1(void *argp, CLIENT *clnt)
-{
- static mountlist clnt_res;
-
- memset((char *)&clnt_res, 0, sizeof(clnt_res));
- if (clnt_call(clnt, MOUNTPROC_DUMP, xdr_void, argp, xdr_mountlist, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
- return (NULL);
- }
- return (&clnt_res);
-}
-
-void *
-mountproc_umnt_1(dirpath *argp, CLIENT *clnt)
-{
- static char clnt_res;
-
- memset((char *)&clnt_res, 0, sizeof(clnt_res));
- if (clnt_call(clnt, MOUNTPROC_UMNT, xdr_dirpath, argp, xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
- return (NULL);
- }
- return ((void *)&clnt_res);
-}
-
-void *
-mountproc_umntall_1(void *argp, CLIENT *clnt)
-{
- static char clnt_res;
-
- memset((char *)&clnt_res, 0, sizeof(clnt_res));
- if (clnt_call(clnt, MOUNTPROC_UMNTALL, xdr_void, argp, xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
- return (NULL);
- }
- return ((void *)&clnt_res);
-}
-
-exports *
-mountproc_export_1(void *argp, CLIENT *clnt)
-{
- static exports clnt_res;
-
- memset((char *)&clnt_res, 0, sizeof(clnt_res));
- if (clnt_call(clnt, MOUNTPROC_EXPORT, xdr_void, argp, xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
- return (NULL);
- }
- return (&clnt_res);
-}
-
-exports *
-mountproc_exportall_1(void *argp, CLIENT *clnt)
-{
- static exports clnt_res;
-
- memset((char *)&clnt_res, 0, sizeof(clnt_res));
- if (clnt_call(clnt, MOUNTPROC_EXPORTALL, xdr_void, argp, xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
- return (NULL);
- }
- return (&clnt_res);
-}
diff --git a/mount/rpcsvc/mount_xdr.c b/mount/rpcsvc/mount_xdr.c
deleted file mode 100644
index be5eb41f1..000000000
--- a/mount/rpcsvc/mount_xdr.c
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * Please do not edit this file.
- * It was generated using rpcgen.
- */
-
-#include "mount.h"
-
-bool_t
-xdr_fhandle(XDR *xdrs, fhandle objp)
-{
-
- register long *buf;
-
- if (!xdr_opaque(xdrs, objp, FHSIZE)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_fhstatus(XDR *xdrs, fhstatus *objp)
-{
-
- register long *buf;
-
- if (!xdr_u_int(xdrs, &objp->fhs_status)) {
- return (FALSE);
- }
- switch (objp->fhs_status) {
- case 0:
- if (!xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle)) {
- return (FALSE);
- }
- break;
- default:
- break;
- }
- return (TRUE);
-}
-
-bool_t
-xdr_dirpath(XDR *xdrs, dirpath *objp)
-{
-
- register long *buf;
-
- if (!xdr_string(xdrs, objp, MNTPATHLEN)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_name(XDR *xdrs, name *objp)
-{
-
- register long *buf;
-
- if (!xdr_string(xdrs, objp, MNTNAMLEN)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_mountlist(XDR *xdrs, mountlist *objp)
-{
-
- register long *buf;
-
- if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct mountbody), (xdrproc_t)xdr_mountbody)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_mountbody(XDR *xdrs, mountbody *objp)
-{
-
- register long *buf;
-
- if (!xdr_name(xdrs, &objp->ml_hostname)) {
- return (FALSE);
- }
- if (!xdr_dirpath(xdrs, &objp->ml_directory)) {
- return (FALSE);
- }
- if (!xdr_mountlist(xdrs, &objp->ml_next)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_groups(XDR *xdrs, groups *objp)
-{
-
- register long *buf;
-
- if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct groupnode), (xdrproc_t)xdr_groupnode)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_groupnode(XDR *xdrs, groupnode *objp)
-{
-
- register long *buf;
-
- if (!xdr_name(xdrs, &objp->gr_name)) {
- return (FALSE);
- }
- if (!xdr_groups(xdrs, &objp->gr_next)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_exports(XDR *xdrs, exports *objp)
-{
-
- register long *buf;
-
- if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct exportnode), (xdrproc_t)xdr_exportnode)) {
- return (FALSE);
- }
- return (TRUE);
-}
-
-bool_t
-xdr_exportnode(XDR *xdrs, exportnode *objp)
-{
-
- register long *buf;
-
- if (!xdr_dirpath(xdrs, &objp->ex_dir)) {
- return (FALSE);
- }
- if (!xdr_groups(xdrs, &objp->ex_groups)) {
- return (FALSE);
- }
- if (!xdr_exports(xdrs, &objp->ex_next)) {
- return (FALSE);
- }
- return (TRUE);
-}
diff --git a/mount/mount.h b/mount/rpcsvc/nfsmount.h
index d70ccaf9d..73c71fc68 100644
--- a/mount/mount.h
+++ b/mount/rpcsvc/nfsmount.h
@@ -3,11 +3,47 @@
* It was generated using rpcgen.
*/
-#ifndef _MOUNT_H_RPCGEN
-#define _MOUNT_H_RPCGEN
+#ifndef _NFSMOUNT_H_RPCGEN
+#define _NFSMOUNT_H_RPCGEN
#include <rpc/rpc.h>
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+ */
+
+/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
+#ifndef _rpcsvc_mount_h
+#define _rpcsvc_mount_h
#define MNTPATHLEN 1024
#define MNTNAMLEN 255
#define FHSIZE 32
@@ -132,6 +168,28 @@ bool_t xdr_exportnode();
#endif /* Old Style C */
+struct ppathcnf {
+ int pc_link_max;
+ short pc_max_canon;
+ short pc_max_input;
+ short pc_name_max;
+ short pc_path_max;
+ short pc_pipe_buf;
+ u_char pc_vdisable;
+ char pc_xxx;
+ short pc_mask[2];
+};
+typedef struct ppathcnf ppathcnf;
+#ifdef __cplusplus
+extern "C" bool_t xdr_ppathcnf(XDR *, ppathcnf*);
+#elif __STDC__
+extern bool_t xdr_ppathcnf(XDR *, ppathcnf*);
+#else /* Old Style C */
+bool_t xdr_ppathcnf();
+#endif /* Old Style C */
+
+#endif /*!_rpcsvc_mount_h*/
+
#define MOUNTPROG ((u_long)100005)
#define MOUNTVERS ((u_long)1)
@@ -204,5 +262,64 @@ extern exports * mountproc_export_1_svc();
extern exports * mountproc_exportall_1();
extern exports * mountproc_exportall_1_svc();
#endif /* Old Style C */
+#define MOUNTVERS_POSIX ((u_long)2)
+
+#ifdef __cplusplus
+extern "C" void * mountproc_null_2(void *, CLIENT *);
+extern "C" void * mountproc_null_2_svc(void *, struct svc_req *);
+extern "C" fhstatus * mountproc_mnt_2(dirpath *, CLIENT *);
+extern "C" fhstatus * mountproc_mnt_2_svc(dirpath *, struct svc_req *);
+extern "C" mountlist * mountproc_dump_2(void *, CLIENT *);
+extern "C" mountlist * mountproc_dump_2_svc(void *, struct svc_req *);
+extern "C" void * mountproc_umnt_2(dirpath *, CLIENT *);
+extern "C" void * mountproc_umnt_2_svc(dirpath *, struct svc_req *);
+extern "C" void * mountproc_umntall_2(void *, CLIENT *);
+extern "C" void * mountproc_umntall_2_svc(void *, struct svc_req *);
+extern "C" exports * mountproc_export_2(void *, CLIENT *);
+extern "C" exports * mountproc_export_2_svc(void *, struct svc_req *);
+extern "C" exports * mountproc_exportall_2(void *, CLIENT *);
+extern "C" exports * mountproc_exportall_2_svc(void *, struct svc_req *);
+#define MOUNTPROC_PATHCONF ((u_long)7)
+extern "C" ppathcnf * mountproc_pathconf_2(dirpath *, CLIENT *);
+extern "C" ppathcnf * mountproc_pathconf_2_svc(dirpath *, struct svc_req *);
+
+#elif __STDC__
+extern void * mountproc_null_2(void *, CLIENT *);
+extern void * mountproc_null_2_svc(void *, struct svc_req *);
+extern fhstatus * mountproc_mnt_2(dirpath *, CLIENT *);
+extern fhstatus * mountproc_mnt_2_svc(dirpath *, struct svc_req *);
+extern mountlist * mountproc_dump_2(void *, CLIENT *);
+extern mountlist * mountproc_dump_2_svc(void *, struct svc_req *);
+extern void * mountproc_umnt_2(dirpath *, CLIENT *);
+extern void * mountproc_umnt_2_svc(dirpath *, struct svc_req *);
+extern void * mountproc_umntall_2(void *, CLIENT *);
+extern void * mountproc_umntall_2_svc(void *, struct svc_req *);
+extern exports * mountproc_export_2(void *, CLIENT *);
+extern exports * mountproc_export_2_svc(void *, struct svc_req *);
+extern exports * mountproc_exportall_2(void *, CLIENT *);
+extern exports * mountproc_exportall_2_svc(void *, struct svc_req *);
+#define MOUNTPROC_PATHCONF ((u_long)7)
+extern ppathcnf * mountproc_pathconf_2(dirpath *, CLIENT *);
+extern ppathcnf * mountproc_pathconf_2_svc(dirpath *, struct svc_req *);
+
+#else /* Old Style C */
+extern void * mountproc_null_2();
+extern void * mountproc_null_2_svc();
+extern fhstatus * mountproc_mnt_2();
+extern fhstatus * mountproc_mnt_2_svc();
+extern mountlist * mountproc_dump_2();
+extern mountlist * mountproc_dump_2_svc();
+extern void * mountproc_umnt_2();
+extern void * mountproc_umnt_2_svc();
+extern void * mountproc_umntall_2();
+extern void * mountproc_umntall_2_svc();
+extern exports * mountproc_export_2();
+extern exports * mountproc_export_2_svc();
+extern exports * mountproc_exportall_2();
+extern exports * mountproc_exportall_2_svc();
+#define MOUNTPROC_PATHCONF ((u_long)7)
+extern ppathcnf * mountproc_pathconf_2();
+extern ppathcnf * mountproc_pathconf_2_svc();
+#endif /* Old Style C */
-#endif /* !_MOUNT_H_RPCGEN */
+#endif /* !_NFSMOUNT_H_RPCGEN */
diff --git a/mount/rpcsvc/nfsmount.x b/mount/rpcsvc/nfsmount.x
new file mode 100644
index 000000000..90590eb2c
--- /dev/null
+++ b/mount/rpcsvc/nfsmount.x
@@ -0,0 +1,259 @@
+%/*
+% * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+% * unrestricted use provided that this legend is included on all tape
+% * media and as a part of the software program in whole or part. Users
+% * may copy or modify Sun RPC without charge, but are not authorized
+% * to license or distribute it to anyone else except as part of a product or
+% * program developed by the user or with the express written consent of
+% * Sun Microsystems, Inc.
+% *
+% * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+% * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+% * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+% *
+% * Sun RPC is provided with no support and without any obligation on the
+% * part of Sun Microsystems, Inc. to assist in its use, correction,
+% * modification or enhancement.
+% *
+% * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+% * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+% * OR ANY PART THEREOF.
+% *
+% * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+% * or profits or other special, indirect and consequential damages, even if
+% * Sun has been advised of the possibility of such damages.
+% *
+% * Sun Microsystems, Inc.
+% * 2550 Garcia Avenue
+% * Mountain View, California 94043
+% */
+
+%/*
+% * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+% */
+%
+%/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
+
+/*
+ * Protocol description for the mount program
+ */
+
+#ifdef RPC_HDR
+%#ifndef _rpcsvc_mount_h
+%#define _rpcsvc_mount_h
+#endif
+
+#ifdef RPC_CLNT
+%#include <string.h> /* for memset() */
+#endif
+
+const MNTPATHLEN = 1024; /* maximum bytes in a pathname argument */
+const MNTNAMLEN = 255; /* maximum bytes in a name argument */
+const FHSIZE = 32; /* size in bytes of a file handle */
+
+/*
+ * The fhandle is the file handle that the server passes to the client.
+ * All file operations are done using the file handles to refer to a file
+ * or a directory. The file handle can contain whatever information the
+ * server needs to distinguish an individual file.
+ */
+typedef opaque fhandle[FHSIZE];
+
+/*
+ * If a status of zero is returned, the call completed successfully, and
+ * a file handle for the directory follows. A non-zero status indicates
+ * some sort of error. The status corresponds with UNIX error numbers.
+ */
+union fhstatus switch (unsigned fhs_status) {
+case 0:
+ fhandle fhs_fhandle;
+default:
+ void;
+};
+
+/*
+ * The type dirpath is the pathname of a directory
+ */
+typedef string dirpath<MNTPATHLEN>;
+
+/*
+ * The type name is used for arbitrary names (hostnames, groupnames)
+ */
+typedef string name<MNTNAMLEN>;
+
+/*
+ * A list of who has what mounted
+ */
+typedef struct mountbody *mountlist;
+struct mountbody {
+ name ml_hostname;
+ dirpath ml_directory;
+ mountlist ml_next;
+};
+
+/*
+ * A list of netgroups
+ */
+typedef struct groupnode *groups;
+struct groupnode {
+ name gr_name;
+ groups gr_next;
+};
+
+/*
+ * A list of what is exported and to whom
+ */
+typedef struct exportnode *exports;
+struct exportnode {
+ dirpath ex_dir;
+ groups ex_groups;
+ exports ex_next;
+};
+
+/*
+ * POSIX pathconf information
+ */
+struct ppathcnf {
+ int pc_link_max; /* max links allowed */
+ short pc_max_canon; /* max line len for a tty */
+ short pc_max_input; /* input a tty can eat all at once */
+ short pc_name_max; /* max file name length (dir entry) */
+ short pc_path_max; /* max path name length (/x/y/x/.. ) */
+ short pc_pipe_buf; /* size of a pipe (bytes) */
+ u_char pc_vdisable; /* safe char to turn off c_cc[i] */
+ char pc_xxx; /* alignment padding; cc_t == char */
+ short pc_mask[2]; /* validity and boolean bits */
+};
+
+program MOUNTPROG {
+ /*
+ * Version one of the mount protocol communicates with version two
+ * of the NFS protocol. The only connecting point is the fhandle
+ * structure, which is the same for both protocols.
+ */
+ version MOUNTVERS {
+ /*
+ * Does no work. It is made available in all RPC services
+ * to allow server reponse testing and timing
+ */
+ void
+ MOUNTPROC_NULL(void) = 0;
+
+ /*
+ * If fhs_status is 0, then fhs_fhandle contains the
+ * file handle for the directory. This file handle may
+ * be used in the NFS protocol. This procedure also adds
+ * a new entry to the mount list for this client mounting
+ * the directory.
+ * Unix authentication required.
+ */
+ fhstatus
+ MOUNTPROC_MNT(dirpath) = 1;
+
+ /*
+ * Returns the list of remotely mounted filesystems. The
+ * mountlist contains one entry for each hostname and
+ * directory pair.
+ */
+ mountlist
+ MOUNTPROC_DUMP(void) = 2;
+
+ /*
+ * Removes the mount list entry for the directory
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNT(dirpath) = 3;
+
+ /*
+ * Removes all of the mount list entries for this client
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNTALL(void) = 4;
+
+ /*
+ * Returns a list of all the exported filesystems, and which
+ * machines are allowed to import it.
+ */
+ exports
+ MOUNTPROC_EXPORT(void) = 5;
+
+ /*
+ * Identical to MOUNTPROC_EXPORT above
+ */
+ exports
+ MOUNTPROC_EXPORTALL(void) = 6;
+ } = 1;
+
+ /*
+ * Version two of the mount protocol communicates with version two
+ * of the NFS protocol.
+ * The only difference from version one is the addition of a POSIX
+ * pathconf call.
+ */
+ version MOUNTVERS_POSIX {
+ /*
+ * Does no work. It is made available in all RPC services
+ * to allow server reponse testing and timing
+ */
+ void
+ MOUNTPROC_NULL(void) = 0;
+
+ /*
+ * If fhs_status is 0, then fhs_fhandle contains the
+ * file handle for the directory. This file handle may
+ * be used in the NFS protocol. This procedure also adds
+ * a new entry to the mount list for this client mounting
+ * the directory.
+ * Unix authentication required.
+ */
+ fhstatus
+ MOUNTPROC_MNT(dirpath) = 1;
+
+ /*
+ * Returns the list of remotely mounted filesystems. The
+ * mountlist contains one entry for each hostname and
+ * directory pair.
+ */
+ mountlist
+ MOUNTPROC_DUMP(void) = 2;
+
+ /*
+ * Removes the mount list entry for the directory
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNT(dirpath) = 3;
+
+ /*
+ * Removes all of the mount list entries for this client
+ * Unix authentication required.
+ */
+ void
+ MOUNTPROC_UMNTALL(void) = 4;
+
+ /*
+ * Returns a list of all the exported filesystems, and which
+ * machines are allowed to import it.
+ */
+ exports
+ MOUNTPROC_EXPORT(void) = 5;
+
+ /*
+ * Identical to MOUNTPROC_EXPORT above
+ */
+ exports
+ MOUNTPROC_EXPORTALL(void) = 6;
+
+ /*
+ * POSIX pathconf info (Sun hack)
+ */
+ ppathcnf
+ MOUNTPROC_PATHCONF(dirpath) = 7;
+ } = 2;
+} = 100005;
+
+#ifdef RPC_HDR
+%#endif /*!_rpcsvc_mount_h*/
+#endif
diff --git a/mount/rpcsvc/nfsmount_clnt.c b/mount/rpcsvc/nfsmount_clnt.c
new file mode 100644
index 000000000..a77f4c5eb
--- /dev/null
+++ b/mount/rpcsvc/nfsmount_clnt.c
@@ -0,0 +1,255 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "nfsmount.h"
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+ */
+
+/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
+
+#include <string.h> /* for memset() */
+
+/* Default timeout can be changed using clnt_control() */
+static struct timeval TIMEOUT = { 25, 0 };
+
+void *
+mountproc_null_1(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static char clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((void *)&clnt_res);
+}
+
+fhstatus *
+mountproc_mnt_1(argp, clnt)
+ dirpath *argp;
+ CLIENT *clnt;
+{
+ static fhstatus clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, argp, (xdrproc_t) xdr_fhstatus, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+mountlist *
+mountproc_dump_1(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static mountlist clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_mountlist, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+void *
+mountproc_umnt_1(argp, clnt)
+ dirpath *argp;
+ CLIENT *clnt;
+{
+ static char clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((void *)&clnt_res);
+}
+
+void *
+mountproc_umntall_1(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static char clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((void *)&clnt_res);
+}
+
+exports *
+mountproc_export_1(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static exports clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+exports *
+mountproc_exportall_1(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static exports clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+void *
+mountproc_null_2(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static char clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_NULL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((void *)&clnt_res);
+}
+
+fhstatus *
+mountproc_mnt_2(argp, clnt)
+ dirpath *argp;
+ CLIENT *clnt;
+{
+ static fhstatus clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, argp, (xdrproc_t) xdr_fhstatus, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+mountlist *
+mountproc_dump_2(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static mountlist clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_mountlist, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+void *
+mountproc_umnt_2(argp, clnt)
+ dirpath *argp;
+ CLIENT *clnt;
+{
+ static char clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((void *)&clnt_res);
+}
+
+void *
+mountproc_umntall_2(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static char clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return ((void *)&clnt_res);
+}
+
+exports *
+mountproc_export_2(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static exports clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+exports *
+mountproc_exportall_2(argp, clnt)
+ void *argp;
+ CLIENT *clnt;
+{
+ static exports clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
+
+ppathcnf *
+mountproc_pathconf_2(argp, clnt)
+ dirpath *argp;
+ CLIENT *clnt;
+{
+ static ppathcnf clnt_res;
+
+ memset((char *)&clnt_res, 0, sizeof(clnt_res));
+ if (clnt_call(clnt, MOUNTPROC_PATHCONF, (xdrproc_t) xdr_dirpath, argp, (xdrproc_t) xdr_ppathcnf, &clnt_res, TIMEOUT) != RPC_SUCCESS) {
+ return (NULL);
+ }
+ return (&clnt_res);
+}
diff --git a/mount/rpcsvc/nfsmount_xdr.c b/mount/rpcsvc/nfsmount_xdr.c
new file mode 100644
index 000000000..6f539c24f
--- /dev/null
+++ b/mount/rpcsvc/nfsmount_xdr.c
@@ -0,0 +1,351 @@
+/*
+ * Please do not edit this file.
+ * It was generated using rpcgen.
+ */
+
+#include "nfsmount.h"
+/*
+ * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
+ * unrestricted use provided that this legend is included on all tape
+ * media and as a part of the software program in whole or part. Users
+ * may copy or modify Sun RPC without charge, but are not authorized
+ * to license or distribute it to anyone else except as part of a product or
+ * program developed by the user or with the express written consent of
+ * Sun Microsystems, Inc.
+ *
+ * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
+ * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
+ *
+ * Sun RPC is provided with no support and without any obligation on the
+ * part of Sun Microsystems, Inc. to assist in its use, correction,
+ * modification or enhancement.
+ *
+ * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
+ * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
+ * OR ANY PART THEREOF.
+ *
+ * In no event will Sun Microsystems, Inc. be liable for any lost revenue
+ * or profits or other special, indirect and consequential damages, even if
+ * Sun has been advised of the possibility of such damages.
+ *
+ * Sun Microsystems, Inc.
+ * 2550 Garcia Avenue
+ * Mountain View, California 94043
+ */
+/*
+ * Copyright (c) 1985, 1990 by Sun Microsystems, Inc.
+ */
+
+/* from @(#)mount.x 1.3 91/03/11 TIRPC 1.0 */
+
+bool_t
+xdr_fhandle(xdrs, objp)
+ XDR *xdrs;
+ fhandle objp;
+{
+
+ register long *buf;
+
+ if (!xdr_opaque(xdrs, objp, FHSIZE)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_fhstatus(xdrs, objp)
+ XDR *xdrs;
+ fhstatus *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_u_int(xdrs, &objp->fhs_status)) {
+ return (FALSE);
+ }
+ switch (objp->fhs_status) {
+ case 0:
+ if (!xdr_fhandle(xdrs, objp->fhstatus_u.fhs_fhandle)) {
+ return (FALSE);
+ }
+ break;
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_dirpath(xdrs, objp)
+ XDR *xdrs;
+ dirpath *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_string(xdrs, objp, MNTPATHLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_name(xdrs, objp)
+ XDR *xdrs;
+ name *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_string(xdrs, objp, MNTNAMLEN)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_mountlist(xdrs, objp)
+ XDR *xdrs;
+ mountlist *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct mountbody), (xdrproc_t)xdr_mountbody)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_mountbody(xdrs, objp)
+ XDR *xdrs;
+ mountbody *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_name(xdrs, &objp->ml_hostname)) {
+ return (FALSE);
+ }
+ if (!xdr_dirpath(xdrs, &objp->ml_directory)) {
+ return (FALSE);
+ }
+ if (!xdr_mountlist(xdrs, &objp->ml_next)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_groups(xdrs, objp)
+ XDR *xdrs;
+ groups *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct groupnode), (xdrproc_t)xdr_groupnode)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_groupnode(xdrs, objp)
+ XDR *xdrs;
+ groupnode *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_name(xdrs, &objp->gr_name)) {
+ return (FALSE);
+ }
+ if (!xdr_groups(xdrs, &objp->gr_next)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_exports(xdrs, objp)
+ XDR *xdrs;
+ exports *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_pointer(xdrs, (char **)objp, sizeof(struct exportnode), (xdrproc_t)xdr_exportnode)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_exportnode(xdrs, objp)
+ XDR *xdrs;
+ exportnode *objp;
+{
+
+ register long *buf;
+
+ if (!xdr_dirpath(xdrs, &objp->ex_dir)) {
+ return (FALSE);
+ }
+ if (!xdr_groups(xdrs, &objp->ex_groups)) {
+ return (FALSE);
+ }
+ if (!xdr_exports(xdrs, &objp->ex_next)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
+
+bool_t
+xdr_ppathcnf(xdrs, objp)
+ XDR *xdrs;
+ ppathcnf *objp;
+{
+
+ register long *buf;
+
+ int i;
+
+ if (xdrs->x_op == XDR_ENCODE) {
+ buf = XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_int(xdrs, &objp->pc_link_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_canon)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_input)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_name_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_path_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ IXDR_PUT_LONG(buf,objp->pc_link_max);
+ IXDR_PUT_SHORT(buf,objp->pc_max_canon);
+ IXDR_PUT_SHORT(buf,objp->pc_max_input);
+ IXDR_PUT_SHORT(buf,objp->pc_name_max);
+ IXDR_PUT_SHORT(buf,objp->pc_path_max);
+ IXDR_PUT_SHORT(buf,objp->pc_pipe_buf);
+ }
+ if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
+ return (FALSE);
+ }
+ if (!xdr_char(xdrs, &objp->pc_xxx)) {
+ return (FALSE);
+ }
+ buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ { register short *genp;
+ for ( i = 0,genp=objp->pc_mask;
+ i < 2; i++){
+ IXDR_PUT_SHORT(buf,*genp++);
+ }
+ };
+ }
+
+ return (TRUE);
+ } else if (xdrs->x_op == XDR_DECODE) {
+ buf = XDR_INLINE(xdrs,6 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_int(xdrs, &objp->pc_link_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_canon)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_input)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_name_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_path_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ objp->pc_link_max = IXDR_GET_LONG(buf);
+ objp->pc_max_canon = IXDR_GET_SHORT(buf);
+ objp->pc_max_input = IXDR_GET_SHORT(buf);
+ objp->pc_name_max = IXDR_GET_SHORT(buf);
+ objp->pc_path_max = IXDR_GET_SHORT(buf);
+ objp->pc_pipe_buf = IXDR_GET_SHORT(buf);
+ }
+ if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
+ return (FALSE);
+ }
+ if (!xdr_char(xdrs, &objp->pc_xxx)) {
+ return (FALSE);
+ }
+ buf = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT);
+ if (buf == NULL) {
+ if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) {
+ return (FALSE);
+ }
+
+ }
+ else {
+ { register short *genp;
+ for ( i = 0,genp=objp->pc_mask;
+ i < 2; i++){
+ *genp++ = IXDR_GET_SHORT(buf);
+ }
+ };
+ }
+ return(TRUE);
+ }
+
+ if (!xdr_int(xdrs, &objp->pc_link_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_canon)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_max_input)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_name_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_path_max)) {
+ return (FALSE);
+ }
+ if (!xdr_short(xdrs, &objp->pc_pipe_buf)) {
+ return (FALSE);
+ }
+ if (!xdr_u_char(xdrs, &objp->pc_vdisable)) {
+ return (FALSE);
+ }
+ if (!xdr_char(xdrs, &objp->pc_xxx)) {
+ return (FALSE);
+ }
+ if (!xdr_vector(xdrs, (char *)objp->pc_mask, 2, sizeof(short), (xdrproc_t)xdr_short)) {
+ return (FALSE);
+ }
+ return (TRUE);
+}
diff --git a/mount/sundries.c b/mount/sundries.c
index 5ebf0195f..4506924aa 100644
--- a/mount/sundries.c
+++ b/mount/sundries.c
@@ -4,328 +4,224 @@
*
* added fcntl locking by Kjetil T. (kjetilho@math.uio.no) - aeb, 950927
*/
-
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <mntent.h> /* for MNTTYPE_SWAP */
+#include "fstab.h"
#include "sundries.h"
-#include "mount.h"
-
-/* File pointer for /etc/mtab. */
-FILE *F_mtab = NULL;
-
-/* File pointer for temp mtab. */
-FILE *F_temp = NULL;
+#include "nfsmount.h"
-/* File descriptor for lock. Value tested in unlock_mtab() to remove race. */
-static int lock = -1;
-
-/* Flag for already existing lock file. */
-static int old_lockfile = 1;
/* String list constructor. (car() and cdr() are defined in "sundries.h"). */
string_list
-cons (char *a, const string_list b)
-{
- string_list p;
-
- p = xmalloc (sizeof *p);
+cons (char *a, const string_list b) {
+ string_list p;
- car (p) = a;
- cdr (p) = b;
- return p;
+ p = xmalloc (sizeof *p);
+ car (p) = a;
+ cdr (p) = b;
+ return p;
}
void *
-xmalloc (size_t size)
-{
- void *t;
+xmalloc (size_t size) {
+ void *t;
- if (size == 0)
- return NULL;
+ if (size == 0)
+ return NULL;
- t = malloc (size);
- if (t == NULL)
- die (2, "not enough memory");
+ t = malloc (size);
+ if (t == NULL)
+ die (EX_SYSERR, "not enough memory");
- return t;
+ return t;
}
char *
-xstrdup (const char *s)
-{
- char *t;
+xstrdup (const char *s) {
+ char *t;
- if (s == NULL)
- return NULL;
+ if (s == NULL)
+ return NULL;
- t = strdup (s);
+ t = strdup (s);
- if (t == NULL)
- die (2, "not enough memory");
+ if (t == NULL)
+ die (EX_SYSERR, "not enough memory");
- return t;
+ return t;
}
-/* Call this with SIG_BLOCK to block and SIG_UNBLOCK to unblock. */
-void
-block_signals (int how)
-{
- sigset_t sigs;
+char *
+xstrndup (const char *s, int n) {
+ char *t;
- sigfillset (&sigs);
- sigprocmask (how, &sigs, (sigset_t *) 0);
-}
+ if (s == NULL)
+ die (EX_SOFTWARE, "bug in xstrndup call");
+ t = xmalloc(n+1);
+ strncpy(t,s,n);
+ t[n] = 0;
-/* Non-fatal error. Print message and return. */
-void
-error (const char *fmt, ...)
-{
- va_list args;
-
- if (mount_quiet) return;
- va_start (args, fmt);
- vfprintf (stderr, fmt, args);
- fprintf (stderr, "\n");
- va_end (args);
+ return t;
}
-/* Fatal error. Print message and exit. */
-void
-die (int err, const char *fmt, ...)
-{
- va_list args;
-
- va_start (args, fmt);
- vfprintf (stderr, fmt, args);
- fprintf (stderr, "\n");
- va_end (args);
+char *
+xstrconcat2 (const char *s, const char *t) {
+ char *res;
- unlock_mtab ();
- exit (err);
+ if (!s) s = "";
+ if (!t) t = "";
+ res = xmalloc(strlen(s) + strlen(t) + 1);
+ strcpy(res, s);
+ strcat(res, t);
+ return res;
}
-/* Ensure that the lock is released if we are interrupted. */
-static void
-handler (int sig)
-{
- die (2, "%s", sys_siglist[sig]);
-}
+char *
+xstrconcat3 (const char *s, const char *t, const char *u) {
+ char *res;
-static void
-setlkw_timeout (int sig)
-{
- /* nothing, fcntl will fail anyway */
+ if (!s) s = "";
+ if (!t) t = "";
+ if (!u) u = "";
+ res = xmalloc(strlen(s) + strlen(t) + strlen(u) + 1);
+ strcpy(res, s);
+ strcat(res, t);
+ strcat(res, u);
+ return res;
}
-/* Create the lock file. The lock file will be removed if we catch a signal
- or when we exit. The value of lock is tested to remove the race. */
-void
-lock_mtab (void)
-{
- int sig = 0;
- struct sigaction sa;
- struct flock flock;
-
- /* If this is the first time, ensure that the lock will be removed. */
- if (lock < 0)
- {
- struct stat st;
- sa.sa_handler = handler;
- sa.sa_flags = 0;
- sigfillset (&sa.sa_mask);
-
- while (sigismember (&sa.sa_mask, ++sig) != -1)
- {
- if (sig == SIGALRM)
- sa.sa_handler = setlkw_timeout;
- else
- sa.sa_handler = handler;
- sigaction (sig, &sa, (struct sigaction *) 0);
- }
-
- /* This stat is performed so we know when not to be overly eager
- when cleaning up after signals. The window between stat and
- open is not significant. */
- if (lstat (MOUNTED_LOCK, &st) < 0 && errno == ENOENT)
- old_lockfile = 0;
-
- lock = open (MOUNTED_LOCK, O_WRONLY|O_CREAT, 0);
- if (lock < 0)
- {
- die (2, "can't create lock file %s: %s",
- MOUNTED_LOCK, strerror (errno));
- }
-
- flock.l_type = F_WRLCK;
- flock.l_whence = SEEK_SET;
- flock.l_start = 0;
- flock.l_len = 0;
-
- alarm(LOCK_BUSY);
- if (fcntl (lock, F_SETLKW, &flock) < 0)
- {
- close (lock);
- /* The file should not be removed */
- lock = -1;
- die (2, "can't lock lock file %s: %s",
- MOUNTED_LOCK, errno == EINTR ? "timed out" : strerror (errno));
- }
- /* We have now access to the lock, and it can always be removed */
- old_lockfile = 0;
- }
-}
+char *
+xstrconcat4 (const char *s, const char *t, const char *u, const char *v) {
+ char *res;
-/* Remove lock file. */
-void
-unlock_mtab (void)
-{
- if (lock != -1)
- {
- close (lock);
- if (!old_lockfile)
- unlink (MOUNTED_LOCK);
- }
+ if (!s) s = "";
+ if (!t) t = "";
+ if (!u) u = "";
+ if (!v) v = "";
+ res = xmalloc(strlen(s) + strlen(t) + strlen(u) + strlen(v) + 1);
+ strcpy(res, s);
+ strcat(res, t);
+ strcat(res, u);
+ strcat(res, v);
+ return res;
}
-/* Open mtab. */
+/* Call this with SIG_BLOCK to block and SIG_UNBLOCK to unblock. */
void
-open_mtab (const char *mode)
-{
- if ((F_mtab = setmntent (MOUNTED, mode)) == NULL)
- die (2, "can't open %s: %s", MOUNTED, strerror (errno));
-}
+block_signals (int how) {
+ sigset_t sigs;
-/* Close mtab. */
-void
-close_mtab (void)
-{
- if (fchmod (fileno (F_mtab), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0)
- die (1, "mount: error changing mode of %s: %s", MOUNTED, strerror (errno));
- endmntent (F_mtab);
+ sigfillset (&sigs);
+ sigdelset(&sigs, SIGTRAP);
+ sigdelset(&sigs, SIGSEGV);
+ sigprocmask (how, &sigs, (sigset_t *) 0);
}
-/* Update the mtab by removing any DIR entries and replace it with INSTEAD. */
-void
-update_mtab (const char *dir, struct mntent *instead)
-{
- struct mntent *mnt;
- struct mntent *next;
- int added = 0;
- open_mtab ("r");
+/* Non-fatal error. Print message and return. */
+/* (print the message in a single printf, in an attempt
+ to avoid mixing output of several threads) */
+void
+error (const char *fmt, ...) {
+ va_list args;
+ char *fmt2;
- if ((F_temp = setmntent (MOUNTED_TEMP, "w")) == NULL)
- die (2, "can't open %s: %s", MOUNTED_TEMP, strerror (errno));
-
- while ((mnt = getmntent (F_mtab)))
- {
- next = streq (mnt->mnt_dir, dir) ? (added++, instead) : mnt;
- if (next && addmntent(F_temp, next) == 1)
- die (1, "error writing %s: %s", MOUNTED_TEMP, strerror (errno));
- }
- if (instead && !added)
- addmntent(F_temp, instead);
-
- endmntent (F_mtab);
- if (fchmod (fileno (F_temp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0)
- die (1, "error changing mode of %s: %s", MOUNTED_TEMP, strerror (errno));
- endmntent (F_temp);
-
- if (rename (MOUNTED_TEMP, MOUNTED) < 0)
- die (1, "can't rename %s to %s: %s",
- MOUNTED_TEMP, MOUNTED, strerror(errno));
+ if (mount_quiet)
+ return;
+ fmt2 = xstrconcat2 (fmt, "\n");
+ va_start (args, fmt);
+ vfprintf (stderr, fmt2, args);
+ va_end (args);
+ free (fmt2);
}
-/* Given the name FILE, try to find it in mtab. */
-struct mntent *
-getmntfile (const char *file)
-{
- struct mntent *mnt;
-
- if (!F_mtab)
- return NULL;
-
- rewind(F_mtab);
+/* Fatal error. Print message and exit. */
+void
+die (int err, const char *fmt, ...) {
+ va_list args;
- while ((mnt = getmntent (F_mtab)) != NULL)
- {
- if (streq (mnt->mnt_dir, file))
- break;
- if (streq (mnt->mnt_fsname, file))
- break;
- }
+ va_start (args, fmt);
+ vfprintf (stderr, fmt, args);
+ fprintf (stderr, "\n");
+ va_end (args);
- return mnt;
+ unlock_mtab ();
+ exit (err);
}
/* Parse a list of strings like str[,str]... into a string list. */
string_list
-parse_list (char *strings)
-{
- string_list list;
- char *t;
+parse_list (char *strings) {
+ string_list list;
+ char *t;
- if (strings == NULL)
- return NULL;
+ if (strings == NULL)
+ return NULL;
- list = cons (strtok (strings, ","), NULL);
+ list = cons (strtok (strings, ","), NULL);
- while ((t = strtok (NULL, ",")) != NULL)
- list = cons (t, list);
+ while ((t = strtok (NULL, ",")) != NULL)
+ list = cons (t, list);
- return list;
+ return list;
}
/* True if fstypes match. Null *TYPES means match anything,
- except that swap types always return false. This routine
- has some ugliness to deal with ``no'' types. */
+ except that swap types always return false.
+ This routine has some ugliness to deal with ``no'' types.
+ Fixed bug: the `no' part comes at the end - aeb, 970216 */
int
-matching_type (const char *type, string_list types)
-{
- char *notype;
- int no; /* true if a "no" type match, ie -t nominix */
-
- if (streq (type, MNTTYPE_SWAP))
- return 0;
- if (types == NULL)
- return 1;
-
- if ((notype = alloca (strlen (type) + 3)) == NULL)
- die (2, "mount: out of memory");
- sprintf (notype, "no%s", type);
- no = (car (types)[0] == 'n') && (car (types)[1] == 'o');
-
- /* If we get a match and the user specified a positive match type (e.g.
- "minix") we return true. If we match and a negative match type (e.g.
- "nominix") was specified we return false. */
- while (types != NULL)
- if (streq (type, car (types)))
- return !no;
- else if (streq (notype, car (types)))
- return 0; /* match with "nofoo" always returns false */
- else
- types = cdr (types);
-
- /* No matches, so if the user specified a positive match type return false,
- if a negative match type was specified, return true. */
- return no;
+matching_type (const char *type, string_list types) {
+ char *notype;
+ int foundyes, foundno;
+ int no; /* true if a "no" type match, eg -t nominix */
+
+ if (streq (type, MNTTYPE_SWAP))
+ return 0;
+ if (types == NULL)
+ return 1;
+
+ if ((notype = alloca (strlen (type) + 3)) == NULL)
+ die (EX_SYSERR, "mount: out of memory");
+ sprintf (notype, "no%s", type);
+
+ foundyes = foundno = no = 0;
+ while (types != NULL) {
+ if (cdr (types) == NULL)
+ no = (car (types)[0] == 'n') && (car (types)[1] == 'o');
+ if (streq (type, car (types)))
+ foundyes = 1;
+ else if (streq (notype, car (types)))
+ foundno = 1;
+ types = cdr (types);
+ }
+
+ return (foundno ? 0 : (no ^ foundyes));
}
/* Make a canonical pathname from PATH. Returns a freshly malloced string.
It is up the *caller* to ensure that the PATH is sensible. i.e.
canonicalize ("/dev/fd0/.") returns "/dev/fd0" even though ``/dev/fd0/.''
- is not a legal pathname for ``/dev/fd0.'' Anything we cannot parse
+ is not a legal pathname for ``/dev/fd0''. Anything we cannot parse
we return unmodified. */
char *
-canonicalize (const char *path)
-{
- char *canonical = xmalloc (PATH_MAX + 1);
+canonicalize (const char *path) {
+ char *canonical;
- if (path == NULL)
- return NULL;
+ if (path == NULL)
+ return NULL;
+
+ if (streq(path, "none") || streq(path, "proc"))
+ return xstrdup(path);
+
+ canonical = xmalloc (PATH_MAX + 1);
- if (realpath (path, canonical))
- return canonical;
+ if (realpath (path, canonical))
+ return canonical;
- strcpy (canonical, path);
- return canonical;
+ free(canonical);
+ return xstrdup(path);
}
diff --git a/mount/sundries.h b/mount/sundries.h
index 77d8d32f4..0c96f865b 100644
--- a/mount/sundries.h
+++ b/mount/sundries.h
@@ -4,49 +4,21 @@
*/
#include <sys/types.h>
-#include <sys/mount.h>
-#include <sys/stat.h>
-#include <stdio.h>
-#include <errno.h>
#include <fcntl.h>
-#include <getopt.h>
#include <limits.h>
-#include <mntent.h>
#include <signal.h>
#include <stdarg.h>
#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#if 0
-#include <linux/version.h>
-#if LINUX_VERSION_CODE >= 0x010302
-#define SUPPORT_PRIORITIES
-#endif
+#ifndef bool_t
+#include <rpc/types.h>
#endif
-#ifdef SUPPORT_PRIORITIES
-#include <linux/swap.h>
-#endif
-
-#include "fstab.h"
-
extern int mount_quiet;
+extern int verbose;
#define streq(s, t) (strcmp ((s), (t)) == 0)
-#define MOUNTED_LOCK "/etc/mtab~"
-#define MOUNTED_TEMP "/etc/mtab.tmp"
-#define _PATH_FSTAB "/etc/fstab"
-#define LOCK_BUSY 10
-
-/* File pointer for /etc/mtab. */
-extern FILE *F_mtab;
-
-/* File pointer for temp mtab. */
-extern FILE *F_temp;
-
/* String list data structure. */
typedef struct string_list
{
@@ -62,24 +34,19 @@ string_list cons (char *a, const string_list);
/* Quiet compilation with -Wmissing-prototypes. */
int main (int argc, char *argv[]);
-/* From mount_call.c. */
-int mount5 (const char *, const char *, const char *, int, void *);
-
/* Functions in sundries.c that are used in mount.c and umount.c */
void block_signals (int how);
char *canonicalize (const char *path);
char *realpath (const char *path, char *resolved_path);
-void close_mtab (void);
void error (const char *fmt, ...);
-void lock_mtab (void);
int matching_type (const char *type, string_list types);
-void open_mtab (const char *mode);
string_list parse_list (char *strings);
-void unlock_mtab (void);
-void update_mtab (const char *special, struct mntent *with);
-struct mntent *getmntfile (const char *file);
void *xmalloc (size_t size);
char *xstrdup (const char *s);
+char *xstrndup (const char *s, int n);
+char *xstrconcat2 (const char *, const char *);
+char *xstrconcat3 (const char *, const char *, const char *);
+char *xstrconcat4 (const char *, const char *, const char *, const char *);
/* Here is some serious cruft. */
#ifdef __GNUC__
@@ -97,6 +64,11 @@ int nfsmount (const char *spec, const char *node, int *flags,
char **orig_opts, char **opt_args);
#endif
-#define mount5(special, dir, type, flags, data) \
- mount (special, dir, type, 0xC0ED0000 | (flags), data)
-
+/* exit status - bits below are ORed */
+#define EX_USAGE 1 /* incorrect invocation or permission */
+#define EX_SYSERR 2 /* out of memory, cannot fork, ... */
+#define EX_SOFTWARE 4 /* internal mount bug or wrong version */
+#define EX_USER 8 /* user interrupt */
+#define EX_FILEIO 16 /* problems writing, locking, ... mtab/fstab */
+#define EX_FAIL 32 /* mount failure */
+#define EX_SOMEOK 64 /* some mount succeeded */
diff --git a/mount/swap.configure b/mount/swap.configure
new file mode 100644
index 000000000..70bce506b
--- /dev/null
+++ b/mount/swap.configure
@@ -0,0 +1,22 @@
+# find out whether we can include <sys/swap.h>
+# and whether libc thinks that swapon() has two arguments.
+CC=${CC-cc}
+compile="$CC -o conftest conftest.c >/dev/null 2>&1"
+rm -f conftest conftest.c swapargs.h
+SWAPH=
+if [ -f /usr/include/sys/swap.h ]; then SWAPH="#include <sys/swap.h>"; fi
+echo $SWAPH > conftest.c
+echo '#include <unistd.h>
+main(){ exit(0); swapon("/dev/null", 0); }' >> conftest.c
+eval $compile
+if test -s conftest && ./conftest 2>/dev/null; then
+ echo "#define SWAPON_HAS_TWO_ARGS" > swapargs.h
+ echo $SWAPH >> swapargs.h
+else
+ echo > swapargs.h
+ echo "
+Your libc thinks that swapon has 1 arg only.
+Define SWAPON_NEEDS_TWO_ARGS in swapon.c if you want to use priorities.
+" 1>&2
+fi
+rm -f conftest conftest.c
diff --git a/mount/swapon.8 b/mount/swapon.8
index 911855dcf..0ebb450a8 100644
--- a/mount/swapon.8
+++ b/mount/swapon.8
@@ -36,6 +36,7 @@
.\" Sat Oct 9 09:35:30 1993: Converted to man format by faith@cs.unc.edu
.\" Sat Nov 27 20:22:42 1993: Updated authorship information, faith@cs.unc.edu
.\" Mon Sep 25 14:12:38 1995: Added -v and -p information
+.\" Tue Apr 30 03:32:07 1996: Added some text from A. Koppenhoefer
.\"
.TH SWAPON 8 "25 September 1995" "Linux 1.x" "Linux Programmer's Manual"
.SH NAME
@@ -47,6 +48,8 @@ swapon, swapoff \- enable/disable devices and files for paging and swapping
.br
.BI "/sbin/swapon [\-v] [\-p " "priority" "] " " specialfile " ...
.br
+.B /sbin/swapon [\-s]
+.br
.B /sbin/swapoff [\-h \-V]
.br
.B /sbin/swapoff \-a
@@ -70,6 +73,9 @@ Provide help
.B \-V
Display version
.TP
+.B \-s
+Display swap usage summary by device
+.TP
.B \-a
All devices marked as ``sw'' swap devices in
.I /etc/fstab
@@ -81,6 +87,15 @@ Specify priority for
This option is only available if
.B swapon
was compiled under and is used under a 1.3.2 or later kernel.
+.I priority
+is a value between 0 and 32767. See
+.BR swapon (2)
+for a full description of swap priorities. Add
+.BI pri= value
+to the option field of
+.I /etc/fstab
+for use with
+.BR "swapon -a" .
.PP
.B Swapoff
disables swapping on the specified devices and files, or on all swap
diff --git a/mount/swapon.c b/mount/swapon.c
index 331238f0b..5fdd15c5d 100644
--- a/mount/swapon.c
+++ b/mount/swapon.c
@@ -1,15 +1,28 @@
/*
* A swapon(8)/swapoff(8) for Linux 0.99.
* swapon.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
+ * Added '-s' (Summary option) <Vincent.Renardias@waw.com> 02/1997.
*/
-#include "sundries.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <getopt.h>
+#include <string.h>
+#include <mntent.h>
+#include <errno.h>
+#include "swap.h"
+#include "swapargs.h"
+
+#define streq(s, t) (strcmp ((s), (t)) == 0)
+
+#define _PATH_FSTAB "/etc/fstab"
+#define PROC_SWAPS "/proc/swaps"
+
+/* #define SWAPON_NEEDS_TWO_ARGS */
/* Nonzero for chatty (-v). This is a nonstandard flag (not in BSD). */
int verbose = 0;
-#ifdef SUPPORT_PRIORITIES
int priority = -1; /* non-prioritized swap by default */
-#endif
extern char version[];
static char *program_name;
@@ -17,57 +30,69 @@ static struct option longopts[] =
{
{ "all", 0, 0, 'a' },
{ "help", 0, 0, 'h' },
-#ifdef SUPPORT_PRIORITIES
{ "priority", required_argument, 0, 'p' },
-#endif
+ { "summary", 0, 0, 's' },
{ "verbose", 0, 0, 'v' },
{ "version", 0, 0, 'V' },
{ NULL, 0, 0, 0 }
};
-#ifdef SUPPORT_PRIORITIES
-const char *usage_string = "\
-usage: %s [-hV]\n\
- %s -a [-v]\n\
- %s [-v] [-p priority] special ...\n\
-";
-#else
const char *usage_string = "\
usage: %s [-hV]\n\
%s -a [-v]\n\
%s [-v] [-p priority] special ...\n\
+ %s [-s]\n\
";
-#endif
static void
usage (FILE *fp, int n)
{
- fprintf (fp, usage_string, program_name, program_name, program_name);
+ fprintf (fp, usage_string, program_name, program_name, program_name, program_name);
exit (n);
}
-static int
-#ifdef SUPPORT_PRIORITIES
-swap (const char *special, int prio)
+#ifdef SWAPON_HAS_TWO_ARGS
+#define SWAPON_NEEDS_TWO_ARGS
+#endif
+
+#ifdef SWAPON_NEEDS_TWO_ARGS
+#ifdef SWAPON_HAS_TWO_ARGS
+/* libc is OK */
+#include <unistd.h>
+#else
+/* We want a swapon with two args, but have an old libc.
+ Build the kernel call by hand. */
+#include <linux/unistd.h>
+static
+_syscall2(int, swapon, const char *, path, int, flags);
+static
+_syscall1(int, swapoff, const char *, path);
+#endif
#else
-swap (const char *special)
+/* just do as libc says */
+#include <unistd.h>
#endif
+
+static int
+swap (const char *special, int prio)
{
int status;
-#ifdef SUPPORT_PRIORITIES
- int flags;
-#endif
if (verbose)
printf("%s on device %s\n", program_name, special);
if (streq (program_name, "swapon")) {
-#ifdef SUPPORT_PRIORITIES
- flags = 0;
+#ifdef SWAPON_NEEDS_TWO_ARGS
+ int flags = 0;
+
+#ifdef SWAP_FLAG_PREFER
if (prio >= 0) {
+ if (prio > SWAP_FLAG_PRIO_MASK)
+ prio = SWAP_FLAG_PRIO_MASK;
flags = SWAP_FLAG_PREFER
| ((prio & SWAP_FLAG_PRIO_MASK) << SWAP_FLAG_PRIO_SHIFT);
}
+#endif
status = swapon (special, flags);
#else
status = swapon (special);
@@ -81,10 +106,27 @@ swap (const char *special)
return status;
}
+static int
+display_summary(void)
+{
+ FILE *swaps;
+ char line[200] ;
+
+ if ((swaps = fopen(PROC_SWAPS, "r")) == NULL) {
+ fprintf (stderr, "%s: %s: %s\n", program_name, PROC_SWAPS,
+ strerror (errno));
+ return -1 ;
+ }
+ while ( fgets(line, sizeof(line), swaps))
+ printf ("%s", line);
+
+ return 0 ;
+}
+
int
main (int argc, char *argv[])
{
- struct fstab *fstab;
+ struct mntent *fstab;
int status;
int all = 0;
int c;
@@ -94,11 +136,7 @@ main (int argc, char *argv[])
else
program_name = argv[0];
-#ifdef SUPPORT_PRIORITIES
- while ((c = getopt_long (argc, argv, "ahp:vV", longopts, NULL)) != EOF)
-#else
- while ((c = getopt_long (argc, argv, "ahvV", longopts, NULL)) != EOF)
-#endif
+ while ((c = getopt_long (argc, argv, "ahp:svV", longopts, NULL)) != EOF)
switch (c)
{
case 'a': /* all */
@@ -107,16 +145,17 @@ main (int argc, char *argv[])
case 'h': /* help */
usage (stdout, 0);
break;
-#ifdef SUPPORT_PRIORITIES
case 'p': /* priority */
priority = atoi(optarg);
break;
-#endif
+ case 's': /* tell about current use of swap areas */
+ status = display_summary();
+ exit(status);
case 'v': /* be chatty */
++verbose;
break;
case 'V': /* version */
- printf ("swapon: %s\n", version);
+ printf ("%s: %s\n", program_name, version);
exit (0);
case 0:
break;
@@ -129,43 +168,30 @@ main (int argc, char *argv[])
status = 0;
- if (all)
- {
- while ((fstab = getfsent()) != NULL)
- if (streq (fstab->fs_type, FSTAB_SW))
- {
-#ifdef SUPPORT_PRIORITIES
- /* parse mount options; */
- char *opt, *opts = strdup(fstab->fs_mntopts);
+ if (all) {
+ FILE *fp = setmntent(_PATH_FSTAB, "r");
+ if (fp == NULL) {
+ fprintf(stderr, "%s: cannot open %s: %s\n", program_name,
+ _PATH_FSTAB, strerror(errno));
+ exit(2);
+ }
+ while ((fstab = getmntent(fp)) != NULL) {
+ if (streq (fstab->mnt_type, MNTTYPE_SWAP)) {
+ /* parse mount options; */
+ char *opt, *opts = strdup(fstab->mnt_opts);
- for (opt = strtok (opts, ",");
- opt != NULL;
- opt = strtok (NULL, ","))
- {
- if (strncmp(opt, "pri=", 4) == 0)
- {
- priority = atoi(opt+4);
- }
- }
- status |= swap (fstab->fs_spec, priority);
-#else
- status |= swap (fstab->fs_spec);
-#endif
- }
- }
- else if (*argv == NULL)
- {
- usage (stderr, 2);
- }
- else
- {
- while (*argv != NULL) {
-#ifdef SUPPORT_PRIORITIES
- status |= swap (*argv++,priority);
-#else
- status |= swap (*argv++);
-#endif
+ for (opt = strtok (opts, ","); opt != NULL;
+ opt = strtok (NULL, ","))
+ if (strncmp(opt, "pri=", 4) == 0)
+ priority = atoi(opt+4);
+ status |= swap (fstab->mnt_fsname, priority);
+ }
}
- }
+ } else if (*argv == NULL) {
+ usage (stderr, 2);
+ } else {
+ while (*argv != NULL)
+ status |= swap (*argv++,priority);
+ }
return status;
}
diff --git a/mount/umount.8 b/mount/umount.8
index 85425b487..196bd7f8a 100644
--- a/mount/umount.8
+++ b/mount/umount.8
@@ -1 +1,108 @@
-.so man8/mount.8
+.\" Copyright (c) 1996 Andries Brouwer
+.\" This page is somewhat derived from a page that was
+.\" (c) 1980, 1989, 1991 The Regents of the University of California
+.\" and had been heavily modified by Rik Faith and myself.
+.\"
+.\" This is free documentation; you can redistribute it and/or
+.\" modify it under the terms of the GNU General Public License as
+.\" published by the Free Software Foundation; either version 2 of
+.\" the License, or (at your option) any later version.
+.\"
+.\" The GNU General Public License's references to "object code"
+.\" and "executables" are to be interpreted as the output of any
+.\" document formatting or typesetting system, including
+.\" intermediate and printed output.
+.\"
+.\" This manual is distributed in the hope that it will be useful,
+.\" but WITHOUT ANY WARRANTY; without even the implied warranty of
+.\" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+.\" GNU General Public License for more details.
+.\"
+.\" You should have received a copy of the GNU General Public
+.\" License along with this manual; if not, write to the Free
+.\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139,
+.\" USA.
+.\"
+.TH UMOUNT 8 "26 July 1997" "Linux 2.0" "Linux Programmer's Manual"
+.SH NAME
+umount \- unmount file systems
+.SH SYNOPSIS
+.BI "umount [\-hV]"
+.LP
+.BI "umount -a [\-nrv] [\-t " vfstype ]
+.br
+.BI "umount [\-nrv] " "device " | " dir " [...]
+.SH DESCRIPTION
+The
+.B umount
+command detaches the file system(s) mentioned from the file hierarchy.
+A file system is specified either by giving the directory where it
+has been mounted, or by giving the special device on which it lives.
+
+Note that a file system cannot be unmounted when it is `busy' -
+for example, when there are open files on it, or when some process
+has its working directory there, or when a swap file on it is in use.
+The offending process could even be
+.B umount
+itself - it opens libc, and libc in its turn may open for example
+locale files.
+
+Options for the
+.B umount
+command:
+.TP
+.B \-V
+Print version and exit.
+.TP
+.B \-h
+Print help message and exit.
+.TP
+.B \-v
+Verbose mode.
+.TP
+.B \-n
+Unmount without writing in
+.IR /etc/mtab .
+.TP
+.B \-r
+In case unmounting fails, try to remount read-only.
+.TP
+.B \-a
+All of the file systems described in
+.I /etc/mtab
+are unmounted. (With
+.B umount
+version 2.7 and later: the
+.I proc
+filesystem is not unmounted.)
+.TP
+.BI \-t " vfstype"
+Indicate that the actions should only be taken on file systems of the
+specified type. More than one type may be specified in a comma separated
+list. The list of file system types can be prefixed with
+.B no
+to specify the file system types on which no action should be taken.
+
+.SH "THE LOOP DEVICE"
+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 .
+Any pending loop devices can be freed using `losetup -d', see
+.BR losetup (8).
+
+
+.SH FILES
+.I /etc/mtab
+table of mounted file systems
+
+.SH "SEE ALSO"
+.BR umount (2),
+.BR mount (8),
+.BR losetup (8).
+
+.SH HISTORY
+A
+.B umount
+command appeared in Version 6 AT&T UNIX.
diff --git a/mount/umount.c b/mount/umount.c
index 236f05241..de80fd1bc 100644
--- a/mount/umount.c
+++ b/mount/umount.c
@@ -8,9 +8,29 @@
*
* 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 - canonise names from fstab
+ * 970726: aeb - remount read-only in cases where umount fails
*/
+#include <unistd.h>
+#include <getopt.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/stat.h>
+#include <sys/mount.h>
+#include "mount_constants.h"
#include "sundries.h"
+#include "lomount.h"
+#include "loop.h"
+#include "fstab.h"
#ifdef HAVE_NFS
#include <sys/socket.h>
@@ -19,7 +39,7 @@
#include <rpc/rpc.h>
#include <rpc/pmap_clnt.h>
#include <rpc/pmap_prot.h>
-#include "mount.h"
+#include "nfsmount.h"
#include <arpa/inet.h>
#endif
@@ -29,6 +49,12 @@
int force = 0;
#endif
+/* When umount fails, attempt a read-only remount (-r). */
+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). */
int verbose = 0;
@@ -40,32 +66,109 @@ static int xdr_dir(XDR *xdrsp, char *dirp)
{
return (xdr_string(xdrsp, &dirp, MNTPATHLEN));
}
-#endif
-
-
-/* Umount a single device. Return a status code, so don't exit
- on a non-fatal error. We lock/unlock around each umount. */
static int
-umount_one (const char *spec, const char *node, const char *type)
+nfs_umount_rpc_call(const char *spec, const char *opts)
{
- int umnt_err;
- int isroot;
- struct mntent *mnt;
-
-#ifdef HAVE_NFS
- char buffer[256];
register CLIENT *clp;
struct sockaddr_in saddr;
struct timeval pertry, try;
enum clnt_stat clnt_stat;
int so = RPC_ANYSOCK;
- char *p;
struct hostent *hostp;
- char hostname[MAXHOSTNAMELEN];
- char dirname[1024];
+ char *hostname;
+ char *dirname;
+ char *p;
+
+ if (spec == NULL || (p = strchr(spec,':')) == NULL)
+ return 0;
+ hostname = xstrndup(spec, p-spec);
+ dirname = xstrdup(p+1);
+#ifdef DEBUG
+ printf("host: %s, directory: %s\n", hostname, dirname);
+#endif
+
+ if (opts && (p = strstr(opts, "addr="))) {
+ char *q;
+
+ free(hostname);
+ p += 5;
+ q = p;
+ while (*q && *q != ',') q++;
+ hostname = xstrndup(p,q-p);
+ }
+
+ if (hostname[0] >= '0' && hostname[0] <= '9')
+ saddr.sin_addr.s_addr = inet_addr(hostname);
+ else
+ if ((hostp = gethostbyname(hostname)) == NULL) {
+ fprintf(stderr, "mount: can't get address for %s\n",
+ hostname);
+ return 1;
+ } else
+ memcpy(&saddr.sin_addr, hostp->h_addr, hostp->h_length);
+
+ saddr.sin_family = AF_INET;
+ saddr.sin_port = 0;
+ pertry.tv_sec = 3;
+ pertry.tv_usec = 0;
+ if ((clp = clntudp_create(&saddr, MOUNTPROG, MOUNTVERS,
+ pertry, &so)) == NULL) {
+ clnt_pcreateerror("Cannot MOUNTPROG RPC");
+ return (1);
+ }
+ clp->cl_auth = authunix_create_default();
+ try.tv_sec = 20;
+ try.tv_usec = 0;
+ clnt_stat = clnt_call(clp, MOUNTPROC_UMNT,
+ (xdrproc_t) xdr_dir, dirname,
+ (xdrproc_t) xdr_void, (caddr_t) 0,
+ try);
+
+ if (clnt_stat != RPC_SUCCESS) {
+ clnt_perror(clp, "Bad UMNT RPC");
+ return (1);
+ }
+ auth_destroy(clp->cl_auth);
+ clnt_destroy(clp);
+
+ return (0);
+}
#endif /* HAVE_NFS */
-
+
+/* complain about a failed umount */
+static void complain(int err, const char *dev) {
+ switch (err) {
+ case ENXIO:
+ error ("umount: %s: invalid block device", dev); break;
+ case EINVAL:
+ error ("umount: %s: not mounted", dev); break;
+ case EIO:
+ error ("umount: %s: can't write superblock", dev); break;
+ case EBUSY:
+ /* Let us hope fstab has a line "proc /proc ..."
+ and not "none /proc ..."*/
+ error ("umount: %s: device is busy", dev); break;
+ case ENOENT:
+ error ("umount: %s: not found", dev); break;
+ case EPERM:
+ error ("umount: %s: must be superuser to umount", dev); break;
+ case EACCES:
+ error ("umount: %s: block devices not permitted on fs", dev); break;
+ default:
+ error ("umount: %s: %s", dev, strerror (err)); break;
+ }
+}
+
+/* Umount a single device. Return a status code, so don't exit
+ 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)
+{
+ 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
@@ -73,122 +176,108 @@ umount_one (const char *spec, const char *node, const char *type)
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"));
+ isroot = (streq (node, "/") || streq (node, "root")
+ || streq (node, "rootfs"));
+ if (isroot)
+ nomtab++;
#ifdef HAVE_NFS
- strcpy(buffer,spec);
- /* spec is constant so must use own buffer */
- if(!strcasecmp(type, "nfs") && (p=strchr(buffer,':')))
- {
- *p='\0';
- strcpy(hostname,buffer);
- strcpy(dirname,p+1);
-#ifdef DEBUG
- printf("host: %s, directory: %s\n", hostname,dirname);
+ /* 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
-
-
- if (hostname[0] >= '0' && hostname[0] <= '9')
- {
- saddr.sin_addr.s_addr = inet_addr(hostname);
- }
- else
- if ((hostp = gethostbyname(hostname)) == NULL)
- {
- fprintf(stderr, "mount: can't get address for %s\n", hostname);
- return(1);
- }
- else
- {
- memcpy(&saddr.sin_addr, hostp->h_addr, hostp->h_length);
- }
-
- saddr.sin_family = AF_INET;
- saddr.sin_port = 0;
- pertry.tv_sec = 3;
- pertry.tv_usec = 0;
- if ((clp = clntudp_create(&saddr, MOUNTPROG, MOUNTVERS,
- pertry, &so)) == NULL)
- {
- clnt_pcreateerror("Cannot MOUNTPROG PRC");
- return (1);
- }
- clp->cl_auth = authunix_create_default();
- try.tv_sec = 20;
- try.tv_usec = 0;
- clnt_stat = clnt_call(clp, MOUNTPROC_UMNT,
- xdr_dir, dirname,
- xdr_void, (caddr_t)0,
- try);
-
- if (clnt_stat != RPC_SUCCESS)
- {
- clnt_perror(clp, "Bad UMNT RPC");
- return (1);
- }
- auth_destroy(clp->cl_auth);
- clnt_destroy(clp);
- }
-#endif /* HAVE_NFS */
- if (!isroot)
- lock_mtab ();
- if (umount (node) >= 0)
- /* Umount succeeded, update mtab. */
- {
+ umnt_err = umnt_err2 = 0;
+ 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 (!isroot)
- {
+ if (!nomtab && mtab_is_writable()) {
+ struct mntentchn *mc;
/* Special stuff for loop devices */
- open_mtab("r");
- if ((mnt = getmntfile (spec)) ||
- (mnt = getmntfile (node))) {
- if (mnt && streq(mnt->mnt_type, "loop")) {
- extern int del_loop(const char *);
-
+
+ if ((mc = getmntfile (spec)) || (mc = getmntfile (node))) {
+ char *opts;
+
+ /* old style mtab line? */
+ if (streq(mc->mnt_type, "loop"))
if (del_loop(spec))
goto fail;
+
+ /* new style mtab line? */
+ opts = mc->mnt_opts ? xstrdup(mc->mnt_opts) : "";
+ for (opts = strtok (opts, ","); opts; opts = strtok (NULL, ",")) {
+ if (!strncmp(opts, "loop=", 5)) {
+ if (del_loop(opts+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;
}
- close_mtab();
/* Non-loop stuff */
update_mtab (node, NULL);
- unlock_mtab ();
- }
+ }
return 0;
- }
+ }
fail:
- /* Umount failed, complain, but don't die. */
- umnt_err = errno;
- if (!isroot)
- unlock_mtab ();
+ /* 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);
+ }
- switch (umnt_err)
- {
- case ENXIO:
- error ("umount: %s: invalid block device", spec); break;
- case EINVAL:
- error ("umount: %s: not mounted", spec); break;
- case EIO:
- error ("umount: %s: can't write superblock", spec); break;
- case EBUSY:
- /* Let us hope fstab has a line "proc /proc ..."
- and not "none /proc ..."*/
- error ("umount: %s: device is busy", spec); break;
- case ENOENT:
- error ("umount: %s: not mounted", spec); break;
- case EPERM:
- error ("umount: %s: must be superuser to umount", spec); break;
- case EACCES:
- error ("umount: %s: block devices not permitted on fs", spec); break;
- default:
- error ("umount: %s: %s", spec, strerror (umnt_err)); break;
- }
+ if (umnt_err2)
+ complain(umnt_err2, spec);
+ if (umnt_err && umnt_err != umnt_err2)
+ complain(umnt_err, node);
return 1;
}
@@ -196,39 +285,24 @@ fail:
concurrently updating mtab after every succesful umount, we have to
slurp in the entire file before we start. This isn't too bad, because
in any case it's important to umount mtab entries in reverse order
- to umount, e.g. /usr/spool before /usr. */
+ to mount, e.g. /usr/spool before /usr. */
static int
-umount_all (string_list types)
-{
- string_list spec_list = NULL;
- string_list node_list = NULL;
- string_list type_list = NULL;
- struct mntent *mnt;
- int errors;
-
- open_mtab ("r");
-
- while ((mnt = getmntent (F_mtab)))
- if (matching_type (mnt->mnt_type, types))
- {
- spec_list = cons (xstrdup (mnt->mnt_fsname), spec_list);
- node_list = cons (xstrdup (mnt->mnt_dir), node_list);
- type_list = cons (xstrdup (mnt->mnt_type), type_list);
- }
-
- close_mtab ();
-
- errors = 0;
- while (spec_list != NULL)
- {
- errors |= umount_one (car (spec_list), car (node_list), car (type_list));
- spec_list = cdr (spec_list);
- node_list = cdr (node_list);
- type_list = cdr (type_list);
- }
+umount_all (string_list types) {
+ struct mntentchn *mc, *hd;
+ int errors = 0;
+
+ hd = mtab_head();
+ 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);
+ }
+ }
- sync ();
- return errors;
+ sync ();
+ return errors;
}
extern char version[];
@@ -237,16 +311,18 @@ static struct option longopts[] =
{ "all", 0, 0, 'a' },
{ "force", 0, 0, 'f' },
{ "help", 0, 0, 'h' },
+ { "no-mtab", 0, 0, 'n' },
{ "verbose", 0, 0, 'v' },
{ "version", 0, 0, 'V' },
+ { "read-only", 0, 0, 'r' },
{ "types", 1, 0, 't' },
{ NULL, 0, 0, 0 }
};
char *usage_string = "\
usage: umount [-hV]\n\
- umount -a [-v] [-t vfstypes]\n\
- umount [-v] special | node...\n\
+ umount -a [-r] [-n] [-v] [-t vfstypes]\n\
+ umount [-r] [-n] [-v] special | node...\n\
";
static void
@@ -265,15 +341,12 @@ main (int argc, char *argv[])
int all = 0;
string_list types = NULL;
string_list options;
- struct mntent *mnt;
- struct mntent mntbuf;
- struct mntent *fs;
+ struct mntentchn *mc, *fs;
char *file;
int result = 0;
- while ((c = getopt_long (argc, argv, "afhvVt:", longopts, NULL)) != EOF)
- switch (c)
- {
+ while ((c = getopt_long (argc, argv, "afhnrvVt:", longopts, NULL)) != EOF)
+ switch (c) {
case 'a': /* umount everything */
++all;
break;
@@ -287,6 +360,12 @@ main (int argc, char *argv[])
case 'h': /* help */
usage (stdout, 0);
break;
+ case 'n':
+ ++nomtab;
+ break;
+ case 'r': /* remount read-only if umount fails */
+ ++remount;
+ break;
case 'v': /* make noise */
++verbose;
break;
@@ -301,65 +380,65 @@ main (int argc, char *argv[])
case '?':
default:
usage (stderr, 1);
- }
+ }
if (getuid () != geteuid ())
{
suid = 1;
- if (all || types)
+ if (all || types || nomtab)
die (2, "umount: only root can do that");
}
argc -= optind;
argv += optind;
- if (all)
- result = umount_all (types);
- else if (argc < 1)
- usage (stderr, 2);
- else while (argc--)
- {
- file = canonicalize (*argv); /* mtab paths are canonicalized */
-
- open_mtab ("r");
- mnt = getmntfile (file);
- if (mnt)
- {
- /* Copy the structure and strings becuase they're in static areas. */
- mntbuf = *mnt;
- mnt = &mntbuf;
- mnt->mnt_fsname = xstrdup (mnt->mnt_fsname);
- mnt->mnt_dir = xstrdup (mnt->mnt_dir);
- }
- close_mtab ();
-
- if (suid)
- {
- if (!mnt)
+ if (all) {
+ if (types == NULL)
+ types = parse_list(xstrdup("noproc"));
+ result = umount_all (types);
+ } else if (argc < 1) {
+ usage (stderr, 2);
+ } else while (argc--) {
+ file = canonicalize (*argv); /* mtab paths are canonicalized */
+ if (verbose > 1)
+ printf("Trying to umount %s\n", file);
+
+ mc = getmntfile (file);
+ if (!mc && verbose)
+ printf("Could not find %s in mtab\n", file);
+
+ if (suid) {
+ if (!mc)
die (2, "umount: %s is not mounted (according to mtab)", file);
if (!(fs = getfsspec (file)) && !(fs = getfsfile (file)))
- die (2, "umount: %s is not in the fstab", file);
- if (!streq (mnt->mnt_fsname, fs->mnt_fsname)
- || !streq (mnt->mnt_dir, fs->mnt_dir))
+ die (2, "umount: %s is not in the fstab (and you are not root)",
+ file);
+ if ((!streq (mc->mnt_fsname, fs->mnt_fsname) &&
+ !streq (mc->mnt_fsname, canonicalize (fs->mnt_fsname)))
+ || (!streq (mc->mnt_dir, fs->mnt_dir) &&
+ !streq (mc->mnt_dir, canonicalize (fs->mnt_dir)))) {
die (2, "umount: %s mount disagrees with the fstab", file);
+ }
options = parse_list (fs->mnt_opts);
- while (options)
- {
+ while (options) {
if (streq (car (options), "user"))
break;
options = cdr (options);
- }
+ }
if (!options)
die (2, "umount: only root can unmount %s from %s",
fs->mnt_fsname, fs->mnt_dir);
- }
+ }
- if (mnt)
- result = umount_one (xstrdup (mnt->mnt_fsname), xstrdup(mnt->mnt_dir),
- xstrdup(mnt->mnt_type));
- else
- result = umount_one (*argv, *argv, *argv);
+ if (mc)
+ result = umount_one (xstrdup(mc->mnt_fsname), xstrdup(mc->mnt_dir),
+ xstrdup(mc->mnt_type), xstrdup(mc->mnt_opts));
+ else
+ result = umount_one (*argv, *argv, *argv, *argv);
- }
+ argv++;
+
+ }
exit (result);
}
+
diff --git a/mount/version.c b/mount/version.c
index 47aed1dcd..c17613e08 100644
--- a/mount/version.c
+++ b/mount/version.c
@@ -1 +1 @@
-char version[] = "version from util-linux-2.5";
+char version[] = "mount-2.7e";