Browse Source

general code cleanup

pull/575/head
Antonio SJ Musumeci 6 years ago
parent
commit
9d9ee7b71d
  1. 1
      src/buildvector.hpp
  2. 105
      src/chmod.cpp
  3. 111
      src/chown.cpp
  4. 177
      src/config.cpp
  5. 209
      src/config.hpp
  6. 30
      src/fallocate.hpp
  7. 28
      src/flock.hpp
  8. 8
      src/fs.cpp
  9. 30
      src/fs.hpp
  10. 2
      src/fs_acl.hpp
  11. 10
      src/fs_attr.hpp
  12. 24
      src/fs_base_access.hpp
  13. 42
      src/fs_base_chmod.hpp
  14. 70
      src/fs_base_chown.hpp
  15. 4
      src/fs_base_close.hpp
  16. 4
      src/fs_base_closedir.hpp
  17. 4
      src/fs_base_dirfd.hpp
  18. 4
      src/fs_base_dup.hpp
  19. 18
      src/fs_base_fadvise.hpp
  20. 8
      src/fs_base_fallocate.hpp
  21. 6
      src/fs_base_flock.hpp
  22. 8
      src/fs_base_fsync.hpp
  23. 6
      src/fs_base_ftruncate.hpp
  24. 8
      src/fs_base_futimesat.hpp
  25. 4
      src/fs_base_getxattr.hpp
  26. 7
      src/fs_base_link.hpp
  27. 4
      src/fs_base_listxattr.hpp
  28. 8
      src/fs_base_lseek.hpp
  29. 6
      src/fs_base_mkdir.hpp
  30. 8
      src/fs_base_mknod.hpp
  31. 14
      src/fs_base_mkstemp.hpp
  32. 4
      src/fs_base_open.hpp
  33. 4
      src/fs_base_opendir.hpp
  34. 18
      src/fs_base_read.hpp
  35. 4
      src/fs_base_readdir.hpp
  36. 8
      src/fs_base_readlink.hpp
  37. 10
      src/fs_base_realpath.hpp
  38. 12
      src/fs_base_remove.hpp
  39. 10
      src/fs_base_removexattr.hpp
  40. 12
      src/fs_base_rmdir.hpp
  41. 4
      src/fs_base_setxattr.hpp
  42. 57
      src/fs_base_stat.hpp
  43. 4
      src/fs_base_statvfs.hpp
  44. 24
      src/fs_base_symlink.hpp
  45. 15
      src/fs_base_truncate.hpp
  46. 26
      src/fs_base_utime.hpp
  47. 132
      src/fs_base_utime_generic.hpp
  48. 2
      src/fs_clonefile.cpp
  49. 22
      src/fs_clonepath.cpp
  50. 2
      src/fs_copyfile.cpp
  51. 2
      src/fs_cow.cpp
  52. 4
      src/fs_devid.hpp
  53. 8
      src/fs_exists.hpp
  54. 7
      src/fs_glob.hpp
  55. 15
      src/fs_inode.hpp
  56. 2
      src/fs_movefile.cpp
  57. 41
      src/fs_path.hpp
  58. 4
      src/fs_statvfs_cache.cpp
  59. 56
      src/fuse_access.cpp
  60. 10
      src/fuse_access.hpp
  61. 105
      src/fuse_chmod.cpp
  62. 10
      src/fuse_chmod.hpp
  63. 110
      src/fuse_chown.cpp
  64. 12
      src/fuse_chown.hpp
  65. 62
      src/fuse_create.cpp
  66. 14
      src/fuse_create.hpp
  67. 9
      src/fuse_destroy.cpp
  68. 9
      src/fuse_destroy.hpp
  69. 54
      src/fuse_fallocate.cpp
  70. 27
      src/fuse_fallocate.hpp
  71. 47
      src/fuse_fgetattr.cpp
  72. 14
      src/fuse_fgetattr.hpp
  73. 40
      src/fuse_flock.cpp
  74. 12
      src/fuse_flock.hpp
  75. 44
      src/fuse_flush.cpp
  76. 26
      src/fuse_flush.hpp
  77. 48
      src/fuse_fsync.cpp
  78. 12
      src/fuse_fsync.hpp
  79. 46
      src/fuse_fsyncdir.cpp
  80. 13
      src/fuse_fsyncdir.hpp
  81. 40
      src/fuse_ftruncate.cpp
  82. 14
      src/fuse_ftruncate.hpp
  83. 117
      src/fuse_getattr.cpp
  84. 11
      src/fuse_getattr.hpp
  85. 467
      src/fuse_getxattr.cpp
  86. 14
      src/fuse_getxattr.hpp
  87. 27
      src/fuse_init.cpp
  88. 11
      src/fuse_init.hpp
  89. 49
      src/fuse_ioctl.cpp
  90. 16
      src/fuse_ioctl.hpp
  91. 249
      src/fuse_link.cpp
  92. 24
      src/fuse_link.hpp
  93. 146
      src/fuse_listxattr.cpp
  94. 25
      src/fuse_listxattr.hpp
  95. 149
      src/fuse_mkdir.cpp
  96. 24
      src/fuse_mkdir.hpp
  97. 151
      src/fuse_mknod.cpp
  98. 26
      src/fuse_mknod.hpp
  99. 45
      src/fuse_open.cpp
  100. 26
      src/fuse_open.hpp

1
src/buildvector.hpp

@ -17,6 +17,7 @@
#pragma once #pragma once
#include <algorithm> #include <algorithm>
#include <vector>
template<typename V, bool SORT = false> template<typename V, bool SORT = false>
class buildvector class buildvector

105
src/chmod.cpp

@ -1,105 +0,0 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <fuse.h>
#include <string>
#include <vector>
#include "config.hpp"
#include "errno.hpp"
#include "fs_base_chmod.hpp"
#include "fs_path.hpp"
#include "rv.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
using std::string;
using std::vector;
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 = fs::chmod(fullpath,mode);
return error::calc(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
int
_chmod(Policy::Func::Action actionFunc,
const Branches &branches_,
const uint64_t minfreespace,
const char *fusepath,
const mode_t mode)
{
int rv;
vector<const string*> basepaths;
rv = actionFunc(branches_,fusepath,minfreespace,basepaths);
if(rv == -1)
return -errno;
return _chmod_loop(basepaths,fusepath,mode);
}
namespace mergerfs
{
namespace fuse
{
int
chmod(const char *fusepath,
mode_t mode)
{
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
return _chmod(config.chmod,
config.branches,
config.minfreespace,
fusepath,
mode);
}
}
}

111
src/chown.cpp

@ -1,111 +0,0 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <fuse.h>
#include <string>
#include <vector>
#include "config.hpp"
#include "errno.hpp"
#include "fs_base_chown.hpp"
#include "fs_path.hpp"
#include "rv.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
using std::string;
using std::vector;
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 = fs::lchown(fullpath,uid,gid);
return error::calc(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
int
_chown(Policy::Func::Action actionFunc,
const Branches &branches_,
const uint64_t minfreespace,
const char *fusepath,
const uid_t uid,
const gid_t gid)
{
int rv;
vector<const string*> basepaths;
rv = actionFunc(branches_,fusepath,minfreespace,basepaths);
if(rv == -1)
return -errno;
return _chown_loop(basepaths,fusepath,uid,gid);
}
namespace mergerfs
{
namespace fuse
{
int
chown(const char *fusepath,
uid_t uid,
gid_t gid)
{
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
return _chown(config.chown,
config.branches,
config.minfreespace,
fusepath,
uid,
gid);
}
}
}

177
src/config.cpp

@ -31,95 +31,92 @@
using std::string; using std::string;
using std::vector; using std::vector;
namespace mergerfs
Config::Config()
: destmount(),
branches(),
branches_lock(),
minfreespace(MINFREESPACE_DEFAULT),
moveonenospc(false),
direct_io(false),
dropcacheonclose(false),
symlinkify(false),
symlinkify_timeout(3600),
nullrw(false),
ignorepponrename(false),
security_capability(true),
link_cow(false),
xattr(0),
statfs(StatFS::BASE),
statfs_ignore(StatFSIgnore::NONE),
POLICYINIT(access),
POLICYINIT(chmod),
POLICYINIT(chown),
POLICYINIT(create),
POLICYINIT(getattr),
POLICYINIT(getxattr),
POLICYINIT(link),
POLICYINIT(listxattr),
POLICYINIT(mkdir),
POLICYINIT(mknod),
POLICYINIT(open),
POLICYINIT(readlink),
POLICYINIT(removexattr),
POLICYINIT(rename),
POLICYINIT(rmdir),
POLICYINIT(setxattr),
POLICYINIT(symlink),
POLICYINIT(truncate),
POLICYINIT(unlink),
POLICYINIT(utimens),
controlfile("/.mergerfs")
{ {
Config::Config()
: destmount(),
branches(),
branches_lock(),
minfreespace(MINFREESPACE_DEFAULT),
moveonenospc(false),
direct_io(false),
dropcacheonclose(false),
symlinkify(false),
symlinkify_timeout(3600),
nullrw(false),
ignorepponrename(false),
security_capability(true),
link_cow(false),
xattr(0),
statfs(StatFS::BASE),
statfs_ignore(StatFSIgnore::NONE),
POLICYINIT(access),
POLICYINIT(chmod),
POLICYINIT(chown),
POLICYINIT(create),
POLICYINIT(getattr),
POLICYINIT(getxattr),
POLICYINIT(link),
POLICYINIT(listxattr),
POLICYINIT(mkdir),
POLICYINIT(mknod),
POLICYINIT(open),
POLICYINIT(readlink),
POLICYINIT(removexattr),
POLICYINIT(rename),
POLICYINIT(rmdir),
POLICYINIT(setxattr),
POLICYINIT(symlink),
POLICYINIT(truncate),
POLICYINIT(unlink),
POLICYINIT(utimens),
controlfile("/.mergerfs")
{
pthread_rwlock_init(&branches_lock,NULL);
set_category_policy("action","epall");
set_category_policy("create","epmfs");
set_category_policy("search","ff");
}
int
Config::set_func_policy(const string &fusefunc_,
const string &policy_)
{
const Policy *policy;
const FuseFunc *fusefunc;
fusefunc = FuseFunc::find(fusefunc_);
if(fusefunc == FuseFunc::invalid)
return (errno=ENODATA,-1);
policy = Policy::find(policy_);
if(policy == Policy::invalid)
return (errno=EINVAL,-1);
policies[(FuseFunc::Enum::Type)*fusefunc] = policy;
return 0;
}
int
Config::set_category_policy(const string &category_,
const string &policy_)
{
const Policy *policy;
const Category *category;
category = Category::find(category_);
if(category == Category::invalid)
return (errno=ENODATA,-1);
policy = Policy::find(policy_);
if(policy == Policy::invalid)
return (errno=EINVAL,-1);
for(int i = 0; i < FuseFunc::Enum::END; i++)
{
if(FuseFunc::fusefuncs[i] == (Category::Enum::Type)*category)
policies[(FuseFunc::Enum::Type)FuseFunc::fusefuncs[i]] = policy;
}
return 0;
}
pthread_rwlock_init(&branches_lock,NULL);
set_category_policy("action","epall");
set_category_policy("create","epmfs");
set_category_policy("search","ff");
}
int
Config::set_func_policy(const string &fusefunc_,
const string &policy_)
{
const Policy *policy;
const FuseFunc *fusefunc;
fusefunc = FuseFunc::find(fusefunc_);
if(fusefunc == FuseFunc::invalid)
return (errno=ENODATA,-1);
policy = Policy::find(policy_);
if(policy == Policy::invalid)
return (errno=EINVAL,-1);
policies[(FuseFunc::Enum::Type)*fusefunc] = policy;
return 0;
}
int
Config::set_category_policy(const string &category_,
const string &policy_)
{
const Policy *policy;
const Category *category;
category = Category::find(category_);
if(category == Category::invalid)
return (errno=ENODATA,-1);
policy = Policy::find(policy_);
if(policy == Policy::invalid)
return (errno=EINVAL,-1);
for(int i = 0; i < FuseFunc::Enum::END; i++)
{
if(FuseFunc::fusefuncs[i] == (Category::Enum::Type)*category)
policies[(FuseFunc::Enum::Type)FuseFunc::fusefuncs[i]] = policy;
}
return 0;
} }

209
src/config.hpp

@ -23,115 +23,112 @@
#include <fuse.h> #include <fuse.h>
#include <stdint.h>
#include <sys/stat.h>
#include <string> #include <string>
#include <vector> #include <vector>
namespace mergerfs
#include <stdint.h>
#include <sys/stat.h>
class Config
{ {
class Config
public:
struct StatFS
{
enum Enum
{
BASE,
FULL
};
};
struct StatFSIgnore
{ {
public:
struct StatFS
{
enum Enum
{
BASE,
FULL
};
};
struct StatFSIgnore
{
enum Enum
{
NONE,
RO,
NC
};
};
public:
Config();
public:
int set_func_policy(const std::string &fusefunc_,
const std::string &policy_);
int set_category_policy(const std::string &category_,
const std::string &policy_);
public:
std::string destmount;
Branches branches;
mutable pthread_rwlock_t branches_lock;
uint64_t minfreespace;
bool moveonenospc;
bool direct_io;
bool dropcacheonclose;
bool symlinkify;
time_t symlinkify_timeout;
bool nullrw;
bool ignorepponrename;
bool security_capability;
bool link_cow;
int xattr;
StatFS::Enum statfs;
StatFSIgnore::Enum statfs_ignore;
public:
const Policy *policies[FuseFunc::Enum::END];
const Policy *&access;
const Policy *&chmod;
const Policy *&chown;
const Policy *&create;
const Policy *&getattr;
const Policy *&getxattr;
const Policy *&link;
const Policy *&listxattr;
const Policy *&mkdir;
const Policy *&mknod;
const Policy *&open;
const Policy *&readlink;
const Policy *&removexattr;
const Policy *&rename;
const Policy *&rmdir;
const Policy *&setxattr;
const Policy *&symlink;
const Policy *&truncate;
const Policy *&unlink;
const Policy *&utimens;
public:
mutable PolicyCache open_cache;
public:
const std::string controlfile;
public:
static
const
Config &
get(void)
{
const fuse_context *fc = fuse_get_context();
return get(fc);
}
static
const Config &
get(const fuse_context *fc)
{
return *((Config*)fc->private_data);
}
static
Config &
get_writable(void)
{
return (*((Config*)fuse_get_context()->private_data));
}
enum Enum
{
NONE,
RO,
NC
};
}; };
}
public:
Config();
public:
int set_func_policy(const std::string &fusefunc_,
const std::string &policy_);
int set_category_policy(const std::string &category_,
const std::string &policy_);
public:
std::string destmount;
Branches branches;
mutable pthread_rwlock_t branches_lock;
uint64_t minfreespace;
bool moveonenospc;
bool direct_io;
bool dropcacheonclose;
bool symlinkify;
time_t symlinkify_timeout;
bool nullrw;
bool ignorepponrename;
bool security_capability;
bool link_cow;
int xattr;
StatFS::Enum statfs;
StatFSIgnore::Enum statfs_ignore;
public:
const Policy *policies[FuseFunc::Enum::END];
const Policy *&access;
const Policy *&chmod;
const Policy *&chown;
const Policy *&create;
const Policy *&getattr;
const Policy *&getxattr;
const Policy *&link;
const Policy *&listxattr;
const Policy *&mkdir;
const Policy *&mknod;
const Policy *&open;
const Policy *&readlink;
const Policy *&removexattr;
const Policy *&rename;
const Policy *&rmdir;
const Policy *&setxattr;
const Policy *&symlink;
const Policy *&truncate;
const Policy *&unlink;
const Policy *&utimens;
public:
mutable PolicyCache open_cache;
public:
const std::string controlfile;
public:
static
const
Config &
get(void)
{
const fuse_context *fc = fuse_get_context();
return get(fc);
}
static
const Config &
get(const fuse_context *fc)
{
return *((Config*)fc->private_data);
}
static
Config &
get_writable(void)
{
return (*((Config*)fuse_get_context()->private_data));
}
};

30
src/fallocate.hpp

@ -1,30 +0,0 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
namespace mergerfs
{
namespace fuse
{
int
fallocate(const char *fusepath,
int mode,
off_t offset,
off_t len,
fuse_file_info *fi);
}
}

28
src/flock.hpp

@ -1,28 +0,0 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
namespace mergerfs
{
namespace fuse
{
int
flock(const char *fusepath,
fuse_file_info *ffi,
int op);
}
}

8
src/fs.cpp

@ -46,7 +46,7 @@ namespace fs
for(size_t i = 0, ei = basepaths.size(); i != ei; i++) for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
fs::path::make(&basepaths[i],fusepath,fullpath);
fullpath = fs::path::make(basepaths[i],fusepath);
if(!fs::exists(fullpath)) if(!fs::exists(fullpath))
continue; continue;
@ -66,16 +66,16 @@ namespace fs
string fullpath; string fullpath;
struct stat st; struct stat st;
rv = fs::fstat(fd,st);
rv = fs::fstat(fd,&st);
if(rv == -1) if(rv == -1)
return -1; return -1;
dev = st.st_dev; dev = st.st_dev;
for(size_t i = 0, ei = basepaths.size(); i != ei; i++) for(size_t i = 0, ei = basepaths.size(); i != ei; i++)
{ {
fs::path::make(&basepaths[i],fusepath,fullpath);
fullpath = fs::path::make(basepaths[i],fusepath);
rv = fs::lstat(fullpath,st);
rv = fs::lstat(fullpath,&st);
if(rv == -1) if(rv == -1)
continue; continue;

30
src/fs.hpp

@ -27,22 +27,22 @@ namespace fs
using std::string; using std::string;
using std::vector; using std::vector;
void findallfiles(const vector<string> &basepaths,
const char *fusepath,
vector<string> &paths);
void findallfiles(const vector<string> &basepaths_,
const char *fusepath_,
vector<string> &paths_);
int findonfs(const vector<string> &basepaths,
const string &fusepath,
const int fd,
string &basepath);
int findonfs(const vector<string> &basepaths_,
const string &fusepath_,
const int fd_,
string &basepath_);
void realpathize(vector<string> &strs);
void realpathize(vector<string> &strs_);
int getfl(const int fd);
int setfl(const int fd,
const mode_t mode);
int getfl(const int fd_);
int setfl(const int fd_,
const mode_t mode_);
int mfs(const vector<string> &srcs,
const uint64_t minfreespace,
string &path);
};
int mfs(const vector<string> &srcs_,
const uint64_t minfreespace_,
string &path_);
}

2
src/fs_acl.hpp

@ -25,6 +25,6 @@ namespace fs
namespace acl namespace acl
{ {
bool bool
dir_has_defaults(const std::string &fullpath);
dir_has_defaults(const std::string &fullpath_);
} }
} }

