Browse Source

checkpoint

clonefd
Antonio SJ Musumeci 5 years ago
parent
commit
ec46077fb5
  1. 3547
      libfuse/ChangeLog
  2. 9
      libfuse/Makefile
  3. 303
      libfuse/NEWS
  4. 33
      libfuse/README.NFS
  5. 108
      libfuse/README.md
  6. 11
      libfuse/fuse.pc.in
  7. 17
      libfuse/include/Makefile.am
  8. 87
      libfuse/include/cuse_lowlevel.h
  9. 121
      libfuse/include/fuse.h
  10. 22
      libfuse/include/fuse_chan.h
  11. 17
      libfuse/include/fuse_common.h
  12. 2
      libfuse/include/fuse_common_compat.h
  13. 196
      libfuse/include/fuse_compat.h
  14. 340
      libfuse/include/fuse_lowlevel.h
  15. 13
      libfuse/include/fuse_lowlevel_compat.h
  16. 42
      libfuse/lib/Makefile.am
  17. 371
      libfuse/lib/cuse_lowlevel.c
  18. 496
      libfuse/lib/fuse.c
  19. 248
      libfuse/lib/fuse_chan.c
  20. 56
      libfuse/lib/fuse_dev.c
  21. 40
      libfuse/lib/fuse_dev.h
  22. 48
      libfuse/lib/fuse_i.h
  23. 103
      libfuse/lib/fuse_kern_chan.c
  24. 46
      libfuse/lib/fuse_loop.c
  25. 117
      libfuse/lib/fuse_loop_mt.c
  26. 914
      libfuse/lib/fuse_lowlevel.c
  27. 92
      libfuse/lib/fuse_mt.c
  28. 185
      libfuse/lib/fuse_session.c
  29. 207
      libfuse/lib/fuse_versionscript
  30. 208
      libfuse/lib/helper.c
  31. 17
      libfuse/lib/mount_generic.c
  32. 17
      libfuse/lib/mount_util.c
  33. 1
      libfuse/lib/mount_util.h
  34. 48
      libfuse/lib/sys.c
  35. 4
      libfuse/lib/sys.h
  36. 27
      libfuse/util/fusermount.c
  37. 4
      libfuse/util/mount.mergerfs.c
  38. 17
      libfuse/util/mount_util.c
  39. 2
      src/config.cpp
  40. 2
      src/fuse_init.cpp
  41. 2
      src/option_parser.cpp

3547
libfuse/ChangeLog
File diff suppressed because it is too large
View File

9
libfuse/Makefile

@ -22,11 +22,9 @@ INSTALLMAN1DIR = $(DESTDIR)$(MAN1DIR)
SRC = \ SRC = \
lib/buffer.c \ lib/buffer.c \
lib/cuse_lowlevel.c \
lib/fuse_dirents.c \
lib/fuse.c \ lib/fuse.c \
lib/fuse_kern_chan.c \
lib/fuse_loop.c \
lib/fuse_chan.c \
lib/fuse_dirents.c \
lib/fuse_loop_mt.c \ lib/fuse_loop_mt.c \
lib/fuse_lowlevel.c \ lib/fuse_lowlevel.c \
lib/fuse_mt.c \ lib/fuse_mt.c \
@ -34,7 +32,8 @@ SRC = \
lib/fuse_session.c \ lib/fuse_session.c \
lib/fuse_signals.c \ lib/fuse_signals.c \
lib/helper.c \ lib/helper.c \
lib/mount.c
lib/mount.c \
lib/sys.c
OBJS = $(SRC:lib/%.c=build/%.o) OBJS = $(SRC:lib/%.c=build/%.o)
DEPS = $(SRC:lib/%.c=build/%.d) DEPS = $(SRC:lib/%.c=build/%.d)

303
libfuse/NEWS

@ -1,303 +0,0 @@
What is new in 2.9
- Add "zero copy" support for kernel 2.6.35 or newer
- Make maximum background requests tunable on kernel 2.6.32 or newer
- Require --no-canonicalize in (u)mount (util-linux version 2.18 or
newer) to fix security problems with fusermount
- Use dynamically sized hash tables in high level library
- Memory use of filesystem daemon can shrink more easily
- Add "auto_unmount" option
- Add "remember" option
- Add man pages for fusermount, mount.fuse and ulockmgr_server
- API changes:
o Introduce "store" and "retrieve" for accessing kernel buffers on
kernel 2.6.36 or newer
o Introduce abstract buffer for zero copy operations
o Allow path calculation to be omitted on certain operations
o Allow batching forget requests
o Add "flock" method
o Add support for ioctl on directories
o Add delete notification
o Add fallocate operation (linux kernel 3.5 or newer)
- Bug fixes and small improvements
============================================================================
What is new in 2.8
- More scalable directory tree locking
- Atomic open(O_TRUNC) support
- Support big write requests on kernels 2.6.26 and newer
- Out-of-tree fuse module removed
- Better NFS exporting support
- New ioctl and poll requests
- New CUSE (Character Device in Userspace) interface
- Allow umask processing in userspace
- Added cache invalidation notifications
- Bugfixes and small improvements
============================================================================
What is new in 2.7
- Stacking support for the high level API
- Add filename charset conversion module
- Improved mounting
============================================================================
What is new in 2.6
- Improved read characteristics (asynchronous reads)
- Support for aborting filesystem connection
- POSIX file locking support
- Request interruption support
- Building module for Linux kernels earlier than 2.6.9 not supported
- Allow block device based filesystems to support swap files
- Several bugs fixed, including a rare system hang on SMP
============================================================================
What is new in 2.5
- Merge library part of FreeBSD port
- New atomic create+open, access and ftruncate operations
- On filesystems implementing the new create+open operation, and
running on Linux kernels 2.6.15 or later, the 'cp' operation will
work correctly when copying read-only files.
- New option parsing interface added to the library
- Lots of minor improvements and fixes
============================================================================
What is new in 2.4
- Simplify device opening. Now '/dev/fuse' is a requirement
- Allow module auto-loading if user has access to '/dev/fuse'
- Allow mounting over a regular file for unprivileged users
- Allow mounting of arbitrary FUSE filesystems from /etc/fstab
- New mount options: 'umask=M', 'uid=N', 'gid=N'
- Check for non-empty mountpoint, and refuse mount by default. New
mount option: 'nonempty'
- Low level (inode based) API added
- Allow 'direct_io' and 'keep_cache' options to be set on a
case-by-case basis on open.
- Add 'attr_timeout' and 'entry_timeout' mount options to the
high-level library. Until now these timeouts were fixed at 1 sec.
- Some bugfixes
============================================================================
What is new in 2.3
- Add new directory related operations: opendir(), readdir(),
releasedir() and fsyncdir()
- Add init() and destroy() operations which are called before the
event loop is started and after it has exited
- Update kernel ABI so that on dual architectures (e.g. AMD64) 32bit
binaries work under a 64bit kernel
- Bugfixes
============================================================================
What is new in 2.2
Userspace changes:
- Add fuse_file_info structure to file operations, this allows the
filesystem to return a file handle in open() which is passed to
read(), write(), flush(), fsync() and release().
- Add source compatibility with 2.1 and 1.4 releases
- Binary compatibility with 2.1 release is retained
Kernel changes:
- Make requests interruptible. This prevents the filesystem to go
into an unbreakable deadlock with itself.
- Make readpages() synchronous. Asynchronous requests are deadlock
prone, since they cannot be interrupted (see above)
- Remove shared-writeable mapping support, which could deadlock the
machine
- Remove INVALIDATE userspace initiated request
- Update ABI to be independent of sizeof(long), so dual-size archs
don't cause problems
- Remove /sys/fs/fuse/version. Version checking is now done through
the fuse device
- Replace directory reading method on the kernel interface. Instead
of passing an open file descriptor to the kernel, send data through
the FUSE device, like all other operations.
============================================================================
What is new in 2.1
* Bug fixes
* Improved support for filesystems implementing a custom event-loop
* Add 'pkg-config' support
* Kernel module can be compiled separately
============================================================================
What is new in 1.9
* Lots of bugs fixed
* Minor modifications to the library API
* Improvements to the kernel/userspace interface
* Mounting by non-root made more secure
* Build shared library in addition to the static one
* Consolidated mount options
* Optimized reading under 2.6 kernels
* Direct I/O support
* Support file I/O on deleted files
* Extended attributes support
============================================================================
What is new in 1.3
* Thanks to user bugreports and stress testing with LTP and sfx-linux
a number of bugs were fixed, some quite serious.
* Fix compile problems with recent SuSE kernles
============================================================================
What is new in 1.2
* Fix mount problems on recent 2.6 kernels with SELinux enabled
* Fixed writing files lager than 2GBytes
* Other bugfixes
============================================================================
What is new in 1.1
* Support for the 2.6 kernels
* Support for exporting filesystem over NFS in 2.6 kernels
* Read efficiency improvements: read in 64k blocks instead of 4k
(Michael Grigoriev). Can be turned on with '-l' option of fusermount
* Lazy automatic unmount
* Added 'fsync()' VFS call to the FUSE interface
* Bugfixes
============================================================================
What is new in 1.0
* Cleanups and bugfixes
* Added 'release()' VFS call to the FUSE interface
* 64 bit file offsets (handling of > 4 GByte files)
* libfuse is now under LGPL
* New 'statfs' call (Mark Glines)
* Cleaned up mount procedure (mostly by Mark Glines)
NOTE: Binaries linked with with a previous version of libavfs may
not work with the new version of the fusermount program. In such
case recompile the program after installing the new libavfs library.
* Fix for problems under linux kernel 2.4.19
============================================================================
What is new in 0.95
* Optimized read/write operations. Raw throughput has increased to
about 60Mbyte/s on a Celeron/360
* Python bindings by Jeff Epler
* Perl bindings by Mark Glines
* Improved multithreaded operation
* Simplified library interface
* Bugfixes
============================================================================
What is new in 0.9:
* Everything

33
libfuse/README.NFS

@ -1,33 +0,0 @@
NFS exporting is supported in Linux kernels 2.6.27 or later.
You need to add an fsid=NNN option to /etc/exports to make exporting a
FUSE directory work.
Filesystem support
------------------
NFS exporting works to some extent on all fuse filesystems, but not
perfectly. This is due to the stateless nature of the protocol, the
server has no way of knowing whether the client is keeping a reference
to a file or not, and hence that file may be removed from the server's
cache. In that case there has to be a way to look up that object
using the inode number, otherwise an ESTALE error will be returned.
1) low-level interface
Filesystems need to implement special lookups for the names "." and
"..". The former may be requested on any inode, including
non-directories, while the latter is only requested for directories.
Otherwise these special lookups should behave identically to ordinary
lookups.
2) high-level interface
Because the high-level interface is path based, it is not possible to
delegate looking up by inode to the filesystem.
To work around this, currently a "noforget" option is provided, which
makes the library remember nodes forever. This will make the NFS
server happy, but also results in an ever growing memory footprint for
the filesystem. For this reason if the filesystem is large (or the
memory is small), then this option is not recommended.

108
libfuse/README.md

