diff --git a/sbin/mount/Makefile b/sbin/mount/Makefile index 4cd26acd4176..6429858c05e9 100644 --- a/sbin/mount/Makefile +++ b/sbin/mount/Makefile @@ -2,8 +2,8 @@ # $FreeBSD$ PROG= mount -SRCS= mount.c mount_ufs.c getmntopts.c vfslist.c -WARNS?= 3 +SRCS= mount.c mount_fs.c mount_ufs.c getmntopts.c vfslist.c +WARNS?= 6 MAN= mount.8 # We do NOT install the getmntopts.3 man page. diff --git a/sbin/mount/extern.h b/sbin/mount/extern.h index 2271da5c699c..ef0666cb9b42 100644 --- a/sbin/mount/extern.h +++ b/sbin/mount/extern.h @@ -31,4 +31,5 @@ int checkvfsname(const char *, const char **); const char **makevfslist(char *); /* mount_ufs.c */ -int mount_ufs(int, char * const []); +int mount_ufs(int, char *[]); +int mount_fs(const char *, int, char *[]); diff --git a/sbin/mount/mount.c b/sbin/mount/mount.c index d2f90be6642c..f2eeff574ef7 100644 --- a/sbin/mount/mount.c +++ b/sbin/mount/mount.c @@ -74,7 +74,7 @@ struct statfs *getmntpt(const char *); int hasopt(const char *, const char *); int ismounted(struct fstab *, struct statfs *, int); int isremountable(const char *); -void mangle(char *, int *, const char **); +void mangle(char *, int *, char **); char *update_options(char *, char *, int); int mountfs(const char *, const char *, const char *, int, const char *, const char *); @@ -120,6 +120,67 @@ remountable_fs_names[] = { 0 }; +static int +use_mountprog(const char *vfstype) +{ + /* XXX: We need to get away from implementing external mount + * programs for every filesystem, and move towards having + * each filesystem properly implement the nmount() system call. + */ + unsigned int i; + const char *fs[] = { + "mfs", "msdosfs", "nfs", "nfs4", "ntfs", + "nwfs", "nullfs", "portalfs", "reiserfs", "smbfs", "udf", "umapfs", + "unionfs", + NULL + }; + + for (i=0; fs[i] != NULL; ++i) { + if (strcmp(vfstype, fs[i]) == 0) + return 1; + } + + return 0; +} + +static int +exec_mountprog(const char *name, const char *execname, + char *const argv[]) +{ + pid_t pid; + int status; + + switch (pid = fork()) { + case -1: /* Error. */ + warn("fork"); + exit (1); + case 0: /* Child. */ + /* Go find an executable. */ + execvP(execname, _PATH_SYSPATH, argv); + if (errno == ENOENT) { + warn("exec %s not found in %s", execname, + _PATH_SYSPATH); + } + exit(1); + default: /* Parent. */ + if (waitpid(pid, &status, 0) < 0) { + warn("waitpid"); + return (1); + } + + if (WIFEXITED(status)) { + if (WEXITSTATUS(status) != 0) + return (WEXITSTATUS(status)); + } else if (WIFSIGNALED(status)) { + warnx("%s: %s", name, sys_siglist[WTERMSIG(status)]); + return (1); + } + break; + } + + return (0); +} + int main(int argc, char *argv[]) { @@ -383,10 +444,9 @@ int mountfs(const char *vfstype, const char *spec, const char *name, int flags, const char *options, const char *mntopts) { - const char *argv[100]; + char *argv[100]; struct statfs sf; - pid_t pid; - int argc, i, status; + int argc, i, ret; char *optbuf, execname[PATH_MAX], mntpath[PATH_MAX]; #if __GNUC__ @@ -435,8 +495,8 @@ mountfs(const char *vfstype, const char *spec, const char *name, int flags, argc = 0; argv[argc++] = execname; mangle(optbuf, &argc, argv); - argv[argc++] = spec; - argv[argc++] = name; + argv[argc++] = strdup(spec); + argv[argc++] = strdup(name); argv[argc] = NULL; if (debug) { @@ -447,50 +507,25 @@ mountfs(const char *vfstype, const char *spec, const char *name, int flags, return (0); } - switch (pid = fork()) { - case -1: /* Error. */ - warn("fork"); - free(optbuf); - return (1); - case 0: /* Child. */ - if (strcmp(vfstype, "ufs") == 0) - exit(mount_ufs(argc, (char * const *) argv)); + if (strcmp(vfstype, "ufs")==0) { + ret = mount_ufs(argc, argv); + } else if (use_mountprog(vfstype)) { + ret = exec_mountprog(name, execname, argv); + } else { + ret = mount_fs(vfstype, argc, argv); + } - /* Go find an executable. */ - execvP(execname, _PATH_SYSPATH, (char * const *)argv); - if (errno == ENOENT) { - warn("exec mount_%s not found in %s", vfstype, - _PATH_SYSPATH); - } - exit(1); - /* NOTREACHED */ - default: /* Parent. */ - free(optbuf); + free(optbuf); - if (waitpid(pid, &status, 0) < 0) { - warn("waitpid"); + if (verbose) { + if (statfs(name, &sf) < 0) { + warn("statfs %s", name); return (1); } - - if (WIFEXITED(status)) { - if (WEXITSTATUS(status) != 0) - return (WEXITSTATUS(status)); - } else if (WIFSIGNALED(status)) { - warnx("%s: %s", name, sys_siglist[WTERMSIG(status)]); - return (1); - } - - if (verbose) { - if (statfs(name, &sf) < 0) { - warn("statfs %s", name); - return (1); - } - if (fstab_style) - putfsent(&sf); - else - prmount(&sf); - } - break; + if (fstab_style) + putfsent(&sf); + else + prmount(&sf); } return (0); @@ -583,7 +618,7 @@ void mangle(options, argcp, argv) char *options; int *argcp; - const char **argv; + char **argv; { char *p, *s; int argc; @@ -599,7 +634,7 @@ mangle(options, argcp, argv) argv[argc++] = p+1; } } else if (strcmp(p, "rw") != 0) { - argv[argc++] = "-o"; + argv[argc++] = strdup("-o"); argv[argc++] = p; } } diff --git a/sbin/mount/mount_fs.c b/sbin/mount/mount_fs.c new file mode 100644 index 000000000000..d56891fcf965 --- /dev/null +++ b/sbin/mount/mount_fs.c @@ -0,0 +1,135 @@ +/* + * Copyright (c) 1992, 1993, 1994 + * The Regents of the University of California. All rights reserved. + * + * This code is derived from software donated to Berkeley by + * Jan-Simon Pendry. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + * must display the following acknowledgement: + * This product includes software developed by the University of + * California, Berkeley and its contributors. + * 4. Neither the name of the University nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#ifndef lint +static const char copyright[] = +"@(#) Copyright (c) 1992, 1993, 1994\n\ + The Regents of the University of California. All rights reserved.\n"; +#endif /* not lint */ + +#ifndef lint +#if 0 +static char sccsid[] = "@(#)mount_fs.c 8.6 (Berkeley) 4/26/95"; +#endif +static const char rcsid[] = + "$FreeBSD$"; +#endif /* not lint */ + +#include +#include + +#include +#include +#include +#include +#include +#include +#include + +#include "extern.h" +#include "mntopts.h" + +struct mntopt mopts[] = { + MOPT_STDOPTS, + MOPT_END +}; + +static void +usage(void) +{ + (void)fprintf(stderr, + "usage: mount [-t fstype] [-o options] target_fs mount_point\n"); + exit(1); +} + +int +mount_fs(const char *vfstype, int argc, char *argv[]) +{ + struct iovec *iov; + int iovlen; + int mntflags = 0; + int ch; + char *dev, *dir, mntpath[MAXPATHLEN]; + char fstype[32]; + char *p, *val; + int ret; + + strncpy(fstype, vfstype, sizeof(fstype)); + + getmnt_silent = 1; + iov = NULL; + iovlen = 0; + + optind = optreset = 1; /* Reset for parse of new argv. */ + while ((ch = getopt(argc, argv, "o:")) != -1) { + switch(ch) { + case 'o': + getmntopts(optarg, mopts, &mntflags, 0); + p = strchr(optarg, '='); + val = NULL; + if (p != NULL) { + *p = '\0'; + val = p + 1; + } + build_iovec(&iov, &iovlen, optarg, val, -1); + break; + case '?': + default: + usage(); + } + } + + argc -= optind; + argv += optind; + if (argc != 2) + usage(); + + dev = argv[0]; + dir = argv[1]; + + (void)checkpath(dir, mntpath); + (void)rmslashes(dev, dev); + + build_iovec(&iov, &iovlen, "fstype", fstype, -1); + build_iovec(&iov, &iovlen, "fspath", mntpath, -1); + build_iovec(&iov, &iovlen, "from", dev, -1); + + ret = nmount(iov, iovlen, mntflags); + if (ret < 0) + err(1, "%s", dev); + + return (ret); +} diff --git a/sbin/mount/mount_ufs.c b/sbin/mount/mount_ufs.c index 3c99576de2e7..45e9bfc21ef9 100644 --- a/sbin/mount/mount_ufs.c +++ b/sbin/mount/mount_ufs.c @@ -68,7 +68,7 @@ static struct mntopt mopts[] = { }; int -mount_ufs(int argc, char * const argv[]) +mount_ufs(int argc, char *argv[]) { struct ufs_args args; int ch, mntflags;