Browse Source

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.
bespoke-policies
Antonio SJ Musumeci 1 month ago
parent
commit
22a7ac1c90
  1. 17
      src/config.cpp
  2. 26
      src/config.hpp
  3. 8
      src/config_follow_symlinks.hpp
  4. 9
      src/follow_symlinks_enum.hpp
  5. 17
      src/fs_lstat.hpp
  6. 0
      src/fs_stat.cpp
  7. 59
      src/fs_stat.hpp
  8. 61
      src/fs_statx.hpp
  9. 36
      src/fsproxy.cpp
  10. 54
      src/fsproxy.hpp
  11. 73
      src/func_access.hpp
  12. 29
      src/func_access_all.cpp
  13. 19
      src/func_access_all.hpp
  14. 24
      src/func_access_base.hpp
  15. 30
      src/func_access_factory.cpp
  16. 13
      src/func_access_factory.hpp
  17. 73
      src/func_chmod.hpp
  18. 35
      src/func_chmod_all.cpp
  19. 19
      src/func_chmod_all.hpp
  20. 23
      src/func_chmod_base.hpp
  21. 30
      src/func_chmod_factory.cpp
  22. 13
      src/func_chmod_factory.hpp
  23. 75
      src/func_chown.hpp
  24. 36
      src/func_chown_all.cpp
  25. 20
      src/func_chown_all.hpp
  26. 24
      src/func_chown_base.hpp
  27. 30
      src/func_chown_factory.cpp
  28. 13
      src/func_chown_factory.hpp
  29. 76
      src/func_getattr.hpp
  30. 35
      src/func_getattr_base.hpp
  31. 71
      src/func_getattr_combine.cpp
  32. 21
      src/func_getattr_combine.hpp
  33. 39
      src/func_getattr_factory.cpp
  34. 13
      src/func_getattr_factory.hpp
  35. 41
      src/func_getattr_ff.cpp
  36. 23
      src/func_getattr_ff.hpp
  37. 57
      src/func_getattr_newest.cpp
  38. 21
      src/func_getattr_newest.hpp
  39. 77
      src/func_getxattr.hpp
  40. 25
      src/func_getxattr_base.hpp
  41. 30
      src/func_getxattr_factory.cpp
  42. 13
      src/func_getxattr_factory.hpp
  43. 35
      src/func_getxattr_ff.cpp
  44. 21
      src/func_getxattr_ff.hpp
  45. 73
      src/func_ioctl.hpp
  46. 25
      src/func_ioctl_all.cpp
  47. 18
      src/func_ioctl_all.hpp
  48. 22
      src/func_ioctl_base.hpp
  49. 30
      src/func_ioctl_factory.cpp
  50. 13
      src/func_ioctl_factory.hpp
  51. 73
      src/func_listxattr.hpp
  52. 27
      src/func_listxattr_all.cpp
  53. 20
      src/func_listxattr_all.hpp
  54. 24
      src/func_listxattr_base.hpp
  55. 30
      src/func_listxattr_factory.cpp
  56. 13
      src/func_listxattr_factory.hpp
  57. 73
      src/func_open.hpp
  58. 27
      src/func_open_all.cpp
  59. 19
      src/func_open_all.hpp
  60. 23
      src/func_open_base.hpp
  61. 30
      src/func_open_factory.cpp
  62. 13
      src/func_open_factory.hpp
  63. 75
      src/func_readlink.hpp
  64. 28
      src/func_readlink_all.cpp
  65. 20
      src/func_readlink_all.hpp
  66. 24
      src/func_readlink_base.hpp
  67. 30
      src/func_readlink_factory.cpp
  68. 13
      src/func_readlink_factory.hpp
  69. 73
      src/func_removexattr.hpp
  70. 35
      src/func_removexattr_all.cpp
  71. 19
      src/func_removexattr_all.hpp
  72. 23
      src/func_removexattr_base.hpp
  73. 30
      src/func_removexattr_factory.cpp
  74. 13
      src/func_removexattr_factory.hpp
  75. 71
      src/func_rmdir.hpp
  76. 50
      src/func_rmdir_all.cpp
  77. 18
      src/func_rmdir_all.hpp
  78. 22
      src/func_rmdir_base.hpp
  79. 30
      src/func_rmdir_factory.cpp
  80. 13
      src/func_rmdir_factory.hpp
  81. 79
      src/func_setxattr.hpp
  82. 38
      src/func_setxattr_all.cpp
  83. 22
      src/func_setxattr_all.hpp
  84. 26
      src/func_setxattr_base.hpp
  85. 30
      src/func_setxattr_factory.cpp
  86. 13
      src/func_setxattr_factory.hpp
  87. 81
      src/func_statx.hpp
  88. 38
      src/func_statx_base.hpp
  89. 79
      src/func_statx_combine.cpp
  90. 23
      src/func_statx_combine.hpp
  91. 39
      src/func_statx_factory.cpp
  92. 13
      src/func_statx_factory.hpp
  93. 48
      src/func_statx_ff.cpp
  94. 25
      src/func_statx_ff.hpp
  95. 64
      src/func_statx_newest.cpp
  96. 23
      src/func_statx_newest.hpp
  97. 73
      src/func_truncate.hpp
  98. 35
      src/func_truncate_all.cpp
  99. 19
      src/func_truncate_all.hpp
  100. 23
      src/func_truncate_base.hpp

