Skip to content

Commit

Permalink
Add fs::parent_canonical()
Browse files Browse the repository at this point in the history
  • Loading branch information
roberth committed Dec 13, 2024
1 parent f1187cb commit cd3d456
Show file tree
Hide file tree
Showing 2 changed files with 28 additions and 0 deletions.
15 changes: 15 additions & 0 deletions src/libutil/file-system.cc
Original file line number Diff line number Diff line change
Expand Up @@ -765,4 +765,19 @@ bool isExecutableFileAmbient(const fs::path & exe) {
) == 0;
}

namespace fs {

std::filesystem::path parent_canonical(const std::filesystem::path & path)
{
auto parent = path.parent_path();
if (parent == path) {
// `path` is a root directory => trivially canonical
return parent;
}
return std::filesystem::canonical(parent) / path.filename();
}

} // namespace nix::fs


} // namespace nix
13 changes: 13 additions & 0 deletions src/libutil/file-system.hh
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,19 @@ inline bool symlink_exists(const std::filesystem::path & path) {
return std::filesystem::exists(std::filesystem::symlink_status(path));
}

/**
* Canonicalize a path except for the last component.
*
* This is useful for getting the canonical location of a symlink.
*
* Consider the case where `foo/l` is a symlink. `canonical("foo/l")` will
* resolve the symlink `l` to its target.
* `parent_canonical("foo/l")` will not resolve the symlink `l` to its target,
* but does ensure that the returned parent path's parent equals its `canonical`,
* and can therefore be retrieved without traversing any symlinks.
*/
std::filesystem::path parent_canonical(const std::filesystem::path & path);

} // namespace fs

/**
Expand Down

0 comments on commit cd3d456

Please sign in to comment.