mirror of
https://github.com/NixOS/nix
synced 2025-06-25 14:51:16 +02:00
parent
8abff3cf05
commit
0213f22650
3 changed files with 44 additions and 0 deletions
|
@ -765,4 +765,19 @@ bool isExecutableFileAmbient(const fs::path & exe) {
|
|||
) == 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
|
||||
|
|
|
@ -143,6 +143,23 @@ inline bool symlink_exists(const std::filesystem::path & path) {
|
|||
|
||||
} // 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.
|
||||
* Useful for inferring default paths across directories that might not
|
||||
|
|
|
@ -50,6 +50,18 @@ struct PosixSourceAccessor : virtual SourceAccessor
|
|||
* possible, (e.g. on Windows it could scoped to a drive like
|
||||
* `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
|
||||
* [`std::filesystem::path::root_path`](https://en.cppreference.com/w/cpp/filesystem/path/root_path)
|
||||
* and
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue