/* $Header: /cvsroot/watchdog/watchdog/src/mount.c,v 1.2 2006/07/31 09:39:23 meskes Exp $ */
/*
* A mount(8) for Linux 0.99.
* mount.c,v 1.1.1.1 1993/11/18 08:40:51 jrs Exp
*
* Thu Jul 14 07:32:40 1994: faith@cs.unc.edu added changes from Adam
* J. Richter (adam@adam.yggdrasil.com) so that /proc/filesystems is used
* if no -t option is given. I modified his patches so that, if
* /proc/filesystems is not available, the behavior of mount is the same as
* it was previously.
*
* Wed Sep 14 22:43:00 1994: Mitchum DSouza
* (mitch@mrc-applied-psychology.cambridge.ac.uk) added support for mounting
* the "loop" device.
*
* Wed Sep 14 22:55:10 1994: Sander van Malssen (svm@kozmix.hacktic.nl)
* added support for remounting readonly file systems readonly.
*
* Wed Feb 8 09:23:18 1995: Mike Grupenhoff <kashmir@umiacs.UMD.EDU> added
* a probe of the superblock for the type before /proc/filesystems is
* checked.
*
* Wed Feb 8 12:27:00 1995: Andries.Brouwer@cwi.nl fixed up error messages.
* Sat Jun 3 20:44:38 1995: Patches from Andries.Brouwer@cwi.nl applied.
* Tue Sep 26 22:38:20 1995: aeb@cwi.nl, many changes
* Fri Feb 23 13:47:00 1996: aeb@cwi.nl, loop device related changes
*
* Fri Apr 5 01:13:33 1996: quinlan@bucknell.edu, fixed up iso9660 autodetect
*
* Since then, many changes - aeb.
*
* Wed Oct 1 23:55:28 1997: Dick Streefland <dick_streefland@tasking.com>
* Implemented the "bg", "fg" and "retry" mount options for NFS.
*
* Tue Aug 4 15:54:31 1998: aeb@cwi.nl:
* Open fd 0,1,2 so that printf's do not clobber /etc/mtab or so.
* Mangle filenames with embedded spaces. Add ufsmagic. Add locking.
* Avoid unnecessary error messages about /proc.
* Improve support for noncanonical names in /etc/fstab.
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <unistd.h>
#include <ctype.h>
#include <errno.h>
#include <string.h>
#include <getopt.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/stat.h>
#include <sys/wait.h>
#include <sys/mount.h>
#include "mount_constants.h"
#include "sundries.h"
#include "wd_mntent.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;
/* Don't write a entry in /etc/mtab (-n). */
int mount_nomtab = 0;
/* True for explicit readonly (-r). */
int readonly = 0;
/* Nonzero for chatty (-v). */
int mount_verbose = 0;
/* Nonzero for sloppy (-s). */
int sloppy = 0;
/* True for explicit read/write (-w). */
int readwrite = 0;
/* True for all mount (-a). */
int all = 0;
/* True for fork() during all mount (-F). */
int optfork = 0;
/* True if ruid != euid. */
int mount_suid = 0;
/* Map from -o and fstab option strings to the flag argument to mount(2). */
struct opt_map
{
const char *opt; /* option name */
int skip; /* skip in mtab option string */
int inv; /* true if flag value should be inverted */
int mask; /* flag mask value */
};
/* Custom mount options for our own purposes. */
/* We can use the high-order 16 bits, since the mount call
has MS_MGC_VAL there. */
#define MS_NOAUTO 0x80000000
#define MS_USER 0x40000000
#define MS_LOOP 0x00010000
/* Options that we keep the mount system call from seeing. */
#define MS_NOSYS (MS_NOAUTO|MS_USER|MS_LOOP)
/* Options that we keep from appearing in the options field in the mtab. */
#define MS_NOMTAB (MS_REMOUNT|MS_NOAUTO|MS_USER)
/* OPTIONS that we make ordinary users have by default. */
#define MS_SECURE (MS_NOEXEC|MS_NOSUID|MS_NODEV)
const struct opt_map opt_map[] = {
{ "defaults", 0, 0, 0 }, /* default options */
{ "ro", 1, 0, MS_RDONLY }, /* read-only */
{ "rw", 1, 1, MS_RDONLY }, /* read-write */
{ "exec", 0, 1, MS_NOEXEC }, /* permit execution of binaries */
{ "noexec", 0, 0, MS_NOEXEC }, /* don't execute binaries */
{ "mount_suid", 0, 1, MS_NOSUID }, /* honor mount_suid executables */
{ "nomount_suid", 0, 0, MS_NOSUID }, /* don't honor mount_suid executables */
{ "dev", 0, 1, MS_NODEV }, /* interpret device files */
{ "nodev", 0, 0, MS_NODEV }, /* don't interpret devices */
{ "sync", 0, 0, MS_SYNCHRONOUS}, /* synchronous I/O */
{ "async", 0, 1, MS_SYNCHRONOUS}, /* asynchronous I/O */
{ "remount", 0, 0, MS_REMOUNT}, /* Alter flags of mounted FS */
{ "auto", 0, 1, MS_NOAUTO }, /* Can be mounted using -a */
{ "noauto", 0, 0, MS_NOAUTO }, /* Can only be mounted explicitly */
{ "user", 0, 0, MS_USER }, /* Allow ordinary user to mount */
{ "nouser", 0, 1, MS_USER }, /* Forbid ordinary user to mount */
/* add new options here */
#ifdef MS_NOSUB
{ "sub", 0, 1, MS_NOSUB }, /* allow submounts */
{ "nosub", 0, 0, MS_NOSUB }, /* don't allow submounts */
#endif
#ifdef MS_SILENT
{ "quiet", 0, 0, MS_SILENT }, /* be quiet */
{ "loud", 0, 1, MS_SILENT }, /* print out messages. */
#endif
#ifdef MS_MANDLOCK
{ "mand", 0, 0, MS_MANDLOCK }, /* Allow mandatory locks on this FS */
{ "nomand", 0, 1, MS_MANDLOCK }, /* Forbid mandatory locks on this FS */
#endif
{ "loop", 1, 0, MS_LOOP }, /* use a loop device */
#ifdef MS_NOATIME
{ "atime", 0, 1, MS_NOATIME }, /* Update access time */
{ "noatime", 0, 0, MS_NOATIME }, /* Do not update access time */
#endif
#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 }
};
char *opt_loopdev, *opt_vfstype, *opt_offset, *opt_encryption;
struct string_opt_map {
char *tag;
int skip;
char **valptr;
} string_opt_map[] = {
{ "loop=", 0, &opt_loopdev },
{ "vfs=", 1, &opt_vfstype },
{ "offset=", 0, &opt_offset },
{ "encryption=", 0, &opt_encryption },
{ NULL, 0, NULL }
};
static void
clear_string_opts(void) {
struct string_opt_map *m;
for (m = &string_opt_map[0]; m->tag; m++)
*(m->valptr) = NULL;
}
static int
parse_string_opt(char *s) {
struct string_opt_map *m;
int lth;
for (m = &string_opt_map[0]; m->tag; m++) {
lth = strlen(m->tag);
if (!strncmp(s, m->tag, lth)) {
*(m->valptr) = xstrdup(s + lth);
return 1;
}
}
return 0;
}
int mount_mount_quiet=0;
/* Report on a single mount. */
static void
print_one (const struct mntentchn *mc) {
if (mount_mount_quiet)
return;
printf ("%s on %s", mc->mnt_fsname, mc->mnt_dir);
if (mc->mnt_type != NULL && *(mc->mnt_type) != '\0')
printf (" type %s", mc->mnt_type);
if (mc->mnt_opts != NULL)
printf (" (%s)", mc->mnt_opts);
printf ("\n");
}
/* Report on everything in mtab (of the specified types if any). */
static int
print_all (string_list types)
{
struct mntentchn *mc;
for (mc = mtab_head()->nxt; mc; mc = mc->nxt) {
if (matching_type (mc->mnt_type, types))
print_one (mc);
}
exit (0);
}
/* Look for OPT in opt_map table and return mask value. If OPT isn't found,
tack it onto extra_opts (which is non-NULL). */
static inline void
parse_opt (const char *opt, int *mask, char *extra_opts)
{
const struct opt_map *om;
for (om = opt_map; om->opt != NULL; om++)
if (streq (opt, om->opt))
{
if (om->inv)
*mask &= ~om->mask;
else
*mask |= om->mask;
if (om->mask == MS_USER)
*mask |= MS_SECURE;
#ifdef MS_SILENT
if (om->mask == MS_SILENT && om->inv) {
mount_mount_quiet = 1;
mount_verbose = 0;
}
#endif
return;
}
if (*extra_opts)
strcat(extra_opts, ",");
strcat(extra_opts, opt);
}
/* Take -o options list and compute 4th and 5th args to mount(2). flags
gets the standard options and extra_opts anything we don't recognize. */
static void
parse_opts (char *opts, int *flags, char **extra_opts)
{
char *o