diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/fuse.c | 17 | ||||
-rw-r--r-- | lib/fuse_i.h | 59 | ||||
-rwxr-xr-x | lib/fuse_lowlevel.c | 72 | ||||
-rw-r--r-- | lib/fuse_versionscript | 5 | ||||
-rw-r--r-- | lib/helper.c | 44 | ||||
-rw-r--r-- | lib/mount.c | 98 | ||||
-rw-r--r-- | lib/mount_bsd.c | 71 |
7 files changed, 217 insertions, 149 deletions
@@ -4631,7 +4631,7 @@ void fuse_stop_cleanup_thread(struct fuse *f) } } -struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args, +struct fuse *fuse_new(struct fuse_args *args, const struct fuse_operations *op, size_t op_size, void *user_data) { @@ -4721,13 +4721,13 @@ struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args, 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(); goto out_free_fs; } - fuse_session_add_chan(f->se, ch); - if (f->conf.debug) { fprintf(stderr, "nopath: %i\n", f->conf.nopath); } @@ -4837,12 +4837,11 @@ void fuse_destroy(struct fuse *f) fuse_delete_context_key(); } -struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args) -{ - return fuse_session_mount(mountpoint, args); +int fuse_mount(struct fuse *f, const char *mountpoint) { + return fuse_session_mount(fuse_get_session(f), mountpoint); } -void fuse_unmount(const char *mountpoint, struct fuse_chan *ch) -{ - fuse_session_unmount(mountpoint, ch); + +void fuse_unmount(struct fuse *f) { + return fuse_session_unmount(fuse_get_session(f)); } diff --git a/lib/fuse_i.h b/lib/fuse_i.h index dca588a..c4d0709 100644 --- a/lib/fuse_i.h +++ b/lib/fuse_i.h @@ -11,13 +11,16 @@ struct fuse_chan; struct fuse_ll; +struct mount_opts; struct fuse_session { struct fuse_ll *f; + char *mountpoint; volatile int exited; struct fuse_chan *ch; + struct mount_opts *mo; }; struct fuse_chan { @@ -116,7 +119,11 @@ struct fuse_module { int fuse_chan_clearfd(struct fuse_chan *ch); void fuse_chan_close(struct fuse_chan *ch); -/** +/* ----------------------------------------------------------- * + * Channel interface * + * ----------------------------------------------------------- */ + + /** * Create a new channel * * @param op channel operations @@ -133,8 +140,56 @@ struct fuse_chan *fuse_chan_new(int fd); */ struct fuse_session *fuse_chan_session(struct fuse_chan *ch); +/** + * Remove the channel from a session + * + * If the channel is not assigned to a session, then this is a no-op + * + * @param ch the channel to remove + */ +void fuse_session_remove_chan(struct fuse_chan *ch); + +/** + * Assign a channel to a session + * + * If a session is destroyed, the assigned channel is also destroyed + * + * @param se the session + * @param ch the channel + */ +void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch); + +/** + * Return channel assigned to the session + * + * @param se the session + * @return the channel + */ +struct fuse_chan *fuse_session_chan(struct fuse_session *se); + +/** + * Obtain counted reference to the channel + * + * @param ch the channel + * @return the channel + */ +struct fuse_chan *fuse_chan_get(struct fuse_chan *ch); + +/** + * Drop counted reference to a channel + * + * @param ch the channel + */ +void fuse_chan_put(struct fuse_chan *ch); + + +struct mount_opts *parse_mount_opts(struct fuse_args *args); +void destroy_mount_opts(struct mount_opts *mo); +void fuse_mount_help(void); +void fuse_mount_version(void); + void fuse_kern_unmount(const char *mountpoint, int fd); -int fuse_kern_mount(const char *mountpoint, struct fuse_args *args); +int fuse_kern_mount(const char *mountpoint, struct mount_opts *mo); int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov, int count); diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c index 92265cc..43539da 100755 --- a/lib/fuse_lowlevel.c +++ b/lib/fuse_lowlevel.c @@ -2437,10 +2437,9 @@ static int fuse_ll_copy_from_pipe(struct fuse_bufvec *dst, } void fuse_session_process_buf(struct fuse_session *se, - const struct fuse_buf *buf, - struct fuse_chan *ch) + const struct fuse_buf *buf) { - fuse_session_process_buf_int(se, buf, ch); + fuse_session_process_buf_int(se, buf, se->ch); } void fuse_session_process_buf_int(struct fuse_session *se, @@ -2666,15 +2665,17 @@ 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) 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; default: @@ -2706,6 +2707,7 @@ void fuse_session_destroy(struct fuse_session *se) { fuse_ll_destroy(se->f); fuse_chan_put(se->ch); + destroy_mount_opts(se->mo); free(se); } @@ -2716,10 +2718,9 @@ static void fuse_ll_pipe_destructor(void *data) fuse_ll_pipe_free(llp); } -int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf, - struct fuse_chan *ch) +int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf) { - return fuse_session_receive_buf_int(se, buf, ch); + return fuse_session_receive_buf_int(se, buf, se->ch); } int fuse_session_receive_buf_int(struct fuse_session *se, struct fuse_buf *buf, @@ -2878,6 +2879,7 @@ struct fuse_session *fuse_session_new(struct fuse_args *args, int err; struct fuse_ll *f; struct fuse_session *se; + struct mount_opts *mo; if (sizeof(struct fuse_lowlevel_ops) < op_size) { fprintf(stderr, "fuse: warning: library too old, some operations may not work\n"); @@ -2890,6 +2892,16 @@ struct fuse_session *fuse_session_new(struct fuse_args *args, goto out; } + /* 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; + + if (f->debug) + fprintf(stderr, "FUSE library version: %s\n", PACKAGE_VERSION); + f->conn.async_read = 1; f->conn.max_write = UINT_MAX; f->conn.max_readahead = UINT_MAX; @@ -2910,12 +2922,6 @@ struct fuse_session *fuse_session_new(struct fuse_args *args, goto out_free; } - if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1) - goto out_key_destroy; - - if (f->debug) - fprintf(stderr, "FUSE library version: %s\n", PACKAGE_VERSION); - memcpy(&f->op, op, op_size); f->owner = getuid(); f->userdata = userdata; @@ -2927,19 +2933,21 @@ struct fuse_session *fuse_session_new(struct fuse_args *args, } memset(se, 0, sizeof(*se)); se->f = f; + se->mo = mo; return se; out_key_destroy: pthread_key_delete(f->pipe_key); out_free: + free(mo); +out_free0: pthread_mutex_destroy(&f->lock); free(f); out: return NULL; } -struct fuse_chan *fuse_session_mount(const char *mountpoint, - struct fuse_args *args) +int fuse_session_mount(struct fuse_session *se, const char *mountpoint) { struct fuse_chan *ch; int fd; @@ -2954,23 +2962,39 @@ struct fuse_chan *fuse_session_mount(const char *mountpoint, close(fd); } while (fd >= 0 && fd <= 2); - fd = fuse_kern_mount(mountpoint, args); + /* Open channel */ + fd = fuse_kern_mount(mountpoint, se->mo); if (fd == -1) - return NULL; + return -1; ch = fuse_chan_new(fd); if (!ch) - fuse_kern_unmount(mountpoint, fd); + goto error_out; + + /* Add channel to session */ + fuse_session_add_chan(se, ch); - return ch; + /* Save mountpoint */ + se->mountpoint = strdup(mountpoint); + if (se->mountpoint == NULL) + goto error_out; + + return 0; + +error_out: + fuse_kern_unmount(mountpoint, fd); + return -1; } -void fuse_session_unmount(const char *mountpoint, struct fuse_chan *ch) +void fuse_session_unmount(struct fuse_session *se) { - if (mountpoint) { - int fd = ch ? fuse_chan_clearfd(ch) : -1; - fuse_kern_unmount(mountpoint, fd); - fuse_chan_put(ch); + fuse_session_remove_chan(se->ch); + if (se->mountpoint) { + int fd = se->ch ? fuse_chan_clearfd(se->ch) : -1; + fuse_kern_unmount(se->mountpoint, fd); + fuse_chan_put(se->ch); + free(se->mountpoint); + se->mountpoint = NULL; } } diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript index eacd37a..ee9c9d7 100644 --- a/lib/fuse_versionscript +++ b/lib/fuse_versionscript @@ -4,8 +4,6 @@ FUSE_3.0 { fuse_exit; fuse_loop; fuse_loop_mt; - fuse_chan_destroy; - fuse_chan_fd; fuse_reply_attr; fuse_reply_buf; fuse_reply_entry; @@ -15,13 +13,11 @@ FUSE_3.0 { fuse_reply_write; fuse_reply_xattr; fuse_req_userdata; - fuse_session_add_chan; fuse_session_destroy; fuse_session_exit; fuse_session_exited; fuse_session_loop; fuse_session_loop_mt; - fuse_session_chan; fuse_session_reset; fuse_opt_parse; fuse_opt_add_opt; @@ -48,7 +44,6 @@ FUSE_3.0 { fuse_reply_lock; fuse_req_interrupt_func; fuse_req_interrupted; - fuse_session_remove_chan; fuse_unmount; fuse_session_unmount; fuse_fs_access; diff --git a/lib/helper.c b/lib/helper.c index cd1a54b..7ee767b 100644 --- a/lib/helper.c +++ b/lib/helper.c @@ -227,30 +227,32 @@ 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, - char **mountpoint, int *multithreaded, void *user_data) + 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_chan *ch; struct fuse *fuse; + char *mountpoint; int foreground; int res; - res = fuse_parse_cmdline(&args, mountpoint, multithreaded, &foreground); + res = fuse_parse_cmdline(&args, &mountpoint, multithreaded, &foreground); if (res == -1) return NULL; - ch = fuse_mount(*mountpoint, &args); - if (!ch) { + fuse = fuse_new(&args, op, op_size, user_data); + if (fuse == NULL) { fuse_opt_free_args(&args); - goto err_free; + free(mountpoint); + return NULL; } - fuse = fuse_new(ch, &args, op, op_size, user_data); - fuse_opt_free_args(&args); - if (fuse == NULL) - goto err_unmount; + res = fuse_mount(fuse, mountpoint); + free(mountpoint); + if (res != 0) + goto err_out1; res = fuse_daemonize(foreground); if (res == -1) @@ -263,33 +265,29 @@ static struct fuse *fuse_setup(int argc, char *argv[], return fuse; err_unmount: - fuse_unmount(*mountpoint, ch); - if (fuse) - fuse_destroy(fuse); -err_free: - free(*mountpoint); + fuse_unmount(fuse); +err_out1: + fuse_destroy(fuse); + fuse_opt_free_args(&args); return NULL; } -static void fuse_teardown(struct fuse *fuse, char *mountpoint) +static void fuse_teardown(struct fuse *fuse) { struct fuse_session *se = fuse_get_session(fuse); - struct fuse_chan *ch = fuse_session_chan(se); fuse_remove_signal_handlers(se); - fuse_unmount(mountpoint, ch); + fuse_unmount(fuse); fuse_destroy(fuse); - free(mountpoint); } int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op, size_t op_size, void *user_data) { struct fuse *fuse; - char *mountpoint; int multithreaded; int res; - fuse = fuse_setup(argc, argv, op, op_size, &mountpoint, + fuse = fuse_setup(argc, argv, op, op_size, &multithreaded, user_data); if (fuse == NULL) return 1; @@ -299,7 +297,7 @@ int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op, else res = fuse_loop(fuse); - fuse_teardown(fuse, mountpoint); + fuse_teardown(fuse); if (res == -1) return 1; diff --git a/lib/mount.c b/lib/mount.c index b2b841d..fb17c00 100644 --- a/lib/mount.c +++ b/lib/mount.c @@ -57,14 +57,11 @@ enum { KEY_MTAB_OPT, KEY_ALLOW_ROOT, KEY_RO, - KEY_HELP, - KEY_VERSION, }; struct mount_opts { int allow_other; int allow_root; - int ishelp; int flags; int nonempty; int auto_unmount; @@ -118,14 +115,10 @@ static const struct fuse_opt fuse_mount_opts[] = { FUSE_OPT_KEY("dirsync", KEY_KERN_FLAG), FUSE_OPT_KEY("atime", KEY_KERN_FLAG), FUSE_OPT_KEY("noatime", KEY_KERN_FLAG), - 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 mount_help(void) +void fuse_mount_help(void) { printf( " -o allow_other allow access to other users\n" @@ -146,7 +139,7 @@ static void exec_fusermount(const char *argv[]) execvp(FUSERMOUNT_PROG, (char **) argv); } -static void mount_version(void) +void fuse_mount_version(void) { int pid = fork(); if (!pid) { @@ -230,16 +223,6 @@ static int fuse_mount_opt_proc(void *data, const char *arg, int key, case KEY_MTAB_OPT: return fuse_opt_add_opt(&mo->mtab_opts, arg); - - case KEY_HELP: - mount_help(); - mo->ishelp = 1; - break; - - case KEY_VERSION: - mount_version(); - mo->ishelp = 1; - break; } /* Pass through unknown options */ @@ -568,67 +551,84 @@ static int get_mnt_flag_opts(char **mnt_optsp, int flags) return 0; } -int fuse_kern_mount(const char *mountpoint, struct fuse_args *args) +struct mount_opts *parse_mount_opts(struct fuse_args *args) { - struct mount_opts mo; - int res = -1; - char *mnt_opts = NULL; + struct mount_opts *mo; + + mo = (struct mount_opts*) malloc(sizeof(struct mount_opts)); + if (mo == NULL) + return NULL; - memset(&mo, 0, sizeof(mo)); - mo.flags = MS_NOSUID | MS_NODEV; + memset(mo, 0, sizeof(struct mount_opts)); + mo->flags = MS_NOSUID | MS_NODEV; if (args && - fuse_opt_parse(args, &mo, fuse_mount_opts, fuse_mount_opt_proc) == -1) - return -1; + fuse_opt_parse(args, mo, fuse_mount_opts, fuse_mount_opt_proc) == -1) + goto err_out; - if (mo.allow_other && mo.allow_root) { + if (mo->allow_other && mo->allow_root) { fprintf(stderr, "fuse: 'allow_other' and 'allow_root' options are mutually exclusive\n"); - goto out; + goto err_out; } - res = 0; - if (mo.ishelp) - goto out; + + return mo; + +err_out: + destroy_mount_opts(mo); + return NULL; +} + +void destroy_mount_opts(struct mount_opts *mo) +{ + free(mo->fsname); + free(mo->subtype); + free(mo->fusermount_opts); + free(mo->subtype_opt); + free(mo->kernel_opts); + free(mo->mtab_opts); + free(mo); +} + + +int fuse_kern_mount(const char *mountpoint, struct mount_opts *mo) +{ + int res = -1; + char *mnt_opts = NULL; res = -1; - if (get_mnt_flag_opts(&mnt_opts, mo.flags) == -1) + if (get_mnt_flag_opts(&mnt_opts, mo->flags) == -1) goto out; - if (mo.kernel_opts && fuse_opt_add_opt(&mnt_opts, mo.kernel_opts) == -1) + if (mo->kernel_opts && fuse_opt_add_opt(&mnt_opts, mo->kernel_opts) == -1) goto out; - if (mo.mtab_opts && fuse_opt_add_opt(&mnt_opts, mo.mtab_opts) == -1) + if (mo->mtab_opts && fuse_opt_add_opt(&mnt_opts, mo->mtab_opts) == -1) goto out; - res = fuse_mount_sys(mountpoint, &mo, mnt_opts); + res = fuse_mount_sys(mountpoint, mo, mnt_opts); if (res == -2) { - if (mo.fusermount_opts && - fuse_opt_add_opt(&mnt_opts, mo.fusermount_opts) == -1) + if (mo->fusermount_opts && + fuse_opt_add_opt(&mnt_opts, mo->fusermount_opts) == -1) goto out; - if (mo.subtype) { + if (mo->subtype) { char *tmp_opts = NULL; res = -1; if (fuse_opt_add_opt(&tmp_opts, mnt_opts) == -1 || - fuse_opt_add_opt(&tmp_opts, mo.subtype_opt) == -1) { + fuse_opt_add_opt(&tmp_opts, mo->subtype_opt) == -1) { free(tmp_opts); goto out; } - res = fuse_mount_fusermount(mountpoint, &mo, tmp_opts, 1); + res = fuse_mount_fusermount(mountpoint, mo, tmp_opts, 1); free(tmp_opts); if (res == -1) - res = fuse_mount_fusermount(mountpoint, &mo, + res = fuse_mount_fusermount(mountpoint, mo, mnt_opts, 0); } else { - res = fuse_mount_fusermount(mountpoint, &mo, mnt_opts, 0); + res = fuse_mount_fusermount(mountpoint, mo, mnt_opts, 0); } } out: free(mnt_opts); - free(mo.fsname); - free(mo.subtype); - free(mo.fusermount_opts); - free(mo.subtype_opt); - free(mo.kernel_opts); - free(mo.mtab_opts); return res; } diff --git a/lib/mount_bsd.c b/lib/mount_bsd.c index 40ef93f..0d886b0 100644 --- a/lib/mount_bsd.c +++ b/lib/mount_bsd.c @@ -31,15 +31,12 @@ enum { KEY_ALLOW_ROOT, KEY_RO, - KEY_HELP, - KEY_VERSION, KEY_KERN }; struct mount_opts { int allow_other; int allow_root; - int ishelp; char *kernel_opts; }; @@ -51,10 +48,6 @@ static const struct fuse_opt fuse_mount_opts[] = { { "allow_root", offsetof(struct mount_opts, allow_root), 1 }, FUSE_OPT_KEY("allow_root", KEY_ALLOW_ROOT), FUSE_OPT_KEY("-r", KEY_RO), - FUSE_OPT_KEY("-h", KEY_HELP), - FUSE_OPT_KEY("--help", KEY_HELP), - FUSE_OPT_KEY("-V", KEY_VERSION), - FUSE_OPT_KEY("--version", KEY_VERSION), /* standard FreeBSD mount options */ FUSE_DUAL_OPT_KEY("dev", KEY_KERN), FUSE_DUAL_OPT_KEY("async", KEY_KERN), @@ -100,14 +93,14 @@ static const struct fuse_opt fuse_mount_opts[] = { FUSE_OPT_END }; -static void mount_help(void) +void fuse_mount_help(void) { printf(" -o allow_root allow access to root\n"); system(FUSERMOUNT_PROG " --help"); fputc('\n', stderr); } -static void mount_version(void) +void fuse_mount_version(void) { system(FUSERMOUNT_PROG " --version"); } @@ -130,16 +123,6 @@ static int fuse_mount_opt_proc(void *data, const char *arg, int key, case KEY_KERN: return fuse_opt_add_opt(&mo->kernel_opts, arg); - - case KEY_HELP: - mount_help(); - mo->ishelp = 1; - break; - - case KEY_VERSION: - mount_version(); - mo->ishelp = 1; - break; } /* Pass through unknown options */ @@ -314,30 +297,44 @@ out: return fd; } -int fuse_kern_mount(const char *mountpoint, struct fuse_args *args) +struct mount_opts *parse_mount_opts(struct fuse_args *args) { - struct mount_opts mo; - int res = -1; + struct mount_opts *mo; - memset(&mo, 0, sizeof(mo)); - /* mount util should not try to spawn the daemon */ - setenv("MOUNT_FUSEFS_SAFE", "1", 1); - /* to notify the mount util it's called from lib */ - setenv("MOUNT_FUSEFS_CALL_BY_LIB", "1", 1); + mo = (struct mount_opts*) malloc(sizeof(struct mount_opts)); + if (mo == NULL) + return NULL; + + memset(mo, 0, sizeof(struct mount_opts)); if (args && - fuse_opt_parse(args, &mo, fuse_mount_opts, fuse_mount_opt_proc) == -1) - return -1; + fuse_opt_parse(args, mo, fuse_mount_opts, fuse_mount_opt_proc) == -1) + goto err_out; - if (mo.allow_other && mo.allow_root) { + if (mo->allow_other && mo->allow_root) { fprintf(stderr, "fuse: 'allow_other' and 'allow_root' options are mutually exclusive\n"); - goto out; + goto err_out; } - if (mo.ishelp) - return 0; - res = fuse_mount_core(mountpoint, mo.kernel_opts); -out: - free(mo.kernel_opts); - return res; + return mo; + +err_out: + destroy_mount_opts(mo); + return NULL; +} + +void destroy_mount_opts(struct mount_opts *mo) +{ + free(mo->kernel_opts); + free(mo); +} + +int fuse_kern_mount(const char *mountpoint, struct mount_opts *mo) +{ + /* mount util should not try to spawn the daemon */ + setenv("MOUNT_FUSEFS_SAFE", "1", 1); + /* to notify the mount util it's called from lib */ + setenv("MOUNT_FUSEFS_CALL_BY_LIB", "1", 1); + + return fuse_mount_core(mountpoint, mo->kernel_opts); } |