Browse Source

config: rework global config, remove rwlock, make branches RCU like

Also added unit tests. Should have done separately but found a number of bugs.
pull/865/head
Antonio SJ Musumeci 4 years ago
parent
commit
538467b86d
  1. 2
      LICENSE
  2. 32
      Makefile
  3. 366
      src/branch.cpp
  4. 67
      src/branch.hpp
  5. 429
      src/branches.cpp
  6. 94
      src/branches.hpp
  7. 49
      src/category.cpp
  8. 93
      src/category.hpp
  9. 228
      src/config.cpp
  10. 98
      src/config.hpp
  11. 1
      src/config_cachefiles.hpp
  12. 1
      src/config_inodecalc.cpp
  13. 5
      src/config_inodecalc.hpp
  14. 9
      src/config_moveonenospc.cpp
  15. 14
      src/config_moveonenospc.hpp
  16. 1
      src/config_nfsopenhack.cpp
  17. 1
      src/config_nfsopenhack.hpp
  18. 1
      src/config_readdir.cpp
  19. 1
      src/config_readdir.hpp
  20. 1
      src/config_statfs.cpp
  21. 1
      src/config_statfs.hpp
  22. 1
      src/config_statfsignore.cpp
  23. 1
      src/config_xattr.cpp
  24. 1
      src/config_xattr.hpp
  25. 1
      src/dirinfo.hpp
  26. 1
      src/endian.hpp
  27. 1
      src/enum.hpp
  28. 1
      src/fh.hpp
  29. 1
      src/fileinfo.hpp
  30. 4
      src/fixed_mem_pool.hpp
  31. 17
      src/from_string.cpp
  32. 2
      src/from_string.hpp
  33. 1
      src/fs_acl.cpp
  34. 1
      src/fs_acl.hpp
  35. 1
      src/fs_attr.hpp
  36. 1
      src/fs_attr_linux.icpp
  37. 1
      src/fs_attr_unsupported.icpp
  38. 1
      src/fs_clonefile.cpp
  39. 1
      src/fs_clonefile.hpp
  40. 5
      src/fs_clonepath.cpp
  41. 1
      src/fs_clonepath.hpp
  42. 1
      src/fs_close.hpp
  43. 1
      src/fs_closedir.hpp
  44. 4
      src/fs_copy_file_range.hpp
  45. 4
      src/fs_copy_file_range_linux.icpp
  46. 4
      src/fs_copy_file_range_unsupported.icpp
  47. 1
      src/fs_copydata.cpp
  48. 1
      src/fs_copydata.hpp
  49. 3
      src/fs_copydata_copy_file_range.cpp
  50. 3
      src/fs_copydata_copy_file_range.hpp
  51. 1
      src/fs_copydata_readwrite.cpp
  52. 1
      src/fs_copydata_readwrite.hpp
  53. 1
      src/fs_cow.cpp
  54. 1
      src/fs_cow.hpp
  55. 1
      src/fs_devid.hpp
  56. 1
      src/fs_dirfd.hpp
  57. 1
      src/fs_dup.hpp
  58. 1
      src/fs_eaccess.hpp
  59. 1
      src/fs_exists.hpp
  60. 1
      src/fs_faccessat.hpp
  61. 1
      src/fs_fadvise.hpp
  62. 1
      src/fs_fadvise_posix.icpp
  63. 1
      src/fs_fadvise_unsupported.icpp
  64. 1
      src/fs_fallocate.hpp
  65. 1
      src/fs_fallocate_linux.icpp
  66. 3
      src/fs_fallocate_osx.icpp
  67. 1
      src/fs_fallocate_posix.icpp
  68. 1
      src/fs_fallocate_unsupported.icpp
  69. 1
      src/fs_fchmod.hpp
  70. 1
      src/fs_fchmodat.hpp
  71. 1
      src/fs_fchown.hpp
  72. 1
      src/fs_fdatasync.hpp
  73. 1
      src/fs_fgetxattr.hpp
  74. 1
      src/fs_ficlone.hpp
  75. 1
      src/fs_ficlone_linux.icpp
  76. 1
      src/fs_ficlone_unsupported.icpp
  77. 3
      src/fs_file_size.cpp
  78. 3
      src/fs_file_size.hpp
  79. 1
      src/fs_findallfiles.cpp
  80. 9
      src/fs_findallfiles.hpp
  81. 32
      src/fs_findonfs.cpp
  82. 11
      src/fs_findonfs.hpp
  83. 1
      src/fs_flistxattr.hpp
  84. 1
      src/fs_flock.hpp
  85. 1
      src/fs_fsetxattr.hpp
  86. 1
      src/fs_fstat.hpp
  87. 1
      src/fs_fstatat.hpp
  88. 1
      src/fs_fsync.hpp
  89. 1
      src/fs_ftruncate.hpp
  90. 1
      src/fs_futimens.hpp
  91. 1
      src/fs_futimens_freebsd_11.hpp
  92. 1
      src/fs_futimens_generic.hpp
  93. 1
      src/fs_futimens_linux.hpp
  94. 1
      src/fs_futimesat.hpp
  95. 1
      src/fs_futimesat_generic.icpp
  96. 1
      src/fs_futimesat_osx.icpp
  97. 1
      src/fs_getdents64.cpp
  98. 1
      src/fs_getdents64.hpp
  99. 1
      src/fs_getfl.cpp
  100. 1
      src/fs_getfl.hpp

2
LICENSE

