From 6fe13e6aba771452e2637d9a8102569c1007d919 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Sat, 18 Feb 2012 01:23:52 +0100 Subject: [PATCH] Fix chroots builds MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 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. --- src/libstore/build.cc | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/src/libstore/build.cc b/src/libstore/build.cc index e60ea2106c..138c40070b 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 #include @@ -771,6 +772,9 @@ private: /* RAII object to delete the chroot directory. */ boost::shared_ptr 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); } }