aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog.rst67
-rw-r--r--doc/developer-notes.rst28
-rw-r--r--example/fuse_lo-plus.c40
-rwxr-xr-xexample/hello_ll.c46
-rw-r--r--include/fuse.h43
-rw-r--r--include/fuse_common.h1
-rw-r--r--include/fuse_lowlevel.h99
-rw-r--r--lib/fuse.c17
-rw-r--r--lib/fuse_i.h59
-rwxr-xr-xlib/fuse_lowlevel.c72
-rw-r--r--lib/fuse_versionscript5
-rw-r--r--lib/helper.c44
-rw-r--r--lib/mount.c98
-rw-r--r--lib/mount_bsd.c71
14 files changed, 363 insertions, 327 deletions
diff --git a/ChangeLog.rst b/ChangeLog.rst
index 23c606e..a15b55a 100644
--- a/ChangeLog.rst
+++ b/ChangeLog.rst
@@ -12,9 +12,70 @@ Unreleased Changes
* The ``fuse_lowlevel_notify_*`` functions now all take a `struct
fuse_session` parameter instead of a `struct fuse_chan`.
-* The channel interface (``fuse_chan_*`` functions) has been
- made private. The `struct fuse_chan_ops` data structure is now
- opaque.
+* The channel interface (``fuse_chan_*`` functions) has been made
+ private. As a result, the typical initialization sequence of a
+ low-level file system has changed from ::
+
+ ch = fuse_mount(mountpoint, &args);
+ se = fuse_lowlevel_new(&args, &lo_oper, sizeof(lo_oper), &lo);
+ fuse_set_signal_handlers(se);
+ fuse_session_add_chan(se, ch);
+ fuse_daemonize(fg);
+ if (mt)
+ fuse_session_loop_mt(se);
+ else
+ fuse_session_loop(se);
+ fuse_remove_signal_handlers(se);
+ fuse_session_remove_chan(ch);
+ fuse_session_destroy(se);
+ fuse_unmount(mountpoint, ch);
+
+ to ::
+
+ se = fuse_session_new(&args, &ll_ops, sizeof(ll_ops), NULL);
+ fuse_set_signal_handlers(se);
+ fuse_session_mount(se, mountpoint);
+ fuse_daemonize(fg);
+ if (mt)
+ fuse_session_loop_mt(se);
+ else
+ fuse_session_loop(se);
+ fuse_remove_signal_handlers(se);
+ fuse_session_unmount(se);
+ fuse_lowlevel_destroy(se);
+
+ The typical high-level setup has changed from ::
+
+ ch = fuse_mount(*mountpoint, &args);
+ fuse = fuse_new(ch, &args, op, op_size, user_data);
+ se = fuse_get_session(fuse);
+ fuse_set_signal_handlers(se);
+ fuse_daemonize(fg);
+ if (mt)
+ fuse_loop_mt(fuse);
+ else
+ fuse_loop(fuse);
+ fuse_remove_signal_handlers(se);
+ fuse_unmount(mountpoint, ch);
+ fuse_destroy(fuse);
+
+ to ::
+
+ fuse = fuse_new(&args, op, op_size, user_data);
+ se = fuse_get_session(fuse);
+ fuse_set_signal_handlers(se);
+ fuse_mount(se, mountpoint);
+ fuse_daemonize(fg);
+ if (mt)
+ fuse_loop_mt(fuse);
+ else
+ fuse_loop(fuse);
+ fuse_remove_signal_handlers(se);
+ fuse_unmount(se);
+ fuse_destroy(fuse);
+
+ File systems that use `fuse_main` are not affected by this change.
+
* Added *clone_fd* option. This creates a separate device file
descriptor for each processing thread, which might improve
diff --git a/doc/developer-notes.rst b/doc/developer-notes.rst
index 4e9b31a..1df082a 100644
--- a/doc/developer-notes.rst
+++ b/doc/developer-notes.rst
@@ -5,31 +5,3 @@
If you are working on libfuse itself (rather than using it for a
different project) this file should be of interest to you. Otherwise
you should ignore it entirely.
-
-Channel Interface
-=================
-
-From the API, it may appear as if every fuse session (`struct
-fuse_session`) is associated with a single fuse channel (`struct
-fuse_chan`) that is created by `fuse_mount()` and assigned to the
-session in `fuse_session_add_chan()`. Therefore, one may wonder why
-there are two separate structs in the first place, and why the channel
-structure has a reference counter and mutex.
-
-The answer is that when using the multi-threaded session loop with the
-*clone_fd* option enabled, there are actually multiple channel objects
-per session. The session only holds a reference to the first one, and
-the additional channel objects don't actually hold references to the
-session object -- but they still exist. The additional channels are
-created by duplicating the fd (in `fuse_clone_chan()`, called by
-`fuse_loop_start_thread`). When processing a request,
-`fuse_session_process_buf()` records the active channel in the request
-object (`struct fuse_req`) so that it can be retrieved by e.g. the
-``fuse_reply_*`` functions. Since the request object can potentially
-live longer than the worker thread that created it, we need to keep a
-reference count for the channel.
-
-The reason for not having references to the session object from the
-extra channels is not clear, but with the current implementation this
-would not work because `fuse_session_remove_chan` always attempts to
-remove the channel from the session.
diff --git a/example/fuse_lo-plus.c b/example/fuse_lo-plus.c
index e79c727..4171d3e 100644
--- a/example/fuse_lo-plus.c
+++ b/example/fuse_lo-plus.c
@@ -455,7 +455,7 @@ static const struct fuse_opt lo_opts[] = {
int main(int argc, char *argv[])
{
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
- struct fuse_chan *ch;
+ struct fuse_session *se;
char *mountpoint;
int ret = -1;
struct lo_data lo = { .debug = 0 };
@@ -468,23 +468,29 @@ int main(int argc, char *argv[])
if (lo.root.fd == -1)
err(1, "open(\"/\", O_PATH)");
- if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != -1 &&
- (ch = fuse_session_mount(mountpoint, &args)) != NULL) {
- struct fuse_session *se;
- se = fuse_session_new(&args, &lo_oper, sizeof(lo_oper), &lo);
- if (se != NULL) {
- if (fuse_set_signal_handlers(se) != -1) {
- fuse_session_add_chan(se, ch);
- ret = fuse_session_loop(se);
- fuse_remove_signal_handlers(se);
- fuse_session_remove_chan(ch);
- }
- fuse_session_destroy(se);
- }
- fuse_session_unmount(mountpoint, ch);
- free(mountpoint);
- }
+ 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)
+ goto err_out2;
+
+ ret = fuse_session_loop(se);
+
+ fuse_session_unmount(se);
+err_out2:
+ fuse_remove_signal_handlers(se);
+err_out1:
+ fuse_session_destroy(se);
+err_out:
+ free(mountpoint);
while (lo.root.next != &lo.root)
lo_free(lo.root.next);
diff --git a/example/hello_ll.c b/example/hello_ll.c
index 528b216..07529d1 100755
--- a/example/hello_ll.c
+++ b/example/hello_ll.c
@@ -186,31 +186,35 @@ static struct fuse_lowlevel_ops hello_ll_oper = {
int main(int argc, char *argv[])
{
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
- struct fuse_chan *ch;
+ struct fuse_session *se;
char *mountpoint;
int err = -1;
- if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != -1 &&
- (ch = fuse_session_mount(mountpoint, &args)) != NULL) {
- struct fuse_session *se;
-
- se = fuse_session_new(&args, &hello_ll_oper,
- sizeof(hello_ll_oper), NULL);
- if (se != NULL) {
- if (fuse_set_signal_handlers(se) != -1) {
- fuse_session_add_chan(se, ch);
-
- /* Block until ctrl+c or fusermount -u */
- err = fuse_session_loop(se);
-
- fuse_remove_signal_handlers(se);
- fuse_session_remove_chan(ch);
- }
- fuse_session_destroy(se);
- }
- fuse_session_unmount(mountpoint, ch);
- }
+ if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != 0)
+ goto err_out;
+
+ 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)
+ goto err_out2;
+
+ /* Block until ctrl+c or fusermount -u */
+ err = fuse_session_loop(se);
+
+ fuse_session_unmount(se);
+err_out2:
+ fuse_remove_signal_handlers(se);
+err_out1:
+ fuse_session_destroy(se);
+err_out:
+ free(mountpoint);
return err ? 1 : 0;
}
diff --git a/include/fuse.h b/include/fuse.h
index 948442c..c3fea2d 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -640,55 +640,44 @@ struct fuse_context {
/**
* Create a new FUSE filesystem.
*
- * Known parameters in `args` are removed. If there are any unknown
- * arguments, an error is printed to stderr and the function returns
+ * Known arguments are defined in `struct fuse_opt fuse_lib_opts[]`,
+ * `struct fuse_opt fuse_mount_opts[]`, and `struct fuse_opt
+ * fuse_ll_opts[]`. If there are any unknown arguments, an error
+ * message will be printed to stderr and the function will return
* NULL.
*
* If the --help or --version parameters are specified, the function
* prints the requested information to stdout and returns NULL.
*
- * @param ch the communication channel
* @param args argument vector
* @param op the filesystem operations
* @param op_size the size of the fuse_operations structure
* @param user_data user data supplied in the context during the init() method
* @return the created FUSE handle
*/
-struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
- const struct fuse_operations *op, size_t op_size,
- void *user_data);
+struct fuse *fuse_new(struct fuse_args *args, const struct fuse_operations *op,
+ size_t op_size, void *user_data);
/**
- * Create a FUSE mountpoint
- *
- * Returns a control file descriptor suitable for passing to
- * fuse_new(). Unknown parameters in `args` are passed through
- * unchanged. Known parameters (with the exception of --help and
- * --version) are removed from `args`.
- *
- * If the --help or --version parameters are specified, the function
- * prints the requested information to stdout and returns a valid
- * pointer. However, it does not actually perform the mount.
+ * Mount a FUSE file system.
*
* @param mountpoint the mount point path
- * @param args argument vector
- * @return the communication channel on success, NULL on failure
- */
-struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args);
+ * @param f the FUSE handle
+ *
+ * @return 0 on success, -1 on failure.
+ **/
+int fuse_mount(struct fuse *f, const char *mountpoint);
/**
- * Umount a FUSE mountpoint
+ * Unmount a FUSE file system.
*
- * @param mountpoint the mount point path
- * @param ch the communication channel
- */
-void fuse_unmount(const char *mountpoint, struct fuse_chan *ch);
+ * @param f the FUSE handle
+ **/
+void fuse_unmount(struct fuse *f);
/**
* Destroy the FUSE handle.
*
- * The communication channel attached to the handle is also destroyed.
- *
* NOTE: This function does not unmount the filesystem. If this is
* needed, call fuse_unmount() before calling this function.
*
diff --git a/include/fuse_common.h b/include/fuse_common.h
index bab2a5b..f39dab3 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -206,7 +206,6 @@ struct fuse_conn_info {
};
struct fuse_session;
-struct fuse_chan;
struct fuse_pollhandle;
/**
diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h
index 9656c98..f0f0e0b 100644
--- a/include/fuse_lowlevel.h
+++ b/include/fuse_lowlevel.h
@@ -56,14 +56,6 @@ typedef struct fuse_req *fuse_req_t;
*/
struct fuse_session;
-/**
- * Channel
- *
- * A communication channel, providing hooks for sending and receiving
- * messages
- */
-struct fuse_chan;
-
/** Directory entry parameters supplied to fuse_reply_entry() */
struct fuse_entry_param {
/** Unique inode number
@@ -1573,30 +1565,15 @@ int fuse_req_interrupted(fuse_req_t req);
* ----------------------------------------------------------- */
/**
- * Create a FUSE mountpoint
- *
- * Returns a control file descriptor suitable for passing to
- * fuse_new(). Unknown parameters in `args` are passed through
- * unchanged. Known parameters (with the exception of --help and
- * --version) are removed from `args`.
+ * Create a low level session.
*
- * If the --help or --version parameters are specified, the function
- * prints the requested information to stdout and returns a valid
- * pointer. However, it does not actually perform the mount.
- *
- * @param mountpoint the mount point path
- * @param args argument vector
- * @return the communication channel on success, NULL on failure
- */
-struct fuse_chan *fuse_session_mount(const char *mountpoint,
- struct fuse_args *args);
-
-/**
- * Create a low level session
+ * Returns a session structure suitable for passing to
+ * fuse_session_mount() and fuse_session_loop().
*
- * Known parameters in `args` are removed. If there are any unknown
- * arguments, an error is printed to stderr and the function returns
- * NULL.
+ * Known arguments are defined in `struct fuse_opt fuse_ll_opts[]` and
+ * `struct fuse_opt fuse_mount_opts[]`. If there are any unknown
+ * arguments, an error message will be printed to stderr and the
+ * function will return NULL.
*
* If the --help or --version parameters are specified, the function
* prints the requsted information to stdout and returns NULL.
@@ -1616,14 +1593,14 @@ struct fuse_session *fuse_session_new(struct fuse_args *args,
size_t op_size, void *userdata);
/**
- * Assign a channel to a session
+ * Mount a FUSE file system.
*
- * If a session is destroyed, the assigned channel is also destroyed
+ * @param mountpoint the mount point path
+ * @param se session object
*
- * @param se the session
- * @param ch the channel
- */
-void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch);
+ * @return 0 on success, -1 on failure.
+ **/
+int fuse_session_mount(struct fuse_session *se, const char *mountpoint);
/**
* Enter a single threaded, blocking event loop.
@@ -1672,13 +1649,11 @@ void fuse_session_reset(struct fuse_session *se);
int fuse_session_exited(struct fuse_session *se);
/**
- * Remove the channel from a session
+ * Unmount the file system
*
- * If the channel is not assigned to a session, then this is a no-op
- *
- * @param ch the channel to remove
+ * @param se the session
*/
-void fuse_session_remove_chan(struct fuse_chan *ch);
+void fuse_session_unmount(struct fuse_session *se);
/**
* Destroy a session
@@ -1687,15 +1662,6 @@ void fuse_session_remove_chan(struct fuse_chan *ch);
*/
void fuse_session_destroy(struct fuse_session *se);
-/**
- * Umount a FUSE mountpoint
- *
- * @param mountpoint the mount point path
- * @param ch the communication channel
- */
-void fuse_session_unmount(const char *mountpoint, struct fuse_chan *ch);
-
-
/* ----------------------------------------------------------- *
* Request processing (for custom event loops) *
* ----------------------------------------------------------- */
@@ -1710,7 +1676,7 @@ void fuse_session_unmount(const char *mountpoint, struct fuse_chan *ch);
* @param ch channel on which the request was received
*/
void fuse_session_process_buf(struct fuse_session *se,
- const struct fuse_buf *buf, struct fuse_chan *ch);
+ const struct fuse_buf *buf);
/**
* Receive a raw request supplied in a generic buffer
@@ -1723,36 +1689,7 @@ void fuse_session_process_buf(struct fuse_session *se,
* @param ch the channel
* @return the actual size of the raw request, or -errno on error
*/
-int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf,
- struct fuse_chan *ch);
-
-/* ----------------------------------------------------------- *
- * Channel interface *
- * ----------------------------------------------------------- */
-
-/**
- * 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);
+int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf);
#ifdef __cplusplus
}
diff --git a/lib/fuse.c b/lib/fuse.c
index 47b72d0..bd7dc27 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -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);
}