about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Makefile.config.in2
-rw-r--r--configure.ac19
-rw-r--r--corepkgs/buildenv.nix18
-rw-r--r--doc/manual/command-ref/conf-file.xml58
-rw-r--r--doc/manual/command-ref/nix-shell.xml4
-rw-r--r--doc/manual/expressions/builtins.xml20
-rw-r--r--doc/manual/installation/prerequisites-source.xml2
-rw-r--r--doc/manual/release-notes/release-notes.xml1
-rw-r--r--doc/manual/release-notes/rl-0.10.1.xml4
-rw-r--r--doc/manual/release-notes/rl-0.10.xml4
-rw-r--r--doc/manual/release-notes/rl-0.11.xml4
-rw-r--r--doc/manual/release-notes/rl-0.12.xml4
-rw-r--r--doc/manual/release-notes/rl-0.13.xml4
-rw-r--r--doc/manual/release-notes/rl-0.14.xml6
-rw-r--r--doc/manual/release-notes/rl-0.15.xml4
-rw-r--r--doc/manual/release-notes/rl-0.16.xml4
-rw-r--r--doc/manual/release-notes/rl-0.6.xml4
-rw-r--r--doc/manual/release-notes/rl-0.7.xml4
-rw-r--r--doc/manual/release-notes/rl-0.8.1.xml4
-rw-r--r--doc/manual/release-notes/rl-0.8.xml4
-rw-r--r--doc/manual/release-notes/rl-0.9.1.xml4
-rw-r--r--doc/manual/release-notes/rl-0.9.2.xml4
-rw-r--r--doc/manual/release-notes/rl-0.9.xml4
-rw-r--r--doc/manual/release-notes/rl-1.0.xml4
-rw-r--r--doc/manual/release-notes/rl-1.1.xml4
-rw-r--r--doc/manual/release-notes/rl-1.10.xml2
-rw-r--r--doc/manual/release-notes/rl-1.11.xml105
-rw-r--r--doc/manual/release-notes/rl-1.2.xml4
-rw-r--r--doc/manual/release-notes/rl-1.3.xml4
-rw-r--r--doc/manual/release-notes/rl-1.4.xml4
-rw-r--r--doc/manual/release-notes/rl-1.5.1.xml4
-rw-r--r--doc/manual/release-notes/rl-1.5.2.xml4
-rw-r--r--doc/manual/release-notes/rl-1.5.xml4
-rw-r--r--doc/manual/release-notes/rl-1.6.1.xml4
-rw-r--r--doc/manual/release-notes/rl-1.6.xml4
-rw-r--r--doc/manual/release-notes/rl-1.7.xml4
-rw-r--r--doc/manual/release-notes/rl-1.8.xml4
-rw-r--r--doc/manual/release-notes/rl-1.9.xml2
-rw-r--r--mk/lib.mk4
-rw-r--r--nix.spec.in1
-rw-r--r--release.nix8
-rw-r--r--scripts/download-from-binary-cache.pl.in2
-rwxr-xr-xscripts/nix-build.in3
-rwxr-xr-xscripts/nix-copy-closure.in1
-rwxr-xr-xscripts/resolve-system-dependencies.pl.in2
-rw-r--r--src/libexpr/eval.cc11
-rw-r--r--src/libexpr/local.mk5
-rw-r--r--src/libexpr/nixexpr.cc5
-rw-r--r--src/libexpr/primops.cc2
-rw-r--r--src/libstore/build.cc264
-rw-r--r--src/libstore/local-store.cc9
-rw-r--r--src/libstore/local.mk2
-rw-r--r--src/libstore/optimise-store.cc11
-rw-r--r--src/libstore/pathlocks.cc6
-rw-r--r--src/libstore/remote-store.cc12
-rw-r--r--src/libstore/store-api.hh14
-rw-r--r--src/libstore/worker-protocol.hh2
-rw-r--r--src/libutil/affinity.cc10
-rw-r--r--src/libutil/compression.cc1
-rw-r--r--src/libutil/util.cc8
-rw-r--r--src/libutil/util.hh6
-rw-r--r--src/nix-daemon/nix-daemon.cc15
-rw-r--r--src/nix-env/nix-env.cc12
-rw-r--r--src/nix-store/nix-store.cc3
64 files changed, 516 insertions, 246 deletions
diff --git a/Makefile.config.in b/Makefile.config.in
index df18e9336d1f..f0de4da37855 100644
--- a/Makefile.config.in
+++ b/Makefile.config.in
@@ -4,10 +4,12 @@ CFLAGS = @CFLAGS@
 CXX = @CXX@
 CXXFLAGS = @CXXFLAGS@
 HAVE_SODIUM = @HAVE_SODIUM@
+LIBCURL_LIBS = @LIBCURL_LIBS@
 OPENSSL_LIBS = @OPENSSL_LIBS@
 PACKAGE_NAME = @PACKAGE_NAME@
 PACKAGE_VERSION = @PACKAGE_VERSION@
 SODIUM_LIBS = @SODIUM_LIBS@
+SQLITE3_LIBS = @SQLITE3_LIBS@
 bash = @bash@
 bindir = @bindir@
 bsddiff_compat_include = @bsddiff_compat_include@
diff --git a/configure.ac b/configure.ac
index bade079b3b53..3a24053bb6a1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -77,18 +77,7 @@ static char buf[1024];]],
 AC_LANG_POP(C++)
 
 
-# Check for chroot support (requires chroot() and bind mounts).
-AC_CHECK_FUNCS([chroot])
-AC_CHECK_FUNCS([unshare])
 AC_CHECK_FUNCS([statvfs])
-AC_CHECK_HEADERS([sched.h])
-AC_CHECK_HEADERS([sys/param.h])
-AC_CHECK_HEADERS([sys/mount.h], [], [],
-[#ifdef HAVE_SYS_PARAM_H
-# include <sys/param.h>
-# endif
-])
-AC_CHECK_HEADERS([sys/syscall.h])
 
 
 # Check for lutimes, optionally used for changing the mtime of
@@ -96,10 +85,6 @@ AC_CHECK_HEADERS([sys/syscall.h])
 AC_CHECK_FUNCS([lutimes])
 
 
-# Check for sched_setaffinity.
-AC_CHECK_FUNCS([sched_setaffinity])
-
-
 # Check whether the store optimiser can optimise symlinks.
 AC_MSG_CHECKING([whether it is possible to create a link to a symlink])
 ln -s bla tmp_link
@@ -123,10 +108,6 @@ AC_CHECK_HEADER([err.h], [], [bsddiff_compat_include="-Icompat-include"])
 AC_SUBST([bsddiff_compat_include])
 
 
