1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-09 12:06:01 +01:00

nix shell: Handle output paths that are symlinks

This requires moving resolveSymlinks() into SourceAccessor. Also, it
requires LocalStoreAccessor::maybeLstat() to work on parents of the
store (to avoid an error like "/nix is not in the store").

Fixes #10375.
This commit is contained in:
Eelco Dolstra 2024-04-10 23:46:19 +02:00
parent 021488497d
commit 85b9f4ef4f
8 changed files with 97 additions and 72 deletions

View file

@ -39,9 +39,9 @@ void SourceAccessor::readFile(
}
Hash SourceAccessor::hashPath(
const CanonPath & path,
PathFilter & filter,
HashAlgorithm ha)
const CanonPath & path,
PathFilter & filter,
HashAlgorithm ha)
{
HashSink sink(ha);
dumpPath(path, sink, filter);
@ -67,4 +67,42 @@ std::string SourceAccessor::showPath(const CanonPath & path)
return displayPrefix + path.abs() + displaySuffix;
}
CanonPath SourceAccessor::resolveSymlinks(
const CanonPath & path,
SymlinkResolution mode)
{
auto res = CanonPath::root;
int linksAllowed = 1024;
std::list<std::string> todo;
for (auto & c : path)
todo.push_back(std::string(c));
while (!todo.empty()) {
auto c = *todo.begin();
todo.pop_front();
if (c == "" || c == ".")
;
else if (c == "..")
res.pop();
else {
res.push(c);
if (mode == SymlinkResolution::Full || !todo.empty()) {
if (auto st = maybeLstat(res); st && st->type == SourceAccessor::tSymlink) {
if (!linksAllowed--)
throw Error("infinite symlink recursion in path '%s'", showPath(path));
auto target = readLink(res);
res.pop();
if (hasPrefix(target, "/"))
res = CanonPath::root;
todo.splice(todo.begin(), tokenizeString<std::list<std::string>>(target, "/"));
}
}
}
}
return res;
}
}