17
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;

26
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;

8
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<FollowSymlinksEnum> FollowSymlinks;

9
src/follow_symlinks_enum.hpp

@ -0,0 +1,9 @@
#pragma once
enum class FollowSymlinksEnum
{
NEVER,
DIRECTORY,
REGULAR,
ALL
};

17
src/fs_lstat.hpp

@ -19,8 +19,7 @@
#pragma once
#include "to_neg_errno.hpp"
#include <string>
#include "to_cstr.hpp"
#include <sys/stat.h>
#include <sys/types.h>
@ -29,25 +28,17 @@
namespace fs
{
template<typename PathType>
static
inline
int
lstat(const char *path_,
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_);
}
}

0
src/fs_stat.cpp

59
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 <string>
@ -29,25 +32,71 @@
namespace fs
{
template<typename PathType>
static
inline
int
stat(const char *path_,
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<typename PathType>
static
inline
int
stat(const std::string &path_,
struct stat *st_)
stat(const PathType &path_,
struct stat *st_,
FollowSymlinksEnum follow_)
{
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))
{
return fs::stat(path_.c_str(),st_);
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;
}
}

61
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<typename PathType>
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<typename PathType>
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;
}
}

36
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;
}

54
src/fsproxy.hpp

@ -0,0 +1,54 @@
#pragma once
#include <unordered_map>
#include <fcntl.h>
#include <unistd.h>
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<uid_t>{}(key_.uid);
size_t h1 = std::hash<uid_t>{}(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<UGID,Process,UGIDHash> _proxies;
};

73
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 <atomic>
#include <cassert>
namespace Func2
{
class Access : public ToFromString
{
private:
std::shared_ptr<Func2::AccessBase> _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<Func2::AccessBase> p;
p = std::atomic_load(&_impl);
return (*p)(branches_,
fusepath_,
mode_);
}
public:
std::string
to_string() const
{
std::shared_ptr<Func2::AccessBase> p;
p = std::atomic_load(&_impl);
return std::string{p->name()};
}
int
from_string(const std::string_view str_)
{
std::shared_ptr<Func2::AccessBase> p;
p = Func2::AccessFactory::make(str_);
if(!p)
return -EINVAL;
_impl = std::atomic_load(&p);
return 0;
}
};
}

29
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;
}

19
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);
};
}

24
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;
};
}

