* In `nix-store --export', abort if the contents of a path has

changed.  This prevents corrupt paths from spreading to other
  machines.  Note that checking the hash is cheap because we're
  hashing anyway (because of the --sign feature).
This commit is contained in:
Eelco Dolstra 2010-03-09 14:32:03 +00:00
parent 44f6e6de77
commit 4c356acd04
3 changed files with 26 additions and 7 deletions

View File

@ -930,16 +930,19 @@ struct HashAndWriteSink : Sink
{
Sink & writeSink;
HashSink hashSink;
bool hashing;
HashAndWriteSink(Sink & writeSink) : writeSink(writeSink), hashSink(htSHA256)
{
hashing = true;
}
virtual void operator ()
(const unsigned char * data, unsigned int len)
{
writeSink(data, len);
if (hashing) hashSink(data, len);
hashSink(data, len);
}
Hash currentHash()
{
HashSink hashSinkClone(hashSink);
return hashSinkClone.finish();
}
};
@ -970,6 +973,15 @@ void LocalStore::exportPath(const Path & path, bool sign,
dumpPath(path, hashAndWriteSink);
/* Refuse to export paths that have changed. This prevents
filesystem corruption from spreading to other machines. */
Hash hash = hashAndWriteSink.currentHash();
Hash storedHash = queryPathHash(path);
if (hash != storedHash)
throw Error(format("hash of path `%1%' has changed from `%2%' to `%3%'!") % path
% printHash(storedHash) % printHash(hash));
printMsg(lvlError, printHash(hash));
writeInt(EXPORT_MAGIC, hashAndWriteSink);
writeString(path, hashAndWriteSink);
@ -982,8 +994,7 @@ void LocalStore::exportPath(const Path & path, bool sign,
writeString(deriver, hashAndWriteSink);
if (sign) {
Hash hash = hashAndWriteSink.hashSink.finish();
hashAndWriteSink.hashing = false;
Hash hash = hashAndWriteSink.currentHash();
writeInt(1, hashAndWriteSink);

View File

@ -289,6 +289,13 @@ HashSink::HashSink(HashType ht) : ht(ht)
start(ht, *ctx);
}
HashSink::HashSink(const HashSink & h)
{
ht = h.ht;
ctx = new Ctx;
*ctx = *h.ctx;
}
HashSink::~HashSink()
{
delete ctx;

View File

@ -96,6 +96,7 @@ private:
public:
HashSink(HashType ht);
HashSink(const HashSink & h);
~HashSink();
virtual void operator () (const unsigned char * data, unsigned int len);
Hash finish();