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 Nix The 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";}