Browse Source

Merge pull request #219 from trapexit/pathmake

use references to srcmounts rather than copies
pull/220/head
Antonio SJ Musumeci 9 years ago
parent
commit
c568a6d356
  1. 11
      src/access.cpp
  2. 53
      src/chmod.cpp
  3. 55
      src/chown.cpp
  4. 66
      src/create.cpp
  5. 4
      src/fallocate.cpp
  6. 4
      src/flush.cpp
  7. 16
      src/fs.cpp
  8. 4
      src/fs.hpp
  9. 11
      src/fs_clonepath.cpp
  10. 2
      src/fs_clonepath.hpp
  11. 5
      src/fs_movefile.cpp
  12. 62
      src/fs_path.cpp
  13. 35
      src/fs_path.hpp
  14. 11
      src/getattr.cpp
  15. 24
      src/getxattr.cpp
  16. 14
      src/ioctl.cpp
  17. 139
      src/link.cpp
  18. 21
      src/listxattr.cpp
  19. 85
      src/mkdir.cpp
  20. 89
      src/mknod.cpp
  21. 36
      src/open.cpp
  22. 48
      src/policy.hpp
  23. 15
      src/policy_all.cpp
  24. 4
      src/policy_einval.cpp
  25. 4
      src/policy_enosys.cpp
  26. 4
      src/policy_enotsup.cpp
  27. 36
      src/policy_epmfs.cpp
  28. 4
      src/policy_erofs.cpp
  29. 4
      src/policy_exdev.cpp
  30. 25
      src/policy_ff.cpp
  31. 21
      src/policy_ffwp.cpp
  32. 26
      src/policy_fwfs.cpp
  33. 4
      src/policy_invalid.cpp
  34. 36
      src/policy_lfs.cpp
  35. 36
      src/policy_mfs.cpp
  36. 24
      src/policy_newest.cpp
  37. 4
      src/policy_rand.cpp
  38. 5
      src/readdir.cpp
  39. 35
      src/readlink.cpp
  40. 64
      src/removexattr.cpp
  41. 76
      src/rename.cpp
  42. 52
      src/rmdir.cpp
  43. 72
      src/setxattr.cpp
  44. 10
      src/str.cpp
  45. 4
      src/str.hpp
  46. 88
      src/symlink.cpp
  47. 53
      src/truncate.cpp
  48. 51
      src/unlink.cpp
  49. 53
      src/utimens.cpp

11
src/access.cpp

@ -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);
} }

53
src/chmod.cpp

@ -30,33 +30,56 @@ using std::string;
using std::vector; using std::vector;
using mergerfs::Policy; using mergerfs::Policy;
static
int
_chmod_loop_core(const string *basepath,
const char *fusepath,
const mode_t mode,
const int error)
{
int rv;
string fullpath;
fs::path::make(basepath,fusepath,fullpath);
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;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{
error = _chmod_loop_core(basepaths[i],fusepath,mode,error);
}
return -error;
}
static static
int int
_chmod(Policy::Func::Action actionFunc, _chmod(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 mode_t mode) const mode_t mode)
{ {
int rv; int rv;
int error;
vector<string> paths;
vector<const string*> basepaths;
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
rv = actionFunc(srcmounts,fusepath,minfreespace,basepaths);
if(rv == -1) if(rv == -1)
return -errno; return -errno;
error = -1;
for(size_t i = 0, ei = paths.size(); i != ei; i++)
{
fs::path::append(paths[i],fusepath);
rv = ::chmod(paths[i].c_str(),mode);
error = calc_error(rv,error,errno);
}
return -error;
return _chmod_loop(basepaths,fusepath,mode);
} }
namespace mergerfs namespace mergerfs

55
src/chown.cpp

@ -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<string> paths;
vector<const string*> basepaths;
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
rv = actionFunc(srcmounts,fusepath,minfreespace,basepaths);
if(rv == -1) if(rv == -1)
return -errno; return -errno;
error = -1;
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;
return _chown_loop(basepaths,fusepath,uid,gid);
} }
namespace mergerfs namespace mergerfs

