mirror of
https://github.com/trapexit/mergerfs.git
synced 2026-10-19 16:16:48 +00:00
Compare commits
98
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8bd3726cf8 | ||
|
|
18b72049a4 | ||
|
|
2f91276333 | ||
|
|
7c1bea4757 | ||
|
|
14f775a302 | ||
|
|
4622bc8160 | ||
|
|
5176458c7b | ||
|
|
06256e1120 | ||
|
|
ab27265347 | ||
|
|
13b4bf4649 | ||
|
|
dc5c7e95a6 | ||
|
|
ef825e0ff6 | ||
|
|
557a02115c | ||
|
|
73c9d86481 | ||
|
|
7ba1b8f332 | ||
|
|
31470ee458 | ||
|
|
0ef62afcbf | ||
|
|
2cd64960e3 | ||
|
|
fb534e5aba | ||
|
|
6e4b618376 | ||
|
|
802f9a0eaf | ||
|
|
04f2068adf | ||
|
|
d36688c752 | ||
|
|
e0cf997312 | ||
|
|
999b774dcb | ||
|
|
c0252fa5e6 | ||
|
|
50caf408f6 | ||
|
|
2fcd019f30 | ||
|
|
3fed8a12db | ||
|
|
17f7df7b3e | ||
|
|
0b552d11f8 | ||
|
|
c59c79f92c | ||
|
|
2e1d028516 | ||
|
|
316c971e6f | ||
|
|
ee4a8a18ac | ||
|
|
4675d8045b | ||
|
|
72fde7def8 | ||
|
|
7e8e279ed3 | ||
|
|
b021e73752 | ||
|
|
06f0d1b2d8 | ||
|
|
7eeee57043 | ||
|
|
21b8e376be | ||
|
|
353a5f7103 | ||
|
|
a863981746 | ||
|
|
71a939112d | ||
|
|
882634fa38 | ||
|
|
03a28d3ebe | ||
|
|
6e5b4aa40f | ||
|
|
28c36aea0e | ||
|
|
bcb45b917d | ||
|
|
59bec051fc | ||
|
|
9dba189b90 | ||
|
|
e8289f2cbe | ||
|
|
ea88c8ac56 | ||
|
|
2c177ddaeb | ||
|
|
bb674484b1 | ||
|
|
3f0ec90891 | ||
|
|
2338e7d8a9 | ||
|
|
8ec2d01d59 | ||
|
|
4996628e7f | ||
|
|
3c96b138f0 | ||
|
|
4d81f824a4 | ||
|
|
d90763fcd2 | ||
|
|
b3100540c6 | ||
|
|
5db592d4db | ||
|
|
695b1042f9 | ||
|
|
fe4c7faf4b | ||
|
|
da13bdff15 | ||
|
|
5b478446aa | ||
|
|
a376263d43 | ||
|
|
a0e10d7638 | ||
|
|
f5bb8f6c60 | ||
|
|
266a936208 | ||
|
|
15dd1cae2b | ||
|
|
867fb8ef46 | ||
|
|
b33a72ca5c | ||
|
|
2fa854dcc3 | ||
|
|
03145a0789 | ||
|
|
a2638a98b0 | ||
|
|
8188b13d73 | ||
|
|
46d3297d5e | ||
|
|
51af59ee59 | ||
|
|
8a961d56d9 | ||
|
|
2166f3537b | ||
|
|
8e0e88cd34 | ||
|
|
02cb3e2242 | ||
|
|
4b02d1c6c0 | ||
|
|
89bbd38ef2 | ||
|
|
4b8d68fb03 | ||
|
|
234f534204 | ||
|
|
08b11ea09d | ||
|
|
1b1d46a35c | ||
|
|
07db8d2ee9 | ||
|
|
332ca520aa | ||
|
|
e18fcc5714 | ||
|
|
d818892b93 | ||
|
|
8ab6bcf554 | ||
|
|
b3b8e793f9 |
+45
-32
@@ -275,7 +275,9 @@ static
|
||||
void
|
||||
debug_open_flags(const uint32_t flags_)
|
||||
{
|
||||
fmt::print("{}, ",open_accmode_to_str(flags_));
|
||||
fmt::print(g_OUTPUT,
|
||||
"{}, ",
|
||||
open_accmode_to_str(flags_));
|
||||
for(size_t i = 0; i < (sizeof(flags_) * 8); i++)
|
||||
{
|
||||
const char *str;
|
||||
@@ -287,7 +289,7 @@ debug_open_flags(const uint32_t flags_)
|
||||
if(str == NULL)
|
||||
continue;
|
||||
|
||||
fmt::print("{}, ",str);
|
||||
fmt::print(g_OUTPUT,"{}, ",str);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -315,7 +317,7 @@ fuse_fopen_flag_to_str(const uint32_t offset_)
|
||||
void
|
||||
debug_fuse_open_out(const struct fuse_open_out *arg_)
|
||||
{
|
||||
fmt::print(stderr,
|
||||
fmt::print(g_OUTPUT,
|
||||
"fuse_open_out:"
|
||||
" fh=0x{:#08x};"
|
||||
" open_flags=0x{:#04x} (",
|
||||
@@ -332,9 +334,9 @@ debug_fuse_open_out(const struct fuse_open_out *arg_)
|
||||
if(str == NULL)
|
||||
continue;
|
||||
|
||||
fmt::print(stderr,"{},",str);
|
||||
fmt::print(g_OUTPUT,"{},",str);
|
||||
}
|
||||
fmt::print(stderr,");\n");
|
||||
fmt::print(g_OUTPUT,");\n");
|
||||
}
|
||||
|
||||
static
|
||||
@@ -445,7 +447,7 @@ debug_fuse_mkdir_in(const void *arg_)
|
||||
"fuse_mkdir_in:"
|
||||
" mode={:o};"
|
||||
" umask={:o};"
|
||||
" name=%s;"
|
||||
" name={};"
|
||||
"\n"
|
||||
,
|
||||
arg->mode,
|
||||
@@ -461,7 +463,7 @@ debug_fuse_unlink(const void *arg_)
|
||||
|
||||
fmt::print(g_OUTPUT,
|
||||
"fuse_unlink:"
|
||||
" name=%s;"
|
||||
" name={};"
|
||||
"\n"
|
||||
,
|
||||
name);
|
||||
@@ -475,7 +477,7 @@ debug_fuse_rmdir(const void *arg_)
|
||||
|
||||
fmt::print(g_OUTPUT,
|
||||
"fuse_mkdir:"
|
||||
" name=%s;"
|
||||
" name={};"
|
||||
"\n"
|
||||
,
|
||||
name);
|
||||
@@ -493,8 +495,8 @@ debug_fuse_symlink(const void *arg_)
|
||||
|
||||
fmt::print(g_OUTPUT,
|
||||
"fuse_mkdir:"
|
||||
" linkname=%s;"
|
||||
" name=%s;"
|
||||
" linkname={};"
|
||||
" name={};"
|
||||
"\n"
|
||||
,
|
||||
linkname,
|
||||
@@ -514,9 +516,9 @@ debug_fuse_rename_in(const void *arg_)
|
||||
|
||||
fmt::print(g_OUTPUT,
|
||||
"fuse_rename_in:"
|
||||
" oldname=%s;"
|
||||
" oldname={};"
|
||||
" newdir={};"
|
||||
" newname=%s;"
|
||||
" newname={};"
|
||||
"\n"
|
||||
,
|
||||
oldname,
|
||||
@@ -536,7 +538,7 @@ debug_fuse_link_in(const void *arg_)
|
||||
fmt::print(g_OUTPUT,
|
||||
"fuse_link_in:"
|
||||
" oldnodeid={};"
|
||||
" name=%s;"
|
||||
" name={};"
|
||||
"\n"
|
||||
,
|
||||
arg->oldnodeid,
|
||||
@@ -556,7 +558,7 @@ debug_fuse_create_in(const void *arg_)
|
||||
"fuse_create_in:"
|
||||
" mode={:o};"
|
||||
" umask={:o};"
|
||||
" name=%s;"
|
||||
" name={};"
|
||||
" flags=0x%X (",
|
||||
arg->mode,
|
||||
arg->umask,
|
||||
@@ -574,7 +576,7 @@ debug_fuse_open_in(const void *arg_)
|
||||
|
||||
fmt::print(g_OUTPUT,
|
||||
"fuse_open_in:"
|
||||
" flags=0x%08X (",
|
||||
" flags=0x{:08X} (",
|
||||
arg->flags);
|
||||
debug_open_flags(arg->flags);
|
||||
fmt::print(g_OUTPUT,");\n");
|
||||
@@ -639,7 +641,7 @@ debug_fuse_write_in(const void *arg_)
|
||||
if(str == NULL)
|
||||
continue;
|
||||
|
||||
fmt::print(g_OUTPUT,"%s,",str);
|
||||
fmt::print(g_OUTPUT,"{},",str);
|
||||
}
|
||||
fmt::print(g_OUTPUT,");\n");
|
||||
}
|
||||
@@ -712,8 +714,8 @@ debug_fuse_setxattr_in(const void *arg_)
|
||||
"fuse_setxattr_in:"
|
||||
" size={};"
|
||||
" flags=0x%X;"
|
||||
" name=%s;"
|
||||
" value=%s;"
|
||||
" name={};"
|
||||
" value={};"
|
||||
"\n"
|
||||
,
|
||||
arg->size,
|
||||
@@ -734,7 +736,7 @@ debug_fuse_getxattr_in(const void *arg_)
|
||||
fmt::print(g_OUTPUT,
|
||||
"fuse_getxattr_in:"
|
||||
" size={};"
|
||||
" name=%s;"
|
||||
" name={};"
|
||||
"\n"
|
||||
,
|
||||
arg->size,
|
||||
@@ -763,7 +765,7 @@ debug_fuse_removexattr(const void *arg_)
|
||||
|
||||
fmt::print(g_OUTPUT,
|
||||
"fuse_removexattr:"
|
||||
" name=%s;"
|
||||
" name={};"
|
||||
"\n"
|
||||
,
|
||||
name);
|
||||
@@ -816,7 +818,7 @@ debug_fuse_init_in(const struct fuse_init_in *arg_)
|
||||
if(str == NULL)
|
||||
continue;
|
||||
|
||||
fmt::print(g_OUTPUT,"%s, ",str);
|
||||
fmt::print(g_OUTPUT,"{}, ",str);
|
||||
}
|
||||
fmt::print(g_OUTPUT,")\n");
|
||||
}
|
||||
@@ -932,7 +934,7 @@ debug_fuse_init_out(const uint64_t unique_,
|
||||
if(str == NULL)
|
||||
continue;
|
||||
|
||||
fmt::print(g_OUTPUT,"%s, ",str);
|
||||
fmt::print(g_OUTPUT,"{}, ",str);
|
||||
}
|
||||
|
||||
fmt::print(g_OUTPUT,
|
||||
@@ -1100,13 +1102,14 @@ opcode_name(enum fuse_opcode op_)
|
||||
{
|
||||
static const char *names[] =
|
||||
{
|
||||
"INVALID",
|
||||
"INVALID0",
|
||||
"LOOKUP",
|
||||
"FORGET",
|
||||
"GETATTR",
|
||||
"SETATTR",
|
||||
"READLINK",
|
||||
"SYMLINK",
|
||||
"INVALID1",
|
||||
"MKNOD",
|
||||
"MKDIR",
|
||||
"UNLINK",
|
||||
@@ -1118,6 +1121,7 @@ opcode_name(enum fuse_opcode op_)
|
||||
"WRITE",
|
||||
"STATFS",
|
||||
"RELEASE",
|
||||
"INVALID3",
|
||||
"FSYNC",
|
||||
"SETXATTR",
|
||||
"GETXATTR",
|
||||
@@ -1147,7 +1151,10 @@ opcode_name(enum fuse_opcode op_)
|
||||
"LSEEK",
|
||||
"COPY_FILE_RANGE",
|
||||
"SETUPMAPPING",
|
||||
"REMOVEMAPPING"
|
||||
"REMOVEMAPPING",
|
||||
"SYNCFS",
|
||||
"TMPFILE",
|
||||
"STATX"
|
||||
};
|
||||
|
||||
if(op_ >= (sizeof(names) / sizeof(names[0])))
|
||||
@@ -1161,9 +1168,9 @@ debug_fuse_in_header(const struct fuse_in_header *hdr_)
|
||||
{
|
||||
const void *arg = &hdr_[1];
|
||||
|
||||
fmt::print(stderr,
|
||||
"unique=0x%016" PRIx64 ";"
|
||||
" opcode=%s ({});"
|
||||
fmt::print(g_OUTPUT,
|
||||
"unique=0x{:016x};"
|
||||
" opcode={} ({});"
|
||||
" nodeid={};"
|
||||
" uid={};"
|
||||
" gid={};"
|
||||
@@ -1265,8 +1272,14 @@ debug_fuse_in_header(const struct fuse_in_header *hdr_)
|
||||
case FUSE_INTERRUPT:
|
||||
debug_fuse_interrupt_in(arg);
|
||||
break;
|
||||
case FUSE_SYNCFS:
|
||||
break;
|
||||
case FUSE_TMPFILE:
|
||||
break;
|
||||
case FUSE_STATX:
|
||||
break;
|
||||
default:
|
||||
fmt::print(g_OUTPUT,"FIXME\n");
|
||||
fmt::print(g_OUTPUT,"FIXME: {}\n",hdr_->opcode);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -1275,10 +1288,10 @@ void
|
||||
debug_fuse_out_header(const struct fuse_out_header *hdr_)
|
||||
{
|
||||
fmt::print(g_OUTPUT,
|
||||
"unique=0x%016" PRIx64 ";"
|
||||
"unique=0x{:016x};"
|
||||
" opcode=RESPONSE;"
|
||||
" error=%d (%s);"
|
||||
" len={};"
|
||||
" error={} ({});"
|
||||
" len={};\n"
|
||||
,
|
||||
hdr_->unique,
|
||||
hdr_->error,
|
||||
@@ -1312,7 +1325,7 @@ debug_fuse_readlink(const uint64_t unique_,
|
||||
" opcode=RESPONSE;"
|
||||
" error=0 (Success);"
|
||||
" len={}; || "
|
||||
"readlink: linkname=%s"
|
||||
"readlink: linkname={}"
|
||||
"\n"
|
||||
,
|
||||
unique_,
|
||||
|
||||
@@ -51,6 +51,7 @@ void debug_fuse_lk_out(const uint64_t unique,
|
||||
void debug_fuse_bmap_out(const uint64_t unique,
|
||||
const struct fuse_bmap_out *arg);
|
||||
void debug_fuse_in_header(const struct fuse_in_header *hdr);
|
||||
void debug_fuse_out_header(const struct fuse_out_header *hdr);
|
||||
|
||||
std::string fuse_debug_init_flag_name(const uint64_t);
|
||||
|
||||
|
||||
@@ -1797,6 +1797,8 @@ fuse_ll_buf_process_read(struct fuse_session *se_,
|
||||
if(fuse_ll_funcs[in->opcode] == NULL)
|
||||
goto reply_err;
|
||||
|
||||
// debug_fuse_in_header(in);
|
||||
|
||||
fuse_ll_funcs[in->opcode](req, in);
|
||||
|
||||
return;
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <utility>
|
||||
|
||||
template<typename T>
|
||||
class AtomicSharedPtr
|
||||
{
|
||||
private:
|
||||
std::shared_ptr<T> _ptr;
|
||||
|
||||
public:
|
||||
AtomicSharedPtr() = default;
|
||||
|
||||
explicit
|
||||
AtomicSharedPtr(std::shared_ptr<T> ptr_)
|
||||
: _ptr(std::move(ptr_))
|
||||
{
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
explicit
|
||||
AtomicSharedPtr(Args&&... args)
|
||||
: _ptr(std::make_shared<T>(std::forward<Args>(args)...))
|
||||
{
|
||||
}
|
||||
|
||||
AtomicSharedPtr(const AtomicSharedPtr&) = delete;
|
||||
AtomicSharedPtr& operator=(const AtomicSharedPtr&) = delete;
|
||||
|
||||
AtomicSharedPtr(AtomicSharedPtr&& other_) noexcept
|
||||
: _ptr(std::move(other_._ptr))
|
||||
{
|
||||
}
|
||||
|
||||
AtomicSharedPtr&
|
||||
operator=(AtomicSharedPtr&& other_) noexcept
|
||||
{
|
||||
if(this != &other_)
|
||||
_ptr = std::move(other_._ptr);
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
std::shared_ptr<T>
|
||||
load() const
|
||||
{
|
||||
return std::atomic_load(&_ptr);
|
||||
}
|
||||
|
||||
void
|
||||
store(std::shared_ptr<T> desired_)
|
||||
{
|
||||
std::atomic_store(&_ptr, std::move(desired_));
|
||||
}
|
||||
|
||||
std::shared_ptr<T>
|
||||
exchange(std::shared_ptr<T> desired_)
|
||||
{
|
||||
return std::atomic_exchange(&_ptr, std::move(desired_));
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_strong(std::shared_ptr<T>& expected_,
|
||||
std::shared_ptr<T> desired_)
|
||||
{
|
||||
return std::atomic_compare_exchange_strong(&_ptr,
|
||||
&expected_,
|
||||
std::move(desired_));
|
||||
}
|
||||
|
||||
bool
|
||||
compare_exchange_weak(std::shared_ptr<T>& expected_,
|
||||
std::shared_ptr<T> desired_)
|
||||
{
|
||||
return std::atomic_compare_exchange_weak(&_ptr,
|
||||
&expected_,
|
||||
std::move(desired_));
|
||||
}
|
||||
|
||||
bool
|
||||
is_null() const
|
||||
{
|
||||
return !std::atomic_load(&_ptr);
|
||||
}
|
||||
|
||||
void
|
||||
reset()
|
||||
{
|
||||
std::atomic_store(&_ptr, std::shared_ptr<T>());
|
||||
}
|
||||
|
||||
T*
|
||||
get() const
|
||||
{
|
||||
return std::atomic_load(&_ptr).get();
|
||||
}
|
||||
|
||||
template<typename... Args>
|
||||
auto
|
||||
operator()(Args&&... args) const ->
|
||||
decltype(std::declval<T>()(std::forward<Args>(args)...))
|
||||
{
|
||||
auto ptr = load();
|
||||
|
||||
return (*ptr)(std::forward<Args>(args)...);
|
||||
}
|
||||
};
|
||||
@@ -42,16 +42,8 @@ namespace Category
|
||||
public:
|
||||
Action(Funcs &funcs_)
|
||||
{
|
||||
funcs.push_back(&funcs_.chmod);
|
||||
funcs.push_back(&funcs_.chown);
|
||||
funcs.push_back(&funcs_.link);
|
||||
funcs.push_back(&funcs_.removexattr);
|
||||
funcs.push_back(&funcs_.rename);
|
||||
funcs.push_back(&funcs_.rmdir);
|
||||
funcs.push_back(&funcs_.setxattr);
|
||||
funcs.push_back(&funcs_.truncate);
|
||||
funcs.push_back(&funcs_.unlink);
|
||||
funcs.push_back(&funcs_.utimens);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -78,12 +70,9 @@ namespace Category
|
||||
public:
|
||||
Search(Funcs &funcs_)
|
||||
{
|
||||
funcs.push_back(&funcs_.access);
|
||||
funcs.push_back(&funcs_.getattr);
|
||||
funcs.push_back(&funcs_.getxattr);
|
||||
funcs.push_back(&funcs_.listxattr);
|
||||
funcs.push_back(&funcs_.open);
|
||||
funcs.push_back(&funcs_.readlink);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+16
-14
@@ -138,6 +138,7 @@ Config::Config()
|
||||
|
||||
_congestion_threshold(fuse_cfg.congestion_threshold),
|
||||
_debug(fuse_cfg.debug),
|
||||
_getattr_statx(getattr,statx),
|
||||
_gid(fuse_cfg.gid),
|
||||
_max_background(fuse_cfg.max_background),
|
||||
_mount(mountpoint),
|
||||
@@ -225,27 +226,28 @@ Config::Config()
|
||||
_map["flush-on-close"] = &flushonclose;
|
||||
_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.access"] = &access;
|
||||
_map["func.chmod"] = &chmod;
|
||||
_map["func.chown"] = &chown;
|
||||
_map["func.create"] = &func.create;
|
||||
_map["func.getattr"] = &func.getattr;
|
||||
_map["func.getxattr"] = &func.getxattr;
|
||||
_map["func.getattr"] = &_getattr_statx;
|
||||
_map["func.getxattr"] = &getxattr;
|
||||
_map["func.link"] = &func.link;
|
||||
_map["func.listxattr"] = &func.listxattr;
|
||||
_map["func.listxattr"] = &listxattr;
|
||||
_map["func.mkdir"] = &func.mkdir;
|
||||
_map["func.mknod"] = &func.mknod;
|
||||
_map["func.mknod"] = &mknod;
|
||||
_map["func.open"] = &func.open;
|
||||
_map["func.readdir"] = &readdir;
|
||||
_map["func.readlink"] = &func.readlink;
|
||||
_map["func.removexattr"] = &func.removexattr;
|
||||
_map["func.readlink"] = &readlink;
|
||||
_map["func.removexattr"] = &removexattr;
|
||||
_map["func.rename"] = &func.rename;
|
||||
_map["func.rmdir"] = &func.rmdir;
|
||||
_map["func.setxattr"] = &func.setxattr;
|
||||
_map["func.rmdir"] = &rmdir;
|
||||
_map["func.setxattr"] = &setxattr;
|
||||
_map["func.statx"] = &_getattr_statx;
|
||||
_map["func.symlink"] = &func.symlink;
|
||||
_map["func.truncate"] = &func.truncate;
|
||||
_map["func.unlink"] = &func.unlink;
|
||||
_map["func.utimens"] = &func.utimens;
|
||||
_map["func.truncate"] = &truncate;
|
||||
_map["func.unlink"] = &unlink;
|
||||
_map["func.utimens"] = &utimens;
|
||||
_map["fuse-msg-size"] = &fuse_msg_size;
|
||||
_map["gid"] = &_gid;
|
||||
_map["gid-cache.expire-timeout"] = &_dummy;
|
||||
|
||||
@@ -16,12 +16,29 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "func_access.hpp"
|
||||
#include "func_chmod.hpp"
|
||||
#include "func_chown.hpp"
|
||||
#include "func_getattr.hpp"
|
||||
#include "func_getxattr.hpp"
|
||||
#include "func_listxattr.hpp"
|
||||
#include "func_mknod.hpp"
|
||||
#include "func_readlink.hpp"
|
||||
#include "func_removexattr.hpp"
|
||||
#include "func_rmdir.hpp"
|
||||
#include "func_setxattr.hpp"
|
||||
#include "func_statx.hpp"
|
||||
#include "func_truncate.hpp"
|
||||
#include "func_unlink.hpp"
|
||||
#include "func_utimens.hpp"
|
||||
|
||||
#include "branches.hpp"
|
||||
#include "category.hpp"
|
||||
#include "config_cachefiles.hpp"
|
||||
#include "config_dummy.hpp"
|
||||
#include "config_flushonclose.hpp"
|
||||
#include "config_follow_symlinks.hpp"
|
||||
#include "config_getattr_statx.hpp"
|
||||
#include "config_inodecalc.hpp"
|
||||
#include "config_link_exdev.hpp"
|
||||
#include "config_log_metrics.hpp"
|
||||
@@ -108,6 +125,22 @@ public:
|
||||
Config& operator=(const Config&);
|
||||
|
||||
public:
|
||||
Func2::Access access{"all"};
|
||||
Func2::Chmod chmod{"all"};
|
||||
Func2::Chown chown{"all"};
|
||||
Func2::GetAttr getattr{"cdfo"};
|
||||
Func2::Getxattr getxattr{"ff"};
|
||||
Func2::Listxattr listxattr{"ff"};
|
||||
Func2::Mknod mknod{"ff"};
|
||||
Func2::Readlink readlink{"ff"};
|
||||
Func2::Removexattr removexattr{"all"};
|
||||
Func2::Rmdir rmdir{"all"};
|
||||
Func2::Setxattr setxattr{"all"};
|
||||
Func2::Statx statx{"cdfo"};
|
||||
Func2::Truncate truncate{"all"};
|
||||
Func2::Unlink unlink{"all"};
|
||||
Func2::Utimens utimens{"all"};
|
||||
|
||||
ConfigBOOL allow_idmap;
|
||||
ConfigBOOL async_read;
|
||||
Branches branches;
|
||||
@@ -171,6 +204,7 @@ private:
|
||||
TFSRef<int> _congestion_threshold;
|
||||
TFSRef<bool> _debug;
|
||||
CfgDummy _dummy;
|
||||
ConfigGetAttrStatx _getattr_statx;
|
||||
TFSRef<s64> _gid;
|
||||
TFSRef<int> _max_background;
|
||||
TFSRef<fs::path> _mount;
|
||||
|
||||
@@ -19,12 +19,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "enum.hpp"
|
||||
#include "follow_symlinks_enum.hpp"
|
||||
|
||||
enum class FollowSymlinksEnum
|
||||
{
|
||||
NEVER,
|
||||
DIRECTORY,
|
||||
REGULAR,
|
||||
ALL
|
||||
};
|
||||
typedef Enum<FollowSymlinksEnum> FollowSymlinks;
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
#pragma once
|
||||
|
||||
#include "config.hpp"
|
||||
#include "tofrom_string.hpp"
|
||||
|
||||
class ConfigGetAttrStatx : public ToFromString
|
||||
{
|
||||
private:
|
||||
Func2::GetAttr &_getattr;
|
||||
Func2::Statx &_statx;
|
||||
|
||||
public:
|
||||
ConfigGetAttrStatx() = delete;
|
||||
ConfigGetAttrStatx(Func2::GetAttr &getattr_,
|
||||
Func2::Statx &statx_)
|
||||
: _getattr(getattr_),
|
||||
_statx(statx_)
|
||||
{
|
||||
}
|
||||
|
||||
std::string
|
||||
to_string() const
|
||||
{
|
||||
return _getattr.to_string();
|
||||
}
|
||||
|
||||
int
|
||||
from_string(const std::string_view str_)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = _getattr.from_string(str_);
|
||||
if(rv < 0)
|
||||
return rv;
|
||||
|
||||
rv = _statx.from_string(str_);
|
||||
assert(rv == 0);
|
||||
|
||||
return rv;
|
||||
}
|
||||
};
|
||||
+14
-7
@@ -15,27 +15,34 @@ public:
|
||||
{
|
||||
}
|
||||
|
||||
operator int()
|
||||
operator int() const
|
||||
{
|
||||
return (_err.has_value() ? _err.value() : -ENOENT);
|
||||
return (_err.has_value() ? _err.value() : 0);
|
||||
}
|
||||
|
||||
// A rough heuristic for prioritizing errors. Success always
|
||||
// overrides failures. ENOENT is lowest errno priority, then EROFS
|
||||
// (which can be set due to branch mode = RO) then any other error.
|
||||
Err&
|
||||
operator=(int v_)
|
||||
operator=(int new_err_)
|
||||
{
|
||||
if(!_err.has_value())
|
||||
_err = ((v_ >= 0) ? 0 : v_);
|
||||
else if(v_ >= 0)
|
||||
_err = ((new_err_ >= 0) ? 0 : new_err_);
|
||||
else if(new_err_ >= 0)
|
||||
_err = 0;
|
||||
else if(_err == -ENOENT)
|
||||
_err = new_err_;
|
||||
else if((_err == -EROFS) && (new_err_ != -ENOENT))
|
||||
_err = new_err_;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool
|
||||
operator==(int v_)
|
||||
operator==(int other_)
|
||||
{
|
||||
if(_err.has_value())
|
||||
return (_err.value() == v_);
|
||||
return (_err.value() == other_);
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
|
||||
enum class FollowSymlinksEnum
|
||||
{
|
||||
NEVER,
|
||||
DIRECTORY,
|
||||
REGULAR,
|
||||
ALL
|
||||
};
|
||||
+5
-14
@@ -19,8 +19,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "to_neg_errno.hpp"
|
||||
|
||||
#include <string>
|
||||
#include "to_cstr.hpp"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
@@ -29,25 +28,17 @@
|
||||
|
||||
namespace fs
|
||||
{
|
||||
template<typename PathType>
|
||||
static
|
||||
inline
|
||||
int
|
||||
lstat(const char *path_,
|
||||
struct stat *st_)
|
||||
lstat(const PathType &path_,
|
||||
struct stat *st_)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = ::lstat(path_,st_);
|
||||
rv = ::lstat(to_cstr(path_),st_);
|
||||
|
||||
return ::to_neg_errno(rv);
|
||||
}
|
||||
|
||||
static
|
||||
inline
|
||||
int
|
||||
lstat(const std::string &path_,
|
||||
struct stat *st_)
|
||||
{
|
||||
return fs::lstat(path_.c_str(),st_);
|
||||
}
|
||||
}
|
||||
|
||||
+13
-4
@@ -1,5 +1,6 @@
|
||||
#pragma once
|
||||
|
||||
#include "fs_acl.hpp"
|
||||
#include "fs_mknod.hpp"
|
||||
#include "ugid.hpp"
|
||||
|
||||
@@ -13,9 +14,13 @@ namespace fs
|
||||
int
|
||||
mknod_as(const ugid_t ugid_,
|
||||
const T &path_,
|
||||
const mode_t mode_,
|
||||
const dev_t dev_)
|
||||
mode_t mode_,
|
||||
dev_t dev_,
|
||||
mode_t umask_)
|
||||
{
|
||||
if(not fs::acl::dir_has_defaults(path_))
|
||||
mode_ &= ~umask_;
|
||||
|
||||
const ugid::SetGuard _(ugid_);
|
||||
|
||||
return fs::mknod(path_,mode_,dev_);
|
||||
@@ -32,11 +37,15 @@ namespace fs
|
||||
int
|
||||
mknod_as(const ugid_t ugid_,
|
||||
const T &path_,
|
||||
const mode_t mode_,
|
||||
const dev_t dev_)
|
||||
mode_t mode_,
|
||||
dev_t dev_,
|
||||
mode_t umask_)
|
||||
{
|
||||
int rv;
|
||||
|
||||
if(not fs::acl::dir_has_defaults(path_))
|
||||
mode_ &= ~umask_;
|
||||
|
||||
rv = fs::mknod(path_,mode_,dev_);
|
||||
|
||||
fs::lchown(path_,ugid_.uid,ugid_.gid);
|
||||
|
||||
+55
-6
@@ -18,7 +18,10 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "follow_symlinks_enum.hpp"
|
||||
#include "to_neg_errno.hpp"
|
||||
#include "to_cstr.hpp"
|
||||
#include "fs_lstat.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
@@ -29,25 +32,71 @@
|
||||
|
||||
namespace fs
|
||||
{
|
||||
template<typename PathType>
|
||||
static
|
||||
inline
|
||||
int
|
||||
stat(const char *path_,
|
||||
struct stat *st_)
|
||||
stat(const PathType &path_,
|
||||
struct stat *st_)
|
||||
{
|
||||
int rv;
|
||||
|
||||
rv = ::stat(path_,st_);
|
||||
rv = ::stat(to_cstr(path_),st_);
|
||||
|
||||
return ::to_neg_errno(rv);
|
||||
}
|
||||
|
||||
template<typename PathType>
|
||||
static
|
||||
inline
|
||||
int
|
||||
stat(const std::string &path_,
|
||||
struct stat *st_)
|
||||
stat(const PathType &path_,
|
||||
struct stat *st_,
|
||||
FollowSymlinksEnum follow_)
|
||||
{
|
||||
return fs::stat(path_.c_str(),st_);
|
||||
int rv;
|
||||
|
||||
switch(follow_)
|
||||
{
|
||||
default:
|
||||
case FollowSymlinksEnum::NEVER:
|
||||
rv = fs::lstat(path_,st_);
|
||||
return rv;
|
||||
case FollowSymlinksEnum::DIRECTORY:
|
||||
rv = fs::lstat(path_,st_);
|
||||
if((rv >= 0) && S_ISLNK(st_->st_mode))
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
rv = fs::stat(path_,&st);
|
||||
if(rv < 0)
|
||||
return rv;
|
||||
|
||||
if(S_ISDIR(st.st_mode))
|
||||
*st_ = st;
|
||||
}
|
||||
return rv;
|
||||
case FollowSymlinksEnum::REGULAR:
|
||||
rv = fs::lstat(path_,st_);
|
||||
if((rv >= 0) && S_ISLNK(st_->st_mode))
|
||||
{
|
||||
struct stat st;
|
||||
|
||||
rv = fs::stat(path_,&st);
|
||||
if(rv < 0)
|
||||
return rv;
|
||||
|
||||
if(S_ISREG(st.st_mode))
|
||||
*st_ = st;
|
||||
}
|
||||
return rv;
|
||||
case FollowSymlinksEnum::ALL:
|
||||
rv = fs::stat(path_,st_);
|
||||
if(rv < 0)
|
||||
rv = fs::lstat(path_,st_);
|
||||
return rv;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
+53
-9
@@ -1,5 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "follow_symlinks_enum.hpp"
|
||||
#include "to_cstr.hpp"
|
||||
#include "to_neg_errno.hpp"
|
||||
|
||||
#include "fuse_kernel.h"
|
||||
@@ -15,13 +17,15 @@
|
||||
|
||||
#include "supported_statx.hpp"
|
||||
|
||||
|
||||
namespace fs
|
||||
{
|
||||
template<typename PathType>
|
||||
static
|
||||
inline
|
||||
int
|
||||
statx(const int dirfd_,
|
||||
const char *pathname_,
|
||||
const PathType &pathname_,
|
||||
const int flags_,
|
||||
const unsigned int mask_,
|
||||
struct fuse_statx *st_)
|
||||
@@ -30,7 +34,7 @@ namespace fs
|
||||
int rv;
|
||||
|
||||
rv = ::statx(dirfd_,
|
||||
pathname_,
|
||||
to_cstr(pathname_),
|
||||
flags_,
|
||||
mask_,
|
||||
(struct statx*)st_);
|
||||
@@ -41,19 +45,59 @@ namespace fs
|
||||
#endif
|
||||
}
|
||||
|
||||
template<typename PathType>
|
||||
static
|
||||
inline
|
||||
int
|
||||
statx(const int dirfd_,
|
||||
const std::string &pathname_,
|
||||
const PathType &pathname_,
|
||||
const int flags_,
|
||||
const unsigned int mask_,
|
||||
struct fuse_statx *st_)
|
||||
struct fuse_statx *st_,
|
||||
FollowSymlinksEnum followsymlinks_)
|
||||
{
|
||||
return fs::statx(dirfd_,
|
||||
pathname_.c_str(),
|
||||
flags_,
|
||||
mask_,
|
||||
st_);
|
||||
int rv;
|
||||
|
||||
switch(followsymlinks_)
|
||||
{
|
||||
case FollowSymlinksEnum::NEVER:
|
||||
rv = fs::statx(AT_FDCWD,pathname_,flags_|AT_SYMLINK_NOFOLLOW,mask_,st_);
|
||||
return rv;
|
||||
case FollowSymlinksEnum::DIRECTORY:
|
||||
rv = fs::statx(AT_FDCWD,pathname_,flags_|AT_SYMLINK_NOFOLLOW,mask_,st_);
|
||||
if((rv >= 0) && S_ISLNK(st_->mode))
|
||||
{
|
||||
struct fuse_statx st;
|
||||
|
||||
rv = fs::statx(AT_FDCWD,pathname_,AT_SYMLINK_FOLLOW,STATX_TYPE,&st);
|
||||
if(rv < 0)
|
||||
return rv;
|
||||
|
||||
if(S_ISDIR(st.mode))
|
||||
*st_ = st;
|
||||
}
|
||||
return rv;
|
||||
case FollowSymlinksEnum::REGULAR:
|
||||
rv = fs::statx(AT_FDCWD,pathname_,flags_|AT_SYMLINK_NOFOLLOW,mask_,st_);
|
||||
if((rv >= 0) && S_ISLNK(st_->mode))
|
||||
{
|
||||
struct fuse_statx st;
|
||||
|
||||
rv = fs::statx(AT_FDCWD,pathname_,AT_SYMLINK_FOLLOW,STATX_TYPE,&st);
|
||||
if(rv < 0)
|
||||
return rv;
|
||||
|
||||
if(S_ISREG(st.mode))
|
||||
*st_ = st;
|
||||
}
|
||||
return rv;
|
||||
case FollowSymlinksEnum::ALL:
|
||||
rv = fs::statx(AT_FDCWD,pathname_,flags_|AT_SYMLINK_FOLLOW,mask_,st_);
|
||||
if(rv < 0)
|
||||
rv = fs::statx(AT_FDCWD,pathname_,flags_|AT_SYMLINK_NOFOLLOW,mask_,st_);
|
||||
return rv;
|
||||
}
|
||||
|
||||
return -ENOENT;
|
||||
}
|
||||
}
|
||||
|
||||
+2
-2
@@ -338,7 +338,7 @@ fs::xattr::copy(const int fdin_,
|
||||
map<string,string> attrs;
|
||||
|
||||
rv = fs::xattr::get(fdin_,&attrs);
|
||||
if(rv < 0)
|
||||
if(rv <= 0)
|
||||
return rv;
|
||||
|
||||
return fs::xattr::set(fdout_,attrs);
|
||||
@@ -352,7 +352,7 @@ fs::xattr::copy(const string &from_,
|
||||
map<string,string> attrs;
|
||||
|
||||
rv = fs::xattr::get(from_,&attrs);
|
||||
if(rv < 0)
|
||||
if(rv <= 0)
|
||||
return rv;
|
||||
|
||||
return fs::xattr::set(to_,attrs);
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
#include "fsproxy.hpp"
|
||||
|
||||
#include "fs_close.hpp"
|
||||
|
||||
int
|
||||
FSProxy::_spawn_proxy_if_needed(const uid_t uid_,
|
||||
const gid_t gid_)
|
||||
{
|
||||
int rv;
|
||||
FSProxy::Process process;
|
||||
|
||||
if(_proxies.count({uid_,gid_}))
|
||||
return 0;
|
||||
|
||||
rv = pipe(process.req_pipe);
|
||||
if(rv == -1)
|
||||
return rv;
|
||||
rv = pipe(process.res_pipe);
|
||||
if(rv == -1)
|
||||
return rv;
|
||||
|
||||
process.pid = fork();
|
||||
if(process.pid != 0)
|
||||
{
|
||||
fs::close(process.req_pipe[1]);
|
||||
fs::close(process.res_pipe[0]);
|
||||
// listen on req in loop for instructions
|
||||
return 0;
|
||||
}
|
||||
|
||||
fs::close(process.req_pipe[0]);
|
||||
fs::close(process.res_pipe[1]);
|
||||
_proxies[UGID{uid_,gid_}] = process;
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,54 @@
|
||||
#pragma once
|
||||
|
||||
#include <unordered_map>
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
class FSProxy
|
||||
{
|
||||
public:
|
||||
struct UGID
|
||||
{
|
||||
bool
|
||||
operator==(const UGID &other_) const
|
||||
{
|
||||
return ((uid == other_.uid) &&
|
||||
(gid == other_.gid));
|
||||
}
|
||||
|
||||
uid_t uid;
|
||||
gid_t gid;
|
||||
};
|
||||
|
||||
struct UGIDHash
|
||||
{
|
||||
size_t
|
||||
operator()(const UGID &key_) const
|
||||
{
|
||||
size_t h0 = std::hash<uid_t>{}(key_.uid);
|
||||
size_t h1 = std::hash<uid_t>{}(key_.gid);
|
||||
|
||||
return (h0 ^ (h1 << 1));
|
||||
}
|
||||
};
|
||||
|
||||
struct Process
|
||||
{
|
||||
int pid;
|
||||
int req_pipe[2];
|
||||
int res_pipe[2];
|
||||
};
|
||||
|
||||
public:
|
||||
int create(uid_t uid,
|
||||
gid_t gid,
|
||||
const char *pathname,
|
||||
mode_t mode);
|
||||
|
||||
private:
|
||||
int _spawn_proxy_if_needed(uid_t,gid_t);
|
||||
|
||||
private:
|
||||
std::unordered_map<UGID,Process,UGIDHash> _proxies;
|
||||
};
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_access_base.hpp"
|
||||
#include "func_access_factory.hpp"
|
||||
|
||||
#include "func_wrapper.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
using Access = FuncWrapper<Func2::AccessBase,
|
||||
Func2::AccessFactory,
|
||||
int,
|
||||
const Branches&,
|
||||
const fs::path&,
|
||||
const int&>;
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
#include "func_access_all.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs_eaccess.hpp"
|
||||
|
||||
|
||||
std::string_view
|
||||
Func2::AccessAll::name() const
|
||||
{
|
||||
return "all";
|
||||
}
|
||||
|
||||
int
|
||||
Func2::AccessAll::operator()(const Branches &branches_,
|
||||
const fs::path &fusepath_,
|
||||
const int mode_)
|
||||
{
|
||||
int rv;
|
||||
fs::path fullpath;
|
||||
|
||||
for(const auto &branch : branches_)
|
||||
{
|
||||
fullpath = branch.path / fusepath_;
|
||||
|
||||
rv = fs::eaccess(fullpath,mode_);
|
||||
if(rv < 0)
|
||||
return rv;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "func_access_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class AccessAll : public AccessBase
|
||||
{
|
||||
public:
|
||||
AccessAll() {}
|
||||
~AccessAll() {}
|
||||
|
||||
public:
|
||||
std::string_view name() const;
|
||||
|
||||
public:
|
||||
int operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
const int mode);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "branches.hpp"
|
||||
|
||||
#include "fs_path.hpp"
|
||||
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class AccessBase
|
||||
{
|
||||
public:
|
||||
AccessBase() {}
|
||||
~AccessBase() {}
|
||||
|
||||
public:
|
||||
virtual std::string_view name() const = 0;
|
||||
|
||||
public:
|
||||
virtual int operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
const int mode) = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "func_access_factory.hpp"
|
||||
|
||||
#include "func_access_all.hpp"
|
||||
|
||||
#include "policies.hpp"
|
||||
|
||||
|
||||
bool
|
||||
Func2::AccessFactory::valid(const std::string str_)
|
||||
{
|
||||
if(str_ == "all")
|
||||
return true;
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<Func2::AccessBase>
|
||||
Func2::AccessFactory::make(const std::string_view str_)
|
||||
{
|
||||
if(str_ == "all")
|
||||
return std::make_shared<Func2::AccessAll>();
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return std::make_shared<Func2::AccessAll>();
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_access_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class AccessFactory
|
||||
{
|
||||
public:
|
||||
static bool valid(const std::string str);
|
||||
static std::shared_ptr<AccessBase> make(const std::string_view str);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_chmod_base.hpp"
|
||||
#include "func_chmod_factory.hpp"
|
||||
|
||||
#include "func_wrapper.hpp"
|
||||
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
using Chmod = FuncWrapper<Func2::ChmodBase,
|
||||
Func2::ChmodFactory,
|
||||
int,
|
||||
const Branches&,
|
||||
const fs::path&,
|
||||
const mode_t&>;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "func_chmod_all.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs_lchmod.hpp"
|
||||
|
||||
|
||||
std::string_view
|
||||
Func2::ChmodAll::name() const
|
||||
{
|
||||
return "all";
|
||||
}
|
||||
|
||||
int
|
||||
Func2::ChmodAll::operator()(const Branches &branches_,
|
||||
const fs::path &fusepath_,
|
||||
const mode_t mode_)
|
||||
{
|
||||
Err err;
|
||||
fs::path fullpath;
|
||||
|
||||
for(const auto &branch : branches_)
|
||||
{
|
||||
if(branch.ro())
|
||||
{
|
||||
err = -EROFS;
|
||||
continue;
|
||||
}
|
||||
|
||||
fullpath = branch.path / fusepath_;
|
||||
|
||||
err = fs::lchmod(fullpath,mode_);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "func_chmod_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class ChmodAll : public ChmodBase
|
||||
{
|
||||
public:
|
||||
ChmodAll() {}
|
||||
~ChmodAll() {}
|
||||
|
||||
public:
|
||||
std::string_view name() const;
|
||||
|
||||
public:
|
||||
int operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
const mode_t mode);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "branches.hpp"
|
||||
|
||||
#include "fs_path.hpp"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class ChmodBase
|
||||
{
|
||||
public:
|
||||
ChmodBase() {}
|
||||
~ChmodBase() {}
|
||||
|
||||
public:
|
||||
virtual std::string_view name() const = 0;
|
||||
|
||||
public:
|
||||
virtual int operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
const mode_t mode) = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "func_chmod_factory.hpp"
|
||||
|
||||
#include "func_chmod_all.hpp"
|
||||
|
||||
#include "policies.hpp"
|
||||
|
||||
|
||||
bool
|
||||
Func2::ChmodFactory::valid(const std::string str_)
|
||||
{
|
||||
if(str_ == "all")
|
||||
return true;
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<Func2::ChmodBase>
|
||||
Func2::ChmodFactory::make(const std::string_view str_)
|
||||
{
|
||||
if(str_ == "all")
|
||||
return std::make_shared<Func2::ChmodAll>();
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return std::make_shared<Func2::ChmodAll>();
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_chmod_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class ChmodFactory
|
||||
{
|
||||
public:
|
||||
static bool valid(const std::string str);
|
||||
static std::shared_ptr<ChmodBase> make(const std::string_view str);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_chown_base.hpp"
|
||||
#include "func_chown_factory.hpp"
|
||||
|
||||
#include "func_wrapper.hpp"
|
||||
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
using Chown = FuncWrapper<Func2::ChownBase,
|
||||
Func2::ChownFactory,
|
||||
int,
|
||||
const Branches&,
|
||||
const fs::path&,
|
||||
const uid_t&,
|
||||
const gid_t&>;
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
#include "func_chown_all.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs_lchown.hpp"
|
||||
|
||||
|
||||
std::string_view
|
||||
Func2::ChownAll::name() const
|
||||
{
|
||||
return "all";
|
||||
}
|
||||
|
||||
int
|
||||
Func2::ChownAll::operator()(const Branches &branches_,
|
||||
const fs::path &fusepath_,
|
||||
const uid_t uid_,
|
||||
const gid_t gid_)
|
||||
{
|
||||
Err err;
|
||||
fs::path fullpath;
|
||||
|
||||
for(const auto &branch : branches_)
|
||||
{
|
||||
if(branch.ro())
|
||||
{
|
||||
err = -EROFS;
|
||||
continue;
|
||||
}
|
||||
|
||||
fullpath = branch.path / fusepath_;
|
||||
|
||||
err = fs::lchown(fullpath,uid_,gid_);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "func_chown_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class ChownAll : public ChownBase
|
||||
{
|
||||
public:
|
||||
ChownAll() {}
|
||||
~ChownAll() {}
|
||||
|
||||
public:
|
||||
std::string_view name() const;
|
||||
|
||||
public:
|
||||
int operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
const uid_t uid,
|
||||
const gid_t gid);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#pragma once
|
||||
|
||||
#include "branches.hpp"
|
||||
|
||||
#include "fs_path.hpp"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class ChownBase
|
||||
{
|
||||
public:
|
||||
ChownBase() {}
|
||||
~ChownBase() {}
|
||||
|
||||
public:
|
||||
virtual std::string_view name() const = 0;
|
||||
|
||||
public:
|
||||
virtual int operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
const uid_t uid,
|
||||
const gid_t gid) = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "func_chown_factory.hpp"
|
||||
|
||||
#include "func_chown_all.hpp"
|
||||
|
||||
#include "policies.hpp"
|
||||
|
||||
|
||||
bool
|
||||
Func2::ChownFactory::valid(const std::string str_)
|
||||
{
|
||||
if(str_ == "all")
|
||||
return true;
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<Func2::ChownBase>
|
||||
Func2::ChownFactory::make(const std::string_view str_)
|
||||
{
|
||||
if(str_ == "all")
|
||||
return std::make_shared<Func2::ChownAll>();
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return std::make_shared<Func2::ChownAll>();
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_chown_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class ChownFactory
|
||||
{
|
||||
public:
|
||||
static bool valid(const std::string str);
|
||||
static std::shared_ptr<ChownBase> make(const std::string_view str);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_getattr_base.hpp"
|
||||
#include "func_getattr_factory.hpp"
|
||||
|
||||
#include "func_wrapper.hpp"
|
||||
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
using GetAttr = FuncWrapper<Func2::GetAttrBase,
|
||||
Func2::GetAttrFactory,
|
||||
int,
|
||||
const Branches&,
|
||||
const fs::path&,
|
||||
struct stat*&,
|
||||
const FollowSymlinksEnum&,
|
||||
const s64&>;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#pragma once
|
||||
|
||||
#include "follow_symlinks_enum.hpp"
|
||||
|
||||
#include "fs_path.hpp"
|
||||
#include "branches.hpp"
|
||||
#include "base_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,74 @@
|
||||
#include "func_getattr_cdco.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs_inode.hpp"
|
||||
#include "fs_stat.hpp"
|
||||
#include "symlinkify.hpp"
|
||||
#include "timespec_utils.hpp"
|
||||
|
||||
|
||||
std::string_view
|
||||
Func2::GetAttrCDCO::name() const
|
||||
{
|
||||
return "cdco";
|
||||
}
|
||||
|
||||
int
|
||||
Func2::GetAttrCDCO::operator()(const Branches &branches_,
|
||||
const fs::path &fusepath_,
|
||||
struct stat *st_,
|
||||
const FollowSymlinksEnum follow_symlinks_,
|
||||
const s64 symlinkify_timeout_)
|
||||
{
|
||||
int rv;
|
||||
Err err;
|
||||
fs::path fullpath;
|
||||
const Branch *first_branch;
|
||||
|
||||
first_branch = nullptr;
|
||||
for(const auto &branch : branches_)
|
||||
{
|
||||
struct stat tmp_st;
|
||||
|
||||
fullpath = branch.path / fusepath_;
|
||||
|
||||
err = rv = fs::stat(fullpath,&tmp_st,follow_symlinks_);
|
||||
if(rv < 0)
|
||||
continue;
|
||||
|
||||
if(not first_branch)
|
||||
{
|
||||
*st_ = tmp_st;
|
||||
first_branch = &branch;
|
||||
continue;
|
||||
}
|
||||
|
||||
// This upgrades the uid:gid because mergerfs now does most
|
||||
// file interaction as root and relies on `default_permissions`
|
||||
// to manage permissions. Want to ensure that root owned files
|
||||
// can't be changed so we treat them all as root owned.
|
||||
if(tmp_st.st_uid == 0)
|
||||
st_->st_uid = 0;
|
||||
if(tmp_st.st_gid == 0)
|
||||
st_->st_gid = 0;
|
||||
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 err;
|
||||
|
||||
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 GetAttrCDCO : public GetAttrBase
|
||||
{
|
||||
public:
|
||||
GetAttrCDCO() {}
|
||||
~GetAttrCDCO() {}
|
||||
|
||||
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,78 @@
|
||||
#include "func_getattr_cdfo.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs_inode.hpp"
|
||||
#include "fs_stat.hpp"
|
||||
#include "symlinkify.hpp"
|
||||
#include "timespec_utils.hpp"
|
||||
|
||||
|
||||
std::string_view
|
||||
Func2::GetAttrCDFO::name() const
|
||||
{
|
||||
return "cdfo";
|
||||
}
|
||||
|
||||
int
|
||||
Func2::GetAttrCDFO::operator()(const Branches &branches_,
|
||||
const fs::path &fusepath_,
|
||||
struct stat *st_,
|
||||
const FollowSymlinksEnum follow_symlinks_,
|
||||
const s64 symlinkify_timeout_)
|
||||
{
|
||||
int rv;
|
||||
Err err;
|
||||
fs::path fullpath;
|
||||
const Branch *first_branch;
|
||||
|
||||
first_branch = nullptr;
|
||||
for(const auto &branch : branches_)
|
||||
{
|
||||
struct stat tmp_st;
|
||||
|
||||
fullpath = branch.path / fusepath_;
|
||||
|
||||
err = rv = fs::stat(fullpath,
|
||||
&tmp_st,
|
||||
follow_symlinks_);
|
||||
if(rv < 0)
|
||||
continue;
|
||||
|
||||
if(not first_branch)
|
||||
{
|
||||
*st_ = tmp_st;
|
||||
first_branch = &branch;
|
||||
if(not S_ISDIR(tmp_st.st_mode))
|
||||
break;
|
||||
continue;
|
||||
}
|
||||
|
||||
// This upgrades the uid:gid because mergerfs now does most
|
||||
// file interaction as root and relies on `default_permissions`
|
||||
// to manage permissions. Want to ensure that root owned files
|
||||
// can't be changed so we treat them all as root owned.
|
||||
if(tmp_st.st_uid == 0)
|
||||
st_->st_uid = 0;
|
||||
if(tmp_st.st_gid == 0)
|
||||
st_->st_gid = 0;
|
||||
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 err;
|
||||
|
||||
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 GetAttrCDFO : public GetAttrBase
|
||||
{
|
||||
public:
|
||||
GetAttrCDFO() {}
|
||||
~GetAttrCDFO() {}
|
||||
|
||||
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,44 @@
|
||||
#include "func_getattr_factory.hpp"
|
||||
|
||||
#include "func_getattr_cdfo.hpp"
|
||||
#include "func_getattr_cdco.hpp"
|
||||
#include "func_getattr_ff.hpp"
|
||||
#include "func_getattr_newest.hpp"
|
||||
|
||||
#include "policies.hpp"
|
||||
|
||||
bool
|
||||
Func2::GetAttrFactory::valid(const std::string str_)
|
||||
{
|
||||
if(str_ == "cdfo")
|
||||
return true;
|
||||
if(str_ == "cdco")
|
||||
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_ == "cdfo")
|
||||
return std::make_shared<Func2::GetAttrCDFO>();
|
||||
if(str_ == "cdco")
|
||||
return std::make_shared<Func2::GetAttrCDCO>();
|
||||
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::GetAttrCDFO>();
|
||||
|
||||
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,44 @@
|
||||
#include "func_getattr_ff.hpp"
|
||||
|
||||
#include "error.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;
|
||||
Err err;
|
||||
fs::path fullpath;
|
||||
|
||||
for(const auto &branch : branches_)
|
||||
{
|
||||
fullpath = branch.path / fusepath_;
|
||||
|
||||
err = 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 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -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,59 @@
|
||||
#include "func_getattr_newest.hpp"
|
||||
|
||||
#include "error.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;
|
||||
Err err;
|
||||
fs::path fullpath;
|
||||
const Branch *newest_branch;
|
||||
|
||||
newest_branch = nullptr;
|
||||
for(const auto &branch : branches_)
|
||||
{
|
||||
struct stat tmp_st;
|
||||
|
||||
fullpath = branch.path / fusepath_;
|
||||
err = rv = fs::stat(fullpath,&tmp_st,follow_symlinks_);
|
||||
if(rv < 0)
|
||||
continue;
|
||||
|
||||
if(st_->st_mtim > tmp_st.st_mtim)
|
||||
continue;
|
||||
|
||||
*st_ = tmp_st;
|
||||
newest_branch = &branch;
|
||||
}
|
||||
|
||||
if(!newest_branch)
|
||||
return err;
|
||||
|
||||
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,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_getxattr_base.hpp"
|
||||
#include "func_getxattr_factory.hpp"
|
||||
|
||||
#include "func_wrapper.hpp"
|
||||
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
using Getxattr = FuncWrapper<Func2::GetxattrBase,
|
||||
Func2::GetxattrFactory,
|
||||
int,
|
||||
const Branches&,
|
||||
const fs::path&,
|
||||
const char*&,
|
||||
char*&,
|
||||
const size_t&>;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "branches.hpp"
|
||||
|
||||
#include "fs_path.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class GetxattrBase
|
||||
{
|
||||
public:
|
||||
GetxattrBase() {}
|
||||
~GetxattrBase() {}
|
||||
|
||||
public:
|
||||
virtual std::string_view name() const = 0;
|
||||
|
||||
public:
|
||||
virtual int operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
const char *attrname,
|
||||
char *attrval,
|
||||
const size_t attrval_size) = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "func_getxattr_factory.hpp"
|
||||
|
||||
#include "func_getxattr_ff.hpp"
|
||||
|
||||
#include "policies.hpp"
|
||||
|
||||
|
||||
bool
|
||||
Func2::GetxattrFactory::valid(const std::string str_)
|
||||
{
|
||||
if(str_ == "ff")
|
||||
return true;
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<Func2::GetxattrBase>
|
||||
Func2::GetxattrFactory::make(const std::string_view str_)
|
||||
{
|
||||
if(str_ == "ff")
|
||||
return std::make_shared<Func2::GetxattrFF>();
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return std::make_shared<Func2::GetxattrFF>();
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_getxattr_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class GetxattrFactory
|
||||
{
|
||||
public:
|
||||
static bool valid(const std::string str);
|
||||
static std::shared_ptr<GetxattrBase> make(const std::string_view str);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "func_getxattr_ff.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs_lgetxattr.hpp"
|
||||
|
||||
|
||||
std::string_view
|
||||
Func2::GetxattrFF::name() const
|
||||
{
|
||||
return "ff";
|
||||
}
|
||||
|
||||
int
|
||||
Func2::GetxattrFF::operator()(const Branches &branches_,
|
||||
const fs::path &fusepath_,
|
||||
const char *attrname_,
|
||||
char *attrval_,
|
||||
const size_t attrvalsize_)
|
||||
{
|
||||
int rv;
|
||||
Err err;
|
||||
fs::path fullpath;
|
||||
|
||||
for(const auto &branch : branches_)
|
||||
{
|
||||
fullpath = branch.path / fusepath_;
|
||||
|
||||
rv = fs::lgetxattr(fullpath,attrname_,attrval_,attrvalsize_);
|
||||
if(rv >= 0)
|
||||
return rv;
|
||||
err = rv;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "func_getxattr_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class GetxattrFF : public GetxattrBase
|
||||
{
|
||||
public:
|
||||
GetxattrFF() {}
|
||||
~GetxattrFF() {}
|
||||
|
||||
public:
|
||||
std::string_view name() const;
|
||||
|
||||
public:
|
||||
int operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
const char *attrname,
|
||||
char *attrval,
|
||||
const size_t attrvalsize);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_ioctl_base.hpp"
|
||||
#include "func_ioctl_factory.hpp"
|
||||
|
||||
#include "func_wrapper.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
using Ioctl = FuncWrapper<Func2::IoctlBase,
|
||||
Func2::IoctlFactory,
|
||||
int,
|
||||
const Branches&,
|
||||
const fs::path&,
|
||||
const mode_t&>;
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "branches.hpp"
|
||||
|
||||
#include "fs_path.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class IoctlBase
|
||||
{
|
||||
public:
|
||||
IoctlBase() {}
|
||||
~IoctlBase() {}
|
||||
|
||||
public:
|
||||
virtual std::string_view name() const = 0;
|
||||
|
||||
public:
|
||||
virtual int operator()(const Branches &branches,
|
||||
const fs::path &fusepath) = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "func_ioctl_factory.hpp"
|
||||
|
||||
#include "func_ioctl_ff.hpp"
|
||||
|
||||
#include "policies.hpp"
|
||||
|
||||
|
||||
bool
|
||||
Func2::IoctlFactory::valid(const std::string str_)
|
||||
{
|
||||
if(str_ == "ff")
|
||||
return true;
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<Func2::IoctlBase>
|
||||
Func2::IoctlFactory::make(const std::string_view str_)
|
||||
{
|
||||
if(str_ == "ff")
|
||||
return std::make_shared<Func2::IoctlFF>();
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return std::make_shared<Func2::IoctlFF>();
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_ioctl_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class IoctlFactory
|
||||
{
|
||||
public:
|
||||
static bool valid(const std::string str);
|
||||
static std::shared_ptr<IoctlBase> make(const std::string_view str);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#include "func_ioctl_ff.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs_ioctl.hpp"
|
||||
|
||||
|
||||
std::string_view
|
||||
Func2::IoctlFF::name() const
|
||||
{
|
||||
return "ff";
|
||||
}
|
||||
|
||||
int
|
||||
Func2::IoctlFF::operator()(const Branches &branches_,
|
||||
const fs::path &fusepath_)
|
||||
{
|
||||
Err err;
|
||||
fs::path fullpath;
|
||||
|
||||
for(const auto &branch : branches_)
|
||||
{
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "func_ioctl_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class IoctlFF : public IoctlBase
|
||||
{
|
||||
public:
|
||||
IoctlFF() {}
|
||||
~IoctlFF() {}
|
||||
|
||||
public:
|
||||
std::string_view name() const;
|
||||
|
||||
public:
|
||||
int operator()(const Branches &branches,
|
||||
const fs::path &fusepath);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_listxattr_base.hpp"
|
||||
#include "func_listxattr_factory.hpp"
|
||||
|
||||
#include "func_wrapper.hpp"
|
||||
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
using Listxattr = FuncWrapper<Func2::ListxattrBase,
|
||||
Func2::ListxattrFactory,
|
||||
ssize_t,
|
||||
const Branches&,
|
||||
const fs::path&,
|
||||
char*&,
|
||||
const size_t&>;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#pragma once
|
||||
|
||||
#include "branches.hpp"
|
||||
|
||||
#include "fs_path.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class ListxattrBase
|
||||
{
|
||||
public:
|
||||
ListxattrBase() {}
|
||||
~ListxattrBase() {}
|
||||
|
||||
public:
|
||||
virtual std::string_view name() const = 0;
|
||||
|
||||
public:
|
||||
virtual ssize_t operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
char *list,
|
||||
const size_t size) = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "func_listxattr_factory.hpp"
|
||||
|
||||
#include "func_listxattr_ff.hpp"
|
||||
|
||||
#include "policies.hpp"
|
||||
|
||||
|
||||
bool
|
||||
Func2::ListxattrFactory::valid(const std::string str_)
|
||||
{
|
||||
if(str_ == "ff")
|
||||
return true;
|
||||
|
||||
if(Policies::Search::find(str_))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<Func2::ListxattrBase>
|
||||
Func2::ListxattrFactory::make(const std::string_view str_)
|
||||
{
|
||||
if(str_ == "ff")
|
||||
return std::make_shared<Func2::ListxattrFF>();
|
||||
|
||||
if(Policies::Search::find(str_))
|
||||
return std::make_shared<Func2::ListxattrFF>();
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_listxattr_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class ListxattrFactory
|
||||
{
|
||||
public:
|
||||
static bool valid(const std::string str);
|
||||
static std::shared_ptr<ListxattrBase> make(const std::string_view str);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
#include "func_listxattr_ff.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs_llistxattr.hpp"
|
||||
|
||||
|
||||
std::string_view
|
||||
Func2::ListxattrFF::name() const
|
||||
{
|
||||
return "ff";
|
||||
}
|
||||
|
||||
static
|
||||
ssize_t
|
||||
_listxattr_ff(const Branches &branches_,
|
||||
const fs::path &fusepath_,
|
||||
char *list_,
|
||||
const size_t size_)
|
||||
{
|
||||
Err err;
|
||||
ssize_t rv;
|
||||
fs::path fullpath;
|
||||
|
||||
for(const auto &branch : branches_)
|
||||
{
|
||||
fullpath = branch.path / fusepath_;
|
||||
|
||||
rv = fs::llistxattr(fullpath,list_,size_);
|
||||
switch(rv)
|
||||
{
|
||||
case -ERANGE:
|
||||
case -ENOTSUP:
|
||||
case -E2BIG:
|
||||
return rv;
|
||||
default:
|
||||
if(rv >= 0)
|
||||
return rv;
|
||||
err = rv;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
ssize_t
|
||||
Func2::ListxattrFF::operator()(const Branches &branches_,
|
||||
const fs::path &fusepath_,
|
||||
char *list_,
|
||||
const size_t size_)
|
||||
{
|
||||
return ::_listxattr_ff(branches_,fusepath_,list_,size_);
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#include "func_listxattr_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class ListxattrFF : public ListxattrBase
|
||||
{
|
||||
public:
|
||||
ListxattrFF() {}
|
||||
~ListxattrFF() {}
|
||||
|
||||
public:
|
||||
std::string_view name() const;
|
||||
|
||||
public:
|
||||
ssize_t operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
char *list,
|
||||
const size_t size);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_mknod_base.hpp"
|
||||
#include "func_mknod_factory.hpp"
|
||||
|
||||
#include "func_wrapper.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
using Mknod = FuncWrapper<Func2::MknodBase,
|
||||
Func2::MknodFactory,
|
||||
int,
|
||||
const ugid_t&,
|
||||
const Branches&,
|
||||
const fs::path&,
|
||||
const mode_t&,
|
||||
const dev_t&,
|
||||
const mode_t&>;
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#pragma once
|
||||
|
||||
#include "branches.hpp"
|
||||
#include "fs_path.hpp"
|
||||
#include "ugid.hpp"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class MknodBase
|
||||
{
|
||||
public:
|
||||
MknodBase() {}
|
||||
~MknodBase() {}
|
||||
|
||||
public:
|
||||
virtual std::string_view name() const = 0;
|
||||
|
||||
public:
|
||||
virtual int operator()(const ugid_t &ugid,
|
||||
const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
const mode_t mode,
|
||||
const dev_t dev,
|
||||
const mode_t umask) = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#include "func_mknod_factory.hpp"
|
||||
|
||||
#include "func_mknod_ff.hpp"
|
||||
#include "func_mknod_mfs.hpp"
|
||||
|
||||
bool
|
||||
Func2::MknodFactory::valid(const std::string str_)
|
||||
{
|
||||
if(str_ == "ff")
|
||||
return true;
|
||||
if(str_ == "mfs")
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<Func2::MknodBase>
|
||||
Func2::MknodFactory::make(const std::string_view str_)
|
||||
{
|
||||
if(str_ == "ff")
|
||||
return std::make_shared<Func2::MknodFF>();
|
||||
if(str_ == "mfs")
|
||||
return std::make_shared<Func2::MknodMFS>();
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include <memory>
|
||||
#include <string_view>
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class MknodBase;
|
||||
|
||||
class MknodFactory
|
||||
{
|
||||
public:
|
||||
static bool valid(const std::string str_);
|
||||
|
||||
static std::shared_ptr<MknodBase> make(const std::string_view str_);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,73 @@
|
||||
#include "func_mknod_ff.hpp"
|
||||
|
||||
#include "errno.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs_clonepath.hpp"
|
||||
#include "fs_exists.hpp"
|
||||
#include "fs_info.hpp"
|
||||
#include "fs_mknod_as.hpp"
|
||||
#include "fs_path.hpp"
|
||||
#include "ugid.hpp"
|
||||
|
||||
|
||||
std::string_view
|
||||
Func2::MknodFF::name() const
|
||||
{
|
||||
return "ff";
|
||||
}
|
||||
|
||||
int
|
||||
Func2::MknodFF::operator()(const ugid_t &ugid_,
|
||||
const Branches &branches_,
|
||||
const fs::path &fusepath_,
|
||||
const mode_t mode_,
|
||||
const dev_t dev_,
|
||||
const mode_t umask_)
|
||||
{
|
||||
int rv;
|
||||
Err err;
|
||||
fs::path path;
|
||||
fs::info_t info;
|
||||
|
||||
for(const auto &dst_branch : branches_)
|
||||
{
|
||||
if(dst_branch.ro_or_nc())
|
||||
continue;
|
||||
rv = fs::info(dst_branch.path,&info);
|
||||
if(rv < 0)
|
||||
continue;
|
||||
if(info.readonly)
|
||||
continue;
|
||||
if(info.spaceavail < dst_branch.minfreespace())
|
||||
continue;
|
||||
|
||||
path = dst_branch.path / fusepath_;
|
||||
|
||||
rv = fs::mknod_as(ugid_,path,mode_,dev_,umask_);
|
||||
if(rv == 0)
|
||||
return rv;
|
||||
if(rv == -EEXIST)
|
||||
return rv;
|
||||
err = rv;
|
||||
if(rv != -ENOENT)
|
||||
continue;
|
||||
|
||||
path = fusepath_.parent_path();
|
||||
for(const auto &src_branch : branches_)
|
||||
{
|
||||
if(src_branch.path == dst_branch.path)
|
||||
continue;
|
||||
|
||||
rv = fs::clonepath(src_branch.path,
|
||||
dst_branch.path,
|
||||
path);
|
||||
if(rv == 0)
|
||||
break;
|
||||
}
|
||||
|
||||
path = dst_branch.path / fusepath_;
|
||||
return fs::mknod_as(ugid_,path,mode_,dev_,umask_);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "func_mknod_base.hpp"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class MknodFF : public MknodBase
|
||||
{
|
||||
public:
|
||||
MknodFF() {}
|
||||
~MknodFF() {}
|
||||
|
||||
public:
|
||||
std::string_view name() const;
|
||||
|
||||
public:
|
||||
int operator()(const ugid_t &ugid,
|
||||
const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
const mode_t mode,
|
||||
const dev_t dev,
|
||||
const mode_t umask);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,28 @@
|
||||
#include "func_mknod_mfs.hpp"
|
||||
|
||||
#include "errno.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs_acl.hpp"
|
||||
#include "fs_clonepath.hpp"
|
||||
#include "fs_exists.hpp"
|
||||
#include "fs_info.hpp"
|
||||
#include "fs_mknod_as.hpp"
|
||||
#include "fs_path.hpp"
|
||||
#include "ugid.hpp"
|
||||
|
||||
std::string_view
|
||||
Func2::MknodMFS::name() const
|
||||
{
|
||||
return "mfs";
|
||||
}
|
||||
|
||||
int
|
||||
Func2::MknodMFS::operator()(const ugid_t &ugid_,
|
||||
const Branches &branches_,
|
||||
const fs::path &fusepath_,
|
||||
const mode_t mode_,
|
||||
const dev_t dev_,
|
||||
const mode_t umask_)
|
||||
{
|
||||
return -EIO;
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
#include "func_mknod_base.hpp"
|
||||
|
||||
#include <string_view>
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class MknodMFS : public MknodBase
|
||||
{
|
||||
public:
|
||||
MknodMFS() {}
|
||||
~MknodMFS() {}
|
||||
|
||||
public:
|
||||
std::string_view name() const;
|
||||
|
||||
public:
|
||||
int operator()(const ugid_t &ugid,
|
||||
const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
const mode_t mode,
|
||||
const dev_t dev,
|
||||
const mode_t umask);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_open_base.hpp"
|
||||
#include "func_open_factory.hpp"
|
||||
|
||||
#include "func_wrapper.hpp"
|
||||
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
using Open = FuncWrapper<Func2::OpenBase,
|
||||
Func2::OpenFactory,
|
||||
int,
|
||||
const Branches&,
|
||||
const fs::path&,
|
||||
const mode_t&>;
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
#pragma once
|
||||
|
||||
#include "branches.hpp"
|
||||
|
||||
#include "fs_path.hpp"
|
||||
|
||||
#include <sys/types.h>
|
||||
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class OpenBase
|
||||
{
|
||||
public:
|
||||
OpenBase() {}
|
||||
~OpenBase() {}
|
||||
|
||||
public:
|
||||
virtual std::string_view name() const = 0;
|
||||
|
||||
public:
|
||||
virtual int operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
const mode_t mode) = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "func_open_factory.hpp"
|
||||
|
||||
#include "func_open_ff.hpp"
|
||||
|
||||
#include "policies.hpp"
|
||||
|
||||
|
||||
bool
|
||||
Func2::OpenFactory::valid(const std::string str_)
|
||||
{
|
||||
if(str_ == "ff")
|
||||
return true;
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<Func2::OpenBase>
|
||||
Func2::OpenFactory::make(const std::string_view str_)
|
||||
{
|
||||
if(str_ == "ff")
|
||||
return std::make_shared<Func2::OpenFF>();
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return std::make_shared<Func2::OpenFF>();
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_open_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class OpenFactory
|
||||
{
|
||||
public:
|
||||
static bool valid(const std::string str);
|
||||
static std::shared_ptr<OpenBase> make(const std::string_view str);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
#include "func_open_ff.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs_open.hpp"
|
||||
|
||||
|
||||
std::string_view
|
||||
Func2::OpenFF::name() const
|
||||
{
|
||||
return "ff";
|
||||
}
|
||||
|
||||
int
|
||||
Func2::OpenFF::operator()(const Branches &branches_,
|
||||
const fs::path &fusepath_,
|
||||
const mode_t mode_)
|
||||
{
|
||||
Err err;
|
||||
fs::path fullpath;
|
||||
|
||||
for(const auto &branch : branches_)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "func_open_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class OpenFF : public OpenBase
|
||||
{
|
||||
public:
|
||||
OpenFF() {}
|
||||
~OpenFF() {}
|
||||
|
||||
public:
|
||||
std::string_view name() const;
|
||||
|
||||
public:
|
||||
int operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
const mode_t mode);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_readlink_base.hpp"
|
||||
#include "func_readlink_factory.hpp"
|
||||
|
||||
#include "func_wrapper.hpp"
|
||||
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
using Readlink = FuncWrapper<Func2::ReadlinkBase,
|
||||
Func2::ReadlinkFactory,
|
||||
int,
|
||||
const Branches&,
|
||||
const fs::path&,
|
||||
char *&,
|
||||
const size_t&,
|
||||
const time_t&>;
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
#pragma once
|
||||
|
||||
#include "branches.hpp"
|
||||
|
||||
#include "fs_path.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class ReadlinkBase
|
||||
{
|
||||
public:
|
||||
ReadlinkBase() {}
|
||||
~ReadlinkBase() {}
|
||||
|
||||
public:
|
||||
virtual std::string_view name() const = 0;
|
||||
|
||||
public:
|
||||
virtual int operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
char *buf,
|
||||
const size_t bufsize,
|
||||
const time_t symlinkify_timeout) = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "func_readlink_factory.hpp"
|
||||
|
||||
#include "func_readlink_ff.hpp"
|
||||
|
||||
#include "policies.hpp"
|
||||
|
||||
|
||||
bool
|
||||
Func2::ReadlinkFactory::valid(const std::string str_)
|
||||
{
|
||||
if(str_ == "ff")
|
||||
return true;
|
||||
|
||||
if(Policies::Search::find(str_))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<Func2::ReadlinkBase>
|
||||
Func2::ReadlinkFactory::make(const std::string_view str_)
|
||||
{
|
||||
if(str_ == "ff")
|
||||
return std::make_shared<Func2::ReadlinkFF>();
|
||||
|
||||
if(Policies::Search::find(str_))
|
||||
return std::make_shared<Func2::ReadlinkFF>();
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_readlink_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class ReadlinkFactory
|
||||
{
|
||||
public:
|
||||
static bool valid(const std::string str);
|
||||
static std::shared_ptr<ReadlinkBase> make(const std::string_view str);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
#include "func_readlink_ff.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs_readlink.hpp"
|
||||
#include "fs_lstat.hpp"
|
||||
#include "symlinkify.hpp"
|
||||
|
||||
#include <cstring>
|
||||
|
||||
|
||||
std::string_view
|
||||
Func2::ReadlinkFF::name() const
|
||||
{
|
||||
return "ff";
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_readlink_symlinkify(const Branches &branches_,
|
||||
const fs::path &fusepath_,
|
||||
char *buf_,
|
||||
const size_t bufsize_,
|
||||
const time_t symlinkify_timeout_)
|
||||
{
|
||||
int rv;
|
||||
Err err;
|
||||
struct stat st;
|
||||
fs::path fullpath;
|
||||
|
||||
for(const auto &branch : branches_)
|
||||
{
|
||||
fullpath = branch.path / fusepath_;
|
||||
|
||||
err = rv = fs::lstat(fullpath,&st);
|
||||
if(rv < 0)
|
||||
continue;
|
||||
|
||||
if(not symlinkify::can_be_symlink(st,symlinkify_timeout_))
|
||||
{
|
||||
err = rv = fs::readlink(fusepath_,buf_,bufsize_);
|
||||
if(rv < 0)
|
||||
continue;
|
||||
|
||||
buf_[rv] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
strncpy(buf_,fullpath.c_str(),bufsize_);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_readlink(const Branches &branches_,
|
||||
const fs::path &fusepath_,
|
||||
char *buf_,
|
||||
const size_t bufsize_)
|
||||
{
|
||||
int rv;
|
||||
Err err;
|
||||
fs::path fullpath;
|
||||
|
||||
for(const auto &branch : branches_)
|
||||
{
|
||||
fullpath = branch.path / fusepath_;
|
||||
|
||||
err = rv = fs::readlink(fusepath_,buf_,bufsize_);
|
||||
if(rv < 0)
|
||||
continue;
|
||||
|
||||
buf_[rv] = '\0';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
|
||||
|
||||
int
|
||||
Func2::ReadlinkFF::operator()(const Branches &branches_,
|
||||
const fs::path &fusepath_,
|
||||
char *buf_,
|
||||
const size_t bufsize_,
|
||||
const time_t symlinkify_timeout_)
|
||||
{
|
||||
if(symlinkify_timeout_ > 0)
|
||||
return ::_readlink_symlinkify(branches_,
|
||||
fusepath_,
|
||||
buf_,
|
||||
bufsize_,
|
||||
symlinkify_timeout_);
|
||||
|
||||
return ::_readlink(branches_,
|
||||
fusepath_,
|
||||
buf_,
|
||||
bufsize_);
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
#include "func_readlink_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class ReadlinkFF : public ReadlinkBase
|
||||
{
|
||||
public:
|
||||
ReadlinkFF() {}
|
||||
~ReadlinkFF() {}
|
||||
|
||||
public:
|
||||
std::string_view name() const;
|
||||
|
||||
public:
|
||||
int operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
char *buf,
|
||||
const size_t bufsize,
|
||||
const time_t symlinkify_timeout);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_removexattr_base.hpp"
|
||||
#include "func_removexattr_factory.hpp"
|
||||
|
||||
#include "func_wrapper.hpp"
|
||||
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
using Removexattr = FuncWrapper<Func2::RemovexattrBase,
|
||||
Func2::RemovexattrFactory,
|
||||
int,
|
||||
const Branches&,
|
||||
const fs::path&,
|
||||
const char*&>;
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
#include "func_removexattr_all.hpp"
|
||||
|
||||
#include "error.hpp"
|
||||
#include "fs_lremovexattr.hpp"
|
||||
|
||||
|
||||
std::string_view
|
||||
Func2::RemovexattrAll::name() const
|
||||
{
|
||||
return "all";
|
||||
}
|
||||
|
||||
int
|
||||
Func2::RemovexattrAll::operator()(const Branches &branches_,
|
||||
const fs::path &fusepath_,
|
||||
const char *attrname_)
|
||||
{
|
||||
Err err;
|
||||
fs::path fullpath;
|
||||
|
||||
for(const auto &branch : branches_)
|
||||
{
|
||||
if(branch.ro())
|
||||
{
|
||||
err = -EROFS;
|
||||
continue;
|
||||
}
|
||||
|
||||
fullpath = branch.path / fusepath_;
|
||||
|
||||
err = fs::lremovexattr(fullpath,attrname_);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
#include "func_removexattr_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class RemovexattrAll : public RemovexattrBase
|
||||
{
|
||||
public:
|
||||
RemovexattrAll() {}
|
||||
~RemovexattrAll() {}
|
||||
|
||||
public:
|
||||
std::string_view name() const;
|
||||
|
||||
public:
|
||||
int operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
const char *attrname);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
#pragma once
|
||||
|
||||
#include "branches.hpp"
|
||||
|
||||
#include "fs_path.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class RemovexattrBase
|
||||
{
|
||||
public:
|
||||
RemovexattrBase() {}
|
||||
~RemovexattrBase() {}
|
||||
|
||||
public:
|
||||
virtual std::string_view name() const = 0;
|
||||
|
||||
public:
|
||||
virtual int operator()(const Branches &branches,
|
||||
const fs::path &fusepath,
|
||||
const char *attrname) = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "func_removexattr_factory.hpp"
|
||||
|
||||
#include "func_removexattr_all.hpp"
|
||||
|
||||
#include "policies.hpp"
|
||||
|
||||
|
||||
bool
|
||||
Func2::RemovexattrFactory::valid(const std::string str_)
|
||||
{
|
||||
if(str_ == "all")
|
||||
return true;
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<Func2::RemovexattrBase>
|
||||
Func2::RemovexattrFactory::make(const std::string_view str_)
|
||||
{
|
||||
if(str_ == "all")
|
||||
return std::make_shared<Func2::RemovexattrAll>();
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return std::make_shared<Func2::RemovexattrAll>();
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_removexattr_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class RemovexattrFactory
|
||||
{
|
||||
public:
|
||||
static bool valid(const std::string str);
|
||||
static std::shared_ptr<RemovexattrBase> make(const std::string_view str);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_rmdir_base.hpp"
|
||||
#include "func_rmdir_factory.hpp"
|
||||
|
||||
#include "func_wrapper.hpp"
|
||||
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
using Rmdir = FuncWrapper<Func2::RmdirBase,
|
||||
Func2::RmdirFactory,
|
||||
int,
|
||||
const Branches&,
|
||||
const fs::path&>;
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
#include "func_rmdir_all.hpp"
|
||||
|
||||
#include "config.hpp"
|
||||
#include "error.hpp"
|
||||
#include "fs_rmdir.hpp"
|
||||
#include "fs_unlink.hpp"
|
||||
|
||||
|
||||
std::string_view
|
||||
Func2::RmdirAll::name() const
|
||||
{
|
||||
return "all";
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_should_unlink(int rv_)
|
||||
|
||||
{
|
||||
return ((rv_ == -ENOTDIR) &&
|
||||
(cfg.follow_symlinks != FollowSymlinks::ENUM::NEVER));
|
||||
}
|
||||
|
||||
int
|
||||
Func2::RmdirAll::operator()(const Branches &branches_,
|
||||
const fs::path &fusepath_)
|
||||
{
|
||||
int rv;
|
||||
Err err;
|
||||
fs::path fullpath;
|
||||
|
||||
for(const auto &branch : branches_)
|
||||
{
|
||||
if(branch.ro())
|
||||
{
|
||||
err = -EROFS;
|
||||
continue;
|
||||
}
|
||||
|
||||
fullpath = branch.path / fusepath_;
|
||||
|
||||
rv = fs::rmdir(fullpath);
|
||||
if(::_should_unlink(rv))
|
||||
rv = fs::unlink(fullpath);
|
||||
err = rv;
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
#include "func_rmdir_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class RmdirAll : public RmdirBase
|
||||
{
|
||||
public:
|
||||
RmdirAll() {}
|
||||
~RmdirAll() {}
|
||||
|
||||
public:
|
||||
std::string_view name() const;
|
||||
|
||||
public:
|
||||
int operator()(const Branches &branches,
|
||||
const fs::path &fusepath);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
#pragma once
|
||||
|
||||
#include "branches.hpp"
|
||||
|
||||
#include "fs_path.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class RmdirBase
|
||||
{
|
||||
public:
|
||||
RmdirBase() {}
|
||||
~RmdirBase() {}
|
||||
|
||||
public:
|
||||
virtual std::string_view name() const = 0;
|
||||
|
||||
public:
|
||||
virtual int operator()(const Branches &branches,
|
||||
const fs::path &fusepath) = 0;
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
#include "func_rmdir_factory.hpp"
|
||||
|
||||
#include "func_rmdir_all.hpp"
|
||||
|
||||
#include "policies.hpp"
|
||||
|
||||
|
||||
bool
|
||||
Func2::RmdirFactory::valid(const std::string str_)
|
||||
{
|
||||
if(str_ == "all")
|
||||
return true;
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::shared_ptr<Func2::RmdirBase>
|
||||
Func2::RmdirFactory::make(const std::string_view str_)
|
||||
{
|
||||
if(str_ == "all")
|
||||
return std::make_shared<Func2::RmdirAll>();
|
||||
|
||||
if(Policies::Action::find(str_))
|
||||
return std::make_shared<Func2::RmdirAll>();
|
||||
|
||||
return {};
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_rmdir_base.hpp"
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
class RmdirFactory
|
||||
{
|
||||
public:
|
||||
static bool valid(const std::string str);
|
||||
static std::shared_ptr<RmdirBase> make(const std::string_view str);
|
||||
};
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
#pragma once
|
||||
|
||||
#include "func_setxattr_base.hpp"
|
||||
#include "func_setxattr_factory.hpp"
|
||||
|
||||
#include "func_wrapper.hpp"
|
||||
|
||||
|
||||
namespace Func2
|
||||
{
|
||||
using Setxattr = FuncWrapper<Func2::SetxattrBase,
|
||||
Func2::SetxattrFactory,
|
||||
int,
|
||||
const Branches&,
|
||||
const fs::path&,
|
||||
const char*&,
|
||||
const char*&,
|
||||
const size_t&,
|
||||
const int&>;
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user