about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/store.cc44
-rw-r--r--src/libstore/store.hh2
-rw-r--r--src/nix-store/main.cc12
3 files changed, 47 insertions, 11 deletions
diff --git a/src/libstore/store.cc b/src/libstore/store.cc
index 0c7702f973bd..da60a62b0457 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 e981ade1009b..8e59679a7d3e 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 a3c1b8fa782e..a124543fb230 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);
 }