diff --git a/corepkgs/buildenv/builder.pl.in b/corepkgs/buildenv/builder.pl.in
index 7b9f0ed7d..c1a2ff237 100755
--- a/corepkgs/buildenv/builder.pl.in
+++ b/corepkgs/buildenv/builder.pl.in
@@ -70,7 +70,7 @@ sub createLinks {
}
unlink $dstFile or die "error unlinking `$dstFile': $!";
mkdir $dstFile, 0755 || die "error creating directory `$dstFile': $!";
- createLinks($target, $dstFile, $priority); # !!! <- priority isn't right
+ createLinks($target, $dstFile, $priorities{$dstFile});
createLinks($srcFile, $dstFile, $priority);
}
diff --git a/corepkgs/channels/unpack.sh.in b/corepkgs/channels/unpack.sh.in
index 03c6e5b2f..1f2886a6a 100644
--- a/corepkgs/channels/unpack.sh.in
+++ b/corepkgs/channels/unpack.sh.in
@@ -24,7 +24,7 @@ for ((n = 0; n < ${#inputs[*]}; n += 2)); do
@coreutils@/mv * ../$dirName # !!! hacky
attrName=$(echo $dirName | @tr@ -- '- ' '__')
- echo "$attrName = import ./$dirName {};" >> $expr
+ echo "$attrName = let e = import ./$dirName; in if builtins.isFunction e then e {} else e;" >> $expr
done
echo '} // {_combineChannels = true;}' >> $expr
diff --git a/doc/manual/installation.xml b/doc/manual/installation.xml
index 2642bca1d..3a143e44f 100644
--- a/doc/manual/installation.xml
+++ b/doc/manual/installation.xml
@@ -6,6 +6,39 @@
Installation
+Supported platforms
+
+Nix is currently supported on the following platforms:
+
+
+
+ Linux (particularly on x86, x86_64, and
+ PowerPC).
+
+ Mac OS X, both on Intel and
+ PowerPC.
+
+ FreeBSD (only tested on Intel).
+
+ Windows through Cygwin.
+
+ On Cygwin, Nix must be installed
+ on an NTFS partition. It will not work correctly on a FAT
+ partition.
+
+
+
+
+
+
+
+Nix is pretty portable, so it should work on most other Unix
+platforms as well.
+
+
+
+
Obtaining NixThe easiest way to obtain Nix is to download a
-$ autoreconf -i
+$ ./boostrap
The installation path can be specified by passing the
to
@@ -163,49 +196,44 @@ xlink:href="http://nix.cs.uu.nl/dist/nix/" />.
-Permissions
+Security
-All Nix operations must be performed under the user ID that owns
-the Nix store and database
-(prefix/store and
-prefix/var/nix/db,
-respectively). When installed from the RPM packages, these
-directories are owned by root.
+Nix has two basic security models. First, it can be used in
+“single-user mode”, which is similar to what most other package
+management tools do: there is a single user (typically root) who performs all package
+management operations. All other users can then use the installed
+packages, but they cannot perform package management operations
+themselves.
-Setuid installation
+Alternatively, you can configure Nix in “multi-user mode”. In
+this model, all users can perform package management operations — for
+instance, every user can install software without requiring root
+privileges. Nix ensures that this is secure. For instance, it’s not
+possible for one user to overwrite a package used by another user with
+a Trojan horse.
-As a somewhat ad hoc hack, you can also
-install the Nix binaries setuid so that a Nix store can
-be shared among several users. To do this, configure Nix with the
---enable-setuid option. Nix will be installed as
-owned by a user and group specified by the
-user and
-group
-options. E.g.,
-
-$ ./configure --enable-setuid --with-nix-user=my_nix_user --with-nix-group=my_nix_group
+Single-user mode
+
+In single-user mode, all Nix operations that access the database
+in prefix/var/nix/db
+or modify the Nix store in
+prefix/store must be
+performed under the user ID that owns those directories. This is
+typically root. (If you
+install from RPM packages, that’s in fact the default ownership.)
+However, on single-user machines, it is often convenient to
+chown those directories to your normal user account
+so that you don’t have to su to root all the time.
-The user and group default to nix. You should make
-sure that both the user and the group exist. Any real
-users that you want to allow access should be added to the Nix
-group.
+
-A setuid installation should only by used if the users
-in the Nix group are mutually trusted, since any user in that group
-has the ability to change anything in the Nix store or database. For
-instance, they could install a trojan horse in executables used by
-other users.
-On some platforms, the Nix binaries will be installed
-as setuid root. They drop root privileges
-immediately after startup and switch to the Nix user. The reason for
-this is that both the real and effective user must be set to the Nix
-user, and POSIX has no system call to do this. This is not the case
-on systems that have the setresuid() system call
-(such as Linux and FreeBSD), so on those systems the binaries are
-simply owned by the Nix user.
+Multi-user mode
+
-
+Multi-user mode has one important limitation: only
+root can run nix-pull to register the availability
+of pre-built binaries. However, those registrations
+are used by all users to speed up
+builds.
-
+
+Using Nix
diff --git a/doc/manual/manual.xml b/doc/manual/manual.xml
index d8fd5ddb2..35b4417f1 100644
--- a/doc/manual/manual.xml
+++ b/doc/manual/manual.xml
@@ -85,7 +85,7 @@
nix-prefetch-url
-
+ nix-pull
diff --git a/doc/manual/nix-prefetch-url.xml b/doc/manual/nix-prefetch-url.xml
index b341fd88a..b03169376 100644
--- a/doc/manual/nix-prefetch-url.xml
+++ b/doc/manual/nix-prefetch-url.xml
@@ -39,7 +39,7 @@ avoided.
The environment variable NIX_HASH_ALGO specifies
which hash algorithm to use. It can be either md5,
sha1, or sha256. The default is
-md5.
+sha256.
If hash is specified, then a download
is not performed if the Nix store already contains a file with the
diff --git a/doc/manual/release-notes.xml b/doc/manual/release-notes.xml
index 43358fe55..c3bc060cb 100644
--- a/doc/manual/release-notes.xml
+++ b/doc/manual/release-notes.xml
@@ -12,7 +12,9 @@
- TODO: multi-user support.
+ TODO: multi-user support. The old setuid method for
+ sharing a store between multiple users has been
+ removed.nix-copy-closure copies the
diff --git a/scripts/nix-build.in b/scripts/nix-build.in
index 08201f857..bce4a8007 100644
--- a/scripts/nix-build.in
+++ b/scripts/nix-build.in
@@ -122,7 +122,7 @@ foreach my $expr (@exprs) {
close DRVPATHS or exit 1;
foreach my $drvPath (@drvPaths) {
- my $target = readlink $drvPath;
+ my $target = readlink $drvPath or die "cannot read symlink `$drvPath'";
print STDERR "store derivation is $target\n";
}
@@ -134,7 +134,7 @@ foreach my $expr (@exprs) {
close OUTPATHS or exit 1;
foreach my $outPath (@outPaths) {
- my $target = readlink $outPath;
+ my $target = readlink $outPath or die "cannot read symlink `$outPath'";
print "$target\n";
}
}
diff --git a/scripts/nix-channel.in b/scripts/nix-channel.in
index 095f36d79..41a75adf1 100644
--- a/scripts/nix-channel.in
+++ b/scripts/nix-channel.in
@@ -94,7 +94,6 @@ sub update {
$url =~ /\/([^\/]+)\/?$/;
my $channelName = $1;
$channelName = "unnamed" unless defined $channelName;
- print "$channelName\n";
my $fullURL = "$url/nixexprs.tar.bz2";
print "downloading Nix expressions from `$fullURL'...\n";
diff --git a/scripts/nix-copy-closure.in b/scripts/nix-copy-closure.in
index aff62fb8e..1b1b3ebc8 100644
--- a/scripts/nix-copy-closure.in
+++ b/scripts/nix-copy-closure.in
@@ -120,7 +120,6 @@ else { # Copy FROM the remote machine.
if (!defined $storePathsSeen{$_}) {
push @allStorePaths, $_;
$storePathsSeen{$_} = 1;
- print "GOT $_\n";
}
}
diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc
index 552b58625..a8a22e2f2 100644
--- a/src/libexpr/eval.cc
+++ b/src/libexpr/eval.cc
@@ -478,7 +478,7 @@ LocalNoInline(Expr evalCall(EvalState & state, Expr fun, Expr arg))
}
else throwTypeError(
- "the left-hand side of the function call is neither a function nor a primop (built-in operation) but %1%",
+ "attempt to call something which is neither a function nor a primop (built-in operation) but %1%",
showType(fun));
}
diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y
index 3540058bc..1c06240fd 100644
--- a/src/libexpr/parser.y
+++ b/src/libexpr/parser.y
@@ -249,6 +249,7 @@ expr_list
formals
: formal ',' formals { $$ = ATinsert($3, $1); } /* idem - right recursive */
| formal { $$ = ATinsert(ATempty, $1); }
+ | { $$ = ATempty; }
;
formal
diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc
index b004a3c26..d18f3274b 100644
--- a/src/libexpr/primops.cc
+++ b/src/libexpr/primops.cc
@@ -116,6 +116,18 @@ static Expr prim_isNull(EvalState & state, const ATermVector & args)
}
+/* Determine whether the argument is a function. */
+static Expr prim_isFunction(EvalState & state, const ATermVector & args)
+{
+ Expr e = evalExpr(state, args[0]);
+ ATermList formals;
+ ATerm name, body, pos;
+ return makeBool(
+ matchFunction(e, formals, body, pos) ||
+ matchFunction1(e, name, body, pos));
+}
+
+
static Path findDependency(Path dir, string dep)
{
if (dep[0] == '/') throw EvalError(
@@ -1032,6 +1044,7 @@ void EvalState::addPrimOps()
// Miscellaneous
addPrimOp("import", 1, prim_import);
addPrimOp("isNull", 1, prim_isNull);
+ addPrimOp("__isFunction", 1, prim_isFunction);
addPrimOp("dependencyClosure", 1, prim_dependencyClosure);
addPrimOp("abort", 1, prim_abort);
addPrimOp("throw", 1, prim_throw);
diff --git a/src/libstore/db.cc b/src/libstore/db.cc
index 90b7d31c7..8370d1cd3 100644
--- a/src/libstore/db.cc
+++ b/src/libstore/db.cc
@@ -145,6 +145,15 @@ Database::~Database()
void openEnv(DbEnv * & env, const string & path, u_int32_t flags)
{
+ try {
+ createDirs(path);
+ } catch (SysError & e) {
+ if (e.errNo == EPERM || e.errNo == EACCES)
+ throw DbNoPermission(format("cannot create the Nix database in `%1%'") % path);
+ else
+ throw;
+ }
+
try {
env->open(path.c_str(),
DB_INIT_LOCK | DB_INIT_LOG | DB_INIT_MPOOL | DB_INIT_TXN |
diff --git a/src/libstore/gc.cc b/src/libstore/gc.cc
index 2e4f25397..758f86a4b 100644
--- a/src/libstore/gc.cc
+++ b/src/libstore/gc.cc
@@ -97,6 +97,11 @@ Path addPermRoot(const Path & _storePath, const Path & _gcRoot,
Path gcRoot(canonPath(_gcRoot));
assertStorePath(storePath);
+ if (isInStore(gcRoot))
+ throw Error(format(
+ "creating a garbage collector root (%1%) in the Nix store is forbidden "
+ "(are you running nix-build inside the store?)") % gcRoot);
+
if (indirect) {
createSymlink(gcRoot, storePath, true);
store->addIndirectRoot(gcRoot);
@@ -114,7 +119,6 @@ Path addPermRoot(const Path & _storePath, const Path & _gcRoot,
}
createSymlink(gcRoot, storePath, false);
-
}
/* Check that the root can be found by the garbage collector. */
diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh
index ee18bb08b..65b6e1754 100644
--- a/src/libstore/local-store.hh
+++ b/src/libstore/local-store.hh
@@ -13,7 +13,7 @@ class Transaction;
/* Nix store and database schema version. Version 1 (or 0) was Nix <=
- 0.7. Version 2 was Nix 0.8 and 0.8. Version 3 is Nix 0.10 and
+ 0.7. Version 2 was Nix 0.8 and 0.9. Version 3 is Nix 0.10 and
up. */
const int nixSchemaVersion = 3;
diff --git a/tests/lang/eval-okay-empty-args.exp b/tests/lang/eval-okay-empty-args.exp
new file mode 100644
index 000000000..c386bbc80
--- /dev/null
+++ b/tests/lang/eval-okay-empty-args.exp
@@ -0,0 +1 @@
+Str("ab",[])
diff --git a/tests/lang/eval-okay-empty-args.nix b/tests/lang/eval-okay-empty-args.nix
new file mode 100644
index 000000000..78c133afd
--- /dev/null
+++ b/tests/lang/eval-okay-empty-args.nix
@@ -0,0 +1 @@
+({}: {x,y,}: "${x}${y}") {} {x = "a"; y = "b";}