* 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:
		
							parent
							
								
									a7b94e87d7
								
							
						
					
					
						commit
						9530cc3170
					
				
					 9 changed files with 63 additions and 34 deletions
				
			
		|  | @ -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); | ||||||
|  |  | ||||||
|  | @ -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
 | ||||||
|  |  | ||||||
|  | @ -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 | ||||||
|  |  | ||||||
|  | @ -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; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
|  |  | ||||||
|  | @ -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; |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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]; | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -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"), | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue