aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore4
-rw-r--r--ChangeLog93
-rw-r--r--Makefile.am4
-rw-r--r--configure.ac15
-rw-r--r--doc/.gitignore1
-rwxr-xr-x[-rw-r--r--]doc/Doxyfile8
-rw-r--r--doc/Makefile.am2
-rwxr-xr-x[-rw-r--r--]doc/how-fuse-works0
-rw-r--r--doc/images/490px-FUSE_structure.svg.pngbin0 -> 22606 bytes
-rwxr-xr-xdoc/mainpage.dox92
-rw-r--r--doc/ulockmgr_server.128
-rw-r--r--example/Makefile.am6
-rwxr-xr-x[-rw-r--r--]example/cusexmp.c19
-rwxr-xr-x[-rw-r--r--]example/fioc.c19
-rwxr-xr-x[-rw-r--r--]example/fioc.h9
-rwxr-xr-x[-rw-r--r--]example/fioclient.c18
-rwxr-xr-x[-rw-r--r--]example/fsel.c19
-rwxr-xr-x[-rw-r--r--]example/fselclient.c16
-rwxr-xr-x[-rw-r--r--]example/fusexmp.c18
-rwxr-xr-x[-rw-r--r--]example/fusexmp_fh.c30
-rwxr-xr-x[-rw-r--r--]example/hello.c33
-rwxr-xr-x[-rw-r--r--]example/hello_ll.c42
-rwxr-xr-x[-rw-r--r--]example/null.c19
-rw-r--r--fuse3.pc.in (renamed from fuse.pc.in)2
-rw-r--r--include/Makefile.am7
-rw-r--r--include/fuse.h204
-rw-r--r--include/fuse_common.h103
-rw-r--r--include/fuse_common_compat.h26
-rw-r--r--include/fuse_compat.h201
-rw-r--r--include/fuse_kernel.h478
-rw-r--r--include/fuse_lowlevel.h307
-rw-r--r--include/fuse_lowlevel_compat.h155
-rw-r--r--include/fuse_opt.h5
-rw-r--r--include/old/fuse.h9
-rw-r--r--include/ulockmgr.h24
-rw-r--r--lib/Makefile.am14
-rw-r--r--lib/cuse_lowlevel.c10
-rw-r--r--lib/fuse.c495
-rw-r--r--lib/fuse_i.h76
-rw-r--r--lib/fuse_kern_chan.c98
-rw-r--r--lib/fuse_loop.c24
-rwxr-xr-x[-rw-r--r--]lib/fuse_loop_mt.c31
-rwxr-xr-x[-rw-r--r--]lib/fuse_lowlevel.c469
-rw-r--r--lib/fuse_misc.h12
-rw-r--r--lib/fuse_mt.c101
-rw-r--r--lib/fuse_opt.c15
-rw-r--r--lib/fuse_session.c156
-rwxr-xr-x[-rw-r--r--]lib/fuse_signals.c3
-rw-r--r--lib/fuse_versionscript84
-rw-r--r--lib/helper.c210
-rw-r--r--lib/modules/iconv.c7
-rw-r--r--lib/modules/subdir.c7
-rw-r--r--lib/mount.c36
-rw-r--r--lib/mount_bsd.c7
-rw-r--r--lib/mount_util.c1
-rw-r--r--lib/ulockmgr.c444
-rw-r--r--test/stracedecode.c1
-rw-r--r--util/.gitignore1
-rw-r--r--util/Makefile.am7
-rw-r--r--util/fusermount.c19
-rw-r--r--util/mount.fuse.c2
-rw-r--r--util/ulockmgr_server.c425
62 files changed, 1307 insertions, 3464 deletions
diff --git a/.gitignore b/.gitignore
index 65a37c7..ff4a66e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -30,7 +30,7 @@ config.*
/compile
/libtool
/INSTALL
-/fuse.pc
+/*.pc
/.pc
-/patches
+/patches*
/m4
diff --git a/ChangeLog b/ChangeLog
index 1b71fd4..753aaab 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -3,9 +3,31 @@
* libfuse: Add missing includes. This allows compiling fuse with
musl. Patch by Daniel Thau
-2013-07-01 Miklos Szeredi <miklos@szeredi.hu>
+2013-07-26 Miklos Szeredi <miklos@szeredi.hu>
- * Released 2.9.3
+ * Print help on stdout instead of stderr
+
+2013-07-25 Miklos Szeredi <miklos@szeredi.hu>
+
+ * libfuse: fuse -> fuse3. Allow 2.X and 3.X to coexist. Includes
+ are now stored under /usr/include/fuse3 and library is named
+ libfuse3.*. Invoke pkg-config with "fuse3" as the first argument
+ to build with version 3 of the library.
+
+ * ulockmgr: strip ulockmgr support from this source package and
+ distribute it separately. It is not needed for the building of
+ libfuse, only fusexmp_fh. Check ulockmgr library in ./configure
+ and if not disable remote-lock suport in fusexmp_fh.
+
+2013-07-24 Miklos Szeredi <miklos@szeredi.hu>
+
+ * libfuse: remove "-D_FILE_OFFSET_BITS=64" from fuse.pc, add
+ AC_SYS_LARGEFILE to your configure.ac instead.
+
+2013-06-21 Miklos Szeredi <miklos@szeredi.hu>
+
+ * libfuse: set FD_CLOEXEC also when receiving device fd from
+ fusermount
2013-06-20 Miklos Szeredi <miklos@szeredi.hu>
@@ -18,6 +40,67 @@
cancelling that same worker. This caused a segmenation
fault. Reported and tested by Anatol Pomozov
+2013-02-20 Miklos Szeredi <miklos@szeredi.hu>
+
+ * libfuse: change the type of fuse_ino_t from 'unsigned long' to
+ 'uint64_t'
+
+ * libfuse: use O_CLOEXEC flag when opening /dev/fuse device.
+ Patch by Richard W.M. Jones
+
+ * libfuse: don't force -D_FILE_OFFSET_BITS=64 in pkgconfig file.
+ Patch by Richard W.M. Jones
+
+2013-02-19 Miklos Szeredi <miklos@szeredi.hu>
+
+ * fuse_daemonize(): chdir to "/" even if not running in the
+ background for consistency. Reported by Vladimir Rutsky
+
+2013-02-18 Miklos Szeredi <miklos@szeredi.hu>
+
+ * fuse_opt_parse(): when storing a newly allocated string for
+ format "%s", free the previous value stored at that location.
+ Reported by Marco Schuster
+
+2013-02-07 Miklos Szeredi <miklos@szeredi.hu>
+
+ * libfuse: add readdirplus support in fuse_lowlevel_ops. Patch by
+ Feng Shuo
+
+ * libfuse: add poll_events to fuse_file_info. Patch by Enke Chen
+
+ * libfuse: fix fs cleanup. Reported by Eric Wong
+
+ * libfuse: pass security context options to kernel. Patch by
+ Dalvik Khertel
+
+ * libfuse: remove deprecated features:
+ - fuse_is_lib_option()
+ - fuse_invalidate()
+ - fuse_set_getcontext_func()
+ - fuse_loop_mt_proc()
+ - fuse_read_cmd()
+ - fuse_process_cmd()
+ - fuse_setup()
+ - fuse_teardown()
+ - fuse_exited()
+ - fuse_lowlevel_is_lib_option()
+ - fuse_operations.getdir()
+ - fuse_operations.utime()
+ - fuse_operations.utime_omit_ok
+
+2013-02-06 Miklos Szeredi <miklos@szeredi.hu>
+
+ * libfuse: set close-on-exec flag on pipe file descriptors. Patch
+ by Eric Wong
+
+ * libfuse: add missing INIT flags
+
+2013-02-05 Miklos Szeredi <miklos@szeredi.hu>
+
+ * libfuse: fix fuse_get_context() in non fuse threads. Reported
+ by Michael Berlin
+
2013-02-04 Miklos Szeredi <miklos@szeredi.hu>
* libfuse: fix crash in unlock_path(). Patch by Ratna Manoj
@@ -62,6 +145,12 @@
2012-07-19 Miklos Szeredi <miklos@szeredi.hu>
+ * Start of 3.0 series. This is going to be a new major version of
+ the library breaking backward compatibility on the binary level as
+ well as the source level.
+
+2012-07-19 Miklos Szeredi <miklos@szeredi.hu>
+
* Released 2.9.1
2012-07-19 Miklos Szeredi <miklos@szeredi.hu>
diff --git a/Makefile.am b/Makefile.am
index 8bb0781..10926cc 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -5,12 +5,12 @@ ACLOCAL_AMFLAGS = -I m4
SUBDIRS = @subdirs2@ doc
EXTRA_DIST = \
- fuse.pc.in \
+ fuse3.pc.in \
README* \
Filesystems \
FAQ
pkgconfigdir = @pkgconfigdir@
-pkgconfig_DATA = fuse.pc
+pkgconfig_DATA = fuse3.pc
$(pkgconfig_DATA): config.status
diff --git a/configure.ac b/configure.ac
index 8963f2a..0e621d4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,5 +1,4 @@
-AC_INIT(fuse, 2.9.3)
-
+AC_INIT(fuse, 3.0.0-pre0)
AC_PREREQ(2.59d)
AC_CONFIG_MACRO_DIR([m4])
AC_CANONICAL_TARGET
@@ -8,7 +7,8 @@ m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES(yes)])
AC_CONFIG_HEADERS(include/config.h)
AC_PROG_LIBTOOL
-AC_PROG_CC
+AC_PROG_CC_STDC
+AC_SYS_LARGEFILE
AC_PROG_MKDIR_P
AM_PROG_CC_C_O
@@ -53,7 +53,7 @@ if test "$enable_mtab" = "no"; then
AC_DEFINE(IGNORE_MTAB, 1, [Don't update /etc/mtab])
fi
-AC_CHECK_FUNCS([fork setxattr fdatasync splice vmsplice utimensat])
+AC_CHECK_FUNCS([fork setxattr fdatasync splice vmsplice utimensat pipe2])
AC_CHECK_FUNCS([posix_fallocate])
AC_CHECK_MEMBERS([struct stat.st_atim])
AC_CHECK_MEMBERS([struct stat.st_atimespec])
@@ -63,6 +63,11 @@ AC_SEARCH_LIBS(dlopen, [dl])
AC_SEARCH_LIBS(clock_gettime, [rt])
libfuse_libs=$LIBS
LIBS=
+AC_CHECK_LIB(ulockmgr, ulockmgr_op)
+fusexmp_fh_libs=$LIBS
+AC_SUBST(fusexmp_fh_libs)
+LIBS=
+
AC_ARG_WITH([libiconv-prefix],
[ --with-libiconv-prefix=DIR search for libiconv in DIR/include and DIR/lib], [
for dir in `echo "$withval" | tr : ' '`; do
@@ -112,7 +117,7 @@ if test "$arch" = linux -a "$cross_compiling" != "yes"; then
fi
fi
-AC_CONFIG_FILES([fuse.pc Makefile lib/Makefile util/Makefile example/Makefile include/Makefile doc/Makefile])
+AC_CONFIG_FILES([fuse3.pc Makefile lib/Makefile util/Makefile example/Makefile include/Makefile doc/Makefile])
AC_OUTPUT
if test "$util_linux_ok" = no; then
diff --git a/doc/.gitignore b/doc/.gitignore
new file mode 100644
index 0000000..1936cc1
--- /dev/null
+++ b/doc/.gitignore
@@ -0,0 +1 @@
+html
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/Makefile.am b/doc/Makefile.am
index ebc9679..bc34a9c 100644
--- a/doc/Makefile.am
+++ b/doc/Makefile.am
@@ -1,5 +1,5 @@
## Process this file with automake to produce Makefile.in
-dist_man_MANS = fusermount.1 mount.fuse.8 ulockmgr_server.1
+dist_man_MANS = fusermount.1 mount.fuse.8
EXTRA_DIST = how-fuse-works kernel.txt Doxyfile
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
new file mode 100644
index 0000000..a4a9731
--- /dev/null
+++ b/doc/images/490px-FUSE_structure.svg.png
Binary files differ
diff --git a/doc/mainpage.dox b/doc/mainpage.dox
new file mode 100755
index 0000000..9b1801f
--- /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/doc/ulockmgr_server.1 b/doc/ulockmgr_server.1
deleted file mode 100644
index 7b8ab9a..0000000
--- a/doc/ulockmgr_server.1
+++ /dev/null
@@ -1,28 +0,0 @@
-.TH ULOCKMGR_SERVER 1 2011\-10\-23 2.8.6 "Filesystem in Userspace (FUSE)"
-
-.SH NAME
-\fBulockmgr_server\fR \- Lock Manager Server for FUSE filesystems
-
-.SH SYNOPSIS
-\fBulockmgr_server\fR
-
-.SH DESCRIPTION
-Filesystem in Userspace (FUSE) is a simple interface for userspace programs to export a virtual filesystem to the Linux kernel. It also aims to provide a secure method for non privileged users to create and mount their own filesystem implementations.
-.PP
-\fBulockmgr_server\fR is the Userspace Lock Manager Server for FUSE filesystems.
-
-.SH OPTIONS
-\fBulockmgr_server\fR has no options.
-
-.SH SEE ALSO
-\fIfusermount\fR(1),
-\fImount\fR(8),
-\fImount.fuse\fR(8).
-
-.SH HOMEPAGE
-More information about ulockmgr_server and the FUSE project can be found at <\fIhttp://fuse.sourceforge.net/\fR>.
-
-.SH AUTHOR
-FUSE was written by Miklos Szeredi <\fImiklos@szeredi.hu\fR>.
-.PP
-This manual page was written by Daniel Baumann <\fIdaniel.baumann@progress\-technologies.net\fR>.
diff --git a/example/Makefile.am b/example/Makefile.am
index 1c04057..0db537b 100644
--- a/example/Makefile.am
+++ b/example/Makefile.am
@@ -1,12 +1,12 @@
## Process this file with automake to produce Makefile.in
-AM_CPPFLAGS = -I$(top_srcdir)/include -D_FILE_OFFSET_BITS=64 -D_REENTRANT
+AM_CPPFLAGS = -I$(top_srcdir)/include -D_REENTRANT
noinst_HEADERS = fioc.h
noinst_PROGRAMS = fusexmp fusexmp_fh null hello hello_ll fioc fioclient \
fsel fselclient cusexmp
-LDADD = ../lib/libfuse.la
-fusexmp_fh_LDADD = ../lib/libfuse.la ../lib/libulockmgr.la
+LDADD = ../lib/libfuse3.la
+fusexmp_fh_LDADD = ../lib/libfuse3.la @fusexmp_fh_libs@
fioclient_CPPFLAGS =
fioclient_LDFLAGS =
diff --git a/example/cusexmp.c b/example/cusexmp.c
index 01fcdf7..8d22075 100644..100755
--- a/example/cusexmp.c
+++ b/example/cusexmp.c
@@ -6,10 +6,25 @@
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
*/
-#define FUSE_USE_VERSION 29
+/** @file
+ * @tableofcontents
+ *
+ * cusexmp.c - CUSE example: Character device in Userspace
+ *
+ * \section section_compile compiling this example
+ *
+ * gcc -Wall cusexmp.c `pkg-config fuse3 --cflags --libs` -o cusexmp
+ *
+ * \section section_source the complete source
+ * \include cusexmp.c
+ */
+
+
+#define FUSE_USE_VERSION 30
+
+#include <config.h>
#include <cuse_lowlevel.h>
#include <fuse_opt.h>
diff --git a/example/fioc.c b/example/fioc.c
index bee40b9..2117ac8 100644..100755
--- a/example/fioc.c
+++ b/example/fioc.c
@@ -6,10 +6,25 @@
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
*/
-#define FUSE_USE_VERSION 26
+/** @file
+ * @tableofcontents
+ *
+ * fioc.c - FUSE fioc: FUSE ioctl example
+ *
+ * \section section_compile compiling this example
+ *
+ * gcc -Wall fioc.c `pkg-config fuse3 --cflags --libs` -o fioc
+ *
+ * \section section_source the complete source
+ * \include fioc.c
+ */
+
+
+#define FUSE_USE_VERSION 30
+
+#include <config.h>
#include <fuse.h>
#include <stdlib.h>
diff --git a/example/fioc.h b/example/fioc.h
index ec1a39d..42799aa 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..a7c0dbe 100644..100755
--- a/example/fioclient.c
+++ b/example/fioclient.c
@@ -5,10 +5,24 @@
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 <config.h>
+
#include <sys/types.h>
#include <sys/fcntl.h>
#include <sys/stat.h>
diff --git a/example/fsel.c b/example/fsel.c
index 9cf0221..69202ee 100644..100755
--- a/example/fsel.c
+++ b/example/fsel.c
@@ -6,10 +6,25 @@
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
*/
-#define FUSE_USE_VERSION 29
+/** @file
+ * @tableofcontents
+ *
+ * fsel.c - FUSE fsel: FUSE select example
+ *
+ * \section section_compile compiling this example
+ *
+ * gcc -Wall fsel.c `pkg-config fuse3 --cflags --libs` -o fsel
+ *
+ * \section section_source the complete source
+ * \include fsel.c
+ */
+
+
+#define FUSE_USE_VERSION 30
+
+#include <config.h>
#include <fuse.h>
#include <unistd.h>
diff --git a/example/fselclient.c b/example/fselclient.c
index 7c4b837..ac8b7b0 100644..100755
--- a/example/fselclient.c
+++ b/example/fselclient.c
@@ -6,9 +6,23 @@
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 <config.h>
+
#include <sys/select.h>
#include <sys/time.h>
#include <sys/types.h>
diff --git a/example/fusexmp.c b/example/fusexmp.c
index dca8a46..6f63ae9 100644..100755
--- a/example/fusexmp.c
+++ b/example/fusexmp.c
@@ -5,11 +5,23 @@
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
*/
-#define FUSE_USE_VERSION 26
+/** @file
+ * @tableofcontents
+ *
+ * fusexmp.c - FUSE: Filesystem in Userspace
+ *
+ * \section section_compile compiling this example
+ *
+ * gcc -Wall fusexmp.c `pkg-config fuse3 --cflags --libs` -o fusexmp
+ *
+ * \section section_source the complete source
+ * \include fusexmp.c
+ */
+
+
+#define FUSE_USE_VERSION 30
#ifdef HAVE_CONFIG_H
#include <config.h>
diff --git a/example/fusexmp_fh.c b/example/fusexmp_fh.c
index 1ba9dbc..ba6789b 100644..100755
--- a/example/fusexmp_fh.c
+++ b/example/fusexmp_fh.c
@@ -5,11 +5,22 @@
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
*/
-#define FUSE_USE_VERSION 26
+/** @file
+ * @tableofcontents
+ *
+ * fusexmp_fh.c - FUSE: Filesystem in Userspace
+ *
+ * \section section_compile compiling this example
+ *
+ * gcc -Wall fusexmp_fh.c `pkg-config fuse3 --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
#include <config.h>
@@ -18,7 +29,11 @@
#define _GNU_SOURCE
#include <fuse.h>
+
+#ifdef HAVE_LIBULOCKMGR
#include <ulockmgr.h>
+#endif
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@@ -489,6 +504,7 @@ static int xmp_removexattr(const char *path, const char *name)
}
#endif /* HAVE_SETXATTR */
+#ifdef HAVE_LIBULOCKMGR
static int xmp_lock(const char *path, struct fuse_file_info *fi, int cmd,
struct flock *lock)
{
@@ -497,6 +513,7 @@ static int xmp_lock(const char *path, struct fuse_file_info *fi, int cmd,
return ulockmgr_op(fi->fh, cmd, lock, &fi->lock_owner,
sizeof(fi->lock_owner));
}
+#endif
static int xmp_flock(const char *path, struct fuse_file_info *fi, int op)
{
@@ -551,13 +568,10 @@ static struct fuse_operations xmp_oper = {
.listxattr = xmp_listxattr,
.removexattr = xmp_removexattr,
#endif
+#ifdef HAVE_LIBULOCKMGR
.lock = xmp_lock,
- .flock = xmp_flock,
-
- .flag_nullpath_ok = 1,
-#if HAVE_UTIMENSAT
- .flag_utime_omit_ok = 1,
#endif
+ .flock = xmp_flock,
};
int main(int argc, char *argv[])
diff --git a/example/hello.c b/example/hello.c
index bcb6b4c..d26d826 100644..100755
--- a/example/hello.c
+++ b/example/hello.c
@@ -4,11 +4,38 @@
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
*/
-#define FUSE_USE_VERSION 26
+/** @file
+ *
+ * hello.c - minimal FUSE example featuring fuse_main usage
+ *
+ * \section section_compile compiling this example
+ *
+ * gcc -Wall hello.c `pkg-config fuse3 --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 <config.h>
#include <fuse.h>
#include <stdio.h>
diff --git a/example/hello_ll.c b/example/hello_ll.c
index 1405441..1bf7155 100644..100755
--- a/example/hello_ll.c
+++ b/example/hello_ll.c
@@ -4,11 +4,42 @@
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
*/
-#define FUSE_USE_VERSION 26
+/** @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 fuse3 --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 <config.h>
#include <fuse_lowlevel.h>
#include <stdio.h>
@@ -151,6 +182,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);
@@ -167,7 +199,10 @@ int main(int argc, char *argv[])
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);
}
@@ -179,3 +214,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 b72cf4d..1ff1954 100644..100755
--- a/example/null.c
+++ b/example/null.c
@@ -4,11 +4,24 @@
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
*/
-#define FUSE_USE_VERSION 26
+/** @file
+ *
+ * null.c - FUSE: Filesystem in Userspace
+ *
+ * \section section_compile compiling this example
+ *
+ * gcc -Wall null.c `pkg-config fuse3 --cflags --libs` -o null
+ *
+ * \section section_source the complete source
+ * \include null.c
+ */
+
+
+#define FUSE_USE_VERSION 30
+
+#include <config.h>
#include <fuse.h>
#include <string.h>
diff --git a/fuse.pc.in b/fuse3.pc.in
index 8fdb841..0b52ba1 100644
--- a/fuse.pc.in
+++ b/fuse3.pc.in
@@ -8,4 +8,4 @@ Description: Filesystem in Userspace
Version: @VERSION@
Libs: -L${libdir} -lfuse -pthread
Libs.private: @libfuse_libs@
-Cflags: -I${includedir}/fuse -D_FILE_OFFSET_BITS=64
+Cflags: -I${includedir}/fuse3
diff --git a/include/Makefile.am b/include/Makefile.am
index 663e164..ffbfafa 100644
--- a/include/Makefile.am
+++ b/include/Makefile.am
@@ -1,17 +1,12 @@
## Process this file with automake to produce Makefile.in
-fuseincludedir=$(includedir)/fuse
+fuseincludedir=$(includedir)/fuse3
fuseinclude_HEADERS = \
fuse.h \
- fuse_compat.h \
fuse_common.h \
- fuse_common_compat.h \
fuse_lowlevel.h \
- fuse_lowlevel_compat.h \
fuse_opt.h \
cuse_lowlevel.h
-include_HEADERS = old/fuse.h ulockmgr.h
-
noinst_HEADERS = fuse_kernel.h
diff --git a/include/fuse.h b/include/fuse.h
index c657e67..b8a9307 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -13,21 +13,13 @@
*
* This file defines the library interface of FUSE
*
- * IMPORTANT: you should define FUSE_USE_VERSION before including this
- * header. To use the newest API define it to 26 (recommended for any
- * new application), to use the old API define it to 21 (default) 22
- * or 25, to use the even older 1.X API define it to 11.
+ * IMPORTANT: you should define FUSE_USE_VERSION before including this header.
*/
-#ifndef FUSE_USE_VERSION
-#define FUSE_USE_VERSION 21
-#endif
-
#include "fuse_common.h"
#include <fcntl.h>
#include <time.h>
-#include <utime.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/statvfs.h>
@@ -44,9 +36,6 @@ extern "C" {
/** Handle for a FUSE filesystem */
struct fuse;
-/** Structure containing a raw command */
-struct fuse_cmd;
-
/** Function to add an entry in a readdir() operation
*
* @param buf the buffer passed to the readdir() operation
@@ -58,11 +47,6 @@ struct fuse_cmd;
typedef int (*fuse_fill_dir_t) (void *buf, const char *name,
const struct stat *stbuf, off_t off);
-/* Used by deprecated getdir() method */
-typedef struct fuse_dirhandle *fuse_dirh_t;
-typedef int (*fuse_dirfil_t) (fuse_dirh_t h, const char *name, int type,
- ino_t ino);
-
/**
* The file system operations:
*
@@ -86,6 +70,24 @@ typedef int (*fuse_dirfil_t) (fuse_dirh_t h, const char *name, int type,
* is also a snapshot of the relevant wiki pages in the doc/ folder.
*/
struct fuse_operations {
+ /**
+ * Flag indicating that the path need not be calculated for
+ * the following operations:
+ *
+ * read, write, flush, release, fsync, readdir, releasedir,
+ * fsyncdir, ftruncate, fgetattr, lock, ioctl and poll
+ *
+ * If this flag is set then the path will not be calculaged even if the
+ * file wasn't unlinked. However the path can still be non-NULL if it
+ * needs to be calculated for some other reason.
+ */
+ unsigned int flag_nopath:1;
+
+ /**
+ * Reserved flags, don't set
+ */
+ unsigned int flag_reserved:31;
+
/** Get file attributes.
*
* Similar to stat(). The 'st_dev' and 'st_blksize' fields are
@@ -104,9 +106,6 @@ struct fuse_operations {
*/
int (*readlink) (const char *, char *, size_t);
- /* Deprecated, use readdir() instead */
- int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
-
/** Create a file node
*
* This is called for creation of all non-directory, non-symlink
@@ -115,7 +114,7 @@ struct fuse_operations {
*/
int (*mknod) (const char *, mode_t, dev_t);
- /** Create a directory
+ /** Create a directory
*
* Note that the mode argument may not have the type specification
* bits set, i.e. S_ISDIR(mode) can be false. To obtain the
@@ -147,12 +146,6 @@ struct fuse_operations {
/** Change the size of a file */
int (*truncate) (const char *, off_t);
- /** Change the access and/or modification times of a file
- *
- * Deprecated, use utimens() instead.
- */
- int (*utime) (const char *, struct utimbuf *);
-
/** File open operation
*
* No creation (O_CREAT, O_EXCL) and by default also no
@@ -282,16 +275,12 @@ struct fuse_operations {
/** Read directory
*
- * This supersedes the old getdir() interface. New applications
- * should use this.
- *
* The filesystem may choose between two modes of operation:
*
* 1) The readdir implementation ignores the offset parameter, and
* passes zero to the filler function's offset. The filler
* function will not return '1' (unless an error happens), so the
- * whole directory is read in a single readdir operation. This
- * works just like the old getdir() method.
+ * whole directory is read in a single readdir operation.
*
* 2) The readdir implementation keeps track of the offsets of the
* directory entries. It uses the offset parameter and always
@@ -454,43 +443,6 @@ struct fuse_operations {
int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
/**
- * Flag indicating that the filesystem can accept a NULL path
- * as the first argument for the following operations:
- *
- * read, write, flush, release, fsync, readdir, releasedir,
- * fsyncdir, ftruncate, fgetattr, lock, ioctl and poll
- *
- * If this flag is set these operations continue to work on
- * unlinked files even if "-ohard_remove" option was specified.
- */
- unsigned int flag_nullpath_ok:1;
-
- /**
- * Flag indicating that the path need not be calculated for
- * the following operations:
- *
- * read, write, flush, release, fsync, readdir, releasedir,
- * fsyncdir, ftruncate, fgetattr, lock, ioctl and poll
- *
- * Closely related to flag_nullpath_ok, but if this flag is
- * set then the path will not be calculaged even if the file
- * wasn't unlinked. However the path can still be non-NULL if
- * it needs to be calculated for some other reason.
- */
- unsigned int flag_nopath:1;
-
- /**
- * Flag indicating that the filesystem accepts special
- * UTIME_NOW and UTIME_OMIT values in its utimens operation.
- */
- unsigned int flag_utime_omit_ok:1;
-
- /**
- * Reserved flags, don't set
- */
- unsigned int flag_reserved:29;
-
- /**
* Ioctl
*
* flags will have FUSE_IOCTL_COMPAT set for 32bit ioctls in
@@ -637,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,
@@ -683,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);
@@ -703,8 +659,24 @@ 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 will wait for one callback to return before calling another.
+ *
+ * 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);
@@ -746,16 +718,6 @@ int fuse_getgroups(int size, gid_t list[]);
int fuse_interrupted(void);
/**
- * Obsolete, doesn't do anything
- *
- * @return -EINVAL
- */
-int fuse_invalidate(struct fuse *f, const char *path);
-
-/* Deprecated, don't use */
-int fuse_is_lib_option(const char *opt);
-
-/**
* The real main function
*
* Do not call this directly, use fuse_main()
@@ -964,93 +926,9 @@ void fuse_register_module(struct fuse_module *mod);
fuse_register_module(&mod); \
}
-
-/* ----------------------------------------------------------- *
- * Advanced API for event handling, don't worry about this... *
- * ----------------------------------------------------------- */
-
-/* NOTE: the following functions are deprecated, and will be removed
- from the 3.0 API. Use the lowlevel session functions instead */
-
-/** Function type used to process commands */
-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[],
- const struct fuse_operations *op, size_t op_size,
- char **mountpoint, int *multithreaded,
- void *user_data);
-
-/** This is the part of fuse_main() after the event loop */
-void fuse_teardown(struct fuse *fuse, char *mountpoint);
-
-/** Read a single command. If none are read, return NULL */
-struct fuse_cmd *fuse_read_cmd(struct fuse *f);
-
-/** Process a single command */
-void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd);
-
-/** Multi threaded event loop, which calls the custom command
- processor function */
-int fuse_loop_mt_proc(struct fuse *f, fuse_processor_t proc, void *data);
-
-/** Return the exited flag, which indicates if fuse_exit() has been
- called */
-int fuse_exited(struct fuse *f);
-
-/** This function is obsolete and implemented as a no-op */
-void fuse_set_getcontext_func(struct fuse_context *(*func)(void));
-
/** Get session from fuse object */
struct fuse_session *fuse_get_session(struct fuse *f);
-/* ----------------------------------------------------------- *
- * Compatibility stuff *
- * ----------------------------------------------------------- */
-
-#if FUSE_USE_VERSION < 26
-# include "fuse_compat.h"
-# undef fuse_main
-# if FUSE_USE_VERSION == 25
-# define fuse_main(argc, argv, op) \
- fuse_main_real_compat25(argc, argv, op, sizeof(*(op)))
-# define fuse_new fuse_new_compat25
-# define fuse_setup fuse_setup_compat25
-# define fuse_teardown fuse_teardown_compat22
-# define fuse_operations fuse_operations_compat25
-# elif FUSE_USE_VERSION == 22
-# define fuse_main(argc, argv, op) \
- fuse_main_real_compat22(argc, argv, op, sizeof(*(op)))
-# define fuse_new fuse_new_compat22
-# define fuse_setup fuse_setup_compat22
-# define fuse_teardown fuse_teardown_compat22
-# define fuse_operations fuse_operations_compat22
-# define fuse_file_info fuse_file_info_compat
-# elif FUSE_USE_VERSION == 24
-# error Compatibility with high-level API version 24 not supported
-# else
-# define fuse_dirfil_t fuse_dirfil_t_compat
-# define __fuse_read_cmd fuse_read_cmd
-# define __fuse_process_cmd fuse_process_cmd
-# define __fuse_loop_mt fuse_loop_mt_proc
-# if FUSE_USE_VERSION == 21
-# define fuse_operations fuse_operations_compat2
-# define fuse_main fuse_main_compat2
-# define fuse_new fuse_new_compat2
-# define __fuse_setup fuse_setup_compat2
-# define __fuse_teardown fuse_teardown_compat22
-# define __fuse_exited fuse_exited
-# define __fuse_set_getcontext_func fuse_set_getcontext_func
-# else
-# define fuse_statfs fuse_statfs_compat1
-# define fuse_operations fuse_operations_compat1
-# define fuse_main fuse_main_compat1
-# define fuse_new fuse_new_compat1
-# define FUSE_DEBUG FUSE_DEBUG_COMPAT1
-# endif
-# endif
-#endif
-
#ifdef __cplusplus
}
#endif
diff --git a/include/fuse_common.h b/include/fuse_common.h
index a4d980d..765e0a3 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -1,5 +1,4 @@
-/*
- FUSE: Filesystem in Userspace
+/* FUSE: Filesystem in Userspace
Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
This program can be distributed under the terms of the GNU LGPLv2.
@@ -20,19 +19,14 @@
#include <sys/types.h>
/** Major version of FUSE library interface */
-#define FUSE_MAJOR_VERSION 2
+#define FUSE_MAJOR_VERSION 3
/** Minor version of FUSE library interface */
-#define FUSE_MINOR_VERSION 9
+#define FUSE_MINOR_VERSION 0
#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min))
#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
-/* This interface uses 64 bit off_t */
-#if _FILE_OFFSET_BITS != 64
-#error Please add -D_FILE_OFFSET_BITS=64 to your compile flags!
-#endif
-
#ifdef __cplusplus
extern "C" {
#endif
@@ -40,18 +34,15 @@ extern "C" {
/**
* Information about open files
*
- * Changed in version 2.5
+ * Changed in version 3.0
*/
struct fuse_file_info {
/** Open flags. Available in open() and release() */
int flags;
- /** Old file handle, don't use */
- unsigned long fh_old;
-
/** In case of a write operation indicates if this was caused by a
writepage */
- int writepage;
+ unsigned int writepage : 1;
/** Can be filled in by open, to use direct I/O on this file.
Introduced in version 2.4 */
@@ -85,6 +76,11 @@ struct fuse_file_info {
/** Lock owner id. Available in locking operations and flush */
uint64_t lock_owner;
+
+ /** Requested poll events. Available in ->poll. Only set on kernels
+ which support it. If unsupported, this field is set to zero.
+ Introduced in version 3.0 */
+ uint32_t poll_events;
};
/**
@@ -101,17 +97,20 @@ struct fuse_file_info {
* FUSE_CAP_SPLICE_READ: ability to use splice() to read from the fuse device
* FUSE_CAP_IOCTL_DIR: ioctl support on directories
*/
-#define FUSE_CAP_ASYNC_READ (1 << 0)
-#define FUSE_CAP_POSIX_LOCKS (1 << 1)
-#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3)
-#define FUSE_CAP_EXPORT_SUPPORT (1 << 4)
-#define FUSE_CAP_BIG_WRITES (1 << 5)
-#define FUSE_CAP_DONT_MASK (1 << 6)
-#define FUSE_CAP_SPLICE_WRITE (1 << 7)
-#define FUSE_CAP_SPLICE_MOVE (1 << 8)
-#define FUSE_CAP_SPLICE_READ (1 << 9)
-#define FUSE_CAP_FLOCK_LOCKS (1 << 10)
-#define FUSE_CAP_IOCTL_DIR (1 << 11)
+#define FUSE_CAP_ASYNC_READ (1 << 0)
+#define FUSE_CAP_POSIX_LOCKS (1 << 1)
+#define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3)
+#define FUSE_CAP_EXPORT_SUPPORT (1 << 4)
+#define FUSE_CAP_BIG_WRITES (1 << 5)
+#define FUSE_CAP_DONT_MASK (1 << 6)
+#define FUSE_CAP_SPLICE_WRITE (1 << 7)
+#define FUSE_CAP_SPLICE_MOVE (1 << 8)
+#define FUSE_CAP_SPLICE_READ (1 << 9)
+#define FUSE_CAP_FLOCK_LOCKS (1 << 10)
+#define FUSE_CAP_IOCTL_DIR (1 << 11)
+#define FUSE_CAP_AUTO_INVAL_DATA (1 << 12)
+#define FUSE_CAP_READDIRPLUS (1 << 13)
+#define FUSE_CAP_READDIRPLUS_AUTO (1 << 14)
/**
* Ioctl flags
@@ -449,8 +448,15 @@ 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);
@@ -461,6 +467,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);
@@ -468,38 +477,26 @@ void fuse_remove_signal_handlers(struct fuse_session *se);
* Compatibility stuff *
* ----------------------------------------------------------- */
-#if FUSE_USE_VERSION < 26
-# ifdef __FreeBSD__
-# if FUSE_USE_VERSION < 25
-# error On FreeBSD API version 25 or greater must be used
-# endif
-# endif
-# include "fuse_common_compat.h"
-# undef FUSE_MINOR_VERSION
-# undef fuse_main
-# define fuse_unmount fuse_unmount_compat22
-# if FUSE_USE_VERSION == 25
-# define FUSE_MINOR_VERSION 5
-# define fuse_mount fuse_mount_compat25
-# elif FUSE_USE_VERSION == 24 || FUSE_USE_VERSION == 22
-# define FUSE_MINOR_VERSION 4
-# define fuse_mount fuse_mount_compat22
-# elif FUSE_USE_VERSION == 21
-# define FUSE_MINOR_VERSION 1
-# define fuse_mount fuse_mount_compat22
-# elif FUSE_USE_VERSION == 11
-# warning Compatibility with API version 11 is deprecated
-# undef FUSE_MAJOR_VERSION
-# define FUSE_MAJOR_VERSION 1
-# define FUSE_MINOR_VERSION 1
-# define fuse_mount fuse_mount_compat1
-# else
-# error Compatibility with API version other than 21, 22, 24, 25 and 11 not supported
-# endif
+#if !defined(FUSE_USE_VERSION) || FUSE_USE_VERSION < 30
+# error only API version 30 or greater is supported
#endif
#ifdef __cplusplus
}
#endif
+
+/*
+ * This interface uses 64 bit off_t.
+ *
+ * On 32bit systems please add -D_FILE_OFFSET_BITS=64 to your compile flags!
+ */
+
+#if defined(__GNUC__) && (__GNUC__ > 4 || __GNUC__ == 4 && __GNUC_MINOR__ >= 6) && !defined __cplusplus
+_Static_assert(sizeof(off_t) == 8, "fuse: off_t must be 64bit");
+#else
+struct _fuse_off_t_must_be_64bit_dummy_struct \
+ { unsigned _fuse_off_t_must_be_64bit:((sizeof(off_t) == 8) ? 1 : -1); };
+#endif
+
#endif /* _FUSE_COMMON_H_ */
diff --git a/include/fuse_common_compat.h b/include/fuse_common_compat.h
deleted file mode 100644
index 34440ff..0000000
--- a/include/fuse_common_compat.h
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- FUSE: Filesystem in Userspace
- Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
-
- This program can be distributed under the terms of the GNU LGPLv2.
- See the file COPYING.LIB.
-*/
-
-/* these definitions provide source compatibility to prior versions.
- Do not include this file directly! */
-
-struct fuse_file_info_compat {
- int flags;
- unsigned long fh;
- int writepage;
- unsigned int direct_io : 1;
- unsigned int keep_cache : 1;
-};
-
-int fuse_mount_compat25(const char *mountpoint, struct fuse_args *args);
-
-int fuse_mount_compat22(const char *mountpoint, const char *opts);
-
-int fuse_mount_compat1(const char *mountpoint, const char *args[]);
-
-void fuse_unmount_compat22(const char *mountpoint);
diff --git a/include/fuse_compat.h b/include/fuse_compat.h
deleted file mode 100644
index e7497a9..0000000
--- a/include/fuse_compat.h
+++ /dev/null
@@ -1,201 +0,0 @@
-/*
- FUSE: Filesystem in Userspace
- Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
-
- This program can be distributed under the terms of the GNU LGPLv2.
- See the file COPYING.LIB.
-*/
-
-/* these definitions provide source compatibility to prior versions.
- Do not include this file directly! */
-
-struct fuse_operations_compat25 {
- int (*getattr) (const char *, struct stat *);
- int (*readlink) (const char *, char *, size_t);
- int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
- int (*mknod) (const char *, mode_t, dev_t);
- int (*mkdir) (const char *, mode_t);
- int (*unlink) (const char *);
- int (*rmdir) (const char *);
- int (*symlink) (const char *, const char *);
- int (*rename) (const char *, const char *);
- int (*link) (const char *, const char *);
- int (*chmod) (const char *, mode_t);
- int (*chown) (const char *, uid_t, gid_t);
- int (*truncate) (const char *, off_t);
- int (*utime) (const char *, struct utimbuf *);
- int (*open) (const char *, struct fuse_file_info *);
- int (*read) (const char *, char *, size_t, off_t,
- struct fuse_file_info *);
- int (*write) (const char *, const char *, size_t, off_t,
- struct fuse_file_info *);
- int (*statfs) (const char *, struct statvfs *);
- int (*flush) (const char *, struct fuse_file_info *);
- int (*release) (const char *, struct fuse_file_info *);
- int (*fsync) (const char *, int, struct fuse_file_info *);
- int (*setxattr) (const char *, const char *, const char *, size_t, int);
- int (*getxattr) (const char *, const char *, char *, size_t);
- int (*listxattr) (const char *, char *, size_t);
- int (*removexattr) (const char *, const char *);
- int (*opendir) (const char *, struct fuse_file_info *);
- int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t,
- struct fuse_file_info *);
- int (*releasedir) (const char *, struct fuse_file_info *);
- int (*fsyncdir) (const char *, int, struct fuse_file_info *);
- void *(*init) (void);
- void (*destroy) (void *);
- int (*access) (const char *, int);
- int (*create) (const char *, mode_t, struct fuse_file_info *);
- int (*ftruncate) (const char *, off_t, struct fuse_file_info *);
- int (*fgetattr) (const char *, struct stat *, struct fuse_file_info *);
-};
-
-struct fuse *fuse_new_compat25(int fd, struct fuse_args *args,
- const struct fuse_operations_compat25 *op,
- size_t op_size);
-
-int fuse_main_real_compat25(int argc, char *argv[],
- const struct fuse_operations_compat25 *op,
- size_t op_size);
-
-struct fuse *fuse_setup_compat25(int argc, char *argv[],
- const struct fuse_operations_compat25 *op,
- size_t op_size, char **mountpoint,
- int *multithreaded, int *fd);
-
-void fuse_teardown_compat22(struct fuse *fuse, int fd, char *mountpoint);
-
-#if !defined(__FreeBSD__) && !defined(__NetBSD__)
-#include <sys/statfs.h>
-
-struct fuse_operations_compat22 {
- int (*getattr) (const char *, struct stat *);
- int (*readlink) (const char *, char *, size_t);
- int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t);
- int (*mknod) (const char *, mode_t, dev_t);
- int (*mkdir) (const char *, mode_t);
- int (*unlink) (const char *);
- int (*rmdir) (const char *);
- int (*symlink) (const char *, const char *);
- int (*rename) (const char *, const char *);
- int (*link) (const char *, const char *);
- int (*chmod) (const char *, mode_t);
- int (*chown) (const char *, uid_t, gid_t);
- int (*truncate) (const char *, off_t);
- int (*utime) (const char *, struct utimbuf *);
- int (*open) (const char *, struct fuse_file_info_compat *);
- int (*read) (const char *, char *, size_t, off_t,
- struct fuse_file_info_compat *);
- int (*write) (const char *, const char *, size_t, off_t,
- struct fuse_file_info_compat *);
- int (*statfs) (const char *, struct statfs *);
- int (*flush) (const char *, struct fuse_file_info_compat *);
- int (*release) (const char *, struct fuse_file_info_compat *);
- int (*fsync) (const char *, int, struct fuse_file_info_compat *);
- int (*setxattr) (const char *, const char *, const char *, size_t, int);
- int (*getxattr) (const char *, const char *, char *, size_t);
- int (*listxattr) (const char *, char *, size_t);
- int (*removexattr) (const char *, const char *);
- int (*opendir) (const char *, struct fuse_file_info_compat *);
- int (*readdir) (const char *, void *, fuse_fill_dir_t, off_t,
- struct fuse_file_info_compat *);
- int (*releasedir) (const char *, struct fuse_file_info_compat *);
- int (*fsyncdir) (const char *, int, struct fuse_file_info_compat *);
- void *(*init) (void);
- void (*destroy) (void *);
-};
-
-struct fuse *fuse_new_compat22(int fd, const char *opts,
- const struct fuse_operations_compat22 *op,
- size_t op_size);
-
-struct fuse *fuse_setup_compat22(int argc, char *argv[],
- const struct fuse_operations_compat22 *op,
- size_t op_size, char **mountpoint,
- int *multithreaded, int *fd);
-
-int fuse_main_real_compat22(int argc, char *argv[],
- const struct fuse_operations_compat22 *op,
- size_t op_size);
-
-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 *);
- int (*readlink) (const char *, char *, size_t);
- int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t_compat);
- int (*mknod) (const char *, mode_t, dev_t);
- int (*mkdir) (const char *, mode_t);
- int (*unlink) (const char *);
- int (*rmdir) (const char *);
- int (*symlink) (const char *, const char *);
- int (*rename) (const char *, const char *);
- int (*link) (const char *, const char *);
- int (*chmod) (const char *, mode_t);
- int (*chown) (const char *, uid_t, gid_t);
- int (*truncate) (const char *, off_t);
- int (*utime) (const char *, struct utimbuf *);
- int (*open) (const char *, int);
- int (*read) (const char *, char *, size_t, off_t);
- int (*write) (const char *, const char *, size_t, off_t);
- int (*statfs) (const char *, struct statfs *);
- int (*flush) (const char *);
- int (*release) (const char *, int);
- int (*fsync) (const char *, int);
- int (*setxattr) (const char *, const char *, const char *,
- size_t, int);
- int (*getxattr) (const char *, const char *, char *, size_t);
- int (*listxattr) (const char *, char *, size_t);
- int (*removexattr) (const char *, const char *);
-};
-
-int fuse_main_compat2(int argc, char *argv[],
- const struct fuse_operations_compat2 *op);
-
-struct fuse *fuse_new_compat2(int fd, const char *opts,
- const struct fuse_operations_compat2 *op);
-
-struct fuse *fuse_setup_compat2(int argc, char *argv[],
- const struct fuse_operations_compat2 *op,
- char **mountpoint, int *multithreaded, int *fd);
-
-struct fuse_statfs_compat1 {
- long block_size;
- long blocks;
- long blocks_free;
- long files;
- long files_free;
- long namelen;
-};
-
-struct fuse_operations_compat1 {
- int (*getattr) (const char *, struct stat *);
- int (*readlink) (const char *, char *, size_t);
- int (*getdir) (const char *, fuse_dirh_t, fuse_dirfil_t_compat);
- int (*mknod) (const char *, mode_t, dev_t);
- int (*mkdir) (const char *, mode_t);
- int (*unlink) (const char *);
- int (*rmdir) (const char *);
- int (*symlink) (const char *, const char *);
- int (*rename) (const char *, const char *);
- int (*link) (const char *, const char *);
- int (*chmod) (const char *, mode_t);
- int (*chown) (const char *, uid_t, gid_t);
- int (*truncate) (const char *, off_t);
- int (*utime) (const char *, struct utimbuf *);
- int (*open) (const char *, int);
- int (*read) (const char *, char *, size_t, off_t);
- int (*write) (const char *, const char *, size_t, off_t);
- int (*statfs) (struct fuse_statfs_compat1 *);
- int (*release) (const char *, int);
- int (*fsync) (const char *, int);
-};
-
-#define FUSE_DEBUG_COMPAT1 (1 << 1)
-
-struct fuse *fuse_new_compat1(int fd, int flags,
- const struct fuse_operations_compat1 *op);
-
-void fuse_main_compat1(int argc, char *argv[],
- const struct fuse_operations_compat1 *op);
-
-#endif /* __FreeBSD__ || __NetBSD__ */
diff --git a/include/fuse_kernel.h b/include/fuse_kernel.h
index c632b58..706d035 100644
--- a/include/fuse_kernel.h
+++ b/include/fuse_kernel.h
@@ -83,17 +83,23 @@
*
* 7.19
* - add FUSE_FALLOCATE
+ *
+ * 7.20
+ * - add FUSE_AUTO_INVAL_DATA
+ *
+ * 7.21
+ * - add FUSE_READDIRPLUS
+ * - send the requested events in POLL request
*/
#ifndef _LINUX_FUSE_H
#define _LINUX_FUSE_H
-#include <sys/types.h>
-#define __u64 uint64_t
-#define __s64 int64_t
-#define __u32 uint32_t
-#define __s32 int32_t
-#define __u16 uint16_t
+#ifdef __KERNEL__
+#include <linux/types.h>
+#else
+#include <stdint.h>
+#endif
/*
* Version negotiation:
@@ -119,7 +125,7 @@
#define FUSE_KERNEL_VERSION 7
/** Minor version number of this interface */
-#define FUSE_KERNEL_MINOR_VERSION 19
+#define FUSE_KERNEL_MINOR_VERSION 21
/** The node ID of the root inode */
#define FUSE_ROOT_ID 1
@@ -128,42 +134,42 @@
userspace works under 64bit kernels */
struct fuse_attr {
- __u64 ino;
- __u64 size;
- __u64 blocks;
- __u64 atime;
- __u64 mtime;
- __u64 ctime;
- __u32 atimensec;
- __u32 mtimensec;
- __u32 ctimensec;
- __u32 mode;
- __u32 nlink;
- __u32 uid;
- __u32 gid;
- __u32 rdev;
- __u32 blksize;
- __u32 padding;
+ uint64_t ino;
+ uint64_t size;
+ uint64_t blocks;
+ uint64_t atime;
+ uint64_t mtime;
+ uint64_t ctime;
+ uint32_t atimensec;
+ uint32_t mtimensec;
+ uint32_t ctimensec;
+ uint32_t mode;
+ uint32_t nlink;
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t rdev;
+ uint32_t blksize;
+ uint32_t padding;
};
struct fuse_kstatfs {
- __u64 blocks;
- __u64 bfree;
- __u64 bavail;
- __u64 files;
- __u64 ffree;
- __u32 bsize;
- __u32 namelen;
- __u32 frsize;
- __u32 padding;
- __u32 spare[6];
+ uint64_t blocks;
+ uint64_t bfree;
+ uint64_t bavail;
+ uint64_t files;
+ uint64_t ffree;
+ uint32_t bsize;
+ uint32_t namelen;
+ uint32_t frsize;
+ uint32_t padding;
+ uint32_t spare[6];
};
struct fuse_file_lock {
- __u64 start;
- __u64 end;
- __u32 type;
- __u32 pid; /* tgid */
+ uint64_t start;
+ uint64_t end;
+ uint32_t type;
+ uint32_t pid; /* tgid */
};
/**
@@ -194,10 +200,21 @@ struct fuse_file_lock {
/**
* INIT request/reply flags
*
+ * FUSE_ASYNC_READ: asynchronous read requests
* FUSE_POSIX_LOCKS: remote locking for POSIX file locks
+ * FUSE_FILE_OPS: kernel sends file handle for fstat, etc... (not yet supported)
+ * FUSE_ATOMIC_O_TRUNC: handles the O_TRUNC open flag in the filesystem
* FUSE_EXPORT_SUPPORT: filesystem handles lookups of "." and ".."
+ * FUSE_BIG_WRITES: filesystem can handle write size larger than 4kB
* FUSE_DONT_MASK: don't apply umask to file mode on create operations
+ * FUSE_SPLICE_WRITE: kernel supports splice write on the device
+ * FUSE_SPLICE_MOVE: kernel supports splice move on the device
+ * FUSE_SPLICE_READ: kernel supports splice read on the device
* FUSE_FLOCK_LOCKS: remote locking for BSD style file locks
+ * FUSE_HAS_IOCTL_DIR: kernel supports ioctl on directories
+ * FUSE_AUTO_INVAL_DATA: automatically invalidate cached pages
+ * FUSE_DO_READDIRPLUS: do READDIRPLUS (READDIR+LOOKUP in one)
+ * FUSE_READDIRPLUS_AUTO: adaptive readdirplus
*/
#define FUSE_ASYNC_READ (1 << 0)
#define FUSE_POSIX_LOCKS (1 << 1)
@@ -206,7 +223,14 @@ struct fuse_file_lock {
#define FUSE_EXPORT_SUPPORT (1 << 4)
#define FUSE_BIG_WRITES (1 << 5)
#define FUSE_DONT_MASK (1 << 6)
+#define FUSE_SPLICE_WRITE (1 << 7)
+#define FUSE_SPLICE_MOVE (1 << 8)
+#define FUSE_SPLICE_READ (1 << 9)
#define FUSE_FLOCK_LOCKS (1 << 10)
+#define FUSE_HAS_IOCTL_DIR (1 << 11)
+#define FUSE_AUTO_INVAL_DATA (1 << 12)
+#define FUSE_DO_READDIRPLUS (1 << 13)
+#define FUSE_READDIRPLUS_AUTO (1 << 14)
/**
* CUSE INIT request/reply flags
@@ -313,6 +337,7 @@ enum fuse_opcode {
FUSE_NOTIFY_REPLY = 41,
FUSE_BATCH_FORGET = 42,
FUSE_FALLOCATE = 43,
+ FUSE_READDIRPLUS = 44,
/* CUSE specific operations */
CUSE_INIT = 4096,
@@ -334,143 +359,143 @@ enum fuse_notify_code {
#define FUSE_COMPAT_ENTRY_OUT_SIZE 120
struct fuse_entry_out {
- __u64 nodeid; /* Inode ID */
- __u64 generation; /* Inode generation: nodeid:gen must
- be unique for the fs's lifetime */
- __u64 entry_valid; /* Cache timeout for the name */
- __u64 attr_valid; /* Cache timeout for the attributes */
- __u32 entry_valid_nsec;
- __u32 attr_valid_nsec;
+ uint64_t nodeid; /* Inode ID */
+ uint64_t generation; /* Inode generation: nodeid:gen must
+ be unique for the fs's lifetime */
+ uint64_t entry_valid; /* Cache timeout for the name */
+ uint64_t attr_valid; /* Cache timeout for the attributes */
+ uint32_t entry_valid_nsec;
+ uint32_t attr_valid_nsec;
struct fuse_attr attr;
};
struct fuse_forget_in {
- __u64 nlookup;
+ uint64_t nlookup;
};
struct fuse_forget_one {
- __u64 nodeid;
- __u64 nlookup;
+ uint64_t nodeid;
+ uint64_t nlookup;
};
struct fuse_batch_forget_in {
- __u32 count;
- __u32 dummy;
+ uint32_t count;
+ uint32_t dummy;
};
struct fuse_getattr_in {
- __u32 getattr_flags;
- __u32 dummy;
- __u64 fh;
+ uint32_t getattr_flags;
+ uint32_t dummy;
+ uint64_t fh;
};
#define FUSE_COMPAT_ATTR_OUT_SIZE 96
struct fuse_attr_out {
- __u64 attr_valid; /* Cache timeout for the attributes */
- __u32 attr_valid_nsec;
- __u32 dummy;
+ uint64_t attr_valid; /* Cache timeout for the attributes */
+ uint32_t attr_valid_nsec;
+ uint32_t dummy;
struct fuse_attr attr;
};
#define FUSE_COMPAT_MKNOD_IN_SIZE 8
struct fuse_mknod_in {
- __u32 mode;
- __u32 rdev;
- __u32 umask;
- __u32 padding;
+ uint32_t mode;
+ uint32_t rdev;
+ uint32_t umask;
+ uint32_t padding;
};
struct fuse_mkdir_in {
- __u32 mode;
- __u32 umask;
+ uint32_t mode;
+ uint32_t umask;
};
struct fuse_rename_in {
- __u64 newdir;
+ uint64_t newdir;
};
struct fuse_link_in {
- __u64 oldnodeid;
+ uint64_t oldnodeid;
};
struct fuse_setattr_in {
- __u32 valid;
- __u32 padding;
- __u64 fh;
- __u64 size;
- __u64 lock_owner;
- __u64 atime;
- __u64 mtime;
- __u64 unused2;
- __u32 atimensec;
- __u32 mtimensec;
- __u32 unused3;
- __u32 mode;
- __u32 unused4;
- __u32 uid;
- __u32 gid;
- __u32 unused5;
+ uint32_t valid;
+ uint32_t padding;
+ uint64_t fh;
+ uint64_t size;
+ uint64_t lock_owner;
+ uint64_t atime;
+ uint64_t mtime;
+ uint64_t unused2;
+ uint32_t atimensec;
+ uint32_t mtimensec;
+ uint32_t unused3;
+ uint32_t mode;
+ uint32_t unused4;
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t unused5;
};
struct fuse_open_in {
- __u32 flags;
- __u32 unused;
+ uint32_t flags;
+ uint32_t unused;
};
struct fuse_create_in {
- __u32 flags;
- __u32 mode;
- __u32 umask;
- __u32 padding;
+ uint32_t flags;
+ uint32_t mode;
+ uint32_t umask;
+ uint32_t padding;
};
struct fuse_open_out {
- __u64 fh;
- __u32 open_flags;
- __u32 padding;
+ uint64_t fh;
+ uint32_t open_flags;
+ uint32_t padding;
};
struct fuse_release_in {
- __u64 fh;
- __u32 flags;
- __u32 release_flags;
- __u64 lock_owner;
+ uint64_t fh;
+ uint32_t flags;
+ uint32_t release_flags;
+ uint64_t lock_owner;
};
struct fuse_flush_in {
- __u64 fh;
- __u32 unused;
- __u32 padding;
- __u64 lock_owner;
+ uint64_t fh;
+ uint32_t unused;
+ uint32_t padding;
+ uint64_t lock_owner;
};
struct fuse_read_in {
- __u64 fh;
- __u64 offset;
- __u32 size;
- __u32 read_flags;
- __u64 lock_owner;
- __u32 flags;
- __u32 padding;
+ uint64_t fh;
+ uint64_t offset;
+ uint32_t size;
+ uint32_t read_flags;
+ uint64_t lock_owner;
+ uint32_t flags;
+ uint32_t padding;
};
#define FUSE_COMPAT_WRITE_IN_SIZE 24
struct fuse_write_in {
- __u64 fh;
- __u64 offset;
- __u32 size;
- __u32 write_flags;
- __u64 lock_owner;
- __u32 flags;
- __u32 padding;
+ uint64_t fh;
+ uint64_t offset;
+ uint32_t size;
+ uint32_t write_flags;
+ uint64_t lock_owner;
+ uint32_t flags;
+ uint32_t padding;
};
struct fuse_write_out {
- __u32 size;
- __u32 padding;
+ uint32_t size;
+ uint32_t padding;
};
#define FUSE_COMPAT_STATFS_SIZE 48
@@ -480,32 +505,32 @@ struct fuse_statfs_out {
};
struct fuse_fsync_in {
- __u64 fh;
- __u32 fsync_flags;
- __u32 padding;
+ uint64_t fh;
+ uint32_t fsync_flags;
+ uint32_t padding;
};
struct fuse_setxattr_in {
- __u32 size;
- __u32 flags;
+ uint32_t size;
+ uint32_t flags;
};
struct fuse_getxattr_in {
- __u32 size;
- __u32 padding;
+ uint32_t size;
+ uint32_t padding;
};
struct fuse_getxattr_out {
- __u32 size;
- __u32 padding;
+ uint32_t size;
+ uint32_t padding;
};
struct fuse_lk_in {
- __u64 fh;
- __u64 owner;
+ uint64_t fh;
+ uint64_t owner;
struct fuse_file_lock lk;
- __u32 lk_flags;
- __u32 padding;
+ uint32_t lk_flags;
+ uint32_t padding;
};
struct fuse_lk_out {
@@ -513,179 +538,190 @@ struct fuse_lk_out {
};
struct fuse_access_in {
- __u32 mask;
- __u32 padding;
+ uint32_t mask;
+ uint32_t padding;
};
struct fuse_init_in {
- __u32 major;
- __u32 minor;
- __u32 max_readahead;
- __u32 flags;
+ uint32_t major;
+ uint32_t minor;
+ uint32_t max_readahead;
+ uint32_t flags;
};
struct fuse_init_out {
- __u32 major;
- __u32 minor;
- __u32 max_readahead;
- __u32 flags;
- __u16 max_background;
- __u16 congestion_threshold;
- __u32 max_write;
+ uint32_t major;
+ uint32_t minor;
+ uint32_t max_readahead;
+ uint32_t flags;
+ uint16_t max_background;
+ uint16_t congestion_threshold;
+ uint32_t max_write;
};
#define CUSE_INIT_INFO_MAX 4096
struct cuse_init_in {
- __u32 major;
- __u32 minor;
- __u32 unused;
- __u32 flags;
+ uint32_t major;
+ uint32_t minor;
+ uint32_t unused;
+ uint32_t flags;
};
struct cuse_init_out {
- __u32 major;
- __u32 minor;
- __u32 unused;
- __u32 flags;
- __u32 max_read;
- __u32 max_write;
- __u32 dev_major; /* chardev major */
- __u32 dev_minor; /* chardev minor */
- __u32 spare[10];
+ uint32_t major;
+ uint32_t minor;
+ uint32_t unused;
+ uint32_t flags;
+ uint32_t max_read;
+ uint32_t max_write;
+ uint32_t dev_major; /* chardev major */
+ uint32_t dev_minor; /* chardev minor */
+ uint32_t spare[10];
};
struct fuse_interrupt_in {
- __u64 unique;
+ uint64_t unique;
};
struct fuse_bmap_in {
- __u64 block;
- __u32 blocksize;
- __u32 padding;
+ uint64_t block;
+ uint32_t blocksize;
+ uint32_t padding;
};
struct fuse_bmap_out {
- __u64 block;
+ uint64_t block;
};
struct fuse_ioctl_in {
- __u64 fh;
- __u32 flags;
- __u32 cmd;
- __u64 arg;
- __u32 in_size;
- __u32 out_size;
+ uint64_t fh;
+ uint32_t flags;
+ uint32_t cmd;
+ uint64_t arg;
+ uint32_t in_size;
+ uint32_t out_size;
};
struct fuse_ioctl_iovec {
- __u64 base;
- __u64 len;
+ uint64_t base;
+ uint64_t len;
};
struct fuse_ioctl_out {
- __s32 result;
- __u32 flags;
- __u32 in_iovs;
- __u32 out_iovs;
+ int32_t result;
+ uint32_t flags;
+ uint32_t in_iovs;
+ uint32_t out_iovs;
};
struct fuse_poll_in {
- __u64 fh;
- __u64 kh;
- __u32 flags;
- __u32 padding;
+ uint64_t fh;
+ uint64_t kh;
+ uint32_t flags;
+ uint32_t events;
};
struct fuse_poll_out {
- __u32 revents;
- __u32 padding;
+ uint32_t revents;
+ uint32_t padding;
};
struct fuse_notify_poll_wakeup_out {
- __u64 kh;
+ uint64_t kh;
};
struct fuse_fallocate_in {
- __u64 fh;
- __u64 offset;
- __u64 length;
- __u32 mode;
- __u32 padding;
+ uint64_t fh;
+ uint64_t offset;
+ uint64_t length;
+ uint32_t mode;
+ uint32_t padding;
};
struct fuse_in_header {
- __u32 len;
- __u32 opcode;
- __u64 unique;
- __u64 nodeid;
- __u32 uid;
- __u32 gid;
- __u32 pid;
- __u32 padding;
+ uint32_t len;
+ uint32_t opcode;
+ uint64_t unique;
+ uint64_t nodeid;
+ uint32_t uid;
+ uint32_t gid;
+ uint32_t pid;
+ uint32_t padding;
};
struct fuse_out_header {
- __u32 len;
- __s32 error;
- __u64 unique;
+ uint32_t len;
+ int32_t error;
+ uint64_t unique;
};
struct fuse_dirent {
- __u64 ino;
- __u64 off;
- __u32 namelen;
- __u32 type;
+ uint64_t ino;
+ uint64_t off;
+ uint32_t namelen;
+ uint32_t type;
char name[];
};
#define FUSE_NAME_OFFSET offsetof(struct fuse_dirent, name)
-#define FUSE_DIRENT_ALIGN(x) (((x) + sizeof(__u64) - 1) & ~(sizeof(__u64) - 1))
+#define FUSE_DIRENT_ALIGN(x) \
+ (((x) + sizeof(uint64_t) - 1) & ~(sizeof(uint64_t) - 1))
#define FUSE_DIRENT_SIZE(d) \
FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + (d)->namelen)
+struct fuse_direntplus {
+ struct fuse_entry_out entry_out;
+ struct fuse_dirent dirent;
+};
+
+#define FUSE_NAME_OFFSET_DIRENTPLUS \
+ offsetof(struct fuse_direntplus, dirent.name)
+#define FUSE_DIRENTPLUS_SIZE(d) \
+ FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_DIRENTPLUS + (d)->dirent.namelen)
+
struct fuse_notify_inval_inode_out {
- __u64 ino;
- __s64 off;
- __s64 len;
+ uint64_t ino;
+ int64_t off;
+ int64_t len;
};
struct fuse_notify_inval_entry_out {
- __u64 parent;
- __u32 namelen;
- __u32 padding;
+ uint64_t parent;
+ uint32_t namelen;
+ uint32_t padding;
};
struct fuse_notify_delete_out {
- __u64 parent;
- __u64 child;
- __u32 namelen;
- __u32 padding;
+ uint64_t parent;
+ uint64_t child;
+ uint32_t namelen;
+ uint32_t padding;
};
struct fuse_notify_store_out {
- __u64 nodeid;
- __u64 offset;
- __u32 size;
- __u32 padding;
+ uint64_t nodeid;
+ uint64_t offset;
+ uint32_t size;
+ uint32_t padding;
};
struct fuse_notify_retrieve_out {
- __u64 notify_unique;
- __u64 nodeid;
- __u64 offset;
- __u32 size;
- __u32 padding;
+ uint64_t notify_unique;
+ uint64_t nodeid;
+ uint64_t offset;
+ uint32_t size;
+ uint32_t padding;
};
/* Matches the size of fuse_write_in */
struct fuse_notify_retrieve_in {
- __u64 dummy1;
- __u64 offset;
- __u32 size;
- __u32 dummy2;
- __u64 dummy3;
- __u64 dummy4;
+ uint64_t dummy1;
+ uint64_t offset;
+ uint32_t size;
+ uint32_t dummy2;
+ uint64_t dummy3;
+ uint64_t dummy4;
};
#endif /* _LINUX_FUSE_H */
diff --git a/include/fuse_lowlevel.h b/include/fuse_lowlevel.h
index 2036717..595f061 100644
--- a/include/fuse_lowlevel.h
+++ b/include/fuse_lowlevel.h
@@ -44,7 +44,7 @@ extern "C" {
#define FUSE_ROOT_ID 1
/** Inode number type */
-typedef unsigned long fuse_ino_t;
+typedef uint64_t fuse_ino_t;
/** Request pointer type */
typedef struct fuse_req *fuse_req_t;
@@ -88,7 +88,7 @@ struct fuse_entry_param {
* it as an error.
*
*/
- unsigned long generation;
+ uint64_t generation;
/** Inode attributes.
*
@@ -122,7 +122,7 @@ struct fuse_ctx {
};
struct fuse_forget_data {
- uint64_t ino;
+ fuse_ino_t ino;
uint64_t nlookup;
};
@@ -233,7 +233,7 @@ struct fuse_lowlevel_ops {
* @param ino the inode number
* @param nlookup the number of lookups to forget
*/
- void (*forget) (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup);
+ void (*forget) (fuse_req_t req, fuse_ino_t ino, uint64_t nlookup);
/**
* Get file attributes
@@ -600,6 +600,9 @@ struct fuse_lowlevel_ops {
*
* fi->fh will contain the value set by the opendir method, or
* will be undefined if the opendir method didn't set any value.
+ *
+ * Returning a directory entry from readdir() does not affect
+ * its lookup count.
*
* Valid replies:
* fuse_reply_buf
@@ -1016,6 +1019,36 @@ struct fuse_lowlevel_ops {
*/
void (*fallocate) (fuse_req_t req, fuse_ino_t ino, int mode,
off_t offset, off_t length, struct fuse_file_info *fi);
+
+ /**
+ * Read directory with attributes
+ *
+ * Send a buffer filled using fuse_add_direntry_plus(), with size not
+ * exceeding the requested size. Send an empty buffer on end of
+ * stream.
+ *
+ * fi->fh will contain the value set by the opendir method, or
+ * will be undefined if the opendir method didn't set any value.
+ *
+ * In contrast to readdir() (which does not affect the lookup
+ * counts), the lookup count of every entry returned by
+ * readdirplus() is increased by one.
+ *
+ * Introduced in version 3.0
+ *
+ * Valid replies:
+ * fuse_reply_buf
+ * fuse_reply_data
+ * fuse_reply_err
+ *
+ * @param req request handle
+ * @param ino the inode number
+ * @param size maximum number of bytes to send
+ * @param off offset to continue reading the directory stream
+ * @param fi file information
+ */
+ void (*readdirplus) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
+ struct fuse_file_info *fi);
};
/**
@@ -1150,6 +1183,11 @@ int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size);
* Possible requests:
* read, readdir, getxattr, listxattr
*
+ * Side effects:
+ * when used to return data from a readdirplus() (but not readdir())
+ * call, increments the lookup count of each returned entry by one
+ * on success.
+ *
* @param req request handle
* @param bufv buffer vector
* @param flags flags controlling the copy
@@ -1252,6 +1290,34 @@ size_t fuse_add_direntry(fuse_req_t req, char *buf, size_t bufsize,
off_t off);
/**
+ * Add a directory entry to the buffer with the attributes
+ *
+ * Buffer needs to be large enough to hold the entry. If it's not,
+ * then the entry is not filled in but the size of the entry is still
+ * returned. The caller can check this by comparing the bufsize
+ * parameter with the returned entry size. If the entry size is
+ * larger than the buffer size, the operation failed.
+ *
+ * From the 'stbuf' argument the st_ino field and bits 12-15 of the
+ * st_mode field are used. The other fields are ignored.
+ *
+ * Note: offsets do not necessarily represent physical offsets, and
+ * could be any marker, that enables the implementation to find a
+ * specific point in the directory stream.
+ *
+ * @param req request handle
+ * @param buf the point where the new entry will be added to the buffer
+ * @param bufsize remaining size of the buffer
+ * @param name the name of the entry
+ * @param e the directory entry
+ * @param off the offset of the next entry
+ * @return the space needed for the entry
+ */
+size_t fuse_add_direntry_plus(fuse_req_t req, char *buf, size_t bufsize,
+ const char *name,
+ const struct fuse_entry_param *e, off_t off);
+
+/**
* Reply to ask for data fetch and output buffer preparation. ioctl
* will be retried with the specified input data fetched and output
* buffer prepared.
@@ -1491,9 +1557,6 @@ int fuse_req_interrupted(fuse_req_t req);
* Filesystem setup *
* ----------------------------------------------------------- */
-/* Deprecated, don't use */
-int fuse_lowlevel_is_lib_option(const char *opt);
-
/**
* Create a low level session
*
@@ -1502,6 +1565,9 @@ int fuse_lowlevel_is_lib_option(const char *opt);
* @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,
@@ -1512,61 +1578,8 @@ struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
* ----------------------------------------------------------- */
/**
- * Session operations
- *
- * This is used in session creation
- */
-struct fuse_session_ops {
- /**
- * Hook to process a request (mandatory)
- *
- * @param data user data passed to fuse_session_new()
- * @param buf buffer containing the raw request
- * @param len request length
- * @param ch channel on which the request was received
- */
- void (*process) (void *data, const char *buf, size_t len,
- struct fuse_chan *ch);
-
- /**
- * Hook for session exit and reset (optional)
- *
- * @param data user data passed to fuse_session_new()
- * @param val exited status (1 - exited, 0 - not exited)
- */
- void (*exit) (void *data, int val);
-
- /**
- * Hook for querying the current exited status (optional)
- *
- * @param data user data passed to fuse_session_new()
- * @return 1 if exited, 0 if not exited
- */
- int (*exited) (void *data);
-
- /**
- * Hook for cleaning up the channel on destroy (optional)
- *
- * @param data user data passed to fuse_session_new()
- */
- void (*destroy) (void *data);
-};
-
-/**
- * Create a new session
- *
- * @param op session operations
- * @param data user data
- * @return new session object, or NULL on failure
- */
-struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data);
-
-/**
* Assign a channel to a session
*
- * Note: currently only a single channel may be assigned. This may
- * change in the future
- *
* If a session is destroyed, the assigned channel is also destroyed
*
* @param se the session
@@ -1575,7 +1588,7 @@ struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data);
void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch);
/**
- * Remove a channel from a session
+ * Remove the channel from a session
*
* If the channel is not assigned to a session, then this is a no-op
*
@@ -1584,35 +1597,17 @@ void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch);
void fuse_session_remove_chan(struct fuse_chan *ch);
/**
- * Iterate over the channels assigned to a session
- *
- * The iterating function needs to start with a NULL channel, and
- * after that needs to pass the previously returned channel to the
- * function.
- *
- * @param se the session
- * @param ch the previous channel, or NULL
- * @return the next channel, or NULL if no more channels exist
- */
-struct fuse_chan *fuse_session_next_chan(struct fuse_session *se,
- struct fuse_chan *ch);
-
-/**
- * Process a raw request
+ * Return channel assigned to the session
*
* @param se the session
- * @param buf buffer containing the raw request
- * @param len request length
- * @param ch channel on which the request was received
+ * @return the channel
*/
-void fuse_session_process(struct fuse_session *se, const char *buf, size_t len,
- struct fuse_chan *ch);
+struct fuse_chan *fuse_session_chan(struct fuse_session *se);
/**
* Process a raw request supplied in a generic buffer
*
- * This is a more generic version of fuse_session_process(). The
- * fuse_buf may contain a memory buffer or a pipe file descriptor.
+ * The fuse_buf may contain a memory buffer or a pipe file descriptor.
*
* @param se the session
* @param buf the fuse_buf containing the request
@@ -1624,17 +1619,16 @@ void fuse_session_process_buf(struct fuse_session *se,
/**
* Receive a raw request supplied in a generic buffer
*
- * This is a more generic version of fuse_chan_recv(). The fuse_buf
- * supplied to this function contains a suitably allocated memory
+ * The fuse_buf supplied to this function contains a suitably allocated memory
* buffer. This may be overwritten with a file descriptor buffer.
*
* @param se the session
* @param buf the fuse_buf to store the request in
- * @param chp pointer to the channel
+ * @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 **chp);
+ struct fuse_chan *ch);
/**
* Destroy a session
@@ -1644,7 +1638,10 @@ 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()
*
* @param se the session
*/
@@ -1666,15 +1663,11 @@ void fuse_session_reset(struct fuse_session *se);
int fuse_session_exited(struct fuse_session *se);
/**
- * Get the user data provided to the session
+ * Enter a single threaded, blocking event loop.
*
- * @param se the session
- * @return the user data
- */
-void *fuse_session_data(struct fuse_session *se);
-
-/**
- * Enter a single threaded 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
@@ -1694,56 +1687,6 @@ int fuse_session_loop_mt(struct fuse_session *se);
* ----------------------------------------------------------- */
/**
- * Channel operations
- *
- * This is used in channel creation
- */
-struct fuse_chan_ops {
- /**
- * Hook for receiving a raw request
- *
- * @param ch pointer to the channel
- * @param buf the buffer to store the request in
- * @param size the size of the buffer
- * @return the actual size of the raw request, or -1 on error
- */
- int (*receive)(struct fuse_chan **chp, char *buf, size_t size);
-
- /**
- * Hook for sending a raw reply
- *
- * A return value of -ENOENT means, that the request was
- * interrupted, and the reply was discarded
- *
- * @param ch the channel
- * @param iov vector of blocks
- * @param count the number of blocks in vector
- * @return zero on success, -errno on failure
- */
- int (*send)(struct fuse_chan *ch, const struct iovec iov[],
- size_t count);
-
- /**
- * Destroy the channel
- *
- * @param ch the channel
- */
- void (*destroy)(struct fuse_chan *ch);
-};
-
-/**
- * Create a new channel
- *
- * @param op channel operations
- * @param fd file descriptor of the channel
- * @param bufsize the minimal receive buffer size
- * @param data user data
- * @return the new channel object, or NULL on failure
- */
-struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd,
- size_t bufsize, void *data);
-
-/**
* Query the file descriptor of the channel
*
* @param ch the channel
@@ -1752,84 +1695,12 @@ struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd,
int fuse_chan_fd(struct fuse_chan *ch);
/**
- * Query the minimal receive buffer size
- *
- * @param ch the channel
- * @return the buffer size passed to fuse_chan_new()
- */
-size_t fuse_chan_bufsize(struct fuse_chan *ch);
-
-/**
- * Query the user data
- *
- * @param ch the channel
- * @return the user data passed to fuse_chan_new()
- */
-void *fuse_chan_data(struct fuse_chan *ch);
-
-/**
- * Query the session to which this channel is assigned
- *
- * @param ch the channel
- * @return the session, or NULL if the channel is not assigned
- */
-struct fuse_session *fuse_chan_session(struct fuse_chan *ch);
-
-/**
- * Receive a raw request
- *
- * A return value of -ENODEV means, that the filesystem was unmounted
- *
- * @param ch pointer to the channel
- * @param buf the buffer to store the request in
- * @param size the size of the buffer
- * @return the actual size of the raw request, or -errno on error
- */
-int fuse_chan_recv(struct fuse_chan **ch, char *buf, size_t size);
-
-/**
- * Send a raw reply
- *
- * A return value of -ENOENT means, that the request was
- * interrupted, and the reply was discarded
- *
- * @param ch the channel
- * @param iov vector of blocks
- * @param count the number of blocks in vector
- * @return zero on success, -errno on failure
- */
-int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[],
- size_t count);
-
-/**
* Destroy a channel
*
* @param ch the channel
*/
void fuse_chan_destroy(struct fuse_chan *ch);
-/* ----------------------------------------------------------- *
- * Compatibility stuff *
- * ----------------------------------------------------------- */
-
-#if FUSE_USE_VERSION < 26
-# include "fuse_lowlevel_compat.h"
-# define fuse_chan_ops fuse_chan_ops_compat24
-# define fuse_chan_new fuse_chan_new_compat24
-# if FUSE_USE_VERSION == 25
-# define fuse_lowlevel_ops fuse_lowlevel_ops_compat25
-# define fuse_lowlevel_new fuse_lowlevel_new_compat25
-# elif FUSE_USE_VERSION == 24
-# define fuse_lowlevel_ops fuse_lowlevel_ops_compat
-# define fuse_lowlevel_new fuse_lowlevel_new_compat
-# define fuse_file_info fuse_file_info_compat
-# define fuse_reply_statfs fuse_reply_statfs_compat
-# define fuse_reply_open fuse_reply_open_compat
-# else
-# error Compatibility with low-level API version < 24 not supported
-# endif
-#endif
-
#ifdef __cplusplus
}
#endif
diff --git a/include/fuse_lowlevel_compat.h b/include/fuse_lowlevel_compat.h
deleted file mode 100644
index 8de220b..0000000
--- a/include/fuse_lowlevel_compat.h
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- FUSE: Filesystem in Userspace
- Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
-
- This program can be distributed under the terms of the GNU LGPLv2.
- See the file COPYING.LIB.
-*/
-
-/* these definitions provide source compatibility to prior versions.
- Do not include this file directly! */
-
-struct fuse_lowlevel_ops_compat25 {
- void (*init) (void *userdata);
- void (*destroy) (void *userdata);
- void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name);
- void (*forget) (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup);
- void (*getattr) (fuse_req_t req, fuse_ino_t ino,
- struct fuse_file_info *fi);
- void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
- int to_set, struct fuse_file_info *fi);
- void (*readlink) (fuse_req_t req, fuse_ino_t ino);
- void (*mknod) (fuse_req_t req, fuse_ino_t parent, const char *name,
- mode_t mode, dev_t rdev);
- void (*mkdir) (fuse_req_t req, fuse_ino_t parent, const char *name,
- mode_t mode);
- void (*unlink) (fuse_req_t req, fuse_ino_t parent, const char *name);
- void (*rmdir) (fuse_req_t req, fuse_ino_t parent, const char *name);
- void (*symlink) (fuse_req_t req, const char *link, fuse_ino_t parent,
- const char *name);
- void (*rename) (fuse_req_t req, fuse_ino_t parent, const char *name,
- fuse_ino_t newparent, const char *newname);
- void (*link) (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
- const char *newname);
- void (*open) (fuse_req_t req, fuse_ino_t ino,
- struct fuse_file_info *fi);
- void (*read) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
- struct fuse_file_info *fi);
- void (*write) (fuse_req_t req, fuse_ino_t ino, const char *buf,
- size_t size, off_t off, struct fuse_file_info *fi);
- void (*flush) (fuse_req_t req, fuse_ino_t ino,
- struct fuse_file_info *fi);
- void (*release) (fuse_req_t req, fuse_ino_t ino,
- struct fuse_file_info *fi);
- void (*fsync) (fuse_req_t req, fuse_ino_t ino, int datasync,
- struct fuse_file_info *fi);
- void (*opendir) (fuse_req_t req, fuse_ino_t ino,
- struct fuse_file_info *fi);
- void (*readdir) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
- struct fuse_file_info *fi);
- void (*releasedir) (fuse_req_t req, fuse_ino_t ino,
- struct fuse_file_info *fi);
- void (*fsyncdir) (fuse_req_t req, fuse_ino_t ino, int datasync,
- struct fuse_file_info *fi);
- void (*statfs) (fuse_req_t req);
- void (*setxattr) (fuse_req_t req, fuse_ino_t ino, const char *name,
- const char *value, size_t size, int flags);
- void (*getxattr) (fuse_req_t req, fuse_ino_t ino, const char *name,
- size_t size);
- void (*listxattr) (fuse_req_t req, fuse_ino_t ino, size_t size);
- void (*removexattr) (fuse_req_t req, fuse_ino_t ino, const char *name);
- void (*access) (fuse_req_t req, fuse_ino_t ino, int mask);
- void (*create) (fuse_req_t req, fuse_ino_t parent, const char *name,
- mode_t mode, struct fuse_file_info *fi);
-};
-
-struct fuse_session *fuse_lowlevel_new_compat25(struct fuse_args *args,
- const struct fuse_lowlevel_ops_compat25 *op,
- size_t op_size, void *userdata);
-
-size_t fuse_dirent_size(size_t namelen);
-
-char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf,
- off_t off);
-
-#if !defined(__FreeBSD__) && !defined(__NetBSD__)
-
-#include <sys/statfs.h>
-
-struct fuse_lowlevel_ops_compat {
- void (*init) (void *userdata);
- void (*destroy) (void *userdata);
- void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name);
- void (*forget) (fuse_req_t req, fuse_ino_t ino, unsigned long nlookup);
- void (*getattr) (fuse_req_t req, fuse_ino_t ino,
- struct fuse_file_info_compat *fi);
- void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr,
- int to_set, struct fuse_file_info_compat *fi);
- void (*readlink) (fuse_req_t req, fuse_ino_t ino);
- void (*mknod) (fuse_req_t req, fuse_ino_t parent, const char *name,
- mode_t mode, dev_t rdev);
- void (*mkdir) (fuse_req_t req, fuse_ino_t parent, const char *name,
- mode_t mode);
- void (*unlink) (fuse_req_t req, fuse_ino_t parent, const char *name);
- void (*rmdir) (fuse_req_t req, fuse_ino_t parent, const char *name);
- void (*symlink) (fuse_req_t req, const char *link, fuse_ino_t parent,
- const char *name);
- void (*rename) (fuse_req_t req, fuse_ino_t parent, const char *name,
- fuse_ino_t newparent, const char *newname);
- void (*link) (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent,
- const char *newname);
- void (*open) (fuse_req_t req, fuse_ino_t ino,
- struct fuse_file_info_compat *fi);
- void (*read) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
- struct fuse_file_info_compat *fi);
- void (*write) (fuse_req_t req, fuse_ino_t ino, const char *buf,
- size_t size, off_t off, struct fuse_file_info_compat *fi);
- void (*flush) (fuse_req_t req, fuse_ino_t ino,
- struct fuse_file_info_compat *fi);
- void (*release) (fuse_req_t req, fuse_ino_t ino,
- struct fuse_file_info_compat *fi);
- void (*fsync) (fuse_req_t req, fuse_ino_t ino, int datasync,
- struct fuse_file_info_compat *fi);
- void (*opendir) (fuse_req_t req, fuse_ino_t ino,
- struct fuse_file_info_compat *fi);
- void (*readdir) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off,
- struct fuse_file_info_compat *fi);
- void (*releasedir) (fuse_req_t req, fuse_ino_t ino,
- struct fuse_file_info_compat *fi);
- void (*fsyncdir) (fuse_req_t req, fuse_ino_t ino, int datasync,
- struct fuse_file_info_compat *fi);
- void (*statfs) (fuse_req_t req);
- void (*setxattr) (fuse_req_t req, fuse_ino_t ino, const char *name,
- const char *value, size_t size, int flags);
- void (*getxattr) (fuse_req_t req, fuse_ino_t ino, const char *name,
- size_t size);
- void (*listxattr) (fuse_req_t req, fuse_ino_t ino, size_t size);
- void (*removexattr) (fuse_req_t req, fuse_ino_t ino, const char *name);
- void (*access) (fuse_req_t req, fuse_ino_t ino, int mask);
- void (*create) (fuse_req_t req, fuse_ino_t parent, const char *name,
- mode_t mode, struct fuse_file_info_compat *fi);
-};
-
-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_compat *op,
- size_t op_size, void *userdata);
-
-#endif /* __FreeBSD__ || __NetBSD__ */
-
-struct fuse_chan_ops_compat24 {
- int (*receive)(struct fuse_chan *ch, char *buf, size_t size);
- int (*send)(struct fuse_chan *ch, const struct iovec iov[],
- size_t count);
- void (*destroy)(struct fuse_chan *ch);
-};
-
-struct fuse_chan *fuse_chan_new_compat24(struct fuse_chan_ops_compat24 *op,
- int fd, size_t bufsize, void *data);
-
-int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size);
-struct fuse_chan *fuse_kern_chan_new(int fd);
diff --git a/include/fuse_opt.h b/include/fuse_opt.h
index add0a30..20653b1 100644
--- a/include/fuse_opt.h
+++ b/include/fuse_opt.h
@@ -70,8 +70,9 @@ extern "C" {
*
* 6) "-x %s", etc. Combination of 4) and 5)
*
- * If the format is "%s", memory is allocated for the string unlike
- * with scanf().
+ * If the format is "%s", memory is allocated for the string unlike with
+ * scanf(). The previous value (if non-NULL) stored at the this location is
+ * freed.
*/
struct fuse_opt {
/** Matching template and optional parameter formatting */
diff --git a/include/old/fuse.h b/include/old/fuse.h
deleted file mode 100644
index 3db0945..0000000
--- a/include/old/fuse.h
+++ /dev/null
@@ -1,9 +0,0 @@
-/*
- This header is for compatibility with older software using FUSE.
-
- Please use 'pkg-config --cflags fuse' to set include path. The
- correct usage is still '#include <fuse.h>', not '#include
- <fuse/fuse.h>'.
-*/
-
-#include "fuse/fuse.h"
diff --git a/include/ulockmgr.h b/include/ulockmgr.h
deleted file mode 100644
index ad55579..0000000
--- a/include/ulockmgr.h
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- libulockmgr: Userspace Lock Manager Library
- Copyright (C) 2006 Miklos Szeredi <miklos@szeredi.hu>
-
- This program can be distributed under the terms of the GNU LGPLv2.
- See the file COPYING.LIB.
-*/
-
-#include <stdint.h>
-#include <fcntl.h>
-#include <sys/types.h>
-
-/**
- * Perform POSIX locking operation
- *
- * @param fd the file descriptor
- * @param cmd the locking command (F_GETFL, F_SETLK or F_SETLKW)
- * @param lock the lock parameters
- * @param owner the lock owner ID cookie
- * @param owner_len length of the lock owner ID cookie
- * @return 0 on success -errno on error
- */
-int ulockmgr_op(int fd, int cmd, struct flock *lock, const void *owner,
- size_t owner_len);
diff --git a/lib/Makefile.am b/lib/Makefile.am
index 87c0522..2ad0f15 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -1,9 +1,9 @@
## Process this file with automake to produce Makefile.in
AM_CPPFLAGS = -I$(top_srcdir)/include -DFUSERMOUNT_DIR=\"$(bindir)\" \
- -D_FILE_OFFSET_BITS=64 -D_REENTRANT -DFUSE_USE_VERSION=26
+ -D_REENTRANT -DFUSE_USE_VERSION=30
-lib_LTLIBRARIES = libfuse.la libulockmgr.la
+lib_LTLIBRARIES = libfuse3.la
if BSD
mount_source = mount_bsd.c
@@ -17,10 +17,9 @@ else
iconv_source =
endif
-libfuse_la_SOURCES = \
+libfuse3_la_SOURCES = \
fuse.c \
fuse_i.h \
- fuse_kern_chan.c \
fuse_loop.c \
fuse_loop_mt.c \
fuse_lowlevel.c \
@@ -36,14 +35,11 @@ libfuse_la_SOURCES = \
$(iconv_source) \
$(mount_source)
-libfuse_la_LDFLAGS = -pthread @libfuse_libs@ -version-number 2:9:3 \
+libfuse3_la_LDFLAGS = -pthread @libfuse_libs@ -version-number 0:0:0 \
-Wl,--version-script,$(srcdir)/fuse_versionscript
if NETBSD
-libfuse_la_LIBADD = -lperfuse -lpuffs
+libfuse3_la_LIBADD = -lperfuse -lpuffs
endif
-libulockmgr_la_SOURCES = ulockmgr.c
-libulockmgr_la_LDFLAGS = -pthread -version-number 1:0:1
-
EXTRA_DIST = fuse_versionscript
diff --git a/lib/cuse_lowlevel.c b/lib/cuse_lowlevel.c
index 402cf4b..fbaa873 100644
--- a/lib/cuse_lowlevel.c
+++ b/lib/cuse_lowlevel.c
@@ -7,11 +7,11 @@
See the file COPYING.LIB.
*/
+#include "config.h"
#include "cuse_lowlevel.h"
#include "fuse_kernel.h"
#include "fuse_i.h"
#include "fuse_opt.h"
-#include "fuse_misc.h"
#include <stdio.h>
#include <string.h>
@@ -170,12 +170,12 @@ struct fuse_session *cuse_lowlevel_new(struct fuse_args *args,
lop.ioctl = clop->ioctl ? cuse_fll_ioctl : NULL;
lop.poll = clop->poll ? cuse_fll_poll : NULL;
- se = fuse_lowlevel_new_common(args, &lop, sizeof(lop), userdata);
+ se = fuse_lowlevel_new(args, &lop, sizeof(lop), userdata);
if (!se) {
free(cd);
return NULL;
}
- ll = se->data;
+ ll = se->f;
ll->cuse_data = cd;
return se;
@@ -200,7 +200,7 @@ void cuse_lowlevel_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
struct cuse_init_out outarg;
struct fuse_ll *f = req->f;
struct cuse_data *cd = f->cuse_data;
- size_t bufsize = fuse_chan_bufsize(req->ch);
+ size_t bufsize = f->bufsize;
struct cuse_lowlevel_ops *clop = req_clop(req);
(void) nodeid;
@@ -313,7 +313,7 @@ struct fuse_session *cuse_lowlevel_setup(int argc, char *argv[],
goto err_se;
}
- ch = fuse_kern_chan_new(fd);
+ ch = fuse_chan_new(fd);
if (!ch) {
close(fd);
goto err_se;
diff --git a/lib/fuse.c b/lib/fuse.c
index cfac238..7508c54 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -15,8 +15,6 @@
#include "fuse_lowlevel.h"
#include "fuse_opt.h"
#include "fuse_misc.h"
-#include "fuse_common_compat.h"
-#include "fuse_compat.h"
#include "fuse_kernel.h"
#include <stdio.h>
@@ -83,7 +81,6 @@ struct fuse_fs {
struct fuse_operations op;
struct fuse_module *m;
void *user_data;
- int compat;
int debug;
};
@@ -146,8 +143,6 @@ struct fuse {
struct fuse_config conf;
int intr_installed;
struct fuse_fs *fs;
- int nullpath_ok;
- int utime_omit_ok;
struct lock_queue_element *lockq;
int pagesize;
struct list_head partial_slabs;
@@ -208,12 +203,6 @@ struct fuse_dh {
fuse_ino_t nodeid;
};
-/* old dir handle */
-struct fuse_dirhandle {
- fuse_fill_dir_t filler;
- void *buf;
-};
-
struct fuse_context_i {
struct fuse_context ctx;
fuse_req_t req;
@@ -1104,10 +1093,13 @@ static void debug_path(struct fuse *f, const char *msg, fuse_ino_t nodeid,
if (wr)
wnode = lookup_node(f, nodeid, name);
- if (wnode)
- fprintf(stderr, "%s %li (w)\n", msg, wnode->nodeid);
- else
- fprintf(stderr, "%s %li\n", msg, nodeid);
+ if (wnode) {
+ fprintf(stderr, "%s %llu (w)\n",
+ msg, (unsigned long long) wnode->nodeid);
+ } else {
+ fprintf(stderr, "%s %llu\n",
+ msg, (unsigned long long) nodeid);
+ }
}
}
@@ -1182,7 +1174,7 @@ static int get_path_nullok(struct fuse *f, fuse_ino_t nodeid, char **path)
*path = NULL;
} else {
err = get_path_common(f, nodeid, NULL, path, NULL);
- if (err == -ENOENT && f->nullpath_ok)
+ if (err == -ENOENT)
err = 0;
}
@@ -1464,129 +1456,6 @@ static inline void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,
fuse_do_prepare_interrupt(req, d);
}
-#if !defined(__FreeBSD__) && !defined(__NetBSD__)
-
-static int fuse_compat_open(struct fuse_fs *fs, const char *path,
- struct fuse_file_info *fi)
-{
- int err;
- if (!fs->compat || fs->compat >= 25)
- err = fs->op.open(path, fi);
- else if (fs->compat == 22) {
- struct fuse_file_info_compat tmp;
- memcpy(&tmp, fi, sizeof(tmp));
- err = ((struct fuse_operations_compat22 *) &fs->op)->open(path,
- &tmp);
- memcpy(fi, &tmp, sizeof(tmp));
- fi->fh = tmp.fh;
- } else
- err = ((struct fuse_operations_compat2 *) &fs->op)
- ->open(path, fi->flags);
- return err;
-}
-
-static int fuse_compat_release(struct fuse_fs *fs, const char *path,
- struct fuse_file_info *fi)
-{
- if (!fs->compat || fs->compat >= 22)
- return fs->op.release(path, fi);
- else
- return ((struct fuse_operations_compat2 *) &fs->op)
- ->release(path, fi->flags);
-}
-
-static int fuse_compat_opendir(struct fuse_fs *fs, const char *path,
- struct fuse_file_info *fi)
-{
- if (!fs->compat || fs->compat >= 25)
- return fs->op.opendir(path, fi);
- else {
- int err;
- struct fuse_file_info_compat tmp;
- memcpy(&tmp, fi, sizeof(tmp));
- err = ((struct fuse_operations_compat22 *) &fs->op)
- ->opendir(path, &tmp);
- memcpy(fi, &tmp, sizeof(tmp));
- fi->fh = tmp.fh;
- return err;
- }
-}
-
-static void convert_statfs_compat(struct fuse_statfs_compat1 *compatbuf,
- struct statvfs *stbuf)
-{
- stbuf->f_bsize = compatbuf->block_size;
- stbuf->f_blocks = compatbuf->blocks;
- stbuf->f_bfree = compatbuf->blocks_free;
- stbuf->f_bavail = compatbuf->blocks_free;
- stbuf->f_files = compatbuf->files;
- stbuf->f_ffree = compatbuf->files_free;
- stbuf->f_namemax = compatbuf->namelen;
-}
-
-static void convert_statfs_old(struct statfs *oldbuf, struct statvfs *stbuf)
-{
- stbuf->f_bsize = oldbuf->f_bsize;
- stbuf->f_blocks = oldbuf->f_blocks;
- stbuf->f_bfree = oldbuf->f_bfree;
- stbuf->f_bavail = oldbuf->f_bavail;
- stbuf->f_files = oldbuf->f_files;
- stbuf->f_ffree = oldbuf->f_ffree;
- stbuf->f_namemax = oldbuf->f_namelen;
-}
-
-static int fuse_compat_statfs(struct fuse_fs *fs, const char *path,
- struct statvfs *buf)
-{
- int err;
-
- if (!fs->compat || fs->compat >= 25) {
- err = fs->op.statfs(fs->compat == 25 ? "/" : path, buf);
- } else if (fs->compat > 11) {
- struct statfs oldbuf;
- err = ((struct fuse_operations_compat22 *) &fs->op)
- ->statfs("/", &oldbuf);
- if (!err)
- convert_statfs_old(&oldbuf, buf);
- } else {
- struct fuse_statfs_compat1 compatbuf;
- memset(&compatbuf, 0, sizeof(struct fuse_statfs_compat1));
- err = ((struct fuse_operations_compat1 *) &fs->op)
- ->statfs(&compatbuf);
- if (!err)
- convert_statfs_compat(&compatbuf, buf);
- }
- return err;
-}
-
-#else /* __FreeBSD__ || __NetBSD__ */
-
-static inline int fuse_compat_open(struct fuse_fs *fs, char *path,
- struct fuse_file_info *fi)
-{
- return fs->op.open(path, fi);
-}
-
-static inline int fuse_compat_release(struct fuse_fs *fs, const char *path,
- struct fuse_file_info *fi)
-{
- return fs->op.release(path, fi);
-}
-
-static inline int fuse_compat_opendir(struct fuse_fs *fs, const char *path,
- struct fuse_file_info *fi)
-{
- return fs->op.opendir(path, fi);
-}
-
-static inline int fuse_compat_statfs(struct fuse_fs *fs, const char *path,
- struct statvfs *buf)
-{
- return fs->op.statfs(fs->compat == 25 ? "/" : path, buf);
-}
-
-#endif /* __FreeBSD__ || __NetBSD__ */
-
int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf)
{
fuse_get_context()->private_data = fs->user_data;
@@ -1696,7 +1565,7 @@ int fuse_fs_release(struct fuse_fs *fs, const char *path,
fi->flush ? "+flush" : "",
(unsigned long long) fi->fh, fi->flags);
- return fuse_compat_release(fs, path, fi);
+ return fs->op.release(path, fi);
} else {
return 0;
}
@@ -1713,10 +1582,10 @@ int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
fprintf(stderr, "opendir flags: 0x%x %s\n", fi->flags,
path);
- err = fuse_compat_opendir(fs, path, fi);
+ err = fs->op.opendir(path, fi);
if (fs->debug && !err)
- fprintf(stderr, " opendir[%lli] flags: 0x%x %s\n",
+ fprintf(stderr, " opendir[%llu] flags: 0x%x %s\n",
(unsigned long long) fi->fh, fi->flags, path);
return err;
@@ -1736,10 +1605,10 @@ int fuse_fs_open(struct fuse_fs *fs, const char *path,
fprintf(stderr, "open flags: 0x%x %s\n", fi->flags,
path);
- err = fuse_compat_open(fs, path, fi);
+ err = fs->op.open(path, fi);
if (fs->debug && !err)
- fprintf(stderr, " open[%lli] flags: 0x%x %s\n",
+ fprintf(stderr, " open[%llu] flags: 0x%x %s\n",
(unsigned long long) fi->fh, fi->flags, path);
return err;
@@ -1958,7 +1827,7 @@ int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf)
if (fs->debug)
fprintf(stderr, "statfs %s\n", path);
- return fuse_compat_statfs(fs, path, buf);
+ return fs->op.statfs(path, buf);
} else {
buf->f_namemax = 255;
buf->f_bsize = 512;
@@ -1981,20 +1850,6 @@ int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
}
}
-static int fill_dir_old(struct fuse_dirhandle *dh, const char *name, int type,
- ino_t ino)
-{
- int res;
- struct stat stbuf;
-
- memset(&stbuf, 0, sizeof(stbuf));
- stbuf.st_mode = type << 12;
- stbuf.st_ino = ino;
-
- res = dh->filler(dh->buf, name, &stbuf, 0);
- return res ? -ENOMEM : 0;
-}
-
int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
fuse_fill_dir_t filler, off_t off,
struct fuse_file_info *fi)
@@ -2007,16 +1862,6 @@ int fuse_fs_readdir(struct fuse_fs *fs, const char *path, void *buf,
(unsigned long long) off);
return fs->op.readdir(path, buf, filler, off, fi);
- } else if (fs->op.getdir) {
- struct fuse_dirhandle dh;
-
- if (fs->debug)
- fprintf(stderr, "getdir[%llu]\n",
- (unsigned long long) fi->fh);
-
- dh.filler = filler;
- dh.buf = buf;
- return fs->op.getdir(path, &dh, fill_dir_old);
} else {
return -ENOSYS;
}
@@ -2154,16 +1999,6 @@ int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
tv[1].tv_sec, tv[1].tv_nsec);
return fs->op.utimens(path, tv);
- } else if(fs->op.utime) {
- struct utimbuf buf;
-
- if (fs->debug)
- fprintf(stderr, "utime %s %li %li\n", path,
- tv[0].tv_sec, tv[1].tv_sec);
-
- buf.actime = tv[0].tv_sec;
- buf.modtime = tv[1].tv_sec;
- return fs->op.utime(path, &buf);
} else {
return -ENOSYS;
}
@@ -2324,8 +2159,9 @@ int fuse_fs_poll(struct fuse_fs *fs, const char *path,
int res;
if (fs->debug)
- fprintf(stderr, "poll[%llu] ph: %p\n",
- (unsigned long long) fi->fh, ph);
+ fprintf(stderr, "poll[%llu] ph: %p, events 0x%x\n",
+ (unsigned long long) fi->fh, ph,
+ fi->poll_events);
res = fs->op.poll(path, fi, ph, reventsp);
@@ -2487,8 +2323,8 @@ static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
}
set_stat(f, e->ino, &e->attr);
if (f->conf.debug)
- fprintf(stderr, " NODEID: %lu\n",
- (unsigned long) e->ino);
+ fprintf(stderr, " NODEID: %llu\n",
+ (unsigned long long) e->ino);
}
}
return res;
@@ -2496,9 +2332,12 @@ static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
static struct fuse_context_i *fuse_get_context_internal(void)
{
- struct fuse_context_i *c;
+ return (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
+}
- c = (struct fuse_context_i *) pthread_getspecific(fuse_context_key);
+static struct fuse_context_i *fuse_create_context(struct fuse *f)
+{
+ struct fuse_context_i *c = fuse_get_context_internal();
if (c == NULL) {
c = (struct fuse_context_i *)
calloc(1, sizeof(struct fuse_context_i));
@@ -2511,7 +2350,11 @@ static struct fuse_context_i *fuse_get_context_internal(void)
abort();
}
pthread_setspecific(fuse_context_key, c);
+ } else {
+ memset(c, 0, sizeof(*c));
}
+ c->ctx.fuse = f;
+
return c;
}
@@ -2551,10 +2394,9 @@ static void fuse_delete_context_key(void)
static struct fuse *req_fuse_prepare(fuse_req_t req)
{
- struct fuse_context_i *c = fuse_get_context_internal();
+ struct fuse_context_i *c = fuse_create_context(req_fuse(req));
const struct fuse_ctx *ctx = fuse_req_ctx(req);
c->req = req;
- c->ctx.fuse = req_fuse(req);
c->ctx.uid = ctx->uid;
c->ctx.gid = ctx->gid;
c->ctx.pid = ctx->pid;
@@ -2598,10 +2440,8 @@ void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn)
static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
{
struct fuse *f = (struct fuse *) data;
- struct fuse_context_i *c = fuse_get_context_internal();
- memset(c, 0, sizeof(*c));
- c->ctx.fuse = f;
+ fuse_create_context(f);
conn->want |= FUSE_CAP_EXPORT_SUPPORT;
fuse_fs_init(f->fs, conn);
}
@@ -2619,10 +2459,8 @@ void fuse_fs_destroy(struct fuse_fs *fs)
static void fuse_lib_destroy(void *data)
{
struct fuse *f = (struct fuse *) data;
- struct fuse_context_i *c = fuse_get_context_internal();
- memset(c, 0, sizeof(*c));
- c->ctx.fuse = f;
+ fuse_create_context(f);
fuse_fs_destroy(f->fs);
f->fs = NULL;
}
@@ -2692,8 +2530,7 @@ static void do_forget(struct fuse *f, fuse_ino_t ino, uint64_t nlookup)
forget_node(f, ino, nlookup);
}
-static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino,
- unsigned long nlookup)
+static void fuse_lib_forget(fuse_req_t req, fuse_ino_t ino, uint64_t nlookup)
{
do_forget(req_fuse(req), ino, nlookup);
fuse_reply_none(req);
@@ -2796,7 +2633,7 @@ static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
attr->st_size);
}
#ifdef HAVE_UTIMENSAT
- if (!err && f->utime_omit_ok &&
+ if (!err &&
(valid & (FUSE_SET_ATTR_ATIME | FUSE_SET_ATTR_MTIME))) {
struct timespec tv[2];
@@ -3079,14 +2916,8 @@ static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,
{
struct node *node;
int unlink_hidden = 0;
- const char *compatpath;
- if (path != NULL || f->nullpath_ok || f->conf.nopath)
- compatpath = path;
- else
- compatpath = "-";
-
- fuse_fs_release(f->fs, compatpath, fi);
+ fuse_fs_release(f->fs, path, fi);
pthread_mutex_lock(&f->lock);
node = get_node(f, ino);
@@ -3312,7 +3143,6 @@ static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,
struct fuse_dh *dh = (struct fuse_dh *) (uintptr_t) llfi->fh;
memset(fi, 0, sizeof(struct fuse_file_info));
fi->fh = dh->fh;
- fi->fh_old = dh->fh;
return dh;
}
@@ -3517,16 +3347,11 @@ static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info fi;
struct fuse_dh *dh = get_dirhandle(llfi, &fi);
char *path;
- const char *compatpath;
get_path_nullok(f, ino, &path);
- if (path != NULL || f->nullpath_ok || f->conf.nopath)
- compatpath = path;
- else
- compatpath = "-";
fuse_prepare_interrupt(f, req, &d);
- fuse_fs_releasedir(f->fs, compatpath, &fi);
+ fuse_fs_releasedir(f->fs, path, &fi);
fuse_finish_interrupt(f, req, &d);
free_path(f, ino, path);
@@ -4184,90 +4009,29 @@ int fuse_notify_poll(struct fuse_pollhandle *ph)
return fuse_lowlevel_notify_poll(ph);
}
-static void free_cmd(struct fuse_cmd *cmd)
-{
- free(cmd->buf);
- free(cmd);
-}
-
-void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd)
-{
- fuse_session_process(f->se, cmd->buf, cmd->buflen, cmd->ch);
- free_cmd(cmd);
-}
-
-int fuse_exited(struct fuse *f)
-{
- return fuse_session_exited(f->se);
-}
-
struct fuse_session *fuse_get_session(struct fuse *f)
{
return f->se;
}
-static struct fuse_cmd *fuse_alloc_cmd(size_t bufsize)
-{
- struct fuse_cmd *cmd = (struct fuse_cmd *) malloc(sizeof(*cmd));
- if (cmd == NULL) {
- fprintf(stderr, "fuse: failed to allocate cmd\n");
- return NULL;
- }
- cmd->buf = (char *) malloc(bufsize);
- if (cmd->buf == NULL) {
- fprintf(stderr, "fuse: failed to allocate read buffer\n");
- free(cmd);
- return NULL;
- }
- return cmd;
-}
-
-struct fuse_cmd *fuse_read_cmd(struct fuse *f)
-{
- struct fuse_chan *ch = fuse_session_next_chan(f->se, NULL);
- size_t bufsize = fuse_chan_bufsize(ch);
- struct fuse_cmd *cmd = fuse_alloc_cmd(bufsize);
- if (cmd != NULL) {
- int res = fuse_chan_recv(&ch, cmd->buf, bufsize);
- if (res <= 0) {
- free_cmd(cmd);
- if (res < 0 && res != -EINTR && res != -EAGAIN)
- fuse_exit(f);
- return NULL;
- }
- cmd->buflen = res;
- cmd->ch = ch;
- }
- return cmd;
-}
-
static int fuse_session_loop_remember(struct fuse *f)
{
struct fuse_session *se = f->se;
int res = 0;
struct timespec now;
time_t next_clean;
- struct fuse_chan *ch = fuse_session_next_chan(se, NULL);
- size_t bufsize = fuse_chan_bufsize(ch);
- char *buf = (char *) malloc(bufsize);
+ struct fuse_chan *ch = fuse_session_chan(se);
struct pollfd fds = {
.fd = fuse_chan_fd(ch),
.events = POLLIN
};
-
- if (!buf) {
- fprintf(stderr, "fuse: failed to allocate read buffer\n");
- return -1;
- }
+ struct fuse_buf fbuf = {
+ .mem = NULL,
+ };
curr_time(&now);
next_clean = now.tv_sec;
while (!fuse_session_exited(se)) {
- struct fuse_chan *tmpch = ch;
- struct fuse_buf fbuf = {
- .mem = buf,
- .size = bufsize,
- };
unsigned timeout;
curr_time(&now);
@@ -4283,14 +4047,14 @@ static int fuse_session_loop_remember(struct fuse *f)
else
break;
} else if (res > 0) {
- res = fuse_session_receive_buf(se, &fbuf, &tmpch);
+ res = fuse_session_receive_buf(se, &fbuf, ch);
if (res == -EINTR)
continue;
if (res <= 0)
break;
- fuse_session_process_buf(se, &fbuf, tmpch);
+ fuse_session_process_buf(se, &fbuf, ch);
} else {
timeout = fuse_clean_cache(f);
curr_time(&now);
@@ -4298,7 +4062,7 @@ static int fuse_session_loop_remember(struct fuse *f)
}
}
- free(buf);
+ free(fbuf.mem);
fuse_session_reset(se);
return res < 0 ? -1 : 0;
}
@@ -4314,13 +4078,6 @@ int fuse_loop(struct fuse *f)
return fuse_session_loop(f->se);
}
-int fuse_invalidate(struct fuse *f, const char *path)
-{
- (void) f;
- (void) path;
- return -EINVAL;
-}
-
void fuse_exit(struct fuse *f)
{
fuse_session_exit(f->se);
@@ -4328,36 +4085,31 @@ void fuse_exit(struct fuse *f)
struct fuse_context *fuse_get_context(void)
{
- return &fuse_get_context_internal()->ctx;
-}
+ struct fuse_context_i *c = fuse_get_context_internal();
-/*
- * The size of fuse_context got extended, so need to be careful about
- * incompatibility (i.e. a new binary cannot work with an old
- * library).
- */
-struct fuse_context *fuse_get_context_compat22(void);
-struct fuse_context *fuse_get_context_compat22(void)
-{
- return &fuse_get_context_internal()->ctx;
+ if (c)
+ return &c->ctx;
+ else
+ return NULL;
}
-FUSE_SYMVER(".symver fuse_get_context_compat22,fuse_get_context@FUSE_2.2");
int fuse_getgroups(int size, gid_t list[])
{
- fuse_req_t req = fuse_get_context_internal()->req;
- return fuse_req_getgroups(req, size, list);
+ struct fuse_context_i *c = fuse_get_context_internal();
+ if (!c)
+ return -EINVAL;
+
+ return fuse_req_getgroups(c->req, size, list);
}
int fuse_interrupted(void)
{
- return fuse_req_interrupted(fuse_get_context_internal()->req);
-}
+ struct fuse_context_i *c = fuse_get_context_internal();
-void fuse_set_getcontext_func(struct fuse_context *(*func)(void))
-{
- (void) func;
- /* no-op */
+ if (c)
+ return fuse_req_interrupted(c->req);
+ else
+ return 0;
}
enum {
@@ -4402,7 +4154,7 @@ static const struct fuse_opt fuse_lib_opts[] = {
static void fuse_lib_help(void)
{
- fprintf(stderr,
+ printf(
" -o hard_remove immediate removal (don't hide files)\n"
" -o use_ino let filesystem set inode numbers\n"
" -o readdir_ino try to fill in d_ino in readdir\n"
@@ -4428,7 +4180,7 @@ static void fuse_lib_help(void)
static void fuse_lib_help_modules(void)
{
struct fuse_module *m;
- fprintf(stderr, "\nModule options:\n");
+ printf("\nModule options:\n");
pthread_mutex_lock(&fuse_context_lock);
for (m = fuse_modules; m; m = m->next) {
struct fuse_fs *fs = NULL;
@@ -4436,7 +4188,7 @@ static void fuse_lib_help_modules(void)
struct fuse_args args = FUSE_ARGS_INIT(0, NULL);
if (fuse_opt_add_arg(&args, "") != -1 &&
fuse_opt_add_arg(&args, "-h") != -1) {
- fprintf(stderr, "\n[%s]\n", m->name);
+ printf("\n[%s]\n", m->name);
newfs = m->factory(&args, &fs);
assert(newfs == NULL);
}
@@ -4459,12 +4211,6 @@ static int fuse_lib_opt_proc(void *data, const char *arg, int key,
return 1;
}
-int fuse_is_lib_option(const char *opt)
-{
- return fuse_lowlevel_is_lib_option(opt) ||
- fuse_opt_match(fuse_lib_opts, opt);
-}
-
static int fuse_init_intr_signal(int signum, int *installed)
{
struct sigaction old_sa;
@@ -4517,9 +4263,7 @@ static int fuse_push_module(struct fuse *f, const char *module,
}
newfs->m = m;
f->fs = newfs;
- f->nullpath_ok = newfs->op.flag_nullpath_ok && f->nullpath_ok;
f->conf.nopath = newfs->op.flag_nopath && f->conf.nopath;
- f->utime_omit_ok = newfs->op.flag_utime_omit_ok && f->utime_omit_ok;
return 0;
}
@@ -4589,9 +4333,9 @@ void fuse_stop_cleanup_thread(struct fuse *f)
}
}
-struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
- const struct fuse_operations *op,
- size_t op_size, void *user_data, int compat)
+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 *f;
struct node *root;
@@ -4611,11 +4355,8 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
if (!fs)
goto out_free;
- fs->compat = compat;
f->fs = fs;
- f->nullpath_ok = fs->op.flag_nullpath_ok;
f->conf.nopath = fs->op.flag_nopath;
- f->utime_omit_ok = fs->op.flag_utime_omit_ok;
/* Oh f**k, this is ugly! */
if (!fs->op.lock) {
@@ -4663,12 +4404,7 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
f->conf.readdir_ino = 1;
#endif
- if (compat && compat <= 25) {
- if (fuse_sync_compat_args(args) == -1)
- goto out_free_fs;
- }
-
- f->se = fuse_lowlevel_new_common(args, &llop, sizeof(llop), f);
+ f->se = fuse_lowlevel_new(args, &llop, sizeof(llop), f);
if (f->se == NULL) {
if (f->conf.help)
fuse_lib_help_modules();
@@ -4678,9 +4414,7 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
fuse_session_add_chan(f->se, ch);
if (f->conf.debug) {
- fprintf(stderr, "nullpath_ok: %i\n", f->nullpath_ok);
fprintf(stderr, "nopath: %i\n", f->conf.nopath);
- fprintf(stderr, "utime_omit_ok: %i\n", f->utime_omit_ok);
}
/* Trace topmost layer by default */
@@ -4729,10 +4463,9 @@ out_free_name_table:
out_free_session:
fuse_session_destroy(f->se);
out_free_fs:
- /* Horrible compatibility hack to stop the destructor from being
- called on the filesystem without init being called first */
- fs->op.destroy = NULL;
- fuse_fs_destroy(f->fs);
+ if (f->fs->m)
+ fuse_put_module(f->fs->m);
+ free(f->fs);
free(f->conf.modules);
out_free:
free(f);
@@ -4742,13 +4475,6 @@ out:
return NULL;
}
-struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
- const struct fuse_operations *op, size_t op_size,
- void *user_data)
-{
- return fuse_new_common(ch, args, op, op_size, user_data, 0);
-}
-
void fuse_destroy(struct fuse *f)
{
size_t i;
@@ -4757,10 +4483,7 @@ void fuse_destroy(struct fuse *f)
fuse_restore_intr_signal(f->conf.intr_signal);
if (f->fs) {
- struct fuse_context_i *c = fuse_get_context_internal();
-
- memset(c, 0, sizeof(*c));
- c->ctx.fuse = f;
+ fuse_create_context(f);
for (i = 0; i < f->id_table.size; i++) {
struct node *node;
@@ -4799,19 +4522,6 @@ void fuse_destroy(struct fuse *f)
fuse_delete_context_key();
}
-static struct fuse *fuse_new_common_compat25(int fd, struct fuse_args *args,
- const struct fuse_operations *op,
- size_t op_size, int compat)
-{
- struct fuse *f = NULL;
- struct fuse_chan *ch = fuse_kern_chan_new(fd);
-
- if (ch)
- f = fuse_new_common(ch, args, op, op_size, NULL, compat);
-
- return f;
-}
-
/* called with fuse_context_lock held or during initialization (before
main() has been called) */
void fuse_register_module(struct fuse_module *mod)
@@ -4823,72 +4533,3 @@ void fuse_register_module(struct fuse_module *mod)
mod->next = fuse_modules;
fuse_modules = mod;
}
-
-#if !defined(__FreeBSD__) && !defined(__NetBSD__)
-
-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 (fuse_opt_add_arg(&args, "") == -1)
- return NULL;
- if (opts &&
- (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_compat25(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_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_compat(fd, opts, (struct fuse_operations *) op,
- sizeof(struct fuse_operations_compat2),
- 21);
-}
-
-struct fuse *fuse_new_compat1(int fd, int flags,
- const struct fuse_operations_compat1 *op)
-{
- const char *opts = NULL;
- if (flags & FUSE_DEBUG_COMPAT1)
- opts = "debug";
- return fuse_new_common_compat(fd, opts, (struct fuse_operations *) op,
- sizeof(struct fuse_operations_compat1),
- 11);
-}
-
-FUSE_SYMVER(".symver fuse_exited,__fuse_exited@");
-FUSE_SYMVER(".symver fuse_process_cmd,__fuse_process_cmd@");
-FUSE_SYMVER(".symver fuse_read_cmd,__fuse_read_cmd@");
-FUSE_SYMVER(".symver fuse_set_getcontext_func,__fuse_set_getcontext_func@");
-FUSE_SYMVER(".symver fuse_new_compat2,fuse_new@");
-FUSE_SYMVER(".symver fuse_new_compat22,fuse_new@FUSE_2.2");
-
-#endif /* __FreeBSD__ || __NetBSD__ */
-
-struct fuse *fuse_new_compat25(int fd, struct fuse_args *args,
- const struct fuse_operations_compat25 *op,
- size_t op_size)
-{
- return fuse_new_common_compat25(fd, args, (struct fuse_operations *) op,
- op_size, 25);
-}
-
-FUSE_SYMVER(".symver fuse_new_compat25,fuse_new@FUSE_2.5");
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index fa37156..5823743 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -13,21 +13,20 @@ struct fuse_chan;
struct fuse_ll;
struct fuse_session {
- struct fuse_session_ops op;
-
- int (*receive_buf)(struct fuse_session *se, struct fuse_buf *buf,
- struct fuse_chan **chp);
-
- void (*process_buf)(void *data, const struct fuse_buf *buf,
- struct fuse_chan *ch);
-
- void *data;
+ struct fuse_ll *f;
volatile int exited;
struct fuse_chan *ch;
};
+struct fuse_chan {
+ struct fuse_session *se;
+
+ int fd;
+};
+
+
struct fuse_req {
struct fuse_ll *f;
uint64_t unique;
@@ -71,6 +70,10 @@ struct fuse_ll {
int no_splice_write;
int no_splice_move;
int no_splice_read;
+ int auto_inval_data;
+ int no_auto_inval_data;
+ int no_readdirplus;
+ int no_readdirplus_auto;
struct fuse_lowlevel_ops op;
int got_init;
struct cuse_data *cuse_data;
@@ -85,28 +88,35 @@ struct fuse_ll {
int broken_splice_nonblock;
uint64_t notify_ctr;
struct fuse_notify_req notify_list;
+ size_t bufsize;
};
-struct fuse_cmd {
- char *buf;
- size_t buflen;
- struct fuse_chan *ch;
-};
-
-struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
- const struct fuse_operations *op,
- size_t op_size, void *user_data, int compat);
-
-int fuse_sync_compat_args(struct fuse_args *args);
-
-struct fuse_chan *fuse_kern_chan_new(int fd);
-
-struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args,
- const struct fuse_lowlevel_ops *op,
- size_t op_size, void *userdata);
-
-void fuse_kern_unmount_compat22(const char *mountpoint);
int fuse_chan_clearfd(struct fuse_chan *ch);
+void fuse_chan_close(struct fuse_chan *ch);
+
+/**
+ * Create a new session
+ *
+ * @return new session object, or NULL on failure
+ */
+struct fuse_session *fuse_session_new(void);
+
+/**
+ * Create a new channel
+ *
+ * @param op channel operations
+ * @param fd file descriptor of the channel
+ * @return the new channel object, or NULL on failure
+ */
+struct fuse_chan *fuse_chan_new(int fd);
+
+/**
+ * Query the session to which this channel is assigned
+ *
+ * @param ch the channel
+ * @return the session, or NULL if the channel is not assigned
+ */
+struct fuse_session *fuse_chan_session(struct fuse_chan *ch);
void fuse_kern_unmount(const char *mountpoint, int fd);
int fuse_kern_mount(const char *mountpoint, struct fuse_args *args);
@@ -115,16 +125,6 @@ int fuse_send_reply_iov_nofree(fuse_req_t req, int error, struct iovec *iov,
int count);
void fuse_free_req(fuse_req_t req);
-
-struct fuse *fuse_setup_common(int argc, char *argv[],
- const struct fuse_operations *op,
- size_t op_size,
- char **mountpoint,
- int *multithreaded,
- int *fd,
- void *user_data,
- int compat);
-
void cuse_lowlevel_init(fuse_req_t req, fuse_ino_t nodeide, const void *inarg);
int fuse_start_thread(pthread_t *thread_id, void *(*func)(void *), void *arg);
diff --git a/lib/fuse_kern_chan.c b/lib/fuse_kern_chan.c
deleted file mode 100644
index 4a9beb8..0000000
--- a/lib/fuse_kern_chan.c
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
- FUSE: Filesystem in Userspace
- Copyright (C) 2001-2007 Miklos Szeredi <miklos@szeredi.hu>
-
- This program can be distributed under the terms of the GNU LGPLv2.
- See the file COPYING.LIB
-*/
-
-#include "fuse_lowlevel.h"
-#include "fuse_kernel.h"
-#include "fuse_i.h"
-
-#include <stdio.h>
-#include <errno.h>
-#include <unistd.h>
-#include <assert.h>
-
-static int fuse_kern_chan_receive(struct fuse_chan **chp, char *buf,
- size_t size)
-{
- struct fuse_chan *ch = *chp;
- int err;
- ssize_t res;
- struct fuse_session *se = fuse_chan_session(ch);
- assert(se != NULL);
-
-restart:
- res = read(fuse_chan_fd(ch), buf, size);
- err = errno;
-
- if (fuse_session_exited(se))
- return 0;
- if (res == -1) {
- /* ENOENT means the operation was interrupted, it's safe
- to restart */
- if (err == ENOENT)
- goto restart;
-
- if (err == ENODEV) {
- fuse_session_exit(se);
- return 0;
- }
- /* Errors occurring during normal operation: EINTR (read
- interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem
- umounted) */
- if (err != EINTR && err != EAGAIN)
- perror("fuse: reading device");
- return -err;
- }
- if ((size_t) res < sizeof(struct fuse_in_header)) {
- fprintf(stderr, "short read on fuse device\n");
- return -EIO;
- }
- return res;
-}
-
-static int fuse_kern_chan_send(struct fuse_chan *ch, const struct iovec iov[],
- size_t count)
-{
- if (iov) {
- ssize_t res = writev(fuse_chan_fd(ch), iov, count);
- int err = errno;
-
- if (res == -1) {
- struct fuse_session *se = fuse_chan_session(ch);
-
- assert(se != NULL);
-
- /* ENOENT means the operation was interrupted */
- if (!fuse_session_exited(se) && err != ENOENT)
- perror("fuse: writing device");
- return -err;
- }
- }
- return 0;
-}
-
-static void fuse_kern_chan_destroy(struct fuse_chan *ch)
-{
- int fd = fuse_chan_fd(ch);
-
- if (fd != -1)
- close(fd);
-}
-
-#define MIN_BUFSIZE 0x21000
-
-struct fuse_chan *fuse_kern_chan_new(int fd)
-{
- struct fuse_chan_ops op = {
- .receive = fuse_kern_chan_receive,
- .send = fuse_kern_chan_send,
- .destroy = fuse_kern_chan_destroy,
- };
- size_t bufsize = getpagesize() + 0x1000;
- bufsize = bufsize < MIN_BUFSIZE ? MIN_BUFSIZE : bufsize;
- return fuse_chan_new(&op, fd, bufsize, NULL);
-}
diff --git a/lib/fuse_loop.c b/lib/fuse_loop.c
index b7b4ca4..fb6d8a6 100644
--- a/lib/fuse_loop.c
+++ b/lib/fuse_loop.c
@@ -6,6 +6,7 @@
See the file COPYING.LIB
*/
+#include "config.h"
#include "fuse_lowlevel.h"
#include <stdio.h>
@@ -15,32 +16,23 @@
int fuse_session_loop(struct fuse_session *se)
{
int res = 0;
- struct fuse_chan *ch = fuse_session_next_chan(se, NULL);
- size_t bufsize = fuse_chan_bufsize(ch);
- char *buf = (char *) malloc(bufsize);
- if (!buf) {
- fprintf(stderr, "fuse: failed to allocate read buffer\n");
- return -1;
- }
+ struct fuse_chan *ch = fuse_session_chan(se);
+ struct fuse_buf fbuf = {
+ .mem = NULL,
+ };
while (!fuse_session_exited(se)) {
- struct fuse_chan *tmpch = ch;
- struct fuse_buf fbuf = {
- .mem = buf,
- .size = bufsize,
- };
-
- res = fuse_session_receive_buf(se, &fbuf, &tmpch);
+ res = fuse_session_receive_buf(se, &fbuf, ch);
if (res == -EINTR)
continue;
if (res <= 0)
break;
- fuse_session_process_buf(se, &fbuf, tmpch);
+ fuse_session_process_buf(se, &fbuf, ch);
}
- free(buf);
+ free(fbuf.mem);
fuse_session_reset(se);
return res < 0 ? -1 : 0;
}
diff --git a/lib/fuse_loop_mt.c b/lib/fuse_loop_mt.c
index 82e3001..8f4dceb 100644..100755
--- a/lib/fuse_loop_mt.c
+++ b/lib/fuse_loop_mt.c
@@ -6,6 +6,7 @@
See the file COPYING.LIB.
*/
+#include "config.h"
#include "fuse_lowlevel.h"
#include "fuse_misc.h"
#include "fuse_kernel.h"
@@ -28,7 +29,7 @@ struct fuse_worker {
struct fuse_worker *next;
pthread_t thread_id;
size_t bufsize;
- char *buf;
+ struct fuse_buf fbuf;
struct fuse_mt *mt;
};
@@ -70,15 +71,10 @@ static void *fuse_do_work(void *data)
while (!fuse_session_exited(mt->se)) {
int isforget = 0;
- struct fuse_chan *ch = mt->prevch;
- struct fuse_buf fbuf = {
- .mem = w->buf,
- .size = w->bufsize,
- };
int res;
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
- res = fuse_session_receive_buf(mt->se, &fbuf, &ch);
+ res = fuse_session_receive_buf(mt->se, &w->fbuf, mt->prevch);
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
if (res == -EINTR)
continue;
@@ -100,8 +96,8 @@ static void *fuse_do_work(void *data)
* This disgusting hack is needed so that zillions of threads
* are not created on a burst of FORGET messages
*/
- if (!(fbuf.flags & FUSE_BUF_IS_FD)) {
- struct fuse_in_header *in = fbuf.mem;
+ if (!(w->fbuf.flags & FUSE_BUF_IS_FD)) {
+ struct fuse_in_header *in = w->fbuf.mem;
if (in->opcode == FUSE_FORGET ||
in->opcode == FUSE_BATCH_FORGET)
@@ -114,7 +110,7 @@ static void *fuse_do_work(void *data)
fuse_loop_start_thread(mt);
pthread_mutex_unlock(&mt->lock);
- fuse_session_process_buf(mt->se, &fbuf, ch);
+ fuse_session_process_buf(mt->se, &w->fbuf, mt->prevch);
pthread_mutex_lock(&mt->lock);
if (!isforget)
@@ -130,7 +126,7 @@ static void *fuse_do_work(void *data)
pthread_mutex_unlock(&mt->lock);
pthread_detach(w->thread_id);
- free(w->buf);
+ free(w->fbuf.mem);
free(w);
return NULL;
}
@@ -184,18 +180,11 @@ static int fuse_loop_start_thread(struct fuse_mt *mt)
return -1;
}
memset(w, 0, sizeof(struct fuse_worker));
- w->bufsize = fuse_chan_bufsize(mt->prevch);
- w->buf = malloc(w->bufsize);
+ w->fbuf.mem = NULL;
w->mt = mt;
- if (!w->buf) {
- fprintf(stderr, "fuse: failed to allocate read buffer\n");
- free(w);
- return -1;
- }
res = fuse_start_thread(&w->thread_id, fuse_do_work, w);
if (res == -1) {
- free(w->buf);
free(w);
return -1;
}
@@ -212,7 +201,7 @@ static void fuse_join_worker(struct fuse_mt *mt, struct fuse_worker *w)
pthread_mutex_lock(&mt->lock);
list_del_worker(w);
pthread_mutex_unlock(&mt->lock);
- free(w->buf);
+ free(w->fbuf.mem);
free(w);
}
@@ -224,7 +213,7 @@ int fuse_session_loop_mt(struct fuse_session *se)
memset(&mt, 0, sizeof(struct fuse_mt));
mt.se = se;
- mt.prevch = fuse_session_next_chan(se, NULL);
+ mt.prevch = fuse_session_chan(se);
mt.error = 0;
mt.numworker = 0;
mt.numavail = 0;
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 8853346..2b8df06 100644..100755
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -13,8 +13,6 @@
#include "fuse_kernel.h"
#include "fuse_opt.h"
#include "fuse_misc.h"
-#include "fuse_common_compat.h"
-#include "fuse_lowlevel_compat.h"
#include <stdio.h>
#include <stdlib.h>
@@ -156,6 +154,82 @@ static struct fuse_req *fuse_ll_alloc_req(struct fuse_ll *f)
return req;
}
+static int fuse_chan_recv(struct fuse_session *se, struct fuse_buf *buf,
+ struct fuse_chan *ch)
+{
+ struct fuse_ll *f = se->f;
+ int err;
+ ssize_t res;
+
+ if (!buf->mem) {
+ buf->mem = malloc(f->bufsize);
+ if (!buf->mem) {
+ fprintf(stderr,
+ "fuse: failed to allocate read buffer\n");
+ return -ENOMEM;
+ }
+ }
+
+restart:
+ res = read(fuse_chan_fd(ch), buf->mem, f->bufsize);
+ err = errno;
+
+ if (fuse_session_exited(se))
+ return 0;
+ if (res == -1) {
+ /* ENOENT means the operation was interrupted, it's safe
+ to restart */
+ if (err == ENOENT)
+ goto restart;
+
+ if (err == ENODEV) {
+ fuse_session_exit(se);
+ return 0;
+ }
+ /* Errors occurring during normal operation: EINTR (read
+ interrupted), EAGAIN (nonblocking I/O), ENODEV (filesystem
+ umounted) */
+ if (err != EINTR && err != EAGAIN)
+ perror("fuse: reading device");
+ return -err;
+ }
+ if ((size_t) res < sizeof(struct fuse_in_header)) {
+ fprintf(stderr, "short read on fuse device\n");
+ return -EIO;
+ }
+
+ buf->size = res;
+
+ return res;
+}
+
+static int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[],
+ size_t count)
+{
+ ssize_t res = writev(fuse_chan_fd(ch), iov, count);
+ int err = errno;
+
+ if (res == -1) {
+ struct fuse_session *se = fuse_chan_session(ch);
+
+ assert(se != NULL);
+
+ /* ENOENT means the operation was interrupted */
+ if (!fuse_session_exited(se) && err != ENOENT)
+ perror("fuse: writing device");
+ return -err;
+ }
+
+ return 0;
+}
+
+void fuse_chan_close(struct fuse_chan *ch)
+{
+ int fd = fuse_chan_fd(ch);
+ if (fd != -1)
+ close(fd);
+}
+
static int fuse_send_msg(struct fuse_ll *f, struct fuse_chan *ch,
struct iovec *iov, int count)
@@ -242,13 +316,13 @@ int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count)
return res;
}
-size_t fuse_dirent_size(size_t namelen)
+static size_t fuse_dirent_size(size_t namelen)
{
return FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET + namelen);
}
-char *fuse_add_dirent(char *buf, const char *name, const struct stat *stbuf,
- off_t off)
+static char *fuse_add_dirent(char *buf, const char *name,
+ const struct stat *stbuf, off_t off)
{
unsigned namelen = strlen(name);
unsigned entlen = FUSE_NAME_OFFSET + namelen;
@@ -304,8 +378,6 @@ int fuse_reply_err(fuse_req_t req, int err)
void fuse_reply_none(fuse_req_t req)
{
- if (req->ch)
- fuse_chan_send(req->ch, NULL, 0);
fuse_free_req(req);
}
@@ -342,6 +414,25 @@ static void fill_entry(struct fuse_entry_out *arg,
convert_stat(&e->attr, &arg->attr);
}
+size_t fuse_add_direntry_plus(fuse_req_t req, char *buf, size_t bufsize,
+ const char *name,
+ const struct fuse_entry_param *e, off_t off)
+{
+ struct fuse_entry_out *argp;
+ size_t entsize;
+
+ (void) req;
+ entsize = FUSE_DIRENT_ALIGN(FUSE_NAME_OFFSET_DIRENTPLUS +
+ fuse_dirent_size(strlen(name)));
+ if (entsize <= bufsize && buf){
+ argp = (struct fuse_entry_out *)buf;
+ memset(argp, 0, sizeof(*argp));
+ fill_entry(argp, e);
+ fuse_add_dirent(buf + sizeof(*argp), name, &(e->attr), off);
+ }
+ return entsize;
+}
+
static void fill_open(struct fuse_open_out *arg,
const struct fuse_file_info *f)
{
@@ -486,6 +577,31 @@ static void fuse_ll_pipe_free(struct fuse_ll_pipe *llp)
}
#ifdef HAVE_SPLICE
+#if !defined(HAVE_PIPE2) || !defined(O_CLOEXEC)
+static int fuse_pipe(int fds[2])
+{
+ int rv = pipe(fds);
+
+ if (rv == -1)
+ return rv;
+
+ if (fcntl(fds[0], F_SETFL, O_NONBLOCK) == -1 ||
+ fcntl(fds[1], F_SETFL, O_NONBLOCK) == -1 ||
+ fcntl(fds[0], F_SETFD, FD_CLOEXEC) == -1 ||
+ fcntl(fds[1], F_SETFD, FD_CLOEXEC) == -1) {
+ close(fds[0]);
+ close(fds[1]);
+ rv = -1;
+ }
+ return rv;
+}
+#else
+static int fuse_pipe(int fds[2])
+{
+ return pipe2(fds, O_CLOEXEC | O_NONBLOCK);
+}
+#endif
+
static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_ll *f)
{
struct fuse_ll_pipe *llp = pthread_getspecific(f->pipe_key);
@@ -496,20 +612,12 @@ static struct fuse_ll_pipe *fuse_ll_get_pipe(struct fuse_ll *f)
if (llp == NULL)
return NULL;
- res = pipe(llp->pipe);
+ res = fuse_pipe(llp->pipe);
if (res == -1) {
free(llp);
return NULL;
}
- if (fcntl(llp->pipe[0], F_SETFL, O_NONBLOCK) == -1 ||
- fcntl(llp->pipe[1], F_SETFL, O_NONBLOCK) == -1) {
- close(llp->pipe[0]);
- close(llp->pipe[1]);
- free(llp);
- return NULL;
- }
-
/*
*the default size is 16 pages on linux
*/
@@ -1036,7 +1144,6 @@ static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
if (arg->getattr_flags & FUSE_GETATTR_FH) {
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
- fi.fh_old = fi.fh;
fip = &fi;
}
}
@@ -1062,7 +1169,6 @@ static void do_setattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
memset(&fi_store, 0, sizeof(fi_store));
fi = &fi_store;
fi->fh = arg->fh;
- fi->fh_old = fi->fh;
}
arg->valid &=
FUSE_SET_ATTR_MODE |
@@ -1225,7 +1331,6 @@ static void do_read(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
- fi.fh_old = fi.fh;
if (req->f->conn.proto_minor >= 9) {
fi.lock_owner = arg->lock_owner;
fi.flags = arg->flags;
@@ -1243,8 +1348,7 @@ static void do_write(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
- fi.fh_old = fi.fh;
- fi.writepage = arg->write_flags & 1;
+ fi.writepage = (arg->write_flags & 1) != 0;
if (req->f->conn.proto_minor < 9) {
param = ((char *) arg) + FUSE_COMPAT_WRITE_IN_SIZE;
@@ -1274,7 +1378,6 @@ static void do_write_buf(fuse_req_t req, fuse_ino_t nodeid, const void *inarg,
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
- fi.fh_old = fi.fh;
fi.writepage = arg->write_flags & 1;
if (req->f->conn.proto_minor < 9) {
@@ -1313,7 +1416,6 @@ static void do_flush(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
- fi.fh_old = fi.fh;
fi.flush = 1;
if (req->f->conn.proto_minor >= 7)
fi.lock_owner = arg->lock_owner;
@@ -1332,7 +1434,6 @@ static void do_release(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
memset(&fi, 0, sizeof(fi));
fi.flags = arg->flags;
fi.fh = arg->fh;
- fi.fh_old = fi.fh;
if (req->f->conn.proto_minor >= 8) {
fi.flush = (arg->release_flags & FUSE_RELEASE_FLUSH) ? 1 : 0;
fi.lock_owner = arg->lock_owner;
@@ -1355,7 +1456,6 @@ static void do_fsync(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
- fi.fh_old = fi.fh;
if (req->f->op.fsync)
req->f->op.fsync(req, nodeid, arg->fsync_flags & 1, &fi);
@@ -1384,7 +1484,6 @@ static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
- fi.fh_old = fi.fh;
if (req->f->op.readdir)
req->f->op.readdir(req, nodeid, arg->size, arg->offset, &fi);
@@ -1392,6 +1491,20 @@ static void do_readdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
fuse_reply_err(req, ENOSYS);
}
+static void do_readdirplus(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
+{
+ struct fuse_read_in *arg = (struct fuse_read_in *) inarg;
+ struct fuse_file_info fi;
+
+ memset(&fi, 0, sizeof(fi));
+ fi.fh = arg->fh;
+
+ if (req->f->op.readdirplus)
+ req->f->op.readdirplus(req, nodeid, arg->size, arg->offset, &fi);
+ else
+ fuse_reply_err(req, ENOSYS);
+}
+
static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
struct fuse_release_in *arg = (struct fuse_release_in *) inarg;
@@ -1400,7 +1513,6 @@ static void do_releasedir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
memset(&fi, 0, sizeof(fi));
fi.flags = arg->flags;
fi.fh = arg->fh;
- fi.fh_old = fi.fh;
if (req->f->op.releasedir)
req->f->op.releasedir(req, nodeid, &fi);
@@ -1415,7 +1527,6 @@ static void do_fsyncdir(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
- fi.fh_old = fi.fh;
if (req->f->op.fsyncdir)
req->f->op.fsyncdir(req, nodeid, arg->fsync_flags & 1, &fi);
@@ -1670,7 +1781,6 @@ static void do_ioctl(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
- fi.fh_old = fi.fh;
if (sizeof(void *) == 4 && req->f->conn.proto_minor >= 16 &&
!(flags & FUSE_IOCTL_32BIT)) {
@@ -1697,7 +1807,7 @@ static void do_poll(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
memset(&fi, 0, sizeof(fi));
fi.fh = arg->fh;
- fi.fh_old = fi.fh;
+ fi.poll_events = arg->events;
if (req->f->op.poll) {
struct fuse_pollhandle *ph = NULL;
@@ -1738,7 +1848,7 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
struct fuse_init_out outarg;
struct fuse_ll *f = req->f;
- size_t bufsize = fuse_chan_bufsize(req->ch);
+ size_t bufsize = f->bufsize;
(void) nodeid;
if (f->debug) {
@@ -1790,6 +1900,12 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
f->conn.capable |= FUSE_CAP_DONT_MASK;
if (arg->flags & FUSE_FLOCK_LOCKS)
f->conn.capable |= FUSE_CAP_FLOCK_LOCKS;
+ if (arg->flags & FUSE_AUTO_INVAL_DATA)
+ f->conn.capable |= FUSE_CAP_AUTO_INVAL_DATA;
+ if (arg->flags & FUSE_DO_READDIRPLUS)
+ f->conn.capable |= FUSE_CAP_READDIRPLUS;
+ if (arg->flags & FUSE_READDIRPLUS_AUTO)
+ f->conn.capable |= FUSE_CAP_READDIRPLUS_AUTO;
} else {
f->conn.async_read = 0;
f->conn.max_readahead = 0;
@@ -1820,6 +1936,13 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
f->conn.want |= FUSE_CAP_FLOCK_LOCKS;
if (f->big_writes)
f->conn.want |= FUSE_CAP_BIG_WRITES;
+ if (f->auto_inval_data)
+ f->conn.want |= FUSE_CAP_AUTO_INVAL_DATA;
+ if (f->op.readdirplus && !f->no_readdirplus) {
+ f->conn.want |= FUSE_CAP_READDIRPLUS;
+ if (!f->no_readdirplus_auto)
+ f->conn.want |= FUSE_CAP_READDIRPLUS_AUTO;
+ }
if (bufsize < FUSE_MIN_READ_BUFFER) {
fprintf(stderr, "fuse: warning: buffer size too small: %zu\n",
@@ -1841,7 +1964,12 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
f->conn.want &= ~FUSE_CAP_SPLICE_WRITE;
if (f->no_splice_move)
f->conn.want &= ~FUSE_CAP_SPLICE_MOVE;
-
+ if (f->no_auto_inval_data)
+ f->conn.want &= ~FUSE_CAP_AUTO_INVAL_DATA;
+ if (f->no_readdirplus)
+ f->conn.want &= ~FUSE_CAP_READDIRPLUS;
+ if (f->no_readdirplus_auto)
+ f->conn.want &= ~FUSE_CAP_READDIRPLUS_AUTO;
if (f->conn.async_read || (f->conn.want & FUSE_CAP_ASYNC_READ))
outarg.flags |= FUSE_ASYNC_READ;
if (f->conn.want & FUSE_CAP_POSIX_LOCKS)
@@ -1856,6 +1984,12 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
outarg.flags |= FUSE_DONT_MASK;
if (f->conn.want & FUSE_CAP_FLOCK_LOCKS)
outarg.flags |= FUSE_FLOCK_LOCKS;
+ if (f->conn.want & FUSE_CAP_AUTO_INVAL_DATA)
+ outarg.flags |= FUSE_AUTO_INVAL_DATA;
+ if (f->conn.want & FUSE_CAP_READDIRPLUS)
+ outarg.flags |= FUSE_DO_READDIRPLUS;
+ if (f->conn.want & FUSE_CAP_READDIRPLUS_AUTO)
+ outarg.flags |= FUSE_READDIRPLUS_AUTO;
outarg.max_readahead = f->conn.max_readahead;
outarg.max_write = f->conn.max_write;
if (f->conn.proto_minor >= 13) {
@@ -1989,7 +2123,7 @@ int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, fuse_ino_t ino,
if (!ch)
return -EINVAL;
- f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch));
+ f = fuse_chan_session(ch)->f;
if (!f)
return -ENODEV;
@@ -2013,7 +2147,7 @@ int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, fuse_ino_t parent,
if (!ch)
return -EINVAL;
- f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch));
+ f = fuse_chan_session(ch)->f;
if (!f)
return -ENODEV;
@@ -2040,7 +2174,7 @@ int fuse_lowlevel_notify_delete(struct fuse_chan *ch,
if (!ch)
return -EINVAL;
- f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch));
+ f = fuse_chan_session(ch)->f;
if (!f)
return -ENODEV;
@@ -2074,7 +2208,7 @@ int fuse_lowlevel_notify_store(struct fuse_chan *ch, fuse_ino_t ino,
if (!ch)
return -EINVAL;
- f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch));
+ f = fuse_chan_session(ch)->f;
if (!f)
return -ENODEV;
@@ -2156,7 +2290,7 @@ int fuse_lowlevel_notify_retrieve(struct fuse_chan *ch, fuse_ino_t ino,
if (!ch)
return -EINVAL;
- f = (struct fuse_ll *)fuse_session_data(fuse_chan_session(ch));
+ f = fuse_chan_session(ch)->f;
if (!f)
return -ENODEV;
@@ -2203,21 +2337,6 @@ const struct fuse_ctx *fuse_req_ctx(fuse_req_t req)
return &req->ctx;
}
-/*
- * The size of fuse_ctx got extended, so need to be careful about
- * incompatibility (i.e. a new binary cannot work with an old
- * library).
- */
-const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req);
-const struct fuse_ctx *fuse_req_ctx_compat24(fuse_req_t req)
-{
- return fuse_req_ctx(req);
-}
-#ifndef __NetBSD__
-FUSE_SYMVER(".symver fuse_req_ctx_compat24,fuse_req_ctx@FUSE_2.4");
-#endif
-
-
void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func,
void *data)
{
@@ -2287,6 +2406,7 @@ static struct {
[FUSE_DESTROY] = { do_destroy, "DESTROY" },
[FUSE_NOTIFY_REPLY] = { (void *) 1, "NOTIFY_REPLY" },
[FUSE_BATCH_FORGET] = { do_batch_forget, "BATCH_FORGET" },
+ [FUSE_READDIRPLUS] = { do_readdirplus, "READDIRPLUS"},
[CUSE_INIT] = { cuse_lowlevel_init, "CUSE_INIT" },
};
@@ -2315,10 +2435,10 @@ static int fuse_ll_copy_from_pipe(struct fuse_bufvec *dst,
return 0;
}
-static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf,
- struct fuse_chan *ch)
+void fuse_session_process_buf(struct fuse_session *se,
+ const struct fuse_buf *buf, struct fuse_chan *ch)
{
- struct fuse_ll *f = (struct fuse_ll *) data;
+ struct fuse_ll *f = se->f;
const size_t write_header_size = sizeof(struct fuse_in_header) +
sizeof(struct fuse_write_in);
struct fuse_bufvec bufv = { .buf[0] = *buf, .count = 1 };
@@ -2352,10 +2472,10 @@ static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf,
if (f->debug) {
fprintf(stderr,
- "unique: %llu, opcode: %s (%i), nodeid: %lu, insize: %zu, pid: %u\n",
+ "unique: %llu, opcode: %s (%i), nodeid: %llu, insize: %zu, pid: %u\n",
(unsigned long long) in->unique,
opname((enum fuse_opcode) in->opcode), in->opcode,
- (unsigned long) in->nodeid, buf->size, in->pid);
+ (unsigned long long) in->nodeid, buf->size, in->pid);
}
req = fuse_ll_alloc_req(f);
@@ -2395,7 +2515,8 @@ static void fuse_ll_process_buf(void *data, const struct fuse_buf *buf,
in->opcode != FUSE_WRITE && in->opcode != FUSE_FSYNC &&
in->opcode != FUSE_RELEASE && in->opcode != FUSE_READDIR &&
in->opcode != FUSE_FSYNCDIR && in->opcode != FUSE_RELEASEDIR &&
- in->opcode != FUSE_NOTIFY_REPLY)
+ in->opcode != FUSE_NOTIFY_REPLY &&
+ in->opcode != FUSE_READDIRPLUS)
goto reply_err;
err = ENOSYS;
@@ -2453,17 +2574,6 @@ clear_pipe:
goto out_free;
}
-static void fuse_ll_process(void *data, const char *buf, size_t len,
- struct fuse_chan *ch)
-{
- struct fuse_buf fbuf = {
- .mem = (void *) buf,
- .size = len,
- };
-
- fuse_ll_process_buf(data, &fbuf, ch);
-}
-
enum {
KEY_HELP,
KEY_VERSION,
@@ -2492,6 +2602,13 @@ static const struct fuse_opt fuse_ll_opts[] = {
{ "no_splice_move", offsetof(struct fuse_ll, no_splice_move), 1},
{ "splice_read", offsetof(struct fuse_ll, splice_read), 1},
{ "no_splice_read", offsetof(struct fuse_ll, no_splice_read), 1},
+ { "auto_inval_data", offsetof(struct fuse_ll, auto_inval_data), 1},
+ { "no_auto_inval_data", offsetof(struct fuse_ll, no_auto_inval_data), 1},
+ { "readdirplus=no", offsetof(struct fuse_ll, no_readdirplus), 1},
+ { "readdirplus=yes", offsetof(struct fuse_ll, no_readdirplus), 0},
+ { "readdirplus=yes", offsetof(struct fuse_ll, no_readdirplus_auto), 1},
+ { "readdirplus=auto", offsetof(struct fuse_ll, no_readdirplus), 0},
+ { "readdirplus=auto", offsetof(struct fuse_ll, no_readdirplus_auto), 0},
FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD),
FUSE_OPT_KEY("-h", KEY_HELP),
FUSE_OPT_KEY("--help", KEY_HELP),
@@ -2502,13 +2619,13 @@ static const struct fuse_opt fuse_ll_opts[] = {
static void fuse_ll_version(void)
{
- fprintf(stderr, "using FUSE kernel interface version %i.%i\n",
- FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
+ printf("using FUSE kernel interface version %i.%i\n",
+ FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
}
static void fuse_ll_help(void)
{
- fprintf(stderr,
+ printf(
" -o max_write=N set maximum size of write requests\n"
" -o max_readahead=N set maximum readahead\n"
" -o max_background=N set number of maximum background requests\n"
@@ -2523,6 +2640,8 @@ static void fuse_ll_help(void)
" -o [no_]splice_write use splice to write to the fuse device\n"
" -o [no_]splice_move move data while splicing to the fuse device\n"
" -o [no_]splice_read use splice to read from the fuse device\n"
+" -o [no_]auto_inval_data use automatic kernel cache invalidation logic\n"
+" -o readdirplus=S control readdirplus use (yes|no|auto)\n"
);
}
@@ -2547,14 +2666,8 @@ static int fuse_ll_opt_proc(void *data, const char *arg, int key,
return -1;
}
-int fuse_lowlevel_is_lib_option(const char *opt)
-{
- return fuse_opt_match(fuse_ll_opts, opt);
-}
-
-static void fuse_ll_destroy(void *data)
+static void fuse_ll_destroy(struct fuse_ll *f)
{
- struct fuse_ll *f = (struct fuse_ll *) data;
struct fuse_ll_pipe *llp;
if (f->got_init && !f->got_destroy) {
@@ -2570,6 +2683,15 @@ static void fuse_ll_destroy(void *data)
free(f);
}
+void fuse_session_destroy(struct fuse_session *se)
+{
+ fuse_ll_destroy(se->f);
+ if (se->ch != NULL)
+ fuse_chan_destroy(se->ch);
+ free(se);
+}
+
+
static void fuse_ll_pipe_destructor(void *data)
{
struct fuse_ll_pipe *llp = data;
@@ -2577,12 +2699,11 @@ static void fuse_ll_pipe_destructor(void *data)
}
#ifdef HAVE_SPLICE
-static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf,
- struct fuse_chan **chp)
+int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf,
+ struct fuse_chan *ch)
{
- struct fuse_chan *ch = *chp;
- struct fuse_ll *f = fuse_session_data(se);
- size_t bufsize = buf->size;
+ struct fuse_ll *f = se->f;
+ size_t bufsize = buf->size = f->bufsize;
struct fuse_ll_pipe *llp;
struct fuse_buf tmpbuf;
int err;
@@ -2666,47 +2787,25 @@ static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf,
return res;
fallback:
- res = fuse_chan_recv(chp, buf->mem, bufsize);
- if (res <= 0)
- return res;
-
- buf->size = res;
-
- return res;
+ return fuse_chan_recv(se, buf, ch);
}
#else
-static int fuse_ll_receive_buf(struct fuse_session *se, struct fuse_buf *buf,
- struct fuse_chan **chp)
+int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf,
+ struct fuse_chan *ch)
{
- (void) se;
-
- int res = fuse_chan_recv(chp, buf->mem, buf->size);
- if (res <= 0)
- return res;
-
- buf->size = res;
-
- return res;
+ return fuse_chan_recv(se, buf, ch);
}
#endif
+#define MIN_BUFSIZE 0x21000
-/*
- * always call fuse_lowlevel_new_common() internally, to work around a
- * misfeature in the FreeBSD runtime linker, which links the old
- * version of a symbol to internal references.
- */
-struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args,
- const struct fuse_lowlevel_ops *op,
- size_t op_size, void *userdata)
+struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
+ const struct fuse_lowlevel_ops *op,
+ size_t op_size, void *userdata)
{
int err;
struct fuse_ll *f;
struct fuse_session *se;
- struct fuse_session_ops sop = {
- .process = fuse_ll_process,
- .destroy = fuse_ll_destroy,
- };
if (sizeof(struct fuse_lowlevel_ops) < op_size) {
fprintf(stderr, "fuse: warning: library too old, some operations may not work\n");
@@ -2723,6 +2822,9 @@ struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args,
f->conn.max_write = UINT_MAX;
f->conn.max_readahead = UINT_MAX;
f->atomic_o_trunc = 0;
+ f->bufsize = getpagesize() + 0x1000;
+ f->bufsize = f->bufsize < MIN_BUFSIZE ? MIN_BUFSIZE : f->bufsize;
+
list_init_req(&f->list);
list_init_req(&f->interrupts);
list_init_nreq(&f->notify_list);
@@ -2746,12 +2848,11 @@ struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args,
f->owner = getuid();
f->userdata = userdata;
- se = fuse_session_new(&sop, f);
+ se = fuse_session_new();
if (!se)
goto out_key_destroy;
- se->receive_buf = fuse_ll_receive_buf;
- se->process_buf = fuse_ll_process_buf;
+ se->f = f;
return se;
@@ -2764,14 +2865,6 @@ out:
return NULL;
}
-
-struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
- const struct fuse_lowlevel_ops *op,
- size_t op_size, void *userdata)
-{
- return fuse_lowlevel_new_common(args, op, op_size, userdata);
-}
-
#ifdef linux
int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
{
@@ -2840,129 +2933,3 @@ int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[])
return -ENOSYS;
}
#endif
-
-#if !defined(__FreeBSD__) && !defined(__NetBSD__)
-
-static void fill_open_compat(struct fuse_open_out *arg,
- const struct fuse_file_info_compat *f)
-{
- arg->fh = f->fh;
- if (f->direct_io)
- arg->open_flags |= FOPEN_DIRECT_IO;
- if (f->keep_cache)
- arg->open_flags |= FOPEN_KEEP_CACHE;
-}
-
-static void convert_statfs_compat(const struct statfs *compatbuf,
- struct statvfs *buf)
-{
- buf->f_bsize = compatbuf->f_bsize;
- buf->f_blocks = compatbuf->f_blocks;
- buf->f_bfree = compatbuf->f_bfree;
- buf->f_bavail = compatbuf->f_bavail;
- buf->f_files = compatbuf->f_files;
- buf->f_ffree = compatbuf->f_ffree;
- buf->f_namemax = compatbuf->f_namelen;
-}
-
-int fuse_reply_open_compat(fuse_req_t req,
- const struct fuse_file_info_compat *f)
-{
- struct fuse_open_out arg;
-
- memset(&arg, 0, sizeof(arg));
- fill_open_compat(&arg, f);
- return send_reply_ok(req, &arg, sizeof(arg));
-}
-
-int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf)
-{
- struct statvfs newbuf;
-
- memset(&newbuf, 0, sizeof(newbuf));
- convert_statfs_compat(stbuf, &newbuf);
-
- return fuse_reply_statfs(req, &newbuf);
-}
-
-struct fuse_session *fuse_lowlevel_new_compat(const char *opts,
- const struct fuse_lowlevel_ops_compat *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, (const struct fuse_lowlevel_ops *) op,
- op_size, userdata);
- fuse_opt_free_args(&args);
-
- return se;
-}
-
-struct fuse_ll_compat_conf {
- unsigned max_read;
- int set_max_read;
-};
-
-static const struct fuse_opt fuse_ll_opts_compat[] = {
- { "max_read=", offsetof(struct fuse_ll_compat_conf, set_max_read), 1 },
- { "max_read=%u", offsetof(struct fuse_ll_compat_conf, max_read), 0 },
- FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP),
- FUSE_OPT_END
-};
-
-int fuse_sync_compat_args(struct fuse_args *args)
-{
- struct fuse_ll_compat_conf conf;
-
- memset(&conf, 0, sizeof(conf));
- if (fuse_opt_parse(args, &conf, fuse_ll_opts_compat, NULL) == -1)
- return -1;
-
- if (fuse_opt_insert_arg(args, 1, "-osync_read"))
- return -1;
-
- if (conf.set_max_read) {
- char tmpbuf[64];
-
- sprintf(tmpbuf, "-omax_readahead=%u", conf.max_read);
- if (fuse_opt_insert_arg(args, 1, tmpbuf) == -1)
- return -1;
- }
- return 0;
-}
-
-FUSE_SYMVER(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4");
-FUSE_SYMVER(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4");
-FUSE_SYMVER(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4");
-
-#else /* __FreeBSD__ || __NetBSD__ */
-
-int fuse_sync_compat_args(struct fuse_args *args)
-{
- (void) args;
- return 0;
-}
-
-#endif /* __FreeBSD__ || __NetBSD__ */
-
-struct fuse_session *fuse_lowlevel_new_compat25(struct fuse_args *args,
- const struct fuse_lowlevel_ops_compat25 *op,
- size_t op_size, void *userdata)
-{
- if (fuse_sync_compat_args(args) == -1)
- return NULL;
-
- return fuse_lowlevel_new_common(args,
- (const struct fuse_lowlevel_ops *) op,
- op_size, userdata);
-}
-
-FUSE_SYMVER(".symver fuse_lowlevel_new_compat25,fuse_lowlevel_new@FUSE_2.5");
diff --git a/lib/fuse_misc.h b/lib/fuse_misc.h
index eedf0e0..8b76775 100644
--- a/lib/fuse_misc.h
+++ b/lib/fuse_misc.h
@@ -6,20 +6,8 @@
See the file COPYING.LIB
*/
-#include "config.h"
#include <pthread.h>
-/*
- Versioned symbols cannot be used in some cases because it
- - confuse the dynamic linker in uClibc
- - not supported on MacOSX (in MachO binary format)
-*/
-#if (!defined(__UCLIBC__) && !defined(__APPLE__))
-#define FUSE_SYMVER(x) __asm__(x)
-#else
-#define FUSE_SYMVER(x)
-#endif
-
#ifndef USE_UCLIBC
#define fuse_mutex_init(mut) pthread_mutex_init(mut, NULL)
#else
diff --git a/lib/fuse_mt.c b/lib/fuse_mt.c
index f6dbe71..be5d644 100644
--- a/lib/fuse_mt.c
+++ b/lib/fuse_mt.c
@@ -6,105 +6,10 @@
See the file COPYING.LIB.
*/
-#include "fuse_i.h"
-#include "fuse_misc.h"
+#include "config.h"
+#include "fuse.h"
#include "fuse_lowlevel.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <pthread.h>
-#include <assert.h>
-
-struct procdata {
- struct fuse *f;
- struct fuse_chan *prevch;
- struct fuse_session *prevse;
- fuse_processor_t proc;
- void *data;
-};
-
-static void mt_session_proc(void *data, const char *buf, size_t len,
- struct fuse_chan *ch)
-{
- struct procdata *pd = (struct procdata *) data;
- struct fuse_cmd *cmd = *(struct fuse_cmd **) buf;
-
- (void) len;
- (void) ch;
- pd->proc(pd->f, cmd, pd->data);
-}
-
-static void mt_session_exit(void *data, int val)
-{
- struct procdata *pd = (struct procdata *) data;
- if (val)
- fuse_session_exit(pd->prevse);
- else
- fuse_session_reset(pd->prevse);
-}
-
-static int mt_session_exited(void *data)
-{
- struct procdata *pd = (struct procdata *) data;
- return fuse_session_exited(pd->prevse);
-}
-
-static int mt_chan_receive(struct fuse_chan **chp, char *buf, size_t size)
-{
- struct fuse_cmd *cmd;
- struct procdata *pd = (struct procdata *) fuse_chan_data(*chp);
-
- assert(size >= sizeof(cmd));
-
- cmd = fuse_read_cmd(pd->f);
- if (cmd == NULL)
- return 0;
-
- *(struct fuse_cmd **) buf = cmd;
-
- return sizeof(cmd);
-}
-
-int fuse_loop_mt_proc(struct fuse *f, fuse_processor_t proc, void *data)
-{
- int res;
- struct procdata pd;
- struct fuse_session *prevse = fuse_get_session(f);
- struct fuse_session *se;
- struct fuse_chan *prevch = fuse_session_next_chan(prevse, NULL);
- struct fuse_chan *ch;
- struct fuse_session_ops sop = {
- .exit = mt_session_exit,
- .exited = mt_session_exited,
- .process = mt_session_proc,
- };
- struct fuse_chan_ops cop = {
- .receive = mt_chan_receive,
- };
-
- pd.f = f;
- pd.prevch = prevch;
- pd.prevse = prevse;
- pd.proc = proc;
- pd.data = data;
-
- se = fuse_session_new(&sop, &pd);
- if (se == NULL)
- return -1;
-
- ch = fuse_chan_new(&cop, fuse_chan_fd(prevch),
- sizeof(struct fuse_cmd *), &pd);
- if (ch == NULL) {
- fuse_session_destroy(se);
- return -1;
- }
- fuse_session_add_chan(se, ch);
- res = fuse_session_loop_mt(se);
- fuse_session_destroy(se);
- return res;
-}
-
int fuse_loop_mt(struct fuse *f)
{
if (f == NULL)
@@ -118,5 +23,3 @@ int fuse_loop_mt(struct fuse *f)
fuse_stop_cleanup_thread(f);
return res;
}
-
-FUSE_SYMVER(".symver fuse_loop_mt_proc,__fuse_loop_mt@");
diff --git a/lib/fuse_opt.c b/lib/fuse_opt.c
index a2118ce..bd7a6ee 100644
--- a/lib/fuse_opt.c
+++ b/lib/fuse_opt.c
@@ -6,6 +6,7 @@
See the file COPYING.LIB
*/
+#include "config.h"
#include "fuse_opt.h"
#include "fuse_misc.h"
@@ -92,13 +93,6 @@ int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
return fuse_opt_insert_arg_common(args, pos, arg);
}
-int fuse_opt_insert_arg_compat(struct fuse_args *args, int pos,
- const char *arg);
-int fuse_opt_insert_arg_compat(struct fuse_args *args, int pos, const char *arg)
-{
- return fuse_opt_insert_arg_common(args, pos, arg);
-}
-
static int next_arg(struct fuse_opt_context *ctx, const char *opt)
{
if (ctx->argctr + 1 >= ctx->argc) {
@@ -211,11 +205,13 @@ static int process_opt_param(void *var, const char *format, const char *param,
{
assert(format[0] == '%');
if (format[1] == 's') {
+ char **s = var;
char *copy = strdup(param);
if (!copy)
return alloc_failed();
- *(char **) var = copy;
+ free(*s);
+ *s = copy;
} else {
if (sscanf(param, format, var) != 1) {
fprintf(stderr, "fuse: invalid parameter in option `%s'\n", arg);
@@ -421,6 +417,3 @@ int fuse_opt_parse(struct fuse_args *args, void *data,
fuse_opt_free_args(&ctx.outargs);
return res;
}
-
-/* This symbol version was mistakenly added to the version script */
-FUSE_SYMVER(".symver fuse_opt_insert_arg_compat,fuse_opt_insert_arg@FUSE_2.5");
diff --git a/lib/fuse_session.c b/lib/fuse_session.c
index 6e11068..e919e73 100644
--- a/lib/fuse_session.c
+++ b/lib/fuse_session.c
@@ -6,10 +6,9 @@
See the file COPYING.LIB
*/
+#include "config.h"
#include "fuse_i.h"
#include "fuse_misc.h"
-#include "fuse_common_compat.h"
-#include "fuse_lowlevel_compat.h"
#include <stdio.h>
#include <stdlib.h>
@@ -17,31 +16,15 @@
#include <assert.h>
#include <errno.h>
-struct fuse_chan {
- struct fuse_chan_ops op;
- struct fuse_session *se;
-
- int fd;
-
- size_t bufsize;
-
- void *data;
-
- int compat;
-};
-
-struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data)
+struct fuse_session *fuse_session_new(void)
{
struct fuse_session *se = (struct fuse_session *) malloc(sizeof(*se));
if (se == NULL) {
fprintf(stderr, "fuse: failed to allocate session\n");
return NULL;
}
-
memset(se, 0, sizeof(*se));
- se->op = *op;
- se->data = data;
return se;
}
@@ -64,89 +47,34 @@ void fuse_session_remove_chan(struct fuse_chan *ch)
}
}
-struct fuse_chan *fuse_session_next_chan(struct fuse_session *se,
- struct fuse_chan *ch)
-{
- assert(ch == NULL || ch == se->ch);
- if (ch == NULL)
- return se->ch;
- else
- return NULL;
-}
-
-void fuse_session_process(struct fuse_session *se, const char *buf, size_t len,
- struct fuse_chan *ch)
-{
- se->op.process(se->data, buf, len, ch);
-}
-
-void fuse_session_process_buf(struct fuse_session *se,
- const struct fuse_buf *buf, struct fuse_chan *ch)
-{
- if (se->process_buf) {
- se->process_buf(se->data, buf, ch);
- } else {
- assert(!(buf->flags & FUSE_BUF_IS_FD));
- fuse_session_process(se->data, buf->mem, buf->size, ch);
- }
-}
-
-int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf,
- struct fuse_chan **chp)
+struct fuse_chan *fuse_session_chan(struct fuse_session *se)
{
- int res;
-
- if (se->receive_buf) {
- res = se->receive_buf(se, buf, chp);
- } else {
- res = fuse_chan_recv(chp, buf->mem, buf->size);
- if (res > 0)
- buf->size = res;
- }
-
- return res;
+ return se->ch;
}
-
-void fuse_session_destroy(struct fuse_session *se)
+int fuse_chan_clearfd(struct fuse_chan *ch)
{
- if (se->op.destroy)
- se->op.destroy(se->data);
- if (se->ch != NULL)
- fuse_chan_destroy(se->ch);
- free(se);
+ int fd = ch->fd;
+ ch->fd = -1;
+ return fd;
}
void fuse_session_exit(struct fuse_session *se)
{
- if (se->op.exit)
- se->op.exit(se->data, 1);
se->exited = 1;
}
void fuse_session_reset(struct fuse_session *se)
{
- if (se->op.exit)
- se->op.exit(se->data, 0);
se->exited = 0;
}
int fuse_session_exited(struct fuse_session *se)
{
- if (se->op.exited)
- return se->op.exited(se->data);
- else
- return se->exited;
-}
-
-void *fuse_session_data(struct fuse_session *se)
-{
- return se->data;
+ return se->exited;
}
-static struct fuse_chan *fuse_chan_new_common(struct fuse_chan_ops *op, int fd,
- size_t bufsize, void *data,
- int compat)
+struct fuse_chan *fuse_chan_new(int fd)
{
struct fuse_chan *ch = (struct fuse_chan *) malloc(sizeof(*ch));
if (ch == NULL) {
@@ -155,86 +83,24 @@ static struct fuse_chan *fuse_chan_new_common(struct fuse_chan_ops *op, int fd,
}
memset(ch, 0, sizeof(*ch));
- ch->op = *op;
ch->fd = fd;
- ch->bufsize = bufsize;
- ch->data = data;
- ch->compat = compat;
return ch;
}
-struct fuse_chan *fuse_chan_new(struct fuse_chan_ops *op, int fd,
- size_t bufsize, void *data)
-{
- return fuse_chan_new_common(op, fd, bufsize, data, 0);
-}
-
-struct fuse_chan *fuse_chan_new_compat24(struct fuse_chan_ops_compat24 *op,
- int fd, size_t bufsize, void *data)
-{
- return fuse_chan_new_common((struct fuse_chan_ops *) op, fd, bufsize,
- data, 24);
-}
-
int fuse_chan_fd(struct fuse_chan *ch)
{
return ch->fd;
}
-int fuse_chan_clearfd(struct fuse_chan *ch)
-{
- int fd = ch->fd;
- ch->fd = -1;
- return fd;
-}
-
-size_t fuse_chan_bufsize(struct fuse_chan *ch)
-{
- return ch->bufsize;
-}
-
-void *fuse_chan_data(struct fuse_chan *ch)
-{
- return ch->data;
-}
-
struct fuse_session *fuse_chan_session(struct fuse_chan *ch)
{
return ch->se;
}
-int fuse_chan_recv(struct fuse_chan **chp, char *buf, size_t size)
-{
- struct fuse_chan *ch = *chp;
- if (ch->compat)
- return ((struct fuse_chan_ops_compat24 *) &ch->op)
- ->receive(ch, buf, size);
- else
- return ch->op.receive(chp, buf, size);
-}
-
-int fuse_chan_receive(struct fuse_chan *ch, char *buf, size_t size)
-{
- int res;
-
- res = fuse_chan_recv(&ch, buf, size);
- return res >= 0 ? res : (res != -EINTR && res != -EAGAIN) ? -1 : 0;
-}
-
-int fuse_chan_send(struct fuse_chan *ch, const struct iovec iov[], size_t count)
-{
- return ch->op.send(ch, iov, count);
-}
-
void fuse_chan_destroy(struct fuse_chan *ch)
{
fuse_session_remove_chan(ch);
- if (ch->op.destroy)
- ch->op.destroy(ch);
+ fuse_chan_close(ch);
free(ch);
}
-
-#ifndef __FreeBSD__
-FUSE_SYMVER(".symver fuse_chan_new_compat24,fuse_chan_new@FUSE_2.4");
-#endif
diff --git a/lib/fuse_signals.c b/lib/fuse_signals.c
index 88ac39e..c78c62d 100644..100755
--- a/lib/fuse_signals.c
+++ b/lib/fuse_signals.c
@@ -6,6 +6,7 @@
See the file COPYING.LIB
*/
+#include "config.h"
#include "fuse_lowlevel.h"
#include <stdio.h>
@@ -14,12 +15,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))
{
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index 8d91887..08dafbd 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -1,38 +1,11 @@
-FUSE_2.2 {
+FUSE_3.0 {
global:
fuse_destroy;
fuse_exit;
- fuse_exited;
- fuse_invalidate;
- fuse_is_lib_option;
fuse_loop;
fuse_loop_mt;
- fuse_loop_mt_proc;
- fuse_main;
- fuse_main_compat1;
- fuse_main_compat2;
- fuse_mount_compat1;
- fuse_new_compat1;
- fuse_new_compat2;
- fuse_process_cmd;
- fuse_read_cmd;
- fuse_set_getcontext_func;
- fuse_setup_compat2;
-};
-
-FUSE_2.4 {
- global:
- fuse_add_dirent;
- fuse_chan_bufsize;
- fuse_chan_data;
fuse_chan_destroy;
fuse_chan_fd;
- fuse_chan_receive;
- fuse_chan_send;
- fuse_chan_session;
- fuse_dirent_size;
- fuse_kern_chan_new;
- fuse_lowlevel_is_lib_option;
fuse_reply_attr;
fuse_reply_buf;
fuse_reply_entry;
@@ -48,18 +21,8 @@ FUSE_2.4 {
fuse_session_exited;
fuse_session_loop;
fuse_session_loop_mt;
- fuse_session_new;
- fuse_session_next_chan;
- fuse_session_process;
+ fuse_session_chan;
fuse_session_reset;
-} FUSE_2.2;
-
-FUSE_2.5 {
- global:
- fuse_lowlevel_new_compat;
- fuse_main_real_compat22;
- fuse_mount_compat22;
- fuse_new_compat22;
fuse_opt_parse;
fuse_opt_add_opt;
fuse_opt_add_arg;
@@ -69,45 +32,23 @@ FUSE_2.5 {
fuse_remove_signal_handlers;
fuse_reply_create;
fuse_reply_open;
- fuse_reply_open_compat;
fuse_reply_statfs;
- fuse_reply_statfs_compat;
- fuse_setup_compat22;
fuse_set_signal_handlers;
-} FUSE_2.4;
-
-FUSE_2.6 {
- global:
fuse_add_direntry;
- fuse_chan_new;
- fuse_chan_new_compat24;
- fuse_chan_recv;
+ fuse_add_direntry_plus;
fuse_daemonize;
fuse_get_session;
fuse_interrupted;
fuse_lowlevel_new;
- fuse_lowlevel_new_compat25;
fuse_main_real;
- fuse_main_real_compat25;
fuse_mount;
- fuse_mount_compat25;
fuse_new;
- fuse_new_compat25;
fuse_opt_insert_arg;
fuse_reply_lock;
fuse_req_interrupt_func;
fuse_req_interrupted;
fuse_session_remove_chan;
- fuse_setup;
- fuse_setup_compat25;
- fuse_teardown;
- fuse_teardown_compat22;
fuse_unmount;
- fuse_unmount_compat22;
-} FUSE_2.5;
-
-FUSE_2.7 {
- global:
fuse_fs_access;
fuse_fs_bmap;
fuse_fs_chmod;
@@ -148,15 +89,7 @@ FUSE_2.7 {
fuse_register_module;
fuse_reply_iov;
fuse_version;
-} FUSE_2.6;
-
-FUSE_2.7.5 {
- global:
fuse_reply_bmap;
-} FUSE_2.7;
-
-FUSE_2.8 {
- global:
cuse_lowlevel_new;
cuse_lowlevel_main;
cuse_lowlevel_setup;
@@ -177,11 +110,6 @@ FUSE_2.8 {
fuse_reply_poll;
fuse_req_ctx;
fuse_req_getgroups;
- fuse_session_data;
-} FUSE_2.7.5;
-
-FUSE_2.9 {
- global:
fuse_buf_copy;
fuse_buf_size;
fuse_fs_read_buf;
@@ -196,12 +124,8 @@ FUSE_2.9 {
fuse_clean_cache;
fuse_lowlevel_notify_delete;
fuse_fs_flock;
-} FUSE_2.8;
-
-FUSE_2.9.1 {
- global:
fuse_fs_fallocate;
local:
*;
-} FUSE_2.9;
+};
diff --git a/lib/helper.c b/lib/helper.c
index b644012..e5550c9 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -11,7 +11,6 @@
#include "fuse_misc.h"
#include "fuse_opt.h"
#include "fuse_lowlevel.h"
-#include "fuse_common_compat.h"
#include <stdio.h>
#include <stdlib.h>
@@ -59,30 +58,26 @@ static const struct fuse_opt fuse_helper_opts[] = {
static void usage(const char *progname)
{
- fprintf(stderr,
- "usage: %s mountpoint [options]\n\n", progname);
- fprintf(stderr,
- "general options:\n"
- " -o opt,[opt...] mount options\n"
- " -h --help print help\n"
- " -V --version print version\n"
- "\n");
+ printf("usage: %s mountpoint [options]\n\n", progname);
+ printf("general options:\n"
+ " -o opt,[opt...] mount options\n"
+ " -h --help print help\n"
+ " -V --version print version\n"
+ "\n");
}
static void helper_help(void)
{
- fprintf(stderr,
- "FUSE options:\n"
- " -d -o debug enable debug output (implies -f)\n"
- " -f foreground operation\n"
- " -s disable multi-threaded operation\n"
- "\n"
- );
+ printf("FUSE options:\n"
+ " -d -o debug enable debug output (implies -f)\n"
+ " -f foreground operation\n"
+ " -s disable multi-threaded operation\n"
+ "\n");
}
static void helper_version(void)
{
- fprintf(stderr, "FUSE library version: %s\n", PACKAGE_VERSION);
+ printf("FUSE library version: %s\n", PACKAGE_VERSION);
}
static int fuse_helper_opt_proc(void *data, const char *arg, int key,
@@ -211,12 +206,13 @@ int fuse_daemonize(int foreground)
if (nullfd > 2)
close(nullfd);
}
+ } else {
+ (void) chdir("/");
}
return 0;
}
-static struct fuse_chan *fuse_mount_common(const char *mountpoint,
- struct fuse_args *args)
+struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args)
{
struct fuse_chan *ch;
int fd;
@@ -231,23 +227,18 @@ static struct fuse_chan *fuse_mount_common(const char *mountpoint,
close(fd);
} while (fd >= 0 && fd <= 2);
- fd = fuse_mount_compat25(mountpoint, args);
+ fd = fuse_kern_mount(mountpoint, args);
if (fd == -1)
return NULL;
- ch = fuse_kern_chan_new(fd);
+ ch = fuse_chan_new(fd);
if (!ch)
fuse_kern_unmount(mountpoint, fd);
return ch;
}
-struct fuse_chan *fuse_mount(const char *mountpoint, struct fuse_args *args)
-{
- return fuse_mount_common(mountpoint, args);
-}
-
-static void fuse_unmount_common(const char *mountpoint, struct fuse_chan *ch)
+void fuse_unmount(const char *mountpoint, struct fuse_chan *ch)
{
if (mountpoint) {
int fd = ch ? fuse_chan_clearfd(ch) : -1;
@@ -257,19 +248,9 @@ static void fuse_unmount_common(const char *mountpoint, struct fuse_chan *ch)
}
}
-void fuse_unmount(const char *mountpoint, struct fuse_chan *ch)
-{
- fuse_unmount_common(mountpoint, ch);
-}
-
-struct fuse *fuse_setup_common(int argc, char *argv[],
- const struct fuse_operations *op,
- size_t op_size,
- char **mountpoint,
- int *multithreaded,
- int *fd,
- void *user_data,
- int compat)
+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)
{
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
struct fuse_chan *ch;
@@ -281,13 +262,13 @@ struct fuse *fuse_setup_common(int argc, char *argv[],
if (res == -1)
return NULL;
- ch = fuse_mount_common(*mountpoint, &args);
+ ch = fuse_mount(*mountpoint, &args);
if (!ch) {
fuse_opt_free_args(&args);
goto err_free;
}
- fuse = fuse_new_common(ch, &args, op, op_size, user_data, compat);
+ fuse = fuse_new(ch, &args, op, op_size, user_data);
fuse_opt_free_args(&args);
if (fuse == NULL)
goto err_unmount;
@@ -300,13 +281,10 @@ struct fuse *fuse_setup_common(int argc, char *argv[],
if (res == -1)
goto err_unmount;
- if (fd)
- *fd = fuse_chan_fd(ch);
-
return fuse;
err_unmount:
- fuse_unmount_common(*mountpoint, ch);
+ fuse_unmount(*mountpoint, ch);
if (fuse)
fuse_destroy(fuse);
err_free:
@@ -314,40 +292,26 @@ err_free:
return NULL;
}
-struct fuse *fuse_setup(int argc, char *argv[],
- const struct fuse_operations *op, size_t op_size,
- char **mountpoint, int *multithreaded, void *user_data)
-{
- return fuse_setup_common(argc, argv, op, op_size, mountpoint,
- multithreaded, NULL, user_data, 0);
-}
-
-static void fuse_teardown_common(struct fuse *fuse, char *mountpoint)
+static void fuse_teardown(struct fuse *fuse, char *mountpoint)
{
struct fuse_session *se = fuse_get_session(fuse);
- struct fuse_chan *ch = fuse_session_next_chan(se, NULL);
+ struct fuse_chan *ch = fuse_session_chan(se);
fuse_remove_signal_handlers(se);
- fuse_unmount_common(mountpoint, ch);
+ fuse_unmount(mountpoint, ch);
fuse_destroy(fuse);
free(mountpoint);
}
-void fuse_teardown(struct fuse *fuse, char *mountpoint)
-{
- fuse_teardown_common(fuse, mountpoint);
-}
-
-static int fuse_main_common(int argc, char *argv[],
- const struct fuse_operations *op, size_t op_size,
- void *user_data, int compat)
+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_common(argc, argv, op, op_size, &mountpoint,
- &multithreaded, NULL, user_data, compat);
+ fuse = fuse_setup(argc, argv, op, op_size, &mountpoint,
+ &multithreaded, user_data);
if (fuse == NULL)
return 1;
@@ -356,125 +320,15 @@ static int fuse_main_common(int argc, char *argv[],
else
res = fuse_loop(fuse);
- fuse_teardown_common(fuse, mountpoint);
+ fuse_teardown(fuse, mountpoint);
if (res == -1)
return 1;
return 0;
}
-int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
- size_t op_size, void *user_data)
-{
- return fuse_main_common(argc, argv, op, op_size, user_data, 0);
-}
-
-#undef fuse_main
-int fuse_main(void);
-int fuse_main(void)
-{
- fprintf(stderr, "fuse_main(): This function does not exist\n");
- return -1;
-}
-
int fuse_version(void)
{
return FUSE_VERSION;
}
-#include "fuse_compat.h"
-
-#if !defined(__FreeBSD__) && !defined(__NetBSD__)
-
-struct fuse *fuse_setup_compat22(int argc, char *argv[],
- const struct fuse_operations_compat22 *op,
- 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, NULL,
- 22);
-}
-
-struct fuse *fuse_setup_compat2(int argc, char *argv[],
- const struct fuse_operations_compat2 *op,
- char **mountpoint, int *multithreaded,
- int *fd)
-{
- return fuse_setup_common(argc, argv, (struct fuse_operations *) op,
- sizeof(struct fuse_operations_compat2),
- mountpoint, multithreaded, fd, NULL, 21);
-}
-
-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, NULL, 22);
-}
-
-void fuse_main_compat1(int argc, char *argv[],
- const struct fuse_operations_compat1 *op)
-{
- fuse_main_common(argc, argv, (struct fuse_operations *) op,
- sizeof(struct fuse_operations_compat1), NULL, 11);
-}
-
-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), NULL,
- 21);
-}
-
-int fuse_mount_compat1(const char *mountpoint, const char *args[])
-{
- /* just ignore mount args for now */
- (void) args;
- return fuse_mount_compat22(mountpoint, NULL);
-}
-
-FUSE_SYMVER(".symver fuse_setup_compat2,__fuse_setup@");
-FUSE_SYMVER(".symver fuse_setup_compat22,fuse_setup@FUSE_2.2");
-FUSE_SYMVER(".symver fuse_teardown,__fuse_teardown@");
-FUSE_SYMVER(".symver fuse_main_compat2,fuse_main@");
-FUSE_SYMVER(".symver fuse_main_real_compat22,fuse_main_real@FUSE_2.2");
-
-#endif /* __FreeBSD__ || __NetBSD__ */
-
-
-struct fuse *fuse_setup_compat25(int argc, char *argv[],
- const struct fuse_operations_compat25 *op,
- 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, NULL,
- 25);
-}
-
-int fuse_main_real_compat25(int argc, char *argv[],
- const struct fuse_operations_compat25 *op,
- size_t op_size)
-{
- return fuse_main_common(argc, argv, (struct fuse_operations *) op,
- op_size, NULL, 25);
-}
-
-void fuse_teardown_compat22(struct fuse *fuse, int fd, char *mountpoint)
-{
- (void) fd;
- fuse_teardown_common(fuse, mountpoint);
-}
-
-int fuse_mount_compat25(const char *mountpoint, struct fuse_args *args)
-{
- return fuse_kern_mount(mountpoint, args);
-}
-
-FUSE_SYMVER(".symver fuse_setup_compat25,fuse_setup@FUSE_2.5");
-FUSE_SYMVER(".symver fuse_teardown_compat22,fuse_teardown@FUSE_2.2");
-FUSE_SYMVER(".symver fuse_main_real_compat25,fuse_main_real@FUSE_2.5");
-FUSE_SYMVER(".symver fuse_mount_compat25,fuse_mount@FUSE_2.5");
diff --git a/lib/modules/iconv.c b/lib/modules/iconv.c
index 89b22e4..7438ecb 100644
--- a/lib/modules/iconv.c
+++ b/lib/modules/iconv.c
@@ -6,7 +6,9 @@
See the file COPYING.LIB
*/
-#define FUSE_USE_VERSION 26
+#define FUSE_USE_VERSION 30
+
+#include <config.h>
#include <fuse.h>
#include <stdio.h>
@@ -631,7 +633,6 @@ static const struct fuse_operations iconv_oper = {
.flock = iconv_flock,
.bmap = iconv_bmap,
- .flag_nullpath_ok = 1,
.flag_nopath = 1,
};
@@ -649,7 +650,7 @@ static void iconv_help(void)
char *charmap = strdup(nl_langinfo(CODESET));
setlocale(LC_CTYPE, old);
free(old);
- fprintf(stderr,
+ printf(
" -o from_code=CHARSET original encoding of file names (default: UTF-8)\n"
" -o to_code=CHARSET new encoding of the file names (default: %s)\n",
charmap);
diff --git a/lib/modules/subdir.c b/lib/modules/subdir.c
index 76a53fa..eb56d36 100644
--- a/lib/modules/subdir.c
+++ b/lib/modules/subdir.c
@@ -6,7 +6,9 @@
See the file COPYING.LIB
*/
-#define FUSE_USE_VERSION 26
+#define FUSE_USE_VERSION 30
+
+#include <config.h>
#include <fuse.h>
#include <stdio.h>
@@ -614,7 +616,6 @@ static const struct fuse_operations subdir_oper = {
.flock = subdir_flock,
.bmap = subdir_bmap,
- .flag_nullpath_ok = 1,
.flag_nopath = 1,
};
@@ -629,7 +630,7 @@ static const struct fuse_opt subdir_opts[] = {
static void subdir_help(void)
{
- fprintf(stderr,
+ printf(
" -o subdir=DIR prepend this directory to all paths (mandatory)\n"
" -o [no]rellinks transform absolute symlinks to relative\n");
}
diff --git a/lib/mount.c b/lib/mount.c
index 0f767c8..fb9231a 100644
--- a/lib/mount.c
+++ b/lib/mount.c
@@ -10,7 +10,6 @@
#include "fuse_i.h"
#include "fuse_misc.h"
#include "fuse_opt.h"
-#include "fuse_common_compat.h"
#include "mount_util.h"
#include <stdio.h>
@@ -98,6 +97,10 @@ static const struct fuse_opt fuse_mount_opts[] = {
FUSE_OPT_KEY("large_read", KEY_KERN_OPT),
FUSE_OPT_KEY("blksize=", KEY_KERN_OPT),
FUSE_OPT_KEY("default_permissions", KEY_KERN_OPT),
+ FUSE_OPT_KEY("context=", KEY_KERN_OPT),
+ FUSE_OPT_KEY("fscontext=", KEY_KERN_OPT),
+ FUSE_OPT_KEY("defcontext=", KEY_KERN_OPT),
+ FUSE_OPT_KEY("rootcontext=", KEY_KERN_OPT),
FUSE_OPT_KEY("max_read=", KEY_KERN_OPT),
FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP),
FUSE_OPT_KEY("user=", KEY_MTAB_OPT),
@@ -124,7 +127,7 @@ static const struct fuse_opt fuse_mount_opts[] = {
static void mount_help(void)
{
- fprintf(stderr,
+ printf(
" -o allow_other allow access to other users\n"
" -o allow_root allow access to root\n"
" -o auto_unmount auto unmount on process termination\n"
@@ -291,9 +294,6 @@ void fuse_kern_unmount(const char *mountpoint, int fd)
int res;
int pid;
- if (!mountpoint)
- return;
-
if (fd != -1) {
struct pollfd pfd;
@@ -337,11 +337,6 @@ void fuse_kern_unmount(const char *mountpoint, int fd)
waitpid(pid, NULL, 0);
}
-void fuse_unmount_compat22(const char *mountpoint)
-{
- fuse_kern_unmount(mountpoint, -1);
-}
-
static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo,
const char *opts, int quiet)
{
@@ -409,17 +404,15 @@ static int fuse_mount_fusermount(const char *mountpoint, struct mount_opts *mo,
waitpid(pid, NULL, 0); /* bury zombie */
}
+ if (rv >= 0)
+ fcntl(rv, F_SETFD, FD_CLOEXEC);
+
return rv;
}
-int fuse_mount_compat22(const char *mountpoint, const char *opts)
-{
- struct mount_opts mo;
- memset(&mo, 0, sizeof(mo));
- mo.flags = MS_NOSUID | MS_NODEV;
-
- return fuse_mount_fusermount(mountpoint, &mo, opts, 0);
-}
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
static int fuse_mount_sys(const char *mnt, struct mount_opts *mo,
const char *mnt_opts)
@@ -457,7 +450,7 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo,
return -2;
}
- fd = open(devname, O_RDWR);
+ fd = open(devname, O_RDWR | O_CLOEXEC);
if (fd == -1) {
if (errno == ENODEV || errno == ENOENT)
fprintf(stderr, "fuse: device not found, try 'modprobe fuse' first\n");
@@ -466,6 +459,8 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo,
devname, strerror(errno));
return -1;
}
+ if (!O_CLOEXEC)
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
snprintf(tmp, sizeof(tmp), "fd=%i,rootmode=%o,user_id=%i,group_id=%i",
fd, stbuf.st_mode & S_IFMT, getuid(), getgid());
@@ -635,6 +630,3 @@ out:
free(mo.mtab_opts);
return res;
}
-
-FUSE_SYMVER(".symver fuse_mount_compat22,fuse_mount@FUSE_2.2");
-FUSE_SYMVER(".symver fuse_unmount_compat22,fuse_unmount@FUSE_2.2");
diff --git a/lib/mount_bsd.c b/lib/mount_bsd.c
index 3aec3e3..8f3acf0 100644
--- a/lib/mount_bsd.c
+++ b/lib/mount_bsd.c
@@ -6,6 +6,7 @@
See the file COPYING.LIB.
*/
+#include "config.h"
#include "fuse_i.h"
#include "fuse_misc.h"
#include "fuse_opt.h"
@@ -101,9 +102,7 @@ static const struct fuse_opt fuse_mount_opts[] = {
static void mount_help(void)
{
- fprintf(stderr,
- " -o allow_root allow access to root\n"
- );
+ printf(" -o allow_root allow access to root\n");
system(FUSERMOUNT_PROG " --help");
fputc('\n', stderr);
}
@@ -387,5 +386,3 @@ out:
free(mo.kernel_opts);
return res;
}
-
-FUSE_SYMVER(".symver fuse_unmount_compat22,fuse_unmount@FUSE_2.2");
diff --git a/lib/mount_util.c b/lib/mount_util.c
index 3cad2e6..87e3888 100644
--- a/lib/mount_util.c
+++ b/lib/mount_util.c
@@ -6,6 +6,7 @@
See the file COPYING.LIB.
*/
+#include "config.h"
#include "mount_util.h"
#include <stdio.h>
#include <unistd.h>
diff --git a/lib/ulockmgr.c b/lib/ulockmgr.c
deleted file mode 100644
index b875c50..0000000
--- a/lib/ulockmgr.c
+++ /dev/null
@@ -1,444 +0,0 @@
-/*
- libulockmgr: Userspace Lock Manager Library
- Copyright (C) 2006 Miklos Szeredi <miklos@szeredi.hu>
-
- This program can be distributed under the terms of the GNU LGPLv2.
- See the file COPYING.LIB
-*/
-
-/* #define DEBUG 1 */
-
-#include "ulockmgr.h"
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <pthread.h>
-#include <errno.h>
-#include <assert.h>
-#include <signal.h>
-#include <sys/stat.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-
-struct message {
- unsigned intr : 1;
- unsigned nofd : 1;
- pthread_t thr;
- int cmd;
- int fd;
- struct flock lock;
- int error;
-};
-
-struct fd_store {
- struct fd_store *next;
- int fd;
- int inuse;
-};
-
-struct owner {
- struct owner *next;
- struct owner *prev;
- struct fd_store *fds;
- void *id;
- size_t id_len;
- int cfd;
-};
-
-static pthread_mutex_t ulockmgr_lock;
-static int ulockmgr_cfd = -1;
-static struct owner owner_list = { .next = &owner_list, .prev = &owner_list };
-
-#define MAX_SEND_FDS 2
-
-static void list_del_owner(struct owner *owner)
-{
- struct owner *prev = owner->prev;
- struct owner *next = owner->next;
- prev->next = next;
- next->prev = prev;
-}
-
-static void list_add_owner(struct owner *owner, struct owner *next)
-{
- struct owner *prev = next->prev;
- owner->next = next;
- owner->prev = prev;
- prev->next = owner;
- next->prev = owner;
-}
-
-/*
- * There's a bug in the linux kernel (< 2.6.22) recv() implementation
- * on AF_UNIX, SOCK_STREAM sockets, that could cause it to return
- * zero, even if data was available. Retrying the recv will return
- * the data in this case.
- */
-static int do_recv(int sock, void *buf, size_t len, int flags)
-{
- int res = recv(sock, buf, len, flags);
- if (res == 0)
- res = recv(sock, buf, len, flags);
-
- return res;
-}
-
-static int ulockmgr_send_message(int sock, void *buf, size_t buflen,
- int *fdp, int numfds)
-{
- struct msghdr msg;
- struct cmsghdr *p_cmsg;
- struct iovec vec;
- size_t cmsgbuf[CMSG_SPACE(sizeof(int) * MAX_SEND_FDS) / sizeof(size_t)];
- int res;
-
- assert(numfds <= MAX_SEND_FDS);
- msg.msg_control = cmsgbuf;
- msg.msg_controllen = sizeof(cmsgbuf);
- p_cmsg = CMSG_FIRSTHDR(&msg);
- p_cmsg->cmsg_level = SOL_SOCKET;
- p_cmsg->cmsg_type = SCM_RIGHTS;
- p_cmsg->cmsg_len = CMSG_LEN(sizeof(int) * numfds);
- memcpy(CMSG_DATA(p_cmsg), fdp, sizeof(int) * numfds);
- msg.msg_controllen = p_cmsg->cmsg_len;
- msg.msg_name = NULL;
- msg.msg_namelen = 0;
- msg.msg_iov = &vec;
- msg.msg_iovlen = 1;
- msg.msg_flags = 0;
- vec.iov_base = buf;
- vec.iov_len = buflen;
- res = sendmsg(sock, &msg, MSG_NOSIGNAL);
- if (res == -1) {
- perror("libulockmgr: sendmsg");
- return -1;
- }
- if ((size_t) res != buflen) {
- fprintf(stderr, "libulockmgr: sendmsg short\n");
- return -1;
- }
- return 0;
-}
-
-static int ulockmgr_start_daemon(void)
-{
- int sv[2];
- int res;
- char tmp[64];
-
- res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
- if (res == -1) {
- perror("libulockmgr: socketpair");
- return -1;
- }
- snprintf(tmp, sizeof(tmp), "exec ulockmgr_server %i", sv[0]);
- res = system(tmp);
- close(sv[0]);
- if (res == -1 || !WIFEXITED(res) || WEXITSTATUS(res) != 0) {
- close(sv[1]);
- return -1;
- }
- ulockmgr_cfd = sv[1];
- return 0;
-}
-
-static struct owner *ulockmgr_new_owner(const void *id, size_t id_len)
-{
- int sv[2];
- int res;
- char c = 'm';
- struct owner *o;
-
- if (ulockmgr_cfd == -1 && ulockmgr_start_daemon() == -1)
- return NULL;
-
- o = calloc(1, sizeof(struct owner) + id_len);
- if (!o) {
- fprintf(stderr, "libulockmgr: failed to allocate memory\n");
- return NULL;
- }
- o->id = o + 1;
- o->id_len = id_len;
- res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
- if (res == -1) {
- perror("libulockmgr: socketpair");
- goto out_free;
- }
- res = ulockmgr_send_message(ulockmgr_cfd, &c, sizeof(c), &sv[0], 1);
- close(sv[0]);
- if (res == -1) {
- close(ulockmgr_cfd);
- ulockmgr_cfd = -1;
- goto out_close;
- }
-
- o->cfd = sv[1];
- memcpy(o->id, id, id_len);
- list_add_owner(o, &owner_list);
-
- return o;
-
-out_close:
- close(sv[1]);
-out_free:
- free(o);
- return NULL;
-}
-
-static int ulockmgr_send_request(struct message *msg, const void *id,
- size_t id_len)
-{
- int sv[2];
- int cfd;
- struct owner *o;
- struct fd_store *f = NULL;
- struct fd_store *newf = NULL;
- struct fd_store **fp;
- int fd = msg->fd;
- int cmd = msg->cmd;
- int res;
- int unlockall = (cmd == F_SETLK && msg->lock.l_type == F_UNLCK &&
- msg->lock.l_start == 0 && msg->lock.l_len == 0);
-
- for (o = owner_list.next; o != &owner_list; o = o->next)
- if (o->id_len == id_len && memcmp(o->id, id, id_len) == 0)
- break;
-
- if (o == &owner_list)
- o = NULL;
-
- if (!o && cmd != F_GETLK && msg->lock.l_type != F_UNLCK)
- o = ulockmgr_new_owner(id, id_len);
-
- if (!o) {
- if (cmd == F_GETLK) {
- res = fcntl(msg->fd, F_GETLK, &msg->lock);
- return (res == -1) ? -errno : 0;
- } else if (msg->lock.l_type == F_UNLCK)
- return 0;
- else
- return -ENOLCK;
- }
-
- if (unlockall)
- msg->nofd = 1;
- else {
- for (fp = &o->fds; *fp; fp = &(*fp)->next) {
- f = *fp;
- if (f->fd == fd) {
- msg->nofd = 1;
- break;
- }
- }
- }
-
- if (!msg->nofd) {
- newf = f = calloc(1, sizeof(struct fd_store));
- if (!f) {
- fprintf(stderr, "libulockmgr: failed to allocate memory\n");
- return -ENOLCK;
- }
- }
-
- res = socketpair(AF_UNIX, SOCK_STREAM, 0, sv);
- if (res == -1) {
- perror("libulockmgr: socketpair");
- free(newf);
- return -ENOLCK;
- }
-
- cfd = sv[1];
- sv[1] = msg->fd;
- res = ulockmgr_send_message(o->cfd, msg, sizeof(struct message), sv,
- msg->nofd ? 1 : 2);
- close(sv[0]);
- if (res == -1) {
- free(newf);
- close(cfd);
- return -EIO;
- }
-
- if (newf) {
- newf->fd = msg->fd;
- newf->next = o->fds;
- o->fds = newf;
- }
- if (f)
- f->inuse++;
-
- res = do_recv(cfd, msg, sizeof(struct message), MSG_WAITALL);
- if (res == -1) {
- perror("libulockmgr: recv");
- msg->error = EIO;
- } else if (res != sizeof(struct message)) {
- fprintf(stderr, "libulockmgr: recv short\n");
- msg->error = EIO;
- } else if (cmd == F_SETLKW && msg->error == EAGAIN) {
- pthread_mutex_unlock(&ulockmgr_lock);
- while (1) {
- sigset_t old;
- sigset_t unblock;
- int errno_save;
-
- sigemptyset(&unblock);
- sigaddset(&unblock, SIGUSR1);
- pthread_sigmask(SIG_UNBLOCK, &unblock, &old);
- res = do_recv(cfd, msg, sizeof(struct message),
- MSG_WAITALL);
- errno_save = errno;
- pthread_sigmask(SIG_SETMASK, &old, NULL);
- if (res == sizeof(struct message))
- break;
- else if (res >= 0) {
- fprintf(stderr, "libulockmgr: recv short\n");
- msg->error = EIO;
- break;
- } else if (errno_save != EINTR) {
- errno = errno_save;
- perror("libulockmgr: recv");
- msg->error = EIO;
- break;
- }
- msg->intr = 1;
- res = send(o->cfd, msg, sizeof(struct message),
- MSG_NOSIGNAL);
- if (res == -1) {
- perror("libulockmgr: send");
- msg->error = EIO;
- break;
- }
- if (res != sizeof(struct message)) {
- fprintf(stderr, "libulockmgr: send short\n");
- msg->error = EIO;
- break;
- }
- }
- pthread_mutex_lock(&ulockmgr_lock);
-
- }
- if (f)
- f->inuse--;
- close(cfd);
- if (unlockall) {
- for (fp = &o->fds; *fp;) {
- f = *fp;
- if (f->fd == fd && !f->inuse) {
- *fp = f->next;
- free(f);
- } else
- fp = &f->next;
- }
- if (!o->fds) {
- list_del_owner(o);
- close(o->cfd);
- free(o);
- }
- /* Force OK on unlock-all, since it _will_ succeed once the
- owner is deleted */
- msg->error = 0;
- }
-
- return -msg->error;
-}
-
-#ifdef DEBUG
-static uint32_t owner_hash(const unsigned char *id, size_t id_len)
-{
- uint32_t h = 0;
- size_t i;
- for (i = 0; i < id_len; i++)
- h = ((h << 8) | (h >> 24)) ^ id[i];
-
- return h;
-}
-#endif
-
-static int ulockmgr_canonicalize(int fd, struct flock *lock)
-{
- off_t offset;
- if (lock->l_whence == SEEK_CUR) {
- offset = lseek(fd, 0, SEEK_CUR);
- if (offset == (off_t) -1)
- return -errno;
- } else if (lock->l_whence == SEEK_END) {
- struct stat stbuf;
- int res = fstat(fd, &stbuf);
- if (res == -1)
- return -errno;
-
- offset = stbuf.st_size;
- } else
- offset = 0;
-
- lock->l_whence = SEEK_SET;
- lock->l_start += offset;
-
- if (lock->l_start < 0)
- return -EINVAL;
-
- if (lock->l_len < 0) {
- lock->l_start += lock->l_len;
- if (lock->l_start < 0)
- return -EINVAL;
- lock->l_len = -lock->l_len;
- }
- if (lock->l_len && lock->l_start + lock->l_len - 1 < 0)
- return -EINVAL;
-
- return 0;
-}
-
-int ulockmgr_op(int fd, int cmd, struct flock *lock, const void *owner,
- size_t owner_len)
-{
- int err;
- struct message msg;
- sigset_t old;
- sigset_t block;
-
- if (cmd != F_GETLK && cmd != F_SETLK && cmd != F_SETLKW)
- return -EINVAL;
-
- if (lock->l_type != F_RDLCK && lock->l_type != F_WRLCK &&
- lock->l_type != F_UNLCK)
- return -EINVAL;
-
- if (lock->l_whence != SEEK_SET && lock->l_whence != SEEK_CUR &&
- lock->l_whence != SEEK_END)
- return -EINVAL;
-
-#ifdef DEBUG
- fprintf(stderr, "libulockmgr: %i %i %i %lli %lli own: 0x%08x\n",
- cmd, lock->l_type, lock->l_whence, lock->l_start, lock->l_len,
- owner_hash(owner, owner_len));
-#endif
-
- /* Unlock should never block anyway */
- if (cmd == F_SETLKW && lock->l_type == F_UNLCK)
- cmd = F_SETLK;
-
- memset(&msg, 0, sizeof(struct message));
- msg.cmd = cmd;
- msg.fd = fd;
- msg.lock = *lock;
- err = ulockmgr_canonicalize(fd, &msg.lock);
- if (err)
- return err;
-
- sigemptyset(&block);
- sigaddset(&block, SIGUSR1);
- pthread_sigmask(SIG_BLOCK, &block, &old);
- pthread_mutex_lock(&ulockmgr_lock);
- err = ulockmgr_send_request(&msg, owner, owner_len);
- pthread_mutex_unlock(&ulockmgr_lock);
- pthread_sigmask(SIG_SETMASK, &old, NULL);
- if (!err && cmd == F_GETLK) {
- if (msg.lock.l_type == F_UNLCK)
- lock->l_type = F_UNLCK;
- else
- *lock = msg.lock;
- }
-
- return err;
-}
diff --git a/test/stracedecode.c b/test/stracedecode.c
index 27b883c..940438a 100644
--- a/test/stracedecode.c
+++ b/test/stracedecode.c
@@ -41,6 +41,7 @@ static struct {
[FUSE_INTERRUPT] = { "INTERRUPT" },
[FUSE_BMAP] = { "BMAP" },
[FUSE_DESTROY] = { "DESTROY" },
+ [FUSE_READDIRPLUS] = { "READDIRPLUS" },
};
#define FUSE_MAXOP (sizeof(fuse_ll_ops) / sizeof(fuse_ll_ops[0]))
diff --git a/util/.gitignore b/util/.gitignore
index 4a58d8e..961b59b 100644
--- a/util/.gitignore
+++ b/util/.gitignore
@@ -1,5 +1,4 @@
fusermount
-ulockmgr_server
fuse_ioslave
mount.fuse
mount_util.c
diff --git a/util/Makefile.am b/util/Makefile.am
index 059d5fc..a489d28 100644
--- a/util/Makefile.am
+++ b/util/Makefile.am
@@ -1,7 +1,6 @@
## Process this file with automake to produce Makefile.in
-AM_CPPFLAGS = -D_FILE_OFFSET_BITS=64
-bin_PROGRAMS = fusermount ulockmgr_server
+bin_PROGRAMS = fusermount
noinst_PROGRAMS = mount.fuse
# we re-use mount_util.c from the library, but do want to keep ourself
@@ -16,10 +15,6 @@ mount_util.c: $(top_srcdir)/lib/mount_util.c
mount_fuse_SOURCES = mount.fuse.c
-ulockmgr_server_SOURCES = ulockmgr_server.c
-ulockmgr_server_CPPFLAGS = -D_FILE_OFFSET_BITS=64 -D_REENTRANT
-ulockmgr_server_LDFLAGS = -pthread
-
install-exec-hook:
-chmod u+s $(DESTDIR)$(bindir)/fusermount
@if test ! -e $(DESTDIR)/dev/fuse; then \
diff --git a/util/fusermount.c b/util/fusermount.c
index 4fc72ed..e7dbca6 100644
--- a/util/fusermount.c
+++ b/util/fusermount.c
@@ -1159,16 +1159,15 @@ static int send_fd(int sock_fd, int fd)
static void usage(void)
{
- fprintf(stderr,
- "%s: [options] mountpoint\n"
- "Options:\n"
- " -h print help\n"
- " -V print version\n"
- " -o opt[,opt...] mount options\n"
- " -u unmount\n"
- " -q quiet\n"
- " -z lazy unmount\n",
- progname);
+ printf("%s: [options] mountpoint\n"
+ "Options:\n"
+ " -h print help\n"
+ " -V print version\n"
+ " -o opt[,opt...] mount options\n"
+ " -u unmount\n"
+ " -q quiet\n"
+ " -z lazy unmount\n",
+ progname);
exit(1);
}
diff --git a/util/mount.fuse.c b/util/mount.fuse.c
index 6df8c03..363b12b 100644
--- a/util/mount.fuse.c
+++ b/util/mount.fuse.c
@@ -6,6 +6,8 @@
See the file COPYING.
*/
+#include <config.h>
+
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
diff --git a/util/ulockmgr_server.c b/util/ulockmgr_server.c
deleted file mode 100644
index baef45d..0000000
--- a/util/ulockmgr_server.c
+++ /dev/null
@@ -1,425 +0,0 @@
-/*
- ulockmgr_server: Userspace Lock Manager Server
- Copyright (C) 2006 Miklos Szeredi <miklos@szeredi.hu>
-
- This program can be distributed under the terms of the GNU GPL.
- See the file COPYING.
-*/
-
-/* #define DEBUG 1 */
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <fcntl.h>
-#include <dirent.h>
-#include <pthread.h>
-#include <stdint.h>
-#include <errno.h>
-#include <assert.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/wait.h>
-
-struct message {
- unsigned intr : 1;
- unsigned nofd : 1;
- pthread_t thr;
- int cmd;
- int fd;
- struct flock lock;
- int error;
-};
-
-struct fd_store {
- struct fd_store *next;
- int fd;
- int origfd;
- int inuse;
-};
-
-struct owner {
- struct fd_store *fds;
- pthread_mutex_t lock;
-};
-
-struct req_data {
- struct owner *o;
- int cfd;
- struct fd_store *f;
- struct message msg;
-};
-
-#define MAX_SEND_FDS 2
-
-static int receive_message(int sock, void *buf, size_t buflen, int *fdp,
- int *numfds)
-{
- struct msghdr msg;
- struct iovec iov;
- size_t ccmsg[CMSG_SPACE(sizeof(int) * MAX_SEND_FDS) / sizeof(size_t)];
- struct cmsghdr *cmsg;
- int res;
- int i;
-
- assert(*numfds <= MAX_SEND_FDS);
- iov.iov_base = buf;
- iov.iov_len = buflen;
-
- memset(&msg, 0, sizeof(msg));
- memset(ccmsg, -1, sizeof(ccmsg));
- msg.msg_iov = &iov;
- msg.msg_iovlen = 1;
- msg.msg_control = ccmsg;
- msg.msg_controllen = sizeof(ccmsg);
-
- res = recvmsg(sock, &msg, MSG_WAITALL);
- if (!res) {
- /* retry on zero return, see do_recv() in ulockmgr.c */
- res = recvmsg(sock, &msg, MSG_WAITALL);
- if (!res)
- return 0;
- }
- if (res == -1) {
- perror("ulockmgr_server: recvmsg");
- return -1;
- }
- if ((size_t) res != buflen) {
- fprintf(stderr, "ulockmgr_server: short message received\n");
- return -1;
- }
-
- cmsg = CMSG_FIRSTHDR(&msg);
- if (cmsg) {
- if (!cmsg->cmsg_type == SCM_RIGHTS) {
- fprintf(stderr,
- "ulockmgr_server: unknown control message %d\n",
- cmsg->cmsg_type);
- return -1;
- }
- memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
- if (msg.msg_flags & MSG_CTRUNC) {
- fprintf(stderr,
- "ulockmgr_server: control message truncated\n");
- for (i = 0; i < *numfds; i++)
- close(fdp[i]);
- *numfds = 0;
- }
- } else {
- if (msg.msg_flags & MSG_CTRUNC) {
- fprintf(stderr,
- "ulockmgr_server: control message truncated(*)\n");
-
- /* There's a bug in the Linux kernel, that if
- not all file descriptors were allocated,
- then the cmsg header is not filled in */
- cmsg = (struct cmsghdr *) ccmsg;
- memcpy(fdp, CMSG_DATA(cmsg), sizeof(int) * *numfds);
- for (i = 0; i < *numfds; i++)
- close(fdp[i]);
- }
- *numfds = 0;
- }
- return res;
-}
-
-static int closefrom(int minfd)
-{
- DIR *dir = opendir("/proc/self/fd");
- if (dir) {
- int dfd = dirfd(dir);
- struct dirent *ent;
- while ((ent = readdir(dir))) {
- char *end;
- int fd = strtol(ent->d_name, &end, 10);
- if (ent->d_name[0] && !end[0] && fd >= minfd &&
- fd != dfd)
- close(fd);
- }
- closedir(dir);
- }
- return 0;
-}
-
-static void send_reply(int cfd, struct message *msg)
-{
- int res = send(cfd, msg, sizeof(struct message), MSG_NOSIGNAL);
- if (res == -1)
- perror("ulockmgr_server: sending reply");
-#ifdef DEBUG
- fprintf(stderr, "ulockmgr_server: error: %i\n", msg->error);
-#endif
-}
-
-static void *process_request(void *d_)
-{
- struct req_data *d = d_;
- int res;
-
- assert(d->msg.cmd == F_SETLKW);
- res = fcntl(d->f->fd, F_SETLK, &d->msg.lock);
- if (res == -1 && errno == EAGAIN) {
- d->msg.error = EAGAIN;
- d->msg.thr = pthread_self();
- send_reply(d->cfd, &d->msg);
- res = fcntl(d->f->fd, F_SETLKW, &d->msg.lock);
- }
- d->msg.error = (res == -1) ? errno : 0;
- pthread_mutex_lock(&d->o->lock);
- d->f->inuse--;
- pthread_mutex_unlock(&d->o->lock);
- send_reply(d->cfd, &d->msg);
- close(d->cfd);
- free(d);
-
- return NULL;
-}
-
-static void process_message(struct owner *o, struct message *msg, int cfd,
- int fd)
-{
- struct fd_store *f = NULL;
- struct fd_store *newf = NULL;
- struct fd_store **fp;
- struct req_data *d;
- pthread_t tid;
- int res;
-
-#ifdef DEBUG
- fprintf(stderr, "ulockmgr_server: %i %i %i %lli %lli\n",
- msg->cmd, msg->lock.l_type, msg->lock.l_whence,
- msg->lock.l_start, msg->lock.l_len);
-#endif
-
- if (msg->cmd == F_SETLK && msg->lock.l_type == F_UNLCK &&
- msg->lock.l_start == 0 && msg->lock.l_len == 0) {
- for (fp = &o->fds; *fp;) {
- f = *fp;
- if (f->origfd == msg->fd && !f->inuse) {
- close(f->fd);
- *fp = f->next;
- free(f);
- } else
- fp = &f->next;
- }
- if (!msg->nofd)
- close(fd);
-
- msg->error = 0;
- send_reply(cfd, msg);
- close(cfd);
- return;
- }
-
- if (msg->nofd) {
- for (fp = &o->fds; *fp; fp = &(*fp)->next) {
- f = *fp;
- if (f->origfd == msg->fd)
- break;
- }
- if (!*fp) {
- fprintf(stderr, "ulockmgr_server: fd %i not found\n",
- msg->fd);
- msg->error = EIO;
- send_reply(cfd, msg);
- close(cfd);
- return;
- }
- } else {
- newf = f = malloc(sizeof(struct fd_store));
- if (!f) {
- msg->error = ENOLCK;
- send_reply(cfd, msg);
- close(cfd);
- return;
- }
-
- f->fd = fd;
- f->origfd = msg->fd;
- f->inuse = 0;
- }
-
- if (msg->cmd == F_GETLK || msg->cmd == F_SETLK ||
- msg->lock.l_type == F_UNLCK) {
- res = fcntl(f->fd, msg->cmd, &msg->lock);
- msg->error = (res == -1) ? errno : 0;
- send_reply(cfd, msg);
- close(cfd);
- if (newf) {
- newf->next = o->fds;
- o->fds = newf;
- }
- return;
- }
-
- d = malloc(sizeof(struct req_data));
- if (!d) {
- msg->error = ENOLCK;
- send_reply(cfd, msg);
- close(cfd);
- free(newf);
- return;
- }
-
- f->inuse++;
- d->o = o;
- d->cfd = cfd;
- d->f = f;
- d->msg = *msg;
- res = pthread_create(&tid, NULL, process_request, d);
- if (res) {
- msg->error = ENOLCK;
- send_reply(cfd, msg);
- close(cfd);
- free(d);
- f->inuse--;
- free(newf);
- return;
- }
-
- if (newf) {
- newf->next = o->fds;
- o->fds = newf;
- }
- pthread_detach(tid);
-}
-
-static void sigusr1_handler(int sig)
-{
- (void) sig;
- /* Nothing to do */
-}
-
-static void process_owner(int cfd)
-{
- struct owner o;
- struct sigaction sa;
-
- memset(&sa, 0, sizeof(struct sigaction));
- sa.sa_handler = sigusr1_handler;
- sigemptyset(&sa.sa_mask);
-
- if (sigaction(SIGUSR1, &sa, NULL) == -1) {
- perror("ulockmgr_server: cannot set sigusr1 signal handler");
- exit(1);
- }
-
- memset(&o, 0, sizeof(struct owner));
- pthread_mutex_init(&o.lock, NULL);
- while (1) {
- struct message msg;
- int rfds[2];
- int res;
- int numfds = 2;
-
- res = receive_message(cfd, &msg, sizeof(msg), rfds, &numfds);
- if (!res)
- break;
- if (res == -1)
- exit(1);
-
- if (msg.intr) {
- if (numfds != 0)
- fprintf(stderr,
- "ulockmgr_server: too many fds for intr\n");
- pthread_kill(msg.thr, SIGUSR1);
- } else {
- if (numfds != 2)
- continue;
-
- pthread_mutex_lock(&o.lock);
- process_message(&o, &msg, rfds[0], rfds[1]);
- pthread_mutex_unlock(&o.lock);
- }
- }
- if (o.fds)
- fprintf(stderr,
- "ulockmgr_server: open file descriptors on exit\n");
-}
-
-int main(int argc, char *argv[])
-{
- int nullfd;
- char *end;
- int cfd;
- sigset_t empty;
-
- if (argc != 2 || !argv[1][0])
- goto out_inval;
-
- cfd = strtol(argv[1], &end, 10);
- if (*end)
- goto out_inval;
-
- /* demonize current process */
- switch(fork()) {
- case -1:
- perror("ulockmgr_server: fork");
- exit(1);
- case 0:
- break;
- default:
- _exit(0);
- }
-
- if (setsid() == -1) {
- perror("ulockmgr_server: setsid");
- exit(1);
- }
-
- (void) chdir("/");
-
- sigemptyset(&empty);
- sigprocmask(SIG_SETMASK, &empty, NULL);
-
- if (dup2(cfd, 4) == -1) {
- perror("ulockmgr_server: dup2");
- exit(1);
- }
- cfd = 4;
- nullfd = open("/dev/null", O_RDWR);
- if (nullfd >= 0) {
- dup2(nullfd, 0);
- dup2(nullfd, 1);
- }
- close(3);
- closefrom(5);
- while (1) {
- char c;
- int sock;
- int pid;
- int numfds = 1;
- int res = receive_message(cfd, &c, sizeof(c), &sock, &numfds);
- if (!res)
- break;
- if (res == -1)
- exit(1);
- assert(numfds == 1);
-
- pid = fork();
- if (pid == -1) {
- perror("ulockmgr_server: fork");
- close(sock);
- continue;
- }
- if (pid == 0) {
- close(cfd);
- pid = fork();
- if (pid == -1) {
- perror("ulockmgr_server: fork");
- _exit(1);
- }
- if (pid == 0)
- process_owner(sock);
- _exit(0);
- }
- waitpid(pid, NULL, 0);
- close(sock);
- }
- return 0;
-
-out_inval:
- fprintf(stderr, "%s should be started by libulockmgr\n", argv[0]);
- return 1;
-}