From 538467b86dd17358fe98e6f001dfe000cf27f920 Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Sat, 19 Dec 2020 15:06:08 -0500 Subject: [PATCH] config: rework global config, remove rwlock, make branches RCU like Also added unit tests. Should have done separately but found a number of bugs. --- LICENSE | 2 +- Makefile | 32 +- src/branch.cpp | 366 +---- src/branch.hpp | 67 +- src/branches.cpp | 429 ++++++ src/branches.hpp | 94 ++ src/category.cpp | 49 + src/category.hpp | 93 +- src/config.cpp | 228 ++- src/config.hpp | 98 +- src/config_cachefiles.hpp | 1 + src/config_inodecalc.cpp | 1 + src/config_inodecalc.hpp | 5 +- src/config_moveonenospc.cpp | 9 +- src/config_moveonenospc.hpp | 14 +- src/config_nfsopenhack.cpp | 1 + src/config_nfsopenhack.hpp | 1 + src/config_readdir.cpp | 1 + src/config_readdir.hpp | 1 + src/config_statfs.cpp | 1 + src/config_statfs.hpp | 1 + src/config_statfsignore.cpp | 1 + src/config_xattr.cpp | 1 + src/config_xattr.hpp | 1 + src/dirinfo.hpp | 1 + src/endian.hpp | 1 + src/enum.hpp | 1 + src/fh.hpp | 1 + src/fileinfo.hpp | 1 + src/fixed_mem_pool.hpp | 4 +- src/from_string.cpp | 17 +- src/from_string.hpp | 2 +- src/fs_acl.cpp | 1 + src/fs_acl.hpp | 1 + src/fs_attr.hpp | 1 + src/fs_attr_linux.icpp | 1 + src/fs_attr_unsupported.icpp | 1 + src/fs_clonefile.cpp | 1 + src/fs_clonefile.hpp | 1 + src/fs_clonepath.cpp | 5 +- src/fs_clonepath.hpp | 1 + src/fs_close.hpp | 1 + src/fs_closedir.hpp | 1 + src/fs_copy_file_range.hpp | 4 +- src/fs_copy_file_range_linux.icpp | 4 +- src/fs_copy_file_range_unsupported.icpp | 4 +- src/fs_copydata.cpp | 1 + src/fs_copydata.hpp | 1 + src/fs_copydata_copy_file_range.cpp | 3 +- src/fs_copydata_copy_file_range.hpp | 3 +- src/fs_copydata_readwrite.cpp | 1 + src/fs_copydata_readwrite.hpp | 1 + src/fs_cow.cpp | 1 + src/fs_cow.hpp | 1 + src/fs_devid.hpp | 1 + src/fs_dirfd.hpp | 1 + src/fs_dup.hpp | 1 + src/fs_eaccess.hpp | 1 + src/fs_exists.hpp | 1 + src/fs_faccessat.hpp | 1 + src/fs_fadvise.hpp | 1 + src/fs_fadvise_posix.icpp | 1 + src/fs_fadvise_unsupported.icpp | 1 + src/fs_fallocate.hpp | 1 + src/fs_fallocate_linux.icpp | 1 + src/fs_fallocate_osx.icpp | 3 +- src/fs_fallocate_posix.icpp | 1 + src/fs_fallocate_unsupported.icpp | 1 + src/fs_fchmod.hpp | 1 + src/fs_fchmodat.hpp | 1 + src/fs_fchown.hpp | 1 + src/fs_fdatasync.hpp | 1 + src/fs_fgetxattr.hpp | 1 + src/fs_ficlone.hpp | 1 + src/fs_ficlone_linux.icpp | 1 + src/fs_ficlone_unsupported.icpp | 1 + src/fs_file_size.cpp | 3 +- src/fs_file_size.hpp | 3 +- src/fs_findallfiles.cpp | 1 + src/fs_findallfiles.hpp | 9 +- src/fs_findonfs.cpp | 32 +- src/fs_findonfs.hpp | 11 +- src/fs_flistxattr.hpp | 1 + src/fs_flock.hpp | 1 + src/fs_fsetxattr.hpp | 1 + src/fs_fstat.hpp | 1 + src/fs_fstatat.hpp | 1 + src/fs_fsync.hpp | 1 + src/fs_ftruncate.hpp | 1 + src/fs_futimens.hpp | 1 + src/fs_futimens_freebsd_11.hpp | 1 + src/fs_futimens_generic.hpp | 1 + src/fs_futimens_linux.hpp | 1 + src/fs_futimesat.hpp | 1 + src/fs_futimesat_generic.icpp | 1 + src/fs_futimesat_osx.icpp | 1 + src/fs_getdents64.cpp | 1 + src/fs_getdents64.hpp | 1 + src/fs_getfl.cpp | 1 + src/fs_getfl.hpp | 1 + src/fs_glob.cpp | 4 +- src/fs_glob.hpp | 1 + src/fs_has_space.cpp | 2 +- src/fs_has_space.hpp | 2 +- src/fs_info.cpp | 4 +- src/fs_info.hpp | 1 + src/fs_info_t.hpp | 3 +- src/fs_inode.cpp | 8 +- src/fs_inode.hpp | 2 +- src/fs_ioctl.hpp | 1 + src/fs_lchmod.hpp | 1 + src/fs_lchown.hpp | 1 + src/fs_lgetxattr.hpp | 1 + src/fs_link.hpp | 1 + src/fs_llistxattr.hpp | 1 + src/fs_lremovexattr.hpp | 1 + src/fs_lseek.hpp | 1 + src/fs_lsetxattr.hpp | 1 + src/fs_lstat.hpp | 1 + src/fs_lutimens.hpp | 1 + src/fs_mkdir.hpp | 1 + src/fs_mknod.hpp | 1 + src/fs_mktemp.cpp | 1 + src/fs_mktemp.hpp | 1 + src/fs_movefile.cpp | 21 +- src/fs_movefile.hpp | 19 +- src/fs_open.hpp | 1 + src/fs_opendir.hpp | 1 + src/fs_path.cpp | 9 +- src/fs_path.hpp | 1 + src/fs_read.hpp | 1 + src/fs_readdir.hpp | 1 + src/fs_readlink.hpp | 1 + src/fs_realpath.hpp | 1 + src/fs_realpathize.cpp | 1 + src/fs_realpathize.hpp | 1 + src/fs_remove.hpp | 1 + src/fs_rename.hpp | 1 + src/fs_rmdir.hpp | 1 + src/fs_sendfile.hpp | 1 + src/fs_sendfile_linux.icpp | 3 +- src/fs_sendfile_unsupported.icpp | 3 +- src/fs_setfl.cpp | 1 + src/fs_setfl.hpp | 1 + src/fs_stat.hpp | 1 + src/fs_stat_utils.hpp | 1 + src/fs_statvfs.hpp | 2 + src/fs_statvfs_cache.cpp | 3 +- src/fs_statvfs_cache.hpp | 4 +- src/fs_symlink.hpp | 1 + src/fs_truncate.hpp | 1 + src/fs_unlink.hpp | 1 + src/fs_utimensat_freebsd.hpp | 1 + src/fs_utimensat_generic.hpp | 1 + src/fs_utimensat_linux.hpp | 1 + src/fs_write.hpp | 1 + src/fs_xattr.cpp | 2 +- src/fs_xattr.hpp | 1 + src/func.cpp | 39 +- src/func.hpp | 267 ++-- src/func_category.cpp | 90 -- src/func_category.hpp | 69 - src/funcs.hpp | 44 +- src/fuse_access.cpp | 31 +- src/fuse_access.hpp | 1 + src/fuse_chmod.cpp | 26 +- src/fuse_chmod.hpp | 1 + src/fuse_chown.cpp | 16 +- src/fuse_chown.hpp | 1 + src/fuse_copy_file_range.cpp | 3 +- src/fuse_copy_file_range.hpp | 1 + src/fuse_create.cpp | 35 +- src/fuse_create.hpp | 3 +- src/fuse_destroy.hpp | 1 + src/fuse_fallocate.cpp | 3 +- src/fuse_fallocate.hpp | 1 + src/fuse_fchmod.cpp | 3 +- src/fuse_fchmod.hpp | 3 +- src/fuse_fchown.cpp | 3 +- src/fuse_fchown.hpp | 3 +- src/fuse_fgetattr.cpp | 11 +- src/fuse_fgetattr.hpp | 3 +- src/fuse_flock.cpp | 3 +- src/fuse_flock.hpp | 3 +- src/fuse_flush.cpp | 3 +- src/fuse_flush.hpp | 3 +- src/fuse_free_hide.cpp | 3 +- src/fuse_free_hide.hpp | 3 +- src/fuse_fsync.cpp | 3 +- src/fuse_fsync.hpp | 5 +- src/fuse_fsyncdir.cpp | 3 +- src/fuse_fsyncdir.hpp | 3 +- src/fuse_ftruncate.cpp | 3 +- src/fuse_ftruncate.hpp | 3 +- src/fuse_futimens.cpp | 3 +- src/fuse_futimens.hpp | 3 +- src/fuse_getattr.cpp | 46 +- src/fuse_getattr.hpp | 1 + src/fuse_getxattr.cpp | 47 +- src/fuse_getxattr.hpp | 1 + src/fuse_init.cpp | 25 +- src/fuse_init.hpp | 3 +- src/fuse_ioctl.cpp | 58 +- src/fuse_ioctl.hpp | 5 +- src/fuse_link.cpp | 65 +- src/fuse_link.hpp | 1 + src/fuse_listxattr.cpp | 26 +- src/fuse_listxattr.hpp | 1 + src/fuse_mkdir.cpp | 40 +- src/fuse_mkdir.hpp | 1 + src/fuse_mknod.cpp | 17 +- src/fuse_mknod.hpp | 1 + src/fuse_open.cpp | 38 +- src/fuse_open.hpp | 3 +- src/fuse_opendir.cpp | 7 +- src/fuse_opendir.hpp | 3 +- src/fuse_prepare_hide.cpp | 3 +- src/fuse_prepare_hide.hpp | 3 +- src/fuse_read.cpp | 3 +- src/fuse_read.hpp | 3 +- src/fuse_read_buf.cpp | 3 +- src/fuse_read_buf.hpp | 3 +- src/fuse_readdir.cpp | 15 +- src/fuse_readdir.hpp | 3 +- src/fuse_readdir_linux.cpp | 36 +- src/fuse_readdir_linux.hpp | 13 +- src/fuse_readdir_plus.cpp | 23 +- src/fuse_readdir_plus.hpp | 3 +- src/fuse_readdir_plus_linux.cpp | 46 +- src/fuse_readdir_plus_linux.hpp | 17 +- src/fuse_readdir_plus_posix.cpp | 50 +- src/fuse_readdir_plus_posix.hpp | 17 +- src/fuse_readdir_posix.cpp | 37 +- src/fuse_readdir_posix.hpp | 13 +- src/fuse_readlink.cpp | 20 +- src/fuse_readlink.hpp | 1 + src/fuse_release.cpp | 10 +- src/fuse_release.hpp | 3 +- src/fuse_releasedir.cpp | 3 +- src/fuse_releasedir.hpp | 3 +- src/fuse_removexattr.cpp | 21 +- src/fuse_removexattr.hpp | 1 + src/fuse_rename.cpp | 108 +- src/fuse_rename.hpp | 1 + src/fuse_rmdir.cpp | 16 +- src/fuse_rmdir.hpp | 1 + src/fuse_setxattr.cpp | 78 +- src/fuse_setxattr.hpp | 1 + src/fuse_statfs.cpp | 40 +- src/fuse_statfs.hpp | 1 + src/fuse_symlink.cpp | 31 +- src/fuse_symlink.hpp | 1 + src/fuse_truncate.cpp | 28 +- src/fuse_truncate.hpp | 1 + src/fuse_unlink.cpp | 16 +- src/fuse_unlink.hpp | 1 + src/fuse_utimens.cpp | 32 +- src/fuse_utimens.hpp | 1 + src/fuse_write.cpp | 13 +- src/fuse_write.hpp | 3 +- src/fuse_write_buf.cpp | 9 +- src/fuse_write_buf.hpp | 3 +- src/hw_cpu.cpp | 1 + src/hw_cpu.hpp | 1 + src/mergerfs.cpp | 25 +- src/num.cpp | 3 +- src/num.hpp | 5 +- src/option_parser.cpp | 190 +-- src/option_parser.hpp | 9 +- src/policies.cpp | 132 ++ src/policies.hpp | 121 ++ src/policy.cpp | 96 -- src/policy.hpp | 360 ++--- src/policy_all.cpp | 56 +- src/policy_all.hpp | 61 + src/policy_cache.cpp | 22 +- src/policy_cache.hpp | 12 +- src/policy_epall.cpp | 125 +- src/policy_epall.hpp | 64 + src/policy_epff.cpp | 121 +- src/policy_epff.hpp | 61 + src/policy_eplfs.cpp | 123 +- src/policy_eplfs.hpp | 61 + src/policy_eplus.cpp | 123 +- src/policy_eplus.hpp | 61 + src/policy_epmfs.cpp | 126 +- src/policy_epmfs.hpp | 64 + src/policy_eppfrd.cpp | 161 +- src/policy_eppfrd.hpp | 61 + src/policy_eprand.cpp | 48 +- src/policy_eprand.hpp | 61 + src/policy_erofs.cpp | 27 +- src/policy_erofs.hpp | 61 + src/policy_ff.cpp | 56 +- src/policy_ff.hpp | 61 + src/policy_lfs.cpp | 56 +- src/policy_lfs.hpp | 61 + src/policy_lus.cpp | 55 +- src/policy_lus.hpp | 61 + src/policy_mfs.cpp | 55 +- src/policy_mfs.hpp | 61 + src/policy_msplfs.cpp | 68 +- src/policy_msplfs.hpp | 61 + src/policy_msplus.cpp | 68 +- src/policy_msplus.hpp | 61 + src/policy_mspmfs.cpp | 65 +- src/policy_mspmfs.hpp | 61 + src/policy_msppfrd.cpp | 80 +- src/policy_msppfrd.hpp | 61 + src/policy_newest.cpp | 121 +- src/policy_newest.hpp | 61 + src/policy_pfrd.cpp | 68 +- src/policy_pfrd.hpp | 61 + src/policy_rand.cpp | 48 +- src/policy_rand.hpp | 61 + src/rnd.cpp | 4 +- src/rnd.hpp | 3 +- src/statvfs_util.hpp | 3 +- src/str.cpp | 25 +- src/str.hpp | 5 + src/{policy_invalid.cpp => strvec.hpp} | 19 +- src/to_string.cpp | 2 +- src/to_string.hpp | 2 +- src/tofrom_wrapper.hpp | 15 +- tests/acutest.h | 1794 +++++++++++++++++++++++ tests/tests.cpp | 283 ++++ tools/cppfind | 2 +- 327 files changed, 6646 insertions(+), 2991 deletions(-) create mode 100644 src/branches.cpp create mode 100644 src/branches.hpp create mode 100644 src/category.cpp delete mode 100644 src/func_category.cpp delete mode 100644 src/func_category.hpp create mode 100644 src/policies.cpp create mode 100644 src/policies.hpp delete mode 100644 src/policy.cpp create mode 100644 src/policy_all.hpp create mode 100644 src/policy_epall.hpp create mode 100644 src/policy_epff.hpp create mode 100644 src/policy_eplfs.hpp create mode 100644 src/policy_eplus.hpp create mode 100644 src/policy_epmfs.hpp create mode 100644 src/policy_eppfrd.hpp create mode 100644 src/policy_eprand.hpp create mode 100644 src/policy_erofs.hpp create mode 100644 src/policy_ff.hpp create mode 100644 src/policy_lfs.hpp create mode 100644 src/policy_lus.hpp create mode 100644 src/policy_mfs.hpp create mode 100644 src/policy_msplfs.hpp create mode 100644 src/policy_msplus.hpp create mode 100644 src/policy_mspmfs.hpp create mode 100644 src/policy_msppfrd.hpp create mode 100644 src/policy_newest.hpp create mode 100644 src/policy_pfrd.hpp create mode 100644 src/policy_rand.hpp rename src/{policy_invalid.cpp => strvec.hpp} (67%) create mode 100644 tests/acutest.h create mode 100644 tests/tests.cpp diff --git a/LICENSE b/LICENSE index f867f7d7..b4fdad4f 100644 --- a/LICENSE +++ b/LICENSE @@ -1,7 +1,7 @@ /* ISC License - Copyright (c) 2020, Antonio SJ Musumeci + Copyright (c) 2021, Antonio SJ Musumeci Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above diff --git a/Makefile b/Makefile index d98021c4..ddbc8a2e 100644 --- a/Makefile +++ b/Makefile @@ -58,13 +58,20 @@ LTO_FLAGS := endif SRC = $(wildcard src/*.cpp) -OBJS = $(SRC:src/%.cpp=build/%.o) -DEPS = $(SRC:src/%.cpp=build/%.d) +OBJS = $(SRC:src/%.cpp=build/.src/%.o) +DEPS = $(SRC:src/%.cpp=build/.src/%.d) + +TESTS = $(wildcard tests/*.cpp) +TESTS_OBJS = $(filter-out build/.src/mergerfs.o,$(OBJS)) +TESTS_OBJS += $(TESTS:tests/%.cpp=build/.tests/%.o) +TESTS_DEPS = $(TESTS:tests/%.cpp=build/.tests/%.d) +TESTS_DEPS += $(DEPS) + MANPAGE = mergerfs.1 CXXFLAGS ?= ${OPT_FLAGS} CXXFLAGS := \ ${CXXFLAGS} \ - -std=c++0x \ + -std=c++11 \ $(STATIC_FLAGS) \ $(LTO_FLAGS) \ -Wall \ @@ -77,6 +84,9 @@ FUSE_FLAGS = \ MFS_FLAGS = \ -DUSE_XATTR=$(USE_XATTR) \ -DUGID_USE_RWLOCK=$(UGID_USE_RWLOCK) +TESTS_FLAGS = \ + -Isrc \ + -DTESTS LDFLAGS := \ ${LDFLAGS} \ @@ -110,11 +120,19 @@ help: objects: version build/stamp $(MAKE) $(OBJS) +tests-objects: + $(MAKE) $(TESTS_OBJS) + build/mergerfs: libfuse objects $(CXX) $(CXXFLAGS) $(FUSE_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) $(OBJS) -o $@ libfuse/build/libfuse.a $(LDFLAGS) +build/tests: build/mergerfs tests-objects + $(CXX) $(CXXFLAGS) $(TESTS_FLAGS) $(FUSE_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) $(TESTS_OBJS) -o $@ libfuse/build/libfuse.a $(LDFLAGS) + mergerfs: build/mergerfs +tests: build/tests + changelog: ifeq ($(GIT_REPO),1) $(GIT2DEBCL) --name mergerfs > ChangeLog @@ -127,12 +145,16 @@ version: tools/update-version build/stamp: - $(MKDIR) -p build + $(MKDIR) -p build/.src build/.tests $(TOUCH) $@ -build/%.o: src/%.cpp +build/.src/%.o: src/%.cpp $(CXX) $(CXXFLAGS) $(FUSE_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) -c $< -o $@ +build/.tests/%.o: tests/%.cpp + $(CXX) $(CXXFLAGS) $(TESTS_FLAGS) $(FUSE_FLAGS) $(MFS_FLAGS) $(CPPFLAGS) -c $< -o $@ + + .PHONY: clean clean: rpm-clean $(RM) -rf build diff --git a/src/branch.cpp b/src/branch.cpp index 34d79442..a693b8df 100644 --- a/src/branch.cpp +++ b/src/branch.cpp @@ -18,21 +18,8 @@ #include "branch.hpp" #include "ef.hpp" -#include "from_string.hpp" -#include "fs_glob.hpp" -#include "fs_realpathize.hpp" -#include "nonstd/optional.hpp" +#include "errno.hpp" #include "num.hpp" -#include "str.hpp" - -#include - -#include -#include - -using std::string; -using std::vector; -using nonstd::optional; Branch::Branch(const uint64_t &default_minfreespace_) @@ -108,354 +95,3 @@ Branch::ro_or_nc(void) const return ((mode == Branch::Mode::RO) || (mode == Branch::Mode::NC)); } - -namespace l -{ - static - void - split(const std::string &s_, - std::string *instr_, - std::string *values_) - { - uint64_t offset; - - offset = s_.find_first_of('/'); - *instr_ = s_.substr(0,offset); - if(offset != std::string::npos) - *values_ = s_.substr(offset); - } -} - -Branches::Branches(const uint64_t &default_minfreespace_) - : default_minfreespace(default_minfreespace_) -{ - pthread_rwlock_init(&lock,NULL); -} - -namespace l -{ - static - int - parse_mode(const string &str_, - Branch::Mode *mode_) - { - if(str_ == "RW") - *mode_ = Branch::Mode::RW; - ef(str_ == "RO") - *mode_ = Branch::Mode::RO; - ef(str_ == "NC") - *mode_ = Branch::Mode::NC; - else - return -EINVAL; - - return 0; - } - - static - int - parse_minfreespace(const string &str_, - optional *minfreespace_) - { - int rv; - uint64_t uint64; - - rv = str::from(str_,&uint64); - if(rv < 0) - return rv; - - *minfreespace_ = uint64; - - return 0; - } - - static - int - parse_branch(const string &str_, - string *glob_, - Branch::Mode *mode_, - optional *minfreespace_) - { - int rv; - string options; - vector v; - - str::rsplit1(str_,'=',&v); - switch(v.size()) - { - case 1: - *glob_ = v[0]; - *mode_ = Branch::Mode::RW; - break; - case 2: - *glob_ = v[0]; - options = v[1]; - v.clear(); - str::split(options,',',&v); - switch(v.size()) - { - case 2: - rv = l::parse_minfreespace(v[1],minfreespace_); - if(rv < 0) - return rv; - case 1: - rv = l::parse_mode(v[0],mode_); - if(rv < 0) - return rv; - break; - case 0: - return -EINVAL; - } - break; - default: - return -EINVAL; - } - - return 0; - } - - static - int - parse(const string &str_, - const uint64_t &default_minfreespace_, - BranchVec *branches_) - { - int rv; - string glob; - vector globbed; - optional minfreespace; - Branch branch(default_minfreespace_); - - rv = l::parse_branch(str_,&glob,&branch.mode,&minfreespace); - if(rv < 0) - return rv; - - if(minfreespace.has_value()) - branch.set_minfreespace(minfreespace.value()); - - fs::glob(glob,&globbed); - fs::realpathize(&globbed); - for(size_t i = 0; i < globbed.size(); i++) - { - branch.path = globbed[i]; - branches_->push_back(branch); - } - - return 0; - } - - static - int - set(const std::string &str_, - Branches *branches_) - { - int rv; - vector paths; - BranchVec tmp_branchvec; - - str::split(str_,':',&paths); - - for(size_t i = 0; i < paths.size(); i++) - { - rv = l::parse(paths[i],branches_->default_minfreespace,&tmp_branchvec); - if(rv < 0) - return rv; - } - - branches_->vec.clear(); - branches_->vec.insert(branches_->vec.end(), - tmp_branchvec.begin(), - tmp_branchvec.end()); - - return 0; - } - - static - int - add_begin(const std::string &str_, - Branches *branches_) - { - int rv; - vector paths; - BranchVec tmp_branchvec; - - str::split(str_,':',&paths); - - for(size_t i = 0; i < paths.size(); i++) - { - rv = l::parse(paths[i],branches_->default_minfreespace,&tmp_branchvec); - if(rv < 0) - return rv; - } - - branches_->vec.insert(branches_->vec.begin(), - tmp_branchvec.begin(), - tmp_branchvec.end()); - - return 0; - } - - static - int - add_end(const std::string &str_, - Branches *branches_) - { - int rv; - vector paths; - BranchVec tmp_branchvec; - - str::split(str_,':',&paths); - - for(size_t i = 0; i < paths.size(); i++) - { - rv = l::parse(paths[i],branches_->default_minfreespace,&tmp_branchvec); - if(rv < 0) - return rv; - } - - branches_->vec.insert(branches_->vec.end(), - tmp_branchvec.begin(), - tmp_branchvec.end()); - - return 0; - } - - static - int - erase_begin(BranchVec *branches_) - { - branches_->erase(branches_->begin()); - - return 0; - } - - static - int - erase_end(BranchVec *branches_) - { - branches_->pop_back(); - - return 0; - } - - static - int - erase_fnmatch(const std::string &str_, - Branches *branches_) - { - vector patterns; - - str::split(str_,':',&patterns); - - for(BranchVec::iterator i = branches_->vec.begin(); - i != branches_->vec.end();) - { - int match = FNM_NOMATCH; - - for(vector::const_iterator pi = patterns.begin(); - pi != patterns.end() && match != 0; - ++pi) - { - match = ::fnmatch(pi->c_str(),i->path.c_str(),0); - } - - i = ((match == 0) ? branches_->vec.erase(i) : (i+1)); - } - - return 0; - } -} - -int -Branches::from_string(const std::string &s_) -{ - rwlock::WriteGuard guard(lock); - - std::string instr; - std::string values; - - l::split(s_,&instr,&values); - - if(instr == "+") - return l::add_end(values,this); - if(instr == "+<") - return l::add_begin(values,this); - if(instr == "+>") - return l::add_end(values,this); - if(instr == "-") - return l::erase_fnmatch(values,this); - if(instr == "-<") - return l::erase_begin(&vec); - if(instr == "->") - return l::erase_end(&vec); - if(instr == "=") - return l::set(values,this); - if(instr.empty()) - return l::set(values,this); - - return -EINVAL; -} - -string -Branches::to_string(void) const -{ - rwlock::ReadGuard guard(lock); - - string tmp; - - for(size_t i = 0; i < vec.size(); i++) - { - const Branch &branch = vec[i]; - - tmp += branch.to_string(); - tmp += ':'; - } - - if(*tmp.rbegin() == ':') - tmp.erase(tmp.size() - 1); - - return tmp; -} - -void -Branches::to_paths(vector &vec_) const -{ - rwlock::ReadGuard guard(lock); - - for(size_t i = 0; i < vec.size(); i++) - { - const Branch &branch = vec[i]; - - vec_.push_back(branch.path); - } -} - -SrcMounts::SrcMounts(Branches &b_) - : _branches(b_) -{ - -} - -int -SrcMounts::from_string(const std::string &s_) -{ - return _branches.from_string(s_); -} - -std::string -SrcMounts::to_string(void) const -{ - rwlock::ReadGuard guard(_branches.lock); - - std::string rv; - - for(uint64_t i = 0; i < _branches.vec.size(); i++) - { - rv += _branches.vec[i].path; - rv += ':'; - } - - if(*rv.rbegin() == ':') - rv.erase(rv.size() - 1); - - return rv; -} diff --git a/src/branch.hpp b/src/branch.hpp index 421f0e3c..588aa79a 100644 --- a/src/branch.hpp +++ b/src/branch.hpp @@ -18,81 +18,50 @@ #pragma once -#include "rwlock.hpp" -#include "tofrom_string.hpp" #include "nonstd/optional.hpp" +#include "strvec.hpp" +#include "tofrom_string.hpp" +#include #include #include -#include -#include -class Branch : public ToFromString +class Branch final : public ToFromString { public: - Branch(const uint64_t &default_minfreespace); + typedef std::vector Vector; public: - int from_string(const std::string &str); - std::string to_string(void) const; + Branch(const uint64_t &default_minfreespace_); public: enum class Mode { - INVALID, - RO, - RW, - NC + INVALID, + RO, + RW, + NC }; -public: - Mode mode; - std::string path; - uint64_t minfreespace() const; - -public: - void set_minfreespace(const uint64_t minfreespace); - public: bool ro(void) const; bool nc(void) const; bool ro_or_nc(void) const; -private: - nonstd::optional _minfreespace; - const uint64_t *_default_minfreespace; -}; - -typedef std::vector BranchVec; - -class Branches : public ToFromString -{ -public: - Branches(const uint64_t &default_minfreespace_); - -public: - int from_string(const std::string &str); - std::string to_string(void) const; - -public: - void to_paths(std::vector &vec) const; - public: - mutable pthread_rwlock_t lock; - BranchVec vec; - const uint64_t &default_minfreespace; -}; + int from_string(const std::string &str) final; + std::string to_string(void) const final; -class SrcMounts : public ToFromString -{ public: - SrcMounts(Branches &b_); + uint64_t minfreespace() const; + void set_minfreespace(const uint64_t); public: - int from_string(const std::string &str); - std::string to_string(void) const; + Mode mode; + std::string path; private: - Branches &_branches; + nonstd::optional _minfreespace; + const uint64_t *_default_minfreespace; }; diff --git a/src/branches.cpp b/src/branches.cpp new file mode 100644 index 00000000..b8ca5ebb --- /dev/null +++ b/src/branches.cpp @@ -0,0 +1,429 @@ +/* + ISC License + + Copyright (c) 2021, Antonio SJ Musumeci + + 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 "branches.hpp" +#include "ef.hpp" +#include "errno.hpp" +#include "from_string.hpp" +#include "fs_glob.hpp" +#include "fs_realpathize.hpp" +#include "nonstd/optional.hpp" +#include "num.hpp" +#include "str.hpp" + +#include + +#include + +using std::string; +using std::vector; +using nonstd::optional; + + +Branches::Impl::Impl(const uint64_t &default_minfreespace_) + : _default_minfreespace(default_minfreespace_) +{ +} + +Branches::Impl& +Branches::Impl::operator=(Branches::Impl &rval_) +{ + auto this_base = dynamic_cast(this); + auto rval_base = dynamic_cast(&rval_); + + *this_base = *rval_base; + + return *this; +} + +Branches::Impl& +Branches::Impl::operator=(Branches::Impl &&rval_) +{ + auto this_base = dynamic_cast(this); + auto rval_base = dynamic_cast(&rval_); + + *this_base = std::move(*rval_base); + + return *this; +} + +const +uint64_t& +Branches::Impl::minfreespace(void) const +{ + return _default_minfreespace; +} + +namespace l +{ + static + void + split(const std::string &s_, + std::string *instr_, + std::string *values_) + { + uint64_t offset; + + offset = s_.find_first_of('/'); + *instr_ = s_.substr(0,offset); + if(offset != std::string::npos) + *values_ = s_.substr(offset); + } + + static + int + parse_mode(const string &str_, + Branch::Mode *mode_) + { + if(str_ == "RW") + *mode_ = Branch::Mode::RW; + ef(str_ == "RO") + *mode_ = Branch::Mode::RO; + ef(str_ == "NC") + *mode_ = Branch::Mode::NC; + else + return -EINVAL; + + return 0; + } + + static + int + parse_minfreespace(const string &str_, + optional *minfreespace_) + { + int rv; + uint64_t uint64; + + rv = str::from(str_,&uint64); + if(rv < 0) + return rv; + + *minfreespace_ = uint64; + + return 0; + } + + static + int + parse_branch(const string &str_, + string *glob_, + Branch::Mode *mode_, + optional *minfreespace_) + { + int rv; + string options; + vector v; + + str::rsplit1(str_,'=',&v); + switch(v.size()) + { + case 1: + *glob_ = v[0]; + *mode_ = Branch::Mode::RW; + break; + case 2: + *glob_ = v[0]; + options = v[1]; + v.clear(); + str::split(options,',',&v); + switch(v.size()) + { + case 2: + rv = l::parse_minfreespace(v[1],minfreespace_); + if(rv < 0) + return rv; + case 1: + rv = l::parse_mode(v[0],mode_); + if(rv < 0) + return rv; + break; + case 0: + return -EINVAL; + } + break; + default: + return -EINVAL; + } + + return 0; + } + + static + int + parse(const string &str_, + Branches::Impl *branches_) + { + int rv; + string glob; + StrVec paths; + optional minfreespace; + Branch branch(branches_->minfreespace()); + + rv = l::parse_branch(str_,&glob,&branch.mode,&minfreespace); + if(rv < 0) + return rv; + + if(minfreespace.has_value()) + branch.set_minfreespace(minfreespace.value()); + + fs::glob(glob,&paths); + fs::realpathize(&paths); + for(auto &path : paths) + { + branch.path = path; + branches_->push_back(branch); + } + + return 0; + } + + static + int + set(const std::string &str_, + Branches::Impl *branches_) + { + int rv; + StrVec paths; + Branches::Impl tmp_branches(branches_->minfreespace()); + + str::split(str_,':',&paths); + for(auto &path : paths) + { + rv = l::parse(path,&tmp_branches); + if(rv < 0) + return rv; + } + + *branches_ = std::move(tmp_branches); + + return 0; + } + + static + int + add_begin(const std::string &str_, + Branches::Impl *branches_) + { + int rv; + vector paths; + Branches::Impl tmp_branches(branches_->minfreespace()); + + str::split(str_,':',&paths); + for(auto &path : paths) + { + rv = l::parse(path,&tmp_branches); + if(rv < 0) + return rv; + } + + branches_->insert(branches_->begin(), + tmp_branches.begin(), + tmp_branches.end()); + + return 0; + } + + static + int + add_end(const std::string &str_, + Branches::Impl *branches_) + { + int rv; + StrVec paths; + Branches::Impl tmp_branches(branches_->minfreespace()); + + str::split(str_,':',&paths); + for(auto &path : paths) + { + rv = l::parse(path,&tmp_branches); + if(rv < 0) + return rv; + } + + branches_->insert(branches_->end(), + tmp_branches.begin(), + tmp_branches.end()); + + return 0; + } + + static + int + erase_begin(Branches::Impl *branches_) + { + branches_->erase(branches_->begin()); + + return 0; + } + + static + int + erase_end(Branches::Impl *branches_) + { + branches_->pop_back(); + + return 0; + } + + static + int + erase_fnmatch(const std::string &str_, + Branches::Impl *branches_) + { + StrVec patterns; + + str::split(str_,':',&patterns); + for(auto i = branches_->begin(); i != branches_->end();) + { + int match = FNM_NOMATCH; + + for(auto pi = patterns.cbegin(); pi != patterns.cend() && match != 0; ++pi) + { + match = ::fnmatch(pi->c_str(),i->path.c_str(),0); + } + + i = ((match == 0) ? branches_->erase(i) : (i+1)); + } + + return 0; + } +} + +int +Branches::Impl::from_string(const std::string &s_) +{ + std::string instr; + std::string values; + + l::split(s_,&instr,&values); + + if(instr == "+") + return l::add_end(values,this); + if(instr == "+<") + return l::add_begin(values,this); + if(instr == "+>") + return l::add_end(values,this); + if(instr == "-") + return l::erase_fnmatch(values,this); + if(instr == "-<") + return l::erase_begin(this); + if(instr == "->") + return l::erase_end(this); + if(instr == "=") + return l::set(values,this); + if(instr.empty()) + return l::set(values,this); + + return -EINVAL; +} + +std::string +Branches::Impl::to_string(void) const +{ + string tmp; + + if(empty()) + return tmp; + + for(auto &branch : *this) + { + tmp += branch.to_string(); + tmp += ':'; + } + + tmp.pop_back(); + + return tmp; +} + +void +Branches::Impl::to_paths(StrVec &paths_) const +{ + for(auto &branch : *this) + { + paths_.push_back(branch.path); + } +} + +int +Branches::from_string(const std::string &str_) +{ + int rv; + Branches::Ptr impl; + Branches::Ptr new_impl; + + { + std::lock_guard lock_guard(_mutex); + impl = _impl; + } + + new_impl = std::make_shared(impl->minfreespace()); + *new_impl = *impl; + + rv = new_impl->from_string(str_); + if(rv < 0) + return rv; + + { + std::lock_guard lock_guard(_mutex); + _impl = new_impl; + } + + return 0; +} + +string +Branches::to_string(void) const +{ + std::lock_guard lock_guard(_mutex); + + return _impl->to_string(); +} + +SrcMounts::SrcMounts(Branches &b_) + : _branches(b_) +{ + +} + +int +SrcMounts::from_string(const std::string &s_) +{ + return _branches.from_string(s_); +} + +std::string +SrcMounts::to_string(void) const +{ + std::string rv; + Branches::CPtr branches = _branches; + + if(branches->empty()) + return rv; + + for(const auto &branch : *branches) + { + rv += branch.path; + rv += ':'; + } + + rv.pop_back(); + + return rv; +} diff --git a/src/branches.hpp b/src/branches.hpp new file mode 100644 index 00000000..28731847 --- /dev/null +++ b/src/branches.hpp @@ -0,0 +1,94 @@ +/* + ISC License + + Copyright (c) 2021, Antonio SJ Musumeci + + 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 "branch.hpp" +#include "nonstd/optional.hpp" +#include "strvec.hpp" +#include "tofrom_string.hpp" + +#include +#include +#include +#include +#include + + +class Branches final : public ToFromString +{ +public: + class Impl final : public ToFromString, public Branch::Vector + { + public: + typedef std::shared_ptr Ptr; + typedef std::shared_ptr CPtr; + + public: + Impl(const uint64_t &default_minfreespace_); + + public: + int from_string(const std::string &str) final; + std::string to_string(void) const final; + + public: + const uint64_t& minfreespace(void) const; + void to_paths(StrVec &strvec) const; + + public: + Impl& operator=(Impl &impl_); + Impl& operator=(Impl &&impl_); + + private: + const uint64_t &_default_minfreespace; + }; + +public: + typedef Branches::Impl::Ptr Ptr; + typedef Branches::Impl::CPtr CPtr; + +public: + Branches(const uint64_t &default_minfreespace_) + : _impl(std::make_shared(default_minfreespace_)) + {} + +public: + int from_string(const std::string &str) final; + std::string to_string(void) const final; + +public: + operator CPtr() const { std::lock_guard lg(_mutex); return _impl; } + CPtr operator->() const { std::lock_guard lg(_mutex); return _impl; } + +private: + mutable std::mutex _mutex; + Ptr _impl; +}; + +class SrcMounts : public ToFromString +{ +public: + SrcMounts(Branches &b_); + +public: + int from_string(const std::string &str) final; + std::string to_string(void) const final; + +private: + Branches &_branches; +}; diff --git a/src/category.cpp b/src/category.cpp new file mode 100644 index 00000000..e1fd7f2a --- /dev/null +++ b/src/category.cpp @@ -0,0 +1,49 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "category.hpp" +#include "errno.hpp" +#include "str.hpp" + +#include + +int +Category::Base::from_string(const std::string &s_) +{ + int rv; + + for(auto func : funcs) + { + rv = func->from_string(s_); + if(rv < 0) + return rv; + } + + return 0; +} + +std::string +Category::Base::to_string(void) const +{ + std::set rv; + + for(auto func : funcs) + rv.insert(func->to_string()); + + return str::join(rv,','); +} diff --git a/src/category.hpp b/src/category.hpp index 08a7c00a..ff3b87f2 100644 --- a/src/category.hpp +++ b/src/category.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2016, Antonio SJ Musumeci + Copyright (c) 2020, Antonio SJ Musumeci Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -16,9 +16,92 @@ #pragma once -enum class Category +#include "tofrom_string.hpp" +#include "funcs.hpp" +#include "func.hpp" + +#include + +namespace Category +{ + class Base : public ToFromString + { + public: + int from_string(const std::string &s) final; + std::string to_string() const final; + + protected: + std::vector funcs; + }; + + class Action final : public Base + { + private: + Action(); + + public: + Action(Funcs &funcs_) + { + funcs.push_back(&funcs_.chmod); + funcs.push_back(&funcs_.chown); + funcs.push_back(&funcs_.link); + funcs.push_back(&funcs_.removexattr); + funcs.push_back(&funcs_.rename); + funcs.push_back(&funcs_.rmdir); + funcs.push_back(&funcs_.setxattr); + funcs.push_back(&funcs_.truncate); + funcs.push_back(&funcs_.unlink); + funcs.push_back(&funcs_.utimens); + } + }; + + class Create final : public Base { - ACTION, - CREATE, - SEARCH + private: + Create(); + + public: + Create(Funcs &funcs_) + { + funcs.push_back(&funcs_.create); + funcs.push_back(&funcs_.mkdir); + funcs.push_back(&funcs_.mknod); + funcs.push_back(&funcs_.symlink); + } }; + + class Search final : public Base + { + private: + Search(); + + public: + Search(Funcs &funcs_) + { + funcs.push_back(&funcs_.access); + funcs.push_back(&funcs_.getattr); + funcs.push_back(&funcs_.getxattr); + funcs.push_back(&funcs_.listxattr); + funcs.push_back(&funcs_.open); + funcs.push_back(&funcs_.readlink); + } + }; +} + +class Categories final +{ +private: + Categories(); + +public: + Categories(Funcs &funcs_) + : action(funcs_), + create(funcs_), + search(funcs_) + {} + +public: + Category::Action action; + Category::Create create; + Category::Search search; +}; diff --git a/src/config.cpp b/src/config.cpp index 6c8e1064..aadb2ae6 100644 --- a/src/config.cpp +++ b/src/config.cpp @@ -20,14 +20,18 @@ #include "from_string.hpp" #include "num.hpp" #include "rwlock.hpp" +#include "str.hpp" #include "to_string.hpp" #include "version.hpp" #include -#include +#include +#include #include +#include -#include +#include +#include #include #include @@ -37,6 +41,11 @@ using std::string; #define IFERT(S) if(S == s_) return true +const std::string CONTROLFILE = "/.mergerfs"; + +Config Config::_singleton; + + namespace l { static @@ -60,49 +69,44 @@ namespace l } Config::Config() - : - open_cache(), - - controlfile("/.mergerfs"), - - async_read(true), - auto_cache(false), - branches(minfreespace), - cache_attr(1), - cache_entry(1), - cache_files(CacheFiles::ENUM::LIBFUSE), - cache_negative_entry(0), - cache_readdir(false), - cache_statfs(0), - cache_symlinks(false), - category(func), - direct_io(false), - dropcacheonclose(false), - fsname(), - func(), - fuse_msg_size(FUSE_MAX_MAX_PAGES), - ignorepponrename(false), - inodecalc("hybrid-hash"), - link_cow(false), - minfreespace(MINFREESPACE_DEFAULT), - mount(), - moveonenospc(false), - nfsopenhack(NFSOpenHack::ENUM::OFF), - nullrw(false), - pid(::getpid()), - posix_acl(false), - readdir(ReadDir::ENUM::POSIX), - readdirplus(false), - security_capability(true), - srcmounts(branches), - statfs(StatFS::ENUM::BASE), - statfs_ignore(StatFSIgnore::ENUM::NONE), - symlinkify(false), - symlinkify_timeout(3600), - threads(0), - version(MERGERFS_VERSION), - writeback_cache(false), - xattr(XAttr::ENUM::PASSTHROUGH) + : async_read(true), + auto_cache(false), + branches(minfreespace), + cache_attr(1), + cache_entry(1), + cache_files(CacheFiles::ENUM::LIBFUSE), + cache_negative_entry(0), + cache_readdir(false), + cache_statfs(0), + cache_symlinks(false), + category(func), + direct_io(false), + dropcacheonclose(false), + fsname(), + func(), + fuse_msg_size(FUSE_MAX_MAX_PAGES), + ignorepponrename(false), + inodecalc("hybrid-hash"), + link_cow(false), + minfreespace(MINFREESPACE_DEFAULT), + mount(), + moveonenospc(false), + nfsopenhack(NFSOpenHack::ENUM::OFF), + nullrw(false), + pid(::getpid()), + posix_acl(false), + readdir(ReadDir::ENUM::POSIX), + readdirplus(false), + security_capability(true), + srcmounts(branches), + statfs(StatFS::ENUM::BASE), + statfs_ignore(StatFSIgnore::ENUM::NONE), + symlinkify(false), + symlinkify_timeout(3600), + threads(0), + version(MERGERFS_VERSION), + writeback_cache(false), + xattr(XAttr::ENUM::PASSTHROUGH) { _map["async_read"] = &async_read; _map["auto_cache"] = &auto_cache; @@ -166,17 +170,22 @@ Config::Config() _map["xattr"] = &xattr; } -const Config& -Config::ro(void) +Config::operator=(const Config &cfg_) { - return *((Config*)fuse_get_context()->private_data); -} + int rv; + std::string val; -Config& -Config::rw(void) -{ - return *((Config*)fuse_get_context()->private_data); + for(auto &kv : _map) + { + rv = cfg_.get(kv.first,&val); + if(rv) + continue; + + kv.second->from_string(val); + } + + return *this; } bool @@ -254,11 +263,80 @@ Config::set(const std::string &key_, const std::string &value_) { if(l::readonly(key_)) - return -EINVAL; + return -EROFS; return set_raw(key_,value_); } +int +Config::set(const std::string &kv_) +{ + std::string key; + std::string val; + + str::splitkv(kv_,'=',&key,&val); + key = str::trim(key); + val = str::trim(val); + + return set(key,val); +} + +int +Config::from_stream(std::istream &istrm_, + ErrVec *errs_) +{ + int rv; + std::string line; + std::string key; + std::string val; + Config newcfg; + + newcfg = *this; + + while(std::getline(istrm_,line,'\n')) + { + line = str::trim(line); + if(!line.empty() && (line[0] == '#')) + continue; + + str::splitkv(line,'=',&key,&val); + key = str::trim(key); + val = str::trim(val); + + rv = newcfg.set(key,val); + if(rv < 0) + errs_->push_back({rv,key}); + } + + if(!errs_->empty()) + return -EINVAL; + + *this = newcfg; + + return 0; +} + +int +Config::from_file(const std::string &filepath_, + ErrVec *errs_) +{ + int rv; + std::ifstream ifstrm; + + ifstrm.open(filepath_); + if(!ifstrm.good()) + { + errs_->push_back({-errno,filepath_}); + return -errno; + } + + rv = from_stream(ifstrm,errs_); + + ifstrm.close(); + + return rv; +} + std::ostream& operator<<(std::ostream &os_, const Config &c_) @@ -268,7 +346,47 @@ operator<<(std::ostream &os_, for(i = c_._map.begin(), ei = c_._map.end(); i != ei; ++i) { - os_ << i->first << '=' << i->second << '\n'; + os_ << i->first << '=' << i->second->to_string() << std::endl; + } + + return os_; +} + + +static +std::string +err2str(const int err_) +{ + switch(err_) + { + case 0: + return std::string(); + case -EINVAL: + return "invalid value"; + case -ENOATTR: + return "unknown option"; + case -EROFS: + return "read-only option"; + default: + return strerror(-err_); + } + + return std::string(); +} + +std::ostream& +operator<<(std::ostream &os_, + const Config::ErrVec &ev_) +{ + std::string errstr; + + for(auto &err : ev_) + { + os_ << "* ERROR: "; + errstr = err2str(err.err); + if(!errstr.empty()) + os_ << errstr << " - "; + os_ << err.str << std::endl; } return os_; diff --git a/src/config.hpp b/src/config.hpp index c66f3815..6bd1d02b 100644 --- a/src/config.hpp +++ b/src/config.hpp @@ -16,7 +16,8 @@ #pragma once -#include "branch.hpp" +#include "branches.hpp" +#include "category.hpp" #include "config_cachefiles.hpp" #include "config_inodecalc.hpp" #include "config_moveonenospc.hpp" @@ -27,18 +28,20 @@ #include "config_xattr.hpp" #include "enum.hpp" #include "errno.hpp" -#include "func_category.hpp" #include "funcs.hpp" #include "policy.hpp" -#include "policy_cache.hpp" +#include "rwlock.hpp" #include "tofrom_wrapper.hpp" -#include +#include "fuse.h" +#include +#include +#include +#include #include #include -#include #include typedef ToFromWrapper ConfigBOOL; @@ -47,16 +50,50 @@ typedef ToFromWrapper ConfigINT; typedef ToFromWrapper ConfigSTR; typedef std::map Str2TFStrMap; +extern const std::string CONTROLFILE; + class Config { public: - Config(); + struct Err + { + int err; + std::string str; + }; + + typedef std::vector ErrVec; + +public: + class Read + { + public: + Read(); + + public: + inline const Config* operator->() const; + + private: + const Config &_cfg; + }; public: - mutable PolicyCache open_cache; + class Write + { + public: + Write(); + + public: + Config* operator->(); + + private: + Config &_cfg; + }; public: - const std::string controlfile; + Config(); + +public: + Config& operator=(const Config&); public: ConfigBOOL async_read; @@ -69,7 +106,7 @@ public: ConfigBOOL cache_readdir; ConfigUINT64 cache_statfs; ConfigBOOL cache_symlinks; - FuncCategories category; + Categories category; ConfigBOOL direct_io; ConfigBOOL dropcacheonclose; ConfigSTR fsname; @@ -112,11 +149,50 @@ public: int get(const std::string &key, std::string *val) const; int set_raw(const std::string &key, const std::string &val); int set(const std::string &key, const std::string &val); + int set(const std::string &kv); public: - static const Config &ro(void); - static Config &rw(void); + int from_stream(std::istream &istrm, ErrVec *errs); + int from_file(const std::string &filepath, ErrVec *errs); private: Str2TFStrMap _map; + +private: + static Config _singleton; + +public: + friend class Read; + friend class Write; }; + +std::ostream& operator<<(std::ostream &s,const Config::ErrVec &ev); + +inline +Config::Read::Read() + : _cfg(Config::_singleton) +{ + +} + +inline +const +Config* +Config::Read::operator->() const +{ + return &_cfg; +} + +inline +Config::Write::Write() + : _cfg(Config::_singleton) +{ + +} + +inline +Config* +Config::Write::operator->() +{ + return &_cfg; +} diff --git a/src/config_cachefiles.hpp b/src/config_cachefiles.hpp index c2df5d7e..b6c9a2dc 100644 --- a/src/config_cachefiles.hpp +++ b/src/config_cachefiles.hpp @@ -20,6 +20,7 @@ #include "enum.hpp" + enum class CacheFilesEnum { LIBFUSE, diff --git a/src/config_inodecalc.cpp b/src/config_inodecalc.cpp index b471004d..aa21e048 100644 --- a/src/config_inodecalc.cpp +++ b/src/config_inodecalc.cpp @@ -19,6 +19,7 @@ #include "config_inodecalc.hpp" #include "fs_inode.hpp" + InodeCalc::InodeCalc(const std::string &s_) { fs::inode::set_algo(s_); diff --git a/src/config_inodecalc.hpp b/src/config_inodecalc.hpp index b87b7fc5..8a882593 100644 --- a/src/config_inodecalc.hpp +++ b/src/config_inodecalc.hpp @@ -20,12 +20,13 @@ #include "tofrom_string.hpp" + class InodeCalc : public ToFromString { public: InodeCalc(const std::string &); public: - std::string to_string(void) const; - int from_string(const std::string &); + std::string to_string(void) const final; + int from_string(const std::string &) final; }; diff --git a/src/config_moveonenospc.cpp b/src/config_moveonenospc.cpp index a1975459..17950cc8 100644 --- a/src/config_moveonenospc.cpp +++ b/src/config_moveonenospc.cpp @@ -21,12 +21,13 @@ #include "errno.hpp" #include "from_string.hpp" + int MoveOnENOSPC::from_string(const std::string &s_) { int rv; std::string s; - const Policy *tmp; + Policy::CreateImpl *tmp; rv = str::from(s_,&enabled); if((rv == 0) && (enabled == true)) @@ -36,8 +37,8 @@ MoveOnENOSPC::from_string(const std::string &s_) else return 0; - tmp = &Policy::find(s); - if(tmp == Policy::invalid) + tmp = Policies::Create::find(s); + if(tmp == NULL) return -EINVAL; policy = tmp; @@ -50,6 +51,6 @@ std::string MoveOnENOSPC::to_string(void) const { if(enabled) - return policy->to_string(); + return policy.name(); return "false"; } diff --git a/src/config_moveonenospc.hpp b/src/config_moveonenospc.hpp index a7aa4fe1..2aac71fb 100644 --- a/src/config_moveonenospc.hpp +++ b/src/config_moveonenospc.hpp @@ -19,26 +19,26 @@ #pragma once #include "policy.hpp" +#include "policies.hpp" #include "tofrom_string.hpp" #include + class MoveOnENOSPC : public ToFromString { public: MoveOnENOSPC(const bool enabled_) - : enabled(enabled_) + : enabled(enabled_), + policy(&Policies::Create::mfs) { - policy = (enabled ? - &Policy::mfs : - &Policy::invalid); } public: - int from_string(const std::string &s); - std::string to_string() const; + int from_string(const std::string &s) final; + std::string to_string() const final; public: bool enabled; - const Policy *policy; + Policy::Create policy; }; diff --git a/src/config_nfsopenhack.cpp b/src/config_nfsopenhack.cpp index 81c9b169..55cad062 100644 --- a/src/config_nfsopenhack.cpp +++ b/src/config_nfsopenhack.cpp @@ -20,6 +20,7 @@ #include "ef.hpp" #include "errno.hpp" + template<> int NFSOpenHack::from_string(const std::string &s_) diff --git a/src/config_nfsopenhack.hpp b/src/config_nfsopenhack.hpp index e6a3e797..0e54b482 100644 --- a/src/config_nfsopenhack.hpp +++ b/src/config_nfsopenhack.hpp @@ -20,6 +20,7 @@ #include "enum.hpp" + enum class NFSOpenHackEnum { OFF, diff --git a/src/config_readdir.cpp b/src/config_readdir.cpp index b0dd07bd..f03b2a77 100644 --- a/src/config_readdir.cpp +++ b/src/config_readdir.cpp @@ -20,6 +20,7 @@ #include "ef.hpp" #include "errno.hpp" + template<> int ReadDir::from_string(const std::string &s_) diff --git a/src/config_readdir.hpp b/src/config_readdir.hpp index fe041d87..96767f20 100644 --- a/src/config_readdir.hpp +++ b/src/config_readdir.hpp @@ -20,6 +20,7 @@ #include "enum.hpp" + enum class ReadDirEnum { POSIX, diff --git a/src/config_statfs.cpp b/src/config_statfs.cpp index 07642786..50910367 100644 --- a/src/config_statfs.cpp +++ b/src/config_statfs.cpp @@ -20,6 +20,7 @@ #include "ef.hpp" #include "errno.hpp" + template<> std::string StatFS::to_string() const diff --git a/src/config_statfs.hpp b/src/config_statfs.hpp index f217371b..0d408aeb 100644 --- a/src/config_statfs.hpp +++ b/src/config_statfs.hpp @@ -20,6 +20,7 @@ #include "enum.hpp" + enum class StatFSEnum { BASE, diff --git a/src/config_statfsignore.cpp b/src/config_statfsignore.cpp index e3355053..14b5ded3 100644 --- a/src/config_statfsignore.cpp +++ b/src/config_statfsignore.cpp @@ -20,6 +20,7 @@ #include "ef.hpp" #include "errno.hpp" + template<> std::string StatFSIgnore::to_string() const diff --git a/src/config_xattr.cpp b/src/config_xattr.cpp index 8b243c0f..bb626f22 100644 --- a/src/config_xattr.cpp +++ b/src/config_xattr.cpp @@ -20,6 +20,7 @@ #include "ef.hpp" #include "errno.hpp" + template<> std::string XAttr::to_string() const diff --git a/src/config_xattr.hpp b/src/config_xattr.hpp index c9eac263..34329fa4 100644 --- a/src/config_xattr.hpp +++ b/src/config_xattr.hpp @@ -21,6 +21,7 @@ #include "enum.hpp" #include "errno.hpp" + enum class XAttrEnum { PASSTHROUGH = 0, diff --git a/src/dirinfo.hpp b/src/dirinfo.hpp index 37ee6d3b..7048fbf4 100644 --- a/src/dirinfo.hpp +++ b/src/dirinfo.hpp @@ -20,6 +20,7 @@ #include + class DirInfo : public FH { public: diff --git a/src/endian.hpp b/src/endian.hpp index d294dba8..d5454994 100644 --- a/src/endian.hpp +++ b/src/endian.hpp @@ -18,6 +18,7 @@ #pragma once + namespace endian { static diff --git a/src/enum.hpp b/src/enum.hpp index 6f0dd35a..848ffca8 100644 --- a/src/enum.hpp +++ b/src/enum.hpp @@ -22,6 +22,7 @@ #include + template class Enum : public ToFromString { diff --git a/src/fh.hpp b/src/fh.hpp index 2060e2a5..4187b7f5 100644 --- a/src/fh.hpp +++ b/src/fh.hpp @@ -18,6 +18,7 @@ #include + class FH { public: diff --git a/src/fileinfo.hpp b/src/fileinfo.hpp index a3ca65b1..4d4948e4 100644 --- a/src/fileinfo.hpp +++ b/src/fileinfo.hpp @@ -20,6 +20,7 @@ #include + class FileInfo : public FH { public: diff --git a/src/fixed_mem_pool.hpp b/src/fixed_mem_pool.hpp index e81f1343..2f012b17 100644 --- a/src/fixed_mem_pool.hpp +++ b/src/fixed_mem_pool.hpp @@ -18,8 +18,10 @@ #pragma once +#include + #include -#include + typedef struct fixed_mem_pool_t fixed_mem_pool_t; struct fixed_mem_pool_t diff --git a/src/from_string.cpp b/src/from_string.cpp index 796f9256..638c8772 100644 --- a/src/from_string.cpp +++ b/src/from_string.cpp @@ -17,13 +17,14 @@ */ #include "ef.hpp" +#include "errno.hpp" +#include #include -#include -#include #include + namespace str { int @@ -50,7 +51,17 @@ namespace str from(const std::string &value_, int *int_) { - *int_ = ::strtol(value_.c_str(),NULL,10); + int tmp; + char *endptr; + + errno = 0; + tmp = ::strtol(value_.c_str(),&endptr,10); + if(errno != 0) + return -EINVAL; + if(endptr == value_.c_str()) + return -EINVAL; + + *int_ = tmp; return 0; } diff --git a/src/from_string.hpp b/src/from_string.hpp index 3c06884c..018bc2b7 100644 --- a/src/from_string.hpp +++ b/src/from_string.hpp @@ -18,9 +18,9 @@ #pragma once +#include #include -#include namespace str { diff --git a/src/fs_acl.cpp b/src/fs_acl.cpp index 148f21dc..3737bc16 100644 --- a/src/fs_acl.cpp +++ b/src/fs_acl.cpp @@ -23,6 +23,7 @@ const char POSIX_ACL_DEFAULT_XATTR[] = "system.posix_acl_default"; + namespace fs { namespace acl diff --git a/src/fs_acl.hpp b/src/fs_acl.hpp index f3b16e43..92fef84b 100644 --- a/src/fs_acl.hpp +++ b/src/fs_acl.hpp @@ -20,6 +20,7 @@ #include + namespace fs { namespace acl diff --git a/src/fs_attr.hpp b/src/fs_attr.hpp index c9bee84e..96d9944b 100644 --- a/src/fs_attr.hpp +++ b/src/fs_attr.hpp @@ -18,6 +18,7 @@ #include + namespace fs { namespace attr diff --git a/src/fs_attr_linux.icpp b/src/fs_attr_linux.icpp index 8d346190..abae1e5e 100644 --- a/src/fs_attr_linux.icpp +++ b/src/fs_attr_linux.icpp @@ -26,6 +26,7 @@ using std::string; + namespace fs { namespace attr diff --git a/src/fs_attr_unsupported.icpp b/src/fs_attr_unsupported.icpp index 852038fc..4a5c37bb 100644 --- a/src/fs_attr_unsupported.icpp +++ b/src/fs_attr_unsupported.icpp @@ -18,6 +18,7 @@ #include + namespace fs { namespace attr diff --git a/src/fs_clonefile.cpp b/src/fs_clonefile.cpp index 6dabde05..69d94c04 100644 --- a/src/fs_clonefile.cpp +++ b/src/fs_clonefile.cpp @@ -22,6 +22,7 @@ #include "fs_fchmod.hpp" #include "fs_futimens.hpp" + namespace l { static diff --git a/src/fs_clonefile.hpp b/src/fs_clonefile.hpp index a9835e57..67eeca33 100644 --- a/src/fs_clonefile.hpp +++ b/src/fs_clonefile.hpp @@ -16,6 +16,7 @@ #pragma once + namespace fs { int diff --git a/src/fs_clonepath.cpp b/src/fs_clonepath.cpp index 9e42946a..4fec3ae7 100644 --- a/src/fs_clonepath.cpp +++ b/src/fs_clonepath.cpp @@ -14,8 +14,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include - #include "errno.h" #include "fs_attr.hpp" #include "fs_clonepath.hpp" @@ -27,8 +25,11 @@ #include "fs_xattr.hpp" #include "ugid.hpp" +#include + using std::string; + namespace l { static diff --git a/src/fs_clonepath.hpp b/src/fs_clonepath.hpp index 34904d0c..8ad68c97 100644 --- a/src/fs_clonepath.hpp +++ b/src/fs_clonepath.hpp @@ -18,6 +18,7 @@ #include + namespace fs { int clonepath(const std::string &from, diff --git a/src/fs_close.hpp b/src/fs_close.hpp index 236d290d..646482fa 100644 --- a/src/fs_close.hpp +++ b/src/fs_close.hpp @@ -20,6 +20,7 @@ #include + namespace fs { static diff --git a/src/fs_closedir.hpp b/src/fs_closedir.hpp index 03ae8785..f7fc081f 100644 --- a/src/fs_closedir.hpp +++ b/src/fs_closedir.hpp @@ -21,6 +21,7 @@ #include #include + namespace fs { static diff --git a/src/fs_copy_file_range.hpp b/src/fs_copy_file_range.hpp index aab5fc9e..5ffdc656 100644 --- a/src/fs_copy_file_range.hpp +++ b/src/fs_copy_file_range.hpp @@ -18,10 +18,12 @@ #pragma once +#include + #include -#include #include + namespace fs { int64_t diff --git a/src/fs_copy_file_range_linux.icpp b/src/fs_copy_file_range_linux.icpp index 7df4f845..79103443 100644 --- a/src/fs_copy_file_range_linux.icpp +++ b/src/fs_copy_file_range_linux.icpp @@ -22,13 +22,15 @@ #include "errno.hpp" +#include + #include -#include #include #include #include #include + namespace l { static diff --git a/src/fs_copy_file_range_unsupported.icpp b/src/fs_copy_file_range_unsupported.icpp index c0e87fc8..2e87ecb7 100644 --- a/src/fs_copy_file_range_unsupported.icpp +++ b/src/fs_copy_file_range_unsupported.icpp @@ -18,10 +18,12 @@ #include "errno.h" +#include + #include -#include #include + namespace fs { ssize_t diff --git a/src/fs_copydata.cpp b/src/fs_copydata.cpp index 979b31b7..fee8821a 100644 --- a/src/fs_copydata.cpp +++ b/src/fs_copydata.cpp @@ -24,6 +24,7 @@ #include + namespace fs { int diff --git a/src/fs_copydata.hpp b/src/fs_copydata.hpp index 48e0784d..4347bcb6 100644 --- a/src/fs_copydata.hpp +++ b/src/fs_copydata.hpp @@ -20,6 +20,7 @@ #include + namespace fs { int diff --git a/src/fs_copydata_copy_file_range.cpp b/src/fs_copydata_copy_file_range.cpp index f8e7c388..5722750b 100644 --- a/src/fs_copydata_copy_file_range.cpp +++ b/src/fs_copydata_copy_file_range.cpp @@ -18,7 +18,8 @@ #include "fs_copy_file_range.hpp" #include "fs_fstat.hpp" -#include +#include + namespace l { diff --git a/src/fs_copydata_copy_file_range.hpp b/src/fs_copydata_copy_file_range.hpp index 6b0f7567..b22f53ec 100644 --- a/src/fs_copydata_copy_file_range.hpp +++ b/src/fs_copydata_copy_file_range.hpp @@ -16,7 +16,8 @@ #pragma once -#include +#include + namespace fs { diff --git a/src/fs_copydata_readwrite.cpp b/src/fs_copydata_readwrite.cpp index c119585d..e2c48795 100644 --- a/src/fs_copydata_readwrite.cpp +++ b/src/fs_copydata_readwrite.cpp @@ -24,6 +24,7 @@ using std::vector; + namespace l { static diff --git a/src/fs_copydata_readwrite.hpp b/src/fs_copydata_readwrite.hpp index 9e900d03..43271165 100644 --- a/src/fs_copydata_readwrite.hpp +++ b/src/fs_copydata_readwrite.hpp @@ -16,6 +16,7 @@ #pragma once + namespace fs { int diff --git a/src/fs_cow.cpp b/src/fs_cow.cpp index 63379fe5..37855329 100644 --- a/src/fs_cow.cpp +++ b/src/fs_cow.cpp @@ -34,6 +34,7 @@ using std::string; + namespace l { static diff --git a/src/fs_cow.hpp b/src/fs_cow.hpp index 5cb9353d..7403e5d9 100644 --- a/src/fs_cow.hpp +++ b/src/fs_cow.hpp @@ -21,6 +21,7 @@ #include #include + namespace fs { namespace cow diff --git a/src/fs_devid.hpp b/src/fs_devid.hpp index 2f9bde05..d75bcf3e 100644 --- a/src/fs_devid.hpp +++ b/src/fs_devid.hpp @@ -20,6 +20,7 @@ #include "fs_fstat.hpp" + namespace fs { static diff --git a/src/fs_dirfd.hpp b/src/fs_dirfd.hpp index d4afa76e..767d6685 100644 --- a/src/fs_dirfd.hpp +++ b/src/fs_dirfd.hpp @@ -21,6 +21,7 @@ #include #include + namespace fs { static diff --git a/src/fs_dup.hpp b/src/fs_dup.hpp index fc1dd106..fdb82c66 100644 --- a/src/fs_dup.hpp +++ b/src/fs_dup.hpp @@ -20,6 +20,7 @@ #include + namespace fs { static diff --git a/src/fs_eaccess.hpp b/src/fs_eaccess.hpp index f661566a..03f55287 100644 --- a/src/fs_eaccess.hpp +++ b/src/fs_eaccess.hpp @@ -20,6 +20,7 @@ #include "fs_faccessat.hpp" + namespace fs { static diff --git a/src/fs_exists.hpp b/src/fs_exists.hpp index 808bc8b1..2abdd646 100644 --- a/src/fs_exists.hpp +++ b/src/fs_exists.hpp @@ -23,6 +23,7 @@ #include + namespace fs { static diff --git a/src/fs_faccessat.hpp b/src/fs_faccessat.hpp index 02729b87..80329f47 100644 --- a/src/fs_faccessat.hpp +++ b/src/fs_faccessat.hpp @@ -23,6 +23,7 @@ #include #include + namespace fs { static diff --git a/src/fs_fadvise.hpp b/src/fs_fadvise.hpp index 96fa8360..e1126228 100644 --- a/src/fs_fadvise.hpp +++ b/src/fs_fadvise.hpp @@ -18,6 +18,7 @@ #include + namespace fs { int diff --git a/src/fs_fadvise_posix.icpp b/src/fs_fadvise_posix.icpp index a51e5de5..15bc8601 100644 --- a/src/fs_fadvise_posix.icpp +++ b/src/fs_fadvise_posix.icpp @@ -16,6 +16,7 @@ #include + namespace fs { static diff --git a/src/fs_fadvise_unsupported.icpp b/src/fs_fadvise_unsupported.icpp index b25aebcb..40617b01 100644 --- a/src/fs_fadvise_unsupported.icpp +++ b/src/fs_fadvise_unsupported.icpp @@ -16,6 +16,7 @@ #include "errno.hpp" + namespace fs { static diff --git a/src/fs_fallocate.hpp b/src/fs_fallocate.hpp index d6691472..74d33feb 100644 --- a/src/fs_fallocate.hpp +++ b/src/fs_fallocate.hpp @@ -18,6 +18,7 @@ #include + namespace fs { int diff --git a/src/fs_fallocate_linux.icpp b/src/fs_fallocate_linux.icpp index ae274eeb..f3eb2821 100644 --- a/src/fs_fallocate_linux.icpp +++ b/src/fs_fallocate_linux.icpp @@ -16,6 +16,7 @@ #include + namespace fs { int diff --git a/src/fs_fallocate_osx.icpp b/src/fs_fallocate_osx.icpp index d98c2795..746d7fb4 100644 --- a/src/fs_fallocate_osx.icpp +++ b/src/fs_fallocate_osx.icpp @@ -14,10 +14,11 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "errno.hpp" + #include #include -#include "errno.hpp" namespace l { diff --git a/src/fs_fallocate_posix.icpp b/src/fs_fallocate_posix.icpp index 17f99e95..bbd2678c 100644 --- a/src/fs_fallocate_posix.icpp +++ b/src/fs_fallocate_posix.icpp @@ -18,6 +18,7 @@ #include + namespace fs { int diff --git a/src/fs_fallocate_unsupported.icpp b/src/fs_fallocate_unsupported.icpp index 9c913e84..c4211986 100644 --- a/src/fs_fallocate_unsupported.icpp +++ b/src/fs_fallocate_unsupported.icpp @@ -16,6 +16,7 @@ #include "errno.hpp" + namespace fs { int diff --git a/src/fs_fchmod.hpp b/src/fs_fchmod.hpp index 5300d43d..5d8c8195 100644 --- a/src/fs_fchmod.hpp +++ b/src/fs_fchmod.hpp @@ -24,6 +24,7 @@ #define MODE_BITS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO) + namespace fs { static diff --git a/src/fs_fchmodat.hpp b/src/fs_fchmodat.hpp index 209efbc6..e6e5ec9d 100644 --- a/src/fs_fchmodat.hpp +++ b/src/fs_fchmodat.hpp @@ -23,6 +23,7 @@ #include #include + namespace fs { static diff --git a/src/fs_fchown.hpp b/src/fs_fchown.hpp index 1b879e07..f8d92561 100644 --- a/src/fs_fchown.hpp +++ b/src/fs_fchown.hpp @@ -25,6 +25,7 @@ #include #include + namespace fs { static diff --git a/src/fs_fdatasync.hpp b/src/fs_fdatasync.hpp index 7b7fa72f..ac6183c1 100644 --- a/src/fs_fdatasync.hpp +++ b/src/fs_fdatasync.hpp @@ -26,6 +26,7 @@ #include + namespace fs { static diff --git a/src/fs_fgetxattr.hpp b/src/fs_fgetxattr.hpp index 57541eb0..7530d5d6 100644 --- a/src/fs_fgetxattr.hpp +++ b/src/fs_fgetxattr.hpp @@ -25,6 +25,7 @@ #include + namespace fs { static diff --git a/src/fs_ficlone.hpp b/src/fs_ficlone.hpp index 6900a82b..fd046c64 100644 --- a/src/fs_ficlone.hpp +++ b/src/fs_ficlone.hpp @@ -18,6 +18,7 @@ #pragma once + namespace fs { int diff --git a/src/fs_ficlone_linux.icpp b/src/fs_ficlone_linux.icpp index a36196fd..f0ce01bd 100644 --- a/src/fs_ficlone_linux.icpp +++ b/src/fs_ficlone_linux.icpp @@ -21,6 +21,7 @@ #include + namespace fs { int diff --git a/src/fs_ficlone_unsupported.icpp b/src/fs_ficlone_unsupported.icpp index aa6c4f0f..e7b864f5 100644 --- a/src/fs_ficlone_unsupported.icpp +++ b/src/fs_ficlone_unsupported.icpp @@ -18,6 +18,7 @@ #include "errno.hpp" + namespace fs { int diff --git a/src/fs_file_size.cpp b/src/fs_file_size.cpp index d06b7007..5528dbe1 100644 --- a/src/fs_file_size.cpp +++ b/src/fs_file_size.cpp @@ -18,7 +18,8 @@ #include "fs_fstat.hpp" -#include +#include + namespace fs { diff --git a/src/fs_file_size.hpp b/src/fs_file_size.hpp index 4977663e..1b01ea31 100644 --- a/src/fs_file_size.hpp +++ b/src/fs_file_size.hpp @@ -18,7 +18,8 @@ #pragma once -#include +#include + namespace fs { diff --git a/src/fs_findallfiles.cpp b/src/fs_findallfiles.cpp index a7a60d42..fc15f445 100644 --- a/src/fs_findallfiles.cpp +++ b/src/fs_findallfiles.cpp @@ -22,6 +22,7 @@ #include #include + namespace fs { void diff --git a/src/fs_findallfiles.hpp b/src/fs_findallfiles.hpp index ff3d81ed..db3e5895 100644 --- a/src/fs_findallfiles.hpp +++ b/src/fs_findallfiles.hpp @@ -18,13 +18,16 @@ #pragma once +#include "strvec.hpp" + #include #include + namespace fs { void - findallfiles(const std::vector &basepaths, - const char *fusepath, - std::vector *paths); + findallfiles(const StrVec &basepaths, + const char *fusepath, + StrVec *paths); } diff --git a/src/fs_findonfs.cpp b/src/fs_findonfs.cpp index e52c7333..ec8b2dc1 100644 --- a/src/fs_findonfs.cpp +++ b/src/fs_findonfs.cpp @@ -16,7 +16,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "branch.hpp" +#include "branches.hpp" #include "errno.hpp" #include "fs_fstat.hpp" #include "fs_lstat.hpp" @@ -24,31 +24,29 @@ #include + namespace l { static int - findonfs(const BranchVec &branches_, - const std::string &fusepath_, - const int fd_, - std::string *basepath_) + findonfs(const Branches::CPtr &branches_, + const std::string &fusepath_, + const int fd_, + std::string *basepath_) { int rv; dev_t dev; struct stat st; std::string fullpath; - const Branch *branch; rv = fs::fstat(fd_,&st); if(rv == -1) return -1; dev = st.st_dev; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(const auto &branch : *branches_) { - branch = &branches_[i]; - - fullpath = fs::path::make(branch->path,fusepath_); + fullpath = fs::path::make(branch.path,fusepath_); rv = fs::lstat(fullpath,&st); if(rv == -1) @@ -57,7 +55,7 @@ namespace l if(st.st_dev != dev) continue; - *basepath_ = branch->path; + *basepath_ = branch.path; return 0; } @@ -69,13 +67,11 @@ namespace l namespace fs { int - findonfs(const Branches &branches_, - const std::string &fusepath_, - const int fd_, - std::string *basepath_) + findonfs(const Branches::CPtr &branches_, + const std::string &fusepath_, + const int fd_, + std::string *basepath_) { - rwlock::ReadGuard guard(branches_.lock); - - return l::findonfs(branches_.vec,fusepath_,fd_,basepath_); + return l::findonfs(branches_,fusepath_,fd_,basepath_); } } diff --git a/src/fs_findonfs.hpp b/src/fs_findonfs.hpp index 3a72fd26..af7441a9 100644 --- a/src/fs_findonfs.hpp +++ b/src/fs_findonfs.hpp @@ -18,15 +18,16 @@ #pragma once -#include "branch.hpp" +#include "branches.hpp" #include + namespace fs { int - findonfs(const Branches &branches, - const std::string &fusepath, - const int fd, - std::string *basepath); + findonfs(const Branches::CPtr &branches, + const std::string &fusepath, + const int fd, + std::string *basepath); } diff --git a/src/fs_flistxattr.hpp b/src/fs_flistxattr.hpp index cbfa3425..1a9f6ae8 100644 --- a/src/fs_flistxattr.hpp +++ b/src/fs_flistxattr.hpp @@ -23,6 +23,7 @@ #include + namespace fs { static diff --git a/src/fs_flock.hpp b/src/fs_flock.hpp index 1cee9c6d..a6fd59f8 100644 --- a/src/fs_flock.hpp +++ b/src/fs_flock.hpp @@ -20,6 +20,7 @@ #include + namespace fs { static diff --git a/src/fs_fsetxattr.hpp b/src/fs_fsetxattr.hpp index d2cfb023..c2f2e129 100644 --- a/src/fs_fsetxattr.hpp +++ b/src/fs_fsetxattr.hpp @@ -25,6 +25,7 @@ #include + namespace fs { static diff --git a/src/fs_fstat.hpp b/src/fs_fstat.hpp index 233d72fb..702b1030 100644 --- a/src/fs_fstat.hpp +++ b/src/fs_fstat.hpp @@ -23,6 +23,7 @@ #include #include + namespace fs { static diff --git a/src/fs_fstatat.hpp b/src/fs_fstatat.hpp index 6148d9d5..cfada9fb 100644 --- a/src/fs_fstatat.hpp +++ b/src/fs_fstatat.hpp @@ -23,6 +23,7 @@ #include #include + namespace fs { static diff --git a/src/fs_fsync.hpp b/src/fs_fsync.hpp index c91e0181..91374487 100644 --- a/src/fs_fsync.hpp +++ b/src/fs_fsync.hpp @@ -20,6 +20,7 @@ #include + namespace fs { static diff --git a/src/fs_ftruncate.hpp b/src/fs_ftruncate.hpp index 0244bd2d..ec2c17a3 100644 --- a/src/fs_ftruncate.hpp +++ b/src/fs_ftruncate.hpp @@ -21,6 +21,7 @@ #include #include + namespace fs { static diff --git a/src/fs_futimens.hpp b/src/fs_futimens.hpp index 9f223303..2e4b8874 100644 --- a/src/fs_futimens.hpp +++ b/src/fs_futimens.hpp @@ -33,6 +33,7 @@ #include "fs_futimens_generic.hpp" #endif + namespace fs { static diff --git a/src/fs_futimens_freebsd_11.hpp b/src/fs_futimens_freebsd_11.hpp index 745bedee..d3e25247 100644 --- a/src/fs_futimens_freebsd_11.hpp +++ b/src/fs_futimens_freebsd_11.hpp @@ -20,6 +20,7 @@ #include + namespace fs { static diff --git a/src/fs_futimens_generic.hpp b/src/fs_futimens_generic.hpp index d6124151..ead03dc8 100644 --- a/src/fs_futimens_generic.hpp +++ b/src/fs_futimens_generic.hpp @@ -33,6 +33,7 @@ # define UTIME_OMIT ((1l << 30) - 2l) #endif + namespace l { static diff --git a/src/fs_futimens_linux.hpp b/src/fs_futimens_linux.hpp index 745bedee..d3e25247 100644 --- a/src/fs_futimens_linux.hpp +++ b/src/fs_futimens_linux.hpp @@ -20,6 +20,7 @@ #include + namespace fs { static diff --git a/src/fs_futimesat.hpp b/src/fs_futimesat.hpp index d18c44c4..f5a34d64 100644 --- a/src/fs_futimesat.hpp +++ b/src/fs_futimesat.hpp @@ -20,6 +20,7 @@ #include + namespace fs { int diff --git a/src/fs_futimesat_generic.icpp b/src/fs_futimesat_generic.icpp index 4f2b2134..acf49095 100644 --- a/src/fs_futimesat_generic.icpp +++ b/src/fs_futimesat_generic.icpp @@ -19,6 +19,7 @@ #include #include + namespace fs { int diff --git a/src/fs_futimesat_osx.icpp b/src/fs_futimesat_osx.icpp index e00c4ddd..b96b4623 100644 --- a/src/fs_futimesat_osx.icpp +++ b/src/fs_futimesat_osx.icpp @@ -26,6 +26,7 @@ #include #include + namespace l { static diff --git a/src/fs_getdents64.cpp b/src/fs_getdents64.cpp index a955fa12..0015cc07 100644 --- a/src/fs_getdents64.cpp +++ b/src/fs_getdents64.cpp @@ -23,6 +23,7 @@ #include #endif + namespace fs { int diff --git a/src/fs_getdents64.hpp b/src/fs_getdents64.hpp index e1c12d6a..f328c431 100644 --- a/src/fs_getdents64.hpp +++ b/src/fs_getdents64.hpp @@ -18,6 +18,7 @@ #pragma once + namespace fs { int diff --git a/src/fs_getfl.cpp b/src/fs_getfl.cpp index 891561db..f84676a6 100644 --- a/src/fs_getfl.cpp +++ b/src/fs_getfl.cpp @@ -18,6 +18,7 @@ #include + namespace fs { int diff --git a/src/fs_getfl.hpp b/src/fs_getfl.hpp index ddb30034..0abb3e20 100644 --- a/src/fs_getfl.hpp +++ b/src/fs_getfl.hpp @@ -18,6 +18,7 @@ #pragma once + namespace fs { int getfl(const int fd); diff --git a/src/fs_glob.cpp b/src/fs_glob.cpp index 02efe6c5..fb7177dd 100644 --- a/src/fs_glob.cpp +++ b/src/fs_glob.cpp @@ -14,16 +14,16 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include - #include +#include #include #include using std::string; using std::vector; + namespace fs { void diff --git a/src/fs_glob.hpp b/src/fs_glob.hpp index ed16c95c..9d2b3b06 100644 --- a/src/fs_glob.hpp +++ b/src/fs_glob.hpp @@ -19,6 +19,7 @@ #include #include + namespace fs { void diff --git a/src/fs_has_space.cpp b/src/fs_has_space.cpp index f41ee8b5..3ce5bc18 100644 --- a/src/fs_has_space.cpp +++ b/src/fs_has_space.cpp @@ -19,9 +19,9 @@ #include "fs_statvfs.hpp" #include "statvfs_util.hpp" +#include #include -#include namespace fs { diff --git a/src/fs_has_space.hpp b/src/fs_has_space.hpp index ed4c5c79..64aa7825 100644 --- a/src/fs_has_space.hpp +++ b/src/fs_has_space.hpp @@ -18,9 +18,9 @@ #pragma once +#include #include -#include namespace fs { diff --git a/src/fs_info.cpp b/src/fs_info.cpp index e36d41f7..6368036e 100644 --- a/src/fs_info.cpp +++ b/src/fs_info.cpp @@ -23,12 +23,12 @@ #include "fs_statvfs_cache.hpp" #include "statvfs_util.hpp" -#include - +#include #include using std::string; + namespace fs { int diff --git a/src/fs_info.hpp b/src/fs_info.hpp index cc8639a3..ec7cf30d 100644 --- a/src/fs_info.hpp +++ b/src/fs_info.hpp @@ -22,6 +22,7 @@ #include + namespace fs { int diff --git a/src/fs_info_t.hpp b/src/fs_info_t.hpp index 623617d7..7db05d74 100644 --- a/src/fs_info_t.hpp +++ b/src/fs_info_t.hpp @@ -18,7 +18,8 @@ #pragma once -#include +#include + namespace fs { diff --git a/src/fs_inode.cpp b/src/fs_inode.cpp index 20256940..b0330c77 100644 --- a/src/fs_inode.cpp +++ b/src/fs_inode.cpp @@ -21,10 +21,10 @@ #include "fs_inode.hpp" #include "wyhash.h" +#include #include #include -#include #include #include @@ -184,10 +184,16 @@ namespace fs return "passthrough"; if(g_func == path_hash) return "path-hash"; + if(g_func == path_hash32) + return "path-hash32"; if(g_func == devino_hash) return "devino-hash"; + if(g_func == devino_hash32) + return "devino-hash32"; if(g_func == hybrid_hash) return "hybrid-hash"; + if(g_func == hybrid_hash32) + return "hybrid-hash32"; return std::string(); } diff --git a/src/fs_inode.hpp b/src/fs_inode.hpp index a7e0fb76..baf7d718 100644 --- a/src/fs_inode.hpp +++ b/src/fs_inode.hpp @@ -18,9 +18,9 @@ #pragma once +#include #include -#include #include diff --git a/src/fs_ioctl.hpp b/src/fs_ioctl.hpp index cdb74e2b..86ee9bdf 100644 --- a/src/fs_ioctl.hpp +++ b/src/fs_ioctl.hpp @@ -20,6 +20,7 @@ #include + namespace fs { static diff --git a/src/fs_lchmod.hpp b/src/fs_lchmod.hpp index 21c94500..95012ab0 100644 --- a/src/fs_lchmod.hpp +++ b/src/fs_lchmod.hpp @@ -26,6 +26,7 @@ #define MODE_BITS (S_ISUID|S_ISGID|S_ISVTX|S_IRWXU|S_IRWXG|S_IRWXO) + namespace fs { static diff --git a/src/fs_lchown.hpp b/src/fs_lchown.hpp index 83fa30d8..6091a269 100644 --- a/src/fs_lchown.hpp +++ b/src/fs_lchown.hpp @@ -22,6 +22,7 @@ #include + namespace fs { static diff --git a/src/fs_lgetxattr.hpp b/src/fs_lgetxattr.hpp index 482fa35c..7d4fe8e1 100644 --- a/src/fs_lgetxattr.hpp +++ b/src/fs_lgetxattr.hpp @@ -25,6 +25,7 @@ #include + namespace fs { static diff --git a/src/fs_link.hpp b/src/fs_link.hpp index 09ef6459..8b41d4a2 100644 --- a/src/fs_link.hpp +++ b/src/fs_link.hpp @@ -22,6 +22,7 @@ #include + namespace fs { static diff --git a/src/fs_llistxattr.hpp b/src/fs_llistxattr.hpp index e8c83dc4..9818a665 100644 --- a/src/fs_llistxattr.hpp +++ b/src/fs_llistxattr.hpp @@ -25,6 +25,7 @@ #include + namespace fs { static diff --git a/src/fs_lremovexattr.hpp b/src/fs_lremovexattr.hpp index 4d9f3f53..06258f9d 100644 --- a/src/fs_lremovexattr.hpp +++ b/src/fs_lremovexattr.hpp @@ -23,6 +23,7 @@ #include + namespace fs { static diff --git a/src/fs_lseek.hpp b/src/fs_lseek.hpp index 34744c49..79bcfe3b 100644 --- a/src/fs_lseek.hpp +++ b/src/fs_lseek.hpp @@ -21,6 +21,7 @@ #include #include + namespace fs { static diff --git a/src/fs_lsetxattr.hpp b/src/fs_lsetxattr.hpp index 41baf862..ba3a7325 100644 --- a/src/fs_lsetxattr.hpp +++ b/src/fs_lsetxattr.hpp @@ -25,6 +25,7 @@ #include + namespace fs { static diff --git a/src/fs_lstat.hpp b/src/fs_lstat.hpp index 83254b83..dd8e8384 100644 --- a/src/fs_lstat.hpp +++ b/src/fs_lstat.hpp @@ -24,6 +24,7 @@ #include #include + namespace fs { static diff --git a/src/fs_lutimens.hpp b/src/fs_lutimens.hpp index ab1ce218..e2937a6d 100644 --- a/src/fs_lutimens.hpp +++ b/src/fs_lutimens.hpp @@ -21,6 +21,7 @@ #include "fs_utimensat.hpp" #include "fs_stat_utils.hpp" + namespace fs { static diff --git a/src/fs_mkdir.hpp b/src/fs_mkdir.hpp index 05eb78b5..8d55c595 100644 --- a/src/fs_mkdir.hpp +++ b/src/fs_mkdir.hpp @@ -23,6 +23,7 @@ #include #include + namespace fs { static diff --git a/src/fs_mknod.hpp b/src/fs_mknod.hpp index bf85f3b2..9bf80636 100644 --- a/src/fs_mknod.hpp +++ b/src/fs_mknod.hpp @@ -23,6 +23,7 @@ #include #include + namespace fs { static diff --git a/src/fs_mktemp.cpp b/src/fs_mktemp.cpp index 1f2166eb..bd4ea2cf 100644 --- a/src/fs_mktemp.cpp +++ b/src/fs_mktemp.cpp @@ -29,6 +29,7 @@ using std::string; #define PADLEN 6 #define MAX_ATTEMPTS 10 + static string generate_tmp_path(const string &base_) diff --git a/src/fs_mktemp.hpp b/src/fs_mktemp.hpp index 2bd19b16..aecf0e74 100644 --- a/src/fs_mktemp.hpp +++ b/src/fs_mktemp.hpp @@ -20,6 +20,7 @@ #include + namespace fs { int diff --git a/src/fs_movefile.cpp b/src/fs_movefile.cpp index 2c2c13e2..bd9c37b6 100644 --- a/src/fs_movefile.cpp +++ b/src/fs_movefile.cpp @@ -43,12 +43,13 @@ using std::string; using std::vector; + namespace l { static int - movefile(Policy::Func::Create createFunc_, - const Branches &branches_, + movefile(const Policy::Create &createFunc_, + const Branches::CPtr &branches_, const string &fusepath_, int *origfd_) { @@ -132,19 +133,19 @@ namespace l namespace fs { int - movefile(const Policy *policy_, - const Branches &basepaths_, - const string &fusepath_, - int *origfd_) + movefile(const Policy::Create &policy_, + const Branches::CPtr &basepaths_, + const string &fusepath_, + int *origfd_) { return l::movefile(policy_,basepaths_,fusepath_,origfd_); } int - movefile_as_root(const Policy *policy_, - const Branches &basepaths_, - const string &fusepath_, - int *origfd_) + movefile_as_root(const Policy::Create &policy_, + const Branches::CPtr &basepaths_, + const string &fusepath_, + int *origfd_) { const ugid::Set ugid(0,0); diff --git a/src/fs_movefile.hpp b/src/fs_movefile.hpp index 7b21312e..8df1e1c2 100644 --- a/src/fs_movefile.hpp +++ b/src/fs_movefile.hpp @@ -16,22 +16,23 @@ #pragma once -#include "branch.hpp" +#include "branches.hpp" #include "policy.hpp" #include + namespace fs { int - movefile(const Policy *policy, - const Branches &branches, - const std::string &fusepath, - int *origfd); + movefile(const Policy::Create &policy, + const Branches::CPtr &branches, + const std::string &fusepath, + int *origfd); int - movefile_as_root(const Policy *policy, - const Branches &branches, - const std::string &fusepath, - int *origfd); + movefile_as_root(const Policy::Create &policy, + const Branches::CPtr &branches, + const std::string &fusepath, + int *origfd); } diff --git a/src/fs_open.hpp b/src/fs_open.hpp index 2e4a7279..02364361 100644 --- a/src/fs_open.hpp +++ b/src/fs_open.hpp @@ -24,6 +24,7 @@ #include #include + namespace fs { static diff --git a/src/fs_opendir.hpp b/src/fs_opendir.hpp index 7b62aecf..a7f1197e 100644 --- a/src/fs_opendir.hpp +++ b/src/fs_opendir.hpp @@ -23,6 +23,7 @@ #include #include + namespace fs { static diff --git a/src/fs_path.cpp b/src/fs_path.cpp index 861973f3..90c65a5c 100644 --- a/src/fs_path.cpp +++ b/src/fs_path.cpp @@ -14,17 +14,18 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "fs_path.hpp" + +#include + #include #include #include #include -#include - -#include "fs_path.hpp" - using std::string; + namespace fs { namespace path diff --git a/src/fs_path.hpp b/src/fs_path.hpp index 531c21df..d36b8fd6 100644 --- a/src/fs_path.hpp +++ b/src/fs_path.hpp @@ -19,6 +19,7 @@ #include #include + namespace fs { namespace path diff --git a/src/fs_read.hpp b/src/fs_read.hpp index d794543e..c1021fe7 100644 --- a/src/fs_read.hpp +++ b/src/fs_read.hpp @@ -20,6 +20,7 @@ #include + namespace fs { static diff --git a/src/fs_readdir.hpp b/src/fs_readdir.hpp index 7a82d61e..cad0d643 100644 --- a/src/fs_readdir.hpp +++ b/src/fs_readdir.hpp @@ -20,6 +20,7 @@ #include + namespace fs { static diff --git a/src/fs_readlink.hpp b/src/fs_readlink.hpp index a8fc1a5b..0cd2df0f 100644 --- a/src/fs_readlink.hpp +++ b/src/fs_readlink.hpp @@ -22,6 +22,7 @@ #include + namespace fs { static diff --git a/src/fs_realpath.hpp b/src/fs_realpath.hpp index d31a270c..31c30316 100644 --- a/src/fs_realpath.hpp +++ b/src/fs_realpath.hpp @@ -23,6 +23,7 @@ #include #include + namespace fs { static diff --git a/src/fs_realpathize.cpp b/src/fs_realpathize.cpp index 42db33b6..fe85d2d2 100644 --- a/src/fs_realpathize.cpp +++ b/src/fs_realpathize.cpp @@ -21,6 +21,7 @@ #include #include + namespace fs { void diff --git a/src/fs_realpathize.hpp b/src/fs_realpathize.hpp index dfd6270d..0702097e 100644 --- a/src/fs_realpathize.hpp +++ b/src/fs_realpathize.hpp @@ -21,6 +21,7 @@ #include #include + namespace fs { void diff --git a/src/fs_remove.hpp b/src/fs_remove.hpp index 07ae25cc..b9d7f417 100644 --- a/src/fs_remove.hpp +++ b/src/fs_remove.hpp @@ -22,6 +22,7 @@ #include + namespace fs { static diff --git a/src/fs_rename.hpp b/src/fs_rename.hpp index 7bfdba7e..a0fe92b3 100644 --- a/src/fs_rename.hpp +++ b/src/fs_rename.hpp @@ -20,6 +20,7 @@ #include + namespace fs { static diff --git a/src/fs_rmdir.hpp b/src/fs_rmdir.hpp index d87a3f42..dd39a5b4 100644 --- a/src/fs_rmdir.hpp +++ b/src/fs_rmdir.hpp @@ -22,6 +22,7 @@ #include + namespace fs { static diff --git a/src/fs_sendfile.hpp b/src/fs_sendfile.hpp index 54238426..ae2fb017 100644 --- a/src/fs_sendfile.hpp +++ b/src/fs_sendfile.hpp @@ -16,6 +16,7 @@ #pragma once + namespace fs { ssize_t diff --git a/src/fs_sendfile_linux.icpp b/src/fs_sendfile_linux.icpp index a6291ddc..5f62c70a 100644 --- a/src/fs_sendfile_linux.icpp +++ b/src/fs_sendfile_linux.icpp @@ -14,9 +14,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "errno.hpp" + #include -#include "errno.hpp" namespace fs { diff --git a/src/fs_sendfile_unsupported.icpp b/src/fs_sendfile_unsupported.icpp index a08fc1a4..96a8827a 100644 --- a/src/fs_sendfile_unsupported.icpp +++ b/src/fs_sendfile_unsupported.icpp @@ -14,9 +14,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "errno.hpp" + #include -#include "errno.hpp" namespace fs { diff --git a/src/fs_setfl.cpp b/src/fs_setfl.cpp index faf1b2e4..7251c66b 100644 --- a/src/fs_setfl.cpp +++ b/src/fs_setfl.cpp @@ -18,6 +18,7 @@ #include + namespace fs { int diff --git a/src/fs_setfl.hpp b/src/fs_setfl.hpp index 9b146f10..31c07f71 100644 --- a/src/fs_setfl.hpp +++ b/src/fs_setfl.hpp @@ -20,6 +20,7 @@ #include + namespace fs { int diff --git a/src/fs_stat.hpp b/src/fs_stat.hpp index 5b5fed7c..b1c7c864 100644 --- a/src/fs_stat.hpp +++ b/src/fs_stat.hpp @@ -24,6 +24,7 @@ #include #include + namespace fs { static diff --git a/src/fs_stat_utils.hpp b/src/fs_stat_utils.hpp index 42f13dd8..777a7140 100644 --- a/src/fs_stat_utils.hpp +++ b/src/fs_stat_utils.hpp @@ -24,6 +24,7 @@ #include #include + namespace fs { static diff --git a/src/fs_statvfs.hpp b/src/fs_statvfs.hpp index 26f8a054..db0c1cf1 100644 --- a/src/fs_statvfs.hpp +++ b/src/fs_statvfs.hpp @@ -22,6 +22,7 @@ #include "fs_close.hpp" #include "fs_open.hpp" +#include #include #include @@ -30,6 +31,7 @@ # define O_PATH 0 #endif + namespace fs { static diff --git a/src/fs_statvfs_cache.cpp b/src/fs_statvfs_cache.cpp index 4cea84d0..a0c73192 100644 --- a/src/fs_statvfs_cache.cpp +++ b/src/fs_statvfs_cache.cpp @@ -19,14 +19,15 @@ #include "fs_statvfs.hpp" #include "statvfs_util.hpp" +#include #include #include #include -#include #include #include + struct Element { uint64_t time; diff --git a/src/fs_statvfs_cache.hpp b/src/fs_statvfs_cache.hpp index 1beb46f3..d48d075d 100644 --- a/src/fs_statvfs_cache.hpp +++ b/src/fs_statvfs_cache.hpp @@ -18,9 +18,11 @@ #pragma once -#include +#include + #include + namespace fs { uint64_t diff --git a/src/fs_symlink.hpp b/src/fs_symlink.hpp index 6fa9e535..1db1823e 100644 --- a/src/fs_symlink.hpp +++ b/src/fs_symlink.hpp @@ -22,6 +22,7 @@ #include + namespace fs { static diff --git a/src/fs_truncate.hpp b/src/fs_truncate.hpp index 512214cc..9a88ba60 100644 --- a/src/fs_truncate.hpp +++ b/src/fs_truncate.hpp @@ -23,6 +23,7 @@ #include #include + namespace fs { static diff --git a/src/fs_unlink.hpp b/src/fs_unlink.hpp index 08828595..5fad40d2 100644 --- a/src/fs_unlink.hpp +++ b/src/fs_unlink.hpp @@ -22,6 +22,7 @@ #include + namespace fs { static diff --git a/src/fs_utimensat_freebsd.hpp b/src/fs_utimensat_freebsd.hpp index ef3935ff..251c3f56 100644 --- a/src/fs_utimensat_freebsd.hpp +++ b/src/fs_utimensat_freebsd.hpp @@ -23,6 +23,7 @@ #include #include + namespace fs { static diff --git a/src/fs_utimensat_generic.hpp b/src/fs_utimensat_generic.hpp index 1834c0c3..2bd5bf26 100644 --- a/src/fs_utimensat_generic.hpp +++ b/src/fs_utimensat_generic.hpp @@ -36,6 +36,7 @@ # define UTIME_OMIT ((1l << 30) - 2l) #endif + namespace l { static diff --git a/src/fs_utimensat_linux.hpp b/src/fs_utimensat_linux.hpp index ef3935ff..251c3f56 100644 --- a/src/fs_utimensat_linux.hpp +++ b/src/fs_utimensat_linux.hpp @@ -23,6 +23,7 @@ #include #include + namespace fs { static diff --git a/src/fs_write.hpp b/src/fs_write.hpp index 96eebbb1..750bef03 100644 --- a/src/fs_write.hpp +++ b/src/fs_write.hpp @@ -20,6 +20,7 @@ #include + namespace fs { static diff --git a/src/fs_xattr.cpp b/src/fs_xattr.cpp index c73766d6..e7ac84a3 100644 --- a/src/fs_xattr.cpp +++ b/src/fs_xattr.cpp @@ -31,12 +31,12 @@ #include #include - using std::string; using std::vector; using std::map; using std::istringstream; + namespace fs { namespace xattr diff --git a/src/fs_xattr.hpp b/src/fs_xattr.hpp index caad0749..da7d2ba3 100644 --- a/src/fs_xattr.hpp +++ b/src/fs_xattr.hpp @@ -20,6 +20,7 @@ #include #include + namespace fs { namespace xattr diff --git a/src/func.cpp b/src/func.cpp index b82773ab..39aa7194 100644 --- a/src/func.cpp +++ b/src/func.cpp @@ -18,22 +18,45 @@ #include "func.hpp" + int -Func::from_string(const std::string &s_) +Func::Base::Action::from_string(const std::string &policyname_) +{ + policy = Policies::Action::find(policyname_); + + return 0; +} + +std::string +Func::Base::Action::to_string(void) const { - const Policy *tmp; + return policy.name(); +} - tmp = &Policy::find(s_); - if(tmp == Policy::invalid) - return -EINVAL; +int +Func::Base::Create::from_string(const std::string &policyname_) +{ + policy = Policies::Create::find(policyname_); - policy = tmp; + return 0; +} + +std::string +Func::Base::Create::to_string(void) const +{ + return policy.name(); +} + +int +Func::Base::Search::from_string(const std::string &policyname_) +{ + policy = Policies::Search::find(policyname_); return 0; } std::string -Func::to_string(void) const +Func::Base::Search::to_string(void) const { - return policy->to_string(); + return policy.name(); } diff --git a/src/func.hpp b/src/func.hpp index f1a390f3..97ef6f64 100644 --- a/src/func.hpp +++ b/src/func.hpp @@ -19,203 +19,166 @@ #pragma once #include "policy.hpp" +#include "policies.hpp" #include "tofrom_string.hpp" #include -#include -class Func : public ToFromString + +namespace Func { -public: - Func(const Policy &policy_) - : policy(&policy_) + namespace Base { - } + class Action : public ToFromString + { + public: + Action(Policy::ActionImpl *policy_) + : policy(policy_) + {} -public: - int from_string(const std::string &s); - std::string to_string() const; + public: + int from_string(const std::string &s) final; + std::string to_string() const final; -public: - const Policy *policy; -}; + public: + Policy::Action policy; + }; -class FuncAccess : public Func -{ -public: - FuncAccess() - : Func(Policy::ff) - { + class Create : public ToFromString + { + public: + Create(Policy::CreateImpl *policy_) + : policy(policy_) + {} + + public: + int from_string(const std::string &s) final; + std::string to_string() const final; + + public: + Policy::Create policy; + }; + + class Search : public ToFromString + { + public: + Search(Policy::SearchImpl *policy_) + : policy(policy_) + {} + + public: + int from_string(const std::string &s) final; + std::string to_string() const final; + + public: + Policy::Search policy; + }; + + class ActionDefault : public Action + { + public: + ActionDefault() + : Func::Base::Action(&Policies::Action::epall) + { + } + }; + + class CreateDefault : public Create + { + public: + CreateDefault() + : Func::Base::Create(&Policies::Create::epmfs) + { + } + }; + + class SearchDefault : public Search + { + public: + SearchDefault() + : Func::Base::Search(&Policies::Search::ff) + { + } + }; } -}; -class FuncChmod : public Func -{ -public: - FuncChmod() - : Func(Policy::epall) + class Access final : public Base::SearchDefault { - } -}; + }; -class FuncChown : public Func -{ -public: - FuncChown() - : Func(Policy::epall) + class Chmod final : public Base::ActionDefault { - } -}; + }; -class FuncCreate : public Func -{ -public: - FuncCreate() - : Func(Policy::epmfs) + class Chown final : public Base::ActionDefault { - } -}; + }; -class FuncGetAttr : public Func -{ -public: - FuncGetAttr() - : Func(Policy::ff) + class Create final : public Base::CreateDefault { - } -}; + }; -class FuncGetXAttr : public Func -{ -public: - FuncGetXAttr() - : Func(Policy::ff) + class GetAttr final : public Base::SearchDefault { - } -}; + }; -class FuncLink : public Func -{ -public: - FuncLink() - : Func(Policy::epall) + class GetXAttr final : public Base::SearchDefault { - } -}; + }; -class FuncListXAttr : public Func -{ -public: - FuncListXAttr() - : Func(Policy::ff) + class Link final : public Base::ActionDefault { - } -}; + }; -class FuncMkdir : public Func -{ -public: - FuncMkdir() - : Func(Policy::epmfs) + class ListXAttr final : public Base::SearchDefault { - } -}; + }; -class FuncMknod : public Func -{ -public: - FuncMknod() - : Func(Policy::epmfs) + class Mkdir final : public Base::CreateDefault { - } -}; + }; -class FuncOpen : public Func -{ -public: - FuncOpen() - : Func(Policy::ff) + class Mknod final : public Base::CreateDefault { - } -}; + }; -class FuncReadlink : public Func -{ -public: - FuncReadlink() - : Func(Policy::ff) + class Open final : public Base::SearchDefault { - } -}; + }; -class FuncRemoveXAttr : public Func -{ -public: - FuncRemoveXAttr() - : Func(Policy::epall) + class Readlink final : public Base::SearchDefault { - } -}; + }; -class FuncRename : public Func -{ -public: - FuncRename() - : Func(Policy::epall) + class RemoveXAttr final : public Base::ActionDefault { - } -}; + }; -class FuncRmdir : public Func -{ -public: - FuncRmdir() - : Func(Policy::epall) + class Rename final : public Base::ActionDefault { - } -}; + }; -class FuncSetXAttr : public Func -{ -public: - FuncSetXAttr() - : Func(Policy::epall) + class Rmdir final : public Base::ActionDefault { - } -}; + }; -class FuncSymlink : public Func -{ -public: - FuncSymlink() - : Func(Policy::epmfs) + class SetXAttr final : public Base::ActionDefault { - } -}; + }; -class FuncTruncate : public Func -{ -public: - FuncTruncate() - : Func(Policy::epall) + class Symlink final : public Base::CreateDefault { - } -}; + }; -class FuncUnlink : public Func -{ -public: - FuncUnlink() - : Func(Policy::epall) + class Truncate final : public Base::ActionDefault { - } -}; + }; -class FuncUtimens : public Func -{ -public: - FuncUtimens() - : Func(Policy::epall) + class Unlink final : public Base::ActionDefault { - } -}; + }; + + class Utimens final : public Base::ActionDefault + { + }; +} diff --git a/src/func_category.cpp b/src/func_category.cpp deleted file mode 100644 index eb60c9d3..00000000 --- a/src/func_category.cpp +++ /dev/null @@ -1,90 +0,0 @@ -/* - ISC License - - Copyright (c) 2019, Antonio SJ Musumeci - - 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 "func_category.hpp" -#include "str.hpp" - -#include "buildvector.hpp" - -#include -#include -#include - -int -FuncCategory::from_string(const std::string &s_) -{ - const Policy *tmp; - - tmp = &Policy::find(s_); - if(tmp == &Policy::invalid) - return -EINVAL; - - for(uint64_t i = 0; i < _funcs.size(); i++) - _funcs[i]->policy = tmp; - - return 0; -} - -std::string -FuncCategory::to_string(void) const -{ - std::vector rv; - - for(uint64_t i = 0; i < _funcs.size(); i++) - rv.push_back(_funcs[i]->policy->to_string()); - - std::sort(rv.begin(),rv.end()); - rv.erase(std::unique(rv.begin(),rv.end()),rv.end()); - - return str::join(rv,','); -} - -FuncCategoryCreate::FuncCategoryCreate(Funcs &funcs_) -{ - _funcs = buildvector - (&funcs_.create) - (&funcs_.mkdir) - (&funcs_.mknod) - (&funcs_.symlink); -} - -FuncCategoryAction::FuncCategoryAction(Funcs &funcs_) -{ - _funcs = buildvector - (&funcs_.chmod) - (&funcs_.chown) - (&funcs_.link) - (&funcs_.removexattr) - (&funcs_.rename) - (&funcs_.rmdir) - (&funcs_.setxattr) - (&funcs_.truncate) - (&funcs_.unlink) - (&funcs_.utimens); -} - -FuncCategorySearch::FuncCategorySearch(Funcs &funcs_) -{ - _funcs = buildvector - (&funcs_.access) - (&funcs_.getattr) - (&funcs_.getxattr) - (&funcs_.listxattr) - (&funcs_.open) - (&funcs_.readlink); -} diff --git a/src/func_category.hpp b/src/func_category.hpp deleted file mode 100644 index 775239f5..00000000 --- a/src/func_category.hpp +++ /dev/null @@ -1,69 +0,0 @@ -/* - ISC License - - Copyright (c) 2019, Antonio SJ Musumeci - - 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 "funcs.hpp" -#include "tofrom_string.hpp" - -#include -#include - -class FuncCategory : public ToFromString -{ -public: - int from_string(const std::string &); - std::string to_string(void) const; - -protected: - std::vector _funcs; -}; - -class FuncCategoryCreate : public FuncCategory -{ -public: - FuncCategoryCreate(Funcs &funcs_); -}; - -class FuncCategoryAction : public FuncCategory -{ -public: - FuncCategoryAction(Funcs &funcs_); -}; - -class FuncCategorySearch : public FuncCategory -{ -public: - FuncCategorySearch(Funcs &funcs_); -}; - -class FuncCategories -{ -public: - FuncCategories(Funcs &funcs_) - : action(funcs_), - create(funcs_), - search(funcs_) - { - } - -public: - FuncCategoryAction action; - FuncCategoryCreate create; - FuncCategorySearch search; -}; diff --git a/src/funcs.hpp b/src/funcs.hpp index a482b36e..dbb1eb8c 100644 --- a/src/funcs.hpp +++ b/src/funcs.hpp @@ -20,27 +20,27 @@ #include "func.hpp" -class Funcs + +struct Funcs { -public: - FuncAccess access; - FuncChmod chmod; - FuncChown chown; - FuncCreate create; - FuncGetAttr getattr; - FuncGetXAttr getxattr; - FuncLink link; - FuncListXAttr listxattr; - FuncMkdir mkdir; - FuncMknod mknod; - FuncOpen open; - FuncReadlink readlink; - FuncRemoveXAttr removexattr; - FuncRename rename; - FuncRmdir rmdir; - FuncSetXAttr setxattr; - FuncSymlink symlink; - FuncTruncate truncate; - FuncUnlink unlink; - FuncUtimens utimens; + Func::Access access; + Func::Chmod chmod; + Func::Chown chown; + Func::Create create; + Func::GetAttr getattr; + Func::GetXAttr getxattr; + Func::Link link; + Func::ListXAttr listxattr; + Func::Mkdir mkdir; + Func::Mknod mknod; + Func::Open open; + Func::Readlink readlink; + Func::RemoveXAttr removexattr; + Func::Rename rename; + Func::Rmdir rmdir; + Func::SetXAttr setxattr; + Func::Symlink symlink; + Func::Truncate truncate; + Func::Unlink unlink; + Func::Utimens utimens; }; diff --git a/src/fuse_access.cpp b/src/fuse_access.cpp index e9705ce3..6e196295 100644 --- a/src/fuse_access.cpp +++ b/src/fuse_access.cpp @@ -26,26 +26,27 @@ using std::string; using std::vector; + namespace l { static int - access(Policy::Func::Search searchFunc, + access(const Policy::Search &searchFunc_, const Branches &branches_, - const char *fusepath, - const int mask) + const char *fusepath_, + const int mask_) { int rv; string fullpath; - vector basepaths; + StrVec basepaths; - rv = searchFunc(branches_,fusepath,&basepaths); + rv = searchFunc_(branches_,fusepath_,&basepaths); if(rv == -1) return -errno; - fullpath = fs::path::make(basepaths[0],fusepath); + fullpath = fs::path::make(basepaths[0],fusepath_); - rv = fs::eaccess(fullpath,mask); + rv = fs::eaccess(fullpath,mask_); return ((rv == -1) ? -errno : 0); } @@ -54,16 +55,16 @@ namespace l namespace FUSE { int - access(const char *fusepath, - int mask) + access(const char *fusepath_, + int mask_) { - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::access(config.func.access.policy, - config.branches, - fusepath, - mask); + return l::access(cfg->func.access.policy, + cfg->branches, + fusepath_, + mask_); } } diff --git a/src/fuse_access.hpp b/src/fuse_access.hpp index 7fc64277..72386aae 100644 --- a/src/fuse_access.hpp +++ b/src/fuse_access.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { int diff --git a/src/fuse_chmod.cpp b/src/fuse_chmod.cpp index 938427b9..c2e0e709 100644 --- a/src/fuse_chmod.cpp +++ b/src/fuse_chmod.cpp @@ -24,12 +24,10 @@ #include "fuse.h" #include -#include #include using std::string; -using std::vector; namespace l @@ -73,10 +71,10 @@ namespace l static void - chmod_loop(const vector &basepaths_, - const char *fusepath_, - const mode_t mode_, - PolicyRV *prv_) + chmod_loop(const StrVec &basepaths_, + const char *fusepath_, + const mode_t mode_, + PolicyRV *prv_) { for(size_t i = 0, ei = basepaths_.size(); i != ei; i++) { @@ -86,15 +84,15 @@ namespace l static int - chmod(Policy::Func::Action actionFunc_, - Policy::Func::Search searchFunc_, + chmod(const Policy::Action &actionFunc_, + const Policy::Search &searchFunc_, const Branches &branches_, const char *fusepath_, const mode_t mode_) { int rv; PolicyRV prv; - vector basepaths; + StrVec basepaths; rv = actionFunc_(branches_,fusepath_,&basepaths); if(rv == -1) @@ -121,13 +119,13 @@ namespace FUSE chmod(const char *fusepath_, mode_t mode_) { - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::chmod(config.func.chmod.policy, - config.func.getattr.policy, - config.branches, + return l::chmod(cfg->func.chmod.policy, + cfg->func.getattr.policy, + cfg->branches, fusepath_, mode_); } diff --git a/src/fuse_chmod.hpp b/src/fuse_chmod.hpp index 6bbcdb40..ea335a34 100644 --- a/src/fuse_chmod.hpp +++ b/src/fuse_chmod.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { int diff --git a/src/fuse_chown.cpp b/src/fuse_chown.cpp index 70788687..106545b4 100644 --- a/src/fuse_chown.cpp +++ b/src/fuse_chown.cpp @@ -21,7 +21,7 @@ #include "policy_rv.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include #include @@ -86,8 +86,8 @@ namespace l static int - chown(Policy::Func::Action actionFunc_, - Policy::Func::Search searchFunc_, + chown(const Policy::Action &actionFunc_, + const Policy::Search &searchFunc_, const Branches &branches_, const char *fusepath_, const uid_t uid_, @@ -123,13 +123,13 @@ namespace FUSE uid_t uid_, gid_t gid_) { - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::chown(config.func.chown.policy, - config.func.getattr.policy, - config.branches, + return l::chown(cfg->func.chown.policy, + cfg->func.getattr.policy, + cfg->branches, fusepath_, uid_, gid_); diff --git a/src/fuse_chown.hpp b/src/fuse_chown.hpp index cda0058d..1a367acf 100644 --- a/src/fuse_chown.hpp +++ b/src/fuse_chown.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { int diff --git a/src/fuse_copy_file_range.cpp b/src/fuse_copy_file_range.cpp index 2c88733e..34988d86 100644 --- a/src/fuse_copy_file_range.cpp +++ b/src/fuse_copy_file_range.cpp @@ -18,10 +18,11 @@ #include "fileinfo.hpp" #include "fs_copy_file_range.hpp" -#include +#include "fuse.h" #include + namespace l { static diff --git a/src/fuse_copy_file_range.hpp b/src/fuse_copy_file_range.hpp index 30185ad3..ef18a3e6 100644 --- a/src/fuse_copy_file_range.hpp +++ b/src/fuse_copy_file_range.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { ssize_t diff --git a/src/fuse_create.cpp b/src/fuse_create.cpp index 4a854d1a..5d66d5eb 100644 --- a/src/fuse_create.cpp +++ b/src/fuse_create.cpp @@ -23,7 +23,7 @@ #include "fs_path.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include #include @@ -31,6 +31,7 @@ using std::string; using std::vector; + namespace l { /* @@ -54,15 +55,15 @@ namespace l static void - config_to_ffi_flags(const Config &config_, + config_to_ffi_flags(Config::Read &cfg_, fuse_file_info_t *ffi_) { - switch(config_.cache_files) + switch(cfg_->cache_files) { case CacheFiles::ENUM::LIBFUSE: - ffi_->direct_io = config_.direct_io; - ffi_->keep_cache = config_.kernel_cache; - ffi_->auto_cache = config_.auto_cache; + ffi_->direct_io = cfg_->direct_io; + ffi_->keep_cache = cfg_->kernel_cache; + ffi_->auto_cache = cfg_->auto_cache; break; case CacheFiles::ENUM::OFF: ffi_->direct_io = 1; @@ -125,8 +126,8 @@ namespace l static int - create(Policy::Func::Search searchFunc_, - Policy::Func::Create createFunc_, + create(const Policy::Search &searchFunc_, + const Policy::Create &createFunc_, const Branches &branches_, const char *fusepath_, const mode_t mode_, @@ -137,8 +138,8 @@ namespace l int rv; string fullpath; string fusedirpath; - vector createpaths; - vector existingpaths; + StrVec createpaths; + StrVec existingpaths; fusedirpath = fs::path::dirname(fusepath_); @@ -170,18 +171,18 @@ namespace FUSE mode_t mode_, fuse_file_info_t *ffi_) { - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - l::config_to_ffi_flags(config,ffi_); + l::config_to_ffi_flags(cfg,ffi_); - if(config.writeback_cache) + if(cfg->writeback_cache) l::tweak_flags_writeback_cache(&ffi_->flags); - return l::create(config.func.getattr.policy, - config.func.create.policy, - config.branches, + return l::create(cfg->func.getattr.policy, + cfg->func.create.policy, + cfg->branches, fusepath_, mode_, fc->umask, diff --git a/src/fuse_create.hpp b/src/fuse_create.hpp index 0fa08a80..36a74d17 100644 --- a/src/fuse_create.hpp +++ b/src/fuse_create.hpp @@ -16,10 +16,11 @@ #pragma once -#include +#include "fuse.h" #include + namespace FUSE { int diff --git a/src/fuse_destroy.hpp b/src/fuse_destroy.hpp index 60ae8577..31410ee3 100644 --- a/src/fuse_destroy.hpp +++ b/src/fuse_destroy.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { void diff --git a/src/fuse_fallocate.cpp b/src/fuse_fallocate.cpp index 8235ce43..c1b4e82d 100644 --- a/src/fuse_fallocate.cpp +++ b/src/fuse_fallocate.cpp @@ -18,7 +18,8 @@ #include "fileinfo.hpp" #include "fs_fallocate.hpp" -#include +#include "fuse.h" + namespace l { diff --git a/src/fuse_fallocate.hpp b/src/fuse_fallocate.hpp index f29e4a7f..978cc032 100644 --- a/src/fuse_fallocate.hpp +++ b/src/fuse_fallocate.hpp @@ -18,6 +18,7 @@ #include "fuse.h" + namespace FUSE { int diff --git a/src/fuse_fchmod.cpp b/src/fuse_fchmod.cpp index 3b8cdf8c..27d802de 100644 --- a/src/fuse_fchmod.cpp +++ b/src/fuse_fchmod.cpp @@ -18,7 +18,8 @@ #include "fileinfo.hpp" #include "fs_fchmod.hpp" -#include +#include "fuse.h" + namespace l { diff --git a/src/fuse_fchmod.hpp b/src/fuse_fchmod.hpp index 96d4be7e..64f9e7a5 100644 --- a/src/fuse_fchmod.hpp +++ b/src/fuse_fchmod.hpp @@ -16,10 +16,11 @@ #pragma once -#include +#include "fuse.h" #include + namespace FUSE { int diff --git a/src/fuse_fchown.cpp b/src/fuse_fchown.cpp index 5bf873ab..48e8aa16 100644 --- a/src/fuse_fchown.cpp +++ b/src/fuse_fchown.cpp @@ -18,10 +18,11 @@ #include "fileinfo.hpp" #include "fs_fchown.hpp" -#include +#include "fuse.h" #include + namespace l { static diff --git a/src/fuse_fchown.hpp b/src/fuse_fchown.hpp index 6b043282..991734f6 100644 --- a/src/fuse_fchown.hpp +++ b/src/fuse_fchown.hpp @@ -16,7 +16,8 @@ #pragma once -#include +#include "fuse.h" + namespace FUSE { diff --git a/src/fuse_fgetattr.cpp b/src/fuse_fgetattr.cpp index eb5242ec..bc8b44d4 100644 --- a/src/fuse_fgetattr.cpp +++ b/src/fuse_fgetattr.cpp @@ -20,7 +20,8 @@ #include "fs_fstat.hpp" #include "fs_inode.hpp" -#include +#include "fuse.h" + namespace l { @@ -50,15 +51,15 @@ namespace FUSE fuse_timeouts_t *timeout_) { int rv; - const Config &config = Config::ro(); + Config::Read cfg; FileInfo *fi = reinterpret_cast(ffi_->fh); rv = l::fgetattr(fi->fd,fi->fusepath,st_); timeout_->entry = ((rv >= 0) ? - config.cache_entry : - config.cache_negative_entry); - timeout_->attr = config.cache_attr; + cfg->cache_entry : + cfg->cache_negative_entry); + timeout_->attr = cfg->cache_attr; return rv; } diff --git a/src/fuse_fgetattr.hpp b/src/fuse_fgetattr.hpp index ce032ac5..e58a061a 100644 --- a/src/fuse_fgetattr.hpp +++ b/src/fuse_fgetattr.hpp @@ -16,12 +16,13 @@ #pragma once -#include +#include "fuse.h" #include #include #include + namespace FUSE { int diff --git a/src/fuse_flock.cpp b/src/fuse_flock.cpp index f1df49fa..4a6a2bb3 100644 --- a/src/fuse_flock.cpp +++ b/src/fuse_flock.cpp @@ -18,7 +18,8 @@ #include "fileinfo.hpp" #include "fs_flock.hpp" -#include +#include "fuse.h" + namespace l { diff --git a/src/fuse_flock.hpp b/src/fuse_flock.hpp index cab3c845..194da4de 100644 --- a/src/fuse_flock.hpp +++ b/src/fuse_flock.hpp @@ -16,7 +16,8 @@ #pragma once -#include +#include "fuse.h" + namespace FUSE { diff --git a/src/fuse_flush.cpp b/src/fuse_flush.cpp index 33935530..37dc87b2 100644 --- a/src/fuse_flush.cpp +++ b/src/fuse_flush.cpp @@ -19,7 +19,8 @@ #include "fs_close.hpp" #include "fs_dup.hpp" -#include +#include "fuse.h" + namespace l { diff --git a/src/fuse_flush.hpp b/src/fuse_flush.hpp index 27ca708b..b8d447c3 100644 --- a/src/fuse_flush.hpp +++ b/src/fuse_flush.hpp @@ -16,7 +16,8 @@ #pragma once -#include +#include "fuse.h" + namespace FUSE { diff --git a/src/fuse_free_hide.cpp b/src/fuse_free_hide.cpp index 778d4bf7..4c057d5f 100644 --- a/src/fuse_free_hide.cpp +++ b/src/fuse_free_hide.cpp @@ -19,7 +19,8 @@ #include "fileinfo.hpp" #include "fs_close.hpp" -#include +#include + namespace FUSE { diff --git a/src/fuse_free_hide.hpp b/src/fuse_free_hide.hpp index c8f7c471..8b6be9ee 100644 --- a/src/fuse_free_hide.hpp +++ b/src/fuse_free_hide.hpp @@ -18,7 +18,8 @@ #pragma once -#include +#include + namespace FUSE { diff --git a/src/fuse_fsync.cpp b/src/fuse_fsync.cpp index 96dbc083..1ab9824b 100644 --- a/src/fuse_fsync.cpp +++ b/src/fuse_fsync.cpp @@ -19,11 +19,12 @@ #include "fs_fdatasync.hpp" #include "fs_fsync.hpp" -#include +#include "fuse.h" #include #include + namespace l { static diff --git a/src/fuse_fsync.hpp b/src/fuse_fsync.hpp index c97e569f..58302504 100644 --- a/src/fuse_fsync.hpp +++ b/src/fuse_fsync.hpp @@ -16,12 +16,13 @@ #pragma once -#include +#include "fuse.h" + namespace FUSE { int fsync(const fuse_file_info_t *ffi, int isdatasync); - + } diff --git a/src/fuse_fsyncdir.cpp b/src/fuse_fsyncdir.cpp index 21ae8efd..1388b410 100644 --- a/src/fuse_fsyncdir.cpp +++ b/src/fuse_fsyncdir.cpp @@ -18,11 +18,12 @@ #include "dirinfo.hpp" #include "fs_fsync.hpp" -#include +#include "fuse.h" #include #include + namespace l { static diff --git a/src/fuse_fsyncdir.hpp b/src/fuse_fsyncdir.hpp index 7db828cd..e1eba800 100644 --- a/src/fuse_fsyncdir.hpp +++ b/src/fuse_fsyncdir.hpp @@ -16,7 +16,8 @@ #pragma once -#include +#include "fuse.h" + namespace FUSE { diff --git a/src/fuse_ftruncate.cpp b/src/fuse_ftruncate.cpp index c68a312f..4e3116d4 100644 --- a/src/fuse_ftruncate.cpp +++ b/src/fuse_ftruncate.cpp @@ -18,7 +18,8 @@ #include "fileinfo.hpp" #include "fs_ftruncate.hpp" -#include +#include "fuse.h" + namespace l { diff --git a/src/fuse_ftruncate.hpp b/src/fuse_ftruncate.hpp index 78c8fb9e..16d1c720 100644 --- a/src/fuse_ftruncate.hpp +++ b/src/fuse_ftruncate.hpp @@ -16,11 +16,12 @@ #pragma once -#include +#include "fuse.h" #include #include + namespace FUSE { int diff --git a/src/fuse_futimens.cpp b/src/fuse_futimens.cpp index 2f21b319..8dd27323 100644 --- a/src/fuse_futimens.cpp +++ b/src/fuse_futimens.cpp @@ -18,10 +18,11 @@ #include "fileinfo.hpp" #include "fs_futimens.hpp" -#include +#include "fuse.h" #include + namespace l { static diff --git a/src/fuse_futimens.hpp b/src/fuse_futimens.hpp index 6d149ed7..7e373cc4 100644 --- a/src/fuse_futimens.hpp +++ b/src/fuse_futimens.hpp @@ -16,10 +16,11 @@ #pragma once -#include +#include "fuse.h" #include + namespace FUSE { int diff --git a/src/fuse_getattr.cpp b/src/fuse_getattr.cpp index 54669a09..38ca49ae 100644 --- a/src/fuse_getattr.cpp +++ b/src/fuse_getattr.cpp @@ -22,13 +22,12 @@ #include "symlinkify.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include -#include using std::string; -using std::vector; + namespace l { @@ -59,7 +58,7 @@ namespace l static int - getattr(Policy::Func::Search searchFunc_, + getattr(const Policy::Search &searchFunc_, const Branches &branches_, const char *fusepath_, struct stat *st_, @@ -68,7 +67,7 @@ namespace l { int rv; string fullpath; - vector basepaths; + StrVec basepaths; rv = searchFunc_(branches_,fusepath_,&basepaths); if(rv == -1) @@ -87,36 +86,43 @@ namespace l return 0; } -} -namespace FUSE -{ int getattr(const char *fusepath_, struct stat *st_, fuse_timeouts_t *timeout_) { int rv; - const Config &config = Config::ro(); - - if(fusepath_ == config.controlfile) - return l::getattr_controlfile(st_); - + Config::Read cfg; const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - rv = l::getattr(config.func.getattr.policy, - config.branches, + rv = l::getattr(cfg->func.getattr.policy, + cfg->branches, fusepath_, st_, - config.symlinkify, - config.symlinkify_timeout); + cfg->symlinkify, + cfg->symlinkify_timeout); timeout_->entry = ((rv >= 0) ? - config.cache_entry : - config.cache_negative_entry); - timeout_->attr = config.cache_attr; + cfg->cache_entry : + cfg->cache_negative_entry); + timeout_->attr = cfg->cache_attr; return rv; } } + +namespace FUSE +{ + int + getattr(const char *fusepath_, + struct stat *st_, + fuse_timeouts_t *timeout_) + { + if(fusepath_ == CONTROLFILE) + return l::getattr_controlfile(st_); + + return l::getattr(fusepath_,st_,timeout_); + } +} diff --git a/src/fuse_getattr.hpp b/src/fuse_getattr.hpp index a41eccd1..03e4b6c1 100644 --- a/src/fuse_getattr.hpp +++ b/src/fuse_getattr.hpp @@ -20,6 +20,7 @@ #include #include + namespace FUSE { int diff --git a/src/fuse_getxattr.cpp b/src/fuse_getxattr.cpp index e0fd6ca8..2f8145a2 100644 --- a/src/fuse_getxattr.cpp +++ b/src/fuse_getxattr.cpp @@ -24,12 +24,11 @@ #include "ugid.hpp" #include "version.hpp" -#include +#include "fuse.h" #include #include #include -#include #include #include @@ -37,7 +36,7 @@ static const char SECURITY_CAPABILITY[] = "security.capability"; using std::string; -using std::vector; + namespace l { @@ -64,7 +63,7 @@ namespace l static int - getxattr_controlfile(const Config &config_, + getxattr_controlfile(Config::Read &cfg_, const char *attrname_, char *buf_, const size_t count_) @@ -73,13 +72,13 @@ namespace l size_t len; string key; string val; - vector attr; + StrVec attr; if(!str::startswith(attrname_,"user.mergerfs.")) return -ENOATTR; key = &attrname_[14]; - rv = config_.get(key,&val); + rv = cfg_->get(key,&val); if(rv < 0) return rv; @@ -117,16 +116,16 @@ namespace l static int - getxattr_user_mergerfs_allpaths(const Branches &branches_, - const char *fusepath_, - char *buf_, - const size_t count_) + getxattr_user_mergerfs_allpaths(const Branches::CPtr &branches_, + const char *fusepath_, + char *buf_, + const size_t count_) { string concated; - vector paths; - vector branches; + StrVec paths; + StrVec branches; - branches_.to_paths(branches); + branches_->to_paths(branches); fs::findallfiles(branches,fusepath_,&paths); @@ -145,7 +144,7 @@ namespace l char *buf_, const size_t count_) { - vector attr; + StrVec attr; str::split(attrname_,'.',&attr); @@ -163,7 +162,7 @@ namespace l static int - getxattr(Policy::Func::Search searchFunc_, + getxattr(const Policy::Search &searchFunc_, const Branches &branches_, const char *fusepath_, const char *attrname_, @@ -172,7 +171,7 @@ namespace l { int rv; string fullpath; - vector basepaths; + StrVec basepaths; rv = searchFunc_(branches_,fusepath_,&basepaths); if(rv == -1) @@ -201,26 +200,26 @@ namespace FUSE char *buf_, size_t count_) { - const Config &config = Config::ro(); + Config::Read cfg; - if(fusepath_ == config.controlfile) - return l::getxattr_controlfile(config, + if(fusepath_ == CONTROLFILE) + return l::getxattr_controlfile(cfg, attrname_, buf_, count_); - if((config.security_capability == false) && + if((cfg->security_capability == false) && l::is_attrname_security_capability(attrname_)) return -ENOATTR; - if(config.xattr.to_int()) - return -config.xattr.to_int(); + if(cfg->xattr.to_int()) + return -cfg->xattr.to_int(); const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::getxattr(config.func.getxattr.policy, - config.branches, + return l::getxattr(cfg->func.getxattr.policy, + cfg->branches, fusepath_, attrname_, buf_, diff --git a/src/fuse_getxattr.hpp b/src/fuse_getxattr.hpp index 4ff565c0..60869c87 100644 --- a/src/fuse_getxattr.hpp +++ b/src/fuse_getxattr.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { int diff --git a/src/fuse_init.cpp b/src/fuse_init.cpp index adda4c32..2dccd9c8 100644 --- a/src/fuse_init.cpp +++ b/src/fuse_init.cpp @@ -17,7 +17,8 @@ #include "config.hpp" #include "ugid.hpp" -#include +#include "fuse.h" + namespace l { @@ -64,16 +65,16 @@ namespace l static void want_if_capable_max_pages(fuse_conn_info *conn_, - Config &c_) + Config::Write &cfg_) { if(l::capable(conn_,FUSE_CAP_MAX_PAGES)) { l::want(conn_,FUSE_CAP_MAX_PAGES); - conn_->max_pages = c_.fuse_msg_size; + conn_->max_pages = cfg_->fuse_msg_size; } else { - c_.fuse_msg_size = FUSE_DEFAULT_MAX_PAGES_PER_REQ; + cfg_->fuse_msg_size = FUSE_DEFAULT_MAX_PAGES_PER_REQ; } } } @@ -83,24 +84,24 @@ namespace FUSE void * init(fuse_conn_info *conn_) { - Config &config = Config::rw(); + Config::Write cfg; ugid::init(); l::want_if_capable(conn_,FUSE_CAP_ASYNC_DIO); - l::want_if_capable(conn_,FUSE_CAP_ASYNC_READ,&config.async_read); + l::want_if_capable(conn_,FUSE_CAP_ASYNC_READ,&cfg->async_read); l::want_if_capable(conn_,FUSE_CAP_ATOMIC_O_TRUNC); l::want_if_capable(conn_,FUSE_CAP_BIG_WRITES); - l::want_if_capable(conn_,FUSE_CAP_CACHE_SYMLINKS,&config.cache_symlinks); + l::want_if_capable(conn_,FUSE_CAP_CACHE_SYMLINKS,&cfg->cache_symlinks); l::want_if_capable(conn_,FUSE_CAP_DONT_MASK); l::want_if_capable(conn_,FUSE_CAP_IOCTL_DIR); l::want_if_capable(conn_,FUSE_CAP_PARALLEL_DIROPS); - l::want_if_capable(conn_,FUSE_CAP_READDIR_PLUS,&config.readdirplus); + l::want_if_capable(conn_,FUSE_CAP_READDIR_PLUS,&cfg->readdirplus); //l::want_if_capable(conn_,FUSE_CAP_READDIR_PLUS_AUTO); - l::want_if_capable(conn_,FUSE_CAP_POSIX_ACL,&config.posix_acl); - l::want_if_capable(conn_,FUSE_CAP_WRITEBACK_CACHE,&config.writeback_cache); - l::want_if_capable_max_pages(conn_,config); + l::want_if_capable(conn_,FUSE_CAP_POSIX_ACL,&cfg->posix_acl); + l::want_if_capable(conn_,FUSE_CAP_WRITEBACK_CACHE,&cfg->writeback_cache); + l::want_if_capable_max_pages(conn_,cfg); - return &config; + return NULL; } } diff --git a/src/fuse_init.hpp b/src/fuse_init.hpp index d36b9070..5867d646 100644 --- a/src/fuse_init.hpp +++ b/src/fuse_init.hpp @@ -16,7 +16,8 @@ #pragma once -#include +#include "fuse.h" + namespace FUSE { diff --git a/src/fuse_ioctl.cpp b/src/fuse_ioctl.cpp index 88d49610..db7199e0 100644 --- a/src/fuse_ioctl.cpp +++ b/src/fuse_ioctl.cpp @@ -27,7 +27,7 @@ #include "str.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include #include @@ -134,7 +134,7 @@ namespace l static int - ioctl_dir_base(Policy::Func::Search searchFunc_, + ioctl_dir_base(const Policy::Search &searchFunc_, const Branches &branches_, const char *fusepath_, const uint32_t cmd_, @@ -144,7 +144,7 @@ namespace l int fd; int rv; string fullpath; - vector basepaths; + StrVec basepaths; rv = searchFunc_(branches_,fusepath_,&basepaths); if(rv == -1) @@ -170,13 +170,13 @@ namespace l void *data_, uint32_t *out_bufsz_) { - DirInfo *di = reinterpret_cast(ffi_->fh); - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + DirInfo *di = reinterpret_cast(ffi_->fh); + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::ioctl_dir_base(config.func.open.policy, - config.branches, + return l::ioctl_dir_base(cfg->func.open.policy, + cfg->branches, di->fusepath.c_str(), cmd_, data_, @@ -203,10 +203,10 @@ namespace l int read_keys(void *data_) { - std::string keys; - const Config &config = Config::ro(); + Config::Read cfg; + std::string keys; - config.keys(keys); + cfg->keys(keys); return l::strcpy(keys,data_); } @@ -215,17 +215,17 @@ namespace l int read_val(void *data_) { + Config::Read cfg; int rv; char *data; std::string key; std::string val; - const Config &config = Config::ro(); data = (char*)data_; data[sizeof(IOCTL_BUF) - 1] = '\0'; key = data; - rv = config.get(key,&val); + rv = cfg->get(key,&val); if(rv < 0) return rv; @@ -236,11 +236,11 @@ namespace l int write_val(void *data_) { + Config::Write cfg; char *data; std::string kv; std::string key; std::string val; - Config &config = Config::rw(); data = (char*)data_; data[sizeof(IOCTL_BUF) - 1] = '\0'; @@ -248,18 +248,18 @@ namespace l kv = data; str::splitkv(kv,'=',&key,&val); - return config.set(key,val); + return cfg->set(key,val); } static int - file_basepath(Policy::Func::Search searchFunc_, + file_basepath(const Policy::Search &searchFunc_, const Branches &branches_, const char *fusepath_, void *data_) { int rv; - vector basepaths; + StrVec basepaths; rv = searchFunc_(branches_,fusepath_,&basepaths); if(rv == -1) @@ -273,11 +273,11 @@ namespace l file_basepath(const fuse_file_info_t *ffi_, void *data_) { - const Config &config = Config::ro(); + Config::Read cfg; std::string &fusepath = reinterpret_cast(ffi_->fh)->fusepath; - return l::file_basepath(config.func.open.policy, - config.branches, + return l::file_basepath(cfg->func.open.policy, + cfg->branches, fusepath.c_str(), data_); } @@ -294,14 +294,14 @@ namespace l static int - file_fullpath(Policy::Func::Search searchFunc_, + file_fullpath(const Policy::Search &searchFunc_, const Branches &branches_, const string &fusepath_, void *data_) { int rv; string fullpath; - vector basepaths; + StrVec basepaths; rv = searchFunc_(branches_,fusepath_,&basepaths); if(rv == -1) @@ -317,11 +317,11 @@ namespace l file_fullpath(const fuse_file_info_t *ffi_, void *data_) { - const Config &config = Config::ro(); + Config::Read cfg; std::string &fusepath = reinterpret_cast(ffi_->fh)->fusepath; - return l::file_fullpath(config.func.open.policy, - config.branches, + return l::file_fullpath(cfg->func.open.policy, + cfg->branches, fusepath, data_); } @@ -331,13 +331,13 @@ namespace l file_allpaths(const fuse_file_info_t *ffi_, void *data_) { + Config::Read cfg; string concated; - vector paths; - vector branches; + StrVec paths; + StrVec branches; string &fusepath = reinterpret_cast(ffi_->fh)->fusepath; - const Config &config = Config::ro(); - config.branches.to_paths(branches); + cfg->branches->to_paths(branches); fs::findallfiles(branches,fusepath.c_str(),&paths); diff --git a/src/fuse_ioctl.hpp b/src/fuse_ioctl.hpp index 98b6f863..11ea6233 100644 --- a/src/fuse_ioctl.hpp +++ b/src/fuse_ioctl.hpp @@ -16,7 +16,10 @@ #pragma once -#include +#include + +#include "fuse.h" + namespace FUSE { diff --git a/src/fuse_link.cpp b/src/fuse_link.cpp index ecc1ed41..4b06adcf 100644 --- a/src/fuse_link.cpp +++ b/src/fuse_link.cpp @@ -21,7 +21,7 @@ #include "fs_path.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include #include @@ -29,6 +29,7 @@ using std::string; using std::vector; + namespace error { static @@ -73,11 +74,11 @@ namespace l static int - link_create_path_loop(const vector &oldbasepaths_, - const string &newbasepath_, - const char *oldfusepath_, - const char *newfusepath_, - const string &newfusedirpath_) + link_create_path_loop(const StrVec &oldbasepaths_, + const string &newbasepath_, + const char *oldfusepath_, + const char *newfusepath_, + const string &newfusedirpath_) { int rv; int error; @@ -99,16 +100,16 @@ namespace l static int - link_create_path(Policy::Func::Search searchFunc_, - Policy::Func::Action actionFunc_, + link_create_path(const Policy::Search &searchFunc_, + const Policy::Action &actionFunc_, const Branches &branches_, const char *oldfusepath_, const char *newfusepath_) { int rv; string newfusedirpath; - vector oldbasepaths; - vector newbasepaths; + StrVec oldbasepaths; + StrVec newbasepaths; rv = actionFunc_(branches_,oldfusepath_,&oldbasepaths); if(rv == -1) @@ -127,8 +128,8 @@ namespace l static int - clonepath_if_would_create(Policy::Func::Search searchFunc_, - Policy::Func::Create createFunc_, + clonepath_if_would_create(const Policy::Search &searchFunc_, + const Policy::Create &createFunc_, const Branches &branches_, const string &oldbasepath_, const char *oldfusepath_, @@ -136,7 +137,7 @@ namespace l { int rv; string newfusedirpath; - vector newbasepath; + StrVec newbasepath; newfusedirpath = fs::path::dirname(newfusepath_); @@ -156,8 +157,8 @@ namespace l static int - link_preserve_path_core(Policy::Func::Search searchFunc_, - Policy::Func::Create createFunc_, + link_preserve_path_core(const Policy::Search &searchFunc_, + const Policy::Create &createFunc_, const Branches &branches_, const string &oldbasepath_, const char *oldfusepath_, @@ -187,12 +188,12 @@ namespace l static int - link_preserve_path_loop(Policy::Func::Search searchFunc_, - Policy::Func::Create createFunc_, + link_preserve_path_loop(const Policy::Search &searchFunc_, + const Policy::Create &createFunc_, const Branches &branches_, const char *oldfusepath_, const char *newfusepath_, - const vector &oldbasepaths_) + const StrVec &oldbasepaths_) { int error; @@ -211,15 +212,15 @@ namespace l static int - link_preserve_path(Policy::Func::Search searchFunc_, - Policy::Func::Action actionFunc_, - Policy::Func::Create createFunc_, + link_preserve_path(const Policy::Search &searchFunc_, + const Policy::Action &actionFunc_, + const Policy::Create &createFunc_, const Branches &branches_, const char *oldfusepath_, const char *newfusepath_) { int rv; - vector oldbasepaths; + StrVec oldbasepaths; rv = actionFunc_(branches_,oldfusepath_,&oldbasepaths); if(rv == -1) @@ -238,21 +239,21 @@ namespace FUSE link(const char *from_, const char *to_) { - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - if(config.func.create.policy->path_preserving() && !config.ignorepponrename) - return l::link_preserve_path(config.func.getattr.policy, - config.func.link.policy, - config.func.create.policy, - config.branches, + if(cfg->func.create.policy.path_preserving() && !cfg->ignorepponrename) + return l::link_preserve_path(cfg->func.getattr.policy, + cfg->func.link.policy, + cfg->func.create.policy, + cfg->branches, from_, to_); - return l::link_create_path(config.func.link.policy, - config.func.create.policy, - config.branches, + return l::link_create_path(cfg->func.getattr.policy, + cfg->func.link.policy, + cfg->branches, from_, to_); } diff --git a/src/fuse_link.hpp b/src/fuse_link.hpp index bb1eb2ec..ab601f88 100644 --- a/src/fuse_link.hpp +++ b/src/fuse_link.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { int diff --git a/src/fuse_listxattr.cpp b/src/fuse_listxattr.cpp index 29b3f57c..1f69b15c 100644 --- a/src/fuse_listxattr.cpp +++ b/src/fuse_listxattr.cpp @@ -14,7 +14,6 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "buildvector.hpp" #include "category.hpp" #include "config.hpp" #include "errno.hpp" @@ -23,27 +22,26 @@ #include "ugid.hpp" #include "xattr.hpp" -#include +#include "fuse.h" #include -#include #include using std::string; -using std::vector; + namespace l { static int - listxattr_controlfile(const Config &config_, + listxattr_controlfile(Config::Read &cfg_, char *list_, const size_t size_) { string xattrs; - config_.keys_xattr(xattrs); + cfg_->keys_xattr(xattrs); if(size_ == 0) return xattrs.size(); @@ -57,7 +55,7 @@ namespace l static int - listxattr(Policy::Func::Search searchFunc_, + listxattr(const Policy::Search &searchFunc_, const Branches &branches_, const char *fusepath_, char *list_, @@ -65,7 +63,7 @@ namespace l { int rv; string fullpath; - vector basepaths; + StrVec basepaths; rv = searchFunc_(branches_,fusepath_,&basepaths); if(rv == -1) @@ -86,12 +84,12 @@ namespace FUSE char *list_, size_t size_) { - const Config &config = Config::ro(); + Config::Read cfg; - if(fusepath_ == config.controlfile) - return l::listxattr_controlfile(config,list_,size_); + if(fusepath_ == CONTROLFILE) + return l::listxattr_controlfile(cfg,list_,size_); - switch(config.xattr) + switch(cfg->xattr) { case XAttr::ENUM::PASSTHROUGH: break; @@ -104,8 +102,8 @@ namespace FUSE const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::listxattr(config.func.listxattr.policy, - config.branches, + return l::listxattr(cfg->func.listxattr.policy, + cfg->branches, fusepath_, list_, size_); diff --git a/src/fuse_listxattr.hpp b/src/fuse_listxattr.hpp index cef0b91c..f06c32c8 100644 --- a/src/fuse_listxattr.hpp +++ b/src/fuse_listxattr.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { int diff --git a/src/fuse_mkdir.cpp b/src/fuse_mkdir.cpp index 66efccd7..c8bc3e57 100644 --- a/src/fuse_mkdir.cpp +++ b/src/fuse_mkdir.cpp @@ -20,15 +20,15 @@ #include "fs_clonepath.hpp" #include "fs_mkdir.hpp" #include "fs_path.hpp" +#include "policy.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include -#include using std::string; -using std::vector; + namespace error { @@ -84,12 +84,12 @@ namespace l static int - mkdir_loop(const string &existingpath_, - const vector &createpaths_, - const char *fusepath_, - const string &fusedirpath_, - const mode_t mode_, - const mode_t umask_) + mkdir_loop(const string &existingpath_, + const StrVec &createpaths_, + const char *fusepath_, + const string &fusedirpath_, + const mode_t mode_, + const mode_t umask_) { int rv; int error; @@ -113,8 +113,8 @@ namespace l static int - mkdir(Policy::Func::Search searchFunc_, - Policy::Func::Create createFunc_, + mkdir(const Policy::Search &getattrPolicy_, + const Policy::Create &mkdirPolicy_, const Branches &branches_, const char *fusepath_, const mode_t mode_, @@ -122,16 +122,16 @@ namespace l { int rv; string fusedirpath; - vector createpaths; - vector existingpaths; + StrVec createpaths; + StrVec existingpaths; fusedirpath = fs::path::dirname(fusepath_); - rv = searchFunc_(branches_,fusedirpath,&existingpaths); + rv = getattrPolicy_(branches_,fusedirpath.c_str(),&existingpaths); if(rv == -1) return -errno; - rv = createFunc_(branches_,fusedirpath,&createpaths); + rv = mkdirPolicy_(branches_,fusedirpath.c_str(),&createpaths); if(rv == -1) return -errno; @@ -150,13 +150,13 @@ namespace FUSE mkdir(const char *fusepath_, mode_t mode_) { - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::mkdir(config.func.getattr.policy, - config.func.mkdir.policy, - config.branches, + return l::mkdir(cfg->func.getattr.policy, + cfg->func.mkdir.policy, + cfg->branches, fusepath_, mode_, fc->umask); diff --git a/src/fuse_mkdir.hpp b/src/fuse_mkdir.hpp index e70fa64e..f2c515b2 100644 --- a/src/fuse_mkdir.hpp +++ b/src/fuse_mkdir.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { int diff --git a/src/fuse_mknod.cpp b/src/fuse_mknod.cpp index 042efefc..ad7b4f46 100644 --- a/src/fuse_mknod.cpp +++ b/src/fuse_mknod.cpp @@ -22,7 +22,7 @@ #include "fs_path.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include #include @@ -30,6 +30,7 @@ using std::string; using std::vector; + namespace error { static @@ -115,8 +116,8 @@ namespace l static int - mknod(Policy::Func::Search searchFunc_, - Policy::Func::Create createFunc_, + mknod(const Policy::Search &searchFunc_, + const Policy::Create &createFunc_, const Branches &branches_, const char *fusepath_, const mode_t mode_, @@ -151,13 +152,13 @@ namespace FUSE mode_t mode_, dev_t rdev_) { - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::mknod(config.func.getattr.policy, - config.func.mknod.policy, - config.branches, + return l::mknod(cfg->func.getattr.policy, + cfg->func.mknod.policy, + cfg->branches, fusepath_, mode_, fc->umask, diff --git a/src/fuse_mknod.hpp b/src/fuse_mknod.hpp index adb56d8d..6350f310 100644 --- a/src/fuse_mknod.hpp +++ b/src/fuse_mknod.hpp @@ -17,6 +17,7 @@ #pragma once + namespace FUSE { int diff --git a/src/fuse_open.cpp b/src/fuse_open.cpp index 583714f4..2e86fe5a 100644 --- a/src/fuse_open.cpp +++ b/src/fuse_open.cpp @@ -23,7 +23,6 @@ #include "fs_open.hpp" #include "fs_path.hpp" #include "fs_stat.hpp" -#include "policy_cache.hpp" #include "stat_util.hpp" #include "ugid.hpp" @@ -35,6 +34,7 @@ using std::string; using std::vector; + namespace l { static @@ -117,15 +117,15 @@ namespace l static void - config_to_ffi_flags(const Config &config_, + config_to_ffi_flags(Config::Read &cfg_, fuse_file_info_t *ffi_) { - switch(config_.cache_files) + switch(cfg_->cache_files) { case CacheFiles::ENUM::LIBFUSE: - ffi_->direct_io = config_.direct_io; - ffi_->keep_cache = config_.kernel_cache; - ffi_->auto_cache = config_.auto_cache; + ffi_->direct_io = cfg_->direct_io; + ffi_->keep_cache = cfg_->kernel_cache; + ffi_->auto_cache = cfg_->auto_cache; break; case CacheFiles::ENUM::OFF: ffi_->direct_io = 1; @@ -180,8 +180,7 @@ namespace l static int - open(Policy::Func::Search searchFunc_, - PolicyCache &cache, + open(const Policy::Search &searchFunc_, const Branches &branches_, const char *fusepath_, const int flags_, @@ -190,13 +189,13 @@ namespace l uint64_t *fh_) { int rv; - string basepath; + StrVec basepaths; - rv = cache(searchFunc_,branches_,fusepath_,&basepath); + rv = searchFunc_(branches_,fusepath_,&basepaths); if(rv == -1) return -errno; - return l::open_core(basepath,fusepath_,flags_,link_cow_,nfsopenhack_,fh_); + return l::open_core(basepaths[0],fusepath_,flags_,link_cow_,nfsopenhack_,fh_); } } @@ -206,22 +205,21 @@ namespace FUSE open(const char *fusepath_, fuse_file_info_t *ffi_) { - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - l::config_to_ffi_flags(config,ffi_); + l::config_to_ffi_flags(cfg,ffi_); - if(config.writeback_cache) + if(cfg->writeback_cache) l::tweak_flags_writeback_cache(&ffi_->flags); - return l::open(config.func.open.policy, - config.open_cache, - config.branches, + return l::open(cfg->func.open.policy, + cfg->branches, fusepath_, ffi_->flags, - config.link_cow, - config.nfsopenhack, + cfg->link_cow, + cfg->nfsopenhack, &ffi_->fh); } } diff --git a/src/fuse_open.hpp b/src/fuse_open.hpp index 2d7cadee..34c758bc 100644 --- a/src/fuse_open.hpp +++ b/src/fuse_open.hpp @@ -16,7 +16,8 @@ #pragma once -#include +#include "fuse.h" + namespace FUSE { diff --git a/src/fuse_opendir.cpp b/src/fuse_opendir.cpp index 6bd5e864..43c706ae 100644 --- a/src/fuse_opendir.cpp +++ b/src/fuse_opendir.cpp @@ -17,7 +17,8 @@ #include "config.hpp" #include "dirinfo.hpp" -#include +#include "fuse.h" + namespace FUSE { @@ -25,11 +26,11 @@ namespace FUSE opendir(const char *fusepath_, fuse_file_info_t *ffi_) { - const Config &config = Config::ro(); + Config::Read cfg; ffi_->fh = reinterpret_cast(new DirInfo(fusepath_)); - if(config.cache_readdir) + if(cfg->cache_readdir) { ffi_->keep_cache = 1; ffi_->cache_readdir = 1; diff --git a/src/fuse_opendir.hpp b/src/fuse_opendir.hpp index 7bc83339..1a2dca84 100644 --- a/src/fuse_opendir.hpp +++ b/src/fuse_opendir.hpp @@ -16,7 +16,8 @@ #pragma once -#include +#include "fuse.h" + namespace FUSE { diff --git a/src/fuse_prepare_hide.cpp b/src/fuse_prepare_hide.cpp index 73c8e74b..fbd741ea 100644 --- a/src/fuse_prepare_hide.cpp +++ b/src/fuse_prepare_hide.cpp @@ -18,10 +18,11 @@ #include "fuse_open.hpp" -#include +#include #include + namespace FUSE { int diff --git a/src/fuse_prepare_hide.hpp b/src/fuse_prepare_hide.hpp index 696f5819..9e38760b 100644 --- a/src/fuse_prepare_hide.hpp +++ b/src/fuse_prepare_hide.hpp @@ -18,7 +18,8 @@ #pragma once -#include +#include + namespace FUSE { diff --git a/src/fuse_read.cpp b/src/fuse_read.cpp index 34a4b2e5..cc177de4 100644 --- a/src/fuse_read.cpp +++ b/src/fuse_read.cpp @@ -18,7 +18,8 @@ #include "fileinfo.hpp" #include "fs_read.hpp" -#include +#include "fuse.h" + namespace l { diff --git a/src/fuse_read.hpp b/src/fuse_read.hpp index 21110ee2..b15c8d27 100644 --- a/src/fuse_read.hpp +++ b/src/fuse_read.hpp @@ -16,7 +16,8 @@ #pragma once -#include +#include "fuse.h" + namespace FUSE { diff --git a/src/fuse_read_buf.cpp b/src/fuse_read_buf.cpp index d43355a9..733940f1 100644 --- a/src/fuse_read_buf.cpp +++ b/src/fuse_read_buf.cpp @@ -17,13 +17,14 @@ #include "errno.hpp" #include "fileinfo.hpp" -#include +#include "fuse.h" #include #include typedef struct fuse_bufvec fuse_bufvec; + namespace l { static diff --git a/src/fuse_read_buf.hpp b/src/fuse_read_buf.hpp index 34ecc46f..f614e916 100644 --- a/src/fuse_read_buf.hpp +++ b/src/fuse_read_buf.hpp @@ -16,10 +16,11 @@ #pragma once -#include +#include "fuse.h" #include + namespace FUSE { int diff --git a/src/fuse_readdir.cpp b/src/fuse_readdir.cpp index e9607442..2ef0b3e4 100644 --- a/src/fuse_readdir.cpp +++ b/src/fuse_readdir.cpp @@ -24,7 +24,8 @@ #include "rwlock.hpp" #include "ugid.hpp" -#include +#include "fuse.h" + namespace FUSE { @@ -32,18 +33,18 @@ namespace FUSE readdir(const fuse_file_info_t *ffi_, fuse_dirents_t *buf_) { - DirInfo *di = reinterpret_cast(ffi_->fh); - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + DirInfo *di = reinterpret_cast(ffi_->fh); + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - switch(config.readdir) + switch(cfg->readdir) { case ReadDir::ENUM::LINUX: - return FUSE::readdir_linux(config.branches,di->fusepath.c_str(),buf_); + return FUSE::readdir_linux(cfg->branches,di->fusepath.c_str(),buf_); default: case ReadDir::ENUM::POSIX: - return FUSE::readdir_posix(config.branches,di->fusepath.c_str(),buf_); + return FUSE::readdir_posix(cfg->branches,di->fusepath.c_str(),buf_); } } } diff --git a/src/fuse_readdir.hpp b/src/fuse_readdir.hpp index 92741edd..c82937c3 100644 --- a/src/fuse_readdir.hpp +++ b/src/fuse_readdir.hpp @@ -16,7 +16,8 @@ #pragma once -#include +#include "fuse.h" + namespace FUSE { diff --git a/src/fuse_readdir_linux.cpp b/src/fuse_readdir_linux.cpp index 4d0cf062..7bbf2ece 100644 --- a/src/fuse_readdir_linux.cpp +++ b/src/fuse_readdir_linux.cpp @@ -14,7 +14,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "branch.hpp" +#include "branches.hpp" #include "errno.hpp" #include "fs_close.hpp" #include "fs_devid.hpp" @@ -26,10 +26,9 @@ #include "hashset.hpp" #include "linux_dirent64.h" #include "mempools.hpp" -#include "rwlock.hpp" -#include -#include +#include "fuse.h" +#include "fuse_dirents.h" #include #include @@ -53,9 +52,9 @@ namespace l static int - readdir(const BranchVec &branches_, - const char *dirname_, - fuse_dirents_t *buf_) + readdir(const Branches::CPtr &branches_, + const char *dirname_, + fuse_dirents_t *buf_) { int rv; dev_t dev; @@ -70,20 +69,18 @@ namespace l if(buf == NULL) return -ENOMEM; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(const auto &branch : *branches_) { int dirfd; int64_t nread; - basepath = fs::path::make(branches_[i].path,dirname_); + basepath = fs::path::make(branch.path,dirname_); dirfd = fs::open_dir_ro(basepath); if(dirfd == -1) continue; dev = fs::devid(dirfd); - if(dev == (dev_t)-1) - dev = i; for(;;) { @@ -122,25 +119,14 @@ namespace l return 0; } - - static - int - readdir(const Branches &branches_, - const char *dirname_, - fuse_dirents_t *buf_) - { - rwlock::ReadGuard guard(branches_.lock); - - return l::readdir(branches_.vec,dirname_,buf_); - } } namespace FUSE { int - readdir_linux(const Branches &branches_, - const char *dirname_, - fuse_dirents_t *buf_) + readdir_linux(const Branches::CPtr &branches_, + const char *dirname_, + fuse_dirents_t *buf_) { return l::readdir(branches_,dirname_,buf_); } diff --git a/src/fuse_readdir_linux.hpp b/src/fuse_readdir_linux.hpp index d6b9b09d..26cfff6a 100644 --- a/src/fuse_readdir_linux.hpp +++ b/src/fuse_readdir_linux.hpp @@ -18,16 +18,17 @@ #pragma once -#include "branch.hpp" +#include "branches.hpp" -#include +#include "fuse.h" + +#include -#include namespace FUSE { int - readdir_linux(const Branches &branches, - const char *dirname, - fuse_dirents_t *buf); + readdir_linux(const Branches::CPtr &branches, + const char *dirname, + fuse_dirents_t *buf); } diff --git a/src/fuse_readdir_plus.cpp b/src/fuse_readdir_plus.cpp index 6ee1f52a..e9870fa2 100644 --- a/src/fuse_readdir_plus.cpp +++ b/src/fuse_readdir_plus.cpp @@ -24,7 +24,8 @@ #include "rwlock.hpp" #include "ugid.hpp" -#include +#include "fuse.h" + namespace FUSE { @@ -32,25 +33,25 @@ namespace FUSE readdir_plus(const fuse_file_info_t *ffi_, fuse_dirents_t *buf_) { - DirInfo *di = reinterpret_cast(ffi_->fh); - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + DirInfo *di = reinterpret_cast(ffi_->fh); + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - switch(config.readdir) + switch(cfg->readdir) { case ReadDir::ENUM::LINUX: - return FUSE::readdir_plus_linux(config.branches, + return FUSE::readdir_plus_linux(cfg->branches, di->fusepath.c_str(), - config.cache_entry, - config.cache_attr, + cfg->cache_entry, + cfg->cache_attr, buf_); default: case ReadDir::ENUM::POSIX: - return FUSE::readdir_plus_posix(config.branches, + return FUSE::readdir_plus_posix(cfg->branches, di->fusepath.c_str(), - config.cache_entry, - config.cache_attr, + cfg->cache_entry, + cfg->cache_attr, buf_); } } diff --git a/src/fuse_readdir_plus.hpp b/src/fuse_readdir_plus.hpp index 20278f0c..8e298e61 100644 --- a/src/fuse_readdir_plus.hpp +++ b/src/fuse_readdir_plus.hpp @@ -16,7 +16,8 @@ #pragma once -#include +#include "fuse.h" + namespace FUSE { diff --git a/src/fuse_readdir_plus_linux.cpp b/src/fuse_readdir_plus_linux.cpp index ad643a5f..9e87568b 100644 --- a/src/fuse_readdir_plus_linux.cpp +++ b/src/fuse_readdir_plus_linux.cpp @@ -14,7 +14,7 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "branch.hpp" +#include "branches.hpp" #include "errno.hpp" #include "fs_close.hpp" #include "fs_devid.hpp" @@ -28,8 +28,8 @@ #include "linux_dirent64.h" #include "mempools.hpp" -#include -#include +#include "fuse.h" +#include "fuse_dirents.h" #include #include @@ -53,11 +53,11 @@ namespace l static int - readdir_plus(const BranchVec &branches_, - const char *dirname_, - const uint64_t entry_timeout_, - const uint64_t attr_timeout_, - fuse_dirents_t *buf_) + readdir_plus(const Branches::CPtr &branches_, + const char *dirname_, + const uint64_t entry_timeout_, + const uint64_t attr_timeout_, + fuse_dirents_t *buf_) { int rv; dev_t dev; @@ -78,20 +78,17 @@ namespace l entry.attr_valid = attr_timeout_; entry.entry_valid_nsec = 0; entry.attr_valid_nsec = 0; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { int dirfd; int64_t nread; - basepath = fs::path::make(branches_[i].path,dirname_); + basepath = fs::path::make(branch.path,dirname_); dirfd = fs::open_dir_ro(basepath); if(dirfd == -1) continue; - dev = fs::devid(dirfd); - if(dev == (dev_t)-1) - dev = i; for(;;) { @@ -136,29 +133,16 @@ namespace l return 0; } - - static - int - readdir_plus(const Branches &branches_, - const char *dirname_, - const uint64_t entry_timeout_, - const uint64_t attr_timeout_, - fuse_dirents_t *buf_) - { - rwlock::ReadGuard guard(branches_.lock); - - return l::readdir_plus(branches_.vec,dirname_,entry_timeout_,attr_timeout_,buf_); - } } namespace FUSE { int - readdir_plus_linux(const Branches &branches_, - const char *dirname_, - const uint64_t entry_timeout_, - const uint64_t attr_timeout_, - fuse_dirents_t *buf_) + readdir_plus_linux(const Branches::CPtr &branches_, + const char *dirname_, + const uint64_t entry_timeout_, + const uint64_t attr_timeout_, + fuse_dirents_t *buf_) { return l::readdir_plus(branches_,dirname_,entry_timeout_,attr_timeout_,buf_); } diff --git a/src/fuse_readdir_plus_linux.hpp b/src/fuse_readdir_plus_linux.hpp index 68020b7f..a0bca539 100644 --- a/src/fuse_readdir_plus_linux.hpp +++ b/src/fuse_readdir_plus_linux.hpp @@ -18,18 +18,19 @@ #pragma once -#include "branch.hpp" +#include "branches.hpp" -#include +#include "fuse.h" + +#include -#include namespace FUSE { int - readdir_plus_linux(const Branches &branches, - const char *dirname, - const uint64_t entry_timeout, - const uint64_t attr_timeout, - fuse_dirents_t *buf); + readdir_plus_linux(const Branches::CPtr &branches, + const char *dirname, + const uint64_t entry_timeout, + const uint64_t attr_timeout, + fuse_dirents_t *buf); } diff --git a/src/fuse_readdir_plus_posix.cpp b/src/fuse_readdir_plus_posix.cpp index 6f809684..b78f9516 100644 --- a/src/fuse_readdir_plus_posix.cpp +++ b/src/fuse_readdir_plus_posix.cpp @@ -16,7 +16,7 @@ #define _DEFAULT_SOURCE -#include "branch.hpp" +#include "branches.hpp" #include "errno.hpp" #include "fs_closedir.hpp" #include "fs_devid.hpp" @@ -28,10 +28,9 @@ #include "fs_readdir.hpp" #include "fs_stat.hpp" #include "hashset.hpp" -#include "rwlock.hpp" -#include -#include +#include "fuse.h" +#include "fuse_dirents.h" #include #include @@ -58,11 +57,11 @@ namespace l static int - readdir_plus(const BranchVec &branches_, - const char *dirname_, - const uint64_t entry_timeout_, - const uint64_t attr_timeout_, - fuse_dirents_t *buf_) + readdir_plus(const Branches::CPtr &branches_, + const char *dirname_, + const uint64_t entry_timeout_, + const uint64_t attr_timeout_, + fuse_dirents_t *buf_) { dev_t dev; HashSet names; @@ -78,13 +77,13 @@ namespace l entry.attr_valid = attr_timeout_; entry.entry_valid_nsec = 0; entry.attr_valid_nsec = 0; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { int rv; int dirfd; DIR *dh; - basepath = fs::path::make(branches_[i].path,dirname_); + basepath = fs::path::make(branch.path,dirname_); dh = fs::opendir(basepath); if(!dh) @@ -92,8 +91,6 @@ namespace l dirfd = fs::dirfd(dh); dev = fs::devid(dirfd); - if(dev == (dev_t)-1) - dev = i; rv = 0; for(struct dirent *de = fs::readdir(dh); de && !rv; de = fs::readdir(dh)) @@ -127,33 +124,16 @@ namespace l return 0; } - - static - int - readdir_plus(const Branches &branches_, - const char *dirname_, - const uint64_t entry_timeout_, - const uint64_t attr_timeout_, - fuse_dirents_t *buf_) - { - rwlock::ReadGuard guard(branches_.lock); - - return l::readdir_plus(branches_.vec, - dirname_, - entry_timeout_, - attr_timeout_, - buf_); - } } namespace FUSE { int - readdir_plus_posix(const Branches &branches_, - const char *dirname_, - const uint64_t entry_timeout_, - const uint64_t attr_timeout_, - fuse_dirents_t *buf_) + readdir_plus_posix(const Branches::CPtr &branches_, + const char *dirname_, + const uint64_t entry_timeout_, + const uint64_t attr_timeout_, + fuse_dirents_t *buf_) { return l::readdir_plus(branches_,dirname_,entry_timeout_,attr_timeout_,buf_); } diff --git a/src/fuse_readdir_plus_posix.hpp b/src/fuse_readdir_plus_posix.hpp index ac040673..910cab5f 100644 --- a/src/fuse_readdir_plus_posix.hpp +++ b/src/fuse_readdir_plus_posix.hpp @@ -18,18 +18,19 @@ #pragma once -#include "branch.hpp" +#include "branches.hpp" -#include +#include "fuse.h" + +#include -#include namespace FUSE { int - readdir_plus_posix(const Branches &branches, - const char *dirname, - const uint64_t entry_timeout, - const uint64_t attr_timeout, - fuse_dirents_t *buf); + readdir_plus_posix(const Branches::CPtr &branches, + const char *dirname, + const uint64_t entry_timeout, + const uint64_t attr_timeout, + fuse_dirents_t *buf); } diff --git a/src/fuse_readdir_posix.cpp b/src/fuse_readdir_posix.cpp index ba944a83..5d3bf961 100644 --- a/src/fuse_readdir_posix.cpp +++ b/src/fuse_readdir_posix.cpp @@ -16,7 +16,7 @@ #define _DEFAULT_SOURCE -#include "branch.hpp" +#include "branches.hpp" #include "errno.hpp" #include "fs_closedir.hpp" #include "fs_devid.hpp" @@ -27,10 +27,9 @@ #include "fs_readdir.hpp" #include "fs_stat.hpp" #include "hashset.hpp" -#include "rwlock.hpp" -#include -#include +#include "fuse.h" +#include "fuse_dirents.h" #include #include @@ -40,6 +39,7 @@ using std::string; using std::vector; + namespace l { static @@ -57,9 +57,9 @@ namespace l static int - readdir(const BranchVec &branches_, - const char *dirname_, - fuse_dirents_t *buf_) + readdir(const Branches::CPtr &branches_, + const char *dirname_, + fuse_dirents_t *buf_) { dev_t dev; HashSet names; @@ -67,13 +67,13 @@ namespace l string fullpath; uint64_t namelen; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(const auto &branch : *branches_) { int rv; int dirfd; DIR *dh; - basepath = fs::path::make(branches_[i].path,dirname_); + basepath = fs::path::make(branch.path,dirname_); dh = fs::opendir(basepath); if(!dh) @@ -81,8 +81,6 @@ namespace l dirfd = fs::dirfd(dh); dev = fs::devid(dirfd); - if(dev == (dev_t)-1) - dev = i; rv = 0; for(struct dirent *de = fs::readdir(dh); de && !rv; de = fs::readdir(dh)) @@ -110,25 +108,14 @@ namespace l return 0; } - - static - int - readdir(const Branches &branches_, - const char *dirname_, - fuse_dirents_t *buf_) - { - rwlock::ReadGuard guard(branches_.lock); - - return l::readdir(branches_.vec,dirname_,buf_); - } } namespace FUSE { int - readdir_posix(const Branches &branches_, - const char *dirname_, - fuse_dirents_t *buf_) + readdir_posix(const Branches::CPtr &branches_, + const char *dirname_, + fuse_dirents_t *buf_) { return l::readdir(branches_,dirname_,buf_); } diff --git a/src/fuse_readdir_posix.hpp b/src/fuse_readdir_posix.hpp index 04eea9d3..36d08dbb 100644 --- a/src/fuse_readdir_posix.hpp +++ b/src/fuse_readdir_posix.hpp @@ -18,16 +18,17 @@ #pragma once -#include "branch.hpp" +#include "branches.hpp" -#include +#include "fuse.h" + +#include -#include namespace FUSE { int - readdir_posix(const Branches &branches, - const char *dirname, - fuse_dirents_t *buf); + readdir_posix(const Branches::CPtr &branches, + const char *dirname, + fuse_dirents_t *buf); } diff --git a/src/fuse_readlink.cpp b/src/fuse_readlink.cpp index 8cebea19..e24354f4 100644 --- a/src/fuse_readlink.cpp +++ b/src/fuse_readlink.cpp @@ -22,12 +22,12 @@ #include "symlinkify.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include using std::string; -using std::vector; + namespace l { @@ -92,7 +92,7 @@ namespace l static int - readlink(Policy::Func::Search searchFunc_, + readlink(const Policy::Search &searchFunc_, const Branches &branches_, const char *fusepath_, char *buf_, @@ -101,7 +101,7 @@ namespace l const time_t symlinkify_timeout_) { int rv; - vector basepaths; + StrVec basepaths; rv = searchFunc_(branches_,fusepath_,&basepaths); if(rv == -1) @@ -119,16 +119,16 @@ namespace FUSE char *buf_, size_t size_) { - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::readlink(config.func.readlink.policy, - config.branches, + return l::readlink(cfg->func.readlink.policy, + cfg->branches, fusepath_, buf_, size_, - config.symlinkify, - config.symlinkify_timeout); + cfg->symlinkify, + cfg->symlinkify_timeout); } } diff --git a/src/fuse_readlink.hpp b/src/fuse_readlink.hpp index e9f37a15..b7e5e6f2 100644 --- a/src/fuse_readlink.hpp +++ b/src/fuse_readlink.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { int diff --git a/src/fuse_release.cpp b/src/fuse_release.cpp index 88c1357e..03b6dcdb 100644 --- a/src/fuse_release.cpp +++ b/src/fuse_release.cpp @@ -20,10 +20,11 @@ #include "fs_close.hpp" #include "fs_fadvise.hpp" -#include +#include "fuse.h" #include + namespace l { static @@ -52,12 +53,9 @@ namespace FUSE int release(const fuse_file_info_t *ffi_) { - const Config &config = Config::ro(); + Config::Read cfg; FileInfo *fi = reinterpret_cast(ffi_->fh); - if(config.open_cache.timeout) - config.open_cache.cleanup(10); - - return l::release(fi,config.dropcacheonclose); + return l::release(fi,cfg->dropcacheonclose); } } diff --git a/src/fuse_release.hpp b/src/fuse_release.hpp index 547490fa..94858839 100644 --- a/src/fuse_release.hpp +++ b/src/fuse_release.hpp @@ -16,7 +16,8 @@ #pragma once -#include +#include "fuse.h" + namespace FUSE { diff --git a/src/fuse_releasedir.cpp b/src/fuse_releasedir.cpp index b4a096ac..8a7c15c5 100644 --- a/src/fuse_releasedir.cpp +++ b/src/fuse_releasedir.cpp @@ -17,7 +17,8 @@ #include "config.hpp" #include "dirinfo.hpp" -#include +#include "fuse.h" + namespace l { diff --git a/src/fuse_releasedir.hpp b/src/fuse_releasedir.hpp index caf7acce..28d278e0 100644 --- a/src/fuse_releasedir.hpp +++ b/src/fuse_releasedir.hpp @@ -16,7 +16,8 @@ #pragma once -#include +#include "fuse.h" + namespace FUSE { diff --git a/src/fuse_removexattr.cpp b/src/fuse_removexattr.cpp index 9f0ba7ef..d22367ac 100644 --- a/src/fuse_removexattr.cpp +++ b/src/fuse_removexattr.cpp @@ -21,7 +21,7 @@ #include "policy_rv.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include #include @@ -84,8 +84,8 @@ namespace l static int - removexattr(Policy::Func::Action actionFunc_, - Policy::Func::Search searchFunc_, + removexattr(const Policy::Action &actionFunc_, + const Policy::Search &searchFunc_, const Branches &branches_, const char *fusepath_, const char *attrname_) @@ -119,19 +119,20 @@ namespace FUSE removexattr(const char *fusepath_, const char *attrname_) { - const Config &config = Config::ro(); + Config::Read cfg; - if(fusepath_ == config.controlfile) + if(fusepath_ == CONTROLFILE) return -ENOATTR; - if(config.xattr.to_int()) - return -config.xattr.to_int(); + + if(cfg->xattr.to_int()) + return -cfg->xattr.to_int(); const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::removexattr(config.func.removexattr.policy, - config.func.getxattr.policy, - config.branches, + return l::removexattr(cfg->func.removexattr.policy, + cfg->func.getxattr.policy, + cfg->branches, fusepath_, attrname_); } diff --git a/src/fuse_removexattr.hpp b/src/fuse_removexattr.hpp index 7dbef5de..4c7357f9 100644 --- a/src/fuse_removexattr.hpp +++ b/src/fuse_removexattr.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { int diff --git a/src/fuse_rename.cpp b/src/fuse_rename.cpp index e9fdf0cf..541bce8e 100644 --- a/src/fuse_rename.cpp +++ b/src/fuse_rename.cpp @@ -24,10 +24,8 @@ #include #include -#include using std::string; -using std::vector; namespace error @@ -52,8 +50,8 @@ namespace error static bool -member(const vector &haystack, - const string &needle) +member(const StrVec &haystack, + const string &needle) { for(size_t i = 0, ei = haystack.size(); i != ei; i++) { @@ -66,7 +64,7 @@ member(const vector &haystack, static void -_remove(const vector &toremove) +_remove(const StrVec &toremove) { for(size_t i = 0, ei = toremove.size(); i != ei; i++) fs::remove(toremove[i]); @@ -74,14 +72,14 @@ _remove(const vector &toremove) static void -_rename_create_path_core(const vector &oldbasepaths, - const string &oldbasepath, - const string &newbasepath, - const char *oldfusepath, - const char *newfusepath, - const string &newfusedirpath, - int &error, - vector &tounlink) +_rename_create_path_core(const StrVec &oldbasepaths, + const string &oldbasepath, + const string &newbasepath, + const char *oldfusepath, + const char *newfusepath, + const string &newfusedirpath, + int &error, + StrVec &tounlink) { int rv; bool ismember; @@ -114,19 +112,19 @@ _rename_create_path_core(const vector &oldbasepaths, static int -_rename_create_path(Policy::Func::Search searchFunc, - Policy::Func::Action actionFunc, - const Branches &branches_, +_rename_create_path(const Policy::Search &searchFunc, + const Policy::Action &actionFunc, + const Branches::CPtr &branches_, const char *oldfusepath, const char *newfusepath) { int rv; int error; string newfusedirpath; - vector toremove; - vector newbasepath; - vector oldbasepaths; - vector branches; + StrVec toremove; + StrVec newbasepath; + StrVec oldbasepaths; + StrVec branches; rv = actionFunc(branches_,oldfusepath,&oldbasepaths); if(rv == -1) @@ -134,11 +132,11 @@ _rename_create_path(Policy::Func::Search searchFunc, newfusedirpath = fs::path::dirname(newfusepath); - rv = searchFunc(branches_,newfusedirpath,&newbasepath); + rv = searchFunc(branches_,newfusedirpath.c_str(),&newbasepath); if(rv == -1) return -errno; - branches_.to_paths(branches); + branches_->to_paths(branches); error = -1; for(size_t i = 0, ei = branches.size(); i != ei; i++) @@ -161,15 +159,15 @@ _rename_create_path(Policy::Func::Search searchFunc, static int -_clonepath(Policy::Func::Search searchFunc, - const Branches &branches_, +_clonepath(const Policy::Search &searchFunc, + const Branches::CPtr &branches_, const string &dstbasepath, const string &fusedirpath) { int rv; - vector srcbasepath; + StrVec srcbasepath; - rv = searchFunc(branches_,fusedirpath,&srcbasepath); + rv = searchFunc(branches_,fusedirpath.c_str(),&srcbasepath); if(rv == -1) return -errno; @@ -180,20 +178,20 @@ _clonepath(Policy::Func::Search searchFunc, static int -_clonepath_if_would_create(Policy::Func::Search searchFunc, - Policy::Func::Create createFunc, - const Branches &branches_, +_clonepath_if_would_create(const Policy::Search &searchFunc, + const Policy::Create &createFunc, + const Branches::CPtr &branches_, const string &oldbasepath, const char *oldfusepath, const char *newfusepath) { int rv; string newfusedirpath; - vector newbasepath; + StrVec newbasepath; newfusedirpath = fs::path::dirname(newfusepath); - rv = createFunc(branches_,newfusedirpath,&newbasepath); + rv = createFunc(branches_,newfusedirpath.c_str(),&newbasepath); if(rv == -1) return rv; @@ -205,15 +203,15 @@ _clonepath_if_would_create(Policy::Func::Search searchFunc, static void -_rename_preserve_path_core(Policy::Func::Search searchFunc, - Policy::Func::Create createFunc, - const Branches &branches_, - const vector &oldbasepaths, +_rename_preserve_path_core(const Policy::Search &searchFunc, + const Policy::Create &createFunc, + const Branches::CPtr &branches_, + const StrVec &oldbasepaths, const string &oldbasepath, const char *oldfusepath, const char *newfusepath, int &error, - vector &toremove) + StrVec &toremove) { int rv; bool ismember; @@ -250,24 +248,24 @@ _rename_preserve_path_core(Policy::Func::Search searchFunc, static int -_rename_preserve_path(Policy::Func::Search searchFunc, - Policy::Func::Action actionFunc, - Policy::Func::Create createFunc, - const Branches &branches_, +_rename_preserve_path(const Policy::Search &searchFunc, + const Policy::Action &actionFunc, + const Policy::Create &createFunc, + const Branches::CPtr &branches_, const char *oldfusepath, const char *newfusepath) { int rv; int error; - vector toremove; - vector oldbasepaths; - vector branches; + StrVec toremove; + StrVec oldbasepaths; + StrVec branches; rv = actionFunc(branches_,oldfusepath,&oldbasepaths); if(rv == -1) return -errno; - branches_.to_paths(branches); + branches_->to_paths(branches); error = -1; for(size_t i = 0, ei = branches.size(); i != ei; i++) @@ -293,23 +291,21 @@ namespace FUSE rename(const char *oldpath, const char *newpath) { - const fuse_context *fc = fuse_get_context(); - Config &config = Config::rw(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - config.open_cache.erase(oldpath); - - if(config.func.create.policy->path_preserving() && !config.ignorepponrename) - return _rename_preserve_path(config.func.getattr.policy, - config.func.rename.policy, - config.func.create.policy, - config.branches, + if(cfg->func.create.policy.path_preserving() && !cfg->ignorepponrename) + return _rename_preserve_path(cfg->func.getattr.policy, + cfg->func.rename.policy, + cfg->func.create.policy, + cfg->branches, oldpath, newpath); - return _rename_create_path(config.func.getattr.policy, - config.func.rename.policy, - config.branches, + return _rename_create_path(cfg->func.getattr.policy, + cfg->func.rename.policy, + cfg->branches, oldpath, newpath); } diff --git a/src/fuse_rename.hpp b/src/fuse_rename.hpp index affa01d2..abbcf515 100644 --- a/src/fuse_rename.hpp +++ b/src/fuse_rename.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { int diff --git a/src/fuse_rmdir.cpp b/src/fuse_rmdir.cpp index 9c650caf..c7c6e107 100644 --- a/src/fuse_rmdir.cpp +++ b/src/fuse_rmdir.cpp @@ -20,7 +20,7 @@ #include "fs_path.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include @@ -66,8 +66,8 @@ namespace l static int - rmdir_loop(const vector &basepaths_, - const char *fusepath_) + rmdir_loop(const StrVec &basepaths_, + const char *fusepath_) { int error; @@ -82,7 +82,7 @@ namespace l static int - rmdir(Policy::Func::Action actionFunc_, + rmdir(const Policy::Action &actionFunc_, const Branches &branches_, const char *fusepath_) { @@ -102,12 +102,12 @@ namespace FUSE int rmdir(const char *fusepath_) { - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::rmdir(config.func.rmdir.policy, - config.branches, + return l::rmdir(cfg->func.rmdir.policy, + cfg->branches, fusepath_); } } diff --git a/src/fuse_rmdir.hpp b/src/fuse_rmdir.hpp index 0c59659c..d2782468 100644 --- a/src/fuse_rmdir.hpp +++ b/src/fuse_rmdir.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { int diff --git a/src/fuse_setxattr.cpp b/src/fuse_setxattr.cpp index 6bb9d041..c46bc7c1 100644 --- a/src/fuse_setxattr.cpp +++ b/src/fuse_setxattr.cpp @@ -25,7 +25,7 @@ #include "str.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include #include @@ -69,31 +69,30 @@ namespace l static int - setxattr_controlfile(Config &config_, - const string &attrname_, + setxattr_controlfile(const string &attrname_, const string &attrval_, const int flags_) { int rv; string key; + Config::Write cfg; if(!str::startswith(attrname_,"user.mergerfs.")) return -ENOATTR; key = &attrname_[14]; - if(config_.has_key(key) == false) + if(cfg->has_key(key) == false) return -ENOATTR; if((flags_ & XATTR_CREATE) == XATTR_CREATE) return -EEXIST; - rv = config_.set(key,attrval_); + rv = cfg->set(key,attrval_); if(rv < 0) return rv; - config_.open_cache.clear(); - fs::statvfs_cache_timeout(config_.cache_statfs); + fs::statvfs_cache_timeout(cfg->cache_statfs); return rv; } @@ -120,13 +119,13 @@ namespace l static void - setxattr_loop(const vector &basepaths_, - const char *fusepath_, - const char *attrname_, - const char *attrval_, - const size_t attrvalsize_, - const int flags_, - PolicyRV *prv_) + setxattr_loop(const StrVec &basepaths_, + const char *fusepath_, + const char *attrname_, + const char *attrval_, + const size_t attrvalsize_, + const int flags_, + PolicyRV *prv_) { for(size_t i = 0, ei = basepaths_.size(); i != ei; i++) { @@ -138,8 +137,8 @@ namespace l static int - setxattr(Policy::Func::Action actionFunc_, - Policy::Func::Search searchFunc_, + setxattr(const Policy::Action &setxattrPolicy_, + const Policy::Search &getxattrPolicy_, const Branches &branches_, const char *fusepath_, const char *attrname_, @@ -149,9 +148,9 @@ namespace l { int rv; PolicyRV prv; - vector basepaths; + StrVec basepaths; - rv = actionFunc_(branches_,fusepath_,&basepaths); + rv = setxattrPolicy_(branches_,fusepath_,&basepaths); if(rv == -1) return -errno; @@ -162,16 +161,13 @@ namespace l return prv.error[0].rv; basepaths.clear(); - rv = searchFunc_(branches_,fusepath_,&basepaths); + rv = getxattrPolicy_(branches_,fusepath_,&basepaths); if(rv == -1) return -errno; return l::get_error(prv,basepaths[0]); } -} -namespace FUSE -{ int setxattr(const char *fusepath_, const char *attrname_, @@ -179,27 +175,21 @@ namespace FUSE size_t attrvalsize_, int flags_) { - Config &config = Config::rw(); - - if(fusepath_ == config.controlfile) - return l::setxattr_controlfile(config, - attrname_, - string(attrval_,attrvalsize_), - flags_); + Config::Read cfg; - if((config.security_capability == false) && + if((cfg->security_capability == false) && l::is_attrname_security_capability(attrname_)) return -ENOATTR; - if(config.xattr.to_int()) - return -config.xattr.to_int(); + if(cfg->xattr.to_int()) + return -cfg->xattr.to_int(); const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::setxattr(config.func.setxattr.policy, - config.func.getxattr.policy, - config.branches, + return l::setxattr(cfg->func.setxattr.policy, + cfg->func.getxattr.policy, + cfg->branches, fusepath_, attrname_, attrval_, @@ -207,3 +197,21 @@ namespace FUSE flags_); } } + +namespace FUSE +{ + int + setxattr(const char *fusepath_, + const char *attrname_, + const char *attrval_, + size_t attrvalsize_, + int flags_) + { + if(fusepath_ == CONTROLFILE) + return l::setxattr_controlfile(attrname_, + string(attrval_,attrvalsize_), + flags_); + + return l::setxattr(fusepath_,attrname_,attrval_,attrvalsize_,flags_); + } +} diff --git a/src/fuse_setxattr.hpp b/src/fuse_setxattr.hpp index 2b882b66..6ae1f52e 100644 --- a/src/fuse_setxattr.hpp +++ b/src/fuse_setxattr.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { int diff --git a/src/fuse_statfs.cpp b/src/fuse_statfs.cpp index 0c15f7bf..68ffb2cf 100644 --- a/src/fuse_statfs.cpp +++ b/src/fuse_statfs.cpp @@ -19,11 +19,10 @@ #include "fs_lstat.hpp" #include "fs_path.hpp" #include "fs_statvfs.hpp" -#include "rwlock.hpp" #include "statvfs_util.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include #include @@ -35,6 +34,7 @@ using std::string; using std::map; using std::vector; + namespace l { static @@ -69,24 +69,22 @@ namespace l static bool should_ignore(const StatFSIgnore ignore_, - const Branch *branch_, + const Branch &branch_, const bool readonly_) { return ((((ignore_ == StatFSIgnore::ENUM::RO) || readonly_) && - (branch_->ro_or_nc())) || - ((ignore_ == StatFSIgnore::ENUM::NC) && (branch_->nc()))); + (branch_.ro_or_nc())) || + ((ignore_ == StatFSIgnore::ENUM::NC) && (branch_.nc()))); } static int - statfs(const Branches &branches_, - const char *fusepath_, - const StatFS mode_, - const StatFSIgnore ignore_, - struct statvfs *fsstat_) + statfs(const Branches::CPtr &branches_, + const char *fusepath_, + const StatFS mode_, + const StatFSIgnore ignore_, + struct statvfs *fsstat_) { - rwlock::ReadGuard guard(branches_.lock); - int rv; string fullpath; struct stat st; @@ -99,11 +97,11 @@ namespace l min_bsize = std::numeric_limits::max(); min_frsize = std::numeric_limits::max(); min_namemax = std::numeric_limits::max(); - for(size_t i = 0, ei = branches_.vec.size(); i < ei; i++) + for(const auto &branch : *branches_) { fullpath = ((mode_ == StatFS::ENUM::FULL) ? - fs::path::make(branches_.vec[i].path,fusepath_) : - branches_.vec[i].path); + fs::path::make(branch.path,fusepath_) : + branch.path); rv = fs::lstat(fullpath,&st); if(rv == -1) @@ -120,7 +118,7 @@ namespace l if(stvfs.f_namemax && (min_namemax > stvfs.f_namemax)) min_namemax = stvfs.f_namemax; - if(l::should_ignore(ignore_,&branches_.vec[i],StatVFS::readonly(stvfs))) + if(l::should_ignore(ignore_,branch,StatVFS::readonly(stvfs))) { stvfs.f_bavail = 0; stvfs.f_favail = 0; @@ -153,14 +151,14 @@ namespace FUSE statfs(const char *fusepath_, struct statvfs *st_) { - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::statfs(config.branches, + return l::statfs(cfg->branches, fusepath_, - config.statfs, - config.statfs_ignore, + cfg->statfs, + cfg->statfs_ignore, st_); } } diff --git a/src/fuse_statfs.hpp b/src/fuse_statfs.hpp index 8d0933bb..c34ac43a 100644 --- a/src/fuse_statfs.hpp +++ b/src/fuse_statfs.hpp @@ -18,6 +18,7 @@ #include + namespace FUSE { int diff --git a/src/fuse_symlink.cpp b/src/fuse_symlink.cpp index c332d6f4..cdfb407c 100644 --- a/src/fuse_symlink.cpp +++ b/src/fuse_symlink.cpp @@ -21,7 +21,7 @@ #include "fs_path.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include @@ -29,7 +29,6 @@ #include using std::string; -using std::vector; namespace error @@ -73,11 +72,11 @@ namespace l static int - symlink_loop(const string &existingpath_, - const vector &newbasepaths_, - const char *oldpath_, - const char *newpath_, - const string &newdirpath_) + symlink_loop(const string &existingpath_, + const StrVec &newbasepaths_, + const char *oldpath_, + const char *newpath_, + const string &newdirpath_) { int rv; int error; @@ -100,16 +99,16 @@ namespace l static int - symlink(Policy::Func::Search searchFunc_, - Policy::Func::Create createFunc_, + symlink(const Policy::Search &searchFunc_, + const Policy::Create &createFunc_, const Branches &branches_, const char *oldpath_, const char *newpath_) { int rv; string newdirpath; - vector newbasepaths; - vector existingpaths; + StrVec newbasepaths; + StrVec existingpaths; newdirpath = fs::path::dirname(newpath_); @@ -132,13 +131,13 @@ namespace FUSE symlink(const char *oldpath_, const char *newpath_) { - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::symlink(config.func.getattr.policy, - config.func.symlink.policy, - config.branches, + return l::symlink(cfg->func.getattr.policy, + cfg->func.symlink.policy, + cfg->branches, oldpath_, newpath_); } diff --git a/src/fuse_symlink.hpp b/src/fuse_symlink.hpp index 561a8300..0bbced2e 100644 --- a/src/fuse_symlink.hpp +++ b/src/fuse_symlink.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { int diff --git a/src/fuse_truncate.cpp b/src/fuse_truncate.cpp index 331f0c4d..669715a8 100644 --- a/src/fuse_truncate.cpp +++ b/src/fuse_truncate.cpp @@ -21,16 +21,14 @@ #include "policy_rv.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include -#include #include #include using std::string; -using std::vector; namespace l @@ -74,10 +72,10 @@ namespace l static void - truncate_loop(const vector &basepaths_, - const char *fusepath_, - const off_t size_, - PolicyRV *prv_) + truncate_loop(const StrVec &basepaths_, + const char *fusepath_, + const off_t size_, + PolicyRV *prv_) { for(size_t i = 0, ei = basepaths_.size(); i != ei; i++) { @@ -87,15 +85,15 @@ namespace l static int - truncate(Policy::Func::Action actionFunc_, - Policy::Func::Search searchFunc_, + truncate(const Policy::Action &actionFunc_, + const Policy::Search &searchFunc_, const Branches &branches_, const char *fusepath_, const off_t size_) { int rv; PolicyRV prv; - vector basepaths; + StrVec basepaths; rv = actionFunc_(branches_,fusepath_,&basepaths); if(rv == -1) @@ -122,13 +120,13 @@ namespace FUSE truncate(const char *fusepath_, off_t size_) { - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::truncate(config.func.truncate.policy, - config.func.getattr.policy, - config.branches, + return l::truncate(cfg->func.truncate.policy, + cfg->func.getattr.policy, + cfg->branches, fusepath_, size_); } diff --git a/src/fuse_truncate.hpp b/src/fuse_truncate.hpp index ea7557db..61331295 100644 --- a/src/fuse_truncate.hpp +++ b/src/fuse_truncate.hpp @@ -18,6 +18,7 @@ #include + namespace FUSE { int diff --git a/src/fuse_unlink.cpp b/src/fuse_unlink.cpp index 507590c1..5f551935 100644 --- a/src/fuse_unlink.cpp +++ b/src/fuse_unlink.cpp @@ -20,7 +20,7 @@ #include "fs_unlink.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include #include @@ -84,14 +84,14 @@ namespace l static int - unlink(Policy::Func::Action actionFunc_, + unlink(const Policy::Action &unlinkPolicy_, const Branches &branches_, const char *fusepath_) { int rv; vector basepaths; - rv = actionFunc_(branches_,fusepath_,&basepaths); + rv = unlinkPolicy_(branches_,fusepath_,&basepaths); if(rv == -1) return -errno; @@ -104,14 +104,12 @@ namespace FUSE int unlink(const char *fusepath_) { - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - config.open_cache.erase(fusepath_); - - return l::unlink(config.func.unlink.policy, - config.branches, + return l::unlink(cfg->func.unlink.policy, + cfg->branches, fusepath_); } } diff --git a/src/fuse_unlink.hpp b/src/fuse_unlink.hpp index e7f1a272..845ac186 100644 --- a/src/fuse_unlink.hpp +++ b/src/fuse_unlink.hpp @@ -16,6 +16,7 @@ #pragma once + namespace FUSE { int diff --git a/src/fuse_utimens.cpp b/src/fuse_utimens.cpp index e5a072ac..83c4b584 100644 --- a/src/fuse_utimens.cpp +++ b/src/fuse_utimens.cpp @@ -21,15 +21,13 @@ #include "policy_rv.hpp" #include "ugid.hpp" -#include +#include "fuse.h" #include -#include #include using std::string; -using std::vector; namespace l @@ -73,10 +71,10 @@ namespace l static void - utimens_loop(const vector &basepaths_, - const char *fusepath_, - const timespec ts_[2], - PolicyRV *prv_) + utimens_loop(const StrVec &basepaths_, + const char *fusepath_, + const timespec ts_[2], + PolicyRV *prv_) { for(size_t i = 0, ei = basepaths_.size(); i != ei; i++) { @@ -86,17 +84,17 @@ namespace l static int - utimens(Policy::Func::Action actionFunc_, - Policy::Func::Search searchFunc_, + utimens(const Policy::Action &utimensPolicy_, + const Policy::Search &getattrPolicy_, const Branches &branches_, const char *fusepath_, const timespec ts_[2]) { int rv; PolicyRV prv; - vector basepaths; + StrVec basepaths; - rv = actionFunc_(branches_,fusepath_,&basepaths); + rv = utimensPolicy_(branches_,fusepath_,&basepaths); if(rv == -1) return -errno; @@ -107,7 +105,7 @@ namespace l return prv.error[0].rv; basepaths.clear(); - rv = searchFunc_(branches_,fusepath_,&basepaths); + rv = getattrPolicy_(branches_,fusepath_,&basepaths); if(rv == -1) return -errno; @@ -121,13 +119,13 @@ namespace FUSE utimens(const char *fusepath_, const timespec ts_[2]) { - const fuse_context *fc = fuse_get_context(); - const Config &config = Config::ro(); + Config::Read cfg; + const fuse_context *fc = fuse_get_context(); const ugid::Set ugid(fc->uid,fc->gid); - return l::utimens(config.func.utimens.policy, - config.func.getattr.policy, - config.branches, + return l::utimens(cfg->func.utimens.policy, + cfg->func.getattr.policy, + cfg->branches, fusepath_, ts_); } diff --git a/src/fuse_utimens.hpp b/src/fuse_utimens.hpp index cb78c181..2b24258e 100644 --- a/src/fuse_utimens.hpp +++ b/src/fuse_utimens.hpp @@ -18,6 +18,7 @@ #include + namespace FUSE { int diff --git a/src/fuse_write.cpp b/src/fuse_write.cpp index 9dbad931..303b6cba 100644 --- a/src/fuse_write.cpp +++ b/src/fuse_write.cpp @@ -21,16 +21,17 @@ #include "fs_write.hpp" #include "ugid.hpp" +#include "fuse.h" + #include #include -#include - using std::string; using std::vector; typedef int (*WriteFunc)(const int,const void*,const size_t,const off_t); + namespace l { static @@ -85,13 +86,13 @@ namespace l int err_) { int rv; - const Config &config = Config::ro(); + Config::Read cfg; - if(config.moveonenospc.enabled == false) + if(cfg->moveonenospc.enabled == false) return err_; - rv = fs::movefile_as_root(config.moveonenospc.policy, - config.branches, + rv = fs::movefile_as_root(cfg->moveonenospc.policy, + cfg->branches, fi_->fusepath, &fi_->fd); if(rv == -1) diff --git a/src/fuse_write.hpp b/src/fuse_write.hpp index 7d439b7c..abbfd093 100644 --- a/src/fuse_write.hpp +++ b/src/fuse_write.hpp @@ -16,7 +16,8 @@ #pragma once -#include +#include "fuse.h" + namespace FUSE { diff --git a/src/fuse_write_buf.cpp b/src/fuse_write_buf.cpp index 899e377e..fb06e4de 100644 --- a/src/fuse_write_buf.cpp +++ b/src/fuse_write_buf.cpp @@ -31,6 +31,7 @@ using std::string; using std::vector; + namespace l { static @@ -67,13 +68,13 @@ namespace l int err_) { int rv; - const Config &config = Config::ro(); + Config::Read cfg; - if(config.moveonenospc.enabled == false) + if(cfg->moveonenospc.enabled == false) return err_; - rv = fs::movefile_as_root(config.moveonenospc.policy, - config.branches, + rv = fs::movefile_as_root(cfg->moveonenospc.policy, + cfg->branches, fi_->fusepath, &fi_->fd); if(rv == -1) diff --git a/src/fuse_write_buf.hpp b/src/fuse_write_buf.hpp index cf225918..be4779df 100644 --- a/src/fuse_write_buf.hpp +++ b/src/fuse_write_buf.hpp @@ -16,10 +16,11 @@ #pragma once -#include +#include "fuse.h" #include + namespace FUSE { int diff --git a/src/hw_cpu.cpp b/src/hw_cpu.cpp index c65e713b..b829c2fc 100644 --- a/src/hw_cpu.cpp +++ b/src/hw_cpu.cpp @@ -18,6 +18,7 @@ #include + namespace hw { namespace cpu diff --git a/src/hw_cpu.hpp b/src/hw_cpu.hpp index dd17c1de..7c702219 100644 --- a/src/hw_cpu.hpp +++ b/src/hw_cpu.hpp @@ -18,6 +18,7 @@ #pragma once + namespace hw { namespace cpu diff --git a/src/mergerfs.cpp b/src/mergerfs.cpp index a5b65a15..11c7fc67 100644 --- a/src/mergerfs.cpp +++ b/src/mergerfs.cpp @@ -18,6 +18,7 @@ #include "mergerfs.hpp" #include "option_parser.hpp" #include "resources.hpp" +#include "strvec.hpp" #include "fuse_access.hpp" #include "fuse_chmod.hpp" @@ -66,13 +67,14 @@ #include "fuse_write.hpp" #include "fuse_write_buf.hpp" -#include +#include "fuse.h" #include #include #include + namespace l { static @@ -151,10 +153,10 @@ namespace l main(const int argc_, char **argv_) { - Config config; - fuse_args args; - fuse_operations ops; - std::vector errs; + Config::Read cfg; + Config::ErrVec errs; + fuse_args args; + fuse_operations ops; memset(&ops,0,sizeof(fuse_operations)); @@ -162,22 +164,17 @@ namespace l args.argv = argv_; args.allocated = 0; - options::parse(&args,&config,&errs); + options::parse(&args,&errs); if(errs.size()) - { - for(uint64_t i = 0; i < errs.size(); i++) - std::cerr << "* ERROR: " << errs[i] << std::endl; - - return 1; - } + std::cerr << errs << std::endl; l::setup_resources(); - l::get_fuse_operations(ops,config.nullrw); + l::get_fuse_operations(ops,cfg->nullrw); return fuse_main(args.argc, args.argv, &ops, - &config); + NULL); } } diff --git a/src/num.cpp b/src/num.cpp index 67ad43b7..667be092 100644 --- a/src/num.cpp +++ b/src/num.cpp @@ -16,9 +16,9 @@ #include "ef.hpp" +#include #include -#include #include #include #include @@ -28,6 +28,7 @@ #define GB (MB * 1024UL) #define TB (GB * 1024UL) + namespace num { int diff --git a/src/num.hpp b/src/num.hpp index 40ba30c2..4e8dc79e 100644 --- a/src/num.hpp +++ b/src/num.hpp @@ -16,10 +16,11 @@ #pragma once -#include - +#include #include +#include + namespace num { int to_uint64_t(const std::string &str, uint64_t *value); diff --git a/src/option_parser.cpp b/src/option_parser.cpp index 5646ee14..519b52c3 100644 --- a/src/option_parser.cpp +++ b/src/option_parser.cpp @@ -25,7 +25,7 @@ #include "str.hpp" #include "version.hpp" -#include +#include "fuse.h" #include #include @@ -48,12 +48,6 @@ enum MERGERFS_OPT_VERSION }; -struct Data -{ - Config *config; - vector *errs; -}; - namespace l { @@ -74,140 +68,81 @@ namespace l return tc; } - - static - void - read_config(Data *data_, - std::istream &is_) - { - int rv; - std::string key; - std::string val; - std::string line; - - rv = 0; - while(std::getline(is_,line,'\n')) - { - line = str::trim(line); - if(!line.empty() && (line[0] == '#')) - continue; - - str::splitkv(line,'=',&key,&val); - key = str::trim(key); - val = str::trim(val); - - if(key.empty() || val.empty()) - continue; - - rv = data_->config->set_raw(key,val); - switch(rv) - { - case -EINVAL: - data_->errs->push_back("invalid argument - " + line); - break; - case -ENOATTR: - data_->errs->push_back("unknown option - " + line); - break; - default: - break; - } - } - } - - static - void - read_config(Data *data_, - const std::string &filepath_) - { - std::ifstream is; - - is.open(filepath_); - if(is.bad()) - { - data_->errs->push_back("unable to open config - " + filepath_); - } - else - { - l::read_config(data_,is); - if(!is.eof()) - data_->errs->push_back("failure reading config file"); - is.close(); - } - } } static void -set_option(fuse_args *args, - const std::string &option_) +set_option(const std::string &option_, + fuse_args *args_) { - fuse_opt_add_arg(args,"-o"); - fuse_opt_add_arg(args,option_.c_str()); + fuse_opt_add_arg(args_,"-o"); + fuse_opt_add_arg(args_,option_.c_str()); } static void -set_kv_option(fuse_args *args, - const std::string &key, - const std::string &value) +set_kv_option(const std::string &key_, + const std::string &val_, + fuse_args *args_) { std::string option; - option = key + '=' + value; + option = key_ + '=' + val_; - set_option(args,option); + set_option(option,args_); } static void -set_threads(fuse_args *args_, - Config *config_) +set_threads(Config::Write &cfg_, + fuse_args *args_) { int threads; - threads = l::calculate_thread_count(config_->threads); + threads = l::calculate_thread_count(cfg_->threads); - config_->threads = threads; + cfg_->threads = threads; - set_kv_option(args_,"threads",config_->threads.to_string()); + set_kv_option("threads",cfg_->threads.to_string(),args_); } static void -set_fsname(fuse_args *args_, - Config *config_) +set_fsname(Config::Write &cfg_, + fuse_args *args_) { - if(config_->fsname->empty()) + if(cfg_->fsname->empty()) { - vector branches; + vector paths; - config_->branches.to_paths(branches); + cfg_->branches->to_paths(paths); - if(branches.size() > 0) - config_->fsname = str::remove_common_prefix_and_join(branches,':'); + if(paths.size() > 0) + cfg_->fsname = str::remove_common_prefix_and_join(paths,':'); } - set_kv_option(args_,"fsname",config_->fsname); + set_kv_option("fsname",cfg_->fsname,args_); } static void -set_subtype(fuse_args *args) +set_subtype(fuse_args *args_) { - set_kv_option(args,"subtype","mergerfs"); + set_kv_option("subtype","mergerfs",args_); } static void -set_default_options(fuse_args *args) +set_default_options(fuse_args *args_) { - set_option(args,"default_permissions"); + set_option("default_permissions",args_); } static int -parse_and_process_kv_arg(Data *data_, +parse_and_process_kv_arg(Config::Write &cfg_, + Config::ErrVec *errs_, const std::string &key_, const std::string &val_) { @@ -217,7 +152,7 @@ parse_and_process_kv_arg(Data *data_, rv = 0; if(key == "config") - return (l::read_config(data_,val_),0); + return ((cfg_->from_file(val_,errs_) < 0) ? 1 : 0); ef(key == "attr_timeout") key = "cache.attr"; ef(key == "entry_timeout") @@ -245,57 +180,62 @@ parse_and_process_kv_arg(Data *data_, ef(key == "cache.open") return 0; - if(data_->config->has_key(key) == false) + if(cfg_->has_key(key) == false) return 1; - rv = data_->config->set_raw(key,val); + rv = cfg_->set_raw(key,val); if(rv) - data_->errs->push_back("invalid argument - " + key_ + '=' + val_); + errs_->push_back({rv,key+'='+val}); return 0; } static int -process_opt(Data *data_, +process_opt(Config::Write &cfg_, + Config::ErrVec *errs_, const std::string &arg_) { std::string key; std::string val; str::splitkv(arg_,'=',&key,&val); + key = str::trim(key); + val = str::trim(val); - return parse_and_process_kv_arg(data_,key,val); + return parse_and_process_kv_arg(cfg_,errs_,key,val); } static int -process_branches(Data *data_, - const char *arg_) +process_branches(Config::Write &cfg_, + Config::ErrVec *errs_, + const char *arg_) { int rv; string arg; arg = arg_; - rv = data_->config->set_raw("branches",arg); + rv = cfg_->set_raw("branches",arg); if(rv) - data_->errs->push_back("unable to parse 'branches' - " + arg); + errs_->push_back({rv,"branches="+arg}); return 0; } static int -process_mount(Data *data_, - const char *arg_) +process_mount(Config::Write &cfg_, + Config::ErrVec *errs_, + const char *arg_) { int rv; string arg; arg = arg_; - rv = data_->config->set_raw("mount",arg); + rv = cfg_->set_raw("mount",arg); if(rv) - data_->errs->push_back("unable to set 'mount' - " + arg); + errs_->push_back({rv,"mount="+arg}); return 1; } @@ -412,18 +352,19 @@ option_processor(void *data_, int key_, fuse_args *outargs_) { - Data *data = (Data*)data_; + Config::Write cfg; + Config::ErrVec *errs = (Config::ErrVec*)data_; switch(key_) { case FUSE_OPT_KEY_OPT: - return process_opt(data,arg_); + return process_opt(cfg,errs,arg_); case FUSE_OPT_KEY_NONOPT: - if(data->config->branches.vec.empty()) - return process_branches(data,arg_); + if(cfg->branches->empty()) + return process_branches(cfg,errs,arg_); else - return process_mount(data,arg_); + return process_mount(cfg,errs,arg_); case MERGERFS_OPT_HELP: usage(); @@ -445,11 +386,10 @@ option_processor(void *data_, namespace options { void - parse(fuse_args *args_, - Config *config_, - std::vector *errs_) + parse(fuse_args *args_, + Config::ErrVec *errs_) { - Data data; + Config::Write cfg; const struct fuse_opt opts[] = { FUSE_OPT_KEY("-h",MERGERFS_OPT_HELP), @@ -460,21 +400,19 @@ namespace options {NULL,-1U,0} }; - data.config = config_; - data.errs = errs_; fuse_opt_parse(args_, - &data, + errs_, opts, ::option_processor); - if(config_->branches.vec.empty()) - errs_->push_back("branches not set"); - if(config_->mount->empty()) - errs_->push_back("mountpoint not set"); + if(cfg->branches->empty()) + errs_->push_back({0,"branches not set"}); + if(cfg->mount->empty()) + errs_->push_back({0,"mountpoint not set"}); set_default_options(args_); - set_fsname(args_,config_); + set_fsname(cfg,args_); set_subtype(args_); - set_threads(args_,config_); + set_threads(cfg,args_); } } diff --git a/src/option_parser.hpp b/src/option_parser.hpp index 324eb905..1e9c4122 100644 --- a/src/option_parser.hpp +++ b/src/option_parser.hpp @@ -18,15 +18,12 @@ #include "config.hpp" -#include -#include +#include "fuse.h" -#include namespace options { void - parse(fuse_args *args, - Config *config, - std::vector *errs); + parse(fuse_args *args, + Config::ErrVec *errs); } diff --git a/src/policies.cpp b/src/policies.cpp new file mode 100644 index 00000000..dc64370c --- /dev/null +++ b/src/policies.cpp @@ -0,0 +1,132 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policies.hpp" + +#define IFERTA(X) if(name_ == #X) return &Policies::Action::X; +#define IFERTC(X) if(name_ == #X) return &Policies::Create::X; +#define IFERTS(X) if(name_ == #X) return &Policies::Search::X; + +#define IFERT(FUNC) \ + FUNC(all) \ + FUNC(epall) \ + FUNC(epff) \ + FUNC(eplfs) \ + FUNC(eplus) \ + FUNC(epmfs) \ + FUNC(eppfrd) \ + FUNC(eprand) \ + FUNC(erofs) \ + FUNC(ff) \ + FUNC(lfs) \ + FUNC(lus) \ + FUNC(mfs) \ + FUNC(msplfs) \ + FUNC(msplus) \ + FUNC(mspmfs) \ + FUNC(msppfrd) \ + FUNC(newest) \ + FUNC(pfrd) \ + FUNC(rand) + +Policy::ActionImpl* +Policies::Action::find(const std::string &name_) +{ + IFERT(IFERTA); + + return NULL; +} + +Policy::CreateImpl* +Policies::Create::find(const std::string &name_) +{ + IFERT(IFERTC); + + return NULL; +} + +Policy::SearchImpl* +Policies::Search::find(const std::string &name_) +{ + IFERT(IFERTS); + + return NULL; +} + +Policy::All::Action Policies::Action::all; +Policy::EPAll::Action Policies::Action::epall; +Policy::EPFF::Action Policies::Action::epff; +Policy::EPLFS::Action Policies::Action::eplfs; +Policy::EPLUS::Action Policies::Action::eplus; +Policy::EPMFS::Action Policies::Action::epmfs; +Policy::EPPFRD::Action Policies::Action::eppfrd; +Policy::EPRand::Action Policies::Action::eprand; +Policy::ERoFS::Action Policies::Action::erofs; +Policy::FF::Action Policies::Action::ff; +Policy::LFS::Action Policies::Action::lfs; +Policy::LUS::Action Policies::Action::lus; +Policy::MFS::Action Policies::Action::mfs; +Policy::MSPLFS::Action Policies::Action::msplfs; +Policy::MSPLUS::Action Policies::Action::msplus; +Policy::MSPMFS::Action Policies::Action::mspmfs; +Policy::MSPPFRD::Action Policies::Action::msppfrd; +Policy::Newest::Action Policies::Action::newest; +Policy::PFRD::Action Policies::Action::pfrd; +Policy::Rand::Action Policies::Action::rand; + +Policy::All::Create Policies::Create::all; +Policy::EPAll::Create Policies::Create::epall; +Policy::EPFF::Create Policies::Create::epff; +Policy::EPLFS::Create Policies::Create::eplfs; +Policy::EPLUS::Create Policies::Create::eplus; +Policy::EPMFS::Create Policies::Create::epmfs; +Policy::EPPFRD::Create Policies::Create::eppfrd; +Policy::EPRand::Create Policies::Create::eprand; +Policy::ERoFS::Create Policies::Create::erofs; +Policy::FF::Create Policies::Create::ff; +Policy::LFS::Create Policies::Create::lfs; +Policy::LUS::Create Policies::Create::lus; +Policy::MFS::Create Policies::Create::mfs; +Policy::MSPLFS::Create Policies::Create::msplfs; +Policy::MSPLUS::Create Policies::Create::msplus; +Policy::MSPMFS::Create Policies::Create::mspmfs; +Policy::MSPPFRD::Create Policies::Create::msppfrd; +Policy::Newest::Create Policies::Create::newest; +Policy::PFRD::Create Policies::Create::pfrd; +Policy::Rand::Create Policies::Create::rand; + +Policy::All::Search Policies::Search::all; +Policy::EPAll::Search Policies::Search::epall; +Policy::EPFF::Search Policies::Search::epff; +Policy::EPLFS::Search Policies::Search::eplfs; +Policy::EPLUS::Search Policies::Search::eplus; +Policy::EPMFS::Search Policies::Search::epmfs; +Policy::EPPFRD::Search Policies::Search::eppfrd; +Policy::EPRand::Search Policies::Search::eprand; +Policy::ERoFS::Search Policies::Search::erofs; +Policy::FF::Search Policies::Search::ff; +Policy::LFS::Search Policies::Search::lfs; +Policy::LUS::Search Policies::Search::lus; +Policy::MFS::Search Policies::Search::mfs; +Policy::MSPLFS::Search Policies::Search::msplfs; +Policy::MSPLUS::Search Policies::Search::msplus; +Policy::MSPMFS::Search Policies::Search::mspmfs; +Policy::MSPPFRD::Search Policies::Search::msppfrd; +Policy::Newest::Search Policies::Search::newest; +Policy::PFRD::Search Policies::Search::pfrd; +Policy::Rand::Search Policies::Search::rand; diff --git a/src/policies.hpp b/src/policies.hpp new file mode 100644 index 00000000..65d7f7a0 --- /dev/null +++ b/src/policies.hpp @@ -0,0 +1,121 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy_all.hpp" +#include "policy_epall.hpp" +#include "policy_epff.hpp" +#include "policy_eplfs.hpp" +#include "policy_eplus.hpp" +#include "policy_epmfs.hpp" +#include "policy_eppfrd.hpp" +#include "policy_eprand.hpp" +#include "policy_erofs.hpp" +#include "policy_ff.hpp" +#include "policy_lfs.hpp" +#include "policy_lus.hpp" +#include "policy_mfs.hpp" +#include "policy_msplfs.hpp" +#include "policy_msplus.hpp" +#include "policy_mspmfs.hpp" +#include "policy_msppfrd.hpp" +#include "policy_newest.hpp" +#include "policy_pfrd.hpp" +#include "policy_rand.hpp" + +struct Policies +{ + struct Action + { + static Policy::ActionImpl *find(const std::string &name); + + static Policy::All::Action all; + static Policy::EPAll::Action epall; + static Policy::EPFF::Action epff; + static Policy::EPLFS::Action eplfs; + static Policy::EPLUS::Action eplus; + static Policy::EPMFS::Action epmfs; + static Policy::EPPFRD::Action eppfrd; + static Policy::EPRand::Action eprand; + static Policy::ERoFS::Action erofs; + static Policy::FF::Action ff; + static Policy::LFS::Action lfs; + static Policy::LUS::Action lus; + static Policy::MFS::Action mfs; + static Policy::MSPLFS::Action msplfs; + static Policy::MSPLUS::Action msplus; + static Policy::MSPMFS::Action mspmfs; + static Policy::MSPPFRD::Action msppfrd; + static Policy::Newest::Action newest; + static Policy::PFRD::Action pfrd; + static Policy::Rand::Action rand; + }; + + struct Create + { + static Policy::CreateImpl *find(const std::string &name); + + static Policy::All::Create all; + static Policy::EPAll::Create epall; + static Policy::EPFF::Create epff; + static Policy::EPLFS::Create eplfs; + static Policy::EPLUS::Create eplus; + static Policy::EPMFS::Create epmfs; + static Policy::EPPFRD::Create eppfrd; + static Policy::EPRand::Create eprand; + static Policy::ERoFS::Create erofs; + static Policy::FF::Create ff; + static Policy::LFS::Create lfs; + static Policy::LUS::Create lus; + static Policy::MFS::Create mfs; + static Policy::MSPLFS::Create msplfs; + static Policy::MSPLUS::Create msplus; + static Policy::MSPMFS::Create mspmfs; + static Policy::MSPPFRD::Create msppfrd; + static Policy::Newest::Create newest; + static Policy::PFRD::Create pfrd; + static Policy::Rand::Create rand; + }; + + struct Search + { + static Policy::SearchImpl *find(const std::string &name); + + static Policy::All::Search all; + static Policy::EPAll::Search epall; + static Policy::EPFF::Search epff; + static Policy::EPLFS::Search eplfs; + static Policy::EPLUS::Search eplus; + static Policy::EPMFS::Search epmfs; + static Policy::EPPFRD::Search eppfrd; + static Policy::EPRand::Search eprand; + static Policy::ERoFS::Search erofs; + static Policy::FF::Search ff; + static Policy::LFS::Search lfs; + static Policy::LUS::Search lus; + static Policy::MFS::Search mfs; + static Policy::MSPLFS::Search msplfs; + static Policy::MSPLUS::Search msplus; + static Policy::MSPMFS::Search mspmfs; + static Policy::MSPPFRD::Search msppfrd; + static Policy::Newest::Search newest; + static Policy::PFRD::Search pfrd; + static Policy::Rand::Search rand; + }; +}; diff --git a/src/policy.cpp b/src/policy.cpp deleted file mode 100644 index 3e854bad..00000000 --- a/src/policy.cpp +++ /dev/null @@ -1,96 +0,0 @@ -/* - Copyright (c) 2016, Antonio SJ Musumeci - - 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 - -#include "buildvector.hpp" -#include "policy.hpp" - -#define POLICY(X,PP) (Policy(Policy::Enum::X,#X,Policy::Func::X,PP)) -#define PRESERVES_PATH true -#define DOESNT_PRESERVE_PATH false - -const std::vector Policy::_policies_ = - buildvector - (POLICY(invalid,DOESNT_PRESERVE_PATH)) - (POLICY(all,DOESNT_PRESERVE_PATH)) - (POLICY(epall,PRESERVES_PATH)) - (POLICY(epff,PRESERVES_PATH)) - (POLICY(eplfs,PRESERVES_PATH)) - (POLICY(eplus,PRESERVES_PATH)) - (POLICY(epmfs,PRESERVES_PATH)) - (POLICY(eppfrd,PRESERVES_PATH)) - (POLICY(eprand,PRESERVES_PATH)) - (POLICY(erofs,DOESNT_PRESERVE_PATH)) - (POLICY(ff,DOESNT_PRESERVE_PATH)) - (POLICY(lfs,DOESNT_PRESERVE_PATH)) - (POLICY(lus,DOESNT_PRESERVE_PATH)) - (POLICY(mfs,DOESNT_PRESERVE_PATH)) - (POLICY(msplfs,PRESERVES_PATH)) - (POLICY(msplus,PRESERVES_PATH)) - (POLICY(mspmfs,PRESERVES_PATH)) - (POLICY(msppfrd,PRESERVES_PATH)) - (POLICY(newest,DOESNT_PRESERVE_PATH)) - (POLICY(pfrd,DOESNT_PRESERVE_PATH)) - (POLICY(rand,DOESNT_PRESERVE_PATH)); - -const Policy * const Policy::policies = &_policies_[1]; - -#define CONST_POLICY(X) const Policy &Policy::X = Policy::policies[Policy::Enum::X] - -CONST_POLICY(invalid); -CONST_POLICY(all); -CONST_POLICY(epall); -CONST_POLICY(epff); -CONST_POLICY(eplfs); -CONST_POLICY(eplus); -CONST_POLICY(epmfs); -CONST_POLICY(eppfrd); -CONST_POLICY(eprand); -CONST_POLICY(erofs); -CONST_POLICY(ff); -CONST_POLICY(lfs); -CONST_POLICY(lus); -CONST_POLICY(mfs); -CONST_POLICY(msplfs); -CONST_POLICY(msplus); -CONST_POLICY(mspmfs); -CONST_POLICY(msppfrd); -CONST_POLICY(newest); -CONST_POLICY(pfrd); -CONST_POLICY(rand); - -const Policy& -Policy::find(const std::string &str) -{ - for(int i = Enum::BEGIN; i != Enum::END; ++i) - { - if(policies[i] == str) - return policies[i]; - } - - return invalid; -} - -const Policy& -Policy::find(const Policy::Enum::Type i) -{ - if(i >= Policy::Enum::BEGIN && - i < Policy::Enum::END) - return policies[i]; - - return invalid; -} diff --git a/src/policy.hpp b/src/policy.hpp index 1663e618..e527b94a 100644 --- a/src/policy.hpp +++ b/src/policy.hpp @@ -1,5 +1,5 @@ /* - Copyright (c) 2016, Antonio SJ Musumeci + Copyright (c) 2020, Antonio SJ Musumeci Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -16,217 +16,179 @@ #pragma once -#include "branch.hpp" -#include "category.hpp" +#include "branches.hpp" +#include "strvec.hpp" #include -#include -class Policy +namespace Policy { -public: - struct Enum + class ActionImpl { - enum Type - { - invalid = -1, - BEGIN = 0, - all = BEGIN, - epall, - epff, - eplfs, - eplus, - epmfs, - eppfrd, - eprand, - erofs, - ff, - lfs, - lus, - mfs, - msplfs, - msplus, - mspmfs, - msppfrd, - newest, - pfrd, - rand, - END - }; - - static size_t begin() { return BEGIN; } - static size_t end() { return END; } + public: + ActionImpl(const std::string &name_) + : name(name_) + { + } + + public: + std::string name; + virtual int operator()(const Branches::CPtr&,const char*,StrVec*) const = 0; }; - struct Func + class Action { - typedef std::string string; - typedef std::vector strvec; - typedef const string cstring; - typedef const uint64_t cuint64_t; - typedef const strvec cstrvec; - - typedef int (*Ptr)(Category,const Branches&,const char*,strvec *); - - template - class Base - { - public: - Base(const Policy &p_) - : func(p_._func) - {} - - Base(const Policy *p_) - : func(p_->_func) - {} - - int - operator()(const Branches &a,const char *b,strvec *c) - { - return func(T,a,b,c); - } - - int - operator()(const Branches &a,const string &b,strvec *c) - { - return func(T,a,b.c_str(),c); - } - - int - operator()(const Branches &a,const char *b,string *c) - { - int rv; - strvec v; - - rv = func(T,a,b,&v); - if(!v.empty()) - *c = v[0]; - - return rv; - } - - private: - const Ptr func; - }; - - typedef Base Action; - typedef Base Create; - typedef Base Search; - - static int invalid(Category,const Branches&,const char *,strvec*); - static int all(Category,const Branches&,const char*,strvec*); - static int epall(Category,const Branches&,const char*,strvec*); - static int epff(Category,const Branches&,const char *,strvec*); - static int eplfs(Category,const Branches&,const char *,strvec*); - static int eplus(Category,const Branches&,const char *,strvec*); - static int epmfs(Category,const Branches&,const char *,strvec*); - static int eppfrd(Category,const Branches&,const char *,strvec*); - static int eprand(Category,const Branches&,const char *,strvec*); - static int erofs(Category,const Branches&,const char *,strvec*); - static int ff(Category,const Branches&,const char *,strvec*); - static int lfs(Category,const Branches&,const char *,strvec*); - static int lus(Category,const Branches&,const char *,strvec*); - static int mfs(Category,const Branches&,const char *,strvec*); - static int msplfs(Category,const Branches&,const char *,strvec*); - static int msplus(Category,const Branches&,const char *,strvec*); - static int mspmfs(Category,const Branches&,const char *,strvec*); - static int msppfrd(Category,const Branches&,const char *,strvec*); - static int newest(Category,const Branches&,const char *,strvec*); - static int pfrd(Category,const Branches&,const char *,strvec*); - static int rand(Category,const Branches&,const char *,strvec*); + public: + Action(ActionImpl *impl_) + : impl(impl_) + {} + + Action& + operator=(ActionImpl *impl_) + { + impl = impl_; + return *this; + } + + const + std::string& + name(void) const + { + return impl->name; + } + + int + operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const + { + return (*impl)(branches_,fusepath_,paths_); + } + + int + operator()(const Branches::CPtr &branches_, + const std::string &fusepath_, + StrVec *paths_) const + { + return (*impl)(branches_,fusepath_.c_str(),paths_); + } + + private: + ActionImpl *impl; }; -private: - Enum::Type _enum; - std::string _str; - Func::Ptr _func; - bool _path_preserving; - -public: - Policy() - : _enum(invalid), - _str(invalid), - _func(invalid), - _path_preserving(false) + class CreateImpl { - } - - Policy(const Enum::Type enum_, - const std::string &str_, - const Func::Ptr func_, - const bool path_preserving_) - : _enum(enum_), - _str(str_), - _func(func_), - _path_preserving(path_preserving_) + public: + CreateImpl(const std::string &name_) + : name(name_) + { + } + + public: + std::string name; + virtual int operator()(const Branches::CPtr&,const char*,StrVec*) const = 0; + virtual bool path_preserving(void) const = 0; + }; + + class Create { - } + public: + Create(CreateImpl *impl_) + : impl(impl_) + {} + + Create& + operator=(CreateImpl *impl_) + { + impl = impl_; + return *this; + } + + const + std::string& + name(void) const + { + return impl->name; + } + + bool + path_preserving(void) const + { + return impl->path_preserving(); + } - bool - path_preserving() const + int + operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const + { + return (*impl)(branches_,fusepath_,paths_); + } + + int + operator()(const Branches::CPtr &branches_, + const std::string &fusepath_, + StrVec *paths_) const + { + return (*impl)(branches_,fusepath_.c_str(),paths_); + } + + private: + CreateImpl *impl; + }; + + class SearchImpl { - return _path_preserving; - } - -public: - operator const Enum::Type() const { return _enum; } - operator const std::string&() const { return _str; } - operator const Func::Ptr() const { return _func; } - operator const Policy*() const { return this; } - const std::string& to_string() const { return _str; } - - bool operator==(const Enum::Type enum_) const - { return _enum == enum_; } - bool operator==(const std::string &str_) const - { return _str == str_; } - bool operator==(const Func::Ptr func_) const - { return _func == func_; } - - bool operator!=(const Policy &r) const - { return _enum != r._enum; } - - bool operator<(const Policy &r) const - { return _enum < r._enum; } - -public: - static const Policy &find(const std::string&); - static const Policy &find(const Enum::Type); - -public: - - static const std::vector _policies_; - static const Policy * const policies; - - static const Policy &invalid; - static const Policy &all; - static const Policy &epall; - static const Policy &epff; - static const Policy &eplfs; - static const Policy ⩱ - static const Policy &epmfs; - static const Policy &eppfrd; - static const Policy &eprand; - static const Policy &erofs; - static const Policy &ff; - static const Policy &lfs; - static const Policy &lus; - static const Policy &mfs; - static const Policy &msplfs; - static const Policy &msplus; - static const Policy &mspmfs; - static const Policy &msppfrd; - static const Policy &newest; - static const Policy &pfrd; - static const Policy &rand; -}; - -namespace std -{ - static - inline - string - to_string(const Policy &p_) + public: + SearchImpl(const std::string &name_) + : name(name_) + { + } + + public: + std::string name; + virtual int operator()(const Branches::CPtr&,const char*,StrVec*) const = 0; + }; + + class Search { - return p_.to_string(); - } + public: + Search(SearchImpl *impl_) + : impl(impl_) + {} + + Search& + operator=(SearchImpl *impl_) + { + impl = impl_; + return *this; + } + + const + std::string& + name(void) const + { + return impl->name; + } + + int + operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const + { + return (*impl)(branches_,fusepath_,paths_); + } + + int + operator()(const Branches::CPtr &branches_, + const std::string &fusepath_, + StrVec *paths_) const + { + return (*impl)(branches_,fusepath_.c_str(),paths_); + } + + private: + SearchImpl *impl; + }; } diff --git a/src/policy_all.cpp b/src/policy_all.cpp index 92d86bfc..785a634b 100644 --- a/src/policy_all.cpp +++ b/src/policy_all.cpp @@ -19,43 +19,39 @@ #include "fs_info.hpp" #include "fs_path.hpp" #include "policy.hpp" +#include "policies.hpp" #include "policy_error.hpp" -#include "rwlock.hpp" +#include "strvec.hpp" #include -#include using std::string; -using std::vector; namespace all { static int - create(const BranchVec &branches_, - vector *paths_) + create(const Branches::CPtr &branches_, + StrVec *paths_) { int rv; int error; fs::info_t info; - const Branch *branch; error = ENOENT; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(error,EROFS); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) error_and_continue(error,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(error,ENOSPC); - paths_->push_back(branch->path); + paths_->push_back(branch.path); } if(paths_->empty()) @@ -63,26 +59,28 @@ namespace all return 0; } +} - static - int - create(const Branches &branches_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return all::create(branches_.vec,paths_); - } +int +Policy::All::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Action::epall(branches_,fusepath_,paths_); } int -Policy::Func::all(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::All::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - if(type_ == Category::CREATE) - return all::create(branches_,paths_); + return ::all::create(branches_,paths_); +} - return Policy::Func::epall(type_,branches_,fusepath_,paths_); +int +Policy::All::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Search::epall(branches_,fusepath_,paths_); } diff --git a/src/policy_all.hpp b/src/policy_all.hpp new file mode 100644 index 00000000..8f5b67c8 --- /dev/null +++ b/src/policy_all.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace All + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("all") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("all") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving(void) const final { return false; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("all") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_cache.cpp b/src/policy_cache.cpp index 08645eab..590ea54f 100644 --- a/src/policy_cache.cpp +++ b/src/policy_cache.cpp @@ -28,7 +28,7 @@ namespace l PolicyCache::Value::Value() : time(0), - path() + paths() { } @@ -91,18 +91,17 @@ PolicyCache::clear(void) } int -PolicyCache::operator()(Policy::Func::Search &func_, +PolicyCache::operator()(const Policy::Search &policy_, const Branches &branches_, const char *fusepath_, - std::string *branch_) + StrVec *paths_) { int rv; Value *v; uint64_t now; - string branch; if(timeout == 0) - return func_(branches_,fusepath_,branch_); + return policy_(branches_,fusepath_,paths_); now = l::get_time(); @@ -112,16 +111,19 @@ PolicyCache::operator()(Policy::Func::Search &func_, if((now - v->time) >= timeout) { pthread_mutex_unlock(&_lock); - rv = func_(branches_,fusepath_,&branch); + + rv = policy_(branches_,fusepath_,paths_); if(rv == -1) return -1; pthread_mutex_lock(&_lock); - v->time = now; - v->path = branch; + v->time = now; + v->paths = *paths_; + } + else + { + *paths_ = v->paths; } - - *branch_ = v->path; pthread_mutex_unlock(&_lock); diff --git a/src/policy_cache.hpp b/src/policy_cache.hpp index dc7218d9..6cdb9280 100644 --- a/src/policy_cache.hpp +++ b/src/policy_cache.hpp @@ -19,12 +19,14 @@ #pragma once #include "policy.hpp" +#include "strvec.hpp" +#include #include #include #include -#include + class PolicyCache { @@ -33,8 +35,8 @@ public: { Value(); - uint64_t time; - std::string path; + uint64_t time; + StrVec paths; }; public: @@ -46,10 +48,10 @@ public: void clear(void); public: - int operator()(Policy::Func::Search &func, + int operator()(const Policy::Search &policy, const Branches &branches, const char *fusepath, - std::string *branch); + StrVec *paths); public: uint64_t timeout; diff --git a/src/policy_epall.cpp b/src/policy_epall.cpp index 47c1992e..af4b526b 100644 --- a/src/policy_epall.cpp +++ b/src/policy_epall.cpp @@ -20,46 +20,43 @@ #include "fs_path.hpp" #include "fs_statvfs_cache.hpp" #include "policy.hpp" +#include "policy_epall.hpp" #include "policy_error.hpp" -#include "rwlock.hpp" +#include "strvec.hpp" #include -#include using std::string; -using std::vector; + namespace epall { static int - create(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + create(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int rv; int error; fs::info_t info; - const Branch *branch; error = ENOENT; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(error,EROFS); - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) error_and_continue(error,ENOENT); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) error_and_continue(error,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(error,ENOSPC); - paths_->push_back(branch->path); + paths_->push_back(branch.path); } if(paths_->empty()) @@ -70,42 +67,28 @@ namespace epall static int - create(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return epall::create(branches_.vec,fusepath_,paths_); - } - - static - int - action(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + action(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int rv; int error; bool readonly; - const Branch *branch; error = ENOENT; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro()) + if(branch.ro()) error_and_continue(error,EROFS); - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) error_and_continue(error,ENOENT); - rv = fs::statvfs_cache_readonly(branch->path,&readonly); + rv = fs::statvfs_cache_readonly(branch.path,&readonly); if(rv == -1) error_and_continue(error,ENOENT); if(readonly) error_and_continue(error,EROFS); - paths_->push_back(branch->path); + paths_->push_back(branch.path); } if(paths_->empty()) @@ -116,31 +99,16 @@ namespace epall static int - action(const Branches &branches_, - const char *fusepath_, - vector *paths_) + search(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { - rwlock::ReadGuard guard(branches_.lock); - - return epall::action(branches_.vec,fusepath_,paths_); - } - - static - int - search(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) - { - const Branch *branch; - - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) continue; - paths_->push_back(branch->path); + paths_->push_back(branch.path); } if(paths_->empty()) @@ -148,33 +116,28 @@ namespace epall return 0; } +} - static - int - search(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); +int +Policy::EPAll::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::epall::action(branches_,fusepath_,paths_); +} - return epall::search(branches_.vec,fusepath_,paths_); - } +int +Policy::EPAll::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::epall::create(branches_,fusepath_,paths_); } int -Policy::Func::epall(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::EPAll::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - switch(type_) - { - case Category::CREATE: - return epall::create(branches_,fusepath_,paths_); - case Category::ACTION: - return epall::action(branches_,fusepath_,paths_); - case Category::SEARCH: - default: - return epall::search(branches_,fusepath_,paths_); - } + return ::epall::search(branches_,fusepath_,paths_); } diff --git a/src/policy_epall.hpp b/src/policy_epall.hpp new file mode 100644 index 00000000..1b665671 --- /dev/null +++ b/src/policy_epall.hpp @@ -0,0 +1,64 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace EPAll + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("epall") + { + } + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("epall") + { + } + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving(void) const final { return true; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("epall") + { + } + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_epff.cpp b/src/policy_epff.cpp index ac519c96..d2980f42 100644 --- a/src/policy_epff.cpp +++ b/src/policy_epff.cpp @@ -14,12 +14,14 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include "branches.hpp" #include "errno.hpp" #include "fs_exists.hpp" #include "fs_info.hpp" #include "fs_path.hpp" #include "fs_statvfs_cache.hpp" #include "policy.hpp" +#include "policy_epff.hpp" #include "policy_error.hpp" #include "rwlock.hpp" @@ -33,33 +35,30 @@ namespace epff { static int - create(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + create(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int rv; int error; fs::info_t info; - const Branch *branch; error = ENOENT; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(error,EROFS); - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) error_and_continue(error,ENOENT); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) error_and_continue(error,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(error,ENOSPC); - paths_->push_back(branch->path); + paths_->push_back(branch.path); return 0; } @@ -69,42 +68,28 @@ namespace epff static int - create(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return epff::create(branches_.vec,fusepath_,paths_); - } - - static - int - action(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + action(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int rv; int error; bool readonly; - const Branch *branch; error = ENOENT; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro()) + if(branch.ro()) error_and_continue(error,EROFS); - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) error_and_continue(error,ENOENT); - rv = fs::statvfs_cache_readonly(branch->path,&readonly); + rv = fs::statvfs_cache_readonly(branch.path,&readonly); if(rv == -1) error_and_continue(error,ENOENT); if(readonly) error_and_continue(error,EROFS); - paths_->push_back(branch->path); + paths_->push_back(branch.path); return 0; } @@ -114,64 +99,44 @@ namespace epff static int - action(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return epff::action(branches_.vec,fusepath_,paths_); - } - - static - int - search(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + search(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { - const Branch *branch; - - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) continue; - paths_->push_back(branch->path); + paths_->push_back(branch.path); return 0; } return (errno=ENOENT,-1); } +} - static - int - search(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); +int +Policy::EPFF::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::epff::action(branches_,fusepath_,paths_); +} - return epff::search(branches_.vec,fusepath_,paths_); - } +int +Policy::EPFF::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::epff::create(branches_,fusepath_,paths_); } int -Policy::Func::epff(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::EPFF::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - switch(type_) - { - case Category::CREATE: - return epff::create(branches_,fusepath_,paths_); - case Category::ACTION: - return epff::action(branches_,fusepath_,paths_); - case Category::SEARCH: - default: - return epff::search(branches_,fusepath_,paths_); - } + return ::epff::search(branches_,fusepath_,paths_); } diff --git a/src/policy_epff.hpp b/src/policy_epff.hpp new file mode 100644 index 00000000..0e3e5f4a --- /dev/null +++ b/src/policy_epff.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace EPFF + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("epff") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("epff") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving(void) const final { return true; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("epff") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_eplfs.cpp b/src/policy_eplfs.cpp index 26164fdd..3ef4ed18 100644 --- a/src/policy_eplfs.cpp +++ b/src/policy_eplfs.cpp @@ -19,9 +19,10 @@ #include "fs_info.hpp" #include "fs_path.hpp" #include "fs_statvfs_cache.hpp" +#include "policies.hpp" #include "policy.hpp" +#include "policy_eplfs.hpp" #include "policy_error.hpp" -#include "rwlock.hpp" #include #include @@ -34,40 +35,37 @@ namespace eplfs { static int - create(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + create(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int rv; int error; uint64_t eplfs; fs::info_t info; - const Branch *branch; const string *basepath; error = ENOENT; eplfs = std::numeric_limits::max(); basepath = NULL; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(const auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(error,EROFS); - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) error_and_continue(error,ENOENT); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) error_and_continue(error,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(error,ENOSPC); if(info.spaceavail > eplfs) continue; eplfs = info.spaceavail; - basepath = &branch->path; + basepath = &branch.path; } if(basepath == NULL) @@ -80,40 +78,26 @@ namespace eplfs static int - create(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return eplfs::create(branches_.vec,fusepath_,paths_); - } - - static - int - action(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + action(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int rv; int error; uint64_t eplfs; fs::info_t info; - const Branch *branch; const string *basepath; error = ENOENT; eplfs = std::numeric_limits::max(); basepath = NULL; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(const auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro()) + if(branch.ro()) error_and_continue(error,EROFS); - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) error_and_continue(error,ENOENT); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) @@ -122,7 +106,7 @@ namespace eplfs continue; eplfs = info.spaceavail; - basepath = &branch->path; + basepath = &branch.path; } if(basepath == NULL) @@ -135,43 +119,29 @@ namespace eplfs static int - action(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return eplfs::action(branches_.vec,fusepath_,paths_); - } - - static - int - search(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + search(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int rv; uint64_t eplfs; uint64_t spaceavail; - const Branch *branch; const string *basepath; eplfs = std::numeric_limits::max(); basepath = NULL; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(const auto &branch : *branches_) { - branch = &branches_[i]; - - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) continue; - rv = fs::statvfs_cache_spaceavail(branch->path,&spaceavail); + rv = fs::statvfs_cache_spaceavail(branch.path,&spaceavail); if(rv == -1) continue; if(spaceavail > eplfs) continue; eplfs = spaceavail; - basepath = &branch->path; + basepath = &branch.path; } if(basepath == NULL) @@ -181,33 +151,28 @@ namespace eplfs return 0; } +} - static - int - search(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); +int +Policy::EPLFS::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::eplfs::action(branches_,fusepath_,paths_); +} - return eplfs::search(branches_.vec,fusepath_,paths_); - } +int +Policy::EPLFS::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::eplfs::create(branches_,fusepath_,paths_); } int -Policy::Func::eplfs(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::EPLFS::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - switch(type_) - { - case Category::CREATE: - return eplfs::create(branches_,fusepath_,paths_); - case Category::ACTION: - return eplfs::action(branches_,fusepath_,paths_); - case Category::SEARCH: - default: - return eplfs::search(branches_,fusepath_,paths_); - } + return ::eplfs::search(branches_,fusepath_,paths_); } diff --git a/src/policy_eplfs.hpp b/src/policy_eplfs.hpp new file mode 100644 index 00000000..60006b06 --- /dev/null +++ b/src/policy_eplfs.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace EPLFS + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("eplfs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("eplfs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving(void) const final { return true; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("eplfs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_eplus.cpp b/src/policy_eplus.cpp index b8c79ab1..e5bac154 100644 --- a/src/policy_eplus.cpp +++ b/src/policy_eplus.cpp @@ -20,54 +20,50 @@ #include "fs_path.hpp" #include "fs_statvfs_cache.hpp" #include "policy.hpp" +#include "policy_eplus.hpp" #include "policy_error.hpp" #include "rwlock.hpp" #include #include -#include using std::string; -using std::vector; namespace eplus { static int - create(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + create(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int rv; int error; uint64_t eplus; fs::info_t info; - const Branch *branch; const string *basepath; error = ENOENT; eplus = std::numeric_limits::max(); basepath = NULL; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(error,EROFS); - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) error_and_continue(error,ENOENT); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) error_and_continue(error,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(error,ENOSPC); if(info.spaceused >= eplus) continue; eplus = info.spaceused; - basepath = &branch->path; + basepath = &branch.path; } if(basepath == NULL) @@ -80,40 +76,26 @@ namespace eplus static int - create(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return eplus::create(branches_.vec,fusepath_,paths_); - } - - static - int - action(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + action(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int rv; int error; uint64_t eplus; fs::info_t info; - const Branch *branch; const string *basepath; error = ENOENT; eplus = std::numeric_limits::max(); basepath = NULL; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro()) + if(branch.ro()) error_and_continue(error,EROFS); - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) error_and_continue(error,ENOENT); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) @@ -122,7 +104,7 @@ namespace eplus continue; eplus = info.spaceused; - basepath = &branch->path; + basepath = &branch.path; } if(basepath == NULL) @@ -135,43 +117,29 @@ namespace eplus static int - action(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return eplus::action(branches_.vec,fusepath_,paths_); - } - - static - int - search(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + search(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int rv; uint64_t eplus; uint64_t spaceused; - const Branch *branch; const string *basepath; eplus = 0; basepath = NULL; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) continue; - rv = fs::statvfs_cache_spaceused(branch->path,&spaceused); + rv = fs::statvfs_cache_spaceused(branch.path,&spaceused); if(rv == -1) continue; if(spaceused >= eplus) continue; eplus = spaceused; - basepath = &branch->path; + basepath = &branch.path; } if(basepath == NULL) @@ -181,33 +149,28 @@ namespace eplus return 0; } +} - static - int - search(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); +int +Policy::EPLUS::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::eplus::action(branches_,fusepath_,paths_); +} - return eplus::search(branches_.vec,fusepath_,paths_); - } +int +Policy::EPLUS::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::eplus::create(branches_,fusepath_,paths_); } int -Policy::Func::eplus(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::EPLUS::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - switch(type_) - { - case Category::CREATE: - return eplus::create(branches_,fusepath_,paths_); - case Category::ACTION: - return eplus::action(branches_,fusepath_,paths_); - case Category::SEARCH: - default: - return eplus::search(branches_,fusepath_,paths_); - } + return ::eplus::search(branches_,fusepath_,paths_); } diff --git a/src/policy_eplus.hpp b/src/policy_eplus.hpp new file mode 100644 index 00000000..ca253f7e --- /dev/null +++ b/src/policy_eplus.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace EPLUS + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("eplus") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("eplus") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving(void) const final { return true; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("eplus") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_epmfs.cpp b/src/policy_epmfs.cpp index b4e24919..7f44c032 100644 --- a/src/policy_epmfs.cpp +++ b/src/policy_epmfs.cpp @@ -20,54 +20,51 @@ #include "fs_path.hpp" #include "fs_statvfs_cache.hpp" #include "policy.hpp" +#include "policy_epmfs.hpp" #include "policy_error.hpp" -#include "rwlock.hpp" #include #include -#include + using std::string; -using std::vector; + namespace epmfs { static int - create(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + create(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int rv; int error; uint64_t epmfs; fs::info_t info; - const Branch *branch; const string *basepath; error = ENOENT; epmfs = std::numeric_limits::min(); basepath = NULL; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(const auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(error,EROFS); - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) error_and_continue(error,ENOENT); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) error_and_continue(error,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(error,ENOSPC); if(info.spaceavail < epmfs) continue; epmfs = info.spaceavail; - basepath = &branch->path; + basepath = &branch.path; } if(basepath == NULL) @@ -80,40 +77,26 @@ namespace epmfs static int - create(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return epmfs::create(branches_.vec,fusepath_,paths_); - } - - static - int - action(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + action(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int rv; int error; uint64_t epmfs; fs::info_t info; - const Branch *branch; const string *basepath; error = ENOENT; epmfs = std::numeric_limits::min(); basepath = NULL; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(const auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro()) + if(branch.ro()) error_and_continue(error,EROFS); - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) error_and_continue(error,ENOENT); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) @@ -122,7 +105,7 @@ namespace epmfs continue; epmfs = info.spaceavail; - basepath = &branch->path; + basepath = &branch.path; } if(basepath == NULL) @@ -135,43 +118,29 @@ namespace epmfs static int - action(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return epmfs::action(branches_.vec,fusepath_,paths_); - } - - static - int - search(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + search(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int rv; uint64_t epmfs; uint64_t spaceavail; - const Branch *branch; const string *basepath; epmfs = 0; basepath = NULL; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(const auto &branch : *branches_) { - branch = &branches_[i]; - - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) continue; - rv = fs::statvfs_cache_spaceavail(branch->path,&spaceavail); + rv = fs::statvfs_cache_spaceavail(branch.path,&spaceavail); if(rv == -1) continue; if(spaceavail < epmfs) continue; epmfs = spaceavail; - basepath = &branch->path; + basepath = &branch.path; } if(basepath == NULL) @@ -181,33 +150,28 @@ namespace epmfs return 0; } +} - static - int - search(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); +int +Policy::EPMFS::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::epmfs::action(branches_,fusepath_,paths_); +} - return epmfs::search(branches_.vec,fusepath_,paths_); - } +int +Policy::EPMFS::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::epmfs::create(branches_,fusepath_,paths_); } int -Policy::Func::epmfs(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::EPMFS::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - switch(type_) - { - case Category::CREATE: - return epmfs::create(branches_,fusepath_,paths_); - case Category::ACTION: - return epmfs::action(branches_,fusepath_,paths_); - case Category::SEARCH: - default: - return epmfs::search(branches_,fusepath_,paths_); - } + return ::epmfs::search(branches_,fusepath_,paths_); } diff --git a/src/policy_epmfs.hpp b/src/policy_epmfs.hpp new file mode 100644 index 00000000..e0b8382a --- /dev/null +++ b/src/policy_epmfs.hpp @@ -0,0 +1,64 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace EPMFS + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("epmfs") + { + } + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("epmfs") + { + } + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving(void) const final { return true; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("epmfs") + { + } + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_eppfrd.cpp b/src/policy_eppfrd.cpp index 2c38efc2..d2ba449c 100644 --- a/src/policy_eppfrd.cpp +++ b/src/policy_eppfrd.cpp @@ -20,9 +20,11 @@ #include "fs_path.hpp" #include "fs_statvfs_cache.hpp" #include "policy.hpp" +#include "policy_eppfrd.hpp" #include "policy_error.hpp" #include "rnd.hpp" #include "rwlock.hpp" +#include "strvec.hpp" #include #include @@ -42,39 +44,36 @@ namespace eppfrd { static int - get_branchinfo_create(const BranchVec &branches_, - const char *fusepath_, - BranchInfoVec *branchinfo_, - uint64_t *sum_) + get_branchinfo_create(const Branches::CPtr &branches_, + const char *fusepath_, + BranchInfoVec *branchinfo_, + uint64_t *sum_) { int rv; int error; BranchInfo bi; fs::info_t info; - const Branch *branch; *sum_ = 0; error = ENOENT; - for(size_t i = 0, ei = branches_.size(); i < ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(error,EROFS); - if(!fs::exists(branch->path,fusepath_)) - error_and_continue(error,ENOENT); - rv = fs::info(branch->path,&info); + if(!fs::exists(branch.path,fusepath_)) + error_and_continue(error,ENOENT); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) error_and_continue(error,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(error,ENOSPC); *sum_ += info.spaceavail; bi.spaceavail = info.spaceavail; - bi.basepath = &branch->path; + bi.basepath = &branch.path; branchinfo_->push_back(bi); } @@ -83,42 +82,25 @@ namespace eppfrd static int - get_branchinfo_create(const Branches &branches_, - const char *fusepath_, - BranchInfoVec *branchinfo_, - uint64_t *sum_) - { - rwlock::ReadGuard guard(branches_.lock); - - branchinfo_->reserve(branches_.vec.size()); - - return eppfrd::get_branchinfo_create(branches_.vec,fusepath_,branchinfo_,sum_); - } - - static - int - get_branchinfo_action(const BranchVec &branches_, - const char *fusepath_, - BranchInfoVec *branchinfo_, - uint64_t *sum_) + get_branchinfo_action(const Branches::CPtr &branches_, + const char *fusepath_, + BranchInfoVec *branchinfo_, + uint64_t *sum_) { int rv; int error; BranchInfo bi; fs::info_t info; - const Branch *branch; *sum_ = 0; error = ENOENT; - for(size_t i = 0, ei = branches_.size(); i < ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro()) + if(branch.ro()) error_and_continue(error,EROFS); - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) error_and_continue(error,ENOENT); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) @@ -127,7 +109,7 @@ namespace eppfrd *sum_ += info.spaceavail; bi.spaceavail = info.spaceavail; - bi.basepath = &branch->path; + bi.basepath = &branch.path; branchinfo_->push_back(bi); } @@ -136,65 +118,34 @@ namespace eppfrd static int - get_branchinfo_action(const Branches &branches_, - const char *fusepath_, - BranchInfoVec *branchinfo_, - uint64_t *sum_) - { - rwlock::ReadGuard guard(branches_.lock); - - branchinfo_->reserve(branches_.vec.size()); - - return eppfrd::get_branchinfo_action(branches_.vec,fusepath_,branchinfo_,sum_); - } - - static - int - get_branchinfo_search(const BranchVec &branches_, - const char *fusepath_, - BranchInfoVec *branchinfo_, - uint64_t *sum_) + get_branchinfo_search(const Branches::CPtr &branches_, + const char *fusepath_, + BranchInfoVec *branchinfo_, + uint64_t *sum_) { int rv; BranchInfo bi; uint64_t spaceavail; - const Branch *branch; *sum_ = 0; - for(size_t i = 0, ei = branches_.size(); i < ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) continue; - rv = fs::statvfs_cache_spaceavail(branch->path,&spaceavail); + rv = fs::statvfs_cache_spaceavail(branch.path,&spaceavail); if(rv == -1) continue; *sum_ += spaceavail; bi.spaceavail = spaceavail; - bi.basepath = &branch->path; + bi.basepath = &branch.path; branchinfo_->push_back(bi); } return ENOENT; } - static - int - get_branchinfo_search(const Branches &branches_, - const char *fusepath_, - BranchInfoVec *branchinfo_, - uint64_t *sum_) - { - rwlock::ReadGuard guard(branches_.lock); - - branchinfo_->reserve(branches_.vec.size()); - - return eppfrd::get_branchinfo_search(branches_.vec,fusepath_,branchinfo_,sum_); - } - static const string* @@ -221,9 +172,9 @@ namespace eppfrd static int - create(const Branches &branches_, - const char *fusepath_, - vector *paths_) + create(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int error; uint64_t sum; @@ -242,9 +193,9 @@ namespace eppfrd static int - action(const Branches &branches_, - const char *fusepath_, - vector *paths_) + action(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int error; uint64_t sum; @@ -263,9 +214,9 @@ namespace eppfrd static int - search(const Branches &branches_, - const char *fusepath_, - vector *paths_) + search(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int error; uint64_t sum; @@ -284,19 +235,25 @@ namespace eppfrd } int -Policy::Func::eppfrd(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::EPPFRD::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::eppfrd::action(branches_,fusepath_,paths_); +} + +int +Policy::EPPFRD::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::eppfrd::create(branches_,fusepath_,paths_); +} + +int +Policy::EPPFRD::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - switch(type_) - { - case Category::CREATE: - return eppfrd::create(branches_,fusepath_,paths_); - case Category::ACTION: - return eppfrd::action(branches_,fusepath_,paths_); - default: - case Category::SEARCH: - return eppfrd::search(branches_,fusepath_,paths_); - } + return ::eppfrd::search(branches_,fusepath_,paths_); } diff --git a/src/policy_eppfrd.hpp b/src/policy_eppfrd.hpp new file mode 100644 index 00000000..f3b6cbc3 --- /dev/null +++ b/src/policy_eppfrd.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace EPPFRD + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("eppfrd") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("eppfrd") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving(void) const final { return true; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("eppfrd") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_eprand.cpp b/src/policy_eprand.cpp index 65dd9ffa..248249c8 100644 --- a/src/policy_eprand.cpp +++ b/src/policy_eprand.cpp @@ -15,24 +15,54 @@ */ #include "errno.hpp" +#include "policies.hpp" #include "policy.hpp" +#include "policy_eprand.hpp" #include -#include -#include -using std::string; -using std::vector; +int +Policy::EPRand::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + int rv; + + rv = Policies::Action::epall(branches_,fusepath_,paths_); + if(rv == 0) + { + std::random_shuffle(paths_->begin(),paths_->end()); + paths_->resize(1); + } + + return rv; +} + +int +Policy::EPRand::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + int rv; + + rv = Policies::Create::epall(branches_,fusepath_,paths_); + if(rv == 0) + { + std::random_shuffle(paths_->begin(),paths_->end()); + paths_->resize(1); + } + + return rv; +} int -Policy::Func::eprand(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::EPRand::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { int rv; - rv = Policy::Func::epall(type_,branches_,fusepath_,paths_); + rv = Policies::Search::epall(branches_,fusepath_,paths_); if(rv == 0) { std::random_shuffle(paths_->begin(),paths_->end()); diff --git a/src/policy_eprand.hpp b/src/policy_eprand.hpp new file mode 100644 index 00000000..f0a62b4f --- /dev/null +++ b/src/policy_eprand.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace EPRand + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("eprand") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("eprand") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving(void) const final { return true; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("eprand") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_erofs.cpp b/src/policy_erofs.cpp index c7ee6682..27376be3 100644 --- a/src/policy_erofs.cpp +++ b/src/policy_erofs.cpp @@ -16,18 +16,33 @@ #include "errno.hpp" #include "policy.hpp" +#include "policy_erofs.hpp" #include -#include using std::string; -using std::vector; + + +int +Policy::ERoFS::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return (errno=EROFS,-1); +} + +int +Policy::ERoFS::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return (errno=EROFS,-1); +} int -Policy::Func::erofs(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths) +Policy::ERoFS::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { return (errno=EROFS,-1); } diff --git a/src/policy_erofs.hpp b/src/policy_erofs.hpp new file mode 100644 index 00000000..f17f4053 --- /dev/null +++ b/src/policy_erofs.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace ERoFS + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("erofs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("erofs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving(void) const final { return false; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("erofs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_ff.cpp b/src/policy_ff.cpp index 72a8f1e2..4cf00b32 100644 --- a/src/policy_ff.cpp +++ b/src/policy_ff.cpp @@ -18,70 +18,68 @@ #include "fs_exists.hpp" #include "fs_info.hpp" #include "fs_path.hpp" +#include "policies.hpp" #include "policy.hpp" #include "policy_error.hpp" -#include "rwlock.hpp" +#include "policy_ff.hpp" #include -#include using std::string; -using std::vector; namespace ff { static int - create(const BranchVec &branches_, - vector *paths_) + create(const Branches::CPtr &branches_, + StrVec *paths_) { int rv; int error; fs::info_t info; - const Branch *branch; error = ENOENT; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(error,EROFS); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) error_and_continue(error,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(error,ENOSPC); - paths_->push_back(branch->path); + paths_->push_back(branch.path); return 0; } return (errno=error,-1); } +} - static - int - create(const Branches &branches_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return ff::create(branches_.vec,paths_); - } +int +Policy::FF::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Action::epff(branches_,fusepath_,paths_); } int -Policy::Func::ff(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::FF::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - if(type_ == Category::CREATE) - return ff::create(branches_,paths_); + return ::ff::create(branches_,paths_); +} - return Policy::Func::epff(type_,branches_,fusepath_,paths_); +int +Policy::FF::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Search::epff(branches_,fusepath_,paths_); } diff --git a/src/policy_ff.hpp b/src/policy_ff.hpp new file mode 100644 index 00000000..1b0db87f --- /dev/null +++ b/src/policy_ff.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace FF + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("ff") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("ff") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving(void) const final { return false; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("ff") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_lfs.cpp b/src/policy_lfs.cpp index 05000c18..ace2a1bf 100644 --- a/src/policy_lfs.cpp +++ b/src/policy_lfs.cpp @@ -18,23 +18,23 @@ #include "fs_exists.hpp" #include "fs_info.hpp" #include "fs_path.hpp" +#include "policies.hpp" #include "policy.hpp" #include "policy_error.hpp" -#include "rwlock.hpp" +#include "policy_lfs.hpp" +#include "strvec.hpp" #include #include -#include using std::string; -using std::vector; namespace lfs { static int - create(const BranchVec &branches_, - vector *paths_) + create(const Branches::CPtr &branches_, + StrVec *paths_) { int rv; int error; @@ -46,24 +46,22 @@ namespace lfs error = ENOENT; lfs = std::numeric_limits::max(); basepath = NULL; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(const auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(error,EROFS); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) error_and_continue(error,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(error,ENOSPC); if(info.spaceavail > lfs) continue; lfs = info.spaceavail; - basepath = &branch->path; + basepath = &branch.path; } if(basepath == NULL) @@ -73,26 +71,28 @@ namespace lfs return 0; } +} - static - int - create(const Branches &branches_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return lfs::create(branches_.vec,paths_); - } +int +Policy::LFS::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Action::eplfs(branches_,fusepath_,paths_); } int -Policy::Func::lfs(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::LFS::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - if(type_ == Category::CREATE) - return lfs::create(branches_,paths_); + return ::lfs::create(branches_,paths_); +} - return Policy::Func::eplfs(type_,branches_,fusepath_,paths_); +int +Policy::LFS::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Search::eplfs(branches_,fusepath_,paths_); } diff --git a/src/policy_lfs.hpp b/src/policy_lfs.hpp new file mode 100644 index 00000000..e0b456ef --- /dev/null +++ b/src/policy_lfs.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace LFS + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("lfs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("lfs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving() const final { return false; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("lfs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_lus.cpp b/src/policy_lus.cpp index 3576afad..c23570aa 100644 --- a/src/policy_lus.cpp +++ b/src/policy_lus.cpp @@ -18,9 +18,11 @@ #include "fs_exists.hpp" #include "fs_info.hpp" #include "fs_path.hpp" +#include "policies.hpp" #include "policy.hpp" #include "policy_error.hpp" -#include "rwlock.hpp" +#include "policy_lus.hpp" +#include "strvec.hpp" #include #include @@ -33,37 +35,34 @@ namespace lus { static int - create(const BranchVec &branches_, - vector *paths_) + create(const Branches::CPtr &branches_, + StrVec *paths_) { int rv; int error; uint64_t lus; fs::info_t info; - const Branch *branch; const string *basepath; error = ENOENT; lus = std::numeric_limits::max(); basepath = NULL; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(error,EROFS); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) error_and_continue(error,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(error,ENOSPC); if(info.spaceused >= lus) continue; lus = info.spaceused; - basepath = &branch->path; + basepath = &branch.path; } if(basepath == NULL) @@ -73,26 +72,28 @@ namespace lus return 0; } +} - static - int - create(const Branches &branches_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return lus::create(branches_.vec,paths_); - } +int +Policy::LUS::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Action::eplus(branches_,fusepath_,paths_); } int -Policy::Func::lus(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::LUS::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - if(type_ == Category::CREATE) - return lus::create(branches_,paths_); + return ::lus::create(branches_,paths_); +} - return Policy::Func::eplus(type_,branches_,fusepath_,paths_); +int +Policy::LUS::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Search::eplus(branches_,fusepath_,paths_); } diff --git a/src/policy_lus.hpp b/src/policy_lus.hpp new file mode 100644 index 00000000..b6c07717 --- /dev/null +++ b/src/policy_lus.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace LUS + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("lus") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("lus") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving() const final { return false; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("lus") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_mfs.cpp b/src/policy_mfs.cpp index ed766d95..489e0cd9 100644 --- a/src/policy_mfs.cpp +++ b/src/policy_mfs.cpp @@ -18,51 +18,46 @@ #include "fs_exists.hpp" #include "fs_info.hpp" #include "fs_path.hpp" +#include "policies.hpp" #include "policy.hpp" #include "policy_error.hpp" -#include "rwlock.hpp" #include -#include using std::string; -using std::vector; namespace mfs { static int - create(const BranchVec &branches_, - vector *paths_) + create(const Branches::CPtr &branches_, + StrVec *paths_) { int rv; int error; uint64_t mfs; fs::info_t info; - const Branch *branch; const string *basepath; error = ENOENT; mfs = 0; basepath = NULL; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(const auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(error,EROFS); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) error_and_continue(error,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(error,ENOSPC); if(info.spaceavail < mfs) continue; mfs = info.spaceavail; - basepath = &branch->path; + basepath = &branch.path; } if(basepath == NULL) @@ -72,26 +67,28 @@ namespace mfs return 0; } +} - static - int - create(const Branches &branches_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return mfs::create(branches_.vec,paths_); - } +int +Policy::MFS::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Action::mfs(branches_,fusepath_,paths_); } int -Policy::Func::mfs(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::MFS::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - if(type_ == Category::CREATE) - return mfs::create(branches_,paths_); + return ::mfs::create(branches_,paths_); +} - return Policy::Func::epmfs(type_,branches_,fusepath_,paths_); +int +Policy::MFS::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Search::epmfs(branches_,fusepath_,paths_); } diff --git a/src/policy_mfs.hpp b/src/policy_mfs.hpp new file mode 100644 index 00000000..9247f77a --- /dev/null +++ b/src/policy_mfs.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace MFS + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("mfs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("mfs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving() const final { return false; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("mfs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_msplfs.cpp b/src/policy_msplfs.cpp index 3d6a6f61..27039a62 100644 --- a/src/policy_msplfs.cpp +++ b/src/policy_msplfs.cpp @@ -19,16 +19,16 @@ #include "fs_info.hpp" #include "fs_path.hpp" #include "fs_statvfs_cache.hpp" +#include "policies.hpp" #include "policy.hpp" #include "policy_error.hpp" -#include "rwlock.hpp" +#include "policy_msplfs.hpp" +#include "strvec.hpp" #include #include -#include using std::string; -using std::vector; namespace msplfs @@ -36,38 +36,35 @@ namespace msplfs static const string* - create_1(const BranchVec &branches_, - const string &fusepath_, - int *err_) + create_1(const Branches::CPtr &branches_, + const string &fusepath_, + int *err_) { int rv; uint64_t lfs; fs::info_t info; - const Branch *branch; const string *basepath; basepath = NULL; lfs = std::numeric_limits::max(); - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(const auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(*err_,EROFS); - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) error_and_continue(*err_,ENOENT); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(*err_,ENOENT); if(info.readonly) error_and_continue(*err_,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(*err_,ENOSPC); if(info.spaceavail > lfs) continue; lfs = info.spaceavail; - basepath = &branch->path; + basepath = &branch.path; } return basepath; @@ -75,9 +72,9 @@ namespace msplfs static int - create(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + create(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int error; string fusepath; @@ -102,27 +99,28 @@ namespace msplfs return 0; } +} - static - int - create(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return msplfs::create(branches_.vec,fusepath_,paths_); - } +int +Policy::MSPLFS::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Action::eplfs(branches_,fusepath_,paths_); } int -Policy::Func::msplfs(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::MSPLFS::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - if(type_ == Category::CREATE) - return msplfs::create(branches_,fusepath_,paths_); + return ::msplfs::create(branches_,fusepath_,paths_); +} - return Policy::Func::eplfs(type_,branches_,fusepath_,paths_); +int +Policy::MSPLFS::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Search::eplfs(branches_,fusepath_,paths_); } diff --git a/src/policy_msplfs.hpp b/src/policy_msplfs.hpp new file mode 100644 index 00000000..7e0a8d3e --- /dev/null +++ b/src/policy_msplfs.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace MSPLFS + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("msplfs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("msplfs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving() const final { return true; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("msplfs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_msplus.cpp b/src/policy_msplus.cpp index 28278fc2..e6e0cb87 100644 --- a/src/policy_msplus.cpp +++ b/src/policy_msplus.cpp @@ -19,55 +19,50 @@ #include "fs_info.hpp" #include "fs_path.hpp" #include "fs_statvfs_cache.hpp" +#include "policies.hpp" #include "policy.hpp" #include "policy_error.hpp" -#include "rwlock.hpp" +#include "policy_msplus.hpp" #include #include -#include using std::string; -using std::vector; - namespace msplus { static const string* - create_1(const BranchVec &branches_, - const string &fusepath_, - int *err_) + create_1(const Branches::CPtr &branches_, + const string &fusepath_, + int *err_) { int rv; uint64_t lus; fs::info_t info; - const Branch *branch; const string *basepath; basepath = NULL; lus = std::numeric_limits::max(); - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(*err_,EROFS); - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) error_and_continue(*err_,ENOENT); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(*err_,ENOENT); if(info.readonly) error_and_continue(*err_,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(*err_,ENOSPC); if(info.spaceused >= lus) continue; lus = info.spaceused;; - basepath = &branch->path; + basepath = &branch.path; } return basepath; @@ -75,9 +70,9 @@ namespace msplus static int - create(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + create(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int error; string fusepath; @@ -102,27 +97,28 @@ namespace msplus return 0; } +} - static - int - create(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return msplus::create(branches_.vec,fusepath_,paths_); - } +int +Policy::MSPLUS::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Action::eplus(branches_,fusepath_,paths_); } int -Policy::Func::msplus(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::MSPLUS::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - if(type_ == Category::CREATE) - return msplus::create(branches_,fusepath_,paths_); + return ::msplus::create(branches_,fusepath_,paths_); +} - return Policy::Func::eplus(type_,branches_,fusepath_,paths_); +int +Policy::MSPLUS::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Search::eplus(branches_,fusepath_,paths_); } diff --git a/src/policy_msplus.hpp b/src/policy_msplus.hpp new file mode 100644 index 00000000..5ccf06eb --- /dev/null +++ b/src/policy_msplus.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace MSPLUS + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("msplus") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("msplus") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving() const final { return true; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("msplus") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_mspmfs.cpp b/src/policy_mspmfs.cpp index edc8e9b6..ec00f496 100644 --- a/src/policy_mspmfs.cpp +++ b/src/policy_mspmfs.cpp @@ -19,9 +19,10 @@ #include "fs_info.hpp" #include "fs_path.hpp" #include "fs_statvfs_cache.hpp" +#include "policies.hpp" #include "policy.hpp" #include "policy_error.hpp" -#include "rwlock.hpp" +#include "policy_mspmfs.hpp" #include #include @@ -36,38 +37,35 @@ namespace mspmfs static const string* - create_1(const BranchVec &branches_, - const string &fusepath_, - int *err_) + create_1(const Branches::CPtr &branches_, + const string &fusepath_, + int *err_) { int rv; uint64_t mfs; fs::info_t info; - const Branch *branch; const string *basepath; basepath = NULL; mfs = std::numeric_limits::min(); - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(const auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(*err_,EROFS); - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) error_and_continue(*err_,ENOENT); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(*err_,ENOENT); if(info.readonly) error_and_continue(*err_,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(*err_,ENOSPC); if(info.spaceavail < mfs) continue; mfs = info.spaceavail; - basepath = &branch->path; + basepath = &branch.path; } return basepath; @@ -75,9 +73,9 @@ namespace mspmfs static int - create(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + create(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int error; string fusepath; @@ -102,27 +100,28 @@ namespace mspmfs return 0; } +} - static - int - create(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return mspmfs::create(branches_.vec,fusepath_,paths_); - } +int +Policy::MSPMFS::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Action::epmfs(branches_,fusepath_,paths_); } int -Policy::Func::mspmfs(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::MSPMFS::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - if(type_ == Category::CREATE) - return mspmfs::create(branches_,fusepath_,paths_); + return ::mspmfs::create(branches_,fusepath_,paths_); +} - return Policy::Func::epmfs(type_,branches_,fusepath_,paths_); +int +Policy::MSPMFS::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Search::epmfs(branches_,fusepath_,paths_); } diff --git a/src/policy_mspmfs.hpp b/src/policy_mspmfs.hpp new file mode 100644 index 00000000..3123e952 --- /dev/null +++ b/src/policy_mspmfs.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace MSPMFS + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("mspmfs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("mspmfs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving() const final { return true; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("mspmfs") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_msppfrd.cpp b/src/policy_msppfrd.cpp index dd4f8931..baa1bd95 100644 --- a/src/policy_msppfrd.cpp +++ b/src/policy_msppfrd.cpp @@ -22,9 +22,10 @@ #include "fs_path.hpp" #include "fs_statvfs_cache.hpp" #include "policy.hpp" +#include "policy_msppfrd.hpp" +#include "policies.hpp" #include "policy_error.hpp" #include "rnd.hpp" -#include "rwlock.hpp" #include #include @@ -44,39 +45,36 @@ namespace msppfrd { static int - create_1(const BranchVec &branches_, - const string &fusepath_, - BranchInfoVec *branchinfo_, - uint64_t *sum_) + create_1(const Branches::CPtr &branches_, + const string &fusepath_, + BranchInfoVec *branchinfo_, + uint64_t *sum_) { int rv; int error; BranchInfo bi; fs::info_t info; - const Branch *branch; *sum_ = 0; error = ENOENT; - for(size_t i = 0, ei = branches_.size(); i < ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(error,EROFS); - if(!fs::exists(branch->path,fusepath_)) + if(!fs::exists(branch.path,fusepath_)) error_and_continue(error,ENOENT); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) error_and_continue(error,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(error,ENOSPC); *sum_ += info.spaceavail; bi.spaceavail = info.spaceavail; - bi.basepath = &branch->path; + bi.basepath = &branch.path; branchinfo_->push_back(bi); } @@ -85,24 +83,10 @@ namespace msppfrd static int - create_1(const Branches &branches_, - const string &fusepath_, - BranchInfoVec *branchinfo_, - uint64_t *sum_) - { - rwlock::ReadGuard guard(branches_.lock); - - branchinfo_->reserve(branches_.vec.size()); - - return msppfrd::create_1(branches_.vec,fusepath_,branchinfo_,sum_); - } - - static - int - get_branchinfo(const Branches &branches_, - const char *fusepath_, - BranchInfoVec *branchinfo_, - uint64_t *sum_) + get_branchinfo(const Branches::CPtr &branches_, + const char *fusepath_, + BranchInfoVec *branchinfo_, + uint64_t *sum_) { int error; string fusepath; @@ -147,9 +131,9 @@ namespace msppfrd static int - create(const Branches &branches_, - const char *fusepath_, - vector *paths_) + create(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int error; uint64_t sum; @@ -168,13 +152,25 @@ namespace msppfrd } int -Policy::Func::msppfrd(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::MSPPFRD::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - if(type_ == Category::CREATE) - return msppfrd::create(branches_,fusepath_,paths_); + return Policies::Action::eppfrd(branches_,fusepath_,paths_); +} - return Policy::Func::eppfrd(type_,branches_,fusepath_,paths_); +int +Policy::MSPPFRD::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::msppfrd::create(branches_,fusepath_,paths_); +} + +int +Policy::MSPPFRD::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Search::eppfrd(branches_,fusepath_,paths_); } diff --git a/src/policy_msppfrd.hpp b/src/policy_msppfrd.hpp new file mode 100644 index 00000000..d357d033 --- /dev/null +++ b/src/policy_msppfrd.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace MSPPFRD + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("msppfrd") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("msppfrd") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving() const final { return true; }; + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("msppfrd") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_newest.cpp b/src/policy_newest.cpp index 520cc1c9..f65e0f66 100644 --- a/src/policy_newest.cpp +++ b/src/policy_newest.cpp @@ -21,56 +21,52 @@ #include "fs_statvfs_cache.hpp" #include "policy.hpp" #include "policy_error.hpp" +#include "policy_newest.hpp" #include "rwlock.hpp" #include -#include #include #include using std::string; -using std::vector; namespace newest { static int - create(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + create(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int rv; int error; time_t newest; struct stat st; fs::info_t info; - const Branch *branch; const string *basepath; error = ENOENT; newest = std::numeric_limits::min(); basepath = NULL; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(error,EROFS); - if(!fs::exists(branch->path,fusepath_,&st)) + if(!fs::exists(branch.path,fusepath_,&st)) error_and_continue(error,ENOENT); if(st.st_mtime < newest) continue; - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) error_and_continue(error,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(error,ENOSPC); newest = st.st_mtime; - basepath = &branch->path; + basepath = &branch.path; } if(basepath == NULL) @@ -83,50 +79,36 @@ namespace newest static int - create(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return newest::create(branches_.vec,fusepath_,paths_); - } - - static - int - action(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + action(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int rv; int error; bool readonly; time_t newest; struct stat st; - const Branch *branch; const string *basepath; error = ENOENT; newest = std::numeric_limits::min(); basepath = NULL; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro()) + if(branch.ro()) error_and_continue(error,EROFS); - if(!fs::exists(branch->path,fusepath_,&st)) + if(!fs::exists(branch.path,fusepath_,&st)) error_and_continue(error,ENOENT); if(st.st_mtime < newest) continue; - rv = fs::statvfs_cache_readonly(branch->path,&readonly); + rv = fs::statvfs_cache_readonly(branch.path,&readonly); if(rv == -1) error_and_continue(error,ENOENT); if(readonly) error_and_continue(error,EROFS); newest = st.st_mtime; - basepath = &branch->path; + basepath = &branch.path; } if(basepath == NULL) @@ -139,39 +121,25 @@ namespace newest static int - action(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); - - return newest::action(branches_.vec,fusepath_,paths_); - } - - static - int - search(const BranchVec &branches_, - const char *fusepath_, - vector *paths_) + search(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { time_t newest; struct stat st; - const Branch *branch; const string *basepath; newest = std::numeric_limits::min(); basepath = NULL; - for(size_t i = 0, ei = branches_.size(); i != ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(!fs::exists(branch->path,fusepath_,&st)) + if(!fs::exists(branch.path,fusepath_,&st)) continue; if(st.st_mtime < newest) continue; newest = st.st_mtime; - basepath = &branch->path; + basepath = &branch.path; } if(basepath == NULL) @@ -181,33 +149,28 @@ namespace newest return 0; } +} - static - int - search(const Branches &branches_, - const char *fusepath_, - vector *paths_) - { - rwlock::ReadGuard guard(branches_.lock); +int +Policy::Newest::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::newest::action(branches_,fusepath_,paths_); +} - return newest::search(branches_.vec,fusepath_,paths_); - } +int +Policy::Newest::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::newest::create(branches_,fusepath_,paths_); } int -Policy::Func::newest(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::Newest::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - switch(type_) - { - case Category::CREATE: - return newest::create(branches_,fusepath_,paths_); - case Category::ACTION: - return newest::action(branches_,fusepath_,paths_); - case Category::SEARCH: - default: - return newest::search(branches_,fusepath_,paths_); - } + return ::newest::search(branches_,fusepath_,paths_); } diff --git a/src/policy_newest.hpp b/src/policy_newest.hpp new file mode 100644 index 00000000..c4baf298 --- /dev/null +++ b/src/policy_newest.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace Newest + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("newest") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("newest") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving() const final { return false; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("newest") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_pfrd.cpp b/src/policy_pfrd.cpp index ab22e278..2862d3ca 100644 --- a/src/policy_pfrd.cpp +++ b/src/policy_pfrd.cpp @@ -17,10 +17,12 @@ #include "errno.hpp" #include "fs_info.hpp" #include "fs_path.hpp" +#include "policies.hpp" #include "policy.hpp" #include "policy_error.hpp" +#include "policy_pfrd.hpp" #include "rnd.hpp" -#include "rwlock.hpp" +#include "strvec.hpp" #include #include @@ -40,55 +42,39 @@ namespace pfrd { static int - get_branchinfo(const BranchVec &branches_, - BranchInfoVec *branchinfo_, - uint64_t *sum_) + get_branchinfo(const Branches::CPtr &branches_, + BranchInfoVec *branchinfo_, + uint64_t *sum_) { int rv; int error; BranchInfo bi; fs::info_t info; - const Branch *branch; *sum_ = 0; error = ENOENT; - for(size_t i = 0, ei = branches_.size(); i < ei; i++) + for(auto &branch : *branches_) { - branch = &branches_[i]; - - if(branch->ro_or_nc()) + if(branch.ro_or_nc()) error_and_continue(error,EROFS); - rv = fs::info(branch->path,&info); + rv = fs::info(branch.path,&info); if(rv == -1) error_and_continue(error,ENOENT); if(info.readonly) error_and_continue(error,EROFS); - if(info.spaceavail < branch->minfreespace()) + if(info.spaceavail < branch.minfreespace()) error_and_continue(error,ENOSPC); *sum_ += info.spaceavail; bi.spaceavail = info.spaceavail; - bi.basepath = &branch->path; + bi.basepath = &branch.path; branchinfo_->push_back(bi); } return error; } - static - int - get_branchinfo(const Branches &branches_, - BranchInfoVec *branchinfo_, - uint64_t *sum_) - { - rwlock::ReadGuard guard(branches_.lock); - - branchinfo_->reserve(branches_.vec.size()); - - return pfrd::get_branchinfo(branches_.vec,branchinfo_,sum_); - } - static const string* @@ -115,9 +101,9 @@ namespace pfrd static int - create(const Branches &branches_, - const char *fusepath_, - vector *paths_) + create(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) { int error; uint64_t sum; @@ -136,13 +122,25 @@ namespace pfrd } int -Policy::Func::pfrd(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::PFRD::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { - if(type_ == Category::CREATE) - return pfrd::create(branches_,fusepath_,paths_); + return Policies::Action::eppfrd(branches_,fusepath_,paths_); +} - return Policy::Func::eppfrd(type_,branches_,fusepath_,paths_); +int +Policy::PFRD::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return ::pfrd::create(branches_,fusepath_,paths_); +} + +int +Policy::PFRD::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + return Policies::Search::eppfrd(branches_,fusepath_,paths_); } diff --git a/src/policy_pfrd.hpp b/src/policy_pfrd.hpp new file mode 100644 index 00000000..86b3c11c --- /dev/null +++ b/src/policy_pfrd.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace PFRD + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("pfrd") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("pfrd") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving() const final { return false; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("pfrd") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/policy_rand.cpp b/src/policy_rand.cpp index 160d39e5..9a74f017 100644 --- a/src/policy_rand.cpp +++ b/src/policy_rand.cpp @@ -16,23 +16,53 @@ #include "errno.hpp" #include "policy.hpp" +#include "policy_rand.hpp" +#include "policies.hpp" #include -#include -#include -using std::string; -using std::vector; +int +Policy::Rand::Action::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + int rv; + + rv = Policies::Action::all(branches_,fusepath_,paths_); + if(rv == 0) + { + std::random_shuffle(paths_->begin(),paths_->end()); + paths_->resize(1); + } + + return rv; +} + +int +Policy::Rand::Create::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const +{ + int rv; + + rv = Policies::Create::all(branches_,fusepath_,paths_); + if(rv == 0) + { + std::random_shuffle(paths_->begin(),paths_->end()); + paths_->resize(1); + } + + return rv; +} int -Policy::Func::rand(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) +Policy::Rand::Search::operator()(const Branches::CPtr &branches_, + const char *fusepath_, + StrVec *paths_) const { int rv; - rv = Policy::Func::all(type_,branches_,fusepath_,paths_); + rv = Policies::Search::all(branches_,fusepath_,paths_); if(rv == 0) { std::random_shuffle(paths_->begin(),paths_->end()); diff --git a/src/policy_rand.hpp b/src/policy_rand.hpp new file mode 100644 index 00000000..7d435433 --- /dev/null +++ b/src/policy_rand.hpp @@ -0,0 +1,61 @@ +/* + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci + + 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 "policy.hpp" + +namespace Policy +{ + namespace Rand + { + class Action final : public Policy::ActionImpl + { + public: + Action() + : Policy::ActionImpl("rand") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + + class Create final : public Policy::CreateImpl + { + public: + Create() + : Policy::CreateImpl("rand") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + bool path_preserving() const final { return false; } + }; + + class Search final : public Policy::SearchImpl + { + public: + Search() + : Policy::SearchImpl("rand") + {} + + public: + int operator()(const Branches::CPtr&,const char*,StrVec*) const final; + }; + } +} diff --git a/src/rnd.cpp b/src/rnd.cpp index 5eab6ce1..c30f3a74 100644 --- a/src/rnd.cpp +++ b/src/rnd.cpp @@ -20,9 +20,11 @@ #include "wyhash.h" -#include +#include + #include + static uint64_t G_SEED; static RND G_RND; diff --git a/src/rnd.hpp b/src/rnd.hpp index dd9b6648..e9b300d0 100644 --- a/src/rnd.hpp +++ b/src/rnd.hpp @@ -18,7 +18,8 @@ #pragma once -#include +#include + class RND { diff --git a/src/statvfs_util.hpp b/src/statvfs_util.hpp index 0447d181..a1e83dd1 100644 --- a/src/statvfs_util.hpp +++ b/src/statvfs_util.hpp @@ -16,11 +16,12 @@ #pragma once +#include #include -#include #include + namespace StatVFS { static diff --git a/src/str.cpp b/src/str.cpp index de07ff2c..66d05183 100644 --- a/src/str.cpp +++ b/src/str.cpp @@ -14,15 +14,17 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include +#include #include #include -#include #include +using std::istringstream; +using std::set; using std::string; using std::vector; -using std::istringstream; namespace str { @@ -105,6 +107,25 @@ namespace str return str::join(vec_,0,sep_); } + string + join(const set &set_, + const char sep_) + { + string rv; + set::iterator i; + + if(set_.empty()) + return string(); + + i = set_.begin(); + rv += *i; + ++i; + for(; i != set_.end(); ++i) + rv += sep_ + *i; + + return rv; + } + size_t longest_common_prefix_index(const vector &vec_) { diff --git a/src/str.hpp b/src/str.hpp index c9a6f268..34f19e8c 100644 --- a/src/str.hpp +++ b/src/str.hpp @@ -16,6 +16,7 @@ #pragma once +#include #include #include @@ -50,6 +51,10 @@ namespace str join(const std::vector &vec, const char sep); + std::string + join(const std::set &s, + const char sep); + size_t longest_common_prefix_index(const std::vector &vec); diff --git a/src/policy_invalid.cpp b/src/strvec.hpp similarity index 67% rename from src/policy_invalid.cpp rename to src/strvec.hpp index caedc24f..593263df 100644 --- a/src/policy_invalid.cpp +++ b/src/strvec.hpp @@ -1,5 +1,7 @@ /* - Copyright (c) 2016, Antonio SJ Musumeci + ISC License + + Copyright (c) 2020, Antonio SJ Musumeci Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above @@ -14,20 +16,9 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "errno.hpp" -#include "policy.hpp" +#pragma once #include #include -using std::string; -using std::vector; - -int -Policy::Func::invalid(const Category type_, - const Branches &branches_, - const char *fusepath_, - vector *paths_) -{ - return (errno=EINVAL,-1); -} +typedef std::vector StrVec; diff --git a/src/to_string.cpp b/src/to_string.cpp index 3019b682..0d5cddd7 100644 --- a/src/to_string.cpp +++ b/src/to_string.cpp @@ -16,10 +16,10 @@ OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ +#include #include #include -#include #include namespace str diff --git a/src/to_string.hpp b/src/to_string.hpp index 5e4f04e7..846147a4 100644 --- a/src/to_string.hpp +++ b/src/to_string.hpp @@ -18,9 +18,9 @@ #pragma once +#include #include -#include namespace str { diff --git a/src/tofrom_wrapper.hpp b/src/tofrom_wrapper.hpp index 9be0d3fe..ebcc605f 100644 --- a/src/tofrom_wrapper.hpp +++ b/src/tofrom_wrapper.hpp @@ -29,13 +29,13 @@ class ToFromWrapper : public ToFromString { public: int - from_string(const std::string &s_) + from_string(const std::string &s_) final { return str::from(s_,&_data); } std::string - to_string(void) const + to_string(void) const final { return str::to(_data); } @@ -70,6 +70,13 @@ public: return &_data; } + const + T* + operator->() const + { + return &_data; + } + public: bool operator==(const T &data_) const @@ -86,13 +93,13 @@ class ROToFromWrapper : public ToFromString { public: int - from_string(const std::string &s_) + from_string(const std::string &s_) final { return -EINVAL; } std::string - to_string(void) const + to_string(void) const final { return str::to(_data); } diff --git a/tests/acutest.h b/tests/acutest.h new file mode 100644 index 00000000..8b49afc8 --- /dev/null +++ b/tests/acutest.h @@ -0,0 +1,1794 @@ +/* + * Acutest -- Another C/C++ Unit Test facility + * + * + * Copyright 2013-2020 Martin Mitas + * Copyright 2019 Garrett D'Amore + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS + * IN THE SOFTWARE. + */ + +#ifndef ACUTEST_H +#define ACUTEST_H + + +/************************ + *** Public interface *** + ************************/ + +/* By default, "acutest.h" provides the main program entry point (function + * main()). However, if the test suite is composed of multiple source files + * which include "acutest.h", then this causes a problem of multiple main() + * definitions. To avoid this problem, #define macro TEST_NO_MAIN in all + * compilation units but one. + */ + +/* Macro to specify list of unit tests in the suite. + * The unit test implementation MUST provide list of unit tests it implements + * with this macro: + * + * TEST_LIST = { + * { "test1_name", test1_func_ptr }, + * { "test2_name", test2_func_ptr }, + * ... + * { NULL, NULL } // zeroed record marking the end of the list + * }; + * + * The list specifies names of each test (must be unique) and pointer to + * a function implementing it. The function does not take any arguments + * and has no return values, i.e. every test function has to be compatible + * with this prototype: + * + * void test_func(void); + * + * Note the list has to be ended with a zeroed record. + */ +#define TEST_LIST const struct test_ test_list_[] + + +/* Macros for testing whether an unit test succeeds or fails. These macros + * can be used arbitrarily in functions implementing the unit tests. + * + * If any condition fails throughout execution of a test, the test fails. + * + * TEST_CHECK takes only one argument (the condition), TEST_CHECK_ allows + * also to specify an error message to print out if the condition fails. + * (It expects printf-like format string and its parameters). The macros + * return non-zero (condition passes) or 0 (condition fails). + * + * That can be useful when more conditions should be checked only if some + * preceding condition passes, as illustrated in this code snippet: + * + * SomeStruct* ptr = allocate_some_struct(); + * if(TEST_CHECK(ptr != NULL)) { + * TEST_CHECK(ptr->member1 < 100); + * TEST_CHECK(ptr->member2 > 200); + * } + */ +#define TEST_CHECK_(cond,...) test_check_((cond), __FILE__, __LINE__, __VA_ARGS__) +#define TEST_CHECK(cond) test_check_((cond), __FILE__, __LINE__, "%s", #cond) + + +/* These macros are the same as TEST_CHECK_ and TEST_CHECK except that if the + * condition fails, the currently executed unit test is immediately aborted. + * + * That is done either by calling abort() if the unit test is executed as a + * child process; or via longjmp() if the unit test is executed within the + * main Acutest process. + * + * As a side effect of such abortion, your unit tests may cause memory leaks, + * unflushed file descriptors, and other phenomena caused by the abortion. + * + * Therefore you should not use these as a general replacement for TEST_CHECK. + * Use it with some caution, especially if your test causes some other side + * effects to the outside world (e.g. communicating with some server, inserting + * into a database etc.). + */ +#define TEST_ASSERT_(cond,...) \ + do { \ + if(!test_check_((cond), __FILE__, __LINE__, __VA_ARGS__)) \ + test_abort_(); \ + } while(0) +#define TEST_ASSERT(cond) \ + do { \ + if(!test_check_((cond), __FILE__, __LINE__, "%s", #cond)) \ + test_abort_(); \ + } while(0) + + +#ifdef __cplusplus +/* Macros to verify that the code (the 1st argument) throws exception of given + * type (the 2nd argument). (Note these macros are only available in C++.) + * + * TEST_EXCEPTION_ is like TEST_EXCEPTION but accepts custom printf-like + * message. + * + * For example: + * + * TEST_EXCEPTION(function_that_throw(), ExpectedExceptionType); + * + * If the function_that_throw() throws ExpectedExceptionType, the check passes. + * If the function throws anything incompatible with ExpectedExceptionType + * (or if it does not thrown an exception at all), the check fails. + */ +#define TEST_EXCEPTION(code, exctype) \ + do { \ + bool exc_ok_ = false; \ + const char *msg_ = NULL; \ + try { \ + code; \ + msg_ = "No exception thrown."; \ + } catch(exctype const&) { \ + exc_ok_= true; \ + } catch(...) { \ + msg_ = "Unexpected exception thrown."; \ + } \ + test_check_(exc_ok_, __FILE__, __LINE__, #code " throws " #exctype); \ + if(msg_ != NULL) \ + test_message_("%s", msg_); \ + } while(0) +#define TEST_EXCEPTION_(code, exctype, ...) \ + do { \ + bool exc_ok_ = false; \ + const char *msg_ = NULL; \ + try { \ + code; \ + msg_ = "No exception thrown."; \ + } catch(exctype const&) { \ + exc_ok_= true; \ + } catch(...) { \ + msg_ = "Unexpected exception thrown."; \ + } \ + test_check_(exc_ok_, __FILE__, __LINE__, __VA_ARGS__); \ + if(msg_ != NULL) \ + test_message_("%s", msg_); \ + } while(0) +#endif /* #ifdef __cplusplus */ + + +/* Sometimes it is useful to split execution of more complex unit tests to some + * smaller parts and associate those parts with some names. + * + * This is especially handy if the given unit test is implemented as a loop + * over some vector of multiple testing inputs. Using these macros allow to use + * sort of subtitle for each iteration of the loop (e.g. outputting the input + * itself or a name associated to it), so that if any TEST_CHECK condition + * fails in the loop, it can be easily seen which iteration triggers the + * failure, without the need to manually output the iteration-specific data in + * every single TEST_CHECK inside the loop body. + * + * TEST_CASE allows to specify only single string as the name of the case, + * TEST_CASE_ provides all the power of printf-like string formatting. + * + * Note that the test cases cannot be nested. Starting a new test case ends + * implicitly the previous one. To end the test case explicitly (e.g. to end + * the last test case after exiting the loop), you may use TEST_CASE(NULL). + */ +#define TEST_CASE_(...) test_case_(__VA_ARGS__) +#define TEST_CASE(name) test_case_("%s", name) + + +/* Maximal output per TEST_CASE call. Longer messages are cut. + * You may define another limit prior including "acutest.h" + */ +#ifndef TEST_CASE_MAXSIZE + #define TEST_CASE_MAXSIZE 64 +#endif + + +/* printf-like macro for outputting an extra information about a failure. + * + * Intended use is to output some computed output versus the expected value, + * e.g. like this: + * + * if(!TEST_CHECK(produced == expected)) { + * TEST_MSG("Expected: %d", expected); + * TEST_MSG("Produced: %d", produced); + * } + * + * Note the message is only written down if the most recent use of any checking + * macro (like e.g. TEST_CHECK or TEST_EXCEPTION) in the current test failed. + * This means the above is equivalent to just this: + * + * TEST_CHECK(produced == expected); + * TEST_MSG("Expected: %d", expected); + * TEST_MSG("Produced: %d", produced); + * + * The macro can deal with multi-line output fairly well. It also automatically + * adds a final new-line if there is none present. + */ +#define TEST_MSG(...) test_message_(__VA_ARGS__) + + +/* Maximal output per TEST_MSG call. Longer messages are cut. + * You may define another limit prior including "acutest.h" + */ +#ifndef TEST_MSG_MAXSIZE + #define TEST_MSG_MAXSIZE 1024 +#endif + + +/* Macro for dumping a block of memory. + * + * Its intended use is very similar to what TEST_MSG is for, but instead of + * generating any printf-like message, this is for dumping raw block of a + * memory in a hexadecimal form: + * + * TEST_CHECK(size_produced == size_expected && + * memcmp(addr_produced, addr_expected, size_produced) == 0); + * TEST_DUMP("Expected:", addr_expected, size_expected); + * TEST_DUMP("Produced:", addr_produced, size_produced); + */ +#define TEST_DUMP(title, addr, size) test_dump_(title, addr, size) + +/* Maximal output per TEST_DUMP call (in bytes to dump). Longer blocks are cut. + * You may define another limit prior including "acutest.h" + */ +#ifndef TEST_DUMP_MAXSIZE + #define TEST_DUMP_MAXSIZE 1024 +#endif + + +/* Common test initialiation/clean-up + * + * In some test suites, it may be needed to perform some sort of the same + * initialization and/or clean-up in all the tests. + * + * Such test suites may use macros TEST_INIT and/or TEST_FINI prior including + * this header. The expansion of the macro is then used as a body of helper + * function called just before executing every single (TEST_INIT) or just after + * it ends (TEST_FINI). + * + * Examples of various ways how to use the macro TEST_INIT: + * + * #define TEST_INIT my_init_func(); + * #define TEST_INIT my_init_func() // Works even without the semicolon + * #define TEST_INIT setlocale(LC_ALL, NULL); + * #define TEST_INIT { setlocale(LC_ALL, NULL); my_init_func(); } + * + * TEST_FINI is to be used in the same way. + */ + + +/********************** + *** Implementation *** + **********************/ + +/* The unit test files should not rely on anything below. */ + +#include +#include +#include +#include +#include +#include + +#if defined(unix) || defined(__unix__) || defined(__unix) || defined(__APPLE__) + #define ACUTEST_UNIX_ 1 + #include + #include + #include + #include + #include + #include + #include + + #if defined CLOCK_PROCESS_CPUTIME_ID && defined CLOCK_MONOTONIC + #define ACUTEST_HAS_POSIX_TIMER_ 1 + #endif +#endif + +#if defined(_gnu_linux_) || defined(__linux__) + #define ACUTEST_LINUX_ 1 + #include + #include +#endif + +#if defined(_WIN32) || defined(__WIN32__) || defined(__WINDOWS__) + #define ACUTEST_WIN_ 1 + #include + #include +#endif + +#ifdef __cplusplus + #include +#endif + +/* Load valgrind.h, if available. This allows to detect valgrind's presence via RUNNING_ON_VALGRIND. */ +#ifdef __has_include + #if __has_include() + #include + #endif +#endif + +/* Enable the use of the non-standard keyword __attribute__ to silence warnings under some compilers */ +#if defined(__GNUC__) || defined(__clang__) + #define TEST_ATTRIBUTE_(attr) __attribute__((attr)) +#else + #define TEST_ATTRIBUTE_(attr) +#endif + +/* Note our global private identifiers end with '_' to mitigate risk of clash + * with the unit tests implementation. */ + +#ifdef __cplusplus + extern "C" { +#endif + +#ifdef _MSC_VER + /* In the multi-platform code like ours, we cannot use the non-standard + * "safe" functions from Microsoft C lib like e.g. sprintf_s() instead of + * standard sprintf(). Hence, lets disable the warning C4996. */ + #pragma warning(push) + #pragma warning(disable: 4996) +#endif + + +struct test_ { + const char* name; + void (*func)(void); +}; + +struct test_detail_ { + unsigned char flags; + double duration; +}; + +enum { + TEST_FLAG_RUN_ = 1 << 0, + TEST_FLAG_SUCCESS_ = 1 << 1, + TEST_FLAG_FAILURE_ = 1 << 2, +}; + +extern const struct test_ test_list_[]; + +int test_check_(int cond, const char* file, int line, const char* fmt, ...); +void test_case_(const char* fmt, ...); +void test_message_(const char* fmt, ...); +void test_dump_(const char* title, const void* addr, size_t size); +void test_abort_(void) TEST_ATTRIBUTE_(noreturn); + + +#ifndef TEST_NO_MAIN + +static char* test_argv0_ = NULL; +static size_t test_list_size_ = 0; +static struct test_detail_ *test_details_ = NULL; +static size_t test_count_ = 0; +static int test_no_exec_ = -1; +static int test_no_summary_ = 0; +static int test_tap_ = 0; +static int test_skip_mode_ = 0; +static int test_worker_ = 0; +static int test_worker_index_ = 0; +static int test_cond_failed_ = 0; +static int test_was_aborted_ = 0; +static FILE *test_xml_output_ = NULL; + +static int test_stat_failed_units_ = 0; +static int test_stat_run_units_ = 0; + +static const struct test_* test_current_unit_ = NULL; +static int test_current_index_ = 0; +static char test_case_name_[TEST_CASE_MAXSIZE] = ""; +static int test_current_already_logged_ = 0; +static int test_case_current_already_logged_ = 0; +static int test_verbose_level_ = 2; +static int test_current_failures_ = 0; +static int test_colorize_ = 0; +static int test_timer_ = 0; + +static int test_abort_has_jmp_buf_ = 0; +static jmp_buf test_abort_jmp_buf_; + + +static void +test_cleanup_(void) +{ + free((void*) test_details_); +} + +static void +test_exit_(int exit_code) +{ + test_cleanup_(); + exit(exit_code); +} + +#if defined ACUTEST_WIN_ + typedef LARGE_INTEGER test_timer_type_; + static LARGE_INTEGER test_timer_freq_; + static test_timer_type_ test_timer_start_; + static test_timer_type_ test_timer_end_; + + static void + test_timer_init_(void) + { + QueryPerformanceFrequency(&test_timer_freq_); + } + + static void + test_timer_get_time_(LARGE_INTEGER* ts) + { + QueryPerformanceCounter(ts); + } + + static double + test_timer_diff_(LARGE_INTEGER start, LARGE_INTEGER end) + { + double duration = (double)(end.QuadPart - start.QuadPart); + duration /= (double)test_timer_freq_.QuadPart; + return duration; + } + + static void + test_timer_print_diff_(void) + { + printf("%.6lf secs", test_timer_diff_(test_timer_start_, test_timer_end_)); + } +#elif defined ACUTEST_HAS_POSIX_TIMER_ + static clockid_t test_timer_id_; + typedef struct timespec test_timer_type_; + static test_timer_type_ test_timer_start_; + static test_timer_type_ test_timer_end_; + + static void + test_timer_init_(void) + { + if(test_timer_ == 1) + test_timer_id_ = CLOCK_MONOTONIC; + else if(test_timer_ == 2) + test_timer_id_ = CLOCK_PROCESS_CPUTIME_ID; + } + + static void + test_timer_get_time_(struct timespec* ts) + { + clock_gettime(test_timer_id_, ts); + } + + static double + test_timer_diff_(struct timespec start, struct timespec end) + { + double endns; + double startns; + + endns = end.tv_sec; + endns *= 1e9; + endns += end.tv_nsec; + + startns = start.tv_sec; + startns *= 1e9; + startns += start.tv_nsec; + + return ((endns - startns)/ 1e9); + } + + static void + test_timer_print_diff_(void) + { + printf("%.6lf secs", + test_timer_diff_(test_timer_start_, test_timer_end_)); + } +#else + typedef int test_timer_type_; + static test_timer_type_ test_timer_start_; + static test_timer_type_ test_timer_end_; + + void + test_timer_init_(void) + {} + + static void + test_timer_get_time_(int* ts) + { + (void) ts; + } + + static double + test_timer_diff_(int start, int end) + { + (void) start; + (void) end; + return 0.0; + } + + static void + test_timer_print_diff_(void) + {} +#endif + +#define TEST_COLOR_DEFAULT_ 0 +#define TEST_COLOR_GREEN_ 1 +#define TEST_COLOR_RED_ 2 +#define TEST_COLOR_DEFAULT_INTENSIVE_ 3 +#define TEST_COLOR_GREEN_INTENSIVE_ 4 +#define TEST_COLOR_RED_INTENSIVE_ 5 + +static int TEST_ATTRIBUTE_(format (printf, 2, 3)) +test_print_in_color_(int color, const char* fmt, ...) +{ + va_list args; + char buffer[256]; + int n; + + va_start(args, fmt); + vsnprintf(buffer, sizeof(buffer), fmt, args); + va_end(args); + buffer[sizeof(buffer)-1] = '\0'; + + if(!test_colorize_) { + return printf("%s", buffer); + } + +#if defined ACUTEST_UNIX_ + { + const char* col_str; + switch(color) { + case TEST_COLOR_GREEN_: col_str = "\033[0;32m"; break; + case TEST_COLOR_RED_: col_str = "\033[0;31m"; break; + case TEST_COLOR_GREEN_INTENSIVE_: col_str = "\033[1;32m"; break; + case TEST_COLOR_RED_INTENSIVE_: col_str = "\033[1;31m"; break; + case TEST_COLOR_DEFAULT_INTENSIVE_: col_str = "\033[1m"; break; + default: col_str = "\033[0m"; break; + } + printf("%s", col_str); + n = printf("%s", buffer); + printf("\033[0m"); + return n; + } +#elif defined ACUTEST_WIN_ + { + HANDLE h; + CONSOLE_SCREEN_BUFFER_INFO info; + WORD attr; + + h = GetStdHandle(STD_OUTPUT_HANDLE); + GetConsoleScreenBufferInfo(h, &info); + + switch(color) { + case TEST_COLOR_GREEN_: attr = FOREGROUND_GREEN; break; + case TEST_COLOR_RED_: attr = FOREGROUND_RED; break; + case TEST_COLOR_GREEN_INTENSIVE_: attr = FOREGROUND_GREEN | FOREGROUND_INTENSITY; break; + case TEST_COLOR_RED_INTENSIVE_: attr = FOREGROUND_RED | FOREGROUND_INTENSITY; break; + case TEST_COLOR_DEFAULT_INTENSIVE_: attr = FOREGROUND_BLUE | FOREGROUND_GREEN | FOREGROUND_RED | FOREGROUND_INTENSITY; break; + default: attr = 0; break; + } + if(attr != 0) + SetConsoleTextAttribute(h, attr); + n = printf("%s", buffer); + SetConsoleTextAttribute(h, info.wAttributes); + return n; + } +#else + n = printf("%s", buffer); + return n; +#endif +} + +static void +test_begin_test_line_(const struct test_* test) +{ + if(!test_tap_) { + if(test_verbose_level_ >= 3) { + test_print_in_color_(TEST_COLOR_DEFAULT_INTENSIVE_, "Test %s:\n", test->name); + test_current_already_logged_++; + } else if(test_verbose_level_ >= 1) { + int n; + char spaces[48]; + + n = test_print_in_color_(TEST_COLOR_DEFAULT_INTENSIVE_, "Test %s... ", test->name); + memset(spaces, ' ', sizeof(spaces)); + if(n < (int) sizeof(spaces)) + printf("%.*s", (int) sizeof(spaces) - n, spaces); + } else { + test_current_already_logged_ = 1; + } + } +} + +static void +test_finish_test_line_(int result) +{ + if(test_tap_) { + const char* str = (result == 0) ? "ok" : "not ok"; + + printf("%s %d - %s\n", str, test_current_index_ + 1, test_current_unit_->name); + + if(result == 0 && test_timer_) { + printf("# Duration: "); + test_timer_print_diff_(); + printf("\n"); + } + } else { + int color = (result == 0) ? TEST_COLOR_GREEN_INTENSIVE_ : TEST_COLOR_RED_INTENSIVE_; + const char* str = (result == 0) ? "OK" : "FAILED"; + printf("[ "); + test_print_in_color_(color, "%s", str); + printf(" ]"); + + if(result == 0 && test_timer_) { + printf(" "); + test_timer_print_diff_(); + } + + printf("\n"); + } +} + +static void +test_line_indent_(int level) +{ + static const char spaces[] = " "; + int n = level * 2; + + if(test_tap_ && n > 0) { + n--; + printf("#"); + } + + while(n > 16) { + printf("%s", spaces); + n -= 16; + } + printf("%.*s", n, spaces); +} + +int TEST_ATTRIBUTE_(format (printf, 4, 5)) +test_check_(int cond, const char* file, int line, const char* fmt, ...) +{ + const char *result_str; + int result_color; + int verbose_level; + + if(cond) { + result_str = "ok"; + result_color = TEST_COLOR_GREEN_; + verbose_level = 3; + } else { + if(!test_current_already_logged_ && test_current_unit_ != NULL) + test_finish_test_line_(-1); + + result_str = "failed"; + result_color = TEST_COLOR_RED_; + verbose_level = 2; + test_current_failures_++; + test_current_already_logged_++; + } + + if(test_verbose_level_ >= verbose_level) { + va_list args; + + if(!test_case_current_already_logged_ && test_case_name_[0]) { + test_line_indent_(1); + test_print_in_color_(TEST_COLOR_DEFAULT_INTENSIVE_, "Case %s:\n", test_case_name_); + test_current_already_logged_++; + test_case_current_already_logged_++; + } + + test_line_indent_(test_case_name_[0] ? 2 : 1); + if(file != NULL) { +#ifdef ACUTEST_WIN_ + const char* lastsep1 = strrchr(file, '\\'); + const char* lastsep2 = strrchr(file, '/'); + if(lastsep1 == NULL) + lastsep1 = file-1; + if(lastsep2 == NULL) + lastsep2 = file-1; + file = (lastsep1 > lastsep2 ? lastsep1 : lastsep2) + 1; +#else + const char* lastsep = strrchr(file, '/'); + if(lastsep != NULL) + file = lastsep+1; +#endif + printf("%s:%d: Check ", file, line); + } + + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + + printf("... "); + test_print_in_color_(result_color, "%s", result_str); + printf("\n"); + test_current_already_logged_++; + } + + test_cond_failed_ = (cond == 0); + return !test_cond_failed_; +} + +void TEST_ATTRIBUTE_(format (printf, 1, 2)) +test_case_(const char* fmt, ...) +{ + va_list args; + + if(test_verbose_level_ < 2) + return; + + if(test_case_name_[0]) { + test_case_current_already_logged_ = 0; + test_case_name_[0] = '\0'; + } + + if(fmt == NULL) + return; + + va_start(args, fmt); + vsnprintf(test_case_name_, sizeof(test_case_name_) - 1, fmt, args); + va_end(args); + test_case_name_[sizeof(test_case_name_) - 1] = '\0'; + + if(test_verbose_level_ >= 3) { + test_line_indent_(1); + test_print_in_color_(TEST_COLOR_DEFAULT_INTENSIVE_, "Case %s:\n", test_case_name_); + test_current_already_logged_++; + test_case_current_already_logged_++; + } +} + +void TEST_ATTRIBUTE_(format (printf, 1, 2)) +test_message_(const char* fmt, ...) +{ + char buffer[TEST_MSG_MAXSIZE]; + char* line_beg; + char* line_end; + va_list args; + + if(test_verbose_level_ < 2) + return; + + /* We allow extra message only when something is already wrong in the + * current test. */ + if(test_current_unit_ == NULL || !test_cond_failed_) + return; + + va_start(args, fmt); + vsnprintf(buffer, TEST_MSG_MAXSIZE, fmt, args); + va_end(args); + buffer[TEST_MSG_MAXSIZE-1] = '\0'; + + line_beg = buffer; + while(1) { + line_end = strchr(line_beg, '\n'); + if(line_end == NULL) + break; + test_line_indent_(test_case_name_[0] ? 3 : 2); + printf("%.*s\n", (int)(line_end - line_beg), line_beg); + line_beg = line_end + 1; + } + if(line_beg[0] != '\0') { + test_line_indent_(test_case_name_[0] ? 3 : 2); + printf("%s\n", line_beg); + } +} + +void +test_dump_(const char* title, const void* addr, size_t size) +{ + static const size_t BYTES_PER_LINE = 16; + size_t line_beg; + size_t truncate = 0; + + if(test_verbose_level_ < 2) + return; + + /* We allow extra message only when something is already wrong in the + * current test. */ + if(test_current_unit_ == NULL || !test_cond_failed_) + return; + + if(size > TEST_DUMP_MAXSIZE) { + truncate = size - TEST_DUMP_MAXSIZE; + size = TEST_DUMP_MAXSIZE; + } + + test_line_indent_(test_case_name_[0] ? 3 : 2); + printf((title[strlen(title)-1] == ':') ? "%s\n" : "%s:\n", title); + + for(line_beg = 0; line_beg < size; line_beg += BYTES_PER_LINE) { + size_t line_end = line_beg + BYTES_PER_LINE; + size_t off; + + test_line_indent_(test_case_name_[0] ? 4 : 3); + printf("%08lx: ", (unsigned long)line_beg); + for(off = line_beg; off < line_end; off++) { + if(off < size) + printf(" %02x", ((const unsigned char*)addr)[off]); + else + printf(" "); + } + + printf(" "); + for(off = line_beg; off < line_end; off++) { + unsigned char byte = ((const unsigned char*)addr)[off]; + if(off < size) + printf("%c", (iscntrl(byte) ? '.' : byte)); + else + break; + } + + printf("\n"); + } + + if(truncate > 0) { + test_line_indent_(test_case_name_[0] ? 4 : 3); + printf(" ... (and more %u bytes)\n", (unsigned) truncate); + } +} + +/* This is called just before each test */ +static void +test_init_(const char *test_name) +{ +#ifdef TEST_INIT + TEST_INIT + ; /* Allow for a single unterminated function call */ +#endif + + /* Suppress any warnings about unused variable. */ + (void) test_name; +} + +/* This is called after each test */ +static void +test_fini_(const char *test_name) +{ +#ifdef TEST_FINI + TEST_FINI + ; /* Allow for a single unterminated function call */ +#endif + + /* Suppress any warnings about unused variable. */ + (void) test_name; +} + +void +test_abort_(void) +{ + if(test_abort_has_jmp_buf_) { + longjmp(test_abort_jmp_buf_, 1); + } else { + if(test_current_unit_ != NULL) + test_fini_(test_current_unit_->name); + abort(); + } +} + +static void +test_list_names_(void) +{ + const struct test_* test; + + printf("Unit tests:\n"); + for(test = &test_list_[0]; test->func != NULL; test++) + printf(" %s\n", test->name); +} + +static void +test_remember_(int i) +{ + if(test_details_[i].flags & TEST_FLAG_RUN_) + return; + + test_details_[i].flags |= TEST_FLAG_RUN_; + test_count_++; +} + +static void +test_set_success_(int i, int success) +{ + test_details_[i].flags |= success ? TEST_FLAG_SUCCESS_ : TEST_FLAG_FAILURE_; +} + +static void +test_set_duration_(int i, double duration) +{ + test_details_[i].duration = duration; +} + +static int +test_name_contains_word_(const char* name, const char* pattern) +{ + static const char word_delim[] = " \t-_/.,:;"; + const char* substr; + size_t pattern_len; + + pattern_len = strlen(pattern); + + substr = strstr(name, pattern); + while(substr != NULL) { + int starts_on_word_boundary = (substr == name || strchr(word_delim, substr[-1]) != NULL); + int ends_on_word_boundary = (substr[pattern_len] == '\0' || strchr(word_delim, substr[pattern_len]) != NULL); + + if(starts_on_word_boundary && ends_on_word_boundary) + return 1; + + substr = strstr(substr+1, pattern); + } + + return 0; +} + +static int +test_lookup_(const char* pattern) +{ + int i; + int n = 0; + + /* Try exact match. */ + for(i = 0; i < (int) test_list_size_; i++) { + if(strcmp(test_list_[i].name, pattern) == 0) { + test_remember_(i); + n++; + break; + } + } + if(n > 0) + return n; + + /* Try word match. */ + for(i = 0; i < (int) test_list_size_; i++) { + if(test_name_contains_word_(test_list_[i].name, pattern)) { + test_remember_(i); + n++; + } + } + if(n > 0) + return n; + + /* Try relaxed match. */ + for(i = 0; i < (int) test_list_size_; i++) { + if(strstr(test_list_[i].name, pattern) != NULL) { + test_remember_(i); + n++; + } + } + + return n; +} + + +/* Called if anything goes bad in Acutest, or if the unit test ends in other + * way then by normal returning from its function (e.g. exception or some + * abnormal child process termination). */ +static void TEST_ATTRIBUTE_(format (printf, 1, 2)) +test_error_(const char* fmt, ...) +{ + if(test_verbose_level_ == 0) + return; + + if(test_verbose_level_ >= 2) { + va_list args; + + test_line_indent_(1); + if(test_verbose_level_ >= 3) + test_print_in_color_(TEST_COLOR_RED_INTENSIVE_, "ERROR: "); + va_start(args, fmt); + vprintf(fmt, args); + va_end(args); + printf("\n"); + } + + if(test_verbose_level_ >= 3) { + printf("\n"); + } +} + +/* Call directly the given test unit function. */ +static int +test_do_run_(const struct test_* test, int index) +{ + int status = -1; + + test_was_aborted_ = 0; + test_current_unit_ = test; + test_current_index_ = index; + test_current_failures_ = 0; + test_current_already_logged_ = 0; + test_cond_failed_ = 0; + +#ifdef __cplusplus + try { +#endif + test_init_(test->name); + test_begin_test_line_(test); + + /* This is good to do in case the test unit crashes. */ + fflush(stdout); + fflush(stderr); + + if(!test_worker_) { + test_abort_has_jmp_buf_ = 1; + if(setjmp(test_abort_jmp_buf_) != 0) { + test_was_aborted_ = 1; + goto aborted; + } + } + + test_timer_get_time_(&test_timer_start_); + test->func(); +aborted: + test_abort_has_jmp_buf_ = 0; + test_timer_get_time_(&test_timer_end_); + + if(test_verbose_level_ >= 3) { + test_line_indent_(1); + if(test_current_failures_ == 0) { + test_print_in_color_(TEST_COLOR_GREEN_INTENSIVE_, "SUCCESS: "); + printf("All conditions have passed.\n"); + + if(test_timer_) { + test_line_indent_(1); + printf("Duration: "); + test_timer_print_diff_(); + printf("\n"); + } + } else { + test_print_in_color_(TEST_COLOR_RED_INTENSIVE_, "FAILED: "); + if(!test_was_aborted_) { + printf("%d condition%s %s failed.\n", + test_current_failures_, + (test_current_failures_ == 1) ? "" : "s", + (test_current_failures_ == 1) ? "has" : "have"); + } else { + printf("Aborted.\n"); + } + } + printf("\n"); + } else if(test_verbose_level_ >= 1 && test_current_failures_ == 0) { + test_finish_test_line_(0); + } + + status = (test_current_failures_ == 0) ? 0 : -1; + +#ifdef __cplusplus + } catch(std::exception& e) { + const char* what = e.what(); + test_check_(0, NULL, 0, "Threw std::exception"); + if(what != NULL) + test_message_("std::exception::what(): %s", what); + + if(test_verbose_level_ >= 3) { + test_line_indent_(1); + test_print_in_color_(TEST_COLOR_RED_INTENSIVE_, "FAILED: "); + printf("C++ exception.\n\n"); + } + } catch(...) { + test_check_(0, NULL, 0, "Threw an exception"); + + if(test_verbose_level_ >= 3) { + test_line_indent_(1); + test_print_in_color_(TEST_COLOR_RED_INTENSIVE_, "FAILED: "); + printf("C++ exception.\n\n"); + } + } +#endif + + test_fini_(test->name); + test_case_(NULL); + test_current_unit_ = NULL; + + return status; +} + +/* Trigger the unit test. If possible (and not suppressed) it starts a child + * process who calls test_do_run_(), otherwise it calls test_do_run_() + * directly. */ +static void +test_run_(const struct test_* test, int index, int master_index) +{ + int failed = 1; + test_timer_type_ start, end; + + test_current_unit_ = test; + test_current_already_logged_ = 0; + test_timer_get_time_(&start); + + if(!test_no_exec_) { + +#if defined(ACUTEST_UNIX_) + + pid_t pid; + int exit_code; + + /* Make sure the child starts with empty I/O buffers. */ + fflush(stdout); + fflush(stderr); + + pid = fork(); + if(pid == (pid_t)-1) { + test_error_("Cannot fork. %s [%d]", strerror(errno), errno); + failed = 1; + } else if(pid == 0) { + /* Child: Do the test. */ + test_worker_ = 1; + failed = (test_do_run_(test, index) != 0); + test_exit_(failed ? 1 : 0); + } else { + /* Parent: Wait until child terminates and analyze its exit code. */ + waitpid(pid, &exit_code, 0); + if(WIFEXITED(exit_code)) { + switch(WEXITSTATUS(exit_code)) { + case 0: failed = 0; break; /* test has passed. */ + case 1: /* noop */ break; /* "normal" failure. */ + default: test_error_("Unexpected exit code [%d]", WEXITSTATUS(exit_code)); + } + } else if(WIFSIGNALED(exit_code)) { + char tmp[32]; + const char* signame; + switch(WTERMSIG(exit_code)) { + case SIGINT: signame = "SIGINT"; break; + case SIGHUP: signame = "SIGHUP"; break; + case SIGQUIT: signame = "SIGQUIT"; break; + case SIGABRT: signame = "SIGABRT"; break; + case SIGKILL: signame = "SIGKILL"; break; + case SIGSEGV: signame = "SIGSEGV"; break; + case SIGILL: signame = "SIGILL"; break; + case SIGTERM: signame = "SIGTERM"; break; + default: sprintf(tmp, "signal %d", WTERMSIG(exit_code)); signame = tmp; break; + } + test_error_("Test interrupted by %s.", signame); + } else { + test_error_("Test ended in an unexpected way [%d].", exit_code); + } + } + +#elif defined(ACUTEST_WIN_) + + char buffer[512] = {0}; + STARTUPINFOA startupInfo; + PROCESS_INFORMATION processInfo; + DWORD exitCode; + + /* Windows has no fork(). So we propagate all info into the child + * through a command line arguments. */ + _snprintf(buffer, sizeof(buffer)-1, + "%s --worker=%d %s --no-exec --no-summary %s --verbose=%d --color=%s -- \"%s\"", + test_argv0_, index, test_timer_ ? "--time" : "", + test_tap_ ? "--tap" : "", test_verbose_level_, + test_colorize_ ? "always" : "never", + test->name); + memset(&startupInfo, 0, sizeof(startupInfo)); + startupInfo.cb = sizeof(STARTUPINFO); + if(CreateProcessA(NULL, buffer, NULL, NULL, FALSE, 0, NULL, NULL, &startupInfo, &processInfo)) { + WaitForSingleObject(processInfo.hProcess, INFINITE); + GetExitCodeProcess(processInfo.hProcess, &exitCode); + CloseHandle(processInfo.hThread); + CloseHandle(processInfo.hProcess); + failed = (exitCode != 0); + if(exitCode > 1) { + switch(exitCode) { + case 3: test_error_("Aborted."); break; + case 0xC0000005: test_error_("Access violation."); break; + default: test_error_("Test ended in an unexpected way [%lu].", exitCode); break; + } + } + } else { + test_error_("Cannot create unit test subprocess [%ld].", GetLastError()); + failed = 1; + } + +#else + + /* A platform where we don't know how to run child process. */ + failed = (test_do_run_(test, index) != 0); + +#endif + + } else { + /* Child processes suppressed through --no-exec. */ + failed = (test_do_run_(test, index) != 0); + } + test_timer_get_time_(&end); + + test_current_unit_ = NULL; + + test_stat_run_units_++; + if(failed) + test_stat_failed_units_++; + + test_set_success_(master_index, !failed); + test_set_duration_(master_index, test_timer_diff_(start, end)); +} + +#if defined(ACUTEST_WIN_) +/* Callback for SEH events. */ +static LONG CALLBACK +test_seh_exception_filter_(EXCEPTION_POINTERS *ptrs) +{ + test_check_(0, NULL, 0, "Unhandled SEH exception"); + test_message_("Exception code: 0x%08lx", ptrs->ExceptionRecord->ExceptionCode); + test_message_("Exception address: 0x%p", ptrs->ExceptionRecord->ExceptionAddress); + + fflush(stdout); + fflush(stderr); + + return EXCEPTION_EXECUTE_HANDLER; +} +#endif + + +#define TEST_CMDLINE_OPTFLAG_OPTIONALARG_ 0x0001 +#define TEST_CMDLINE_OPTFLAG_REQUIREDARG_ 0x0002 + +#define TEST_CMDLINE_OPTID_NONE_ 0 +#define TEST_CMDLINE_OPTID_UNKNOWN_ (-0x7fffffff + 0) +#define TEST_CMDLINE_OPTID_MISSINGARG_ (-0x7fffffff + 1) +#define TEST_CMDLINE_OPTID_BOGUSARG_ (-0x7fffffff + 2) + +typedef struct TEST_CMDLINE_OPTION_ { + char shortname; + const char* longname; + int id; + unsigned flags; +} TEST_CMDLINE_OPTION_; + +static int +test_cmdline_handle_short_opt_group_(const TEST_CMDLINE_OPTION_* options, + const char* arggroup, + int (*callback)(int /*optval*/, const char* /*arg*/)) +{ + const TEST_CMDLINE_OPTION_* opt; + int i; + int ret = 0; + + for(i = 0; arggroup[i] != '\0'; i++) { + for(opt = options; opt->id != 0; opt++) { + if(arggroup[i] == opt->shortname) + break; + } + + if(opt->id != 0 && !(opt->flags & TEST_CMDLINE_OPTFLAG_REQUIREDARG_)) { + ret = callback(opt->id, NULL); + } else { + /* Unknown option. */ + char badoptname[3]; + badoptname[0] = '-'; + badoptname[1] = arggroup[i]; + badoptname[2] = '\0'; + ret = callback((opt->id != 0 ? TEST_CMDLINE_OPTID_MISSINGARG_ : TEST_CMDLINE_OPTID_UNKNOWN_), + badoptname); + } + + if(ret != 0) + break; + } + + return ret; +} + +#define TEST_CMDLINE_AUXBUF_SIZE_ 32 + +static int +test_cmdline_read_(const TEST_CMDLINE_OPTION_* options, int argc, char** argv, + int (*callback)(int /*optval*/, const char* /*arg*/)) +{ + + const TEST_CMDLINE_OPTION_* opt; + char auxbuf[TEST_CMDLINE_AUXBUF_SIZE_+1]; + int after_doubledash = 0; + int i = 1; + int ret = 0; + + auxbuf[TEST_CMDLINE_AUXBUF_SIZE_] = '\0'; + + while(i < argc) { + if(after_doubledash || strcmp(argv[i], "-") == 0) { + /* Non-option argument. */ + ret = callback(TEST_CMDLINE_OPTID_NONE_, argv[i]); + } else if(strcmp(argv[i], "--") == 0) { + /* End of options. All the remaining members are non-option arguments. */ + after_doubledash = 1; + } else if(argv[i][0] != '-') { + /* Non-option argument. */ + ret = callback(TEST_CMDLINE_OPTID_NONE_, argv[i]); + } else { + for(opt = options; opt->id != 0; opt++) { + if(opt->longname != NULL && strncmp(argv[i], "--", 2) == 0) { + size_t len = strlen(opt->longname); + if(strncmp(argv[i]+2, opt->longname, len) == 0) { + /* Regular long option. */ + if(argv[i][2+len] == '\0') { + /* with no argument provided. */ + if(!(opt->flags & TEST_CMDLINE_OPTFLAG_REQUIREDARG_)) + ret = callback(opt->id, NULL); + else + ret = callback(TEST_CMDLINE_OPTID_MISSINGARG_, argv[i]); + break; + } else if(argv[i][2+len] == '=') { + /* with an argument provided. */ + if(opt->flags & (TEST_CMDLINE_OPTFLAG_OPTIONALARG_ | TEST_CMDLINE_OPTFLAG_REQUIREDARG_)) { + ret = callback(opt->id, argv[i]+2+len+1); + } else { + sprintf(auxbuf, "--%s", opt->longname); + ret = callback(TEST_CMDLINE_OPTID_BOGUSARG_, auxbuf); + } + break; + } else { + continue; + } + } + } else if(opt->shortname != '\0' && argv[i][0] == '-') { + if(argv[i][1] == opt->shortname) { + /* Regular short option. */ + if(opt->flags & TEST_CMDLINE_OPTFLAG_REQUIREDARG_) { + if(argv[i][2] != '\0') + ret = callback(opt->id, argv[i]+2); + else if(i+1 < argc) + ret = callback(opt->id, argv[++i]); + else + ret = callback(TEST_CMDLINE_OPTID_MISSINGARG_, argv[i]); + break; + } else { + ret = callback(opt->id, NULL); + + /* There might be more (argument-less) short options + * grouped together. */ + if(ret == 0 && argv[i][2] != '\0') + ret = test_cmdline_handle_short_opt_group_(options, argv[i]+2, callback); + break; + } + } + } + } + + if(opt->id == 0) { /* still not handled? */ + if(argv[i][0] != '-') { + /* Non-option argument. */ + ret = callback(TEST_CMDLINE_OPTID_NONE_, argv[i]); + } else { + /* Unknown option. */ + char* badoptname = argv[i]; + + if(strncmp(badoptname, "--", 2) == 0) { + /* Strip any argument from the long option. */ + char* assignment = strchr(badoptname, '='); + if(assignment != NULL) { + size_t len = assignment - badoptname; + if(len > TEST_CMDLINE_AUXBUF_SIZE_) + len = TEST_CMDLINE_AUXBUF_SIZE_; + strncpy(auxbuf, badoptname, len); + auxbuf[len] = '\0'; + badoptname = auxbuf; + } + } + + ret = callback(TEST_CMDLINE_OPTID_UNKNOWN_, badoptname); + } + } + } + + if(ret != 0) + return ret; + i++; + } + + return ret; +} + +static void +test_help_(void) +{ + printf("Usage: %s [options] [test...]\n", test_argv0_); + printf("\n"); + printf("Run the specified unit tests; or if the option '--skip' is used, run all\n"); + printf("tests in the suite but those listed. By default, if no tests are specified\n"); + printf("on the command line, all unit tests in the suite are run.\n"); + printf("\n"); + printf("Options:\n"); + printf(" -s, --skip Execute all unit tests but the listed ones\n"); + printf(" --exec[=WHEN] If supported, execute unit tests as child processes\n"); + printf(" (WHEN is one of 'auto', 'always', 'never')\n"); + printf(" -E, --no-exec Same as --exec=never\n"); +#if defined ACUTEST_WIN_ + printf(" -t, --time Measure test duration\n"); +#elif defined ACUTEST_HAS_POSIX_TIMER_ + printf(" -t, --time Measure test duration (real time)\n"); + printf(" --time=TIMER Measure test duration, using given timer\n"); + printf(" (TIMER is one of 'real', 'cpu')\n"); +#endif + printf(" --no-summary Suppress printing of test results summary\n"); + printf(" --tap Produce TAP-compliant output\n"); + printf(" (See https://testanything.org/)\n"); + printf(" -x, --xml-output=FILE Enable XUnit output to the given file\n"); + printf(" -l, --list List unit tests in the suite and exit\n"); + printf(" -v, --verbose Make output more verbose\n"); + printf(" --verbose=LEVEL Set verbose level to LEVEL:\n"); + printf(" 0 ... Be silent\n"); + printf(" 1 ... Output one line per test (and summary)\n"); + printf(" 2 ... As 1 and failed conditions (this is default)\n"); + printf(" 3 ... As 1 and all conditions (and extended summary)\n"); + printf(" -q, --quiet Same as --verbose=0\n"); + printf(" --color[=WHEN] Enable colorized output\n"); + printf(" (WHEN is one of 'auto', 'always', 'never')\n"); + printf(" --no-color Same as --color=never\n"); + printf(" -h, --help Display this help and exit\n"); + + if(test_list_size_ < 16) { + printf("\n"); + test_list_names_(); + } +} + +static const TEST_CMDLINE_OPTION_ test_cmdline_options_[] = { + { 's', "skip", 's', 0 }, + { 0, "exec", 'e', TEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, + { 'E', "no-exec", 'E', 0 }, +#if defined ACUTEST_WIN_ + { 't', "time", 't', 0 }, + { 0, "timer", 't', 0 }, /* kept for compatibility */ +#elif defined ACUTEST_HAS_POSIX_TIMER_ + { 't', "time", 't', TEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, + { 0, "timer", 't', TEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, /* kept for compatibility */ +#endif + { 0, "no-summary", 'S', 0 }, + { 0, "tap", 'T', 0 }, + { 'l', "list", 'l', 0 }, + { 'v', "verbose", 'v', TEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, + { 'q', "quiet", 'q', 0 }, + { 0, "color", 'c', TEST_CMDLINE_OPTFLAG_OPTIONALARG_ }, + { 0, "no-color", 'C', 0 }, + { 'h', "help", 'h', 0 }, + { 0, "worker", 'w', TEST_CMDLINE_OPTFLAG_REQUIREDARG_ }, /* internal */ + { 'x', "xml-output", 'x', TEST_CMDLINE_OPTFLAG_REQUIREDARG_ }, + { 0, NULL, 0, 0 } +}; + +static int +test_cmdline_callback_(int id, const char* arg) +{ + switch(id) { + case 's': + test_skip_mode_ = 1; + break; + + case 'e': + if(arg == NULL || strcmp(arg, "always") == 0) { + test_no_exec_ = 0; + } else if(strcmp(arg, "never") == 0) { + test_no_exec_ = 1; + } else if(strcmp(arg, "auto") == 0) { + /*noop*/ + } else { + fprintf(stderr, "%s: Unrecognized argument '%s' for option --exec.\n", test_argv0_, arg); + fprintf(stderr, "Try '%s --help' for more information.\n", test_argv0_); + test_exit_(2); + } + break; + + case 'E': + test_no_exec_ = 1; + break; + + case 't': +#if defined ACUTEST_WIN_ || defined ACUTEST_HAS_POSIX_TIMER_ + if(arg == NULL || strcmp(arg, "real") == 0) { + test_timer_ = 1; + #ifndef ACUTEST_WIN_ + } else if(strcmp(arg, "cpu") == 0) { + test_timer_ = 2; + #endif + } else { + fprintf(stderr, "%s: Unrecognized argument '%s' for option --time.\n", test_argv0_, arg); + fprintf(stderr, "Try '%s --help' for more information.\n", test_argv0_); + test_exit_(2); + } +#endif + break; + + case 'S': + test_no_summary_ = 1; + break; + + case 'T': + test_tap_ = 1; + break; + + case 'l': + test_list_names_(); + test_exit_(0); + break; + + case 'v': + test_verbose_level_ = (arg != NULL ? atoi(arg) : test_verbose_level_+1); + break; + + case 'q': + test_verbose_level_ = 0; + break; + + case 'c': + if(arg == NULL || strcmp(arg, "always") == 0) { + test_colorize_ = 1; + } else if(strcmp(arg, "never") == 0) { + test_colorize_ = 0; + } else if(strcmp(arg, "auto") == 0) { + /*noop*/ + } else { + fprintf(stderr, "%s: Unrecognized argument '%s' for option --color.\n", test_argv0_, arg); + fprintf(stderr, "Try '%s --help' for more information.\n", test_argv0_); + test_exit_(2); + } + break; + + case 'C': + test_colorize_ = 0; + break; + + case 'h': + test_help_(); + test_exit_(0); + break; + + case 'w': + test_worker_ = 1; + test_worker_index_ = atoi(arg); + break; + case 'x': + test_xml_output_ = fopen(arg, "w"); + if (!test_xml_output_) { + fprintf(stderr, "Unable to open '%s': %s\n", arg, strerror(errno)); + test_exit_(2); + } + break; + + case 0: + if(test_lookup_(arg) == 0) { + fprintf(stderr, "%s: Unrecognized unit test '%s'\n", test_argv0_, arg); + fprintf(stderr, "Try '%s --list' for list of unit tests.\n", test_argv0_); + test_exit_(2); + } + break; + + case TEST_CMDLINE_OPTID_UNKNOWN_: + fprintf(stderr, "Unrecognized command line option '%s'.\n", arg); + fprintf(stderr, "Try '%s --help' for more information.\n", test_argv0_); + test_exit_(2); + break; + + case TEST_CMDLINE_OPTID_MISSINGARG_: + fprintf(stderr, "The command line option '%s' requires an argument.\n", arg); + fprintf(stderr, "Try '%s --help' for more information.\n", test_argv0_); + test_exit_(2); + break; + + case TEST_CMDLINE_OPTID_BOGUSARG_: + fprintf(stderr, "The command line option '%s' does not expect an argument.\n", arg); + fprintf(stderr, "Try '%s --help' for more information.\n", test_argv0_); + test_exit_(2); + break; + } + + return 0; +} + + +#ifdef ACUTEST_LINUX_ +static int +test_is_tracer_present_(void) +{ + /* Must be large enough so the line 'TracerPid: ${PID}' can fit in. */ + static const int OVERLAP = 32; + + char buf[256+OVERLAP+1]; + int tracer_present = 0; + int fd; + size_t n_read = 0; + + fd = open("/proc/self/status", O_RDONLY); + if(fd == -1) + return 0; + + while(1) { + static const char pattern[] = "TracerPid:"; + const char* field; + + while(n_read < sizeof(buf) - 1) { + ssize_t n; + + n = read(fd, buf + n_read, sizeof(buf) - 1 - n_read); + if(n <= 0) + break; + n_read += n; + } + buf[n_read] = '\0'; + + field = strstr(buf, pattern); + if(field != NULL && field < buf + sizeof(buf) - OVERLAP) { + pid_t tracer_pid = (pid_t) atoi(field + sizeof(pattern) - 1); + tracer_present = (tracer_pid != 0); + break; + } + + if(n_read == sizeof(buf)-1) { + memmove(buf, buf + sizeof(buf)-1 - OVERLAP, OVERLAP); + n_read = OVERLAP; + } else { + break; + } + } + + close(fd); + return tracer_present; +} +#endif + +int +main(int argc, char** argv) +{ + int i; + test_argv0_ = argv[0]; + +#if defined ACUTEST_UNIX_ + test_colorize_ = isatty(STDOUT_FILENO); +#elif defined ACUTEST_WIN_ + #if defined _BORLANDC_ + test_colorize_ = isatty(_fileno(stdout)); + #else + test_colorize_ = _isatty(_fileno(stdout)); + #endif +#else + test_colorize_ = 0; +#endif + + /* Count all test units */ + test_list_size_ = 0; + for(i = 0; test_list_[i].func != NULL; i++) + test_list_size_++; + + test_details_ = (struct test_detail_*)calloc(test_list_size_, sizeof(struct test_detail_)); + if(test_details_ == NULL) { + fprintf(stderr, "Out of memory.\n"); + test_exit_(2); + } + + /* Parse options */ + test_cmdline_read_(test_cmdline_options_, argc, argv, test_cmdline_callback_); + + /* Initialize the proper timer. */ + test_timer_init_(); + +#if defined(ACUTEST_WIN_) + SetUnhandledExceptionFilter(test_seh_exception_filter_); +#ifdef _MSC_VER + _set_abort_behavior(0, _WRITE_ABORT_MSG); +#endif +#endif + + /* By default, we want to run all tests. */ + if(test_count_ == 0) { + for(i = 0; test_list_[i].func != NULL; i++) + test_remember_(i); + } + + /* Guess whether we want to run unit tests as child processes. */ + if(test_no_exec_ < 0) { + test_no_exec_ = 0; + + if(test_count_ <= 1) { + test_no_exec_ = 1; + } else { +#ifdef ACUTEST_WIN_ + if(IsDebuggerPresent()) + test_no_exec_ = 1; +#endif +#ifdef ACUTEST_LINUX_ + if(test_is_tracer_present_()) + test_no_exec_ = 1; +#endif +#ifdef RUNNING_ON_VALGRIND + /* RUNNING_ON_VALGRIND is provided by valgrind.h */ + if(RUNNING_ON_VALGRIND) + test_no_exec_ = 1; +#endif + } + } + + if(test_tap_) { + /* TAP requires we know test result ("ok", "not ok") before we output + * anything about the test, and this gets problematic for larger verbose + * levels. */ + if(test_verbose_level_ > 2) + test_verbose_level_ = 2; + + /* TAP harness should provide some summary. */ + test_no_summary_ = 1; + + if(!test_worker_) + printf("1..%d\n", (int) test_count_); + } + + int index = test_worker_index_; + for(i = 0; test_list_[i].func != NULL; i++) { + int run = (test_details_[i].flags & TEST_FLAG_RUN_); + if (test_skip_mode_) /* Run all tests except those listed. */ + run = !run; + if(run) + test_run_(&test_list_[i], index++, i); + } + + /* Write a summary */ + if(!test_no_summary_ && test_verbose_level_ >= 1) { + if(test_verbose_level_ >= 3) { + test_print_in_color_(TEST_COLOR_DEFAULT_INTENSIVE_, "Summary:\n"); + + printf(" Count of all unit tests: %4d\n", (int) test_list_size_); + printf(" Count of run unit tests: %4d\n", test_stat_run_units_); + printf(" Count of failed unit tests: %4d\n", test_stat_failed_units_); + printf(" Count of skipped unit tests: %4d\n", (int) test_list_size_ - test_stat_run_units_); + } + + if(test_stat_failed_units_ == 0) { + test_print_in_color_(TEST_COLOR_GREEN_INTENSIVE_, "SUCCESS:"); + printf(" All unit tests have passed.\n"); + } else { + test_print_in_color_(TEST_COLOR_RED_INTENSIVE_, "FAILED:"); + printf(" %d of %d unit tests %s failed.\n", + test_stat_failed_units_, test_stat_run_units_, + (test_stat_failed_units_ == 1) ? "has" : "have"); + } + + if(test_verbose_level_ >= 3) + printf("\n"); + } + + if (test_xml_output_) { +#if defined ACUTEST_UNIX_ + char *suite_name = basename(argv[0]); +#elif defined ACUTEST_WIN_ + char suite_name[_MAX_FNAME]; + _splitpath(argv[0], NULL, NULL, suite_name, NULL); +#else + const char *suite_name = argv[0]; +#endif + fprintf(test_xml_output_, "\n"); + fprintf(test_xml_output_, "\n", + suite_name, (int)test_list_size_, test_stat_failed_units_, test_stat_failed_units_, + (int)test_list_size_ - test_stat_run_units_); + for(i = 0; test_list_[i].func != NULL; i++) { + struct test_detail_ *details = &test_details_[i]; + fprintf(test_xml_output_, " \n", test_list_[i].name, details->duration); + if (details->flags & TEST_FLAG_FAILURE_) + fprintf(test_xml_output_, " \n"); + if (!(details->flags & TEST_FLAG_FAILURE_) && !(details->flags & TEST_FLAG_SUCCESS_)) + fprintf(test_xml_output_, " \n"); + fprintf(test_xml_output_, " \n"); + } + fprintf(test_xml_output_, "\n"); + fclose(test_xml_output_); + } + + test_cleanup_(); + + return (test_stat_failed_units_ == 0) ? 0 : 1; +} + + +#endif /* #ifndef TEST_NO_MAIN */ + +#ifdef _MSC_VER + #pragma warning(pop) +#endif + +#ifdef __cplusplus + } /* extern "C" */ +#endif + +#endif /* #ifndef ACUTEST_H */ diff --git a/tests/tests.cpp b/tests/tests.cpp new file mode 100644 index 00000000..98f7ee83 --- /dev/null +++ b/tests/tests.cpp @@ -0,0 +1,283 @@ +#include "acutest.h" + +#include "config.hpp" + +void +test_nop() +{ + TEST_CHECK(true); +} + +void +test_config_bool() +{ + ConfigBOOL v; + + TEST_CHECK(v.from_string("true") == 0); + TEST_CHECK(v == true); + TEST_CHECK(v.to_string() == "true"); + + TEST_CHECK(v.from_string("false") == 0); + TEST_CHECK(v == false); + TEST_CHECK(v.to_string() == "false"); + + TEST_CHECK(v.from_string("asdf") == -EINVAL); +} + +void +test_config_uint64() +{ + ConfigUINT64 v; + + TEST_CHECK(v.from_string("0") == 0); + TEST_CHECK(v == (uint64_t)0); + TEST_CHECK(v.to_string() == "0"); + + TEST_CHECK(v.from_string("123") == 0); + TEST_CHECK(v == (uint64_t)123); + TEST_CHECK(v.to_string() == "123"); + + TEST_CHECK(v.from_string("1234567890") == 0); + TEST_CHECK(v == (uint64_t)1234567890); + TEST_CHECK(v.to_string() == "1234567890"); + + TEST_CHECK(v.from_string("asdf") == -EINVAL); +} + +void +test_config_int() +{ + ConfigINT v; + + TEST_CHECK(v.from_string("0") == 0); + TEST_CHECK(v == (int)0); + TEST_CHECK(v.to_string() == "0"); + + TEST_CHECK(v.from_string("123") == 0); + TEST_CHECK(v == (int)123); + TEST_CHECK(v.to_string() == "123"); + + TEST_CHECK(v.from_string("1234567890") == 0); + TEST_CHECK(v == (int)1234567890); + TEST_CHECK(v.to_string() == "1234567890"); + + TEST_CHECK(v.from_string("asdf") == -EINVAL); +} + +void +test_config_str() +{ + ConfigSTR v; + + TEST_CHECK(v.from_string("foo") == 0); + TEST_CHECK(v == "foo"); + TEST_CHECK(v.to_string() == "foo"); +} + +void +test_config_branches() +{ + uint64_t minfreespace; + Branches b(minfreespace); + Branches::CPtr bcp0; + Branches::CPtr bcp1; + + minfreespace = 1234; + TEST_CHECK(b->minfreespace() == 1234); + TEST_CHECK(b.to_string() == ""); + + bcp0 = b; + TEST_CHECK(b.from_string("/foo/bar") == 0); + TEST_CHECK(b.to_string() == "/foo/bar=RW"); + bcp1 = b; + TEST_CHECK(bcp0.get() != bcp1.get()); + + TEST_CHECK(b.from_string("/foo/bar=RW,1234") == 0); + TEST_CHECK(b.to_string() == "/foo/bar=RW,1234"); + + TEST_CHECK(b.from_string("/foo/bar=RO,1234:/foo/baz=NC,4321") == 0); + TEST_CHECK(b.to_string() == "/foo/bar=RO,1234:/foo/baz=NC,4321"); + bcp0 = b; + TEST_CHECK((*bcp0).size() == 2); + TEST_CHECK((*bcp0)[0].path == "/foo/bar"); + TEST_CHECK((*bcp0)[0].minfreespace() == 1234); + TEST_MSG("minfreespace: expected = %lu; produced = %lu", + 1234, + (*bcp0)[0].minfreespace()); + TEST_CHECK((*bcp0)[1].path == "/foo/baz"); + TEST_CHECK((*bcp0)[1].minfreespace() == 4321); + TEST_MSG("minfreespace: expected = %lu; produced = %lu", + 4321, + (*bcp0)[1].minfreespace()); +} + +void +test_config_cachefiles() +{ + CacheFiles cf; + + TEST_CHECK(cf.from_string("libfuse") == 0); + TEST_CHECK(cf.to_string() == "libfuse"); + TEST_CHECK(cf.from_string("off") == 0); + TEST_CHECK(cf.to_string() == "off"); + TEST_CHECK(cf.from_string("partial") == 0); + TEST_CHECK(cf.to_string() == "partial"); + TEST_CHECK(cf.from_string("full") == 0); + TEST_CHECK(cf.to_string() == "full"); + TEST_CHECK(cf.from_string("auto-full") == 0); + TEST_CHECK(cf.to_string() == "auto-full"); + TEST_CHECK(cf.from_string("foobar") == -EINVAL); +} + +void +test_config_inodecalc() +{ + InodeCalc ic("passthrough"); + + TEST_CHECK(ic.from_string("passthrough") == 0); + TEST_CHECK(ic.to_string() == "passthrough"); + TEST_CHECK(ic.from_string("path-hash") == 0); + TEST_CHECK(ic.to_string() == "path-hash"); + TEST_CHECK(ic.from_string("devino-hash") == 0); + TEST_CHECK(ic.to_string() == "devino-hash"); + TEST_CHECK(ic.from_string("hybrid-hash") == 0); + TEST_CHECK(ic.to_string() == "hybrid-hash"); + TEST_CHECK(ic.from_string("path-hash32") == 0); + TEST_CHECK(ic.to_string() == "path-hash32"); + TEST_CHECK(ic.from_string("devino-hash32") == 0); + TEST_CHECK(ic.to_string() == "devino-hash32"); + TEST_CHECK(ic.from_string("hybrid-hash32") == 0); + TEST_CHECK(ic.to_string() == "hybrid-hash32"); + TEST_CHECK(ic.from_string("asdf") == -EINVAL); +} + +void +test_config_moveonenospc() +{ + MoveOnENOSPC m(false); + + TEST_CHECK(m.to_string() == "false"); + TEST_CHECK(m.from_string("mfs") == 0); + TEST_CHECK(m.to_string() == "mfs"); + TEST_CHECK(m.from_string("mspmfs") == 0); + TEST_CHECK(m.to_string() == "mspmfs"); + TEST_CHECK(m.from_string("true") == 0); + TEST_CHECK(m.to_string() == "mfs"); + TEST_CHECK(m.from_string("blah") == -EINVAL); +} + +void +test_config_nfsopenhack() +{ + NFSOpenHack n; + + TEST_CHECK(n.from_string("off") == 0); + TEST_CHECK(n.to_string() == "off"); + TEST_CHECK(n == NFSOpenHack::ENUM::OFF); + + TEST_CHECK(n.from_string("git") == 0); + TEST_CHECK(n.to_string() == "git"); + TEST_CHECK(n == NFSOpenHack::ENUM::GIT); + + TEST_CHECK(n.from_string("all") == 0); + TEST_CHECK(n.to_string() == "all"); + TEST_CHECK(n == NFSOpenHack::ENUM::ALL); +} + +void +test_config_readdir() +{ + ReadDir r; + + TEST_CHECK(r.from_string("linux") == 0); + TEST_CHECK(r.to_string() == "linux"); + TEST_CHECK(r == ReadDir::ENUM::LINUX); + + TEST_CHECK(r.from_string("posix") == 0); + TEST_CHECK(r.to_string() == "posix"); + TEST_CHECK(r == ReadDir::ENUM::POSIX); +} + +void +test_config_statfs() +{ + StatFS s; + + TEST_CHECK(s.from_string("base") == 0); + TEST_CHECK(s.to_string() == "base"); + TEST_CHECK(s == StatFS::ENUM::BASE); + + TEST_CHECK(s.from_string("full") == 0); + TEST_CHECK(s.to_string() == "full"); + TEST_CHECK(s == StatFS::ENUM::FULL); + + TEST_CHECK(s.from_string("asdf") == -EINVAL); +} + +void +test_config_statfs_ignore() +{ + StatFSIgnore s; + + TEST_CHECK(s.from_string("none") == 0); + TEST_CHECK(s.to_string() == "none"); + TEST_CHECK(s == StatFSIgnore::ENUM::NONE); + + TEST_CHECK(s.from_string("ro") == 0); + TEST_CHECK(s.to_string() == "ro"); + TEST_CHECK(s == StatFSIgnore::ENUM::RO); + + TEST_CHECK(s.from_string("nc") == 0); + TEST_CHECK(s.to_string() == "nc"); + TEST_CHECK(s == StatFSIgnore::ENUM::NC); + + TEST_CHECK(s.from_string("asdf") == -EINVAL); +} + +void +test_config_xattr() +{ + XAttr x; + + TEST_CHECK(x.from_string("passthrough") == 0); + TEST_CHECK(x.to_string() == "passthrough"); + TEST_CHECK(x == XAttr::ENUM::PASSTHROUGH); + + TEST_CHECK(x.from_string("noattr") == 0); + TEST_CHECK(x.to_string() == "noattr"); + TEST_CHECK(x == XAttr::ENUM::NOATTR); + + TEST_CHECK(x.from_string("nosys") == 0); + TEST_CHECK(x.to_string() == "nosys"); + TEST_CHECK(x == XAttr::ENUM::NOSYS); + + TEST_CHECK(x.from_string("asdf") == -EINVAL); +} + +void +test_config() +{ + Config cfg; + + TEST_CHECK(cfg.set_raw("async_read","true") == 0); +} + +TEST_LIST = + { + {"nop",test_nop}, + {"config_bool",test_config_bool}, + {"config_uint64",test_config_uint64}, + {"config_int",test_config_int}, + {"config_str",test_config_str}, + {"config_branches",test_config_branches}, + {"config_cachefiles",test_config_cachefiles}, + {"config_inodecalc",test_config_inodecalc}, + {"config_moveonenospc",test_config_moveonenospc}, + {"config_nfsopenhack",test_config_nfsopenhack}, + {"config_readdir",test_config_readdir}, + {"config_statfs",test_config_statfs}, + {"config_statfsignore",test_config_statfs_ignore}, + {"config_xattr",test_config_xattr}, + {"config",test_config}, + {NULL,NULL} + }; diff --git a/tools/cppfind b/tools/cppfind index 5721d365..51c99029 100755 --- a/tools/cppfind +++ b/tools/cppfind @@ -3,6 +3,6 @@ CXX="${CXX:-c++}" FUSE_CFLAGS="-Ilibfuse/include -D_FILE_OFFSET_BITS=64 -DFUSE_USE_VERSION=29" -echo "#include " | ${CXX} -E ${FUSE_CFLAGS} - | grep "${1}" > /dev/null +echo "#include \"fuse.h\"" | ${CXX} -E ${FUSE_CFLAGS} - | grep "${1}" > /dev/null [ "$?" != "0" ]; echo $?