clean up mount option passing
diff --git a/lib/fuse.c b/lib/fuse.c
index cebca07..2b79d85 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -1550,7 +1550,36 @@
return 0;
}
-struct fuse *fuse_new(int fd, int flags, const struct fuse_operations *op)
+
+int fuse_is_lib_option(const char *opt)
+{
+ if (strcmp(opt, "debug") == 0 ||
+ strcmp(opt, "hard_remove") == 0)
+ return 1;
+ else
+ return 0;
+}
+
+static void parse_lib_opts(struct fuse *f, const char *opts)
+{
+ if (opts) {
+ char *xopts = strdup(opts);
+ char *s = xopts;
+ char *opt;
+
+ while((opt = strsep(&s, ","))) {
+ if (strcmp(opt, "debug") == 0)
+ f->flags |= FUSE_DEBUG;
+ else if (strcmp(opt, "hard_remove") == 0)
+ f->flags |= FUSE_HARD_REMOVE;
+ else
+ fprintf(stderr, "fuse: warning: unknown option `%s'\n", opt);
+ }
+ free(xopts);
+ }
+}
+
+struct fuse *fuse_new(int fd, const char *opts, const struct fuse_operations *op)
{
struct fuse *f;
struct node *root;
@@ -1562,7 +1591,7 @@
return NULL;
}
- f->flags = flags;
+ parse_lib_opts(f, opts);
f->fd = fd;
f->ctr = 0;
f->generation = 0;
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index 8942d74..58c0a41 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -10,6 +10,16 @@
#include <stdio.h>
#include <pthread.h>
+/* FUSE flags: */
+
+/** Enable debuging output */
+#define FUSE_DEBUG (1 << 1)
+
+/** If a file is removed but it's still open, don't hide the file but
+ remove it immediately */
+#define FUSE_HARD_REMOVE (1 << 2)
+
+
typedef unsigned long fino_t;
struct node {
diff --git a/lib/helper.c b/lib/helper.c
index 76b6eb7..b75855a 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -25,23 +25,31 @@
static void usage(char *progname)
{
fprintf(stderr,
- "usage: %s mountpoint [options] [-- [fusermount options]]\n"
+ "usage: %s mountpoint [options]\n"
"Options:\n"
- " -d enable debug output (implies -f)\n"
- " -f foreground operation\n"
- " -s disable multithreaded operation\n"
- " -i immediate removal (don't delay until last release)\n"
- " -h print help\n"
+ " -d enable debug output (implies -f)\n"
+ " -f foreground operation\n"
+ " -s disable multithreaded operation\n"
+ " -o opt,[opt...] mount options\n"
+ " -h print help\n"
"\n"
- "Fusermount options:\n"
- " see 'fusermount -h'\n",
+ "Mount options:\n"
+ " default_permissions enable permission checking\n"
+ " allow_other allow access to other users\n"
+ " kernel_cache cache files in kernel\n"
+ " large_read issue large read requests (2.4 only)\n"
+ " direct_io use direct I/O\n"
+ " max_read=N set maximum size of read requests\n"
+ " hard_remove immediate removal (don't hide files)\n"
+ " debug enable debug output\n"
+ " fsname=NAME set filesystem name in mtab\n",
progname);
exit(1);
}
static void invalid_option(char *argv[], int argctr)
{
- fprintf(stderr, "invalid option: %s\n", argv[argctr]);
+ fprintf(stderr, "invalid option: %s\n\n", argv[argctr]);
usage(argv[0]);
}
@@ -81,12 +89,12 @@
set_one_signal_handler(SIGPIPE, SIG_IGN);
}
-static int fuse_start(int fuse_fd, int flags, int multithreaded,
+static int fuse_do(int fuse_fd, const char *opts, int multithreaded,
int background, const struct fuse_operations *op)
{
int pid;
- fuse = fuse_new(fuse_fd, flags, op);
+ fuse = fuse_new(fuse_fd, opts, op);
if (fuse == NULL)
return 1;
@@ -111,35 +119,79 @@
return 0;
}
+static void add_option_to(const char *opt, char **optp)
+{
+ unsigned len = strlen(opt);
+ if (*optp) {
+ unsigned oldlen = strlen(*optp);
+ *optp = realloc(*optp, oldlen + 1 + len + 1);
+ (*optp)[oldlen] = ',';
+ strcpy(*optp + oldlen + 1, opt);
+ } else {
+ *optp = malloc(len + 1);
+ strcpy(*optp, opt);
+ }
+}
+
+static void add_options(char **lib_optp, char **kernel_optp, const char *opts)
+{
+ char *xopts = strdup(opts);
+ char *s = xopts;
+ char *opt;
+
+ while((opt = strsep(&s, ",")) != NULL) {
+ if (fuse_is_lib_option(opt))
+ add_option_to(opt, lib_optp);
+ else
+ add_option_to(opt, kernel_optp);
+ }
+ free(xopts);
+}
+
void fuse_main(int argc, char *argv[], const struct fuse_operations *op)
{
int argctr;
- int flags;
int multithreaded;
int background;
int fuse_fd;
char *fuse_mountpoint = NULL;
- char **fusermount_args = NULL;
- char *newargs[3];
char *basename;
+ char *kernel_opts = NULL;
+ char *lib_opts = NULL;
+ char *fsname_opt;
int err;
+
+ basename = strrchr(argv[0], '/');
+ if (basename == NULL)
+ basename = argv[0];
+ else if (basename[1] != '\0')
+ basename++;
+
+ fsname_opt = malloc(strlen(basename) + 64);
+ sprintf(fsname_opt, "fsname=%s", basename);
+ add_options(&lib_opts, &kernel_opts, fsname_opt);
+ free(fsname_opt);
- flags = 0;
multithreaded = 1;
background = 1;
- for (argctr = 1; argctr < argc && !fusermount_args; argctr ++) {
+ 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\n");
+ usage(argv[0]);
+ }
+ argctr ++;
+ add_options(&lib_opts, &kernel_opts, argv[argctr]);
+ break;
+
case 'd':
- flags |= FUSE_DEBUG;
+ add_options(&lib_opts, &kernel_opts, "debug");
background = 0;
break;
- case 'i':
- flags |= FUSE_HARD_REMOVE;
- break;
-
case 'f':
background = 0;
break;
@@ -152,15 +204,15 @@
usage(argv[0]);
break;
- case '-':
- fusermount_args = &argv[argctr+1];
- break;
-
default:
invalid_option(argv, argctr);
}
- else
- invalid_option(argv, argctr);
+ else {
+ if (argv[argctr][1] == 'o')
+ add_options(&lib_opts, &kernel_opts, &argv[argctr][2]);
+ else
+ invalid_option(argv, argctr);
+ }
} else if (fuse_mountpoint == NULL)
fuse_mountpoint = strdup(argv[argctr]);
else
@@ -168,30 +220,19 @@
}
if (fuse_mountpoint == NULL) {
- fprintf(stderr, "missing mountpoint\n");
+ fprintf(stderr, "missing mountpoint\n\n");
usage(argv[0]);
}
- if (fusermount_args != NULL)
- fusermount_args -= 2; /* Hack! */
- else {
- fusermount_args = newargs;
- fusermount_args[2] = NULL;
- }
- basename = strrchr(argv[0], '/');
- if (basename == NULL)
- basename = argv[0];
- else if (basename[1] != '\0')
- basename++;
-
- fusermount_args[0] = "-n";
- fusermount_args[1] = basename;
-
- fuse_fd = fuse_mount(fuse_mountpoint, (const char **) fusermount_args);
+ fuse_fd = fuse_mount(fuse_mountpoint, kernel_opts);
if (fuse_fd == -1)
exit(1);
+ if (kernel_opts)
+ free(kernel_opts);
- err = fuse_start(fuse_fd, flags, multithreaded, background, op);
+ err = fuse_do(fuse_fd, lib_opts, multithreaded, background, op);
+ if (lib_opts)
+ free(lib_opts);
close(fuse_fd);
fuse_unmount(fuse_mountpoint);
if (err)
diff --git a/lib/mount.c b/lib/mount.c
index 648dfbc..05dcb59 100644
--- a/lib/mount.c
+++ b/lib/mount.c
@@ -78,7 +78,7 @@
system(umount_cmd);
}
-int fuse_mount(const char *mountpoint, const char *args[])
+int fuse_mount(const char *mountpoint, const char *opts)
{
const char *mountprog = FUSERMOUNT_PROG;
int fds[2], pid;
@@ -101,28 +101,14 @@
if(pid == 0) {
char env[10];
- char **newargv;
- int numargs = 0;
- int actr;
- int i;
-
- if(args != NULL)
- while(args[numargs] != NULL)
- numargs ++;
-
- newargv = (char **) malloc((1 + numargs + 2) * sizeof(char *));
- actr = 0;
- newargv[actr++] = strdup(mountprog);
- for(i = 0; i < numargs; i++)
- newargv[actr++] = strdup(args[i]);
- newargv[actr++] = strdup(mountpoint);
- newargv[actr++] = NULL;
+ const char *argv[] = {mountprog, opts ? "-o" : mountpoint, opts,
+ mountpoint, NULL};
close(fds[1]);
fcntl(fds[0], F_SETFD, 0);
snprintf(env, sizeof(env), "%i", fds[0]);
setenv(FUSE_COMMFD_ENV, env, 1);
- execvp(mountprog, newargv);
+ execvp(mountprog, (char **) argv);
perror("fuse: failed to exec fusermount");
exit(1);
}