aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/fuse.c16
-rw-r--r--lib/fuse_lowlevel.c41
2 files changed, 38 insertions, 19 deletions
diff --git a/lib/fuse.c b/lib/fuse.c
index 976a26c..ee95664 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -80,6 +80,7 @@ struct fuse {
unsigned int gid;
unsigned int umask;
double entry_timeout;
+ double negative_timeout;
double attr_timeout;
};
@@ -611,8 +612,14 @@ static void fuse_lookup(fuse_req_t req, fuse_ino_t parent, const char *name)
fflush(stdout);
}
err = -ENOSYS;
- if (f->op.getattr)
+ if (f->op.getattr) {
err = lookup_path(f, parent, name, path, &e, NULL);
+ if (err == -ENOENT && f->negative_timeout != 0.0) {
+ e.ino = 0;
+ e.entry_timeout = f->negative_timeout;
+ err = 0;
+ }
+ }
free(path);
}
pthread_rwlock_unlock(&f->tree_lock);
@@ -1835,7 +1842,8 @@ int fuse_is_lib_option(const char *opt)
begins_with(opt, "uid=") ||
begins_with(opt, "gid=") ||
begins_with(opt, "entry_timeout=") ||
- begins_with(opt, "attr_timeout="))
+ begins_with(opt, "attr_timeout=") ||
+ begins_with(opt, "negative_timeout="))
return 1;
else
return 0;
@@ -1882,6 +1890,9 @@ static int parse_lib_opts(struct fuse *f, const char *opts, char **llopts)
/* nop */;
else if (sscanf(opt, "attr_timeout=%lf", &f->attr_timeout) == 1)
/* nop */;
+ else if (sscanf(opt, "negative_timeout=%lf",
+ &f->negative_timeout) == 1)
+ /* nop */;
else
fprintf(stderr, "fuse: warning: unknown option `%s'\n", opt);
}
@@ -1924,6 +1935,7 @@ struct fuse *fuse_new_common(int fd, const char *opts,
f->entry_timeout = 1.0;
f->attr_timeout = 1.0;
+ f->negative_timeout = 0.0;
if (parse_lib_opts(f, opts, &llopts) == -1)
goto out_free;
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index 4e5c2ac..3cc49f0 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -188,6 +188,7 @@ static void convert_statfs(const struct statvfs *stbuf,
struct fuse_kstatfs *kstatfs)
{
kstatfs->bsize = stbuf->f_bsize;
+ kstatfs->frsize = stbuf->f_frsize;
kstatfs->blocks = stbuf->f_blocks;
kstatfs->bfree = stbuf->f_bfree;
kstatfs->bavail = stbuf->f_bavail;
@@ -258,6 +259,11 @@ int fuse_reply_entry(fuse_req_t req, const struct fuse_entry_param *e)
{
struct fuse_entry_out arg;
+ /* before ABI 7.4 e->ino == 0 was invalid, only ENOENT meant
+ negative entry */
+ if (!e->ino && req->f->minor < 4)
+ return fuse_reply_err(req, ENOENT);
+
memset(&arg, 0, sizeof(arg));
fill_entry(&arg, e);
return send_reply_ok(req, &arg, sizeof(arg));
@@ -322,11 +328,12 @@ 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);
memset(&arg, 0, sizeof(arg));
convert_statfs(stbuf, &arg.st);
- return send_reply_ok(req, &arg, sizeof(arg));
+ return send_reply_ok(req, &arg, size);
}
int fuse_reply_xattr(fuse_req_t req, size_t count)
@@ -690,11 +697,11 @@ static void do_init(fuse_req_t req, struct fuse_init_in_out *arg)
f->op.init(f->userdata);
f->major = FUSE_KERNEL_VERSION;
- f->minor = FUSE_KERNEL_MINOR_VERSION;
+ f->minor = arg->minor;
memset(&outarg, 0, sizeof(outarg));
outarg.major = f->major;
- outarg.minor = f->minor;
+ outarg.minor = FUSE_KERNEL_MINOR_VERSION;
if (f->debug) {
printf(" INIT: %u.%u\n", outarg.major, outarg.minor);
@@ -976,16 +983,16 @@ static void fill_open_compat(struct fuse_open_out *arg,
arg->open_flags |= FOPEN_KEEP_CACHE;
}
-static void convert_statfs_compat(const struct statfs *stbuf,
- struct fuse_kstatfs *kstatfs)
+static void convert_statfs_compat(const struct statfs *compatbuf,
+ struct statvfs *buf)
{
- kstatfs->bsize = stbuf->f_bsize;
- kstatfs->blocks = stbuf->f_blocks;
- kstatfs->bfree = stbuf->f_bfree;
- kstatfs->bavail = stbuf->f_bavail;
- kstatfs->files = stbuf->f_files;
- kstatfs->ffree = stbuf->f_ffree;
- kstatfs->namelen = stbuf->f_namelen;
+ buf->f_bsize = compatbuf->f_bsize;
+ buf->f_blocks = compatbuf->f_blocks;
+ buf->f_bfree = compatbuf->f_bfree;
+ buf->f_bavail = compatbuf->f_bavail;
+ buf->f_files = compatbuf->f_files;
+ buf->f_ffree = compatbuf->f_ffree;
+ buf->f_namemax = compatbuf->f_namelen;
}
int fuse_reply_open_compat(fuse_req_t req,
@@ -1000,16 +1007,16 @@ int fuse_reply_open_compat(fuse_req_t req,
int fuse_reply_statfs_compat(fuse_req_t req, const struct statfs *stbuf)
{
- struct fuse_statfs_out arg;
+ struct statvfs newbuf;
- memset(&arg, 0, sizeof(arg));
- convert_statfs_compat(stbuf, &arg.st);
+ memset(&newbuf, 0, sizeof(newbuf));
+ convert_statfs_compat(stbuf, &newbuf);
- return send_reply_ok(req, &arg, sizeof(arg));
+ return fuse_reply_statfs(req, &newbuf);
}
__asm__(".symver fuse_reply_statfs_compat,fuse_reply_statfs@FUSE_2.4");
__asm__(".symver fuse_reply_open_compat,fuse_reply_open@FUSE_2.4");
-#endif __FreeBSD__
+#endif /* __FreeBSD__ */