mirror of
https://github.com/trapexit/mergerfs.git
synced 2024-11-22 11:02:35 +08:00
revert removal of 'all' policy and relevant behavior. closes #54
This commit is contained in:
parent
a359c88173
commit
c022741ffb
68
README.md
68
README.md
|
@ -49,13 +49,41 @@ In /etc/fstab it'd look like the following:
|
|||
|
||||
Filesystem calls are broken up into 3 categories: action, create, search. There are also some calls which have no policy attached due to state being kept between calls. These categories can be assigned a policy which dictates how [mergerfs](http://github.com/trapexit/mergerfs) behaves. Any policy can be assigned to a category though some aren't terribly practical. For instance: rand (Random) may be useful for **create** but could lead to very odd behavior if used for **search**.
|
||||
|
||||
#### Functional classifications ####
|
||||
| Class | FUSE calls |
|
||||
|-------|------------|
|
||||
| action | chmod, chown, link, removexattr, rename, rmdir, setxattr, truncate, unlink, utimens |
|
||||
| search | access, getattr, getxattr, listxattr, open, readlink, symlink |
|
||||
| create | create, mkdir, mknod |
|
||||
| N/A | fallocate, fgetattr, fsync, ftruncate, ioctl, read, readdir, statfs, symlink, write, release |
|
||||
#### Functional classifications ####
|
||||
| FUSE Function | Class |
|
||||
|-------------|---------|
|
||||
| access | search |
|
||||
| chmod | action |
|
||||
| chown | action |
|
||||
| create | create |
|
||||
| fallocate | N/A |
|
||||
| fgetattr | N/A |
|
||||
| fsync | N/A |
|
||||
| ftruncate | N/A |
|
||||
| getattr | search |
|
||||
| getxattr | search |
|
||||
| ioctl | N/A* |
|
||||
| link | action |
|
||||
| listxattr | search |
|
||||
| mkdir | create |
|
||||
| mknod | create |
|
||||
| open | search |
|
||||
| read | N/A |
|
||||
| readdir | N/A |
|
||||
| readlink | search |
|
||||
| release | N/A |
|
||||
| removexattr | action |
|
||||
| rename | action |
|
||||
| rmdir | action |
|
||||
| setxattr | action |
|
||||
| statfs | N/A |
|
||||
| symlink | create |
|
||||
| truncate | action |
|
||||
| unlink | action |
|
||||
| utimens | action |
|
||||
| write | N/A |
|
||||
|
||||
`ioctl` behaves differently if its acting on a directory. It'll use the `getattr` policy to find and open the directory before issuing the `ioctl`. In other cases where something may be searched (to confirm a directory exists across all source mounts) then `getattr` will be used.
|
||||
|
||||
#### Policy descriptions ####
|
||||
| Policy | Description |
|
||||
|
@ -69,7 +97,7 @@ Filesystem calls are broken up into 3 categories: action, create, search. There
|
|||
|
||||
#### readdir ####
|
||||
|
||||
[readdir](http://linux.die.net/man/3/readdir) is very different from most functions in this realm. It certainly could have it's own set of policies to tweak its behavior. At this time it provides a simple `first found` merging of directories and file found. That is: only the first file or directory found for a directory is returned.
|
||||
[readdir](http://linux.die.net/man/3/readdir) is very different from most functions in this realm. It certainly could have it's own set of policies to tweak its behavior. At this time it provides a simple `first found` merging of directories and file found. That is: only the first file or directory found for a directory is returned. Given how FUSE works though the data representing the returned entry comes from `getattr`.
|
||||
|
||||
It could be extended to offer the ability to see all files found. Perhaps concatinating `#` and a number to the name. But to really be useful you'd need to be able to access them which would complicate file lookup.
|
||||
|
||||
|
@ -133,29 +161,29 @@ Even if xattrs are disabled the [{list,get,set}xattrs](http://linux.die.net/man/
|
|||
```
|
||||
[trapexit:/tmp/mount] $ xattr -l .mergerfs
|
||||
user.mergerfs.srcmounts: /tmp/a:/tmp/b
|
||||
user.mergerfs.category.action: ff
|
||||
user.mergerfs.category.action: all
|
||||
user.mergerfs.category.create: epmfs
|
||||
user.mergerfs.category.search: ff
|
||||
user.mergerfs.func.access: ff
|
||||
user.mergerfs.func.chmod: ff
|
||||
user.mergerfs.func.chown: ff
|
||||
user.mergerfs.func.chmod: all
|
||||
user.mergerfs.func.chown: all
|
||||
user.mergerfs.func.create: epmfs
|
||||
user.mergerfs.func.getattr: ff
|
||||
user.mergerfs.func.getxattr: ff
|
||||
user.mergerfs.func.link: ff
|
||||
user.mergerfs.func.link: all
|
||||
user.mergerfs.func.listxattr: ff
|
||||
user.mergerfs.func.mkdir: epmfs
|
||||
user.mergerfs.func.mknod: epmfs
|
||||
user.mergerfs.func.open: ff
|
||||
user.mergerfs.func.readlink: ff
|
||||
user.mergerfs.func.removexattr: ff
|
||||
user.mergerfs.func.rename: ff
|
||||
user.mergerfs.func.rmdir: ff
|
||||
user.mergerfs.func.setxattr: ff
|
||||
user.mergerfs.func.symlink: ff
|
||||
user.mergerfs.func.truncate: ff
|
||||
user.mergerfs.func.unlink: ff
|
||||
user.mergerfs.func.utimens: ff
|
||||
user.mergerfs.func.removexattr: all
|
||||
user.mergerfs.func.rename: all
|
||||
user.mergerfs.func.rmdir: all
|
||||
user.mergerfs.func.setxattr: all
|
||||
user.mergerfs.func.symlink: epmfs
|
||||
user.mergerfs.func.truncate: all
|
||||
user.mergerfs.func.unlink: all
|
||||
user.mergerfs.func.utimens: all
|
||||
|
||||
[trapexit:/tmp/mount] $ xattr -p user.mergerfs.category.search .mergerfs
|
||||
ff
|
||||
|
|
|
@ -45,19 +45,19 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_access(const fs::SearchFunc searchFunc,
|
||||
_access(const fs::find::Func searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
const int mask)
|
||||
{
|
||||
int rv;
|
||||
fs::Path path;
|
||||
fs::Paths paths;
|
||||
|
||||
rv = searchFunc(srcmounts,fusepath,path);
|
||||
rv = searchFunc(srcmounts,fusepath,paths,1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
rv = ::eaccess(path.full.c_str(),mask);
|
||||
rv = ::eaccess(paths[0].full.c_str(),mask);
|
||||
|
||||
return ((rv == -1) ? -errno : 0);
|
||||
}
|
||||
|
|
|
@ -39,21 +39,29 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_chmod(const fs::SearchFunc searchFunc,
|
||||
_chmod(const fs::find::Func actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
const mode_t mode)
|
||||
{
|
||||
int rv;
|
||||
fs::Path path;
|
||||
int error;
|
||||
fs::Paths paths;
|
||||
|
||||
rv = searchFunc(srcmounts,fusepath,path);
|
||||
rv = actionFunc(srcmounts,fusepath,paths,-1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
rv = ::chmod(path.full.c_str(),mode);
|
||||
error = 0;
|
||||
for(fs::Paths::const_iterator
|
||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
||||
{
|
||||
rv = ::chmod(i->full.c_str(),mode);
|
||||
if(rv == -1)
|
||||
error = errno;
|
||||
}
|
||||
|
||||
return ((rv == -1) ? -errno : 0);
|
||||
return -error;
|
||||
}
|
||||
|
||||
namespace mergerfs
|
||||
|
|
|
@ -40,22 +40,30 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_chown(const fs::SearchFunc searchFunc,
|
||||
_chown(const fs::find::Func actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
const uid_t uid,
|
||||
const gid_t gid)
|
||||
{
|
||||
int rv;
|
||||
fs::Path path;
|
||||
int error;
|
||||
fs::Paths paths;
|
||||
|
||||
rv = searchFunc(srcmounts,fusepath,path);
|
||||
rv = actionFunc(srcmounts,fusepath,paths,-1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
rv = ::lchown(path.full.c_str(),uid,gid);
|
||||
error = 0;
|
||||
for(fs::Paths::const_iterator
|
||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
||||
{
|
||||
rv = ::lchown(i->full.c_str(),uid,gid);
|
||||
if(rv == -1)
|
||||
error = errno;
|
||||
}
|
||||
|
||||
return ((rv == -1) ? -errno : 0);
|
||||
return -error;
|
||||
}
|
||||
|
||||
namespace mergerfs
|
||||
|
|
|
@ -69,7 +69,7 @@ namespace mergerfs
|
|||
{
|
||||
pthread_rwlock_init(&srcmountslock,NULL);
|
||||
|
||||
setpolicy(Category::Enum::action,Policy::Enum::ff);
|
||||
setpolicy(Category::Enum::action,Policy::Enum::all);
|
||||
setpolicy(Category::Enum::create,Policy::Enum::epmfs);
|
||||
setpolicy(Category::Enum::search,Policy::Enum::ff);
|
||||
}
|
||||
|
|
|
@ -45,8 +45,8 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_create(const fs::SearchFunc searchFunc,
|
||||
const fs::SearchFunc createPathFunc,
|
||||
_create(const fs::find::Func searchFunc,
|
||||
const fs::find::Func createFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
const mode_t mode,
|
||||
|
@ -57,25 +57,25 @@ _create(const fs::SearchFunc searchFunc,
|
|||
int rv;
|
||||
string path;
|
||||
string dirname;
|
||||
fs::Path createpath;
|
||||
fs::Path existingpath;
|
||||
fs::Paths createpath;
|
||||
fs::Paths existingpath;
|
||||
|
||||
dirname = fs::dirname(fusepath);
|
||||
rv = searchFunc(srcmounts,dirname,existingpath);
|
||||
rv = searchFunc(srcmounts,dirname,existingpath,1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
rv = createPathFunc(srcmounts,dirname,createpath);
|
||||
rv = createFunc(srcmounts,dirname,createpath,1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
if(createpath.base != existingpath.base)
|
||||
if(createpath[0].base != existingpath[0].base)
|
||||
{
|
||||
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
||||
fs::clonepath(existingpath.base,createpath.base,dirname);
|
||||
fs::clonepath(existingpath[0].base,createpath[0].base,dirname);
|
||||
}
|
||||
|
||||
path = fs::make_path(createpath.base,fusepath);
|
||||
path = fs::make_path(createpath[0].base,fusepath);
|
||||
|
||||
fd = ::open(path.c_str(),flags,mode);
|
||||
if(fd == -1)
|
||||
|
@ -100,7 +100,7 @@ namespace mergerfs
|
|||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _create(*config.create,
|
||||
return _create(*config.getattr,
|
||||
*config.create,
|
||||
config.srcmounts,
|
||||
fusepath,
|
||||
|
|
86
src/fs.cpp
86
src/fs.cpp
|
@ -28,6 +28,7 @@
|
|||
#include <sstream>
|
||||
#include <cstdlib>
|
||||
#include <iterator>
|
||||
#include <algorithm>
|
||||
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
|
@ -519,7 +520,8 @@ namespace fs
|
|||
int
|
||||
invalid(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
Path &rv)
|
||||
Paths &rv,
|
||||
size_t count)
|
||||
{
|
||||
return (errno = EINVAL,-1);
|
||||
}
|
||||
|
@ -527,7 +529,8 @@ namespace fs
|
|||
int
|
||||
ff(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
Path &path)
|
||||
Paths &paths,
|
||||
size_t count)
|
||||
{
|
||||
errno = ENOENT;
|
||||
for(vector<string>::const_iterator
|
||||
|
@ -544,8 +547,7 @@ namespace fs
|
|||
rv = ::lstat(fullpath.c_str(),&st);
|
||||
if(rv == 0)
|
||||
{
|
||||
path.base = *iter;
|
||||
path.full = fullpath;
|
||||
paths.push_back(Path(*iter,fullpath));
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
@ -556,7 +558,8 @@ namespace fs
|
|||
int
|
||||
ffwp(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
Path &path)
|
||||
Paths &paths,
|
||||
size_t count)
|
||||
{
|
||||
Path fallback;
|
||||
|
||||
|
@ -575,8 +578,7 @@ namespace fs
|
|||
rv = ::lstat(fullpath.c_str(),&st);
|
||||
if(rv == 0)
|
||||
{
|
||||
path.base = *iter;
|
||||
path.full = fullpath;
|
||||
paths.push_back(Path(*iter,fullpath));
|
||||
return 0;
|
||||
}
|
||||
else if(errno == EACCES)
|
||||
|
@ -587,7 +589,7 @@ namespace fs
|
|||
}
|
||||
|
||||
if(!fallback.base.empty())
|
||||
return (path = fallback,0);
|
||||
return (paths.push_back(fallback),0);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -595,7 +597,8 @@ namespace fs
|
|||
int
|
||||
newest(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
Path &path)
|
||||
Paths &paths,
|
||||
size_t count)
|
||||
{
|
||||
time_t newest;
|
||||
string npath;
|
||||
|
@ -624,11 +627,7 @@ namespace fs
|
|||
}
|
||||
|
||||
if(newest)
|
||||
{
|
||||
path.base = *niter;
|
||||
path.full = npath;
|
||||
return 0;
|
||||
}
|
||||
return (paths.push_back(Path(*niter,npath)),0);
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
@ -636,7 +635,8 @@ namespace fs
|
|||
int
|
||||
mfs(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
Path &path)
|
||||
Paths &paths,
|
||||
size_t count)
|
||||
{
|
||||
fsblkcnt_t mfs;
|
||||
size_t mfsidx;
|
||||
|
@ -666,8 +666,8 @@ namespace fs
|
|||
if(mfs == 0)
|
||||
return (errno=ENOENT,-1);
|
||||
|
||||
path.base = basepaths[mfsidx];
|
||||
path.full = fs::make_path(path.base,fusepath);
|
||||
paths.push_back(Path(basepaths[mfsidx],
|
||||
fs::make_path(basepaths[mfsidx],fusepath)));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -675,7 +675,8 @@ namespace fs
|
|||
int
|
||||
epmfs(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
Path &path)
|
||||
Paths &paths,
|
||||
size_t count)
|
||||
{
|
||||
fsblkcnt_t existingmfs = 0;
|
||||
fsblkcnt_t generalmfs = 0;
|
||||
|
@ -726,21 +727,56 @@ namespace fs
|
|||
if(existingmfspath.empty())
|
||||
existingmfspath = generalmfspath;
|
||||
|
||||
path.base = existingmfspath;
|
||||
path.full = fullpath;
|
||||
paths.push_back(Path(existingmfspath,
|
||||
fullpath));
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
all(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
Paths &paths,
|
||||
size_t count)
|
||||
{
|
||||
int rv;
|
||||
struct stat st;
|
||||
string fullpath;
|
||||
|
||||
for(vector<string>::const_iterator
|
||||
iter = basepaths.begin(), eiter = basepaths.end();
|
||||
iter != eiter && count;
|
||||
++iter)
|
||||
{
|
||||
fullpath = fs::make_path(*iter,fusepath);
|
||||
|
||||
rv = ::lstat(fullpath.c_str(),&st);
|
||||
if(rv == 0)
|
||||
{
|
||||
paths.push_back(Path(*iter,fullpath));
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
return paths.empty() ? (errno=ENOENT,-1) : 0;
|
||||
}
|
||||
|
||||
int
|
||||
rand(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
Path &path)
|
||||
Paths &paths,
|
||||
size_t count)
|
||||
{
|
||||
path.base = *random_element(basepaths.begin(),
|
||||
basepaths.end());
|
||||
path.full = fs::make_path(path.base,
|
||||
fusepath);
|
||||
int rv;
|
||||
|
||||
rv = all(basepaths,fusepath,paths,-1);
|
||||
if(rv == -1)
|
||||
return -1;
|
||||
|
||||
std::random_shuffle(paths.begin(),paths.end());
|
||||
|
||||
if(paths.size() > count)
|
||||
paths.resize(count);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
30
src/fs.hpp
30
src/fs.hpp
|
@ -31,6 +31,7 @@
|
|||
|
||||
namespace fs
|
||||
{
|
||||
using std::size_t;
|
||||
using std::string;
|
||||
using std::vector;
|
||||
using std::map;
|
||||
|
@ -48,7 +49,7 @@ namespace fs
|
|||
string full;
|
||||
};
|
||||
|
||||
typedef int (*SearchFunc)(const vector<string>&,const string&,Path&);
|
||||
typedef vector<Path> Paths;
|
||||
|
||||
string dirname(const string &path);
|
||||
string basename(const string &path);
|
||||
|
@ -112,27 +113,40 @@ namespace fs
|
|||
|
||||
namespace find
|
||||
{
|
||||
typedef int (*Func)(const vector<string>&,const string&,Paths&,size_t);
|
||||
|
||||
int invalid(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
Path &path);
|
||||
Paths &path,
|
||||
size_t max);
|
||||
int all(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
Paths &path,
|
||||
size_t max);
|
||||
int ff(const vector<string> &basepaths,
|
||||
const string &fusepath,
|
||||
Path &path);
|
||||
Paths &path,
|
||||
size_t max);
|
||||
int ffwp(const vector<string> &paths,
|
||||
const string &fusepath,
|
||||
Path &path);
|
||||
Paths &path,
|
||||
size_t max);
|
||||
int newest(const vector<string> &paths,
|
||||
const string &fusepath,
|
||||
Path &path);
|
||||
Paths &path,
|
||||
size_t max);
|
||||
int mfs(const vector<string> &paths,
|
||||
const string &fusepath,
|
||||
Path &path);
|
||||
Paths &path,
|
||||
size_t max);
|
||||
int epmfs(const vector<string> &paths,
|
||||
const string &fusepath,
|
||||
Path &path);
|
||||
Paths &path,
|
||||
size_t max);
|
||||
int rand(const vector<string> &paths,
|
||||
const string &fusepath,
|
||||
Path &path);
|
||||
Paths &path,
|
||||
size_t max);
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -52,7 +52,7 @@ namespace mergerfs
|
|||
(FUSEFUNC(rename,action))
|
||||
(FUSEFUNC(rmdir,action))
|
||||
(FUSEFUNC(setxattr,action))
|
||||
(FUSEFUNC(symlink,search))
|
||||
(FUSEFUNC(symlink,create))
|
||||
(FUSEFUNC(truncate,action))
|
||||
(FUSEFUNC(unlink,action))
|
||||
(FUSEFUNC(utimens,action))
|
||||
|
|
|
@ -65,19 +65,19 @@ _getattr_controlfile(struct stat &buf)
|
|||
|
||||
static
|
||||
int
|
||||
_getattr(const fs::SearchFunc searchFunc,
|
||||
_getattr(const fs::find::Func searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
struct stat &buf)
|
||||
{
|
||||
int rv;
|
||||
fs::Path path;
|
||||
fs::Paths path;
|
||||
|
||||
rv = searchFunc(srcmounts,fusepath,path);
|
||||
rv = searchFunc(srcmounts,fusepath,path,1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
rv = ::lstat(path.full.c_str(),&buf);
|
||||
rv = ::lstat(path[0].full.c_str(),&buf);
|
||||
|
||||
return ((rv == -1) ? -errno : 0);
|
||||
}
|
||||
|
|
|
@ -190,7 +190,7 @@ _getxattr_user_mergerfs(const fs::Path &path,
|
|||
|
||||
static
|
||||
int
|
||||
_getxattr(const fs::SearchFunc searchFunc,
|
||||
_getxattr(const fs::find::Func searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
const char *attrname,
|
||||
|
@ -199,17 +199,17 @@ _getxattr(const fs::SearchFunc searchFunc,
|
|||
{
|
||||
#ifndef WITHOUT_XATTR
|
||||
int rv;
|
||||
fs::Path path;
|
||||
fs::Paths path;
|
||||
|
||||
rv = searchFunc(srcmounts,fusepath,path);
|
||||
rv = searchFunc(srcmounts,fusepath,path,1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
if(!strncmp("user.mergerfs.",attrname,sizeof("user.mergerfs.")-1))
|
||||
rv = _getxattr_user_mergerfs(path,srcmounts,fusepath,attrname,buf,count);
|
||||
rv = _getxattr_user_mergerfs(path[0],srcmounts,fusepath,attrname,buf,count);
|
||||
|
||||
if(rv == -1 && errno == ENOATTR)
|
||||
rv = ::lgetxattr(path.full.c_str(),attrname,buf,count);
|
||||
rv = ::lgetxattr(path[0].full.c_str(),attrname,buf,count);
|
||||
|
||||
return ((rv == -1) ? -errno : rv);
|
||||
#else
|
||||
|
|
|
@ -83,7 +83,7 @@ _ioctl(const int fd,
|
|||
#ifdef FUSE_IOCTL_DIR
|
||||
static
|
||||
int
|
||||
_ioctl_dir_base(const fs::SearchFunc searchFunc,
|
||||
_ioctl_dir_base(const fs::find::Func searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
const int cmd,
|
||||
|
@ -93,13 +93,13 @@ _ioctl_dir_base(const fs::SearchFunc searchFunc,
|
|||
{
|
||||
int fd;
|
||||
int rv;
|
||||
fs::Path path;
|
||||
fs::Paths path;
|
||||
|
||||
rv = searchFunc(srcmounts,fusepath,path);
|
||||
rv = searchFunc(srcmounts,fusepath,path,1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
fd = ::open(path.full.c_str(),flags);
|
||||
fd = ::open(path[0].full.c_str(),flags);
|
||||
if(fd == -1)
|
||||
return -errno;
|
||||
|
||||
|
|
68
src/link.cpp
68
src/link.cpp
|
@ -41,41 +41,64 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_link(const fs::SearchFunc searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &from,
|
||||
const string &to)
|
||||
_single_link(const fs::find::Func searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &base,
|
||||
const string &oldpath,
|
||||
const string &newpath)
|
||||
{
|
||||
int rv;
|
||||
fs::Path path;
|
||||
const string fulloldpath = fs::make_path(base,oldpath);
|
||||
const string fullnewpath = fs::make_path(base,newpath);
|
||||
|
||||
rv = searchFunc(srcmounts,from,path);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
const string pathfrom = fs::make_path(path.base,from);
|
||||
const string pathto = fs::make_path(path.base,to);
|
||||
|
||||
rv = ::link(pathfrom.c_str(),pathto.c_str());
|
||||
rv = ::link(fulloldpath.c_str(),fullnewpath.c_str());
|
||||
if(rv == -1 && errno == ENOENT)
|
||||
{
|
||||
string todir;
|
||||
fs::Path foundpath;
|
||||
string newpathdir;
|
||||
fs::Paths foundpath;
|
||||
|
||||
todir = fs::dirname(to);
|
||||
rv = fs::find::ffwp(srcmounts,todir,foundpath);
|
||||
newpathdir = fs::dirname(newpath);
|
||||
rv = searchFunc(srcmounts,newpathdir,foundpath,1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
return -1;
|
||||
|
||||
{
|
||||
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
||||
fs::clonepath(foundpath.base,path.base,todir);
|
||||
fs::clonepath(foundpath[0].base,base,newpathdir);
|
||||
}
|
||||
|
||||
rv = ::link(pathfrom.c_str(),pathto.c_str());
|
||||
rv = ::link(fulloldpath.c_str(),fullnewpath.c_str());
|
||||
}
|
||||
|
||||
return ((rv == -1) ? -errno : 0);
|
||||
return rv;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_link(const fs::find::Func searchFunc,
|
||||
const fs::find::Func actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &oldpath,
|
||||
const string &newpath)
|
||||
{
|
||||
int rv;
|
||||
int error;
|
||||
fs::Paths oldpaths;
|
||||
|
||||
rv = actionFunc(srcmounts,oldpath,oldpaths,-1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
error = 0;
|
||||
for(fs::Paths::const_iterator
|
||||
i = oldpaths.begin(), ei = oldpaths.end(); i != ei; ++i)
|
||||
{
|
||||
rv = _single_link(searchFunc,srcmounts,i->base,oldpath,newpath);
|
||||
if(rv == -1)
|
||||
error = errno;
|
||||
}
|
||||
|
||||
return -error;
|
||||
}
|
||||
|
||||
namespace mergerfs
|
||||
|
@ -91,7 +114,8 @@ namespace mergerfs
|
|||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _link(*config.link,
|
||||
return _link(*config.getattr,
|
||||
*config.link,
|
||||
config.srcmounts,
|
||||
from,
|
||||
to);
|
||||
|
|
|
@ -69,7 +69,7 @@ _listxattr_controlfile(char *list,
|
|||
|
||||
static
|
||||
int
|
||||
_listxattr(const fs::SearchFunc searchFunc,
|
||||
_listxattr(const fs::find::Func searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
char *list,
|
||||
|
@ -77,13 +77,13 @@ _listxattr(const fs::SearchFunc searchFunc,
|
|||
{
|
||||
#ifndef WITHOUT_XATTR
|
||||
int rv;
|
||||
fs::Path path;
|
||||
fs::Paths path;
|
||||
|
||||
rv = searchFunc(srcmounts,fusepath,path);
|
||||
rv = searchFunc(srcmounts,fusepath,path,1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
rv = ::llistxattr(path.full.c_str(),list,size);
|
||||
rv = ::llistxattr(path[0].full.c_str(),list,size);
|
||||
|
||||
return ((rv == -1) ? -errno : rv);
|
||||
#else
|
||||
|
|
|
@ -42,41 +42,46 @@ using std::vector;
|
|||
|
||||
static
|
||||
int
|
||||
_mkdir(const fs::SearchFunc searchFunc,
|
||||
const fs::SearchFunc createPathFunc,
|
||||
_mkdir(const fs::find::Func searchFunc,
|
||||
const fs::find::Func createFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
const mode_t mode)
|
||||
{
|
||||
int rv;
|
||||
string path;
|
||||
int error;
|
||||
string dirname;
|
||||
fs::Path createpath;
|
||||
fs::Path existingpath;
|
||||
|
||||
if(fs::path_exists(srcmounts,fusepath))
|
||||
return -EEXIST;
|
||||
string fullpath;
|
||||
fs::Paths createpaths;
|
||||
fs::Paths existingpath;
|
||||
|
||||
dirname = fs::dirname(fusepath);
|
||||
rv = searchFunc(srcmounts,dirname,existingpath);
|
||||
rv = searchFunc(srcmounts,dirname,existingpath,1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
rv = createPathFunc(srcmounts,dirname,createpath);
|
||||
rv = createFunc(srcmounts,dirname,createpaths,-1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
if(createpath.base != existingpath.base)
|
||||
error = 0;
|
||||
for(fs::Paths::const_iterator
|
||||
i = createpaths.begin(), ei = createpaths.end(); i != ei; ++i)
|
||||
{
|
||||
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
||||
fs::clonepath(existingpath.base,createpath.base,dirname);
|
||||
if(i->base != existingpath[0].base)
|
||||
{
|
||||
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
||||
fs::clonepath(existingpath[0].base,i->base,dirname);
|
||||
}
|
||||
|
||||
fullpath = fs::make_path(i->base,fusepath);
|
||||
|
||||
rv = ::mkdir(fullpath.c_str(),mode);
|
||||
if(rv == -1)
|
||||
error = errno;
|
||||
}
|
||||
|
||||
path = fs::make_path(createpath.base,fusepath);
|
||||
|
||||
rv = ::mkdir(path.c_str(),mode);
|
||||
|
||||
return ((rv == -1) ? -errno : 0);
|
||||
return -error;
|
||||
}
|
||||
|
||||
namespace mergerfs
|
||||
|
|
|
@ -43,42 +43,47 @@ using std::vector;
|
|||
|
||||
static
|
||||
int
|
||||
_mknod(const fs::SearchFunc searchFunc,
|
||||
const fs::SearchFunc createPathFunc,
|
||||
_mknod(const fs::find::Func searchFunc,
|
||||
const fs::find::Func createFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
const mode_t mode,
|
||||
const dev_t dev)
|
||||
{
|
||||
int rv;
|
||||
string path;
|
||||
int error;
|
||||
string dirname;
|
||||
fs::Path createpath;
|
||||
fs::Path existingpath;
|
||||
|
||||
if(fs::path_exists(srcmounts,fusepath))
|
||||
return -EEXIST;
|
||||
string fullpath;
|
||||
fs::Paths createpaths;
|
||||
fs::Paths existingpath;
|
||||
|
||||
dirname = fs::dirname(fusepath);
|
||||
rv = searchFunc(srcmounts,dirname,existingpath);
|
||||
rv = searchFunc(srcmounts,dirname,existingpath,1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
rv = createPathFunc(srcmounts,dirname,createpath);
|
||||
rv = createFunc(srcmounts,dirname,createpaths,-1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
if(existingpath.base != createpath.base)
|
||||
error = 0;
|
||||
for(fs::Paths::const_iterator
|
||||
i = createpaths.begin(), ei = createpaths.end(); i != ei; ++i)
|
||||
{
|
||||
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
||||
fs::clonepath(existingpath.base,createpath.base,dirname);
|
||||
if(i->base != existingpath[0].base)
|
||||
{
|
||||
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
||||
fs::clonepath(existingpath[0].base,i->base,dirname);
|
||||
}
|
||||
|
||||
fullpath = fs::make_path(i->base,fusepath);
|
||||
|
||||
rv = ::mknod(fullpath.c_str(),mode,dev);
|
||||
if(rv == -1)
|
||||
error = errno;
|
||||
}
|
||||
|
||||
path = fs::make_path(createpath.base,fusepath);
|
||||
|
||||
rv = ::mknod(path.c_str(),mode,dev);
|
||||
|
||||
return ((rv == -1) ? -errno : 0);
|
||||
return -error;
|
||||
}
|
||||
|
||||
namespace mergerfs
|
||||
|
|
10
src/open.cpp
10
src/open.cpp
|
@ -43,7 +43,7 @@ using mergerfs::FileInfo;
|
|||
|
||||
static
|
||||
int
|
||||
_open(const fs::SearchFunc searchFunc,
|
||||
_open(const fs::find::Func searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
const int flags,
|
||||
|
@ -51,17 +51,17 @@ _open(const fs::SearchFunc searchFunc,
|
|||
{
|
||||
int fd;
|
||||
int rv;
|
||||
fs::Path path;
|
||||
fs::Paths path;
|
||||
|
||||
rv = searchFunc(srcmounts,fusepath,path);
|
||||
rv = searchFunc(srcmounts,fusepath,path,1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
fd = ::open(path.full.c_str(),flags);
|
||||
fd = ::open(path[0].full.c_str(),flags);
|
||||
if(fd == -1)
|
||||
return -errno;
|
||||
|
||||
fh = (uint64_t)new FileInfo(fd,flags,path.full);
|
||||
fh = (uint64_t)new FileInfo(fd,flags,path[0].full);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -35,6 +35,7 @@ namespace mergerfs
|
|||
const std::vector<Policy> Policy::_policies_ =
|
||||
buildvector<Policy,true>
|
||||
(POLICY(invalid))
|
||||
(POLICY(all))
|
||||
(POLICY(epmfs))
|
||||
(POLICY(ff))
|
||||
(POLICY(ffwp))
|
||||
|
@ -45,6 +46,7 @@ namespace mergerfs
|
|||
const Policy * const Policy::policies = &_policies_[1];
|
||||
|
||||
const Policy &Policy::invalid = Policy::policies[Policy::Enum::invalid];
|
||||
const Policy &Policy::all = Policy::policies[Policy::Enum::all];
|
||||
const Policy &Policy::epmfs = Policy::policies[Policy::Enum::epmfs];
|
||||
const Policy &Policy::ff = Policy::policies[Policy::Enum::ff];
|
||||
const Policy &Policy::ffwp = Policy::policies[Policy::Enum::ffwp];
|
||||
|
|
|
@ -41,7 +41,8 @@ namespace mergerfs
|
|||
{
|
||||
invalid = -1,
|
||||
BEGIN = 0,
|
||||
epmfs = BEGIN,
|
||||
all = BEGIN,
|
||||
epmfs,
|
||||
ff,
|
||||
ffwp,
|
||||
mfs,
|
||||
|
@ -54,7 +55,7 @@ namespace mergerfs
|
|||
private:
|
||||
Enum::Type _enum;
|
||||
std::string _str;
|
||||
fs::SearchFunc _func;
|
||||
fs::find::Func _func;
|
||||
|
||||
public:
|
||||
Policy()
|
||||
|
@ -66,7 +67,7 @@ namespace mergerfs
|
|||
|
||||
Policy(const Enum::Type enum_,
|
||||
const std::string &str_,
|
||||
const fs::SearchFunc func_)
|
||||
const fs::find::Func func_)
|
||||
: _enum(enum_),
|
||||
_str(str_),
|
||||
_func(func_)
|
||||
|
@ -76,14 +77,14 @@ namespace mergerfs
|
|||
public:
|
||||
operator const Enum::Type() const { return _enum; }
|
||||
operator const std::string&() const { return _str; }
|
||||
operator const fs::SearchFunc() const { return _func; }
|
||||
operator const fs::find::Func() const { return _func; }
|
||||
operator const Policy*() const { return this; }
|
||||
|
||||
bool operator==(const Enum::Type enum_) const
|
||||
{ return _enum == enum_; }
|
||||
bool operator==(const std::string &str_) const
|
||||
{ return _str == str_; }
|
||||
bool operator==(const fs::SearchFunc func_) const
|
||||
bool operator==(const fs::find::Func func_) const
|
||||
{ return _func == func_; }
|
||||
|
||||
bool operator!=(const Policy &r) const
|
||||
|
@ -100,6 +101,7 @@ namespace mergerfs
|
|||
static const std::vector<Policy> _policies_;
|
||||
static const Policy * const policies;
|
||||
static const Policy &invalid;
|
||||
static const Policy &all;
|
||||
static const Policy &epmfs;
|
||||
static const Policy &ff;
|
||||
static const Policy &ffwp;
|
||||
|
|
|
@ -41,20 +41,20 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_readlink(const fs::SearchFunc searchFunc,
|
||||
_readlink(const fs::find::Func searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
char *buf,
|
||||
const size_t size)
|
||||
{
|
||||
int rv;
|
||||
fs::Path path;
|
||||
fs::Paths path;
|
||||
|
||||
rv = searchFunc(srcmounts,fusepath,path);
|
||||
rv = searchFunc(srcmounts,fusepath,path,1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
rv = ::readlink(path.full.c_str(),buf,size);
|
||||
rv = ::readlink(path[0].full.c_str(),buf,size);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
|
|
|
@ -41,22 +41,30 @@ using std::vector;
|
|||
|
||||
static
|
||||
int
|
||||
_removexattr(const fs::SearchFunc searchFunc,
|
||||
_removexattr(const fs::find::Func actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
const char *attrname)
|
||||
{
|
||||
#ifndef WITHOUT_XATTR
|
||||
int rv;
|
||||
fs::Path path;
|
||||
int error;
|
||||
fs::Paths paths;
|
||||
|
||||
rv = searchFunc(srcmounts,fusepath,path);
|
||||
rv = actionFunc(srcmounts,fusepath,paths,-1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
rv = ::lremovexattr(path.full.c_str(),attrname);
|
||||
error = 0;
|
||||
for(fs::Paths::const_iterator
|
||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
||||
{
|
||||
rv = ::lremovexattr(i->full.c_str(),attrname);
|
||||
if(rv == -1)
|
||||
error = errno;
|
||||
}
|
||||
|
||||
return ((rv == -1) ? -errno : 0);
|
||||
return -error;
|
||||
#else
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
|
|
|
@ -41,26 +41,62 @@ using std::vector;
|
|||
|
||||
static
|
||||
int
|
||||
_rename(const fs::SearchFunc searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &from,
|
||||
const string &to)
|
||||
_single_rename(const fs::find::Func searchFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const fs::Path &oldpath,
|
||||
const string &newpath)
|
||||
{
|
||||
int rv;
|
||||
string pathto;
|
||||
fs::Path pathfrom;
|
||||
const string fullnewpath = fs::make_path(oldpath.base,newpath);
|
||||
|
||||
rv = searchFunc(srcmounts,from,pathfrom);
|
||||
rv = ::rename(oldpath.full.c_str(),fullnewpath.c_str());
|
||||
if(rv == -1 && errno == ENOENT)
|
||||
{
|
||||
string dirname;
|
||||
fs::Paths newpathdir;
|
||||
|
||||
dirname = fs::dirname(newpath);
|
||||
rv = searchFunc(srcmounts,dirname,newpathdir,1);
|
||||
if(rv == -1)
|
||||
return -1;
|
||||
|
||||
{
|
||||
const mergerfs::ugid::SetResetGuard ugid(0,0);
|
||||
fs::clonepath(newpathdir[0].base,oldpath.base,dirname);
|
||||
}
|
||||
|
||||
rv = ::rename(oldpath.full.c_str(),fullnewpath.c_str());
|
||||
}
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
static
|
||||
int
|
||||
_rename(const fs::find::Func searchFunc,
|
||||
const fs::find::Func actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &oldpath,
|
||||
const string &newpath)
|
||||
{
|
||||
int rv;
|
||||
int error;
|
||||
fs::Paths oldpaths;
|
||||
|
||||
rv = actionFunc(srcmounts,oldpath,oldpaths,-1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
pathto = fs::make_path(pathfrom.base,to);
|
||||
error = 0;
|
||||
for(fs::Paths::const_iterator
|
||||
i = oldpaths.begin(), ei = oldpaths.end(); i != ei; ++i)
|
||||
{
|
||||
rv = _single_rename(searchFunc,srcmounts,*i,newpath);
|
||||
if(rv == -1)
|
||||
error = errno;
|
||||
}
|
||||
|
||||
rv = ::rename(pathfrom.full.c_str(),pathto.c_str());
|
||||
if(rv == -1 && errno == ENOENT)
|
||||
return -EXDEV;
|
||||
|
||||
return ((rv == -1) ? -errno : 0);
|
||||
return -error;
|
||||
}
|
||||
|
||||
namespace mergerfs
|
||||
|
@ -68,18 +104,19 @@ namespace mergerfs
|
|||
namespace rename
|
||||
{
|
||||
int
|
||||
rename(const char *from,
|
||||
const char *to)
|
||||
rename(const char *oldpath,
|
||||
const char *newpath)
|
||||
{
|
||||
const struct fuse_context *fc = fuse_get_context();
|
||||
const config::Config &config = config::get();
|
||||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _rename(*config.rename,
|
||||
return _rename(*config.getattr,
|
||||
*config.rename,
|
||||
config.srcmounts,
|
||||
from,
|
||||
to);
|
||||
oldpath,
|
||||
newpath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,20 +40,28 @@ using mergerfs::Policy;
|
|||
|
||||
static
|
||||
int
|
||||
_rmdir(const fs::SearchFunc searchFunc,
|
||||
_rmdir(const fs::find::Func actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath)
|
||||
{
|
||||
int rv;
|
||||
fs::Path path;
|
||||
int error;
|
||||
fs::Paths paths;
|
||||
|
||||
rv = searchFunc(srcmounts,fusepath,path);
|
||||
rv = actionFunc(srcmounts,fusepath,paths,-1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
rv = ::rmdir(path.full.c_str());
|
||||
error = 0;
|
||||
for(fs::Paths::const_iterator
|
||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
||||
{
|
||||
rv = ::rmdir(i->full.c_str());
|
||||
if(rv == -1)
|
||||
error = errno;
|
||||
}
|
||||
|
||||
return ((rv == -1) ? -errno : 0);
|
||||
return -error;
|
||||
}
|
||||
|
||||
namespace mergerfs
|
||||
|
|
|
@ -256,7 +256,7 @@ _setxattr_controlfile(config::Config &config,
|
|||
|
||||
static
|
||||
int
|
||||
_setxattr(const fs::SearchFunc searchFunc,
|
||||
_setxattr(const fs::find::Func actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
const char *attrname,
|
||||
|
@ -266,15 +266,23 @@ _setxattr(const fs::SearchFunc searchFunc,
|
|||
{
|
||||
#ifndef WITHOUT_XATTR
|
||||
int rv;
|
||||
fs::Path path;
|
||||
int error;
|
||||
fs::Paths paths;
|
||||
|
||||
rv = searchFunc(srcmounts,fusepath,path);
|
||||
rv = actionFunc(srcmounts,fusepath,paths,-1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
rv = ::lsetxattr(path.full.c_str(),attrname,attrval,attrvalsize,flags);
|
||||
error = 0;
|
||||
for(fs::Paths::const_iterator
|
||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
||||
{
|
||||
rv = ::lsetxattr(i->full.c_str(),attrname,attrval,attrvalsize,flags);
|
||||
if(rv == -1)
|
||||
error = errno;
|
||||
}
|
||||
|
||||
return ((rv == -1) ? -errno : 0);
|
||||
return -error;
|
||||
#else
|
||||
return -ENOTSUP;
|
||||
#endif
|
||||
|
|
|
@ -39,22 +39,33 @@ using std::vector;
|
|||
|
||||
static
|
||||
int
|
||||
_symlink(const vector<string> &srcmounts,
|
||||
const string &from,
|
||||
const string &to)
|
||||
_symlink(const fs::find::Func createFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &oldpath,
|
||||
const string &newpath)
|
||||
{
|
||||
int rv;
|
||||
fs::Path path;
|
||||
int error;
|
||||
string newpathdir;
|
||||
fs::Paths newpathdirs;
|
||||
|
||||
rv = fs::find::ff(srcmounts,fs::dirname(to),path);
|
||||
newpathdir = fs::dirname(newpath);
|
||||
rv = createFunc(srcmounts,newpathdir,newpathdirs,-1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
path.full = fs::make_path(path.base,to);
|
||||
error = 0;
|
||||
for(fs::Paths::iterator
|
||||
i = newpathdirs.begin(), ei = newpathdirs.end(); i != ei; ++i)
|
||||
{
|
||||
i->full = fs::make_path(i->base,newpath);
|
||||
|
||||
rv = symlink(from.c_str(),path.full.c_str());
|
||||
rv = symlink(oldpath.c_str(),i->full.c_str());
|
||||
if(rv == -1)
|
||||
error = errno;
|
||||
}
|
||||
|
||||
return ((rv == -1) ? -errno : 0);
|
||||
return -error;
|
||||
}
|
||||
|
||||
namespace mergerfs
|
||||
|
@ -70,7 +81,8 @@ namespace mergerfs
|
|||
const ugid::SetResetGuard ugid(fc->uid,fc->gid);
|
||||
const rwlock::ReadGuard readlock(&config.srcmountslock);
|
||||
|
||||
return _symlink(config.srcmounts,
|
||||
return _symlink(*config.symlink,
|
||||
config.srcmounts,
|
||||
oldpath,
|
||||
newpath);
|
||||
}
|
||||
|
|
|
@ -41,21 +41,29 @@ using std::vector;
|
|||
|
||||
static
|
||||
int
|
||||
_truncate(const fs::SearchFunc searchFunc,
|
||||
_truncate(const fs::find::Func actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
const off_t size)
|
||||
{
|
||||
int rv;
|
||||
fs::Path path;
|
||||
int error;
|
||||
fs::Paths paths;
|
||||
|
||||
rv = searchFunc(srcmounts,fusepath,path);
|
||||
rv = actionFunc(srcmounts,fusepath,paths,-1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
rv = ::truncate(path.full.c_str(),size);
|
||||
error = 0;
|
||||
for(fs::Paths::const_iterator
|
||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
||||
{
|
||||
rv = ::truncate(i->full.c_str(),size);
|
||||
if(rv == -1)
|
||||
error = errno;
|
||||
}
|
||||
|
||||
return ((rv == -1) ? -errno : 0);
|
||||
return -error;
|
||||
}
|
||||
|
||||
namespace mergerfs
|
||||
|
|
|
@ -40,20 +40,28 @@ using std::vector;
|
|||
|
||||
static
|
||||
int
|
||||
_unlink(const fs::SearchFunc searchFunc,
|
||||
_unlink(const fs::find::Func actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath)
|
||||
{
|
||||
int rv;
|
||||
fs::Path path;
|
||||
int error;
|
||||
fs::Paths paths;
|
||||
|
||||
rv = searchFunc(srcmounts,fusepath,path);
|
||||
rv = actionFunc(srcmounts,fusepath,paths,-1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
rv = ::unlink(path.full.c_str());
|
||||
error = 0;
|
||||
for(fs::Paths::const_iterator
|
||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
||||
{
|
||||
rv = ::unlink(i->full.c_str());
|
||||
if(rv == -1)
|
||||
error = errno;
|
||||
}
|
||||
|
||||
return ((rv == -1) ? -errno : 0);
|
||||
return -error;
|
||||
}
|
||||
|
||||
namespace mergerfs
|
||||
|
|
|
@ -41,21 +41,29 @@ using std::vector;
|
|||
|
||||
static
|
||||
int
|
||||
_utimens(const fs::SearchFunc searchFunc,
|
||||
_utimens(const fs::find::Func actionFunc,
|
||||
const vector<string> &srcmounts,
|
||||
const string &fusepath,
|
||||
const struct timespec ts[2])
|
||||
{
|
||||
int rv;
|
||||
fs::Path path;
|
||||
int error;
|
||||
fs::Paths paths;
|
||||
|
||||
rv = searchFunc(srcmounts,fusepath,path);
|
||||
rv = actionFunc(srcmounts,fusepath,paths,-1);
|
||||
if(rv == -1)
|
||||
return -errno;
|
||||
|
||||
rv = ::utimensat(0,path.full.c_str(),ts,AT_SYMLINK_NOFOLLOW);
|
||||
error = 0;
|
||||
for(fs::Paths::const_iterator
|
||||
i = paths.begin(), ei = paths.end(); i != ei; ++i)
|
||||
{
|
||||
rv = ::utimensat(0,i->full.c_str(),ts,AT_SYMLINK_NOFOLLOW);
|
||||
if(rv == -1)
|
||||
error = errno;
|
||||
}
|
||||
|
||||
return ((rv == -1) ? -errno : 0);
|
||||
return -error;
|
||||
}
|
||||
|
||||
namespace mergerfs
|
||||
|
|
Loading…
Reference in New Issue
Block a user