diff options
author | Eelco Dolstra <e.dolstra@tudelft.nl> | 2012-02-18T00·23+0100 |
---|---|---|
committer | Eelco Dolstra <e.dolstra@tudelft.nl> | 2012-02-18T00·23+0100 |
commit | 6fe13e6aba771452e2637d9a8102569c1007d919 (patch) | |
tree | 049f9493fe9740d1249bae7424aacea9bb98d496 | |
parent | bd013b6f987c23c3b99b639ba7cdbc7b694a13f5 (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.cc | 16 |
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); } } |