Browse Source

Misc changes (#1513)

* Start moving to string_view where possible
* Rework readdir object to use atomic load/store
pull/1514/head
trapexit 3 weeks ago
committed by GitHub
parent
commit
6ac7f389c5
No known key found for this signature in database GPG Key ID: B5690EEEBB952194
  1. 2
      src/branch.cpp
  2. 2
      src/branch.hpp
  3. 16
      src/branches.cpp
  4. 13
      src/branches.hpp
  5. 2
      src/category.cpp
  6. 2
      src/category.hpp
  7. 3
      src/config.hpp
  8. 2
      src/config_cachefiles.cpp
  9. 2
      src/config_flushonclose.cpp
  10. 2
      src/config_follow_symlinks.cpp
  11. 4
      src/config_gidcache.cpp
  12. 4
      src/config_gidcache.hpp
  13. 2
      src/config_inodecalc.cpp
  14. 2
      src/config_inodecalc.hpp
  15. 2
      src/config_link_exdev.cpp
  16. 2
      src/config_log_metrics.cpp
  17. 2
      src/config_log_metrics.hpp
  18. 2
      src/config_moveonenospc.cpp
  19. 2
      src/config_moveonenospc.hpp
  20. 2
      src/config_nfsopenhack.cpp
  21. 2
      src/config_pagesize.cpp
  22. 2
      src/config_pagesize.hpp
  23. 2
      src/config_passthrough.cpp
  24. 2
      src/config_pid.hpp
  25. 2
      src/config_rename_exdev.cpp
  26. 2
      src/config_set.cpp
  27. 2
      src/config_set.hpp
  28. 2
      src/config_statfs.cpp
  29. 2
      src/config_statfsignore.cpp
  30. 2
      src/config_xattr.cpp
  31. 2
      src/enum.hpp
  32. 152
      src/from_string.cpp
  33. 17
      src/from_string.hpp
  34. 2
      src/fs_inode.cpp
  35. 2
      src/fs_inode.hpp
  36. 6
      src/func.cpp
  37. 6
      src/func.hpp
  38. 2
      src/fuse_init.cpp
  39. 53
      src/fuse_readdir.cpp
  40. 23
      src/fuse_readdir.hpp
  41. 2
      src/fuse_readdir_base.hpp
  42. 67
      src/fuse_readdir_factory.cpp
  43. 3
      src/fuse_readdir_factory.hpp
  44. 12
      src/fuse_statx_supported.icpp
  45. 1
      src/mergerfs.cpp
  46. 2
      src/mergerfs_api.cpp
  47. 81
      src/num.cpp
  48. 8
      src/num.hpp
  49. 53
      src/option_parser.cpp
  50. 6
      src/policies.cpp
  51. 6
      src/policies.hpp
  52. 77
      src/resources.cpp
  53. 63
      src/state.cpp
  54. 24
      src/state.hpp
  55. 213
      src/str.cpp
  56. 25
      src/str.hpp
  57. 42
      src/symlinkify.hpp
  58. 47
      src/to_string.cpp
  59. 6
      src/to_string.hpp
  60. 3
      src/tofrom_string.hpp
  61. 2
      src/tofrom_wrapper.hpp

2
src/branch.cpp

@ -38,7 +38,7 @@ Branch::Branch(const u64 &default_minfreespace_)
} }
int int
Branch::from_string(const std::string &str_)
Branch::from_string(const std::string_view str_)
{ {
return -EINVAL; return -EINVAL;
} }

2
src/branch.hpp

@ -57,7 +57,7 @@ public:
bool ro_or_nc(void) const; bool ro_or_nc(void) const;
public: public:
int from_string(const std::string &str) final;
int from_string(const std::string_view str) final;
std::string to_string(void) const final; std::string to_string(void) const final;
public: public:

16
src/branches.cpp