-# Check for <linux/fs.h> (for immutable file support).
-AC_CHECK_HEADERS([linux/fs.h])
-
-
 AC_DEFUN([NEED_PROG],
 [
 AC_PATH_PROG($1, $2)
diff --git a/corepkgs/buildenv.nix b/corepkgs/buildenv.nix
index 4a23d15a9ab8..ab1ce13f2cf6 100644
--- a/corepkgs/buildenv.nix
+++ b/corepkgs/buildenv.nix
@@ -23,10 +23,20 @@ derivation {
   # network traffic, so don't do that.
   preferLocalBuild = true;
 
-  __impureHostDeps = [
-    "/usr/lib/libSystem.dylib"
-    "/usr/lib/system"
-  ];
+  __sandboxProfile = ''
+    (allow sysctl-read)
+    (allow file-read*
+           (literal "/usr/lib/libSystem.dylib")
+           (literal "/usr/lib/libSystem.B.dylib")
+           (literal "/usr/lib/libobjc.A.dylib")
+           (literal "/usr/lib/libobjc.dylib")
+           (literal "/usr/lib/libauto.dylib")
+           (literal "/usr/lib/libc++abi.dylib")
+           (literal "/usr/lib/libc++.1.dylib")
+           (literal "/usr/lib/libDiagnosticMessagesClient.dylib")
+           (subpath "/usr/lib/system")
+           (subpath "/dev"))
+  '';
 
   inherit chrootDeps;
 }
diff --git a/doc/manual/command-ref/conf-file.xml b/doc/manual/command-ref/conf-file.xml
index c947d19fa0e1..daaf00ac3905 100644
--- a/doc/manual/command-ref/conf-file.xml
+++ b/doc/manual/command-ref/conf-file.xml
@@ -224,16 +224,16 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para>
   </varlistentry>
 
 
-  <varlistentry><term><literal>build-use-chroot</literal></term>
+  <varlistentry><term><literal>build-use-sandbox</literal></term>
 
     <listitem><para>If set to <literal>true</literal>, builds will be
-    performed in a <emphasis>chroot environment</emphasis>, i.e.,
+    performed in a <emphasis>sandboxed environment</emphasis>, i.e.,
     they’re isolated from the normal file system hierarchy and will
     only see their dependencies in the Nix store, the temporary build
     directory, private versions of <filename>/proc</filename>,
     <filename>/dev</filename>, <filename>/dev/shm</filename> and
-    <filename>/dev/pts</filename>, and the paths configured with the
-    <link linkend='conf-build-chroot-dirs'><literal>build-chroot-dirs</literal>
+    <filename>/dev/pts</filename> (on Linux), and the paths configured with the
+    <link linkend='conf-build-sandbox-paths'><literal>build-sandbox-paths</literal>
     option</link>. This is useful to prevent undeclared dependencies
     on files in directories such as <filename>/usr/bin</filename>. In
     addition, on Linux, builds run in private PID, mount, network, IPC
@@ -241,8 +241,8 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para>
     system (except that fixed-output derivations do not run in private
     network namespace to ensure they can access the network).</para>
 
-    <para>Currently, chroots only work on Linux and Mac OS X. The use
-    of a chroot requires that Nix is run as root (so you should use
+    <para>Currently, sandboxing only work on Linux and Mac OS X. The use
+    of a sandbox requires that Nix is run as root (so you should use
     the <link linkend='conf-build-users-group'>“build users”
     feature</link> to perform the actual builds under different users
     than root).</para>
@@ -250,7 +250,7 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para>
     <para>If this option is set to <literal>relaxed</literal>, then
     fixed-output derivations and derivations that have the
     <varname>__noChroot</varname> attribute set to
-    <literal>true</literal> do not run in chroots.</para>
+    <literal>true</literal> do not run in sandboxes.</para>
 
     <para>The default is <literal>false</literal>.</para>
 
@@ -259,17 +259,16 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para>
   </varlistentry>
 
 
-  <varlistentry xml:id="conf-build-chroot-dirs"><term><literal>build-chroot-dirs</literal></term>
+  <varlistentry xml:id="conf-build-sandbox-paths">
+    <term><literal>build-sandbox-paths</literal></term>
 
-    <listitem><para>A list of paths bind-mounted into Nix chroot
-    environments.  Contrary to what the name suggests, the specified
-    paths do not have to be directories; you can bind-mount other
-    types of files as well.  You can use the syntax
+    <listitem><para>A list of paths bind-mounted into Nix sandbox
+    environments. You can use the syntax
     <literal><replaceable>target</replaceable>=<replaceable>source</replaceable></literal>
-    to mount a path in a different location in the chroot; for
+    to mount a path in a different location in the sandbox; for
     instance, <literal>/bin=/nix-bin</literal> will mount the path
     <literal>/nix-bin</literal> as <literal>/bin</literal> inside the
-    chroot.</para>
+    sandbox.</para>
 
     <para>Depending on how Nix was built, the default value for this option
     may be empty or provide <filename>/bin/sh</filename> as a
@@ -278,10 +277,11 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para>
   </varlistentry>
 
 
-  <varlistentry xml:id="conf-build-extra-chroot-dirs"><term><literal>build-extra-chroot-dirs</literal></term>
+  <varlistentry xml:id="conf-build-extra-sandbox-paths">
+    <term><literal>build-extra-sandbox-paths</literal></term>
 
     <listitem><para>A list of additional paths appended to
-    <option>build-chroot-dirs</option>. Useful if you want to extend
+    <option>build-sandbox-paths</option>. Useful if you want to extend
     its default value.</para></listitem>
 
   </varlistentry>
@@ -426,7 +426,7 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para>
     <listitem><para>The maximum number of parallel HTTP connections
     used by the binary cache substituter to get NAR info files.  This
     number should be high to minimise latency.  It defaults to
-    150.</para></listitem>
+    25.</para></listitem>
 
   </varlistentry>
 
@@ -593,19 +593,21 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para>
       between different versions of the same system to be hard-coded into nix.
       </para>
 
-      <para>The hook is passed the derivation path and, if chroots are enabled,
-      the chroot directory. It can then modify the chroot and send a series of
+      <para>The hook is passed the derivation path and, if sandboxes are enabled,
+      the sandbox directory. It can then modify the sandbox and send a series of
       commands to modify various settings to stdout. The currently recognized
       commands are:</para>
 
       <variablelist>
-        <varlistentry xml:id="extra-chroot-dirs"><term><literal>extra-chroot-dirs</literal></term>
+        <varlistentry xml:id="extra-sandbox-paths">
+          <term><literal>extra-sandbox-paths</literal></term>
 
           <listitem>
 
             <para>Pass a list of files and directories to be included in the
-            chroot for this build. One entry per line, terminated by an empty
-            line. Entries have the same format as build-chroot-dirs.</para>
+            sandbox for this build. One entry per line, terminated by an empty
+            line. Entries have the same format as
+            <literal>build-sandbox-paths</literal>.</para>
 
           </listitem>
 
@@ -616,6 +618,18 @@ flag, e.g. <literal>--option gc-keep-outputs false</literal>.</para>
   </varlistentry>
 
 
+  <varlistentry xml:id="conf-build-repeat"><term><literal>build-repeat</literal></term>
+
+    <listitem><para>How many times to repeat builds to check whether
+    they are deterministic. The default value is 0. If the value is
+    non-zero, every build is repeated the specified number of
+    times. If the contents of any of the runs differs from the
+    previous ones, the build is rejected and the resulting store paths
+    are not registered as “valid” in Nix’s database.</para></listitem>
+
+  </varlistentry>
+
+
 </variablelist>
 
 </para>
diff --git a/doc/manual/command-ref/nix-shell.xml b/doc/manual/command-ref/nix-shell.xml
index 9e3e6d1882ba..a13d9d7c1b34 100644
--- a/doc/manual/command-ref/nix-shell.xml
+++ b/doc/manual/command-ref/nix-shell.xml
@@ -252,8 +252,8 @@ dependencies in Nixpkgs.</para>
 <para>The lines starting with <literal>#! nix-shell</literal> specify
 <command>nix-shell</command> options (see above). Note that you cannot
 write <literal>#1 /usr/bin/env nix-shell -i ...</literal> because
-<command>/usr/bin/env</command> does not support passing options to
-the interpreter.</para>
+many operating systems only allow one argument in
+<literal>#!</literal> lines.</para>
 
 <para>For example, here is a Python script that depends on Python and
 the <literal>prettytable</literal> package:
diff --git a/doc/manual/expressions/builtins.xml b/doc/manual/expressions/builtins.xml
index 3b664479d27b..40d90f78d521 100644
--- a/doc/manual/expressions/builtins.xml
+++ b/doc/manual/expressions/builtins.xml
@@ -335,7 +335,7 @@ stdenv.mkDerivation {
   </varlistentry>
 
 
-  <varlistentry><term><function>builtins.foldl’</function> 
+  <varlistentry><term><function>builtins.foldl’</function>
     <replaceable>op</replaceable> <replaceable>nul</replaceable> <replaceable>list</replaceable></term>
 
     <listitem><para>Reduce a list by applying a binary operator, from
@@ -348,6 +348,24 @@ stdenv.mkDerivation {
   </varlistentry>
 
 
+  <varlistentry><term><function>builtins.functionArgs</function>
+    <replaceable>f</replaceable></term>
+
+    <listitem><para>
+    Return a set containing the names of the formal arguments expected
+    by the function <replaceable>f</replaceable>.
+    The value of each attribute is a Boolean denoting whether the corresponding
+    argument has a default value.  For instance,
+    <literal>functionArgs ({ x, y ? 123}: ...)  =  { x = false; y = true; }</literal>.
+    </para>
+
+    <para>"Formal argument" here refers to the attributes pattern-matched by
+    the function.  Plain lambdas are not included, e.g.
+    <literal>functionArgs (x: ...)  =  { }</literal>.
+    </para></listitem>
+  </varlistentry>
+
+
   <varlistentry><term><function>builtins.fromJSON</function> <replaceable>e</replaceable></term>
 
     <listitem><para>Convert a JSON string to a Nix
diff --git a/doc/manual/installation/prerequisites-source.xml b/doc/manual/installation/prerequisites-source.xml
index 01d52c74030a..49036d940bd4 100644
--- a/doc/manual/installation/prerequisites-source.xml
+++ b/doc/manual/installation/prerequisites-source.xml
@@ -36,7 +36,7 @@
   distribution does not provide them.</para></listitem>
 
   <listitem><para>The <link
-  xlink:href="http://www.hpl.hp.com/personal/Hans_Boehm/gc/">Boehm
+  xlink:href="http://www.hboehm.info/gc/">Boehm
   garbage collector</link> to reduce the evaluator’s memory
   consumption (optional).  To enable it, install
   <literal>pkgconfig</literal> and the Boehm garbage collector, and
diff --git a/doc/manual/release-notes/release-notes.xml b/doc/manual/release-notes/release-notes.xml
index 4ea57c99c3a4..0aa3e8717aa1 100644
--- a/doc/manual/release-notes/release-notes.xml
+++ b/doc/manual/release-notes/release-notes.xml
@@ -12,6 +12,7 @@
 </partintro>
 -->
 
+<xi:include href="rl-1.11.xml" />
 <xi:include href="rl-1.10.xml" />
 <xi:include href="rl-1.9.xml" />
 <xi:include href="rl-1.8.xml" />
diff --git a/doc/manual/release-notes/rl-0.10.1.xml b/doc/manual/release-notes/rl-0.10.1.xml
index 05cd2f654353..95829323d4fb 100644
--- a/doc/manual/release-notes/rl-0.10.1.xml
+++ b/doc/manual/release-notes/rl-0.10.1.xml
@@ -4,10 +4,10 @@
       version="5.0"
       xml:id="ch-relnotes-0.10.1">
 
-<title>Release 0.10.1 (October 11, 2006)</title>
+<title>Release 0.10.1 (2006-10-11)</title>
 
 <para>This release fixes two somewhat obscure bugs that occur when
 evaluating Nix expressions that are stored inside the Nix store
 (<literal>NIX-67</literal>).  These do not affect most users.</para>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-0.10.xml b/doc/manual/release-notes/rl-0.10.xml
index 7815ae75b1b8..9afec4de94de 100644
--- a/doc/manual/release-notes/rl-0.10.xml
+++ b/doc/manual/release-notes/rl-0.10.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ch-relnotes-0.10">
 
-<title>Release 0.10 (October 6, 2006)</title>
+<title>Release 0.10 (2006-10-06)</title>
 
 <note><para>This version of Nix uses Berkeley DB 4.4 instead of 4.3.
 The database is upgraded automatically, but you should be careful not
@@ -320,4 +320,4 @@ irreversible.</para></warning>
 
 </itemizedlist>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-0.11.xml b/doc/manual/release-notes/rl-0.11.xml
index 9c5d8b8beb4b..7ad0ab5b71ad 100644
--- a/doc/manual/release-notes/rl-0.11.xml
+++ b/doc/manual/release-notes/rl-0.11.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ssec-relnotes-0.11">
 
-<title>Release 0.11 (December 31, 2007)</title>
+<title>Release 0.11 (2007-12-31)</title>
 
 <para>Nix 0.11 has many improvements over the previous stable release.
 The most important improvement is secure multi-user support.  It also
@@ -258,4 +258,4 @@ on Nix.  Here is an (incomplete) list:</para>
 
 </itemizedlist>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-0.12.xml b/doc/manual/release-notes/rl-0.12.xml
index 1f04609b1654..fdba8c4d577f 100644
--- a/doc/manual/release-notes/rl-0.12.xml
+++ b/doc/manual/release-notes/rl-0.12.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ssec-relnotes-0.12">
 
-<title>Release 0.12 (November 20, 2008)</title>
+<title>Release 0.12 (2008-11-20)</title>
 
 <itemizedlist>
 
@@ -172,4 +172,4 @@ the following paths will be downloaded/copied (30.02 MiB):
 
 </itemizedlist>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-0.13.xml b/doc/manual/release-notes/rl-0.13.xml
index 9cf144e4ea23..cce2e4a26b05 100644
--- a/doc/manual/release-notes/rl-0.13.xml
+++ b/doc/manual/release-notes/rl-0.13.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ssec-relnotes-0.13">
 
-<title>Release 0.13 (November 5, 2009)</title>
+<title>Release 0.13 (2009-11-05)</title>
 
 <para>This is primarily a bug fix release.  It has some new
 features:</para>
@@ -103,4 +103,4 @@ features:</para>
 
 </itemizedlist>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-0.14.xml b/doc/manual/release-notes/rl-0.14.xml
index a671db3b8588..e5fe9da78e7e 100644
--- a/doc/manual/release-notes/rl-0.14.xml
+++ b/doc/manual/release-notes/rl-0.14.xml
@@ -2,7 +2,9 @@
       xmlns:xlink="http://www.w3.org/1999/xlink"
       xmlns:xi="http://www.w3.org/2001/XInclude"
       version="5.0"
-      xml:id="ssec-relnotes-0.14"><title>Release 0.14 (February 4, 2010)</title>
+      xml:id="ssec-relnotes-0.14">
+
+<title>Release 0.14 (2010-02-04)</title>
 
 <para>This release has the following improvements:</para>
 
@@ -41,4 +43,4 @@
 
 </itemizedlist>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-0.15.xml b/doc/manual/release-notes/rl-0.15.xml
index b76f674ba123..9f58a8efc5d4 100644
--- a/doc/manual/release-notes/rl-0.15.xml
+++ b/doc/manual/release-notes/rl-0.15.xml
@@ -4,11 +4,11 @@
       version="5.0"
       xml:id="ssec-relnotes-0.15">
 
-<title>Release 0.15 (March 17, 2010)</title>
+<title>Release 0.15 (2010-03-17)</title>
 
 <para>This is a bug-fix release.  Among other things, it fixes
 building on Mac OS X (Snow Leopard), and improves the contents of
 <filename>/etc/passwd</filename> and <filename>/etc/group</filename>
 in <literal>chroot</literal> builds.</para>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-0.16.xml b/doc/manual/release-notes/rl-0.16.xml
index 5254e5f9d658..af1edc0ebbe0 100644
--- a/doc/manual/release-notes/rl-0.16.xml
+++ b/doc/manual/release-notes/rl-0.16.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ssec-relnotes-0.16">
 
-<title>Release 0.16 (August 17, 2010)</title>
+<title>Release 0.16 (2010-08-17)</title>
 
 <para>This release has the following improvements:</para>
 
@@ -52,4 +52,4 @@
 
 </itemizedlist>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-0.6.xml b/doc/manual/release-notes/rl-0.6.xml
index 83d9dc897c42..6dc6521d3c2a 100644
--- a/doc/manual/release-notes/rl-0.6.xml
+++ b/doc/manual/release-notes/rl-0.6.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ch-relnotes-0.6">
 
-<title>Release 0.6 (November 14, 2004)</title>
+<title>Release 0.6 (2004-11-14)</title>
 
 <itemizedlist>
 
@@ -119,4 +119,4 @@
 
 </itemizedlist>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-0.7.xml b/doc/manual/release-notes/rl-0.7.xml
index fc8997fc1e36..6f95db4367db 100644
--- a/doc/manual/release-notes/rl-0.7.xml
+++ b/doc/manual/release-notes/rl-0.7.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ch-relnotes-0.7">
 
-<title>Release 0.7 (January 12, 2005)</title>
+<title>Release 0.7 (2005-01-12)</title>
 
 <itemizedlist>
 
@@ -32,4 +32,4 @@
 
 </itemizedlist>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-0.8.1.xml b/doc/manual/release-notes/rl-0.8.1.xml
index b4a855b553a5..f7ffca0f8d59 100644
--- a/doc/manual/release-notes/rl-0.8.1.xml
+++ b/doc/manual/release-notes/rl-0.8.1.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ch-relnotes-0.8.1">
 
-<title>Release 0.8.1 (April 13, 2005)</title>
+<title>Release 0.8.1 (2005-04-13)</title>
 
 <para>This is a bug fix release.</para>
 
@@ -18,4 +18,4 @@
 
 </itemizedlist>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-0.8.xml b/doc/manual/release-notes/rl-0.8.xml
index 970abb6e85e0..784b26c6b7d3 100644
--- a/doc/manual/release-notes/rl-0.8.xml
+++ b/doc/manual/release-notes/rl-0.8.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ch-relnotes-0.8">
 
-<title>Release 0.8 (April 11, 2005)</title>
+<title>Release 0.8 (2005-04-11)</title>
 
 <para>NOTE: the hashing scheme in Nix 0.8 changed (as detailed below).
 As a result, <command>nix-pull</command> manifests and channels built
@@ -243,4 +243,4 @@ $ nix-env -f .../i686-linux.nix -i -E 'x: x.firefoxWrapper'</screen>
 
 </para>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-0.9.1.xml b/doc/manual/release-notes/rl-0.9.1.xml
index a7d093aa8e02..85d11f416877 100644
--- a/doc/manual/release-notes/rl-0.9.1.xml
+++ b/doc/manual/release-notes/rl-0.9.1.xml
@@ -4,10 +4,10 @@
       version="5.0"
       xml:id="ch-relnotes-0.9.1">
 
-<title>Release 0.9.1 (September 20, 2005)</title>
+<title>Release 0.9.1 (2005-09-20)</title>
 
 <para>This bug fix release addresses a problem with the ATerm library
 when the <option>--with-aterm</option> flag in
 <command>configure</command> was <emphasis>not</emphasis> used.</para>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-0.9.2.xml b/doc/manual/release-notes/rl-0.9.2.xml
index 33141c8e94ff..cb705e98ac25 100644
--- a/doc/manual/release-notes/rl-0.9.2.xml
+++ b/doc/manual/release-notes/rl-0.9.2.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ch-relnotes-0.9.2">
 
-<title>Release 0.9.2 (September 21, 2005)</title>
+<title>Release 0.9.2 (2005-09-21)</title>
 
 <para>This bug fix release fixes two problems on Mac OS X:
 
@@ -25,4 +25,4 @@
 
 </para>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-0.9.xml b/doc/manual/release-notes/rl-0.9.xml
index 07dd87cd9f61..fd1e633f78ea 100644
--- a/doc/manual/release-notes/rl-0.9.xml
+++ b/doc/manual/release-notes/rl-0.9.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ch-relnotes-0.9">
 
-<title>Release 0.9 (September 16, 2005)</title>
+<title>Release 0.9 (2005-09-16)</title>
 
 <para>NOTE: this version of Nix uses Berkeley DB 4.3 instead of 4.2.
 The database is upgraded automatically, but you should be careful not
@@ -95,4 +95,4 @@ svnService = derivation {
 
 </itemizedlist>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-1.0.xml b/doc/manual/release-notes/rl-1.0.xml
index d000014eb311..ff11168d0932 100644
--- a/doc/manual/release-notes/rl-1.0.xml
+++ b/doc/manual/release-notes/rl-1.0.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ssec-relnotes-1.0">
 
-<title>Release 1.0 (May 11, 2012)</title>
+<title>Release 1.0 (2012-05-11)</title>
 
 <para>There have been numerous improvements and bug fixes since the
 previous release.  Here are the most significant:</para>
@@ -116,4 +116,4 @@ previous release.  Here are the most significant:</para>
 
 </itemizedlist>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-1.1.xml b/doc/manual/release-notes/rl-1.1.xml
index 7ee076f193e9..2f26e7a24273 100644
--- a/doc/manual/release-notes/rl-1.1.xml
+++ b/doc/manual/release-notes/rl-1.1.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ssec-relnotes-1.1">
 
-<title>Release 1.1 (July 18, 2012)</title>
+<title>Release 1.1 (2012-07-18)</title>
 
 <para>This release has the following improvements:</para>
 
@@ -97,4 +97,4 @@
 
 </itemizedlist>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-1.10.xml b/doc/manual/release-notes/rl-1.10.xml
index 7a90087487e9..689a95466343 100644
--- a/doc/manual/release-notes/rl-1.10.xml
+++ b/doc/manual/release-notes/rl-1.10.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ssec-relnotes-1.10">
 
-<title>Release 1.10 (September 3, 2015)</title>
+<title>Release 1.10 (2015-09-03)</title>
 
 <para>This is primarily a bug fix release. It also has a number of new
 features:</para>
diff --git a/doc/manual/release-notes/rl-1.11.xml b/doc/manual/release-notes/rl-1.11.xml
new file mode 100644
index 000000000000..4efcb9ba269f
--- /dev/null
+++ b/doc/manual/release-notes/rl-1.11.xml
@@ -0,0 +1,105 @@
+<section xmlns="http://docbook.org/ns/docbook"
+      xmlns:xlink="http://www.w3.org/1999/xlink"
+      xmlns:xi="http://www.w3.org/2001/XInclude"
+      version="5.0"
+      xml:id="ssec-relnotes-1.11">
+
+<title>Release 1.11 (2015-01-05)</title>
+
+<para>This is primarily a bug fix release. It also has a number of new
+features:</para>
+
+<itemizedlist>
+
+  <listitem>
+    <para><command>nix-prefetch-url</command> can now download URLs
+    specified in a Nix expression. For example,
+
+<screen>
+$ nix-prefetch-url -A hello.src
+</screen>
+
+    will prefetch the file specified by the
+    <function>fetchurl</function> call in the attribute
+    <literal>hello.src</literal> from the Nix expression in the
+    current directory, and print the cryptographic hash of the
+    resulting file on stdout. This differs from <literal>nix-build -A
+    hello.src</literal> in that it doesn't verify the hash, and is
+    thus useful when you’re updating a Nix expression.</para>
+
+    <para>You can also prefetch the result of functions that unpack a
+    tarball, such as <function>fetchFromGitHub</function>. For example:
+
+<screen>
+$ nix-prefetch-url --unpack https://github.com/NixOS/patchelf/archive/0.8.tar.gz
+</screen>
+
+    or from a Nix expression:
+
+<screen>
+$ nix-prefetch-url -A nix-repl.src
+</screen>
+
+    </para>
+
+  </listitem>
+
+  <listitem>
+    <para>The builtin function
+    <function>&lt;nix/fetchurl.nix></function> now supports
+    downloading and unpacking NARs. This removes the need to have
+    multiple downloads in the Nixpkgs stdenv bootstrap process (like a
+    separate busybox binary for Linux, or curl/mkdir/sh/bzip2 for
+    Darwin). Now all those files can be combined into a single NAR,
+    optionally compressed using <command>xz</command>.</para>
+  </listitem>
+
+  <listitem>
+    <para>Nix now supports SHA-512 hashes for verifying fixed-output
+    derivations, and in <function>builtins.hashString</function>.</para>
+  </listitem>
+
+  <listitem>
+    <para>
+      The new flag <option>--option build-repeat
+      <replaceable>N</replaceable></option> will cause every build to
+      be executed <replaceable>N</replaceable>+1 times. If the build
+      output differs between any round, the build is rejected, and the
+      output paths are not registered as valid. This is primarily
+      useful to verify build determinism. (We already had a
+      <option>--check</option> option to repeat a previously succeeded
+      build. However, with <option>--check</option>, non-deterministic
+      builds are registered in the DB. Preventing that is useful for
+      Hydra to ensure that non-deterministic builds don't end up
+      getting published to the binary cache.)
+    </para>
+  </listitem>
+
+  <listitem>
+    <para>Improved FreeBSD support.</para>
+  </listitem>
+
+  <listitem>
+    <para><command>nix-env -qa --xml --meta</command> now prints
+    license information.</para>
+  </listitem>
+
+  <listitem>
+    <para>The maximum number of parallel TCP connections that the
+    binary cache substituter will use has been decreased from 150 to
+    25. This should prevent upsetting some broken NAT routers, and
+    also improves performance.</para>
+  </listitem>
+
+  <listitem>
+    <para>All "chroot"-containing strings got renamed to "sandbox".
+      In particular, some Nix options got renamed, but the old names
+      are still accepted as lower-priority aliases.
+    </para>
+  </listitem>
+
+</itemizedlist>
+
+<para>This release has contributions from TODO.</para>
+
+</section>
diff --git a/doc/manual/release-notes/rl-1.2.xml b/doc/manual/release-notes/rl-1.2.xml
index 6c05444ff76e..dc272c420ddb 100644
--- a/doc/manual/release-notes/rl-1.2.xml
+++ b/doc/manual/release-notes/rl-1.2.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ssec-relnotes-1.2">
 
-<title>Release 1.2 (December 6, 2012)</title>
+<title>Release 1.2 (2012-12-06)</title>
 
 <para>This release has the following improvements and changes:</para>
 
@@ -154,4 +154,4 @@ $ mount -o remount,ro,bind /nix/store
 <para>This release has contributions from Eelco Dolstra, Florian
 Friesdorf, Mats Erik Andersson and Shea Levy.</para>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-1.3.xml b/doc/manual/release-notes/rl-1.3.xml
index 04169ed01b82..e2009ee3ba4b 100644
--- a/doc/manual/release-notes/rl-1.3.xml
+++ b/doc/manual/release-notes/rl-1.3.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ssec-relnotes-1.3">
 
-<title>Release 1.3 (January 4, 2013)</title>
+<title>Release 1.3 (2013-01-04)</title>
 
 <para>This is primarily a bug fix release.  When this version is first
 run on Linux, it removes any immutable bits from the Nix store and
@@ -16,4 +16,4 @@ efficient.)</para>
 <para>This release has contributions from Eelco Dolstra and Stuart
 Pernsteiner.</para>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-1.4.xml b/doc/manual/release-notes/rl-1.4.xml
index d48e43f21c1b..aefb22f2b934 100644
--- a/doc/manual/release-notes/rl-1.4.xml
+++ b/doc/manual/release-notes/rl-1.4.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ssec-relnotes-1.4">
 
-<title>Release 1.4 (February 26, 2013)</title>
+<title>Release 1.4 (2013-02-26)</title>
 
 <para>This release fixes a security bug in multi-user operation.  It
 was possible for derivations to cause the mode of files outside of the
@@ -36,4 +36,4 @@ xlink:href="https://github.com/NixOS/nix/commit/5526a282b5b44e9296e61e07d7d2626a
 
 </itemizedlist>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-1.5.1.xml b/doc/manual/release-notes/rl-1.5.1.xml
index 046960313ffd..035c8dbcbb16 100644
--- a/doc/manual/release-notes/rl-1.5.1.xml
+++ b/doc/manual/release-notes/rl-1.5.1.xml
@@ -4,9 +4,9 @@
       version="5.0"
       xml:id="ssec-relnotes-1.5.1">
 
-<title>Release 1.5.1 (February 28, 2013)</title>
+<title>Release 1.5.1 (2013-02-28)</title>
 
 <para>The bug fix to the bug fix had a bug itself, of course.  But
 this time it will work for sure!</para>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-1.5.2.xml b/doc/manual/release-notes/rl-1.5.2.xml
index d2f53bbdc0bd..7e81dd243284 100644
--- a/doc/manual/release-notes/rl-1.5.2.xml
+++ b/doc/manual/release-notes/rl-1.5.2.xml
@@ -4,9 +4,9 @@
       version="5.0"
       xml:id="ssec-relnotes-1.5.2">
 
-<title>Release 1.5.2 (May 13, 2013)</title>
+<title>Release 1.5.2 (2013-05-13)</title>
 
 <para>This is primarily a bug fix release.  It has contributions from
 Eelco Dolstra, Lluís Batlle i Rossell and Shea Levy.</para>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-1.5.xml b/doc/manual/release-notes/rl-1.5.xml
index 84e0e9024946..8e279d7693e0 100644
--- a/doc/manual/release-notes/rl-1.5.xml
+++ b/doc/manual/release-notes/rl-1.5.xml
@@ -4,9 +4,9 @@
       version="5.0"
       xml:id="ssec-relnotes-1.5">
 
-<title>Release 1.5 (February 27, 2013)</title>
+<title>Release 1.5 (2013-02-27)</title>
 
 <para>This is a brown paper bag release to fix a regression introduced
 by the hard link security fix in 1.4.</para>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-1.6.1.xml b/doc/manual/release-notes/rl-1.6.1.xml
index 1ca4dfebacdc..9ecc52734737 100644
--- a/doc/manual/release-notes/rl-1.6.1.xml
+++ b/doc/manual/release-notes/rl-1.6.1.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ssec-relnotes-1.6.1">
 
-<title>Release 1.6.1 (October 28, 2013)</title>
+<title>Release 1.6.1 (2013-10-28)</title>
 
 <para>This is primarily a bug fix release.  Changes of interest
 are:</para>
@@ -66,4 +66,4 @@ are:</para>
 
 </itemizedlist>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-1.6.xml b/doc/manual/release-notes/rl-1.6.xml
index a3d61faf2b73..580563420949 100644
--- a/doc/manual/release-notes/rl-1.6.xml
+++ b/doc/manual/release-notes/rl-1.6.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ssec-relnotes-1.6.0">
 
-<title>Release 1.6 (September 10, 2013)</title>
+<title>Release 1.6 (2013-09-10)</title>
 
 <para>In addition to the usual bug fixes, this release has several new
 features:</para>
@@ -124,4 +124,4 @@ in pkgs.bar
 Florian Friesdorf, Gergely Risko, Ivan Kozik, Ludovic Courtès and Shea
 Levy.</para>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-1.7.xml b/doc/manual/release-notes/rl-1.7.xml
index a9863b99cba0..44ecaa78da5f 100644
--- a/doc/manual/release-notes/rl-1.7.xml
+++ b/doc/manual/release-notes/rl-1.7.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ssec-relnotes-1.7">
 
-<title>Release 1.7 (April 11, 2014)</title>
+<title>Release 1.7 (2014-04-11)</title>
 
 <para>In addition to the usual bug fixes, this release has the
 following new features:</para>
@@ -260,4 +260,4 @@ error: attribute `nixUnstabl' missing, at /etc/nixos/configurations/misc/eelco/m
 Eelco Dolstra, Ian-Woo Kim, Ludovic Courtès, Maxim Ivanov, Petr
 Rockai, Ricardo M. Correia and Shea Levy.</para>
 
-</section>
\ No newline at end of file
+</section>
diff --git a/doc/manual/release-notes/rl-1.8.xml b/doc/manual/release-notes/rl-1.8.xml
index e551ee06055f..48caac2c6b60 100644
--- a/doc/manual/release-notes/rl-1.8.xml
+++ b/doc/manual/release-notes/rl-1.8.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ssec-relnotes-1.8">
 
-<title>Release 1.8 (December 14, 2014)</title>
+<title>Release 1.8 (2014-12-14)</title>
 
 <itemizedlist>
 
@@ -60,7 +60,7 @@ $ nix-store -l $(which xterm)
   <listitem><para><command>nix-copy-closure</command> now uses
   <command>nix-store --serve</command> on the remote side to send or
   receive closures. This fixes a race condition between
-  <command>nix-copy-closureE</command> and the garbage
+  <command>nix-copy-closure</command> and the garbage
   collector.</para></listitem>
 
   <listitem><para>Derivations can specify the new special attribute
diff --git a/doc/manual/release-notes/rl-1.9.xml b/doc/manual/release-notes/rl-1.9.xml
index e0c79e751ed7..c8406bd2077c 100644
--- a/doc/manual/release-notes/rl-1.9.xml
+++ b/doc/manual/release-notes/rl-1.9.xml
@@ -4,7 +4,7 @@
       version="5.0"
       xml:id="ssec-relnotes-1.9">
 
-<title>Release 1.9 (June 12, 2015)</title>
+<title>Release 1.9 (2015-06-12)</title>
 
 <para>In addition to the usual bug fixes, this release has the
 following new features:</para>
diff --git a/mk/lib.mk b/mk/lib.mk
index 4ad5c636c8d4..bb82801d3b4e 100644
--- a/mk/lib.mk
+++ b/mk/lib.mk
@@ -61,7 +61,9 @@ ifeq ($(BUILD_SHARED_LIBS), 1)
   endif
   ifneq ($(OS), Darwin)
    ifneq ($(OS), SunOS)
-    GLOBAL_LDFLAGS += -Wl,--no-copy-dt-needed-entries
+    ifneq ($(OS), FreeBSD)
+     GLOBAL_LDFLAGS += -Wl,--no-copy-dt-needed-entries
+    endif
    endif
   endif
   SET_RPATH_TO_LIBS ?= 1
diff --git a/nix.spec.in b/nix.spec.in
index 4dbfdfa09bc0..5fc34e1a0561 100644
--- a/nix.spec.in
+++ b/nix.spec.in
@@ -26,6 +26,7 @@ Requires: gzip
 Requires: xz
 BuildRequires: bzip2-devel
 BuildRequires: sqlite-devel
+BuildRequires: libcurl-devel
 
 # Hack to make that shitty RPM scanning hack shut up.
 Provides: perl(Nix::SSH)
diff --git a/release.nix b/release.nix
index 4269a3f76d8c..a6a745e27548 100644
--- a/release.nix
+++ b/release.nix
@@ -152,7 +152,7 @@ let
         src = tarball;
 
         buildInputs =
-          [ curl perl bzip2 openssl pkgconfig sqlite
+          [ curl perl bzip2 openssl pkgconfig sqlite xz libsodium
             # These are for "make check" only:
             graphviz libxml2 libxslt
           ];
@@ -281,7 +281,7 @@ let
       src = jobs.tarball;
       diskImage = (diskImageFun vmTools.diskImageFuns)
         { extraPackages =
-            [ "perl-DBD-SQLite" "perl-devel" "sqlite" "sqlite-devel" "bzip2-devel" "emacs" "perl-WWW-Curl" "libcurl-devel" ]
+            [ "perl-DBD-SQLite" "perl-devel" "sqlite" "sqlite-devel" "bzip2-devel" "emacs" "perl-WWW-Curl" "libcurl-devel" "openssl-devel" "xz-devel" ]
             ++ extraPackages; };
       memSize = 1024;
       meta.schedulingPriority = 50;
@@ -302,13 +302,13 @@ let
       src = jobs.tarball;
       diskImage = (diskImageFun vmTools.diskImageFuns)
         { extraPackages =
-            [ "libdbd-sqlite3-perl" "libsqlite3-dev" "libbz2-dev" "libwww-curl-perl" "libcurl-dev" ]
+            [ "libdbd-sqlite3-perl" "libsqlite3-dev" "libbz2-dev" "libwww-curl-perl" "libcurl-dev" "libcurl3-nss" "libssl-dev" "liblzma-dev" ]
             ++ extraPackages; };
       memSize = 1024;
       meta.schedulingPriority = 50;
       configureFlags = "--sysconfdir=/etc";
       debRequires =
-        [ "curl" "libdbd-sqlite3-perl" "libsqlite3-0" "libbz2-1.0" "bzip2" "xz-utils" "libwww-curl-perl" ]
+        [ "curl" "libdbd-sqlite3-perl" "libsqlite3-0" "libbz2-1.0" "bzip2" "xz-utils" "libwww-curl-perl" "libssl1.0.0" "liblzma5" ]
         ++ lib.optionals (lib.elem "libsodium-dev" extraPackages) [ "libsodium13" ] ;
       debMaintainer = "Eelco Dolstra <eelco.dolstra@logicblox.com>";
       doInstallCheck = true;
diff --git a/scripts/download-from-binary-cache.pl.in b/scripts/download-from-binary-cache.pl.in
index ea053bf14da4..60f7f9aef3d2 100644
--- a/scripts/download-from-binary-cache.pl.in
+++ b/scripts/download-from-binary-cache.pl.in
@@ -21,7 +21,7 @@ Nix::Config::readConfig;
 my @caches;
 my $gotCaches = 0;
 
-my $maxParallelRequests = int($Nix::Config::config{"binary-caches-parallel-connections"} // 150);
+my $maxParallelRequests = int($Nix::Config::config{"binary-caches-parallel-connections"} // 25);
 $maxParallelRequests = 1 if $maxParallelRequests < 1;
 
 my $ttlNegative = 24 * 3600; # when to purge negative lookups from the database
diff --git a/scripts/nix-build.in b/scripts/nix-build.in
index 0a4431681cb1..ea099532b7cb 100755
--- a/scripts/nix-build.in
+++ b/scripts/nix-build.in
@@ -6,6 +6,7 @@ use Nix::Config;
 use Nix::Store;
 use Nix::Utils;
 use File::Basename;
+use Text::ParseWords;
 use Cwd;
 
 binmode STDERR, ":encoding(utf8)";
@@ -56,7 +57,7 @@ if ($runEnv && defined $ARGV[0] && $ARGV[0] !~ /nix-shell/) {
             while (<SCRIPT>) {
                 chomp;
                 if (/^\#\!\s*nix-shell (.*)$/) {
-                    push @ARGV, split(/ /, $1);
+                    push @ARGV, shellwords(/ /, $1);
                 }
             }
         }
diff --git a/scripts/nix-copy-closure.in b/scripts/nix-copy-closure.in
index 55d108fbb4c2..9cbb4ede51a3 100755
--- a/scripts/nix-copy-closure.in
+++ b/scripts/nix-copy-closure.in
@@ -1,5 +1,6 @@
 #! @perl@ -w @perlFlags@
 
+use utf8;
 use strict;
 use Nix::SSH;
 use Nix::Config;
diff --git a/scripts/resolve-system-dependencies.pl.in b/scripts/resolve-system-dependencies.pl.in
index 23416b75c023..a20f0dc020fe 100755
--- a/scripts/resolve-system-dependencies.pl.in
+++ b/scripts/resolve-system-dependencies.pl.in
@@ -113,7 +113,7 @@ if (defined $ARGV[0]) {
     my $depset = reduce { union($a, $b) } (map { resolve_tree($_, $depcache) } @files);
     print "extra-chroot-dirs\n";
     print join("\n", keys %$depset);
-    print "\n\n";
+    print "\n";
   }
   lock_store($DEPS, $cache);
 } else {
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index acf1fbdc1356..df1600bc1963 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -1032,6 +1032,17 @@ void EvalState::autoCallFunction(Bindings & args, Value & fun, Value & res)
 {
     forceValue(fun);
 
+    if (fun.type == tAttrs) {
+        auto found = fun.attrs->find(sFunctor);
+        if (found != fun.attrs->end()) {
+            forceValue(*found->value);
+            Value * v = allocValue();
+            callFunction(*found->value, fun, *v, noPos);
+            forceValue(*v);
+            return autoCallFunction(args, *v, res);
+        }
+    }
+
     if (fun.type != tLambda || !fun.lambda.fun->matchAttrs) {
         res = fun;
         return;
diff --git a/src/libexpr/local.mk b/src/libexpr/local.mk
index d1b1987fb037..5de9ccc6d011 100644
--- a/src/libexpr/local.mk
+++ b/src/libexpr/local.mk
@@ -10,7 +10,10 @@ libexpr_CXXFLAGS := -Wno-deprecated-register
 
 libexpr_LIBS = libutil libstore libformat
 
-libexpr_LDFLAGS = -ldl
+libexpr_LDFLAGS =
+ifneq ($(OS), FreeBSD)
+ libexpr_LDFLAGS += -ldl
+endif
 
 # The dependency on libgc must be propagated (i.e. meaning that
 # programs/libraries that use libexpr must explicitly pass -lgc),
diff --git a/src/libexpr/nixexpr.cc b/src/libexpr/nixexpr.cc
index 35db52a13acc..5bc8e4202a49 100644
--- a/src/libexpr/nixexpr.cc
+++ b/src/libexpr/nixexpr.cc
@@ -30,8 +30,9 @@ static void showString(std::ostream & str, const string & s)
 
 static void showId(std::ostream & str, const string & s)
 {
-    assert(!s.empty());
-    if (s == "if")
+    if (s.empty())
+        str << "\"\"";
+    else if (s == "if") // FIXME: handle other keywords
         str << '"' << s << '"';
     else {
         char c = s[0];
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index 5b9ecc018f0e..cf2d3d278f28 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -1154,7 +1154,7 @@ static void prim_catAttrs(EvalState & state, const Pos & pos, Value * * args, Va
 
 /* Return a set containing the names of the formal arguments expected
    by the function `f'.  The value of each attribute is a Boolean
-   denoting whether has a default value.  For instance,
+   denoting whether the corresponding argument has a default value.  For instance,
 
       functionArgs ({ x, y ? 123}: ...)
    => { x = false; y = true; }
diff --git a/src/libstore/build.cc b/src/libstore/build.cc
index d6671f45b231..b41daac99159 100644
--- a/src/libstore/build.cc
+++ b/src/libstore/build.cc
@@ -34,47 +34,27 @@
 
 #include <bzlib.h>
 
-/* Includes required for chroot support. */
-#if HAVE_SYS_PARAM_H
-#include <sys/param.h>
-#endif
-#if HAVE_SYS_MOUNT_H
-#include <sys/mount.h>
-#endif
-#if HAVE_SYS_SYSCALL_H
-#include <sys/syscall.h>
-#endif
-#if HAVE_SCHED_H
-#include <sched.h>
-#endif
-
-/* In GNU libc 2.11, <sys/mount.h> does not define `MS_PRIVATE', but
-   <linux/fs.h> does.  */
-#if !defined MS_PRIVATE && defined HAVE_LINUX_FS_H
-#include <linux/fs.h>
-#endif
-
-#define CHROOT_ENABLED HAVE_CHROOT && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_PRIVATE) && defined(CLONE_NEWNS) && defined(SYS_pivot_root)
-
 /* chroot-like behavior from Apple's sandbox */
 #if __APPLE__
-    #define SANDBOX_ENABLED 1
     #define DEFAULT_ALLOWED_IMPURE_PREFIXES "/System/Library /usr/lib /dev /bin/sh"
 #else
-    #define SANDBOX_ENABLED 0
-    #define DEFAULT_ALLOWED_IMPURE_PREFIXES "/bin" "/usr/bin"
+    #define DEFAULT_ALLOWED_IMPURE_PREFIXES ""
 #endif
 
-#if CHROOT_ENABLED
+/* Includes required for chroot support. */
+#if __linux__
 #include <sys/socket.h>
 #include <sys/ioctl.h>
 #include <net/if.h>
 #include <netinet/ip.h>
-#endif
-
-#if __linux__
 #include <sys/personality.h>
 #include <sys/mman.h>
+#include <sched.h>
+#include <sys/param.h>
+#include <sys/mount.h>
+#include <sys/syscall.h>
+#include <linux/fs.h>
+#define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root, put_old))
 #endif
 
 #if HAVE_STATVFS
@@ -745,6 +725,9 @@ private:
     /* The temporary directory. */
     Path tmpDir;
 
+    /* The path of the temporary directory in the sandbox. */
+    Path tmpDirInSandbox;
+
     /* File descriptor for the log file. */
     FILE * fLogFile = 0;
     BZFILE * bzLogFile = 0;
@@ -779,6 +762,12 @@ private:
     typedef map<string, string> Environment;
     Environment env;
 
+#if __APPLE__
+    typedef string SandboxProfile;
+    SandboxProfile additionalSandboxProfile;
+    AutoDelete autoDelSandbox;
+#endif
+
     /* Hash rewriting. */
     HashRewrites rewritesToTmp, rewritesFromTmp;
     typedef map<Path, Path> RedirectedOutputs;
@@ -791,13 +780,19 @@ private:
        temporary paths. */
     PathSet redirectedBadOutputs;
 
-    /* Set of inodes seen during calls to canonicalisePathMetaData()
-       for this build's outputs.  This needs to be shared between
-       outputs to allow hard links between outputs. */
-    InodesSeen inodesSeen;
-
     BuildResult result;
 
+    /* The current round, if we're building multiple times. */
+    unsigned int curRound = 1;
+
+    unsigned int nrRounds;
+
+    /* Path registration info from the previous round, if we're
+       building multiple times. Since this contains the hash, it
+       allows us to compare whether two rounds produced the same
+       result. */
+    ValidPathInfos prevInfos;
+
 public:
     DerivationGoal(const Path & drvPath, const StringSet & wantedOutputs,
         Worker & worker, BuildMode buildMode = bmNormal);
@@ -1238,6 +1233,10 @@ void DerivationGoal::inputsRealised()
     for (auto & i : drv->outputs)
         if (i.second.hash == "") fixedOutput = false;
 
+    /* Don't repeat fixed-output derivations since they're already
+       verified by their output hash.*/
+    nrRounds = fixedOutput ? 1 : settings.get("build-repeat", 0) + 1;
+
     /* Okay, try to build.  Note that here we don't wait for a build
        slot to become available, since we don't need one if there is a
        build hook. */
@@ -1259,6 +1258,9 @@ static bool canBuildLocally(const BasicDerivation & drv)
 #if __linux__
         || (drv.platform == "i686-linux" && settings.thisSystem == "x86_64-linux")
         || (drv.platform == "armv6l-linux" && settings.thisSystem == "armv7l-linux")
+#elif __FreeBSD__
+        || (drv.platform == "i686-linux" && settings.thisSystem == "x86_64-freebsd")
+        || (drv.platform == "i686-linux" && settings.thisSystem == "i686-freebsd")
 #endif
         ;
 }
@@ -1420,6 +1422,9 @@ void replaceValidPath(const Path & storePath, const Path tmpPath)
 }
 
 
+MakeError(NotDeterministic, BuildError)
+
+
 void DerivationGoal::buildDone()
 {
     trace("build done");
@@ -1519,6 +1524,15 @@ void DerivationGoal::buildDone()
 
         deleteTmpDir(true);
 
+        /* Repeat the build if necessary. */
+        if (curRound++ < nrRounds) {
+            outputLocks.unlock();
+            buildUser.release();
+            state = &DerivationGoal::tryToBuild;
+            worker.wakeUp(shared_from_this());
+            return;
+        }
+
         /* It is now safe to delete the lock files, since all future
            lockers will see that the output paths are valid; they will
            not create new lock files with the same names as the old
@@ -1552,6 +1566,7 @@ void DerivationGoal::buildDone()
                     % drvPath % 1 % e.msg());
 
             st =
+                dynamic_cast<NotDeterministic*>(&e) ? BuildResult::NotDeterministic :
                 statusOk(status) ? BuildResult::OutputRejected :
                 fixedOutput || diskFull ? BuildResult::TransientFailure :
                 BuildResult::PermanentFailure;
@@ -1678,10 +1693,13 @@ int childEntry(void * arg)
 
 void DerivationGoal::startBuilder()
 {
-    startNest(nest, lvlInfo, format(
-            buildMode == bmRepair ? "repairing path(s) %1%" :
-            buildMode == bmCheck ? "checking path(s) %1%" :
-            "building path(s) %1%") % showPaths(missingPaths));
+    auto f = format(
+        buildMode == bmRepair ? "repairing path(s) %1%" :
+        buildMode == bmCheck ? "checking path(s) %1%" :
+        nrRounds > 1 ? "building path(s) %1% (round %2%/%3%)" :
+        "building path(s) %1%");
+    f.exceptions(boost::io::all_error_bits ^ boost::io::too_many_args_bit);
+    startNest(nest, lvlInfo, f % showPaths(missingPaths) % curRound % nrRounds);
 
     /* Right platform? */
     if (!canBuildLocally(*drv)) {
@@ -1692,7 +1710,40 @@ void DerivationGoal::startBuilder()
             % drv->platform % settings.thisSystem % drvPath);
     }
 
+#if __APPLE__
+    additionalSandboxProfile = get(drv->env, "__sandboxProfile");
+#endif
+
+    /* Are we doing a chroot build?  Note that fixed-output
+       derivations are never done in a chroot, mainly so that
+       functions like fetchurl (which needs a proper /etc/resolv.conf)
+       work properly.  Purity checking for fixed-output derivations
+       is somewhat pointless anyway. */
+    {
+        string x = settings.get("build-use-sandbox",
+            /* deprecated alias */
+            settings.get("build-use-chroot", string("false")));
+        if (x != "true" && x != "false" && x != "relaxed")
+            throw Error("option ‘build-use-sandbox’ must be set to one of ‘true’, ‘false’ or ‘relaxed’");
+        if (x == "true") {
+            if (get(drv->env, "__noChroot") == "1")
+                throw Error(format("derivation ‘%1%’ has ‘__noChroot’ set, "
+                    "but that's not allowed when ‘build-use-sandbox’ is ‘true’") % drvPath);
+#if __APPLE__
+            if (additionalSandboxProfile != "")
+                throw Error(format("derivation ‘%1%’ specifies a sandbox profile, "
+                    "but this is only allowed when ‘build-use-sandbox’ is ‘relaxed’") % drvPath);
+#endif
+            useChroot = true;
+        }
+        else if (x == "false")
+            useChroot = false;
+        else if (x == "relaxed")
+            useChroot = !fixedOutput && get(drv->env, "__noChroot") != "1";
+    }
+
     /* Construct the environment passed to the builder. */
+    env.clear();
 
     /* Most shells initialise PATH to some default (/bin:/usr/bin:...) when
        PATH is not set.  We don't want this, so we fill it in with some dummy
@@ -1719,7 +1770,12 @@ void DerivationGoal::startBuilder()
 
     /* Create a temporary directory where the build will take
        place. */
-    tmpDir = createTempDir("", "nix-build-" + storePathToName(drvPath), false, false, 0700);
+    auto drvName = storePathToName(drvPath);
+    tmpDir = createTempDir("", "nix-build-" + drvName, false, false, 0700);
+
+    /* In a sandbox, for determinism, always use the same temporary
+       directory. */
+    tmpDirInSandbox = useChroot ? canonPath("/tmp", true) + "/nix-build-" + drvName + "-0" : tmpDir;
 
     /* Add all bindings specified in the derivation via the
        environments, except those listed in the passAsFile
@@ -1732,25 +1788,26 @@ void DerivationGoal::startBuilder()
         if (passAsFile.find(i.first) == passAsFile.end()) {
             env[i.first] = i.second;
         } else {
-            Path p = tmpDir + "/.attr-" + std::to_string(fileNr++);
+            string fn = ".attr-" + std::to_string(fileNr++);
+            Path p = tmpDir + "/" + fn;
             writeFile(p, i.second);
             filesToChown.insert(p);
-            env[i.first + "Path"] = p;
+            env[i.first + "Path"] = tmpDirInSandbox + "/" + fn;
         }
     }
 
     /* For convenience, set an environment pointing to the top build
        directory. */
-    env["NIX_BUILD_TOP"] = tmpDir;
+    env["NIX_BUILD_TOP"] = tmpDirInSandbox;
 
     /* Also set TMPDIR and variants to point to this directory. */
-    env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmpDir;
+    env["TMPDIR"] = env["TEMPDIR"] = env["TMP"] = env["TEMP"] = tmpDirInSandbox;
 
     /* Explicitly set PWD to prevent problems with chroot builds.  In
        particular, dietlibc cannot figure out the cwd because the
        inode of the current directory doesn't appear in .. (because
        getdents returns the inode of the mount point). */
-    env["PWD"] = tmpDir;
+    env["PWD"] = tmpDirInSandbox;
 
     /* Compatibility hack with Nix <= 0.7: if this is a fixed-output
        derivation, tell the builder, so that for instance `fetchurl'
@@ -1839,40 +1896,27 @@ void DerivationGoal::startBuilder()
     }
 
 
-    /* Are we doing a chroot build?  Note that fixed-output
-       derivations are never done in a chroot, mainly so that
-       functions like fetchurl (which needs a proper /etc/resolv.conf)
-       work properly.  Purity checking for fixed-output derivations
-       is somewhat pointless anyway. */
-    {
-        string x = settings.get("build-use-chroot", string("false"));
-        if (x != "true" && x != "false" && x != "relaxed")
-            throw Error("option ‘build-use-chroot’ must be set to one of ‘true’, ‘false’ or ‘relaxed’");
-        if (x == "true") {
-            if (get(drv->env, "__noChroot") == "1")
-                throw Error(format("derivation ‘%1%’ has ‘__noChroot’ set, but that's not allowed when ‘build-use-chroot’ is ‘true’") % drvPath);
-            useChroot = true;
-        }
-        else if (x == "false")
-            useChroot = false;
-        else if (x == "relaxed")
-            useChroot = !fixedOutput && get(drv->env, "__noChroot") != "1";
-    }
-
     if (useChroot) {
 
         string defaultChrootDirs;
-#if CHROOT_ENABLED
+#if __linux__
         if (isInStore(BASH_PATH))
             defaultChrootDirs = "/bin/sh=" BASH_PATH;
 #endif
 
         /* Allow a user-configurable set of directories from the
            host file system. */
-        PathSet dirs = tokenizeString<StringSet>(settings.get("build-chroot-dirs", defaultChrootDirs));
-        PathSet dirs2 = tokenizeString<StringSet>(settings.get("build-extra-chroot-dirs", string("")));
+        PathSet dirs = tokenizeString<StringSet>(
+            settings.get("build-sandbox-paths",
+                /* deprecated alias with lower priority */
+                settings.get("build-chroot-dirs", defaultChrootDirs)));
+        PathSet dirs2 = tokenizeString<StringSet>(
+            settings.get("build-extra-chroot-dirs",
+                settings.get("build-extra-sandbox-paths", string(""))));
         dirs.insert(dirs2.begin(), dirs2.end());
 
+        dirsInChroot.clear();
+
         for (auto & i : dirs) {
             size_t p = i.find('=');
             if (p == string::npos)
@@ -1880,7 +1924,7 @@ void DerivationGoal::startBuilder()
             else
                 dirsInChroot[string(i, 0, p)] = string(i, p + 1);
         }
-        dirsInChroot[tmpDir] = tmpDir;
+        dirsInChroot[tmpDirInSandbox] = tmpDir;
 
         /* Add the closure of store paths to the chroot. */
         PathSet closure;
@@ -1911,12 +1955,12 @@ void DerivationGoal::startBuilder()
                 }
             }
             if (!found)
-                throw Error(format("derivation '%1%' requested impure path ‘%2%’, but it was not in allowed-impure-host-deps (‘%3%’)") % drvPath % i % allowed);
+                throw Error(format("derivation ‘%1%’ requested impure path ‘%2%’, but it was not in allowed-impure-host-deps (‘%3%’)") % drvPath % i % allowed);
 
             dirsInChroot[i] = i;
         }
 
-#if CHROOT_ENABLED
+#if __linux__
         /* Create a temporary directory in which we set up the chroot
            environment using bind-mounts.  We put it in the Nix store
            to ensure that we can create hard-links to non-directory
@@ -2009,11 +2053,11 @@ void DerivationGoal::startBuilder()
         for (auto & i : drv->outputs)
             dirsInChroot.erase(i.second.path);
 
-#elif SANDBOX_ENABLED
+#elif __APPLE__
         /* We don't really have any parent prep work to do (yet?)
            All work happens in the child, instead. */
 #else
-        throw Error("chroot builds are not supported on this platform");
+        throw Error("sandboxing builds is not supported on this platform");
 #endif
     }
 