@ -1,108 +0,0 @@
libfuse
=======
Warning: unresolved security issue
----------------------------------
Be aware that FUSE has an unresolved security bug
([bug #15](https://github.com/libfuse/libfuse/issues/15)): the
permission check for accessing a cached directory is only done once
when the directory entry is first loaded into the cache. Subsequent
accesses will re-use the results of the first check, even if the
directory permissions have since changed, and even if the subsequent
access is made by a different user.
This bug needs to be fixed in the Linux kernel and has been known
since 2006 but unfortunately no fix has been applied yet. If you
depend on correct permission handling for FUSE file systems, the only
workaround is to completely disable caching of directory
entries. Alternatively, the severity of the bug can be somewhat
reduced by not using the `allow_other` mount option.
About
-----
FUSE (Filesystem in Userspace) is an interface for userspace programs
to export a filesystem to the Linux kernel. The FUSE project consists
of two components: the *fuse* kernel module (maintained in the regular
kernel repositories) and the *libfuse* userspace library (maintained
in this repository). libfuse provides the reference implementation
for communicating with the FUSE kernel module.
A FUSE file system is typically implemented as a standalone
application that links with libfuse. libfuse provides functions to
mount the file system, unmount it, read requests from the kernel, and
send responses back. libfuse offers two APIs: a "high-level",
synchronous API, and a "low-level" asynchronous API. In both cases,
incoming requests from the kernel are passed to the main program using
callbacks. When using the high-level API, the callbacks may work with
file names and paths instead of inodes, and processing of a request
finishes when the callback function returns. When using the low-level
API, the callbacks must work with inodes and responses must be sent
explicitly using a separate set of API functions.
Installation
------------
./configure
make -j8
make install
You may also need to add `/usr/local/lib` to `/etc/ld.so.conf` and/or
run *ldconfig*. If you're building from the git repository (instead of
using a release tarball), you also need to run `./makeconf.sh` to
create the `configure` script.
You'll also need a fuse kernel module (Linux kernels 2.6.14 or later
contain FUSE support).
For more details see the file `INSTALL`
Security implications
---------------------
If you run `make install`, the *fusermount* program is installed
set-user-id to root. This is done to allow normal users to mount
their own filesystem implementations.
There must however be some limitations, in order to prevent Bad User from
doing nasty things. Currently those limitations are:
- The user can only mount on a mountpoint, for which it has write
permission
- The mountpoint is not a sticky directory which isn't owned by the
user (like /tmp usually is)
- No other user (including root) can access the contents of the
mounted filesystem (though this can be relaxed by allowing the use
of the `allow_other` and `allow_root` mount options in `fuse.conf`)
Building your own filesystem
------------------------------
FUSE comes with several example file systems in the `examples`
directory. For example, the *fusexmp* example mirrors the contents of
the root directory under the mountpoint. Start from there and adapt
the code!
The documentation of the API functions and necessary callbacks is
mostly contained in the files `include/fuse.h` (for the high-level
API) and `include/fuse_lowlevel.h` (for the low-level API). An
autogenerated html version of the API is available in the `doc/html`
directory and at http://libfuse.github.io/doxygen.
Getting Help
------------
If you need help, please ask on the <fuse-devel@lists.sourceforge.net>
mailing list (subscribe at
https://lists.sourceforge.net/lists/listinfo/fuse-devel).
Please report any bugs on the GitHub issue tracker at
https://github.com/libfuse/main/issues.

11
libfuse/fuse.pc.in

@ -1,11 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: fuse
Description: Filesystem in Userspace
Version: @VERSION@
Libs: -L${libdir} -lfuse -pthread
Libs.private: @libfuse_libs@
Cflags: -I${includedir}/fuse -D_FILE_OFFSET_BITS=64

17
libfuse/include/Makefile.am

@ -1,17 +0,0 @@
## Process this file with automake to produce Makefile.in
fuseincludedir=$(includedir)/fuse
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

87
libfuse/include/cuse_lowlevel.h

@ -1,87 +0,0 @@
/*
CUSE: Character device in Userspace
Copyright (C) 2008-2009 SUSE Linux Products GmbH
Copyright (C) 2008-2009 Tejun Heo <tj@kernel.org>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB.
Read example/cusexmp.c for usages.
*/
#ifndef _CUSE_LOWLEVEL_H_
#define _CUSE_LOWLEVEL_H_
#ifndef FUSE_USE_VERSION
#define FUSE_USE_VERSION 29
#endif
#include "fuse_lowlevel.h"
#include <fcntl.h>
#include <sys/types.h>
#include <sys/uio.h>
#ifdef __cplusplus
extern "C" {
#endif
#define CUSE_UNRESTRICTED_IOCTL (1 << 0) /* use unrestricted ioctl */
struct fuse_session;
struct cuse_info {
unsigned dev_major;
unsigned dev_minor;
unsigned dev_info_argc;
const char **dev_info_argv;
unsigned flags;
};
/*
* Most ops behave almost identically to the matching fuse_lowlevel
* ops except that they don't take @ino.
*
* init_done : called after initialization is complete
* read/write : always direct IO, simultaneous operations allowed
* ioctl : might be in unrestricted mode depending on ci->flags
*/
struct cuse_lowlevel_ops {
void (*init) (void *userdata, struct fuse_conn_info *conn);
void (*init_done) (void *userdata);
void (*destroy) (void *userdata);
void (*open) (fuse_req_t req, struct fuse_file_info *fi);
void (*read) (fuse_req_t req, size_t size, off_t off,
struct fuse_file_info *fi);
void (*write) (fuse_req_t req, const char *buf, size_t size, off_t off,
struct fuse_file_info *fi);
void (*flush) (fuse_req_t req, struct fuse_file_info *fi);
void (*release) (fuse_req_t req, struct fuse_file_info *fi);
void (*fsync) (fuse_req_t req, int datasync, struct fuse_file_info *fi);
void (*ioctl) (fuse_req_t req, int cmd, void *arg,
struct fuse_file_info *fi, unsigned int flags,
const void *in_buf, size_t in_bufsz, size_t out_bufsz);
void (*poll) (fuse_req_t req, struct fuse_file_info *fi,
struct fuse_pollhandle *ph);
};
struct fuse_session *cuse_lowlevel_new(struct fuse_args *args,
const struct cuse_info *ci,
const struct cuse_lowlevel_ops *clop,
void *userdata);
struct fuse_session *cuse_lowlevel_setup(int argc, char *argv[],
const struct cuse_info *ci,
const struct cuse_lowlevel_ops *clop,
int *multithreaded, void *userdata);
void cuse_lowlevel_teardown(struct fuse_session *se);
int cuse_lowlevel_main(int argc, char *argv[], const struct cuse_info *ci,
const struct cuse_lowlevel_ops *clop, void *userdata);
#ifdef __cplusplus
}
#endif
#endif /* _CUSE_LOWLEVEL_H_ */

121
libfuse/include/fuse.h

@ -9,20 +9,6 @@
#ifndef _FUSE_H_ #ifndef _FUSE_H_
#define _FUSE_H_ #define _FUSE_H_
/** @file
*
* 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.
*/
#ifndef FUSE_USE_VERSION
#define FUSE_USE_VERSION 21
#endif
#include "fuse_common.h" #include "fuse_common.h"
#include "fuse_dirents.h" #include "fuse_dirents.h"
@ -668,12 +654,11 @@ struct fuse_context {
* @param user_data user data supplied in the context during the init() method * @param user_data user data supplied in the context during the init() method
* @return 0 on success, nonzero on failure * @return 0 on success, nonzero on failure
*/ */
/*
int fuse_main(int argc, char *argv[], const struct fuse_operations *op,
int fuse_main(int argc,
char *argv[],
const struct fuse_operations *op,
void *user_data); void *user_data);
*/
#define fuse_main(argc, argv, op, user_data) \
fuse_main_real(argc, argv, op, sizeof(*(op)), user_data)
/* ----------------------------------------------------------- * /* ----------------------------------------------------------- *
* More detailed API * * More detailed API *
@ -689,7 +674,7 @@ struct fuse_context {
* @param user_data user data supplied in the context during the init() method * @param user_data user data supplied in the context during the init() method
* @return the created FUSE handle * @return the created FUSE handle
*/ */
struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
struct fuse *fuse_new(int devfuse_fd, struct fuse_args *args,
const struct fuse_operations *op, size_t op_size, const struct fuse_operations *op, size_t op_size,
void *user_data); void *user_data);
@ -705,17 +690,6 @@ struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
*/ */
void fuse_destroy(struct fuse *f); void fuse_destroy(struct fuse *f);
/**
* FUSE event loop.
*
* Requests from the kernel are processed, and the appropriate
* operations are called.
*
* @param f the FUSE handle
* @return 0 if no error occurred, -1 otherwise
*/
int fuse_loop(struct fuse *f);
/** /**
* Exit from event loop * Exit from event loop
* *
@ -760,26 +734,6 @@ int fuse_loop_mt(struct fuse *f);
*/ */
struct fuse_context *fuse_get_context(void); struct fuse_context *fuse_get_context(void);
/**
* Get the current supplementary group IDs for the current request
*
* Similar to the getgroups(2) system call, except the return value is
* always the total number of group IDs, even if it is larger than the
* specified size.
*
* The current fuse kernel module in linux (as of 2.6.30) doesn't pass
* the group list to userspace, hence this function needs to parse
* "/proc/$TID/task/$TID/status" to get the group IDs.
*
* This feature may not be supported on all operating systems. In
* such a case this function will return -ENOSYS.
*
* @param size size of given array
* @param list array of group IDs to be filled in
* @return the total number of supplementary group IDs or -errno on failure
*/
int fuse_getgroups(int size, gid_t list[]);
/** /**
* Check if the current request has already been interrupted * Check if the current request has already been interrupted
* *
@ -787,16 +741,6 @@ int fuse_getgroups(int size, gid_t list[]);
*/ */
int fuse_interrupted(void); 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 * The real main function
* *
@ -1030,18 +974,12 @@ typedef void (*fuse_processor_t)(struct fuse *, struct fuse_cmd *, void *);
/** This is the part of fuse_main() before the event loop */ /** This is the part of fuse_main() before the event loop */
struct fuse *fuse_setup(int argc, char *argv[], struct fuse *fuse_setup(int argc, char *argv[],
const struct fuse_operations *op, size_t op_size, const struct fuse_operations *op, size_t op_size,
char **mountpoint, int *multithreaded,
char **mountpoint,
void *user_data); void *user_data);
/** This is the part of fuse_main() after the event loop */ /** This is the part of fuse_main() after the event loop */
void fuse_teardown(struct fuse *fuse, char *mountpoint); 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 /** Multi threaded event loop, which calls the custom command
processor function */ processor function */
int fuse_loop_mt_proc(struct fuse *f, fuse_processor_t proc, void *data); int fuse_loop_mt_proc(struct fuse *f, fuse_processor_t proc, void *data);
@ -1056,53 +994,6 @@ void fuse_set_getcontext_func(struct fuse_context *(*func)(void));
/** Get session from fuse object */ /** Get session from fuse object */
struct fuse_session *fuse_get_session(struct fuse *f); 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 #ifdef __cplusplus
} }
#endif #endif

22
libfuse/include/fuse_chan.h

@ -0,0 +1,22 @@
#pragma once
#include <stdint.h>
#include <sys/uio.h>
#define FUSE_CHAN_SPLICE_READ (1<<0)
#define FUSE_CHAN_SPLICE_WRITE (1<<1)
typedef struct fuse_chan_t fuse_chan_t;
struct fuse_chan_t
{
void *buf;
uint64_t bufsize;
int32_t fd;
int32_t splice_pipe[2];
uint32_t flags;
};
fuse_chan_t *fuse_chan_new(int32_t fd, uint32_t flags);
void fuse_chan_destroy(fuse_chan_t *ch);
int64_t fuse_chan_recv(fuse_chan_t *ch, char *buf, uint64_t size);
int64_t fuse_chan_send(fuse_chan_t *ch, const struct iovec iov[], uint64_t count);

17
libfuse/include/fuse_common.h

