|
@ -36,34 +36,102 @@ using namespace mergerfs; |
|
|
|
|
|
|
|
|
static |
|
|
static |
|
|
int |
|
|
int |
|
|
_single_link(Policy::Func::Search searchFunc, |
|
|
|
|
|
|
|
|
_link_create_path_one(const string &oldbasepath, |
|
|
|
|
|
const string &newbasepath, |
|
|
|
|
|
const string &oldfusepath, |
|
|
|
|
|
const string &newfusepath, |
|
|
|
|
|
const string &newfusedirpath, |
|
|
|
|
|
const int error) |
|
|
|
|
|
{ |
|
|
|
|
|
int rv; |
|
|
|
|
|
string oldfullpath; |
|
|
|
|
|
string newfullpath; |
|
|
|
|
|
|
|
|
|
|
|
if(oldbasepath != newbasepath) |
|
|
|
|
|
{ |
|
|
|
|
|
const ugid::SetRootGuard ugidGuard; |
|
|
|
|
|
fs::clonepath(newbasepath,oldbasepath,newfusedirpath); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
fs::path::make(oldbasepath,oldfusepath,oldfullpath); |
|
|
|
|
|
fs::path::make(oldbasepath,newfusepath,newfullpath); |
|
|
|
|
|
|
|
|
|
|
|
rv = ::link(oldfullpath.c_str(),newfullpath.c_str()); |
|
|
|
|
|
|
|
|
|
|
|
return calc_error(rv,error,errno); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static |
|
|
|
|
|
int |
|
|
|
|
|
_link_create_path(Policy::Func::Search searchFunc, |
|
|
|
|
|
Policy::Func::Action actionFunc, |
|
|
const vector<string> &srcmounts, |
|
|
const vector<string> &srcmounts, |
|
|
const size_t minfreespace, |
|
|
const size_t minfreespace, |
|
|
const string &base, |
|
|
|
|
|
const string &oldpath, |
|
|
|
|
|
const string &newpath) |
|
|
|
|
|
|
|
|
const string &oldfusepath, |
|
|
|
|
|
const string &newfusepath) |
|
|
{ |
|
|
{ |
|
|
int rv; |
|
|
int rv; |
|
|
const string fulloldpath = fs::path::make(base,oldpath); |
|
|
|
|
|
const string fullnewpath = fs::path::make(base,newpath); |
|
|
|
|
|
|
|
|
int error; |
|
|
|
|
|
string newbasepath; |
|
|
|
|
|
vector<string> toremove; |
|
|
|
|
|
vector<string> oldbasepaths; |
|
|
|
|
|
|
|
|
rv = ::link(fulloldpath.c_str(),fullnewpath.c_str()); |
|
|
|
|
|
if((rv == -1) && (errno == ENOENT)) |
|
|
|
|
|
{ |
|
|
|
|
|
string newpathdir; |
|
|
|
|
|
vector<string> foundpath; |
|
|
|
|
|
|
|
|
rv = actionFunc(srcmounts,oldfusepath,minfreespace,oldbasepaths); |
|
|
|
|
|
if(rv == -1) |
|
|
|
|
|
return -errno; |
|
|
|
|
|
|
|
|
newpathdir = fs::path::dirname(newpath); |
|
|
|
|
|
rv = searchFunc(srcmounts,newpathdir,minfreespace,foundpath); |
|
|
|
|
|
|
|
|
const string newfusedirpath = fs::path::dirname(newfusepath); |
|
|
|
|
|
rv = searchFunc(srcmounts,newfusedirpath,minfreespace,newbasepath); |
|
|
if(rv == -1) |
|
|
if(rv == -1) |
|
|
return -1; |
|
|
|
|
|
|
|
|
return -errno; |
|
|
|
|
|
|
|
|
|
|
|
error = -1; |
|
|
|
|
|
for(size_t i = 0, ei = oldbasepaths.size(); i != ei; i++) |
|
|
{ |
|
|
{ |
|
|
const ugid::SetRootGuard ugidGuard; |
|
|
|
|
|
fs::clonepath(foundpath[0],base,newpathdir); |
|
|
|
|
|
|
|
|
const string &oldbasepath = oldbasepaths[i]; |
|
|
|
|
|
|
|
|
|
|
|
error = _link_create_path_one(oldbasepath,newbasepath, |
|
|
|
|
|
oldfusepath,newfusepath, |
|
|
|
|
|
newfusedirpath, |
|
|
|
|
|
error); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
rv = ::link(fulloldpath.c_str(),fullnewpath.c_str()); |
|
|
|
|
|
|
|
|
return -error; |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static |
|
|
|
|
|
int |
|
|
|
|
|
_clonepath_if_would_create(Policy::Func::Search searchFunc, |
|
|
|
|
|
Policy::Func::Create createFunc, |
|
|
|
|
|
const vector<string> &srcmounts, |
|
|
|
|
|
const size_t minfreespace, |
|
|
|
|
|
const string &oldbasepath, |
|
|
|
|
|
const string &oldfusepath, |
|
|
|
|
|
const string &newfusepath) |
|
|
|
|
|
{ |
|
|
|
|
|
int rv; |
|
|
|
|
|
string newbasepath; |
|
|
|
|
|
string newfusedirpath; |
|
|
|
|
|
|
|
|
|
|
|
newfusedirpath = fs::path::dirname(newfusepath); |
|
|
|
|
|
|
|
|
|
|
|
rv = createFunc(srcmounts,newfusedirpath,minfreespace,newbasepath); |
|
|
|
|
|
if(rv != -1) |
|
|
|
|
|
{ |
|
|
|
|
|
if(oldbasepath == newbasepath) |
|
|
|
|
|
{ |
|
|
|
|
|
rv = searchFunc(srcmounts,newfusedirpath,minfreespace,newbasepath); |
|
|
|
|
|
if(rv != -1) |
|
|
|
|
|
{ |
|
|
|
|
|
const ugid::SetRootGuard ugidGuard; |
|
|
|
|
|
fs::clonepath(newbasepath,oldbasepath,newfusedirpath); |
|
|
|
|
|
} |
|
|
|
|
|
} |
|
|
|
|
|
else |
|
|
|
|
|
{ |
|
|
|
|
|
rv = -1; |
|
|
|
|
|
errno = EXDEV; |
|
|
|
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return rv; |
|
|
return rv; |
|
@ -71,27 +139,64 @@ _single_link(Policy::Func::Search searchFunc, |
|
|
|
|
|
|
|
|
static |
|
|
static |
|
|
int |
|
|
int |
|
|
_link(Policy::Func::Search searchFunc, |
|
|
|
|
|
|
|
|
_link_preserve_path_one(Policy::Func::Search searchFunc, |
|
|
|
|
|
Policy::Func::Create createFunc, |
|
|
|
|
|
const vector<string> &srcmounts, |
|
|
|
|
|
const size_t minfreespace, |
|
|
|
|
|
const string &oldbasepath, |
|
|
|
|
|
const string &oldfusepath, |
|
|
|
|
|
const string &newfusepath, |
|
|
|
|
|
const int error) |
|
|
|
|
|
{ |
|
|
|
|
|
int rv; |
|
|
|
|
|
string oldfullpath; |
|
|
|
|
|
string newfullpath; |
|
|
|
|
|
|
|
|
|
|
|
fs::path::make(oldbasepath,oldfusepath,oldfullpath); |
|
|
|
|
|
fs::path::make(oldbasepath,newfusepath,newfullpath); |
|
|
|
|
|
|
|
|
|
|
|
rv = ::link(oldfullpath.c_str(),newfullpath.c_str()); |
|
|
|
|
|
if((rv == -1) && (errno == ENOENT)) |
|
|
|
|
|
{ |
|
|
|
|
|
rv = _clonepath_if_would_create(searchFunc,createFunc, |
|
|
|
|
|
srcmounts,minfreespace, |
|
|
|
|
|
oldbasepath,oldfusepath,newfusepath); |
|
|
|
|
|
if(rv != -1) |
|
|
|
|
|
rv = ::link(oldfullpath.c_str(),newfullpath.c_str()); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
return calc_error(rv,error,errno); |
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
static |
|
|
|
|
|
int |
|
|
|
|
|
_link_preserve_path(Policy::Func::Search searchFunc, |
|
|
Policy::Func::Action actionFunc, |
|
|
Policy::Func::Action actionFunc, |
|
|
|
|
|
Policy::Func::Create createFunc, |
|
|
const vector<string> &srcmounts, |
|
|
const vector<string> &srcmounts, |
|
|
const size_t minfreespace, |
|
|
const size_t minfreespace, |
|
|
const string &oldpath, |
|
|
|
|
|
const string &newpath) |
|
|
|
|
|
|
|
|
const string &oldfusepath, |
|
|
|
|
|
const string &newfusepath) |
|
|
{ |
|
|
{ |
|
|
int rv; |
|
|
int rv; |
|
|
int error; |
|
|
int error; |
|
|
vector<string> oldpaths; |
|
|
|
|
|
|
|
|
vector<string> toremove; |
|
|
|
|
|
vector<string> oldbasepaths; |
|
|
|
|
|
|
|
|
rv = actionFunc(srcmounts,oldpath,minfreespace,oldpaths); |
|
|
|
|
|
|
|
|
rv = actionFunc(srcmounts,oldfusepath,minfreespace,oldbasepaths); |
|
|
if(rv == -1) |
|
|
if(rv == -1) |
|
|
return -errno; |
|
|
return -errno; |
|
|
|
|
|
|
|
|
error = -1; |
|
|
error = -1; |
|
|
for(size_t i = 0, ei = oldpaths.size(); i != ei; i++) |
|
|
|
|
|
|
|
|
for(size_t i = 0, ei = oldbasepaths.size(); i != ei; i++) |
|
|
{ |
|
|
{ |
|
|
rv = _single_link(searchFunc,srcmounts,minfreespace,oldpaths[i],oldpath,newpath); |
|
|
|
|
|
|
|
|
const string &oldbasepath = oldbasepaths[i]; |
|
|
|
|
|
|
|
|
error = calc_error(rv,error,errno); |
|
|
|
|
|
|
|
|
error = _link_preserve_path_one(searchFunc,createFunc, |
|
|
|
|
|
srcmounts,minfreespace, |
|
|
|
|
|
oldbasepath, |
|
|
|
|
|
oldfusepath,newfusepath, |
|
|
|
|
|
error); |
|
|
} |
|
|
} |
|
|
|
|
|
|
|
|
return -error; |
|
|
return -error; |
|
@ -110,8 +215,17 @@ namespace mergerfs |
|
|
const ugid::Set ugid(fc->uid,fc->gid); |
|
|
const ugid::Set ugid(fc->uid,fc->gid); |
|
|
const rwlock::ReadGuard readlock(&config.srcmountslock); |
|
|
const rwlock::ReadGuard readlock(&config.srcmountslock); |
|
|
|
|
|
|
|
|
return _link(config.getattr, |
|
|
|
|
|
|
|
|
if(config.create != Policy::epmfs) |
|
|
|
|
|
return _link_create_path(config.link, |
|
|
|
|
|
config.create, |
|
|
|
|
|
config.srcmounts, |
|
|
|
|
|
config.minfreespace, |
|
|
|
|
|
from, |
|
|
|
|
|
to); |
|
|
|
|
|
|
|
|
|
|
|
return _link_preserve_path(config.getattr, |
|
|
config.link, |
|
|
config.link, |
|
|
|
|
|
config.create, |
|
|
config.srcmounts, |
|
|
config.srcmounts, |
|
|
config.minfreespace, |
|
|
config.minfreespace, |
|
|
from, |
|
|
from, |
|
|