diff --git a/src/fs.cpp b/src/fs.cpp index 83dc6b22..5cae7eae 100644 --- a/src/fs.cpp +++ b/src/fs.cpp @@ -218,6 +218,13 @@ namespace fs return ::fcntl(fd,F_GETFL,0); } + int + setfl(const int fd, + const mode_t mode) + { + return ::fcntl(fd,F_SETFL,mode); + } + int mfs(const vector &basepaths, const uint64_t minfreespace, diff --git a/src/fs.hpp b/src/fs.hpp index b14d6b36..89bda70a 100644 --- a/src/fs.hpp +++ b/src/fs.hpp @@ -20,6 +20,7 @@ #include #include +#include #include namespace fs @@ -59,6 +60,8 @@ namespace fs void realpathize(vector &strs); int getfl(const int fd); + int setfl(const int fd, + const mode_t mode); int mfs(const vector &srcs, const uint64_t minfreespace, diff --git a/src/fs_base_mkstemp.hpp b/src/fs_base_mkstemp.hpp new file mode 100644 index 00000000..dcfa42a1 --- /dev/null +++ b/src/fs_base_mkstemp.hpp @@ -0,0 +1,50 @@ +/* + ISC License + + 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. +*/ + +#ifndef __FS_BASE_MKSTEMP_HPP__ +#define __FS_BASE_MKSTEMP_HPP__ + +#include +#include + +#include + +namespace fs +{ + static + inline + int + mkstemp(std::string &filepath) + { + int fd; + char buf[filepath.size()+8]; + + strcpy(buf,filepath.c_str()); + strcpy(buf+filepath.size(),".XXXXXX"); + + fd = ::mkstemp(buf); + if(fd == -1) + return -1; + + filepath = buf; + + return fd; + } +} + +#endif diff --git a/src/fs_movefile.cpp b/src/fs_movefile.cpp index b6174151..ac053087 100644 --- a/src/fs_movefile.cpp +++ b/src/fs_movefile.cpp @@ -15,6 +15,7 @@ */ #include +#include #include #include #include @@ -22,9 +23,12 @@ #include #include +#include "errno.hpp" #include "fs.hpp" #include "fs_base_open.hpp" #include "fs_base_close.hpp" +#include "fs_base_mkstemp.hpp" +#include "fs_base_rename.hpp" #include "fs_base_unlink.hpp" #include "fs_base_stat.hpp" #include "fs_clonefile.hpp" @@ -49,6 +53,7 @@ namespace fs string fusedir; string fdin_path; string fdout_path; + string fdout_temp; struct stat fdin_st; fdin = origfd; @@ -82,18 +87,22 @@ namespace fs return -1; fs::path::append(fdout_path,fusepath); - fdout = fs::open(fdout_path,fdin_flags|O_CREAT,fdin_st.st_mode); + fdout_temp = fdout_path; + fdout = fs::mkstemp(fdout_temp); if(fdout == -1) return -1; rv = fs::clonefile(fdin,fdout); if(rv == -1) - { - fs::close(fdin); - fs::close(fdout); - fs::unlink(fdout_path); - return -1; - } + goto cleanup; + + rv = fs::setfl(fdout,fdin_flags); + if(rv == -1) + goto cleanup; + + rv = fs::rename(fdout_temp,fdout_path); + if(rv == -1) + goto cleanup; // should we care if it fails? fs::unlink(fdin_path); @@ -103,5 +112,15 @@ namespace fs fs::close(fdout); return 0; + + cleanup: + rv = errno; + if(fdin != -1) + fs::close(fdin); + if(fdout != -1) + fs::close(fdout); + fs::unlink(fdout_temp); + errno = rv; + return -1; } }