mirror of
https://github.com/trapexit/mergerfs.git
synced 2025-02-08 10:07:31 +08:00
Merge pull request #219 from trapexit/pathmake
use references to srcmounts rather than copies
This commit is contained in:
commit
c568a6d356
|
@ -35,19 +35,20 @@ int
|
||||||
_access(Policy::Func::Search searchFunc,
|
_access(Policy::Func::Search searchFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const int mask)
|
const int mask)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
string path;
|
string fullpath;
|
||||||
|
vector<const string*> basepaths;
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,minfreespace,path);
|
rv = searchFunc(srcmounts,fusepath,minfreespace,basepaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
fs::path::append(path,fusepath);
|
fs::path::make(basepaths[0],fusepath,fullpath);
|
||||||
|
|
||||||
rv = ::eaccess(path.c_str(),mask);
|
rv = ::eaccess(fullpath.c_str(),mask);
|
||||||
|
|
||||||
return ((rv == -1) ? -errno : 0);
|
return ((rv == -1) ? -errno : 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,33 +32,56 @@ using mergerfs::Policy;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_chmod(Policy::Func::Action actionFunc,
|
_chmod_loop_core(const string *basepath,
|
||||||
const vector<string> &srcmounts,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const mode_t mode,
|
||||||
const string &fusepath,
|
const int error)
|
||||||
const mode_t mode)
|
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
string fullpath;
|
||||||
vector<string> paths;
|
|
||||||
|
|
||||||
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
if(rv == -1)
|
|
||||||
return -errno;
|
rv = ::chmod(fullpath.c_str(),mode);
|
||||||
|
|
||||||
|
return calc_error(rv,error,errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_chmod_loop(const vector<const string*> &basepaths,
|
||||||
|
const char *fusepath,
|
||||||
|
const mode_t mode)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
error = -1;
|
error = -1;
|
||||||
for(size_t i = 0, ei = paths.size(); i != ei; i++)
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
fs::path::append(paths[i],fusepath);
|
error = _chmod_loop_core(basepaths[i],fusepath,mode,error);
|
||||||
|
|
||||||
rv = ::chmod(paths[i].c_str(),mode);
|
|
||||||
|
|
||||||
error = calc_error(rv,error,errno);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -error;
|
return -error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_chmod(Policy::Func::Action actionFunc,
|
||||||
|
const vector<string> &srcmounts,
|
||||||
|
const size_t minfreespace,
|
||||||
|
const char *fusepath,
|
||||||
|
const mode_t mode)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
vector<const string*> basepaths;
|
||||||
|
|
||||||
|
rv = actionFunc(srcmounts,fusepath,minfreespace,basepaths);
|
||||||
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return _chmod_loop(basepaths,fusepath,mode);
|
||||||
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
{
|
{
|
||||||
namespace fuse
|
namespace fuse
|
||||||
|
|
|
@ -32,34 +32,59 @@ using std::vector;
|
||||||
using mergerfs::Policy;
|
using mergerfs::Policy;
|
||||||
using mergerfs::Config;
|
using mergerfs::Config;
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_chown_loop_core(const string *basepath,
|
||||||
|
const char *fusepath,
|
||||||
|
const uid_t uid,
|
||||||
|
const gid_t gid,
|
||||||
|
const int error)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
string fullpath;
|
||||||
|
|
||||||
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
|
|
||||||
|
rv = ::lchown(fullpath.c_str(),uid,gid);
|
||||||
|
|
||||||
|
return calc_error(rv,error,errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_chown_loop(const vector<const string*> &basepaths,
|
||||||
|
const char *fusepath,
|
||||||
|
const uid_t uid,
|
||||||
|
const gid_t gid)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = -1;
|
||||||
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
|
{
|
||||||
|
error = _chown_loop_core(basepaths[i],fusepath,uid,gid,error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -error;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_chown(Policy::Func::Action actionFunc,
|
_chown(Policy::Func::Action actionFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const uid_t uid,
|
const uid_t uid,
|
||||||
const gid_t gid)
|
const gid_t gid)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
vector<const string*> basepaths;
|
||||||
vector<string> paths;
|
|
||||||
|
|
||||||
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
|
rv = actionFunc(srcmounts,fusepath,minfreespace,basepaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
error = -1;
|
return _chown_loop(basepaths,fusepath,uid,gid);
|
||||||
for(size_t i = 0, ei = paths.size(); i != ei; i++)
|
|
||||||
{
|
|
||||||
fs::path::append(paths[i],fusepath);
|
|
||||||
|
|
||||||
rv = ::lchown(paths[i].c_str(),uid,gid);
|
|
||||||
|
|
||||||
error = calc_error(rv,error,errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
|
|
|
@ -38,39 +38,26 @@ using namespace mergerfs;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_create(Policy::Func::Search searchFunc,
|
_create_core(const string &existingpath,
|
||||||
Policy::Func::Create createFunc,
|
const string &createpath,
|
||||||
const vector<string> &srcmounts,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const char *fusedirpath,
|
||||||
const string &fusepath,
|
const mode_t mode,
|
||||||
const mode_t mode,
|
const int flags,
|
||||||
const int flags,
|
uint64_t &fh)
|
||||||
uint64_t &fh)
|
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
int rv;
|
string fullpath;
|
||||||
string dirname;
|
|
||||||
vector<string> createpath;
|
|
||||||
vector<string> existingpath;
|
|
||||||
|
|
||||||
dirname = fs::path::dirname(fusepath);
|
if(createpath != existingpath)
|
||||||
rv = searchFunc(srcmounts,dirname,minfreespace,existingpath);
|
|
||||||
if(rv == -1)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
rv = createFunc(srcmounts,dirname,minfreespace,createpath);
|
|
||||||
if(rv == -1)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
if(createpath[0] != existingpath[0])
|
|
||||||
{
|
{
|
||||||
const ugid::SetRootGuard ugidGuard;
|
const ugid::SetRootGuard ugidGuard;
|
||||||
fs::clonepath(existingpath[0],createpath[0],dirname);
|
fs::clonepath(existingpath,createpath,fusedirpath);
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path::append(createpath[0],fusepath);
|
fs::path::make(&createpath,fusepath,fullpath);
|
||||||
|
|
||||||
fd = ::open(createpath[0].c_str(),flags,mode);
|
fd = ::open(fullpath.c_str(),flags,mode);
|
||||||
if(fd == -1)
|
if(fd == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
|
@ -79,6 +66,41 @@ _create(Policy::Func::Search searchFunc,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_create(Policy::Func::Search searchFunc,
|
||||||
|
Policy::Func::Create createFunc,
|
||||||
|
const vector<string> &srcmounts,
|
||||||
|
const size_t minfreespace,
|
||||||
|
const char *fusepath,
|
||||||
|
const mode_t mode,
|
||||||
|
const int flags,
|
||||||
|
uint64_t &fh)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
string fullpath;
|
||||||
|
string fusedirpath;
|
||||||
|
const char *fusedirpathcstr;
|
||||||
|
vector<const string*> createpaths;
|
||||||
|
vector<const string*> existingpaths;
|
||||||
|
|
||||||
|
fusedirpath = fusepath;
|
||||||
|
fs::path::dirname(fusedirpath);
|
||||||
|
fusedirpathcstr = fusedirpath.c_str();
|
||||||
|
|
||||||
|
rv = searchFunc(srcmounts,fusedirpathcstr,minfreespace,existingpaths);
|
||||||
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
rv = createFunc(srcmounts,fusedirpathcstr,minfreespace,createpaths);
|
||||||
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return _create_core(*existingpaths[0],*createpaths[0],
|
||||||
|
fusepath,fusedirpathcstr,
|
||||||
|
mode,flags,fh);
|
||||||
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
{
|
{
|
||||||
namespace fuse
|
namespace fuse
|
||||||
|
|
|
@ -16,10 +16,6 @@
|
||||||
|
|
||||||
#if FALLOCATE
|
#if FALLOCATE
|
||||||
|
|
||||||
#ifndef _GNU_SOURCE
|
|
||||||
#define _GNU_SOURCE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <fuse.h>
|
#include <fuse.h>
|
||||||
|
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
|
@ -27,11 +27,11 @@ _flush(const int fd)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
rv = dup(fd);
|
rv = ::dup(fd);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
errno = EIO;
|
errno = EIO;
|
||||||
else
|
else
|
||||||
rv = close(rv);
|
rv = ::close(rv);
|
||||||
|
|
||||||
return ((rv == -1) ? -errno : 0);
|
return ((rv == -1) ? -errno : 0);
|
||||||
}
|
}
|
||||||
|
|
20
src/fs.cpp
20
src/fs.cpp
|
@ -40,16 +40,16 @@ namespace fs
|
||||||
{
|
{
|
||||||
void
|
void
|
||||||
findallfiles(const vector<string> &srcmounts,
|
findallfiles(const vector<string> &srcmounts,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
vector<string> &paths)
|
vector<string> &paths)
|
||||||
{
|
{
|
||||||
|
int rv;
|
||||||
|
string fullpath;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
for(size_t i = 0, ei = srcmounts.size(); i != ei; i++)
|
for(size_t i = 0, ei = srcmounts.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
int rv;
|
fs::path::make(&srcmounts[i],fusepath,fullpath);
|
||||||
string fullpath;
|
|
||||||
struct stat st;
|
|
||||||
|
|
||||||
fs::path::make(srcmounts[i],fusepath,fullpath);
|
|
||||||
|
|
||||||
rv = ::lstat(fullpath.c_str(),&st);
|
rv = ::lstat(fullpath.c_str(),&st);
|
||||||
if(rv == 0)
|
if(rv == 0)
|
||||||
|
@ -59,12 +59,12 @@ namespace fs
|
||||||
|
|
||||||
int
|
int
|
||||||
findonfs(const vector<string> &srcmounts,
|
findonfs(const vector<string> &srcmounts,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const int fd,
|
const int fd,
|
||||||
string &basepath)
|
string &basepath)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
string tmppath;
|
string fullpath;
|
||||||
unsigned long fsid;
|
unsigned long fsid;
|
||||||
struct statvfs buf;
|
struct statvfs buf;
|
||||||
|
|
||||||
|
@ -75,9 +75,9 @@ namespace fs
|
||||||
fsid = buf.f_fsid;
|
fsid = buf.f_fsid;
|
||||||
for(int i = 0, ei = srcmounts.size(); i != ei; i++)
|
for(int i = 0, ei = srcmounts.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
fs::path::make(srcmounts[i],fusepath,tmppath);
|
fs::path::make(&srcmounts[i],fusepath,fullpath);
|
||||||
|
|
||||||
rv = ::statvfs(tmppath.c_str(),&buf);
|
rv = ::statvfs(fullpath.c_str(),&buf);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
|
|
@ -27,11 +27,11 @@ namespace fs
|
||||||
using std::vector;
|
using std::vector;
|
||||||
|
|
||||||
void findallfiles(const vector<string> &srcmounts,
|
void findallfiles(const vector<string> &srcmounts,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
vector<string> &paths);
|
vector<string> &paths);
|
||||||
|
|
||||||
int findonfs(const vector<string> &srcmounts,
|
int findonfs(const vector<string> &srcmounts,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const int fd,
|
const int fd,
|
||||||
string &basepath);
|
string &basepath);
|
||||||
|
|
||||||
|
|
|
@ -49,7 +49,7 @@ namespace fs
|
||||||
int
|
int
|
||||||
clonepath(const string &fromsrc,
|
clonepath(const string &fromsrc,
|
||||||
const string &tosrc,
|
const string &tosrc,
|
||||||
const string &relative)
|
const char *relative)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
@ -57,22 +57,23 @@ namespace fs
|
||||||
string frompath;
|
string frompath;
|
||||||
string dirname;
|
string dirname;
|
||||||
|
|
||||||
dirname = fs::path::dirname(relative);
|
dirname = relative;
|
||||||
|
fs::path::dirname(dirname);
|
||||||
if(!dirname.empty())
|
if(!dirname.empty())
|
||||||
{
|
{
|
||||||
rv = clonepath(fromsrc,tosrc,dirname);
|
rv = clonepath(fromsrc,tosrc,dirname.c_str());
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path::make(fromsrc,relative,frompath);
|
fs::path::make(&fromsrc,relative,frompath);
|
||||||
rv = ::stat(frompath.c_str(),&st);
|
rv = ::stat(frompath.c_str(),&st);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -1;
|
return -1;
|
||||||
else if(!S_ISDIR(st.st_mode))
|
else if(!S_ISDIR(st.st_mode))
|
||||||
return (errno = ENOTDIR,-1);
|
return (errno = ENOTDIR,-1);
|
||||||
|
|
||||||
fs::path::make(tosrc,relative,topath);
|
fs::path::make(&tosrc,relative,topath);
|
||||||
rv = ::mkdir(topath.c_str(),st.st_mode);
|
rv = ::mkdir(topath.c_str(),st.st_mode);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
{
|
{
|
||||||
|
|
|
@ -20,5 +20,5 @@ namespace fs
|
||||||
{
|
{
|
||||||
int clonepath(const std::string &from,
|
int clonepath(const std::string &from,
|
||||||
const std::string &to,
|
const std::string &to,
|
||||||
const std::string &relative);
|
const char *relative);
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,8 +66,9 @@ namespace fs
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
fusedir = fs::path::dirname(fusepath);
|
fusedir = fusepath;
|
||||||
rv = fs::clonepath(fdin_path,fdout_path,fusedir);
|
fs::path::dirname(fusedir);
|
||||||
|
rv = fs::clonepath(fdin_path,fdout_path,fusedir.c_str());
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
|
|
|
@ -29,15 +29,14 @@ namespace fs
|
||||||
{
|
{
|
||||||
namespace path
|
namespace path
|
||||||
{
|
{
|
||||||
string
|
void
|
||||||
dirname(const string &path)
|
dirname(string &path)
|
||||||
{
|
{
|
||||||
string parent = path;
|
|
||||||
string::reverse_iterator i;
|
string::reverse_iterator i;
|
||||||
string::reverse_iterator bi;
|
string::reverse_iterator bi;
|
||||||
|
|
||||||
bi = parent.rend();
|
bi = path.rend();
|
||||||
i = parent.rbegin();
|
i = path.rbegin();
|
||||||
while(*i == '/' && i != bi)
|
while(*i == '/' && i != bi)
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
|
@ -47,9 +46,7 @@ namespace fs
|
||||||
while(*i == '/' && i != bi)
|
while(*i == '/' && i != bi)
|
||||||
i++;
|
i++;
|
||||||
|
|
||||||
parent.erase(i.base(),parent.end());
|
path.erase(i.base(),path.end());
|
||||||
|
|
||||||
return parent;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
string
|
string
|
||||||
|
@ -57,54 +54,5 @@ namespace fs
|
||||||
{
|
{
|
||||||
return path.substr(path.find_last_of('/')+1);
|
return path.substr(path.find_last_of('/')+1);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool
|
|
||||||
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);
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
::closedir(dir);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
fs::path::make(paths[i],fusepath,path);
|
|
||||||
|
|
||||||
rv = ::lstat(path.c_str(),&st);
|
|
||||||
if(rv == 0)
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,43 +25,28 @@ namespace fs
|
||||||
namespace path
|
namespace path
|
||||||
{
|
{
|
||||||
using std::string;
|
using std::string;
|
||||||
using std::vector;
|
|
||||||
|
|
||||||
string dirname(const string &path);
|
void dirname(string &path);
|
||||||
|
|
||||||
string basename(const string &path);
|
string basename(const string &path);
|
||||||
|
|
||||||
bool is_empty(const string &path);
|
|
||||||
|
|
||||||
bool exists(vector<string>::const_iterator begin,
|
|
||||||
vector<string>::const_iterator end,
|
|
||||||
const string &fusepath);
|
|
||||||
bool exists(const vector<string> &srcmounts,
|
|
||||||
const string &fusepath);
|
|
||||||
|
|
||||||
inline
|
|
||||||
string
|
|
||||||
make(const string &base,
|
|
||||||
const string &suffix)
|
|
||||||
{
|
|
||||||
return base + suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
inline
|
||||||
void
|
void
|
||||||
make(const string &base,
|
append(string &base,
|
||||||
const string &suffix,
|
const char *suffix)
|
||||||
string &output)
|
|
||||||
{
|
|
||||||
output = base + suffix;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline
|
|
||||||
void
|
|
||||||
append(string &base,
|
|
||||||
const string &suffix)
|
|
||||||
{
|
{
|
||||||
base += suffix;
|
base += suffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
void
|
||||||
|
make(const string *base,
|
||||||
|
const char *suffix,
|
||||||
|
string &output)
|
||||||
|
{
|
||||||
|
output = *base;
|
||||||
|
output += suffix;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -63,19 +63,20 @@ int
|
||||||
_getattr(Policy::Func::Search searchFunc,
|
_getattr(Policy::Func::Search searchFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
struct stat &buf)
|
struct stat &buf)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
vector<string> path;
|
string fullpath;
|
||||||
|
vector<const string*> basepaths;
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,minfreespace,path);
|
rv = searchFunc(srcmounts,fusepath,minfreespace,basepaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
fs::path::append(path[0],fusepath);
|
fs::path::make(basepaths[0],fusepath,fullpath);
|
||||||
|
|
||||||
rv = ::lstat(path[0].c_str(),&buf);
|
rv = ::lstat(fullpath.c_str(),&buf);
|
||||||
|
|
||||||
return ((rv == -1) ? -errno : 0);
|
return ((rv == -1) ? -errno : 0);
|
||||||
}
|
}
|
||||||
|
|
|
@ -43,14 +43,14 @@ using namespace mergerfs;
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_lgetxattr(const string &path,
|
_lgetxattr(const string &path,
|
||||||
const string &name,
|
const char *attrname,
|
||||||
void *value,
|
void *value,
|
||||||
const size_t size)
|
const size_t size)
|
||||||
{
|
{
|
||||||
#ifndef WITHOUT_XATTR
|
#ifndef WITHOUT_XATTR
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
rv = ::lgetxattr(path.c_str(),name.c_str(),value,size);
|
rv = ::lgetxattr(path.c_str(),attrname,value,size);
|
||||||
|
|
||||||
return ((rv == -1) ? -errno : rv);
|
return ((rv == -1) ? -errno : rv);
|
||||||
#else
|
#else
|
||||||
|
@ -161,7 +161,7 @@ _getxattr_pid(string &attrvalue)
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_getxattr_controlfile(const Config &config,
|
_getxattr_controlfile(const Config &config,
|
||||||
const string &attrname,
|
const char *attrname,
|
||||||
char *buf,
|
char *buf,
|
||||||
const size_t count)
|
const size_t count)
|
||||||
{
|
{
|
||||||
|
@ -236,7 +236,7 @@ _getxattr_from_string(char *destbuf,
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_getxattr_user_mergerfs_allpaths(const vector<string> &srcmounts,
|
_getxattr_user_mergerfs_allpaths(const vector<string> &srcmounts,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
char *buf,
|
char *buf,
|
||||||
const size_t count)
|
const size_t count)
|
||||||
{
|
{
|
||||||
|
@ -253,10 +253,10 @@ _getxattr_user_mergerfs_allpaths(const vector<string> &srcmounts,
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_getxattr_user_mergerfs(const string &basepath,
|
_getxattr_user_mergerfs(const string &basepath,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const string &fullpath,
|
const string &fullpath,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const string &attrname,
|
const char *attrname,
|
||||||
char *buf,
|
char *buf,
|
||||||
const size_t count)
|
const size_t count)
|
||||||
{
|
{
|
||||||
|
@ -281,23 +281,23 @@ int
|
||||||
_getxattr(Policy::Func::Search searchFunc,
|
_getxattr(Policy::Func::Search searchFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const string &attrname,
|
const char *attrname,
|
||||||
char *buf,
|
char *buf,
|
||||||
const size_t count)
|
const size_t count)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
string fullpath;
|
string fullpath;
|
||||||
vector<string> basepath;
|
vector<const string*> basepaths;
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,minfreespace,basepath);
|
rv = searchFunc(srcmounts,fusepath,minfreespace,basepaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
fs::path::make(basepath[0],fusepath,fullpath);
|
fs::path::make(basepaths[0],fusepath,fullpath);
|
||||||
|
|
||||||
if(str::isprefix(attrname,"user.mergerfs."))
|
if(str::isprefix(attrname,"user.mergerfs."))
|
||||||
rv = _getxattr_user_mergerfs(basepath[0],fusepath,fullpath,srcmounts,attrname,buf,count);
|
rv = _getxattr_user_mergerfs(*basepaths[0],fusepath,fullpath,srcmounts,attrname,buf,count);
|
||||||
else
|
else
|
||||||
rv = _lgetxattr(fullpath,attrname,buf,count);
|
rv = _lgetxattr(fullpath,attrname,buf,count);
|
||||||
|
|
||||||
|
|
|
@ -61,21 +61,23 @@ int
|
||||||
_ioctl_dir_base(Policy::Func::Search searchFunc,
|
_ioctl_dir_base(Policy::Func::Search searchFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const int cmd,
|
const int cmd,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
int rv;
|
int rv;
|
||||||
vector<string> path;
|
string fullpath;
|
||||||
|
vector<const string*> basepaths;
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,minfreespace,path);
|
rv = searchFunc(srcmounts,fusepath,minfreespace,basepaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
fs::path::append(path[0],fusepath);
|
fs::path::make(basepaths[0],fusepath,fullpath);
|
||||||
|
|
||||||
fd = ::open(path[0].c_str(),O_RDWR|O_NOATIME|O_DIRECTORY);
|
const int flags = O_RDWR | O_NOATIME | O_DIRECTORY;
|
||||||
|
fd = ::open(fullpath.c_str(),flags);
|
||||||
if(fd == -1)
|
if(fd == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
|
@ -88,9 +90,9 @@ _ioctl_dir_base(Policy::Func::Search searchFunc,
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_ioctl_dir(const string &fusepath,
|
_ioctl_dir(const char *fusepath,
|
||||||
const int cmd,
|
const int cmd,
|
||||||
void *data)
|
void *data)
|
||||||
{
|
{
|
||||||
const fuse_context *fc = fuse_get_context();
|
const fuse_context *fc = fuse_get_context();
|
||||||
const Config &config = Config::get(fc);
|
const Config &config = Config::get(fc);
|
||||||
|
|
163
src/link.cpp
163
src/link.cpp
|
@ -36,12 +36,12 @@ using namespace mergerfs;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_link_create_path_one(const string &oldbasepath,
|
_link_create_path_core(const string &oldbasepath,
|
||||||
const string &newbasepath,
|
const string &newbasepath,
|
||||||
const string &oldfusepath,
|
const char *oldfusepath,
|
||||||
const string &newfusepath,
|
const char *newfusepath,
|
||||||
const string &newfusedirpath,
|
const string &newfusedirpath,
|
||||||
const int error)
|
const int error)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
string oldfullpath;
|
string oldfullpath;
|
||||||
|
@ -50,53 +50,66 @@ _link_create_path_one(const string &oldbasepath,
|
||||||
if(oldbasepath != newbasepath)
|
if(oldbasepath != newbasepath)
|
||||||
{
|
{
|
||||||
const ugid::SetRootGuard ugidGuard;
|
const ugid::SetRootGuard ugidGuard;
|
||||||
fs::clonepath(newbasepath,oldbasepath,newfusedirpath);
|
fs::clonepath(newbasepath,oldbasepath,newfusedirpath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path::make(oldbasepath,oldfusepath,oldfullpath);
|
fs::path::make(&oldbasepath,oldfusepath,oldfullpath);
|
||||||
fs::path::make(oldbasepath,newfusepath,newfullpath);
|
fs::path::make(&oldbasepath,newfusepath,newfullpath);
|
||||||
|
|
||||||
rv = ::link(oldfullpath.c_str(),newfullpath.c_str());
|
rv = ::link(oldfullpath.c_str(),newfullpath.c_str());
|
||||||
|
|
||||||
return calc_error(rv,error,errno);
|
return calc_error(rv,error,errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_link_create_path_loop(const vector<const string*> &oldbasepaths,
|
||||||
|
const string &newbasepath,
|
||||||
|
const char *oldfusepath,
|
||||||
|
const char *newfusepath,
|
||||||
|
const string &newfusedirpath)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = -1;
|
||||||
|
for(size_t i = 0, ei = oldbasepaths.size(); i != ei; i++)
|
||||||
|
{
|
||||||
|
error = _link_create_path_core(*oldbasepaths[i],newbasepath,
|
||||||
|
oldfusepath,newfusepath,
|
||||||
|
newfusedirpath,
|
||||||
|
error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -error;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_link_create_path(Policy::Func::Search searchFunc,
|
_link_create_path(Policy::Func::Search searchFunc,
|
||||||
Policy::Func::Action actionFunc,
|
Policy::Func::Action actionFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &oldfusepath,
|
const char *oldfusepath,
|
||||||
const string &newfusepath)
|
const char *newfusepath)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
string newfusedirpath;
|
||||||
string newbasepath;
|
vector<const string*> oldbasepaths;
|
||||||
vector<string> toremove;
|
vector<const string*> newbasepaths;
|
||||||
vector<string> oldbasepaths;
|
|
||||||
|
|
||||||
rv = actionFunc(srcmounts,oldfusepath,minfreespace,oldbasepaths);
|
rv = actionFunc(srcmounts,oldfusepath,minfreespace,oldbasepaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
const string newfusedirpath = fs::path::dirname(newfusepath);
|
newfusedirpath = newfusepath;
|
||||||
rv = searchFunc(srcmounts,newfusedirpath,minfreespace,newbasepath);
|
fs::path::dirname(newfusedirpath);
|
||||||
|
rv = searchFunc(srcmounts,newfusedirpath.c_str(),minfreespace,newbasepaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
error = -1;
|
return _link_create_path_loop(oldbasepaths,*newbasepaths[0],
|
||||||
for(size_t i = 0, ei = oldbasepaths.size(); i != ei; i++)
|
oldfusepath,newfusepath,
|
||||||
{
|
newfusedirpath);
|
||||||
const string &oldbasepath = oldbasepaths[i];
|
|
||||||
|
|
||||||
error = _link_create_path_one(oldbasepath,newbasepath,
|
|
||||||
oldfusepath,newfusepath,
|
|
||||||
newfusedirpath,
|
|
||||||
error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -106,25 +119,28 @@ _clonepath_if_would_create(Policy::Func::Search searchFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &oldbasepath,
|
const string &oldbasepath,
|
||||||
const string &oldfusepath,
|
const char *oldfusepath,
|
||||||
const string &newfusepath)
|
const char *newfusepath)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
string newbasepath;
|
|
||||||
string newfusedirpath;
|
string newfusedirpath;
|
||||||
|
const char *newfusedirpathcstr;
|
||||||
|
vector<const string*> newbasepath;
|
||||||
|
|
||||||
newfusedirpath = fs::path::dirname(newfusepath);
|
newfusedirpath = newfusepath;
|
||||||
|
fs::path::dirname(newfusedirpath);
|
||||||
|
newfusedirpathcstr = newfusedirpath.c_str();
|
||||||
|
|
||||||
rv = createFunc(srcmounts,newfusedirpath,minfreespace,newbasepath);
|
rv = createFunc(srcmounts,newfusedirpathcstr,minfreespace,newbasepath);
|
||||||
if(rv != -1)
|
if(rv != -1)
|
||||||
{
|
{
|
||||||
if(oldbasepath == newbasepath)
|
if(oldbasepath == *newbasepath[0])
|
||||||
{
|
{
|
||||||
rv = searchFunc(srcmounts,newfusedirpath,minfreespace,newbasepath);
|
rv = searchFunc(srcmounts,newfusedirpathcstr,minfreespace,newbasepath);
|
||||||
if(rv != -1)
|
if(rv != -1)
|
||||||
{
|
{
|
||||||
const ugid::SetRootGuard ugidGuard;
|
const ugid::SetRootGuard ugidGuard;
|
||||||
fs::clonepath(newbasepath,oldbasepath,newfusedirpath);
|
fs::clonepath(*newbasepath[0],oldbasepath,newfusedirpathcstr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -139,28 +155,29 @@ _clonepath_if_would_create(Policy::Func::Search searchFunc,
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_link_preserve_path_one(Policy::Func::Search searchFunc,
|
_link_preserve_path_core(Policy::Func::Search searchFunc,
|
||||||
Policy::Func::Create createFunc,
|
Policy::Func::Create createFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &oldbasepath,
|
const string &oldbasepath,
|
||||||
const string &oldfusepath,
|
const char *oldfusepath,
|
||||||
const string &newfusepath,
|
const char *newfusepath,
|
||||||
const int error)
|
const int error)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
string oldfullpath;
|
string oldfullpath;
|
||||||
string newfullpath;
|
string newfullpath;
|
||||||
|
|
||||||
fs::path::make(oldbasepath,oldfusepath,oldfullpath);
|
fs::path::make(&oldbasepath,oldfusepath,oldfullpath);
|
||||||
fs::path::make(oldbasepath,newfusepath,newfullpath);
|
fs::path::make(&oldbasepath,newfusepath,newfullpath);
|
||||||
|
|
||||||
rv = ::link(oldfullpath.c_str(),newfullpath.c_str());
|
rv = ::link(oldfullpath.c_str(),newfullpath.c_str());
|
||||||
if((rv == -1) && (errno == ENOENT))
|
if((rv == -1) && (errno == ENOENT))
|
||||||
{
|
{
|
||||||
rv = _clonepath_if_would_create(searchFunc,createFunc,
|
rv = _clonepath_if_would_create(searchFunc,createFunc,
|
||||||
srcmounts,minfreespace,
|
srcmounts,minfreespace,
|
||||||
oldbasepath,oldfusepath,newfusepath);
|
oldbasepath,
|
||||||
|
oldfusepath,newfusepath);
|
||||||
if(rv != -1)
|
if(rv != -1)
|
||||||
rv = ::link(oldfullpath.c_str(),newfullpath.c_str());
|
rv = ::link(oldfullpath.c_str(),newfullpath.c_str());
|
||||||
}
|
}
|
||||||
|
@ -168,6 +185,31 @@ _link_preserve_path_one(Policy::Func::Search searchFunc,
|
||||||
return calc_error(rv,error,errno);
|
return calc_error(rv,error,errno);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_link_preserve_path_loop(Policy::Func::Search searchFunc,
|
||||||
|
Policy::Func::Create createFunc,
|
||||||
|
const vector<string> &srcmounts,
|
||||||
|
const size_t minfreespace,
|
||||||
|
const char *oldfusepath,
|
||||||
|
const char *newfusepath,
|
||||||
|
const vector<const string*> &oldbasepaths)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = -1;
|
||||||
|
for(size_t i = 0, ei = oldbasepaths.size(); i != ei; i++)
|
||||||
|
{
|
||||||
|
error = _link_preserve_path_core(searchFunc,createFunc,
|
||||||
|
srcmounts,minfreespace,
|
||||||
|
*oldbasepaths[i],
|
||||||
|
oldfusepath,newfusepath,
|
||||||
|
error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -error;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_link_preserve_path(Policy::Func::Search searchFunc,
|
_link_preserve_path(Policy::Func::Search searchFunc,
|
||||||
|
@ -175,31 +217,20 @@ _link_preserve_path(Policy::Func::Search searchFunc,
|
||||||
Policy::Func::Create createFunc,
|
Policy::Func::Create createFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &oldfusepath,
|
const char *oldfusepath,
|
||||||
const string &newfusepath)
|
const char *newfusepath)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
vector<const string*> oldbasepaths;
|
||||||
vector<string> toremove;
|
|
||||||
vector<string> oldbasepaths;
|
|
||||||
|
|
||||||
rv = actionFunc(srcmounts,oldfusepath,minfreespace,oldbasepaths);
|
rv = actionFunc(srcmounts,oldfusepath,minfreespace,oldbasepaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
error = -1;
|
return _link_preserve_path_loop(searchFunc,createFunc,
|
||||||
for(size_t i = 0, ei = oldbasepaths.size(); i != ei; i++)
|
srcmounts,minfreespace,
|
||||||
{
|
oldfusepath,newfusepath,
|
||||||
const string &oldbasepath = oldbasepaths[i];
|
oldbasepaths);
|
||||||
|
|
||||||
error = _link_preserve_path_one(searchFunc,createFunc,
|
|
||||||
srcmounts,minfreespace,
|
|
||||||
oldbasepath,
|
|
||||||
oldfusepath,newfusepath,
|
|
||||||
error);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
|
|
|
@ -69,32 +69,31 @@ _listxattr_controlfile(char *list,
|
||||||
return xattrs.size();
|
return xattrs.size();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WITHOUT_XATTR
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_listxattr(Policy::Func::Search searchFunc,
|
_listxattr(Policy::Func::Search searchFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
char *list,
|
char *list,
|
||||||
const size_t size)
|
const size_t size)
|
||||||
{
|
{
|
||||||
#ifndef WITHOUT_XATTR
|
|
||||||
int rv;
|
int rv;
|
||||||
vector<string> path;
|
string fullpath;
|
||||||
|
vector<const string*> basepaths;
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,minfreespace,path);
|
rv = searchFunc(srcmounts,fusepath,minfreespace,basepaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
fs::path::append(path[0],fusepath);
|
fs::path::make(basepaths[0],fusepath,fullpath);
|
||||||
|
|
||||||
rv = ::llistxattr(path[0].c_str(),list,size);
|
rv = ::llistxattr(fullpath.c_str(),list,size);
|
||||||
|
|
||||||
return ((rv == -1) ? -errno : rv);
|
return ((rv == -1) ? -errno : rv);
|
||||||
#else
|
|
||||||
return -ENOTSUP;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
{
|
{
|
||||||
|
@ -111,6 +110,7 @@ namespace mergerfs
|
||||||
if(fusepath == config.controlfile)
|
if(fusepath == config.controlfile)
|
||||||
return _listxattr_controlfile(list,size);
|
return _listxattr_controlfile(list,size);
|
||||||
|
|
||||||
|
#ifndef WITHOUT_XATTR
|
||||||
const ugid::Set ugid(fc->uid,fc->gid);
|
const ugid::Set ugid(fc->uid,fc->gid);
|
||||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||||
|
|
||||||
|
@ -120,6 +120,9 @@ namespace mergerfs
|
||||||
fusepath,
|
fusepath,
|
||||||
list,
|
list,
|
||||||
size);
|
size);
|
||||||
|
#else
|
||||||
|
return -ENOTSUP;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,49 +37,80 @@ using namespace mergerfs;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_mkdir(Policy::Func::Search searchFunc,
|
_mkdir_loop_core(const string &existingpath,
|
||||||
Policy::Func::Create createFunc,
|
const string &createpath,
|
||||||
const vector<string> &srcmounts,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const char *fusedirpath,
|
||||||
const string &fusepath,
|
const mode_t mode,
|
||||||
const mode_t mode)
|
const int error)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
string fullpath;
|
||||||
|
|
||||||
|
if(createpath != existingpath)
|
||||||
|
{
|
||||||
|
const ugid::SetRootGuard ugidGuard;
|
||||||
|
fs::clonepath(existingpath,createpath,fusedirpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::path::make(&createpath,fusepath,fullpath);
|
||||||
|
|
||||||
|
rv = ::mkdir(fullpath.c_str(),mode);
|
||||||
|
|
||||||
|
return calc_error(rv,error,errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_mkdir_loop(const string &existingpath,
|
||||||
|
const vector<const string*> &createpaths,
|
||||||
|
const char *fusepath,
|
||||||
|
const char *fusedirpath,
|
||||||
|
const mode_t mode)
|
||||||
|
{
|
||||||
int error;
|
int error;
|
||||||
string dirname;
|
|
||||||
string existingpath;
|
|
||||||
vector<string> createpaths;
|
|
||||||
|
|
||||||
dirname = fs::path::dirname(fusepath);
|
|
||||||
rv = searchFunc(srcmounts,dirname,minfreespace,existingpath);
|
|
||||||
if(rv == -1)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
rv = createFunc(srcmounts,dirname,minfreespace,createpaths);
|
|
||||||
if(rv == -1)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
error = -1;
|
error = -1;
|
||||||
for(size_t i = 0, ei = createpaths.size(); i != ei; i++)
|
for(size_t i = 0, ei = createpaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
string &createpath = createpaths[i];
|
error = _mkdir_loop_core(existingpath,*createpaths[i],
|
||||||
|
fusepath,fusedirpath,mode,error);
|
||||||
if(createpath != existingpath)
|
|
||||||
{
|
|
||||||
const ugid::SetRootGuard ugidGuard;
|
|
||||||
fs::clonepath(existingpath,createpath,dirname);
|
|
||||||
}
|
|
||||||
|
|
||||||
fs::path::append(createpath,fusepath);
|
|
||||||
|
|
||||||
rv = ::mkdir(createpath.c_str(),mode);
|
|
||||||
|
|
||||||
error = calc_error(rv,error,errno);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -error;
|
return -error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_mkdir(Policy::Func::Search searchFunc,
|
||||||
|
Policy::Func::Create createFunc,
|
||||||
|
const vector<string> &srcmounts,
|
||||||
|
const size_t minfreespace,
|
||||||
|
const char *fusepath,
|
||||||
|
const mode_t mode)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
string fusedirpath;
|
||||||
|
const char *fusedirpathcstr;
|
||||||
|
vector<const string*> createpaths;
|
||||||
|
vector<const string*> existingpaths;
|
||||||
|
|
||||||
|
fusedirpath = fusepath;
|
||||||
|
fs::path::dirname(fusedirpath);
|
||||||
|
fusedirpathcstr = fusedirpath.c_str();
|
||||||
|
|
||||||
|
rv = searchFunc(srcmounts,fusedirpathcstr,minfreespace,existingpaths);
|
||||||
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
rv = createFunc(srcmounts,fusedirpathcstr,minfreespace,createpaths);
|
||||||
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return _mkdir_loop(*existingpaths[0],createpaths,
|
||||||
|
fusepath,fusedirpathcstr,mode);
|
||||||
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
{
|
{
|
||||||
namespace fuse
|
namespace fuse
|
||||||
|
|
|
@ -38,50 +38,85 @@ using namespace mergerfs;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_mknod(Policy::Func::Search searchFunc,
|
_mknod_loop_core(const string &existingpath,
|
||||||
Policy::Func::Create createFunc,
|
const string &createpath,
|
||||||
const vector<string> &srcmounts,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const char *fusedirpath,
|
||||||
const string &fusepath,
|
const mode_t mode,
|
||||||
const mode_t mode,
|
const dev_t dev,
|
||||||
const dev_t dev)
|
const int error)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
string fullpath;
|
||||||
|
|
||||||
|
if(createpath != existingpath)
|
||||||
|
{
|
||||||
|
const ugid::SetRootGuard ugidGuard;
|
||||||
|
fs::clonepath(existingpath,createpath,fusedirpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::path::make(&createpath,fusepath,fullpath);
|
||||||
|
|
||||||
|
rv = ::mknod(fullpath.c_str(),mode,dev);
|
||||||
|
|
||||||
|
return calc_error(rv,error,errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_mknod_loop(const string &existingpath,
|
||||||
|
const vector<const string*> &createpaths,
|
||||||
|
const char *fusepath,
|
||||||
|
const char *fusedirpath,
|
||||||
|
const mode_t mode,
|
||||||
|
const dev_t dev)
|
||||||
|
{
|
||||||
int error;
|
int error;
|
||||||
string dirname;
|
|
||||||
string existingpath;
|
|
||||||
vector<string> createpaths;
|
|
||||||
|
|
||||||
dirname = fs::path::dirname(fusepath);
|
|
||||||
rv = searchFunc(srcmounts,dirname,minfreespace,existingpath);
|
|
||||||
if(rv == -1)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
rv = createFunc(srcmounts,dirname,minfreespace,createpaths);
|
|
||||||
if(rv == -1)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
error = -1;
|
error = -1;
|
||||||
for(size_t i = 0, ei = createpaths.size(); i != ei; i++)
|
for(size_t i = 0, ei = createpaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
string &createpath = createpaths[i];
|
error = _mknod_loop_core(existingpath,*createpaths[i],
|
||||||
|
fusepath,fusedirpath,
|
||||||
if(createpath != existingpath)
|
mode,dev,error);
|
||||||
{
|
|
||||||
const ugid::SetRootGuard ugidGuard;
|
|
||||||
fs::clonepath(existingpath,createpath,dirname);
|
|
||||||
}
|
|
||||||
|
|
||||||
fs::path::append(createpath,fusepath);
|
|
||||||
|
|
||||||
rv = ::mknod(createpath.c_str(),mode,dev);
|
|
||||||
|
|
||||||
error = calc_error(rv,error,errno);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -error;
|
return -error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_mknod(Policy::Func::Search searchFunc,
|
||||||
|
Policy::Func::Create createFunc,
|
||||||
|
const vector<string> &srcmounts,
|
||||||
|
const size_t minfreespace,
|
||||||
|
const char *fusepath,
|
||||||
|
const mode_t mode,
|
||||||
|
const dev_t dev)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
string fusedirpath;
|
||||||
|
const char *fusedirpathcstr;
|
||||||
|
vector<const string*> createpaths;
|
||||||
|
vector<const string*> existingpaths;
|
||||||
|
|
||||||
|
fusedirpath = fusepath;
|
||||||
|
fs::path::dirname(fusedirpath);
|
||||||
|
fusedirpathcstr = fusedirpath.c_str();
|
||||||
|
|
||||||
|
rv = searchFunc(srcmounts,fusedirpathcstr,minfreespace,existingpaths);
|
||||||
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
rv = createFunc(srcmounts,fusedirpathcstr,minfreespace,createpaths);
|
||||||
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return _mknod_loop(*existingpaths[0],createpaths,
|
||||||
|
fusepath,fusedirpathcstr,
|
||||||
|
mode,dev);
|
||||||
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
{
|
{
|
||||||
namespace fuse
|
namespace fuse
|
||||||
|
|
40
src/open.cpp
40
src/open.cpp
|
@ -35,24 +35,17 @@ using mergerfs::Policy;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_open(Policy::Func::Search searchFunc,
|
_open_core(const string *basepath,
|
||||||
const vector<string> &srcmounts,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const int flags,
|
||||||
const string &fusepath,
|
uint64_t &fh)
|
||||||
const int flags,
|
|
||||||
uint64_t &fh)
|
|
||||||
{
|
{
|
||||||
int fd;
|
int fd;
|
||||||
int rv;
|
string fullpath;
|
||||||
vector<string> path;
|
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,minfreespace,path);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
if(rv == -1)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
fs::path::append(path[0],fusepath);
|
fd = ::open(fullpath.c_str(),flags);
|
||||||
|
|
||||||
fd = ::open(path[0].c_str(),flags);
|
|
||||||
if(fd == -1)
|
if(fd == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
|
@ -61,6 +54,25 @@ _open(Policy::Func::Search searchFunc,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_open(Policy::Func::Search searchFunc,
|
||||||
|
const vector<string> &srcmounts,
|
||||||
|
const size_t minfreespace,
|
||||||
|
const char *fusepath,
|
||||||
|
const int flags,
|
||||||
|
uint64_t &fh)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
vector<const string*> basepaths;
|
||||||
|
|
||||||
|
rv = searchFunc(srcmounts,fusepath,minfreespace,basepaths);
|
||||||
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return _open_core(basepaths[0],fusepath,flags,fh);
|
||||||
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
{
|
{
|
||||||
namespace fuse
|
namespace fuse
|
||||||
|
|
|
@ -61,12 +61,13 @@ namespace mergerfs
|
||||||
typedef std::string string;
|
typedef std::string string;
|
||||||
typedef std::size_t size_t;
|
typedef std::size_t size_t;
|
||||||
typedef std::vector<string> strvec;
|
typedef std::vector<string> strvec;
|
||||||
|
typedef std::vector<const string*> cstrptrvec;
|
||||||
typedef const string cstring;
|
typedef const string cstring;
|
||||||
typedef const size_t csize_t;
|
typedef const size_t csize_t;
|
||||||
typedef const strvec cstrvec;
|
typedef const strvec cstrvec;
|
||||||
typedef const Category::Enum::Type CType;
|
typedef const Category::Enum::Type CType;
|
||||||
|
|
||||||
typedef int (*Ptr)(CType,cstrvec&,cstring&,csize_t,strvec&);
|
typedef int (*Ptr)(CType,cstrvec &,const char *,csize_t,cstrptrvec &);
|
||||||
|
|
||||||
template <CType T>
|
template <CType T>
|
||||||
class Base
|
class Base
|
||||||
|
@ -77,24 +78,11 @@ namespace mergerfs
|
||||||
{}
|
{}
|
||||||
|
|
||||||
int
|
int
|
||||||
operator()(cstrvec& b,cstring& c,csize_t d,strvec& e)
|
operator()(cstrvec &b,const char *c,csize_t d,cstrptrvec &e)
|
||||||
{
|
{
|
||||||
return func(T,b,c,d,e);
|
return func(T,b,c,d,e);
|
||||||
}
|
}
|
||||||
|
|
||||||
int
|
|
||||||
operator()(cstrvec& b,cstring& c,csize_t d,string& e)
|
|
||||||
{
|
|
||||||
int rv;
|
|
||||||
strvec vec;
|
|
||||||
|
|
||||||
rv = func(T,b,c,d,vec);
|
|
||||||
if(!vec.empty())
|
|
||||||
e = vec[0];
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const Ptr func;
|
const Ptr func;
|
||||||
};
|
};
|
||||||
|
@ -103,21 +91,21 @@ namespace mergerfs
|
||||||
typedef Base<Category::Enum::create> Create;
|
typedef Base<Category::Enum::create> Create;
|
||||||
typedef Base<Category::Enum::search> Search;
|
typedef Base<Category::Enum::search> Search;
|
||||||
|
|
||||||
static int all(CType,cstrvec&,cstring&,csize_t,strvec&);
|
static int all(CType,cstrvec&,const char*,csize_t,cstrptrvec&);
|
||||||
static int einval(CType,cstrvec&,cstring&,csize_t,strvec&);
|
static int einval(CType,cstrvec&,const char*,csize_t,cstrptrvec&);
|
||||||
static int enosys(CType,cstrvec&,cstring&,csize_t,strvec&);
|
static int enosys(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
|
||||||
static int enotsup(CType,cstrvec&,cstring&,csize_t,strvec&);
|
static int enotsup(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
|
||||||
static int epmfs(CType,cstrvec&,cstring&,csize_t,strvec&);
|
static int epmfs(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
|
||||||
static int erofs(CType,cstrvec&,cstring&,csize_t,strvec&);
|
static int erofs(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
|
||||||
static int exdev(CType,cstrvec&,cstring&,csize_t,strvec&);
|
static int exdev(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
|
||||||
static int ff(CType,cstrvec&,cstring&,csize_t,strvec&);
|
static int ff(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
|
||||||
static int ffwp(CType,cstrvec&,cstring&,csize_t,strvec&);
|
static int ffwp(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
|
||||||
static int fwfs(CType,cstrvec&,cstring&,csize_t,strvec&);
|
static int fwfs(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
|
||||||
static int invalid(CType,cstrvec&,cstring&,csize_t,strvec&);
|
static int invalid(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
|
||||||
static int lfs(CType,cstrvec&,cstring&,csize_t,strvec&);
|
static int lfs(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
|
||||||
static int mfs(CType,cstrvec&,cstring&,csize_t,strvec&);
|
static int mfs(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
|
||||||
static int newest(CType,cstrvec&,cstring&,csize_t,strvec&);
|
static int newest(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
|
||||||
static int rand(CType,cstrvec&,cstring&,csize_t,strvec&);
|
static int rand(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
|
||||||
};
|
};
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -31,9 +31,9 @@ using std::size_t;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_all(const vector<string> &basepaths,
|
_all(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
struct stat st;
|
struct stat st;
|
||||||
|
@ -41,7 +41,7 @@ _all(const vector<string> &basepaths,
|
||||||
|
|
||||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
const string &basepath = basepaths[i];
|
const string *basepath = &basepaths[i];
|
||||||
|
|
||||||
fs::path::make(basepath,fusepath,fullpath);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
|
|
||||||
|
@ -58,13 +58,14 @@ _all(const vector<string> &basepaths,
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_all_create(const vector<string> &basepaths,
|
_all_create(const vector<string> &basepaths,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
if(basepaths.empty())
|
if(basepaths.empty())
|
||||||
return (errno=ENOENT,-1);
|
return (errno=ENOENT,-1);
|
||||||
|
|
||||||
paths = basepaths;
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
|
paths.push_back(&basepaths[i]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -74,9 +75,9 @@ namespace mergerfs
|
||||||
int
|
int
|
||||||
Policy::Func::all(const Category::Enum::Type type,
|
Policy::Func::all(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
if(type == Category::Enum::create)
|
if(type == Category::Enum::create)
|
||||||
return _all_create(basepaths,paths);
|
return _all_create(basepaths,paths);
|
||||||
|
|
|
@ -29,9 +29,9 @@ namespace mergerfs
|
||||||
int
|
int
|
||||||
Policy::Func::einval(const Category::Enum::Type type,
|
Policy::Func::einval(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
return (errno=EINVAL,-1);
|
return (errno=EINVAL,-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,9 @@ namespace mergerfs
|
||||||
int
|
int
|
||||||
Policy::Func::enosys(const Category::Enum::Type type,
|
Policy::Func::enosys(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
return (errno=ENOSYS,-1);
|
return (errno=ENOSYS,-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,9 @@ namespace mergerfs
|
||||||
int
|
int
|
||||||
Policy::Func::enotsup(const Category::Enum::Type type,
|
Policy::Func::enotsup(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
return (errno=ENOTSUP,-1);
|
return (errno=ENOTSUP,-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,13 +34,12 @@ using mergerfs::Category;
|
||||||
typedef struct statvfs statvfs_t;
|
typedef struct statvfs statvfs_t;
|
||||||
|
|
||||||
static
|
static
|
||||||
inline
|
|
||||||
void
|
void
|
||||||
_calc_mfs(const statvfs_t &fsstats,
|
_calc_mfs(const statvfs_t &fsstats,
|
||||||
const string &basepath,
|
const string *basepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
fsblkcnt_t &mfs,
|
fsblkcnt_t &mfs,
|
||||||
string &mfsbasepath)
|
const string *&mfsbasepath)
|
||||||
{
|
{
|
||||||
fsblkcnt_t spaceavail;
|
fsblkcnt_t spaceavail;
|
||||||
|
|
||||||
|
@ -54,22 +53,22 @@ _calc_mfs(const statvfs_t &fsstats,
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_epmfs_create(const vector<string> &basepaths,
|
_epmfs_create(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
|
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
string fullpath;
|
||||||
|
statvfs_t fsstats;
|
||||||
fsblkcnt_t epmfs;
|
fsblkcnt_t epmfs;
|
||||||
string epmfsbasepath;
|
const string *epmfsbasepath;
|
||||||
string fullpath;
|
|
||||||
statvfs_t fsstats;
|
|
||||||
|
|
||||||
epmfs = 0;
|
epmfs = 0;
|
||||||
|
epmfsbasepath = NULL;
|
||||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
const string &basepath = basepaths[i];
|
const string *basepath = &basepaths[i];
|
||||||
|
|
||||||
fs::path::make(basepath,fusepath,fullpath);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
|
|
||||||
|
@ -78,7 +77,7 @@ _epmfs_create(const vector<string> &basepaths,
|
||||||
_calc_mfs(fsstats,basepath,minfreespace,epmfs,epmfsbasepath);
|
_calc_mfs(fsstats,basepath,minfreespace,epmfs,epmfsbasepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(epmfsbasepath.empty())
|
if(epmfsbasepath == NULL)
|
||||||
return Policy::Func::mfs(Category::Enum::create,basepaths,fusepath,minfreespace,paths);
|
return Policy::Func::mfs(Category::Enum::create,basepaths,fusepath,minfreespace,paths);
|
||||||
|
|
||||||
paths.push_back(epmfsbasepath);
|
paths.push_back(epmfsbasepath);
|
||||||
|
@ -88,21 +87,22 @@ _epmfs_create(const vector<string> &basepaths,
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_epmfs(const vector<string> &basepaths,
|
_epmfs(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
|
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
string fullpath;
|
||||||
|
statvfs_t fsstats;
|
||||||
fsblkcnt_t epmfs;
|
fsblkcnt_t epmfs;
|
||||||
string epmfsbasepath;
|
const string *epmfsbasepath;
|
||||||
string fullpath;
|
|
||||||
statvfs_t fsstats;
|
|
||||||
|
|
||||||
epmfs = 0;
|
epmfs = 0;
|
||||||
|
epmfsbasepath = NULL;
|
||||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
const string &basepath = basepaths[i];
|
const string *basepath = &basepaths[i];
|
||||||
|
|
||||||
fs::path::make(basepath,fusepath,fullpath);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
|
|
||||||
|
@ -111,7 +111,7 @@ _epmfs(const vector<string> &basepaths,
|
||||||
_calc_mfs(fsstats,basepath,0,epmfs,epmfsbasepath);
|
_calc_mfs(fsstats,basepath,0,epmfs,epmfsbasepath);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(epmfsbasepath.empty())
|
if(epmfsbasepath == NULL)
|
||||||
return (errno=ENOENT,-1);
|
return (errno=ENOENT,-1);
|
||||||
|
|
||||||
paths.push_back(epmfsbasepath);
|
paths.push_back(epmfsbasepath);
|
||||||
|
@ -124,9 +124,9 @@ namespace mergerfs
|
||||||
int
|
int
|
||||||
Policy::Func::epmfs(const Category::Enum::Type type,
|
Policy::Func::epmfs(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
if(type == Category::Enum::create)
|
if(type == Category::Enum::create)
|
||||||
return _epmfs_create(basepaths,fusepath,minfreespace,paths);
|
return _epmfs_create(basepaths,fusepath,minfreespace,paths);
|
||||||
|
|
|
@ -29,9 +29,9 @@ namespace mergerfs
|
||||||
int
|
int
|
||||||
Policy::Func::erofs(const Category::Enum::Type type,
|
Policy::Func::erofs(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
return (errno=EROFS,-1);
|
return (errno=EROFS,-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,9 +29,9 @@ namespace mergerfs
|
||||||
int
|
int
|
||||||
Policy::Func::exdev(const Category::Enum::Type type,
|
Policy::Func::exdev(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
return (errno=EXDEV,-1);
|
return (errno=EXDEV,-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,18 +31,19 @@ using std::size_t;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_ff(const vector<string> &basepaths,
|
_ff(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
|
int rv;
|
||||||
|
string fullpath;
|
||||||
|
struct stat st;
|
||||||
|
|
||||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
int rv;
|
const string *basepath = &basepaths[i];
|
||||||
struct stat st;
|
|
||||||
string fullpath;
|
|
||||||
const string &basepath = basepaths[i];
|
|
||||||
|
|
||||||
fullpath = fs::path::make(basepath,fusepath);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
|
|
||||||
rv = ::lstat(fullpath.c_str(),&st);
|
rv = ::lstat(fullpath.c_str(),&st);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
|
@ -58,14 +59,14 @@ _ff(const vector<string> &basepaths,
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_ff_create(const vector<string> &basepaths,
|
_ff_create(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
if(basepaths.empty())
|
if(basepaths.empty())
|
||||||
return (errno=ENOENT,-1);
|
return (errno=ENOENT,-1);
|
||||||
|
|
||||||
paths.push_back(basepaths[0]);
|
paths.push_back(&basepaths[0]);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -75,9 +76,9 @@ namespace mergerfs
|
||||||
int
|
int
|
||||||
Policy::Func::ff(const Category::Enum::Type type,
|
Policy::Func::ff(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
if(type == Category::Enum::create)
|
if(type == Category::Enum::create)
|
||||||
return _ff_create(basepaths,fusepath,paths);
|
return _ff_create(basepaths,fusepath,paths);
|
||||||
|
|
|
@ -31,18 +31,19 @@ using std::size_t;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_ffwp(const vector<string> &basepaths,
|
_ffwp(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
string fallback;
|
int rv;
|
||||||
|
struct stat st;
|
||||||
|
string fullpath;
|
||||||
|
const string *fallback;
|
||||||
|
|
||||||
|
fallback = NULL;
|
||||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
int rv;
|
const string *basepath = &basepaths[i];
|
||||||
struct stat st;
|
|
||||||
string fullpath;
|
|
||||||
const string &basepath = basepaths[i];
|
|
||||||
|
|
||||||
fs::path::make(basepath,fusepath,fullpath);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
|
|
||||||
|
@ -58,7 +59,7 @@ _ffwp(const vector<string> &basepaths,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(fallback.empty())
|
if(fallback == NULL)
|
||||||
return (errno=ENOENT,-1);
|
return (errno=ENOENT,-1);
|
||||||
|
|
||||||
paths.push_back(fallback);
|
paths.push_back(fallback);
|
||||||
|
@ -71,9 +72,9 @@ namespace mergerfs
|
||||||
int
|
int
|
||||||
Policy::Func::ffwp(const Category::Enum::Type type,
|
Policy::Func::ffwp(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
return _ffwp(basepaths,fusepath,paths);
|
return _ffwp(basepaths,fusepath,paths);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,15 +33,16 @@ static
|
||||||
int
|
int
|
||||||
_fwfs_create(const Category::Enum::Type type,
|
_fwfs_create(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
|
int rv;
|
||||||
|
struct statvfs fsstats;
|
||||||
|
|
||||||
for(size_t i = 0, size = basepaths.size(); i != size; i++)
|
for(size_t i = 0, size = basepaths.size(); i != size; i++)
|
||||||
{
|
{
|
||||||
int rv;
|
const string &basepath = basepaths[i];
|
||||||
struct statvfs fsstats;
|
|
||||||
const string &basepath = basepaths[i];
|
|
||||||
|
|
||||||
rv = ::statvfs(basepath.c_str(),&fsstats);
|
rv = ::statvfs(basepath.c_str(),&fsstats);
|
||||||
if(rv == 0)
|
if(rv == 0)
|
||||||
|
@ -52,7 +53,7 @@ _fwfs_create(const Category::Enum::Type type,
|
||||||
if(spaceavail < minfreespace)
|
if(spaceavail < minfreespace)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
paths.push_back(basepath);
|
paths.push_back(&basepath);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -65,16 +66,17 @@ static
|
||||||
int
|
int
|
||||||
_fwfs(const Category::Enum::Type type,
|
_fwfs(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
|
int rv;
|
||||||
|
string fullpath;
|
||||||
|
struct statvfs fsstats;
|
||||||
|
|
||||||
for(size_t i = 0, size = basepaths.size(); i != size; i++)
|
for(size_t i = 0, size = basepaths.size(); i != size; i++)
|
||||||
{
|
{
|
||||||
int rv;
|
const string *basepath = &basepaths[i];
|
||||||
string fullpath;
|
|
||||||
struct statvfs fsstats;
|
|
||||||
const string &basepath = basepaths[i];
|
|
||||||
|
|
||||||
fs::path::make(basepath,fusepath,fullpath);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
|
|
||||||
|
@ -101,9 +103,9 @@ namespace mergerfs
|
||||||
int
|
int
|
||||||
Policy::Func::fwfs(const Category::Enum::Type type,
|
Policy::Func::fwfs(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
if(type == Category::Enum::create)
|
if(type == Category::Enum::create)
|
||||||
return _fwfs_create(type,basepaths,fusepath,minfreespace,paths);
|
return _fwfs_create(type,basepaths,fusepath,minfreespace,paths);
|
||||||
|
|
|
@ -30,9 +30,9 @@ namespace mergerfs
|
||||||
int
|
int
|
||||||
Policy::Func::invalid(const Category::Enum::Type type,
|
Policy::Func::invalid(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &rv)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
return (errno=EINVAL,-1);
|
return (errno=EINVAL,-1);
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,18 +36,19 @@ static
|
||||||
int
|
int
|
||||||
_lfs_create(const Category::Enum::Type type,
|
_lfs_create(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
|
int rv;
|
||||||
fsblkcnt_t lfs;
|
fsblkcnt_t lfs;
|
||||||
string lfsstr;
|
const string *lfsstr;
|
||||||
|
struct statvfs fsstats;
|
||||||
|
|
||||||
lfs = -1;
|
lfs = -1;
|
||||||
|
lfsstr = NULL;
|
||||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
int rv;
|
|
||||||
struct statvfs fsstats;
|
|
||||||
const string &basepath = basepaths[i];
|
const string &basepath = basepaths[i];
|
||||||
|
|
||||||
rv = ::statvfs(basepath.c_str(),&fsstats);
|
rv = ::statvfs(basepath.c_str(),&fsstats);
|
||||||
|
@ -60,12 +61,12 @@ _lfs_create(const Category::Enum::Type type,
|
||||||
(spaceavail < lfs))
|
(spaceavail < lfs))
|
||||||
{
|
{
|
||||||
lfs = spaceavail;
|
lfs = spaceavail;
|
||||||
lfsstr = basepath;
|
lfsstr = &basepath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lfsstr.empty())
|
if(lfsstr == NULL)
|
||||||
return Policy::Func::mfs(type,basepaths,fusepath,minfreespace,paths);
|
return Policy::Func::mfs(type,basepaths,fusepath,minfreespace,paths);
|
||||||
|
|
||||||
paths.push_back(lfsstr);
|
paths.push_back(lfsstr);
|
||||||
|
@ -77,20 +78,21 @@ static
|
||||||
int
|
int
|
||||||
_lfs(const Category::Enum::Type type,
|
_lfs(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
|
int rv;
|
||||||
|
string fullpath;
|
||||||
|
struct statvfs fsstats;
|
||||||
fsblkcnt_t lfs;
|
fsblkcnt_t lfs;
|
||||||
string lfsstr;
|
const string *lfsstr;
|
||||||
|
|
||||||
lfs = -1;
|
lfs = -1;
|
||||||
|
lfsstr = NULL;
|
||||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
int rv;
|
const string *basepath = &basepaths[i];
|
||||||
string fullpath;
|
|
||||||
struct statvfs fsstats;
|
|
||||||
const string &basepath = basepaths[i];
|
|
||||||
|
|
||||||
fs::path::make(basepath,fusepath,fullpath);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
|
|
||||||
|
@ -109,7 +111,7 @@ _lfs(const Category::Enum::Type type,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(lfsstr.empty())
|
if(lfsstr == NULL)
|
||||||
return Policy::Func::mfs(type,basepaths,fusepath,minfreespace,paths);
|
return Policy::Func::mfs(type,basepaths,fusepath,minfreespace,paths);
|
||||||
|
|
||||||
paths.push_back(lfsstr);
|
paths.push_back(lfsstr);
|
||||||
|
@ -122,9 +124,9 @@ namespace mergerfs
|
||||||
int
|
int
|
||||||
Policy::Func::lfs(const Category::Enum::Type type,
|
Policy::Func::lfs(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
if(type == Category::Enum::create)
|
if(type == Category::Enum::create)
|
||||||
return _lfs_create(type,basepaths,fusepath,minfreespace,paths);
|
return _lfs_create(type,basepaths,fusepath,minfreespace,paths);
|
||||||
|
|
|
@ -29,18 +29,19 @@ using std::size_t;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_mfs_create(const vector<string> &basepaths,
|
_mfs_create(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
|
int rv;
|
||||||
|
struct statvfs fsstats;
|
||||||
fsblkcnt_t mfs;
|
fsblkcnt_t mfs;
|
||||||
string mfsstr;
|
const string *mfsstr;
|
||||||
|
|
||||||
mfs = 0;
|
mfs = 0;
|
||||||
|
mfsstr = NULL;
|
||||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
int rv;
|
|
||||||
struct statvfs fsstats;
|
|
||||||
const string &basepath = basepaths[i];
|
const string &basepath = basepaths[i];
|
||||||
|
|
||||||
rv = ::statvfs(basepath.c_str(),&fsstats);
|
rv = ::statvfs(basepath.c_str(),&fsstats);
|
||||||
|
@ -52,12 +53,12 @@ _mfs_create(const vector<string> &basepaths,
|
||||||
if(spaceavail > mfs)
|
if(spaceavail > mfs)
|
||||||
{
|
{
|
||||||
mfs = spaceavail;
|
mfs = spaceavail;
|
||||||
mfsstr = basepath;
|
mfsstr = &basepath;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mfsstr.empty())
|
if(mfsstr == NULL)
|
||||||
return (errno=ENOENT,-1);
|
return (errno=ENOENT,-1);
|
||||||
|
|
||||||
paths.push_back(mfsstr);
|
paths.push_back(mfsstr);
|
||||||
|
@ -67,20 +68,21 @@ _mfs_create(const vector<string> &basepaths,
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_mfs(const vector<string> &basepaths,
|
_mfs(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
|
int rv;
|
||||||
|
string fullpath;
|
||||||
|
struct statvfs fsstats;
|
||||||
fsblkcnt_t mfs;
|
fsblkcnt_t mfs;
|
||||||
string mfsstr;
|
const string *mfsstr;
|
||||||
|
|
||||||
mfs = 0;
|
mfs = 0;
|
||||||
|
mfsstr = NULL;
|
||||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
int rv;
|
const string *basepath = &basepaths[i];
|
||||||
string fullpath;
|
|
||||||
struct statvfs fsstats;
|
|
||||||
const string &basepath = basepaths[i];
|
|
||||||
|
|
||||||
fs::path::make(basepath,fusepath,fullpath);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
|
|
||||||
|
@ -98,7 +100,7 @@ _mfs(const vector<string> &basepaths,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(mfsstr.empty())
|
if(mfsstr == NULL)
|
||||||
return (errno=ENOENT,-1);
|
return (errno=ENOENT,-1);
|
||||||
|
|
||||||
paths.push_back(mfsstr);
|
paths.push_back(mfsstr);
|
||||||
|
@ -111,9 +113,9 @@ namespace mergerfs
|
||||||
int
|
int
|
||||||
Policy::Func::mfs(const Category::Enum::Type type,
|
Policy::Func::mfs(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
if(type == Category::Enum::create)
|
if(type == Category::Enum::create)
|
||||||
return _mfs_create(basepaths,fusepath,paths);
|
return _mfs_create(basepaths,fusepath,paths);
|
||||||
|
|
|
@ -32,19 +32,21 @@ using std::size_t;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_newest(const vector<string> &basepaths,
|
_newest(const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
time_t newest = std::numeric_limits<time_t>::min();
|
int rv;
|
||||||
string neweststr;
|
struct stat st;
|
||||||
|
string fullpath;
|
||||||
|
time_t newest;
|
||||||
|
const string *neweststr;
|
||||||
|
|
||||||
|
newest = std::numeric_limits<time_t>::min();
|
||||||
|
neweststr = NULL;
|
||||||
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
int rv;
|
const string *basepath = &basepaths[i];
|
||||||
struct stat st;
|
|
||||||
string fullpath;
|
|
||||||
const string &basepath = basepaths[i];
|
|
||||||
|
|
||||||
fs::path::make(basepath,fusepath,fullpath);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
|
|
||||||
|
@ -56,7 +58,7 @@ _newest(const vector<string> &basepaths,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if(neweststr.empty())
|
if(neweststr == NULL)
|
||||||
return (errno=ENOENT,-1);
|
return (errno=ENOENT,-1);
|
||||||
|
|
||||||
paths.push_back(neweststr);
|
paths.push_back(neweststr);
|
||||||
|
@ -69,9 +71,9 @@ namespace mergerfs
|
||||||
int
|
int
|
||||||
Policy::Func::newest(const Category::Enum::Type type,
|
Policy::Func::newest(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
return _newest(basepaths,fusepath,paths);
|
return _newest(basepaths,fusepath,paths);
|
||||||
}
|
}
|
||||||
|
|
|
@ -31,9 +31,9 @@ namespace mergerfs
|
||||||
int
|
int
|
||||||
Policy::Func::rand(const Category::Enum::Type type,
|
Policy::Func::rand(const Category::Enum::Type type,
|
||||||
const vector<string> &basepaths,
|
const vector<string> &basepaths,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
vector<string> &paths)
|
vector<const string*> &paths)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
|
|
|
@ -41,7 +41,7 @@ using std::pair;
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_readdir(const vector<string> &srcmounts,
|
_readdir(const vector<string> &srcmounts,
|
||||||
const string &dirname,
|
const char *dirname,
|
||||||
void *buf,
|
void *buf,
|
||||||
const fuse_fill_dir_t filler)
|
const fuse_fill_dir_t filler)
|
||||||
{
|
{
|
||||||
|
@ -53,7 +53,8 @@ _readdir(const vector<string> &srcmounts,
|
||||||
DIR *dh;
|
DIR *dh;
|
||||||
string basepath;
|
string basepath;
|
||||||
|
|
||||||
fs::path::make(srcmounts[i],dirname,basepath);
|
fs::path::make(&srcmounts[i],dirname,basepath);
|
||||||
|
|
||||||
dh = ::opendir(basepath.c_str());
|
dh = ::opendir(basepath.c_str());
|
||||||
if(!dh)
|
if(!dh)
|
||||||
continue;
|
continue;
|
||||||
|
|
|
@ -33,23 +33,17 @@ using mergerfs::Policy;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_readlink(Policy::Func::Search searchFunc,
|
_readlink_core(const string *basepath,
|
||||||
const vector<string> &srcmounts,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
char *buf,
|
||||||
const string &fusepath,
|
const size_t size)
|
||||||
char *buf,
|
|
||||||
const size_t size)
|
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
vector<string> path;
|
string fullpath;
|
||||||
|
|
||||||
rv = searchFunc(srcmounts,fusepath,minfreespace,path);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
if(rv == -1)
|
|
||||||
return -errno;
|
|
||||||
|
|
||||||
fs::path::append(path[0],fusepath);
|
rv = ::readlink(fullpath.c_str(),buf,size);
|
||||||
|
|
||||||
rv = ::readlink(path[0].c_str(),buf,size);
|
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
|
@ -58,6 +52,25 @@ _readlink(Policy::Func::Search searchFunc,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_readlink(Policy::Func::Search searchFunc,
|
||||||
|
const vector<string> &srcmounts,
|
||||||
|
const size_t minfreespace,
|
||||||
|
const char *fusepath,
|
||||||
|
char *buf,
|
||||||
|
const size_t size)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
vector<const string*> basepaths;
|
||||||
|
|
||||||
|
rv = searchFunc(srcmounts,fusepath,minfreespace,basepaths);
|
||||||
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return _readlink_core(basepaths[0],fusepath,buf,size);
|
||||||
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
{
|
{
|
||||||
namespace fuse
|
namespace fuse
|
||||||
|
|
|
@ -33,38 +33,60 @@ using std::string;
|
||||||
using std::vector;
|
using std::vector;
|
||||||
using mergerfs::Policy;
|
using mergerfs::Policy;
|
||||||
|
|
||||||
|
#ifndef WITHOUT_XATTR
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_removexattr_loop_core(const string *basepath,
|
||||||
|
const char *fusepath,
|
||||||
|
const char *attrname,
|
||||||
|
const int error)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
string fullpath;
|
||||||
|
|
||||||
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
|
|
||||||
|
rv = ::lremovexattr(fullpath.c_str(),attrname);
|
||||||
|
|
||||||
|
return calc_error(rv,error,errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_removexattr_loop(const vector<const string*> &basepaths,
|
||||||
|
const char *fusepath,
|
||||||
|
const char *attrname)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = -1;
|
||||||
|
|
||||||
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
|
{
|
||||||
|
error = _removexattr_loop_core(basepaths[i],fusepath,attrname,error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -error;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_removexattr(Policy::Func::Action actionFunc,
|
_removexattr(Policy::Func::Action actionFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const char *attrname)
|
const char *attrname)
|
||||||
{
|
{
|
||||||
#ifndef WITHOUT_XATTR
|
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
vector<const string*> basepaths;
|
||||||
vector<string> paths;
|
|
||||||
|
|
||||||
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
|
rv = actionFunc(srcmounts,fusepath,minfreespace,basepaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
error = -1;
|
return _removexattr_loop(basepaths,fusepath,attrname);
|
||||||
for(size_t i = 0, ei = paths.size(); i != ei; i++)
|
|
||||||
{
|
|
||||||
fs::path::append(paths[i],fusepath);
|
|
||||||
|
|
||||||
rv = ::lremovexattr(paths[i].c_str(),attrname);
|
|
||||||
|
|
||||||
error = calc_error(rv,error,errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -error;
|
|
||||||
#else
|
|
||||||
return -ENOTSUP;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
{
|
{
|
||||||
|
@ -74,6 +96,7 @@ namespace mergerfs
|
||||||
removexattr(const char *fusepath,
|
removexattr(const char *fusepath,
|
||||||
const char *attrname)
|
const char *attrname)
|
||||||
{
|
{
|
||||||
|
#ifndef WITHOUT_XATTR
|
||||||
const fuse_context *fc = fuse_get_context();
|
const fuse_context *fc = fuse_get_context();
|
||||||
const Config &config = Config::get(fc);
|
const Config &config = Config::get(fc);
|
||||||
|
|
||||||
|
@ -88,6 +111,9 @@ namespace mergerfs
|
||||||
config.minfreespace,
|
config.minfreespace,
|
||||||
fusepath,
|
fusepath,
|
||||||
attrname);
|
attrname);
|
||||||
|
#else
|
||||||
|
return -ENOTSUP;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
114
src/rename.cpp
114
src/rename.cpp
|
@ -38,10 +38,16 @@ using namespace mergerfs;
|
||||||
|
|
||||||
static
|
static
|
||||||
bool
|
bool
|
||||||
member(const vector<string> &haystack,
|
member(const vector<const string*> &haystack,
|
||||||
const string &needle)
|
const string &needle)
|
||||||
{
|
{
|
||||||
return (std::find(haystack.begin(),haystack.end(),needle) != haystack.end());
|
for(size_t i = 0, ei = haystack.size(); i != ei; i++)
|
||||||
|
{
|
||||||
|
if(*haystack[i] == needle)
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
|
@ -54,21 +60,21 @@ _remove(const vector<string> &toremove)
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
_rename_create_path_one(const vector<string> &oldbasepaths,
|
_rename_create_path_core(const vector<const string*> &oldbasepaths,
|
||||||
const string &oldbasepath,
|
const string &oldbasepath,
|
||||||
const string &newbasepath,
|
const string &newbasepath,
|
||||||
const string &oldfusepath,
|
const char *oldfusepath,
|
||||||
const string &newfusepath,
|
const char *newfusepath,
|
||||||
const string &newfusedirpath,
|
const string &newfusedirpath,
|
||||||
int &error,
|
int &error,
|
||||||
vector<string> &tounlink)
|
vector<string> &tounlink)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
bool ismember;
|
bool ismember;
|
||||||
string oldfullpath;
|
string oldfullpath;
|
||||||
string newfullpath;
|
string newfullpath;
|
||||||
|
|
||||||
fs::path::make(oldbasepath,newfusepath,newfullpath);
|
fs::path::make(&oldbasepath,newfusepath,newfullpath);
|
||||||
|
|
||||||
ismember = member(oldbasepaths,oldbasepath);
|
ismember = member(oldbasepaths,oldbasepath);
|
||||||
if(ismember)
|
if(ismember)
|
||||||
|
@ -76,10 +82,10 @@ _rename_create_path_one(const vector<string> &oldbasepaths,
|
||||||
if(oldbasepath != newbasepath)
|
if(oldbasepath != newbasepath)
|
||||||
{
|
{
|
||||||
const ugid::SetRootGuard ugidGuard;
|
const ugid::SetRootGuard ugidGuard;
|
||||||
fs::clonepath(newbasepath,oldbasepath,newfusedirpath);
|
fs::clonepath(newbasepath,oldbasepath,newfusedirpath.c_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
fs::path::make(oldbasepath,oldfusepath,oldfullpath);
|
fs::path::make(&oldbasepath,oldfusepath,oldfullpath);
|
||||||
|
|
||||||
rv = ::rename(oldfullpath.c_str(),newfullpath.c_str());
|
rv = ::rename(oldfullpath.c_str(),newfullpath.c_str());
|
||||||
error = calc_error(rv,error,errno);
|
error = calc_error(rv,error,errno);
|
||||||
|
@ -98,21 +104,22 @@ _rename_create_path(Policy::Func::Search searchFunc,
|
||||||
Policy::Func::Action actionFunc,
|
Policy::Func::Action actionFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &oldfusepath,
|
const char *oldfusepath,
|
||||||
const string &newfusepath)
|
const char *newfusepath)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
int error;
|
||||||
string newbasepath;
|
|
||||||
vector<string> toremove;
|
vector<string> toremove;
|
||||||
vector<string> oldbasepaths;
|
vector<const string*> newbasepath;
|
||||||
|
vector<const string*> oldbasepaths;
|
||||||
|
|
||||||
rv = actionFunc(srcmounts,oldfusepath,minfreespace,oldbasepaths);
|
rv = actionFunc(srcmounts,oldfusepath,minfreespace,oldbasepaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
const string newfusedirpath = fs::path::dirname(newfusepath);
|
string newfusedirpath = newfusepath;
|
||||||
rv = searchFunc(srcmounts,newfusedirpath,minfreespace,newbasepath);
|
fs::path::dirname(newfusedirpath);
|
||||||
|
rv = searchFunc(srcmounts,newfusedirpath.c_str(),minfreespace,newbasepath);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
|
@ -121,10 +128,11 @@ _rename_create_path(Policy::Func::Search searchFunc,
|
||||||
{
|
{
|
||||||
const string &oldbasepath = srcmounts[i];
|
const string &oldbasepath = srcmounts[i];
|
||||||
|
|
||||||
_rename_create_path_one(oldbasepaths,oldbasepath,newbasepath,
|
_rename_create_path_core(oldbasepaths,
|
||||||
oldfusepath,newfusepath,
|
oldbasepath,*newbasepath[0],
|
||||||
newfusedirpath,
|
oldfusepath,newfusepath,
|
||||||
error,toremove);
|
newfusedirpath,
|
||||||
|
error,toremove);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(error == 0)
|
if(error == 0)
|
||||||
|
@ -140,25 +148,25 @@ _clonepath_if_would_create(Policy::Func::Search searchFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &oldbasepath,
|
const string &oldbasepath,
|
||||||
const string &oldfusepath,
|
const char *oldfusepath,
|
||||||
const string &newfusepath)
|
const char *newfusepath)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
string newbasepath;
|
|
||||||
string newfusedirpath;
|
string newfusedirpath;
|
||||||
|
vector<const string*> newbasepath;
|
||||||
|
|
||||||
newfusedirpath = fs::path::dirname(newfusepath);
|
newfusedirpath = newfusepath;
|
||||||
|
fs::path::dirname(newfusedirpath);
|
||||||
rv = createFunc(srcmounts,newfusedirpath,minfreespace,newbasepath);
|
rv = createFunc(srcmounts,newfusedirpath.c_str(),minfreespace,newbasepath);
|
||||||
if(rv != -1)
|
if(rv != -1)
|
||||||
{
|
{
|
||||||
if(oldbasepath == newbasepath)
|
if(oldbasepath == *newbasepath[0])
|
||||||
{
|
{
|
||||||
rv = searchFunc(srcmounts,newfusedirpath,minfreespace,newbasepath);
|
rv = searchFunc(srcmounts,newfusedirpath.c_str(),minfreespace,newbasepath);
|
||||||
if(rv != -1)
|
if(rv != -1)
|
||||||
{
|
{
|
||||||
const ugid::SetRootGuard ugidGuard;
|
const ugid::SetRootGuard ugidGuard;
|
||||||
fs::clonepath(newbasepath,oldbasepath,newfusedirpath);
|
fs::clonepath(*newbasepath[0],oldbasepath,newfusedirpath.c_str());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -173,29 +181,29 @@ _clonepath_if_would_create(Policy::Func::Search searchFunc,
|
||||||
|
|
||||||
static
|
static
|
||||||
void
|
void
|
||||||
_rename_preserve_path_one(Policy::Func::Search searchFunc,
|
_rename_preserve_path_core(Policy::Func::Search searchFunc,
|
||||||
Policy::Func::Create createFunc,
|
Policy::Func::Create createFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const vector<string> &oldbasepaths,
|
const vector<const string*> &oldbasepaths,
|
||||||
const string &oldbasepath,
|
const string &oldbasepath,
|
||||||
const string &oldfusepath,
|
const char *oldfusepath,
|
||||||
const string &newfusepath,
|
const char *newfusepath,
|
||||||
int &error,
|
int &error,
|
||||||
vector<string> &toremove)
|
vector<string> &toremove)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
bool ismember;
|
bool ismember;
|
||||||
string newfullpath;
|
string newfullpath;
|
||||||
|
|
||||||
fs::path::make(oldbasepath,newfusepath,newfullpath);
|
fs::path::make(&oldbasepath,newfusepath,newfullpath);
|
||||||
|
|
||||||
ismember = member(oldbasepaths,oldbasepath);
|
ismember = member(oldbasepaths,oldbasepath);
|
||||||
if(ismember)
|
if(ismember)
|
||||||
{
|
{
|
||||||
string oldfullpath;
|
string oldfullpath;
|
||||||
|
|
||||||
fs::path::make(oldbasepath,oldfusepath,oldfullpath);
|
fs::path::make(&oldbasepath,oldfusepath,oldfullpath);
|
||||||
|
|
||||||
rv = ::rename(oldfullpath.c_str(),newfullpath.c_str());
|
rv = ::rename(oldfullpath.c_str(),newfullpath.c_str());
|
||||||
if((rv == -1) && (errno == ENOENT))
|
if((rv == -1) && (errno == ENOENT))
|
||||||
|
@ -224,13 +232,13 @@ _rename_preserve_path(Policy::Func::Search searchFunc,
|
||||||
Policy::Func::Create createFunc,
|
Policy::Func::Create createFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &oldfusepath,
|
const char *oldfusepath,
|
||||||
const string &newfusepath)
|
const char *newfusepath)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
int error;
|
||||||
vector<string> toremove;
|
vector<string> toremove;
|
||||||
vector<string> oldbasepaths;
|
vector<const string*> oldbasepaths;
|
||||||
|
|
||||||
rv = actionFunc(srcmounts,oldfusepath,minfreespace,oldbasepaths);
|
rv = actionFunc(srcmounts,oldfusepath,minfreespace,oldbasepaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
|
@ -241,11 +249,11 @@ _rename_preserve_path(Policy::Func::Search searchFunc,
|
||||||
{
|
{
|
||||||
const string &oldbasepath = srcmounts[i];
|
const string &oldbasepath = srcmounts[i];
|
||||||
|
|
||||||
_rename_preserve_path_one(searchFunc,createFunc,
|
_rename_preserve_path_core(searchFunc,createFunc,
|
||||||
srcmounts,minfreespace,
|
srcmounts,minfreespace,
|
||||||
oldbasepaths,oldbasepath,
|
oldbasepaths,oldbasepath,
|
||||||
oldfusepath,newfusepath,
|
oldfusepath,newfusepath,
|
||||||
error,toremove);
|
error,toremove);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(error == 0)
|
if(error == 0)
|
||||||
|
|
|
@ -33,32 +33,54 @@ using mergerfs::Policy;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_rmdir(Policy::Func::Action actionFunc,
|
_rmdir_loop_core(const string *basepath,
|
||||||
const vector<string> &srcmounts,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const int error)
|
||||||
const string &fusepath)
|
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
string fullpath;
|
||||||
vector<string> paths;
|
|
||||||
|
|
||||||
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
if(rv == -1)
|
|
||||||
return -errno;
|
rv = ::rmdir(fullpath.c_str());
|
||||||
|
|
||||||
|
return calc_error(rv,error,errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_rmdir_loop(const vector<const string*> &basepaths,
|
||||||
|
const char *fusepath)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
error = -1;
|
error = -1;
|
||||||
for(size_t i = 0, ei = paths.size(); i != ei; i++)
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
fs::path::append(paths[i],fusepath);
|
error = _rmdir_loop_core(basepaths[i],fusepath,error);
|
||||||
|
|
||||||
rv = ::rmdir(paths[i].c_str());
|
|
||||||
|
|
||||||
error = calc_error(rv,error,errno);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -error;
|
return -error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_rmdir(Policy::Func::Action actionFunc,
|
||||||
|
const vector<string> &srcmounts,
|
||||||
|
const size_t minfreespace,
|
||||||
|
const char *fusepath)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
vector<const string*> basepaths;
|
||||||
|
|
||||||
|
rv = actionFunc(srcmounts,fusepath,minfreespace,basepaths);
|
||||||
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return _rmdir_loop(basepaths,fusepath);
|
||||||
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
{
|
{
|
||||||
namespace fuse
|
namespace fuse
|
||||||
|
|
|
@ -287,41 +287,73 @@ _setxattr_controlfile(Config &config,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef WITHOUT_XATTR
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_setxattr_loop_core(const string *basepath,
|
||||||
|
const char *fusepath,
|
||||||
|
const char *attrname,
|
||||||
|
const char *attrval,
|
||||||
|
const size_t attrvalsize,
|
||||||
|
const int flags,
|
||||||
|
const int error)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
string fullpath;
|
||||||
|
|
||||||
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
|
|
||||||
|
rv = ::lsetxattr(fullpath.c_str(),attrname,attrval,attrvalsize,flags);
|
||||||
|
|
||||||
|
return calc_error(rv,error,errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_setxattr_loop(const vector<const string*> &basepaths,
|
||||||
|
const char *fusepath,
|
||||||
|
const char *attrname,
|
||||||
|
const char *attrval,
|
||||||
|
const size_t attrvalsize,
|
||||||
|
const int flags)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = -1;
|
||||||
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
|
{
|
||||||
|
error = _setxattr_loop_core(basepaths[i],fusepath,
|
||||||
|
attrname,attrval,attrvalsize,flags,
|
||||||
|
error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -error;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_setxattr(Policy::Func::Action actionFunc,
|
_setxattr(Policy::Func::Action actionFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &fusepath,
|
const char *fusepath,
|
||||||
const char *attrname,
|
const char *attrname,
|
||||||
const char *attrval,
|
const char *attrval,
|
||||||
const size_t attrvalsize,
|
const size_t attrvalsize,
|
||||||
const int flags)
|
const int flags)
|
||||||
{
|
{
|
||||||
#ifndef WITHOUT_XATTR
|
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
vector<const string*> basepaths;
|
||||||
vector<string> paths;
|
|
||||||
|
|
||||||
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
|
rv = actionFunc(srcmounts,fusepath,minfreespace,basepaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
error = -1;
|
return _setxattr_loop(basepaths,fusepath,attrname,attrval,attrvalsize,flags);
|
||||||
for(size_t i = 0, ei = paths.size(); i != ei; i++)
|
|
||||||
{
|
|
||||||
fs::path::append(paths[i],fusepath);
|
|
||||||
|
|
||||||
rv = ::lsetxattr(paths[i].c_str(),attrname,attrval,attrvalsize,flags);
|
|
||||||
|
|
||||||
error = calc_error(rv,error,errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -error;
|
|
||||||
#else
|
|
||||||
return -ENOTSUP;
|
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
{
|
{
|
||||||
namespace fuse
|
namespace fuse
|
||||||
|
@ -342,6 +374,7 @@ namespace mergerfs
|
||||||
string(attrval,attrvalsize),
|
string(attrval,attrvalsize),
|
||||||
flags);
|
flags);
|
||||||
|
|
||||||
|
#ifndef WITHOUT_XATTR
|
||||||
const ugid::Set ugid(fc->uid,fc->gid);
|
const ugid::Set ugid(fc->uid,fc->gid);
|
||||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||||
|
|
||||||
|
@ -353,6 +386,9 @@ namespace mergerfs
|
||||||
attrval,
|
attrval,
|
||||||
attrvalsize,
|
attrvalsize,
|
||||||
flags);
|
flags);
|
||||||
|
#else
|
||||||
|
return -ENOTSUP;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
10
src/str.cpp
10
src/str.cpp
|
@ -28,7 +28,7 @@ namespace str
|
||||||
{
|
{
|
||||||
void
|
void
|
||||||
split(vector<string> &result,
|
split(vector<string> &result,
|
||||||
const string &str,
|
const char *str,
|
||||||
const char delimiter)
|
const char delimiter)
|
||||||
{
|
{
|
||||||
string part;
|
string part;
|
||||||
|
@ -38,6 +38,14 @@ namespace str
|
||||||
result.push_back(part);
|
result.push_back(part);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
split(vector<string> &result,
|
||||||
|
const string &str,
|
||||||
|
const char delimiter)
|
||||||
|
{
|
||||||
|
return split(result,str.c_str(),delimiter);
|
||||||
|
}
|
||||||
|
|
||||||
string
|
string
|
||||||
join(const vector<string> &vec,
|
join(const vector<string> &vec,
|
||||||
const size_t substridx,
|
const size_t substridx,
|
||||||
|
|
|
@ -20,6 +20,10 @@
|
||||||
namespace str
|
namespace str
|
||||||
{
|
{
|
||||||
void
|
void
|
||||||
|
split(std::vector<std::string> &result,
|
||||||
|
const char *str,
|
||||||
|
const char delimiter);
|
||||||
|
void
|
||||||
split(std::vector<std::string> &result,
|
split(std::vector<std::string> &result,
|
||||||
const std::string &str,
|
const std::string &str,
|
||||||
const char delimiter);
|
const char delimiter);
|
||||||
|
|
|
@ -33,49 +33,81 @@ using std::vector;
|
||||||
using mergerfs::Policy;
|
using mergerfs::Policy;
|
||||||
using namespace mergerfs;
|
using namespace mergerfs;
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_symlink_loop_core(const string &existingpath,
|
||||||
|
const string &newbasepath,
|
||||||
|
const char *oldpath,
|
||||||
|
const char *newpath,
|
||||||
|
const char *newdirpath,
|
||||||
|
const int error)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
string fullnewpath;
|
||||||
|
|
||||||
|
if(newbasepath != existingpath)
|
||||||
|
{
|
||||||
|
const ugid::SetRootGuard ugidGuard;
|
||||||
|
fs::clonepath(existingpath,newbasepath,newdirpath);
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::path::make(&newbasepath,newpath,fullnewpath);
|
||||||
|
|
||||||
|
rv = ::symlink(oldpath,fullnewpath.c_str());
|
||||||
|
|
||||||
|
return calc_error(rv,error,errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_symlink_loop(const string &existingpath,
|
||||||
|
const vector<const string*> newbasepaths,
|
||||||
|
const char *oldpath,
|
||||||
|
const char *newpath,
|
||||||
|
const char *newdirpath)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
|
error = -1;
|
||||||
|
for(size_t i = 0, ei = newbasepaths.size(); i != ei; i++)
|
||||||
|
{
|
||||||
|
error = _symlink_loop_core(existingpath,*newbasepaths[i],
|
||||||
|
oldpath,newpath,newdirpath,
|
||||||
|
error);
|
||||||
|
}
|
||||||
|
|
||||||
|
return -error;
|
||||||
|
}
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_symlink(Policy::Func::Search searchFunc,
|
_symlink(Policy::Func::Search searchFunc,
|
||||||
Policy::Func::Create createFunc,
|
Policy::Func::Create createFunc,
|
||||||
const vector<string> &srcmounts,
|
const vector<string> &srcmounts,
|
||||||
const size_t minfreespace,
|
const size_t minfreespace,
|
||||||
const string &oldpath,
|
const char *oldpath,
|
||||||
const string &newpath)
|
const char *newpath)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
string newdirpath;
|
||||||
string dirname;
|
const char *newdirpathcstr;
|
||||||
string existingpath;
|
vector<const string*> newbasepaths;
|
||||||
vector<string> newpathdirs;
|
vector<const string*> existingpaths;
|
||||||
|
|
||||||
dirname = fs::path::dirname(newpath);
|
newdirpath = newpath;
|
||||||
rv = searchFunc(srcmounts,dirname,minfreespace,existingpath);
|
fs::path::dirname(newdirpath);
|
||||||
|
newdirpathcstr = newdirpath.c_str();
|
||||||
|
|
||||||
|
rv = searchFunc(srcmounts,newdirpathcstr,minfreespace,existingpaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
rv = createFunc(srcmounts,dirname,minfreespace,newpathdirs);
|
rv = createFunc(srcmounts,newdirpathcstr,minfreespace,newbasepaths);
|
||||||
if(rv == -1)
|
if(rv == -1)
|
||||||
return -errno;
|
return -errno;
|
||||||
|
|
||||||
error = -1;
|
return _symlink_loop(*existingpaths[0],newbasepaths,
|
||||||
for(size_t i = 0, ei = newpathdirs.size(); i != ei; i++)
|
oldpath,newpath,newdirpathcstr);
|
||||||
{
|
|
||||||
string &newpathdir = newpathdirs[i];
|
|
||||||
|
|
||||||
if(newpathdir != existingpath)
|
|
||||||
{
|
|
||||||
const ugid::SetRootGuard ugidGuard;
|
|
||||||
fs::clonepath(existingpath,newpathdir,dirname);
|
|
||||||
}
|
|
||||||
|
|
||||||
fs::path::append(newpathdir,newpath);
|
|
||||||
|
|
||||||
rv = symlink(oldpath.c_str(),newpathdir.c_str());
|
|
||||||
|
|
||||||
error = calc_error(rv,error,errno);
|
|
||||||
}
|
|
||||||
|
|
||||||
return -error;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
|
|
|
@ -35,33 +35,56 @@ using mergerfs::Policy;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_truncate(Policy::Func::Action actionFunc,
|
_truncate_loop_core(const string *basepath,
|
||||||
const vector<string> &srcmounts,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const off_t size,
|
||||||
const string &fusepath,
|
const int error)
|
||||||
const off_t size)
|
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
string fullpath;
|
||||||
vector<string> paths;
|
|
||||||
|
|
||||||
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
if(rv == -1)
|
|
||||||
return -errno;
|
rv = ::truncate(fullpath.c_str(),size);
|
||||||
|
|
||||||
|
return calc_error(rv,error,errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_truncate_loop(const vector<const string*> &basepaths,
|
||||||
|
const char *fusepath,
|
||||||
|
const off_t size)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
error = -1;
|
error = -1;
|
||||||
for(size_t i = 0, ei = paths.size(); i != ei; i++)
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
fs::path::append(paths[i],fusepath);
|
error = _truncate_loop_core(basepaths[0],fusepath,size,error);
|
||||||
|
|
||||||
rv = ::truncate(paths[i].c_str(),size);
|
|
||||||
|
|
||||||
error = calc_error(rv,error,errno);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -error;
|
return -error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_truncate(Policy::Func::Action actionFunc,
|
||||||
|
const vector<string> &srcmounts,
|
||||||
|
const size_t minfreespace,
|
||||||
|
const char *fusepath,
|
||||||
|
const off_t size)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
vector<const string*> basepaths;
|
||||||
|
|
||||||
|
rv = actionFunc(srcmounts,fusepath,minfreespace,basepaths);
|
||||||
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return _truncate_loop(basepaths,fusepath,size);
|
||||||
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
{
|
{
|
||||||
namespace fuse
|
namespace fuse
|
||||||
|
|
|
@ -34,32 +34,53 @@ using mergerfs::Policy;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_unlink(Policy::Func::Action actionFunc,
|
_unlink_loop_core(const string *basepath,
|
||||||
const vector<string> &srcmounts,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const int error)
|
||||||
const string &fusepath)
|
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
string fullpath;
|
||||||
vector<string> paths;
|
|
||||||
|
|
||||||
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
if(rv == -1)
|
|
||||||
return -errno;
|
rv = ::unlink(fullpath.c_str());
|
||||||
|
|
||||||
|
return calc_error(rv,error,errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_unlink_loop(const vector<const string*> &basepaths,
|
||||||
|
const char *fusepath)
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
error = -1;
|
error = -1;
|
||||||
for(size_t i = 0, ei = paths.size(); i != ei; i++)
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
fs::path::append(paths[i],fusepath);
|
error = _unlink_loop_core(basepaths[i],fusepath,error);
|
||||||
|
|
||||||
rv = ::unlink(paths[i].c_str());
|
|
||||||
|
|
||||||
error = calc_error(rv,error,errno);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -error;
|
return -error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_unlink(Policy::Func::Action actionFunc,
|
||||||
|
const vector<string> &srcmounts,
|
||||||
|
const size_t minfreespace,
|
||||||
|
const char *fusepath)
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
vector<const string*> basepaths;
|
||||||
|
|
||||||
|
rv = actionFunc(srcmounts,fusepath,minfreespace,basepaths);
|
||||||
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return _unlink_loop(basepaths,fusepath);
|
||||||
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
{
|
{
|
||||||
namespace fuse
|
namespace fuse
|
||||||
|
|
|
@ -35,33 +35,56 @@ using mergerfs::Policy;
|
||||||
|
|
||||||
static
|
static
|
||||||
int
|
int
|
||||||
_utimens(Policy::Func::Action actionFunc,
|
_utimens_loop_core(const string *basepath,
|
||||||
const vector<string> &srcmounts,
|
const char *fusepath,
|
||||||
const size_t minfreespace,
|
const timespec ts[2],
|
||||||
const string &fusepath,
|
const int error)
|
||||||
const timespec ts[2])
|
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
int error;
|
string fullpath;
|
||||||
vector<string> paths;
|
|
||||||
|
|
||||||
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
|
fs::path::make(basepath,fusepath,fullpath);
|
||||||
if(rv == -1)
|
|
||||||
return -errno;
|
rv = ::utimensat(0,fullpath.c_str(),ts,AT_SYMLINK_NOFOLLOW);
|
||||||
|
|
||||||
|
return calc_error(rv,error,errno);
|
||||||
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_utimens_loop(const vector<const string*> &basepaths,
|
||||||
|
const char *fusepath,
|
||||||
|
const timespec ts[2])
|
||||||
|
{
|
||||||
|
int error;
|
||||||
|
|
||||||
error = -1;
|
error = -1;
|
||||||
for(size_t i = 0, ei = paths.size(); i != ei; i++)
|
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
|
||||||
{
|
{
|
||||||
fs::path::append(paths[i],fusepath);
|
error = _utimens_loop_core(basepaths[i],fusepath,ts,error);
|
||||||
|
|
||||||
rv = ::utimensat(0,paths[i].c_str(),ts,AT_SYMLINK_NOFOLLOW);
|
|
||||||
|
|
||||||
error = calc_error(rv,error,errno);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return -error;
|
return -error;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static
|
||||||
|
int
|
||||||
|
_utimens(Policy::Func::Action actionFunc,
|
||||||
|
const vector<string> &srcmounts,
|
||||||
|
const size_t minfreespace,
|
||||||
|
const char *fusepath,
|
||||||
|
const timespec ts[2])
|
||||||
|
{
|
||||||
|
int rv;
|
||||||
|
vector<const string*> basepaths;
|
||||||
|
|
||||||
|
rv = actionFunc(srcmounts,fusepath,minfreespace,basepaths);
|
||||||
|
if(rv == -1)
|
||||||
|
return -errno;
|
||||||
|
|
||||||
|
return _utimens_loop(basepaths,fusepath,ts);
|
||||||
|
}
|
||||||
|
|
||||||
namespace mergerfs
|
namespace mergerfs
|
||||||
{
|
{
|
||||||
namespace fuse
|
namespace fuse
|
||||||
|
|
Loading…
Reference in New Issue
Block a user