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_clonefile.hpp"
|
|||
#include "fs_attr.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_open.hpp"
|
|||
#include "fs_rename.hpp"
|
|||
#include "fs_unlink.hpp"
|
|||
#include "fs_xattr.hpp"
|
|||
|
|||
#include "scope_guard.hpp"
|
|||
|
|||
#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 |
|||
fs::copyfile(const std::filesystem::path &src_, |
|||
const std::filesystem::path &dst_) |
|||
const std::filesystem::path &dst_, |
|||
const u32 flags_) |
|||
{ |
|||
int rv; |
|||
int src_fd; |
|||
int dst_fd; |
|||
struct stat src_st = {0}; |
|||
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); |
|||
if(src_fd < 0) |
|||
return 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; |
|||
} |
@ -1,9 +1,24 @@ |
|||
#pragma once
|
|||
|
|||
#include "int_types.h"
|
|||
|
|||
#include <filesystem>
|
|||
|
|||
#include <sys/stat.h>
|
|||
|
|||
#define FS_COPYFILE_NONE (0)
|
|||
#define FS_COPYFILE_CLEANUP_FAILURE (1 << 0)
|
|||
|
|||
|
|||
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