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. 13fbbd9655SWarner Losh * 3. 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"; 34fba1c154SSteve Price #if 0 35c06fe0a0SPeter Wemm static char sccsid[] = "@(#)mount.c 8.25 (Berkeley) 5/8/95"; 36fba1c154SSteve Price #endif 378fae3551SRodney W. Grimes #endif /* not lint */ 388fae3551SRodney W. Grimes 3900356118SDavid E. O'Brien #include <sys/cdefs.h> 4000356118SDavid E. O'Brien __FBSDID("$FreeBSD$"); 4100356118SDavid E. O'Brien 428fae3551SRodney W. Grimes #include <sys/param.h> 438fae3551SRodney W. Grimes #include <sys/mount.h> 448a978495SDavid Greenman #include <sys/stat.h> 4574cf460bSBruce Evans #include <sys/wait.h> 468fae3551SRodney W. Grimes 47003dbca6SMaxime Henrion #include <ctype.h> 488fae3551SRodney W. Grimes #include <err.h> 498fae3551SRodney W. Grimes #include <errno.h> 508fae3551SRodney W. Grimes #include <fstab.h> 51a3ba4c65SGordon Tetlow #include <paths.h> 52c06fe0a0SPeter Wemm #include <pwd.h> 538fae3551SRodney W. Grimes #include <signal.h> 5496c65ccbSIan Dowse #include <stdint.h> 558fae3551SRodney W. Grimes #include <stdio.h> 568fae3551SRodney W. Grimes #include <stdlib.h> 578fae3551SRodney W. Grimes #include <string.h> 588fae3551SRodney W. Grimes #include <unistd.h> 59e9988cedSPawel Jakub Dawidek #include <libutil.h> 608fae3551SRodney W. Grimes 61fba1c154SSteve Price #include "extern.h" 6273dd3167SPoul-Henning Kamp #include "mntopts.h" 638fae3551SRodney W. Grimes #include "pathnames.h" 648fae3551SRodney W. Grimes 6518af6044SJoseph Koshy /* `meta' options */ 6618af6044SJoseph Koshy #define MOUNT_META_OPTION_FSTAB "fstab" 6718af6044SJoseph Koshy #define MOUNT_META_OPTION_CURRENT "current" 6818af6044SJoseph Koshy 691efe3c6bSEd Schouten static int debug, fstab_style, verbose; 70a257a45eSJordan K. Hubbard 71a86de995SDavid E. O'Brien struct cpa { 7200356118SDavid E. O'Brien char **a; 730e969ed7SDavid E. O'Brien ssize_t sz; 74a86de995SDavid E. O'Brien int c; 75a86de995SDavid E. O'Brien }; 76a86de995SDavid E. O'Brien 7785429990SWarner Losh char *catopt(char *, const char *); 7885429990SWarner Losh struct statfs *getmntpt(const char *); 7985429990SWarner Losh int hasopt(const char *, const char *); 8085429990SWarner Losh int ismounted(struct fstab *, struct statfs *, int); 8185429990SWarner Losh int isremountable(const char *); 82a86de995SDavid E. O'Brien void mangle(char *, struct cpa *); 8385429990SWarner Losh char *update_options(char *, char *, int); 8485429990SWarner Losh int mountfs(const char *, const char *, const char *, 8585429990SWarner Losh int, const char *, const char *); 8685429990SWarner Losh void remopt(char *, const char *); 8785429990SWarner Losh void prmount(struct statfs *); 88031ea52fSMatteo Riondato void putfsent(struct statfs *); 8985429990SWarner Losh void usage(void); 9085429990SWarner Losh char *flags2opts(int); 918fae3551SRodney W. Grimes 92bcb1d846SPhilippe Charnier /* Map from mount options to printable formats. */ 938fae3551SRodney W. Grimes static struct opt { 949df3a164SBjoern A. Zeeb uint64_t o_opt; 958fae3551SRodney W. Grimes const char *o_name; 968fae3551SRodney W. Grimes } optnames[] = { 978fae3551SRodney W. Grimes { MNT_ASYNC, "asynchronous" }, 988fae3551SRodney W. Grimes { MNT_EXPORTED, "NFS exported" }, 998fae3551SRodney W. Grimes { MNT_LOCAL, "local" }, 10055e50aceSDavid Greenman { MNT_NOATIME, "noatime" }, 1018fae3551SRodney W. Grimes { MNT_NOEXEC, "noexec" }, 1028fae3551SRodney W. Grimes { MNT_NOSUID, "nosuid" }, 1035ddc8dedSWolfram Schneider { MNT_NOSYMFOLLOW, "nosymfollow" }, 1048fae3551SRodney W. Grimes { MNT_QUOTA, "with quotas" }, 1058fae3551SRodney W. Grimes { MNT_RDONLY, "read-only" }, 1068fae3551SRodney W. Grimes { MNT_SYNCHRONOUS, "synchronous" }, 1078fae3551SRodney W. Grimes { MNT_UNION, "union" }, 10875b714acSKATO Takenori { MNT_NOCLUSTERR, "noclusterr" }, 10975b714acSKATO Takenori { MNT_NOCLUSTERW, "noclusterw" }, 11052bf64c7SJulian Elischer { MNT_SUIDDIR, "suiddir" }, 111b1897c19SJulian Elischer { MNT_SOFTDEP, "soft-updates" }, 112d716efa9SKirk McKusick { MNT_SUJ, "journaled soft-updates" }, 113ba0fbe96SRobert Watson { MNT_MULTILABEL, "multilabel" }, 11403d94b50SRobert Watson { MNT_ACLS, "acls" }, 1159340fc72SEdward Tomasz Napierala { MNT_NFS4ACLS, "nfsv4acls" }, 116ac88569cSPawel Jakub Dawidek { MNT_GJOURNAL, "gjournal" }, 1173914ddf8SEdward Tomasz Napierala { MNT_AUTOMOUNTED, "automounted" }, 11818af6044SJoseph Koshy { 0, NULL } 1198fae3551SRodney W. Grimes }; 1208fae3551SRodney W. Grimes 121fba1c154SSteve Price /* 122fba1c154SSteve Price * List of VFS types that can be remounted without becoming mounted on top 123fba1c154SSteve Price * of each other. 124fba1c154SSteve Price * XXX Is this list correct? 125fba1c154SSteve Price */ 126fba1c154SSteve Price static const char * 127fba1c154SSteve Price remountable_fs_names[] = { 1285a4420e3SAlexey Zelkin "ufs", "ffs", "ext2fs", 129fba1c154SSteve Price 0 130fba1c154SSteve Price }; 131fba1c154SSteve Price 1326e74fb9dSMaxim Konovalov static const char userquotaeq[] = "userquota="; 1336e74fb9dSMaxim Konovalov static const char groupquotaeq[] = "groupquota="; 1346e74fb9dSMaxim Konovalov 135c7835769SCraig Rodrigues static char *mountprog = NULL; 136c7835769SCraig Rodrigues 1376f5f1a6bSCraig Rodrigues static int 1386f5f1a6bSCraig Rodrigues use_mountprog(const char *vfstype) 1396f5f1a6bSCraig Rodrigues { 1406f5f1a6bSCraig Rodrigues /* XXX: We need to get away from implementing external mount 1416f5f1a6bSCraig Rodrigues * programs for every filesystem, and move towards having 1426f5f1a6bSCraig Rodrigues * each filesystem properly implement the nmount() system call. 1436f5f1a6bSCraig Rodrigues */ 1446f5f1a6bSCraig Rodrigues unsigned int i; 1456f5f1a6bSCraig Rodrigues const char *fs[] = { 146a42ac676SAttilio Rao "cd9660", "mfs", "msdosfs", "nfs", 1474e25c86fSEdward Tomasz Napierala "nullfs", "smbfs", "udf", "unionfs", 1486f5f1a6bSCraig Rodrigues NULL 1496f5f1a6bSCraig Rodrigues }; 1506f5f1a6bSCraig Rodrigues 151c7835769SCraig Rodrigues if (mountprog != NULL) 152c7835769SCraig Rodrigues return (1); 153c7835769SCraig Rodrigues 1546f5f1a6bSCraig Rodrigues for (i = 0; fs[i] != NULL; ++i) { 1556f5f1a6bSCraig Rodrigues if (strcmp(vfstype, fs[i]) == 0) 1564796c6ccSJuli Mallett return (1); 1576f5f1a6bSCraig Rodrigues } 1586f5f1a6bSCraig Rodrigues 1594796c6ccSJuli Mallett return (0); 1606f5f1a6bSCraig Rodrigues } 1616f5f1a6bSCraig Rodrigues 1626f5f1a6bSCraig Rodrigues static int 1634796c6ccSJuli Mallett exec_mountprog(const char *name, const char *execname, char *const argv[]) 1646f5f1a6bSCraig Rodrigues { 1656f5f1a6bSCraig Rodrigues pid_t pid; 1666f5f1a6bSCraig Rodrigues int status; 1676f5f1a6bSCraig Rodrigues 1686f5f1a6bSCraig Rodrigues switch (pid = fork()) { 1696f5f1a6bSCraig Rodrigues case -1: /* Error. */ 1706f5f1a6bSCraig Rodrigues warn("fork"); 1716f5f1a6bSCraig Rodrigues exit (1); 1726f5f1a6bSCraig Rodrigues case 0: /* Child. */ 1736f5f1a6bSCraig Rodrigues /* Go find an executable. */ 1746f5f1a6bSCraig Rodrigues execvP(execname, _PATH_SYSPATH, argv); 1756f5f1a6bSCraig Rodrigues if (errno == ENOENT) { 176c7835769SCraig Rodrigues warn("exec %s not found", execname); 177c7835769SCraig Rodrigues if (execname[0] != '/') { 178c7835769SCraig Rodrigues warnx("in path: %s", _PATH_SYSPATH); 179c7835769SCraig Rodrigues } 1806f5f1a6bSCraig Rodrigues } 1816f5f1a6bSCraig Rodrigues exit(1); 1826f5f1a6bSCraig Rodrigues default: /* Parent. */ 1836f5f1a6bSCraig Rodrigues if (waitpid(pid, &status, 0) < 0) { 1846f5f1a6bSCraig Rodrigues warn("waitpid"); 1856f5f1a6bSCraig Rodrigues return (1); 1866f5f1a6bSCraig Rodrigues } 1876f5f1a6bSCraig Rodrigues 1886f5f1a6bSCraig Rodrigues if (WIFEXITED(status)) { 1896f5f1a6bSCraig Rodrigues if (WEXITSTATUS(status) != 0) 1906f5f1a6bSCraig Rodrigues return (WEXITSTATUS(status)); 1916f5f1a6bSCraig Rodrigues } else if (WIFSIGNALED(status)) { 1926f5f1a6bSCraig Rodrigues warnx("%s: %s", name, sys_siglist[WTERMSIG(status)]); 1936f5f1a6bSCraig Rodrigues return (1); 1946f5f1a6bSCraig Rodrigues } 1956f5f1a6bSCraig Rodrigues break; 1966f5f1a6bSCraig Rodrigues } 1976f5f1a6bSCraig Rodrigues 1986f5f1a6bSCraig Rodrigues return (0); 1996f5f1a6bSCraig Rodrigues } 2006f5f1a6bSCraig Rodrigues 20149a41c4fSRuslan Ermilov static int 20249a41c4fSRuslan Ermilov specified_ro(const char *arg) 2033cbf527eSRuslan Ermilov { 2043cbf527eSRuslan Ermilov char *optbuf, *opt; 2053cbf527eSRuslan Ermilov int ret = 0; 2063cbf527eSRuslan Ermilov 2073cbf527eSRuslan Ermilov optbuf = strdup(arg); 2083cbf527eSRuslan Ermilov if (optbuf == NULL) 2093cbf527eSRuslan Ermilov err(1, NULL); 2103cbf527eSRuslan Ermilov 2113cbf527eSRuslan Ermilov for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) { 2123cbf527eSRuslan Ermilov if (strcmp(opt, "ro") == 0) { 2133cbf527eSRuslan Ermilov ret = 1; 2143cbf527eSRuslan Ermilov break; 2153cbf527eSRuslan Ermilov } 2163cbf527eSRuslan Ermilov } 2173cbf527eSRuslan Ermilov free(optbuf); 2183cbf527eSRuslan Ermilov return (ret); 2193cbf527eSRuslan Ermilov } 2203cbf527eSRuslan Ermilov 221e9988cedSPawel Jakub Dawidek static void 222e9988cedSPawel Jakub Dawidek restart_mountd(void) 223e9988cedSPawel Jakub Dawidek { 224e9988cedSPawel Jakub Dawidek struct pidfh *pfh; 225e9988cedSPawel Jakub Dawidek pid_t mountdpid; 226e9988cedSPawel Jakub Dawidek 227e9988cedSPawel Jakub Dawidek pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &mountdpid); 228e9988cedSPawel Jakub Dawidek if (pfh != NULL) { 229e9988cedSPawel Jakub Dawidek /* Mountd is not running. */ 230e9988cedSPawel Jakub Dawidek pidfile_remove(pfh); 231e9988cedSPawel Jakub Dawidek return; 232e9988cedSPawel Jakub Dawidek } 233e9988cedSPawel Jakub Dawidek if (errno != EEXIST) { 234e9988cedSPawel Jakub Dawidek /* Cannot open pidfile for some reason. */ 235e9988cedSPawel Jakub Dawidek return; 236e9988cedSPawel Jakub Dawidek } 237e9988cedSPawel Jakub Dawidek /* We have mountd(8) PID in mountdpid varible, let's signal it. */ 238e9988cedSPawel Jakub Dawidek if (kill(mountdpid, SIGHUP) == -1) 239e9988cedSPawel Jakub Dawidek err(1, "signal mountd"); 240e9988cedSPawel Jakub Dawidek } 241e9988cedSPawel Jakub Dawidek 2428fae3551SRodney W. Grimes int 243e24dc56aSCraig Rodrigues main(int argc, char *argv[]) 2448fae3551SRodney W. Grimes { 245c06fe0a0SPeter Wemm const char *mntfromname, **vfslist, *vfstype; 2468fae3551SRodney W. Grimes struct fstab *fs; 2478fae3551SRodney W. Grimes struct statfs *mntbuf; 248c7383075SXin LI int all, ch, i, init_flags, late, failok, mntsize, rval, have_fstab, ro; 249b48b774fSChris Rees int onlylate; 250003dbca6SMaxime Henrion char *cp, *ep, *options; 2518fae3551SRodney W. Grimes 252b48b774fSChris Rees all = init_flags = late = onlylate = 0; 2533cbf527eSRuslan Ermilov ro = 0; 2543cbf527eSRuslan Ermilov options = NULL; 2558fae3551SRodney W. Grimes vfslist = NULL; 2568fae3551SRodney W. Grimes vfstype = "ufs"; 257fc98db27SRobert Millan while ((ch = getopt(argc, argv, "adF:fLlno:prt:uvw")) != -1) 2588fae3551SRodney W. Grimes switch (ch) { 2598fae3551SRodney W. Grimes case 'a': 2608fae3551SRodney W. Grimes all = 1; 2618fae3551SRodney W. Grimes break; 2628fae3551SRodney W. Grimes case 'd': 2638fae3551SRodney W. Grimes debug = 1; 2648fae3551SRodney W. Grimes break; 265ef258dd9SMatthew N. Dodd case 'F': 266ef258dd9SMatthew N. Dodd setfstab(optarg); 267ef258dd9SMatthew N. Dodd break; 2688fae3551SRodney W. Grimes case 'f': 2698fae3551SRodney W. Grimes init_flags |= MNT_FORCE; 2708fae3551SRodney W. Grimes break; 271b48b774fSChris Rees case 'L': 272b48b774fSChris Rees onlylate = 1; 273b48b774fSChris Rees late = 1; 274b48b774fSChris Rees break; 2754b4f9170SDag-Erling Smørgrav case 'l': 2764b4f9170SDag-Erling Smørgrav late = 1; 2774b4f9170SDag-Erling Smørgrav break; 278fc98db27SRobert Millan case 'n': 279fc98db27SRobert Millan /* For compatibility with the Linux version of mount. */ 280fc98db27SRobert Millan break; 2818fae3551SRodney W. Grimes case 'o': 2823cbf527eSRuslan Ermilov if (*optarg) { 2838fae3551SRodney W. Grimes options = catopt(options, optarg); 2843cbf527eSRuslan Ermilov if (specified_ro(optarg)) 2853cbf527eSRuslan Ermilov ro = 1; 2863cbf527eSRuslan Ermilov } 2878fae3551SRodney W. Grimes break; 28874cf460bSBruce Evans case 'p': 28974cf460bSBruce Evans fstab_style = 1; 29074cf460bSBruce Evans verbose = 1; 29174cf460bSBruce Evans break; 2928fae3551SRodney W. Grimes case 'r': 293ad044771SDima Dorfman options = catopt(options, "ro"); 2943cbf527eSRuslan Ermilov ro = 1; 2958fae3551SRodney W. Grimes break; 2968fae3551SRodney W. Grimes case 't': 2978fae3551SRodney W. Grimes if (vfslist != NULL) 298bcb1d846SPhilippe Charnier errx(1, "only one -t option may be specified"); 2998fae3551SRodney W. Grimes vfslist = makevfslist(optarg); 3008fae3551SRodney W. Grimes vfstype = optarg; 3018fae3551SRodney W. Grimes break; 3028fae3551SRodney W. Grimes case 'u': 3038fae3551SRodney W. Grimes init_flags |= MNT_UPDATE; 3048fae3551SRodney W. Grimes break; 3058fae3551SRodney W. Grimes case 'v': 3068fae3551SRodney W. Grimes verbose = 1; 3078fae3551SRodney W. Grimes break; 3088fae3551SRodney W. Grimes case 'w': 309ad044771SDima Dorfman options = catopt(options, "noro"); 3108fae3551SRodney W. Grimes break; 3118fae3551SRodney W. Grimes case '?': 3128fae3551SRodney W. Grimes default: 3138fae3551SRodney W. Grimes usage(); 3148fae3551SRodney W. Grimes /* NOTREACHED */ 3158fae3551SRodney W. Grimes } 3168fae3551SRodney W. Grimes argc -= optind; 3178fae3551SRodney W. Grimes argv += optind; 3188fae3551SRodney W. Grimes 3198fae3551SRodney W. Grimes #define BADTYPE(type) \ 3208fae3551SRodney W. Grimes (strcmp(type, FSTAB_RO) && \ 3218fae3551SRodney W. Grimes strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) 3228fae3551SRodney W. Grimes 3233cbf527eSRuslan Ermilov if ((init_flags & MNT_UPDATE) && (ro == 0)) 3243cbf527eSRuslan Ermilov options = catopt(options, "noro"); 3253cbf527eSRuslan Ermilov 3268fae3551SRodney W. Grimes rval = 0; 3278fae3551SRodney W. Grimes switch (argc) { 3288fae3551SRodney W. Grimes case 0: 329fddf7baeSKirk McKusick if ((mntsize = getmntinfo(&mntbuf, MNT_NOWAIT)) == 0) 330fba1c154SSteve Price err(1, "getmntinfo"); 331fba1c154SSteve Price if (all) { 3328fae3551SRodney W. Grimes while ((fs = getfsent()) != NULL) { 3338fae3551SRodney W. Grimes if (BADTYPE(fs->fs_type)) 3348fae3551SRodney W. Grimes continue; 335c06fe0a0SPeter Wemm if (checkvfsname(fs->fs_vfstype, vfslist)) 3368fae3551SRodney W. Grimes continue; 337c06fe0a0SPeter Wemm if (hasopt(fs->fs_mntops, "noauto")) 33889beb278SDavid Greenman continue; 339b48b774fSChris Rees if (!hasopt(fs->fs_mntops, "late") && onlylate) 340b48b774fSChris Rees continue; 3414b4f9170SDag-Erling Smørgrav if (hasopt(fs->fs_mntops, "late") && !late) 3424b4f9170SDag-Erling Smørgrav continue; 343c7383075SXin LI if (hasopt(fs->fs_mntops, "failok")) 344c7383075SXin LI failok = 1; 345c7383075SXin LI else 346c7383075SXin LI failok = 0; 34798201b0cSBruce Evans if (!(init_flags & MNT_UPDATE) && 34898201b0cSBruce Evans ismounted(fs, mntbuf, mntsize)) 349fba1c154SSteve Price continue; 35013cbdf24SGuido van Rooij options = update_options(options, fs->fs_mntops, 35113cbdf24SGuido van Rooij mntbuf->f_flags); 3528fae3551SRodney W. Grimes if (mountfs(fs->fs_vfstype, fs->fs_spec, 3538fae3551SRodney W. Grimes fs->fs_file, init_flags, options, 354c7383075SXin LI fs->fs_mntops) && !failok) 3558fae3551SRodney W. Grimes rval = 1; 3568fae3551SRodney W. Grimes } 357fba1c154SSteve Price } else if (fstab_style) { 358a257a45eSJordan K. Hubbard for (i = 0; i < mntsize; i++) { 359c06fe0a0SPeter Wemm if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) 360a257a45eSJordan K. Hubbard continue; 361a257a45eSJordan K. Hubbard putfsent(&mntbuf[i]); 362a257a45eSJordan K. Hubbard } 36374cf460bSBruce Evans } else { 3648fae3551SRodney W. Grimes for (i = 0; i < mntsize; i++) { 36574cf460bSBruce Evans if (checkvfsname(mntbuf[i].f_fstypename, 36674cf460bSBruce Evans vfslist)) 3678fae3551SRodney W. Grimes continue; 3688abb2a6eSPawel Jakub Dawidek if (!verbose && 3698abb2a6eSPawel Jakub Dawidek (mntbuf[i].f_flags & MNT_IGNORE) != 0) 3708abb2a6eSPawel Jakub Dawidek continue; 371c06fe0a0SPeter Wemm prmount(&mntbuf[i]); 3728fae3551SRodney W. Grimes } 3738fae3551SRodney W. Grimes } 3748fae3551SRodney W. Grimes exit(rval); 3758fae3551SRodney W. Grimes case 1: 3768fae3551SRodney W. Grimes if (vfslist != NULL) 3778fae3551SRodney W. Grimes usage(); 3788fae3551SRodney W. Grimes 37901a9bce5SEric Anholt rmslashes(*argv, *argv); 3808fae3551SRodney W. Grimes if (init_flags & MNT_UPDATE) { 381cf96af72SBrian Feldman mntfromname = NULL; 382cf96af72SBrian Feldman have_fstab = 0; 3838fae3551SRodney W. Grimes if ((mntbuf = getmntpt(*argv)) == NULL) 384cf96af72SBrian Feldman errx(1, "not currently mounted %s", *argv); 385cf96af72SBrian Feldman /* 386cf96af72SBrian Feldman * Only get the mntflags from fstab if both mntpoint 387cf96af72SBrian Feldman * and mntspec are identical. Also handle the special 388cf96af72SBrian Feldman * case where just '/' is mounted and 'spec' is not 389cf96af72SBrian Feldman * identical with the one from fstab ('/dev' is missing 390cf96af72SBrian Feldman * in the spec-string at boot-time). 391cf96af72SBrian Feldman */ 39218af6044SJoseph Koshy if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) { 393cf96af72SBrian Feldman if (strcmp(fs->fs_spec, 394cf96af72SBrian Feldman mntbuf->f_mntfromname) == 0 && 395cf96af72SBrian Feldman strcmp(fs->fs_file, 396cf96af72SBrian Feldman mntbuf->f_mntonname) == 0) { 397cf96af72SBrian Feldman have_fstab = 1; 398cf96af72SBrian Feldman mntfromname = mntbuf->f_mntfromname; 399cf96af72SBrian Feldman } else if (argv[0][0] == '/' && 400cf96af72SBrian Feldman argv[0][1] == '\0') { 401cf96af72SBrian Feldman fs = getfsfile("/"); 402cf96af72SBrian Feldman have_fstab = 1; 403c06fe0a0SPeter Wemm mntfromname = fs->fs_spec; 404cf96af72SBrian Feldman } 405cf96af72SBrian Feldman } 406cf96af72SBrian Feldman if (have_fstab) { 40718af6044SJoseph Koshy options = update_options(options, fs->fs_mntops, 40818af6044SJoseph Koshy mntbuf->f_flags); 40918af6044SJoseph Koshy } else { 410c06fe0a0SPeter Wemm mntfromname = mntbuf->f_mntfromname; 41118af6044SJoseph Koshy options = update_options(options, NULL, 41218af6044SJoseph Koshy mntbuf->f_flags); 41318af6044SJoseph Koshy } 414c06fe0a0SPeter Wemm rval = mountfs(mntbuf->f_fstypename, mntfromname, 415c06fe0a0SPeter Wemm mntbuf->f_mntonname, init_flags, options, 0); 416c06fe0a0SPeter Wemm break; 417c06fe0a0SPeter Wemm } 4188fae3551SRodney W. Grimes if ((fs = getfsfile(*argv)) == NULL && 4198fae3551SRodney W. Grimes (fs = getfsspec(*argv)) == NULL) 420bcb1d846SPhilippe Charnier errx(1, "%s: unknown special file or file system", 4218fae3551SRodney W. Grimes *argv); 4228fae3551SRodney W. Grimes if (BADTYPE(fs->fs_type)) 423bcb1d846SPhilippe Charnier errx(1, "%s has unknown file system type", 4248fae3551SRodney W. Grimes *argv); 425c06fe0a0SPeter Wemm rval = mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, 426c06fe0a0SPeter Wemm init_flags, options, fs->fs_mntops); 4278fae3551SRodney W. Grimes break; 4288fae3551SRodney W. Grimes case 2: 4298fae3551SRodney W. Grimes /* 430cf96af72SBrian Feldman * If -t flag has not been specified, the path cannot be 431003dbca6SMaxime Henrion * found, spec contains either a ':' or a '@', then assume 432cf96af72SBrian Feldman * that an NFS file system is being specified ala Sun. 433003dbca6SMaxime Henrion * Check if the hostname contains only allowed characters 434003dbca6SMaxime Henrion * to reduce false positives. IPv6 addresses containing 435003dbca6SMaxime Henrion * ':' will be correctly parsed only if the separator is '@'. 436003dbca6SMaxime Henrion * The definition of a valid hostname is taken from RFC 1034. 4378fae3551SRodney W. Grimes */ 43805779418SIan Dowse if (vfslist == NULL && ((ep = strchr(argv[0], '@')) != NULL || 43905779418SIan Dowse (ep = strchr(argv[0], ':')) != NULL)) { 440da85c82bSMaxime Henrion if (*ep == '@') { 441da85c82bSMaxime Henrion cp = ep + 1; 442da85c82bSMaxime Henrion ep = cp + strlen(cp); 443da85c82bSMaxime Henrion } else 444003dbca6SMaxime Henrion cp = argv[0]; 445003dbca6SMaxime Henrion while (cp != ep) { 446003dbca6SMaxime Henrion if (!isdigit(*cp) && !isalpha(*cp) && 447003dbca6SMaxime Henrion *cp != '.' && *cp != '-' && *cp != ':') 448003dbca6SMaxime Henrion break; 449003dbca6SMaxime Henrion cp++; 450003dbca6SMaxime Henrion } 451003dbca6SMaxime Henrion if (cp == ep) 4528fae3551SRodney W. Grimes vfstype = "nfs"; 453003dbca6SMaxime Henrion } 4548fae3551SRodney W. Grimes rval = mountfs(vfstype, 4558fae3551SRodney W. Grimes argv[0], argv[1], init_flags, options, NULL); 4568fae3551SRodney W. Grimes break; 4578fae3551SRodney W. Grimes default: 4588fae3551SRodney W. Grimes usage(); 4598fae3551SRodney W. Grimes /* NOTREACHED */ 4608fae3551SRodney W. Grimes } 4618fae3551SRodney W. Grimes 4628fae3551SRodney W. Grimes /* 4638fae3551SRodney W. Grimes * If the mount was successfully, and done by root, tell mountd the 464e9988cedSPawel Jakub Dawidek * good news. 4658fae3551SRodney W. Grimes */ 466e9988cedSPawel Jakub Dawidek if (rval == 0 && getuid() == 0) 467e9988cedSPawel Jakub Dawidek restart_mountd(); 4688fae3551SRodney W. Grimes 4698fae3551SRodney W. Grimes exit(rval); 4708fae3551SRodney W. Grimes } 4718fae3551SRodney W. Grimes 4728fae3551SRodney W. Grimes int 473e24dc56aSCraig Rodrigues ismounted(struct fstab *fs, struct statfs *mntbuf, int mntsize) 474fba1c154SSteve Price { 47590742659SPawel Jakub Dawidek char realfsfile[PATH_MAX]; 476fba1c154SSteve Price int i; 477fba1c154SSteve Price 478fba1c154SSteve Price if (fs->fs_file[0] == '/' && fs->fs_file[1] == '\0') 479fba1c154SSteve Price /* the root file system can always be remounted */ 480fba1c154SSteve Price return (0); 481fba1c154SSteve Price 48290742659SPawel Jakub Dawidek /* The user may have specified a symlink in fstab, resolve the path */ 48390742659SPawel Jakub Dawidek if (realpath(fs->fs_file, realfsfile) == NULL) { 48490742659SPawel Jakub Dawidek /* Cannot resolve the path, use original one */ 48590742659SPawel Jakub Dawidek strlcpy(realfsfile, fs->fs_file, sizeof(realfsfile)); 48690742659SPawel Jakub Dawidek } 48790742659SPawel Jakub Dawidek 488b5bbeb21SAlan Somers /* 489b5bbeb21SAlan Somers * Consider the filesystem to be mounted if: 490b5bbeb21SAlan Somers * It has the same mountpoint as a mounted filesytem, and 491b5bbeb21SAlan Somers * It has the same type as that same mounted filesystem, and 492b5bbeb21SAlan Somers * It has the same device name as that same mounted filesystem, OR 493b5bbeb21SAlan Somers * It is a nonremountable filesystem 494b5bbeb21SAlan Somers */ 495fba1c154SSteve Price for (i = mntsize - 1; i >= 0; --i) 49690742659SPawel Jakub Dawidek if (strcmp(realfsfile, mntbuf[i].f_mntonname) == 0 && 497b5bbeb21SAlan Somers strcmp(fs->fs_vfstype, mntbuf[i].f_fstypename) == 0 && 498fba1c154SSteve Price (!isremountable(fs->fs_vfstype) || 499b5bbeb21SAlan Somers (strcmp(fs->fs_spec, mntbuf[i].f_mntfromname) == 0))) 500fba1c154SSteve Price return (1); 501fba1c154SSteve Price return (0); 502fba1c154SSteve Price } 503fba1c154SSteve Price 504fba1c154SSteve Price int 505e24dc56aSCraig Rodrigues isremountable(const char *vfsname) 506fba1c154SSteve Price { 507fba1c154SSteve Price const char **cp; 508fba1c154SSteve Price 509fba1c154SSteve Price for (cp = remountable_fs_names; *cp; cp++) 510fba1c154SSteve Price if (strcmp(*cp, vfsname) == 0) 511fba1c154SSteve Price return (1); 512fba1c154SSteve Price return (0); 513fba1c154SSteve Price } 514fba1c154SSteve Price 515fba1c154SSteve Price int 516e24dc56aSCraig Rodrigues hasopt(const char *mntopts, const char *option) 517c06fe0a0SPeter Wemm { 518c06fe0a0SPeter Wemm int negative, found; 519c06fe0a0SPeter Wemm char *opt, *optbuf; 520c06fe0a0SPeter Wemm 521c06fe0a0SPeter Wemm if (option[0] == 'n' && option[1] == 'o') { 522c06fe0a0SPeter Wemm negative = 1; 523c06fe0a0SPeter Wemm option += 2; 524c06fe0a0SPeter Wemm } else 525c06fe0a0SPeter Wemm negative = 0; 526c06fe0a0SPeter Wemm optbuf = strdup(mntopts); 527c06fe0a0SPeter Wemm found = 0; 528c06fe0a0SPeter Wemm for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) { 529c06fe0a0SPeter Wemm if (opt[0] == 'n' && opt[1] == 'o') { 530c06fe0a0SPeter Wemm if (!strcasecmp(opt + 2, option)) 531c06fe0a0SPeter Wemm found = negative; 532c06fe0a0SPeter Wemm } else if (!strcasecmp(opt, option)) 533c06fe0a0SPeter Wemm found = !negative; 534c06fe0a0SPeter Wemm } 535c06fe0a0SPeter Wemm free(optbuf); 536c06fe0a0SPeter Wemm return (found); 537c06fe0a0SPeter Wemm } 538c06fe0a0SPeter Wemm 539a86de995SDavid E. O'Brien static void 540a86de995SDavid E. O'Brien append_arg(struct cpa *sa, char *arg) 541a86de995SDavid E. O'Brien { 5420e969ed7SDavid E. O'Brien if (sa->c + 1 == sa->sz) { 5430e969ed7SDavid E. O'Brien sa->sz = sa->sz == 0 ? 8 : sa->sz * 2; 544e96092e8SUlrich Spörlein sa->a = realloc(sa->a, sizeof(*sa->a) * sa->sz); 54500356118SDavid E. O'Brien if (sa->a == NULL) 54600356118SDavid E. O'Brien errx(1, "realloc failed"); 54700356118SDavid E. O'Brien } 548a86de995SDavid E. O'Brien sa->a[++sa->c] = arg; 549a86de995SDavid E. O'Brien } 550a86de995SDavid E. O'Brien 551c06fe0a0SPeter Wemm int 552e24dc56aSCraig Rodrigues mountfs(const char *vfstype, const char *spec, const char *name, int flags, 553e24dc56aSCraig Rodrigues const char *options, const char *mntopts) 5548fae3551SRodney W. Grimes { 5558fae3551SRodney W. Grimes struct statfs sf; 55676c46216SDavid E. O'Brien int i, ret; 55768dd1ff4SWarner Losh char *optbuf, execname[PATH_MAX], mntpath[PATH_MAX]; 5580e969ed7SDavid E. O'Brien static struct cpa mnt_argv; 5598fae3551SRodney W. Grimes 56073dd3167SPoul-Henning Kamp /* resolve the mountpoint with realpath(3) */ 561d3250014SJaakko Heinonen if (checkpath(name, mntpath) != 0) { 562d3250014SJaakko Heinonen warn("%s", mntpath); 563d3250014SJaakko Heinonen return (1); 564d3250014SJaakko Heinonen } 5658fae3551SRodney W. Grimes name = mntpath; 5668fae3551SRodney W. Grimes 567c06fe0a0SPeter Wemm if (mntopts == NULL) 568c06fe0a0SPeter Wemm mntopts = ""; 5698fae3551SRodney W. Grimes optbuf = catopt(strdup(mntopts), options); 5708fae3551SRodney W. Grimes 5718fae3551SRodney W. Grimes if (strcmp(name, "/") == 0) 5728fae3551SRodney W. Grimes flags |= MNT_UPDATE; 5738fae3551SRodney W. Grimes if (flags & MNT_FORCE) 5748fae3551SRodney W. Grimes optbuf = catopt(optbuf, "force"); 5758fae3551SRodney W. Grimes if (flags & MNT_RDONLY) 5768fae3551SRodney W. Grimes optbuf = catopt(optbuf, "ro"); 5778fae3551SRodney W. Grimes /* 5788fae3551SRodney W. Grimes * XXX 5798fae3551SRodney W. Grimes * The mount_mfs (newfs) command uses -o to select the 580bcb1d846SPhilippe Charnier * optimization mode. We don't pass the default "-o rw" 5818fae3551SRodney W. Grimes * for that reason. 5828fae3551SRodney W. Grimes */ 5838fae3551SRodney W. Grimes if (flags & MNT_UPDATE) 5848fae3551SRodney W. Grimes optbuf = catopt(optbuf, "update"); 5858fae3551SRodney W. Grimes 5864ccd7546SRuslan Ermilov /* Compatibility glue. */ 5875b548564SCraig Rodrigues if (strcmp(vfstype, "msdos") == 0) { 5885b548564SCraig Rodrigues warnx( 5895b548564SCraig Rodrigues "Using \"-t msdosfs\", since \"-t msdos\" is deprecated."); 5904ccd7546SRuslan Ermilov vfstype = "msdosfs"; 5915b548564SCraig Rodrigues } 5924ccd7546SRuslan Ermilov 5936e34b479SColin Percival /* Construct the name of the appropriate mount command */ 5946e34b479SColin Percival (void)snprintf(execname, sizeof(execname), "mount_%s", vfstype); 5956e34b479SColin Percival 596a86de995SDavid E. O'Brien mnt_argv.c = -1; 597a86de995SDavid E. O'Brien append_arg(&mnt_argv, execname); 598a86de995SDavid E. O'Brien mangle(optbuf, &mnt_argv); 599c7835769SCraig Rodrigues if (mountprog != NULL) 600*6e24000aSAlan Somers strlcpy(execname, mountprog, sizeof(execname)); 601c7835769SCraig Rodrigues 602a86de995SDavid E. O'Brien append_arg(&mnt_argv, strdup(spec)); 603a86de995SDavid E. O'Brien append_arg(&mnt_argv, strdup(name)); 604a86de995SDavid E. O'Brien append_arg(&mnt_argv, NULL); 605fce5f960SDavid E. O'Brien 6068fae3551SRodney W. Grimes if (debug) { 607c195c7f6SCraig Rodrigues if (use_mountprog(vfstype)) 608c7835769SCraig Rodrigues printf("exec: %s", execname); 609c195c7f6SCraig Rodrigues else 610c195c7f6SCraig Rodrigues printf("mount -t %s", vfstype); 611a86de995SDavid E. O'Brien for (i = 1; i < mnt_argv.c; i++) 612a86de995SDavid E. O'Brien (void)printf(" %s", mnt_argv.a[i]); 6138fae3551SRodney W. Grimes (void)printf("\n"); 614d2e17ce9SJohn Baldwin free(optbuf); 615d2e17ce9SJohn Baldwin free(mountprog); 616d2e17ce9SJohn Baldwin mountprog = NULL; 6178fae3551SRodney W. Grimes return (0); 6188fae3551SRodney W. Grimes } 6198fae3551SRodney W. Grimes 620b1e6b712SCraig Rodrigues if (use_mountprog(vfstype)) { 621a86de995SDavid E. O'Brien ret = exec_mountprog(name, execname, mnt_argv.a); 6226f5f1a6bSCraig Rodrigues } else { 623a86de995SDavid E. O'Brien ret = mount_fs(vfstype, mnt_argv.c, mnt_argv.a); 6246f5f1a6bSCraig Rodrigues } 6256f5f1a6bSCraig Rodrigues 6268fae3551SRodney W. Grimes free(optbuf); 627d2e17ce9SJohn Baldwin free(mountprog); 628d2e17ce9SJohn Baldwin mountprog = NULL; 6298fae3551SRodney W. Grimes 6308fae3551SRodney W. Grimes if (verbose) { 6318fae3551SRodney W. Grimes if (statfs(name, &sf) < 0) { 632c06fe0a0SPeter Wemm warn("statfs %s", name); 6338fae3551SRodney W. Grimes return (1); 6348fae3551SRodney W. Grimes } 635a257a45eSJordan K. Hubbard if (fstab_style) 636a257a45eSJordan K. Hubbard putfsent(&sf); 637a257a45eSJordan K. Hubbard else 638c06fe0a0SPeter Wemm prmount(&sf); 6398fae3551SRodney W. Grimes } 6408fae3551SRodney W. Grimes 641bbe9d7daSMatteo Riondato return (ret); 6428fae3551SRodney W. Grimes } 6438fae3551SRodney W. Grimes 6448fae3551SRodney W. Grimes void 645e24dc56aSCraig Rodrigues prmount(struct statfs *sfp) 6468fae3551SRodney W. Grimes { 6479df3a164SBjoern A. Zeeb uint64_t flags; 648aedf10acSCraig Rodrigues unsigned int i; 6498fae3551SRodney W. Grimes struct opt *o; 650c06fe0a0SPeter Wemm struct passwd *pw; 6518fae3551SRodney W. Grimes 652af2ea5aaSNick Hibma (void)printf("%s on %s (%s", sfp->f_mntfromname, sfp->f_mntonname, 653af2ea5aaSNick Hibma sfp->f_fstypename); 6548fae3551SRodney W. Grimes 655c06fe0a0SPeter Wemm flags = sfp->f_flags & MNT_VISFLAGMASK; 6569df3a164SBjoern A. Zeeb for (o = optnames; flags != 0 && o->o_opt != 0; o++) 6578fae3551SRodney W. Grimes if (flags & o->o_opt) { 658af2ea5aaSNick Hibma (void)printf(", %s", o->o_name); 6598fae3551SRodney W. Grimes flags &= ~o->o_opt; 6608fae3551SRodney W. Grimes } 661dc9c6194SPawel Jakub Dawidek /* 662dc9c6194SPawel Jakub Dawidek * Inform when file system is mounted by an unprivileged user 663dc9c6194SPawel Jakub Dawidek * or privileged non-root user. 664dc9c6194SPawel Jakub Dawidek */ 665ddb842ccSJacques Vidrine if ((flags & MNT_USER) != 0 || sfp->f_owner != 0) { 666af2ea5aaSNick Hibma (void)printf(", mounted by "); 667c06fe0a0SPeter Wemm if ((pw = getpwuid(sfp->f_owner)) != NULL) 668c06fe0a0SPeter Wemm (void)printf("%s", pw->pw_name); 669c06fe0a0SPeter Wemm else 670c06fe0a0SPeter Wemm (void)printf("%d", sfp->f_owner); 671c06fe0a0SPeter Wemm } 672c62ffab6SSheldon Hearn if (verbose) { 673677b9b3fSBruce Evans if (sfp->f_syncwrites != 0 || sfp->f_asyncwrites != 0) 67496c65ccbSIan Dowse (void)printf(", writes: sync %ju async %ju", 67596c65ccbSIan Dowse (uintmax_t)sfp->f_syncwrites, 67696c65ccbSIan Dowse (uintmax_t)sfp->f_asyncwrites); 677461bb71eSKirk McKusick if (sfp->f_syncreads != 0 || sfp->f_asyncreads != 0) 67896c65ccbSIan Dowse (void)printf(", reads: sync %ju async %ju", 67996c65ccbSIan Dowse (uintmax_t)sfp->f_syncreads, 68096c65ccbSIan Dowse (uintmax_t)sfp->f_asyncreads); 68105779418SIan Dowse if (sfp->f_fsid.val[0] != 0 || sfp->f_fsid.val[1] != 0) { 68238f102c2SIan Dowse printf(", fsid "); 68338f102c2SIan Dowse for (i = 0; i < sizeof(sfp->f_fsid); i++) 68438f102c2SIan Dowse printf("%02x", ((u_char *)&sfp->f_fsid)[i]); 685c62ffab6SSheldon Hearn } 68605779418SIan Dowse } 687af2ea5aaSNick Hibma (void)printf(")\n"); 6888fae3551SRodney W. Grimes } 6898fae3551SRodney W. Grimes 6908fae3551SRodney W. Grimes struct statfs * 691e24dc56aSCraig Rodrigues getmntpt(const char *name) 6928fae3551SRodney W. Grimes { 6938fae3551SRodney W. Grimes struct statfs *mntbuf; 6948fae3551SRodney W. Grimes int i, mntsize; 6958fae3551SRodney W. Grimes 696fddf7baeSKirk McKusick mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 697cf96af72SBrian Feldman for (i = mntsize - 1; i >= 0; i--) { 6988fae3551SRodney W. Grimes if (strcmp(mntbuf[i].f_mntfromname, name) == 0 || 6998fae3551SRodney W. Grimes strcmp(mntbuf[i].f_mntonname, name) == 0) 7008fae3551SRodney W. Grimes return (&mntbuf[i]); 701cf96af72SBrian Feldman } 7028fae3551SRodney W. Grimes return (NULL); 7038fae3551SRodney W. Grimes } 7048fae3551SRodney W. Grimes 7058fae3551SRodney W. Grimes char * 706e24dc56aSCraig Rodrigues catopt(char *s0, const char *s1) 7078fae3551SRodney W. Grimes { 7088fae3551SRodney W. Grimes char *cp; 7098fae3551SRodney W. Grimes 71018af6044SJoseph Koshy if (s1 == NULL || *s1 == '\0') 7114796c6ccSJuli Mallett return (s0); 71218af6044SJoseph Koshy 7138fae3551SRodney W. Grimes if (s0 && *s0) { 7148967299bSPedro F. Giffuni if (asprintf(&cp, "%s,%s", s0, s1) == -1) 7158967299bSPedro F. Giffuni errx(1, "asprintf failed"); 7168fae3551SRodney W. Grimes } else 7178fae3551SRodney W. Grimes cp = strdup(s1); 7188fae3551SRodney W. Grimes 7198fae3551SRodney W. Grimes if (s0) 7208fae3551SRodney W. Grimes free(s0); 7218fae3551SRodney W. Grimes return (cp); 7228fae3551SRodney W. Grimes } 7238fae3551SRodney W. Grimes 7248fae3551SRodney W. Grimes void 725a86de995SDavid E. O'Brien mangle(char *options, struct cpa *a) 7268fae3551SRodney W. Grimes { 727c7835769SCraig Rodrigues char *p, *s, *val; 7288fae3551SRodney W. Grimes 7298fae3551SRodney W. Grimes for (s = options; (p = strsep(&s, ",")) != NULL;) 73018af6044SJoseph Koshy if (*p != '\0') { 731d9fa6ce7SCraig Rodrigues if (strcmp(p, "noauto") == 0) { 732d9fa6ce7SCraig Rodrigues /* 733d9fa6ce7SCraig Rodrigues * Do not pass noauto option to nmount(). 734d9fa6ce7SCraig Rodrigues * or external mount program. noauto is 735d9fa6ce7SCraig Rodrigues * only used to prevent mounting a filesystem 736d9fa6ce7SCraig Rodrigues * when 'mount -a' is specified, and is 737d9fa6ce7SCraig Rodrigues * not a real mount option. 738d9fa6ce7SCraig Rodrigues */ 739d9fa6ce7SCraig Rodrigues continue; 7404b4f9170SDag-Erling Smørgrav } else if (strcmp(p, "late") == 0) { 7414b4f9170SDag-Erling Smørgrav /* 7424b4f9170SDag-Erling Smørgrav * "late" is used to prevent certain file 7434b4f9170SDag-Erling Smørgrav * systems from being mounted before late 7444b4f9170SDag-Erling Smørgrav * in the boot cycle; for instance, 7454b4f9170SDag-Erling Smørgrav * loopback NFS mounts can't be mounted 7464b4f9170SDag-Erling Smørgrav * before mountd starts. 7474b4f9170SDag-Erling Smørgrav */ 7484b4f9170SDag-Erling Smørgrav continue; 749c7383075SXin LI } else if (strcmp(p, "failok") == 0) { 750c7383075SXin LI /* 751c7383075SXin LI * "failok" is used to prevent certain file 752c7383075SXin LI * systems from being causing the system to 753c7383075SXin LI * drop into single user mode in the boot 754c7383075SXin LI * cycle, and is not a real mount option. 755c7383075SXin LI */ 756c7383075SXin LI continue; 757c7835769SCraig Rodrigues } else if (strncmp(p, "mountprog", 9) == 0) { 758c7835769SCraig Rodrigues /* 759c7835769SCraig Rodrigues * "mountprog" is used to force the use of 760c7835769SCraig Rodrigues * userland mount programs. 761c7835769SCraig Rodrigues */ 762c7835769SCraig Rodrigues val = strchr(p, '='); 763c7835769SCraig Rodrigues if (val != NULL) { 764c7835769SCraig Rodrigues ++val; 765c7835769SCraig Rodrigues if (*val != '\0') 766c7835769SCraig Rodrigues mountprog = strdup(val); 767c7835769SCraig Rodrigues } 768c7835769SCraig Rodrigues 769c7835769SCraig Rodrigues if (mountprog == NULL) { 770c7835769SCraig Rodrigues errx(1, "Need value for -o mountprog"); 771c7835769SCraig Rodrigues } 772c7835769SCraig Rodrigues continue; 77335d6c7f5SCraig Rodrigues } else if (strcmp(p, "userquota") == 0) { 77435d6c7f5SCraig Rodrigues continue; 7756e74fb9dSMaxim Konovalov } else if (strncmp(p, userquotaeq, 7766e74fb9dSMaxim Konovalov sizeof(userquotaeq) - 1) == 0) { 7776e74fb9dSMaxim Konovalov continue; 77835d6c7f5SCraig Rodrigues } else if (strcmp(p, "groupquota") == 0) { 77935d6c7f5SCraig Rodrigues continue; 7806e74fb9dSMaxim Konovalov } else if (strncmp(p, groupquotaeq, 7816e74fb9dSMaxim Konovalov sizeof(groupquotaeq) - 1) == 0) { 7826e74fb9dSMaxim Konovalov continue; 783d9fa6ce7SCraig Rodrigues } else if (*p == '-') { 784a86de995SDavid E. O'Brien append_arg(a, p); 7858fae3551SRodney W. Grimes p = strchr(p, '='); 786adfdbe22STom Rhodes if (p != NULL) { 7878fae3551SRodney W. Grimes *p = '\0'; 788a86de995SDavid E. O'Brien append_arg(a, p + 1); 7898fae3551SRodney W. Grimes } 790748e259bSCraig Rodrigues } else { 791a86de995SDavid E. O'Brien append_arg(a, strdup("-o")); 792a86de995SDavid E. O'Brien append_arg(a, p); 7938fae3551SRodney W. Grimes } 79418af6044SJoseph Koshy } 7958fae3551SRodney W. Grimes } 7968fae3551SRodney W. Grimes 79718af6044SJoseph Koshy 79818af6044SJoseph Koshy char * 7994796c6ccSJuli Mallett update_options(char *opts, char *fstab, int curflags) 80018af6044SJoseph Koshy { 80118af6044SJoseph Koshy char *o, *p; 80218af6044SJoseph Koshy char *cur; 80318af6044SJoseph Koshy char *expopt, *newopt, *tmpopt; 80418af6044SJoseph Koshy 80518af6044SJoseph Koshy if (opts == NULL) 8064796c6ccSJuli Mallett return (strdup("")); 80718af6044SJoseph Koshy 80818af6044SJoseph Koshy /* remove meta options from list */ 80918af6044SJoseph Koshy remopt(fstab, MOUNT_META_OPTION_FSTAB); 81018af6044SJoseph Koshy remopt(fstab, MOUNT_META_OPTION_CURRENT); 81118af6044SJoseph Koshy cur = flags2opts(curflags); 81218af6044SJoseph Koshy 81318af6044SJoseph Koshy /* 81418af6044SJoseph Koshy * Expand all meta-options passed to us first. 81518af6044SJoseph Koshy */ 81618af6044SJoseph Koshy expopt = NULL; 81718af6044SJoseph Koshy for (p = opts; (o = strsep(&p, ",")) != NULL;) { 81818af6044SJoseph Koshy if (strcmp(MOUNT_META_OPTION_FSTAB, o) == 0) 81918af6044SJoseph Koshy expopt = catopt(expopt, fstab); 82018af6044SJoseph Koshy else if (strcmp(MOUNT_META_OPTION_CURRENT, o) == 0) 82118af6044SJoseph Koshy expopt = catopt(expopt, cur); 82218af6044SJoseph Koshy else 82318af6044SJoseph Koshy expopt = catopt(expopt, o); 82418af6044SJoseph Koshy } 82518af6044SJoseph Koshy free(cur); 82618af6044SJoseph Koshy free(opts); 82718af6044SJoseph Koshy 82818af6044SJoseph Koshy /* 82918af6044SJoseph Koshy * Remove previous contradictory arguments. Given option "foo" we 83018af6044SJoseph Koshy * remove all the "nofoo" options. Given "nofoo" we remove "nonofoo" 83118af6044SJoseph Koshy * and "foo" - so we can deal with possible options like "notice". 83218af6044SJoseph Koshy */ 83318af6044SJoseph Koshy newopt = NULL; 83418af6044SJoseph Koshy for (p = expopt; (o = strsep(&p, ",")) != NULL;) { 83518af6044SJoseph Koshy if ((tmpopt = malloc( strlen(o) + 2 + 1 )) == NULL) 83618af6044SJoseph Koshy errx(1, "malloc failed"); 83718af6044SJoseph Koshy 83818af6044SJoseph Koshy strcpy(tmpopt, "no"); 83918af6044SJoseph Koshy strcat(tmpopt, o); 84018af6044SJoseph Koshy remopt(newopt, tmpopt); 84118af6044SJoseph Koshy free(tmpopt); 84218af6044SJoseph Koshy 84318af6044SJoseph Koshy if (strncmp("no", o, 2) == 0) 84418af6044SJoseph Koshy remopt(newopt, o+2); 84518af6044SJoseph Koshy 84618af6044SJoseph Koshy newopt = catopt(newopt, o); 84718af6044SJoseph Koshy } 84818af6044SJoseph Koshy free(expopt); 84918af6044SJoseph Koshy 8504796c6ccSJuli Mallett return (newopt); 85118af6044SJoseph Koshy } 85218af6044SJoseph Koshy 85318af6044SJoseph Koshy void 8544796c6ccSJuli Mallett remopt(char *string, const char *opt) 85518af6044SJoseph Koshy { 85618af6044SJoseph Koshy char *o, *p, *r; 85718af6044SJoseph Koshy 85818af6044SJoseph Koshy if (string == NULL || *string == '\0' || opt == NULL || *opt == '\0') 85918af6044SJoseph Koshy return; 86018af6044SJoseph Koshy 86118af6044SJoseph Koshy r = string; 86218af6044SJoseph Koshy 86318af6044SJoseph Koshy for (p = string; (o = strsep(&p, ",")) != NULL;) { 86418af6044SJoseph Koshy if (strcmp(opt, o) != 0) { 86518af6044SJoseph Koshy if (*r == ',' && *o != '\0') 86618af6044SJoseph Koshy r++; 86718af6044SJoseph Koshy while ((*r++ = *o++) != '\0') 86818af6044SJoseph Koshy ; 86918af6044SJoseph Koshy *--r = ','; 87018af6044SJoseph Koshy } 87118af6044SJoseph Koshy } 87218af6044SJoseph Koshy *r = '\0'; 87318af6044SJoseph Koshy } 87418af6044SJoseph Koshy 8758fae3551SRodney W. Grimes void 8764796c6ccSJuli Mallett usage(void) 8778fae3551SRodney W. Grimes { 8788fae3551SRodney W. Grimes 879bcb1d846SPhilippe Charnier (void)fprintf(stderr, "%s\n%s\n%s\n", 8804b4f9170SDag-Erling Smørgrav "usage: mount [-adflpruvw] [-F fstab] [-o options] [-t ufs | external_type]", 8818d646af5SRuslan Ermilov " mount [-dfpruvw] special | node", 8828d646af5SRuslan Ermilov " mount [-dfpruvw] [-o options] [-t ufs | external_type] special node"); 8838fae3551SRodney W. Grimes exit(1); 8848fae3551SRodney W. Grimes } 885a257a45eSJordan K. Hubbard 886a257a45eSJordan K. Hubbard void 887031ea52fSMatteo Riondato putfsent(struct statfs *ent) 888a257a45eSJordan K. Hubbard { 889a257a45eSJordan K. Hubbard struct fstab *fst; 89072da5470SJaakko Heinonen char *opts, *rw; 891306d73d6SPoul-Henning Kamp int l; 892a257a45eSJordan K. Hubbard 89372da5470SJaakko Heinonen opts = NULL; 89472da5470SJaakko Heinonen /* flags2opts() doesn't return the "rw" option. */ 89572da5470SJaakko Heinonen if ((ent->f_flags & MNT_RDONLY) != 0) 89672da5470SJaakko Heinonen rw = NULL; 89772da5470SJaakko Heinonen else 89872da5470SJaakko Heinonen rw = catopt(NULL, "rw"); 89972da5470SJaakko Heinonen 90018af6044SJoseph Koshy opts = flags2opts(ent->f_flags); 90172da5470SJaakko Heinonen opts = catopt(rw, opts); 9023ae7ea68SGiorgos Keramidas 903031ea52fSMatteo Riondato if (strncmp(ent->f_mntfromname, "<below>", 7) == 0 || 904031ea52fSMatteo Riondato strncmp(ent->f_mntfromname, "<above>", 7) == 0) { 905*6e24000aSAlan Somers strlcpy(ent->f_mntfromname, 906*6e24000aSAlan Somers (strnstr(ent->f_mntfromname, ":", 8) +1), 907*6e24000aSAlan Somers sizeof(ent->f_mntfromname)); 908031ea52fSMatteo Riondato } 909031ea52fSMatteo Riondato 910306d73d6SPoul-Henning Kamp l = strlen(ent->f_mntfromname); 911306d73d6SPoul-Henning Kamp printf("%s%s%s%s", ent->f_mntfromname, 912306d73d6SPoul-Henning Kamp l < 8 ? "\t" : "", 913306d73d6SPoul-Henning Kamp l < 16 ? "\t" : "", 914306d73d6SPoul-Henning Kamp l < 24 ? "\t" : " "); 915306d73d6SPoul-Henning Kamp l = strlen(ent->f_mntonname); 916306d73d6SPoul-Henning Kamp printf("%s%s%s%s", ent->f_mntonname, 917306d73d6SPoul-Henning Kamp l < 8 ? "\t" : "", 918306d73d6SPoul-Henning Kamp l < 16 ? "\t" : "", 919306d73d6SPoul-Henning Kamp l < 24 ? "\t" : " "); 920306d73d6SPoul-Henning Kamp printf("%s\t", ent->f_fstypename); 921306d73d6SPoul-Henning Kamp l = strlen(opts); 922306d73d6SPoul-Henning Kamp printf("%s%s", opts, 923306d73d6SPoul-Henning Kamp l < 8 ? "\t" : " "); 92418af6044SJoseph Koshy free(opts); 925c06fe0a0SPeter Wemm 926fba1c154SSteve Price if ((fst = getfsspec(ent->f_mntfromname))) 927a257a45eSJordan K. Hubbard printf("\t%u %u\n", fst->fs_freq, fst->fs_passno); 928fba1c154SSteve Price else if ((fst = getfsfile(ent->f_mntonname))) 929a257a45eSJordan K. Hubbard printf("\t%u %u\n", fst->fs_freq, fst->fs_passno); 930ab80d6faSBrian Feldman else if (strcmp(ent->f_fstypename, "ufs") == 0) { 931ab80d6faSBrian Feldman if (strcmp(ent->f_mntonname, "/") == 0) 932a257a45eSJordan K. Hubbard printf("\t1 1\n"); 933a257a45eSJordan K. Hubbard else 934ab80d6faSBrian Feldman printf("\t2 2\n"); 935ab80d6faSBrian Feldman } else 936a257a45eSJordan K. Hubbard printf("\t0 0\n"); 937a257a45eSJordan K. Hubbard } 93818af6044SJoseph Koshy 93918af6044SJoseph Koshy 94018af6044SJoseph Koshy char * 9414796c6ccSJuli Mallett flags2opts(int flags) 94218af6044SJoseph Koshy { 94318af6044SJoseph Koshy char *res; 94418af6044SJoseph Koshy 94518af6044SJoseph Koshy res = NULL; 94618af6044SJoseph Koshy 94788e2c335SCraig Rodrigues if (flags & MNT_RDONLY) res = catopt(res, "ro"); 94818af6044SJoseph Koshy if (flags & MNT_SYNCHRONOUS) res = catopt(res, "sync"); 94918af6044SJoseph Koshy if (flags & MNT_NOEXEC) res = catopt(res, "noexec"); 95018af6044SJoseph Koshy if (flags & MNT_NOSUID) res = catopt(res, "nosuid"); 95118af6044SJoseph Koshy if (flags & MNT_UNION) res = catopt(res, "union"); 95218af6044SJoseph Koshy if (flags & MNT_ASYNC) res = catopt(res, "async"); 95318af6044SJoseph Koshy if (flags & MNT_NOATIME) res = catopt(res, "noatime"); 95418af6044SJoseph Koshy if (flags & MNT_NOCLUSTERR) res = catopt(res, "noclusterr"); 95518af6044SJoseph Koshy if (flags & MNT_NOCLUSTERW) res = catopt(res, "noclusterw"); 95618af6044SJoseph Koshy if (flags & MNT_NOSYMFOLLOW) res = catopt(res, "nosymfollow"); 95718af6044SJoseph Koshy if (flags & MNT_SUIDDIR) res = catopt(res, "suiddir"); 958ba0fbe96SRobert Watson if (flags & MNT_MULTILABEL) res = catopt(res, "multilabel"); 95903d94b50SRobert Watson if (flags & MNT_ACLS) res = catopt(res, "acls"); 9609340fc72SEdward Tomasz Napierala if (flags & MNT_NFS4ACLS) res = catopt(res, "nfsv4acls"); 96118af6044SJoseph Koshy 9624796c6ccSJuli Mallett return (res); 96318af6044SJoseph Koshy } 964