From 30ece080006087a7e615cce3f7fc51b6d8a5d5bf Mon Sep 17 00:00:00 2001 From: Miklos Szeredi Date: Fri, 8 Feb 2008 17:22:15 +0000 Subject: [PATCH] Support receiving file handle from kernel in GETATTR request; Allow operations with a NULL path argument, if the filesystem supports it --- ChangeLog | 5 + example/fusexmp_fh.c | 2 + include/fuse.h | 14 +++ include/fuse_common.h | 2 +- lib/fuse.c | 32 ++++-- lib/fuse_lowlevel.c | 16 ++- lib/modules/iconv.c | 22 +++- lib/modules/subdir.c | 248 ++++++++++++++++++++++-------------------- 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 * 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[] = { -- 2.30.2