mirror of https://github.com/trapexit/mergerfs.git
11 changed files with 348 additions and 18 deletions
-
2src/config.cpp
-
2src/config.hpp
-
19src/func_mknod.hpp
-
28src/func_mknod_base.hpp
-
26src/func_mknod_factory.cpp
-
17src/func_mknod_factory.hpp
-
94src/func_mknod_ff.cpp
-
24src/func_mknod_ff.hpp
-
99src/func_mknod_mfs.cpp
-
24src/func_mknod_mfs.hpp
-
31src/fuse_mknod.cpp
@ -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 mode_t&, |
||||
|
const dev_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 mode_t umask, |
||||
|
const dev_t dev) = 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,94 @@ |
|||||
|
#include "func_mknod_ff.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::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 mode_t umask_, |
||||
|
const dev_t dev_) |
||||
|
{ |
||||
|
int rv; |
||||
|
fs::path fusedirpath; |
||||
|
mode_t umask; |
||||
|
|
||||
|
fusedirpath = fusepath_.parent_path(); |
||||
|
umask = 0; // TODO: get actual umask
|
||||
|
|
||||
|
// Find first branch with the directory
|
||||
|
const Branch *existing_branch = nullptr; |
||||
|
for(const auto &branch : branches_) |
||||
|
{ |
||||
|
if(fs::exists(branch.path / fusedirpath)) |
||||
|
{ |
||||
|
existing_branch = &branch; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if(!existing_branch) |
||||
|
return -ENOENT; |
||||
|
|
||||
|
// Find first branch for creation
|
||||
|
const Branch *create_branch = nullptr; |
||||
|
for(const auto &branch : branches_) |
||||
|
{ |
||||
|
if(branch.ro_or_nc()) |
||||
|
continue; |
||||
|
|
||||
|
fs::info_t info; |
||||
|
rv = fs::info(branch.path, &info); |
||||
|
if(rv < 0) |
||||
|
continue; |
||||
|
|
||||
|
if(info.readonly) |
||||
|
continue; |
||||
|
|
||||
|
if(info.spaceavail < branch.minfreespace()) |
||||
|
continue; |
||||
|
|
||||
|
create_branch = &branch; |
||||
|
break; |
||||
|
} |
||||
|
|
||||
|
if(!create_branch) |
||||
|
return -ENOSPC; |
||||
|
|
||||
|
// Clone path if needed
|
||||
|
if(existing_branch != create_branch) |
||||
|
{ |
||||
|
rv = fs::clonepath(existing_branch->path, |
||||
|
create_branch->path, |
||||
|
fusedirpath); |
||||
|
if(rv < 0) |
||||
|
return rv; |
||||
|
} |
||||
|
|
||||
|
// Create the node
|
||||
|
fs::path fullpath = create_branch->path / fusepath_; |
||||
|
if(!fs::acl::dir_has_defaults(fullpath)) |
||||
|
{ |
||||
|
mode_t mode = mode_ & ~umask_; |
||||
|
return fs::mknod_as(ugid_, fullpath, mode, dev_); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return fs::mknod_as(ugid_, fullpath, mode_, dev_); |
||||
|
} |
||||
|
} |
||||
@ -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 mode_t umask, |
||||
|
const dev_t dev); |
||||
|
}; |
||||
|
} |
||||
@ -0,0 +1,99 @@ |
|||||
|
#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 mode_t umask_, |
||||
|
const dev_t dev_) |
||||
|
{ |
||||
|
int rv; |
||||
|
fs::path fusedirpath; |
||||
|
mode_t umask; |
||||
|
|
||||
|
fusedirpath = fusepath_.parent_path(); |
||||
|
umask = 0; // TODO: get actual umask
|
||||
|
|
||||
|
// Find first branch with the directory
|
||||
|
const Branch *existing_branch = nullptr; |
||||
|
for(const auto &branch : branches_) |
||||
|
{ |
||||
|
if(fs::exists(branch.path / fusedirpath)) |
||||
|
{ |
||||
|
existing_branch = &branch; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if(!existing_branch) |
||||
|
return -ENOENT; |
||||
|
|
||||
|
// Find branch with most free space for creation
|
||||
|
const Branch *create_branch = nullptr; |
||||
|
uint64_t max_space = 0; |
||||
|
|
||||
|
for(const auto &branch : branches_) |
||||
|
{ |
||||
|
if(branch.ro_or_nc()) |
||||
|
continue; |
||||
|
|
||||
|
fs::info_t info; |
||||
|
rv = fs::info(branch.path, &info); |
||||
|
if(rv < 0) |
||||
|
continue; |
||||
|
|
||||
|
if(info.readonly) |
||||
|
continue; |
||||
|
|
||||
|
if(info.spaceavail < branch.minfreespace()) |
||||
|
continue; |
||||
|
|
||||
|
if(info.spaceavail > max_space) |
||||
|
{ |
||||
|
max_space = info.spaceavail; |
||||
|
create_branch = &branch; |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
if(!create_branch) |
||||
|
return -ENOSPC; |
||||
|
|
||||
|
// Clone path if needed
|
||||
|
if(existing_branch != create_branch) |
||||
|
{ |
||||
|
rv = fs::clonepath(existing_branch->path, |
||||
|
create_branch->path, |
||||
|
fusedirpath); |
||||
|
if(rv < 0) |
||||
|
return rv; |
||||
|
} |
||||
|
|
||||
|
// Create the node
|
||||
|
fs::path fullpath = create_branch->path / fusepath_; |
||||
|
if(!fs::acl::dir_has_defaults(fullpath)) |
||||
|
{ |
||||
|
mode_t mode = mode_ & ~umask_; |
||||
|
return fs::mknod_as(ugid_, fullpath, mode, dev_); |
||||
|
} |
||||
|
else |
||||
|
{ |
||||
|
return fs::mknod_as(ugid_, fullpath, mode_, dev_); |
||||
|
} |
||||
|
} |
||||
@ -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 mode_t umask, |
||||
|
const dev_t dev); |
||||
|
}; |
||||
|
} |
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue