aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/fuse.c132
-rw-r--r--lib/fuse_i.h25
-rw-r--r--lib/fuse_lowlevel.c98
-rw-r--r--lib/fuse_versionscript4
-rw-r--r--lib/helper.c134
-rw-r--r--lib/modules/iconv.c51
-rw-r--r--lib/modules/subdir.c53
-rw-r--r--lib/mount.c26
-rw-r--r--lib/mount_bsd.c11
-rw-r--r--lib/mount_util.c33
-rw-r--r--lib/mount_util.h2
11 files changed, 205 insertions, 364 deletions
diff --git a/lib/fuse.c b/lib/fuse.c
index fb15b04..07e63d2 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -1537,34 +1537,15 @@ static inline void fuse_prepare_interrupt(struct fuse *f, fuse_req_t req,
fuse_do_prepare_interrupt(req, d);
}
-int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf)
+int fuse_fs_getattr(struct fuse_fs *fs, const char *path, struct stat *buf,
+ struct fuse_file_info *fi)
{
fuse_get_context()->private_data = fs->user_data;
if (fs->op.getattr) {
if (fs->debug)
- fprintf(stderr, "getattr %s\n", path);
-
- return fs->op.getattr(path, buf);
- } else {
- return -ENOSYS;
- }
-}
-
-int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf,
- struct fuse_file_info *fi)
-{
- fuse_get_context()->private_data = fs->user_data;
- if (fs->op.fgetattr) {
- if (fs->debug)
- fprintf(stderr, "fgetattr[%llu] %s\n",
+ fprintf(stderr, "getattr[%llu] %s\n",
(unsigned long long) fi->fh, path);
-
- return fs->op.fgetattr(path, buf, fi);
- } else if (path && fs->op.getattr) {
- if (fs->debug)
- fprintf(stderr, "getattr %s\n", path);
-
- return fs->op.getattr(path, buf);
+ return fs->op.getattr(path, buf, fi);
} else {
return -ENOSYS;
}
@@ -2023,67 +2004,50 @@ int fuse_fs_flock(struct fuse_fs *fs, const char *path,
}
}
-int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid, gid_t gid)
+int fuse_fs_chown(struct fuse_fs *fs, const char *path, uid_t uid,
+ gid_t gid, struct fuse_file_info *fi)
{
fuse_get_context()->private_data = fs->user_data;
if (fs->op.chown) {
if (fs->debug)
- fprintf(stderr, "chown %s %lu %lu\n", path,
+ fprintf(stderr, "chown[%llu] %s %lu %lu\n",
+ (unsigned long long) fi->fh, path,
(unsigned long) uid, (unsigned long) gid);
- return fs->op.chown(path, uid, gid);
- } else {
- return -ENOSYS;
- }
-}
-
-int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size)
-{
- fuse_get_context()->private_data = fs->user_data;
- if (fs->op.truncate) {
- if (fs->debug)
- fprintf(stderr, "truncate %s %llu\n", path,
- (unsigned long long) size);
-
- return fs->op.truncate(path, size);
+ return fs->op.chown(path, uid, gid, fi);
} else {
return -ENOSYS;
}
}
-int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size,
+int fuse_fs_truncate(struct fuse_fs *fs, const char *path, off_t size,
struct fuse_file_info *fi)
{
fuse_get_context()->private_data = fs->user_data;
- if (fs->op.ftruncate) {
+ if (fs->op.truncate) {
if (fs->debug)
- fprintf(stderr, "ftruncate[%llu] %llu\n",
+ fprintf(stderr, "truncate[%llu] %llu\n",
(unsigned long long) fi->fh,
(unsigned long long) size);
- return fs->op.ftruncate(path, size, fi);
- } else if (path && fs->op.truncate) {
- if (fs->debug)
- fprintf(stderr, "truncate %s %llu\n", path,
- (unsigned long long) size);
-
- return fs->op.truncate(path, size);
+ return fs->op.truncate(path, size, fi);
} else {
return -ENOSYS;
}
}
int fuse_fs_utimens(struct fuse_fs *fs, const char *path,
- const struct timespec tv[2])
+ const struct timespec tv[2], struct fuse_file_info *fi)
{
fuse_get_context()->private_data = fs->user_data;
if (fs->op.utimens) {
if (fs->debug)
- fprintf(stderr, "utimens %s %li.%09lu %li.%09lu\n",
- path, tv[0].tv_sec, tv[0].tv_nsec,
+ fprintf(stderr, "utimens[%llu] %s %li.%09lu %li.%09lu\n",
+ (unsigned long long) fi->fh, path,
+ tv[0].tv_sec, tv[0].tv_nsec,
tv[1].tv_sec, tv[1].tv_nsec);
- return fs->op.utimens(path, tv);
+ return fs->op.utimens(path, tv, fi);
} else {
return -ENOSYS;
}
@@ -2318,7 +2282,7 @@ static char *hidden_name(struct fuse *f, fuse_ino_t dir, const char *oldname,
break;
memset(&buf, 0, sizeof(buf));
- res = fuse_fs_getattr(f->fs, newpath, &buf);
+ res = fuse_fs_getattr(f->fs, newpath, &buf, NULL);
if (res == -ENOENT)
break;
free(newpath);
@@ -2409,10 +2373,7 @@ static int lookup_path(struct fuse *f, fuse_ino_t nodeid,
int res;
memset(e, 0, sizeof(struct fuse_entry_param));
- if (fi)
- res = fuse_fs_fgetattr(f->fs, path, &e->attr, fi);
- else
- res = fuse_fs_getattr(f->fs, path, &e->attr);
+ res = fuse_fs_getattr(f->fs, path, &e->attr, fi);
if (res == 0) {
res = do_lookup(f, nodeid, name, e);
if (res == 0 && f->conf.debug) {
@@ -2652,17 +2613,14 @@ static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
memset(&buf, 0, sizeof(buf));
- if (fi != NULL && f->fs->op.fgetattr)
+ if (fi != NULL)
err = get_path_nullok(f, ino, &path);
else
err = get_path(f, ino, &path);
if (!err) {
struct fuse_intr_data d;
fuse_prepare_interrupt(f, req, &d);
- if (fi)
- err = fuse_fs_fgetattr(f->fs, path, &buf, fi);
- else
- err = fuse_fs_getattr(f->fs, path, &buf);
+ err = fuse_fs_getattr(f->fs, path, &buf, fi);
fuse_finish_interrupt(f, req, &d);
free_path(f, ino, path);
}
@@ -2682,11 +2640,12 @@ static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
reply_err(req, err);
}
-int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode)
+int fuse_fs_chmod(struct fuse_fs *fs, const char *path, mode_t mode,
+ struct fuse_file_info *fi)
{
fuse_get_context()->private_data = fs->user_data;
if (fs->op.chmod)
- return fs->op.chmod(path, mode);
+ return fs->op.chmod(path, mode, fi);
else
return -ENOSYS;
}
@@ -2700,8 +2659,7 @@ static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
int err;
memset(&buf, 0, sizeof(buf));
- if (valid == FUSE_SET_ATTR_SIZE && fi != NULL &&
- f->fs->op.ftruncate && f->fs->op.fgetattr)
+ if (fi != NULL)
err = get_path_nullok(f, ino, &path);
else
err = get_path(f, ino, &path);
@@ -2710,21 +2668,17 @@ static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
fuse_prepare_interrupt(f, req, &d);
err = 0;
if (!err && (valid & FUSE_SET_ATTR_MODE))
- err = fuse_fs_chmod(f->fs, path, attr->st_mode);
+ err = fuse_fs_chmod(f->fs, path, attr->st_mode, fi);
if (!err && (valid & (FUSE_SET_ATTR_UID | FUSE_SET_ATTR_GID))) {
uid_t uid = (valid & FUSE_SET_ATTR_UID) ?
attr->st_uid : (uid_t) -1;
gid_t gid = (valid & FUSE_SET_ATTR_GID) ?
attr->st_gid : (gid_t) -1;
- err = fuse_fs_chown(f->fs, path, uid, gid);
+ err = fuse_fs_chown(f->fs, path, uid, gid, fi);
}
if (!err && (valid & FUSE_SET_ATTR_SIZE)) {
- if (fi)
- err = fuse_fs_ftruncate(f->fs, path,
- attr->st_size, fi);
- else
- err = fuse_fs_truncate(f->fs, path,
- attr->st_size);
+ err = fuse_fs_truncate(f->fs, path,
+ attr->st_size, fi);
}
#ifdef HAVE_UTIMENSAT
if (!err &&
@@ -2746,7 +2700,7 @@ static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
else if (valid & FUSE_SET_ATTR_MTIME)
tv[1] = attr->st_mtim;
- err = fuse_fs_utimens(f->fs, path, tv);
+ err = fuse_fs_utimens(f->fs, path, tv, fi);
} else
#endif
if (!err &&
@@ -2757,13 +2711,10 @@ static void fuse_lib_setattr(fuse_req_t req, fuse_ino_t ino, struct stat *attr,
tv[0].tv_nsec = ST_ATIM_NSEC(attr);
tv[1].tv_sec = attr->st_mtime;
tv[1].tv_nsec = ST_MTIM_NSEC(attr);
- err = fuse_fs_utimens(f->fs, path, tv);
+ err = fuse_fs_utimens(f->fs, path, tv, fi);
}
if (!err) {
- if (fi)
- err = fuse_fs_fgetattr(f->fs, path, &buf, fi);
- else
- err = fuse_fs_getattr(f->fs, path, &buf);
+ err = fuse_fs_getattr(f->fs, path, &buf, fi);
}
fuse_finish_interrupt(f, req, &d);
free_path(f, ino, path);
@@ -3116,7 +3067,7 @@ static void open_auto_cache(struct fuse *f, fuse_ino_t ino, const char *path,
struct stat stbuf;
int err;
pthread_mutex_unlock(&f->lock);
- err = fuse_fs_fgetattr(f->fs, path, &stbuf, fi);
+ err = fuse_fs_getattr(f->fs, path, &stbuf, fi);
pthread_mutex_lock(&f->lock);
if (!err)
update_stat(node, &stbuf);
@@ -4455,7 +4406,6 @@ static const struct fuse_opt fuse_lib_opts[] = {
FUSE_LIB_OPT("negative_timeout=%lf", negative_timeout, 0),
FUSE_LIB_OPT("noforget", remember, -1),
FUSE_LIB_OPT("remember=%u", remember, 0),
- FUSE_LIB_OPT("nopath", nopath, 1),
FUSE_LIB_OPT("intr", intr, 1),
FUSE_LIB_OPT("intr_signal=%d", intr_signal, 0),
FUSE_LIB_OPT("modules=%s", modules, 0),
@@ -4464,12 +4414,9 @@ static const struct fuse_opt fuse_lib_opts[] = {
static void fuse_lib_help(void)
{
+ /* These are not all options, but only the ones that
+ may be of interest to an end-user */
printf(
-"High-level options\n"
-" -o hard_remove immediate removal (don't hide files)\n"
-" -o use_ino let filesystem set inode numbers\n"
-" -o readdir_ino try to fill in d_ino in readdir\n"
-" -o direct_io use direct I/O\n"
" -o kernel_cache cache files in kernel\n"
" -o [no]auto_cache enable caching based on modification times (off)\n"
" -o umask=M set file permissions (octal)\n"
@@ -4481,11 +4428,7 @@ static void fuse_lib_help(void)
" -o ac_attr_timeout=T auto cache timeout for attributes (attr_timeout)\n"
" -o noforget never forget cached inodes\n"
" -o remember=T remember cached inodes for T seconds (0s)\n"
-" -o nopath don't supply path if not necessary\n"
-" -o intr allow requests to be interrupted\n"
-" -o intr_signal=NUM signal to send on interrupt (%i)\n"
-" -o modules=M1[:M2...] names of modules to push onto filesystem stack\n\n",
- FUSE_DEFAULT_INTR_SIGNAL);
+" -o modules=M1[:M2...] names of modules to push onto filesystem stack\n");
}
static void fuse_lib_help_modules(void)
@@ -4662,7 +4605,6 @@ struct fuse *fuse_new(struct fuse_args *args,
if (f->conf.show_help) {
fuse_lib_help();
fuse_lowlevel_help();
- fuse_mount_help();
/* Defer printing module help until modules
have been loaded */
}
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index 5ed23c7..50962e3 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -41,34 +41,11 @@ struct fuse_notify_req {
struct fuse_notify_req *prev;
};
-struct session_opts {
- int atomic_o_trunc;
- int no_remote_posix_lock;
- int no_remote_flock;
- int splice_write;
- int splice_move;
- int splice_read;
- int no_splice_write;
- int no_splice_move;
- int no_splice_read;
- int auto_inval_data;
- int no_auto_inval_data;
- int no_readdirplus;
- int no_readdirplus_auto;
- int async_dio;
- int no_async_dio;
- int writeback_cache;
- int no_writeback_cache;
- int async_read;
- int sync_read;
-};
-
struct fuse_session {
char *mountpoint;
volatile int exited;
int fd;
struct mount_opts *mo;
- struct session_opts opts;
int debug;
int allow_root;
struct fuse_lowlevel_ops op;
@@ -130,9 +107,7 @@ void fuse_chan_put(struct fuse_chan *ch);
struct mount_opts *parse_mount_opts(struct fuse_args *args);
void destroy_mount_opts(struct mount_opts *mo);
-void fuse_mount_help(void);
void fuse_mount_version(void);
-
void fuse_kern_unmount(const char *mountpoint, int fd);
int fuse_kern_mount(const char *mountpoint, struct mount_opts *mo);
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 33e0ae5..1dbe6ed 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -1809,39 +1809,6 @@ static void do_fallocate(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
fuse_reply_err(req, ENOSYS);
}
-static void apply_want_options(struct session_opts *opts,
- struct fuse_conn_info *conn)
-{
-#define LL_ENABLE(cond,cap) \
- if (cond) conn->want |= (cap)
-#define LL_DISABLE(cond,cap) \
- if (cond) conn->want &= ~(cap)
-
- LL_ENABLE(opts->splice_read, FUSE_CAP_SPLICE_READ);
- LL_DISABLE(opts->no_splice_read, FUSE_CAP_SPLICE_READ);
-
- LL_ENABLE(opts->splice_write, FUSE_CAP_SPLICE_WRITE);
- LL_DISABLE(opts->no_splice_write, FUSE_CAP_SPLICE_WRITE);
-
- LL_ENABLE(opts->splice_move, FUSE_CAP_SPLICE_MOVE);
- LL_DISABLE(opts->no_splice_move, FUSE_CAP_SPLICE_MOVE);
-
- LL_ENABLE(opts->auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
- LL_DISABLE(opts->no_auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
-
- LL_DISABLE(opts->no_readdirplus, FUSE_CAP_READDIRPLUS);
- LL_DISABLE(opts->no_readdirplus_auto, FUSE_CAP_READDIRPLUS_AUTO);
-
- LL_ENABLE(opts->async_dio, FUSE_CAP_ASYNC_DIO);
- LL_DISABLE(opts->no_async_dio, FUSE_CAP_ASYNC_DIO);
-
- LL_ENABLE(opts->writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
- LL_DISABLE(opts->no_writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
-
- LL_ENABLE(opts->async_read, FUSE_CAP_ASYNC_READ);
- LL_DISABLE(opts->sync_read, FUSE_CAP_ASYNC_READ);
-}
-
static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
struct fuse_init_in *arg = (struct fuse_init_in *) inarg;
@@ -1946,19 +1913,9 @@ static void do_init(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
f->conn.max_write = bufsize;
f->got_init = 1;
-
- /* Apply command-line options (so that init() handler has
- an idea about user preferences */
- apply_want_options(&f->opts, &f->conn);
-
- /* Allow file-system to overwrite defaults */
if (f->op.init)
f->op.init(f->userdata, &f->conn);
- /* Now explicitly overwrite file-system's decision
- with command-line options */
- apply_want_options(&f->opts, &f->conn);
-
/* Always enable big writes, this is superseded
by the max_write option */
outarg.flags |= FUSE_BIG_WRITES;
@@ -2566,36 +2523,8 @@ clear_pipe:
static const struct fuse_opt fuse_ll_opts[] = {
LL_OPTION("debug", debug, 1),
LL_OPTION("-d", debug, 1),
+ LL_OPTION("--debug", debug, 1),
LL_OPTION("allow_root", allow_root, 1),
- LL_OPTION("max_write=%u", conn.max_write, 0),
- LL_OPTION("max_readahead=%u", conn.max_readahead, 0),
- LL_OPTION("max_background=%u", conn.max_background, 0),
- LL_OPTION("congestion_threshold=%u", conn.congestion_threshold, 0),
- LL_OPTION("sync_read", opts.sync_read, 1),
- LL_OPTION("async_read", opts.async_read, 1),
- LL_OPTION("atomic_o_trunc", opts.atomic_o_trunc, 1),
- LL_OPTION("no_remote_lock", opts.no_remote_posix_lock, 1),
- LL_OPTION("no_remote_lock", opts.no_remote_flock, 1),
- LL_OPTION("no_remote_flock", opts.no_remote_flock, 1),
- LL_OPTION("no_remote_posix_lock", opts.no_remote_posix_lock, 1),
- LL_OPTION("splice_write", opts.splice_write, 1),
- LL_OPTION("no_splice_write", opts.no_splice_write, 1),
- LL_OPTION("splice_move", opts.splice_move, 1),
- LL_OPTION("no_splice_move", opts.no_splice_move, 1),
- LL_OPTION("splice_read", opts.splice_read, 1),
- LL_OPTION("no_splice_read", opts.no_splice_read, 1),
- LL_OPTION("auto_inval_data", opts.auto_inval_data, 1),
- LL_OPTION("no_auto_inval_data", opts.no_auto_inval_data, 1),
- LL_OPTION("readdirplus=no", opts.no_readdirplus, 1),
- LL_OPTION("readdirplus=yes", opts.no_readdirplus, 0),
- LL_OPTION("readdirplus=yes", opts.no_readdirplus_auto, 1),
- LL_OPTION("readdirplus=auto", opts.no_readdirplus, 0),
- LL_OPTION("readdirplus=auto", opts.no_readdirplus_auto, 0),
- LL_OPTION("async_dio", opts.async_dio, 1),
- LL_OPTION("no_async_dio", opts.no_async_dio, 1),
- LL_OPTION("writeback_cache", opts.writeback_cache, 1),
- LL_OPTION("no_writeback_cache", opts.no_writeback_cache, 1),
- LL_OPTION("time_gran=%u", conn.time_gran, 0),
FUSE_OPT_END
};
@@ -2603,30 +2532,17 @@ void fuse_lowlevel_version(void)
{
printf("using FUSE kernel interface version %i.%i\n",
FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
+ fuse_mount_version();
}
void fuse_lowlevel_help(void)
{
+ /* These are not all options, but the ones that are
+ potentially of interest to an end-user */
printf(
-"Low-level options\n"
-" -o max_write=N set maximum size of write requests\n"
-" -o max_readahead=N set maximum readahead\n"
-" -o max_background=N set number of maximum background requests\n"
-" -o congestion_threshold=N set kernel's congestion threshold\n"
-" -o async_read perform reads asynchronously (default)\n"
-" -o sync_read perform reads synchronously\n"
-" -o atomic_o_trunc enable atomic open+truncate support\n"
-" -o no_remote_lock disable remote file locking\n"
-" -o no_remote_flock disable remote file locking (BSD)\n"
-" -o no_remote_posix_lock disable remote file locking (POSIX)\n"
-" -o [no_]splice_write use splice to write to the fuse device\n"
-" -o [no_]splice_move move data while splicing to the fuse device\n"
-" -o [no_]splice_read use splice to read from the fuse device\n"
-" -o [no_]auto_inval_data use automatic kernel cache invalidation logic\n"
-" -o readdirplus=S control readdirplus use (yes|no|auto)\n"
-" -o [no_]async_dio asynchronous direct I/O\n"
-" -o [no_]writeback_cache asynchronous, buffered writes\n"
-" -o time_gran=N time granularity in nsec\n\n");
+" -o allow_other allow access to other users\n"
+" -o allow_root allow access to root\n"
+" -o auto_unmount auto unmount on process termination\n");
}
void fuse_session_destroy(struct fuse_session *se)
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index 3301b12..1edaf5e 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -126,9 +126,9 @@ FUSE_3.0 {
fuse_fs_fallocate;
fuse_lowlevel_help;
fuse_lowlevel_version;
- fuse_mount_help;
fuse_cmdline_help;
- fuse_mount_version;
+ fuse_apply_conn_info_opts;
+ fuse_parse_conn_info_opts;
local:
*;
diff --git a/lib/helper.c b/lib/helper.c
index 5663fa9..a76c19d 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -49,16 +49,78 @@ static const struct fuse_opt fuse_helper_opts[] = {
FUSE_OPT_END
};
+struct fuse_conn_info_opts {
+ int atomic_o_trunc;
+ int no_remote_posix_lock;
+ int no_remote_flock;
+ int splice_write;
+ int splice_move;
+ int splice_read;
+ int no_splice_write;
+ int no_splice_move;
+ int no_splice_read;
+ int auto_inval_data;
+ int no_auto_inval_data;
+ int no_readdirplus;
+ int no_readdirplus_auto;
+ int async_dio;
+ int no_async_dio;
+ int writeback_cache;
+ int no_writeback_cache;
+ int async_read;
+ int sync_read;
+ unsigned max_write;
+ unsigned max_readahead;
+ unsigned max_background;
+ unsigned congestion_threshold;
+ unsigned time_gran;
+};
+
+#define CONN_OPTION(t, p, v) \
+ { t, offsetof(struct fuse_conn_info_opts, p), v }
+static const struct fuse_opt conn_info_opt_spec[] = {
+ CONN_OPTION("max_write=%u", max_write, 0),
+ CONN_OPTION("max_readahead=%u", max_readahead, 0),
+ CONN_OPTION("max_background=%u", max_background, 0),
+ CONN_OPTION("congestion_threshold=%u", congestion_threshold, 0),
+ CONN_OPTION("sync_read", sync_read, 1),
+ CONN_OPTION("async_read", async_read, 1),
+ CONN_OPTION("atomic_o_trunc", atomic_o_trunc, 1),
+ CONN_OPTION("no_remote_lock", no_remote_posix_lock, 1),
+ CONN_OPTION("no_remote_lock", no_remote_flock, 1),
+ CONN_OPTION("no_remote_flock", no_remote_flock, 1),
+ CONN_OPTION("no_remote_posix_lock", no_remote_posix_lock, 1),
+ CONN_OPTION("splice_write", splice_write, 1),
+ CONN_OPTION("no_splice_write", no_splice_write, 1),
+ CONN_OPTION("splice_move", splice_move, 1),
+ CONN_OPTION("no_splice_move", no_splice_move, 1),
+ CONN_OPTION("splice_read", splice_read, 1),
+ CONN_OPTION("no_splice_read", no_splice_read, 1),
+ CONN_OPTION("auto_inval_data", auto_inval_data, 1),
+ CONN_OPTION("no_auto_inval_data", no_auto_inval_data, 1),
+ CONN_OPTION("readdirplus=no", no_readdirplus, 1),
+ CONN_OPTION("readdirplus=yes", no_readdirplus, 0),
+ CONN_OPTION("readdirplus=yes", no_readdirplus_auto, 1),
+ CONN_OPTION("readdirplus=auto", no_readdirplus, 0),
+ CONN_OPTION("readdirplus=auto", no_readdirplus_auto, 0),
+ CONN_OPTION("async_dio", async_dio, 1),
+ CONN_OPTION("no_async_dio", no_async_dio, 1),
+ CONN_OPTION("writeback_cache", writeback_cache, 1),
+ CONN_OPTION("no_writeback_cache", no_writeback_cache, 1),
+ CONN_OPTION("time_gran=%u", time_gran, 0),
+ FUSE_OPT_END
+};
+
+
void fuse_cmdline_help(void)
{
- printf("General options:\n"
- " -h --help print help\n"
+ printf(" -h --help print help\n"
" -V --version print version\n"
" -d -o debug enable debug output (implies -f)\n"
" -f foreground operation\n"
" -s disable multi-threaded operation\n"
" -o clone_fd use separate fuse device fd for each thread\n"
- "\n");
+ " (may improve performance)\n");
}
static int fuse_helper_opt_proc(void *data, const char *arg, int key,
@@ -196,7 +258,6 @@ int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
if (opts.show_version) {
printf("FUSE library version %s\n", PACKAGE_VERSION);
fuse_lowlevel_version();
- fuse_mount_version();
res = 0;
goto out1;
}
@@ -207,6 +268,7 @@ int fuse_main_real(int argc, char *argv[], const struct fuse_operations *op,
if(args.argv[0] != '\0')
printf("usage: %s [options] <mountpoint>\n\n",
args.argv[0]);
+ printf("FUSE options:\n");
fuse_cmdline_help();
if (fuse_opt_add_arg(&args, "--help") == -1) {
res = 1;
@@ -262,3 +324,67 @@ out1:
fuse_opt_free_args(&args);
return res;
}
+
+
+void fuse_apply_conn_info_opts(struct fuse_conn_info_opts *opts,
+ struct fuse_conn_info *conn)
+{
+ if(opts->max_write)
+ conn->max_write = opts->max_write;
+ if(opts->max_background)
+ conn->max_background = opts->max_background;
+ if(opts->congestion_threshold)
+ conn->congestion_threshold = opts->congestion_threshold;
+ if(opts->time_gran)
+ conn->time_gran = opts->time_gran;
+ if(opts->max_readahead)
+ conn->max_readahead = opts->max_readahead;
+
+#define LL_ENABLE(cond,cap) \
+ if (cond) conn->want |= (cap)
+#define LL_DISABLE(cond,cap) \
+ if (cond) conn->want &= ~(cap)
+
+ LL_ENABLE(opts->splice_read, FUSE_CAP_SPLICE_READ);
+ LL_DISABLE(opts->no_splice_read, FUSE_CAP_SPLICE_READ);
+
+ LL_ENABLE(opts->splice_write, FUSE_CAP_SPLICE_WRITE);
+ LL_DISABLE(opts->no_splice_write, FUSE_CAP_SPLICE_WRITE);
+
+ LL_ENABLE(opts->splice_move, FUSE_CAP_SPLICE_MOVE);
+ LL_DISABLE(opts->no_splice_move, FUSE_CAP_SPLICE_MOVE);
+
+ LL_ENABLE(opts->auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
+ LL_DISABLE(opts->no_auto_inval_data, FUSE_CAP_AUTO_INVAL_DATA);
+
+ LL_DISABLE(opts->no_readdirplus, FUSE_CAP_READDIRPLUS);
+ LL_DISABLE(opts->no_readdirplus_auto, FUSE_CAP_READDIRPLUS_AUTO);
+
+ LL_ENABLE(opts->async_dio, FUSE_CAP_ASYNC_DIO);
+ LL_DISABLE(opts->no_async_dio, FUSE_CAP_ASYNC_DIO);
+
+ LL_ENABLE(opts->writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
+ LL_DISABLE(opts->no_writeback_cache, FUSE_CAP_WRITEBACK_CACHE);
+
+ LL_ENABLE(opts->async_read, FUSE_CAP_ASYNC_READ);
+ LL_DISABLE(opts->sync_read, FUSE_CAP_ASYNC_READ);
+
+ LL_DISABLE(opts->no_remote_posix_lock, FUSE_CAP_POSIX_LOCKS);
+ LL_DISABLE(opts->no_remote_flock, FUSE_CAP_FLOCK_LOCKS);
+}
+
+struct fuse_conn_info_opts* fuse_parse_conn_info_opts(struct fuse_args *args)
+{
+ struct fuse_conn_info_opts *opts;
+
+ opts = calloc(1, sizeof(struct fuse_conn_info_opts));
+ if(opts == NULL) {
+ fprintf(stderr, "calloc failed\n");
+ return NULL;
+ }
+ if(fuse_opt_parse(args, opts, conn_info_opt_spec, NULL) == -1) {
+ free(opts);
+ return NULL;
+ }
+ return opts;
+}
diff --git a/lib/modules/iconv.c b/lib/modules/iconv.c
index 174e2b9..41a072c 100644
--- a/lib/modules/iconv.c
+++ b/lib/modules/iconv.c
@@ -101,26 +101,14 @@ err:
return err;
}
-static int iconv_getattr(const char *path, struct stat *stbuf)
+static int iconv_getattr(const char *path, struct stat *stbuf,
+ struct fuse_file_info *fi)
{
struct iconv *ic = iconv_get();
char *newpath;
int err = iconv_convpath(ic, path, &newpath, 0);
if (!err) {
- err = fuse_fs_getattr(ic->next, newpath, stbuf);
- free(newpath);
- }
- return err;
-}
-
-static int iconv_fgetattr(const char *path, struct stat *stbuf,
- struct fuse_file_info *fi)
-{
- struct iconv *ic = iconv_get();
- char *newpath;
- int err = iconv_convpath(ic, path, &newpath, 0);
- if (!err) {
- err = fuse_fs_fgetattr(ic->next, newpath, stbuf, fi);
+ err = fuse_fs_getattr(ic->next, newpath, stbuf, fi);
free(newpath);
}
return err;
@@ -315,62 +303,53 @@ static int iconv_link(const char *from, const char *to)
return err;
}
-static int iconv_chmod(const char *path, mode_t mode)
-{
- struct iconv *ic = iconv_get();
- char *newpath;
- int err = iconv_convpath(ic, path, &newpath, 0);
- if (!err) {
- err = fuse_fs_chmod(ic->next, newpath, mode);
- free(newpath);
- }
- return err;
-}
-
-static int iconv_chown(const char *path, uid_t uid, gid_t gid)
+static int iconv_chmod(const char *path, mode_t mode,
+ struct fuse_file_info *fi)
{
struct iconv *ic = iconv_get();
char *newpath;
int err = iconv_convpath(ic, path, &newpath, 0);
if (!err) {
- err = fuse_fs_chown(ic->next, newpath, uid, gid);
+ err = fuse_fs_chmod(ic->next, newpath, mode, fi);
free(newpath);
}
return err;
}
-static int iconv_truncate(const char *path, off_t size)
+static int iconv_chown(const char *path, uid_t uid, gid_t gid,
+ struct fuse_file_info *fi)
{
struct iconv *ic = iconv_get();
char *newpath;
int err = iconv_convpath(ic, path, &newpath, 0);
if (!err) {
- err = fuse_fs_truncate(ic->next, newpath, size);
+ err = fuse_fs_chown(ic->next, newpath, uid, gid, fi);
free(newpath);
}
return err;
}
-static int iconv_ftruncate(const char *path, off_t size,
+static int iconv_truncate(const char *path, off_t size,
struct fuse_file_info *fi)
{
struct iconv *ic = iconv_get();
char *newpath;
int err = iconv_convpath(ic, path, &newpath, 0);
if (!err) {
- err = fuse_fs_ftruncate(ic->next, newpath, size, fi);
+ err = fuse_fs_truncate(ic->next, newpath, size, fi);
free(newpath);
}
return err;
}
-static int iconv_utimens(const char *path, const struct timespec ts[2])
+static int iconv_utimens(const char *path, const struct timespec ts[2],
+ struct fuse_file_info *fi)
{
struct iconv *ic = iconv_get();
char *newpath;
int err = iconv_convpath(ic, path, &newpath, 0);
if (!err) {
- err = fuse_fs_utimens(ic->next, newpath, ts);
+ err = fuse_fs_utimens(ic->next, newpath, ts, fi);
free(newpath);
}
return err;
@@ -600,7 +579,6 @@ static const struct fuse_operations iconv_oper = {
.destroy = iconv_destroy,
.init = iconv_init,
.getattr = iconv_getattr,
- .fgetattr = iconv_fgetattr,
.access = iconv_access,
.readlink = iconv_readlink,
.opendir = iconv_opendir,
@@ -616,7 +594,6 @@ static const struct fuse_operations iconv_oper = {
.chmod = iconv_chmod,
.chown = iconv_chown,
.truncate = iconv_truncate,
- .ftruncate = iconv_ftruncate,
.utimens = iconv_utimens,
.create = iconv_create,
.open = iconv_open_file,
diff --git a/lib/modules/subdir.c b/lib/modules/subdir.c
index a039b3c..c264fb4 100644
--- a/lib/modules/subdir.c
+++ b/lib/modules/subdir.c
@@ -52,26 +52,14 @@ static int subdir_addpath(struct subdir *d, const char *path, char **newpathp)
return 0;
}
-static int subdir_getattr(const char *path, struct stat *stbuf)
+static int subdir_getattr(const char *path, struct stat *stbuf,
+ struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
char *newpath;
int err = subdir_addpath(d, path, &newpath);
if (!err) {
- err = fuse_fs_getattr(d->next, newpath, stbuf);
- free(newpath);
- }
- return err;
-}
-
-static int subdir_fgetattr(const char *path, struct stat *stbuf,
- struct fuse_file_info *fi)
-{
- struct subdir *d = subdir_get();
- char *newpath;
- int err = subdir_addpath(d, path, &newpath);
- if (!err) {
- err = fuse_fs_fgetattr(d->next, newpath, stbuf, fi);
+ err = fuse_fs_getattr(d->next, newpath, stbuf, fi);
free(newpath);
}
return err;
@@ -301,62 +289,53 @@ static int subdir_link(const char *from, const char *to)
return err;
}
-static int subdir_chmod(const char *path, mode_t mode)
-{
- struct subdir *d = subdir_get();
- char *newpath;
- int err = subdir_addpath(d, path, &newpath);
- if (!err) {
- err = fuse_fs_chmod(d->next, newpath, mode);
- free(newpath);
- }
- return err;
-}
-
-static int subdir_chown(const char *path, uid_t uid, gid_t gid)
+static int subdir_chmod(const char *path, mode_t mode,
+ struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
char *newpath;
int err = subdir_addpath(d, path, &newpath);
if (!err) {
- err = fuse_fs_chown(d->next, newpath, uid, gid);
+ err = fuse_fs_chmod(d->next, newpath, mode, fi);
free(newpath);
}
return err;
}
-static int subdir_truncate(const char *path, off_t size)
+static int subdir_chown(const char *path, uid_t uid, gid_t gid,
+ struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
char *newpath;
int err = subdir_addpath(d, path, &newpath);
if (!err) {
- err = fuse_fs_truncate(d->next, newpath, size);
+ err = fuse_fs_chown(d->next, newpath, uid, gid, fi);
free(newpath);
}
return err;
}
-static int subdir_ftruncate(const char *path, off_t size,
- struct fuse_file_info *fi)
+static int subdir_truncate(const char *path, off_t size,
+ struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
char *newpath;
int err = subdir_addpath(d, path, &newpath);
if (!err) {
- err = fuse_fs_ftruncate(d->next, newpath, size, fi);
+ err = fuse_fs_truncate(d->next, newpath, size, fi);
free(newpath);
}
return err;
}
-static int subdir_utimens(const char *path, const struct timespec ts[2])
+static int subdir_utimens(const char *path, const struct timespec ts[2],
+ struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
char *newpath;
int err = subdir_addpath(d, path, &newpath);
if (!err) {
- err = fuse_fs_utimens(d->next, newpath, ts);
+ err = fuse_fs_utimens(d->next, newpath, ts, fi);
free(newpath);
}
return err;
@@ -582,7 +561,6 @@ static const struct fuse_operations subdir_oper = {
.destroy = subdir_destroy,
.init = subdir_init,
.getattr = subdir_getattr,
- .fgetattr = subdir_fgetattr,
.access = subdir_access,
.readlink = subdir_readlink,
.opendir = subdir_opendir,
@@ -598,7 +576,6 @@ static const struct fuse_operations subdir_oper = {
.chmod = subdir_chmod,
.chown = subdir_chown,
.truncate = subdir_truncate,
- .ftruncate = subdir_ftruncate,
.utimens = subdir_utimens,
.create = subdir_create,
.open = subdir_open,
diff --git a/lib/mount.c b/lib/mount.c
index 386260c..051b424 100644
--- a/lib/mount.c
+++ b/lib/mount.c
@@ -65,7 +65,6 @@ struct mount_opts {
int allow_other;
int allow_root;
int flags;
- int nonempty;
int auto_unmount;
int blkdev;
char *fsname;
@@ -81,19 +80,16 @@ struct mount_opts {
static const struct fuse_opt fuse_mount_opts[] = {
FUSE_MOUNT_OPT("allow_other", allow_other),
FUSE_MOUNT_OPT("allow_root", allow_root),
- FUSE_MOUNT_OPT("nonempty", nonempty),
FUSE_MOUNT_OPT("blkdev", blkdev),
FUSE_MOUNT_OPT("auto_unmount", auto_unmount),
FUSE_MOUNT_OPT("fsname=%s", fsname),
FUSE_MOUNT_OPT("subtype=%s", subtype),
FUSE_OPT_KEY("allow_other", KEY_KERN_OPT),
FUSE_OPT_KEY("allow_root", KEY_ALLOW_ROOT),
- FUSE_OPT_KEY("nonempty", KEY_FUSERMOUNT_OPT),
FUSE_OPT_KEY("auto_unmount", KEY_FUSERMOUNT_OPT),
FUSE_OPT_KEY("blkdev", KEY_FUSERMOUNT_OPT),
FUSE_OPT_KEY("fsname=", KEY_FUSERMOUNT_OPT),
FUSE_OPT_KEY("subtype=", KEY_SUBTYPE_OPT),
- FUSE_OPT_KEY("large_read", KEY_KERN_OPT),
FUSE_OPT_KEY("blksize=", KEY_KERN_OPT),
FUSE_OPT_KEY("default_permissions", KEY_KERN_OPT),
FUSE_OPT_KEY("context=", KEY_KERN_OPT),
@@ -119,21 +115,6 @@ static const struct fuse_opt fuse_mount_opts[] = {
FUSE_OPT_END
};
-void fuse_mount_help(void)
-{
- printf(
-"FUSE-specific mount options:\n"
-" -o allow_other allow access to other users\n"
-" -o allow_root allow access to root\n"
-" -o auto_unmount auto unmount on process termination\n"
-" -o nonempty allow mounts over non-empty file/dir\n"
-" -o default_permissions enable permission checking by kernel\n"
-" -o fsname=NAME set filesystem name\n"
-" -o subtype=NAME set filesystem type\n"
-" -o large_read issue large read requests (2.4 only)\n"
-" -o max_read=N set maximum size of read requests\n\n");
-}
-
static void exec_fusermount(const char *argv[])
{
execv(FUSERMOUNT_DIR "/" FUSERMOUNT_PROG, (char **) argv);
@@ -423,13 +404,6 @@ static int fuse_mount_sys(const char *mnt, struct mount_opts *mo,
return -1;
}
- if (!mo->nonempty) {
- res = fuse_mnt_check_empty("fuse", mnt, stbuf.st_mode,
- stbuf.st_size);
- if (res == -1)
- return -1;
- }
-
if (mo->auto_unmount) {
/* Tell the caller to fallback to fusermount because
auto-unmount does not work otherwise. */
diff --git a/lib/mount_bsd.c b/lib/mount_bsd.c
index bc3ed89..9cf9dfa 100644
--- a/lib/mount_bsd.c
+++ b/lib/mount_bsd.c
@@ -90,20 +90,9 @@ static const struct fuse_opt fuse_mount_opts[] = {
* handle them
*/
FUSE_OPT_KEY("fsname=", KEY_KERN),
- FUSE_OPT_KEY("nonempty", KEY_KERN),
- FUSE_OPT_KEY("large_read", KEY_KERN),
FUSE_OPT_END
};
-void fuse_mount_help(void)
-{
- printf(
-"FUSE-specific mount options:\n"
-" -o allow_root allow access to root\n");
- system(FUSERMOUNT_PROG " --help");
- fputc('\n', stderr);
-}
-
void fuse_mount_version(void)
{
system(FUSERMOUNT_PROG " --version");
diff --git a/lib/mount_util.c b/lib/mount_util.c
index a23ab0b..8b64ca2 100644
--- a/lib/mount_util.c
+++ b/lib/mount_util.c
@@ -333,39 +333,6 @@ char *fuse_mnt_resolve_path(const char *progname, const char *orig)
return dst;
}
-int fuse_mnt_check_empty(const char *progname, const char *mnt,
- mode_t rootmode, off_t rootsize)
-{
- int isempty = 1;
-
- if (S_ISDIR(rootmode)) {
- struct dirent *ent;
- DIR *dp = opendir(mnt);
- if (dp == NULL) {
- fprintf(stderr,
- "%s: failed to open mountpoint for reading: %s\n",
- progname, strerror(errno));
- return -1;
- }
- while ((ent = readdir(dp)) != NULL) {
- if (strcmp(ent->d_name, ".") != 0 &&
- strcmp(ent->d_name, "..") != 0) {
- isempty = 0;
- break;
- }
- }
- closedir(dp);
- } else if (rootsize)
- isempty = 0;
-
- if (!isempty) {
- fprintf(stderr, "%s: mountpoint is not empty\n", progname);
- fprintf(stderr, "%s: if you are sure this is safe, use the 'nonempty' mount option\n", progname);
- return -1;
- }
- return 0;
-}
-
int fuse_mnt_check_fuseblk(void)
{
char buf[256];
diff --git a/lib/mount_util.h b/lib/mount_util.h
index dc5c916..55c6c5e 100644
--- a/lib/mount_util.h
+++ b/lib/mount_util.h
@@ -14,6 +14,4 @@ int fuse_mnt_remove_mount(const char *progname, const char *mnt);
int fuse_mnt_umount(const char *progname, const char *abs_mnt,
const char *rel_mnt, int lazy);
char *fuse_mnt_resolve_path(const char *progname, const char *orig);
-int fuse_mnt_check_empty(const char *progname, const char *mnt,
- mode_t rootmode, off_t rootsize);
int fuse_mnt_check_fuseblk(void);