1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-25 19:01:16 +02:00

Add makeParentCanonical()

(cherry picked from commit 69853c067c)
This commit is contained in:
Robert Hensing 2024-12-13 18:37:25 +01:00 committed by Mergify
parent 8abff3cf05
commit 0213f22650
3 changed files with 44 additions and 0 deletions

View file

@ -765,4 +765,19 @@ bool isExecutableFileAmbient(const fs::path & exe) {
) == 0; ) == 0;
} }
std::filesystem::path makeParentCanonical(const std::filesystem::path & rawPath)
{
std::filesystem::path path(absPath(rawPath));;
try {
auto parent = path.parent_path();
if (parent == path) {
// `path` is a root directory => trivially canonical
return parent;
} }
return std::filesystem::canonical(parent) / path.filename();
} catch (fs::filesystem_error & e) {
throw SysError("canonicalising parent path of '%1%'", path);
}
}
} // namespace nix

View file

@ -143,6 +143,23 @@ inline bool symlink_exists(const std::filesystem::path & path) {
} // namespace fs } // namespace fs
/**
* 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.
* `makeParentCanonical("foo/l")` will not resolve the symlink `l` to its target,
* but does ensure that the returned parent part of the path, `foo` is resolved
* to `canonical("foo")`, and can therefore be retrieved without traversing any
* symlinks.
*
* If a relative path is passed, it will be made absolute, so that the parent
* can always be canonicalized.
*/
std::filesystem::path makeParentCanonical(const std::filesystem::path & path);
/** /**
* A version of pathExists that returns false on a permission error. * A version of pathExists that returns false on a permission error.
* Useful for inferring default paths across directories that might not * Useful for inferring default paths across directories that might not

View file

@ -50,6 +50,18 @@ struct PosixSourceAccessor : virtual SourceAccessor
* possible, (e.g. on Windows it could scoped to a drive like * possible, (e.g. on Windows it could scoped to a drive like
* `C:\`). This allows more `..` parent accessing to work. * `C:\`). This allows more `..` parent accessing to work.
* *
* @note When `path` is trusted user input, canonicalize it using
* `std::filesystem::canonical`, `makeParentCanonical`, `std::filesystem::weakly_canonical`, etc,
* as appropriate for the use case. At least weak canonicalization is
* required for the `SourcePath` to do anything useful at the location it
* points to.
*
* @note A canonicalizing behavior is not built in `createAtRoot` so that
* callers do not accidentally introduce symlink-related security vulnerabilities.
* Furthermore, `createAtRoot` does not know whether the file pointed to by
* `path` should be resolved if it is itself a symlink. In other words,
* `createAtRoot` can not decide between aforementioned `canonical`, `makeParentCanonical`, etc. for its callers.
*
* See * See
* [`std::filesystem::path::root_path`](https://en.cppreference.com/w/cpp/filesystem/path/root_path) * [`std::filesystem::path::root_path`](https://en.cppreference.com/w/cpp/filesystem/path/root_path)
* and * and