summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiklos Szeredi <miklos@szeredi.hu>2008-02-08 17:22:15 +0000
committerMiklos Szeredi <miklos@szeredi.hu>2008-02-08 17:22:15 +0000
commit30ece080006087a7e615cce3f7fc51b6d8a5d5bf (patch)
tree5d60a4679f82a1bb941356278d87abe2b9560d1b
parentb20d88bbbc6e5ae67f0c99595859fd653949a3aa (diff)
downloadfuse-30ece080006087a7e615cce3f7fc51b6d8a5d5bf.tar.gz
Support receiving file handle from kernel in GETATTR request; Allow operations with a NULL path argument, if the filesystem supports it
-rw-r--r--ChangeLog5
-rw-r--r--example/fusexmp_fh.c2
-rw-r--r--include/fuse.h14
-rw-r--r--include/fuse_common.h2
-rw-r--r--lib/fuse.c32
-rw-r--r--lib/fuse_lowlevel.c16
-rw-r--r--lib/modules/iconv.c22
-rw-r--r--lib/modules/subdir.c248
8 files changed, 206 insertions, 135 deletions
diff --git a/ChangeLog b/ChangeLog
index 5b45dcf..7149a07 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -6,6 +6,11 @@
* Update kernel interface to 7.9
+ * Support receiving file handle from kernel in GETATTR request
+
+ * Allow operations with a NULL path argument, if the filesystem
+ supports it
+
2008-02-03 Csaba Henk <csaba.henk@creo.hu>
* lib/mount_bsd.c:
diff --git a/example/fusexmp_fh.c b/example/fusexmp_fh.c
index 4949675..b86d3f6 100644
--- a/example/fusexmp_fh.c
+++ b/example/fusexmp_fh.c
@@ -484,6 +484,8 @@ static struct fuse_operations xmp_oper = {
.removexattr = xmp_removexattr,
#endif
.lock = xmp_lock,
+
+ .flag_nullpath_ok = 1,
};
int main(int argc, char *argv[])
diff --git a/include/fuse.h b/include/fuse.h
index b7708c7..384a7b4 100644
--- a/include/fuse.h
+++ b/include/fuse.h
@@ -423,6 +423,20 @@ struct fuse_operations {
* Introduced in version 2.6
*/
int (*bmap) (const char *, size_t blocksize, uint64_t *idx);
+
+ /**
+ * Flag indicating, that the filesystem can accept a NULL path
+ * as the first argument for the following operations:
+ *
+ * read, write, flush, release, fsync, readdir, releasedir,
+ * fsyncdir, ftruncate, fgetattr and lock
+ */
+ unsigned int flag_nullpath_ok : 1;
+
+ /**
+ * Reserved flags, don't set
+ */
+ unsigned int flag_reserved : 31;
};
/** Extra context that may be needed by some filesystems
diff --git a/include/fuse_common.h b/include/fuse_common.h
index 8d4ba2b..5f50d60 100644
--- a/include/fuse_common.h
+++ b/include/fuse_common.h
@@ -22,7 +22,7 @@
#define FUSE_MAJOR_VERSION 2
/** Minor version of FUSE library interface */
-#define FUSE_MINOR_VERSION 7
+#define FUSE_MINOR_VERSION 8
#define FUSE_MAKE_VERSION(maj, min) ((maj) * 10 + (min))
#define FUSE_VERSION FUSE_MAKE_VERSION(FUSE_MAJOR_VERSION, FUSE_MINOR_VERSION)
diff --git a/lib/fuse.c b/lib/fuse.c
index 7bcbe76..a15b5c2 100644
--- a/lib/fuse.c
+++ b/lib/fuse.c
@@ -90,6 +90,7 @@ struct fuse {
struct fuse_config conf;
int intr_installed;
struct fuse_fs *fs;
+ int nullpath_ok;
};
struct lock {
@@ -764,7 +765,7 @@ int fuse_fs_fgetattr(struct fuse_fs *fs, const char *path, struct stat *buf,
fuse_get_context()->private_data = fs->user_data;
if (fs->op.fgetattr)
return fs->op.fgetattr(path, buf, fi);
- else if (fs->op.getattr)
+ else if (path && fs->op.getattr)
return fs->op.getattr(path, buf);
else
return -ENOSYS;
@@ -992,7 +993,7 @@ int fuse_fs_ftruncate(struct fuse_fs *fs, const char *path, off_t size,
fuse_get_context()->private_data = fs->user_data;
if (fs->op.ftruncate)
return fs->op.ftruncate(path, size, fi);
- else if (fs->op.truncate)
+ else if (path && fs->op.truncate)
return fs->op.truncate(path, size);
else
return -ENOSYS;
@@ -1409,16 +1410,18 @@ static void fuse_lib_getattr(fuse_req_t req, fuse_ino_t ino,
char *path;
int err;
- (void) fi;
memset(&buf, 0, sizeof(buf));
err = -ENOENT;
pthread_rwlock_rdlock(&f->tree_lock);
path = get_path(f, ino);
- if (path != NULL) {
+ if (path != NULL || (fi && f->nullpath_ok)) {
struct fuse_intr_data d;
fuse_prepare_interrupt(f, req, &d);
- err = fuse_fs_getattr(f->fs, path, &buf);
+ if (fi)
+ err = fuse_fs_fgetattr(f->fs, path, &buf, fi);
+ else
+ err = fuse_fs_getattr(f->fs, path, &buf);
fuse_finish_interrupt(f, req, &d);
free(path);
}
@@ -1774,7 +1777,7 @@ static void fuse_do_release(struct fuse *f, fuse_ino_t ino, const char *path,
struct node *node;
int unlink_hidden = 0;
- fuse_fs_release(f->fs, path ? path : "-", fi);
+ fuse_fs_release(f->fs, (path || f->nullpath_ok) ? path : "-", fi);
pthread_mutex_lock(&f->lock);
node = get_node(f, ino);
@@ -1950,7 +1953,7 @@ static void fuse_lib_read(fuse_req_t req, fuse_ino_t ino, size_t size,
res = -ENOENT;
pthread_rwlock_rdlock(&f->tree_lock);
path = get_path(f, ino);
- if (path != NULL) {
+ if (path != NULL || f->nullpath_ok) {
struct fuse_intr_data d;
if (f->conf.debug)
fprintf(stderr, "READ[%llu] %lu bytes from %llu\n",
@@ -1987,7 +1990,7 @@ static void fuse_lib_write(fuse_req_t req, fuse_ino_t ino, const char *buf,
res = -ENOENT;
pthread_rwlock_rdlock(&f->tree_lock);
path = get_path(f, ino);
- if (path != NULL) {
+ if (path != NULL || f->nullpath_ok) {
struct fuse_intr_data d;
if (f->conf.debug)
fprintf(stderr, "WRITE%s[%llu] %lu bytes to %llu\n",
@@ -2024,7 +2027,7 @@ static void fuse_lib_fsync(fuse_req_t req, fuse_ino_t ino, int datasync,
err = -ENOENT;
pthread_rwlock_rdlock(&f->tree_lock);
path = get_path(f, ino);
- if (path != NULL) {
+ if (path != NULL || f->nullpath_ok) {
struct fuse_intr_data d;
if (f->conf.debug)
fprintf(stderr, "FSYNC[%llu]\n",
@@ -2251,7 +2254,7 @@ static void fuse_lib_releasedir(fuse_req_t req, fuse_ino_t ino,
pthread_rwlock_rdlock(&f->tree_lock);
path = get_path(f, ino);
fuse_prepare_interrupt(f, req, &d);
- fuse_fs_releasedir(f->fs, path ? path : "-", &fi);
+ fuse_fs_releasedir(f->fs, (path || f->nullpath_ok) ? path : "-", &fi);
fuse_finish_interrupt(f, req, &d);
if (path)
free(path);
@@ -2644,7 +2647,7 @@ static void fuse_lib_flush(fuse_req_t req, fuse_ino_t ino,
pthread_rwlock_rdlock(&f->tree_lock);
path = get_path(f, ino);
- if (path && f->conf.debug)
+ if (f->conf.debug)
fprintf(stderr, "FLUSH[%llu]\n", (unsigned long long) fi->fh);
err = fuse_flush_common(f, req, ino, path, fi);
free(path);
@@ -2663,7 +2666,7 @@ static int fuse_lock_common(fuse_req_t req, fuse_ino_t ino,
err = -ENOENT;
pthread_rwlock_rdlock(&f->tree_lock);
path = get_path(f, ino);
- if (path != NULL) {
+ if (path != NULL || f->nullpath_ok) {
struct fuse_intr_data d;
fuse_prepare_interrupt(f, req, &d);
err = fuse_fs_lock(f->fs, path, fi, cmd, lock);
@@ -3023,6 +3026,7 @@ static int fuse_push_module(struct fuse *f, const char *module,
}
newfs->m = m;
f->fs = newfs;
+ f->nullpath_ok = newfs->op.flag_nullpath_ok && f->nullpath_ok;
return 0;
}
@@ -3072,6 +3076,7 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
fs->compat = compat;
f->fs = fs;
+ f->nullpath_ok = fs->op.flag_nullpath_ok;
/* Oh f**k, this is ugly! */
if (!fs->op.lock) {
@@ -3103,6 +3108,9 @@ struct fuse *fuse_new_common(struct fuse_chan *ch, struct fuse_args *args,
}
}
+ if (f->conf.debug)
+ fprintf(stderr, "nullpath_ok: %i\n", f->nullpath_ok);
+
if (!f->conf.ac_attr_timeout_set)
f->conf.ac_attr_timeout = f->conf.attr_timeout;
diff --git a/lib/fuse_lowlevel.c b/lib/fuse_lowlevel.c
index ed885fd..d1ef7b2 100644
--- a/lib/fuse_lowlevel.c
+++ b/lib/fuse_lowlevel.c
@@ -458,10 +458,22 @@ static void do_forget(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
static void do_getattr(fuse_req_t req, fuse_ino_t nodeid, const void *inarg)
{
- (void) inarg;
+ struct fuse_file_info *fip = NULL;
+ struct fuse_file_info fi;
+
+ if (req->f->conn.proto_minor >= 9) {
+ struct fuse_getattr_in *arg = (struct fuse_getattr_in *) inarg;
+
+ if (arg->getattr_flags & FUSE_GETATTR_FH) {
+ memset(&fi, 0, sizeof(fi));
+ fi.fh = arg->fh;
+ fi.fh_old = fi.fh;
+ fip = &fi;
+ }
+ }
if (req->f->op.getattr)
- req->f->op.getattr(req, nodeid, NULL);
+ req->f->op.getattr(req, nodeid, fip);
else
fuse_reply_err(req, ENOSYS);
}
diff --git a/lib/modules/iconv.c b/lib/modules/iconv.c
index c0e2b80..409cb66 100644
--- a/lib/modules/iconv.c
+++ b/lib/modules/iconv.c
@@ -42,17 +42,27 @@ static struct iconv *iconv_get(void)
static int iconv_convpath(struct iconv *ic, const char *path, char **newpathp,
int fromfs)
{
- size_t pathlen = strlen(path);
- size_t newpathlen = pathlen * 4;
- char *newpath = malloc(newpathlen + 1);
- size_t plen = newpathlen;
- char *p = newpath;
+ size_t pathlen;
+ size_t newpathlen;
+ char *newpath;
+ size_t plen;
+ char *p;
size_t res;
int err;
+ if (path == NULL) {
+ *newpathp = NULL;
+ return 0;
+ }
+
+ pathlen = strlen(path);
+ newpathlen = pathlen * 4;
+ newpath = malloc(newpathlen + 1);
if (!newpath)
return -ENOMEM;
+ plen = newpathlen;
+ p = newpath;
pthread_mutex_lock(&ic->lock);
do {
res = iconv(fromfs ? ic->fromfs : ic->tofs, (char **) &path,
@@ -607,6 +617,8 @@ static struct fuse_operations iconv_oper = {
.removexattr = iconv_removexattr,
.lock = iconv_lock,
.bmap = iconv_bmap,
+
+ .flag_nullpath_ok = 1,
};
static struct fuse_opt iconv_opts[] = {
diff --git a/lib/modules/subdir.c b/lib/modules/subdir.c
index 6f7b187..3188d1f 100644
--- a/lib/modules/subdir.c
+++ b/lib/modules/subdir.c
@@ -27,11 +27,17 @@ static struct subdir *subdir_get(void)
return fuse_get_context()->private_data;
}
-static char *subdir_addpath(struct subdir *d, const char *path)
+static int subdir_addpath(struct subdir *d, const char *path, char **newpathp)
{
- unsigned newlen = d->baselen + strlen(path);
- char *newpath = malloc(newlen + 2);
- if (newpath) {
+ char *newpath = NULL;
+
+ if (path != NULL) {
+ unsigned newlen = d->baselen + strlen(path);
+
+ newpath = malloc(newlen + 2);
+ if (!newpath)
+ return -ENOMEM;
+
if (path[0] == '/')
path++;
strcpy(newpath, d->base);
@@ -39,15 +45,17 @@ static char *subdir_addpath(struct subdir *d, const char *path)
if (!newpath[0])
strcpy(newpath, ".");
}
- return newpath;
+ *newpathp = newpath;
+
+ return 0;
}
static int subdir_getattr(const char *path, struct stat *stbuf)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_getattr(d->next, newpath, stbuf);
free(newpath);
}
@@ -58,9 +66,9 @@ static int subdir_fgetattr(const char *path, struct stat *stbuf,
struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_fgetattr(d->next, newpath, stbuf, fi);
free(newpath);
}
@@ -70,9 +78,9 @@ static int subdir_fgetattr(const char *path, struct stat *stbuf,
static int subdir_access(const char *path, int mask)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_access(d->next, newpath, mask);
free(newpath);
}
@@ -146,9 +154,9 @@ static void transform_symlink(struct subdir *d, const char *path,
static int subdir_readlink(const char *path, char *buf, size_t size)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_readlink(d->next, newpath, buf, size);
if (!err && d->rellinks)
transform_symlink(d, newpath, buf, size);
@@ -160,9 +168,9 @@ static int subdir_readlink(const char *path, char *buf, size_t size)
static int subdir_opendir(const char *path, struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_opendir(d->next, newpath, fi);
free(newpath);
}
@@ -174,9 +182,9 @@ static int subdir_readdir(const char *path, void *buf,
struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_readdir(d->next, newpath, buf, filler, offset,
fi);
free(newpath);
@@ -187,9 +195,9 @@ static int subdir_readdir(const char *path, void *buf,
static int subdir_releasedir(const char *path, struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_releasedir(d->next, newpath, fi);
free(newpath);
}
@@ -199,9 +207,9 @@ static int subdir_releasedir(const char *path, struct fuse_file_info *fi)
static int subdir_mknod(const char *path, mode_t mode, dev_t rdev)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_mknod(d->next, newpath, mode, rdev);
free(newpath);
}
@@ -211,9 +219,9 @@ static int subdir_mknod(const char *path, mode_t mode, dev_t rdev)
static int subdir_mkdir(const char *path, mode_t mode)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_mkdir(d->next, newpath, mode);
free(newpath);
}
@@ -223,9 +231,9 @@ static int subdir_mkdir(const char *path, mode_t mode)
static int subdir_unlink(const char *path)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_unlink(d->next, newpath);
free(newpath);
}
@@ -235,9 +243,9 @@ static int subdir_unlink(const char *path)
static int subdir_rmdir(const char *path)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_rmdir(d->next, newpath);
free(newpath);
}
@@ -247,9 +255,9 @@ static int subdir_rmdir(const char *path)
static int subdir_symlink(const char *from, const char *path)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_symlink(d->next, from, newpath);
free(newpath);
}
@@ -259,35 +267,43 @@ static int subdir_symlink(const char *from, const char *path)
static int subdir_rename(const char *from, const char *to)
{
struct subdir *d = subdir_get();
- char *newfrom = subdir_addpath(d, from);
- char *newto = subdir_addpath(d, to);
- int err = -ENOMEM;
- if (newfrom && newto)
- err = fuse_fs_rename(d->next, newfrom, newto);
- free(newfrom);
- free(newto);
+ char *newfrom;
+ char *newto;
+ int err = subdir_addpath(d, from, &newfrom);
+ if (!err) {
+ err = subdir_addpath(d, to, &newto);
+ if (!err) {
+ err = fuse_fs_rename(d->next, newfrom, newto);
+ free(newto);
+ }
+ free(newfrom);
+ }
return err;
}
static int subdir_link(const char *from, const char *to)
{
struct subdir *d = subdir_get();
- char *newfrom = subdir_addpath(d, from);
- char *newto = subdir_addpath(d, to);
- int err = -ENOMEM;
- if (newfrom && newto)
- err = fuse_fs_link(d->next, newfrom, newto);
- free(newfrom);
- free(newto);
+ char *newfrom;
+ char *newto;
+ int err = subdir_addpath(d, from, &newfrom);
+ if (!err) {
+ err = subdir_addpath(d, to, &newto);
+ if (!err) {
+ err = fuse_fs_link(d->next, newfrom, newto);
+ free(newto);
+ }
+ free(newfrom);
+ }
return err;
}
static int subdir_chmod(const char *path, mode_t mode)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_chmod(d->next, newpath, mode);
free(newpath);
}
@@ -297,9 +313,9 @@ static int subdir_chmod(const char *path, mode_t mode)
static int subdir_chown(const char *path, uid_t uid, gid_t gid)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_chown(d->next, newpath, uid, gid);
free(newpath);
}
@@ -309,9 +325,9 @@ static int subdir_chown(const char *path, uid_t uid, gid_t gid)
static int subdir_truncate(const char *path, off_t size)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_truncate(d->next, newpath, size);
free(newpath);
}
@@ -322,9 +338,9 @@ static int subdir_ftruncate(const char *path, off_t size,
struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_ftruncate(d->next, newpath, size, fi);
free(newpath);
}
@@ -334,9 +350,9 @@ static int subdir_ftruncate(const char *path, off_t size,
static int subdir_utimens(const char *path, const struct timespec ts[2])
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_utimens(d->next, newpath, ts);
free(newpath);
}
@@ -347,9 +363,9 @@ static int subdir_create(const char *path, mode_t mode,
struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_create(d->next, newpath, mode, fi);
free(newpath);
}
@@ -359,9 +375,9 @@ static int subdir_create(const char *path, mode_t mode,
static int subdir_open(const char *path, struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_open(d->next, newpath, fi);
free(newpath);
}
@@ -372,9 +388,9 @@ static int subdir_read(const char *path, char *buf, size_t size, off_t offset,
struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_read(d->next, newpath, buf, size, offset, fi);
free(newpath);
}
@@ -385,9 +401,9 @@ static int subdir_write(const char *path, const char *buf, size_t size,
off_t offset, struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_write(d->next, newpath, buf, size, offset, fi);
free(newpath);
}
@@ -397,9 +413,9 @@ static int subdir_write(const char *path, const char *buf, size_t size,
static int subdir_statfs(const char *path, struct statvfs *stbuf)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_statfs(d->next, newpath, stbuf);
free(newpath);
}
@@ -409,9 +425,9 @@ static int subdir_statfs(const char *path, struct statvfs *stbuf)
static int subdir_flush(const char *path, struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_flush(d->next, newpath, fi);
free(newpath);
}
@@ -421,9 +437,9 @@ static int subdir_flush(const char *path, struct fuse_file_info *fi)
static int subdir_release(const char *path, struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_release(d->next, newpath, fi);
free(newpath);
}
@@ -434,9 +450,9 @@ static int subdir_fsync(const char *path, int isdatasync,
struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_fsync(d->next, newpath, isdatasync, fi);
free(newpath);
}
@@ -447,9 +463,9 @@ static int subdir_fsyncdir(const char *path, int isdatasync,
struct fuse_file_info *fi)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_fsyncdir(d->next, newpath, isdatasync, fi);
free(newpath);
}
@@ -460,9 +476,9 @@ static int subdir_setxattr(const char *path, const char *name,
const char *value, size_t size, int flags)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_setxattr(d->next, newpath, name, value, size,
flags);
free(newpath);
@@ -474,9 +490,9 @@ static int subdir_getxattr(const char *path, const char *name, char *value,
size_t size)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_getxattr(d->next, newpath, name, value, size);
free(newpath);
}
@@ -486,9 +502,9 @@ static int subdir_getxattr(const char *path, const char *name, char *value,
static int subdir_listxattr(const char *path, char *list, size_t size)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_listxattr(d->next, newpath, list, size);
free(newpath);
}
@@ -498,9 +514,9 @@ static int subdir_listxattr(const char *path, char *list, size_t size)
static int subdir_removexattr(const char *path, const char *name)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_removexattr(d->next, newpath, name);
free(newpath);
}
@@ -511,9 +527,9 @@ static int subdir_lock(const char *path, struct fuse_file_info *fi, int cmd,
struct flock *lock)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_lock(d->next, newpath, fi, cmd, lock);
free(newpath);
}
@@ -523,9 +539,9 @@ static int subdir_lock(const char *path, struct fuse_file_info *fi, int cmd,
static int subdir_bmap(const char *path, size_t blocksize, uint64_t *idx)
{
struct subdir *d = subdir_get();
- char *newpath = subdir_addpath(d, path);
- int err = -ENOMEM;
- if (newpath) {
+ char *newpath;
+ int err = subdir_addpath(d, path, &newpath);
+ if (!err) {
err = fuse_fs_bmap(d->next, newpath, blocksize, idx);
free(newpath);
}
@@ -584,6 +600,8 @@ static struct fuse_operations subdir_oper = {
.removexattr = subdir_removexattr,
.lock = subdir_lock,
.bmap = subdir_bmap,
+
+ .flag_nullpath_ok = 1,
};
static struct fuse_opt subdir_opts[] = {