@ -33,8 +33,8 @@
#error Please add -D_FILE_OFFSET_BITS=64 to your compile flags! #error Please add -D_FILE_OFFSET_BITS=64 to your compile flags!
#endif #endif
#define FUSE_DEFAULT_MAX_PAGES_PER_REQ 32
#define FUSE_MAX_MAX_PAGES 256
#define FUSE_MSG_DEFAULT_PAGES 32
#define FUSE_MSG_MAX_PAGES 256
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -206,7 +206,7 @@ struct fuse_conn_info {
}; };
struct fuse_session; struct fuse_session;
struct fuse_chan;
typedef struct fuse_chan_t fuse_chan_t;
struct fuse_pollhandle; struct fuse_pollhandle;
/** /**
@ -219,7 +219,7 @@ struct fuse_pollhandle;
* @param args argument vector * @param args argument vector
* @return the communication channel on success, NULL on failure * @return the communication channel on success, NULL on failure
*/ */
struct fuse_chan *fuse_mount(const char *mountpoint,
int fuse_mount(const char *mountpoint,
struct fuse_args *args); struct fuse_args *args);
/** /**
@ -228,7 +228,8 @@ struct fuse_chan *fuse_mount(const char *mountpoint,
* @param mountpoint the mount point path * @param mountpoint the mount point path
* @param ch the communication channel * @param ch the communication channel
*/ */
void fuse_unmount(const char *mountpoint, struct fuse_chan *ch);
void fuse_unmount(const char *mountpoint,
int devfuse_fd);
/** /**
* Parse common options * Parse common options
@ -247,12 +248,12 @@ void fuse_unmount(const char *mountpoint, struct fuse_chan *ch);
* *
* @param args argument vector * @param args argument vector
* @param mountpoint the returned mountpoint, should be freed after use * @param mountpoint the returned mountpoint, should be freed after use
* @param multithreaded set to 1 unless the '-s' option is present
* @param foreground set to 1 if one of the relevant options is present * @param foreground set to 1 if one of the relevant options is present
* @return 0 on success, -1 on failure * @return 0 on success, -1 on failure
*/ */
int fuse_parse_cmdline(struct fuse_args *args, char **mountpoint,
int *multithreaded, int *foreground);
int fuse_parse_cmdline(struct fuse_args *args,
char **mountpoint,
int *foreground);
/** /**
* Go into the background * Go into the background

2
libfuse/include/fuse_common_compat.h

@ -9,6 +9,8 @@
/* these definitions provide source compatibility to prior versions. /* these definitions provide source compatibility to prior versions.
Do not include this file directly! */ Do not include this file directly! */
#include "fuse_opt.h"
struct fuse_file_info_compat { struct fuse_file_info_compat {
int flags; int flags;
unsigned long fh; unsigned long fh;

196
libfuse/include/fuse_compat.h

@ -1,196 +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 (*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 *, 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 (*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 *, 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);
struct fuse_operations_compat2 {
int (*getattr) (const char *, struct stat *);
int (*readlink) (const char *, char *, size_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 *, 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 (*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__ */

340
libfuse/include/fuse_lowlevel.h

@ -63,7 +63,7 @@ struct fuse_session;
* A communication channel, providing hooks for sending and receiving * A communication channel, providing hooks for sending and receiving
* messages * messages
*/ */
struct fuse_chan;
typedef struct fuse_chan_t fuse_chan_t;
/** Directory entry parameters supplied to fuse_reply_entry() */ /** Directory entry parameters supplied to fuse_reply_entry() */
struct fuse_entry_param { struct fuse_entry_param {
@ -1320,122 +1320,6 @@ int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov,
*/ */
int fuse_reply_poll(fuse_req_t req, unsigned revents); int fuse_reply_poll(fuse_req_t req, unsigned revents);
/* ----------------------------------------------------------- *
* Notification *
* ----------------------------------------------------------- */
/**
* Notify IO readiness event
*
* For more information, please read comment for poll operation.
*
* @param ph poll handle to notify IO readiness event for
*/
int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph);
/**
* Notify to invalidate cache for an inode
*
* @param ch the channel through which to send the invalidation
* @param ino the inode number
* @param off the offset in the inode where to start invalidating
* or negative to invalidate attributes only
* @param len the amount of cache to invalidate or 0 for all
* @return zero for success, -errno for failure
*/
int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, fuse_ino_t ino,
off_t off, off_t len);
/**
* Notify to invalidate parent attributes and the dentry matching
* parent/name
*
* To avoid a deadlock don't call this function from a filesystem operation and
* don't call it with a lock held that can also be held by a filesystem
* operation.
*
* @param ch the channel through which to send the invalidation
* @param parent inode number
* @param name file name
* @param namelen strlen() of file name
* @return zero for success, -errno for failure
*/
int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, fuse_ino_t parent,
const char *name, size_t namelen);
/**
* Notify to invalidate parent attributes and delete the dentry matching
* parent/name if the dentry's inode number matches child (otherwise it
* will invalidate the matching dentry).
*
* To avoid a deadlock don't call this function from a filesystem operation and
* don't call it with a lock held that can also be held by a filesystem
* operation.
*
* @param ch the channel through which to send the notification
* @param parent inode number
* @param child inode number
* @param name file name
* @param namelen strlen() of file name
* @return zero for success, -errno for failure
*/
int fuse_lowlevel_notify_delete(struct fuse_chan *ch,
fuse_ino_t parent, fuse_ino_t child,
const char *name, size_t namelen);
/**
* Store data to the kernel buffers
*
* Synchronously store data in the kernel buffers belonging to the
* given inode. The stored data is marked up-to-date (no read will be
* performed against it, unless it's invalidated or evicted from the
* cache).
*
* If the stored data overflows the current file size, then the size
* is extended, similarly to a write(2) on the filesystem.
*
* If this function returns an error, then the store wasn't fully
* completed, but it may have been partially completed.
*
* @param ch the channel through which to send the invalidation
* @param ino the inode number
* @param offset the starting offset into the file to store to
* @param bufv buffer vector
* @param flags flags controlling the copy
* @return zero for success, -errno for failure
*/
int fuse_lowlevel_notify_store(struct fuse_chan *ch, fuse_ino_t ino,
off_t offset, struct fuse_bufvec *bufv,
enum fuse_buf_copy_flags flags);
/**
* Retrieve data from the kernel buffers
*
* Retrieve data in the kernel buffers belonging to the given inode.
* If successful then the retrieve_reply() method will be called with
* the returned data.
*
* Only present pages are returned in the retrieve reply. Retrieving
* stops when it finds a non-present page and only data prior to that is
* returned.
*
* If this function returns an error, then the retrieve will not be
* completed and no reply will be sent.
*
* This function doesn't change the dirty state of pages in the kernel
* buffer. For dirty pages the write() method will be called
* regardless of having been retrieved previously.
*
* @param ch the channel through which to send the invalidation
* @param ino the inode number
* @param size the number of bytes to retrieve
* @param offset the starting offset into the file to retrieve from
* @param cookie user data to supply to the reply callback
* @return zero for success, -errno for failure
*/
int fuse_lowlevel_notify_retrieve(struct fuse_chan *ch, fuse_ino_t ino,
size_t size, off_t offset, void *cookie);
/* ----------------------------------------------------------- * /* ----------------------------------------------------------- *
* Utility functions * * Utility functions *
* ----------------------------------------------------------- */ * ----------------------------------------------------------- */
@ -1459,27 +1343,6 @@ void *fuse_req_userdata(fuse_req_t req);
*/ */
const struct fuse_ctx *fuse_req_ctx(fuse_req_t req); const struct fuse_ctx *fuse_req_ctx(fuse_req_t req);
/**
* Get the current supplementary group IDs for the specified request
*
* Similar to the getgroups(2) system call, except the return value is
* always the total number of group IDs, even if it is larger than the
* specified size.
*
* The current fuse kernel module in linux (as of 2.6.30) doesn't pass
* the group list to userspace, hence this function needs to parse
* "/proc/$TID/task/$TID/status" to get the group IDs.
*
* This feature may not be supported on all operating systems. In
* such a case this function will return -ENOSYS.
*
* @param req request handle
* @param size size of given array
* @param list array of group IDs to be filled in
* @return the total number of supplementary group IDs or -errno on failure
*/
int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[]);
/** /**
* Callback function for an interrupt * Callback function for an interrupt
* *
@ -1534,23 +1397,30 @@ struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
* Session interface * * Session interface *
* ----------------------------------------------------------- */ * ----------------------------------------------------------- */
void
fuse_ll_process_buf(void *data,
const struct fuse_buf *buf,
fuse_chan_t *ch);
int
fuse_ll_receive_buf(struct fuse_session *se,
struct fuse_buf *buf,
fuse_chan_t *ch);
int
fuse_ll_receive_buf2(struct fuse_buf *buf,
fuse_chan_t *ch);
int
fuse_ll_receive_buf3(struct fuse_session *se,
struct fuse_buf *buf,
fuse_chan_t *ch);
/** /**
* Session operations * Session operations
* *
* This is used in session creation * This is used in session creation
*/ */
struct fuse_session_ops { 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) * Hook for session exit and reset (optional)
* *
@ -1584,42 +1454,6 @@ struct fuse_session_ops {
*/ */
struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data); 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
* @param ch the channel
*/
void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch);
/**
* Remove a channel from a session
*
* If the channel is not assigned to a session, then this is a no-op
*
* @param ch the channel to remove
*/
void fuse_session_remove_chan(struct fuse_chan *ch);
/**
* 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 * Process a raw request
* *
@ -1629,7 +1463,7 @@ struct fuse_chan *fuse_session_next_chan(struct fuse_session *se,
* @param ch channel on which the request was received * @param ch channel on which the request was received
*/ */
void fuse_session_process(struct fuse_session *se, const char *buf, size_t len, void fuse_session_process(struct fuse_session *se, const char *buf, size_t len,
struct fuse_chan *ch);
fuse_chan_t *ch);
/** /**
* Process a raw request supplied in a generic buffer * Process a raw request supplied in a generic buffer
@ -1642,7 +1476,7 @@ void fuse_session_process(struct fuse_session *se, const char *buf, size_t len,
* @param ch channel on which the request was received * @param ch channel on which the request was received
*/ */
void fuse_session_process_buf(struct fuse_session *se, void fuse_session_process_buf(struct fuse_session *se,
const struct fuse_buf *buf, struct fuse_chan *ch);
const struct fuse_buf *buf, fuse_chan_t *ch);
/** /**
* Receive a raw request supplied in a generic buffer * Receive a raw request supplied in a generic buffer
@ -1656,8 +1490,9 @@ void fuse_session_process_buf(struct fuse_session *se,
* @param chp pointer to the channel * @param chp pointer to the channel
* @return the actual size of the raw request, or -errno on error * @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);
int fuse_session_receive_buf(struct fuse_session *se,
struct fuse_buf *buf,
fuse_chan_t *ch);
/** /**
* Destroy a session * Destroy a session
@ -1696,14 +1531,6 @@ int fuse_session_exited(struct fuse_session *se);
*/ */
void *fuse_session_data(struct fuse_session *se); void *fuse_session_data(struct fuse_session *se);
/**
* Enter a single threaded event loop
*
* @param se the session
* @return 0 on success, -1 on error
*/
int fuse_session_loop(struct fuse_session *se);
/** /**
* Enter a multi-threaded event loop * Enter a multi-threaded event loop
* *
@ -1712,125 +1539,6 @@ int fuse_session_loop(struct fuse_session *se);
*/ */
int fuse_session_loop_mt(struct fuse_session *se, const int threads); int fuse_session_loop_mt(struct fuse_session *se, const int threads);
/* ----------------------------------------------------------- *
* Channel interface *
* ----------------------------------------------------------- */
/**
* 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
* @return the file descriptor passed to fuse_chan_new()
*/
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 * * Compatibility stuff *
* ----------------------------------------------------------- */ * ----------------------------------------------------------- */

13
libfuse/include/fuse_lowlevel_compat.h

@ -141,15 +141,4 @@ struct fuse_session *fuse_lowlevel_new_compat(const char *opts,
#endif /* __FreeBSD__ || __NetBSD__ */ #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);
int fuse_chan_receive(fuse_chan_t *ch, char *buf, size_t size);

42
libfuse/lib/Makefile.am

@ -1,42 +0,0 @@
## Process this file with automake to produce Makefile.in
AUTOMAKE_OPTIONS = subdir-objects
AM_CPPFLAGS = -I$(top_srcdir)/include -DFUSERMOUNT_DIR=\"$(bindir)\" \
-D_FILE_OFFSET_BITS=64 -D_REENTRANT -DFUSE_USE_VERSION=26
lib_LTLIBRARIES = libfuse.la libulockmgr.la
if BSD
mount_source = mount_bsd.c
else
mount_source = mount.c mount_util.c mount_util.h
endif
libfuse_la_SOURCES = \
fuse.c \
fuse_i.h \
fuse_kern_chan.c \
fuse_loop.c \
fuse_loop_mt.c \
fuse_lowlevel.c \
fuse_misc.h \
fuse_mt.c \
fuse_opt.c \
fuse_session.c \
fuse_signals.c \
buffer.c \
cuse_lowlevel.c \
helper.c \
$(mount_source)
libfuse_la_LDFLAGS = -pthread @libfuse_libs@ -version-number 2:9:7 \
-Wl,--version-script,$(srcdir)/fuse_versionscript
if NETBSD
libfuse_la_LIBADD = -lperfuse -lpuffs
endif
libulockmgr_la_SOURCES = ulockmgr.c
libulockmgr_la_LDFLAGS = -pthread -version-number 1:0:1
EXTRA_DIST = fuse_versionscript

371
libfuse/lib/cuse_lowlevel.c

@ -1,371 +0,0 @@
/*
CUSE: Character device in Userspace
Copyright (C) 2008 SUSE Linux Products GmbH
Copyright (C) 2008 Tejun Heo <teheo@suse.de>
This program can be distributed under the terms of the GNU LGPLv2.
See the file COPYING.LIB.
*/
#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>
#include <stdlib.h>
#include <stddef.h>
#include <errno.h>
#include <unistd.h>
struct cuse_data {
struct cuse_lowlevel_ops clop;
unsigned max_read;
unsigned dev_major;
unsigned dev_minor;
unsigned flags;
unsigned dev_info_len;
char dev_info[];
};
static struct cuse_lowlevel_ops *req_clop(fuse_req_t req)
{
return &req->f->cuse_data->clop;
}
static void cuse_fll_open(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi)
{
(void)ino;
req_clop(req)->open(req, fi);
}
static void cuse_fll_read(fuse_req_t req, fuse_ino_t ino, size_t size,
off_t off, struct fuse_file_info *fi)
{
(void)ino;
req_clop(req)->read(req, size, off, fi);
}
static void cuse_fll_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
size_t size, off_t off, struct fuse_file_info *fi)
{
(void)ino;
req_clop(req)->write(req, buf, size, off, fi);
}
static void cuse_fll_flush(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi)
{
(void)ino;
req_clop(req)->flush(req, fi);
}
static void cuse_fll_release(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi)
{
(void)ino;
req_clop(req)->release(req, fi);
}
static void cuse_fll_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
struct fuse_file_info *fi)
{
(void)ino;
req_clop(req)->fsync(req, datasync, fi);
}
static void cuse_fll_ioctl(fuse_req_t req, fuse_ino_t ino, int cmd, void *arg,
struct fuse_file_info *fi, unsigned int flags,
const void *in_buf, size_t in_bufsz, size_t out_bufsz)
{
(void)ino;
req_clop(req)->ioctl(req, cmd, arg, fi, flags, in_buf, in_bufsz,
out_bufsz);
}
static void cuse_fll_poll(fuse_req_t req, fuse_ino_t ino,
struct fuse_file_info *fi, struct fuse_pollhandle *ph)
{
(void)ino;
req_clop(req)->poll(req, fi, ph);
}
static size_t cuse_pack_info(int argc, const char **argv, char *buf)
{
size_t size = 0;
int i;
for (i = 0; i < argc; i++) {
size_t len;
len = strlen(argv[i]) + 1;
size += len;
if (buf) {
memcpy(buf, argv[i], len);
buf += len;
}
}
return size;
}
static struct cuse_data *cuse_prep_data(const struct cuse_info *ci,
const struct cuse_lowlevel_ops *clop)
{
struct cuse_data *cd;
size_t dev_info_len;
dev_info_len = cuse_pack_info(ci->dev_info_argc, ci->dev_info_argv,
NULL);
if (dev_info_len > CUSE_INIT_INFO_MAX) {
fprintf(stderr, "cuse: dev_info (%zu) too large, limit=%u\n",
dev_info_len, CUSE_INIT_INFO_MAX);
return NULL;
}
cd = calloc(1, sizeof(*cd) + dev_info_len);
if (!cd) {
fprintf(stderr, "cuse: failed to allocate cuse_data\n");
return NULL;
}
memcpy(&cd->clop, clop, sizeof(cd->clop));
cd->max_read = 131072;
cd->dev_major = ci->dev_major;
cd->dev_minor = ci->dev_minor;
cd->dev_info_len = dev_info_len;
cd->flags = ci->flags;
cuse_pack_info(ci->dev_info_argc, ci->dev_info_argv, cd->dev_info);
return cd;
}
struct fuse_session *cuse_lowlevel_new(struct fuse_args *args,
const struct cuse_info *ci,
const struct cuse_lowlevel_ops *clop,
void *userdata)
{
struct fuse_lowlevel_ops lop;
struct cuse_data *cd;
struct fuse_session *se;
struct fuse_ll *ll;
cd = cuse_prep_data(ci, clop);
if (!cd)
return NULL;
memset(&lop, 0, sizeof(lop));
lop.init = clop->init;
lop.destroy = clop->destroy;
lop.open = clop->open ? cuse_fll_open : NULL;
lop.read = clop->read ? cuse_fll_read : NULL;
lop.write = clop->write ? cuse_fll_write : NULL;
lop.flush = clop->flush ? cuse_fll_flush : NULL;
lop.release = clop->release ? cuse_fll_release : NULL;
lop.fsync = clop->fsync ? cuse_fll_fsync : NULL;
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);
if (!se) {
free(cd);
return NULL;
}
ll = se->data;
ll->cuse_data = cd;
return se;
}
static int cuse_reply_init(fuse_req_t req, struct cuse_init_out *arg,
char *dev_info, unsigned dev_info_len)
{
struct iovec iov[3];
iov[1].iov_base = arg;
iov[1].iov_len = sizeof(struct cuse_init_out);
iov[2].iov_base = dev_info;
iov[2].iov_len = dev_info_len;
return fuse_send_reply_iov_nofree(req, 0, iov, 3);
}
void cuse_lowlevel_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
struct fuse_init_in *arg = (struct fuse_init_in *) 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);
struct cuse_lowlevel_ops *clop = req_clop(req);
(void) nodeid;
if (f->debug) {
fprintf(stderr, "CUSE_INIT: %u.%u\n", arg->major, arg->minor);
fprintf(stderr, "flags=0x%08x\n", arg->flags);
}
f->conn.proto_major = arg->major;
f->conn.proto_minor = arg->minor;
f->conn.capable = 0;
f->conn.want = 0;
if (arg->major < 7) {
fprintf(stderr, "cuse: unsupported protocol version: %u.%u\n",
arg->major, arg->minor);
fuse_reply_err(req, EPROTO);
return;
}
if (bufsize < FUSE_MIN_READ_BUFFER) {
fprintf(stderr, "cuse: warning: buffer size too small: %zu\n",
bufsize);
bufsize = FUSE_MIN_READ_BUFFER;
}
bufsize -= 4096;
if (bufsize < f->conn.max_write)
f->conn.max_write = bufsize;
f->got_init = 1;
if (f->op.init)
f->op.init(f->userdata, &f->conn);
memset(&outarg, 0, sizeof(outarg));
outarg.major = FUSE_KERNEL_VERSION;
outarg.minor = FUSE_KERNEL_MINOR_VERSION;
outarg.flags = cd->flags;
outarg.max_read = cd->max_read;
outarg.max_write = f->conn.max_write;
outarg.dev_major = cd->dev_major;
outarg.dev_minor = cd->dev_minor;
if (f->debug) {
fprintf(stderr, " CUSE_INIT: %u.%u\n",
outarg.major, outarg.minor);
fprintf(stderr, " flags=0x%08x\n", outarg.flags);
fprintf(stderr, " max_read=0x%08x\n", outarg.max_read);
fprintf(stderr, " max_write=0x%08x\n", outarg.max_write);
fprintf(stderr, " dev_major=%u\n", outarg.dev_major);
fprintf(stderr, " dev_minor=%u\n", outarg.dev_minor);
fprintf(stderr, " dev_info: %.*s\n", cd->dev_info_len,
cd->dev_info);
}
cuse_reply_init(req, &outarg, cd->dev_info, cd->dev_info_len);
if (clop->init_done)
clop->init_done(f->userdata);
fuse_free_req(req);
}
struct fuse_session *cuse_lowlevel_setup(int argc, char *argv[],
const struct cuse_info *ci,
const struct cuse_lowlevel_ops *clop,
int *multithreaded, void *userdata)
{
const char *devname = "/dev/cuse";
static const struct fuse_opt kill_subtype_opts[] = {
FUSE_OPT_KEY("subtype=", FUSE_OPT_KEY_DISCARD),
FUSE_OPT_END
};
struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
struct fuse_session *se;
struct fuse_chan *ch;
int fd;
int foreground;
int res;
res = fuse_parse_cmdline(&args, NULL, multithreaded, &foreground);
if (res == -1)
goto err_args;
res = fuse_opt_parse(&args, NULL, kill_subtype_opts, NULL);
if (res == -1)
goto err_args;
/*
* Make sure file descriptors 0, 1 and 2 are open, otherwise chaos
* would ensue.
*/
do {
fd = open("/dev/null", O_RDWR);
if (fd > 2)
close(fd);
} while (fd >= 0 && fd <= 2);
se = cuse_lowlevel_new(&args, ci, clop, userdata);
fuse_opt_free_args(&args);
if (se == NULL)
goto err_args;
fd = open(devname, O_RDWR);
if (fd == -1) {
if (errno == ENODEV || errno == ENOENT)
fprintf(stderr, "cuse: device not found, try 'modprobe cuse' first\n");
else
fprintf(stderr, "cuse: failed to open %s: %s\n",
devname, strerror(errno));
goto err_se;
}
ch = fuse_kern_chan_new(fd);
if (!ch) {
close(fd);
goto err_se;
}
fuse_session_add_chan(se, ch);
res = fuse_set_signal_handlers(se);
if (res == -1)
goto err_se;
res = fuse_daemonize(foreground);
if (res == -1)
goto err_sig;
return se;
err_sig:
fuse_remove_signal_handlers(se);
err_se:
fuse_session_destroy(se);
err_args:
fuse_opt_free_args(&args);
return NULL;
}
void cuse_lowlevel_teardown(struct fuse_session *se)
{
fuse_remove_signal_handlers(se);
fuse_session_destroy(se);
}
int cuse_lowlevel_main(int argc, char *argv[], const struct cuse_info *ci,
const struct cuse_lowlevel_ops *clop, void *userdata)
{
struct fuse_session *se;
int multithreaded;
int res;
se = cuse_lowlevel_setup(argc, argv, ci, clop, &multithreaded,
userdata);
if (se == NULL)
return 1;
if (multithreaded)
res = fuse_session_loop_mt(se, 0);
else
res = fuse_session_loop(se);
cuse_lowlevel_teardown(se);
if (res == -1)
return 1;
return 0;
}