10
src/fs_attr.hpp

@ -22,11 +22,9 @@ namespace fs
{ {
namespace attr namespace attr
{ {
using std::string;
int copy(const int fdin,
const int fdout);
int copy(const string &from,
const string &to);
int copy(const int fdin_,
const int fdout_);
int copy(const std::string &from_,
const std::string &to_);
} }
} }

24
src/fs_base_access.hpp

@ -28,30 +28,30 @@ namespace fs
static static
inline inline
int int
access(const int dirfd,
const std::string &path,
const int mode,
const int flags)
access(const int dirfd_,
const std::string &path_,
const int mode_,
const int flags_)
{ {
return ::faccessat(dirfd,path.c_str(),mode,flags);
return ::faccessat(dirfd_,path_.c_str(),mode_,flags_);
} }
static static
inline inline
int int
access(const std::string &path,
const int mode,
const int flags)
access(const std::string &path_,
const int mode_,
const int flags_)
{ {
return fs::access(AT_FDCWD,path,mode,flags);
return fs::access(AT_FDCWD,path_,mode_,flags_);
} }
static static
inline inline
int int
eaccess(const std::string &path,
const int mode)
eaccess(const std::string &path_,
const int mode_)
{ {
return fs::access(path,mode,AT_EACCESS);
return fs::access(path_,mode_,AT_EACCESS);
} }
} }

42
src/fs_base_chmod.hpp

@ -18,10 +18,10 @@
#pragma once #pragma once
#include <sys/stat.h>
#include "fs_base_stat.hpp" #include "fs_base_stat.hpp"
#include <sys/stat.h>
#define MODE_BITS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO) #define MODE_BITS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO)
namespace fs namespace fs
@ -29,50 +29,50 @@ namespace fs
static static
inline inline
int int
chmod(const std::string &path,
const mode_t mode)
chmod(const std::string &path_,
const mode_t mode_)
{ {
return ::chmod(path.c_str(),mode);
return ::chmod(path_.c_str(),mode_);
} }
static static
inline inline
int int
fchmod(const int fd,
const mode_t mode)
fchmod(const int fd_,
const mode_t mode_)
{ {
return ::fchmod(fd,mode);
return ::fchmod(fd_,mode_);
} }
static static
inline inline
int int
fchmod(const int fd,
const struct stat &st)
fchmod(const int fd_,
const struct stat &st_)
{ {
return ::fchmod(fd,st.st_mode);
return ::fchmod(fd_,st_.st_mode);
} }
static static
inline inline
int int
chmod_check_on_error(const std::string &path,
const mode_t mode)
chmod_check_on_error(const std::string &path_,
const mode_t mode_)
{ {
int rv; int rv;
rv = fs::chmod(path,mode);
rv = fs::chmod(path_,mode_);
if(rv == -1) if(rv == -1)
{ {
int error; int error;
struct stat st; struct stat st;
error = errno; error = errno;
rv = fs::stat(path,st);
rv = fs::stat(path_,&st);
if(rv == -1) if(rv == -1)
return -1; return -1;
if((st.st_mode & MODE_BITS) != (mode & MODE_BITS))
if((st.st_mode & MODE_BITS) != (mode_ & MODE_BITS))
return (errno=error,-1); return (errno=error,-1);
} }
@ -82,23 +82,23 @@ namespace fs
static static
inline inline
int int
fchmod_check_on_error(const int fd,
const struct stat &st)
fchmod_check_on_error(const int fd_,
const struct stat &st_)
{ {
int rv; int rv;
rv = fs::fchmod(fd,st);
rv = fs::fchmod(fd_,st_);
if(rv == -1) if(rv == -1)
{ {
int error; int error;
struct stat tmpst; struct stat tmpst;
error = errno; error = errno;
rv = fs::fstat(fd,tmpst);
rv = fs::fstat(fd_,&tmpst);
if(rv == -1) if(rv == -1)
return -1; return -1;
if((st.st_mode & MODE_BITS) != (tmpst.st_mode & MODE_BITS))
if((st_.st_mode & MODE_BITS) != (tmpst.st_mode & MODE_BITS))
return (errno=error,-1); return (errno=error,-1);
} }

70
src/fs_base_chown.hpp

@ -18,94 +18,94 @@
#pragma once #pragma once
#include "fs_base_stat.hpp"
#include <string> #include <string>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
#include "fs_base_stat.hpp"
namespace fs namespace fs
{ {
static static
inline inline
int int
chown(const std::string &path,
const uid_t uid,
const gid_t gid)
chown(const std::string &path_,
const uid_t uid_,
const gid_t gid_)
{ {
return ::chown(path.c_str(),uid,gid);
return ::chown(path_.c_str(),uid_,gid_);
} }
static static
inline inline
int int
chown(const std::string &path,
const struct stat &st)
chown(const std::string &path_,
const struct stat &st_)
{ {
return fs::chown(path,st.st_uid,st.st_gid);
return fs::chown(path_,st_.st_uid,st_.st_gid);
} }
static static
inline inline
int int
lchown(const std::string &path,
const uid_t uid,
const gid_t gid)
lchown(const std::string &path_,
const uid_t uid_,
const gid_t gid_)
{ {
return ::lchown(path.c_str(),uid,gid);
return ::lchown(path_.c_str(),uid_,gid_);
} }
static static
inline inline
int int
lchown(const std::string &path,
const struct stat &st)
lchown(const std::string &path_,
const struct stat &st_)
{ {
return fs::lchown(path,st.st_uid,st.st_gid);
return fs::lchown(path_,st_.st_uid,st_.st_gid);
} }
static static
inline inline
int int
fchown(const int fd,
const uid_t uid,
const gid_t gid)
fchown(const int fd_,
const uid_t uid_,
const gid_t gid_)
{ {
return ::fchown(fd,uid,gid);
return ::fchown(fd_,uid_,gid_);
} }
static static
inline inline
int int
fchown(const int fd,
const struct stat &st)
fchown(const int fd_,
const struct stat &st_)
{ {
return fs::fchown(fd,st.st_uid,st.st_gid);
return fs::fchown(fd_,st_.st_uid,st_.st_gid);
} }
static static
inline inline
int int
lchown_check_on_error(const std::string &path,
const struct stat &st)
lchown_check_on_error(const std::string &path_,
const struct stat &st_)
{ {
int rv; int rv;
rv = fs::lchown(path,st);
rv = fs::lchown(path_,st_);
if(rv == -1) if(rv == -1)
{ {
int error; int error;
struct stat tmpst; struct stat tmpst;
error = errno; error = errno;
rv = fs::lstat(path,tmpst);
rv = fs::lstat(path_,&tmpst);
if(rv == -1) if(rv == -1)
return -1; return -1;
if((st.st_uid != tmpst.st_uid) ||
(st.st_gid != tmpst.st_gid))
if((st_.st_uid != tmpst.st_uid) ||
(st_.st_gid != tmpst.st_gid))
return (errno=error,-1); return (errno=error,-1);
} }
@ -115,24 +115,24 @@ namespace fs
static static
inline inline
int int
fchown_check_on_error(const int fd,
const struct stat &st)
fchown_check_on_error(const int fd_,
const struct stat &st_)
{ {
int rv; int rv;
rv = fs::fchown(fd,st);
rv = fs::fchown(fd_,st_);
if(rv == -1) if(rv == -1)
{ {
int error; int error;
struct stat tmpst; struct stat tmpst;
error = errno; error = errno;
rv = fs::fstat(fd,tmpst);
rv = fs::fstat(fd_,&tmpst);
if(rv == -1) if(rv == -1)
return -1; return -1;
if((st.st_uid != tmpst.st_uid) ||
(st.st_gid != tmpst.st_gid))
if((st_.st_uid != tmpst.st_uid) ||
(st_.st_gid != tmpst.st_gid))
return (errno=error,-1); return (errno=error,-1);
} }

4
src/fs_base_close.hpp

@ -25,8 +25,8 @@ namespace fs
static static
inline inline
int int
close(const int fd)
close(const int fd_)
{ {
return ::close(fd);
return ::close(fd_);
} }
} }

4
src/fs_base_closedir.hpp

@ -26,8 +26,8 @@ namespace fs
static static
inline inline
int int
closedir(DIR *dirp)
closedir(DIR *dirp_)
{ {
return ::closedir(dirp);
return ::closedir(dirp_);
} }
} }

4
src/fs_base_dirfd.hpp

@ -26,8 +26,8 @@ namespace fs
static static
inline inline
int int
dirfd(DIR *dirp)
dirfd(DIR *dirp_)
{ {
return ::dirfd(dirp);
return ::dirfd(dirp_);
} }
} }

4
src/fs_base_dup.hpp

@ -25,8 +25,8 @@ namespace fs
static static
inline inline
int int
dup(const int fd)
dup(const int fd_)
{ {
return ::dup(fd);
return ::dup(fd_);
} }
} }

18
src/fs_base_fadvise.hpp

@ -19,17 +19,17 @@
namespace fs namespace fs
{ {
int int
fadvise_dontneed(const int fd,
const off_t offset = 0,
const off_t len = 0);
fadvise_dontneed(const int fd_,
const off_t offset_ = 0,
const off_t len_ = 0);
int int
fadvise_willneed(const int fd,
const off_t offset = 0,
const off_t len = 0);
fadvise_willneed(const int fd_,
const off_t offset_ = 0,
const off_t len_ = 0);
int int
fadvise_sequential(const int fd,
const off_t offset = 0,
const off_t len = 0);
fadvise_sequential(const int fd_,
const off_t offset_ = 0,
const off_t len_ = 0);
} }

8
src/fs_base_fallocate.hpp

@ -21,8 +21,8 @@
namespace fs namespace fs
{ {
int int
fallocate(const int fd,
const int mode,
const off_t offset,
const off_t len);
fallocate(const int fd_,
const int mode_,
const off_t offset_,
const off_t len_);
} }

6
src/fs_base_flock.hpp

@ -25,9 +25,9 @@ namespace fs
static static
inline inline
int int
flock(const int fd,
const int operation)
flock(const int fd_,
const int operation_)
{ {
return ::flock(fd,operation);
return ::flock(fd_,operation_);
} }
} }

