summaryrefslogtreecommitdiffstats
path: root/mount
diff options
context:
space:
mode:
authorKarel Zak2006-12-07 00:25:35 +0100
committerKarel Zak2006-12-07 00:25:35 +0100
commit2b6fc908bc368b540845a313c3b8a867c5ad9a42 (patch)
tree6fad48a239bc90515a5dc4084d6e3c3ee1f41e29 /mount
parentImported from util-linux-2.7.1 tarball. (diff)
downloadkernel-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/Makefile18
-rw-r--r--mount/Makefile.standalone4
-rw-r--r--mount/fstab.510
-rw-r--r--mount/fstab.c4
-rw-r--r--mount/h/loop.h8
-rw-r--r--mount/linux_fs.h59
-rw-r--r--mount/lomount.c15
-rw-r--r--mount/losetup.c6
-rw-r--r--mount/mk_loop_h30
-rw-r--r--mount/mount.820
-rw-r--r--mount/mount.c339
-rw-r--r--mount/mount_constants.h7
-rw-r--r--mount/nfs.531
-rw-r--r--mount/nfsmount.c246
-rw-r--r--mount/nfsmount_clnt.c54
-rw-r--r--mount/realpath.c4
-rw-r--r--mount/sundries.h12
-rw-r--r--mount/swap.configure4
-rw-r--r--mount/umount.c13
-rw-r--r--mount/version.c2
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";