diff options
author | Karen Arutyunov <karen@codesynthesis.com> | 2020-03-15 17:03:49 +0300 |
---|---|---|
committer | Karen Arutyunov <karen@codesynthesis.com> | 2020-03-17 13:27:37 +0300 |
commit | 34466f10506fd57836e89cffda7738c3008321b1 (patch) | |
tree | 1c4408885403a303e85a39d883399eca1aff05a5 /libbutl/filesystem.cxx | |
parent | 955afeb419ed02a078b45312949767692751274c (diff) |
Fix mkanylink() to complete relative target against link directory when create hardlink or copy
Diffstat (limited to 'libbutl/filesystem.cxx')
-rw-r--r-- | libbutl/filesystem.cxx | 20 |
1 files changed, 16 insertions, 4 deletions
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). |