aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKaren Arutyunov <karen@codesynthesis.com>2020-03-15 17:03:49 +0300
committerKaren Arutyunov <karen@codesynthesis.com>2020-03-17 13:27:37 +0300
commit34466f10506fd57836e89cffda7738c3008321b1 (patch)
tree1c4408885403a303e85a39d883399eca1aff05a5
parent955afeb419ed02a078b45312949767692751274c (diff)
Fix mkanylink() to complete relative target against link directory when create hardlink or copy
-rw-r--r--libbutl/builtin.cxx4
-rw-r--r--libbutl/command.cxx2
-rw-r--r--libbutl/command.mxx2
-rw-r--r--libbutl/filesystem.cxx20
-rw-r--r--libbutl/filesystem.mxx4
5 files changed, 23 insertions, 9 deletions
diff --git a/libbutl/builtin.cxx b/libbutl/builtin.cxx
index f1b6b63..9efa697 100644
--- a/libbutl/builtin.cxx
+++ b/libbutl/builtin.cxx
@@ -277,7 +277,7 @@ namespace butl
}
// Return the current working directory if wd is empty and wd otherwise,
- // completed against the current directory if it is relative. Fail if
+ // completed using the current directory if it is relative. Fail if
// std::system_error is thrown by the underlying function call.
//
dir_path
@@ -779,7 +779,7 @@ namespace butl
assert (link.absolute () && link.normalized ());
// Determine the target type, fail if the target doesn't exist. Note that
- // to do that we need to complete a relative target path against the link
+ // to do that we need to complete a relative target path using the link
// directory making the target path absolute.
//
const path& atp (target.relative ()
diff --git a/libbutl/command.cxx b/libbutl/command.cxx
index 8dcfd05..bb5287c 100644
--- a/libbutl/command.cxx
+++ b/libbutl/command.cxx
@@ -137,7 +137,7 @@ namespace butl
// Sort the remaining command line elements into the arguments and
// redirects, performing the substitutions. Complete relative redirects
- // against CWD and use the rightmost redirect.
+ // using CWD and use the rightmost redirect.
//
vector<string> args;
diff --git a/libbutl/command.mxx b/libbutl/command.mxx
index b215817..02c8eb8 100644
--- a/libbutl/command.mxx
+++ b/libbutl/command.mxx
@@ -55,7 +55,7 @@ LIBBUTL_MODEXPORT namespace butl
// possible substitutions (so the redirect character cannot be the result of
// a substitution; see below).
//
- // The relative redirect file paths are completed against the command
+ // The relative redirect file paths are completed using the command
// current working directory. Note that if it is altered via the process
// environment, then the new value is used.
//
diff --git a/libbutl/filesystem.cxx b/libbutl/filesystem.cxx
index fa36ed3..4698ed9 100644
--- a/libbutl/filesystem.cxx
+++ b/libbutl/filesystem.cxx
@@ -1453,9 +1453,11 @@ namespace butl
{
using error = pair<entry_type, system_error>;
+ const path& tp (rel ? target.relative (link.directory ()) : target);
+
try
{
- mksymlink (rel ? target.relative (link.directory ()) : target, link);
+ mksymlink (tp, link);
return entry_type::symlink;
}
catch (system_error& e)
@@ -1469,9 +1471,19 @@ namespace butl
if (c == ENOSYS || // Not implemented.
c == EPERM) // Not supported by the filesystem(s).
{
+ // Note that for hardlinking/copying we need to complete a relative
+ // target using the link directory.
+ //
+ const path& ctp (tp.relative () ? link.directory () / tp : tp);
+
try
{
- mkhardlink (target, link);
+ // The target can be a symlink (or a symlink chain) with a
+ // relative target that, unless the (final) symlink and the
+ // hardlink are in the same directory, will result in a dangling
+ // link.
+ //
+ mkhardlink (followsymlink (ctp), link);
return entry_type::other;
}
catch (system_error& e)
@@ -1485,7 +1497,7 @@ namespace butl
{
try
{
- cpfile (target, link);
+ cpfile (ctp, link);
return entry_type::regular;
}
catch (system_error& e)
@@ -2416,7 +2428,7 @@ namespace butl
recursive_dir_iterator (recursive_dir_iterator&&) = default;
// Return false if no more entries left. Otherwise save the next entry path
- // and return true. The path is relative against the directory being
+ // and return true. The path is relative to the directory being
// traversed and contains a trailing separator for sub-directories. Throw
// std::system_error in case of a failure (insufficient permissions,
// dangling symlink encountered, etc).
diff --git a/libbutl/filesystem.mxx b/libbutl/filesystem.mxx
index a445b70..94ed366 100644
--- a/libbutl/filesystem.mxx
+++ b/libbutl/filesystem.mxx
@@ -362,7 +362,9 @@ LIBBUTL_MODEXPORT namespace butl
// no directories, only files), whichever is possible in that order. If
// `relative` is true, then make the symlink target relative to the link
// directory (note: it is the caller's responsibility to make sure this is
- // possible).
+ // possible). Otherwise, assume a relative target to be relative to the
+ // link directory and complete it accordingly when create a hardlink or a
+ // copy.
//
// On success, return the type of entry created: `regular` for copy,
// `symlink` for symlink, and `other` for hardlink. On failure, throw a