mirror of
https://github.com/libfuse/libfuse.git
synced 2024-11-27 06:04:27 +08:00
Don't handle --help and --version in fuse_session_new().
Help and version messages can be generated using the new fuse_lowlevel_help(), fuse_lowlevel_version(), fuse_mount_help(), and fuse_mount_version() functions. The fuse_parse_cmdline() function has been made more powerful to do this automatically, and is now explicitly intended only for low-level API users. This is a code simplication patch. We don't have to parse for --help and --version in quite as many places, and we no longer have a low-level initialization function be responsible for the (super-high level) task of printing a program usage message. In the high-level API, we can now handle the command line parsing earlier and avoid running other initialization code if we're just going to abort later on.
This commit is contained in:
parent
a10ee045e7
commit
425db842ff
@ -2,12 +2,20 @@ Unreleased Changes
|
||||
==================
|
||||
|
||||
* The `fuse_lowlevel_new` function has been renamed to
|
||||
`fuse_session_new`.
|
||||
`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 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.
|
||||
* 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`.
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
struct fuse_cmdline_opts opts;
|
||||
int ret = -1;
|
||||
|
||||
if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != 0)
|
||||
goto err_out;
|
||||
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] */
|
||||
|
@ -208,34 +208,6 @@ struct fuse_conn_info {
|
||||
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
|
||||
*
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
74
lib/fuse.c
74
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;
|
||||
}
|
||||
|
@ -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;
|
||||
(void) data; (void) outargs; (void) key; (void) arg;
|
||||
|
||||
switch (key) {
|
||||
case KEY_HELP:
|
||||
fuse_ll_help();
|
||||
fuse_mount_help();
|
||||
break;
|
||||
|
||||
case KEY_VERSION:
|
||||
fuse_ll_version();
|
||||
fuse_mount_version();
|
||||
break;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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:
|
||||
*;
|
||||
|
249
lib/helper.c
249
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(&hopts, 0, sizeof(hopts));
|
||||
res = fuse_opt_parse(args, &hopts, fuse_helper_opts,
|
||||
fuse_helper_opt_proc);
|
||||
if (res == -1)
|
||||
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 (!hopts.nodefault_subtype) {
|
||||
res = add_default_subtype(args->argv[0], args);
|
||||
if (res == -1)
|
||||
goto err;
|
||||
if (opts->show_version) {
|
||||
helper_version();
|
||||
fuse_lowlevel_version();
|
||||
fuse_mount_version();
|
||||
return -1;
|
||||
}
|
||||
if (mountpoint)
|
||||
*mountpoint = hopts.mountpoint;
|
||||
else
|
||||
free(hopts.mountpoint);
|
||||
|
||||
if (multithreaded)
|
||||
*multithreaded = !hopts.singlethread;
|
||||
if (foreground)
|
||||
*foreground = hopts.foreground;
|
||||
if (opts->show_help) {
|
||||
usage(args->argv[0]);
|
||||
helper_help();
|
||||
fuse_lowlevel_help();
|
||||
fuse_mount_help();
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!opts->mountpoint) {
|
||||
fprintf(stderr, "error: no mountpoint specified\n");
|
||||
usage(args->argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
|
||||
return 0;
|
||||
|
||||
err:
|
||||
free(hopts.mountpoint);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
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)
|
||||
{
|
||||
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
|
||||
struct fuse *fuse;
|
||||
char *mountpoint;
|
||||
int foreground;
|
||||
int res;
|
||||
|
||||
res = fuse_parse_cmdline(&args, &mountpoint, multithreaded, &foreground);
|
||||
if (res == -1)
|
||||
return NULL;
|
||||
|
||||
fuse = fuse_new(&args, op, op_size, user_data);
|
||||
if (fuse == NULL) {
|
||||
fuse_opt_free_args(&args);
|
||||
free(mountpoint);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
res = fuse_mount(fuse, mountpoint);
|
||||
free(mountpoint);
|
||||
if (res != 0)
|
||||
goto err_out1;
|
||||
|
||||
res = fuse_daemonize(foreground);
|
||||
if (res == -1)
|
||||
goto err_unmount;
|
||||
|
||||
res = fuse_set_signal_handlers(fuse_get_session(fuse));
|
||||
if (res == -1)
|
||||
goto err_unmount;
|
||||
|
||||
return fuse;
|
||||
|
||||
err_unmount:
|
||||
fuse_unmount(fuse);
|
||||
err_out1:
|
||||
fuse_destroy(fuse);
|
||||
fuse_opt_free_args(&args);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
int multithreaded;
|
||||
struct fuse_cmdline_opts opts;
|
||||
int res;
|
||||
|
||||
fuse = fuse_setup(argc, argv, op, op_size,
|
||||
&multithreaded, user_data);
|
||||
if (fuse == NULL)
|
||||
memset(&opts, 0, sizeof(opts));
|
||||
if (fuse_opt_parse(&args, &opts, fuse_helper_opts,
|
||||
fuse_helper_opt_proc) == -1)
|
||||
return 1;
|
||||
|
||||
if (multithreaded)
|
||||
res = fuse_loop_mt(fuse);
|
||||
else
|
||||
if (opts.show_version) {
|
||||
helper_version();
|
||||
fuse_lowlevel_version();
|
||||
fuse_mount_version();
|
||||
res = 0;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
if (!opts.show_help &&
|
||||
!opts.mountpoint) {
|
||||
fprintf(stderr, "error: no mountpoint specified\n");
|
||||
usage(args.argv[0]);
|
||||
res = 1;
|
||||
goto out1;
|
||||
}
|
||||
|
||||
/* 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;
|
||||
}
|
||||
}
|
||||
|
||||
/* --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;
|
||||
}
|
||||
|
||||
if (fuse_mount(fuse,opts.mountpoint) != 0) {
|
||||
res = 1;
|
||||
goto out2;
|
||||
}
|
||||
|
||||
if (fuse_daemonize(opts.foreground) != 0) {
|
||||
res = 1;
|
||||
goto out3;
|
||||
}
|
||||
|
||||
struct fuse_session *se = fuse_get_session(fuse);
|
||||
if (fuse_set_signal_handlers(se) != 0) {
|
||||
res = 1;
|
||||
goto out3;
|
||||
}
|
||||
|
||||
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)
|
||||
|
Loading…
Reference in New Issue
Block a user