mirror of https://github.com/trapexit/mergerfs.git
committed by
GitHub
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 665 additions and 647 deletions
-
9src/fs_attr.hpp
-
185src/fs_attr_linux.icpp
-
86src/fs_clonefile.cpp
-
25src/fs_clonefile.hpp
-
13src/fs_copydata.cpp
-
70src/fs_copydata_copy_file_range.cpp
-
7src/fs_copydata_copy_file_range.hpp
-
148src/fs_copydata_readwrite.cpp
-
6src/fs_copydata_readwrite.hpp
-
134src/fs_copyfile.cpp
-
19src/fs_copyfile.hpp
-
149src/fs_cow.cpp
-
58src/fs_fcntl.hpp
-
36src/fs_file_unchanged.hpp
-
180src/fs_movefile.cpp
-
147src/fs_movefile_and_open.cpp
-
18src/fs_movefile_and_open.hpp
-
2src/fsck_mergerfs.cpp
-
20src/fuse_write.cpp
@ -1,86 +0,0 @@ |
|||||
/*
|
|
||||
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link> |
|
||||
|
|
||||
Permission to use, copy, modify, and/or distribute this software for any |
|
||||
purpose with or without fee is hereby granted, provided that the above |
|
||||
copyright notice and this permission notice appear in all copies. |
|
||||
|
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
||||
*/ |
|
||||
|
|
||||
#include "fs_fstat.hpp"
|
|
||||
#include "fs_copydata.hpp"
|
|
||||
#include "fs_attr.hpp"
|
|
||||
#include "fs_xattr.hpp"
|
|
||||
#include "fs_fchown.hpp"
|
|
||||
#include "fs_fchmod.hpp"
|
|
||||
#include "fs_futimens.hpp"
|
|
||||
|
|
||||
|
|
||||
namespace l |
|
||||
{ |
|
||||
static |
|
||||
bool |
|
||||
ignorable_error(const int err_) |
|
||||
{ |
|
||||
switch(err_) |
|
||||
{ |
|
||||
case ENOTTY: |
|
||||
case ENOTSUP: |
|
||||
#if ENOTSUP != EOPNOTSUPP
|
|
||||
case EOPNOTSUPP: |
|
||||
#endif
|
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
return false; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
namespace fs |
|
||||
{ |
|
||||
int |
|
||||
clonefile(const int src_fd_, |
|
||||
const int dst_fd_) |
|
||||
{ |
|
||||
int rv; |
|
||||
struct stat src_st; |
|
||||
|
|
||||
rv = fs::fstat(src_fd_,&src_st); |
|
||||
if(rv < 0) |
|
||||
return -1; |
|
||||
|
|
||||
rv = fs::copydata(src_fd_,dst_fd_,src_st.st_size); |
|
||||
if(rv == -1) |
|
||||
return -1; |
|
||||
|
|
||||
// TODO: should not copy "immutable" flag till last
|
|
||||
rv = fs::attr::copy(src_fd_,dst_fd_); |
|
||||
if((rv == -1) && !l::ignorable_error(errno)) |
|
||||
return -1; |
|
||||
|
|
||||
rv = fs::xattr::copy(src_fd_,dst_fd_); |
|
||||
if((rv == -1) && !l::ignorable_error(errno)) |
|
||||
return -1; |
|
||||
|
|
||||
rv = fs::fchown_check_on_error(dst_fd_,src_st); |
|
||||
if(rv == -1) |
|
||||
return -1; |
|
||||
|
|
||||
rv = fs::fchmod_check_on_error(dst_fd_,src_st); |
|
||||
if(rv == -1) |
|
||||
return -1; |
|
||||
|
|
||||
rv = fs::futimens(dst_fd_,src_st); |
|
||||
if(rv == -1) |
|
||||
return -1; |
|
||||
|
|
||||
return 0; |
|
||||
} |
|
||||
} |
|
@ -1,25 +0,0 @@ |
|||||
/*
|
|
||||
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link> |
|
||||
|
|
||||
Permission to use, copy, modify, and/or distribute this software for any |
|
||||
purpose with or without fee is hereby granted, provided that the above |
|
||||
copyright notice and this permission notice appear in all copies. |
|
||||
|
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
||||
*/ |
|
||||
|
|
||||
#pragma once
|
|
||||
|
|
||||
|
|
||||
namespace fs |
|
||||
{ |
|
||||
int |
|
||||
clonefile(const int src_fd, |
|
||||
const int dst_fd); |
|
||||
} |
|
@ -1,39 +1,153 @@ |
|||||
#include "fs_copyfile.hpp"
|
#include "fs_copyfile.hpp"
|
||||
|
|
||||
#include "fs_clonefile.hpp"
|
|
||||
|
#include "fs_attr.hpp"
|
||||
#include "fs_close.hpp"
|
#include "fs_close.hpp"
|
||||
|
#include "fs_copydata.hpp"
|
||||
|
#include "fs_fchmod.hpp"
|
||||
|
#include "fs_fchown.hpp"
|
||||
|
#include "fs_fcntl.hpp"
|
||||
|
#include "fs_file_unchanged.hpp"
|
||||
|
#include "fs_fstat.hpp"
|
||||
|
#include "fs_futimens.hpp"
|
||||
#include "fs_mktemp.hpp"
|
#include "fs_mktemp.hpp"
|
||||
#include "fs_open.hpp"
|
#include "fs_open.hpp"
|
||||
#include "fs_rename.hpp"
|
#include "fs_rename.hpp"
|
||||
|
#include "fs_unlink.hpp"
|
||||
|
#include "fs_xattr.hpp"
|
||||
|
|
||||
#include "scope_guard.hpp"
|
#include "scope_guard.hpp"
|
||||
|
|
||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||
|
#include <signal.h>
|
||||
|
|
||||
|
|
||||
|
static |
||||
|
bool |
||||
|
_ignorable_error(const int err_) |
||||
|
{ |
||||
|
switch(err_) |
||||
|
{ |
||||
|
case ENOTTY: |
||||
|
case ENOTSUP: |
||||
|
#if ENOTSUP != EOPNOTSUPP
|
||||
|
case EOPNOTSUPP: |
||||
|
#endif
|
||||
|
return true; |
||||
|
} |
||||
|
|
||||
|
return false; |
||||
|
} |
||||
|
|
||||
|
int |
||||
|
fs::copyfile(const int src_fd_, |
||||
|
const struct stat &src_st_, |
||||
|
const int dst_fd_) |
||||
|
{ |
||||
|
int rv; |
||||
|
|
||||
|
rv = fs::copydata(src_fd_,dst_fd_,src_st_.st_size); |
||||
|
if(rv == -1) |
||||
|
return -1; |
||||
|
|
||||
|
rv = fs::xattr::copy(src_fd_,dst_fd_); |
||||
|
if((rv == -1) && !::_ignorable_error(errno)) |
||||
|
return -1; |
||||
|
|
||||
|
rv = fs::attr::copy(src_fd_,dst_fd_,FS_ATTR_CLEAR_IMMUTABLE); |
||||
|
if((rv == -1) && !::_ignorable_error(errno)) |
||||
|
return -1; |
||||
|
|
||||
|
rv = fs::fchown_check_on_error(dst_fd_,src_st_); |
||||
|
if(rv == -1) |
||||
|
return -1; |
||||
|
|
||||
|
rv = fs::fchmod_check_on_error(dst_fd_,src_st_); |
||||
|
if(rv == -1) |
||||
|
return -1; |
||||
|
|
||||
|
rv = fs::futimens(dst_fd_,src_st_); |
||||
|
if(rv == -1) |
||||
|
return -1; |
||||
|
|
||||
|
return 0; |
||||
|
} |
||||
|
|
||||
|
|
||||
|
|
||||
|
|
||||
|
// Limitations:
|
||||
|
// * Doesn't handle immutable files well. Will ignore the flag on attr
|
||||
|
// copy.
|
||||
|
// * Does not handle non-regular files.
|
||||
|
|
||||
int |
int |
||||
fs::copyfile(const std::filesystem::path &src_, |
fs::copyfile(const std::filesystem::path &src_, |
||||
const std::filesystem::path &dst_) |
|
||||
|
const std::filesystem::path &dst_, |
||||
|
const u32 flags_) |
||||
{ |
{ |
||||
int rv; |
int rv; |
||||
int src_fd; |
int src_fd; |
||||
int dst_fd; |
int dst_fd; |
||||
|
struct stat src_st = {0}; |
||||
std::string dst_tmppath; |
std::string dst_tmppath; |
||||
|
struct sigaction old_act; |
||||
|
struct sigaction new_act; |
||||
|
|
||||
|
// Done in case fcntl(F_SETLEASE) works.
|
||||
|
new_act.sa_handler = SIG_IGN; |
||||
|
new_act.sa_flags = 0; |
||||
|
sigemptyset(&new_act.sa_mask); |
||||
|
sigaction(SIGIO,&new_act,&old_act); |
||||
|
DEFER { sigaction(SIGIO,&old_act,NULL); }; |
||||
|
|
||||
src_fd = fs::open(src_,O_RDONLY|O_NOFOLLOW); |
src_fd = fs::open(src_,O_RDONLY|O_NOFOLLOW); |
||||
if(src_fd < 0) |
if(src_fd < 0) |
||||
return src_fd; |
return src_fd; |
||||
DEFER { fs::close(src_fd); }; |
DEFER { fs::close(src_fd); }; |
||||
|
|
||||
std::tie(dst_fd,dst_tmppath) = fs::mktemp(dst_,O_RDWR); |
|
||||
if(dst_fd < 0) |
|
||||
return dst_fd; |
|
||||
DEFER { fs::close(dst_fd); }; |
|
||||
|
while(true) |
||||
|
{ |
||||
|
std::tie(dst_fd,dst_tmppath) = fs::mktemp(dst_,O_RDWR); |
||||
|
if(dst_fd < 0) |
||||
|
return dst_fd; |
||||
|
DEFER { fs::close(dst_fd); }; |
||||
|
|
||||
|
// If it fails or is unsupported... so be it. This will help
|
||||
|
// limit the possibility of the file being modified while the
|
||||
|
// copy happens. Opening read-only is fine but open for write or
|
||||
|
// truncate will block for others till this finishes or the
|
||||
|
// kernel wide timeout (/proc/sys/fs/lease-break-time).
|
||||
|
fs::fcntl_setlease_rdlck(src_fd); |
||||
|
DEFER { fs::fcntl_setlease_unlck(src_fd); }; |
||||
|
|
||||
|
// For comparison after the copy to see if the file was
|
||||
|
// modified. This could be made more thorough by adding some
|
||||
|
// hashing but probably overkill. Also used to provide size and
|
||||
|
// other details for data copying.
|
||||
|
rv = fs::fstat(src_fd,&src_st); |
||||
|
if(rv < 0) |
||||
|
return rv; |
||||
|
|
||||
|
rv = fs::copyfile(src_fd,src_st,dst_fd); |
||||
|
if(rv < 0) |
||||
|
{ |
||||
|
if(flags_ & FS_COPYFILE_CLEANUP_FAILURE) |
||||
|
fs::unlink(dst_tmppath); |
||||
|
return rv; |
||||
|
} |
||||
|
|
||||
rv = fs::clonefile(src_fd,dst_fd); |
|
||||
if(rv < 0) |
|
||||
return rv; |
|
||||
|
rv = fs::file_changed(src_fd,src_st); |
||||
|
if(rv == FS_FILE_CHANGED) |
||||
|
{ |
||||
|
fs::unlink(dst_tmppath); |
||||
|
continue; |
||||
|
} |
||||
|
|
||||
rv = fs::rename(dst_tmppath,dst_); |
|
||||
|
rv = fs::rename(dst_tmppath,dst_); |
||||
|
if((rv < 0) && (flags_ & FS_COPYFILE_CLEANUP_FAILURE)) |
||||
|
fs::unlink(dst_tmppath); |
||||
|
break; |
||||
|
} |
||||
|
|
||||
return rv; |
return rv; |
||||
} |
} |
@ -1,9 +1,24 @@ |
|||||
#pragma once
|
#pragma once
|
||||
|
|
||||
|
#include "int_types.h"
|
||||
|
|
||||
#include <filesystem>
|
#include <filesystem>
|
||||
|
|
||||
|
#include <sys/stat.h>
|
||||
|
|
||||
|
#define FS_COPYFILE_NONE (0)
|
||||
|
#define FS_COPYFILE_CLEANUP_FAILURE (1 << 0)
|
||||
|
|
||||
|
|
||||
namespace fs |
namespace fs |
||||
{ |
{ |
||||
int copyfile(const std::filesystem::path &src, |
|
||||
const std::filesystem::path &dst); |
|
||||
|
int |
||||
|
copyfile(const int src_fd, |
||||
|
const struct stat &src_st, |
||||
|
const int dst_fd); |
||||
|
|
||||
|
int |
||||
|
copyfile(const std::filesystem::path &src, |
||||
|
const std::filesystem::path &dst, |
||||
|
const u32 flags); |
||||
} |
} |
@ -0,0 +1,58 @@ |
|||||
|
#pragma once
|
||||
|
|
||||
|
#include <fcntl.h>
|
||||
|
|
||||
|
namespace fs |
||||
|
{ |
||||
|
static |
||||
|
inline |
||||
|
int |
||||
|
fcntl(const int fd_, |
||||
|
const int op_) |
||||
|
{ |
||||
|
int rv; |
||||
|
|
||||
|
rv = ::fcntl(fd_,op_); |
||||
|
|
||||
|
return ((rv == -1) ? -errno : rv); |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
inline |
||||
|
int |
||||
|
fcntl(const int fd_, |
||||
|
const int op_, |
||||
|
const int arg_) |
||||
|
{ |
||||
|
int rv; |
||||
|
|
||||
|
rv = ::fcntl(fd_,op_,arg_); |
||||
|
|
||||
|
return ((rv == -1) ? -errno : rv); |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
inline |
||||
|
int |
||||
|
fcntl_setlease_rdlck(const int fd_) |
||||
|
{ |
||||
|
#if defined(F_SETLEASE) && defined(F_RDLCK)
|
||||
|
return fs::fcntl(fd_,F_SETLEASE,F_RDLCK); |
||||
|
#else
|
||||
|
return -ENOTSUP; |
||||
|
#endif
|
||||
|
} |
||||
|
|
||||
|
static |
||||
|
inline |
||||
|
int |
||||
|
fcntl_setlease_unlck(const int fd_) |
||||
|
{ |
||||
|
#if defined(F_SETLEASE) && defined(F_UNLCK)
|
||||
|
return fs::fcntl(fd_,F_SETLEASE,F_UNLCK); |
||||
|
#else
|
||||
|
return -ENOTSUP; |
||||
|
#endif
|
||||
|
|
||||
|
} |
||||
|
} |
@ -0,0 +1,36 @@ |
|||||
|
#pragma once
|
||||
|
|
||||
|
#include "fs_fstat.hpp"
|
||||
|
|
||||
|
#define FS_FILE_CHANGED 0
|
||||
|
#define FS_FILE_UNCHANGED 1
|
||||
|
|
||||
|
namespace fs |
||||
|
{ |
||||
|
static |
||||
|
inline |
||||
|
int |
||||
|
file_changed(const int fd_, |
||||
|
const struct stat &orig_st_) |
||||
|
{ |
||||
|
int rv; |
||||
|
struct stat new_st; |
||||
|
|
||||
|
rv = fs::fstat(fd_,&new_st); |
||||
|
if(rv < 0) |
||||
|
return rv; |
||||
|
|
||||
|
if(orig_st_.st_ino != new_st.st_ino) |
||||
|
return FS_FILE_CHANGED; |
||||
|
if(orig_st_.st_dev != new_st.st_dev) |
||||
|
return FS_FILE_CHANGED; |
||||
|
if(orig_st_.st_size != new_st.st_size) |
||||
|
return FS_FILE_CHANGED; |
||||
|
if(orig_st_.st_mtim.tv_sec != new_st.st_mtim.tv_sec) |
||||
|
return FS_FILE_CHANGED; |
||||
|
if(orig_st_.st_mtim.tv_nsec != new_st.st_mtim.tv_nsec) |
||||
|
return FS_FILE_CHANGED; |
||||
|
|
||||
|
return FS_FILE_UNCHANGED; |
||||
|
} |
||||
|
} |
@ -1,180 +0,0 @@ |
|||||
/*
|
|
||||
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link> |
|
||||
|
|
||||
Permission to use, copy, modify, and/or distribute this software for any |
|
||||
purpose with or without fee is hereby granted, provided that the above |
|
||||
copyright notice and this permission notice appear in all copies. |
|
||||
|
|
||||
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|
||||
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|
||||
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
|
||||
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|
||||
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
|
||||
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
|
||||
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|
||||
*/ |
|
||||
|
|
||||
#include "errno.hpp"
|
|
||||
#include "fs_clonefile.hpp"
|
|
||||
#include "fs_clonepath.hpp"
|
|
||||
#include "fs_close.hpp"
|
|
||||
#include "fs_file_size.hpp"
|
|
||||
#include "fs_findonfs.hpp"
|
|
||||
#include "fs_getfl.hpp"
|
|
||||
#include "fs_has_space.hpp"
|
|
||||
#include "fs_mktemp.hpp"
|
|
||||
#include "fs_open.hpp"
|
|
||||
#include "fs_path.hpp"
|
|
||||
#include "fs_rename.hpp"
|
|
||||
#include "fs_stat.hpp"
|
|
||||
#include "fs_unlink.hpp"
|
|
||||
#include "policy.hpp"
|
|
||||
#include "ugid.hpp"
|
|
||||
|
|
||||
#include <string>
|
|
||||
#include <vector>
|
|
||||
|
|
||||
#include <fcntl.h>
|
|
||||
#include <stdlib.h>
|
|
||||
#include <sys/stat.h>
|
|
||||
#include <sys/types.h>
|
|
||||
#include <unistd.h>
|
|
||||
|
|
||||
|
|
||||
static |
|
||||
int |
|
||||
cleanup_flags(const int flags_) |
|
||||
{ |
|
||||
int rv; |
|
||||
|
|
||||
rv = flags_; |
|
||||
rv = (rv & ~O_TRUNC); |
|
||||
rv = (rv & ~O_CREAT); |
|
||||
rv = (rv & ~O_EXCL); |
|
||||
|
|
||||
return rv; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
namespace l |
|
||||
{ |
|
||||
static |
|
||||
int |
|
||||
movefile(const Policy::Create &createFunc_, |
|
||||
const Branches::Ptr &branches_, |
|
||||
const std::string &fusepath_, |
|
||||
int origfd_) |
|
||||
{ |
|
||||
int rv; |
|
||||
int srcfd; |
|
||||
int dstfd; |
|
||||
int dstfd_flags; |
|
||||
int origfd_flags; |
|
||||
int64_t srcfd_size; |
|
||||
std::string fusedir; |
|
||||
std::string srcfd_branch; |
|
||||
std::string srcfd_filepath; |
|
||||
std::string dstfd_filepath; |
|
||||
std::string dstfd_tmp_filepath; |
|
||||
std::vector<Branch*> dstfd_branch; |
|
||||
|
|
||||
srcfd = -1; |
|
||||
dstfd = -1; |
|
||||
|
|
||||
rv = fs::findonfs(branches_,fusepath_,origfd_,&srcfd_branch); |
|
||||
if(rv == -1) |
|
||||
return -errno; |
|
||||
|
|
||||
rv = createFunc_(branches_,fusepath_.c_str(),dstfd_branch); |
|
||||
if(rv == -1) |
|
||||
return -errno; |
|
||||
|
|
||||
origfd_flags = fs::getfl(origfd_); |
|
||||
if(origfd_flags == -1) |
|
||||
return -errno; |
|
||||
|
|
||||
srcfd_size = fs::file_size(origfd_); |
|
||||
if(srcfd_size == -1) |
|
||||
return -errno; |
|
||||
|
|
||||
if(fs::has_space(dstfd_branch[0]->path,srcfd_size) == false) |
|
||||
return -ENOSPC; |
|
||||
|
|
||||
fusedir = fs::path::dirname(fusepath_); |
|
||||
|
|
||||
rv = fs::clonepath(srcfd_branch,dstfd_branch[0]->path,fusedir); |
|
||||
if(rv == -1) |
|
||||
return -ENOSPC; |
|
||||
|
|
||||
srcfd_filepath = srcfd_branch; |
|
||||
fs::path::append(srcfd_filepath,fusepath_); |
|
||||
srcfd = fs::open(srcfd_filepath,O_RDONLY); |
|
||||
if(srcfd == -1) |
|
||||
return -ENOSPC; |
|
||||
|
|
||||
dstfd_filepath = dstfd_branch[0]->path; |
|
||||
fs::path::append(dstfd_filepath,fusepath_); |
|
||||
std::tie(dstfd,dstfd_tmp_filepath) = fs::mktemp(dstfd_filepath,O_WRONLY); |
|
||||
if(dstfd < 0) |
|
||||
{ |
|
||||
fs::close(srcfd); |
|
||||
return -ENOSPC; |
|
||||
} |
|
||||
|
|
||||
rv = fs::clonefile(srcfd,dstfd); |
|
||||
if(rv == -1) |
|
||||
{ |
|
||||
fs::close(srcfd); |
|
||||
fs::close(dstfd); |
|
||||
fs::unlink(dstfd_tmp_filepath); |
|
||||
return -ENOSPC; |
|
||||
} |
|
||||
|
|
||||
rv = fs::rename(dstfd_tmp_filepath,dstfd_filepath); |
|
||||
if(rv == -1) |
|
||||
{ |
|
||||
fs::close(srcfd); |
|
||||
fs::close(dstfd); |
|
||||
fs::unlink(dstfd_tmp_filepath); |
|
||||
return -ENOSPC; |
|
||||
} |
|
||||
|
|
||||
fs::close(srcfd); |
|
||||
fs::close(dstfd); |
|
||||
|
|
||||
dstfd_flags = ::cleanup_flags(origfd_flags); |
|
||||
rv = fs::open(dstfd_filepath,dstfd_flags); |
|
||||
if(rv == -1) |
|
||||
{ |
|
||||
fs::unlink(dstfd_tmp_filepath); |
|
||||
return -ENOSPC; |
|
||||
} |
|
||||
|
|
||||
fs::unlink(srcfd_filepath); |
|
||||
|
|
||||
return rv; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
namespace fs |
|
||||
{ |
|
||||
int |
|
||||
movefile(const Policy::Create &policy_, |
|
||||
const Branches::Ptr &basepaths_, |
|
||||
const std::string &fusepath_, |
|
||||
int origfd_) |
|
||||
{ |
|
||||
return l::movefile(policy_,basepaths_,fusepath_,origfd_); |
|
||||
} |
|
||||
|
|
||||
int |
|
||||
movefile_as_root(const Policy::Create &policy_, |
|
||||
const Branches::Ptr &basepaths_, |
|
||||
const std::string &fusepath_, |
|
||||
int origfd_) |
|
||||
{ |
|
||||
const ugid::Set ugid(0,0); |
|
||||
|
|
||||
return fs::movefile(policy_,basepaths_,fusepath_,origfd_); |
|
||||
} |
|
||||
} |
|
@ -0,0 +1,147 @@ |
|||||
|
/*
|
||||
|
Copyright (c) 2016, Antonio SJ Musumeci <trapexit@spawn.link> |
||||
|
|
||||
|
Permission to use, copy, modify, and/or distribute this software for any |
||||
|
purpose with or without fee is hereby granted, provided that the above |
||||
|
copyright notice and this permission notice appear in all copies. |
||||
|
|
||||
|
THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
||||
|
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
||||
|
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR |
||||
|
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
||||
|
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN |
||||
|
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF |
||||
|
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
||||
|
*/ |
||||
|
|
||||
|
#include "fs_movefile_and_open.hpp"
|
||||
|
|
||||
|
#include "errno.hpp"
|
||||
|
#include "fs_clonepath.hpp"
|
||||
|
#include "fs_close.hpp"
|
||||
|
#include "fs_copyfile.hpp"
|
||||
|
#include "fs_file_size.hpp"
|
||||
|
#include "fs_findonfs.hpp"
|
||||
|
#include "fs_getfl.hpp"
|
||||
|
#include "fs_has_space.hpp"
|
||||
|
#include "fs_mktemp.hpp"
|
||||
|
#include "fs_open.hpp"
|
||||
|
#include "fs_path.hpp"
|
||||
|
#include "fs_rename.hpp"
|
||||
|
#include "fs_stat.hpp"
|
||||
|
#include "fs_unlink.hpp"
|
||||
|
#include "int_types.h"
|
||||
|
#include "policy.hpp"
|
||||
|
#include "ugid.hpp"
|
||||
|
|
||||
|
#include <string>
|
||||
|
#include <vector>
|
||||
|
|
||||
|
#include <fcntl.h>
|
||||
|
#include <stdlib.h>
|
||||
|
#include <sys/stat.h>
|
||||
|
#include <sys/types.h>
|
||||
|
#include <unistd.h>
|
||||
|
|
||||
|
|
||||
|
static |
||||
|
int |
||||
|
_cleanup_flags(const int flags_) |
||||
|
{ |
||||
|
int rv; |
||||
|
|
||||
|
rv = flags_; |
||||
|
rv = (rv & ~O_TRUNC); |
||||
|
rv = (rv & ~O_CREAT); |
||||
|
rv = (rv & ~O_EXCL); |
||||
|
|
||||
|
return rv; |
||||
|
} |
||||
|
|
||||
|
static |
||||
|
int |
||||
|
_movefile_and_open(const Policy::Create &createFunc_, |
||||
|
const Branches::Ptr &branches_, |
||||
|
const std::string &branchpath_, |
||||
|
const std::string &fusepath_, |
||||
|
int origfd_) |
||||
|
{ |
||||
|
int rv; |
||||
|
int dstfd_flags; |
||||
|
int origfd_flags; |
||||
|
s64 src_size; |
||||
|
std::string fusedir; |
||||
|
std::string src_branch; |
||||
|
std::string src_filepath; |
||||
|
std::string dst_filepath; |
||||
|
std::vector<Branch*> dst_branch; |
||||
|
|
||||
|
src_branch = branchpath_; |
||||
|
|
||||
|
rv = createFunc_(branches_,fusepath_.c_str(),dst_branch); |
||||
|
if(rv == -1) |
||||
|
return -errno; |
||||
|
|
||||
|
origfd_flags = fs::getfl(origfd_); |
||||
|
if(origfd_flags == -1) |
||||
|
return -errno; |
||||
|
|
||||
|
src_size = fs::file_size(origfd_); |
||||
|
if(src_size == -1) |
||||
|
return -errno; |
||||
|
|
||||
|
if(fs::has_space(dst_branch[0]->path,src_size) == false) |
||||
|
return -ENOSPC; |
||||
|
|
||||
|
fusedir = fs::path::dirname(fusepath_); |
||||
|
|
||||
|
rv = fs::clonepath(src_branch,dst_branch[0]->path,fusedir); |
||||
|
if(rv == -1) |
||||
|
return -ENOSPC; |
||||
|
|
||||
|
src_filepath = fs::path::make(src_branch,fusepath_); |
||||
|
dst_filepath = fs::path::make(dst_branch[0]->path,fusepath_); |
||||
|
|
||||
|
rv = fs::copyfile(src_filepath,dst_filepath,FS_COPYFILE_CLEANUP_FAILURE); |
||||
|
if(rv < 0) |
||||
|
return -ENOSPC; |
||||
|
|
||||
|
dstfd_flags = ::_cleanup_flags(origfd_flags); |
||||
|
rv = fs::open(dst_filepath,dstfd_flags); |
||||
|
if(rv == -1) |
||||
|
return -ENOSPC; |
||||
|
|
||||
|
fs::unlink(src_filepath); |
||||
|
|
||||
|
return rv; |
||||
|
} |
||||
|
|
||||
|
int |
||||
|
fs::movefile_and_open(const Policy::Create &policy_, |
||||
|
const Branches::Ptr &branches_, |
||||
|
const std::string &branchpath_, |
||||
|
const std::string &fusepath_, |
||||
|
const int origfd_) |
||||
|
{ |
||||
|
return ::_movefile_and_open(policy_, |
||||
|
branches_, |
||||
|
branchpath_, |
||||
|
fusepath_, |
||||
|
origfd_); |
||||
|
} |
||||
|
|
||||
|
int |
||||
|
fs::movefile_and_open_as_root(const Policy::Create &policy_, |
||||
|
const Branches::Ptr &branches_, |
||||
|
const std::string &branchpath_, |
||||
|
const std::string &fusepath_, |
||||
|
const int origfd_) |
||||
|
{ |
||||
|
const ugid::Set ugid(0,0); |
||||
|
|
||||
|
return fs::movefile_and_open(policy_, |
||||
|
branches_, |
||||
|
branchpath_, |
||||
|
fusepath_, |
||||
|
origfd_); |
||||
|
} |
Write
Preview
Loading…
Cancel
Save
Reference in new issue