aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog12
-rw-r--r--configure.in2
-rw-r--r--example/fusexmp.c2
-rw-r--r--example/fusexmp_fh.c2
-rw-r--r--example/hello.c2
-rw-r--r--example/hello_ll.c28
-rw-r--r--example/null.c2
-rw-r--r--include/fuse.h18
-rw-r--r--include/fuse_common.h36
-rw-r--r--include/fuse_compat.h4
-rw-r--r--include/fuse_lowlevel.h39
-rw-r--r--include/fuse_lowlevel_compat.h6
-rw-r--r--include/fuse_opt.h53
-rw-r--r--kernel/configure.ac2
-rw-r--r--kernel/dev.c2
-rw-r--r--kernel/dir.c2
-rw-r--r--kernel/file.c2
-rw-r--r--kernel/fuse_i.h2
-rw-r--r--kernel/fuse_kernel.h4
-rw-r--r--kernel/inode.c2
-rw-r--r--lib/Makefile.am1
-rw-r--r--lib/fuse.c64
-rw-r--r--lib/fuse_i.h4
-rw-r--r--lib/fuse_kern_chan.c2
-rw-r--r--lib/fuse_loop.c2
-rw-r--r--lib/fuse_loop_mt.c2
-rw-r--r--lib/fuse_lowlevel.c33
-rw-r--r--lib/fuse_mt.c2
-rw-r--r--lib/fuse_opt.c43
-rw-r--r--lib/fuse_session.c2
-rw-r--r--lib/fuse_signals.c72
-rw-r--r--lib/fuse_versionscript9
-rw-r--r--lib/helper.c300
-rw-r--r--lib/mount.c90
-rw-r--r--util/fusermount.c2
35 files changed, 511 insertions, 339 deletions
diff --git a/ChangeLog b/ChangeLog
index b14b6ad..89610fc 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,12 +1,16 @@
2006-01-06 Miklos Szeredi <miklos@szeredi.hu>
- * Released 2.5.0
-
-2006-01-06 Miklos Szeredi <miklos@szeredi.hu>
-
* Change working directory to "/" even if running in the
foreground. Patch from Jonathan Brandmeyer
+ * Changed lots of functions to use 'struct fuse_args' instead of
+ separate argc and argv
+
+ * Added fuse_parse_cmdline(), fuse_set_signal_handlers() and
+ fuse_remove_signal_handlers() functions, so that it's now pretty
+ easy to get all the functionality of fuse_main() with a filesystem
+ using the lowlevel API.
+
2006-01-02 Miklos Szeredi <miklos@szeredi.hu>
* mount.fuse: the 'user' option should be ignored. Report and
diff --git a/configure.in b/configure.in
index d14db87..322d6eb 100644
--- a/configure.in
+++ b/configure.in
@@ -1,4 +1,4 @@
-AC_INIT(fuse, 2.5.0)
+AC_INIT(fuse, 2.5.0-pre2)
AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE
AM_CONFIG_HEADER(include/config.h)
diff --git a/example/fusexmp.c b/example/fusexmp.c
index 26b2be2..172dc88 100644
--- a/example/fusexmp.c
+++ b/example/fusexmp.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
diff --git a/example/fusexmp_fh.c b/example/fusexmp_fh.c
index 787f87c..3ff6c9d 100644
--- a/example/fusexmp_fh.c
+++ b/example/fusexmp_fh.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
diff --git a/example/hello.c b/example/hello.c
index b71bcd6..8ab7181 100644
--- a/example/hello.c
+++ b/example/hello.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
diff --git a/example/hello_ll.c b/example/hello_ll.c
index d365771..7682f4e 100644
--- a/example/hello_ll.c
+++ b/example/hello_ll.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
@@ -146,32 +146,32 @@ static struct fuse_lowlevel_ops hello_ll_oper = {
int main(int argc, char *argv[])
{
- const char *mountpoint;
+ struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+ char *mountpoint;
int err = -1;
int fd;
- if (argc != 2) {
- fprintf(stderr, "usage: %s mountpoint\n", argv[0]);
- return 1;
- }
- mountpoint = argv[1];
- fd = fuse_mount(mountpoint, NULL);
- if (fd != -1) {
+ if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != -1 &&
+ (fd = fuse_mount(mountpoint, &args)) != -1) {
struct fuse_session *se;
- se = fuse_lowlevel_new("debug", &hello_ll_oper, sizeof(hello_ll_oper),
+ se = fuse_lowlevel_new(&args, &hello_ll_oper, sizeof(hello_ll_oper),
NULL);
if (se != NULL) {
- struct fuse_chan *ch = fuse_kern_chan_new(fd);
- if (ch != NULL) {
- fuse_session_add_chan(se, ch);
- err = fuse_session_loop(se);
+ if (fuse_set_signal_handlers(se) != -1) {
+ struct fuse_chan *ch = fuse_kern_chan_new(fd);
+ if (ch != NULL) {
+ fuse_session_add_chan(se, ch);
+ err = fuse_session_loop(se);
+ }
+ fuse_remove_signal_handlers(se);
}
fuse_session_destroy(se);
}
close(fd);
}
fuse_unmount(mountpoint);
+ fuse_opt_free_args(&args);
return err ? 1 : 0;
}
diff --git a/example/null.c b/example/null.c
index d9539ab..82e7c45 100644
--- a/example/null.c
+++ b/example/null.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
diff --git a/include/fuse.h b/include/fuse.h
index 1cf727c..2eac635 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB.
@@ -420,12 +420,12 @@ int fuse_main(int argc, char *argv[], const struct fuse_operations *op);
* Create a new FUSE filesystem.
*
* @param fd the control file descriptor
- * @param opts mount options to be used by the library
+ * @param args argument vector
* @param op the operations
* @param op_size the size of the fuse_operations structure
* @return the created FUSE handle
*/
-struct fuse *fuse_new(int fd, const char *opts,
+struct fuse *fuse_new(int fd, struct fuse_args *args,
const struct fuse_operations *op, size_t op_size);
/**
@@ -488,13 +488,7 @@ struct fuse_context *fuse_get_context(void);
*/
int fuse_invalidate(struct fuse *f, const char *path);
-/**
- * Check whether a mount option should be passed to the kernel or the
- * library
- *
- * @param opt the option to check
- * @return 1 if it is a library option, 0 otherwise
- */
+/* Deprecated, don't use */
int fuse_is_lib_option(const char *opt);
/**
@@ -513,9 +507,9 @@ int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
typedef void (*fuse_processor_t)(struct fuse *, struct fuse_cmd *, void *);
/** This is the part of fuse_main() before the event loop */
-struct fuse *fuse_setup(int argc, char *argv[],
+struct fuse *fuse_setup(struct fuse_args *args,
const struct fuse_operations *op, size_t op_size,
- char **mountpoint, int *multithreaded, int *fd);
+ char **mountpoint, int *multithreaded, int *fd);
/** This is the part of fuse_main() after the event loop */
void fuse_teardown(struct fuse *fuse, int fd, char *mountpoint);
diff --git a/include/fuse_common.h b/include/fuse_common.h
index 979c092..0f35ea6 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB.
@@ -13,6 +13,7 @@
#ifndef _FUSE_COMMON_H_
#define _FUSE_COMMON_H_
+#include "fuse_opt.h"
#include <stdint.h>
/** Major version of FUSE library interface */
@@ -65,25 +66,50 @@ struct fuse_file_info {
uint64_t fh;
};
-/*
+/**
* Create a FUSE mountpoint
*
* Returns a control file descriptor suitable for passing to
* fuse_new()
*
* @param mountpoint the mount point path
- * @param opts a comma separated list of mount options. Can be NULL.
+ * @param args argument vector
* @return the control file descriptor on success, -1 on failure
*/
-int fuse_mount(const char *mountpoint, const char *opts);
+int fuse_mount(const char *mountpoint, struct fuse_args *args);
-/*
+/**
* Umount a FUSE mountpoint
*
* @param mountpoint the mount point path
*/
void fuse_unmount(const char *mountpoint);
+/**
+ * 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
+ *
+ * All parameters may be NULL
+ *
+ * @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);
+
+
#ifdef __cplusplus
}
#endif
diff --git a/include/fuse_compat.h b/include/fuse_compat.h
index 1fe68ec..220ef07 100644
--- a/include/fuse_compat.h
+++ b/include/fuse_compat.h
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB.
@@ -69,6 +69,8 @@ int fuse_main_real_compat22(int argc, char *argv[],
const struct fuse_operations_compat22 *op,
size_t op_size);
+int fuse_mount_compat22(const char *mountpoint, const char *opts);
+
typedef int (*fuse_dirfil_t_compat) (fuse_dirh_t h, const char *name, int type);
struct fuse_operations_compat2 {
int (*getattr) (const char *, struct stat *);
diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h
index 74c483c..e45968c 100644
--- a/include/fuse_lowlevel.h
+++ b/include/fuse_lowlevel.h
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB.
@@ -928,25 +928,19 @@ const struct fuse_ctx *fuse_req_ctx(fuse_req_t req);
* Filesystem setup *
* ----------------------------------------------------------- */
-/**
- * Check whether a mount option is claimed by the low level library or
- * not
- *
- * @param opt the option to check
- * @return 1 if it is a low level library option, 0 otherwise
- */
+/* Deprecated, don't use */
int fuse_lowlevel_is_lib_option(const char *opt);
/**
* Create a low level session
*
- * @param opts the comma separated list of options
+ * @param args argument vector
* @param op the low level filesystem operations
* @param op_size sizeof(struct fuse_lowlevel_ops)
* @param userdata user data
* @return the created session object, or NULL on failure
*/
-struct fuse_session *fuse_lowlevel_new(const char *opts,
+struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
const struct fuse_lowlevel_ops *op,
size_t op_size, void *userdata);
@@ -1213,6 +1207,31 @@ int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[],
void fuse_chan_destroy(struct fuse_chan *ch);
/* ----------------------------------------------------------- *
+ * Signal handling *
+ * ----------------------------------------------------------- */
+
+/**
+ * Exit session on HUP, TERM and INT signals and ignore PIPE signal
+ *
+ * Stores session in a global variable. May only be called once per
+ * process until fuse_remove_signal_handlers() is called.
+ *
+ * @param se the session to exit
+ * @return 0 on success, -1 on failure
+ */
+int fuse_set_signal_handlers(struct fuse_session *se);
+
+/**
+ * Restore default signal handlers
+ *
+ * Resets global session. After this fuse_set_signal_handlers() may
+ * be called again.
+ *
+ * @param se the same session as given in fuse_set_signal_handlers()
+ */
+void fuse_remove_signal_handlers(struct fuse_session *se);
+
+/* ----------------------------------------------------------- *
* Compatibility stuff *
* ----------------------------------------------------------- */
diff --git a/include/fuse_lowlevel_compat.h b/include/fuse_lowlevel_compat.h
index c2bd3c1..ccb7d01 100644
--- a/include/fuse_lowlevel_compat.h
+++ b/include/fuse_lowlevel_compat.h
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB.
@@ -23,3 +23,7 @@ int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf);
int fuse_reply_open_compat(fuse_req_t req,
const struct fuse_file_info_compat *fi);
+
+struct fuse_session *fuse_lowlevel_new_compat(const char *opts,
+ const struct fuse_lowlevel_ops *op,
+ size_t op_size, void *userdata);
diff --git a/include/fuse_opt.h b/include/fuse_opt.h
index f3a06dd..ceec864 100644
--- a/include/fuse_opt.h
+++ b/include/fuse_opt.h
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
@@ -16,12 +16,6 @@ extern "C" {
#endif
/**
- * Special 'offset' value. In case of a match, the processing
- * function will be called with 'value' as the key
- */
-#define FUSE_OPT_OFFSET_KEY -1U
-
-/**
* Option description
*
* This structure describes a single option, and and action associated
@@ -44,7 +38,7 @@ extern "C" {
*
* - 'offsetof(struct foo, member)' actions i) and iii)
*
- * - FUSE_OPT_OFFSET_KEY action ii)
+ * - -1 action ii)
*
* The 'offsetof()' macro is defined in the <stddef.h> header.
*
@@ -82,7 +76,7 @@ struct fuse_opt {
/**
* Offset of variable within 'data' parameter of fuse_opt_parse()
- * or FUSE_OPT_OFFSET_KEY
+ * or -1
*/
unsigned long offset;
@@ -94,22 +88,35 @@ struct fuse_opt {
};
/**
+ * Key option. In case of a match, the processing function will be
+ * called with the specified key.
+ */
+#define FUSE_OPT_KEY(template, key) { template, -1U, key }
+
+/**
+ * Last option. An array of 'struct fuse_opt' must end with a NULL
+ * template value
+ */
+#define FUSE_OPT_END { .template = NULL }
+
+/**
* Argument list
*/
struct fuse_args {
/** Argument count */
int argc;
- /* Argument vector. NULL terminated */
+ /** Argument vector. NULL terminated */
char **argv;
+
+ /** Is 'argv' allocated? */
+ int allocated;
};
/**
- * Last option. An array of 'struct fuse_opt' must end with a NULL
- * template value
+ * Initializer for 'struct fuse_args'
*/
-#define FUSE_OPT_END { .template = NULL }
-
+#define FUSE_ARGS_INIT(argc, argv) { argc, argv, 0 }
/**
* Key value passed to the processing function if an option did not
@@ -131,7 +138,7 @@ struct fuse_args {
* This function is called if
* - option did not match any 'struct fuse_opt'
* - argument is a non-option
- * - option did match and offset was set to FUSE_OPT_OFFSET_KEY
+ * - option did match and offset was set to -1
*
* The 'arg' parameter will always contain the whole argument or
* option including the parameter if exists. A two-argument option
@@ -156,7 +163,10 @@ typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key,
/**
* Option parsing function
*
- * If 'argv' is NULL, the contents of 'outargs' will be used as input
+ * If 'args' was returned from a previous call to fuse_opt_parse() or
+ * it was constructed from
+ *
+ * A NULL 'args' is equivalent to an empty argument vector
*
* A NULL 'opts' is equivalent to an 'opts' array containing a single
* end marker
@@ -164,19 +174,14 @@ typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key,
* A NULL 'proc' is equivalent to a processing function always
* returning '1'
*
- * If outargs is NULL, then any output arguments are discarded
- *
- * @param argc is the input argument count
- * @param argv is the input argument vector
+ * @param args is the input and output argument list
* @param data is the user data
* @param opts is the option description array
* @param proc is the processing function
- * @param outargs is the output argument list
* @return -1 on error, 0 on success
*/
-int fuse_opt_parse(int argc, char *argv[], void *data,
- const struct fuse_opt opts[], fuse_opt_proc_t proc,
- struct fuse_args *outargs);
+int fuse_opt_parse(struct fuse_args *args, void *data,
+ const struct fuse_opt opts[], fuse_opt_proc_t proc);
/**
* Add an option to a comma separated option list
diff --git a/kernel/configure.ac b/kernel/configure.ac
index c5fde42..a0c6bab 100644
--- a/kernel/configure.ac
+++ b/kernel/configure.ac
@@ -1,4 +1,4 @@
-AC_INIT(fuse-kernel, 2.5.0)
+AC_INIT(fuse-kernel, 2.5.0-pre2)
AC_CONFIG_HEADERS([config.h])
AC_PROG_INSTALL
diff --git a/kernel/dev.c b/kernel/dev.c
index f7ccb7b..073333f 100644
--- a/kernel/dev.c
+++ b/kernel/dev.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
diff --git a/kernel/dir.c b/kernel/dir.c
index fa4857f..084946d 100644
--- a/kernel/dir.c
+++ b/kernel/dir.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
diff --git a/kernel/file.c b/kernel/file.c
index 2486e7a..14c4f7c 100644
--- a/kernel/file.c
+++ b/kernel/file.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
diff --git a/kernel/fuse_i.h b/kernel/fuse_i.h
index 4bf9a32..335b0c8 100644
--- a/kernel/fuse_i.h
+++ b/kernel/fuse_i.h
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
diff --git a/kernel/fuse_kernel.h b/kernel/fuse_kernel.h
index f494aff..191b97d 100644
--- a/kernel/fuse_kernel.h
+++ b/kernel/fuse_kernel.h
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
@@ -13,7 +13,7 @@
This -- and only this -- header file may also be distributed under
the terms of the BSD Licence as follows:
- Copyright (C) 2005 Miklos Szeredi. All rights reserved.
+ Copyright (C) 2001-2006 Miklos Szeredi. All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions
diff --git a/kernel/inode.c b/kernel/inode.c
index 464a519..af374c8 100644
--- a/kernel/inode.c
+++ b/kernel/inode.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 2af57b9..d58cfed 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -18,6 +18,7 @@ libfuse_la_SOURCES = \
fuse_mt.c \
fuse_opt.c \
fuse_session.c \
+ fuse_signals.c \
helper.c \
$(mount_source)
diff --git a/lib/fuse.c b/lib/fuse.c
index 35dc227..d68ca5d 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB
@@ -32,7 +32,6 @@
#define FUSE_UNKNOWN_INO 0xffffffff
struct fuse_config {
- char *llopts;
unsigned int uid;
unsigned int gid;
unsigned int umask;
@@ -1807,20 +1806,13 @@ void fuse_set_getcontext_func(struct fuse_context *(*func)(void))
fuse_getcontext = func;
}
-static int fuse_lib_opt_proc(void *data, const char *arg, int key,
- struct fuse_args *outargs)
-{
- struct fuse_config *conf = data;
- (void) key;
- (void) outargs;
- return fuse_opt_add_opt(&conf->llopts, arg);
-}
-
#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
static const struct fuse_opt fuse_lib_opts[] = {
- { "debug", FUSE_OPT_OFFSET_KEY, 0 },
+ FUSE_OPT_KEY("debug", 0),
+ FUSE_OPT_KEY("-d", 0),
FUSE_LIB_OPT("debug", debug, 1),
+ FUSE_LIB_OPT("-d", debug, 1),
FUSE_LIB_OPT("hard_remove", hard_remove, 1),
FUSE_LIB_OPT("use_ino", use_ino, 1),
FUSE_LIB_OPT("readdir_ino", readdir_ino, 1),
@@ -1844,7 +1836,7 @@ int fuse_is_lib_option(const char *opt)
fuse_opt_match(fuse_lib_opts, opt);
}
-struct fuse *fuse_new_common(int fd, const char *opts,
+struct fuse *fuse_new_common(int fd, struct fuse_args *args,
const struct fuse_operations *op,
size_t op_size, int compat)
{
@@ -1867,12 +1859,8 @@ struct fuse *fuse_new_common(int fd, const char *opts,
f->conf.attr_timeout = 1.0;
f->conf.negative_timeout = 0.0;
- if (opts) {
- const char *argv[] = { "", "-o", opts, NULL };
- if (fuse_opt_parse(3, (char **) argv, &f->conf,
- fuse_lib_opts, fuse_lib_opt_proc, NULL) == -1)
+ if (fuse_opt_parse(args, &f->conf, fuse_lib_opts, NULL) == -1)
goto out_free;
- }
#ifdef __FreeBSD__
/*
@@ -1882,9 +1870,7 @@ struct fuse *fuse_new_common(int fd, const char *opts,
f->conf.readdir_ino = 1;
#endif
- f->se = fuse_lowlevel_new(f->conf.llopts, &fuse_path_ops,
- sizeof(fuse_path_ops), f);
- free(f->conf.llopts);
+ f->se = fuse_lowlevel_new(args, &fuse_path_ops, sizeof(fuse_path_ops), f);
if (f->se == NULL)
goto out_free;
@@ -1952,10 +1938,10 @@ struct fuse *fuse_new_common(int fd, const char *opts,
return NULL;
}
-struct fuse *fuse_new(int fd, const char *opts,
+struct fuse *fuse_new(int fd, struct fuse_args *args,
const struct fuse_operations *op, size_t op_size)
{
- return fuse_new_common(fd, opts, op, op_size, 0);
+ return fuse_new_common(fd, args, op, op_size, 0);
}
void fuse_destroy(struct fuse *f)
@@ -2080,19 +2066,39 @@ static int fuse_do_statfs(struct fuse *f, char *path, struct statvfs *buf)
return err;
}
+static struct fuse *fuse_new_common_compat(int fd, const char *opts,
+ const struct fuse_operations *op,
+ size_t op_size, int compat)
+{
+ struct fuse *f;
+ struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
+
+ if (opts &&
+ (fuse_opt_add_arg(&args, "") == -1 ||
+ fuse_opt_add_arg(&args, "-o") == -1 ||
+ fuse_opt_add_arg(&args, opts) == -1)) {
+ fuse_opt_free_args(&args);
+ return NULL;
+ }
+ f = fuse_new_common(fd, &args, op, op_size, compat);
+ fuse_opt_free_args(&args);
+
+ return f;
+}
+
struct fuse *fuse_new_compat22(int fd, const char *opts,
const struct fuse_operations_compat22 *op,
size_t op_size)
{
- return fuse_new_common(fd, opts, (struct fuse_operations *) op,
- op_size, 22);
+ return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
+ op_size, 22);
}
struct fuse *fuse_new_compat2(int fd, const char *opts,
const struct fuse_operations_compat2 *op)
{
- return fuse_new_common(fd, opts, (struct fuse_operations *) op,
- sizeof(struct fuse_operations_compat2), 21);
+ return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
+ sizeof(struct fuse_operations_compat2), 21);
}
struct fuse *fuse_new_compat1(int fd, int flags,
@@ -2101,8 +2107,8 @@ struct fuse *fuse_new_compat1(int fd, int flags,
const char *opts = NULL;
if (flags & FUSE_DEBUG_COMPAT1)
opts = "debug";
- return fuse_new_common(fd, opts, (struct fuse_operations *) op,
- sizeof(struct fuse_operations_compat1), 11);
+ return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
+ sizeof(struct fuse_operations_compat1), 11);
}
__asm__(".symver fuse_exited,__fuse_exited@");
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index 281ddc4..ea1eefe 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB
@@ -19,6 +19,6 @@ struct fuse_cmd {
struct fuse_session *fuse_get_session(struct fuse *f);
-struct fuse *fuse_new_common(int fd, const char *opts,
+struct fuse *fuse_new_common(int fd, struct fuse_args *args,
const struct fuse_operations *op,
size_t op_size, int compat);
diff --git a/lib/fuse_kern_chan.c b/lib/fuse_kern_chan.c
index fbe3943..d58c8b2 100644
--- a/lib/fuse_kern_chan.c
+++ b/lib/fuse_kern_chan.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB
diff --git a/lib/fuse_loop.c b/lib/fuse_loop.c
index f9a05d8..1609bfc 100644
--- a/lib/fuse_loop.c
+++ b/lib/fuse_loop.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB
diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c
index 3566c60..540607b 100644
--- a/lib/fuse_loop_mt.c
+++ b/lib/fuse_loop_mt.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB.
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 6913d63..d1b4b36 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB
@@ -895,6 +895,7 @@ static void fuse_ll_process(void *data, const char *buf, size_t len,
static struct fuse_opt fuse_ll_opts[] = {
{ "debug", offsetof(struct fuse_ll, debug), 1 },
+ { "-d", offsetof(struct fuse_ll, debug), 1 },
{ "allow_root", offsetof(struct fuse_ll, allow_root), 1 },
FUSE_OPT_END
};
@@ -924,7 +925,7 @@ static void fuse_ll_destroy(void *data)
free(f);
}
-struct fuse_session *fuse_lowlevel_new(const char *opts,
+struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
const struct fuse_lowlevel_ops *op,
size_t op_size, void *userdata)
{
@@ -946,12 +947,8 @@ struct fuse_session *fuse_lowlevel_new(const char *opts,
goto out;
}
- if (opts) {
- const char *argv[] = { "", "-o", opts, NULL };
- if (fuse_opt_parse(3, (char **) argv, f, fuse_ll_opts,
- fuse_ll_opt_proc, NULL) == -1)
- goto out_free;
- }
+ if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1)
+ goto out_free;
memcpy(&f->op, op, op_size);
f->owner = getuid();
@@ -1015,8 +1012,28 @@ int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf)
return fuse_reply_statfs(req, &newbuf);
}
+struct fuse_session *fuse_lowlevel_new_compat(const char *opts,
+ const struct fuse_lowlevel_ops *op,
+ size_t op_size, void *userdata)
+{
+ struct fuse_session *se;
+ struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
+
+ if (opts &&
+ (fuse_opt_add_arg(&args, "") == -1 ||
+ fuse_opt_add_arg(&args, "-o") == -1 ||
+ fuse_opt_add_arg(&args, opts) == -1)) {
+ fuse_opt_free_args(&args);
+ return NULL;
+ }
+ se = fuse_lowlevel_new(&args, op, op_size, userdata);
+ fuse_opt_free_args(&args);
+
+ return se;
+}
__asm__(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4");
__asm__(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4");
+__asm__(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4");
#endif /* __FreeBSD__ */
diff --git a/lib/fuse_mt.c b/lib/fuse_mt.c
index f56fe62..8a8964f 100644
--- a/lib/fuse_mt.c
+++ b/lib/fuse_mt.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB.
diff --git a/lib/fuse_opt.c b/lib/fuse_opt.c
index d1b3259..2ac499c 100644
--- a/lib/fuse_opt.c
+++ b/lib/fuse_opt.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB
@@ -27,12 +27,13 @@ struct fuse_opt_context {
void fuse_opt_free_args(struct fuse_args *args)
{
- if (args && args->argv) {
+ if (args && args->argv && args->allocated) {
int i;
for (i = 0; i < args->argc; i++)
free(args->argv[i]);
free(args->argv);
args->argv = NULL;
+ args->allocated = 0;
}
}
@@ -44,12 +45,18 @@ static int alloc_failed(void)
int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
{
- char **newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *));
- char *newarg = newargv ? strdup(arg) : NULL;
+ char **newargv;
+ char *newarg;
+
+ assert(!args->argv || args->allocated);
+
+ newargv = realloc(args->argv, (args->argc + 2) * sizeof(char *));
+ newarg = newargv ? strdup(arg) : NULL;
if (!newargv || !newarg)
return alloc_failed();
args->argv = newargv;
+ args->allocated = 1;
args->argv[args->argc++] = newarg;
args->argv[args->argc] = NULL;
return 0;
@@ -183,7 +190,7 @@ static int process_opt(struct fuse_opt_context *ctx,
const struct fuse_opt *opt, unsigned sep,
const char *arg, int iso)
{
- if (opt->offset == FUSE_OPT_OFFSET_KEY) {
+ if (opt->offset == -1U) {
if (call_proc(ctx, arg, opt->value, iso) == -1)
return -1;
} else {
@@ -324,27 +331,29 @@ static int opt_parse(struct fuse_opt_context *ctx)
return 0;
}
-int fuse_opt_parse(int argc, char *argv[], void *data,
- const struct fuse_opt opts[], fuse_opt_proc_t proc,
- struct fuse_args *outargs)
+int fuse_opt_parse(struct fuse_args *args, void *data,
+ const struct fuse_opt opts[], fuse_opt_proc_t proc)
{
int res;
struct fuse_opt_context ctx = {
- .argc = argv ? argc : outargs->argc,
- .argv = argv ? argv : outargs->argv,
.data = data,
.opt = opts,
.proc = proc,
};
+ if (!args || !args->argv || !args->argc)
+ return 0;
+
+ ctx.argc = args->argc;
+ ctx.argv = args->argv;
+
res = opt_parse(&ctx);
- if (!argv)
- fuse_opt_free_args(outargs);
+ if (res != -1) {
+ struct fuse_args tmp = *args;
+ *args = ctx.outargs;
+ ctx.outargs = tmp;
+ }
free(ctx.opts);
- if (res != -1 && outargs)
- *outargs = ctx.outargs;
- else
- fuse_opt_free_args(&ctx.outargs);
-
+ fuse_opt_free_args(&ctx.outargs);
return res;
}
diff --git a/lib/fuse_session.c b/lib/fuse_session.c
index f88d6e5..4ea792a 100644
--- a/lib/fuse_session.c
+++ b/lib/fuse_session.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB
diff --git a/lib/fuse_signals.c b/lib/fuse_signals.c
new file mode 100644
index 0000000..38f407d
--- /dev/null
+++ b/lib/fuse_signals.c
@@ -0,0 +1,72 @@
+/*
+ FUSE: Filesystem in Userspace
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
+
+ This program can be distributed under the terms of the GNU LGPL.
+ See the file COPYING.LIB
+*/
+
+#include "fuse_lowlevel.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <signal.h>
+
+static struct fuse_session *fuse_instance;
+
+static void exit_handler(int sig)
+{
+ (void) sig;
+ if (fuse_instance)
+ fuse_session_exit(fuse_instance);
+}
+
+static int set_one_signal_handler(int sig, void (*handler)(int))
+{
+ struct sigaction sa;
+ struct sigaction old_sa;
+
+ memset(&sa, 0, sizeof(struct sigaction));
+ sa.sa_handler = handler;
+ sigemptyset(&(sa.sa_mask));
+ sa.sa_flags = 0;
+
+ if (sigaction(sig, NULL, &old_sa) == -1) {
+ perror("FUSE: cannot get old signal handler");
+ return -1;
+ }
+
+ if (old_sa.sa_handler == SIG_DFL &&
+ sigaction(sig, &sa, NULL) == -1) {
+ perror("Cannot set signal handler");
+ return -1;
+ }
+ return 0;
+}
+
+int fuse_set_signal_handlers(struct fuse_session *se)
+{
+ if (set_one_signal_handler(SIGHUP, exit_handler) == -1 ||
+ set_one_signal_handler(SIGINT, exit_handler) == -1 ||
+ set_one_signal_handler(SIGTERM, exit_handler) == -1 ||
+ set_one_signal_handler(SIGPIPE, SIG_IGN) == -1)
+ return -1;
+
+ fuse_instance = se;
+ return 0;
+}
+
+void fuse_remove_signal_handlers(struct fuse_session *se)
+{
+ if (fuse_instance != se)
+ fprintf(stderr,
+ "fuse: fuse_remove_signal_handlers: unknown session\n");
+ else
+ fuse_instance = NULL;
+
+ set_one_signal_handler(SIGHUP, SIG_DFL);
+ set_one_signal_handler(SIGINT, SIG_DFL);
+ set_one_signal_handler(SIGTERM, SIG_DFL);
+ set_one_signal_handler(SIGPIPE, SIG_DFL);
+}
+
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index e610b88..9927158 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -12,7 +12,6 @@ FUSE_2.2 {
fuse_main;
fuse_main_compat1;
fuse_main_compat2;
- fuse_mount;
fuse_mount_compat1;
fuse_new_compat1;
fuse_new_compat2;
@@ -38,7 +37,6 @@ FUSE_2.4 {
fuse_dirent_size;
fuse_kern_chan_new;
fuse_lowlevel_is_lib_option;
- fuse_lowlevel_new;
fuse_reply_attr;
fuse_reply_buf;
fuse_reply_entry;
@@ -63,8 +61,12 @@ FUSE_2.4 {
FUSE_2.5 {
global:
+ fuse_lowlevel_new;
+ fuse_lowlevel_new_compat;
fuse_main_real;
fuse_main_real_compat22;
+ fuse_mount;
+ fuse_mount_compat22;
fuse_new;
fuse_new_compat22;
fuse_opt_parse;
@@ -72,6 +74,8 @@ FUSE_2.5 {
fuse_opt_add_arg;
fuse_opt_free_args;
fuse_opt_match;
+ fuse_parse_cmdline;
+ fuse_remove_signal_handlers;
fuse_reply_create;
fuse_reply_open;
fuse_reply_open_compat;
@@ -79,6 +83,7 @@ FUSE_2.5 {
fuse_reply_statfs_compat;
fuse_setup;
fuse_setup_compat22;
+ fuse_set_signal_handlers;
local:
*;
diff --git a/lib/helper.c b/lib/helper.c
index 38f048b..82be718 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB.
@@ -8,6 +8,7 @@
#include "fuse_i.h"
#include "fuse_opt.h"
+#include "fuse_lowlevel.h"
#include <stdio.h>
#include <stdlib.h>
@@ -15,9 +16,6 @@
#include <unistd.h>
#include <string.h>
#include <limits.h>
-#include <signal.h>
-
-static struct fuse *fuse_instance;
static void usage(const char *progname)
{
@@ -54,105 +52,33 @@ static void usage(const char *progname)
);
}
-static void exit_handler(int sig)
-{
- (void) sig;
- if (fuse_instance != NULL)
- fuse_exit(fuse_instance);
-}
-
-static int set_one_signal_handler(int sig, void (*handler)(int))
-{
- struct sigaction sa;
- struct sigaction old_sa;
-
- memset(&sa, 0, sizeof(struct sigaction));
- sa.sa_handler = handler;
- sigemptyset(&(sa.sa_mask));
- sa.sa_flags = 0;
-
- if (sigaction(sig, NULL, &old_sa) == -1) {
- perror("FUSE: cannot get old signal handler");
- return -1;
- }
-
- if (old_sa.sa_handler == SIG_DFL &&
- sigaction(sig, &sa, NULL) == -1) {
- perror("Cannot set signal handler");
- return -1;
- }
- return 0;
-}
-
-static int set_signal_handlers(void)
-{
- if (set_one_signal_handler(SIGHUP, exit_handler) == -1 ||
- set_one_signal_handler(SIGINT, exit_handler) == -1 ||
- set_one_signal_handler(SIGTERM, exit_handler) == -1 ||
- set_one_signal_handler(SIGPIPE, SIG_IGN) == -1)
- return -1;
-
- return 0;
-}
-
enum {
KEY_HELP,
KEY_HELP_NOHEADER,
- KEY_DEBUG,
- KEY_KERN,
- KEY_ALLOW_ROOT,
- KEY_RO,
+ KEY_KEEP,
};
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_HELPER_OPT("-d", foreground),
+ FUSE_HELPER_OPT("debug", foreground),
+ FUSE_HELPER_OPT("-f", foreground),
+ FUSE_HELPER_OPT("-s", singlethread),
+ FUSE_HELPER_OPT("fsname=", fsname),
+
+ FUSE_OPT_KEY("-h", KEY_HELP),
+ FUSE_OPT_KEY("--help", KEY_HELP),
+ FUSE_OPT_KEY("-ho", KEY_HELP_NOHEADER),
+ FUSE_OPT_KEY("-d", KEY_KEEP),
+ FUSE_OPT_KEY("debug", KEY_KEEP),
FUSE_OPT_END
};
@@ -161,83 +87,78 @@ static int fuse_helper_opt_proc(void *data, const char *arg, int key,
{
struct helper_opts *hopts = data;
- (void) outargs;
-
switch (key) {
case KEY_HELP:
case KEY_HELP_NOHEADER:
- usage(key == KEY_HELP ? hopts->progname : NULL);
+ usage(key == KEY_HELP ? outargs->argv[0] : 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;
-
- return fuse_opt_add_opt(&hopts->mountpoint, arg);
-
- case KEY_DEBUG:
- return fuse_opt_add_opt(&hopts->lib_opts, "debug");
+ if (!hopts->mountpoint)
+ return fuse_opt_add_opt(&hopts->mountpoint, arg);
- 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;
- return 0;
-
- case KEY_RO:
- arg = "ro";
/* fall through */
- case KEY_KERN:
- return fuse_opt_add_opt(&hopts->kernel_opts, arg);
+ default:
+ case KEY_KEEP:
+ return 1;
}
+}
- fprintf(stderr, "fuse: invalid option `%s'\n", arg);
- return -1;
+static int add_default_fsname(const char *progname, struct fuse_args *args)
+{
+ int res;
+ char *fsname_opt;
+ const char *basename = strrchr(progname, '/');
+ if (basename == NULL)
+ basename = progname;
+ 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, "-ofsname=%s", basename);
+ res = fuse_opt_add_arg(args, fsname_opt);
+ free(fsname_opt);
+ return res;
}
-static int fuse_parse_cmdline(int argc, const char *argv[],
- struct helper_opts *hopts)
+int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint,
+ int *multithreaded, int *foreground)
{
int res;
+ struct helper_opts hopts;
- hopts->progname = argv[0];
- res = fuse_opt_parse(argc, (char **) argv, hopts, fuse_helper_opts,
- fuse_helper_opt_proc, NULL);
+ memset(&hopts, 0, sizeof(hopts));
+ res = fuse_opt_parse(args, &hopts, fuse_helper_opts, fuse_helper_opt_proc);
if (res == -1)
return -1;
- if (hopts->allow_other && hopts->allow_root) {
- fprintf(stderr, "fuse: 'allow_other' and 'allow_root' options are mutually exclusive\n");
- return -1;
- }
-
- 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);
- res = fuse_opt_add_opt(&hopts->kernel_opts, fsname_opt);
- free(fsname_opt);
+ if (!hopts.fsname) {
+ res = add_default_fsname(args->argv[0], args);
if (res == -1)
- return -1;
+ goto err;
}
+ if (mountpoint)
+ *mountpoint = hopts.mountpoint;
+ else
+ free(hopts.mountpoint);
+
+ if (multithreaded)
+ *multithreaded = !hopts.singlethread;
+ if (foreground)
+ *foreground = hopts.foreground;
return 0;
+
+ err:
+ free(hopts.mountpoint);
+ return -1;
}
-static struct fuse *fuse_setup_common(int argc, char *argv[],
+static struct fuse *fuse_setup_common(struct fuse_args *args,
const struct fuse_operations *op,
size_t op_size,
char **mountpoint,
@@ -246,28 +167,22 @@ static struct fuse *fuse_setup_common(int argc, char *argv[],
int compat)
{
struct fuse *fuse;
- struct helper_opts hopts;
+ int foreground;
int res;
- if (fuse_instance != NULL) {
- fprintf(stderr, "fuse: fuse_setup() called twice\n");
- return NULL;
- }
-
- memset(&hopts, 0, sizeof(hopts));
- res = fuse_parse_cmdline(argc, (const char **) argv, &hopts);
+ res = fuse_parse_cmdline(args, mountpoint, multithreaded, &foreground);
if (res == -1)
- goto err_free;
+ return NULL;
- *fd = fuse_mount(hopts.mountpoint, hopts.kernel_opts);
+ *fd = fuse_mount(*mountpoint, args);
if (*fd == -1)
goto err_free;
- fuse = fuse_new_common(*fd, hopts.lib_opts, op, op_size, compat);
+ fuse = fuse_new_common(*fd, args, op, op_size, compat);
if (fuse == NULL)
goto err_unmount;
- if (!hopts.foreground) {
+ if (!foreground) {
res = daemon(0, 0);
if (res == -1) {
perror("fuse: failed to daemonize program\n");
@@ -282,52 +197,41 @@ static struct fuse *fuse_setup_common(int argc, char *argv[],
}
}
- res = set_signal_handlers();
+ res = fuse_set_signal_handlers(fuse_get_session(fuse));
if (res == -1)
goto err_destroy;
- *mountpoint = hopts.mountpoint;
- *multithreaded = !hopts.singlethread;
- fuse_instance = fuse;
- free(hopts.kernel_opts);
- free(hopts.lib_opts);
return fuse;
err_destroy:
fuse_destroy(fuse);
err_unmount:
- fuse_unmount(hopts.mountpoint);
+ fuse_unmount(*mountpoint);
err_free:
- free(hopts.mountpoint);
- free(hopts.kernel_opts);
- free(hopts.lib_opts);
+ free(*mountpoint);
return NULL;
}
-struct fuse *fuse_setup(int argc, char *argv[],
- const struct fuse_operations *op,
- size_t op_size, char **mountpoint,
- int *multithreaded, int *fd)
+struct fuse *fuse_setup(struct fuse_args *args,
+ const struct fuse_operations *op,
+ size_t op_size, char **mountpoint,
+ int *multithreaded, int *fd)
{
- return fuse_setup_common(argc, argv, op, op_size, mountpoint,
- multithreaded, fd, 0);
+ return fuse_setup_common(args, op, op_size, mountpoint, multithreaded, fd,
+ 0);
}
void fuse_teardown(struct fuse *fuse, int fd, char *mountpoint)
{
(void) fd;
- if (fuse_instance != fuse)
- fprintf(stderr, "fuse: fuse_teardown() with unknown fuse object\n");
- else
- fuse_instance = NULL;
-
+ fuse_remove_signal_handlers(fuse_get_session(fuse));
fuse_unmount(mountpoint);
fuse_destroy(fuse);
free(mountpoint);
}
-static int fuse_main_common(int argc, char *argv[],
+static int fuse_main_common(struct fuse_args *args,
const struct fuse_operations *op, size_t op_size,
int compat)
{
@@ -337,8 +241,8 @@ static int fuse_main_common(int argc, char *argv[],
int res;
int fd;
- fuse = fuse_setup_common(argc, argv, op, op_size, &mountpoint,
- &multithreaded, &fd, compat);
+ fuse = fuse_setup_common(args, op, op_size, &mountpoint, &multithreaded,
+ &fd, compat);
if (fuse == NULL)
return 1;
@@ -357,7 +261,10 @@ static int fuse_main_common(int argc, char *argv[],
int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
size_t op_size)
{
- return fuse_main_common(argc, argv, op, op_size, 0);
+ struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+ int res = fuse_main_common(&args, op, op_size, 0);
+ fuse_opt_free_args(&args);
+ return res;
}
#undef fuse_main
@@ -376,8 +283,12 @@ struct fuse *fuse_setup_compat22(int argc, char *argv[],
size_t op_size, char **mountpoint,
int *multithreaded, int *fd)
{
- return fuse_setup_common(argc, argv, (struct fuse_operations *) op,
- op_size, mountpoint, multithreaded, fd, 22);
+ struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+ struct fuse *f =
+ fuse_setup_common(&args, (struct fuse_operations *) op,
+ op_size, mountpoint, multithreaded, fd, 22);
+ fuse_opt_free_args(&args);
+ return f;
}
struct fuse *fuse_setup_compat2(int argc, char *argv[],
@@ -385,31 +296,44 @@ struct fuse *fuse_setup_compat2(int argc, char *argv[],
char **mountpoint, int *multithreaded,
int *fd)
{
- return fuse_setup_common(argc, argv, (struct fuse_operations *) op,
- sizeof(struct fuse_operations_compat2),
- mountpoint, multithreaded, fd, 21);
+ struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+ struct fuse *f =
+ fuse_setup_common(&args, (struct fuse_operations *) op,
+ sizeof(struct fuse_operations_compat2),
+ mountpoint, multithreaded, fd, 21);
+ fuse_opt_free_args(&args);
+ return f;
}
int fuse_main_real_compat22(int argc, char *argv[],
const struct fuse_operations_compat22 *op,
size_t op_size)
{
- return fuse_main_common(argc, argv, (struct fuse_operations *) op,
- op_size, 22);
+ struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+ int res =
+ fuse_main_common(&args, (struct fuse_operations *) op, op_size, 22);
+ fuse_opt_free_args(&args);
+ return res;
}
void fuse_main_compat1(int argc, char *argv[],
const struct fuse_operations_compat1 *op)
{
- fuse_main_common(argc, argv, (struct fuse_operations *) op,
+ struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+ fuse_main_common(&args, (struct fuse_operations *) op,
sizeof(struct fuse_operations_compat1), 11);
+ fuse_opt_free_args(&args);
}
int fuse_main_compat2(int argc, char *argv[],
const struct fuse_operations_compat2 *op)
{
- return fuse_main_common(argc, argv, (struct fuse_operations *) op,
- sizeof(struct fuse_operations_compat2), 21);
+ struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
+ int res =
+ fuse_main_common(&args, (struct fuse_operations *) op,
+ sizeof(struct fuse_operations_compat2), 21);
+ fuse_opt_free_args(&args);
+ return res;
}
__asm__(".symver fuse_setup_compat2,__fuse_setup@");
diff --git a/lib/mount.c b/lib/mount.c
index 787c448..bd1b66f 100644
--- a/lib/mount.c
+++ b/lib/mount.c
@@ -1,17 +1,19 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPL.
See the file COPYING.LIB.
*/
#include "fuse.h"
+#include "fuse_opt.h"
#include "fuse_compat.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
+#include <stddef.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
@@ -21,6 +23,64 @@
#define FUSERMOUNT_PROG "fusermount"
#define FUSE_COMMFD_ENV "_FUSE_COMMFD"
+enum {
+ KEY_KERN,
+ KEY_ALLOW_ROOT,
+ KEY_RO,
+};
+
+struct mount_opts {
+ int allow_other;
+ int allow_root;
+ char *kernel_opts;
+};
+
+static const struct fuse_opt fuse_mount_opts[] = {
+ { "allow_other", offsetof(struct mount_opts, allow_other), 1 },
+ { "allow_root", offsetof(struct mount_opts, allow_root), 1 },
+ FUSE_OPT_KEY("allow_other", KEY_KERN),
+ FUSE_OPT_KEY("allow_root", KEY_ALLOW_ROOT),
+ FUSE_OPT_KEY("nonempty", KEY_KERN),
+ FUSE_OPT_KEY("default_permissions", KEY_KERN),
+ FUSE_OPT_KEY("fsname=", KEY_KERN),
+ FUSE_OPT_KEY("large_read", KEY_KERN),
+ FUSE_OPT_KEY("max_read=", KEY_KERN),
+ FUSE_OPT_KEY("-r", KEY_RO),
+ FUSE_OPT_KEY("ro", KEY_KERN),
+ FUSE_OPT_KEY("rw", KEY_KERN),
+ FUSE_OPT_KEY("suid", KEY_KERN),
+ FUSE_OPT_KEY("nosuid", KEY_KERN),
+ FUSE_OPT_KEY("dev", KEY_KERN),
+ FUSE_OPT_KEY("nodev", KEY_KERN),
+ FUSE_OPT_KEY("exec", KEY_KERN),
+ FUSE_OPT_KEY("noexec", KEY_KERN),
+ FUSE_OPT_KEY("async", KEY_KERN),
+ FUSE_OPT_KEY("sync", KEY_KERN),
+ FUSE_OPT_KEY("atime", KEY_KERN),
+ FUSE_OPT_KEY("noatime", KEY_KERN),
+};
+
+static int fuse_mount_opt_proc(void *data, const char *arg, int key,
+ struct fuse_args *outargs)
+{
+ struct mount_opts *mo = data;
+
+ switch (key) {
+ case KEY_ALLOW_ROOT:
+ if (fuse_opt_add_opt(&mo->kernel_opts, "allow_other") == -1 ||
+ fuse_opt_add_arg(outargs, "-oallow_root") == -1)
+ return -1;
+ return 0;
+
+ case KEY_RO:
+ arg = "ro";
+ /* fall through */
+
+ case KEY_KERN:
+ return fuse_opt_add_opt(&mo->kernel_opts, arg);
+ }
+ return 1;
+}
/* return value:
* >= 0 => fd
@@ -98,7 +158,7 @@ void fuse_unmount(const char *mountpoint)
waitpid(pid, NULL, 0);
}
-int fuse_mount(const char *mountpoint, const char *opts)
+int fuse_mount_compat22(const char *mountpoint, const char *opts)
{
const char *mountprog = FUSERMOUNT_PROG;
int fds[2], pid;
@@ -159,9 +219,33 @@ int fuse_mount(const char *mountpoint, const char *opts)
return rv;
}
+int fuse_mount(const char *mountpoint, struct fuse_args *args)
+{
+ struct mount_opts mo;
+ int res = -1;
+
+ memset(&mo, 0, sizeof(mo));
+
+ if (args &&
+ fuse_opt_parse(args, &mo, fuse_mount_opts, fuse_mount_opt_proc) == -1)
+ return -1;
+
+ if (mo.allow_other && mo.allow_root) {
+ fprintf(stderr, "fuse: 'allow_other' and 'allow_root' options are mutually exclusive\n");
+ goto out;
+ }
+
+ res = fuse_mount_compat22(mountpoint, mo.kernel_opts);
+ out:
+ free(mo.kernel_opts);
+ return res;
+}
+
int fuse_mount_compat1(const char *mountpoint, const char *args[])
{
/* just ignore mount args for now */
(void) args;
- return fuse_mount(mountpoint, NULL);
+ return fuse_mount_compat22(mountpoint, NULL);
}
+
+__asm__(".symver fuse_mount_compat22,fuse_mount@");
diff --git a/util/fusermount.c b/util/fusermount.c
index 13305d1..63a6068 100644
--- a/util/fusermount.c
+++ b/util/fusermount.c
@@ -1,6 +1,6 @@
/*
FUSE: Filesystem in Userspace
- Copyright (C) 2001-2005 Miklos Szeredi <miklos@szeredi.hu>
+ Copyright (C) 2001-2006 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU GPL.
See the file COPYING.