From 6f6cb5e3880d0c7a1dd2bc13c2e0be8ce0ae9fa1 Mon Sep 17 00:00:00 2001 From: Sam Doshi Date: Mon, 7 Oct 2019 11:40:42 +0100 Subject: [PATCH 01/25] nix search: remove verbose example --- src/nix/search.cc | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/nix/search.cc b/src/nix/search.cc index e086de226..764dcb70a 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -80,10 +80,6 @@ struct CmdSearch : SourceExprCommand, MixJSON Example{ "To search for git and frontend or gui:", "nix search git 'frontend|gui'" - }, - Example{ - "To display the description of the found packages:", - "nix search git --verbose" } }; } From 00a567588e43b51944a9b91c1e890bda27773aed Mon Sep 17 00:00:00 2001 From: Danny Bautista Date: Tue, 8 Oct 2019 14:02:40 -0400 Subject: [PATCH 02/25] Fix typos in the Nix Manual. --- doc/manual/command-ref/conf-file.xml | 2 +- doc/manual/command-ref/nix-env.xml | 2 +- doc/manual/command-ref/nix-prefetch-url.xml | 2 +- doc/manual/expressions/builtins.xml | 4 ++-- doc/manual/expressions/simple-building-testing.xml | 2 +- 5 files changed, 6 insertions(+), 6 deletions(-) diff --git a/doc/manual/command-ref/conf-file.xml b/doc/manual/command-ref/conf-file.xml index 320e15339..48dce7c95 100644 --- a/doc/manual/command-ref/conf-file.xml +++ b/doc/manual/command-ref/conf-file.xml @@ -433,7 +433,7 @@ builtins.fetchurl { keep-env-derivations If false (default), derivations - are not stored in Nix user environments. That is, the derivation + are not stored in Nix user environments. That is, the derivations of any build-time-only dependencies may be garbage-collected. If true, when you add a Nix derivation to diff --git a/doc/manual/command-ref/nix-env.xml b/doc/manual/command-ref/nix-env.xml index c8c01f9a4..d257a5e49 100644 --- a/doc/manual/command-ref/nix-env.xml +++ b/doc/manual/command-ref/nix-env.xml @@ -659,7 +659,7 @@ upgrading `mozilla-1.2' to `mozilla-1.4' gcc-3.3.1 are split into two parts: the package name (gcc), and the version (3.3.1). The version part starts after the first -dash not following by a letter. x is considered an +dash not followed by a letter. x is considered an upgrade of y if their package names match, and the version of y is higher that that of x. diff --git a/doc/manual/command-ref/nix-prefetch-url.xml b/doc/manual/command-ref/nix-prefetch-url.xml index 8ef748c74..621ded72e 100644 --- a/doc/manual/command-ref/nix-prefetch-url.xml +++ b/doc/manual/command-ref/nix-prefetch-url.xml @@ -53,7 +53,7 @@ avoided. If hash is specified, then a download is not performed if the Nix store already contains a file with the same hash and base name. Otherwise, the file is downloaded, and an -error if signaled if the actual hash of the file does not match the +error is signaled if the actual hash of the file does not match the specified hash. This command prints the hash on standard output. Additionally, diff --git a/doc/manual/expressions/builtins.xml b/doc/manual/expressions/builtins.xml index e164d1441..465fa1e0b 100644 --- a/doc/manual/expressions/builtins.xml +++ b/doc/manual/expressions/builtins.xml @@ -289,7 +289,7 @@ if builtins ? getEnv then builtins.getEnv "PATH" else "" Return element n from the list xs. Elements are counted - starting from 0. A fatal error occurs in the index is out of + starting from 0. A fatal error occurs if the index is out of bounds. @@ -1466,7 +1466,7 @@ in foo A set containing { __toString = self: ...; }. An integer. A list, in which case the string representations of its elements are joined with spaces. - A Boolean (false yields "", true yields "1". + A Boolean (false yields "", true yields "1"). null, which yields the empty string. diff --git a/doc/manual/expressions/simple-building-testing.xml b/doc/manual/expressions/simple-building-testing.xml index 0348c082b..7326a3e76 100644 --- a/doc/manual/expressions/simple-building-testing.xml +++ b/doc/manual/expressions/simple-building-testing.xml @@ -43,7 +43,7 @@ use nix-build’s switch to give the symlink another name. -Nix has a transactional semantics. Once a build finishes +Nix has transactional semantics. Once a build finishes successfully, Nix makes a note of this in its database: it registers that the path denoted by out is now valid. If you try to build the derivation again, Nix From 0847f2f1b3145a62dc34707ba788275ce6b6fc57 Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Tue, 8 Oct 2019 21:17:27 -0400 Subject: [PATCH 03/25] Copy instead of linking launch agent On Catalina, the /nix filesystem might not be mounted at start time. To avoid this service not starting, we need to keep the launch agent outside of the Nix store. A wait4pid will hold for our /nix dir to be mounted. Fixes #3125. --- misc/launchd/org.nixos.nix-daemon.plist.in | 2 +- scripts/install-darwin-multi-user.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/misc/launchd/org.nixos.nix-daemon.plist.in b/misc/launchd/org.nixos.nix-daemon.plist.in index b340610e9..39d7757a4 100644 --- a/misc/launchd/org.nixos.nix-daemon.plist.in +++ b/misc/launchd/org.nixos.nix-daemon.plist.in @@ -17,7 +17,7 @@ /bin/sh -c - /bin/wait4path @bindir@/nix-daemon && @bindir@/nix-daemon + /bin/wait4path @bindir@/nix-daemon && /nix/var/nix/profiles/default/bin/nix-daemon StandardErrorPath /var/log/nix-daemon.log diff --git a/scripts/install-darwin-multi-user.sh b/scripts/install-darwin-multi-user.sh index 87c4c2b05..49076bd5c 100644 --- a/scripts/install-darwin-multi-user.sh +++ b/scripts/install-darwin-multi-user.sh @@ -39,7 +39,7 @@ EOF poly_configure_nix_daemon_service() { _sudo "to set up the nix-daemon as a LaunchDaemon" \ - ln -sfn "/nix/var/nix/profiles/default$PLIST_DEST" "$PLIST_DEST" + cp -f "/nix/var/nix/profiles/default$PLIST_DEST" "$PLIST_DEST" _sudo "to load the LaunchDaemon plist for nix-daemon" \ launchctl load /Library/LaunchDaemons/org.nixos.nix-daemon.plist From d4e51aac080e73982e16b43088f9ae404f07136e Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Tue, 8 Oct 2019 21:35:09 -0400 Subject: [PATCH 04/25] Make preexisting Nix install a warning, not a failure In the multi-user install script, we originally made sure no previous references to Nix existed. This prevented any previous installs from contaminating the new install. However, some users need the ability to repair their existing Nix installation without uninstalling all references to Nix. This change allows users with existing Nix installations to use the installer, while still outputing a warning message on the dangers of this. As a result, the multi-user install script work much more like the single-user install script has worked in the past. This is a requirement for macOS Catalina users now that /Library/LaunchDaemons/org.nixos.nix-daemon.plisg is not managed by the Nix store. If there is ever a change to the .plist, all users will need to rerun this install script to get the new changes. Otherwise, changes to the launch daemon will require manual interventions. --- scripts/install-multi-user.sh | 104 ++-------------------------------- 1 file changed, 5 insertions(+), 99 deletions(-) diff --git a/scripts/install-multi-user.sh b/scripts/install-multi-user.sh index a41309e93..fd0f54184 100644 --- a/scripts/install-multi-user.sh +++ b/scripts/install-multi-user.sh @@ -278,73 +278,9 @@ EOF fi if type nix-env 2> /dev/null >&2; then - failure < Date: Tue, 8 Oct 2019 22:41:05 -0400 Subject: [PATCH 05/25] =?UTF-8?q?Don=E2=80=99t=20source=20bashrc=20in=20pu?= =?UTF-8?q?re=20mode?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pure mode should not try to source the user’s bashrc file. These may have many impurities that the user does not expect to get into their shell. Fixes #3090 --- src/nix-build/nix-build.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 2b36846cd..3e1081c05 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -412,7 +412,7 @@ static void _main(int argc, char * * argv) auto rcfile = (Path) tmpDir + "/rc"; writeFile(rcfile, fmt( (keepTmp ? "" : "rm -rf '%1%'; "s) + - "[ -n \"$PS1\" ] && [ -e ~/.bashrc ] && source ~/.bashrc; " + (pure ? "" : "[ -n \"$PS1\" ] && [ -e ~/.bashrc ] && source ~/.bashrc;") "%2%" "dontAddDisableDepTrack=1; " "[ -e $stdenv/setup ] && source $stdenv/setup; " From 199e888785bd23073e44e56f6c74b95dc7c10ffa Mon Sep 17 00:00:00 2001 From: Matthew Bauer Date: Tue, 8 Oct 2019 23:12:31 -0400 Subject: [PATCH 06/25] Handle empty sandbox_shell Previously, SANDBOX_SHELL was set to empty when unavailable. This caused issues when actually generating the sandbox. Instead, just set SANDBOX_SHELL when --with-sandbox-shell= is non-empty. Alternative implementation to https://github.com/NixOS/nix/pull/3038. --- src/libstore/local.mk | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/libstore/local.mk b/src/libstore/local.mk index 89fc918c3..d690fea28 100644 --- a/src/libstore/local.mk +++ b/src/libstore/local.mk @@ -39,9 +39,12 @@ libstore_CXXFLAGS = \ -DNIX_LIBEXEC_DIR=\"$(libexecdir)\" \ -DNIX_BIN_DIR=\"$(bindir)\" \ -DNIX_MAN_DIR=\"$(mandir)\" \ - -DSANDBOX_SHELL="\"$(sandbox_shell)\"" \ -DLSOF=\"$(lsof)\" +ifneq ($(sandbox_shell),) +libstore_CXXFLAGS += -DSANDBOX_SHELL="\"$(sandbox_shell)\"" +endif + $(d)/local-store.cc: $(d)/schema.sql.gen.hh $(d)/build.cc: From 8c4a5e7ba1990348b9497c0fc4dc236dda3e7986 Mon Sep 17 00:00:00 2001 From: Dan Callahan Date: Wed, 9 Oct 2019 08:51:49 +0100 Subject: [PATCH 07/25] Make nix-daemon.plist less fragile on macOS We're calling `wait4path` on the full, resolved `@bindir@/nix-daemon` path. That means we're hardcoding something like: /bin/wait4path /nix/store/zs9c5xhp3zv9p23qnjxp87nl5injsi1i-nix-2.3/bin/nix-daemon && /nix/var/nix/profiles/default/bin/nix-daemon That seems unnecessarily fragile. It might be better to wait4path on the path we intend to call. --- misc/launchd/org.nixos.nix-daemon.plist.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/misc/launchd/org.nixos.nix-daemon.plist.in b/misc/launchd/org.nixos.nix-daemon.plist.in index 39d7757a4..9f26296a9 100644 --- a/misc/launchd/org.nixos.nix-daemon.plist.in +++ b/misc/launchd/org.nixos.nix-daemon.plist.in @@ -17,7 +17,7 @@ /bin/sh -c - /bin/wait4path @bindir@/nix-daemon && /nix/var/nix/profiles/default/bin/nix-daemon + /bin/wait4path /nix/var/nix/profiles/default/bin/nix-daemon && /nix/var/nix/profiles/default/bin/nix-daemon StandardErrorPath /var/log/nix-daemon.log From 64d88729005841ff3ccfa75134f9aa5e5828da6d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 14:46:44 +0200 Subject: [PATCH 08/25] nix-build: Fix compilation --- src/nix-build/nix-build.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix-build/nix-build.cc b/src/nix-build/nix-build.cc index 3e1081c05..085650e4f 100755 --- a/src/nix-build/nix-build.cc +++ b/src/nix-build/nix-build.cc @@ -412,7 +412,7 @@ static void _main(int argc, char * * argv) auto rcfile = (Path) tmpDir + "/rc"; writeFile(rcfile, fmt( (keepTmp ? "" : "rm -rf '%1%'; "s) + - (pure ? "" : "[ -n \"$PS1\" ] && [ -e ~/.bashrc ] && source ~/.bashrc;") + (pure ? "" : "[ -n \"$PS1\" ] && [ -e ~/.bashrc ] && source ~/.bashrc;") + "%2%" "dontAddDisableDepTrack=1; " "[ -e $stdenv/setup ] && source $stdenv/setup; " From 7c74f075f4a7274ad38c90085cc269a19a977438 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 14:46:58 +0200 Subject: [PATCH 09/25] nix search: Don't quietly ignore errors --- src/nix/search.cc | 1 + 1 file changed, 1 insertion(+) diff --git a/src/nix/search.cc b/src/nix/search.cc index 764dcb70a..eb75493e4 100644 --- a/src/nix/search.cc +++ b/src/nix/search.cc @@ -261,6 +261,7 @@ struct CmdSearch : SourceExprCommand, MixJSON https://gcc.gnu.org/bugzilla/show_bug.cgi?id=66145 */ if (!jsonCacheFile) throw Error("error writing to %s", tmpFile); + throw; } if (writeCache && rename(tmpFile.c_str(), jsonCacheFileName.c_str()) == -1) From e6e61f0a54dac0174df996e93fcfedcac7769ab4 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 15:36:51 +0200 Subject: [PATCH 10/25] getSourceExpr(): Handle channels Fixes #1892. Fixes #1865. Fixes #3119. --- src/nix/installables.cc | 31 ++++++++++++++++--------------- 1 file changed, 16 insertions(+), 15 deletions(-) diff --git a/src/nix/installables.cc b/src/nix/installables.cc index 0c1ad3ab3..52f9778fc 100644 --- a/src/nix/installables.cc +++ b/src/nix/installables.cc @@ -45,25 +45,26 @@ Value * SourceExprCommand::getSourceExpr(EvalState & state) std::unordered_set seen; - for (auto & i : searchPath) { - if (i.first == "") continue; - if (seen.count(i.first)) continue; - seen.insert(i.first); -#if 0 - auto res = state.resolveSearchPathElem(i); - if (!res.first) continue; - if (!pathExists(res.second)) continue; - mkApp(*state.allocAttr(*vSourceExpr, state.symbols.create(i.first)), - state.getBuiltin("import"), - mkString(*state.allocValue(), res.second)); -#endif + auto addEntry = [&](const std::string & name) { + if (name == "") return; + if (!seen.insert(name).second) return; Value * v1 = state.allocValue(); mkPrimOpApp(*v1, state.getBuiltin("findFile"), state.getBuiltin("nixPath")); Value * v2 = state.allocValue(); - mkApp(*v2, *v1, mkString(*state.allocValue(), i.first)); - mkApp(*state.allocAttr(*vSourceExpr, state.symbols.create(i.first)), + mkApp(*v2, *v1, mkString(*state.allocValue(), name)); + mkApp(*state.allocAttr(*vSourceExpr, state.symbols.create(name)), state.getBuiltin("import"), *v2); - } + }; + + for (auto & i : searchPath) + /* Hack to handle channels. */ + if (i.first.empty() && pathExists(i.second + "/manifest.nix")) { + for (auto & j : readDirectory(i.second)) + if (j.name != "manifest.nix" + && pathExists(fmt("%s/%s/default.nix", i.second, j.name))) + addEntry(j.name); + } else + addEntry(i.first); vSourceExpr->attrs->sort(); } From 99b73fb5071db9fd757c9927fc3fde34e2abac63 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 15:51:52 +0200 Subject: [PATCH 11/25] OCD performance fix: {find,count}+insert => insert --- src/libexpr/eval.cc | 24 +++++++------------ src/libexpr/get-drvs.cc | 3 +-- src/libexpr/parser.y | 3 +-- src/libexpr/primops.cc | 6 ++--- src/libexpr/value-to-xml.cc | 5 ++-- src/libstore/build.cc | 11 ++++----- src/libstore/builtins/buildenv.cc | 3 +-- src/libstore/local-store.cc | 3 +-- src/libstore/misc.cc | 9 +++---- src/libstore/references.cc | 3 +-- src/libstore/store-api.cc | 3 +-- src/nix-env/nix-env.cc | 7 ++---- src/nix-store/dotgraph.cc | 7 ++---- src/nix-store/nix-store.cc | 3 +-- src/nix/verify.cc | 3 +-- .../resolve-system-dependencies.cc | 4 +--- 16 files changed, 32 insertions(+), 65 deletions(-) diff --git a/src/libexpr/eval.cc b/src/libexpr/eval.cc index 9f4b6b411..f60e8d3ab 100644 --- a/src/libexpr/eval.cc +++ b/src/libexpr/eval.cc @@ -46,11 +46,10 @@ static void printValue(std::ostream & str, std::set & active, con { checkInterrupt(); - if (active.find(&v) != active.end()) { + if (!active.insert(&v).second) { str << ""; return; } - active.insert(&v); switch (v.type) { case tInt: @@ -1446,8 +1445,7 @@ void EvalState::forceValueDeep(Value & v) std::function recurse; recurse = [&](Value & v) { - if (seen.find(&v) != seen.end()) return; - seen.insert(&v); + if (!seen.insert(&v).second) return; forceValue(v); @@ -1865,8 +1863,7 @@ size_t valueSize(Value & v) std::set seen; auto doString = [&](const char * s) -> size_t { - if (seen.find(s) != seen.end()) return 0; - seen.insert(s); + if (!seen.insert(s).second) return 0; return strlen(s) + 1; }; @@ -1874,8 +1871,7 @@ size_t valueSize(Value & v) std::function doEnv; doValue = [&](Value & v) -> size_t { - if (seen.find(&v) != seen.end()) return 0; - seen.insert(&v); + if (!seen.insert(&v).second) return 0; size_t sz = sizeof(Value); @@ -1890,8 +1886,7 @@ size_t valueSize(Value & v) sz += doString(v.path); break; case tAttrs: - if (seen.find(v.attrs) == seen.end()) { - seen.insert(v.attrs); + if (seen.insert(v.attrs).second) { sz += sizeof(Bindings) + sizeof(Attr) * v.attrs->capacity(); for (auto & i : *v.attrs) sz += doValue(*i.value); @@ -1900,8 +1895,7 @@ size_t valueSize(Value & v) case tList1: case tList2: case tListN: - if (seen.find(v.listElems()) == seen.end()) { - seen.insert(v.listElems()); + if (seen.insert(v.listElems()).second) { sz += v.listSize() * sizeof(Value *); for (size_t n = 0; n < v.listSize(); ++n) sz += doValue(*v.listElems()[n]); @@ -1922,8 +1916,7 @@ size_t valueSize(Value & v) sz += doValue(*v.primOpApp.right); break; case tExternal: - if (seen.find(v.external) != seen.end()) break; - seen.insert(v.external); + if (!seen.insert(v.external).second) break; sz += v.external->valueSize(seen); break; default: @@ -1934,8 +1927,7 @@ size_t valueSize(Value & v) }; doEnv = [&](Env & env) -> size_t { - if (seen.find(&env) != seen.end()) return 0; - seen.insert(&env); + if (!seen.insert(&env).second) return 0; size_t sz = sizeof(Env) + sizeof(Value *) * env.size; diff --git a/src/libexpr/get-drvs.cc b/src/libexpr/get-drvs.cc index 21a4d7917..4e22a1d77 100644 --- a/src/libexpr/get-drvs.cc +++ b/src/libexpr/get-drvs.cc @@ -277,8 +277,7 @@ static bool getDerivation(EvalState & state, Value & v, /* Remove spurious duplicates (e.g., a set like `rec { x = derivation {...}; y = x;}'. */ - if (done.find(v.attrs) != done.end()) return false; - done.insert(v.attrs); + if (!done.insert(v.attrs).second) return false; DrvInfo drv(state, attrPath, v.attrs); diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 967c88d9b..1dcd532ad 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -138,11 +138,10 @@ static void addAttr(ExprAttrs * attrs, AttrPath & attrPath, static void addFormal(const Pos & pos, Formals * formals, const Formal & formal) { - if (formals->argNames.find(formal.name) != formals->argNames.end()) + if (!formals->argNames.insert(formal.name).second) throw ParseError(format("duplicate formal function argument '%1%' at %2%") % formal.name % pos); formals->formals.push_front(formal); - formals->argNames.insert(formal.name); } diff --git a/src/libexpr/primops.cc b/src/libexpr/primops.cc index d4c60f870..deaffa605 100644 --- a/src/libexpr/primops.cc +++ b/src/libexpr/primops.cc @@ -396,8 +396,7 @@ static void prim_genericClosure(EvalState & state, const Pos & pos, Value * * ar throw EvalError(format("attribute 'key' required, at %1%") % pos); state.forceValue(*key->value); - if (doneKeys.find(key->value) != doneKeys.end()) continue; - doneKeys.insert(key->value); + if (!doneKeys.insert(key->value).second) continue; res.push_back(e); /* Call the `operator' function with `e' as argument. */ @@ -1273,13 +1272,12 @@ static void prim_listToAttrs(EvalState & state, const Pos & pos, Value * * args, string name = state.forceStringNoCtx(*j->value, pos); Symbol sym = state.symbols.create(name); - if (seen.find(sym) == seen.end()) { + if (seen.insert(sym).second) { Bindings::iterator j2 = v2.attrs->find(state.symbols.create(state.sValue)); if (j2 == v2.attrs->end()) throw TypeError(format("'value' attribute missing in a call to 'listToAttrs', at %1%") % pos); v.attrs->push_back(Attr(sym, j2->value, j2->pos)); - seen.insert(sym); } } diff --git a/src/libexpr/value-to-xml.cc b/src/libexpr/value-to-xml.cc index 00b1918a8..1f0b1541d 100644 --- a/src/libexpr/value-to-xml.cc +++ b/src/libexpr/value-to-xml.cc @@ -105,10 +105,9 @@ static void printValueAsXML(EvalState & state, bool strict, bool location, XMLOpenElement _(doc, "derivation", xmlAttrs); - if (drvPath != "" && drvsSeen.find(drvPath) == drvsSeen.end()) { - drvsSeen.insert(drvPath); + if (drvPath != "" && drvsSeen.insert(drvPath).second) showAttrs(state, strict, location, *v.attrs, doc, context, drvsSeen); - } else + else doc.writeEmptyElement("repeated"); } diff --git a/src/libstore/build.cc b/src/libstore/build.cc index 9a6729f9e..0e0f8a545 100644 --- a/src/libstore/build.cc +++ b/src/libstore/build.cc @@ -568,10 +568,9 @@ UserLock::UserLock() { auto lockedPaths(lockedPaths_.lock()); - if (lockedPaths->count(fnUserLock)) + if (!lockedPaths->insert(fnUserLock).second) /* We already have a lock on this one. */ continue; - lockedPaths->insert(fnUserLock); } try { @@ -620,8 +619,8 @@ UserLock::UserLock() UserLock::~UserLock() { auto lockedPaths(lockedPaths_.lock()); - assert(lockedPaths->count(fnUserLock)); - lockedPaths->erase(fnUserLock); + auto erased = lockedPaths->erase(fnUserLock); + assert(erased); } @@ -1125,10 +1124,8 @@ void DerivationGoal::addWantedOutputs(const StringSet & outputs) needRestart = true; } else for (auto & i : outputs) - if (wantedOutputs.find(i) == wantedOutputs.end()) { - wantedOutputs.insert(i); + if (wantedOutputs.insert(i).second) needRestart = true; - } } diff --git a/src/libstore/builtins/buildenv.cc b/src/libstore/builtins/buildenv.cc index 74e706664..096593886 100644 --- a/src/libstore/builtins/buildenv.cc +++ b/src/libstore/builtins/buildenv.cc @@ -123,8 +123,7 @@ static Path out; static void addPkg(const Path & pkgDir, int priority) { - if (done.count(pkgDir)) return; - done.insert(pkgDir); + if (!done.insert(pkgDir).second) return; createLinks(pkgDir, out, priority); try { diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index a2af51d0e..859094e61 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1292,8 +1292,7 @@ void LocalStore::verifyPath(const Path & path, const PathSet & store, { checkInterrupt(); - if (done.find(path) != done.end()) return; - done.insert(path); + if (!done.insert(path).second) return; if (!isStorePath(path)) { printError(format("path '%1%' is not in the Nix store") % path); diff --git a/src/libstore/misc.cc b/src/libstore/misc.cc index dddf13430..05b93d4c9 100644 --- a/src/libstore/misc.cc +++ b/src/libstore/misc.cc @@ -29,8 +29,7 @@ void Store::computeFSClosure(const PathSet & startPaths, { auto state(state_.lock()); if (state->exc) return; - if (state->paths.count(path)) return; - state->paths.insert(path); + if (!state->paths.insert(path).second) return; state->pending++; } @@ -175,8 +174,7 @@ void Store::queryMissing(const PathSet & targets, { auto state(state_.lock()); - if (state->done.count(path)) return; - state->done.insert(path); + if (!state->done.insert(path).second) return; } DrvPathWithOutputs i2 = parseDrvPathWithOutputs(path); @@ -252,8 +250,7 @@ Paths Store::topoSortPaths(const PathSet & paths) if (parents.find(path) != parents.end()) throw BuildError(format("cycle detected in the references of '%1%' from '%2%'") % path % *parent); - if (visited.find(path) != visited.end()) return; - visited.insert(path); + if (!visited.insert(path).second) return; parents.insert(path); PathSet references; diff --git a/src/libstore/references.cc b/src/libstore/references.cc index 5b7eb1f84..0dcc264c3 100644 --- a/src/libstore/references.cc +++ b/src/libstore/references.cc @@ -36,11 +36,10 @@ static void search(const unsigned char * s, size_t len, } if (!match) continue; string ref((const char *) s + i, refLength); - if (hashes.find(ref) != hashes.end()) { + if (hashes.erase(ref)) { debug(format("found reference to '%1%' at offset '%2%'") % ref % i); seen.insert(ref); - hashes.erase(ref); } ++i; } diff --git a/src/libstore/store-api.cc b/src/libstore/store-api.cc index 5f63c53b5..be13fa49a 100644 --- a/src/libstore/store-api.cc +++ b/src/libstore/store-api.cc @@ -954,8 +954,7 @@ std::list> getDefaultSubstituters() StringSet done; auto addStore = [&](const std::string & uri) { - if (done.count(uri)) return; - done.insert(uri); + if (!done.insert(uri).second) return; try { stores.push_back(openStore(uri)); } catch (Error & e) { diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 87b2e43f0..48686ce72 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -124,11 +124,10 @@ static void getAllExprs(EvalState & state, string attrName = i; if (hasSuffix(attrName, ".nix")) attrName = string(attrName, 0, attrName.size() - 4); - if (attrs.find(attrName) != attrs.end()) { + if (!attrs.insert(attrName).second) { printError(format("warning: name collision in input Nix expressions, skipping '%1%'") % path2); continue; } - attrs.insert(attrName); /* Load the expression on demand. */ Value & vFun = state.getBuiltin("import"); Value & vArg(*state.allocValue()); @@ -307,10 +306,8 @@ static DrvInfos filterBySelector(EvalState & state, const DrvInfos & allElems, /* Insert only those elements in the final list that we haven't inserted before. */ for (auto & j : matches) - if (done.find(j.second) == done.end()) { - done.insert(j.second); + if (done.insert(j.second).second) elems.push_back(j.first); - } } checkSelectorUse(selectors); diff --git a/src/nix-store/dotgraph.cc b/src/nix-store/dotgraph.cc index abdfa5e58..d448654fe 100644 --- a/src/nix-store/dotgraph.cc +++ b/src/nix-store/dotgraph.cc @@ -71,9 +71,7 @@ void printClosure(const Path & nePath, const StoreExpr & fs) Path path = *(workList.begin()); workList.erase(path); - if (doneSet.find(path) == doneSet.end()) { - doneSet.insert(path); - + if (doneSet.insert(path).second) { ClosureElems::const_iterator elem = fs.closure.elems.find(path); if (elem == fs.closure.elems.end()) throw Error(format("bad closure, missing path '%1%'") % path); @@ -104,8 +102,7 @@ void printDotGraph(ref store, const PathSet & roots) Path path = *(workList.begin()); workList.erase(path); - if (doneSet.find(path) != doneSet.end()) continue; - doneSet.insert(path); + if (!doneSet.insert(path).second) continue; cout << makeNode(path, symbolicName(path), "#ff0000"); diff --git a/src/nix-store/nix-store.cc b/src/nix-store/nix-store.cc index 0cbceb02f..19384499d 100644 --- a/src/nix-store/nix-store.cc +++ b/src/nix-store/nix-store.cc @@ -242,11 +242,10 @@ const string treeNull = " "; static void printTree(const Path & path, const string & firstPad, const string & tailPad, PathSet & done) { - if (done.find(path) != done.end()) { + if (!done.insert(path).second) { cout << format("%1%%2% [...]\n") % firstPad % path; return; } - done.insert(path); cout << format("%1%%2%\n") % firstPad % path; diff --git a/src/nix/verify.cc b/src/nix/verify.cc index 7ef571561..2e0d5cffe 100644 --- a/src/nix/verify.cc +++ b/src/nix/verify.cc @@ -118,8 +118,7 @@ struct CmdVerify : StorePathsCommand auto doSigs = [&](StringSet sigs) { for (auto sig : sigs) { - if (sigsSeen.count(sig)) continue; - sigsSeen.insert(sig); + if (!sigsSeen.insert(sig).second) continue; if (validSigs < ValidPathInfo::maxSigs && info->checkSignature(publicKeys, sig)) validSigs++; } diff --git a/src/resolve-system-dependencies/resolve-system-dependencies.cc b/src/resolve-system-dependencies/resolve-system-dependencies.cc index e02cfc03e..45e8b6796 100644 --- a/src/resolve-system-dependencies/resolve-system-dependencies.cc +++ b/src/resolve-system-dependencies/resolve-system-dependencies.cc @@ -117,9 +117,7 @@ Path resolveSymlink(const Path & path) std::set resolveTree(const Path & path, PathSet & deps) { std::set results; - if (deps.count(path)) - return {}; - deps.insert(path); + if (!deps.insert(path).second) return {}; for (auto & lib : runResolver(path)) { results.insert(lib); for (auto & p : resolveTree(lib, deps)) { From 926d3e5bb0ca696ab59352b25d0a818707a28186 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 22:57:37 +0200 Subject: [PATCH 12/25] Fix Bison 2.4 warning --- src/libexpr/parser.y | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libexpr/parser.y b/src/libexpr/parser.y index 1dcd532ad..93834bec6 100644 --- a/src/libexpr/parser.y +++ b/src/libexpr/parser.y @@ -1,5 +1,5 @@ %glr-parser -%pure-parser +%define api.pure %locations %define parse.error verbose %defines From 55bba8e4f51758e6c0556b24743e6946c96f6d92 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 23:04:11 +0200 Subject: [PATCH 13/25] Make std::uncaught_exception warning less noisy --- src/libutil/json.cc | 5 +++++ src/libutil/json.hh | 5 +---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/src/libutil/json.cc b/src/libutil/json.cc index 0a6fb65f0..74e37b4c4 100644 --- a/src/libutil/json.cc +++ b/src/libutil/json.cc @@ -171,4 +171,9 @@ JSONObject JSONPlaceholder::object() return JSONObject(state); } +JSONPlaceholder::~JSONPlaceholder() +{ + assert(!first || std::uncaught_exception()); +} + } diff --git a/src/libutil/json.hh b/src/libutil/json.hh index 02a39917f..83213ca66 100644 --- a/src/libutil/json.hh +++ b/src/libutil/json.hh @@ -168,10 +168,7 @@ public: { } - ~JSONPlaceholder() - { - assert(!first || std::uncaught_exception()); - } + ~JSONPlaceholder(); template void write(const T & v) From 4331eeb13d241dfe2d2e6a01c53915c556cac94f Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 23:25:06 +0200 Subject: [PATCH 14/25] Filter ANSI escape sequences in -L output Otherwise, builds like NixOS VM tests may leave the terminal in a weird state and do resets. --- src/nix/progress-bar.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/nix/progress-bar.cc b/src/nix/progress-bar.cc index c0bcfb0c9..5c05d6b22 100644 --- a/src/nix/progress-bar.cc +++ b/src/nix/progress-bar.cc @@ -120,7 +120,7 @@ public: void log(State & state, Verbosity lvl, const std::string & s) { if (state.active) { - writeToStderr("\r\e[K" + s + ANSI_NORMAL "\n"); + writeToStderr("\r\e[K" + filterANSIEscapes(s, !isTTY) + ANSI_NORMAL "\n"); draw(state); } else { auto s2 = s + ANSI_NORMAL "\n"; From 5a303093dcae1e5ce9212616ef18f2ca51020b0d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 18:01:21 +0200 Subject: [PATCH 15/25] Remove world-writability from per-user directories 'nix-daemon' now creates subdirectories for users when they first connect. Fixes #509 (CVE-2019-17365). Should also fix #3127. --- nix.spec.in | 2 +- scripts/install-multi-user.sh | 9 ++++----- scripts/nix-profile-daemon.sh.in | 13 ------------- scripts/nix-profile.sh.in | 14 -------------- src/libstore/local-store.cc | 24 ++++++++++++++++++++---- src/libstore/local-store.hh | 2 ++ src/libstore/store-api.hh | 3 +++ src/nix-daemon/nix-daemon.cc | 9 ++++++--- tests/nix-profile.sh | 2 -- tests/remote-store.sh | 4 ++++ tests/user-envs.sh | 2 +- 11 files changed, 41 insertions(+), 43 deletions(-) diff --git a/nix.spec.in b/nix.spec.in index 477768c6a..6b9e37637 100644 --- a/nix.spec.in +++ b/nix.spec.in @@ -106,7 +106,7 @@ chmod 1775 $RPM_BUILD_ROOT/nix/store for d in profiles gcroots; do mkdir -p $RPM_BUILD_ROOT/nix/var/nix/$d/per-user - chmod 1777 $RPM_BUILD_ROOT/nix/var/nix/$d/per-user + chmod 755 $RPM_BUILD_ROOT/nix/var/nix/$d/per-user done # fix permission of nix profile diff --git a/scripts/install-multi-user.sh b/scripts/install-multi-user.sh index fd0f54184..258469a0b 100644 --- a/scripts/install-multi-user.sh +++ b/scripts/install-multi-user.sh @@ -437,16 +437,15 @@ create_build_users() { } create_directories() { + # FIXME: remove all of this because it duplicates LocalStore::LocalStore(). + _sudo "to make the basic directory structure of Nix (part 1)" \ - mkdir -pv -m 0755 /nix /nix/var /nix/var/log /nix/var/log/nix /nix/var/log/nix/drvs /nix/var/nix{,/db,/gcroots,/profiles,/temproots,/userpool} + mkdir -pv -m 0755 /nix /nix/var /nix/var/log /nix/var/log/nix /nix/var/log/nix/drvs /nix/var/nix{,/db,/gcroots,/profiles,/temproots,/userpool} /nix/var/nix/{gcroots,profiles}/per-user _sudo "to make the basic directory structure of Nix (part 2)" \ - mkdir -pv -m 1777 /nix/var/nix/{gcroots,profiles}/per-user - - _sudo "to make the basic directory structure of Nix (part 3)" \ mkdir -pv -m 1775 /nix/store - _sudo "to make the basic directory structure of Nix (part 4)" \ + _sudo "to make the basic directory structure of Nix (part 3)" \ chgrp "$NIX_BUILD_GROUP_NAME" /nix/store _sudo "to set up the root user's profile (part 1)" \ diff --git a/scripts/nix-profile-daemon.sh.in b/scripts/nix-profile-daemon.sh.in index 23da5e855..3e138ac42 100644 --- a/scripts/nix-profile-daemon.sh.in +++ b/scripts/nix-profile-daemon.sh.in @@ -5,12 +5,6 @@ __ETC_PROFILE_NIX_SOURCED=1 export NIX_USER_PROFILE_DIR="@localstatedir@/nix/profiles/per-user/$USER" export NIX_PROFILES="@localstatedir@/nix/profiles/default $HOME/.nix-profile" -# Set up the per-user profile. -mkdir -m 0755 -p $NIX_USER_PROFILE_DIR -if ! test -O "$NIX_USER_PROFILE_DIR"; then - echo "WARNING: bad ownership on $NIX_USER_PROFILE_DIR" >&2 -fi - if test -w $HOME; then if ! test -L $HOME/.nix-profile; then if test "$USER" != root; then @@ -26,13 +20,6 @@ if test -w $HOME; then echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > $HOME/.nix-channels fi - # Create the per-user garbage collector roots directory. - NIX_USER_GCROOTS_DIR=@localstatedir@/nix/gcroots/per-user/$USER - mkdir -m 0755 -p $NIX_USER_GCROOTS_DIR - if ! test -O "$NIX_USER_GCROOTS_DIR"; then - echo "WARNING: bad ownership on $NIX_USER_GCROOTS_DIR" >&2 - fi - # Set up a default Nix expression from which to install stuff. if [ ! -e $HOME/.nix-defexpr -o -L $HOME/.nix-defexpr ]; then rm -f $HOME/.nix-defexpr diff --git a/scripts/nix-profile.sh.in b/scripts/nix-profile.sh.in index 85f1d6e5d..7f9b5877a 100644 --- a/scripts/nix-profile.sh.in +++ b/scripts/nix-profile.sh.in @@ -9,12 +9,6 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then NIX_USER_PROFILE_DIR=@localstatedir@/nix/profiles/per-user/$USER - mkdir -m 0755 -p "$NIX_USER_PROFILE_DIR" - - if [ "$(stat --printf '%u' "$NIX_USER_PROFILE_DIR")" != "$(id -u)" ]; then - echo "Nix: WARNING: bad ownership on "$NIX_USER_PROFILE_DIR", should be $(id -u)" >&2 - fi - if [ -w "$HOME" ]; then if ! [ -L "$NIX_LINK" ]; then echo "Nix: creating $NIX_LINK" >&2 @@ -33,14 +27,6 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > "$HOME/.nix-channels" fi - # Create the per-user garbage collector roots directory. - __user_gcroots=@localstatedir@/nix/gcroots/per-user/"$USER" - mkdir -m 0755 -p "$__user_gcroots" - if [ "$(stat --printf '%u' "$__user_gcroots")" != "$(id -u)" ]; then - echo "Nix: WARNING: bad ownership on $__user_gcroots, should be $(id -u)" >&2 - fi - unset __user_gcroots - # Set up a default Nix expression from which to install stuff. __nix_defexpr="$HOME"/.nix-defexpr [ -L "$__nix_defexpr" ] && rm -f "$__nix_defexpr" diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 859094e61..685d43c9c 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -74,10 +74,11 @@ LocalStore::LocalStore(const Params & params) multi-user install. */ if (getuid() == 0 && settings.buildUsersGroup != "") { - Path perUserDir = profilesDir + "/per-user"; - createDirs(perUserDir); - if (chmod(perUserDir.c_str(), 01777) == -1) - throw SysError(format("could not set permissions on '%1%' to 1777") % perUserDir); + for (auto & perUserDir : {profilesDir + "/per-user", gcRootsDir + "/per-user"}) { + createDirs(perUserDir); + if (chmod(perUserDir.c_str(), 0755) == -1) + throw SysError("could not set permissions on '%s' to 755", perUserDir); + } mode_t perm = 01775; @@ -1432,4 +1433,19 @@ void LocalStore::signPathInfo(ValidPathInfo & info) } +void LocalStore::createUser(const std::string & userName, uid_t userId) +{ + for (auto & dir : { + fmt("%s/profiles/per-user/%s", stateDir, userName), + fmt("%s/gcroots/per-user/%s", stateDir, userName) + }) { + createDirs(dir); + if (chmod(dir.c_str(), 0700) == -1) + throw SysError("changing permissions of directory '%s'", dir); + if (chown(dir.c_str(), userId, -1) == -1) + throw SysError("changing owner of directory '%s'", dir); + } +} + + } diff --git a/src/libstore/local-store.hh b/src/libstore/local-store.hh index 3ae34c403..379a06af8 100644 --- a/src/libstore/local-store.hh +++ b/src/libstore/local-store.hh @@ -293,6 +293,8 @@ private: Path getRealStoreDir() override { return realStoreDir; } + void createUser(const std::string & userName, uid_t userId) override; + friend class DerivationGoal; friend class SubstitutionGoal; }; diff --git a/src/libstore/store-api.hh b/src/libstore/store-api.hh index 7fb568602..ba8990755 100644 --- a/src/libstore/store-api.hh +++ b/src/libstore/store-api.hh @@ -628,6 +628,9 @@ public: return storePath; } + virtual void createUser(const std::string & userName, uid_t userId) + { } + protected: Stats stats; diff --git a/src/nix-daemon/nix-daemon.cc b/src/nix-daemon/nix-daemon.cc index e88aaf636..cd18489b0 100644 --- a/src/nix-daemon/nix-daemon.cc +++ b/src/nix-daemon/nix-daemon.cc @@ -742,7 +742,8 @@ static void performOp(TunnelLogger * logger, ref store, } -static void processConnection(bool trusted) +static void processConnection(bool trusted, + const std::string & userName, uid_t userId) { MonitorFdHup monitor(from.fd); @@ -793,6 +794,8 @@ static void processConnection(bool trusted) params["path-info-cache-size"] = "0"; auto store = openStore(settings.storeUri, params); + store->createUser(userName, userId); + tunnelLogger->stopWork(); to.flush(); @@ -1053,7 +1056,7 @@ static void daemonLoop(char * * argv) /* Handle the connection. */ from.fd = remote.get(); to.fd = remote.get(); - processConnection(trusted); + processConnection(trusted, user, peer.uid); exit(0); }, options); @@ -1133,7 +1136,7 @@ static int _main(int argc, char * * argv) } } } else { - processConnection(true); + processConnection(true, "root", 0); } } else { daemonLoop(argv); diff --git a/tests/nix-profile.sh b/tests/nix-profile.sh index b244815e2..5b17fe3fa 100644 --- a/tests/nix-profile.sh +++ b/tests/nix-profile.sh @@ -10,5 +10,3 @@ USER=$user $SHELL -e -c ". $TEST_ROOT/nix-profile.sh" # test idempotency [ -L $TEST_HOME/.nix-profile ] [ -e $TEST_HOME/.nix-channels ] -[ -e $TEST_ROOT/profile-var/nix/gcroots/per-user/$user ] -[ -e $TEST_ROOT/profile-var/nix/profiles/per-user/$user ] diff --git a/tests/remote-store.sh b/tests/remote-store.sh index f2f2806d0..77437658e 100644 --- a/tests/remote-store.sh +++ b/tests/remote-store.sh @@ -13,3 +13,7 @@ cmp $TEST_ROOT/d1 $TEST_ROOT/d2 nix-store --gc --max-freed 1K killDaemon + +user=$(whoami) +[ -e $NIX_STATE_DIR/gcroots/per-user/$user ] +[ -e $NIX_STATE_DIR/profiles/per-user/$user ] diff --git a/tests/user-envs.sh b/tests/user-envs.sh index ba6392311..aebf6a2a2 100644 --- a/tests/user-envs.sh +++ b/tests/user-envs.sh @@ -20,7 +20,7 @@ drvPath10=$(nix-env -f ./user-envs.nix -qa --drv-path --no-name '*' | grep foo-1 # Query descriptions. nix-env -f ./user-envs.nix -qa '*' --description | grep -q silly -rm -f $HOME/.nix-defexpr +rm -rf $HOME/.nix-defexpr ln -s $(pwd)/user-envs.nix $HOME/.nix-defexpr nix-env -qa '*' --description | grep -q silly From c43d9f6131102f2761f22b1ec26f345d357f169c Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 18:05:42 +0200 Subject: [PATCH 16/25] Remove some redundant initialization --- scripts/install-multi-user.sh | 6 ------ 1 file changed, 6 deletions(-) diff --git a/scripts/install-multi-user.sh b/scripts/install-multi-user.sh index 258469a0b..40013eaaf 100644 --- a/scripts/install-multi-user.sh +++ b/scripts/install-multi-user.sh @@ -448,12 +448,6 @@ create_directories() { _sudo "to make the basic directory structure of Nix (part 3)" \ chgrp "$NIX_BUILD_GROUP_NAME" /nix/store - _sudo "to set up the root user's profile (part 1)" \ - mkdir -pv -m 0755 /nix/var/nix/profiles/per-user/root - - _sudo "to set up the root user's profile (part 2)" \ - mkdir -pv -m 0700 "$ROOT_HOME/.nix-defexpr" - _sudo "to place the default nix daemon configuration (part 1)" \ mkdir -pv -m 0555 /etc/nix } From 26762ceb8629af95300c0cc8c372a99282060dc1 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 18:30:31 +0200 Subject: [PATCH 17/25] nix-profile.sh: Don't create .nix-channels This is already done by the installer, so no need to do it again. --- scripts/nix-profile-daemon.sh.in | 5 ----- scripts/nix-profile.sh.in | 5 ----- tests/nix-profile.sh | 1 - 3 files changed, 11 deletions(-) diff --git a/scripts/nix-profile-daemon.sh.in b/scripts/nix-profile-daemon.sh.in index 3e138ac42..2133a6d3b 100644 --- a/scripts/nix-profile-daemon.sh.in +++ b/scripts/nix-profile-daemon.sh.in @@ -15,11 +15,6 @@ if test -w $HOME; then fi fi - # Subscribe the root user to the NixOS channel by default. - if [ "$USER" = root -a ! -e $HOME/.nix-channels ]; then - echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > $HOME/.nix-channels - fi - # Set up a default Nix expression from which to install stuff. if [ ! -e $HOME/.nix-defexpr -o -L $HOME/.nix-defexpr ]; then rm -f $HOME/.nix-defexpr diff --git a/scripts/nix-profile.sh.in b/scripts/nix-profile.sh.in index 7f9b5877a..8e70c68b2 100644 --- a/scripts/nix-profile.sh.in +++ b/scripts/nix-profile.sh.in @@ -22,11 +22,6 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then fi fi - # Subscribe the user to the unstable Nixpkgs channel by default. - if [ ! -e "$HOME/.nix-channels" ]; then - echo "https://nixos.org/channels/nixpkgs-unstable nixpkgs" > "$HOME/.nix-channels" - fi - # Set up a default Nix expression from which to install stuff. __nix_defexpr="$HOME"/.nix-defexpr [ -L "$__nix_defexpr" ] && rm -f "$__nix_defexpr" diff --git a/tests/nix-profile.sh b/tests/nix-profile.sh index 5b17fe3fa..b808cf1b4 100644 --- a/tests/nix-profile.sh +++ b/tests/nix-profile.sh @@ -9,4 +9,3 @@ USER=$user $SHELL -e -c ". $TEST_ROOT/nix-profile.sh; set" USER=$user $SHELL -e -c ". $TEST_ROOT/nix-profile.sh" # test idempotency [ -L $TEST_HOME/.nix-profile ] -[ -e $TEST_HOME/.nix-channels ] From 9348f9291e5d9e4ba3c4347ea1b235640f54fd79 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 19:21:07 +0200 Subject: [PATCH 18/25] nix-env: Create ~/.nix-profile automatically --- scripts/nix-profile-daemon.sh.in | 9 --------- scripts/nix-profile.sh.in | 12 ------------ src/libstore/local-store.cc | 15 ++++++++------- src/libutil/util.cc | 10 ++++++++++ src/libutil/util.hh | 2 ++ src/nix-channel/nix-channel.cc | 8 +------- src/nix-env/nix-env.cc | 11 ++++++++--- tests/nix-channel.sh | 4 ++-- tests/nix-profile.sh | 2 -- 9 files changed, 31 insertions(+), 42 deletions(-) diff --git a/scripts/nix-profile-daemon.sh.in b/scripts/nix-profile-daemon.sh.in index 2133a6d3b..aa78e6fcc 100644 --- a/scripts/nix-profile-daemon.sh.in +++ b/scripts/nix-profile-daemon.sh.in @@ -6,15 +6,6 @@ export NIX_USER_PROFILE_DIR="@localstatedir@/nix/profiles/per-user/$USER" export NIX_PROFILES="@localstatedir@/nix/profiles/default $HOME/.nix-profile" if test -w $HOME; then - if ! test -L $HOME/.nix-profile; then - if test "$USER" != root; then - ln -s $NIX_USER_PROFILE_DIR/profile $HOME/.nix-profile - else - # Root installs in the system-wide profile by default. - ln -s @localstatedir@/nix/profiles/default $HOME/.nix-profile - fi - fi - # Set up a default Nix expression from which to install stuff. if [ ! -e $HOME/.nix-defexpr -o -L $HOME/.nix-defexpr ]; then rm -f $HOME/.nix-defexpr diff --git a/scripts/nix-profile.sh.in b/scripts/nix-profile.sh.in index 8e70c68b2..087f6ee57 100644 --- a/scripts/nix-profile.sh.in +++ b/scripts/nix-profile.sh.in @@ -10,18 +10,6 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then NIX_USER_PROFILE_DIR=@localstatedir@/nix/profiles/per-user/$USER if [ -w "$HOME" ]; then - if ! [ -L "$NIX_LINK" ]; then - echo "Nix: creating $NIX_LINK" >&2 - if [ "$USER" != root ]; then - if ! ln -s "$NIX_USER_PROFILE_DIR"/profile "$NIX_LINK"; then - echo "Nix: WARNING: could not create $NIX_LINK -> $NIX_USER_PROFILE_DIR/profile" >&2 - fi - else - # Root installs in the system-wide profile by default. - ln -s @localstatedir@/nix/profiles/default "$NIX_LINK" - fi - fi - # Set up a default Nix expression from which to install stuff. __nix_defexpr="$HOME"/.nix-defexpr [ -L "$__nix_defexpr" ] && rm -f "$__nix_defexpr" diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 685d43c9c..2bc04da46 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -70,16 +70,17 @@ LocalStore::LocalStore(const Params & params) createSymlink(profilesDir, gcRootsDir + "/profiles"); } + for (auto & perUserDir : {profilesDir + "/per-user", gcRootsDir + "/per-user"}) { + createDirs(perUserDir); + if (chmod(perUserDir.c_str(), 0755) == -1) + throw SysError("could not set permissions on '%s' to 755", perUserDir); + } + + createUser(getUserName(), getuid()); + /* Optionally, create directories and set permissions for a multi-user install. */ if (getuid() == 0 && settings.buildUsersGroup != "") { - - for (auto & perUserDir : {profilesDir + "/per-user", gcRootsDir + "/per-user"}) { - createDirs(perUserDir); - if (chmod(perUserDir.c_str(), 0755) == -1) - throw SysError("could not set permissions on '%s' to 755", perUserDir); - } - mode_t perm = 01775; struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str()); diff --git a/src/libutil/util.cc b/src/libutil/util.cc index 1b7449991..6f3bf7ae8 100644 --- a/src/libutil/util.cc +++ b/src/libutil/util.cc @@ -475,6 +475,16 @@ Path createTempDir(const Path & tmpRoot, const Path & prefix, } +std::string getUserName() +{ + auto pw = getpwuid(geteuid()); + std::string name = pw ? pw->pw_name : getEnv("USER", ""); + if (name.empty()) + throw Error("cannot figure out user name"); + return name; +} + + static Lazy getHome2([]() { Path homeDir = getEnv("HOME"); if (homeDir.empty()) { diff --git a/src/libutil/util.hh b/src/libutil/util.hh index 07c3d28ff..f057fdb2c 100644 --- a/src/libutil/util.hh +++ b/src/libutil/util.hh @@ -126,6 +126,8 @@ void deletePath(const Path & path, unsigned long long & bytesFreed); Path createTempDir(const Path & tmpRoot = "", const Path & prefix = "nix", bool includePid = true, bool useGlobalCounter = true, mode_t mode = 0755); +std::string getUserName(); + /* Return $HOME or the user's home directory from /etc/passwd. */ Path getHome(); diff --git a/src/nix-channel/nix-channel.cc b/src/nix-channel/nix-channel.cc index 06eb3d23b..70aa5c966 100755 --- a/src/nix-channel/nix-channel.cc +++ b/src/nix-channel/nix-channel.cc @@ -159,13 +159,7 @@ static int _main(int argc, char ** argv) nixDefExpr = home + "/.nix-defexpr"; // Figure out the name of the channels profile. - ; - auto pw = getpwuid(geteuid()); - std::string name = pw ? pw->pw_name : getEnv("USER", ""); - if (name.empty()) - throw Error("cannot figure out user name"); - profile = settings.nixStateDir + "/profiles/per-user/" + name + "/channels"; - createDirs(dirOf(profile)); + profile = fmt("%s/profiles/per-user/%s/channels", settings.nixStateDir, getUserName()); enum { cNone, diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 48686ce72..1b412f0bd 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -1422,9 +1422,14 @@ static int _main(int argc, char * * argv) if (globals.profile == "") { Path profileLink = getHome() + "/.nix-profile"; - globals.profile = pathExists(profileLink) - ? absPath(readLink(profileLink), dirOf(profileLink)) - : canonPath(settings.nixStateDir + "/profiles/default"); + if (!pathExists(profileLink)) { + replaceSymlink( + getuid() == 0 + ? settings.nixStateDir + "/profiles/default" + : fmt("%s/profiles/per-user/%s/profile", settings.nixStateDir, getUserName()), + profileLink); + } + globals.profile = absPath(readLink(profileLink), dirOf(profileLink)); } op(globals, opFlags, opArgs); diff --git a/tests/nix-channel.sh b/tests/nix-channel.sh index 55f1695c4..93f837bef 100644 --- a/tests/nix-channel.sh +++ b/tests/nix-channel.sh @@ -36,7 +36,7 @@ grep -q 'item.*attrPath="foo".*name="dependencies"' $TEST_ROOT/meta.xml # Do an install. nix-env -i dependencies -[ -e $TEST_ROOT/var/nix/profiles/default/foobar ] +[ -e $TEST_HOME/.nix-profile/foobar ] clearProfiles rm -f $TEST_HOME/.nix-channels @@ -55,5 +55,5 @@ grep -q 'item.*attrPath="foo".*name="dependencies"' $TEST_ROOT/meta.xml # Do an install. nix-env -i dependencies -[ -e $TEST_ROOT/var/nix/profiles/default/foobar ] +[ -e $TEST_HOME/.nix-profile/foobar ] diff --git a/tests/nix-profile.sh b/tests/nix-profile.sh index b808cf1b4..e2e0d1090 100644 --- a/tests/nix-profile.sh +++ b/tests/nix-profile.sh @@ -7,5 +7,3 @@ rm -rf $TEST_HOME $TEST_ROOT/profile-var mkdir -p $TEST_HOME USER=$user $SHELL -e -c ". $TEST_ROOT/nix-profile.sh; set" USER=$user $SHELL -e -c ". $TEST_ROOT/nix-profile.sh" # test idempotency - -[ -L $TEST_HOME/.nix-profile ] From 61a6176acaa8522cbcf091a34a663ef45307fef7 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 19:38:01 +0200 Subject: [PATCH 19/25] nix-profile.sh: Remove coreutils dependency --- scripts/nix-profile.sh.in | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/scripts/nix-profile.sh.in b/scripts/nix-profile.sh.in index 087f6ee57..ed4d1a639 100644 --- a/scripts/nix-profile.sh.in +++ b/scripts/nix-profile.sh.in @@ -1,6 +1,4 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then - __savedpath="$PATH" - export PATH=@coreutils@ # Set up the per-user profile. # This part should be kept in sync with nixpkgs:nixos/modules/programs/shell.nix @@ -47,6 +45,6 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then export MANPATH="$NIX_LINK/share/man:$MANPATH" fi - export PATH="$NIX_LINK/bin:$__savedpath" - unset __savedpath NIX_LINK NIX_USER_PROFILE_DIR + export PATH="$NIX_LINK/bin:$PATH" + unset NIX_LINK NIX_USER_PROFILE_DIR fi From c9159f86cc9a2fc07e2ab1217c2d8a8824123df4 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 19:50:46 +0200 Subject: [PATCH 20/25] nix-env: Create ~/.nix-defexpr automatically --- scripts/nix-profile-daemon.sh.in | 12 ------------ scripts/nix-profile.sh.in | 11 ----------- src/nix-env/nix-env.cc | 19 ++++++++++++------- 3 files changed, 12 insertions(+), 30 deletions(-) diff --git a/scripts/nix-profile-daemon.sh.in b/scripts/nix-profile-daemon.sh.in index aa78e6fcc..47655080a 100644 --- a/scripts/nix-profile-daemon.sh.in +++ b/scripts/nix-profile-daemon.sh.in @@ -5,18 +5,6 @@ __ETC_PROFILE_NIX_SOURCED=1 export NIX_USER_PROFILE_DIR="@localstatedir@/nix/profiles/per-user/$USER" export NIX_PROFILES="@localstatedir@/nix/profiles/default $HOME/.nix-profile" -if test -w $HOME; then - # Set up a default Nix expression from which to install stuff. - if [ ! -e $HOME/.nix-defexpr -o -L $HOME/.nix-defexpr ]; then - rm -f $HOME/.nix-defexpr - mkdir -p $HOME/.nix-defexpr - if [ "$USER" != root ]; then - ln -s @localstatedir@/nix/profiles/per-user/root/channels $HOME/.nix-defexpr/channels_root - fi - fi -fi - - # Set $NIX_SSL_CERT_FILE so that Nixpkgs applications like curl work. if [ ! -z "${NIX_SSL_CERT_FILE:-}" ]; then : # Allow users to override the NIX_SSL_CERT_FILE diff --git a/scripts/nix-profile.sh.in b/scripts/nix-profile.sh.in index ed4d1a639..e15f7cd46 100644 --- a/scripts/nix-profile.sh.in +++ b/scripts/nix-profile.sh.in @@ -7,17 +7,6 @@ if [ -n "$HOME" ] && [ -n "$USER" ]; then NIX_USER_PROFILE_DIR=@localstatedir@/nix/profiles/per-user/$USER - if [ -w "$HOME" ]; then - # Set up a default Nix expression from which to install stuff. - __nix_defexpr="$HOME"/.nix-defexpr - [ -L "$__nix_defexpr" ] && rm -f "$__nix_defexpr" - mkdir -m 0755 -p "$__nix_defexpr" - if [ "$USER" != root ] && [ ! -L "$__nix_defexpr"/channels_root ]; then - ln -s @localstatedir@/nix/profiles/per-user/root/channels "$__nix_defexpr"/channels_root - fi - unset __nix_defexpr - fi - # Append ~/.nix-defexpr/channels to $NIX_PATH so that # paths work when the user has fetched the Nixpkgs channel. export NIX_PATH=${NIX_PATH:+$NIX_PATH:}$HOME/.nix-defexpr/channels diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 1b412f0bd..2aeb8ebb0 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -192,12 +192,6 @@ static void loadDerivations(EvalState & state, Path nixExprPath, } -static Path getDefNixExprPath() -{ - return getHome() + "/.nix-defexpr"; -} - - static long getPriority(EvalState & state, DrvInfo & drv) { return drv.queryMetaInt("priority", 0); @@ -1327,9 +1321,20 @@ static int _main(int argc, char * * argv) Globals globals; globals.instSource.type = srcUnknown; - globals.instSource.nixExprPath = getDefNixExprPath(); + globals.instSource.nixExprPath = getHome() + "/.nix-defexpr"; globals.instSource.systemFilter = "*"; + if (!pathExists(globals.instSource.nixExprPath)) { + createDirs(globals.instSource.nixExprPath); + replaceSymlink( + fmt("%s/profiles/per-user/%s/channels", settings.nixStateDir, getUserName()), + globals.instSource.nixExprPath + "/channels"); + if (getuid() != 0) + replaceSymlink( + fmt("%s/profiles/per-user/root/channels", settings.nixStateDir), + globals.instSource.nixExprPath + "/channels_root"); + } + globals.dryRun = false; globals.preserveInstalled = false; globals.removeAll = false; From d7bae5680fc26303acb9a9ee1a202f537841a624 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 19:55:05 +0200 Subject: [PATCH 21/25] Go back to 755 permission on per-user directories 700 is pointless since the store is world-readable anyway. And per-user/root/channels must be world-readable. --- src/libstore/local-store.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 2bc04da46..fbf5dc35c 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1441,7 +1441,7 @@ void LocalStore::createUser(const std::string & userName, uid_t userId) fmt("%s/gcroots/per-user/%s", stateDir, userName) }) { createDirs(dir); - if (chmod(dir.c_str(), 0700) == -1) + if (chmod(dir.c_str(), 0755) == -1) throw SysError("changing permissions of directory '%s'", dir); if (chown(dir.c_str(), userId, -1) == -1) throw SysError("changing owner of directory '%s'", dir); From 9277e72cb0aac72100c01334fdf25ea79d19052e Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 21:04:21 +0200 Subject: [PATCH 22/25] Typo --- scripts/install-multi-user.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/scripts/install-multi-user.sh b/scripts/install-multi-user.sh index 40013eaaf..d060e5165 100644 --- a/scripts/install-multi-user.sh +++ b/scripts/install-multi-user.sh @@ -490,7 +490,7 @@ EOF We will: - make sure your computer doesn't already have Nix files - (if it does, I will tell you how to clean them up.) + (if it does, I will tell you how to clean them up.) - create local users (see the list above for the users we'll make) - create a local group ($NIX_BUILD_GROUP_NAME) - install Nix in to $NIX_ROOT From 20eec802ff11dd2b152715cd5c81b756d318219d Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Wed, 9 Oct 2019 23:33:28 +0200 Subject: [PATCH 23/25] Force per-user group to a known value --- src/libstore/local-store.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index fbf5dc35c..00f3a31a2 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1443,7 +1443,7 @@ void LocalStore::createUser(const std::string & userName, uid_t userId) createDirs(dir); if (chmod(dir.c_str(), 0755) == -1) throw SysError("changing permissions of directory '%s'", dir); - if (chown(dir.c_str(), userId, -1) == -1) + if (chown(dir.c_str(), userId, 0) == -1) throw SysError("changing owner of directory '%s'", dir); } } From bda64a2b0f79346012332ed18f5a76388e6d9bae Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 10 Oct 2019 00:12:30 +0200 Subject: [PATCH 24/25] Doh https://hydra.nixos.org/build/102803044 --- src/libstore/local-store.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/libstore/local-store.cc b/src/libstore/local-store.cc index 00f3a31a2..d86f7b1d2 100644 --- a/src/libstore/local-store.cc +++ b/src/libstore/local-store.cc @@ -1443,7 +1443,7 @@ void LocalStore::createUser(const std::string & userName, uid_t userId) createDirs(dir); if (chmod(dir.c_str(), 0755) == -1) throw SysError("changing permissions of directory '%s'", dir); - if (chown(dir.c_str(), userId, 0) == -1) + if (chown(dir.c_str(), userId, getgid()) == -1) throw SysError("changing owner of directory '%s'", dir); } } From c3aaf3b8da1a925c569389f13a861816a781a3c8 Mon Sep 17 00:00:00 2001 From: Eelco Dolstra Date: Thu, 10 Oct 2019 09:14:05 +0200 Subject: [PATCH 25/25] nix-env: Ignore failures creating ~/.nix-profile and ~/.nix-defexpr https://hydra.nixos.org/build/102803093 --- src/nix-env/nix-env.cc | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/src/nix-env/nix-env.cc b/src/nix-env/nix-env.cc index 2aeb8ebb0..199dc92aa 100644 --- a/src/nix-env/nix-env.cc +++ b/src/nix-env/nix-env.cc @@ -1325,14 +1325,16 @@ static int _main(int argc, char * * argv) globals.instSource.systemFilter = "*"; if (!pathExists(globals.instSource.nixExprPath)) { - createDirs(globals.instSource.nixExprPath); - replaceSymlink( - fmt("%s/profiles/per-user/%s/channels", settings.nixStateDir, getUserName()), - globals.instSource.nixExprPath + "/channels"); - if (getuid() != 0) + try { + createDirs(globals.instSource.nixExprPath); replaceSymlink( - fmt("%s/profiles/per-user/root/channels", settings.nixStateDir), - globals.instSource.nixExprPath + "/channels_root"); + fmt("%s/profiles/per-user/%s/channels", settings.nixStateDir, getUserName()), + globals.instSource.nixExprPath + "/channels"); + if (getuid() != 0) + replaceSymlink( + fmt("%s/profiles/per-user/root/channels", settings.nixStateDir), + globals.instSource.nixExprPath + "/channels_root"); + } catch (Error &) { } } globals.dryRun = false; @@ -1427,14 +1429,18 @@ static int _main(int argc, char * * argv) if (globals.profile == "") { Path profileLink = getHome() + "/.nix-profile"; - if (!pathExists(profileLink)) { - replaceSymlink( - getuid() == 0 - ? settings.nixStateDir + "/profiles/default" - : fmt("%s/profiles/per-user/%s/profile", settings.nixStateDir, getUserName()), - profileLink); + try { + if (!pathExists(profileLink)) { + replaceSymlink( + getuid() == 0 + ? settings.nixStateDir + "/profiles/default" + : fmt("%s/profiles/per-user/%s/profile", settings.nixStateDir, getUserName()), + profileLink); + } + globals.profile = absPath(readLink(profileLink), dirOf(profileLink)); + } catch (Error &) { + globals.profile = profileLink; } - globals.profile = absPath(readLink(profileLink), dirOf(profileLink)); } op(globals, opFlags, opArgs);