2023-01-07 01:06:03 +02:00
|
|
|
#include "store-dir-config.hh"
|
2019-12-05 20:11:09 +02:00
|
|
|
|
|
|
|
namespace nix {
|
|
|
|
|
2020-06-16 15:16:39 +03:00
|
|
|
static void checkName(std::string_view path, std::string_view name)
|
2019-12-05 20:11:09 +02:00
|
|
|
{
|
2020-06-16 15:16:39 +03:00
|
|
|
if (name.empty())
|
|
|
|
throw BadStorePath("store path '%s' has an empty name", path);
|
2023-01-19 07:26:06 +02:00
|
|
|
if (name.size() > StorePath::MaxPathLen)
|
2023-05-23 20:12:02 +03:00
|
|
|
throw BadStorePath("store path '%s' has a name longer than %d characters",
|
|
|
|
path, StorePath::MaxPathLen);
|
2023-01-19 07:26:06 +02:00
|
|
|
// See nameRegexStr for the definition
|
2024-01-30 19:37:23 +02:00
|
|
|
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, "..");
|
|
|
|
}
|
|
|
|
}
|
2020-06-16 15:16:39 +03:00
|
|
|
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);
|
2019-12-05 20:11:09 +02:00
|
|
|
}
|
|
|
|
|
2020-06-16 15:16:39 +03:00
|
|
|
StorePath::StorePath(std::string_view _baseName)
|
|
|
|
: baseName(_baseName)
|
2019-12-05 20:11:09 +02:00
|
|
|
{
|
2020-06-16 15:16:39 +03:00
|
|
|
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());
|
2019-12-05 20:11:09 +02:00
|
|
|
}
|
|
|
|
|
2020-06-16 15:16:39 +03:00
|
|
|
StorePath::StorePath(const Hash & hash, std::string_view _name)
|
2023-11-28 16:38:15 +02:00
|
|
|
: baseName((hash.to_string(HashFormat::Nix32, false) + "-").append(std::string(_name)))
|
2019-12-05 20:11:09 +02:00
|
|
|
{
|
2020-06-16 15:16:39 +03:00
|
|
|
checkName(baseName, name());
|
2019-12-05 20:11:09 +02:00
|
|
|
}
|
|
|
|
|
2024-05-22 19:35:44 +03:00
|
|
|
bool StorePath::isDerivation() const noexcept
|
2019-12-05 20:11:09 +02:00
|
|
|
{
|
|
|
|
return hasSuffix(name(), drvExtension);
|
|
|
|
}
|
|
|
|
|
2024-05-22 19:35:44 +03:00
|
|
|
void StorePath::requireDerivation() const
|
|
|
|
{
|
|
|
|
if (!isDerivation())
|
|
|
|
throw FormatError("store path '%s' is not a valid derivation path", to_string());
|
|
|
|
}
|
|
|
|
|
2020-06-16 15:16:39 +03:00
|
|
|
StorePath StorePath::dummy("ffffffffffffffffffffffffffffffff-x");
|
2020-01-21 22:14:13 +02:00
|
|
|
|
2022-03-30 17:31:01 +03:00
|
|
|
StorePath StorePath::random(std::string_view name)
|
|
|
|
{
|
2024-01-03 22:02:20 +02:00
|
|
|
return StorePath(Hash::random(HashAlgorithm::SHA1), name);
|
2022-03-30 17:31:01 +03:00
|
|
|
}
|
|
|
|
|
2023-01-07 01:06:03 +02:00
|
|
|
StorePath StoreDirConfig::parseStorePath(std::string_view path) const
|
2019-12-05 20:11:09 +02:00
|
|
|
{
|
2024-01-14 20:36:53 +02:00
|
|
|
// On Windows, `/nix/store` is not a canonical path. More broadly it
|
|
|
|
// is unclear whether this function should be using the native
|
|
|
|
// notion of a canonical path at all. For example, it makes to
|
|
|
|
// support remote stores whose store dir is a non-native path (e.g.
|
|
|
|
// Windows <-> Unix ssh-ing).
|
|
|
|
auto p =
|
|
|
|
#ifdef _WIN32
|
|
|
|
path
|
|
|
|
#else
|
|
|
|
canonPath(std::string(path))
|
|
|
|
#endif
|
|
|
|
;
|
2020-06-16 15:16:39 +03:00
|
|
|
if (dirOf(p) != storeDir)
|
|
|
|
throw BadStorePath("path '%s' is not in the Nix store", p);
|
|
|
|
return StorePath(baseNameOf(p));
|
2019-12-05 20:11:09 +02:00
|
|
|
}
|
|
|
|
|
2023-01-07 01:06:03 +02:00
|
|
|
std::optional<StorePath> StoreDirConfig::maybeParseStorePath(std::string_view path) const
|
2020-02-28 19:07:10 +02:00
|
|
|
{
|
|
|
|
try {
|
|
|
|
return parseStorePath(path);
|
|
|
|
} catch (Error &) {
|
|
|
|
return {};
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-01-07 01:06:03 +02:00
|
|
|
bool StoreDirConfig::isStorePath(std::string_view path) const
|
2020-02-28 19:07:10 +02:00
|
|
|
{
|
|
|
|
return (bool) maybeParseStorePath(path);
|
|
|
|
}
|
|
|
|
|
2023-01-07 01:06:03 +02:00
|
|
|
StorePathSet StoreDirConfig::parseStorePathSet(const PathSet & paths) const
|
2019-12-05 20:11:09 +02:00
|
|
|
{
|
|
|
|
StorePathSet res;
|
|
|
|
for (auto & i : paths) res.insert(parseStorePath(i));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
2023-01-07 01:06:03 +02:00
|
|
|
std::string StoreDirConfig::printStorePath(const StorePath & path) const
|
2019-12-05 20:11:09 +02:00
|
|
|
{
|
2020-06-16 15:16:39 +03:00
|
|
|
return (storeDir + "/").append(path.to_string());
|
2019-12-05 20:11:09 +02:00
|
|
|
}
|
|
|
|
|
2023-01-07 01:06:03 +02:00
|
|
|
PathSet StoreDirConfig::printStorePathSet(const StorePathSet & paths) const
|
2019-12-05 20:11:09 +02:00
|
|
|
{
|
|
|
|
PathSet res;
|
|
|
|
for (auto & i : paths) res.insert(printStorePath(i));
|
|
|
|
return res;
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|