From 0c17492c786a4d65e7e04ffd270b62f93d1f6ec2 Mon Sep 17 00:00:00 2001 From: "Antonio S. Musumeci" Date: Sat, 18 Apr 2026 00:56:15 -0400 Subject: [PATCH] FUSE: pass Branches::Ptr by value with empty-branches guards Previously most FUSE ops took a reference to the live cfg.branches object. With atomic_load now producing a shared_ptr snapshot, pass it by value: the op works against a single stable view of the configuration for its whole lifetime, immune to concurrent reconfiguration. Also bail out with -ENOENT when the policy returns an empty branch set rather than dereferencing branches[0]. This was reachable if a policy rejected every branch (e.g. everything readonly while looking for a writable target). Covers access, chmod, chown, create, getattr, getxattr, ioctl, link, listxattr, mkdir, mknod, open, readdir (cor/cosr), readlink, removexattr, rename, rmdir, setxattr, statfs, statx, symlink, truncate, unlink, utimens. While here, in _getattr only dereference st_->st_mode when lstat succeeded (it is otherwise uninitialized). --- src/fuse_access.cpp | 4 +++- src/fuse_chmod.cpp | 6 +++++- src/fuse_chown.cpp | 6 +++++- src/fuse_create.cpp | 6 +++++- src/fuse_getattr.cpp | 8 +++++--- src/fuse_getxattr.cpp | 8 +++++--- src/fuse_ioctl.cpp | 5 ++++- src/fuse_link.cpp | 16 ++++++++++++---- src/fuse_listxattr.cpp | 2 +- src/fuse_mkdir.cpp | 6 +++++- src/fuse_mknod.cpp | 6 +++++- src/fuse_open.cpp | 14 ++++++++------ src/fuse_readdir_cor.cpp | 2 +- src/fuse_readdir_cosr.cpp | 2 +- src/fuse_readlink.cpp | 2 +- src/fuse_removexattr.cpp | 6 +++++- src/fuse_rename.cpp | 20 ++++++++++++-------- src/fuse_rmdir.cpp | 2 +- src/fuse_setxattr.cpp | 6 +++++- src/fuse_statfs.cpp | 4 ++-- src/fuse_statx_supported.icpp | 4 +++- src/fuse_symlink.cpp | 6 +++++- src/fuse_truncate.cpp | 6 +++++- src/fuse_unlink.cpp | 2 +- src/fuse_utimens.cpp | 6 +++++- 25 files changed, 110 insertions(+), 45 deletions(-) diff --git a/src/fuse_access.cpp b/src/fuse_access.cpp index a98fc8bc..23e1e28c 100644 --- a/src/fuse_access.cpp +++ b/src/fuse_access.cpp @@ -30,7 +30,7 @@ static int _access(const Policy::Search &searchFunc_, - const Branches &branches_, + const Branches::Ptr branches_, const fs::path &fusepath_, const int mask_) { @@ -42,6 +42,8 @@ _access(const Policy::Search &searchFunc_, rv = searchFunc_(branches_,fusepath_,branches); if(rv < 0) return rv; + if(branches.empty()) + return -ENOENT; fullpath = branches[0]->path / fusepath_; diff --git a/src/fuse_chmod.cpp b/src/fuse_chmod.cpp index 1c2857d7..22362c8e 100644 --- a/src/fuse_chmod.cpp +++ b/src/fuse_chmod.cpp @@ -64,7 +64,7 @@ static int _chmod(const Policy::Action &actionFunc_, const Policy::Search &searchFunc_, - const Branches &branches_, + const Branches::Ptr branches_, const fs::path &fusepath_, const mode_t mode_) { @@ -75,6 +75,8 @@ _chmod(const Policy::Action &actionFunc_, rv = actionFunc_(branches_,fusepath_,branches); if(rv < 0) return rv; + if(branches.empty()) + return -ENOENT; ::_chmod_loop(branches,fusepath_,mode_,&prv); if(prv.errors.empty()) @@ -86,6 +88,8 @@ _chmod(const Policy::Action &actionFunc_, rv = searchFunc_(branches_,fusepath_,branches); if(rv < 0) return rv; + if(branches.empty()) + return -ENOENT; return prv.get_error(branches[0]->path); } diff --git a/src/fuse_chown.cpp b/src/fuse_chown.cpp index b51c4c99..466f525d 100644 --- a/src/fuse_chown.cpp +++ b/src/fuse_chown.cpp @@ -66,7 +66,7 @@ static int _chown(const Policy::Action &actionFunc_, const Policy::Search &searchFunc_, - const Branches &branches_, + const Branches::Ptr branches_, const fs::path &fusepath_, const uid_t uid_, const gid_t gid_) @@ -78,6 +78,8 @@ _chown(const Policy::Action &actionFunc_, rv = actionFunc_(branches_,fusepath_,branches); if(rv < 0) return rv; + if(branches.empty()) + return -ENOENT; ::_chown_loop(branches,fusepath_,uid_,gid_,&prv); @@ -90,6 +92,8 @@ _chown(const Policy::Action &actionFunc_, rv = searchFunc_(branches_,fusepath_,branches); if(rv < 0) return rv; + if(branches.empty()) + return -ENOENT; return prv.get_error(branches[0]->path); } diff --git a/src/fuse_create.cpp b/src/fuse_create.cpp index 40cd0ea8..49f61b7b 100644 --- a/src/fuse_create.cpp +++ b/src/fuse_create.cpp @@ -207,7 +207,7 @@ int _create(const ugid_t ugid_, const Policy::Search &searchFunc_, const Policy::Create &createFunc_, - const Branches &branches_, + const Branches::Ptr branches_, const fs::path &fusepath_, fuse_file_info_t *ffi_, const mode_t mode_, @@ -224,10 +224,14 @@ _create(const ugid_t ugid_, rv = searchFunc_(branches_,fusedirpath,existingpaths); if(rv < 0) return rv; + if(existingpaths.empty()) + return -ENOENT; rv = createFunc_(branches_,fusedirpath,createpaths); if(rv < 0) return rv; + if(createpaths.empty()) + return -ENOENT; rv = fs::clonepath(existingpaths[0]->path, createpaths[0]->path, diff --git a/src/fuse_getattr.cpp b/src/fuse_getattr.cpp index 3bebb35e..dc3c932b 100644 --- a/src/fuse_getattr.cpp +++ b/src/fuse_getattr.cpp @@ -120,7 +120,7 @@ _getattr_controlfile(struct stat *st_) static int _getattr(const Policy::Search &searchFunc_, - const Branches &branches_, + const Branches::Ptr branches_, const fs::path &fusepath_, struct stat *st_, const bool symlinkify_, @@ -134,6 +134,8 @@ _getattr(const Policy::Search &searchFunc_, rv = searchFunc_(branches_,fusepath_,branches); if(rv < 0) return rv; + if(branches.empty()) + return -ENOENT; fullpath = branches[0]->path / fusepath_; @@ -144,12 +146,12 @@ _getattr(const Policy::Search &searchFunc_, break; case FollowSymlinks::ENUM::DIRECTORY: rv = fs::lstat(fullpath,st_); - if(S_ISLNK(st_->st_mode)) + if((rv >= 0) && S_ISLNK(st_->st_mode)) ::_set_stat_if_leads_to_dir(fullpath,st_); break; case FollowSymlinks::ENUM::REGULAR: rv = fs::lstat(fullpath,st_); - if(S_ISLNK(st_->st_mode)) + if((rv >= 0) && S_ISLNK(st_->st_mode)) ::_set_stat_if_leads_to_reg(fullpath,st_); break; case FollowSymlinks::ENUM::ALL: diff --git a/src/fuse_getxattr.cpp b/src/fuse_getxattr.cpp index 55d5b43c..2a7a8a87 100644 --- a/src/fuse_getxattr.cpp +++ b/src/fuse_getxattr.cpp @@ -97,7 +97,7 @@ _getxattr_from_string(char *destbuf_, static int -_getxattr_user_mergerfs_allpaths(const Branches::Ptr &branches_, +_getxattr_user_mergerfs_allpaths(const Branches::Ptr branches_, const fs::path &fusepath_, char *buf_, const size_t count_) @@ -120,7 +120,7 @@ int _getxattr_user_mergerfs(const fs::path &basepath_, const fs::path &fusepath_, const fs::path &fullpath_, - const Branches &branches_, + const Branches::Ptr branches_, const char *attrname_, char *buf_, const size_t count_) @@ -144,7 +144,7 @@ _getxattr_user_mergerfs(const fs::path &basepath_, static int _getxattr(const Policy::Search &searchFunc_, - const Branches &branches_, + const Branches::Ptr branches_, const fs::path &fusepath_, const char *attrname_, char *buf_, @@ -157,6 +157,8 @@ _getxattr(const Policy::Search &searchFunc_, rv = searchFunc_(branches_,fusepath_,branches); if(rv < 0) return rv; + if(branches.empty()) + return -ENOENT; fullpath = branches[0]->path / fusepath_; diff --git a/src/fuse_ioctl.cpp b/src/fuse_ioctl.cpp index cdf1dbbf..eecf5ac2 100644 --- a/src/fuse_ioctl.cpp +++ b/src/fuse_ioctl.cpp @@ -32,6 +32,7 @@ #include "fs_open.hpp" #include "fs_path.hpp" #include "mergerfs_ioctl.hpp" +#include "state.hpp" #include "str.hpp" #include @@ -128,7 +129,7 @@ _ioctl_file(const fuse_req_ctx_t *ctx_, static int _ioctl_dir_base(const Policy::Search &searchFunc_, - const Branches &branches_, + const Branches::Ptr branches_, const fs::path &fusepath_, const u32 cmd_, void *data_, @@ -142,6 +143,8 @@ _ioctl_dir_base(const Policy::Search &searchFunc_, rv = searchFunc_(branches_,fusepath_,branches); if(rv < 0) return rv; + if(branches.empty()) + return -ENOENT; fullpath = branches[0]->path / fusepath_; diff --git a/src/fuse_link.cpp b/src/fuse_link.cpp index 7cabdf78..b9b5c3da 100644 --- a/src/fuse_link.cpp +++ b/src/fuse_link.cpp @@ -74,7 +74,7 @@ static int _link_create_path(const Policy::Search &searchFunc_, const Policy::Action &actionFunc_, - const Branches &ibranches_, + const Branches::Ptr ibranches_, const fs::path &oldfusepath_, const fs::path &newfusepath_) { @@ -86,12 +86,16 @@ _link_create_path(const Policy::Search &searchFunc_, rv = actionFunc_(ibranches_,oldfusepath_,oldbranches); if(rv < 0) return rv; + if(oldbranches.empty()) + return -ENOENT; newfusedirpath = newfusepath_.parent_path(); rv = searchFunc_(ibranches_,newfusedirpath,newbranches); if(rv < 0) return rv; + if(newbranches.empty()) + return -ENOENT; return ::_link_create_path_loop(oldbranches,newbranches[0], oldfusepath_,newfusepath_, @@ -148,7 +152,7 @@ _link_preserve_path_loop(const std::vector &oldbranches_, static int _link_preserve_path(const Policy::Action &actionFunc_, - const Branches &branches_, + const Branches::Ptr branches_, const fs::path &oldfusepath_, const fs::path &newfusepath_, struct stat *st_) @@ -159,6 +163,8 @@ _link_preserve_path(const Policy::Action &actionFunc_, rv = actionFunc_(branches_,oldfusepath_,oldbranches); if(rv < 0) return rv; + if(oldbranches.empty()) + return -ENOENT; return ::_link_preserve_path_loop(oldbranches, oldfusepath_, @@ -231,8 +237,8 @@ _link_exdev_rel_symlink(const fuse_req_ctx_t *ctx_, static int _link_exdev_abs_base_symlink(const fuse_req_ctx_t *ctx_, - const Policy::Search &openPolicy_, - const Branches::Ptr &ibranches_, + const Policy::Search &openPolicy_, + const Branches::Ptr ibranches_, const fs::path &oldpath_, const fs::path &newpath_, struct stat *st_, @@ -245,6 +251,8 @@ _link_exdev_abs_base_symlink(const fuse_req_ctx_t *ctx_, rv = openPolicy_(ibranches_,oldpath_,obranches); if(rv < 0) return rv; + if(obranches.empty()) + return -ENOENT; target = obranches[0]->path / oldpath_; diff --git a/src/fuse_listxattr.cpp b/src/fuse_listxattr.cpp index d14035e3..ce84e64e 100644 --- a/src/fuse_listxattr.cpp +++ b/src/fuse_listxattr.cpp @@ -121,7 +121,7 @@ _listxattr(const std::vector &branches_, static int _listxattr(const Policy::Search &searchFunc_, - const Branches &ibranches_, + const Branches::Ptr ibranches_, const fs::path &fusepath_, char *list_, const size_t size_) diff --git a/src/fuse_mkdir.cpp b/src/fuse_mkdir.cpp index 68f732a7..bd3e9c68 100644 --- a/src/fuse_mkdir.cpp +++ b/src/fuse_mkdir.cpp @@ -103,7 +103,7 @@ int _mkdir(const ugid_t ugid_, const Policy::Search &getattrPolicy_, const Policy::Create &mkdirPolicy_, - const Branches &branches_, + const Branches::Ptr branches_, const fs::path &fusepath_, const mode_t mode_, const mode_t umask_) @@ -118,10 +118,14 @@ _mkdir(const ugid_t ugid_, rv = getattrPolicy_(branches_,fusedirpath,existingbranches); if(rv < 0) return rv; + if(existingbranches.empty()) + return -ENOENT; rv = mkdirPolicy_(branches_,fusedirpath,createbranches); if(rv < 0) return rv; + if(createbranches.empty()) + return -ENOENT; return ::_mkdir_loop(ugid_, existingbranches[0], diff --git a/src/fuse_mknod.cpp b/src/fuse_mknod.cpp index 7e3d3cf2..889f1a96 100644 --- a/src/fuse_mknod.cpp +++ b/src/fuse_mknod.cpp @@ -108,7 +108,7 @@ int _mknod(const ugid_t ugid_, const Policy::Search &searchFunc_, const Policy::Create &createFunc_, - const Branches &branches_, + const Branches::Ptr branches_, const fs::path &fusepath_, const mode_t mode_, const mode_t umask_, @@ -124,10 +124,14 @@ _mknod(const ugid_t ugid_, rv = searchFunc_(branches_,fusedirpath,existingbranches); if(rv < 0) return rv; + if(existingbranches.empty()) + return -ENOENT; rv = createFunc_(branches_,fusedirpath,createbranches); if(rv < 0) return rv; + if(createbranches.empty()) + return -ENOENT; return ::_mknod_loop(ugid_, existingbranches[0]->path, diff --git a/src/fuse_open.cpp b/src/fuse_open.cpp index 8513e39b..6bdc3e70 100644 --- a/src/fuse_open.cpp +++ b/src/fuse_open.cpp @@ -25,9 +25,9 @@ simultaneously attempt to open the same file (same nodeid), and we need to: - 1. Share a single canonical FileInfo entry in the open_files map for all - opens of the same file while still giving each FUSE handle its own - FileInfo object and file descriptor + 1. Share a single canonical FileInfo entry in the open_files map for + all opens of the same file while still giving each FUSE handle + its own FileInfo object and file descriptor 2. Properly reference count to know when to release resources 3. Handle race conditions without deadlocks or resource leaks 4. Support FUSE passthrough mode for performance @@ -45,8 +45,8 @@ FileInfo by re-opening the canonical file descriptor 3. If it doesn't exist, we create a new FileInfo and try to insert it 4. If insertion fails (another thread inserted first), we clean up - and retry (because to use passthrough it MUST be the same underlying - file as the backing id was created) + and retry (because to use passthrough it MUST be the same + underlying file as the backing id was created) THE RETRY LOOP -------------- @@ -308,7 +308,7 @@ _open_fd(const int fd_, static int _open(const Policy::Search &searchFunc_, - const Branches &ibranches_, + const Branches::Ptr ibranches_, const fs::path &fusepath_, fuse_file_info_t *ffi_, const bool link_cow_, @@ -321,6 +321,8 @@ _open(const Policy::Search &searchFunc_, rv = searchFunc_(ibranches_,fusepath_,obranches); if(rv < 0) return rv; + if(obranches.empty()) + return -ENOENT; filepath = obranches[0]->path / fusepath_; diff --git a/src/fuse_readdir_cor.cpp b/src/fuse_readdir_cor.cpp index b0f5ba4a..596a27f4 100644 --- a/src/fuse_readdir_cor.cpp +++ b/src/fuse_readdir_cor.cpp @@ -47,7 +47,7 @@ static inline int _concurrent_readdir(ThreadPool &tp_, - const Branches::Ptr &branches_, + const Branches::Ptr branches_, const fs::path &rel_dirpath_, fuse_dirents_t *dirents_) { diff --git a/src/fuse_readdir_cosr.cpp b/src/fuse_readdir_cosr.cpp index a916ba2e..6d7bb721 100644 --- a/src/fuse_readdir_cosr.cpp +++ b/src/fuse_readdir_cosr.cpp @@ -45,7 +45,7 @@ static inline int _readdir(ThreadPool &tp_, - const Branches::Ptr &branches_, + const Branches::Ptr branches_, const fs::path &rel_dirpath_, fuse_dirents_t *dirents_) { diff --git a/src/fuse_readlink.cpp b/src/fuse_readlink.cpp index 7dd12933..9f5e748d 100644 --- a/src/fuse_readlink.cpp +++ b/src/fuse_readlink.cpp @@ -101,7 +101,7 @@ _readlink_core(const fs::path &basepath_, static int _readlink(const Policy::Search &searchFunc_, - const Branches &ibranches_, + const Branches::Ptr ibranches_, const fs::path &fusepath_, char *buf_, const size_t bufsize_, diff --git a/src/fuse_removexattr.cpp b/src/fuse_removexattr.cpp index e9b67c8f..f43bb411 100644 --- a/src/fuse_removexattr.cpp +++ b/src/fuse_removexattr.cpp @@ -63,7 +63,7 @@ static int _removexattr(const Policy::Action &actionFunc_, const Policy::Search &searchFunc_, - const Branches &ibranches_, + const Branches::Ptr ibranches_, const fs::path &fusepath_, const char *attrname_) { @@ -74,6 +74,8 @@ _removexattr(const Policy::Action &actionFunc_, rv = actionFunc_(ibranches_,fusepath_,obranches); if(rv < 0) return rv; + if(obranches.empty()) + return -ENOENT; ::_removexattr_loop(obranches,fusepath_,attrname_,&prv); if(prv.errors.empty()) @@ -85,6 +87,8 @@ _removexattr(const Policy::Action &actionFunc_, rv = searchFunc_(ibranches_,fusepath_,obranches); if(rv < 0) return rv; + if(obranches.empty()) + return -ENOENT; return prv.get_error(obranches[0]->path); } diff --git a/src/fuse_rename.cpp b/src/fuse_rename.cpp index 36bc1e8e..ad550a2f 100644 --- a/src/fuse_rename.cpp +++ b/src/fuse_rename.cpp @@ -70,8 +70,8 @@ _remove(const StrVec &toremove_) static int _rename_create_path(const Policy::Search &searchPolicy_, - const Policy::Action &actionPolicy_, - const Branches::Ptr &branches_, + const Policy::Action &actionPolicy_, + const Branches::Ptr branches_, const fs::path &oldfusepath_, const fs::path &newfusepath_) { @@ -86,10 +86,14 @@ _rename_create_path(const Policy::Search &searchPolicy_, rv = actionPolicy_(branches_,oldfusepath_,oldbranches); if(rv < 0) return rv; + if(oldbranches.empty()) + return -ENOENT; rv = searchPolicy_(branches_,newfusepath_.parent_path(),newbranches); if(rv < 0) return rv; + if(newbranches.empty()) + return -ENOENT; for(auto &branch : *branches_) { @@ -127,7 +131,7 @@ _rename_create_path(const Policy::Search &searchPolicy_, static int _rename_preserve_path(const Policy::Action &actionPolicy_, - const Branches::Ptr &branches_, + const Branches::Ptr branches_, const fs::path &oldfusepath_, const fs::path &newfusepath_) { @@ -198,7 +202,7 @@ _rename_exdev_rename_back(const std::vector &branches_, static int _rename_exdev_rename_target(const Policy::Action &actionPolicy_, - const Branches::Ptr &ibranches_, + const Branches::Ptr ibranches_, const fs::path &oldfusepath_, std::vector &obranches_) { @@ -245,8 +249,8 @@ _rename_exdev_rename_target(const Policy::Action &actionPolicy_, static int _rename_exdev_rel_symlink(const fuse_req_ctx_t *ctx_, - const Policy::Action &actionPolicy_, - const Branches::Ptr &branches_, + const Policy::Action &actionPolicy_, + const Branches::Ptr branches_, const fs::path &oldfusepath_, const fs::path &newfusepath_) { @@ -274,8 +278,8 @@ _rename_exdev_rel_symlink(const fuse_req_ctx_t *ctx_, static int _rename_exdev_abs_symlink(const fuse_req_ctx_t *ctx_, - const Policy::Action &actionPolicy_, - const Branches::Ptr &branches_, + const Policy::Action &actionPolicy_, + const Branches::Ptr branches_, const fs::path &mount_, const fs::path &oldfusepath_, const fs::path &newfusepath_) diff --git a/src/fuse_rmdir.cpp b/src/fuse_rmdir.cpp index e2dad055..e6fcbd53 100644 --- a/src/fuse_rmdir.cpp +++ b/src/fuse_rmdir.cpp @@ -78,7 +78,7 @@ _rmdir_loop(const std::vector &branches_, static int _rmdir(const Policy::Action &actionFunc_, - const Branches &branches_, + const Branches::Ptr branches_, const FollowSymlinks followsymlinks_, const fs::path &fusepath_) { diff --git a/src/fuse_setxattr.cpp b/src/fuse_setxattr.cpp index 4f398c32..260d2beb 100644 --- a/src/fuse_setxattr.cpp +++ b/src/fuse_setxattr.cpp @@ -145,7 +145,7 @@ static int _setxattr(const Policy::Action &setxattrPolicy_, const Policy::Search &getxattrPolicy_, - const Branches &branches_, + const Branches::Ptr branches_, const fs::path &fusepath_, const char *attrname_, const char *attrval_, @@ -159,6 +159,8 @@ _setxattr(const Policy::Action &setxattrPolicy_, rv = setxattrPolicy_(branches_,fusepath_,branches); if(rv < 0) return rv; + if(branches.empty()) + return -ENOENT; ::_setxattr_loop(branches,fusepath_,attrname_,attrval_,attrvalsize_,flags_,&prv); if(prv.errors.empty()) @@ -170,6 +172,8 @@ _setxattr(const Policy::Action &setxattrPolicy_, rv = getxattrPolicy_(branches_,fusepath_,branches); if(rv < 0) return rv; + if(branches.empty()) + return -ENOENT; return prv.get_error(branches[0]->path); } diff --git a/src/fuse_statfs.cpp b/src/fuse_statfs.cpp index 68f0194d..ebe37a7c 100644 --- a/src/fuse_statfs.cpp +++ b/src/fuse_statfs.cpp @@ -76,7 +76,7 @@ _should_ignore(const StatFSIgnore ignore_, static int -_statfs(const Branches::Ptr &branches_, +_statfs(const Branches::Ptr branches_, const fs::path &fusepath_, const StatFS mode_, const StatFSIgnore ignore_, @@ -147,7 +147,7 @@ FUSE::statfs(const fuse_req_ctx_t *ctx_, const char *fusepath_, struct statvfs *st_) { - const fs::path fusepath{fusepath_}; + const fs::path fusepath{fusepath_}; return ::_statfs(cfg.branches, fusepath, diff --git a/src/fuse_statx_supported.icpp b/src/fuse_statx_supported.icpp index e16f792f..32f8eb19 100644 --- a/src/fuse_statx_supported.icpp +++ b/src/fuse_statx_supported.icpp @@ -116,7 +116,7 @@ _statx_controlfile(struct fuse_statx *st_) static int _statx(const Policy::Search &searchFunc_, - const Branches &branches_, + const Branches::Ptr branches_, const fs::path &fusepath_, const uint32_t flags_, const uint32_t mask_, @@ -132,6 +132,8 @@ _statx(const Policy::Search &searchFunc_, rv = searchFunc_(branches_,fusepath_,branches); if(rv < 0) return rv; + if(branches.empty()) + return -ENOENT; fullpath = branches[0]->path / fusepath_; diff --git a/src/fuse_symlink.cpp b/src/fuse_symlink.cpp index a2cbd367..5dbc818a 100644 --- a/src/fuse_symlink.cpp +++ b/src/fuse_symlink.cpp @@ -97,7 +97,7 @@ int _symlink(const ugid_t ugid_, const Policy::Search &searchFunc_, const Policy::Create &createFunc_, - const Branches &branches_, + const Branches::Ptr branches_, const char *target_, const fs::path &linkpath_, struct stat *st_) @@ -112,10 +112,14 @@ _symlink(const ugid_t ugid_, rv = searchFunc_(branches_,newdirpath,existingbranches); if(rv < 0) return rv; + if(existingbranches.empty()) + return -ENOENT; rv = createFunc_(branches_,newdirpath,newbranches); if(rv < 0) return rv; + if(newbranches.empty()) + return -ENOENT; return ::_symlink_loop(ugid_, existingbranches[0]->path, diff --git a/src/fuse_truncate.cpp b/src/fuse_truncate.cpp index ca9a9e07..6ea0f8a1 100644 --- a/src/fuse_truncate.cpp +++ b/src/fuse_truncate.cpp @@ -64,7 +64,7 @@ static int _truncate(const Policy::Action &actionFunc_, const Policy::Search &searchFunc_, - const Branches &branches_, + const Branches::Ptr branches_, const fs::path &fusepath_, const off_t size_) { @@ -75,6 +75,8 @@ _truncate(const Policy::Action &actionFunc_, rv = actionFunc_(branches_,fusepath_,branches); if(rv < 0) return rv; + if(branches.empty()) + return -ENOENT; ::_truncate_loop(branches,fusepath_,size_,&prv); if(prv.errors.empty()) @@ -86,6 +88,8 @@ _truncate(const Policy::Action &actionFunc_, rv = searchFunc_(branches_,fusepath_,branches); if(rv < 0) return rv; + if(branches.empty()) + return -ENOENT; return prv.get_error(branches[0]->path); } diff --git a/src/fuse_unlink.cpp b/src/fuse_unlink.cpp index 8f72e1a4..abd7ee35 100644 --- a/src/fuse_unlink.cpp +++ b/src/fuse_unlink.cpp @@ -52,7 +52,7 @@ _unlink_loop(const std::vector &branches_, static int _unlink(const Policy::Action &unlinkPolicy_, - const Branches &branches_, + const Branches::Ptr branches_, const fs::path &fusepath_) { int rv; diff --git a/src/fuse_utimens.cpp b/src/fuse_utimens.cpp index 48b8f8fc..7fbec390 100644 --- a/src/fuse_utimens.cpp +++ b/src/fuse_utimens.cpp @@ -63,7 +63,7 @@ static int _utimens(const Policy::Action &utimensPolicy_, const Policy::Search &getattrPolicy_, - const Branches &branches_, + const Branches::Ptr branches_, const fs::path &fusepath_, const timespec ts_[2]) { @@ -74,6 +74,8 @@ _utimens(const Policy::Action &utimensPolicy_, rv = utimensPolicy_(branches_,fusepath_,branches); if(rv < 0) return rv; + if(branches.empty()) + return -ENOENT; ::_utimens_loop(branches,fusepath_,ts_,&prv); if(prv.errors.empty()) @@ -85,6 +87,8 @@ _utimens(const Policy::Action &utimensPolicy_, rv = getattrPolicy_(branches_,fusepath_,branches); if(rv < 0) return rv; + if(branches.empty()) + return -ENOENT; return prv.get_error(branches[0]->path); }