diff --git a/src/libstore/store.cc b/src/libstore/store.cc index 0c7702f973..da60a62b04 100644 --- a/src/libstore/store.cc +++ b/src/libstore/store.cc @@ -623,7 +623,23 @@ void deleteFromStore(const Path & _path) } -void verifyStore() +static Hash queryHash(const Transaction & txn, const Path & storePath) +{ + string s; + nixDB.queryString(txn, dbValidPaths, storePath, s); + unsigned int colon = s.find(':'); + if (colon == string::npos) + throw Error(format("corrupt hash `%1%' in valid-path entry for `%2%'") + % s % storePath); + HashType ht = parseHashType(string(s, 0, colon)); + if (ht == htUnknown) + throw Error(format("unknown hash type `%1%' in valid-path entry for `%2%'") + % string(0, colon) % storePath); + return parseHash(ht, string(s, colon + 1)); +} + + +void verifyStore(bool checkContents) { Transaction txn(nixDB); @@ -633,14 +649,24 @@ void verifyStore() for (Paths::iterator i = paths.begin(); i != paths.end(); ++i) { Path path = *i; - if (!pathExists(path)) { - printMsg(lvlError, format("path `%1%' disappeared") % path); - invalidatePath(path, txn); - } else if (!isStorePath(path)) { - printMsg(lvlError, format("path `%1%' is not in the Nix store") % path); - invalidatePath(path, txn); - } else - validPaths.insert(path); + if (!pathExists(*i)) { + printMsg(lvlError, format("path `%1%' disappeared") % *i); + invalidatePath(*i, txn); + } else if (!isStorePath(*i)) { + printMsg(lvlError, format("path `%1%' is not in the Nix store") % *i); + invalidatePath(*i, txn); + } else { + if (checkContents) { + Hash expected = queryHash(txn, *i); + Hash current = hashPath(expected.type, *i); + if (current != expected) { + printMsg(lvlError, format("path `%1%' was modified! " + "expected hash `%2%', got `%3%'") + % *i % printHash(expected) % printHash(current)); + } + } + validPaths.insert(*i); + } } /* "Usable" paths are those that are valid or have a diff --git a/src/libstore/store.hh b/src/libstore/store.hh index e981ade100..8e59679a7d 100644 --- a/src/libstore/store.hh +++ b/src/libstore/store.hh @@ -122,7 +122,7 @@ Path addTextToStore(const string & suffix, const string & s, /* Delete a value from the nixStore directory. */ void deleteFromStore(const Path & path); -void verifyStore(); +void verifyStore(bool checkContents); #endif /* !__STORE_H */ diff --git a/src/nix-store/main.cc b/src/nix-store/main.cc index a3c1b8fa78..a124543fb2 100644 --- a/src/nix-store/main.cc +++ b/src/nix-store/main.cc @@ -420,7 +420,17 @@ static void opInit(Strings opFlags, Strings opArgs) /* Verify the consistency of the Nix environment. */ static void opVerify(Strings opFlags, Strings opArgs) { - verifyStore(); + if (!opArgs.empty()) + throw UsageError("no arguments expected"); + + bool checkContents = false; + + for (Strings::iterator i = opFlags.begin(); + i != opFlags.end(); ++i) + if (*i == "--check-contents") checkContents = true; + else throw UsageError(format("unknown flag `%1%'") % *i); + + verifyStore(checkContents); }