diff options
-rwxr-xr-x[-rw-r--r--] | doc/Doxyfile | 8 | ||||
-rwxr-xr-x[-rw-r--r--] | doc/how-fuse-works | 0 | ||||
-rw-r--r-- | doc/images/490px-FUSE_structure.svg.png | bin | 0 -> 22606 bytes | |||
-rwxr-xr-x | doc/mainpage.dox | 92 | ||||
-rwxr-xr-x[-rw-r--r--] | example/cusexmp.c | 15 | ||||
-rwxr-xr-x[-rw-r--r--] | example/fioc.c | 15 | ||||
-rwxr-xr-x[-rw-r--r--] | example/fioc.h | 9 | ||||
-rwxr-xr-x[-rw-r--r--] | example/fioclient.c | 17 | ||||
-rwxr-xr-x[-rw-r--r--] | example/fsel.c | 15 | ||||
-rwxr-xr-x[-rw-r--r--] | example/fselclient.c | 15 | ||||
-rwxr-xr-x[-rw-r--r--] | example/fusexmp.c | 16 | ||||
-rwxr-xr-x[-rw-r--r--] | example/fusexmp_fh.c | 15 | ||||
-rwxr-xr-x[-rw-r--r--] | example/hello.c | 31 | ||||
-rwxr-xr-x[-rw-r--r--] | example/hello_ll.c | 41 | ||||
-rwxr-xr-x[-rw-r--r--] | example/null.c | 15 | ||||
-rw-r--r-- | include/fuse.h | 23 | ||||
-rw-r--r-- | include/fuse_common.h | 9 | ||||
-rw-r--r-- | include/fuse_lowlevel.h | 13 | ||||
-rwxr-xr-x[-rw-r--r--] | lib/fuse_loop_mt.c | 0 | ||||
-rw-r--r-- | lib/fuse_signals.c | 2 |
20 files changed, 327 insertions, 24 deletions
diff --git a/doc/Doxyfile b/doc/Doxyfile index 3926aaf..16ce23a 100644..100755 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -544,7 +544,7 @@ WARN_LOGFILE = # directories like "/usr/src/myproject". Separate the files or directories # with spaces. -INPUT = include +INPUT = . ../include ../example ../lib # This tag can be used to specify the character encoding of the source files # that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is @@ -561,7 +561,7 @@ INPUT_ENCODING = UTF-8 # *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx # *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.py *.f90 -FILE_PATTERNS = *.h +FILE_PATTERNS = *.h *.c *.h *.dox # The RECURSIVE tag can be used to turn specify whether or not subdirectories # should be searched for input files as well. Possible values are YES and NO. @@ -601,7 +601,7 @@ EXCLUDE_SYMBOLS = # directories that contain example code fragments that are included (see # the \include command). -EXAMPLE_PATH = +EXAMPLE_PATH = . ../example/ ../lib # If the value of the EXAMPLE_PATH tag contains directories, you can use the # EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp @@ -621,7 +621,7 @@ EXAMPLE_RECURSIVE = NO # directories that contain image that are included in the documentation (see # the \image command). -IMAGE_PATH = +IMAGE_PATH = images/ # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program diff --git a/doc/how-fuse-works b/doc/how-fuse-works index a5febe3..a5febe3 100644..100755 --- a/doc/how-fuse-works +++ b/doc/how-fuse-works diff --git a/doc/images/490px-FUSE_structure.svg.png b/doc/images/490px-FUSE_structure.svg.png Binary files differnew file mode 100644 index 0000000..a4a9731 --- /dev/null +++ b/doc/images/490px-FUSE_structure.svg.png diff --git a/doc/mainpage.dox b/doc/mainpage.dox new file mode 100755 index 0000000..9202207 --- /dev/null +++ b/doc/mainpage.dox @@ -0,0 +1,92 @@ +/*! +\mainpage FUSE API documentation + +Filesystem in Userspace (FUSE) is a loadable kernel module for Unix-like computer operating systems that lets non-privileged users create their own file systems without editing kernel code. This is achieved by running file system code in user space while the FUSE module provides only a "bridge" to the actual kernel interfaces. + +(c) Wikipedia + +@tableofcontents + + + + + +\section section1 How FUSE works + +@image html 490px-FUSE_structure.svg.png "Structural diagramm of Filesystem in Userspace from http://en.wikipedia.org/wiki/File:FUSE_structure.svg" + +\include how-fuse-works + + + + +\section section2 Kernel + +\include kernel.txt + + + + + +\section section_examples examples + +have a look at the examples listed in the example directory, which can be found here: <a href="files.html">files.html</a>. + +- @ref hello.c - minimal FUSE example featuring fuse_main usage + +- @ref hello_ll.c - FUSE: Filesystem in Userspace + +- @ref null.c - FUSE: Filesystem in Userspace + +- @ref cusexmp.c - CUSE example: Character device in Userspace + +- @ref fioc.c - FUSE fioc: FUSE ioctl example + +- @ref fioclient.c - FUSE fioclient: FUSE ioctl example client + +- @ref fsel.c - FUSE fsel: FUSE select example + +- @ref fselclient.c - FUSE fselclient: FUSE select example client + +- @ref fusexmp.c - FUSE: Filesystem in Userspace + +- @ref fusexmp_fh.c - FUSE: Filesystem in Userspace + + +\section section_links links + +<a href="http://sourceforge.net/apps/mediawiki/fuse/index.php?title=Main_Page">http://sourceforge.net/apps/mediawiki/fuse/index.php?title=Main_Page</a> - the fuse wiki + +<a href="http://en.wikipedia.org/wiki/Filesystem_in_Userspace">http://en.wikipedia.org/wiki/Filesystem_in_Userspace</a> - FUSE on wikipedia + + +\section section_todo todo + +general: + + - fuse_lowlevel.h, describe: + - a channel (or communication channel) is created by fuse_mount(..) + - a fuse session is associated with a channel and a signal handler and runs until the assigned signal handler + shuts the session down, see fuse_session_loop(se) and hello_ll.c + + - http://www.cs.nmsu.edu/~pfeiffer/fuse-tutorial/ + + - http://cinwell.wordpress.com/ + + - http://sourceforge.net/apps/mediawiki/fuse/index.php?title=FuseProtocolSketch + + - http://muratbuffalo.blogspot.de/2011/05/refuse-to-crash-with-re-fuse.html + +examples: + - demonstrate the effect of single vs multithreaded -> fuse_loop fuse_loop_mt + + - add comments and source form all existing examples + + - also add examples form here: http://sourceforge.net/apps/mediawiki/fuse/index.php?title=Main_Page#How_should_threads_be_startedx3f + + - add this new example: http://fuse.996288.n3.nabble.com/Create-multiple-filesystems-in-same-process-td9292.html + + \section section_thanks thanks + - Mark Glines, <mark@glines.org> for his coments on fuse_loop() and fuse_loop_mt(). + - Wikipedia - copied the FUSE introduction from the Filesystem in userspace article. +*/ diff --git a/example/cusexmp.c b/example/cusexmp.c index b69f97c..a02818c 100644..100755 --- a/example/cusexmp.c +++ b/example/cusexmp.c @@ -6,9 +6,22 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall cusexmp.c `pkg-config fuse --cflags --libs` -o cusexmp */ +/** @file + * @tableofcontents + * + * cusexmp.c - CUSE example: Character device in Userspace + * + * \section section_compile compiling this example + * + * gcc -Wall cusexmp.c `pkg-config fuse --cflags --libs` -o cusexmp + * + * \section section_source the complete source + * \include cusexmp.c + */ + + #define FUSE_USE_VERSION 30 #include <cuse_lowlevel.h> diff --git a/example/fioc.c b/example/fioc.c index 849bd5d..cfb18ae 100644..100755 --- a/example/fioc.c +++ b/example/fioc.c @@ -6,9 +6,22 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall fioc.c `pkg-config fuse --cflags --libs` -o fioc */ +/** @file + * @tableofcontents + * + * fioc.c - FUSE fioc: FUSE ioctl example + * + * \section section_compile compiling this example + * + * gcc -Wall fioc.c `pkg-config fuse --cflags --libs` -o fioc + * + * \section section_source the complete source + * \include fioc.c + */ + + #define FUSE_USE_VERSION 30 #include <fuse.h> diff --git a/example/fioc.h b/example/fioc.h index ec1a39d..c9bf358 100644..100755 --- a/example/fioc.h +++ b/example/fioc.h @@ -7,6 +7,15 @@ See the file COPYING. */ +/** @file + * @tableofcontents + * + * fioc.h - FUSE-ioctl: ioctl support for FUSE + * + * \include fioc.h + */ + + #include <sys/types.h> #include <sys/uio.h> #include <sys/ioctl.h> diff --git a/example/fioclient.c b/example/fioclient.c index 5f05525..9718622 100644..100755 --- a/example/fioclient.c +++ b/example/fioclient.c @@ -5,10 +5,23 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - - gcc -Wall fioclient.c -o fioclient */ +/** @file + * @tableofcontents + * + * fioclient.c - FUSE fioclient: FUSE ioctl example client + * + * \section section_compile compiling this example + * + * gcc -Wall fioclient.c -o fioclient + * + * \section section_source the complete source + * fioclient.c + * \include fioclient.c + */ + + #include <sys/types.h> #include <sys/fcntl.h> #include <sys/stat.h> diff --git a/example/fsel.c b/example/fsel.c index bddc1aa..3c52033 100644..100755 --- a/example/fsel.c +++ b/example/fsel.c @@ -6,9 +6,22 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall fsel.c `pkg-config fuse --cflags --libs` -o fsel */ +/** @file + * @tableofcontents + * + * fsel.c - FUSE fsel: FUSE select example + * + * \section section_compile compiling this example + * + * gcc -Wall fsel.c `pkg-config fuse --cflags --libs` -o fsel + * + * \section section_source the complete source + * \include fsel.c + */ + + #define FUSE_USE_VERSION 30 #include <fuse.h> diff --git a/example/fselclient.c b/example/fselclient.c index 7c4b837..2e2e571 100644..100755 --- a/example/fselclient.c +++ b/example/fselclient.c @@ -6,9 +6,22 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - gcc -Wall fselclient.c -o fselclient */ +/** @file + * @tableofcontents + * + * fselclient.c - FUSE fselclient: FUSE select example client + * + * \section section_compile compiling this example + * + * gcc -Wall fselclient.c -o fselclient + * + * \section section_source the complete source + * \include fselclient.c + */ + + #include <sys/select.h> #include <sys/time.h> #include <sys/types.h> diff --git a/example/fusexmp.c b/example/fusexmp.c index 42a8134..73e9898 100644..100755 --- a/example/fusexmp.c +++ b/example/fusexmp.c @@ -5,10 +5,22 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - - gcc -Wall fusexmp.c `pkg-config fuse --cflags --libs` -o fusexmp */ +/** @file + * @tableofcontents + * + * fusexmp.c - FUSE: Filesystem in Userspace + * + * \section section_compile compiling this example + * + * gcc -Wall fusexmp.c `pkg-config fuse --cflags --libs` -o fusexmp + * + * \section section_source the complete source + * \include fusexmp.c + */ + + #define FUSE_USE_VERSION 30 #ifdef HAVE_CONFIG_H diff --git a/example/fusexmp_fh.c b/example/fusexmp_fh.c index eea6b9b..e538b49 100644..100755 --- a/example/fusexmp_fh.c +++ b/example/fusexmp_fh.c @@ -5,10 +5,21 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - - gcc -Wall fusexmp_fh.c `pkg-config fuse --cflags --libs` -lulockmgr -o fusexmp_fh */ +/** @file + * @tableofcontents + * + * fusexmp_fh.c - FUSE: Filesystem in Userspace + * + * \section section_compile compiling this example + * + * gcc -Wall fusexmp_fh.c `pkg-config fuse --cflags --libs` -lulockmgr -o fusexmp_fh + * + * \section section_source the complete source + * \include fusexmp_fh.c + */ + #define FUSE_USE_VERSION 30 #ifdef HAVE_CONFIG_H diff --git a/example/hello.c b/example/hello.c index b31fbe5..c8b4a48 100644..100755 --- a/example/hello.c +++ b/example/hello.c @@ -4,10 +4,35 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - - gcc -Wall hello.c `pkg-config fuse --cflags --libs` -o hello */ +/** @file + * + * hello.c - minimal FUSE example featuring fuse_main usage + * +* \section section_compile compiling this example + * + * gcc -Wall hello.c `pkg-config fuse --cflags --libs` -o hello + * + * \section section_usage usage + \verbatim + % mkdir mnt + % ./hello mnt # program will vanish into the background + % ls -la mnt + total 4 + drwxr-xr-x 2 root root 0 Jan 1 1970 ./ + drwxrwx--- 1 root vboxsf 4096 Jun 16 23:12 ../ + -r--r--r-- 1 root root 13 Jan 1 1970 hello + % cat mnt/hello + Hello World! + % fusermount -u mnt + \endverbatim + * + * \section section_source the complete source + * \include hello.c + */ + + #define FUSE_USE_VERSION 30 #include <fuse.h> @@ -83,6 +108,7 @@ static int hello_read(const char *path, char *buf, size_t size, off_t offset, return size; } +// fuse_operations hello_oper is redirecting function-calls to _our_ functions implemented above static struct fuse_operations hello_oper = { .getattr = hello_getattr, .readdir = hello_readdir, @@ -90,6 +116,7 @@ static struct fuse_operations hello_oper = { .read = hello_read, }; +// in the main function we call the blocking fuse_main(..) function with &hello_oper int main(int argc, char *argv[]) { return fuse_main(argc, argv, &hello_oper, NULL); diff --git a/example/hello_ll.c b/example/hello_ll.c index baf41bc..687c6f1 100644..100755 --- a/example/hello_ll.c +++ b/example/hello_ll.c @@ -4,10 +4,39 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - - gcc -Wall hello_ll.c `pkg-config fuse --cflags --libs` -o hello_ll */ +/** @file + * + * hello_ll.c - fuse low level functionality + * + * unlike hello.c this example will stay in the foreground. it also replaced + * the convenience function fuse_main(..) with a more low level approach. + * + * \section section_compile compiling this example + * + * gcc -Wall hello_ll.c `pkg-config fuse --cflags --libs` -o hello_ll + * + * \section section_usage usage + \verbatim + % mkdir mnt + % ./hello_ll mnt # program will wait in foreground until you press CTRL+C + in a different shell do: + % ls -la mnt + total 4 + drwxr-xr-x 2 root root 0 Jan 1 1970 ./ + drwxrwx--- 1 root vboxsf 4096 Jun 16 23:12 ../ + -r--r--r-- 1 root root 13 Jan 1 1970 hello + % cat mnt/hello + Hello World! + finally either press ctrl+c or do: + % fusermount -u mnt + \endverbatim + * + * \section section_source the complete source + * \include hello_ll.c + */ + #define FUSE_USE_VERSION 30 #include <fuse_lowlevel.h> @@ -151,6 +180,7 @@ static struct fuse_lowlevel_ops hello_ll_oper = { .read = hello_ll_read, }; +//! [doxygen_fuse_lowlevel_usage] int main(int argc, char *argv[]) { struct fuse_args args = FUSE_ARGS_INIT(argc, argv); @@ -161,13 +191,15 @@ int main(int argc, char *argv[]) if (fuse_parse_cmdline(&args, &mountpoint, NULL, NULL) != -1 && (ch = fuse_mount(mountpoint, &args)) != NULL) { struct fuse_session *se; - se = fuse_lowlevel_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); - err = fuse_session_loop(se); + + // fuse_session_loop(..) blocks until ctrl+c or fusermount -u + err = fuse_session_loop(se); + fuse_remove_signal_handlers(se); fuse_session_remove_chan(ch); } @@ -179,3 +211,4 @@ int main(int argc, char *argv[]) return err ? 1 : 0; } +//! [doxygen_fuse_lowlevel_usage] diff --git a/example/null.c b/example/null.c index 4e2bb8f..6952333 100644..100755 --- a/example/null.c +++ b/example/null.c @@ -4,10 +4,21 @@ This program can be distributed under the terms of the GNU GPL. See the file COPYING. - - gcc -Wall null.c `pkg-config fuse --cflags --libs` -o null */ +/** @file + * + * null.c - FUSE: Filesystem in Userspace + * + * \section section_compile compiling this example + * + * gcc -Wall null.c `pkg-config fuse --cflags --libs` -o null + * + * \section section_source the complete source + * \include null.c + */ + + #define FUSE_USE_VERSION 30 #include <fuse.h> diff --git a/include/fuse.h b/include/fuse.h index 793862e..c7647ce 100644 --- a/include/fuse.h +++ b/include/fuse.h @@ -589,6 +589,8 @@ struct fuse_context { * @param op the file system operation * @param user_data user data supplied in the context during the init() method * @return 0 on success, nonzero on failure + * + * Example usage, see hello.c */ /* int fuse_main(int argc, char *argv[], const struct fuse_operations *op, @@ -635,6 +637,8 @@ void fuse_destroy(struct fuse *f); * * @param f the FUSE handle * @return 0 if no error occurred, -1 otherwise + * + * See also: fuse_loop() */ int fuse_loop(struct fuse *f); @@ -654,9 +658,28 @@ void fuse_exit(struct fuse *f); * * Calling this function requires the pthreads library to be linked to * the application. + * + * Note: using fuse_loop() instead of fuse_loop_mt() means you are running in single-threaded mode, + * and that you will not have to worry about reentrancy, + * though you will have to worry about recursive lookups. In single-threaded mode, FUSE + * holds a global lock on your filesystem, and will wait for one callback to return + * before calling another. This can lead to deadlocks, if your script makes any attempt + * to access files or directories in the filesystem it is providing. + * (This includes calling stat() on the mount-point, statfs() calls from the 'df' command, + * and so on and so forth.) It is worth paying a little attention and being careful about this. + * + * Enabling multiple threads, by using fuse_loop_mt(), will cause FUSE to make multiple simultaneous + * calls into the various callback functions given by your fuse_operations record. + * + * If you are using multiple threads, you can enjoy all the parallel execution and interactive + * response benefits of threads, and you get to enjoy all the benefits of race conditions + * and locking bugs, too. Ensure that any code used in the callback funtion of fuse_operations + * is also thread-safe. * * @param f the FUSE handle * @return 0 if no error occurred, -1 otherwise + * + * See also: fuse_loop() */ int fuse_loop_mt(struct fuse *f); diff --git a/include/fuse_common.h b/include/fuse_common.h index af16203..9fd4bbb 100644 --- a/include/fuse_common.h +++ b/include/fuse_common.h @@ -451,8 +451,14 @@ ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src, * Stores session in a global variable. May only be called once per * process until fuse_remove_signal_handlers() is called. * + * Once either of the POSIX signals arrives, the exit_handler() in fuse_signals.c is called: + * \snippet fuse_signals.c doxygen_exit_handler + * * @param se the session to exit * @return 0 on success, -1 on failure + * + * See also: + * fuse_remove_signal_handlers() */ int fuse_set_signal_handlers(struct fuse_session *se); @@ -463,6 +469,9 @@ int fuse_set_signal_handlers(struct fuse_session *se); * be called again. * * @param se the same session as given in fuse_set_signal_handlers() + * + * See also: + * fuse_set_signal_handlers() */ void fuse_remove_signal_handlers(struct fuse_session *se); diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h index d46ef86..ada5ce8 100644 --- a/include/fuse_lowlevel.h +++ b/include/fuse_lowlevel.h @@ -1565,6 +1565,9 @@ int fuse_req_interrupted(fuse_req_t req); * @param op_size sizeof(struct fuse_lowlevel_ops) * @param userdata user data * @return the created session object, or NULL on failure + * + * Example: See hello_ll.c: + * \snippet hello_ll.c doxygen_fuse_lowlevel_usage */ struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, const struct fuse_lowlevel_ops *op, @@ -1707,7 +1710,9 @@ int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf, void fuse_session_destroy(struct fuse_session *se); /** - * Exit a session + * Exit a session. This function is invoked by the POSIX signal handlers, when registered using: + * * fuse_set_signal_handlers() + * * fuse_remove_signal_handlers() * * @param se the session */ @@ -1737,7 +1742,11 @@ int fuse_session_exited(struct fuse_session *se); void *fuse_session_data(struct fuse_session *se); /** - * Enter a single threaded event loop + * Enter a single threaded, blocking event loop. + * + * Using POSIX signals this event loop can be exited but the session + * needs to be configued by issuing: + * fuse_set_signal_handlers() first. * * @param se the session * @return 0 on success, -1 on error diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c index 82e3001..82e3001 100644..100755 --- a/lib/fuse_loop_mt.c +++ b/lib/fuse_loop_mt.c diff --git a/lib/fuse_signals.c b/lib/fuse_signals.c index 88ac39e..cab9951 100644 --- a/lib/fuse_signals.c +++ b/lib/fuse_signals.c @@ -14,12 +14,14 @@ static struct fuse_session *fuse_instance; +//! [doxygen_exit_handler] static void exit_handler(int sig) { (void) sig; if (fuse_instance) fuse_session_exit(fuse_instance); } +//! [doxygen_exit_handler] static int set_one_signal_handler(int sig, void (*handler)(int)) { |