diff options
author | Karel Zak | 2006-12-07 00:25:32 +0100 |
---|---|---|
committer | Karel Zak | 2006-12-07 00:25:32 +0100 |
commit | 6dbe3af945a63f025561abb83275cee9ff06c57b (patch) | |
tree | 19e59eac8ac465b5bc409b5adf815b582c92f633 /mount | |
download | kernel-qcow2-util-linux-6dbe3af945a63f025561abb83275cee9ff06c57b.tar.gz kernel-qcow2-util-linux-6dbe3af945a63f025561abb83275cee9ff06c57b.tar.xz kernel-qcow2-util-linux-6dbe3af945a63f025561abb83275cee9ff06c57b.zip |
Imported from util-linux-2.2 tarball.
Diffstat (limited to 'mount')
-rw-r--r-- | mount/Makefile | 93 | ||||
-rw-r--r-- | mount/README.mount | 147 | ||||
-rw-r--r-- | mount/fstab.5 | 168 | ||||
-rw-r--r-- | mount/fstab.c | 92 | ||||
-rw-r--r-- | mount/fstab.h | 25 | ||||
-rw-r--r-- | mount/lomount.c | 223 | ||||
-rw-r--r-- | mount/loop.h | 77 | ||||
-rw-r--r-- | mount/mount.8 | 589 | ||||
-rw-r--r-- | mount/mount.c | 734 | ||||
-rw-r--r-- | mount/mount.h | 208 | ||||
-rw-r--r-- | mount/mount.x | 161 | ||||
-rw-r--r-- | mount/mount_clnt.c | 94 | ||||
-rw-r--r-- | mount/mount_xdr.c | 150 | ||||
-rw-r--r-- | mount/nfs.5 | 209 | ||||
-rw-r--r-- | mount/nfsmount.c | 475 | ||||
-rw-r--r-- | mount/realpath.c | 178 | ||||
-rw-r--r-- | mount/rpcsvc/mount.h | 208 | ||||
-rw-r--r-- | mount/rpcsvc/mount.x | 161 | ||||
-rw-r--r-- | mount/rpcsvc/mount_clnt.c | 94 | ||||
-rw-r--r-- | mount/rpcsvc/mount_xdr.c | 150 | ||||
-rw-r--r-- | mount/sundries.c | 283 | ||||
-rw-r--r-- | mount/sundries.h | 90 | ||||
-rw-r--r-- | mount/swapoff.8 | 1 | ||||
-rw-r--r-- | mount/swapon.8 | 94 | ||||
-rw-r--r-- | mount/swapon.c | 109 | ||||
-rw-r--r-- | mount/umount.8 | 1 | ||||
-rw-r--r-- | mount/umount.c | 353 | ||||
-rw-r--r-- | mount/version.c | 1 |
28 files changed, 5168 insertions, 0 deletions
diff --git a/mount/Makefile b/mount/Makefile new file mode 100644 index 000000000..737c716ab --- /dev/null +++ b/mount/Makefile @@ -0,0 +1,93 @@ +# To make "ext" the default file system type for mount +# (used when no other type is specified), replace \"minix\" by \"ext2\". +DEFAULT_FSTYPE=\"minix\" + +# you need rpcgen and libc-4.2 or rpclib to compile in the NFS support +DEFINES = -DHAVE_NFS -DFSTYPE_DEFAULT=$(DEFAULT_FSTYPE) + +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) +WARNFLAGS = -Wall -Wstrict-prototypes -Wmissing-prototypes +#LDFLAGS = -s -N +LDLIBS = +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 +#prefix = /usr + +## for suid progs (mount, umount) +#BINDIR = /bin +## for nosuid progs (swapon) +#SBINDIR = /etc + +# End of configuration section. + +COMPILE = $(CC) -c $(WARNFLAGS) $(CFLAGS) $(DEFINES) +LINK = $(CC) $(LDFLAGS) + +SUID_PROGS = mount umount +NOSUID_PROGS = swapon +PROGS = $(SUID_PROGS) $(NOSUID_PROGS) +MAN5 = fstab.5 nfs.5 +MAN8 = mount.8 swapoff.8 swapon.8 umount.8 + +# comment these out if you are not compiling in NFS support +NFS_OBJS = nfsmount.o mount_xdr.o mount_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 + +# comment these out if you are not compiling in loop support +LO_OBJS=lomount.o + +all: $(PROGS) + +install: $(PROGS) + $(INSTALLDIR) $(BINDIR) $(SBINDIR) + $(INSTALLSUID) -s $(SUID_PROGS) $(BINDIR) + $(INSTALLBIN) -s $(NOSUID_PROGS) $(SBINDIR) + (cd $(SBINDIR); ln -sf swapon swapoff) + $(INSTALLDIR) $(MAN5DIR) $(MAN8DIR) + $(INSTALLMAN) $(MAN5) $(MAN5DIR) + $(INSTALLMAN) $(MAN8) $(MAN8DIR) + +.c.o: + $(COMPILE) $< + +mount: mount.o fstab.o sundries.o version.o $(NFS_OBJS) $(LO_OBJS) + $(LINK) $^ $(LDLIBS) -o $@ + +umount: umount.o fstab.o sundries.o version.o $(LO_OBJS) + $(LINK) $^ $(LDLIBS) -o $@ + +swapon: swapon.o fstab.o version.o + $(LINK) $^ $(LDLIBS) -o $@ + +nfsmount.o mount_xdr.o mount_clnt.o: mount.h + +mount_clnt.o: mount_clnt.c + $(COMPILE) $(RPC_CFLAGS) mount_clnt.c + +mount_xdr.o: mount_xdr.c + $(COMPILE) $(RPC_CFLAGS) mount_xdr.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 + +mount.x: + cp $(RPCSVCDIR)/mount.x . + +clean: + rm -f a.out core *~ *.o $(PROGS) + +clobber: clean + rm -f $(PROGS) $(GEN_FILES) diff --git a/mount/README.mount b/mount/README.mount new file mode 100644 index 000000000..9bea2dc2e --- /dev/null +++ b/mount/README.mount @@ -0,0 +1,147 @@ +mount/umount for Linux 0.99.14 +============================== + +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. + +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 new file mode 100644 index 000000000..8f96ee3b8 --- /dev/null +++ b/mount/fstab.5 @@ -0,0 +1,168 @@ +.\" Copyright (c) 1980, 1989, 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" 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 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. +.\" +.\" @(#)fstab.5 6.5 (Berkeley) 5/10/91 +.\" +.\" Modified Sat Mar 6 20:45:03 1993, faith@cs.unc.edu, for Linux +.\" Sat Oct 9 10:07:10 1993: converted to man format by faith@cs.unc.edu +.\" Sat Nov 20 20:47:38 1993: hpfs documentation added +.\" Sat Nov 27 20:23:32 1993: Updated authorship information +.\" +.TH FSTAB 5 "27 November 1993" "Linux 0.99" "Linux Programmer's Manual" +.SH NAME +fstab \- static information about the filesystems +.SH SYNOPSIS +.B #include <fstab.h> +.SH DESCRIPTION +The file +.B fstab +contains descriptive information about the various file systems. +.B fstab +is only read by programs, and not written; it is the duty of the system +administrator to properly create and maintain this file. Each filesystem +is described on a separate line; fields on each line are separated by tabs +or spaces. The order of records in +.B fstab +is important because +.BR fsck "(8), " mount "(8), and " umount "(8) +sequentially iterate through +.B fstab +doing their thing. + +The first field, +.RI ( fs_spec ), +describes the block special device or +remote filesystem to be mounted. + +The second field, +.RI ( fs_file ), +describes the mount point for the filesystem. For swap partitions, this +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: +.TP +.I minix +a local filesystem, supporting filenames of length 14 or 30 characters. +.TP +.I ext +a local filesystem with longer filenames and larger inodes. This +filesystem has been replaced by the +.I ext2 +file system, and should no longer be used. +.TP +.I ext2 +a local filesystem with longer filenames, larger inodes, and lots of other +features. +.TP +.I xiafs +a local filesystem with longer filenames, larger inodes, and lots of other +features. +.TP +.I msdos +a local filesystem for MS-DOS partitions. +.TP +.I hpfs +a local filesystem for HPFS partitions. +.TP +.I iso9660 +a local filesystem used for CD-ROM drives. +.TP +.I nfs +a filesystem for mounting partitions from remote systems. +.TP +.I swap +a disk partition to be used for swapping. +.PP +If +.I vfs_fstype +is specified as ``ignore'' the entry is ignored. This is useful to show +disk partitions which are currently unused. + +The fourth field, +.RI ( fs_mntops ), +describes the mount options associated with the filesystem. + +It is formatted as a comma separated list of options. It contains at least +the type of mount plus any additional options appropriate to the filesystem +type. For documentation on all of the available options, see +.BR mount (8). + +The fifth field, +.RI ( fs_freq ), +is used for these filesystems by the +.BR dump (8) +command to determine which filesystems need to be dumped. If the fifth +field is not present, a value of zero is returned and +.B dump +will assume that the filesystem does not need to be dumped. + +The sixth field, +.RI ( fs_passno ), +is used by the +.BR fsck (8) +program to determine the order in which filesystem checks are done at +reboot time. The root filesystem should be specified with a +.I fs_passno +of 1, and other filesystems should have a +.I fs_passno +of 2. Filesystems within a drive will be checked sequentially, but +filesystems on different drives will be checked at the same time to utilize +parallelism available in the hardware. If the sixth field is not present +or zero, a value of zero is returned and +.B fsck +will assume that the filesystem does not need to be checked. + +The proper way to read records from +.B fstab +is to use the routines +.BR getmntent (3). +.SH FILES +.I /etc/fstab +The file +.B fstab +resides in +.IR /etc . +.SH BUGS +Linux does not, currently, support the special fields for +.BR dump " and " fsck . + +The documentation in +.BR mount (8) +is often more up-to-date. +.SH "SEE ALSO" +.BR getmntent "(3), " mount "(8), " swapon (8) +.SH HISTORY +The +.B fstab +file format appeared in 4.0BSD. diff --git a/mount/fstab.c b/mount/fstab.c new file mode 100644 index 000000000..95b0879e0 --- /dev/null +++ b/mount/fstab.c @@ -0,0 +1,92 @@ +/* /home/faith/cvs/util-linux/mount/fstab.c,v 1.1.1.1 1995/02/22 19:09:21 faith Exp */ + +#include "fstab.h" +#include <stdio.h> + +#define streq(s, t) (strcmp ((s), (t)) == 0) + +/* These routines are superceded 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. */ + + +static FILE *F_fstab = NULL; + +/* Open fstab or rewind if already open. */ +int +setfsent (void) +{ + if (F_fstab) + return (fseek (F_fstab, 0L, SEEK_SET) == 0); + + F_fstab = setmntent (_PATH_FSTAB, "r"); + return (F_fstab != NULL); +} + +/* Close fstab. */ +void +endfsent (void) +{ + endmntent (F_fstab); +} + +/* 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 + break; + } + else if ((*fstab->mnt_fsname != '#') + && !streq (fstab->mnt_type, MNTTYPE_IGNORE)) + break; + } + return fstab; +} + +/* Find the dir FILE in fstab. */ +struct mntent * +getfsfile (const char *file) +{ + struct mntent *fstab; + + /* Open or rewind fstab. */ + if (!setfsent ()) + return 0; + + while ((fstab = getfsent ())) + if (streq (fstab->mnt_dir, file)) + break; + + return fstab; +} + +/* Find the device SPEC in fstab. */ +struct mntent * +getfsspec (const char *spec) +{ + struct mntent *fstab; + + /* Open or rewind fstab. */ + if (!setfsent()) + return 0; + + while ((fstab = getfsent ())) + if (streq (fstab->mnt_fsname, spec)) + break; + + return fstab; +} diff --git a/mount/fstab.h b/mount/fstab.h new file mode 100644 index 000000000..c3c48b9e4 --- /dev/null +++ b/mount/fstab.h @@ -0,0 +1,25 @@ +/* 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. + /home/faith/cvs/util-linux/mount/fstab.h,v 1.1.1.1 1995/02/22 19:09:21 faith Exp */ + +#ifndef _FSTAB_H +#include <stdio.h> +#include <mntent.h> + +#define _PATH_FSTAB "/etc/fstab" + +/* 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 FSTAB_SW MNTTYPE_SWAP + +struct fstab *getfsent (void); +struct fstab *getfsspec (const char *spec); +struct fstab *getfsfile (const char *file); +int setfsent (void); +void endfsent (void); + +#endif /* _FSTAB_H */ diff --git a/mount/lomount.c b/mount/lomount.c new file mode 100644 index 000000000..5dd02d8bb --- /dev/null +++ b/mount/lomount.c @@ -0,0 +1,223 @@ +/* Taken from Ted's losetup.c - Mitch <m.dsouza@mrc-apu.cam.ac.uk> */ + +/* + * losetup.c - setup and control loop devices + */ + +#include <stdio.h> +#include <string.h> +#include <ctype.h> +#include <fcntl.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/ioctl.h> +#include <linux/fs.h> +#include "loop.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 **); + +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 + } +}; + +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"; +} + +int +crypt_type (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; +} + +void +show_loop (char *device) +{ + struct loop_info loopinfo; + int fd; + + if ((fd = open (device, O_RDWR)) < 0) { + fprintf(stderr, "loop: can't open device %s: %s\n", + device, strerror (errno)); + return; + } + if (ioctl (fd, LOOP_GET_STATUS, &loopinfo) < 0) { + fprintf(stderr, "loop: can't get info on device %s: %s\n", + device, strerror (errno)); + 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, char *encryption) +{ + struct loop_info loopinfo; + int fd, + ffd, + i; + char *pass; + + if ((fd = open (device, O_RDWR)) < 0) { + perror (device); + return 1; + } + if ((ffd = open (file, O_RDWR)) < 0) { + perror (file); + return 1; + } + 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); + return 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]); + return 1; + } + break; + default: + fprintf (stderr, + "Don't know how to get key for encryption system %d\n", + loopinfo.lo_encrypt_type); + return 1; + } + if (ioctl (fd, LOOP_SET_FD, ffd) < 0) { + perror ("ioctl: LOOP_SET_FD"); + return 1; + } + if (ioctl (fd, LOOP_SET_STATUS, &loopinfo) < 0) { + (void) ioctl (fd, LOOP_CLR_FD, 0); + perror ("ioctl: LOOP_SET_STATUS"); + return 1; + } + close (fd); + close (ffd); + return 0; +} + +int +del_loop (const char *device) +{ + int fd; + + if ((fd = open (device, O_RDONLY)) < 0) { + fprintf(stderr, "loop: can't delete device %s: %s\n", + device, strerror (errno)); + return 1; + } + if (ioctl (fd, LOOP_CLR_FD, 0) < 0) { +#if 0 + perror ("ioctl: LOOP_CLR_FD"); +#endif + return 1; + } + return 0; +} + + +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; +} diff --git a/mount/loop.h b/mount/loop.h new file mode 100644 index 000000000..81ee7611e --- /dev/null +++ b/mount/loop.h @@ -0,0 +1,77 @@ +#ifndef _LINUX_LOOP_H +#define _LINUX_LOOP_H + +/* + * include/linux/loop.h + * + * Written by Theodore Ts'o, 3/29/93. + * + * Copyright 1993 by Theodore Ts'o. Redistribution of this file is + * permitted under the GNU Public License. + */ + +#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 */ + unsigned long lo_inode; /* ioctl r/o */ + dev_t lo_rdevice; /* ioctl r/o */ + int lo_offset; + int lo_encrypt_type; + int lo_encrypt_key_size; /* ioctl w/o */ + int lo_flags; /* ioctl r/o */ + char lo_name[LO_NAME_SIZE]; + unsigned char lo_encrypt_key[LO_KEY_SIZE]; /* ioctl w/o */ + unsigned long lo_init[2]; + char reserved[4]; +}; + +/* + * Loop encryption types --- LO_CRYPT_IDEA isn't supported yet + */ + +#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 + +/* + * IOCTL commands --- we will commandeer 0x4C ('L') + */ + +#define LOOP_SET_FD 0x4C00 +#define LOOP_CLR_FD 0x4C01 +#define LOOP_SET_STATUS 0x4C02 +#define LOOP_GET_STATUS 0x4C03 + +#endif diff --git a/mount/mount.8 b/mount/mount.8 new file mode 100644 index 000000000..a47091dde --- /dev/null +++ b/mount/mount.8 @@ -0,0 +1,589 @@ +.\" Copyright (c) 1980, 1989, 1991 The Regents of the University of California. +.\" All rights reserved. +.\" +.\" 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 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. +.\" +.\" @(#)mount.8 6.17 (Berkeley) 8/5/91 +.\" +.\" When you change this file, please add an update notice to the ones below: +.\" +.\" 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. +.\" +.TH MOUNT 8 "8 February 1995" "Linux 1.1" "Linux Programmer's Manual" +.SH NAME +mount, umount \- mount and dismount file systems +.SH SYNOPSIS +.BI "mount [\-afrwuvn] [\-t " vfstype ] +.br +.BI "mount [\-frwuvn] [\-o " remount " [,...]] " "special " | " node" +.br +.BI "mount [\-frwun] [\-t " vfstype "] [\-o " options "] " "special node" +.br +.BI "umount [\-an] [\-t " vfstype ] +.br +.BI "umount " "special " | " node" +.\" " for hilit19 +.SH DESCRIPTION +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 special keyword +.I none +can be used instead of a path or +.I node +specification. This is useful when mounting the +.I proc +file system. + +The system maintains a list of currently mounted file systems. If no +arguments are given to +.BR mount , +this list is printed. + +Options available for the +.B mount +command: +.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 +conjunction with the +.B \-v +flag to determine what the +.B mount +command is trying to do. +.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 +.I /etc/fstab +file. The following options apply to any file system that is being +mounted: +.RS +.TP +.B async +All I/O to the file system should be done asynchronously. +.TP +.B auto +Can be mounted with the +.B \-a +option. +.TP +.B defaults +Use default options: +.BR rw ", " suid ", " dev ", " exec ", " auto ", " nouser ", and " async. +.TP +.B dev +Interpret character or block special devices on the file system. +.TP +.B exec +Permit execution of binaries. +.TP +.B noauto +Can only be mounted explicitly (i.e., the +.B \-a +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. +.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 +binaries for architectures other than its own. +.TP +.B nosuid +Do not allow set-user-identifier or set-group-identifier bits to take +effect. +.TP +.B nouser +Forbid an ordinary (i.e., non-root) user to mount the file system. +.TP +.B remount +Attempt to remount an already-mounted file system. This is commonly +used to change the mount flags for a file system, especially to make a +readonly file system writeable. +.TP +.B ro +Mount the file system read-only. +.TP +.B rw +Mount the file system read-write. +.TP +.B suid +Allow set-user-identifier or set-group-identifier bits to take +effect. +.TP +.B sync +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: +.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: +.TP +.BI case= value +For the +.I hpfs +file system, specify case as +.I lower +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 (0.99.15), the following values can be specified with +this option: +.RS +.TP +.I none +no extra check is performed by the kernel code +.TP +.I normal +The inodes and blocks bitmaps are checked when the file system is mounted +(this is the default) +.TP +.I strict +In addition to the +.I normal +checks, block deallocation checks that the block to free is in the data +zone. +.RE +.TP +.BI check= value +For the +.I msdos +file system, three different levels of pickyness can be chosen: +.RS +.TP +.I relaxed +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). +.TP +.I normal +Like "relaxed", but many special characters (*, ?, <, spaces, etc.) are +rejected. This is the default. +.TP +.I strict +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 . +The +.I iso9660 +file system also allows +.I value +to be +.IR mtext . + +The +.I msdos +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 +no translation is performed. This is the default. +.TP +.I text +CRLF<-->NL translation is performed on all files. +.TP +.I 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 09913r, 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, +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. + +For file systems mounted in +.B 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 +.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 +.TP +.B ro +The file system is remounted read only, and subsequent writes are refused. +.TP +.B panic +When an error is detected, the system panics. +.RE +.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! +.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 . +.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 +Normal +.I iso9600 +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 +block/character devices, etc. + +Rock Ridge is an extension to iso9660 that provides all of these unix like +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 +.B norock +switch disables the use of Rock Ridge extensions, even if available. C.f. +.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 +.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 +and +.I hpfs +file systems, give every file a uid equal to +.IR value . +.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. + +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 minux ", " ext ", " ext2 ", " xiafs ", " msdos ", " hpfs , +.IR proc ", " nfs ", " iso9660 ", " 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, 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"). + +For example, the +.B mount +command: +.RS + +.RS +mount -a -t nomsdos,ext +.RE + +mounts all file systems except those of type +.I msdos +and +.IR ext . +.RE +.TP +.B \-v +Verbose mode. +.TP +.B \-w +The file system object is to be read and write. +.TP +.B \-n +Mount without writing in +.IR /etc/mtab . +.PP +.B Umount +removes the +.I special +device grafted at point +.I node +from file system tree. + +Options for the +.B umount +command: +.TP +.B \-a +All of the file systems described in +.I /etc/mtab +are unmounted. +.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 +.B mount +command.) + +.SH FILES +.I /etc/fstab +file system table +.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) +.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" +(the ext2fs +.I does +support synchronous updates (a la BSD) when mounted with the +.B sync +option). +.PP +The +.BI \-o " remount" +may not be able to change mount parameters (all +.I ext2fs +parameters, except +.BR sb , +are changeable with a remount, for example, but you can't change +.B gid +or +.B umask +for the +.IR dosfs ). +.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 new file mode 100644 index 000000000..b6ffbcd67 --- /dev/null +++ b/mount/mount.c @@ -0,0 +1,734 @@ +/* + * A mount(8) for Linux 0.99. + * mount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp + * + * Thu Jul 14 07:32:40 1994: faith@cs.unc.edu added changed from Adam + * J. Richter (adam@adam.yggdrasil.com) so that /proc/filesystems is used + * if no -t option is given. I modified his patches so that, if + * /proc/filesystems is not available, the behavior of mount is the same as + * it was previously. + * + * Wed Sep 14 22:43:00 1994: Mitchum DSouza + * (mitch@mrc-applied-psychology.cambridge.ac.uk) added support for mounting + * the "loop" device. + * + * Wed Sep 14 22:55:10 1994: Sander van Malssen (svm@kozmix.hacktic.nl) + * added support for remounting readonly file systems readonly. + * + * Wed Feb 8 09:23:18 1995: Mike Grupenhoff <kashmir@umiacs.UMD.EDU> added + * a probe of the superblock for the type before /proc/filesystems is + * checked. + * + * Wed Feb 8 12:27:00 1995: Andries.Brouwer@cwi.nl fixed up error messages. + * + */ + +#include "sundries.h" + +#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> + +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). */ +int readonly = 0; + +/* Nonzero for chatty (-v). */ +int verbose = 0; + +/* True for read/write (-w). */ +int readwrite = 0; + +/* True for all mount (-a). */ +int all = 0; + +/* True if ruid != euid. */ +int suid = 0; + +/* Map from -o and fstab option strings to the flag argument to mount(2). */ +struct opt_map +{ + const char *opt; /* option name */ + int inv; /* true if flag value should be inverted */ + int mask; /* flag mask value */ +}; + +/* Custom mount options for our own purposes. */ +#define MS_NOAUTO 0x80000000 +#define MS_USER 0x40000000 + +/* Options that we keep the mount system call from seeing. */ +#define MS_NOSYS (MS_NOAUTO|MS_USER) + +/* Options that we keep from appearing in the options field in the mtab. */ +#define MS_NOMTAB (MS_REMOUNT|MS_NOAUTO|MS_USER) + +/* 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 */ + /* add new options here */ +#ifdef MS_NOSUB + { "sub", 1, MS_NOSUB }, /* allow submounts */ + { "nosub", 0, MS_NOSUB }, /* don't allow submounts */ +#endif + { NULL, 0, 0 } +}; + + +/* Report on a single mount. */ +static void +print_one (const struct mntent *mnt) +{ + 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"); +} + +/* 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); + + if (ferror (F_mtab)) + die (1, "mount: error reading %s: %s", MOUNTED, strerror (errno)); + + exit (0); +} + + +/* Look for OPT in opt_map table and return mask value. If OPT isn't found, + tack it onto extra_opts. */ +static inline void +parse_opt (const char *opt, int *mask, char *extra_opts) +{ + const struct opt_map *om; + + for (om = opt_map; om->opt != NULL; om++) + if (streq (opt, om->opt)) + { + if (om->inv) + *mask &= ~om->mask; + else + *mask |= om->mask; + if (om->mask == MS_USER) + *mask |= MS_SECURE; + return; + } + if (*extra_opts) + strcat(extra_opts, ","); + strcat(extra_opts, opt); +} + +/* Take -o options list and compute 4th and 5th args to mount(2). flags + gets the standard options and extra_opts anything we don't recognize. */ +static void +parse_opts (char *opts, int *flags, char **extra_opts) +{ + char *opt; + + *flags = 0; + *extra_opts = NULL; + + 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); + } + + if (readonly) + *flags |= MS_RDONLY; + if (readwrite) + *flags &= ~MS_RDONLY; +} + +/* Try to build a canonical options string. */ +static char * +fix_opts_string (int flags, char *extra_opts) +{ + const struct opt_map *om; + 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) + 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; + 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; + } + return new_opts; +} + + +/* + char *fstype(const char *device); + + probes the device and attempts to determine the type of filesystem + contained within. + + Original routine by <jmorriso@bogomips.ww.ubc.ca>; made into a function + for mount(8) by Mike Grupenhoff <kashmir@umiacs.umd.edu>. + + Currently supports: minix, ext, ext2, xia +*/ + +static char * +fstype(const char *device) +{ + int fd; + + /* MINIX */ + struct minix_super_block ms; + /* extended fs */ + struct ext_super_block es; + /* 2nd extended fs */ + struct ext2_super_block e2s; + /* xia fs */ + struct xiafs_super_block xfs; + + fd = open(device, O_RDONLY); + if (fd < 0) { + perror(device); + return 0; + } + lseek(fd, BLOCK_SIZE, SEEK_SET); + read(fd, (char *) &ms, sizeof(ms)); + if (ms.s_magic == MINIX_SUPER_MAGIC || ms.s_magic == MINIX_SUPER_MAGIC2) { + close(fd); + return("minix"); + } + + lseek(fd, BLOCK_SIZE, SEEK_SET); + read(fd, (char *) &es, sizeof(es)); + if (es.s_magic == EXT_SUPER_MAGIC) { + close(fd); + return("ext"); + } + + lseek(fd, BLOCK_SIZE, SEEK_SET); + read(fd, (char *) &e2s, sizeof(e2s)); + if (e2s.s_magic == EXT2_SUPER_MAGIC || e2s.s_magic == EXT2_PRE_02B_MAGIC) { + close(fd); + return("ext2"); + } + + lseek(fd, 0, SEEK_SET); + read(fd, (char *) &xfs, sizeof(xfs)); + if (xfs.s_magic == _XIAFS_SUPER_MAGIC) { + close(fd); + return("xiafs"); + } + + close(fd); + + return(0); + +} + + +/* Mount a single file system. Return status, + so don't exit on non-fatal errors. */ + +static int +try_mount5 (char *spec, char *node, char **type, int flags, char *mount_opts) { + FILE *procfs_file; + char line[100]; + char fsname[50]; + + if (*type) return mount5 (spec, node, *type, flags & ~MS_NOSYS, mount_opts); + if (( procfs_file = fopen("/proc/filesystems", "r")) == NULL) { + /* If /proc/filesystems is not available, + preserve the old behavior of mount. */ + return mount5 (spec, + node, + FSTYPE_DEFAULT, + flags & ~MS_NOSYS, mount_opts); + } + while (fgets(line, sizeof(line), procfs_file)) { + if (sscanf (line, "nodev %[^\n]\n", fsname) == 1) continue; + if (sscanf (line, " %[^ \n]\n", fsname) != 1) continue; + if (mount5 (spec, node, fsname, flags & ~MS_NOSYS, mount_opts) == 0) { + *type=xstrdup(fsname); + fclose(procfs_file); + return 0; + } + } + fclose(procfs_file); + return -1; +} + + +static int +mount_one (char *spec, char *node, char *type, char *opts, int freq, int pass) +{ + struct mntent mnt; + int mnt_err; + int flags; + char *extra_opts; + char *mount_opts; + int anti_recurse = 0; + int loop=0; + + if (type == NULL) + { + if (strchr (spec, ':') != NULL) + type = "nfs"; + } + + parse_opts (xstrdup (opts), &flags, &extra_opts); + + /* root may allow certain types of mounts by ordinary users */ + if (suid && !(flags & MS_USER)) + die (3, "mount: only root can mount %s on %s", spec, node); + + /* quietly succeed for fstab entries that don't get mounted automatically */ + if (all && (flags & MS_NOAUTO)) + return 0; + + 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; + + loop=1; + if (lomount (spec, node, dev, &type, + &flags, &opts, &mount_opts) != 0) + return 1; + spec=dev; + mount_opts=NULL; + } + + if (!fake && type && streq (type, "nfs")) +#ifdef HAVE_NFS + if (nfsmount (spec, node, &flags, &extra_opts, &mount_opts) != 0) + return 1; +#else + die (1, "mount: this version doesn't support the type `nfs'"); +#endif + + if (!type && !(type = fstype(spec))) + return 1; + + block_signals (SIG_BLOCK); + + if (fake + || (try_mount5 (spec, node, &type, flags & ~MS_NOSYS, mount_opts)) == 0) + /* Mount succeeded, 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; + + /* 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); + + 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)); + } + + block_signals (SIG_UNBLOCK); + return 0; + } + + 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. */ + switch (mnt_err) + { + case EPERM: + if (geteuid() == 0) + error ("mount: mount point %s is not a directory", node); + else + error ("mount: must be superuser to use mount"); + break; + case EBUSY: + error ("mount: %s already mounted or %s busy", spec, node); + break; + case ENOENT: + { struct stat statbuf; + if (stat (node, &statbuf)) + error ("mount: mount point %s does not exist", node); + else if (stat (spec, &statbuf)) + error ("mount: special device %s does not exist", spec); + else { + errno = mnt_err; + perror("mount"); + } + break; + } + case ENOTDIR: + 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; + case EMFILE: + error ("mount table full"); break; + case EIO: + error ("mount: %s: can't read superblock", spec); break; + case ENODEV: + error ("mount: fs type %s not supported by kernel", type); break; + case ENOTBLK: + 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 EROFS: /* linux 1.1.38 and later */ + if (anti_recurse) + { + error ("mount: block device %s is not permitted on its filesystem", spec); + break; + } + else + { + anti_recurse++; + if (opts) + { + opts = realloc(xstrdup(opts), strlen(opts)+3); + strcat(opts, ",ro"); + } + else + opts = "ro"; + error ("mount: block device %s is write-protected, mounting read-only", spec); + return mount_one (spec, node, type, opts, freq, pass); + } + break; + default: + error ("mount: %s", strerror (mnt_err)); break; + } + return 1; +} + +/* 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); + } + + status = 0; + 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); + + return status; +} + +/* 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); + + 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); +} + +extern char version[]; +static struct option longopts[] = +{ + { "all", 0, 0, 'a' }, + { "fake", 0, 0, 'f' }, + { "help", 0, 0, 'h' }, + { "no-mtab", 0, 0, 'n' }, + { "read-only", 0, 0, 'r' }, + { "ro", 0, 0, 'r' }, + { "verbose", 0, 0, 'v' }, + { "version", 0, 0, 'V' }, + { "read-write", 0, 0, 'w' }, + { "rw", 0, 0, 'w' }, + { "options", 1, 0, 'o' }, + { "types", 1, 0, 't' }, + { NULL, 0, 0, 0 } +}; + +const char *usage_string = "\ +usage: mount [-hV]\n\ + mount -a [-nfrvw] [-t vfstypes]\n\ + mount [-nfrvw] [-o options] special | node\n\ + mount [-nfrvw] [-t vfstype] [-o options] special node\n\ +"; + +static void +usage (FILE *fp, int n) +{ + fprintf (fp, "%s", usage_string); + exit (n); +} + +int +main (int argc, char *argv[]) +{ + int c; + char *options = NULL; + string_list types = NULL; + struct mntent *fs; + char *spec; + int result = 0; + struct stat statbuf; + + while ((c = getopt_long (argc, argv, "afhnrvVwt:o:", 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 'h': /* help */ + usage (stdout, 0); + break; + case 'n': /* mount without writing in /etc/mtab */ + ++nomtab; + break; + case 'r': /* mount readonly */ + ++readonly; + readwrite = 0; + break; + case 'v': /* be chatty */ + ++verbose; + break; + case 'V': /* version */ + printf ("%s\n", version); + exit (0); + case 'w': /* mount read/write */ + ++readwrite; + 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; + } + + argc -= optind; + argv += optind; + + if (argc == 0) + { + if (options) + usage (stderr, 1); + if (!all) + return print_all (types); + } + + 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"); + + + switch (argc) + { + case 0: + /* mount -a */ + result = mount_all (types); + break; + + case 1: + /* mount [-nfrvw] [-o options] special | node */ + if (types != NULL) + usage (stderr, 1); + /* 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); + /* Merge the fstab and command line options. */ + if (options == NULL) + options = fs->mnt_opts; + else + { + char *tmp = xmalloc(strlen(fs->mnt_opts) + strlen(options) + 2); + + 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); + break; + + case 2: + /* mount [-nfrvw] [-t vfstype] [-o options] special node */ + if (types == NULL) + result = mount_one (argv[0], argv[1], NULL, options, 0, 0); + else if (cdr (types) == NULL) + result = mount_one (argv[0], argv[1], car (types), options, 0, 0); + else + usage (stderr, 2); + break; + + default: + usage (stderr, 2); + } + + if (!nomtab) + { + endmntent (F_mtab); + unlock_mtab (); + } + + exit (result); +} diff --git a/mount/mount.h b/mount/mount.h new file mode 100644 index 000000000..d70ccaf9d --- /dev/null +++ b/mount/mount.h @@ -0,0 +1,208 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _MOUNT_H_RPCGEN +#define _MOUNT_H_RPCGEN + +#include <rpc/rpc.h> + +#define MNTPATHLEN 1024 +#define MNTNAMLEN 255 +#define FHSIZE 32 + +typedef char fhandle[FHSIZE]; +#ifdef __cplusplus +extern "C" bool_t xdr_fhandle(XDR *, fhandle); +#elif __STDC__ +extern bool_t xdr_fhandle(XDR *, fhandle); +#else /* Old Style C */ +bool_t xdr_fhandle(); +#endif /* Old Style C */ + + +struct fhstatus { + u_int fhs_status; + union { + fhandle fhs_fhandle; + } fhstatus_u; +}; +typedef struct fhstatus fhstatus; +#ifdef __cplusplus +extern "C" bool_t xdr_fhstatus(XDR *, fhstatus*); +#elif __STDC__ +extern bool_t xdr_fhstatus(XDR *, fhstatus*); +#else /* Old Style C */ +bool_t xdr_fhstatus(); +#endif /* Old Style C */ + + +typedef char *dirpath; +#ifdef __cplusplus +extern "C" bool_t xdr_dirpath(XDR *, dirpath*); +#elif __STDC__ +extern bool_t xdr_dirpath(XDR *, dirpath*); +#else /* Old Style C */ +bool_t xdr_dirpath(); +#endif /* Old Style C */ + + +typedef char *name; +#ifdef __cplusplus +extern "C" bool_t xdr_name(XDR *, name*); +#elif __STDC__ +extern bool_t xdr_name(XDR *, name*); +#else /* Old Style C */ +bool_t xdr_name(); +#endif /* Old Style C */ + + +typedef struct mountbody *mountlist; +#ifdef __cplusplus +extern "C" bool_t xdr_mountlist(XDR *, mountlist*); +#elif __STDC__ +extern bool_t xdr_mountlist(XDR *, mountlist*); +#else /* Old Style C */ +bool_t xdr_mountlist(); +#endif /* Old Style C */ + + +struct mountbody { + name ml_hostname; + dirpath ml_directory; + mountlist ml_next; +}; +typedef struct mountbody mountbody; +#ifdef __cplusplus +extern "C" bool_t xdr_mountbody(XDR *, mountbody*); +#elif __STDC__ +extern bool_t xdr_mountbody(XDR *, mountbody*); +#else /* Old Style C */ +bool_t xdr_mountbody(); +#endif /* Old Style C */ + + +typedef struct groupnode *groups; +#ifdef __cplusplus +extern "C" bool_t xdr_groups(XDR *, groups*); +#elif __STDC__ +extern bool_t xdr_groups(XDR *, groups*); +#else /* Old Style C */ +bool_t xdr_groups(); +#endif /* Old Style C */ + + +struct groupnode { + name gr_name; + groups gr_next; +}; +typedef struct groupnode groupnode; +#ifdef __cplusplus +extern "C" bool_t xdr_groupnode(XDR *, groupnode*); +#elif __STDC__ +extern bool_t xdr_groupnode(XDR *, groupnode*); +#else /* Old Style C */ +bool_t xdr_groupnode(); +#endif /* Old Style C */ + + +typedef struct exportnode *exports; +#ifdef __cplusplus +extern "C" bool_t xdr_exports(XDR *, exports*); +#elif __STDC__ +extern bool_t xdr_exports(XDR *, exports*); +#else /* Old Style C */ +bool_t xdr_exports(); +#endif /* Old Style C */ + + +struct exportnode { + dirpath ex_dir; + groups ex_groups; + exports ex_next; +}; +typedef struct exportnode exportnode; +#ifdef __cplusplus +extern "C" bool_t xdr_exportnode(XDR *, exportnode*); +#elif __STDC__ +extern bool_t xdr_exportnode(XDR *, exportnode*); +#else /* Old Style C */ +bool_t xdr_exportnode(); +#endif /* Old Style C */ + + +#define MOUNTPROG ((u_long)100005) +#define MOUNTVERS ((u_long)1) + +#ifdef __cplusplus +#define MOUNTPROC_NULL ((u_long)0) +extern "C" void * mountproc_null_1(void *, CLIENT *); +extern "C" void * mountproc_null_1_svc(void *, struct svc_req *); +#define MOUNTPROC_MNT ((u_long)1) +extern "C" fhstatus * mountproc_mnt_1(dirpath *, CLIENT *); +extern "C" fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_DUMP ((u_long)2) +extern "C" mountlist * mountproc_dump_1(void *, CLIENT *); +extern "C" mountlist * mountproc_dump_1_svc(void *, struct svc_req *); +#define MOUNTPROC_UMNT ((u_long)3) +extern "C" void * mountproc_umnt_1(dirpath *, CLIENT *); +extern "C" void * mountproc_umnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_UMNTALL ((u_long)4) +extern "C" void * mountproc_umntall_1(void *, CLIENT *); +extern "C" void * mountproc_umntall_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORT ((u_long)5) +extern "C" exports * mountproc_export_1(void *, CLIENT *); +extern "C" exports * mountproc_export_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORTALL ((u_long)6) +extern "C" exports * mountproc_exportall_1(void *, CLIENT *); +extern "C" exports * mountproc_exportall_1_svc(void *, struct svc_req *); + +#elif __STDC__ +#define MOUNTPROC_NULL ((u_long)0) +extern void * mountproc_null_1(void *, CLIENT *); +extern void * mountproc_null_1_svc(void *, struct svc_req *); +#define MOUNTPROC_MNT ((u_long)1) +extern fhstatus * mountproc_mnt_1(dirpath *, CLIENT *); +extern fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_DUMP ((u_long)2) +extern mountlist * mountproc_dump_1(void *, CLIENT *); +extern mountlist * mountproc_dump_1_svc(void *, struct svc_req *); +#define MOUNTPROC_UMNT ((u_long)3) +extern void * mountproc_umnt_1(dirpath *, CLIENT *); +extern void * mountproc_umnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_UMNTALL ((u_long)4) +extern void * mountproc_umntall_1(void *, CLIENT *); +extern void * mountproc_umntall_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORT ((u_long)5) +extern exports * mountproc_export_1(void *, CLIENT *); +extern exports * mountproc_export_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORTALL ((u_long)6) +extern exports * mountproc_exportall_1(void *, CLIENT *); +extern exports * mountproc_exportall_1_svc(void *, struct svc_req *); + +#else /* Old Style C */ +#define MOUNTPROC_NULL ((u_long)0) +extern void * mountproc_null_1(); +extern void * mountproc_null_1_svc(); +#define MOUNTPROC_MNT ((u_long)1) +extern fhstatus * mountproc_mnt_1(); +extern fhstatus * mountproc_mnt_1_svc(); +#define MOUNTPROC_DUMP ((u_long)2) +extern mountlist * mountproc_dump_1(); +extern mountlist * mountproc_dump_1_svc(); +#define MOUNTPROC_UMNT ((u_long)3) +extern void * mountproc_umnt_1(); +extern void * mountproc_umnt_1_svc(); +#define MOUNTPROC_UMNTALL ((u_long)4) +extern void * mountproc_umntall_1(); +extern void * mountproc_umntall_1_svc(); +#define MOUNTPROC_EXPORT ((u_long)5) +extern exports * mountproc_export_1(); +extern exports * mountproc_export_1_svc(); +#define MOUNTPROC_EXPORTALL ((u_long)6) +extern exports * mountproc_exportall_1(); +extern exports * mountproc_exportall_1_svc(); +#endif /* Old Style C */ + +#endif /* !_MOUNT_H_RPCGEN */ diff --git a/mount/mount.x b/mount/mount.x new file mode 100644 index 000000000..7e0d7f3ad --- /dev/null +++ b/mount/mount.x @@ -0,0 +1,161 @@ +/* @(#)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 new file mode 100644 index 000000000..bc6e5122b --- /dev/null +++ b/mount/mount_clnt.c @@ -0,0 +1,94 @@ +/* + * 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_xdr.c b/mount/mount_xdr.c new file mode 100644 index 000000000..be5eb41f1 --- /dev/null +++ b/mount/mount_xdr.c @@ -0,0 +1,150 @@ +/* + * 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.5 b/mount/nfs.5 new file mode 100644 index 000000000..ee5203f5a --- /dev/null +++ b/mount/nfs.5 @@ -0,0 +1,209 @@ +.\" nfs.5 "Rick Sladkey" <jrs@world.std.com> +.\" Wed Feb 8 12:52:42 1995, faith@cs.unc.edu: updates for Ross Biro's +.\" patches. " +.TH NFS 5 "20 November 1993" "Linux 0.99" "Linux Programmer's Manual" +.SH NAME +nfs \- nfs fstab format and options +.SH SYNOPSIS +.B /etc/fstab +.SH DESCRIPTION +The +.I fstab +file contains information about which filesystems +to mount where and with what options. +For NFS mounts, it contains the server name and +exported server directory to mount from, +the local directory that is the mount point, +and the NFS specific options that control +the way the filesystem is mounted. +.P +Here is an example from an \fI/etc/fstab\fP file from an NFS mount. +.sp +.nf +.ta 2.5i +0.75i +0.75i +1.0i +server:/usr/local/pub /pub nfs timeo=14,intr +.fi +.DT +.SS Options +.TP 1.5i +.I rsize=n +The number of bytes NFS uses when reading files from an NFS server. +The default value is dependent on the kernel, currently 1024 bytes. +.TP 1.5i +.I wsize=n +The number of bytes NFS uses when writing files to an NFS server. +The default value is dependent on the kernel, currently 1024 bytes. +.TP 1.5i +.I timeo=n +The value in tenths of a second before sending the +first retransmission after an RPC timeout. +The default value is 7 tenths of a second. After the first timeout, +the timeout is doubled after each successive timeout until a maximum +timeout of 60 seconds is reached or the enough retransmissions +have occured to cause a major timeout. Then, if the filesystem +is hard mounted, each new timeout cascade restarts at twice the +initial value of the previous cascade, again doubling at each +retransmission. The maximum timeout is always 60 seconds. +Better overall performance may be achieved by increasing the +timeout when mounting on a busy network, to a slow server, or through +several routers or gateways. +.TP 1.5i +.I retrans=n +The number of minor timeouts and retransmissions that must occur before +a major timeout occurs. The default is 3 timeouts. When a major timeout +occurs, the file operation is either aborted or a "server not responding" +message is printed on the console. +.TP 1.5i +.I acregmin=n +The minimum time in seconds that attributes of a regular file should +be cached before requesting fresh information from a server. +The default is 3 seconds. +.TP 1.5i +.I acregmax=n +The maximum time in seconds that attributes of a regular file can +be cached before requesting fresh information from a server. +The default is 60 seconds. +.TP 1.5i +.I acdirmin=n +The minimum time in seconds that attributes of a directory should +be cached before requesting fresh information from a server. +The default is 30 seconds. +.TP 1.5i +.I acdirmax=n +The maximum time in seconds that attributes of a directory can +be cached before requesting fresh information from a server. +The default is 60 seconds. +.TP 1.5i +.I actimeo=n +Using actimeo sets all of +.I acregmin, +.I acregmax, +.I acdirmin, +and +.I acdirmax +to the same value. +There is no default value. +.TP 1.5i +.I retry=n +The number of times to retry a backgrounded NFS mount operation +before giving up. +The default value is 10000 times. +.TP 1.5i +.I namlen=n +When an NFS server does not support version two of the +RPC mount protocol, this option can be used to specify +the maximum length of a filename that is supported on +the remote filesystem. This is used to support the +POSIX pathconf functions. The default is 255 characters. +.TP 1.5i +.I port=n +The numeric value of the port to connect to the NFS server on. +If the port number is 0 (the default) then query the +remote host's portmapper for the port number to use. +If the remote host's NFS daemon is not registered with +its portmapper, the standard NFS port number 2049 is +used instead. +.TP 1.5i +.I mountport=n +The numeric value of the +.B mountd +port. +.TP 1.5i +.I mounthost=name +The name of the host running +.B mountd . +.TP 1.5i +.I mountprog=n +Use an alternate RPC program number to contact the +mount daemon on the remote host. This option is useful +for hosts that can run multiple NFS servers. +The default value is 100005 which is the standard RPC +mount daemon program number. +.TP 1.5i +.I mountvers=n +Use an alternate RPC version number to contact the +mount daemon on the remote host. This option is useful +for hosts that can run multiple NFS servers. +The default value is version 1. +.TP 1.5i +.I nfsprog=n +Use an alternate RPC program number to contact the +NFS daemon on the remote host. This option is useful +for hosts that can run multiple NFS servers. +The default value is 100003 which is the standard RPC +NFS daemon program number. +.TP 1.5i +.I nfsvers=n +Use an alternate RPC version number to contact the +NFS daemon on the remote host. This option is useful +for hosts that can run multiple NFS servers. +The default value is version 2. +.TP 1.5i +.I bg +If the first NFS mount attempt times out, continue trying the mount +in the background. +The default is to not to background the mount on timeout but fail. +.TP 1.5i +.I fg +If the first NFS mount attempt times out, fail immediately. +This is the default. +.TP 1.5i +.I soft +If an NFS file operation has a major timeout then report an I/O error to +the calling program. +The default is to continue retrying NFS file operations indefinitely. +.TP 1.5i +.I hard +If an NFS file operation has a major timeout then report +"server not responding" on the console and continue retrying indefinitely. +This is the default. +.TP 1.5i +.I intr +If an NFS file operation has a major timeout and it is hard mounted, +then allow signals to interupt the file operation and cause it to +return EINTR to the calling program. The default is to not +allow file operations to be interrupted. +.TP 1.5i +.I posix +Mount the NFS filesystem using POSIX semantics. This allows +an NFS filesystem to properly support the POSIX pathconf +command by querying the mount server for the maximum length +of a filename. To do this, the remote host must support version +two of the RPC mount protocol. Many NFS servers support only +version one. +.TP 1.5i +.I nocto +Supress the retrieval of new attributes when creating a file. +.TP 1.5i +.I noac +Disable all forms of attribute caching entirely. This extracts a +server performance penalty but it allows two different NFS clients +to get reasonable good results when both clients are actively +writing to common filesystem on the server. +.TP 1.5i +.I tcp +Mount the NFS filesystem using the TCP protocol instead of the +default UDP protocol. Many NFS severs only support UDP. +.TP 1.5i +.I udp +Mount the NFS filesystem using the UDP protocol. This +is the default. +.P +All of the non-value options have corresponding nooption forms. +For example, nointr means don't allow file operations to be +interrupted. +.SH FILES +.I /etc/fstab +.SH "SEE ALSO" +.BR fstab "(5), " mount "(8), " umount (8) +.SH AUTHOR +"Rick Sladkey" <jrs@world.std.com> +.SH BUGS +The bg, fg, retry, posix, and nocto options are parsed by mount +but currently are silently ignored. +.P +The tcp and namlen options are implemented but are not currently +supported by the Linux kernel. +.P +The umount command should notify the server +when an NFS filesystem is unmounted. diff --git a/mount/nfsmount.c b/mount/nfsmount.c new file mode 100644 index 000000000..9be51be02 --- /dev/null +++ b/mount/nfsmount.c @@ -0,0 +1,475 @@ +/* + * nfsmount.c -- Linux NFS mount + * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com> + * + * This program is free software; 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, or (at your option) + * any later version. + * + * This program 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. + * + * Wed Feb 8 12:51:48 1995, biro@yggdrasil.com (Ross Biro): allow all port + * numbers to be specified on the command line. + */ + +/* + * nfsmount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp + */ + +#include <stdio.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 <arpa/inet.h> +#include <errno.h> + +#include "sundries.h" + +#include "mount.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); +} + +static char *nfs_strerror(int stat); + +int nfsmount(const char *spec, const char *node, int *flags, + char **extra_opts, char **mount_opts) +{ + char hostdir[1024]; + CLIENT *mclient; + char *hostname; + char *dirname; + char *old_opts; + char *mounthost=NULL; + char new_opts[1024]; + fhandle root_fhandle; + struct timeval total_timeout; + enum clnt_stat clnt_stat; + static struct nfs_mount_data data; + char *opt, *opteq; + int val; + struct hostent *hp; + struct sockaddr_in server_addr; + struct sockaddr_in mount_server_addr; + int msock, fsock; + struct timeval pertry_timeout; + struct fhstatus status; + char *s; + int port; + int mountport; + int bg; + int soft; + int intr; + int posix; + int nocto; + int noac; + int retry; + int tcp; + int mountprog; + int mountvers; + int nfsprog; + int nfsvers; + + msock = fsock = -1; + mclient = NULL; + strcpy(hostdir, spec); + if ((s = (strchr(hostdir, ':')))) { + hostname = hostdir; + dirname = s + 1; + *s = '\0'; + } + else { + fprintf(stderr, "mount: " + "directory to mount not in host:dir format\n"); + 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); + } + + memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr)); + + /* add IP address to mtab options for use when unmounting */ + + old_opts = *extra_opts; + if (!old_opts) + old_opts = ""; + 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; + data.retrans = 3; + data.acregmin = 3; + data.acregmax = 60; + data.acdirmin = 30; + data.acdirmax = 60; +#if NFS_MOUNT_VERSION >= 2 + data.namlen = NAME_MAX; +#endif + + bg = 0; + soft = 0; + intr = 0; + posix = 0; + nocto = 0; + noac = 0; + retry = 10000; + tcp = 0; + + mountprog = MOUNTPROG; + mountvers = MOUNTVERS; + port = 0; + mountport = 0; + nfsprog = NFS_PROGRAM; + nfsvers = NFS_VERSION; + + /* parse options */ + + for (opt = strtok(old_opts, ","); opt; opt = strtok(NULL, ",")) { + if ((opteq = strchr(opt, '='))) { + val = atoi(opteq + 1); + *opteq = '\0'; + if (!strcmp(opt, "rsize")) + data.rsize = val; + else if (!strcmp(opt, "wsize")) + data.wsize = val; + else if (!strcmp(opt, "timeo")) + data.timeo = val; + else if (!strcmp(opt, "retrans")) + data.retrans = val; + else if (!strcmp(opt, "acregmin")) + data.acregmin = val; + else if (!strcmp(opt, "acregmax")) + data.acregmax = val; + else if (!strcmp(opt, "acdirmin")) + data.acdirmin = val; + else if (!strcmp(opt, "acdirmax")) + data.acdirmax = val; + else if (!strcmp(opt, "actimeo")) { + data.acregmin = val; + data.acregmax = val; + data.acdirmin = val; + data.acdirmax = val; + } + else if (!strcmp(opt, "retry")) + retry = val; + else if (!strcmp(opt, "port")) + port = val; + else if (!strcmp(opt, "mountport")) + mountport = val; + else if (!strcmp(opt, "mounthost")) + mounthost=strndup(opteq+1, + strcspn(opteq+1," \t\n\r,")); + else if (!strcmp(opt, "mountprog")) + mountprog = val; + else if (!strcmp(opt, "mountvers")) + mountvers = val; + else if (!strcmp(opt, "nfsprog")) + nfsprog = val; + else if (!strcmp(opt, "nfsvers")) + nfsvers = val; + else if (!strcmp(opt, "namlen")) { +#if NFS_MOUNT_VERSION >= 2 + data.namlen = val; +#else + printf("Warning: Option namlen is not supported.\n"); +#endif + } + else if (!strcmp(opt, "addr")) + /* ignore */; + else { + printf("unknown nfs mount parameter: " + "%s=%d\n", opt, val); + goto fail; + } + } + else { + val = 1; + if (!strncmp(opt, "no", 2)) { + val = 0; + opt += 2; + } + if (!strcmp(opt, "bg")) + bg = val; + else if (!strcmp(opt, "fg")) + bg = !val; + else if (!strcmp(opt, "soft")) + soft = val; + else if (!strcmp(opt, "hard")) + soft = !val; + else if (!strcmp(opt, "intr")) + intr = val; + else if (!strcmp(opt, "posix")) + posix = val; + else if (!strcmp(opt, "cto")) + nocto = !val; + else if (!strcmp(opt, "ac")) + noac = !val; + else if (!strcmp(opt, "tcp")) + tcp = val; + else if (!strcmp(opt, "udp")) + tcp = !val; + else { + printf("unknown nfs mount option: " + "%s%s\n", val ? "" : "no", opt); + goto fail; + } + } + } + data.flags = (soft ? NFS_MOUNT_SOFT : 0) + | (intr ? NFS_MOUNT_INTR : 0) + | (posix ? NFS_MOUNT_POSIX : 0) + | (nocto ? NFS_MOUNT_NOCTO : 0) + | (noac ? NFS_MOUNT_NOAC : 0); +#if NFS_MOUNT_VERSION >= 2 + data.flags |= (tcp ? NFS_MOUNT_TCP : 0); +#endif + +#ifdef NFS_MOUNT_DEBUG + printf("rsize = %d, wsize = %d, timeo = %d, retrans = %d\n", + data.rsize, data.wsize, data.timeo, data.retrans); + printf("acreg (min, max) = (%d, %d), acdir (min, max) = (%d, %d)\n", + data.acregmin, data.acregmax, data.acdirmin, data.acdirmax); + printf("port = %d, bg = %d, retry = %d, flags = %.8x\n", + port, bg, retry, data.flags); + printf("mountprog = %d, mountvers = %d, nfsprog = %d, nfsvers = %d\n", + mountprog, mountvers, nfsprog, nfsvers); + printf("soft = %d, intr = %d, posix = %d, nocto = %d, noac = %d\n", + (data.flags & NFS_MOUNT_SOFT) != 0, + (data.flags & NFS_MOUNT_INTR) != 0, + (data.flags & NFS_MOUNT_POSIX) != 0, + (data.flags & NFS_MOUNT_NOCTO) != 0, + (data.flags & NFS_MOUNT_NOAC) != 0); +#if NFS_MOUNT_VERSION >= 2 + printf("tcp = %d\n", + (data.flags & NFS_MOUNT_TCP) != 0); +#endif +#if 0 + goto fail; +#endif +#endif + + data.version = NFS_MOUNT_VERSION; + *mount_opts = (char *) &data; + + if (*flags & MS_REMOUNT) + return 0; + + /* create mount deamon client */ + /* See if the nfs host = mount host. */ + if (mounthost) { + if (mounthost[0] >= '0' && mounthost[0] <= '9') { + mount_server_addr.sin_family = AF_INET; + mount_server_addr.sin_addr.s_addr = inet_addr(hostname); + } + else if ((hp = gethostbyname(mounthost)) == NULL) { + fprintf(stderr, "mount: can't get address for %s\n", hostname); + goto fail; + } + else { + mount_server_addr.sin_family = AF_INET; + memcpy(&mount_server_addr.sin_addr, hp->h_addr, hp->h_length); + } + } + + mount_server_addr.sin_port = htons(mountport); + msock = RPC_ANYSOCK; + if ((mclient = clnttcp_create(&mount_server_addr, + mountprog, mountvers, &msock, 0, 0)) == NULL) { + mount_server_addr.sin_port = htons(mountport); + msock = RPC_ANYSOCK; + pertry_timeout.tv_sec = 3; + pertry_timeout.tv_usec = 0; + if ((mclient = clntudp_create(&mount_server_addr, + mountprog, mountvers, pertry_timeout, &msock)) == NULL) { + clnt_pcreateerror("mount clntudp_create"); + goto fail; + } +#ifdef NFS_MOUNT_DEBUG + printf("using UDP for mount deamon\n"); +#endif + } +#ifdef NFS_MOUNT_DEBUG + else + printf("using TCP for mount deamon\n"); +#endif + mclient->cl_auth = authunix_create_default(); + total_timeout.tv_sec = 20; + total_timeout.tv_usec = 0; + + /* try to mount hostname:dirname */ + + clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, + xdr_dirpath, &dirname, + xdr_fhstatus, &status, + total_timeout); + if (clnt_stat != RPC_SUCCESS) { + clnt_perror(mclient, "rpc mount"); + goto fail; + } + if (status.fhs_status != 0) { + fprintf(stderr, + "mount: %s:%s failed, reason given by server: %s\n", + hostname, dirname, nfs_strerror(status.fhs_status)); + goto fail; + } + memcpy((char *) &root_fhandle, (char *) status.fhstatus_u.fhs_fhandle, + sizeof (root_fhandle)); + + /* create nfs socket for kernel */ + + if (tcp) { +#if NFS_MOUNT_VERSION >= 2 + fsock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); +#else + printf("NFS over TCP is not supported.\n"); + goto fail; +#endif + } + else + fsock = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); + if (fsock < 0) { + perror("nfs socket"); + goto fail; + } + if (bindresvport(fsock, 0) < 0) { + perror("nfs bindresvport"); + goto fail; + } + if (port == 0) { + server_addr.sin_port = PMAPPORT; + port = pmap_getport(&server_addr, nfsprog, nfsvers, + tcp ? IPPROTO_TCP : IPPROTO_UDP); + if (port == 0) + port = NFS_PORT; +#ifdef NFS_MOUNT_DEBUG + else + printf("used portmapper to find NFS port\n"); +#endif + } +#ifdef NFS_MOUNT_DEBUG + 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) { + perror("nfs connect"); + goto fail; + } + + /* prepare data structure for kernel */ + + data.fd = fsock; + memcpy((char *) &data.root, (char *) &root_fhandle, + sizeof (root_fhandle)); + memcpy((char *) &data.addr, (char *) &server_addr, sizeof(data.addr)); + strncpy(data.hostname, hostname, sizeof(data.hostname)); + + /* clean up */ + + auth_destroy(mclient->cl_auth); + clnt_destroy(mclient); + close(msock); + return 0; + + /* abort */ + +fail: + if (msock != -1) { + auth_destroy(mclient->cl_auth); + clnt_destroy(mclient); + close(msock); + } + if (fsock != -1) + close(fsock); + return 1;} + + +/* + * We need to translate between nfs status return values and + * the local errno values which may not be the same. + */ + +#ifndef EDQUOT +#define EDQUOT ENOSPC +#endif + +static struct { + enum nfs_stat stat; + int errno; +} nfs_errtbl[] = { + { NFS_OK, 0 }, + { NFSERR_PERM, EPERM }, + { NFSERR_NOENT, ENOENT }, + { NFSERR_IO, EIO }, + { NFSERR_NXIO, ENXIO }, + { NFSERR_ACCES, EACCES }, + { NFSERR_EXIST, EEXIST }, + { NFSERR_NODEV, ENODEV }, + { NFSERR_NOTDIR, ENOTDIR }, + { NFSERR_ISDIR, EISDIR }, +#ifdef NFSERR_INVAL + { NFSERR_INVAL, EINVAL }, /* that Sun forgot */ +#endif + { NFSERR_FBIG, EFBIG }, + { NFSERR_NOSPC, ENOSPC }, + { NFSERR_ROFS, EROFS }, + { NFSERR_NAMETOOLONG, ENAMETOOLONG }, + { NFSERR_NOTEMPTY, ENOTEMPTY }, + { NFSERR_DQUOT, EDQUOT }, + { NFSERR_STALE, ESTALE }, +#ifdef EWFLUSH + { NFSERR_WFLUSH, EWFLUSH }, +#endif + { -1, EIO } +}; + +static char *nfs_strerror(int stat) +{ + int i; + static char buf[256]; + + for (i = 0; nfs_errtbl[i].stat != -1; i++) { + if (nfs_errtbl[i].stat == stat) + return strerror(nfs_errtbl[i].errno); + } + sprintf(buf, "unknown nfs status return value: %d", stat); + return buf; +} + diff --git a/mount/realpath.c b/mount/realpath.c new file mode 100644 index 000000000..4ea46a311 --- /dev/null +++ b/mount/realpath.c @@ -0,0 +1,178 @@ +/* + * realpath.c -- canonicalize pathname by removing symlinks + * Copyright (C) 1993 Rick Sladkey <jrs@world.std.com> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Library Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program 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 Library Public License for more details. + */ + +/* + * realpath.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp + */ + +#ifdef __linux__ +extern char *realpath(const char *path, char *resolved_path); +#define HAVE_UNISTD_H +#define HAVE_STRING_H +#endif + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <sys/types.h> +#if defined(HAVE_UNISTD_H) || defined(STDC_HEADERS) +#include <unistd.h> +#endif +#include <stdio.h> +#ifdef HAVE_STRING_H +#include <string.h> +#else +#include <strings.h> +#endif +#ifdef _POSIX_VERSION +#include <limits.h> /* for PATH_MAX */ +#else +#include <sys/param.h> /* for MAXPATHLEN */ +#endif +#include <errno.h> +#ifndef STDC_HEADERS +extern int errno; +#endif + +#include <sys/stat.h> /* for S_IFLNK */ + +#ifndef PATH_MAX +#ifdef _POSIX_VERSION +#define PATH_MAX _POSIX_PATH_MAX +#else +#ifdef MAXPATHLEN +#define PATH_MAX MAXPATHLEN +#else +#define PATH_MAX 1024 +#endif +#endif +#endif + +#define MAX_READLINKS 32 + +#ifdef __STDC__ +char *realpath(const char *path, char *resolved_path) +#else +char *realpath(path, resolved_path) +const char *path; +char *resolved_path; +#endif +{ + char copy_path[PATH_MAX]; + char link_path[PATH_MAX]; + char *new_path = resolved_path; + char *max_path; + int readlinks = 0; + int n; + + /* Make a copy of the source path since we may need to modify it. */ + 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 + getcwd(new_path, PATH_MAX - 1); +#else + getwd(new_path); +#endif + new_path += strlen(new_path); + if (new_path[-1] != '/') + *new_path++ = '/'; + } + else { + *new_path++ = '/'; + path++; + } + /* Expand each slash-separated pathname component. */ + while (*path != '\0') { + /* Ignore stray "/". */ + if (*path == '/') { + path++; + continue; + } + if (*path == '.') { + /* Ignore ".". */ + if (path[1] == '\0' || path[1] == '/') { + path++; + continue; + } + if (path[1] == '.') { + if (path[2] == '\0' || path[2] == '/') { + path += 2; + /* Ignore ".." at root. */ + if (new_path == resolved_path + 1) + continue; + /* Handle ".." by backing up. */ + while ((--new_path)[-1] != '/') + ; + continue; + } + } + } + /* Safely copy the next pathname component. */ + while (*path != '\0' && *path != '/') { + if (path > max_path) { + errno = ENAMETOOLONG; + return NULL; + } + *new_path++ = *path++; + } +#ifdef S_IFLNK + /* Protect against infinite loops. */ + if (readlinks++ > MAX_READLINKS) { + errno = ELOOP; + return NULL; + } + /* See if latest pathname component is a symlink. */ + *new_path = '\0'; + n = readlink(resolved_path, link_path, PATH_MAX - 1); + if (n < 0) { + /* EINVAL means the file exists but isn't a symlink. */ + if (errno != EINVAL) + return NULL; + } + else { + /* Note: readlink doesn't add the null byte. */ + link_path[n] = '\0'; + if (*link_path == '/') + /* Start over for an absolute symlink. */ + new_path = resolved_path; + else + /* Otherwise back up over this component. */ + while (*(--new_path) != '/') + ; + /* Safe sex check. */ + if (strlen(path) + n >= PATH_MAX) { + errno = ENAMETOOLONG; + return NULL; + } + /* Insert symlink contents into path. */ + strcat(link_path, path); + strcpy(copy_path, link_path); + path = copy_path; + } +#endif /* S_IFLNK */ + *new_path++ = '/'; + } + /* Delete trailing slash but don't whomp a lone slash. */ + if (new_path != resolved_path + 1 && new_path[-1] == '/') + new_path--; + /* Make sure it's null terminated. */ + *new_path = '\0'; + return resolved_path; +} + diff --git a/mount/rpcsvc/mount.h b/mount/rpcsvc/mount.h new file mode 100644 index 000000000..d70ccaf9d --- /dev/null +++ b/mount/rpcsvc/mount.h @@ -0,0 +1,208 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#ifndef _MOUNT_H_RPCGEN +#define _MOUNT_H_RPCGEN + +#include <rpc/rpc.h> + +#define MNTPATHLEN 1024 +#define MNTNAMLEN 255 +#define FHSIZE 32 + +typedef char fhandle[FHSIZE]; +#ifdef __cplusplus +extern "C" bool_t xdr_fhandle(XDR *, fhandle); +#elif __STDC__ +extern bool_t xdr_fhandle(XDR *, fhandle); +#else /* Old Style C */ +bool_t xdr_fhandle(); +#endif /* Old Style C */ + + +struct fhstatus { + u_int fhs_status; + union { + fhandle fhs_fhandle; + } fhstatus_u; +}; +typedef struct fhstatus fhstatus; +#ifdef __cplusplus +extern "C" bool_t xdr_fhstatus(XDR *, fhstatus*); +#elif __STDC__ +extern bool_t xdr_fhstatus(XDR *, fhstatus*); +#else /* Old Style C */ +bool_t xdr_fhstatus(); +#endif /* Old Style C */ + + +typedef char *dirpath; +#ifdef __cplusplus +extern "C" bool_t xdr_dirpath(XDR *, dirpath*); +#elif __STDC__ +extern bool_t xdr_dirpath(XDR *, dirpath*); +#else /* Old Style C */ +bool_t xdr_dirpath(); +#endif /* Old Style C */ + + +typedef char *name; +#ifdef __cplusplus +extern "C" bool_t xdr_name(XDR *, name*); +#elif __STDC__ +extern bool_t xdr_name(XDR *, name*); +#else /* Old Style C */ +bool_t xdr_name(); +#endif /* Old Style C */ + + +typedef struct mountbody *mountlist; +#ifdef __cplusplus +extern "C" bool_t xdr_mountlist(XDR *, mountlist*); +#elif __STDC__ +extern bool_t xdr_mountlist(XDR *, mountlist*); +#else /* Old Style C */ +bool_t xdr_mountlist(); +#endif /* Old Style C */ + + +struct mountbody { + name ml_hostname; + dirpath ml_directory; + mountlist ml_next; +}; +typedef struct mountbody mountbody; +#ifdef __cplusplus +extern "C" bool_t xdr_mountbody(XDR *, mountbody*); +#elif __STDC__ +extern bool_t xdr_mountbody(XDR *, mountbody*); +#else /* Old Style C */ +bool_t xdr_mountbody(); +#endif /* Old Style C */ + + +typedef struct groupnode *groups; +#ifdef __cplusplus +extern "C" bool_t xdr_groups(XDR *, groups*); +#elif __STDC__ +extern bool_t xdr_groups(XDR *, groups*); +#else /* Old Style C */ +bool_t xdr_groups(); +#endif /* Old Style C */ + + +struct groupnode { + name gr_name; + groups gr_next; +}; +typedef struct groupnode groupnode; +#ifdef __cplusplus +extern "C" bool_t xdr_groupnode(XDR *, groupnode*); +#elif __STDC__ +extern bool_t xdr_groupnode(XDR *, groupnode*); +#else /* Old Style C */ +bool_t xdr_groupnode(); +#endif /* Old Style C */ + + +typedef struct exportnode *exports; +#ifdef __cplusplus +extern "C" bool_t xdr_exports(XDR *, exports*); +#elif __STDC__ +extern bool_t xdr_exports(XDR *, exports*); +#else /* Old Style C */ +bool_t xdr_exports(); +#endif /* Old Style C */ + + +struct exportnode { + dirpath ex_dir; + groups ex_groups; + exports ex_next; +}; +typedef struct exportnode exportnode; +#ifdef __cplusplus +extern "C" bool_t xdr_exportnode(XDR *, exportnode*); +#elif __STDC__ +extern bool_t xdr_exportnode(XDR *, exportnode*); +#else /* Old Style C */ +bool_t xdr_exportnode(); +#endif /* Old Style C */ + + +#define MOUNTPROG ((u_long)100005) +#define MOUNTVERS ((u_long)1) + +#ifdef __cplusplus +#define MOUNTPROC_NULL ((u_long)0) +extern "C" void * mountproc_null_1(void *, CLIENT *); +extern "C" void * mountproc_null_1_svc(void *, struct svc_req *); +#define MOUNTPROC_MNT ((u_long)1) +extern "C" fhstatus * mountproc_mnt_1(dirpath *, CLIENT *); +extern "C" fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_DUMP ((u_long)2) +extern "C" mountlist * mountproc_dump_1(void *, CLIENT *); +extern "C" mountlist * mountproc_dump_1_svc(void *, struct svc_req *); +#define MOUNTPROC_UMNT ((u_long)3) +extern "C" void * mountproc_umnt_1(dirpath *, CLIENT *); +extern "C" void * mountproc_umnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_UMNTALL ((u_long)4) +extern "C" void * mountproc_umntall_1(void *, CLIENT *); +extern "C" void * mountproc_umntall_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORT ((u_long)5) +extern "C" exports * mountproc_export_1(void *, CLIENT *); +extern "C" exports * mountproc_export_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORTALL ((u_long)6) +extern "C" exports * mountproc_exportall_1(void *, CLIENT *); +extern "C" exports * mountproc_exportall_1_svc(void *, struct svc_req *); + +#elif __STDC__ +#define MOUNTPROC_NULL ((u_long)0) +extern void * mountproc_null_1(void *, CLIENT *); +extern void * mountproc_null_1_svc(void *, struct svc_req *); +#define MOUNTPROC_MNT ((u_long)1) +extern fhstatus * mountproc_mnt_1(dirpath *, CLIENT *); +extern fhstatus * mountproc_mnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_DUMP ((u_long)2) +extern mountlist * mountproc_dump_1(void *, CLIENT *); +extern mountlist * mountproc_dump_1_svc(void *, struct svc_req *); +#define MOUNTPROC_UMNT ((u_long)3) +extern void * mountproc_umnt_1(dirpath *, CLIENT *); +extern void * mountproc_umnt_1_svc(dirpath *, struct svc_req *); +#define MOUNTPROC_UMNTALL ((u_long)4) +extern void * mountproc_umntall_1(void *, CLIENT *); +extern void * mountproc_umntall_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORT ((u_long)5) +extern exports * mountproc_export_1(void *, CLIENT *); +extern exports * mountproc_export_1_svc(void *, struct svc_req *); +#define MOUNTPROC_EXPORTALL ((u_long)6) +extern exports * mountproc_exportall_1(void *, CLIENT *); +extern exports * mountproc_exportall_1_svc(void *, struct svc_req *); + +#else /* Old Style C */ +#define MOUNTPROC_NULL ((u_long)0) +extern void * mountproc_null_1(); +extern void * mountproc_null_1_svc(); +#define MOUNTPROC_MNT ((u_long)1) +extern fhstatus * mountproc_mnt_1(); +extern fhstatus * mountproc_mnt_1_svc(); +#define MOUNTPROC_DUMP ((u_long)2) +extern mountlist * mountproc_dump_1(); +extern mountlist * mountproc_dump_1_svc(); +#define MOUNTPROC_UMNT ((u_long)3) +extern void * mountproc_umnt_1(); +extern void * mountproc_umnt_1_svc(); +#define MOUNTPROC_UMNTALL ((u_long)4) +extern void * mountproc_umntall_1(); +extern void * mountproc_umntall_1_svc(); +#define MOUNTPROC_EXPORT ((u_long)5) +extern exports * mountproc_export_1(); +extern exports * mountproc_export_1_svc(); +#define MOUNTPROC_EXPORTALL ((u_long)6) +extern exports * mountproc_exportall_1(); +extern exports * mountproc_exportall_1_svc(); +#endif /* Old Style C */ + +#endif /* !_MOUNT_H_RPCGEN */ diff --git a/mount/rpcsvc/mount.x b/mount/rpcsvc/mount.x new file mode 100644 index 000000000..7e0d7f3ad --- /dev/null +++ b/mount/rpcsvc/mount.x @@ -0,0 +1,161 @@ +/* @(#)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 new file mode 100644 index 000000000..bc6e5122b --- /dev/null +++ b/mount/rpcsvc/mount_clnt.c @@ -0,0 +1,94 @@ +/* + * 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 new file mode 100644 index 000000000..be5eb41f1 --- /dev/null +++ b/mount/rpcsvc/mount_xdr.c @@ -0,0 +1,150 @@ +/* + * 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/sundries.c b/mount/sundries.c new file mode 100644 index 000000000..45e0e14d8 --- /dev/null +++ b/mount/sundries.c @@ -0,0 +1,283 @@ +/* + * Support functions. Exported functions are prototyped in sundries.h. + * sundries.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp + */ + +#include "sundries.h" + +/* File pointer for /etc/mtab. */ +FILE *F_mtab = NULL; + +/* File pointer for temp mtab. */ +FILE *F_temp = NULL; + +/* File descriptor for lock. Value tested in unlock_mtab() to remove race. */ +static int lock = -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); + + car (p) = a; + cdr (p) = b; + return p; +} + +void * +xmalloc (size_t size) +{ + void *t; + + if (size == 0) + return NULL; + + t = malloc (size); + if (t == NULL) + die (2, "not enough memory"); + + return t; +} + +char * +xstrdup (const char *s) +{ + char *t; + + if (s == NULL) + return NULL; + + t = strdup (s); + + if (t == NULL) + die (2, "not enough memory"); + + return t; +} + +/* Call this with SIG_BLOCK to block and SIG_UNBLOCK to unblock. */ +void +block_signals (int how) +{ + sigset_t sigs; + + sigfillset (&sigs); + sigprocmask (how, &sigs, (sigset_t *) 0); +} + + +/* Non-fatal error. Print message and return. */ +void +error (const char *fmt, ...) +{ + va_list args; + + va_start (args, fmt); + vfprintf (stderr, fmt, args); + fprintf (stderr, "\n"); + va_end (args); +} + +/* 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); + + unlock_mtab (); + exit (err); +} + +/* Ensure that the lock is released if we are interrupted. */ +static void +handler (int sig) +{ + die (2, "%s", sys_siglist[sig]); +} + +/* 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; + + /* If this is the first time, ensure that the lock will be removed. */ + if (lock < 0) + { + sa.sa_handler = handler; + sa.sa_flags = 0; + sigfillset (&sa.sa_mask); + + while (sigismember (&sa.sa_mask, ++sig) != -1) + sigaction (sig, &sa, (struct sigaction *) 0); + + if ((lock = open (MOUNTED_LOCK, O_WRONLY|O_CREAT|O_EXCL, 0)) < 0) + die (2, "can't create lock file %s: %s", + MOUNTED_LOCK, strerror (errno)); + } +} + +/* Remove lock file. */ +void +unlock_mtab (void) +{ + if (lock != -1) + { + close( lock ); + unlink (MOUNTED_LOCK); + } +} + +/* Open mtab. */ +void +open_mtab (const char *mode) +{ + if ((F_mtab = setmntent (MOUNTED, mode)) == NULL) + die (2, "can't open %s: %s", MOUNTED, strerror (errno)); +} + +/* 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); +} + +/* 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"); + + 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)); +} + +/* 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); + + while ((mnt = getmntent (F_mtab)) != NULL) + { + if (streq (mnt->mnt_dir, file)) + break; + if (streq (mnt->mnt_fsname, file)) + break; + } + + return mnt; +} + +/* Parse a list of strings like str[,str]... into a string list. */ +string_list +parse_list (char *strings) +{ + string_list list; + char *t; + + if (strings == NULL) + return NULL; + + list = cons (strtok (strings, ","), NULL); + + while ((t = strtok (NULL, ",")) != NULL) + list = cons (t, 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. */ +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; +} + +/* 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 + we return unmodified. */ +char * +canonicalize (const char *path) +{ + char *canonical = xmalloc (PATH_MAX + 1); + + if (path == NULL) + return NULL; + + if (realpath (path, canonical)) + return canonical; + + strcpy (canonical, path); + return canonical; +} diff --git a/mount/sundries.h b/mount/sundries.h new file mode 100644 index 000000000..ba878c9b4 --- /dev/null +++ b/mount/sundries.h @@ -0,0 +1,90 @@ +/* + * Support function prototypes. Functions are in sundries.c. + * sundries.h,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp + */ + +#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> + +#include "fstab.h" + + +#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 3 + +/* 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 +{ + char *hd; + struct string_list *tl; +} *string_list; + +#define car(p) ((p) -> hd) +#define cdr(p) ((p) -> tl) + +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); + +/* Here is some serious cruft. */ +#ifdef __GNUC__ +#if defined(__GNUC_MINOR__) && __GNUC__ == 2 && __GNUC_MINOR__ >= 5 +void die (int errcode, const char *fmt, ...) __attribute__ ((noreturn)); +#else /* GNUC < 2.5 */ +void volatile die (int errcode, const char *fmt, ...); +#endif /* GNUC < 2.5 */ +#else /* !__GNUC__ */ +void die (int errcode, const char *fmt, ...); +#endif /* !__GNUC__ */ + +#ifdef HAVE_NFS +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) + diff --git a/mount/swapoff.8 b/mount/swapoff.8 new file mode 100644 index 000000000..1a06b7e8d --- /dev/null +++ b/mount/swapoff.8 @@ -0,0 +1 @@ +.so man8/swapon.8 diff --git a/mount/swapon.8 b/mount/swapon.8 new file mode 100644 index 000000000..44c841681 --- /dev/null +++ b/mount/swapon.8 @@ -0,0 +1,94 @@ +.\" Copyright (c) 1980, 1991 Regents of the University of California. +.\" All rights reserved. +.\" +.\" 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 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. +.\" +.\" @(#)swapon.8 6.3 (Berkeley) 3/16/91 +.\" +.\" Sun Dec 27 12:31:30 1992: Modified by faith@cs.unc.edu +.\" Sat Mar 6 20:46:02 1993: Modified by faith@cs.unc.edu +.\" 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 +.\" +.TH SWAPON 8 "27 November 1993" "Linux 0.99" "Linux Programmer's Manual" +.SH NAME +swapon, swapoff \- enable/disable devices and files for paging and swapping +.SH SYNOPSIS +.B /etc/swapon \-a +.br +.BI /etc/swapon " specialfile " ... +.br +.B /etc/swapoff \-a +.br +.BI /etc/swapoff " specialfile " ... +.SH DESCRIPTION +.B Swapon +is used to specify devices on which paging and swapping are to take place. +Calls to +.B swapon +normally occur in the system multi-user initialization file +.I /etc/rc +making all swap devices available, so that the paging and swapping activity +is interleaved across several devices and files. + +Normally, the first form is used: +.TP +.B \-a +All devices marked as ``sw'' swap devices in +.I /etc/fstab +are made available. +.PP +.B Swapoff +disables swapping on the specified devices and files, or on all swap +entries in +.I /etc/fstab +when the +.B \-a +flag is given. +.SH SEE ALSO +.BR swapon "(2), " swapoff "(2), " fstab "(5), " init "(8), " mkswap (8), +.BR rc "(8), " mount (8) +.SH FILES +.I /dev/hd[ab]? +standard paging devices +.br +.I /dev/sd[ab]? +standard (SCSI) paging devices +.br +.I /etc/fstab +ascii filesystem description table +.SH HISTORY +The +.B swapon +command appeared in 4.0BSD. +.SH AUTHORS +See the Linux +.BR mount (8) +man page for a complete author list. Primary contributors include Doug +Quale, H. J. Lu, Rick Sladkey, and Stephen Tweedie. diff --git a/mount/swapon.c b/mount/swapon.c new file mode 100644 index 000000000..584033021 --- /dev/null +++ b/mount/swapon.c @@ -0,0 +1,109 @@ +/* + * A swapon(8)/swapoff(8) for Linux 0.99. + * swapon.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp + */ + +#include "sundries.h" + +/* Nonzero for chatty (-v). This is a nonstandard flag (not in BSD). */ +int verbose = 0; + +extern char version[]; +static char *program_name; +static struct option longopts[] = +{ + { "all", 0, 0, 'a' }, + { "help", 0, 0, 'h' }, + { "verbose", 0, 0, 'v' }, + { "version", 0, 0, 'V' }, + { NULL, 0, 0, 0 } +}; + +const char *usage_string = "\ +usage: %s [-hV]\n\ + %s -a [-v]\n\ + %s [-v] special ...\n\ +"; + +static void +usage (FILE *fp, int n) +{ + fprintf (fp, usage_string, program_name, program_name, program_name); + exit (n); +} + +static int +swap (const char *special) +{ + int status; + + if (verbose) + printf("%s on device %s\n", program_name, special); + + if (streq (program_name, "swapon")) + status = swapon (special); + else + status = swapoff (special); + + if (status < 0) + fprintf (stderr, "%s: %s: %s\n", program_name, special, strerror (errno)); + + return status; +} + +int +main (int argc, char *argv[]) +{ + struct fstab *fstab; + int status; + int all = 0; + int c; + + if (strrchr (argv[0], '/') != NULL) + program_name = strrchr (argv[0], '/') + 1; + else + program_name = argv[0]; + + while ((c = getopt_long (argc, argv, "ahvV", longopts, NULL)) != EOF) + switch (c) + { + case 'a': /* all */ + ++all; + break; + case 'h': /* help */ + usage (stdout, 0); + break; + case 'v': /* be chatty */ + ++verbose; + break; + case 'V': /* version */ + printf ("%s\n", version); + exit (0); + case 0: + break; + case '?': + default: + usage (stderr, 1); + } + + argv += optind; + + status = 0; + + if (all) + { + while ((fstab = getfsent()) != NULL) + if (streq (fstab->fs_type, FSTAB_SW)) + status |= swap (fstab->fs_spec); + } + else if (*argv == NULL) + { + usage (stderr, 2); + } + else + { + while (*argv != NULL) + status |= swap (*argv++); + } + return status; +} diff --git a/mount/umount.8 b/mount/umount.8 new file mode 100644 index 000000000..85425b487 --- /dev/null +++ b/mount/umount.8 @@ -0,0 +1 @@ +.so man8/mount.8 diff --git a/mount/umount.c b/mount/umount.c new file mode 100644 index 000000000..c3cfee71a --- /dev/null +++ b/mount/umount.c @@ -0,0 +1,353 @@ +/* + * A umount(8) for Linux 0.99. + * umount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp + * + * Wed Sep 14 22:43:54 1994: Sebastian Lederer + * (lederer@next-pc.informatik.uni-bonn.de) added support for sending an + * unmount RPC call to the server when an NFS-filesystem is unmounted. + */ + +#include "sundries.h" + +#ifdef HAVE_NFS +#include <sys/socket.h> +#include <sys/time.h> +#include <netdb.h> +#include <rpc/rpc.h> +#include <rpc/pmap_clnt.h> +#include <rpc/pmap_prot.h> +#include "mount.h" +#include <arpa/inet.h> +#endif + + +#ifdef notyet +/* Nonzero for force umount (-f). This needs kernel support we don't have. */ +int force = 0; +#endif + +/* Nonzero for chatty (-v). This is a nonstandard flag (not in BSD). */ +int verbose = 0; + +/* True if ruid != euid. */ +int suid = 0; + +#ifdef HAVE_NFS +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) +{ + 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]; +#endif /* HAVE_NFS */ + + + /* Special case for root. As of 0.99pl10 we can (almost) unmount root; + the kernel will remount it readonly so that we can carry on running + afterwards. The readonly remount is illegal if any files are opened + for writing at the time, so we can't update mtab for an unmount of + root. As it is only really a remount, this doesn't matter too + much. [sct May 29, 1993] */ + isroot = (streq (node, "/") || streq (node, "root")); + +#ifdef HAVE_NFS + strcpy(buffer,spec); + /* spec is constant so must use own buffer */ + if((p=strchr(buffer,':'))) + { + *p='\0'; + strcpy(hostname,buffer); + strcpy(dirname,p+1); +#ifdef DEBUG + printf("host: %s, directory: %s\n", hostname,dirname); +#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. */ + { + if (verbose) + printf ("%s umounted\n", spec); + + if (!isroot) + { + /* 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 (del_loop(spec)) + goto fail; + } + } + 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 (); + + 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: + 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; + } + return 1; +} + +/* Unmount all filesystems of type VFSTYPES found in mtab. Since we are + 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. */ +static int +umount_all (string_list types) +{ + string_list spec_list = NULL; + string_list node_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); + } + + close_mtab (); + + errors = 0; + while (spec_list != NULL) + { + errors |= umount_one (car (spec_list), car (node_list)); + spec_list = cdr (spec_list); + node_list = cdr (node_list); + } + + sync (); + return errors; +} + +extern char version[]; +static struct option longopts[] = +{ + { "all", 0, 0, 'a' }, + { "force", 0, 0, 'f' }, + { "help", 0, 0, 'h' }, + { "verbose", 0, 0, 'v' }, + { "version", 0, 0, 'V' }, + { "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\ +"; + +static void +usage (FILE *fp, int n) +{ + fprintf (fp, "%s", usage_string); + exit (n); +} + +int +main (int argc, char *argv[]) +{ + int c; + int all = 0; + string_list types = NULL; + string_list options; + struct mntent *mnt; + struct mntent mntbuf; + struct mntent *fs; + char *file; + int result = 0; + + while ((c = getopt_long (argc, argv, "afhvVt:", longopts, NULL)) != EOF) + switch (c) + { + case 'a': /* umount everything */ + ++all; + break; + case 'f': /* force umount (needs kernel support) */ +#if 0 + ++force; +#else + die (2, "umount: forced umount not supported yet"); +#endif + break; + case 'h': /* help */ + usage (stdout, 0); + break; + case 'v': /* make noise */ + ++verbose; + break; + case 'V': /* version */ + printf ("%s\n", version); + exit (0); + case 't': /* specify file system type */ + types = parse_list (optarg); + break; + case 0: + break; + case '?': + default: + usage (stderr, 1); + } + + if (getuid () != geteuid ()) + { + suid = 1; + if (all || types) + 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 + { + 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) + die (2, "umount: %s is not mounted", 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 mount disagrees with the fstab", file); + options = parse_list (fs->mnt_opts); + 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)); + else + result = umount_one (*argv, *argv); + } + exit (result); +} diff --git a/mount/version.c b/mount/version.c new file mode 100644 index 000000000..ece944d29 --- /dev/null +++ b/mount/version.c @@ -0,0 +1 @@ +char version[] = "(u)mount: version from util-linux-2.2"; |