@ -74,7 +74,7 @@ namespace l
{ {
static static
void void
split(const std::string &s_,
split(const std::string_view s_,
std::string *instr_, std::string *instr_,
std::string *values_) std::string *values_)
{ {
@ -222,7 +222,7 @@ namespace l
static static
int int
set(const std::string &str_,
set(const std::string_view str_,
Branches::Impl *branches_) Branches::Impl *branches_)
{ {
int rv; int rv;
@ -244,7 +244,7 @@ namespace l
static static
int int
add_begin(const std::string &str_,
add_begin(const std::string_view str_,
Branches::Impl *branches_) Branches::Impl *branches_)
{ {
int rv; int rv;
@ -268,7 +268,7 @@ namespace l
static static
int int
add_end(const std::string &str_,
add_end(const std::string_view str_,
Branches::Impl *branches_) Branches::Impl *branches_)
{ {
int rv; int rv;
@ -310,7 +310,7 @@ namespace l
static static
int int
erase_fnmatch(const std::string &str_,
erase_fnmatch(const std::string_view str_,
Branches::Impl *branches_) Branches::Impl *branches_)
{ {
StrVec patterns; StrVec patterns;
@ -336,7 +336,7 @@ namespace l
} }
int int
Branches::Impl::from_string(const std::string &s_)
Branches::Impl::from_string(const std::string_view s_)
{ {
std::string instr; std::string instr;
std::string values; std::string values;
@ -403,7 +403,7 @@ Branches::Impl::to_paths() const
} }
int int
Branches::from_string(const std::string &str_)
Branches::from_string(const std::string_view str_)
{ {
int rv; int rv;
Branches::Ptr impl; Branches::Ptr impl;
@ -462,7 +462,7 @@ SrcMounts::SrcMounts(Branches &b_)
} }
int int
SrcMounts::from_string(const std::string &s_)
SrcMounts::from_string(const std::string_view s_)
{ {
// return _branches.from_string(s_); // return _branches.from_string(s_);
return 0; return 0;

13
src/branches.hpp

@ -46,7 +46,7 @@ public:
Impl(const u64 &default_minfreespace); Impl(const u64 &default_minfreespace);
public: public:
int from_string(const std::string &str) final;
int from_string(const std::string_view str) final;
std::string to_string(void) const final; std::string to_string(void) const final;
public: public:
@ -73,13 +73,20 @@ public:
{} {}
public: public:
int from_string(const std::string &str) final;
int from_string(const std::string_view str) final;
std::string to_string(void) const final; std::string to_string(void) const final;
public: public:
operator Ptr() const { std::lock_guard<std::mutex> lg(_mutex); return _impl; } operator Ptr() const { std::lock_guard<std::mutex> lg(_mutex); return _impl; }
Ptr operator->() const { std::lock_guard<std::mutex> lg(_mutex); return _impl; } Ptr operator->() const { std::lock_guard<std::mutex> lg(_mutex); return _impl; }
public:
Impl::iterator begin() { return _impl->begin(); }
Impl::iterator end() { return _impl->end(); }
Impl::const_iterator begin() const { return _impl->begin(); }
Impl::const_iterator end() const { return _impl->end(); }
public: public:
void find_and_set_mode_ro(); void find_and_set_mode_ro();
}; };
@ -90,7 +97,7 @@ public:
SrcMounts(Branches &b); SrcMounts(Branches &b);
public: public:
int from_string(const std::string &str) final;
int from_string(const std::string_view str) final;
std::string to_string(void) const final; std::string to_string(void) const final;
private: private:

2
src/category.cpp

@ -23,7 +23,7 @@
#include <string> #include <string>
int int
Category::Base::from_string(const std::string &s_)
Category::Base::from_string(const std::string_view s_)
{ {
int rv; int rv;

2
src/category.hpp

@ -27,7 +27,7 @@ namespace Category
class Base : public ToFromString class Base : public ToFromString
{ {
public: public:
int from_string(const std::string &s) final;
int from_string(const std::string_view s) final;
std::string to_string() const final; std::string to_string() const final;
protected: protected:

3
src/config.hpp

@ -56,6 +56,7 @@
typedef ToFromWrapper<bool> ConfigBOOL; typedef ToFromWrapper<bool> ConfigBOOL;
typedef ToFromWrapper<uint64_t> ConfigUINT64; typedef ToFromWrapper<uint64_t> ConfigUINT64;
typedef ToFromWrapper<int64_t> ConfigS64;
typedef ToFromWrapper<int> ConfigINT; typedef ToFromWrapper<int> ConfigINT;
typedef ToFromWrapper<std::string> ConfigSTR; typedef ToFromWrapper<std::string> ConfigSTR;
typedef ToFromWrapper<std::filesystem::path> ConfigPath; typedef ToFromWrapper<std::filesystem::path> ConfigPath;
@ -161,7 +162,7 @@ public:
StatFS statfs; StatFS statfs;
StatFSIgnore statfs_ignore; StatFSIgnore statfs_ignore;
ConfigBOOL symlinkify; ConfigBOOL symlinkify;
ConfigUINT64 symlinkify_timeout;
ConfigS64 symlinkify_timeout;
ConfigINT fuse_read_thread_count; ConfigINT fuse_read_thread_count;
ConfigINT fuse_process_thread_count; ConfigINT fuse_process_thread_count;
ConfigINT fuse_process_thread_queue_depth; ConfigINT fuse_process_thread_queue_depth;

2
src/config_cachefiles.cpp

@ -45,7 +45,7 @@ CacheFiles::to_string() const
template<> template<>
int int
CacheFiles::from_string(const std::string &s_)
CacheFiles::from_string(const std::string_view s_)
{ {
if(s_ == "libfuse") if(s_ == "libfuse")
_data = CacheFiles::ENUM::LIBFUSE; _data = CacheFiles::ENUM::LIBFUSE;

2
src/config_flushonclose.cpp

@ -39,7 +39,7 @@ FlushOnClose::to_string() const
template<> template<>
int int
FlushOnClose::from_string(const std::string &s_)
FlushOnClose::from_string(const std::string_view s_)
{ {
if(s_ == "never") if(s_ == "never")
_data = FlushOnClose::ENUM::NEVER; _data = FlushOnClose::ENUM::NEVER;

2
src/config_follow_symlinks.cpp

@ -41,7 +41,7 @@ FollowSymlinks::to_string(void) const
template<> template<>
int int
FollowSymlinks::from_string(const std::string &s_)
FollowSymlinks::from_string(const std::string_view s_)
{ {
if(s_ == "never") if(s_ == "never")
_data = FollowSymlinks::ENUM::NEVER; _data = FollowSymlinks::ENUM::NEVER;

4
src/config_gidcache.cpp

@ -23,7 +23,7 @@ GIDCacheExpireTimeout::to_string(void) const
} }
int int
GIDCacheExpireTimeout::from_string(const std::string &s_)
GIDCacheExpireTimeout::from_string(const std::string_view s_)
{ {
int rv; int rv;
@ -53,7 +53,7 @@ GIDCacheRemoveTimeout::to_string(void) const
} }
int int
GIDCacheRemoveTimeout::from_string(const std::string &s_)
GIDCacheRemoveTimeout::from_string(const std::string_view s_)
{ {
int rv; int rv;

4
src/config_gidcache.hpp

@ -10,7 +10,7 @@ public:
public: public:
std::string to_string(void) const final; std::string to_string(void) const final;
int from_string(const std::string &) final;
int from_string(const std::string_view) final;
}; };
class GIDCacheRemoveTimeout : public ToFromString class GIDCacheRemoveTimeout : public ToFromString
@ -21,5 +21,5 @@ public:
public: public:
std::string to_string(void) const final; std::string to_string(void) const final;
int from_string(const std::string &) final;
int from_string(const std::string_view) final;
}; };

2
src/config_inodecalc.cpp

@ -32,7 +32,7 @@ InodeCalc::to_string(void) const
} }
int int
InodeCalc::from_string(const std::string &s_)
InodeCalc::from_string(const std::string_view s_)
{ {
return fs::inode::set_algo(s_); return fs::inode::set_algo(s_);
} }

2
src/config_inodecalc.hpp

@ -28,5 +28,5 @@ public:
public: public:
std::string to_string(void) const final; std::string to_string(void) const final;
int from_string(const std::string &) final;
int from_string(const std::string_view) final;
}; };

2
src/config_link_exdev.cpp

@ -41,7 +41,7 @@ LinkEXDEV::to_string(void) const
template<> template<>
int int
LinkEXDEV::from_string(const std::string &s_)
LinkEXDEV::from_string(const std::string_view s_)
{ {
if(s_ == "passthrough") if(s_ == "passthrough")
_data = LinkEXDEV::ENUM::PASSTHROUGH; _data = LinkEXDEV::ENUM::PASSTHROUGH;

2
src/config_log_metrics.cpp

@ -38,7 +38,7 @@ LogMetrics::to_string(void) const
} }
int int
LogMetrics::from_string(const std::string &s_)
LogMetrics::from_string(const std::string_view s_)
{ {
int rv; int rv;
bool val; bool val;

2
src/config_log_metrics.hpp

@ -27,5 +27,5 @@ public:
public: public:
std::string to_string(void) const final; std::string to_string(void) const final;
int from_string(const std::string &) final;
int from_string(const std::string_view) final;
}; };

2
src/config_moveonenospc.cpp

@ -23,7 +23,7 @@
int int
MoveOnENOSPC::from_string(const std::string &s_)
MoveOnENOSPC::from_string(const std::string_view s_)
{ {
int rv; int rv;
std::string s; std::string s;

2
src/config_moveonenospc.hpp

@ -35,7 +35,7 @@ public:
} }
public: public:
int from_string(const std::string &s) final;
int from_string(const std::string_view s) final;
std::string to_string() const final; std::string to_string() const final;
public: public:

2
src/config_nfsopenhack.cpp

@ -23,7 +23,7 @@
template<> template<>
int int
NFSOpenHack::from_string(const std::string &s_)
NFSOpenHack::from_string(const std::string_view s_)
{ {
if(s_ == "off") if(s_ == "off")
_data = NFSOpenHack::ENUM::OFF; _data = NFSOpenHack::ENUM::OFF;

2
src/config_pagesize.cpp

@ -44,7 +44,7 @@ ConfigPageSize::to_string(void) const
} }
int int
ConfigPageSize::from_string(const std::string &s_)
ConfigPageSize::from_string(const std::string_view s_)
{ {
uint64_t v; uint64_t v;
uint64_t pagesize; uint64_t pagesize;

2
src/config_pagesize.hpp

@ -33,7 +33,7 @@ public:
public: public:
std::string to_string(void) const final; std::string to_string(void) const final;
int from_string(const std::string &) final;
int from_string(const std::string_view) final;
public: public:
ConfigPageSize& ConfigPageSize&

2
src/config_passthrough.cpp

@ -41,7 +41,7 @@ Passthrough::to_string() const
template<> template<>
int int
Passthrough::from_string(const std::string &s_)
Passthrough::from_string(const std::string_view s_)
{ {
if(s_ == "off") if(s_ == "off")
_data = Passthrough::ENUM::OFF; _data = Passthrough::ENUM::OFF;

2
src/config_pid.hpp

@ -35,7 +35,7 @@ public:
} }
int int
from_string(const std::string &) final
from_string(const std::string_view) final
{ {
return -EROFS; return -EROFS;
} }

2
src/config_rename_exdev.cpp

@ -39,7 +39,7 @@ RenameEXDEV::to_string(void) const
template<> template<>
int int
RenameEXDEV::from_string(const std::string &s_)
RenameEXDEV::from_string(const std::string_view s_)
{ {
if(s_ == "passthrough") if(s_ == "passthrough")
_data = RenameEXDEV::ENUM::PASSTHROUGH; _data = RenameEXDEV::ENUM::PASSTHROUGH;

2
src/config_set.cpp

@ -33,7 +33,7 @@ ConfigSet::to_string(void) const
} }
int int
ConfigSet::from_string(const std::string &str_)
ConfigSet::from_string(const std::string_view str_)
{ {
this->clear(); this->clear();

2
src/config_set.hpp

@ -31,5 +31,5 @@ public:
public: public:
std::string to_string(void) const final; std::string to_string(void) const final;
int from_string(const std::string &) final;
int from_string(const std::string_view) final;
}; };

2
src/config_statfs.cpp

@ -38,7 +38,7 @@ StatFS::to_string() const
template<> template<>
int int
StatFS::from_string(const std::string &s_)
StatFS::from_string(const std::string_view s_)
{ {
if(s_ == "base") if(s_ == "base")
_data = StatFS::ENUM::BASE; _data = StatFS::ENUM::BASE;

2
src/config_statfsignore.cpp

@ -40,7 +40,7 @@ StatFSIgnore::to_string() const
template<> template<>
int int
StatFSIgnore::from_string(const std::string &s_)
StatFSIgnore::from_string(const std::string_view s_)
{ {
if(s_ == "none") if(s_ == "none")
_data = StatFSIgnore::ENUM::NONE; _data = StatFSIgnore::ENUM::NONE;

2
src/config_xattr.cpp

@ -40,7 +40,7 @@ XAttr::to_string() const
template<> template<>
int int
XAttr::from_string(const std::string &s_)
XAttr::from_string(const std::string_view s_)
{ {
if(s_ == "passthrough") if(s_ == "passthrough")
_data = XAttr::ENUM::PASSTHROUGH; _data = XAttr::ENUM::PASSTHROUGH;

2
src/enum.hpp

@ -68,7 +68,7 @@ public:
public: public:
std::string to_string() const final; std::string to_string() const final;
int from_string(const std::string &) final;
int from_string(const std::string_view) final;
public: public:
int to_int() const int to_int() const

152
src/from_string.cpp

@ -21,15 +21,15 @@
#include "ef.hpp" #include "ef.hpp"
#include "errno.hpp" #include "errno.hpp"
#include <charconv>
#include <stdlib.h> #include <stdlib.h>
namespace str
{
int
from(const std::string &value_,
int
str::from(const std::string_view value_,
bool *bool_) bool *bool_)
{
{
if((value_ == "true") || if((value_ == "true") ||
(value_ == "1") || (value_ == "1") ||
(value_ == "on") || (value_ == "on") ||
@ -44,96 +44,152 @@ namespace str
return -EINVAL; return -EINVAL;
return 0; return 0;
}
}
int
from(const std::string &value_,
int *int_)
{
int
str::from(const std::string_view val_,
int *rv_)
{
int tmp; int tmp;
char *endptr;
const int base = 10;
errno = 0;
tmp = ::strtol(value_.c_str(),&endptr,10);
if(errno != 0)
return -EINVAL;
if(endptr == value_.c_str())
auto [ptr,ec] = std::from_chars(val_.begin(),
val_.end(),
tmp,
base);
if(ec != std::errc{})
return -EINVAL; return -EINVAL;
*int_ = tmp;
*rv_ = tmp;
return 0; return 0;
}
}
int
from(const std::string &value_,
uint64_t *uint64_)
{
char *endptr;
uint64_t tmp;
int
str::from(const std::string_view val_,
int64_t *rv_)
{
int64_t tmp;
const int base = 10;
auto [ptr,ec] = std::from_chars(val_.begin(),
val_.end(),
tmp,
base);
tmp = ::strtoll(value_.c_str(),&endptr,10);
switch(*endptr)
if(ec != std::errc{})
return -EINVAL;
*rv_ = tmp;
if(ptr == val_.end())
return 0;
switch(*ptr)
{ {
case 'b': case 'b':
case 'B': case 'B':
tmp *= 1ULL;
*rv_ *= 1ULL;
break; break;
case 'k': case 'k':
case 'K': case 'K':
tmp *= 1024ULL;
*rv_ *= 1024ULL;
break; break;
case 'm': case 'm':
case 'M': case 'M':
tmp *= (1024ULL * 1024ULL);
*rv_ *= (1024ULL * 1024ULL);
break; break;
case 'g': case 'g':
case 'G': case 'G':
tmp *= (1024ULL * 1024ULL * 1024ULL);
*rv_ *= (1024ULL * 1024ULL * 1024ULL);
break; break;
case 't': case 't':
case 'T': case 'T':
tmp *= (1024ULL * 1024ULL * 1024ULL * 1024ULL);
break;
case '\0':
*rv_ *= (1024ULL * 1024ULL * 1024ULL * 1024ULL);
break; break;
default: default:
return -EINVAL; return -EINVAL;
} }
*uint64_ = tmp;
return 0;
}
int
str::from(const std::string_view val_,
uint64_t *rv_)
{
uint64_t tmp;
const int base = 10;
auto [ptr,ec] = std::from_chars(val_.begin(),
val_.end(),
tmp,
base);
if(ec != std::errc{})
return -EINVAL;
*rv_ = tmp;
if(ptr == val_.end())
return 0; return 0;
switch(*ptr)
{
case 'b':
case 'B':
*rv_ *= 1ULL;
break;
case 'k':
case 'K':
*rv_ *= 1024ULL;
break;
case 'm':
case 'M':
*rv_ *= (1024ULL * 1024ULL);
break;
case 'g':
case 'G':
*rv_ *= (1024ULL * 1024ULL * 1024ULL);
break;
case 't':
case 'T':
*rv_ *= (1024ULL * 1024ULL * 1024ULL * 1024ULL);
break;
default:
return -EINVAL;
} }
int
from(const std::string &value_,
return 0;
}
int
str::from(const std::string_view value_,
std::string *str_) std::string *str_)
{
{
*str_ = value_; *str_ = value_;
return 0; return 0;
}
}
int
from(const std::string &value_,
int
str::from(const std::string_view value_,
const std::string *key_) const std::string *key_)
{
{
return -EINVAL; return -EINVAL;
}
}
int
from(const std::string &value_,
fs::Path *path_)
{
int
str::from(const std::string_view value_,
std::filesystem::path *path_)
{
*path_ = value_; *path_ = value_;
return 0; return 0;
}
} }

17
src/from_string.hpp

@ -18,18 +18,19 @@
#pragma once #pragma once
#include "fs_path.hpp"
#include <cstdint> #include <cstdint>
#include <filesystem>
#include <string> #include <string>
#include <string_view>
namespace str namespace str
{ {
int from(const std::string &, bool *);
int from(const std::string &, int *);
int from(const std::string &, uint64_t *);
int from(const std::string &, std::string *);
int from(const std::string &, const std::string *);
int from(const std::string &, fs::Path *);
int from(const std::string_view, bool *);
int from(const std::string_view, int *);
int from(const std::string_view, uint64_t *);
int from(const std::string_view, int64_t *);
int from(const std::string_view, std::string *);
int from(const std::string_view, const std::string *);
int from(const std::string_view, std::filesystem::path *);
} }

2
src/fs_inode.cpp

@ -147,7 +147,7 @@ _hybrid_hash32(const std::string_view branch_path_,
} }
int int
fs::inode::set_algo(const std::string &algo_)
fs::inode::set_algo(const std::string_view algo_)
{ {
if(algo_ == "passthrough") if(algo_ == "passthrough")
g_func = ::_passthrough; g_func = ::_passthrough;

2
src/fs_inode.hpp

@ -31,7 +31,7 @@ namespace fs
{ {
namespace inode namespace inode
{ {
int set_algo(const std::string &s);
int set_algo(const std::string_view s);
std::string get_algo(void); std::string get_algo(void);
uint64_t calc(const std::string_view basepath, uint64_t calc(const std::string_view basepath,

6
src/func.cpp

@ -20,7 +20,7 @@
int int
Func::Base::Action::from_string(const std::string &policyname_)
Func::Base::Action::from_string(const std::string_view policyname_)
{ {
policy = Policies::Action::find(policyname_); policy = Policies::Action::find(policyname_);
if(!policy) if(!policy)
@ -36,7 +36,7 @@ Func::Base::Action::to_string(void) const
} }
int int
Func::Base::Create::from_string(const std::string &policyname_)
Func::Base::Create::from_string(const std::string_view policyname_)
{ {
policy = Policies::Create::find(policyname_); policy = Policies::Create::find(policyname_);
if(!policy) if(!policy)
@ -52,7 +52,7 @@ Func::Base::Create::to_string(void) const
} }
int int
Func::Base::Search::from_string(const std::string &policyname_)
Func::Base::Search::from_string(const std::string_view policyname_)
{ {
policy = Policies::Search::find(policyname_); policy = Policies::Search::find(policyname_);
if(!policy) if(!policy)

6
src/func.hpp

@ -37,7 +37,7 @@ namespace Func
{} {}
public: public:
int from_string(const std::string &s) final;
int from_string(const std::string_view s) final;
std::string to_string() const final; std::string to_string() const final;
public: public:
@ -52,7 +52,7 @@ namespace Func
{} {}
public: public:
int from_string(const std::string &s) final;
int from_string(const std::string_view s) final;
std::string to_string() const final; std::string to_string() const final;
public: public:
@ -67,7 +67,7 @@ namespace Func
{} {}
public: public:
int from_string(const std::string &s) final;
int from_string(const std::string_view s) final;
std::string to_string() const final; std::string to_string() const final;
public: public:

2
src/fuse_init.cpp

@ -192,8 +192,6 @@ FUSE::init(fuse_conn_info *conn_)
procfs::init(); procfs::init();
ugid::init(); ugid::init();
cfg->readdir.initialize();
::_want_if_capable(conn_,FUSE_CAP_ASYNC_DIO); ::_want_if_capable(conn_,FUSE_CAP_ASYNC_DIO);
::_want_if_capable(conn_,FUSE_CAP_ASYNC_READ,&cfg->async_read); ::_want_if_capable(conn_,FUSE_CAP_ASYNC_READ,&cfg->async_read);
::_want_if_capable(conn_,FUSE_CAP_ATOMIC_O_TRUNC); ::_want_if_capable(conn_,FUSE_CAP_ATOMIC_O_TRUNC);

53
src/fuse_readdir.cpp

@ -44,56 +44,36 @@ FUSE::readdir(const fuse_file_info_t *ffi_,
return cfg->readdir(ffi_,buf_); return cfg->readdir(ffi_,buf_);
} }
FUSE::ReadDir::ReadDir(std::string const s_)
: _initialized(false)
FUSE::ReadDir::ReadDir(const std::string_view s_)
: _str(new std::string())
{ {
from_string(s_); from_string(s_);
if(_initialized)
assert(_readdir);
} }
std::string std::string
FUSE::ReadDir::to_string() const FUSE::ReadDir::to_string() const
{ {
std::lock_guard<std::mutex> lg(_mutex);
std::shared_ptr<std::string> str;
return _type;
}
str = std::atomic_load(&_str);
void
FUSE::ReadDir::initialize()
{
_initialized = true;
from_string(_type);
return (*str);
} }
int int
FUSE::ReadDir::from_string(std::string const &str_)
FUSE::ReadDir::from_string(const std::string_view str_)
{ {
if(_initialized)
{
std::shared_ptr<FUSE::ReadDirBase> tmp;
std::shared_ptr<std::string> tmp_str;
std::shared_ptr<FUSE::ReadDirBase> tmp_readdir;
tmp = FUSE::ReadDirFactory::make(str_);
if(!tmp)
tmp_readdir = FUSE::ReadDirFactory::make(str_);
if(!tmp_readdir)
return -EINVAL; return -EINVAL;
{
std::lock_guard<std::mutex> lg(_mutex);
_type = str_;
std::swap(_readdir,tmp);
}
}
else
{
std::lock_guard<std::mutex> lg(_mutex);
if(!FUSE::ReadDirFactory::valid(str_))
return -EINVAL;
tmp_str = std::make_shared<std::string>(str_);
_type = str_;
}
std::atomic_store(&_str,tmp_str);
std::atomic_store(&_impl,tmp_readdir);
return 0; return 0;
} }
@ -113,7 +93,7 @@ _handle_ENOENT(const fuse_file_info_t *ffi_,
de.d_ino = 0; de.d_ino = 0;
de.d_off = 0; de.d_off = 0;
de.d_type = DT_REG;
de.d_type = DT_UNKNOWN;
strcpy(de.d_name,"error: no valid mergerfs branch found, check config"); strcpy(de.d_name,"error: no valid mergerfs branch found, check config");
de.d_reclen = sizeof(de); de.d_reclen = sizeof(de);
@ -134,10 +114,7 @@ FUSE::ReadDir::operator()(const fuse_file_info_t *ffi_,
int rv; int rv;
std::shared_ptr<FUSE::ReadDirBase> readdir; std::shared_ptr<FUSE::ReadDirBase> readdir;
{
std::lock_guard<std::mutex> lg(_mutex);
readdir = _readdir;
}
readdir = std::atomic_load(&_impl);
rv = (*readdir)(ffi_,buf_); rv = (*readdir)(ffi_,buf_);
if(rv == -ENOENT) if(rv == -ENOENT)

23
src/fuse_readdir.hpp

@ -25,37 +25,30 @@
#include <assert.h> #include <assert.h>
// The initialization behavior is not pretty but for the moment
// needed due to the daemonizing function of the libfuse library when
// not using foreground mode. The threads need to be created after the
// fork, not before.
namespace FUSE namespace FUSE
{ {
int readdir(fuse_file_info_t const *ffi, int readdir(fuse_file_info_t const *ffi,
fuse_dirents_t *buf); fuse_dirents_t *buf);
}
namespace FUSE
{
class ReadDir : public ToFromString class ReadDir : public ToFromString
{ {
public: public:
ReadDir(std::string const s_);
ReadDir(const std::string_view s_);
public: public:
std::string to_string() const; std::string to_string() const;
int from_string(const std::string &);
int from_string(const std::string_view);
public: public:
int operator()(fuse_file_info_t const *ffi, int operator()(fuse_file_info_t const *ffi,
fuse_dirents_t *buf); fuse_dirents_t *buf);
public:
void initialize();
private:
mutable std::mutex _mutex;
private: private:
bool _initialized;
std::string _type;
std::shared_ptr<FUSE::ReadDirBase> _readdir;
std::shared_ptr<std::string> _str;
std::shared_ptr<FUSE::ReadDirBase> _impl;
}; };
} }

2
src/fuse_readdir_base.hpp

@ -18,6 +18,8 @@
#include "fuse.h" #include "fuse.h"
#include <string_view>
namespace FUSE namespace FUSE
{ {

67
src/fuse_readdir_factory.cpp

@ -22,31 +22,46 @@
#include "fuse_readdir_cosr.hpp" #include "fuse_readdir_cosr.hpp"
#include "fuse_readdir_seq.hpp" #include "fuse_readdir_seq.hpp"
#include <array>
#include <cassert> #include <cassert>
#include <cmath> #include <cmath>
#include <cstdio> #include <cstdio>
#include <cstdlib> #include <cstdlib>
#include <set>
#include <regex>
// Regex:
// ^([a-z]{1,15}) -> required type
// (?::(\d+))? -> optional colon + concurrency
// (?::(\d+))? -> optional colon + max_queue_depth
// $ -> end of string
static static
void void
_read_cfg(std::string const str_,
_read_cfg(const std::string_view str_,
std::string &type_, std::string &type_,
unsigned &concurrency_,
unsigned &max_queue_depth_)
int &concurrency_,
int &max_queue_depth_)
{ {
char type[16];
std::string type;
int concurrency; int concurrency;
int max_queue_depth; int max_queue_depth;
bool matched;
std::cmatch match;
std::regex re(R"(^([a-z]{1,15})(?::(\d+))?(?::(\d+))?$)");
concurrency = 0; concurrency = 0;
max_queue_depth = 0; max_queue_depth = 0;
std::sscanf(str_.c_str(),
"%15[a-z]:%d:%d",
type,
&concurrency,
&max_queue_depth);
matched = std::regex_match(str_.begin(),
str_.end(),
match,
re);
if(matched)
{
type = match[1];
if(match[2].matched)
concurrency = std::stoi(match[2]);
if(match[3].matched)
max_queue_depth = std::stoi(match[3]);
}
if(concurrency == 0) if(concurrency == 0)
{ {
@ -73,37 +88,13 @@ _read_cfg(std::string const str_,
} }
bool
FUSE::ReadDirFactory::valid(const std::string str_)
{
unsigned concurrency;
unsigned max_queue_depth;
std::string type;
static const std::set<std::string> types =
{
"seq", "cosr", "cor"
};
::_read_cfg(str_,type,concurrency,max_queue_depth);
if(types.find(type) == types.end())
return false;
if(concurrency <= 0)
return false;
return true;
}
std::shared_ptr<FUSE::ReadDirBase> std::shared_ptr<FUSE::ReadDirBase>
FUSE::ReadDirFactory::make(std::string const str_)
FUSE::ReadDirFactory::make(const std::string_view str_)
{ {
unsigned concurrency;
unsigned max_queue_depth;
int concurrency;
int max_queue_depth;
std::string type; std::string type;
if(!valid(str_))
return {};
::_read_cfg(str_,type,concurrency,max_queue_depth); ::_read_cfg(str_,type,concurrency,max_queue_depth);
if(type == "seq") if(type == "seq")

3
src/fuse_readdir_factory.hpp

@ -29,7 +29,6 @@ namespace FUSE
class ReadDirFactory class ReadDirFactory
{ {
public: public:
static bool valid(std::string str);
static std::shared_ptr<ReadDirBase> make(std::string const str);
static std::shared_ptr<ReadDirBase> make(const std::string_view str);
}; };
} }

12
src/fuse_statx_supported.icpp

@ -210,7 +210,11 @@ FUSE::statx(const char *fusepath_,
if(Config::is_ctrl_file(fusepath_)) if(Config::is_ctrl_file(fusepath_))
return ::_statx_controlfile(st_); return ::_statx_controlfile(st_);
return ::_statx(fusepath_,flags_|AT_STATX_DONT_SYNC,mask_,st_,timeout_);
return ::_statx(fusepath_,
flags_|AT_STATX_DONT_SYNC,
mask_,
st_,
timeout_);
} }
int int
@ -222,5 +226,9 @@ FUSE::statx_fh(const uint64_t fh_,
{ {
FileInfo *fi = reinterpret_cast<FileInfo*>(fh_); FileInfo *fi = reinterpret_cast<FileInfo*>(fh_);
return ::_statx(fi->fusepath.c_str(),flags_,mask_,st_,timeout_);
return ::_statx(fi->fusepath.c_str(),
flags_|AT_STATX_DONT_SYNC,
mask_,
st_,
timeout_);
} }

1
src/mergerfs.cpp

@ -181,6 +181,7 @@ namespace l
orig = oom::get_oom_score_adj(); orig = oom::get_oom_score_adj();
rv = oom::set_oom_score_adj(score); rv = oom::set_oom_score_adj(score);
(void)rv;
SysLog::info("set oom_score_adj to {}, originally {}", SysLog::info("set oom_score_adj to {}, originally {}",
score, score,
orig); orig);

2
src/mergerfs_api.cpp

@ -44,7 +44,7 @@ mergerfs::api::allpaths(const std::string &input_path_,
if(rv < 0) if(rv < 0)
return rv; return rv;
str::split_on_null(val.data(),val.size(),&output_paths_);
str::split_on_null(val,&output_paths_);
return 0; return 0;
} }

81
src/num.cpp

@ -24,7 +24,7 @@
#include <time.h> #include <time.h>
#include <cstdint> #include <cstdint>
#include <string>
#define KB (1024ULL) #define KB (1024ULL)
#define MB (KB * 1024ULL) #define MB (KB * 1024ULL)
@ -33,85 +33,6 @@
namespace num namespace num
{
int
to_uint64_t(const std::string &str,
uint64_t &value)
{
char *endptr;
uint64_t tmp;
tmp = strtoll(str.c_str(),&endptr,10);
switch(*endptr)
{
case 'k':
case 'K':
tmp *= 1024;
break;
case 'm':
case 'M':
tmp *= (1024 * 1024);
break;
case 'g':
case 'G':
tmp *= (1024 * 1024 * 1024);
break;
case 't':
case 'T':
tmp *= (1024ULL * 1024 * 1024 * 1024);
break;
case '\0':
break;
default:
return -1;
}
value = tmp;
return 0;
}
int
to_double(const std::string &str_,
double *d_)
{
double tmp;
char *endptr;
tmp = strtod(str_.c_str(),&endptr);
if(*endptr != '\0')
return -1;
*d_ = tmp;
return 0;
}
int
to_time_t(const std::string &str,
time_t &value)
{
time_t tmp;
char *endptr;
tmp = strtoll(str.c_str(),&endptr,10);
if(*endptr != '\0')
return -1;
if(tmp < 0)
return -1;
value = tmp;
return 0;
}
}
namespace num
{ {
std::string std::string
humanize(const uint64_t bytes_) humanize(const uint64_t bytes_)

8
src/num.hpp

@ -19,14 +19,6 @@
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <time.h>
namespace num
{
int to_uint64_t(const std::string &str, uint64_t *value);
int to_double(const std::string &str, double *value);
int to_time_t(const std::string &str, time_t *value);
}
namespace num namespace num
{ {

53
src/option_parser.cpp

@ -204,7 +204,7 @@ _parse_and_process_kv_arg(Config::Write &cfg_,
static static
int int
process_opt(Config::Write &cfg_,
_process_opt(Config::Write &cfg_,
Config::ErrVec *errs_, Config::ErrVec *errs_,
const std::string &arg_) const std::string &arg_)
{ {
@ -220,7 +220,7 @@ process_opt(Config::Write &cfg_,
static static
int int
process_branches(Config::Write &cfg_,
_process_branches(Config::Write &cfg_,
Config::ErrVec *errs_, Config::ErrVec *errs_,
const char *arg_) const char *arg_)
{ {
@ -237,7 +237,7 @@ process_branches(Config::Write &cfg_,
static static
int int
process_mount(Config::Write &cfg_,
_process_mount(Config::Write &cfg_,
Config::ErrVec *errs_, Config::ErrVec *errs_,
const char *arg_) const char *arg_)
{ {
@ -290,7 +290,7 @@ _usage(void)
static static
int int
option_processor(void *data_,
_option_processor(void *data_,
const char *arg_, const char *arg_,
int key_, int key_,
fuse_args *outargs_) fuse_args *outargs_)
@ -301,13 +301,13 @@ option_processor(void *data_,
switch(key_) switch(key_)
{ {
case FUSE_OPT_KEY_OPT: case FUSE_OPT_KEY_OPT:
return process_opt(cfg,errs,arg_);
return ::_process_opt(cfg,errs,arg_);
case FUSE_OPT_KEY_NONOPT: case FUSE_OPT_KEY_NONOPT:
if(cfg->branches->empty()) if(cfg->branches->empty())
return process_branches(cfg,errs,arg_);
return ::_process_branches(cfg,errs,arg_);
else else
return process_mount(cfg,errs,arg_);
return ::_process_mount(cfg,errs,arg_);
case MERGERFS_OPT_HELP: case MERGERFS_OPT_HELP:
::_usage(); ::_usage();
@ -367,6 +367,41 @@ _check_for_mount_loop(Config::Write &cfg_,
} }
} }
static
void
_print_warnings(Config::Write &cfg_)
{
if(cfg_->passthrough != Passthrough::ENUM::OFF)
{
if(cfg_->cache_files == CacheFiles::ENUM::OFF)
{
SysLog::warning("'cache.files' can not be 'off' when using 'passthrough'."
" Setting 'cache.files=auto-full'");
cfg_->cache_files = CacheFiles::ENUM::AUTO_FULL;
}
if(cfg_->writeback_cache == true)
{
SysLog::warning("'cache.writeback' can not be enabled when using 'passthrough'."
" Setting 'cache.writeback=false'");
cfg_->writeback_cache = false;
}
if(cfg_->moveonenospc.enabled == true)
{
SysLog::warning("`moveonenospc` will not function when `passthrough` is enabled");
}
}
}
static
void
_cleanup_options(Config::Write &cfg_)
{
if(!cfg_->symlinkify)
cfg_->symlinkify_timeout = -1;
}
namespace options namespace options
{ {
void void
@ -387,7 +422,7 @@ namespace options
fuse_opt_parse(args_, fuse_opt_parse(args_,
errs_, errs_,
opts, opts,
::option_processor);
::_option_processor);
if(cfg->branches->empty()) if(cfg->branches->empty())
errs_->push_back({0,"branches not set"}); errs_->push_back({0,"branches not set"});
@ -400,6 +435,8 @@ namespace options
::_set_fsname(cfg,args_); ::_set_fsname(cfg,args_);
::_set_subtype(args_); ::_set_subtype(args_);
::_set_fuse_threads(cfg); ::_set_fuse_threads(cfg);
::_print_warnings(cfg);
::_cleanup_options(cfg);
cfg->finish_initializing(); cfg->finish_initializing();
} }

6
src/policies.cpp

@ -45,7 +45,7 @@
FUNC(rand) FUNC(rand)
Policy::ActionImpl* Policy::ActionImpl*
Policies::Action::find(const std::string &name_)
Policies::Action::find(const std::string_view name_)
{ {
IFERT(IFERTA); IFERT(IFERTA);
@ -53,7 +53,7 @@ Policies::Action::find(const std::string &name_)
} }
Policy::CreateImpl* Policy::CreateImpl*
Policies::Create::find(const std::string &name_)
Policies::Create::find(const std::string_view name_)
{ {
IFERT(IFERTC); IFERT(IFERTC);
@ -61,7 +61,7 @@ Policies::Create::find(const std::string &name_)
} }
Policy::SearchImpl* Policy::SearchImpl*
Policies::Search::find(const std::string &name_)
Policies::Search::find(const std::string_view name_)
{ {
IFERT(IFERTS); IFERT(IFERTS);

6
src/policies.hpp

@ -43,7 +43,7 @@ struct Policies
{ {
struct Action struct Action
{ {
static Policy::ActionImpl *find(const std::string &name);
static Policy::ActionImpl *find(const std::string_view name);
static Policy::All::Action all; static Policy::All::Action all;
static Policy::EPAll::Action epall; static Policy::EPAll::Action epall;
@ -69,7 +69,7 @@ struct Policies
struct Create struct Create
{ {
static Policy::CreateImpl *find(const std::string &name);
static Policy::CreateImpl *find(const std::string_view name);
static Policy::All::Create all; static Policy::All::Create all;
static Policy::EPAll::Create epall; static Policy::EPAll::Create epall;
@ -95,7 +95,7 @@ struct Policies
struct Search struct Search
{ {
static Policy::SearchImpl *find(const std::string &name);
static Policy::SearchImpl *find(const std::string_view name);
static Policy::All::Search all; static Policy::All::Search all;
static Policy::EPAll::Search epall; static Policy::EPAll::Search epall;

77
src/resources.cpp

@ -14,6 +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 "resources.hpp"
#include "fs_opendir.hpp"
#include "fs_closedir.hpp"
#include "fs_readdir.hpp"
#include "errno.hpp" #include "errno.hpp"
#include <unistd.h> #include <unistd.h>
@ -22,18 +27,17 @@
#include <sys/time.h> #include <sys/time.h>
#include <sys/resource.h> #include <sys/resource.h>
namespace resources
int
resources::reset_umask(void)
{ {
int
reset_umask(void)
{
umask(0); umask(0);
return 0; return 0;
}
}
int
maxout_rlimit(const int resource)
{
int
resources::maxout_rlimit(const int resource)
{
int rv; int rv;
struct rlimit rlim; struct rlimit rlim;
@ -57,28 +61,55 @@ namespace resources
} }
return rv; return rv;
}
}
int
maxout_rlimit_nofile(void)
{
int
resources::maxout_rlimit_nofile(void)
{
return maxout_rlimit(RLIMIT_NOFILE); return maxout_rlimit(RLIMIT_NOFILE);
}
}
int
maxout_rlimit_fsize(void)
{
int
resources::maxout_rlimit_fsize(void)
{
return maxout_rlimit(RLIMIT_FSIZE); return maxout_rlimit(RLIMIT_FSIZE);
}
}
int
resources::setpriority(const int prio_)
{
DIR *dir;
struct dirent *e;
::setpriority(PRIO_PROCESS,0,prio_);
int
setpriority(const int prio)
dir = fs::opendir("/proc/self/task");
if(dir == NULL)
return -errno;
while(true)
{ {
int rv;
const int SELF = 0;
pid_t tid;
rv = ::setpriority(PRIO_PROCESS,SELF,prio);
e = fs::readdir(dir);
if(e == NULL)
break;
if(e->d_name[0] == '.')
continue;
return ((rv == -1) ? -errno : rv);
try
{
tid = std::stoi(e->d_name);
} }
catch(...)
{
continue;
}
::setpriority(PRIO_PROCESS,tid,prio_);
}
fs::closedir(dir);
return 0;
} }

63
src/state.cpp

@ -1,3 +1,66 @@
#include "state.hpp" #include "state.hpp"
#include "fmt/core.h"
#include "errno.hpp"
State state; State state;
// static
// void
// _register_getattr(State *state_)
// {
// State::GetSet x;
// x.get = [state_]() -> std::string
// {
// return state_->getattr.to_string();
// };
// x.set = [state_](const std::string_view s_) -> int
// {
// return state_->getattr.from_string(s_);
// };
// state_->set_getset("user.mergerfs.func.getattr",x);
// }
State::State()
{
// _register_getattr(this);
}
void
State::set_getset(const std::string &name_,
const State::GetSet &gs_)
{
_getset[name_] = gs_;
}
int
State::get(const std::string &key_,
std::string &val_)
{
std::map<std::string,State::GetSet>::iterator i;
i = _getset.find(key_);
if((i == _getset.end()) || (!i->second.get))
return -ENOATTR;
val_ = i->second.get();
return 0;
}
int
State::set(const std::string &key_,
const std::string_view val_)
{
std::map<std::string,State::GetSet>::iterator i;
i = _getset.find(key_);
if((i == _getset.end()) || (!i->second.set))
return -ENOATTR;
return i->second.set(val_);
}

24
src/state.hpp

@ -4,11 +4,18 @@
#include "fileinfo.hpp" #include "fileinfo.hpp"
#include <functional>
#include <map>
#include <string>
constexpr int INVALID_BACKING_ID = -1; constexpr int INVALID_BACKING_ID = -1;
class State class State
{ {
public:
State();
public: public:
struct OpenFile struct OpenFile
{ {
@ -24,10 +31,27 @@ public:
FileInfo *fi; FileInfo *fi;
}; };
public:
struct GetSet
{
std::function<std::string()> get;
std::function<int(const std::string_view)> set;
};
void set_getset(const std::string &name,
const State::GetSet &gs);
int get(const std::string &key,
std::string &val);
int set(const std::string &key,
const std::string_view val);
public: public:
using OpenFileMap = boost::concurrent_flat_map<u64,OpenFile>; using OpenFileMap = boost::concurrent_flat_map<u64,OpenFile>;
private:
std::map<std::string,GetSet> _getset;
public: public:
OpenFileMap open_files; OpenFileMap open_files;
}; };

213
src/str.cpp

@ -28,131 +28,111 @@
using std::istringstream; using std::istringstream;
using std::set; using std::set;
using std::string; using std::string;
using std::string_view;
using std::vector; using std::vector;
namespace str
{
void
split(const char *str_,
void
str::split(const string_view str_,
const char delimiter_, const char delimiter_,
vector<string> *result_) vector<string> *result_)
{
string part;
istringstream ss(str_);
while(std::getline(ss,part,delimiter_))
result_->push_back(part);
}
{
size_t pos;
size_t start;
void
split(const char *str_,
const char delimiter_,
set<string> *result_)
start = 0;
pos = str_.find(delimiter_,start);
while(pos != std::string_view::npos)
{ {
string part;
istringstream ss(str_);
while(std::getline(ss,part,delimiter_))
result_->insert(part);
result_->push_back(std::string{str_.substr(start,pos)});
start = (pos + 1);
pos = str_.find(delimiter_,start);
} }
void
split(const string &str_,
const char delimiter_,
vector<string> *result_)
{
return str::split(str_.c_str(),delimiter_,result_);
}
result_->push_back(std::string{str_.substr(start)});
}
void
split(const string &str_,
void
str::split(const string_view str_,
const char delimiter_, const char delimiter_,
set<string> *result_) set<string> *result_)
{
size_t pos;
size_t start;
start = 0;
pos = str_.find(delimiter_,start);
while(pos != std::string_view::npos)
{ {
return str::split(str_.c_str(),delimiter_,result_);
result_->insert(std::string{str_.substr(start,pos)});
start = (pos + 1);
pos = str_.find(delimiter_,start);
} }
void
split_on_null(const char *str_,
const size_t len_,
result_->insert(std::string{str_.substr(start)});
}
void
str::split_on_null(const std::string_view str_,
std::vector<std::string> *result_) std::vector<std::string> *result_)
{
{
const char *start; const char *start;
const char *end; const char *end;
start = str_;
end = start + len_;
start = str_.begin();
end = str_.end();
while(start < end) while(start < end)
{ {
result_->emplace_back(start); result_->emplace_back(start);
start += (result_->back().size() + 1); start += (result_->back().size() + 1);
} }
}
}
void
rsplit1(const string &str_,
void
str::rsplit1(const string_view &str_,
const char delimiter_, const char delimiter_,
vector<string> *result_) vector<string> *result_)
{
{
std::size_t off; std::size_t off;
off = str_.rfind('='); off = str_.rfind('=');
if(off == std::string::npos) if(off == std::string::npos)
{ {
result_->push_back(str_);
result_->push_back(std::string{str_});
} }
else else
{ {
result_->push_back(str_.substr(0,off));
result_->push_back(str_.substr(off+1));
}
result_->push_back(std::string{str_.substr(0,off)});
result_->push_back(std::string{str_.substr(off+1)});
} }
}
void
splitkv(const std::string_view &str_,
void
str::splitkv(const std::string_view str_,
const char delimiter_, const char delimiter_,
std::string &key_,
std::string_view &val_)
{
std::string *key_,
std::string *val_)
{
size_t pos; size_t pos;
pos = str_.find(delimiter_); pos = str_.find(delimiter_);
if(pos != std::string_view::npos) if(pos != std::string_view::npos)
{ {
key_ = str_.substr(0,pos);
val_ = str_.substr(pos + 1,
str_.size() - pos + 1);
*key_ = str_.substr(0, pos);
*val_ = str_.substr(pos + 1);
} }
else else
{ {
key_ = str_;
val_ = std::string_view{};
}
}
void
splitkv(const string &str_,
const char delimiter_,
string *key_,
string *val_)
{
istringstream iss;
std::string key;
std::string val;
iss.str(str_);
std::getline(iss,key,delimiter_);
std::getline(iss,val,'\0');
*key_ = key;
*val_ = val;
*key_ = str_;
*val_ = "";
} }
}
string
join(const vector<string> &vec_,
string
str::join(const vector<string> &vec_,
const size_t substridx_, const size_t substridx_,
const char sep_) const char sep_)
{
{
if(vec_.empty()) if(vec_.empty())
return string(); return string();
@ -161,19 +141,19 @@ namespace str
rv += sep_ + vec_[i].substr(substridx_); rv += sep_ + vec_[i].substr(substridx_);
return rv; return rv;
}
}
string
join(const vector<string> &vec_,
string
str::join(const vector<string> &vec_,
const char sep_) const char sep_)
{
{
return str::join(vec_,0,sep_); return str::join(vec_,0,sep_);
}
}
string
join(const set<string> &set_,
string
str::join(const set<string> &set_,
const char sep_) const char sep_)
{
{
string rv; string rv;
for(auto const &s : set_) for(auto const &s : set_)
@ -181,11 +161,11 @@ namespace str
rv.pop_back(); rv.pop_back();
return rv; return rv;
}
}
size_t
longest_common_prefix_index(const vector<string> &vec_)
{
size_t
str::longest_common_prefix_index(const vector<string> &vec_)
{
if(vec_.empty()) if(vec_.empty())
return string::npos; return string::npos;
@ -202,11 +182,11 @@ namespace str
} }
return string::npos; return string::npos;
}
}
string
longest_common_prefix(const vector<string> &vec_)
{
string
str::longest_common_prefix(const vector<string> &vec_)
{
size_t idx; size_t idx;
idx = longest_common_prefix_index(vec_); idx = longest_common_prefix_index(vec_);
@ -214,12 +194,12 @@ namespace str
return vec_[0].substr(0,idx); return vec_[0].substr(0,idx);
return string(); return string();
}
}
string
remove_common_prefix_and_join(const vector<string> &vec_,
string
str::remove_common_prefix_and_join(const vector<string> &vec_,
const char sep_) const char sep_)
{
{
size_t idx; size_t idx;
idx = str::longest_common_prefix_index(vec_); idx = str::longest_common_prefix_index(vec_);
@ -227,12 +207,12 @@ namespace str
idx = 0; idx = 0;
return str::join(vec_,idx,sep_); return str::join(vec_,idx,sep_);
}
}
void
erase_fnmatches(const vector<string> &patterns_,
void
str::erase_fnmatches(const vector<string> &patterns_,
vector<string> &strs_) vector<string> &strs_)
{
{
vector<string>::iterator si; vector<string>::iterator si;
vector<string>::const_iterator pi; vector<string>::const_iterator pi;
@ -253,39 +233,39 @@ namespace str
else else
++si; ++si;
} }
}
}
bool
isprefix(const string &s0_,
bool
str::isprefix(const string &s0_,
const string &s1_) const string &s1_)
{
{
return ((s0_.size() >= s1_.size()) && return ((s0_.size() >= s1_.size()) &&
(s0_.compare(0,s1_.size(),s1_) == 0)); (s0_.compare(0,s1_.size(),s1_) == 0));
}
}
bool
startswith(const string &str_,
bool
str::startswith(const string &str_,
const string &prefix_) const string &prefix_)
{
{
return ((str_.size() >= prefix_.size()) && return ((str_.size() >= prefix_.size()) &&
(str_.compare(0,prefix_.size(),prefix_) == 0)); (str_.compare(0,prefix_.size(),prefix_) == 0));
}
}
bool
endswith(const string &str_,
bool
str::endswith(const string &str_,
const string &suffix_) const string &suffix_)
{
{
if(suffix_.size() > str_.size()) if(suffix_.size() > str_.size())
return false; return false;
return std::equal(suffix_.rbegin(), return std::equal(suffix_.rbegin(),
suffix_.rend(), suffix_.rend(),
str_.rbegin()); str_.rbegin());
}
}
std::string
trim(const std::string &str_)
{
std::string
str::trim(const std::string &str_)
{
std::string rv; std::string rv;
rv = str_; rv = str_;
@ -296,7 +276,6 @@ namespace str
rv.erase(rv.size()-1); rv.erase(rv.size()-1);
return rv; return rv;
}
} }
bool bool

25
src/str.hpp

@ -23,45 +23,30 @@
namespace str namespace str
{ {
void void
split(const char *str,
const char delimiter,
std::vector<std::string> *result);
void
split(const std::string &str,
split(const std::string_view str,
const char delimiter, const char delimiter,
std::vector<std::string> *result); std::vector<std::string> *result);
void void
split(const char *str,
const char delimiter,
std::set<std::string> *result);
void
split(const std::string &str,
split(const std::string_view str,
const char delimiter, const char delimiter,
std::set<std::string> *result); std::set<std::string> *result);
void void
split_on_null(const char *str,
const size_t len,
split_on_null(const std::string_view str,
std::vector<std::string> *result); std::vector<std::string> *result);
void void
rsplit1(const std::string &str,
rsplit1(const std::string_view &str,
const char delimiter, const char delimiter,
std::vector<std::string> *result); std::vector<std::string> *result);
void void
splitkv(const std::string &str,
splitkv(const std::string_view str,
const char delimiter, const char delimiter,
std::string *key, std::string *key,
std::string *value); std::string *value);
void
splitkv(const std::string_view &str,
const char delimiter,
std::string &key,
std::string_view &val);
std::string std::string
join(const std::vector<std::string> &vec, join(const std::vector<std::string> &vec,
const size_t substridx, const size_t substridx,

42
src/symlinkify.hpp

@ -19,9 +19,7 @@
#pragma once #pragma once
#include "fuse_kernel.h" #include "fuse_kernel.h"
#include <sys/stat.h>
#include <time.h>
#include "int_types.h"
#include <string> #include <string>
@ -32,13 +30,13 @@ namespace symlinkify
inline inline
bool bool
can_be_symlink(const struct stat &st_, can_be_symlink(const struct stat &st_,
const time_t timeout_)
const s64 timeout_)
{ {
if(S_ISDIR(st_.st_mode) || if(S_ISDIR(st_.st_mode) ||
(st_.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH))) (st_.st_mode & (S_IWUSR|S_IWGRP|S_IWOTH)))
return false; return false;
const time_t now = ::time(NULL);
const s64 now = ::time(NULL);
return (((now - st_.st_mtime) > timeout_) && return (((now - st_.st_mtime) > timeout_) &&
((now - st_.st_ctime) > timeout_)); ((now - st_.st_ctime) > timeout_));
@ -48,13 +46,13 @@ namespace symlinkify
inline inline
bool bool
can_be_symlink(const struct fuse_statx &st_, can_be_symlink(const struct fuse_statx &st_,
const time_t timeout_)
const s64 timeout_)
{ {
if(S_ISDIR(st_.mode) || if(S_ISDIR(st_.mode) ||
(st_.mode & (S_IWUSR|S_IWGRP|S_IWOTH))) (st_.mode & (S_IWUSR|S_IWGRP|S_IWOTH)))
return false; return false;
const time_t now = ::time(NULL);
const s64 now = ::time(NULL);
return (((now - st_.mtime.tv_sec) > timeout_) && return (((now - st_.mtime.tv_sec) > timeout_) &&
((now - st_.ctime.tv_sec) > timeout_)); ((now - st_.ctime.tv_sec) > timeout_));
@ -81,4 +79,34 @@ namespace symlinkify
st_->size = target_.size(); st_->size = target_.size();
st_->blocks = 0; st_->blocks = 0;
} }
static
inline
void
convert_if_can_be_symlink(const std::string &target_,
struct stat *st_,
const s64 timeout_)
{
if(timeout_ < 0)
return;
if(!symlinkify::can_be_symlink(*st_,timeout_))
return;
symlinkify::convert(target_,st_);
}
static
inline
void
convert_if_can_be_symlink(const std::string &target_,
fuse_statx *st_,
const s64 timeout_)
{
if(timeout_ < 0)
return;
if(!symlinkify::can_be_symlink(*st_,timeout_))
return;
symlinkify::convert(target_,st_);
}
} }

47
src/to_string.cpp

@ -23,38 +23,39 @@
#include <cstdint> #include <cstdint>
#include <string> #include <string>
#include <inttypes.h>
#include <stdio.h>
namespace str
std::string
str::to(const bool bool_)
{ {
std::string
to(const bool bool_)
{
return (bool_ ? "true" : "false"); return (bool_ ? "true" : "false");
}
}
std::string
to(const int int_)
{
std::string
str::to(const int int_)
{
return fmt::format("{}",int_); return fmt::format("{}",int_);
}
}
std::string
to(const uint64_t uint64_)
{
std::string
str::to(const uint64_t uint64_)
{
return fmt::format("{}",uint64_); return fmt::format("{}",uint64_);
}
}
std::string
to(const std::string &s_)
{
std::string
str::to(const int64_t int64_)
{
return fmt::format("{}",int64_);
}
std::string
str::to(const std::string &s_)
{
return s_; return s_;
}
}
std::string
to(const fs::Path &path_)
{
std::string
str::to(const std::filesystem::path &path_)
{
return path_.string(); return path_.string();
}
} }

6
src/to_string.hpp

@ -18,9 +18,8 @@
#pragma once #pragma once
#include "fs_path.hpp"
#include <cstdint> #include <cstdint>
#include <filesystem>
#include <string> #include <string>
@ -29,6 +28,7 @@ namespace str
std::string to(const bool); std::string to(const bool);
std::string to(const int); std::string to(const int);
std::string to(const uint64_t); std::string to(const uint64_t);
std::string to(const int64_t);
std::string to(const std::string&); std::string to(const std::string&);
std::string to(const fs::Path&);
std::string to(const std::filesystem::path&);
} }

3
src/tofrom_string.hpp

@ -19,10 +19,11 @@
#pragma once #pragma once
#include <string> #include <string>
#include <string_view>
class ToFromString class ToFromString
{ {
public: public:
virtual std::string to_string() const = 0; virtual std::string to_string() const = 0;
virtual int from_string(const std::string &) = 0;
virtual int from_string(const std::string_view) = 0;
}; };

2
src/tofrom_wrapper.hpp

@ -29,7 +29,7 @@ class ToFromWrapper : public ToFromString
{ {
public: public:
int int
from_string(const std::string &s_) final
from_string(const std::string_view s_) final
{ {
return str::from(s_,&_data); return str::from(s_,&_data);
} }

Loading…
Cancel
Save