66
src/create.cpp

@ -38,39 +38,26 @@ using namespace mergerfs;
static static
int int
_create(Policy::Func::Search searchFunc,
Policy::Func::Create createFunc,
const vector<string> &srcmounts,
const size_t minfreespace,
const string &fusepath,
_create_core(const string &existingpath,
const string &createpath,
const char *fusepath,
const char *fusedirpath,
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 dirname;
vector<string> createpath;
vector<string> existingpath;
dirname = fs::path::dirname(fusepath);
rv = searchFunc(srcmounts,dirname,minfreespace,existingpath);
if(rv == -1)
return -errno;
string fullpath;
rv = createFunc(srcmounts,dirname,minfreespace,createpath);
if(rv == -1)
return -errno;
if(createpath[0] != existingpath[0])
if(createpath != existingpath)
{ {
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

4
src/fallocate.cpp

@ -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>

4
src/flush.cpp

@ -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);
} }

16
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)
{
for(size_t i = 0, ei = srcmounts.size(); i != ei; i++)
{ {
int rv; int rv;
string fullpath; string fullpath;
struct stat st; struct stat st;
fs::path::make(srcmounts[i],fusepath,fullpath);
for(size_t i = 0, ei = srcmounts.size(); i != ei; i++)
{
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;

4
src/fs.hpp

@ -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);

11
src/fs_clonepath.cpp

@ -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)
{ {

2
src/fs_clonepath.hpp

@ -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);
} }

5
src/fs_movefile.cpp

@ -66,8 +66,9 @@ namespace fs
if(rv == -1) if(rv == -1)
return -1; return -1;
fusedir = fs::path::dirname(fusepath);
rv = fs::clonepath(fdin_path,fdout_path,fusedir);
fusedir = fusepath;
fs::path::dirname(fusedir);
rv = fs::clonepath(fdin_path,fdout_path,fusedir.c_str());
if(rv == -1) if(rv == -1)
return -1; return -1;

62
src/fs_path.cpp

@ -29,15 +29,14 @@ namespace fs
{ {
namespace path namespace path
{ {
string
dirname(const string &path)
void
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();
i = parent.rbegin();
bi = path.rend();
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());
return parent;
path.erase(i.base(),path.end());
} }
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;
}
} }
} }

35
src/fs_path.hpp

@ -25,42 +25,27 @@ namespace fs
namespace path namespace path
{ {
using std::string; using std::string;
using std::vector;
string dirname(const string &path);
string basename(const string &path);
bool is_empty(const string &path);
void dirname(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;
}
string basename(const string &path);
inline inline
void void
make(const string &base,
const string &suffix,
string &output)
append(string &base,
const char *suffix)
{ {
output = base + suffix;
base += suffix;
} }
inline inline
void void
append(string &base,
const string &suffix)
make(const string *base,
const char *suffix,
string &output)
{ {
base += suffix;
output = *base;
output += suffix;
} }
} }
}; };

11
src/getattr.cpp

@ -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);
} }

24
src/getxattr.cpp

@ -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 string &attrname,
const char *fusepath,
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);

14
src/ioctl.cpp

