diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc index 56e64369a..ba59083ca 100644 --- a/src/libstore/gc.cc +++ b/src/libstore/gc.cc @@ -82,6 +82,15 @@ void LocalStore::syncWithGC() } +void LocalStore::addIndirectRoot(const Path & path) +{ + string hash = printHash32(hashString(htSHA1, path)); + Path realRoot = canonPath((format("%1%/%2%/auto/%3%") + % nixStateDir % gcRootsDir % hash).str()); + createSymlink(realRoot, path, false); +} + + Path addPermRoot(const Path & _storePath, const Path & _gcRoot, bool indirect, bool allowOutsideRootsDir) { @@ -90,12 +99,8 @@ Path addPermRoot(const Path & _storePath, const Path & _gcRoot, assertStorePath(storePath); if (indirect) { - string hash = printHash32(hashString(htSHA1, gcRoot)); - Path realRoot = canonPath((format("%1%/%2%/auto/%3%") - % nixStateDir % gcRootsDir % hash).str()); - createSymlink(gcRoot, storePath, true); - createSymlink(realRoot, gcRoot, false); + store->addIndirectRoot(gcRoot); } else { diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 389be33a3..251f8922f 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -61,6 +61,8 @@ public: void addTempRoot(const Path & path); + void addIndirectRoot(const Path & path); + void syncWithGC(); }; diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc index da63765cd..8dd87d046 100644 --- a/src/libstore/remote-store.cc +++ b/src/libstore/remote-store.cc @@ -253,6 +253,15 @@ void RemoteStore::addTempRoot(const Path & path) } +void RemoteStore::addIndirectRoot(const Path & path) +{ + writeInt(wopAddIndirectRoot, to); + writeString(path, to); + processStderr(); + readInt(from); +} + + void RemoteStore::syncWithGC() { writeInt(wopSyncWithGC, to); diff --git a/src/libstore/remote-store.hh b/src/libstore/remote-store.hh index ad29305db..4b6983045 100644 --- a/src/libstore/remote-store.hh +++ b/src/libstore/remote-store.hh @@ -49,6 +49,8 @@ public: void addTempRoot(const Path & path); + void addIndirectRoot(const Path & path); + void syncWithGC(); private: diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 67d230ca7..795488d17 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -91,6 +91,13 @@ public: The root disappears as soon as we exit. */ virtual void addTempRoot(const Path & path) = 0; + /* Add an indirect root, which is merely a symlink to `path' from + /nix/var/nix/gcroots/auto/. `path' is supposed + to be a symlink to a store path. The garbage collector will + automatically remove the indirect root when it finds that + `path' has disappeared. */ + virtual void addIndirectRoot(const Path & path) = 0; + /* Acquire the global GC lock, then immediately release it. This function must be called after registering a new permanent root, but before exiting. Otherwise, it is possible that a running diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh index 8b1d4e15d..ff47fdd67 100644 --- a/src/libstore/worker-protocol.hh +++ b/src/libstore/worker-protocol.hh @@ -19,7 +19,8 @@ typedef enum { wopBuildDerivations, wopEnsurePath, wopAddTempRoot, - wopSyncWithGC + wopAddIndirectRoot, + wopSyncWithGC, } WorkerOp; diff --git a/src/nix-worker/main.cc b/src/nix-worker/main.cc index c8abe1429..80db782e9 100644 --- a/src/nix-worker/main.cc +++ b/src/nix-worker/main.cc @@ -269,6 +269,15 @@ static void performOp(Source & from, Sink & to, unsigned int op) break; } + case wopAddIndirectRoot: { + Path path = absPath(readString(from)); + startWork(); + store->addIndirectRoot(path); + stopWork(); + writeInt(1, to); + break; + } + case wopSyncWithGC: { startWork(); store->syncWithGC(); @@ -473,6 +482,7 @@ void run(Strings args) else if (daemon) { if (setuidMode) throw Error("daemon cannot be started in setuid mode"); + chdir("/"); daemonLoop(); }