aboutsummaryrefslogtreecommitdiff
path: root/src/zencore
diff options
context:
space:
mode:
Diffstat (limited to 'src/zencore')
-rw-r--r--src/zencore/filesystem.cpp30
1 files changed, 30 insertions, 0 deletions
diff --git a/src/zencore/filesystem.cpp b/src/zencore/filesystem.cpp
index f117001b5..85f7690bd 100644
--- a/src/zencore/filesystem.cpp
+++ b/src/zencore/filesystem.cpp
@@ -624,6 +624,9 @@ CopyTree(std::filesystem::path FromPath, std::filesystem::path ToPath, const Cop
if (ToPath.empty())
throw std::runtime_error("no CopyTree target specified");
+ if (Options.MustClone && !SupportsBlockRefCounting(FromPath))
+ throw std::runtime_error(fmt::format("cloning not possible from '{}'", FromPath));
+
if (std::filesystem::exists(ToPath))
{
if (!std::filesystem::is_directory(ToPath))
@@ -636,6 +639,33 @@ CopyTree(std::filesystem::path FromPath, std::filesystem::path ToPath, const Cop
std::filesystem::create_directories(ToPath);
}
+ if (Options.MustClone && !SupportsBlockRefCounting(ToPath))
+ throw std::runtime_error(fmt::format("cloning not possible from '{}'", ToPath));
+
+ // Verify source/target relationships
+
+ std::error_code Ec;
+ std::filesystem::path FromCanonical = std::filesystem::canonical(FromPath, Ec);
+
+ if (!Ec)
+ {
+ std::filesystem::path ToCanonical = std::filesystem::canonical(ToPath, Ec);
+
+ if (!Ec)
+ {
+ if (FromCanonical == ToCanonical)
+ {
+ throw std::runtime_error("Target and source must be distinct files or directories");
+ }
+
+ if (ToCanonical.generic_string().starts_with(FromCanonical.generic_string()) ||
+ FromCanonical.generic_string().starts_with(ToCanonical.generic_string()))
+ {
+ throw std::runtime_error("Invalid parent/child relationship for source/target directories");
+ }
+ }
+ }
+
struct CopyVisitor : public FileSystemTraversal::TreeVisitor
{
CopyVisitor(std::filesystem::path InBasePath, zen::CopyFileOptions InCopyOptions) : BasePath(InBasePath), CopyOptions(InCopyOptions)