8
src/fs_base_fsync.hpp

@ -31,18 +31,18 @@ namespace fs
static static
inline inline
int int
fsync(const int fd)
fsync(const int fd_)
{ {
return ::fsync(fd);
return ::fsync(fd_);
} }
static static
inline inline
int int
fdatasync(const int fd)
fdatasync(const int fd_)
{ {
#if _POSIX_SYNCHRONIZED_IO > 0 #if _POSIX_SYNCHRONIZED_IO > 0
return ::fdatasync(fd);
return ::fdatasync(fd_);
#else #else
return (errno=ENOSYS,-1); return (errno=ENOSYS,-1);
#endif #endif

6
src/fs_base_ftruncate.hpp

@ -26,9 +26,9 @@ namespace fs
static static
inline inline
int int
ftruncate(const int fd,
const off_t size)
ftruncate(const int fd_,
const off_t size_)
{ {
return ::ftruncate(fd,size);
return ::ftruncate(fd_,size_);
} }
} }

8
src/fs_base_futimesat.hpp

@ -18,10 +18,12 @@
#pragma once #pragma once
#include <sys/time.h>
namespace fs namespace fs
{ {
int int
futimesat(const int dirfd,
const char *pathname,
const struct timeval times[2]);
futimesat(const int dirfd_,
const char *pathname_,
const struct timeval times_[2]);
} }

4
src/fs_base_getxattr.hpp

@ -21,10 +21,10 @@
#include "errno.hpp" #include "errno.hpp"
#include "xattr.hpp" #include "xattr.hpp"
#include <sys/types.h>
#include <string> #include <string>
#include <sys/types.h>
namespace fs namespace fs
{ {
static static

7
src/fs_base_link.hpp

@ -27,9 +27,10 @@ namespace fs
static static
inline inline
int int
link(const std::string &oldpath,
const std::string &newpath)
link(const std::string &oldpath_,
const std::string &newpath_)
{ {
return ::link(oldpath.c_str(),newpath.c_str());
return ::link(oldpath_.c_str(),
newpath_.c_str());
} }
} }

4
src/fs_base_listxattr.hpp

@ -21,10 +21,10 @@
#include "errno.hpp" #include "errno.hpp"
#include "xattr.hpp" #include "xattr.hpp"
#include <sys/types.h>
#include <string> #include <string>
#include <sys/types.h>
namespace fs namespace fs
{ {
static static

8
src/fs_base_lseek.hpp

@ -26,10 +26,10 @@ namespace fs
static static
inline inline
off_t off_t
lseek(const int fd,
const off_t offset,
const int whence)
lseek(const int fd_,
const off_t offset_,
const int whence_)
{ {
return ::lseek(fd,offset,whence);
return ::lseek(fd_,offset_,whence_);
} }
} }

6
src/fs_base_mkdir.hpp

@ -28,9 +28,9 @@ namespace fs
static static
inline inline
int int
mkdir(const std::string &path,
const mode_t mode)
mkdir(const std::string &path_,
const mode_t mode_)
{ {
return ::mkdir(path.c_str(),mode);
return ::mkdir(path_.c_str(),mode_);
} }
} }

8
src/fs_base_mknod.hpp

@ -28,10 +28,10 @@ namespace fs
static static
inline inline
int int
mknod(const std::string &path,
const mode_t mode,
const dev_t dev)
mknod(const std::string &path_,
const mode_t mode_,
const dev_t dev_)
{ {
return ::mknod(path.c_str(),mode,dev);
return ::mknod(path_.c_str(),mode_,dev_);
} }
} }

14
src/fs_base_mkstemp.hpp

@ -18,29 +18,29 @@
#pragma once #pragma once
#include <string>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <string>
namespace fs namespace fs
{ {
static static
inline inline
int int
mkstemp(std::string &filepath)
mkstemp(std::string &filepath_)
{ {
int fd; int fd;
char buf[filepath.size()+8];
char buf[filepath_.size()+8];
strcpy(buf,filepath.c_str());
strcpy(buf+filepath.size(),".XXXXXX");
strcpy(buf,filepath_.c_str());
strcpy(buf+filepath_.size(),".XXXXXX");
fd = ::mkstemp(buf); fd = ::mkstemp(buf);
if(fd == -1) if(fd == -1)
return -1; return -1;
filepath = buf;
filepath_ = buf;
return fd; return fd;
} }

4
src/fs_base_open.hpp

@ -18,12 +18,12 @@
#pragma once #pragma once
#include <string>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <string>
namespace fs namespace fs
{ {
static static

4
src/fs_base_opendir.hpp

@ -28,8 +28,8 @@ namespace fs
static static
inline inline
DIR * DIR *
opendir(const std::string &name)
opendir(const std::string &name_)
{ {
return ::opendir(name.c_str());
return ::opendir(name_.c_str());
} }
} }

18
src/fs_base_read.hpp

@ -25,21 +25,21 @@ namespace fs
static static
inline inline
ssize_t ssize_t
read(const int fd,
void *buf,
const size_t count)
read(const int fd_,
void *buf_,
const size_t count_)
{ {
return ::read(fd,buf,count);
return ::read(fd_,buf_,count_);
} }
static static
inline inline
ssize_t ssize_t
pread(const int fd,
void *buf,
const size_t count,
const off_t offset)
pread(const int fd_,
void *buf_,
const size_t count_,
const off_t offset_)
{ {
return ::pread(fd,buf,count,offset);
return ::pread(fd_,buf_,count_,offset_);
} }
} }

4
src/fs_base_readdir.hpp

@ -25,8 +25,8 @@ namespace fs
static static
inline inline
struct dirent * struct dirent *
readdir(DIR *dirp)
readdir(DIR *dirp_)
{ {
return ::readdir(dirp);
return ::readdir(dirp_);
} }
} }

8
src/fs_base_readlink.hpp

@ -27,10 +27,10 @@ namespace fs
static static
inline inline
int int
readlink(const std::string &path,
char *buf,
const size_t bufsiz)
readlink(const std::string &path_,
char *buf_,
const size_t bufsiz_)
{ {
return ::readlink(path.c_str(),buf,bufsiz);
return ::readlink(path_.c_str(),buf_,bufsiz_);
} }
} }

10
src/fs_base_realpath.hpp

@ -28,17 +28,17 @@ namespace fs
static static
inline inline
char * char *
realpath(const std::string &path,
char *resolved_path)
realpath(const std::string &path_,
char *resolved_path_)
{ {
return ::realpath(path.c_str(),resolved_path);
return ::realpath(path_.c_str(),resolved_path_);
} }
static static
inline inline
char * char *
realpath(const std::string &path)
realpath(const std::string &path_)
{ {
return fs::realpath(path,NULL);
return fs::realpath(path_,NULL);
} }
} }

12
src/fs_base_remove.hpp

@ -27,8 +27,16 @@ namespace fs
static static
inline inline
int int
remove(const std::string &pathname)
remove(const char *pathname_)
{ {
return ::remove(pathname.c_str());
return ::remove(pathname_);
}
static
inline
int
remove(const std::string &pathname_)
{
return fs::remove(pathname_.c_str());
} }
} }

10
src/fs_base_removexattr.hpp

@ -18,21 +18,21 @@
#pragma once #pragma once
#include <sys/types.h>
#include "errno.hpp" #include "errno.hpp"
#include "xattr.hpp" #include "xattr.hpp"
#include <sys/types.h>
namespace fs namespace fs
{ {
static static
inline inline
int int
lremovexattr(const std::string &path,
const char *attrname)
lremovexattr(const std::string &path_,
const char *attrname_)
{ {
#ifdef USE_XATTR #ifdef USE_XATTR
return ::lremovexattr(path.c_str(),attrname);
return ::lremovexattr(path_.c_str(),attrname_);
#else #else
return (errno=ENOTSUP,-1); return (errno=ENOTSUP,-1);
#endif #endif

12
src/fs_base_rmdir.hpp

@ -27,8 +27,16 @@ namespace fs
static static
inline inline
int int
rmdir(const std::string &path)
rmdir(const char *path_)
{ {
return ::rmdir(path.c_str());
return ::rmdir(path_);
}
static
inline
int
rmdir(const std::string &path_)
{
return fs::rmdir(path_.c_str());
} }
} }

4
src/fs_base_setxattr.hpp

@ -21,10 +21,10 @@
#include "errno.hpp" #include "errno.hpp"
#include "xattr.hpp" #include "xattr.hpp"
#include <sys/types.h>
#include <string> #include <string>
#include <sys/types.h>
namespace fs namespace fs
{ {
static static

57
src/fs_base_stat.hpp

@ -29,48 +29,57 @@ namespace fs
static static
inline inline
int int
stat(const char *path,
struct stat &st)
stat(const char *path_,
struct stat *st_)
{ {
return ::stat(path,&st);
return ::stat(path_,st_);
} }
static static
inline inline
int int
stat(const std::string &path,
struct stat &st)
stat(const std::string &path_,
struct stat *st_)
{ {
return fs::stat(path.c_str(),st);
return fs::stat(path_.c_str(),st_);
} }
static static
inline inline
int int
lstat(const std::string &path,
struct stat &st)
lstat(const char *path_,
struct stat *st_)
{ {
return ::lstat(path.c_str(),&st);
return ::lstat(path_,st_);
} }
static static
inline inline
int int
fstat(const int fd,
struct stat &st)
lstat(const std::string &path_,
struct stat *st_)
{ {
return ::fstat(fd,&st);
return fs::lstat(path_.c_str(),st_);
}
static
inline
int
fstat(const int fd_,
struct stat *st_)
{
return ::fstat(fd_,st_);
} }
static static
inline inline
timespec * timespec *
stat_atime(struct stat &st)
stat_atime(struct stat *st_)
{ {
#if __APPLE__ #if __APPLE__
return &st.st_atimespec;
return &st_->st_atimespec;
#else #else
return &st.st_atim;
return &st_->st_atim;
#endif #endif
} }
@ -78,24 +87,24 @@ namespace fs
inline inline
const const
timespec * timespec *
stat_atime(const struct stat &st)
stat_atime(const struct stat *st_)
{ {
#if __APPLE__ #if __APPLE__
return &st.st_atimespec;
return &st_->st_atimespec;
#else #else
return &st.st_atim;
return &st_->st_atim;
#endif #endif
} }
static static
inline inline
timespec * timespec *
stat_mtime(struct stat &st)
stat_mtime(struct stat *st_)
{ {
#if __APPLE__ #if __APPLE__
return &st.st_mtimespec;
return &st_->st_mtimespec;
#else #else
return &st.st_mtim;
return &st_->st_mtim;
#endif #endif
} }
@ -103,12 +112,12 @@ namespace fs
inline inline
const const
timespec * timespec *
stat_mtime(const struct stat &st)
stat_mtime(const struct stat *st_)
{ {
#if __APPLE__ #if __APPLE__
return &st.st_mtimespec;
return &st_->st_mtimespec;
#else #else
return &st.st_mtim;
return &st_->st_mtim;
#endif #endif
} }
} }

4
src/fs_base_statvfs.hpp

@ -22,10 +22,10 @@
#include "fs_base_close.hpp" #include "fs_base_close.hpp"
#include "fs_base_open.hpp" #include "fs_base_open.hpp"
#include <sys/statvfs.h>
#include <string> #include <string>
#include <sys/statvfs.h>
#ifndef O_PATH #ifndef O_PATH
# define O_PATH 0 # define O_PATH 0
#endif #endif

24
src/fs_base_symlink.hpp

@ -27,18 +27,30 @@ namespace fs
static static
inline inline
int int
symlink(const std::string &oldpath,
const std::string &newpath)
symlink(const char *oldpath_,
const char *newpath_)
{ {
return ::symlink(oldpath.c_str(),newpath.c_str());
return ::symlink(oldpath_,
newpath_);
} }
static static
inline inline
int int
symlink(const char *oldpath,
const std::string &newpath)
symlink(const std::string &oldpath_,
const std::string &newpath_)
{ {
return ::symlink(oldpath,newpath.c_str());
return fs::symlink(oldpath_.c_str(),
newpath_.c_str());
}
static
inline
int
symlink(const char *oldpath_,
const std::string &newpath_)
{
return fs::symlink(oldpath_,
newpath_.c_str());
} }
} }

15
src/fs_base_truncate.hpp

@ -28,9 +28,18 @@ namespace fs
static static
inline inline
int int
truncate(const std::string &path,
const off_t length)
truncate(const char *path_,
const off_t length_)
{ {
return ::truncate(path.c_str(),length);
return ::truncate(path_,length_);
}
static
inline
int
truncate(const std::string &path_,
const off_t length_)
{
return fs::truncate(path_.c_str(),length_);
} }
} }

26
src/fs_base_utime.hpp

@ -31,37 +31,37 @@ namespace fs
static static
inline inline
int int
utime(const std::string &path,
const struct stat &st)
utime(const std::string &path_,
const struct stat &st_)
{ {
struct timespec times[2]; struct timespec times[2];
times[0] = *fs::stat_atime(st);
times[1] = *fs::stat_mtime(st);
times[0] = *fs::stat_atime(&st_);
times[1] = *fs::stat_mtime(&st_);
return fs::utime(AT_FDCWD,path,times,0);
return fs::utime(AT_FDCWD,path_,times,0);
} }
static static
inline inline
int int
utime(const int fd,
const struct stat &st)
utime(const int fd_,
const struct stat &st_)
{ {
struct timespec times[2]; struct timespec times[2];
times[0] = *fs::stat_atime(st);
times[1] = *fs::stat_mtime(st);
times[0] = *fs::stat_atime(&st_);
times[1] = *fs::stat_mtime(&st_);
return fs::utime(fd,times);
return fs::utime(fd_,times);
} }
static static
inline inline
int int
lutime(const std::string &path,
const struct timespec times[2])
lutime(const std::string &path_,
const struct timespec times_[2])
{ {
return fs::utime(AT_FDCWD,path,times,AT_SYMLINK_NOFOLLOW);
return fs::utime(AT_FDCWD,path_,times_,AT_SYMLINK_NOFOLLOW);
} }
} }

132
src/fs_base_utime_generic.hpp

