Browse Source

checkpoint

toml
Antonio SJ Musumeci 3 years ago
parent
commit
3cc77d6066
  1. 8
      config.toml
  2. 402
      src/config.cpp
  3. 205
      src/config.hpp
  4. 62
      src/config_cachefiles.cpp
  5. 33
      src/config_cachefiles.hpp
  6. 58
      src/config_follow_symlinks.cpp
  7. 30
      src/config_follow_symlinks.hpp
  8. 59
      src/config_inodecalc.cpp
  9. 35
      src/config_inodecalc.hpp
  10. 53
      src/config_log_metrics.cpp
  11. 31
      src/config_log_metrics.hpp
  12. 56
      src/config_moveonenospc.cpp
  13. 44
      src/config_moveonenospc.hpp
  14. 55
      src/config_nfsopenhack.cpp
  15. 31
      src/config_nfsopenhack.hpp
  16. 51
      src/config_readdir.cpp
  17. 30
      src/config_readdir.hpp
  18. 51
      src/config_statfs.cpp
  19. 30
      src/config_statfs.hpp
  20. 55
      src/config_statfsignore.cpp
  21. 30
      src/config_statfsignore.hpp
  22. 55
      src/config_xattr.cpp
  23. 32
      src/config_xattr.hpp
  24. 2
      src/fuse_access_policy_factory.cpp
  25. 2
      src/fuse_chmod_policy_factory.cpp
  26. 2
      src/fuse_chown_policy_factory.cpp
  27. 2
      src/fuse_create_policy_factory.cpp
  28. 2
      src/fuse_getattr_policy_factory.cpp
  29. 2
      src/fuse_getxattr_policy_factory.cpp
  30. 323
      src/fuse_ioctl.cpp
  31. 2
      src/fuse_ioctl_policy_factory.cpp
  32. 2
      src/fuse_link_policy_factory.cpp
  33. 2
      src/fuse_listxattr_policy_factory.cpp
  34. 2
      src/fuse_mkdir_policy_factory.cpp
  35. 2
      src/fuse_mknod_policy_factory.cpp
  36. 2
      src/fuse_open_policy_factory.cpp
  37. 2
      src/fuse_readlink_policy_factory.cpp
  38. 2
      src/fuse_removexattr_policy_factory.cpp
  39. 2
      src/fuse_rename_policy_factory.cpp
  40. 2
      src/fuse_rmdir_policy_factory.cpp
  41. 163
      src/fuse_setxattr.cpp
  42. 2
      src/fuse_setxattr_policy_factory.cpp
  43. 2
      src/fuse_symlink_policy_factory.cpp
  44. 2
      src/fuse_truncate_policy_factory.cpp
  45. 99
      src/fuse_unlink.cpp
  46. 2
      src/fuse_unlink_policy_factory.cpp
  47. 2
      src/fuse_utimens_policy_factory.cpp
  48. 9
      src/mergerfs.cpp
  49. 418
      src/option_parser.cpp
  50. 29
      src/option_parser.hpp

8
config.toml

@ -55,7 +55,7 @@ link-cow = true
nfs-hack = 'off'
[func.rename]
policy = ''
policy = 'all'
exdev = 'passthrough'
[func.statfs]
@ -84,6 +84,6 @@ path-type = 'literal'
mode = 'RW'
if-not-mountpoint = 'fail' # 'fail' | 'deactivate' ?
[[branches.group.branch]]
path = '/tmp/mergerfs/*'
path-type = 'glob'
#[[branches.group.branch]]
#path = '/tmp/mergerfs/*'
#path-type = 'glob'

402
src/config.cpp

