aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog.rst4
-rw-r--r--include/fuse.h183
-rw-r--r--lib/fuse.c34
-rw-r--r--lib/modules/iconv.c5
-rw-r--r--lib/modules/subdir.c5
5 files changed, 195 insertions, 36 deletions
diff --git a/ChangeLog.rst b/ChangeLog.rst
index a668d5f..7d32ba6 100644
--- a/ChangeLog.rst
+++ b/ChangeLog.rst
@@ -1,6 +1,10 @@
Unreleased Changes
==================
+* The high-level init() handler now receives an additional struct
+ fuse_config pointer that can be used to adjust high-level API
+ specific configuration options.
+
* File systems that use the low-level API and support lookup requests
for '.' and '..' should continue make sure to set the
FUSE_CAP_EXPORT_SUPPORT bit in fuse_conn_info->want.
diff --git a/include/fuse.h b/include/fuse.h
index 52b8698..3c13c14 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -76,6 +76,183 @@ enum fuse_fill_dir_flags {
typedef int (*fuse_fill_dir_t) (void *buf, const char *name,
const struct stat *stbuf, off_t off,
enum fuse_fill_dir_flags flags);
+/**
+ * Configuration of the high-level API
+ *
+ * This structure is initialized from the arguments passed to
+ * fuse_new(), and then passed to the file system's init() handler
+ * which should ensure that the configuration is compatible with the
+ * file system implementation.
+ */
+struct fuse_config {
+ /**
+ * If `set_gid` is non-zero, the st_gid attribute of each file
+ * is overwritten with the value of `gid`.
+ */
+ int set_gid;
+ unsigned int gid;
+
+ /**
+ * If `set_uid` is non-zero, the st_uid attribute of each file
+ * is overwritten with the value of `uid`.
+ */
+ int set_uid;
+ unsigned int uid;
+
+ /**
+ * If `set_mode` is non-zero, the any permissions bits set in
+ * `umask` are unset in the st_mode attribute of each file.
+ */
+ int set_mode;
+ unsigned int umask;
+
+ /**
+ * The timeout in seconds for which name lookups will be
+ * cached.
+ */
+ double entry_timeout;
+
+ /**
+ * The timeout in seconds for which a negative lookup will be
+ * cached. This means, that if file did not exist (lookup
+ * retuned ENOENT), the lookup will only be redone after the
+ * timeout, and the file/directory will be assumed to not
+ * exist until then. A value of zero means that negative
+ * lookups are not cached.
+ */
+ double negative_timeout;
+
+ /**
+ * The timeout in seconds for which file/directory attributes
+ * (as returned by e.g. the `getattr` handler) are cached.
+ */
+ double attr_timeout;
+
+ /**
+ * Allow requests to be interrupted
+ */
+ int intr;
+
+ /**
+ * Specify which signal number to send to the filesystem when
+ * a request is interrupted. The default is hardcoded to
+ * USR1.
+ */
+ int intr_signal;
+
+ /**
+ * Normally, FUSE assigns inodes to paths only for as long as
+ * the kernel is aware of them. With this option inodes are
+ * instead remembered for at least this many seconds. This
+ * will require more memory, but may be necessary when using
+ * applications that make use of inode numbers.
+ *
+ * A number of -1 means that inodes will be remembered for the
+ * entire life-time of the file-system process.
+ */
+ int remember;
+
+ /**
+ * The default behavior is that if an open file is deleted,
+ * the file is renamed to a hidden file (.fuse_hiddenXXX), and
+ * only removed when the file is finally released. This
+ * relieves the filesystem implementation of having to deal
+ * with this problem. This option disables the hiding
+ * behavior, and files are removed immediately in an unlink
+ * operation (or in a rename operation which overwrites an
+ * existing file).
+ *
+ * It is recommended that you not use the hard_remove
+ * option. When hard_remove is set, the following libc
+ * functions fail on unlinked files (returning errno of
+ * ENOENT): read(2), write(2), fsync(2), close(2), f*xattr(2),
+ * ftruncate(2), fstat(2), fch‐ mod(2), fchown(2)
+ */
+ int hard_remove;
+
+ /**
+ * Honor the st_ino field in the functions getattr() and
+ * fill_dir(). This value is used to fill in the st_ino field
+ * in the stat(2), lstat(2), fstat(2) functions and the d_ino
+ * field in the readdir(2) function. The filesystem does not
+ * have to guarantee uniqueness, however some applications
+ * rely on this value being unique for the whole filesystem.
+ */
+ int use_ino;
+
+ /**
+ * If use_ino option is not given, still try to fill in the
+ * d_ino field in readdir(2). If the name was previously
+ * looked up, and is still in the cache, the inode number
+ * found there will be used. Otherwise it will be set to -1.
+ * If use_ino option is given, this option is ignored.
+ */
+ int readdir_ino;
+
+ /**
+ * This option disables the use of page cache (file content cache)
+ * in the kernel for this filesystem. This has several affects:
+ *
+ * 1. Each read(2) or write(2) system call will initiate one
+ * or more read or write operations, data will not be
+ * cached in the kernel.
+ *
+ * 2. The return value of the read() and write() system calls
+ * will correspond to the return values of the read and
+ * write operations. This is useful for example if the
+ * file size is not known in advance (before reading it).
+ *
+ * Internally, enabling this option causes fuse to set the
+ * `direct_io` field of `struct fuse_file_info` - overwriting
+ * any value that was put there by the file system.
+ */
+ int direct_io;
+
+ /**
+ * This option disables flushing the cache of the file
+ * contents on every open(2). This should only be enabled on
+ * filesystems, where the file data is never changed
+ * externally (not through the mounted FUSE filesystem). Thus
+ * it is not suitable for network filesystems and other
+ * intermediate filesystems.
+ *
+ * NOTE: if this option is not specified (and neither
+ * direct_io) data is still cached after the open(2), so a
+ * read(2) system call will not always initiate a read
+ * operation.
+ *
+ * Internally, enabling this option causes fuse to set the
+ * `keep_cache` field of `struct fuse_file_info` - overwriting
+ * any value that was put there by the file system.
+ */
+ int kernel_cache;
+
+ /**
+ * This option is an alternative to `kernel_cache`. Instead of
+ * unconditionally keeping cached data, the cached data is
+ * invalidated on open(2) if if the modification time or the
+ * size of the file has changed since it was last opened.
+ */
+ int auto_cache;
+
+ /**
+ * The timeout in seconds for which file attributes are cached
+ * for the purpose of checking if auto_cache should flush the
+ * file data on open.
+ */
+ int ac_attr_timeout_set;
+ double ac_attr_timeout;
+
+ /**
+ * The remaining options are used by libfuse internally and
+ * should not be touched.
+ */
+ int show_help;
+ char *modules;
+ int debug;
+ int nopath;
+};
+
/**
* The file system operations:
@@ -354,7 +531,8 @@ struct fuse_operations {
* fuse_context to all file operations and as a parameter to the
* destroy() method.
*/
- void *(*init) (struct fuse_conn_info *conn);
+ void *(*init) (struct fuse_conn_info *conn,
+ struct fuse_config *cfg);
/**
* Clean up filesystem
@@ -881,7 +1059,8 @@ int fuse_fs_poll(struct fuse_fs *fs, const char *path,
unsigned *reventsp);
int fuse_fs_fallocate(struct fuse_fs *fs, const char *path, 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_init(struct fuse_fs *fs, struct fuse_conn_info *conn,
+ struct fuse_config *cfg);
void fuse_fs_destroy(struct fuse_fs *fs);
int fuse_notify_poll(struct fuse_pollhandle *ph);
diff --git a/lib/fuse.c b/lib/fuse.c
index 07e63d2..f469378 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -57,33 +57,6 @@
#define NODE_TABLE_MIN_SIZE 8192
-struct fuse_config {
- unsigned int uid;
- unsigned int gid;
- unsigned int umask;
- double entry_timeout;
- double negative_timeout;
- double attr_timeout;
- double ac_attr_timeout;
- int ac_attr_timeout_set;
- int remember;
- int nopath;
- int debug;
- int hard_remove;
- int use_ino;
- int readdir_ino;
- int set_mode;
- int set_uid;
- int set_gid;
- int direct_io;
- int kernel_cache;
- int auto_cache;
- int intr;
- int intr_signal;
- int show_help;
- char *modules;
-};
-
struct fuse_fs {
struct fuse_operations op;
struct fuse_module *m;
@@ -2478,7 +2451,8 @@ static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
reply_err(req, err);
}
-void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn)
+void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn,
+ struct fuse_config *cfg)
{
fuse_get_context()->private_data = fs->user_data;
if (!fs->op.write_buf)
@@ -2488,7 +2462,7 @@ void fuse_fs_init(struct fuse_fs *fs, struct fuse_conn_info *conn)
if (!fs->op.flock)
conn->want &= ~FUSE_CAP_FLOCK_LOCKS;
if (fs->op.init)
- fs->user_data = fs->op.init(conn);
+ fs->user_data = fs->op.init(conn, cfg);
}
static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
@@ -2497,7 +2471,7 @@ static void fuse_lib_init(void *data, struct fuse_conn_info *conn)
fuse_create_context(f);
conn->want |= FUSE_CAP_EXPORT_SUPPORT;
- fuse_fs_init(f->fs, conn);
+ fuse_fs_init(f->fs, conn, &f->conf);
}
void fuse_fs_destroy(struct fuse_fs *fs)
diff --git a/lib/modules/iconv.c b/lib/modules/iconv.c
index 41a072c..b0453be 100644
--- a/lib/modules/iconv.c
+++ b/lib/modules/iconv.c
@@ -556,10 +556,11 @@ static int iconv_bmap(const char *path, size_t blocksize, uint64_t *idx)
return err;
}
-static void *iconv_init(struct fuse_conn_info *conn)
+static void *iconv_init(struct fuse_conn_info *conn,
+ struct fuse_config *cfg)
{
struct iconv *ic = iconv_get();
- fuse_fs_init(ic->next, conn);
+ fuse_fs_init(ic->next, conn, cfg);
return ic;
}
diff --git a/lib/modules/subdir.c b/lib/modules/subdir.c
index c264fb4..708edf3 100644
--- a/lib/modules/subdir.c
+++ b/lib/modules/subdir.c
@@ -542,10 +542,11 @@ static int subdir_bmap(const char *path, size_t blocksize, uint64_t *idx)
return err;
}
-static void *subdir_init(struct fuse_conn_info *conn)
+static void *subdir_init(struct fuse_conn_info *conn,
+ struct fuse_config *cfg)
{
struct subdir *d = subdir_get();
- fuse_fs_init(d->next, conn);
+ fuse_fs_init(d->next, conn, cfg);
return d;
}