about summary refs log tree commit diff
path: root/src/libstore/gc.cc
diff options
context:
space:
mode:
authorEelco Dolstra <eelco.dolstra@logicblox.com>2012-07-26T19·14-0400
committerEelco Dolstra <eelco.dolstra@logicblox.com>2012-07-26T19·14-0400
commit8c7910083976e255300efa797030448f5a1cb864 (patch)
treeafbd7a37d0724feb408a2d025364ed3938b5673a /src/libstore/gc.cc
parentaa115e22df1c80e8878237a9e704d7d70783a243 (diff)
parent3a4623afbbc1bff85bde33167d36e8c5a4a3df0d (diff)
Merge branch 'master' into no-manifests
Diffstat (limited to 'src/libstore/gc.cc')
-rw-r--r--src/libstore/gc.cc37
1 files changed, 37 insertions, 0 deletions
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index f6ed7dd2264e..874efe4d32d9 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -436,6 +436,8 @@ bool LocalStore::tryToDelete(GCState & state, const Path & path)
 {
     checkInterrupt();
 
+    if (path == linksDir) return true;
+
     struct stat st;
     if (lstat(path.c_str(), &st)) {
         if (errno == ENOENT) return true;
@@ -569,6 +571,37 @@ bool LocalStore::tryToDelete(GCState & state, const Path & path)
 }
 
 
+/* Unlink all files in /nix/store/.links that have a link count of 1,
+   which indicates that there are no other links and so they can be
+   safely deleted.  FIXME: race condition with optimisePath(): we
+   might see a link count of 1 just before optimisePath() increases
+   the link count. */
+void LocalStore::removeUnusedLinks()
+{
+    AutoCloseDir dir = opendir(linksDir.c_str());
+    if (!dir) throw SysError(format("opening directory `%1%'") % linksDir);
+
+    struct dirent * dirent;
+    while (errno = 0, dirent = readdir(dir)) {
+        checkInterrupt();
+        string name = dirent->d_name;
+        if (name == "." || name == "..") continue;
+        Path path = linksDir + "/" + name;
+
+        struct stat st;
+        if (lstat(path.c_str(), &st) == -1)
+            throw SysError(format("statting `%1%'") % path);
+
+        if (st.st_nlink != 1) continue;
+
+        printMsg(lvlTalkative, format("deleting unused link `%1%'") % path);
+
+        if (unlink(path.c_str()) == -1)
+            throw SysError(format("deleting `%1%'") % path);
+    }
+}
+
+
 void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
 {
     GCState state(results);
@@ -682,6 +715,10 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
        released. */
     foreach (PathSet::iterator, i, state.invalidated)
         deleteGarbage(state, *i);
+
+    /* Clean up the links directory. */
+    printMsg(lvlError, format("deleting unused links..."));
+    removeUnusedLinks();
 }