30
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::AccessBase>
Func2::AccessFactory::make(const std::string_view str_)
{
if(str_ == "all")
return std::make_shared<Func2::AccessAll>();
if(Policies::Action::find(str_))
return std::make_shared<Func2::AccessAll>();
return {};
}

13
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<AccessBase> make(const std::string_view str);
};
}

73
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 <atomic>
#include <cassert>
namespace Func2
{
class Chmod : public ToFromString
{
private:
std::shared_ptr<Func2::ChmodBase> _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<Func2::ChmodBase> p;
p = std::atomic_load(&_impl);
return (*p)(branches_,
fusepath_,
mode_);
}
public:
std::string
to_string() const
{
std::shared_ptr<Func2::ChmodBase> p;
p = std::atomic_load(&_impl);
return std::string{p->name()};
}
int
from_string(const std::string_view str_)
{
std::shared_ptr<Func2::ChmodBase> p;
p = Func2::ChmodFactory::make(str_);
if(!p)
return -EINVAL;
_impl = std::atomic_load(&p);
return 0;
}
};
}

35
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;
}

19
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);
};
}

23
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;
};
}

30
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::ChmodBase>
Func2::ChmodFactory::make(const std::string_view str_)
{
if(str_ == "all")
return std::make_shared<Func2::ChmodAll>();
if(Policies::Action::find(str_))
return std::make_shared<Func2::ChmodAll>();
return {};
}

13
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<ChmodBase> make(const std::string_view str);
};
}

75
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 <atomic>
#include <cassert>
namespace Func2
{
class Chown : public ToFromString
{
private:
std::shared_ptr<Func2::ChownBase> _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<Func2::ChownBase> p;
p = std::atomic_load(&_impl);
return (*p)(branches_,
fusepath_,
uid_,
gid_);
}
public:
std::string
to_string() const
{
std::shared_ptr<Func2::ChownBase> p;
p = std::atomic_load(&_impl);
return std::string{p->name()};
}
int
from_string(const std::string_view str_)
{
std::shared_ptr<Func2::ChownBase> p;
p = Func2::ChownFactory::make(str_);
if(!p)
return -EINVAL;
_impl = std::atomic_load(&p);
return 0;
}
};
}

36
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;
}

20
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);
};
}

24
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;
};
}

30
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::ChownBase>
Func2::ChownFactory::make(const std::string_view str_)
{
if(str_ == "all")
return std::make_shared<Func2::ChownAll>();
if(Policies::Action::find(str_))
return std::make_shared<Func2::ChownAll>();
return {};
}

13
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<ChownBase> make(const std::string_view str);
};
}

76
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 <atomic>
#include <cassert>
namespace Func2
{
class GetAttr : public ToFromString
{
private:
std::shared_ptr<Func2::GetAttrBase> _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<Func2::GetAttrBase> p;
p = std::atomic_load(&_impl);
return (*p)(branches_,
fusepath_,
st_,
follow_symlinks_,
symlinkify_timeout_);
}
public:
std::string
to_string() const
{
std::shared_ptr<Func2::GetAttrBase> p;
p = std::atomic_load(&_impl);
return std::string(p->name());
}
int
from_string(const std::string_view str_)
{
std::shared_ptr<Func2::GetAttrBase> p;
p = Func2::GetAttrFactory::make(str_);
if(!p)
return -EINVAL;
_impl = std::atomic_load(&p);
return 0;
}
};
}

35
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 <string_view>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
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;
};
}

71
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;
}

21
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);
};
}

39
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::GetAttrBase>
Func2::GetAttrFactory::make(const std::string_view str_)
{
if(str_ == "combine")
return std::make_shared<Func2::GetAttrCombine>();
if(str_ == "ff")
return std::make_shared<Func2::GetAttrFF>();
if(str_ == "newest")
return std::make_shared<Func2::GetAttrNewest>();
if(Policies::Search::find(str_))
return std::make_shared<Func2::GetAttrCombine>();
return {};
}

13
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<GetAttrBase> make(const std::string_view str);
};
}

41
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;
}

23
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);
};
}

57
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;
}

21
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);
};
}

77
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 <atomic>
#include <cassert>
namespace Func2
{
class Getxattr : public ToFromString
{
private:
std::shared_ptr<Func2::GetxattrBase> _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<Func2::GetxattrBase> p;
p = std::atomic_load(&_impl);
return (*p)(branches_,
fusepath_,
attrname_,
attrval_,
attrvalsize_);
}
public:
std::string
to_string() const
{
std::shared_ptr<Func2::GetxattrBase> p;
p = std::atomic_load(&_impl);
return std::string{p->name()};
}
int
from_string(const std::string_view str_)
{
std::shared_ptr<Func2::GetxattrBase> p;
p = Func2::GetxattrFactory::make(str_);
if(!p)
return -EINVAL;
_impl = std::atomic_load(&p);
return 0;
}
};
}

25
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;
};
}

30
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::GetxattrBase>
Func2::GetxattrFactory::make(const std::string_view str_)
{
if(str_ == "ff")
return std::make_shared<Func2::GetxattrFF>();
if(Policies::Action::find(str_))
return std::make_shared<Func2::GetxattrFF>();
return {};
}

13
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<GetxattrBase> make(const std::string_view str);
};
}

35
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;
}

21
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);
};
}

73
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 <atomic>
#include <cassert>
namespace Func2
{
class Ioctl : public ToFromString
{
private:
std::shared_ptr<Func2::IoctlBase> _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<Func2::IoctlBase> p;
p = std::atomic_load(&_impl);
return (*p)(branches_,
fusepath_,
mode_);
}
public:
std::string
to_string() const
{
std::shared_ptr<Func2::IoctlBase> p;
p = std::atomic_load(&_impl);
return std::string{p->name()};
}
int
from_string(const std::string_view str_)
{
std::shared_ptr<Func2::IoctlBase> p;
p = Func2::IoctlFactory::make(str_);
if(!p)
return -EINVAL;
_impl = std::atomic_load(&p);
return 0;
}
};
}

25
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;
}

18
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);
};
}

22
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;
};
}

30
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::IoctlBase>
Func2::IoctlFactory::make(const std::string_view str_)
{
if(str_ == "all")
return std::make_shared<Func2::IoctlAll>();
if(Policies::Action::find(str_))
return std::make_shared<Func2::IoctlAll>();
return {};
}

13
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<IoctlBase> make(const std::string_view str);
};
}

73
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 <atomic>
#include <cassert>
namespace Func2
{
class Listxattr : public ToFromString
{
private:
std::shared_ptr<Func2::ListxattrBase> _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<Func2::ListxattrBase> p;
p = std::atomic_load(&_impl);
return (*p)(branches_,
fusepath_,
mode_);
}
public:
std::string
to_string() const
{
std::shared_ptr<Func2::ListxattrBase> p;
p = std::atomic_load(&_impl);
return std::string{p->name()};
}
int
from_string(const std::string_view str_)
{
std::shared_ptr<Func2::ListxattrBase> p;
p = Func2::ListxattrFactory::make(str_);
if(!p)
return -EINVAL;
_impl = std::atomic_load(&p);
return 0;
}
};
}

27
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;
}

20
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);
};
}

24
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;
};
}

30
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::ListxattrBase>
Func2::ListxattrFactory::make(const std::string_view str_)
{
if(str_ == "all")
return std::make_shared<Func2::ListxattrAll>();
if(Policies::Action::find(str_))
return std::make_shared<Func2::ListxattrAll>();
return {};
}

13
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<ListxattrBase> make(const std::string_view str);
};
}

73
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 <atomic>
#include <cassert>
namespace Func2
{
class Open : public ToFromString
{
private:
std::shared_ptr<Func2::OpenBase> _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<Func2::OpenBase> p;
p = std::atomic_load(&_impl);
return (*p)(branches_,
fusepath_,
mode_);
}
public:
std::string
to_string() const
{
std::shared_ptr<Func2::OpenBase> p;
p = std::atomic_load(&_impl);
return std::string{p->name()};
}
int
from_string(const std::string_view str_)
{
std::shared_ptr<Func2::OpenBase> p;
p = Func2::OpenFactory::make(str_);
if(!p)
return -EINVAL;
_impl = std::atomic_load(&p);
return 0;
}
};
}

27
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;
}

19
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);
};
}

23
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;
};
}

30
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::OpenBase>
Func2::OpenFactory::make(const std::string_view str_)
{
if(str_ == "all")
return std::make_shared<Func2::OpenAll>();
if(Policies::Action::find(str_))
return std::make_shared<Func2::OpenAll>();
return {};
}

13
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<OpenBase> make(const std::string_view str);
};
}

75
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 <atomic>
#include <cassert>
namespace Func2
{
class Readlink : public ToFromString
{
private:
std::shared_ptr<Func2::ReadlinkBase> _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<Func2::ReadlinkBase> p;
p = std::atomic_load(&_impl);
return (*p)(branches_,
fusepath_,
buf_,
bufsize_);
}
public:
std::string
to_string() const
{
std::shared_ptr<Func2::ReadlinkBase> p;
p = std::atomic_load(&_impl);
return std::string{p->name()};
}
int
from_string(const std::string_view str_)
{
std::shared_ptr<Func2::ReadlinkBase> p;
p = Func2::ReadlinkFactory::make(str_);
if(!p)
return -EINVAL;
_impl = std::atomic_load(&p);
return 0;
}
};
}

28
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;
}

20
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);
};
}

24
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;
};
}

30
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::ReadlinkBase>
Func2::ReadlinkFactory::make(const std::string_view str_)
{
if(str_ == "all")
return std::make_shared<Func2::ReadlinkAll>();
if(Policies::Action::find(str_))
return std::make_shared<Func2::ReadlinkAll>();
return {};
}

13
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<ReadlinkBase> make(const std::string_view str);
};
}

73
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 <atomic>
#include <cassert>
namespace Func2
{
class Removexattr : public ToFromString
{
private:
std::shared_ptr<Func2::RemovexattrBase> _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<Func2::RemovexattrBase> p;
p = std::atomic_load(&_impl);
return (*p)(branches_,
fusepath_,
attrname_);
}
public:
std::string
to_string() const
{
std::shared_ptr<Func2::RemovexattrBase> p;
p = std::atomic_load(&_impl);
return std::string{p->name()};
}
int
from_string(const std::string_view str_)
{
std::shared_ptr<Func2::RemovexattrBase> p;
p = Func2::RemovexattrFactory::make(str_);
if(!p)
return -EINVAL;
_impl = std::atomic_load(&p);
return 0;
}
};
}

35
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;
}

19
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);
};
}

23
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;
};
}

30
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::RemovexattrBase>
Func2::RemovexattrFactory::make(const std::string_view str_)
{
if(str_ == "all")
return std::make_shared<Func2::RemovexattrAll>();
if(Policies::Action::find(str_))
return std::make_shared<Func2::RemovexattrAll>();
return {};
}

13
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<RemovexattrBase> make(const std::string_view str);
};
}

71
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 <atomic>
#include <cassert>
namespace Func2
{
class Rmdir : public ToFromString
{
private:
std::shared_ptr<Func2::RmdirBase> _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<Func2::RmdirBase> p;
p = std::atomic_load(&_impl);
return (*p)(branches_,
fusepath_);
}
public:
std::string
to_string() const
{
std::shared_ptr<Func2::RmdirBase> p;
p = std::atomic_load(&_impl);
return std::string{p->name()};
}
int
from_string(const std::string_view str_)
{
std::shared_ptr<Func2::RmdirBase> p;
p = Func2::RmdirFactory::make(str_);
if(!p)
return -EINVAL;
_impl = std::atomic_load(&p);
return 0;
}
};
}

