about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2012-02-18T00·23+0100
committerEelco Dolstra <e.dolstra@tudelft.nl>2012-02-18T00·23+0100
commit6fe13e6aba771452e2637d9a8102569c1007d919 (patch)
tree049f9493fe9740d1249bae7424aacea9bb98d496
parentbd013b6f987c23c3b99b639ba7cdbc7b694a13f5 (diff)
Fix chroots builds
Chroots are initialised by hard-linking inputs from the Nix store to
the chroot.  This doesn't work if the input has its immutable bit set,
because it's forbidden to create hard links to immutable files.  So
temporarily clear the immutable bit when creating and destroying the
chroot.

Note that making regular files in the Nix store immutable isn't very
reliable, since the bit can easily become cleared: for instance, if we
run the garbage collector after running ‘nix-store --optimise’.  So
maybe we should only make directories immutable.
-rw-r--r--src/libstore/build.cc16
1 files changed, 16 insertions, 0 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index e60ea2106ccd..138c40070b40 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -7,6 +7,7 @@
 #include "local-store.hh"
 #include "util.hh"
 #include "archive.hh"
+#include "immutable.hh"
 
 #include <map>
 #include <iostream>
@@ -771,6 +772,9 @@ private:
     /* RAII object to delete the chroot directory. */
     boost::shared_ptr<AutoDelete> autoDelChroot;
 
+    /* All inputs that are regular files. */
+    PathSet regularInputPaths;
+
     /* Whether this is a fixed-output derivation. */
     bool fixedOutput;
     
@@ -1291,6 +1295,11 @@ void DerivationGoal::buildDone()
 
         /* Delete the chroot (if we were using one). */
         autoDelChroot.reset(); /* this runs the destructor */
+
+        /* Deleting the chroot will have caused the immutable bits on
+           hard-linked inputs to be cleared.  So set them again. */
+        foreach (PathSet::iterator, i, regularInputPaths)
+            makeImmutable(*i);
         
         /* Compute the FS closure of the outputs and register them as
            being valid. */
@@ -1687,6 +1696,10 @@ void DerivationGoal::startBuilder()
             if (S_ISDIR(st.st_mode))
                 dirsInChroot.insert(*i);
             else {
+                /* Creating a hard link to *i is impossible if its
+                   immutable bit is set.  So clear it first. */
+                makeMutable(*i);
+                
                 Path p = chrootRootDir + *i;
                 if (link(i->c_str(), p.c_str()) == -1) {
                     /* Hard-linking fails if we exceed the maximum
@@ -1700,6 +1713,9 @@ void DerivationGoal::startBuilder()
                     StringSource source(sink.s);
                     restorePath(p, source);
                 }
+                
+                makeImmutable(*i);
+                regularInputPaths.insert(*i);
             }
         }