Files
lix/lix/libutil/source-path.cc
T
eldritch horrorsandJade Lovelace c948b350fb libutil: add CheckedSourcePath for accessing things
SourcePath only manipulates path names now. all accesses must go through
a checked path going forward to ensure we don't escape restriction lists
of pure and restricted evaluation. if a directory path is checked it can
safely be assumed that the directory itself is allowed, and its contents
will likewise be safe to access. it is tempting to assumed that contents
will also be fine, but that's only true if the content is not a symlink.

Change-Id: Icec3098d53fe9dce50997954ba958fe4f304d59b
2025-01-10 15:20:27 -08:00

82 lines
2.0 KiB
C++

#include "lix/libutil/source-path.hh"
#include "file-system.hh"
#include "lix/libutil/strings.hh"
namespace nix {
std::ostream & operator << (std::ostream & str, const SourcePath & path)
{
str << path.to_string();
return str;
}
std::string_view SourcePath::baseName() const
{
return path.baseName().value_or("source");
}
SourcePath SourcePath::parent() const
{
auto p = path.parent();
assert(p);
return std::move(*p);
}
static InputAccessor::Stat convertStat(const struct stat & st)
{
return InputAccessor::Stat {
.type =
S_ISREG(st.st_mode) ? InputAccessor::tRegular :
S_ISDIR(st.st_mode) ? InputAccessor::tDirectory :
S_ISLNK(st.st_mode) ? InputAccessor::tSymlink :
InputAccessor::tMisc,
.isExecutable = S_ISREG(st.st_mode) && st.st_mode & S_IXUSR
};
}
InputAccessor::Stat CheckedSourcePath::lstat() const
{
return convertStat(nix::lstat(path.abs()));
}
std::optional<InputAccessor::Stat> CheckedSourcePath::maybeLstat() const
{
if (auto st = nix::maybeLstat(path.abs())) {
return convertStat(*st);
} else {
return std::nullopt;
}
}
InputAccessor::Stat CheckedSourcePath::stat() const
{
return convertStat(nix::stat(path.abs()));
}
std::optional<InputAccessor::Stat> CheckedSourcePath::maybeStat() const
{
if (auto st = nix::maybeStat(path.abs())) {
return convertStat(*st);
} else {
return std::nullopt;
}
}
InputAccessor::DirEntries CheckedSourcePath::readDirectory() const
{
InputAccessor::DirEntries res;
for (auto & entry : nix::readDirectory(path.abs())) {
std::optional<InputAccessor::Type> type;
switch (entry.type) {
case DT_REG: type = InputAccessor::Type::tRegular; break;
case DT_LNK: type = InputAccessor::Type::tSymlink; break;
case DT_DIR: type = InputAccessor::Type::tDirectory; break;
default: break; // unknown type
}
res.emplace(entry.name, type);
}
return res;
}
}