aboutsummaryrefslogtreecommitdiffstats
path: root/lib/helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'lib/helper.c')
-rw-r--r--lib/helper.c320
1 files changed, 134 insertions, 186 deletions
diff --git a/lib/helper.c b/lib/helper.c
index bb8243c..1f99c2f 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -7,9 +7,11 @@
*/
#include "fuse_i.h"
+#include "fuse_opt.h"
#include <stdio.h>
#include <stdlib.h>
+#include <stddef.h>
#include <unistd.h>
#include <string.h>
#include <limits.h>
@@ -52,12 +54,6 @@ static void usage(const char *progname)
);
}
-static void invalid_option(const char *argv[], int argctr)
-{
- fprintf(stderr, "fuse: invalid option: %s\n\n", argv[argctr]);
- fprintf(stderr, "see `%s -h' for usage\n", argv[0]);
-}
-
static void exit_handler(int sig)
{
(void) sig;
@@ -99,187 +95,140 @@ static int set_signal_handlers(void)
return 0;
}
-static int opt_member(const char *opts, const char *opt)
+enum {
+ KEY_HELP,
+ KEY_HELP_NOHEADER,
+ KEY_DEBUG,
+ KEY_KERN,
+ KEY_ALLOW_ROOT,
+ KEY_RO,
+};
+
+struct helper_opts {
+ const char *progname;
+ int singlethread;
+ int foreground;
+ int allow_other;
+ int allow_root;
+ int fsname;
+ char *kernel_opts;
+ char *lib_opts;
+ char *mountpoint;
+};
+
+#define FUSE_HELPER_OPT(t, p) { t, offsetof(struct helper_opts, p), 1 }
+#define FUSE_HELPER_KEY(t, k) { t, FUSE_OPT_OFFSET_KEY, k }
+
+static const struct fuse_opt fuse_helper_opts[] = {
+ FUSE_HELPER_OPT("-d", foreground),
+ FUSE_HELPER_OPT("debug", foreground),
+ FUSE_HELPER_OPT("-f", foreground),
+ FUSE_HELPER_OPT("-s", singlethread),
+ FUSE_HELPER_OPT("allow_other", allow_other),
+ FUSE_HELPER_OPT("allow_root", allow_root),
+ FUSE_HELPER_OPT("fsname=", fsname),
+
+ FUSE_HELPER_KEY("-h", KEY_HELP),
+ FUSE_HELPER_KEY("--help", KEY_HELP),
+ FUSE_HELPER_KEY("-ho", KEY_HELP_NOHEADER),
+ FUSE_HELPER_KEY("-d", KEY_DEBUG),
+ FUSE_HELPER_KEY("debug", KEY_DEBUG),
+ FUSE_HELPER_KEY("allow_other", KEY_KERN),
+ FUSE_HELPER_KEY("allow_root", KEY_ALLOW_ROOT),
+ FUSE_HELPER_KEY("nonempty", KEY_KERN),
+ FUSE_HELPER_KEY("default_permissions", KEY_KERN),
+ FUSE_HELPER_KEY("fsname=", KEY_KERN),
+ FUSE_HELPER_KEY("large_read", KEY_KERN),
+ FUSE_HELPER_KEY("max_read=", KEY_KERN),
+ FUSE_HELPER_KEY("-r", KEY_RO),
+ FUSE_HELPER_KEY("ro", KEY_KERN),
+ FUSE_HELPER_KEY("rw", KEY_KERN),
+ FUSE_HELPER_KEY("suid", KEY_KERN),
+ FUSE_HELPER_KEY("nosuid", KEY_KERN),
+ FUSE_HELPER_KEY("dev", KEY_KERN),
+ FUSE_HELPER_KEY("nodev", KEY_KERN),
+ FUSE_HELPER_KEY("exec", KEY_KERN),
+ FUSE_HELPER_KEY("noexec", KEY_KERN),
+ FUSE_HELPER_KEY("async", KEY_KERN),
+ FUSE_HELPER_KEY("sync", KEY_KERN),
+ FUSE_HELPER_KEY("atime", KEY_KERN),
+ FUSE_HELPER_KEY("noatime", KEY_KERN),
+ FUSE_OPT_END
+};
+
+static int fuse_helper_opt_proc(void *data, const char *arg, int key)
{
- const char *e, *s = opts;
- int optlen = strlen(opt);
- for (s = opts; s; s = e + 1) {
- if(!(e = strchr(s, ',')))
+ struct helper_opts *hopts = data;
+
+ switch (key) {
+ case KEY_HELP:
+ case KEY_HELP_NOHEADER:
+ usage(key == KEY_HELP ? hopts->progname : NULL);
+ exit(1);
+
+ case FUSE_OPT_KEY_OPT:
+ return fuse_opt_add_opt(&hopts->lib_opts, arg);
+
+ case FUSE_OPT_KEY_NONOPT:
+ if (hopts->mountpoint)
break;
- if (e - s == optlen && strncmp(s, opt, optlen) == 0)
- return 1;
- }
- return (s && strcmp(s, opt) == 0);
-}
-static int add_option_to(const char *opt, char **optp)
-{
- unsigned len = strlen(opt);
- if (*optp) {
- unsigned oldlen = strlen(*optp);
- *optp = (char *) realloc(*optp, oldlen + 1 + len + 1);
- if (*optp == NULL)
- return -1;
- (*optp)[oldlen] = ',';
- strcpy(*optp + oldlen + 1, opt);
- } else {
- *optp = (char *) malloc(len + 1);
- if (*optp == NULL)
+ return fuse_opt_add_opt(&hopts->mountpoint, arg);
+
+ case KEY_DEBUG:
+ return fuse_opt_add_opt(&hopts->lib_opts, "debug");
+
+ case KEY_ALLOW_ROOT:
+ if (fuse_opt_add_opt(&hopts->kernel_opts, "allow_other") == -1 ||
+ fuse_opt_add_opt(&hopts->lib_opts, "allow_root") == -1)
return -1;
- strcpy(*optp, opt);
+ return 0;
+
+ case KEY_RO:
+ arg = "ro";
+ /* fall through */
+
+ case KEY_KERN:
+ return fuse_opt_add_opt(&hopts->kernel_opts, arg);
}
- return 0;
+
+ fprintf(stderr, "fuse: invalid option `%s'\n", arg);
+ return -1;
}
-static int add_options(char **lib_optp, char **kernel_optp, const char *opts)
+static int fuse_parse_cmdline(int argc, const char *argv[],
+ struct helper_opts *hopts)
{
- char *xopts = strdup(opts);
- char *s = xopts;
- char *opt;
- int has_allow_other = 0;
- int has_allow_root = 0;
-
- if (xopts == NULL) {
- fprintf(stderr, "fuse: memory allocation failed\n");
+ int res;
+
+ hopts->progname = argv[0];
+ res = fuse_opt_parse(argc, (char **) argv, hopts, fuse_helper_opts,
+ fuse_helper_opt_proc, NULL, NULL);
+ if (res == -1)
return -1;
- }
- while((opt = strsep(&s, ",")) != NULL) {
- int res;
- if (fuse_is_lib_option(opt)) {
- res = add_option_to(opt, lib_optp);
- /* Compatibility hack */
- if (strcmp(opt, "allow_root") == 0 && res != -1) {
- has_allow_root = 1;
- res = add_option_to("allow_other", kernel_optp);
- }
- }
- else {
- res = add_option_to(opt, kernel_optp);
- if (strcmp(opt, "allow_other") == 0)
- has_allow_other = 1;
- }
- if (res == -1) {
- fprintf(stderr, "fuse: memory allocation failed\n");
- return -1;
- }
- }
- if (has_allow_other && has_allow_root) {
+ if (hopts->allow_other && hopts->allow_root) {
fprintf(stderr, "fuse: 'allow_other' and 'allow_root' options are mutually exclusive\n");
return -1;
}
- free(xopts);
- return 0;
-}
-static int fuse_parse_cmdline(int argc, const char *argv[], char **kernel_opts,
- char **lib_opts, char **mountpoint,
- int *multithreaded, int *background)
-{
- int res;
- int argctr;
- const char *basename;
- char *fsname_opt;
-
- *kernel_opts = NULL;
- *lib_opts = NULL;
- *mountpoint = NULL;
- *multithreaded = 1;
- *background = 1;
-
- basename = strrchr(argv[0], '/');
- if (basename == NULL)
- basename = argv[0];
- else if (basename[1] != '\0')
- basename++;
-
- fsname_opt = (char *) malloc(strlen(basename) + 64);
- if (fsname_opt == NULL) {
- fprintf(stderr, "fuse: memory allocation failed\n");
- return -1;
- }
- sprintf(fsname_opt, "fsname=%s", basename);
- res = add_options(lib_opts, kernel_opts, fsname_opt);
- free(fsname_opt);
- if (res == -1)
- goto err;
-
- for (argctr = 1; argctr < argc; argctr ++) {
- if (argv[argctr][0] == '-') {
- if (strlen(argv[argctr]) == 2)
- switch (argv[argctr][1]) {
- case 'o':
- if (argctr + 1 == argc || argv[argctr+1][0] == '-') {
- fprintf(stderr, "missing option after -o\n");
- fprintf(stderr, "see `%s -h' for usage\n", argv[0]);
- goto err;
- }
- argctr ++;
- res = add_options(lib_opts, kernel_opts, argv[argctr]);
- if (res == -1)
- goto err;
- break;
-
- case 'd':
- res = add_options(lib_opts, kernel_opts, "debug");
- if (res == -1)
- goto err;
- break;
-
- case 'r':
- res = add_options(lib_opts, kernel_opts, "ro");
- if (res == -1)
- goto err;
- break;
-
- case 'f':
- *background = 0;
- break;
-
- case 's':
- *multithreaded = 0;
- break;
-
- case 'h':
- usage(argv[0]);
- goto err;
-
- default:
- invalid_option(argv, argctr);
- goto err;
- }
- else {
- if (argv[argctr][1] == 'o') {
- res = add_options(lib_opts, kernel_opts, &argv[argctr][2]);
- if (res == -1)
- goto err;
- } else if(strcmp(argv[argctr], "-ho") == 0) {
- usage(NULL);
- goto err;
- } else {
- invalid_option(argv, argctr);
- goto err;
- }
- }
- } else if (*mountpoint == NULL) {
- *mountpoint = strdup(argv[argctr]);
- if (*mountpoint == NULL) {
- fprintf(stderr, "fuse: memory allocation failed\n");
- goto err;
- }
- }
- else {
- invalid_option(argv, argctr);
- goto err;
+ if (!hopts->fsname) {
+ char *fsname_opt;
+ const char *basename = strrchr(argv[0], '/');
+ if (basename == NULL)
+ basename = argv[0];
+ else if (basename[1] != '\0')
+ basename++;
+
+ fsname_opt = (char *) malloc(strlen(basename) + 64);
+ if (fsname_opt == NULL) {
+ fprintf(stderr, "fuse: memory allocation failed\n");
+ return -1;
}
+ sprintf(fsname_opt, "fsname=%s", basename);
+ fuse_opt_add_opt(&hopts->kernel_opts, fsname_opt);
}
return 0;
-
- err:
- free(*kernel_opts);
- free(*lib_opts);
- free(*mountpoint);
- return -1;
}
static struct fuse *fuse_setup_common(int argc, char *argv[],
@@ -291,9 +240,7 @@ static struct fuse *fuse_setup_common(int argc, char *argv[],
int compat)
{
struct fuse *fuse;
- int background;
- char *kernel_opts;
- char *lib_opts;
+ struct helper_opts hopts;
int res;
if (fuse_instance != NULL) {
@@ -301,21 +248,20 @@ static struct fuse *fuse_setup_common(int argc, char *argv[],
return NULL;
}
- res = fuse_parse_cmdline(argc, (const char **) argv, &kernel_opts,
- &lib_opts, mountpoint, multithreaded,
- &background);
+ memset(&hopts, 0, sizeof(hopts));
+ res = fuse_parse_cmdline(argc, (const char **) argv, &hopts);
if (res == -1)
- return NULL;
+ goto err_free;
- *fd = fuse_mount(*mountpoint, kernel_opts);
+ *fd = fuse_mount(hopts.mountpoint, hopts.kernel_opts);
if (*fd == -1)
goto err_free;
- fuse = fuse_new_common(*fd, lib_opts, op, op_size, compat);
+ fuse = fuse_new_common(*fd, hopts.lib_opts, op, op_size, compat);
if (fuse == NULL)
goto err_unmount;
- if (background && !opt_member(lib_opts, "debug")) {
+ if (!hopts.foreground) {
res = daemon(0, 0);
if (res == -1) {
perror("fuse: failed to daemonize program\n");
@@ -327,19 +273,21 @@ static struct fuse *fuse_setup_common(int argc, char *argv[],
if (res == -1)
goto err_destroy;
+ *mountpoint = hopts.mountpoint;
+ *multithreaded = !hopts.singlethread;
fuse_instance = fuse;
- free(kernel_opts);
- free(lib_opts);
+ free(hopts.kernel_opts);
+ free(hopts.lib_opts);
return fuse;
err_destroy:
fuse_destroy(fuse);
err_unmount:
- fuse_unmount(*mountpoint);
+ fuse_unmount(hopts.mountpoint);
err_free:
- free(kernel_opts);
- free(lib_opts);
- free(*mountpoint);
+ free(hopts.mountpoint);
+ free(hopts.kernel_opts);
+ free(hopts.lib_opts);
return NULL;
}