From d30cae217b9c1e02c2c144a810b1448722761a19 Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Sat, 7 Feb 2015 18:27:47 -0500 Subject: [PATCH] add user.mergerfs.allpaths and user.mergerfs.relpath to getxattr --- README.md | 11 +++++++++-- src/fs.cpp | 21 +++++++++++++++++++++ src/fs.hpp | 4 ++++ src/getxattr.cpp | 49 +++++++++++++++++++++++++++++++++++++++++++----- 4 files changed, 78 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 9b5b1afb..d968191e 100644 --- a/README.md +++ b/README.md @@ -148,8 +148,10 @@ For **user.mergerfs.srcmounts** there are several instructions available for man While they won't show up when using [listxattr](http://linux.die.net/man/2/listxattr) mergerfs offers a number of special xattrs to query information about the files served. To access the values you will need to issue a [getxattr](http://linux.die.net/man/2/getxattr) for one of the following: -* user.mergerfs.basepath : gives you the base mount point for the file given the current search policy -* user.mergerfs.fullpath : gives you the full path of the original file given the search policy +* user.mergerfs.basepath: the base mount point for the file given the current search policy +* user.mergerfs.relpath: the relative path of the file from the perspective of the mount point +* user.mergerfs.fullpath: the full path of the original file given the search policy +* user.mergerfs.allpaths: a NUL ('\0') separated list of full paths to all files found ``` [trapexit:/tmp/mount] $ ls @@ -158,4 +160,9 @@ A B C /mnt/a/full/path/to/A [trapexit:/tmp/mount] $ xattr -p user.mergerfs.basepath A /mnt/a +[trapexit:/tmp/mount] $ xattr -p user.mergerfs.relpath A +/full/path/to/A +[trapexit:/tmp/mount] $ xattr -p user.mergerfs.allpaths A | tr '\0' '\n' +/mnt/a/full/path/to/A +/mnt/b/full/path/to/A ``` diff --git a/src/fs.cpp b/src/fs.cpp index 76813f88..93f18b7c 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -162,6 +162,27 @@ namespace fs fusepath); } + void + findallfiles(const vector &srcmounts, + const string &fusepath, + vector &paths) + { + for(vector::const_iterator + iter = srcmounts.begin(), eiter = srcmounts.end(); + iter != eiter; + ++iter) + { + int rv; + string fullpath; + struct stat st; + + fullpath = fs::make_path(*iter,fusepath); + rv = ::lstat(fullpath.c_str(),&st); + if(rv == 0) + paths.push_back(fullpath); + } + } + int listxattr(const string &path, vector &attrs) diff --git a/src/fs.hpp b/src/fs.hpp index e87a0ff6..588b960a 100644 --- a/src/fs.hpp +++ b/src/fs.hpp @@ -64,6 +64,10 @@ namespace fs bool path_exists(const vector &srcmounts, const string &fusepath); + void findallfiles(const vector &srcmounts, + const string &fusepath, + vector &paths); + int clonepath(const string &srcfrom, const string &srcto, const string &relative); diff --git a/src/getxattr.cpp b/src/getxattr.cpp index 5e1c4dfd..a67529c4 100644 --- a/src/getxattr.cpp +++ b/src/getxattr.cpp @@ -94,6 +94,46 @@ _getxattr_from_string(char *destbuf, return srcbufsize; } +static +int +_getxattr_user_mergerfs_allpaths(const vector &srcmounts, + const string &fusepath, + char *buf, + const size_t count) +{ + string concated; + vector paths; + + fs::findallfiles(srcmounts,fusepath,paths); + + concated = str::join(paths,'\0'); + + return ::_getxattr_from_string(buf,count,concated); +} + +static +int +_getxattr_user_mergerfs(const fs::Path &path, + const vector &srcmounts, + const string &fusepath, + const char *attrname, + char *buf, + const size_t count) +{ + const char *attrbasename = &attrname[sizeof("user.mergerfs")]; + + if(!strcmp(attrbasename,"basepath")) + return ::_getxattr_from_string(buf,count,path.base); + else if(!strcmp(attrbasename,"fullpath")) + return ::_getxattr_from_string(buf,count,path.full); + else if(!strcmp(attrbasename,"relpath")) + return ::_getxattr_from_string(buf,count,fusepath); + else if(!strcmp(attrbasename,"allpaths")) + return ::_getxattr_user_mergerfs_allpaths(srcmounts,fusepath,buf,count); + + return (errno=ENOATTR,-1); +} + static int _getxattr(const fs::SearchFunc searchFunc, @@ -111,11 +151,10 @@ _getxattr(const fs::SearchFunc searchFunc, if(rv == -1) return -errno; - if(!strcmp(attrname,"user.mergerfs.basepath")) - rv = ::_getxattr_from_string(buf,count,path.base); - else if(!strcmp(attrname,"user.mergerfs.fullpath")) - rv = ::_getxattr_from_string(buf,count,path.full); - else + if(!strncmp("user.mergerfs.",attrname,sizeof("user.mergerfs.")-1)) + rv = _getxattr_user_mergerfs(path,srcmounts,fusepath,attrname,buf,count); + + if(rv == -1 && errno == ENOATTR) rv = ::lgetxattr(path.full.c_str(),attrname,buf,count); return ((rv == -1) ? -errno : rv);