struct fuse_config conf;
int intr_installed;
struct fuse_fs *fs;
+ int nullpath_ok;
};
struct lock {
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;
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;
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);
}
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);
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",
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",
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",
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);
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);
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);
}
newfs->m = m;
f->fs = newfs;
+ f->nullpath_ok = newfs->op.flag_nullpath_ok && f->nullpath_ok;
return 0;
}
fs->compat = compat;
f->fs = fs;
+ f->nullpath_ok = fs->op.flag_nullpath_ok;
/* Oh f**k, this is ugly! */
if (!fs->op.lock) {
}
}
+ 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;
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);
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);
}
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);
}
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);
}
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);
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);
}
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);
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
}
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);
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);
}
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);
}
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);
}
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);
}
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);
}
.removexattr = subdir_removexattr,
.lock = subdir_lock,
.bmap = subdir_bmap,
+
+ .flag_nullpath_ok = 1,
};
static struct fuse_opt subdir_opts[] = {