@ -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,7 +90,7 @@ _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)
{ {

139
src/link.cpp

@ -36,10 +36,10 @@ 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 string &newfusepath,
const char *oldfusepath,
const char *newfusepath,
const string &newfusedirpath, const string &newfusedirpath,
const int error) const int error)
{ {
@ -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,newfusepath,newfullpath);
fs::path::make(&oldbasepath,oldfusepath,oldfullpath);
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 string &newfusepath)
const char *oldfusepath,
const char *newfusepath)
{ {
int rv; int rv;
int error;
string newbasepath;
vector<string> toremove;
vector<string> oldbasepaths;
string newfusedirpath;
vector<const string*> oldbasepaths;
vector<const string*> newbasepaths;
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);
rv = searchFunc(srcmounts,newfusedirpath,minfreespace,newbasepath);
newfusedirpath = newfusepath;
fs::path::dirname(newfusedirpath);
rv = searchFunc(srcmounts,newfusedirpath.c_str(),minfreespace,newbasepaths);
if(rv == -1) if(rv == -1)
return -errno; return -errno;
error = -1;
for(size_t i = 0, ei = oldbasepaths.size(); i != ei; i++)
{
const string &oldbasepath = oldbasepaths[i];
error = _link_create_path_one(oldbasepath,newbasepath,
return _link_create_path_loop(oldbasepaths,*newbasepaths[0],
oldfusepath,newfusepath, oldfusepath,newfusepath,
newfusedirpath,
error);
}
return -error;
newfusedirpath);
} }
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 string &newfusepath)
const char *oldfusepath,
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 string &newfusepath,
const char *oldfusepath,
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,newfusepath,newfullpath);
fs::path::make(&oldbasepath,oldfusepath,oldfullpath);
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());
} }
@ -170,31 +187,22 @@ _link_preserve_path_one(Policy::Func::Search searchFunc,
static static
int int
_link_preserve_path(Policy::Func::Search searchFunc,
Policy::Func::Action actionFunc,
_link_preserve_path_loop(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 string &newfusepath)
const char *oldfusepath,
const char *newfusepath,
const vector<const string*> &oldbasepaths)
{ {
int rv;
int error; int error;
vector<string> toremove;
vector<string> oldbasepaths;
rv = actionFunc(srcmounts,oldfusepath,minfreespace,oldbasepaths);
if(rv == -1)
return -errno;
error = -1; error = -1;
for(size_t i = 0, ei = oldbasepaths.size(); i != ei; i++) for(size_t i = 0, ei = oldbasepaths.size(); i != ei; i++)
{ {
const string &oldbasepath = oldbasepaths[i];
error = _link_preserve_path_one(searchFunc,createFunc,
error = _link_preserve_path_core(searchFunc,createFunc,
srcmounts,minfreespace, srcmounts,minfreespace,
oldbasepath,
*oldbasepaths[i],
oldfusepath,newfusepath, oldfusepath,newfusepath,
error); error);
} }
@ -202,6 +210,29 @@ _link_preserve_path(Policy::Func::Search searchFunc,
return -error; return -error;
} }
static
int
_link_preserve_path(Policy::Func::Search searchFunc,
Policy::Func::Action actionFunc,
Policy::Func::Create createFunc,
const vector<string> &srcmounts,
const size_t minfreespace,
const char *oldfusepath,
const char *newfusepath)
{
int rv;
vector<const string*> oldbasepaths;
rv = actionFunc(srcmounts,oldfusepath,minfreespace,oldbasepaths);
if(rv == -1)
return -errno;
return _link_preserve_path_loop(searchFunc,createFunc,
srcmounts,minfreespace,
oldfusepath,newfusepath,
oldbasepaths);
}
namespace mergerfs namespace mergerfs
{ {
namespace fuse namespace fuse

21
src/listxattr.cpp

@ -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
} }
} }
} }

85
src/mkdir.cpp

