From 031b87f67490634d4212bfc6f667b6eb8c78f465 Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Tue, 27 Jan 2015 16:08:13 -0500 Subject: [PATCH 1/4] slight refactoring --- src/mergerfs.cpp | 147 +++++++++++++++++++++++++---------------------- 1 file changed, 79 insertions(+), 68 deletions(-) diff --git a/src/mergerfs.cpp b/src/mergerfs.cpp index 768e8ed7..d4e01693 100644 --- a/src/mergerfs.cpp +++ b/src/mergerfs.cpp @@ -71,87 +71,102 @@ #include "write.hpp" #include "write_buf.hpp" -static -struct fuse_operations -get_fuse_operations() +namespace local { - struct fuse_operations ops = {0}; - + static + void + get_fuse_operations(struct fuse_operations &ops) + { #if FLAG_NOPATH - ops.flag_nopath = false; + ops.flag_nopath = false; #endif - ops.flag_nullpath_ok = false; - - ops.access = mergerfs::access::access; - ops.bmap = NULL; - ops.chmod = mergerfs::chmod::chmod; - ops.chown = mergerfs::chown::chown; - ops.create = mergerfs::create::create; - ops.destroy = mergerfs::destroy::destroy; + ops.flag_nullpath_ok = false; + + ops.access = mergerfs::access::access; + ops.bmap = NULL; + ops.chmod = mergerfs::chmod::chmod; + ops.chown = mergerfs::chown::chown; + ops.create = mergerfs::create::create; + ops.destroy = mergerfs::destroy::destroy; #if FALLOCATE - ops.fallocate = mergerfs::fallocate::fallocate; + ops.fallocate = mergerfs::fallocate::fallocate; #endif - ops.fgetattr = mergerfs::fgetattr::fgetattr; + ops.fgetattr = mergerfs::fgetattr::fgetattr; #if FLOCK - ops.flock = NULL; + ops.flock = NULL; #endif - ops.flush = mergerfs::flush::flush; - ops.fsync = mergerfs::fsync::fsync; - ops.fsyncdir = NULL; - ops.ftruncate = mergerfs::ftruncate::ftruncate; - ops.getattr = mergerfs::getattr::getattr; - ops.getdir = NULL; /* deprecated; use readdir */ - ops.getxattr = mergerfs::getxattr::getxattr; - ops.init = mergerfs::init::init; - ops.ioctl = mergerfs::ioctl::ioctl; - ops.link = mergerfs::link::link; - ops.listxattr = mergerfs::listxattr::listxattr; - ops.lock = NULL; - ops.mkdir = mergerfs::mkdir::mkdir; - ops.mknod = mergerfs::mknod::mknod; - ops.open = mergerfs::open::open; - ops.opendir = mergerfs::opendir::opendir; - ops.poll = NULL; - ops.read = mergerfs::read::read; + ops.flush = mergerfs::flush::flush; + ops.fsync = mergerfs::fsync::fsync; + ops.fsyncdir = NULL; + ops.ftruncate = mergerfs::ftruncate::ftruncate; + ops.getattr = mergerfs::getattr::getattr; + ops.getdir = NULL; /* deprecated; use readdir */ + ops.getxattr = mergerfs::getxattr::getxattr; + ops.init = mergerfs::init::init; + ops.ioctl = mergerfs::ioctl::ioctl; + ops.link = mergerfs::link::link; + ops.listxattr = mergerfs::listxattr::listxattr; + ops.lock = NULL; + ops.mkdir = mergerfs::mkdir::mkdir; + ops.mknod = mergerfs::mknod::mknod; + ops.open = mergerfs::open::open; + ops.opendir = mergerfs::opendir::opendir; + ops.poll = NULL; + ops.read = mergerfs::read::read; #if READ_BUF - ops.read_buf = mergerfs::read_buf::read_buf; + ops.read_buf = mergerfs::read_buf::read_buf; #endif - ops.readdir = mergerfs::readdir::readdir; - ops.readlink = mergerfs::readlink::readlink; - ops.release = mergerfs::release::release; - ops.releasedir = mergerfs::releasedir::releasedir; - ops.removexattr = mergerfs::removexattr::removexattr; - ops.rename = mergerfs::rename::rename; - ops.rmdir = mergerfs::rmdir::rmdir; - ops.setxattr = mergerfs::setxattr::setxattr; - ops.statfs = mergerfs::statfs::statfs; - ops.symlink = mergerfs::symlink::symlink; - ops.truncate = mergerfs::truncate::truncate; - ops.unlink = mergerfs::unlink::unlink; - ops.utime = NULL; /* deprecated; use utimens() */ - ops.utimens = mergerfs::utimens::utimens; - ops.write = mergerfs::write::write; + ops.readdir = mergerfs::readdir::readdir; + ops.readlink = mergerfs::readlink::readlink; + ops.release = mergerfs::release::release; + ops.releasedir = mergerfs::releasedir::releasedir; + ops.removexattr = mergerfs::removexattr::removexattr; + ops.rename = mergerfs::rename::rename; + ops.rmdir = mergerfs::rmdir::rmdir; + ops.setxattr = mergerfs::setxattr::setxattr; + ops.statfs = mergerfs::statfs::statfs; + ops.symlink = mergerfs::symlink::symlink; + ops.truncate = mergerfs::truncate::truncate; + ops.unlink = mergerfs::unlink::unlink; + ops.utime = NULL; /* deprecated; use utimens() */ + ops.utimens = mergerfs::utimens::utimens; + ops.write = mergerfs::write::write; #if WRITE_BUF - ops.write_buf = mergerfs::write_buf::write_buf; + ops.write_buf = mergerfs::write_buf::write_buf; #endif - return ops; + return; + } + + static + void + setup_resources(void) + { + std::srand(time(NULL)); + mergerfs::resources::reset_umask(); + mergerfs::resources::maxout_rlimit_nofile(); + mergerfs::resources::maxout_rlimit_fsize(); + } } namespace mergerfs { int - main(const struct fuse_args &args, - config::Config &config) + main(const int argc, + char **argv) { - struct fuse_operations ops; + struct fuse_args args; + struct fuse_operations ops = {0}; + mergerfs::config::Config config; - ops = get_fuse_operations(); + args.argc = argc; + args.argv = argv; + args.allocated = 0; - std::srand(time(NULL)); - resources::reset_umask(); - resources::maxout_rlimit_nofile(); - resources::maxout_rlimit_fsize(); + mergerfs::options::parse(args,config); + + local::setup_resources(); + local::get_fuse_operations(ops); return fuse_main(args.argc, args.argv, @@ -161,16 +176,12 @@ namespace mergerfs } int -main(int argc, - char *argv[]) +main(int argc, + char **argv) { int rv; - mergerfs::config::Config config; - struct fuse_args args = FUSE_ARGS_INIT(argc,argv); - - mergerfs::options::parse(args,config); - rv = mergerfs::main(args,config); + rv = mergerfs::main(argc,argv); return rv; } From d1f3bd82e82d7c5dc7c7059f93de7baa0ea18587 Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Tue, 27 Jan 2015 18:25:20 -0500 Subject: [PATCH 2/4] add clonepath tool --- Makefile | 43 ++++++++++++++++++++++++++----------- src/clonepath.cpp | 54 +++++++++++++++++++++++++++++++++++++++++++++++ src/clonepath.hpp | 30 ++++++++++++++++++++++++++ src/mergerfs.cpp | 18 +++++++++++++--- 4 files changed, 130 insertions(+), 15 deletions(-) create mode 100644 src/clonepath.cpp create mode 100644 src/clonepath.hpp diff --git a/Makefile b/Makefile index 83f33382..f5219e07 100644 --- a/Makefile +++ b/Makefile @@ -27,6 +27,7 @@ MKDIR = $(shell which mkdir) TOUCH = $(shell which touch) CP = $(shell which cp) RM = $(shell which rm) +LN = $(shell which ln) FIND = $(shell which find) INSTALL = $(shell which install) MKTEMP = $(shell which mktemp) @@ -82,8 +83,8 @@ LDFLAGS = $(shell $(PKGCONFIG) fuse --libs) BINDIR = $(PREFIX)/usr/bin MANDIR = $(PREFIX)/usr/share/man/man1 -INSTALLTARGET = $(DESTDIR)/$(BINDIR)/$(TARGET) -MANTARGET = $(DESTDIR)/$(MANDIR)/$(MANPAGE) +INSTALLBINDIR = $(DESTDIR)$(BINDIR) +INSTALLMANDIR = $(DESTDIR)$(MANDIR) ifeq ($(XATTR_AVAILABLE),0) $(warning "xattr not available: disabling") @@ -98,7 +99,7 @@ ifeq ($(KERNEL),Darwin) CFLAGS += -DOSX endif -all: $(TARGET) +all: $(TARGET) clonepath help: @echo "usage: make" @@ -107,6 +108,9 @@ help: $(TARGET): obj/obj-stamp $(OBJ) $(CXX) $(CFLAGS) $(OBJ) -o $@ $(LDFLAGS) +clonepath: $(TARGET) + $(LN) -s $< $@ + changelog: $(GIT) log --pretty --numstat --summary | git2cl > ChangeLog @@ -118,22 +122,37 @@ obj/%.o: src/%.cpp $(CXX) $(CFLAGS) -c $< -o $@ clean: - $(RM) -rf obj "$(TARGET)" "$(MANPAGE)" + $(RM) -rf obj + $(RM) -f "$(TARGET)" "$(MANPAGE)" clonepath $(FIND) -name "*~" -delete distclean: clean $(GIT) clean -fd -install: $(TARGET) $(MANPAGE) - $(INSTALL) -m 0755 -D "$(TARGET)" "$(INSTALLTARGET)" - $(INSTALL) -m 0644 -D "$(MANPAGE)" "$(MANTARGET)" +install: install-base install-clonepath install-man + +install-base: $(TARGET) + $(INSTALL) -v -m 0755 -D "$(TARGET)" "$(INSTALLBINDIR)/$(TARGET)" + +install-clonepath: clonepath + $(CP) -a $< "$(INSTALLBINDIR)/$<" + +install-man: $(MANPAGE) + $(INSTALL) -v -m 0644 -D "$(MANPAGE)" "$(INSTALLMANDIR)/$(MANPAGE)" + +install-strip: install-base + $(STRIP) "$(INSTALLBINDIR)/$(TARGET)" + +uninstall: uninstall-base uninstall-clonepath uninstall-man + +uninstall-base: + $(RM) -f "$(INSTALLBINDIR)/$(TARGET)" -install-strip: install - $(STRIP) "$(INSTALLTARGET)" +uninstall-clonepath: + $(RM) -f "$(INSTALLBINDIR)/clonepath" -uninstall: - $(RM) "$(INSTALLTARGET)" - $(RM) "$(MANTARGET)" +uninstall-man: + $(RM) -f "$(INSTALLMANDIR)/$(MANPAGE") $(MANPAGE): README.md $(PANDOC) -s -t man -o $(MANPAGE) README.md diff --git a/src/clonepath.cpp b/src/clonepath.cpp new file mode 100644 index 00000000..c8ef9aee --- /dev/null +++ b/src/clonepath.cpp @@ -0,0 +1,54 @@ +/* + The MIT License (MIT) + + Copyright (c) 2014 Antonio SJ Musumeci + + 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. + */ + +#include + +#include + +#include "fs.hpp" + +namespace clonepath +{ + static + void + print_usage_and__exit(void) + { + std::cerr << "usage: clonepath " + << " " + << std::endl; + _exit(1); + } + + int + main(const int argc, + char * const argv[]) + { + if(argc != 4) + print_usage_and__exit(); + + return fs::clonepath(argv[1], + argv[2], + argv[3]); + } +} diff --git a/src/clonepath.hpp b/src/clonepath.hpp new file mode 100644 index 00000000..07a80d31 --- /dev/null +++ b/src/clonepath.hpp @@ -0,0 +1,30 @@ +/* + The MIT License (MIT) + + Copyright (c) 2014 Antonio SJ Musumeci + + 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. + */ + +namespace clonepath +{ + int + main(const int argc, + char * const *argv); +} diff --git a/src/mergerfs.cpp b/src/mergerfs.cpp index d4e01693..1f35f95e 100644 --- a/src/mergerfs.cpp +++ b/src/mergerfs.cpp @@ -33,6 +33,8 @@ #include "resources.hpp" #include "fs.hpp" +#include "clonepath.hpp" + #include "access.hpp" #include "chmod.hpp" #include "chown.hpp" @@ -73,6 +75,14 @@ namespace local { + static + std::string + getappname(const int argc, + char * const *argv) + { + return fs::basename(argv[0]); + } + static void get_fuse_operations(struct fuse_operations &ops) @@ -179,9 +189,11 @@ int main(int argc, char **argv) { - int rv; + std::string appname; - rv = mergerfs::main(argc,argv); + appname = local::getappname(argc,argv); + if(appname == "clonepath") + return clonepath::main(argc,argv); - return rv; + return mergerfs::main(argc,argv); } From 6276ce9779935ed6db8497c31fbeca257f335f04 Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Tue, 27 Jan 2015 18:54:35 -0500 Subject: [PATCH 3/4] handle EEXIST while cloning a path. closes #40 --- src/fs.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/fs.cpp b/src/fs.cpp index d6619da6..783a6852 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -424,7 +424,14 @@ namespace fs topath = fs::make_path(tosrc,relative); rv = ::mkdir(topath.c_str(),st.st_mode); if(rv == -1) - return -1; + { + if(errno != EEXIST) + return -1; + + rv = ::chmod(topath.c_str(),st.st_mode); + if(rv == -1) + return -1; + } rv = ::chown(topath.c_str(),st.st_uid,st.st_gid); if(rv == -1) From c2cbb93c25d738fadf589bc99e83761bcebdedd5 Mon Sep 17 00:00:00 2001 From: Antonio SJ Musumeci Date: Thu, 29 Jan 2015 00:24:57 -0500 Subject: [PATCH 4/4] elevate privileges when calling clonepath. closes #41 --- src/create.cpp | 5 ++++- src/link.cpp | 6 +++++- src/mkdir.cpp | 5 ++++- src/mknod.cpp | 5 ++++- 4 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/create.cpp b/src/create.cpp index 978fa55b..77dead4c 100644 --- a/src/create.cpp +++ b/src/create.cpp @@ -70,7 +70,10 @@ _create(const fs::SearchFunc searchFunc, return -errno; if(createpath[0].base != existingpath[0].base) - fs::clonepath(existingpath[0].base,createpath[0].base,dirname); + { + const mergerfs::ugid::SetResetGuard ugid(0,0); + fs::clonepath(existingpath[0].base,createpath[0].base,dirname); + } path = fs::make_path(createpath[0].base,fusepath); diff --git a/src/link.cpp b/src/link.cpp index 13c0f893..bc85de29 100644 --- a/src/link.cpp +++ b/src/link.cpp @@ -73,7 +73,11 @@ _link(const fs::SearchFunc searchFunc, fs::find::ffwp(srcmounts,todir,topaths); if(topaths.size() > 0) { - fs::clonepath(topaths[0].base,i->base,todir); + { + const mergerfs::ugid::SetResetGuard ugid(0,0); + fs::clonepath(topaths[0].base,i->base,todir); + } + lrv = ::link(pathfrom.c_str(),pathto.c_str()); } } diff --git a/src/mkdir.cpp b/src/mkdir.cpp index a6b7dd13..9ee2b36a 100644 --- a/src/mkdir.cpp +++ b/src/mkdir.cpp @@ -64,7 +64,10 @@ _mkdir(const fs::SearchFunc searchFunc, rv = createPathFunc(srcmounts,dirname,createpath); if(createpath[0].base != existingpath[0].base) - fs::clonepath(existingpath[0].base,createpath[0].base,dirname); + { + const mergerfs::ugid::SetResetGuard ugid(0,0); + fs::clonepath(existingpath[0].base,createpath[0].base,dirname); + } path = fs::make_path(createpath[0].base,fusepath); diff --git a/src/mknod.cpp b/src/mknod.cpp index 19f1f997..a5a4b005 100644 --- a/src/mknod.cpp +++ b/src/mknod.cpp @@ -66,7 +66,10 @@ _mknod(const fs::SearchFunc searchFunc, createPathFunc(srcmounts,dirname,createpath); if(existingpath[0].base != createpath[0].base) - fs::clonepath(existingpath[0].base,createpath[0].base,dirname); + { + const mergerfs::ugid::SetResetGuard ugid(0,0); + fs::clonepath(existingpath[0].base,createpath[0].base,dirname); + } path = fs::make_path(createpath[0].base,fusepath);