@ -18,15 +18,15 @@
#pragma once #pragma once
#include "fs_base_futimesat.hpp"
#include "fs_base_stat.hpp"
#include <string> #include <string>
#include <fcntl.h> #include <fcntl.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/time.h> #include <sys/time.h>
#include "fs_base_futimesat.hpp"
#include "fs_base_stat.hpp"
#ifndef UTIME_NOW #ifndef UTIME_NOW
# define UTIME_NOW ((1l << 30) - 1l) # define UTIME_NOW ((1l << 30) - 1l)
#endif #endif
@ -38,54 +38,54 @@
static static
inline inline
bool bool
_can_call_lutimes(const int dirfd,
const std::string &path,
const int flags)
_can_call_lutimes(const int dirfd_,
const std::string &path_,
const int flags_)
{ {
return ((flags == AT_SYMLINK_NOFOLLOW) &&
((dirfd == AT_FDCWD) ||
(path[0] == '/')));
return ((flags_ == AT_SYMLINK_NOFOLLOW) &&
((dirfd_ == AT_FDCWD) ||
(path_[0] == '/')));
} }
static static
inline inline
bool bool
_should_ignore(const struct timespec ts[2])
_should_ignore(const struct timespec ts_[2])
{ {
return ((ts != NULL) &&
(ts[0].tv_nsec == UTIME_OMIT) &&
(ts[1].tv_nsec == UTIME_OMIT));
return ((ts_ != NULL) &&
(ts_[0].tv_nsec == UTIME_OMIT) &&
(ts_[1].tv_nsec == UTIME_OMIT));
} }
static static
inline inline
bool bool
_should_be_set_to_now(const struct timespec ts[2])
_should_be_set_to_now(const struct timespec ts_[2])
{ {
return ((ts == NULL) ||
((ts[0].tv_nsec == UTIME_NOW) &&
(ts[1].tv_nsec == UTIME_NOW)));
return ((ts_ == NULL) ||
((ts_[0].tv_nsec == UTIME_NOW) &&
(ts_[1].tv_nsec == UTIME_NOW)));
} }
static static
inline inline
bool bool
_timespec_invalid(const struct timespec &ts)
_timespec_invalid(const struct timespec &ts_)
{ {
return (((ts.tv_nsec < 0) ||
(ts.tv_nsec > 999999999)) &&
((ts.tv_nsec != UTIME_NOW) &&
(ts.tv_nsec != UTIME_OMIT)));
return (((ts_.tv_nsec < 0) ||
(ts_.tv_nsec > 999999999)) &&
((ts_.tv_nsec != UTIME_NOW) &&
(ts_.tv_nsec != UTIME_OMIT)));
} }
static static
inline inline
bool bool
_timespec_invalid(const struct timespec ts[2])
_timespec_invalid(const struct timespec ts_[2])
{ {
return ((ts != NULL) &&
(_timespec_invalid(ts[0]) ||
_timespec_invalid(ts[1])));
return ((ts_ != NULL) &&
(_timespec_invalid(ts_[0]) ||
_timespec_invalid(ts_[1])));
} }
static static
@ -99,19 +99,19 @@ _flags_invalid(const int flags)
static static
inline inline
bool bool
_any_timespec_is_utime_omit(const struct timespec ts[2])
_any_timespec_is_utime_omit(const struct timespec ts_[2])
{ {
return ((ts[0].tv_nsec == UTIME_OMIT) ||
(ts[1].tv_nsec == UTIME_OMIT));
return ((ts_[0].tv_nsec == UTIME_OMIT) ||
(ts_[1].tv_nsec == UTIME_OMIT));
} }
static static
inline inline
bool bool
_any_timespec_is_utime_now(const struct timespec ts[2])
_any_timespec_is_utime_now(const struct timespec ts_[2])
{ {
return ((ts[0].tv_nsec == UTIME_NOW) ||
(ts[1].tv_nsec == UTIME_NOW));
return ((ts_[0].tv_nsec == UTIME_NOW) ||
(ts_[1].tv_nsec == UTIME_NOW));
} }
static static
@ -119,7 +119,7 @@ inline
int int
_set_utime_omit_to_current_value(const int dirfd, _set_utime_omit_to_current_value(const int dirfd,
const std::string &path, const std::string &path,
const struct timespec ts[2],
const struct timespec ts_[2],
struct timeval tv[2], struct timeval tv[2],
const int flags) const int flags)
{ {
@ -128,7 +128,7 @@ _set_utime_omit_to_current_value(const int dirfd,
timespec *atime; timespec *atime;
timespec *mtime; timespec *mtime;
if(!_any_timespec_is_utime_omit(ts))
if(!_any_timespec_is_utime_omit(ts_))
return 0; return 0;
rv = ::fstatat(dirfd,path.c_str(),&st,flags); rv = ::fstatat(dirfd,path.c_str(),&st,flags);
@ -138,9 +138,9 @@ _set_utime_omit_to_current_value(const int dirfd,
atime = fs::stat_atime(st); atime = fs::stat_atime(st);
mtime = fs::stat_mtime(st); mtime = fs::stat_mtime(st);
if(ts[0].tv_nsec == UTIME_OMIT)
if(ts_[0].tv_nsec == UTIME_OMIT)
TIMESPEC_TO_TIMEVAL(&tv[0],atime); TIMESPEC_TO_TIMEVAL(&tv[0],atime);
if(ts[1].tv_nsec == UTIME_OMIT)
if(ts_[1].tv_nsec == UTIME_OMIT)
TIMESPEC_TO_TIMEVAL(&tv[1],mtime); TIMESPEC_TO_TIMEVAL(&tv[1],mtime);
return 0; return 0;
@ -150,7 +150,7 @@ static
inline inline
int int
_set_utime_omit_to_current_value(const int fd, _set_utime_omit_to_current_value(const int fd,
const struct timespec ts[2],
const struct timespec ts_[2],
struct timeval tv[2]) struct timeval tv[2])
{ {
int rv; int rv;
@ -158,7 +158,7 @@ _set_utime_omit_to_current_value(const int fd,
timespec *atime; timespec *atime;
timespec *mtime; timespec *mtime;
if(!_any_timespec_is_utime_omit(ts))
if(!_any_timespec_is_utime_omit(ts_))
return 0; return 0;
rv = ::fstat(fd,&st); rv = ::fstat(fd,&st);
@ -168,9 +168,9 @@ _set_utime_omit_to_current_value(const int fd,
atime = fs::stat_atime(st); atime = fs::stat_atime(st);
mtime = fs::stat_mtime(st); mtime = fs::stat_mtime(st);
if(ts[0].tv_nsec == UTIME_OMIT)
if(ts_[0].tv_nsec == UTIME_OMIT)
TIMESPEC_TO_TIMEVAL(&tv[0],atime); TIMESPEC_TO_TIMEVAL(&tv[0],atime);
if(ts[1].tv_nsec == UTIME_OMIT)
if(ts_[1].tv_nsec == UTIME_OMIT)
TIMESPEC_TO_TIMEVAL(&tv[1],mtime); TIMESPEC_TO_TIMEVAL(&tv[1],mtime);
return 0; return 0;
@ -179,22 +179,22 @@ _set_utime_omit_to_current_value(const int fd,
static static
inline inline
int int
_set_utime_now_to_now(const struct timespec ts[2],
_set_utime_now_to_now(const struct timespec ts_[2],
struct timeval tv[2]) struct timeval tv[2])
{ {
int rv; int rv;
struct timeval now; struct timeval now;
if(_any_timespec_is_utime_now(ts))
if(_any_timespec_is_utime_now(ts_))
return 0; return 0;
rv = ::gettimeofday(&now,NULL); rv = ::gettimeofday(&now,NULL);
if(rv == -1) if(rv == -1)
return -1; return -1;
if(ts[0].tv_nsec == UTIME_NOW)
if(ts_[0].tv_nsec == UTIME_NOW)
tv[0] = now; tv[0] = now;
if(ts[1].tv_nsec == UTIME_NOW)
if(ts_[1].tv_nsec == UTIME_NOW)
tv[1] = now; tv[1] = now;
return 0; return 0;
@ -205,24 +205,24 @@ inline
int int
_convert_timespec_to_timeval(const int dirfd, _convert_timespec_to_timeval(const int dirfd,
const std::string &path, const std::string &path,
const struct timespec ts[2],
const struct timespec ts_[2],
struct timeval tv[2], struct timeval tv[2],
struct timeval *&tvp, struct timeval *&tvp,
const int flags) const int flags)
{ {
int rv; int rv;
if(_should_be_set_to_now(ts))
if(_should_be_set_to_now(ts_))
return (tvp=NULL,0); return (tvp=NULL,0);
TIMESPEC_TO_TIMEVAL(&tv[0],&ts[0]);
TIMESPEC_TO_TIMEVAL(&tv[1],&ts[1]);
TIMESPEC_TO_TIMEVAL(&tv[0],&ts_[0]);
TIMESPEC_TO_TIMEVAL(&tv[1],&ts_[1]);
rv = _set_utime_omit_to_current_value(dirfd,path,ts,tv,flags);
rv = _set_utime_omit_to_current_value(dirfd,path,ts_,tv,flags);
if(rv == -1) if(rv == -1)
return -1; return -1;
rv = _set_utime_now_to_now(ts,tv);
rv = _set_utime_now_to_now(ts_,tv);
if(rv == -1) if(rv == -1)
return -1; return -1;
@ -233,23 +233,23 @@ static
inline inline
int int
_convert_timespec_to_timeval(const int fd, _convert_timespec_to_timeval(const int fd,
const struct timespec ts[2],
const struct timespec ts_[2],
struct timeval tv[2], struct timeval tv[2],
struct timeval *&tvp) struct timeval *&tvp)
{ {
int rv; int rv;
if(_should_be_set_to_now(ts))
if(_should_be_set_to_now(ts_))
return (tvp=NULL,0); return (tvp=NULL,0);
TIMESPEC_TO_TIMEVAL(&tv[0],&ts[0]);
TIMESPEC_TO_TIMEVAL(&tv[1],&ts[1]);
TIMESPEC_TO_TIMEVAL(&tv[0],&ts_[0]);
TIMESPEC_TO_TIMEVAL(&tv[1],&ts_[1]);
rv = _set_utime_omit_to_current_value(fd,ts,tv);
rv = _set_utime_omit_to_current_value(fd,ts_,tv);
if(rv == -1) if(rv == -1)
return -1; return -1;
rv = _set_utime_now_to_now(ts,tv);
rv = _set_utime_now_to_now(ts_,tv);
if(rv == -1) if(rv == -1)
return -1; return -1;
@ -263,7 +263,7 @@ namespace fs
int int
utime(const int dirfd, utime(const int dirfd,
const std::string &path, const std::string &path,
const struct timespec ts[2],
const struct timespec ts_[2],
const int flags) const int flags)
{ {
int rv; int rv;
@ -272,12 +272,12 @@ namespace fs
if(_flags_invalid(flags)) if(_flags_invalid(flags))
return (errno=EINVAL,-1); return (errno=EINVAL,-1);
if(_timespec_invalid(ts))
if(_timespec_invalid(ts_))
return (errno=EINVAL,-1); return (errno=EINVAL,-1);
if(_should_ignore(ts))
if(_should_ignore(ts_))
return 0; return 0;
rv = _convert_timespec_to_timeval(dirfd,path,ts,tv,tvp,flags);
rv = _convert_timespec_to_timeval(dirfd,path,ts_,tv,tvp,flags);
if(rv == -1) if(rv == -1)
return -1; return -1;
@ -292,22 +292,22 @@ namespace fs
static static
inline inline
int int
utime(const int fd,
const struct timespec ts[2])
utime(const int fd_,
const struct timespec ts_[2])
{ {
int rv; int rv;
struct timeval tv[2]; struct timeval tv[2];
struct timeval *tvp; struct timeval *tvp;
if(_timespec_invalid(ts))
if(_timespec_invalid(ts_))
return (errno=EINVAL,-1); return (errno=EINVAL,-1);
if(_should_ignore(ts))
if(_should_ignore(ts_))
return 0; return 0;
rv = _convert_timespec_to_timeval(fd,ts,tv,tvp);
rv = _convert_timespec_to_timeval(fd_,ts_,tv,tvp);
if(rv == -1) if(rv == -1)
return -1; return -1;
return ::futimes(fd,tvp);
return ::futimes(fd_,tvp);
} }
} }

2
src/fs_clonefile.cpp

@ -84,7 +84,7 @@ namespace fs
int rv; int rv;
struct stat src_st; struct stat src_st;
rv = fs::fstat(src_fd_,src_st);
rv = fs::fstat(src_fd_,&src_st);
if(rv == -1) if(rv == -1)
return -1; return -1;

22
src/fs_clonepath.cpp

@ -78,14 +78,14 @@ namespace fs
return -1; return -1;
} }
fs::path::make(&fromsrc,relative,frompath);
rv = fs::stat(frompath,st);
frompath = fs::path::make(fromsrc,relative);
rv = fs::stat(frompath,&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);
topath = fs::path::make(tosrc,relative);
rv = fs::mkdir(topath,st.st_mode); rv = fs::mkdir(topath,st.st_mode);
if(rv == -1) if(rv == -1)
{ {
@ -117,10 +117,10 @@ namespace fs
} }
int int
clonepath(const std::string &from,
const std::string &to,
const std::string &relative,
const bool return_metadata_errors)
clonepath(const string &from,
const string &to,
const string &relative,
const bool return_metadata_errors)
{ {
return fs::clonepath(from,to,relative.c_str(),return_metadata_errors); return fs::clonepath(from,to,relative.c_str(),return_metadata_errors);
} }
@ -144,10 +144,10 @@ namespace fs
} }
int int
clonepath_as_root(const std::string &from,
const std::string &to,
const std::string &relative,
const bool return_metadata_errors)
clonepath_as_root(const string &from,
const string &to,
const string &relative,
const bool return_metadata_errors)
{ {
return fs::clonepath_as_root(from,to,relative.c_str(),return_metadata_errors); return fs::clonepath_as_root(from,to,relative.c_str(),return_metadata_errors);
} }

2
src/fs_copyfile.cpp

@ -98,7 +98,7 @@ namespace fs
int rv; int rv;
struct stat st; struct stat st;
rv = fs::fstat(src_fd_,st);
rv = fs::fstat(src_fd_,&st);
if(rv == -1) if(rv == -1)
return rv; return rv;

2
src/fs_cow.cpp

@ -89,7 +89,7 @@ namespace fs
if(!is_eligible(flags_)) if(!is_eligible(flags_))
return false; return false;
rv = fs::lstat(fullpath_,st);
rv = fs::lstat(fullpath_,&st);
if(rv == -1) if(rv == -1)
return false; return false;

4
src/fs_devid.hpp

@ -27,12 +27,12 @@ namespace fs
static static
inline inline
dev_t dev_t
devid(const int fd)
devid(const int fd_)
{ {
int rv; int rv;
struct stat st; struct stat st;
rv = ::fstat(fd,&st);
rv = ::fstat(fd_,&st);
if(rv == -1) if(rv == -1)
return -1; return -1;

8
src/fs_exists.hpp

@ -29,7 +29,7 @@ namespace fs
inline inline
bool bool
exists(const std::string &path_, exists(const std::string &path_,
struct stat &st_)
struct stat *st_)
{ {
int rv; int rv;
@ -45,7 +45,7 @@ namespace fs
{ {
struct stat st; struct stat st;
return fs::exists(path_,st);
return fs::exists(path_,&st);
} }
@ -54,7 +54,7 @@ namespace fs
bool bool
exists(const std::string &basepath_, exists(const std::string &basepath_,
const char *relpath_, const char *relpath_,
struct stat &st_)
struct stat *st_)
{ {
std::string fullpath; std::string fullpath;
@ -71,6 +71,6 @@ namespace fs
{ {
struct stat st; struct stat st;
return fs::exists(basepath_,relpath_,st);
return fs::exists(basepath_,relpath_,&st);
} }
} }

7
src/fs_glob.hpp

@ -19,10 +19,7 @@
namespace fs namespace fs
{ {
using std::string;
using std::vector;
void void
glob(const string &pattern_,
vector<string> &strs_);
glob(const std::string &pattern_,
std::vector<std::string> &strs_);
} }

15
src/fs_inode.hpp

@ -25,20 +25,17 @@ namespace fs
{ {
namespace inode namespace inode
{ {
enum
{
MAGIC = 0x7472617065786974
};
static const uint64_t MAGIC = 0x7472617065786974;
inline inline
void void
recompute(struct stat &st)
recompute(struct stat *st_)
{ {
// not ideal to do this at runtime but likely gets optimized out
if(sizeof(st.st_ino) == 4)
st.st_ino |= ((uint32_t)st.st_dev << 16);
/* not ideal to do this at runtime but likely gets optimized out */
if(sizeof(st_->st_ino) == 4)
st_->st_ino |= ((uint32_t)st_->st_dev << 16);
else else
st.st_ino |= ((uint64_t)st.st_dev << 32);
st_->st_ino |= ((uint64_t)st_->st_dev << 32);
} }
} }
} }

2
src/fs_movefile.cpp

@ -58,7 +58,7 @@ namespace fs
fdin = origfd; fdin = origfd;
rv = fs::fstat(fdin,fdin_st);
rv = fs::fstat(fdin,&fdin_st);
if(rv == -1) if(rv == -1)
return -1; return -1;

41
src/fs_path.hpp

@ -30,6 +30,7 @@ namespace fs
string basename(const string &path); string basename(const string &path);
static
inline inline
void void
append(string &base, append(string &base,
@ -38,6 +39,7 @@ namespace fs
base += suffix; base += suffix;
} }
static
inline inline
void void
append(string &base, append(string &base,
@ -46,36 +48,16 @@ namespace fs
base += suffix; base += suffix;
} }
static
inline inline
void
string
make(const string &base_, make(const string &base_,
const char *suffix_,
string *output_)
{
*output_ = base_;
*output_ += suffix_;
}
inline
void
make(const string *base,
const char *suffix,
string &output)
{
output = *base;
output += suffix;
}
inline
void
make(const string *base,
const string &suffix,
string &output)
const char *suffix_)
{ {
output = *base;
output += suffix;
return (base_ + suffix_);
} }
static
inline inline
string string
make(const string *base_, make(const string *base_,
@ -92,5 +74,14 @@ namespace fs
{ {
return (*base_ + *suffix_); return (*base_ + *suffix_);
} }
static
inline
string
make(const string &base_,
const string &suffix_)
{
return (base_ + suffix_);
}
} }
}; };

4
src/fs_statvfs_cache.cpp

@ -39,7 +39,7 @@ static uint64_t g_timeout = 0;
static statvfs_cache g_cache; static statvfs_cache g_cache;
static pthread_mutex_t g_cache_lock = PTHREAD_MUTEX_INITIALIZER; static pthread_mutex_t g_cache_lock = PTHREAD_MUTEX_INITIALIZER;
namespace local
namespace l
{ {
static static
uint64_t uint64_t
@ -82,7 +82,7 @@ namespace fs
return fs::statvfs(path_,st_); return fs::statvfs(path_,st_);
rv = 0; rv = 0;
now = local::get_time();
now = l::get_time();
pthread_mutex_lock(&g_cache_lock); pthread_mutex_lock(&g_cache_lock);

56
src/access.cpp → src/fuse_access.cpp

@ -27,47 +27,47 @@
using std::string; using std::string;
using std::vector; using std::vector;
static
int
_access(Policy::Func::Search searchFunc,
const Branches &branches_,
const uint64_t minfreespace,
const char *fusepath,
const int mask)
namespace l
{ {
int rv;
string fullpath;
vector<const string*> basepaths;
static
int
access(Policy::Func::Search searchFunc,
const Branches &branches_,
const uint64_t minfreespace,
const char *fusepath,
const int mask)
{
int rv;
string fullpath;
vector<const string*> basepaths;
rv = searchFunc(branches_,fusepath,minfreespace,basepaths);
if(rv == -1)
return -errno;
rv = searchFunc(branches_,fusepath,minfreespace,basepaths);
if(rv == -1)
return -errno;
fs::path::make(basepaths[0],fusepath,fullpath);
fullpath = fs::path::make(basepaths[0],fusepath);
rv = fs::eaccess(fullpath,mask);
rv = fs::eaccess(fullpath,mask);
return ((rv == -1) ? -errno : 0);
return ((rv == -1) ? -errno : 0);
}
} }
namespace mergerfs
namespace FUSE
{ {
namespace fuse
int
access(const char *fusepath,
int mask)
{ {
int
access(const char *fusepath,
int mask)
{
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
return _access(config.access,
return l::access(config.access,
config.branches, config.branches,
config.minfreespace, config.minfreespace,
fusepath, fusepath,
mask); mask);
}
} }
} }

10
src/rmdir.hpp → src/fuse_access.hpp

@ -16,11 +16,9 @@
#pragma once #pragma once
namespace mergerfs
namespace FUSE
{ {
namespace fuse
{
int
rmdir(const char *fusepath);
}
int
access(const char *fusepath_,
int mask_);
} }

105
src/fuse_chmod.cpp

@ -0,0 +1,105 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.hpp"
#include "errno.hpp"
#include "fs_base_chmod.hpp"
#include "fs_path.hpp"
#include "rv.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
#include <fuse.h>
#include <string>
#include <vector>
using std::string;
using std::vector;
namespace l
{
static
int
chmod_loop_core(const string *basepath_,
const char *fusepath_,
const mode_t mode_,
const int error_)
{
int rv;
string fullpath;
fullpath = fs::path::make(basepath_,fusepath_);
rv = fs::chmod(fullpath,mode_);
return error::calc(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 = l::chmod_loop_core(basepaths_[i],fusepath_,mode_,error);
}
return -error;
}
static
int
chmod(Policy::Func::Action actionFunc_,
const Branches &branches_,
const uint64_t minfreespace_,
const char *fusepath_,
const mode_t mode_)
{
int rv;
vector<const string*> basepaths;
rv = actionFunc_(branches_,fusepath_,minfreespace_,basepaths);
if(rv == -1)
return -errno;
return l::chmod_loop(basepaths,fusepath_,mode_);
}
}
namespace FUSE
{
int
chmod(const char *fusepath_,
mode_t mode_)
{
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
return l::chmod(config.chmod,
config.branches,
config.minfreespace,
fusepath_,
mode_);
}
}

10
src/unlink.hpp → src/fuse_chmod.hpp

@ -16,11 +16,9 @@
#pragma once #pragma once
namespace mergerfs
namespace FUSE
{ {
namespace fuse
{
int
unlink(const char *fusepath);
}
int
chmod(const char *fusepath_,
mode_t mode_);
} }

110
src/fuse_chown.cpp

@ -0,0 +1,110 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.hpp"
#include "errno.hpp"
#include "fs_base_chown.hpp"
#include "fs_path.hpp"
#include "rv.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
#include <fuse.h>
#include <string>
#include <vector>
using std::string;
using std::vector;
namespace l
{
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;
fullpath = fs::path::make(basepath_,fusepath_);
rv = fs::lchown(fullpath,uid_,gid_);
return error::calc(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 = l::chown_loop_core(basepaths_[i],fusepath_,uid_,gid_,error);
}
return -error;
}
static
int
chown(Policy::Func::Action actionFunc_,
const Branches &branches_,
const uint64_t minfreespace_,
const char *fusepath_,
const uid_t uid_,
const gid_t gid_)
{
int rv;
vector<const string*> basepaths;
rv = actionFunc_(branches_,fusepath_,minfreespace_,basepaths);
if(rv == -1)
return -errno;
return l::chown_loop(basepaths,fusepath_,uid_,gid_);
}
}
namespace FUSE
{
int
chown(const char *fusepath_,
uid_t uid_,
gid_t gid_)
{
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
return l::chown(config.chown,
config.branches,
config.minfreespace,
fusepath_,
uid_,
gid_);
}
}

12
src/link.hpp → src/fuse_chown.hpp

@ -16,12 +16,10 @@
#pragma once #pragma once
namespace mergerfs
namespace FUSE
{ {
namespace fuse
{
int
link(const char *from,
const char *to);
}
int
chown(const char *fusepath_,
uid_t uid_,
gid_t gid_);
} }

62
src/create.cpp → src/fuse_create.cpp

@ -31,9 +31,8 @@
using std::string; using std::string;
using std::vector; using std::vector;
using namespace mergerfs;
namespace local
namespace l
{ {
static static
int int
@ -60,9 +59,9 @@ namespace local
int rv; int rv;
string fullpath; string fullpath;
fs::path::make(&createpath_,fusepath_,fullpath);
fullpath = fs::path::make(createpath_,fusepath_);
rv = local::create_core(fullpath,mode_,umask_,flags_);
rv = l::create_core(fullpath,mode_,umask_,flags_);
if(rv == -1) if(rv == -1)
return -errno; return -errno;
@ -103,39 +102,36 @@ namespace local
if(rv == -1) if(rv == -1)
return -errno; return -errno;
return local::create_core(*createpaths[0],
fusepath_,
mode_,
umask_,
flags_,
fh_);
return l::create_core(*createpaths[0],
fusepath_,
mode_,
umask_,
flags_,
fh_);
} }
} }
namespace mergerfs
namespace FUSE
{ {
namespace fuse
int
create(const char *fusepath_,
mode_t mode_,
fuse_file_info *ffi_)
{ {
int
create(const char *fusepath_,
mode_t mode_,
fuse_file_info *ffi_)
{
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
ffi_->direct_io = config.direct_io;
return local::create(config.getattr,
config.create,
config.branches,
config.minfreespace,
fusepath_,
mode_,
fc->umask,
ffi_->flags,
&ffi_->fh);
}
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
ffi_->direct_io = config.direct_io;
return l::create(config.getattr,
config.create,
config.branches,
config.minfreespace,
fusepath_,
mode_,
fc->umask,
ffi_->flags,
&ffi_->fh);
} }
} }

14
src/truncate.hpp → src/fuse_create.hpp

@ -16,14 +16,14 @@
#pragma once #pragma once
#include <fuse.h>
#include <sys/types.h> #include <sys/types.h>
namespace mergerfs
namespace FUSE
{ {
namespace fuse
{
int
truncate(const char *fusepath,
off_t size);
}
int
create(const char *fusepath_,
mode_t mode_,
fuse_file_info *ffi_);
} }

9
src/destroy.cpp → src/fuse_destroy.cpp

@ -14,14 +14,11 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
namespace mergerfs
namespace FUSE
{ {
namespace fuse
void
destroy(void *)
{ {
void
destroy(void *)
{
}
} }
} }

9
src/destroy.hpp → src/fuse_destroy.hpp

@ -16,11 +16,8 @@
#pragma once #pragma once
namespace mergerfs
namespace FUSE
{ {
namespace fuse
{
void
destroy(void *);
}
void
destroy(void *);
} }

54
src/fallocate.cpp → src/fuse_fallocate.cpp

@ -14,43 +14,43 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <fuse.h>
#include "errno.hpp" #include "errno.hpp"
#include "fileinfo.hpp" #include "fileinfo.hpp"
#include "fs_base_fallocate.hpp" #include "fs_base_fallocate.hpp"
static
int
_fallocate(const int fd,
const int mode,
const off_t offset,
const off_t len)
#include <fuse.h>
namespace l
{ {
int rv;
static
int
fallocate(const int fd_,
const int mode_,
const off_t offset_,
const off_t len_)
{
int rv;
rv = fs::fallocate(fd,mode,offset,len);
rv = fs::fallocate(fd_,mode_,offset_,len_);
return ((rv == -1) ? -errno : 0);
return ((rv == -1) ? -errno : 0);
}
} }
namespace mergerfs
namespace FUSE
{ {
namespace fuse
int
fallocate(const char *fusepath_,
int mode_,
off_t offset_,
off_t len_,
fuse_file_info *ffi_)
{ {
int
fallocate(const char *fusepath,
int mode,
off_t offset,
off_t len,
fuse_file_info *ffi)
{
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi->fh);
return _fallocate(fi->fd,
mode,
offset,
len);
}
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi_->fh);
return l::fallocate(fi->fd,
mode_,
offset_,
len_);
} }
} }

27
src/fuse_fallocate.hpp

@ -0,0 +1,27 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
namespace FUSE
{
int
fallocate(const char *fusepath_,
int mode_,
off_t offset_,
off_t len_,
fuse_file_info *ffi_);
}

47
src/fgetattr.cpp → src/fuse_fgetattr.cpp

@ -14,41 +14,42 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <fuse.h>
#include "errno.hpp" #include "errno.hpp"
#include "fileinfo.hpp" #include "fileinfo.hpp"
#include "fs_base_stat.hpp" #include "fs_base_stat.hpp"
#include "fs_inode.hpp" #include "fs_inode.hpp"
static
int
_fgetattr(const int fd,
struct stat &st)
#include <fuse.h>
namespace l
{ {
int rv;
static
int
fgetattr(const int fd_,
struct stat *st_)
{
int rv;
rv = fs::fstat(fd,st);
if(rv == -1)
return -errno;
rv = fs::fstat(fd_,st_);
if(rv == -1)
return -errno;
fs::inode::recompute(st);
fs::inode::recompute(st_);
return 0;
return 0;
}
} }
namespace mergerfs
namespace FUSE
{ {
namespace fuse
int
fgetattr(const char *fusepath_,
struct stat *st_,
fuse_file_info *ffi_)
{ {
int
fgetattr(const char *fusepath,
struct stat *st,
fuse_file_info *ffi)
{
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi->fh);
return ::_fgetattr(fi->fd,*st);
}
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi_->fh);
return l::fgetattr(fi->fd,st_);
} }
} }

14
src/ftruncate.hpp → src/fuse_fgetattr.hpp

@ -18,16 +18,14 @@
#include <fuse.h> #include <fuse.h>
#include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h> #include <unistd.h>
namespace mergerfs
namespace FUSE
{ {
namespace fuse
{
int
ftruncate(const char *fusepath,
off_t size,
fuse_file_info *fi);
}
int
fgetattr(const char *fusepath_,
struct stat *st_,
fuse_file_info *ffi_);
} }

40
src/flock.cpp → src/fuse_flock.cpp

@ -14,36 +14,36 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <fuse.h>
#include "errno.hpp" #include "errno.hpp"
#include "fileinfo.hpp" #include "fileinfo.hpp"
#include "fs_base_flock.hpp" #include "fs_base_flock.hpp"
static
int
_flock(const int fd,
const int operation)
#include <fuse.h>
namespace l
{ {
int rv;
static
int
flock(const int fd_,
const int operation_)
{
int rv;
rv = fs::flock(fd,operation);
rv = fs::flock(fd_,operation_);
return ((rv == -1) ? -errno : 0);
return ((rv == -1) ? -errno : 0);
}
} }
namespace mergerfs
namespace FUSE
{ {
namespace fuse
int
flock(const char *fusepath_,
fuse_file_info *ffi_,
int op_)
{ {
int
flock(const char *fusepath,
fuse_file_info *ffi,
int op)
{
FileInfo* fi = reinterpret_cast<FileInfo*>(ffi->fh);
return _flock(fi->fd,op);
}
FileInfo* fi = reinterpret_cast<FileInfo*>(ffi_->fh);
return l::flock(fi->fd,op_);
} }
} }

12
src/open.hpp → src/fuse_flock.hpp

@ -18,12 +18,10 @@
#include <fuse.h> #include <fuse.h>
namespace mergerfs
namespace FUSE
{ {
namespace fuse
{
int
open(const char *fusepath,
fuse_file_info *ffi);
}
int
flock(const char *fusepath_,
fuse_file_info *ffi_,
int op_);
} }

44
src/flush.cpp → src/fuse_flush.cpp

@ -14,39 +14,39 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <fuse.h>
#include "errno.hpp" #include "errno.hpp"
#include "fileinfo.hpp" #include "fileinfo.hpp"
#include "fs_base_close.hpp" #include "fs_base_close.hpp"
#include "fs_base_dup.hpp" #include "fs_base_dup.hpp"
static
int
_flush(const int fd)
#include <fuse.h>
namespace l
{ {
int rv;
static
int
flush(const int fd_)
{
int rv;
rv = fs::dup(fd);
if(rv == -1)
errno = EIO;
else
rv = fs::close(rv);
rv = fs::dup(fd_);
if(rv == -1)
errno = EIO;
else
rv = fs::close(rv);
return ((rv == -1) ? -errno : 0);
return ((rv == -1) ? -errno : 0);
}
} }
namespace mergerfs
namespace FUSE
{ {
namespace fuse
int
flush(const char *fusepath_,
fuse_file_info *ffi_)
{ {
int
flush(const char *fusepath,
fuse_file_info *ffi)
{
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi->fh);
return ::_flush(fi->fd);
}
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi_->fh);
return l::flush(fi->fd);
} }
} }

26
src/fuse_flush.hpp

@ -0,0 +1,26 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include <fuse.h>
namespace FUSE
{
int
flush(const char *path_,
fuse_file_info *ffi_);
}

48
src/fsync.cpp → src/fuse_fsync.cpp

@ -14,41 +14,41 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "errno.hpp"
#include "fileinfo.hpp"
#include "fs_base_fsync.hpp"
#include <fuse.h> #include <fuse.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include "errno.hpp"
#include "fileinfo.hpp"
#include "fs_base_fsync.hpp"
static
int
_fsync(const int fd,
const int isdatasync)
namespace l
{ {
int rv;
static
int
fsync(const int fd_,
const int isdatasync_)
{
int rv;
rv = (isdatasync ?
fs::fdatasync(fd) :
fs::fsync(fd));
rv = (isdatasync_ ?
fs::fdatasync(fd_) :
fs::fsync(fd_));
return ((rv == -1) ? -errno : 0);
return ((rv == -1) ? -errno : 0);
}
} }
namespace mergerfs
namespace FUSE
{ {
namespace fuse
int
fsync(const char *fusepath_,
int isdatasync_,
fuse_file_info *ffi_)
{ {
int
fsync(const char *fusepath,
int isdatasync,
fuse_file_info *ffi)
{
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi->fh);
return ::_fsync(fi->fd,isdatasync);
}
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi_->fh);
return l::fsync(fi->fd,isdatasync_);
} }
} }

12
src/releasedir.hpp → src/fuse_fsync.hpp

@ -18,12 +18,10 @@
#include <fuse.h> #include <fuse.h>
namespace mergerfs
namespace FUSE
{ {
namespace fuse
{
int
releasedir(const char *fusepath,
fuse_file_info *ffi);
}
int
fsync(const char *fusepath_,
int isdatasync_,
fuse_file_info *ffi_);
} }

46
src/fsyncdir.cpp → src/fuse_fsyncdir.cpp

@ -14,40 +14,40 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include "errno.hpp"
#include "dirinfo.hpp"
#include "fs_base_fsync.hpp"
#include <fuse.h> #include <fuse.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include "errno.hpp"
#include "dirinfo.hpp"
#include "fs_base_fsync.hpp"
static
int
_fsyncdir(const DirInfo *di,
const int isdatasync)
namespace l
{ {
int rv;
static
int
fsyncdir(const DirInfo *di_,
const int isdatasync_)
{
int rv;
rv = -1;
errno = ENOSYS;
rv = -1;
errno = ENOSYS;
return ((rv == -1) ? -errno : 0);
return ((rv == -1) ? -errno : 0);
}
} }
namespace mergerfs
namespace FUSE
{ {
namespace fuse
int
fsyncdir(const char *fusepath_,
int isdatasync_,
fuse_file_info *ffi_)
{ {
int
fsyncdir(const char *fusepath,
int isdatasync,
fuse_file_info *ffi)
{
DirInfo *di = reinterpret_cast<DirInfo*>(ffi->fh);
return ::_fsyncdir(di,isdatasync);
}
DirInfo *di = reinterpret_cast<DirInfo*>(ffi_->fh);
return l::fsyncdir(di,isdatasync_);
} }
} }

13
src/fsyncdir.hpp → src/fuse_fsyncdir.hpp

@ -18,13 +18,10 @@
#include <fuse.h> #include <fuse.h>
namespace mergerfs
namespace FUSE
{ {
namespace fuse
{
int
fsyncdir(const char *fusepath,
int isdatasync,
fuse_file_info *ffi);
}
int
fsyncdir(const char *fusepath_,
int isdatasync_,
fuse_file_info *ffi_);
} }

40
src/ftruncate.cpp → src/fuse_ftruncate.cpp

@ -14,36 +14,36 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <fuse.h>
#include "errno.hpp" #include "errno.hpp"
#include "fileinfo.hpp" #include "fileinfo.hpp"
#include "fs_base_ftruncate.hpp" #include "fs_base_ftruncate.hpp"
static
int
_ftruncate(const int fd,
const off_t size)
#include <fuse.h>
namespace l
{ {
int rv;
static
int
ftruncate(const int fd_,
const off_t size_)
{
int rv;
rv = fs::ftruncate(fd,size);
rv = fs::ftruncate(fd_,size_);
return ((rv == -1) ? -errno : 0);
return ((rv == -1) ? -errno : 0);
}
} }
namespace mergerfs
namespace FUSE
{ {
namespace fuse
int
ftruncate(const char *fusepath_,
off_t size_,
fuse_file_info *ffi_)
{ {
int
ftruncate(const char *fusepath,
off_t size,
fuse_file_info *ffi)
{
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi->fh);
return ::_ftruncate(fi->fd,size);
}
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi_->fh);
return l::ftruncate(fi->fd,size_);
} }
} }

14
src/create.hpp → src/fuse_ftruncate.hpp

@ -19,14 +19,12 @@
#include <fuse.h> #include <fuse.h>
#include <sys/types.h> #include <sys/types.h>
#include <unistd.h>
namespace mergerfs
namespace FUSE
{ {
namespace fuse
{
int
create(const char *fusepath,
mode_t mode,
fuse_file_info *ffi);
}
int
ftruncate(const char *fusepath_,
off_t size_,
fuse_file_info *ffi_);
} }

117
src/fuse_getattr.cpp

@ -0,0 +1,117 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.hpp"
#include "errno.hpp"
#include "fs_base_stat.hpp"
#include "fs_inode.hpp"
#include "fs_path.hpp"
#include "rwlock.hpp"
#include "symlinkify.hpp"
#include "ugid.hpp"
#include <fuse.h>
#include <string>
#include <vector>
using std::string;
using std::vector;
namespace l
{
static
int
getattr_controlfile(struct stat *st_)
{
static const uid_t uid = ::getuid();
static const gid_t gid = ::getgid();
static const time_t now = ::time(NULL);
st_->st_dev = 0;
st_->st_ino = fs::inode::MAGIC;
st_->st_mode = (S_IFREG|S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP|S_IROTH);
st_->st_nlink = 1;
st_->st_uid = uid;
st_->st_gid = gid;
st_->st_rdev = 0;
st_->st_size = 0;
st_->st_blksize = 512;
st_->st_blocks = 0;
st_->st_atime = now;
st_->st_mtime = now;
st_->st_ctime = now;
return 0;
}
static
int
getattr(Policy::Func::Search searchFunc_,
const Branches &branches_,
const uint64_t minfreespace_,
const char *fusepath_,
struct stat *st_,
const bool symlinkify_,
const time_t symlinkify_timeout_)
{
int rv;
string fullpath;
vector<const string*> basepaths;
rv = searchFunc_(branches_,fusepath_,minfreespace_,basepaths);
if(rv == -1)
return -errno;
fullpath = fs::path::make(basepaths[0],fusepath_);
rv = fs::lstat(fullpath,st_);
if(rv == -1)
return -errno;
if(symlinkify_ && symlinkify::can_be_symlink(*st_,symlinkify_timeout_))
st_->st_mode = symlinkify::convert(st_->st_mode);
fs::inode::recompute(st_);
return 0;
}
}
namespace FUSE
{
int
getattr(const char *fusepath_,
struct stat *st_)
{
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
if(fusepath_ == config.controlfile)
return l::getattr_controlfile(st_);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
return l::getattr(config.getattr,
config.branches,
config.minfreespace,
fusepath_,
st_,
config.symlinkify,
config.symlinkify_timeout);
}
}

11
src/getattr.hpp → src/fuse_getattr.hpp

@ -20,12 +20,9 @@
#include <sys/stat.h> #include <sys/stat.h>
#include <unistd.h> #include <unistd.h>
namespace mergerfs
namespace FUSE
{ {
namespace fuse
{
int
getattr(const char *fusepath,
struct stat *buf);
}
int
getattr(const char *fusepath_,
struct stat *buf_);
} }

467
src/fuse_getxattr.cpp

@ -0,0 +1,467 @@
/*
Copyright (c) 2018, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.hpp"
#include "errno.hpp"
#include "fs_base_getxattr.hpp"
#include "fs_path.hpp"
#include "fs_statvfs_cache.hpp"
#include "rwlock.hpp"
#include "str.hpp"
#include "ugid.hpp"
#include "version.hpp"
#include <fuse.h>
#include <algorithm>
#include <set>
#include <sstream>
#include <string>
#include <vector>
#include <stdio.h>
#include <string.h>
static const char SECURITY_CAPABILITY[] = "security.capability";
using std::string;
using std::vector;
using std::set;
namespace l
{
static
bool
is_attrname_security_capability(const char *attrname_)
{
return (strcmp(attrname_,SECURITY_CAPABILITY) == 0);
}
static
int
lgetxattr(const string &path_,
const char *attrname_,
void *value_,
const size_t size_)
{
int rv;
rv = fs::lgetxattr(path_,attrname_,value_,size_);
return ((rv == -1) ? -errno : rv);
}
static
void
getxattr_controlfile_fusefunc_policy(const Config &config_,
const string &attr_,
string &attrvalue_)
{
FuseFunc fusefunc;
fusefunc = FuseFunc::find(attr_);
if(fusefunc != FuseFunc::invalid)
attrvalue_ = (std::string)*config_.policies[(FuseFunc::Enum::Type)*fusefunc];
}
static
void
getxattr_controlfile_category_policy(const Config &config_,
const string &attr_,
string &attrvalue_)
{
Category cat;
cat = Category::find(attr_);
if(cat != Category::invalid)
{
vector<string> policies;
for(int i = FuseFunc::Enum::BEGIN; i < FuseFunc::Enum::END; i++)
{
if(cat == (Category::Enum::Type)*FuseFunc::fusefuncs[i])
policies.push_back(*config_.policies[i]);
}
std::sort(policies.begin(),policies.end());
policies.erase(std::unique(policies.begin(),policies.end()),
policies.end());
attrvalue_ = str::join(policies,',');
}
}
static
void
getxattr_controlfile_srcmounts(const Config &config_,
string &attrvalue_)
{
attrvalue_ = config_.branches.to_string();
}
static
void
getxattr_controlfile_branches(const Config &config_,
string &attrvalue_)
{
attrvalue_ = config_.branches.to_string(true);
}
static
void
getxattr_controlfile_uint64_t(const uint64_t uint_,
string &attrvalue_)
{
std::ostringstream os;
os << uint_;
attrvalue_ = os.str();
}
static
void
getxattr_controlfile_time_t(const time_t time,
string &attrvalue)
{
std::ostringstream os;
os << time;
attrvalue = os.str();
}
static
void
getxattr_controlfile_bool(const bool boolvalue,
string &attrvalue)
{
attrvalue = (boolvalue ? "true" : "false");
}
static
void
getxattr_controlfile_errno(const int errno_,
string &attrvalue)
{
switch(errno_)
{
case 0:
attrvalue = "passthrough";
break;
case ENOATTR:
attrvalue = "noattr";
break;
case ENOSYS:
attrvalue = "nosys";
break;
default:
attrvalue = "ERROR";
break;
}
}
static
void
getxattr_controlfile_statfs(const Config::StatFS::Enum enum_,
string &attrvalue_)
{
switch(enum_)
{
case Config::StatFS::BASE:
attrvalue_ = "base";
break;
case Config::StatFS::FULL:
attrvalue_ = "full";
break;
default:
attrvalue_ = "ERROR";
break;
}
}
static
void
getxattr_controlfile_statfsignore(const Config::StatFSIgnore::Enum enum_,
string &attrvalue_)
{
switch(enum_)
{
case Config::StatFSIgnore::NONE:
attrvalue_ = "none";
break;
case Config::StatFSIgnore::RO:
attrvalue_ = "ro";
break;
case Config::StatFSIgnore::NC:
attrvalue_ = "nc";
break;
default:
attrvalue_ = "ERROR";
break;
}
}
static
void
getxattr_controlfile_policies(const Config &config,
string &attrvalue)
{
size_t i = Policy::Enum::begin();
attrvalue = (string)Policy::policies[i];
for(i++; i < Policy::Enum::end(); i++)
attrvalue += ',' + (string)Policy::policies[i];
}
static
void
getxattr_controlfile_version(string &attrvalue)
{
attrvalue = MERGERFS_VERSION;
if(attrvalue.empty())
attrvalue = "unknown_possible_problem_with_build";
}
static
void
getxattr_pid(string &attrvalue)
{
int pid;
char buf[32];
pid = getpid();
snprintf(buf,sizeof(buf),"%d",pid);
attrvalue = buf;
}
static
int
getxattr_controlfile(const Config &config,
const char *attrname,
char *buf,
const size_t count)
{
size_t len;
string attrvalue;
vector<string> attr;
str::split(attr,attrname,'.');
if((attr[0] != "user") || (attr[1] != "mergerfs"))
return -ENOATTR;
switch(attr.size())
{
case 3:
if(attr[2] == "srcmounts")
l::getxattr_controlfile_srcmounts(config,attrvalue);
else if(attr[2] == "branches")
l::getxattr_controlfile_branches(config,attrvalue);
else if(attr[2] == "minfreespace")
l::getxattr_controlfile_uint64_t(config.minfreespace,attrvalue);
else if(attr[2] == "moveonenospc")
l::getxattr_controlfile_bool(config.moveonenospc,attrvalue);
else if(attr[2] == "dropcacheonclose")
l::getxattr_controlfile_bool(config.dropcacheonclose,attrvalue);
else if(attr[2] == "symlinkify")
l::getxattr_controlfile_bool(config.symlinkify,attrvalue);
else if(attr[2] == "symlinkify_timeout")
l::getxattr_controlfile_time_t(config.symlinkify_timeout,attrvalue);
else if(attr[2] == "nullrw")
l::getxattr_controlfile_bool(config.nullrw,attrvalue);
else if(attr[2] == "ignorepponrename")
l::getxattr_controlfile_bool(config.ignorepponrename,attrvalue);
else if(attr[2] == "security_capability")
l::getxattr_controlfile_bool(config.security_capability,attrvalue);
else if(attr[2] == "xattr")
l::getxattr_controlfile_errno(config.xattr,attrvalue);
else if(attr[2] == "link_cow")
l::getxattr_controlfile_bool(config.link_cow,attrvalue);
else if(attr[2] == "statfs")
l::getxattr_controlfile_statfs(config.statfs,attrvalue);
else if(attr[2] == "statfs_ignore")
l::getxattr_controlfile_statfsignore(config.statfs_ignore,attrvalue);
else if(attr[2] == "policies")
l::getxattr_controlfile_policies(config,attrvalue);
else if(attr[2] == "version")
l::getxattr_controlfile_version(attrvalue);
else if(attr[2] == "pid")
l::getxattr_pid(attrvalue);
else if(attr[2] == "direct_io")
l::getxattr_controlfile_bool(config.direct_io,attrvalue);
break;
case 4:
if(attr[2] == "category")
l::getxattr_controlfile_category_policy(config,attr[3],attrvalue);
else if(attr[2] == "func")
l::getxattr_controlfile_fusefunc_policy(config,attr[3],attrvalue);
else if((attr[2] == "cache") && (attr[3] == "open"))
l::getxattr_controlfile_uint64_t(config.open_cache.timeout,attrvalue);
else if((attr[2] == "cache") && (attr[3] == "statfs"))
l::getxattr_controlfile_uint64_t(fs::statvfs_cache_timeout(),attrvalue);
break;
}
if(attrvalue.empty())
return -ENOATTR;
len = attrvalue.size();
if(count == 0)
return len;
if(count < len)
return -ERANGE;
memcpy(buf,attrvalue.c_str(),len);
return (int)len;
}
static
int
getxattr_from_string(char *destbuf,
const size_t destbufsize,
const string &src)
{
const size_t srcbufsize = src.size();
if(destbufsize == 0)
return srcbufsize;
if(srcbufsize > destbufsize)
return -ERANGE;
memcpy(destbuf,src.data(),srcbufsize);
return srcbufsize;
}
static
int
getxattr_user_mergerfs_allpaths(const Branches &branches_,
const char *fusepath,
char *buf,
const size_t count)
{
string concated;
vector<string> paths;
vector<string> branches;
branches_.to_paths(branches);
fs::findallfiles(branches,fusepath,paths);
concated = str::join(paths,'\0');
return l::getxattr_from_string(buf,count,concated);
}
static
int
getxattr_user_mergerfs(const string &basepath,
const char *fusepath,
const string &fullpath,
const Branches &branches_,
const char *attrname,
char *buf,
const size_t count)
{
vector<string> attr;
str::split(attr,attrname,'.');
if(attr[2] == "basepath")
return l::getxattr_from_string(buf,count,basepath);
else if(attr[2] == "relpath")
return l::getxattr_from_string(buf,count,fusepath);
else if(attr[2] == "fullpath")
return l::getxattr_from_string(buf,count,fullpath);
else if(attr[2] == "allpaths")
return l::getxattr_user_mergerfs_allpaths(branches_,fusepath,buf,count);
return -ENOATTR;
}
static
int
getxattr(Policy::Func::Search searchFunc,
const Branches &branches_,
const size_t minfreespace,
const char *fusepath,
const char *attrname,
char *buf,
const size_t count)
{
int rv;
string fullpath;
vector<const string*> basepaths;
rv = searchFunc(branches_,fusepath,minfreespace,basepaths);
if(rv == -1)
return -errno;
fullpath = fs::path::make(basepaths[0],fusepath);
if(str::isprefix(attrname,"user.mergerfs."))
return l::getxattr_user_mergerfs(*basepaths[0],
fusepath,
fullpath,
branches_,
attrname,
buf,
count);
return l::lgetxattr(fullpath,attrname,buf,count);
}
}
namespace FUSE
{
int
getxattr(const char *fusepath,
const char *attrname,
char *buf,
size_t count)
{
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
if(fusepath == config.controlfile)
return l::getxattr_controlfile(config,
attrname,
buf,
count);
if((config.security_capability == false) &&
l::is_attrname_security_capability(attrname))
return -ENOATTR;
if(config.xattr)
return -config.xattr;
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
return l::getxattr(config.getxattr,
config.branches,
config.minfreespace,
fusepath,
attrname,
buf,
count);
}
}

14
src/chown.hpp → src/fuse_getxattr.hpp

@ -16,13 +16,11 @@
#pragma once #pragma once
namespace mergerfs
namespace FUSE
{ {
namespace fuse
{
int
chown(const char *fusepath,
uid_t uid,
gid_t gid);
}
int
getxattr(const char *fusepath_,
const char *attrname_,
char *buf_,
size_t count_);
} }

27
src/init.cpp → src/fuse_init.cpp

@ -14,27 +14,24 @@
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/ */
#include <fuse.h>
#include "config.hpp" #include "config.hpp"
#include "ugid.hpp" #include "ugid.hpp"
namespace mergerfs
#include <fuse.h>
namespace FUSE
{ {
namespace fuse
void *
init(fuse_conn_info *conn_)
{ {
void *
init(fuse_conn_info *conn)
{
ugid::init();
ugid::init();
conn->want |= FUSE_CAP_ASYNC_READ;
conn->want |= FUSE_CAP_ATOMIC_O_TRUNC;
conn->want |= FUSE_CAP_BIG_WRITES;
conn->want |= FUSE_CAP_DONT_MASK;
conn->want |= FUSE_CAP_IOCTL_DIR;
conn_->want |= FUSE_CAP_ASYNC_READ;
conn_->want |= FUSE_CAP_ATOMIC_O_TRUNC;
conn_->want |= FUSE_CAP_BIG_WRITES;
conn_->want |= FUSE_CAP_DONT_MASK;
conn_->want |= FUSE_CAP_IOCTL_DIR;
return &Config::get_writable();
}
return &Config::get_writable();
} }
} }

11
src/init.hpp → src/fuse_init.hpp

@ -16,11 +16,10 @@
#pragma once #pragma once
namespace mergerfs
#include <fuse.h>
namespace FUSE
{ {
namespace fuse
{
void *
init(fuse_conn_info *conn);
}
void *
init(fuse_conn_info *conn_);
} }

49
src/ioctl.cpp → src/fuse_ioctl.cpp

@ -34,9 +34,8 @@
using std::string; using std::string;
using std::vector; using std::vector;
using namespace mergerfs;
namespace local
namespace l
{ {
static static
int int
@ -59,7 +58,7 @@ namespace local
{ {
FileInfo *fi = reinterpret_cast<FileInfo*>(ffi_->fh); FileInfo *fi = reinterpret_cast<FileInfo*>(ffi_->fh);
return local::ioctl(fi->fd,cmd_,data_);
return l::ioctl(fi->fd,cmd_,data_);
} }
@ -85,14 +84,14 @@ namespace local
if(rv == -1) if(rv == -1)
return -errno; return -errno;
fs::path::make(basepaths[0],fusepath_,fullpath);
fullpath = fs::path::make(basepaths[0],fusepath_);
const int flags = O_RDONLY | O_NOATIME | O_NONBLOCK; const int flags = O_RDONLY | O_NOATIME | O_NONBLOCK;
fd = fs::open(fullpath,flags); fd = fs::open(fullpath,flags);
if(fd == -1) if(fd == -1)
return -errno; return -errno;
rv = local::ioctl(fd,cmd_,data_);
rv = l::ioctl(fd,cmd_,data_);
fs::close(fd); fs::close(fd);
@ -111,31 +110,29 @@ namespace local
const ugid::Set ugid(fc->uid,fc->gid); const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock); const rwlock::ReadGuard readlock(&config.branches_lock);
return local::ioctl_dir_base(config.open,
config.branches,
config.minfreespace,
di->fusepath.c_str(),
cmd_,
data_);
return l::ioctl_dir_base(config.open,
config.branches,
config.minfreespace,
di->fusepath.c_str(),
cmd_,
data_);
} }
} }
namespace mergerfs
namespace FUSE
{ {
namespace fuse
int
ioctl(const char *fusepath_,
int cmd_,
void *arg_,
fuse_file_info *ffi_,
unsigned int flags_,
void *data_)
{ {
int
ioctl(const char *fusepath_,
int cmd_,
void *arg_,
fuse_file_info *ffi_,
unsigned int flags_,
void *data_)
{
if(flags_ & FUSE_IOCTL_DIR)
return local::ioctl_dir(ffi_,cmd_,data_);
return local::ioctl_file(ffi_,cmd_,data_);
}
if(flags_ & FUSE_IOCTL_DIR)
return l::ioctl_dir(ffi_,cmd_,data_);
return l::ioctl_file(ffi_,cmd_,data_);
} }
} }

