mirror of https://github.com/trapexit/mergerfs.git
Browse Source
add tagging branches RW/RO/NW
add tagging branches RW/RO/NW
This allows users to tag a branch as readonly or not for writing regardless of how the filesystem is mounted. Should simplify deployments and offer more flexibility.pull/527/head
Antonio SJ Musumeci
6 years ago
57 changed files with 1669 additions and 1293 deletions
-
64README.md
-
113man/mergerfs.1
-
8src/access.cpp
-
216src/branch.cpp
-
55src/branch.hpp
-
8src/chmod.cpp
-
8src/chown.cpp
-
8src/config.cpp
-
5src/config.hpp
-
10src/create.cpp
-
14src/fs.cpp
-
4src/fs.hpp
-
15src/fs_glob.cpp
-
2src/fs_glob.hpp
-
18src/fs_info.cpp
-
5src/fs_info.hpp
-
8src/getattr.cpp
-
33src/getxattr.cpp
-
8src/ioctl.cpp
-
32src/link.cpp
-
9src/listxattr.cpp
-
10src/mkdir.cpp
-
10src/mknod.cpp
-
8src/open.cpp
-
26src/option_parser.cpp
-
37src/policy.hpp
-
62src/policy_all.cpp
-
107src/policy_epall.cpp
-
119src/policy_epff.cpp
-
133src/policy_eplfs.cpp
-
133src/policy_eplus.cpp
-
133src/policy_epmfs.cpp
-
4src/policy_eprand.cpp
-
2src/policy_erofs.cpp
-
51src/policy_error.hpp
-
70src/policy_ff.cpp
-
2src/policy_invalid.cpp
-
96src/policy_lfs.cpp
-
95src/policy_lus.cpp
-
95src/policy_mfs.cpp
-
116src/policy_newest.cpp
-
4src/policy_rand.cpp
-
10src/readdir.cpp
-
8src/readlink.cpp
-
8src/removexattr.cpp
-
40src/rename.cpp
-
8src/rmdir.cpp
-
117src/setxattr.cpp
-
16src/statfs.cpp
-
12src/str.cpp
-
4src/str.hpp
-
10src/symlink.cpp
-
8src/truncate.cpp
-
8src/unlink.cpp
-
8src/utimens.cpp
-
16src/write.cpp
-
23src/write_buf.cpp
@ -0,0 +1,216 @@ |
|||
/*
|
|||
ISC License |
|||
|
|||
Copyright (c) 2018, Antonio SJ Musumeci <trapexit@spawn.link> |
|||
|
|||
Permission to use, copy, modify, and/or distribute this software for any |
|||
purpose with or without fee is hereby granted, provided that the above |
|||
copyright notice and this permission notice appear in all copies. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
*/ |
|||
|
|||
#include "branch.hpp"
|
|||
#include "fs.hpp"
|
|||
#include "fs_glob.hpp"
|
|||
#include "str.hpp"
|
|||
|
|||
#include <fnmatch.h>
|
|||
|
|||
#include <string>
|
|||
|
|||
using std::string; |
|||
using std::vector; |
|||
|
|||
bool |
|||
Branch::ro(void) const |
|||
{ |
|||
return (mode == Branch::RO); |
|||
} |
|||
|
|||
bool |
|||
Branch::ro_or_nw(void) const |
|||
{ |
|||
return ((mode == Branch::RO) || |
|||
(mode == Branch::NW)); |
|||
} |
|||
|
|||
string |
|||
Branches::to_string(const bool mode_) const |
|||
{ |
|||
string tmp; |
|||
|
|||
for(size_t i = 0; i < size(); i++) |
|||
{ |
|||
const Branch &branch = (*this)[i]; |
|||
|
|||
tmp += branch.path; |
|||
|
|||
if(mode_) |
|||
{ |
|||
tmp += '='; |
|||
switch(branch.mode) |
|||
{ |
|||
default: |
|||
case Branch::RW: |
|||
tmp += "RW"; |
|||
break; |
|||
case Branch::RO: |
|||
tmp += "RO"; |
|||
break; |
|||
case Branch::NW: |
|||
tmp += "NW"; |
|||
break; |
|||
} |
|||
} |
|||
|
|||
tmp += ':'; |
|||
} |
|||
|
|||
if(*tmp.rbegin() == ':') |
|||
tmp.erase(tmp.size() - 1); |
|||
|
|||
return tmp; |
|||
} |
|||
|
|||
void |
|||
Branches::to_paths(vector<string> &vec_) const |
|||
{ |
|||
for(size_t i = 0; i < size(); i++) |
|||
{ |
|||
const Branch &branch = (*this)[i]; |
|||
|
|||
vec_.push_back(branch.path); |
|||
} |
|||
} |
|||
|
|||
static |
|||
void |
|||
parse(const string &str_, |
|||
Branches &branches_) |
|||
{ |
|||
string str; |
|||
Branch branch; |
|||
vector<string> globbed; |
|||
|
|||
str = str_; |
|||
branch.mode = Branch::INVALID; |
|||
if(str::ends_with(str,"=RO")) |
|||
branch.mode = Branch::RO; |
|||
else if(str::ends_with(str,"=RW")) |
|||
branch.mode = Branch::RW; |
|||
else if(str::ends_with(str,"=NW")) |
|||
branch.mode = Branch::NW; |
|||
|
|||
if(branch.mode != Branch::INVALID) |
|||
str.resize(str.size() - 3); |
|||
else |
|||
branch.mode = Branch::RW; |
|||
|
|||
fs::glob(str,globbed); |
|||
fs::realpathize(globbed); |
|||
for(size_t i = 0; i < globbed.size(); i++) |
|||
{ |
|||
branch.path = globbed[i]; |
|||
branches_.push_back(branch); |
|||
} |
|||
} |
|||
|
|||
void |
|||
Branches::set(const std::string &str_) |
|||
{ |
|||
vector<string> paths; |
|||
|
|||
clear(); |
|||
|
|||
str::split(paths,str_,':'); |
|||
|
|||
for(size_t i = 0; i < paths.size(); i++) |
|||
{ |
|||
Branches branches; |
|||
|
|||
parse(paths[i],branches); |
|||
|
|||
insert(end(), |
|||
branches.begin(), |
|||
branches.end()); |
|||
} |
|||
} |
|||
|
|||
void |
|||
Branches::add_begin(const std::string &str_) |
|||
{ |
|||
vector<string> paths; |
|||
|
|||
str::split(paths,str_,':'); |
|||
|
|||
for(size_t i = 0; i < paths.size(); i++) |
|||
{ |
|||
Branches branches; |
|||
|
|||
parse(paths[i],branches); |
|||
|
|||
insert(begin(), |
|||
branches.begin(), |
|||
branches.end()); |
|||
} |
|||
} |
|||
|
|||
void |
|||
Branches::add_end(const std::string &str_) |
|||
{ |
|||
vector<string> paths; |
|||
|
|||
str::split(paths,str_,':'); |
|||
|
|||
for(size_t i = 0; i < paths.size(); i++) |
|||
{ |
|||
Branches branches; |
|||
|
|||
parse(paths[i],branches); |
|||
|
|||
insert(end(), |
|||
branches.begin(), |
|||
branches.end()); |
|||
} |
|||
} |
|||
|
|||
void |
|||
Branches::erase_begin(void) |
|||
{ |
|||
erase(begin()); |
|||
} |
|||
|
|||
void |
|||
Branches::erase_end(void) |
|||
{ |
|||
pop_back(); |
|||
} |
|||
|
|||
void |
|||
Branches::erase_fnmatch(const std::string &str_) |
|||
{ |
|||
vector<string> patterns; |
|||
|
|||
str::split(patterns,str_,':'); |
|||
|
|||
for(iterator i = begin(); i != end();) |
|||
{ |
|||
int match = FNM_NOMATCH; |
|||
|
|||
for(vector<string>::const_iterator pi = patterns.begin(); |
|||
pi != patterns.end() && match != 0; |
|||
++pi) |
|||
{ |
|||
match = ::fnmatch(pi->c_str(),i->path.c_str(),0); |
|||
} |
|||
|
|||
i = ((match == 0) ? erase(i) : (i+1)); |
|||
} |
|||
} |
@ -0,0 +1,55 @@ |
|||
/*
|
|||
ISC License |
|||
|
|||
Copyright (c) 2018, Antonio SJ Musumeci <trapexit@spawn.link> |
|||
|
|||
Permission to use, copy, modify, and/or distribute this software for any |
|||
purpose with or without fee is hereby granted, provided that the above |
|||
copyright notice and this permission notice appear in all copies. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
*/ |
|||
|
|||
#pragma once
|
|||
|
|||
#include <string>
|
|||
#include <vector>
|
|||
|
|||
struct Branch |
|||
{ |
|||
enum Mode |
|||
{ |
|||
INVALID, |
|||
RO, |
|||
RW, |
|||
NW |
|||
}; |
|||
|
|||
Mode mode; |
|||
std::string path; |
|||
|
|||
bool ro(void) const; |
|||
bool ro_or_nw(void) const; |
|||
}; |
|||
|
|||
class Branches : public std::vector<Branch> |
|||
{ |
|||
public: |
|||
std::string to_string(const bool mode_ = false) const; |
|||
|
|||
void to_paths(std::vector<std::string> &vec_) const; |
|||
|
|||
public: |
|||
void set(const std::string &str_); |
|||
void add_begin(const std::string &str_); |
|||
void add_end(const std::string &str_); |
|||
void erase_begin(void); |
|||
void erase_end(void); |
|||
void erase_fnmatch(const std::string &str_); |
|||
}; |
@ -0,0 +1,51 @@ |
|||
/*
|
|||
ISC License |
|||
|
|||
Copyright (c) 2018, Antonio SJ Musumeci <trapexit@spawn.link> |
|||
|
|||
Permission to use, copy, modify, and/or distribute this software for any |
|||
purpose with or without fee is hereby granted, provided that the above |
|||
copyright notice and this permission notice appear in all copies. |
|||
|
|||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
*/ |
|||
|
|||
#pragma once
|
|||
|
|||
#define error_and_continue(CUR,ERR) \
|
|||
{ \ |
|||
policy::calc_error(CUR,ERR); \ |
|||
continue; \ |
|||
} |
|||
|
|||
namespace policy |
|||
{ |
|||
static |
|||
inline |
|||
void |
|||
calc_error(int &cur_, |
|||
int err_) |
|||
{ |
|||
switch(cur_) |
|||
{ |
|||
default: |
|||
case ENOENT: |
|||
cur_ = err_; |
|||
break; |
|||
case ENOSPC: |
|||
if(err_ != ENOENT) |
|||
cur_ = err_; |
|||
break; |
|||
case EROFS: |
|||
if((err_ != ENOENT) && (err_ != ENOSPC)) |
|||
cur_ = err_; |
|||
break; |
|||
} |
|||
} |
|||
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue