Browse Source

checkpoint

toml
Antonio SJ Musumeci 3 years ago
parent
commit
8f6467a11c
  1. 177
      src/fuse_create.cpp
  2. 35
      src/fuse_init.cpp
  3. 121
      src/fuse_link.cpp
  4. 130
      src/fuse_mkdir.cpp
  5. 58
      src/fuse_readdir_plus.cpp
  6. 37
      src/fuse_readdirplus.cpp
  7. 4
      src/fuse_readdirplus.hpp
  8. 48
      src/fuse_readdirplus_policy.hpp
  9. 37
      src/fuse_readdirplus_policy_base.hpp
  10. 34
      src/fuse_readdirplus_policy_enosys.cpp
  11. 39
      src/fuse_readdirplus_policy_enosys.hpp
  12. 39
      src/fuse_readdirplus_policy_factory.cpp
  13. 30
      src/fuse_readdirplus_policy_factory.hpp
  14. 21
      src/fuse_readdirplus_policy_linux.cpp
  15. 24
      src/fuse_readdirplus_policy_linux.hpp
  16. 21
      src/fuse_readdirplus_policy_posix.cpp
  17. 26
      src/fuse_readdirplus_policy_posix.hpp
  18. 126
      src/fuse_statfs.cpp
  19. 33
      src/fuse_statfs_policy_branch.cpp
  20. 6
      src/fuse_statfs_policy_full.hpp
  21. 150
      src/fuse_symlink.cpp
  22. 3
      src/fuse_symlink.hpp
  23. 6
      src/fuse_symlink_policy.hpp
  24. 6
      src/fuse_symlink_policy_base.hpp
  25. 4
      src/fuse_symlink_policy_epff.cpp
  26. 4
      src/fuse_symlink_policy_epff.hpp
  27. 4
      src/fuse_symlink_policy_ff.cpp
  28. 4
      src/fuse_symlink_policy_ff.hpp
  29. 116
      src/fuse_utimens.cpp
  30. 22
      src/fuse_utimens_policy.hpp
  31. 2
      src/fuse_utimens_policy_base.hpp
  32. 13
      src/mergerfs.cpp
  33. 7
      src/state.cpp
  34. 21
      src/state.hpp

177
src/fuse_create.cpp

@ -14,198 +14,23 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "toml.hpp"
#include "config.hpp"
#include "errno.hpp"
#include "fileinfo.hpp"
#include "fs_acl.hpp"
#include "fs_clonepath.hpp"
#include "fs_open.hpp"
#include "fs_path.hpp"
#include "state.hpp"
#include "ugid.hpp"
#include "fuse.h"
#include <string>
#include <vector>
using std::string;
using std::vector;
namespace l
{
/*
The kernel expects being able to issue read requests when running
with writeback caching enabled so we must change O_WRONLY to
O_RDWR.
With writeback caching enabled the kernel handles O_APPEND. Could
be an issue if the underlying file changes out of band but that is
true of any caching.
*/
static
void
tweak_flags_writeback_cache(int *flags_)
{
if((*flags_ & O_ACCMODE) == O_WRONLY)
*flags_ = ((*flags_ & ~O_ACCMODE) | O_RDWR);
if(*flags_ & O_APPEND)
*flags_ &= ~O_APPEND;
}
static
void
config_to_ffi_flags(Config::Read &cfg_,
fuse_file_info_t *ffi_)
{
switch(cfg_->cache_files)
{
case CacheFiles::ENUM::LIBFUSE:
ffi_->direct_io = cfg_->direct_io;
ffi_->keep_cache = cfg_->kernel_cache;
ffi_->auto_cache = cfg_->auto_cache;
break;
case CacheFiles::ENUM::OFF:
ffi_->direct_io = 1;
ffi_->keep_cache = 0;
ffi_->auto_cache = 0;
break;
case CacheFiles::ENUM::PARTIAL:
ffi_->direct_io = 0;
ffi_->keep_cache = 0;
ffi_->auto_cache = 0;
break;
case CacheFiles::ENUM::FULL:
ffi_->direct_io = 0;
ffi_->keep_cache = 1;
ffi_->auto_cache = 0;
break;
case CacheFiles::ENUM::AUTO_FULL:
ffi_->direct_io = 0;
ffi_->keep_cache = 0;
ffi_->auto_cache = 1;
break;
}
}
static
int
create_core(const string &fullpath_,
mode_t mode_,
const mode_t umask_,
const int flags_)
{
if(!fs::acl::dir_has_defaults(fullpath_))
mode_ &= ~umask_;
return fs::open(fullpath_,flags_,mode_);
}
static
int
create_core(const string &createpath_,
const char *fusepath_,
const mode_t mode_,
const mode_t umask_,
const int flags_,
uint64_t *fh_)
{
int rv;
string fullpath;
fullpath = fs::path::make(createpath_,fusepath_);
rv = l::create_core(fullpath,mode_,umask_,flags_);
if(rv == -1)
return -errno;
*fh_ = reinterpret_cast<uint64_t>(new FileInfo(rv,fusepath_));
return 0;
}
static
int
create(const Policy::Search &searchFunc_,
const Policy::Create &createFunc_,
const Branches &branches_,
const char *fusepath_,
const mode_t mode_,
const mode_t umask_,
const int flags_,
uint64_t *fh_)
{
int rv;
string fullpath;
string fusedirpath;
StrVec createpaths;
StrVec existingpaths;
fusedirpath = fs::path::dirname(fusepath_);
rv = searchFunc_(branches_,fusedirpath,&existingpaths);
if(rv == -1)
return -errno;
rv = createFunc_(branches_,fusedirpath,&createpaths);
if(rv == -1)
return -errno;
rv = fs::clonepath_as_root(existingpaths[0],createpaths[0],fusedirpath);
if(rv == -1)
return -errno;
return l::create_core(createpaths[0],
fusepath_,
mode_,
umask_,
flags_,
fh_);
}
}
namespace FUSE::CREATE
{
int
create2(const char *fusepath_,
mode_t mode_,
fuse_file_info_t *ffi_)
{
Config::Read cfg;
const fuse_context *fc = fuse_get_context();
const ugid::Set ugid(fc->uid,fc->gid);
l::config_to_ffi_flags(cfg,ffi_);
if(cfg->writeback_cache)
l::tweak_flags_writeback_cache(&ffi_->flags);
return l::create(cfg->func.getattr.policy,
cfg->func.create.policy,
cfg->branches,
fusepath_,
mode_,
fc->umask,
ffi_->flags,
&ffi_->fh);
}
int
create(const char *fusepath_,
mode_t mode_,
fuse_file_info_t *ffi_)
{
State s;
gfs::path fusepath(fusepath_);
const fuse_context *fc = fuse_get_context();
const ugid::Set ugid(fc->uid,fc->gid);
if(s->writeback_cache)
l::tweak_flags_writeback_cache(&ffi_->flags);
return s->create(fusepath,mode_,fc->umask,ffi_);
return s->create(&fusepath_[1],mode_,fc->umask,ffi_);
}
}

