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:
Nikolaus Rath 2016-10-02 20:52:33 -07:00
parent a10ee045e7
commit 425db842ff
10 changed files with 323 additions and 296 deletions

View File

@ -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`.

View File

@ -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);

View File

@ -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] */

View File

@ -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
*

View File

@ -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)

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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;
}

View File

@ -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:
*;

View File

@ -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)