From 62f8fc524e64717536234ecebe27df6adabdb906 Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Fri, 15 Jan 2016 15:55:34 -0500 Subject: [PATCH] have link act similar to rename closes #193 --- src/link.cpp | 190 ++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 152 insertions(+), 38 deletions(-) diff --git a/src/link.cpp b/src/link.cpp index 6706c196..d701b5f8 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -36,34 +36,102 @@ using namespace mergerfs; static int -_single_link(Policy::Func::Search searchFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &base, - const string &oldpath, - const string &newpath) +_link_create_path_one(const string &oldbasepath, + const string &newbasepath, + const string &oldfusepath, + const string &newfusepath, + const string &newfusedirpath, + const int error) { int rv; - const string fulloldpath = fs::path::make(base,oldpath); - const string fullnewpath = fs::path::make(base,newpath); + string oldfullpath; + string newfullpath; - rv = ::link(fulloldpath.c_str(),fullnewpath.c_str()); - if((rv == -1) && (errno == ENOENT)) + if(oldbasepath != newbasepath) { - string newpathdir; - vector foundpath; + 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 &srcmounts, + const size_t minfreespace, + const string &oldfusepath, + const string &newfusepath) +{ + int rv; + int error; + string newbasepath; + vector toremove; + vector oldbasepaths; - newpathdir = fs::path::dirname(newpath); - rv = searchFunc(srcmounts,newpathdir,minfreespace,foundpath); - if(rv == -1) - return -1; + rv = actionFunc(srcmounts,oldfusepath,minfreespace,oldbasepaths); + if(rv == -1) + return -errno; - { - const ugid::SetRootGuard ugidGuard; - fs::clonepath(foundpath[0],base,newpathdir); - } + const string newfusedirpath = fs::path::dirname(newfusepath); + rv = searchFunc(srcmounts,newfusedirpath,minfreespace,newbasepath); + if(rv == -1) + return -errno; - rv = ::link(fulloldpath.c_str(),fullnewpath.c_str()); + error = -1; + for(size_t i = 0, ei = oldbasepaths.size(); i != ei; i++) + { + const string &oldbasepath = oldbasepaths[i]; + + error = _link_create_path_one(oldbasepath,newbasepath, + oldfusepath,newfusepath, + newfusedirpath, + error); + } + + return -error; +} + +static +int +_clonepath_if_would_create(Policy::Func::Search searchFunc, + Policy::Func::Create createFunc, + const vector &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; @@ -71,27 +139,64 @@ _single_link(Policy::Func::Search searchFunc, static int -_link(Policy::Func::Search searchFunc, - Policy::Func::Action actionFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &oldpath, - const string &newpath) +_link_preserve_path_one(Policy::Func::Search searchFunc, + Policy::Func::Create createFunc, + const vector &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::Create createFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &oldfusepath, + const string &newfusepath) { int rv; int error; - vector oldpaths; + vector toremove; + vector oldbasepaths; - rv = actionFunc(srcmounts,oldpath,minfreespace,oldpaths); + rv = actionFunc(srcmounts,oldfusepath,minfreespace,oldbasepaths); if(rv == -1) return -errno; 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; @@ -110,12 +215,21 @@ namespace mergerfs const ugid::Set ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _link(config.getattr, - config.link, - config.srcmounts, - config.minfreespace, - from, - to); + 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.create, + config.srcmounts, + config.minfreespace, + from, + to); } } }