* Start move towards SHA-256 hashes instead of MD5.

* Start cleaning up unique store path generation (they weren't always
  unique; in particular the suffix ("-aterm-2.2", "-builder.sh") was
  not part of the hash, therefore changes to the suffix would cause
  multiple store objects with the same hash).
This commit is contained in:
Eelco Dolstra 2005-01-14 13:51:38 +00:00
parent a7b94e87d7
commit 9530cc3170
9 changed files with 63 additions and 34 deletions

View file

@ -59,7 +59,7 @@ static Path copyAtom(EvalState & state, const Path & srcPath)
ne.closure.elems[dstPath] = elem; ne.closure.elems[dstPath] = elem;
Hash drvHash = hashDerivation(state, ne); Hash drvHash = hashDerivation(state, ne);
Path drvPath = writeTerm(unparseStoreExpr(ne), ""); Path drvPath = writeTerm(unparseStoreExpr(ne), "c");
state.drvHashes.insert(make_pair(drvPath, drvHash)); state.drvHashes.insert(make_pair(drvPath, drvHash));
state.drvRoots[drvPath] = ne.closure.roots; state.drvRoots[drvPath] = ne.closure.roots;
@ -250,21 +250,32 @@ static Expr primDerivation(EvalState & state, const ATermVector & _args)
throw Error(format("invalid character `%1%' in derivation name `%2%'") throw Error(format("invalid character `%1%' in derivation name `%2%'")
% *i % drvName); % *i % drvName);
} }
/* Construct the "masked" derivation store expression, which is
the final one except that the list of output paths is set to
the set of output names, and the corresponding environment
variables have an empty value. This ensures that changes in
the set of output names do get reflected in the hash. */
ne.derivation.env["out"] = "";
ne.derivation.outputs.insert("out");
/* Determine the output path by hashing the Nix expression with no /* Determine the output path by hashing the Nix expression with no
outputs to produce a unique but deterministic path name for outputs to produce a unique but deterministic path name for
this derivation. */ this derivation. */
if (!outHashGiven) outHash = hashDerivation(state, ne); if (!outHashGiven) outHash = hashDerivation(state, ne);
Path outPath = canonPath(nixStore + "/" + Path outPath = makeStorePath("output:out",
((string) outHash).c_str() + "-" + drvName); outHash, drvName);
/* Construct the final derivation store expression. */
ne.derivation.env["out"] = outPath; ne.derivation.env["out"] = outPath;
ne.derivation.outputs.clear();
ne.derivation.outputs.insert(outPath); ne.derivation.outputs.insert(outPath);
/* Write the resulting term into the Nix store directory. */ /* Write the resulting term into the Nix store directory. */
Hash drvHash = outHashGiven Hash drvHash = outHashGiven
? hashString((string) outHash + outPath, htMD5) ? hashString((string) outHash + outPath, htMD5)
: hashDerivation(state, ne); : hashDerivation(state, ne);
Path drvPath = writeTerm(unparseStoreExpr(ne), "-d-" + drvName); Path drvPath = writeTerm(unparseStoreExpr(ne), "d-" + drvName);
printMsg(lvlChatty, format("instantiated `%1%' -> `%2%'") printMsg(lvlChatty, format("instantiated `%1%' -> `%2%'")
% drvName % drvPath); % drvName % drvPath);

View file

