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