From a925fbe59c9b99ca2906c057c286fbd408cb3315 Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Sun, 2 Aug 2020 19:19:53 -0400 Subject: [PATCH] libfuse cleanup: extern cplusplus cleanup --- libfuse/include/extern_c.h | 9 + libfuse/include/fuse.h | 1605 ++++++++-------- libfuse/include/fuse_common.h | 718 ++++---- libfuse/include/fuse_lowlevel.h | 3023 +++++++++++++++---------------- libfuse/include/fuse_opt.h | 442 +++-- libfuse/include/ulockmgr.h | 24 - 6 files changed, 2898 insertions(+), 2923 deletions(-) create mode 100644 libfuse/include/extern_c.h delete mode 100644 libfuse/include/ulockmgr.h diff --git a/libfuse/include/extern_c.h b/libfuse/include/extern_c.h new file mode 100644 index 00000000..d838ccab --- /dev/null +++ b/libfuse/include/extern_c.h @@ -0,0 +1,9 @@ +#pragma once + +#ifdef __cplusplus +#define EXTERN_C_BEGIN extern "C" { +#define EXTERN_C_END } +#else +#define EXTERN_C_BEGIN +#define EXTERN_C_END +#endif diff --git a/libfuse/include/fuse.h b/libfuse/include/fuse.h index 1feff3f2..538216c8 100644 --- a/libfuse/include/fuse.h +++ b/libfuse/include/fuse.h @@ -23,6 +23,7 @@ #define FUSE_USE_VERSION 21 #endif +#include "extern_c.h" #include "fuse_common.h" #include "fuse_dirents.h" @@ -34,892 +35,888 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN - /* ----------------------------------------------------------- * - * Basic FUSE API * - * ----------------------------------------------------------- */ +/* ----------------------------------------------------------- * + * Basic FUSE API * + * ----------------------------------------------------------- */ - /** Handle for a FUSE filesystem */ - struct fuse; +/** Handle for a FUSE filesystem */ +struct fuse; - /** Structure containing a raw command */ - struct fuse_cmd; +/** Structure containing a raw command */ +struct fuse_cmd; - /** - * The file system operations: - * - * Most of these should work very similarly to the well known UNIX - * file system operations. A major exception is that instead of - * returning an error in 'errno', the operation should return the - * negated error value (-errno) directly. - * - * All methods are optional, but some are essential for a useful - * filesystem (e.g. getattr). Open, flush, release, fsync, opendir, - * releasedir, fsyncdir, access, create, ftruncate, fgetattr, lock, - * init and destroy are special purpose methods, without which a full - * featured filesystem can still be implemented. - * - * Almost all operations take a path which can be of any length. - * - * Changed in fuse 2.8.0 (regardless of API version) - * Previously, paths were limited to a length of PATH_MAX. - * - * See http://fuse.sourceforge.net/wiki/ for more information. There - * is also a snapshot of the relevant wiki pages in the doc/ folder. - */ - struct fuse_operations - { - /** Get file attributes. - * - * Similar to stat(). The 'st_dev' and 'st_blksize' fields are - * ignored. The 'st_ino' field is ignored except if the 'use_ino' - * mount option is given. - */ - int (*getattr) (const char *, struct stat *, fuse_timeouts_t *); - - /** Read the target of a symbolic link - * - * The buffer should be filled with a null terminated string. The - * buffer size argument includes the space for the terminating - * null character. If the linkname is too long to fit in the - * buffer, it should be truncated. The return value should be 0 - * for success. - */ - int (*readlink) (const char *, char *, size_t); - - /** Create a file node - * - * This is called for creation of all non-directory, non-symlink - * nodes. If the filesystem defines a create() method, then for - * regular files that will be called instead. - */ - int (*mknod) (const char *, mode_t, dev_t); - - /** Create a directory - * - * Note that the mode argument may not have the type specification - * bits set, i.e. S_ISDIR(mode) can be false. To obtain the - * correct directory type bits use mode|S_IFDIR - * */ - int (*mkdir) (const char *, mode_t); - - /** Hide files unlinked / renamed over - * - * Allows storing of a file handle when a file is unlinked - * while open. Helps manage the fact the kernel usually does - * not send fh with getattr requests. - */ - int (*prepare_hide)(const char *name_, uint64_t *fh_); - int (*free_hide)(const uint64_t fh_); - - /** Remove a file */ - int (*unlink) (const char *); - - /** Remove a directory */ - int (*rmdir) (const char *); - - /** Create a symbolic link */ - int (*symlink) (const char *, const char *); - - /** Rename a file */ - int (*rename) (const char *, const char *); - - /** Create a hard link to a file */ - int (*link) (const char *, const char *); - - /** Change the permission bits of a file */ - int (*chmod) (const char *, mode_t); - int (*fchmod)(const struct fuse_file_info *, const mode_t); - - /** Change the owner and group of a file */ - int (*chown) (const char *, uid_t, gid_t); - int (*fchown)(const struct fuse_file_info *, const uid_t, const gid_t); - - /** Change the size of a file */ - int (*truncate) (const char *, off_t); - - /** Change the access and/or modification times of a file - * - * Deprecated, use utimens() instead. - */ - int (*utime) (const char *, struct utimbuf *); - - /** File open operation - * - * No creation (O_CREAT, O_EXCL) and by default also no - * truncation (O_TRUNC) flags will be passed to open(). If an - * application specifies O_TRUNC, fuse first calls truncate() - * and then open(). Only if 'atomic_o_trunc' has been - * specified and kernel version is 2.6.24 or later, O_TRUNC is - * passed on to open. - * - * Unless the 'default_permissions' mount option is given, - * open should check if the operation is permitted for the - * given flags. Optionally open may also return an arbitrary - * filehandle in the fuse_file_info structure, which will be - * passed to all file operations. - * - * Changed in version 2.2 - */ - int (*open) (const char *, struct fuse_file_info *); - - /** Read data from an open file - * - * Read should return exactly the number of bytes requested except - * on EOF or error, otherwise the rest of the data will be - * substituted with zeroes. An exception to this is when the - * 'direct_io' mount option is specified, in which case the return - * value of the read system call will reflect the return value of - * this operation. - * - * Changed in version 2.2 - */ - int (*read) (char *, size_t, off_t, - struct fuse_file_info *); - - /** Write data to an open file - * - * Write should return exactly the number of bytes requested - * except on error. An exception to this is when the 'direct_io' - * mount option is specified (see read operation). - * - * Changed in version 2.2 - */ - int (*write) (const char *, size_t, off_t, - struct fuse_file_info *); - - /** Get file system statistics - * - * The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored - * - * Replaced 'struct statfs' parameter with 'struct statvfs' in - * version 2.5 - */ - int (*statfs) (const char *, struct statvfs *); - - /** Possibly flush cached data - * - * BIG NOTE: This is not equivalent to fsync(). It's not a - * request to sync dirty data. - * - * Flush is called on each close() of a file descriptor. So if a - * filesystem wants to return write errors in close() and the file - * has cached dirty data, this is a good place to write back data - * and return any errors. Since many applications ignore close() - * errors this is not always useful. - * - * NOTE: The flush() method may be called more than once for each - * open(). This happens if more than one file descriptor refers - * to an opened file due to dup(), dup2() or fork() calls. It is - * not possible to determine if a flush is final, so each flush - * should be treated equally. Multiple write-flush sequences are - * relatively rare, so this shouldn't be a problem. - * - * Filesystems shouldn't assume that flush will always be called - * after some writes, or that if will be called at all. - * - * Changed in version 2.2 - */ - int (*flush) (struct fuse_file_info *); - - /** Release an open file - * - * Release is called when there are no more references to an open - * file: all file descriptors are closed and all memory mappings - * are unmapped. - * - * For every open() call there will be exactly one release() call - * with the same flags and file descriptor. It is possible to - * have a file opened more than once, in which case only the last - * release will mean, that no more reads/writes will happen on the - * file. The return value of release is ignored. - * - * Changed in version 2.2 - */ - int (*release) (struct fuse_file_info *); - - /** Synchronize file contents - * - * If the datasync parameter is non-zero, then only the user data - * should be flushed, not the meta data. - * - * Changed in version 2.2 - */ - int (*fsync) (int, struct fuse_file_info *); - - /** Set extended attributes */ - int (*setxattr) (const char *, const char *, const char *, size_t, int); - - /** Get extended attributes */ - int (*getxattr) (const char *, const char *, char *, size_t); - - /** List extended attributes */ - int (*listxattr) (const char *, char *, size_t); - - /** Remove extended attributes */ - int (*removexattr) (const char *, const char *); - - /** Open directory - * - * Unless the 'default_permissions' mount option is given, - * this method should check if opendir is permitted for this - * directory. Optionally opendir may also return an arbitrary - * filehandle in the fuse_file_info structure, which will be - * passed to readdir, closedir and fsyncdir. - * - * Introduced in version 2.3 - */ - int (*opendir) (const char *, struct fuse_file_info *); - - /** Read directory - * - * This supersedes the old getdir() interface. New applications - * should use this. - * - * The filesystem may choose between two modes of operation: - * - * 1) The readdir implementation ignores the offset parameter, and - * passes zero to the filler function's offset. The filler - * function will not return '1' (unless an error happens), so the - * whole directory is read in a single readdir operation. This - * works just like the old getdir() method. - * - * 2) The readdir implementation keeps track of the offsets of the - * directory entries. It uses the offset parameter and always - * passes non-zero offset to the filler function. When the buffer - * is full (or an error happens) the filler function will return - * '1'. - * - * Introduced in version 2.3 - */ - int (*readdir)(struct fuse_file_info *, - fuse_dirents_t *); - - int (*readdir_plus)(struct fuse_file_info *, - fuse_dirents_t *); - - - /** Release directory - * - * Introduced in version 2.3 - */ - int (*releasedir) (struct fuse_file_info *); - - /** Synchronize directory contents - * - * If the datasync parameter is non-zero, then only the user data - * should be flushed, not the meta data - * - * Introduced in version 2.3 - */ - int (*fsyncdir) (int, struct fuse_file_info *); - - /** - * Initialize filesystem - * - * The return value will passed in the private_data field of - * fuse_context to all file operations and as a parameter to the - * destroy() method. - * - * Introduced in version 2.3 - * Changed in version 2.6 - */ - void *(*init) (struct fuse_conn_info *conn); - - /** - * Clean up filesystem - * - * Called on filesystem exit. - * - * Introduced in version 2.3 - */ - void (*destroy) (void *); - - /** - * Check file access permissions - * - * This will be called for the access() system call. If the - * 'default_permissions' mount option is given, this method is not - * called. - * - * This method is not called under Linux kernel versions 2.4.x - * - * Introduced in version 2.5 - */ - int (*access) (const char *, int); - - /** - * Create and open a file - * - * If the file does not exist, first create it with the specified - * mode, and then open it. - * - * If this method is not implemented or under Linux kernel - * versions earlier than 2.6.15, the mknod() and open() methods - * will be called instead. - * - * Introduced in version 2.5 - */ - int (*create) (const char *, mode_t, struct fuse_file_info *); - - /** - * Change the size of an open file - * - * This method is called instead of the truncate() method if the - * truncation was invoked from an ftruncate() system call. - * - * If this method is not implemented or under Linux kernel - * versions earlier than 2.6.15, the truncate() method will be - * called instead. - * - * Introduced in version 2.5 - */ - int (*ftruncate) (off_t, struct fuse_file_info *); - - /** - * Get attributes from an open file - * - * This method is called instead of the getattr() method if the - * file information is available. - * - * Currently this is only called after the create() method if that - * is implemented (see above). Later it may be called for - * invocations of fstat() too. - * - * Introduced in version 2.5 - */ - int (*fgetattr) (struct stat *, struct fuse_file_info *, fuse_timeouts_t *); - - /** - * Perform POSIX file locking operation - * - * The cmd argument will be either F_GETLK, F_SETLK or F_SETLKW. - * - * For the meaning of fields in 'struct flock' see the man page - * for fcntl(2). The l_whence field will always be set to - * SEEK_SET. - * - * For checking lock ownership, the 'fuse_file_info->owner' - * argument must be used. - * - * For F_GETLK operation, the library will first check currently - * held locks, and if a conflicting lock is found it will return - * information without calling this method. This ensures, that - * for local locks the l_pid field is correctly filled in. The - * results may not be accurate in case of race conditions and in - * the presence of hard links, but it's unlikely that an - * application would rely on accurate GETLK results in these - * cases. If a conflicting lock is not found, this method will be - * called, and the filesystem may fill out l_pid by a meaningful - * value, or it may leave this field zero. - * - * For F_SETLK and F_SETLKW the l_pid field will be set to the pid - * of the process performing the locking operation. - * - * Note: if this method is not implemented, the kernel will still - * allow file locking to work locally. Hence it is only - * interesting for network filesystems and similar. - * - * Introduced in version 2.6 - */ - int (*lock) (struct fuse_file_info *, int cmd, - struct flock *); - - /** - * Change the access and modification times of a file with - * nanosecond resolution - * - * This supersedes the old utime() interface. New applications - * should use this. - * - * See the utimensat(2) man page for details. - * - * Introduced in version 2.6 - */ - int (*utimens)(const char *, const struct timespec tv[2]); - int (*futimens)(const struct fuse_file_info *ffi_, const struct timespec tv_[2]); - - /** - * Map block index within file to block index within device - * - * Note: This makes sense only for block device backed filesystems - * mounted with the 'blkdev' option - * - * Introduced in version 2.6 - */ - int (*bmap) (const char *, size_t blocksize, uint64_t *idx); - - /** - * Ioctl - * - * flags will have FUSE_IOCTL_COMPAT set for 32bit ioctls in - * 64bit environment. The size and direction of data is - * determined by _IOC_*() decoding of cmd. For _IOC_NONE, - * data will be NULL, for _IOC_WRITE data is out area, for - * _IOC_READ in area and if both are set in/out area. In all - * non-NULL cases, the area is of _IOC_SIZE(cmd) bytes. - * - * If flags has FUSE_IOCTL_DIR then the fuse_file_info refers to a - * directory file handle. - * - * Introduced in version 2.8 - */ - int (*ioctl) (unsigned long cmd, - void *arg, - struct fuse_file_info *ffi, - unsigned int flags, - void *data, - uint32_t *out_bufsz); - - /** - * Poll for IO readiness events - * - * Note: If ph is non-NULL, the client should notify - * when IO readiness events occur by calling - * fuse_notify_poll() with the specified ph. - * - * Regardless of the number of times poll with a non-NULL ph - * is received, single notification is enough to clear all. - * Notifying more times incurs overhead but doesn't harm - * correctness. - * - * The callee is responsible for destroying ph with - * fuse_pollhandle_destroy() when no longer in use. - * - * Introduced in version 2.8 - */ - int (*poll) (struct fuse_file_info *, - struct fuse_pollhandle *ph, unsigned *reventsp); - - /** Write contents of buffer to an open file - * - * Similar to the write() method, but data is supplied in a - * generic buffer. Use fuse_buf_copy() to transfer data to - * the destination. - * - * Introduced in version 2.9 - */ - int (*write_buf) (struct fuse_bufvec *buf, off_t off, - struct fuse_file_info *); - - /** Store data from an open file in a buffer - * - * Similar to the read() method, but data is stored and - * returned in a generic buffer. - * - * No actual copying of data has to take place, the source - * file descriptor may simply be stored in the buffer for - * later data transfer. - * - * The buffer must be allocated dynamically and stored at the - * location pointed to by bufp. If the buffer contains memory - * regions, they too must be allocated using malloc(). The - * allocated memory will be freed by the caller. - * - * Introduced in version 2.9 - */ - int (*read_buf) (struct fuse_bufvec **bufp, - size_t size, off_t off, struct fuse_file_info *); - /** - * Perform BSD file locking operation - * - * The op argument will be either LOCK_SH, LOCK_EX or LOCK_UN - * - * Nonblocking requests will be indicated by ORing LOCK_NB to - * the above operations - * - * For more information see the flock(2) manual page. - * - * Additionally fi->owner will be set to a value unique to - * this open file. This same value will be supplied to - * ->release() when the file is released. - * - * Note: if this method is not implemented, the kernel will still - * allow file locking to work locally. Hence it is only - * interesting for network filesystems and similar. - * - * Introduced in version 2.9 - */ - int (*flock) (struct fuse_file_info *, int op); - - /** - * Allocates space for an open file - * - * This function ensures that required space is allocated for specified - * file. If this function returns success then any subsequent write - * request to specified range is guaranteed not to fail because of lack - * of space on the file system media. - * - * Introduced in version 2.9.1 - */ - int (*fallocate) (int, off_t, off_t,struct fuse_file_info *); - - /** - * Copy a range of data from one file to another - * - * Performs an optimized copy between two file descriptors without - * the additional cost of transferring data through the FUSE kernel - * module to user space (glibc) and then back into the FUSE filesystem - * again. - * - * In case this method is not implemented, glibc falls back to - * reading data from the source and writing to the - * destination. Effectively doing an inefficient copy of the - * data. - */ - ssize_t (*copy_file_range)(struct fuse_file_info *fi_in, - off_t offset_in, - struct fuse_file_info *fi_out, - off_t offset_out, - size_t size, - int flags); - }; - - /** Extra context that may be needed by some filesystems - * - * The uid, gid and pid fields are not filled in case of a writepage - * operation. - */ - struct fuse_context - { - /** Pointer to the fuse object */ - struct fuse *fuse; - - /** User ID of the calling process */ - uid_t uid; - - /** Group ID of the calling process */ - gid_t gid; - - /** Thread ID of the calling process */ - pid_t pid; - - /** Private filesystem data */ - void *private_data; - - /** Umask of the calling process (introduced in version 2.8) */ - mode_t umask; - }; +/** + * The file system operations: + * + * Most of these should work very similarly to the well known UNIX + * file system operations. A major exception is that instead of + * returning an error in 'errno', the operation should return the + * negated error value (-errno) directly. + * + * All methods are optional, but some are essential for a useful + * filesystem (e.g. getattr). Open, flush, release, fsync, opendir, + * releasedir, fsyncdir, access, create, ftruncate, fgetattr, lock, + * init and destroy are special purpose methods, without which a full + * featured filesystem can still be implemented. + * + * Almost all operations take a path which can be of any length. + * + * Changed in fuse 2.8.0 (regardless of API version) + * Previously, paths were limited to a length of PATH_MAX. + * + * See http://fuse.sourceforge.net/wiki/ for more information. There + * is also a snapshot of the relevant wiki pages in the doc/ folder. + */ +struct fuse_operations +{ + /** Get file attributes. + * + * Similar to stat(). The 'st_dev' and 'st_blksize' fields are + * ignored. The 'st_ino' field is ignored except if the 'use_ino' + * mount option is given. + */ + int (*getattr) (const char *, struct stat *, fuse_timeouts_t *); - /** - * Main function of FUSE. - * - * This is for the lazy. This is all that has to be called from the - * main() function. - * - * This function does the following: - * - parses command line options (-d -s and -h) - * - passes relevant mount options to the fuse_mount() - * - installs signal handlers for INT, HUP, TERM and PIPE - * - registers an exit handler to unmount the filesystem on program exit - * - creates a fuse handle - * - registers the operations - * - calls either the single-threaded or the multi-threaded event loop - * - * Note: this is currently implemented as a macro. - * - * @param argc the argument counter passed to the main() function - * @param argv the argument vector passed to the main() function - * @param op the file system operation - * @param user_data user data supplied in the context during the init() method - * @return 0 on success, nonzero on failure - */ - /* - int fuse_main(int argc, char *argv[], const struct fuse_operations *op, - void *user_data); - */ -#define fuse_main(argc, argv, op, user_data) \ - fuse_main_real(argc, argv, op, sizeof(*(op)), user_data) + /** Read the target of a symbolic link + * + * The buffer should be filled with a null terminated string. The + * buffer size argument includes the space for the terminating + * null character. If the linkname is too long to fit in the + * buffer, it should be truncated. The return value should be 0 + * for success. + */ + int (*readlink) (const char *, char *, size_t); - /* ----------------------------------------------------------- * - * More detailed API * - * ----------------------------------------------------------- */ + /** Create a file node + * + * This is called for creation of all non-directory, non-symlink + * nodes. If the filesystem defines a create() method, then for + * regular files that will be called instead. + */ + int (*mknod) (const char *, mode_t, dev_t); - /** - * Create a new FUSE filesystem. + /** Create a directory * - * @param ch the communication channel - * @param args argument vector - * @param op the filesystem operations - * @param op_size the size of the fuse_operations structure - * @param user_data user data supplied in the context during the init() method - * @return the created FUSE handle + * Note that the mode argument may not have the type specification + * bits set, i.e. S_ISDIR(mode) can be false. To obtain the + * correct directory type bits use mode|S_IFDIR + * */ + int (*mkdir) (const char *, mode_t); + + /** Hide files unlinked / renamed over + * + * Allows storing of a file handle when a file is unlinked + * while open. Helps manage the fact the kernel usually does + * not send fh with getattr requests. */ - struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args, - const struct fuse_operations *op, size_t op_size, - void *user_data); + int (*prepare_hide)(const char *name_, uint64_t *fh_); + int (*free_hide)(const uint64_t fh_); - /** - * Destroy the FUSE handle. + /** Remove a file */ + int (*unlink) (const char *); + + /** Remove a directory */ + int (*rmdir) (const char *); + + /** Create a symbolic link */ + int (*symlink) (const char *, const char *); + + /** Rename a file */ + int (*rename) (const char *, const char *); + + /** Create a hard link to a file */ + int (*link) (const char *, const char *); + + /** Change the permission bits of a file */ + int (*chmod) (const char *, mode_t); + int (*fchmod)(const struct fuse_file_info *, const mode_t); + + /** Change the owner and group of a file */ + int (*chown) (const char *, uid_t, gid_t); + int (*fchown)(const struct fuse_file_info *, const uid_t, const gid_t); + + /** Change the size of a file */ + int (*truncate) (const char *, off_t); + + /** Change the access and/or modification times of a file * - * The communication channel attached to the handle is also destroyed. + * Deprecated, use utimens() instead. + */ + int (*utime) (const char *, struct utimbuf *); + + /** File open operation + * + * No creation (O_CREAT, O_EXCL) and by default also no + * truncation (O_TRUNC) flags will be passed to open(). If an + * application specifies O_TRUNC, fuse first calls truncate() + * and then open(). Only if 'atomic_o_trunc' has been + * specified and kernel version is 2.6.24 or later, O_TRUNC is + * passed on to open. * - * NOTE: This function does not unmount the filesystem. If this is - * needed, call fuse_unmount() before calling this function. + * Unless the 'default_permissions' mount option is given, + * open should check if the operation is permitted for the + * given flags. Optionally open may also return an arbitrary + * filehandle in the fuse_file_info structure, which will be + * passed to all file operations. * - * @param f the FUSE handle + * Changed in version 2.2 */ - void fuse_destroy(struct fuse *f); + int (*open) (const char *, struct fuse_file_info *); - /** - * Exit from event loop + /** Read data from an open file * - * @param f the FUSE handle + * Read should return exactly the number of bytes requested except + * on EOF or error, otherwise the rest of the data will be + * substituted with zeroes. An exception to this is when the + * 'direct_io' mount option is specified, in which case the return + * value of the read system call will reflect the return value of + * this operation. + * + * Changed in version 2.2 */ - void fuse_exit(struct fuse *f); + int (*read) (char *, size_t, off_t, + struct fuse_file_info *); - int fuse_config_num_threads(const struct fuse *fuse_); + /** Write data to an open file + * + * Write should return exactly the number of bytes requested + * except on error. An exception to this is when the 'direct_io' + * mount option is specified (see read operation). + * + * Changed in version 2.2 + */ + int (*write) (const char *, size_t, off_t, + struct fuse_file_info *); - /** - * FUSE event loop with multiple threads + /** Get file system statistics + * + * The 'f_frsize', 'f_favail', 'f_fsid' and 'f_flag' fields are ignored + * + * Replaced 'struct statfs' parameter with 'struct statvfs' in + * version 2.5 + */ + int (*statfs) (const char *, struct statvfs *); + + /** Possibly flush cached data + * + * BIG NOTE: This is not equivalent to fsync(). It's not a + * request to sync dirty data. + * + * Flush is called on each close() of a file descriptor. So if a + * filesystem wants to return write errors in close() and the file + * has cached dirty data, this is a good place to write back data + * and return any errors. Since many applications ignore close() + * errors this is not always useful. + * + * NOTE: The flush() method may be called more than once for each + * open(). This happens if more than one file descriptor refers + * to an opened file due to dup(), dup2() or fork() calls. It is + * not possible to determine if a flush is final, so each flush + * should be treated equally. Multiple write-flush sequences are + * relatively rare, so this shouldn't be a problem. + * + * Filesystems shouldn't assume that flush will always be called + * after some writes, or that if will be called at all. + * + * Changed in version 2.2 + */ + int (*flush) (struct fuse_file_info *); + + /** Release an open file + * + * Release is called when there are no more references to an open + * file: all file descriptors are closed and all memory mappings + * are unmapped. + * + * For every open() call there will be exactly one release() call + * with the same flags and file descriptor. It is possible to + * have a file opened more than once, in which case only the last + * release will mean, that no more reads/writes will happen on the + * file. The return value of release is ignored. + * + * Changed in version 2.2 + */ + int (*release) (struct fuse_file_info *); + + /** Synchronize file contents + * + * If the datasync parameter is non-zero, then only the user data + * should be flushed, not the meta data. + * + * Changed in version 2.2 + */ + int (*fsync) (int, struct fuse_file_info *); + + /** Set extended attributes */ + int (*setxattr) (const char *, const char *, const char *, size_t, int); + + /** Get extended attributes */ + int (*getxattr) (const char *, const char *, char *, size_t); + + /** List extended attributes */ + int (*listxattr) (const char *, char *, size_t); + + /** Remove extended attributes */ + int (*removexattr) (const char *, const char *); + + /** Open directory + * + * Unless the 'default_permissions' mount option is given, + * this method should check if opendir is permitted for this + * directory. Optionally opendir may also return an arbitrary + * filehandle in the fuse_file_info structure, which will be + * passed to readdir, closedir and fsyncdir. + * + * Introduced in version 2.3 + */ + int (*opendir) (const char *, struct fuse_file_info *); + + /** Read directory + * + * This supersedes the old getdir() interface. New applications + * should use this. * - * Requests from the kernel are processed, and the appropriate - * operations are called. Request are processed in parallel by - * distributing them between multiple threads. + * The filesystem may choose between two modes of operation: * - * Calling this function requires the pthreads library to be linked to - * the application. + * 1) The readdir implementation ignores the offset parameter, and + * passes zero to the filler function's offset. The filler + * function will not return '1' (unless an error happens), so the + * whole directory is read in a single readdir operation. This + * works just like the old getdir() method. * - * @param f the FUSE handle - * @return 0 if no error occurred, -1 otherwise + * 2) The readdir implementation keeps track of the offsets of the + * directory entries. It uses the offset parameter and always + * passes non-zero offset to the filler function. When the buffer + * is full (or an error happens) the filler function will return + * '1'. + * + * Introduced in version 2.3 + */ + int (*readdir)(struct fuse_file_info *, + fuse_dirents_t *); + + int (*readdir_plus)(struct fuse_file_info *, + fuse_dirents_t *); + + + /** Release directory + * + * Introduced in version 2.3 + */ + int (*releasedir) (struct fuse_file_info *); + + /** Synchronize directory contents + * + * If the datasync parameter is non-zero, then only the user data + * should be flushed, not the meta data + * + * Introduced in version 2.3 */ - int fuse_loop_mt(struct fuse *f); + int (*fsyncdir) (int, struct fuse_file_info *); /** - * Get the current context + * Initialize filesystem * - * The context is only valid for the duration of a filesystem - * operation, and thus must not be stored and used later. + * The return value will passed in the private_data field of + * fuse_context to all file operations and as a parameter to the + * destroy() method. * - * @return the context + * Introduced in version 2.3 + * Changed in version 2.6 */ - struct fuse_context *fuse_get_context(void); + void *(*init) (struct fuse_conn_info *conn); /** - * Check if the current request has already been interrupted + * Clean up filesystem + * + * Called on filesystem exit. * - * @return 1 if the request has been interrupted, 0 otherwise + * Introduced in version 2.3 */ - int fuse_interrupted(void); + void (*destroy) (void *); /** - * Obsolete, doesn't do anything + * Check file access permissions * - * @return -EINVAL + * This will be called for the access() system call. If the + * 'default_permissions' mount option is given, this method is not + * called. + * + * This method is not called under Linux kernel versions 2.4.x + * + * Introduced in version 2.5 */ - int fuse_invalidate(struct fuse *f, const char *path); + int (*access) (const char *, int); - /* Deprecated, don't use */ - int fuse_is_lib_option(const char *opt); + /** + * Create and open a file + * + * If the file does not exist, first create it with the specified + * mode, and then open it. + * + * If this method is not implemented or under Linux kernel + * versions earlier than 2.6.15, the mknod() and open() methods + * will be called instead. + * + * Introduced in version 2.5 + */ + int (*create) (const char *, mode_t, struct fuse_file_info *); /** - * The real main function + * Change the size of an open file * - * Do not call this directly, use fuse_main() + * This method is called instead of the truncate() method if the + * truncation was invoked from an ftruncate() system call. + * + * If this method is not implemented or under Linux kernel + * versions earlier than 2.6.15, the truncate() method will be + * called instead. + * + * Introduced in version 2.5 */ - int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op, - size_t op_size, void *user_data); + int (*ftruncate) (off_t, struct fuse_file_info *); /** - * Start the cleanup thread when using option "remember". + * Get attributes from an open file + * + * This method is called instead of the getattr() method if the + * file information is available. * - * This is done automatically by fuse_loop_mt() - * @param fuse struct fuse pointer for fuse instance - * @return 0 on success and -1 on error + * Currently this is only called after the create() method if that + * is implemented (see above). Later it may be called for + * invocations of fstat() too. + * + * Introduced in version 2.5 */ - int fuse_start_cleanup_thread(struct fuse *fuse); + int (*fgetattr) (struct stat *, struct fuse_file_info *, fuse_timeouts_t *); /** - * Stop the cleanup thread when using option "remember". + * Perform POSIX file locking operation + * + * The cmd argument will be either F_GETLK, F_SETLK or F_SETLKW. + * + * For the meaning of fields in 'struct flock' see the man page + * for fcntl(2). The l_whence field will always be set to + * SEEK_SET. + * + * For checking lock ownership, the 'fuse_file_info->owner' + * argument must be used. + * + * For F_GETLK operation, the library will first check currently + * held locks, and if a conflicting lock is found it will return + * information without calling this method. This ensures, that + * for local locks the l_pid field is correctly filled in. The + * results may not be accurate in case of race conditions and in + * the presence of hard links, but it's unlikely that an + * application would rely on accurate GETLK results in these + * cases. If a conflicting lock is not found, this method will be + * called, and the filesystem may fill out l_pid by a meaningful + * value, or it may leave this field zero. + * + * For F_SETLK and F_SETLKW the l_pid field will be set to the pid + * of the process performing the locking operation. + * + * Note: if this method is not implemented, the kernel will still + * allow file locking to work locally. Hence it is only + * interesting for network filesystems and similar. * - * This is done automatically by fuse_loop_mt() - * @param fuse struct fuse pointer for fuse instance + * Introduced in version 2.6 */ - void fuse_stop_cleanup_thread(struct fuse *fuse); + int (*lock) (struct fuse_file_info *, int cmd, + struct flock *); /** - * Iterate over cache removing stale entries - * use in conjunction with "-oremember" + * Change the access and modification times of a file with + * nanosecond resolution * - * NOTE: This is already done for the standard sessions + * This supersedes the old utime() interface. New applications + * should use this. * - * @param fuse struct fuse pointer for fuse instance - * @return the number of seconds until the next cleanup + * See the utimensat(2) man page for details. + * + * Introduced in version 2.6 */ - int fuse_clean_cache(struct fuse *fuse); + int (*utimens)(const char *, const struct timespec tv[2]); + int (*futimens)(const struct fuse_file_info *ffi_, const struct timespec tv_[2]); - /* - * Stacking API + /** + * Map block index within file to block index within device + * + * Note: This makes sense only for block device backed filesystems + * mounted with the 'blkdev' option + * + * Introduced in version 2.6 */ + int (*bmap) (const char *, size_t blocksize, uint64_t *idx); /** - * Fuse filesystem object + * Ioctl * - * This is opaque object represents a filesystem layer + * flags will have FUSE_IOCTL_COMPAT set for 32bit ioctls in + * 64bit environment. The size and direction of data is + * determined by _IOC_*() decoding of cmd. For _IOC_NONE, + * data will be NULL, for _IOC_WRITE data is out area, for + * _IOC_READ in area and if both are set in/out area. In all + * non-NULL cases, the area is of _IOC_SIZE(cmd) bytes. + * + * If flags has FUSE_IOCTL_DIR then the fuse_file_info refers to a + * directory file handle. + * + * Introduced in version 2.8 */ - struct fuse_fs; + int (*ioctl) (unsigned long cmd, + void *arg, + struct fuse_file_info *ffi, + unsigned int flags, + void *data, + uint32_t *out_bufsz); - /* - * These functions call the relevant filesystem operation, and return - * the result. + /** + * Poll for IO readiness events * - * If the operation is not defined, they return -ENOSYS, with the - * exception of fuse_fs_open, fuse_fs_release, fuse_fs_opendir, - * fuse_fs_releasedir and fuse_fs_statfs, which return 0. + * Note: If ph is non-NULL, the client should notify + * when IO readiness events occur by calling + * fuse_notify_poll() with the specified ph. + * + * Regardless of the number of times poll with a non-NULL ph + * is received, single notification is enough to clear all. + * Notifying more times incurs overhead but doesn't harm + * correctness. + * + * The callee is responsible for destroying ph with + * fuse_pollhandle_destroy() when no longer in use. + * + * Introduced in version 2.8 */ + int (*poll) (struct fuse_file_info *, + struct fuse_pollhandle *ph, unsigned *reventsp); - int fuse_fs_getattr(struct fuse_fs *fs, - const char *path, - struct stat *buf, - fuse_timeouts_t *timeout); + /** Write contents of buffer to an open file + * + * Similar to the write() method, but data is supplied in a + * generic buffer. Use fuse_buf_copy() to transfer data to + * the destination. + * + * Introduced in version 2.9 + */ + int (*write_buf) (struct fuse_bufvec *buf, off_t off, + struct fuse_file_info *); - int fuse_fs_fgetattr(struct fuse_fs *fs, - struct stat *buf, - struct fuse_file_info *fi, - fuse_timeouts_t *timeout); + /** Store data from an open file in a buffer + * + * Similar to the read() method, but data is stored and + * returned in a generic buffer. + * + * No actual copying of data has to take place, the source + * file descriptor may simply be stored in the buffer for + * later data transfer. + * + * The buffer must be allocated dynamically and stored at the + * location pointed to by bufp. If the buffer contains memory + * regions, they too must be allocated using malloc(). The + * allocated memory will be freed by the caller. + * + * Introduced in version 2.9 + */ + int (*read_buf) (struct fuse_bufvec **bufp, + size_t size, off_t off, struct fuse_file_info *); + /** + * Perform BSD file locking operation + * + * The op argument will be either LOCK_SH, LOCK_EX or LOCK_UN + * + * Nonblocking requests will be indicated by ORing LOCK_NB to + * the above operations + * + * For more information see the flock(2) manual page. + * + * Additionally fi->owner will be set to a value unique to + * this open file. This same value will be supplied to + * ->release() when the file is released. + * + * Note: if this method is not implemented, the kernel will still + * allow file locking to work locally. Hence it is only + * interesting for network filesystems and similar. + * + * Introduced in version 2.9 + */ + int (*flock) (struct fuse_file_info *, int op); - int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath, - const char *newpath); - int fuse_fs_unlink(struct fuse_fs *fs, const char *path); - int fuse_fs_rmdir(struct fuse_fs *fs, const char *path); - int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, - const char *path); - int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath); - int fuse_fs_release(struct fuse_fs *fs, - struct fuse_file_info *fi); - int fuse_fs_open(struct fuse_fs *fs, const char *path, - struct fuse_file_info *fi); - int fuse_fs_read(struct fuse_fs *fs, char *buf, size_t size, - off_t off, struct fuse_file_info *fi); - int fuse_fs_read_buf(struct fuse_fs *fs, - struct fuse_bufvec **bufp, size_t size, off_t off, - struct fuse_file_info *fi); - int fuse_fs_write(struct fuse_fs *fs, const char *buf, - size_t size, off_t off, struct fuse_file_info *fi); - int fuse_fs_write_buf(struct fuse_fs *fs, - struct fuse_bufvec *buf, off_t off, - struct fuse_file_info *fi); - int fuse_fs_fsync(struct fuse_fs *fs, int datasync, - struct fuse_file_info *fi); - int fuse_fs_flush(struct fuse_fs *fs, - struct fuse_file_info *fi); - int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf); - int fuse_fs_opendir(struct fuse_fs *fs, const char *path, - struct fuse_file_info *fi); - int fuse_fs_readdir(struct fuse_fs *fs, - struct fuse_file_info *fi, - fuse_dirents_t *buf); - int fuse_fs_fsyncdir(struct fuse_fs *fs, int datasync, - struct fuse_file_info *fi); - int fuse_fs_releasedir(struct fuse_fs *fs, - struct fuse_file_info *fi); - int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode, - struct fuse_file_info *fi); - int fuse_fs_lock(struct fuse_fs *fs, - struct fuse_file_info *fi, int cmd, struct flock *lock); - int fuse_fs_flock(struct fuse_fs *fs, - struct fuse_file_info *fi, int op); - int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode); - int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid); - int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size); - int fuse_fs_ftruncate(struct fuse_fs *fs, off_t size, - struct fuse_file_info *fi); - int fuse_fs_utimens(struct fuse_fs *fs, const char *path, - const struct timespec tv[2]); - int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask); - int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf, - size_t len); - int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode, - dev_t rdev); - int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode); - int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name, - const char *value, size_t size, int flags); - int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name, - char *value, size_t size); - int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list, - size_t size); - int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, - const char *name); - int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize, - uint64_t *idx); - int fuse_fs_ioctl(struct fuse_fs *fs, unsigned long cmd, void *arg, - struct fuse_file_info *fi, unsigned int flags, - void *data, uint32_t *out_bufsz); - int fuse_fs_poll(struct fuse_fs *fs, - struct fuse_file_info *fi, struct fuse_pollhandle *ph, - unsigned *reventsp); - int fuse_fs_fallocate(struct fuse_fs *fs, int mode, - off_t offset, off_t length, struct fuse_file_info *fi); - void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn); - void fuse_fs_destroy(struct fuse_fs *fs); - - int fuse_fs_prepare_hide(struct fuse_fs *fs, const char *path, uint64_t *fh); - int fuse_fs_free_hide(struct fuse_fs *fs, uint64_t fh); - ssize_t fuse_fs_copy_file_range(struct fuse_fs *fs, - struct fuse_file_info *fi_in, off_t off_in, - struct fuse_file_info *fi_out, off_t off_out, - size_t len, int flags); - - int fuse_notify_poll(struct fuse_pollhandle *ph); + /** + * Allocates space for an open file + * + * This function ensures that required space is allocated for specified + * file. If this function returns success then any subsequent write + * request to specified range is guaranteed not to fail because of lack + * of space on the file system media. + * + * Introduced in version 2.9.1 + */ + int (*fallocate) (int, off_t, off_t,struct fuse_file_info *); /** - * Create a new fuse filesystem object + * Copy a range of data from one file to another * - * This is usually called from the factory of a fuse module to create - * a new instance of a filesystem. + * Performs an optimized copy between two file descriptors without + * the additional cost of transferring data through the FUSE kernel + * module to user space (glibc) and then back into the FUSE filesystem + * again. * - * @param op the filesystem operations - * @param op_size the size of the fuse_operations structure - * @param user_data user data supplied in the context during the init() method - * @return a new filesystem object + * In case this method is not implemented, glibc falls back to + * reading data from the source and writing to the + * destination. Effectively doing an inefficient copy of the + * data. */ - struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size, - void *user_data); + ssize_t (*copy_file_range)(struct fuse_file_info *fi_in, + off_t offset_in, + struct fuse_file_info *fi_out, + off_t offset_out, + size_t size, + int flags); +}; + +/** Extra context that may be needed by some filesystems + * + * The uid, gid and pid fields are not filled in case of a writepage + * operation. + */ +struct fuse_context +{ + /** Pointer to the fuse object */ + struct fuse *fuse; - /* ----------------------------------------------------------- * - * Advanced API for event handling, don't worry about this... * - * ----------------------------------------------------------- */ + /** User ID of the calling process */ + uid_t uid; - /* NOTE: the following functions are deprecated, and will be removed - from the 3.0 API. Use the lowlevel session functions instead */ + /** Group ID of the calling process */ + gid_t gid; - /** Function type used to process commands */ - typedef void (*fuse_processor_t)(struct fuse *, struct fuse_cmd *, void *); + /** Thread ID of the calling process */ + pid_t pid; - /** This is the part of fuse_main() before the event loop */ - struct fuse *fuse_setup(int argc, char *argv[], - const struct fuse_operations *op, size_t op_size, - char **mountpoint, - void *user_data); + /** Private filesystem data */ + void *private_data; - /** This is the part of fuse_main() after the event loop */ - void fuse_teardown(struct fuse *fuse, char *mountpoint); + /** Umask of the calling process (introduced in version 2.8) */ + mode_t umask; +}; - /** Read a single command. If none are read, return NULL */ - struct fuse_cmd *fuse_read_cmd(struct fuse *f); +/** + * Main function of FUSE. + * + * This is for the lazy. This is all that has to be called from the + * main() function. + * + * This function does the following: + * - parses command line options (-d -s and -h) + * - passes relevant mount options to the fuse_mount() + * - installs signal handlers for INT, HUP, TERM and PIPE + * - registers an exit handler to unmount the filesystem on program exit + * - creates a fuse handle + * - registers the operations + * - calls either the single-threaded or the multi-threaded event loop + * + * Note: this is currently implemented as a macro. + * + * @param argc the argument counter passed to the main() function + * @param argv the argument vector passed to the main() function + * @param op the file system operation + * @param user_data user data supplied in the context during the init() method + * @return 0 on success, nonzero on failure + */ +/* + int fuse_main(int argc, char *argv[], const struct fuse_operations *op, + void *user_data); +*/ +#define fuse_main(argc, argv, op, user_data) \ + fuse_main_real(argc, argv, op, sizeof(*(op)), user_data) - /** Process a single command */ - void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd); +/* ----------------------------------------------------------- * + * More detailed API * + * ----------------------------------------------------------- */ - /** Multi threaded event loop, which calls the custom command - processor function */ - int fuse_loop_mt_proc(struct fuse *f, fuse_processor_t proc, void *data); +/** + * Create a new FUSE filesystem. + * + * @param ch the communication channel + * @param args argument vector + * @param op the filesystem operations + * @param op_size the size of the fuse_operations structure + * @param user_data user data supplied in the context during the init() method + * @return the created FUSE handle + */ +struct fuse *fuse_new(struct fuse_chan *ch, struct fuse_args *args, + const struct fuse_operations *op, size_t op_size, + void *user_data); - /** Return the exited flag, which indicates if fuse_exit() has been - called */ - int fuse_exited(struct fuse *f); +/** + * Destroy the FUSE handle. + * + * The communication channel attached to the handle is also destroyed. + * + * NOTE: This function does not unmount the filesystem. If this is + * needed, call fuse_unmount() before calling this function. + * + * @param f the FUSE handle + */ +void fuse_destroy(struct fuse *f); - /** This function is obsolete and implemented as a no-op */ - void fuse_set_getcontext_func(struct fuse_context *(*func)(void)); +/** + * Exit from event loop + * + * @param f the FUSE handle + */ +void fuse_exit(struct fuse *f); - /** Get session from fuse object */ - struct fuse_session *fuse_get_session(struct fuse *f); +int fuse_config_num_threads(const struct fuse *fuse_); -#ifdef __cplusplus -} -#endif +/** + * FUSE event loop with multiple threads + * + * Requests from the kernel are processed, and the appropriate + * operations are called. Request are processed in parallel by + * distributing them between multiple threads. + * + * Calling this function requires the pthreads library to be linked to + * the application. + * + * @param f the FUSE handle + * @return 0 if no error occurred, -1 otherwise + */ +int fuse_loop_mt(struct fuse *f); + +/** + * Get the current context + * + * The context is only valid for the duration of a filesystem + * operation, and thus must not be stored and used later. + * + * @return the context + */ +struct fuse_context *fuse_get_context(void); + +/** + * Check if the current request has already been interrupted + * + * @return 1 if the request has been interrupted, 0 otherwise + */ +int fuse_interrupted(void); + +/** + * Obsolete, doesn't do anything + * + * @return -EINVAL + */ +int fuse_invalidate(struct fuse *f, const char *path); + +/* Deprecated, don't use */ +int fuse_is_lib_option(const char *opt); + +/** + * The real main function + * + * Do not call this directly, use fuse_main() + */ +int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op, + size_t op_size, void *user_data); + +/** + * Start the cleanup thread when using option "remember". + * + * This is done automatically by fuse_loop_mt() + * @param fuse struct fuse pointer for fuse instance + * @return 0 on success and -1 on error + */ +int fuse_start_cleanup_thread(struct fuse *fuse); + +/** + * Stop the cleanup thread when using option "remember". + * + * This is done automatically by fuse_loop_mt() + * @param fuse struct fuse pointer for fuse instance + */ +void fuse_stop_cleanup_thread(struct fuse *fuse); + +/** + * Iterate over cache removing stale entries + * use in conjunction with "-oremember" + * + * NOTE: This is already done for the standard sessions + * + * @param fuse struct fuse pointer for fuse instance + * @return the number of seconds until the next cleanup + */ +int fuse_clean_cache(struct fuse *fuse); + +/* + * Stacking API + */ + +/** + * Fuse filesystem object + * + * This is opaque object represents a filesystem layer + */ +struct fuse_fs; + +/* + * These functions call the relevant filesystem operation, and return + * the result. + * + * If the operation is not defined, they return -ENOSYS, with the + * exception of fuse_fs_open, fuse_fs_release, fuse_fs_opendir, + * fuse_fs_releasedir and fuse_fs_statfs, which return 0. + */ + +int fuse_fs_getattr(struct fuse_fs *fs, + const char *path, + struct stat *buf, + fuse_timeouts_t *timeout); + +int fuse_fs_fgetattr(struct fuse_fs *fs, + struct stat *buf, + struct fuse_file_info *fi, + fuse_timeouts_t *timeout); + +int fuse_fs_rename(struct fuse_fs *fs, const char *oldpath, + const char *newpath); +int fuse_fs_unlink(struct fuse_fs *fs, const char *path); +int fuse_fs_rmdir(struct fuse_fs *fs, const char *path); +int fuse_fs_symlink(struct fuse_fs *fs, const char *linkname, + const char *path); +int fuse_fs_link(struct fuse_fs *fs, const char *oldpath, const char *newpath); +int fuse_fs_release(struct fuse_fs *fs, + struct fuse_file_info *fi); +int fuse_fs_open(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi); +int fuse_fs_read(struct fuse_fs *fs, char *buf, size_t size, + off_t off, struct fuse_file_info *fi); +int fuse_fs_read_buf(struct fuse_fs *fs, + struct fuse_bufvec **bufp, size_t size, off_t off, + struct fuse_file_info *fi); +int fuse_fs_write(struct fuse_fs *fs, const char *buf, + size_t size, off_t off, struct fuse_file_info *fi); +int fuse_fs_write_buf(struct fuse_fs *fs, + struct fuse_bufvec *buf, off_t off, + struct fuse_file_info *fi); +int fuse_fs_fsync(struct fuse_fs *fs, int datasync, + struct fuse_file_info *fi); +int fuse_fs_flush(struct fuse_fs *fs, + struct fuse_file_info *fi); +int fuse_fs_statfs(struct fuse_fs *fs, const char *path, struct statvfs *buf); +int fuse_fs_opendir(struct fuse_fs *fs, const char *path, + struct fuse_file_info *fi); +int fuse_fs_readdir(struct fuse_fs *fs, + struct fuse_file_info *fi, + fuse_dirents_t *buf); +int fuse_fs_fsyncdir(struct fuse_fs *fs, int datasync, + struct fuse_file_info *fi); +int fuse_fs_releasedir(struct fuse_fs *fs, + struct fuse_file_info *fi); +int fuse_fs_create(struct fuse_fs *fs, const char *path, mode_t mode, + struct fuse_file_info *fi); +int fuse_fs_lock(struct fuse_fs *fs, + struct fuse_file_info *fi, int cmd, struct flock *lock); +int fuse_fs_flock(struct fuse_fs *fs, + struct fuse_file_info *fi, int op); +int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode); +int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid); +int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size); +int fuse_fs_ftruncate(struct fuse_fs *fs, off_t size, + struct fuse_file_info *fi); +int fuse_fs_utimens(struct fuse_fs *fs, const char *path, + const struct timespec tv[2]); +int fuse_fs_access(struct fuse_fs *fs, const char *path, int mask); +int fuse_fs_readlink(struct fuse_fs *fs, const char *path, char *buf, + size_t len); +int fuse_fs_mknod(struct fuse_fs *fs, const char *path, mode_t mode, + dev_t rdev); +int fuse_fs_mkdir(struct fuse_fs *fs, const char *path, mode_t mode); +int fuse_fs_setxattr(struct fuse_fs *fs, const char *path, const char *name, + const char *value, size_t size, int flags); +int fuse_fs_getxattr(struct fuse_fs *fs, const char *path, const char *name, + char *value, size_t size); +int fuse_fs_listxattr(struct fuse_fs *fs, const char *path, char *list, + size_t size); +int fuse_fs_removexattr(struct fuse_fs *fs, const char *path, + const char *name); +int fuse_fs_bmap(struct fuse_fs *fs, const char *path, size_t blocksize, + uint64_t *idx); +int fuse_fs_ioctl(struct fuse_fs *fs, unsigned long cmd, void *arg, + struct fuse_file_info *fi, unsigned int flags, + void *data, uint32_t *out_bufsz); +int fuse_fs_poll(struct fuse_fs *fs, + struct fuse_file_info *fi, struct fuse_pollhandle *ph, + unsigned *reventsp); +int fuse_fs_fallocate(struct fuse_fs *fs, int mode, + off_t offset, off_t length, struct fuse_file_info *fi); +void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn); +void fuse_fs_destroy(struct fuse_fs *fs); + +int fuse_fs_prepare_hide(struct fuse_fs *fs, const char *path, uint64_t *fh); +int fuse_fs_free_hide(struct fuse_fs *fs, uint64_t fh); +ssize_t fuse_fs_copy_file_range(struct fuse_fs *fs, + struct fuse_file_info *fi_in, off_t off_in, + struct fuse_file_info *fi_out, off_t off_out, + size_t len, int flags); + +int fuse_notify_poll(struct fuse_pollhandle *ph); + +/** + * Create a new fuse filesystem object + * + * This is usually called from the factory of a fuse module to create + * a new instance of a filesystem. + * + * @param op the filesystem operations + * @param op_size the size of the fuse_operations structure + * @param user_data user data supplied in the context during the init() method + * @return a new filesystem object + */ +struct fuse_fs *fuse_fs_new(const struct fuse_operations *op, size_t op_size, + void *user_data); + +/* ----------------------------------------------------------- * + * Advanced API for event handling, don't worry about this... * + * ----------------------------------------------------------- */ + +/* NOTE: the following functions are deprecated, and will be removed + from the 3.0 API. Use the lowlevel session functions instead */ + +/** Function type used to process commands */ +typedef void (*fuse_processor_t)(struct fuse *, struct fuse_cmd *, void *); + +/** This is the part of fuse_main() before the event loop */ +struct fuse *fuse_setup(int argc, char *argv[], + const struct fuse_operations *op, size_t op_size, + char **mountpoint, + void *user_data); + +/** This is the part of fuse_main() after the event loop */ +void fuse_teardown(struct fuse *fuse, char *mountpoint); + +/** Read a single command. If none are read, return NULL */ +struct fuse_cmd *fuse_read_cmd(struct fuse *f); + +/** Process a single command */ +void fuse_process_cmd(struct fuse *f, struct fuse_cmd *cmd); + +/** Multi threaded event loop, which calls the custom command + processor function */ +int fuse_loop_mt_proc(struct fuse *f, fuse_processor_t proc, void *data); + +/** Return the exited flag, which indicates if fuse_exit() has been + called */ +int fuse_exited(struct fuse *f); + +/** This function is obsolete and implemented as a no-op */ +void fuse_set_getcontext_func(struct fuse_context *(*func)(void)); + +/** Get session from fuse object */ +struct fuse_session *fuse_get_session(struct fuse *f); + +EXTERN_C_END #endif /* _FUSE_H_ */ diff --git a/libfuse/include/fuse_common.h b/libfuse/include/fuse_common.h index 0de750ef..96c317f9 100644 --- a/libfuse/include/fuse_common.h +++ b/libfuse/include/fuse_common.h @@ -15,8 +15,10 @@ #ifndef _FUSE_COMMON_H_ #define _FUSE_COMMON_H_ +#include "extern_c.h" #include "fuse_opt.h" #include "fuse_timeouts.h" + #include #include @@ -37,76 +39,74 @@ #define FUSE_DEFAULT_MAX_PAGES_PER_REQ 32 #define FUSE_MAX_MAX_PAGES 256 -#ifdef __cplusplus -extern "C" { -#endif - - /** - * Information about open files - * - * Changed in version 2.5 - */ - struct - fuse_file_info - { - /** Open flags. Available in open() and release() */ - int flags; - - /** In case of a write operation indicates if this was caused by a - writepage */ - uint32_t writepage : 1; - - /** Can be filled in by open, to use direct I/O on this file. - Introduced in version 2.4 */ - uint32_t direct_io : 1; - - /** Can be filled in by open, to indicate, that cached file data - need not be invalidated. Introduced in version 2.4 */ - uint32_t keep_cache : 1; - - /** Indicates a flush operation. Set in flush operation, also - maybe set in highlevel lock operation and lowlevel release - operation. Introduced in version 2.6 */ - uint32_t flush : 1; - - /** Can be filled in by open, to indicate that the file is not - seekable. Introduced in version 2.8 */ - uint32_t nonseekable : 1; - - /* Indicates that flock locks for this file should be - released. If set, lock_owner shall contain a valid value. - May only be set in ->release(). Introduced in version - 2.9 */ - uint32_t flock_release : 1; - - /* Requests the kernel to cache entries returned by readdir */ - uint32_t cache_readdir : 1; - - uint32_t auto_cache : 1; - - /** File handle. May be filled in by filesystem in open(). - Available in all other file operations */ - uint64_t fh; - - /** Lock owner id. Available in locking operations and flush */ - uint64_t lock_owner; - }; - - /** - * Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want' - * - * FUSE_CAP_ASYNC_READ: filesystem supports asynchronous read requests - * FUSE_CAP_POSIX_LOCKS: filesystem supports "remote" locking - * FUSE_CAP_ATOMIC_O_TRUNC: filesystem handles the O_TRUNC open flag - * FUSE_CAP_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." - * FUSE_CAP_BIG_WRITES: filesystem can handle write size larger than 4kB - * FUSE_CAP_DONT_MASK: don't apply umask to file mode on create operations - * FUSE_CAP_SPLICE_WRITE: ability to use splice() to write to the fuse device - * FUSE_CAP_SPLICE_MOVE: ability to move data to the fuse device with splice() - * FUSE_CAP_SPLICE_READ: ability to use splice() to read from the fuse device - * FUSE_CAP_IOCTL_DIR: ioctl support on directories - * FUSE_CAP_CACHE_SYMLINKS: cache READLINK responses - */ +EXTERN_C_BEGIN + +/** + * Information about open files + * + * Changed in version 2.5 + */ +struct +fuse_file_info +{ + /** Open flags. Available in open() and release() */ + int flags; + + /** In case of a write operation indicates if this was caused by a + writepage */ + uint32_t writepage : 1; + + /** Can be filled in by open, to use direct I/O on this file. + Introduced in version 2.4 */ + uint32_t direct_io : 1; + + /** Can be filled in by open, to indicate, that cached file data + need not be invalidated. Introduced in version 2.4 */ + uint32_t keep_cache : 1; + + /** Indicates a flush operation. Set in flush operation, also + maybe set in highlevel lock operation and lowlevel release + operation. Introduced in version 2.6 */ + uint32_t flush : 1; + + /** Can be filled in by open, to indicate that the file is not + seekable. Introduced in version 2.8 */ + uint32_t nonseekable : 1; + + /* Indicates that flock locks for this file should be + released. If set, lock_owner shall contain a valid value. + May only be set in ->release(). Introduced in version + 2.9 */ + uint32_t flock_release : 1; + + /* Requests the kernel to cache entries returned by readdir */ + uint32_t cache_readdir : 1; + + uint32_t auto_cache : 1; + + /** File handle. May be filled in by filesystem in open(). + Available in all other file operations */ + uint64_t fh; + + /** Lock owner id. Available in locking operations and flush */ + uint64_t lock_owner; +}; + +/** + * Capability bits for 'fuse_conn_info.capable' and 'fuse_conn_info.want' + * + * FUSE_CAP_ASYNC_READ: filesystem supports asynchronous read requests + * FUSE_CAP_POSIX_LOCKS: filesystem supports "remote" locking + * FUSE_CAP_ATOMIC_O_TRUNC: filesystem handles the O_TRUNC open flag + * FUSE_CAP_EXPORT_SUPPORT: filesystem handles lookups of "." and ".." + * FUSE_CAP_BIG_WRITES: filesystem can handle write size larger than 4kB + * FUSE_CAP_DONT_MASK: don't apply umask to file mode on create operations + * FUSE_CAP_SPLICE_WRITE: ability to use splice() to write to the fuse device + * FUSE_CAP_SPLICE_MOVE: ability to move data to the fuse device with splice() + * FUSE_CAP_SPLICE_READ: ability to use splice() to read from the fuse device + * FUSE_CAP_IOCTL_DIR: ioctl support on directories + * FUSE_CAP_CACHE_SYMLINKS: cache READLINK responses + */ #define FUSE_CAP_ASYNC_READ (1 << 0) #define FUSE_CAP_POSIX_LOCKS (1 << 1) #define FUSE_CAP_ATOMIC_O_TRUNC (1 << 3) @@ -127,16 +127,16 @@ extern "C" { #define FUSE_CAP_CACHE_SYMLINKS (1 << 20) #define FUSE_CAP_MAX_PAGES (1 << 21) - /** - * Ioctl flags - * - * FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine - * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed - * FUSE_IOCTL_RETRY: retry with new iovecs - * FUSE_IOCTL_DIR: is a directory - * - * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs - */ +/** + * Ioctl flags + * + * FUSE_IOCTL_COMPAT: 32bit compat ioctl on 64bit machine + * FUSE_IOCTL_UNRESTRICTED: not restricted to well-formed ioctls, retry allowed + * FUSE_IOCTL_RETRY: retry with new iovecs + * FUSE_IOCTL_DIR: is a directory + * + * FUSE_IOCTL_MAX_IOV: maximum of in_iovecs + out_iovecs + */ #define FUSE_IOCTL_COMPAT (1 << 0) #define FUSE_IOCTL_UNRESTRICTED (1 << 1) #define FUSE_IOCTL_RETRY (1 << 2) @@ -144,282 +144,282 @@ extern "C" { #define FUSE_IOCTL_MAX_IOV 256 +/** + * Connection information, passed to the ->init() method + * + * Some of the elements are read-write, these can be changed to + * indicate the value requested by the filesystem. The requested + * value must usually be smaller than the indicated value. + */ +struct fuse_conn_info { /** - * Connection information, passed to the ->init() method - * - * Some of the elements are read-write, these can be changed to - * indicate the value requested by the filesystem. The requested - * value must usually be smaller than the indicated value. + * Major version of the protocol (read-only) */ - struct fuse_conn_info { - /** - * Major version of the protocol (read-only) - */ - unsigned proto_major; - - /** - * Minor version of the protocol (read-only) - */ - unsigned proto_minor; - - /** - * Maximum size of the write buffer - */ - unsigned max_write; - - /** - * Maximum readahead - */ - unsigned max_readahead; - - /** - * Capability flags, that the kernel supports - */ - unsigned capable; - - /** - * Capability flags, that the filesystem wants to enable - */ - unsigned want; - - /** - * Maximum number of backgrounded requests - */ - unsigned max_background; - - /** - * Kernel congestion threshold parameter - */ - unsigned congestion_threshold; - - /** - * Max pages - */ - uint16_t max_pages; - - /** - * For future use. - */ - unsigned reserved[22]; - }; - - struct fuse_session; - struct fuse_chan; - struct fuse_pollhandle; + unsigned proto_major; /** - * Create a FUSE mountpoint - * - * Returns a control file descriptor suitable for passing to - * fuse_new() - * - * @param mountpoint the mount point path - * @param args argument vector - * @return the communication channel on success, NULL on failure + * Minor version of the protocol (read-only) + */ + unsigned proto_minor; + + /** + * Maximum size of the write buffer + */ + unsigned max_write; + + /** + * Maximum readahead + */ + unsigned max_readahead; + + /** + * Capability flags, that the kernel supports */ - struct fuse_chan *fuse_mount(const char *mountpoint, - struct fuse_args *args); + unsigned capable; /** - * Umount a FUSE mountpoint + * Capability flags, that the filesystem wants to enable + */ + unsigned want; + + /** + * Maximum number of backgrounded requests + */ + unsigned max_background; + + /** + * Kernel congestion threshold parameter + */ + unsigned congestion_threshold; + + /** + * Max pages + */ + uint16_t max_pages; + + /** + * For future use. + */ + unsigned reserved[22]; +}; + +struct fuse_session; +struct fuse_chan; +struct fuse_pollhandle; + +/** + * Create a FUSE mountpoint + * + * Returns a control file descriptor suitable for passing to + * fuse_new() + * + * @param mountpoint the mount point path + * @param args argument vector + * @return the communication channel on success, NULL on failure + */ +struct fuse_chan *fuse_mount(const char *mountpoint, + struct fuse_args *args); + +/** + * Umount a FUSE mountpoint + * + * @param mountpoint the mount point path + * @param ch the communication channel + */ +void fuse_unmount(const char *mountpoint, struct fuse_chan *ch); + +/** + * Parse common options + * + * The following options are parsed: + * + * '-f' foreground + * '-d' '-odebug' foreground, but keep the debug option + * '-h' '--help' help + * '-ho' help without header + * '-ofsname=..' file system name, if not present, then set to the program + * name + * + * All parameters may be NULL + * + * @param args argument vector + * @param mountpoint the returned mountpoint, should be freed after use + * @param foreground set to 1 if one of the relevant options is present + * @return 0 on success, -1 on failure + */ +int fuse_parse_cmdline(struct fuse_args *args, + char **mountpoint, + int *foreground); + +/** + * Go into the background + * + * @param foreground if true, stay in the foreground + * @return 0 on success, -1 on failure + */ +int fuse_daemonize(int foreground); + +/** + * Get the version of the library + * + * @return the version + */ +int fuse_version(void); + +/** + * Destroy poll handle + * + * @param ph the poll handle + */ +void fuse_pollhandle_destroy(struct fuse_pollhandle *ph); + +/* ----------------------------------------------------------- * + * Data buffer * + * ----------------------------------------------------------- */ + +/** + * Buffer flags + */ +enum fuse_buf_flags { + /** + * Buffer contains a file descriptor * - * @param mountpoint the mount point path - * @param ch the communication channel + * If this flag is set, the .fd field is valid, otherwise the + * .mem fields is valid. */ - void fuse_unmount(const char *mountpoint, struct fuse_chan *ch); + FUSE_BUF_IS_FD = (1 << 1), /** - * Parse common options + * Seek on the file descriptor * - * The following options are parsed: + * If this flag is set then the .pos field is valid and is + * used to seek to the given offset before performing + * operation on file descriptor. + */ + FUSE_BUF_FD_SEEK = (1 << 2), + + /** + * Retry operation on file descriptor * - * '-f' foreground - * '-d' '-odebug' foreground, but keep the debug option - * '-h' '--help' help - * '-ho' help without header - * '-ofsname=..' file system name, if not present, then set to the program - * name + * If this flag is set then retry operation on file descriptor + * until .size bytes have been copied or an error or EOF is + * detected. + */ + FUSE_BUF_FD_RETRY = (1 << 3), +}; + +/** + * Buffer copy flags + */ +enum fuse_buf_copy_flags { + /** + * Don't use splice(2) * - * All parameters may be NULL + * Always fall back to using read and write instead of + * splice(2) to copy data from one file descriptor to another. * - * @param args argument vector - * @param mountpoint the returned mountpoint, should be freed after use - * @param foreground set to 1 if one of the relevant options is present - * @return 0 on success, -1 on failure + * If this flag is not set, then only fall back if splice is + * unavailable. */ - int fuse_parse_cmdline(struct fuse_args *args, - char **mountpoint, - int *foreground); + FUSE_BUF_NO_SPLICE = (1 << 1), /** - * Go into the background + * Force splice * - * @param foreground if true, stay in the foreground - * @return 0 on success, -1 on failure + * Always use splice(2) to copy data from one file descriptor + * to another. If splice is not available, return -EINVAL. */ - int fuse_daemonize(int foreground); + FUSE_BUF_FORCE_SPLICE = (1 << 2), /** - * Get the version of the library + * Try to move data with splice. * - * @return the version + * If splice is used, try to move pages from the source to the + * destination instead of copying. See documentation of + * SPLICE_F_MOVE in splice(2) man page. */ - int fuse_version(void); + FUSE_BUF_SPLICE_MOVE = (1 << 3), /** - * Destroy poll handle + * Don't block on the pipe when copying data with splice * - * @param ph the poll handle + * Makes the operations on the pipe non-blocking (if the pipe + * is full or empty). See SPLICE_F_NONBLOCK in the splice(2) + * man page. */ - void fuse_pollhandle_destroy(struct fuse_pollhandle *ph); - - /* ----------------------------------------------------------- * - * Data buffer * - * ----------------------------------------------------------- */ + FUSE_BUF_SPLICE_NONBLOCK= (1 << 4), +}; + +/** + * Single data buffer + * + * Generic data buffer for I/O, extended attributes, etc... Data may + * be supplied as a memory pointer or as a file descriptor + */ +struct fuse_buf { + /** + * Size of data in bytes + */ + size_t size; /** * Buffer flags */ - enum fuse_buf_flags { - /** - * Buffer contains a file descriptor - * - * If this flag is set, the .fd field is valid, otherwise the - * .mem fields is valid. - */ - FUSE_BUF_IS_FD = (1 << 1), - - /** - * Seek on the file descriptor - * - * If this flag is set then the .pos field is valid and is - * used to seek to the given offset before performing - * operation on file descriptor. - */ - FUSE_BUF_FD_SEEK = (1 << 2), - - /** - * Retry operation on file descriptor - * - * If this flag is set then retry operation on file descriptor - * until .size bytes have been copied or an error or EOF is - * detected. - */ - FUSE_BUF_FD_RETRY = (1 << 3), - }; + enum fuse_buf_flags flags; /** - * Buffer copy flags + * Memory pointer + * + * Used unless FUSE_BUF_IS_FD flag is set. */ - enum fuse_buf_copy_flags { - /** - * Don't use splice(2) - * - * Always fall back to using read and write instead of - * splice(2) to copy data from one file descriptor to another. - * - * If this flag is not set, then only fall back if splice is - * unavailable. - */ - FUSE_BUF_NO_SPLICE = (1 << 1), - - /** - * Force splice - * - * Always use splice(2) to copy data from one file descriptor - * to another. If splice is not available, return -EINVAL. - */ - FUSE_BUF_FORCE_SPLICE = (1 << 2), - - /** - * Try to move data with splice. - * - * If splice is used, try to move pages from the source to the - * destination instead of copying. See documentation of - * SPLICE_F_MOVE in splice(2) man page. - */ - FUSE_BUF_SPLICE_MOVE = (1 << 3), - - /** - * Don't block on the pipe when copying data with splice - * - * Makes the operations on the pipe non-blocking (if the pipe - * is full or empty). See SPLICE_F_NONBLOCK in the splice(2) - * man page. - */ - FUSE_BUF_SPLICE_NONBLOCK= (1 << 4), - }; + void *mem; /** - * Single data buffer + * File descriptor * - * Generic data buffer for I/O, extended attributes, etc... Data may - * be supplied as a memory pointer or as a file descriptor + * Used if FUSE_BUF_IS_FD flag is set. */ - struct fuse_buf { - /** - * Size of data in bytes - */ - size_t size; - - /** - * Buffer flags - */ - enum fuse_buf_flags flags; - - /** - * Memory pointer - * - * Used unless FUSE_BUF_IS_FD flag is set. - */ - void *mem; - - /** - * File descriptor - * - * Used if FUSE_BUF_IS_FD flag is set. - */ - int fd; - - /** - * File position - * - * Used if FUSE_BUF_FD_SEEK flag is set. - */ - off_t pos; - }; + int fd; /** - * Data buffer vector - * - * An array of data buffers, each containing a memory pointer or a - * file descriptor. + * File position * - * Allocate dynamically to add more than one buffer. + * Used if FUSE_BUF_FD_SEEK flag is set. + */ + off_t pos; +}; + +/** + * Data buffer vector + * + * An array of data buffers, each containing a memory pointer or a + * file descriptor. + * + * Allocate dynamically to add more than one buffer. + */ +struct fuse_bufvec { + /** + * Number of buffers in the array + */ + size_t count; + + /** + * Index of current buffer within the array + */ + size_t idx; + + /** + * Current offset within the current buffer + */ + size_t off; + + /** + * Array of buffers */ - struct fuse_bufvec { - /** - * Number of buffers in the array - */ - size_t count; - - /** - * Index of current buffer within the array - */ - size_t idx; - - /** - * Current offset within the current buffer - */ - size_t off; - - /** - * Array of buffers - */ - struct fuse_buf buf[1]; - }; - - /* Initialize bufvec with a single buffer of given size */ + struct fuse_buf buf[1]; +}; + +/* Initialize bufvec with a single buffer of given size */ #define FUSE_BUFVEC_INIT(size__) \ ((struct fuse_bufvec) { \ /* .count= */ 1, \ @@ -434,52 +434,50 @@ extern "C" { } } \ } ) - /** - * Get total size of data in a fuse buffer vector - * - * @param bufv buffer vector - * @return size of data - */ - size_t fuse_buf_size(const struct fuse_bufvec *bufv); - - /** - * Copy data from one buffer vector to another - * - * @param dst destination buffer vector - * @param src source buffer vector - * @param flags flags controlling the copy - * @return actual number of bytes copied or -errno on error - */ - ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src, - enum fuse_buf_copy_flags flags); - - /* ----------------------------------------------------------- * - * Signal handling * - * ----------------------------------------------------------- */ - - /** - * Exit session on HUP, TERM and INT signals and ignore PIPE signal - * - * Stores session in a global variable. May only be called once per - * process until fuse_remove_signal_handlers() is called. - * - * @param se the session to exit - * @return 0 on success, -1 on failure - */ - int fuse_set_signal_handlers(struct fuse_session *se); - - /** - * Restore default signal handlers - * - * Resets global session. After this fuse_set_signal_handlers() may - * be called again. - * - * @param se the same session as given in fuse_set_signal_handlers() - */ - void fuse_remove_signal_handlers(struct fuse_session *se); - -#ifdef __cplusplus -} -#endif +/** + * Get total size of data in a fuse buffer vector + * + * @param bufv buffer vector + * @return size of data + */ +size_t fuse_buf_size(const struct fuse_bufvec *bufv); + +/** + * Copy data from one buffer vector to another + * + * @param dst destination buffer vector + * @param src source buffer vector + * @param flags flags controlling the copy + * @return actual number of bytes copied or -errno on error + */ +ssize_t fuse_buf_copy(struct fuse_bufvec *dst, struct fuse_bufvec *src, + enum fuse_buf_copy_flags flags); + +/* ----------------------------------------------------------- * + * Signal handling * + * ----------------------------------------------------------- */ + +/** + * Exit session on HUP, TERM and INT signals and ignore PIPE signal + * + * Stores session in a global variable. May only be called once per + * process until fuse_remove_signal_handlers() is called. + * + * @param se the session to exit + * @return 0 on success, -1 on failure + */ +int fuse_set_signal_handlers(struct fuse_session *se); + +/** + * Restore default signal handlers + * + * Resets global session. After this fuse_set_signal_handlers() may + * be called again. + * + * @param se the same session as given in fuse_set_signal_handlers() + */ +void fuse_remove_signal_handlers(struct fuse_session *se); + +EXTERN_C_END #endif /* _FUSE_COMMON_H_ */ diff --git a/libfuse/include/fuse_lowlevel.h b/libfuse/include/fuse_lowlevel.h index ffb7e1f0..133ec1c5 100644 --- a/libfuse/include/fuse_lowlevel.h +++ b/libfuse/include/fuse_lowlevel.h @@ -23,6 +23,7 @@ #define FUSE_USE_VERSION 24 #endif +#include "extern_c.h" #include "fuse_common.h" #include @@ -33,1780 +34,1700 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN - /* ----------------------------------------------------------- * - * Miscellaneous definitions * - * ----------------------------------------------------------- */ +/* ----------------------------------------------------------- * + * Miscellaneous definitions * + * ----------------------------------------------------------- */ - /** The node ID of the root inode */ +/** The node ID of the root inode */ #define FUSE_ROOT_ID 1 - /** Inode number type */ - typedef uint64_t fuse_ino_t; +/** Inode number type */ +typedef uint64_t fuse_ino_t; - /** Request pointer type */ - typedef struct fuse_req *fuse_req_t; +/** Request pointer type */ +typedef struct fuse_req *fuse_req_t; - /** - * Session - * - * This provides hooks for processing requests, and exiting - */ - struct fuse_session; +/** + * Session + * + * This provides hooks for processing requests, and exiting + */ +struct fuse_session; - /** - * Channel - * - * A communication channel, providing hooks for sending and receiving - * messages - */ - struct fuse_chan; - - /** Directory entry parameters supplied to fuse_reply_entry() */ - struct fuse_entry_param - { - /** Unique inode number - * - * In lookup, zero means negative entry (from version 2.5) - * Returning ENOENT also means negative entry, but by setting zero - * ino the kernel may cache negative entries for entry_timeout - * seconds. - */ - fuse_ino_t ino; - - /** Generation number for this entry. - * - * If the file system will be exported over NFS, the - * ino/generation pairs need to be unique over the file - * system's lifetime (rather than just the mount time). So if - * the file system reuses an inode after it has been deleted, - * it must assign a new, previously unused generation number - * to the inode at the same time. - * - * The generation must be non-zero, otherwise FUSE will treat - * it as an error. - * - */ - uint64_t generation; - - - /** Inode attributes. - * - * Even if attr_timeout == 0, attr must be correct. For example, - * for open(), FUSE uses attr.st_size from lookup() to determine - * how many bytes to request. If this value is not correct, - * incorrect data will be returned. - */ - struct stat attr; - - fuse_timeouts_t timeout; - }; - - /** Additional context associated with requests */ - struct fuse_ctx - { - /** User ID of the calling process */ - uid_t uid; - - /** Group ID of the calling process */ - gid_t gid; - - /** Thread ID of the calling process */ - pid_t pid; - - /** Umask of the calling process (introduced in version 2.8) */ - mode_t umask; - }; - - struct fuse_forget_data - { - fuse_ino_t ino; - uint64_t nlookup; - }; - - /* ----------------------------------------------------------- * - * Request methods and replies * - * ----------------------------------------------------------- */ +/** + * Channel + * + * A communication channel, providing hooks for sending and receiving + * messages + */ +struct fuse_chan; - /** - * Low level filesystem operations - * - * Most of the methods (with the exception of init and destroy) - * receive a request handle (fuse_req_t) as their first argument. - * This handle must be passed to one of the specified reply functions. - * - * This may be done inside the method invocation, or after the call - * has returned. The request handle is valid until one of the reply - * functions is called. - * - * Other pointer arguments (name, fuse_file_info, etc) are not valid - * after the call has returned, so if they are needed later, their - * contents have to be copied. - * - * The filesystem sometimes needs to handle a return value of -ENOENT - * from the reply function, which means, that the request was - * interrupted, and the reply discarded. For example if - * fuse_reply_open() return -ENOENT means, that the release method for - * this file will not be called. - */ - struct fuse_lowlevel_ops - { - /** - * Initialize filesystem - * - * Called before any other filesystem method - * - * There's no reply to this function - * - * @param userdata the user data passed to fuse_lowlevel_new() - */ - void (*init) (void *userdata, struct fuse_conn_info *conn); - - /** - * Clean up filesystem - * - * Called on filesystem exit - * - * There's no reply to this function - * - * @param userdata the user data passed to fuse_lowlevel_new() - */ - void (*destroy) (void *userdata); - - /** - * Look up a directory entry by name and get its attributes. - * - * Valid replies: - * fuse_reply_entry - * fuse_reply_err - * - * @param req request handle - * @param parent inode number of the parent directory - * @param name the name to look up - */ - void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name); - - /** - * Forget about an inode - * - * This function is called when the kernel removes an inode - * from its internal caches. - * - * The inode's lookup count increases by one for every call to - * fuse_reply_entry and fuse_reply_create. The nlookup parameter - * indicates by how much the lookup count should be decreased. - * - * Inodes with a non-zero lookup count may receive request from - * the kernel even after calls to unlink, rmdir or (when - * overwriting an existing file) rename. Filesystems must handle - * such requests properly and it is recommended to defer removal - * of the inode until the lookup count reaches zero. Calls to - * unlink, remdir or rename will be followed closely by forget - * unless the file or directory is open, in which case the - * kernel issues forget only after the release or releasedir - * calls. - * - * Note that if a file system will be exported over NFS the - * inodes lifetime must extend even beyond forget. See the - * generation field in struct fuse_entry_param above. - * - * On unmount the lookup count for all inodes implicitly drops - * to zero. It is not guaranteed that the file system will - * receive corresponding forget messages for the affected - * inodes. - * - * Valid replies: - * fuse_reply_none - * - * @param req request handle - * @param ino the inode number - * @param nlookup the number of lookups to forget - */ - void (*forget) (fuse_req_t req, fuse_ino_t ino, uint64_t nlookup); - - /** - * Get file attributes - * - * Valid replies: - * fuse_reply_attr - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi for future use, currently always NULL - */ - void (*getattr) (fuse_req_t req, fuse_ino_t ino, - struct fuse_file_info *fi); +/** Directory entry parameters supplied to fuse_reply_entry() */ +struct fuse_entry_param +{ +/** Unique inode number + * + * In lookup, zero means negative entry (from version 2.5) + * Returning ENOENT also means negative entry, but by setting zero + * ino the kernel may cache negative entries for entry_timeout + * seconds. + */ +fuse_ino_t ino; - /** - * Set file attributes - * - * In the 'attr' argument only members indicated by the 'to_set' - * bitmask contain valid values. Other members contain undefined - * values. - * - * If the setattr was invoked from the ftruncate() system call - * under Linux kernel versions 2.6.15 or later, the fi->fh will - * contain the value set by the open method or will be undefined - * if the open method didn't set any value. Otherwise (not - * ftruncate call, or kernel version earlier than 2.6.15) the fi - * parameter will be NULL. - * - * Valid replies: - * fuse_reply_attr - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param attr the attributes - * @param to_set bit mask of attributes which should be set - * @param fi file information, or NULL - * - * Changed in version 2.5: - * file information filled in for ftruncate - */ - void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr, - int to_set, struct fuse_file_info *fi); - - /** - * Read symbolic link - * - * Valid replies: - * fuse_reply_readlink - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - */ - void (*readlink) (fuse_req_t req, fuse_ino_t ino); - - /** - * Create file node - * - * Create a regular file, character device, block device, fifo or - * socket node. - * - * Valid replies: - * fuse_reply_entry - * fuse_reply_err - * - * @param req request handle - * @param parent inode number of the parent directory - * @param name to create - * @param mode file type and mode with which to create the new file - * @param rdev the device number (only valid if created file is a device) - */ - void (*mknod) (fuse_req_t req, fuse_ino_t parent, const char *name, - mode_t mode, dev_t rdev); - - /** - * Create a directory - * - * Valid replies: - * fuse_reply_entry - * fuse_reply_err - * - * @param req request handle - * @param parent inode number of the parent directory - * @param name to create - * @param mode with which to create the new file - */ - void (*mkdir) (fuse_req_t req, fuse_ino_t parent, const char *name, - mode_t mode); - - /** - * Remove a file - * - * If the file's inode's lookup count is non-zero, the file - * system is expected to postpone any removal of the inode - * until the lookup count reaches zero (see description of the - * forget function). - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param parent inode number of the parent directory - * @param name to remove - */ - void (*unlink) (fuse_req_t req, fuse_ino_t parent, const char *name); - - /** - * Remove a directory - * - * If the directory's inode's lookup count is non-zero, the - * file system is expected to postpone any removal of the - * inode until the lookup count reaches zero (see description - * of the forget function). - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param parent inode number of the parent directory - * @param name to remove - */ - void (*rmdir) (fuse_req_t req, fuse_ino_t parent, const char *name); - - /** - * Create a symbolic link - * - * Valid replies: - * fuse_reply_entry - * fuse_reply_err - * - * @param req request handle - * @param link the contents of the symbolic link - * @param parent inode number of the parent directory - * @param name to create - */ - void (*symlink) (fuse_req_t req, const char *link, fuse_ino_t parent, - const char *name); - - /** Rename a file - * - * If the target exists it should be atomically replaced. If - * the target's inode's lookup count is non-zero, the file - * system is expected to postpone any removal of the inode - * until the lookup count reaches zero (see description of the - * forget function). - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param parent inode number of the old parent directory - * @param name old name - * @param newparent inode number of the new parent directory - * @param newname new name - */ - void (*rename) (fuse_req_t req, fuse_ino_t parent, const char *name, - fuse_ino_t newparent, const char *newname); - - /** - * Create a hard link - * - * Valid replies: - * fuse_reply_entry - * fuse_reply_err - * - * @param req request handle - * @param ino the old inode number - * @param newparent inode number of the new parent directory - * @param newname new name to create - */ - void (*link) (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, - const char *newname); - - /** - * Open a file - * - * Open flags (with the exception of O_CREAT, O_EXCL, O_NOCTTY and - * O_TRUNC) are available in fi->flags. - * - * Filesystem may store an arbitrary file handle (pointer, index, - * etc) in fi->fh, and use this in other all other file operations - * (read, write, flush, release, fsync). - * - * Filesystem may also implement stateless file I/O and not store - * anything in fi->fh. - * - * There are also some flags (direct_io, keep_cache) which the - * filesystem may set in fi, to change the way the file is opened. - * See fuse_file_info structure in for more details. - * - * Valid replies: - * fuse_reply_open - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi file information - */ - void (*open) (fuse_req_t req, fuse_ino_t ino, - struct fuse_file_info *fi); - - /** - * Read data - * - * Read should send exactly the number of bytes requested except - * on EOF or error, otherwise the rest of the data will be - * substituted with zeroes. An exception to this is when the file - * has been opened in 'direct_io' mode, in which case the return - * value of the read system call will reflect the return value of - * this operation. - * - * fi->fh will contain the value set by the open method, or will - * be undefined if the open method didn't set any value. - * - * Valid replies: - * fuse_reply_buf - * fuse_reply_iov - * fuse_reply_data - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param size number of bytes to read - * @param off offset to read from - * @param fi file information - */ - void (*read) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, - struct fuse_file_info *fi); - - /** - * Write data - * - * Write should return exactly the number of bytes requested - * except on error. An exception to this is when the file has - * been opened in 'direct_io' mode, in which case the return value - * of the write system call will reflect the return value of this - * operation. - * - * fi->fh will contain the value set by the open method, or will - * be undefined if the open method didn't set any value. - * - * Valid replies: - * fuse_reply_write - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param buf data to write - * @param size number of bytes to write - * @param off offset to write to - * @param fi file information - */ - void (*write) (fuse_req_t req, fuse_ino_t ino, const char *buf, - size_t size, off_t off, struct fuse_file_info *fi); - - /** - * Flush method - * - * This is called on each close() of the opened file. - * - * Since file descriptors can be duplicated (dup, dup2, fork), for - * one open call there may be many flush calls. - * - * Filesystems shouldn't assume that flush will always be called - * after some writes, or that if will be called at all. - * - * fi->fh will contain the value set by the open method, or will - * be undefined if the open method didn't set any value. - * - * NOTE: the name of the method is misleading, since (unlike - * fsync) the filesystem is not forced to flush pending writes. - * One reason to flush data, is if the filesystem wants to return - * write errors. - * - * If the filesystem supports file locking operations (setlk, - * getlk) it should remove all locks belonging to 'fi->owner'. - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi file information - */ - void (*flush) (fuse_req_t req, fuse_ino_t ino, - struct fuse_file_info *fi); +/** Generation number for this entry. + * + * If the file system will be exported over NFS, the + * ino/generation pairs need to be unique over the file + * system's lifetime (rather than just the mount time). So if + * the file system reuses an inode after it has been deleted, + * it must assign a new, previously unused generation number + * to the inode at the same time. + * + * The generation must be non-zero, otherwise FUSE will treat + * it as an error. + * + */ +uint64_t generation; - /** - * Release an open file - * - * Release is called when there are no more references to an open - * file: all file descriptors are closed and all memory mappings - * are unmapped. - * - * For every open call there will be exactly one release call. - * - * The filesystem may reply with an error, but error values are - * not returned to close() or munmap() which triggered the - * release. - * - * fi->fh will contain the value set by the open method, or will - * be undefined if the open method didn't set any value. - * fi->flags will contain the same flags as for open. - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi file information - */ - void (*release) (fuse_req_t req, fuse_ino_t ino, - struct fuse_file_info *fi); - /** - * Synchronize file contents - * - * If the datasync parameter is non-zero, then only the user data - * should be flushed, not the meta data. - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param datasync flag indicating if only data should be flushed - * @param fi file information - */ - void (*fsync) (fuse_req_t req, fuse_ino_t ino, int datasync, - struct fuse_file_info *fi); +/** Inode attributes. + * + * Even if attr_timeout == 0, attr must be correct. For example, + * for open(), FUSE uses attr.st_size from lookup() to determine + * how many bytes to request. If this value is not correct, + * incorrect data will be returned. + */ +struct stat attr; - /** - * Open a directory - * - * Filesystem may store an arbitrary file handle (pointer, index, - * etc) in fi->fh, and use this in other all other directory - * stream operations (readdir, releasedir, fsyncdir). - * - * Filesystem may also implement stateless directory I/O and not - * store anything in fi->fh, though that makes it impossible to - * implement standard conforming directory stream operations in - * case the contents of the directory can change between opendir - * and releasedir. - * - * Valid replies: - * fuse_reply_open - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi file information - */ - void (*opendir) (fuse_req_t req, fuse_ino_t ino, - struct fuse_file_info *fi); +fuse_timeouts_t timeout; +}; - /** - * Read directory - * - * Send a buffer filled using fuse_add_direntry(), with size not - * exceeding the requested size. Send an empty buffer on end of - * stream. - * - * fi->fh will contain the value set by the opendir method, or - * will be undefined if the opendir method didn't set any value. - * - * Valid replies: - * fuse_reply_buf - * fuse_reply_data - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param size maximum number of bytes to send - * @param off offset to continue reading the directory stream - * @param fi file information - */ - void (*readdir) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, - struct fuse_file_info *llffi); - - void (*readdir_plus)(fuse_req_t req, fuse_ino_t ino, - size_t size, off_t off, - struct fuse_file_info *ffi); - - /** - * Release an open directory - * - * For every opendir call there will be exactly one releasedir - * call. - * - * fi->fh will contain the value set by the opendir method, or - * will be undefined if the opendir method didn't set any value. - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi file information - */ - void (*releasedir) (fuse_req_t req, fuse_ino_t ino, - struct fuse_file_info *fi); - - /** - * Synchronize directory contents - * - * If the datasync parameter is non-zero, then only the directory - * contents should be flushed, not the meta data. - * - * fi->fh will contain the value set by the opendir method, or - * will be undefined if the opendir method didn't set any value. - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param datasync flag indicating if only data should be flushed - * @param fi file information - */ - void (*fsyncdir) (fuse_req_t req, fuse_ino_t ino, int datasync, - struct fuse_file_info *fi); +/** Additional context associated with requests */ +struct fuse_ctx +{ +/** User ID of the calling process */ +uid_t uid; + +/** Group ID of the calling process */ +gid_t gid; + +/** Thread ID of the calling process */ +pid_t pid; + +/** Umask of the calling process (introduced in version 2.8) */ +mode_t umask; +}; + +struct fuse_forget_data +{ +fuse_ino_t ino; +uint64_t nlookup; +}; + +/* ----------------------------------------------------------- * + * Request methods and replies * + * ----------------------------------------------------------- */ + +/** + * Low level filesystem operations + * + * Most of the methods (with the exception of init and destroy) + * receive a request handle (fuse_req_t) as their first argument. + * This handle must be passed to one of the specified reply functions. + * + * This may be done inside the method invocation, or after the call + * has returned. The request handle is valid until one of the reply + * functions is called. + * + * Other pointer arguments (name, fuse_file_info, etc) are not valid + * after the call has returned, so if they are needed later, their + * contents have to be copied. + * + * The filesystem sometimes needs to handle a return value of -ENOENT + * from the reply function, which means, that the request was + * interrupted, and the reply discarded. For example if + * fuse_reply_open() return -ENOENT means, that the release method for + * this file will not be called. + */ +struct fuse_lowlevel_ops +{ +/** + * Initialize filesystem + * + * Called before any other filesystem method + * + * There's no reply to this function + * + * @param userdata the user data passed to fuse_lowlevel_new() + */ +void (*init) (void *userdata, struct fuse_conn_info *conn); + +/** + * Clean up filesystem + * + * Called on filesystem exit + * + * There's no reply to this function + * + * @param userdata the user data passed to fuse_lowlevel_new() + */ +void (*destroy) (void *userdata); - /** - * Get file system statistics - * - * Valid replies: - * fuse_reply_statfs - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number, zero means "undefined" - */ - void (*statfs) (fuse_req_t req, fuse_ino_t ino); - - /** - * Set an extended attribute - * - * Valid replies: - * fuse_reply_err - */ - void (*setxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, - const char *value, size_t size, int flags); - - /** - * Get an extended attribute - * - * If size is zero, the size of the value should be sent with - * fuse_reply_xattr. - * - * If the size is non-zero, and the value fits in the buffer, the - * value should be sent with fuse_reply_buf. - * - * If the size is too small for the value, the ERANGE error should - * be sent. - * - * Valid replies: - * fuse_reply_buf - * fuse_reply_data - * fuse_reply_xattr - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param name of the extended attribute - * @param size maximum size of the value to send - */ - void (*getxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, - size_t size); - - /** - * List extended attribute names - * - * If size is zero, the total size of the attribute list should be - * sent with fuse_reply_xattr. - * - * If the size is non-zero, and the null character separated - * attribute list fits in the buffer, the list should be sent with - * fuse_reply_buf. - * - * If the size is too small for the list, the ERANGE error should - * be sent. - * - * Valid replies: - * fuse_reply_buf - * fuse_reply_data - * fuse_reply_xattr - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param size maximum size of the list to send - */ - void (*listxattr) (fuse_req_t req, fuse_ino_t ino, size_t size); - - /** - * Remove an extended attribute - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param name of the extended attribute - */ - void (*removexattr) (fuse_req_t req, fuse_ino_t ino, const char *name); - - /** - * Check file access permissions - * - * This will be called for the access() system call. If the - * 'default_permissions' mount option is given, this method is not - * called. - * - * This method is not called under Linux kernel versions 2.4.x - * - * Introduced in version 2.5 - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param mask requested access mode - */ - void (*access) (fuse_req_t req, fuse_ino_t ino, int mask); - - /** - * Create and open a file - * - * If the file does not exist, first create it with the specified - * mode, and then open it. - * - * Open flags (with the exception of O_NOCTTY) are available in - * fi->flags. - * - * Filesystem may store an arbitrary file handle (pointer, index, - * etc) in fi->fh, and use this in other all other file operations - * (read, write, flush, release, fsync). - * - * There are also some flags (direct_io, keep_cache) which the - * filesystem may set in fi, to change the way the file is opened. - * See fuse_file_info structure in for more details. - * - * If this method is not implemented or under Linux kernel - * versions earlier than 2.6.15, the mknod() and open() methods - * will be called instead. - * - * Introduced in version 2.5 - * - * Valid replies: - * fuse_reply_create - * fuse_reply_err - * - * @param req request handle - * @param parent inode number of the parent directory - * @param name to create - * @param mode file type and mode with which to create the new file - * @param fi file information - */ - void (*create) (fuse_req_t req, fuse_ino_t parent, const char *name, - mode_t mode, struct fuse_file_info *fi); - - /** - * Test for a POSIX file lock - * - * Introduced in version 2.6 - * - * Valid replies: - * fuse_reply_lock - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi file information - * @param lock the region/type to test - */ - void (*getlk) (fuse_req_t req, fuse_ino_t ino, - struct fuse_file_info *fi, struct flock *lock); - - /** - * Acquire, modify or release a POSIX file lock - * - * For POSIX threads (NPTL) there's a 1-1 relation between pid and - * owner, but otherwise this is not always the case. For checking - * lock ownership, 'fi->owner' must be used. The l_pid field in - * 'struct flock' should only be used to fill in this field in - * getlk(). - * - * Note: if the locking methods are not implemented, the kernel - * will still allow file locking to work locally. Hence these are - * only interesting for network filesystems and similar. - * - * Introduced in version 2.6 - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi file information - * @param lock the region/type to set - * @param sleep locking operation may sleep - */ - void (*setlk) (fuse_req_t req, fuse_ino_t ino, - struct fuse_file_info *fi, - struct flock *lock, int sleep); - - /** - * Map block index within file to block index within device - * - * Note: This makes sense only for block device backed filesystems - * mounted with the 'blkdev' option - * - * Introduced in version 2.6 - * - * Valid replies: - * fuse_reply_bmap - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param blocksize unit of block index - * @param idx block index within file - */ - void (*bmap) (fuse_req_t req, fuse_ino_t ino, size_t blocksize, - uint64_t idx); - - /** - * Ioctl - * - * Note: For unrestricted ioctls (not allowed for FUSE - * servers), data in and out areas can be discovered by giving - * iovs and setting FUSE_IOCTL_RETRY in @flags. For - * restricted ioctls, kernel prepares in/out data area - * according to the information encoded in cmd. - * - * Introduced in version 2.8 - * - * Valid replies: - * fuse_reply_ioctl_retry - * fuse_reply_ioctl - * fuse_reply_ioctl_iov - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param cmd ioctl command - * @param arg ioctl argument - * @param fi file information - * @param flags for FUSE_IOCTL_* flags - * @param in_buf data fetched from the caller - * @param in_bufsz number of fetched bytes - * @param out_bufsz maximum size of output data - */ - void (*ioctl) (fuse_req_t req, fuse_ino_t ino, unsigned long cmd, void *arg, - struct fuse_file_info *fi, unsigned flags, - const void *in_buf, uint32_t in_bufsz, uint32_t out_bufsz); - - /** - * Poll for IO readiness - * - * Introduced in version 2.8 - * - * Note: If ph is non-NULL, the client should notify - * when IO readiness events occur by calling - * fuse_lowelevel_notify_poll() with the specified ph. - * - * Regardless of the number of times poll with a non-NULL ph - * is received, single notification is enough to clear all. - * Notifying more times incurs overhead but doesn't harm - * correctness. - * - * The callee is responsible for destroying ph with - * fuse_pollhandle_destroy() when no longer in use. - * - * Valid replies: - * fuse_reply_poll - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi file information - * @param ph poll handle to be used for notification - */ - void (*poll) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, - struct fuse_pollhandle *ph); - - /** - * Write data made available in a buffer - * - * This is a more generic version of the ->write() method. If - * FUSE_CAP_SPLICE_READ is set in fuse_conn_info.want and the - * kernel supports splicing from the fuse device, then the - * data will be made available in pipe for supporting zero - * copy data transfer. - * - * buf->count is guaranteed to be one (and thus buf->idx is - * always zero). The write_buf handler must ensure that - * bufv->off is correctly updated (reflecting the number of - * bytes read from bufv->buf[0]). - * - * Introduced in version 2.9 - * - * Valid replies: - * fuse_reply_write - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param bufv buffer containing the data - * @param off offset to write to - * @param fi file information - */ - void (*write_buf) (fuse_req_t req, fuse_ino_t ino, - struct fuse_bufvec *bufv, off_t off, - struct fuse_file_info *fi); - - /** - * Callback function for the retrieve request - * - * Introduced in version 2.9 - * - * Valid replies: - * fuse_reply_none - * - * @param req request handle - * @param cookie user data supplied to fuse_lowlevel_notify_retrieve() - * @param ino the inode number supplied to fuse_lowlevel_notify_retrieve() - * @param offset the offset supplied to fuse_lowlevel_notify_retrieve() - * @param bufv the buffer containing the returned data - */ - void (*retrieve_reply) (fuse_req_t req, void *cookie, fuse_ino_t ino, - off_t offset, struct fuse_bufvec *bufv); - - /** - * Forget about multiple inodes - * - * See description of the forget function for more - * information. - * - * Introduced in version 2.9 - * - * Valid replies: - * fuse_reply_none - * - * @param req request handle - */ - void (*forget_multi) (fuse_req_t req, size_t count, - struct fuse_forget_data *forgets); - - /** - * Acquire, modify or release a BSD file lock - * - * Note: if the locking methods are not implemented, the kernel - * will still allow file locking to work locally. Hence these are - * only interesting for network filesystems and similar. - * - * Introduced in version 2.9 - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param fi file information - * @param op the locking operation, see flock(2) - */ - void (*flock) (fuse_req_t req, fuse_ino_t ino, - struct fuse_file_info *fi, int op); - - /** - * Allocate requested space. If this function returns success then - * subsequent writes to the specified range shall not fail due to the lack - * of free space on the file system storage media. - * - * Introduced in version 2.9 - * - * Valid replies: - * fuse_reply_err - * - * @param req request handle - * @param ino the inode number - * @param offset starting point for allocated region - * @param length size of allocated region - * @param mode determines the operation to be performed on the given range, - * see fallocate(2) - */ - void (*fallocate) (fuse_req_t req, fuse_ino_t ino, int mode, - off_t offset, off_t length, struct fuse_file_info *fi); - - /** - * Copy a range of data from one file to another - * - * Performs an optimized copy between two file descriptors without - * the - * additional cost of transferring data through the FUSE kernel - * module - * to user space (glibc) and then back into the FUSE filesystem - * again. - * - * In case this method is not implemented, glibc falls back to - * reading - * data from the source and writing to the destination. Effectively - * doing an inefficient copy of the data. - * - * If this request is answered with an error code of ENOSYS, this is - * treated as a permanent failure with error code EOPNOTSUPP, - * i.e. all - * future copy_file_range() requests will fail with EOPNOTSUPP - * without - * being send to the filesystem process. - * - * Valid replies: - * fuse_reply_write - * fuse_reply_err - * - * @param req request handle - * @param ino_in the inode number of the source file - * @param off_in starting point from were the data should be read - * @param fi_in file information of the source file - * @param ino_out the inode number of the destination file - * @param off_out starting point where the data should be written - * @param fi_out file information of the destination file - * @param len maximum size of the data to copy - * @param flags passed along with the copy_file_range() syscall - */ - void (*copy_file_range)(fuse_req_t req, - fuse_ino_t ino_in, - off_t off_in, - struct fuse_file_info *fi_in, - fuse_ino_t ino_out, - off_t off_out, - struct fuse_file_info *fi_out, - size_t len, - int flags); - }; +/** + * Look up a directory entry by name and get its attributes. + * + * Valid replies: + * fuse_reply_entry + * fuse_reply_err + * + * @param req request handle + * @param parent inode number of the parent directory + * @param name the name to look up + */ +void (*lookup) (fuse_req_t req, fuse_ino_t parent, const char *name); + +/** + * Forget about an inode + * + * This function is called when the kernel removes an inode + * from its internal caches. + * + * The inode's lookup count increases by one for every call to + * fuse_reply_entry and fuse_reply_create. The nlookup parameter + * indicates by how much the lookup count should be decreased. + * + * Inodes with a non-zero lookup count may receive request from + * the kernel even after calls to unlink, rmdir or (when + * overwriting an existing file) rename. Filesystems must handle + * such requests properly and it is recommended to defer removal + * of the inode until the lookup count reaches zero. Calls to + * unlink, remdir or rename will be followed closely by forget + * unless the file or directory is open, in which case the + * kernel issues forget only after the release or releasedir + * calls. + * + * Note that if a file system will be exported over NFS the + * inodes lifetime must extend even beyond forget. See the + * generation field in struct fuse_entry_param above. + * + * On unmount the lookup count for all inodes implicitly drops + * to zero. It is not guaranteed that the file system will + * receive corresponding forget messages for the affected + * inodes. + * + * Valid replies: + * fuse_reply_none + * + * @param req request handle + * @param ino the inode number + * @param nlookup the number of lookups to forget + */ + void (*forget) (fuse_req_t req, fuse_ino_t ino, uint64_t nlookup); /** - * Reply with an error code or success + * Get file attributes * - * Possible requests: - * all except forget - * - * unlink, rmdir, rename, flush, release, fsync, fsyncdir, setxattr, - * removexattr and setlk may send a zero code + * Valid replies: + * fuse_reply_attr + * fuse_reply_err * * @param req request handle - * @param err the positive error value, or zero for success - * @return zero for success, -errno for failure to send reply + * @param ino the inode number + * @param fi for future use, currently always NULL */ - int fuse_reply_err(fuse_req_t req, int err); + void (*getattr) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); /** - * Don't send reply + * Set file attributes + * + * In the 'attr' argument only members indicated by the 'to_set' + * bitmask contain valid values. Other members contain undefined + * values. * - * Possible requests: - * forget + * If the setattr was invoked from the ftruncate() system call + * under Linux kernel versions 2.6.15 or later, the fi->fh will + * contain the value set by the open method or will be undefined + * if the open method didn't set any value. Otherwise (not + * ftruncate call, or kernel version earlier than 2.6.15) the fi + * parameter will be NULL. + * + * Valid replies: + * fuse_reply_attr + * fuse_reply_err * * @param req request handle + * @param ino the inode number + * @param attr the attributes + * @param to_set bit mask of attributes which should be set + * @param fi file information, or NULL + * + * Changed in version 2.5: + * file information filled in for ftruncate */ - void fuse_reply_none(fuse_req_t req); + void (*setattr) (fuse_req_t req, fuse_ino_t ino, struct stat *attr, + int to_set, struct fuse_file_info *fi); /** - * Reply with a directory entry - * - * Possible requests: - * lookup, mknod, mkdir, symlink, link + * Read symbolic link * - * Side effects: - * increments the lookup count on success + * Valid replies: + * fuse_reply_readlink + * fuse_reply_err * * @param req request handle - * @param e the entry parameters - * @return zero for success, -errno for failure to send reply + * @param ino the inode number */ - int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e); + void (*readlink) (fuse_req_t req, fuse_ino_t ino); /** - * Reply with a directory entry and open parameters - * - * currently the following members of 'fi' are used: - * fh, direct_io, keep_cache + * Create file node * - * Possible requests: - * create + * Create a regular file, character device, block device, fifo or + * socket node. * - * Side effects: - * increments the lookup count on success + * Valid replies: + * fuse_reply_entry + * fuse_reply_err * * @param req request handle - * @param e the entry parameters - * @param fi file information - * @return zero for success, -errno for failure to send reply + * @param parent inode number of the parent directory + * @param name to create + * @param mode file type and mode with which to create the new file + * @param rdev the device number (only valid if created file is a device) */ - int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, - const struct fuse_file_info *fi); + void (*mknod) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, dev_t rdev); /** - * Reply with attributes + * Create a directory * - * Possible requests: - * getattr, setattr + * Valid replies: + * fuse_reply_entry + * fuse_reply_err * * @param req request handle - * @param attr the attributes - * @param attr_timeout validity timeout (in seconds) for the attributes - * @return zero for success, -errno for failure to send reply + * @param parent inode number of the parent directory + * @param name to create + * @param mode with which to create the new file */ - int fuse_reply_attr(fuse_req_t req, - const struct stat *attr, - const uint64_t timeout); + void (*mkdir) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode); /** - * Reply with the contents of a symbolic link + * Remove a file * - * Possible requests: - * readlink + * If the file's inode's lookup count is non-zero, the file + * system is expected to postpone any removal of the inode + * until the lookup count reaches zero (see description of the + * forget function). + * + * Valid replies: + * fuse_reply_err * * @param req request handle - * @param link symbolic link contents - * @return zero for success, -errno for failure to send reply + * @param parent inode number of the parent directory + * @param name to remove */ - int fuse_reply_readlink(fuse_req_t req, const char *link); + void (*unlink) (fuse_req_t req, fuse_ino_t parent, const char *name); /** - * Reply with open parameters + * Remove a directory * - * currently the following members of 'fi' are used: - * fh, direct_io, keep_cache + * If the directory's inode's lookup count is non-zero, the + * file system is expected to postpone any removal of the + * inode until the lookup count reaches zero (see description + * of the forget function). * - * Possible requests: - * open, opendir + * Valid replies: + * fuse_reply_err * * @param req request handle - * @param fi file information - * @return zero for success, -errno for failure to send reply + * @param parent inode number of the parent directory + * @param name to remove */ - int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi); + void (*rmdir) (fuse_req_t req, fuse_ino_t parent, const char *name); /** - * Reply with number of bytes written + * Create a symbolic link * - * Possible requests: - * write + * Valid replies: + * fuse_reply_entry + * fuse_reply_err * * @param req request handle - * @param count the number of bytes written - * @return zero for success, -errno for failure to send reply + * @param link the contents of the symbolic link + * @param parent inode number of the parent directory + * @param name to create */ - int fuse_reply_write(fuse_req_t req, size_t count); + void (*symlink) (fuse_req_t req, const char *link, fuse_ino_t parent, + const char *name); - /** - * Reply with data + /** Rename a file * - * Possible requests: - * read, readdir, getxattr, listxattr + * If the target exists it should be atomically replaced. If + * the target's inode's lookup count is non-zero, the file + * system is expected to postpone any removal of the inode + * until the lookup count reaches zero (see description of the + * forget function). + * + * Valid replies: + * fuse_reply_err * * @param req request handle - * @param buf buffer containing data - * @param size the size of data in bytes - * @return zero for success, -errno for failure to send reply + * @param parent inode number of the old parent directory + * @param name old name + * @param newparent inode number of the new parent directory + * @param newname new name */ - int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size); + void (*rename) (fuse_req_t req, fuse_ino_t parent, const char *name, + fuse_ino_t newparent, const char *newname); /** - * Reply with data copied/moved from buffer(s) + * Create a hard link * - * Possible requests: - * read, readdir, getxattr, listxattr + * Valid replies: + * fuse_reply_entry + * fuse_reply_err * * @param req request handle - * @param bufv buffer vector - * @param flags flags controlling the copy - * @return zero for success, -errno for failure to send reply + * @param ino the old inode number + * @param newparent inode number of the new parent directory + * @param newname new name to create */ - int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv, - enum fuse_buf_copy_flags flags); + void (*link) (fuse_req_t req, fuse_ino_t ino, fuse_ino_t newparent, + const char *newname); /** - * Reply with data vector + * Open a file * - * Possible requests: - * read, readdir, getxattr, listxattr + * Open flags (with the exception of O_CREAT, O_EXCL, O_NOCTTY and + * O_TRUNC) are available in fi->flags. * - * @param req request handle - * @param iov the vector containing the data - * @param count the size of vector - * @return zero for success, -errno for failure to send reply - */ - int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count); - - /** - * Reply with filesystem statistics + * Filesystem may store an arbitrary file handle (pointer, index, + * etc) in fi->fh, and use this in other all other file operations + * (read, write, flush, release, fsync). + * + * Filesystem may also implement stateless file I/O and not store + * anything in fi->fh. + * + * There are also some flags (direct_io, keep_cache) which the + * filesystem may set in fi, to change the way the file is opened. + * See fuse_file_info structure in for more details. * - * Possible requests: - * statfs + * Valid replies: + * fuse_reply_open + * fuse_reply_err * * @param req request handle - * @param stbuf filesystem statistics - * @return zero for success, -errno for failure to send reply + * @param ino the inode number + * @param fi file information */ - int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf); + void (*open) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); /** - * Reply with needed buffer size + * Read data + * + * Read should send exactly the number of bytes requested except + * on EOF or error, otherwise the rest of the data will be + * substituted with zeroes. An exception to this is when the file + * has been opened in 'direct_io' mode, in which case the return + * value of the read system call will reflect the return value of + * this operation. + * + * fi->fh will contain the value set by the open method, or will + * be undefined if the open method didn't set any value. * - * Possible requests: - * getxattr, listxattr + * Valid replies: + * fuse_reply_buf + * fuse_reply_iov + * fuse_reply_data + * fuse_reply_err * * @param req request handle - * @param count the buffer size needed in bytes - * @return zero for success, -errno for failure to send reply + * @param ino the inode number + * @param size number of bytes to read + * @param off offset to read from + * @param fi file information */ - int fuse_reply_xattr(fuse_req_t req, size_t count); + void (*read) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info *fi); /** - * Reply with file lock information + * Write data + * + * Write should return exactly the number of bytes requested + * except on error. An exception to this is when the file has + * been opened in 'direct_io' mode, in which case the return value + * of the write system call will reflect the return value of this + * operation. + * + * fi->fh will contain the value set by the open method, or will + * be undefined if the open method didn't set any value. * - * Possible requests: - * getlk + * Valid replies: + * fuse_reply_write + * fuse_reply_err * * @param req request handle - * @param lock the lock information - * @return zero for success, -errno for failure to send reply + * @param ino the inode number + * @param buf data to write + * @param size number of bytes to write + * @param off offset to write to + * @param fi file information */ - int fuse_reply_lock(fuse_req_t req, const struct flock *lock); + void (*write) (fuse_req_t req, fuse_ino_t ino, const char *buf, + size_t size, off_t off, struct fuse_file_info *fi); /** - * Reply with block index + * Flush method + * + * This is called on each close() of the opened file. + * + * Since file descriptors can be duplicated (dup, dup2, fork), for + * one open call there may be many flush calls. + * + * Filesystems shouldn't assume that flush will always be called + * after some writes, or that if will be called at all. * - * Possible requests: - * bmap + * fi->fh will contain the value set by the open method, or will + * be undefined if the open method didn't set any value. + * + * NOTE: the name of the method is misleading, since (unlike + * fsync) the filesystem is not forced to flush pending writes. + * One reason to flush data, is if the filesystem wants to return + * write errors. + * + * If the filesystem supports file locking operations (setlk, + * getlk) it should remove all locks belonging to 'fi->owner'. + * + * Valid replies: + * fuse_reply_err * * @param req request handle - * @param idx block index within device - * @return zero for success, -errno for failure to send reply + * @param ino the inode number + * @param fi file information */ - int fuse_reply_bmap(fuse_req_t req, uint64_t idx); + void (*flush) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); /** - * Reply to ask for data fetch and output buffer preparation. ioctl - * will be retried with the specified input data fetched and output - * buffer prepared. + * Release an open file + * + * Release is called when there are no more references to an open + * file: all file descriptors are closed and all memory mappings + * are unmapped. + * + * For every open call there will be exactly one release call. * - * Possible requests: - * ioctl + * The filesystem may reply with an error, but error values are + * not returned to close() or munmap() which triggered the + * release. + * + * fi->fh will contain the value set by the open method, or will + * be undefined if the open method didn't set any value. + * fi->flags will contain the same flags as for open. + * + * Valid replies: + * fuse_reply_err * * @param req request handle - * @param in_iov iovec specifying data to fetch from the caller - * @param in_count number of entries in in_iov - * @param out_iov iovec specifying addresses to write output to - * @param out_count number of entries in out_iov - * @return zero for success, -errno for failure to send reply + * @param ino the inode number + * @param fi file information */ - int fuse_reply_ioctl_retry(fuse_req_t req, - const struct iovec *in_iov, size_t in_count, - const struct iovec *out_iov, size_t out_count); + void (*release) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); /** - * Reply to finish ioctl + * Synchronize file contents + * + * If the datasync parameter is non-zero, then only the user data + * should be flushed, not the meta data. * - * Possible requests: - * ioctl + * Valid replies: + * fuse_reply_err * * @param req request handle - * @param result result to be passed to the caller - * @param buf buffer containing output data - * @param size length of output data + * @param ino the inode number + * @param datasync flag indicating if only data should be flushed + * @param fi file information */ - int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, uint32_t size); + void (*fsync) (fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info *fi); /** - * Reply to finish ioctl with iov buffer + * Open a directory + * + * Filesystem may store an arbitrary file handle (pointer, index, + * etc) in fi->fh, and use this in other all other directory + * stream operations (readdir, releasedir, fsyncdir). * - * Possible requests: - * ioctl + * Filesystem may also implement stateless directory I/O and not + * store anything in fi->fh, though that makes it impossible to + * implement standard conforming directory stream operations in + * case the contents of the directory can change between opendir + * and releasedir. + * + * Valid replies: + * fuse_reply_open + * fuse_reply_err * * @param req request handle - * @param result result to be passed to the caller - * @param iov the vector containing the data - * @param count the size of vector + * @param ino the inode number + * @param fi file information */ - int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov, - int count); + void (*opendir) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); /** - * Reply with poll result event mask + * Read directory + * + * Send a buffer filled using fuse_add_direntry(), with size not + * exceeding the requested size. Send an empty buffer on end of + * stream. + * + * fi->fh will contain the value set by the opendir method, or + * will be undefined if the opendir method didn't set any value. + * + * Valid replies: + * fuse_reply_buf + * fuse_reply_data + * fuse_reply_err * * @param req request handle - * @param revents poll result event mask + * @param ino the inode number + * @param size maximum number of bytes to send + * @param off offset to continue reading the directory stream + * @param fi file information */ - int fuse_reply_poll(fuse_req_t req, unsigned revents); + void (*readdir) (fuse_req_t req, fuse_ino_t ino, size_t size, off_t off, + struct fuse_file_info *llffi); - /* ----------------------------------------------------------- * - * Notification * - * ----------------------------------------------------------- */ + void (*readdir_plus)(fuse_req_t req, fuse_ino_t ino, + size_t size, off_t off, + struct fuse_file_info *ffi); /** - * Notify IO readiness event + * Release an open directory + * + * For every opendir call there will be exactly one releasedir + * call. * - * For more information, please read comment for poll operation. + * fi->fh will contain the value set by the opendir method, or + * will be undefined if the opendir method didn't set any value. * - * @param ph poll handle to notify IO readiness event for + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information */ - int fuse_lowlevel_notify_poll(struct fuse_pollhandle *ph); + void (*releasedir) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi); /** - * Notify to invalidate cache for an inode + * Synchronize directory contents + * + * If the datasync parameter is non-zero, then only the directory + * contents should be flushed, not the meta data. + * + * fi->fh will contain the value set by the opendir method, or + * will be undefined if the opendir method didn't set any value. * - * @param ch the channel through which to send the invalidation + * Valid replies: + * fuse_reply_err + * + * @param req request handle * @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 + * @param datasync flag indicating if only data should be flushed + * @param fi file information */ - int fuse_lowlevel_notify_inval_inode(struct fuse_chan *ch, fuse_ino_t ino, - off_t off, off_t len); + void (*fsyncdir) (fuse_req_t req, fuse_ino_t ino, int datasync, + struct fuse_file_info *fi); /** - * Notify to invalidate parent attributes and the dentry matching - * parent/name + * Get file system statistics * - * 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. + * Valid replies: + * fuse_reply_statfs + * fuse_reply_err * - * @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 + * @param req request handle + * @param ino the inode number, zero means "undefined" */ - int fuse_lowlevel_notify_inval_entry(struct fuse_chan *ch, fuse_ino_t parent, - const char *name, size_t namelen); + void (*statfs) (fuse_req_t req, fuse_ino_t ino); /** - * 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. + * Set an extended attribute * - * @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 + * Valid replies: + * fuse_reply_err */ - int fuse_lowlevel_notify_delete(struct fuse_chan *ch, - fuse_ino_t parent, fuse_ino_t child, - const char *name, size_t namelen); + void (*setxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, + const char *value, size_t size, int flags); /** - * Store data to the kernel buffers + * Get an extended attribute * - * 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 size is zero, the size of the value should be sent with + * fuse_reply_xattr. * - * If the stored data overflows the current file size, then the size - * is extended, similarly to a write(2) on the filesystem. + * If the size is non-zero, and the value fits in the buffer, the + * value should be sent with fuse_reply_buf. * - * If this function returns an error, then the store wasn't fully - * completed, but it may have been partially completed. + * If the size is too small for the value, the ERANGE error should + * be sent. * - * @param ch the channel through which to send the invalidation + * Valid replies: + * fuse_reply_buf + * fuse_reply_data + * fuse_reply_xattr + * fuse_reply_err + * + * @param req request handle * @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 + * @param name of the extended attribute + * @param size maximum size of the value to send */ - 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); + void (*getxattr) (fuse_req_t req, fuse_ino_t ino, const char *name, + size_t size); + /** - * Retrieve data from the kernel buffers + * List extended attribute names * - * 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. + * If size is zero, the total size of the attribute list should be + * sent with fuse_reply_xattr. * - * 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 the size is non-zero, and the null character separated + * attribute list fits in the buffer, the list should be sent with + * fuse_reply_buf. * - * If this function returns an error, then the retrieve will not be - * completed and no reply will be sent. + * If the size is too small for the list, the ERANGE error should + * 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. + * Valid replies: + * fuse_reply_buf + * fuse_reply_data + * fuse_reply_xattr + * fuse_reply_err * - * @param ch the channel through which to send the invalidation + * @param req request handle * @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 + * @param size maximum size of the list to send */ - int fuse_lowlevel_notify_retrieve(struct fuse_chan *ch, fuse_ino_t ino, - size_t size, off_t offset, void *cookie); - - - /* ----------------------------------------------------------- * - * Utility functions * - * ----------------------------------------------------------- */ + void (*listxattr) (fuse_req_t req, fuse_ino_t ino, size_t size); /** - * Get the userdata from the request + * Remove an extended attribute + * + * Valid replies: + * fuse_reply_err * * @param req request handle - * @return the user data passed to fuse_lowlevel_new() + * @param ino the inode number + * @param name of the extended attribute */ - void *fuse_req_userdata(fuse_req_t req); + void (*removexattr) (fuse_req_t req, fuse_ino_t ino, const char *name); /** - * Get the context from the request + * Check file access permissions + * + * This will be called for the access() system call. If the + * 'default_permissions' mount option is given, this method is not + * called. + * + * This method is not called under Linux kernel versions 2.4.x * - * The pointer returned by this function will only be valid for the - * request's lifetime + * Introduced in version 2.5 + * + * Valid replies: + * fuse_reply_err * * @param req request handle - * @return the context structure + * @param ino the inode number + * @param mask requested access mode */ - const struct fuse_ctx *fuse_req_ctx(fuse_req_t req); + void (*access) (fuse_req_t req, fuse_ino_t ino, int mask); /** - * Get the current supplementary group IDs for the specified request + * Create and open a file + * + * If the file does not exist, first create it with the specified + * mode, and then open it. + * + * Open flags (with the exception of O_NOCTTY) are available in + * fi->flags. * - * 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. + * Filesystem may store an arbitrary file handle (pointer, index, + * etc) in fi->fh, and use this in other all other file operations + * (read, write, flush, release, fsync). * - * 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. + * There are also some flags (direct_io, keep_cache) which the + * filesystem may set in fi, to change the way the file is opened. + * See fuse_file_info structure in for more details. * - * This feature may not be supported on all operating systems. In - * such a case this function will return -ENOSYS. + * If this method is not implemented or under Linux kernel + * versions earlier than 2.6.15, the mknod() and open() methods + * will be called instead. + * + * Introduced in version 2.5 + * + * Valid replies: + * fuse_reply_create + * fuse_reply_err * * @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 + * @param parent inode number of the parent directory + * @param name to create + * @param mode file type and mode with which to create the new file + * @param fi file information */ - int fuse_req_getgroups(fuse_req_t req, int size, gid_t list[]); + void (*create) (fuse_req_t req, fuse_ino_t parent, const char *name, + mode_t mode, struct fuse_file_info *fi); /** - * Callback function for an interrupt + * Test for a POSIX file lock * - * @param req interrupted request - * @param data user data - */ - typedef void (*fuse_interrupt_func_t)(fuse_req_t req, void *data); - - /** - * Register/unregister callback for an interrupt + * Introduced in version 2.6 * - * If an interrupt has already happened, then the callback function is - * called from within this function, hence it's not possible for - * interrupts to be lost. + * Valid replies: + * fuse_reply_lock + * fuse_reply_err * * @param req request handle - * @param func the callback function or NULL for unregister - * @param data user data passed to the callback function + * @param ino the inode number + * @param fi file information + * @param lock the region/type to test */ - void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func, - void *data); + void (*getlk) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, struct flock *lock); /** - * Check if a request has already been interrupted + * Acquire, modify or release a POSIX file lock + * + * For POSIX threads (NPTL) there's a 1-1 relation between pid and + * owner, but otherwise this is not always the case. For checking + * lock ownership, 'fi->owner' must be used. The l_pid field in + * 'struct flock' should only be used to fill in this field in + * getlk(). + * + * Note: if the locking methods are not implemented, the kernel + * will still allow file locking to work locally. Hence these are + * only interesting for network filesystems and similar. + * + * Introduced in version 2.6 + * + * Valid replies: + * fuse_reply_err * * @param req request handle - * @return 1 if the request has been interrupted, 0 otherwise + * @param ino the inode number + * @param fi file information + * @param lock the region/type to set + * @param sleep locking operation may sleep */ - int fuse_req_interrupted(fuse_req_t req); - - /* ----------------------------------------------------------- * - * Filesystem setup * - * ----------------------------------------------------------- */ - - /* Deprecated, don't use */ - int fuse_lowlevel_is_lib_option(const char *opt); + void (*setlk) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, + struct flock *lock, int sleep); /** - * Create a low level session + * Map block index within file to block index within device * - * @param args argument vector - * @param op the low level filesystem operations - * @param op_size sizeof(struct fuse_lowlevel_ops) - * @param userdata user data - * @return the created session object, or NULL on failure - */ - struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, - const struct fuse_lowlevel_ops *op, - size_t op_size, void *userdata); - - /* ----------------------------------------------------------- * - * Session interface * - * ----------------------------------------------------------- */ - - /** - * Session operations + * Note: This makes sense only for block device backed filesystems + * mounted with the 'blkdev' option + * + * Introduced in version 2.6 * - * This is used in session creation + * Valid replies: + * fuse_reply_bmap + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param blocksize unit of block index + * @param idx block index within file */ - struct fuse_session_ops - { - /** - * Hook to process a request (mandatory) - * - * @param data user data passed to fuse_session_new() - * @param buf buffer containing the raw request - * @param len request length - * @param ch channel on which the request was received - */ - void (*process) (void *data, const char *buf, size_t len, - struct fuse_chan *ch); - - /** - * Hook for session exit and reset (optional) - * - * @param data user data passed to fuse_session_new() - * @param val exited status (1 - exited, 0 - not exited) - */ - void (*exit) (void *data, int val); - - /** - * Hook for querying the current exited status (optional) - * - * @param data user data passed to fuse_session_new() - * @return 1 if exited, 0 if not exited - */ - int (*exited) (void *data); - - /** - * Hook for cleaning up the channel on destroy (optional) - * - * @param data user data passed to fuse_session_new() - */ - void (*destroy) (void *data); - }; + void (*bmap) (fuse_req_t req, fuse_ino_t ino, size_t blocksize, + uint64_t idx); /** - * Create a new session + * Ioctl * - * @param op session operations - * @param data user data - * @return new session object, or NULL on failure + * Note: For unrestricted ioctls (not allowed for FUSE + * servers), data in and out areas can be discovered by giving + * iovs and setting FUSE_IOCTL_RETRY in @flags. For + * restricted ioctls, kernel prepares in/out data area + * according to the information encoded in cmd. + * + * Introduced in version 2.8 + * + * Valid replies: + * fuse_reply_ioctl_retry + * fuse_reply_ioctl + * fuse_reply_ioctl_iov + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param cmd ioctl command + * @param arg ioctl argument + * @param fi file information + * @param flags for FUSE_IOCTL_* flags + * @param in_buf data fetched from the caller + * @param in_bufsz number of fetched bytes + * @param out_bufsz maximum size of output data */ - struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data); + void (*ioctl) (fuse_req_t req, fuse_ino_t ino, unsigned long cmd, void *arg, + struct fuse_file_info *fi, unsigned flags, + const void *in_buf, uint32_t in_bufsz, uint32_t out_bufsz); /** - * Assign a channel to a session + * Poll for IO readiness * - * Note: currently only a single channel may be assigned. This may - * change in the future + * Introduced in version 2.8 * - * If a session is destroyed, the assigned channel is also destroyed + * Note: If ph is non-NULL, the client should notify + * when IO readiness events occur by calling + * fuse_lowelevel_notify_poll() with the specified ph. * - * @param se the session - * @param ch the channel + * Regardless of the number of times poll with a non-NULL ph + * is received, single notification is enough to clear all. + * Notifying more times incurs overhead but doesn't harm + * correctness. + * + * The callee is responsible for destroying ph with + * fuse_pollhandle_destroy() when no longer in use. + * + * Valid replies: + * fuse_reply_poll + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + * @param ph poll handle to be used for notification */ - void fuse_session_add_chan(struct fuse_session *se, struct fuse_chan *ch); + void (*poll) (fuse_req_t req, fuse_ino_t ino, struct fuse_file_info *fi, + struct fuse_pollhandle *ph); /** - * Remove a channel from a session + * Write data made available in a buffer + * + * This is a more generic version of the ->write() method. If + * FUSE_CAP_SPLICE_READ is set in fuse_conn_info.want and the + * kernel supports splicing from the fuse device, then the + * data will be made available in pipe for supporting zero + * copy data transfer. * - * If the channel is not assigned to a session, then this is a no-op + * buf->count is guaranteed to be one (and thus buf->idx is + * always zero). The write_buf handler must ensure that + * bufv->off is correctly updated (reflecting the number of + * bytes read from bufv->buf[0]). * - * @param ch the channel to remove + * Introduced in version 2.9 + * + * Valid replies: + * fuse_reply_write + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param bufv buffer containing the data + * @param off offset to write to + * @param fi file information */ - void fuse_session_remove_chan(struct fuse_chan *ch); + void (*write_buf) (fuse_req_t req, fuse_ino_t ino, + struct fuse_bufvec *bufv, off_t off, + struct fuse_file_info *fi); /** - * Iterate over the channels assigned to a session + * Callback function for the retrieve request + * + * Introduced in version 2.9 * - * The iterating function needs to start with a NULL channel, and - * after that needs to pass the previously returned channel to the - * function. + * Valid replies: + * fuse_reply_none * - * @param se the session - * @param ch the previous channel, or NULL - * @return the next channel, or NULL if no more channels exist + * @param req request handle + * @param cookie user data supplied to fuse_lowlevel_notify_retrieve() + * @param ino the inode number supplied to fuse_lowlevel_notify_retrieve() + * @param offset the offset supplied to fuse_lowlevel_notify_retrieve() + * @param bufv the buffer containing the returned data */ - struct fuse_chan *fuse_session_next_chan(struct fuse_session *se, - struct fuse_chan *ch); + void (*retrieve_reply) (fuse_req_t req, void *cookie, fuse_ino_t ino, + off_t offset, struct fuse_bufvec *bufv); /** - * Process a raw request + * Forget about multiple inodes * - * @param se the session - * @param buf buffer containing the raw request - * @param len request length - * @param ch channel on which the request was received + * See description of the forget function for more + * information. + * + * Introduced in version 2.9 + * + * Valid replies: + * fuse_reply_none + * + * @param req request handle */ - void fuse_session_process(struct fuse_session *se, const char *buf, size_t len, - struct fuse_chan *ch); + void (*forget_multi) (fuse_req_t req, size_t count, + struct fuse_forget_data *forgets); /** - * Process a raw request supplied in a generic buffer + * Acquire, modify or release a BSD file lock * - * This is a more generic version of fuse_session_process(). The - * fuse_buf may contain a memory buffer or a pipe file descriptor. + * Note: if the locking methods are not implemented, the kernel + * will still allow file locking to work locally. Hence these are + * only interesting for network filesystems and similar. * - * @param se the session - * @param buf the fuse_buf containing the request - * @param ch channel on which the request was received + * Introduced in version 2.9 + * + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param fi file information + * @param op the locking operation, see flock(2) */ - void fuse_session_process_buf(struct fuse_session *se, - const struct fuse_buf *buf, struct fuse_chan *ch); + void (*flock) (fuse_req_t req, fuse_ino_t ino, + struct fuse_file_info *fi, int op); /** - * Receive a raw request supplied in a generic buffer + * Allocate requested space. If this function returns success then + * subsequent writes to the specified range shall not fail due to the lack + * of free space on the file system storage media. * - * This is a more generic version of fuse_chan_recv(). The fuse_buf - * supplied to this function contains a suitably allocated memory - * buffer. This may be overwritten with a file descriptor buffer. + * Introduced in version 2.9 * - * @param se the session - * @param buf the fuse_buf to store the request in - * @param chp pointer to the channel - * @return the actual size of the raw request, or -errno on error + * Valid replies: + * fuse_reply_err + * + * @param req request handle + * @param ino the inode number + * @param offset starting point for allocated region + * @param length size of allocated region + * @param mode determines the operation to be performed on the given range, + * see fallocate(2) */ - int fuse_session_receive_buf(struct fuse_session *se, struct fuse_buf *buf, - struct fuse_chan **chp); + void (*fallocate) (fuse_req_t req, fuse_ino_t ino, int mode, + off_t offset, off_t length, struct fuse_file_info *fi); /** - * Destroy a session + * Copy a range of data from one file to another + * + * Performs an optimized copy between two file descriptors without + * the + * additional cost of transferring data through the FUSE kernel + * module + * to user space (glibc) and then back into the FUSE filesystem + * again. + * + * In case this method is not implemented, glibc falls back to + * reading + * data from the source and writing to the destination. Effectively + * doing an inefficient copy of the data. + * + * If this request is answered with an error code of ENOSYS, this is + * treated as a permanent failure with error code EOPNOTSUPP, + * i.e. all + * future copy_file_range() requests will fail with EOPNOTSUPP + * without + * being send to the filesystem process. + * + * Valid replies: + * fuse_reply_write + * fuse_reply_err * - * @param se the session + * @param req request handle + * @param ino_in the inode number of the source file + * @param off_in starting point from were the data should be read + * @param fi_in file information of the source file + * @param ino_out the inode number of the destination file + * @param off_out starting point where the data should be written + * @param fi_out file information of the destination file + * @param len maximum size of the data to copy + * @param flags passed along with the copy_file_range() syscall */ - void fuse_session_destroy(struct fuse_session *se); + void (*copy_file_range)(fuse_req_t req, + fuse_ino_t ino_in, + off_t off_in, + struct fuse_file_info *fi_in, + fuse_ino_t ino_out, + off_t off_out, + struct fuse_file_info *fi_out, + size_t len, + int flags); +}; + +/** + * Reply with an error code or success + * + * Possible requests: + * all except forget + * + * unlink, rmdir, rename, flush, release, fsync, fsyncdir, setxattr, + * removexattr and setlk may send a zero code + * + * @param req request handle + * @param err the positive error value, or zero for success + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_err(fuse_req_t req, int err); +/** + * Don't send reply + * + * Possible requests: + * forget + * + * @param req request handle + */ +void fuse_reply_none(fuse_req_t req); + +/** + * Reply with a directory entry + * + * Possible requests: + * lookup, mknod, mkdir, symlink, link + * + * Side effects: + * increments the lookup count on success + * + * @param req request handle + * @param e the entry parameters + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e); + +/** + * Reply with a directory entry and open parameters + * + * currently the following members of 'fi' are used: + * fh, direct_io, keep_cache + * + * Possible requests: + * create + * + * Side effects: + * increments the lookup count on success + * + * @param req request handle + * @param e the entry parameters + * @param fi file information + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_create(fuse_req_t req, const struct fuse_entry_param *e, + const struct fuse_file_info *fi); + +/** + * Reply with attributes + * + * Possible requests: + * getattr, setattr + * + * @param req request handle + * @param attr the attributes + * @param attr_timeout validity timeout (in seconds) for the attributes + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_attr(fuse_req_t req, + const struct stat *attr, + const uint64_t timeout); + +/** + * Reply with the contents of a symbolic link + * + * Possible requests: + * readlink + * + * @param req request handle + * @param link symbolic link contents + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_readlink(fuse_req_t req, const char *link); + +/** + * Reply with open parameters + * + * currently the following members of 'fi' are used: + * fh, direct_io, keep_cache + * + * Possible requests: + * open, opendir + * + * @param req request handle + * @param fi file information + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_open(fuse_req_t req, const struct fuse_file_info *fi); + +/** + * Reply with number of bytes written + * + * Possible requests: + * write + * + * @param req request handle + * @param count the number of bytes written + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_write(fuse_req_t req, size_t count); + +/** + * Reply with data + * + * Possible requests: + * read, readdir, getxattr, listxattr + * + * @param req request handle + * @param buf buffer containing data + * @param size the size of data in bytes + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size); + +/** + * Reply with data copied/moved from buffer(s) + * + * Possible requests: + * read, readdir, getxattr, listxattr + * + * @param req request handle + * @param bufv buffer vector + * @param flags flags controlling the copy + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_data(fuse_req_t req, struct fuse_bufvec *bufv, + enum fuse_buf_copy_flags flags); + +/** + * Reply with data vector + * + * Possible requests: + * read, readdir, getxattr, listxattr + * + * @param req request handle + * @param iov the vector containing the data + * @param count the size of vector + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_iov(fuse_req_t req, const struct iovec *iov, int count); + +/** + * Reply with filesystem statistics + * + * Possible requests: + * statfs + * + * @param req request handle + * @param stbuf filesystem statistics + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf); + +/** + * Reply with needed buffer size + * + * Possible requests: + * getxattr, listxattr + * + * @param req request handle + * @param count the buffer size needed in bytes + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_xattr(fuse_req_t req, size_t count); + +/** + * Reply with file lock information + * + * Possible requests: + * getlk + * + * @param req request handle + * @param lock the lock information + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_lock(fuse_req_t req, const struct flock *lock); + +/** + * Reply with block index + * + * Possible requests: + * bmap + * + * @param req request handle + * @param idx block index within device + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_bmap(fuse_req_t req, uint64_t idx); + +/** + * Reply to ask for data fetch and output buffer preparation. ioctl + * will be retried with the specified input data fetched and output + * buffer prepared. + * + * Possible requests: + * ioctl + * + * @param req request handle + * @param in_iov iovec specifying data to fetch from the caller + * @param in_count number of entries in in_iov + * @param out_iov iovec specifying addresses to write output to + * @param out_count number of entries in out_iov + * @return zero for success, -errno for failure to send reply + */ +int fuse_reply_ioctl_retry(fuse_req_t req, + const struct iovec *in_iov, size_t in_count, + const struct iovec *out_iov, size_t out_count); + +/** + * Reply to finish ioctl + * + * Possible requests: + * ioctl + * + * @param req request handle + * @param result result to be passed to the caller + * @param buf buffer containing output data + * @param size length of output data + */ +int fuse_reply_ioctl(fuse_req_t req, int result, const void *buf, uint32_t size); + +/** + * Reply to finish ioctl with iov buffer + * + * Possible requests: + * ioctl + * + * @param req request handle + * @param result result to be passed to the caller + * @param iov the vector containing the data + * @param count the size of vector + */ +int fuse_reply_ioctl_iov(fuse_req_t req, int result, const struct iovec *iov, + int count); + +/** + * Reply with poll result event mask + * + * @param req request handle + * @param revents poll result event mask + */ +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 * + * ----------------------------------------------------------- */ + +/** + * Get the userdata from the request + * + * @param req request handle + * @return the user data passed to fuse_lowlevel_new() + */ +void *fuse_req_userdata(fuse_req_t req); + +/** + * Get the context from the request + * + * The pointer returned by this function will only be valid for the + * request's lifetime + * + * @param req request handle + * @return the context structure + */ +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 + * + * @param req interrupted request + * @param data user data + */ +typedef void (*fuse_interrupt_func_t)(fuse_req_t req, void *data); + +/** + * Register/unregister callback for an interrupt + * + * If an interrupt has already happened, then the callback function is + * called from within this function, hence it's not possible for + * interrupts to be lost. + * + * @param req request handle + * @param func the callback function or NULL for unregister + * @param data user data passed to the callback function + */ +void fuse_req_interrupt_func(fuse_req_t req, fuse_interrupt_func_t func, + void *data); + +/** + * Check if a request has already been interrupted + * + * @param req request handle + * @return 1 if the request has been interrupted, 0 otherwise + */ +int fuse_req_interrupted(fuse_req_t req); + +/* ----------------------------------------------------------- * + * Filesystem setup * + * ----------------------------------------------------------- */ + +/* Deprecated, don't use */ +int fuse_lowlevel_is_lib_option(const char *opt); + +/** + * Create a low level session + * + * @param args argument vector + * @param op the low level filesystem operations + * @param op_size sizeof(struct fuse_lowlevel_ops) + * @param userdata user data + * @return the created session object, or NULL on failure + */ +struct fuse_session *fuse_lowlevel_new(struct fuse_args *args, + const struct fuse_lowlevel_ops *op, + size_t op_size, void *userdata); + +/* ----------------------------------------------------------- * + * Session interface * + * ----------------------------------------------------------- */ + +/** + * Session operations + * + * This is used in session creation + */ +struct fuse_session_ops +{ /** - * Exit a session + * Hook to process a request (mandatory) * - * @param se the session + * @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 fuse_session_exit(struct fuse_session *se); + void (*process) (void *data, const char *buf, size_t len, + struct fuse_chan *ch); /** - * Reset the exited status of a session + * Hook for session exit and reset (optional) * - * @param se the session + * @param data user data passed to fuse_session_new() + * @param val exited status (1 - exited, 0 - not exited) */ - void fuse_session_reset(struct fuse_session *se); + void (*exit) (void *data, int val); /** - * Query the exited status of a session + * Hook for querying the current exited status (optional) * - * @param se the session + * @param data user data passed to fuse_session_new() * @return 1 if exited, 0 if not exited */ - int fuse_session_exited(struct fuse_session *se); + int (*exited) (void *data); /** - * Get the user data provided to the session + * Hook for cleaning up the channel on destroy (optional) * - * @param se the session - * @return the user data + * @param data user data passed to fuse_session_new() */ - void *fuse_session_data(struct fuse_session *se); + void (*destroy) (void *data); +}; - /** - * Enter a multi-threaded event loop - * - * @param se the session - * @return 0 on success, -1 on error - */ - int fuse_session_loop_mt(struct fuse_session *se, const int threads); +/** + * Create a new session + * + * @param op session operations + * @param data user data + * @return new session object, or NULL on failure + */ +struct fuse_session *fuse_session_new(struct fuse_session_ops *op, void *data); - /* ----------------------------------------------------------- * - * Channel interface * - * ----------------------------------------------------------- */ +/** + * 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); - /** - * 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); - }; +/** + * 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); - /** - * 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); +/** + * 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); - /** - * 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); +/** + * Process a raw request + * + * @param se the session + * @param buf buffer containing the raw request + * @param len request length + * @param ch channel on which the request was received + */ +void fuse_session_process(struct fuse_session *se, const char *buf, size_t len, + 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); +/** + * Process a raw request supplied in a generic buffer + * + * This is a more generic version of fuse_session_process(). The + * fuse_buf may contain a memory buffer or a pipe file descriptor. + * + * @param se the session + * @param buf the fuse_buf containing the request + * @param ch channel on which the request was received + */ +void fuse_session_process_buf(struct fuse_session *se, + const struct fuse_buf *buf, struct fuse_chan *ch); - /** - * 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); +/** + * Receive a raw request supplied in a generic buffer + * + * This is a more generic version of fuse_chan_recv(). The fuse_buf + * supplied to this function contains a suitably allocated memory + * buffer. This may be overwritten with a file descriptor buffer. + * + * @param se the session + * @param buf the fuse_buf to store the request in + * @param chp pointer to the channel + * @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); - /** - * 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); +/** + * Destroy a session + * + * @param se the session + */ +void fuse_session_destroy(struct fuse_session *se); + +/** + * Exit a session + * + * @param se the session + */ +void fuse_session_exit(struct fuse_session *se); + +/** + * Reset the exited status of a session + * + * @param se the session + */ +void fuse_session_reset(struct fuse_session *se); + +/** + * Query the exited status of a session + * + * @param se the session + * @return 1 if exited, 0 if not exited + */ +int fuse_session_exited(struct fuse_session *se); + +/** + * Get the user data provided to the session + * + * @param se the session + * @return the user data + */ +void *fuse_session_data(struct fuse_session *se); + +/** + * Enter a multi-threaded event loop + * + * @param se the session + * @return 0 on success, -1 on error + */ +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 +{ /** - * Receive a raw request - * - * A return value of -ENODEV means, that the filesystem was unmounted + * 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 -errno on error + * @return the actual size of the raw request, or -1 on error */ - int fuse_chan_recv(struct fuse_chan **ch, char *buf, size_t size); + int (*receive)(struct fuse_chan **chp, char *buf, size_t size); /** - * Send a raw reply + * Hook for sending a raw reply * * A return value of -ENOENT means, that the request was * interrupted, and the reply was discarded @@ -1816,18 +1737,94 @@ extern "C" { * @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); + int (*send)(struct fuse_chan *ch, const struct iovec iov[], + size_t count); /** - * Destroy a channel + * Destroy the channel * * @param ch the channel */ - void fuse_chan_destroy(struct fuse_chan *ch); + void (*destroy)(struct fuse_chan *ch); +}; -#ifdef __cplusplus -} -#endif +/** + * 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); + +EXTERN_C_END #endif /* _FUSE_LOWLEVEL_H_ */ diff --git a/libfuse/include/fuse_opt.h b/libfuse/include/fuse_opt.h index 229c3931..c82eef0d 100644 --- a/libfuse/include/fuse_opt.h +++ b/libfuse/include/fuse_opt.h @@ -9,264 +9,262 @@ #ifndef _FUSE_OPT_H_ #define _FUSE_OPT_H_ +#include "extern_c.h" + /** @file * * This file defines the option parsing interface of FUSE */ -#ifdef __cplusplus -extern "C" { -#endif +EXTERN_C_BEGIN + +/** + * Option description + * + * This structure describes a single option, and action associated + * with it, in case it matches. + * + * More than one such match may occur, in which case the action for + * each match is executed. + * + * There are three possible actions in case of a match: + * + * i) An integer (int or unsigned) variable determined by 'offset' is + * set to 'value' + * + * ii) The processing function is called, with 'value' as the key + * + * iii) An integer (any) or string (char *) variable determined by + * 'offset' is set to the value of an option parameter + * + * 'offset' should normally be either set to + * + * - 'offsetof(struct foo, member)' actions i) and iii) + * + * - -1 action ii) + * + * The 'offsetof()' macro is defined in the header. + * + * The template determines which options match, and also have an + * effect on the action. Normally the action is either i) or ii), but + * if a format is present in the template, then action iii) is + * performed. + * + * The types of templates are: + * + * 1) "-x", "-foo", "--foo", "--foo-bar", etc. These match only + * themselves. Invalid values are "--" and anything beginning + * with "-o" + * + * 2) "foo", "foo-bar", etc. These match "-ofoo", "-ofoo-bar" or + * the relevant option in a comma separated option list + * + * 3) "bar=", "--foo=", etc. These are variations of 1) and 2) + * which have a parameter + * + * 4) "bar=%s", "--foo=%lu", etc. Same matching as above but perform + * action iii). + * + * 5) "-x ", etc. Matches either "-xparam" or "-x param" as + * two separate arguments + * + * 6) "-x %s", etc. Combination of 4) and 5) + * + * If the format is "%s", memory is allocated for the string unlike + * with scanf(). + */ +struct fuse_opt +{ + /** Matching template and optional parameter formatting */ + const char *templ; /** - * Option description - * - * This structure describes a single option, and action associated - * with it, in case it matches. - * - * More than one such match may occur, in which case the action for - * each match is executed. - * - * There are three possible actions in case of a match: - * - * i) An integer (int or unsigned) variable determined by 'offset' is - * set to 'value' - * - * ii) The processing function is called, with 'value' as the key - * - * iii) An integer (any) or string (char *) variable determined by - * 'offset' is set to the value of an option parameter - * - * 'offset' should normally be either set to - * - * - 'offsetof(struct foo, member)' actions i) and iii) - * - * - -1 action ii) - * - * The 'offsetof()' macro is defined in the header. - * - * The template determines which options match, and also have an - * effect on the action. Normally the action is either i) or ii), but - * if a format is present in the template, then action iii) is - * performed. - * - * The types of templates are: - * - * 1) "-x", "-foo", "--foo", "--foo-bar", etc. These match only - * themselves. Invalid values are "--" and anything beginning - * with "-o" - * - * 2) "foo", "foo-bar", etc. These match "-ofoo", "-ofoo-bar" or - * the relevant option in a comma separated option list - * - * 3) "bar=", "--foo=", etc. These are variations of 1) and 2) - * which have a parameter - * - * 4) "bar=%s", "--foo=%lu", etc. Same matching as above but perform - * action iii). - * - * 5) "-x ", etc. Matches either "-xparam" or "-x param" as - * two separate arguments - * - * 6) "-x %s", etc. Combination of 4) and 5) - * - * If the format is "%s", memory is allocated for the string unlike - * with scanf(). + * Offset of variable within 'data' parameter of fuse_opt_parse() + * or -1 */ - struct fuse_opt - { - /** Matching template and optional parameter formatting */ - const char *templ; - - /** - * Offset of variable within 'data' parameter of fuse_opt_parse() - * or -1 - */ - unsigned long offset; - - /** - * Value to set the variable to, or to be passed as 'key' to the - * processing function. Ignored if template has a format - */ - int value; - }; + unsigned long offset; /** - * Key option. In case of a match, the processing function will be - * called with the specified key. + * Value to set the variable to, or to be passed as 'key' to the + * processing function. Ignored if template has a format */ + int value; +}; + +/** + * Key option. In case of a match, the processing function will be + * called with the specified key. + */ #define FUSE_OPT_KEY(templ, key) { templ, -1U, key } - /** - * Last option. An array of 'struct fuse_opt' must end with a NULL - * template value - */ +/** + * Last option. An array of 'struct fuse_opt' must end with a NULL + * template value + */ #define FUSE_OPT_END { NULL, 0, 0 } - /** - * Argument list - */ - struct fuse_args - { - /** Argument count */ - int argc; +/** + * Argument list + */ +struct fuse_args +{ + /** Argument count */ + int argc; - /** Argument vector. NULL terminated */ - char **argv; + /** Argument vector. NULL terminated */ + char **argv; - /** Is 'argv' allocated? */ - int allocated; - }; + /** Is 'argv' allocated? */ + int allocated; +}; - /** - * Initializer for 'struct fuse_args' - */ +/** + * Initializer for 'struct fuse_args' + */ #define FUSE_ARGS_INIT(argc, argv) { argc, argv, 0 } - /** - * Key value passed to the processing function if an option did not - * match any template - */ +/** + * Key value passed to the processing function if an option did not + * match any template + */ #define FUSE_OPT_KEY_OPT -1 - /** - * Key value passed to the processing function for all non-options - * - * Non-options are the arguments beginning with a character other than - * '-' or all arguments after the special '--' option - */ +/** + * Key value passed to the processing function for all non-options + * + * Non-options are the arguments beginning with a character other than + * '-' or all arguments after the special '--' option + */ #define FUSE_OPT_KEY_NONOPT -2 - /** - * Special key value for options to keep - * - * Argument is not passed to processing function, but behave as if the - * processing function returned 1 - */ +/** + * Special key value for options to keep + * + * Argument is not passed to processing function, but behave as if the + * processing function returned 1 + */ #define FUSE_OPT_KEY_KEEP -3 - /** - * Special key value for options to discard - * - * Argument is not passed to processing function, but behave as if the - * processing function returned zero - */ +/** + * Special key value for options to discard + * + * Argument is not passed to processing function, but behave as if the + * processing function returned zero + */ #define FUSE_OPT_KEY_DISCARD -4 - /** - * Processing function - * - * This function is called if - * - option did not match any 'struct fuse_opt' - * - argument is a non-option - * - option did match and offset was set to -1 - * - * The 'arg' parameter will always contain the whole argument or - * option including the parameter if exists. A two-argument option - * ("-x foo") is always converted to single argument option of the - * form "-xfoo" before this function is called. - * - * Options of the form '-ofoo' are passed to this function without the - * '-o' prefix. - * - * The return value of this function determines whether this argument - * is to be inserted into the output argument vector, or discarded. - * - * @param data is the user data passed to the fuse_opt_parse() function - * @param arg is the whole argument or option - * @param key determines why the processing function was called - * @param outargs the current output argument list - * @return -1 on error, 0 if arg is to be discarded, 1 if arg should be kept - */ - typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key, - struct fuse_args *outargs); +/** + * Processing function + * + * This function is called if + * - option did not match any 'struct fuse_opt' + * - argument is a non-option + * - option did match and offset was set to -1 + * + * The 'arg' parameter will always contain the whole argument or + * option including the parameter if exists. A two-argument option + * ("-x foo") is always converted to single argument option of the + * form "-xfoo" before this function is called. + * + * Options of the form '-ofoo' are passed to this function without the + * '-o' prefix. + * + * The return value of this function determines whether this argument + * is to be inserted into the output argument vector, or discarded. + * + * @param data is the user data passed to the fuse_opt_parse() function + * @param arg is the whole argument or option + * @param key determines why the processing function was called + * @param outargs the current output argument list + * @return -1 on error, 0 if arg is to be discarded, 1 if arg should be kept + */ +typedef int (*fuse_opt_proc_t)(void *data, const char *arg, int key, + struct fuse_args *outargs); - /** - * Option parsing function - * - * If 'args' was returned from a previous call to fuse_opt_parse() or - * it was constructed from - * - * A NULL 'args' is equivalent to an empty argument vector - * - * A NULL 'opts' is equivalent to an 'opts' array containing a single - * end marker - * - * A NULL 'proc' is equivalent to a processing function always - * returning '1' - * - * @param args is the input and output argument list - * @param data is the user data - * @param opts is the option description array - * @param proc is the processing function - * @return -1 on error, 0 on success - */ - int fuse_opt_parse(struct fuse_args *args, void *data, - const struct fuse_opt opts[], fuse_opt_proc_t proc); +/** + * Option parsing function + * + * If 'args' was returned from a previous call to fuse_opt_parse() or + * it was constructed from + * + * A NULL 'args' is equivalent to an empty argument vector + * + * A NULL 'opts' is equivalent to an 'opts' array containing a single + * end marker + * + * A NULL 'proc' is equivalent to a processing function always + * returning '1' + * + * @param args is the input and output argument list + * @param data is the user data + * @param opts is the option description array + * @param proc is the processing function + * @return -1 on error, 0 on success + */ +int fuse_opt_parse(struct fuse_args *args, void *data, + const struct fuse_opt opts[], fuse_opt_proc_t proc); - /** - * Add an option to a comma separated option list - * - * @param opts is a pointer to an option list, may point to a NULL value - * @param opt is the option to add - * @return -1 on allocation error, 0 on success - */ - int fuse_opt_add_opt(char **opts, const char *opt); +/** + * Add an option to a comma separated option list + * + * @param opts is a pointer to an option list, may point to a NULL value + * @param opt is the option to add + * @return -1 on allocation error, 0 on success + */ +int fuse_opt_add_opt(char **opts, const char *opt); - /** - * Add an option, escaping commas, to a comma separated option list - * - * @param opts is a pointer to an option list, may point to a NULL value - * @param opt is the option to add - * @return -1 on allocation error, 0 on success - */ - int fuse_opt_add_opt_escaped(char **opts, const char *opt); +/** + * Add an option, escaping commas, to a comma separated option list + * + * @param opts is a pointer to an option list, may point to a NULL value + * @param opt is the option to add + * @return -1 on allocation error, 0 on success + */ +int fuse_opt_add_opt_escaped(char **opts, const char *opt); - /** - * Add an argument to a NULL terminated argument vector - * - * @param args is the structure containing the current argument list - * @param arg is the new argument to add - * @return -1 on allocation error, 0 on success - */ - int fuse_opt_add_arg(struct fuse_args *args, const char *arg); +/** + * Add an argument to a NULL terminated argument vector + * + * @param args is the structure containing the current argument list + * @param arg is the new argument to add + * @return -1 on allocation error, 0 on success + */ +int fuse_opt_add_arg(struct fuse_args *args, const char *arg); - /** - * Add an argument at the specified position in a NULL terminated - * argument vector - * - * Adds the argument to the N-th position. This is useful for adding - * options at the beginning of the array which must not come after the - * special '--' option. - * - * @param args is the structure containing the current argument list - * @param pos is the position at which to add the argument - * @param arg is the new argument to add - * @return -1 on allocation error, 0 on success - */ - int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg); +/** + * Add an argument at the specified position in a NULL terminated + * argument vector + * + * Adds the argument to the N-th position. This is useful for adding + * options at the beginning of the array which must not come after the + * special '--' option. + * + * @param args is the structure containing the current argument list + * @param pos is the position at which to add the argument + * @param arg is the new argument to add + * @return -1 on allocation error, 0 on success + */ +int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg); - /** - * Free the contents of argument list - * - * The structure itself is not freed - * - * @param args is the structure containing the argument list - */ - void fuse_opt_free_args(struct fuse_args *args); +/** + * Free the contents of argument list + * + * The structure itself is not freed + * + * @param args is the structure containing the argument list + */ +void fuse_opt_free_args(struct fuse_args *args); - /** - * Check if an option matches - * - * @param opts is the option description array - * @param opt is the option to match - * @return 1 if a match is found, 0 if not - */ - int fuse_opt_match(const struct fuse_opt opts[], const char *opt); +/** + * Check if an option matches + * + * @param opts is the option description array + * @param opt is the option to match + * @return 1 if a match is found, 0 if not + */ +int fuse_opt_match(const struct fuse_opt opts[], const char *opt); -#ifdef __cplusplus -} -#endif +EXTERN_C_END #endif /* _FUSE_OPT_H_ */ diff --git a/libfuse/include/ulockmgr.h b/libfuse/include/ulockmgr.h deleted file mode 100644 index ad555799..00000000 --- a/libfuse/include/ulockmgr.h +++ /dev/null @@ -1,24 +0,0 @@ -/* - libulockmgr: Userspace Lock Manager Library - Copyright (C) 2006 Miklos Szeredi - - This program can be distributed under the terms of the GNU LGPLv2. - See the file COPYING.LIB. -*/ - -#include -#include -#include - -/** - * Perform POSIX locking operation - * - * @param fd the file descriptor - * @param cmd the locking command (F_GETFL, F_SETLK or F_SETLKW) - * @param lock the lock parameters - * @param owner the lock owner ID cookie - * @param owner_len length of the lock owner ID cookie - * @return 0 on success -errno on error - */ -int ulockmgr_op(int fd, int cmd, struct flock *lock, const void *owner, - size_t owner_len);