@ -1,402 +0,0 @@
/*
Copyright (c) 2016, 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_access.hpp"
#include "fuse_getattr.hpp"
#include "config.hpp"
#include "ef.hpp"
#include "errno.hpp"
#include "from_string.hpp"
#include "num.hpp"
#include "rwlock.hpp"
#include "str.hpp"
#include "to_string.hpp"
#include "version.hpp"
#include "toml.hpp"
#include "toml_verify.hpp"
//#include "nonstd/span.hpp"
#include <algorithm>
#include <cstdint>
#include <fstream>
#include <iostream>
#include <string>
#include <pthread.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#define MINFREESPACE_DEFAULT (4294967295ULL)
using std::string;
#define IFERT(S) if(S == s_) return true
Config Config::_singleton;
namespace l
{
static
bool
readonly(const std::string &s_)
{
IFERT("async_read");
IFERT("cache.symlinks");
IFERT("cache.writeback");
IFERT("fsname");
IFERT("fuse_msg_size");
IFERT("mount");
IFERT("nullrw");
IFERT("pid");
IFERT("readdirplus");
IFERT("threads");
IFERT("version");
return false;
}
}
Config::Config()
: async_read(true),
auto_cache(false),
minfreespace(MINFREESPACE_DEFAULT),
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(),
follow_symlinks(FollowSymlinks::ENUM::NEVER),
func(),
fuse_msg_size(FUSE_MAX_MAX_PAGES),
ignorepponrename(false),
inodecalc("hybrid-hash"),
link_cow(false),
log_metrics(false),
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["auto_cache"] = &auto_cache;
_map["branches"] = &branches;
_map["cache.attr"] = &cache_attr;
_map["cache.entry"] = &cache_entry;
_map["cache.files"] = &cache_files;
_map["cache.negative_entry"] = &cache_negative_entry;
_map["cache.readdir"] = &cache_readdir;
_map["cache.statfs"] = &cache_statfs;
_map["cache.symlinks"] = &cache_symlinks;
_map["cache.writeback"] = &writeback_cache;
_map["category.action"] = &category.action;
_map["category.create"] = &category.create;
_map["category.search"] = &category.search;
_map["direct_io"] = &direct_io;
_map["dropcacheonclose"] = &dropcacheonclose;
_map["follow-symlinks"] = &follow_symlinks;
_map["fsname"] = &fsname;
_map["func.access"] = &func.access;
_map["func.chmod"] = &func.chmod;
_map["func.chown"] = &func.chown;
_map["func.create"] = &func.create;
_map["func.getattr"] = &func.getattr;
_map["func.getxattr"] = &func.getxattr;
_map["func.link"] = &func.link;
_map["func.listxattr"] = &func.listxattr;
_map["func.mkdir"] = &func.mkdir;
_map["func.mknod"] = &func.mknod;
_map["func.open"] = &func.open;
_map["func.readlink"] = &func.readlink;
_map["func.removexattr"] = &func.removexattr;
_map["func.rename"] = &func.rename;
_map["func.rmdir"] = &func.rmdir;
_map["func.setxattr"] = &func.setxattr;
_map["func.symlink"] = &func.symlink;
_map["func.truncate"] = &func.truncate;
_map["func.unlink"] = &func.unlink;
_map["func.utimens"] = &func.utimens;
_map["fuse_msg_size"] = &fuse_msg_size;
_map["ignorepponrename"] = &ignorepponrename;
_map["inodecalc"] = &inodecalc;
_map["kernel_cache"] = &kernel_cache;
_map["link_cow"] = &link_cow;
_map["log.metrics"] = &log_metrics;
_map["minfreespace"] = &minfreespace;
_map["mount"] = &mount;
_map["moveonenospc"] = &moveonenospc;
_map["nfsopenhack"] = &nfsopenhack;
_map["nullrw"] = &nullrw;
_map["pid"] = &pid;
_map["posix_acl"] = &posix_acl;
// _map["readdir"] = &readdir;
_map["readdirplus"] = &readdirplus;
_map["security_capability"] = &security_capability;
_map["srcmounts"] = &srcmounts;
_map["statfs"] = &statfs;
_map["statfs_ignore"] = &statfs_ignore;
_map["symlinkify"] = &symlinkify;
_map["symlinkify_timeout"] = &symlinkify_timeout;
_map["threads"] = &threads;
_map["version"] = &version;
_map["xattr"] = &xattr;
}
Config&
Config::operator=(const Config &cfg_)
{
int rv;
std::string val;
for(auto &kv : _map)
{
rv = cfg_.get(kv.first,&val);
if(rv)
continue;
kv.second->from_string(val);
}
return *this;
}
bool
Config::has_key(const std::string &key_) const
{
return _map.count(key_);
}
void
Config::keys(std::string &s_) const
{
Str2TFStrMap::const_iterator i;
Str2TFStrMap::const_iterator ei;
s_.reserve(512);
i = _map.begin();
ei = _map.end();
for(; i != ei; ++i)
{
s_ += i->first;
s_ += '\0';
}
s_.resize(s_.size() - 1);
}
void
Config::keys_xattr(std::string &s_) const
{
Str2TFStrMap::const_iterator i;
Str2TFStrMap::const_iterator ei;
s_.reserve(1024);
for(i = _map.begin(), ei = _map.end(); i != ei; ++i)
{
s_ += "user.mergerfs.";
s_ += i->first;
s_ += '\0';
}
}
int
Config::get(const std::string &key_,
std::string *val_) const
{
Str2TFStrMap::const_iterator i;
i = _map.find(key_);
if(i == _map.end())
return -ENOATTR;
*val_ = i->second->to_string();
return 0;
}
int
Config::set_raw(const std::string &key_,
const std::string &value_)
{
Str2TFStrMap::iterator i;
i = _map.find(key_);
if(i == _map.end())
return -ENOATTR;
return i->second->from_string(value_);
}
int
Config::set(const std::string &key_,
const std::string &value_)
{
if(l::readonly(key_))
return -EROFS;
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&
operator<<(std::ostream &os_,
const Config &c_)
{
Str2TFStrMap::const_iterator i;
Str2TFStrMap::const_iterator ei;
for(i = c_._map.begin(), ei = c_._map.end(); i != ei; ++i)
{
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_;
}

205
src/config.hpp

@ -1,205 +0,0 @@
/*
Copyright (c) 2016, 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 "branches.hpp"
#include "category.hpp"
#include "config_cachefiles.hpp"
#include "config_follow_symlinks.hpp"
#include "config_inodecalc.hpp"
#include "config_log_metrics.hpp"
#include "config_moveonenospc.hpp"
#include "config_nfsopenhack.hpp"
#include "config_readdir.hpp"
#include "config_statfs.hpp"
#include "config_statfsignore.hpp"
#include "config_xattr.hpp"
#include "enum.hpp"
#include "errno.hpp"
#include "funcs.hpp"
#include "policy.hpp"
#include "rwlock.hpp"
#include "tofrom_wrapper.hpp"
#include "fuse.h"
#include "toml.hpp"
#include <cstdint>
#include <map>
#include <memory>
#include <string>
#include <vector>
#include <sys/stat.h>
typedef ToFromWrapper<bool> ConfigBOOL;
typedef ToFromWrapper<uint64_t> ConfigUINT64;
typedef ToFromWrapper<int> ConfigINT;
typedef ToFromWrapper<std::string> ConfigSTR;
typedef std::map<std::string,ToFromString*> Str2TFStrMap;
class Config
{
public:
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:
class Write
{
public:
Write();
public:
Config* operator->();
private:
Config &_cfg;
};
public:
Config();
public:
Config& operator=(const Config&);
public:
ConfigBOOL async_read;
ConfigBOOL auto_cache;
ConfigUINT64 minfreespace;
Branches branches;
ConfigUINT64 cache_attr;
ConfigUINT64 cache_entry;
CacheFiles cache_files;
ConfigUINT64 cache_negative_entry;
ConfigBOOL cache_readdir;
ConfigUINT64 cache_statfs;
ConfigBOOL cache_symlinks;
Categories category;
ConfigBOOL direct_io;
ConfigBOOL dropcacheonclose;
ConfigSTR fsname;
FollowSymlinks follow_symlinks;
Funcs func;
ConfigUINT64 fuse_msg_size;
ConfigBOOL ignorepponrename;
InodeCalc inodecalc;
ConfigBOOL kernel_cache;
ConfigBOOL link_cow;
LogMetrics log_metrics;
ConfigSTR mount;
MoveOnENOSPC moveonenospc;
NFSOpenHack nfsopenhack;
ConfigBOOL nullrw;
ConfigUINT64 pid;
ConfigBOOL posix_acl;
ReadDir readdir;
ConfigBOOL readdirplus;
ConfigBOOL security_capability;
SrcMounts srcmounts;
StatFS statfs;
StatFSIgnore statfs_ignore;
ConfigBOOL symlinkify;
ConfigUINT64 symlinkify_timeout;
ConfigINT threads;
ConfigSTR version;
ConfigBOOL writeback_cache;
XAttr xattr;
public:
friend std::ostream& operator<<(std::ostream &s,
const Config &c);
public:
bool has_key(const std::string &key) const;
void keys(std::string &s) const;
void keys_xattr(std::string &s) const;
public:
int get(const std::string &key, std::string *val) const;
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 &kv);
public:
int from_stream(std::istream &istrm, ErrVec *errs);
int from_file(const std::string &filepath, ErrVec *errs);
int from_toml(const toml::value &value, ErrVec *errs);
private:
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;
}
int process_toml_config(const std::string &filepath_);

62
src/config_cachefiles.cpp

@ -1,62 +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 "config_cachefiles.hpp"
#include "ef.hpp"
#include "errno.hpp"
template<>
std::string
CacheFiles::to_string() const
{
switch(_data)
{
case CacheFiles::ENUM::LIBFUSE:
return "libfuse";
case CacheFiles::ENUM::OFF:
return "off";
case CacheFiles::ENUM::PARTIAL:
return "partial";
case CacheFiles::ENUM::FULL:
return "full";
case CacheFiles::ENUM::AUTO_FULL:
return "auto-full";
}
return "invalid";
}
template<>
int
CacheFiles::from_string(const std::string &s_)
{
if(s_ == "libfuse")
_data = CacheFiles::ENUM::LIBFUSE;
ef(s_ == "off")
_data = CacheFiles::ENUM::OFF;
ef(s_ == "partial")
_data = CacheFiles::ENUM::PARTIAL;
ef(s_ == "full")
_data = CacheFiles::ENUM::FULL;
ef(s_ == "auto-full")
_data = CacheFiles::ENUM::AUTO_FULL;
else
return -EINVAL;
return 0;
}

33
src/config_cachefiles.hpp

@ -1,33 +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.
*/
#pragma once
#include "enum.hpp"
enum class CacheFilesEnum
{
LIBFUSE,
OFF,
PARTIAL,
FULL,
AUTO_FULL
};
typedef Enum<CacheFilesEnum> CacheFiles;

58
src/config_follow_symlinks.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 "config_follow_symlinks.hpp"
#include "ef.hpp"
#include "errno.hpp"
template<>
std::string
FollowSymlinks::to_string(void) const
{
switch(_data)
{
case FollowSymlinks::ENUM::NEVER:
return "never";
case FollowSymlinks::ENUM::DIRECTORY:
return "directory";
case FollowSymlinks::ENUM::REGULAR:
return "regular";
case FollowSymlinks::ENUM::ALL:
return "all";
}
return "invalid";
}
template<>
int
FollowSymlinks::from_string(const std::string &s_)
{
if(s_ == "never")
_data = FollowSymlinks::ENUM::NEVER;
ef(s_ == "directory")
_data = FollowSymlinks::ENUM::DIRECTORY;
ef(s_ == "regular")
_data = FollowSymlinks::ENUM::REGULAR;
ef(s_ == "all")
_data = FollowSymlinks::ENUM::ALL;
else
return -EINVAL;
return 0;
}

30
src/config_follow_symlinks.hpp

@ -1,30 +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.
*/
#pragma once
#include "enum.hpp"
enum class FollowSymlinksEnum
{
NEVER,
DIRECTORY,
REGULAR,
ALL
};
typedef Enum<FollowSymlinksEnum> FollowSymlinks;

59
src/config_inodecalc.cpp

@ -1,59 +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 "config_inodecalc.hpp"
#include "fs_inode.hpp"
#include "toml.hpp"
InodeCalc::InodeCalc(const std::string &s_)
{
fs::inode::set_algo(s_);
}
std::string
InodeCalc::to_string(void) const
{
return fs::inode::get_algo();
}
int
InodeCalc::from_string(const std::string &s_)
{
return fs::inode::set_algo(s_);
}
void
InodeCalc::from_toml(const toml::value &v_)
{
int rv;
rv = fs::inode::set_algo(v_.as_string());
if(rv < 0)
throw toml::type_error("must be: "
"passthrough|"
"path-hash|"
"path-hash32|"
"devino-hash|"
"devino-hash32|"
"hybrid-hash|"
"hybrid-hash32"
,
v_.location());
return;
}

35
src/config_inodecalc.hpp

@ -1,35 +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.
*/
#pragma once
#include "tofrom_string.hpp"
#include "toml.hpp"
class InodeCalc : public ToFromString
{
public:
InodeCalc(const std::string &);
public:
void from_toml(const toml::value &);
public:
std::string to_string(void) const final;
int from_string(const std::string &) final;
};

53
src/config_log_metrics.cpp

@ -1,53 +0,0 @@
/*
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 "config_log_metrics.hpp"
#include "from_string.hpp"
#include "to_string.hpp"
#include "fuse.h"
LogMetrics::LogMetrics(const bool val_)
{
fuse_log_metrics_set(val_);
}
std::string
LogMetrics::to_string(void) const
{
bool val;
val = fuse_log_metrics_get();
return str::to(val);
}
int
LogMetrics::from_string(const std::string &s_)
{
int rv;
bool val;
rv = str::from(s_,&val);
if(rv < 0)
return rv;
fuse_log_metrics_set(val);
return 0;
}

31
src/config_log_metrics.hpp

@ -1,31 +0,0 @@
/*
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 "tofrom_string.hpp"
class LogMetrics : public ToFromString
{
public:
LogMetrics(const bool);
public:
std::string to_string(void) const final;
int from_string(const std::string &) final;
};

56
src/config_moveonenospc.cpp

@ -1,56 +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 "config_moveonenospc.hpp"
#include "ef.hpp"
#include "errno.hpp"
#include "from_string.hpp"
int
MoveOnENOSPC::from_string(const std::string &s_)
{
int rv;
std::string s;
Policy::CreateImpl *tmp;
rv = str::from(s_,&enabled);
if((rv == 0) && (enabled == true))
s = "mfs";
ef(rv != 0)
s = s_;
else
return 0;
tmp = Policies::Create::find(s);
if(tmp == NULL)
return -EINVAL;
policy = tmp;
enabled = true;
return 0;
}
std::string
MoveOnENOSPC::to_string(void) const
{
if(enabled)
return policy.name();
return "false";
}

44
src/config_moveonenospc.hpp

@ -1,44 +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.
*/
#pragma once
#include "policy.hpp"
#include "policies.hpp"
#include "tofrom_string.hpp"
#include <string>
class MoveOnENOSPC : public ToFromString
{
public:
MoveOnENOSPC(const bool enabled_)
: enabled(enabled_),
policy(&Policies::Create::mfs)
{
}
public:
int from_string(const std::string &s) final;
std::string to_string() const final;
public:
bool enabled;
Policy::Create policy;
};

55
src/config_nfsopenhack.cpp

@ -1,55 +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 "config_nfsopenhack.hpp"
#include "ef.hpp"
#include "errno.hpp"
template<>
int
NFSOpenHack::from_string(const std::string &s_)
{
if(s_ == "off")
_data = NFSOpenHack::ENUM::OFF;
ef(s_ == "git")
_data = NFSOpenHack::ENUM::GIT;
ef(s_ == "all")
_data = NFSOpenHack::ENUM::ALL;
else
return -EINVAL;
return 0;
}
template<>
std::string
NFSOpenHack::to_string(void) const
{
switch(_data)
{
case NFSOpenHack::ENUM::OFF:
return "off";
case NFSOpenHack::ENUM::GIT:
return "git";
case NFSOpenHack::ENUM::ALL:
return "all";
}
return std::string();
}

31
src/config_nfsopenhack.hpp

@ -1,31 +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.
*/
#pragma once
#include "enum.hpp"
enum class NFSOpenHackEnum
{
OFF,
GIT,
ALL
};
typedef Enum<NFSOpenHackEnum> NFSOpenHack;

51
src/config_readdir.cpp

@ -1,51 +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 "config_readdir.hpp"
#include "ef.hpp"
#include "errno.hpp"
template<>
int
ReadDir::from_string(const std::string &s_)
{
if(s_ == "posix")
_data = ReadDir::ENUM::POSIX;
ef(s_ == "linux")
_data = ReadDir::ENUM::LINUX;
else
return -EINVAL;
return 0;
}
template<>
std::string
ReadDir::to_string(void) const
{
switch(_data)
{
case ReadDir::ENUM::POSIX:
return "posix";
case ReadDir::ENUM::LINUX:
return "linux";
}
return "invalid";
}

30
src/config_readdir.hpp

