mirror of
https://github.com/trapexit/mergerfs.git
synced 2025-01-21 12:39:30 +08:00
commit
1d798ad285
|
@ -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<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const int mask)
|
||||
_access(Policy::Func::Search searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const int mask)
|
||||
{
|
||||
int rv;
|
||||
Paths paths;
|
||||
vector<string> 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,
|
||||
|
|
|
@ -39,25 +39,26 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_chmod(const Policy::Func::Ptr actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const mode_t mode)
|
||||
_chmod(Policy::Func::Action actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const mode_t mode)
|
||||
{
|
||||
int rv;
|
||||
int error;
|
||||
Paths paths;
|
||||
vector<string> 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,
|
||||
|
|
|
@ -40,26 +40,27 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_chown(const Policy::Func::Ptr actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const uid_t uid,
|
||||
const gid_t gid)
|
||||
_chown(Policy::Func::Action actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const uid_t uid,
|
||||
const gid_t gid)
|
||||
{
|
||||
int rv;
|
||||
int error;
|
||||
Paths paths;
|
||||
vector<string> 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,
|
||||
|
|
|
@ -43,23 +43,22 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_create(const Policy::Func::Ptr searchFunc,
|
||||
const Policy::Func::Ptr createFunc,
|
||||
const vector<string> &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<string> &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<string> createpath;
|
||||
vector<string> 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,
|
||||
|
|
156
src/fs.cpp
156
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;
|
||||
string
|
||||
dirname(const string &path)
|
||||
{
|
||||
string parent = path;
|
||||
string::reverse_iterator i;
|
||||
string::reverse_iterator bi;
|
||||
|
||||
bi = parent.rend();
|
||||
i = parent.rbegin();
|
||||
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++;
|
||||
|
||||
while(*i == '/' && i != bi)
|
||||
i++;
|
||||
while(*i == '/' && i != bi)
|
||||
i++;
|
||||
|
||||
parent.erase(i.base(),parent.end());
|
||||
parent.erase(i.base(),parent.end());
|
||||
|
||||
return parent;
|
||||
}
|
||||
return parent;
|
||||
}
|
||||
|
||||
string
|
||||
basename(const string &path)
|
||||
{
|
||||
return path.substr(path.find_last_of('/')+1);
|
||||
}
|
||||
string
|
||||
basename(const string &path)
|
||||
{
|
||||
return path.substr(path.find_last_of('/')+1);
|
||||
}
|
||||
|
||||
bool
|
||||
dir_is_empty(const string &path)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *de;
|
||||
|
||||
dir = ::opendir(path.c_str());
|
||||
if(!dir)
|
||||
return false;
|
||||
|
||||
while((de = ::readdir(dir)))
|
||||
{
|
||||
const char *d_name = de->d_name;
|
||||
|
||||
if(d_name[0] == '.' &&
|
||||
((d_name[1] == '\0') ||
|
||||
(d_name[1] == '.' && d_name[2] == '\0')))
|
||||
continue;
|
||||
|
||||
::closedir(dir);
|
||||
bool
|
||||
is_empty(const string &path)
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *de;
|
||||
|
||||
dir = ::opendir(path.c_str());
|
||||
if(!dir)
|
||||
return false;
|
||||
}
|
||||
|
||||
::closedir(dir);
|
||||
while((de = ::readdir(dir)))
|
||||
{
|
||||
const char *d_name = de->d_name;
|
||||
|
||||
return true;
|
||||
}
|
||||
if(d_name[0] == '.' &&
|
||||
((d_name[1] == '\0') ||
|
||||
(d_name[1] == '.' && d_name[2] == '\0')))
|
||||
continue;
|
||||
|
||||
string
|
||||
make_path(const string &base,
|
||||
const string &suffix)
|
||||
{
|
||||
if(suffix[0] == '/' ||
|
||||
*base.rbegin() == '/')
|
||||
return base + suffix;
|
||||
return base + '/' + suffix;
|
||||
}
|
||||
::closedir(dir);
|
||||
|
||||
bool
|
||||
path_exists(vector<string>::const_iterator begin,
|
||||
vector<string>::const_iterator end,
|
||||
const string &fusepath)
|
||||
{
|
||||
for(vector<string>::const_iterator
|
||||
iter = begin; iter != end; ++iter)
|
||||
{
|
||||
int rv;
|
||||
string path;
|
||||
struct stat st;
|
||||
return false;
|
||||
}
|
||||
|
||||
path = fs::make_path(*iter,fusepath);
|
||||
rv = ::lstat(path.c_str(),&st);
|
||||
if(rv == 0)
|
||||
return true;
|
||||
}
|
||||
::closedir(dir);
|
||||
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
bool
|
||||
path_exists(const vector<string> &srcmounts,
|
||||
const string &fusepath)
|
||||
{
|
||||
return path_exists(srcmounts.begin(),
|
||||
srcmounts.end(),
|
||||
fusepath);
|
||||
bool
|
||||
exists(const vector<string> &paths,
|
||||
const string &fusepath)
|
||||
{
|
||||
for(size_t i = 0, ei = paths.size(); i != ei; i++)
|
||||
{
|
||||
int rv;
|
||||
string path;
|
||||
struct stat st;
|
||||
|
||||
path = fs::path::make(paths[i],fusepath);
|
||||
|
||||
rv = ::lstat(path.c_str(),&st);
|
||||
if(rv == 0)
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -166,16 +149,14 @@ namespace fs
|
|||
const string &fusepath,
|
||||
vector<string> &paths)
|
||||
{
|
||||
for(vector<string>::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)
|
||||
{
|
||||
|
|
36
src/fs.hpp
36
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);
|
||||
namespace path
|
||||
{
|
||||
string dirname(const string &path);
|
||||
string basename(const string &path);
|
||||
|
||||
bool dir_is_empty(const string &path);
|
||||
bool is_empty(const string &path);
|
||||
|
||||
string make_path(const string &base,
|
||||
const string &suffix);
|
||||
bool exists(vector<string>::const_iterator begin,
|
||||
vector<string>::const_iterator end,
|
||||
const string &fusepath);
|
||||
bool exists(const vector<string> &srcmounts,
|
||||
const string &fusepath);
|
||||
|
||||
bool path_exists(vector<string>::const_iterator begin,
|
||||
vector<string>::const_iterator end,
|
||||
const string &fusepath);
|
||||
bool path_exists(const vector<string> &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<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
|
|
|
@ -66,20 +66,22 @@ _getattr_controlfile(struct stat &buf)
|
|||
|
||||
static
|
||||
int
|
||||
_getattr(const Policy::Func::Ptr searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
struct stat &buf)
|
||||
_getattr(Policy::Func::Search searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
struct stat &buf)
|
||||
{
|
||||
int rv;
|
||||
Paths path;
|
||||
vector<string> 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,
|
||||
|
|
|
@ -167,9 +167,10 @@ _getxattr_user_mergerfs_allpaths(const vector<string> &srcmounts,
|
|||
|
||||
static
|
||||
int
|
||||
_getxattr_user_mergerfs(const Path &path,
|
||||
const vector<string> &srcmounts,
|
||||
_getxattr_user_mergerfs(const string &basepath,
|
||||
const string &fusepath,
|
||||
const string &fullpath,
|
||||
const vector<string> &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<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const char *attrname,
|
||||
char *buf,
|
||||
const size_t count)
|
||||
_getxattr(Policy::Func::Search searchFunc,
|
||||
const vector<string> &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<string> 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,
|
||||
|
|
|
@ -82,30 +82,32 @@ _ioctl(const int fd,
|
|||
#ifdef FUSE_IOCTL_DIR
|
||||
static
|
||||
int
|
||||
_ioctl_dir_base(const Policy::Func::Ptr searchFunc,
|
||||
const vector<string> &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<string> &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<string> 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,
|
||||
|
|
45
src/link.cpp
45
src/link.cpp
|
@ -41,31 +41,31 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_single_link(const Policy::Func::Ptr searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &base,
|
||||
const string &oldpath,
|
||||
const string &newpath)
|
||||
_single_link(Policy::Func::Search searchFunc,
|
||||
const vector<string> &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<string> 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<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &oldpath,
|
||||
const string &newpath)
|
||||
_link(Policy::Func::Search searchFunc,
|
||||
Policy::Func::Action actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &oldpath,
|
||||
const string &newpath)
|
||||
{
|
||||
int rv;
|
||||
int error;
|
||||
Paths oldpaths;
|
||||
vector<string> 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,
|
||||
|
|
|
@ -69,22 +69,24 @@ _listxattr_controlfile(char *list,
|
|||
|
||||
static
|
||||
int
|
||||
_listxattr(const Policy::Func::Ptr searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
char *list,
|
||||
const size_t size)
|
||||
_listxattr(Policy::Func::Search searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
char *list,
|
||||
const size_t size)
|
||||
{
|
||||
#ifndef WITHOUT_XATTR
|
||||
int rv;
|
||||
Paths path;
|
||||
vector<string> 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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -42,21 +42,21 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_mkdir(const Policy::Func::Ptr searchFunc,
|
||||
const Policy::Func::Ptr createFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const mode_t mode)
|
||||
_mkdir(Policy::Func::Search searchFunc,
|
||||
Policy::Func::Create createFunc,
|
||||
const vector<string> &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<string> createpaths;
|
||||
vector<string> 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,
|
||||
|
|
|
@ -44,22 +44,21 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_mknod(const Policy::Func::Ptr searchFunc,
|
||||
const Policy::Func::Ptr createFunc,
|
||||
const vector<string> &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<string> &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<string> createpaths;
|
||||
vector<string> 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,
|
||||
|
|
18
src/open.cpp
18
src/open.cpp
|
@ -42,22 +42,22 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_open(const Policy::Func::Ptr searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const int flags,
|
||||
uint64_t &fh)
|
||||
_open(Policy::Func::Search searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const int flags,
|
||||
uint64_t &fh)
|
||||
{
|
||||
int fd;
|
||||
int rv;
|
||||
Paths path;
|
||||
vector<string> 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,
|
||||
|
|
|
@ -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;
|
||||
|
||||
|
|
|
@ -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<string> strvec;
|
||||
typedef const string cstring;
|
||||
typedef const size_t csize_t;
|
||||
typedef const strvec cstrvec;
|
||||
typedef const Category::Enum::Type CType;
|
||||
|
||||
typedef int (*Ptr)(const strvec&,const string&,const size_t,Paths&);
|
||||
typedef int (*Ptr)(CType,cstrvec&,cstring&,csize_t,strvec&);
|
||||
|
||||
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&);
|
||||
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<Policy> _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;
|
||||
};
|
||||
}
|
||||
|
||||
|
|
|
@ -36,30 +36,40 @@ using std::string;
|
|||
using std::vector;
|
||||
using std::size_t;
|
||||
|
||||
static
|
||||
int
|
||||
_all(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
vector<string> &paths)
|
||||
{
|
||||
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);
|
||||
|
||||
rv = ::lstat(fullpath.c_str(),&st);
|
||||
if(rv == 0)
|
||||
paths.push_back(basepath);
|
||||
}
|
||||
|
||||
return paths.empty() ? (errno=ENOENT,-1) : 0;
|
||||
}
|
||||
|
||||
namespace mergerfs
|
||||
{
|
||||
int
|
||||
Policy::Func::all(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
Paths &paths)
|
||||
Policy::Func::all(const Category::Enum::Type type,
|
||||
const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
vector<string> &paths)
|
||||
{
|
||||
int rv;
|
||||
struct stat st;
|
||||
string fullpath;
|
||||
|
||||
for(vector<string>::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(Path(*iter,fullpath));
|
||||
}
|
||||
|
||||
return paths.empty() ? (errno=ENOENT,-1) : 0;
|
||||
return _all(basepaths,fusepath,paths);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<string> &basepaths,
|
||||
const string &fusepath,
|
||||
vector<string> &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<string> &basepaths,
|
||||
const string &fusepath,
|
||||
vector<string> &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<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
Paths &paths)
|
||||
Policy::Func::epmfs(const Category::Enum::Type type,
|
||||
const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
vector<string> &paths)
|
||||
{
|
||||
fsblkcnt_t existingmfs;
|
||||
fsblkcnt_t generalmfs;
|
||||
string fullpath;
|
||||
string generalmfspath;
|
||||
string existingmfspath;
|
||||
vector<string>::const_iterator iter = basepaths.begin();
|
||||
vector<string>::const_iterator eiter = basepaths.end();
|
||||
if(type == Category::Enum::create)
|
||||
return _epmfs_create(basepaths,fusepath,paths);
|
||||
|
||||
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;
|
||||
return _epmfs(basepaths,fusepath,paths);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,34 +37,43 @@ using std::string;
|
|||
using std::vector;
|
||||
using std::size_t;
|
||||
|
||||
static
|
||||
int
|
||||
_ff(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
vector<string> &paths)
|
||||
{
|
||||
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 == -1)
|
||||
continue;
|
||||
|
||||
paths.push_back(basepath);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (errno=ENOENT,-1);
|
||||
}
|
||||
|
||||
namespace mergerfs
|
||||
{
|
||||
int
|
||||
Policy::Func::ff(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
Paths &paths)
|
||||
Policy::Func::ff(const Category::Enum::Type type,
|
||||
const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
vector<string> &paths)
|
||||
{
|
||||
errno = ENOENT;
|
||||
for(vector<string>::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;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
return _ff(basepaths,fusepath,paths);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,44 +36,54 @@ using std::string;
|
|||
using std::vector;
|
||||
using std::size_t;
|
||||
|
||||
static
|
||||
int
|
||||
_ffwp(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
vector<string> &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<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
Paths &paths)
|
||||
Policy::Func::ffwp(const Category::Enum::Type type,
|
||||
const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
vector<string> &paths)
|
||||
{
|
||||
Path fallback;
|
||||
|
||||
errno = ENOENT;
|
||||
for(vector<string>::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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
vector<string> &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<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
vector<string> &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<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
Paths &paths)
|
||||
Policy::Func::fwfs(const Category::Enum::Type type,
|
||||
const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
vector<string> &paths)
|
||||
{
|
||||
for(size_t i = 0, size = basepaths.size(); i != size; i++)
|
||||
{
|
||||
int rv;
|
||||
const char *basepath;
|
||||
struct statvfs fsstats;
|
||||
if(type == Category::Enum::create)
|
||||
return _fwfs_create(type,basepaths,fusepath,minfreespace,paths);
|
||||
|
||||
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);
|
||||
return _fwfs(type,basepaths,fusepath,minfreespace,paths);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,10 +36,11 @@ using std::size_t;
|
|||
namespace mergerfs
|
||||
{
|
||||
int
|
||||
Policy::Func::invalid(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
Paths &rv)
|
||||
Policy::Func::invalid(const Category::Enum::Type type,
|
||||
const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
vector<string> &rv)
|
||||
{
|
||||
return (errno = EINVAL,-1);
|
||||
}
|
||||
|
|
|
@ -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<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
vector<string> &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<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
vector<string> &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<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
Paths &paths)
|
||||
Policy::Func::lfs(const Category::Enum::Type type,
|
||||
const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
vector<string> &paths)
|
||||
{
|
||||
fsblkcnt_t lfs;
|
||||
const char *lfsstr;
|
||||
if(type == Category::Enum::create)
|
||||
return _lfs_create(type,basepaths,fusepath,minfreespace,paths);
|
||||
|
||||
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;
|
||||
return _lfs(type,basepaths,fusepath,minfreespace,paths);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -34,45 +34,100 @@ using std::string;
|
|||
using std::vector;
|
||||
using std::size_t;
|
||||
|
||||
static
|
||||
int
|
||||
_mfs_create(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
vector<string> &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<string> &basepaths,
|
||||
const string &fusepath,
|
||||
vector<string> &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<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
Paths &paths)
|
||||
Policy::Func::mfs(const Category::Enum::Type type,
|
||||
const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
vector<string> &paths)
|
||||
{
|
||||
fsblkcnt_t mfs;
|
||||
size_t mfsidx;
|
||||
if(type == Category::Enum::create)
|
||||
return _mfs_create(basepaths,fusepath,paths);
|
||||
|
||||
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;
|
||||
return _mfs(basepaths,fusepath,paths);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,43 +36,52 @@ using std::string;
|
|||
using std::vector;
|
||||
using std::size_t;
|
||||
|
||||
static
|
||||
int
|
||||
_newest(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
vector<string> &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<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
Paths &paths)
|
||||
Policy::Func::newest(const Category::Enum::Type type,
|
||||
const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
vector<string> &paths)
|
||||
{
|
||||
time_t newest;
|
||||
string npath;
|
||||
vector<string>::const_iterator niter;
|
||||
|
||||
newest = 0;
|
||||
errno = ENOENT;
|
||||
for(vector<string>::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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,14 +37,15 @@ using std::size_t;
|
|||
namespace mergerfs
|
||||
{
|
||||
int
|
||||
Policy::Func::rand(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
Paths &paths)
|
||||
Policy::Func::rand(const Category::Enum::Type type,
|
||||
const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
const size_t minfreespace,
|
||||
vector<string> &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;
|
||||
|
||||
|
|
|
@ -57,15 +57,12 @@ _readdir(const vector<string> &srcmounts,
|
|||
set<string> found;
|
||||
struct stat st = {0};
|
||||
|
||||
for(vector<string>::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;
|
||||
|
|
|
@ -41,21 +41,23 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_readlink(const Policy::Func::Ptr searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
char *buf,
|
||||
const size_t size)
|
||||
_readlink(Policy::Func::Search searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
char *buf,
|
||||
const size_t size)
|
||||
{
|
||||
int rv;
|
||||
Paths path;
|
||||
vector<string> 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,
|
||||
|
|
|
@ -42,26 +42,27 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_removexattr(const Policy::Func::Ptr actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const char *attrname)
|
||||
_removexattr(Policy::Func::Action actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const char *attrname)
|
||||
{
|
||||
#ifndef WITHOUT_XATTR
|
||||
int rv;
|
||||
int error;
|
||||
Paths paths;
|
||||
vector<string> 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,
|
||||
|
|
|
@ -42,32 +42,33 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_single_rename(const Policy::Func::Ptr searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const Path &oldpath,
|
||||
const string &newpath)
|
||||
_single_rename(Policy::Func::Search searchFunc,
|
||||
const vector<string> &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<string> 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<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &oldpath,
|
||||
const string &newpath)
|
||||
_rename(Policy::Func::Search searchFunc,
|
||||
Policy::Func::Action actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &oldfusepath,
|
||||
const string &newfusepath)
|
||||
{
|
||||
int rv;
|
||||
int error;
|
||||
Paths oldpaths;
|
||||
vector<string> 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,
|
||||
|
|
|
@ -40,24 +40,25 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_rmdir(const Policy::Func::Ptr actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath)
|
||||
_rmdir(Policy::Func::Action actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath)
|
||||
{
|
||||
int rv;
|
||||
int error;
|
||||
Paths paths;
|
||||
vector<string> 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);
|
||||
|
|
|
@ -240,29 +240,30 @@ _setxattr_controlfile(config::Config &config,
|
|||
|
||||
static
|
||||
int
|
||||
_setxattr(const Policy::Func::Ptr actionFunc,
|
||||
const vector<string> &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<string> &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<string> 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,
|
||||
|
|
|
@ -82,11 +82,11 @@ _statfs(const vector<string> &srcmounts,
|
|||
vector<string>::const_iterator iter;
|
||||
vector<string>::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;
|
||||
|
||||
|
|
|
@ -40,29 +40,28 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_symlink(const Policy::Func::Ptr createFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &oldpath,
|
||||
const string &newpath)
|
||||
_symlink(Policy::Func::Create createFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &oldpath,
|
||||
const string &newpath)
|
||||
{
|
||||
int rv;
|
||||
int error;
|
||||
string newpathdir;
|
||||
Paths newpathdirs;
|
||||
vector<string> 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,
|
||||
|
|
|
@ -42,25 +42,26 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_truncate(const Policy::Func::Ptr actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const off_t size)
|
||||
_truncate(Policy::Func::Action actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const off_t size)
|
||||
{
|
||||
int rv;
|
||||
int error;
|
||||
Paths paths;
|
||||
vector<string> 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,
|
||||
|
|
|
@ -41,24 +41,25 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_unlink(const Policy::Func::Ptr actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath)
|
||||
_unlink(Policy::Func::Action actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath)
|
||||
{
|
||||
int rv;
|
||||
int error;
|
||||
Paths paths;
|
||||
vector<string> 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);
|
||||
|
|
|
@ -42,25 +42,26 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_utimens(const Policy::Func::Ptr actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const struct timespec ts[2])
|
||||
_utimens(Policy::Func::Action actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const size_t minfreespace,
|
||||
const string &fusepath,
|
||||
const struct timespec ts[2])
|
||||
{
|
||||
int rv;
|
||||
int error;
|
||||
Paths paths;
|
||||
vector<string> 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,
|
||||
|
|
Loading…
Reference in New Issue
Block a user