xref: /freebsd/sbin/mount_fusefs/mount_fusefs.c (revision 32e86a82f54826f14ea381affa6674db3aa3b5ae)
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