@ -1,7 +1,7 @@
/* /*
ISC License ISC License
Copyright (c) 2020, Antonio SJ Musumeci <trapexit@spawn.link>
Copyright (c) 2021, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above

32
Makefile

@ -58,13 +58,20 @@ LTO_FLAGS :=
endif endif
SRC = $(wildcard src/*.cpp) SRC = $(wildcard src/*.cpp)
OBJS = $(SRC:src/%.cpp=build/%.o)
DEPS = $(SRC:src/%.cpp=build/%.d)
OBJS = $(SRC:src/%.cpp=build/.src/%.o)
DEPS = $(SRC:src/%.cpp=build/.src/%.d)
TESTS = $(wildcard tests/*.cpp)
TESTS_OBJS = $(filter-out build/.src/mergerfs.o,$(OBJS))
TESTS_OBJS += $(TESTS:tests/%.cpp=build/.tests/%.o)
TESTS_DEPS = $(TESTS:tests/%.cpp=build/.tests/%.d)
TESTS_DEPS += $(DEPS)
MANPAGE = mergerfs.1 MANPAGE = mergerfs.1
CXXFLAGS ?= ${OPT_FLAGS} CXXFLAGS ?= ${OPT_FLAGS}
CXXFLAGS := \ CXXFLAGS := \
${CXXFLAGS} \ ${CXXFLAGS} \
-std=c++0x \
-std=c++11 \
$(STATIC_FLAGS) \ $(STATIC_FLAGS) \
$(LTO_FLAGS) \ $(LTO_FLAGS) \
-Wall \ -Wall \
@ -77,6 +84,9 @@ FUSE_FLAGS = \
MFS_FLAGS = \ MFS_FLAGS = \
-DUSE_XATTR=$(USE_XATTR) \ -DUSE_XATTR=$(USE_XATTR) \
-DUGID_USE_RWLOCK=$(UGID_USE_RWLOCK) -DUGID_USE_RWLOCK=$(UGID_USE_RWLOCK)
TESTS_FLAGS = \
-Isrc \
-DTESTS
LDFLAGS := \ LDFLAGS := \
${LDFLAGS} \ ${LDFLAGS} \
@ -110,11 +120,19 @@ help:
objects: version build/stamp objects: version build/stamp
$(MAKE) $(OBJS) $(MAKE) $(OBJS)
tests-objects:
$(MAKE) $(TESTS_OBJS)
build/mergerfs: libfuse objects build/mergerfs: libfuse objects
$(CXX) $(CXXFLAGS) $(FUSE_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) $(OBJS) -o $@ libfuse/build/libfuse.a $(LDFLAGS) $(CXX) $(CXXFLAGS) $(FUSE_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) $(OBJS) -o $@ libfuse/build/libfuse.a $(LDFLAGS)
build/tests: build/mergerfs tests-objects
$(CXX) $(CXXFLAGS) $(TESTS_FLAGS) $(FUSE_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) $(TESTS_OBJS) -o $@ libfuse/build/libfuse.a $(LDFLAGS)
mergerfs: build/mergerfs mergerfs: build/mergerfs
tests: build/tests
changelog: changelog:
ifeq ($(GIT_REPO),1) ifeq ($(GIT_REPO),1)
$(GIT2DEBCL) --name mergerfs > ChangeLog $(GIT2DEBCL) --name mergerfs > ChangeLog
@ -127,12 +145,16 @@ version:
tools/update-version tools/update-version
build/stamp: build/stamp:
$(MKDIR) -p build
$(MKDIR) -p build/.src build/.tests
$(TOUCH) $@ $(TOUCH) $@
build/%.o: src/%.cpp
build/.src/%.o: src/%.cpp
$(CXX) $(CXXFLAGS) $(FUSE_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) -c $< -o $@ $(CXX) $(CXXFLAGS) $(FUSE_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) -c $< -o $@
build/.tests/%.o: tests/%.cpp
$(CXX) $(CXXFLAGS) $(TESTS_FLAGS) $(FUSE_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) -c $< -o $@
.PHONY: clean .PHONY: clean
clean: rpm-clean clean: rpm-clean
$(RM) -rf build $(RM) -rf build

366
src/branch.cpp

@ -18,21 +18,8 @@
#include "branch.hpp" #include "branch.hpp"
#include "ef.hpp" #include "ef.hpp"
#include "from_string.hpp"
#include "fs_glob.hpp"
#include "fs_realpathize.hpp"
#include "nonstd/optional.hpp"
#include "errno.hpp"
#include "num.hpp" #include "num.hpp"
#include "str.hpp"
#include <string>
#include <errno.h>
#include <fnmatch.h>
using std::string;
using std::vector;
using nonstd::optional;
Branch::Branch(const uint64_t &default_minfreespace_) Branch::Branch(const uint64_t &default_minfreespace_)
@ -108,354 +95,3 @@ Branch::ro_or_nc(void) const
return ((mode == Branch::Mode::RO) || return ((mode == Branch::Mode::RO) ||
(mode == Branch::Mode::NC)); (mode == Branch::Mode::NC));
} }
namespace l
{
static
void
split(const std::string &s_,
std::string *instr_,
std::string *values_)
{
uint64_t offset;
offset = s_.find_first_of('/');
*instr_ = s_.substr(0,offset);
if(offset != std::string::npos)
*values_ = s_.substr(offset);
}
}
Branches::Branches(const uint64_t &default_minfreespace_)
: default_minfreespace(default_minfreespace_)
{
pthread_rwlock_init(&lock,NULL);
}
namespace l
{
static
int
parse_mode(const string &str_,
Branch::Mode *mode_)
{
if(str_ == "RW")
*mode_ = Branch::Mode::RW;
ef(str_ == "RO")
*mode_ = Branch::Mode::RO;
ef(str_ == "NC")
*mode_ = Branch::Mode::NC;
else
return -EINVAL;
return 0;
}
static
int
parse_minfreespace(const string &str_,
optional<uint64_t> *minfreespace_)
{
int rv;
uint64_t uint64;
rv = str::from(str_,&uint64);
if(rv < 0)
return rv;
*minfreespace_ = uint64;
return 0;
}
static
int
parse_branch(const string &str_,
string *glob_,
Branch::Mode *mode_,
optional<uint64_t> *minfreespace_)
{
int rv;
string options;
vector<string> v;
str::rsplit1(str_,'=',&v);
switch(v.size())
{
case 1:
*glob_ = v[0];
*mode_ = Branch::Mode::RW;
break;
case 2:
*glob_ = v[0];
options = v[1];
v.clear();
str::split(options,',',&v);
switch(v.size())
{
case 2:
rv = l::parse_minfreespace(v[1],minfreespace_);
if(rv < 0)
return rv;
case 1:
rv = l::parse_mode(v[0],mode_);
if(rv < 0)
return rv;
break;
case 0:
return -EINVAL;
}
break;
default:
return -EINVAL;
}
return 0;
}
static
int
parse(const string &str_,
const uint64_t &default_minfreespace_,
BranchVec *branches_)
{
int rv;
string glob;
vector<string> globbed;
optional<uint64_t> minfreespace;
Branch branch(default_minfreespace_);
rv = l::parse_branch(str_,&glob,&branch.mode,&minfreespace);
if(rv < 0)
return rv;
if(minfreespace.has_value())
branch.set_minfreespace(minfreespace.value());
fs::glob(glob,&globbed);
fs::realpathize(&globbed);
for(size_t i = 0; i < globbed.size(); i++)
{
branch.path = globbed[i];
branches_->push_back(branch);
}
return 0;
}
static
int
set(const std::string &str_,
Branches *branches_)
{
int rv;
vector<string> paths;
BranchVec tmp_branchvec;
str::split(str_,':',&paths);
for(size_t i = 0; i < paths.size(); i++)
{
rv = l::parse(paths[i],branches_->default_minfreespace,&tmp_branchvec);
if(rv < 0)
return rv;
}
branches_->vec.clear();
branches_->vec.insert(branches_->vec.end(),
tmp_branchvec.begin(),
tmp_branchvec.end());
return 0;
}
static
int
add_begin(const std::string &str_,
Branches *branches_)
{
int rv;
vector<string> paths;
BranchVec tmp_branchvec;
str::split(str_,':',&paths);
for(size_t i = 0; i < paths.size(); i++)
{
rv = l::parse(paths[i],branches_->default_minfreespace,&tmp_branchvec);
if(rv < 0)
return rv;
}
branches_->vec.insert(branches_->vec.begin(),
tmp_branchvec.begin(),
tmp_branchvec.end());
return 0;
}
static
int
add_end(const std::string &str_,
Branches *branches_)
{
int rv;
vector<string> paths;
BranchVec tmp_branchvec;
str::split(str_,':',&paths);
for(size_t i = 0; i < paths.size(); i++)
{
rv = l::parse(paths[i],branches_->default_minfreespace,&tmp_branchvec);
if(rv < 0)
return rv;
}
branches_->vec.insert(branches_->vec.end(),
tmp_branchvec.begin(),
tmp_branchvec.end());
return 0;
}
static
int
erase_begin(BranchVec *branches_)
{
branches_->erase(branches_->begin());
return 0;
}
static
int
erase_end(BranchVec *branches_)
{
branches_->pop_back();
return 0;
}
static
int
erase_fnmatch(const std::string &str_,
Branches *branches_)
{
vector<string> patterns;
str::split(str_,':',&patterns);
for(BranchVec::iterator i = branches_->vec.begin();
i != branches_->vec.end();)
{
int match = FNM_NOMATCH;
for(vector<string>::const_iterator pi = patterns.begin();
pi != patterns.end() && match != 0;
++pi)
{
match = ::fnmatch(pi->c_str(),i->path.c_str(),0);
}
i = ((match == 0) ? branches_->vec.erase(i) : (i+1));
}
return 0;
}
}
int
Branches::from_string(const std::string &s_)
{
rwlock::WriteGuard guard(lock);
std::string instr;
std::string values;
l::split(s_,&instr,&values);
if(instr == "+")
return l::add_end(values,this);
if(instr == "+<")
return l::add_begin(values,this);
if(instr == "+>")
return l::add_end(values,this);
if(instr == "-")
return l::erase_fnmatch(values,this);
if(instr == "-<")
return l::erase_begin(&vec);
if(instr == "->")
return l::erase_end(&vec);
if(instr == "=")
return l::set(values,this);
if(instr.empty())
return l::set(values,this);
return -EINVAL;
}
string
Branches::to_string(void) const
{
rwlock::ReadGuard guard(lock);
string tmp;
for(size_t i = 0; i < vec.size(); i++)
{
const Branch &branch = vec[i];
tmp += branch.to_string();
tmp += ':';
}
if(*tmp.rbegin() == ':')
tmp.erase(tmp.size() - 1);
return tmp;
}
void
Branches::to_paths(vector<string> &vec_) const
{
rwlock::ReadGuard guard(lock);
for(size_t i = 0; i < vec.size(); i++)
{
const Branch &branch = vec[i];
vec_.push_back(branch.path);
}
}
SrcMounts::SrcMounts(Branches &b_)
: _branches(b_)
{
}
int
SrcMounts::from_string(const std::string &s_)
{
return _branches.from_string(s_);
}
std::string
SrcMounts::to_string(void) const
{
rwlock::ReadGuard guard(_branches.lock);
std::string rv;
for(uint64_t i = 0; i < _branches.vec.size(); i++)
{
rv += _branches.vec[i].path;
rv += ':';
}
if(*rv.rbegin() == ':')
rv.erase(rv.size() - 1);
return rv;
}

67
src/branch.hpp

@ -18,81 +18,50 @@
#pragma once #pragma once
#include "rwlock.hpp"
#include "tofrom_string.hpp"
#include "nonstd/optional.hpp" #include "nonstd/optional.hpp"
#include "strvec.hpp"
#include "tofrom_string.hpp"
#include <cstdint>
#include <string> #include <string>
#include <vector> #include <vector>
#include <stdint.h>
#include <pthread.h>
class Branch : public ToFromString
class Branch final : public ToFromString
{ {
public: public:
Branch(const uint64_t &default_minfreespace);
typedef std::vector<Branch> Vector;
public: public:
int from_string(const std::string &str);
std::string to_string(void) const;
Branch(const uint64_t &default_minfreespace_);
public: public:
enum class Mode enum class Mode
{ {
INVALID,
RO,
RW,
NC
INVALID,
RO,
RW,
NC
}; };
public:
Mode mode;
std::string path;
uint64_t minfreespace() const;
public:
void set_minfreespace(const uint64_t minfreespace);
public: public:
bool ro(void) const; bool ro(void) const;
bool nc(void) const; bool nc(void) const;
bool ro_or_nc(void) const; bool ro_or_nc(void) const;
private:
nonstd::optional<uint64_t> _minfreespace;
const uint64_t *_default_minfreespace;
};
typedef std::vector<Branch> BranchVec;
class Branches : public ToFromString
{
public:
Branches(const uint64_t &default_minfreespace_);
public:
int from_string(const std::string &str);
std::string to_string(void) const;
public:
void to_paths(std::vector<std::string> &vec) const;
public: public:
mutable pthread_rwlock_t lock;
BranchVec vec;
const uint64_t &default_minfreespace;
};
int from_string(const std::string &str) final;
std::string to_string(void) const final;
class SrcMounts : public ToFromString
{
public: public:
SrcMounts(Branches &b_);
uint64_t minfreespace() const;
void set_minfreespace(const uint64_t);
public: public:
int from_string(const std::string &str);
std::string to_string(void) const;
Mode mode;
std::string path;
private: private:
Branches &_branches;
nonstd::optional<uint64_t> _minfreespace;
const uint64_t *_default_minfreespace;
}; };

429
src/branches.cpp

@ -0,0 +1,429 @@
/*
ISC License
Copyright (c) 2021, 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 "branches.hpp"
#include "ef.hpp"
#include "errno.hpp"
#include "from_string.hpp"
#include "fs_glob.hpp"
#include "fs_realpathize.hpp"
#include "nonstd/optional.hpp"
#include "num.hpp"
#include "str.hpp"
#include <string>
#include <fnmatch.h>
using std::string;
using std::vector;
using nonstd::optional;
Branches::Impl::Impl(const uint64_t &default_minfreespace_)
: _default_minfreespace(default_minfreespace_)
{
}
Branches::Impl&
Branches::Impl::operator=(Branches::Impl &rval_)
{
auto this_base = dynamic_cast<Branch::Vector*>(this);
auto rval_base = dynamic_cast<Branch::Vector*>(&rval_);
*this_base = *rval_base;
return *this;
}
Branches::Impl&
Branches::Impl::operator=(Branches::Impl &&rval_)
{
auto this_base = dynamic_cast<Branch::Vector*>(this);
auto rval_base = dynamic_cast<Branch::Vector*>(&rval_);
*this_base = std::move(*rval_base);
return *this;
}
const
uint64_t&
Branches::Impl::minfreespace(void) const
{
return _default_minfreespace;
}
namespace l
{
static
void
split(const std::string &s_,
std::string *instr_,
std::string *values_)
{
uint64_t offset;
offset = s_.find_first_of('/');
*instr_ = s_.substr(0,offset);
if(offset != std::string::npos)
*values_ = s_.substr(offset);
}
static
int
parse_mode(const string &str_,
Branch::Mode *mode_)
{
if(str_ == "RW")
*mode_ = Branch::Mode::RW;
ef(str_ == "RO")
*mode_ = Branch::Mode::RO;
ef(str_ == "NC")
*mode_ = Branch::Mode::NC;
else
return -EINVAL;
return 0;
}
static
int
parse_minfreespace(const string &str_,
optional<uint64_t> *minfreespace_)
{
int rv;
uint64_t uint64;
rv = str::from(str_,&uint64);
if(rv < 0)
return rv;
*minfreespace_ = uint64;
return 0;
}
static
int
parse_branch(const string &str_,
string *glob_,
Branch::Mode *mode_,
optional<uint64_t> *minfreespace_)
{
int rv;
string options;
vector<string> v;
str::rsplit1(str_,'=',&v);
switch(v.size())
{
case 1:
*glob_ = v[0];
*mode_ = Branch::Mode::RW;
break;
case 2:
*glob_ = v[0];
options = v[1];
v.clear();
str::split(options,',',&v);
switch(v.size())
{
case 2:
rv = l::parse_minfreespace(v[1],minfreespace_);
if(rv < 0)
return rv;
case 1:
rv = l::parse_mode(v[0],mode_);
if(rv < 0)
return rv;
break;
case 0:
return -EINVAL;
}
break;
default:
return -EINVAL;
}
return 0;
}
static
int
parse(const string &str_,
Branches::Impl *branches_)
{
int rv;
string glob;
StrVec paths;
optional<uint64_t> minfreespace;
Branch branch(branches_->minfreespace());
rv = l::parse_branch(str_,&glob,&branch.mode,&minfreespace);
if(rv < 0)
return rv;
if(minfreespace.has_value())
branch.set_minfreespace(minfreespace.value());
fs::glob(glob,&paths);
fs::realpathize(&paths);
for(auto &path : paths)
{
branch.path = path;
branches_->push_back(branch);
}
return 0;
}
static
int
set(const std::string &str_,
Branches::Impl *branches_)
{
int rv;
StrVec paths;
Branches::Impl tmp_branches(branches_->minfreespace());
str::split(str_,':',&paths);
for(auto &path : paths)
{
rv = l::parse(path,&tmp_branches);
if(rv < 0)
return rv;
}
*branches_ = std::move(tmp_branches);
return 0;
}
static
int
add_begin(const std::string &str_,
Branches::Impl *branches_)
{
int rv;
vector<string> paths;
Branches::Impl tmp_branches(branches_->minfreespace());
str::split(str_,':',&paths);
for(auto &path : paths)
{
rv = l::parse(path,&tmp_branches);
if(rv < 0)
return rv;
}
branches_->insert(branches_->begin(),
tmp_branches.begin(),
tmp_branches.end());
return 0;
}
static
int
add_end(const std::string &str_,
Branches::Impl *branches_)
{
int rv;
StrVec paths;
Branches::Impl tmp_branches(branches_->minfreespace());
str::split(str_,':',&paths);
for(auto &path : paths)
{
rv = l::parse(path,&tmp_branches);
if(rv < 0)
return rv;
}
branches_->insert(branches_->end(),
tmp_branches.begin(),
tmp_branches.end());
return 0;
}
static
int
erase_begin(Branches::Impl *branches_)
{
branches_->erase(branches_->begin());
return 0;
}
static
int
erase_end(Branches::Impl *branches_)
{
branches_->pop_back();
return 0;
}
static
int
erase_fnmatch(const std::string &str_,
Branches::Impl *branches_)
{
StrVec patterns;
str::split(str_,':',&patterns);
for(auto i = branches_->begin(); i != branches_->end();)
{
int match = FNM_NOMATCH;
for(auto pi = patterns.cbegin(); pi != patterns.cend() && match != 0; ++pi)
{
match = ::fnmatch(pi->c_str(),i->path.c_str(),0);
}
i = ((match == 0) ? branches_->erase(i) : (i+1));
}
return 0;
}
}
int
Branches::Impl::from_string(const std::string &s_)
{
std::string instr;
std::string values;
l::split(s_,&instr,&values);
if(instr == "+")
return l::add_end(values,this);
if(instr == "+<")
return l::add_begin(values,this);
if(instr == "+>")
return l::add_end(values,this);
if(instr == "-")
return l::erase_fnmatch(values,this);
if(instr == "-<")
return l::erase_begin(this);
if(instr == "->")
return l::erase_end(this);
if(instr == "=")
return l::set(values,this);
if(instr.empty())
return l::set(values,this);
return -EINVAL;
}
std::string
Branches::Impl::to_string(void) const
{
string tmp;
if(empty())
return tmp;
for(auto &branch : *this)
{
tmp += branch.to_string();
tmp += ':';
}
tmp.pop_back();
return tmp;
}
void
Branches::Impl::to_paths(StrVec &paths_) const
{
for(auto &branch : *this)
{
paths_.push_back(branch.path);
}
}
int
Branches::from_string(const std::string &str_)
{
int rv;
Branches::Ptr impl;
Branches::Ptr new_impl;
{
std::lock_guard<std::mutex> lock_guard(_mutex);
impl = _impl;
}
new_impl = std::make_shared<Branches::Impl>(impl->minfreespace());
*new_impl = *impl;
rv = new_impl->from_string(str_);
if(rv < 0)
return rv;
{
std::lock_guard<std::mutex> lock_guard(_mutex);
_impl = new_impl;
}
return 0;
}
string
Branches::to_string(void) const
{
std::lock_guard<std::mutex> lock_guard(_mutex);
return _impl->to_string();
}
SrcMounts::SrcMounts(Branches &b_)
: _branches(b_)
{
}
int
SrcMounts::from_string(const std::string &s_)
{
return _branches.from_string(s_);
}
std::string
SrcMounts::to_string(void) const
{
std::string rv;
Branches::CPtr branches = _branches;
if(branches->empty())
return rv;
for(const auto &branch : *branches)
{
rv += branch.path;
rv += ':';
}
rv.pop_back();
return rv;
}

94
src/branches.hpp

@ -0,0 +1,94 @@
/*
ISC License
Copyright (c) 2021, 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 "branch.hpp"
#include "nonstd/optional.hpp"
#include "strvec.hpp"
#include "tofrom_string.hpp"
#include <cstdint>
#include <memory>
#include <mutex>
#include <string>
#include <vector>
class Branches final : public ToFromString
{
public:
class Impl final : public ToFromString, public Branch::Vector
{
public:
typedef std::shared_ptr<Impl> Ptr;
typedef std::shared_ptr<const Impl> CPtr;
public:
Impl(const uint64_t &default_minfreespace_);
public:
int from_string(const std::string &str) final;
std::string to_string(void) const final;
public:
const uint64_t& minfreespace(void) const;
void to_paths(StrVec &strvec) const;
public:
Impl& operator=(Impl &impl_);
Impl& operator=(Impl &&impl_);
private:
const uint64_t &_default_minfreespace;
};
public:
typedef Branches::Impl::Ptr Ptr;
typedef Branches::Impl::CPtr CPtr;
public:
Branches(const uint64_t &default_minfreespace_)
: _impl(std::make_shared<Impl>(default_minfreespace_))
{}
public:
int from_string(const std::string &str) final;
std::string to_string(void) const final;
public:
operator CPtr() const { std::lock_guard<std::mutex> lg(_mutex); return _impl; }
CPtr operator->() const { std::lock_guard<std::mutex> lg(_mutex); return _impl; }
private:
mutable std::mutex _mutex;
Ptr _impl;
};
class SrcMounts : public ToFromString
{
public:
SrcMounts(Branches &b_);
public:
int from_string(const std::string &str) final;
std::string to_string(void) const final;
private:
Branches &_branches;
};

49
src/category.cpp

@ -0,0 +1,49 @@
/*
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 "category.hpp"
#include "errno.hpp"
#include "str.hpp"
#include <string>
int
Category::Base::from_string(const std::string &s_)
{
int rv;
for(auto func : funcs)
{
rv = func->from_string(s_);
if(rv < 0)
return rv;
}
return 0;
}
std::string
Category::Base::to_string(void) const
{
std::set<std::string> rv;
for(auto func : funcs)
rv.insert(func->to_string());
return str::join(rv,',');
}

93
src/category.hpp

@ -1,5 +1,5 @@
/* /*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Copyright (c) 2020, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above purpose with or without fee is hereby granted, provided that the above
@ -16,9 +16,92 @@
#pragma once #pragma once
enum class Category
#include "tofrom_string.hpp"
#include "funcs.hpp"
#include "func.hpp"
#include <string>
namespace Category
{
class Base : public ToFromString
{
public:
int from_string(const std::string &s) final;
std::string to_string() const final;
protected:
std::vector<ToFromString*> funcs;
};
class Action final : public Base
{
private:
Action();
public:
Action(Funcs &funcs_)
{
funcs.push_back(&funcs_.chmod);
funcs.push_back(&funcs_.chown);
funcs.push_back(&funcs_.link);
funcs.push_back(&funcs_.removexattr);
funcs.push_back(&funcs_.rename);
funcs.push_back(&funcs_.rmdir);
funcs.push_back(&funcs_.setxattr);
funcs.push_back(&funcs_.truncate);
funcs.push_back(&funcs_.unlink);
funcs.push_back(&funcs_.utimens);
}
};
class Create final : public Base
{ {
ACTION,
CREATE,
SEARCH
private:
Create();
public:
Create(Funcs &funcs_)
{
funcs.push_back(&funcs_.create);
funcs.push_back(&funcs_.mkdir);
funcs.push_back(&funcs_.mknod);
funcs.push_back(&funcs_.symlink);
}
}; };
class Search final : public Base
{
private:
Search();
public:
Search(Funcs &funcs_)
{
funcs.push_back(&funcs_.access);
funcs.push_back(&funcs_.getattr);
funcs.push_back(&funcs_.getxattr);
funcs.push_back(&funcs_.listxattr);
funcs.push_back(&funcs_.open);
funcs.push_back(&funcs_.readlink);
}
};
}
class Categories final
{
private:
Categories();
public:
Categories(Funcs &funcs_)
: action(funcs_),
create(funcs_),
search(funcs_)
{}
public:
Category::Action action;
Category::Create create;
Category::Search search;
};

228
src/config.cpp

@ -20,14 +20,18 @@
#include "from_string.hpp" #include "from_string.hpp"
#include "num.hpp" #include "num.hpp"
#include "rwlock.hpp" #include "rwlock.hpp"
#include "str.hpp"
#include "to_string.hpp" #include "to_string.hpp"
#include "version.hpp" #include "version.hpp"
#include <algorithm> #include <algorithm>
#include <string>
#include <cstdint>
#include <fstream>
#include <iostream> #include <iostream>
#include <string>
#include <stdint.h>
#include <pthread.h>
#include <string.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
@ -37,6 +41,11 @@ using std::string;
#define IFERT(S) if(S == s_) return true #define IFERT(S) if(S == s_) return true
const std::string CONTROLFILE = "/.mergerfs";
Config Config::_singleton;
namespace l namespace l
{ {
static static
@ -60,49 +69,44 @@ namespace l
} }
Config::Config() Config::Config()
:
open_cache(),
controlfile("/.mergerfs"),
async_read(true),
auto_cache(false),
branches(minfreespace),
cache_attr(1),
cache_entry(1),
cache_files(CacheFiles::ENUM::LIBFUSE),
cache_negative_entry(0),
cache_readdir(false),
cache_statfs(0),
cache_symlinks(false),
category(func),
direct_io(false),
dropcacheonclose(false),
fsname(),
func(),
fuse_msg_size(FUSE_MAX_MAX_PAGES),
ignorepponrename(false),
inodecalc("hybrid-hash"),
link_cow(false),
minfreespace(MINFREESPACE_DEFAULT),
mount(),
moveonenospc(false),
nfsopenhack(NFSOpenHack::ENUM::OFF),
nullrw(false),
pid(::getpid()),
posix_acl(false),
readdir(ReadDir::ENUM::POSIX),
readdirplus(false),
security_capability(true),
srcmounts(branches),
statfs(StatFS::ENUM::BASE),
statfs_ignore(StatFSIgnore::ENUM::NONE),
symlinkify(false),
symlinkify_timeout(3600),
threads(0),
version(MERGERFS_VERSION),
writeback_cache(false),
xattr(XAttr::ENUM::PASSTHROUGH)
: async_read(true),
auto_cache(false),
branches(minfreespace),
cache_attr(1),
cache_entry(1),
cache_files(CacheFiles::ENUM::LIBFUSE),
cache_negative_entry(0),
cache_readdir(false),
cache_statfs(0),
cache_symlinks(false),
category(func),
direct_io(false),
dropcacheonclose(false),
fsname(),
func(),
fuse_msg_size(FUSE_MAX_MAX_PAGES),
ignorepponrename(false),
inodecalc("hybrid-hash"),
link_cow(false),
minfreespace(MINFREESPACE_DEFAULT),
mount(),
moveonenospc(false),
nfsopenhack(NFSOpenHack::ENUM::OFF),
nullrw(false),
pid(::getpid()),
posix_acl(false),
readdir(ReadDir::ENUM::POSIX),
readdirplus(false),
security_capability(true),
srcmounts(branches),
statfs(StatFS::ENUM::BASE),
statfs_ignore(StatFSIgnore::ENUM::NONE),
symlinkify(false),
symlinkify_timeout(3600),
threads(0),
version(MERGERFS_VERSION),
writeback_cache(false),
xattr(XAttr::ENUM::PASSTHROUGH)
{ {
_map["async_read"] = &async_read; _map["async_read"] = &async_read;
_map["auto_cache"] = &auto_cache; _map["auto_cache"] = &auto_cache;
@ -166,17 +170,22 @@ Config::Config()
_map["xattr"] = &xattr; _map["xattr"] = &xattr;
} }
const
Config& Config&
Config::ro(void)
Config::operator=(const Config &cfg_)
{ {
return *((Config*)fuse_get_context()->private_data);
}
int rv;
std::string val;
Config&
Config::rw(void)
{
return *((Config*)fuse_get_context()->private_data);
for(auto &kv : _map)
{
rv = cfg_.get(kv.first,&val);
if(rv)
continue;
kv.second->from_string(val);
}
return *this;
} }
bool bool
@ -254,11 +263,80 @@ Config::set(const std::string &key_,
const std::string &value_) const std::string &value_)
{ {
if(l::readonly(key_)) if(l::readonly(key_))
return -EINVAL;
return -EROFS;
return set_raw(key_,value_); return set_raw(key_,value_);
} }
int
Config::set(const std::string &kv_)
{
std::string key;
std::string val;
str::splitkv(kv_,'=',&key,&val);
key = str::trim(key);
val = str::trim(val);
return set(key,val);
}
int
Config::from_stream(std::istream &istrm_,
ErrVec *errs_)
{
int rv;
std::string line;
std::string key;
std::string val;
Config newcfg;
newcfg = *this;
while(std::getline(istrm_,line,'\n'))
{
line = str::trim(line);
if(!line.empty() && (line[0] == '#'))
continue;
str::splitkv(line,'=',&key,&val);
key = str::trim(key);
val = str::trim(val);
rv = newcfg.set(key,val);
if(rv < 0)
errs_->push_back({rv,key});
}
if(!errs_->empty())
return -EINVAL;
*this = newcfg;
return 0;
}
int
Config::from_file(const std::string &filepath_,
ErrVec *errs_)
{
int rv;
std::ifstream ifstrm;
ifstrm.open(filepath_);
if(!ifstrm.good())
{
errs_->push_back({-errno,filepath_});
return -errno;
}
rv = from_stream(ifstrm,errs_);
ifstrm.close();
return rv;
}
std::ostream& std::ostream&
operator<<(std::ostream &os_, operator<<(std::ostream &os_,
const Config &c_) const Config &c_)
@ -268,7 +346,47 @@ operator<<(std::ostream &os_,
for(i = c_._map.begin(), ei = c_._map.end(); i != ei; ++i) for(i = c_._map.begin(), ei = c_._map.end(); i != ei; ++i)
{ {
os_ << i->first << '=' << i->second << '\n';
os_ << i->first << '=' << i->second->to_string() << std::endl;
}
return os_;
}
static
std::string
err2str(const int err_)
{
switch(err_)
{
case 0:
return std::string();
case -EINVAL:
return "invalid value";
case -ENOATTR:
return "unknown option";
case -EROFS:
return "read-only option";
default:
return strerror(-err_);
}
return std::string();
}
std::ostream&
operator<<(std::ostream &os_,
const Config::ErrVec &ev_)
{
std::string errstr;
for(auto &err : ev_)
{
os_ << "* ERROR: ";
errstr = err2str(err.err);
if(!errstr.empty())
os_ << errstr << " - ";
os_ << err.str << std::endl;
} }
return os_; return os_;

98
src/config.hpp

@ -16,7 +16,8 @@
#pragma once #pragma once
#include "branch.hpp"
#include "branches.hpp"
#include "category.hpp"
#include "config_cachefiles.hpp" #include "config_cachefiles.hpp"
#include "config_inodecalc.hpp" #include "config_inodecalc.hpp"
#include "config_moveonenospc.hpp" #include "config_moveonenospc.hpp"
@ -27,18 +28,20 @@
#include "config_xattr.hpp" #include "config_xattr.hpp"
#include "enum.hpp" #include "enum.hpp"
#include "errno.hpp" #include "errno.hpp"
#include "func_category.hpp"
#include "funcs.hpp" #include "funcs.hpp"
#include "policy.hpp" #include "policy.hpp"
#include "policy_cache.hpp"
#include "rwlock.hpp"
#include "tofrom_wrapper.hpp" #include "tofrom_wrapper.hpp"
#include <fuse.h>
#include "fuse.h"
#include <cstdint>
#include <map>
#include <memory>
#include <mutex>
#include <string> #include <string>
#include <vector> #include <vector>
#include <stdint.h>
#include <sys/stat.h> #include <sys/stat.h>
typedef ToFromWrapper<bool> ConfigBOOL; typedef ToFromWrapper<bool> ConfigBOOL;
@ -47,16 +50,50 @@ typedef ToFromWrapper<int> ConfigINT;
typedef ToFromWrapper<std::string> ConfigSTR; typedef ToFromWrapper<std::string> ConfigSTR;
typedef std::map<std::string,ToFromString*> Str2TFStrMap; typedef std::map<std::string,ToFromString*> Str2TFStrMap;
extern const std::string CONTROLFILE;
class Config class Config
{ {
public: public:
Config();
struct Err
{
int err;
std::string str;
};
typedef std::vector<Err> ErrVec;
public:
class Read
{
public:
Read();
public:
inline const Config* operator->() const;
private:
const Config &_cfg;
};
public: public:
mutable PolicyCache open_cache;
class Write
{
public:
Write();
public:
Config* operator->();
private:
Config &_cfg;
};
public: public:
const std::string controlfile;
Config();
public:
Config& operator=(const Config&);
public: public:
ConfigBOOL async_read; ConfigBOOL async_read;
@ -69,7 +106,7 @@ public:
ConfigBOOL cache_readdir; ConfigBOOL cache_readdir;
ConfigUINT64 cache_statfs; ConfigUINT64 cache_statfs;
ConfigBOOL cache_symlinks; ConfigBOOL cache_symlinks;
FuncCategories category;
Categories category;
ConfigBOOL direct_io; ConfigBOOL direct_io;
ConfigBOOL dropcacheonclose; ConfigBOOL dropcacheonclose;
ConfigSTR fsname; ConfigSTR fsname;
@ -112,11 +149,50 @@ public:
int get(const std::string &key, std::string *val) const; int get(const std::string &key, std::string *val) const;
int set_raw(const std::string &key, const std::string &val); int set_raw(const std::string &key, const std::string &val);
int set(const std::string &key, const std::string &val); int set(const std::string &key, const std::string &val);
int set(const std::string &kv);
public: public:
static const Config &ro(void);
static Config &rw(void);
int from_stream(std::istream &istrm, ErrVec *errs);
int from_file(const std::string &filepath, ErrVec *errs);
private: private:
Str2TFStrMap _map; Str2TFStrMap _map;
private:
static Config _singleton;
public:
friend class Read;
friend class Write;
}; };
std::ostream& operator<<(std::ostream &s,const Config::ErrVec &ev);
inline
Config::Read::Read()
: _cfg(Config::_singleton)
{
}
inline
const
Config*
Config::Read::operator->() const
{
return &_cfg;
}
inline
Config::Write::Write()
: _cfg(Config::_singleton)
{
}
inline
Config*
Config::Write::operator->()
{
return &_cfg;
}

1
src/config_cachefiles.hpp

@ -20,6 +20,7 @@
#include "enum.hpp" #include "enum.hpp"
enum class CacheFilesEnum enum class CacheFilesEnum
{ {
LIBFUSE, LIBFUSE,

1
src/config_inodecalc.cpp

@ -19,6 +19,7 @@
#include "config_inodecalc.hpp" #include "config_inodecalc.hpp"
#include "fs_inode.hpp" #include "fs_inode.hpp"
InodeCalc::InodeCalc(const std::string &s_) InodeCalc::InodeCalc(const std::string &s_)
{ {
fs::inode::set_algo(s_); fs::inode::set_algo(s_);

5
src/config_inodecalc.hpp

@ -20,12 +20,13 @@
#include "tofrom_string.hpp" #include "tofrom_string.hpp"
class InodeCalc : public ToFromString class InodeCalc : public ToFromString
{ {
public: public:
InodeCalc(const std::string &); InodeCalc(const std::string &);
public: public:
std::string to_string(void) const;
int from_string(const std::string &);
std::string to_string(void) const final;
int from_string(const std::string &) final;
}; };

9
src/config_moveonenospc.cpp

@ -21,12 +21,13 @@
#include "errno.hpp" #include "errno.hpp"
#include "from_string.hpp" #include "from_string.hpp"
int int
MoveOnENOSPC::from_string(const std::string &s_) MoveOnENOSPC::from_string(const std::string &s_)
{ {
int rv; int rv;
std::string s; std::string s;
const Policy *tmp;
Policy::CreateImpl *tmp;
rv = str::from(s_,&enabled); rv = str::from(s_,&enabled);
if((rv == 0) && (enabled == true)) if((rv == 0) && (enabled == true))
@ -36,8 +37,8 @@ MoveOnENOSPC::from_string(const std::string &s_)
else else
return 0; return 0;
tmp = &Policy::find(s);
if(tmp == Policy::invalid)
tmp = Policies::Create::find(s);
if(tmp == NULL)
return -EINVAL; return -EINVAL;
policy = tmp; policy = tmp;
@ -50,6 +51,6 @@ std::string
MoveOnENOSPC::to_string(void) const MoveOnENOSPC::to_string(void) const
{ {
if(enabled) if(enabled)
return policy->to_string();
return policy.name();
return "false"; return "false";
} }

14
src/config_moveonenospc.hpp

@ -19,26 +19,26 @@
#pragma once #pragma once
#include "policy.hpp" #include "policy.hpp"
#include "policies.hpp"
#include "tofrom_string.hpp" #include "tofrom_string.hpp"
#include <string> #include <string>
class MoveOnENOSPC : public ToFromString class MoveOnENOSPC : public ToFromString
{ {
public: public:
MoveOnENOSPC(const bool enabled_) MoveOnENOSPC(const bool enabled_)
: enabled(enabled_)
: enabled(enabled_),
policy(&Policies::Create::mfs)
{ {
policy = (enabled ?
&Policy::mfs :
&Policy::invalid);
} }
public: public:
int from_string(const std::string &s);
std::string to_string() const;
int from_string(const std::string &s) final;
std::string to_string() const final;
public: public:
bool enabled; bool enabled;
const Policy *policy;
Policy::Create policy;
}; };

1
src/config_nfsopenhack.cpp

@ -20,6 +20,7 @@
#include "ef.hpp" #include "ef.hpp"
#include "errno.hpp" #include "errno.hpp"
template<> template<>
int int
NFSOpenHack::from_string(const std::string &s_) NFSOpenHack::from_string(const std::string &s_)

1
src/config_nfsopenhack.hpp

@ -20,6 +20,7 @@
#include "enum.hpp" #include "enum.hpp"
enum class NFSOpenHackEnum enum class NFSOpenHackEnum
{ {
OFF, OFF,

1
src/config_readdir.cpp

@ -20,6 +20,7 @@
#include "ef.hpp" #include "ef.hpp"
#include "errno.hpp" #include "errno.hpp"
template<> template<>
int int
ReadDir::from_string(const std::string &s_) ReadDir::from_string(const std::string &s_)

1
src/config_readdir.hpp

@ -20,6 +20,7 @@
#include "enum.hpp" #include "enum.hpp"
enum class ReadDirEnum enum class ReadDirEnum
{ {
POSIX, POSIX,

1
src/config_statfs.cpp

@ -20,6 +20,7 @@
#include "ef.hpp" #include "ef.hpp"
#include "errno.hpp" #include "errno.hpp"
template<> template<>
std::string std::string
StatFS::to_string() const StatFS::to_string() const

1
src/config_statfs.hpp

@ -20,6 +20,7 @@
#include "enum.hpp" #include "enum.hpp"
enum class StatFSEnum enum class StatFSEnum
{ {
BASE, BASE,

1
src/config_statfsignore.cpp

@ -20,6 +20,7 @@
#include "ef.hpp" #include "ef.hpp"
#include "errno.hpp" #include "errno.hpp"
template<> template<>
std::string std::string
StatFSIgnore::to_string() const StatFSIgnore::to_string() const

1
src/config_xattr.cpp

@ -20,6 +20,7 @@
#include "ef.hpp" #include "ef.hpp"
#include "errno.hpp" #include "errno.hpp"
template<> template<>
std::string std::string
XAttr::to_string() const XAttr::to_string() const

1
src/config_xattr.hpp

@ -21,6 +21,7 @@
#include "enum.hpp" #include "enum.hpp"
#include "errno.hpp" #include "errno.hpp"
enum class XAttrEnum enum class XAttrEnum
{ {
PASSTHROUGH = 0, PASSTHROUGH = 0,

1
src/dirinfo.hpp

@ -20,6 +20,7 @@
#include <string> #include <string>
class DirInfo : public FH class DirInfo : public FH
{ {
public: public:

1
src/endian.hpp

@ -18,6 +18,7 @@
#pragma once #pragma once
namespace endian namespace endian
{ {
static static

1
src/enum.hpp

@ -22,6 +22,7 @@
#include <string> #include <string>
template<typename E> template<typename E>
class Enum : public ToFromString class Enum : public ToFromString
{ {

1
src/fh.hpp

@ -18,6 +18,7 @@
#include <string> #include <string>
class FH class FH
{ {
public: public:

1
src/fileinfo.hpp

@ -20,6 +20,7 @@
#include <string> #include <string>
class FileInfo : public FH class FileInfo : public FH
{ {
public: public:

4
src/fixed_mem_pool.hpp

@ -18,8 +18,10 @@
#pragma once #pragma once
#include <cstdint>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
typedef struct fixed_mem_pool_t fixed_mem_pool_t; typedef struct fixed_mem_pool_t fixed_mem_pool_t;
struct fixed_mem_pool_t struct fixed_mem_pool_t

17
src/from_string.cpp

@ -17,13 +17,14 @@
*/ */
#include "ef.hpp" #include "ef.hpp"
#include "errno.hpp"
#include <cstdint>
#include <string> #include <string>
#include <errno.h>
#include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
namespace str namespace str
{ {
int int
@ -50,7 +51,17 @@ namespace str
from(const std::string &value_, from(const std::string &value_,
int *int_) int *int_)
{ {
*int_ = ::strtol(value_.c_str(),NULL,10);
int tmp;
char *endptr;
errno = 0;
tmp = ::strtol(value_.c_str(),&endptr,10);
if(errno != 0)
return -EINVAL;
if(endptr == value_.c_str())
return -EINVAL;
*int_ = tmp;
return 0; return 0;
} }

2
src/from_string.hpp

@ -18,9 +18,9 @@
#pragma once #pragma once
#include <cstdint>
#include <string> #include <string>
#include <stdint.h>
namespace str namespace str
{ {

1
src/fs_acl.cpp

@ -23,6 +23,7 @@
const char POSIX_ACL_DEFAULT_XATTR[] = "system.posix_acl_default"; const char POSIX_ACL_DEFAULT_XATTR[] = "system.posix_acl_default";
namespace fs namespace fs
{ {
namespace acl namespace acl

1
src/fs_acl.hpp

@ -20,6 +20,7 @@
#include <string> #include <string>
namespace fs namespace fs
{ {
namespace acl namespace acl

1
src/fs_attr.hpp

@ -18,6 +18,7 @@
#include <string> #include <string>
namespace fs namespace fs
{ {
namespace attr namespace attr

1
src/fs_attr_linux.icpp

@ -26,6 +26,7 @@
using std::string; using std::string;
namespace fs namespace fs
{ {
namespace attr namespace attr

1
src/fs_attr_unsupported.icpp

@ -18,6 +18,7 @@
#include <string> #include <string>
namespace fs namespace fs
{ {
namespace attr namespace attr

1
src/fs_clonefile.cpp

@ -22,6 +22,7 @@
#include "fs_fchmod.hpp" #include "fs_fchmod.hpp"
#include "fs_futimens.hpp" #include "fs_futimens.hpp"
namespace l namespace l
{ {
static static

1
src/fs_clonefile.hpp

@ -16,6 +16,7 @@
#pragma once #pragma once
namespace fs namespace fs
{ {
int int

5
src/fs_clonepath.cpp

@ -14,8 +14,6 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <string>
#include "errno.h" #include "errno.h"
#include "fs_attr.hpp" #include "fs_attr.hpp"
#include "fs_clonepath.hpp" #include "fs_clonepath.hpp"
@ -27,8 +25,11 @@
#include "fs_xattr.hpp" #include "fs_xattr.hpp"
#include "ugid.hpp" #include "ugid.hpp"
#include <string>
using std::string; using std::string;
namespace l namespace l
{ {
static static

1
src/fs_clonepath.hpp

@ -18,6 +18,7 @@
#include <string> #include <string>
namespace fs namespace fs
{ {
int clonepath(const std::string &from, int clonepath(const std::string &from,

1
src/fs_close.hpp

@ -20,6 +20,7 @@
#include <unistd.h> #include <unistd.h>
namespace fs namespace fs
{ {
static static

1
src/fs_closedir.hpp

@ -21,6 +21,7 @@
#include <dirent.h> #include <dirent.h>
#include <sys/types.h> #include <sys/types.h>
namespace fs namespace fs
{ {
static static

4
src/fs_copy_file_range.hpp

@ -18,10 +18,12 @@
#pragma once #pragma once
#include <cstdint>
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
namespace fs namespace fs
{ {
int64_t int64_t

4
src/fs_copy_file_range_linux.icpp

@ -22,13 +22,15 @@
#include "errno.hpp" #include "errno.hpp"
#include <cstdint>
#include <fcntl.h> #include <fcntl.h>
#include <stdint.h>
#include <stdio.h> #include <stdio.h>
#include <sys/syscall.h> #include <sys/syscall.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
namespace l namespace l
{ {
static static

4
src/fs_copy_file_range_unsupported.icpp

@ -18,10 +18,12 @@
#include "errno.h" #include "errno.h"
#include <cstdint>
#include <stddef.h> #include <stddef.h>
#include <stdint.h>
#include <sys/types.h> #include <sys/types.h>
namespace fs namespace fs
{ {
ssize_t ssize_t

1
src/fs_copydata.cpp

@ -24,6 +24,7 @@
#include <stddef.h> #include <stddef.h>
namespace fs namespace fs
{ {
int int

1
src/fs_copydata.hpp

@ -20,6 +20,7 @@
#include <stddef.h> #include <stddef.h>
namespace fs namespace fs
{ {
int int

3
src/fs_copydata_copy_file_range.cpp

@ -18,7 +18,8 @@
#include "fs_copy_file_range.hpp" #include "fs_copy_file_range.hpp"
#include "fs_fstat.hpp" #include "fs_fstat.hpp"
#include <stdint.h>
#include <cstdint>
namespace l namespace l
{ {

3
src/fs_copydata_copy_file_range.hpp

@ -16,7 +16,8 @@
#pragma once #pragma once
#include <stdint.h>
#include <cstdint>
namespace fs namespace fs
{ {

1
src/fs_copydata_readwrite.cpp

@ -24,6 +24,7 @@
using std::vector; using std::vector;
namespace l namespace l
{ {
static static

1
src/fs_copydata_readwrite.hpp

@ -16,6 +16,7 @@
#pragma once #pragma once
namespace fs namespace fs
{ {
int int

1
src/fs_cow.cpp

@ -34,6 +34,7 @@
using std::string; using std::string;
namespace l namespace l
{ {
static static

1
src/fs_cow.hpp

@ -21,6 +21,7 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
namespace fs namespace fs
{ {
namespace cow namespace cow

1
src/fs_devid.hpp

@ -20,6 +20,7 @@
#include "fs_fstat.hpp" #include "fs_fstat.hpp"
namespace fs namespace fs
{ {
static static

1
src/fs_dirfd.hpp

@ -21,6 +21,7 @@
#include <dirent.h> #include <dirent.h>
#include <sys/types.h> #include <sys/types.h>
namespace fs namespace fs
{ {
static static

1
src/fs_dup.hpp

@ -20,6 +20,7 @@
#include <unistd.h> #include <unistd.h>
namespace fs namespace fs
{ {
static static

1
src/fs_eaccess.hpp

@ -20,6 +20,7 @@
#include "fs_faccessat.hpp" #include "fs_faccessat.hpp"
namespace fs namespace fs
{ {
static static

1
src/fs_exists.hpp

@ -23,6 +23,7 @@
#include <string> #include <string>
namespace fs namespace fs
{ {
static static

1
src/fs_faccessat.hpp

@ -23,6 +23,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
namespace fs namespace fs
{ {
static static

1
src/fs_fadvise.hpp

@ -18,6 +18,7 @@
#include <sys/types.h> #include <sys/types.h>
namespace fs namespace fs
{ {
int int

1
src/fs_fadvise_posix.icpp

@ -16,6 +16,7 @@
#include <fcntl.h> #include <fcntl.h>
namespace fs namespace fs
{ {
static static

1
src/fs_fadvise_unsupported.icpp

@ -16,6 +16,7 @@
#include "errno.hpp" #include "errno.hpp"
namespace fs namespace fs
{ {
static static

1
src/fs_fallocate.hpp

@ -18,6 +18,7 @@
#include <fcntl.h> #include <fcntl.h>
namespace fs namespace fs
{ {
int int

1
src/fs_fallocate_linux.icpp

@ -16,6 +16,7 @@
#include <fcntl.h> #include <fcntl.h>
namespace fs namespace fs
{ {
int int

3
src/fs_fallocate_osx.icpp

@ -14,10 +14,11 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "errno.hpp"
#include <fcntl.h> #include <fcntl.h>
#include <unistd.h> #include <unistd.h>
#include "errno.hpp"
namespace l namespace l
{ {

1
src/fs_fallocate_posix.icpp

@ -18,6 +18,7 @@
#include <fcntl.h> #include <fcntl.h>
namespace fs namespace fs
{ {
int int

1
src/fs_fallocate_unsupported.icpp

@ -16,6 +16,7 @@
#include "errno.hpp" #include "errno.hpp"
namespace fs namespace fs
{ {
int int

1
src/fs_fchmod.hpp

@ -24,6 +24,7 @@
#define MODE_BITS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO) #define MODE_BITS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
namespace fs namespace fs
{ {
static static

1
src/fs_fchmodat.hpp

@ -23,6 +23,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
namespace fs namespace fs
{ {
static static

1
src/fs_fchown.hpp

@ -25,6 +25,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
namespace fs namespace fs
{ {
static static

1
src/fs_fdatasync.hpp

@ -26,6 +26,7 @@
#include <unistd.h> #include <unistd.h>
namespace fs namespace fs
{ {
static static

1
src/fs_fgetxattr.hpp

@ -25,6 +25,7 @@
#include <sys/types.h> #include <sys/types.h>
namespace fs namespace fs
{ {
static static

1
src/fs_ficlone.hpp

@ -18,6 +18,7 @@
#pragma once #pragma once
namespace fs namespace fs
{ {
int int

1
src/fs_ficlone_linux.icpp

@ -21,6 +21,7 @@
#include <linux/fs.h> #include <linux/fs.h>
namespace fs namespace fs
{ {
int int

1
src/fs_ficlone_unsupported.icpp

@ -18,6 +18,7 @@
#include "errno.hpp" #include "errno.hpp"
namespace fs namespace fs
{ {
int int

3
src/fs_file_size.cpp

@ -18,7 +18,8 @@
#include "fs_fstat.hpp" #include "fs_fstat.hpp"
#include <stdint.h>
#include <cstdint>
namespace fs namespace fs
{ {

3
src/fs_file_size.hpp

@ -18,7 +18,8 @@
#pragma once #pragma once
#include <stdint.h>
#include <cstdint>
namespace fs namespace fs
{ {

1
src/fs_findallfiles.cpp

@ -22,6 +22,7 @@
#include <string> #include <string>
#include <vector> #include <vector>
namespace fs namespace fs
{ {
void void

9
src/fs_findallfiles.hpp

@ -18,13 +18,16 @@
#pragma once #pragma once
#include "strvec.hpp"
#include <string> #include <string>
#include <vector> #include <vector>
namespace fs namespace fs
{ {
void void
findallfiles(const std::vector<std::string> &basepaths,
const char *fusepath,
std::vector<std::string> *paths);
findallfiles(const StrVec &basepaths,
const char *fusepath,
StrVec *paths);
} }

32
src/fs_findonfs.cpp

@ -16,7 +16,7 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "branch.hpp"
#include "branches.hpp"
#include "errno.hpp" #include "errno.hpp"
#include "fs_fstat.hpp" #include "fs_fstat.hpp"
#include "fs_lstat.hpp" #include "fs_lstat.hpp"
@ -24,31 +24,29 @@
#include <string> #include <string>
namespace l namespace l
{ {
static static
int int
findonfs(const BranchVec &branches_,
const std::string &fusepath_,
const int fd_,
std::string *basepath_)
findonfs(const Branches::CPtr &branches_,
const std::string &fusepath_,
const int fd_,
std::string *basepath_)
{ {
int rv; int rv;
dev_t dev; dev_t dev;
struct stat st; struct stat st;
std::string fullpath; std::string fullpath;
const Branch *branch;
rv = fs::fstat(fd_,&st); rv = fs::fstat(fd_,&st);
if(rv == -1) if(rv == -1)
return -1; return -1;
dev = st.st_dev; dev = st.st_dev;
for(size_t i = 0, ei = branches_.size(); i != ei; i++)
for(const auto &branch : *branches_)
{ {
branch = &branches_[i];
fullpath = fs::path::make(branch->path,fusepath_);
fullpath = fs::path::make(branch.path,fusepath_);
rv = fs::lstat(fullpath,&st); rv = fs::lstat(fullpath,&st);
if(rv == -1) if(rv == -1)
@ -57,7 +55,7 @@ namespace l
if(st.st_dev != dev) if(st.st_dev != dev)
continue; continue;
*basepath_ = branch->path;
*basepath_ = branch.path;
return 0; return 0;
} }
@ -69,13 +67,11 @@ namespace l
namespace fs namespace fs
{ {
int int
findonfs(const Branches &branches_,
const std::string &fusepath_,
const int fd_,
std::string *basepath_)
findonfs(const Branches::CPtr &branches_,
const std::string &fusepath_,
const int fd_,
std::string *basepath_)
{ {
rwlock::ReadGuard guard(branches_.lock);
return l::findonfs(branches_.vec,fusepath_,fd_,basepath_);
return l::findonfs(branches_,fusepath_,fd_,basepath_);
} }
} }

11
src/fs_findonfs.hpp

@ -18,15 +18,16 @@
#pragma once #pragma once
#include "branch.hpp"
#include "branches.hpp"
#include <string> #include <string>
namespace fs namespace fs
{ {
int int
findonfs(const Branches &branches,
const std::string &fusepath,
const int fd,
std::string *basepath);
findonfs(const Branches::CPtr &branches,
const std::string &fusepath,
const int fd,
std::string *basepath);
} }

1
src/fs_flistxattr.hpp

@ -23,6 +23,7 @@
#include <sys/types.h> #include <sys/types.h>
namespace fs namespace fs
{ {
static static

1
src/fs_flock.hpp

@ -20,6 +20,7 @@
#include <sys/file.h> #include <sys/file.h>
namespace fs namespace fs
{ {
static static

1
src/fs_fsetxattr.hpp

@ -25,6 +25,7 @@
#include <sys/types.h> #include <sys/types.h>
namespace fs namespace fs
{ {
static static

1
src/fs_fstat.hpp

@ -23,6 +23,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
namespace fs namespace fs
{ {
static static

1
src/fs_fstatat.hpp

@ -23,6 +23,7 @@
#include <unistd.h> #include <unistd.h>
#include <fcntl.h> #include <fcntl.h>
namespace fs namespace fs
{ {
static static

1
src/fs_fsync.hpp

@ -20,6 +20,7 @@
#include <unistd.h> #include <unistd.h>
namespace fs namespace fs
{ {
static static

1
src/fs_ftruncate.hpp

@ -21,6 +21,7 @@
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
namespace fs namespace fs
{ {
static static

1
src/fs_futimens.hpp

@ -33,6 +33,7 @@
#include "fs_futimens_generic.hpp" #include "fs_futimens_generic.hpp"
#endif #endif
namespace fs namespace fs
{ {
static static

1
src/fs_futimens_freebsd_11.hpp

@ -20,6 +20,7 @@
#include <sys/stat.h> #include <sys/stat.h>
namespace fs namespace fs
{ {
static static

1
src/fs_futimens_generic.hpp

@ -33,6 +33,7 @@
# define UTIME_OMIT ((1l << 30) - 2l) # define UTIME_OMIT ((1l << 30) - 2l)
#endif #endif
namespace l namespace l
{ {
static static

1
src/fs_futimens_linux.hpp

@ -20,6 +20,7 @@
#include <sys/stat.h> #include <sys/stat.h>
namespace fs namespace fs
{ {
static static

1
src/fs_futimesat.hpp

@ -20,6 +20,7 @@
#include <sys/time.h> #include <sys/time.h>
namespace fs namespace fs
{ {
int int

1
src/fs_futimesat_generic.icpp

@ -19,6 +19,7 @@
#include <fcntl.h> #include <fcntl.h>
#include <sys/time.h> #include <sys/time.h>
namespace fs namespace fs
{ {
int int

1
src/fs_futimesat_osx.icpp

@ -26,6 +26,7 @@
#include <sys/time.h> #include <sys/time.h>
#include <unistd.h> #include <unistd.h>
namespace l namespace l
{ {
static static

1
src/fs_getdents64.cpp

@ -23,6 +23,7 @@
#include <sys/syscall.h> #include <sys/syscall.h>
#endif #endif
namespace fs namespace fs
{ {
int int

1
src/fs_getdents64.hpp

@ -18,6 +18,7 @@
#pragma once #pragma once
namespace fs namespace fs
{ {
int int

1
src/fs_getfl.cpp

@ -18,6 +18,7 @@
#include <fcntl.h> #include <fcntl.h>
namespace fs namespace fs
{ {
int int

1
src/fs_getfl.hpp

@ -18,6 +18,7 @@
#pragma once #pragma once
namespace fs namespace fs
{ {
int getfl(const int fd); int getfl(const int fd);

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

Loading…
Cancel
Save