35
src/fuse_init.cpp

@ -14,8 +14,8 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.hpp"
#include "ugid.hpp"
#include "state.hpp"
#include "fuse.h"
@ -51,7 +51,7 @@ namespace l
void
want_if_capable(fuse_conn_info *conn_,
const int flag_,
ConfigBOOL *want_)
bool *want_)
{
if(*want_ && l::capable(conn_,flag_))
{
@ -65,16 +65,16 @@ namespace l
static
void
want_if_capable_max_pages(fuse_conn_info *conn_,
Config::Write &cfg_)
State &s_)
{
if(l::capable(conn_,FUSE_CAP_MAX_PAGES))
{
l::want(conn_,FUSE_CAP_MAX_PAGES);
conn_->max_pages = cfg_->fuse_msg_size;
conn_->max_pages = s_->fuse_msg_size;
}
else
{
cfg_->fuse_msg_size = FUSE_DEFAULT_MAX_PAGES_PER_REQ;
s_->fuse_msg_size = FUSE_DEFAULT_MAX_PAGES_PER_REQ;
}
}
}
@ -84,23 +84,34 @@ namespace FUSE::INIT
void *
init(fuse_conn_info *conn_)
{
Config::Write cfg;
State s;
bool async_read;
bool posix_acl;
bool wb_cache;
bool readdirplus;
bool cache_symlinks;
async_read = toml::find_or(s->config_toml,"fuse","async-read",true);
posix_acl = toml::find_or(s->config_toml,"fuse","posix-acl",false);
wb_cache = toml::find_or(s->config_toml,"cache","writeback",false);
readdirplus = toml::find_or(s->config_toml,"func","readdir","readdirplus",false);
cache_symlinks = toml::find_or(s->config_toml,"cache","symlinks",false);
ugid::init();
l::want_if_capable(conn_,FUSE_CAP_ASYNC_DIO);
l::want_if_capable(conn_,FUSE_CAP_ASYNC_READ,&cfg->async_read);
l::want_if_capable(conn_,FUSE_CAP_ASYNC_READ,&async_read);
l::want_if_capable(conn_,FUSE_CAP_ATOMIC_O_TRUNC);
l::want_if_capable(conn_,FUSE_CAP_BIG_WRITES);
l::want_if_capable(conn_,FUSE_CAP_CACHE_SYMLINKS,&cfg->cache_symlinks);
l::want_if_capable(conn_,FUSE_CAP_CACHE_SYMLINKS,&cache_symlinks);
l::want_if_capable(conn_,FUSE_CAP_DONT_MASK);
l::want_if_capable(conn_,FUSE_CAP_IOCTL_DIR);
l::want_if_capable(conn_,FUSE_CAP_PARALLEL_DIROPS);
l::want_if_capable(conn_,FUSE_CAP_READDIR_PLUS,&cfg->readdirplus);
l::want_if_capable(conn_,FUSE_CAP_READDIR_PLUS,&readdirplus);
//l::want_if_capable(conn_,FUSE_CAP_READDIR_PLUS_AUTO);
l::want_if_capable(conn_,FUSE_CAP_POSIX_ACL,&cfg->posix_acl);
l::want_if_capable(conn_,FUSE_CAP_WRITEBACK_CACHE,&cfg->writeback_cache);
l::want_if_capable_max_pages(conn_,cfg);
l::want_if_capable(conn_,FUSE_CAP_POSIX_ACL,&posix_acl);
l::want_if_capable(conn_,FUSE_CAP_WRITEBACK_CACHE,&wb_cache);
l::want_if_capable_max_pages(conn_,s);
conn_->want &= ~FUSE_CAP_POSIX_LOCKS;
conn_->want &= ~FUSE_CAP_FLOCK_LOCKS;

121
src/fuse_link.cpp

@ -14,129 +14,12 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.hpp"
#include "errno.hpp"
#include "fs_clonepath.hpp"
#include "fs_link.hpp"
#include "fs_lstat.hpp"
#include "fs_path.hpp"
#include "fuse_getattr.hpp"
#include "fuse_symlink.hpp"
#include "state.hpp"
#include "ugid.hpp"
#include "fuse.h"
namespace l
{
static
int
link_exdev_rel_symlink(const char *oldpath_,
const char *newpath_,
struct stat *st_,
fuse_timeouts_t *timeouts_)
{
int rv;
gfs::path target(oldpath_);
gfs::path linkpath(newpath_);
target = target.lexically_relative(linkpath.parent_path());
rv = FUSE::SYMLINK::symlink(target.c_str(),linkpath.c_str());
if(rv == 0)
rv = FUSE::GETATTR::getattr(oldpath_,st_,timeouts_);
// Disable caching since we created a symlink but should be a regular.
timeouts_->attr = 0;
timeouts_->entry = 0;
return rv;
}
static
int
link_exdev_abs_base_symlink(const char *oldpath_,
const char *newpath_,
struct stat *st_,
fuse_timeouts_t *timeouts_)
{
int rv;
StrVec basepaths;
gfs::path target;
target = "FIXME";
rv = FUSE::SYMLINK::symlink(target.c_str(),newpath_);
if(rv == 0)
rv = FUSE::GETATTR::getattr(oldpath_,st_,timeouts_);
// Disable caching since we created a symlink but should be a regular.
timeouts_->attr = 0;
timeouts_->entry = 0;
return rv;
}
static
int
link_exdev_abs_pool_symlink(const gfs::path &mount_,
const char *oldpath_,
const char *newpath_,
struct stat *st_,
fuse_timeouts_t *timeouts_)
{
int rv;
gfs::path target;
target = mount_ / &oldpath_[1];
rv = FUSE::SYMLINK::symlink(target.c_str(),newpath_);
if(rv == 0)
rv = FUSE::GETATTR::getattr(oldpath_,st_,timeouts_);
// Disable caching since we created a symlink but should be a regular.
timeouts_->attr = 0;
timeouts_->entry = 0;
return rv;
}
static
int
link_exdev(State &s_,
const char *oldpath_,
const char *newpath_,
struct stat *st_,
fuse_timeouts_t *timeouts_)
{
switch(s_->link_exdev)
{
case LinkEXDEV::INVALID:
case LinkEXDEV::PASSTHROUGH:
return -EXDEV;
case LinkEXDEV::REL_SYMLINK:
return l::link_exdev_rel_symlink(oldpath_,
newpath_,
st_,
timeouts_);
case LinkEXDEV::ABS_BASE_SYMLINK:
return l::link_exdev_abs_base_symlink(oldpath_,
newpath_,
st_,
timeouts_);
case LinkEXDEV::ABS_POOL_SYMLINK:
return l::link_exdev_abs_pool_symlink(s_->mountpoint,
oldpath_,
newpath_,
st_,
timeouts_);
}
return -EXDEV;
}
}
namespace FUSE::LINK
{
int
@ -155,8 +38,8 @@ namespace FUSE::LINK
oldpath = &oldpath_[1];
newpath = &newpath_[1];
rv = s->link(oldpath,newpath);
if(rv == -EXDEV)
return l::link_exdev(s,oldpath_,newpath_,st_,timeouts_);
if(rv < 0)
return rv;
return s->getattr(newpath,st_,timeouts_);
}

130
src/fuse_mkdir.cpp

@ -14,137 +14,11 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.hpp"
#include "errno.hpp"
#include "fs_acl.hpp"
#include "fs_clonepath.hpp"
#include "fs_mkdir.hpp"
#include "fs_path.hpp"
#include "ghc/filesystem.hpp"
#include "policy.hpp"
#include "state.hpp"
#include "ugid.hpp"
#include "fuse.h"
#include <string>
using std::string;
namespace error
{
static
inline
int
calc(const int rv_,
const int prev_,
const int cur_)
{
if(rv_ == -1)
{
if(prev_ == 0)
return 0;
return cur_;
}
return 0;
}
}
namespace l
{
static
int
mkdir_core(const string &fullpath_,
mode_t mode_,
const mode_t umask_)
{
if(!fs::acl::dir_has_defaults(fullpath_))
mode_ &= ~umask_;
return fs::mkdir(fullpath_,mode_);
}
static
int
mkdir_loop_core(const string &createpath_,
const char *fusepath_,
const mode_t mode_,
const mode_t umask_,
const int error_)
{
int rv;
string fullpath;
fullpath = fs::path::make(createpath_,fusepath_);
rv = l::mkdir_core(fullpath,mode_,umask_);
return error::calc(rv,error_,errno);
}
static
int
mkdir_loop(const string &existingpath_,
const StrVec &createpaths_,
const char *fusepath_,
const string &fusedirpath_,
const mode_t mode_,
const mode_t umask_)
{
int rv;
int error;
error = -1;
for(size_t i = 0, ei = createpaths_.size(); i != ei; i++)
{
rv = fs::clonepath_as_root(existingpath_,createpaths_[i],fusedirpath_);
if(rv == -1)
error = error::calc(rv,error,errno);
else
error = l::mkdir_loop_core(createpaths_[i],
fusepath_,
mode_,
umask_,
error);
}
return -error;
}
static
int
mkdir(const Policy::Search &getattrPolicy_,
const Policy::Create &mkdirPolicy_,
const Branches &branches_,
const char *fusepath_,
const mode_t mode_,
const mode_t umask_)
{
int rv;
string fusedirpath;
StrVec createpaths;
StrVec existingpaths;
fusedirpath = fs::path::dirname(fusepath_);
rv = getattrPolicy_(branches_,fusedirpath.c_str(),&existingpaths);
if(rv == -1)
return -errno;
rv = mkdirPolicy_(branches_,fusedirpath.c_str(),&createpaths);
if(rv == -1)
return -errno;
return l::mkdir_loop(existingpaths[0],
createpaths,
fusepath_,
fusedirpath,
mode_,
umask_);
}
}
namespace FUSE::MKDIR
{
@ -153,11 +27,9 @@ namespace FUSE::MKDIR
mode_t mode_)
{
State s;
gfs::path fusepath;
const fuse_context *fc = fuse_get_context();
const ugid::Set ugid(fc->uid,fc->gid);
fusepath = &fusepath_[1];
return s->mkdir(fusepath,mode_,fc->umask);
return s->mkdir(&fusepath_[1],mode_,fc->umask);
}
}

58
src/fuse_readdir_plus.cpp

@ -1,58 +0,0 @@
/*
ISC License
Copyright (c) 2020, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "fuse_readdir_plus_linux.hpp"
#include "fuse_readdir_plus_posix.hpp"
#include "config.hpp"
#include "dirinfo.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
#include "fuse.h"
namespace FUSE::READDIR_PLUS
{
int
readdir_plus(const fuse_file_info_t *ffi_,
fuse_dirents_t *buf_)
{
Config::Read cfg;
DirInfo *di = reinterpret_cast<DirInfo*>(ffi_->fh);
const fuse_context *fc = fuse_get_context();
const ugid::Set ugid(fc->uid,fc->gid);
switch(cfg->readdir)
{
case ReadDir::ENUM::LINUX:
return FUSE::READDIR_PLUS_LINUX::readdir_plus_linux(cfg->branches,
di->fusepath.c_str(),
cfg->cache_entry,
cfg->cache_attr,
buf_);
default:
case ReadDir::ENUM::POSIX:
return FUSE::READDIR_PLUS_POSIX::readdir_plus_posix(cfg->branches,
di->fusepath.c_str(),
cfg->cache_entry,
cfg->cache_attr,
buf_);
}
}
}

37
src/fuse_readdirplus.cpp

@ -0,0 +1,37 @@
/*
ISC License
Copyright (c) 2022, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "state.hpp"
#include "ugid.hpp"
#include "fuse.h"
namespace FUSE::READDIRPLUS
{
int
readdirplus(const fuse_file_info_t *ffi_,
fuse_dirents_t *buf_)
{
State s;
const fuse_context *fc = fuse_get_context();
const ugid::Set ugid(fc->uid,fc->gid);
return s->readdirplus(ffi_,buf_);
}
}

4
src/fuse_readdir_plus.hpp → src/fuse_readdirplus.hpp

@ -19,9 +19,9 @@
#include "fuse.h"
namespace FUSE::READDIR_PLUS
namespace FUSE::READDIRPLUS
{
int
readdir_plus(const fuse_file_info_t *ffi,
readdirplus(const fuse_file_info_t *ffi,
fuse_dirents_t *buf);
}

48
src/fuse_readdirplus_policy.hpp

@ -0,0 +1,48 @@
/*
ISC License
Copyright (c) 2022, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include "fuse_readdirplus_policy_base.hpp"
#include "fuse_readdirplus_policy_factory.hpp"
#include "fuse.h"
namespace FUSE::READDIRPLUS
{
class Policy
{
public:
Policy(const toml::value &toml_)
{
_readdirplus = POLICY::factory(toml_);
}
public:
int
operator()(const fuse_file_info_t *ffi_,
fuse_dirents_t *buf_)
{
return (*_readdirplus)(ffi_,buf_);
}
private:
POLICY::Base::Ptr _readdirplus;
};
}

37
src/fuse_readdirplus_policy_base.hpp

@ -0,0 +1,37 @@
/*
ISC License
Copyright (c) 2022, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include "fuse.h"
#include <memory>
namespace FUSE::READDIRPLUS::POLICY
{
class Base
{
public:
typedef std::shared_ptr<Base> Ptr;
public:
virtual int operator()(const fuse_file_info_t *ffi,
fuse_dirents_t *buf) = 0;
};
}

34
src/fuse_readdirplus_policy_enosys.cpp

@ -0,0 +1,34 @@
/*
ISC License
Copyright (c) 2022, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "fuse_readdirplus_policy_enosys.hpp"
#include "errno.hpp"
FUSE::READDIRPLUS::POLICY::enosys::enosys(const toml::value &toml_)
{
}
int
FUSE::READDIRPLUS::POLICY::enosys::operator()(const fuse_file_info_t *ffi_,
fuse_dirents_t *buf_)
{
return -ENOSYS;
}

39
src/fuse_readdirplus_policy_enosys.hpp

@ -0,0 +1,39 @@
/*
ISC License
Copyright (c) 2022, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include "fuse_readdirplus_policy_base.hpp"
#include "branches.hpp"
#include "toml.hpp"
namespace FUSE::READDIRPLUS::POLICY
{
class enosys : public Base
{
public:
enosys(const toml::value &);
public:
int operator()(const fuse_file_info_t *ffi,
fuse_dirents_t *buf) final;
};
}

39
src/fuse_readdirplus_policy_factory.cpp

@ -0,0 +1,39 @@
/*
ISC License
Copyright (c) 2022, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "fuse_readdirplus_policy_factory.hpp"
#include "fuse_readdirplus_policy_enosys.hpp"
#include <stdexcept>
namespace FUSE::READDIRPLUS::POLICY
{
Base::Ptr
factory(const toml::value &toml_)
{
std::string str;
str = toml::find_or(toml_,"func","readdirplus","policy","enosys");
if(str == "enosys")
return std::make_shared<enosys>(toml_);
throw std::runtime_error("readdirplus");
}
}

30
src/fuse_readdirplus_policy_factory.hpp

@ -0,0 +1,30 @@
/*
ISC License
Copyright (c) 2022, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include "fuse_readdirplus_policy_base.hpp"
#include "toml.hpp"
namespace FUSE::READDIRPLUS::POLICY
{
Base::Ptr
factory(const toml::value &);
}

21
src/fuse_readdir_plus_linux.cpp → src/fuse_readdirplus_policy_linux.cpp

@ -14,6 +14,8 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "fuse_readdirplus_policy_linux.hpp"
#include "branches.hpp"
#include "errno.hpp"
#include "fs_close.hpp"
@ -137,15 +139,16 @@ namespace l
}
}
namespace FUSE::READDIR_PLUS_LINUX
FUSE::READDIRPLUS::POLICY::linux::linux(const toml::value &toml_)
: _branches(toml_)
{
int
readdir_plus_linux(const Branches::CPtr &branches_,
const char *dirname_,
const uint64_t entry_timeout_,
const uint64_t attr_timeout_,
}
int
FUSE::READDIRPLUS::POLICY::linux::operator()(const fuse_file_info_t *ffi_,
fuse_dirents_t *buf_)
{
return l::readdir_plus(branches_,dirname_,entry_timeout_,attr_timeout_,buf_);
}
{
return -ENOENT;
}

24
src/fuse_readdir_plus_posix.hpp → src/fuse_readdirplus_policy_linux.hpp

@ -18,19 +18,25 @@
#pragma once
#include "fuse_readdirplus_policy_base.hpp"
#include "branches.hpp"
#include "fuse.h"
#include <cstdint>
namespace FUSE::READDIR_PLUS_POSIX
namespace FUSE::READDIRPLUS::POLICY
{
int
readdir_plus_posix(const Branches::CPtr &branches,
const char *dirname,
const uint64_t entry_timeout,
const uint64_t attr_timeout,
fuse_dirents_t *buf);
class linux : public Base
{
public:
linux(const toml::value &);
public:
int operator()(const fuse_file_info_t *ffi,
fuse_dirents_t *buf) final;
private:
Branches2 _branches;
};
}

21
src/fuse_readdir_plus_posix.cpp → src/fuse_readdirplus_policy_posix.cpp

@ -16,6 +16,8 @@
#define _DEFAULT_SOURCE
#include "fuse_readdirplus_policy_posix.hpp"
#include "branches.hpp"
#include "errno.hpp"
#include "fs_closedir.hpp"
@ -128,15 +130,16 @@ namespace l
}
}
namespace FUSE::READDIR_PLUS_POSIX
FUSE::READDIRPLUS::POLICY::POSIX::POSIX(const toml::value &toml_)
: _branches(toml_)
{
int
readdir_plus_posix(const Branches::CPtr &branches_,
const char *dirname_,
const uint64_t entry_timeout_,
const uint64_t attr_timeout_,
}
int
FUSE::READDIRPLUS::POLICY::POSIX::operator()(const fuse_file_info_t *ffi_,
fuse_dirents_t *buf_)
{
return l::readdir_plus(branches_,dirname_,entry_timeout_,attr_timeout_,buf_);
}
{
return -ENOENT;
}

26
src/fuse_readdir_plus_linux.hpp → src/fuse_readdirplus_policy_posix.hpp

@ -1,7 +1,7 @@
/*
ISC License
Copyright (c) 2020, Antonio SJ Musumeci <trapexit@spawn.link>
Copyright (c) 2022, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
@ -18,19 +18,25 @@
#pragma once
#include "fuse_readdirplus_policy_base.hpp"
#include "branches.hpp"
#include "fuse.h"
#include <cstdint>
namespace FUSE::READDIR_PLUS_LINUX
namespace FUSE::READDIRPLUS::POLICY
{
int
readdir_plus_linux(const Branches::CPtr &branches,
const char *dirname,
const uint64_t entry_timeout,
const uint64_t attr_timeout,
fuse_dirents_t *buf);
class POSIX : public Base
{
public:
POSIX(const toml::value &);
public:
int operator()(const fuse_file_info_t *ffi,
fuse_dirents_t *buf) final;
private:
Branches2 _branches;
};
}

126
src/fuse_statfs.cpp

@ -14,135 +14,11 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "errno.hpp"
#include "fs_lstat.hpp"
#include "fs_path.hpp"
#include "fs_statvfs.hpp"
#include "statvfs_util.hpp"
#include "state.hpp"
#include "ugid.hpp"
#include "fuse.h"
#include <algorithm>
#include <limits>
#include <map>
#include <string>
#include <vector>
using std::string;
using std::map;
using std::vector;
namespace l
{
static
void
normalize_statvfs(struct statvfs *fsstat_,
const unsigned long min_bsize_,
const unsigned long min_frsize_,
const unsigned long min_namemax_)
{
fsstat_->f_blocks = (fsblkcnt_t)((fsstat_->f_blocks * fsstat_->f_frsize) / min_frsize_);
fsstat_->f_bfree = (fsblkcnt_t)((fsstat_->f_bfree * fsstat_->f_frsize) / min_frsize_);
fsstat_->f_bavail = (fsblkcnt_t)((fsstat_->f_bavail * fsstat_->f_frsize) / min_frsize_);
fsstat_->f_bsize = min_bsize_;
fsstat_->f_frsize = min_frsize_;
fsstat_->f_namemax = min_namemax_;
}
static
void
merge_statvfs(struct statvfs * const out_,
const struct statvfs * const in_)
{
out_->f_blocks += in_->f_blocks;
out_->f_bfree += in_->f_bfree;
out_->f_bavail += in_->f_bavail;
out_->f_files += in_->f_files;
out_->f_ffree += in_->f_ffree;
out_->f_favail += in_->f_favail;
}
static
bool
should_ignore(const StatFSIgnore ignore_,
const Branch &branch_,
const bool readonly_)
{
return ((((ignore_ == StatFSIgnore::ENUM::RO) || readonly_) &&
(branch_.ro_or_nc())) ||
((ignore_ == StatFSIgnore::ENUM::NC) && (branch_.nc())));
}
static
int
statfs(const Branches::CPtr &branches_,
const char *fusepath_,
const StatFS mode_,
const StatFSIgnore ignore_,
struct statvfs *fsstat_)
{
int rv;
string fullpath;
struct stat st;
struct statvfs stvfs;
unsigned long min_bsize;
unsigned long min_frsize;
unsigned long min_namemax;
map<dev_t,struct statvfs> fsstats;
min_bsize = std::numeric_limits<unsigned long>::max();
min_frsize = std::numeric_limits<unsigned long>::max();
min_namemax = std::numeric_limits<unsigned long>::max();
for(const auto &branch : *branches_)
{
fullpath = ((mode_ == StatFS::ENUM::FULL) ?
fs::path::make(branch.path,fusepath_) :
branch.path);
rv = fs::lstat(fullpath,&st);
if(rv == -1)
continue;
rv = fs::lstatvfs(fullpath,&stvfs);
if(rv == -1)
continue;
if(stvfs.f_bsize && (min_bsize > stvfs.f_bsize))
min_bsize = stvfs.f_bsize;
if(stvfs.f_frsize && (min_frsize > stvfs.f_frsize))
min_frsize = stvfs.f_frsize;
if(stvfs.f_namemax && (min_namemax > stvfs.f_namemax))
min_namemax = stvfs.f_namemax;
if(l::should_ignore(ignore_,branch,StatVFS::readonly(stvfs)))
{
stvfs.f_bavail = 0;
stvfs.f_favail = 0;
}
fsstats.insert(std::make_pair(st.st_dev,stvfs));
}
map<dev_t,struct statvfs>::iterator iter = fsstats.begin();
map<dev_t,struct statvfs>::iterator enditer = fsstats.end();
if(iter != enditer)
{
*fsstat_ = iter->second;
l::normalize_statvfs(fsstat_,min_bsize,min_frsize,min_namemax);
for(++iter; iter != enditer; ++iter)
{
l::normalize_statvfs(&iter->second,min_bsize,min_frsize,min_namemax);
l::merge_statvfs(fsstat_,&iter->second);
}
}
return 0;
}
}
namespace FUSE::STATFS
{

33
src/fuse_statfs_policy_branch.cpp

@ -0,0 +1,33 @@
/*
ISC License
Copyright (c) 2022, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "fuse_statfs_policy_branch.hpp"
FUSE::STATFS::POLICY::Branch::Branch(const toml::value &toml_)
: _branches(toml_)
{
}
int
FUSE::STATFS::POLICY::Branch::operator()(const gfs::path &fusepath_,
struct statvfs *fsstat)
{
return 0;
}

6
src/fuse_statfs_policy_full.hpp

@ -18,7 +18,11 @@
#pragma once
#include "fuse_statfs_policy_full.hpp"
#include "fuse_statfs_policy_base.hpp"
#include "branches.hpp"
#include "toml.hpp"
namespace FUSE::STATFS::POLICY

150
src/fuse_symlink.cpp

@ -14,130 +14,11 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.hpp"
#include "errno.hpp"
#include "fs_clonepath.hpp"
#include "fs_lstat.hpp"
#include "fs_path.hpp"
#include "fs_inode.hpp"
#include "fs_symlink.hpp"
#include "fuse_getattr.hpp"
#include "ugid.hpp"
#include "state.hpp"
#include "ugid.hpp"
#include "fuse.h"
#include <string>
#include <sys/types.h>
#include <unistd.h>
using std::string;
namespace error
{
static
inline
int
calc(const int rv_,
const int prev_,
const int cur_)
{
if(rv_ == -1)
{
if(prev_ == 0)
return 0;
return cur_;
}
return 0;
}
}
namespace l
{
static
int
symlink_loop_core(const string &newbasepath_,
const char *target_,
const char *linkpath_,
struct stat *st_,
const int error_)
{
int rv;
string fullnewpath;
fullnewpath = fs::path::make(newbasepath_,linkpath_);
rv = fs::symlink(target_,fullnewpath);
if((rv != -1) && (st_ != NULL) && (st_->st_ino == 0))
{
fs::lstat(fullnewpath,st_);
if(st_->st_ino != 0)
fs::inode::calc(linkpath_,st_);
}
return error::calc(rv,error_,errno);
}
static
int
symlink_loop(const string &existingpath_,
const StrVec &newbasepaths_,
const char *target_,
const char *linkpath_,
const string &newdirpath_,
struct stat *st_)
{
int rv;
int error;
error = -1;
for(size_t i = 0, ei = newbasepaths_.size(); i != ei; i++)
{
rv = fs::clonepath_as_root(existingpath_,newbasepaths_[i],newdirpath_);
if(rv == -1)
error = error::calc(rv,error,errno);
else
error = l::symlink_loop_core(newbasepaths_[i],
target_,
linkpath_,
st_,
error);
}
return -error;
}
static
int
symlink(const Policy::Search &searchFunc_,
const Policy::Create &createFunc_,
const Branches &branches_,
const char *target_,
const char *linkpath_,
struct stat *st_)
{
int rv;
string newdirpath;
StrVec newbasepaths;
StrVec existingpaths;
newdirpath = fs::path::dirname(linkpath_);
rv = searchFunc_(branches_,newdirpath,&existingpaths);
if(rv == -1)
return -errno;
rv = createFunc_(branches_,newdirpath,&newbasepaths);
if(rv == -1)
return -errno;
return l::symlink_loop(existingpaths[0],newbasepaths,
target_,linkpath_,newdirpath,st_);
}
}
namespace FUSE::SYMLINK
{
@ -147,35 +28,10 @@ namespace FUSE::SYMLINK
struct stat *st_,
fuse_timeouts_t *timeouts_)
{
int rv;
Config::Read cfg;
State s;
const fuse_context *fc = fuse_get_context();
const ugid::Set ugid(fc->uid,fc->gid);
rv = l::symlink(cfg->func.getattr.policy,
cfg->func.symlink.policy,
cfg->branches,
target_,
linkpath_,
st_);
if(timeouts_ != NULL)
{
switch(cfg->follow_symlinks)
{
case FollowSymlinks::ENUM::NEVER:
timeouts_->entry = ((rv >= 0) ?
cfg->cache_entry :
cfg->cache_negative_entry);
timeouts_->attr = cfg->cache_attr;
break;
default:
timeouts_->entry = 0;
timeouts_->attr = 0;
break;
}
}
return rv;
return s->symlink(target_,&linkpath_[1],st_,timeouts_);
}
}

3
src/fuse_symlink.hpp

@ -18,9 +18,6 @@
#include "fuse.h"
#include "toml.hpp"
#include <sys/stat.h>
namespace FUSE::SYMLINK
{

6
src/fuse_symlink_policy.hpp

@ -37,9 +37,11 @@ namespace FUSE::SYMLINK
public:
int
operator()(const char *target_,
const gfs::path &linkpath_)
const gfs::path &linkpath_,
struct stat *st_ = NULL,
fuse_timeouts_t *timeouts_ = NULL)
{
return (*_symlink)(target_,linkpath_);
return (*_symlink)(target_,linkpath_,st_,timeouts_);
}
private:

6
src/fuse_symlink_policy_base.hpp

@ -20,6 +20,8 @@
#include "fs_path.hpp"
#include "fuse.h"
#include <memory>
@ -32,6 +34,8 @@ namespace FUSE::SYMLINK::POLICY
public:
virtual int operator()(const char *target,
const gfs::path &linkpath) = 0;
const gfs::path &linkpath,
struct stat *st_ = NULL,
fuse_timeouts_t *timeouts_ = NULL) = 0;
};
}

4
src/fuse_symlink_policy_epff.cpp

@ -29,7 +29,9 @@ FUSE::SYMLINK::POLICY::EPFF::EPFF(const toml::value &toml_)
int
FUSE::SYMLINK::POLICY::EPFF::operator()(const char *target_,
const gfs::path &linkpath_)
const gfs::path &linkpath_,
struct stat *st_,
fuse_timeouts_t *timeouts_)
{
int rv;
gfs::path fullpath;

4
src/fuse_symlink_policy_epff.hpp

@ -32,7 +32,9 @@ namespace FUSE::SYMLINK::POLICY
public:
int operator()(const char *target,
const gfs::path &linkpath) final;
const gfs::path &linkpath,
struct stat *st,
fuse_timeouts_t *timeouts) final;
private:
Branches2 _branches;

4
src/fuse_symlink_policy_ff.cpp

@ -32,7 +32,9 @@ FUSE::SYMLINK::POLICY::FF::FF(const toml::value &toml_)
int
FUSE::SYMLINK::POLICY::FF::operator()(const char *target_,
const gfs::path &linkpath_)
const gfs::path &linkpath_,
struct stat *st_,
fuse_timeouts_t *timeouts_)
{
int rv;
gfs::path fullpath;

4
src/fuse_symlink_policy_ff.hpp

@ -32,7 +32,9 @@ namespace FUSE::SYMLINK::POLICY
public:
int operator()(const char *target,
const gfs::path &linkpath) final;
const gfs::path &linkpath,
struct stat *st,
fuse_timeouts_t *timeouts) final;
private:
Branches2 _branches;

116
src/fuse_utimens.cpp

@ -14,132 +14,22 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.hpp"
#include "errno.hpp"
#include "fs_lutimens.hpp"
#include "fs_path.hpp"
#include "policy_rv.hpp"
#include "state.hpp"
#include "ugid.hpp"
#include "fuse.h"
#include <string>
#include <fcntl.h>
using std::string;
namespace l
{
static
int
get_error(const PolicyRV &prv_,
const string &basepath_)
{
for(int i = 0, ei = prv_.success.size(); i < ei; i++)
{
if(prv_.success[i].basepath == basepath_)
return prv_.success[i].rv;
}
for(int i = 0, ei = prv_.error.size(); i < ei; i++)
{
if(prv_.error[i].basepath == basepath_)
return prv_.error[i].rv;
}
return 0;
}
static
void
utimens_loop_core(const string &basepath_,
const char *fusepath_,
const timespec ts_[2],
PolicyRV *prv_)
{
string fullpath;
fullpath = fs::path::make(basepath_,fusepath_);
errno = 0;
fs::lutimens(fullpath,ts_);
prv_->insert(errno,basepath_);
}
static
void
utimens_loop(const StrVec &basepaths_,
const char *fusepath_,
const timespec ts_[2],
PolicyRV *prv_)
{
for(size_t i = 0, ei = basepaths_.size(); i != ei; i++)
{
l::utimens_loop_core(basepaths_[i],fusepath_,ts_,prv_);
}
}
static
int
utimens(const Policy::Action &utimensPolicy_,
const Policy::Search &getattrPolicy_,
const Branches &branches_,
const char *fusepath_,
const timespec ts_[2])
{
int rv;
PolicyRV prv;
StrVec basepaths;
rv = utimensPolicy_(branches_,fusepath_,&basepaths);
if(rv == -1)
return -errno;
l::utimens_loop(basepaths,fusepath_,ts_,&prv);
if(prv.error.empty())
return 0;
if(prv.success.empty())
return prv.error[0].rv;
basepaths.clear();
rv = getattrPolicy_(branches_,fusepath_,&basepaths);
if(rv == -1)
return -errno;
return l::get_error(prv,basepaths[0]);
}
}
namespace FUSE::UTIMENS
{
int
config(const toml::value &toml_)
{
std::string val;
Config::Write cfg;
val = toml::find<std::string>(toml_,"func","utimens","policy");
cfg->func.utimens.from_string(val);
return 0;
}
int
utimens(const char *fusepath_,
const timespec ts_[2])
{
Config::Read cfg;
State s;
const fuse_context *fc = fuse_get_context();
const ugid::Set ugid(fc->uid,fc->gid);
return l::utimens(cfg->func.utimens.policy,
cfg->func.getattr.policy,
cfg->branches,
fusepath_,
ts_);
return s->utimens(&fusepath_[1],ts_);
}
}

22
src/fuse_utimens_policy.hpp

@ -18,25 +18,31 @@
#pragma once
#include "fuse_utimens_func_base.hpp"
#include "fuse_utimens_policy_base.hpp"
#include "fuse_utimens_policy_factory.hpp"
#include "toml.hpp"
#include <sys/stat.h>
namespace FUSE::UTIMENS
{
class Func
class Policy
{
public:
Func(const toml::value &);
Policy(const toml::value &toml_)
{
_utimens = POLICY::factory(toml_);
}
public:
int operator()(const char *fusepath,
const timespec ts_[2]);
int
operator()(const gfs::path &fusepath_,
const timespec ts_[2])
{
return (*_utimens)(fusepath_,ts_);
}
private:
FuncBase::Ptr _utimens;
POLICY::Base::Ptr _utimens;
};
}

2
src/fuse_utimens_policy_base.hpp

@ -20,6 +20,8 @@
#include "fs_path.hpp"
#include "fuse.h"
#include <memory>

13
src/mergerfs.cpp

@ -54,7 +54,7 @@
#include "fuse_prepare_hide.hpp"
#include "fuse_read_buf.hpp"
#include "fuse_readdir.hpp"
#include "fuse_readdir_plus.hpp"
#include "fuse_readdirplus.hpp"
#include "fuse_readlink.hpp"
#include "fuse_release.hpp"
#include "fuse_releasedir.hpp"
@ -84,8 +84,7 @@ namespace l
{
static
void
get_fuse_operations(struct fuse_operations &ops_,
const bool nullrw_)
get_fuse_operations(struct fuse_operations &ops_)
{
ops_.access = FUSE::ACCESS::access;
ops_.bmap = FUSE::BMAP::bmap;
@ -118,9 +117,9 @@ namespace l
ops_.opendir = FUSE::OPENDIR::opendir;
ops_.poll = FUSE::POLL::poll;;
ops_.prepare_hide = FUSE::PREPARE_HIDE::prepare_hide;
ops_.read_buf = (nullrw_ ? FUSE::READ_BUF::read_buf_null : FUSE::READ_BUF::read_buf);
// ops_.read_buf = FUSE::READ::read;
ops_.readdir = FUSE::READDIR::readdir;
ops_.readdir_plus = FUSE::READDIR_PLUS::readdir_plus;
ops_.readdir_plus = FUSE::READDIRPLUS::readdirplus;
ops_.readlink = FUSE::READLINK::readlink;
ops_.release = FUSE::RELEASE::release;
ops_.releasedir = FUSE::RELEASEDIR::releasedir;
@ -133,7 +132,7 @@ namespace l
ops_.truncate = FUSE::TRUNCATE::truncate;
ops_.unlink = FUSE::UNLINK::unlink;
ops_.utimens = FUSE::UTIMENS::utimens;
ops_.write_buf = (nullrw_ ? FUSE::WRITE_BUF::write_buf_null : FUSE::WRITE_BUF::write_buf);
// ops_.write_buf = FUSE::WRITE::write;
return;
}
@ -165,7 +164,7 @@ namespace l
args.allocated = 0;
l::setup_resources();
l::get_fuse_operations(ops,false);
l::get_fuse_operations(ops);
return fuse_main(args.argc,
args.argv,

7
src/state.cpp

@ -40,15 +40,18 @@ StateBase::StateBase(const toml::value &toml_)
mknod(toml_),
open(toml_),
readdir(toml_),
readdirplus(toml_),
readlink(toml_),
removexattr(toml_),
rename(toml_),
rmdir(toml_),
setxattr(toml_),
statfs(toml_),
symlink(toml_),
truncate(toml_),
write(toml_),
unlink(toml_)
unlink(toml_),
utimens(toml_),
write(toml_)
{
mountpoint = toml::find<std::string>(toml_,"filesystem","mountpoint");

21
src/state.hpp

@ -31,14 +31,17 @@
#include "fuse_mknod_policy.hpp"
#include "fuse_open_policy.hpp"
#include "fuse_readdir_policy.hpp"
#include "fuse_readdirplus_policy.hpp"
#include "fuse_readlink_policy.hpp"
#include "fuse_removexattr_policy.hpp"
#include "fuse_rename_policy.hpp"
#include "fuse_rmdir_policy.hpp"
#include "fuse_setxattr_policy.hpp"
#include "fuse_statfs_policy.hpp"
#include "fuse_symlink_policy.hpp"
#include "fuse_truncate_policy.hpp"
#include "fuse_unlink_policy.hpp"
#include "fuse_utimens_policy.hpp"
#include "fuse_write_policy.hpp"
#include "branches.hpp"
@ -46,7 +49,7 @@
#include "link_exdev_enum.hpp"
#include "rename_exdev_enum.hpp"
#include "ghc/filesystem.hpp"
#include "fs_path.hpp"
#include <atomic>
#include <memory>
@ -64,6 +67,14 @@ public:
public:
StateBase(const toml::value &);
public:
uint64_t fuse_msg_size;
public:
bool async_read;
bool cache_symlinks;
bool posix_acl;
public:
int entry_cache_timeout;
int neg_entry_cache_timeout;
@ -80,7 +91,7 @@ public:
bool security_capability;
public:
ghc::filesystem::path mountpoint;
gfs::path mountpoint;
Branches2 branches;
public:
@ -107,19 +118,21 @@ public:
FUSE::MKNOD::Policy mknod;
FUSE::OPEN::Policy open;
FUSE::READDIR::Policy readdir;
FUSE::READDIRPLUS::Policy readdirplus;
FUSE::READLINK::Policy readlink;
FUSE::REMOVEXATTR::Policy removexattr;
FUSE::RENAME::Policy rename;
FUSE::RMDIR::Policy rmdir;
FUSE::SETXATTR::Policy setxattr;
FUSE::STATFS::Policy statfs;
FUSE::SYMLINK::Policy symlink;
FUSE::TRUNCATE::Policy truncate;
FUSE::UNLINK::Policy unlink;
FUSE::UTIMENS::Policy utimens;
FUSE::WRITE::Policy write;
public:
const toml::value _toml;
const toml::value config_toml;
};
class State

Loading…
Cancel
Save