Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/windirstat/llfio.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorJenkins nedprod CI <jenkins-nedprod@europe5.nedproductions.biz>2020-07-09 02:00:12 +0300
committerJenkins nedprod CI <jenkins-nedprod@europe5.nedproductions.biz>2020-07-09 02:00:12 +0300
commit9050f5c8446e147ea5ed1f1470da6cd40f8d883a (patch)
treea9bd37df2f06fde417df9926a0acc59a3eb0f68c
parentd78c59d3d968f025fca67103cd90a5c08e13dc25 (diff)
parent87e87e998e59703610b8a17e5a7e5d12cb3d1242 (diff)
Merged from develop branch as CDash reports all green
-rw-r--r--include/llfio/revision.hpp6
-rw-r--r--include/llfio/v2.0/algorithm/clone.hpp35
-rw-r--r--include/llfio/v2.0/detail/impl/clone.ipp25
3 files changed, 51 insertions, 15 deletions
diff --git a/include/llfio/revision.hpp b/include/llfio/revision.hpp
index bafbaa31..bbd5205c 100644
--- a/include/llfio/revision.hpp
+++ b/include/llfio/revision.hpp
@@ -1,4 +1,4 @@
// Note the second line of this file must ALWAYS be the git SHA, third line ALWAYS the git SHA update time
-#define LLFIO_PREVIOUS_COMMIT_REF 07068de54ae723c8e4e3d9c91fde97ee378ccad2
-#define LLFIO_PREVIOUS_COMMIT_DATE "2020-07-03 19:01:39 +00:00"
-#define LLFIO_PREVIOUS_COMMIT_UNIQUE 07068de5
+#define LLFIO_PREVIOUS_COMMIT_REF cc0e5e5ad9c04b23aadfc8eed704b2c2194292ea
+#define LLFIO_PREVIOUS_COMMIT_DATE "2020-07-08 12:34:00 +00:00"
+#define LLFIO_PREVIOUS_COMMIT_UNIQUE cc0e5e5a
diff --git a/include/llfio/v2.0/algorithm/clone.hpp b/include/llfio/v2.0/algorithm/clone.hpp
index fbfade35..570ef089 100644
--- a/include/llfio/v2.0/algorithm/clone.hpp
+++ b/include/llfio/v2.0/algorithm/clone.hpp
@@ -45,7 +45,10 @@ namespace algorithm
the original to the clone/copy as possible.
\param force_copy_now Parameter to pass to `file_handle::clone_extents()` to force
extents to be copied now, not copy-on-write lazily later.
- \param creation How to create the destination file handle.
+ \param creation How to create the destination file handle. NOTE that if this
+ is NOT `always_new`, if the destination has identical maximum extent and
+ timestamps (and permissions on POSIX) to the source, it is NOT copied, and
+ zero is returned.
\param d Deadline by which to complete the operation.
Firstly, a `file_handle` is constructed at the destination using `creation`,
@@ -76,6 +79,7 @@ namespace algorithm
bool preserve_timestamps = true, bool force_copy_now = false,
file_handle::creation creation = file_handle::creation::always_new,
deadline d = {}) noexcept;
+
#if 0
#ifdef _MSC_VER
#pragma warning(push)
@@ -98,17 +102,24 @@ namespace algorithm
clone, //!< File content is to be extents cloned when possible
copy, //!< File content is to copied now into its destination
link, //!< File content is to be hard linked into its destination
- symlink //! File content is to be symlinked into its destination
- } op;
+ symlink //!< File content is to be symlinked into its destination
+ } op{op_t::clone};
+ bool always_create_new_files{false};
bool follow_symlinks{false};
std::chrono::steady_clock::duration timeout{std::chrono::seconds(10)};
std::chrono::steady_clock::time_point begin;
+ //! Default constructor
+ clone_copy_link_symlink_visitor() = default;
//! Constructs an instance with the default timeout of ten seconds.
- constexpr clone_copy_link_symlink_visitor(op_t _op, bool _follow_symlinks = false) : op(_op), follow_symlinks(_follow_symlinks) {}
+ constexpr clone_copy_link_symlink_visitor(op_t _op, bool _always_create_new_files = false, bool _follow_symlinks = false) : op(_op), always_create_new_files(_always_create_new_files), follow_symlinks(_follow_symlinks) {}
//! Constructs an instance with the specified timeout.
- constexpr explicit clone_copy_link_symlink_visitor(op_t _op, std::chrono::steady_clock::duration _timeout, bool _follow_symlinks = false)
- : op(_op), follow_symlinks(_follow_symlinks), timeout(_timeout)
+ constexpr explicit clone_copy_link_symlink_visitor(op_t _op, std::chrono::steady_clock::duration _timeout, bool _always_create_new_files = false,
+ bool _follow_symlinks = false)
+ : op(_op)
+ , always_create_new_files(_always_create_new_files)
+ , follow_symlinks(_follow_symlinks)
+ , timeout(_timeout)
{
}
@@ -149,9 +160,17 @@ namespace algorithm
would exceed the free disc space on the destination volume, the destination is removed
and an error code is returned comparing equal to `errc::no_space_on_device`.
- Otherwise, for every file in the source, its contents are cloned with `emulate_if_unsupported = true`
+ Otherwise, for every file in the source, its contents are cloned with `clone_or_copy()`
into an equivalent file in the destination. This means that the contents are either
- cloned or copied to the best extent of your filesystems and kernel.
+ cloned or copied to the best extent of your filesystems and kernel. If failure occurs
+ during this stage, the destination is left as-is in a partially copied state.
+
+ Note the default visitor parameters: Extent cloning is preferred, we do nothing
+ if destination file maximum extent and timestamps are identical to source, we don't
+ follow symlinks, instead cloning the symlink itself.
+
+ Note also that files or directories in the destination which are not in the source
+ are left untouched.
You should review the documentation for `algorithm::traverse()`, as this algorithm is
entirely implemented using that algorithm.
diff --git a/include/llfio/v2.0/detail/impl/clone.ipp b/include/llfio/v2.0/detail/impl/clone.ipp
index 743f9e48..4ceb58e9 100644
--- a/include/llfio/v2.0/detail/impl/clone.ipp
+++ b/include/llfio/v2.0/detail/impl/clone.ipp
@@ -36,17 +36,34 @@ namespace algorithm
filesystem::path destleaf_;
if(destleaf.empty())
{
- OUTCOME_TRY(auto &&_, src.current_path());
- if(_.empty())
+ OUTCOME_TRY(destleaf_, src.current_path());
+ if(destleaf_.empty())
{
// Source has been deleted, so can't infer leafname
return errc::no_such_file_or_directory;
}
- destleaf_ = std::move(_);
destleaf = destleaf_;
}
stat_t stat(nullptr);
OUTCOME_TRY(stat.fill(src));
+ if(creation != file_handle::creation::always_new)
+ {
+ auto r = file_handle::file(destdir, destleaf, file_handle::mode::attr_read, file_handle::creation::open_existing);
+ if(r)
+ {
+ stat_t deststat(nullptr);
+ OUTCOME_TRY(deststat.fill(r.value()));
+ if((stat.st_type == deststat.st_type) && (stat.st_mtim == deststat.st_mtim) && (stat.st_ctim == deststat.st_ctim) &&
+ (stat.st_birthtim == deststat.st_birthtim) && (stat.st_size == deststat.st_size)
+#ifndef _WIN32
+ && (stat.st_perms == deststat.st_perms) && (stat.st_uid == deststat.st_uid) && (stat.st_gid == deststat.st_gid) && (stat.st_rdev == deststat.st_rdev)
+#endif
+ )
+ {
+ return 0; // nothing copied
+ }
+ }
+ }
OUTCOME_TRY(auto dest, file_handle::file(destdir, destleaf, file_handle::mode::write, creation, src.kernel_caching()));
bool failed = true;
auto undest = make_scope_exit([&]() noexcept {
@@ -76,7 +93,7 @@ namespace algorithm
{
return errc::no_space_on_device;
}
- OUTCOME_TRY(auto &&copied, src.clone_extents_to(dest, d, force_copy_now, true));
+ OUTCOME_TRY(auto copied, src.clone_extents_to(dest, d, force_copy_now, true));
failed = false;
return copied.length;
}