mirror of
https://github.com/NixOS/nix.git
synced 2025-11-23 10:49:36 +01:00
Merge remote-tracking branch 'upstream/2.3-maintenance' into builder-host-key-stable
This commit is contained in:
commit
b4abe56a23
54 changed files with 776 additions and 402 deletions
|
|
@ -9,7 +9,7 @@ libexpr_SOURCES := $(wildcard $(d)/*.cc) $(wildcard $(d)/primops/*.cc) $(d)/lexe
|
|||
libexpr_LIBS = libutil libstore
|
||||
|
||||
libexpr_LDFLAGS =
|
||||
ifneq ($(OS), FreeBSD)
|
||||
ifdef HOST_LINUX
|
||||
libexpr_LDFLAGS += -ldl
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -105,7 +105,7 @@ void ExprAttrs::show(std::ostream & str) const
|
|||
str << "{ ";
|
||||
for (auto & i : attrs)
|
||||
if (i.second.inherited)
|
||||
str << "inherit " << i.first << " " << "; ";
|
||||
str << "inherit " << i.first << "; ";
|
||||
else
|
||||
str << i.first << " = " << *i.second.e << "; ";
|
||||
for (auto & i : dynamicAttrs)
|
||||
|
|
@ -211,7 +211,7 @@ string showAttrPath(const AttrPath & attrPath)
|
|||
if (i.symbol.set())
|
||||
out << i.symbol;
|
||||
else
|
||||
out << "\"${" << *i.expr << "}\"";
|
||||
out << "${" << *i.expr << "}";
|
||||
}
|
||||
return out.str();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -937,10 +937,16 @@ static void prim_hashFile(EvalState & state, const Pos & pos, Value * * args, Va
|
|||
if (ht == htUnknown)
|
||||
throw Error(format("unknown hash type '%1%', at %2%") % type % pos);
|
||||
|
||||
PathSet context; // discarded
|
||||
Path p = state.coerceToPath(pos, *args[1], context);
|
||||
PathSet context;
|
||||
Path path = state.coerceToPath(pos, *args[1], context);
|
||||
try {
|
||||
state.realiseContext(context);
|
||||
} catch (InvalidPathError & e) {
|
||||
throw EvalError(format("cannot read '%1%', since path '%2%' is not valid, at %3%")
|
||||
% path % e.path % pos);
|
||||
}
|
||||
|
||||
mkString(v, hashFile(ht, state.checkSourcePath(p)).to_string(Base16, false), context);
|
||||
mkString(v, hashFile(ht, state.checkSourcePath(state.toRealPath(path, context))).to_string(Base16, false));
|
||||
}
|
||||
|
||||
/* Read a directory (without . or ..) */
|
||||
|
|
@ -1350,6 +1356,10 @@ static void prim_catAttrs(EvalState & state, const Pos & pos, Value * * args, Va
|
|||
static void prim_functionArgs(EvalState & state, const Pos & pos, Value * * args, Value & v)
|
||||
{
|
||||
state.forceValue(*args[0]);
|
||||
if (args[0]->type == tPrimOpApp || args[0]->type == tPrimOp) {
|
||||
state.mkAttrs(v, 0);
|
||||
return;
|
||||
}
|
||||
if (args[0]->type != tLambda)
|
||||
throw TypeError(format("'functionArgs' requires a function, at %1%") % pos);
|
||||
|
||||
|
|
@ -1817,7 +1827,7 @@ static void prim_hashString(EvalState & state, const Pos & pos, Value * * args,
|
|||
PathSet context; // discarded
|
||||
string s = state.forceString(*args[1], context, pos);
|
||||
|
||||
mkString(v, hashString(ht, s).to_string(Base16, false), context);
|
||||
mkString(v, hashString(ht, s).to_string(Base16, false));
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -2075,7 +2085,7 @@ void fetch(EvalState & state, const Pos & pos, Value * * args, Value & v,
|
|||
else if (n == "name")
|
||||
request.name = state.forceStringNoCtx(*attr.value, *attr.pos);
|
||||
else
|
||||
throw EvalError(format("unsupported argument '%1%' to '%2%', at %3%") % attr.name % who % attr.pos);
|
||||
throw EvalError(format("unsupported argument '%1%' to '%2%', at %3%") % attr.name % who % *attr.pos);
|
||||
}
|
||||
|
||||
if (request.uri.empty())
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@
|
|||
#include "hash.hh"
|
||||
|
||||
#include <sys/time.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <regex>
|
||||
|
||||
|
|
@ -173,7 +174,7 @@ GitInfo exportGit(ref<Store> store, const std::string & uri,
|
|||
Path tmpDir = createTempDir();
|
||||
AutoDelete delTmpDir(tmpDir, true);
|
||||
|
||||
runProgram("tar", true, { "x", "-C", tmpDir }, tar);
|
||||
runProgram("tar", true, { "-x", "-f", "-", "-C", tmpDir }, tar);
|
||||
|
||||
gitInfo.storePath = store->addToStore(name, tmpDir);
|
||||
|
||||
|
|
|
|||
|
|
@ -14,6 +14,14 @@
|
|||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <signal.h>
|
||||
#ifdef __linux__
|
||||
#include <features.h>
|
||||
#endif
|
||||
#ifdef __GLIBC__
|
||||
#include <gnu/lib-names.h>
|
||||
#include <nss.h>
|
||||
#include <dlfcn.h>
|
||||
#endif
|
||||
|
||||
#include <openssl/crypto.h>
|
||||
|
||||
|
|
@ -95,6 +103,40 @@ static void opensslLockCallback(int mode, int type, const char * file, int line)
|
|||
}
|
||||
#endif
|
||||
|
||||
static std::once_flag dns_resolve_flag;
|
||||
|
||||
static void preloadNSS() {
|
||||
/* builtin:fetchurl can trigger a DNS lookup, which with glibc can trigger a dynamic library load of
|
||||
one of the glibc NSS libraries in a sandboxed child, which will fail unless the library's already
|
||||
been loaded in the parent. So we force a lookup of an invalid domain to force the NSS machinery to
|
||||
load its lookup libraries in the parent before any child gets a chance to. */
|
||||
std::call_once(dns_resolve_flag, []() {
|
||||
#ifdef __GLIBC__
|
||||
/* On linux, glibc will run every lookup through the nss layer.
|
||||
* That means every lookup goes, by default, through nscd, which acts as a local
|
||||
* cache.
|
||||
* Because we run builds in a sandbox, we also remove access to nscd otherwise
|
||||
* lookups would leak into the sandbox.
|
||||
*
|
||||
* But now we have a new problem, we need to make sure the nss_dns backend that
|
||||
* does the dns lookups when nscd is not available is loaded or available.
|
||||
*
|
||||
* We can't make it available without leaking nix's environment, so instead we'll
|
||||
* load the backend, and configure nss so it does not try to run dns lookups
|
||||
* through nscd.
|
||||
*
|
||||
* This is technically only used for builtins:fetch* functions so we only care
|
||||
* about dns.
|
||||
*
|
||||
* All other platforms are unaffected.
|
||||
*/
|
||||
if (dlopen (LIBNSS_DNS_SO, RTLD_NOW) == NULL) {
|
||||
printMsg(Verbosity::lvlWarn, fmt("Unable to load nss_dns backend"));
|
||||
}
|
||||
__nss_configure_lookup ("hosts", "dns");
|
||||
#endif
|
||||
});
|
||||
}
|
||||
|
||||
static void sigHandler(int signo) { }
|
||||
|
||||
|
|
@ -158,6 +200,8 @@ void initNix()
|
|||
if (hasPrefix(getEnv("TMPDIR"), "/var/folders/"))
|
||||
unsetenv("TMPDIR");
|
||||
#endif
|
||||
|
||||
preloadNSS();
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -34,7 +34,6 @@
|
|||
#include <sys/resource.h>
|
||||
#include <sys/socket.h>
|
||||
#include <fcntl.h>
|
||||
#include <netdb.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <cstring>
|
||||
|
|
@ -45,7 +44,6 @@
|
|||
|
||||
/* Includes required for chroot support. */
|
||||
#if __linux__
|
||||
#include <sys/socket.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <net/if.h>
|
||||
#include <netinet/ip.h>
|
||||
|
|
@ -181,6 +179,8 @@ public:
|
|||
|
||||
virtual string key() = 0;
|
||||
|
||||
virtual void cleanup() { }
|
||||
|
||||
protected:
|
||||
|
||||
virtual void amDone(ExitCode result);
|
||||
|
|
@ -426,6 +426,8 @@ void Goal::amDone(ExitCode result)
|
|||
}
|
||||
waiters.clear();
|
||||
worker.removeGoal(shared_from_this());
|
||||
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -1222,8 +1224,13 @@ void DerivationGoal::outputsSubstituted()
|
|||
|
||||
/* If the substitutes form an incomplete closure, then we should
|
||||
build the dependencies of this derivation, but after that, we
|
||||
can still use the substitutes for this derivation itself. */
|
||||
if (nrIncompleteClosure > 0) retrySubstitution = true;
|
||||
can still use the substitutes for this derivation itself.
|
||||
|
||||
If the nrIncompleteClosure != nrFailed, we have another issue as well.
|
||||
In particular, it may be the case that the hole in the closure is
|
||||
an output of the current derivation, which causes a loop if retried.
|
||||
*/
|
||||
if (nrIncompleteClosure > 0 && nrIncompleteClosure == nrFailed) retrySubstitution = true;
|
||||
|
||||
nrFailed = nrNoSubstituters = nrIncompleteClosure = 0;
|
||||
|
||||
|
|
@ -1881,22 +1888,6 @@ PathSet DerivationGoal::exportReferences(PathSet storePaths)
|
|||
return paths;
|
||||
}
|
||||
|
||||
static std::once_flag dns_resolve_flag;
|
||||
|
||||
static void preloadNSS() {
|
||||
/* builtin:fetchurl can trigger a DNS lookup, which with glibc can trigger a dynamic library load of
|
||||
one of the glibc NSS libraries in a sandboxed child, which will fail unless the library's already
|
||||
been loaded in the parent. So we force a lookup of an invalid domain to force the NSS machinery to
|
||||
load its lookup libraries in the parent before any child gets a chance to. */
|
||||
std::call_once(dns_resolve_flag, []() {
|
||||
struct addrinfo *res = NULL;
|
||||
|
||||
if (getaddrinfo("this.pre-initializes.the.dns.resolvers.invalid.", "http", NULL, &res) != 0) {
|
||||
if (res) freeaddrinfo(res);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void DerivationGoal::startBuilder()
|
||||
{
|
||||
/* Right platform? */
|
||||
|
|
@ -1908,9 +1899,6 @@ void DerivationGoal::startBuilder()
|
|||
settings.thisSystem,
|
||||
concatStringsSep(", ", settings.systemFeatures));
|
||||
|
||||
if (drv->isBuiltin())
|
||||
preloadNSS();
|
||||
|
||||
#if __APPLE__
|
||||
additionalSandboxProfile = parsedDrv->getStringAttr("__sandboxProfile").value_or("");
|
||||
#endif
|
||||
|
|
@ -2060,7 +2048,9 @@ void DerivationGoal::startBuilder()
|
|||
if (!found)
|
||||
throw Error(format("derivation '%1%' requested impure path '%2%', but it was not in allowed-impure-host-deps") % drvPath % i);
|
||||
|
||||
dirsInChroot[i] = i;
|
||||
/* Allow files in __impureHostDeps to be missing; e.g.
|
||||
macOS 11+ has no /usr/lib/libSystem*.dylib */
|
||||
dirsInChroot[i] = {i, true};
|
||||
}
|
||||
|
||||
#if __linux__
|
||||
|
|
@ -2834,8 +2824,6 @@ void DerivationGoal::runChild()
|
|||
|
||||
ss.push_back("/etc/services");
|
||||
ss.push_back("/etc/hosts");
|
||||
if (pathExists("/var/run/nscd/socket"))
|
||||
ss.push_back("/var/run/nscd/socket");
|
||||
}
|
||||
|
||||
for (auto & i : ss) dirsInChroot.emplace(i, i);
|
||||
|
|
@ -3911,6 +3899,8 @@ public:
|
|||
void handleChildOutput(int fd, const string & data) override;
|
||||
void handleEOF(int fd) override;
|
||||
|
||||
void cleanup() override;
|
||||
|
||||
Path getStorePath() { return storePath; }
|
||||
|
||||
void amDone(ExitCode result) override
|
||||
|
|
@ -3934,15 +3924,7 @@ SubstitutionGoal::SubstitutionGoal(const Path & storePath, Worker & worker, Repa
|
|||
|
||||
SubstitutionGoal::~SubstitutionGoal()
|
||||
{
|
||||
try {
|
||||
if (thr.joinable()) {
|
||||
// FIXME: signal worker thread to quit.
|
||||
thr.join();
|
||||
worker.childTerminated(this);
|
||||
}
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
cleanup();
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -3977,6 +3959,8 @@ void SubstitutionGoal::tryNext()
|
|||
{
|
||||
trace("trying next substituter");
|
||||
|
||||
cleanup();
|
||||
|
||||
if (subs.size() == 0) {
|
||||
/* None left. Terminate this goal and let someone else deal
|
||||
with it. */
|
||||
|
|
@ -4104,7 +4088,7 @@ void SubstitutionGoal::tryToRun()
|
|||
thr = std::thread([this]() {
|
||||
try {
|
||||
/* Wake up the worker loop when we're done. */
|
||||
Finally updateStats([this]() { outPipe.writeSide = -1; });
|
||||
Finally updateStats([this]() { outPipe.writeSide.close(); });
|
||||
|
||||
Activity act(*logger, actSubstitute, Logger::Fields{storePath, sub->getUri()});
|
||||
PushActivity pact(act.id);
|
||||
|
|
@ -4188,6 +4172,20 @@ void SubstitutionGoal::handleEOF(int fd)
|
|||
if (fd == outPipe.readSide.get()) worker.wakeUp(shared_from_this());
|
||||
}
|
||||
|
||||
void SubstitutionGoal::cleanup()
|
||||
{
|
||||
try {
|
||||
if (thr.joinable()) {
|
||||
// FIXME: signal worker thread to quit.
|
||||
thr.join();
|
||||
worker.childTerminated(this);
|
||||
}
|
||||
|
||||
outPipe.close();
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////
|
||||
|
||||
|
|
|
|||
|
|
@ -349,6 +349,13 @@ struct CurlDownloader : public Downloader
|
|||
(httpStatus == 200 || httpStatus == 201 || httpStatus == 204 || httpStatus == 206 || httpStatus == 304 || httpStatus == 226 /* FTP */ || httpStatus == 0 /* other protocol */))
|
||||
{
|
||||
result.cached = httpStatus == 304;
|
||||
|
||||
// In 2021, GitHub responds to If-None-Match with 304,
|
||||
// but omits ETag. We just use the If-None-Match etag
|
||||
// since 304 implies they are the same.
|
||||
if (httpStatus == 304 && result.etag == "")
|
||||
result.etag = request.expectedETag;
|
||||
|
||||
act.progress(result.bodySize, result.bodySize);
|
||||
done = true;
|
||||
callback(std::move(result));
|
||||
|
|
|
|||
|
|
@ -34,7 +34,7 @@ Settings::Settings()
|
|||
, nixLibexecDir(canonPath(getEnv("NIX_LIBEXEC_DIR", NIX_LIBEXEC_DIR)))
|
||||
, nixBinDir(canonPath(getEnv("NIX_BIN_DIR", NIX_BIN_DIR)))
|
||||
, nixManDir(canonPath(NIX_MAN_DIR))
|
||||
, nixDaemonSocketFile(canonPath(nixStateDir + DEFAULT_SOCKET_PATH))
|
||||
, nixDaemonSocketFile(canonPath(getEnv("NIX_DAEMON_SOCKET_PATH", nixStateDir + DEFAULT_SOCKET_PATH)))
|
||||
{
|
||||
buildUsersGroup = getuid() == 0 ? "nixbld" : "";
|
||||
lockCPU = getEnv("NIX_AFFINITY_HACK", "1") == "1";
|
||||
|
|
|
|||
|
|
@ -1029,6 +1029,40 @@ void LocalStore::addToStore(const ValidPathInfo & info, Source & source,
|
|||
throw Error("size mismatch importing path '%s';\n wanted: %s\n got: %s",
|
||||
info.path, info.narSize, hashResult.second);
|
||||
|
||||
if (!info.ca.empty()) {
|
||||
auto ca = info.ca;
|
||||
if (hasPrefix(ca, "fixed:")) {
|
||||
bool recursive = ca.compare(6, 2, "r:") == 0;
|
||||
Hash expectedHash(std::string(ca, recursive ? 8 : 6));
|
||||
if (info.references.empty()) {
|
||||
auto actualFoHash = hashCAPath(
|
||||
recursive,
|
||||
expectedHash.type,
|
||||
realPath
|
||||
);
|
||||
if (ca != actualFoHash) {
|
||||
throw Error("ca hash mismatch importing path '%s';\n specified: %s\n got: %s",
|
||||
info.path,
|
||||
ca,
|
||||
actualFoHash);
|
||||
}
|
||||
} else {
|
||||
throw Error("path '%s' claims to be content-addressed, but has references. This isn’t allowed",
|
||||
info.path);
|
||||
}
|
||||
|
||||
} else if (hasPrefix(ca, "text:")) {
|
||||
Hash textHash(std::string(ca, 5));
|
||||
auto actualTextHash = hashString(htSHA256, readFile(realPath));
|
||||
if (textHash != actualTextHash) {
|
||||
throw Error("ca hash mismatch importing path '%s';\n specified: %s\n got: %s",
|
||||
info.path,
|
||||
textHash.to_string(Base32, true),
|
||||
actualTextHash.to_string(Base32, true));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
autoGC();
|
||||
|
||||
canonicalisePathMetaData(realPath, -1);
|
||||
|
|
@ -1450,4 +1484,20 @@ void LocalStore::createUser(const std::string & userName, uid_t userId)
|
|||
}
|
||||
|
||||
|
||||
std::string LocalStore::hashCAPath(
|
||||
bool recursive,
|
||||
const HashType & hashType,
|
||||
const Path & path
|
||||
)
|
||||
{
|
||||
HashSink caSink(hashType);
|
||||
if (recursive) {
|
||||
dumpPath(path, caSink);
|
||||
} else {
|
||||
readFile(path, caSink);
|
||||
}
|
||||
auto hash = caSink.finish().first;
|
||||
return makeFixedOutputCA(recursive, hash);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -295,8 +295,14 @@ private:
|
|||
|
||||
void createUser(const std::string & userName, uid_t userId) override;
|
||||
|
||||
friend class DerivationGoal;
|
||||
friend class SubstitutionGoal;
|
||||
std::string hashCAPath(
|
||||
bool recursive,
|
||||
const HashType & hashType,
|
||||
const Path & path
|
||||
);
|
||||
|
||||
friend struct DerivationGoal;
|
||||
friend struct SubstitutionGoal;
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -9,7 +9,7 @@ libstore_SOURCES := $(wildcard $(d)/*.cc $(d)/builtins/*.cc)
|
|||
libstore_LIBS = libutil
|
||||
|
||||
libstore_LDFLAGS = $(SQLITE3_LIBS) -lbz2 $(LIBCURL_LIBS) $(SODIUM_LIBS) -pthread
|
||||
ifneq ($(OS), FreeBSD)
|
||||
ifdef HOST_LINUX
|
||||
libstore_LDFLAGS += -ldl
|
||||
endif
|
||||
|
||||
|
|
@ -21,7 +21,7 @@ ifeq ($(ENABLE_S3), 1)
|
|||
libstore_LDFLAGS += -laws-cpp-sdk-transfer -laws-cpp-sdk-s3 -laws-cpp-sdk-core
|
||||
endif
|
||||
|
||||
ifeq ($(OS), SunOS)
|
||||
ifdef HOST_SOLARIS
|
||||
libstore_LDFLAGS += -lsocket
|
||||
endif
|
||||
|
||||
|
|
|
|||
|
|
@ -56,6 +56,10 @@ class AwsLogger : public Aws::Utils::Logging::FormattedLogSystem
|
|||
{
|
||||
debug("AWS: %s", chomp(statement));
|
||||
}
|
||||
|
||||
#if !(AWS_VERSION_MAJOR <= 1 && AWS_VERSION_MINOR <= 7 && AWS_VERSION_PATCH <= 115)
|
||||
void Flush() override {}
|
||||
#endif
|
||||
};
|
||||
|
||||
static void initAWS()
|
||||
|
|
|
|||
|
|
@ -32,7 +32,9 @@
|
|||
(literal "/tmp") (subpath TMPDIR))
|
||||
|
||||
; Some packages like to read the system version.
|
||||
(allow file-read* (literal "/System/Library/CoreServices/SystemVersion.plist"))
|
||||
(allow file-read*
|
||||
(literal "/System/Library/CoreServices/SystemVersion.plist")
|
||||
(literal "/System/Library/CoreServices/SystemVersionCompat.plist"))
|
||||
|
||||
; Without this line clang cannot write to /dev/null, breaking some configure tests.
|
||||
(allow file-read-metadata (literal "/dev"))
|
||||
|
|
|
|||
|
|
@ -1,4 +1,5 @@
|
|||
#include "sqlite.hh"
|
||||
#include "globals.hh"
|
||||
#include "util.hh"
|
||||
|
||||
#include <sqlite3.h>
|
||||
|
|
@ -27,8 +28,12 @@ namespace nix {
|
|||
|
||||
SQLite::SQLite(const Path & path)
|
||||
{
|
||||
// useSQLiteWAL also indicates what virtual file system we need. Using
|
||||
// `unix-dotfile` is needed on NFS file systems and on Windows' Subsystem
|
||||
// for Linux (WSL) where useSQLiteWAL should be false by default.
|
||||
const char *vfs = settings.useSQLiteWAL ? 0 : "unix-dotfile";
|
||||
if (sqlite3_open_v2(path.c_str(), &db,
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, 0) != SQLITE_OK)
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE, vfs) != SQLITE_OK)
|
||||
throw Error(format("cannot open SQLite database '%s'") % path);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -5,8 +5,10 @@
|
|||
|
||||
#include <lzma.h>
|
||||
#include <bzlib.h>
|
||||
#include <zstd.h>
|
||||
#include <cstdio>
|
||||
#include <cstring>
|
||||
#include <vector>
|
||||
|
||||
#include <brotli/decode.h>
|
||||
#include <brotli/encode.h>
|
||||
|
|
@ -198,6 +200,78 @@ struct BrotliDecompressionSink : ChunkedCompressionSink
|
|||
}
|
||||
};
|
||||
|
||||
struct ZstdDecompressionSink : CompressionSink
|
||||
{
|
||||
Sink & nextSink;
|
||||
ZSTD_DStream *strm;
|
||||
|
||||
std::vector<uint8_t> inbuf;
|
||||
size_t outbuf_size = ZSTD_DStreamOutSize();
|
||||
uint8_t *outbuf = new uint8_t[outbuf_size];
|
||||
|
||||
ZstdDecompressionSink(Sink & nextSink) : nextSink(nextSink)
|
||||
{
|
||||
strm = ZSTD_createDStream();
|
||||
if (!strm)
|
||||
throw CompressionError("unable to initialise zstd decoder");
|
||||
|
||||
ZSTD_initDStream(strm);
|
||||
}
|
||||
|
||||
~ZstdDecompressionSink()
|
||||
{
|
||||
delete[] outbuf;
|
||||
ZSTD_freeDStream(strm);
|
||||
}
|
||||
|
||||
void finish() override
|
||||
{
|
||||
// this call doesn't make any sense, but it's here for consistency with the other compression sinks
|
||||
// CompressionSink inherits from BufferedSink, but none of the subclasses appear to ever make use of the buffer
|
||||
flush();
|
||||
|
||||
// if we still have undecoded data in the input buffer, we can't signal EOF to libzstd
|
||||
// if we don't, then we're done here anyway
|
||||
if (inbuf.size())
|
||||
throw CompressionError("received unexpected EOF while decompressing zstd file");
|
||||
|
||||
nextSink(nullptr, 0);
|
||||
}
|
||||
|
||||
void write(const unsigned char * data, size_t len) override
|
||||
{
|
||||
inbuf.insert(inbuf.end(), data, data + len);
|
||||
|
||||
ZSTD_inBuffer in = {
|
||||
.src = inbuf.data(),
|
||||
.size = inbuf.size(),
|
||||
.pos = 0
|
||||
};
|
||||
|
||||
ZSTD_outBuffer out = {
|
||||
.dst = outbuf,
|
||||
.size = outbuf_size,
|
||||
.pos = 0
|
||||
};
|
||||
|
||||
while (in.pos < in.size) {
|
||||
out.pos = 0;
|
||||
|
||||
size_t ret = ZSTD_decompressStream(strm, &out, &in);
|
||||
if (ZSTD_isError(ret))
|
||||
throw CompressionError("error %s while decompressing zstd file", ZSTD_getErrorName(ret));
|
||||
|
||||
if (out.pos)
|
||||
nextSink(outbuf, out.pos);
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
// drop consumed input
|
||||
inbuf.erase(inbuf.begin(), inbuf.begin() + in.pos);
|
||||
}
|
||||
};
|
||||
|
||||
ref<std::string> decompress(const std::string & method, const std::string & in)
|
||||
{
|
||||
StringSink ssink;
|
||||
|
|
@ -217,6 +291,8 @@ ref<CompressionSink> makeDecompressionSink(const std::string & method, Sink & ne
|
|||
return make_ref<BzipDecompressionSink>(nextSink);
|
||||
else if (method == "br")
|
||||
return make_ref<BrotliDecompressionSink>(nextSink);
|
||||
else if (method == "zstd")
|
||||
return make_ref<ZstdDecompressionSink>(nextSink);
|
||||
else
|
||||
throw UnknownCompressionMethod("unknown compression method '%s'", method);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
#include "json.hh"
|
||||
|
||||
#include <iomanip>
|
||||
#include <cstdint>
|
||||
#include <cstring>
|
||||
|
||||
namespace nix {
|
||||
|
|
|
|||
|
|
@ -6,4 +6,4 @@ libutil_DIR := $(d)
|
|||
|
||||
libutil_SOURCES := $(wildcard $(d)/*.cc)
|
||||
|
||||
libutil_LDFLAGS = $(LIBLZMA_LIBS) -lbz2 -pthread $(OPENSSL_LIBS) $(LIBBROTLI_LIBS) $(BOOST_LDFLAGS) -lboost_context
|
||||
libutil_LDFLAGS = $(LIBLZMA_LIBS) -lbz2 -pthread $(OPENSSL_LIBS) $(LIBBROTLI_LIBS) $(LIBZSTD_LIBS) $(BOOST_LDFLAGS) -lboost_context
|
||||
|
|
|
|||
|
|
@ -753,6 +753,7 @@ void AutoCloseFD::close()
|
|||
if (::close(fd) == -1)
|
||||
/* This should never happen. */
|
||||
throw SysError(format("closing file descriptor %1%") % fd);
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -770,6 +771,12 @@ int AutoCloseFD::release()
|
|||
return oldFD;
|
||||
}
|
||||
|
||||
void Pipe::close()
|
||||
{
|
||||
readSide.close();
|
||||
writeSide.close();
|
||||
}
|
||||
|
||||
|
||||
void Pipe::create()
|
||||
{
|
||||
|
|
@ -1080,7 +1087,7 @@ void runProgram2(const RunOptions & options)
|
|||
throw SysError("executing '%1%'", options.program);
|
||||
}, processOptions);
|
||||
|
||||
out.writeSide = -1;
|
||||
out.writeSide.close();
|
||||
|
||||
std::thread writerThread;
|
||||
|
||||
|
|
@ -1093,7 +1100,7 @@ void runProgram2(const RunOptions & options)
|
|||
|
||||
|
||||
if (source) {
|
||||
in.readSide = -1;
|
||||
in.readSide.close();
|
||||
writerThread = std::thread([&]() {
|
||||
try {
|
||||
std::vector<unsigned char> buf(8 * 1024);
|
||||
|
|
@ -1110,7 +1117,7 @@ void runProgram2(const RunOptions & options)
|
|||
} catch (...) {
|
||||
promise.set_exception(std::current_exception());
|
||||
}
|
||||
in.writeSide = -1;
|
||||
in.writeSide.close();
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -190,7 +190,6 @@ public:
|
|||
class AutoCloseFD
|
||||
{
|
||||
int fd;
|
||||
void close();
|
||||
public:
|
||||
AutoCloseFD();
|
||||
AutoCloseFD(int fd);
|
||||
|
|
@ -202,6 +201,7 @@ public:
|
|||
int get() const;
|
||||
explicit operator bool() const;
|
||||
int release();
|
||||
void close();
|
||||
};
|
||||
|
||||
|
||||
|
|
@ -210,6 +210,7 @@ class Pipe
|
|||
public:
|
||||
AutoCloseFD readSide, writeSide;
|
||||
void create();
|
||||
void close();
|
||||
};
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -106,7 +106,7 @@ static void _main(int argc, char * * argv)
|
|||
// Heuristic to see if we're invoked as a shebang script, namely,
|
||||
// if we have at least one argument, it's the name of an
|
||||
// executable file, and it starts with "#!".
|
||||
if (runEnv && argc > 1 && !std::regex_search(argv[1], std::regex("nix-shell"))) {
|
||||
if (runEnv && argc > 1) {
|
||||
script = argv[1];
|
||||
try {
|
||||
auto lines = tokenizeString<Strings>(readFile(script), "\n");
|
||||
|
|
@ -425,6 +425,7 @@ static void _main(int argc, char * * argv)
|
|||
"unset NIX_ENFORCE_PURITY; "
|
||||
"shopt -u nullglob; "
|
||||
"unset TZ; %6%"
|
||||
"shopt -s execfail;"
|
||||
"%7%",
|
||||
(Path) tmpDir,
|
||||
(pure ? "" : "p=$PATH; "),
|
||||
|
|
|
|||
|
|
@ -901,7 +901,11 @@ static PeerInfo getPeerInfo(int remote)
|
|||
|
||||
#if defined(SO_PEERCRED)
|
||||
|
||||
#if defined(__OpenBSD__)
|
||||
struct sockpeercred cred;
|
||||
#else
|
||||
ucred cred;
|
||||
#endif
|
||||
socklen_t credLen = sizeof(cred);
|
||||
if (getsockopt(remote, SOL_SOCKET, SO_PEERCRED, &cred, &credLen) == -1)
|
||||
throw SysError("getting peer credentials");
|
||||
|
|
|
|||
|
|
@ -50,10 +50,12 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
|||
output paths, and optionally the derivation path, as well
|
||||
as the meta attributes. */
|
||||
Path drvPath = keepDerivations ? i.queryDrvPath() : "";
|
||||
DrvInfo::Outputs outputs = i.queryOutputs(true);
|
||||
StringSet metaNames = i.queryMetaNames();
|
||||
|
||||
Value & v(*state.allocValue());
|
||||
manifest.listElems()[n++] = &v;
|
||||
state.mkAttrs(v, 16);
|
||||
state.mkAttrs(v, 7 + outputs.size());
|
||||
|
||||
mkString(*state.allocAttr(v, state.sType), "derivation");
|
||||
mkString(*state.allocAttr(v, state.sName), i.queryName());
|
||||
|
|
@ -65,7 +67,6 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
|||
mkString(*state.allocAttr(v, state.sDrvPath), i.queryDrvPath());
|
||||
|
||||
// Copy each output meant for installation.
|
||||
DrvInfo::Outputs outputs = i.queryOutputs(true);
|
||||
Value & vOutputs = *state.allocAttr(v, state.sOutputs);
|
||||
state.mkList(vOutputs, outputs.size());
|
||||
unsigned int m = 0;
|
||||
|
|
@ -85,8 +86,7 @@ bool createUserEnv(EvalState & state, DrvInfos & elems,
|
|||
|
||||
// Copy the meta attributes.
|
||||
Value & vMeta = *state.allocAttr(v, state.sMeta);
|
||||
state.mkAttrs(vMeta, 16);
|
||||
StringSet metaNames = i.queryMetaNames();
|
||||
state.mkAttrs(vMeta, metaNames.size());
|
||||
for (auto & j : metaNames) {
|
||||
Value * v = i.queryMeta(j);
|
||||
if (!v) continue;
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
ifeq ($(OS), Darwin)
|
||||
ifdef HOST_DARWIN
|
||||
programs += resolve-system-dependencies
|
||||
endif
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue