From 22a7ac1c90a8872f21bc45a04411361d912bc065 Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Thu, 13 Nov 2025 20:45:52 -0600 Subject: [PATCH] Change getattr and statx to bespoke policies * Provides: slight improvement in performance as it no longer will need to find and then act on the files. * It doesn't make sense to support all original policy types. Most people used 'newest' or 'ff' and 'combine' is a better default which has same runtime as 'newest' but with better output. --- src/config.cpp | 17 ++--- src/config.hpp | 26 ++++++++ src/config_follow_symlinks.hpp | 8 +-- src/follow_symlinks_enum.hpp | 9 +++ src/fs_lstat.hpp | 19 ++---- src/fs_stat.cpp | 0 src/fs_stat.hpp | 61 +++++++++++++++-- src/fs_statx.hpp | 61 ++++++++++++++--- src/fsproxy.cpp | 36 ++++++++++ src/fsproxy.hpp | 54 +++++++++++++++ src/func_access.hpp | 73 ++++++++++++++++++++ src/func_access_all.cpp | 29 ++++++++ src/func_access_all.hpp | 19 ++++++ src/func_access_base.hpp | 24 +++++++ src/func_access_factory.cpp | 30 +++++++++ src/func_access_factory.hpp | 13 ++++ src/func_chmod.hpp | 73 ++++++++++++++++++++ src/func_chmod_all.cpp | 35 ++++++++++ src/func_chmod_all.hpp | 19 ++++++ src/func_chmod_base.hpp | 23 +++++++ src/func_chmod_factory.cpp | 30 +++++++++ src/func_chmod_factory.hpp | 13 ++++ src/func_chown.hpp | 75 +++++++++++++++++++++ src/func_chown_all.cpp | 36 ++++++++++ src/func_chown_all.hpp | 20 ++++++ src/func_chown_base.hpp | 24 +++++++ src/func_chown_factory.cpp | 30 +++++++++ src/func_chown_factory.hpp | 13 ++++ src/func_getattr.hpp | 76 +++++++++++++++++++++ src/func_getattr_base.hpp | 35 ++++++++++ src/func_getattr_combine.cpp | 71 ++++++++++++++++++++ src/func_getattr_combine.hpp | 21 ++++++ src/func_getattr_factory.cpp | 39 +++++++++++ src/func_getattr_factory.hpp | 13 ++++ src/func_getattr_ff.cpp | 41 ++++++++++++ src/func_getattr_ff.hpp | 23 +++++++ src/func_getattr_newest.cpp | 57 ++++++++++++++++ src/func_getattr_newest.hpp | 21 ++++++ src/func_getxattr.hpp | 77 +++++++++++++++++++++ src/func_getxattr_base.hpp | 25 +++++++ src/func_getxattr_factory.cpp | 30 +++++++++ src/func_getxattr_factory.hpp | 13 ++++ src/func_getxattr_ff.cpp | 35 ++++++++++ src/func_getxattr_ff.hpp | 21 ++++++ src/func_ioctl.hpp | 73 ++++++++++++++++++++ src/func_ioctl_all.cpp | 25 +++++++ src/func_ioctl_all.hpp | 18 +++++ src/func_ioctl_base.hpp | 22 ++++++ src/func_ioctl_factory.cpp | 30 +++++++++ src/func_ioctl_factory.hpp | 13 ++++ src/func_listxattr.hpp | 73 ++++++++++++++++++++ src/func_listxattr_all.cpp | 27 ++++++++ src/func_listxattr_all.hpp | 20 ++++++ src/func_listxattr_base.hpp | 24 +++++++ src/func_listxattr_factory.cpp | 30 +++++++++ src/func_listxattr_factory.hpp | 13 ++++ src/func_open.hpp | 73 ++++++++++++++++++++ src/func_open_all.cpp | 27 ++++++++ src/func_open_all.hpp | 19 ++++++ src/func_open_base.hpp | 23 +++++++ src/func_open_factory.cpp | 30 +++++++++ src/func_open_factory.hpp | 13 ++++ src/func_readlink.hpp | 75 +++++++++++++++++++++ src/func_readlink_all.cpp | 28 ++++++++ src/func_readlink_all.hpp | 20 ++++++ src/func_readlink_base.hpp | 24 +++++++ src/func_readlink_factory.cpp | 30 +++++++++ src/func_readlink_factory.hpp | 13 ++++ src/func_removexattr.hpp | 73 ++++++++++++++++++++ src/func_removexattr_all.cpp | 35 ++++++++++ src/func_removexattr_all.hpp | 19 ++++++ src/func_removexattr_base.hpp | 23 +++++++ src/func_removexattr_factory.cpp | 30 +++++++++ src/func_removexattr_factory.hpp | 13 ++++ src/func_rmdir.hpp | 71 ++++++++++++++++++++ src/func_rmdir_all.cpp | 50 ++++++++++++++ src/func_rmdir_all.hpp | 18 +++++ src/func_rmdir_base.hpp | 22 ++++++ src/func_rmdir_factory.cpp | 30 +++++++++ src/func_rmdir_factory.hpp | 13 ++++ src/func_setxattr.hpp | 79 ++++++++++++++++++++++ src/func_setxattr_all.cpp | 38 +++++++++++ src/func_setxattr_all.hpp | 22 ++++++ src/func_setxattr_base.hpp | 26 ++++++++ src/func_setxattr_factory.cpp | 30 +++++++++ src/func_setxattr_factory.hpp | 13 ++++ src/func_statx.hpp | 81 ++++++++++++++++++++++ src/func_statx_base.hpp | 38 +++++++++++ src/func_statx_combine.cpp | 79 ++++++++++++++++++++++ src/func_statx_combine.hpp | 23 +++++++ src/func_statx_factory.cpp | 39 +++++++++++ src/func_statx_factory.hpp | 13 ++++ src/func_statx_ff.cpp | 48 +++++++++++++ src/func_statx_ff.hpp | 25 +++++++ src/func_statx_newest.cpp | 64 ++++++++++++++++++ src/func_statx_newest.hpp | 23 +++++++ src/func_truncate.hpp | 73 ++++++++++++++++++++ src/func_truncate_all.cpp | 35 ++++++++++ src/func_truncate_all.hpp | 19 ++++++ src/func_truncate_base.hpp | 23 +++++++ src/func_truncate_factory.cpp | 30 +++++++++ src/func_truncate_factory.hpp | 13 ++++ src/func_unlink.hpp | 71 ++++++++++++++++++++ src/func_unlink_all.cpp | 34 ++++++++++ src/func_unlink_all.hpp | 18 +++++ src/func_unlink_base.hpp | 22 ++++++ src/func_unlink_factory.cpp | 30 +++++++++ src/func_unlink_factory.hpp | 13 ++++ src/func_utimens.hpp | 73 ++++++++++++++++++++ src/func_utimens_all.cpp | 35 ++++++++++ src/func_utimens_all.hpp | 19 ++++++ src/func_utimens_base.hpp | 23 +++++++ src/func_utimens_factory.cpp | 30 +++++++++ src/func_utimens_factory.hpp | 13 ++++ src/fuse_chmod.cpp | 87 +----------------------- src/fuse_chown.cpp | 82 ++--------------------- src/fuse_getattr.cpp | 103 ++-------------------------- src/fuse_removexattr.cpp | 74 +-------------------- src/fuse_rmdir.cpp | 80 +--------------------- src/fuse_statx_supported.icpp | 111 ++----------------------------- src/fuse_truncate.cpp | 72 +------------------- src/fuse_unlink.cpp | 49 +------------- src/fuse_utimens.cpp | 77 +-------------------- src/timespec_utils.hpp | 72 ++++++++++++++++++++ src/to_cstr.hpp | 22 ++++++ 125 files changed, 3901 insertions(+), 751 deletions(-) create mode 100644 src/follow_symlinks_enum.hpp create mode 100644 src/fs_stat.cpp create mode 100644 src/fsproxy.cpp create mode 100644 src/fsproxy.hpp create mode 100644 src/func_access.hpp create mode 100644 src/func_access_all.cpp create mode 100644 src/func_access_all.hpp create mode 100644 src/func_access_base.hpp create mode 100644 src/func_access_factory.cpp create mode 100644 src/func_access_factory.hpp create mode 100644 src/func_chmod.hpp create mode 100644 src/func_chmod_all.cpp create mode 100644 src/func_chmod_all.hpp create mode 100644 src/func_chmod_base.hpp create mode 100644 src/func_chmod_factory.cpp create mode 100644 src/func_chmod_factory.hpp create mode 100644 src/func_chown.hpp create mode 100644 src/func_chown_all.cpp create mode 100644 src/func_chown_all.hpp create mode 100644 src/func_chown_base.hpp create mode 100644 src/func_chown_factory.cpp create mode 100644 src/func_chown_factory.hpp create mode 100644 src/func_getattr.hpp create mode 100644 src/func_getattr_base.hpp create mode 100644 src/func_getattr_combine.cpp create mode 100644 src/func_getattr_combine.hpp create mode 100644 src/func_getattr_factory.cpp create mode 100644 src/func_getattr_factory.hpp create mode 100644 src/func_getattr_ff.cpp create mode 100644 src/func_getattr_ff.hpp create mode 100644 src/func_getattr_newest.cpp create mode 100644 src/func_getattr_newest.hpp create mode 100644 src/func_getxattr.hpp create mode 100644 src/func_getxattr_base.hpp create mode 100644 src/func_getxattr_factory.cpp create mode 100644 src/func_getxattr_factory.hpp create mode 100644 src/func_getxattr_ff.cpp create mode 100644 src/func_getxattr_ff.hpp create mode 100644 src/func_ioctl.hpp create mode 100644 src/func_ioctl_all.cpp create mode 100644 src/func_ioctl_all.hpp create mode 100644 src/func_ioctl_base.hpp create mode 100644 src/func_ioctl_factory.cpp create mode 100644 src/func_ioctl_factory.hpp create mode 100644 src/func_listxattr.hpp create mode 100644 src/func_listxattr_all.cpp create mode 100644 src/func_listxattr_all.hpp create mode 100644 src/func_listxattr_base.hpp create mode 100644 src/func_listxattr_factory.cpp create mode 100644 src/func_listxattr_factory.hpp create mode 100644 src/func_open.hpp create mode 100644 src/func_open_all.cpp create mode 100644 src/func_open_all.hpp create mode 100644 src/func_open_base.hpp create mode 100644 src/func_open_factory.cpp create mode 100644 src/func_open_factory.hpp create mode 100644 src/func_readlink.hpp create mode 100644 src/func_readlink_all.cpp create mode 100644 src/func_readlink_all.hpp create mode 100644 src/func_readlink_base.hpp create mode 100644 src/func_readlink_factory.cpp create mode 100644 src/func_readlink_factory.hpp create mode 100644 src/func_removexattr.hpp create mode 100644 src/func_removexattr_all.cpp create mode 100644 src/func_removexattr_all.hpp create mode 100644 src/func_removexattr_base.hpp create mode 100644 src/func_removexattr_factory.cpp create mode 100644 src/func_removexattr_factory.hpp create mode 100644 src/func_rmdir.hpp create mode 100644 src/func_rmdir_all.cpp create mode 100644 src/func_rmdir_all.hpp create mode 100644 src/func_rmdir_base.hpp create mode 100644 src/func_rmdir_factory.cpp create mode 100644 src/func_rmdir_factory.hpp create mode 100644 src/func_setxattr.hpp create mode 100644 src/func_setxattr_all.cpp create mode 100644 src/func_setxattr_all.hpp create mode 100644 src/func_setxattr_base.hpp create mode 100644 src/func_setxattr_factory.cpp create mode 100644 src/func_setxattr_factory.hpp create mode 100644 src/func_statx.hpp create mode 100644 src/func_statx_base.hpp create mode 100644 src/func_statx_combine.cpp create mode 100644 src/func_statx_combine.hpp create mode 100644 src/func_statx_factory.cpp create mode 100644 src/func_statx_factory.hpp create mode 100644 src/func_statx_ff.cpp create mode 100644 src/func_statx_ff.hpp create mode 100644 src/func_statx_newest.cpp create mode 100644 src/func_statx_newest.hpp create mode 100644 src/func_truncate.hpp create mode 100644 src/func_truncate_all.cpp create mode 100644 src/func_truncate_all.hpp create mode 100644 src/func_truncate_base.hpp create mode 100644 src/func_truncate_factory.cpp create mode 100644 src/func_truncate_factory.hpp create mode 100644 src/func_unlink.hpp create mode 100644 src/func_unlink_all.cpp create mode 100644 src/func_unlink_all.hpp create mode 100644 src/func_unlink_base.hpp create mode 100644 src/func_unlink_factory.cpp create mode 100644 src/func_unlink_factory.hpp create mode 100644 src/func_utimens.hpp create mode 100644 src/func_utimens_all.cpp create mode 100644 src/func_utimens_all.hpp create mode 100644 src/func_utimens_base.hpp create mode 100644 src/func_utimens_factory.cpp create mode 100644 src/func_utimens_factory.hpp create mode 100644 src/timespec_utils.hpp create mode 100644 src/to_cstr.hpp diff --git a/src/config.cpp b/src/config.cpp index 691dd2bc..8f3f6297 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -226,10 +226,10 @@ Config::Config() _map["follow-symlinks"] = &follow_symlinks; _map["fsname"] = &fsname; _map["func.access"] = &func.access; - _map["func.chmod"] = &func.chmod; - _map["func.chown"] = &func.chown; + _map["func.chmod"] = &chmod; + _map["func.chown"] = &chown; _map["func.create"] = &func.create; - _map["func.getattr"] = &func.getattr; + _map["func.getattr"] = &getattr; _map["func.getxattr"] = &func.getxattr; _map["func.link"] = &func.link; _map["func.listxattr"] = &func.listxattr; @@ -238,14 +238,15 @@ Config::Config() _map["func.open"] = &func.open; _map["func.readdir"] = &readdir; _map["func.readlink"] = &func.readlink; - _map["func.removexattr"] = &func.removexattr; + _map["func.removexattr"] = &removexattr; _map["func.rename"] = &func.rename; - _map["func.rmdir"] = &func.rmdir; + _map["func.rmdir"] = &rmdir; _map["func.setxattr"] = &func.setxattr; + _map["func.statx"] = &statx; _map["func.symlink"] = &func.symlink; - _map["func.truncate"] = &func.truncate; - _map["func.unlink"] = &func.unlink; - _map["func.utimens"] = &func.utimens; + _map["func.truncate"] = &truncate; + _map["func.unlink"] = &unlink; + _map["func.utimens"] = &utimens; _map["fuse-msg-size"] = &fuse_msg_size; _map["gid"] = &_gid; _map["gid-cache.expire-timeout"] = &_dummy; diff --git a/src/config.hpp b/src/config.hpp index c16e46d3..57153066 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -16,6 +16,19 @@ #pragma once +#include "func_chmod.hpp" +#include "func_chown.hpp" +#include "func_getattr.hpp" +#include "func_getxattr.hpp" +#include "func_readlink.hpp" +#include "func_removexattr.hpp" +#include "func_rmdir.hpp" +#include "func_setxattr.hpp" +#include "func_statx.hpp" +#include "func_truncate.hpp" +#include "func_unlink.hpp" +#include "func_utimens.hpp" + #include "branches.hpp" #include "category.hpp" #include "config_cachefiles.hpp" @@ -108,6 +121,19 @@ public: Config& operator=(const Config&); public: + Func2::Chmod chmod{"all"}; + Func2::Chown chown{"all"}; + Func2::GetAttr getattr{"combine"}; + Func2::Getxattr getxattr{"ff"}; + Func2::Readlink readlink{"ff"}; + Func2::Removexattr removexattr{"all"}; + Func2::Rmdir rmdir{"all"}; + Func2::Setxattr setxattr{"all"}; + Func2::Statx statx{"combine"}; + Func2::Truncate truncate{"all"}; + Func2::Unlink unlink{"all"}; + Func2::Utimens utimens{"all"}; + ConfigBOOL allow_idmap; ConfigBOOL async_read; Branches branches; diff --git a/src/config_follow_symlinks.hpp b/src/config_follow_symlinks.hpp index 1ebbdecf..a6df2bce 100644 --- a/src/config_follow_symlinks.hpp +++ b/src/config_follow_symlinks.hpp @@ -19,12 +19,6 @@ #pragma once #include "enum.hpp" +#include "follow_symlinks_enum.hpp" -enum class FollowSymlinksEnum - { - NEVER, - DIRECTORY, - REGULAR, - ALL - }; typedef Enum FollowSymlinks; diff --git a/src/follow_symlinks_enum.hpp b/src/follow_symlinks_enum.hpp new file mode 100644 index 00000000..c708b898 --- /dev/null +++ b/src/follow_symlinks_enum.hpp @@ -0,0 +1,9 @@ +#pragma once + +enum class FollowSymlinksEnum + { + NEVER, + DIRECTORY, + REGULAR, + ALL + }; diff --git a/src/fs_lstat.hpp b/src/fs_lstat.hpp index 574fd80b..ece50c9c 100644 --- a/src/fs_lstat.hpp +++ b/src/fs_lstat.hpp @@ -19,8 +19,7 @@ #pragma once #include "to_neg_errno.hpp" - -#include +#include "to_cstr.hpp" #include #include @@ -29,25 +28,17 @@ namespace fs { + template static inline int - lstat(const char *path_, - struct stat *st_) + lstat(const PathType &path_, + struct stat *st_) { int rv; - rv = ::lstat(path_,st_); + rv = ::lstat(to_cstr(path_),st_); return ::to_neg_errno(rv); } - - static - inline - int - lstat(const std::string &path_, - struct stat *st_) - { - return fs::lstat(path_.c_str(),st_); - } } diff --git a/src/fs_stat.cpp b/src/fs_stat.cpp new file mode 100644 index 00000000..e69de29b diff --git a/src/fs_stat.hpp b/src/fs_stat.hpp index 0e85f7f3..c3e60c98 100644 --- a/src/fs_stat.hpp +++ b/src/fs_stat.hpp @@ -18,7 +18,10 @@ #pragma once +#include "follow_symlinks_enum.hpp" #include "to_neg_errno.hpp" +#include "to_cstr.hpp" +#include "fs_lstat.hpp" #include @@ -29,25 +32,71 @@ namespace fs { + template static inline int - stat(const char *path_, - struct stat *st_) + stat(const PathType &path_, + struct stat *st_) { int rv; - rv = ::stat(path_,st_); + rv = ::stat(to_cstr(path_),st_); return ::to_neg_errno(rv); } + template static inline int - stat(const std::string &path_, - struct stat *st_) + stat(const PathType &path_, + struct stat *st_, + FollowSymlinksEnum follow_) { - return fs::stat(path_.c_str(),st_); + int rv; + + switch(follow_) + { + default: + case FollowSymlinksEnum::NEVER: + rv = fs::lstat(path_,st_); + return rv; + case FollowSymlinksEnum::DIRECTORY: + rv = fs::lstat(path_,st_); + if((rv >= 0) && S_ISLNK(st_->st_mode)) + { + struct stat st; + + rv = fs::stat(path_,&st); + if(rv < 0) + return rv; + + if(S_ISDIR(st.st_mode)) + *st_ = st; + } + return rv; + case FollowSymlinksEnum::REGULAR: + rv = fs::lstat(path_,st_); + if((rv >= 0) && S_ISLNK(st_->st_mode)) + { + struct stat st; + + rv = fs::stat(path_,&st); + if(rv < 0) + return rv; + + if(S_ISREG(st.st_mode)) + *st_ = st; + } + return rv; + case FollowSymlinksEnum::ALL: + rv = fs::stat(path_,st_); + if(rv < 0) + rv = fs::lstat(path_,st_); + return rv; + } + + return -ENOENT; } } diff --git a/src/fs_statx.hpp b/src/fs_statx.hpp index 6c0365b0..8ad3b443 100644 --- a/src/fs_statx.hpp +++ b/src/fs_statx.hpp @@ -1,5 +1,7 @@ #pragma once +#include "follow_symlinks_enum.hpp" +#include "to_cstr.hpp" #include "to_neg_errno.hpp" #include "fuse_kernel.h" @@ -17,11 +19,12 @@ namespace fs { + template static inline int statx(const int dirfd_, - const char *pathname_, + const PathType &pathname_, const int flags_, const unsigned int mask_, struct fuse_statx *st_) @@ -30,7 +33,7 @@ namespace fs int rv; rv = ::statx(dirfd_, - pathname_, + to_cstr(pathname_), flags_, mask_, (struct statx*)st_); @@ -41,19 +44,59 @@ namespace fs #endif } + template static inline int statx(const int dirfd_, - const std::string &pathname_, + const PathType &pathname_, const int flags_, const unsigned int mask_, - struct fuse_statx *st_) + struct fuse_statx *st_, + FollowSymlinksEnum followsymlinks_) { - return fs::statx(dirfd_, - pathname_.c_str(), - flags_, - mask_, - st_); + int rv; + + switch(followsymlinks_) + { + case FollowSymlinksEnum::NEVER: + rv = fs::statx(AT_FDCWD,pathname_,flags_|AT_SYMLINK_NOFOLLOW,mask_,st_); + return rv; + case FollowSymlinksEnum::DIRECTORY: + rv = fs::statx(AT_FDCWD,pathname_,flags_|AT_SYMLINK_NOFOLLOW,mask_,st_); + if((rv >= 0) && S_ISLNK(st_->mode)) + { + struct fuse_statx st; + + rv = fs::statx(AT_FDCWD,pathname_,AT_SYMLINK_FOLLOW,STATX_TYPE,&st); + if(rv < 0) + return rv; + + if(S_ISDIR(st.mode)) + *st_ = st; + } + return rv; + case FollowSymlinksEnum::REGULAR: + rv = fs::statx(AT_FDCWD,pathname_,flags_|AT_SYMLINK_NOFOLLOW,mask_,st_); + if((rv >= 0) && S_ISLNK(st_->mode)) + { + struct fuse_statx st; + + rv = fs::statx(AT_FDCWD,pathname_,AT_SYMLINK_FOLLOW,STATX_TYPE,&st); + if(rv < 0) + return rv; + + if(S_ISREG(st.mode)) + *st_ = st; + } + return rv; + case FollowSymlinksEnum::ALL: + rv = fs::statx(AT_FDCWD,pathname_,flags_|AT_SYMLINK_FOLLOW,mask_,st_); + if(rv < 0) + rv = fs::statx(AT_FDCWD,pathname_,flags_|AT_SYMLINK_NOFOLLOW,mask_,st_); + return rv; + } + + return -ENOENT; } } diff --git a/src/fsproxy.cpp b/src/fsproxy.cpp new file mode 100644 index 00000000..aa4d3716 --- /dev/null +++ b/src/fsproxy.cpp @@ -0,0 +1,36 @@ +#include "fsproxy.hpp" + +#include "fs_close.hpp" + +int +FSProxy::_spawn_proxy_if_needed(const uid_t uid_, + const gid_t gid_) +{ + int rv; + FSProxy::Process process; + + if(_proxies.count({uid_,gid_})) + return 0; + + rv = pipe(process.req_pipe); + if(rv == -1) + return rv; + rv = pipe(process.res_pipe); + if(rv == -1) + return rv; + + process.pid = fork(); + if(process.pid != 0) + { + fs::close(process.req_pipe[1]); + fs::close(process.res_pipe[0]); + // listen on req in loop for instructions + return 0; + } + + fs::close(process.req_pipe[0]); + fs::close(process.res_pipe[1]); + _proxies[UGID{uid_,gid_}] = process; + + return 0; +} diff --git a/src/fsproxy.hpp b/src/fsproxy.hpp new file mode 100644 index 00000000..95043769 --- /dev/null +++ b/src/fsproxy.hpp @@ -0,0 +1,54 @@ +#pragma once + +#include + +#include +#include + +class FSProxy +{ +public: + struct UGID + { + bool + operator==(const UGID &other_) const + { + return ((uid == other_.uid) && + (gid == other_.gid)); + } + + uid_t uid; + gid_t gid; + }; + + struct UGIDHash + { + size_t + operator()(const UGID &key_) const + { + size_t h0 = std::hash{}(key_.uid); + size_t h1 = std::hash{}(key_.gid); + + return (h0 ^ (h1 << 1)); + } + }; + + struct Process + { + int pid; + int req_pipe[2]; + int res_pipe[2]; + }; + +public: + int create(uid_t uid, + gid_t gid, + const char *pathname, + mode_t mode); + +private: + int _spawn_proxy_if_needed(uid_t,gid_t); + +private: + std::unordered_map _proxies; +}; diff --git a/src/func_access.hpp b/src/func_access.hpp new file mode 100644 index 00000000..38f7b832 --- /dev/null +++ b/src/func_access.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include "func_access_base.hpp" +#include "func_access_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + + +namespace Func2 +{ + class Access : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + Access() + { + } + + Access(const std::string &name_) + { + _impl = Func2::AccessFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_, + const mode_t mode_) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_, + mode_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string{p->name()}; + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::AccessFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_access_all.cpp b/src/func_access_all.cpp new file mode 100644 index 00000000..abe6b847 --- /dev/null +++ b/src/func_access_all.cpp @@ -0,0 +1,29 @@ +#include "func_access_all.hpp" + +#include "error.hpp" +#include "fs_eaccess.hpp" + + +std::string_view +Func2::AccessAll::name() const +{ + return "all"; +} + +int +Func2::AccessAll::operator()(const Branches &branches_, + const fs::path &fusepath_, + const int mode_) +{ + Err err; + fs::path fullpath; + + for(const auto &branch : branches_) + { + fullpath = branch.path / fusepath_; + + err = fs::eaccess(fullpath,mode_); + } + + return err; +} diff --git a/src/func_access_all.hpp b/src/func_access_all.hpp new file mode 100644 index 00000000..d8a90349 --- /dev/null +++ b/src/func_access_all.hpp @@ -0,0 +1,19 @@ +#include "func_access_base.hpp" + +namespace Func2 +{ + class AccessAll : public AccessBase + { + public: + AccessAll() {} + ~AccessAll() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + const int mode); + }; +} diff --git a/src/func_access_base.hpp b/src/func_access_base.hpp new file mode 100644 index 00000000..0be5ee2b --- /dev/null +++ b/src/func_access_base.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "branches.hpp" + +#include "fs_path.hpp" + + +namespace Func2 +{ + class AccessBase + { + public: + AccessBase() {} + ~AccessBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath, + const int mode) = 0; + }; +} diff --git a/src/func_access_factory.cpp b/src/func_access_factory.cpp new file mode 100644 index 00000000..39e7fd23 --- /dev/null +++ b/src/func_access_factory.cpp @@ -0,0 +1,30 @@ +#include "func_access_factory.hpp" + +#include "func_access_all.hpp" + +#include "policies.hpp" + + +bool +Func2::AccessFactory::valid(const std::string str_) +{ + if(str_ == "all") + return true; + + if(Policies::Action::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::AccessFactory::make(const std::string_view str_) +{ + if(str_ == "all") + return std::make_shared(); + + if(Policies::Action::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_access_factory.hpp b/src/func_access_factory.hpp new file mode 100644 index 00000000..786592a5 --- /dev/null +++ b/src/func_access_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_access_base.hpp" + +namespace Func2 +{ + class AccessFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/func_chmod.hpp b/src/func_chmod.hpp new file mode 100644 index 00000000..3c61113a --- /dev/null +++ b/src/func_chmod.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include "func_chmod_base.hpp" +#include "func_chmod_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + + +namespace Func2 +{ + class Chmod : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + Chmod() + { + } + + Chmod(const std::string &name_) + { + _impl = Func2::ChmodFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_, + const mode_t mode_) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_, + mode_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string{p->name()}; + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::ChmodFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_chmod_all.cpp b/src/func_chmod_all.cpp new file mode 100644 index 00000000..1b701e1a --- /dev/null +++ b/src/func_chmod_all.cpp @@ -0,0 +1,35 @@ +#include "func_chmod_all.hpp" + +#include "error.hpp" +#include "fs_lchmod.hpp" + + +std::string_view +Func2::ChmodAll::name() const +{ + return "all"; +} + +int +Func2::ChmodAll::operator()(const Branches &branches_, + const fs::path &fusepath_, + const mode_t mode_) +{ + Err err; + fs::path fullpath; + + for(const auto &branch : branches_) + { + if(branch.ro()) + { + err = -EROFS; + continue; + } + + fullpath = branch.path / fusepath_; + + err = fs::lchmod(fullpath,mode_); + } + + return err; +} diff --git a/src/func_chmod_all.hpp b/src/func_chmod_all.hpp new file mode 100644 index 00000000..eb3fe9cc --- /dev/null +++ b/src/func_chmod_all.hpp @@ -0,0 +1,19 @@ +#include "func_chmod_base.hpp" + +namespace Func2 +{ + class ChmodAll : public ChmodBase + { + public: + ChmodAll() {} + ~ChmodAll() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + const mode_t mode); + }; +} diff --git a/src/func_chmod_base.hpp b/src/func_chmod_base.hpp new file mode 100644 index 00000000..49077c31 --- /dev/null +++ b/src/func_chmod_base.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "branches.hpp" + +#include "fs_path.hpp" + +namespace Func2 +{ + class ChmodBase + { + public: + ChmodBase() {} + ~ChmodBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath, + const mode_t mode) = 0; + }; +} diff --git a/src/func_chmod_factory.cpp b/src/func_chmod_factory.cpp new file mode 100644 index 00000000..2b6536fd --- /dev/null +++ b/src/func_chmod_factory.cpp @@ -0,0 +1,30 @@ +#include "func_chmod_factory.hpp" + +#include "func_chmod_all.hpp" + +#include "policies.hpp" + + +bool +Func2::ChmodFactory::valid(const std::string str_) +{ + if(str_ == "all") + return true; + + if(Policies::Action::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::ChmodFactory::make(const std::string_view str_) +{ + if(str_ == "all") + return std::make_shared(); + + if(Policies::Action::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_chmod_factory.hpp b/src/func_chmod_factory.hpp new file mode 100644 index 00000000..4d6ad154 --- /dev/null +++ b/src/func_chmod_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_chmod_base.hpp" + +namespace Func2 +{ + class ChmodFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/func_chown.hpp b/src/func_chown.hpp new file mode 100644 index 00000000..26314566 --- /dev/null +++ b/src/func_chown.hpp @@ -0,0 +1,75 @@ +#pragma once + +#include "func_chown_base.hpp" +#include "func_chown_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + + +namespace Func2 +{ + class Chown : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + Chown() + { + } + + Chown(const std::string &name_) + { + _impl = Func2::ChownFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_, + const uid_t uid_, + const gid_t gid_) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_, + uid_, + gid_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string{p->name()}; + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::ChownFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_chown_all.cpp b/src/func_chown_all.cpp new file mode 100644 index 00000000..2a476afd --- /dev/null +++ b/src/func_chown_all.cpp @@ -0,0 +1,36 @@ +#include "func_chown_all.hpp" + +#include "error.hpp" +#include "fs_lchown.hpp" + + +std::string_view +Func2::ChownAll::name() const +{ + return "all"; +} + +int +Func2::ChownAll::operator()(const Branches &branches_, + const fs::path &fusepath_, + const uid_t uid_, + const gid_t gid_) +{ + Err err; + fs::path fullpath; + + for(const auto &branch : branches_) + { + if(branch.ro()) + { + err = -EROFS; + continue; + } + + fullpath = branch.path / fusepath_; + + err = fs::lchown(fullpath,uid_,gid_); + } + + return err; +} diff --git a/src/func_chown_all.hpp b/src/func_chown_all.hpp new file mode 100644 index 00000000..cd5516d7 --- /dev/null +++ b/src/func_chown_all.hpp @@ -0,0 +1,20 @@ +#include "func_chown_base.hpp" + +namespace Func2 +{ + class ChownAll : public ChownBase + { + public: + ChownAll() {} + ~ChownAll() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + const uid_t uid, + const gid_t gid); + }; +} diff --git a/src/func_chown_base.hpp b/src/func_chown_base.hpp new file mode 100644 index 00000000..c4d92514 --- /dev/null +++ b/src/func_chown_base.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "branches.hpp" + +#include "fs_path.hpp" + +namespace Func2 +{ + class ChownBase + { + public: + ChownBase() {} + ~ChownBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath, + const uid_t uid, + const gid_t gid) = 0; + }; +} diff --git a/src/func_chown_factory.cpp b/src/func_chown_factory.cpp new file mode 100644 index 00000000..9c13e5c9 --- /dev/null +++ b/src/func_chown_factory.cpp @@ -0,0 +1,30 @@ +#include "func_chown_factory.hpp" + +#include "func_chown_all.hpp" + +#include "policies.hpp" + + +bool +Func2::ChownFactory::valid(const std::string str_) +{ + if(str_ == "all") + return true; + + if(Policies::Action::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::ChownFactory::make(const std::string_view str_) +{ + if(str_ == "all") + return std::make_shared(); + + if(Policies::Action::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_chown_factory.hpp b/src/func_chown_factory.hpp new file mode 100644 index 00000000..72529519 --- /dev/null +++ b/src/func_chown_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_chown_base.hpp" + +namespace Func2 +{ + class ChownFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/func_getattr.hpp b/src/func_getattr.hpp new file mode 100644 index 00000000..d3687960 --- /dev/null +++ b/src/func_getattr.hpp @@ -0,0 +1,76 @@ +#pragma once + +#include "func_getattr_base.hpp" +#include "func_getattr_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + +namespace Func2 +{ + class GetAttr : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + GetAttr() + { + } + + GetAttr(const std::string &name_) + { + _impl = Func2::GetAttrFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_, + struct stat *st_, + const FollowSymlinksEnum follow_symlinks_, + const s64 symlinkify_timeout_) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_, + st_, + follow_symlinks_, + symlinkify_timeout_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string(p->name()); + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::GetAttrFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_getattr_base.hpp b/src/func_getattr_base.hpp new file mode 100644 index 00000000..6f89b750 --- /dev/null +++ b/src/func_getattr_base.hpp @@ -0,0 +1,35 @@ +#pragma once + +#include "follow_symlinks_enum.hpp" + +#include "fs_path.hpp" +#include "branches.hpp" +#include "int_types.h" + +#include "fuse.h" + +#include + +#include +#include +#include + +namespace Func2 +{ + class GetAttrBase + { + public: + GetAttrBase() {} + ~GetAttrBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath, + struct stat *st, + const FollowSymlinksEnum follow_symlinks, + const s64 symlinkify_timeout) = 0; + }; +} diff --git a/src/func_getattr_combine.cpp b/src/func_getattr_combine.cpp new file mode 100644 index 00000000..24723178 --- /dev/null +++ b/src/func_getattr_combine.cpp @@ -0,0 +1,71 @@ +#include "func_getattr_combine.hpp" + +#include "fs_inode.hpp" +#include "fs_stat.hpp" +#include "symlinkify.hpp" +#include "timespec_utils.hpp" + + +std::string_view +Func2::GetAttrCombine::name() const +{ + return "combine"; +} + +int +Func2::GetAttrCombine::operator()(const Branches &branches_, + const fs::path &fusepath_, + struct stat *st_, + const FollowSymlinksEnum follow_symlinks_, + const s64 symlinkify_timeout_) +{ + int rv; + fs::path fullpath; + const Branch *first_branch; + + first_branch = nullptr; + for(const auto &branch : branches_) + { + struct stat tmp_st; + + fullpath = branch.path / fusepath_; + rv = fs::stat(fullpath,&tmp_st,follow_symlinks_); + if(rv < 0) + continue; + + if(!first_branch) + { + *st_ = tmp_st; + first_branch = &branch; + continue; + } + + // This upgrades the uid:gid because mergerfs now does most + // file interaction as root and relies on `default_permissions` + // to manage permissions. Want to ensure that root owned files + // can't be changed so we treat them all as root owned. + if(tmp_st.st_uid == 0) + st_->st_uid = 0; + if(tmp_st.st_gid == 0) + st_->st_gid = 0; + st_->st_atim = TimeSpec::newest(st_->st_atim,tmp_st.st_atim); + st_->st_ctim = TimeSpec::newest(st_->st_ctim,tmp_st.st_ctim); + st_->st_mtim = TimeSpec::newest(st_->st_mtim,tmp_st.st_mtim); + st_->st_nlink += tmp_st.st_nlink; + } + + if(!first_branch) + return -ENOENT; + + if(symlinkify_timeout_ >= 0) + { + fullpath = first_branch->path / fusepath_; + symlinkify::convert_if_can_be_symlink(fullpath, + st_, + symlinkify_timeout_); + } + + fs::inode::calc(first_branch->path,fusepath_,st_); + + return 0; +} diff --git a/src/func_getattr_combine.hpp b/src/func_getattr_combine.hpp new file mode 100644 index 00000000..2a97bdf4 --- /dev/null +++ b/src/func_getattr_combine.hpp @@ -0,0 +1,21 @@ +#include "func_getattr_base.hpp" + +namespace Func2 +{ + class GetAttrCombine : public GetAttrBase + { + public: + GetAttrCombine() {} + ~GetAttrCombine() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + struct stat *st, + const FollowSymlinksEnum follow_symlinks, + const s64 symlinkify_timeout); + }; +} diff --git a/src/func_getattr_factory.cpp b/src/func_getattr_factory.cpp new file mode 100644 index 00000000..e6ee3576 --- /dev/null +++ b/src/func_getattr_factory.cpp @@ -0,0 +1,39 @@ +#include "func_getattr_factory.hpp" + +#include "func_getattr_combine.hpp" +#include "func_getattr_ff.hpp" +#include "func_getattr_newest.hpp" + +#include "policies.hpp" + +bool +Func2::GetAttrFactory::valid(const std::string str_) +{ + if(str_ == "combined") + return true; + if(str_ == "ff") + return true; + if(str_ == "newest") + return true; + + if(Policies::Search::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::GetAttrFactory::make(const std::string_view str_) +{ + if(str_ == "combine") + return std::make_shared(); + if(str_ == "ff") + return std::make_shared(); + if(str_ == "newest") + return std::make_shared(); + + if(Policies::Search::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_getattr_factory.hpp b/src/func_getattr_factory.hpp new file mode 100644 index 00000000..1e085980 --- /dev/null +++ b/src/func_getattr_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_getattr_base.hpp" + +namespace Func2 +{ + class GetAttrFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/func_getattr_ff.cpp b/src/func_getattr_ff.cpp new file mode 100644 index 00000000..4a94f69c --- /dev/null +++ b/src/func_getattr_ff.cpp @@ -0,0 +1,41 @@ +#include "func_getattr_ff.hpp" + +#include "fs_stat.hpp" +#include "fs_inode.hpp" +#include "symlinkify.hpp" + + +std::string_view +Func2::GetAttrFF::name() const +{ + return "ff"; +} + +int +Func2::GetAttrFF::operator()(const Branches &branches_, + const fs::path &fusepath_, + struct stat *st_, + const FollowSymlinksEnum follow_symlinks_, + const s64 symlinkify_timeout_) +{ + int rv; + fs::path fullpath; + + for(const auto &branch : branches_) + { + fullpath = branch.path / fusepath_; + rv = fs::stat(fullpath,st_,follow_symlinks_); + if(rv < 0) + continue; + + symlinkify::convert_if_can_be_symlink(fullpath, + st_, + symlinkify_timeout_); + + fs::inode::calc(branch.path,fusepath_,st_); + + return rv; + } + + return -ENOENT; +} diff --git a/src/func_getattr_ff.hpp b/src/func_getattr_ff.hpp new file mode 100644 index 00000000..e3d4b18f --- /dev/null +++ b/src/func_getattr_ff.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "func_getattr_base.hpp" + +namespace Func2 +{ + class GetAttrFF : public GetAttrBase + { + public: + GetAttrFF() {} + ~GetAttrFF() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + struct stat *st, + const FollowSymlinksEnum follow_symlinks, + const s64 symlinkify_timeout); + }; +} diff --git a/src/func_getattr_newest.cpp b/src/func_getattr_newest.cpp new file mode 100644 index 00000000..32a03b78 --- /dev/null +++ b/src/func_getattr_newest.cpp @@ -0,0 +1,57 @@ +#include "func_getattr_newest.hpp" + +#include "fs_stat.hpp" +#include "fs_inode.hpp" +#include "timespec_utils.hpp" +#include "symlinkify.hpp" + + +std::string_view +Func2::GetAttrNewest::name() const +{ + return "newest"; +} + +int +Func2::GetAttrNewest::operator()(const Branches &branches_, + const fs::path &fusepath_, + struct stat *st_, + const FollowSymlinksEnum follow_symlinks_, + const s64 symlinkify_timeout_) +{ + int rv; + fs::path fullpath; + const Branch *newest_branch; + + newest_branch = nullptr; + for(const auto &branch : branches_) + { + struct stat tmp_st; + + fullpath = branch.path / fusepath_; + rv = fs::stat(fullpath,&tmp_st,follow_symlinks_); + if(rv < 0) + continue; + + if(!TimeSpec::is_newer(tmp_st.st_mtim,st_->st_mtim)) + continue; + + *st_ = tmp_st; + newest_branch = &branch; + } + + if(!newest_branch) + return -ENOENT; + + if(symlinkify_timeout_ >= 0) + { + fullpath = newest_branch->path / fusepath_; + symlinkify::convert_if_can_be_symlink(fullpath, + st_, + symlinkify_timeout_); + } + + fs::inode::calc(newest_branch->path,fusepath_,st_); + + return 0; +} diff --git a/src/func_getattr_newest.hpp b/src/func_getattr_newest.hpp new file mode 100644 index 00000000..b08d0a67 --- /dev/null +++ b/src/func_getattr_newest.hpp @@ -0,0 +1,21 @@ +#include "func_getattr_base.hpp" + +namespace Func2 +{ + class GetAttrNewest : public GetAttrBase + { + public: + GetAttrNewest() {} + ~GetAttrNewest() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + struct stat *st, + const FollowSymlinksEnum follow_symlinks, + const s64 symlinkify_timeout); + }; +} diff --git a/src/func_getxattr.hpp b/src/func_getxattr.hpp new file mode 100644 index 00000000..5f1e9536 --- /dev/null +++ b/src/func_getxattr.hpp @@ -0,0 +1,77 @@ +#pragma once + +#include "func_getxattr_base.hpp" +#include "func_getxattr_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + + +namespace Func2 +{ + class Getxattr : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + Getxattr() + { + } + + Getxattr(const std::string &name_) + { + _impl = Func2::GetxattrFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_, + const char *attrname_, + char *attrval_, + const size_t attrvalsize_) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_, + attrname_, + attrval_, + attrvalsize_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string{p->name()}; + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::GetxattrFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_getxattr_base.hpp b/src/func_getxattr_base.hpp new file mode 100644 index 00000000..563ac6be --- /dev/null +++ b/src/func_getxattr_base.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "branches.hpp" + +#include "fs_path.hpp" + +namespace Func2 +{ + class GetxattrBase + { + public: + GetxattrBase() {} + ~GetxattrBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath, + const char *attrname, + char *attrval, + const size_t attrval_size) = 0; + }; +} diff --git a/src/func_getxattr_factory.cpp b/src/func_getxattr_factory.cpp new file mode 100644 index 00000000..416393f9 --- /dev/null +++ b/src/func_getxattr_factory.cpp @@ -0,0 +1,30 @@ +#include "func_getxattr_factory.hpp" + +#include "func_getxattr_ff.hpp" + +#include "policies.hpp" + + +bool +Func2::GetxattrFactory::valid(const std::string str_) +{ + if(str_ == "ff") + return true; + + if(Policies::Action::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::GetxattrFactory::make(const std::string_view str_) +{ + if(str_ == "ff") + return std::make_shared(); + + if(Policies::Action::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_getxattr_factory.hpp b/src/func_getxattr_factory.hpp new file mode 100644 index 00000000..0d8c7c87 --- /dev/null +++ b/src/func_getxattr_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_getxattr_base.hpp" + +namespace Func2 +{ + class GetxattrFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/func_getxattr_ff.cpp b/src/func_getxattr_ff.cpp new file mode 100644 index 00000000..17876887 --- /dev/null +++ b/src/func_getxattr_ff.cpp @@ -0,0 +1,35 @@ +#include "func_getxattr_ff.hpp" + +#include "error.hpp" +#include "fs_lgetxattr.hpp" + + +std::string_view +Func2::GetxattrFF::name() const +{ + return "ff"; +} + +int +Func2::GetxattrFF::operator()(const Branches &branches_, + const fs::path &fusepath_, + const char *attrname_, + char *attrval_, + const size_t attrvalsize_) +{ + int rv; + Err err; + fs::path fullpath; + + for(const auto &branch : branches_) + { + fullpath = branch.path / fusepath_; + + rv = fs::lgetxattr(fullpath,attrname_,attrval_,attrvalsize_); + if(rv >= 0) + return rv; + err = rv; + } + + return err; +} diff --git a/src/func_getxattr_ff.hpp b/src/func_getxattr_ff.hpp new file mode 100644 index 00000000..0f13577a --- /dev/null +++ b/src/func_getxattr_ff.hpp @@ -0,0 +1,21 @@ +#include "func_getxattr_base.hpp" + +namespace Func2 +{ + class GetxattrFF : public GetxattrBase + { + public: + GetxattrFF() {} + ~GetxattrFF() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + const char *attrname, + char *attrval, + const size_t attrvalsize); + }; +} diff --git a/src/func_ioctl.hpp b/src/func_ioctl.hpp new file mode 100644 index 00000000..96af1408 --- /dev/null +++ b/src/func_ioctl.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include "func_ioctl_base.hpp" +#include "func_ioctl_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + + +namespace Func2 +{ + class Ioctl : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + Ioctl() + { + } + + Ioctl(const std::string &name_) + { + _impl = Func2::IoctlFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_, + const mode_t mode_) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_, + mode_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string{p->name()}; + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::IoctlFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_ioctl_all.cpp b/src/func_ioctl_all.cpp new file mode 100644 index 00000000..b38922b7 --- /dev/null +++ b/src/func_ioctl_all.cpp @@ -0,0 +1,25 @@ +#include "func_ioctl_all.hpp" + +#include "error.hpp" +#include "fs_ioctl.hpp" + + +std::string_view +Func2::IoctlAll::name() const +{ + return "all"; +} + +int +Func2::IoctlAll::operator()(const Branches &branches_, + const fs::path &fusepath_) +{ + Err err; + fs::path fullpath; + + for(const auto &branch : branches_) + { + } + + return err; +} diff --git a/src/func_ioctl_all.hpp b/src/func_ioctl_all.hpp new file mode 100644 index 00000000..1090e1b8 --- /dev/null +++ b/src/func_ioctl_all.hpp @@ -0,0 +1,18 @@ +#include "func_ioctl_base.hpp" + +namespace Func2 +{ + class IoctlAll : public IoctlBase + { + public: + IoctlAll() {} + ~IoctlAll() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath); + }; +} diff --git a/src/func_ioctl_base.hpp b/src/func_ioctl_base.hpp new file mode 100644 index 00000000..7601c6f1 --- /dev/null +++ b/src/func_ioctl_base.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "branches.hpp" + +#include "fs_path.hpp" + +namespace Func2 +{ + class IoctlBase + { + public: + IoctlBase() {} + ~IoctlBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath) = 0; + }; +} diff --git a/src/func_ioctl_factory.cpp b/src/func_ioctl_factory.cpp new file mode 100644 index 00000000..98678859 --- /dev/null +++ b/src/func_ioctl_factory.cpp @@ -0,0 +1,30 @@ +#include "func_ioctl_factory.hpp" + +#include "func_ioctl_all.hpp" + +#include "policies.hpp" + + +bool +Func2::IoctlFactory::valid(const std::string str_) +{ + if(str_ == "all") + return true; + + if(Policies::Action::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::IoctlFactory::make(const std::string_view str_) +{ + if(str_ == "all") + return std::make_shared(); + + if(Policies::Action::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_ioctl_factory.hpp b/src/func_ioctl_factory.hpp new file mode 100644 index 00000000..353df41b --- /dev/null +++ b/src/func_ioctl_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_ioctl_base.hpp" + +namespace Func2 +{ + class IoctlFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/func_listxattr.hpp b/src/func_listxattr.hpp new file mode 100644 index 00000000..28e375e1 --- /dev/null +++ b/src/func_listxattr.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include "func_listxattr_base.hpp" +#include "func_listxattr_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + + +namespace Func2 +{ + class Listxattr : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + Listxattr() + { + } + + Listxattr(const std::string &name_) + { + _impl = Func2::ListxattrFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_, + const mode_t mode_) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_, + mode_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string{p->name()}; + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::ListxattrFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_listxattr_all.cpp b/src/func_listxattr_all.cpp new file mode 100644 index 00000000..8b894b3f --- /dev/null +++ b/src/func_listxattr_all.cpp @@ -0,0 +1,27 @@ +#include "func_listxattr_all.hpp" + +#include "error.hpp" +#include "fs_llistxattr.hpp" + + +std::string_view +Func2::ListxattrAll::name() const +{ + return "all"; +} + +int +Func2::ListxattrAll::operator()(const Branches &branches_, + const fs::path &fusepath_, + char *list_, + const size_t size_) +{ + Err err; + fs::path fullpath; + + for(const auto &branch : branches_) + { + } + + return err; +} diff --git a/src/func_listxattr_all.hpp b/src/func_listxattr_all.hpp new file mode 100644 index 00000000..ece815c9 --- /dev/null +++ b/src/func_listxattr_all.hpp @@ -0,0 +1,20 @@ +#include "func_listxattr_base.hpp" + +namespace Func2 +{ + class ListxattrAll : public ListxattrBase + { + public: + ListxattrAll() {} + ~ListxattrAll() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + char *list, + const size_t size); + }; +} diff --git a/src/func_listxattr_base.hpp b/src/func_listxattr_base.hpp new file mode 100644 index 00000000..8a4f2ddf --- /dev/null +++ b/src/func_listxattr_base.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "branches.hpp" + +#include "fs_path.hpp" + +namespace Func2 +{ + class ListxattrBase + { + public: + ListxattrBase() {} + ~ListxattrBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath, + char *list, + const size_t size) = 0; + }; +} diff --git a/src/func_listxattr_factory.cpp b/src/func_listxattr_factory.cpp new file mode 100644 index 00000000..8fb6b839 --- /dev/null +++ b/src/func_listxattr_factory.cpp @@ -0,0 +1,30 @@ +#include "func_listxattr_factory.hpp" + +#include "func_listxattr_all.hpp" + +#include "policies.hpp" + + +bool +Func2::ListxattrFactory::valid(const std::string str_) +{ + if(str_ == "all") + return true; + + if(Policies::Action::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::ListxattrFactory::make(const std::string_view str_) +{ + if(str_ == "all") + return std::make_shared(); + + if(Policies::Action::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_listxattr_factory.hpp b/src/func_listxattr_factory.hpp new file mode 100644 index 00000000..52b13f17 --- /dev/null +++ b/src/func_listxattr_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_listxattr_base.hpp" + +namespace Func2 +{ + class ListxattrFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/func_open.hpp b/src/func_open.hpp new file mode 100644 index 00000000..562d1550 --- /dev/null +++ b/src/func_open.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include "func_open_base.hpp" +#include "func_open_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + + +namespace Func2 +{ + class Open : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + Open() + { + } + + Open(const std::string &name_) + { + _impl = Func2::OpenFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_, + const mode_t mode_) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_, + mode_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string{p->name()}; + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::OpenFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_open_all.cpp b/src/func_open_all.cpp new file mode 100644 index 00000000..f539b60c --- /dev/null +++ b/src/func_open_all.cpp @@ -0,0 +1,27 @@ +#include "func_open_all.hpp" + +#include "error.hpp" +#include "fs_open.hpp" + + +std::string_view +Func2::OpenAll::name() const +{ + return "all"; +} + +int +Func2::OpenAll::operator()(const Branches &branches_, + const fs::path &fusepath_, + const mode_t mode_) +{ + Err err; + fs::path fullpath; + + for(const auto &branch : branches_) + { + + } + + return err; +} diff --git a/src/func_open_all.hpp b/src/func_open_all.hpp new file mode 100644 index 00000000..c2af7990 --- /dev/null +++ b/src/func_open_all.hpp @@ -0,0 +1,19 @@ +#include "func_open_base.hpp" + +namespace Func2 +{ + class OpenAll : public OpenBase + { + public: + OpenAll() {} + ~OpenAll() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + const mode_t mode); + }; +} diff --git a/src/func_open_base.hpp b/src/func_open_base.hpp new file mode 100644 index 00000000..1a7a56e8 --- /dev/null +++ b/src/func_open_base.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "branches.hpp" + +#include "fs_path.hpp" + +namespace Func2 +{ + class OpenBase + { + public: + OpenBase() {} + ~OpenBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath, + const mode_t mode) = 0; + }; +} diff --git a/src/func_open_factory.cpp b/src/func_open_factory.cpp new file mode 100644 index 00000000..c573923e --- /dev/null +++ b/src/func_open_factory.cpp @@ -0,0 +1,30 @@ +#include "func_open_factory.hpp" + +#include "func_open_all.hpp" + +#include "policies.hpp" + + +bool +Func2::OpenFactory::valid(const std::string str_) +{ + if(str_ == "all") + return true; + + if(Policies::Action::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::OpenFactory::make(const std::string_view str_) +{ + if(str_ == "all") + return std::make_shared(); + + if(Policies::Action::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_open_factory.hpp b/src/func_open_factory.hpp new file mode 100644 index 00000000..c36164e9 --- /dev/null +++ b/src/func_open_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_open_base.hpp" + +namespace Func2 +{ + class OpenFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/func_readlink.hpp b/src/func_readlink.hpp new file mode 100644 index 00000000..67c1b63b --- /dev/null +++ b/src/func_readlink.hpp @@ -0,0 +1,75 @@ +#pragma once + +#include "func_readlink_base.hpp" +#include "func_readlink_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + + +namespace Func2 +{ + class Readlink : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + Readlink() + { + } + + Readlink(const std::string &name_) + { + _impl = Func2::ReadlinkFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_, + char *buf_, + const size_t bufsize_) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_, + buf_, + bufsize_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string{p->name()}; + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::ReadlinkFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_readlink_all.cpp b/src/func_readlink_all.cpp new file mode 100644 index 00000000..e4347dc4 --- /dev/null +++ b/src/func_readlink_all.cpp @@ -0,0 +1,28 @@ +#include "func_readlink_all.hpp" + +#include "error.hpp" +#include "fs_readlink.hpp" + + +std::string_view +Func2::ReadlinkAll::name() const +{ + return "all"; +} + +int +Func2::ReadlinkAll::operator()(const Branches &branches_, + const fs::path &fusepath_, + char *buf_, + const size_t bufsize_) +{ + Err err; + fs::path fullpath; + + for(const auto &branch : branches_) + { + + } + + return err; +} diff --git a/src/func_readlink_all.hpp b/src/func_readlink_all.hpp new file mode 100644 index 00000000..c903b25e --- /dev/null +++ b/src/func_readlink_all.hpp @@ -0,0 +1,20 @@ +#include "func_readlink_base.hpp" + +namespace Func2 +{ + class ReadlinkAll : public ReadlinkBase + { + public: + ReadlinkAll() {} + ~ReadlinkAll() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + char *buf, + const size_t bufsize); + }; +} diff --git a/src/func_readlink_base.hpp b/src/func_readlink_base.hpp new file mode 100644 index 00000000..faaac669 --- /dev/null +++ b/src/func_readlink_base.hpp @@ -0,0 +1,24 @@ +#pragma once + +#include "branches.hpp" + +#include "fs_path.hpp" + +namespace Func2 +{ + class ReadlinkBase + { + public: + ReadlinkBase() {} + ~ReadlinkBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath, + char *buf, + const size_t bufsize) = 0; + }; +} diff --git a/src/func_readlink_factory.cpp b/src/func_readlink_factory.cpp new file mode 100644 index 00000000..bbcfcb62 --- /dev/null +++ b/src/func_readlink_factory.cpp @@ -0,0 +1,30 @@ +#include "func_readlink_factory.hpp" + +#include "func_readlink_all.hpp" + +#include "policies.hpp" + + +bool +Func2::ReadlinkFactory::valid(const std::string str_) +{ + if(str_ == "all") + return true; + + if(Policies::Action::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::ReadlinkFactory::make(const std::string_view str_) +{ + if(str_ == "all") + return std::make_shared(); + + if(Policies::Action::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_readlink_factory.hpp b/src/func_readlink_factory.hpp new file mode 100644 index 00000000..bdc833a3 --- /dev/null +++ b/src/func_readlink_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_readlink_base.hpp" + +namespace Func2 +{ + class ReadlinkFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/func_removexattr.hpp b/src/func_removexattr.hpp new file mode 100644 index 00000000..c8ed340f --- /dev/null +++ b/src/func_removexattr.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include "func_removexattr_base.hpp" +#include "func_removexattr_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + + +namespace Func2 +{ + class Removexattr : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + Removexattr() + { + } + + Removexattr(const std::string &name_) + { + _impl = Func2::RemovexattrFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_, + const char *attrname_) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_, + attrname_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string{p->name()}; + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::RemovexattrFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_removexattr_all.cpp b/src/func_removexattr_all.cpp new file mode 100644 index 00000000..2e92478f --- /dev/null +++ b/src/func_removexattr_all.cpp @@ -0,0 +1,35 @@ +#include "func_removexattr_all.hpp" + +#include "error.hpp" +#include "fs_lremovexattr.hpp" + + +std::string_view +Func2::RemovexattrAll::name() const +{ + return "all"; +} + +int +Func2::RemovexattrAll::operator()(const Branches &branches_, + const fs::path &fusepath_, + const char *attrname_) +{ + Err err; + fs::path fullpath; + + for(const auto &branch : branches_) + { + if(branch.ro()) + { + err = -EROFS; + continue; + } + + fullpath = branch.path / fusepath_; + + err = fs::lremovexattr(fullpath,attrname_); + } + + return err; +} diff --git a/src/func_removexattr_all.hpp b/src/func_removexattr_all.hpp new file mode 100644 index 00000000..560ed3dd --- /dev/null +++ b/src/func_removexattr_all.hpp @@ -0,0 +1,19 @@ +#include "func_removexattr_base.hpp" + +namespace Func2 +{ + class RemovexattrAll : public RemovexattrBase + { + public: + RemovexattrAll() {} + ~RemovexattrAll() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + const char *attrname); + }; +} diff --git a/src/func_removexattr_base.hpp b/src/func_removexattr_base.hpp new file mode 100644 index 00000000..a9d6aa8f --- /dev/null +++ b/src/func_removexattr_base.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "branches.hpp" + +#include "fs_path.hpp" + +namespace Func2 +{ + class RemovexattrBase + { + public: + RemovexattrBase() {} + ~RemovexattrBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath, + const char *attrname) = 0; + }; +} diff --git a/src/func_removexattr_factory.cpp b/src/func_removexattr_factory.cpp new file mode 100644 index 00000000..dc2e010b --- /dev/null +++ b/src/func_removexattr_factory.cpp @@ -0,0 +1,30 @@ +#include "func_removexattr_factory.hpp" + +#include "func_removexattr_all.hpp" + +#include "policies.hpp" + + +bool +Func2::RemovexattrFactory::valid(const std::string str_) +{ + if(str_ == "all") + return true; + + if(Policies::Action::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::RemovexattrFactory::make(const std::string_view str_) +{ + if(str_ == "all") + return std::make_shared(); + + if(Policies::Action::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_removexattr_factory.hpp b/src/func_removexattr_factory.hpp new file mode 100644 index 00000000..6057550f --- /dev/null +++ b/src/func_removexattr_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_removexattr_base.hpp" + +namespace Func2 +{ + class RemovexattrFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/func_rmdir.hpp b/src/func_rmdir.hpp new file mode 100644 index 00000000..64282a3f --- /dev/null +++ b/src/func_rmdir.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include "func_rmdir_base.hpp" +#include "func_rmdir_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + + +namespace Func2 +{ + class Rmdir : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + Rmdir() + { + } + + Rmdir(const std::string &name_) + { + _impl = Func2::RmdirFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string{p->name()}; + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::RmdirFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_rmdir_all.cpp b/src/func_rmdir_all.cpp new file mode 100644 index 00000000..b88e70bc --- /dev/null +++ b/src/func_rmdir_all.cpp @@ -0,0 +1,50 @@ +#include "func_rmdir_all.hpp" + +#include "config.hpp" +#include "error.hpp" +#include "fs_rmdir.hpp" +#include "fs_unlink.hpp" + + +std::string_view +Func2::RmdirAll::name() const +{ + return "all"; +} + +static +int +_should_unlink(int rv_) + +{ + return ((rv_ == -ENOTDIR) && + (cfg.follow_symlinks != FollowSymlinks::ENUM::NEVER)); +} + +int +Func2::RmdirAll::operator()(const Branches &branches_, + const fs::path &fusepath_) +{ + Err err; + fs::path fullpath; + + for(const auto &branch : branches_) + { + int rv; + + if(branch.ro()) + { + err = -EROFS; + continue; + } + + fullpath = branch.path / fusepath_; + + rv = fs::rmdir(fullpath); + if(::_should_unlink(rv)) + rv = fs::unlink(fullpath); + err = rv; + } + + return err; +} diff --git a/src/func_rmdir_all.hpp b/src/func_rmdir_all.hpp new file mode 100644 index 00000000..9cd573c3 --- /dev/null +++ b/src/func_rmdir_all.hpp @@ -0,0 +1,18 @@ +#include "func_rmdir_base.hpp" + +namespace Func2 +{ + class RmdirAll : public RmdirBase + { + public: + RmdirAll() {} + ~RmdirAll() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath); + }; +} diff --git a/src/func_rmdir_base.hpp b/src/func_rmdir_base.hpp new file mode 100644 index 00000000..8aaf5748 --- /dev/null +++ b/src/func_rmdir_base.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "branches.hpp" + +#include "fs_path.hpp" + +namespace Func2 +{ + class RmdirBase + { + public: + RmdirBase() {} + ~RmdirBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath) = 0; + }; +} diff --git a/src/func_rmdir_factory.cpp b/src/func_rmdir_factory.cpp new file mode 100644 index 00000000..dbb48515 --- /dev/null +++ b/src/func_rmdir_factory.cpp @@ -0,0 +1,30 @@ +#include "func_rmdir_factory.hpp" + +#include "func_rmdir_all.hpp" + +#include "policies.hpp" + + +bool +Func2::RmdirFactory::valid(const std::string str_) +{ + if(str_ == "all") + return true; + + if(Policies::Action::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::RmdirFactory::make(const std::string_view str_) +{ + if(str_ == "all") + return std::make_shared(); + + if(Policies::Action::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_rmdir_factory.hpp b/src/func_rmdir_factory.hpp new file mode 100644 index 00000000..962cc470 --- /dev/null +++ b/src/func_rmdir_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_rmdir_base.hpp" + +namespace Func2 +{ + class RmdirFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/func_setxattr.hpp b/src/func_setxattr.hpp new file mode 100644 index 00000000..8b572b75 --- /dev/null +++ b/src/func_setxattr.hpp @@ -0,0 +1,79 @@ +#pragma once + +#include "func_setxattr_base.hpp" +#include "func_setxattr_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + + +namespace Func2 +{ + class Setxattr : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + Setxattr() + { + } + + Setxattr(const std::string &name_) + { + _impl = Func2::SetxattrFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_, + const char *attrname_, + const char *attrval_, + const size_t attrvalsize_, + const int flags_) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_, + attrname_, + attrval_, + attrvalsize_, + flags_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string{p->name()}; + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::SetxattrFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_setxattr_all.cpp b/src/func_setxattr_all.cpp new file mode 100644 index 00000000..f0cadd26 --- /dev/null +++ b/src/func_setxattr_all.cpp @@ -0,0 +1,38 @@ +#include "func_setxattr_all.hpp" + +#include "error.hpp" +#include "fs_lsetxattr.hpp" + + +std::string_view +Func2::SetxattrAll::name() const +{ + return "all"; +} + +int +Func2::SetxattrAll::operator()(const Branches &branches_, + const fs::path &fusepath_, + const char *attrname_, + const char *attrval_, + size_t attrvalsize_, + int flags_) +{ + Err err; + fs::path fullpath; + + for(const auto &branch : branches_) + { + if(branch.ro()) + { + err = -EROFS; + continue; + } + + fullpath = branch.path / fusepath_; + + err = fs::lsetxattr(fullpath,attrname_,attrval_,attrvalsize_,flags_); + } + + return err; +} diff --git a/src/func_setxattr_all.hpp b/src/func_setxattr_all.hpp new file mode 100644 index 00000000..e89890dd --- /dev/null +++ b/src/func_setxattr_all.hpp @@ -0,0 +1,22 @@ +#include "func_setxattr_base.hpp" + +namespace Func2 +{ + class SetxattrAll : public SetxattrBase + { + public: + SetxattrAll() {} + ~SetxattrAll() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + const char *attrname_, + const char *attrval_, + size_t attrvalsize_, + int flags_); + }; +} diff --git a/src/func_setxattr_base.hpp b/src/func_setxattr_base.hpp new file mode 100644 index 00000000..5058a7e4 --- /dev/null +++ b/src/func_setxattr_base.hpp @@ -0,0 +1,26 @@ +#pragma once + +#include "branches.hpp" + +#include "fs_path.hpp" + +namespace Func2 +{ + class SetxattrBase + { + public: + SetxattrBase() {} + ~SetxattrBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath, + const char *attrname, + const char *attrval, + size_t attrvalsize, + int flags) = 0; + }; +} diff --git a/src/func_setxattr_factory.cpp b/src/func_setxattr_factory.cpp new file mode 100644 index 00000000..4eacb934 --- /dev/null +++ b/src/func_setxattr_factory.cpp @@ -0,0 +1,30 @@ +#include "func_setxattr_factory.hpp" + +#include "func_setxattr_all.hpp" + +#include "policies.hpp" + + +bool +Func2::SetxattrFactory::valid(const std::string str_) +{ + if(str_ == "all") + return true; + + if(Policies::Action::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::SetxattrFactory::make(const std::string_view str_) +{ + if(str_ == "all") + return std::make_shared(); + + if(Policies::Action::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_setxattr_factory.hpp b/src/func_setxattr_factory.hpp new file mode 100644 index 00000000..99559f5d --- /dev/null +++ b/src/func_setxattr_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_setxattr_base.hpp" + +namespace Func2 +{ + class SetxattrFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/func_statx.hpp b/src/func_statx.hpp new file mode 100644 index 00000000..a3a0b87f --- /dev/null +++ b/src/func_statx.hpp @@ -0,0 +1,81 @@ +#pragma once + +#include "func_statx_base.hpp" +#include "func_statx_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + + +namespace Func2 +{ + class Statx : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + Statx() + { + } + + Statx(const std::string &name_) + { + _impl = Func2::StatxFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_, + const u32 flags_, + const u32 mask_, + struct fuse_statx *st_, + const FollowSymlinksEnum follow_symlinks_, + const s64 symlinkify_timeout_) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_, + flags_, + mask_, + st_, + follow_symlinks_, + symlinkify_timeout_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string(p->name()); + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::StatxFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_statx_base.hpp b/src/func_statx_base.hpp new file mode 100644 index 00000000..872ba349 --- /dev/null +++ b/src/func_statx_base.hpp @@ -0,0 +1,38 @@ +#pragma once + +#include "follow_symlinks_enum.hpp" + +#include "fs_path.hpp" +#include "branches.hpp" +#include "int_types.h" + +#include "fuse.h" + +#include + +#include +#include +#include + + +namespace Func2 +{ + class StatxBase + { + public: + StatxBase() {} + ~StatxBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath, + const u32 flags_, + const u32 mask_, + struct fuse_statx *st, + const FollowSymlinksEnum follow_symlinks, + const s64 symlinkify_timeout) = 0; + }; +} diff --git a/src/func_statx_combine.cpp b/src/func_statx_combine.cpp new file mode 100644 index 00000000..a9f3a05a --- /dev/null +++ b/src/func_statx_combine.cpp @@ -0,0 +1,79 @@ +#include "func_statx_combine.hpp" + +#include "fs_inode.hpp" +#include "fs_statx.hpp" +#include "symlinkify.hpp" +#include "timespec_utils.hpp" + + +std::string_view +Func2::StatxCombine::name() const +{ + return "combine"; +} + +int +Func2::StatxCombine::operator()(const Branches &branches_, + const fs::path &fusepath_, + const u32 flags_, + const u32 mask_, + struct fuse_statx *st_, + const FollowSymlinksEnum follow_symlinks_, + const s64 symlinkify_timeout_) +{ + int rv; + fs::path fullpath; + const Branch *first_branch; + + first_branch = nullptr; + for(const auto &branch : branches_) + { + struct fuse_statx tmp_st; + + fullpath = branch.path / fusepath_; + rv = fs::statx(AT_FDCWD, + fullpath, + flags_|AT_SYMLINK_NOFOLLOW, + mask_, + &tmp_st, + follow_symlinks_); + if(rv < 0) + continue; + + if(!first_branch) + { + *st_ = tmp_st; + first_branch = &branch; + continue; + } + + // This upgrades the uid:gid because mergerfs now does most + // file interaction as root and relies on `default_permissions` + // to manage permissions. Want to ensure that root owned files + // can't be changed so we treat them all as root owned. + if(tmp_st.uid == 0) + st_->uid = 0; + if(tmp_st.gid == 0) + st_->gid = 0; + st_->atime = TimeSpec::newest(st_->atime,tmp_st.atime); + st_->ctime = TimeSpec::newest(st_->ctime,tmp_st.ctime); + st_->mtime = TimeSpec::newest(st_->mtime,tmp_st.mtime); + st_->btime = TimeSpec::newest(st_->btime,tmp_st.btime); + st_->nlink += tmp_st.nlink; + } + + if(!first_branch) + return -ENOENT; + + if(symlinkify_timeout_ >= 0) + { + fullpath = first_branch->path / fusepath_; + symlinkify::convert_if_can_be_symlink(fullpath, + st_, + symlinkify_timeout_); + } + + fs::inode::calc(first_branch->path,fusepath_,st_); + + return 0; +} diff --git a/src/func_statx_combine.hpp b/src/func_statx_combine.hpp new file mode 100644 index 00000000..ef81fc69 --- /dev/null +++ b/src/func_statx_combine.hpp @@ -0,0 +1,23 @@ +#include "func_statx_base.hpp" + +namespace Func2 +{ + class StatxCombine : public StatxBase + { + public: + StatxCombine() {} + ~StatxCombine() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + const u32 flags_, + const u32 mask_, + struct fuse_statx *st, + const FollowSymlinksEnum follow_symlinks, + const s64 symlinkify_timeout); + }; +} diff --git a/src/func_statx_factory.cpp b/src/func_statx_factory.cpp new file mode 100644 index 00000000..5d9397f5 --- /dev/null +++ b/src/func_statx_factory.cpp @@ -0,0 +1,39 @@ +#include "func_statx_factory.hpp" + +#include "func_statx_combine.hpp" +#include "func_statx_ff.hpp" +#include "func_statx_newest.hpp" + +#include "policies.hpp" + +bool +Func2::StatxFactory::valid(const std::string str_) +{ + if(str_ == "combined") + return true; + if(str_ == "ff") + return true; + if(str_ == "newest") + return true; + + if(Policies::Search::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::StatxFactory::make(const std::string_view str_) +{ + if(str_ == "combine") + return std::make_shared(); + if(str_ == "ff") + return std::make_shared(); + if(str_ == "newest") + return std::make_shared(); + + if(Policies::Search::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_statx_factory.hpp b/src/func_statx_factory.hpp new file mode 100644 index 00000000..50ae11e6 --- /dev/null +++ b/src/func_statx_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_statx_base.hpp" + +namespace Func2 +{ + class StatxFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/func_statx_ff.cpp b/src/func_statx_ff.cpp new file mode 100644 index 00000000..f28170b9 --- /dev/null +++ b/src/func_statx_ff.cpp @@ -0,0 +1,48 @@ +#include "func_statx_ff.hpp" + +#include "fs_statx.hpp" +#include "fs_inode.hpp" +#include "symlinkify.hpp" + + +std::string_view +Func2::StatxFF::name() const +{ + return "ff"; +} + +int +Func2::StatxFF::operator()(const Branches &branches_, + const fs::path &fusepath_, + const u32 flags_, + const u32 mask_, + struct fuse_statx *st_, + const FollowSymlinksEnum follow_symlinks_, + const s64 symlinkify_timeout_) +{ + int rv; + fs::path fullpath; + + for(const auto &branch : branches_) + { + fullpath = branch.path / fusepath_; + rv = fs::statx(AT_FDCWD, + fullpath, + flags_|AT_SYMLINK_NOFOLLOW, + mask_, + st_, + follow_symlinks_); + if(rv < 0) + continue; + + symlinkify::convert_if_can_be_symlink(fullpath, + st_, + symlinkify_timeout_); + + fs::inode::calc(branch.path,fusepath_,st_); + + return rv; + } + + return -ENOENT; +} diff --git a/src/func_statx_ff.hpp b/src/func_statx_ff.hpp new file mode 100644 index 00000000..f216a3bf --- /dev/null +++ b/src/func_statx_ff.hpp @@ -0,0 +1,25 @@ +#pragma once + +#include "func_statx_base.hpp" + +namespace Func2 +{ + class StatxFF : public StatxBase + { + public: + StatxFF() {} + ~StatxFF() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + const u32 flags_, + const u32 mask_, + struct fuse_statx *st, + const FollowSymlinksEnum follow_symlinks, + const s64 symlinkify_timeout); + }; +} diff --git a/src/func_statx_newest.cpp b/src/func_statx_newest.cpp new file mode 100644 index 00000000..57a650cc --- /dev/null +++ b/src/func_statx_newest.cpp @@ -0,0 +1,64 @@ +#include "func_statx_newest.hpp" + +#include "fs_statx.hpp" +#include "fs_inode.hpp" +#include "symlinkify.hpp" +#include "timespec_utils.hpp" + + +std::string_view +Func2::StatxNewest::name() const +{ + return "newest"; +} + +int +Func2::StatxNewest::operator()(const Branches &branches_, + const fs::path &fusepath_, + const u32 flags_, + const u32 mask_, + struct fuse_statx *st_, + const FollowSymlinksEnum follow_symlinks_, + const s64 symlinkify_timeout_) +{ + int rv; + fs::path fullpath; + const Branch *newest_branch; + + newest_branch = nullptr; + for(const auto &branch : branches_) + { + struct fuse_statx tmp_st; + + fullpath = branch.path / fusepath_; + rv = fs::statx(AT_FDCWD, + fullpath, + flags_|AT_SYMLINK_NOFOLLOW, + mask_, + &tmp_st, + follow_symlinks_); + if(rv < 0) + continue; + + if(not TimeSpec::is_newer(tmp_st.mtime,st_->mtime)) + continue; + + *st_ = tmp_st; + newest_branch = &branch; + } + + if(!newest_branch) + return -ENOENT; + + if(symlinkify_timeout_ >= 0) + { + fullpath = newest_branch->path / fusepath_; + symlinkify::convert_if_can_be_symlink(fullpath, + st_, + symlinkify_timeout_); + } + + fs::inode::calc(newest_branch->path,fusepath_,st_); + + return 0; +} diff --git a/src/func_statx_newest.hpp b/src/func_statx_newest.hpp new file mode 100644 index 00000000..220ed7bf --- /dev/null +++ b/src/func_statx_newest.hpp @@ -0,0 +1,23 @@ +#include "func_statx_base.hpp" + +namespace Func2 +{ + class StatxNewest : public StatxBase + { + public: + StatxNewest() {} + ~StatxNewest() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + const u32 flags_, + const u32 mask_, + struct fuse_statx *st, + const FollowSymlinksEnum follow_symlinks, + const s64 symlinkify_timeout); + }; +} diff --git a/src/func_truncate.hpp b/src/func_truncate.hpp new file mode 100644 index 00000000..847a6ace --- /dev/null +++ b/src/func_truncate.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include "func_truncate_base.hpp" +#include "func_truncate_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + + +namespace Func2 +{ + class Truncate : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + Truncate() + { + } + + Truncate(const std::string &name_) + { + _impl = Func2::TruncateFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_, + const off_t size_) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_, + size_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string{p->name()}; + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::TruncateFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_truncate_all.cpp b/src/func_truncate_all.cpp new file mode 100644 index 00000000..7300cfd0 --- /dev/null +++ b/src/func_truncate_all.cpp @@ -0,0 +1,35 @@ +#include "func_truncate_all.hpp" + +#include "error.hpp" +#include "fs_truncate.hpp" + + +std::string_view +Func2::TruncateAll::name() const +{ + return "all"; +} + +int +Func2::TruncateAll::operator()(const Branches &branches_, + const fs::path &fusepath_, + const off_t size_) +{ + Err err; + fs::path fullpath; + + for(const auto &branch : branches_) + { + if(branch.ro()) + { + err = -EROFS; + continue; + } + + fullpath = branch.path / fusepath_; + + err = fs::truncate(fullpath,size_); + } + + return err; +} diff --git a/src/func_truncate_all.hpp b/src/func_truncate_all.hpp new file mode 100644 index 00000000..76fc7d49 --- /dev/null +++ b/src/func_truncate_all.hpp @@ -0,0 +1,19 @@ +#include "func_truncate_base.hpp" + +namespace Func2 +{ + class TruncateAll : public TruncateBase + { + public: + TruncateAll() {} + ~TruncateAll() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + const off_t size_); + }; +} diff --git a/src/func_truncate_base.hpp b/src/func_truncate_base.hpp new file mode 100644 index 00000000..9a818c67 --- /dev/null +++ b/src/func_truncate_base.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "branches.hpp" + +#include "fs_path.hpp" + +namespace Func2 +{ + class TruncateBase + { + public: + TruncateBase() {} + ~TruncateBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath, + const off_t size) = 0; + }; +} diff --git a/src/func_truncate_factory.cpp b/src/func_truncate_factory.cpp new file mode 100644 index 00000000..077076f0 --- /dev/null +++ b/src/func_truncate_factory.cpp @@ -0,0 +1,30 @@ +#include "func_truncate_factory.hpp" + +#include "func_truncate_all.hpp" + +#include "policies.hpp" + + +bool +Func2::TruncateFactory::valid(const std::string str_) +{ + if(str_ == "all") + return true; + + if(Policies::Action::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::TruncateFactory::make(const std::string_view str_) +{ + if(str_ == "all") + return std::make_shared(); + + if(Policies::Action::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_truncate_factory.hpp b/src/func_truncate_factory.hpp new file mode 100644 index 00000000..92a03fc0 --- /dev/null +++ b/src/func_truncate_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_truncate_base.hpp" + +namespace Func2 +{ + class TruncateFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/func_unlink.hpp b/src/func_unlink.hpp new file mode 100644 index 00000000..39611059 --- /dev/null +++ b/src/func_unlink.hpp @@ -0,0 +1,71 @@ +#pragma once + +#include "func_unlink_base.hpp" +#include "func_unlink_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + + +namespace Func2 +{ + class Unlink : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + Unlink() + { + } + + Unlink(const std::string &name_) + { + _impl = Func2::UnlinkFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string{p->name()}; + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::UnlinkFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_unlink_all.cpp b/src/func_unlink_all.cpp new file mode 100644 index 00000000..5d73a186 --- /dev/null +++ b/src/func_unlink_all.cpp @@ -0,0 +1,34 @@ +#include "func_unlink_all.hpp" + +#include "error.hpp" +#include "fs_unlink.hpp" + + +std::string_view +Func2::UnlinkAll::name() const +{ + return "all"; +} + +int +Func2::UnlinkAll::operator()(const Branches &branches_, + const fs::path &fusepath_) +{ + Err err; + fs::path fullpath; + + for(const auto &branch : branches_) + { + if(branch.ro()) + { + err = -EROFS; + continue; + } + + fullpath = branch.path / fusepath_; + + err = fs::unlink(fullpath); + } + + return err; +} diff --git a/src/func_unlink_all.hpp b/src/func_unlink_all.hpp new file mode 100644 index 00000000..16943dcd --- /dev/null +++ b/src/func_unlink_all.hpp @@ -0,0 +1,18 @@ +#include "func_unlink_base.hpp" + +namespace Func2 +{ + class UnlinkAll : public UnlinkBase + { + public: + UnlinkAll() {} + ~UnlinkAll() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath); + }; +} diff --git a/src/func_unlink_base.hpp b/src/func_unlink_base.hpp new file mode 100644 index 00000000..9737866f --- /dev/null +++ b/src/func_unlink_base.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include "branches.hpp" + +#include "fs_path.hpp" + +namespace Func2 +{ + class UnlinkBase + { + public: + UnlinkBase() {} + ~UnlinkBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath) = 0; + }; +} diff --git a/src/func_unlink_factory.cpp b/src/func_unlink_factory.cpp new file mode 100644 index 00000000..03ee7d3d --- /dev/null +++ b/src/func_unlink_factory.cpp @@ -0,0 +1,30 @@ +#include "func_unlink_factory.hpp" + +#include "func_unlink_all.hpp" + +#include "policies.hpp" + + +bool +Func2::UnlinkFactory::valid(const std::string str_) +{ + if(str_ == "all") + return true; + + if(Policies::Action::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::UnlinkFactory::make(const std::string_view str_) +{ + if(str_ == "all") + return std::make_shared(); + + if(Policies::Action::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_unlink_factory.hpp b/src/func_unlink_factory.hpp new file mode 100644 index 00000000..1d8058e0 --- /dev/null +++ b/src/func_unlink_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_unlink_base.hpp" + +namespace Func2 +{ + class UnlinkFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/func_utimens.hpp b/src/func_utimens.hpp new file mode 100644 index 00000000..b5fcf9c7 --- /dev/null +++ b/src/func_utimens.hpp @@ -0,0 +1,73 @@ +#pragma once + +#include "func_utimens_base.hpp" +#include "func_utimens_factory.hpp" + +#include "tofrom_string.hpp" + +#include "fmt/core.h" + +#include + +#include + + +namespace Func2 +{ + class Utimens : public ToFromString + { + private: + std::shared_ptr _impl; + + public: + Utimens() + { + } + + Utimens(const std::string &name_) + { + _impl = Func2::UtimensFactory::make(name_); + assert(_impl); + } + + public: + int + operator()(const Branches &branches_, + const fs::path &fusepath_, + const timespec times_[2]) + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return (*p)(branches_, + fusepath_, + times_); + } + + public: + std::string + to_string() const + { + std::shared_ptr p; + + p = std::atomic_load(&_impl); + + return std::string{p->name()}; + } + + int + from_string(const std::string_view str_) + { + std::shared_ptr p; + + p = Func2::UtimensFactory::make(str_); + if(!p) + return -EINVAL; + + _impl = std::atomic_load(&p); + + return 0; + } + }; +} diff --git a/src/func_utimens_all.cpp b/src/func_utimens_all.cpp new file mode 100644 index 00000000..5b77ab40 --- /dev/null +++ b/src/func_utimens_all.cpp @@ -0,0 +1,35 @@ +#include "func_utimens_all.hpp" + +#include "error.hpp" +#include "fs_lutimens.hpp" + + +std::string_view +Func2::UtimensAll::name() const +{ + return "all"; +} + +int +Func2::UtimensAll::operator()(const Branches &branches_, + const fs::path &fusepath_, + const timespec times_[2]) +{ + Err err; + fs::path fullpath; + + for(const auto &branch : branches_) + { + if(branch.ro()) + { + err = -EROFS; + continue; + } + + fullpath = branch.path / fusepath_; + + err = fs::lutimens(fullpath,times_); + } + + return err; +} diff --git a/src/func_utimens_all.hpp b/src/func_utimens_all.hpp new file mode 100644 index 00000000..6d02a6db --- /dev/null +++ b/src/func_utimens_all.hpp @@ -0,0 +1,19 @@ +#include "func_utimens_base.hpp" + +namespace Func2 +{ + class UtimensAll : public UtimensBase + { + public: + UtimensAll() {} + ~UtimensAll() {} + + public: + std::string_view name() const; + + public: + int operator()(const Branches &branches, + const fs::path &fusepath, + const timespec times_[2]); + }; +} diff --git a/src/func_utimens_base.hpp b/src/func_utimens_base.hpp new file mode 100644 index 00000000..9f118439 --- /dev/null +++ b/src/func_utimens_base.hpp @@ -0,0 +1,23 @@ +#pragma once + +#include "branches.hpp" + +#include "fs_path.hpp" + +namespace Func2 +{ + class UtimensBase + { + public: + UtimensBase() {} + ~UtimensBase() {} + + public: + virtual std::string_view name() const = 0; + + public: + virtual int operator()(const Branches &branches, + const fs::path &fusepath, + const timespec times_[2]) = 0; + }; +} diff --git a/src/func_utimens_factory.cpp b/src/func_utimens_factory.cpp new file mode 100644 index 00000000..b2a9b313 --- /dev/null +++ b/src/func_utimens_factory.cpp @@ -0,0 +1,30 @@ +#include "func_utimens_factory.hpp" + +#include "func_utimens_all.hpp" + +#include "policies.hpp" + + +bool +Func2::UtimensFactory::valid(const std::string str_) +{ + if(str_ == "all") + return true; + + if(Policies::Action::find(str_)) + return true; + + return false; +} + +std::shared_ptr +Func2::UtimensFactory::make(const std::string_view str_) +{ + if(str_ == "all") + return std::make_shared(); + + if(Policies::Action::find(str_)) + return std::make_shared(); + + return {}; +} diff --git a/src/func_utimens_factory.hpp b/src/func_utimens_factory.hpp new file mode 100644 index 00000000..62fd94c4 --- /dev/null +++ b/src/func_utimens_factory.hpp @@ -0,0 +1,13 @@ +#pragma once + +#include "func_utimens_base.hpp" + +namespace Func2 +{ + class UtimensFactory + { + public: + static bool valid(const std::string str); + static std::shared_ptr make(const std::string_view str); + }; +} diff --git a/src/fuse_chmod.cpp b/src/fuse_chmod.cpp index 79a8b1be..3eceef7d 100644 --- a/src/fuse_chmod.cpp +++ b/src/fuse_chmod.cpp @@ -17,90 +17,7 @@ #include "fuse_chmod.hpp" #include "config.hpp" -#include "errno.hpp" -#include "fs_lchmod.hpp" -#include "fs_path.hpp" -#include "policy_rv.hpp" -#include "ugid.hpp" -#include "fuse.h" - -#include -#include - - -static -void -_chmod_loop_core(const std::string &basepath_, - const fs::path &fusepath_, - const mode_t mode_, - PolicyRV *prv_) -{ - fs::path fullpath; - - fullpath = basepath_ / fusepath_; - - errno = 0; - fs::lchmod(fullpath,mode_); - - prv_->insert(errno,basepath_); -} - -static -void -_chmod_loop(const std::vector &branches_, - const fs::path &fusepath_, - const mode_t mode_, - PolicyRV *prv_) -{ - for(auto &branch : branches_) - { - ::_chmod_loop_core(branch->path,fusepath_,mode_,prv_); - } -} - -static -int -_chmod(const Policy::Action &actionFunc_, - const Policy::Search &searchFunc_, - const Branches &branches_, - const fs::path &fusepath_, - const mode_t mode_) -{ - int rv; - PolicyRV prv; - std::vector branches; - - rv = actionFunc_(branches_,fusepath_,branches); - if(rv < 0) - return rv; - - ::_chmod_loop(branches,fusepath_,mode_,&prv); - if(prv.errors.empty()) - return 0; - if(prv.successes.empty()) - return prv.errors[0].rv; - - branches.clear(); - rv = searchFunc_(branches_,fusepath_,branches); - if(rv < 0) - return rv; - - return prv.get_error(branches[0]->path); -} - -static -int -_chmod(const fs::path &fusepath_, - const mode_t mode_) -{ - - return ::_chmod(cfg.func.chmod.policy, - cfg.func.getattr.policy, - cfg.branches, - fusepath_, - mode_); -} int FUSE::chmod(const fuse_req_ctx_t *ctx_, @@ -109,5 +26,7 @@ FUSE::chmod(const fuse_req_ctx_t *ctx_, { const fs::path fusepath{fusepath_}; - return ::_chmod(fusepath,mode_); + return cfg.chmod(cfg.branches, + fusepath_, + mode_); } diff --git a/src/fuse_chown.cpp b/src/fuse_chown.cpp index 2abb37b6..7890f02a 100644 --- a/src/fuse_chown.cpp +++ b/src/fuse_chown.cpp @@ -17,81 +17,9 @@ #include "fuse_chown.hpp" #include "config.hpp" -#include "errno.hpp" -#include "fs_lchown.hpp" -#include "fs_path.hpp" -#include "policy_rv.hpp" -#include "ugid.hpp" #include "fuse.h" -#include -#include - - -static -void -_chown_loop_core(const fs::path &basepath_, - const fs::path &fusepath_, - const uid_t uid_, - const gid_t gid_, - PolicyRV *prv_) -{ - fs::path fullpath; - - fullpath = basepath_ / fusepath_; - - errno = 0; - fs::lchown(fullpath,uid_,gid_); - - prv_->insert(errno,basepath_); -} - -static -void -_chown_loop(const std::vector &branches_, - const fs::path &fusepath_, - const uid_t uid_, - const gid_t gid_, - PolicyRV *prv_) -{ - for(const auto &branch : branches_) - { - ::_chown_loop_core(branch->path,fusepath_,uid_,gid_,prv_); - } -} - -static -int -_chown(const Policy::Action &actionFunc_, - const Policy::Search &searchFunc_, - const Branches &branches_, - const fs::path &fusepath_, - const uid_t uid_, - const gid_t gid_) -{ - int rv; - PolicyRV prv; - std::vector branches; - - rv = actionFunc_(branches_,fusepath_,branches); - if(rv < 0) - return rv; - - ::_chown_loop(branches,fusepath_,uid_,gid_,&prv); - - if(prv.errors.empty()) - return 0; - if(prv.successes.empty()) - return prv.errors[0].rv; - - branches.clear(); - rv = searchFunc_(branches_,fusepath_,branches); - if(rv < 0) - return rv; - - return prv.get_error(branches[0]->path); -} int FUSE::chown(const fuse_req_ctx_t *ctx_, @@ -101,10 +29,8 @@ FUSE::chown(const fuse_req_ctx_t *ctx_, { const fs::path fusepath{fusepath_}; - return ::_chown(cfg.func.chown.policy, - cfg.func.getattr.policy, - cfg.branches, - fusepath, - uid_, - gid_); + return cfg.chown(cfg.branches, + fusepath, + uid_, + gid_); } diff --git a/src/fuse_getattr.cpp b/src/fuse_getattr.cpp index 6c441004..95a68a88 100644 --- a/src/fuse_getattr.cpp +++ b/src/fuse_getattr.cpp @@ -34,42 +34,6 @@ #include -static -void -_set_stat_if_leads_to_dir(const fs::path &path_, - struct stat *st_) -{ - int rv; - struct stat st; - - rv = fs::stat(path_,&st); - if(rv < 0) - return; - - if(S_ISDIR(st.st_mode)) - *st_ = st; - - return; -} - -static -void -_set_stat_if_leads_to_reg(const fs::path &path_, - struct stat *st_) -{ - int rv; - struct stat st; - - rv = fs::stat(path_,&st); - if(rv < 0) - return; - - if(S_ISREG(st.st_mode)) - *st_ = st; - - return; -} - static int _getattr_fake_root(struct stat *st_) @@ -116,61 +80,6 @@ _getattr_controlfile(struct stat *st_) return 0; } -static -int -_getattr(const Policy::Search &searchFunc_, - const Branches &branches_, - const fs::path &fusepath_, - struct stat *st_, - const bool symlinkify_, - const time_t symlinkify_timeout_, - FollowSymlinks followsymlinks_) -{ - int rv; - fs::path fullpath; - std::vector branches; - - rv = searchFunc_(branches_,fusepath_,branches); - if(rv < 0) - return rv; - - fullpath = branches[0]->path / fusepath_; - - switch(followsymlinks_) - { - case FollowSymlinks::ENUM::NEVER: - rv = fs::lstat(fullpath,st_); - break; - case FollowSymlinks::ENUM::DIRECTORY: - rv = fs::lstat(fullpath,st_); - if(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)) - ::_set_stat_if_leads_to_reg(fullpath,st_); - break; - case FollowSymlinks::ENUM::ALL: - rv = fs::stat(fullpath,st_); - if(rv < 0) - rv = fs::lstat(fullpath,st_); - break; - } - - if(rv < 0) - return rv; - - if(symlinkify_ && symlinkify::can_be_symlink(*st_,symlinkify_timeout_)) - symlinkify::convert(fullpath,st_); - - fs::inode::calc(branches[0]->path, - fusepath_, - st_); - - return 0; -} - int _getattr(const fs::path &fusepath_, struct stat *st_, @@ -178,13 +87,11 @@ _getattr(const fs::path &fusepath_, { int rv; - rv = ::_getattr(cfg.func.getattr.policy, - cfg.branches, - fusepath_, - st_, - cfg.symlinkify, - cfg.symlinkify_timeout, - cfg.follow_symlinks); + rv = cfg.getattr(cfg.branches, + fusepath_, + st_, + cfg.follow_symlinks, + cfg.symlinkify_timeout); if((rv < 0) && Config::is_rootdir(fusepath_)) return ::_getattr_fake_root(st_); diff --git a/src/fuse_removexattr.cpp b/src/fuse_removexattr.cpp index c952d98a..9025695d 100644 --- a/src/fuse_removexattr.cpp +++ b/src/fuse_removexattr.cpp @@ -18,75 +18,9 @@ #include "config.hpp" #include "errno.hpp" -#include "fs_lremovexattr.hpp" -#include "fs_path.hpp" -#include "policy_rv.hpp" -#include "ugid.hpp" #include "fuse.h" -#include - - -static -void -_removexattr_loop_core(const fs::path &basepath_, - const fs::path &fusepath_, - const char *attrname_, - PolicyRV *prv_) -{ - fs::path fullpath; - - fullpath = basepath_ / fusepath_; - - errno = 0; - fs::lremovexattr(fullpath,attrname_); - - prv_->insert(errno,basepath_); -} - -static -void -_removexattr_loop(const std::vector &branches_, - const fs::path &fusepath_, - const char *attrname_, - PolicyRV *prv_) -{ - for(auto &branch : branches_) - { - ::_removexattr_loop_core(branch->path,fusepath_,attrname_,prv_); - } -} - -static -int -_removexattr(const Policy::Action &actionFunc_, - const Policy::Search &searchFunc_, - const Branches &ibranches_, - const fs::path &fusepath_, - const char *attrname_) -{ - int rv; - PolicyRV prv; - std::vector obranches; - - rv = actionFunc_(ibranches_,fusepath_,obranches); - if(rv < 0) - return rv; - - ::_removexattr_loop(obranches,fusepath_,attrname_,&prv); - if(prv.errors.empty()) - return 0; - if(prv.successes.empty()) - return prv.errors[0].rv; - - obranches.clear(); - rv = searchFunc_(ibranches_,fusepath_,obranches); - if(rv < 0) - return rv; - - return prv.get_error(obranches[0]->path); -} int FUSE::removexattr(const fuse_req_ctx_t *ctx_, @@ -96,14 +30,10 @@ FUSE::removexattr(const fuse_req_ctx_t *ctx_, const fs::path fusepath{fusepath_}; if(Config::is_ctrl_file(fusepath)) - return -ENOATTR; + return -EROFS; if(cfg.xattr.to_int()) return -cfg.xattr.to_int(); - return ::_removexattr(cfg.func.removexattr.policy, - cfg.func.getxattr.policy, - cfg.branches, - fusepath, - attrname_); + return cfg.removexattr(cfg.branches,fusepath,attrname_); } diff --git a/src/fuse_rmdir.cpp b/src/fuse_rmdir.cpp index 5a7cff2e..d1db6150 100644 --- a/src/fuse_rmdir.cpp +++ b/src/fuse_rmdir.cpp @@ -17,88 +17,14 @@ #include "fuse_rmdir.hpp" #include "config.hpp" -#include "errno.hpp" -#include "error.hpp" -#include "fs_path.hpp" -#include "fs_rmdir.hpp" -#include "fs_unlink.hpp" -#include "ugid.hpp" -#include "fuse.h" - -#include - -#include - - -static -int -_should_unlink(int rv_, - FollowSymlinks followsymlinks_) -{ - return ((rv_ == -ENOTDIR) && - (followsymlinks_ != FollowSymlinks::ENUM::NEVER)); -} - -static -int -_rmdir_core(const fs::path &basepath_, - const fs::path &fusepath_, - const FollowSymlinks followsymlinks_) -{ - int rv; - fs::path fullpath; - - fullpath = basepath_ / fusepath_; - - rv = fs::rmdir(fullpath); - if(::_should_unlink(rv,followsymlinks_)) - rv = fs::unlink(fullpath); - - return rv; -} - -static -int -_rmdir_loop(const std::vector &branches_, - const fs::path &fusepath_, - const FollowSymlinks followsymlinks_) -{ - Err err; - - for(const auto &branch : branches_) - { - err = ::_rmdir_core(branch->path,fusepath_,followsymlinks_); - } - - return err; -} - -static -int -_rmdir(const Policy::Action &actionFunc_, - const Branches &branches_, - const FollowSymlinks followsymlinks_, - const fs::path &fusepath_) -{ - int rv; - std::vector branches; - - rv = actionFunc_(branches_,fusepath_,branches); - if(rv < 0) - return rv; - - return ::_rmdir_loop(branches,fusepath_,followsymlinks_); -} int FUSE::rmdir(const fuse_req_ctx_t *ctx_, const char *fusepath_) { - const fs::path fusepath{fusepath_}; + const fs::path fusepath{fusepath_}; - return ::_rmdir(cfg.func.rmdir.policy, - cfg.branches, - cfg.follow_symlinks, - fusepath); + return cfg.rmdir(cfg.branches, + fusepath); } diff --git a/src/fuse_statx_supported.icpp b/src/fuse_statx_supported.icpp index 6e99e9ef..0dd364c0 100644 --- a/src/fuse_statx_supported.icpp +++ b/src/fuse_statx_supported.icpp @@ -30,49 +30,11 @@ #include "symlinkify.hpp" #include "ugid.hpp" -#include "fmt/core.h" - #include "fuse.h" #include -static -void -_set_stat_if_leads_to_dir(const fs::path &path_, - struct fuse_statx *st_) -{ - int rv; - struct fuse_statx st; - - rv = fs::statx(AT_FDCWD,path_,AT_SYMLINK_FOLLOW,STATX_TYPE,&st); - if(rv < 0) - return; - - if(S_ISDIR(st.mode)) - *st_ = st; - - return; -} - -static -void -_set_stat_if_leads_to_reg(const fs::path &path_, - struct fuse_statx *st_) -{ - int rv; - struct fuse_statx st; - - rv = fs::statx(AT_FDCWD,path_,AT_SYMLINK_FOLLOW,STATX_TYPE,&st); - if(rv < 0) - return; - - if(S_ISREG(st.mode)) - *st_ = st; - - return; -} - static int _statx_fake_root(struct fuse_statx *st_) @@ -113,63 +75,6 @@ _statx_controlfile(struct fuse_statx *st_) return 0; } -static -int -_statx(const Policy::Search &searchFunc_, - const Branches &branches_, - const fs::path &fusepath_, - const uint32_t flags_, - const uint32_t mask_, - struct fuse_statx *st_, - const bool symlinkify_, - const time_t symlinkify_timeout_, - FollowSymlinks followsymlinks_) -{ - int rv; - fs::path fullpath; - std::vector branches; - - rv = searchFunc_(branches_,fusepath_,branches); - if(rv < 0) - return rv; - - fullpath = branches[0]->path / fusepath_; - - switch(followsymlinks_) - { - case FollowSymlinks::ENUM::NEVER: - rv = fs::statx(AT_FDCWD,fullpath,flags_|AT_SYMLINK_NOFOLLOW,mask_,st_); - break; - case FollowSymlinks::ENUM::DIRECTORY: - rv = fs::statx(AT_FDCWD,fullpath,flags_|AT_SYMLINK_NOFOLLOW,mask_,st_); - if((rv >= 0) && S_ISLNK(st_->mode)) - ::_set_stat_if_leads_to_dir(fullpath,st_); - break; - case FollowSymlinks::ENUM::REGULAR: - rv = fs::statx(AT_FDCWD,fullpath,flags_|AT_SYMLINK_NOFOLLOW,mask_,st_); - if((rv >= 0) && S_ISLNK(st_->mode)) - ::_set_stat_if_leads_to_reg(fullpath,st_); - break; - case FollowSymlinks::ENUM::ALL: - rv = fs::statx(AT_FDCWD,fullpath,flags_|AT_SYMLINK_FOLLOW,mask_,st_); - if(rv < 0) - rv = fs::statx(AT_FDCWD,fullpath,flags_|AT_SYMLINK_NOFOLLOW,mask_,st_); - break; - } - - if(rv < 0) - return rv; - - if(symlinkify_ && symlinkify::can_be_symlink(*st_,symlinkify_timeout_)) - symlinkify::convert(fullpath,st_); - - fs::inode::calc(branches[0]->path, - fusepath_, - st_); - - return 0; -} - static int _statx(const fs::path &fusepath_, @@ -180,15 +85,13 @@ _statx(const fs::path &fusepath_, { int rv; - rv = ::_statx(cfg.func.getattr.policy, - cfg.branches, - fusepath_, - flags_, - mask_, - st_, - cfg.symlinkify, - cfg.symlinkify_timeout, - cfg.follow_symlinks); + rv = cfg.statx(cfg.branches, + fusepath_, + flags_, + mask_, + st_, + cfg.follow_symlinks, + cfg.symlinkify_timeout); if((rv < 0) && Config::is_rootdir(fusepath_)) return ::_statx_fake_root(st_); diff --git a/src/fuse_truncate.cpp b/src/fuse_truncate.cpp index f3008268..369ddcf7 100644 --- a/src/fuse_truncate.cpp +++ b/src/fuse_truncate.cpp @@ -19,75 +19,9 @@ #include "config.hpp" #include "errno.hpp" #include "fs_path.hpp" -#include "fs_truncate.hpp" -#include "policy_rv.hpp" -#include "ugid.hpp" #include "fuse.h" -#include -#include - - -static -void -_truncate_loop_core(const fs::path &basepath_, - const fs::path &fusepath_, - const off_t size_, - PolicyRV *prv_) -{ - int rv; - fs::path fullpath; - - fullpath = basepath_ / fusepath_; - - rv = fs::truncate(fullpath,size_); - - prv_->insert(rv,basepath_); -} - -static -void -_truncate_loop(const std::vector &branches_, - const fs::path &fusepath_, - const off_t size_, - PolicyRV *prv_) -{ - for(auto &branch : branches_) - { - ::_truncate_loop_core(branch->path,fusepath_,size_,prv_); - } -} - -static -int -_truncate(const Policy::Action &actionFunc_, - const Policy::Search &searchFunc_, - const Branches &branches_, - const fs::path &fusepath_, - const off_t size_) -{ - int rv; - PolicyRV prv; - std::vector branches; - - rv = actionFunc_(branches_,fusepath_,branches); - if(rv < 0) - return rv; - - ::_truncate_loop(branches,fusepath_,size_,&prv); - if(prv.errors.empty()) - return 0; - if(prv.successes.empty()) - return prv.errors[0].rv; - - branches.clear(); - rv = searchFunc_(branches_,fusepath_,branches); - if(rv < 0) - return rv; - - return prv.get_error(branches[0]->path); -} int FUSE::truncate(const fuse_req_ctx_t *ctx_, @@ -96,9 +30,5 @@ FUSE::truncate(const fuse_req_ctx_t *ctx_, { const fs::path fusepath{fusepath_}; - return ::_truncate(cfg.func.truncate.policy, - cfg.func.getattr.policy, - cfg.branches, - fusepath, - size_); + return cfg.truncate(cfg.branches,fusepath,size_); } diff --git a/src/fuse_unlink.cpp b/src/fuse_unlink.cpp index a870c930..b2b29122 100644 --- a/src/fuse_unlink.cpp +++ b/src/fuse_unlink.cpp @@ -17,52 +17,7 @@ #include "fuse_unlink.hpp" #include "config.hpp" -#include "errno.hpp" -#include "error.hpp" -#include "fs_path.hpp" -#include "fs_unlink.hpp" -#include "ugid.hpp" -#include "fuse.h" - -#include - -#include - - -static -int -_unlink_loop(const std::vector &branches_, - const fs::path &fusepath_) -{ - Err err; - fs::path fullpath; - - for(const auto &branch : branches_) - { - fullpath = branch->path / fusepath_; - - err = fs::unlink(fullpath); - } - - return err; -} - -static -int -_unlink(const Policy::Action &unlinkPolicy_, - const Branches &branches_, - const fs::path &fusepath_) -{ - int rv; - std::vector branches; - - rv = unlinkPolicy_(branches_,fusepath_,branches); - if(rv < 0) - return rv; - - return ::_unlink_loop(branches,fusepath_); -} int FUSE::unlink(const fuse_req_ctx_t *ctx_, @@ -70,7 +25,5 @@ FUSE::unlink(const fuse_req_ctx_t *ctx_, { const fs::path fusepath{fusepath_}; - return ::_unlink(cfg.func.unlink.policy, - cfg.branches, - fusepath); + return cfg.unlink(cfg.branches,fusepath); } diff --git a/src/fuse_utimens.cpp b/src/fuse_utimens.cpp index 485a14f2..4df58ea2 100644 --- a/src/fuse_utimens.cpp +++ b/src/fuse_utimens.cpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2016, Antonio SJ Musumeci + Copyright (c) 2025, Antonio SJ Musumeci Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -17,76 +17,7 @@ #include "fuse_utimens.hpp" #include "config.hpp" -#include "errno.hpp" -#include "fs_lutimens.hpp" -#include "fs_path.hpp" -#include "policy_rv.hpp" -#include "ugid.hpp" -#include "fuse.h" - -#include - - -static -void -_utimens_loop_core(const fs::path &basepath_, - const fs::path &fusepath_, - const timespec ts_[2], - PolicyRV *prv_) -{ - int rv; - fs::path fullpath; - - fullpath = basepath_ / fusepath_; - - rv = fs::lutimens(fullpath,ts_); - - prv_->insert(rv,basepath_); -} - -static -void -_utimens_loop(const std::vector &branches_, - const fs::path &fusepath_, - const timespec ts_[2], - PolicyRV *prv_) -{ - for(auto &branch : branches_) - { - ::_utimens_loop_core(branch->path,fusepath_,ts_,prv_); - } -} - -static -int -_utimens(const Policy::Action &utimensPolicy_, - const Policy::Search &getattrPolicy_, - const Branches &branches_, - const fs::path &fusepath_, - const timespec ts_[2]) -{ - int rv; - PolicyRV prv; - std::vector branches; - - rv = utimensPolicy_(branches_,fusepath_,branches); - if(rv < 0) - return rv; - - ::_utimens_loop(branches,fusepath_,ts_,&prv); - if(prv.errors.empty()) - return 0; - if(prv.successes.empty()) - return prv.errors[0].rv; - - branches.clear(); - rv = getattrPolicy_(branches_,fusepath_,branches); - if(rv < 0) - return rv; - - return prv.get_error(branches[0]->path); -} int FUSE::utimens(const fuse_req_ctx_t *ctx_, @@ -95,9 +26,5 @@ FUSE::utimens(const fuse_req_ctx_t *ctx_, { const fs::path fusepath{fusepath_}; - return ::_utimens(cfg.func.utimens.policy, - cfg.func.getattr.policy, - cfg.branches, - fusepath, - ts_); + return cfg.utimens(cfg.branches,fusepath,ts_); } diff --git a/src/timespec_utils.hpp b/src/timespec_utils.hpp new file mode 100644 index 00000000..24fbbd05 --- /dev/null +++ b/src/timespec_utils.hpp @@ -0,0 +1,72 @@ +#pragma once + +namespace TimeSpec +{ + static + inline + bool + is_newer(const timespec &t0_, + const timespec &t1_) + { + if(t0_.tv_sec > t1_.tv_sec) + return true; + if(t0_.tv_sec == t1_.tv_sec) + { + if(t0_.tv_nsec > t1_.tv_nsec) + return true; + } + + return false; + } + + static + inline + timespec + newest(const timespec &t0_, + const timespec &t1_) + { + if(t0_.tv_sec > t1_.tv_sec) + return t0_; + if(t0_.tv_sec == t1_.tv_sec) + { + if(t0_.tv_nsec > t1_.tv_nsec) + return t0_; + } + + return t1_; + } + + static + inline + bool + is_newer(const fuse_sx_time &t0_, + const fuse_sx_time &t1_) + { + if(t0_.tv_sec > t1_.tv_sec) + return true; + if(t0_.tv_sec == t1_.tv_sec) + { + if(t0_.tv_nsec > t1_.tv_nsec) + return true; + } + + return false; + } + + static + inline + fuse_sx_time + newest(const fuse_sx_time &t0_, + const fuse_sx_time &t1_) + { + if(t0_.tv_sec > t1_.tv_sec) + return t0_; + if(t0_.tv_sec == t1_.tv_sec) + { + if(t0_.tv_nsec > t1_.tv_nsec) + return t0_; + } + + return t1_; + } +} diff --git a/src/to_cstr.hpp b/src/to_cstr.hpp new file mode 100644 index 00000000..85da6ff4 --- /dev/null +++ b/src/to_cstr.hpp @@ -0,0 +1,22 @@ +#pragma once + +#include +#include +#include + + +template +const char* +to_cstr(const PathType &p_) +{ + if constexpr (std::is_same_v, std::filesystem::path>) + return p_.c_str(); + if constexpr (std::is_same_v, std::string>) + return p_.c_str(); + if constexpr (std::is_same_v, const char*> || + std::is_same_v, char*>) + return p_; + + abort(); + return NULL; +}