@ -1,30 +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.
*/
#pragma once
#include "enum.hpp"
enum class ReadDirEnum
{
POSIX,
LINUX
};
typedef Enum<ReadDirEnum> ReadDir;

51
src/config_statfs.cpp

@ -1,51 +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 "config_statfs.hpp"
#include "ef.hpp"
#include "errno.hpp"
template<>
std::string
StatFS::to_string() const
{
switch(_data)
{
case StatFS::ENUM::BASE:
return "base";
case StatFS::ENUM::FULL:
return "full";
}
return "invalid";
}
template<>
int
StatFS::from_string(const std::string &s_)
{
if(s_ == "base")
_data = StatFS::ENUM::BASE;
ef(s_ == "full")
_data = StatFS::ENUM::FULL;
else
return -EINVAL;
return 0;
}

30
src/config_statfs.hpp

@ -1,30 +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.
*/
#pragma once
#include "enum.hpp"
enum class StatFSEnum
{
BASE,
FULL
};
typedef Enum<StatFSEnum> StatFS;

55
src/config_statfsignore.cpp

@ -1,55 +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 "config_statfsignore.hpp"
#include "ef.hpp"
#include "errno.hpp"
template<>
std::string
StatFSIgnore::to_string() const
{
switch(_data)
{
case StatFSIgnore::ENUM::NONE:
return "none";
case StatFSIgnore::ENUM::RO:
return "ro";
case StatFSIgnore::ENUM::NC:
return "nc";
}
return "invalid";
}
template<>
int
StatFSIgnore::from_string(const std::string &s_)
{
if(s_ == "none")
_data = StatFSIgnore::ENUM::NONE;
ef(s_ == "ro")
_data = StatFSIgnore::ENUM::RO;
ef(s_ == "nc")
_data = StatFSIgnore::ENUM::NC;
else
return -EINVAL;
return 0;
}

30
src/config_statfsignore.hpp

@ -1,30 +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.
*/
#pragma once
#include "enum.hpp"
enum class StatFSIgnoreEnum
{
NONE,
RO,
NC
};
typedef Enum<StatFSIgnoreEnum> StatFSIgnore;

55
src/config_xattr.cpp

@ -1,55 +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 "config_xattr.hpp"
#include "ef.hpp"
#include "errno.hpp"
template<>
std::string
XAttr::to_string() const
{
switch(_data)
{
case XAttr::ENUM::PASSTHROUGH:
return "passthrough";
case XAttr::ENUM::NOSYS:
return "nosys";
case XAttr::ENUM::NOATTR:
return "noattr";
}
return "invalid";
}
template<>
int
XAttr::from_string(const std::string &s_)
{
if(s_ == "passthrough")
_data = XAttr::ENUM::PASSTHROUGH;
ef(s_ == "nosys")
_data = XAttr::ENUM::NOSYS;
ef(s_ == "noattr")
_data = XAttr::ENUM::NOATTR;
else
return -EINVAL;
return 0;
}

32
src/config_xattr.hpp

@ -1,32 +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.
*/
#pragma once
#include "enum.hpp"
#include "errno.hpp"
enum class XAttrEnum
{
PASSTHROUGH = 0,
NOSYS = ENOSYS,
NOATTR = ENOATTR
};
typedef Enum<XAttrEnum> XAttr;

2
src/fuse_access_policy_factory.cpp

@ -33,6 +33,6 @@ namespace FUSE::ACCESS::POLICY
if(str == "ff")
return std::make_shared<FF>(toml_);
throw std::runtime_error("");
throw std::runtime_error("access");
}
}

2
src/fuse_chmod_policy_factory.cpp

@ -33,6 +33,6 @@ namespace FUSE::CHMOD::POLICY
if(str == "all")
return std::make_shared<ALL>(toml_);
throw std::runtime_error("");
throw std::runtime_error("chmod");
}
}

2
src/fuse_chown_policy_factory.cpp

@ -33,6 +33,6 @@ namespace FUSE::CHOWN::POLICY
if(str == "all")
return std::make_shared<ALL>(toml_);
throw std::runtime_error("");
throw std::runtime_error("chown");
}
}

2
src/fuse_create_policy_factory.cpp

@ -35,6 +35,6 @@ namespace FUSE::CREATE::POLICY
if(str == "epff")
return std::make_shared<EPFF>(toml_);
throw std::runtime_error("");
throw std::runtime_error("create");
}
}

2
src/fuse_getattr_policy_factory.cpp

@ -43,6 +43,6 @@ namespace FUSE::GETATTR::POLICY
if(str == "check-ff")
return std::make_shared<CheckFF>(toml_);
throw std::runtime_error("");
throw std::runtime_error("getattr");
}
}

2
src/fuse_getxattr_policy_factory.cpp

@ -34,6 +34,6 @@ namespace FUSE::GETXATTR::POLICY
if(str == "ff")
return std::make_shared<FF>(toml_);
throw std::runtime_error("");
throw std::runtime_error("getxattr");
}
}

323
src/fuse_ioctl.cpp

