diff options
author | Karel Zak | 2006-12-07 00:25:35 +0100 |
---|---|---|
committer | Karel Zak | 2006-12-07 00:25:35 +0100 |
commit | 2b6fc908bc368b540845a313c3b8a867c5ad9a42 (patch) | |
tree | 6fad48a239bc90515a5dc4084d6e3c3ee1f41e29 /mount | |
parent | Imported from util-linux-2.7.1 tarball. (diff) | |
download | kernel-qcow2-util-linux-2b6fc908bc368b540845a313c3b8a867c5ad9a42.tar.gz kernel-qcow2-util-linux-2b6fc908bc368b540845a313c3b8a867c5ad9a42.tar.xz kernel-qcow2-util-linux-2b6fc908bc368b540845a313c3b8a867c5ad9a42.zip |
Imported from util-linux-2.8 tarball.
Diffstat (limited to 'mount')
-rw-r--r-- | mount/Makefile | 18 | ||||
-rw-r--r-- | mount/Makefile.standalone | 4 | ||||
-rw-r--r-- | mount/fstab.5 | 10 | ||||
-rw-r--r-- | mount/fstab.c | 4 | ||||
-rw-r--r-- | mount/h/loop.h | 8 | ||||
-rw-r--r-- | mount/linux_fs.h | 59 | ||||
-rw-r--r-- | mount/lomount.c | 15 | ||||
-rw-r--r-- | mount/losetup.c | 6 | ||||
-rw-r--r-- | mount/mk_loop_h | 30 | ||||
-rw-r--r-- | mount/mount.8 | 20 | ||||
-rw-r--r-- | mount/mount.c | 339 | ||||
-rw-r--r-- | mount/mount_constants.h | 7 | ||||
-rw-r--r-- | mount/nfs.5 | 31 | ||||
-rw-r--r-- | mount/nfsmount.c | 246 | ||||
-rw-r--r-- | mount/nfsmount_clnt.c | 54 | ||||
-rw-r--r-- | mount/realpath.c | 4 | ||||
-rw-r--r-- | mount/sundries.h | 12 | ||||
-rw-r--r-- | mount/swap.configure | 4 | ||||
-rw-r--r-- | mount/umount.c | 13 | ||||
-rw-r--r-- | mount/version.c | 2 |
20 files changed, 607 insertions, 279 deletions
diff --git a/mount/Makefile b/mount/Makefile index cfbedd59d..32272a9b6 100644 --- a/mount/Makefile +++ b/mount/Makefile @@ -66,16 +66,20 @@ swapon: swapon.o version.o losetup: losetup.o $(LINK) $^ $(LDLIBS) -o $@ +mount.o: linux_fs.h + mount.o umount.o nfsmount.o losetup.o fstab.o sundries.o: sundries.h mount.o umount.o fstab.o sundries.o: fstab.h -mount.o umount.o losetup.o: lomount.h loop.h +mount.o umount.o losetup.o lomount.o: lomount.h loop.h swapon.o: swap.h swapargs.h sundries.o nfsmount.o nfsmount_xdr.o nfsmount_clnt.o: nfsmount.h +umount.o: mount_constants.h + nfsmount_clnt.o: nfsmount_clnt.c $(COMPILE) $(RPC_CFLAGS) nfsmount_clnt.c @@ -95,8 +99,6 @@ nfsmount.x: nfsmount.o: nfs_mountversion.h nfs_mount3.h NFSMOUNTH=/usr/include/linux/nfs_mount.h -SWAPH=/usr/include/linux/swap.h -LOOPH=/usr/include/linux/loop.h nfs_mountversion.h: rm -f nfs_mountversion.h @@ -107,6 +109,7 @@ nfs_mountversion.h: echo '#define KERNEL_NFS_MOUNT_VERSION 0'; \ fi > nfs_mountversion.h +SWAPH=/usr/include/linux/swap.h swap.h: rm -f swap.h if [ -f $(SWAPH) ]; then cp $(SWAPH) .; else touch swap.h; fi @@ -115,14 +118,11 @@ swapargs.h: sh swap.configure loop.h: - rm -f loop.h - if [ -f $(LOOPH) ]; then cp $(LOOPH) .; else touch loop.h; fi + sh mk_loop_h clean: - rm -f a.out core *~ *.o swapargs.h $(PROGS) - -cleaner: clean + rm -f a.out core *~ *.o swapargs.h $(PROGS) swapoff rm -f swap.h loop.h nfs_mountversion.h -clobber distclean realclean: cleaner +clobber distclean realclean: clean # rm -f $(GEN_FILES) diff --git a/mount/Makefile.standalone b/mount/Makefile.standalone index 9576cdb1d..2cedcd235 100644 --- a/mount/Makefile.standalone +++ b/mount/Makefile.standalone @@ -135,9 +135,7 @@ loop.h: clean: rm -f a.out core *~ *.o swapargs.h $(PROGS) swapoff - -cleaner: clean rm -f swap.h loop.h nfs_mountversion.h -clobber distclean realclean: cleaner +clobber distclean realclean: clean rm -f $(GEN_FILES) diff --git a/mount/fstab.5 b/mount/fstab.5 index e276350c2..8af521b2f 100644 --- a/mount/fstab.5 +++ b/mount/fstab.5 @@ -36,6 +36,7 @@ .\" Sat Nov 20 20:47:38 1993: hpfs documentation added .\" Sat Nov 27 20:23:32 1993: Updated authorship information .\" Wed Jul 26 00:00:00 1995: Updated some nfs stuff, joey@infodrom.north.de +.\" Tue Apr 2 00:38:28 1996: added info about "noauto", "user", etc. .\" .TH FSTAB 5 "27 November 1993" "Linux 0.99" "Linux Programmer's Manual" .SH NAME @@ -53,7 +54,10 @@ 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) +.BR fsck (8), +.BR mount (8), +and +.BR umount (8) sequentially iterate through .B fstab doing their thing. @@ -122,6 +126,10 @@ see .BR mount (8). For documentation on all nfs-specific options have a look at .BR nfs (5). +Common for all types of file system are the options ``noauto'' +(do not mount when "mount -a" is given, e.g., at boot time), +and ``user'' (allow a user to mount). For more details, see +.BR mount (8). The fifth field, .RI ( fs_freq ), diff --git a/mount/fstab.c b/mount/fstab.c index 524779a63..6a2adc657 100644 --- a/mount/fstab.c +++ b/mount/fstab.c @@ -372,12 +372,12 @@ update_mtab (const char *dir, struct mntent *instead) { endmntent (fp); if (fchmod (fileno (ftmp), S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH) < 0) - fprintf(stderr, "error changing mode of %s: %s", MOUNTED_TEMP, + fprintf(stderr, "error changing mode of %s: %s\n", MOUNTED_TEMP, strerror (errno)); endmntent (ftmp); if (rename (MOUNTED_TEMP, MOUNTED) < 0) - fprintf(stderr, "can't rename %s to %s: %s", MOUNTED_TEMP, MOUNTED, + fprintf(stderr, "can't rename %s to %s: %s\n", MOUNTED_TEMP, MOUNTED, strerror(errno)); leave: diff --git a/mount/h/loop.h b/mount/h/loop.h index a78dff721..1bd7fa87a 100644 --- a/mount/h/loop.h +++ b/mount/h/loop.h @@ -25,20 +25,12 @@ struct loop_info { 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 3 #define MAX_LO_CRYPT 4 -/* - * IOCTL commands --- we will commandeer 0x4C ('L') - */ - #define LOOP_SET_FD 0x4C00 #define LOOP_CLR_FD 0x4C01 #define LOOP_SET_STATUS 0x4C02 diff --git a/mount/linux_fs.h b/mount/linux_fs.h new file mode 100644 index 000000000..4e73c3b04 --- /dev/null +++ b/mount/linux_fs.h @@ -0,0 +1,59 @@ +/* Including <linux/fs.h> became more and more painful. + Below a very abbreviated version of some declarations, + only designed to be able to check a magic number + in case no filesystem type was given. */ + +#ifndef BLKGETSIZE +#define BLKGETSIZE 0x1260 /* return device size */ +#endif + +#define MINIX_SUPER_MAGIC 0x137F /* original minix fs */ +#define MINIX_SUPER_MAGIC2 0x138F /* minix fs, 30 char names */ +struct minix_super_block { + u_char s_dummy[16]; + u_char s_magic[2]; +}; +#define minixmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8)) + +#define ISODCL(from, to) (to - from + 1) +#define ISO_STANDARD_ID "CD001" +struct iso_volume_descriptor { + char type[ISODCL(1,1)]; /* 711 */ + char id[ISODCL(2,6)]; + char version[ISODCL(7,7)]; + char data[ISODCL(8,2048)]; +}; + +#define HS_STANDARD_ID "CDROM" +struct hs_volume_descriptor { + char foo[ISODCL ( 1, 8)]; /* 733 */ + char type[ISODCL ( 9, 9)]; /* 711 */ + char id[ISODCL ( 10, 14)]; + char version[ISODCL ( 15, 15)]; /* 711 */ + char data[ISODCL(16,2048)]; +}; + +#define EXT_SUPER_MAGIC 0x137D +struct ext_super_block { + u_char s_dummy[56]; + u_char s_magic[2]; +}; +#define extmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8)) + +#define EXT2_PRE_02B_MAGIC 0xEF51 +#define EXT2_SUPER_MAGIC 0xEF53 +struct ext2_super_block { + u_char s_dummy[56]; + u_char s_magic[2]; +}; +#define ext2magic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8)) + +#define _XIAFS_SUPER_MAGIC 0x012FD16D +struct xiafs_super_block { + u_char s_boot_segment[512]; /* 1st sector reserved for boot */ + u_char s_dummy[60]; + u_char s_magic[4]; +}; +#define xiafsmagic(s) ((uint) s.s_magic[0] + (((uint) s.s_magic[1]) << 8) + \ + (((uint) s.s_magic[2]) << 16) + \ + (((uint) s.s_magic[3]) << 24)) diff --git a/mount/lomount.c b/mount/lomount.c index a6ad187ae..276ab4e49 100644 --- a/mount/lomount.c +++ b/mount/lomount.c @@ -18,13 +18,12 @@ #include <sys/ioctl.h> #include <sys/stat.h> -#if defined(__GLIBC__) -#define _SOCKETBITS_H -#endif /* __GLIBC */ -#include "sundries.h" /* for xstrdup */ #include "loop.h" #include "lomount.h" +char *xstrdup (const char *s); /* not: #include "sundries.h" */ +void error (const char *fmt, ...); /* idem */ + #ifdef LOOP_SET_FD struct crypt_type_struct { int id; @@ -137,17 +136,17 @@ find_unused_loop_device (void) if (loop_known == 1) error( "mount: Could not find any loop device.\n" -" Maybe /dev/loop# has a wrong major number?\n"); +" Maybe /dev/loop# has a wrong major number?"); else if (loop_known == -1) error( "mount: Could not find any loop device, and, according to %s,\n" " this kernel does not know about the loop device.\n" -" (If so, then recompile or `insmod loop.o'.)\n", PROC_DEVICES); +" (If so, then recompile or `insmod loop.o'.)", PROC_DEVICES); else error( "mount: Could not find any loop device. Maybe this kernel does not know\n" " about the loop device (then recompile or `insmod loop.o'), or\n" -" maybe /dev/loop# has the wrong major number?\n"); +" maybe /dev/loop# has the wrong major number?"); } else error("mount: could not find any free loop device"); return 0; @@ -180,7 +179,7 @@ set_loop (const char *device, const char *file, int offset, 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); + fprintf (stderr, "Unsupported encryption type %s\n", encryption); return 1; } loopinfo.lo_offset = offset; diff --git a/mount/losetup.c b/mount/losetup.c index ae5886ac4..8f9dbe52b 100644 --- a/mount/losetup.c +++ b/mount/losetup.c @@ -56,7 +56,7 @@ static void show_loop(const char *device) { struct loop_info loopinfo; int fd; - + if ((fd = open(device, O_RDWR)) < 0) { perror(device); return; @@ -80,7 +80,7 @@ int set_loop(const char *device, const char *file, int offset, struct loop_info loopinfo; int fd, ffd, mode, i; char *pass; - + mode = *loopro ? O_RDONLY : O_RDWR; if ((ffd = open (file, mode)) < 0 && !*loopro && (errno != EROFS || (ffd = open (file, mode = O_RDONLY)) < 0)) { @@ -98,7 +98,7 @@ int set_loop(const char *device, const char *file, int offset, 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); + fprintf(stderr,"Unsupported encryption type %s\n",encryption); exit(1); } loopinfo.lo_offset = offset; diff --git a/mount/mk_loop_h b/mount/mk_loop_h new file mode 100644 index 000000000..9351b57e0 --- /dev/null +++ b/mount/mk_loop_h @@ -0,0 +1,30 @@ +#!/bin/sh +# +# Figure out (i) the type of dev_t (ii) the defines for loop stuff +# + +rm -f loop.h + +# Since 1.3.79 there is an include file <asm/posix_types.h> +# that defines __kernel_dev_t. +# (The file itself appeared in 1.3.78, but there it defined __dev_t.) +# If it exists, we use it. Otherwise we guess that __kernel_dev_t +# is an unsigned short (which is true on i386, but false on alpha). + +if [ -f /usr/include/asm/posix_types.h ]; then + echo '#include <asm/posix_types.h>' >> loop.h + echo '#define dev_t __kernel_dev_t' >> loop.h +else + echo '#define dev_t unsigned short' >> loop.h +fi + +# Next we have to find the loop stuff itself. +# First try kernel source, then a private version. + +if [ -f /usr/include/linux/loop.h ]; then + echo '#include <linux/loop.h>' >> loop.h +else + echo '#include "h/loop.h"' >> loop.h +fi + +echo '#undef dev_t' >> loop.h diff --git a/mount/mount.8 b/mount/mount.8 index e1ed6f4a3..097dee005 100644 --- a/mount/mount.8 +++ b/mount/mount.8 @@ -27,21 +27,22 @@ .\" Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, .\" USA. .\" -.\" 960705, aeb: version for mount-2.5k +.\" 960705, aeb: version for mount-2.7g .\" 970114, aeb: xiafs and ext are dead; romfs is new .\" 970623, aeb: -F option +.\" 970914, reg: -s option .\" -.TH MOUNT 8 "5 July 1996" "Linux 2.0" "Linux Programmer's Manual" +.TH MOUNT 8 "14 September 1997" "Linux 2.0" "Linux Programmer's Manual" .SH NAME mount \- mount a file system .SH SYNOPSIS .BI "mount [\-hV]" .LP -.BI "mount \-a [\-fFnrvw] [\-t " vfstype ] +.BI "mount \-a [\-fFnrsvw] [\-t " vfstype ] .br -.BI "mount [\-fnrvw] [\-o " options " [,...]] " "device " | " dir" +.BI "mount [\-fnrsvw] [\-o " options " [,...]] " "device " | " dir" .br -.BI "mount [\-fnrvw] [\-t " vfstype "] [\-o " options "] " "device dir" +.BI "mount [\-fnrsvw] [\-t " vfstype "] [\-o " options "] " "device dir" .SH DESCRIPTION All files accessible in a Unix system are arranged in one big tree, the file hierarchy, rooted at @@ -224,7 +225,8 @@ Mount all filesystems (of the given types) mentioned in (Used in conjunction with .BR \-a .) Fork off a new incarnation of mount for each device. -This will do the mounts on different devices in parallel. +This will do the mounts on different devices or different NFS servers +in parallel. This has the advantage that it is faster; also NFS timeouts go in parallel. A disadvantage is that the mounts are done in undefined order. Thus, you cannot use this option if you want to mount both @@ -249,6 +251,12 @@ This is necessary for example when .I /etc is on a read-only file system. .TP +.B \-s +Tolerate sloppy mount options rather than failing. This will ignore +mount options not supported by a filesystem type. Not all filesystems +support this option. This option exists for support of the Linux +autofs\-based automounter. +.TP .B \-r Mount the file system read-only. A synonym is .BR "\-o ro" . diff --git a/mount/mount.c b/mount/mount.c index 98093956c..19c507640 100644 --- a/mount/mount.c +++ b/mount/mount.c @@ -27,6 +27,9 @@ * Fri Apr 5 01:13:33 1996: quinlan@bucknell.edu, fixed up iso9660 autodetect * * Since then, many changes - aeb. + * + * Wed Oct 1 23:55:28 1997: Dick Streefland <dick_streefland@tasking.com> + * Implemented the "bg", "fg" and "retry" mount options for NFS. */ #include <unistd.h> @@ -34,6 +37,7 @@ #include <errno.h> #include <string.h> #include <getopt.h> +#include <stdio.h> #include <sys/types.h> #include <sys/ioctl.h> @@ -41,27 +45,26 @@ #include <sys/wait.h> #include <sys/mount.h> -#if !defined(__GLIBC__) -#define _LINUX_TYPES_H /* kludge to prevent inclusion */ -#endif /* __GLIBC */ -#define _LINUX_WAIT_H /* idem */ -#define _I386_BITOPS_H /* idem */ -#include <linux/fs.h> -#include <linux/minix_fs.h> -#include <linux/ext2_fs.h> -#include <linux/iso_fs.h> - -#if defined(__GLIBC__) -#define _SOCKETBITS_H -#endif /* __GLIBC */ +#include "mount_constants.h" #include "sundries.h" #include "fstab.h" #include "lomount.h" #include "loop.h" +#include "linux_fs.h" #define PROC_FILESYSTEMS "/proc/filesystems" #define SIZE(a) (sizeof(a)/sizeof(a[0])) +#define DO_PS_FIDDLING + +#ifdef DO_PS_FIDDLING +#define PROC_NAME "mount: " +static int argc0; +static char** argv0; +static char** envp0; +extern char** environ; +#endif + /* True for fake mount (-f). */ int fake = 0; @@ -74,6 +77,9 @@ int readonly = 0; /* Nonzero for chatty (-v). */ int verbose = 0; +/* Nonzero for sloppy (-s). */ +int sloppy = 0; + /* True for explicit read/write (-w). */ int readwrite = 0; @@ -146,6 +152,10 @@ const struct opt_map opt_map[] = { { "atime", 0, 1, MS_NOATIME }, /* Update access time */ { "noatime", 0, 0, MS_NOATIME }, /* Do not update access time */ #endif +#ifdef MS_NODIRATIME + { "diratime", 0, 1, MS_NODIRATIME }, /* Update dir access times */ + { "nodiratime", 0, 0, MS_NODIRATIME },/* Do not update dir access times */ +#endif { NULL, 0, 0, 0 } }; @@ -307,30 +317,6 @@ fix_opts_string (int flags, char *extra_opts) xiafs does not touch the 1st sector and has its magic in the 2nd sector; ext2 does not touch the first two sectors. */ -/* ext definitions - required since 2.1.21 */ -#ifndef EXT_SUPER_MAGIC -#define EXT_SUPER_MAGIC 0x137D -struct ext_super_block { - unsigned long s_dummy[14]; - unsigned short s_magic; -}; -#endif - -/* xiafs definitions - required since they were removed from - the kernel since 2.1.21 */ -#ifndef _XIAFS_SUPER_MAGIC -#define _XIAFS_SUPER_MAGIC 0x012FD16D -struct xiafs_super_block { - u_char s_boot_segment[512]; /* 1st sector reserved for boot */ - u_long s_dummy[15]; - u_long s_magic; /* 15: magic number for xiafs */ -}; -#endif - -#ifndef EXT2_PRE_02B_MAGIC -#define EXT2_PRE_02B_MAGIC 0xEF51 -#endif - static inline unsigned short swapped(unsigned short a) { return (a>>8) | (a<<8); @@ -348,7 +334,7 @@ swapped(unsigned short a) { Added a test for iso9660 - aeb Added a test for high sierra (iso9660) - quinlan@bucknell.edu Corrected the test for xiafs - aeb - added romfs - aeb + Added romfs - aeb Currently supports: minix, ext, ext2, xiafs, iso9660, romfs */ @@ -394,20 +380,20 @@ fstype(const char *device) if (fd < 0) return 0; - if (lseek(fd, BLOCK_SIZE, SEEK_SET) != BLOCK_SIZE + if (lseek(fd, 1024, SEEK_SET) != 1024 || read(fd, (char *) &sb, sizeof(sb)) != sizeof(sb)) goto io_error; - if (sb.e2s.s_magic == EXT2_SUPER_MAGIC - || sb.e2s.s_magic == EXT2_PRE_02B_MAGIC - || sb.e2s.s_magic == swapped(EXT2_SUPER_MAGIC)) + if (ext2magic(sb.e2s) == EXT2_SUPER_MAGIC + || ext2magic(sb.e2s) == EXT2_PRE_02B_MAGIC + || ext2magic(sb.e2s) == swapped(EXT2_SUPER_MAGIC)) type = "ext2"; - else if (sb.ms.s_magic == MINIX_SUPER_MAGIC - || sb.ms.s_magic == MINIX_SUPER_MAGIC2) + else if (minixmagic(sb.ms) == MINIX_SUPER_MAGIC + || minixmagic(sb.ms) == MINIX_SUPER_MAGIC2) type = "minix"; - else if (sb.es.s_magic == EXT_SUPER_MAGIC) + else if (extmagic(sb.es) == EXT_SUPER_MAGIC) type = "ext"; if (!type) { @@ -415,7 +401,7 @@ fstype(const char *device) || read(fd, (char *) &xsb, sizeof(xsb)) != sizeof(xsb)) goto io_error; - if (xsb.xiasb.s_magic == _XIAFS_SUPER_MAGIC) + if (xiafsmagic(xsb.xiasb) == _XIAFS_SUPER_MAGIC) type = "xiafs"; else if(!strncmp(xsb.romfs_magic, "-rom1fs-", 8)) type = "romfs"; @@ -590,9 +576,16 @@ try_mount5 (char *spec, char *node, char **type, int flags, char *mount_opts) { return -1; } +/* + * try_mount_one() + * Try to mount one file system. When "bg" is 1, this is a retry + * in the background. One additional exit code EX_BG is used here. + * It is used to instruct the caller to retry the mount in the + * background. + */ static int -mount_one (char *spec0, char *node0, char *type0, char *opts0, - int freq, int pass) +try_mount_one (char *spec0, char *node0, char *type0, char *opts0, + int freq, int pass, int bg) { struct mntentchn mcn; struct mntent mnt; @@ -603,31 +596,13 @@ mount_one (char *spec0, char *node0, char *type0, char *opts0, static int added_ro = 0; int loop, looptype, offset; char *spec, *node, *type, *opts, *loopdev, *loopfile; + struct stat statbuf; spec = xstrdup(spec0); node = xstrdup(node0); type = xstrdup(type0); opts = xstrdup(opts0); -/* - * There are two special cases: nfs mounts and loop mounts. - * In the case of nfs mounts spec is probably of the form machine:path. - * In the case of a loop mount, either type is of the form lo@/dev/loop5 - * or the option "-o loop=/dev/loop5" or just "-o loop" is given, or - * mount just has to figure things out for itself from the fact that - * spec is not a block device. We do not test for a block device - * immediately: maybe later other types of mountable objects will occur. - */ - - if (type == NULL) { - if (strchr (spec, ':') != NULL) { - type = "nfs"; - if (verbose) - printf("mount: no type was given - " - "I'll assume nfs because of the colon\n"); - } - } - parse_opts (xstrdup (opts), &flags, &extra_opts); /* root may allow certain types of mounts by ordinary users */ @@ -645,10 +620,13 @@ mount_one (char *spec0, char *node0, char *type0, char *opts0, mount_opts = extra_opts; /* - * A loop mount? - * Only test for explicitly specified loop here, - * and try implicit loop if the mount fails. + * In the case of a loop mount, either type is of the form lo@/dev/loop5 + * or the option "-o loop=/dev/loop5" or just "-o loop" is given, or + * mount just has to figure things out for itself from the fact that + * spec is not a block device. We do not test for a block device + * immediately: maybe later other types of mountable objects will occur. */ + loopdev = opt_loopdev; looptype = (type && strncmp("lo@", type, 3) == 0); @@ -691,14 +669,16 @@ mount_one (char *spec0, char *node0, char *type0, char *opts0, } } - if (!fake && type && streq (type, "nfs")) + if (!fake && type && streq (type, "nfs")) { #ifdef HAVE_NFS - if (nfsmount (spec, node, &flags, &extra_opts, &mount_opts) != 0) - return EX_FAIL; + mnt_err = nfsmount (spec, node, &flags, &extra_opts, &mount_opts, bg); + if (mnt_err) + return mnt_err; #else die (EX_SOFTWARE, "mount: this version was compiled " "without support for the type `nfs'"); #endif + } /* * Call mount.TYPE for types that require a separate @@ -711,7 +691,6 @@ mount_one (char *spec0, char *node0, char *type0, char *opts0, if (strlen (type) < 100) #endif { - struct stat statbuf; char mountprog[120]; sprintf(mountprog, "/sbin/mount.%s", type); @@ -805,7 +784,6 @@ mount_one (char *spec0, char *node0, char *type0, char *opts0, { case EPERM: if (geteuid() == 0) { - struct stat statbuf; if (stat (node, &statbuf) || !S_ISDIR(statbuf.st_mode)) error ("mount: mount point %s is not a directory", node); else @@ -822,29 +800,26 @@ mount_one (char *spec0, char *node0, char *type0, char *opts0, } break; case ENOENT: - { struct stat statbuf; - if (lstat (node, &statbuf)) - error ("mount: mount point %s does not exist", node); - else if (stat (node, &statbuf)) - error ("mount: mount point %s is a symbolic link to nowhere", - node); - else if (stat (spec, &statbuf)) - error ("mount: special device %s does not exist", spec); - else { + if (lstat (node, &statbuf)) + error ("mount: mount point %s does not exist", node); + else if (stat (node, &statbuf)) + error ("mount: mount point %s is a symbolic link to nowhere", + node); + else if (stat (spec, &statbuf)) + error ("mount: special device %s does not exist", spec); + else { errno = mnt_err; perror("mount"); - } - break; } + break; case ENOTDIR: error ("mount: mount point %s is not a directory", node); break; case EINVAL: { int fd, size; - struct stat statbuf; if (flags & MS_REMOUNT) { - error ("mount: %s not mounted already, or bad option\n", node); + error ("mount: %s not mounted already, or bad option", node); } else { error ("mount: wrong fs type, bad option, bad superblock on %s,\n" " or too many mounted file systems", @@ -854,7 +829,7 @@ mount_one (char *spec0, char *node0, char *type0, char *opts0, && (fd = open(spec, O_RDONLY)) >= 0) { if(ioctl(fd, BLKGETSIZE, &size) == 0 && size <= 2) error (" (aren't you trying to mount an extended partition,\n" - " instead of some logical partition inside?)\n"); + " instead of some logical partition inside?)"); close(fd); } } @@ -892,19 +867,16 @@ mount_one (char *spec0, char *node0, char *type0, char *opts0, spec, type); break; case ENOTBLK: - { struct stat statbuf; - - if (stat (spec, &statbuf)) /* strange ... */ - error ("mount: %s is not a block device, and stat fails?", spec); - else if (S_ISBLK(statbuf.st_mode)) - error ("mount: the kernel does not recognize %s as a block device\n" - " (maybe `insmod driver'?)", spec); - else if (S_ISREG(statbuf.st_mode)) - error ("mount: %s is not a block device (maybe try `-o loop'?)", + if (stat (spec, &statbuf)) /* strange ... */ + error ("mount: %s is not a block device, and stat fails?", spec); + else if (S_ISBLK(statbuf.st_mode)) + error ("mount: the kernel does not recognize %s as a block device\n" + " (maybe `insmod driver'?)", spec); + else if (S_ISREG(statbuf.st_mode)) + error ("mount: %s is not a block device (maybe try `-o loop'?)", spec); - else - error ("mount: %s is not a block device", spec); - } + else + error ("mount: %s is not a block device", spec); break; case ENXIO: error ("mount: %s is not a valid block device", spec); break; @@ -929,7 +901,7 @@ mount_one (char *spec0, char *node0, char *type0, char *opts0, type = 0; error ("mount: %s%s is write-protected, mounting read-only", loop ? "" : "block device ", spec0); - return mount_one (spec0, node0, type, opts, freq, pass); + return try_mount_one (spec0, node0, type, opts, freq, pass, bg); } break; default: @@ -938,6 +910,90 @@ mount_one (char *spec0, char *node0, char *type0, char *opts0, return EX_FAIL; } +/* + * set_proc_name() + * Update the argument vector, so that this process may be easily + * identified in a "ps" listing. + */ +static void +set_proc_name (char *spec) +{ +#ifdef DO_PS_FIDDLING + int i, l; + + /* + * Move the environment so we can reuse the memory. + * (Code borrowed from sendmail.) + * WARNING: ugly assumptions on memory layout here; if this ever causes + * problems, #undef DO_PS_FIDDLING + */ + for (i = 0; envp0[i] != NULL; i++) + continue; + environ = (char **) xmalloc(sizeof(char *) * (i + 1)); + for (i = 0; envp0[i] != NULL; i++) + environ[i] = xstrdup(envp0[i]); + environ[i] = NULL; + + if (i > 0) + l = envp0[i-1] + strlen(envp0[i-1]) - argv0[0]; + else + l = argv0[argc0-1] + strlen(argv0[argc0-1]) - argv0[0]; + if (l > sizeof(PROC_NAME)) { + strcpy(argv0[0], PROC_NAME); + strncpy(argv0[0] + sizeof(PROC_NAME) - 1, spec, l - sizeof(PROC_NAME) - 1); + argv0[1] = NULL; + } +#endif +} + +static int +mount_one (char *spec, char *node, char *type, char *opts, char *cmdlineopts, + int freq, int pass) +{ + int status; + int status2; + + /* Merge the fstab and command line options. */ + if (opts == NULL) + opts = cmdlineopts; + else if (cmdlineopts != NULL) + opts = xstrconcat3(opts, ",", cmdlineopts); + + if (type == NULL) { + if (strchr (spec, ':') != NULL) { + type = "nfs"; + if (verbose) + printf("mount: no type was given - " + "I'll assume nfs because of the colon\n"); + } + } + + /* + * Try to mount the file system. When the exit status is EX_BG, + * we will retry in the background. Otherwise, we're done. + */ + status = try_mount_one (spec, node, type, opts, freq, pass, 0); + if (status != EX_BG) + return status; + + /* + * Retry in the background. + */ + printf ("mount: backgrounding \"%s\"\n", spec); + fflush( stdout ); /* prevent duplicate output */ + if (fork() > 0) + return 0; /* parent returns "success" */ + spec = xstrdup(spec); /* arguments will be destroyed */ + node = xstrdup(node); /* by set_proc_name() */ + type = xstrdup(type); + opts = xstrdup(opts); + set_proc_name (spec); /* make a nice "ps" listing */ + status2 = try_mount_one (spec, node, type, opts, freq, pass, 1); + if (verbose && status2) + printf ("mount: giving up \"%s\"\n", spec); + exit (0); /* child stops here */ +} + /* Check if an fsname/dir pair was already in the old mtab. */ static int mounted (char *spec, char *node) { @@ -956,23 +1012,25 @@ mounted (char *spec, char *node) { /* With the --fork option: fork and let different incarnations of mount handle different filesystems. However, try to avoid several simultaneous mounts on the same physical disk, since that is very slow. */ -#define DISKMAJOR(m) ((m) & ~0xf) +#define DISKMAJOR(m) (((int) m) & ~0xf) static int -mount_all (string_list types) { +mount_all (string_list types, char *options) { struct mntentchn *mc, *mtmp; - int status = 0, m; + int status = 0; struct stat statbuf; struct child { pid_t pid; - dev_t major; + char *group; struct mntentchn *mec; struct mntentchn *meclast; struct child *nxt; } childhead, *childtail, *cp; + char major[22]; + char *g, *colon; /* build a chain of what we have to do, or maybe - several chains, one for each major */ + several chains, one for each major or NFS host */ childhead.nxt = 0; childtail = &childhead; for (mc = fstab_head()->nxt; mc; mc = mc->nxt) { @@ -987,13 +1045,25 @@ mount_all (string_list types) { mtmp = (struct mntentchn *) xmalloc(sizeof(*mtmp)); *mtmp = *mc; mtmp->nxt = 0; - m = 0; - if (optfork && stat(mc->mnt_fsname, &statbuf) == 0 - && S_ISBLK(statbuf.st_mode)) - m = DISKMAJOR(statbuf.st_rdev); - if (m) { + g = NULL; + if (optfork) { + if (stat(mc->mnt_fsname, &statbuf) == 0 && + S_ISBLK(statbuf.st_mode)) { + sprintf(major, "#%x", DISKMAJOR(statbuf.st_rdev)); + g = major; + } +#ifdef HAVE_NFS + if (strcmp(mc->mnt_type, "nfs") == 0) { + g = xstrdup(mc->mnt_fsname); + colon = strchr(g, ':'); + if (colon) + *colon = '\0'; + } +#endif + } + if (g) { for (cp = childhead.nxt; cp; cp = cp->nxt) - if (cp->major == m) { + if (cp->group && strcmp(cp->group, g) == 0) { cp->meclast->nxt = mtmp; cp->meclast = mtmp; goto fnd; @@ -1002,7 +1072,7 @@ mount_all (string_list types) { cp = (struct child *) xmalloc(sizeof *cp); cp->nxt = 0; cp->mec = cp->meclast = mtmp; - cp->major = m; + cp->group = xstrdup(g); cp->pid = 0; childtail->nxt = cp; childtail = cp; @@ -1026,7 +1096,8 @@ mount_all (string_list types) { if (p == 0 || p == -1) { for (mc = cp->mec; mc; mc = mc->nxt) status |= mount_one (mc->mnt_fsname, mc->mnt_dir, - mc->mnt_type, mc->mnt_opts, 0, 0); + mc->mnt_type, mc->mnt_opts, + options, 0, 0); if (mountcount) status |= EX_SOMEOK; if (p == 0) @@ -1076,9 +1147,9 @@ static struct option longopts[] = const char *usage_string = "\ usage: mount [-hV]\n\ - mount -a [-nfFrvw] [-t vfstypes]\n\ - mount [-nfrvw] [-o options] special | node\n\ - mount [-nfrvw] [-t vfstype] [-o options] special node\n\ + mount -a [-nfFrsvw] [-t vfstypes]\n\ + mount [-nfrsvw] [-o options] special | node\n\ + mount [-nfrsvw] [-t vfstype] [-o options] special node\n\ "; static void @@ -1096,7 +1167,13 @@ main (int argc, char *argv[]) { string_list types = NULL; struct mntentchn *mc; - while ((c = getopt_long (argc, argv, "afFhno:rvVwt:", longopts, NULL)) +#ifdef DO_PS_FIDDLING + argc0 = argc; + argv0 = argv; + envp0 = environ; +#endif + + while ((c = getopt_long (argc, argv, "afFhno:rsvVwt:", longopts, NULL)) != EOF) switch (c) { case 'a': /* mount everything in fstab */ @@ -1124,6 +1201,9 @@ main (int argc, char *argv[]) { readonly = 1; readwrite = 0; break; + case 's': /* allow sloppy mount options */ + sloppy = 1; + break; case 't': /* specify file system types */ types = parse_list (optarg); break; @@ -1147,11 +1227,10 @@ main (int argc, char *argv[]) { argc -= optind; argv += optind; - if (argc == 0) { + if (argc == 0 && !all) { if (options) usage (stderr, EX_USAGE); - if (!all) - return print_all (types); + return print_all (types); } if (getuid () != geteuid ()) { @@ -1169,7 +1248,7 @@ main (int argc, char *argv[]) { switch (argc) { case 0: /* mount -a */ - result = mount_all (types); + result = mount_all (types, options); if (result == 0 && verbose) error("not mounted anything"); break; @@ -1186,22 +1265,18 @@ main (int argc, char *argv[]) { die (EX_USAGE, "mount: can't find %s in %s or %s", spec, MOUNTED, _PATH_FSTAB); - /* Merge the fstab and command line options. */ - if (options == NULL) - options = mc->mnt_opts; - else - options = xstrconcat3(mc->mnt_opts, ",", options); - result = mount_one (xstrdup (mc->mnt_fsname), xstrdup (mc->mnt_dir), - xstrdup (mc->mnt_type), options, 0, 0); + xstrdup (mc->mnt_type), mc->mnt_opts, options, 0, 0); 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); + result = mount_one (argv[0], argv[1], + NULL, NULL, options, 0, 0); else if (cdr (types) == NULL) - result = mount_one (argv[0], argv[1], car (types), options, 0, 0); + result = mount_one (argv[0], argv[1], + car (types), NULL, options, 0, 0); else usage (stderr, EX_USAGE); break; diff --git a/mount/mount_constants.h b/mount/mount_constants.h index c0ae49849..5f033452d 100644 --- a/mount/mount_constants.h +++ b/mount/mount_constants.h @@ -5,13 +5,12 @@ #define MS_SYNCHRONOUS 16 /* Writes are synced at once */ #define MS_REMOUNT 32 /* Alter flags of a mounted FS */ #define MS_MANDLOCK 64 /* Allow mandatory locks on an FS */ -#define S_WRITE 128 /* Write on file/directory/symlink */ -#define S_APPEND 256 /* Append-only file */ -#define S_IMMUTABLE 512 /* Immutable file */ #define MS_NOATIME 1024 /* Do not update access times. */ - +#define MS_NODIRATIME 2048 /* Do not update directory access times */ /* * Magic mount flag number. Has to be or-ed to the flag values. */ +#ifndef MS_MGC_VAL #define MS_MGC_VAL 0xC0ED0000 /* magic flag number to indicate "new" flags */ +#endif #define MS_MGC_MSK 0xffff0000 /* magic flag number mask */ diff --git a/mount/nfs.5 b/mount/nfs.5 index cdfba803d..59f199b2b 100644 --- a/mount/nfs.5 +++ b/mount/nfs.5 @@ -21,7 +21,7 @@ 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 +server:/usr/local/pub /pub nfs rsize=8192,wsize=8192,timeo=14,intr .fi .DT .SS Options @@ -29,10 +29,14 @@ server:/usr/local/pub /pub nfs timeo=14,intr .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. +(However, throughput is improved greatly by asking for +.IR rsize=8192 .) .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. +(However, throughput is improved greatly by asking for +.IR wsize=8192 .) .TP 1.5i .I timeo=n The value in tenths of a second before sending the @@ -85,9 +89,9 @@ 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. +The number of minutes to retry an NFS mount operation +in the foreground or background before giving up. +The default value is 10000 minutes, which is roughly one week. .TP 1.5i .I namlen=n When an NFS server does not support version two of the @@ -140,13 +144,20 @@ 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 +If the first NFS mount attempt times out, retry the mount in the background. -The default is to not to background the mount on timeout but fail. +After a mount operation is backgrounded, all subsequent mounts +on the same NFS server will be backgrounded immediately, without +first attempting the mount. +A missing mount point is treated as a timeout, +to allow for nested NFS mounts. .TP 1.5i .I fg -If the first NFS mount attempt times out, fail immediately. -This is the default. +If the first NFS mount attempt times out, retry the mount +in the foreground. +This is the complement of the +.I bg +option, and also the default behavior. .TP 1.5i .I soft If an NFS file operation has a major timeout then report an I/O error to @@ -173,7 +184,7 @@ 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. +Suppress the retrieval of new attributes when creating a file. .TP 1.5i .I noac Disable all forms of attribute caching entirely. This extracts a @@ -199,7 +210,7 @@ interrupted. .SH AUTHOR "Rick Sladkey" <jrs@world.std.com> .SH BUGS -The bg, fg, retry, posix, and nocto options are parsed by mount +The 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 diff --git a/mount/nfsmount.c b/mount/nfsmount.c index ee869dc44..fd9364669 100644 --- a/mount/nfsmount.c +++ b/mount/nfsmount.c @@ -17,6 +17,9 @@ * * Fri, 8 Mar 1996 18:01:39, Swen Thuemmler <swen@uni-paderborn.de>: * Omit the call to connect() for Linux version 1.3.11 or later. + * + * Wed Oct 1 23:55:28 1997: Dick Streefland <dick_streefland@tasking.com> + * Implemented the "bg", "fg" and "retry" mount options for NFS. */ /* @@ -34,17 +37,14 @@ #include <sys/socket.h> #include <sys/time.h> #include <sys/utsname.h> +#include <sys/stat.h> #include <arpa/inet.h> #include "sundries.h" #include "nfsmount.h" -#if defined(__GLIBC__) -#define _LINUX_SOCKET_H -#endif /* __GLIBC__ */ -#define _I386_BITOPS_H -#include <linux/fs.h> #include <linux/nfs.h> +#include "mount_constants.h" #include "nfs_mount3.h" static char *nfs_strerror(int stat); @@ -96,8 +96,9 @@ find_kernel_nfs_mount_version(void) { } int nfsmount(const char *spec, const char *node, int *flags, - char **extra_opts, char **mount_opts) + char **extra_opts, char **mount_opts, int running_bg) { + static char *prev_bg_host; char hostdir[1024]; CLIENT *mclient; char *hostname; @@ -115,8 +116,9 @@ int nfsmount(const char *spec, const char *node, int *flags, struct sockaddr_in server_addr; struct sockaddr_in mount_server_addr; int msock, fsock; - struct timeval pertry_timeout; + struct timeval retry_timeout; struct fhstatus status; + struct stat statbuf; char *s; int port; int mountport; @@ -133,9 +135,14 @@ int nfsmount(const char *spec, const char *node, int *flags, int mountvers; int nfsprog; int nfsvers; + int retval; + time_t t; + time_t prevt; + time_t timeout; find_kernel_nfs_mount_version(); + retval = EX_FAIL; msock = fsock = -1; mclient = NULL; if (strlen(spec) >= sizeof(hostdir)) { @@ -148,21 +155,30 @@ int nfsmount(const char *spec, const char *node, int *flags, hostname = hostdir; dirname = s + 1; *s = '\0'; - } - else { + } else { fprintf(stderr, "mount: " "directory to mount not in host:dir format\n"); goto fail; } server_addr.sin_family = AF_INET; - if (!inet_aton(hostname, &server_addr.sin_addr)) { +#if 1 /* old libc's do not have inet_aton() -- change 1 to 0 */ + if (!inet_aton(hostname, &server_addr.sin_addr)) +#endif + { if ((hp = gethostbyname(hostname)) == NULL) { fprintf(stderr, "mount: can't get address for %s\n", hostname); goto fail; - } else - memcpy(&server_addr.sin_addr, hp->h_addr, hp->h_length); + } else { + if (hp->h_length > sizeof(struct in_addr)) { + fprintf(stderr, + "mount: got bad hp->h_length\n"); + hp->h_length = sizeof(struct in_addr); + } + memcpy(&server_addr.sin_addr, + hp->h_addr, hp->h_length); + } } memcpy (&mount_server_addr, &server_addr, sizeof (mount_server_addr)); @@ -203,7 +219,7 @@ int nfsmount(const char *spec, const char *node, int *flags, nocto = 0; nolock = 0; noac = 0; - retry = 10000; + retry = 10000; /* 10000 minutes ~ 1 week */ tcp = 0; mountprog = MOUNTPROG; @@ -306,9 +322,11 @@ int nfsmount(const char *spec, const char *node, int *flags, else printf("Warning: option nolock is not supported.\n"); } else { - printf("unknown nfs mount option: " - "%s%s\n", val ? "" : "no", opt); - goto fail; + if (!sloppy) { + printf("unknown nfs mount option: " + "%s%s\n", val ? "" : "no", opt); + goto fail; + } } } } @@ -349,9 +367,6 @@ int nfsmount(const char *spec, const char *node, int *flags, printf("tcp = %d\n", (data.flags & NFS_MOUNT_TCP) != 0); #endif -#if 0 - goto fail; -#endif #endif data.version = nfs_mount_version; @@ -360,58 +375,132 @@ int nfsmount(const char *spec, const char *node, int *flags, if (*flags & MS_REMOUNT) return 0; + /* + * If the previous mount operation on the same host was + * backgrounded, and the "bg" for this mount is also set, + * give up immediately, to avoid the initial timeout. + */ + if (bg && !running_bg && + prev_bg_host && strcmp(hostname, prev_bg_host) == 0) { + if (retry > 0) + retval = EX_BG; + return retval; + } + /* 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); + } else { + if ((hp = gethostbyname(mounthost)) == NULL) { + fprintf(stderr, "mount: can't get address for %s\n", + hostname); + goto fail; + } else { + if (hp->h_length > sizeof(struct in_addr)) { + fprintf(stderr, + "mount: got bad hp->h_length?\n"); + hp->h_length = sizeof(struct in_addr); + } + 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"); + /* + * The following loop implements the mount retries. On the first + * call, "running_bg" is 0. When the mount times out, and the + * "bg" option is set, the exit status EX_BG will be returned. + * For a backgrounded mount, there will be a second call by the + * child process with "running_bg" set to 1. + * + * The case where the mount point is not present and the "bg" + * option is set, is treated as a timeout. This is done to + * support nested mounts. + * + * The "retry" count specified by the user is the number of + * minutes to retry before giving up. + * + * Only the first error message will be displayed. + */ + retry_timeout.tv_sec = 3; + retry_timeout.tv_usec = 0; + total_timeout.tv_sec = 20; + total_timeout.tv_usec = 0; + timeout = time(NULL) + 60 * retry; + prevt = 0; + t = 30; + val = 1; + for (;;) { + if (bg && stat(node, &statbuf) == -1) { + if (running_bg) { + sleep(val); /* 1, 2, 4, 8, 16, 30, ... */ + val *= 2; + if (val > 30) + val = 30; + } + } else { + /* be careful not to use too many CPU cycles */ + if (t - prevt < 30) + sleep(30); + + /* contact the mount daemon via TCP */ + mount_server_addr.sin_port = htons(mountport); + msock = RPC_ANYSOCK; + mclient = clnttcp_create(&mount_server_addr, + mountprog, mountvers, + &msock, 0, 0); + + /* if this fails, contact the mount daemon via UDP */ + if (!mclient) { + mount_server_addr.sin_port = htons(mountport); + msock = RPC_ANYSOCK; + mclient = clntudp_create(&mount_server_addr, + mountprog, mountvers, + retry_timeout, &msock); + } + if (mclient) { + /* try to mount hostname:dirname */ + mclient->cl_auth = authunix_create_default(); + clnt_stat = clnt_call(mclient, MOUNTPROC_MNT, + (xdrproc_t) xdr_dirpath, (caddr_t) &dirname, + (xdrproc_t) xdr_fhstatus, (caddr_t) &status, + total_timeout); + if (clnt_stat == RPC_SUCCESS) + break; /* we're done */ + if (errno != ECONNREFUSED) { + clnt_perror(mclient, "mount"); + goto fail; /* don't retry */ + } + if (!running_bg && prevt == 0) + clnt_perror(mclient, "mount"); + auth_destroy(mclient->cl_auth); + clnt_destroy(mclient); + mclient = 0; + close(msock); + } else { + if (!running_bg && prevt == 0) + clnt_pcreateerror("mount"); + } + prevt = t; + } + if (!bg) + goto fail; + if (!running_bg) { + prev_bg_host = xstrdup(hostname); + if (retry > 0) + retval = EX_BG; goto fail; } -#ifdef NFS_MOUNT_DEBUG - printf("using UDP for mount deamon\n"); -#endif + t = time(NULL); + if (t >= timeout) + goto fail; } -#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, - (xdrproc_t) xdr_dirpath, &dirname, - (xdrproc_t) 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", @@ -485,15 +574,16 @@ int nfsmount(const char *spec, const char *node, int *flags, fail: if (msock != -1) { - auth_destroy(mclient->cl_auth); - clnt_destroy(mclient); + if (mclient) { + auth_destroy(mclient->cl_auth); + clnt_destroy(mclient); + } close(msock); } if (fsock != -1) close(fsock); - return 1; -} - + return retval; +} /* * We need to translate between nfs status return values and @@ -554,3 +644,33 @@ static char *nfs_strerror(int stat) return buf; } +#if 0 +int +my_getport(struct in_addr server, struct timeval *timeo, ...) +{ + struct sockaddr_in sin; + struct pmap pmap; + CLIENT *clnt; + int sock = RPC_ANYSOCK, port; + + pmap.pm_prog = prog; + pmap.pm_vers = vers; + pmap.pm_prot = prot; + pmap.pm_port = 0; + sin.sin_family = AF_INET; + sin.sin_addr = server; + sin.sin_port = htons(111); + clnt = clntudp_create(&sin, 100000, 2, *timeo, &sock); + status = clnt_call(clnt, PMAP_GETPORT, + &pmap, (xdrproc_t) xdr_pmap, + &port, (xdrproc_t) xdr_uint); + if (status != SUCCESS) { + /* natter */ + port = 0; + } + + clnt_destroy(clnt); + close(sock); + return port; +} +#endif diff --git a/mount/nfsmount_clnt.c b/mount/nfsmount_clnt.c index a77f4c5eb..ef5752583 100644 --- a/mount/nfsmount_clnt.c +++ b/mount/nfsmount_clnt.c @@ -66,7 +66,9 @@ mountproc_mnt_1(argp, clnt) static fhstatus clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); - if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, argp, (xdrproc_t) xdr_fhstatus, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, + (caddr_t) argp, (xdrproc_t) xdr_fhstatus, + (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); @@ -80,7 +82,9 @@ mountproc_dump_1(argp, clnt) static mountlist clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); - if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_mountlist, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, + (caddr_t) argp, (xdrproc_t) xdr_mountlist, + (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); @@ -94,7 +98,9 @@ mountproc_umnt_1(argp, clnt) static char clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); - if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath, + (caddr_t) argp, (xdrproc_t) xdr_void, + (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return ((void *)&clnt_res); @@ -108,7 +114,9 @@ mountproc_umntall_1(argp, clnt) static char clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); - if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void, + (caddr_t) argp, (xdrproc_t) xdr_void, + (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return ((void *)&clnt_res); @@ -122,7 +130,9 @@ mountproc_export_1(argp, clnt) static exports clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); - if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void, + (caddr_t) argp, (xdrproc_t) xdr_exports, + (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); @@ -136,8 +146,10 @@ mountproc_exportall_1(argp, clnt) static exports clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); - if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) { - return (NULL); + if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, + (caddr_t) argp, (xdrproc_t) xdr_exports, + (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { + return (NULL); } return (&clnt_res); } @@ -164,7 +176,9 @@ mountproc_mnt_2(argp, clnt) static fhstatus clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); - if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, argp, (xdrproc_t) xdr_fhstatus, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + if (clnt_call(clnt, MOUNTPROC_MNT, (xdrproc_t) xdr_dirpath, + (caddr_t) argp, (xdrproc_t) xdr_fhstatus, + (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); @@ -178,7 +192,9 @@ mountproc_dump_2(argp, clnt) static mountlist clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); - if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_mountlist, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + if (clnt_call(clnt, MOUNTPROC_DUMP, (xdrproc_t) xdr_void, argp, + (xdrproc_t) xdr_mountlist, (caddr_t) &clnt_res, + TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); @@ -192,7 +208,9 @@ mountproc_umnt_2(argp, clnt) static char clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); - if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + if (clnt_call(clnt, MOUNTPROC_UMNT, (xdrproc_t) xdr_dirpath, + (caddr_t) argp, (xdrproc_t) xdr_void, + (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return ((void *)&clnt_res); @@ -206,7 +224,9 @@ mountproc_umntall_2(argp, clnt) static char clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); - if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_void, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + if (clnt_call(clnt, MOUNTPROC_UMNTALL, (xdrproc_t) xdr_void, + (caddr_t) argp, (xdrproc_t) xdr_void, + (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return ((void *)&clnt_res); @@ -220,7 +240,9 @@ mountproc_export_2(argp, clnt) static exports clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); - if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + if (clnt_call(clnt, MOUNTPROC_EXPORT, (xdrproc_t) xdr_void, + argp, (xdrproc_t) xdr_exports, (caddr_t) &clnt_res, + TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); @@ -234,7 +256,9 @@ mountproc_exportall_2(argp, clnt) static exports clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); - if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, argp, (xdrproc_t) xdr_exports, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + if (clnt_call(clnt, MOUNTPROC_EXPORTALL, (xdrproc_t) xdr_void, argp, + (xdrproc_t) xdr_exports, (caddr_t) &clnt_res, + TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); @@ -248,7 +272,9 @@ mountproc_pathconf_2(argp, clnt) static ppathcnf clnt_res; memset((char *)&clnt_res, 0, sizeof(clnt_res)); - if (clnt_call(clnt, MOUNTPROC_PATHCONF, (xdrproc_t) xdr_dirpath, argp, (xdrproc_t) xdr_ppathcnf, &clnt_res, TIMEOUT) != RPC_SUCCESS) { + if (clnt_call(clnt, MOUNTPROC_PATHCONF, (xdrproc_t) xdr_dirpath, + (caddr_t) argp, (xdrproc_t) xdr_ppathcnf, + (caddr_t) &clnt_res, TIMEOUT) != RPC_SUCCESS) { return (NULL); } return (&clnt_res); diff --git a/mount/realpath.c b/mount/realpath.c index 4214cad72..0eebba3ac 100644 --- a/mount/realpath.c +++ b/mount/realpath.c @@ -46,9 +46,6 @@ extern char *realpath(const char *path, char *resolved_path); #include <sys/param.h> /* for MAXPATHLEN */ #endif #include <errno.h> -#ifndef STDC_HEADERS -extern int errno; -#endif #include <sys/stat.h> /* for S_IFLNK */ @@ -183,4 +180,3 @@ char *resolved_path; *new_path = '\0'; return resolved_path; } - diff --git a/mount/sundries.h b/mount/sundries.h index 0c96f865b..cad87a1c8 100644 --- a/mount/sundries.h +++ b/mount/sundries.h @@ -1,6 +1,6 @@ /* + * sundries.h * 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> @@ -9,12 +9,13 @@ #include <signal.h> #include <stdarg.h> #include <stdlib.h> -#ifndef bool_t +#if !defined(bool_t) && !defined(__GLIBC__) #include <rpc/types.h> #endif extern int mount_quiet; extern int verbose; +extern int sloppy; #define streq(s, t) (strcmp ((s), (t)) == 0) @@ -31,9 +32,6 @@ typedef struct string_list string_list cons (char *a, const string_list); -/* Quiet compilation with -Wmissing-prototypes. */ -int main (int argc, char *argv[]); - /* Functions in sundries.c that are used in mount.c and umount.c */ void block_signals (int how); char *canonicalize (const char *path); @@ -61,7 +59,7 @@ void die (int errcode, const char *fmt, ...); #ifdef HAVE_NFS int nfsmount (const char *spec, const char *node, int *flags, - char **orig_opts, char **opt_args); + char **orig_opts, char **opt_args, int running_bg); #endif /* exit status - bits below are ORed */ @@ -72,3 +70,5 @@ int nfsmount (const char *spec, const char *node, int *flags, #define EX_FILEIO 16 /* problems writing, locking, ... mtab/fstab */ #define EX_FAIL 32 /* mount failure */ #define EX_SOMEOK 64 /* some mount succeeded */ + +#define EX_BG 256 /* retry in background (internal only) */ diff --git a/mount/swap.configure b/mount/swap.configure index 70bce506b..a557e1871 100644 --- a/mount/swap.configure +++ b/mount/swap.configure @@ -1,5 +1,7 @@ -# find out whether we can include <sys/swap.h> +# Find out whether we can include <sys/swap.h> # and whether libc thinks that swapon() has two arguments. +# Of course this will fail if <sys/swap.h> exists but belongs +# to a libc that is not in use at present. CC=${CC-cc} compile="$CC -o conftest conftest.c >/dev/null 2>&1" rm -f conftest conftest.c swapargs.h diff --git a/mount/umount.c b/mount/umount.c index de80fd1bc..6f28213b4 100644 --- a/mount/umount.c +++ b/mount/umount.c @@ -100,13 +100,18 @@ nfs_umount_rpc_call(const char *spec, const char *opts) if (hostname[0] >= '0' && hostname[0] <= '9') saddr.sin_addr.s_addr = inet_addr(hostname); - else + else { if ((hostp = gethostbyname(hostname)) == NULL) { - fprintf(stderr, "mount: can't get address for %s\n", + fprintf(stderr, "umount: can't get address for %s\n", hostname); return 1; - } else - memcpy(&saddr.sin_addr, hostp->h_addr, hostp->h_length); + } + if (hostp->h_length > sizeof(struct in_addr)) { + fprintf(stderr, "umount: got bad hostp->h_length\n"); + hostp->h_length = sizeof(struct in_addr); + } + memcpy(&saddr.sin_addr, hostp->h_addr, hostp->h_length); + } saddr.sin_family = AF_INET; saddr.sin_port = 0; diff --git a/mount/version.c b/mount/version.c index c17613e08..0c9363d37 100644 --- a/mount/version.c +++ b/mount/version.c @@ -1 +1 @@ -char version[] = "mount-2.7e"; +char version[] = "mount-2.8"; |