aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog.rst20
-rw-r--r--example/fuse_lo-plus.c51
-rw-r--r--example/hello_ll.c42
-rw-r--r--include/fuse_common.h28
-rw-r--r--include/fuse_lowlevel.h65
-rw-r--r--lib/cuse_lowlevel.c23
-rw-r--r--lib/fuse.c74
-rwxr-xr-xlib/fuse_lowlevel.c67
-rw-r--r--lib/fuse_versionscript4
-rw-r--r--lib/helper.c233
10 files changed, 317 insertions, 290 deletions
diff --git a/ChangeLog.rst b/ChangeLog.rst
index a15b55a..9afc173 100644
--- a/ChangeLog.rst
+++ b/ChangeLog.rst
@@ -2,12 +2,20 @@ Unreleased Changes
==================
* The `fuse_lowlevel_new` function has been renamed to
- `fuse_session_new`.
-
-* There are now new `fuse_session_unmount` and `fuse_session_mount`
- functions that should be used in the low-level API. The
- `fuse_mount` and `fuse_unmount` functions should be used with the
- high-level API only.
+ `fuse_session_new` and no longer interprets the --version or --help
+ options. To print help or version information, use the new
+ `fuse_lowlevel_help` and `fuse_lowlevel_version` functions.
+
+* There are new `fuse_session_unmount` and `fuse_session_mount`
+ functions that should be used in the low-level API. The `fuse_mount`
+ and `fuse_unmount` functions should be used with the high-level API
+ only.
+
+* Neither `fuse_mount` nor `fuse_session_mount` take struct fuse_opts
+ parameters anymore. Mount options are parsed by `fuse_new` (for the
+ high-level API) and `fuse_session_new` (for the low-level API)
+ instead. To print help or version information, use the new
+ `fuse_mount_help` and `fuse_mount_version` functions.
* The ``fuse_lowlevel_notify_*`` functions now all take a `struct
fuse_session` parameter instead of a `struct fuse_chan`.
diff --git a/example/fuse_lo-plus.c b/example/fuse_lo-plus.c
index 4171d3e..1aa97b0 100644
--- a/example/fuse_lo-plus.c
+++ b/example/fuse_lo-plus.c
@@ -442,55 +442,54 @@ static struct fuse_lowlevel_ops lo_oper = {
.read = lo_read,
};
-#define LO_OPT(t, p, v) { t, offsetof(struct lo_data, p), v }
-
-static const struct fuse_opt lo_opts[] = {
- FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
- FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
- LO_OPT("debug", debug, 1),
- LO_OPT("-d", debug, 1),
- FUSE_OPT_END
-};
-
int main(int argc, char *argv[])
{
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
struct fuse_session *se;
- char *mountpoint;
- int ret = -1;
+ struct fuse_cmdline_opts opts;
struct lo_data lo = { .debug = 0 };
+ int ret = -1;
- if (fuse_opt_parse(&args, &lo, lo_opts, NULL) == -1)
- exit(1);
+ if (fuse_parse_cmdline(&args, &opts) != 0)
+ return 1;
+ if (opts.show_help || opts.show_version) {
+ ret = 1;
+ goto err_out1;
+ }
+ if (!opts.foreground)
+ fprintf(stderr, "Warning: background operation "
+ "is not supported\n");
+ if (!opts.singlethread)
+ fprintf(stderr, "Warning: multithreading is not "
+ "supported\n");
+
+ lo.debug = opts.debug;
lo.root.next = lo.root.prev = &lo.root;
lo.root.fd = open("/", O_PATH);
lo.root.nlookup = 2;
if (lo.root.fd == -1)
err(1, "open(\"/\", O_PATH)");
- if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != 0)
- goto err_out;
-
se = fuse_session_new(&args, &lo_oper, sizeof(lo_oper), &lo);
- fuse_opt_free_args(&args);
if (se == NULL)
- goto err_out;
-
- if (fuse_set_signal_handlers(se) != 0)
goto err_out1;
- if (fuse_session_mount(se, mountpoint) != 0)
+ if (fuse_set_signal_handlers(se) != 0)
goto err_out2;
+ if (fuse_session_mount(se, opts.mountpoint) != 0)
+ goto err_out3;
+
ret = fuse_session_loop(se);
fuse_session_unmount(se);
-err_out2:
+err_out3:
fuse_remove_signal_handlers(se);
-err_out1:
+err_out2:
fuse_session_destroy(se);
-err_out:
- free(mountpoint);
+err_out1:
+ free(opts.mountpoint);
+ fuse_opt_free_args(&args);
while (lo.root.next != &lo.root)
lo_free(lo.root.next);
diff --git a/example/hello_ll.c b/example/hello_ll.c
index 07529d1..b7e77cd 100644
--- a/example/hello_ll.c
+++ b/example/hello_ll.c
@@ -187,35 +187,45 @@ int main(int argc, char *argv[])
{
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
struct fuse_session *se;
- char *mountpoint;
- int err = -1;
-
- if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != 0)
- goto err_out;
+ struct fuse_cmdline_opts opts;
+ int ret = -1;
+
+ if (fuse_parse_cmdline(&args, &opts) != 0)
+ return 1;
+ if (opts.show_help || opts.show_version) {
+ ret = 1;
+ goto err_out1;
+ }
+ if (!opts.foreground)
+ fprintf(stderr, "Warning: background operation "
+ "is not supported\n");
+ if (!opts.singlethread)
+ fprintf(stderr, "Warning: multithreading is not "
+ "supported\n");
se = fuse_session_new(&args, &hello_ll_oper,
sizeof(hello_ll_oper), NULL);
- fuse_opt_free_args(&args);
if (se == NULL)
- goto err_out;
-
- if (fuse_set_signal_handlers(se) != 0)
goto err_out1;
- if (fuse_session_mount(se, mountpoint) != 0)
+ if (fuse_set_signal_handlers(se) != 0)
goto err_out2;
+ if (fuse_session_mount(se, opts.mountpoint) != 0)
+ goto err_out3;
+
/* Block until ctrl+c or fusermount -u */
- err = fuse_session_loop(se);
+ ret = fuse_session_loop(se);
fuse_session_unmount(se);
-err_out2:
+err_out3:
fuse_remove_signal_handlers(se);
-err_out1:
+err_out2:
fuse_session_destroy(se);
-err_out:
- free(mountpoint);
+err_out1:
+ free(opts.mountpoint);
+ fuse_opt_free_args(&args);
- return err ? 1 : 0;
+ return ret ? 1 : 0;
}
/*! [doxygen_fuse_lowlevel_usage] */
diff --git a/include/fuse_common.h b/include/fuse_common.h
index f39dab3..f32c872 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -209,34 +209,6 @@ struct fuse_session;
struct fuse_pollhandle;
/**
- * Utility functions for simple file systems to parse common options.
- *
- * The following options are parsed:
- *
- * '-f' foreground
- * '-d' '-odebug' foreground, but keep the debug option
- * '-s' single threaded
- * '-h' '--help' help
- * '-ho' help without header
- * '-ofsname=..' file system name, if not present, then set to the program
- * name
- *
- * Unknown parameters in `args` are passed through unchanged. Known
- * parameters (with the exception of --help and --version) are removed.
- *
- * All parameters may be NULL (in which case they may still
- * be specified on the command line, but will not be set).
- *
- * @param args argument vector
- * @param mountpoint the returned mountpoint, should be freed after use
- * @param multithreaded set to 1 unless the '-s' option is present
- * @param foreground set to 1 if one of the relevant options is present
- * @return 0 on success, -1 on failure
- */
-int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint,
- int *multithreaded, int *foreground);
-
-/**
* Go into the background
*
* @param foreground if true, stay in the foreground
diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h
index f90a052..0822e51 100644
--- a/include/fuse_lowlevel.h
+++ b/include/fuse_lowlevel.h
@@ -1560,10 +1560,72 @@ void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func,
*/
int fuse_req_interrupted(fuse_req_t req);
+
+/* ----------------------------------------------------------- *
+ * Inquiry functions *
+ * ----------------------------------------------------------- */
+
+/**
+ * Print FUSE library version to stdout.
+ */
+void fuse_lowlevel_version(void);
+
+/**
+ * Print FUSE mount (fusermount) version stdout.
+ */
+void fuse_mount_version(void);
+
+/**
+ * Print available low-level options to stdout.
+ * These options may be passed to `fuse_session_new()`
+ */
+void fuse_lowlevel_help(void);
+
+/**
+ * Print available mount options to stdout.
+ * These options may be passed to `fuse_session_new()`
+ */
+void fuse_mount_help(void);
+
/* ----------------------------------------------------------- *
* Filesystem setup & teardown *
* ----------------------------------------------------------- */
+struct fuse_cmdline_opts {
+ int singlethread;
+ int foreground;
+ int debug;
+ int nodefault_subtype;
+ char *mountpoint;
+ int show_version;
+ int show_help;
+};
+
+/**
+ * Utility function to parse common options for simple file systems
+ * using the low-level API. Available options are listed in `struct
+ * fuse_opt fuse_helper_opts[]`. A single non-option argument is
+ * treated as the mountpoint. Multiple (or no) non-option arguments
+ * will result in an error.
+ *
+ * Unknown options are passed through unchanged. Known options (other
+ * than --debug, which is preserved) and the mountpoint argument are
+ * removed from *args*.
+ *
+ * If --help or --version is specified, the appropriate information is
+ * printed to stdout and the function proceeds normally.
+ *
+ * If neither -o subtype= or -o fsname= options are given, the subtype
+ * is set to the basename of the program (the fsname defaults to
+ * "fuse").
+ *
+ * @param args argument vector (input+output)
+ * @param opts output argument for parsed options
+ * @return 0 on success, -1 on failure
+ */
+int fuse_parse_cmdline(struct fuse_args *args,
+ struct fuse_cmdline_opts *opts);
+
/**
* Create a low level session.
*
@@ -1574,9 +1636,6 @@ int fuse_req_interrupted(fuse_req_t req);
* `struct fuse_opt fuse_mount_opts[]`. If not all options are known,
* an error message is written to stderr and the function returns NULL.
*
- * If the --help or --version parameters are specified, the function
- * prints the requsted information to stdout and returns NULL.
- *
* @param args argument vector
* @param op the (low-level) filesystem operations
* @param op_size sizeof(struct fuse_lowlevel_ops)
diff --git a/lib/cuse_lowlevel.c b/lib/cuse_lowlevel.c
index 3dd79d8..8f596cb 100644
--- a/lib/cuse_lowlevel.c
+++ b/lib/cuse_lowlevel.c
@@ -276,21 +276,18 @@ struct fuse_session *cuse_lowlevel_setup(int argc, char *argv[],
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
struct fuse_session *se;
struct fuse_chan *ch;
+ struct fuse_cmdline_opts opts;
int fd;
- int foreground;
int res;
- res = fuse_parse_cmdline(&args, NULL, multithreaded, &foreground);
- if (res == -1) {
- fuse_opt_free_args(&args);
+ if (fuse_parse_cmdline(&args, &opts) == -1)
return NULL;
- }
+ *multithreaded = !opts.singlethread;
+ /* Remove subtype= option */
res = fuse_opt_parse(&args, NULL, kill_subtype_opts, NULL);
- if (res == -1) {
- fuse_opt_free_args(&args);
- return NULL;
- }
+ if (res == -1)
+ goto out1;
/*
* Make sure file descriptors 0, 1 and 2 are open, otherwise chaos
@@ -303,9 +300,8 @@ struct fuse_session *cuse_lowlevel_setup(int argc, char *argv[],
} while (fd >= 0 && fd <= 2);
se = cuse_lowlevel_new(&args, ci, clop, userdata);
- fuse_opt_free_args(&args);
if (se == NULL)
- return NULL;
+ goto out1;
fd = open(devname, O_RDWR);
if (fd == -1) {
@@ -329,7 +325,7 @@ struct fuse_session *cuse_lowlevel_setup(int argc, char *argv[],
if (res == -1)
goto err_se;
- res = fuse_daemonize(foreground);
+ res = fuse_daemonize(opts.foreground);
if (res == -1)
goto err_sig;
@@ -339,6 +335,9 @@ err_sig:
fuse_remove_signal_handlers(se);
err_se:
fuse_session_destroy(se);
+out1:
+ free(opts.mountpoint);
+ fuse_opt_free_args(&args);
return NULL;
}
diff --git a/lib/fuse.c b/lib/fuse.c
index d5cc678..0414f6b 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -77,7 +77,7 @@ struct fuse_config {
int auto_cache;
int intr;
int intr_signal;
- int help;
+ int show_help;
char *modules;
};
@@ -4410,15 +4410,11 @@ int fuse_interrupted(void)
return 0;
}
-enum {
- KEY_HELP,
-};
-
#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
static const struct fuse_opt fuse_lib_opts[] = {
- FUSE_OPT_KEY("-h", KEY_HELP),
- FUSE_OPT_KEY("--help", KEY_HELP),
+ FUSE_LIB_OPT("-h", show_help, 1),
+ FUSE_LIB_OPT("--help", show_help, 1),
FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
FUSE_LIB_OPT("debug", debug, 1),
@@ -4499,14 +4495,9 @@ static void fuse_lib_help_modules(void)
static int fuse_lib_opt_proc(void *data, const char *arg, int key,
struct fuse_args *outargs)
{
- (void) arg; (void) outargs;
-
- if (key == KEY_HELP) {
- struct fuse_config *conf = (struct fuse_config *) data;
- fuse_lib_help();
- conf->help = 1;
- }
+ (void) arg; (void) outargs; (void) data; (void) key;
+ /* Pass through unknown options */
return 1;
}
@@ -4641,6 +4632,25 @@ struct fuse *fuse_new(struct fuse_args *args,
struct fuse_fs *fs;
struct fuse_lowlevel_ops llop = fuse_path_ops;
+ f = (struct fuse *) calloc(1, sizeof(struct fuse));
+ if (f == NULL) {
+ fprintf(stderr, "fuse: failed to allocate fuse object\n");
+ goto out;
+ }
+
+ /* Parse options */
+ if (fuse_opt_parse(args, &f->conf, fuse_lib_opts,
+ fuse_lib_opt_proc) == -1)
+ goto out_free;
+
+ if (f->conf.show_help) {
+ fuse_lib_help();
+ fuse_lowlevel_help();
+ fuse_mount_help();
+ /* Defer printing module help until modules
+ have been loaded */
+ }
+
pthread_mutex_lock(&fuse_context_lock);
static int builtin_modules_registered = 0;
/* Have the builtin modules already been registered? */
@@ -4652,19 +4662,12 @@ struct fuse *fuse_new(struct fuse_args *args,
}
pthread_mutex_unlock(&fuse_context_lock);
-
if (fuse_create_context_key() == -1)
- goto out;
-
- f = (struct fuse *) calloc(1, sizeof(struct fuse));
- if (f == NULL) {
- fprintf(stderr, "fuse: failed to allocate fuse object\n");
- goto out_delete_context_key;
- }
+ goto out_free;
fs = fuse_fs_new(op, op_size, user_data);
if (!fs)
- goto out_free;
+ goto out_delete_context_key;
f->fs = fs;
f->conf.nopath = fs->op.flag_nopath;
@@ -4685,13 +4688,6 @@ struct fuse *fuse_new(struct fuse_args *args,
init_list_head(&f->full_slabs);
init_list_head(&f->lru_table);
- /* When --help or --version are specified, we print messages
- to stderr but continue for now (and keep the arguments in
- `args` for use below */
- if (fuse_opt_parse(args, &f->conf, fuse_lib_opts,
- fuse_lib_opt_proc) == -1)
- goto out_free_fs;
-
if (f->conf.modules) {
char *module;
char *next;
@@ -4707,6 +4703,11 @@ struct fuse *fuse_new(struct fuse_args *args,
}
}
+ if(f->conf.show_help) {
+ fuse_lib_help_modules();
+ goto out_free_fs;
+ }
+
if (!f->conf.ac_attr_timeout_set)
f->conf.ac_attr_timeout = f->conf.attr_timeout;
@@ -4718,16 +4719,9 @@ struct fuse *fuse_new(struct fuse_args *args,
f->conf.readdir_ino = 1;
#endif
- /* This function will return NULL if there is an --help
- or --version argument in `args` */
f->se = fuse_session_new(args, &llop, sizeof(llop), f);
- if (f->se == NULL) {
- /* If we've printed help before, add module help at
- * the end */
- if (f->conf.help)
- fuse_lib_help_modules();
+ if (f->se == NULL)
goto out_free_fs;
- }
if (f->conf.debug) {
fprintf(stderr, "nopath: %i\n", f->conf.nopath);
@@ -4783,10 +4777,10 @@ out_free_fs:
fuse_put_module(f->fs->m);
free(f->fs);
free(f->conf.modules);
-out_free:
- free(f);
out_delete_context_key:
fuse_delete_context_key();
+out_free:
+ free(f);
out:
return NULL;
}
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 1d843d1..2597c39 100755
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -2581,11 +2581,6 @@ clear_pipe:
goto out_free;
}
-enum {
- KEY_HELP,
- KEY_VERSION,
-};
-
static const struct fuse_opt fuse_ll_opts[] = {
{ "debug", offsetof(struct fuse_ll, debug), 1 },
{ "-d", offsetof(struct fuse_ll, debug), 1 },
@@ -2622,20 +2617,16 @@ static const struct fuse_opt fuse_ll_opts[] = {
{ "no_writeback_cache", offsetof(struct fuse_ll, no_writeback_cache), 1},
{ "time_gran=%u", offsetof(struct fuse_ll, conn.time_gran), 0 },
{ "clone_fd", offsetof(struct fuse_ll, clone_fd), 1 },
- FUSE_OPT_KEY("-h", KEY_HELP),
- FUSE_OPT_KEY("--help", KEY_HELP),
- FUSE_OPT_KEY("-V", KEY_VERSION),
- FUSE_OPT_KEY("--version", KEY_VERSION),
FUSE_OPT_END
};
-static void fuse_ll_version(void)
+void fuse_lowlevel_version(void)
{
printf("using FUSE kernel interface version %i.%i\n",
FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
}
-static void fuse_ll_help(void)
+void fuse_lowlevel_help(void)
{
printf(
"Low-level options\n"
@@ -2664,25 +2655,10 @@ static void fuse_ll_help(void)
static int fuse_ll_opt_proc(void *data, const char *arg, int key,
struct fuse_args *outargs)
{
- (void) data; (void) outargs; (void) arg;
-
- switch (key) {
- case KEY_HELP:
- fuse_ll_help();
- fuse_mount_help();
- break;
-
- case KEY_VERSION:
- fuse_ll_version();
- fuse_mount_version();
- break;
+ (void) data; (void) outargs; (void) key; (void) arg;
- default:
- fprintf(stderr, "fuse: unknown option `%s'\n", arg);
- }
-
- /* Fail */
- return -1;
+ /* Passthrough unknown options */
+ return 1;
}
static void fuse_ll_destroy(struct fuse_ll *f)
@@ -2888,15 +2864,23 @@ struct fuse_session *fuse_session_new(struct fuse_args *args,
f = (struct fuse_ll *) calloc(1, sizeof(struct fuse_ll));
if (f == NULL) {
fprintf(stderr, "fuse: failed to allocate fuse object\n");
- goto out;
+ goto out1;
}
/* Parse options */
mo = parse_mount_opts(args);
if (mo == NULL)
- goto out_free0;
- if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1)
- goto out_free;
+ goto out2;
+ if(fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1)
+ goto out3;
+ if (args->argc != 1) {
+ int i;
+ fprintf(stderr, "fuse: unknown option(s): `");
+ for(i = 1; i < args->argc-1; i++)
+ fprintf(stderr, "%s ", args->argv[i]);
+ fprintf(stderr, "%s'\n", args->argv[i]);
+ goto out4;
+ }
if (f->debug)
fprintf(stderr, "FUSE library version: %s\n", PACKAGE_VERSION);
@@ -2918,7 +2902,7 @@ struct fuse_session *fuse_session_new(struct fuse_args *args,
if (err) {
fprintf(stderr, "fuse: failed to create thread specific key: %s\n",
strerror(err));
- goto out_free;
+ goto out5;
}
memcpy(&f->op, op, op_size);
@@ -2928,21 +2912,24 @@ struct fuse_session *fuse_session_new(struct fuse_args *args,
se = (struct fuse_session *) malloc(sizeof(*se));
if (se == NULL) {
fprintf(stderr, "fuse: failed to allocate session\n");
- goto out_key_destroy;
+ goto out6;
}
memset(se, 0, sizeof(*se));
se->f = f;
se->mo = mo;
return se;
-out_key_destroy:
+out6:
pthread_key_delete(f->pipe_key);
-out_free:
- free(mo);
-out_free0:
+out5:
pthread_mutex_destroy(&f->lock);
+out4:
+ fuse_opt_free_args(args);
+out3:
+ free(mo);
+out2:
free(f);
-out:
+out1:
return NULL;
}
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index ee9c9d7..4327429 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -122,6 +122,10 @@ FUSE_3.0 {
fuse_lowlevel_notify_delete;
fuse_fs_flock;
fuse_fs_fallocate;
+ fuse_lowlevel_help;
+ fuse_lowlevel_version;
+ fuse_mount_help;
+ fuse_mount_version;
local:
*;
diff --git a/lib/helper.c b/lib/helper.c
index 309c096..63f26c2 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -21,36 +21,24 @@
#include <errno.h>
#include <sys/param.h>
-enum {
- KEY_HELP,
- KEY_HELP_NOHEADER,
- KEY_VERSION,
-};
-
-struct helper_opts {
- int singlethread;
- int foreground;
- int nodefault_subtype;
- char *mountpoint;
-};
-
-#define FUSE_HELPER_OPT(t, p) { t, offsetof(struct helper_opts, p), 1 }
+#define FUSE_HELPER_OPT(t, p) \
+ { t, offsetof(struct fuse_cmdline_opts, p), 1 }
static const struct fuse_opt fuse_helper_opts[] = {
+ FUSE_HELPER_OPT("-h", show_help),
+ FUSE_HELPER_OPT("--help", show_help),
+ FUSE_HELPER_OPT("-V", show_version),
+ FUSE_HELPER_OPT("--version", show_version),
+ FUSE_HELPER_OPT("-d", debug),
+ FUSE_HELPER_OPT("debug", debug),
FUSE_HELPER_OPT("-d", foreground),
FUSE_HELPER_OPT("debug", foreground),
+ FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
+ FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
FUSE_HELPER_OPT("-f", foreground),
FUSE_HELPER_OPT("-s", singlethread),
FUSE_HELPER_OPT("fsname=", nodefault_subtype),
FUSE_HELPER_OPT("subtype=", nodefault_subtype),
-
- FUSE_OPT_KEY("-h", KEY_HELP),
- FUSE_OPT_KEY("--help", KEY_HELP),
- FUSE_OPT_KEY("-ho", KEY_HELP_NOHEADER),
- FUSE_OPT_KEY("-V", KEY_VERSION),
- FUSE_OPT_KEY("--version", KEY_VERSION),
- FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
- FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
FUSE_OPT_KEY("fsname=", FUSE_OPT_KEY_KEEP),
FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_KEEP),
FUSE_OPT_END
@@ -80,23 +68,12 @@ static void helper_version(void)
static int fuse_helper_opt_proc(void *data, const char *arg, int key,
struct fuse_args *outargs)
{
- struct helper_opts *hopts = data;
+ (void) outargs;
+ struct fuse_cmdline_opts *opts = data;
switch (key) {
- case KEY_HELP:
- usage(outargs->argv[0]);
- /* fall through */
-
- case KEY_HELP_NOHEADER:
- helper_help();
- return fuse_opt_add_arg(outargs, "-h");
-
- case KEY_VERSION:
- helper_version();
- return 1;
-
case FUSE_OPT_KEY_NONOPT:
- if (!hopts->mountpoint) {
+ if (!opts->mountpoint) {
char mountpoint[PATH_MAX];
if (realpath(arg, mountpoint) == NULL) {
fprintf(stderr,
@@ -104,7 +81,7 @@ static int fuse_helper_opt_proc(void *data, const char *arg, int key,
arg, strerror(errno));
return -1;
}
- return fuse_opt_add_opt(&hopts->mountpoint, mountpoint);
+ return fuse_opt_add_opt(&opts->mountpoint, mountpoint);
} else {
fprintf(stderr, "fuse: invalid argument `%s'\n", arg);
return -1;
@@ -137,39 +114,45 @@ static int add_default_subtype(const char *progname, struct fuse_args *args)
return res;
}
-int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint,
- int *multithreaded, int *foreground)
+int fuse_parse_cmdline(struct fuse_args *args,
+ struct fuse_cmdline_opts *opts)
{
- int res;
- struct helper_opts hopts;
+ memset(opts, 0, sizeof(struct fuse_cmdline_opts));
+ if (fuse_opt_parse(args, opts, fuse_helper_opts,
+ fuse_helper_opt_proc) == -1)
+ return -1;
+
+ if (opts->show_version) {
+ helper_version();
+ fuse_lowlevel_version();
+ fuse_mount_version();
+ return -1;
+ }
- memset(&hopts, 0, sizeof(hopts));
- res = fuse_opt_parse(args, &hopts, fuse_helper_opts,
- fuse_helper_opt_proc);
- if (res == -1)
+ if (opts->show_help) {
+ usage(args->argv[0]);
+ helper_help();
+ fuse_lowlevel_help();
+ fuse_mount_help();
return -1;
+ }
- if (!hopts.nodefault_subtype) {
- res = add_default_subtype(args->argv[0], args);
- if (res == -1)
- goto err;
+ if (!opts->mountpoint) {
+ fprintf(stderr, "error: no mountpoint specified\n");
+ usage(args->argv[0]);
+ return -1;
}
- if (mountpoint)
- *mountpoint = hopts.mountpoint;
- else
- free(hopts.mountpoint);
- if (multithreaded)
- *multithreaded = !hopts.singlethread;
- if (foreground)
- *foreground = hopts.foreground;
- return 0;
+ /* If neither -o subtype nor -o fsname are specified,
+ set subtype to program's basename */
+ if (!opts->nodefault_subtype)
+ if (add_default_subtype(args->argv[0], args) == -1)
+ return -1;
-err:
- free(hopts.mountpoint);
- return -1;
+ return 0;
}
+
int fuse_daemonize(int foreground)
{
if (!foreground) {
@@ -224,81 +207,93 @@ int fuse_daemonize(int foreground)
return 0;
}
-
-static struct fuse *fuse_setup(int argc, char *argv[],
- const struct fuse_operations *op, size_t op_size,
- int *multithreaded, void *user_data)
+int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
+ size_t op_size, void *user_data)
{
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
struct fuse *fuse;
- char *mountpoint;
- int foreground;
+ struct fuse_cmdline_opts opts;
int res;
- res = fuse_parse_cmdline(&args, &mountpoint, multithreaded, &foreground);
- if (res == -1)
- return NULL;
+ memset(&opts, 0, sizeof(opts));
+ if (fuse_opt_parse(&args, &opts, fuse_helper_opts,
+ fuse_helper_opt_proc) == -1)
+ return 1;
- fuse = fuse_new(&args, op, op_size, user_data);
- if (fuse == NULL) {
- fuse_opt_free_args(&args);
- free(mountpoint);
- return NULL;
+ if (opts.show_version) {
+ helper_version();
+ fuse_lowlevel_version();
+ fuse_mount_version();
+ res = 0;
+ goto out1;
}
- res = fuse_mount(fuse, mountpoint);
- free(mountpoint);
- if (res != 0)
- goto err_out1;
-
- res = fuse_daemonize(foreground);
- if (res == -1)
- goto err_unmount;
+ /* Re-add --help for later processing by fuse_new()
+ (that way we also get help for modules options) */
+ if (opts.show_help) {
+ helper_help();
+ if (fuse_opt_add_arg(&args, "--help") == -1) {
+ res = 1;
+ goto out1;
+ }
+ }
- res = fuse_set_signal_handlers(fuse_get_session(fuse));
- if (res == -1)
- goto err_unmount;
+ if (!opts.show_help &&
+ !opts.mountpoint) {
+ fprintf(stderr, "error: no mountpoint specified\n");
+ usage(args.argv[0]);
+ res = 1;
+ goto out1;
+ }
- return fuse;
+ /* If neither -o subtype nor -o fsname are specified,
+ set subtype to program's basename */
+ if (!opts.nodefault_subtype) {
+ if (add_default_subtype(args.argv[0], &args) == -1) {
+ res = 1;
+ goto out1;
+ }
+ }
-err_unmount:
- fuse_unmount(fuse);
-err_out1:
- fuse_destroy(fuse);
- fuse_opt_free_args(&args);
- return NULL;
-}
+ /* --help is processed here and will result in NULL */
+ fuse = fuse_new(&args, op, op_size, user_data);
+ if (fuse == NULL) {
+ res = opts.show_help ? 0 : 1;
+ goto out1;
+ }
-static void fuse_teardown(struct fuse *fuse)
-{
- struct fuse_session *se = fuse_get_session(fuse);
- fuse_remove_signal_handlers(se);
- fuse_unmount(fuse);
- fuse_destroy(fuse);
-}
+ if (fuse_mount(fuse,opts.mountpoint) != 0) {
+ res = 1;
+ goto out2;
+ }
-int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
- size_t op_size, void *user_data)
-{
- struct fuse *fuse;
- int multithreaded;
- int res;
+ if (fuse_daemonize(opts.foreground) != 0) {
+ res = 1;
+ goto out3;
+ }
- fuse = fuse_setup(argc, argv, op, op_size,
- &multithreaded, user_data);
- if (fuse == NULL)
- return 1;
+ struct fuse_session *se = fuse_get_session(fuse);
+ if (fuse_set_signal_handlers(se) != 0) {
+ res = 1;
+ goto out3;
+ }
- if (multithreaded)
- res = fuse_loop_mt(fuse);
- else
+ if (opts.singlethread)
res = fuse_loop(fuse);
+ else
+ res = fuse_loop_mt(fuse);
+ if (res)
+ res = 1;
- fuse_teardown(fuse);
- if (res == -1)
- return 1;
-
- return 0;
+ fuse_remove_signal_handlers(se);
+out3:
+ fuse_unmount(fuse);
+out2:
+ fuse_destroy(fuse);
+out1:
+ free(opts.mountpoint);
+ fuse_opt_free_args(&args);
+ return res;
}
int fuse_version(void)