@ -14,322 +14,11 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.hpp"
#include "dirinfo.hpp"
#include "endian.hpp"
#include "errno.hpp"
#include "fileinfo.hpp"
#include "fs_close.hpp"
#include "fs_findallfiles.hpp"
#include "fs_ioctl.hpp"
#include "fs_open.hpp"
#include "fs_path.hpp"
#include "state.hpp"
#include "str.hpp"
#include "ugid.hpp"
#include <string>
#include <vector>
#include "fuse.h"
#include <fcntl.h>
#include <string.h>
using std::string;
using std::vector;
#ifndef _IOC_TYPE
#define _IOC_TYPE(X) (((X) >> 8) & 0xFF)
#endif
typedef char IOCTL_BUF[4096];
#define IOCTL_APP_TYPE 0xDF
#define IOCTL_FILE_INFO _IOWR(IOCTL_APP_TYPE,0,IOCTL_BUF)
#ifndef FS_IOC_GETFLAGS
# define FS_IOC_GETFLAGS _IOR('f',1,long)
#endif
#ifndef FS_IOC_SETFLAGS
# define FS_IOC_SETFLAGS _IOW('f',2,long)
#endif
#ifndef FS_IOC_GETVERSION
# define FS_IOC_GETVERSION _IOR('v',1,long)
#endif
#ifndef FS_IOC_SETVERSION
# define FS_IOC_SETVERSION _IOW('v',2,long)
#endif
/*
There is a bug with FUSE and these ioctl commands. The regular
libfuse high level API assumes the output buffer size based on the
command and gives no control over this. FS_IOC_GETFLAGS and
FS_IOC_SETFLAGS however are defined as `long` when in fact it is an
`int`. On 64bit systems where long is 8 bytes this can lead to
libfuse telling the kernel to write 8 bytes and if the user only
allocated an integer then it will overwrite the 4 bytes after the
variable which could result in data corruption and/or crashes.
I've modified the API to allow changing of the output buffer
size. This fixes the issue on little endian systems because the
lower 4 bytes are the same regardless of what the user
allocated. However, on big endian systems that's not the case and it
is not possible to safely handle the situation.
https://lwn.net/Articles/575846/
*/
namespace l
{
static
int
ioctl(const int fd_,
const uint32_t cmd_,
void *data_,
uint32_t *out_bufsz_)
{
int rv;
switch(cmd_)
{
case FS_IOC_GETFLAGS:
case FS_IOC_SETFLAGS:
case FS_IOC_GETVERSION:
case FS_IOC_SETVERSION:
if(endian::is_big() && (sizeof(long) != sizeof(int)))
return -ENOTTY;
if((data_ != NULL) && (*out_bufsz_ > 4))
*out_bufsz_ = 4;
break;
}
rv = fs::ioctl(fd_,cmd_,data_);
return ((rv == -1) ? -errno : rv);
}
static
int
ioctl_file(const fuse_file_info_t *ffi_,
const uint32_t cmd_,
void *data_,
uint32_t *out_bufsz_)
{
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi_->fh);
const fuse_context *fc = fuse_get_context();
const ugid::Set ugid(fc->uid,fc->gid);
return l::ioctl(fi->fd,cmd_,data_,out_bufsz_);
}
#ifndef O_NOATIME
#define O_NOATIME 0
#endif
static
int
ioctl_dir_base(const Policy::Search &searchFunc_,
const Branches &branches_,
const char *fusepath_,
const uint32_t cmd_,
void *data_,
uint32_t *out_bufsz_)
{
int fd;
int rv;
string fullpath;
StrVec basepaths;
rv = searchFunc_(branches_,fusepath_,&basepaths);
if(rv == -1)
return -errno;
fullpath = fs::path::make(basepaths[0],fusepath_);
fd = fs::open(fullpath,O_RDONLY|O_NOATIME|O_NONBLOCK);
if(fd == -1)
return -errno;
rv = l::ioctl(fd,cmd_,data_,out_bufsz_);
fs::close(fd);
return rv;
}
static
int
ioctl_dir(const fuse_file_info_t *ffi_,
const uint32_t cmd_,
void *data_,
uint32_t *out_bufsz_)
{
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);
return l::ioctl_dir_base(cfg->func.open.policy,
cfg->branches,
di->fusepath.c_str(),
cmd_,
data_,
out_bufsz_);
}
static
int
strcpy(const std::string &s_,
void *data_)
{
char *data = (char*)data_;
if(s_.size() >= (sizeof(IOCTL_BUF) - 1))
return -ERANGE;
memcpy(data,s_.c_str(),s_.size());
data[s_.size()] = '\0';
return s_.size();
}
static
int
file_basepath(const Policy::Search &searchFunc_,
const Branches &branches_,
const char *fusepath_,
void *data_)
{
int rv;
StrVec basepaths;
rv = searchFunc_(branches_,fusepath_,&basepaths);
if(rv == -1)
return -errno;
return l::strcpy(basepaths[0],data_);
}
static
int
file_basepath(const fuse_file_info_t *ffi_,
void *data_)
{
Config::Read cfg;
gfs::path &fusepath = reinterpret_cast<FH*>(ffi_->fh)->fusepath;
return l::file_basepath(cfg->func.open.policy,
cfg->branches,
fusepath.c_str(),
data_);
}
static
int
file_relpath(const fuse_file_info_t *ffi_,
void *data_)
{
gfs::path &fusepath = reinterpret_cast<FH*>(ffi_->fh)->fusepath;
return l::strcpy(fusepath,data_);
}
static
int
file_fullpath(const Policy::Search &searchFunc_,
const Branches &branches_,
const string &fusepath_,
void *data_)
{
int rv;
string fullpath;
StrVec basepaths;
rv = searchFunc_(branches_,fusepath_,&basepaths);
if(rv == -1)
return -errno;
fullpath = fs::path::make(basepaths[0],fusepath_);
return l::strcpy(fullpath,data_);
}
static
int
file_fullpath(const fuse_file_info_t *ffi_,
void *data_)
{
Config::Read cfg;
gfs::path &fusepath = reinterpret_cast<FH*>(ffi_->fh)->fusepath;
return l::file_fullpath(cfg->func.open.policy,
cfg->branches,
fusepath,
data_);
}
static
int
file_allpaths(const fuse_file_info_t *ffi_,
void *data_)
{
Config::Read cfg;
string concated;
StrVec paths;
StrVec branches;
gfs::path &fusepath = reinterpret_cast<FH*>(ffi_->fh)->fusepath;
cfg->branches->to_paths(branches);
fs::findallfiles(branches,fusepath.c_str(),&paths);
concated = str::join(paths,'\0');
return l::strcpy(concated,data_);
}
static
int
file_info(const fuse_file_info_t *ffi_,
void *data_)
{
char *key = (char*)data_;
if(!strcmp("basepath",key))
return l::file_basepath(ffi_,data_);
if(!strcmp("relpath",key))
return l::file_relpath(ffi_,data_);
if(!strcmp("fullpath",key))
return l::file_fullpath(ffi_,data_);
if(!strcmp("allpaths",key))
return l::file_allpaths(ffi_,data_);
return -ENOATTR;
}
static
bool
is_mergerfs_ioctl_cmd(const unsigned long cmd_)
{
return (_IOC_TYPE(cmd_) == IOCTL_APP_TYPE);
}
static
int
ioctl_custom(const fuse_file_info_t *ffi_,
unsigned long cmd_,
void *data_)
{
switch(cmd_)
{
case IOCTL_FILE_INFO:
return l::file_info(ffi_,data_);
}
return -ENOTTY;
}
}
namespace FUSE::IOCTL
{
@ -341,12 +30,12 @@ namespace FUSE::IOCTL
void *data_,
uint32_t *out_bufsz_)
{
if(l::is_mergerfs_ioctl_cmd(cmd_))
return l::ioctl_custom(ffi_,cmd_,data_);
(void)arg_;
if(flags_ & FUSE_IOCTL_DIR)
return State()->ioctl(ffi_,cmd_,flags_,data_,out_bufsz_);
State s;
const fuse_context *fc = fuse_get_context();
const ugid::Set ugid(fc->uid,fc->gid);
return l::ioctl_file(ffi_,cmd_,data_,out_bufsz_);
return s->ioctl(ffi_,cmd_,flags_,data_,out_bufsz_);
}
}

2
src/fuse_ioctl_policy_factory.cpp

@ -33,6 +33,6 @@ namespace FUSE::IOCTL::POLICY
if(str == "all")
return std::make_shared<ALL>(toml_);
throw std::runtime_error("");
throw std::runtime_error("ioctl");
}
}

2
src/fuse_link_policy_factory.cpp

@ -34,6 +34,6 @@ namespace FUSE::LINK::POLICY
if(str == "all")
return std::make_shared<ALL>(toml_);
throw std::runtime_error("");
throw std::runtime_error("link");
}
}

2
src/fuse_listxattr_policy_factory.cpp

@ -34,6 +34,6 @@ namespace FUSE::LISTXATTR::POLICY
if(str == "ff")
return std::make_shared<FF>(toml_);
throw std::runtime_error("");
throw std::runtime_error("listxattr");
}
}

2
src/fuse_mkdir_policy_factory.cpp

@ -36,6 +36,6 @@ namespace FUSE::MKDIR::POLICY
if(str == "epff")
return std::make_shared<EPFF>(toml_);
throw std::runtime_error("");
throw std::runtime_error("mkdir");
}
}

2
src/fuse_mknod_policy_factory.cpp

@ -36,6 +36,6 @@ namespace FUSE::MKNOD::POLICY
if(str == "epff")
return std::make_shared<EPFF>(toml_);
throw std::runtime_error("");
throw std::runtime_error("mknod");
}
}

2
src/fuse_open_policy_factory.cpp

@ -34,6 +34,6 @@ namespace FUSE::OPEN::POLICY
if(str == "ff")
return std::make_shared<FF>(toml_);
throw std::runtime_error("");
throw std::runtime_error("open");
}
}

2
src/fuse_readlink_policy_factory.cpp

@ -33,6 +33,6 @@ namespace FUSE::READLINK::POLICY
if(str == "ff")
return std::make_shared<FF>(toml_);
throw std::runtime_error("");
throw std::runtime_error("readlink");
}
}

2
src/fuse_removexattr_policy_factory.cpp

@ -33,6 +33,6 @@ namespace FUSE::REMOVEXATTR::POLICY
if(str == "all")
return std::make_shared<ALL>(toml_);
throw std::runtime_error("");
throw std::runtime_error("removexattr");
}
}

2
src/fuse_rename_policy_factory.cpp

@ -33,6 +33,6 @@ namespace FUSE::RENAME::POLICY
if(str == "all")
return std::make_shared<ALL>(toml_);
throw std::runtime_error("");
throw std::runtime_error("rename");
}
}

2
src/fuse_rmdir_policy_factory.cpp

@ -34,6 +34,6 @@ namespace FUSE::RMDIR::POLICY
if(str == "all")
return std::make_shared<ALL>(toml_);
throw std::runtime_error("");
throw std::runtime_error("rmdir");
}
}

163
src/fuse_setxattr.cpp