@ -69,10 +69,10 @@ static void initAndRun(int argc, char * * argv)
} }
/* Setup Nix paths. */ /* Setup Nix paths. */
nixStore = getEnv("NIX_STORE_DIR", canonPath(NIX_STORE_DIR)); nixStore = canonPath(getEnv("NIX_STORE_DIR", NIX_STORE_DIR));
nixDataDir = getEnv("NIX_DATA_DIR", canonPath(NIX_DATA_DIR)); nixDataDir = canonPath(getEnv("NIX_DATA_DIR", NIX_DATA_DIR));
nixLogDir = getEnv("NIX_LOG_DIR", canonPath(NIX_LOG_DIR)); nixLogDir = canonPath(getEnv("NIX_LOG_DIR", NIX_LOG_DIR));
nixStateDir = getEnv("NIX_STATE_DIR", canonPath(NIX_STATE_DIR)); nixStateDir = canonPath(getEnv("NIX_STATE_DIR", NIX_STATE_DIR));
nixDBPath = getEnv("NIX_DB_DIR", nixStateDir + "/db"); nixDBPath = getEnv("NIX_DB_DIR", nixStateDir + "/db");
/* Check that the store directory and its parent are not /* Check that the store directory and its parent are not

View file

@ -1137,7 +1137,7 @@ void NormalisationGoal::createClosure()
/* Write the normal form. This does not have to occur in the /* Write the normal form. This does not have to occur in the
transaction below because writing terms is idem-potent. */ transaction below because writing terms is idem-potent. */
ATerm nfTerm = unparseStoreExpr(nf); ATerm nfTerm = unparseStoreExpr(nf);
Path nfPath = writeTerm(nfTerm, "-s"); Path nfPath = writeTerm(nfTerm, "s");
/* Register each output path, and register the normal form. This /* Register each output path, and register the normal form. This
is wrapped in one database transaction to ensure that if we is wrapped in one database transaction to ensure that if we

View file

@ -411,19 +411,34 @@ static void invalidatePath(const Path & path, Transaction & txn)
} }
Path makeStorePath(const string & type,
Hash & hash, const string & suffix)
{
/* e.g., "source:sha256:1abc...:/nix/store:foo.tar.gz" */
string s = type + ":sha256:" + (string) hash + ":"
+ nixStore + ":" + suffix;
Hash nameHash = hashString(s, htSHA256);
printMsg(lvlError, format("name input: %1% -> %2%") % s % (string) nameHash);
return nixStore + "/" + (string) nameHash + "-" + suffix;
}
Path addToStore(const Path & _srcPath) Path addToStore(const Path & _srcPath)
{ {
Path srcPath(absPath(_srcPath)); Path srcPath(absPath(_srcPath));
debug(format("adding `%1%' to the store") % srcPath); debug(format("adding `%1%' to the store") % srcPath);
Hash h(htMD5); Hash h(htSHA256);
{ {
SwitchToOriginalUser sw; SwitchToOriginalUser sw;
h = hashPath(srcPath, htMD5); h = hashPath(srcPath, htSHA256);
} }
string baseName = baseNameOf(srcPath); string baseName = baseNameOf(srcPath);
Path dstPath = canonPath(nixStore + "/" + (string) h + "-" + baseName); Path dstPath = makeStorePath("source", h, baseName);
if (!readOnlyMode && !isValidPath(dstPath)) { if (!readOnlyMode && !isValidPath(dstPath)) {
@ -443,6 +458,11 @@ Path addToStore(const Path & _srcPath)
copyPath(srcPath, dstPath); copyPath(srcPath, dstPath);
Hash h2 = hashPath(dstPath, htSHA256);
if (h != h2)
throw Error(format("contents of `%1%' changed while copying it to `%2%' (%3% -> %4%)")
% srcPath % dstPath % (string) h % (string) h2);
makePathReadOnly(dstPath); makePathReadOnly(dstPath);
Transaction txn(nixDB); Transaction txn(nixDB);
@ -457,11 +477,13 @@ Path addToStore(const Path & _srcPath)
} }
void addTextToStore(const Path & dstPath, const string & s) Path addTextToStore(const string & suffix, const string & s)
{ {
assertStorePath(dstPath); Hash hash = hashString(s, htSHA256);
Path dstPath = makeStorePath("text", hash, suffix);
if (!isValidPath(dstPath)) { if (!readOnlyMode && !isValidPath(dstPath)) {
PathSet lockPaths; PathSet lockPaths;
lockPaths.insert(dstPath); lockPaths.insert(dstPath);
@ -482,6 +504,8 @@ void addTextToStore(const Path & dstPath, const string & s)
outputLock.setDeletion(true); outputLock.setDeletion(true);
} }
return dstPath;
} }

View file

@ -81,14 +81,17 @@ void assertStorePath(const Path & path);
/* Checks whether a path is valid. */ /* Checks whether a path is valid. */
bool isValidPath(const Path & path); bool isValidPath(const Path & path);
/* Constructs a unique store path name. */
Path makeStorePath(const string & type,
Hash & hash, const string & suffix);
/* Copy the contents of a path to the store and register the validity /* Copy the contents of a path to the store and register the validity
the resulting path. The resulting path is returned. */ the resulting path. The resulting path is returned. */
Path addToStore(const Path & srcPath); Path addToStore(const Path & srcPath);
/* Like addToStore, but the path of the output is given, and the /* Like addToStore, but the contents written to the output path is a
contents written to the output path is a regular file containing regular file containing the given string. */
the given string. */ Path addTextToStore(const string & suffix, const string & s);
void addTextToStore(const Path & dstPath, const string & s);
/* Delete a value from the nixStore directory. */ /* Delete a value from the nixStore directory. */
void deleteFromStore(const Path & path); void deleteFromStore(const Path & path);

View file

@ -14,19 +14,9 @@ Hash hashTerm(ATerm t)
Path writeTerm(ATerm t, const string & suffix) Path writeTerm(ATerm t, const string & suffix)
{ {
/* The id of a term is its hash. */ char * s = ATwriteToString(t);
Hash h = hashTerm(t); if (!s) throw Error("cannot print aterm");
return addTextToStore(suffix + ".store", string(s));
Path path = canonPath(nixStore + "/" +
(string) h + suffix + ".store");
if (!readOnlyMode && !isValidPath(path)) {
char * s = ATwriteToString(t);
if (!s) throw Error(format("cannot write aterm to `%1%'") % path);
addTextToStore(path, string(s));
}
return path;
} }

View file

@ -22,6 +22,7 @@ Hash::Hash(HashType type)
else if (type == htSHA1) hashSize = sha1HashSize; else if (type == htSHA1) hashSize = sha1HashSize;
else if (type == htSHA256) hashSize = sha256HashSize; else if (type == htSHA256) hashSize = sha256HashSize;
else throw Error("unknown hash type"); else throw Error("unknown hash type");
assert(hashSize <= maxHashSize);
memset(hash, 0, hashSize); memset(hash, 0, hashSize);
} }

View file

@ -18,7 +18,7 @@ const int sha256HashSize = 32;
struct Hash struct Hash
{ {
static const unsigned int maxHashSize = 20; static const unsigned int maxHashSize = 32;
unsigned int hashSize; unsigned int hashSize;
unsigned char hash[maxHashSize]; unsigned char hash[maxHashSize];

View file

@ -216,7 +216,7 @@ void createUserEnv(EvalState & state, const DrvInfos & drvs,
/* Also write a copy of the list of inputs to the store; we need /* Also write a copy of the list of inputs to the store; we need
it for future modifications of the environment. */ it for future modifications of the environment. */
Path inputsFile = writeTerm(inputs2, "-env-inputs"); Path inputsFile = writeTerm(inputs2, "env-inputs");
Expr topLevel = makeCall(envBuilder, makeAttrs(ATmakeList3( Expr topLevel = makeCall(envBuilder, makeAttrs(ATmakeList3(
makeBind(toATerm("system"), makeBind(toATerm("system"),