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