15fe58019SAttilio Rao /*-
2*4d846d26SWarner Losh * SPDX-License-Identifier: BSD-2-Clause
31de7b4b8SPedro F. Giffuni *
45fe58019SAttilio Rao * Copyright (c) 2005 Jean-Sebastien Pedron
55fe58019SAttilio Rao * Copyright (c) 2005 Csaba Henk
65fe58019SAttilio Rao * All rights reserved.
75fe58019SAttilio Rao *
88aafc8c3SAlan Somers * Copyright (c) 2019 The FreeBSD Foundation
98aafc8c3SAlan Somers *
108aafc8c3SAlan Somers * Portions of this software were developed by BFF Storage Systems under
118aafc8c3SAlan Somers * sponsorship from the FreeBSD Foundation.
128aafc8c3SAlan Somers *
135fe58019SAttilio Rao * Redistribution and use in source and binary forms, with or without
145fe58019SAttilio Rao * modification, are permitted provided that the following conditions
155fe58019SAttilio Rao * are met:
165fe58019SAttilio Rao * 1. Redistributions of source code must retain the above copyright
175fe58019SAttilio Rao * notice, this list of conditions and the following disclaimer.
185fe58019SAttilio Rao * 2. Redistributions in binary form must reproduce the above copyright
195fe58019SAttilio Rao * notice, this list of conditions and the following disclaimer in the
205fe58019SAttilio Rao * documentation and/or other materials provided with the distribution.
215fe58019SAttilio Rao *
225fe58019SAttilio Rao * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
235fe58019SAttilio Rao * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
245fe58019SAttilio Rao * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
255fe58019SAttilio Rao * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
265fe58019SAttilio Rao * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
275fe58019SAttilio Rao * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
285fe58019SAttilio Rao * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
295fe58019SAttilio Rao * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
305fe58019SAttilio Rao * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
315fe58019SAttilio Rao * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
325fe58019SAttilio Rao * SUCH DAMAGE.
335fe58019SAttilio Rao *
345fe58019SAttilio Rao */
355fe58019SAttilio Rao
365fe58019SAttilio Rao #include <sys/param.h>
375fe58019SAttilio Rao #include <sys/mount.h>
385fe58019SAttilio Rao #include <sys/uio.h>
395fe58019SAttilio Rao #include <sys/stat.h>
405fe58019SAttilio Rao #include <sys/sysctl.h>
415fe58019SAttilio Rao
425fe58019SAttilio Rao #include <err.h>
435fe58019SAttilio Rao #include <stdio.h>
445fe58019SAttilio Rao #include <stdlib.h>
455fe58019SAttilio Rao #include <string.h>
465fe58019SAttilio Rao #include <sysexits.h>
475fe58019SAttilio Rao #include <unistd.h>
485fe58019SAttilio Rao #include <fcntl.h>
495fe58019SAttilio Rao #include <signal.h>
505fe58019SAttilio Rao #include <getopt.h>
515fe58019SAttilio Rao #include <limits.h>
525fe58019SAttilio Rao #include <osreldate.h>
535fe58019SAttilio Rao #include <paths.h>
545fe58019SAttilio Rao
555fe58019SAttilio Rao #include "mntopts.h"
565fe58019SAttilio Rao
575fe58019SAttilio Rao #ifndef FUSE4BSD_VERSION
585fe58019SAttilio Rao #define FUSE4BSD_VERSION "0.3.9-pre1"
595fe58019SAttilio Rao #endif
605fe58019SAttilio Rao
615fe58019SAttilio Rao void __usage_short(void);
625fe58019SAttilio Rao void usage(void);
635fe58019SAttilio Rao void helpmsg(void);
645fe58019SAttilio Rao void showversion(void);
655fe58019SAttilio Rao
66ae824d80SEd Schouten static struct mntopt mopts[] = {
675fe58019SAttilio Rao #define ALTF_PRIVATE 0x01
685fe58019SAttilio Rao { "private", 0, ALTF_PRIVATE, 1 },
695fe58019SAttilio Rao { "neglect_shares", 0, 0x02, 1 },
705fe58019SAttilio Rao { "push_symlinks_in", 0, 0x04, 1 },
715fe58019SAttilio Rao { "allow_other", 0, 0x08, 1 },
725fe58019SAttilio Rao { "default_permissions", 0, 0x10, 1 },
735fe58019SAttilio Rao #define ALTF_MAXREAD 0x20
745fe58019SAttilio Rao { "max_read=", 0, ALTF_MAXREAD, 1 },
755fe58019SAttilio Rao #define ALTF_SUBTYPE 0x40
765fe58019SAttilio Rao { "subtype=", 0, ALTF_SUBTYPE, 1 },
772f636248SAlan Somers #define ALTF_FSNAME 0x80
782f636248SAlan Somers { "fsname=", 0, ALTF_FSNAME, 1 },
795e252f64SEdward Tomasz Napierala /*
805e252f64SEdward Tomasz Napierala * MOPT_AUTOMOUNTED, included by MOPT_STDOPTS, does not fit into
815e252f64SEdward Tomasz Napierala * the 'flags' argument to nmount(2). We have to abuse altflags
825e252f64SEdward Tomasz Napierala * to pass it, as string, via iovec.
835e252f64SEdward Tomasz Napierala */
845e252f64SEdward Tomasz Napierala #define ALTF_AUTOMOUNTED 0x100
855e252f64SEdward Tomasz Napierala { "automounted", 0, ALTF_AUTOMOUNTED, 1 },
86ed74f781SAlan Somers #define ALTF_INTR 0x200
87ed74f781SAlan Somers { "intr", 0, ALTF_INTR, 1 },
885fe58019SAttilio Rao /* Linux specific options, we silently ignore them */
895fe58019SAttilio Rao { "fd=", 0, 0x00, 1 },
905fe58019SAttilio Rao { "rootmode=", 0, 0x00, 1 },
915fe58019SAttilio Rao { "user_id=", 0, 0x00, 1 },
925fe58019SAttilio Rao { "group_id=", 0, 0x00, 1 },
935fe58019SAttilio Rao { "large_read", 0, 0x00, 1 },
945fe58019SAttilio Rao /* "nonempty", just the first two chars are stripped off during parsing */
955fe58019SAttilio Rao { "nempty", 0, 0x00, 1 },
968eecd9ceSAlan Somers { "async", 0, MNT_ASYNC, 0},
978eecd9ceSAlan Somers { "noasync", 1, MNT_ASYNC, 0},
985fe58019SAttilio Rao MOPT_STDOPTS,
995fe58019SAttilio Rao MOPT_END
1005fe58019SAttilio Rao };
1015fe58019SAttilio Rao
1025fe58019SAttilio Rao struct mntval {
1035fe58019SAttilio Rao int mv_flag;
1045fe58019SAttilio Rao void *mv_value;
1055fe58019SAttilio Rao int mv_len;
1065fe58019SAttilio Rao };
1075fe58019SAttilio Rao
108ae824d80SEd Schouten static struct mntval mvals[] = {
1095fe58019SAttilio Rao { ALTF_MAXREAD, NULL, 0 },
1105fe58019SAttilio Rao { ALTF_SUBTYPE, NULL, 0 },
1112f636248SAlan Somers { ALTF_FSNAME, NULL, 0 },
1125fe58019SAttilio Rao { 0, NULL, 0 }
1135fe58019SAttilio Rao };
1145fe58019SAttilio Rao
1154abf8766SAlan Somers #define DEFAULT_MOUNT_FLAGS ALTF_PRIVATE
1165fe58019SAttilio Rao
1175fe58019SAttilio Rao int
main(int argc,char * argv[])1185fe58019SAttilio Rao main(int argc, char *argv[])
1195fe58019SAttilio Rao {
1205fe58019SAttilio Rao struct iovec *iov;
1215fe58019SAttilio Rao int mntflags, iovlen, verbose = 0;
1225fe58019SAttilio Rao char *dev = NULL, *dir = NULL, mntpath[MAXPATHLEN];
1235fe58019SAttilio Rao char *devo = NULL, *diro = NULL;
1245fe58019SAttilio Rao char ndev[128], fdstr[15];
1255fe58019SAttilio Rao int i, done = 0, reject_allow_other = 0, safe_level = 0;
1265fe58019SAttilio Rao int altflags = DEFAULT_MOUNT_FLAGS;
1275fe58019SAttilio Rao int __altflags = DEFAULT_MOUNT_FLAGS;
128d14cfe6eSAttilio Rao int ch = 0;
1295fe58019SAttilio Rao struct mntopt *mo;
1305fe58019SAttilio Rao struct mntval *mv;
1315fe58019SAttilio Rao static struct option longopts[] = {
1325fe58019SAttilio Rao {"reject-allow_other", no_argument, NULL, 'A'},
1335fe58019SAttilio Rao {"safe", no_argument, NULL, 'S'},
1345fe58019SAttilio Rao {"daemon", required_argument, NULL, 'D'},
1355fe58019SAttilio Rao {"daemon_opts", required_argument, NULL, 'O'},
1365fe58019SAttilio Rao {"special", required_argument, NULL, 's'},
1375fe58019SAttilio Rao {"mountpath", required_argument, NULL, 'm'},
1385fe58019SAttilio Rao {"version", no_argument, NULL, 'V'},
1395fe58019SAttilio Rao {"help", no_argument, NULL, 'h'},
1405fe58019SAttilio Rao {0,0,0,0}
1415fe58019SAttilio Rao };
1425fe58019SAttilio Rao int pid = 0;
1435fe58019SAttilio Rao int fd = -1, fdx;
1445fe58019SAttilio Rao char *ep;
1455fe58019SAttilio Rao char *daemon_str = NULL, *daemon_opts = NULL;
1465fe58019SAttilio Rao
1475fe58019SAttilio Rao /*
1485fe58019SAttilio Rao * We want a parsing routine which is not sensitive to
1495fe58019SAttilio Rao * the position of args/opts; it should extract the
1505fe58019SAttilio Rao * first two args and stop at the beginning of the rest.
1515fe58019SAttilio Rao * (This makes it easier to call mount_fusefs from external
1525fe58019SAttilio Rao * utils than it is with a strict "util flags args" syntax.)
1535fe58019SAttilio Rao */
1545fe58019SAttilio Rao
1555fe58019SAttilio Rao iov = NULL;
1565fe58019SAttilio Rao iovlen = 0;
1575fe58019SAttilio Rao mntflags = 0;
1585fe58019SAttilio Rao /* All in all, I feel it more robust this way... */
1595fe58019SAttilio Rao unsetenv("POSIXLY_CORRECT");
1605fe58019SAttilio Rao if (getenv("MOUNT_FUSEFS_IGNORE_UNKNOWN"))
1615fe58019SAttilio Rao getmnt_silent = 1;
1625fe58019SAttilio Rao if (getenv("MOUNT_FUSEFS_VERBOSE"))
1635fe58019SAttilio Rao verbose = 1;
1645fe58019SAttilio Rao
1655fe58019SAttilio Rao do {
1665fe58019SAttilio Rao for (i = 0; i < 3; i++) {
1675fe58019SAttilio Rao if (optind < argc && argv[optind][0] != '-') {
1685fe58019SAttilio Rao if (dir) {
1695fe58019SAttilio Rao done = 1;
1705fe58019SAttilio Rao break;
1715fe58019SAttilio Rao }
1725fe58019SAttilio Rao if (dev)
1735fe58019SAttilio Rao dir = argv[optind];
1745fe58019SAttilio Rao else
1755fe58019SAttilio Rao dev = argv[optind];
1765fe58019SAttilio Rao optind++;
1775fe58019SAttilio Rao }
1785fe58019SAttilio Rao }
1795fe58019SAttilio Rao switch(ch) {
1805fe58019SAttilio Rao case 'A':
1815fe58019SAttilio Rao reject_allow_other = 1;
1825fe58019SAttilio Rao break;
1835fe58019SAttilio Rao case 'S':
1845fe58019SAttilio Rao safe_level = 1;
1855fe58019SAttilio Rao break;
1865fe58019SAttilio Rao case 'D':
1875fe58019SAttilio Rao if (daemon_str)
1885fe58019SAttilio Rao errx(1, "daemon specified inconsistently");
1895fe58019SAttilio Rao daemon_str = optarg;
1905fe58019SAttilio Rao break;
1915fe58019SAttilio Rao case 'O':
1925fe58019SAttilio Rao if (daemon_opts)
1935fe58019SAttilio Rao errx(1, "daemon opts specified inconsistently");
1945fe58019SAttilio Rao daemon_opts = optarg;
1955fe58019SAttilio Rao break;
1965fe58019SAttilio Rao case 'o':
1975fe58019SAttilio Rao getmntopts(optarg, mopts, &mntflags, &altflags);
1985fe58019SAttilio Rao for (mv = mvals; mv->mv_flag; ++mv) {
1995fe58019SAttilio Rao if (! (altflags & mv->mv_flag))
2005fe58019SAttilio Rao continue;
2015fe58019SAttilio Rao for (mo = mopts; mo->m_flag; ++mo) {
2025fe58019SAttilio Rao char *p, *q;
2035fe58019SAttilio Rao
2045fe58019SAttilio Rao if (mo->m_flag != mv->mv_flag)
2055fe58019SAttilio Rao continue;
2065fe58019SAttilio Rao p = strstr(optarg, mo->m_option);
2075fe58019SAttilio Rao if (p) {
2085fe58019SAttilio Rao p += strlen(mo->m_option);
2095fe58019SAttilio Rao q = p;
2105fe58019SAttilio Rao while (*q != '\0' && *q != ',')
2115fe58019SAttilio Rao q++;
2125fe58019SAttilio Rao mv->mv_len = q - p + 1;
2135fe58019SAttilio Rao mv->mv_value = malloc(mv->mv_len);
2148c50ee01SAlan Somers if (mv->mv_value == NULL)
2158c50ee01SAlan Somers err(1, "malloc");
2165fe58019SAttilio Rao memcpy(mv->mv_value, p, mv->mv_len - 1);
2175fe58019SAttilio Rao ((char *)mv->mv_value)[mv->mv_len - 1] = '\0';
2185fe58019SAttilio Rao break;
2195fe58019SAttilio Rao }
2205fe58019SAttilio Rao }
2215fe58019SAttilio Rao }
2225fe58019SAttilio Rao break;
2235fe58019SAttilio Rao case 's':
2245fe58019SAttilio Rao if (devo)
2255fe58019SAttilio Rao errx(1, "special specified inconsistently");
2265fe58019SAttilio Rao devo = optarg;
2275fe58019SAttilio Rao break;
2285fe58019SAttilio Rao case 'm':
2295fe58019SAttilio Rao if (diro)
2305fe58019SAttilio Rao errx(1, "mount path specified inconsistently");
2315fe58019SAttilio Rao diro = optarg;
2325fe58019SAttilio Rao break;
2335fe58019SAttilio Rao case 'v':
2345fe58019SAttilio Rao verbose = 1;
2355fe58019SAttilio Rao break;
2365fe58019SAttilio Rao case 'h':
2375fe58019SAttilio Rao helpmsg();
2385fe58019SAttilio Rao break;
2395fe58019SAttilio Rao case 'V':
2405fe58019SAttilio Rao showversion();
2415fe58019SAttilio Rao break;
2425fe58019SAttilio Rao case '\0':
2435fe58019SAttilio Rao break;
2445fe58019SAttilio Rao case '?':
2455fe58019SAttilio Rao default:
2465fe58019SAttilio Rao usage();
2475fe58019SAttilio Rao }
2485fe58019SAttilio Rao if (done)
2495fe58019SAttilio Rao break;
2505fe58019SAttilio Rao } while ((ch = getopt_long(argc, argv, "AvVho:SD:O:s:m:", longopts, NULL)) != -1);
2515fe58019SAttilio Rao
2525fe58019SAttilio Rao argc -= optind;
2535fe58019SAttilio Rao argv += optind;
2545fe58019SAttilio Rao
2555fe58019SAttilio Rao if (devo) {
2565fe58019SAttilio Rao if (dev)
2575fe58019SAttilio Rao errx(1, "special specified inconsistently");
2585fe58019SAttilio Rao dev = devo;
2595fe58019SAttilio Rao } else if (diro)
2605fe58019SAttilio Rao errx(1, "if mountpoint is given via an option, special should also be given via an option");
2615fe58019SAttilio Rao
2625fe58019SAttilio Rao if (diro) {
2635fe58019SAttilio Rao if (dir)
2645fe58019SAttilio Rao errx(1, "mount path specified inconsistently");
2655fe58019SAttilio Rao dir = diro;
2665fe58019SAttilio Rao }
2675fe58019SAttilio Rao
2685fe58019SAttilio Rao if ((! dev) && argc > 0) {
2695fe58019SAttilio Rao dev = *argv++;
2705fe58019SAttilio Rao argc--;
2715fe58019SAttilio Rao }
2725fe58019SAttilio Rao
2735fe58019SAttilio Rao if ((! dir) && argc > 0) {
2745fe58019SAttilio Rao dir = *argv++;
2755fe58019SAttilio Rao argc--;
2765fe58019SAttilio Rao }
2775fe58019SAttilio Rao
2785fe58019SAttilio Rao if (! (dev && dir))
2795fe58019SAttilio Rao errx(1, "missing special and/or mountpoint");
2805fe58019SAttilio Rao
2815fe58019SAttilio Rao for (mo = mopts; mo->m_flag; ++mo) {
2825fe58019SAttilio Rao if (altflags & mo->m_flag) {
2835fe58019SAttilio Rao int iov_done = 0;
2845fe58019SAttilio Rao
2855fe58019SAttilio Rao if (reject_allow_other &&
2865fe58019SAttilio Rao strcmp(mo->m_option, "allow_other") == 0)
2875fe58019SAttilio Rao /*
2885fe58019SAttilio Rao * reject_allow_other is stronger than a
2895fe58019SAttilio Rao * negative of allow_other: if this is set,
2905fe58019SAttilio Rao * allow_other is blocked, period.
2915fe58019SAttilio Rao */
2925fe58019SAttilio Rao errx(1, "\"allow_other\" usage is banned by respective option");
2935fe58019SAttilio Rao
2945fe58019SAttilio Rao for (mv = mvals; mv->mv_flag; ++mv) {
2955fe58019SAttilio Rao if (mo->m_flag != mv->mv_flag)
2965fe58019SAttilio Rao continue;
2975fe58019SAttilio Rao if (mv->mv_value) {
2985fe58019SAttilio Rao build_iovec(&iov, &iovlen, mo->m_option, mv->mv_value, mv->mv_len);
2995fe58019SAttilio Rao iov_done = 1;
3005fe58019SAttilio Rao break;
3015fe58019SAttilio Rao }
3025fe58019SAttilio Rao }
3035fe58019SAttilio Rao if (! iov_done)
3045fe58019SAttilio Rao build_iovec(&iov, &iovlen, mo->m_option,
3055fe58019SAttilio Rao __DECONST(void *, ""), -1);
3065fe58019SAttilio Rao }
3075fe58019SAttilio Rao if (__altflags & mo->m_flag) {
3085fe58019SAttilio Rao char *uscore_opt;
3095fe58019SAttilio Rao
3105fe58019SAttilio Rao if (asprintf(&uscore_opt, "__%s", mo->m_option) == -1)
3115fe58019SAttilio Rao err(1, "failed to allocate memory");
3125fe58019SAttilio Rao build_iovec(&iov, &iovlen, uscore_opt,
3135fe58019SAttilio Rao __DECONST(void *, ""), -1);
3145fe58019SAttilio Rao free(uscore_opt);
3155fe58019SAttilio Rao }
3165fe58019SAttilio Rao }
3175fe58019SAttilio Rao
3185fe58019SAttilio Rao if (getenv("MOUNT_FUSEFS_SAFE"))
3195fe58019SAttilio Rao safe_level = 1;
3205fe58019SAttilio Rao
3215fe58019SAttilio Rao if (safe_level > 0 && (argc > 0 || daemon_str || daemon_opts))
3225fe58019SAttilio Rao errx(1, "safe mode, spawning daemon not allowed");
3235fe58019SAttilio Rao
3245fe58019SAttilio Rao if ((argc > 0 && (daemon_str || daemon_opts)) ||
3255fe58019SAttilio Rao (daemon_opts && ! daemon_str))
3265fe58019SAttilio Rao errx(1, "daemon specified inconsistently");
3275fe58019SAttilio Rao
3285fe58019SAttilio Rao /*
3295fe58019SAttilio Rao * Resolve the mountpoint with realpath(3) and remove unnecessary
3305fe58019SAttilio Rao * slashes from the devicename if there are any.
3315fe58019SAttilio Rao */
3325fe58019SAttilio Rao if (checkpath(dir, mntpath) != 0)
3335fe58019SAttilio Rao err(1, "%s", mntpath);
3345fe58019SAttilio Rao (void)rmslashes(dev, dev);
3355fe58019SAttilio Rao
3365fe58019SAttilio Rao if (strcmp(dev, "auto") == 0)
3375fe58019SAttilio Rao dev = __DECONST(char *, "/dev/fuse");
3385fe58019SAttilio Rao
3395fe58019SAttilio Rao if (strcmp(dev, "/dev/fuse") == 0) {
3405fe58019SAttilio Rao if (! (argc > 0 || daemon_str)) {
3415fe58019SAttilio Rao fprintf(stderr, "Please also specify the fuse daemon to run when mounting via the multiplexer!\n");
3425fe58019SAttilio Rao usage();
3435fe58019SAttilio Rao }
3445fe58019SAttilio Rao if ((fd = open(dev, O_RDWR)) < 0)
3455fe58019SAttilio Rao err(1, "failed to open fuse device");
3465fe58019SAttilio Rao } else {
3475fe58019SAttilio Rao fdx = strtol(dev, &ep, 10);
3485fe58019SAttilio Rao if (*ep == '\0')
3495fe58019SAttilio Rao fd = fdx;
3505fe58019SAttilio Rao }
3515fe58019SAttilio Rao
3525fe58019SAttilio Rao /* Identifying device */
3535fe58019SAttilio Rao if (fd >= 0) {
3545fe58019SAttilio Rao struct stat sbuf;
3555fe58019SAttilio Rao char *ndevbas, *lep;
3565fe58019SAttilio Rao
3575fe58019SAttilio Rao if (fstat(fd, &sbuf) == -1)
3585fe58019SAttilio Rao err(1, "cannot stat device file descriptor");
3595fe58019SAttilio Rao
3605fe58019SAttilio Rao strcpy(ndev, _PATH_DEV);
3615fe58019SAttilio Rao ndevbas = ndev + strlen(_PATH_DEV);
3625fe58019SAttilio Rao devname_r(sbuf.st_rdev, S_IFCHR, ndevbas,
3635fe58019SAttilio Rao sizeof(ndev) - strlen(_PATH_DEV));
3645fe58019SAttilio Rao
3655fe58019SAttilio Rao if (strncmp(ndevbas, "fuse", 4))
3665fe58019SAttilio Rao errx(1, "mounting inappropriate device");
3675fe58019SAttilio Rao
3685fe58019SAttilio Rao strtol(ndevbas + 4, &lep, 10);
3695fe58019SAttilio Rao if (*lep != '\0')
3705fe58019SAttilio Rao errx(1, "mounting inappropriate device");
3715fe58019SAttilio Rao
3725fe58019SAttilio Rao dev = ndev;
3735fe58019SAttilio Rao }
3745fe58019SAttilio Rao
3755fe58019SAttilio Rao if (argc > 0 || daemon_str) {
3765fe58019SAttilio Rao char *fds;
3775fe58019SAttilio Rao
3785fe58019SAttilio Rao if (fd < 0 && (fd = open(dev, O_RDWR)) < 0)
3795fe58019SAttilio Rao err(1, "failed to open fuse device");
3805fe58019SAttilio Rao
3815fe58019SAttilio Rao if (asprintf(&fds, "%d", fd) == -1)
3825fe58019SAttilio Rao err(1, "failed to allocate memory");
3835fe58019SAttilio Rao setenv("FUSE_DEV_FD", fds, 1);
3845fe58019SAttilio Rao free(fds);
3855fe58019SAttilio Rao setenv("FUSE_NO_MOUNT", "1", 1);
3865fe58019SAttilio Rao
3875fe58019SAttilio Rao if (daemon_str) {
3885fe58019SAttilio Rao char *bgdaemon;
3895fe58019SAttilio Rao int len;
3905fe58019SAttilio Rao
3915fe58019SAttilio Rao if (! daemon_opts)
3925fe58019SAttilio Rao daemon_opts = __DECONST(char *, "");
3935fe58019SAttilio Rao
3945fe58019SAttilio Rao len = strlen(daemon_str) + 1 + strlen(daemon_opts) +
3955fe58019SAttilio Rao 2 + 1;
3965fe58019SAttilio Rao bgdaemon = calloc(1, len);
3975fe58019SAttilio Rao
3985fe58019SAttilio Rao if (! bgdaemon)
3995fe58019SAttilio Rao err(1, "failed to allocate memory");
4005fe58019SAttilio Rao
4015fe58019SAttilio Rao strlcpy(bgdaemon, daemon_str, len);
4025fe58019SAttilio Rao strlcat(bgdaemon, " ", len);
4035fe58019SAttilio Rao strlcat(bgdaemon, daemon_opts, len);
4045fe58019SAttilio Rao strlcat(bgdaemon, " &", len);
4055fe58019SAttilio Rao
4065fe58019SAttilio Rao if (system(bgdaemon))
4075fe58019SAttilio Rao err(1, "failed to call fuse daemon");
4085fe58019SAttilio Rao } else {
4095fe58019SAttilio Rao if ((pid = fork()) < 0)
4105fe58019SAttilio Rao err(1, "failed to fork for fuse daemon");
4115fe58019SAttilio Rao
4125fe58019SAttilio Rao if (pid == 0) {
4135fe58019SAttilio Rao execvp(argv[0], argv);
4145fe58019SAttilio Rao err(1, "failed to exec fuse daemon");
4155fe58019SAttilio Rao }
4165fe58019SAttilio Rao }
4175fe58019SAttilio Rao }
4185fe58019SAttilio Rao
4195fe58019SAttilio Rao /* Prepare the options vector for nmount(). build_iovec() is declared
4205fe58019SAttilio Rao * in mntopts.h. */
4215fe58019SAttilio Rao sprintf(fdstr, "%d", fd);
4225fe58019SAttilio Rao build_iovec(&iov, &iovlen, "fstype", __DECONST(void *, "fusefs"), -1);
4235fe58019SAttilio Rao build_iovec(&iov, &iovlen, "fspath", mntpath, -1);
4245fe58019SAttilio Rao build_iovec(&iov, &iovlen, "from", dev, -1);
4255fe58019SAttilio Rao build_iovec(&iov, &iovlen, "fd", fdstr, -1);
4265fe58019SAttilio Rao
4275fe58019SAttilio Rao if (verbose)
4285fe58019SAttilio Rao fprintf(stderr, "mounting fuse daemon on device %s\n", dev);
4295fe58019SAttilio Rao
4305fe58019SAttilio Rao if (nmount(iov, iovlen, mntflags) < 0)
4315fe58019SAttilio Rao err(EX_OSERR, "%s on %s", dev, mntpath);
4325fe58019SAttilio Rao
4335fe58019SAttilio Rao exit(0);
4345fe58019SAttilio Rao }
4355fe58019SAttilio Rao
4365fe58019SAttilio Rao void
__usage_short(void)4375fe58019SAttilio Rao __usage_short(void) {
4385fe58019SAttilio Rao fprintf(stderr,
4395fe58019SAttilio Rao "usage:\n%s [-A|-S|-v|-V|-h|-D daemon|-O args|-s special|-m node|-o option...] special node [daemon args...]\n\n",
440ae824d80SEd Schouten getprogname());
4415fe58019SAttilio Rao }
4425fe58019SAttilio Rao
4435fe58019SAttilio Rao void
usage(void)4445fe58019SAttilio Rao usage(void)
4455fe58019SAttilio Rao {
4465fe58019SAttilio Rao struct mntopt *mo;
4475fe58019SAttilio Rao
4485fe58019SAttilio Rao __usage_short();
4495fe58019SAttilio Rao
4505fe58019SAttilio Rao fprintf(stderr, "known options:\n");
4515fe58019SAttilio Rao for (mo = mopts; mo->m_flag; ++mo)
4525fe58019SAttilio Rao fprintf(stderr, "\t%s\n", mo->m_option);
4535fe58019SAttilio Rao
4545fe58019SAttilio Rao fprintf(stderr, "\n(use -h for a detailed description of these options)\n");
4555fe58019SAttilio Rao exit(EX_USAGE);
4565fe58019SAttilio Rao }
4575fe58019SAttilio Rao
4585fe58019SAttilio Rao void
helpmsg(void)4595fe58019SAttilio Rao helpmsg(void)
4605fe58019SAttilio Rao {
4615fe58019SAttilio Rao if (! getenv("MOUNT_FUSEFS_CALL_BY_LIB")) {
4625fe58019SAttilio Rao __usage_short();
4635fe58019SAttilio Rao fprintf(stderr, "description of options:\n");
4645fe58019SAttilio Rao }
4655fe58019SAttilio Rao
4665fe58019SAttilio Rao /*
4675fe58019SAttilio Rao * The main use case of this function is giving info embedded in general
4685fe58019SAttilio Rao * FUSE lib help output. Therefore the style and the content of the output
4695fe58019SAttilio Rao * tries to fit there as much as possible.
4705fe58019SAttilio Rao */
4715fe58019SAttilio Rao fprintf(stderr,
4725fe58019SAttilio Rao " -o allow_other allow access to other users\n"
4735fe58019SAttilio Rao /* " -o nonempty allow mounts over non-empty file/dir\n" */
4745fe58019SAttilio Rao " -o default_permissions enable permission checking by kernel\n"
475ed74f781SAlan Somers " -o intr interruptible mount\n"
4765fe58019SAttilio Rao " -o fsname=NAME set filesystem name\n"
4772f636248SAlan Somers /*
4785fe58019SAttilio Rao " -o large_read issue large read requests (2.4 only)\n"
4795fe58019SAttilio Rao */
4805fe58019SAttilio Rao " -o subtype=NAME set filesystem type\n"
4815fe58019SAttilio Rao " -o max_read=N set maximum size of read requests\n"
4825fe58019SAttilio Rao " -o noprivate allow secondary mounting of the filesystem\n"
4835fe58019SAttilio Rao " -o neglect_shares don't report EBUSY when unmount attempted\n"
4845fe58019SAttilio Rao " in presence of secondary mounts\n"
4855fe58019SAttilio Rao " -o push_symlinks_in prefix absolute symlinks with mountpoint\n"
4865fe58019SAttilio Rao );
4875fe58019SAttilio Rao exit(EX_USAGE);
4885fe58019SAttilio Rao }
4895fe58019SAttilio Rao
4905fe58019SAttilio Rao void
showversion(void)4915fe58019SAttilio Rao showversion(void)
4925fe58019SAttilio Rao {
4935fe58019SAttilio Rao puts("mount_fusefs [fuse4bsd] version: " FUSE4BSD_VERSION);
4945fe58019SAttilio Rao exit(EX_USAGE);
4955fe58019SAttilio Rao }
496