@ -1,5 +1,5 @@
/*
Copyright (c) 2018, 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
@ -14,173 +14,14 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.hpp"
#include "errno.hpp"
#include "fs_glob.hpp"
#include "fs_lsetxattr.hpp"
#include "fs_path.hpp"
#include "fs_statvfs_cache.hpp"
#include "num.hpp"
#include "policy_rv.hpp"
#include "state.hpp"
#include "str.hpp"
#include "ugid.hpp"
#include "fuse.h"
#include <string>
#include <vector>
#include <string.h>
static const char SECURITY_CAPABILITY[] = "security.capability";
using std::string;
using std::vector;
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
bool
is_attrname_security_capability(const char *attrname_)
{
return (strcmp(attrname_,SECURITY_CAPABILITY) == 0);
}
static
void
setxattr_loop_core(const string &basepath_,
const char *fusepath_,
const char *attrname_,
const char *attrval_,
const size_t attrvalsize_,
const int flags_,
PolicyRV *prv_)
{
string fullpath;
fullpath = fs::path::make(basepath_,fusepath_);
errno = 0;
fs::lsetxattr(fullpath,attrname_,attrval_,attrvalsize_,flags_);
prv_->insert(errno,basepath_);
}
static
void
setxattr_loop(const StrVec &basepaths_,
const char *fusepath_,
const char *attrname_,
const char *attrval_,
const size_t attrvalsize_,
const int flags_,
PolicyRV *prv_)
{
for(size_t i = 0, ei = basepaths_.size(); i != ei; i++)
{
l::setxattr_loop_core(basepaths_[i],fusepath_,
attrname_,attrval_,attrvalsize_,
flags_,prv_);
}
}
static
int
setxattr(const Policy::Action &setxattrPolicy_,
const Policy::Search &getxattrPolicy_,
const Branches &branches_,
const char *fusepath_,
const char *attrname_,
const char *attrval_,
const size_t attrvalsize_,
const int flags_)
{
int rv;
PolicyRV prv;
StrVec basepaths;
rv = setxattrPolicy_(branches_,fusepath_,&basepaths);
if(rv == -1)
return -errno;
l::setxattr_loop(basepaths,fusepath_,attrname_,attrval_,attrvalsize_,flags_,&prv);
if(prv.error.empty())
return 0;
if(prv.success.empty())
return prv.error[0].rv;
basepaths.clear();
rv = getxattrPolicy_(branches_,fusepath_,&basepaths);
if(rv == -1)
return -errno;
return l::get_error(prv,basepaths[0]);
}
int
setxattr(const char *fusepath_,
const char *attrname_,
const char *attrval_,
size_t attrvalsize_,
int flags_)
{
Config::Read cfg;
if((cfg->security_capability == false) &&
l::is_attrname_security_capability(attrname_))
return -ENOATTR;
if(cfg->xattr.to_int())
return -cfg->xattr.to_int();
const fuse_context *fc = fuse_get_context();
const ugid::Set ugid(fc->uid,fc->gid);
return l::setxattr(cfg->func.setxattr.policy,
cfg->func.getxattr.policy,
cfg->branches,
fusepath_,
attrname_,
attrval_,
attrvalsize_,
flags_);
}
}
namespace FUSE::SETXATTR
{
int
setxattr_old(const char *fusepath_,
const char *attrname_,
const char *attrval_,
size_t attrvalsize_,
int flags_)
{
return l::setxattr(fusepath_,attrname_,attrval_,attrvalsize_,flags_);
}
int
setxattr(const char *fusepath_,
const char *attrname_,
@ -189,6 +30,8 @@ namespace FUSE::SETXATTR
int flags_)
{
State s;
const fuse_context *fc = fuse_get_context();
const ugid::Set ugid(fc->uid,fc->gid);
return s->setxattr(fusepath_,
attrname_,

2
src/fuse_setxattr_policy_factory.cpp

@ -34,6 +34,6 @@ namespace FUSE::SETXATTR::POLICY
if(str == "all")
return std::make_shared<ALL>(toml_);
throw std::runtime_error("");
throw std::runtime_error("setxattr");
}
}

2
src/fuse_symlink_policy_factory.cpp

@ -37,6 +37,6 @@ namespace FUSE::SYMLINK::POLICY
if(str == "epff")
return std::make_shared<EPFF>(toml_);
throw std::runtime_error("");
throw std::runtime_error("symlink");
}
}

2
src/fuse_truncate_policy_factory.cpp

@ -33,6 +33,6 @@ namespace FUSE::TRUNCATE::POLICY
if(str == "all")
return std::make_shared<ALL>(toml_);
throw std::runtime_error("");
throw std::runtime_error("truncate");
}
}

99
src/fuse_unlink.cpp

@ -1,5 +1,5 @@
/*
Copyright (c) 2019, 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
@ -14,111 +14,22 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.hpp"
#include "errno.hpp"
#include "fs_path.hpp"
#include "fs_unlink.hpp"
#include "ugid.hpp"
#include "state.hpp"
#include "ugid.hpp"
#include "fuse.h"
#include <string>
#include <vector>
#include <unistd.h>
using std::string;
using std::vector;
namespace error
{
static
inline
int
calc(const int rv_,
const int prev_,
const int cur_)
{
if(prev_ != 0)
return prev_;
if(rv_ == -1)
return cur_;
return 0;
}
}
namespace l
{
static
int
unlink_loop_core(const string &basepath_,
const char *fusepath_,
const int error_)
{
int rv;
string fullpath;
fullpath = fs::path::make(basepath_,fusepath_);
rv = fs::unlink(fullpath);
return error::calc(rv,error_,errno);
}
static
int
unlink_loop(const vector<string> &basepaths_,
const char *fusepath_)
{
int error;
error = 0;
for(size_t i = 0, ei = basepaths_.size(); i != ei; i++)
{
error = l::unlink_loop_core(basepaths_[i],fusepath_,error);
}
return -error;
}
static
int
unlink(const Policy::Action &unlinkPolicy_,
const Branches &branches_,
const char *fusepath_)
{
int rv;
vector<string> basepaths;
rv = unlinkPolicy_(branches_,fusepath_,&basepaths);
if(rv == -1)
return -errno;
return l::unlink_loop(basepaths,fusepath_);
}
}
namespace FUSE::UNLINK
{
int
unlink_old(const char *fusepath_)
{
Config::Read cfg;
const fuse_context *fc = fuse_get_context();
const ugid::Set ugid(fc->uid,fc->gid);
return l::unlink(cfg->func.unlink.policy,
cfg->branches,
fusepath_);
}
int
unlink(const char *fusepath_)
{
State s;
const fuse_context *fc = fuse_get_context();
const ugid::Set ugid(fc->uid,fc->gid);
return s->unlink(fusepath_);
return s->unlink(&fusepath_[1]);
}
}

2
src/fuse_unlink_policy_factory.cpp

@ -33,6 +33,6 @@ namespace FUSE::UNLINK::POLICY
if(str == "all")
return std::make_shared<ALL>(toml_);
throw std::runtime_error("");
throw std::runtime_error("unlink");
}
}

2
src/fuse_utimens_policy_factory.cpp

@ -33,6 +33,6 @@ namespace FUSE::UTIMENS::POLICY
if(str == "all")
return std::make_shared<ALL>(toml_);
throw std::runtime_error("");
throw std::runtime_error("utimens");
}
}

9
src/mergerfs.cpp

@ -16,7 +16,6 @@
#include "fs_path.hpp"
#include "mergerfs.hpp"
#include "option_parser.hpp"
#include "resources.hpp"
#include "strvec.hpp"
@ -156,8 +155,6 @@ namespace l
main(const int argc_,
char **argv_)
{
Config::Read cfg;
Config::ErrVec errs;
fuse_args args;
fuse_operations ops;
@ -167,12 +164,8 @@ namespace l
args.argv = argv_;
args.allocated = 0;
options::parse(&args,&errs);
if(errs.size())
std::cerr << errs << std::endl;
l::setup_resources();
l::get_fuse_operations(ops,cfg->nullrw);
l::get_fuse_operations(ops,false);
return fuse_main(args.argc,
args.argv,

418
src/option_parser.cpp

@ -1,418 +0,0 @@
/*
Copyright (c) 2016, 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 "config.hpp"
#include "ef.hpp"
#include "errno.hpp"
#include "fs_glob.hpp"
#include "fs_statvfs_cache.hpp"
#include "hw_cpu.hpp"
#include "num.hpp"
#include "policy.hpp"
#include "str.hpp"
#include "version.hpp"
#include "fuse.h"
#include <fstream>
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
#include <stddef.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
using std::string;
using std::vector;
enum
{
MERGERFS_OPT_HELP,
MERGERFS_OPT_VERSION
};
namespace l
{
static
int
calculate_thread_count(int threads_)
{
int tc;
if(threads_ > 0)
return threads_;
tc = hw::cpu::logical_core_count();
if(threads_ < 0)
tc /= -threads_;
if(tc == 0)
tc = 1;
return tc;
}
}
static
void
set_option(const std::string &option_,
fuse_args *args_)
{
fuse_opt_add_arg(args_,"-o");
fuse_opt_add_arg(args_,option_.c_str());
}
static
void
set_kv_option(const std::string &key_,
const std::string &val_,
fuse_args *args_)
{
std::string option;
option = key_ + '=' + val_;
set_option(option,args_);
}
static
void
set_threads(Config::Write &cfg_,
fuse_args *args_)
{
int threads;
threads = l::calculate_thread_count(cfg_->threads);
cfg_->threads = threads;
set_kv_option("threads",cfg_->threads.to_string(),args_);
}
static
void
set_fsname(Config::Write &cfg_,
fuse_args *args_)
{
if(cfg_->fsname->empty())
{
vector<string> paths;
cfg_->branches->to_paths(paths);
if(paths.size() > 0)
cfg_->fsname = str::remove_common_prefix_and_join(paths,':');
}
set_kv_option("fsname",cfg_->fsname,args_);
}
static
void
set_subtype(fuse_args *args_)
{
set_kv_option("subtype","mergerfs",args_);
}
static
void
set_default_options(fuse_args *args_)
{
set_option("default_permissions",args_);
}
static
int
parse_and_process_kv_arg(Config::Write &cfg_,
Config::ErrVec *errs_,
const std::string &key_,
const std::string &val_)
{
int rv;
std::string key(key_);
std::string val(val_);
rv = 0;
if(key == "config")
return ((cfg_->from_file(val_,errs_) < 0) ? 1 : 0);
ef(key == "attr_timeout")
key = "cache.attr";
ef(key == "entry_timeout")
key = "cache.entry";
ef(key == "negative_entry")
key = "cache.negative_entry";
ef(key == "direct_io" && val.empty())
val = "true";
ef(key == "kernel_cache" && val.empty())
val = "true";
ef(key == "auto_cache" && val.empty())
val = "true";
ef(key == "async_read" && val.empty())
val = "true";
ef(key == "sync_read" && val.empty())
{key = "async_read", val = "false";}
ef(key == "defaults")
return 0;
ef(key == "hard_remove")
return 0;
ef(key == "atomic_o_trunc")
return 0;
ef(key == "big_writes")
return 0;
ef(key == "cache.open")
return 0;
if(cfg_->has_key(key) == false)
return 1;
rv = cfg_->set_raw(key,val);
if(rv)
errs_->push_back({rv,key+'='+val});
return 0;
}
static
int
process_opt(Config::Write &cfg_,
Config::ErrVec *errs_,
const std::string &arg_)
{
std::string key;
std::string val;
str::splitkv(arg_,'=',&key,&val);
key = str::trim(key);
val = str::trim(val);
return parse_and_process_kv_arg(cfg_,errs_,key,val);
}
static
int
process_branches(Config::Write &cfg_,
Config::ErrVec *errs_,
const char *arg_)
{
int rv;
string arg;
arg = arg_;
rv = cfg_->set_raw("branches",arg);
if(rv)
errs_->push_back({rv,"branches="+arg});
return 0;
}
static
int
process_mount(Config::Write &cfg_,
Config::ErrVec *errs_,
const char *arg_)
{
int rv;
string arg;
arg = arg_;
rv = cfg_->set_raw("mount",arg);
if(rv)
errs_->push_back({rv,"mount="+arg});
return 1;
}
static
void
usage(void)
{
std::cout <<
"Usage: mergerfs [options] <branches> <destpath>\n"
"\n"
" -o [opt,...] mount options\n"
" -h --help print help\n"
" -v --version print version\n"
"\n"
"mergerfs options:\n"
" <branches> ':' delimited list of directories. Supports\n"
" shell globbing (must be escaped in shell)\n"
" -o config=FILE Read options from file in key=val format\n"
" -o func.FUNC=POLICY Set function FUNC to policy POLICY\n"
" -o category.CAT=POLICY Set functions in category CAT to POLICY\n"
" -o fsname=STR Sets the name of the filesystem.\n"
" -o cache.open=INT 'open' policy cache timeout in seconds.\n"
" default = 0 (disabled)\n"
" -o cache.statfs=INT 'statfs' cache timeout in seconds. Used by\n"
" policies. default = 0 (disabled)\n"
" -o cache.files=libfuse|off|partial|full|auto-full\n"
" * libfuse: Use direct_io, kernel_cache, auto_cache\n"
" values directly\n"
" * off: Disable page caching\n"
" * partial: Clear page cache on file open\n"
" * full: Keep cache on file open\n"
" * auto-full: Keep cache if mtime & size not changed\n"
" default = libfuse\n"
" -o cache.writeback=BOOL\n"
" Enable kernel writeback caching (if supported)\n"
" cache.files must be enabled as well.\n"
" default = false\n"
" -o cache.symlinks=BOOL\n"
" Enable kernel caching of symlinks (if supported)\n"
" default = false\n"
" -o cache.readdir=BOOL\n"
" Enable kernel caching readdir (if supported)\n"
" default = false\n"
" -o cache.attr=INT File attribute cache timeout in seconds.\n"
" default = 1\n"
" -o cache.entry=INT File name lookup cache timeout in seconds.\n"
" default = 1\n"
" -o cache.negative_entry=INT\n"
" Negative file name lookup cache timeout in\n"
" seconds. default = 0\n"
" -o use_ino Have mergerfs generate inode values rather than\n"
" autogenerated by libfuse. Suggested.\n"
" -o inodecalc=passthrough|path-hash|devino-hash|hybrid-hash\n"
" Selects the inode calculation algorithm.\n"
" default = hybrid-hash\n"
" -o minfreespace=INT Minimum free space needed for certain policies.\n"
" default = 4G\n"
" -o moveonenospc=BOOL Try to move file to another drive when ENOSPC\n"
" on write. default = false\n"
" -o dropcacheonclose=BOOL\n"
" When a file is closed suggest to OS it drop\n"
" the file's cache. This is useful when using\n"
" 'cache.files'. default = false\n"
" -o symlinkify=BOOL Read-only files, after a timeout, will be turned\n"
" into symlinks. Read docs for limitations and\n"
" possible issues. default = false\n"
" -o symlinkify_timeout=INT\n"
" Timeout in seconds before files turn to symlinks.\n"
" default = 3600\n"
" -o nullrw=BOOL Disables reads and writes. For benchmarking.\n"
" default = false\n"
" -o ignorepponrename=BOOL\n"
" Ignore path preserving when performing renames\n"
" and links. default = false\n"
" -o link_cow=BOOL Delink/clone file on open to simulate CoW.\n"
" default = false\n"
" -o nfsopenhack=off|git|all\n"
" A workaround for exporting mergerfs over NFS\n"
" where there are issues with creating files for\n"
" write while setting the mode to read-only.\n"
" default = off\n"
" -o security_capability=BOOL\n"
" When disabled return ENOATTR when the xattr\n"
" security.capability is queried. default = true\n"
" -o xattr=passthrough|noattr|nosys\n"
" Runtime control of xattrs. By default xattr\n"
" requests will pass through to the underlying\n"
" filesystems. notattr will short circuit as if\n"
" nothing exists. nosys will respond as if not\n"
" supported or disabled. default = passthrough\n"
" -o statfs=base|full When set to 'base' statfs will use all branches\n"
" when performing statfs calculations. 'full' will\n"
" only include branches on which that path is\n"
" available. default = base\n"
" -o statfs_ignore=none|ro|nc\n"
" 'ro' will cause statfs calculations to ignore\n"
" available space for branches mounted or tagged\n"
" as 'read only' or 'no create'. 'nc' will ignore\n"
" available space for branches tagged as\n"
" 'no create'. default = none\n"
" -o posix_acl=BOOL Enable POSIX ACL support. default = false\n"
" -o async_read=BOOL If disabled or unavailable the kernel will\n"
" ensure there is at most one pending read \n"
" request per file and will attempt to order\n"
" requests by offset. default = true\n"
<< std::endl;
}
static
int
option_processor(void *data_,
const char *arg_,
int key_,
fuse_args *outargs_)
{
Config::Write cfg;
Config::ErrVec *errs = (Config::ErrVec*)data_;
switch(key_)
{
case FUSE_OPT_KEY_OPT:
return process_opt(cfg,errs,arg_);
case FUSE_OPT_KEY_NONOPT:
if(cfg->branches->empty())
return process_branches(cfg,errs,arg_);
else
return process_mount(cfg,errs,arg_);
case MERGERFS_OPT_HELP:
usage();
exit(0);
case MERGERFS_OPT_VERSION:
std::cout << "mergerfs version: "
<< (MERGERFS_VERSION[0] ? MERGERFS_VERSION : "unknown")
<< std::endl;
exit(0);
default:
break;
}
return 0;
}
namespace options
{
void
parse(fuse_args *args_,
Config::ErrVec *errs_)
{
Config::Write cfg;
const struct fuse_opt opts[] =
{
FUSE_OPT_KEY("-h",MERGERFS_OPT_HELP),
FUSE_OPT_KEY("--help",MERGERFS_OPT_HELP),
FUSE_OPT_KEY("-v",MERGERFS_OPT_VERSION),
FUSE_OPT_KEY("-V",MERGERFS_OPT_VERSION),
FUSE_OPT_KEY("--version",MERGERFS_OPT_VERSION),
{NULL,-1U,0}
};
fuse_opt_parse(args_,
errs_,
opts,
::option_processor);
if(cfg->branches->empty())
errs_->push_back({0,"branches not set"});
if(cfg->mount->empty())
errs_->push_back({0,"mountpoint not set"});
set_default_options(args_);
set_fsname(cfg,args_);
set_subtype(args_);
set_threads(cfg,args_);
}
}

29
src/option_parser.hpp

@ -1,29 +0,0 @@
/*
Copyright (c) 2016, 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 "config.hpp"
#include "fuse.h"
namespace options
{
void
parse(fuse_args *args,
Config::ErrVec *errs);
}
Loading…
Cancel
Save