1
1
Fork 0
mirror of https://github.com/NixOS/nix.git synced 2025-11-15 23:12:44 +01:00

Merge remote-tracking branch 'upstream/master' into overlayfs-store

This commit is contained in:
John Ericson 2024-04-05 16:32:02 -04:00
commit c99c80f075
200 changed files with 6007 additions and 1158 deletions

View file

@ -124,14 +124,6 @@ void BinaryCacheStore::writeNarInfo(ref<NarInfo> narInfo)
diskCache->upsertNarInfo(getUri(), std::string(narInfo->path.hashPart()), std::shared_ptr<NarInfo>(narInfo));
}
AutoCloseFD openFile(const Path & path)
{
auto fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
if (!fd)
throw SysError("opening file '%1%'", path);
return fd;
}
ref<const ValidPathInfo> BinaryCacheStore::addToStoreCommon(
Source & narSource, RepairFlag repair, CheckSigsFlag checkSigs,
std::function<ValidPathInfo(HashResult)> mkInfo)

View file

@ -17,7 +17,6 @@
#include "cgroup.hh"
#include "personality.hh"
#include "current-process.hh"
#include "namespaces.hh"
#include "child.hh"
#include "unix-domain-socket.hh"
#include "posix-fs-canonicalise.hh"
@ -40,18 +39,19 @@
/* Includes required for chroot support. */
#if __linux__
#include <sys/ioctl.h>
#include <net/if.h>
#include <netinet/ip.h>
#include <sys/mman.h>
#include <sched.h>
#include <sys/param.h>
#include <sys/mount.h>
#include <sys/syscall.h>
#if HAVE_SECCOMP
#include <seccomp.h>
#endif
#define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root, put_old))
# include <sys/ioctl.h>
# include <net/if.h>
# include <netinet/ip.h>
# include <sys/mman.h>
# include <sched.h>
# include <sys/param.h>
# include <sys/mount.h>
# include <sys/syscall.h>
# include "namespaces.hh"
# if HAVE_SECCOMP
# include <seccomp.h>
# endif
# define pivot_root(new_root, put_old) (syscall(SYS_pivot_root, new_root, put_old))
#endif
#if __APPLE__
@ -488,7 +488,7 @@ void LocalDerivationGoal::startBuilder()
/* Create a temporary directory where the build will take
place. */
tmpDir = createTempDir("", "nix-build-" + std::string(drvPath.name()), false, false, 0700);
tmpDir = createTempDir(settings.buildDir.get().value_or(""), "nix-build-" + std::string(drvPath.name()), false, false, 0700);
chownToBuilder(tmpDir);
@ -2053,13 +2053,13 @@ void LocalDerivationGoal::runChild()
i.first, i.second.source);
std::string path = i.first;
struct stat st;
if (lstat(path.c_str(), &st)) {
if (i.second.optional && errno == ENOENT)
auto optSt = maybeLstat(path.c_str());
if (!optSt) {
if (i.second.optional)
continue;
throw SysError("getting attributes of path '%s", path);
throw SysError("getting attributes of required path '%s", path);
}
if (S_ISDIR(st.st_mode))
if (S_ISDIR(optSt->st_mode))
sandboxProfile += fmt("\t(subpath \"%s\")\n", path);
else
sandboxProfile += fmt("\t(literal \"%s\")\n", path);
@ -2089,11 +2089,12 @@ void LocalDerivationGoal::runChild()
bool allowLocalNetworking = parsedDrv->getBoolAttr("__darwinAllowLocalNetworking");
/* The tmpDir in scope points at the temporary build directory for our derivation. Some packages try different mechanisms
to find temporary directories, so we want to open up a broader place for them to dump their files, if needed. */
Path globalTmpDir = canonPath(getEnvNonEmpty("TMPDIR").value_or("/tmp"), true);
to find temporary directories, so we want to open up a broader place for them to put their files, if needed. */
Path globalTmpDir = canonPath(defaultTempDir(), true);
/* They don't like trailing slashes on subpath directives */
if (globalTmpDir.back() == '/') globalTmpDir.pop_back();
while (!globalTmpDir.empty() && globalTmpDir.back() == '/')
globalTmpDir.pop_back();
if (getEnv("_NIX_TEST_NO_SANDBOX") != "1") {
builder = "/usr/bin/sandbox-exec";
@ -2270,14 +2271,12 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
continue;
}
struct stat st;
if (lstat(actualPath.c_str(), &st) == -1) {
if (errno == ENOENT)
throw BuildError(
"builder for '%s' failed to produce output path for output '%s' at '%s'",
worker.store.printStorePath(drvPath), outputName, actualPath);
throw SysError("getting attributes of path '%s'", actualPath);
}
auto optSt = maybeLstat(actualPath.c_str());
if (!optSt)
throw BuildError(
"builder for '%s' failed to produce output path for output '%s' at '%s'",
worker.store.printStorePath(drvPath), outputName, actualPath);
struct stat & st = *optSt;
#ifndef __CYGWIN__
/* Check that the output is not group or world writable, as

View file

@ -64,9 +64,9 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
continue;
else if (S_ISDIR(srcSt.st_mode)) {
struct stat dstSt;
auto res = lstat(dstFile.c_str(), &dstSt);
if (res == 0) {
auto dstStOpt = maybeLstat(dstFile.c_str());
if (dstStOpt) {
auto & dstSt = *dstStOpt;
if (S_ISDIR(dstSt.st_mode)) {
createLinks(state, srcFile, dstFile, priority);
continue;
@ -82,14 +82,13 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
createLinks(state, srcFile, dstFile, priority);
continue;
}
} else if (errno != ENOENT)
throw SysError("getting status of '%1%'", dstFile);
}
}
else {
struct stat dstSt;
auto res = lstat(dstFile.c_str(), &dstSt);
if (res == 0) {
auto dstStOpt = maybeLstat(dstFile.c_str());
if (dstStOpt) {
auto & dstSt = *dstStOpt;
if (S_ISLNK(dstSt.st_mode)) {
auto prevPriority = state.priorities[dstFile];
if (prevPriority == priority)
@ -104,8 +103,7 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
throw SysError("unlinking '%1%'", dstFile);
} else if (S_ISDIR(dstSt.st_mode))
throw Error("collision between non-directory '%1%' and directory '%2%'", srcFile, dstFile);
} else if (errno != ENOENT)
throw SysError("getting status of '%1%'", dstFile);
}
}
createSymlink(srcFile, dstFile);

View file

@ -1,5 +1,6 @@
#include "daemon.hh"
#include "monitor-fd.hh"
#include "signals.hh"
#include "worker-protocol.hh"
#include "worker-protocol-impl.hh"
#include "build-result.hh"
@ -254,7 +255,7 @@ struct ClientSettings
else if (setSubstituters(settings.substituters))
;
else
debug("ignoring the client-specified setting '%s', because it is a restricted setting and you are not a trusted user", name);
warn("ignoring the client-specified setting '%s', because it is a restricted setting and you are not a trusted user", name);
} catch (UsageError & e) {
warn(e.what());
}
@ -1038,7 +1039,7 @@ void processConnection(
unsigned int opCount = 0;
Finally finally([&]() {
_isInterrupted = false;
setInterrupted(false);
printMsgUsing(prevLogger, lvlDebug, "%d operations", opCount);
});

View file

@ -1239,16 +1239,14 @@ DerivationOutput DerivationOutput::fromJSON(
const ExperimentalFeatureSettings & xpSettings)
{
std::set<std::string_view> keys;
ensureType(_json, nlohmann::detail::value_t::object);
auto json = (std::map<std::string, nlohmann::json>) _json;
auto & json = getObject(_json);
for (const auto & [key, _] : json)
keys.insert(key);
auto methodAlgo = [&]() -> std::pair<ContentAddressMethod, HashAlgorithm> {
std::string hashAlgoStr = json["hashAlgo"];
// remaining to parse, will be mutated by parsers
std::string_view s = hashAlgoStr;
auto & str = getString(valueAt(json, "hashAlgo"));
std::string_view s = str;
ContentAddressMethod method = ContentAddressMethod::parsePrefix(s);
if (method == TextIngestionMethod {})
xpSettings.require(Xp::DynamicDerivations);
@ -1258,7 +1256,7 @@ DerivationOutput DerivationOutput::fromJSON(
if (keys == (std::set<std::string_view> { "path" })) {
return DerivationOutput::InputAddressed {
.path = store.parseStorePath((std::string) json["path"]),
.path = store.parseStorePath(getString(valueAt(json, "path"))),
};
}
@ -1267,10 +1265,10 @@ DerivationOutput DerivationOutput::fromJSON(
auto dof = DerivationOutput::CAFixed {
.ca = ContentAddress {
.method = std::move(method),
.hash = Hash::parseNonSRIUnprefixed((std::string) json["hash"], hashAlgo),
.hash = Hash::parseNonSRIUnprefixed(getString(valueAt(json, "hash")), hashAlgo),
},
};
if (dof.path(store, drvName, outputName) != store.parseStorePath((std::string) json["path"]))
if (dof.path(store, drvName, outputName) != store.parseStorePath(getString(valueAt(json, "path"))))
throw Error("Path doesn't match derivation output");
return dof;
}
@ -1357,20 +1355,19 @@ nlohmann::json Derivation::toJSON(const StoreDirConfig & store) const
Derivation Derivation::fromJSON(
const StoreDirConfig & store,
const nlohmann::json & json,
const nlohmann::json & _json,
const ExperimentalFeatureSettings & xpSettings)
{
using nlohmann::detail::value_t;
Derivation res;
ensureType(json, value_t::object);
auto & json = getObject(_json);
res.name = ensureType(valueAt(json, "name"), value_t::string);
res.name = getString(valueAt(json, "name"));
try {
auto & outputsObj = ensureType(valueAt(json, "outputs"), value_t::object);
for (auto & [outputName, output] : outputsObj.items()) {
for (auto & [outputName, output] : getObject(valueAt(json, "outputs"))) {
res.outputs.insert_or_assign(
outputName,
DerivationOutput::fromJSON(store, res.name, outputName, output));
@ -1381,8 +1378,7 @@ Derivation Derivation::fromJSON(
}
try {
auto & inputsList = ensureType(valueAt(json, "inputSrcs"), value_t::array);
for (auto & input : inputsList)
for (auto & input : getArray(valueAt(json, "inputSrcs")))
res.inputSrcs.insert(store.parseStorePath(static_cast<const std::string &>(input)));
} catch (Error & e) {
e.addTrace({}, "while reading key 'inputSrcs'");
@ -1391,18 +1387,17 @@ Derivation Derivation::fromJSON(
try {
std::function<DerivedPathMap<StringSet>::ChildNode(const nlohmann::json &)> doInput;
doInput = [&](const auto & json) {
doInput = [&](const auto & _json) {
auto & json = getObject(_json);
DerivedPathMap<StringSet>::ChildNode node;
node.value = static_cast<const StringSet &>(
ensureType(valueAt(json, "outputs"), value_t::array));
for (auto & [outputId, childNode] : ensureType(valueAt(json, "dynamicOutputs"), value_t::object).items()) {
node.value = getStringSet(valueAt(json, "outputs"));
for (auto & [outputId, childNode] : getObject(valueAt(json, "dynamicOutputs"))) {
xpSettings.require(Xp::DynamicDerivations);
node.childMap[outputId] = doInput(childNode);
}
return node;
};
auto & inputDrvsObj = ensureType(valueAt(json, "inputDrvs"), value_t::object);
for (auto & [inputDrvPath, inputOutputs] : inputDrvsObj.items())
for (auto & [inputDrvPath, inputOutputs] : getObject(valueAt(json, "inputDrvs")))
res.inputDrvs.map[store.parseStorePath(inputDrvPath)] =
doInput(inputOutputs);
} catch (Error & e) {
@ -1410,10 +1405,10 @@ Derivation Derivation::fromJSON(
throw;
}
res.platform = ensureType(valueAt(json, "system"), value_t::string);
res.builder = ensureType(valueAt(json, "builder"), value_t::string);
res.args = ensureType(valueAt(json, "args"), value_t::array);
res.env = ensureType(valueAt(json, "env"), value_t::object);
res.platform = getString(valueAt(json, "system"));
res.builder = getString(valueAt(json, "builder"));
res.args = getStringList(valueAt(json, "args"));
res.env = getStringMap(valueAt(json, "env"));
return res;
}

View file

@ -1,5 +1,4 @@
#include "filetransfer.hh"
#include "namespaces.hh"
#include "globals.hh"
#include "store-api.hh"
#include "s3.hh"
@ -12,6 +11,10 @@
#include <aws/core/client/ClientConfiguration.h>
#endif
#if __linux__
# include "namespaces.hh"
#endif
#include <unistd.h>
#include <fcntl.h>
@ -255,11 +258,11 @@ struct curlFileTransfer : public FileTransfer
int progressCallback(double dltotal, double dlnow)
{
try {
act.progress(dlnow, dltotal);
act.progress(dlnow, dltotal);
} catch (nix::Interrupted &) {
assert(_isInterrupted);
assert(getInterrupted());
}
return _isInterrupted;
return getInterrupted();
}
static int progressCallbackWrapper(void * userp, double dltotal, double dlnow, double ultotal, double ulnow)
@ -463,7 +466,7 @@ struct curlFileTransfer : public FileTransfer
if (errorSink)
response = std::move(errorSink->s);
auto exc =
code == CURLE_ABORTED_BY_CALLBACK && _isInterrupted
code == CURLE_ABORTED_BY_CALLBACK && getInterrupted()
? FileTransferError(Interrupted, std::move(response), "%s of '%s' was interrupted", request.verb(), request.uri)
: httpStatus != 0
? FileTransferError(err,
@ -568,7 +571,9 @@ struct curlFileTransfer : public FileTransfer
stopWorkerThread();
});
#if __linux__
unshareFilesystem();
#endif
std::map<CURL *, std::shared_ptr<TransferItem>> items;

View file

@ -2,7 +2,6 @@
#include "current-process.hh"
#include "archive.hh"
#include "args.hh"
#include "users.hh"
#include "abstract-setting-to-json.hh"
#include "compute-levels.hh"
@ -57,7 +56,7 @@ Settings::Settings()
, nixManDir(canonPath(NIX_MAN_DIR))
, nixDaemonSocketFile(canonPath(getEnvNonEmpty("NIX_DAEMON_SOCKET_PATH").value_or(nixStateDir + DEFAULT_SOCKET_PATH)))
{
buildUsersGroup = getuid() == 0 ? "nixbld" : "";
buildUsersGroup = isRootUser() ? "nixbld" : "";
allowSymlinkedStore = getEnv("NIX_IGNORE_SYMLINK_STORE") == "1";
auto sslOverride = getEnv("NIX_SSL_CERT_FILE").value_or(getEnv("SSL_CERT_FILE").value_or(""));
@ -346,6 +345,12 @@ void initPlugins()
dlopen(file.c_str(), RTLD_LAZY | RTLD_LOCAL);
if (!handle)
throw Error("could not dynamically open plugin file '%s': %s", file, dlerror());
/* Older plugins use a statically initialized object to run their code.
Newer plugins can also export nix_plugin_entry() */
void (*nix_plugin_entry)() = (void (*)())dlsym(handle, "nix_plugin_entry");
if (nix_plugin_entry)
nix_plugin_entry();
}
}
@ -404,6 +409,7 @@ void assertLibStoreInitialized() {
}
void initLibStore() {
if (initLibStoreDone) return;
initLibUtil();
@ -415,7 +421,7 @@ void initLibStore() {
sshd). This breaks build users because they don't have access
to the TMPDIR, in particular in nix-store --serve. */
#if __APPLE__
if (hasPrefix(getEnv("TMPDIR").value_or("/tmp"), "/var/folders/"))
if (hasPrefix(defaultTempDir(), "/var/folders/"))
unsetenv("TMPDIR");
#endif

View file

@ -5,6 +5,7 @@
#include "config.hh"
#include "environment-variables.hh"
#include "experimental-features.hh"
#include "users.hh"
#include <map>
#include <limits>
@ -665,7 +666,7 @@ public:
Setting<bool> sandboxFallback{this, true, "sandbox-fallback",
"Whether to disable sandboxing when the kernel doesn't allow it."};
Setting<bool> requireDropSupplementaryGroups{this, getuid() == 0, "require-drop-supplementary-groups",
Setting<bool> requireDropSupplementaryGroups{this, isRootUser(), "require-drop-supplementary-groups",
R"(
Following the principle of least privilege,
Nix will attempt to drop supplementary groups when building with sandboxing.
@ -687,16 +688,36 @@ public:
Setting<std::string> sandboxShmSize{
this, "50%", "sandbox-dev-shm-size",
R"(
This option determines the maximum size of the `tmpfs` filesystem
mounted on `/dev/shm` in Linux sandboxes. For the format, see the
description of the `size` option of `tmpfs` in mount(8). The default
is `50%`.
*Linux only*
This option determines the maximum size of the `tmpfs` filesystem
mounted on `/dev/shm` in Linux sandboxes. For the format, see the
description of the `size` option of `tmpfs` in mount(8). The default
is `50%`.
)"};
Setting<Path> sandboxBuildDir{this, "/build", "sandbox-build-dir",
"The build directory inside the sandbox."};
R"(
*Linux only*
The build directory inside the sandbox.
This directory is backed by [`build-dir`](#conf-build-dir) on the host.
)"};
#endif
Setting<std::optional<Path>> buildDir{this, std::nullopt, "build-dir",
R"(
The directory on the host, in which derivations' temporary build directories are created.
If not set, Nix will use the system temporary directory indicated by the `TMPDIR` environment variable.
Note that builds are often performed by the Nix daemon, so its `TMPDIR` is used, and not that of the Nix command line interface.
This is also the location where [`--keep-failed`](@docroot@/command-ref/opt-common.md#opt-keep-failed) leaves its files.
If Nix runs without sandbox, or if the platform does not support sandboxing with bind mounts (e.g. macOS), then the [`builder`](@docroot@/language/derivations.md#attr-builder)'s environment will contain this directory, instead of the virtual location [`sandbox-build-dir`](#conf-sandbox-build-dir).
)"};
Setting<PathSet> allowedImpureHostPrefixes{this, {}, "allowed-impure-host-deps",
"Which prefixes to allow derivations to ask for access to (primarily for Darwin)."};
@ -1136,9 +1157,10 @@ public:
this, {}, "plugin-files",
R"(
A list of plugin files to be loaded by Nix. Each of these files will
be dlopened by Nix, allowing them to affect execution through static
initialization. In particular, these plugins may construct static
instances of RegisterPrimOp to add new primops or constants to the
be dlopened by Nix. If they contain the symbol `nix_plugin_entry()`,
this symbol will be called. Alternatively, they can affect execution
through static initialization. In particular, these plugins may construct
static instances of RegisterPrimOp to add new primops or constants to the
expression language, RegisterStoreImplementation to add new store
implementations, RegisterCommand to add new subcommands to the `nix`
command, and RegisterSetting to add new nix config settings. See the

View file

@ -49,7 +49,7 @@ public:
, BinaryCacheStore(params)
, cacheUri(scheme + "://" + _cacheUri)
{
if (cacheUri.back() == '/')
while (!cacheUri.empty() && cacheUri.back() == '/')
cacheUri.pop_back();
diskCache = getNarInfoDiskCache();

View file

@ -16,6 +16,7 @@
#include "posix-fs-canonicalise.hh"
#include "posix-source-accessor.hh"
#include "keys.hh"
#include "users.hh"
#include <iostream>
#include <algorithm>
@ -223,7 +224,7 @@ LocalStore::LocalStore(const Params & params)
/* Optionally, create directories and set permissions for a
multi-user install. */
if (getuid() == 0 && settings.buildUsersGroup != "") {
if (isRootUser() && settings.buildUsersGroup != "") {
mode_t perm = 01775;
struct group * gr = getgrnam(settings.buildUsersGroup.get().c_str());
@ -558,6 +559,19 @@ void LocalStore::openDB(State & state, bool create)
sqlite3_exec(db, ("pragma main.journal_mode = " + mode + ";").c_str(), 0, 0, 0) != SQLITE_OK)
SQLiteError::throw_(db, "setting journal mode");
if (mode == "wal") {
/* persist the WAL files when the db connection is closed. This allows
for read-only connections without write permissions on the
containing directory to succeed on a closed db. Setting the
journal_size_limit to 2^40 bytes results in the WAL files getting
truncated to 0 on exit and limits the on disk size of the WAL files
to 2^40 bytes following a checkpoint */
if (sqlite3_exec(db, "pragma main.journal_size_limit = 1099511627776;", 0, 0, 0) == SQLITE_OK) {
int enable = 1;
sqlite3_file_control(db, NULL, SQLITE_FCNTL_PERSIST_WAL, &enable);
}
}
/* Increase the auto-checkpoint interval to 40000 pages. This
seems enough to ensure that instantiating the NixOS system
derivation is done in a single fsync(). */
@ -579,7 +593,7 @@ void LocalStore::openDB(State & state, bool create)
void LocalStore::makeStoreWritable()
{
#if __linux__
if (getuid() != 0) return;
if (!isRootUser()) return;
/* Check if /nix/store is on a read-only mount. */
struct statvfs stat;
if (statvfs(realStoreDir.get().c_str(), &stat) != 0)
@ -1588,7 +1602,7 @@ static void makeMutable(const Path & path)
/* Upgrade from schema 6 (Nix 0.15) to schema 7 (Nix >= 1.3). */
void LocalStore::upgradeStore7()
{
if (getuid() != 0) return;
if (!isRootUser()) return;
printInfo("removing immutable bits from the Nix store (this may take a while)...");
makeMutable(realStoreDir);
}

View file

@ -5,12 +5,15 @@ libstore_NAME = libnixstore
libstore_DIR := $(d)
libstore_SOURCES := $(wildcard $(d)/*.cc $(d)/builtins/*.cc $(d)/build/*.cc)
ifdef HOST_UNIX
libstore_SOURCES += $(wildcard $(d)/unix/*.cc)
endif
libstore_LIBS = libutil
libstore_LDFLAGS += $(SQLITE3_LIBS) $(LIBCURL_LIBS) $(THREAD_LDFLAGS)
ifdef HOST_LINUX
libstore_LDFLAGS += -ldl
libstore_LDFLAGS += -ldl
endif
$(foreach file,$(libstore_FILES),$(eval $(call install-data-in,$(d)/$(file),$(datadir)/nix/sandbox)))
@ -27,8 +30,15 @@ ifeq ($(HAVE_SECCOMP), 1)
libstore_LDFLAGS += $(LIBSECCOMP_LIBS)
endif
# Not just for this library itself, but also for downstream libraries using this library
INCLUDE_libstore := -I $(d) -I $(d)/build
ifdef HOST_UNIX
INCLUDE_libstore += -I $(d)/unix
endif
libstore_CXXFLAGS += \
-I src/libutil -I src/libstore -I src/libstore/build \
$(INCLUDE_libutil) $(INCLUDE_libstore) $(INCLUDE_libstore) \
-DNIX_PREFIX=\"$(prefix)\" \
-DNIX_STORE_DIR=\"$(storedir)\" \
-DNIX_DATA_DIR=\"$(datadir)\" \

View file

@ -2,6 +2,7 @@
#include "file-system.hh"
#include "globals.hh"
#include "pathlocks.hh"
#include "users.hh"
#include <pwd.h>
#include <grp.h>
@ -192,10 +193,10 @@ std::unique_ptr<UserLock> acquireUserLock(uid_t nrIds, bool useUserNamespace)
bool useBuildUsers()
{
#if __linux__
static bool b = (settings.buildUsersGroup != "" || settings.autoAllocateUids) && getuid() == 0;
static bool b = (settings.buildUsersGroup != "" || settings.autoAllocateUids) && isRootUser();
return b;
#elif __APPLE__
static bool b = settings.buildUsersGroup != "" && getuid() == 0;
static bool b = settings.buildUsersGroup != "" && isRootUser();
return b;
#else
return false;

View file

@ -172,19 +172,18 @@ NarInfo NarInfo::fromJSON(
};
if (json.contains("url"))
res.url = ensureType(valueAt(json, "url"), value_t::string);
res.url = getString(valueAt(json, "url"));
if (json.contains("compression"))
res.compression = ensureType(valueAt(json, "compression"), value_t::string);
res.compression = getString(valueAt(json, "compression"));
if (json.contains("downloadHash"))
res.fileHash = Hash::parseAny(
static_cast<const std::string &>(
ensureType(valueAt(json, "downloadHash"), value_t::string)),
getString(valueAt(json, "downloadHash")),
std::nullopt);
if (json.contains("downloadSize"))
res.fileSize = ensureType(valueAt(json, "downloadSize"), value_t::number_integer);
res.fileSize = getInteger(valueAt(json, "downloadSize"));
return res;
}

View file

@ -190,23 +190,18 @@ nlohmann::json UnkeyedValidPathInfo::toJSON(
UnkeyedValidPathInfo UnkeyedValidPathInfo::fromJSON(
const Store & store,
const nlohmann::json & json)
const nlohmann::json & _json)
{
using nlohmann::detail::value_t;
UnkeyedValidPathInfo res {
Hash(Hash::dummy),
};
ensureType(json, value_t::object);
res.narHash = Hash::parseAny(
static_cast<const std::string &>(
ensureType(valueAt(json, "narHash"), value_t::string)),
std::nullopt);
res.narSize = ensureType(valueAt(json, "narSize"), value_t::number_integer);
auto & json = getObject(_json);
res.narHash = Hash::parseAny(getString(valueAt(json, "narHash")), std::nullopt);
res.narSize = getInteger(valueAt(json, "narSize"));
try {
auto & references = ensureType(valueAt(json, "references"), value_t::array);
auto references = getStringList(valueAt(json, "references"));
for (auto & input : references)
res.references.insert(store.parseStorePath(static_cast<const std::string &>
(input)));
@ -216,20 +211,16 @@ UnkeyedValidPathInfo UnkeyedValidPathInfo::fromJSON(
}
if (json.contains("ca"))
res.ca = ContentAddress::parse(
static_cast<const std::string &>(
ensureType(valueAt(json, "ca"), value_t::string)));
res.ca = ContentAddress::parse(getString(valueAt(json, "ca")));
if (json.contains("deriver"))
res.deriver = store.parseStorePath(
static_cast<const std::string &>(
ensureType(valueAt(json, "deriver"), value_t::string)));
res.deriver = store.parseStorePath(getString(valueAt(json, "deriver")));
if (json.contains("registrationTime"))
res.registrationTime = ensureType(valueAt(json, "registrationTime"), value_t::number_integer);
res.registrationTime = getInteger(valueAt(json, "registrationTime"));
if (json.contains("ultimate"))
res.ultimate = ensureType(valueAt(json, "ultimate"), value_t::boolean);
res.ultimate = getBoolean(valueAt(json, "ultimate"));
if (json.contains("signatures"))
res.sigs = valueAt(json, "signatures");

View file

@ -308,7 +308,7 @@ std::string optimisticLockProfile(const Path & profile)
Path profilesDir()
{
auto profileRoot =
(getuid() == 0)
isRootUser()
? rootProfilesDir()
: createNixStateDir() + "/profiles";
createDirs(profileRoot);
@ -332,7 +332,7 @@ Path getDefaultProfile()
// Backwards compatibiliy measure: Make root's profile available as
// `.../default` as it's what NixOS and most of the init scripts expect
Path globalProfileLink = settings.nixStateDir + "/profiles/default";
if (getuid() == 0 && !pathExists(globalProfileLink)) {
if (isRootUser() && !pathExists(globalProfileLink)) {
replaceSymlink(profile, globalProfileLink);
}
return absPath(readLink(profileLink), dirOf(profileLink));

View file

@ -7,6 +7,7 @@
#include <sqlite3.h>
#include <atomic>
#include <thread>
namespace nix {
@ -256,10 +257,8 @@ void handleSQLiteBusy(const SQLiteBusy & e, time_t & nextWarning)
/* Sleep for a while since retrying the transaction right away
is likely to fail again. */
checkInterrupt();
struct timespec t;
t.tv_sec = 0;
t.tv_nsec = (random() % 100) * 1000 * 1000; /* <= 0.1s */
nanosleep(&t, 0);
/* <= 0.1s */
std::this_thread::sleep_for(std::chrono::milliseconds { rand() % 100 });
}
}

View file

@ -1307,7 +1307,7 @@ std::shared_ptr<Store> openFromNonUri(const std::string & uri, const Store::Para
#if __linux__
else if (!pathExists(stateDir)
&& params.empty()
&& getuid() != 0
&& !isRootUser()
&& !getEnv("NIX_STORE_DIR").has_value()
&& !getEnv("NIX_STATE_DIR").has_value())
{