diff --git a/src/access.cpp b/src/access.cpp index 86418d94..f846ee58 100644 --- a/src/access.cpp +++ b/src/access.cpp @@ -42,23 +42,26 @@ using std::string; using std::vector; using mergerfs::Policy; +using mergerfs::Category; static int -_access(const Policy::Func::Ptr searchFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - const int mask) +_access(Policy::Func::Search searchFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + const int mask) { int rv; - Paths paths; + vector path; - rv = searchFunc(srcmounts,fusepath,minfreespace,paths); + rv = searchFunc(srcmounts,fusepath,minfreespace,path); if(rv == -1) return -errno; - rv = ::eaccess(paths[0].full.c_str(),mask); + fs::path::append(path[0],fusepath); + + rv = ::eaccess(path[0].c_str(),mask); return ((rv == -1) ? -errno : 0); } @@ -76,7 +79,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _access(*config.access, + return _access(config.access, config.srcmounts, config.minfreespace, fusepath, diff --git a/src/chmod.cpp b/src/chmod.cpp index ecd57ae4..5e61261e 100644 --- a/src/chmod.cpp +++ b/src/chmod.cpp @@ -39,25 +39,26 @@ using mergerfs::Policy; static int -_chmod(const Policy::Func::Ptr actionFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - const mode_t mode) +_chmod(Policy::Func::Action actionFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + const mode_t mode) { int rv; int error; - Paths paths; + vector paths; rv = actionFunc(srcmounts,fusepath,minfreespace,paths); if(rv == -1) return -errno; error = 0; - for(Paths::const_iterator - i = paths.begin(), ei = paths.end(); i != ei; ++i) + for(size_t i = 0, ei = paths.size(); i != ei; i++) { - rv = ::chmod(i->full.c_str(),mode); + fs::path::append(paths[i],fusepath); + + rv = ::chmod(paths[i].c_str(),mode); if(rv == -1) error = errno; } @@ -78,7 +79,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _chmod(*config.chmod, + return _chmod(config.chmod, config.srcmounts, config.minfreespace, fusepath, diff --git a/src/chown.cpp b/src/chown.cpp index 19469d6a..f013c07c 100644 --- a/src/chown.cpp +++ b/src/chown.cpp @@ -40,26 +40,27 @@ using mergerfs::Policy; static int -_chown(const Policy::Func::Ptr actionFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - const uid_t uid, - const gid_t gid) +_chown(Policy::Func::Action actionFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + const uid_t uid, + const gid_t gid) { int rv; int error; - Paths paths; + vector paths; rv = actionFunc(srcmounts,fusepath,minfreespace,paths); if(rv == -1) return -errno; error = 0; - for(Paths::const_iterator - i = paths.begin(), ei = paths.end(); i != ei; ++i) + for(size_t i = 0, ei = paths.size(); i != ei; i++) { - rv = ::lchown(i->full.c_str(),uid,gid); + fs::path::append(paths[i],fusepath); + + rv = ::lchown(paths[i].c_str(),uid,gid); if(rv == -1) error = errno; } @@ -81,7 +82,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _chown(*config.chown, + return _chown(config.chown, config.srcmounts, config.minfreespace, fusepath, diff --git a/src/create.cpp b/src/create.cpp index 80a1a836..365a77ca 100644 --- a/src/create.cpp +++ b/src/create.cpp @@ -43,23 +43,22 @@ using mergerfs::Policy; static int -_create(const Policy::Func::Ptr searchFunc, - const Policy::Func::Ptr createFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - const mode_t mode, - const int flags, - uint64_t &fh) +_create(Policy::Func::Search searchFunc, + Policy::Func::Create createFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + const mode_t mode, + const int flags, + uint64_t &fh) { int fd; int rv; - string path; string dirname; - Paths createpath; - Paths existingpath; + vector createpath; + vector existingpath; - dirname = fs::dirname(fusepath); + dirname = fs::path::dirname(fusepath); rv = searchFunc(srcmounts,dirname,minfreespace,existingpath); if(rv == -1) return -errno; @@ -68,15 +67,15 @@ _create(const Policy::Func::Ptr searchFunc, if(rv == -1) return -errno; - if(createpath[0].base != existingpath[0].base) + if(createpath[0] != existingpath[0]) { const mergerfs::ugid::SetResetGuard ugid(0,0); - fs::clonepath(existingpath[0].base,createpath[0].base,dirname); + fs::clonepath(existingpath[0],createpath[0],dirname); } - path = fs::make_path(createpath[0].base,fusepath); + fs::path::append(createpath[0],fusepath); - fd = ::open(path.c_str(),flags,mode); + fd = ::open(createpath[0].c_str(),flags,mode); if(fd == -1) return -errno; @@ -99,8 +98,8 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _create(*config.getattr, - *config.create, + return _create(config.getattr, + config.create, config.srcmounts, config.minfreespace, fusepath, diff --git a/src/fs.cpp b/src/fs.cpp index 3e41b4bb..66fb28c7 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -63,102 +63,85 @@ random_element(Iter begin, namespace fs { - string - dirname(const string &path) + namespace path { - string parent = path; - string::reverse_iterator i; - string::reverse_iterator bi; - - bi = parent.rend(); - i = parent.rbegin(); - while(*i == '/' && i != bi) - i++; + string + dirname(const string &path) + { + string parent = path; + string::reverse_iterator i; + string::reverse_iterator bi; - while(*i != '/' && i != bi) - i++; + bi = parent.rend(); + i = parent.rbegin(); + while(*i == '/' && i != bi) + i++; - while(*i == '/' && i != bi) - i++; + while(*i != '/' && i != bi) + i++; - parent.erase(i.base(),parent.end()); + while(*i == '/' && i != bi) + i++; - return parent; - } + parent.erase(i.base(),parent.end()); - string - basename(const string &path) - { - return path.substr(path.find_last_of('/')+1); - } + return parent; + } - bool - dir_is_empty(const string &path) - { - DIR *dir; - struct dirent *de; + string + basename(const string &path) + { + return path.substr(path.find_last_of('/')+1); + } - dir = ::opendir(path.c_str()); - if(!dir) - return false; + bool + is_empty(const string &path) + { + DIR *dir; + struct dirent *de; - while((de = ::readdir(dir))) - { - const char *d_name = de->d_name; + dir = ::opendir(path.c_str()); + if(!dir) + return false; - if(d_name[0] == '.' && - ((d_name[1] == '\0') || - (d_name[1] == '.' && d_name[2] == '\0'))) - continue; + while((de = ::readdir(dir))) + { + const char *d_name = de->d_name; - ::closedir(dir); + if(d_name[0] == '.' && + ((d_name[1] == '\0') || + (d_name[1] == '.' && d_name[2] == '\0'))) + continue; - return false; - } + ::closedir(dir); - ::closedir(dir); + return false; + } - return true; - } + ::closedir(dir); - string - make_path(const string &base, - const string &suffix) - { - if(suffix[0] == '/' || - *base.rbegin() == '/') - return base + suffix; - return base + '/' + suffix; - } + return true; + } - bool - path_exists(vector::const_iterator begin, - vector::const_iterator end, - const string &fusepath) - { - for(vector::const_iterator - iter = begin; iter != end; ++iter) - { - int rv; - string path; - struct stat st; + bool + exists(const vector &paths, + const string &fusepath) + { + for(size_t i = 0, ei = paths.size(); i != ei; i++) + { + int rv; + string path; + struct stat st; - path = fs::make_path(*iter,fusepath); - rv = ::lstat(path.c_str(),&st); - if(rv == 0) - return true; - } + path = fs::path::make(paths[i],fusepath); - return false; - } + rv = ::lstat(path.c_str(),&st); + if(rv == 0) + return true; + } - bool - path_exists(const vector &srcmounts, - const string &fusepath) - { - return path_exists(srcmounts.begin(), - srcmounts.end(), - fusepath); + return false; + } } void @@ -166,16 +149,14 @@ namespace fs const string &fusepath, vector &paths) { - for(vector::const_iterator - iter = srcmounts.begin(), eiter = srcmounts.end(); - iter != eiter; - ++iter) + for(size_t i = 0, ei = srcmounts.size(); i != ei; i++) { int rv; string fullpath; struct stat st; - fullpath = fs::make_path(*iter,fusepath); + fullpath = fs::path::make(srcmounts[i],fusepath); + rv = ::lstat(fullpath.c_str(),&st); if(rv == 0) paths.push_back(fullpath); @@ -450,7 +431,7 @@ namespace fs string frompath; string dirname; - dirname = fs::dirname(relative); + dirname = fs::path::dirname(relative); if(!dirname.empty()) { rv = clonepath(fromsrc,tosrc,dirname); @@ -458,15 +439,14 @@ namespace fs return -1; } - frompath = fs::make_path(fromsrc,relative); - + frompath = fs::path::make(fromsrc,relative); rv = ::stat(frompath.c_str(),&st); if(rv == -1) return -1; else if(!S_ISDIR(st.st_mode)) return (errno = ENOTDIR,-1); - topath = fs::make_path(tosrc,relative); + topath = fs::path::make(tosrc,relative); rv = ::mkdir(topath.c_str(),st.st_mode); if(rv == -1) { diff --git a/src/fs.hpp b/src/fs.hpp index 1ef65b31..f6cfa915 100644 --- a/src/fs.hpp +++ b/src/fs.hpp @@ -38,19 +38,35 @@ namespace fs using std::vector; using std::map; - string dirname(const string &path); - string basename(const string &path); - - bool dir_is_empty(const string &path); - - string make_path(const string &base, - const string &suffix); - - bool path_exists(vector::const_iterator begin, - vector::const_iterator end, - const string &fusepath); - bool path_exists(const vector &srcmounts, - const string &fusepath); + namespace path + { + string dirname(const string &path); + string basename(const string &path); + + bool is_empty(const string &path); + + bool exists(vector::const_iterator begin, + vector::const_iterator end, + const string &fusepath); + bool exists(const vector &srcmounts, + const string &fusepath); + + inline + string + make(const string &base, + const string &suffix) + { + return base + suffix; + } + + inline + void + append(string &base, + const string &suffix) + { + base += suffix; + } + } void findallfiles(const vector &srcmounts, const string &fusepath, diff --git a/src/getattr.cpp b/src/getattr.cpp index fd471c5b..63bea591 100644 --- a/src/getattr.cpp +++ b/src/getattr.cpp @@ -66,20 +66,22 @@ _getattr_controlfile(struct stat &buf) static int -_getattr(const Policy::Func::Ptr searchFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - struct stat &buf) +_getattr(Policy::Func::Search searchFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + struct stat &buf) { int rv; - Paths path; + vector path; rv = searchFunc(srcmounts,fusepath,minfreespace,path); if(rv == -1) return -errno; - rv = ::lstat(path[0].full.c_str(),&buf); + fs::path::append(path[0],fusepath); + + rv = ::lstat(path[0].c_str(),&buf); return ((rv == -1) ? -errno : 0); } @@ -101,7 +103,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _getattr(*config.getattr, + return _getattr(config.getattr, config.srcmounts, config.minfreespace, fusepath, diff --git a/src/getxattr.cpp b/src/getxattr.cpp index 9f277e90..e8e6d6e5 100644 --- a/src/getxattr.cpp +++ b/src/getxattr.cpp @@ -167,9 +167,10 @@ _getxattr_user_mergerfs_allpaths(const vector &srcmounts, static int -_getxattr_user_mergerfs(const Path &path, - const vector &srcmounts, +_getxattr_user_mergerfs(const string &basepath, const string &fusepath, + const string &fullpath, + const vector &srcmounts, const char *attrname, char *buf, const size_t count) @@ -177,39 +178,42 @@ _getxattr_user_mergerfs(const Path &path, const char *attrbasename = &attrname[sizeof("user.mergerfs")]; if(!strcmp(attrbasename,"basepath")) - return ::_getxattr_from_string(buf,count,path.base); + return ::_getxattr_from_string(buf,count,basepath); else if(!strcmp(attrbasename,"fullpath")) - return ::_getxattr_from_string(buf,count,path.full); + return ::_getxattr_from_string(buf,count,fullpath); else if(!strcmp(attrbasename,"relpath")) return ::_getxattr_from_string(buf,count,fusepath); else if(!strcmp(attrbasename,"allpaths")) return ::_getxattr_user_mergerfs_allpaths(srcmounts,fusepath,buf,count); - return ::lgetxattr(path.full.c_str(),attrname,buf,count); + return ::lgetxattr(fullpath.c_str(),attrname,buf,count); } static int -_getxattr(const Policy::Func::Ptr searchFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - const char *attrname, - char *buf, - const size_t count) +_getxattr(Policy::Func::Search searchFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + const char *attrname, + char *buf, + const size_t count) { #ifndef WITHOUT_XATTR int rv; - Paths path; + vector basepath; + string fullpath; - rv = searchFunc(srcmounts,fusepath,minfreespace,path); + rv = searchFunc(srcmounts,fusepath,minfreespace,basepath); if(rv == -1) return -errno; + fullpath = fs::path::make(basepath[0],fusepath); + if(!strncmp("user.mergerfs.",attrname,sizeof("user.mergerfs.")-1)) - rv = _getxattr_user_mergerfs(path[0],srcmounts,fusepath,attrname,buf,count); + rv = _getxattr_user_mergerfs(basepath[0],fusepath,fullpath,srcmounts,attrname,buf,count); else - rv = ::lgetxattr(path[0].full.c_str(),attrname,buf,count); + rv = ::lgetxattr(fullpath.c_str(),attrname,buf,count); return ((rv == -1) ? -errno : rv); #else @@ -239,7 +243,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _getxattr(*config.getxattr, + return _getxattr(config.getxattr, config.srcmounts, config.minfreespace, fusepath, diff --git a/src/ioctl.cpp b/src/ioctl.cpp index 41947431..3449b4c9 100644 --- a/src/ioctl.cpp +++ b/src/ioctl.cpp @@ -82,30 +82,32 @@ _ioctl(const int fd, #ifdef FUSE_IOCTL_DIR static int -_ioctl_dir_base(const Policy::Func::Ptr searchFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - const int cmd, - void *arg, - const unsigned int flags, - void *data) +_ioctl_dir_base(Policy::Func::Search searchFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + const int cmd, + void *arg, + const unsigned int flags, + void *data) { int fd; int rv; - Paths path; + vector path; rv = searchFunc(srcmounts,fusepath,minfreespace,path); if(rv == -1) return -errno; - fd = ::open(path[0].full.c_str(),flags); + fs::path::append(path[0],fusepath); + + fd = ::open(path[0].c_str(),flags); if(fd == -1) return -errno; rv = _ioctl(fd,cmd,arg,flags,data); - close(fd); + ::close(fd); return rv; } @@ -123,7 +125,7 @@ _ioctl_dir(const string &fusepath, const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _ioctl_dir_base(*config.getattr, + return _ioctl_dir_base(config.getattr, config.srcmounts, config.minfreespace, fusepath, diff --git a/src/link.cpp b/src/link.cpp index 8f53a18c..b27c75c3 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -41,31 +41,31 @@ using mergerfs::Policy; static int -_single_link(const Policy::Func::Ptr searchFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &base, - const string &oldpath, - const string &newpath) +_single_link(Policy::Func::Search searchFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &base, + const string &oldpath, + const string &newpath) { int rv; - const string fulloldpath = fs::make_path(base,oldpath); - const string fullnewpath = fs::make_path(base,newpath); + const string fulloldpath = fs::path::make(base,oldpath); + const string fullnewpath = fs::path::make(base,newpath); rv = ::link(fulloldpath.c_str(),fullnewpath.c_str()); if(rv == -1 && errno == ENOENT) { string newpathdir; - Paths foundpath; + vector foundpath; - newpathdir = fs::dirname(newpath); + newpathdir = fs::path::dirname(newpath); rv = searchFunc(srcmounts,newpathdir,minfreespace,foundpath); if(rv == -1) return -1; { const mergerfs::ugid::SetResetGuard ugid(0,0); - fs::clonepath(foundpath[0].base,base,newpathdir); + fs::clonepath(foundpath[0],base,newpathdir); } rv = ::link(fulloldpath.c_str(),fullnewpath.c_str()); @@ -76,26 +76,25 @@ _single_link(const Policy::Func::Ptr searchFunc, static int -_link(const Policy::Func::Ptr searchFunc, - const Policy::Func::Ptr actionFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &oldpath, - const string &newpath) +_link(Policy::Func::Search searchFunc, + Policy::Func::Action actionFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &oldpath, + const string &newpath) { int rv; int error; - Paths oldpaths; + vector oldpaths; rv = actionFunc(srcmounts,oldpath,minfreespace,oldpaths); if(rv == -1) return -errno; error = 0; - for(Paths::const_iterator - i = oldpaths.begin(), ei = oldpaths.end(); i != ei; ++i) + for(size_t i = 0, ei = oldpaths.size(); i != ei; i++) { - rv = _single_link(searchFunc,srcmounts,minfreespace,i->base,oldpath,newpath); + rv = _single_link(searchFunc,srcmounts,minfreespace,oldpaths[i],oldpath,newpath); if(rv == -1) error = errno; } @@ -116,8 +115,8 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _link(*config.getattr, - *config.link, + return _link(config.getattr, + config.link, config.srcmounts, config.minfreespace, from, diff --git a/src/listxattr.cpp b/src/listxattr.cpp index 59428cc8..4715f443 100644 --- a/src/listxattr.cpp +++ b/src/listxattr.cpp @@ -69,22 +69,24 @@ _listxattr_controlfile(char *list, static int -_listxattr(const Policy::Func::Ptr searchFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - char *list, - const size_t size) +_listxattr(Policy::Func::Search searchFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + char *list, + const size_t size) { #ifndef WITHOUT_XATTR int rv; - Paths path; + vector path; rv = searchFunc(srcmounts,fusepath,minfreespace,path); if(rv == -1) return -errno; - rv = ::llistxattr(path[0].full.c_str(),list,size); + fs::path::append(path[0],fusepath); + + rv = ::llistxattr(path[0].c_str(),list,size); return ((rv == -1) ? -errno : rv); #else @@ -110,7 +112,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _listxattr(*config.listxattr, + return _listxattr(config.listxattr, config.srcmounts, config.minfreespace, fusepath, diff --git a/src/mergerfs.cpp b/src/mergerfs.cpp index 254b4d12..422d9965 100644 --- a/src/mergerfs.cpp +++ b/src/mergerfs.cpp @@ -80,7 +80,7 @@ namespace local getappname(const int argc, char * const *argv) { - return fs::basename(argv[0]); + return fs::path::basename(argv[0]); } static diff --git a/src/mkdir.cpp b/src/mkdir.cpp index fb8caf23..9edce6c4 100644 --- a/src/mkdir.cpp +++ b/src/mkdir.cpp @@ -42,21 +42,21 @@ using mergerfs::Policy; static int -_mkdir(const Policy::Func::Ptr searchFunc, - const Policy::Func::Ptr createFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - const mode_t mode) +_mkdir(Policy::Func::Search searchFunc, + Policy::Func::Create createFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + const mode_t mode) { int rv; int error; string dirname; string fullpath; - Paths createpaths; - Paths existingpath; + vector createpaths; + vector existingpath; - dirname = fs::dirname(fusepath); + dirname = fs::path::dirname(fusepath); rv = searchFunc(srcmounts,dirname,minfreespace,existingpath); if(rv == -1) return -errno; @@ -66,18 +66,19 @@ _mkdir(const Policy::Func::Ptr searchFunc, return -errno; error = 0; - for(Paths::const_iterator - i = createpaths.begin(), ei = createpaths.end(); i != ei; ++i) + for(size_t i = 0, ei = createpaths.size(); i != ei; i++) { - if(i->base != existingpath[0].base) + string &createpath = createpaths[i]; + + if(createpath != existingpath[0]) { const mergerfs::ugid::SetResetGuard ugid(0,0); - fs::clonepath(existingpath[0].base,i->base,dirname); + fs::clonepath(existingpath[0],createpath,dirname); } - fullpath = fs::make_path(i->base,fusepath); + fs::path::append(createpath,fusepath); - rv = ::mkdir(fullpath.c_str(),mode); + rv = ::mkdir(createpath.c_str(),mode); if(rv == -1) error = errno; } @@ -98,8 +99,8 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _mkdir(*config.getattr, - *config.mkdir, + return _mkdir(config.getattr, + config.mkdir, config.srcmounts, config.minfreespace, fusepath, diff --git a/src/mknod.cpp b/src/mknod.cpp index 21ab3f7d..b8b41f5a 100644 --- a/src/mknod.cpp +++ b/src/mknod.cpp @@ -44,22 +44,21 @@ using mergerfs::Policy; static int -_mknod(const Policy::Func::Ptr searchFunc, - const Policy::Func::Ptr createFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - const mode_t mode, - const dev_t dev) +_mknod(Policy::Func::Search searchFunc, + Policy::Func::Create createFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + const mode_t mode, + const dev_t dev) { int rv; int error; string dirname; - string fullpath; - Paths createpaths; - Paths existingpath; + vector createpaths; + vector existingpath; - dirname = fs::dirname(fusepath); + dirname = fs::path::dirname(fusepath); rv = searchFunc(srcmounts,dirname,minfreespace,existingpath); if(rv == -1) return -errno; @@ -69,18 +68,19 @@ _mknod(const Policy::Func::Ptr searchFunc, return -errno; error = 0; - for(Paths::const_iterator - i = createpaths.begin(), ei = createpaths.end(); i != ei; ++i) + for(size_t i = 0, ei = createpaths.size(); i != ei; i++) { - if(i->base != existingpath[0].base) + string &createpath = createpaths[0]; + + if(createpath != existingpath[0]) { const mergerfs::ugid::SetResetGuard ugid(0,0); - fs::clonepath(existingpath[0].base,i->base,dirname); + fs::clonepath(existingpath[0],createpath,dirname); } - fullpath = fs::make_path(i->base,fusepath); + fs::path::append(createpath,fusepath); - rv = ::mknod(fullpath.c_str(),mode,dev); + rv = ::mknod(createpath.c_str(),mode,dev); if(rv == -1) error = errno; } @@ -102,8 +102,8 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _mknod(*config.getattr, - *config.mknod, + return _mknod(config.getattr, + config.mknod, config.srcmounts, config.minfreespace, fusepath, diff --git a/src/open.cpp b/src/open.cpp index b06cec3d..9b488372 100644 --- a/src/open.cpp +++ b/src/open.cpp @@ -42,22 +42,22 @@ using mergerfs::Policy; static int -_open(const Policy::Func::Ptr searchFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - const int flags, - uint64_t &fh) +_open(Policy::Func::Search searchFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + const int flags, + uint64_t &fh) { int fd; int rv; - Paths path; + vector path; rv = searchFunc(srcmounts,fusepath,minfreespace,path); if(rv == -1) return -errno; - fd = ::open(path[0].full.c_str(),flags); + fd = ::open(path[0].c_str(),flags); if(fd == -1) return -errno; @@ -79,7 +79,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _open(*config.open, + return _open(config.open, config.srcmounts, config.minfreespace, fusepath, diff --git a/src/option_parser.cpp b/src/option_parser.cpp index 9c5c16de..96bc9563 100644 --- a/src/option_parser.cpp +++ b/src/option_parser.cpp @@ -121,8 +121,8 @@ parse_and_process_minfreespace(const std::string &value, minfreespace *= (1024 * 1024); break; - case 'b': - case 'B': + case 'g': + case 'G': minfreespace *= (1024 * 1024 * 1024); break; diff --git a/src/policy.hpp b/src/policy.hpp index a40b069c..e75f559f 100644 --- a/src/policy.hpp +++ b/src/policy.hpp @@ -31,6 +31,7 @@ #include "path.hpp" #include "fs.hpp" +#include "category.hpp" namespace mergerfs { @@ -61,19 +62,74 @@ namespace mergerfs typedef std::string string; typedef std::size_t size_t; typedef std::vector strvec; - - typedef int (*Ptr)(const strvec&,const string&,const size_t,Paths&); - - static int invalid(const strvec&,const string&,const size_t,Paths&); - static int all(const strvec&,const string&,const size_t,Paths&); - static int epmfs(const strvec&,const string&,const size_t,Paths&); - static int ff(const strvec&,const string&,const size_t,Paths&); - static int ffwp(const strvec&,const string&,const size_t,Paths&); - static int fwfs(const strvec&,const string&,const size_t,Paths&); - static int lfs(const strvec&,const string&,const size_t,Paths&); - static int mfs(const strvec&,const string&,const size_t,Paths&); - static int newest(const strvec&,const string&,const size_t,Paths&); - static int rand(const strvec&,const string&,const size_t,Paths&); + typedef const string cstring; + typedef const size_t csize_t; + typedef const strvec cstrvec; + typedef const Category::Enum::Type CType; + + typedef int (*Ptr)(CType,cstrvec&,cstring&,csize_t,strvec&); + + class Action + { + public: + Action(const Policy *p) + : func(p->_func) + {} + + int + operator()(cstrvec& b,cstring& c,csize_t d,strvec& e) + { + return func(Category::Enum::action,b,c,d,e); + } + + private: + const Ptr func; + }; + + class Create + { + public: + Create(const Policy *p) + : func(p->_func) + {} + + int + operator()(cstrvec& b,cstring& c,csize_t d,strvec& e) + { + return func(Category::Enum::create,b,c,d,e); + } + + private: + const Ptr func; + }; + + class Search + { + public: + Search(const Policy *p) + : func(p->_func) + {} + + int + operator()(cstrvec& b,cstring& c,csize_t d,strvec& e) + { + return func(Category::Enum::search,b,c,d,e); + } + + private: + const Ptr func; + }; + + static int invalid(CType,cstrvec&,cstring&,csize_t,strvec&); + static int all(CType,cstrvec&,cstring&,csize_t,strvec&); + static int epmfs(CType,cstrvec&,cstring&,csize_t,strvec&); + static int ff(CType,cstrvec&,cstring&,csize_t,strvec&); + static int ffwp(CType,cstrvec&,cstring&,csize_t,strvec&); + static int fwfs(CType,cstrvec&,cstring&,csize_t,strvec&); + static int lfs(CType,cstrvec&,cstring&,csize_t,strvec&); + static int mfs(CType,cstrvec&,cstring&,csize_t,strvec&); + static int newest(CType,cstrvec&,cstring&,csize_t,strvec&); + static int rand(CType,cstrvec&,cstring&,csize_t,strvec&); }; private: @@ -124,16 +180,17 @@ namespace mergerfs public: static const std::vector _policies_; static const Policy * const policies; - static const Policy &invalid; - static const Policy &all; - static const Policy &epmfs; - static const Policy &ff; - static const Policy &ffwp; - static const Policy &fwfs; - static const Policy &lfs; - static const Policy &mfs; - static const Policy &newest; - static const Policy &rand; + + static const Policy &invalid; + static const Policy &all; + static const Policy &epmfs; + static const Policy &ff; + static const Policy &ffwp; + static const Policy &fwfs; + static const Policy &lfs; + static const Policy &mfs; + static const Policy &newest; + static const Policy &rand; }; } diff --git a/src/policy_all.cpp b/src/policy_all.cpp index 9260651c..e939d24a 100644 --- a/src/policy_all.cpp +++ b/src/policy_all.cpp @@ -36,30 +36,40 @@ using std::string; using std::vector; using std::size_t; -namespace mergerfs +static +int +_all(const vector &basepaths, + const string &fusepath, + vector &paths) { - int - Policy::Func::all(const vector &basepaths, - const string &fusepath, - const size_t minfreespace, - Paths &paths) - { - int rv; - struct stat st; - string fullpath; + int rv; + struct stat st; + string fullpath; + + for(size_t i = 0, ei = basepaths.size(); i != ei; i++) + { + const char *basepath; + + basepath = basepaths[i].c_str(); + fullpath = fs::path::make(basepath,fusepath); - for(vector::const_iterator - iter = basepaths.begin(), eiter = basepaths.end(); - iter != eiter; - ++iter) - { - fullpath = fs::make_path(*iter,fusepath); + rv = ::lstat(fullpath.c_str(),&st); + if(rv == 0) + paths.push_back(basepath); + } - rv = ::lstat(fullpath.c_str(),&st); - if(rv == 0) - paths.push_back(Path(*iter,fullpath)); - } + return paths.empty() ? (errno=ENOENT,-1) : 0; +} - return paths.empty() ? (errno=ENOENT,-1) : 0; +namespace mergerfs +{ + int + Policy::Func::all(const Category::Enum::Type type, + const vector &basepaths, + const string &fusepath, + const size_t minfreespace, + vector &paths) + { + return _all(basepaths,fusepath,paths); } } diff --git a/src/policy_epmfs.cpp b/src/policy_epmfs.cpp index b6456f5d..80caeb3c 100644 --- a/src/policy_epmfs.cpp +++ b/src/policy_epmfs.cpp @@ -37,68 +37,172 @@ using std::string; using std::vector; using std::size_t; +static +inline +void +_calc_epmfs(const struct statvfs &fsstats, + const char *basepath, + fsblkcnt_t &epmfs, + const char *&epmfsbasepath, + fsblkcnt_t &mfs, + const char *&mfsbasepath) +{ + fsblkcnt_t spaceavail; + + spaceavail = (fsstats.f_frsize * fsstats.f_bavail); + if(spaceavail > epmfs) + { + epmfs = spaceavail; + epmfsbasepath = basepath; + } + + if(spaceavail > mfs) + { + mfs = spaceavail; + mfsbasepath = basepath; + } +} + +static +inline +void +_calc_mfs(const struct statvfs &fsstats, + const char *basepath, + fsblkcnt_t &mfs, + const char *&mfsbasepath) +{ + fsblkcnt_t spaceavail; + + spaceavail = (fsstats.f_frsize * fsstats.f_bavail); + if(spaceavail > mfs) + { + mfs = spaceavail; + mfsbasepath = basepath; + } +} + +static +inline +int +_try_statvfs(const char *basepath, + const string &fullpath, + fsblkcnt_t &epmfs, + const char *&epmfsbasepath, + fsblkcnt_t &mfs, + const char *&mfsbasepath) +{ + int rv; + struct statvfs fsstats; + + rv = ::statvfs(fullpath.c_str(),&fsstats); + if(rv == 0) + _calc_epmfs(fsstats,basepath,epmfs,epmfsbasepath,mfs,mfsbasepath); + + return rv; +} + +static +inline +int +_try_statvfs(const char *basepath, + fsblkcnt_t &mfs, + const char *&mfsbasepath) +{ + int rv; + struct statvfs fsstats; + + rv = ::statvfs(basepath,&fsstats); + if(rv == 0) + _calc_mfs(fsstats,basepath,mfs,mfsbasepath); + + return rv; +} + +static +int +_epmfs_create(const vector &basepaths, + const string &fusepath, + vector &paths) + +{ + fsblkcnt_t epmfs; + fsblkcnt_t mfs; + const char *basepath; + const char *mfsbasepath; + const char *epmfsbasepath; + string fullpath; + + mfs = 0; + epmfs = 0; + mfsbasepath = NULL; + epmfsbasepath = NULL; + for(size_t i = 0, ei = basepaths.size(); i != ei; i++) + { + int rv; + + basepath = basepaths[i].c_str(); + fullpath = fs::path::make(basepath,fusepath); + + rv = _try_statvfs(basepath,fusepath,epmfs,epmfsbasepath,mfs,mfsbasepath); + if(rv == -1) + _try_statvfs(basepath,mfs,mfsbasepath); + } + + if(epmfsbasepath == NULL) + epmfsbasepath = mfsbasepath; + + paths.push_back(epmfsbasepath); + + return 0; +} + +static +int +_epmfs(const vector &basepaths, + const string &fusepath, + vector &paths) + +{ + fsblkcnt_t epmfs; + const char *basepath; + const char *epmfsbasepath; + string fullpath; + + epmfs = 0; + epmfsbasepath = NULL; + for(size_t i = 0, ei = basepaths.size(); i != ei; i++) + { + int rv; + struct statvfs fsstats; + + basepath = basepaths[i].c_str(); + fullpath = fs::path::make(basepath,fusepath); + + rv = ::statvfs(fullpath.c_str(),&fsstats); + if(rv == 0) + _calc_mfs(fsstats,basepath,epmfs,epmfsbasepath); + } + + if(epmfsbasepath == NULL) + return (errno=ENOENT,-1); + + paths.push_back(epmfsbasepath); + + return 0; +} + namespace mergerfs { int - Policy::Func::epmfs(const vector &basepaths, - const string &fusepath, - const size_t minfreespace, - Paths &paths) + Policy::Func::epmfs(const Category::Enum::Type type, + const vector &basepaths, + const string &fusepath, + const size_t minfreespace, + vector &paths) { - fsblkcnt_t existingmfs; - fsblkcnt_t generalmfs; - string fullpath; - string generalmfspath; - string existingmfspath; - vector::const_iterator iter = basepaths.begin(); - vector::const_iterator eiter = basepaths.end(); - - if(iter == eiter) - return (errno = ENOENT,-1); - - existingmfs = 0; - generalmfs = 0; - do - { - int rv; - struct statvfs fsstats; - const string &mountpoint = *iter; - - rv = ::statvfs(mountpoint.c_str(),&fsstats); - if(rv == 0) - { - fsblkcnt_t spaceavail; - struct stat st; - - spaceavail = (fsstats.f_frsize * fsstats.f_bavail); - if(spaceavail > generalmfs) - { - generalmfs = spaceavail; - generalmfspath = mountpoint; - } - - fullpath = fs::make_path(mountpoint,fusepath); - rv = ::lstat(fullpath.c_str(),&st); - if(rv == 0) - { - if(spaceavail > existingmfs) - { - existingmfs = spaceavail; - existingmfspath = mountpoint; - } - } - } - - ++iter; - } - while(iter != eiter); - - if(existingmfspath.empty()) - existingmfspath = generalmfspath; - - paths.push_back(Path(existingmfspath, - fullpath)); - - return 0; + if(type == Category::Enum::create) + return _epmfs_create(basepaths,fusepath,paths); + + return _epmfs(basepaths,fusepath,paths); } } diff --git a/src/policy_ff.cpp b/src/policy_ff.cpp index a555ee1c..929d42be 100644 --- a/src/policy_ff.cpp +++ b/src/policy_ff.cpp @@ -37,34 +37,43 @@ using std::string; using std::vector; using std::size_t; -namespace mergerfs +static +int +_ff(const vector &basepaths, + const string &fusepath, + vector &paths) { - int - Policy::Func::ff(const vector &basepaths, - const string &fusepath, - const size_t minfreespace, - Paths &paths) - { - errno = ENOENT; - for(vector::const_iterator - iter = basepaths.begin(), eiter = basepaths.end(); - iter != eiter; - ++iter) - { - int rv; - struct stat st; - string fullpath; + for(size_t i = 0, ei = basepaths.size(); i != ei; i++) + { + int rv; + struct stat st; + const char *basepath; + string fullpath; - fullpath = fs::make_path(*iter,fusepath); + basepath = basepaths[i].c_str(); + fullpath = fs::path::make(basepath,fusepath); - rv = ::lstat(fullpath.c_str(),&st); - if(rv == 0) - { - paths.push_back(Path(*iter,fullpath)); - return 0; - } - } + rv = ::lstat(fullpath.c_str(),&st); + if(rv == -1) + continue; - return -1; + paths.push_back(basepath); + + return 0; + } + + return (errno=ENOENT,-1); +} + +namespace mergerfs +{ + int + Policy::Func::ff(const Category::Enum::Type type, + const vector &basepaths, + const string &fusepath, + const size_t minfreespace, + vector &paths) + { + return _ff(basepaths,fusepath,paths); } } diff --git a/src/policy_ffwp.cpp b/src/policy_ffwp.cpp index fc908c45..154876fc 100644 --- a/src/policy_ffwp.cpp +++ b/src/policy_ffwp.cpp @@ -36,44 +36,54 @@ using std::string; using std::vector; using std::size_t; +static +int +_ffwp(const vector &basepaths, + const string &fusepath, + vector &paths) +{ + const char *fallback; + + fallback = NULL; + for(size_t i = 0, ei = basepaths.size(); i != ei; i++) + { + int rv; + struct stat st; + const char *basepath; + string fullpath; + + basepath = basepaths[i].c_str(); + fullpath = fs::path::make(basepath,fusepath); + + rv = ::lstat(fullpath.c_str(),&st); + if(rv == 0) + { + paths.push_back(basepath); + return 0; + } + else if(errno == EACCES) + { + fallback = basepath; + } + } + + if(fallback == NULL) + return (errno=ENOENT,-1); + + paths.push_back(fallback); + + return 0; +} + namespace mergerfs { int - Policy::Func::ffwp(const vector &basepaths, - const string &fusepath, - const size_t minfreespace, - Paths &paths) + Policy::Func::ffwp(const Category::Enum::Type type, + const vector &basepaths, + const string &fusepath, + const size_t minfreespace, + vector &paths) { - Path fallback; - - errno = ENOENT; - for(vector::const_iterator - iter = basepaths.begin(), eiter = basepaths.end(); - iter != eiter; - ++iter) - { - int rv; - struct stat st; - string fullpath; - - fullpath = fs::make_path(*iter,fusepath); - - rv = ::lstat(fullpath.c_str(),&st); - if(rv == 0) - { - paths.push_back(Path(*iter,fullpath)); - return 0; - } - else if(errno == EACCES) - { - fallback.base = *iter; - fallback.full = fullpath; - } - } - - if(!fallback.base.empty()) - return (paths.push_back(fallback),0); - - return -1; + return _ffwp(basepaths,fusepath,paths); } } diff --git a/src/policy_fwfs.cpp b/src/policy_fwfs.cpp index 517060d1..ccc77b16 100644 --- a/src/policy_fwfs.cpp +++ b/src/policy_fwfs.cpp @@ -33,37 +33,89 @@ using std::string; using std::vector; using std::size_t; +using mergerfs::Policy; +using mergerfs::Category; + +static +int +_fwfs_create(const Category::Enum::Type type, + const vector &basepaths, + const string &fusepath, + const size_t minfreespace, + vector &paths) +{ + for(size_t i = 0, size = basepaths.size(); i != size; i++) + { + int rv; + const char *basepath; + struct statvfs fsstats; + + basepath = basepaths[i].c_str(); + rv = ::statvfs(basepath,&fsstats); + if(rv == 0) + { + fsblkcnt_t spaceavail; + + spaceavail = (fsstats.f_frsize * fsstats.f_bavail); + if(spaceavail < minfreespace) + continue; + + paths.push_back(basepath); + + return 0; + } + } + + return Policy::Func::mfs(type,basepaths,fusepath,minfreespace,paths); +} + +static +int +_fwfs(const Category::Enum::Type type, + const vector &basepaths, + const string &fusepath, + const size_t minfreespace, + vector &paths) +{ + for(size_t i = 0, size = basepaths.size(); i != size; i++) + { + int rv; + string fullpath; + const char *basepath; + struct statvfs fsstats; + + basepath = basepaths[i].c_str(); + fullpath = fs::path::make(basepath,fusepath); + rv = ::statvfs(fullpath.c_str(),&fsstats); + if(rv == 0) + { + fsblkcnt_t spaceavail; + + spaceavail = (fsstats.f_frsize * fsstats.f_bavail); + if(spaceavail < minfreespace) + continue; + + paths.push_back(basepath); + + return 0; + } + } + + return Policy::Func::mfs(type,basepaths,fusepath,minfreespace,paths); +} namespace mergerfs { int - Policy::Func::fwfs(const vector &basepaths, - const string &fusepath, - const size_t minfreespace, - Paths &paths) + Policy::Func::fwfs(const Category::Enum::Type type, + const vector &basepaths, + const string &fusepath, + const size_t minfreespace, + vector &paths) { - for(size_t i = 0, size = basepaths.size(); i != size; i++) - { - int rv; - const char *basepath; - struct statvfs fsstats; - - basepath = basepaths[i].c_str(); - rv = ::statvfs(basepath,&fsstats); - if(rv == 0) - { - fsblkcnt_t spaceavail; - - spaceavail = (fsstats.f_frsize * fsstats.f_bavail); - if(spaceavail > minfreespace) - { - paths.push_back(Path(basepath, - fs::make_path(basepath,fusepath))); - return 0; - } - } - } - - return mfs(basepaths,fusepath,minfreespace,paths); + if(type == Category::Enum::create) + return _fwfs_create(type,basepaths,fusepath,minfreespace,paths); + + return _fwfs(type,basepaths,fusepath,minfreespace,paths); } } diff --git a/src/policy_invalid.cpp b/src/policy_invalid.cpp index 829db3e5..5fa251db 100644 --- a/src/policy_invalid.cpp +++ b/src/policy_invalid.cpp @@ -36,10 +36,11 @@ using std::size_t; namespace mergerfs { int - Policy::Func::invalid(const vector &basepaths, - const string &fusepath, - const size_t minfreespace, - Paths &rv) + Policy::Func::invalid(const Category::Enum::Type type, + const vector &basepaths, + const string &fusepath, + const size_t minfreespace, + vector &rv) { return (errno = EINVAL,-1); } diff --git a/src/policy_lfs.cpp b/src/policy_lfs.cpp index 89cc22be..8ec98772 100644 --- a/src/policy_lfs.cpp +++ b/src/policy_lfs.cpp @@ -36,48 +36,109 @@ using std::string; using std::vector; using std::size_t; +using mergerfs::Policy; +using mergerfs::Category; + +static +int +_lfs_create(const Category::Enum::Type type, + const vector &basepaths, + const string &fusepath, + const size_t minfreespace, + vector &paths) +{ + fsblkcnt_t lfs; + const char *lfsstr; + + lfs = -1; + lfsstr = NULL; + for(size_t i = 0, ei = basepaths.size(); i != ei; i++) + { + int rv; + const char *basepath; + struct statvfs fsstats; + + basepath = basepaths[i].c_str(); + rv = ::statvfs(basepath,&fsstats); + if(rv == 0) + { + fsblkcnt_t spaceavail; + + spaceavail = (fsstats.f_frsize * fsstats.f_bavail); + if((spaceavail > minfreespace) && + (spaceavail < lfs)) + { + lfs = spaceavail; + lfsstr = basepath; + } + } + } + + if(lfsstr == NULL) + return Policy::Func::mfs(type,basepaths,fusepath,minfreespace,paths); + + paths.push_back(lfsstr); + + return 0; +} + +static +int +_lfs(const Category::Enum::Type type, + const vector &basepaths, + const string &fusepath, + const size_t minfreespace, + vector &paths) +{ + fsblkcnt_t lfs; + const char *lfsstr; + + lfs = -1; + lfsstr = NULL; + for(size_t i = 0, ei = basepaths.size(); i != ei; i++) + { + int rv; + string fullpath; + const char *basepath; + struct statvfs fsstats; + + basepath = basepaths[i].c_str(); + fullpath = fs::path::make(basepath,fusepath); + rv = ::statvfs(fullpath.c_str(),&fsstats); + if(rv == 0) + { + fsblkcnt_t spaceavail; + + spaceavail = (fsstats.f_frsize * fsstats.f_bavail); + if((spaceavail > minfreespace) && + (spaceavail < lfs)) + { + lfs = spaceavail; + lfsstr = basepath; + } + } + } + + if(lfsstr == NULL) + return Policy::Func::mfs(type,basepaths,fusepath,minfreespace,paths); + + paths.push_back(lfsstr); + + return 0; +} namespace mergerfs { int - Policy::Func::lfs(const vector &basepaths, - const string &fusepath, - const size_t minfreespace, - Paths &paths) + Policy::Func::lfs(const Category::Enum::Type type, + const vector &basepaths, + const string &fusepath, + const size_t minfreespace, + vector &paths) { - fsblkcnt_t lfs; - const char *lfsstr; - - lfs = -1; - lfsstr = NULL; - for(size_t i = 0, size = basepaths.size(); i != size; i++) - { - int rv; - const char *basepath; - struct statvfs fsstats; - - basepath = basepaths[i].c_str(); - rv = ::statvfs(basepath,&fsstats); - if(rv == 0) - { - fsblkcnt_t spaceavail; - - spaceavail = (fsstats.f_frsize * fsstats.f_bavail); - if((spaceavail > minfreespace) && - (spaceavail < lfs)) - { - lfs = spaceavail; - lfsstr = basepath; - } - } - } - - if(lfsstr == NULL) - return Policy::Func::mfs(basepaths,fusepath,minfreespace,paths); - - paths.push_back(Path(lfsstr, - fs::make_path(lfsstr,fusepath))); - - return 0; + if(type == Category::Enum::create) + return _lfs_create(type,basepaths,fusepath,minfreespace,paths); + + return _lfs(type,basepaths,fusepath,minfreespace,paths); } } diff --git a/src/policy_mfs.cpp b/src/policy_mfs.cpp index 62c0596e..b13d7722 100644 --- a/src/policy_mfs.cpp +++ b/src/policy_mfs.cpp @@ -34,45 +34,100 @@ using std::string; using std::vector; using std::size_t; +static +int +_mfs_create(const vector &basepaths, + const string &fusepath, + vector &paths) +{ + fsblkcnt_t mfs; + const char *mfsstr; + + mfs = 0; + mfsstr = NULL; + for(size_t i = 0, ei = basepaths.size(); i != ei; i++) + { + int rv; + const char *basepath; + struct statvfs fsstats; + + basepath = basepaths[i].c_str(); + rv = ::statvfs(basepath,&fsstats); + if(rv == 0) + { + fsblkcnt_t spaceavail; + + spaceavail = (fsstats.f_frsize * fsstats.f_bavail); + if(spaceavail > mfs) + { + mfs = spaceavail; + mfsstr = basepath; + } + } + } + + if(mfsstr == NULL) + return (errno=ENOENT,-1); + + paths.push_back(mfsstr); + + return 0; +} + +static +int +_mfs(const vector &basepaths, + const string &fusepath, + vector &paths) +{ + fsblkcnt_t mfs; + const char *mfsstr; + + mfs = 0; + mfsstr = NULL; + for(size_t i = 0, ei = basepaths.size(); i != ei; i++) + { + int rv; + string fullpath; + const char *basepath; + struct statvfs fsstats; + + basepath = basepaths[i].c_str(); + fullpath = fs::path::make(basepath,fusepath); + rv = ::statvfs(fullpath.c_str(),&fsstats); + if(rv == 0) + { + fsblkcnt_t spaceavail; + + spaceavail = (fsstats.f_frsize * fsstats.f_bavail); + if(spaceavail > mfs) + { + mfs = spaceavail; + mfsstr = basepath; + } + } + } + + if(mfsstr == NULL) + return (errno=ENOENT,-1); + + paths.push_back(mfsstr); + + return 0; +} + namespace mergerfs { int - Policy::Func::mfs(const vector &basepaths, - const string &fusepath, - const size_t minfreespace, - Paths &paths) + Policy::Func::mfs(const Category::Enum::Type type, + const vector &basepaths, + const string &fusepath, + const size_t minfreespace, + vector &paths) { - fsblkcnt_t mfs; - size_t mfsidx; - - mfs = 0; - for(size_t i = 0, size = basepaths.size(); - i != size; - i++) - { - int rv; - struct statvfs fsstats; - - rv = ::statvfs(basepaths[i].c_str(),&fsstats); - if(rv == 0) - { - fsblkcnt_t spaceavail; - - spaceavail = (fsstats.f_frsize * fsstats.f_bavail); - if(spaceavail > mfs) - { - mfs = spaceavail; - mfsidx = i; - } - } - } - - if(mfs == 0) - return (errno=ENOENT,-1); - - paths.push_back(Path(basepaths[mfsidx], - fs::make_path(basepaths[mfsidx],fusepath))); - - return 0; + if(type == Category::Enum::create) + return _mfs_create(basepaths,fusepath,paths); + + return _mfs(basepaths,fusepath,paths); } } diff --git a/src/policy_newest.cpp b/src/policy_newest.cpp index d260aba7..ea7b9eab 100644 --- a/src/policy_newest.cpp +++ b/src/policy_newest.cpp @@ -36,43 +36,52 @@ using std::string; using std::vector; using std::size_t; +static +int +_newest(const vector &basepaths, + const string &fusepath, + vector &paths) +{ + time_t newest; + const char *neweststr; + + newest = 0; + neweststr = NULL; + for(size_t i = 0, ei = basepaths.size(); i != ei; i++) + { + int rv; + struct stat st; + const char *basepath; + string fullpath; + + basepath = basepaths[i].c_str(); + fullpath = fs::path::make(basepath,fusepath); + + rv = ::lstat(fullpath.c_str(),&st); + if(rv == 0 && st.st_mtime > newest) + { + newest = st.st_mtime; + neweststr = basepath; + } + } + + if(neweststr == NULL) + return (errno=ENOENT,-1); + + paths.push_back(neweststr); + + return 0; +} + namespace mergerfs { int - Policy::Func::newest(const vector &basepaths, - const string &fusepath, - const size_t minfreespace, - Paths &paths) + Policy::Func::newest(const Category::Enum::Type type, + const vector &basepaths, + const string &fusepath, + const size_t minfreespace, + vector &paths) { - time_t newest; - string npath; - vector::const_iterator niter; - - newest = 0; - errno = ENOENT; - for(vector::const_iterator - iter = basepaths.begin(), eiter = basepaths.end(); - iter != eiter; - ++iter) - { - int rv; - struct stat st; - string fullpath; - - fullpath = fs::make_path(*iter,fusepath); - - rv = ::lstat(fullpath.c_str(),&st); - if(rv == 0 && st.st_mtime > newest) - { - newest = st.st_mtime; - niter = iter; - npath = fullpath; - } - } - - if(newest) - return (paths.push_back(Path(*niter,npath)),0); - - return -1; + return _newest(basepaths,fusepath,paths); } } diff --git a/src/policy_rand.cpp b/src/policy_rand.cpp index b4fdc2d7..87049fc2 100644 --- a/src/policy_rand.cpp +++ b/src/policy_rand.cpp @@ -37,14 +37,15 @@ using std::size_t; namespace mergerfs { int - Policy::Func::rand(const vector &basepaths, - const string &fusepath, - const size_t minfreespace, - Paths &paths) + Policy::Func::rand(const Category::Enum::Type type, + const vector &basepaths, + const string &fusepath, + const size_t minfreespace, + vector &paths) { int rv; - rv = Policy::Func::all(basepaths,fusepath,minfreespace,paths); + rv = Policy::Func::all(type,basepaths,fusepath,minfreespace,paths); if(rv == -1) return -1; diff --git a/src/readdir.cpp b/src/readdir.cpp index 0d8f5817..8319d779 100644 --- a/src/readdir.cpp +++ b/src/readdir.cpp @@ -57,15 +57,12 @@ _readdir(const vector &srcmounts, set found; struct stat st = {0}; - for(vector::const_iterator - iter = srcmounts.begin(), enditer = srcmounts.end(); - iter != enditer; - ++iter) + for(size_t i = 0, ei = srcmounts.size(); i != ei; i++) { DIR *dh; string basepath; - basepath = fs::make_path(*iter,dirname); + basepath = fs::path::make(srcmounts[i],dirname); dh = ::opendir(basepath.c_str()); if(!dh) continue; diff --git a/src/readlink.cpp b/src/readlink.cpp index 8ca42216..1a413573 100644 --- a/src/readlink.cpp +++ b/src/readlink.cpp @@ -41,21 +41,23 @@ using mergerfs::Policy; static int -_readlink(const Policy::Func::Ptr searchFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - char *buf, - const size_t size) +_readlink(Policy::Func::Search searchFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + char *buf, + const size_t size) { int rv; - Paths path; + vector path; rv = searchFunc(srcmounts,fusepath,minfreespace,path); if(rv == -1) return -errno; - rv = ::readlink(path[0].full.c_str(),buf,size); + fs::path::append(path[0],fusepath); + + rv = ::readlink(path[0].c_str(),buf,size); if(rv == -1) return -errno; @@ -78,7 +80,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _readlink(*config.readlink, + return _readlink(config.readlink, config.srcmounts, config.minfreespace, fusepath, diff --git a/src/removexattr.cpp b/src/removexattr.cpp index 235bb1bf..ff8d8853 100644 --- a/src/removexattr.cpp +++ b/src/removexattr.cpp @@ -42,26 +42,27 @@ using mergerfs::Policy; static int -_removexattr(const Policy::Func::Ptr actionFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - const char *attrname) +_removexattr(Policy::Func::Action actionFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + const char *attrname) { #ifndef WITHOUT_XATTR int rv; int error; - Paths paths; + vector paths; rv = actionFunc(srcmounts,fusepath,minfreespace,paths); if(rv == -1) return -errno; error = 0; - for(Paths::const_iterator - i = paths.begin(), ei = paths.end(); i != ei; ++i) + for(size_t i = 0, ei = paths.size(); i != ei; i++) { - rv = ::lremovexattr(i->full.c_str(),attrname); + fs::path::append(paths[i],fusepath); + + rv = ::lremovexattr(paths[i].c_str(),attrname); if(rv == -1) error = errno; } @@ -89,7 +90,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _removexattr(*config.removexattr, + return _removexattr(config.removexattr, config.srcmounts, config.minfreespace, fusepath, diff --git a/src/rename.cpp b/src/rename.cpp index e0e05299..89f0860c 100644 --- a/src/rename.cpp +++ b/src/rename.cpp @@ -42,32 +42,33 @@ using mergerfs::Policy; static int -_single_rename(const Policy::Func::Ptr searchFunc, - const vector &srcmounts, - const size_t minfreespace, - const Path &oldpath, - const string &newpath) +_single_rename(Policy::Func::Search searchFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &oldbasepath, + const string &oldfullpath, + const string &newpath) { int rv; - const string fullnewpath = fs::make_path(oldpath.base,newpath); + const string newfullpath = fs::path::make(oldbasepath,newpath); - rv = ::rename(oldpath.full.c_str(),fullnewpath.c_str()); + rv = ::rename(oldfullpath.c_str(),newfullpath.c_str()); if(rv == -1 && errno == ENOENT) { string dirname; - Paths newpathdir; + vector newpathdir; - dirname = fs::dirname(newpath); + dirname = fs::path::dirname(newpath); rv = searchFunc(srcmounts,dirname,minfreespace,newpathdir); if(rv == -1) return -1; { const mergerfs::ugid::SetResetGuard ugid(0,0); - fs::clonepath(newpathdir[0].base,oldpath.base,dirname); + fs::clonepath(newpathdir[0],oldbasepath,dirname); } - rv = ::rename(oldpath.full.c_str(),fullnewpath.c_str()); + rv = ::rename(oldfullpath.c_str(),newfullpath.c_str()); } return rv; @@ -75,26 +76,28 @@ _single_rename(const Policy::Func::Ptr searchFunc, static int -_rename(const Policy::Func::Ptr searchFunc, - const Policy::Func::Ptr actionFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &oldpath, - const string &newpath) +_rename(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; - Paths oldpaths; + vector oldbasepaths; - rv = actionFunc(srcmounts,oldpath,minfreespace,oldpaths); + rv = actionFunc(srcmounts,oldfusepath,minfreespace,oldbasepaths); if(rv == -1) return -errno; error = 0; - for(Paths::const_iterator - i = oldpaths.begin(), ei = oldpaths.end(); i != ei; ++i) + for(size_t i = 0, ei = oldbasepaths.size(); i != ei; i++) { - rv = _single_rename(searchFunc,srcmounts,minfreespace,*i,newpath); + const string oldfullpath = fs::path::make(oldbasepaths[i],oldfusepath); + + rv = _single_rename(searchFunc,srcmounts,minfreespace, + oldbasepaths[i],oldfullpath,newfusepath); if(rv == -1) error = errno; } @@ -115,8 +118,8 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _rename(*config.getattr, - *config.rename, + return _rename(config.getattr, + config.rename, config.srcmounts, config.minfreespace, oldpath, diff --git a/src/rmdir.cpp b/src/rmdir.cpp index dd9e1abe..5be43959 100644 --- a/src/rmdir.cpp +++ b/src/rmdir.cpp @@ -40,24 +40,25 @@ using mergerfs::Policy; static int -_rmdir(const Policy::Func::Ptr actionFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath) +_rmdir(Policy::Func::Action actionFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath) { int rv; int error; - Paths paths; + vector paths; rv = actionFunc(srcmounts,fusepath,minfreespace,paths); if(rv == -1) return -errno; error = 0; - for(Paths::const_iterator - i = paths.begin(), ei = paths.end(); i != ei; ++i) + for(size_t i = 0, ei = paths.size(); i != ei; i++) { - rv = ::rmdir(i->full.c_str()); + fs::path::append(paths[i],fusepath); + + rv = ::rmdir(paths[i].c_str()); if(rv == -1) error = errno; } @@ -77,7 +78,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readguard(&config.srcmountslock); - return _rmdir(*config.rmdir, + return _rmdir(config.rmdir, config.srcmounts, config.minfreespace, fusepath); diff --git a/src/setxattr.cpp b/src/setxattr.cpp index c2d5c870..00754f8b 100644 --- a/src/setxattr.cpp +++ b/src/setxattr.cpp @@ -240,29 +240,30 @@ _setxattr_controlfile(config::Config &config, static int -_setxattr(const Policy::Func::Ptr actionFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - const char *attrname, - const char *attrval, - const size_t attrvalsize, - const int flags) +_setxattr(Policy::Func::Action actionFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + const char *attrname, + const char *attrval, + const size_t attrvalsize, + const int flags) { #ifndef WITHOUT_XATTR int rv; int error; - Paths paths; + vector paths; rv = actionFunc(srcmounts,fusepath,minfreespace,paths); if(rv == -1) return -errno; error = 0; - for(Paths::const_iterator - i = paths.begin(), ei = paths.end(); i != ei; ++i) + for(size_t i = 0, ei = paths.size(); i != ei; i++) { - rv = ::lsetxattr(i->full.c_str(),attrname,attrval,attrvalsize,flags); + fs::path::append(paths[i],fusepath); + + rv = ::lsetxattr(paths[i].c_str(),attrname,attrval,attrvalsize,flags); if(rv == -1) error = errno; } @@ -301,7 +302,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _setxattr(*config.setxattr, + return _setxattr(config.setxattr, config.srcmounts, config.minfreespace, fusepath, diff --git a/src/statfs.cpp b/src/statfs.cpp index 3ae39c35..5aab37ed 100644 --- a/src/statfs.cpp +++ b/src/statfs.cpp @@ -82,11 +82,11 @@ _statfs(const vector &srcmounts, vector::const_iterator iter; vector::const_iterator enditer; - for(iter = srcmounts.begin(), enditer = srcmounts.end(); iter != enditer; ++iter) + for(size_t i = 0, ei = srcmounts.size(); i != ei; i++) { int rv; struct statvfs fsstat; - rv = ::statvfs(iter->c_str(),&fsstat); + rv = ::statvfs(srcmounts[i].c_str(),&fsstat); if(rv != 0) continue; diff --git a/src/symlink.cpp b/src/symlink.cpp index 418310d0..defffce2 100644 --- a/src/symlink.cpp +++ b/src/symlink.cpp @@ -40,29 +40,28 @@ using mergerfs::Policy; static int -_symlink(const Policy::Func::Ptr createFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &oldpath, - const string &newpath) +_symlink(Policy::Func::Create createFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &oldpath, + const string &newpath) { int rv; int error; string newpathdir; - Paths newpathdirs; + vector newpathdirs; - newpathdir = fs::dirname(newpath); + newpathdir = fs::path::dirname(newpath); rv = createFunc(srcmounts,newpathdir,minfreespace,newpathdirs); if(rv == -1) return -errno; error = 0; - for(Paths::iterator - i = newpathdirs.begin(), ei = newpathdirs.end(); i != ei; ++i) + for(size_t i = 0, ei = newpathdirs.size(); i != ei; i++) { - i->full = fs::make_path(i->base,newpath); + fs::path::append(newpathdirs[i],newpath); - rv = symlink(oldpath.c_str(),i->full.c_str()); + rv = symlink(oldpath.c_str(),newpathdirs[i].c_str()); if(rv == -1) error = errno; } @@ -83,7 +82,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _symlink(*config.symlink, + return _symlink(config.symlink, config.srcmounts, config.minfreespace, oldpath, diff --git a/src/truncate.cpp b/src/truncate.cpp index 70f0df6b..d7ae5cf5 100644 --- a/src/truncate.cpp +++ b/src/truncate.cpp @@ -42,25 +42,26 @@ using mergerfs::Policy; static int -_truncate(const Policy::Func::Ptr actionFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - const off_t size) +_truncate(Policy::Func::Action actionFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + const off_t size) { int rv; int error; - Paths paths; + vector paths; rv = actionFunc(srcmounts,fusepath,minfreespace,paths); if(rv == -1) return -errno; error = 0; - for(Paths::const_iterator - i = paths.begin(), ei = paths.end(); i != ei; ++i) + for(size_t i = 0, ei = paths.size(); i != ei; i++) { - rv = ::truncate(i->full.c_str(),size); + fs::path::append(paths[i],fusepath); + + rv = ::truncate(paths[i].c_str(),size); if(rv == -1) error = errno; } @@ -81,7 +82,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _truncate(*config.truncate, + return _truncate(config.truncate, config.srcmounts, config.minfreespace, fusepath, diff --git a/src/unlink.cpp b/src/unlink.cpp index e6965635..5b4537ce 100644 --- a/src/unlink.cpp +++ b/src/unlink.cpp @@ -41,24 +41,25 @@ using mergerfs::Policy; static int -_unlink(const Policy::Func::Ptr actionFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath) +_unlink(Policy::Func::Action actionFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath) { int rv; int error; - Paths paths; + vector paths; rv = actionFunc(srcmounts,fusepath,minfreespace,paths); if(rv == -1) return -errno; error = 0; - for(Paths::const_iterator - i = paths.begin(), ei = paths.end(); i != ei; ++i) + for(size_t i = 0, ei = paths.size(); i != ei; i++) { - rv = ::unlink(i->full.c_str()); + fs::path::append(paths[i],fusepath); + + rv = ::unlink(paths[i].c_str()); if(rv == -1) error = errno; } @@ -78,7 +79,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _unlink(*config.unlink, + return _unlink(config.unlink, config.srcmounts, config.minfreespace, fusepath); diff --git a/src/utimens.cpp b/src/utimens.cpp index 42f4bc99..e623a3d5 100644 --- a/src/utimens.cpp +++ b/src/utimens.cpp @@ -42,25 +42,26 @@ using mergerfs::Policy; static int -_utimens(const Policy::Func::Ptr actionFunc, - const vector &srcmounts, - const size_t minfreespace, - const string &fusepath, - const struct timespec ts[2]) +_utimens(Policy::Func::Action actionFunc, + const vector &srcmounts, + const size_t minfreespace, + const string &fusepath, + const struct timespec ts[2]) { int rv; int error; - Paths paths; + vector paths; rv = actionFunc(srcmounts,fusepath,minfreespace,paths); if(rv == -1) return -errno; error = 0; - for(Paths::const_iterator - i = paths.begin(), ei = paths.end(); i != ei; ++i) + for(size_t i = 0, ei = paths.size(); i != ei; i++) { - rv = ::utimensat(0,i->full.c_str(),ts,AT_SYMLINK_NOFOLLOW); + fs::path::append(paths[i],fusepath); + + rv = ::utimensat(0,paths[i].c_str(),ts,AT_SYMLINK_NOFOLLOW); if(rv == -1) error = errno; } @@ -81,7 +82,7 @@ namespace mergerfs const ugid::SetResetGuard ugid(fc->uid,fc->gid); const rwlock::ReadGuard readlock(&config.srcmountslock); - return _utimens(*config.utimens, + return _utimens(config.utimens, config.srcmounts, config.minfreespace, fusepath,