496
libfuse/lib/fuse.c

@ -11,14 +11,15 @@
#define _GNU_SOURCE #define _GNU_SOURCE
#include "config.h" #include "config.h"
#include "fuse_chan.h"
#include "fuse_common_compat.h"
#include "fuse_dirents.h"
#include "fuse_i.h" #include "fuse_i.h"
#include "fuse_kernel.h"
#include "fuse_lowlevel.h" #include "fuse_lowlevel.h"
#include "fuse_opt.h"
#include "fuse_misc.h" #include "fuse_misc.h"
#include "fuse_common_compat.h"
#include "fuse_compat.h"
#include "fuse_kernel.h"
#include "fuse_dirents.h"
#include "fuse_opt.h"
#include <assert.h> #include <assert.h>
#include <dlfcn.h> #include <dlfcn.h>
@ -54,7 +55,8 @@
#define NODE_TABLE_MIN_SIZE 8192 #define NODE_TABLE_MIN_SIZE 8192
struct fuse_config {
struct fuse_config
{
unsigned int uid; unsigned int uid;
unsigned int gid; unsigned int gid;
unsigned int umask; unsigned int umask;
@ -74,10 +76,10 @@ struct fuse_config {
int threads; int threads;
}; };
struct fuse_fs {
struct fuse_fs
{
struct fuse_operations op; struct fuse_operations op;
void *user_data; void *user_data;
int compat;
int debug; int debug;
}; };
@ -1381,129 +1383,6 @@ static inline void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,
fuse_do_prepare_interrupt(req, d); 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) int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf)
{ {
fuse_get_context()->private_data = fs->user_data; fuse_get_context()->private_data = fs->user_data;
@ -1637,7 +1516,7 @@ int fuse_fs_release(struct fuse_fs *fs, const char *path,
fi->flush ? "+flush" : "", fi->flush ? "+flush" : "",
(unsigned long long) fi->fh, fi->flags); (unsigned long long) fi->fh, fi->flags);
return fuse_compat_release(fs, path, fi);
return fs->op.release(path, fi);
} else { } else {
return 0; return 0;
} }
@ -1654,7 +1533,7 @@ int fuse_fs_opendir(struct fuse_fs *fs, const char *path,
fprintf(stderr, "opendir flags: 0x%x %s\n", fi->flags, fprintf(stderr, "opendir flags: 0x%x %s\n", fi->flags,
path); path);
err = fuse_compat_opendir(fs, path, fi);
err = fs->op.opendir(path,fi);
if (fs->debug && !err) if (fs->debug && !err)
fprintf(stderr, " opendir[%lli] flags: 0x%x %s\n", fprintf(stderr, " opendir[%lli] flags: 0x%x %s\n",
@ -1677,7 +1556,7 @@ int fuse_fs_open(struct fuse_fs *fs, const char *path,
fprintf(stderr, "open flags: 0x%x %s\n", fi->flags, fprintf(stderr, "open flags: 0x%x %s\n", fi->flags,
path); path);
err = fuse_compat_open(fs, path, fi);
err = fs->op.open(path,fi);
if (fs->debug && !err) if (fs->debug && !err)
fprintf(stderr, " open[%lli] flags: 0x%x %s\n", fprintf(stderr, " open[%lli] flags: 0x%x %s\n",
@ -1892,19 +1771,24 @@ int fuse_fs_flush(struct fuse_fs *fs, const char *path,
} }
} }
int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf)
int
fuse_fs_statfs(struct fuse_fs *fs,
const char *path,
struct statvfs *buf)
{ {
fuse_get_context()->private_data = fs->user_data; fuse_get_context()->private_data = fs->user_data;
if (fs->op.statfs) {
if(fs->debug) if(fs->debug)
fprintf(stderr, "statfs %s\n", path); fprintf(stderr, "statfs %s\n", path);
return fuse_compat_statfs(fs, path, buf);
} else {
if(fs->op.statfs == NULL)
{
buf->f_namemax = 255; buf->f_namemax = 255;
buf->f_bsize = 512; buf->f_bsize = 512;
return 0; return 0;
} }
return fs->op.statfs(path,buf);
} }
int fuse_fs_releasedir(struct fuse_fs *fs, const char *path, int fuse_fs_releasedir(struct fuse_fs *fs, const char *path,
@ -2482,10 +2366,22 @@ static struct fuse *req_fuse_prepare(fuse_req_t req)
return c->ctx.fuse; return c->ctx.fuse;
} }
static inline void reply_err(fuse_req_t req, int err)
{
/* fuse_reply_err() uses non-negated errno values */ /* fuse_reply_err() uses non-negated errno values */
fuse_reply_err(req, -err);
static
inline
void
reply_err(fuse_req_t req_,
int err_)
{
fuse_reply_err(req_,-err_);
}
static
inline
void
reply_ENOMEM(fuse_req_t req_)
{
fuse_reply_err(req_,ENOMEM);
} }
static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e, static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
@ -3338,7 +3234,10 @@ static struct fuse_dh *get_dirhandle(const struct fuse_file_info *llfi,
return dh; return dh;
} }
static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
static
void
fuse_lib_opendir(fuse_req_t req,
fuse_ino_t ino,
struct fuse_file_info *llfi) struct fuse_file_info *llfi)
{ {
struct fuse *f = req_fuse_prepare(req); struct fuse *f = req_fuse_prepare(req);
@ -3349,10 +3248,8 @@ static void fuse_lib_opendir(fuse_req_t req, fuse_ino_t ino,
int err; int err;
dh = (struct fuse_dh*)calloc(1,sizeof(struct fuse_dh)); dh = (struct fuse_dh*)calloc(1,sizeof(struct fuse_dh));
if (dh == NULL) {
reply_err(req, -ENOMEM);
return;
}
if(dh == NULL)
return reply_ENOMEM(req);
fuse_dirents_init(&dh->d); fuse_dirents_init(&dh->d);
fuse_mutex_init(&dh->lock); fuse_mutex_init(&dh->lock);
@ -3648,22 +3545,24 @@ static int common_getxattr(struct fuse *f, fuse_req_t req, fuse_ino_t ino,
static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name, static void fuse_lib_getxattr(fuse_req_t req, fuse_ino_t ino, const char *name,
size_t size) size_t size)
{ {
struct fuse *f = req_fuse_prepare(req);
int res; int res;
struct fuse *f = req_fuse_prepare(req);
if (size) {
if(size)
{
char *value = (char*)malloc(size); char *value = (char*)malloc(size);
if (value == NULL) {
reply_err(req, -ENOMEM);
return;
}
if(value == NULL)
return reply_ENOMEM(req);
res = common_getxattr(f, req, ino, name, value, size); res = common_getxattr(f, req, ino, name, value, size);
if(res > 0) if(res > 0)
fuse_reply_buf(req, value, res); fuse_reply_buf(req, value, res);
else else
reply_err(req, res); reply_err(req, res);
free(value); free(value);
} else {
}
else
{
res = common_getxattr(f, req, ino, name, NULL, 0); res = common_getxattr(f, req, ino, name, NULL, 0);
if(res >= 0) if(res >= 0)
fuse_reply_xattr(req, res); fuse_reply_xattr(req, res);
@ -3694,19 +3593,21 @@ static void fuse_lib_listxattr(fuse_req_t req, fuse_ino_t ino, size_t size)
struct fuse *f = req_fuse_prepare(req); struct fuse *f = req_fuse_prepare(req);
int res; int res;
if (size) {
if(size)
{
char *list = (char*)malloc(size); char *list = (char*)malloc(size);
if (list == NULL) {
reply_err(req, -ENOMEM);
return;
}
if(list == NULL)
return reply_ENOMEM(req);
res = common_listxattr(f, req, ino, list, size); res = common_listxattr(f, req, ino, list, size);
if (res > 0) if (res > 0)
fuse_reply_buf(req, list, res); fuse_reply_buf(req, list, res);
else else
reply_err(req, res); reply_err(req, res);
free(list); free(list);
} else {
}
else
{
res = common_listxattr(f, req, ino, NULL, 0); res = common_listxattr(f, req, ino, NULL, 0);
if (res >= 0) if (res >= 0)
fuse_reply_xattr(req, res); fuse_reply_xattr(req, res);
@ -4225,7 +4126,8 @@ int fuse_clean_cache(struct fuse *f)
return clean_delay(f); return clean_delay(f);
} }
static struct fuse_lowlevel_ops fuse_path_ops = {
static struct fuse_lowlevel_ops fuse_path_ops =
{
.init = fuse_lib_init, .init = fuse_lib_init,
.destroy = fuse_lib_destroy, .destroy = fuse_lib_destroy,
.lookup = fuse_lib_lookup, .lookup = fuse_lib_lookup,
@ -4269,175 +4171,29 @@ static struct fuse_lowlevel_ops fuse_path_ops = {
.copy_file_range = fuse_lib_copy_file_range, .copy_file_range = fuse_lib_copy_file_range,
}; };
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) int fuse_exited(struct fuse *f)
{ {
return fuse_session_exited(f->se); return fuse_session_exited(f->se);
} }
struct fuse_session *fuse_get_session(struct fuse *f)
struct fuse_session*
fuse_get_session(struct fuse *f)
{ {
return f->se; 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 pollfd fds = {
.fd = fuse_chan_fd(ch),
.events = POLLIN
};
if (!buf) {
fprintf(stderr, "fuse: failed to allocate read buffer\n");
return -1;
}
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);
if (now.tv_sec < next_clean)
timeout = next_clean - now.tv_sec;
else
timeout = 0;
res = poll(&fds, 1, timeout * 1000);
if (res == -1) {
if (errno == -EINTR)
continue;
else
break;
} else if (res > 0) {
res = fuse_session_receive_buf(se, &fbuf, &tmpch);
if (res == -EINTR)
continue;
if (res <= 0)
break;
fuse_session_process_buf(se, &fbuf, tmpch);
} else {
timeout = fuse_clean_cache(f);
curr_time(&now);
next_clean = now.tv_sec + timeout;
}
}
free(buf);
fuse_session_reset(se);
return res < 0 ? -1 : 0;
}
int fuse_loop(struct fuse *f)
{
if (!f)
return -1;
if (lru_enabled(f))
return fuse_session_loop_remember(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)
void
fuse_exit(struct fuse *f)
{ {
fuse_session_exit(f->se); fuse_session_exit(f->se);
} }
struct fuse_context *fuse_get_context(void)
{
return &fuse_get_context_internal()->ctx;
}
/*
* 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)
struct
fuse_context*
fuse_get_context(void)
{ {
return &fuse_get_context_internal()->ctx; return &fuse_get_context_internal()->ctx;
} }
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);
}
int fuse_interrupted(void) int fuse_interrupted(void)
{ {
@ -4456,13 +4212,15 @@ enum {
#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v } #define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
static const struct fuse_opt fuse_lib_opts[] = {
static const struct fuse_opt fuse_lib_opts[] =
{
FUSE_OPT_KEY("-h", KEY_HELP), FUSE_OPT_KEY("-h", KEY_HELP),
FUSE_OPT_KEY("--help", KEY_HELP), FUSE_OPT_KEY("--help", KEY_HELP),
FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP), FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP), FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
FUSE_LIB_OPT("debug", debug, 1), FUSE_LIB_OPT("debug", debug, 1),
FUSE_LIB_OPT("-d", debug, 1), FUSE_LIB_OPT("-d", debug, 1),
FUSE_LIB_OPT("use_ino", use_ino, 1),
FUSE_LIB_OPT("umask=", set_mode, 1), FUSE_LIB_OPT("umask=", set_mode, 1),
FUSE_LIB_OPT("umask=%o", umask, 0), FUSE_LIB_OPT("umask=%o", umask, 0),
FUSE_LIB_OPT("uid=", set_uid, 1), FUSE_LIB_OPT("uid=", set_uid, 1),
@ -4478,13 +4236,13 @@ static const struct fuse_opt fuse_lib_opts[] = {
FUSE_LIB_OPT("intr", intr, 1), FUSE_LIB_OPT("intr", intr, 1),
FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0), FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0),
FUSE_LIB_OPT("threads=%d", threads, 0), FUSE_LIB_OPT("threads=%d", threads, 0),
FUSE_LIB_OPT("use_ino", use_ino, 1),
FUSE_OPT_END FUSE_OPT_END
}; };
static void fuse_lib_help(void) static void fuse_lib_help(void)
{ {
fprintf(stderr, fprintf(stderr,
" -o use_ino let filesystem set inode numbers\n"
" -o umask=M set file permissions (octal)\n" " -o umask=M set file permissions (octal)\n"
" -o uid=N set file owner\n" " -o uid=N set file owner\n"
" -o gid=N set file group\n" " -o gid=N set file group\n"
@ -4516,12 +4274,6 @@ static int fuse_lib_opt_proc(void *data, const char *arg, int key,
return 1; 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) static int fuse_init_intr_signal(int signum, int *installed)
{ {
struct sigaction old_sa; struct sigaction old_sa;
@ -4623,9 +4375,10 @@ void fuse_stop_cleanup_thread(struct fuse *f)
} }
} }
struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
struct fuse *
fuse_new_common(int devfuse_fd, struct fuse_args *args,
const struct fuse_operations *op, const struct fuse_operations *op,
size_t op_size, void *user_data, int compat)
size_t op_size, void *user_data)
{ {
struct fuse *f; struct fuse *f;
struct node *root; struct node *root;
@ -4645,7 +4398,6 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
if (!fs) if (!fs)
goto out_free; goto out_free;
fs->compat = compat;
f->fs = fs; f->fs = fs;
f->nullpath_ok = fs->op.flag_nullpath_ok; f->nullpath_ok = fs->op.flag_nullpath_ok;
f->conf.nopath = fs->op.flag_nopath; f->conf.nopath = fs->op.flag_nopath;
@ -4671,17 +4423,12 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
fuse_lib_opt_proc) == -1) fuse_lib_opt_proc) == -1)
goto out_free_fs; goto out_free_fs;
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_common(args, &llop, sizeof(llop), f);
if (f->se == NULL) { if (f->se == NULL) {
goto out_free_fs; goto out_free_fs;
} }
fuse_session_add_chan(f->se, ch);
f->se->devfuse_fd = devfuse_fd;
if (f->conf.debug) { if (f->conf.debug) {
fprintf(stderr, "nullpath_ok: %i\n", f->nullpath_ok); fprintf(stderr, "nullpath_ok: %i\n", f->nullpath_ok);
@ -4748,11 +4495,11 @@ out:
return NULL; return NULL;
} }
struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args,
struct fuse *fuse_new(int devfuse_fd, struct fuse_args *args,
const struct fuse_operations *op, size_t op_size, const struct fuse_operations *op, size_t op_size,
void *user_data) void *user_data)
{ {
return fuse_new_common(ch, args, op, op_size, user_data, 0);
return fuse_new_common(devfuse_fd, args, op, op_size, user_data);
} }
void fuse_destroy(struct fuse *f) void fuse_destroy(struct fuse *f)
@ -4799,91 +4546,6 @@ void fuse_destroy(struct fuse *f)
fuse_delete_context_key(); 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;
}
#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");
int int
fuse_config_num_threads(const struct fuse *fuse_) fuse_config_num_threads(const struct fuse *fuse_)
{ {

248
libfuse/lib/fuse_chan.c

@ -0,0 +1,248 @@
#define _GNU_SOURCE
#include "fuse_chan.h"
#include "fuse_lowlevel.h"
#include "fuse_kernel.h"
#include "sys.h"
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/ioctl.h>
#include <unistd.h>
static const char DEV_FUSE[] = "/dev/fuse";
static
void*
aligned_mem(const uint64_t size_)
{
int rv;
void *mem;
int pagesize;
pagesize = sys_get_pagesize();
rv = posix_memalign(&mem,pagesize,size_);
if(rv == 0)
return mem;
errno = rv;
return NULL;
}
static
int
clone_devfuse_fd(const int devfuse_fd_)
{
#ifdef FUSE_DEV_IOC_CLONE
int rv;
int clone_fd;
clone_fd = open(DEV_FUSE,O_RDWR|O_CLOEXEC);
if(clone_fd == -1)
return devfuse_fd_;
rv = ioctl(clone_fd,FUSE_DEV_IOC_CLONE,&devfuse_fd_);
if(rv == -1)
{
perror("fuse: failed to clone /dev/fuse");
close(clone_fd);
return devfuse_fd_;
}
return clone_fd;
#else
return devfuse_fd_;
#endif
}
int
fuse_msg_bufsize(void)
{
int bufsize;
bufsize = ((FUSE_MSG_MAX_PAGES + 1) * sys_get_pagesize());
return bufsize;
}
fuse_chan_t*
fuse_chan_new(int32_t devfuse_fd_,
uint32_t flags_)
{
int rv;
int bufsize;
fuse_chan_t *ch;
ch = (fuse_chan_t*)calloc(1,sizeof(fuse_chan_t));
if(ch == NULL)
{
fprintf(stderr, "fuse: failed to allocate channel memory\n");
return NULL;
}
bufsize = fuse_msg_bufsize();
ch->fd = clone_devfuse_fd(devfuse_fd_);
ch->buf = aligned_mem(bufsize);
ch->bufsize = bufsize;
ch->flags = flags_;
if(flags_ & (FUSE_CHAN_SPLICE_READ|FUSE_CHAN_SPLICE_WRITE))
{
rv = sys_alloc_pipe(ch->splice_pipe,bufsize);
if(rv == -1)
ch->flags &= ~(FUSE_CHAN_SPLICE_READ|FUSE_CHAN_SPLICE_WRITE);
}
return ch;
}
static
int64_t
fuse_chan_recv_splice(fuse_chan_t *ch_,
char *buf_,
uint64_t size_)
{
int64_t rv;
struct iovec iov;
restart_splice:
rv = splice(ch_->fd,NULL,ch_->splice_pipe[1],NULL,size_,SPLICE_F_MOVE);
switch((rv == -1) ? errno : 0)
{
case 0:
break;
case ENOENT:
case EINTR:
case EAGAIN:
goto restart_splice;
case ENODEV:
return 0;
default:
return -errno;
}
iov.iov_base = buf_;
iov.iov_len = rv;
restart_vmsplice:
rv = vmsplice(ch_->splice_pipe[0],&iov,1,SPLICE_F_MOVE);
switch((rv == -1) ? errno : 0)
{
case 0:
break;
case ENOENT:
case EINTR:
case EAGAIN:
goto restart_vmsplice;
case ENODEV:
return 0;
default:
return -errno;
}
return rv;
}
static
int
fuse_chan_recv_read(fuse_chan_t *ch_,
char *buf_,
uint64_t size_)
{
int64_t rv;
restart:
rv = read(ch_->fd,buf_,size_);
switch((rv == -1) ? errno : 0)
{
case 0:
break;
case ENOENT:
case EINTR:
case EAGAIN:
goto restart;
case ENODEV:
return 0;
default:
return -errno;
}
if(rv < sizeof(struct fuse_in_header))
{
fprintf(stderr, "fuse: short read on fuse device\n");
return -EIO;
}
return rv;
}
int64_t
fuse_chan_recv(fuse_chan_t *ch_,
char *buf_,
size_t size_)
{
if(ch_->flags & FUSE_CHAN_SPLICE_READ)
return fuse_chan_recv_splice(ch_,buf_,size_);
return fuse_chan_recv_read(ch_,buf_,size_);
}
static
int64_t
fuse_chan_send_write(fuse_chan_t *ch_,
const struct iovec iov_[],
size_t count_)
{
int64_t rv;
if(iov_ == NULL)
return 0;
rv = writev(ch_->fd,iov_,count_);
if(rv == -1)
return -errno;
return rv;
}
static
int64_t
fuse_chan_send_splice(fuse_chan_t *ch_,
const struct iovec iov_[],
size_t count_)
{
int64_t rv;
rv = vmsplice(ch_->splice_pipe[1],iov_,count_,SPLICE_F_MOVE);
if(rv == -1)
return -errno;
rv = splice(ch_->splice_pipe[0],NULL,ch_->fd,NULL,rv,SPLICE_F_MOVE);
return rv;
}
int64_t
fuse_chan_send(fuse_chan_t *ch,
const struct iovec iov[],
size_t count)
{
if(ch->flags & FUSE_CHAN_SPLICE_WRITE)
return fuse_chan_send_splice(ch,iov,count);
return fuse_chan_send_write(ch,iov,count);
}
void
fuse_chan_destroy(fuse_chan_t *ch)
{
close(ch->fd);
if(ch->flags & (FUSE_CHAN_SPLICE_READ|FUSE_CHAN_SPLICE_WRITE))
{
close(ch->splice_pipe[0]);
close(ch->splice_pipe[1]);
}
free(ch->buf);
free(ch);
}

56
libfuse/lib/fuse_dev.c

@ -0,0 +1,56 @@
#include "fuse_dev.h"
#include <stdlib.h>
#include <sys/uio.h>
#include <unistd.h>
fuse_dev_t*
fuse_dev_alloc(void)
{
return calloc(1,sizeof(fuse_dev_t));
}
void
fuse_dev_free(fuse_dev_t *fd_)
{
if(fd_)
free(fd_);
}
fuse_dev_t*
fuse_dev_clone(fuse_dev_t *fd_)
{
return fd_;
}
int64_t
fuse_dev_read(const fuse_dev_t *fd_,
void *buf_,
uint64_t count_)
{
int64_t rv;
rv = read(fd_->fd,buf_,count_);
return rv;
}
int64_t
fuse_dev_write(const fuse_dev_t *fd_,
const struct iovec *iov_,
int iovcnt_)
{
int64_t rv;
rv = writev(fd_->fd,iov_,iovcnt_);
return rv;
}
int64_t
fuse_dev_write_splice(const fuse_dev_t* fd_,
const struct iovec *iov_,
int iovcnt_)
{
}

40
libfuse/lib/fuse_dev.h

@ -0,0 +1,40 @@
/*
ISC License
Copyright (c) 2020, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include <stdint.h>
#include <sys/uio.h>
typedef struct fuse_dev_s fuse_dev_t;
struct fuse_dev_s
{
int fd;
};
fuse_dev_t* fuse_dev_alloc(void);
void fuse_dev_free(fuse_dev_t *fd);
fuse_dev_t* fuse_dev_clone(fuse_dev_t *fd);
int64_t fuse_dev_read(const fuse_dev_t *fd,
void *buf,
uint64_t count);
int64_t fuse_dev_write(const fuse_dev_t *fd,
const struct iovec *iov,
int iovcnt);

48
libfuse/lib/fuse_i.h

@ -9,32 +9,25 @@
#include "fuse.h" #include "fuse.h"
#include "fuse_lowlevel.h" #include "fuse_lowlevel.h"
struct fuse_chan;
typedef struct fuse_chan_t fuse_chan_t;
struct fuse_ll; struct fuse_ll;
struct fuse_session {
struct fuse_session
{
struct fuse_session_ops op; 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; void *data;
volatile int exited; volatile int exited;
struct fuse_chan *ch;
int devfuse_fd;
}; };
struct fuse_req {
struct fuse_req
{
struct fuse_ll *f; struct fuse_ll *f;
uint64_t unique; uint64_t unique;
int ctr; int ctr;
pthread_mutex_t lock; pthread_mutex_t lock;
struct fuse_ctx ctx; struct fuse_ctx ctx;
struct fuse_chan *ch;
fuse_chan_t *ch;
int interrupted; int interrupted;
unsigned int ioctl_64bit : 1; unsigned int ioctl_64bit : 1;
union { union {
@ -50,7 +43,8 @@ struct fuse_req {
struct fuse_req *prev; struct fuse_req *prev;
}; };
struct fuse_notify_req {
struct fuse_notify_req
{
uint64_t unique; uint64_t unique;
void (*reply)(struct fuse_notify_req *, fuse_req_t, fuse_ino_t, void (*reply)(struct fuse_notify_req *, fuse_req_t, fuse_ino_t,
const void *, const struct fuse_buf *); const void *, const struct fuse_buf *);
@ -58,7 +52,8 @@ struct fuse_notify_req {
struct fuse_notify_req *prev; struct fuse_notify_req *prev;
}; };
struct fuse_ll {
struct fuse_ll
{
int debug; int debug;
int allow_root; int allow_root;
int atomic_o_trunc; int atomic_o_trunc;
@ -73,7 +68,6 @@ struct fuse_ll {
int no_splice_read; int no_splice_read;
struct fuse_lowlevel_ops op; struct fuse_lowlevel_ops op;
int got_init; int got_init;
struct cuse_data *cuse_data;
void *userdata; void *userdata;
uid_t owner; uid_t owner;
struct fuse_conn_info conn; struct fuse_conn_info conn;
@ -87,26 +81,25 @@ struct fuse_ll {
struct fuse_notify_req notify_list; struct fuse_notify_req notify_list;
}; };
struct fuse_cmd {
struct fuse_cmd
{
char *buf; char *buf;
size_t buflen; size_t buflen;
struct fuse_chan *ch;
fuse_chan_t *ch;
}; };
struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
struct fuse *fuse_new_common(int devfuse_fd, struct fuse_args *args,
const struct fuse_operations *op, const struct fuse_operations *op,
size_t op_size, void *user_data, int compat);
size_t op_size, void *user_data);
int fuse_sync_compat_args(struct fuse_args *args); 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, struct fuse_session *fuse_lowlevel_new_common(struct fuse_args *args,
const struct fuse_lowlevel_ops *op, const struct fuse_lowlevel_ops *op,
size_t op_size, void *userdata); size_t op_size, void *userdata);
void fuse_kern_unmount_compat22(const char *mountpoint); void fuse_kern_unmount_compat22(const char *mountpoint);
int fuse_chan_clearfd(struct fuse_chan *ch);
int fuse_chan_clearfd(fuse_chan_t *ch);
void fuse_kern_unmount(const char *mountpoint, int fd); void fuse_kern_unmount(const char *mountpoint, int fd);
int fuse_kern_mount(const char *mountpoint, struct fuse_args *args); int fuse_kern_mount(const char *mountpoint, struct fuse_args *args);
@ -120,11 +113,6 @@ struct fuse *fuse_setup_common(int argc, char *argv[],
const struct fuse_operations *op, const struct fuse_operations *op,
size_t op_size, size_t op_size,
char **mountpoint, 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);
void *user_data);
int fuse_start_thread(pthread_t *thread_id, void *(*func)(void *), void *arg); int fuse_start_thread(pthread_t *thread_id, void *(*func)(void *), void *arg);

103
libfuse/lib/fuse_kern_chan.c

@ -1,103 +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);
}
struct fuse_chan *
fuse_kern_chan_new(int fd_)
{
long pagesize;
size_t bufsize;
struct fuse_chan_ops op =
{
.receive = fuse_kern_chan_receive,
.send = fuse_kern_chan_send,
.destroy = fuse_kern_chan_destroy,
};
pagesize = sysconf(_SC_PAGESIZE);
bufsize = ((FUSE_MAX_MAX_PAGES * pagesize) + 0x1000);
return fuse_chan_new(&op, fd_, bufsize, NULL);
}

46
libfuse/lib/fuse_loop.c

@ -1,46 +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 <stdio.h>
#include <stdlib.h>
#include <errno.h>
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*)calloc(bufsize,1);
if (!buf) {
fprintf(stderr, "fuse: failed to allocate read buffer\n");
return -1;
}
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);
if (res == -EINTR)
continue;
if (res <= 0)
break;
fuse_session_process_buf(se, &fbuf, tmpch);
}
free(buf);
fuse_session_reset(se);
return res < 0 ? -1 : 0;
}

117
libfuse/lib/fuse_loop_mt.c

@ -6,43 +6,47 @@
See the file COPYING.LIB. See the file COPYING.LIB.
*/ */
#include "fuse_chan.h"
#include "fuse_i.h"
#include "fuse_kernel.h"
#include "fuse_lowlevel.h" #include "fuse_lowlevel.h"
#include "fuse_misc.h" #include "fuse_misc.h"
#include "fuse_kernel.h"
#include "fuse_i.h"
#include <errno.h>
#include <semaphore.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <unistd.h>
#include <signal.h>
#include <semaphore.h>
#include <errno.h>
#include <sys/time.h> #include <sys/time.h>
#include <unistd.h> #include <unistd.h>
/* Environment var controlling the thread stack size */ /* Environment var controlling the thread stack size */
#define ENVNAME_THREAD_STACK "FUSE_THREAD_STACK" #define ENVNAME_THREAD_STACK "FUSE_THREAD_STACK"
struct fuse_worker {
struct fuse_worker
{
struct fuse_worker *prev; struct fuse_worker *prev;
struct fuse_worker *next; struct fuse_worker *next;
pthread_t thread_id;
size_t bufsize;
char *buf;
struct fuse_mt *mt; struct fuse_mt *mt;
pthread_t thread_id;
fuse_chan_t *ch;
}; };
struct fuse_mt {
struct fuse_mt
{
struct fuse_session *se; struct fuse_session *se;
struct fuse_chan *prevch;
struct fuse_worker main; struct fuse_worker main;
sem_t finish; sem_t finish;
int exit; int exit;
int error; int error;
}; };
static void list_add_worker(struct fuse_worker *w, struct fuse_worker *next)
static
void
list_add_worker(struct fuse_worker *w,
struct fuse_worker *next)
{ {
struct fuse_worker *prev = next->prev; struct fuse_worker *prev = next->prev;
w->next = next; w->next = next;
@ -51,7 +55,9 @@ static void list_add_worker(struct fuse_worker *w, struct fuse_worker *next)
next->prev = w; next->prev = w;
} }
static void list_del_worker(struct fuse_worker *w)
static
void
list_del_worker(struct fuse_worker *w)
{ {
struct fuse_worker *prev = w->prev; struct fuse_worker *prev = w->prev;
struct fuse_worker *next = w->next; struct fuse_worker *next = w->next;
@ -61,36 +67,40 @@ static void list_del_worker(struct fuse_worker *w)
static int fuse_loop_start_thread(struct fuse_mt *mt); static int fuse_loop_start_thread(struct fuse_mt *mt);
static void *fuse_do_work(void *data)
static
void*
fuse_do_work(void *data)
{ {
struct fuse_worker *w = (struct fuse_worker *) data;
struct fuse_mt *mt = w->mt;
struct fuse_mt *mt;
fuse_chan_t *ch;
struct fuse_worker *w;
while (!fuse_session_exited(mt->se)) {
struct fuse_chan *ch = mt->prevch;
struct fuse_buf fbuf = {
.mem = w->buf,
.size = w->bufsize,
};
w = (struct fuse_worker*)data;
mt = w->mt;
ch = w->ch;
while(!fuse_session_exited(mt->se))
{
int res; int res;
struct fuse_buf fbuf = { .mem = ch->buf, .size = ch->bufsize };
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL); pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL);
res = fuse_session_receive_buf(mt->se, &fbuf, &ch);
res = fuse_ll_receive_buf(mt->se,&fbuf,ch);
pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL); pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, NULL);
if(res == -EINTR) if(res == -EINTR)
continue; continue;
if (res <= 0) {
if (res < 0) {
if(res == 0)
break;
if(res < 0)
{
fuse_session_exit(mt->se); fuse_session_exit(mt->se);
mt->error = -1; mt->error = -1;
}
break; break;
} }
if(mt->exit) if(mt->exit)
return NULL; return NULL;
fuse_session_process_buf(mt->se, &fbuf, ch);
fuse_ll_process_buf(mt->se->data,&fbuf,ch);
} }
sem_post(&mt->finish); sem_post(&mt->finish);
@ -98,11 +108,14 @@ static void *fuse_do_work(void *data)
return NULL; return NULL;
} }
int fuse_start_thread(pthread_t *thread_id, void *(*func)(void *), void *arg)
int
fuse_start_thread(pthread_t *thread_id,
void *(*func)(void *),
void *arg)
{ {
int res;
sigset_t oldset; sigset_t oldset;
sigset_t newset; sigset_t newset;
int res;
pthread_attr_t attr; pthread_attr_t attr;
char *stack_size; char *stack_size;
@ -122,7 +135,9 @@ int fuse_start_thread(pthread_t *thread_id, void *(*func)(void *), void *arg)
res = pthread_create(thread_id, &attr, func, arg); res = pthread_create(thread_id, &attr, func, arg);
pthread_sigmask(SIG_SETMASK, &oldset, NULL); pthread_sigmask(SIG_SETMASK, &oldset, NULL);
pthread_attr_destroy(&attr); pthread_attr_destroy(&attr);
if (res != 0) {
if(res != 0)
{
fprintf(stderr, "fuse: error creating thread: %s\n", fprintf(stderr, "fuse: error creating thread: %s\n",
strerror(res)); strerror(res));
return -1; return -1;
@ -131,30 +146,38 @@ int fuse_start_thread(pthread_t *thread_id, void *(*func)(void *), void *arg)
return 0; return 0;
} }
static int fuse_loop_start_thread(struct fuse_mt *mt)
static
int
fuse_loop_start_thread(struct fuse_mt *mt)
{ {
int res; int res;
struct fuse_worker *w = malloc(sizeof(struct fuse_worker));
if (!w) {
struct fuse_worker *w;
w = malloc(sizeof(struct fuse_worker));
if(!w)
{
fprintf(stderr, "fuse: failed to allocate worker structure\n"); fprintf(stderr, "fuse: failed to allocate worker structure\n");
return -1; return -1;
} }
memset(w,0,sizeof(struct fuse_worker)); memset(w,0,sizeof(struct fuse_worker));
w->bufsize = fuse_chan_bufsize(mt->prevch);
w->buf = calloc(w->bufsize,1);
w->mt = mt; w->mt = mt;
if (!w->buf) {
fprintf(stderr, "fuse: failed to allocate read buffer\n");
w->ch = fuse_chan_new(mt->se->devfuse_fd,FUSE_CHAN_SPLICE_READ|FUSE_CHAN_SPLICE_WRITE);
if(w->ch == NULL)
{
fprintf(stderr, "fuse: failed to allocate fuse channel\n");
free(w); free(w);
return -1; return -1;
} }
res = fuse_start_thread(&w->thread_id, fuse_do_work, w); res = fuse_start_thread(&w->thread_id, fuse_do_work, w);
if (res == -1) {
free(w->buf);
if(res == -1)
{
free(w); free(w);
return -1; return -1;
} }
list_add_worker(w,&mt->main); list_add_worker(w,&mt->main);
return 0; return 0;
@ -164,7 +187,7 @@ static void fuse_join_worker(struct fuse_worker *w)
{ {
pthread_join(w->thread_id, NULL); pthread_join(w->thread_id, NULL);
list_del_worker(w); list_del_worker(w);
free(w->buf);
fuse_chan_destroy(w->ch);
free(w); free(w);
} }
@ -178,7 +201,7 @@ static int number_of_threads(void)
} }
int fuse_session_loop_mt(struct fuse_session *se, int fuse_session_loop_mt(struct fuse_session *se,
const int _threads)
const int threads_)
{ {
int i; int i;
int err; int err;
@ -188,15 +211,14 @@ int fuse_session_loop_mt(struct fuse_session *se,
memset(&mt, 0, sizeof(struct fuse_mt)); memset(&mt, 0, sizeof(struct fuse_mt));
mt.se = se; mt.se = se;
mt.prevch = fuse_session_next_chan(se, NULL);
mt.error = 0; mt.error = 0;
mt.main.thread_id = pthread_self(); mt.main.thread_id = pthread_self();
mt.main.prev = mt.main.next = &mt.main; mt.main.prev = mt.main.next = &mt.main;
sem_init(&mt.finish, 0, 0); sem_init(&mt.finish, 0, 0);
threads = ((_threads > 0) ? _threads : number_of_threads());
if(_threads < 0)
threads /= -_threads;
threads = ((threads_ > 0) ? threads_ : number_of_threads());
if(threads_ < 0)
threads /= -threads_;
if(threads == 0) if(threads == 0)
threads = 1; threads = 1;
@ -204,7 +226,8 @@ int fuse_session_loop_mt(struct fuse_session *se,
for(i = 0; (i < threads) && !err; i++) for(i = 0; (i < threads) && !err; i++)
err = fuse_loop_start_thread(&mt); err = fuse_loop_start_thread(&mt);
if (!err) {
if(!err)
{
/* sem_wait() is interruptible */ /* sem_wait() is interruptible */
while(!fuse_session_exited(se)) while(!fuse_session_exited(se))
sem_wait(&mt.finish); sem_wait(&mt.finish);

914
libfuse/lib/fuse_lowlevel.c
File diff suppressed because it is too large
View File

92
libfuse/lib/fuse_mt.c

@ -16,96 +16,6 @@
#include <pthread.h> #include <pthread.h>
#include <assert.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_config_num_threads(f));
fuse_session_destroy(se);
return res;
}
int fuse_loop_mt(struct fuse *f) int fuse_loop_mt(struct fuse *f)
{ {
if (f == NULL) if (f == NULL)
@ -120,5 +30,3 @@ int fuse_loop_mt(struct fuse *f)
fuse_stop_cleanup_thread(f); fuse_stop_cleanup_thread(f);
return res; return res;
} }
FUSE_SYMVER(".symver fuse_loop_mt_proc,__fuse_loop_mt@");

185
libfuse/lib/fuse_session.c

@ -6,30 +6,20 @@
See the file COPYING.LIB See the file COPYING.LIB
*/ */
#include "fuse_i.h"
#include "fuse_misc.h"
#include "fuse_chan.h"
#include "fuse_common_compat.h" #include "fuse_common_compat.h"
#include "fuse_i.h"
#include "fuse_kernel.h"
#include "fuse_lowlevel_compat.h" #include "fuse_lowlevel_compat.h"
#include "fuse_misc.h"
#include <assert.h>
#include <errno.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#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;
};
#include <sys/ioctl.h>
#include <unistd.h>
struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data) struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data)
{ {
@ -46,74 +36,10 @@ struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data)
return se; return se;
} }
void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch)
{
assert(se->ch == NULL);
assert(ch->se == NULL);
se->ch = ch;
ch->se = se;
}
void fuse_session_remove_chan(struct fuse_chan *ch)
{
struct fuse_session *se = ch->se;
if (se) {
assert(se->ch == ch);
se->ch = NULL;
ch->se = NULL;
}
}
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)
{
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;
}
void fuse_session_destroy(struct fuse_session *se) void fuse_session_destroy(struct fuse_session *se)
{ {
if (se->op.destroy) if (se->op.destroy)
se->op.destroy(se->data); se->op.destroy(se->data);
if (se->ch != NULL)
fuse_chan_destroy(se->ch);
free(se); free(se);
} }
@ -143,98 +69,3 @@ void *fuse_session_data(struct fuse_session *se)
{ {
return se->data; return se->data;
} }
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 *ch = (struct fuse_chan *) malloc(sizeof(*ch));
if (ch == NULL) {
fprintf(stderr, "fuse: failed to allocate channel\n");
return NULL;
}
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);
free(ch);
}
#ifndef __FreeBSD__
FUSE_SYMVER(".symver fuse_chan_new_compat24,fuse_chan_new@FUSE_2.4");
#endif

207
libfuse/lib/fuse_versionscript

@ -1,207 +0,0 @@
FUSE_2.2 {
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;
fuse_reply_err;
fuse_reply_none;
fuse_reply_readlink;
fuse_reply_write;
fuse_reply_xattr;
fuse_req_userdata;
fuse_session_add_chan;
fuse_session_destroy;
fuse_session_exit;
fuse_session_exited;
fuse_session_loop;
fuse_session_loop_mt;
fuse_session_new;
fuse_session_next_chan;
fuse_session_process;
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;
fuse_opt_free_args;
fuse_opt_match;
fuse_parse_cmdline;
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_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;
fuse_fs_chown;
fuse_fs_create;
fuse_fs_destroy;
fuse_fs_fgetattr;
fuse_fs_flush;
fuse_fs_fsync;
fuse_fs_fsyncdir;
fuse_fs_ftruncate;
fuse_fs_getattr;
fuse_fs_getxattr;
fuse_fs_init;
fuse_fs_link;
fuse_fs_listxattr;
fuse_fs_lock;
fuse_fs_mkdir;
fuse_fs_mknod;
fuse_fs_new;
fuse_fs_open;
fuse_fs_opendir;
fuse_fs_read;
fuse_fs_readdir;
fuse_fs_readlink;
fuse_fs_release;
fuse_fs_releasedir;
fuse_fs_removexattr;
fuse_fs_rename;
fuse_fs_rmdir;
fuse_fs_setxattr;
fuse_fs_statfs;
fuse_fs_symlink;
fuse_fs_truncate;
fuse_fs_unlink;
fuse_fs_utimens;
fuse_fs_write;
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;
cuse_lowlevel_teardown;
fuse_fs_ioctl;
fuse_fs_poll;
fuse_get_context;
fuse_getgroups;
fuse_lowlevel_notify_inval_entry;
fuse_lowlevel_notify_inval_inode;
fuse_lowlevel_notify_poll;
fuse_notify_poll;
fuse_opt_add_opt_escaped;
fuse_pollhandle_destroy;
fuse_reply_ioctl;
fuse_reply_ioctl_iov;
fuse_reply_ioctl_retry;
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;
fuse_fs_write_buf;
fuse_lowlevel_notify_retrieve;
fuse_lowlevel_notify_store;
fuse_reply_data;
fuse_session_process_buf;
fuse_session_receive_buf;
fuse_start_cleanup_thread;
fuse_stop_cleanup_thread;
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;

208
libfuse/lib/helper.c

@ -7,11 +7,11 @@
*/ */
#include "config.h" #include "config.h"
#include "fuse_chan.h"
#include "fuse_i.h" #include "fuse_i.h"
#include "fuse_lowlevel.h"
#include "fuse_misc.h" #include "fuse_misc.h"
#include "fuse_opt.h" #include "fuse_opt.h"
#include "fuse_lowlevel.h"
#include "fuse_common_compat.h"
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@ -78,7 +78,6 @@ static void helper_help(void)
"FUSE options:\n" "FUSE options:\n"
" -d -o debug enable debug output (implies -f)\n" " -d -o debug enable debug output (implies -f)\n"
" -f foreground operation\n" " -f foreground operation\n"
" -s disable multi-threaded operation\n"
"\n" "\n"
); );
} }
@ -150,7 +149,6 @@ static int add_default_subtype(const char *progname, struct fuse_args *args)
int int
fuse_parse_cmdline(struct fuse_args *args_, fuse_parse_cmdline(struct fuse_args *args_,
char **mountpoint_, char **mountpoint_,
int *multithreaded_,
int *foreground_) int *foreground_)
{ {
int res; int res;
@ -177,8 +175,6 @@ fuse_parse_cmdline(struct fuse_args *args_,
else else
free(hopts.mountpoint); free(hopts.mountpoint);
if(multithreaded_)
*multithreaded_ = !hopts.singlethread;
if(foreground_) if(foreground_)
*foreground_ = hopts.foreground; *foreground_ = hopts.foreground;
@ -242,11 +238,10 @@ int fuse_daemonize(int foreground)
} }
static static
struct fuse_chan *
int
fuse_mount_common(const char *mountpoint_, fuse_mount_common(const char *mountpoint_,
struct fuse_args *args_) struct fuse_args *args_)
{ {
struct fuse_chan *ch;
int fd; int fd;
/* /*
@ -260,65 +255,55 @@ fuse_mount_common(const char *mountpoint_,
close(fd); close(fd);
} while(fd >= 0 && fd <= 2); } while(fd >= 0 && fd <= 2);
fd = fuse_mount_compat25(mountpoint_, args_);
fd = fuse_kern_mount(mountpoint_,args_);
if(fd == -1) if(fd == -1)
return NULL;
ch = fuse_kern_chan_new(fd);
if(!ch)
fuse_kern_unmount(mountpoint_, fd);
return -1;
return ch;
return fd;
} }
struct fuse_chan *
int
fuse_mount(const char *mountpoint_, fuse_mount(const char *mountpoint_,
struct fuse_args *args_) struct fuse_args *args_)
{ {
return fuse_mount_common(mountpoint_,args_); return fuse_mount_common(mountpoint_,args_);
} }
static void fuse_unmount_common(const char *mountpoint, struct fuse_chan *ch)
{
if (mountpoint) {
int fd = ch ? fuse_chan_clearfd(ch) : -1;
fuse_kern_unmount(mountpoint, fd);
if (ch)
fuse_chan_destroy(ch);
}
}
void fuse_unmount(const char *mountpoint, struct fuse_chan *ch)
void
fuse_unmount(const char *mountpoint,
int devfuse_fd)
{ {
fuse_unmount_common(mountpoint, ch);
if(mountpoint == NULL)
return;
fuse_kern_unmount(mountpoint,devfuse_fd);
} }
struct fuse *fuse_setup_common(int argc, char *argv[],
struct fuse *
fuse_setup_common(int argc,
char *argv[],
const struct fuse_operations *op, const struct fuse_operations *op,
size_t op_size, size_t op_size,
char **mountpoint, char **mountpoint,
int *multithreaded,
int *fd,
void *user_data,
int compat)
void *user_data)
{ {
struct fuse_args args = FUSE_ARGS_INIT(argc, argv); struct fuse_args args = FUSE_ARGS_INIT(argc, argv);
struct fuse_chan *ch;
struct fuse *fuse;
int foreground;
int res; int res;
int foreground;
int devfuse_fd;
struct fuse *fuse;
res = fuse_parse_cmdline(&args, mountpoint, multithreaded, &foreground);
res = fuse_parse_cmdline(&args, mountpoint, &foreground);
if (res == -1) if (res == -1)
return NULL; return NULL;
ch = fuse_mount_common(*mountpoint, &args);
if (!ch) {
devfuse_fd = fuse_mount_common(*mountpoint, &args);
if(devfuse_fd == -1)
{
fuse_opt_free_args(&args); fuse_opt_free_args(&args);
goto err_free; goto err_free;
} }
fuse = fuse_new_common(ch, &args, op, op_size, user_data, compat);
fuse = fuse_new_common(devfuse_fd, &args, op, op_size, user_data);
fuse_opt_free_args(&args); fuse_opt_free_args(&args);
if (fuse == NULL) if (fuse == NULL)
goto err_unmount; goto err_unmount;
@ -331,13 +316,10 @@ struct fuse *fuse_setup_common(int argc, char *argv[],
if (res == -1) if (res == -1)
goto err_unmount; goto err_unmount;
if (fd)
*fd = fuse_chan_fd(ch);
return fuse; return fuse;
err_unmount: err_unmount:
fuse_unmount_common(*mountpoint, ch);
fuse_kern_unmount(*mountpoint,devfuse_fd);
if(fuse) if(fuse)
fuse_destroy(fuse); fuse_destroy(fuse);
err_free: err_free:
@ -347,45 +329,43 @@ err_free:
struct fuse *fuse_setup(int argc, char *argv[], struct fuse *fuse_setup(int argc, char *argv[],
const struct fuse_operations *op, size_t op_size, const struct fuse_operations *op, size_t op_size,
char **mountpoint, int *multithreaded, void *user_data)
char **mountpoint, void *user_data)
{ {
return fuse_setup_common(argc, argv, op, op_size, mountpoint,
multithreaded, NULL, user_data, 0);
return fuse_setup_common(argc, argv, op, op_size, mountpoint, user_data);
} }
static void fuse_teardown_common(struct fuse *fuse, char *mountpoint) static void fuse_teardown_common(struct fuse *fuse, char *mountpoint)
{ {
struct fuse_session *se = fuse_get_session(fuse); struct fuse_session *se = fuse_get_session(fuse);
struct fuse_chan *ch = fuse_session_next_chan(se, NULL);
fuse_remove_signal_handlers(se); fuse_remove_signal_handlers(se);
fuse_unmount_common(mountpoint, ch);
fuse_kern_unmount(mountpoint,se->devfuse_fd);
fuse_destroy(fuse); fuse_destroy(fuse);
free(mountpoint); free(mountpoint);
} }
void fuse_teardown(struct fuse *fuse, char *mountpoint)
void
fuse_teardown(struct fuse *fuse,
char *mountpoint)
{ {
fuse_teardown_common(fuse,mountpoint); fuse_teardown_common(fuse,mountpoint);
} }
static int fuse_main_common(int argc, char *argv[],
static
int
fuse_main_common(int argc, char *argv[],
const struct fuse_operations *op, size_t op_size, const struct fuse_operations *op, size_t op_size,
void *user_data, int compat)
void *user_data)
{ {
struct fuse *fuse; struct fuse *fuse;
char *mountpoint; char *mountpoint;
int multithreaded;
int res; int res;
fuse = fuse_setup_common(argc, argv, op, op_size, &mountpoint, fuse = fuse_setup_common(argc, argv, op, op_size, &mountpoint,
&multithreaded, NULL, user_data, compat);
user_data);
if(fuse == NULL) if(fuse == NULL)
return 1; return 1;
if (multithreaded)
res = fuse_loop_mt(fuse); res = fuse_loop_mt(fuse);
else
res = fuse_loop(fuse);
fuse_teardown_common(fuse,mountpoint); fuse_teardown_common(fuse,mountpoint);
if (res == -1) if (res == -1)
@ -394,118 +374,24 @@ static int fuse_main_common(int argc, char *argv[],
return 0; return 0;
} }
int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
int
fuse_main_real(int argc, char *argv[],
const struct fuse_operations *op,
size_t op_size, void *user_data) size_t op_size, void *user_data)
{ {
return fuse_main_common(argc, argv, op, op_size, user_data, 0);
return fuse_main_common(argc, argv, op, op_size, user_data);
} }
#undef fuse_main
int fuse_main(void);
int fuse_main(void)
int
fuse_main(int argc,
char *argv[],
const struct fuse_operations *op,
void *user_data)
{ {
fprintf(stderr, "fuse_main(): This function does not exist\n");
return -1;
return fuse_main_real(argc, argv, op, sizeof(*(op)), user_data);
} }
int fuse_version(void) int fuse_version(void)
{ {
return FUSE_VERSION; 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");

17
libfuse/lib/mount_generic.c

@ -69,7 +69,6 @@ struct mount_opts {
int flags; int flags;
int nonempty; int nonempty;
int auto_unmount; int auto_unmount;
int blkdev;
char *fsname; char *fsname;
char *subtype; char *subtype;
char *subtype_opt; char *subtype_opt;
@ -84,7 +83,6 @@ static const struct fuse_opt fuse_mount_opts[] = {
FUSE_MOUNT_OPT("allow_other", allow_other), FUSE_MOUNT_OPT("allow_other", allow_other),
FUSE_MOUNT_OPT("allow_root", allow_root), FUSE_MOUNT_OPT("allow_root", allow_root),
FUSE_MOUNT_OPT("nonempty", nonempty), FUSE_MOUNT_OPT("nonempty", nonempty),
FUSE_MOUNT_OPT("blkdev", blkdev),
FUSE_MOUNT_OPT("auto_unmount", auto_unmount), FUSE_MOUNT_OPT("auto_unmount", auto_unmount),
FUSE_MOUNT_OPT("fsname=%s", fsname), FUSE_MOUNT_OPT("fsname=%s", fsname),
FUSE_MOUNT_OPT("subtype=%s", subtype), FUSE_MOUNT_OPT("subtype=%s", subtype),
@ -92,7 +90,6 @@ static const struct fuse_opt fuse_mount_opts[] = {
FUSE_OPT_KEY("allow_root", KEY_ALLOW_ROOT), FUSE_OPT_KEY("allow_root", KEY_ALLOW_ROOT),
FUSE_OPT_KEY("nonempty", KEY_FUSERMOUNT_OPT), FUSE_OPT_KEY("nonempty", KEY_FUSERMOUNT_OPT),
FUSE_OPT_KEY("auto_unmount", KEY_FUSERMOUNT_OPT), FUSE_OPT_KEY("auto_unmount", KEY_FUSERMOUNT_OPT),
FUSE_OPT_KEY("blkdev", KEY_FUSERMOUNT_OPT),
FUSE_OPT_KEY("fsname=", KEY_FUSERMOUNT_OPT), FUSE_OPT_KEY("fsname=", KEY_FUSERMOUNT_OPT),
FUSE_OPT_KEY("subtype=", KEY_SUBTYPE_OPT), FUSE_OPT_KEY("subtype=", KEY_SUBTYPE_OPT),
FUSE_OPT_KEY("large_read", KEY_KERN_OPT), FUSE_OPT_KEY("large_read", KEY_KERN_OPT),
@ -490,7 +487,7 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo,
goto out_close; goto out_close;
} }
strcpy(type, mo->blkdev ? "fuseblk" : "fuse");
strcpy(type,"fuse");
if (mo->subtype) { if (mo->subtype) {
strcat(type, "."); strcat(type, ".");
strcat(type, mo->subtype); strcat(type, mo->subtype);
@ -501,11 +498,9 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo,
res = mount(source, mnt, type, mo->flags, mo->kernel_opts); res = mount(source, mnt, type, mo->flags, mo->kernel_opts);
if (res == -1 && errno == ENODEV && mo->subtype) { if (res == -1 && errno == ENODEV && mo->subtype) {
/* Probably missing subtype support */ /* Probably missing subtype support */
strcpy(type, mo->blkdev ? "fuseblk" : "fuse");
strcpy(type,"fuse");
if (mo->fsname) { if (mo->fsname) {
if (!mo->blkdev)
sprintf(source, "%s#%s", mo->subtype,
mo->fsname);
sprintf(source, "%s#%s", mo->subtype, mo->fsname);
} else { } else {
strcpy(source, type); strcpy(source, type);
} }
@ -520,12 +515,8 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo,
res = -2; res = -2;
} else { } else {
int errno_save = errno; int errno_save = errno;
if (mo->blkdev && errno == ENODEV &&
!fuse_mnt_check_fuseblk())
fprintf(stderr, fprintf(stderr,
"fuse: 'fuseblk' support missing\n");
else
fprintf(stderr, "fuse: mount failed: %s\n",
"fuse: mount failed: %s\n",
strerror(errno_save)); strerror(errno_save));
} }

17
libfuse/lib/mount_util.c

@ -344,20 +344,3 @@ int fuse_mnt_check_empty(const char *progname, const char *mnt,
} }
return 0; return 0;
} }
int fuse_mnt_check_fuseblk(void)
{
char buf[256];
FILE *f = fopen("/proc/filesystems", "r");
if (!f)
return 1;
while (fgets(buf, sizeof(buf), f))
if (strstr(buf, "fuseblk\n")) {
fclose(f);
return 1;
}
fclose(f);
return 0;
}

1
libfuse/lib/mount_util.h

@ -16,4 +16,3 @@ int fuse_mnt_umount(const char *progname, const char *abs_mnt,
char *fuse_mnt_resolve_path(const char *progname, const char *orig); char *fuse_mnt_resolve_path(const char *progname, const char *orig);
int fuse_mnt_check_empty(const char *progname, const char *mnt, int fuse_mnt_check_empty(const char *progname, const char *mnt,
mode_t rootmode, off_t rootsize); mode_t rootmode, off_t rootsize);
int fuse_mnt_check_fuseblk(void);

48
libfuse/lib/sys.c

@ -0,0 +1,48 @@
#define _GNU_SOURCE
#include <fcntl.h>
#include <unistd.h>
static
int
sys_get_pagesize_(void)
{
#ifdef _SC_PAGESIZE
return sysconf(_SC_PAGESIZE);
#else
return getpagesize();
#endif
}
int
sys_get_pagesize(void)
{
static int pagesize = 0;
if(pagesize == 0)
pagesize = sys_get_pagesize_();
return pagesize;
}
int
sys_alloc_pipe(int pipe_[2],
int bufsize_)
{
#ifdef F_SETPIPE_SZ
int rv;
rv = pipe(pipe_);
if(rv == -1)
return -1;
rv = fcntl(pipe_[0],F_SETPIPE_SZ,bufsize_);
if(rv == -1)
return -1;
return rv;
#else
errno = ENOSYS;
return -1;
#endif
}

4
libfuse/lib/sys.h

@ -0,0 +1,4 @@
#pragma once
int sys_get_pagesize(void);
int sys_alloc_pipe(int p[2], int bufsize);

27
libfuse/util/fusermount.c

@ -173,9 +173,7 @@ static int may_unmount(const char *mnt, int quiet)
while ((entp = getmntent(fp)) != NULL) { while ((entp = getmntent(fp)) != NULL) {
if (!found && strcmp(entp->mnt_dir, mnt) == 0 && if (!found && strcmp(entp->mnt_dir, mnt) == 0 &&
(strcmp(entp->mnt_type, "fuse") == 0 || (strcmp(entp->mnt_type, "fuse") == 0 ||
strcmp(entp->mnt_type, "fuseblk") == 0 ||
strncmp(entp->mnt_type, "fuse.", 5) == 0 ||
strncmp(entp->mnt_type, "fuseblk.", 8) == 0)) {
strncmp(entp->mnt_type, "fuse.", 5) == 0)) {
char *p = strstr(entp->mnt_opts, "user="); char *p = strstr(entp->mnt_opts, "user=");
if (p && if (p &&
(p == entp->mnt_opts || *(p-1) == ',') && (p == entp->mnt_opts || *(p-1) == ',') &&
@ -727,7 +725,6 @@ static int do_mount(const char *mnt, char **typep, mode_t rootmode,
char *source = NULL; char *source = NULL;
char *type = NULL; char *type = NULL;
int check_empty = 1; int check_empty = 1;
int blkdev = 0;
optbuf = (char *) malloc(strlen(opts) + 128); optbuf = (char *) malloc(strlen(opts) + 128);
if (!optbuf) { if (!optbuf) {
@ -751,14 +748,6 @@ static int do_mount(const char *mnt, char **typep, mode_t rootmode,
} else if (begins_with(s, subtype_str)) { } else if (begins_with(s, subtype_str)) {
if (!get_string_opt(s, len, subtype_str, &subtype)) if (!get_string_opt(s, len, subtype_str, &subtype))
goto err; goto err;
} else if (opt_eq(s, len, "blkdev")) {
if (getuid() != 0) {
fprintf(stderr,
"%s: option blkdev is privileged\n",
progname);
goto err;
}
blkdev = 1;
} else if (opt_eq(s, len, "nonempty")) { } else if (opt_eq(s, len, "nonempty")) {
check_empty = 0; check_empty = 0;
} else if (opt_eq(s, len, "auto_unmount")) { } else if (opt_eq(s, len, "auto_unmount")) {
@ -827,9 +816,9 @@ static int do_mount(const char *mnt, char **typep, mode_t rootmode,
} }
if (subtype) if (subtype)
sprintf(type, "%s.%s", blkdev ? "fuseblk" : "fuse", subtype);
sprintf(type, "%s.%s", "fuse", subtype);
else else
strcpy(type, blkdev ? "fuseblk" : "fuse");
strcpy(type, "fuse");
if (fsname) if (fsname)
strcpy(source, fsname); strcpy(source, fsname);
@ -839,9 +828,8 @@ static int do_mount(const char *mnt, char **typep, mode_t rootmode,
res = mount(source, mnt, type, flags, optbuf); res = mount(source, mnt, type, flags, optbuf);
if (res == -1 && errno == ENODEV && subtype) { if (res == -1 && errno == ENODEV && subtype) {
/* Probably missing subtype support */ /* Probably missing subtype support */
strcpy(type, blkdev ? "fuseblk" : "fuse");
strcpy(type, "fuse");
if (fsname) { if (fsname) {
if (!blkdev)
sprintf(source, "%s#%s", subtype, fsname); sprintf(source, "%s#%s", subtype, fsname);
} else { } else {
strcpy(source, type); strcpy(source, type);
@ -857,11 +845,8 @@ static int do_mount(const char *mnt, char **typep, mode_t rootmode,
} }
if (res == -1) { if (res == -1) {
int errno_save = errno; int errno_save = errno;
if (blkdev && errno == ENODEV && !fuse_mnt_check_fuseblk())
fprintf(stderr, "%s: 'fuseblk' support missing\n",
progname);
else
fprintf(stderr, "%s: mount failed: %s\n", progname,
fprintf(stderr,
"%s: mount failed: %s\n", progname,
strerror(errno_save)); strerror(errno_save));
goto err; goto err;
} }

4
libfuse/util/mount.mergerfs.c

@ -96,8 +96,6 @@ int main(int argc, char *argv[])
type = "mergerfs"; type = "mergerfs";
if (strncmp(basename, "mount.fuse.", 11) == 0) if (strncmp(basename, "mount.fuse.", 11) == 0)
type = basename + 11; type = basename + 11;
if (strncmp(basename, "mount.fuseblk.", 14) == 0)
type = basename + 14;
if (type && !type[0]) if (type && !type[0])
type = NULL; type = NULL;
@ -130,8 +128,6 @@ int main(int argc, char *argv[])
type = argv[i]; type = argv[i];
if (strncmp(type, "fuse.", 5) == 0) if (strncmp(type, "fuse.", 5) == 0)
type += 5; type += 5;
else if (strncmp(type, "fuseblk.", 8) == 0)
type += 8;
if (!type[0]) { if (!type[0]) {
fprintf(stderr, fprintf(stderr,

17
libfuse/util/mount_util.c

@ -344,20 +344,3 @@ int fuse_mnt_check_empty(const char *progname, const char *mnt,
} }
return 0; return 0;
} }
int fuse_mnt_check_fuseblk(void)
{
char buf[256];
FILE *f = fopen("/proc/filesystems", "r");
if (!f)
return 1;
while (fgets(buf, sizeof(buf), f))
if (strstr(buf, "fuseblk\n")) {
fclose(f);
return 1;
}
fclose(f);
return 0;
}

2
src/config.cpp

@ -55,7 +55,7 @@ Config::Config()
writeback_cache(false), writeback_cache(false),
readdirplus(false), readdirplus(false),
cache_files(CacheFiles::LIBFUSE), cache_files(CacheFiles::LIBFUSE),
fuse_msg_size(FUSE_MAX_MAX_PAGES),
fuse_msg_size(FUSE_MSG_MAX_PAGES),
POLICYINIT(access), POLICYINIT(access),
POLICYINIT(chmod), POLICYINIT(chmod),
POLICYINIT(chown), POLICYINIT(chown),

2
src/fuse_init.cpp

@ -73,7 +73,7 @@ namespace l
} }
else else
{ {
c_.fuse_msg_size = FUSE_DEFAULT_MAX_PAGES_PER_REQ;
c_.fuse_msg_size = FUSE_MSG_DEFAULT_PAGES;
} }
} }
} }

2
src/option_parser.cpp

@ -382,7 +382,7 @@ parse_and_process_kv_arg(Config &config,
else if(key == "fuse_msg_size") else if(key == "fuse_msg_size")
rv = parse_and_process(value,config.fuse_msg_size, rv = parse_and_process(value,config.fuse_msg_size,
1, 1,
FUSE_MAX_MAX_PAGES);
FUSE_MSG_MAX_PAGES);
} }
if(rv == -1) if(rv == -1)

Loading…
Cancel
Save