mount.c revision 28671
128671Ssteve/*- 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 3528671Sstevestatic const 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 4128671Ssteve#if 0 4223678Speterstatic char sccsid[] = "@(#)mount.c 8.25 (Berkeley) 5/8/95"; 4328671Ssteve#else 4428671Sstevestatic const char rcsid[] = 4528671Ssteve "$Id$"; 4628671Ssteve#endif 471558Srgrimes#endif /* not lint */ 481558Srgrimes 491558Srgrimes#include <sys/param.h> 501558Srgrimes#include <sys/mount.h> 5123805Sbde#include <sys/stat.h> 521558Srgrimes#include <sys/wait.h> 531558Srgrimes 541558Srgrimes#include <err.h> 551558Srgrimes#include <errno.h> 561558Srgrimes#include <fstab.h> 5723678Speter#include <pwd.h> 581558Srgrimes#include <signal.h> 591558Srgrimes#include <stdio.h> 601558Srgrimes#include <stdlib.h> 611558Srgrimes#include <string.h> 621558Srgrimes#include <unistd.h> 631558Srgrimes 6428671Ssteve#include "extern.h" 651558Srgrimes#include "pathnames.h" 661558Srgrimes 6723805Sbdeint debug, fstab_style, verbose; 681558Srgrimes 691558Srgrimeschar *catopt __P((char *, const char *)); 701558Srgrimesstruct statfs 711558Srgrimes *getmntpt __P((const char *)); 7223678Speterint hasopt __P((const char *, const char *)); 7328671Ssteveint ismounted __P((struct fstab *, struct statfs *, int)); 7428671Ssteveint isremountable __P((const char *)); 751558Srgrimesvoid mangle __P((char *, int *, const char **)); 761558Srgrimesint mountfs __P((const char *, const char *, const char *, 771558Srgrimes int, const char *, const char *)); 7823678Spetervoid prmount __P((struct statfs *)); 7923805Sbdevoid putfsent __P((const struct statfs *)); 801558Srgrimesvoid usage __P((void)); 811558Srgrimes 821558Srgrimes/* Map from mount otions to printable formats. */ 831558Srgrimesstatic struct opt { 841558Srgrimes int o_opt; 851558Srgrimes const char *o_name; 861558Srgrimes} optnames[] = { 871558Srgrimes { MNT_ASYNC, "asynchronous" }, 881558Srgrimes { MNT_EXPORTED, "NFS exported" }, 891558Srgrimes { MNT_LOCAL, "local" }, 9018007Sdg { MNT_NOATIME, "noatime" }, 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 { NULL } 991558Srgrimes}; 1001558Srgrimes 10128671Ssteve/* 10228671Ssteve * List of VFS types that can be remounted without becoming mounted on top 10328671Ssteve * of each other. 10428671Ssteve * XXX Is this list correct? 10528671Ssteve */ 10628671Sstevestatic const char * 10728671Ssteveremountable_fs_names[] = { 10828671Ssteve "ufs", "ffs", "lfs", "ext2fs", 10928671Ssteve 0 11028671Ssteve}; 11128671Ssteve 1121558Srgrimesint 1131558Srgrimesmain(argc, argv) 1141558Srgrimes int argc; 1151558Srgrimes char * const argv[]; 1161558Srgrimes{ 11723678Speter const char *mntfromname, **vfslist, *vfstype; 1181558Srgrimes struct fstab *fs; 1191558Srgrimes struct statfs *mntbuf; 1201558Srgrimes FILE *mountdfp; 1211558Srgrimes pid_t pid; 1221558Srgrimes int all, ch, i, init_flags, mntsize, rval; 1231558Srgrimes char *options; 1241558Srgrimes 1251558Srgrimes all = init_flags = 0; 1261558Srgrimes options = NULL; 1271558Srgrimes vfslist = NULL; 1281558Srgrimes vfstype = "ufs"; 12923805Sbde while ((ch = getopt(argc, argv, "adfo:prwt:uv")) != -1) 1301558Srgrimes switch (ch) { 1311558Srgrimes case 'a': 1321558Srgrimes all = 1; 1331558Srgrimes break; 1341558Srgrimes case 'd': 1351558Srgrimes debug = 1; 1361558Srgrimes break; 1371558Srgrimes case 'f': 1381558Srgrimes init_flags |= MNT_FORCE; 1391558Srgrimes break; 1401558Srgrimes case 'o': 1411558Srgrimes if (*optarg) 1421558Srgrimes options = catopt(options, optarg); 1431558Srgrimes break; 14423805Sbde case 'p': 14523805Sbde fstab_style = 1; 14623805Sbde verbose = 1; 14723805Sbde break; 1481558Srgrimes case 'r': 1491558Srgrimes init_flags |= MNT_RDONLY; 1501558Srgrimes break; 1511558Srgrimes case 't': 1521558Srgrimes if (vfslist != NULL) 1531558Srgrimes errx(1, "only one -t option may be specified."); 1541558Srgrimes vfslist = makevfslist(optarg); 1551558Srgrimes vfstype = optarg; 1561558Srgrimes break; 1571558Srgrimes case 'u': 1581558Srgrimes init_flags |= MNT_UPDATE; 1591558Srgrimes break; 1601558Srgrimes case 'v': 1611558Srgrimes verbose = 1; 1621558Srgrimes break; 1631558Srgrimes case 'w': 1641558Srgrimes init_flags &= ~MNT_RDONLY; 1651558Srgrimes break; 1661558Srgrimes case '?': 1671558Srgrimes default: 1681558Srgrimes usage(); 1691558Srgrimes /* NOTREACHED */ 1701558Srgrimes } 1711558Srgrimes argc -= optind; 1721558Srgrimes argv += optind; 1731558Srgrimes 1741558Srgrimes#define BADTYPE(type) \ 1751558Srgrimes (strcmp(type, FSTAB_RO) && \ 1761558Srgrimes strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) 1771558Srgrimes 1781558Srgrimes rval = 0; 1791558Srgrimes switch (argc) { 1801558Srgrimes case 0: 18128671Ssteve if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) 18228671Ssteve err(1, "getmntinfo"); 18328671Ssteve if (all) { 1841558Srgrimes while ((fs = getfsent()) != NULL) { 1851558Srgrimes if (BADTYPE(fs->fs_type)) 1861558Srgrimes continue; 18723678Speter if (checkvfsname(fs->fs_vfstype, vfslist)) 1881558Srgrimes continue; 18923678Speter if (hasopt(fs->fs_mntops, "noauto")) 19010288Sdg continue; 19128671Ssteve if (ismounted(fs, mntbuf, mntsize)) 19228671Ssteve continue; 1931558Srgrimes if (mountfs(fs->fs_vfstype, fs->fs_spec, 19423805Sbde fs->fs_file, init_flags, options, 19523805Sbde fs->fs_mntops)) 19623805Sbde rval = 1; 1971558Srgrimes } 19828671Ssteve } else if (fstab_style) { 19917243Sjkh for (i = 0; i < mntsize; i++) { 20023678Speter if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) 20117243Sjkh continue; 20223805Sbde putfsent(&mntbuf[i]); 20317243Sjkh } 20423805Sbde } else { 2051558Srgrimes for (i = 0; i < mntsize; i++) { 20623805Sbde if (checkvfsname(mntbuf[i].f_fstypename, 20723805Sbde vfslist)) 2081558Srgrimes continue; 20923678Speter prmount(&mntbuf[i]); 2101558Srgrimes } 2111558Srgrimes } 2121558Srgrimes exit(rval); 2131558Srgrimes case 1: 2141558Srgrimes if (vfslist != NULL) 2151558Srgrimes usage(); 2161558Srgrimes 2171558Srgrimes if (init_flags & MNT_UPDATE) { 2181558Srgrimes if ((mntbuf = getmntpt(*argv)) == NULL) 2191558Srgrimes errx(1, 2201558Srgrimes "unknown special file or file system %s.", 2211558Srgrimes *argv); 22223678Speter if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) 22323678Speter mntfromname = fs->fs_spec; 22423678Speter else 22523678Speter mntfromname = mntbuf->f_mntfromname; 22623678Speter rval = mountfs(mntbuf->f_fstypename, mntfromname, 22723678Speter mntbuf->f_mntonname, init_flags, options, 0); 22823678Speter break; 2291558Srgrimes } 23023678Speter if ((fs = getfsfile(*argv)) == NULL && 23123678Speter (fs = getfsspec(*argv)) == NULL) 23223678Speter errx(1, "%s: unknown special file or file system.", 23323678Speter *argv); 23423678Speter if (BADTYPE(fs->fs_type)) 23523678Speter errx(1, "%s has unknown file system type.", 23623678Speter *argv); 23723678Speter rval = mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, 23823678Speter init_flags, options, fs->fs_mntops); 2391558Srgrimes break; 2401558Srgrimes case 2: 2411558Srgrimes /* 2421558Srgrimes * If -t flag has not been specified, and spec contains either 2431558Srgrimes * a ':' or a '@' then assume that an NFS filesystem is being 2441558Srgrimes * specified ala Sun. 2451558Srgrimes */ 2461558Srgrimes if (vfslist == NULL && strpbrk(argv[0], ":@") != NULL) 2471558Srgrimes vfstype = "nfs"; 2481558Srgrimes rval = mountfs(vfstype, 2491558Srgrimes argv[0], argv[1], init_flags, options, NULL); 2501558Srgrimes break; 2511558Srgrimes default: 2521558Srgrimes usage(); 2531558Srgrimes /* NOTREACHED */ 2541558Srgrimes } 2551558Srgrimes 2561558Srgrimes /* 2571558Srgrimes * If the mount was successfully, and done by root, tell mountd the 2581558Srgrimes * good news. Pid checks are probably unnecessary, but don't hurt. 2591558Srgrimes */ 2601558Srgrimes if (rval == 0 && getuid() == 0 && 2611558Srgrimes (mountdfp = fopen(_PATH_MOUNTDPID, "r")) != NULL) { 26228671Ssteve if (fscanf(mountdfp, "%d", &pid) == 1 && 2631558Srgrimes pid > 0 && kill(pid, SIGHUP) == -1 && errno != ESRCH) 2641558Srgrimes err(1, "signal mountd"); 2651558Srgrimes (void)fclose(mountdfp); 2661558Srgrimes } 2671558Srgrimes 2681558Srgrimes exit(rval); 2691558Srgrimes} 2701558Srgrimes 2711558Srgrimesint 27228671Ssteveismounted(fs, mntbuf, mntsize) 27328671Ssteve struct fstab *fs; 27428671Ssteve struct statfs *mntbuf; 27528671Ssteve int mntsize; 27628671Ssteve{ 27728671Ssteve int i; 27828671Ssteve 27928671Ssteve if (fs->fs_file[0] == '/' && fs->fs_file[1] == '\0') 28028671Ssteve /* the root file system can always be remounted */ 28128671Ssteve return (0); 28228671Ssteve 28328671Ssteve for (i = mntsize - 1; i >= 0; --i) 28428671Ssteve if (strcmp(fs->fs_file, mntbuf[i].f_mntonname) == 0 && 28528671Ssteve (!isremountable(fs->fs_vfstype) || 28628671Ssteve strcmp(fs->fs_spec, mntbuf[i].f_mntfromname) == 0)) 28728671Ssteve return (1); 28828671Ssteve return (0); 28928671Ssteve} 29028671Ssteve 29128671Ssteveint 29228671Ssteveisremountable(vfsname) 29328671Ssteve const char *vfsname; 29428671Ssteve{ 29528671Ssteve const char **cp; 29628671Ssteve 29728671Ssteve for (cp = remountable_fs_names; *cp; cp++) 29828671Ssteve if (strcmp(*cp, vfsname) == 0) 29928671Ssteve return (1); 30028671Ssteve return (0); 30128671Ssteve} 30228671Ssteve 30328671Ssteveint 30423678Speterhasopt(mntopts, option) 30523678Speter const char *mntopts, *option; 30623678Speter{ 30723678Speter int negative, found; 30823678Speter char *opt, *optbuf; 30923678Speter 31023678Speter if (option[0] == 'n' && option[1] == 'o') { 31123678Speter negative = 1; 31223678Speter option += 2; 31323678Speter } else 31423678Speter negative = 0; 31523678Speter optbuf = strdup(mntopts); 31623678Speter found = 0; 31723678Speter for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) { 31823678Speter if (opt[0] == 'n' && opt[1] == 'o') { 31923678Speter if (!strcasecmp(opt + 2, option)) 32023678Speter found = negative; 32123678Speter } else if (!strcasecmp(opt, option)) 32223678Speter found = !negative; 32323678Speter } 32423678Speter free(optbuf); 32523678Speter return (found); 32623678Speter} 32723678Speter 32823678Speterint 3291558Srgrimesmountfs(vfstype, spec, name, flags, options, mntopts) 3301558Srgrimes const char *vfstype, *spec, *name, *options, *mntopts; 3311558Srgrimes int flags; 3321558Srgrimes{ 3331558Srgrimes /* List of directories containing mount_xxx subcommands. */ 3341558Srgrimes static const char *edirs[] = { 3351558Srgrimes _PATH_SBIN, 3361558Srgrimes _PATH_USRSBIN, 3371558Srgrimes NULL 3381558Srgrimes }; 3391558Srgrimes const char *argv[100], **edir; 34023805Sbde struct stat sb; 3411558Srgrimes struct statfs sf; 3421558Srgrimes pid_t pid; 3431558Srgrimes int argc, i, status; 3441558Srgrimes char *optbuf, execname[MAXPATHLEN + 1], mntpath[MAXPATHLEN]; 3451558Srgrimes 34628671Ssteve#if __GNUC__ 34728671Ssteve (void)&optbuf; 34828671Ssteve (void)&name; 34928671Ssteve#endif 35028671Ssteve 3516491Sbde if (realpath(name, mntpath) != NULL && stat(mntpath, &sb) == 0) { 3526444Sdg if (!S_ISDIR(sb.st_mode)) { 3536441Sdg warnx("%s: Not a directory", mntpath); 3546441Sdg return (1); 3556441Sdg } 3566441Sdg } else { 3571558Srgrimes warn("%s", mntpath); 3581558Srgrimes return (1); 3591558Srgrimes } 3606441Sdg 3611558Srgrimes name = mntpath; 3621558Srgrimes 36323678Speter if (mntopts == NULL) 36423678Speter mntopts = ""; 3651558Srgrimes if (options == NULL) { 36623678Speter if (*mntopts == '\0') { 3671558Srgrimes options = "rw"; 36823678Speter } else { 3691558Srgrimes options = mntopts; 37023678Speter mntopts = ""; 37123678Speter } 3721558Srgrimes } 3731558Srgrimes optbuf = catopt(strdup(mntopts), options); 3741558Srgrimes 3751558Srgrimes if (strcmp(name, "/") == 0) 3761558Srgrimes flags |= MNT_UPDATE; 3771558Srgrimes if (flags & MNT_FORCE) 3781558Srgrimes optbuf = catopt(optbuf, "force"); 3791558Srgrimes if (flags & MNT_RDONLY) 3801558Srgrimes optbuf = catopt(optbuf, "ro"); 3811558Srgrimes /* 3821558Srgrimes * XXX 3831558Srgrimes * The mount_mfs (newfs) command uses -o to select the 3841558Srgrimes * optimisation mode. We don't pass the default "-o rw" 3851558Srgrimes * for that reason. 3861558Srgrimes */ 3871558Srgrimes if (flags & MNT_UPDATE) 3881558Srgrimes optbuf = catopt(optbuf, "update"); 3891558Srgrimes 3901558Srgrimes argc = 0; 3911558Srgrimes argv[argc++] = vfstype; 3921558Srgrimes mangle(optbuf, &argc, argv); 3931558Srgrimes argv[argc++] = spec; 3941558Srgrimes argv[argc++] = name; 3951558Srgrimes argv[argc] = NULL; 3961558Srgrimes 3971558Srgrimes if (debug) { 3981558Srgrimes (void)printf("exec: mount_%s", vfstype); 3991558Srgrimes for (i = 1; i < argc; i++) 4001558Srgrimes (void)printf(" %s", argv[i]); 4011558Srgrimes (void)printf("\n"); 4021558Srgrimes return (0); 4031558Srgrimes } 4041558Srgrimes 40525120Sache switch (pid = fork()) { 4061558Srgrimes case -1: /* Error. */ 40725120Sache warn("fork"); 4081558Srgrimes free(optbuf); 4091558Srgrimes return (1); 4101558Srgrimes case 0: /* Child. */ 4111558Srgrimes if (strcmp(vfstype, "ufs") == 0) 4121558Srgrimes exit(mount_ufs(argc, (char * const *) argv)); 4131558Srgrimes 4141558Srgrimes /* Go find an executable. */ 41514626Sasami for (edir = edirs; *edir; edir++) { 4161558Srgrimes (void)snprintf(execname, 4171558Srgrimes sizeof(execname), "%s/mount_%s", *edir, vfstype); 4181558Srgrimes execv(execname, (char * const *)argv); 41914626Sasami } 42014626Sasami if (errno == ENOENT) { 42114626Sasami int len = 0; 42214626Sasami char *cp; 42314626Sasami for (edir = edirs; *edir; edir++) 42414626Sasami len += strlen(*edir) + 2; /* ", " */ 42514626Sasami if ((cp = malloc(len)) == NULL) { 42614626Sasami warn(NULL); 42714626Sasami exit(1); 42814626Sasami } 42914626Sasami cp[0] = '\0'; 43014626Sasami for (edir = edirs; *edir; edir++) { 43114626Sasami strcat(cp, *edir); 43214626Sasami if (edir[1] != NULL) 43314626Sasami strcat(cp, ", "); 43414626Sasami } 43514626Sasami warn("exec mount_%s not found in %s", vfstype, cp); 43614626Sasami } 4371558Srgrimes exit(1); 4381558Srgrimes /* NOTREACHED */ 4391558Srgrimes default: /* Parent. */ 4401558Srgrimes free(optbuf); 4411558Srgrimes 4421558Srgrimes if (waitpid(pid, &status, 0) < 0) { 4431558Srgrimes warn("waitpid"); 4441558Srgrimes return (1); 4451558Srgrimes } 4461558Srgrimes 4471558Srgrimes if (WIFEXITED(status)) { 4481558Srgrimes if (WEXITSTATUS(status) != 0) 4491558Srgrimes return (WEXITSTATUS(status)); 4501558Srgrimes } else if (WIFSIGNALED(status)) { 4511558Srgrimes warnx("%s: %s", name, sys_siglist[WTERMSIG(status)]); 4521558Srgrimes return (1); 4531558Srgrimes } 4541558Srgrimes 4551558Srgrimes if (verbose) { 4561558Srgrimes if (statfs(name, &sf) < 0) { 45723678Speter warn("statfs %s", name); 4581558Srgrimes return (1); 4591558Srgrimes } 46017243Sjkh if (fstab_style) 46123805Sbde putfsent(&sf); 46217243Sjkh else 46323678Speter prmount(&sf); 4641558Srgrimes } 4651558Srgrimes break; 4661558Srgrimes } 4671558Srgrimes 4681558Srgrimes return (0); 4691558Srgrimes} 4701558Srgrimes 4711558Srgrimesvoid 47223678Speterprmount(sfp) 47323678Speter struct statfs *sfp; 47423678Speter{ 4751558Srgrimes int flags; 4761558Srgrimes struct opt *o; 47723678Speter struct passwd *pw; 4781558Srgrimes int f; 4791558Srgrimes 48023678Speter (void)printf("%s on %s", sfp->f_mntfromname, sfp->f_mntonname); 4811558Srgrimes 48223678Speter flags = sfp->f_flags & MNT_VISFLAGMASK; 4831558Srgrimes for (f = 0, o = optnames; flags && o->o_opt; o++) 4841558Srgrimes if (flags & o->o_opt) { 4851558Srgrimes (void)printf("%s%s", !f++ ? " (" : ", ", o->o_name); 4861558Srgrimes flags &= ~o->o_opt; 4871558Srgrimes } 48823678Speter if (sfp->f_owner) { 48923678Speter (void)printf("%smounted by ", !f++ ? " (" : ", "); 49023678Speter if ((pw = getpwuid(sfp->f_owner)) != NULL) 49123678Speter (void)printf("%s", pw->pw_name); 49223678Speter else 49323678Speter (void)printf("%d", sfp->f_owner); 49423678Speter } 4951558Srgrimes (void)printf(f ? ")\n" : "\n"); 4961558Srgrimes} 4971558Srgrimes 4981558Srgrimesstruct statfs * 4991558Srgrimesgetmntpt(name) 5001558Srgrimes const char *name; 5011558Srgrimes{ 5021558Srgrimes struct statfs *mntbuf; 5031558Srgrimes int i, mntsize; 5041558Srgrimes 5051558Srgrimes mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 5061558Srgrimes for (i = 0; i < mntsize; i++) 5071558Srgrimes if (strcmp(mntbuf[i].f_mntfromname, name) == 0 || 5081558Srgrimes strcmp(mntbuf[i].f_mntonname, name) == 0) 5091558Srgrimes return (&mntbuf[i]); 5101558Srgrimes return (NULL); 5111558Srgrimes} 5121558Srgrimes 5131558Srgrimeschar * 5141558Srgrimescatopt(s0, s1) 5151558Srgrimes char *s0; 5161558Srgrimes const char *s1; 5171558Srgrimes{ 5181558Srgrimes size_t i; 5191558Srgrimes char *cp; 5201558Srgrimes 5211558Srgrimes if (s0 && *s0) { 5221558Srgrimes i = strlen(s0) + strlen(s1) + 1 + 1; 5231558Srgrimes if ((cp = malloc(i)) == NULL) 5241558Srgrimes err(1, NULL); 5251558Srgrimes (void)snprintf(cp, i, "%s,%s", s0, s1); 5261558Srgrimes } else 5271558Srgrimes cp = strdup(s1); 5281558Srgrimes 5291558Srgrimes if (s0) 5301558Srgrimes free(s0); 5311558Srgrimes return (cp); 5321558Srgrimes} 5331558Srgrimes 5341558Srgrimesvoid 5351558Srgrimesmangle(options, argcp, argv) 5361558Srgrimes char *options; 5371558Srgrimes int *argcp; 5381558Srgrimes const char **argv; 5391558Srgrimes{ 5401558Srgrimes char *p, *s; 5411558Srgrimes int argc; 5421558Srgrimes 5431558Srgrimes argc = *argcp; 5441558Srgrimes for (s = options; (p = strsep(&s, ",")) != NULL;) 5451558Srgrimes if (*p != '\0') 5461558Srgrimes if (*p == '-') { 5471558Srgrimes argv[argc++] = p; 5481558Srgrimes p = strchr(p, '='); 5491558Srgrimes if (p) { 5501558Srgrimes *p = '\0'; 5511558Srgrimes argv[argc++] = p+1; 5521558Srgrimes } 5531558Srgrimes } else if (strcmp(p, "rw") != 0) { 5541558Srgrimes argv[argc++] = "-o"; 5551558Srgrimes argv[argc++] = p; 5561558Srgrimes } 5571558Srgrimes 5581558Srgrimes *argcp = argc; 5591558Srgrimes} 5601558Srgrimes 5611558Srgrimesvoid 5621558Srgrimesusage() 5631558Srgrimes{ 5641558Srgrimes 5651558Srgrimes (void)fprintf(stderr, 5661558Srgrimes "usage: mount %s %s\n mount %s\n mount %s\n", 56717243Sjkh "[-dfpruvw] [-o options] [-t ufs | external_type]", 5681558Srgrimes "special node", 56917243Sjkh "[-adfpruvw] [-t ufs | external_type]", 57017243Sjkh "[-dfpruvw] special | node"); 5711558Srgrimes exit(1); 5721558Srgrimes} 57317243Sjkh 57417243Sjkhvoid 57523805Sbdeputfsent(ent) 57623805Sbde const struct statfs *ent; 57717243Sjkh{ 57823805Sbde struct fstab *fst; 57917243Sjkh 58023805Sbde printf("%s\t%s\t%s %s", ent->f_mntfromname, ent->f_mntonname, 58123805Sbde ent->f_fstypename, (ent->f_flags & MNT_RDONLY) ? "ro" : "rw"); 58217243Sjkh 58323805Sbde /* XXX should use optnames[] - put shorter names in it. */ 58423805Sbde if (ent->f_flags & MNT_SYNCHRONOUS) 58523805Sbde printf(",sync"); 58623805Sbde if (ent->f_flags & MNT_NOEXEC) 58723805Sbde printf(",noexec"); 58823805Sbde if (ent->f_flags & MNT_NOSUID) 58923805Sbde printf(",nosuid"); 59023805Sbde if (ent->f_flags & MNT_NODEV) 59123805Sbde printf(",nodev"); 59223805Sbde if (ent->f_flags & MNT_UNION) 59323805Sbde printf(",union"); 59423805Sbde if (ent->f_flags & MNT_ASYNC) 59523805Sbde printf(",async"); 59623805Sbde if (ent->f_flags & MNT_NOATIME) 59723805Sbde printf(",noatime"); 59817243Sjkh 59928671Ssteve if ((fst = getfsspec(ent->f_mntfromname))) 60023805Sbde printf("\t%u %u\n", fst->fs_freq, fst->fs_passno); 60128671Ssteve else if ((fst = getfsfile(ent->f_mntonname))) 60223805Sbde printf("\t%u %u\n", fst->fs_freq, fst->fs_passno); 60323805Sbde else if (ent->f_type == MOUNT_UFS) 60423805Sbde printf("\t1 1\n"); 60523805Sbde else 60623805Sbde printf("\t0 0\n"); 60717243Sjkh} 608