Compare commits

...
98 Commits
Author SHA1 Message Date
Antonio SJ Musumeci 8bd3726cf8 fs_mknod_as.hpp 2025-12-29 20:20:28 -06:00
Antonio SJ Musumeci 18b72049a4 fs_mknod_as.hpp 2025-12-29 20:20:10 -06:00
Antonio SJ Musumeci 2f91276333 func_mknod_mfs.cpp 2025-12-29 20:18:27 -06:00
Antonio SJ Musumeci 7c1bea4757 func_mknod_mfs.cpp 2025-12-29 20:17:49 -06:00
Antonio SJ Musumeci 14f775a302 func_mknod_mfs.hpp 2025-12-29 20:17:20 -06:00
Antonio SJ Musumeci 4622bc8160 func_mknod_ff.hpp 2025-12-29 20:17:02 -06:00
Antonio SJ Musumeci 5176458c7b func_mknod.hpp 2025-12-29 20:16:20 -06:00
Antonio SJ Musumeci 06256e1120 func_mknod_base.hpp 2025-12-29 20:15:58 -06:00
Antonio SJ Musumeci ab27265347 func_mknod_base.hpp 2025-12-29 20:15:54 -06:00
Antonio SJ Musumeci 13b4bf4649 func_mknod_ff.cpp 2025-12-29 20:15:02 -06:00
Antonio SJ Musumeci dc5c7e95a6 func_mknod_ff.cpp 2025-12-29 20:14:50 -06:00
Antonio SJ Musumeci ef825e0ff6 func_mknod_ff.cpp 2025-12-29 20:14:32 -06:00
Antonio SJ Musumeci 557a02115c func_mknod_ff.cpp 2025-12-29 20:14:27 -06:00
Antonio SJ Musumeci 73c9d86481 func_mknod_ff.cpp 2025-12-29 20:14:06 -06:00
Antonio SJ Musumeci 7ba1b8f332 fs_mknod_as.hpp 2025-12-29 20:13:54 -06:00
Antonio SJ Musumeci 31470ee458 fs_mknod_as.hpp 2025-12-29 20:13:53 -06:00
Antonio SJ Musumeci 0ef62afcbf fs_mknod_as.hpp 2025-12-29 20:13:52 -06:00
Antonio SJ Musumeci 2cd64960e3 fs_mknod_as.hpp 2025-12-29 20:13:50 -06:00
Antonio SJ Musumeci fb534e5aba fs_mknod_as.hpp 2025-12-29 20:13:28 -06:00
Antonio SJ Musumeci 6e4b618376 fs_mknod_as.hpp 2025-12-29 20:13:00 -06:00
Antonio SJ Musumeci 802f9a0eaf fs_mknod_as.hpp 2025-12-29 20:12:53 -06:00
Antonio SJ Musumeci 04f2068adf fs_mknod_as.hpp 2025-12-29 20:11:58 -06:00
Antonio SJ Musumeci d36688c752 func_mknod_ff.cpp 2025-12-29 20:07:18 -06:00
Antonio SJ Musumeci e0cf997312 fuse_mknod.cpp 2025-12-29 20:03:43 -06:00
Antonio SJ Musumeci 999b774dcb tests.cpp 2025-12-29 19:53:22 -06:00
Antonio SJ Musumeci c0252fa5e6 tests.cpp 2025-12-29 19:52:57 -06:00
Antonio SJ Musumeci 50caf408f6 tests.cpp 2025-12-29 19:52:56 -06:00
Antonio SJ Musumeci 2fcd019f30 tests.cpp 2025-12-29 19:48:45 -06:00
Antonio SJ Musumeci 3fed8a12db tests.cpp 2025-12-29 19:48:27 -06:00
Antonio SJ Musumeci 17f7df7b3e tests.cpp 2025-12-29 19:48:14 -06:00
Antonio SJ Musumeci 0b552d11f8 func_mknod_ff.cpp 2025-12-29 19:45:25 -06:00
Antonio SJ Musumeci c59c79f92c func_mknod_ff.cpp 2025-12-29 19:45:21 -06:00
Antonio SJ Musumeci 2e1d028516 tests.cpp 2025-12-29 19:40:47 -06:00
Antonio SJ Musumeci 316c971e6f fs_xattr.cpp 2025-12-29 19:35:50 -06:00
Antonio SJ Musumeci ee4a8a18ac fs_xattr.cpp 2025-12-29 19:32:21 -06:00
Antonio SJ Musumeci 4675d8045b tests.cpp 2025-12-29 19:24:45 -06:00
Antonio SJ Musumeci 72fde7def8 tests.cpp 2025-12-29 19:22:24 -06:00
Antonio SJ Musumeci 7e8e279ed3 tests.cpp 2025-12-29 19:21:59 -06:00
Antonio SJ Musumeci b021e73752 tests.cpp 2025-12-29 19:21:53 -06:00
Antonio SJ Musumeci 06f0d1b2d8 tests.cpp 2025-12-29 19:21:30 -06:00
Antonio SJ Musumeci 7eeee57043 tests.cpp 2025-12-29 19:20:47 -06:00
Antonio SJ Musumeci 21b8e376be tests.cpp 2025-12-29 19:16:35 -06:00
Antonio SJ Musumeci 353a5f7103 tests.cpp 2025-12-29 19:16:34 -06:00
Antonio SJ Musumeci a863981746 tests.cpp 2025-12-29 19:15:48 -06:00
Antonio SJ Musumeci 71a939112d tests.cpp 2025-12-29 19:15:17 -06:00
Antonio SJ Musumeci 882634fa38 tests.cpp 2025-12-29 19:14:31 -06:00
Antonio SJ Musumeci 03a28d3ebe tests.cpp 2025-12-29 19:14:20 -06:00
Antonio SJ Musumeci 6e5b4aa40f tests.cpp 2025-12-29 19:14:03 -06:00
Antonio SJ Musumeci 28c36aea0e func_mknod_ff.cpp 2025-12-29 19:12:25 -06:00
Antonio SJ Musumeci bcb45b917d func_mknod_ff.cpp 2025-12-29 19:11:51 -06:00
Antonio SJ Musumeci 59bec051fc func_mknod_ff.cpp 2025-12-29 19:10:43 -06:00
Antonio SJ Musumeci 9dba189b90 func_mknod_ff.cpp 2025-12-29 19:10:23 -06:00
Antonio SJ Musumeci e8289f2cbe func_mknod_ff.cpp 2025-12-29 19:09:42 -06:00
Antonio SJ Musumeci ea88c8ac56 func_mknod_ff.cpp 2025-12-29 19:09:36 -06:00
Antonio SJ Musumeci 2c177ddaeb func_mknod_ff.cpp 2025-12-29 18:12:27 -06:00
Antonio SJ Musumeci bb674484b1 func_mknod_ff.cpp 2025-12-29 18:12:09 -06:00
Antonio SJ Musumeci 3f0ec90891 func_mknod_ff.cpp 2025-12-29 18:11:58 -06:00
Antonio SJ Musumeci 2338e7d8a9 func_mknod_ff.cpp 2025-12-29 18:10:56 -06:00
Antonio SJ Musumeci 8ec2d01d59 func_mknod_ff.cpp 2025-12-29 18:10:53 -06:00
Antonio SJ Musumeci 4996628e7f func_mknod_ff.cpp 2025-12-29 18:10:47 -06:00
Antonio SJ Musumeci 3c96b138f0 func_mknod_ff.cpp 2025-12-29 18:10:43 -06:00
Antonio SJ Musumeci 4d81f824a4 func_mknod_ff.cpp 2025-12-29 18:10:37 -06:00
Antonio SJ Musumeci d90763fcd2 func_mknod_ff.cpp 2025-12-29 18:10:30 -06:00
Antonio SJ Musumeci b3100540c6 func_mknod_ff.cpp 2025-12-29 18:10:02 -06:00
Antonio SJ Musumeci 5db592d4db func_mknod_ff.cpp 2025-12-29 18:09:57 -06:00
Antonio SJ Musumeci 695b1042f9 func_mknod_ff.cpp 2025-12-29 18:09:16 -06:00
Antonio SJ Musumeci fe4c7faf4b func_mknod_ff.cpp 2025-12-29 18:09:12 -06:00
Antonio SJ Musumeci da13bdff15 func_mknod_ff.cpp 2025-12-29 18:09:12 -06:00
Antonio SJ Musumeci 5b478446aa func_mknod_ff.cpp 2025-12-29 18:09:10 -06:00
Antonio SJ Musumeci a376263d43 func_mknod_ff.cpp 2025-12-29 18:08:30 -06:00
Antonio SJ Musumeci a0e10d7638 func_mknod_ff.cpp 2025-12-29 18:06:26 -06:00
Antonio SJ Musumeci f5bb8f6c60 func_mknod_ff.cpp 2025-12-29 18:06:21 -06:00
Antonio SJ Musumeci 266a936208 func_mknod_ff.cpp 2025-12-29 18:06:16 -06:00
Antonio SJ Musumeci 15dd1cae2b func_mknod_ff.cpp 2025-12-29 18:06:08 -06:00
Antonio SJ Musumeci 867fb8ef46 func_mknod_ff.cpp 2025-12-29 18:06:05 -06:00
Antonio SJ Musumeci b33a72ca5c func_mknod_ff.cpp 2025-12-29 13:48:50 -06:00
Antonio SJ Musumeci 2fa854dcc3 func_mknod_ff.cpp 2025-12-29 13:48:40 -06:00
Antonio SJ Musumeci 03145a0789 func_mknod_ff.cpp 2025-12-29 13:48:35 -06:00
Antonio SJ Musumeci a2638a98b0 func_mknod_ff.cpp 2025-12-29 11:35:20 -06:00
Antonio SJ Musumeci 8188b13d73 func_mknod_ff.cpp 2025-12-29 11:25:40 -06:00
Antonio SJ Musumeci 46d3297d5e func_mknod_ff.cpp 2025-12-29 11:25:10 -06:00
Antonio SJ Musumeci 51af59ee59 func_mknod_ff.cpp 2025-12-29 11:25:07 -06:00
Antonio SJ Musumeci 8a961d56d9 func_mknod_ff.cpp 2025-12-29 11:24:54 -06:00
Antonio SJ Musumeci 2166f3537b func_mknod_ff.cpp 2025-12-29 11:24:08 -06:00
Antonio SJ Musumeci 8e0e88cd34 func_mknod_ff.cpp 2025-12-29 11:21:02 -06:00
Antonio SJ Musumeci 02cb3e2242 func_mknod_ff.cpp 2025-12-29 11:20:56 -06:00
Antonio SJ Musumeci 4b02d1c6c0 func_mknod_ff.cpp 2025-12-29 11:20:54 -06:00
Antonio SJ Musumeci 89bbd38ef2 func_mknod_ff.cpp 2025-12-29 11:20:50 -06:00
Antonio SJ Musumeci 4b8d68fb03 func_mknod_ff.cpp 2025-12-29 11:12:19 -06:00
Antonio SJ Musumeci 234f534204 fuse_mknod.cpp 2025-12-29 11:00:37 -06:00
Antonio SJ Musumeci 08b11ea09d fuse_mknod.cpp 2025-12-29 11:00:36 -06:00
Antonio SJ Musumeci 1b1d46a35c fuse_mknod.cpp 2025-12-29 11:00:32 -06:00
Antonio SJ Musumeci 07db8d2ee9 fuse_mknod.cpp 2025-12-29 11:00:03 -06:00
Antonio SJ Musumeci 332ca520aa fuse_mknod.cpp 2025-12-29 10:59:57 -06:00
Antonio SJ Musumeci e18fcc5714 fuse_mknod.cpp 2025-12-29 10:59:46 -06:00
Antonio SJ Musumeci d818892b93 fuse_mknod.cpp 2025-12-29 10:59:35 -06:00
Antonio SJ Musumeci 8ab6bcf554 checkpoint 2025-12-29 10:58:37 -06:00
Antonio SJ Musumeci b3b8e793f9 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.
2025-12-27 22:14:56 -06:00
156 changed files with 4091 additions and 1336 deletions
+45 -32
View File
@@ -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_,
+1
View File
@@ -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);
+2
View File
@@ -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;
+108
View File
@@ -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)...);
}
};
-11
View File
@@ -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
View File
@@ -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;
+34
View File
@@ -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;
+1 -7
View File
@@ -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;
+41
View File
@@ -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
View File
@@ -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;
}
};
+9
View File
@@ -0,0 +1,9 @@
#pragma once
enum class FollowSymlinksEnum
{
NEVER,
DIRECTORY,
REGULAR,
ALL
};
+5 -14
View File
@@ -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
View File
@@ -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);
View File
+55 -6
View File
@@ -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
View File
@@ -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
View File
@@ -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);
+36
View File
@@ -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;
}
+54
View File
@@ -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;
};
+16
View File
@@ -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&>;
}
+31
View File
@@ -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;
}
+19
View File
@@ -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);
};
}
+24
View File
@@ -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;
};
}
+30
View File
@@ -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 {};
}
+13
View File
@@ -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);
};
}
+17
View File
@@ -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&>;
}
+35
View File
@@ -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;
}
+19
View File
@@ -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);
};
}
+26
View File
@@ -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;
};
}
+30
View File
@@ -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 {};
}
+13
View File
@@ -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);
};
}
+18
View File
@@ -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&>;
}
+36
View File
@@ -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;
}
+20
View File
@@ -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);
};
}
+27
View File
@@ -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;
};
}
+30
View File
@@ -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 {};
}
+13
View File
@@ -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);
};
}
+19
View File
@@ -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&>;
}
+35
View File
@@ -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;
};
}
+74
View File
@@ -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;
}
+21
View File
@@ -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);
};
}
+78
View File
@@ -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;
}
+21
View File
@@ -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);
};
}
+44
View File
@@ -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 {};
}
+13
View File
@@ -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);
};
}
+44
View File
@@ -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;
}
+23
View File
@@ -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);
};
}
+59
View File
@@ -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;
}
+21
View File
@@ -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);
};
}
+19
View File
@@ -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&>;
}
+25
View File
@@ -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;
};
}
+30
View File
@@ -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 {};
}
+13
View File
@@ -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);
};
}
+35
View File
@@ -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;
}
+21
View File
@@ -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);
};
}
+16
View File
@@ -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&>;
}
+22
View File
@@ -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;
};
}
+30
View File
@@ -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 {};
}
+13
View File
@@ -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);
};
}
+25
View File
@@ -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;
}
+18
View File
@@ -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);
};
}
+18
View File
@@ -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&>;
}
+24
View File
@@ -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;
};
}
+30
View File
@@ -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 {};
}
+13
View File
@@ -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);
};
}
+53
View File
@@ -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_);
}
+20
View File
@@ -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);
};
}
+19
View File
@@ -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&>;
}
+28
View File
@@ -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;
};
}
+26
View File
@@ -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 {};
}
+17
View File
@@ -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_);
};
}
+73
View File
@@ -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;
}
+24
View File
@@ -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);
};
}
+28
View File
@@ -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;
}
+24
View File
@@ -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);
};
}
+17
View File
@@ -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&>;
}
+26
View File
@@ -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;
};
}
+30
View File
@@ -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 {};
}
+13
View File
@@ -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);
};
}
+27
View File
@@ -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;
}
+19
View File
@@ -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);
};
}
+19
View File
@@ -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&>;
}
+25
View File
@@ -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;
};
}
+30
View File
@@ -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 {};
}
+13
View File
@@ -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);
};
}
+104
View File
@@ -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_);
}
+21
View File
@@ -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);
};
}
+17
View File
@@ -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*&>;
}
+35
View File
@@ -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;
}
+19
View File
@@ -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);
};
}
+23
View File
@@ -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;
};
}
+30
View File
@@ -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 {};
}
+13
View File
@@ -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);
};
}
+16
View File
@@ -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&>;
}
+49
View File
@@ -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;
}
+18
View File
@@ -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);
};
}
+22
View File
@@ -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;
};
}
+30
View File
@@ -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 {};
}
+13
View File
@@ -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);
};
}
+20
View File
@@ -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