summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Makefile.am2
-rw-r--r--lib/fuse.c34
-rw-r--r--lib/fuse_i.h2
-rw-r--r--lib/fuse_lowlevel.c117
-rw-r--r--lib/fuse_opt.c55
-rw-r--r--lib/fuse_versionscript24
-rw-r--r--lib/helper.c38
-rw-r--r--lib/mount.c1
8 files changed, 210 insertions, 63 deletions
diff --git a/lib/Makefile.am b/lib/Makefile.am
index d58cfed..366fcb0 100644
--- a/lib/Makefile.am
+++ b/lib/Makefile.am
@@ -22,7 +22,7 @@ libfuse_la_SOURCES = \
helper.c \
$(mount_source)
-libfuse_la_LDFLAGS = -lpthread -version-number 2:5:0 \
+libfuse_la_LDFLAGS = -lpthread -version-number 2:7:0 \
-Wl,--version-script,fuse_versionscript
EXTRA_DIST = fuse_versionscript
diff --git a/lib/fuse.c b/lib/fuse.c
index 7d66a7d..2cfb436 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -553,7 +553,7 @@ static void reply_entry(fuse_req_t req, const struct fuse_entry_param *e,
reply_err(req, err);
}
-static void fuse_data_init(void *data)
+static void fuse_data_init(void *data, struct fuse_conn_info *conn)
{
struct fuse *f = (struct fuse *) data;
struct fuse_context *c = fuse_get_context();
@@ -562,7 +562,7 @@ static void fuse_data_init(void *data)
c->fuse = f;
if (f->op.init)
- f->user_data = f->op.init();
+ f->user_data = f->op.init(conn);
}
static void fuse_data_destroy(void *data)
@@ -1808,7 +1808,6 @@ void fuse_set_getcontext_func(struct fuse_context *(*func)(void))
enum {
KEY_HELP,
- KEY_KEEP
};
#define FUSE_LIB_OPT(t, p, v) { t, offsetof(struct fuse_config, p), v }
@@ -1816,8 +1815,8 @@ enum {
static const struct fuse_opt fuse_lib_opts[] = {
FUSE_OPT_KEY("-h", KEY_HELP),
FUSE_OPT_KEY("--help", KEY_HELP),
- FUSE_OPT_KEY("debug", KEY_KEEP),
- FUSE_OPT_KEY("-d", KEY_KEEP),
+ FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
+ FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
FUSE_LIB_OPT("debug", debug, 1),
FUSE_LIB_OPT("-d", debug, 1),
FUSE_LIB_OPT("hard_remove", hard_remove, 1),
@@ -1906,6 +1905,11 @@ struct fuse *fuse_new_common(int fd, struct fuse_args *args,
f->conf.readdir_ino = 1;
#endif
+ if (compat && compat <= 25) {
+ if (fuse_sync_compat_args(args) == -1)
+ goto out_free;
+ }
+
f->se = fuse_lowlevel_new(args, &fuse_path_ops, sizeof(fuse_path_ops), f);
if (f->se == NULL)
goto out_free;
@@ -2012,13 +2016,13 @@ void fuse_destroy(struct fuse *f)
free(f);
}
-#ifndef __FreeBSD__
-
#include "fuse_compat.h"
+#ifndef __FreeBSD__
+
static int fuse_do_open(struct fuse *f, char *path, struct fuse_file_info *fi)
{
- if (!f->compat)
+ if (!f->compat || f->compat >= 25)
return f->op.open(path, fi);
else if (f->compat == 22) {
int err;
@@ -2045,7 +2049,7 @@ static void fuse_do_release(struct fuse *f, char *path,
static int fuse_do_opendir(struct fuse *f, char *path,
struct fuse_file_info *fi)
{
- if (!f->compat) {
+ if (!f->compat || f->compat >= 25) {
return f->op.opendir(path, fi);
} else {
int err;
@@ -2085,7 +2089,7 @@ static int fuse_do_statfs(struct fuse *f, char *path, struct statvfs *buf)
{
int err;
- if (!f->compat) {
+ if (!f->compat || f->compat >= 25) {
err = f->op.statfs(path, buf);
} else if (f->compat > 11) {
struct statfs oldbuf;
@@ -2179,3 +2183,13 @@ static int fuse_do_statfs(struct fuse *f, char *path, struct statvfs *buf)
}
#endif /* __FreeBSD__ */
+
+struct fuse *fuse_new_compat25(int fd, struct fuse_args *args,
+ const struct fuse_operations_compat25 *op,
+ size_t op_size)
+{
+ return fuse_new_common(fd, args, (struct fuse_operations *) op,
+ op_size, 25);
+}
+
+__asm__(".symver fuse_new_compat25,fuse_new@FUSE_2.5");
diff --git a/lib/fuse_i.h b/lib/fuse_i.h
index efbabf7..79c3cbf 100644
--- a/lib/fuse_i.h
+++ b/lib/fuse_i.h
@@ -22,3 +22,5 @@ struct fuse_session *fuse_get_session(struct fuse *f);
struct fuse *fuse_new_common(int fd, struct fuse_args *args,
const struct fuse_operations *op,
size_t op_size, int compat);
+
+int fuse_sync_compat_args(struct fuse_args *args);
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 0bd6c99..13ddab9 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -10,6 +10,7 @@
#include "fuse_lowlevel.h"
#include "fuse_kernel.h"
#include "fuse_opt.h"
+#include "fuse_i.h"
#include <stdio.h>
#include <stdlib.h>
@@ -27,9 +28,8 @@ struct fuse_ll {
struct fuse_lowlevel_ops op;
int got_init;
void *userdata;
- int major;
- int minor;
uid_t owner;
+ struct fuse_conn_info conn;
};
struct fuse_req {
@@ -263,7 +263,7 @@ int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
/* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant
negative entry */
- if (!e->ino && req->f->minor < 4)
+ if (!e->ino && req->f->conn.proto_minor < 4)
return fuse_reply_err(req, ENOENT);
memset(&arg, 0, sizeof(arg));
@@ -330,7 +330,7 @@ int fuse_reply_buf(fuse_req_t req, const char *buf, size_t size)
int fuse_reply_statfs(fuse_req_t req, const struct statvfs *stbuf)
{
struct fuse_statfs_out arg;
- size_t size = req->f->minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(arg);
+ size_t size = req->f->conn.proto_minor < 4 ? FUSE_COMPAT_STATFS_SIZE : sizeof(arg);
memset(&arg, 0, sizeof(arg));
convert_statfs(stbuf, &arg.st);
@@ -693,27 +693,51 @@ static void do_init(fuse_req_t req, struct fuse_init_in *arg)
if (f->debug) {
printf("INIT: %u.%u\n", arg->major, arg->minor);
+ if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
+ printf("flags=0x%08x\n", arg->flags);
+ printf("max_readahead=0x%08x\n", arg->max_readahead);
+ }
fflush(stdout);
}
- f->got_init = 1;
- if (f->op.init)
- f->op.init(f->userdata);
-
- f->major = FUSE_KERNEL_VERSION;
- f->minor = arg->minor;
+ f->conn.proto_major = arg->major;
+ f->conn.proto_minor = arg->minor;
+
+ if (arg->major > 7 || (arg->major == 7 && arg->minor >= 6)) {
+ if (f->conn.async_read)
+ f->conn.async_read = arg->flags & FUSE_ASYNC_READ;
+ if (arg->max_readahead < f->conn.max_readahead)
+ f->conn.max_readahead = arg->max_readahead;
+ } else {
+ f->conn.async_read = 0;
+ f->conn.max_readahead = 0;
+ }
if (bufsize < FUSE_MIN_READ_BUFFER) {
fprintf(stderr, "fuse: warning: buffer size too small: %i\n", bufsize);
bufsize = FUSE_MIN_READ_BUFFER;
}
+ bufsize -= 4096;
+ if (bufsize < f->conn.max_write)
+ f->conn.max_write = bufsize;
+
+ f->got_init = 1;
+ if (f->op.init)
+ f->op.init(f->userdata, &f->conn);
+
memset(&outarg, 0, sizeof(outarg));
- outarg.major = f->major;
+ outarg.major = FUSE_KERNEL_VERSION;
outarg.minor = FUSE_KERNEL_MINOR_VERSION;
- outarg.max_write = bufsize - 4096;
+ if (f->conn.async_read)
+ outarg.flags |= FUSE_ASYNC_READ;
+ outarg.max_readahead = f->conn.max_readahead;
+ outarg.max_write = f->conn.max_write;
if (f->debug) {
printf(" INIT: %u.%u\n", outarg.major, outarg.minor);
+ printf(" flags=0x%08x\n", outarg.flags);
+ printf(" max_readahead=0x%08x\n", outarg.max_readahead);
+ printf(" max_write=0x%08x\n", outarg.max_write);
fflush(stdout);
}
@@ -902,6 +926,11 @@ static struct fuse_opt fuse_ll_opts[] = {
{ "debug", offsetof(struct fuse_ll, debug), 1 },
{ "-d", offsetof(struct fuse_ll, debug), 1 },
{ "allow_root", offsetof(struct fuse_ll, allow_root), 1 },
+ { "max_write=%u", offsetof(struct fuse_ll, conn.max_write), 0 },
+ { "max_readahead=%u", offsetof(struct fuse_ll, conn.max_readahead), 0 },
+ { "async_read", offsetof(struct fuse_ll, conn.async_read), 1 },
+ { "sync_read", offsetof(struct fuse_ll, conn.async_read), 0 },
+ FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_DISCARD),
FUSE_OPT_KEY("-h", KEY_HELP),
FUSE_OPT_KEY("--help", KEY_HELP),
FUSE_OPT_KEY("-V", KEY_VERSION),
@@ -915,6 +944,15 @@ static void fuse_ll_version(void)
FUSE_KERNEL_VERSION, FUSE_KERNEL_MINOR_VERSION);
}
+static void fuse_ll_help(void)
+{
+ fprintf(stderr,
+" -o max_write=N set maximum size of write requests\n"
+" -o max_readahead=N set maximum readahead\n"
+" -o async_read perform reads asynchronously (default)\n"
+" -o sync_read perform reads synchronously\n");
+}
+
static int fuse_ll_opt_proc(void *data, const char *arg, int key,
struct fuse_args *outargs)
{
@@ -922,6 +960,7 @@ static int fuse_ll_opt_proc(void *data, const char *arg, int key,
switch (key) {
case KEY_HELP:
+ fuse_ll_help();
break;
case KEY_VERSION:
@@ -972,6 +1011,10 @@ struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
goto out;
}
+ f->conn.async_read = 1;
+ f->conn.max_write = UINT_MAX;
+ f->conn.max_readahead = UINT_MAX;
+
if (fuse_opt_parse(args, f, fuse_ll_opts, fuse_ll_opt_proc) == -1)
goto out_free;
@@ -991,10 +1034,10 @@ struct fuse_session *fuse_lowlevel_new(struct fuse_args *args,
return NULL;
}
-#ifndef __FreeBSD__
-
#include "fuse_lowlevel_compat.h"
+#ifndef __FreeBSD__
+
static void fill_open_compat(struct fuse_open_out *arg,
const struct fuse_file_info_compat *f)
{
@@ -1062,3 +1105,49 @@ __asm__(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4");
__asm__(".symver fuse_lowlevel_new_compat,fuse_lowlevel_new@FUSE_2.4");
#endif /* __FreeBSD__ */
+
+struct fuse_ll_compat_conf {
+ unsigned max_read;
+ int set_max_read;
+};
+
+static const struct fuse_opt fuse_ll_opts_compat[] = {
+ { "max_read=", offsetof(struct fuse_ll_compat_conf, set_max_read), 1 },
+ { "max_read=%u", offsetof(struct fuse_ll_compat_conf, max_read), 0 },
+ FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP),
+ FUSE_OPT_END
+};
+
+int fuse_sync_compat_args(struct fuse_args *args)
+{
+ struct fuse_ll_compat_conf conf;
+
+ if (fuse_opt_parse(args, &conf, fuse_ll_opts_compat, NULL) == -1)
+ return -1;
+
+ if (fuse_opt_insert_arg(args, 1, "-osync_read"))
+ return -1;
+
+ if (conf.set_max_read) {
+ char tmpbuf[64];
+
+ sprintf(tmpbuf, "-omax_readahead=%u", conf.max_read);
+ if (fuse_opt_insert_arg(args, 1, tmpbuf) == -1)
+ return -1;
+ }
+ return 0;
+}
+
+struct fuse_session *fuse_lowlevel_new_compat25(struct fuse_args *args,
+ const struct fuse_lowlevel_ops_compat25 *op,
+ size_t op_size, void *userdata)
+{
+ if (fuse_sync_compat_args(args) == -1)
+ return NULL;
+
+ return fuse_lowlevel_new(args, (const struct fuse_lowlevel_ops *) op,
+ op_size, userdata);
+}
+
+
+__asm__(".symver fuse_lowlevel_new_compat25,fuse_lowlevel_new@FUSE_2.5");
diff --git a/lib/fuse_opt.c b/lib/fuse_opt.c
index 2ac499c..582c6ad 100644
--- a/lib/fuse_opt.c
+++ b/lib/fuse_opt.c
@@ -62,6 +62,21 @@ int fuse_opt_add_arg(struct fuse_args *args, const char *arg)
return 0;
}
+int fuse_opt_insert_arg(struct fuse_args *args, int pos, const char *arg)
+{
+ assert(pos <= args->argc);
+ if (fuse_opt_add_arg(args, arg) == -1)
+ return -1;
+
+ if (pos != args->argc - 1) {
+ char *newarg = args->argv[args->argc - 1];
+ memmove(&args->argv[pos + 1], &args->argv[pos],
+ sizeof(char *) * (args->argc - pos - 1));
+ args->argv[pos] = newarg;
+ }
+ return 0;
+}
+
static int next_arg(struct fuse_opt_context *ctx, const char *opt)
{
if (ctx->argctr + 1 >= ctx->argc) {
@@ -102,25 +117,13 @@ static int add_opt(struct fuse_opt_context *ctx, const char *opt)
return fuse_opt_add_opt(&ctx->opts, opt);
}
-static int insert_arg(struct fuse_opt_context *ctx, int pos, const char *arg)
-{
- assert(pos <= ctx->outargs.argc);
- if (add_arg(ctx, arg) == -1)
- return -1;
-
- if (pos != ctx->outargs.argc - 1) {
- char *newarg = ctx->outargs.argv[ctx->outargs.argc - 1];
- memmove(&ctx->outargs.argv[pos + 1], &ctx->outargs.argv[pos],
- sizeof(char *) * (ctx->outargs.argc - pos - 1));
- ctx->outargs.argv[pos] = newarg;
- }
- return 0;
-}
-
static int call_proc(struct fuse_opt_context *ctx, const char *arg, int key,
int iso)
{
- if (ctx->proc) {
+ if (key == FUSE_OPT_KEY_DISCARD)
+ return 0;
+
+ if (key != FUSE_OPT_KEY_KEEP && ctx->proc) {
int res = ctx->proc(ctx->data, arg, key, &ctx->outargs);
if (res == -1 || !res)
return res;
@@ -155,8 +158,8 @@ static int match_template(const char *t, const char *arg, unsigned *sepp)
static const struct fuse_opt *find_opt(const struct fuse_opt *opt,
const char *arg, unsigned *sepp)
{
- for (; opt && opt->template; opt++)
- if (match_template(opt->template, arg, sepp))
+ for (; opt && opt->templ; opt++)
+ if (match_template(opt->templ, arg, sepp))
return opt;
return NULL;
}
@@ -195,11 +198,11 @@ static int process_opt(struct fuse_opt_context *ctx,
return -1;
} else {
void *var = ctx->data + opt->offset;
- if (sep && opt->template[sep + 1]) {
+ if (sep && opt->templ[sep + 1]) {
const char *param = arg + sep;
- if (opt->template[sep] == '=')
+ if (opt->templ[sep] == '=')
param ++;
- if (process_opt_param(var, opt->template + sep + 1,
+ if (process_opt_param(var, opt->templ + sep + 1,
param, arg) == -1)
return -1;
} else
@@ -239,7 +242,7 @@ static int process_gopt(struct fuse_opt_context *ctx, const char *arg, int iso)
if (opt) {
for (; opt; opt = find_opt(opt + 1, arg, &sep)) {
int res;
- if (sep && opt->template[sep] == ' ' && !arg[sep])
+ if (sep && opt->templ[sep] == ' ' && !arg[sep])
res = process_opt_sep_arg(ctx, opt, sep, arg, iso);
else
res = process_opt(ctx, opt, sep, arg, iso);
@@ -321,12 +324,14 @@ static int opt_parse(struct fuse_opt_context *ctx)
return -1;
if (ctx->opts) {
- if (insert_arg(ctx, 1, "-o") == -1 ||
- insert_arg(ctx, 2, ctx->opts) == -1)
+ if (fuse_opt_insert_arg(&ctx->outargs, 1, "-o") == -1 ||
+ fuse_opt_insert_arg(&ctx->outargs, 2, ctx->opts) == -1)
return -1;
}
- if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc)
+ if (ctx->nonopt && ctx->nonopt == ctx->outargs.argc) {
+ free(ctx->outargs.argv[ctx->outargs.argc - 1]);
ctx->outargs.argv[--ctx->outargs.argc] = NULL;
+ }
return 0;
}
diff --git a/lib/fuse_versionscript b/lib/fuse_versionscript
index 9927158..421228e 100644
--- a/lib/fuse_versionscript
+++ b/lib/fuse_versionscript
@@ -61,18 +61,16 @@ FUSE_2.4 {
FUSE_2.5 {
global:
- fuse_lowlevel_new;
fuse_lowlevel_new_compat;
- fuse_main_real;
fuse_main_real_compat22;
fuse_mount;
fuse_mount_compat22;
- fuse_new;
fuse_new_compat22;
fuse_opt_parse;
fuse_opt_add_opt;
fuse_opt_add_arg;
fuse_opt_free_args;
+ fuse_opt_insert_arg;
fuse_opt_match;
fuse_parse_cmdline;
fuse_remove_signal_handlers;
@@ -81,10 +79,26 @@ FUSE_2.5 {
fuse_reply_open_compat;
fuse_reply_statfs;
fuse_reply_statfs_compat;
- fuse_setup;
fuse_setup_compat22;
fuse_set_signal_handlers;
+} FUSE_2.4;
+
+FUSE_2.6 {
+ global:
+ fuse_opt_insert_arg;
+} FUSE_2.5;
+
+FUSE_2.7 {
+ global:
+ fuse_lowlevel_new;
+ fuse_lowlevel_new_compat25;
+ fuse_main_real;
+ fuse_main_real_compat25;
+ fuse_new;
+ fuse_new_compat25;
+ fuse_setup;
+ fuse_setup_compat25;
local:
*;
-} FUSE_2.4;
+} FUSE_2.6;
diff --git a/lib/helper.c b/lib/helper.c
index b7f77be..f937366 100644
--- a/lib/helper.c
+++ b/lib/helper.c
@@ -22,7 +22,6 @@ enum {
KEY_HELP,
KEY_HELP_NOHEADER,
KEY_VERSION,
- KEY_KEEP,
};
struct helper_opts {
@@ -46,8 +45,9 @@ static const struct fuse_opt fuse_helper_opts[] = {
FUSE_OPT_KEY("-ho", KEY_HELP_NOHEADER),
FUSE_OPT_KEY("-V", KEY_VERSION),
FUSE_OPT_KEY("--version", KEY_VERSION),
- FUSE_OPT_KEY("-d", KEY_KEEP),
- FUSE_OPT_KEY("debug", KEY_KEEP),
+ FUSE_OPT_KEY("-d", FUSE_OPT_KEY_KEEP),
+ FUSE_OPT_KEY("debug", FUSE_OPT_KEY_KEEP),
+ FUSE_OPT_KEY("fsname=", FUSE_OPT_KEY_KEEP),
FUSE_OPT_END
};
@@ -100,11 +100,12 @@ static int fuse_helper_opt_proc(void *data, const char *arg, int key,
case FUSE_OPT_KEY_NONOPT:
if (!hopts->mountpoint)
return fuse_opt_add_opt(&hopts->mountpoint, arg);
-
- /* fall through */
+ else {
+ fprintf(stderr, "fuse: invalid argument `%s'\n", arg);
+ return -1;
+ }
default:
- case KEY_KEEP:
return 1;
}
}
@@ -289,10 +290,10 @@ int fuse_main(void)
return -1;
}
-#ifndef __FreeBSD__
-
#include "fuse_compat.h"
+#ifndef __FreeBSD__
+
struct fuse *fuse_setup_compat22(int argc, char *argv[],
const struct fuse_operations_compat22 *op,
size_t op_size, char **mountpoint,
@@ -341,3 +342,24 @@ __asm__(".symver fuse_main_compat2,fuse_main@");
__asm__(".symver fuse_main_real_compat22,fuse_main_real@FUSE_2.2");
#endif /* __FreeBSD__ */
+
+
+struct fuse *fuse_setup_compat25(int argc, char *argv[],
+ const struct fuse_operations_compat25 *op,
+ size_t op_size, char **mountpoint,
+ int *multithreaded, int *fd)
+{
+ return fuse_setup_common(argc, argv, (struct fuse_operations *) op,
+ op_size, mountpoint, multithreaded, fd, 25);
+}
+
+int fuse_main_real_compat25(int argc, char *argv[],
+ const struct fuse_operations_compat25 *op,
+ size_t op_size)
+{
+ return fuse_main_common(argc, argv, (struct fuse_operations *) op, op_size,
+ 25);
+}
+
+__asm__(".symver fuse_setup_compat25,fuse_setup@FUSE_2.5");
+__asm__(".symver fuse_main_real_compat25,fuse_main_real@FUSE_2.5");
diff --git a/lib/mount.c b/lib/mount.c
index 219ee14..2840a54 100644
--- a/lib/mount.c
+++ b/lib/mount.c
@@ -48,6 +48,7 @@ static const struct fuse_opt fuse_mount_opts[] = {
FUSE_OPT_KEY("fsname=", KEY_KERN),
FUSE_OPT_KEY("large_read", KEY_KERN),
FUSE_OPT_KEY("max_read=", KEY_KERN),
+ FUSE_OPT_KEY("max_read=", FUSE_OPT_KEY_KEEP),
FUSE_OPT_KEY("-r", KEY_RO),
FUSE_OPT_KEY("ro", KEY_KERN),
FUSE_OPT_KEY("rw", KEY_KERN),