"Fossies" - the Fresh Open Source Software Archive

Member "fuse-3.4.2/doc/html/helper_8c_source.html" (9 Mar 2019, 89267 Bytes) of package /linux/misc/fuse-3.4.2.tar.xz:


Caution: In this restricted "Fossies" environment the current HTML page may not be correctly presentated and may have some non-functional links. You can here alternatively try to browse the pure source code or just view or download the uninterpreted raw source code. If the rendering is insufficient you may try to find and view the page on the FUSE project site itself.

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