mirror of https://github.com/trapexit/mergerfs.git
Browse Source
Change getattr and statx to bespoke policies
Change getattr and statx to bespoke policies
* Provides: slight improvement in performance as it no longer will need to find and then act on the files. * It doesn't make sense to support all original policy types. Most people used 'newest' or 'ff' and 'combine' is a better default which has same runtime as 'newest' but with better output.getattr2
32 changed files with 1050 additions and 239 deletions
-
3src/config.cpp
-
6src/config.hpp
-
8src/config_follow_symlinks.hpp
-
9src/follow_symlinks_enum.hpp
-
19src/fs_lstat.hpp
-
0src/fs_stat.cpp
-
61src/fs_stat.hpp
-
61src/fs_statx.hpp
-
76src/func_getattr.hpp
-
35src/func_getattr_base.hpp
-
63src/func_getattr_combine.cpp
-
21src/func_getattr_combine.hpp
-
39src/func_getattr_factory.cpp
-
13src/func_getattr_factory.hpp
-
41src/func_getattr_ff.cpp
-
23src/func_getattr_ff.hpp
-
57src/func_getattr_newest.cpp
-
21src/func_getattr_newest.hpp
-
81src/func_statx.hpp
-
38src/func_statx_base.hpp
-
71src/func_statx_combine.cpp
-
23src/func_statx_combine.hpp
-
39src/func_statx_factory.cpp
-
13src/func_statx_factory.hpp
-
48src/func_statx_ff.cpp
-
25src/func_statx_ff.hpp
-
64src/func_statx_newest.cpp
-
23src/func_statx_newest.hpp
-
103src/fuse_getattr.cpp
-
111src/fuse_statx_supported.icpp
-
72src/timespec_utils.hpp
-
22src/to_cstr.hpp
@ -0,0 +1,9 @@ |
|||||
|
#pragma once
|
||||
|
|
||||
|
enum class FollowSymlinksEnum |
||||
|
{ |
||||
|
NEVER, |
||||
|
DIRECTORY, |
||||
|
REGULAR, |
||||
|
ALL |
||||
|
}; |
||||
@ -0,0 +1,76 @@ |
|||||
|
#pragma once
|
||||
|
|
||||
|
#include "func_getattr_base.hpp"
|
||||
|
#include "func_getattr_factory.hpp"
|
||||
|
|
||||
|
#include "tofrom_string.hpp"
|
||||
|
|
||||
|
#include "fmt/core.h"
|
||||
|
|
||||
|
#include <atomic>
|
||||
|
|
||||
|
#include <cassert>
|
||||
|
|
||||
|
namespace Func2 |
||||
|
{ |
||||
|
class GetAttr : public ToFromString |
||||
|
{ |
||||
|
private: |
||||
|
std::shared_ptr<Func2::GetAttrBase> _impl; |
||||
|
|
||||
|
public: |
||||
|
GetAttr() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
GetAttr(const std::string &name_) |
||||
|
{ |
||||
|
_impl = Func2::GetAttrFactory::make(name_); |
||||
|
assert(_impl); |
||||
|
} |
||||
|
|
||||
|
public: |
||||
|
int |
||||
|
operator()(const Branches &branches_, |
||||
|
const fs::path &fusepath_, |
||||
|
struct stat *st_, |
||||
|
const FollowSymlinksEnum follow_symlinks_, |
||||
|
const s64 symlinkify_timeout_) |
||||
|
{ |
||||
|
std::shared_ptr<Func2::GetAttrBase> p; |
||||
|
|
||||
|
p = std::atomic_load(&_impl); |
||||
|
|
||||
|
return (*p)(branches_, |
||||
|
fusepath_, |
||||
|
st_, |
||||
|
follow_symlinks_, |
||||
|
symlinkify_timeout_); |
||||
|
} |
||||
|
|
||||
|
public: |
||||
|
std::string |
||||
|
to_string() const |
||||
|
{ |
||||
|
std::shared_ptr<Func2::GetAttrBase> p; |
||||
|
|
||||
|
p = std::atomic_load(&_impl); |
||||
|
|
||||
|
return std::string(p->name()); |
||||
|
} |
||||
|
|
||||
|
int |
||||
|
from_string(const std::string_view str_) |
||||
|
{ |
||||
|
std::shared_ptr<Func2::GetAttrBase> p; |
||||
|
|
||||
|
p = Func2::GetAttrFactory::make(str_); |
||||
|
if(!p) |
||||
|
return -EINVAL; |
||||
|
|
||||
|
_impl = std::atomic_load(&p); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
#pragma once
|
||||
|
|
||||
|
#include "follow_symlinks_enum.hpp"
|
||||
|
|
||||
|
#include "fs_path.hpp"
|
||||
|
#include "branches.hpp"
|
||||
|
#include "int_types.h"
|
||||
|
|
||||
|
#include "fuse.h"
|
||||
|
|
||||
|
#include <string_view>
|
||||
|
|
||||
|
#include <sys/types.h>
|
||||
|
#include <sys/stat.h>
|
||||
|
#include <unistd.h>
|
||||
|
|
||||
|
namespace Func2 |
||||
|
{ |
||||
|
class GetAttrBase |
||||
|
{ |
||||
|
public: |
||||
|
GetAttrBase() {} |
||||
|
~GetAttrBase() {} |
||||
|
|
||||
|
public: |
||||
|
virtual std::string_view name() const = 0; |
||||
|
|
||||
|
public: |
||||
|
virtual int operator()(const Branches &branches, |
||||
|
const fs::path &fusepath, |
||||
|
struct stat *st, |
||||
|
const FollowSymlinksEnum follow_symlinks, |
||||
|
const s64 symlinkify_timeout) = 0; |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,63 @@ |
|||||
|
#include "func_getattr_combine.hpp"
|
||||
|
|
||||
|
#include "fs_inode.hpp"
|
||||
|
#include "fs_stat.hpp"
|
||||
|
#include "symlinkify.hpp"
|
||||
|
#include "timespec_utils.hpp"
|
||||
|
|
||||
|
|
||||
|
std::string_view |
||||
|
Func2::GetAttrCombine::name() const |
||||
|
{ |
||||
|
return "combine"; |
||||
|
} |
||||
|
|
||||
|
int |
||||
|
Func2::GetAttrCombine::operator()(const Branches &branches_, |
||||
|
const fs::path &fusepath_, |
||||
|
struct stat *st_, |
||||
|
const FollowSymlinksEnum follow_symlinks_, |
||||
|
const s64 symlinkify_timeout_) |
||||
|
{ |
||||
|
int rv; |
||||
|
fs::path fullpath; |
||||
|
const Branch *first_branch; |
||||
|
|
||||
|
first_branch = nullptr; |
||||
|
for(const auto &branch : branches_) |
||||
|
{ |
||||
|
struct stat tmp_st; |
||||
|
|
||||
|
fullpath = branch.path / fusepath_; |
||||
|
rv = fs::stat(fullpath,&tmp_st,follow_symlinks_); |
||||
|
if(rv < 0) |
||||
|
continue; |
||||
|
|
||||
|
if(!first_branch) |
||||
|
{ |
||||
|
*st_ = tmp_st; |
||||
|
first_branch = &branch; |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
st_->st_atim = TimeSpec::newest(st_->st_atim,tmp_st.st_atim); |
||||
|
st_->st_ctim = TimeSpec::newest(st_->st_ctim,tmp_st.st_ctim); |
||||
|
st_->st_mtim = TimeSpec::newest(st_->st_mtim,tmp_st.st_mtim); |
||||
|
st_->st_nlink += tmp_st.st_nlink; |
||||
|
} |
||||
|
|
||||
|
if(!first_branch) |
||||
|
return -ENOENT; |
||||
|
|
||||
|
if(symlinkify_timeout_ >= 0) |
||||
|
{ |
||||
|
fullpath = first_branch->path / fusepath_; |
||||
|
symlinkify::convert_if_can_be_symlink(fullpath, |
||||
|
st_, |
||||
|
symlinkify_timeout_); |
||||
|
} |
||||
|
|
||||
|
fs::inode::calc(first_branch->path,fusepath_,st_); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
#include "func_getattr_base.hpp"
|
||||
|
|
||||
|
namespace Func2 |
||||
|
{ |
||||
|
class GetAttrCombine : public GetAttrBase |
||||
|
{ |
||||
|
public: |
||||
|
GetAttrCombine() {} |
||||
|
~GetAttrCombine() {} |
||||
|
|
||||
|
public: |
||||
|
std::string_view name() const; |
||||
|
|
||||
|
public: |
||||
|
int operator()(const Branches &branches, |
||||
|
const fs::path &fusepath, |
||||
|
struct stat *st, |
||||
|
const FollowSymlinksEnum follow_symlinks, |
||||
|
const s64 symlinkify_timeout); |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
#include "func_getattr_factory.hpp"
|
||||
|
|
||||
|
#include "func_getattr_combine.hpp"
|
||||
|
#include "func_getattr_ff.hpp"
|
||||
|
#include "func_getattr_newest.hpp"
|
||||
|
|
||||
|
#include "policies.hpp"
|
||||
|
|
||||
|
bool |
||||
|
Func2::GetAttrFactory::valid(const std::string str_) |
||||
|
{ |
||||
|
if(str_ == "combined") |
||||
|
return true; |
||||
|
if(str_ == "ff") |
||||
|
return true; |
||||
|
if(str_ == "newest") |
||||
|
return true; |
||||
|
|
||||
|
if(Policies::Search::find(str_)) |
||||
|
return true; |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
std::shared_ptr<Func2::GetAttrBase> |
||||
|
Func2::GetAttrFactory::make(const std::string_view str_) |
||||
|
{ |
||||
|
if(str_ == "combine") |
||||
|
return std::make_shared<Func2::GetAttrCombine>(); |
||||
|
if(str_ == "ff") |
||||
|
return std::make_shared<Func2::GetAttrFF>(); |
||||
|
if(str_ == "newest") |
||||
|
return std::make_shared<Func2::GetAttrNewest>(); |
||||
|
|
||||
|
if(Policies::Search::find(str_)) |
||||
|
return std::make_shared<Func2::GetAttrCombine>(); |
||||
|
|
||||
|
return {}; |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
#pragma once
|
||||
|
|
||||
|
#include "func_getattr_base.hpp"
|
||||
|
|
||||
|
namespace Func2 |
||||
|
{ |
||||
|
class GetAttrFactory |
||||
|
{ |
||||
|
public: |
||||
|
static bool valid(const std::string str); |
||||
|
static std::shared_ptr<GetAttrBase> make(const std::string_view str); |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,41 @@ |
|||||
|
#include "func_getattr_ff.hpp"
|
||||
|
|
||||
|
#include "fs_stat.hpp"
|
||||
|
#include "fs_inode.hpp"
|
||||
|
#include "symlinkify.hpp"
|
||||
|
|
||||
|
|
||||
|
std::string_view |
||||
|
Func2::GetAttrFF::name() const |
||||
|
{ |
||||
|
return "ff"; |
||||
|
} |
||||
|
|
||||
|
int |
||||
|
Func2::GetAttrFF::operator()(const Branches &branches_, |
||||
|
const fs::path &fusepath_, |
||||
|
struct stat *st_, |
||||
|
const FollowSymlinksEnum follow_symlinks_, |
||||
|
const s64 symlinkify_timeout_) |
||||
|
{ |
||||
|
int rv; |
||||
|
fs::path fullpath; |
||||
|
|
||||
|
for(const auto &branch : branches_) |
||||
|
{ |
||||
|
fullpath = branch.path / fusepath_; |
||||
|
rv = fs::stat(fullpath,st_,follow_symlinks_); |
||||
|
if(rv < 0) |
||||
|
continue; |
||||
|
|
||||
|
symlinkify::convert_if_can_be_symlink(fullpath, |
||||
|
st_, |
||||
|
symlinkify_timeout_); |
||||
|
|
||||
|
fs::inode::calc(branch.path,fusepath_,st_); |
||||
|
|
||||
|
return rv; |
||||
|
} |
||||
|
|
||||
|
return -ENOENT; |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
#pragma once
|
||||
|
|
||||
|
#include "func_getattr_base.hpp"
|
||||
|
|
||||
|
namespace Func2 |
||||
|
{ |
||||
|
class GetAttrFF : public GetAttrBase |
||||
|
{ |
||||
|
public: |
||||
|
GetAttrFF() {} |
||||
|
~GetAttrFF() {} |
||||
|
|
||||
|
public: |
||||
|
std::string_view name() const; |
||||
|
|
||||
|
public: |
||||
|
int operator()(const Branches &branches, |
||||
|
const fs::path &fusepath, |
||||
|
struct stat *st, |
||||
|
const FollowSymlinksEnum follow_symlinks, |
||||
|
const s64 symlinkify_timeout); |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,57 @@ |
|||||
|
#include "func_getattr_newest.hpp"
|
||||
|
|
||||
|
#include "fs_stat.hpp"
|
||||
|
#include "fs_inode.hpp"
|
||||
|
#include "timespec_utils.hpp"
|
||||
|
#include "symlinkify.hpp"
|
||||
|
|
||||
|
|
||||
|
std::string_view |
||||
|
Func2::GetAttrNewest::name() const |
||||
|
{ |
||||
|
return "newest"; |
||||
|
} |
||||
|
|
||||
|
int |
||||
|
Func2::GetAttrNewest::operator()(const Branches &branches_, |
||||
|
const fs::path &fusepath_, |
||||
|
struct stat *st_, |
||||
|
const FollowSymlinksEnum follow_symlinks_, |
||||
|
const s64 symlinkify_timeout_) |
||||
|
{ |
||||
|
int rv; |
||||
|
fs::path fullpath; |
||||
|
const Branch *newest_branch; |
||||
|
|
||||
|
newest_branch = nullptr; |
||||
|
for(const auto &branch : branches_) |
||||
|
{ |
||||
|
struct stat tmp_st; |
||||
|
|
||||
|
fullpath = branch.path / fusepath_; |
||||
|
rv = fs::stat(fullpath,&tmp_st,follow_symlinks_); |
||||
|
if(rv < 0) |
||||
|
continue; |
||||
|
|
||||
|
if(!TimeSpec::is_newer(tmp_st.st_mtim,st_->st_mtim)) |
||||
|
continue; |
||||
|
|
||||
|
*st_ = tmp_st; |
||||
|
newest_branch = &branch; |
||||
|
} |
||||
|
|
||||
|
if(!newest_branch) |
||||
|
return -ENOENT; |
||||
|
|
||||
|
if(symlinkify_timeout_ >= 0) |
||||
|
{ |
||||
|
fullpath = newest_branch->path / fusepath_; |
||||
|
symlinkify::convert_if_can_be_symlink(fullpath, |
||||
|
st_, |
||||
|
symlinkify_timeout_); |
||||
|
} |
||||
|
|
||||
|
fs::inode::calc(newest_branch->path,fusepath_,st_); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
@ -0,0 +1,21 @@ |
|||||
|
#include "func_getattr_base.hpp"
|
||||
|
|
||||
|
namespace Func2 |
||||
|
{ |
||||
|
class GetAttrNewest : public GetAttrBase |
||||
|
{ |
||||
|
public: |
||||
|
GetAttrNewest() {} |
||||
|
~GetAttrNewest() {} |
||||
|
|
||||
|
public: |
||||
|
std::string_view name() const; |
||||
|
|
||||
|
public: |
||||
|
int operator()(const Branches &branches, |
||||
|
const fs::path &fusepath, |
||||
|
struct stat *st, |
||||
|
const FollowSymlinksEnum follow_symlinks, |
||||
|
const s64 symlinkify_timeout); |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,81 @@ |
|||||
|
#pragma once
|
||||
|
|
||||
|
#include "func_statx_base.hpp"
|
||||
|
#include "func_statx_factory.hpp"
|
||||
|
|
||||
|
#include "tofrom_string.hpp"
|
||||
|
|
||||
|
#include "fmt/core.h"
|
||||
|
|
||||
|
#include <atomic>
|
||||
|
|
||||
|
#include <assert.h>
|
||||
|
|
||||
|
|
||||
|
namespace Func2 |
||||
|
{ |
||||
|
class Statx : public ToFromString |
||||
|
{ |
||||
|
private: |
||||
|
std::shared_ptr<Func2::StatxBase> _impl; |
||||
|
|
||||
|
public: |
||||
|
Statx() |
||||
|
{ |
||||
|
} |
||||
|
|
||||
|
Statx(const std::string &name_) |
||||
|
{ |
||||
|
_impl = Func2::StatxFactory::make(name_); |
||||
|
assert(_impl); |
||||
|
} |
||||
|
|
||||
|
public: |
||||
|
int |
||||
|
operator()(const Branches &branches_, |
||||
|
const fs::path &fusepath_, |
||||
|
const u32 flags_, |
||||
|
const u32 mask_, |
||||
|
struct fuse_statx *st_, |
||||
|
const FollowSymlinksEnum follow_symlinks_, |
||||
|
const s64 symlinkify_timeout_) |
||||
|
{ |
||||
|
std::shared_ptr<Func2::StatxBase> p; |
||||
|
|
||||
|
p = std::atomic_load(&_impl); |
||||
|
|
||||
|
return (*p)(branches_, |
||||
|
fusepath_, |
||||
|
flags_, |
||||
|
mask_, |
||||
|
st_, |
||||
|
follow_symlinks_, |
||||
|
symlinkify_timeout_); |
||||
|
} |
||||
|
|
||||
|
public: |
||||
|
std::string |
||||
|
to_string() const |
||||
|
{ |
||||
|
std::shared_ptr<Func2::StatxBase> p; |
||||
|
|
||||
|
p = std::atomic_load(&_impl); |
||||
|
|
||||
|
return std::string(p->name()); |
||||
|
} |
||||
|
|
||||
|
int |
||||
|
from_string(const std::string_view str_) |
||||
|
{ |
||||
|
std::shared_ptr<Func2::StatxBase> p; |
||||
|
|
||||
|
p = Func2::StatxFactory::make(str_); |
||||
|
if(!p) |
||||
|
return -EINVAL; |
||||
|
|
||||
|
_impl = std::atomic_load(&p); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,38 @@ |
|||||
|
#pragma once
|
||||
|
|
||||
|
#include "follow_symlinks_enum.hpp"
|
||||
|
|
||||
|
#include "fs_path.hpp"
|
||||
|
#include "branches.hpp"
|
||||
|
#include "int_types.h"
|
||||
|
|
||||
|
#include "fuse.h"
|
||||
|
|
||||
|
#include <string_view>
|
||||
|
|
||||
|
#include <sys/types.h>
|
||||
|
#include <sys/stat.h>
|
||||
|
#include <unistd.h>
|
||||
|
|
||||
|
|
||||
|
namespace Func2 |
||||
|
{ |
||||
|
class StatxBase |
||||
|
{ |
||||
|
public: |
||||
|
StatxBase() {} |
||||
|
~StatxBase() {} |
||||
|
|
||||
|
public: |
||||
|
virtual std::string_view name() const = 0; |
||||
|
|
||||
|
public: |
||||
|
virtual int operator()(const Branches &branches, |
||||
|
const fs::path &fusepath, |
||||
|
const u32 flags_, |
||||
|
const u32 mask_, |
||||
|
struct fuse_statx *st, |
||||
|
const FollowSymlinksEnum follow_symlinks, |
||||
|
const s64 symlinkify_timeout) = 0; |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,71 @@ |
|||||
|
#include "func_statx_combine.hpp"
|
||||
|
|
||||
|
#include "fs_inode.hpp"
|
||||
|
#include "fs_statx.hpp"
|
||||
|
#include "symlinkify.hpp"
|
||||
|
#include "timespec_utils.hpp"
|
||||
|
|
||||
|
|
||||
|
std::string_view |
||||
|
Func2::StatxCombine::name() const |
||||
|
{ |
||||
|
return "combine"; |
||||
|
} |
||||
|
|
||||
|
int |
||||
|
Func2::StatxCombine::operator()(const Branches &branches_, |
||||
|
const fs::path &fusepath_, |
||||
|
const u32 flags_, |
||||
|
const u32 mask_, |
||||
|
struct fuse_statx *st_, |
||||
|
const FollowSymlinksEnum follow_symlinks_, |
||||
|
const s64 symlinkify_timeout_) |
||||
|
{ |
||||
|
int rv; |
||||
|
fs::path fullpath; |
||||
|
const Branch *first_branch; |
||||
|
|
||||
|
first_branch = nullptr; |
||||
|
for(const auto &branch : branches_) |
||||
|
{ |
||||
|
struct fuse_statx tmp_st; |
||||
|
|
||||
|
fullpath = branch.path / fusepath_; |
||||
|
rv = fs::statx(AT_FDCWD, |
||||
|
fullpath, |
||||
|
flags_|AT_SYMLINK_NOFOLLOW, |
||||
|
mask_, |
||||
|
&tmp_st, |
||||
|
follow_symlinks_); |
||||
|
if(rv < 0) |
||||
|
continue; |
||||
|
|
||||
|
if(!first_branch) |
||||
|
{ |
||||
|
*st_ = tmp_st; |
||||
|
first_branch = &branch; |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
|
st_->atime = TimeSpec::newest(st_->atime,tmp_st.atime); |
||||
|
st_->ctime = TimeSpec::newest(st_->ctime,tmp_st.ctime); |
||||
|
st_->mtime = TimeSpec::newest(st_->mtime,tmp_st.mtime); |
||||
|
st_->btime = TimeSpec::newest(st_->btime,tmp_st.btime); |
||||
|
st_->nlink += tmp_st.nlink; |
||||
|
} |
||||
|
|
||||
|
if(!first_branch) |
||||
|
return -ENOENT; |
||||
|
|
||||
|
if(symlinkify_timeout_ >= 0) |
||||
|
{ |
||||
|
fullpath = first_branch->path / fusepath_; |
||||
|
symlinkify::convert_if_can_be_symlink(fullpath, |
||||
|
st_, |
||||
|
symlinkify_timeout_); |
||||
|
} |
||||
|
|
||||
|
fs::inode::calc(first_branch->path,fusepath_,st_); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
#include "func_statx_base.hpp"
|
||||
|
|
||||
|
namespace Func2 |
||||
|
{ |
||||
|
class StatxCombine : public StatxBase |
||||
|
{ |
||||
|
public: |
||||
|
StatxCombine() {} |
||||
|
~StatxCombine() {} |
||||
|
|
||||
|
public: |
||||
|
std::string_view name() const; |
||||
|
|
||||
|
public: |
||||
|
int operator()(const Branches &branches, |
||||
|
const fs::path &fusepath, |
||||
|
const u32 flags_, |
||||
|
const u32 mask_, |
||||
|
struct fuse_statx *st, |
||||
|
const FollowSymlinksEnum follow_symlinks, |
||||
|
const s64 symlinkify_timeout); |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,39 @@ |
|||||
|
#include "func_statx_factory.hpp"
|
||||
|
|
||||
|
#include "func_statx_combine.hpp"
|
||||
|
#include "func_statx_ff.hpp"
|
||||
|
#include "func_statx_newest.hpp"
|
||||
|
|
||||
|
#include "policies.hpp"
|
||||
|
|
||||
|
bool |
||||
|
Func2::StatxFactory::valid(const std::string str_) |
||||
|
{ |
||||
|
if(str_ == "combined") |
||||
|
return true; |
||||
|
if(str_ == "ff") |
||||
|
return true; |
||||
|
if(str_ == "newest") |
||||
|
return true; |
||||
|
|
||||
|
if(Policies::Search::find(str_)) |
||||
|
return true; |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
std::shared_ptr<Func2::StatxBase> |
||||
|
Func2::StatxFactory::make(const std::string_view str_) |
||||
|
{ |
||||
|
if(str_ == "combine") |
||||
|
return std::make_shared<Func2::StatxCombine>(); |
||||
|
if(str_ == "ff") |
||||
|
return std::make_shared<Func2::StatxFF>(); |
||||
|
if(str_ == "newest") |
||||
|
return std::make_shared<Func2::StatxNewest>(); |
||||
|
|
||||
|
if(Policies::Search::find(str_)) |
||||
|
return std::make_shared<Func2::StatxCombine>(); |
||||
|
|
||||
|
return {}; |
||||
|
} |
||||
@ -0,0 +1,13 @@ |
|||||
|
#pragma once
|
||||
|
|
||||
|
#include "func_statx_base.hpp"
|
||||
|
|
||||
|
namespace Func2 |
||||
|
{ |
||||
|
class StatxFactory |
||||
|
{ |
||||
|
public: |
||||
|
static bool valid(const std::string str); |
||||
|
static std::shared_ptr<StatxBase> make(const std::string_view str); |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,48 @@ |
|||||
|
#include "func_statx_ff.hpp"
|
||||
|
|
||||
|
#include "fs_statx.hpp"
|
||||
|
#include "fs_inode.hpp"
|
||||
|
#include "symlinkify.hpp"
|
||||
|
|
||||
|
|
||||
|
std::string_view |
||||
|
Func2::StatxFF::name() const |
||||
|
{ |
||||
|
return "ff"; |
||||
|
} |
||||
|
|
||||
|
int |
||||
|
Func2::StatxFF::operator()(const Branches &branches_, |
||||
|
const fs::path &fusepath_, |
||||
|
const u32 flags_, |
||||
|
const u32 mask_, |
||||
|
struct fuse_statx *st_, |
||||
|
const FollowSymlinksEnum follow_symlinks_, |
||||
|
const s64 symlinkify_timeout_) |
||||
|
{ |
||||
|
int rv; |
||||
|
fs::path fullpath; |
||||
|
|
||||
|
for(const auto &branch : branches_) |
||||
|
{ |
||||
|
fullpath = branch.path / fusepath_; |
||||
|
rv = fs::statx(AT_FDCWD, |
||||
|
fullpath, |
||||
|
flags_|AT_SYMLINK_NOFOLLOW, |
||||
|
mask_, |
||||
|
st_, |
||||
|
follow_symlinks_); |
||||
|
if(rv < 0) |
||||
|
continue; |
||||
|
|
||||
|
symlinkify::convert_if_can_be_symlink(fullpath, |
||||
|
st_, |
||||
|
symlinkify_timeout_); |
||||
|
|
||||
|
fs::inode::calc(branch.path,fusepath_,st_); |
||||
|
|
||||
|
return rv; |
||||
|
} |
||||
|
|
||||
|
return -ENOENT; |
||||
|
} |
||||
@ -0,0 +1,25 @@ |
|||||
|
#pragma once
|
||||
|
|
||||
|
#include "func_statx_base.hpp"
|
||||
|
|
||||
|
namespace Func2 |
||||
|
{ |
||||
|
class StatxFF : public StatxBase |
||||
|
{ |
||||
|
public: |
||||
|
StatxFF() {} |
||||
|
~StatxFF() {} |
||||
|
|
||||
|
public: |
||||
|
std::string_view name() const; |
||||
|
|
||||
|
public: |
||||
|
int operator()(const Branches &branches, |
||||
|
const fs::path &fusepath, |
||||
|
const u32 flags_, |
||||
|
const u32 mask_, |
||||
|
struct fuse_statx *st, |
||||
|
const FollowSymlinksEnum follow_symlinks, |
||||
|
const s64 symlinkify_timeout); |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,64 @@ |
|||||
|
#include "func_statx_newest.hpp"
|
||||
|
|
||||
|
#include "fs_statx.hpp"
|
||||
|
#include "fs_inode.hpp"
|
||||
|
#include "symlinkify.hpp"
|
||||
|
#include "timespec_utils.hpp"
|
||||
|
|
||||
|
|
||||
|
std::string_view |
||||
|
Func2::StatxNewest::name() const |
||||
|
{ |
||||
|
return "newest"; |
||||
|
} |
||||
|
|
||||
|
int |
||||
|
Func2::StatxNewest::operator()(const Branches &branches_, |
||||
|
const fs::path &fusepath_, |
||||
|
const u32 flags_, |
||||
|
const u32 mask_, |
||||
|
struct fuse_statx *st_, |
||||
|
const FollowSymlinksEnum follow_symlinks_, |
||||
|
const s64 symlinkify_timeout_) |
||||
|
{ |
||||
|
int rv; |
||||
|
fs::path fullpath; |
||||
|
const Branch *newest_branch; |
||||
|
|
||||
|
newest_branch = nullptr; |
||||
|
for(const auto &branch : branches_) |
||||
|
{ |
||||
|
struct fuse_statx tmp_st; |
||||
|
|
||||
|
fullpath = branch.path / fusepath_; |
||||
|
rv = fs::statx(AT_FDCWD, |
||||
|
fullpath, |
||||
|
flags_|AT_SYMLINK_NOFOLLOW, |
||||
|
mask_, |
||||
|
&tmp_st, |
||||
|
follow_symlinks_); |
||||
|
if(rv < 0) |
||||
|
continue; |
||||
|
|
||||
|
if(not TimeSpec::is_newer(tmp_st.mtime,st_->mtime)) |
||||
|
continue; |
||||
|
|
||||
|
*st_ = tmp_st; |
||||
|
newest_branch = &branch; |
||||
|
} |
||||
|
|
||||
|
if(!newest_branch) |
||||
|
return -ENOENT; |
||||
|
|
||||
|
if(symlinkify_timeout_ >= 0) |
||||
|
{ |
||||
|
fullpath = newest_branch->path / fusepath_; |
||||
|
symlinkify::convert_if_can_be_symlink(fullpath, |
||||
|
st_, |
||||
|
symlinkify_timeout_); |
||||
|
} |
||||
|
|
||||
|
fs::inode::calc(newest_branch->path,fusepath_,st_); |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
@ -0,0 +1,23 @@ |
|||||
|
#include "func_statx_base.hpp"
|
||||
|
|
||||
|
namespace Func2 |
||||
|
{ |
||||
|
class StatxNewest : public StatxBase |
||||
|
{ |
||||
|
public: |
||||
|
StatxNewest() {} |
||||
|
~StatxNewest() {} |
||||
|
|
||||
|
public: |
||||
|
std::string_view name() const; |
||||
|
|
||||
|
public: |
||||
|
int operator()(const Branches &branches, |
||||
|
const fs::path &fusepath, |
||||
|
const u32 flags_, |
||||
|
const u32 mask_, |
||||
|
struct fuse_statx *st, |
||||
|
const FollowSymlinksEnum follow_symlinks, |
||||
|
const s64 symlinkify_timeout); |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,72 @@ |
|||||
|
#pragma once
|
||||
|
|
||||
|
namespace TimeSpec |
||||
|
{ |
||||
|
static |
||||
|
inline |
||||
|
bool |
||||
|
is_newer(const timespec &t0_, |
||||
|
const timespec &t1_) |
||||
|
{ |
||||
|
if(t0_.tv_sec > t1_.tv_sec) |
||||
|
return true; |
||||
|
if(t0_.tv_sec == t1_.tv_sec) |
||||
|
{ |
||||
|
if(t0_.tv_nsec > t1_.tv_nsec) |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
inline |
||||
|
timespec |
||||
|
newest(const timespec &t0_, |
||||
|
const timespec &t1_) |
||||
|
{ |
||||
|
if(t0_.tv_sec > t1_.tv_sec) |
||||
|
return t0_; |
||||
|
if(t0_.tv_sec == t1_.tv_sec) |
||||
|
{ |
||||
|
if(t0_.tv_nsec > t1_.tv_nsec) |
||||
|
return t0_; |
||||
|
} |
||||
|
|
||||
|
return t1_; |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
inline |
||||
|
bool |
||||
|
is_newer(const fuse_sx_time &t0_, |
||||
|
const fuse_sx_time &t1_) |
||||
|
{ |
||||
|
if(t0_.tv_sec > t1_.tv_sec) |
||||
|
return true; |
||||
|
if(t0_.tv_sec == t1_.tv_sec) |
||||
|
{ |
||||
|
if(t0_.tv_nsec > t1_.tv_nsec) |
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
inline |
||||
|
fuse_sx_time |
||||
|
newest(const fuse_sx_time &t0_, |
||||
|
const fuse_sx_time &t1_) |
||||
|
{ |
||||
|
if(t0_.tv_sec > t1_.tv_sec) |
||||
|
return t0_; |
||||
|
if(t0_.tv_sec == t1_.tv_sec) |
||||
|
{ |
||||
|
if(t0_.tv_nsec > t1_.tv_nsec) |
||||
|
return t0_; |
||||
|
} |
||||
|
|
||||
|
return t1_; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,22 @@ |
|||||
|
#pragma once
|
||||
|
|
||||
|
#include <filesystem>
|
||||
|
#include <string>
|
||||
|
#include <type_traits>
|
||||
|
|
||||
|
|
||||
|
template<typename PathType> |
||||
|
const char* |
||||
|
to_cstr(const PathType &p_) |
||||
|
{ |
||||
|
if constexpr (std::is_same_v<std::decay_t<PathType>, std::filesystem::path>) |
||||
|
return p_.c_str(); |
||||
|
if constexpr (std::is_same_v<std::decay_t<PathType>, std::string>) |
||||
|
return p_.c_str(); |
||||
|
if constexpr (std::is_same_v<std::decay_t<PathType>, const char*> || |
||||
|
std::is_same_v<std::decay_t<PathType>, char*>) |
||||
|
return p_; |
||||
|
|
||||
|
abort(); |
||||
|
return NULL; |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue