about summary refs log tree commit diff
path: root/src/libstore/build.cc
diff options
context:
space:
mode:
authorEelco Dolstra <e.dolstra@tudelft.nl>2009-10-22T08·28+0000
committerEelco Dolstra <e.dolstra@tudelft.nl>2009-10-22T08·28+0000
commit8520542071d9ec4c5cc088f9a604d051f4880796 (patch)
tree92af43bc2ad37419af902ec5f15f7e4aa753d216 /src/libstore/build.cc
parent6b9f6b02225035c016cf73868a12aa26bc0ad225 (diff)
* When building in a chroot, make a copy of a file if hard-linking
  fails.  This is likely to happen after a `nix-store --optimise',
  because some files may have 32000 links (NIX-111).

Diffstat (limited to 'src/libstore/build.cc')
-rw-r--r--src/libstore/build.cc15
1 files changed, 13 insertions, 2 deletions
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index b52f82ebbb..61b7d33261 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -4,6 +4,7 @@
 #include "globals.hh"
 #include "local-store.hh"
 #include "util.hh"
+#include "archive.hh"
 
 #include <map>
 #include <iostream>
@@ -1604,8 +1605,18 @@ void DerivationGoal::startBuilder()
                 dirsInChroot.insert(*i);
             else {
                 Path p = chrootRootDir + *i;
-                if (link(i->c_str(), p.c_str()) == -1)
-                    throw SysError(format("linking `%1%' to `%2%'") % p % *i);
+                if (link(i->c_str(), p.c_str()) == -1) {
+                    /* Hard-linking fails if we exceed the maximum
+                       link count on a file (e.g. 32000 of ext3),
+                       which is quite possible after a `nix-store
+                       --optimise'.  Make a copy instead. */
+                    if (errno != EMLINK)
+                        throw SysError(format("linking `%1%' to `%2%'") % p % *i);
+                    StringSink sink;
+                    dumpPath(*i, sink);
+                    StringSource source(sink.s);
+                    restorePath(p, source);
+                }
             }
         }