forked from lix-project/lix
Jade Lovelace
0cc285f87b
Fixes:
- Identifiers starting with _ are prohibited
- Some driveby header dependency cleaning which wound up with doing some
extra fixups.
- Fucking C style casts, man. C++ made these 1000% worse by letting you
also do memory corruption with them with references.
- Remove casts to Expr * where ExprBlackHole is an incomplete type by
introducing an explicitly-cast eBlackHoleAddr as Expr *.
- An incredibly illegal cast of the text bytes of the StorePath hash
into a size_t directly. You can't DO THAT.
Replaced with actually parsing the hash so we get 100% of the bits
being entropy, then memcpying the start of the hash. If this shows
up in a profile we should just make the hash parser faster with a
lookup table or something sensible like that.
- This horrendous bit of UB which I thankfully slapped a deprecation
warning on, built, and it didn't trigger anywhere so it was dead
code and I just deleted it. But holy crap you *cannot* do that.
inline void mkString(const Symbol & s)
{
mkString(((const std::string &) s).c_str());
}
- Some wrong lints. Lots of wrong macro lints, one wrong
suspicious-sizeof lint triggered by the template being instantiated
with only pointers, but the calculation being correct for both
pointers and not-pointers.
- Exceptions in destructors strike again. I tried to catch the
exceptions that might actually happen rather than all the exceptions
imaginable. We can let the runtime hard-kill it on other exceptions
imo.
Change-Id: I71761620846cba64d66ee7ca231b20c061e69710
124 lines
4.1 KiB
C++
124 lines
4.1 KiB
C++
#include "store-api.hh"
|
|
|
|
#include <sodium.h>
|
|
|
|
namespace nix {
|
|
|
|
static void checkName(std::string_view path, std::string_view name)
|
|
{
|
|
if (name.empty())
|
|
throw BadStorePath("store path '%s' has an empty name", path);
|
|
if (name.size() > StorePath::MaxPathLen)
|
|
throw BadStorePath("store path '%s' has a name longer than %d characters",
|
|
path, StorePath::MaxPathLen);
|
|
// See nameRegexStr for the definition
|
|
if (name[0] == '.') {
|
|
// check against "." and "..", followed by end or dash
|
|
if (name.size() == 1)
|
|
throw BadStorePath("store path '%s' has invalid name '%s'", path, name);
|
|
if (name[1] == '-')
|
|
throw BadStorePath("store path '%s' has invalid name '%s': first dash-separated component must not be '%s'", path, name, ".");
|
|
if (name[1] == '.') {
|
|
if (name.size() == 2)
|
|
throw BadStorePath("store path '%s' has invalid name '%s'", path, name);
|
|
if (name[2] == '-')
|
|
throw BadStorePath("store path '%s' has invalid name '%s': first dash-separated component must not be '%s'", path, name, "..");
|
|
}
|
|
}
|
|
for (auto c : name)
|
|
if (!((c >= '0' && c <= '9')
|
|
|| (c >= 'a' && c <= 'z')
|
|
|| (c >= 'A' && c <= 'Z')
|
|
|| c == '+' || c == '-' || c == '.' || c == '_' || c == '?' || c == '='))
|
|
throw BadStorePath("store path '%s' contains illegal character '%s'", path, c);
|
|
}
|
|
|
|
StorePath::StorePath(std::string_view _baseName)
|
|
: baseName(_baseName)
|
|
{
|
|
if (baseName.size() < HashLen + 1)
|
|
throw BadStorePath("'%s' is too short to be a valid store path", baseName);
|
|
for (auto c : hashPart())
|
|
if (c == 'e' || c == 'o' || c == 'u' || c == 't'
|
|
|| !((c >= '0' && c <= '9') || (c >= 'a' && c <= 'z')))
|
|
throw BadStorePath("store path '%s' contains illegal base-32 character '%s'", baseName, c);
|
|
checkName(baseName, name());
|
|
}
|
|
|
|
StorePath::StorePath(const Hash & hash, std::string_view _name)
|
|
: baseName((hash.to_string(Base::Base32, false) + "-").append(std::string(_name)))
|
|
{
|
|
checkName(baseName, name());
|
|
}
|
|
|
|
bool StorePath::isDerivation() const
|
|
{
|
|
return name().ends_with(drvExtension);
|
|
}
|
|
|
|
StorePath StorePath::dummy("ffffffffffffffffffffffffffffffff-x");
|
|
|
|
StorePath StorePath::random(std::string_view name)
|
|
{
|
|
Hash hash(HashType::SHA1);
|
|
randombytes_buf(hash.hash, hash.hashSize);
|
|
return StorePath(hash, name);
|
|
}
|
|
|
|
StorePath Store::parseStorePath(std::string_view path) const
|
|
{
|
|
auto p = canonPath(std::string(path));
|
|
if (dirOf(p) != storeDir)
|
|
throw BadStorePath("path '%s' is not in the Nix store", p);
|
|
return StorePath(baseNameOf(p));
|
|
}
|
|
|
|
std::optional<StorePath> Store::maybeParseStorePath(std::string_view path) const
|
|
{
|
|
// If it's not an absolute path, or if the dirname of the path isn't /nix/store
|
|
// (or whatever our storeDir is), then it can't be a store path.
|
|
if ((path.size() > 0 && path[0] != '/') || dirOf(canonPath(path)) != this->storeDir) {
|
|
return std::nullopt;
|
|
}
|
|
try {
|
|
return parseStorePath(path);
|
|
} catch (Error &) {
|
|
return {};
|
|
}
|
|
}
|
|
|
|
bool Store::isStorePath(std::string_view path) const
|
|
{
|
|
return (bool) maybeParseStorePath(path);
|
|
}
|
|
|
|
StorePathSet Store::parseStorePathSet(const PathSet & paths) const
|
|
{
|
|
StorePathSet res;
|
|
for (auto & i : paths) res.insert(parseStorePath(i));
|
|
return res;
|
|
}
|
|
|
|
std::string Store::printStorePath(const StorePath & path) const
|
|
{
|
|
return (storeDir + "/").append(path.to_string());
|
|
}
|
|
|
|
PathSet Store::printStorePathSet(const StorePathSet & paths) const
|
|
{
|
|
PathSet res;
|
|
for (auto & i : paths) res.insert(printStorePath(i));
|
|
return res;
|
|
}
|
|
|
|
}
|
|
|
|
std::size_t std::hash<nix::StorePath>::operator()(const nix::StorePath & path) const noexcept
|
|
{
|
|
// It's already a cryptographic hash of 160 bits (assuming that nobody gives us bogus ones...), so just parse it.
|
|
auto h = nix::Hash::parseNonSRIUnprefixed(path.hashPart(), nix::HashType::SHA1);
|
|
// This need not be stable across machines, so bit casting the start of it is fine.
|
|
size_t r;
|
|
memcpy(&r, h.hash, sizeof(r));
|
|
return r;
|
|
}
|