xref: /aosp_15_r20/external/libfuse/lib/helper.c (revision 9e5649576b786774a32d7b0252c9cd8c6538fa49)
1*9e564957SAndroid Build Coastguard Worker /*
2*9e564957SAndroid Build Coastguard Worker   FUSE: Filesystem in Userspace
3*9e564957SAndroid Build Coastguard Worker   Copyright (C) 2001-2007  Miklos Szeredi <[email protected]>
4*9e564957SAndroid Build Coastguard Worker 
5*9e564957SAndroid Build Coastguard Worker   Helper functions to create (simple) standalone programs. With the
6*9e564957SAndroid Build Coastguard Worker   aid of these functions it should be possible to create full FUSE
7*9e564957SAndroid Build Coastguard Worker   file system by implementing nothing but the request handlers.
8*9e564957SAndroid Build Coastguard Worker 
9*9e564957SAndroid Build Coastguard Worker   This program can be distributed under the terms of the GNU LGPLv2.
10*9e564957SAndroid Build Coastguard Worker   See the file COPYING.LIB.
11*9e564957SAndroid Build Coastguard Worker */
12*9e564957SAndroid Build Coastguard Worker 
13*9e564957SAndroid Build Coastguard Worker #include "fuse_config.h"
14*9e564957SAndroid Build Coastguard Worker #include "fuse_i.h"
15*9e564957SAndroid Build Coastguard Worker #include "fuse_misc.h"
16*9e564957SAndroid Build Coastguard Worker #include "fuse_opt.h"
17*9e564957SAndroid Build Coastguard Worker #include "fuse_lowlevel.h"
18*9e564957SAndroid Build Coastguard Worker #include "mount_util.h"
19*9e564957SAndroid Build Coastguard Worker 
20*9e564957SAndroid Build Coastguard Worker #include <stdio.h>
21*9e564957SAndroid Build Coastguard Worker #include <stdlib.h>
22*9e564957SAndroid Build Coastguard Worker #include <stddef.h>
23*9e564957SAndroid Build Coastguard Worker #include <unistd.h>
24*9e564957SAndroid Build Coastguard Worker #include <string.h>
25*9e564957SAndroid Build Coastguard Worker #include <limits.h>
26*9e564957SAndroid Build Coastguard Worker #include <errno.h>
27*9e564957SAndroid Build Coastguard Worker #include <sys/param.h>
28*9e564957SAndroid Build Coastguard Worker 
29*9e564957SAndroid Build Coastguard Worker #define FUSE_HELPER_OPT(t, p) \
30*9e564957SAndroid Build Coastguard Worker 	{ t, offsetof(struct fuse_cmdline_opts, p), 1 }
31*9e564957SAndroid Build Coastguard Worker 
32*9e564957SAndroid Build Coastguard Worker static const struct fuse_opt fuse_helper_opts[] = {
33*9e564957SAndroid Build Coastguard Worker 	FUSE_HELPER_OPT("-h",		show_help),
34*9e564957SAndroid Build Coastguard Worker 	FUSE_HELPER_OPT("--help",	show_help),
35*9e564957SAndroid Build Coastguard Worker 	FUSE_HELPER_OPT("-V",		show_version),
36*9e564957SAndroid Build Coastguard Worker 	FUSE_HELPER_OPT("--version",	show_version),
37*9e564957SAndroid Build Coastguard Worker 	FUSE_HELPER_OPT("-d",		debug),
38*9e564957SAndroid Build Coastguard Worker 	FUSE_HELPER_OPT("debug",	debug),
39*9e564957SAndroid Build Coastguard Worker 	FUSE_HELPER_OPT("-d",		foreground),
40*9e564957SAndroid Build Coastguard Worker 	FUSE_HELPER_OPT("debug",	foreground),
41*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("-d",		FUSE_OPT_KEY_KEEP),
42*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("debug",		FUSE_OPT_KEY_KEEP),
43*9e564957SAndroid Build Coastguard Worker 	FUSE_HELPER_OPT("-f",		foreground),
44*9e564957SAndroid Build Coastguard Worker 	FUSE_HELPER_OPT("-s",		singlethread),
45*9e564957SAndroid Build Coastguard Worker 	FUSE_HELPER_OPT("fsname=",	nodefault_subtype),
46*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("fsname=",		FUSE_OPT_KEY_KEEP),
47*9e564957SAndroid Build Coastguard Worker #ifndef __FreeBSD__
48*9e564957SAndroid Build Coastguard Worker 	FUSE_HELPER_OPT("subtype=",	nodefault_subtype),
49*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_KEY("subtype=",	FUSE_OPT_KEY_KEEP),
50*9e564957SAndroid Build Coastguard Worker #endif
51*9e564957SAndroid Build Coastguard Worker 	FUSE_HELPER_OPT("clone_fd",	clone_fd),
52*9e564957SAndroid Build Coastguard Worker 	FUSE_HELPER_OPT("max_idle_threads=%u", max_idle_threads),
53*9e564957SAndroid Build Coastguard Worker 	FUSE_HELPER_OPT("max_threads=%u", max_threads),
54*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_END
55*9e564957SAndroid Build Coastguard Worker };
56*9e564957SAndroid Build Coastguard Worker 
57*9e564957SAndroid Build Coastguard Worker struct fuse_conn_info_opts {
58*9e564957SAndroid Build Coastguard Worker 	int atomic_o_trunc;
59*9e564957SAndroid Build Coastguard Worker 	int no_remote_posix_lock;
60*9e564957SAndroid Build Coastguard Worker 	int no_remote_flock;
61*9e564957SAndroid Build Coastguard Worker 	int splice_write;
62*9e564957SAndroid Build Coastguard Worker 	int splice_move;
63*9e564957SAndroid Build Coastguard Worker 	int splice_read;
64*9e564957SAndroid Build Coastguard Worker 	int no_splice_write;
65*9e564957SAndroid Build Coastguard Worker 	int no_splice_move;
66*9e564957SAndroid Build Coastguard Worker 	int no_splice_read;
67*9e564957SAndroid Build Coastguard Worker 	int auto_inval_data;
68*9e564957SAndroid Build Coastguard Worker 	int no_auto_inval_data;
69*9e564957SAndroid Build Coastguard Worker 	int no_readdirplus;
70*9e564957SAndroid Build Coastguard Worker 	int no_readdirplus_auto;
71*9e564957SAndroid Build Coastguard Worker 	int async_dio;
72*9e564957SAndroid Build Coastguard Worker 	int no_async_dio;
73*9e564957SAndroid Build Coastguard Worker 	int writeback_cache;
74*9e564957SAndroid Build Coastguard Worker 	int no_writeback_cache;
75*9e564957SAndroid Build Coastguard Worker 	int async_read;
76*9e564957SAndroid Build Coastguard Worker 	int sync_read;
77*9e564957SAndroid Build Coastguard Worker 	unsigned max_write;
78*9e564957SAndroid Build Coastguard Worker 	unsigned max_readahead;
79*9e564957SAndroid Build Coastguard Worker 	unsigned max_background;
80*9e564957SAndroid Build Coastguard Worker 	unsigned congestion_threshold;
81*9e564957SAndroid Build Coastguard Worker 	unsigned time_gran;
82*9e564957SAndroid Build Coastguard Worker 	int set_max_write;
83*9e564957SAndroid Build Coastguard Worker 	int set_max_readahead;
84*9e564957SAndroid Build Coastguard Worker 	int set_max_background;
85*9e564957SAndroid Build Coastguard Worker 	int set_congestion_threshold;
86*9e564957SAndroid Build Coastguard Worker 	int set_time_gran;
87*9e564957SAndroid Build Coastguard Worker };
88*9e564957SAndroid Build Coastguard Worker 
89*9e564957SAndroid Build Coastguard Worker #define CONN_OPTION(t, p, v)					\
90*9e564957SAndroid Build Coastguard Worker 	{ t, offsetof(struct fuse_conn_info_opts, p), v }
91*9e564957SAndroid Build Coastguard Worker static const struct fuse_opt conn_info_opt_spec[] = {
92*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("max_write=%u", max_write, 0),
93*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("max_write=", set_max_write, 1),
94*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("max_readahead=%u", max_readahead, 0),
95*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("max_readahead=", set_max_readahead, 1),
96*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("max_background=%u", max_background, 0),
97*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("max_background=", set_max_background, 1),
98*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("congestion_threshold=%u", congestion_threshold, 0),
99*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("congestion_threshold=", set_congestion_threshold, 1),
100*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("sync_read", sync_read, 1),
101*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("async_read", async_read, 1),
102*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("atomic_o_trunc", atomic_o_trunc, 1),
103*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("no_remote_lock", no_remote_posix_lock, 1),
104*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("no_remote_lock", no_remote_flock, 1),
105*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("no_remote_flock", no_remote_flock, 1),
106*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("no_remote_posix_lock", no_remote_posix_lock, 1),
107*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("splice_write", splice_write, 1),
108*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("no_splice_write", no_splice_write, 1),
109*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("splice_move", splice_move, 1),
110*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("no_splice_move", no_splice_move, 1),
111*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("splice_read", splice_read, 1),
112*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("no_splice_read", no_splice_read, 1),
113*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("auto_inval_data", auto_inval_data, 1),
114*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("no_auto_inval_data", no_auto_inval_data, 1),
115*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("readdirplus=no", no_readdirplus, 1),
116*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("readdirplus=yes", no_readdirplus, 0),
117*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("readdirplus=yes", no_readdirplus_auto, 1),
118*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("readdirplus=auto", no_readdirplus, 0),
119*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("readdirplus=auto", no_readdirplus_auto, 0),
120*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("async_dio", async_dio, 1),
121*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("no_async_dio", no_async_dio, 1),
122*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("writeback_cache", writeback_cache, 1),
123*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("no_writeback_cache", no_writeback_cache, 1),
124*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("time_gran=%u", time_gran, 0),
125*9e564957SAndroid Build Coastguard Worker 	CONN_OPTION("time_gran=", set_time_gran, 1),
126*9e564957SAndroid Build Coastguard Worker 	FUSE_OPT_END
127*9e564957SAndroid Build Coastguard Worker };
128*9e564957SAndroid Build Coastguard Worker 
129*9e564957SAndroid Build Coastguard Worker 
fuse_cmdline_help(void)130*9e564957SAndroid Build Coastguard Worker void fuse_cmdline_help(void)
131*9e564957SAndroid Build Coastguard Worker {
132*9e564957SAndroid Build Coastguard Worker 	printf("    -h   --help            print help\n"
133*9e564957SAndroid Build Coastguard Worker 	       "    -V   --version         print version\n"
134*9e564957SAndroid Build Coastguard Worker 	       "    -d   -o debug          enable debug output (implies -f)\n"
135*9e564957SAndroid Build Coastguard Worker 	       "    -f                     foreground operation\n"
136*9e564957SAndroid Build Coastguard Worker 	       "    -s                     disable multi-threaded operation\n"
137*9e564957SAndroid Build Coastguard Worker 	       "    -o clone_fd            use separate fuse device fd for each thread\n"
138*9e564957SAndroid Build Coastguard Worker 	       "                           (may improve performance)\n"
139*9e564957SAndroid Build Coastguard Worker 	       "    -o max_idle_threads    the maximum number of idle worker threads\n"
140*9e564957SAndroid Build Coastguard Worker 	       "                           allowed (default: -1)\n"
141*9e564957SAndroid Build Coastguard Worker 	       "    -o max_threads         the maximum number of worker threads\n"
142*9e564957SAndroid Build Coastguard Worker 	       "                           allowed (default: 10)\n");
143*9e564957SAndroid Build Coastguard Worker }
144*9e564957SAndroid Build Coastguard Worker 
fuse_helper_opt_proc(void * data,const char * arg,int key,struct fuse_args * outargs)145*9e564957SAndroid Build Coastguard Worker static int fuse_helper_opt_proc(void *data, const char *arg, int key,
146*9e564957SAndroid Build Coastguard Worker 				struct fuse_args *outargs)
147*9e564957SAndroid Build Coastguard Worker {
148*9e564957SAndroid Build Coastguard Worker 	(void) outargs;
149*9e564957SAndroid Build Coastguard Worker 	struct fuse_cmdline_opts *opts = data;
150*9e564957SAndroid Build Coastguard Worker 
151*9e564957SAndroid Build Coastguard Worker 	switch (key) {
152*9e564957SAndroid Build Coastguard Worker 	case FUSE_OPT_KEY_NONOPT:
153*9e564957SAndroid Build Coastguard Worker 		if (!opts->mountpoint) {
154*9e564957SAndroid Build Coastguard Worker 			if (fuse_mnt_parse_fuse_fd(arg) != -1) {
155*9e564957SAndroid Build Coastguard Worker 				return fuse_opt_add_opt(&opts->mountpoint, arg);
156*9e564957SAndroid Build Coastguard Worker 			}
157*9e564957SAndroid Build Coastguard Worker 
158*9e564957SAndroid Build Coastguard Worker 			char mountpoint[PATH_MAX] = "";
159*9e564957SAndroid Build Coastguard Worker 			if (realpath(arg, mountpoint) == NULL) {
160*9e564957SAndroid Build Coastguard Worker 				fuse_log(FUSE_LOG_ERR,
161*9e564957SAndroid Build Coastguard Worker 					"fuse: bad mount point `%s': %s\n",
162*9e564957SAndroid Build Coastguard Worker 					arg, strerror(errno));
163*9e564957SAndroid Build Coastguard Worker 				return -1;
164*9e564957SAndroid Build Coastguard Worker 			}
165*9e564957SAndroid Build Coastguard Worker 			return fuse_opt_add_opt(&opts->mountpoint, mountpoint);
166*9e564957SAndroid Build Coastguard Worker 		} else {
167*9e564957SAndroid Build Coastguard Worker 			fuse_log(FUSE_LOG_ERR, "fuse: invalid argument `%s'\n", arg);
168*9e564957SAndroid Build Coastguard Worker 			return -1;
169*9e564957SAndroid Build Coastguard Worker 		}
170*9e564957SAndroid Build Coastguard Worker 
171*9e564957SAndroid Build Coastguard Worker 	default:
172*9e564957SAndroid Build Coastguard Worker 		/* Pass through unknown options */
173*9e564957SAndroid Build Coastguard Worker 		return 1;
174*9e564957SAndroid Build Coastguard Worker 	}
175*9e564957SAndroid Build Coastguard Worker }
176*9e564957SAndroid Build Coastguard Worker 
177*9e564957SAndroid Build Coastguard Worker /* Under FreeBSD, there is no subtype option so this
178*9e564957SAndroid Build Coastguard Worker    function actually sets the fsname */
add_default_subtype(const char * progname,struct fuse_args * args)179*9e564957SAndroid Build Coastguard Worker static int add_default_subtype(const char *progname, struct fuse_args *args)
180*9e564957SAndroid Build Coastguard Worker {
181*9e564957SAndroid Build Coastguard Worker 	int res;
182*9e564957SAndroid Build Coastguard Worker 	char *subtype_opt;
183*9e564957SAndroid Build Coastguard Worker 
184*9e564957SAndroid Build Coastguard Worker 	const char *basename = strrchr(progname, '/');
185*9e564957SAndroid Build Coastguard Worker 	if (basename == NULL)
186*9e564957SAndroid Build Coastguard Worker 		basename = progname;
187*9e564957SAndroid Build Coastguard Worker 	else if (basename[1] != '\0')
188*9e564957SAndroid Build Coastguard Worker 		basename++;
189*9e564957SAndroid Build Coastguard Worker 
190*9e564957SAndroid Build Coastguard Worker 	subtype_opt = (char *) malloc(strlen(basename) + 64);
191*9e564957SAndroid Build Coastguard Worker 	if (subtype_opt == NULL) {
192*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "fuse: memory allocation failed\n");
193*9e564957SAndroid Build Coastguard Worker 		return -1;
194*9e564957SAndroid Build Coastguard Worker 	}
195*9e564957SAndroid Build Coastguard Worker #ifdef __FreeBSD__
196*9e564957SAndroid Build Coastguard Worker 	sprintf(subtype_opt, "-ofsname=%s", basename);
197*9e564957SAndroid Build Coastguard Worker #else
198*9e564957SAndroid Build Coastguard Worker 	sprintf(subtype_opt, "-osubtype=%s", basename);
199*9e564957SAndroid Build Coastguard Worker #endif
200*9e564957SAndroid Build Coastguard Worker 	res = fuse_opt_add_arg(args, subtype_opt);
201*9e564957SAndroid Build Coastguard Worker 	free(subtype_opt);
202*9e564957SAndroid Build Coastguard Worker 	return res;
203*9e564957SAndroid Build Coastguard Worker }
204*9e564957SAndroid Build Coastguard Worker 
205*9e564957SAndroid Build Coastguard Worker int fuse_parse_cmdline_312(struct fuse_args *args,
206*9e564957SAndroid Build Coastguard Worker 			   struct fuse_cmdline_opts *opts);
207*9e564957SAndroid Build Coastguard Worker FUSE_SYMVER("fuse_parse_cmdline_312", "fuse_parse_cmdline@@FUSE_3.12")
fuse_parse_cmdline_312(struct fuse_args * args,struct fuse_cmdline_opts * opts)208*9e564957SAndroid Build Coastguard Worker int fuse_parse_cmdline_312(struct fuse_args *args,
209*9e564957SAndroid Build Coastguard Worker 			   struct fuse_cmdline_opts *opts)
210*9e564957SAndroid Build Coastguard Worker {
211*9e564957SAndroid Build Coastguard Worker 	memset(opts, 0, sizeof(struct fuse_cmdline_opts));
212*9e564957SAndroid Build Coastguard Worker 
213*9e564957SAndroid Build Coastguard Worker 	opts->max_idle_threads = UINT_MAX; /* new default in fuse version 3.12 */
214*9e564957SAndroid Build Coastguard Worker 	opts->max_threads = 10;
215*9e564957SAndroid Build Coastguard Worker 
216*9e564957SAndroid Build Coastguard Worker 	if (fuse_opt_parse(args, opts, fuse_helper_opts,
217*9e564957SAndroid Build Coastguard Worker 			   fuse_helper_opt_proc) == -1)
218*9e564957SAndroid Build Coastguard Worker 		return -1;
219*9e564957SAndroid Build Coastguard Worker 
220*9e564957SAndroid Build Coastguard Worker 	/* *Linux*: if neither -o subtype nor -o fsname are specified,
221*9e564957SAndroid Build Coastguard Worker 	   set subtype to program's basename.
222*9e564957SAndroid Build Coastguard Worker 	   *FreeBSD*: if fsname is not specified, set to program's
223*9e564957SAndroid Build Coastguard Worker 	   basename. */
224*9e564957SAndroid Build Coastguard Worker 	if (!opts->nodefault_subtype)
225*9e564957SAndroid Build Coastguard Worker 		if (add_default_subtype(args->argv[0], args) == -1)
226*9e564957SAndroid Build Coastguard Worker 			return -1;
227*9e564957SAndroid Build Coastguard Worker 
228*9e564957SAndroid Build Coastguard Worker 	return 0;
229*9e564957SAndroid Build Coastguard Worker }
230*9e564957SAndroid Build Coastguard Worker 
231*9e564957SAndroid Build Coastguard Worker /**
232*9e564957SAndroid Build Coastguard Worker  * struct fuse_cmdline_opts got extended in libfuse-3.12
233*9e564957SAndroid Build Coastguard Worker  */
234*9e564957SAndroid Build Coastguard Worker int fuse_parse_cmdline_30(struct fuse_args *args,
235*9e564957SAndroid Build Coastguard Worker 		       struct fuse_cmdline_opts *opts);
236*9e564957SAndroid Build Coastguard Worker FUSE_SYMVER("fuse_parse_cmdline_30", "fuse_parse_cmdline@FUSE_3.0")
fuse_parse_cmdline_30(struct fuse_args * args,struct fuse_cmdline_opts * out_opts)237*9e564957SAndroid Build Coastguard Worker int fuse_parse_cmdline_30(struct fuse_args *args,
238*9e564957SAndroid Build Coastguard Worker 			  struct fuse_cmdline_opts *out_opts)
239*9e564957SAndroid Build Coastguard Worker {
240*9e564957SAndroid Build Coastguard Worker 	struct fuse_cmdline_opts opts;
241*9e564957SAndroid Build Coastguard Worker 
242*9e564957SAndroid Build Coastguard Worker 	int rc = fuse_parse_cmdline_312(args, &opts);
243*9e564957SAndroid Build Coastguard Worker 	if (rc == 0) {
244*9e564957SAndroid Build Coastguard Worker 		/* copy up to the size of the old pre 3.12 struct */
245*9e564957SAndroid Build Coastguard Worker 		memcpy(out_opts, &opts,
246*9e564957SAndroid Build Coastguard Worker 		       offsetof(struct fuse_cmdline_opts, max_idle_threads) +
247*9e564957SAndroid Build Coastguard Worker 		       sizeof(opts.max_idle_threads));
248*9e564957SAndroid Build Coastguard Worker 	}
249*9e564957SAndroid Build Coastguard Worker 
250*9e564957SAndroid Build Coastguard Worker 	return rc;
251*9e564957SAndroid Build Coastguard Worker }
252*9e564957SAndroid Build Coastguard Worker 
fuse_daemonize(int foreground)253*9e564957SAndroid Build Coastguard Worker int fuse_daemonize(int foreground)
254*9e564957SAndroid Build Coastguard Worker {
255*9e564957SAndroid Build Coastguard Worker 	if (!foreground) {
256*9e564957SAndroid Build Coastguard Worker 		int nullfd;
257*9e564957SAndroid Build Coastguard Worker 		int waiter[2];
258*9e564957SAndroid Build Coastguard Worker 		char completed;
259*9e564957SAndroid Build Coastguard Worker 
260*9e564957SAndroid Build Coastguard Worker 		if (pipe(waiter)) {
261*9e564957SAndroid Build Coastguard Worker 			perror("fuse_daemonize: pipe");
262*9e564957SAndroid Build Coastguard Worker 			return -1;
263*9e564957SAndroid Build Coastguard Worker 		}
264*9e564957SAndroid Build Coastguard Worker 
265*9e564957SAndroid Build Coastguard Worker 		/*
266*9e564957SAndroid Build Coastguard Worker 		 * demonize current process by forking it and killing the
267*9e564957SAndroid Build Coastguard Worker 		 * parent.  This makes current process as a child of 'init'.
268*9e564957SAndroid Build Coastguard Worker 		 */
269*9e564957SAndroid Build Coastguard Worker 		switch(fork()) {
270*9e564957SAndroid Build Coastguard Worker 		case -1:
271*9e564957SAndroid Build Coastguard Worker 			perror("fuse_daemonize: fork");
272*9e564957SAndroid Build Coastguard Worker 			return -1;
273*9e564957SAndroid Build Coastguard Worker 		case 0:
274*9e564957SAndroid Build Coastguard Worker 			break;
275*9e564957SAndroid Build Coastguard Worker 		default:
276*9e564957SAndroid Build Coastguard Worker 			(void) read(waiter[0], &completed, sizeof(completed));
277*9e564957SAndroid Build Coastguard Worker 			_exit(0);
278*9e564957SAndroid Build Coastguard Worker 		}
279*9e564957SAndroid Build Coastguard Worker 
280*9e564957SAndroid Build Coastguard Worker 		if (setsid() == -1) {
281*9e564957SAndroid Build Coastguard Worker 			perror("fuse_daemonize: setsid");
282*9e564957SAndroid Build Coastguard Worker 			return -1;
283*9e564957SAndroid Build Coastguard Worker 		}
284*9e564957SAndroid Build Coastguard Worker 
285*9e564957SAndroid Build Coastguard Worker 		(void) chdir("/");
286*9e564957SAndroid Build Coastguard Worker 
287*9e564957SAndroid Build Coastguard Worker 		nullfd = open("/dev/null", O_RDWR, 0);
288*9e564957SAndroid Build Coastguard Worker 		if (nullfd != -1) {
289*9e564957SAndroid Build Coastguard Worker 			(void) dup2(nullfd, 0);
290*9e564957SAndroid Build Coastguard Worker 			(void) dup2(nullfd, 1);
291*9e564957SAndroid Build Coastguard Worker 			(void) dup2(nullfd, 2);
292*9e564957SAndroid Build Coastguard Worker 			if (nullfd > 2)
293*9e564957SAndroid Build Coastguard Worker 				close(nullfd);
294*9e564957SAndroid Build Coastguard Worker 		}
295*9e564957SAndroid Build Coastguard Worker 
296*9e564957SAndroid Build Coastguard Worker 		/* Propagate completion of daemon initialization */
297*9e564957SAndroid Build Coastguard Worker 		completed = 1;
298*9e564957SAndroid Build Coastguard Worker 		(void) write(waiter[1], &completed, sizeof(completed));
299*9e564957SAndroid Build Coastguard Worker 		close(waiter[0]);
300*9e564957SAndroid Build Coastguard Worker 		close(waiter[1]);
301*9e564957SAndroid Build Coastguard Worker 	} else {
302*9e564957SAndroid Build Coastguard Worker 		(void) chdir("/");
303*9e564957SAndroid Build Coastguard Worker 	}
304*9e564957SAndroid Build Coastguard Worker 	return 0;
305*9e564957SAndroid Build Coastguard Worker }
306*9e564957SAndroid Build Coastguard Worker 
307*9e564957SAndroid Build Coastguard Worker int fuse_main_real_317(int argc, char *argv[], const struct fuse_operations *op,
308*9e564957SAndroid Build Coastguard Worker 		   size_t op_size, struct libfuse_version *version, void *user_data);
309*9e564957SAndroid Build Coastguard Worker FUSE_SYMVER("fuse_main_real_317", "fuse_main_real@@FUSE_3.17")
fuse_main_real_317(int argc,char * argv[],const struct fuse_operations * op,size_t op_size,struct libfuse_version * version,void * user_data)310*9e564957SAndroid Build Coastguard Worker int fuse_main_real_317(int argc, char *argv[], const struct fuse_operations *op,
311*9e564957SAndroid Build Coastguard Worker 		   size_t op_size, struct libfuse_version *version, void *user_data)
312*9e564957SAndroid Build Coastguard Worker {
313*9e564957SAndroid Build Coastguard Worker 	struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
314*9e564957SAndroid Build Coastguard Worker 	struct fuse *fuse;
315*9e564957SAndroid Build Coastguard Worker 	struct fuse_cmdline_opts opts;
316*9e564957SAndroid Build Coastguard Worker 	int res;
317*9e564957SAndroid Build Coastguard Worker 	struct fuse_loop_config *loop_config = NULL;
318*9e564957SAndroid Build Coastguard Worker 
319*9e564957SAndroid Build Coastguard Worker 	if (fuse_parse_cmdline(&args, &opts) != 0)
320*9e564957SAndroid Build Coastguard Worker 		return 1;
321*9e564957SAndroid Build Coastguard Worker 
322*9e564957SAndroid Build Coastguard Worker 	if (opts.show_version) {
323*9e564957SAndroid Build Coastguard Worker 		printf("FUSE library version %s\n", PACKAGE_VERSION);
324*9e564957SAndroid Build Coastguard Worker 		fuse_lowlevel_version();
325*9e564957SAndroid Build Coastguard Worker 		res = 0;
326*9e564957SAndroid Build Coastguard Worker 		goto out1;
327*9e564957SAndroid Build Coastguard Worker 	}
328*9e564957SAndroid Build Coastguard Worker 
329*9e564957SAndroid Build Coastguard Worker 	if (opts.show_help) {
330*9e564957SAndroid Build Coastguard Worker 		if(args.argv[0][0] != '\0')
331*9e564957SAndroid Build Coastguard Worker 			printf("usage: %s [options] <mountpoint>\n\n",
332*9e564957SAndroid Build Coastguard Worker 			       args.argv[0]);
333*9e564957SAndroid Build Coastguard Worker 		printf("FUSE options:\n");
334*9e564957SAndroid Build Coastguard Worker 		fuse_cmdline_help();
335*9e564957SAndroid Build Coastguard Worker 		fuse_lib_help(&args);
336*9e564957SAndroid Build Coastguard Worker 		res = 0;
337*9e564957SAndroid Build Coastguard Worker 		goto out1;
338*9e564957SAndroid Build Coastguard Worker 	}
339*9e564957SAndroid Build Coastguard Worker 
340*9e564957SAndroid Build Coastguard Worker 	if (!opts.show_help &&
341*9e564957SAndroid Build Coastguard Worker 	    !opts.mountpoint) {
342*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "error: no mountpoint specified\n");
343*9e564957SAndroid Build Coastguard Worker 		res = 2;
344*9e564957SAndroid Build Coastguard Worker 		goto out1;
345*9e564957SAndroid Build Coastguard Worker 	}
346*9e564957SAndroid Build Coastguard Worker 
347*9e564957SAndroid Build Coastguard Worker 	fuse = _fuse_new(&args, op, op_size, version, user_data);
348*9e564957SAndroid Build Coastguard Worker 	if (fuse == NULL) {
349*9e564957SAndroid Build Coastguard Worker 		res = 3;
350*9e564957SAndroid Build Coastguard Worker 		goto out1;
351*9e564957SAndroid Build Coastguard Worker 	}
352*9e564957SAndroid Build Coastguard Worker 
353*9e564957SAndroid Build Coastguard Worker 	if (fuse_mount(fuse,opts.mountpoint) != 0) {
354*9e564957SAndroid Build Coastguard Worker 		res = 4;
355*9e564957SAndroid Build Coastguard Worker 		goto out2;
356*9e564957SAndroid Build Coastguard Worker 	}
357*9e564957SAndroid Build Coastguard Worker 
358*9e564957SAndroid Build Coastguard Worker 	if (fuse_daemonize(opts.foreground) != 0) {
359*9e564957SAndroid Build Coastguard Worker 		res = 5;
360*9e564957SAndroid Build Coastguard Worker 		goto out3;
361*9e564957SAndroid Build Coastguard Worker 	}
362*9e564957SAndroid Build Coastguard Worker 
363*9e564957SAndroid Build Coastguard Worker 	struct fuse_session *se = fuse_get_session(fuse);
364*9e564957SAndroid Build Coastguard Worker 	if (fuse_set_signal_handlers(se) != 0) {
365*9e564957SAndroid Build Coastguard Worker 		res = 6;
366*9e564957SAndroid Build Coastguard Worker 		goto out3;
367*9e564957SAndroid Build Coastguard Worker 	}
368*9e564957SAndroid Build Coastguard Worker 
369*9e564957SAndroid Build Coastguard Worker 	if (opts.singlethread)
370*9e564957SAndroid Build Coastguard Worker 		res = fuse_loop(fuse);
371*9e564957SAndroid Build Coastguard Worker 	else {
372*9e564957SAndroid Build Coastguard Worker 		loop_config = fuse_loop_cfg_create();
373*9e564957SAndroid Build Coastguard Worker 		if (loop_config == NULL) {
374*9e564957SAndroid Build Coastguard Worker 			res = 7;
375*9e564957SAndroid Build Coastguard Worker 			goto out3;
376*9e564957SAndroid Build Coastguard Worker 		}
377*9e564957SAndroid Build Coastguard Worker 
378*9e564957SAndroid Build Coastguard Worker 		fuse_loop_cfg_set_clone_fd(loop_config, opts.clone_fd);
379*9e564957SAndroid Build Coastguard Worker 
380*9e564957SAndroid Build Coastguard Worker 		fuse_loop_cfg_set_idle_threads(loop_config, opts.max_idle_threads);
381*9e564957SAndroid Build Coastguard Worker 		fuse_loop_cfg_set_max_threads(loop_config, opts.max_threads);
382*9e564957SAndroid Build Coastguard Worker 		res = fuse_loop_mt(fuse, loop_config);
383*9e564957SAndroid Build Coastguard Worker 	}
384*9e564957SAndroid Build Coastguard Worker 	if (res)
385*9e564957SAndroid Build Coastguard Worker 		res = 8;
386*9e564957SAndroid Build Coastguard Worker 
387*9e564957SAndroid Build Coastguard Worker 	fuse_remove_signal_handlers(se);
388*9e564957SAndroid Build Coastguard Worker out3:
389*9e564957SAndroid Build Coastguard Worker 	fuse_unmount(fuse);
390*9e564957SAndroid Build Coastguard Worker out2:
391*9e564957SAndroid Build Coastguard Worker 	fuse_destroy(fuse);
392*9e564957SAndroid Build Coastguard Worker out1:
393*9e564957SAndroid Build Coastguard Worker 	fuse_loop_cfg_destroy(loop_config);
394*9e564957SAndroid Build Coastguard Worker 	free(opts.mountpoint);
395*9e564957SAndroid Build Coastguard Worker 	fuse_opt_free_args(&args);
396*9e564957SAndroid Build Coastguard Worker 	return res;
397*9e564957SAndroid Build Coastguard Worker }
398*9e564957SAndroid Build Coastguard Worker 
399*9e564957SAndroid Build Coastguard Worker int fuse_main_real_30(int argc, char *argv[], const struct fuse_operations *op,
400*9e564957SAndroid Build Coastguard Worker 		      size_t op_size, void *user_data);
401*9e564957SAndroid Build Coastguard Worker FUSE_SYMVER("fuse_main_real_30", "fuse_main_real@FUSE_3.0")
fuse_main_real_30(int argc,char * argv[],const struct fuse_operations * op,size_t op_size,void * user_data)402*9e564957SAndroid Build Coastguard Worker int fuse_main_real_30(int argc, char *argv[], const struct fuse_operations *op,
403*9e564957SAndroid Build Coastguard Worker 		      size_t op_size, void *user_data)
404*9e564957SAndroid Build Coastguard Worker {
405*9e564957SAndroid Build Coastguard Worker 	struct libfuse_version version = { 0 };
406*9e564957SAndroid Build Coastguard Worker 
407*9e564957SAndroid Build Coastguard Worker 	return fuse_main_real_317(argc, argv, op, op_size, &version, user_data);
408*9e564957SAndroid Build Coastguard Worker }
409*9e564957SAndroid Build Coastguard Worker 
fuse_apply_conn_info_opts(struct fuse_conn_info_opts * opts,struct fuse_conn_info * conn)410*9e564957SAndroid Build Coastguard Worker void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts,
411*9e564957SAndroid Build Coastguard Worker 			       struct fuse_conn_info *conn)
412*9e564957SAndroid Build Coastguard Worker {
413*9e564957SAndroid Build Coastguard Worker 	if(opts->set_max_write)
414*9e564957SAndroid Build Coastguard Worker 		conn->max_write = opts->max_write;
415*9e564957SAndroid Build Coastguard Worker 	if(opts->set_max_background)
416*9e564957SAndroid Build Coastguard Worker 		conn->max_background = opts->max_background;
417*9e564957SAndroid Build Coastguard Worker 	if(opts->set_congestion_threshold)
418*9e564957SAndroid Build Coastguard Worker 		conn->congestion_threshold = opts->congestion_threshold;
419*9e564957SAndroid Build Coastguard Worker 	if(opts->set_time_gran)
420*9e564957SAndroid Build Coastguard Worker 		conn->time_gran = opts->time_gran;
421*9e564957SAndroid Build Coastguard Worker 	if(opts->set_max_readahead)
422*9e564957SAndroid Build Coastguard Worker 		conn->max_readahead = opts->max_readahead;
423*9e564957SAndroid Build Coastguard Worker 
424*9e564957SAndroid Build Coastguard Worker #define LL_ENABLE(cond,cap) \
425*9e564957SAndroid Build Coastguard Worker 	if (cond) conn->want |= (cap)
426*9e564957SAndroid Build Coastguard Worker #define LL_DISABLE(cond,cap) \
427*9e564957SAndroid Build Coastguard Worker 	if (cond) conn->want &= ~(cap)
428*9e564957SAndroid Build Coastguard Worker 
429*9e564957SAndroid Build Coastguard Worker 	LL_ENABLE(opts->splice_read, FUSE_CAP_SPLICE_READ);
430*9e564957SAndroid Build Coastguard Worker 	LL_DISABLE(opts->no_splice_read, FUSE_CAP_SPLICE_READ);
431*9e564957SAndroid Build Coastguard Worker 
432*9e564957SAndroid Build Coastguard Worker 	LL_ENABLE(opts->splice_write, FUSE_CAP_SPLICE_WRITE);
433*9e564957SAndroid Build Coastguard Worker 	LL_DISABLE(opts->no_splice_write, FUSE_CAP_SPLICE_WRITE);
434*9e564957SAndroid Build Coastguard Worker 
435*9e564957SAndroid Build Coastguard Worker 	LL_ENABLE(opts->splice_move, FUSE_CAP_SPLICE_MOVE);
436*9e564957SAndroid Build Coastguard Worker 	LL_DISABLE(opts->no_splice_move, FUSE_CAP_SPLICE_MOVE);
437*9e564957SAndroid Build Coastguard Worker 
438*9e564957SAndroid Build Coastguard Worker 	LL_ENABLE(opts->auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
439*9e564957SAndroid Build Coastguard Worker 	LL_DISABLE(opts->no_auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
440*9e564957SAndroid Build Coastguard Worker 
441*9e564957SAndroid Build Coastguard Worker 	LL_DISABLE(opts->no_readdirplus, FUSE_CAP_READDIRPLUS);
442*9e564957SAndroid Build Coastguard Worker 	LL_DISABLE(opts->no_readdirplus_auto, FUSE_CAP_READDIRPLUS_AUTO);
443*9e564957SAndroid Build Coastguard Worker 
444*9e564957SAndroid Build Coastguard Worker 	LL_ENABLE(opts->async_dio, FUSE_CAP_ASYNC_DIO);
445*9e564957SAndroid Build Coastguard Worker 	LL_DISABLE(opts->no_async_dio, FUSE_CAP_ASYNC_DIO);
446*9e564957SAndroid Build Coastguard Worker 
447*9e564957SAndroid Build Coastguard Worker 	LL_ENABLE(opts->writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
448*9e564957SAndroid Build Coastguard Worker 	LL_DISABLE(opts->no_writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
449*9e564957SAndroid Build Coastguard Worker 
450*9e564957SAndroid Build Coastguard Worker 	LL_ENABLE(opts->async_read, FUSE_CAP_ASYNC_READ);
451*9e564957SAndroid Build Coastguard Worker 	LL_DISABLE(opts->sync_read, FUSE_CAP_ASYNC_READ);
452*9e564957SAndroid Build Coastguard Worker 
453*9e564957SAndroid Build Coastguard Worker 	LL_DISABLE(opts->no_remote_posix_lock, FUSE_CAP_POSIX_LOCKS);
454*9e564957SAndroid Build Coastguard Worker 	LL_DISABLE(opts->no_remote_flock, FUSE_CAP_FLOCK_LOCKS);
455*9e564957SAndroid Build Coastguard Worker }
456*9e564957SAndroid Build Coastguard Worker 
fuse_parse_conn_info_opts(struct fuse_args * args)457*9e564957SAndroid Build Coastguard Worker struct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args)
458*9e564957SAndroid Build Coastguard Worker {
459*9e564957SAndroid Build Coastguard Worker 	struct fuse_conn_info_opts *opts;
460*9e564957SAndroid Build Coastguard Worker 
461*9e564957SAndroid Build Coastguard Worker 	opts = calloc(1, sizeof(struct fuse_conn_info_opts));
462*9e564957SAndroid Build Coastguard Worker 	if(opts == NULL) {
463*9e564957SAndroid Build Coastguard Worker 		fuse_log(FUSE_LOG_ERR, "calloc failed\n");
464*9e564957SAndroid Build Coastguard Worker 		return NULL;
465*9e564957SAndroid Build Coastguard Worker 	}
466*9e564957SAndroid Build Coastguard Worker 	if(fuse_opt_parse(args, opts, conn_info_opt_spec, NULL) == -1) {
467*9e564957SAndroid Build Coastguard Worker 		free(opts);
468*9e564957SAndroid Build Coastguard Worker 		return NULL;
469*9e564957SAndroid Build Coastguard Worker 	}
470*9e564957SAndroid Build Coastguard Worker 	return opts;
471*9e564957SAndroid Build Coastguard Worker }
472*9e564957SAndroid Build Coastguard Worker 
fuse_open_channel(const char * mountpoint,const char * options)473*9e564957SAndroid Build Coastguard Worker int fuse_open_channel(const char *mountpoint, const char* options)
474*9e564957SAndroid Build Coastguard Worker {
475*9e564957SAndroid Build Coastguard Worker 	struct mount_opts *opts = NULL;
476*9e564957SAndroid Build Coastguard Worker 	int fd = -1;
477*9e564957SAndroid Build Coastguard Worker 	const char *argv[] = { "", "-o", options };
478*9e564957SAndroid Build Coastguard Worker 	int argc = sizeof(argv) / sizeof(argv[0]);
479*9e564957SAndroid Build Coastguard Worker 	struct fuse_args args = FUSE_ARGS_INIT(argc, (char**) argv);
480*9e564957SAndroid Build Coastguard Worker 
481*9e564957SAndroid Build Coastguard Worker 	opts = parse_mount_opts(&args);
482*9e564957SAndroid Build Coastguard Worker 	if (opts == NULL)
483*9e564957SAndroid Build Coastguard Worker 		return -1;
484*9e564957SAndroid Build Coastguard Worker 
485*9e564957SAndroid Build Coastguard Worker 	fd = fuse_kern_mount(mountpoint, opts);
486*9e564957SAndroid Build Coastguard Worker 	destroy_mount_opts(opts);
487*9e564957SAndroid Build Coastguard Worker 
488*9e564957SAndroid Build Coastguard Worker 	return fd;
489*9e564957SAndroid Build Coastguard Worker }
490