1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-09 03:56:01 +01:00
nix/src/libutil/source-accessor.cc
Sergei Zimmerman 143bd60136
libutil: Make HashResult a proper struct
This resolves an existing TODO and makes the
code slightly more readable.
2025-08-08 02:06:14 +03:00

129 lines
3.3 KiB
C++

#include <atomic>
#include "nix/util/source-accessor.hh"
namespace nix {
static std::atomic<size_t> nextNumber{0};
bool SourceAccessor::Stat::isNotNARSerialisable()
{
return this->type != tRegular && this->type != tSymlink && this->type != tDirectory;
}
std::string SourceAccessor::Stat::typeString()
{
switch (this->type) {
case tRegular:
return "regular";
case tSymlink:
return "symlink";
case tDirectory:
return "directory";
case tChar:
return "character device";
case tBlock:
return "block device";
case tSocket:
return "socket";
case tFifo:
return "fifo";
case tUnknown:
default:
return "unknown";
}
return "unknown";
}
SourceAccessor::SourceAccessor()
: number(++nextNumber)
, displayPrefix{"«unknown»"}
{
}
bool SourceAccessor::pathExists(const CanonPath & path)
{
return maybeLstat(path).has_value();
}
std::string SourceAccessor::readFile(const CanonPath & path)
{
StringSink sink;
std::optional<uint64_t> size;
readFile(path, sink, [&](uint64_t _size) { size = _size; });
assert(size && *size == sink.s.size());
return std::move(sink.s);
}
void SourceAccessor::readFile(const CanonPath & path, Sink & sink, std::function<void(uint64_t)> sizeCallback)
{
auto s = readFile(path);
sizeCallback(s.size());
sink(s);
}
Hash SourceAccessor::hashPath(const CanonPath & path, PathFilter & filter, HashAlgorithm ha)
{
HashSink sink(ha);
dumpPath(path, sink, filter);
return sink.finish().hash;
}
SourceAccessor::Stat SourceAccessor::lstat(const CanonPath & path)
{
if (auto st = maybeLstat(path))
return *st;
else
throw FileNotFound("path '%s' does not exist", showPath(path));
}
void SourceAccessor::setPathDisplay(std::string displayPrefix, std::string displaySuffix)
{
this->displayPrefix = std::move(displayPrefix);
this->displaySuffix = std::move(displaySuffix);
}
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 == "..") {
if (!res.isRoot())
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);
if (isAbsolute(target)) {
res = CanonPath::root;
} else {
res.pop();
}
todo.splice(todo.begin(), tokenizeString<std::list<std::string>>(target, "/"));
}
}
}
}
return res;
}
} // namespace nix