diff --git a/nix/libstore/remote-store.cc b/nix/libstore/remote-store.cc index 140fe9cf4e..0539bbe127 100644 --- a/nix/libstore/remote-store.cc +++ b/nix/libstore/remote-store.cc @@ -585,6 +585,16 @@ void RemoteStore::optimiseStore() readInt(from); } +bool RemoteStore::verifyStore(bool checkContents, bool repair) +{ + openConnection(); + writeInt(wopVerifyStore, to); + writeInt(checkContents, to); + writeInt(repair, to); + processStderr(); + return readInt(from) != 0; +} + void RemoteStore::processStderr(Sink * sink, Source * source) { to.flush(); diff --git a/nix/libstore/remote-store.hh b/nix/libstore/remote-store.hh index 14209cbfb5..030120db40 100644 --- a/nix/libstore/remote-store.hh +++ b/nix/libstore/remote-store.hh @@ -85,6 +85,7 @@ public: void optimiseStore(); + bool verifyStore(bool checkContents, bool repair); private: AutoCloseFD fdSocket; FdSink to; diff --git a/nix/libstore/store-api.hh b/nix/libstore/store-api.hh index 97a60a6a5c..3764f3e542 100644 --- a/nix/libstore/store-api.hh +++ b/nix/libstore/store-api.hh @@ -254,6 +254,10 @@ public: /* Optimise the disk space usage of the Nix store by hard-linking files with the same contents. */ virtual void optimiseStore() = 0; + + /* Check the integrity of the Nix store. Returns true if errors + remain. */ + virtual bool verifyStore(bool checkContents, bool repair) = 0; }; diff --git a/nix/libstore/worker-protocol.hh b/nix/libstore/worker-protocol.hh index 4b040b77ce..d037d7402e 100644 --- a/nix/libstore/worker-protocol.hh +++ b/nix/libstore/worker-protocol.hh @@ -42,7 +42,8 @@ typedef enum { wopQueryValidPaths = 31, wopQuerySubstitutablePaths = 32, wopQueryValidDerivers = 33, - wopOptimiseStore = 34 + wopOptimiseStore = 34, + wopVerifyStore = 35 } WorkerOp; diff --git a/nix/nix-daemon/nix-daemon.cc b/nix/nix-daemon/nix-daemon.cc index 580198956a..96a4e4b773 100644 --- a/nix/nix-daemon/nix-daemon.cc +++ b/nix/nix-daemon/nix-daemon.cc @@ -647,6 +647,16 @@ static void performOp(bool trusted, unsigned int clientVersion, writeInt(1, to); break; + case wopVerifyStore: { + bool checkContents = readInt(from) != 0; + bool repair = readInt(from) != 0; + startWork(); + bool errors = store->verifyStore(checkContents, repair); + stopWork(); + writeInt(errors, to); + break; + } + default: throw Error(format("invalid operation %1%") % op); }