50
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;
}

18
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);
};
}

22
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;
};
}

30
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::RmdirBase>
Func2::RmdirFactory::make(const std::string_view str_)
{
if(str_ == "all")
return std::make_shared<Func2::RmdirAll>();
if(Policies::Action::find(str_))
return std::make_shared<Func2::RmdirAll>();
return {};
}

13
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<RmdirBase> make(const std::string_view str);
};
}

79
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 <atomic>
#include <cassert>
namespace Func2
{
class Setxattr : public ToFromString
{
private:
std::shared_ptr<Func2::SetxattrBase> _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<Func2::SetxattrBase> p;
p = std::atomic_load(&_impl);
return (*p)(branches_,
fusepath_,
attrname_,
attrval_,
attrvalsize_,
flags_);
}
public:
std::string
to_string() const
{
std::shared_ptr<Func2::SetxattrBase> p;
p = std::atomic_load(&_impl);
return std::string{p->name()};
}
int
from_string(const std::string_view str_)
{
std::shared_ptr<Func2::SetxattrBase> p;
p = Func2::SetxattrFactory::make(str_);
if(!p)
return -EINVAL;
_impl = std::atomic_load(&p);
return 0;
}
};
}

38
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;
}

22
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_);
};
}

26
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;
};
}

30
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::SetxattrBase>
Func2::SetxattrFactory::make(const std::string_view str_)
{
if(str_ == "all")
return std::make_shared<Func2::SetxattrAll>();
if(Policies::Action::find(str_))
return std::make_shared<Func2::SetxattrAll>();
return {};
}

13
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<SetxattrBase> make(const std::string_view str);
};
}

81
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 <atomic>
#include <assert.h>
namespace Func2
{
class Statx : public ToFromString
{
private:
std::shared_ptr<Func2::StatxBase> _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<Func2::StatxBase> 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<Func2::StatxBase> p;
p = std::atomic_load(&_impl);
return std::string(p->name());
}
int
from_string(const std::string_view str_)
{
std::shared_ptr<Func2::StatxBase> p;
p = Func2::StatxFactory::make(str_);
if(!p)
return -EINVAL;
_impl = std::atomic_load(&p);
return 0;
}
};
}

38
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 <string_view>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
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;
};
}

79
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;
}

23
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);
};
}

39
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::StatxBase>
Func2::StatxFactory::make(const std::string_view str_)
{
if(str_ == "combine")
return std::make_shared<Func2::StatxCombine>();
if(str_ == "ff")
return std::make_shared<Func2::StatxFF>();
if(str_ == "newest")
return std::make_shared<Func2::StatxNewest>();
if(Policies::Search::find(str_))
return std::make_shared<Func2::StatxCombine>();
return {};
}

13
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<StatxBase> make(const std::string_view str);
};
}

48
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;
}

25
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);
};
}

64
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;
}

23
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);
};
}

73
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 <atomic>
#include <cassert>
namespace Func2
{
class Truncate : public ToFromString
{
private:
std::shared_ptr<Func2::TruncateBase> _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<Func2::TruncateBase> p;
p = std::atomic_load(&_impl);
return (*p)(branches_,
fusepath_,
size_);
}
public:
std::string
to_string() const
{
std::shared_ptr<Func2::TruncateBase> p;
p = std::atomic_load(&_impl);
return std::string{p->name()};
}
int
from_string(const std::string_view str_)
{
std::shared_ptr<Func2::TruncateBase> p;
p = Func2::TruncateFactory::make(str_);
if(!p)
return -EINVAL;
_impl = std::atomic_load(&p);
return 0;
}
};
}

35
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;
}

19
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_);
};
}

23
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;
};
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save