xref: /dragonfly/sbin/mount_ufs/mount.c (revision 06f29be5)
19ecd3762SMatthew Dillon /*-
29ecd3762SMatthew Dillon  * Copyright (c) 1980, 1989, 1993, 1994
39ecd3762SMatthew Dillon  *	The Regents of the University of California.  All rights reserved.
49ecd3762SMatthew Dillon  *
59ecd3762SMatthew Dillon  * Redistribution and use in source and binary forms, with or without
69ecd3762SMatthew Dillon  * modification, are permitted provided that the following conditions
79ecd3762SMatthew Dillon  * are met:
89ecd3762SMatthew Dillon  * 1. Redistributions of source code must retain the above copyright
99ecd3762SMatthew Dillon  *    notice, this list of conditions and the following disclaimer.
109ecd3762SMatthew Dillon  * 2. Redistributions in binary form must reproduce the above copyright
119ecd3762SMatthew Dillon  *    notice, this list of conditions and the following disclaimer in the
129ecd3762SMatthew Dillon  *    documentation and/or other materials provided with the distribution.
13*dc71b7abSJustin C. Sherrill  * 3. Neither the name of the University nor the names of its contributors
149ecd3762SMatthew Dillon  *    may be used to endorse or promote products derived from this software
159ecd3762SMatthew Dillon  *    without specific prior written permission.
169ecd3762SMatthew Dillon  *
179ecd3762SMatthew Dillon  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
189ecd3762SMatthew Dillon  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
199ecd3762SMatthew Dillon  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
209ecd3762SMatthew Dillon  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
219ecd3762SMatthew Dillon  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
229ecd3762SMatthew Dillon  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
239ecd3762SMatthew Dillon  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
249ecd3762SMatthew Dillon  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
259ecd3762SMatthew Dillon  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
269ecd3762SMatthew Dillon  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
279ecd3762SMatthew Dillon  * SUCH DAMAGE.
289ecd3762SMatthew Dillon  *
299ecd3762SMatthew Dillon  * @(#) Copyright (c) 1980, 1989, 1993, 1994 The Regents of the University of California.  All rights reserved.
309ecd3762SMatthew Dillon  * @(#)mount.c	8.25 (Berkeley) 5/8/95
319ecd3762SMatthew Dillon  * $FreeBSD: src/sbin/mount/mount.c,v 1.39.2.3 2001/08/01 08:26:23 obrien Exp $
329ecd3762SMatthew Dillon  */
339ecd3762SMatthew Dillon 
349ecd3762SMatthew Dillon #include <sys/param.h>
359ecd3762SMatthew Dillon #include <sys/mount.h>
369ecd3762SMatthew Dillon #include <sys/mountctl.h>
379ecd3762SMatthew Dillon #include <sys/stat.h>
389ecd3762SMatthew Dillon #include <sys/wait.h>
399ecd3762SMatthew Dillon 
409ecd3762SMatthew Dillon #include <err.h>
419ecd3762SMatthew Dillon #include <errno.h>
429ecd3762SMatthew Dillon #include <fstab.h>
439ecd3762SMatthew Dillon #include <pwd.h>
449ecd3762SMatthew Dillon #include <signal.h>
459ecd3762SMatthew Dillon #include <stdio.h>
469ecd3762SMatthew Dillon #include <stdlib.h>
479ecd3762SMatthew Dillon #include <string.h>
489ecd3762SMatthew Dillon #include <unistd.h>
499ecd3762SMatthew Dillon 
509ecd3762SMatthew Dillon #include "extern.h"
519ecd3762SMatthew Dillon #include "mntopts.h"
529ecd3762SMatthew Dillon #include "pathnames.h"
539ecd3762SMatthew Dillon 
549ecd3762SMatthew Dillon /* `meta' options */
559ecd3762SMatthew Dillon #define MOUNT_META_OPTION_FSTAB		"fstab"
569ecd3762SMatthew Dillon #define MOUNT_META_OPTION_CURRENT	"current"
579ecd3762SMatthew Dillon 
589ecd3762SMatthew Dillon int debug, fstab_style, verbose;
599ecd3762SMatthew Dillon 
609ecd3762SMatthew Dillon static char  *catopt(char *, const char *);
619ecd3762SMatthew Dillon static struct statfs
629ecd3762SMatthew Dillon              *getmntpt(const char *);
639ecd3762SMatthew Dillon static int    hasopt(const char *, const char *);
649ecd3762SMatthew Dillon static int    ismounted(struct fstab *, struct statfs *, int);
659ecd3762SMatthew Dillon static int    isremountable(const char *);
669ecd3762SMatthew Dillon static void   mangle(char *, int *, const char **);
679ecd3762SMatthew Dillon static char  *update_options(char *, char *, int);
689ecd3762SMatthew Dillon static int    mountfs(const char *, const char *, const char *,
699ecd3762SMatthew Dillon 		      int, const char *, const char *);
709ecd3762SMatthew Dillon static void   remopt(char *, const char *);
719ecd3762SMatthew Dillon static void   printdefvals(const struct statfs *);
729ecd3762SMatthew Dillon static void   prmount(struct statfs *);
739ecd3762SMatthew Dillon static void   putfsent(const struct statfs *);
749ecd3762SMatthew Dillon static void   usage(void);
759ecd3762SMatthew Dillon static char  *flags2opts(int);
769ecd3762SMatthew Dillon static char  *xstrdup(const char *str);
779ecd3762SMatthew Dillon 
789ecd3762SMatthew Dillon /* mount_ufs.c */
799ecd3762SMatthew Dillon int mount_ufs(int, const char **);
809ecd3762SMatthew Dillon 
819ecd3762SMatthew Dillon /*
829ecd3762SMatthew Dillon  * List of VFS types that can be remounted without becoming mounted on top
839ecd3762SMatthew Dillon  * of each other.
849ecd3762SMatthew Dillon  * XXX Is this list correct?
859ecd3762SMatthew Dillon  */
869ecd3762SMatthew Dillon static const char *
879ecd3762SMatthew Dillon remountable_fs_names[] = {
889ecd3762SMatthew Dillon 	"ufs", "ffs", "ext2fs",
899ecd3762SMatthew Dillon 	0
909ecd3762SMatthew Dillon };
919ecd3762SMatthew Dillon 
929ecd3762SMatthew Dillon int
main(int argc,char ** argv)939ecd3762SMatthew Dillon main(int argc, char **argv)
949ecd3762SMatthew Dillon {
959ecd3762SMatthew Dillon 	const char *mntfromname, **vfslist, *vfstype;
969ecd3762SMatthew Dillon 	struct fstab *fs;
979ecd3762SMatthew Dillon 	struct statfs *mntbuf;
989ecd3762SMatthew Dillon 	FILE *mountdfp;
999ecd3762SMatthew Dillon 	pid_t pid;
1009ecd3762SMatthew Dillon 	int all, ch, i, init_flags, mntsize, rval, have_fstab;
1019ecd3762SMatthew Dillon 	char *options;
1029ecd3762SMatthew Dillon 
1039ecd3762SMatthew Dillon 	all = init_flags = 0;
1049ecd3762SMatthew Dillon 	options = NULL;
1059ecd3762SMatthew Dillon 	vfslist = NULL;
1069ecd3762SMatthew Dillon 	vfstype = "ufs";
1079ecd3762SMatthew Dillon 	while ((ch = getopt(argc, argv, "adF:fo:prwt:uv")) != -1)
1089ecd3762SMatthew Dillon 		switch (ch) {
1099ecd3762SMatthew Dillon 		case 'a':
1109ecd3762SMatthew Dillon 			all = 1;
1119ecd3762SMatthew Dillon 			break;
1129ecd3762SMatthew Dillon 		case 'd':
1139ecd3762SMatthew Dillon 			debug = 1;
1149ecd3762SMatthew Dillon 			break;
1159ecd3762SMatthew Dillon 		case 'F':
1169ecd3762SMatthew Dillon 			setfstab(optarg);
1179ecd3762SMatthew Dillon 			break;
1189ecd3762SMatthew Dillon 		case 'f':
1199ecd3762SMatthew Dillon 			init_flags |= MNT_FORCE;
1209ecd3762SMatthew Dillon 			break;
1219ecd3762SMatthew Dillon 		case 'o':
1229ecd3762SMatthew Dillon 			if (*optarg)
1239ecd3762SMatthew Dillon 				options = catopt(options, optarg);
1249ecd3762SMatthew Dillon 			break;
1259ecd3762SMatthew Dillon 		case 'p':
1269ecd3762SMatthew Dillon 			fstab_style = 1;
1279ecd3762SMatthew Dillon 			verbose = 1;
1289ecd3762SMatthew Dillon 			break;
1299ecd3762SMatthew Dillon 		case 'r':
1309ecd3762SMatthew Dillon 			options = catopt(options, "ro");
1319ecd3762SMatthew Dillon 			break;
1329ecd3762SMatthew Dillon 		case 't':
1339ecd3762SMatthew Dillon 			if (vfslist != NULL)
1349ecd3762SMatthew Dillon 				errx(1, "only one -t option may be specified");
1359ecd3762SMatthew Dillon 			vfslist = makevfslist(optarg);
1369ecd3762SMatthew Dillon 			vfstype = optarg;
1379ecd3762SMatthew Dillon 			break;
1389ecd3762SMatthew Dillon 		case 'u':
1399ecd3762SMatthew Dillon 			init_flags |= MNT_UPDATE;
1409ecd3762SMatthew Dillon 			break;
1419ecd3762SMatthew Dillon 		case 'v':
1429ecd3762SMatthew Dillon 			verbose = 1;
1439ecd3762SMatthew Dillon 			break;
1449ecd3762SMatthew Dillon 		case 'w':
1459ecd3762SMatthew Dillon 			options = catopt(options, "noro");
1469ecd3762SMatthew Dillon 			break;
1479ecd3762SMatthew Dillon 		case '?':
1489ecd3762SMatthew Dillon 		default:
1499ecd3762SMatthew Dillon 			usage();
1509ecd3762SMatthew Dillon 			/* NOTREACHED */
1519ecd3762SMatthew Dillon 		}
1529ecd3762SMatthew Dillon 	argc -= optind;
1539ecd3762SMatthew Dillon 	argv += optind;
1549ecd3762SMatthew Dillon 
1559ecd3762SMatthew Dillon #define	BADTYPE(type)							\
1569ecd3762SMatthew Dillon 	(strcmp(type, FSTAB_RO) &&					\
1579ecd3762SMatthew Dillon 	    strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ))
1589ecd3762SMatthew Dillon 
1599ecd3762SMatthew Dillon 	rval = 0;
1609ecd3762SMatthew Dillon 	switch (argc) {
1619ecd3762SMatthew Dillon 	case 0:
1629ecd3762SMatthew Dillon 		if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0)
1639ecd3762SMatthew Dillon 			err(1, "getmntinfo");
1649ecd3762SMatthew Dillon 		if (all) {
1659ecd3762SMatthew Dillon 			while ((fs = getfsent()) != NULL) {
1669ecd3762SMatthew Dillon 				if (BADTYPE(fs->fs_type))
1679ecd3762SMatthew Dillon 					continue;
1689ecd3762SMatthew Dillon 				if (checkvfsname(fs->fs_vfstype, vfslist))
1699ecd3762SMatthew Dillon 					continue;
1709ecd3762SMatthew Dillon 				if (hasopt(fs->fs_mntops, "noauto"))
1719ecd3762SMatthew Dillon 					continue;
1729ecd3762SMatthew Dillon 				if (!(init_flags & MNT_UPDATE) &&
1739ecd3762SMatthew Dillon 				    ismounted(fs, mntbuf, mntsize))
1749ecd3762SMatthew Dillon 					continue;
1759ecd3762SMatthew Dillon 				options = update_options(options,
1769ecd3762SMatthew Dillon 				    fs->fs_mntops, mntbuf->f_flags);
1779ecd3762SMatthew Dillon 				if (mountfs(fs->fs_vfstype, fs->fs_spec,
1789ecd3762SMatthew Dillon 				    fs->fs_file, init_flags, options,
1799ecd3762SMatthew Dillon 				    fs->fs_mntops))
1809ecd3762SMatthew Dillon 					rval = 1;
1819ecd3762SMatthew Dillon 			}
1829ecd3762SMatthew Dillon 		} else if (fstab_style) {
1839ecd3762SMatthew Dillon 			for (i = 0; i < mntsize; i++) {
1849ecd3762SMatthew Dillon 				if (checkvfsname(mntbuf[i].f_fstypename, vfslist))
1859ecd3762SMatthew Dillon 					continue;
1869ecd3762SMatthew Dillon 				putfsent(&mntbuf[i]);
1879ecd3762SMatthew Dillon 			}
1889ecd3762SMatthew Dillon 		} else {
1899ecd3762SMatthew Dillon 			for (i = 0; i < mntsize; i++) {
1909ecd3762SMatthew Dillon 				if (checkvfsname(mntbuf[i].f_fstypename,
1919ecd3762SMatthew Dillon 				    vfslist))
1929ecd3762SMatthew Dillon 					continue;
1939ecd3762SMatthew Dillon 				prmount(&mntbuf[i]);
1949ecd3762SMatthew Dillon 			}
1959ecd3762SMatthew Dillon 		}
1969ecd3762SMatthew Dillon 		exit(rval);
1979ecd3762SMatthew Dillon 	case 1:
1989ecd3762SMatthew Dillon 		if (vfslist != NULL)
1999ecd3762SMatthew Dillon 			usage();
2009ecd3762SMatthew Dillon 
2019ecd3762SMatthew Dillon 		rmslashes(*argv, *argv);
2029ecd3762SMatthew Dillon 
2039ecd3762SMatthew Dillon 		if (init_flags & MNT_UPDATE) {
2049ecd3762SMatthew Dillon 			mntfromname = NULL;
2059ecd3762SMatthew Dillon 			have_fstab = 0;
2069ecd3762SMatthew Dillon 			if ((mntbuf = getmntpt(*argv)) == NULL)
2079ecd3762SMatthew Dillon 				errx(1, "not currently mounted %s", *argv);
2089ecd3762SMatthew Dillon 			/*
2099ecd3762SMatthew Dillon 			 * Only get the mntflags from fstab if both mntpoint
2109ecd3762SMatthew Dillon 			 * and mntspec are identical. Also handle the special
2119ecd3762SMatthew Dillon 			 * case where just '/' is mounted and 'spec' is not
2129ecd3762SMatthew Dillon 			 * identical with the one from fstab ('/dev' is missing
2139ecd3762SMatthew Dillon 			 * in the spec-string at boot-time).
2149ecd3762SMatthew Dillon 			 */
2159ecd3762SMatthew Dillon 			if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) {
2169ecd3762SMatthew Dillon 				if (strcmp(fs->fs_spec,
2179ecd3762SMatthew Dillon 				    mntbuf->f_mntfromname) == 0 &&
2189ecd3762SMatthew Dillon 				    strcmp(fs->fs_file,
2199ecd3762SMatthew Dillon 				    mntbuf->f_mntonname) == 0) {
2209ecd3762SMatthew Dillon 					have_fstab = 1;
2219ecd3762SMatthew Dillon 					mntfromname = mntbuf->f_mntfromname;
2229ecd3762SMatthew Dillon 				} else if (argv[0][0] == '/' &&
2239ecd3762SMatthew Dillon 				    argv[0][1] == '\0') {
2249ecd3762SMatthew Dillon 					fs = getfsfile("/");
2259ecd3762SMatthew Dillon 					have_fstab = 1;
2269ecd3762SMatthew Dillon 					mntfromname = fs->fs_spec;
2279ecd3762SMatthew Dillon 				}
2289ecd3762SMatthew Dillon 			}
2299ecd3762SMatthew Dillon 			if (have_fstab) {
2309ecd3762SMatthew Dillon 				options = update_options(options, fs->fs_mntops,
2319ecd3762SMatthew Dillon 				    mntbuf->f_flags);
2329ecd3762SMatthew Dillon 			} else {
2339ecd3762SMatthew Dillon 				mntfromname = mntbuf->f_mntfromname;
2349ecd3762SMatthew Dillon 				options = update_options(options, NULL,
2359ecd3762SMatthew Dillon 				    mntbuf->f_flags);
2369ecd3762SMatthew Dillon 			}
2379ecd3762SMatthew Dillon 			rval = mountfs(mntbuf->f_fstypename, mntfromname,
2389ecd3762SMatthew Dillon 			    mntbuf->f_mntonname, init_flags, options, 0);
2399ecd3762SMatthew Dillon 			break;
2409ecd3762SMatthew Dillon 		}
2419ecd3762SMatthew Dillon 		if ((fs = getfsfile(*argv)) == NULL &&
2429ecd3762SMatthew Dillon 		    (fs = getfsspec(*argv)) == NULL)
2439ecd3762SMatthew Dillon 			errx(1, "%s: unknown special file or file system",
2449ecd3762SMatthew Dillon 			    *argv);
2459ecd3762SMatthew Dillon 		if (BADTYPE(fs->fs_type))
2469ecd3762SMatthew Dillon 			errx(1, "%s has unknown file system type",
2479ecd3762SMatthew Dillon 			    *argv);
2489ecd3762SMatthew Dillon 		rval = mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file,
2499ecd3762SMatthew Dillon 		    init_flags, options, fs->fs_mntops);
2509ecd3762SMatthew Dillon 		break;
2519ecd3762SMatthew Dillon 	case 2:
2529ecd3762SMatthew Dillon 		/*
2539ecd3762SMatthew Dillon 		 * If -t flag has not been specified, the path cannot be
2549ecd3762SMatthew Dillon 		 * found, spec contains either a ':' or a '@', and the
2559ecd3762SMatthew Dillon 		 * spec is not a file with those characters, then assume
2569ecd3762SMatthew Dillon 		 * that an NFS filesystem is being specified ala Sun.
2579ecd3762SMatthew Dillon 		 */
2589ecd3762SMatthew Dillon 		if (vfslist == NULL && strpbrk(argv[0], ":@") != NULL &&
2599ecd3762SMatthew Dillon 		    access(argv[0], 0) == -1)
2609ecd3762SMatthew Dillon 			vfstype = "nfs";
2619ecd3762SMatthew Dillon 		rval = mountfs(vfstype, getdevpath(argv[0], 0), argv[1],
2629ecd3762SMatthew Dillon 			       init_flags, options, NULL);
2639ecd3762SMatthew Dillon 		break;
2649ecd3762SMatthew Dillon 	default:
2659ecd3762SMatthew Dillon 		usage();
2669ecd3762SMatthew Dillon 		/* NOTREACHED */
2679ecd3762SMatthew Dillon 	}
2689ecd3762SMatthew Dillon 
2699ecd3762SMatthew Dillon 	/*
2709ecd3762SMatthew Dillon 	 * If the mount was successfully, and done by root, tell mountd the
2719ecd3762SMatthew Dillon 	 * good news.  Pid checks are probably unnecessary, but don't hurt.
2729ecd3762SMatthew Dillon 	 */
2739ecd3762SMatthew Dillon 	if (rval == 0 && getuid() == 0 &&
2749ecd3762SMatthew Dillon 	    (mountdfp = fopen(_PATH_MOUNTDPID, "r")) != NULL) {
2759ecd3762SMatthew Dillon 		if (fscanf(mountdfp, "%d", &pid) == 1 &&
2769ecd3762SMatthew Dillon 		     pid > 0 && kill(pid, SIGHUP) == -1 && errno != ESRCH)
2779ecd3762SMatthew Dillon 			err(1, "signal mountd");
2789ecd3762SMatthew Dillon 		fclose(mountdfp);
2799ecd3762SMatthew Dillon 	}
2809ecd3762SMatthew Dillon 
2819ecd3762SMatthew Dillon 	exit(rval);
2829ecd3762SMatthew Dillon }
2839ecd3762SMatthew Dillon 
2849ecd3762SMatthew Dillon static int
ismounted(struct fstab * fs,struct statfs * mntbuf,int mntsize)2859ecd3762SMatthew Dillon ismounted(struct fstab *fs, struct statfs *mntbuf, int mntsize)
2869ecd3762SMatthew Dillon {
2879ecd3762SMatthew Dillon 	int i;
2889ecd3762SMatthew Dillon 
2899ecd3762SMatthew Dillon 	if (fs->fs_file[0] == '/' && fs->fs_file[1] == '\0')
2909ecd3762SMatthew Dillon 		/* the root file system can always be remounted */
2919ecd3762SMatthew Dillon 		return (0);
2929ecd3762SMatthew Dillon 
2939ecd3762SMatthew Dillon 	for (i = mntsize - 1; i >= 0; --i)
2949ecd3762SMatthew Dillon 		if (strcmp(fs->fs_file, mntbuf[i].f_mntonname) == 0 &&
2959ecd3762SMatthew Dillon 		    (!isremountable(fs->fs_vfstype) ||
2969ecd3762SMatthew Dillon 		     strcmp(fs->fs_spec, mntbuf[i].f_mntfromname) == 0))
2979ecd3762SMatthew Dillon 			return (1);
2989ecd3762SMatthew Dillon 	return (0);
2999ecd3762SMatthew Dillon }
3009ecd3762SMatthew Dillon 
3019ecd3762SMatthew Dillon static int
isremountable(const char * vfsname)3029ecd3762SMatthew Dillon isremountable(const char *vfsname)
3039ecd3762SMatthew Dillon {
3049ecd3762SMatthew Dillon 	const char **cp;
3059ecd3762SMatthew Dillon 
3069ecd3762SMatthew Dillon 	for (cp = remountable_fs_names; *cp; cp++)
3079ecd3762SMatthew Dillon 		if (strcmp(*cp, vfsname) == 0)
3089ecd3762SMatthew Dillon 			return (1);
3099ecd3762SMatthew Dillon 	return (0);
3109ecd3762SMatthew Dillon }
3119ecd3762SMatthew Dillon 
3129ecd3762SMatthew Dillon static int
hasopt(const char * mntopts,const char * option)3139ecd3762SMatthew Dillon hasopt(const char *mntopts, const char *option)
3149ecd3762SMatthew Dillon {
3159ecd3762SMatthew Dillon 	int negative, found;
3169ecd3762SMatthew Dillon 	char *opt, *optbuf;
3179ecd3762SMatthew Dillon 
3189ecd3762SMatthew Dillon 	if (option[0] == 'n' && option[1] == 'o') {
3199ecd3762SMatthew Dillon 		negative = 1;
3209ecd3762SMatthew Dillon 		option += 2;
3219ecd3762SMatthew Dillon 	} else
3229ecd3762SMatthew Dillon 		negative = 0;
3239ecd3762SMatthew Dillon 	optbuf = xstrdup(mntopts);
3249ecd3762SMatthew Dillon 	found = 0;
3259ecd3762SMatthew Dillon 	for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) {
3269ecd3762SMatthew Dillon 		if (opt[0] == 'n' && opt[1] == 'o') {
3279ecd3762SMatthew Dillon 			if (!strcasecmp(opt + 2, option))
3289ecd3762SMatthew Dillon 				found = negative;
3299ecd3762SMatthew Dillon 		} else if (!strcasecmp(opt, option))
3309ecd3762SMatthew Dillon 			found = !negative;
3319ecd3762SMatthew Dillon 	}
3329ecd3762SMatthew Dillon 	free(optbuf);
3339ecd3762SMatthew Dillon 	return (found);
3349ecd3762SMatthew Dillon }
3359ecd3762SMatthew Dillon 
3369ecd3762SMatthew Dillon static int
mountfs(const char * vfstype,const char * spec,const char * name,int flags,const char * options,const char * mntopts)3379ecd3762SMatthew Dillon mountfs(const char *vfstype, const char *spec, const char *name, int flags,
3389ecd3762SMatthew Dillon         const char *options, const char *mntopts)
3399ecd3762SMatthew Dillon {
3409ecd3762SMatthew Dillon 	/* List of directories containing mount_xxx subcommands. */
3419ecd3762SMatthew Dillon 	static const char *edirs[] = {
3429ecd3762SMatthew Dillon 		_PATH_SBIN,
3439ecd3762SMatthew Dillon 		_PATH_USRSBIN,
3449ecd3762SMatthew Dillon 		NULL
3459ecd3762SMatthew Dillon 	};
3469ecd3762SMatthew Dillon 	const char *argv[100], **edir;
3479ecd3762SMatthew Dillon 	struct statfs sf;
3489ecd3762SMatthew Dillon 	pid_t pid;
3499ecd3762SMatthew Dillon 	int argc, i, status;
3509ecd3762SMatthew Dillon 	char *optbuf, execname[MAXPATHLEN + 1], mntpath[MAXPATHLEN];
3519ecd3762SMatthew Dillon 
3529ecd3762SMatthew Dillon 	/* resolve the mountpoint with realpath(3) */
3539ecd3762SMatthew Dillon 	checkpath(name, mntpath);
3549ecd3762SMatthew Dillon 	name = mntpath;
3559ecd3762SMatthew Dillon 
3569ecd3762SMatthew Dillon 	if (mntopts == NULL)
3579ecd3762SMatthew Dillon 		mntopts = "";
3589ecd3762SMatthew Dillon 	if (options == NULL) {
3599ecd3762SMatthew Dillon 		if (*mntopts == '\0') {
3609ecd3762SMatthew Dillon 			options = "rw";
3619ecd3762SMatthew Dillon 		} else {
3629ecd3762SMatthew Dillon 			options = mntopts;
3639ecd3762SMatthew Dillon 			mntopts = "";
3649ecd3762SMatthew Dillon 		}
3659ecd3762SMatthew Dillon 	}
3669ecd3762SMatthew Dillon 	optbuf = catopt(xstrdup(mntopts), options);
3679ecd3762SMatthew Dillon 
3689ecd3762SMatthew Dillon 	if (strcmp(name, "/") == 0)
3699ecd3762SMatthew Dillon 		flags |= MNT_UPDATE;
3709ecd3762SMatthew Dillon 	if (flags & MNT_FORCE)
3719ecd3762SMatthew Dillon 		optbuf = catopt(optbuf, "force");
3729ecd3762SMatthew Dillon 	if (flags & MNT_RDONLY)
3739ecd3762SMatthew Dillon 		optbuf = catopt(optbuf, "ro");
3749ecd3762SMatthew Dillon 	/*
3759ecd3762SMatthew Dillon 	 * XXX
3769ecd3762SMatthew Dillon 	 * The mount_mfs (newfs) command uses -o to select the
3779ecd3762SMatthew Dillon 	 * optimization mode.  We don't pass the default "-o rw"
3789ecd3762SMatthew Dillon 	 * for that reason.
3799ecd3762SMatthew Dillon 	 */
3809ecd3762SMatthew Dillon 	if (flags & MNT_UPDATE)
3819ecd3762SMatthew Dillon 		optbuf = catopt(optbuf, "update");
3829ecd3762SMatthew Dillon 
3839ecd3762SMatthew Dillon 	argc = 0;
3849ecd3762SMatthew Dillon 	argv[argc++] = vfstype;
3859ecd3762SMatthew Dillon 	mangle(optbuf, &argc, argv);
3869ecd3762SMatthew Dillon 	argv[argc++] = spec;
3879ecd3762SMatthew Dillon 	argv[argc++] = name;
3889ecd3762SMatthew Dillon 	argv[argc] = NULL;
3899ecd3762SMatthew Dillon 
3909ecd3762SMatthew Dillon 	if (debug) {
3919ecd3762SMatthew Dillon 		printf("exec: mount_%s", vfstype);
3929ecd3762SMatthew Dillon 		for (i = 1; i < argc; i++)
3939ecd3762SMatthew Dillon 			printf(" %s", argv[i]);
3949ecd3762SMatthew Dillon 		printf("\n");
3959ecd3762SMatthew Dillon 		return (0);
3969ecd3762SMatthew Dillon 	}
3979ecd3762SMatthew Dillon 
3989ecd3762SMatthew Dillon 	switch (pid = fork()) {
3999ecd3762SMatthew Dillon 	case -1:				/* Error. */
4009ecd3762SMatthew Dillon 		warn("fork");
4019ecd3762SMatthew Dillon 		free(optbuf);
4029ecd3762SMatthew Dillon 		return (1);
4039ecd3762SMatthew Dillon 	case 0:					/* Child. */
4049ecd3762SMatthew Dillon 		if (strcmp(vfstype, "ufs") == 0)
4059ecd3762SMatthew Dillon 			exit(mount_ufs(argc, argv));
4069ecd3762SMatthew Dillon 
4079ecd3762SMatthew Dillon 		/* Go find an executable. */
4089ecd3762SMatthew Dillon 		for (edir = edirs; *edir; edir++) {
4099ecd3762SMatthew Dillon 			snprintf(execname,
4109ecd3762SMatthew Dillon 			    sizeof(execname), "%s/mount_%s", *edir, vfstype);
4119ecd3762SMatthew Dillon 			execv(execname, __DECONST(char * const *, argv));
4129ecd3762SMatthew Dillon 		}
4139ecd3762SMatthew Dillon 		if (errno == ENOENT) {
4149ecd3762SMatthew Dillon 			int len = 0;
4159ecd3762SMatthew Dillon 			char *cp;
4169ecd3762SMatthew Dillon 			for (edir = edirs; *edir; edir++)
4179ecd3762SMatthew Dillon 				len += strlen(*edir) + 2;	/* ", " */
4189ecd3762SMatthew Dillon 			if ((cp = malloc(len)) == NULL)
4199ecd3762SMatthew Dillon 				errx(1, "malloc failed");
4209ecd3762SMatthew Dillon 			cp[0] = '\0';
4219ecd3762SMatthew Dillon 			for (edir = edirs; *edir; edir++) {
4229ecd3762SMatthew Dillon 				strcat(cp, *edir);
4239ecd3762SMatthew Dillon 				if (edir[1] != NULL)
4249ecd3762SMatthew Dillon 					strcat(cp, ", ");
4259ecd3762SMatthew Dillon 			}
4269ecd3762SMatthew Dillon 			warn("exec mount_%s not found in %s", vfstype, cp);
4279ecd3762SMatthew Dillon 		}
4289ecd3762SMatthew Dillon 		exit(1);
4299ecd3762SMatthew Dillon 		/* NOTREACHED */
4309ecd3762SMatthew Dillon 	default:				/* Parent. */
4319ecd3762SMatthew Dillon 		free(optbuf);
4329ecd3762SMatthew Dillon 
4339ecd3762SMatthew Dillon 		if (waitpid(pid, &status, 0) < 0) {
4349ecd3762SMatthew Dillon 			warn("waitpid");
4359ecd3762SMatthew Dillon 			return (1);
4369ecd3762SMatthew Dillon 		}
4379ecd3762SMatthew Dillon 
4389ecd3762SMatthew Dillon 		if (WIFEXITED(status)) {
4399ecd3762SMatthew Dillon 			if (WEXITSTATUS(status) != 0)
4409ecd3762SMatthew Dillon 				return (WEXITSTATUS(status));
4419ecd3762SMatthew Dillon 		} else if (WIFSIGNALED(status)) {
4429ecd3762SMatthew Dillon 			warnx("%s: %s", name, sys_siglist[WTERMSIG(status)]);
4439ecd3762SMatthew Dillon 			return (1);
4449ecd3762SMatthew Dillon 		}
4459ecd3762SMatthew Dillon 
4469ecd3762SMatthew Dillon 		if (verbose) {
4479ecd3762SMatthew Dillon 			if (statfs(name, &sf) < 0) {
4489ecd3762SMatthew Dillon 				warn("statfs %s", name);
4499ecd3762SMatthew Dillon 				return (1);
4509ecd3762SMatthew Dillon 			}
4519ecd3762SMatthew Dillon 			if (fstab_style)
4529ecd3762SMatthew Dillon 				putfsent(&sf);
4539ecd3762SMatthew Dillon 			else
4549ecd3762SMatthew Dillon 				prmount(&sf);
4559ecd3762SMatthew Dillon 		}
4569ecd3762SMatthew Dillon 		break;
4579ecd3762SMatthew Dillon 	}
4589ecd3762SMatthew Dillon 
4599ecd3762SMatthew Dillon 	return (0);
4609ecd3762SMatthew Dillon }
4619ecd3762SMatthew Dillon 
4629ecd3762SMatthew Dillon static void
prmount(struct statfs * sfp)4639ecd3762SMatthew Dillon prmount(struct statfs *sfp)
4649ecd3762SMatthew Dillon {
4659ecd3762SMatthew Dillon 	struct passwd *pw;
4669ecd3762SMatthew Dillon 	char *buf;
467199559e7SSascha Wildner 	int error;
4689ecd3762SMatthew Dillon 	int len;
4699ecd3762SMatthew Dillon 
4709ecd3762SMatthew Dillon 	error = 0;
4719ecd3762SMatthew Dillon 	len = 256;
4729ecd3762SMatthew Dillon 
4739ecd3762SMatthew Dillon 	if ((buf = malloc(len)) == NULL)
4749ecd3762SMatthew Dillon 		errx(1, "malloc failed");
4759ecd3762SMatthew Dillon 
4769ecd3762SMatthew Dillon 	printf("%s on %s (%s", sfp->f_mntfromname, sfp->f_mntonname,
4779ecd3762SMatthew Dillon 	    sfp->f_fstypename);
4789ecd3762SMatthew Dillon 
4799ecd3762SMatthew Dillon 	/* Get a string buffer with all the used flags names */
4809ecd3762SMatthew Dillon 	error = mountctl(sfp->f_mntonname, MOUNTCTL_MOUNTFLAGS,
4819ecd3762SMatthew Dillon 			 -1, NULL, 0, buf, len);
4829ecd3762SMatthew Dillon 
4839ecd3762SMatthew Dillon 	if (sfp->f_owner) {
4849ecd3762SMatthew Dillon 		printf(", mounted by ");
4859ecd3762SMatthew Dillon 		if ((pw = getpwuid(sfp->f_owner)) != NULL)
4869ecd3762SMatthew Dillon 			printf("%s", pw->pw_name);
4879ecd3762SMatthew Dillon 		else
4889ecd3762SMatthew Dillon 			printf("%d", sfp->f_owner);
4899ecd3762SMatthew Dillon 	}
4909ecd3762SMatthew Dillon 
49144869c11SSascha Wildner 	if (error != -1 && strlen(buf))
4929ecd3762SMatthew Dillon 		printf(", %s", buf);
4939ecd3762SMatthew Dillon 
4949ecd3762SMatthew Dillon 	if (verbose) {
4959ecd3762SMatthew Dillon 		if (sfp->f_syncwrites != 0 || sfp->f_asyncwrites != 0)
4969ecd3762SMatthew Dillon 			printf(", writes: sync %ld async %ld",
4979ecd3762SMatthew Dillon 			    sfp->f_syncwrites, sfp->f_asyncwrites);
4989ecd3762SMatthew Dillon 		if (sfp->f_syncreads != 0 || sfp->f_asyncreads != 0)
4999ecd3762SMatthew Dillon 			printf(", reads: sync %ld async %ld",
5009ecd3762SMatthew Dillon 			    sfp->f_syncreads, sfp->f_asyncreads);
5019ecd3762SMatthew Dillon 	}
5029ecd3762SMatthew Dillon 	printf(")\n");
5039ecd3762SMatthew Dillon }
5049ecd3762SMatthew Dillon 
5059ecd3762SMatthew Dillon static struct statfs *
getmntpt(const char * name)5069ecd3762SMatthew Dillon getmntpt(const char *name)
5079ecd3762SMatthew Dillon {
5089ecd3762SMatthew Dillon 	struct statfs *mntbuf;
5099ecd3762SMatthew Dillon 	int i, mntsize;
5109ecd3762SMatthew Dillon 
5119ecd3762SMatthew Dillon 	mntsize = getmntinfo(&mntbuf, MNT_NOWAIT);
5129ecd3762SMatthew Dillon 	for (i = mntsize - 1; i >= 0; i--) {
5139ecd3762SMatthew Dillon 		if (strcmp(mntbuf[i].f_mntfromname, name) == 0 ||
5149ecd3762SMatthew Dillon 		    strcmp(mntbuf[i].f_mntonname, name) == 0)
5159ecd3762SMatthew Dillon 			return (&mntbuf[i]);
5169ecd3762SMatthew Dillon 	}
5179ecd3762SMatthew Dillon 	return (NULL);
5189ecd3762SMatthew Dillon }
5199ecd3762SMatthew Dillon 
5209ecd3762SMatthew Dillon static char *
catopt(char * s0,const char * s1)5219ecd3762SMatthew Dillon catopt(char *s0, const char *s1)
5229ecd3762SMatthew Dillon {
5239ecd3762SMatthew Dillon 	size_t i;
5249ecd3762SMatthew Dillon 	char *cp;
5259ecd3762SMatthew Dillon 
5269ecd3762SMatthew Dillon 	if (s1 == NULL || *s1 == '\0')
5279ecd3762SMatthew Dillon 		return s0;
5289ecd3762SMatthew Dillon 
5299ecd3762SMatthew Dillon 	if (s0 && *s0) {
5309ecd3762SMatthew Dillon 		i = strlen(s0) + strlen(s1) + 1 + 1;
5319ecd3762SMatthew Dillon 		if ((cp = malloc(i)) == NULL)
5329ecd3762SMatthew Dillon 			errx(1, "malloc failed");
5339ecd3762SMatthew Dillon 		snprintf(cp, i, "%s,%s", s0, s1);
5349ecd3762SMatthew Dillon 	} else
5359ecd3762SMatthew Dillon 		cp = xstrdup(s1);
5369ecd3762SMatthew Dillon 
5379ecd3762SMatthew Dillon 	if (s0)
5389ecd3762SMatthew Dillon 		free(s0);
5399ecd3762SMatthew Dillon 	return (cp);
5409ecd3762SMatthew Dillon }
5419ecd3762SMatthew Dillon 
5429ecd3762SMatthew Dillon static void
mangle(char * options,int * argcp,const char ** argv)5439ecd3762SMatthew Dillon mangle(char *options, int *argcp, const char **argv)
5449ecd3762SMatthew Dillon {
5459ecd3762SMatthew Dillon 	char *p, *s;
5469ecd3762SMatthew Dillon 	int argc;
5479ecd3762SMatthew Dillon 
5489ecd3762SMatthew Dillon 	argc = *argcp;
5499ecd3762SMatthew Dillon 	for (s = options; (p = strsep(&s, ",")) != NULL;)
5509ecd3762SMatthew Dillon 		if (*p != '\0') {
5519ecd3762SMatthew Dillon 			if (*p == '-') {
5529ecd3762SMatthew Dillon 				argv[argc++] = p;
5539ecd3762SMatthew Dillon 				p = strchr(p, '=');
5549ecd3762SMatthew Dillon 				if (p) {
5559ecd3762SMatthew Dillon 					*p = '\0';
5569ecd3762SMatthew Dillon 					argv[argc++] = p+1;
5579ecd3762SMatthew Dillon 				}
5589ecd3762SMatthew Dillon 			} else if (strcmp(p, "rw") != 0) {
5599ecd3762SMatthew Dillon 				argv[argc++] = "-o";
5609ecd3762SMatthew Dillon 				argv[argc++] = p;
5619ecd3762SMatthew Dillon 			}
5629ecd3762SMatthew Dillon 		}
5639ecd3762SMatthew Dillon 
5649ecd3762SMatthew Dillon 	*argcp = argc;
5659ecd3762SMatthew Dillon }
5669ecd3762SMatthew Dillon 
5679ecd3762SMatthew Dillon 
5689ecd3762SMatthew Dillon static char *
update_options(char * opts,char * fstab,int curflags)5699ecd3762SMatthew Dillon update_options(char *opts, char *fstab, int curflags)
5709ecd3762SMatthew Dillon {
5719ecd3762SMatthew Dillon 	char *o, *p;
5729ecd3762SMatthew Dillon 	char *cur;
5739ecd3762SMatthew Dillon 	char *expopt, *newopt, *tmpopt;
5749ecd3762SMatthew Dillon 
5759ecd3762SMatthew Dillon 	if (opts == NULL)
5769ecd3762SMatthew Dillon 		return xstrdup("");
5779ecd3762SMatthew Dillon 
5789ecd3762SMatthew Dillon 	/* remove meta options from list */
5799ecd3762SMatthew Dillon 	remopt(fstab, MOUNT_META_OPTION_FSTAB);
5809ecd3762SMatthew Dillon 	remopt(fstab, MOUNT_META_OPTION_CURRENT);
5819ecd3762SMatthew Dillon 	cur = flags2opts(curflags);
5829ecd3762SMatthew Dillon 
5839ecd3762SMatthew Dillon 	/*
5849ecd3762SMatthew Dillon 	 * Expand all meta-options passed to us first.
5859ecd3762SMatthew Dillon 	 */
5869ecd3762SMatthew Dillon 	expopt = NULL;
5879ecd3762SMatthew Dillon 	for (p = opts; (o = strsep(&p, ",")) != NULL;) {
5889ecd3762SMatthew Dillon 		if (strcmp(MOUNT_META_OPTION_FSTAB, o) == 0)
5899ecd3762SMatthew Dillon 			expopt = catopt(expopt, fstab);
5909ecd3762SMatthew Dillon 		else if (strcmp(MOUNT_META_OPTION_CURRENT, o) == 0)
5919ecd3762SMatthew Dillon 			expopt = catopt(expopt, cur);
5929ecd3762SMatthew Dillon 		else
5939ecd3762SMatthew Dillon 			expopt = catopt(expopt, o);
5949ecd3762SMatthew Dillon 	}
5959ecd3762SMatthew Dillon 	free(cur);
5969ecd3762SMatthew Dillon 	free(opts);
5979ecd3762SMatthew Dillon 
5989ecd3762SMatthew Dillon 	/*
5999ecd3762SMatthew Dillon 	 * Remove previous contradictory arguments. Given option "foo" we
6009ecd3762SMatthew Dillon 	 * remove all the "nofoo" options. Given "nofoo" we remove "nonofoo"
6019ecd3762SMatthew Dillon 	 * and "foo" - so we can deal with possible options like "notice".
6029ecd3762SMatthew Dillon 	 */
6039ecd3762SMatthew Dillon 	newopt = NULL;
6049ecd3762SMatthew Dillon 	for (p = expopt; (o = strsep(&p, ",")) != NULL;) {
6059ecd3762SMatthew Dillon 		if ((tmpopt = malloc( strlen(o) + 2 + 1 )) == NULL)
6069ecd3762SMatthew Dillon 			errx(1, "malloc failed");
6079ecd3762SMatthew Dillon 
6089ecd3762SMatthew Dillon 		strcpy(tmpopt, "no");
6099ecd3762SMatthew Dillon 		strcat(tmpopt, o);
6109ecd3762SMatthew Dillon 		remopt(newopt, tmpopt);
6119ecd3762SMatthew Dillon 		free(tmpopt);
6129ecd3762SMatthew Dillon 
6139ecd3762SMatthew Dillon 		if (strncmp("no", o, 2) == 0)
6149ecd3762SMatthew Dillon 			remopt(newopt, o+2);
6159ecd3762SMatthew Dillon 
6169ecd3762SMatthew Dillon 		newopt = catopt(newopt, o);
6179ecd3762SMatthew Dillon 	}
6189ecd3762SMatthew Dillon 	free(expopt);
6199ecd3762SMatthew Dillon 
6209ecd3762SMatthew Dillon 	return newopt;
6219ecd3762SMatthew Dillon }
6229ecd3762SMatthew Dillon 
6239ecd3762SMatthew Dillon static void
remopt(char * string,const char * opt)6249ecd3762SMatthew Dillon remopt(char *string, const char *opt)
6259ecd3762SMatthew Dillon {
6269ecd3762SMatthew Dillon 	char *o, *p, *r;
6279ecd3762SMatthew Dillon 
6289ecd3762SMatthew Dillon 	if (string == NULL || *string == '\0' || opt == NULL || *opt == '\0')
6299ecd3762SMatthew Dillon 		return;
6309ecd3762SMatthew Dillon 
6319ecd3762SMatthew Dillon 	r = string;
6329ecd3762SMatthew Dillon 
6339ecd3762SMatthew Dillon 	for (p = string; (o = strsep(&p, ",")) != NULL;) {
6349ecd3762SMatthew Dillon 		if (strcmp(opt, o) != 0) {
6359ecd3762SMatthew Dillon 			if (*r == ',' && *o != '\0')
6369ecd3762SMatthew Dillon 				r++;
6379ecd3762SMatthew Dillon 			while ((*r++ = *o++) != '\0')
6389ecd3762SMatthew Dillon 			    ;
6399ecd3762SMatthew Dillon 			*--r = ',';
6409ecd3762SMatthew Dillon 		}
6419ecd3762SMatthew Dillon 	}
6429ecd3762SMatthew Dillon 	*r = '\0';
6439ecd3762SMatthew Dillon }
6449ecd3762SMatthew Dillon 
6459ecd3762SMatthew Dillon static void
usage(void)6469ecd3762SMatthew Dillon usage(void)
6479ecd3762SMatthew Dillon {
6489ecd3762SMatthew Dillon 
6499ecd3762SMatthew Dillon 	fprintf(stderr, "%s\n%s\n%s\n",
6509ecd3762SMatthew Dillon "usage: mount [-adfpruvw] [-F fstab] [-o options] [-t type]",
6519ecd3762SMatthew Dillon "       mount [-dfpruvw] {special | node}",
6529ecd3762SMatthew Dillon "       mount [-dfpruvw] [-o options] [-t type] special node");
6539ecd3762SMatthew Dillon 	exit(1);
6549ecd3762SMatthew Dillon }
6559ecd3762SMatthew Dillon 
6569ecd3762SMatthew Dillon /*
6579ecd3762SMatthew Dillon  * Prints the default values for dump frequency and pass number of fsck.
6589ecd3762SMatthew Dillon  * This happens when mount(8) is called with -p and there is no fstab file
6599ecd3762SMatthew Dillon  * or there is but the values aren't specified.
6609ecd3762SMatthew Dillon  */
6619ecd3762SMatthew Dillon static void
printdefvals(const struct statfs * ent)6629ecd3762SMatthew Dillon printdefvals(const struct statfs *ent)
6639ecd3762SMatthew Dillon {
6649ecd3762SMatthew Dillon         if (strcmp(ent->f_fstypename, "ufs") == 0) {
6659ecd3762SMatthew Dillon                 if (strcmp(ent->f_mntonname, "/") == 0)
6669ecd3762SMatthew Dillon                         printf("\t1 1\n");
6679ecd3762SMatthew Dillon                 else
6689ecd3762SMatthew Dillon                         printf("\t2 2\n");
6699ecd3762SMatthew Dillon         } else {
6709ecd3762SMatthew Dillon                 printf("\t0 0\n");
6719ecd3762SMatthew Dillon 	}
6729ecd3762SMatthew Dillon }
6739ecd3762SMatthew Dillon 
6749ecd3762SMatthew Dillon static void
putfsent(const struct statfs * ent)6759ecd3762SMatthew Dillon putfsent(const struct statfs *ent)
6769ecd3762SMatthew Dillon {
6779ecd3762SMatthew Dillon 	struct stat sb;
6789ecd3762SMatthew Dillon 	struct fstab *fst;
6799ecd3762SMatthew Dillon 	char *opts;
6809ecd3762SMatthew Dillon 
6819ecd3762SMatthew Dillon 	opts = flags2opts(ent->f_flags);
6829ecd3762SMatthew Dillon 	printf("%s\t%s\t%s %s", ent->f_mntfromname, ent->f_mntonname,
6839ecd3762SMatthew Dillon 	    ent->f_fstypename, opts);
6849ecd3762SMatthew Dillon 	free(opts);
6859ecd3762SMatthew Dillon 
6869ecd3762SMatthew Dillon 	/*
6879ecd3762SMatthew Dillon 	 * If fstab file is missing don't call getfsspec() or getfsfile()
6889ecd3762SMatthew Dillon 	 * at all, because the same warning will be printed twice for every
6899ecd3762SMatthew Dillon 	 * mounted filesystem.
6909ecd3762SMatthew Dillon 	 */
6919ecd3762SMatthew Dillon 	if (stat(_PATH_FSTAB, &sb) != -1) {
6929ecd3762SMatthew Dillon 		if ((fst = getfsspec(ent->f_mntfromname)))
6939ecd3762SMatthew Dillon 			printf("\t%u %u\n", fst->fs_freq, fst->fs_passno);
6949ecd3762SMatthew Dillon 		else if ((fst = getfsfile(ent->f_mntonname)))
6959ecd3762SMatthew Dillon 			printf("\t%u %u\n", fst->fs_freq, fst->fs_passno);
6969ecd3762SMatthew Dillon 		else
6979ecd3762SMatthew Dillon 			printdefvals(ent);
6989ecd3762SMatthew Dillon 	} else {
6999ecd3762SMatthew Dillon 		printdefvals(ent);
7009ecd3762SMatthew Dillon 	}
7019ecd3762SMatthew Dillon }
7029ecd3762SMatthew Dillon 
7039ecd3762SMatthew Dillon 
7049ecd3762SMatthew Dillon static char *
flags2opts(int flags)7059ecd3762SMatthew Dillon flags2opts(int flags)
7069ecd3762SMatthew Dillon {
7079ecd3762SMatthew Dillon 	char *res;
7089ecd3762SMatthew Dillon 
7099ecd3762SMatthew Dillon 	res = NULL;
7109ecd3762SMatthew Dillon 
7119ecd3762SMatthew Dillon 	res = catopt(res, (flags & MNT_RDONLY) ? "ro" : "rw");
7129ecd3762SMatthew Dillon 
7139ecd3762SMatthew Dillon 	if (flags & MNT_SYNCHRONOUS)	res = catopt(res, "sync");
7149ecd3762SMatthew Dillon 	if (flags & MNT_NOEXEC)		res = catopt(res, "noexec");
7159ecd3762SMatthew Dillon 	if (flags & MNT_NOSUID)		res = catopt(res, "nosuid");
7169ecd3762SMatthew Dillon 	if (flags & MNT_NODEV)		res = catopt(res, "nodev");
7179ecd3762SMatthew Dillon 	if (flags & MNT_ASYNC)		res = catopt(res, "async");
7189ecd3762SMatthew Dillon 	if (flags & MNT_NOATIME)	res = catopt(res, "noatime");
7199ecd3762SMatthew Dillon 	if (flags & MNT_NOCLUSTERR)	res = catopt(res, "noclusterr");
7209ecd3762SMatthew Dillon 	if (flags & MNT_NOCLUSTERW)	res = catopt(res, "noclusterw");
7219ecd3762SMatthew Dillon 	if (flags & MNT_NOSYMFOLLOW)	res = catopt(res, "nosymfollow");
7229ecd3762SMatthew Dillon 	if (flags & MNT_SUIDDIR)	res = catopt(res, "suiddir");
7239ecd3762SMatthew Dillon 	if (flags & MNT_IGNORE)		res = catopt(res, "ignore");
7249ecd3762SMatthew Dillon 
7259ecd3762SMatthew Dillon 	return res;
7269ecd3762SMatthew Dillon }
7279ecd3762SMatthew Dillon 
7289ecd3762SMatthew Dillon static char*
xstrdup(const char * str)7299ecd3762SMatthew Dillon xstrdup(const char *str)
7309ecd3762SMatthew Dillon {
7319ecd3762SMatthew Dillon 	char* ret = strdup(str);
7329ecd3762SMatthew Dillon 	if(ret == NULL) {
7339ecd3762SMatthew Dillon 		errx(1, "strdup failed (could not allocate memory)");
7349ecd3762SMatthew Dillon 	}
7359ecd3762SMatthew Dillon 	return ret;
7369ecd3762SMatthew Dillon }
737