16
src/fsync.hpp → src/fuse_ioctl.hpp

@ -18,13 +18,13 @@
#include <fuse.h> #include <fuse.h>
namespace mergerfs
namespace FUSE
{ {
namespace fuse
{
int
fsync(const char *fusepath,
int isdatasync,
fuse_file_info *fi);
}
int
ioctl(const char *fusepath_,
int cmd_,
void *arg_,
fuse_file_info *ffi_,
unsigned int flags_,
void *data_);
} }

249
src/fuse_link.cpp

@ -0,0 +1,249 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.hpp"
#include "errno.hpp"
#include "fs_base_link.hpp"
#include "fs_clonepath.hpp"
#include "fs_path.hpp"
#include "rv.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
#include <fuse.h>
#include <string>
#include <vector>
using std::string;
using std::vector;
namespace l
{
static
int
link_create_path_core(const string &oldbasepath_,
const string &newbasepath_,
const char *oldfusepath_,
const char *newfusepath_,
const int error_)
{
int rv;
string oldfullpath;
string newfullpath;
oldfullpath = fs::path::make(&oldbasepath_,oldfusepath_);
newfullpath = fs::path::make(&oldbasepath_,newfusepath_);
rv = fs::link(oldfullpath,newfullpath);
return error::calc(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 rv;
int error;
error = -1;
for(size_t i = 0, ei = oldbasepaths_.size(); i != ei; i++)
{
rv = fs::clonepath_as_root(newbasepath_,*oldbasepaths_[i],newfusedirpath_);
if(rv == -1)
error = error::calc(rv,error,errno);
else
error = l::link_create_path_core(*oldbasepaths_[i],newbasepath_,
oldfusepath_,newfusepath_,
error);
}
return -error;
}
static
int
link_create_path(Policy::Func::Search searchFunc_,
Policy::Func::Action actionFunc_,
const Branches &branches_,
const uint64_t minfreespace_,
const char *oldfusepath_,
const char *newfusepath_)
{
int rv;
string newfusedirpath;
vector<const string*> oldbasepaths;
vector<const string*> newbasepaths;
rv = actionFunc_(branches_,oldfusepath_,minfreespace_,oldbasepaths);
if(rv == -1)
return -errno;
newfusedirpath = fs::path::dirname(newfusepath_);
rv = searchFunc_(branches_,newfusedirpath,minfreespace_,newbasepaths);
if(rv == -1)
return -errno;
return l::link_create_path_loop(oldbasepaths,*newbasepaths[0],
oldfusepath_,newfusepath_,
newfusedirpath);
}
static
int
clonepath_if_would_create(Policy::Func::Search searchFunc_,
Policy::Func::Create createFunc_,
const Branches &branches_,
const uint64_t minfreespace_,
const string &oldbasepath_,
const char *oldfusepath_,
const char *newfusepath_)
{
int rv;
string newfusedirpath;
vector<const string*> newbasepath;
newfusedirpath = fs::path::dirname(newfusepath_);
rv = createFunc_(branches_,newfusedirpath,minfreespace_,newbasepath);
if(rv == -1)
return -1;
if(oldbasepath_ != *newbasepath[0])
return (errno=EXDEV,-1);
rv = searchFunc_(branches_,newfusedirpath,minfreespace_,newbasepath);
if(rv == -1)
return -1;
return fs::clonepath_as_root(*newbasepath[0],oldbasepath_,newfusedirpath);
}
static
int
link_preserve_path_core(Policy::Func::Search searchFunc_,
Policy::Func::Create createFunc_,
const Branches &branches_,
const uint64_t minfreespace_,
const string &oldbasepath_,
const char *oldfusepath_,
const char *newfusepath_,
const int error_)
{
int rv;
string oldfullpath;
string newfullpath;
oldfullpath = fs::path::make(&oldbasepath_,oldfusepath_);
newfullpath = fs::path::make(&oldbasepath_,newfusepath_);
rv = fs::link(oldfullpath,newfullpath);
if((rv == -1) && (errno == ENOENT))
{
rv = l::clonepath_if_would_create(searchFunc_,createFunc_,
branches_,minfreespace_,
oldbasepath_,
oldfusepath_,newfusepath_);
if(rv != -1)
rv = fs::link(oldfullpath,newfullpath);
}
return error::calc(rv,error_,errno);
}
static
int
link_preserve_path_loop(Policy::Func::Search searchFunc_,
Policy::Func::Create createFunc_,
const Branches &branches_,
const uint64_t minfreespace_,
const char *oldfusepath_,
const char *newfusepath_,
const vector<const string*> &oldbasepaths_)
{
int error;
error = -1;
for(size_t i = 0, ei = oldbasepaths_.size(); i != ei; i++)
{
error = l::link_preserve_path_core(searchFunc_,createFunc_,
branches_,minfreespace_,
*oldbasepaths_[i],
oldfusepath_,newfusepath_,
error);
}
return -error;
}
static
int
link_preserve_path(Policy::Func::Search searchFunc_,
Policy::Func::Action actionFunc_,
Policy::Func::Create createFunc_,
const Branches &branches_,
const uint64_t minfreespace_,
const char *oldfusepath_,
const char *newfusepath_)
{
int rv;
vector<const string*> oldbasepaths;
rv = actionFunc_(branches_,oldfusepath_,minfreespace_,oldbasepaths);
if(rv == -1)
return -errno;
return l::link_preserve_path_loop(searchFunc_,createFunc_,
branches_,minfreespace_,
oldfusepath_,newfusepath_,
oldbasepaths);
}
}
namespace FUSE
{
int
link(const char *from_,
const char *to_)
{
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
if(config.create->path_preserving() && !config.ignorepponrename)
return l::link_preserve_path(config.getattr,
config.link,
config.create,
config.branches,
config.minfreespace,
from_,
to_);
return l::link_create_path(config.link,
config.create,
config.branches,
config.minfreespace,
from_,
to_);
}
}

24
src/fuse_link.hpp

@ -0,0 +1,24 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
namespace FUSE
{
int
link(const char *from_,
const char *to_);
}

146
src/fuse_listxattr.cpp

@ -0,0 +1,146 @@
/*
Copyright (c) 2018, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "buildvector.hpp"
#include "category.hpp"
#include "config.hpp"
#include "errno.hpp"
#include "fs_base_listxattr.hpp"
#include "fs_path.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
#include "xattr.hpp"
#include <fuse.h>
#include <string>
#include <vector>
#include <string.h>
using std::string;
using std::vector;
namespace l
{
static
int
listxattr_controlfile(char *list_,
const size_t size_)
{
string xattrs;
const vector<string> strs =
buildvector<string>
("user.mergerfs.branches")
("user.mergerfs.cache.open")
("user.mergerfs.cache.statfs")
("user.mergerfs.direct_io")
("user.mergerfs.dropcacheonclose")
("user.mergerfs.ignorepponrename")
("user.mergerfs.link_cow")
("user.mergerfs.minfreespace")
("user.mergerfs.moveonenospc")
("user.mergerfs.nullrw")
("user.mergerfs.pid")
("user.mergerfs.policies")
("user.mergerfs.security_capability")
("user.mergerfs.srcmounts")
("user.mergerfs.statfs")
("user.mergerfs.statfs_ignore")
("user.mergerfs.symlinkify")
("user.mergerfs.symlinkify_timeout")
("user.mergerfs.version")
("user.mergerfs.xattr")
;
xattrs.reserve(1024);
for(size_t i = 0; i < strs.size(); i++)
xattrs += (strs[i] + '\0');
for(size_t i = Category::Enum::BEGIN; i < Category::Enum::END; i++)
xattrs += ("user.mergerfs.category." + (std::string)*Category::categories[i] + '\0');
for(size_t i = FuseFunc::Enum::BEGIN; i < FuseFunc::Enum::END; i++)
xattrs += ("user.mergerfs.func." + (std::string)*FuseFunc::fusefuncs[i] + '\0');
if(size_ == 0)
return xattrs.size();
if(size_ < xattrs.size())
return -ERANGE;
memcpy(list_,xattrs.c_str(),xattrs.size());
return xattrs.size();
}
static
int
listxattr(Policy::Func::Search searchFunc_,
const Branches &branches_,
const uint64_t minfreespace_,
const char *fusepath_,
char *list_,
const size_t size_)
{
int rv;
string fullpath;
vector<const string*> basepaths;
rv = searchFunc_(branches_,fusepath_,minfreespace_,basepaths);
if(rv == -1)
return -errno;
fullpath = fs::path::make(basepaths[0],fusepath_);
rv = fs::llistxattr(fullpath,list_,size_);
return ((rv == -1) ? -errno : rv);
}
}
namespace FUSE
{
int
listxattr(const char *fusepath_,
char *list_,
size_t size_)
{
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
if(fusepath_ == config.controlfile)
return l::listxattr_controlfile(list_,size_);
switch(config.xattr)
{
case 0:
break;
case ENOATTR:
return 0;
default:
return -config.xattr;
}
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
return l::listxattr(config.listxattr,
config.branches,
config.minfreespace,
fusepath_,
list_,
size_);
}
}

25
src/fuse_listxattr.hpp

@ -0,0 +1,25 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
namespace FUSE
{
int
listxattr(const char *fusepath_,
char *buf_,
size_t count_);
}

149
src/fuse_mkdir.cpp

@ -0,0 +1,149 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include <fuse.h>
#include <string>
#include <vector>
#include "config.hpp"
#include "errno.hpp"
#include "fs_acl.hpp"
#include "fs_base_mkdir.hpp"
#include "fs_clonepath.hpp"
#include "fs_path.hpp"
#include "rv.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
using std::string;
using std::vector;
namespace l
{
static
int
mkdir_core(const string &fullpath_,
mode_t mode_,
const mode_t umask_)
{
if(!fs::acl::dir_has_defaults(fullpath_))
mode_ &= ~umask_;
return fs::mkdir(fullpath_,mode_);
}
static
int
mkdir_loop_core(const string &createpath_,
const char *fusepath_,
const mode_t mode_,
const mode_t umask_,
const int error_)
{
int rv;
string fullpath;
fullpath = fs::path::make(createpath_,fusepath_);
rv = l::mkdir_core(fullpath,mode_,umask_);
return error::calc(rv,error_,errno);
}
static
int
mkdir_loop(const string &existingpath_,
const vector<const string*> &createpaths_,
const char *fusepath_,
const string &fusedirpath_,
const mode_t mode_,
const mode_t umask_)
{
int rv;
int error;
error = -1;
for(size_t i = 0, ei = createpaths_.size(); i != ei; i++)
{
rv = fs::clonepath_as_root(existingpath_,*createpaths_[i],fusedirpath_);
if(rv == -1)
error = error::calc(rv,error,errno);
else
error = l::mkdir_loop_core(*createpaths_[i],
fusepath_,
mode_,
umask_,
error);
}
return -error;
}
static
int
mkdir(Policy::Func::Search searchFunc_,
Policy::Func::Create createFunc_,
const Branches &branches_,
const uint64_t minfreespace_,
const char *fusepath_,
const mode_t mode_,
const mode_t umask_)
{
int rv;
string fusedirpath;
vector<const string*> createpaths;
vector<const string*> existingpaths;
fusedirpath = fs::path::dirname(fusepath_);
rv = searchFunc_(branches_,fusedirpath,minfreespace_,existingpaths);
if(rv == -1)
return -errno;
rv = createFunc_(branches_,fusedirpath,minfreespace_,createpaths);
if(rv == -1)
return -errno;
return l::mkdir_loop(*existingpaths[0],
createpaths,
fusepath_,
fusedirpath,
mode_,
umask_);
}
}
namespace FUSE
{
int
mkdir(const char *fusepath_,
mode_t mode_)
{
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
return l::mkdir(config.getattr,
config.mkdir,
config.branches,
config.minfreespace,
fusepath_,
mode_,
fc->umask);
}
}

24
src/fuse_mkdir.hpp

@ -0,0 +1,24 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
namespace FUSE
{
int
mkdir(const char *fusepath_,
mode_t mode_);
}

151
src/fuse_mknod.cpp

@ -0,0 +1,151 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#include "config.hpp"
#include "errno.hpp"
#include "fs_acl.hpp"
#include "fs_base_mknod.hpp"
#include "fs_clonepath.hpp"
#include "fs_path.hpp"
#include "rv.hpp"
#include "rwlock.hpp"
#include "ugid.hpp"
#include <fuse.h>
#include <string>
#include <vector>
using std::string;
using std::vector;
namespace l
{
static
inline
int
mknod_core(const string &fullpath_,
mode_t mode_,
const mode_t umask_,
const dev_t dev_)
{
if(!fs::acl::dir_has_defaults(fullpath_))
mode_ &= ~umask_;
return fs::mknod(fullpath_,mode_,dev_);
}
static
int
mknod_loop_core(const string &createpath_,
const char *fusepath_,
const mode_t mode_,
const mode_t umask_,
const dev_t dev_,
const int error_)
{
int rv;
string fullpath;
fullpath = fs::path::make(&createpath_,fusepath_);
rv = l::mknod_core(fullpath,mode_,umask_,dev_);
return error::calc(rv,error_,errno);
}
static
int
mknod_loop(const string &existingpath_,
const vector<const string*> &createpaths_,
const char *fusepath_,
const string &fusedirpath_,
const mode_t mode_,
const mode_t umask_,
const dev_t dev_)
{
int rv;
int error;
error = -1;
for(size_t i = 0, ei = createpaths_.size(); i != ei; i++)
{
rv = fs::clonepath_as_root(existingpath_,*createpaths_[i],fusedirpath_);
if(rv == -1)
error = error::calc(rv,error,errno);
else
error = l::mknod_loop_core(*createpaths_[i],
fusepath_,
mode_,umask_,dev_,error);
}
return -error;
}
static
int
mknod(Policy::Func::Search searchFunc_,
Policy::Func::Create createFunc_,
const Branches &branches_,
const uint64_t minfreespace_,
const char *fusepath_,
const mode_t mode_,
const mode_t umask_,
const dev_t dev_)
{
int rv;
string fusedirpath;
vector<const string*> createpaths;
vector<const string*> existingpaths;
fusedirpath = fs::path::dirname(fusepath_);
rv = searchFunc_(branches_,fusedirpath,minfreespace_,existingpaths);
if(rv == -1)
return -errno;
rv = createFunc_(branches_,fusedirpath,minfreespace_,createpaths);
if(rv == -1)
return -errno;
return l::mknod_loop(*existingpaths[0],createpaths,
fusepath_,fusedirpath,
mode_,umask_,dev_);
}
}
namespace FUSE
{
int
mknod(const char *fusepath_,
mode_t mode_,
dev_t rdev_)
{
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
return l::mknod(config.getattr,
config.mknod,
config.branches,
config.minfreespace,
fusepath_,
mode_,
fc->umask,
rdev_);
}
}

26
src/fuse_mknod.hpp

@ -0,0 +1,26 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
namespace FUSE
{
int
mknod(const char *fusepath_,
mode_t mode_,
dev_t rdev_);
}

45
src/open.cpp → src/fuse_open.cpp

@ -32,7 +32,7 @@
using std::string; using std::string;
using std::vector; using std::vector;
namespace local
namespace l
{ {
static static
int int
@ -45,7 +45,7 @@ namespace local
int fd; int fd;
string fullpath; string fullpath;
fs::path::make(basepath_,fusepath_,&fullpath);
fullpath = fs::path::make(basepath_,fusepath_);
if(link_cow_ && fs::cow::is_eligible(fullpath.c_str(),flags_)) if(link_cow_ && fs::cow::is_eligible(fullpath.c_str(),flags_))
fs::cow::break_link(fullpath.c_str()); fs::cow::break_link(fullpath.c_str());
@ -77,32 +77,29 @@ namespace local
if(rv == -1) if(rv == -1)
return -errno; return -errno;
return local::open_core(basepath,fusepath_,flags_,link_cow_,fh_);
return l::open_core(basepath,fusepath_,flags_,link_cow_,fh_);
} }
} }
namespace mergerfs
namespace FUSE
{ {
namespace fuse
int
open(const char *fusepath_,
fuse_file_info *ffi_)
{ {
int
open(const char *fusepath_,
fuse_file_info *ffi_)
{
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
ffi_->direct_io = config.direct_io;
return local::open(config.open,
config.open_cache,
config.branches,
config.minfreespace,
fusepath_,
ffi_->flags,
config.link_cow,
&ffi_->fh);
}
const fuse_context *fc = fuse_get_context();
const Config &config = Config::get(fc);
const ugid::Set ugid(fc->uid,fc->gid);
const rwlock::ReadGuard readlock(&config.branches_lock);
ffi_->direct_io = config.direct_io;
return l::open(config.open,
config.open_cache,
config.branches,
config.minfreespace,
fusepath_,
ffi_->flags,
config.link_cow,
&ffi_->fh);
} }
} }

26
src/fuse_open.hpp

@ -0,0 +1,26 @@
/*
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link>
Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
#pragma once
#include <fuse.h>
namespace FUSE
{
int
open(const char *fusepath_,
fuse_file_info *ffi_);
}

Some files were not shown because too many files changed in this diff

Loading…
Cancel
Save