1fba1c154SSteve Price /*- 28a16b7a1SPedro F. Giffuni * SPDX-License-Identifier: BSD-3-Clause 38a16b7a1SPedro F. Giffuni * 48fae3551SRodney W. Grimes * Copyright (c) 1980, 1989, 1993, 1994 58fae3551SRodney W. Grimes * The Regents of the University of California. All rights reserved. 68fae3551SRodney W. Grimes * 78fae3551SRodney W. Grimes * Redistribution and use in source and binary forms, with or without 88fae3551SRodney W. Grimes * modification, are permitted provided that the following conditions 98fae3551SRodney W. Grimes * are met: 108fae3551SRodney W. Grimes * 1. Redistributions of source code must retain the above copyright 118fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer. 128fae3551SRodney W. Grimes * 2. Redistributions in binary form must reproduce the above copyright 138fae3551SRodney W. Grimes * notice, this list of conditions and the following disclaimer in the 148fae3551SRodney W. Grimes * documentation and/or other materials provided with the distribution. 15fbbd9655SWarner Losh * 3. Neither the name of the University nor the names of its contributors 168fae3551SRodney W. Grimes * may be used to endorse or promote products derived from this software 178fae3551SRodney W. Grimes * without specific prior written permission. 188fae3551SRodney W. Grimes * 198fae3551SRodney W. Grimes * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 208fae3551SRodney W. Grimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 218fae3551SRodney W. Grimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 228fae3551SRodney W. Grimes * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 238fae3551SRodney W. Grimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 248fae3551SRodney W. Grimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 258fae3551SRodney W. Grimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 268fae3551SRodney W. Grimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 278fae3551SRodney W. Grimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 288fae3551SRodney W. Grimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 298fae3551SRodney W. Grimes * SUCH DAMAGE. 308fae3551SRodney W. Grimes */ 318fae3551SRodney W. Grimes 328fae3551SRodney W. Grimes #ifndef lint 33fba1c154SSteve Price static const char copyright[] = 348fae3551SRodney W. Grimes "@(#) Copyright (c) 1980, 1989, 1993, 1994\n\ 358fae3551SRodney W. Grimes The Regents of the University of California. All rights reserved.\n"; 36fba1c154SSteve Price #if 0 37c06fe0a0SPeter Wemm static char sccsid[] = "@(#)mount.c 8.25 (Berkeley) 5/8/95"; 38fba1c154SSteve Price #endif 398fae3551SRodney W. Grimes #endif /* not lint */ 408fae3551SRodney W. Grimes 4100356118SDavid E. O'Brien #include <sys/cdefs.h> 4200356118SDavid E. O'Brien __FBSDID("$FreeBSD$"); 4300356118SDavid E. O'Brien 448fae3551SRodney W. Grimes #include <sys/param.h> 4508b242aeSWarner Losh #define _WANT_MNTOPTNAMES 468fae3551SRodney W. Grimes #include <sys/mount.h> 478a978495SDavid Greenman #include <sys/stat.h> 4874cf460bSBruce Evans #include <sys/wait.h> 498fae3551SRodney W. Grimes 50003dbca6SMaxime Henrion #include <ctype.h> 518fae3551SRodney W. Grimes #include <err.h> 528fae3551SRodney W. Grimes #include <errno.h> 538fae3551SRodney W. Grimes #include <fstab.h> 54a3ba4c65SGordon Tetlow #include <paths.h> 55c06fe0a0SPeter Wemm #include <pwd.h> 568fae3551SRodney W. Grimes #include <signal.h> 5796c65ccbSIan Dowse #include <stdint.h> 588fae3551SRodney W. Grimes #include <stdio.h> 598fae3551SRodney W. Grimes #include <stdlib.h> 608fae3551SRodney W. Grimes #include <string.h> 618fae3551SRodney W. Grimes #include <unistd.h> 62e9988cedSPawel Jakub Dawidek #include <libutil.h> 63e725ee7eSCameron Katri #include <libxo/xo.h> 648fae3551SRodney W. Grimes 65fba1c154SSteve Price #include "extern.h" 6673dd3167SPoul-Henning Kamp #include "mntopts.h" 678fae3551SRodney W. Grimes #include "pathnames.h" 688fae3551SRodney W. Grimes 69e725ee7eSCameron Katri #define EXIT(a) { \ 70e725ee7eSCameron Katri xo_close_container("mount"); \ 71e725ee7eSCameron Katri xo_finish(); \ 72e725ee7eSCameron Katri exit(a); \ 73e725ee7eSCameron Katri } 74e725ee7eSCameron Katri 7518af6044SJoseph Koshy /* `meta' options */ 7618af6044SJoseph Koshy #define MOUNT_META_OPTION_FSTAB "fstab" 7718af6044SJoseph Koshy #define MOUNT_META_OPTION_CURRENT "current" 7818af6044SJoseph Koshy 791efe3c6bSEd Schouten static int debug, fstab_style, verbose; 80a257a45eSJordan K. Hubbard 81a86de995SDavid E. O'Brien struct cpa { 8200356118SDavid E. O'Brien char **a; 830e969ed7SDavid E. O'Brien ssize_t sz; 84a86de995SDavid E. O'Brien int c; 85a86de995SDavid E. O'Brien }; 86a86de995SDavid E. O'Brien 8785429990SWarner Losh char *catopt(char *, const char *); 8885429990SWarner Losh struct statfs *getmntpt(const char *); 8985429990SWarner Losh int hasopt(const char *, const char *); 9085429990SWarner Losh int ismounted(struct fstab *, struct statfs *, int); 9185429990SWarner Losh int isremountable(const char *); 92a86de995SDavid E. O'Brien void mangle(char *, struct cpa *); 9385429990SWarner Losh char *update_options(char *, char *, int); 9485429990SWarner Losh int mountfs(const char *, const char *, const char *, 9585429990SWarner Losh int, const char *, const char *); 9685429990SWarner Losh void remopt(char *, const char *); 9785429990SWarner Losh void prmount(struct statfs *); 98031ea52fSMatteo Riondato void putfsent(struct statfs *); 9985429990SWarner Losh void usage(void); 10085429990SWarner Losh char *flags2opts(int); 1018fae3551SRodney W. Grimes 102bcb1d846SPhilippe Charnier /* Map from mount options to printable formats. */ 10308b242aeSWarner Losh static struct mntoptnames optnames[] = { 10408b242aeSWarner Losh MNTOPT_NAMES 1058fae3551SRodney W. Grimes }; 1068fae3551SRodney W. Grimes 107fba1c154SSteve Price /* 108fba1c154SSteve Price * List of VFS types that can be remounted without becoming mounted on top 109fba1c154SSteve Price * of each other. 110fba1c154SSteve Price * XXX Is this list correct? 111fba1c154SSteve Price */ 112fba1c154SSteve Price static const char * 113fba1c154SSteve Price remountable_fs_names[] = { 1145a4420e3SAlexey Zelkin "ufs", "ffs", "ext2fs", 115fba1c154SSteve Price 0 116fba1c154SSteve Price }; 117fba1c154SSteve Price 1186e74fb9dSMaxim Konovalov static const char userquotaeq[] = "userquota="; 1196e74fb9dSMaxim Konovalov static const char groupquotaeq[] = "groupquota="; 1206e74fb9dSMaxim Konovalov 121c7835769SCraig Rodrigues static char *mountprog = NULL; 122c7835769SCraig Rodrigues 1236f5f1a6bSCraig Rodrigues static int 1246f5f1a6bSCraig Rodrigues use_mountprog(const char *vfstype) 1256f5f1a6bSCraig Rodrigues { 1266f5f1a6bSCraig Rodrigues /* XXX: We need to get away from implementing external mount 1276f5f1a6bSCraig Rodrigues * programs for every filesystem, and move towards having 1286f5f1a6bSCraig Rodrigues * each filesystem properly implement the nmount() system call. 1296f5f1a6bSCraig Rodrigues */ 1306f5f1a6bSCraig Rodrigues unsigned int i; 1316f5f1a6bSCraig Rodrigues const char *fs[] = { 132a42ac676SAttilio Rao "cd9660", "mfs", "msdosfs", "nfs", 1334e25c86fSEdward Tomasz Napierala "nullfs", "smbfs", "udf", "unionfs", 1346f5f1a6bSCraig Rodrigues NULL 1356f5f1a6bSCraig Rodrigues }; 1366f5f1a6bSCraig Rodrigues 137c7835769SCraig Rodrigues if (mountprog != NULL) 138c7835769SCraig Rodrigues return (1); 139c7835769SCraig Rodrigues 1406f5f1a6bSCraig Rodrigues for (i = 0; fs[i] != NULL; ++i) { 1416f5f1a6bSCraig Rodrigues if (strcmp(vfstype, fs[i]) == 0) 1424796c6ccSJuli Mallett return (1); 1436f5f1a6bSCraig Rodrigues } 1446f5f1a6bSCraig Rodrigues 1454796c6ccSJuli Mallett return (0); 1466f5f1a6bSCraig Rodrigues } 1476f5f1a6bSCraig Rodrigues 1486f5f1a6bSCraig Rodrigues static int 1494796c6ccSJuli Mallett exec_mountprog(const char *name, const char *execname, char *const argv[]) 1506f5f1a6bSCraig Rodrigues { 1516f5f1a6bSCraig Rodrigues pid_t pid; 1526f5f1a6bSCraig Rodrigues int status; 1536f5f1a6bSCraig Rodrigues 1546f5f1a6bSCraig Rodrigues switch (pid = fork()) { 1556f5f1a6bSCraig Rodrigues case -1: /* Error. */ 156e725ee7eSCameron Katri xo_warn("fork"); 157e725ee7eSCameron Katri EXIT(1); 1586f5f1a6bSCraig Rodrigues case 0: /* Child. */ 1596f5f1a6bSCraig Rodrigues /* Go find an executable. */ 1606f5f1a6bSCraig Rodrigues execvP(execname, _PATH_SYSPATH, argv); 1616f5f1a6bSCraig Rodrigues if (errno == ENOENT) { 162e725ee7eSCameron Katri xo_warn("exec %s not found", execname); 163c7835769SCraig Rodrigues if (execname[0] != '/') { 164e725ee7eSCameron Katri xo_warnx("in path: %s", _PATH_SYSPATH); 165c7835769SCraig Rodrigues } 1666f5f1a6bSCraig Rodrigues } 167e725ee7eSCameron Katri EXIT(1); 1686f5f1a6bSCraig Rodrigues default: /* Parent. */ 1696f5f1a6bSCraig Rodrigues if (waitpid(pid, &status, 0) < 0) { 170e725ee7eSCameron Katri xo_warn("waitpid"); 1716f5f1a6bSCraig Rodrigues return (1); 1726f5f1a6bSCraig Rodrigues } 1736f5f1a6bSCraig Rodrigues 1746f5f1a6bSCraig Rodrigues if (WIFEXITED(status)) { 1756f5f1a6bSCraig Rodrigues if (WEXITSTATUS(status) != 0) 1766f5f1a6bSCraig Rodrigues return (WEXITSTATUS(status)); 1776f5f1a6bSCraig Rodrigues } else if (WIFSIGNALED(status)) { 178e725ee7eSCameron Katri xo_warnx("%s: %s", name, sys_siglist[WTERMSIG(status)]); 1796f5f1a6bSCraig Rodrigues return (1); 1806f5f1a6bSCraig Rodrigues } 1816f5f1a6bSCraig Rodrigues break; 1826f5f1a6bSCraig Rodrigues } 1836f5f1a6bSCraig Rodrigues 1846f5f1a6bSCraig Rodrigues return (0); 1856f5f1a6bSCraig Rodrigues } 1866f5f1a6bSCraig Rodrigues 18749a41c4fSRuslan Ermilov static int 18849a41c4fSRuslan Ermilov specified_ro(const char *arg) 1893cbf527eSRuslan Ermilov { 1903cbf527eSRuslan Ermilov char *optbuf, *opt; 1913cbf527eSRuslan Ermilov int ret = 0; 1923cbf527eSRuslan Ermilov 1933cbf527eSRuslan Ermilov optbuf = strdup(arg); 1943cbf527eSRuslan Ermilov if (optbuf == NULL) 1959d324b5fSJohn Baldwin xo_err(1, "strdup failed"); 1963cbf527eSRuslan Ermilov 1973cbf527eSRuslan Ermilov for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) { 1983cbf527eSRuslan Ermilov if (strcmp(opt, "ro") == 0) { 1993cbf527eSRuslan Ermilov ret = 1; 2003cbf527eSRuslan Ermilov break; 2013cbf527eSRuslan Ermilov } 2023cbf527eSRuslan Ermilov } 2033cbf527eSRuslan Ermilov free(optbuf); 2043cbf527eSRuslan Ermilov return (ret); 2053cbf527eSRuslan Ermilov } 2063cbf527eSRuslan Ermilov 207e9988cedSPawel Jakub Dawidek static void 208e9988cedSPawel Jakub Dawidek restart_mountd(void) 209e9988cedSPawel Jakub Dawidek { 210e9988cedSPawel Jakub Dawidek struct pidfh *pfh; 211e9988cedSPawel Jakub Dawidek pid_t mountdpid; 212e9988cedSPawel Jakub Dawidek 2137bead17dSKonstantin Belousov mountdpid = 0; 214e9988cedSPawel Jakub Dawidek pfh = pidfile_open(_PATH_MOUNTDPID, 0600, &mountdpid); 215e9988cedSPawel Jakub Dawidek if (pfh != NULL) { 216e9988cedSPawel Jakub Dawidek /* Mountd is not running. */ 217e9988cedSPawel Jakub Dawidek pidfile_remove(pfh); 218e9988cedSPawel Jakub Dawidek return; 219e9988cedSPawel Jakub Dawidek } 220e9988cedSPawel Jakub Dawidek if (errno != EEXIST) { 221e9988cedSPawel Jakub Dawidek /* Cannot open pidfile for some reason. */ 222e9988cedSPawel Jakub Dawidek return; 223e9988cedSPawel Jakub Dawidek } 2247bead17dSKonstantin Belousov 2257bead17dSKonstantin Belousov /* 2267bead17dSKonstantin Belousov * Refuse to send broadcast or group signals, this has 2277bead17dSKonstantin Belousov * happened due to the bugs in pidfile(3). 2287bead17dSKonstantin Belousov */ 2297bead17dSKonstantin Belousov if (mountdpid <= 0) { 230e725ee7eSCameron Katri xo_warnx("mountd pid %d, refusing to send SIGHUP", mountdpid); 2317bead17dSKonstantin Belousov return; 2327bead17dSKonstantin Belousov } 2337bead17dSKonstantin Belousov 234e9988cedSPawel Jakub Dawidek /* We have mountd(8) PID in mountdpid varible, let's signal it. */ 235e9988cedSPawel Jakub Dawidek if (kill(mountdpid, SIGHUP) == -1) 236e725ee7eSCameron Katri xo_err(1, "signal mountd"); 237e9988cedSPawel Jakub Dawidek } 238e9988cedSPawel Jakub Dawidek 2398fae3551SRodney W. Grimes int 240e24dc56aSCraig Rodrigues main(int argc, char *argv[]) 2418fae3551SRodney W. Grimes { 242c06fe0a0SPeter Wemm const char *mntfromname, **vfslist, *vfstype; 2438fae3551SRodney W. Grimes struct fstab *fs; 2448fae3551SRodney W. Grimes struct statfs *mntbuf; 245c7383075SXin LI int all, ch, i, init_flags, late, failok, mntsize, rval, have_fstab, ro; 246b48b774fSChris Rees int onlylate; 247003dbca6SMaxime Henrion char *cp, *ep, *options; 2488fae3551SRodney W. Grimes 249b48b774fSChris Rees all = init_flags = late = onlylate = 0; 2503cbf527eSRuslan Ermilov ro = 0; 2513cbf527eSRuslan Ermilov options = NULL; 2528fae3551SRodney W. Grimes vfslist = NULL; 2538fae3551SRodney W. Grimes vfstype = "ufs"; 254e725ee7eSCameron Katri 255e725ee7eSCameron Katri argc = xo_parse_args(argc, argv); 256e725ee7eSCameron Katri if (argc < 0) 257e725ee7eSCameron Katri exit(1); 258e725ee7eSCameron Katri xo_open_container("mount"); 259e725ee7eSCameron Katri 260fc98db27SRobert Millan while ((ch = getopt(argc, argv, "adF:fLlno:prt:uvw")) != -1) 2618fae3551SRodney W. Grimes switch (ch) { 2628fae3551SRodney W. Grimes case 'a': 2638fae3551SRodney W. Grimes all = 1; 2648fae3551SRodney W. Grimes break; 2658fae3551SRodney W. Grimes case 'd': 2668fae3551SRodney W. Grimes debug = 1; 2678fae3551SRodney W. Grimes break; 268ef258dd9SMatthew N. Dodd case 'F': 269ef258dd9SMatthew N. Dodd setfstab(optarg); 270ef258dd9SMatthew N. Dodd break; 2718fae3551SRodney W. Grimes case 'f': 2728fae3551SRodney W. Grimes init_flags |= MNT_FORCE; 2738fae3551SRodney W. Grimes break; 274b48b774fSChris Rees case 'L': 275b48b774fSChris Rees onlylate = 1; 276b48b774fSChris Rees late = 1; 277b48b774fSChris Rees break; 2784b4f9170SDag-Erling Smørgrav case 'l': 2794b4f9170SDag-Erling Smørgrav late = 1; 2804b4f9170SDag-Erling Smørgrav break; 281fc98db27SRobert Millan case 'n': 282fc98db27SRobert Millan /* For compatibility with the Linux version of mount. */ 283fc98db27SRobert Millan break; 2848fae3551SRodney W. Grimes case 'o': 2853cbf527eSRuslan Ermilov if (*optarg) { 2868fae3551SRodney W. Grimes options = catopt(options, optarg); 2873cbf527eSRuslan Ermilov if (specified_ro(optarg)) 2883cbf527eSRuslan Ermilov ro = 1; 2893cbf527eSRuslan Ermilov } 2908fae3551SRodney W. Grimes break; 29174cf460bSBruce Evans case 'p': 29274cf460bSBruce Evans fstab_style = 1; 29374cf460bSBruce Evans verbose = 1; 29474cf460bSBruce Evans break; 2958fae3551SRodney W. Grimes case 'r': 296ad044771SDima Dorfman options = catopt(options, "ro"); 2973cbf527eSRuslan Ermilov ro = 1; 2988fae3551SRodney W. Grimes break; 2998fae3551SRodney W. Grimes case 't': 3008fae3551SRodney W. Grimes if (vfslist != NULL) 301e725ee7eSCameron Katri xo_errx(1, "only one -t option may be specified"); 3028fae3551SRodney W. Grimes vfslist = makevfslist(optarg); 3038fae3551SRodney W. Grimes vfstype = optarg; 3048fae3551SRodney W. Grimes break; 3058fae3551SRodney W. Grimes case 'u': 3068fae3551SRodney W. Grimes init_flags |= MNT_UPDATE; 3078fae3551SRodney W. Grimes break; 3088fae3551SRodney W. Grimes case 'v': 3098fae3551SRodney W. Grimes verbose = 1; 3108fae3551SRodney W. Grimes break; 3118fae3551SRodney W. Grimes case 'w': 312ad044771SDima Dorfman options = catopt(options, "noro"); 3138fae3551SRodney W. Grimes break; 3148fae3551SRodney W. Grimes case '?': 3158fae3551SRodney W. Grimes default: 3168fae3551SRodney W. Grimes usage(); 3178fae3551SRodney W. Grimes /* NOTREACHED */ 3188fae3551SRodney W. Grimes } 3198fae3551SRodney W. Grimes argc -= optind; 3208fae3551SRodney W. Grimes argv += optind; 3218fae3551SRodney W. Grimes 3228fae3551SRodney W. Grimes #define BADTYPE(type) \ 3238fae3551SRodney W. Grimes (strcmp(type, FSTAB_RO) && \ 3248fae3551SRodney W. Grimes strcmp(type, FSTAB_RW) && strcmp(type, FSTAB_RQ)) 3258fae3551SRodney W. Grimes 3263cbf527eSRuslan Ermilov if ((init_flags & MNT_UPDATE) && (ro == 0)) 3273cbf527eSRuslan Ermilov options = catopt(options, "noro"); 3283cbf527eSRuslan Ermilov 3298fae3551SRodney W. Grimes rval = 0; 3308fae3551SRodney W. Grimes switch (argc) { 3318fae3551SRodney W. Grimes case 0: 3324818bd98SKirk McKusick if ((mntsize = getmntinfo(&mntbuf, 3334818bd98SKirk McKusick verbose ? MNT_WAIT : MNT_NOWAIT)) == 0) 334e725ee7eSCameron Katri xo_err(1, "getmntinfo"); 335fba1c154SSteve Price if (all) { 3368fae3551SRodney W. Grimes while ((fs = getfsent()) != NULL) { 3378fae3551SRodney W. Grimes if (BADTYPE(fs->fs_type)) 3388fae3551SRodney W. Grimes continue; 339c06fe0a0SPeter Wemm if (checkvfsname(fs->fs_vfstype, vfslist)) 3408fae3551SRodney W. Grimes continue; 341c06fe0a0SPeter Wemm if (hasopt(fs->fs_mntops, "noauto")) 34289beb278SDavid Greenman continue; 343b48b774fSChris Rees if (!hasopt(fs->fs_mntops, "late") && onlylate) 344b48b774fSChris Rees continue; 3454b4f9170SDag-Erling Smørgrav if (hasopt(fs->fs_mntops, "late") && !late) 3464b4f9170SDag-Erling Smørgrav continue; 347c7383075SXin LI if (hasopt(fs->fs_mntops, "failok")) 348c7383075SXin LI failok = 1; 349c7383075SXin LI else 350c7383075SXin LI failok = 0; 35198201b0cSBruce Evans if (!(init_flags & MNT_UPDATE) && 352634add3cSMaxim Sobolev !hasopt(fs->fs_mntops, "update") && 35398201b0cSBruce Evans ismounted(fs, mntbuf, mntsize)) 354fba1c154SSteve Price continue; 35513cbdf24SGuido van Rooij options = update_options(options, fs->fs_mntops, 35613cbdf24SGuido van Rooij mntbuf->f_flags); 3578fae3551SRodney W. Grimes if (mountfs(fs->fs_vfstype, fs->fs_spec, 3588fae3551SRodney W. Grimes fs->fs_file, init_flags, options, 359c7383075SXin LI fs->fs_mntops) && !failok) 3608fae3551SRodney W. Grimes rval = 1; 3618fae3551SRodney W. Grimes } 362fba1c154SSteve Price } else if (fstab_style) { 363e725ee7eSCameron Katri xo_open_list("fstab"); 364a257a45eSJordan K. Hubbard for (i = 0; i < mntsize; i++) { 365c06fe0a0SPeter Wemm if (checkvfsname(mntbuf[i].f_fstypename, vfslist)) 366a257a45eSJordan K. Hubbard continue; 367e725ee7eSCameron Katri xo_open_instance("fstab"); 368a257a45eSJordan K. Hubbard putfsent(&mntbuf[i]); 369e725ee7eSCameron Katri xo_close_instance("fstab"); 370a257a45eSJordan K. Hubbard } 371e725ee7eSCameron Katri xo_close_list("fstab"); 37274cf460bSBruce Evans } else { 373e725ee7eSCameron Katri xo_open_list("mounted"); 3748fae3551SRodney W. Grimes for (i = 0; i < mntsize; i++) { 37574cf460bSBruce Evans if (checkvfsname(mntbuf[i].f_fstypename, 37674cf460bSBruce Evans vfslist)) 3778fae3551SRodney W. Grimes continue; 3788abb2a6eSPawel Jakub Dawidek if (!verbose && 3798abb2a6eSPawel Jakub Dawidek (mntbuf[i].f_flags & MNT_IGNORE) != 0) 3808abb2a6eSPawel Jakub Dawidek continue; 381e725ee7eSCameron Katri xo_open_instance("mounted"); 382c06fe0a0SPeter Wemm prmount(&mntbuf[i]); 383e725ee7eSCameron Katri xo_close_instance("mounted"); 3848fae3551SRodney W. Grimes } 385e725ee7eSCameron Katri xo_close_list("mounted"); 3868fae3551SRodney W. Grimes } 387e725ee7eSCameron Katri EXIT(rval); 3888fae3551SRodney W. Grimes case 1: 3898fae3551SRodney W. Grimes if (vfslist != NULL) 3908fae3551SRodney W. Grimes usage(); 3918fae3551SRodney W. Grimes 39201a9bce5SEric Anholt rmslashes(*argv, *argv); 3938fae3551SRodney W. Grimes if (init_flags & MNT_UPDATE) { 394cf96af72SBrian Feldman mntfromname = NULL; 395cf96af72SBrian Feldman have_fstab = 0; 3968fae3551SRodney W. Grimes if ((mntbuf = getmntpt(*argv)) == NULL) 397e725ee7eSCameron Katri xo_errx(1, "not currently mounted %s", *argv); 398cf96af72SBrian Feldman /* 399cf96af72SBrian Feldman * Only get the mntflags from fstab if both mntpoint 400cf96af72SBrian Feldman * and mntspec are identical. Also handle the special 401cf96af72SBrian Feldman * case where just '/' is mounted and 'spec' is not 402cf96af72SBrian Feldman * identical with the one from fstab ('/dev' is missing 403cf96af72SBrian Feldman * in the spec-string at boot-time). 404cf96af72SBrian Feldman */ 40518af6044SJoseph Koshy if ((fs = getfsfile(mntbuf->f_mntonname)) != NULL) { 406cf96af72SBrian Feldman if (strcmp(fs->fs_spec, 407cf96af72SBrian Feldman mntbuf->f_mntfromname) == 0 && 408cf96af72SBrian Feldman strcmp(fs->fs_file, 409cf96af72SBrian Feldman mntbuf->f_mntonname) == 0) { 410cf96af72SBrian Feldman have_fstab = 1; 411cf96af72SBrian Feldman mntfromname = mntbuf->f_mntfromname; 412cf96af72SBrian Feldman } else if (argv[0][0] == '/' && 4131f3aded0SEdward Tomasz Napierala argv[0][1] == '\0' && 4141f3aded0SEdward Tomasz Napierala strcmp(fs->fs_vfstype, 4151f3aded0SEdward Tomasz Napierala mntbuf->f_fstypename) == 0) { 416cf96af72SBrian Feldman fs = getfsfile("/"); 417cf96af72SBrian Feldman have_fstab = 1; 418c06fe0a0SPeter Wemm mntfromname = fs->fs_spec; 419cf96af72SBrian Feldman } 420cf96af72SBrian Feldman } 421cf96af72SBrian Feldman if (have_fstab) { 42218af6044SJoseph Koshy options = update_options(options, fs->fs_mntops, 42318af6044SJoseph Koshy mntbuf->f_flags); 42418af6044SJoseph Koshy } else { 425c06fe0a0SPeter Wemm mntfromname = mntbuf->f_mntfromname; 42618af6044SJoseph Koshy options = update_options(options, NULL, 42718af6044SJoseph Koshy mntbuf->f_flags); 42818af6044SJoseph Koshy } 429c06fe0a0SPeter Wemm rval = mountfs(mntbuf->f_fstypename, mntfromname, 430c06fe0a0SPeter Wemm mntbuf->f_mntonname, init_flags, options, 0); 431c06fe0a0SPeter Wemm break; 432c06fe0a0SPeter Wemm } 4338fae3551SRodney W. Grimes if ((fs = getfsfile(*argv)) == NULL && 4348fae3551SRodney W. Grimes (fs = getfsspec(*argv)) == NULL) 435e725ee7eSCameron Katri xo_errx(1, "%s: unknown special file or file system", 4368fae3551SRodney W. Grimes *argv); 4378fae3551SRodney W. Grimes if (BADTYPE(fs->fs_type)) 438e725ee7eSCameron Katri xo_errx(1, "%s has unknown file system type", 4398fae3551SRodney W. Grimes *argv); 440c06fe0a0SPeter Wemm rval = mountfs(fs->fs_vfstype, fs->fs_spec, fs->fs_file, 441c06fe0a0SPeter Wemm init_flags, options, fs->fs_mntops); 4428fae3551SRodney W. Grimes break; 4438fae3551SRodney W. Grimes case 2: 4448fae3551SRodney W. Grimes /* 445cf96af72SBrian Feldman * If -t flag has not been specified, the path cannot be 446003dbca6SMaxime Henrion * found, spec contains either a ':' or a '@', then assume 447cf96af72SBrian Feldman * that an NFS file system is being specified ala Sun. 448003dbca6SMaxime Henrion * Check if the hostname contains only allowed characters 449003dbca6SMaxime Henrion * to reduce false positives. IPv6 addresses containing 450003dbca6SMaxime Henrion * ':' will be correctly parsed only if the separator is '@'. 451003dbca6SMaxime Henrion * The definition of a valid hostname is taken from RFC 1034. 4528fae3551SRodney W. Grimes */ 45305779418SIan Dowse if (vfslist == NULL && ((ep = strchr(argv[0], '@')) != NULL || 45405779418SIan Dowse (ep = strchr(argv[0], ':')) != NULL)) { 455da85c82bSMaxime Henrion if (*ep == '@') { 456da85c82bSMaxime Henrion cp = ep + 1; 457da85c82bSMaxime Henrion ep = cp + strlen(cp); 458da85c82bSMaxime Henrion } else 459003dbca6SMaxime Henrion cp = argv[0]; 460003dbca6SMaxime Henrion while (cp != ep) { 461003dbca6SMaxime Henrion if (!isdigit(*cp) && !isalpha(*cp) && 462003dbca6SMaxime Henrion *cp != '.' && *cp != '-' && *cp != ':') 463003dbca6SMaxime Henrion break; 464003dbca6SMaxime Henrion cp++; 465003dbca6SMaxime Henrion } 466003dbca6SMaxime Henrion if (cp == ep) 4678fae3551SRodney W. Grimes vfstype = "nfs"; 468003dbca6SMaxime Henrion } 4698fae3551SRodney W. Grimes rval = mountfs(vfstype, 4708fae3551SRodney W. Grimes argv[0], argv[1], init_flags, options, NULL); 4718fae3551SRodney W. Grimes break; 4728fae3551SRodney W. Grimes default: 4738fae3551SRodney W. Grimes usage(); 4748fae3551SRodney W. Grimes /* NOTREACHED */ 4758fae3551SRodney W. Grimes } 4768fae3551SRodney W. Grimes 4778fae3551SRodney W. Grimes /* 4788fae3551SRodney W. Grimes * If the mount was successfully, and done by root, tell mountd the 479e9988cedSPawel Jakub Dawidek * good news. 4808fae3551SRodney W. Grimes */ 481e9988cedSPawel Jakub Dawidek if (rval == 0 && getuid() == 0) 482e9988cedSPawel Jakub Dawidek restart_mountd(); 4838fae3551SRodney W. Grimes 484e725ee7eSCameron Katri EXIT(rval); 4858fae3551SRodney W. Grimes } 4868fae3551SRodney W. Grimes 4878fae3551SRodney W. Grimes int 488e24dc56aSCraig Rodrigues ismounted(struct fstab *fs, struct statfs *mntbuf, int mntsize) 489fba1c154SSteve Price { 49090742659SPawel Jakub Dawidek char realfsfile[PATH_MAX]; 491fba1c154SSteve Price int i; 492fba1c154SSteve Price 493fba1c154SSteve Price if (fs->fs_file[0] == '/' && fs->fs_file[1] == '\0') 494fba1c154SSteve Price /* the root file system can always be remounted */ 495fba1c154SSteve Price return (0); 496fba1c154SSteve Price 49790742659SPawel Jakub Dawidek /* The user may have specified a symlink in fstab, resolve the path */ 49890742659SPawel Jakub Dawidek if (realpath(fs->fs_file, realfsfile) == NULL) { 49990742659SPawel Jakub Dawidek /* Cannot resolve the path, use original one */ 50090742659SPawel Jakub Dawidek strlcpy(realfsfile, fs->fs_file, sizeof(realfsfile)); 50190742659SPawel Jakub Dawidek } 50290742659SPawel Jakub Dawidek 503b5bbeb21SAlan Somers /* 504b5bbeb21SAlan Somers * Consider the filesystem to be mounted if: 505*c09770b2SGordon Bergling * It has the same mountpoint as a mounted filesystem, and 506b5bbeb21SAlan Somers * It has the same type as that same mounted filesystem, and 507b5bbeb21SAlan Somers * It has the same device name as that same mounted filesystem, OR 508b5bbeb21SAlan Somers * It is a nonremountable filesystem 509b5bbeb21SAlan Somers */ 510fba1c154SSteve Price for (i = mntsize - 1; i >= 0; --i) 51190742659SPawel Jakub Dawidek if (strcmp(realfsfile, mntbuf[i].f_mntonname) == 0 && 512b5bbeb21SAlan Somers strcmp(fs->fs_vfstype, mntbuf[i].f_fstypename) == 0 && 513fba1c154SSteve Price (!isremountable(fs->fs_vfstype) || 514b5bbeb21SAlan Somers (strcmp(fs->fs_spec, mntbuf[i].f_mntfromname) == 0))) 515fba1c154SSteve Price return (1); 516fba1c154SSteve Price return (0); 517fba1c154SSteve Price } 518fba1c154SSteve Price 519fba1c154SSteve Price int 520e24dc56aSCraig Rodrigues isremountable(const char *vfsname) 521fba1c154SSteve Price { 522fba1c154SSteve Price const char **cp; 523fba1c154SSteve Price 524fba1c154SSteve Price for (cp = remountable_fs_names; *cp; cp++) 525fba1c154SSteve Price if (strcmp(*cp, vfsname) == 0) 526fba1c154SSteve Price return (1); 527fba1c154SSteve Price return (0); 528fba1c154SSteve Price } 529fba1c154SSteve Price 530fba1c154SSteve Price int 531e24dc56aSCraig Rodrigues hasopt(const char *mntopts, const char *option) 532c06fe0a0SPeter Wemm { 533c06fe0a0SPeter Wemm int negative, found; 534c06fe0a0SPeter Wemm char *opt, *optbuf; 535c06fe0a0SPeter Wemm 536c06fe0a0SPeter Wemm if (option[0] == 'n' && option[1] == 'o') { 537c06fe0a0SPeter Wemm negative = 1; 538c06fe0a0SPeter Wemm option += 2; 539c06fe0a0SPeter Wemm } else 540c06fe0a0SPeter Wemm negative = 0; 541c06fe0a0SPeter Wemm optbuf = strdup(mntopts); 542c06fe0a0SPeter Wemm found = 0; 543c06fe0a0SPeter Wemm for (opt = optbuf; (opt = strtok(opt, ",")) != NULL; opt = NULL) { 544c06fe0a0SPeter Wemm if (opt[0] == 'n' && opt[1] == 'o') { 545c06fe0a0SPeter Wemm if (!strcasecmp(opt + 2, option)) 546c06fe0a0SPeter Wemm found = negative; 547c06fe0a0SPeter Wemm } else if (!strcasecmp(opt, option)) 548c06fe0a0SPeter Wemm found = !negative; 549c06fe0a0SPeter Wemm } 550c06fe0a0SPeter Wemm free(optbuf); 551c06fe0a0SPeter Wemm return (found); 552c06fe0a0SPeter Wemm } 553c06fe0a0SPeter Wemm 554a86de995SDavid E. O'Brien static void 555a86de995SDavid E. O'Brien append_arg(struct cpa *sa, char *arg) 556a86de995SDavid E. O'Brien { 5570e969ed7SDavid E. O'Brien if (sa->c + 1 == sa->sz) { 5580e969ed7SDavid E. O'Brien sa->sz = sa->sz == 0 ? 8 : sa->sz * 2; 559e96092e8SUlrich Spörlein sa->a = realloc(sa->a, sizeof(*sa->a) * sa->sz); 56000356118SDavid E. O'Brien if (sa->a == NULL) 561e725ee7eSCameron Katri xo_errx(1, "realloc failed"); 56200356118SDavid E. O'Brien } 563a86de995SDavid E. O'Brien sa->a[++sa->c] = arg; 564a86de995SDavid E. O'Brien } 565a86de995SDavid E. O'Brien 566c06fe0a0SPeter Wemm int 567e24dc56aSCraig Rodrigues mountfs(const char *vfstype, const char *spec, const char *name, int flags, 568e24dc56aSCraig Rodrigues const char *options, const char *mntopts) 5698fae3551SRodney W. Grimes { 5708fae3551SRodney W. Grimes struct statfs sf; 57176c46216SDavid E. O'Brien int i, ret; 57268dd1ff4SWarner Losh char *optbuf, execname[PATH_MAX], mntpath[PATH_MAX]; 5730e969ed7SDavid E. O'Brien static struct cpa mnt_argv; 5748fae3551SRodney W. Grimes 57573dd3167SPoul-Henning Kamp /* resolve the mountpoint with realpath(3) */ 576d3250014SJaakko Heinonen if (checkpath(name, mntpath) != 0) { 577e725ee7eSCameron Katri xo_warn("%s", mntpath); 578d3250014SJaakko Heinonen return (1); 579d3250014SJaakko Heinonen } 5808fae3551SRodney W. Grimes name = mntpath; 5818fae3551SRodney W. Grimes 582c06fe0a0SPeter Wemm if (mntopts == NULL) 583c06fe0a0SPeter Wemm mntopts = ""; 5848fae3551SRodney W. Grimes optbuf = catopt(strdup(mntopts), options); 5858fae3551SRodney W. Grimes 5868fae3551SRodney W. Grimes if (strcmp(name, "/") == 0) 5878fae3551SRodney W. Grimes flags |= MNT_UPDATE; 5888fae3551SRodney W. Grimes if (flags & MNT_FORCE) 5898fae3551SRodney W. Grimes optbuf = catopt(optbuf, "force"); 5908fae3551SRodney W. Grimes if (flags & MNT_RDONLY) 5918fae3551SRodney W. Grimes optbuf = catopt(optbuf, "ro"); 5928fae3551SRodney W. Grimes /* 5938fae3551SRodney W. Grimes * XXX 5948fae3551SRodney W. Grimes * The mount_mfs (newfs) command uses -o to select the 595bcb1d846SPhilippe Charnier * optimization mode. We don't pass the default "-o rw" 5968fae3551SRodney W. Grimes * for that reason. 5978fae3551SRodney W. Grimes */ 5988fae3551SRodney W. Grimes if (flags & MNT_UPDATE) 5998fae3551SRodney W. Grimes optbuf = catopt(optbuf, "update"); 6008fae3551SRodney W. Grimes 6014ccd7546SRuslan Ermilov /* Compatibility glue. */ 6020b8c3359SWarner Losh if (strcmp(vfstype, "msdos") == 0) 6034ccd7546SRuslan Ermilov vfstype = "msdosfs"; 6044ccd7546SRuslan Ermilov 6056e34b479SColin Percival /* Construct the name of the appropriate mount command */ 6066e34b479SColin Percival (void)snprintf(execname, sizeof(execname), "mount_%s", vfstype); 6076e34b479SColin Percival 608a86de995SDavid E. O'Brien mnt_argv.c = -1; 609a86de995SDavid E. O'Brien append_arg(&mnt_argv, execname); 610a86de995SDavid E. O'Brien mangle(optbuf, &mnt_argv); 611c7835769SCraig Rodrigues if (mountprog != NULL) 6126e24000aSAlan Somers strlcpy(execname, mountprog, sizeof(execname)); 613c7835769SCraig Rodrigues 614a86de995SDavid E. O'Brien append_arg(&mnt_argv, strdup(spec)); 615a86de995SDavid E. O'Brien append_arg(&mnt_argv, strdup(name)); 616a86de995SDavid E. O'Brien append_arg(&mnt_argv, NULL); 617fce5f960SDavid E. O'Brien 6188fae3551SRodney W. Grimes if (debug) { 619c195c7f6SCraig Rodrigues if (use_mountprog(vfstype)) 620e725ee7eSCameron Katri xo_emit("{Lwc:exec}{:execname/%s}", execname); 621c195c7f6SCraig Rodrigues else 622e725ee7eSCameron Katri xo_emit("{:execname/mount}{P: }{l:opts/-t}{P: }{l:opts/%s}", vfstype); 623a86de995SDavid E. O'Brien for (i = 1; i < mnt_argv.c; i++) 624e725ee7eSCameron Katri xo_emit("{P: }{l:opts}", mnt_argv.a[i]); 625e725ee7eSCameron Katri xo_emit("\n"); 626d2e17ce9SJohn Baldwin free(optbuf); 627d2e17ce9SJohn Baldwin free(mountprog); 628d2e17ce9SJohn Baldwin mountprog = NULL; 6298fae3551SRodney W. Grimes return (0); 6308fae3551SRodney W. Grimes } 6318fae3551SRodney W. Grimes 632b1e6b712SCraig Rodrigues if (use_mountprog(vfstype)) { 633a86de995SDavid E. O'Brien ret = exec_mountprog(name, execname, mnt_argv.a); 6346f5f1a6bSCraig Rodrigues } else { 635a86de995SDavid E. O'Brien ret = mount_fs(vfstype, mnt_argv.c, mnt_argv.a); 6366f5f1a6bSCraig Rodrigues } 6376f5f1a6bSCraig Rodrigues 6388fae3551SRodney W. Grimes free(optbuf); 639d2e17ce9SJohn Baldwin free(mountprog); 640d2e17ce9SJohn Baldwin mountprog = NULL; 6418fae3551SRodney W. Grimes 6428fae3551SRodney W. Grimes if (verbose) { 6438fae3551SRodney W. Grimes if (statfs(name, &sf) < 0) { 644e725ee7eSCameron Katri xo_warn("statfs %s", name); 6458fae3551SRodney W. Grimes return (1); 6468fae3551SRodney W. Grimes } 647e725ee7eSCameron Katri if (fstab_style) { 648e725ee7eSCameron Katri xo_open_list("fstab"); 649e725ee7eSCameron Katri xo_open_instance("fstab"); 650a257a45eSJordan K. Hubbard putfsent(&sf); 651e725ee7eSCameron Katri xo_close_instance("fstab"); 652e725ee7eSCameron Katri xo_close_list("fstab"); 653e725ee7eSCameron Katri } else { 654e725ee7eSCameron Katri xo_open_list("mounted"); 655e725ee7eSCameron Katri xo_open_instance("mounted"); 656c06fe0a0SPeter Wemm prmount(&sf); 657e725ee7eSCameron Katri xo_close_instance("mounted"); 658e725ee7eSCameron Katri xo_close_list("mounted"); 659e725ee7eSCameron Katri } 6608fae3551SRodney W. Grimes } 6618fae3551SRodney W. Grimes 662bbe9d7daSMatteo Riondato return (ret); 6638fae3551SRodney W. Grimes } 6648fae3551SRodney W. Grimes 6658fae3551SRodney W. Grimes void 666e24dc56aSCraig Rodrigues prmount(struct statfs *sfp) 6678fae3551SRodney W. Grimes { 6689df3a164SBjoern A. Zeeb uint64_t flags; 669aedf10acSCraig Rodrigues unsigned int i; 67008b242aeSWarner Losh struct mntoptnames *o; 671c06fe0a0SPeter Wemm struct passwd *pw; 672e725ee7eSCameron Katri char *fsidbuf; 6738fae3551SRodney W. Grimes 674260f26f0SPiotr Pawel Stefaniak xo_emit("{:special/%hs}{L: on }{:node/%hs}{L: (}{:fstype}", sfp->f_mntfromname, 675e725ee7eSCameron Katri sfp->f_mntonname, sfp->f_fstypename); 6768fae3551SRodney W. Grimes 677c06fe0a0SPeter Wemm flags = sfp->f_flags & MNT_VISFLAGMASK; 6789df3a164SBjoern A. Zeeb for (o = optnames; flags != 0 && o->o_opt != 0; o++) 6798fae3551SRodney W. Grimes if (flags & o->o_opt) { 680e725ee7eSCameron Katri xo_emit("{D:, }{l:opts}", o->o_name); 6818fae3551SRodney W. Grimes flags &= ~o->o_opt; 6828fae3551SRodney W. Grimes } 683dc9c6194SPawel Jakub Dawidek /* 684dc9c6194SPawel Jakub Dawidek * Inform when file system is mounted by an unprivileged user 685dc9c6194SPawel Jakub Dawidek * or privileged non-root user. 686dc9c6194SPawel Jakub Dawidek */ 687ddb842ccSJacques Vidrine if ((flags & MNT_USER) != 0 || sfp->f_owner != 0) { 688e725ee7eSCameron Katri xo_emit("{D:, }{L:mounted by }"); 689c06fe0a0SPeter Wemm if ((pw = getpwuid(sfp->f_owner)) != NULL) 690260f26f0SPiotr Pawel Stefaniak xo_emit("{:mounter/%hs}", pw->pw_name); 691c06fe0a0SPeter Wemm else 692260f26f0SPiotr Pawel Stefaniak xo_emit("{:mounter/%hs}", sfp->f_owner); 693c06fe0a0SPeter Wemm } 694c62ffab6SSheldon Hearn if (verbose) { 695e725ee7eSCameron Katri if (sfp->f_syncwrites != 0 || sfp->f_asyncwrites != 0) { 696e725ee7eSCameron Katri xo_open_container("writes"); 697e725ee7eSCameron Katri xo_emit("{D:, }{Lwc:writes}{Lw:sync}{w:sync/%ju}{Lw:async}{:async/%ju}", 69896c65ccbSIan Dowse (uintmax_t)sfp->f_syncwrites, 69996c65ccbSIan Dowse (uintmax_t)sfp->f_asyncwrites); 700e725ee7eSCameron Katri xo_close_container("writes"); 701e725ee7eSCameron Katri } 702e725ee7eSCameron Katri if (sfp->f_syncreads != 0 || sfp->f_asyncreads != 0) { 703e725ee7eSCameron Katri xo_open_container("reads"); 704e725ee7eSCameron Katri xo_emit("{D:, }{Lwc:reads}{Lw:sync}{w:sync/%ju}{Lw:async}{:async/%ju}", 70596c65ccbSIan Dowse (uintmax_t)sfp->f_syncreads, 70696c65ccbSIan Dowse (uintmax_t)sfp->f_asyncreads); 707e725ee7eSCameron Katri xo_close_container("reads"); 708e725ee7eSCameron Katri } 70905779418SIan Dowse if (sfp->f_fsid.val[0] != 0 || sfp->f_fsid.val[1] != 0) { 710e725ee7eSCameron Katri fsidbuf = malloc(sizeof(sfp->f_fsid) * 2 + 1); 711e725ee7eSCameron Katri if (fsidbuf == NULL) 712e725ee7eSCameron Katri xo_errx(1, "malloc failed"); 71338f102c2SIan Dowse for (i = 0; i < sizeof(sfp->f_fsid); i++) 714e725ee7eSCameron Katri sprintf(&fsidbuf[i * 2], "%02x", 715e725ee7eSCameron Katri ((u_char *)&sfp->f_fsid)[i]); 716e725ee7eSCameron Katri fsidbuf[i * 2] = '\0'; 717e725ee7eSCameron Katri xo_emit("{D:, }{Lw:fsid}{:fsid}", fsidbuf); 718e725ee7eSCameron Katri free(fsidbuf); 719c62ffab6SSheldon Hearn } 72005779418SIan Dowse } 721e725ee7eSCameron Katri xo_emit("{D:)}\n"); 7228fae3551SRodney W. Grimes } 7238fae3551SRodney W. Grimes 7248fae3551SRodney W. Grimes struct statfs * 725e24dc56aSCraig Rodrigues getmntpt(const char *name) 7268fae3551SRodney W. Grimes { 7278fae3551SRodney W. Grimes struct statfs *mntbuf; 7288fae3551SRodney W. Grimes int i, mntsize; 7298fae3551SRodney W. Grimes 730fddf7baeSKirk McKusick mntsize = getmntinfo(&mntbuf, MNT_NOWAIT); 731cf96af72SBrian Feldman for (i = mntsize - 1; i >= 0; i--) { 7328fae3551SRodney W. Grimes if (strcmp(mntbuf[i].f_mntfromname, name) == 0 || 7338fae3551SRodney W. Grimes strcmp(mntbuf[i].f_mntonname, name) == 0) 7348fae3551SRodney W. Grimes return (&mntbuf[i]); 735cf96af72SBrian Feldman } 7368fae3551SRodney W. Grimes return (NULL); 7378fae3551SRodney W. Grimes } 7388fae3551SRodney W. Grimes 7398fae3551SRodney W. Grimes char * 740e24dc56aSCraig Rodrigues catopt(char *s0, const char *s1) 7418fae3551SRodney W. Grimes { 7428fae3551SRodney W. Grimes char *cp; 7438fae3551SRodney W. Grimes 74418af6044SJoseph Koshy if (s1 == NULL || *s1 == '\0') 7454796c6ccSJuli Mallett return (s0); 74618af6044SJoseph Koshy 7478fae3551SRodney W. Grimes if (s0 && *s0) { 7488967299bSPedro F. Giffuni if (asprintf(&cp, "%s,%s", s0, s1) == -1) 749e725ee7eSCameron Katri xo_errx(1, "asprintf failed"); 7508fae3551SRodney W. Grimes } else 7518fae3551SRodney W. Grimes cp = strdup(s1); 7528fae3551SRodney W. Grimes 7538fae3551SRodney W. Grimes if (s0) 7548fae3551SRodney W. Grimes free(s0); 7558fae3551SRodney W. Grimes return (cp); 7568fae3551SRodney W. Grimes } 7578fae3551SRodney W. Grimes 7588fae3551SRodney W. Grimes void 759a86de995SDavid E. O'Brien mangle(char *options, struct cpa *a) 7608fae3551SRodney W. Grimes { 761c7835769SCraig Rodrigues char *p, *s, *val; 7628fae3551SRodney W. Grimes 7638fae3551SRodney W. Grimes for (s = options; (p = strsep(&s, ",")) != NULL;) 76418af6044SJoseph Koshy if (*p != '\0') { 765d9fa6ce7SCraig Rodrigues if (strcmp(p, "noauto") == 0) { 766d9fa6ce7SCraig Rodrigues /* 767d9fa6ce7SCraig Rodrigues * Do not pass noauto option to nmount(). 768d9fa6ce7SCraig Rodrigues * or external mount program. noauto is 769d9fa6ce7SCraig Rodrigues * only used to prevent mounting a filesystem 770d9fa6ce7SCraig Rodrigues * when 'mount -a' is specified, and is 771d9fa6ce7SCraig Rodrigues * not a real mount option. 772d9fa6ce7SCraig Rodrigues */ 773d9fa6ce7SCraig Rodrigues continue; 7744b4f9170SDag-Erling Smørgrav } else if (strcmp(p, "late") == 0) { 7754b4f9170SDag-Erling Smørgrav /* 7764b4f9170SDag-Erling Smørgrav * "late" is used to prevent certain file 7774b4f9170SDag-Erling Smørgrav * systems from being mounted before late 7784b4f9170SDag-Erling Smørgrav * in the boot cycle; for instance, 7794b4f9170SDag-Erling Smørgrav * loopback NFS mounts can't be mounted 7804b4f9170SDag-Erling Smørgrav * before mountd starts. 7814b4f9170SDag-Erling Smørgrav */ 7824b4f9170SDag-Erling Smørgrav continue; 783c7383075SXin LI } else if (strcmp(p, "failok") == 0) { 784c7383075SXin LI /* 785c7383075SXin LI * "failok" is used to prevent certain file 786c7383075SXin LI * systems from being causing the system to 787c7383075SXin LI * drop into single user mode in the boot 788c7383075SXin LI * cycle, and is not a real mount option. 789c7383075SXin LI */ 790c7383075SXin LI continue; 791c7835769SCraig Rodrigues } else if (strncmp(p, "mountprog", 9) == 0) { 792c7835769SCraig Rodrigues /* 793c7835769SCraig Rodrigues * "mountprog" is used to force the use of 794c7835769SCraig Rodrigues * userland mount programs. 795c7835769SCraig Rodrigues */ 796c7835769SCraig Rodrigues val = strchr(p, '='); 797c7835769SCraig Rodrigues if (val != NULL) { 798c7835769SCraig Rodrigues ++val; 799c7835769SCraig Rodrigues if (*val != '\0') 800c7835769SCraig Rodrigues mountprog = strdup(val); 801c7835769SCraig Rodrigues } 802c7835769SCraig Rodrigues 803c7835769SCraig Rodrigues if (mountprog == NULL) { 804e725ee7eSCameron Katri xo_errx(1, "Need value for -o mountprog"); 805c7835769SCraig Rodrigues } 806c7835769SCraig Rodrigues continue; 80735d6c7f5SCraig Rodrigues } else if (strcmp(p, "userquota") == 0) { 80835d6c7f5SCraig Rodrigues continue; 8096e74fb9dSMaxim Konovalov } else if (strncmp(p, userquotaeq, 8106e74fb9dSMaxim Konovalov sizeof(userquotaeq) - 1) == 0) { 8116e74fb9dSMaxim Konovalov continue; 81235d6c7f5SCraig Rodrigues } else if (strcmp(p, "groupquota") == 0) { 81335d6c7f5SCraig Rodrigues continue; 8146e74fb9dSMaxim Konovalov } else if (strncmp(p, groupquotaeq, 8156e74fb9dSMaxim Konovalov sizeof(groupquotaeq) - 1) == 0) { 8166e74fb9dSMaxim Konovalov continue; 817d9fa6ce7SCraig Rodrigues } else if (*p == '-') { 818a86de995SDavid E. O'Brien append_arg(a, p); 8198fae3551SRodney W. Grimes p = strchr(p, '='); 820adfdbe22STom Rhodes if (p != NULL) { 8218fae3551SRodney W. Grimes *p = '\0'; 822a86de995SDavid E. O'Brien append_arg(a, p + 1); 8238fae3551SRodney W. Grimes } 824748e259bSCraig Rodrigues } else { 825a86de995SDavid E. O'Brien append_arg(a, strdup("-o")); 826a86de995SDavid E. O'Brien append_arg(a, p); 8278fae3551SRodney W. Grimes } 82818af6044SJoseph Koshy } 8298fae3551SRodney W. Grimes } 8308fae3551SRodney W. Grimes 83118af6044SJoseph Koshy 83218af6044SJoseph Koshy char * 8334796c6ccSJuli Mallett update_options(char *opts, char *fstab, int curflags) 83418af6044SJoseph Koshy { 83518af6044SJoseph Koshy char *o, *p; 83618af6044SJoseph Koshy char *cur; 83718af6044SJoseph Koshy char *expopt, *newopt, *tmpopt; 83818af6044SJoseph Koshy 83918af6044SJoseph Koshy if (opts == NULL) 8404796c6ccSJuli Mallett return (strdup("")); 84118af6044SJoseph Koshy 84218af6044SJoseph Koshy /* remove meta options from list */ 84318af6044SJoseph Koshy remopt(fstab, MOUNT_META_OPTION_FSTAB); 84418af6044SJoseph Koshy remopt(fstab, MOUNT_META_OPTION_CURRENT); 84518af6044SJoseph Koshy cur = flags2opts(curflags); 84618af6044SJoseph Koshy 84718af6044SJoseph Koshy /* 84818af6044SJoseph Koshy * Expand all meta-options passed to us first. 84918af6044SJoseph Koshy */ 85018af6044SJoseph Koshy expopt = NULL; 85118af6044SJoseph Koshy for (p = opts; (o = strsep(&p, ",")) != NULL;) { 85218af6044SJoseph Koshy if (strcmp(MOUNT_META_OPTION_FSTAB, o) == 0) 85318af6044SJoseph Koshy expopt = catopt(expopt, fstab); 85418af6044SJoseph Koshy else if (strcmp(MOUNT_META_OPTION_CURRENT, o) == 0) 85518af6044SJoseph Koshy expopt = catopt(expopt, cur); 85618af6044SJoseph Koshy else 85718af6044SJoseph Koshy expopt = catopt(expopt, o); 85818af6044SJoseph Koshy } 85918af6044SJoseph Koshy free(cur); 86018af6044SJoseph Koshy free(opts); 86118af6044SJoseph Koshy 86218af6044SJoseph Koshy /* 86318af6044SJoseph Koshy * Remove previous contradictory arguments. Given option "foo" we 86418af6044SJoseph Koshy * remove all the "nofoo" options. Given "nofoo" we remove "nonofoo" 86518af6044SJoseph Koshy * and "foo" - so we can deal with possible options like "notice". 86618af6044SJoseph Koshy */ 86718af6044SJoseph Koshy newopt = NULL; 86818af6044SJoseph Koshy for (p = expopt; (o = strsep(&p, ",")) != NULL;) { 86918af6044SJoseph Koshy if ((tmpopt = malloc( strlen(o) + 2 + 1 )) == NULL) 870e725ee7eSCameron Katri xo_errx(1, "malloc failed"); 87118af6044SJoseph Koshy 87218af6044SJoseph Koshy strcpy(tmpopt, "no"); 87318af6044SJoseph Koshy strcat(tmpopt, o); 87418af6044SJoseph Koshy remopt(newopt, tmpopt); 87518af6044SJoseph Koshy free(tmpopt); 87618af6044SJoseph Koshy 87718af6044SJoseph Koshy if (strncmp("no", o, 2) == 0) 87818af6044SJoseph Koshy remopt(newopt, o+2); 87918af6044SJoseph Koshy 88018af6044SJoseph Koshy newopt = catopt(newopt, o); 88118af6044SJoseph Koshy } 88218af6044SJoseph Koshy free(expopt); 88318af6044SJoseph Koshy 8844796c6ccSJuli Mallett return (newopt); 88518af6044SJoseph Koshy } 88618af6044SJoseph Koshy 88718af6044SJoseph Koshy void 8884796c6ccSJuli Mallett remopt(char *string, const char *opt) 88918af6044SJoseph Koshy { 89018af6044SJoseph Koshy char *o, *p, *r; 89118af6044SJoseph Koshy 89218af6044SJoseph Koshy if (string == NULL || *string == '\0' || opt == NULL || *opt == '\0') 89318af6044SJoseph Koshy return; 89418af6044SJoseph Koshy 89518af6044SJoseph Koshy r = string; 89618af6044SJoseph Koshy 89718af6044SJoseph Koshy for (p = string; (o = strsep(&p, ",")) != NULL;) { 89818af6044SJoseph Koshy if (strcmp(opt, o) != 0) { 89918af6044SJoseph Koshy if (*r == ',' && *o != '\0') 90018af6044SJoseph Koshy r++; 90118af6044SJoseph Koshy while ((*r++ = *o++) != '\0') 90218af6044SJoseph Koshy ; 90318af6044SJoseph Koshy *--r = ','; 90418af6044SJoseph Koshy } 90518af6044SJoseph Koshy } 90618af6044SJoseph Koshy *r = '\0'; 90718af6044SJoseph Koshy } 90818af6044SJoseph Koshy 9098fae3551SRodney W. Grimes void 9104796c6ccSJuli Mallett usage(void) 9118fae3551SRodney W. Grimes { 9128fae3551SRodney W. Grimes 913e725ee7eSCameron Katri xo_error("%s\n%s\n%s\n", 9144b4f9170SDag-Erling Smørgrav "usage: mount [-adflpruvw] [-F fstab] [-o options] [-t ufs | external_type]", 9158d646af5SRuslan Ermilov " mount [-dfpruvw] special | node", 9168d646af5SRuslan Ermilov " mount [-dfpruvw] [-o options] [-t ufs | external_type] special node"); 917e725ee7eSCameron Katri EXIT(1); 9188fae3551SRodney W. Grimes } 919a257a45eSJordan K. Hubbard 920a257a45eSJordan K. Hubbard void 921031ea52fSMatteo Riondato putfsent(struct statfs *ent) 922a257a45eSJordan K. Hubbard { 923a257a45eSJordan K. Hubbard struct fstab *fst; 92472da5470SJaakko Heinonen char *opts, *rw; 925306d73d6SPoul-Henning Kamp int l; 926a257a45eSJordan K. Hubbard 92772da5470SJaakko Heinonen opts = NULL; 92872da5470SJaakko Heinonen /* flags2opts() doesn't return the "rw" option. */ 92972da5470SJaakko Heinonen if ((ent->f_flags & MNT_RDONLY) != 0) 93072da5470SJaakko Heinonen rw = NULL; 93172da5470SJaakko Heinonen else 93272da5470SJaakko Heinonen rw = catopt(NULL, "rw"); 93372da5470SJaakko Heinonen 93418af6044SJoseph Koshy opts = flags2opts(ent->f_flags); 93572da5470SJaakko Heinonen opts = catopt(rw, opts); 9363ae7ea68SGiorgos Keramidas 937031ea52fSMatteo Riondato if (strncmp(ent->f_mntfromname, "<below>", 7) == 0 || 938031ea52fSMatteo Riondato strncmp(ent->f_mntfromname, "<above>", 7) == 0) { 9396e24000aSAlan Somers strlcpy(ent->f_mntfromname, 9406e24000aSAlan Somers (strnstr(ent->f_mntfromname, ":", 8) +1), 9416e24000aSAlan Somers sizeof(ent->f_mntfromname)); 942031ea52fSMatteo Riondato } 943031ea52fSMatteo Riondato 944306d73d6SPoul-Henning Kamp l = strlen(ent->f_mntfromname); 945e725ee7eSCameron Katri xo_emit("{:device}{P:/%s}{P:/%s}{P:/%s}", 946e725ee7eSCameron Katri ent->f_mntfromname, 947306d73d6SPoul-Henning Kamp l < 8 ? "\t" : "", 948306d73d6SPoul-Henning Kamp l < 16 ? "\t" : "", 949306d73d6SPoul-Henning Kamp l < 24 ? "\t" : " "); 950306d73d6SPoul-Henning Kamp l = strlen(ent->f_mntonname); 951e725ee7eSCameron Katri xo_emit("{:mntpoint}{P:/%s}{P:/%s}{P:/%s}", 952e725ee7eSCameron Katri ent->f_mntonname, 953306d73d6SPoul-Henning Kamp l < 8 ? "\t" : "", 954306d73d6SPoul-Henning Kamp l < 16 ? "\t" : "", 955306d73d6SPoul-Henning Kamp l < 24 ? "\t" : " "); 956e725ee7eSCameron Katri xo_emit("{:fstype}{P:\t}", ent->f_fstypename); 957306d73d6SPoul-Henning Kamp l = strlen(opts); 958e725ee7eSCameron Katri xo_emit("{:opts}{P:/%s}", opts, 959306d73d6SPoul-Henning Kamp l < 8 ? "\t" : " "); 96018af6044SJoseph Koshy free(opts); 961c06fe0a0SPeter Wemm 962fba1c154SSteve Price if ((fst = getfsspec(ent->f_mntfromname))) 963e725ee7eSCameron Katri xo_emit("{P:\t}{n:dump/%u}{P: }{n:pass/%u}\n", 964e725ee7eSCameron Katri fst->fs_freq, fst->fs_passno); 965fba1c154SSteve Price else if ((fst = getfsfile(ent->f_mntonname))) 966e725ee7eSCameron Katri xo_emit("{P:\t}{n:dump/%u}{P: }{n:pass/%u}\n", 967e725ee7eSCameron Katri fst->fs_freq, fst->fs_passno); 968ab80d6faSBrian Feldman else if (strcmp(ent->f_fstypename, "ufs") == 0) { 969ab80d6faSBrian Feldman if (strcmp(ent->f_mntonname, "/") == 0) 970e725ee7eSCameron Katri xo_emit("{P:\t}{n:dump/1}{P: }{n:pass/1}\n"); 971a257a45eSJordan K. Hubbard else 972e725ee7eSCameron Katri xo_emit("{P:\t}{n:dump/2}{P: }{n:pass/2}\n"); 973ab80d6faSBrian Feldman } else 974e725ee7eSCameron Katri xo_emit("{P:\t}{n:dump/0}{P: }{n:pass/0}\n"); 975a257a45eSJordan K. Hubbard } 97618af6044SJoseph Koshy 97718af6044SJoseph Koshy 97818af6044SJoseph Koshy char * 9794796c6ccSJuli Mallett flags2opts(int flags) 98018af6044SJoseph Koshy { 98118af6044SJoseph Koshy char *res; 98218af6044SJoseph Koshy 98318af6044SJoseph Koshy res = NULL; 98418af6044SJoseph Koshy 98588e2c335SCraig Rodrigues if (flags & MNT_RDONLY) res = catopt(res, "ro"); 98618af6044SJoseph Koshy if (flags & MNT_SYNCHRONOUS) res = catopt(res, "sync"); 98718af6044SJoseph Koshy if (flags & MNT_NOEXEC) res = catopt(res, "noexec"); 98818af6044SJoseph Koshy if (flags & MNT_NOSUID) res = catopt(res, "nosuid"); 98918af6044SJoseph Koshy if (flags & MNT_UNION) res = catopt(res, "union"); 99018af6044SJoseph Koshy if (flags & MNT_ASYNC) res = catopt(res, "async"); 99118af6044SJoseph Koshy if (flags & MNT_NOATIME) res = catopt(res, "noatime"); 99218af6044SJoseph Koshy if (flags & MNT_NOCLUSTERR) res = catopt(res, "noclusterr"); 99318af6044SJoseph Koshy if (flags & MNT_NOCLUSTERW) res = catopt(res, "noclusterw"); 99418af6044SJoseph Koshy if (flags & MNT_NOSYMFOLLOW) res = catopt(res, "nosymfollow"); 99518af6044SJoseph Koshy if (flags & MNT_SUIDDIR) res = catopt(res, "suiddir"); 996ba0fbe96SRobert Watson if (flags & MNT_MULTILABEL) res = catopt(res, "multilabel"); 99703d94b50SRobert Watson if (flags & MNT_ACLS) res = catopt(res, "acls"); 9989340fc72SEdward Tomasz Napierala if (flags & MNT_NFS4ACLS) res = catopt(res, "nfsv4acls"); 999daba4da8SKirk McKusick if (flags & MNT_UNTRUSTED) res = catopt(res, "untrusted"); 1000ba7a55d9SSean Eric Fagan if (flags & MNT_NOCOVER) res = catopt(res, "nocover"); 1001ba7a55d9SSean Eric Fagan if (flags & MNT_EMPTYDIR) res = catopt(res, "emptydir"); 100218af6044SJoseph Koshy 10034796c6ccSJuli Mallett return (res); 100418af6044SJoseph Koshy } 1005