@@ -2062,7 +2106,7 @@ void DerivationGoal::startBuilder()
             auto line = std::string{lines, lastPos, nlPos - lastPos};
             lastPos = nlPos + 1;
             if (state == stBegin) {
-                if (line == "extra-chroot-dirs") {
+                if (line == "extra-sandbox-paths" || line == "extra-chroot-dirs") {
                     state = stExtraChrootDirs;
                 } else {
                     throw Error(format("unknown pre-build hook command ‘%1%’")
@@ -2092,7 +2136,7 @@ void DerivationGoal::startBuilder()
     builderOut.create();
 
     /* Fork a child to build the package. */
-#if CHROOT_ENABLED
+#if __linux__
     if (useChroot) {
         /* Set up private namespaces for the build:
 
@@ -2133,7 +2177,7 @@ void DerivationGoal::startBuilder()
             size_t stackSize = 1 * 1024 * 1024;
             char * stack = (char *) mmap(0, stackSize,
                 PROT_WRITE | PROT_READ, MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
-            if (!stack) throw SysError("allocating stack");
+            if (stack == MAP_FAILED) throw SysError("allocating stack");
             int flags = CLONE_NEWPID | CLONE_NEWNS | CLONE_NEWIPC | CLONE_NEWUTS | CLONE_PARENT | SIGCHLD;
             if (!fixedOutput) flags |= CLONE_NEWNET;
             pid_t child = clone(childEntry, stack + stackSize, flags, this);
@@ -2194,7 +2238,7 @@ void DerivationGoal::runChild()
 
         commonChildInit(builderOut);
 
-#if CHROOT_ENABLED
+#if __linux__
         if (useChroot) {
 
             /* Initialise the loopback interface. */
@@ -2327,10 +2371,8 @@ void DerivationGoal::runChild()
             if (mkdir("real-root", 0) == -1)
                 throw SysError("cannot create real-root directory");
 
-#define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root, put_old))
             if (pivot_root(".", "real-root") == -1)
                 throw SysError(format("cannot pivot old root directory onto ‘%1%’") % (chrootRootDir + "/real-root"));
-#undef pivot_root
 
             if (chroot(".") == -1)
                 throw SysError(format("cannot change root directory to ‘%1%’") % chrootRootDir);
@@ -2343,7 +2385,7 @@ void DerivationGoal::runChild()
         }
 #endif
 
-        if (chdir(tmpDir.c_str()) == -1)
+        if (chdir(tmpDirInSandbox.c_str()) == -1)
             throw SysError(format("changing into ‘%1%’") % tmpDir);
 
         /* Close all other file descriptors. */
@@ -2410,9 +2452,10 @@ void DerivationGoal::runChild()
         const char *builder = "invalid";
 
         string sandboxProfile;
-        if (isBuiltin(*drv))
+        if (isBuiltin(*drv)) {
             ;
-        else if (useChroot && SANDBOX_ENABLED) {
+#if __APPLE__
+        } else if (useChroot) {
             /* Lots and lots and lots of file functions freak out if they can't stat their full ancestry */
             PathSet ancestry;
 
@@ -2442,8 +2485,6 @@ void DerivationGoal::runChild()
             /* This has to appear before import statements */
             sandboxProfile += "(version 1)\n";
 
-            sandboxProfile += (format("(import \"%1%/nix/sandbox-defaults.sb\")\n") % settings.nixDataDir).str();
-
             /* Violations will go to the syslog if you set this. Unfortunately the destination does not appear to be configurable */
             if (settings.get("darwin-log-sandbox-violations", false)) {
                 sandboxProfile += "(deny default)\n";
@@ -2466,15 +2507,15 @@ void DerivationGoal::runChild()
             sandboxProfile += ")\n";
 
             /* Our inputs (transitive dependencies and any impurities computed above)
-               Note that the sandbox profile allows file-write* even though it isn't seemingly necessary. First of all, nix's standard user permissioning
-               mechanism still prevents builders from writing to input directories, so no security/purity is lost. The reason we allow file-write* is that
-               denying it means the `access` syscall will return EPERM instead of EACCESS, which confuses a few programs that assume (understandably, since
-               it appears to be a violation of the POSIX spec) that `access` won't do that, and don't deal with it nicely if it does. The most notable of
-               these is the entire GHC Haskell ecosystem. */
-            sandboxProfile += "(allow file-read* file-write* process-exec mach-priv-task-port\n";
+
+               without file-write* allowed, access() incorrectly returns EPERM
+             */
+            sandboxProfile += "(allow file-read* file-write* process-exec\n";
             for (auto & i : dirsInChroot) {
                 if (i.first != i.second)
-                    throw SysError(format("can't map '%1%' to '%2%': mismatched impure paths not supported on darwin"));
+                    throw Error(format(
+                        "can't map '%1%' to '%2%': mismatched impure paths not supported on Darwin")
+                        % i.first % i.second);
 
                 string path = i.first;
                 struct stat st;
@@ -2487,28 +2528,32 @@ void DerivationGoal::runChild()
             }
             sandboxProfile += ")\n";
 
-            /* Our ancestry. N.B: this uses literal on folders, instead of subpath. Without that,
-               you open up the entire filesystem because you end up with (subpath "/")
-               Note: file-read-metadata* is not sufficiently permissive for GHC. file-read* is but may
-               be a security hazard.
-               TODO: figure out a more appropriate directive.
-             */
+            /* Allow file-read* on full directory hierarchy to self. Allows realpath() */
             sandboxProfile += "(allow file-read*\n";
             for (auto & i : ancestry) {
                 sandboxProfile += (format("\t(literal \"%1%\")\n") % i.c_str()).str();
             }
             sandboxProfile += ")\n";
 
+            sandboxProfile += additionalSandboxProfile;
+
             debug("Generated sandbox profile:");
             debug(sandboxProfile);
 
+            Path sandboxFile = drvPath + ".sb";
+            if (pathExists(sandboxFile)) deletePath(sandboxFile);
+            autoDelSandbox.reset(sandboxFile, false);
+
+            writeFile(sandboxFile, sandboxProfile);
+
             builder = "/usr/bin/sandbox-exec";
             args.push_back("sandbox-exec");
-            args.push_back("-p");
-            args.push_back(sandboxProfile);
+            args.push_back("-f");
+            args.push_back(sandboxFile);
             args.push_back("-D");
-            args.push_back((format("_GLOBAL_TMP_DIR=%1%") % globalTmpDir).str());
+            args.push_back("_GLOBAL_TMP_DIR=" + globalTmpDir);
             args.push_back(drv->builder);
+#endif
         } else {
             builder = drv->builder.c_str();
             string builderBasename = baseNameOf(drv->builder);
@@ -2582,6 +2627,11 @@ void DerivationGoal::registerOutputs()
 
     ValidPathInfos infos;
 
+    /* Set of inodes seen during calls to canonicalisePathMetaData()
+       for this build's outputs.  This needs to be shared between
+       outputs to allow hard links between outputs. */
+    InodesSeen inodesSeen;
+
     /* Check whether the output paths were created, and grep each
        output path to determine what other paths it references.  Also make all
        output paths read-only. */
@@ -2598,7 +2648,7 @@ void DerivationGoal::registerOutputs()
                     replaceValidPath(path, actualPath);
                 else
                     if (buildMode != bmCheck && rename(actualPath.c_str(), path.c_str()) == -1)
-                        throw SysError(format("moving build output ‘%1%’ from the chroot to the Nix store") % path);
+                        throw SysError(format("moving build output ‘%1%’ from the sandbox to the Nix store") % path);
             }
             if (buildMode != bmCheck) actualPath = path;
         } else {
@@ -2674,8 +2724,8 @@ void DerivationGoal::registerOutputs()
             Hash h2 = recursive ? hashPath(ht, actualPath).first : hashFile(ht, actualPath);
             if (h != h2)
                 throw BuildError(
-                    format("output path ‘%1%’ should have %2% hash ‘%3%’, instead has ‘%4%’")
-                    % path % i.second.hashAlgo % printHash16or32(h) % printHash16or32(h2));
+                    format("output path ‘%1%’ has %2% hash ‘%3%’ when ‘%4%’ was expected")
+                    % path % i.second.hashAlgo % printHash16or32(h2) % printHash16or32(h));
         }
 
         /* Get rid of all weird permissions.  This also checks that
@@ -2753,6 +2803,16 @@ void DerivationGoal::registerOutputs()
 
     if (buildMode == bmCheck) return;
 
+    if (curRound > 1 && prevInfos != infos)
+        throw NotDeterministic(
+            format("result of ‘%1%’ differs from previous round; rejecting as non-deterministic")
+            % drvPath);
+
+    if (curRound < nrRounds) {
+        prevInfos = infos;
+        return;
+    }
+
     /* Register each output path as valid, and register the sets of
        paths referenced by each of them.  If there are cycles in the
        outputs, this will fail. */
diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc
index 978bca28d7fa..d7cd0b088d98 100644
--- a/src/libstore/local-store.cc
+++ b/src/libstore/local-store.cc
@@ -23,16 +23,11 @@
 #include <time.h>
 #include <grp.h>
 
-#if HAVE_UNSHARE && HAVE_STATVFS && HAVE_SYS_MOUNT_H
+#if __linux__
 #include <sched.h>
 #include <sys/statvfs.h>
 #include <sys/mount.h>
-#endif
-
-#if HAVE_LINUX_FS_H
-#include <linux/fs.h>
 #include <sys/ioctl.h>
-#include <errno.h>
 #endif
 
 #include <sqlite3.h>
@@ -502,7 +497,7 @@ void LocalStore::openDB(bool create)
    bind mount.  So make the Nix store writable for this process. */
 void LocalStore::makeStoreWritable()
 {
-#if HAVE_UNSHARE && HAVE_STATVFS && HAVE_SYS_MOUNT_H && defined(MS_BIND) && defined(MS_REMOUNT)
+#if __linux__
     if (getuid() != 0) return;
     /* Check if /nix/store is on a read-only mount. */
     struct statvfs stat;
diff --git a/src/libstore/local.mk b/src/libstore/local.mk
index f10981ad444c..e78f47949ad3 100644
--- a/src/libstore/local.mk
+++ b/src/libstore/local.mk
@@ -8,7 +8,7 @@ libstore_SOURCES := $(wildcard $(d)/*.cc)
 
 libstore_LIBS = libutil libformat
 
-libstore_LDFLAGS = -lsqlite3 -lbz2 -lcurl
+libstore_LDFLAGS = $(SQLITE3_LIBS) -lbz2 $(LIBCURL_LIBS)
 
 ifeq ($(OS), SunOS)
 	libstore_LDFLAGS += -lsocket
diff --git a/src/libstore/optimise-store.cc b/src/libstore/optimise-store.cc
index 6f66961792fb..23cbe7e26b47 100644
--- a/src/libstore/optimise-store.cc
+++ b/src/libstore/optimise-store.cc
@@ -120,9 +120,9 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
         return;
     }
 
-    /* This can still happen on top-level files */
+    /* This can still happen on top-level files. */
     if (st.st_nlink > 1 && inodeHash.count(st.st_ino)) {
-        printMsg(lvlDebug, format("‘%1%’ is already linked, with %2% other file(s).") % path % (st.st_nlink - 2));
+        printMsg(lvlDebug, format("‘%1%’ is already linked, with %2% other file(s)") % path % (st.st_nlink - 2));
         return;
     }
 
@@ -141,6 +141,7 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
     /* Check if this is a known hash. */
     Path linkPath = linksDir + "/" + printHash32(hash);
 
+ retry:
     if (!pathExists(linkPath)) {
         /* Nope, create a hard link in the links directory. */
         if (link(path.c_str(), linkPath.c_str()) == 0) {
@@ -164,6 +165,12 @@ void LocalStore::optimisePath_(OptimiseStats & stats, const Path & path, InodeHa
         return;
     }
 
+    if (st.st_size != stLink.st_size) {
+        printMsg(lvlError, format("removing corrupted link ‘%1%’") % linkPath);
+        unlink(linkPath.c_str());
+        goto retry;
+    }
+
     printMsg(lvlTalkative, format("linking ‘%1%’ to ‘%2%’") % path % linkPath);
 
     /* Make the containing directory writable, but only if it's not
diff --git a/src/libstore/pathlocks.cc b/src/libstore/pathlocks.cc
index 1c87034f8e1a..eddf5bcbda65 100644
--- a/src/libstore/pathlocks.cc
+++ b/src/libstore/pathlocks.cc
@@ -161,7 +161,11 @@ bool PathLocks::lockPaths(const PathSet & _paths,
 
 PathLocks::~PathLocks()
 {
-    unlock();
+    try {
+        unlock();
+    } catch (...) {
+        ignoreException();
+    }
 }
 
 
diff --git a/src/libstore/remote-store.cc b/src/libstore/remote-store.cc
index ed9895ac8133..262e4650bfb5 100644
--- a/src/libstore/remote-store.cc
+++ b/src/libstore/remote-store.cc
@@ -438,12 +438,18 @@ Paths RemoteStore::importPaths(bool requireSignature, Source & source)
 
 void RemoteStore::buildPaths(const PathSet & drvPaths, BuildMode buildMode)
 {
-    if (buildMode != bmNormal) throw Error("repairing or checking is not supported when building through the Nix daemon");
     openConnection();
     to << wopBuildPaths;
-    if (GET_PROTOCOL_MINOR(daemonVersion) >= 13)
+    if (GET_PROTOCOL_MINOR(daemonVersion) >= 13) {
         to << drvPaths;
-    else {
+        if (GET_PROTOCOL_MINOR(daemonVersion) >= 15)
+            to << buildMode;
+        else
+            /* Old daemons did not take a 'buildMode' parameter, so we
+               need to validate it here on the client side.  */
+            if (buildMode != bmNormal)
+                throw Error("repairing or checking is not supported when building through the Nix daemon");
+    } else {
         /* For backwards compatibility with old daemons, strip output
            identifiers. */
         PathSet drvPaths2;
diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh
index 485209d7a8b7..9cc5fd45b7c4 100644
--- a/src/libstore/store-api.hh
+++ b/src/libstore/store-api.hh
@@ -87,10 +87,17 @@ struct ValidPathInfo
     Path deriver;
     Hash hash;
     PathSet references;
-    time_t registrationTime;
-    unsigned long long narSize; // 0 = unknown
+    time_t registrationTime = 0;
+    unsigned long long narSize = 0; // 0 = unknown
     unsigned long long id; // internal use only
-    ValidPathInfo() : registrationTime(0), narSize(0) { }
+
+    bool operator == (const ValidPathInfo & i) const
+    {
+        return
+            path == i.path
+            && hash == i.hash
+            && references == i.references;
+    }
 };
 
 typedef list<ValidPathInfo> ValidPathInfos;
@@ -114,6 +121,7 @@ struct BuildResult
         MiscFailure,
         DependencyFailed,
         LogLimitExceeded,
+        NotDeterministic,
     } status = MiscFailure;
     std::string errorMsg;
     //time_t startTime = 0, stopTime = 0;
diff --git a/src/libstore/worker-protocol.hh b/src/libstore/worker-protocol.hh
index 5a0ef5117aa6..7d9bcb58a249 100644
--- a/src/libstore/worker-protocol.hh
+++ b/src/libstore/worker-protocol.hh
@@ -6,7 +6,7 @@ namespace nix {
 #define WORKER_MAGIC_1 0x6e697863
 #define WORKER_MAGIC_2 0x6478696f
 
-#define PROTOCOL_VERSION 0x10e
+#define PROTOCOL_VERSION 0x10f
 #define GET_PROTOCOL_MAJOR(x) ((x) & 0xff00)
 #define GET_PROTOCOL_MINOR(x) ((x) & 0x00ff)
 
diff --git a/src/libutil/affinity.cc b/src/libutil/affinity.cc
index 3e21f43a2e9d..3cbdf878617a 100644
--- a/src/libutil/affinity.cc
+++ b/src/libutil/affinity.cc
@@ -2,14 +2,14 @@
 #include "util.hh"
 #include "affinity.hh"
 
-#if HAVE_SCHED_H
+#if __linux__
 #include <sched.h>
 #endif
 
 namespace nix {
 
 
-#if HAVE_SCHED_SETAFFINITY
+#if __linux__
 static bool didSaveAffinity = false;
 static cpu_set_t savedAffinity;
 #endif
@@ -17,7 +17,7 @@ static cpu_set_t savedAffinity;
 
 void setAffinityTo(int cpu)
 {
-#if HAVE_SCHED_SETAFFINITY
+#if __linux__
     if (sched_getaffinity(0, sizeof(cpu_set_t), &savedAffinity) == -1) return;
     didSaveAffinity = true;
     printMsg(lvlDebug, format("locking this thread to CPU %1%") % cpu);
@@ -32,7 +32,7 @@ void setAffinityTo(int cpu)
 
 int lockToCurrentCPU()
 {
-#if HAVE_SCHED_SETAFFINITY
+#if __linux__
     int cpu = sched_getcpu();
     if (cpu != -1) setAffinityTo(cpu);
     return cpu;
@@ -44,7 +44,7 @@ int lockToCurrentCPU()
 
 void restoreAffinity()
 {
-#if HAVE_SCHED_SETAFFINITY
+#if __linux__
     if (!didSaveAffinity) return;
     if (sched_setaffinity(0, sizeof(cpu_set_t), &savedAffinity) == -1)
         printMsg(lvlError, "failed to restore affinity %1%");
diff --git a/src/libutil/compression.cc b/src/libutil/compression.cc
index 446fcb781564..fb4160669a29 100644
--- a/src/libutil/compression.cc
+++ b/src/libutil/compression.cc
@@ -2,6 +2,7 @@
 #include "types.hh"
 
 #include <lzma.h>
+#include <cstdio>
 
 namespace nix {
 
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 656d67a53b8d..c1585e27ea1f 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -599,6 +599,8 @@ string drainFD(int fd)
 //////////////////////////////////////////////////////////////////////
 
 
+AutoDelete::AutoDelete() : del{false} {}
+
 AutoDelete::AutoDelete(const string & p, bool recursive) : path(p)
 {
     del = true;
@@ -626,6 +628,12 @@ void AutoDelete::cancel()
     del = false;
 }
 
+void AutoDelete::reset(const Path & p, bool recursive) {
+    path = p;
+    this->recursive = recursive;
+    del = true;
+}
+
 
 
 //////////////////////////////////////////////////////////////////////
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 2edc5344fdc1..cf93c6378a06 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -156,8 +156,8 @@ void printMsg_(Verbosity level, const FormatOrString & fs);
 
 #define printMsg(level, f) \
     do { \
-        if (level <= verbosity) { \
-            printMsg_(level, (f)); \
+        if (level <= nix::verbosity) { \
+            nix::printMsg_(level, (f)); \
         } \
     } while (0)
 
@@ -205,9 +205,11 @@ class AutoDelete
     bool del;
     bool recursive;
 public:
+    AutoDelete();
     AutoDelete(const Path & p, bool recursive = true);
     ~AutoDelete();
     void cancel();
+    void reset(const Path & p, bool recursive = true);
     operator Path() const { return path; }
 };
 
diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc
index b4d1401d95cf..c5e11afa1553 100644
--- a/src/nix-daemon/nix-daemon.cc
+++ b/src/nix-daemon/nix-daemon.cc
@@ -319,8 +319,17 @@ static void performOp(bool trusted, unsigned int clientVersion,
 
     case wopBuildPaths: {
         PathSet drvs = readStorePaths<PathSet>(from);
+        BuildMode mode = bmNormal;
+        if (GET_PROTOCOL_MINOR(clientVersion) >= 15) {
+            mode = (BuildMode)readInt(from);
+
+	    /* Repairing is not atomic, so disallowed for "untrusted"
+	       clients.  */
+            if (mode == bmRepair && !trusted)
+                throw Error("repairing is not supported when building through the Nix daemon");
+        }
         startWork();
-        store->buildPaths(drvs);
+        store->buildPaths(drvs, mode);
         stopWork();
         to << 1;
         break;
@@ -692,6 +701,10 @@ static PeerInfo getPeerInfo(int remote)
 
 #elif defined(LOCAL_PEERCRED)
 
+#if !defined(SOL_LOCAL)
+#define SOL_LOCAL 0
+#endif
+
     xucred cred;
     socklen_t credLen = sizeof(cred);
     if (getsockopt(remote, SOL_LOCAL, LOCAL_PEERCRED, &cred, &credLen) == -1)
diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc
index 313f8a8a8f35..02a9f25a7a4e 100644
--- a/src/nix-env/nix-env.cc
+++ b/src/nix-env/nix-env.cc
@@ -1140,7 +1140,19 @@ static void opQuery(Globals & globals, Strings opFlags, Strings opArgs)
                                         attrs3["value"] = v->listElems()[j]->string.s;
                                         xml.writeEmptyElement("string", attrs3);
                                     }
+                              } else if (v->type == tAttrs) {
+                                  attrs2["type"] = "strings";
+                                  XMLOpenElement m(xml, "meta", attrs2);
+                                  Bindings & attrs = *v->attrs;
+                                  for (auto &i : attrs) {
+                                      Attr & a(*attrs.find(i.name));
+                                      if(a.value->type != tString) continue;
+                                      XMLAttrs attrs3;
+                                      attrs3["type"] = i.name;
+                                      attrs3["value"] = a.value->string.s;
+                                      xml.writeEmptyElement("string", attrs3);
                                 }
+                              }
                             }
                         }
                     }
diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc
index 14354f86e228..b49ebd09475c 100644
--- a/src/nix-store/nix-store.cc
+++ b/src/nix-store/nix-store.cc
@@ -1013,7 +1013,8 @@ static void opGenerateBinaryCacheKey(Strings opFlags, Strings opArgs)
     string publicKeyFile = *i++;
 
 #if HAVE_SODIUM
-    sodium_init();
+    if (sodium_init() == -1)
+        throw Error("could not initialise libsodium");
 
     unsigned char pk[crypto_sign_PUBLICKEYBYTES];
     unsigned char sk[crypto_sign_SECRETKEYBYTES];