@ -35,49 +35,80 @@ using std::vector;
using mergerfs::Policy; using mergerfs::Policy;
using namespace mergerfs; using namespace mergerfs;
static
int
_mkdir_loop_core(const string &existingpath,
const string &createpath,
const char *fusepath,
const char *fusedirpath,
const mode_t mode,
const int error)
{
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;
error = -1;
for(size_t i = 0, ei = createpaths.size(); i != ei; i++)
{
error = _mkdir_loop_core(existingpath,*createpaths[i],
fusepath,fusedirpath,mode,error);
}
return -error;
}
static static
int int
_mkdir(Policy::Func::Search searchFunc, _mkdir(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 &fusepath,
const char *fusepath,
const mode_t mode) const mode_t mode)
{ {
int rv; int rv;
int error;
string dirname;
string existingpath;
vector<string> createpaths;
string fusedirpath;
const char *fusedirpathcstr;
vector<const string*> createpaths;
vector<const string*> existingpaths;
fusedirpath = fusepath;
fs::path::dirname(fusedirpath);
fusedirpathcstr = fusedirpath.c_str();
dirname = fs::path::dirname(fusepath);
rv = searchFunc(srcmounts,dirname,minfreespace,existingpath);
rv = searchFunc(srcmounts,fusedirpathcstr,minfreespace,existingpaths);
if(rv == -1) if(rv == -1)
return -errno; return -errno;
rv = createFunc(srcmounts,dirname,minfreespace,createpaths);
rv = createFunc(srcmounts,fusedirpathcstr,minfreespace,createpaths);
if(rv == -1) if(rv == -1)
return -errno; return -errno;
error = -1;
for(size_t i = 0, ei = createpaths.size(); i != ei; i++)
{
string &createpath = createpaths[i];
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 _mkdir_loop(*existingpaths[0],createpaths,
fusepath,fusedirpathcstr,mode);
} }
namespace mergerfs namespace mergerfs

89
src/mknod.cpp

@ -36,50 +36,85 @@ using std::string;
using std::vector; using std::vector;
using namespace mergerfs; using namespace mergerfs;
static
int
_mknod_loop_core(const string &existingpath,
const string &createpath,
const char *fusepath,
const char *fusedirpath,
const mode_t mode,
const dev_t dev,
const int error)
{
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;
error = -1;
for(size_t i = 0, ei = createpaths.size(); i != ei; i++)
{
error = _mknod_loop_core(existingpath,*createpaths[i],
fusepath,fusedirpath,
mode,dev,error);
}
return -error;
}
static static
int int
_mknod(Policy::Func::Search searchFunc, _mknod(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 &fusepath,
const char *fusepath,
const mode_t mode, const mode_t mode,
const dev_t dev) const dev_t dev)
{ {
int rv; int rv;
int error;
string dirname;
string existingpath;
vector<string> createpaths;
string fusedirpath;
const char *fusedirpathcstr;
vector<const string*> createpaths;
vector<const string*> existingpaths;
fusedirpath = fusepath;
fs::path::dirname(fusedirpath);
fusedirpathcstr = fusedirpath.c_str();
dirname = fs::path::dirname(fusepath);
rv = searchFunc(srcmounts,dirname,minfreespace,existingpath);
rv = searchFunc(srcmounts,fusedirpathcstr,minfreespace,existingpaths);
if(rv == -1) if(rv == -1)
return -errno; return -errno;
rv = createFunc(srcmounts,dirname,minfreespace,createpaths);
rv = createFunc(srcmounts,fusedirpathcstr,minfreespace,createpaths);
if(rv == -1) if(rv == -1)
return -errno; return -errno;
error = -1;
for(size_t i = 0, ei = createpaths.size(); i != ei; i++)
{
string &createpath = createpaths[i];
if(createpath != existingpath)
{
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 _mknod_loop(*existingpaths[0],createpaths,
fusepath,fusedirpathcstr,
mode,dev);
} }
namespace mergerfs namespace mergerfs

36
src/open.cpp

@ -35,24 +35,17 @@ using mergerfs::Policy;
static static
int int
_open(Policy::Func::Search searchFunc,
const vector<string> &srcmounts,
const size_t minfreespace,
const string &fusepath,
_open_core(const string *basepath,
const char *fusepath,
const int flags, const int flags,
uint64_t &fh) uint64_t &fh)
{ {
int fd; int fd;
int rv;
vector<string> path;
string fullpath;
rv = searchFunc(srcmounts,fusepath,minfreespace,path);
if(rv == -1)
return -errno;
fs::path::make(basepath,fusepath,fullpath);
fs::path::append(path[0],fusepath);
fd = ::open(path[0].c_str(),flags);
fd = ::open(fullpath.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

48
src/policy.hpp

@ -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 einval(CType,cstrvec&,cstring&,csize_t,strvec&);
static int enosys(CType,cstrvec&,cstring&,csize_t,strvec&);
static int enotsup(CType,cstrvec&,cstring&,csize_t,strvec&);
static int epmfs(CType,cstrvec&,cstring&,csize_t,strvec&);
static int erofs(CType,cstrvec&,cstring&,csize_t,strvec&);
static int exdev(CType,cstrvec&,cstring&,csize_t,strvec&);
static int ff(CType,cstrvec&,cstring&,csize_t,strvec&);
static int ffwp(CType,cstrvec&,cstring&,csize_t,strvec&);
static int fwfs(CType,cstrvec&,cstring&,csize_t,strvec&);
static int invalid(CType,cstrvec&,cstring&,csize_t,strvec&);
static int lfs(CType,cstrvec&,cstring&,csize_t,strvec&);
static int mfs(CType,cstrvec&,cstring&,csize_t,strvec&);
static int newest(CType,cstrvec&,cstring&,csize_t,strvec&);
static int rand(CType,cstrvec&,cstring&,csize_t,strvec&);
static int all(CType,cstrvec&,const char*,csize_t,cstrptrvec&);
static int einval(CType,cstrvec&,const char*,csize_t,cstrptrvec&);
static int enosys(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
static int enotsup(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
static int epmfs(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
static int erofs(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
static int exdev(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
static int ff(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
static int ffwp(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
static int fwfs(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
static int invalid(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
static int lfs(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
static int mfs(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
static int newest(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
static int rand(CType,cstrvec&,const char *,csize_t,cstrptrvec&);
}; };
private: private:

15
src/policy_all.cpp

@ -32,8 +32,8 @@ using std::size_t;
static static
int int
_all(const vector<string> &basepaths, _all(const vector<string> &basepaths,
const string &fusepath,
vector<string> &paths)
const char *fusepath,
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);
@ -59,12 +59,13 @@ _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);

4
src/policy_einval.cpp

@ -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);
} }

4
src/policy_enosys.cpp

@ -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);
} }

4
src/policy_enotsup.cpp

@ -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);
} }

36
src/policy_epmfs.cpp

@ -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;
@ -55,21 +54,21 @@ _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;
fsblkcnt_t epmfs;
string epmfsbasepath;
string fullpath; string fullpath;
statvfs_t fsstats; statvfs_t fsstats;
fsblkcnt_t epmfs;
const string *epmfsbasepath;
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);
@ -89,20 +88,21 @@ _epmfs_create(const vector<string> &basepaths,
static static
int int
_epmfs(const vector<string> &basepaths, _epmfs(const vector<string> &basepaths,
const string &fusepath,
vector<string> &paths)
const char *fusepath,
vector<const string*> &paths)
{ {
int rv; int rv;
fsblkcnt_t epmfs;
string epmfsbasepath;
string fullpath; string fullpath;
statvfs_t fsstats; statvfs_t fsstats;
fsblkcnt_t epmfs;
const string *epmfsbasepath;
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);

4
src/policy_erofs.cpp

@ -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);
} }

4
src/policy_exdev.cpp

@ -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);
} }

25
src/policy_ff.cpp

@ -32,17 +32,18 @@ using std::size_t;
static static
int int
_ff(const vector<string> &basepaths, _ff(const vector<string> &basepaths,
const string &fusepath,
vector<string> &paths)
const char *fusepath,
vector<const string*> &paths)
{ {
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{
int rv; int rv;
struct stat st;
string fullpath; string fullpath;
const string &basepath = basepaths[i];
struct stat st;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{
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)
@ -59,13 +60,13 @@ _ff(const vector<string> &basepaths,
static static
int int
_ff_create(const vector<string> &basepaths, _ff_create(const vector<string> &basepaths,
const string &fusepath,
vector<string> &paths)
const char *fusepath,
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);

21
src/policy_ffwp.cpp

@ -32,17 +32,18 @@ using std::size_t;
static static
int int
_ffwp(const vector<string> &basepaths, _ffwp(const vector<string> &basepaths,
const string &fusepath,
vector<string> &paths)
const char *fusepath,
vector<const string*> &paths)
{ {
string fallback;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{
int rv; int rv;
struct stat st; struct stat st;
string fullpath; string fullpath;
const string &basepath = basepaths[i];
const string *fallback;
fallback = NULL;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{
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);
} }

26
src/policy_fwfs.cpp

@ -33,14 +33,15 @@ 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)
{ {
for(size_t i = 0, size = basepaths.size(); i != size; i++)
{
int rv; int rv;
struct statvfs fsstats; struct statvfs fsstats;
for(size_t i = 0, size = basepaths.size(); i != size; i++)
{
const string &basepath = basepaths[i]; const string &basepath = basepaths[i];
rv = ::statvfs(basepath.c_str(),&fsstats); rv = ::statvfs(basepath.c_str(),&fsstats);
@ -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)
{ {
for(size_t i = 0, size = basepaths.size(); i != size; i++)
{
int rv; int rv;
string fullpath; string fullpath;
struct statvfs fsstats; struct statvfs fsstats;
const string &basepath = basepaths[i];
for(size_t i = 0, size = basepaths.size(); i != size; i++)
{
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);

4
src/policy_invalid.cpp

@ -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
src/policy_lfs.cpp

@ -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;
string fullpath;
struct statvfs fsstats;
const string &basepath = basepaths[i];
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);

36
src/policy_mfs.cpp

@ -30,17 +30,18 @@ using std::size_t;
static static
int int
_mfs_create(const vector<string> &basepaths, _mfs_create(const vector<string> &basepaths,
const string &fusepath,
vector<string> &paths)
const char *fusepath,
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);
@ -68,19 +69,20 @@ _mfs_create(const vector<string> &basepaths,
static static
int int
_mfs(const vector<string> &basepaths, _mfs(const vector<string> &basepaths,
const string &fusepath,
vector<string> &paths)
const char *fusepath,
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;
string fullpath;
struct statvfs fsstats;
const string &basepath = basepaths[i];
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);

24
src/policy_newest.cpp

@ -33,18 +33,20 @@ using std::size_t;
static static
int int
_newest(const vector<string> &basepaths, _newest(const vector<string> &basepaths,
const string &fusepath,
vector<string> &paths)
const char *fusepath,
vector<const string*> &paths)
{ {
time_t newest = std::numeric_limits<time_t>::min();
string neweststr;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{
int rv; int rv;
struct stat st; struct stat st;
string fullpath; string fullpath;
const string &basepath = basepaths[i];
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++)
{
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);
} }

4
src/policy_rand.cpp

@ -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;

5
src/readdir.cpp

@ -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;

35
src/readlink.cpp

@ -33,23 +33,17 @@ using mergerfs::Policy;
static static
int int
_readlink(Policy::Func::Search searchFunc,
const vector<string> &srcmounts,
const size_t minfreespace,
const string &fusepath,
_readlink_core(const string *basepath,
const char *fusepath,
char *buf, char *buf,
const size_t size) const size_t size)
{ {
int rv; int rv;
vector<string> path;
rv = searchFunc(srcmounts,fusepath,minfreespace,path);
if(rv == -1)
return -errno;
string fullpath;
fs::path::append(path[0],fusepath);
fs::path::make(basepath,fusepath,fullpath);
rv = ::readlink(path[0].c_str(),buf,size);
rv = ::readlink(fullpath.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

64
src/removexattr.cpp

@ -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<string> paths;
vector<const string*> basepaths;
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
rv = actionFunc(srcmounts,fusepath,minfreespace,basepaths);
if(rv == -1) if(rv == -1)
return -errno; return -errno;
error = -1;
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
return _removexattr_loop(basepaths,fusepath,attrname);
} }
#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
} }
} }
} }

76
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,11 +60,11 @@ _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 string &newfusepath,
const char *oldfusepath,
const char *newfusepath,
const string &newfusedirpath, const string &newfusedirpath,
int &error, int &error,
vector<string> &tounlink) vector<string> &tounlink)
@ -68,7 +74,7 @@ _rename_create_path_one(const vector<string> &oldbasepaths,
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 string &newfusepath)
const char *oldfusepath,
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);
rv = searchFunc(srcmounts,newfusedirpath,minfreespace,newbasepath);
string newfusedirpath = newfusepath;
fs::path::dirname(newfusedirpath);
rv = searchFunc(srcmounts,newfusedirpath.c_str(),minfreespace,newbasepath);
if(rv == -1) if(rv == -1)
return -errno; return -errno;
@ -121,7 +128,8 @@ _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,
oldbasepath,*newbasepath[0],
oldfusepath,newfusepath, oldfusepath,newfusepath,
newfusedirpath, newfusedirpath,
error,toremove); error,toremove);
@ -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 string &newfusepath)
const char *oldfusepath,
const char *newfusepath)
{ {
int rv; int rv;
string newbasepath;
string newfusedirpath; string newfusedirpath;
vector<const string*> newbasepath;
newfusedirpath = fs::path::dirname(newfusepath);
rv = createFunc(srcmounts,newfusedirpath,minfreespace,newbasepath);
newfusedirpath = newfusepath;
fs::path::dirname(newfusedirpath);
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,14 +181,14 @@ _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 string &newfusepath,
const char *oldfusepath,
const char *newfusepath,
int &error, int &error,
vector<string> &toremove) vector<string> &toremove)
{ {
@ -188,14 +196,14 @@ _rename_preserve_path_one(Policy::Func::Search searchFunc,
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 string &newfusepath)
const char *oldfusepath,
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,7 +249,7 @@ _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,

52
src/rmdir.cpp

@ -33,32 +33,54 @@ using mergerfs::Policy;
static static
int int
_rmdir(Policy::Func::Action actionFunc,
const vector<string> &srcmounts,
const size_t minfreespace,
const string &fusepath)
_rmdir_loop_core(const string *basepath,
const char *fusepath,
const int error)
{ {
int rv; int rv;
int error;
vector<string> paths;
string fullpath;
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
if(rv == -1)
return -errno;
fs::path::make(basepath,fusepath,fullpath);
error = -1;
for(size_t i = 0, ei = paths.size(); i != ei; i++)
{
fs::path::append(paths[i],fusepath);
rv = ::rmdir(fullpath.c_str());
rv = ::rmdir(paths[i].c_str());
return calc_error(rv,error,errno);
}
static
int
_rmdir_loop(const vector<const string*> &basepaths,
const char *fusepath)
{
int error;
error = calc_error(rv,error,errno);
error = -1;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{
error = _rmdir_loop_core(basepaths[i],fusepath,error);
} }
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

72
src/setxattr.cpp

@ -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<string> paths;
vector<const string*> basepaths;
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
rv = actionFunc(srcmounts,fusepath,minfreespace,basepaths);
if(rv == -1) if(rv == -1)
return -errno; return -errno;
error = -1;
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 _setxattr_loop(basepaths,fusepath,attrname,attrval,attrvalsize,flags);
}
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

@ -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,

4
src/str.hpp

@ -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);

88
src/symlink.cpp

@ -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 string &newpath)
const char *oldpath,
const char *newpath)
{ {
int rv; int rv;
int error;
string dirname;
string existingpath;
vector<string> newpathdirs;
string newdirpath;
const char *newdirpathcstr;
vector<const string*> newbasepaths;
vector<const string*> existingpaths;
newdirpath = newpath;
fs::path::dirname(newdirpath);
newdirpathcstr = newdirpath.c_str();
dirname = fs::path::dirname(newpath);
rv = searchFunc(srcmounts,dirname,minfreespace,existingpath);
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;
for(size_t i = 0, ei = newpathdirs.size(); i != ei; i++)
{
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;
return _symlink_loop(*existingpaths[0],newbasepaths,
oldpath,newpath,newdirpathcstr);
} }
namespace mergerfs namespace mergerfs

53
src/truncate.cpp

@ -33,33 +33,56 @@ using std::string;
using std::vector; using std::vector;
using mergerfs::Policy; using mergerfs::Policy;
static
int
_truncate_loop_core(const string *basepath,
const char *fusepath,
const off_t size,
const int error)
{
int rv;
string fullpath;
fs::path::make(basepath,fusepath,fullpath);
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;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{
error = _truncate_loop_core(basepaths[0],fusepath,size,error);
}
return -error;
}
static static
int int
_truncate(Policy::Func::Action actionFunc, _truncate(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 off_t size) const off_t size)
{ {
int rv; int rv;
int error;
vector<string> paths;
vector<const string*> basepaths;
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
rv = actionFunc(srcmounts,fusepath,minfreespace,basepaths);
if(rv == -1) if(rv == -1)
return -errno; return -errno;
error = -1;
for(size_t i = 0, ei = paths.size(); i != ei; i++)
{
fs::path::append(paths[i],fusepath);
rv = ::truncate(paths[i].c_str(),size);
error = calc_error(rv,error,errno);
}
return -error;
return _truncate_loop(basepaths,fusepath,size);
} }
namespace mergerfs namespace mergerfs

51
src/unlink.cpp

@ -34,32 +34,53 @@ using mergerfs::Policy;
static static
int int
_unlink(Policy::Func::Action actionFunc,
const vector<string> &srcmounts,
const size_t minfreespace,
const string &fusepath)
_unlink_loop_core(const string *basepath,
const char *fusepath,
const int error)
{ {
int rv; int rv;
int error;
vector<string> paths;
string fullpath;
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
if(rv == -1)
return -errno;
fs::path::make(basepath,fusepath,fullpath);
error = -1;
for(size_t i = 0, ei = paths.size(); i != ei; i++)
{
fs::path::append(paths[i],fusepath);
rv = ::unlink(fullpath.c_str());
rv = ::unlink(paths[i].c_str());
return calc_error(rv,error,errno);
}
error = calc_error(rv,error,errno);
static
int
_unlink_loop(const vector<const string*> &basepaths,
const char *fusepath)
{
int error;
error = -1;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{
error = _unlink_loop_core(basepaths[i],fusepath,error);
} }
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

53
src/utimens.cpp

@ -33,33 +33,56 @@ using std::string;
using std::vector; using std::vector;
using mergerfs::Policy; using mergerfs::Policy;
static
int
_utimens_loop_core(const string *basepath,
const char *fusepath,
const timespec ts[2],
const int error)
{
int rv;
string fullpath;
fs::path::make(basepath,fusepath,fullpath);
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;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{
error = _utimens_loop_core(basepaths[i],fusepath,ts,error);
}
return -error;
}
static static
int int
_utimens(Policy::Func::Action actionFunc, _utimens(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 timespec ts[2]) const timespec ts[2])
{ {
int rv; int rv;
int error;
vector<string> paths;
vector<const string*> basepaths;
rv = actionFunc(srcmounts,fusepath,minfreespace,paths);
rv = actionFunc(srcmounts,fusepath,minfreespace,basepaths);
if(rv == -1) if(rv == -1)
return -errno; return -errno;
error = -1;
for(size_t i = 0, ei = paths.size(); i != ei; i++)
{
fs::path::append(paths[i],fusepath);
rv = ::utimensat(0,paths[i].c_str(),ts,AT_SYMLINK_NOFOLLOW);
error = calc_error(rv,error,errno);
}
return -error;
return _utimens_loop(basepaths,fusepath,ts);
} }
namespace mergerfs namespace mergerfs

Loading…
Cancel
Save