parent
fe97c69898
commit
c0015e87af
23 changed files with 205 additions and 213 deletions
|
@ -81,8 +81,7 @@ SV * queryReferences(char * path)
|
|||
SV * queryPathHash(char * path)
|
||||
PPCODE:
|
||||
try {
|
||||
auto hash = store()->queryPathInfo(path)->narHash;
|
||||
string s = "sha256:" + printHash32(hash);
|
||||
auto s = store()->queryPathInfo(path)->narHash.to_string();
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
|
@ -108,7 +107,7 @@ SV * queryPathInfo(char * path, int base32)
|
|||
XPUSHs(&PL_sv_undef);
|
||||
else
|
||||
XPUSHs(sv_2mortal(newSVpv(info->deriver.c_str(), 0)));
|
||||
string s = "sha256:" + (base32 ? printHash32(info->narHash) : printHash(info->narHash));
|
||||
auto s = info->narHash.to_string(base32 ? Base32 : Base16);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
mXPUSHi(info->registrationTime);
|
||||
mXPUSHi(info->narSize);
|
||||
|
@ -184,7 +183,7 @@ void importPaths(int fd, int dontCheckSigs)
|
|||
PPCODE:
|
||||
try {
|
||||
FdSource source(fd);
|
||||
store()->importPaths(source, 0, dontCheckSigs);
|
||||
store()->importPaths(source, nullptr, dontCheckSigs ? NoCheckSigs : CheckSigs);
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
}
|
||||
|
@ -194,7 +193,7 @@ SV * hashPath(char * algo, int base32, char * path)
|
|||
PPCODE:
|
||||
try {
|
||||
Hash h = hashPath(parseHashType(algo), path).first;
|
||||
string s = base32 ? printHash32(h) : printHash(h);
|
||||
auto s = h.to_string(base32 ? Base32 : Base16, false);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
|
@ -205,7 +204,7 @@ SV * hashFile(char * algo, int base32, char * path)
|
|||
PPCODE:
|
||||
try {
|
||||
Hash h = hashFile(parseHashType(algo), path);
|
||||
string s = base32 ? printHash32(h) : printHash(h);
|
||||
auto s = h.to_string(base32 ? Base32 : Base16, false);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
|
@ -216,7 +215,7 @@ SV * hashString(char * algo, int base32, char * s)
|
|||
PPCODE:
|
||||
try {
|
||||
Hash h = hashString(parseHashType(algo), s);
|
||||
string s = base32 ? printHash32(h) : printHash(h);
|
||||
auto s = h.to_string(base32 ? Base32 : Base16, false);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
|
@ -226,8 +225,8 @@ SV * hashString(char * algo, int base32, char * s)
|
|||
SV * convertHash(char * algo, char * s, int toBase32)
|
||||
PPCODE:
|
||||
try {
|
||||
Hash h = parseHash16or32(parseHashType(algo), s);
|
||||
string s = toBase32 ? printHash32(h) : printHash(h);
|
||||
Hash h(s, parseHashType(algo));
|
||||
string s = h.to_string(toBase32 ? Base32 : Base16, false);
|
||||
XPUSHs(sv_2mortal(newSVpv(s.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
croak("%s", e.what());
|
||||
|
@ -286,8 +285,7 @@ SV * addToStore(char * srcPath, int recursive, char * algo)
|
|||
SV * makeFixedOutputPath(int recursive, char * algo, char * hash, char * name)
|
||||
PPCODE:
|
||||
try {
|
||||
HashType ht = parseHashType(algo);
|
||||
Hash h = parseHash16or32(ht, hash);
|
||||
Hash h(hash, parseHashType(algo));
|
||||
Path path = store()->makeFixedOutputPath(recursive, h, name);
|
||||
XPUSHs(sv_2mortal(newSVpv(path.c_str(), 0)));
|
||||
} catch (Error & e) {
|
||||
|
|
|
@ -708,8 +708,8 @@ static void prim_derivationStrict(EvalState & state, const Pos & pos, Value * *
|
|||
HashType ht = parseHashType(outputHashAlgo);
|
||||
if (ht == htUnknown)
|
||||
throw EvalError(format("unknown hash algorithm ‘%1%’, at %2%") % outputHashAlgo % posDrvName);
|
||||
Hash h = parseHash16or32(ht, *outputHash);
|
||||
outputHash = printHash(h);
|
||||
Hash h(*outputHash, ht);
|
||||
outputHash = h.to_string(Base16, false);
|
||||
if (outputHashRecursive) outputHashAlgo = "r:" + outputHashAlgo;
|
||||
|
||||
Path outPath = state.store->makeFixedOutputPath(outputHashRecursive, h, drvName);
|
||||
|
@ -1701,7 +1701,7 @@ static void prim_hashString(EvalState & state, const Pos & pos, Value * * args,
|
|||
PathSet context; // discarded
|
||||
string s = state.forceString(*args[1], context, pos);
|
||||
|
||||
mkString(v, printHash(hashString(ht, s)), context);
|
||||
mkString(v, hashString(ht, s).to_string(Base16, false), context);
|
||||
}
|
||||
|
||||
|
||||
|
@ -1852,7 +1852,7 @@ void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
|
|||
if (n == "url")
|
||||
url = state.forceStringNoCtx(*attr.value, *attr.pos);
|
||||
else if (n == "sha256")
|
||||
expectedHash = parseHash16or32(htSHA256, state.forceStringNoCtx(*attr.value, *attr.pos));
|
||||
expectedHash = Hash(state.forceStringNoCtx(*attr.value, *attr.pos), htSHA256);
|
||||
else if (n == "name")
|
||||
name = state.forceStringNoCtx(*attr.value, *attr.pos);
|
||||
else
|
||||
|
|
|
@ -239,7 +239,7 @@ void BinaryCacheStore::addToStore(const ValidPathInfo & info, const ref<std::str
|
|||
% duration);
|
||||
|
||||
/* Atomically write the NAR file. */
|
||||
narInfo->url = "nar/" + printHash32(narInfo->fileHash) + ".nar"
|
||||
narInfo->url = "nar/" + narInfo->fileHash.to_string(Base32, false) + ".nar"
|
||||
+ (compression == "xz" ? ".xz" :
|
||||
compression == "bzip2" ? ".bz2" :
|
||||
compression == "br" ? ".br" :
|
||||
|
|
|
@ -3236,7 +3236,7 @@ PathSet DerivationGoal::checkPathValidity(bool returnValid, bool checkHash)
|
|||
Path DerivationGoal::addHashRewrite(const Path & path)
|
||||
{
|
||||
string h1 = string(path, worker.store.storeDir.size() + 1, 32);
|
||||
string h2 = string(printHash32(hashString(htSHA256, "rewrite:" + drvPath + ":" + path)), 0, 32);
|
||||
string h2 = string(hashString(htSHA256, "rewrite:" + drvPath + ":" + path).to_string(Base32, false), 0, 32);
|
||||
Path p = worker.store.storeDir + "/" + h2 + string(path, worker.store.storeDir.size() + 33);
|
||||
deletePath(p);
|
||||
assert(path.size() == p.size());
|
||||
|
|
|
@ -23,7 +23,7 @@ void DerivationOutput::parseHashInfo(bool & recursive, Hash & hash) const
|
|||
if (hashType == htUnknown)
|
||||
throw Error(format("unknown hash algorithm ‘%1%’") % algo);
|
||||
|
||||
hash = parseHash(hashType, this->hash);
|
||||
hash = Hash(this->hash, hashType);
|
||||
}
|
||||
|
||||
|
||||
|
@ -354,7 +354,7 @@ Hash hashDerivationModulo(Store & store, Derivation drv)
|
|||
h = hashDerivationModulo(store, drv2);
|
||||
drvHashes[i.first] = h;
|
||||
}
|
||||
inputs2[printHash(h)] = i.second;
|
||||
inputs2[h.to_string(Base16, false)] = i.second;
|
||||
}
|
||||
drv.inputDrvs = inputs2;
|
||||
|
||||
|
@ -437,7 +437,7 @@ Sink & operator << (Sink & out, const BasicDerivation & drv)
|
|||
std::string hashPlaceholder(const std::string & outputName)
|
||||
{
|
||||
// FIXME: memoize?
|
||||
return "/" + printHash32(hashString(htSHA256, "nix-output:" + outputName));
|
||||
return "/" + hashString(htSHA256, "nix-output:" + outputName).to_string(Base32, false);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -581,7 +581,7 @@ Path Downloader::downloadCached(ref<Store> store, const string & url_, bool unpa
|
|||
Path cacheDir = getCacheDir() + "/nix/tarballs";
|
||||
createDirs(cacheDir);
|
||||
|
||||
string urlHash = printHash32(hashString(htSHA256, url));
|
||||
string urlHash = hashString(htSHA256, url).to_string(Base32, false);
|
||||
|
||||
Path dataFile = cacheDir + "/" + urlHash + ".info";
|
||||
Path fileLink = cacheDir + "/" + urlHash + "-file";
|
||||
|
|
|
@ -56,7 +56,7 @@ void Store::exportPath(const Path & path, Sink & sink)
|
|||
Hash hash = hashAndWriteSink.currentHash();
|
||||
if (hash != info->narHash && info->narHash != Hash(info->narHash.type))
|
||||
throw Error(format("hash of path ‘%1%’ has changed from ‘%2%’ to ‘%3%’!") % path
|
||||
% printHash(info->narHash) % printHash(hash));
|
||||
% info->narHash.to_string() % hash.to_string());
|
||||
|
||||
hashAndWriteSink << exportMagic << path << info->references << info->deriver << 0;
|
||||
}
|
||||
|
|
|
@ -76,7 +76,7 @@ void LocalStore::syncWithGC()
|
|||
|
||||
void LocalStore::addIndirectRoot(const Path & path)
|
||||
{
|
||||
string hash = printHash32(hashString(htSHA1, path));
|
||||
string hash = hashString(htSHA1, path).to_string(Base32, false);
|
||||
Path realRoot = canonPath((format("%1%/%2%/auto/%3%")
|
||||
% stateDir % gcRootsDir % hash).str());
|
||||
makeSymlink(realRoot, path);
|
||||
|
|
|
@ -572,7 +572,7 @@ uint64_t LocalStore::addValidPath(State & state,
|
|||
|
||||
state.stmtRegisterValidPath.use()
|
||||
(info.path)
|
||||
("sha256:" + printHash(info.narHash))
|
||||
(info.narHash.to_string(Base16))
|
||||
(info.registrationTime == 0 ? time(0) : info.registrationTime)
|
||||
(info.deriver, info.deriver != "")
|
||||
(info.narSize, info.narSize != 0)
|
||||
|
@ -614,20 +614,6 @@ uint64_t LocalStore::addValidPath(State & state,
|
|||
}
|
||||
|
||||
|
||||
Hash parseHashField(const Path & path, const string & s)
|
||||
{
|
||||
string::size_type colon = s.find(':');
|
||||
if (colon == string::npos)
|
||||
throw Error(format("corrupt hash ‘%1%’ in valid-path entry for ‘%2%’")
|
||||
% s % path);
|
||||
HashType ht = parseHashType(string(s, 0, colon));
|
||||
if (ht == htUnknown)
|
||||
throw Error(format("unknown hash type ‘%1%’ in valid-path entry for ‘%2%’")
|
||||
% string(s, 0, colon) % path);
|
||||
return parseHash(ht, string(s, colon + 1));
|
||||
}
|
||||
|
||||
|
||||
void LocalStore::queryPathInfoUncached(const Path & path,
|
||||
std::function<void(std::shared_ptr<ValidPathInfo>)> success,
|
||||
std::function<void(std::exception_ptr exc)> failure)
|
||||
|
@ -650,7 +636,11 @@ void LocalStore::queryPathInfoUncached(const Path & path,
|
|||
|
||||
info->id = useQueryPathInfo.getInt(0);
|
||||
|
||||
info->narHash = parseHashField(path, useQueryPathInfo.getStr(1));
|
||||
try {
|
||||
info->narHash = Hash(useQueryPathInfo.getStr(1));
|
||||
} catch (BadHash & e) {
|
||||
throw Error("in valid-path entry for ‘%s’: %s", path, e.what());
|
||||
}
|
||||
|
||||
info->registrationTime = useQueryPathInfo.getInt(2);
|
||||
|
||||
|
@ -685,7 +675,7 @@ void LocalStore::updatePathInfo(State & state, const ValidPathInfo & info)
|
|||
{
|
||||
state.stmtUpdatePathInfo.use()
|
||||
(info.narSize, info.narSize != 0)
|
||||
("sha256:" + printHash(info.narHash))
|
||||
(info.narHash.to_string(Base16))
|
||||
(info.ultimate ? 1 : 0, info.ultimate)
|
||||
(concatStringsSep(" ", info.sigs), !info.sigs.empty())
|
||||
(info.ca, !info.ca.empty())
|
||||
|
@ -1211,7 +1201,7 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair)
|
|||
if (info->narHash != nullHash && info->narHash != current.first) {
|
||||
printError(format("path ‘%1%’ was modified! "
|
||||
"expected hash ‘%2%’, got ‘%3%’")
|
||||
% i % printHash(info->narHash) % printHash(current.first));
|
||||
% i % info->narHash.to_string() % current.first.to_string());
|
||||
if (repair) repairPath(i); else errors = true;
|
||||
} else {
|
||||
|
||||
|
|
|
@ -203,9 +203,9 @@ public:
|
|||
narInfo->url = queryNAR.getStr(3);
|
||||
narInfo->compression = queryNAR.getStr(4);
|
||||
if (!queryNAR.isNull(5))
|
||||
narInfo->fileHash = parseHash(queryNAR.getStr(5));
|
||||
narInfo->fileHash = Hash(queryNAR.getStr(5));
|
||||
narInfo->fileSize = queryNAR.getInt(6);
|
||||
narInfo->narHash = parseHash(queryNAR.getStr(7));
|
||||
narInfo->narHash = Hash(queryNAR.getStr(7));
|
||||
narInfo->narSize = queryNAR.getInt(8);
|
||||
for (auto & r : tokenizeString<Strings>(queryNAR.getStr(9), " "))
|
||||
narInfo->references.insert(cache.storeDir + "/" + r);
|
||||
|
|
|
@ -11,7 +11,7 @@ NarInfo::NarInfo(const Store & store, const std::string & s, const std::string &
|
|||
|
||||
auto parseHashField = [&](const string & s) {
|
||||
try {
|
||||
return parseHash(s);
|
||||
return Hash(s);
|
||||
} catch (BadHash &) {
|
||||
corrupt();
|
||||
return Hash(); // never reached
|
||||
|
@ -90,10 +90,10 @@ std::string NarInfo::to_string() const
|
|||
assert(compression != "");
|
||||
res += "Compression: " + compression + "\n";
|
||||
assert(fileHash.type == htSHA256);
|
||||
res += "FileHash: sha256:" + printHash32(fileHash) + "\n";
|
||||
res += "FileHash: " + fileHash.to_string(Base32) + "\n";
|
||||
res += "FileSize: " + std::to_string(fileSize) + "\n";
|
||||
assert(narHash.type == htSHA256);
|
||||
res += "NarHash: sha256:" + printHash32(narHash) + "\n";
|
||||
res += "NarHash: " + narHash.to_string(Base32) + "\n";
|
||||
res += "NarSize: " + std::to_string(narSize) + "\n";
|
||||
|
||||
res += "References: " + concatStringsSep(" ", shortRefs()) + "\n";
|
||||
|
|
|
@ -135,10 +135,10 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
|
|||
contents of the symlink (i.e. the result of readlink()), not
|
||||
the contents of the target (which may not even exist). */
|
||||
Hash hash = hashPath(htSHA256, path).first;
|
||||
debug(format("‘%1%’ has hash ‘%2%’") % path % printHash(hash));
|
||||
debug(format("‘%1%’ has hash ‘%2%’") % path % hash.to_string());
|
||||
|
||||
/* Check if this is a known hash. */
|
||||
Path linkPath = linksDir + "/" + printHash32(hash);
|
||||
Path linkPath = linksDir + "/" + hash.to_string(Base32, false);
|
||||
|
||||
retry:
|
||||
if (!pathExists(linkPath)) {
|
||||
|
|
|
@ -294,7 +294,7 @@ void RemoteStore::queryPathInfoUncached(const Path & path,
|
|||
info->path = path;
|
||||
info->deriver = readString(conn->from);
|
||||
if (info->deriver != "") assertStorePath(info->deriver);
|
||||
info->narHash = parseHash(htSHA256, readString(conn->from));
|
||||
info->narHash = Hash(readString(conn->from), htSHA256);
|
||||
info->references = readStorePaths<PathSet>(*this, conn->from);
|
||||
conn->from >> info->registrationTime >> info->narSize;
|
||||
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 16) {
|
||||
|
@ -387,7 +387,7 @@ void RemoteStore::addToStore(const ValidPathInfo & info, const ref<std::string>
|
|||
|
||||
else {
|
||||
conn->to << wopAddToStoreNar
|
||||
<< info.path << info.deriver << printHash(info.narHash)
|
||||
<< info.path << info.deriver << info.narHash.to_string(Base16, false)
|
||||
<< info.references << info.registrationTime << info.narSize
|
||||
<< info.ultimate << info.sigs << info.ca
|
||||
<< repair << !checkSigs;
|
||||
|
|
|
@ -176,13 +176,12 @@ Path Store::makeStorePath(const string & type,
|
|||
const Hash & hash, const string & name) const
|
||||
{
|
||||
/* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */
|
||||
string s = type + ":sha256:" + printHash(hash) + ":"
|
||||
+ storeDir + ":" + name;
|
||||
string s = type + ":" + hash.to_string(Base16) + ":" + storeDir + ":" + name;
|
||||
|
||||
checkStoreName(name);
|
||||
|
||||
return storeDir + "/"
|
||||
+ printHash32(compressHash(hashString(htSHA256, s), 20))
|
||||
+ compressHash(hashString(htSHA256, s), 20).to_string(Base32, false)
|
||||
+ "-" + name;
|
||||
}
|
||||
|
||||
|
@ -202,7 +201,7 @@ Path Store::makeFixedOutputPath(bool recursive,
|
|||
? makeStorePath("source", hash, name)
|
||||
: makeStorePath("output:out", hashString(htSHA256,
|
||||
"fixed:out:" + (recursive ? (string) "r:" : "") +
|
||||
printHashType(hash.type) + ":" + printHash(hash) + ":"),
|
||||
hash.to_string(Base16) + ":"),
|
||||
name);
|
||||
}
|
||||
|
||||
|
@ -438,7 +437,7 @@ string Store::makeValidityRegistration(const PathSet & paths,
|
|||
auto info = queryPathInfo(i);
|
||||
|
||||
if (showHash) {
|
||||
s += printHash(info->narHash) + "\n";
|
||||
s += info->narHash.to_string(Base16, false) + "\n";
|
||||
s += (format("%1%\n") % info->narSize).str();
|
||||
}
|
||||
|
||||
|
@ -613,7 +612,7 @@ ValidPathInfo decodeValidPathInfo(std::istream & str, bool hashGiven)
|
|||
if (hashGiven) {
|
||||
string s;
|
||||
getline(str, s);
|
||||
info.narHash = parseHash(htSHA256, s);
|
||||
info.narHash = Hash(s, htSHA256);
|
||||
getline(str, s);
|
||||
if (!string2Int(s, info.narSize)) throw Error("number expected");
|
||||
}
|
||||
|
@ -648,7 +647,7 @@ std::string ValidPathInfo::fingerprint() const
|
|||
% path);
|
||||
return
|
||||
"1;" + path + ";"
|
||||
+ printHashType(narHash.type) + ":" + printHash32(narHash) + ";"
|
||||
+ narHash.to_string(Base32) + ";"
|
||||
+ std::to_string(narSize) + ";"
|
||||
+ concatStringsSep(",", references);
|
||||
}
|
||||
|
@ -667,7 +666,7 @@ bool ValidPathInfo::isContentAddressed(const Store & store) const
|
|||
};
|
||||
|
||||
if (hasPrefix(ca, "text:")) {
|
||||
auto hash = parseHash(std::string(ca, 5));
|
||||
Hash hash(std::string(ca, 5));
|
||||
if (store.makeTextPath(storePathToName(path), hash, references) == path)
|
||||
return true;
|
||||
else
|
||||
|
@ -676,7 +675,7 @@ bool ValidPathInfo::isContentAddressed(const Store & store) const
|
|||
|
||||
else if (hasPrefix(ca, "fixed:")) {
|
||||
bool recursive = ca.compare(6, 2, "r:") == 0;
|
||||
auto hash = parseHash(std::string(ca, recursive ? 8 : 6));
|
||||
Hash hash(std::string(ca, recursive ? 8 : 6));
|
||||
if (store.makeFixedOutputPath(recursive, hash, storePathToName(path)) == path)
|
||||
return true;
|
||||
else
|
||||
|
|
|
@ -16,17 +16,8 @@
|
|||
namespace nix {
|
||||
|
||||
|
||||
Hash::Hash()
|
||||
void Hash::init()
|
||||
{
|
||||
type = htUnknown;
|
||||
hashSize = 0;
|
||||
memset(hash, 0, maxHashSize);
|
||||
}
|
||||
|
||||
|
||||
Hash::Hash(HashType type)
|
||||
{
|
||||
this->type = type;
|
||||
if (type == htMD5) hashSize = md5HashSize;
|
||||
else if (type == htSHA1) hashSize = sha1HashSize;
|
||||
else if (type == htSHA256) hashSize = sha256HashSize;
|
||||
|
@ -62,16 +53,10 @@ bool Hash::operator < (const Hash & h) const
|
|||
}
|
||||
|
||||
|
||||
std::string Hash::to_string(bool base32) const
|
||||
{
|
||||
return printHashType(type) + ":" + (base32 ? printHash32(*this) : printHash(*this));
|
||||
}
|
||||
|
||||
|
||||
const string base16Chars = "0123456789abcdef";
|
||||
|
||||
|
||||
string printHash(const Hash & hash)
|
||||
static string printHash16(const Hash & hash)
|
||||
{
|
||||
char buf[hash.hashSize * 2];
|
||||
for (unsigned int i = 0; i < hash.hashSize; i++) {
|
||||
|
@ -82,42 +67,11 @@ string printHash(const Hash & hash)
|
|||
}
|
||||
|
||||
|
||||
Hash parseHash(const string & s)
|
||||
{
|
||||
string::size_type colon = s.find(':');
|
||||
if (colon == string::npos)
|
||||
throw BadHash(format("invalid hash ‘%s’") % s);
|
||||
string hts = string(s, 0, colon);
|
||||
HashType ht = parseHashType(hts);
|
||||
if (ht == htUnknown)
|
||||
throw BadHash(format("unknown hash type ‘%s’") % hts);
|
||||
return parseHash16or32(ht, string(s, colon + 1));
|
||||
}
|
||||
|
||||
|
||||
Hash parseHash(HashType ht, const string & s)
|
||||
{
|
||||
Hash hash(ht);
|
||||
if (s.length() != hash.hashSize * 2)
|
||||
throw BadHash(format("invalid hash ‘%1%’") % s);
|
||||
for (unsigned int i = 0; i < hash.hashSize; i++) {
|
||||
string s2(s, i * 2, 2);
|
||||
if (!isxdigit(s2[0]) || !isxdigit(s2[1]))
|
||||
throw BadHash(format("invalid hash ‘%1%’") % s);
|
||||
istringstream_nocopy str(s2);
|
||||
int n;
|
||||
str >> std::hex >> n;
|
||||
hash.hash[i] = n;
|
||||
}
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
// omitted: E O U T
|
||||
const string base32Chars = "0123456789abcdfghijklmnpqrsvwxyz";
|
||||
|
||||
|
||||
string printHash32(const Hash & hash)
|
||||
static string printHash32(const Hash & hash)
|
||||
{
|
||||
assert(hash.hashSize);
|
||||
size_t len = hash.base32Len();
|
||||
|
@ -142,66 +96,103 @@ string printHash32(const Hash & hash)
|
|||
|
||||
string printHash16or32(const Hash & hash)
|
||||
{
|
||||
return hash.type == htMD5 ? printHash(hash) : printHash32(hash);
|
||||
return hash.to_string(hash.type == htMD5 ? Base16 : Base32);
|
||||
}
|
||||
|
||||
|
||||
Hash parseHash32(HashType ht, const string & s)
|
||||
std::string Hash::to_string(Base base, bool includeType) const
|
||||
{
|
||||
Hash hash(ht);
|
||||
size_t len = hash.base32Len();
|
||||
assert(s.size() == len);
|
||||
std::string s;
|
||||
if (includeType) {
|
||||
s += printHashType(type);
|
||||
s += ':';
|
||||
}
|
||||
switch (base) {
|
||||
case Base16:
|
||||
s += printHash16(*this);
|
||||
break;
|
||||
case Base32:
|
||||
s += printHash32(*this);
|
||||
break;
|
||||
case Base64:
|
||||
s += base64Encode(std::string((const char *) hash, hashSize));
|
||||
break;
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
for (unsigned int n = 0; n < len; ++n) {
|
||||
char c = s[len - n - 1];
|
||||
unsigned char digit;
|
||||
for (digit = 0; digit < base32Chars.size(); ++digit) /* !!! slow */
|
||||
if (base32Chars[digit] == c) break;
|
||||
if (digit >= 32)
|
||||
throw BadHash(format("invalid base-32 hash ‘%1%’") % s);
|
||||
unsigned int b = n * 5;
|
||||
unsigned int i = b / 8;
|
||||
unsigned int j = b % 8;
|
||||
hash.hash[i] |= digit << j;
|
||||
|
||||
if (i < hash.hashSize - 1) {
|
||||
hash.hash[i + 1] |= digit >> (8 - j);
|
||||
} else {
|
||||
if (digit >> (8 - j))
|
||||
throw BadHash(format("invalid base-32 hash ‘%1%’") % s);
|
||||
Hash::Hash(const std::string & s, HashType type)
|
||||
: type(type)
|
||||
{
|
||||
auto colon = s.find(':');
|
||||
|
||||
size_t pos = 0;
|
||||
|
||||
if (colon == string::npos) {
|
||||
if (type == htUnknown)
|
||||
throw BadHash("hash ‘%s’ does not include a type", s);
|
||||
} else {
|
||||
string hts = string(s, 0, colon);
|
||||
this->type = parseHashType(hts);
|
||||
if (this->type == htUnknown)
|
||||
throw BadHash("unknown hash type ‘%s’", hts);
|
||||
if (type != htUnknown && type != this->type)
|
||||
throw BadHash("hash ‘%s’ should have type ‘%s’", s, printHashType(type));
|
||||
pos = colon + 1;
|
||||
}
|
||||
|
||||
init();
|
||||
|
||||
size_t size = s.size() - pos;
|
||||
|
||||
if (size == base16Len()) {
|
||||
|
||||
auto parseHexDigit = [&](char c) {
|
||||
if (c >= '0' && c <= '9') return c - '0';
|
||||
if (c >= 'A' && c <= 'F') return c - 'A' + 10;
|
||||
if (c >= 'a' && c <= 'f') return c - 'a' + 10;
|
||||
throw BadHash("invalid base-16 hash ‘%s’", s);
|
||||
};
|
||||
|
||||
for (unsigned int i = 0; i < hashSize; i++) {
|
||||
hash[i] =
|
||||
parseHexDigit(s[pos + i * 2]) << 4
|
||||
| parseHexDigit(s[pos + i * 2 + 1]);
|
||||
}
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
else if (size == base32Len()) {
|
||||
|
||||
for (unsigned int n = 0; n < size; ++n) {
|
||||
char c = s[pos + size - n - 1];
|
||||
unsigned char digit;
|
||||
for (digit = 0; digit < base32Chars.size(); ++digit) /* !!! slow */
|
||||
if (base32Chars[digit] == c) break;
|
||||
if (digit >= 32)
|
||||
throw BadHash("invalid base-32 hash ‘%s’", s);
|
||||
unsigned int b = n * 5;
|
||||
unsigned int i = b / 8;
|
||||
unsigned int j = b % 8;
|
||||
hash[i] |= digit << j;
|
||||
|
||||
Hash parseHash16or32(HashType ht, const string & s)
|
||||
{
|
||||
Hash hash(ht);
|
||||
if (s.size() == hash.hashSize * 2)
|
||||
/* hexadecimal representation */
|
||||
hash = parseHash(ht, s);
|
||||
else if (s.size() == hash.base32Len())
|
||||
/* base-32 representation */
|
||||
hash = parseHash32(ht, s);
|
||||
else
|
||||
throw BadHash(format("hash ‘%1%’ has wrong length for hash type ‘%2%’")
|
||||
% s % printHashType(ht));
|
||||
return hash;
|
||||
}
|
||||
|
||||
|
||||
bool isHash(const string & s)
|
||||
{
|
||||
if (s.length() != 32) return false;
|
||||
for (int i = 0; i < 32; i++) {
|
||||
char c = s[i];
|
||||
if (!((c >= '0' && c <= '9') ||
|
||||
(c >= 'a' && c <= 'f')))
|
||||
return false;
|
||||
if (i < hashSize - 1) {
|
||||
hash[i + 1] |= digit >> (8 - j);
|
||||
} else {
|
||||
if (digit >> (8 - j))
|
||||
throw BadHash("invalid base-32 hash ‘%s’", s);
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
|
||||
else if (size == base64Len()) {
|
||||
auto d = base64Decode(std::string(s, pos));
|
||||
assert(d.size() == hashSize);
|
||||
memcpy(hash, d.data(), hashSize);
|
||||
}
|
||||
|
||||
else
|
||||
throw BadHash("hash ‘%s’ has wrong length for hash type ‘%s’", s, printHashType(type));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -20,20 +20,30 @@ const int sha512HashSize = 64;
|
|||
|
||||
extern const string base32Chars;
|
||||
|
||||
enum Base : int { Base64, Base32, Base16 };
|
||||
|
||||
|
||||
struct Hash
|
||||
{
|
||||
static const unsigned int maxHashSize = 64;
|
||||
unsigned int hashSize;
|
||||
unsigned char hash[maxHashSize];
|
||||
unsigned int hashSize = 0;
|
||||
unsigned char hash[maxHashSize] = {};
|
||||
|
||||
HashType type;
|
||||
HashType type = htUnknown;
|
||||
|
||||
/* Create an unset hash object. */
|
||||
Hash();
|
||||
Hash() { };
|
||||
|
||||
/* Create a zero-filled hash object. */
|
||||
Hash(HashType type);
|
||||
Hash(HashType type) : type(type) { init(); };
|
||||
|
||||
/* Initialize the hash from a string representation, in the format
|
||||
"[<type>:]<base16|base32|base64>". If the ‘type’ argument is
|
||||
htUnknown, then the hash type must be specified in the
|
||||
string. */
|
||||
Hash(const std::string & s, HashType type = htUnknown);
|
||||
|
||||
void init();
|
||||
|
||||
/* Check whether a hash is set. */
|
||||
operator bool () const { return type != htUnknown; }
|
||||
|
@ -59,33 +69,22 @@ struct Hash
|
|||
return (hashSize * 8 - 1) / 5 + 1;
|
||||
}
|
||||
|
||||
std::string to_string(bool base32 = true) const;
|
||||
/* Returns the length of a base-64 representation of this hash. */
|
||||
size_t base64Len() const
|
||||
{
|
||||
return ((4 * hashSize / 3) + 3) & ~3;
|
||||
}
|
||||
|
||||
/* Return a string representation of the hash, in base-16, base-32
|
||||
or base-64. By default, this is prefixed by the hash type
|
||||
(e.g. "sha256:"). */
|
||||
std::string to_string(Base base = Base32, bool includeType = true) const;
|
||||
};
|
||||
|
||||
|
||||
/* Convert a hash to a hexadecimal representation. */
|
||||
string printHash(const Hash & hash);
|
||||
|
||||
Hash parseHash(const string & s);
|
||||
|
||||
/* Parse a hexadecimal representation of a hash code. */
|
||||
Hash parseHash(HashType ht, const string & s);
|
||||
|
||||
/* Convert a hash to a base-32 representation. */
|
||||
string printHash32(const Hash & hash);
|
||||
|
||||
/* Print a hash in base-16 if it's MD5, or base-32 otherwise. */
|
||||
string printHash16or32(const Hash & hash);
|
||||
|
||||
/* Parse a base-32 representation of a hash code. */
|
||||
Hash parseHash32(HashType ht, const string & s);
|
||||
|
||||
/* Parse a base-16 or base-32 representation of a hash code. */
|
||||
Hash parseHash16or32(HashType ht, const string & s);
|
||||
|
||||
/* Verify that the given string is a valid hash code. */
|
||||
bool isHash(const string & s);
|
||||
|
||||
/* Compute the hash of the given string. */
|
||||
Hash hashString(HashType ht, const string & s);
|
||||
|
||||
|
|
|
@ -216,7 +216,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
|
|||
startWork();
|
||||
auto hash = store->queryPathInfo(path)->narHash;
|
||||
stopWork();
|
||||
to << printHash(hash);
|
||||
to << hash.to_string(Base16, false);
|
||||
break;
|
||||
}
|
||||
|
||||
|
@ -550,7 +550,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
|
|||
if (info) {
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 17)
|
||||
to << 1;
|
||||
to << info->deriver << printHash(info->narHash) << info->references
|
||||
to << info->deriver << info->narHash.to_string(Base16, false) << info->references
|
||||
<< info->registrationTime << info->narSize;
|
||||
if (GET_PROTOCOL_MINOR(clientVersion) >= 16) {
|
||||
to << info->ultimate
|
||||
|
@ -610,7 +610,7 @@ static void performOp(ref<LocalStore> store, bool trusted, unsigned int clientVe
|
|||
from >> info.deriver;
|
||||
if (!info.deriver.empty())
|
||||
store->assertStorePath(info.deriver);
|
||||
info.narHash = parseHash(htSHA256, readString(from));
|
||||
info.narHash = Hash(readString(from), htSHA256);
|
||||
info.references = readStorePaths<PathSet>(*store, from);
|
||||
from >> info.registrationTime >> info.narSize >> info.ultimate;
|
||||
info.sigs = readStrings<StringSet>(from);
|
||||
|
|
|
@ -145,7 +145,7 @@ int main(int argc, char * * argv)
|
|||
Hash hash, expectedHash(ht);
|
||||
Path storePath;
|
||||
if (args.size() == 2) {
|
||||
expectedHash = parseHash16or32(ht, args[1]);
|
||||
expectedHash = Hash(args[1], ht);
|
||||
storePath = store->makeFixedOutputPath(unpack, expectedHash, name);
|
||||
if (store->isValidPath(storePath))
|
||||
hash = expectedHash;
|
||||
|
|
|
@ -212,7 +212,7 @@ static void opPrintFixedPath(Strings opFlags, Strings opArgs)
|
|||
string name = *i++;
|
||||
|
||||
cout << format("%1%\n") %
|
||||
store->makeFixedOutputPath(recursive, parseHash16or32(hashAlgo, hash), name);
|
||||
store->makeFixedOutputPath(recursive, Hash(hash, hashAlgo), name);
|
||||
}
|
||||
|
||||
|
||||
|
@ -380,9 +380,9 @@ static void opQuery(Strings opFlags, Strings opArgs)
|
|||
auto info = store->queryPathInfo(j);
|
||||
if (query == qHash) {
|
||||
assert(info->narHash.type == htSHA256);
|
||||
cout << format("sha256:%1%\n") % printHash32(info->narHash);
|
||||
cout << fmt("%s\n", info->narHash.to_string(Base32));
|
||||
} else if (query == qSize)
|
||||
cout << format("%1%\n") % info->narSize;
|
||||
cout << fmt("%d\n", info->narSize);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
@ -734,7 +734,7 @@ static void opVerifyPath(Strings opFlags, Strings opArgs)
|
|||
if (current.first != info->narHash) {
|
||||
printError(
|
||||
format("path ‘%1%’ was modified! expected hash ‘%2%’, got ‘%3%’")
|
||||
% path % printHash(info->narHash) % printHash(current.first));
|
||||
% path % info->narHash.to_string() % current.first.to_string());
|
||||
status = 1;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,15 +9,16 @@ struct CmdHash : Command
|
|||
{
|
||||
enum Mode { mFile, mPath };
|
||||
Mode mode;
|
||||
bool base32 = false;
|
||||
Base base = Base16;
|
||||
bool truncate = false;
|
||||
HashType ht = htSHA512;
|
||||
Strings paths;
|
||||
|
||||
CmdHash(Mode mode) : mode(mode)
|
||||
{
|
||||
mkFlag(0, "base32", "print hash in base-32", &base32);
|
||||
mkFlag(0, "base16", "print hash in base-16", &base32, false);
|
||||
mkFlag(0, "base64", "print hash in base-64", &base, Base64);
|
||||
mkFlag(0, "base32", "print hash in base-32 (Nix-specific)", &base, Base32);
|
||||
mkFlag(0, "base16", "print hash in base-16", &base, Base16);
|
||||
mkHashTypeFlag("type", &ht);
|
||||
expectArgs("paths", &paths);
|
||||
}
|
||||
|
@ -40,7 +41,7 @@ struct CmdHash : Command
|
|||
Hash h = mode == mFile ? hashFile(ht, path) : hashPath(ht, path).first;
|
||||
if (truncate && h.hashSize > 20) h = compressHash(h, 20);
|
||||
std::cout << format("%1%\n") %
|
||||
(base32 ? printHash32(h) : printHash(h));
|
||||
h.to_string(base, false);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@ -50,11 +51,11 @@ static RegisterCommand r2(make_ref<CmdHash>(CmdHash::mPath));
|
|||
|
||||
struct CmdToBase : Command
|
||||
{
|
||||
bool toBase32;
|
||||
Base base;
|
||||
HashType ht = htSHA512;
|
||||
Strings args;
|
||||
|
||||
CmdToBase(bool toBase32) : toBase32(toBase32)
|
||||
CmdToBase(Base base) : base(base)
|
||||
{
|
||||
mkHashTypeFlag("type", &ht);
|
||||
expectArgs("strings", &args);
|
||||
|
@ -62,28 +63,29 @@ struct CmdToBase : Command
|
|||
|
||||
std::string name() override
|
||||
{
|
||||
return toBase32 ? "to-base32" : "to-base16";
|
||||
return
|
||||
base == Base16 ? "to-base16" :
|
||||
base == Base32 ? "to-base32" :
|
||||
"to-base64";
|
||||
}
|
||||
|
||||
std::string description() override
|
||||
{
|
||||
return toBase32
|
||||
? "convert a hash to base-32 representation"
|
||||
: "convert a hash to base-16 representation";
|
||||
return fmt("convert a hash to base-%d representation",
|
||||
base == Base16 ? 16 :
|
||||
base == Base32 ? 32 : 64);
|
||||
}
|
||||
|
||||
void run() override
|
||||
{
|
||||
for (auto s : args) {
|
||||
Hash h = parseHash16or32(ht, s);
|
||||
std::cout << format("%1%\n") %
|
||||
(toBase32 ? printHash32(h) : printHash(h));
|
||||
}
|
||||
for (auto s : args)
|
||||
std::cout << fmt("%s\n", Hash(s, ht).to_string(base, false));
|
||||
}
|
||||
};
|
||||
|
||||
static RegisterCommand r3(make_ref<CmdToBase>(false));
|
||||
static RegisterCommand r4(make_ref<CmdToBase>(true));
|
||||
static RegisterCommand r3(make_ref<CmdToBase>(Base16));
|
||||
static RegisterCommand r4(make_ref<CmdToBase>(Base32));
|
||||
static RegisterCommand r5(make_ref<CmdToBase>(Base64));
|
||||
|
||||
/* Legacy nix-hash command. */
|
||||
static int compatNixHash(int argc, char * * argv)
|
||||
|
@ -121,14 +123,14 @@ static int compatNixHash(int argc, char * * argv)
|
|||
if (op == opHash) {
|
||||
CmdHash cmd(flat ? CmdHash::mFile : CmdHash::mPath);
|
||||
cmd.ht = ht;
|
||||
cmd.base32 = base32;
|
||||
cmd.base = base32 ? Base32 : Base16;
|
||||
cmd.truncate = truncate;
|
||||
cmd.paths = ss;
|
||||
cmd.run();
|
||||
}
|
||||
|
||||
else {
|
||||
CmdToBase cmd(op == opTo32);
|
||||
CmdToBase cmd(op == opTo32 ? Base32 : Base16);
|
||||
cmd.args = ss;
|
||||
cmd.ht = ht;
|
||||
cmd.run();
|
||||
|
|
|
@ -94,7 +94,7 @@ struct CmdVerify : StorePathsCommand
|
|||
corrupted = 1;
|
||||
printError(
|
||||
format("path ‘%s’ was modified! expected hash ‘%s’, got ‘%s’")
|
||||
% info->path % printHash(info->narHash) % printHash(hash.first));
|
||||
% info->path % info->narHash.to_string() % hash.first.to_string());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,15 @@ outPath=$(nix-build '<nix/fetchurl.nix>' --argstr url file://$(pwd)/fetchurl.sh
|
|||
|
||||
cmp $outPath fetchurl.sh
|
||||
|
||||
# Now using a base-64 hash.
|
||||
clearStore
|
||||
|
||||
hash=$(nix hash-file --type sha512 --base64 ./fetchurl.sh)
|
||||
|
||||
outPath=$(nix-build '<nix/fetchurl.nix>' --argstr url file://$(pwd)/fetchurl.sh --argstr sha512 $hash --no-out-link)
|
||||
|
||||
cmp $outPath fetchurl.sh
|
||||
|
||||
# Test unpacking a NAR.
|
||||
rm -rf $TEST_ROOT/archive
|
||||
mkdir -p $TEST_ROOT/archive
|
||||
|
|
|
@ -63,11 +63,15 @@ try2 md5 "f78b733a68f5edbdf9413899339eaa4a"
|
|||
|
||||
# Conversion.
|
||||
try3() {
|
||||
h64=$(nix to-base64 --type "$1" "$2")
|
||||
[ "$h64" = "$4" ]
|
||||
h32=$(nix-hash --type "$1" --to-base32 "$2")
|
||||
[ "$h32" = "$3" ]
|
||||
h16=$(nix-hash --type "$1" --to-base16 "$h32")
|
||||
[ "$h16" = "$2" ]
|
||||
h16=$(nix to-base16 --type "$1" "$h64")
|
||||
[ "$h16" = "$2" ]
|
||||
}
|
||||
try3 sha1 "800d59cfcd3c05e900cb4e214be48f6b886a08df" "vw46m23bizj4n8afrc0fj19wrp7mj3c0"
|
||||
try3 sha256 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" "1b8m03r63zqhnjf7l5wnldhh7c134ap5vpj0850ymkq1iyzicy5s"
|
||||
try3 sha512 "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445" "12k9jiq29iyqm03swfsgiw5mlqs173qazm3n7daz43infy12pyrcdf30fkk3qwv4yl2ick8yipc2mqnlh48xsvvxl60lbx8vp38yji0"
|
||||
try3 sha1 "800d59cfcd3c05e900cb4e214be48f6b886a08df" "vw46m23bizj4n8afrc0fj19wrp7mj3c0" "gA1Zz808BekAy04hS+SPa4hqCN8="
|
||||
try3 sha256 "ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad" "1b8m03r63zqhnjf7l5wnldhh7c134ap5vpj0850ymkq1iyzicy5s" "ungWv48Bz+pBQUDeXa4iI7ADYaOWF3qctBD/YfIAFa0="
|
||||
try3 sha512 "204a8fc6dda82f0a0ced7beb8e08a41657c16ef468b228a8279be331a703c33596fd15c13b1b07f9aa1d3bea57789ca031ad85c7a71dd70354ec631238ca3445" "12k9jiq29iyqm03swfsgiw5mlqs173qazm3n7daz43infy12pyrcdf30fkk3qwv4yl2ick8yipc2mqnlh48xsvvxl60lbx8vp38yji0" "IEqPxt2oLwoM7XvrjgikFlfBbvRosiioJ5vjMacDwzWW/RXBOxsH+aodO+pXeJygMa2Fx6cd1wNU7GMSOMo0RQ=="
|
||||
|
|
Loading…
Reference in a new issue