mount.c revision 17243
11558Srgrimes/* 21558Srgrimes * Copyright (c) 1980, 1989, 1993, 1994 31558Srgrimes * The Regents of the University of California. All rights reserved. 41558Srgrimes * 51558Srgrimes * Redistribution and use in source and binary forms, with or without 61558Srgrimes * modification, are permitted provided that the following conditions 71558Srgrimes * are met: 81558Srgrimes * 1. Redistributions of source code must retain the above copyright 91558Srgrimes * notice, this list of conditions and the following disclaimer. 101558Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 111558Srgrimes * notice, this list of conditions and the following disclaimer in the 121558Srgrimes * documentation and/or other materials provided with the distribution. 131558Srgrimes * 3. All advertising materials mentioning features or use of this software 141558Srgrimes * must display the following acknowledgement: 151558Srgrimes * This product includes software developed by the University of 161558Srgrimes * California, Berkeley and its contributors. 171558Srgrimes * 4. Neither the name of the University nor the names of its contributors 181558Srgrimes * may be used to endorse or promote products derived from this software 191558Srgrimes * without specific prior written permission. 201558Srgrimes * 211558Srgrimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 221558Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 231558Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 241558Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 251558Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 261558Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 271558Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 281558Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 291558Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 301558Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 311558Srgrimes * SUCH DAMAGE. 321558Srgrimes */ 331558Srgrimes 341558Srgrimes#ifndef lint 351558Srgrimesstatic char copyright[] = 361558Srgrimes"@(#) Copyright (c) 1980, 1989, 1993, 1994\n\ 371558Srgrimes The Regents of the University of California. All rights reserved.\n"; 381558Srgrimes#endif /* not lint */ 391558Srgrimes 401558Srgrimes#ifndef lint 411558Srgrimesstatic char sccsid[] = "@(#)mount.c 8.19 (Berkeley) 4/19/94"; 421558Srgrimes#endif /* not lint */ 431558Srgrimes 441558Srgrimes#include <sys/param.h> 451558Srgrimes#include <sys/mount.h> 461558Srgrimes#include <sys/wait.h> 476441Sdg#include <sys/types.h> 486441Sdg#include <sys/stat.h> 491558Srgrimes 501558Srgrimes#include <err.h> 511558Srgrimes#include <errno.h> 521558Srgrimes#include <fstab.h> 531558Srgrimes#include <signal.h> 541558Srgrimes#include <stdio.h> 551558Srgrimes#include <stdlib.h> 561558Srgrimes#include <string.h> 571558Srgrimes#include <unistd.h> 581558Srgrimes 591558Srgrimes#include "pathnames.h" 601558Srgrimes 611558Srgrimesint debug, verbose, skipvfs; 6217243Sjkhint fstab_style = 0; 631558Srgrimes 6417243Sjkhstatic char *mnttype[] = INITMOUNTNAMES; 6517243Sjkh 661558Srgrimesint badvfsname __P((const char *, const char **)); 671558Srgrimesint badvfstype __P((int, const char **)); 681558Srgrimeschar *catopt __P((char *, const char *)); 691558Srgrimesstruct statfs 701558Srgrimes *getmntpt __P((const char *)); 711558Srgrimesconst char 721558Srgrimes **makevfslist __P((char *)); 731558Srgrimesvoid mangle __P((char *, int *, const char **)); 741558Srgrimesint mountfs __P((const char *, const char *, const char *, 751558Srgrimes int, const char *, const char *)); 761558Srgrimesvoid prmount __P((const char *, const char *, int)); 771558Srgrimesvoid usage __P((void)); 7817243Sjkhvoid putfsent __P((const struct statfs *)); 791558Srgrimes 801558Srgrimes/* From mount_ufs.c. */ 811558Srgrimesint mount_ufs __P((int, char * const *)); 821558Srgrimes 831558Srgrimes/* Map from mount otions to printable formats. */ 841558Srgrimesstatic struct opt { 851558Srgrimes int o_opt; 861558Srgrimes const char *o_name; 871558Srgrimes} optnames[] = { 881558Srgrimes { MNT_ASYNC, "asynchronous" }, 891558Srgrimes { MNT_EXPORTED, "NFS exported" }, 901558Srgrimes { MNT_LOCAL, "local" }, 911558Srgrimes { MNT_NODEV, "nodev" }, 921558Srgrimes { MNT_NOEXEC, "noexec" }, 931558Srgrimes { MNT_NOSUID, "nosuid" }, 941558Srgrimes { MNT_QUOTA, "with quotas" }, 951558Srgrimes { MNT_RDONLY, "read-only" }, 961558Srgrimes { MNT_SYNCHRONOUS, "synchronous" }, 971558Srgrimes { MNT_UNION, "union" }, 981558Srgrimes { MNT_USER, "user mount" }, 991558Srgrimes { NULL } 1001558Srgrimes}; 1011558Srgrimes 1021558Srgrimesint 1031558Srgrimesmain(argc, argv) 1041558Srgrimes int argc; 1051558Srgrimes char * const argv[]; 1061558Srgrimes{ 1071558Srgrimes const char *mntonname, **vfslist, *vfstype; 1081558Srgrimes struct fstab *fs; 1091558Srgrimes struct statfs *mntbuf; 1101558Srgrimes FILE *mountdfp; 1111558Srgrimes pid_t pid; 1121558Srgrimes int all, ch, i, init_flags, mntsize, rval; 1131558Srgrimes char *options; 1141558Srgrimes 1151558Srgrimes all = init_flags = 0; 1161558Srgrimes options = NULL; 1171558Srgrimes vfslist = NULL; 1181558Srgrimes vfstype = "ufs"; 11917243Sjkh while ((ch = getopt(argc, argv, "padfo:rwt:uv")) != EOF) 1201558Srgrimes switch (ch) { 12117243Sjkh case 'p': 12217243Sjkh fstab_style = 1; 12317243Sjkh verbose = 1; 12417243Sjkh break; 1251558Srgrimes case 'a': 1261558Srgrimes all = 1; 1271558Srgrimes break; 1281558Srgrimes case 'd': 1291558Srgrimes debug = 1; 1301558Srgrimes break; 1311558Srgrimes case 'f': 1321558Srgrimes init_flags |= MNT_FORCE; 1331558Srgrimes break; 1341558Srgrimes case 'o': 1351558Srgrimes if (*optarg) 1361558Srgrimes options = catopt(options, optarg); 1371558Srgrimes break; 1381558Srgrimes case 'r': 1391558Srgrimes init_flags |= MNT_RDONLY; 1401558Srgrimes break; 1411558Srgrimes case 't': 1421558Srgrimes if (vfslist != NULL) 1431558Srgrimes errx(1, "only one -t option may be specified."); 1441558Srgrimes vfslist = makevfslist(optarg); 1451558Srgrimes vfstype = optarg; 1461558Srgrimes break; 1471558Srgrimes case 'u': 1481558Srgrimes init_flags |= MNT_UPDATE; 1491558Srgrimes break; 1501558Srgrimes case 'v': 1511558Srgrimes verbose = 1; 1521558Srgrimes break; 1531558Srgrimes case 'w': 1541558Srgrimes init_flags &= ~MNT_RDONLY; 1551558Srgrimes break; 1561558Srgrimes case '?': 1571558Srgrimes default: 1581558Srgrimes usage(); 1591558Srgrimes /* NOTREACHED */ 1601558Srgrimes } 1611558Srgrimes argc -= optind; 1621558Srgrimes argv += optind; 1631558Srgrimes 1641558Srgrimes#define BADTYPE(type) \ 1651558Srgrimes (strcmp(type, FSTAB_RO) && \ 1661558Srgrimes strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) 1671558Srgrimes 1681558Srgrimes rval = 0; 1691558Srgrimes switch (argc) { 1701558Srgrimes case 0: 1711558Srgrimes if (all) 1721558Srgrimes while ((fs = getfsent()) != NULL) { 1731558Srgrimes if (BADTYPE(fs->fs_type)) 1741558Srgrimes continue; 1751558Srgrimes if (badvfsname(fs->fs_vfstype, vfslist)) 1761558Srgrimes continue; 17710288Sdg if (strstr(fs->fs_mntops, "noauto")) 17810288Sdg continue; 1791558Srgrimes if (mountfs(fs->fs_vfstype, fs->fs_spec, 18010288Sdg fs->fs_file, init_flags, options, 18110288Sdg fs->fs_mntops)) 18210199Sjkh rval = 1; 1831558Srgrimes } 18417243Sjkh else if (fstab_style) { 18517243Sjkh if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) 18617243Sjkh err(1, "getmntinfo"); 18717243Sjkh for (i = 0; i < mntsize; i++) { 18817243Sjkh if (badvfstype(mntbuf[i].f_type, vfslist)) 18917243Sjkh continue; 19017243Sjkh putfsent (&mntbuf[i]); 19117243Sjkh } 19217243Sjkh } 1931558Srgrimes else { 1941558Srgrimes if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) 1951558Srgrimes err(1, "getmntinfo"); 1961558Srgrimes for (i = 0; i < mntsize; i++) { 1971558Srgrimes if (badvfstype(mntbuf[i].f_type, vfslist)) 1981558Srgrimes continue; 1991558Srgrimes prmount(mntbuf[i].f_mntfromname, 2001558Srgrimes mntbuf[i].f_mntonname, mntbuf[i].f_flags); 2011558Srgrimes } 2021558Srgrimes } 2031558Srgrimes exit(rval); 2041558Srgrimes case 1: 2051558Srgrimes if (vfslist != NULL) 2061558Srgrimes usage(); 2071558Srgrimes 2081558Srgrimes if (init_flags & MNT_UPDATE) { 2091558Srgrimes if ((mntbuf = getmntpt(*argv)) == NULL) 2101558Srgrimes errx(1, 2111558Srgrimes "unknown special file or file system %s.", 2121558Srgrimes *argv); 2131558Srgrimes if ((fs = getfsfile(mntbuf->f_mntonname)) == NULL) 2141558Srgrimes errx(1, "can't find fstab entry for %s.", 2151558Srgrimes *argv); 2161558Srgrimes /* If it's an update, ignore the fstab file options. */ 2171558Srgrimes fs->fs_mntops = NULL; 2181558Srgrimes mntonname = mntbuf->f_mntonname; 2191558Srgrimes } else { 2201558Srgrimes if ((fs = getfsfile(*argv)) == NULL && 2211558Srgrimes (fs = getfsspec(*argv)) == NULL) 2221558Srgrimes errx(1, 2231558Srgrimes "%s: unknown special file or file system.", 2241558Srgrimes *argv); 2251558Srgrimes if (BADTYPE(fs->fs_type)) 2261558Srgrimes errx(1, "%s has unknown file system type.", 2271558Srgrimes *argv); 2281558Srgrimes mntonname = fs->fs_file; 2291558Srgrimes } 2301558Srgrimes rval = mountfs(fs->fs_vfstype, fs->fs_spec, 2311558Srgrimes mntonname, init_flags, options, fs->fs_mntops); 2321558Srgrimes break; 2331558Srgrimes case 2: 2341558Srgrimes /* 2351558Srgrimes * If -t flag has not been specified, and spec contains either 2361558Srgrimes * a ':' or a '@' then assume that an NFS filesystem is being 2371558Srgrimes * specified ala Sun. 2381558Srgrimes */ 2391558Srgrimes if (vfslist == NULL && strpbrk(argv[0], ":@") != NULL) 2401558Srgrimes vfstype = "nfs"; 2411558Srgrimes rval = mountfs(vfstype, 2421558Srgrimes argv[0], argv[1], init_flags, options, NULL); 2431558Srgrimes break; 2441558Srgrimes default: 2451558Srgrimes usage(); 2461558Srgrimes /* NOTREACHED */ 2471558Srgrimes } 2481558Srgrimes 2491558Srgrimes /* 2501558Srgrimes * If the mount was successfully, and done by root, tell mountd the 2511558Srgrimes * good news. Pid checks are probably unnecessary, but don't hurt. 2521558Srgrimes */ 2531558Srgrimes if (rval == 0 && getuid() == 0 && 2541558Srgrimes (mountdfp = fopen(_PATH_MOUNTDPID, "r")) != NULL) { 2551558Srgrimes if (fscanf(mountdfp, "%ld", &pid) == 1 && 2561558Srgrimes pid > 0 && kill(pid, SIGHUP) == -1 && errno != ESRCH) 2571558Srgrimes err(1, "signal mountd"); 2581558Srgrimes (void)fclose(mountdfp); 2591558Srgrimes } 2601558Srgrimes 2611558Srgrimes exit(rval); 2621558Srgrimes} 2631558Srgrimes 2641558Srgrimesint 2651558Srgrimesmountfs(vfstype, spec, name, flags, options, mntopts) 2661558Srgrimes const char *vfstype, *spec, *name, *options, *mntopts; 2671558Srgrimes int flags; 2681558Srgrimes{ 2696441Sdg struct stat sb; 2706441Sdg 2711558Srgrimes /* List of directories containing mount_xxx subcommands. */ 2721558Srgrimes static const char *edirs[] = { 2731558Srgrimes _PATH_SBIN, 2741558Srgrimes _PATH_USRSBIN, 2751558Srgrimes NULL 2761558Srgrimes }; 2771558Srgrimes const char *argv[100], **edir; 2781558Srgrimes struct statfs sf; 2791558Srgrimes pid_t pid; 2801558Srgrimes int argc, i, status; 2811558Srgrimes char *optbuf, execname[MAXPATHLEN + 1], mntpath[MAXPATHLEN]; 2821558Srgrimes 2836491Sbde if (realpath(name, mntpath) != NULL && stat(mntpath, &sb) == 0) { 2846444Sdg if (!S_ISDIR(sb.st_mode)) { 2856441Sdg warnx("%s: Not a directory", mntpath); 2866441Sdg return (1); 2876441Sdg } 2886441Sdg } else { 2891558Srgrimes warn("%s", mntpath); 2901558Srgrimes return (1); 2911558Srgrimes } 2926441Sdg 2931818Sdg if (mntopts == NULL) 2941818Sdg mntopts = ""; 2951558Srgrimes 2961558Srgrimes name = mntpath; 2971558Srgrimes 2981558Srgrimes if (options == NULL) { 2991818Sdg if (*mntopts == '\0') 3001558Srgrimes options = "rw"; 3011558Srgrimes else 3021558Srgrimes options = mntopts; 3031558Srgrimes mntopts = ""; 3041558Srgrimes } 3051558Srgrimes optbuf = catopt(strdup(mntopts), options); 3061558Srgrimes 3071558Srgrimes if (strcmp(name, "/") == 0) 3081558Srgrimes flags |= MNT_UPDATE; 3091558Srgrimes if (flags & MNT_FORCE) 3101558Srgrimes optbuf = catopt(optbuf, "force"); 3111558Srgrimes if (flags & MNT_RDONLY) 3121558Srgrimes optbuf = catopt(optbuf, "ro"); 3131558Srgrimes /* 3141558Srgrimes * XXX 3151558Srgrimes * The mount_mfs (newfs) command uses -o to select the 3161558Srgrimes * optimisation mode. We don't pass the default "-o rw" 3171558Srgrimes * for that reason. 3181558Srgrimes */ 3191558Srgrimes if (flags & MNT_UPDATE) 3201558Srgrimes optbuf = catopt(optbuf, "update"); 3211558Srgrimes 3221558Srgrimes argc = 0; 3231558Srgrimes argv[argc++] = vfstype; 3241558Srgrimes mangle(optbuf, &argc, argv); 3251558Srgrimes argv[argc++] = spec; 3261558Srgrimes argv[argc++] = name; 3271558Srgrimes argv[argc] = NULL; 3281558Srgrimes 3291558Srgrimes if (debug) { 3301558Srgrimes (void)printf("exec: mount_%s", vfstype); 3311558Srgrimes for (i = 1; i < argc; i++) 3321558Srgrimes (void)printf(" %s", argv[i]); 3331558Srgrimes (void)printf("\n"); 3341558Srgrimes return (0); 3351558Srgrimes } 3361558Srgrimes 3371558Srgrimes switch (pid = vfork()) { 3381558Srgrimes case -1: /* Error. */ 3391558Srgrimes warn("vfork"); 3401558Srgrimes free(optbuf); 3411558Srgrimes return (1); 3421558Srgrimes case 0: /* Child. */ 3431558Srgrimes if (strcmp(vfstype, "ufs") == 0) 3441558Srgrimes exit(mount_ufs(argc, (char * const *) argv)); 3451558Srgrimes 3461558Srgrimes /* Go find an executable. */ 34714626Sasami for (edir = edirs; *edir; edir++) { 3481558Srgrimes (void)snprintf(execname, 3491558Srgrimes sizeof(execname), "%s/mount_%s", *edir, vfstype); 3501558Srgrimes execv(execname, (char * const *)argv); 35114626Sasami } 35214626Sasami if (errno == ENOENT) { 35314626Sasami int len = 0; 35414626Sasami char *cp; 35514626Sasami for (edir = edirs; *edir; edir++) 35614626Sasami len += strlen(*edir) + 2; /* ", " */ 35714626Sasami if ((cp = malloc(len)) == NULL) { 35814626Sasami warn(NULL); 35914626Sasami exit(1); 36014626Sasami } 36114626Sasami cp[0] = '\0'; 36214626Sasami for (edir = edirs; *edir; edir++) { 36314626Sasami strcat(cp, *edir); 36414626Sasami if (edir[1] != NULL) 36514626Sasami strcat(cp, ", "); 36614626Sasami } 36714626Sasami warn("exec mount_%s not found in %s", vfstype, cp); 36814626Sasami } 3691558Srgrimes exit(1); 3701558Srgrimes /* NOTREACHED */ 3711558Srgrimes default: /* Parent. */ 3721558Srgrimes free(optbuf); 3731558Srgrimes 3741558Srgrimes if (waitpid(pid, &status, 0) < 0) { 3751558Srgrimes warn("waitpid"); 3761558Srgrimes return (1); 3771558Srgrimes } 3781558Srgrimes 3791558Srgrimes if (WIFEXITED(status)) { 3801558Srgrimes if (WEXITSTATUS(status) != 0) 3811558Srgrimes return (WEXITSTATUS(status)); 3821558Srgrimes } else if (WIFSIGNALED(status)) { 3831558Srgrimes warnx("%s: %s", name, sys_siglist[WTERMSIG(status)]); 3841558Srgrimes return (1); 3851558Srgrimes } 3861558Srgrimes 3871558Srgrimes if (verbose) { 3881558Srgrimes if (statfs(name, &sf) < 0) { 3891558Srgrimes warn("%s", name); 3901558Srgrimes return (1); 3911558Srgrimes } 39217243Sjkh 39317243Sjkh if (fstab_style) 39417243Sjkh putfsent (&sf); 39517243Sjkh else 39617243Sjkh prmount (sf.f_mntfromname, 39717243Sjkh sf.f_mntonname, sf.f_flags); 3981558Srgrimes } 3991558Srgrimes break; 4001558Srgrimes } 4011558Srgrimes 4021558Srgrimes return (0); 4031558Srgrimes} 4041558Srgrimes 4051558Srgrimesvoid 4061558Srgrimesprmount(spec, name, flags) 4071558Srgrimes const char *spec, *name; 4081558Srgrimes int flags; 4091558Srgrimes{ 4101558Srgrimes struct opt *o; 4111558Srgrimes int f; 4121558Srgrimes 4131558Srgrimes (void)printf("%s on %s", spec, name); 4141558Srgrimes 4151558Srgrimes flags &= MNT_VISFLAGMASK; 4161558Srgrimes for (f = 0, o = optnames; flags && o->o_opt; o++) 4171558Srgrimes if (flags & o->o_opt) { 4181558Srgrimes (void)printf("%s%s", !f++ ? " (" : ", ", o->o_name); 4191558Srgrimes flags &= ~o->o_opt; 4201558Srgrimes } 4211558Srgrimes (void)printf(f ? ")\n" : "\n"); 4221558Srgrimes} 4231558Srgrimes 4241558Srgrimesstruct statfs * 4251558Srgrimesgetmntpt(name) 4261558Srgrimes const char *name; 4271558Srgrimes{ 4281558Srgrimes struct statfs *mntbuf; 4291558Srgrimes int i, mntsize; 4301558Srgrimes 4311558Srgrimes mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 4321558Srgrimes for (i = 0; i < mntsize; i++) 4331558Srgrimes if (strcmp(mntbuf[i].f_mntfromname, name) == 0 || 4341558Srgrimes strcmp(mntbuf[i].f_mntonname, name) == 0) 4351558Srgrimes return (&mntbuf[i]); 4361558Srgrimes return (NULL); 4371558Srgrimes} 4381558Srgrimes 4391558Srgrimesint 4401558Srgrimesbadvfsname(vfsname, vfslist) 4411558Srgrimes const char *vfsname; 4421558Srgrimes const char **vfslist; 4431558Srgrimes{ 4441558Srgrimes 4451558Srgrimes if (vfslist == NULL) 4461558Srgrimes return (0); 4471558Srgrimes while (*vfslist != NULL) { 4481558Srgrimes if (strcmp(vfsname, *vfslist) == 0) 4491558Srgrimes return (skipvfs); 4501558Srgrimes ++vfslist; 4511558Srgrimes } 4521558Srgrimes return (!skipvfs); 4531558Srgrimes} 4541558Srgrimes 4551558Srgrimesint 4561558Srgrimesbadvfstype(vfstype, vfslist) 4571558Srgrimes int vfstype; 4581558Srgrimes const char **vfslist; 4591558Srgrimes{ 4602968Swollman struct vfsconf *vfc; 4612968Swollman vfc = getvfsbytype(vfstype); 4621558Srgrimes 4632968Swollman if ( ! vfc ) 4641558Srgrimes return (0); 4651558Srgrimes 4662968Swollman return (badvfsname(vfc->vfc_name, vfslist)); 4671558Srgrimes} 4681558Srgrimes 4691558Srgrimesconst char ** 4701558Srgrimesmakevfslist(fslist) 4711558Srgrimes char *fslist; 4721558Srgrimes{ 4731558Srgrimes const char **av; 4741558Srgrimes int i; 4751558Srgrimes char *nextcp; 4761558Srgrimes 4771558Srgrimes if (fslist == NULL) 4781558Srgrimes return (NULL); 4791558Srgrimes if (fslist[0] == 'n' && fslist[1] == 'o') { 4801558Srgrimes fslist += 2; 4811558Srgrimes skipvfs = 1; 4821558Srgrimes } 4831558Srgrimes for (i = 0, nextcp = fslist; *nextcp; nextcp++) 4841558Srgrimes if (*nextcp == ',') 4851558Srgrimes i++; 4861558Srgrimes if ((av = malloc((size_t)(i + 2) * sizeof(char *))) == NULL) { 4871558Srgrimes warn(NULL); 4881558Srgrimes return (NULL); 4891558Srgrimes } 4901558Srgrimes nextcp = fslist; 4911558Srgrimes i = 0; 4921558Srgrimes av[i++] = nextcp; 4931558Srgrimes while ((nextcp = strchr(nextcp, ',')) != NULL) { 4941558Srgrimes *nextcp++ = '\0'; 4951558Srgrimes av[i++] = nextcp; 4961558Srgrimes } 4971558Srgrimes av[i++] = NULL; 4981558Srgrimes return (av); 4991558Srgrimes} 5001558Srgrimes 5011558Srgrimeschar * 5021558Srgrimescatopt(s0, s1) 5031558Srgrimes char *s0; 5041558Srgrimes const char *s1; 5051558Srgrimes{ 5061558Srgrimes size_t i; 5071558Srgrimes char *cp; 5081558Srgrimes 5091558Srgrimes if (s0 && *s0) { 5101558Srgrimes i = strlen(s0) + strlen(s1) + 1 + 1; 5111558Srgrimes if ((cp = malloc(i)) == NULL) 5121558Srgrimes err(1, NULL); 5131558Srgrimes (void)snprintf(cp, i, "%s,%s", s0, s1); 5141558Srgrimes } else 5151558Srgrimes cp = strdup(s1); 5161558Srgrimes 5171558Srgrimes if (s0) 5181558Srgrimes free(s0); 5191558Srgrimes return (cp); 5201558Srgrimes} 5211558Srgrimes 5221558Srgrimesvoid 5231558Srgrimesmangle(options, argcp, argv) 5241558Srgrimes char *options; 5251558Srgrimes int *argcp; 5261558Srgrimes const char **argv; 5271558Srgrimes{ 5281558Srgrimes char *p, *s; 5291558Srgrimes int argc; 5301558Srgrimes 5311558Srgrimes argc = *argcp; 5321558Srgrimes for (s = options; (p = strsep(&s, ",")) != NULL;) 5331558Srgrimes if (*p != '\0') 5341558Srgrimes if (*p == '-') { 5351558Srgrimes argv[argc++] = p; 5361558Srgrimes p = strchr(p, '='); 5371558Srgrimes if (p) { 5381558Srgrimes *p = '\0'; 5391558Srgrimes argv[argc++] = p+1; 5401558Srgrimes } 5411558Srgrimes } else if (strcmp(p, "rw") != 0) { 5421558Srgrimes argv[argc++] = "-o"; 5431558Srgrimes argv[argc++] = p; 5441558Srgrimes } 5451558Srgrimes 5461558Srgrimes *argcp = argc; 5471558Srgrimes} 5481558Srgrimes 5491558Srgrimesvoid 5501558Srgrimesusage() 5511558Srgrimes{ 5521558Srgrimes 5531558Srgrimes (void)fprintf(stderr, 5541558Srgrimes "usage: mount %s %s\n mount %s\n mount %s\n", 55517243Sjkh "[-dfpruvw] [-o options] [-t ufs | external_type]", 5561558Srgrimes "special node", 55717243Sjkh "[-adfpruvw] [-t ufs | external_type]", 55817243Sjkh "[-dfpruvw] special | node"); 5591558Srgrimes exit(1); 5601558Srgrimes} 56117243Sjkh 56217243Sjkhvoid 56317243Sjkhputfsent (ent) 56417243Sjkh const struct statfs *ent; 56517243Sjkh{ 56617243Sjkh struct fstab *fst; 56717243Sjkh 56817243Sjkh printf ("%s\t%s\t%s %s", 56917243Sjkh ent->f_mntfromname, ent->f_mntonname, 57017243Sjkh mnttype[ent->f_type], 57117243Sjkh (ent->f_flags & MNT_RDONLY) ? "ro" : "rw"); 57217243Sjkh 57317243Sjkh if (ent->f_flags & MNT_SYNCHRONOUS) 57417243Sjkh printf (",sync"); 57517243Sjkh 57617243Sjkh if (ent->f_flags & MNT_NOEXEC) 57717243Sjkh printf (",noexec"); 57817243Sjkh 57917243Sjkh if (ent->f_flags & MNT_NOSUID) 58017243Sjkh printf (",nosuid"); 58117243Sjkh 58217243Sjkh if (ent->f_flags & MNT_NODEV) 58317243Sjkh printf (",nodev"); 58417243Sjkh 58517243Sjkh if (ent->f_flags & MNT_UNION) 58617243Sjkh printf (",union"); 58717243Sjkh 58817243Sjkh if (ent->f_flags & MNT_ASYNC) 58917243Sjkh printf (",async"); 59017243Sjkh 59117243Sjkh if (fst = getfsspec (ent->f_mntfromname)) 59217243Sjkh printf ("\t%u %u\n", fst->fs_freq, fst->fs_passno); 59317243Sjkh else if (fst = getfsfile (ent->f_mntonname)) 59417243Sjkh printf ("\t%u %u\n", fst->fs_freq, fst->fs_passno); 59517243Sjkh else if (ent->f_type == MOUNT_UFS) 59617243Sjkh printf ("\t1 1\n"); 59717243Sjkh else 59817243Sjkh printf ("\t0 0\n"); 59917243Sjkh} 600