1fba1c154SSteve Price /*- 28fae3551SRodney W. Grimes * Copyright (c) 1980, 1989, 1993, 1994 38fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 48fae3551SRodney W. Grimes * 58fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 68fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 78fae3551SRodney W. Grimes * are met: 88fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 98fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 108fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 118fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 128fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 138fae3551SRodney W. Grimes * 4. Neither the name of the University nor the names of its contributors 148fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 158fae3551SRodney W. Grimes * without specific prior written permission. 168fae3551SRodney W. Grimes * 178fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 188fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 198fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 208fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 218fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 228fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 238fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 248fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 258fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 268fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 278fae3551SRodney W. Grimes * SUCH DAMAGE. 288fae3551SRodney W. Grimes */ 298fae3551SRodney W. Grimes 308fae3551SRodney W. Grimes #ifndef lint 31fba1c154SSteve Price static const char copyright[] = 328fae3551SRodney W. Grimes "@(#) Copyright (c) 1980, 1989, 1993, 1994\n\ 338fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 348fae3551SRodney W. Grimes #endif /* not lint */ 358fae3551SRodney W. Grimes 368fae3551SRodney W. Grimes #ifndef lint 37fba1c154SSteve Price #if 0 38c06fe0a0SPeter Wemm static char sccsid[] = "@(#)mount.c 8.25 (Berkeley) 5/8/95"; 39fba1c154SSteve Price #endif 40bcb1d846SPhilippe Charnier static const char rcsid[] = 417f3dea24SPeter Wemm "$FreeBSD$"; 428fae3551SRodney W. Grimes #endif /* not lint */ 438fae3551SRodney W. Grimes 448fae3551SRodney W. Grimes #include <sys/param.h> 458fae3551SRodney W. Grimes #include <sys/mount.h> 468a978495SDavid Greenman #include <sys/stat.h> 4774cf460bSBruce Evans #include <sys/wait.h> 488fae3551SRodney W. Grimes 49003dbca6SMaxime Henrion #include <ctype.h> 508fae3551SRodney W. Grimes #include <err.h> 518fae3551SRodney W. Grimes #include <errno.h> 528fae3551SRodney W. Grimes #include <fstab.h> 53a3ba4c65SGordon Tetlow #include <paths.h> 54c06fe0a0SPeter Wemm #include <pwd.h> 558fae3551SRodney W. Grimes #include <signal.h> 5696c65ccbSIan Dowse #include <stdint.h> 578fae3551SRodney W. Grimes #include <stdio.h> 588fae3551SRodney W. Grimes #include <stdlib.h> 598fae3551SRodney W. Grimes #include <string.h> 608fae3551SRodney W. Grimes #include <unistd.h> 618fae3551SRodney W. Grimes 62fba1c154SSteve Price #include "extern.h" 6373dd3167SPoul-Henning Kamp #include "mntopts.h" 648fae3551SRodney W. Grimes #include "pathnames.h" 658fae3551SRodney W. Grimes 6618af6044SJoseph Koshy /* `meta' options */ 6718af6044SJoseph Koshy #define MOUNT_META_OPTION_FSTAB "fstab" 6818af6044SJoseph Koshy #define MOUNT_META_OPTION_CURRENT "current" 6918af6044SJoseph Koshy 7074cf460bSBruce Evans int debug, fstab_style, verbose; 71a257a45eSJordan K. Hubbard 7285429990SWarner Losh char *catopt(char *, const char *); 7385429990SWarner Losh struct statfs *getmntpt(const char *); 7485429990SWarner Losh int hasopt(const char *, const char *); 7585429990SWarner Losh int ismounted(struct fstab *, struct statfs *, int); 7685429990SWarner Losh int isremountable(const char *); 774796c6ccSJuli Mallett void mangle(char *, int *, char *[]); 7885429990SWarner Losh char *update_options(char *, char *, int); 7985429990SWarner Losh int mountfs(const char *, const char *, const char *, 8085429990SWarner Losh int, const char *, const char *); 8185429990SWarner Losh void remopt(char *, const char *); 8285429990SWarner Losh void prmount(struct statfs *); 8385429990SWarner Losh void putfsent(const struct statfs *); 8485429990SWarner Losh void usage(void); 8585429990SWarner Losh char *flags2opts(int); 868fae3551SRodney W. Grimes 87bcb1d846SPhilippe Charnier /* Map from mount options to printable formats. */ 888fae3551SRodney W. Grimes static struct opt { 898fae3551SRodney W. Grimes int o_opt; 908fae3551SRodney W. Grimes const char *o_name; 918fae3551SRodney W. Grimes } optnames[] = { 928fae3551SRodney W. Grimes { MNT_ASYNC, "asynchronous" }, 938fae3551SRodney W. Grimes { MNT_EXPORTED, "NFS exported" }, 948fae3551SRodney W. Grimes { MNT_LOCAL, "local" }, 9555e50aceSDavid Greenman { MNT_NOATIME, "noatime" }, 968fae3551SRodney W. Grimes { MNT_NOEXEC, "noexec" }, 978fae3551SRodney W. Grimes { MNT_NOSUID, "nosuid" }, 985ddc8dedSWolfram Schneider { MNT_NOSYMFOLLOW, "nosymfollow" }, 998fae3551SRodney W. Grimes { MNT_QUOTA, "with quotas" }, 1008fae3551SRodney W. Grimes { MNT_RDONLY, "read-only" }, 1018fae3551SRodney W. Grimes { MNT_SYNCHRONOUS, "synchronous" }, 1028fae3551SRodney W. Grimes { MNT_UNION, "union" }, 10375b714acSKATO Takenori { MNT_NOCLUSTERR, "noclusterr" }, 10475b714acSKATO Takenori { MNT_NOCLUSTERW, "noclusterw" }, 10552bf64c7SJulian Elischer { MNT_SUIDDIR, "suiddir" }, 106b1897c19SJulian Elischer { MNT_SOFTDEP, "soft-updates" }, 107ba0fbe96SRobert Watson { MNT_MULTILABEL, "multilabel" }, 10803d94b50SRobert Watson { MNT_ACLS, "acls" }, 10918af6044SJoseph Koshy { 0, NULL } 1108fae3551SRodney W. Grimes }; 1118fae3551SRodney W. Grimes 112fba1c154SSteve Price /* 113fba1c154SSteve Price * List of VFS types that can be remounted without becoming mounted on top 114fba1c154SSteve Price * of each other. 115fba1c154SSteve Price * XXX Is this list correct? 116fba1c154SSteve Price */ 117fba1c154SSteve Price static const char * 118fba1c154SSteve Price remountable_fs_names[] = { 1195a4420e3SAlexey Zelkin "ufs", "ffs", "ext2fs", 120fba1c154SSteve Price 0 121fba1c154SSteve Price }; 122fba1c154SSteve Price 1236e74fb9dSMaxim Konovalov static const char userquotaeq[] = "userquota="; 1246e74fb9dSMaxim Konovalov static const char groupquotaeq[] = "groupquota="; 1256e74fb9dSMaxim Konovalov 1266f5f1a6bSCraig Rodrigues static int 1276f5f1a6bSCraig Rodrigues use_mountprog(const char *vfstype) 1286f5f1a6bSCraig Rodrigues { 1296f5f1a6bSCraig Rodrigues /* XXX: We need to get away from implementing external mount 1306f5f1a6bSCraig Rodrigues * programs for every filesystem, and move towards having 1316f5f1a6bSCraig Rodrigues * each filesystem properly implement the nmount() system call. 1326f5f1a6bSCraig Rodrigues */ 1336f5f1a6bSCraig Rodrigues unsigned int i; 1346f5f1a6bSCraig Rodrigues const char *fs[] = { 1356973ce04STai-hwa Liang "cd9660", "mfs", "msdosfs", "nfs", "nfs4", "ntfs", 136cf9e56b0SCraig Rodrigues "nwfs", "nullfs", "portalfs", "smbfs", "udf", "umapfs", 1376f5f1a6bSCraig Rodrigues "unionfs", 1386f5f1a6bSCraig Rodrigues NULL 1396f5f1a6bSCraig Rodrigues }; 1406f5f1a6bSCraig Rodrigues 1416f5f1a6bSCraig Rodrigues for (i = 0; fs[i] != NULL; ++i) { 1426f5f1a6bSCraig Rodrigues if (strcmp(vfstype, fs[i]) == 0) 1434796c6ccSJuli Mallett return (1); 1446f5f1a6bSCraig Rodrigues } 1456f5f1a6bSCraig Rodrigues 1464796c6ccSJuli Mallett return (0); 1476f5f1a6bSCraig Rodrigues } 1486f5f1a6bSCraig Rodrigues 1496f5f1a6bSCraig Rodrigues static int 1504796c6ccSJuli Mallett exec_mountprog(const char *name, const char *execname, char *const argv[]) 1516f5f1a6bSCraig Rodrigues { 1526f5f1a6bSCraig Rodrigues pid_t pid; 1536f5f1a6bSCraig Rodrigues int status; 1546f5f1a6bSCraig Rodrigues 1556f5f1a6bSCraig Rodrigues switch (pid = fork()) { 1566f5f1a6bSCraig Rodrigues case -1: /* Error. */ 1576f5f1a6bSCraig Rodrigues warn("fork"); 1586f5f1a6bSCraig Rodrigues exit (1); 1596f5f1a6bSCraig Rodrigues case 0: /* Child. */ 1606f5f1a6bSCraig Rodrigues /* Go find an executable. */ 1616f5f1a6bSCraig Rodrigues execvP(execname, _PATH_SYSPATH, argv); 1626f5f1a6bSCraig Rodrigues if (errno == ENOENT) { 1636f5f1a6bSCraig Rodrigues warn("exec %s not found in %s", execname, 1646f5f1a6bSCraig Rodrigues _PATH_SYSPATH); 1656f5f1a6bSCraig Rodrigues } 1666f5f1a6bSCraig Rodrigues exit(1); 1676f5f1a6bSCraig Rodrigues default: /* Parent. */ 1686f5f1a6bSCraig Rodrigues if (waitpid(pid, &status, 0) < 0) { 1696f5f1a6bSCraig Rodrigues warn("waitpid"); 1706f5f1a6bSCraig Rodrigues return (1); 1716f5f1a6bSCraig Rodrigues } 1726f5f1a6bSCraig Rodrigues 1736f5f1a6bSCraig Rodrigues if (WIFEXITED(status)) { 1746f5f1a6bSCraig Rodrigues if (WEXITSTATUS(status) != 0) 1756f5f1a6bSCraig Rodrigues return (WEXITSTATUS(status)); 1766f5f1a6bSCraig Rodrigues } else if (WIFSIGNALED(status)) { 1776f5f1a6bSCraig Rodrigues warnx("%s: %s", name, sys_siglist[WTERMSIG(status)]); 1786f5f1a6bSCraig Rodrigues return (1); 1796f5f1a6bSCraig Rodrigues } 1806f5f1a6bSCraig Rodrigues break; 1816f5f1a6bSCraig Rodrigues } 1826f5f1a6bSCraig Rodrigues 1836f5f1a6bSCraig Rodrigues return (0); 1846f5f1a6bSCraig Rodrigues } 1856f5f1a6bSCraig Rodrigues 18649a41c4fSRuslan Ermilov static int 18749a41c4fSRuslan Ermilov specified_ro(const char *arg) 1883cbf527eSRuslan Ermilov { 1893cbf527eSRuslan Ermilov char *optbuf, *opt; 1903cbf527eSRuslan Ermilov int ret = 0; 1913cbf527eSRuslan Ermilov 1923cbf527eSRuslan Ermilov optbuf = strdup(arg); 1933cbf527eSRuslan Ermilov if (optbuf == NULL) 1943cbf527eSRuslan Ermilov err(1, NULL); 1953cbf527eSRuslan Ermilov 1963cbf527eSRuslan Ermilov for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) { 1973cbf527eSRuslan Ermilov if (strcmp(opt, "ro") == 0) { 1983cbf527eSRuslan Ermilov ret = 1; 1993cbf527eSRuslan Ermilov break; 2003cbf527eSRuslan Ermilov } 2013cbf527eSRuslan Ermilov } 2023cbf527eSRuslan Ermilov free(optbuf); 2033cbf527eSRuslan Ermilov return (ret); 2043cbf527eSRuslan Ermilov } 2053cbf527eSRuslan Ermilov 2068fae3551SRodney W. Grimes int 207e24dc56aSCraig Rodrigues main(int argc, char *argv[]) 2088fae3551SRodney W. Grimes { 209c06fe0a0SPeter Wemm const char *mntfromname, **vfslist, *vfstype; 2108fae3551SRodney W. Grimes struct fstab *fs; 2118fae3551SRodney W. Grimes struct statfs *mntbuf; 2128fae3551SRodney W. Grimes FILE *mountdfp; 2138fae3551SRodney W. Grimes pid_t pid; 2143cbf527eSRuslan Ermilov int all, ch, i, init_flags, late, mntsize, rval, have_fstab, ro; 215003dbca6SMaxime Henrion char *cp, *ep, *options; 2168fae3551SRodney W. Grimes 2174b4f9170SDag-Erling Smørgrav all = init_flags = late = 0; 2183cbf527eSRuslan Ermilov ro = 0; 2193cbf527eSRuslan Ermilov options = NULL; 2208fae3551SRodney W. Grimes vfslist = NULL; 2218fae3551SRodney W. Grimes vfstype = "ufs"; 22249a41c4fSRuslan Ermilov while ((ch = getopt(argc, argv, "adF:flo:prt:uvw")) != -1) 2238fae3551SRodney W. Grimes switch (ch) { 2248fae3551SRodney W. Grimes case 'a': 2258fae3551SRodney W. Grimes all = 1; 2268fae3551SRodney W. Grimes break; 2278fae3551SRodney W. Grimes case 'd': 2288fae3551SRodney W. Grimes debug = 1; 2298fae3551SRodney W. Grimes break; 230ef258dd9SMatthew N. Dodd case 'F': 231ef258dd9SMatthew N. Dodd setfstab(optarg); 232ef258dd9SMatthew N. Dodd break; 2338fae3551SRodney W. Grimes case 'f': 2348fae3551SRodney W. Grimes init_flags |= MNT_FORCE; 2358fae3551SRodney W. Grimes break; 2364b4f9170SDag-Erling Smørgrav case 'l': 2374b4f9170SDag-Erling Smørgrav late = 1; 2384b4f9170SDag-Erling Smørgrav break; 2398fae3551SRodney W. Grimes case 'o': 2403cbf527eSRuslan Ermilov if (*optarg) { 2418fae3551SRodney W. Grimes options = catopt(options, optarg); 2423cbf527eSRuslan Ermilov if (specified_ro(optarg)) 2433cbf527eSRuslan Ermilov ro = 1; 2443cbf527eSRuslan Ermilov } 2458fae3551SRodney W. Grimes break; 24674cf460bSBruce Evans case 'p': 24774cf460bSBruce Evans fstab_style = 1; 24874cf460bSBruce Evans verbose = 1; 24974cf460bSBruce Evans break; 2508fae3551SRodney W. Grimes case 'r': 251ad044771SDima Dorfman options = catopt(options, "ro"); 2523cbf527eSRuslan Ermilov ro = 1; 2538fae3551SRodney W. Grimes break; 2548fae3551SRodney W. Grimes case 't': 2558fae3551SRodney W. Grimes if (vfslist != NULL) 256bcb1d846SPhilippe Charnier errx(1, "only one -t option may be specified"); 2578fae3551SRodney W. Grimes vfslist = makevfslist(optarg); 2588fae3551SRodney W. Grimes vfstype = optarg; 2598fae3551SRodney W. Grimes break; 2608fae3551SRodney W. Grimes case 'u': 2618fae3551SRodney W. Grimes init_flags |= MNT_UPDATE; 2628fae3551SRodney W. Grimes break; 2638fae3551SRodney W. Grimes case 'v': 2648fae3551SRodney W. Grimes verbose = 1; 2658fae3551SRodney W. Grimes break; 2668fae3551SRodney W. Grimes case 'w': 267ad044771SDima Dorfman options = catopt(options, "noro"); 2688fae3551SRodney W. Grimes break; 2698fae3551SRodney W. Grimes case '?': 2708fae3551SRodney W. Grimes default: 2718fae3551SRodney W. Grimes usage(); 2728fae3551SRodney W. Grimes /* NOTREACHED */ 2738fae3551SRodney W. Grimes } 2748fae3551SRodney W. Grimes argc -= optind; 2758fae3551SRodney W. Grimes argv += optind; 2768fae3551SRodney W. Grimes 2778fae3551SRodney W. Grimes #define BADTYPE(type) \ 2788fae3551SRodney W. Grimes (strcmp(type, FSTAB_RO) && \ 2798fae3551SRodney W. Grimes strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) 2808fae3551SRodney W. Grimes 2813cbf527eSRuslan Ermilov if ((init_flags & MNT_UPDATE) && (ro == 0)) 2823cbf527eSRuslan Ermilov options = catopt(options, "noro"); 2833cbf527eSRuslan Ermilov 2848fae3551SRodney W. Grimes rval = 0; 2858fae3551SRodney W. Grimes switch (argc) { 2868fae3551SRodney W. Grimes case 0: 287fba1c154SSteve Price if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) 288fba1c154SSteve Price err(1, "getmntinfo"); 289fba1c154SSteve Price if (all) { 2908fae3551SRodney W. Grimes while ((fs = getfsent()) != NULL) { 2918fae3551SRodney W. Grimes if (BADTYPE(fs->fs_type)) 2928fae3551SRodney W. Grimes continue; 293c06fe0a0SPeter Wemm if (checkvfsname(fs->fs_vfstype, vfslist)) 2948fae3551SRodney W. Grimes continue; 295c06fe0a0SPeter Wemm if (hasopt(fs->fs_mntops, "noauto")) 29689beb278SDavid Greenman continue; 2974b4f9170SDag-Erling Smørgrav if (hasopt(fs->fs_mntops, "late") && !late) 2984b4f9170SDag-Erling Smørgrav continue; 29998201b0cSBruce Evans if (!(init_flags & MNT_UPDATE) && 30098201b0cSBruce Evans ismounted(fs, mntbuf, mntsize)) 301fba1c154SSteve Price continue; 30213cbdf24SGuido van Rooij options = update_options(options, fs->fs_mntops, 30313cbdf24SGuido van Rooij mntbuf->f_flags); 3048fae3551SRodney W. Grimes if (mountfs(fs->fs_vfstype, fs->fs_spec, 3058fae3551SRodney W. Grimes fs->fs_file, init_flags, options, 3068fae3551SRodney W. Grimes fs->fs_mntops)) 3078fae3551SRodney W. Grimes rval = 1; 3088fae3551SRodney W. Grimes } 309fba1c154SSteve Price } else if (fstab_style) { 310a257a45eSJordan K. Hubbard for (i = 0; i < mntsize; i++) { 311c06fe0a0SPeter Wemm if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) 312a257a45eSJordan K. Hubbard continue; 313a257a45eSJordan K. Hubbard putfsent(&mntbuf[i]); 314a257a45eSJordan K. Hubbard } 31574cf460bSBruce Evans } else { 3168fae3551SRodney W. Grimes for (i = 0; i < mntsize; i++) { 31774cf460bSBruce Evans if (checkvfsname(mntbuf[i].f_fstypename, 31874cf460bSBruce Evans vfslist)) 3198fae3551SRodney W. Grimes continue; 320c06fe0a0SPeter Wemm prmount(&mntbuf[i]); 3218fae3551SRodney W. Grimes } 3228fae3551SRodney W. Grimes } 3238fae3551SRodney W. Grimes exit(rval); 3248fae3551SRodney W. Grimes case 1: 3258fae3551SRodney W. Grimes if (vfslist != NULL) 3268fae3551SRodney W. Grimes usage(); 3278fae3551SRodney W. Grimes 32801a9bce5SEric Anholt rmslashes(*argv, *argv); 3298fae3551SRodney W. Grimes if (init_flags & MNT_UPDATE) { 330cf96af72SBrian Feldman mntfromname = NULL; 331cf96af72SBrian Feldman have_fstab = 0; 3328fae3551SRodney W. Grimes if ((mntbuf = getmntpt(*argv)) == NULL) 333cf96af72SBrian Feldman errx(1, "not currently mounted %s", *argv); 334cf96af72SBrian Feldman /* 335cf96af72SBrian Feldman * Only get the mntflags from fstab if both mntpoint 336cf96af72SBrian Feldman * and mntspec are identical. Also handle the special 337cf96af72SBrian Feldman * case where just '/' is mounted and 'spec' is not 338cf96af72SBrian Feldman * identical with the one from fstab ('/dev' is missing 339cf96af72SBrian Feldman * in the spec-string at boot-time). 340cf96af72SBrian Feldman */ 34118af6044SJoseph Koshy if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) { 342cf96af72SBrian Feldman if (strcmp(fs->fs_spec, 343cf96af72SBrian Feldman mntbuf->f_mntfromname) == 0 && 344cf96af72SBrian Feldman strcmp(fs->fs_file, 345cf96af72SBrian Feldman mntbuf->f_mntonname) == 0) { 346cf96af72SBrian Feldman have_fstab = 1; 347cf96af72SBrian Feldman mntfromname = mntbuf->f_mntfromname; 348cf96af72SBrian Feldman } else if (argv[0][0] == '/' && 349cf96af72SBrian Feldman argv[0][1] == '\0') { 350cf96af72SBrian Feldman fs = getfsfile("/"); 351cf96af72SBrian Feldman have_fstab = 1; 352c06fe0a0SPeter Wemm mntfromname = fs->fs_spec; 353cf96af72SBrian Feldman } 354cf96af72SBrian Feldman } 355cf96af72SBrian Feldman if (have_fstab) { 35618af6044SJoseph Koshy options = update_options(options, fs->fs_mntops, 35718af6044SJoseph Koshy mntbuf->f_flags); 35818af6044SJoseph Koshy } else { 359c06fe0a0SPeter Wemm mntfromname = mntbuf->f_mntfromname; 36018af6044SJoseph Koshy options = update_options(options, NULL, 36118af6044SJoseph Koshy mntbuf->f_flags); 36218af6044SJoseph Koshy } 363c06fe0a0SPeter Wemm rval = mountfs(mntbuf->f_fstypename, mntfromname, 364c06fe0a0SPeter Wemm mntbuf->f_mntonname, init_flags, options, 0); 365c06fe0a0SPeter Wemm break; 366c06fe0a0SPeter Wemm } 3678fae3551SRodney W. Grimes if ((fs = getfsfile(*argv)) == NULL && 3688fae3551SRodney W. Grimes (fs = getfsspec(*argv)) == NULL) 369bcb1d846SPhilippe Charnier errx(1, "%s: unknown special file or file system", 3708fae3551SRodney W. Grimes *argv); 3718fae3551SRodney W. Grimes if (BADTYPE(fs->fs_type)) 372bcb1d846SPhilippe Charnier errx(1, "%s has unknown file system type", 3738fae3551SRodney W. Grimes *argv); 374c06fe0a0SPeter Wemm rval = mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, 375c06fe0a0SPeter Wemm init_flags, options, fs->fs_mntops); 3768fae3551SRodney W. Grimes break; 3778fae3551SRodney W. Grimes case 2: 3788fae3551SRodney W. Grimes /* 379cf96af72SBrian Feldman * If -t flag has not been specified, the path cannot be 380003dbca6SMaxime Henrion * found, spec contains either a ':' or a '@', then assume 381cf96af72SBrian Feldman * that an NFS file system is being specified ala Sun. 382003dbca6SMaxime Henrion * Check if the hostname contains only allowed characters 383003dbca6SMaxime Henrion * to reduce false positives. IPv6 addresses containing 384003dbca6SMaxime Henrion * ':' will be correctly parsed only if the separator is '@'. 385003dbca6SMaxime Henrion * The definition of a valid hostname is taken from RFC 1034. 3868fae3551SRodney W. Grimes */ 38705779418SIan Dowse if (vfslist == NULL && ((ep = strchr(argv[0], '@')) != NULL || 38805779418SIan Dowse (ep = strchr(argv[0], ':')) != NULL)) { 389da85c82bSMaxime Henrion if (*ep == '@') { 390da85c82bSMaxime Henrion cp = ep + 1; 391da85c82bSMaxime Henrion ep = cp + strlen(cp); 392da85c82bSMaxime Henrion } else 393003dbca6SMaxime Henrion cp = argv[0]; 394003dbca6SMaxime Henrion while (cp != ep) { 395003dbca6SMaxime Henrion if (!isdigit(*cp) && !isalpha(*cp) && 396003dbca6SMaxime Henrion *cp != '.' && *cp != '-' && *cp != ':') 397003dbca6SMaxime Henrion break; 398003dbca6SMaxime Henrion cp++; 399003dbca6SMaxime Henrion } 400003dbca6SMaxime Henrion if (cp == ep) 4018fae3551SRodney W. Grimes vfstype = "nfs"; 402003dbca6SMaxime Henrion } 4038fae3551SRodney W. Grimes rval = mountfs(vfstype, 4048fae3551SRodney W. Grimes argv[0], argv[1], init_flags, options, NULL); 4058fae3551SRodney W. Grimes break; 4068fae3551SRodney W. Grimes default: 4078fae3551SRodney W. Grimes usage(); 4088fae3551SRodney W. Grimes /* NOTREACHED */ 4098fae3551SRodney W. Grimes } 4108fae3551SRodney W. Grimes 4118fae3551SRodney W. Grimes /* 4128fae3551SRodney W. Grimes * If the mount was successfully, and done by root, tell mountd the 4138fae3551SRodney W. Grimes * good news. Pid checks are probably unnecessary, but don't hurt. 4148fae3551SRodney W. Grimes */ 4158fae3551SRodney W. Grimes if (rval == 0 && getuid() == 0 && 4168fae3551SRodney W. Grimes (mountdfp = fopen(_PATH_MOUNTDPID, "r")) != NULL) { 417fba1c154SSteve Price if (fscanf(mountdfp, "%d", &pid) == 1 && 4188fae3551SRodney W. Grimes pid > 0 && kill(pid, SIGHUP) == -1 && errno != ESRCH) 4198fae3551SRodney W. Grimes err(1, "signal mountd"); 4208fae3551SRodney W. Grimes (void)fclose(mountdfp); 4218fae3551SRodney W. Grimes } 4228fae3551SRodney W. Grimes 4238fae3551SRodney W. Grimes exit(rval); 4248fae3551SRodney W. Grimes } 4258fae3551SRodney W. Grimes 4268fae3551SRodney W. Grimes int 427e24dc56aSCraig Rodrigues ismounted(struct fstab *fs, struct statfs *mntbuf, int mntsize) 428fba1c154SSteve Price { 42990742659SPawel Jakub Dawidek char realfsfile[PATH_MAX]; 430fba1c154SSteve Price int i; 431fba1c154SSteve Price 432fba1c154SSteve Price if (fs->fs_file[0] == '/' && fs->fs_file[1] == '\0') 433fba1c154SSteve Price /* the root file system can always be remounted */ 434fba1c154SSteve Price return (0); 435fba1c154SSteve Price 43690742659SPawel Jakub Dawidek /* The user may have specified a symlink in fstab, resolve the path */ 43790742659SPawel Jakub Dawidek if (realpath(fs->fs_file, realfsfile) == NULL) { 43890742659SPawel Jakub Dawidek /* Cannot resolve the path, use original one */ 43990742659SPawel Jakub Dawidek strlcpy(realfsfile, fs->fs_file, sizeof(realfsfile)); 44090742659SPawel Jakub Dawidek } 44190742659SPawel Jakub Dawidek 442fba1c154SSteve Price for (i = mntsize - 1; i >= 0; --i) 44390742659SPawel Jakub Dawidek if (strcmp(realfsfile, mntbuf[i].f_mntonname) == 0 && 444fba1c154SSteve Price (!isremountable(fs->fs_vfstype) || 445fba1c154SSteve Price strcmp(fs->fs_spec, mntbuf[i].f_mntfromname) == 0)) 446fba1c154SSteve Price return (1); 447fba1c154SSteve Price return (0); 448fba1c154SSteve Price } 449fba1c154SSteve Price 450fba1c154SSteve Price int 451e24dc56aSCraig Rodrigues isremountable(const char *vfsname) 452fba1c154SSteve Price { 453fba1c154SSteve Price const char **cp; 454fba1c154SSteve Price 455fba1c154SSteve Price for (cp = remountable_fs_names; *cp; cp++) 456fba1c154SSteve Price if (strcmp(*cp, vfsname) == 0) 457fba1c154SSteve Price return (1); 458fba1c154SSteve Price return (0); 459fba1c154SSteve Price } 460fba1c154SSteve Price 461fba1c154SSteve Price int 462e24dc56aSCraig Rodrigues hasopt(const char *mntopts, const char *option) 463c06fe0a0SPeter Wemm { 464c06fe0a0SPeter Wemm int negative, found; 465c06fe0a0SPeter Wemm char *opt, *optbuf; 466c06fe0a0SPeter Wemm 467c06fe0a0SPeter Wemm if (option[0] == 'n' && option[1] == 'o') { 468c06fe0a0SPeter Wemm negative = 1; 469c06fe0a0SPeter Wemm option += 2; 470c06fe0a0SPeter Wemm } else 471c06fe0a0SPeter Wemm negative = 0; 472c06fe0a0SPeter Wemm optbuf = strdup(mntopts); 473c06fe0a0SPeter Wemm found = 0; 474c06fe0a0SPeter Wemm for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) { 475c06fe0a0SPeter Wemm if (opt[0] == 'n' && opt[1] == 'o') { 476c06fe0a0SPeter Wemm if (!strcasecmp(opt + 2, option)) 477c06fe0a0SPeter Wemm found = negative; 478c06fe0a0SPeter Wemm } else if (!strcasecmp(opt, option)) 479c06fe0a0SPeter Wemm found = !negative; 480c06fe0a0SPeter Wemm } 481c06fe0a0SPeter Wemm free(optbuf); 482c06fe0a0SPeter Wemm return (found); 483c06fe0a0SPeter Wemm } 484c06fe0a0SPeter Wemm 485c06fe0a0SPeter Wemm int 486e24dc56aSCraig Rodrigues mountfs(const char *vfstype, const char *spec, const char *name, int flags, 487e24dc56aSCraig Rodrigues const char *options, const char *mntopts) 4888fae3551SRodney W. Grimes { 4896f5f1a6bSCraig Rodrigues char *argv[100]; 4908fae3551SRodney W. Grimes struct statfs sf; 4916f5f1a6bSCraig Rodrigues int argc, i, ret; 49268dd1ff4SWarner Losh char *optbuf, execname[PATH_MAX], mntpath[PATH_MAX]; 4938fae3551SRodney W. Grimes 49473dd3167SPoul-Henning Kamp /* resolve the mountpoint with realpath(3) */ 49573dd3167SPoul-Henning Kamp (void)checkpath(name, mntpath); 4968fae3551SRodney W. Grimes name = mntpath; 4978fae3551SRodney W. Grimes 498c06fe0a0SPeter Wemm if (mntopts == NULL) 499c06fe0a0SPeter Wemm mntopts = ""; 5008fae3551SRodney W. Grimes optbuf = catopt(strdup(mntopts), options); 5018fae3551SRodney W. Grimes 5028fae3551SRodney W. Grimes if (strcmp(name, "/") == 0) 5038fae3551SRodney W. Grimes flags |= MNT_UPDATE; 5048fae3551SRodney W. Grimes if (flags & MNT_FORCE) 5058fae3551SRodney W. Grimes optbuf = catopt(optbuf, "force"); 5068fae3551SRodney W. Grimes if (flags & MNT_RDONLY) 5078fae3551SRodney W. Grimes optbuf = catopt(optbuf, "ro"); 5088fae3551SRodney W. Grimes /* 5098fae3551SRodney W. Grimes * XXX 5108fae3551SRodney W. Grimes * The mount_mfs (newfs) command uses -o to select the 511bcb1d846SPhilippe Charnier * optimization mode. We don't pass the default "-o rw" 5128fae3551SRodney W. Grimes * for that reason. 5138fae3551SRodney W. Grimes */ 5148fae3551SRodney W. Grimes if (flags & MNT_UPDATE) 5158fae3551SRodney W. Grimes optbuf = catopt(optbuf, "update"); 5168fae3551SRodney W. Grimes 5174ccd7546SRuslan Ermilov /* Compatibility glue. */ 5184ccd7546SRuslan Ermilov if (strcmp(vfstype, "msdos") == 0) 5194ccd7546SRuslan Ermilov vfstype = "msdosfs"; 5204ccd7546SRuslan Ermilov 5216e34b479SColin Percival /* Construct the name of the appropriate mount command */ 5226e34b479SColin Percival (void)snprintf(execname, sizeof(execname), "mount_%s", vfstype); 5236e34b479SColin Percival 5248fae3551SRodney W. Grimes argc = 0; 5256e34b479SColin Percival argv[argc++] = execname; 5268fae3551SRodney W. Grimes mangle(optbuf, &argc, argv); 5276f5f1a6bSCraig Rodrigues argv[argc++] = strdup(spec); 5286f5f1a6bSCraig Rodrigues argv[argc++] = strdup(name); 5298fae3551SRodney W. Grimes argv[argc] = NULL; 5308fae3551SRodney W. Grimes 5318fae3551SRodney W. Grimes if (debug) { 5328fae3551SRodney W. Grimes (void)printf("exec: mount_%s", vfstype); 5338fae3551SRodney W. Grimes for (i = 1; i < argc; i++) 5348fae3551SRodney W. Grimes (void)printf(" %s", argv[i]); 5358fae3551SRodney W. Grimes (void)printf("\n"); 5368fae3551SRodney W. Grimes return (0); 5378fae3551SRodney W. Grimes } 5388fae3551SRodney W. Grimes 539b1e6b712SCraig Rodrigues if (use_mountprog(vfstype)) { 5406f5f1a6bSCraig Rodrigues ret = exec_mountprog(name, execname, argv); 5416f5f1a6bSCraig Rodrigues } else { 5426f5f1a6bSCraig Rodrigues ret = mount_fs(vfstype, argc, argv); 5436f5f1a6bSCraig Rodrigues } 5446f5f1a6bSCraig Rodrigues 5458fae3551SRodney W. Grimes free(optbuf); 5468fae3551SRodney W. Grimes 5478fae3551SRodney W. Grimes if (verbose) { 5488fae3551SRodney W. Grimes if (statfs(name, &sf) < 0) { 549c06fe0a0SPeter Wemm warn("statfs %s", name); 5508fae3551SRodney W. Grimes return (1); 5518fae3551SRodney W. Grimes } 552a257a45eSJordan K. Hubbard if (fstab_style) 553a257a45eSJordan K. Hubbard putfsent(&sf); 554a257a45eSJordan K. Hubbard else 555c06fe0a0SPeter Wemm prmount(&sf); 5568fae3551SRodney W. Grimes } 5578fae3551SRodney W. Grimes 5588fae3551SRodney W. Grimes return (0); 5598fae3551SRodney W. Grimes } 5608fae3551SRodney W. Grimes 5618fae3551SRodney W. Grimes void 562e24dc56aSCraig Rodrigues prmount(struct statfs *sfp) 5638fae3551SRodney W. Grimes { 564aedf10acSCraig Rodrigues int flags; 565aedf10acSCraig Rodrigues unsigned int i; 5668fae3551SRodney W. Grimes struct opt *o; 567c06fe0a0SPeter Wemm struct passwd *pw; 5688fae3551SRodney W. Grimes 569af2ea5aaSNick Hibma (void)printf("%s on %s (%s", sfp->f_mntfromname, sfp->f_mntonname, 570af2ea5aaSNick Hibma sfp->f_fstypename); 5718fae3551SRodney W. Grimes 572c06fe0a0SPeter Wemm flags = sfp->f_flags & MNT_VISFLAGMASK; 573af2ea5aaSNick Hibma for (o = optnames; flags && o->o_opt; o++) 5748fae3551SRodney W. Grimes if (flags & o->o_opt) { 575af2ea5aaSNick Hibma (void)printf(", %s", o->o_name); 5768fae3551SRodney W. Grimes flags &= ~o->o_opt; 5778fae3551SRodney W. Grimes } 578dc9c6194SPawel Jakub Dawidek /* 579dc9c6194SPawel Jakub Dawidek * Inform when file system is mounted by an unprivileged user 580dc9c6194SPawel Jakub Dawidek * or privileged non-root user. 581dc9c6194SPawel Jakub Dawidek */ 582ddb842ccSJacques Vidrine if ((flags & MNT_USER) != 0 || sfp->f_owner != 0) { 583af2ea5aaSNick Hibma (void)printf(", mounted by "); 584c06fe0a0SPeter Wemm if ((pw = getpwuid(sfp->f_owner)) != NULL) 585c06fe0a0SPeter Wemm (void)printf("%s", pw->pw_name); 586c06fe0a0SPeter Wemm else 587c06fe0a0SPeter Wemm (void)printf("%d", sfp->f_owner); 588c06fe0a0SPeter Wemm } 589c62ffab6SSheldon Hearn if (verbose) { 590677b9b3fSBruce Evans if (sfp->f_syncwrites != 0 || sfp->f_asyncwrites != 0) 59196c65ccbSIan Dowse (void)printf(", writes: sync %ju async %ju", 59296c65ccbSIan Dowse (uintmax_t)sfp->f_syncwrites, 59396c65ccbSIan Dowse (uintmax_t)sfp->f_asyncwrites); 594461bb71eSKirk McKusick if (sfp->f_syncreads != 0 || sfp->f_asyncreads != 0) 59596c65ccbSIan Dowse (void)printf(", reads: sync %ju async %ju", 59696c65ccbSIan Dowse (uintmax_t)sfp->f_syncreads, 59796c65ccbSIan Dowse (uintmax_t)sfp->f_asyncreads); 59805779418SIan Dowse if (sfp->f_fsid.val[0] != 0 || sfp->f_fsid.val[1] != 0) { 59938f102c2SIan Dowse printf(", fsid "); 60038f102c2SIan Dowse for (i = 0; i < sizeof(sfp->f_fsid); i++) 60138f102c2SIan Dowse printf("%02x", ((u_char *)&sfp->f_fsid)[i]); 602c62ffab6SSheldon Hearn } 60305779418SIan Dowse } 604af2ea5aaSNick Hibma (void)printf(")\n"); 6058fae3551SRodney W. Grimes } 6068fae3551SRodney W. Grimes 6078fae3551SRodney W. Grimes struct statfs * 608e24dc56aSCraig Rodrigues getmntpt(const char *name) 6098fae3551SRodney W. Grimes { 6108fae3551SRodney W. Grimes struct statfs *mntbuf; 6118fae3551SRodney W. Grimes int i, mntsize; 6128fae3551SRodney W. Grimes 6138fae3551SRodney W. Grimes mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 614cf96af72SBrian Feldman for (i = mntsize - 1; i >= 0; i--) { 6158fae3551SRodney W. Grimes if (strcmp(mntbuf[i].f_mntfromname, name) == 0 || 6168fae3551SRodney W. Grimes strcmp(mntbuf[i].f_mntonname, name) == 0) 6178fae3551SRodney W. Grimes return (&mntbuf[i]); 618cf96af72SBrian Feldman } 6198fae3551SRodney W. Grimes return (NULL); 6208fae3551SRodney W. Grimes } 6218fae3551SRodney W. Grimes 6228fae3551SRodney W. Grimes char * 623e24dc56aSCraig Rodrigues catopt(char *s0, const char *s1) 6248fae3551SRodney W. Grimes { 6258fae3551SRodney W. Grimes size_t i; 6268fae3551SRodney W. Grimes char *cp; 6278fae3551SRodney W. Grimes 62818af6044SJoseph Koshy if (s1 == NULL || *s1 == '\0') 6294796c6ccSJuli Mallett return (s0); 63018af6044SJoseph Koshy 6318fae3551SRodney W. Grimes if (s0 && *s0) { 6328fae3551SRodney W. Grimes i = strlen(s0) + strlen(s1) + 1 + 1; 6338fae3551SRodney W. Grimes if ((cp = malloc(i)) == NULL) 634bcb1d846SPhilippe Charnier errx(1, "malloc failed"); 6358fae3551SRodney W. Grimes (void)snprintf(cp, i, "%s,%s", s0, s1); 6368fae3551SRodney W. Grimes } else 6378fae3551SRodney W. Grimes cp = strdup(s1); 6388fae3551SRodney W. Grimes 6398fae3551SRodney W. Grimes if (s0) 6408fae3551SRodney W. Grimes free(s0); 6418fae3551SRodney W. Grimes return (cp); 6428fae3551SRodney W. Grimes } 6438fae3551SRodney W. Grimes 6448fae3551SRodney W. Grimes void 6454796c6ccSJuli Mallett mangle(char *options, int *argcp, char *argv[]) 6468fae3551SRodney W. Grimes { 6478fae3551SRodney W. Grimes char *p, *s; 6488fae3551SRodney W. Grimes int argc; 6498fae3551SRodney W. Grimes 6508fae3551SRodney W. Grimes argc = *argcp; 6518fae3551SRodney W. Grimes for (s = options; (p = strsep(&s, ",")) != NULL;) 65218af6044SJoseph Koshy if (*p != '\0') { 653d9fa6ce7SCraig Rodrigues if (strcmp(p, "noauto") == 0) { 654d9fa6ce7SCraig Rodrigues /* 655d9fa6ce7SCraig Rodrigues * Do not pass noauto option to nmount(). 656d9fa6ce7SCraig Rodrigues * or external mount program. noauto is 657d9fa6ce7SCraig Rodrigues * only used to prevent mounting a filesystem 658d9fa6ce7SCraig Rodrigues * when 'mount -a' is specified, and is 659d9fa6ce7SCraig Rodrigues * not a real mount option. 660d9fa6ce7SCraig Rodrigues */ 661d9fa6ce7SCraig Rodrigues continue; 6624b4f9170SDag-Erling Smørgrav } else if (strcmp(p, "late") == 0) { 6634b4f9170SDag-Erling Smørgrav /* 6644b4f9170SDag-Erling Smørgrav * "late" is used to prevent certain file 6654b4f9170SDag-Erling Smørgrav * systems from being mounted before late 6664b4f9170SDag-Erling Smørgrav * in the boot cycle; for instance, 6674b4f9170SDag-Erling Smørgrav * loopback NFS mounts can't be mounted 6684b4f9170SDag-Erling Smørgrav * before mountd starts. 6694b4f9170SDag-Erling Smørgrav */ 6704b4f9170SDag-Erling Smørgrav continue; 67135d6c7f5SCraig Rodrigues } else if (strcmp(p, "userquota") == 0) { 67235d6c7f5SCraig Rodrigues continue; 6736e74fb9dSMaxim Konovalov } else if (strncmp(p, userquotaeq, 6746e74fb9dSMaxim Konovalov sizeof(userquotaeq) - 1) == 0) { 6756e74fb9dSMaxim Konovalov continue; 67635d6c7f5SCraig Rodrigues } else if (strcmp(p, "groupquota") == 0) { 67735d6c7f5SCraig Rodrigues continue; 6786e74fb9dSMaxim Konovalov } else if (strncmp(p, groupquotaeq, 6796e74fb9dSMaxim Konovalov sizeof(groupquotaeq) - 1) == 0) { 6806e74fb9dSMaxim Konovalov continue; 681d9fa6ce7SCraig Rodrigues } else if (*p == '-') { 6828fae3551SRodney W. Grimes argv[argc++] = p; 6838fae3551SRodney W. Grimes p = strchr(p, '='); 684adfdbe22STom Rhodes if (p != NULL) { 6858fae3551SRodney W. Grimes *p = '\0'; 6868fae3551SRodney W. Grimes argv[argc++] = p+1; 6878fae3551SRodney W. Grimes } 688748e259bSCraig Rodrigues } else { 6896f5f1a6bSCraig Rodrigues argv[argc++] = strdup("-o"); 6908fae3551SRodney W. Grimes argv[argc++] = p; 6918fae3551SRodney W. Grimes } 69218af6044SJoseph Koshy } 6938fae3551SRodney W. Grimes 6948fae3551SRodney W. Grimes *argcp = argc; 6958fae3551SRodney W. Grimes } 6968fae3551SRodney W. Grimes 69718af6044SJoseph Koshy 69818af6044SJoseph Koshy char * 6994796c6ccSJuli Mallett update_options(char *opts, char *fstab, int curflags) 70018af6044SJoseph Koshy { 70118af6044SJoseph Koshy char *o, *p; 70218af6044SJoseph Koshy char *cur; 70318af6044SJoseph Koshy char *expopt, *newopt, *tmpopt; 70418af6044SJoseph Koshy 70518af6044SJoseph Koshy if (opts == NULL) 7064796c6ccSJuli Mallett return (strdup("")); 70718af6044SJoseph Koshy 70818af6044SJoseph Koshy /* remove meta options from list */ 70918af6044SJoseph Koshy remopt(fstab, MOUNT_META_OPTION_FSTAB); 71018af6044SJoseph Koshy remopt(fstab, MOUNT_META_OPTION_CURRENT); 71118af6044SJoseph Koshy cur = flags2opts(curflags); 71218af6044SJoseph Koshy 71318af6044SJoseph Koshy /* 71418af6044SJoseph Koshy * Expand all meta-options passed to us first. 71518af6044SJoseph Koshy */ 71618af6044SJoseph Koshy expopt = NULL; 71718af6044SJoseph Koshy for (p = opts; (o = strsep(&p, ",")) != NULL;) { 71818af6044SJoseph Koshy if (strcmp(MOUNT_META_OPTION_FSTAB, o) == 0) 71918af6044SJoseph Koshy expopt = catopt(expopt, fstab); 72018af6044SJoseph Koshy else if (strcmp(MOUNT_META_OPTION_CURRENT, o) == 0) 72118af6044SJoseph Koshy expopt = catopt(expopt, cur); 72218af6044SJoseph Koshy else 72318af6044SJoseph Koshy expopt = catopt(expopt, o); 72418af6044SJoseph Koshy } 72518af6044SJoseph Koshy free(cur); 72618af6044SJoseph Koshy free(opts); 72718af6044SJoseph Koshy 72818af6044SJoseph Koshy /* 72918af6044SJoseph Koshy * Remove previous contradictory arguments. Given option "foo" we 73018af6044SJoseph Koshy * remove all the "nofoo" options. Given "nofoo" we remove "nonofoo" 73118af6044SJoseph Koshy * and "foo" - so we can deal with possible options like "notice". 73218af6044SJoseph Koshy */ 73318af6044SJoseph Koshy newopt = NULL; 73418af6044SJoseph Koshy for (p = expopt; (o = strsep(&p, ",")) != NULL;) { 73518af6044SJoseph Koshy if ((tmpopt = malloc( strlen(o) + 2 + 1 )) == NULL) 73618af6044SJoseph Koshy errx(1, "malloc failed"); 73718af6044SJoseph Koshy 73818af6044SJoseph Koshy strcpy(tmpopt, "no"); 73918af6044SJoseph Koshy strcat(tmpopt, o); 74018af6044SJoseph Koshy remopt(newopt, tmpopt); 74118af6044SJoseph Koshy free(tmpopt); 74218af6044SJoseph Koshy 74318af6044SJoseph Koshy if (strncmp("no", o, 2) == 0) 74418af6044SJoseph Koshy remopt(newopt, o+2); 74518af6044SJoseph Koshy 74618af6044SJoseph Koshy newopt = catopt(newopt, o); 74718af6044SJoseph Koshy } 74818af6044SJoseph Koshy free(expopt); 74918af6044SJoseph Koshy 7504796c6ccSJuli Mallett return (newopt); 75118af6044SJoseph Koshy } 75218af6044SJoseph Koshy 75318af6044SJoseph Koshy void 7544796c6ccSJuli Mallett remopt(char *string, const char *opt) 75518af6044SJoseph Koshy { 75618af6044SJoseph Koshy char *o, *p, *r; 75718af6044SJoseph Koshy 75818af6044SJoseph Koshy if (string == NULL || *string == '\0' || opt == NULL || *opt == '\0') 75918af6044SJoseph Koshy return; 76018af6044SJoseph Koshy 76118af6044SJoseph Koshy r = string; 76218af6044SJoseph Koshy 76318af6044SJoseph Koshy for (p = string; (o = strsep(&p, ",")) != NULL;) { 76418af6044SJoseph Koshy if (strcmp(opt, o) != 0) { 76518af6044SJoseph Koshy if (*r == ',' && *o != '\0') 76618af6044SJoseph Koshy r++; 76718af6044SJoseph Koshy while ((*r++ = *o++) != '\0') 76818af6044SJoseph Koshy ; 76918af6044SJoseph Koshy *--r = ','; 77018af6044SJoseph Koshy } 77118af6044SJoseph Koshy } 77218af6044SJoseph Koshy *r = '\0'; 77318af6044SJoseph Koshy } 77418af6044SJoseph Koshy 7758fae3551SRodney W. Grimes void 7764796c6ccSJuli Mallett usage(void) 7778fae3551SRodney W. Grimes { 7788fae3551SRodney W. Grimes 779bcb1d846SPhilippe Charnier (void)fprintf(stderr, "%s\n%s\n%s\n", 7804b4f9170SDag-Erling Smørgrav "usage: mount [-adflpruvw] [-F fstab] [-o options] [-t ufs | external_type]", 7818d646af5SRuslan Ermilov " mount [-dfpruvw] special | node", 7828d646af5SRuslan Ermilov " mount [-dfpruvw] [-o options] [-t ufs | external_type] special node"); 7838fae3551SRodney W. Grimes exit(1); 7848fae3551SRodney W. Grimes } 785a257a45eSJordan K. Hubbard 786a257a45eSJordan K. Hubbard void 7874796c6ccSJuli Mallett putfsent(const struct statfs *ent) 788a257a45eSJordan K. Hubbard { 789a257a45eSJordan K. Hubbard struct fstab *fst; 79018af6044SJoseph Koshy char *opts; 791a257a45eSJordan K. Hubbard 79218af6044SJoseph Koshy opts = flags2opts(ent->f_flags); 7933ae7ea68SGiorgos Keramidas 7943ae7ea68SGiorgos Keramidas /* 7953ae7ea68SGiorgos Keramidas * "rw" is not a real mount option; this is why we print NULL as "rw" 7963ae7ea68SGiorgos Keramidas * if opts is still NULL here. 7973ae7ea68SGiorgos Keramidas */ 79874cf460bSBruce Evans printf("%s\t%s\t%s %s", ent->f_mntfromname, ent->f_mntonname, 7993ae7ea68SGiorgos Keramidas ent->f_fstypename, opts ? opts : "rw"); 80018af6044SJoseph Koshy free(opts); 801c06fe0a0SPeter Wemm 802fba1c154SSteve Price if ((fst = getfsspec(ent->f_mntfromname))) 803a257a45eSJordan K. Hubbard printf("\t%u %u\n", fst->fs_freq, fst->fs_passno); 804fba1c154SSteve Price else if ((fst = getfsfile(ent->f_mntonname))) 805a257a45eSJordan K. Hubbard printf("\t%u %u\n", fst->fs_freq, fst->fs_passno); 806ab80d6faSBrian Feldman else if (strcmp(ent->f_fstypename, "ufs") == 0) { 807ab80d6faSBrian Feldman if (strcmp(ent->f_mntonname, "/") == 0) 808a257a45eSJordan K. Hubbard printf("\t1 1\n"); 809a257a45eSJordan K. Hubbard else 810ab80d6faSBrian Feldman printf("\t2 2\n"); 811ab80d6faSBrian Feldman } else 812a257a45eSJordan K. Hubbard printf("\t0 0\n"); 813a257a45eSJordan K. Hubbard } 81418af6044SJoseph Koshy 81518af6044SJoseph Koshy 81618af6044SJoseph Koshy char * 8174796c6ccSJuli Mallett flags2opts(int flags) 81818af6044SJoseph Koshy { 81918af6044SJoseph Koshy char *res; 82018af6044SJoseph Koshy 82118af6044SJoseph Koshy res = NULL; 82218af6044SJoseph Koshy 82388e2c335SCraig Rodrigues if (flags & MNT_RDONLY) res = catopt(res, "ro"); 82418af6044SJoseph Koshy if (flags & MNT_SYNCHRONOUS) res = catopt(res, "sync"); 82518af6044SJoseph Koshy if (flags & MNT_NOEXEC) res = catopt(res, "noexec"); 82618af6044SJoseph Koshy if (flags & MNT_NOSUID) res = catopt(res, "nosuid"); 82718af6044SJoseph Koshy if (flags & MNT_UNION) res = catopt(res, "union"); 82818af6044SJoseph Koshy if (flags & MNT_ASYNC) res = catopt(res, "async"); 82918af6044SJoseph Koshy if (flags & MNT_NOATIME) res = catopt(res, "noatime"); 83018af6044SJoseph Koshy if (flags & MNT_NOCLUSTERR) res = catopt(res, "noclusterr"); 83118af6044SJoseph Koshy if (flags & MNT_NOCLUSTERW) res = catopt(res, "noclusterw"); 83218af6044SJoseph Koshy if (flags & MNT_NOSYMFOLLOW) res = catopt(res, "nosymfollow"); 83318af6044SJoseph Koshy if (flags & MNT_SUIDDIR) res = catopt(res, "suiddir"); 834ba0fbe96SRobert Watson if (flags & MNT_MULTILABEL) res = catopt(res, "multilabel"); 83503d94b50SRobert Watson if (flags & MNT_ACLS) res = catopt(res, "acls"); 83618af6044SJoseph Koshy 8374796c6ccSJuli Mallett return (res); 83818af6044SJoseph Koshy } 839