style(3p/nix): Final act in the brace-wrapping saga
This last change set was generated by a full clang-tidy run (including
compilation):
clang-tidy -p ~/projects/nix-build/ \
-checks=-*,readability-braces-around-statements -fix src/*/*.cc
Actually running clang-tidy requires some massaging to make it play
nice with Nix + meson, I'll be adding a wrapper or something for that soon.
This commit is contained in:
parent
cf40d08908
commit
3908732181
84 changed files with 2601 additions and 1554 deletions
|
|
@ -19,9 +19,10 @@
|
|||
namespace nix {
|
||||
|
||||
BinaryCacheStore::BinaryCacheStore(const Params& params) : Store(params) {
|
||||
if (secretKeyFile != "")
|
||||
if (secretKeyFile != "") {
|
||||
secretKey =
|
||||
std::unique_ptr<SecretKey>(new SecretKey(readFile(secretKeyFile)));
|
||||
}
|
||||
|
||||
StringSink sink;
|
||||
sink << narVersionMagic1;
|
||||
|
|
@ -44,10 +45,11 @@ void BinaryCacheStore::init() {
|
|||
auto name = line.substr(0, colon);
|
||||
auto value = trim(line.substr(colon + 1, std::string::npos));
|
||||
if (name == "StoreDir") {
|
||||
if (value != storeDir)
|
||||
if (value != storeDir) {
|
||||
throw Error(format("binary cache '%s' is for Nix stores with prefix "
|
||||
"'%s', not '%s'") %
|
||||
getUri() % value % storeDir);
|
||||
}
|
||||
} else if (name == "WantMassQuery") {
|
||||
wantMassQuery_ = value == "1";
|
||||
} else if (name == "Priority") {
|
||||
|
|
@ -108,9 +110,10 @@ void BinaryCacheStore::writeNarInfo(ref<NarInfo> narInfo) {
|
|||
state_->pathInfoCache.upsert(hashPart, std::shared_ptr<NarInfo>(narInfo));
|
||||
}
|
||||
|
||||
if (diskCache)
|
||||
if (diskCache) {
|
||||
diskCache->upsertNarInfo(getUri(), hashPart,
|
||||
std::shared_ptr<NarInfo>(narInfo));
|
||||
}
|
||||
}
|
||||
|
||||
void BinaryCacheStore::addToStore(const ValidPathInfo& info,
|
||||
|
|
@ -123,7 +126,8 @@ void BinaryCacheStore::addToStore(const ValidPathInfo& info,
|
|||
|
||||
/* Verify that all references are valid. This may do some .narinfo
|
||||
reads, but typically they'll already be cached. */
|
||||
for (auto& ref : info.references) try {
|
||||
for (auto& ref : info.references) {
|
||||
try {
|
||||
if (ref != info.path) {
|
||||
queryPathInfo(ref);
|
||||
}
|
||||
|
|
@ -132,6 +136,7 @@ void BinaryCacheStore::addToStore(const ValidPathInfo& info,
|
|||
"reference '%s' is not valid") %
|
||||
info.path % ref);
|
||||
}
|
||||
}
|
||||
|
||||
assert(nar->compare(0, narMagic.size(), narMagic) == 0);
|
||||
|
||||
|
|
@ -140,10 +145,11 @@ void BinaryCacheStore::addToStore(const ValidPathInfo& info,
|
|||
narInfo->narSize = nar->size();
|
||||
narInfo->narHash = hashString(htSHA256, *nar);
|
||||
|
||||
if (info.narHash && info.narHash != narInfo->narHash)
|
||||
if (info.narHash && info.narHash != narInfo->narHash) {
|
||||
throw Error(
|
||||
format("refusing to copy corrupted path '%1%' to binary cache") %
|
||||
info.path);
|
||||
}
|
||||
|
||||
auto accessor_ = std::dynamic_pointer_cast<RemoteFSAccessor>(accessor);
|
||||
|
||||
|
|
@ -203,8 +209,9 @@ void BinaryCacheStore::addToStore(const ValidPathInfo& info,
|
|||
if (repair || !fileExists(narInfo->url)) {
|
||||
stats.narWrite++;
|
||||
upsertFile(narInfo->url, *narCompressed, "application/x-nix-nar");
|
||||
} else
|
||||
} else {
|
||||
stats.narWriteAverted++;
|
||||
}
|
||||
|
||||
stats.narWriteBytes += nar->size();
|
||||
stats.narWriteCompressedBytes += narCompressed->size();
|
||||
|
|
@ -349,9 +356,9 @@ void BinaryCacheStore::addSignatures(const Path& storePath,
|
|||
std::shared_ptr<std::string> BinaryCacheStore::getBuildLog(const Path& path) {
|
||||
Path drvPath;
|
||||
|
||||
if (isDerivation(path))
|
||||
if (isDerivation(path)) {
|
||||
drvPath = path;
|
||||
else {
|
||||
} else {
|
||||
try {
|
||||
auto info = queryPathInfo(path);
|
||||
// FIXME: add a "Log" field to .narinfo
|
||||
|
|
|
|||
576
third_party/nix/src/libstore/build.cc
vendored
576
third_party/nix/src/libstore/build.cc
vendored
File diff suppressed because it is too large
Load diff
6
third_party/nix/src/libstore/crypto.cc
vendored
6
third_party/nix/src/libstore/crypto.cc
vendored
|
|
@ -32,8 +32,9 @@ Key::Key(const string& s) {
|
|||
|
||||
SecretKey::SecretKey(const string& s) : Key(s) {
|
||||
#if HAVE_SODIUM
|
||||
if (key.size() != crypto_sign_SECRETKEYBYTES)
|
||||
if (key.size() != crypto_sign_SECRETKEYBYTES) {
|
||||
throw Error("secret key is not valid");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
@ -69,8 +70,9 @@ PublicKey SecretKey::toPublicKey() const {
|
|||
|
||||
PublicKey::PublicKey(const string& s) : Key(s) {
|
||||
#if HAVE_SODIUM
|
||||
if (key.size() != crypto_sign_PUBLICKEYBYTES)
|
||||
if (key.size() != crypto_sign_PUBLICKEYBYTES) {
|
||||
throw Error("public key is not valid");
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
|
|
|
|||
34
third_party/nix/src/libstore/derivations.cc
vendored
34
third_party/nix/src/libstore/derivations.cc
vendored
|
|
@ -19,16 +19,18 @@ void DerivationOutput::parseHashInfo(bool& recursive, Hash& hash) const {
|
|||
}
|
||||
|
||||
HashType hashType = parseHashType(algo);
|
||||
if (hashType == htUnknown)
|
||||
if (hashType == htUnknown) {
|
||||
throw Error(format("unknown hash algorithm '%1%'") % algo);
|
||||
}
|
||||
|
||||
hash = Hash(this->hash, hashType);
|
||||
}
|
||||
|
||||
Path BasicDerivation::findOutput(const string& id) const {
|
||||
auto i = outputs.find(id);
|
||||
if (i == outputs.end())
|
||||
if (i == outputs.end()) {
|
||||
throw Error(format("derivation has no output '%1%'") % id);
|
||||
}
|
||||
return i->second.path;
|
||||
}
|
||||
|
||||
|
|
@ -57,8 +59,9 @@ Path writeDerivation(ref<Store> store, const Derivation& drv,
|
|||
static void expect(std::istream& str, const string& s) {
|
||||
char s2[s.size()];
|
||||
str.read(s2, s.size());
|
||||
if (string(s2, s.size()) != s)
|
||||
if (string(s2, s.size()) != s) {
|
||||
throw FormatError(format("expected string '%1%'") % s);
|
||||
}
|
||||
}
|
||||
|
||||
/* Read a C-style string from stream `str'. */
|
||||
|
|
@ -66,26 +69,30 @@ static string parseString(std::istream& str) {
|
|||
string res;
|
||||
expect(str, "\"");
|
||||
int c;
|
||||
while ((c = str.get()) != '"')
|
||||
while ((c = str.get()) != '"') {
|
||||
if (c == '\\') {
|
||||
c = str.get();
|
||||
if (c == 'n')
|
||||
if (c == 'n') {
|
||||
res += '\n';
|
||||
else if (c == 'r')
|
||||
} else if (c == 'r') {
|
||||
res += '\r';
|
||||
else if (c == 't')
|
||||
} else if (c == 't') {
|
||||
res += '\t';
|
||||
else
|
||||
} else {
|
||||
res += c;
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
res += c;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
static Path parsePath(std::istream& str) {
|
||||
string s = parseString(str);
|
||||
if (s.size() == 0 || s[0] != '/')
|
||||
if (s.size() == 0 || s[0] != '/') {
|
||||
throw FormatError(format("bad path '%1%' in derivation") % s);
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
|
@ -103,8 +110,9 @@ static bool endOfList(std::istream& str) {
|
|||
|
||||
static StringSet parseStrings(std::istream& str, bool arePaths) {
|
||||
StringSet res;
|
||||
while (!endOfList(str))
|
||||
while (!endOfList(str)) {
|
||||
res.insert(arePaths ? parsePath(str) : parseString(str));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -147,7 +155,9 @@ static Derivation parseDerivation(const string& s) {
|
|||
|
||||
/* Parse the builder arguments. */
|
||||
expect(str, ",[");
|
||||
while (!endOfList(str)) drv.args.push_back(parseString(str));
|
||||
while (!endOfList(str)) {
|
||||
drv.args.push_back(parseString(str));
|
||||
}
|
||||
|
||||
/* Parse the environment variables. */
|
||||
expect(str, ",[");
|
||||
|
|
|
|||
75
third_party/nix/src/libstore/download.cc
vendored
75
third_party/nix/src/libstore/download.cc
vendored
|
|
@ -36,11 +36,12 @@ DownloadSettings downloadSettings;
|
|||
static GlobalConfig::Register r1(&downloadSettings);
|
||||
|
||||
std::string resolveUri(const std::string& uri) {
|
||||
if (uri.compare(0, 8, "channel:") == 0)
|
||||
if (uri.compare(0, 8, "channel:") == 0) {
|
||||
return "https://nixos.org/channels/" + std::string(uri, 8) +
|
||||
"/nixexprs.tar.xz";
|
||||
else
|
||||
} else {
|
||||
return uri;
|
||||
}
|
||||
}
|
||||
|
||||
struct CurlDownloader : public Downloader {
|
||||
|
|
@ -92,18 +93,21 @@ struct CurlDownloader : public Downloader {
|
|||
writtenToSink += len;
|
||||
this->request.dataCallback((char*)data, len);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
this->result.data->append((char*)data, len);
|
||||
}
|
||||
}) {
|
||||
LOG(INFO) << (request.data ? "uploading '" : "downloading '")
|
||||
<< request.uri << "'";
|
||||
|
||||
if (!request.expectedETag.empty())
|
||||
if (!request.expectedETag.empty()) {
|
||||
requestHeaders = curl_slist_append(
|
||||
requestHeaders, ("If-None-Match: " + request.expectedETag).c_str());
|
||||
if (!request.mimeType.empty())
|
||||
}
|
||||
if (!request.mimeType.empty()) {
|
||||
requestHeaders = curl_slist_append(
|
||||
requestHeaders, ("Content-Type: " + request.mimeType).c_str());
|
||||
}
|
||||
}
|
||||
|
||||
~DownloadItem() {
|
||||
|
|
@ -117,10 +121,11 @@ struct CurlDownloader : public Downloader {
|
|||
curl_slist_free_all(requestHeaders);
|
||||
}
|
||||
try {
|
||||
if (!done)
|
||||
if (!done) {
|
||||
fail(DownloadError(
|
||||
Interrupted,
|
||||
format("download of '%s' was interrupted") % request.uri));
|
||||
}
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
|
|
@ -147,8 +152,9 @@ struct CurlDownloader : public Downloader {
|
|||
size_t realSize = size * nmemb;
|
||||
result.bodySize += realSize;
|
||||
|
||||
if (!decompressionSink)
|
||||
if (!decompressionSink) {
|
||||
decompressionSink = makeDecompressionSink(encoding, finalSink);
|
||||
}
|
||||
|
||||
(*decompressionSink)((unsigned char*)contents, realSize);
|
||||
|
||||
|
|
@ -192,11 +198,12 @@ struct CurlDownloader : public Downloader {
|
|||
<< "shutting down on 200 HTTP response with expected ETag";
|
||||
return 0;
|
||||
}
|
||||
} else if (name == "content-encoding")
|
||||
} else if (name == "content-encoding") {
|
||||
encoding = trim(string(line, i + 1));
|
||||
else if (name == "accept-ranges" &&
|
||||
toLower(trim(std::string(line, i + 1))) == "bytes")
|
||||
} else if (name == "accept-ranges" &&
|
||||
toLower(trim(std::string(line, i + 1))) == "bytes") {
|
||||
acceptRanges = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return realSize;
|
||||
|
|
@ -275,10 +282,11 @@ struct CurlDownloader : public Downloader {
|
|||
curl_easy_setopt(req, CURLOPT_PIPEWAIT, 1);
|
||||
#endif
|
||||
#if LIBCURL_VERSION_NUM >= 0x072f00
|
||||
if (downloadSettings.enableHttp2)
|
||||
if (downloadSettings.enableHttp2) {
|
||||
curl_easy_setopt(req, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_2TLS);
|
||||
else
|
||||
} else {
|
||||
curl_easy_setopt(req, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
|
||||
}
|
||||
#endif
|
||||
curl_easy_setopt(req, CURLOPT_WRITEFUNCTION,
|
||||
DownloadItem::writeCallbackWrapper);
|
||||
|
|
@ -306,8 +314,9 @@ struct CurlDownloader : public Downloader {
|
|||
}
|
||||
|
||||
if (request.verifyTLS) {
|
||||
if (settings.caFile != "")
|
||||
if (settings.caFile != "") {
|
||||
curl_easy_setopt(req, CURLOPT_CAINFO, settings.caFile.c_str());
|
||||
}
|
||||
} else {
|
||||
curl_easy_setopt(req, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
curl_easy_setopt(req, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
|
|
@ -362,14 +371,14 @@ struct CurlDownloader : public Downloader {
|
|||
httpStatus = 304;
|
||||
}
|
||||
|
||||
if (writeException)
|
||||
if (writeException) {
|
||||
failEx(writeException);
|
||||
|
||||
else if (code == CURLE_OK &&
|
||||
(httpStatus == 200 || httpStatus == 201 || httpStatus == 204 ||
|
||||
httpStatus == 206 || httpStatus == 304 ||
|
||||
httpStatus == 226 /* FTP */ ||
|
||||
httpStatus == 0 /* other protocol */)) {
|
||||
} else if (code == CURLE_OK &&
|
||||
(httpStatus == 200 || httpStatus == 201 || httpStatus == 204 ||
|
||||
httpStatus == 206 || httpStatus == 304 ||
|
||||
httpStatus == 226 /* FTP */ ||
|
||||
httpStatus == 0 /* other protocol */)) {
|
||||
result.cached = httpStatus == 304;
|
||||
done = true;
|
||||
callback(std::move(result));
|
||||
|
|
@ -464,8 +473,9 @@ struct CurlDownloader : public Downloader {
|
|||
embargo =
|
||||
std::chrono::steady_clock::now() + std::chrono::milliseconds(ms);
|
||||
downloader.enqueueItem(shared_from_this());
|
||||
} else
|
||||
} else {
|
||||
fail(exc);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
|
@ -548,10 +558,11 @@ struct CurlDownloader : public Downloader {
|
|||
/* Let curl do its thing. */
|
||||
int running;
|
||||
CURLMcode mc = curl_multi_perform(curlm, &running);
|
||||
if (mc != CURLM_OK)
|
||||
if (mc != CURLM_OK) {
|
||||
throw nix::Error(
|
||||
format("unexpected error from curl_multi_perform(): %s") %
|
||||
curl_multi_strerror(mc));
|
||||
}
|
||||
|
||||
/* Set the promises of any finished requests. */
|
||||
CURLMsg* msg;
|
||||
|
|
@ -584,9 +595,10 @@ struct CurlDownloader : public Downloader {
|
|||
: maxSleepTimeMs;
|
||||
DLOG(INFO) << "download thread waiting for " << sleepTimeMs << " ms";
|
||||
mc = curl_multi_wait(curlm, extraFDs, 1, sleepTimeMs, &numfds);
|
||||
if (mc != CURLM_OK)
|
||||
if (mc != CURLM_OK) {
|
||||
throw nix::Error(format("unexpected error from curl_multi_wait(): %s") %
|
||||
curl_multi_strerror(mc));
|
||||
}
|
||||
|
||||
nextWakeup = std::chrono::steady_clock::time_point();
|
||||
|
||||
|
|
@ -596,8 +608,9 @@ struct CurlDownloader : public Downloader {
|
|||
if (extraFDs[0].revents & CURL_WAIT_POLLIN) {
|
||||
char buf[1024];
|
||||
auto res = read(extraFDs[0].fd, buf, sizeof(buf));
|
||||
if (res == -1 && errno != EINTR)
|
||||
if (res == -1 && errno != EINTR) {
|
||||
throw SysError("reading curl wakeup socket");
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::shared_ptr<DownloadItem>> incoming;
|
||||
|
|
@ -612,8 +625,9 @@ struct CurlDownloader : public Downloader {
|
|||
state->incoming.pop();
|
||||
} else {
|
||||
if (nextWakeup == std::chrono::steady_clock::time_point() ||
|
||||
item->embargo < nextWakeup)
|
||||
item->embargo < nextWakeup) {
|
||||
nextWakeup = item->embargo;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
@ -643,22 +657,26 @@ struct CurlDownloader : public Downloader {
|
|||
|
||||
{
|
||||
auto state(state_.lock());
|
||||
while (!state->incoming.empty()) state->incoming.pop();
|
||||
while (!state->incoming.empty()) {
|
||||
state->incoming.pop();
|
||||
}
|
||||
state->quit = true;
|
||||
}
|
||||
}
|
||||
|
||||
void enqueueItem(std::shared_ptr<DownloadItem> item) {
|
||||
if (item->request.data && !hasPrefix(item->request.uri, "http://") &&
|
||||
!hasPrefix(item->request.uri, "https://"))
|
||||
!hasPrefix(item->request.uri, "https://")) {
|
||||
throw nix::Error("uploading to '%s' is not supported", item->request.uri);
|
||||
}
|
||||
|
||||
{
|
||||
auto state(state_.lock());
|
||||
if (state->quit)
|
||||
if (state->quit) {
|
||||
throw nix::Error(
|
||||
"cannot enqueue download request because the download thread is "
|
||||
"shutting down");
|
||||
}
|
||||
state->incoming.push(item);
|
||||
}
|
||||
writeFull(wakeupPipe.writeSide.get(), " ");
|
||||
|
|
@ -900,8 +918,9 @@ CachedDownloadResult Downloader::downloadCached(
|
|||
expectedETag = ss[1];
|
||||
}
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
storePath = "";
|
||||
}
|
||||
}
|
||||
|
||||
if (!skip) {
|
||||
|
|
|
|||
|
|
@ -46,9 +46,10 @@ void Store::exportPath(const Path& path, Sink& sink) {
|
|||
filesystem corruption from spreading to other machines.
|
||||
Don't complain if the stored hash is zero (unknown). */
|
||||
Hash hash = hashAndWriteSink.currentHash();
|
||||
if (hash != info->narHash && info->narHash != Hash(info->narHash.type))
|
||||
if (hash != info->narHash && info->narHash != Hash(info->narHash.type)) {
|
||||
throw Error(format("hash of path '%1%' has changed from '%2%' to '%3%'!") %
|
||||
path % info->narHash.to_string() % hash.to_string());
|
||||
}
|
||||
|
||||
hashAndWriteSink << exportMagic << path << info->references << info->deriver
|
||||
<< 0;
|
||||
|
|
@ -62,17 +63,19 @@ Paths Store::importPaths(Source& source, std::shared_ptr<FSAccessor> accessor,
|
|||
if (n == 0) {
|
||||
break;
|
||||
}
|
||||
if (n != 1)
|
||||
if (n != 1) {
|
||||
throw Error(
|
||||
"input doesn't look like something created by 'nix-store --export'");
|
||||
}
|
||||
|
||||
/* Extract the NAR from the source. */
|
||||
TeeSink tee(source);
|
||||
parseDump(tee, tee.source);
|
||||
|
||||
uint32_t magic = readInt(source);
|
||||
if (magic != exportMagic)
|
||||
if (magic != exportMagic) {
|
||||
throw Error("Nix archive cannot be imported; wrong format");
|
||||
}
|
||||
|
||||
ValidPathInfo info;
|
||||
|
||||
|
|
|
|||
95
third_party/nix/src/libstore/gc.cc
vendored
95
third_party/nix/src/libstore/gc.cc
vendored
|
|
@ -61,8 +61,9 @@ static void makeSymlink(const Path& link, const Path& target) {
|
|||
createSymlink(target, tempLink);
|
||||
|
||||
/* Atomically replace the old one. */
|
||||
if (rename(tempLink.c_str(), link.c_str()) == -1)
|
||||
if (rename(tempLink.c_str(), link.c_str()) == -1) {
|
||||
throw SysError(format("cannot rename '%1%' to '%2%'") % tempLink % link);
|
||||
}
|
||||
}
|
||||
|
||||
void LocalStore::syncWithGC() { AutoCloseFD fdGCLock = openGCLock(ltRead); }
|
||||
|
|
@ -80,18 +81,21 @@ Path LocalFSStore::addPermRoot(const Path& _storePath, const Path& _gcRoot,
|
|||
Path gcRoot(canonPath(_gcRoot));
|
||||
assertStorePath(storePath);
|
||||
|
||||
if (isInStore(gcRoot))
|
||||
if (isInStore(gcRoot)) {
|
||||
throw Error(format("creating a garbage collector root (%1%) in the Nix "
|
||||
"store is forbidden "
|
||||
"(are you running nix-build inside the store?)") %
|
||||
gcRoot);
|
||||
}
|
||||
|
||||
if (indirect) {
|
||||
/* Don't clobber the link if it already exists and doesn't
|
||||
point to the Nix store. */
|
||||
if (pathExists(gcRoot) && (!isLink(gcRoot) || !isInStore(readLink(gcRoot))))
|
||||
if (pathExists(gcRoot) &&
|
||||
(!isLink(gcRoot) || !isInStore(readLink(gcRoot)))) {
|
||||
throw Error(format("cannot create symlink '%1%'; already exists") %
|
||||
gcRoot);
|
||||
}
|
||||
makeSymlink(gcRoot, storePath);
|
||||
addIndirectRoot(gcRoot);
|
||||
}
|
||||
|
|
@ -101,16 +105,18 @@ Path LocalFSStore::addPermRoot(const Path& _storePath, const Path& _gcRoot,
|
|||
Path rootsDir =
|
||||
canonPath((format("%1%/%2%") % stateDir % gcRootsDir).str());
|
||||
|
||||
if (string(gcRoot, 0, rootsDir.size() + 1) != rootsDir + "/")
|
||||
if (string(gcRoot, 0, rootsDir.size() + 1) != rootsDir + "/") {
|
||||
throw Error(format("path '%1%' is not a valid garbage collector root; "
|
||||
"it's not in the directory '%2%'") %
|
||||
gcRoot % rootsDir);
|
||||
}
|
||||
}
|
||||
|
||||
if (baseNameOf(gcRoot) == baseNameOf(storePath))
|
||||
if (baseNameOf(gcRoot) == baseNameOf(storePath)) {
|
||||
writeFile(gcRoot, "");
|
||||
else
|
||||
} else {
|
||||
makeSymlink(gcRoot, storePath);
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that the root can be found by the garbage collector.
|
||||
|
|
@ -144,10 +150,11 @@ void LocalStore::addTempRoot(const Path& path) {
|
|||
while (1) {
|
||||
AutoCloseFD fdGCLock = openGCLock(ltRead);
|
||||
|
||||
if (pathExists(fnTempRoots))
|
||||
if (pathExists(fnTempRoots)) {
|
||||
/* It *must* be stale, since there can be no two
|
||||
processes with the same pid. */
|
||||
unlink(fnTempRoots.c_str());
|
||||
}
|
||||
|
||||
state->fdTempRoots = openLockFile(fnTempRoots, true);
|
||||
|
||||
|
|
@ -159,8 +166,9 @@ void LocalStore::addTempRoot(const Path& path) {
|
|||
/* Check whether the garbage collector didn't get in our
|
||||
way. */
|
||||
struct stat st;
|
||||
if (fstat(state->fdTempRoots.get(), &st) == -1)
|
||||
if (fstat(state->fdTempRoots.get(), &st) == -1) {
|
||||
throw SysError(format("statting '%1%'") % fnTempRoots);
|
||||
}
|
||||
if (st.st_size == 0) {
|
||||
break;
|
||||
}
|
||||
|
|
@ -245,11 +253,12 @@ void LocalStore::findTempRoots(FDs& fds, Roots& tempRoots, bool censor) {
|
|||
void LocalStore::findRoots(const Path& path, unsigned char type, Roots& roots) {
|
||||
auto foundRoot = [&](const Path& path, const Path& target) {
|
||||
Path storePath = toStorePath(target);
|
||||
if (isStorePath(storePath) && isValidPath(storePath))
|
||||
if (isStorePath(storePath) && isValidPath(storePath)) {
|
||||
roots[storePath].emplace(path);
|
||||
else
|
||||
} else {
|
||||
LOG(INFO) << "skipping invalid root from '" << path << "' to '"
|
||||
<< storePath << "'";
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
|
|
@ -258,8 +267,9 @@ void LocalStore::findRoots(const Path& path, unsigned char type, Roots& roots) {
|
|||
}
|
||||
|
||||
if (type == DT_DIR) {
|
||||
for (auto& i : readDirectory(path))
|
||||
for (auto& i : readDirectory(path)) {
|
||||
findRoots(path + "/" + i.name, i.type, roots);
|
||||
}
|
||||
}
|
||||
|
||||
else if (type == DT_LNK) {
|
||||
|
|
@ -292,8 +302,9 @@ void LocalStore::findRoots(const Path& path, unsigned char type, Roots& roots) {
|
|||
|
||||
else if (type == DT_REG) {
|
||||
Path storePath = storeDir + "/" + baseNameOf(path);
|
||||
if (isStorePath(storePath) && isValidPath(storePath))
|
||||
if (isStorePath(storePath) && isValidPath(storePath)) {
|
||||
roots[storePath].emplace(path);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -395,8 +406,9 @@ void LocalStore::findRuntimeRoots(Roots& roots, bool censor) {
|
|||
}
|
||||
struct dirent* fd_ent;
|
||||
while (errno = 0, fd_ent = readdir(fdDir.get())) {
|
||||
if (fd_ent->d_name[0] != '.')
|
||||
if (fd_ent->d_name[0] != '.') {
|
||||
readProcLink(fmt("%s/%s", fdStr, fd_ent->d_name), unchecked);
|
||||
}
|
||||
}
|
||||
if (errno) {
|
||||
if (errno == ESRCH) {
|
||||
|
|
@ -412,8 +424,9 @@ void LocalStore::findRuntimeRoots(Roots& roots, bool censor) {
|
|||
readFile(mapFile, true), "\n");
|
||||
for (const auto& line : mapLines) {
|
||||
auto match = std::smatch{};
|
||||
if (std::regex_match(line, match, mapRegex))
|
||||
if (std::regex_match(line, match, mapRegex)) {
|
||||
unchecked[match[1]].emplace(mapFile);
|
||||
}
|
||||
}
|
||||
|
||||
auto envFile = fmt("/proc/%s/environ", ent->d_name);
|
||||
|
|
@ -421,8 +434,9 @@ void LocalStore::findRuntimeRoots(Roots& roots, bool censor) {
|
|||
auto env_end = std::sregex_iterator{};
|
||||
for (auto i = std::sregex_iterator{envString.begin(), envString.end(),
|
||||
storePathRegex};
|
||||
i != env_end; ++i)
|
||||
i != env_end; ++i) {
|
||||
unchecked[i->str()].emplace(envFile);
|
||||
}
|
||||
} catch (SysError& e) {
|
||||
if (errno == ENOENT || errno == EACCES || errno == ESRCH) {
|
||||
continue;
|
||||
|
|
@ -467,10 +481,11 @@ void LocalStore::findRuntimeRoots(Roots& roots, bool censor) {
|
|||
Path path = toStorePath(target);
|
||||
if (isStorePath(path) && isValidPath(path)) {
|
||||
DLOG(INFO) << "got additional root " << path;
|
||||
if (censor)
|
||||
if (censor) {
|
||||
roots[path].insert(censored);
|
||||
else
|
||||
} else {
|
||||
roots[path].insert(links.begin(), links.end());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -514,10 +529,11 @@ void LocalStore::deletePathRecursive(GCState& state, const Path& path) {
|
|||
if (isStorePath(path) && isValidPath(path)) {
|
||||
PathSet referrers;
|
||||
queryReferrers(path, referrers);
|
||||
for (auto& i : referrers)
|
||||
for (auto& i : referrers) {
|
||||
if (i != path) {
|
||||
deletePathRecursive(state, i);
|
||||
}
|
||||
}
|
||||
size = queryPathInfo(path)->narSize;
|
||||
invalidatePathChecked(path);
|
||||
}
|
||||
|
|
@ -546,12 +562,14 @@ void LocalStore::deletePathRecursive(GCState& state, const Path& path) {
|
|||
// if the path was not valid, need to determine the actual
|
||||
// size.
|
||||
try {
|
||||
if (chmod(realPath.c_str(), st.st_mode | S_IWUSR) == -1)
|
||||
if (chmod(realPath.c_str(), st.st_mode | S_IWUSR) == -1) {
|
||||
throw SysError(format("making '%1%' writable") % realPath);
|
||||
}
|
||||
Path tmp = trashDir + "/" + baseNameOf(path);
|
||||
if (rename(realPath.c_str(), tmp.c_str()))
|
||||
if (rename(realPath.c_str(), tmp.c_str())) {
|
||||
throw SysError(format("unable to rename '%1%' to '%2%'") % realPath %
|
||||
tmp);
|
||||
}
|
||||
state.bytesInvalidated += size;
|
||||
} catch (SysError& e) {
|
||||
if (e.errNo == ENOSPC) {
|
||||
|
|
@ -560,8 +578,9 @@ void LocalStore::deletePathRecursive(GCState& state, const Path& path) {
|
|||
deleteGarbage(state, realPath);
|
||||
}
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
deleteGarbage(state, realPath);
|
||||
}
|
||||
|
||||
if (state.results.bytesFreed + state.bytesInvalidated >
|
||||
state.options.maxFreed) {
|
||||
|
|
@ -606,9 +625,11 @@ bool LocalStore::canReachRoot(GCState& state, PathSet& visited,
|
|||
don't delete the derivation if any of the outputs are alive. */
|
||||
if (state.gcKeepDerivations && isDerivation(path)) {
|
||||
PathSet outputs = queryDerivationOutputs(path);
|
||||
for (auto& i : outputs)
|
||||
if (isValidPath(i) && queryPathInfo(i)->deriver == path)
|
||||
for (auto& i : outputs) {
|
||||
if (isValidPath(i) && queryPathInfo(i)->deriver == path) {
|
||||
incoming.insert(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If keep-outputs is set, then don't delete this path if there
|
||||
|
|
@ -620,12 +641,14 @@ bool LocalStore::canReachRoot(GCState& state, PathSet& visited,
|
|||
}
|
||||
}
|
||||
|
||||
for (auto& i : incoming)
|
||||
if (i != path)
|
||||
for (auto& i : incoming) {
|
||||
if (i != path) {
|
||||
if (canReachRoot(state, visited, i)) {
|
||||
state.alive.insert(path);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
@ -701,8 +724,9 @@ void LocalStore::removeUnusedLinks(const GCState& state) {
|
|||
Path path = linksDir + "/" + name;
|
||||
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st) == -1)
|
||||
if (lstat(path.c_str(), &st) == -1) {
|
||||
throw SysError(format("statting '%1%'") % path);
|
||||
}
|
||||
|
||||
if (st.st_nlink != 1) {
|
||||
actualSize += st.st_size;
|
||||
|
|
@ -807,16 +831,18 @@ void LocalStore::collectGarbage(const GCOptions& options, GCResults& results) {
|
|||
for (auto& i : options.pathsToDelete) {
|
||||
assertStorePath(i);
|
||||
tryToDelete(state, i);
|
||||
if (state.dead.find(i) == state.dead.end())
|
||||
if (state.dead.find(i) == state.dead.end()) {
|
||||
throw Error(format("cannot delete path '%1%' since it is still alive") %
|
||||
i);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (options.maxFreed > 0) {
|
||||
if (state.shouldDelete)
|
||||
if (state.shouldDelete) {
|
||||
LOG(INFO) << "deleting garbage...";
|
||||
else
|
||||
} else {
|
||||
LOG(ERROR) << "determining live/dead paths...";
|
||||
}
|
||||
|
||||
try {
|
||||
AutoCloseDir dir(opendir(realStoreDir.c_str()));
|
||||
|
|
@ -839,10 +865,11 @@ void LocalStore::collectGarbage(const GCOptions& options, GCResults& results) {
|
|||
continue;
|
||||
}
|
||||
Path path = storeDir + "/" + name;
|
||||
if (isStorePath(path) && isValidPath(path))
|
||||
if (isStorePath(path) && isValidPath(path)) {
|
||||
entries.push_back(path);
|
||||
else
|
||||
} else {
|
||||
tryToDelete(state, path);
|
||||
}
|
||||
}
|
||||
|
||||
dir.reset();
|
||||
|
|
@ -897,8 +924,9 @@ void LocalStore::autoGC(bool sync) {
|
|||
static auto fakeFreeSpaceFile = getEnv("_NIX_TEST_FREE_SPACE_FILE", "");
|
||||
|
||||
auto getAvail = [this]() -> uint64_t {
|
||||
if (!fakeFreeSpaceFile.empty())
|
||||
if (!fakeFreeSpaceFile.empty()) {
|
||||
return std::stoll(readFile(fakeFreeSpaceFile));
|
||||
}
|
||||
|
||||
struct statvfs st;
|
||||
if (statvfs(realStoreDir.c_str(), &st)) {
|
||||
|
|
@ -922,8 +950,9 @@ void LocalStore::autoGC(bool sync) {
|
|||
auto now = std::chrono::steady_clock::now();
|
||||
|
||||
if (now < state->lastGCCheck +
|
||||
std::chrono::seconds(settings.minFreeCheckInterval))
|
||||
std::chrono::seconds(settings.minFreeCheckInterval)) {
|
||||
return;
|
||||
}
|
||||
|
||||
auto avail = getAvail();
|
||||
|
||||
|
|
|
|||
32
third_party/nix/src/libstore/globals.cc
vendored
32
third_party/nix/src/libstore/globals.cc
vendored
|
|
@ -49,11 +49,12 @@ Settings::Settings()
|
|||
if (caFile == "") {
|
||||
for (auto& fn :
|
||||
{"/etc/ssl/certs/ca-certificates.crt",
|
||||
"/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"})
|
||||
"/nix/var/nix/profiles/default/etc/ssl/certs/ca-bundle.crt"}) {
|
||||
if (pathExists(fn)) {
|
||||
caFile = fn;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Backwards compatibility. */
|
||||
|
|
@ -112,26 +113,28 @@ const string nixVersion = PACKAGE_VERSION;
|
|||
|
||||
template <>
|
||||
void BaseSetting<SandboxMode>::set(const std::string& str) {
|
||||
if (str == "true")
|
||||
if (str == "true") {
|
||||
value = smEnabled;
|
||||
else if (str == "relaxed")
|
||||
} else if (str == "relaxed") {
|
||||
value = smRelaxed;
|
||||
else if (str == "false")
|
||||
} else if (str == "false") {
|
||||
value = smDisabled;
|
||||
else
|
||||
} else {
|
||||
throw UsageError("option '%s' has invalid value '%s'", name, str);
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
std::string BaseSetting<SandboxMode>::to_string() {
|
||||
if (value == smEnabled)
|
||||
if (value == smEnabled) {
|
||||
return "true";
|
||||
else if (value == smRelaxed)
|
||||
} else if (value == smRelaxed) {
|
||||
return "relaxed";
|
||||
else if (value == smDisabled)
|
||||
} else if (value == smDisabled) {
|
||||
return "false";
|
||||
else
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
}
|
||||
|
||||
template <>
|
||||
|
|
@ -160,11 +163,12 @@ void BaseSetting<SandboxMode>::convertToArg(Args& args,
|
|||
}
|
||||
|
||||
void MaxBuildJobsSetting::set(const std::string& str) {
|
||||
if (str == "auto")
|
||||
if (str == "auto") {
|
||||
value = std::max(1U, std::thread::hardware_concurrency());
|
||||
else if (!string2Int(str, value))
|
||||
} else if (!string2Int(str, value)) {
|
||||
throw UsageError(
|
||||
"configuration setting '%s' should be 'auto' or an integer", name);
|
||||
}
|
||||
}
|
||||
|
||||
void initPlugins() {
|
||||
|
|
@ -172,8 +176,9 @@ void initPlugins() {
|
|||
Paths pluginFiles;
|
||||
try {
|
||||
auto ents = readDirectory(pluginFile);
|
||||
for (const auto& ent : ents)
|
||||
for (const auto& ent : ents) {
|
||||
pluginFiles.emplace_back(pluginFile + "/" + ent.name);
|
||||
}
|
||||
} catch (SysError& e) {
|
||||
if (e.errNo != ENOTDIR) {
|
||||
throw;
|
||||
|
|
@ -184,9 +189,10 @@ void initPlugins() {
|
|||
/* handle is purposefully leaked as there may be state in the
|
||||
DSO needed by the action of the plugin. */
|
||||
void* handle = dlopen(file.c_str(), RTLD_LAZY | RTLD_LOCAL);
|
||||
if (!handle)
|
||||
if (!handle) {
|
||||
throw Error("could not dynamically open plugin file '%s': %s", file,
|
||||
dlerror());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
15
third_party/nix/src/libstore/globals.hh
vendored
15
third_party/nix/src/libstore/globals.hh
vendored
|
|
@ -408,17 +408,10 @@ class Settings : public Config {
|
|||
this, true, "print-missing",
|
||||
"Whether to print what paths need to be built or downloaded."};
|
||||
|
||||
Setting<std::string> preBuildHook {
|
||||
this,
|
||||
#if __APPLE__
|
||||
nixLibexecDir + "/nix/resolve-system-dependencies",
|
||||
#else
|
||||
"",
|
||||
#endif
|
||||
"pre-build-hook",
|
||||
"A program to run just before a build to set derivation-specific build "
|
||||
"settings."
|
||||
};
|
||||
Setting<std::string> preBuildHook{
|
||||
this, "", "pre-build-hook",
|
||||
"A program to run just before a build to set derivation-specific build "
|
||||
"settings."};
|
||||
|
||||
Setting<std::string> postBuildHook{
|
||||
this, "", "post-build-hook",
|
||||
|
|
|
|||
|
|
@ -113,9 +113,10 @@ class HttpBinaryCacheStore : public BinaryCacheStore {
|
|||
try {
|
||||
getDownloader()->download(std::move(request), sink);
|
||||
} catch (DownloadError& e) {
|
||||
if (e.error == Downloader::NotFound || e.error == Downloader::Forbidden)
|
||||
if (e.error == Downloader::NotFound || e.error == Downloader::Forbidden) {
|
||||
throw NoSuchBinaryCacheFile(
|
||||
"file '%s' does not exist in binary cache '%s'", path, getUri());
|
||||
}
|
||||
maybeDisable();
|
||||
throw;
|
||||
}
|
||||
|
|
@ -137,8 +138,9 @@ class HttpBinaryCacheStore : public BinaryCacheStore {
|
|||
(*callbackPtr)(result.get().data);
|
||||
} catch (DownloadError& e) {
|
||||
if (e.error == Downloader::NotFound ||
|
||||
e.error == Downloader::Forbidden)
|
||||
e.error == Downloader::Forbidden) {
|
||||
return (*callbackPtr)(std::shared_ptr<std::string>());
|
||||
}
|
||||
maybeDisable();
|
||||
callbackPtr->rethrow();
|
||||
} catch (...) {
|
||||
|
|
@ -154,8 +156,9 @@ static RegisterStoreImplementation regStore(
|
|||
if (std::string(uri, 0, 7) != "http://" &&
|
||||
std::string(uri, 0, 8) != "https://" &&
|
||||
(getEnv("_NIX_FORCE_HTTP_BINARY_CACHE_STORE") != "1" ||
|
||||
std::string(uri, 0, 7) != "file://"))
|
||||
std::string(uri, 0, 7) != "file://")) {
|
||||
return 0;
|
||||
}
|
||||
auto store = std::make_shared<HttpBinaryCacheStore>(params, uri);
|
||||
store->init();
|
||||
return store;
|
||||
|
|
|
|||
18
third_party/nix/src/libstore/legacy-ssh-store.cc
vendored
18
third_party/nix/src/libstore/legacy-ssh-store.cc
vendored
|
|
@ -69,12 +69,14 @@ struct LegacySSHStore : public Store {
|
|||
conn->to.flush();
|
||||
|
||||
unsigned int magic = readInt(conn->from);
|
||||
if (magic != SERVE_MAGIC_2)
|
||||
if (magic != SERVE_MAGIC_2) {
|
||||
throw Error("protocol mismatch with 'nix-store --serve' on '%s'", host);
|
||||
}
|
||||
conn->remoteVersion = readInt(conn->from);
|
||||
if (GET_PROTOCOL_MAJOR(conn->remoteVersion) != 0x200)
|
||||
if (GET_PROTOCOL_MAJOR(conn->remoteVersion) != 0x200) {
|
||||
throw Error("unsupported 'nix-store --serve' protocol version on '%s'",
|
||||
host);
|
||||
}
|
||||
|
||||
} catch (EndOfFile& e) {
|
||||
throw Error("cannot connect to '%1%'", host);
|
||||
|
|
@ -160,9 +162,10 @@ struct LegacySSHStore : public Store {
|
|||
conn->to.flush();
|
||||
}
|
||||
|
||||
if (readInt(conn->from) != 1)
|
||||
if (readInt(conn->from) != 1) {
|
||||
throw Error(
|
||||
"failed to add path '%s' to remote host '%s', info.path, host");
|
||||
}
|
||||
}
|
||||
|
||||
void narFromPath(const Path& path, Sink& sink) override {
|
||||
|
|
@ -194,10 +197,12 @@ struct LegacySSHStore : public Store {
|
|||
|
||||
conn->to << cmdBuildDerivation << drvPath << drv << settings.maxSilentTime
|
||||
<< settings.buildTimeout;
|
||||
if (GET_PROTOCOL_MINOR(conn->remoteVersion) >= 2)
|
||||
if (GET_PROTOCOL_MINOR(conn->remoteVersion) >= 2) {
|
||||
conn->to << settings.maxLogSize;
|
||||
if (GET_PROTOCOL_MINOR(conn->remoteVersion) >= 3)
|
||||
}
|
||||
if (GET_PROTOCOL_MINOR(conn->remoteVersion) >= 3) {
|
||||
conn->to << settings.buildRepeat << settings.enforceDeterminism;
|
||||
}
|
||||
|
||||
conn->to.flush();
|
||||
|
||||
|
|
@ -205,9 +210,10 @@ struct LegacySSHStore : public Store {
|
|||
status.status = (BuildResult::Status)readInt(conn->from);
|
||||
conn->from >> status.errorMsg;
|
||||
|
||||
if (GET_PROTOCOL_MINOR(conn->remoteVersion) >= 3)
|
||||
if (GET_PROTOCOL_MINOR(conn->remoteVersion) >= 3) {
|
||||
conn->from >> status.timesBuilt >> status.isNonDeterministic >>
|
||||
status.startTime >> status.stopTime;
|
||||
}
|
||||
|
||||
return status;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -26,9 +26,10 @@ class LocalBinaryCacheStore : public BinaryCacheStore {
|
|||
try {
|
||||
readFile(binaryCacheDir + "/" + path, sink);
|
||||
} catch (SysError& e) {
|
||||
if (e.errNo == ENOENT)
|
||||
if (e.errNo == ENOENT) {
|
||||
throw NoSuchBinaryCacheFile("file '%s' does not exist in binary cache",
|
||||
path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -36,8 +37,9 @@ class LocalBinaryCacheStore : public BinaryCacheStore {
|
|||
PathSet paths;
|
||||
|
||||
for (auto& entry : readDirectory(binaryCacheDir)) {
|
||||
if (entry.name.size() != 40 || !hasSuffix(entry.name, ".narinfo"))
|
||||
if (entry.name.size() != 40 || !hasSuffix(entry.name, ".narinfo")) {
|
||||
continue;
|
||||
}
|
||||
paths.insert(storeDir + "/" +
|
||||
entry.name.substr(0, entry.name.size() - 8));
|
||||
}
|
||||
|
|
@ -55,8 +57,9 @@ static void atomicWrite(const Path& path, const std::string& s) {
|
|||
Path tmp = path + ".tmp." + std::to_string(getpid());
|
||||
AutoDelete del(tmp, false);
|
||||
writeFile(tmp, s);
|
||||
if (rename(tmp.c_str(), path.c_str()))
|
||||
if (rename(tmp.c_str(), path.c_str())) {
|
||||
throw SysError(format("renaming '%1%' to '%2%'") % tmp % path);
|
||||
}
|
||||
del.cancel();
|
||||
}
|
||||
|
||||
|
|
@ -74,8 +77,9 @@ static RegisterStoreImplementation regStore(
|
|||
[](const std::string& uri,
|
||||
const Store::Params& params) -> std::shared_ptr<Store> {
|
||||
if (getEnv("_NIX_FORCE_HTTP_BINARY_CACHE_STORE") == "1" ||
|
||||
std::string(uri, 0, 7) != "file://")
|
||||
std::string(uri, 0, 7) != "file://") {
|
||||
return 0;
|
||||
}
|
||||
auto store =
|
||||
std::make_shared<LocalBinaryCacheStore>(params, std::string(uri, 7));
|
||||
store->init();
|
||||
|
|
|
|||
|
|
@ -16,9 +16,10 @@ struct LocalStoreAccessor : public FSAccessor {
|
|||
|
||||
Path toRealPath(const Path& path) {
|
||||
Path storePath = store->toStorePath(path);
|
||||
if (!store->isValidPath(storePath))
|
||||
if (!store->isValidPath(storePath)) {
|
||||
throw InvalidPath(format("path '%1%' is not a valid store path") %
|
||||
storePath);
|
||||
}
|
||||
return store->getRealStoreDir() + std::string(path, store->storeDir.size());
|
||||
}
|
||||
|
||||
|
|
@ -27,13 +28,15 @@ struct LocalStoreAccessor : public FSAccessor {
|
|||
|
||||
struct stat st;
|
||||
if (lstat(realPath.c_str(), &st)) {
|
||||
if (errno == ENOENT || errno == ENOTDIR)
|
||||
if (errno == ENOENT || errno == ENOTDIR) {
|
||||
return {Type::tMissing, 0, false};
|
||||
}
|
||||
throw SysError(format("getting status of '%1%'") % path);
|
||||
}
|
||||
|
||||
if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode))
|
||||
if (!S_ISREG(st.st_mode) && !S_ISDIR(st.st_mode) && !S_ISLNK(st.st_mode)) {
|
||||
throw Error(format("file '%1%' has unsupported type") % path);
|
||||
}
|
||||
|
||||
return {S_ISREG(st.st_mode)
|
||||
? Type::tRegular
|
||||
|
|
|
|||
171
third_party/nix/src/libstore/local-store.cc
vendored
171
third_party/nix/src/libstore/local-store.cc
vendored
|
|
@ -73,8 +73,9 @@ LocalStore::LocalStore(const Params& params)
|
|||
for (auto& perUserDir :
|
||||
{profilesDir + "/per-user", gcRootsDir + "/per-user"}) {
|
||||
createDirs(perUserDir);
|
||||
if (chmod(perUserDir.c_str(), 0755) == -1)
|
||||
if (chmod(perUserDir.c_str(), 0755) == -1) {
|
||||
throw SysError("could not set permissions on '%s' to 755", perUserDir);
|
||||
}
|
||||
}
|
||||
|
||||
createUser(getUserName(), getuid());
|
||||
|
|
@ -90,18 +91,21 @@ LocalStore::LocalStore(const Params& params)
|
|||
<< "' specified in 'build-users-group' does not exist";
|
||||
} else {
|
||||
struct stat st;
|
||||
if (stat(realStoreDir.c_str(), &st))
|
||||
if (stat(realStoreDir.c_str(), &st)) {
|
||||
throw SysError(format("getting attributes of path '%1%'") %
|
||||
realStoreDir);
|
||||
}
|
||||
|
||||
if (st.st_uid != 0 || st.st_gid != gr->gr_gid ||
|
||||
(st.st_mode & ~S_IFMT) != perm) {
|
||||
if (chown(realStoreDir.c_str(), 0, gr->gr_gid) == -1)
|
||||
if (chown(realStoreDir.c_str(), 0, gr->gr_gid) == -1) {
|
||||
throw SysError(format("changing ownership of path '%1%'") %
|
||||
realStoreDir);
|
||||
if (chmod(realStoreDir.c_str(), perm) == -1)
|
||||
}
|
||||
if (chmod(realStoreDir.c_str(), perm) == -1) {
|
||||
throw SysError(format("changing permissions on path '%1%'") %
|
||||
realStoreDir);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -111,13 +115,15 @@ LocalStore::LocalStore(const Params& params)
|
|||
Path path = realStoreDir;
|
||||
struct stat st;
|
||||
while (path != "/") {
|
||||
if (lstat(path.c_str(), &st))
|
||||
if (lstat(path.c_str(), &st)) {
|
||||
throw SysError(format("getting status of '%1%'") % path);
|
||||
if (S_ISLNK(st.st_mode))
|
||||
}
|
||||
if (S_ISLNK(st.st_mode)) {
|
||||
throw Error(format("the path '%1%' is a symlink; "
|
||||
"this is not allowed for the Nix store and its "
|
||||
"parent directories") %
|
||||
path);
|
||||
}
|
||||
path = dirOf(path);
|
||||
}
|
||||
}
|
||||
|
|
@ -168,17 +174,19 @@ LocalStore::LocalStore(const Params& params)
|
|||
openDB(*state, true);
|
||||
writeFile(schemaPath, (format("%1%") % nixSchemaVersion).str());
|
||||
} else if (curSchema < nixSchemaVersion) {
|
||||
if (curSchema < 5)
|
||||
if (curSchema < 5) {
|
||||
throw Error(
|
||||
"Your Nix store has a database in Berkeley DB format,\n"
|
||||
"which is no longer supported. To convert to the new format,\n"
|
||||
"please upgrade Nix to version 0.12 first.");
|
||||
}
|
||||
|
||||
if (curSchema < 6)
|
||||
if (curSchema < 6) {
|
||||
throw Error(
|
||||
"Your Nix store has a database in flat file format,\n"
|
||||
"which is no longer supported. To convert to the new format,\n"
|
||||
"please upgrade Nix to version 1.11 first.");
|
||||
}
|
||||
|
||||
if (!lockFile(globalLock.get(), ltWrite, false)) {
|
||||
LOG(INFO) << "waiting for exclusive access to the Nix store...";
|
||||
|
|
@ -295,24 +303,27 @@ int LocalStore::getSchema() {
|
|||
int curSchema = 0;
|
||||
if (pathExists(schemaPath)) {
|
||||
string s = readFile(schemaPath);
|
||||
if (!string2Int(s, curSchema))
|
||||
if (!string2Int(s, curSchema)) {
|
||||
throw Error(format("'%1%' is corrupt") % schemaPath);
|
||||
}
|
||||
}
|
||||
return curSchema;
|
||||
}
|
||||
|
||||
void LocalStore::openDB(State& state, bool create) {
|
||||
if (access(dbDir.c_str(), R_OK | W_OK))
|
||||
if (access(dbDir.c_str(), R_OK | W_OK)) {
|
||||
throw SysError(format("Nix database directory '%1%' is not writable") %
|
||||
dbDir);
|
||||
}
|
||||
|
||||
/* Open the Nix database. */
|
||||
string dbPath = dbDir + "/db.sqlite";
|
||||
auto& db(state.db);
|
||||
if (sqlite3_open_v2(dbPath.c_str(), &db.db,
|
||||
SQLITE_OPEN_READWRITE | (create ? SQLITE_OPEN_CREATE : 0),
|
||||
0) != SQLITE_OK)
|
||||
0) != SQLITE_OK) {
|
||||
throw Error(format("cannot open Nix database '%1%'") % dbPath);
|
||||
}
|
||||
|
||||
#ifdef __CYGWIN__
|
||||
/* The cygwin version of sqlite3 has a patch which calls
|
||||
|
|
@ -354,15 +365,17 @@ void LocalStore::openDB(State& state, bool create) {
|
|||
}
|
||||
if (prevMode != mode &&
|
||||
sqlite3_exec(db, ("pragma main.journal_mode = " + mode + ";").c_str(), 0,
|
||||
0, 0) != SQLITE_OK)
|
||||
0, 0) != SQLITE_OK) {
|
||||
throwSQLiteError(db, "setting journal mode");
|
||||
}
|
||||
|
||||
/* 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(). */
|
||||
if (mode == "wal" && sqlite3_exec(db, "pragma wal_autocheckpoint = 40000;", 0,
|
||||
0, 0) != SQLITE_OK)
|
||||
0, 0) != SQLITE_OK) {
|
||||
throwSQLiteError(db, "setting autocheckpoint interval");
|
||||
}
|
||||
|
||||
/* Initialise the database schema, if necessary. */
|
||||
if (create) {
|
||||
|
|
@ -382,15 +395,18 @@ void LocalStore::makeStoreWritable() {
|
|||
}
|
||||
/* Check if /nix/store is on a read-only mount. */
|
||||
struct statvfs stat;
|
||||
if (statvfs(realStoreDir.c_str(), &stat) != 0)
|
||||
if (statvfs(realStoreDir.c_str(), &stat) != 0) {
|
||||
throw SysError("getting info about the Nix store mount point");
|
||||
}
|
||||
|
||||
if (stat.f_flag & ST_RDONLY) {
|
||||
if (unshare(CLONE_NEWNS) == -1)
|
||||
if (unshare(CLONE_NEWNS) == -1) {
|
||||
throw SysError("setting up a private mount namespace");
|
||||
}
|
||||
|
||||
if (mount(0, realStoreDir.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1)
|
||||
if (mount(0, realStoreDir.c_str(), "none", MS_REMOUNT | MS_BIND, 0) == -1) {
|
||||
throw SysError(format("remounting %1% writable") % realStoreDir);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
|
@ -405,8 +421,9 @@ static void canonicaliseTimestampAndPermissions(const Path& path,
|
|||
|
||||
if (mode != 0444 && mode != 0555) {
|
||||
mode = (st.st_mode & S_IFMT) | 0444 | (st.st_mode & S_IXUSR ? 0111 : 0);
|
||||
if (chmod(path.c_str(), mode) == -1)
|
||||
if (chmod(path.c_str(), mode) == -1) {
|
||||
throw SysError(format("changing mode of '%1%' to %2$o") % path % mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -417,20 +434,23 @@ static void canonicaliseTimestampAndPermissions(const Path& path,
|
|||
times[1].tv_sec = mtimeStore;
|
||||
times[1].tv_usec = 0;
|
||||
#if HAVE_LUTIMES
|
||||
if (lutimes(path.c_str(), times) == -1)
|
||||
if (lutimes(path.c_str(), times) == -1) {
|
||||
if (errno != ENOSYS ||
|
||||
(!S_ISLNK(st.st_mode) && utimes(path.c_str(), times) == -1))
|
||||
(!S_ISLNK(st.st_mode) && utimes(path.c_str(), times) == -1)) {
|
||||
#else
|
||||
if (!S_ISLNK(st.st_mode) && utimes(path.c_str(), times) == -1)
|
||||
#endif
|
||||
throw SysError(format("changing modification time of '%1%'") % path);
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace nix
|
||||
}
|
||||
|
||||
void canonicaliseTimestampAndPermissions(const Path& path) {
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
if (lstat(path.c_str(), &st)) {
|
||||
throw SysError(format("getting attributes of path '%1%'") % path);
|
||||
}
|
||||
canonicaliseTimestampAndPermissions(path, st);
|
||||
}
|
||||
|
||||
|
|
@ -449,25 +469,29 @@ static void canonicalisePathMetaData_(const Path& path, uid_t fromUid,
|
|||
#endif
|
||||
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
if (lstat(path.c_str(), &st)) {
|
||||
throw SysError(format("getting attributes of path '%1%'") % path);
|
||||
}
|
||||
|
||||
/* Really make sure that the path is of a supported type. */
|
||||
if (!(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode)))
|
||||
if (!(S_ISREG(st.st_mode) || S_ISDIR(st.st_mode) || S_ISLNK(st.st_mode))) {
|
||||
throw Error(format("file '%1%' has an unsupported type") % path);
|
||||
}
|
||||
|
||||
#if __linux__
|
||||
/* Remove extended attributes / ACLs. */
|
||||
ssize_t eaSize = llistxattr(path.c_str(), nullptr, 0);
|
||||
|
||||
if (eaSize < 0) {
|
||||
if (errno != ENOTSUP && errno != ENODATA)
|
||||
if (errno != ENOTSUP && errno != ENODATA) {
|
||||
throw SysError("querying extended attributes of '%s'", path);
|
||||
}
|
||||
} else if (eaSize > 0) {
|
||||
std::vector<char> eaBuf(eaSize);
|
||||
|
||||
if ((eaSize = llistxattr(path.c_str(), eaBuf.data(), eaBuf.size())) < 0)
|
||||
if ((eaSize = llistxattr(path.c_str(), eaBuf.data(), eaBuf.size())) < 0) {
|
||||
throw SysError("querying extended attributes of '%s'", path);
|
||||
}
|
||||
|
||||
for (auto& eaName : tokenizeString<Strings>(
|
||||
std::string(eaBuf.data(), eaSize), std::string("\000", 1))) {
|
||||
|
|
@ -476,9 +500,10 @@ static void canonicalisePathMetaData_(const Path& path, uid_t fromUid,
|
|||
if (eaName == "security.selinux") {
|
||||
continue;
|
||||
}
|
||||
if (lremovexattr(path.c_str(), eaName.c_str()) == -1)
|
||||
if (lremovexattr(path.c_str(), eaName.c_str()) == -1) {
|
||||
throw SysError("removing extended attribute '%s' from '%s'", eaName,
|
||||
path);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
@ -491,8 +516,9 @@ static void canonicalisePathMetaData_(const Path& path, uid_t fromUid,
|
|||
(i.e. "touch $out/foo; ln $out/foo $out/bar"). */
|
||||
if (fromUid != (uid_t)-1 && st.st_uid != fromUid) {
|
||||
assert(!S_ISDIR(st.st_mode));
|
||||
if (inodesSeen.find(Inode(st.st_dev, st.st_ino)) == inodesSeen.end())
|
||||
if (inodesSeen.find(Inode(st.st_dev, st.st_ino)) == inodesSeen.end()) {
|
||||
throw BuildError(format("invalid ownership on file '%1%'") % path);
|
||||
}
|
||||
mode_t mode = st.st_mode & ~S_IFMT;
|
||||
assert(S_ISLNK(st.st_mode) ||
|
||||
(st.st_uid == geteuid() && (mode == 0444 || mode == 0555) &&
|
||||
|
|
@ -513,18 +539,20 @@ static void canonicalisePathMetaData_(const Path& path, uid_t fromUid,
|
|||
users group); we check for this case below. */
|
||||
if (st.st_uid != geteuid()) {
|
||||
#if HAVE_LCHOWN
|
||||
if (lchown(path.c_str(), geteuid(), getegid()) == -1)
|
||||
if (lchown(path.c_str(), geteuid(), getegid()) == -1) {
|
||||
#else
|
||||
if (!S_ISLNK(st.st_mode) && chown(path.c_str(), geteuid(), getegid()) == -1)
|
||||
#endif
|
||||
throw SysError(format("changing owner of '%1%' to %2%") % path %
|
||||
geteuid());
|
||||
}
|
||||
}
|
||||
|
||||
if (S_ISDIR(st.st_mode)) {
|
||||
DirEntries entries = readDirectory(path);
|
||||
for (auto& i : entries)
|
||||
for (auto& i : entries) {
|
||||
canonicalisePathMetaData_(path + "/" + i.name, fromUid, inodesSeen);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -535,8 +563,9 @@ void canonicalisePathMetaData(const Path& path, uid_t fromUid,
|
|||
/* On platforms that don't have lchown(), the top-level path can't
|
||||
be a symlink, since we can't change its ownership. */
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
if (lstat(path.c_str(), &st)) {
|
||||
throw SysError(format("getting attributes of path '%1%'") % path);
|
||||
}
|
||||
|
||||
if (st.st_uid != geteuid()) {
|
||||
assert(S_ISLNK(st.st_mode));
|
||||
|
|
@ -557,10 +586,11 @@ void LocalStore::checkDerivationOutputs(const Path& drvPath,
|
|||
|
||||
if (drv.isFixedOutput()) {
|
||||
DerivationOutputs::const_iterator out = drv.outputs.find("out");
|
||||
if (out == drv.outputs.end())
|
||||
if (out == drv.outputs.end()) {
|
||||
throw Error(
|
||||
format("derivation '%1%' does not have an output named 'out'") %
|
||||
drvPath);
|
||||
}
|
||||
|
||||
bool recursive;
|
||||
Hash h;
|
||||
|
|
@ -569,11 +599,12 @@ void LocalStore::checkDerivationOutputs(const Path& drvPath,
|
|||
|
||||
StringPairs::const_iterator j = drv.env.find("out");
|
||||
if (out->second.path != outPath || j == drv.env.end() ||
|
||||
j->second != outPath)
|
||||
j->second != outPath) {
|
||||
throw Error(
|
||||
format(
|
||||
"derivation '%1%' has incorrect output '%2%', should be '%3%'") %
|
||||
drvPath % out->second.path % outPath);
|
||||
}
|
||||
}
|
||||
|
||||
else {
|
||||
|
|
@ -589,21 +620,23 @@ void LocalStore::checkDerivationOutputs(const Path& drvPath,
|
|||
Path outPath = makeOutputPath(i.first, h, drvName);
|
||||
StringPairs::const_iterator j = drv.env.find(i.first);
|
||||
if (i.second.path != outPath || j == drv.env.end() ||
|
||||
j->second != outPath)
|
||||
j->second != outPath) {
|
||||
throw Error(format("derivation '%1%' has incorrect output '%2%', "
|
||||
"should be '%3%'") %
|
||||
drvPath % i.second.path % outPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
uint64_t LocalStore::addValidPath(State& state, const ValidPathInfo& info,
|
||||
bool checkOutputs) {
|
||||
if (info.ca != "" && !info.isContentAddressed(*this))
|
||||
if (info.ca != "" && !info.isContentAddressed(*this)) {
|
||||
throw Error(
|
||||
"cannot add path '%s' to the Nix store because it claims to be "
|
||||
"content-addressed but isn't",
|
||||
info.path);
|
||||
}
|
||||
|
||||
state.stmtRegisterValidPath
|
||||
.use()(info.path)(info.narHash.to_string(Base16))(
|
||||
|
|
@ -697,8 +730,9 @@ void LocalStore::queryPathInfoUncached(
|
|||
/* Get the references. */
|
||||
auto useQueryReferences(state->stmtQueryReferences.use()(info->id));
|
||||
|
||||
while (useQueryReferences.next())
|
||||
while (useQueryReferences.next()) {
|
||||
info->references.insert(useQueryReferences.getStr(0));
|
||||
}
|
||||
|
||||
return info;
|
||||
}));
|
||||
|
|
@ -740,10 +774,11 @@ bool LocalStore::isValidPathUncached(const Path& path) {
|
|||
PathSet LocalStore::queryValidPaths(const PathSet& paths,
|
||||
SubstituteFlag maybeSubstitute) {
|
||||
PathSet res;
|
||||
for (auto& i : paths)
|
||||
for (auto& i : paths) {
|
||||
if (isValidPath(i)) {
|
||||
res.insert(i);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
|
|
@ -752,7 +787,9 @@ PathSet LocalStore::queryAllValidPaths() {
|
|||
auto state(_state.lock());
|
||||
auto use(state->stmtQueryValidPaths.use());
|
||||
PathSet res;
|
||||
while (use.next()) res.insert(use.getStr(0));
|
||||
while (use.next()) {
|
||||
res.insert(use.getStr(0));
|
||||
}
|
||||
return res;
|
||||
});
|
||||
}
|
||||
|
|
@ -761,8 +798,9 @@ void LocalStore::queryReferrers(State& state, const Path& path,
|
|||
PathSet& referrers) {
|
||||
auto useQueryReferrers(state.stmtQueryReferrers.use()(path));
|
||||
|
||||
while (useQueryReferrers.next())
|
||||
while (useQueryReferrers.next()) {
|
||||
referrers.insert(useQueryReferrers.getStr(0));
|
||||
}
|
||||
}
|
||||
|
||||
void LocalStore::queryReferrers(const Path& path, PathSet& referrers) {
|
||||
|
|
@ -782,8 +820,9 @@ PathSet LocalStore::queryValidDerivers(const Path& path) {
|
|||
auto useQueryValidDerivers(state->stmtQueryValidDerivers.use()(path));
|
||||
|
||||
PathSet derivers;
|
||||
while (useQueryValidDerivers.next())
|
||||
while (useQueryValidDerivers.next()) {
|
||||
derivers.insert(useQueryValidDerivers.getStr(1));
|
||||
}
|
||||
|
||||
return derivers;
|
||||
});
|
||||
|
|
@ -797,8 +836,9 @@ PathSet LocalStore::queryDerivationOutputs(const Path& path) {
|
|||
queryValidPathId(*state, path)));
|
||||
|
||||
PathSet outputs;
|
||||
while (useQueryDerivationOutputs.next())
|
||||
while (useQueryDerivationOutputs.next()) {
|
||||
outputs.insert(useQueryDerivationOutputs.getStr(1));
|
||||
}
|
||||
|
||||
return outputs;
|
||||
});
|
||||
|
|
@ -812,8 +852,9 @@ StringSet LocalStore::queryDerivationOutputNames(const Path& path) {
|
|||
queryValidPathId(*state, path)));
|
||||
|
||||
StringSet outputNames;
|
||||
while (useQueryDerivationOutputs.next())
|
||||
while (useQueryDerivationOutputs.next()) {
|
||||
outputNames.insert(useQueryDerivationOutputs.getStr(0));
|
||||
}
|
||||
|
||||
return outputNames;
|
||||
});
|
||||
|
|
@ -865,11 +906,13 @@ PathSet LocalStore::querySubstitutablePaths(const PathSet& paths) {
|
|||
auto valid = sub->queryValidPaths(remaining);
|
||||
|
||||
PathSet remaining2;
|
||||
for (auto& path : remaining)
|
||||
if (valid.count(path))
|
||||
for (auto& path : remaining) {
|
||||
if (valid.count(path)) {
|
||||
res.insert(path);
|
||||
else
|
||||
} else {
|
||||
remaining2.insert(path);
|
||||
}
|
||||
}
|
||||
|
||||
std::swap(remaining, remaining2);
|
||||
}
|
||||
|
|
@ -935,24 +978,26 @@ void LocalStore::registerValidPaths(const ValidPathInfos& infos) {
|
|||
|
||||
for (auto& i : infos) {
|
||||
assert(i.narHash.type == htSHA256);
|
||||
if (isValidPath_(*state, i.path))
|
||||
if (isValidPath_(*state, i.path)) {
|
||||
updatePathInfo(*state, i);
|
||||
else
|
||||
} else {
|
||||
addValidPath(*state, i, false);
|
||||
}
|
||||
paths.insert(i.path);
|
||||
}
|
||||
|
||||
for (auto& i : infos) {
|
||||
auto referrer = queryValidPathId(*state, i.path);
|
||||
for (auto& j : i.references)
|
||||
for (auto& j : i.references) {
|
||||
state->stmtAddReference.use()(referrer)(queryValidPathId(*state, j))
|
||||
.exec();
|
||||
}
|
||||
}
|
||||
|
||||
/* Check that the derivation outputs are correct. We can't do
|
||||
this in addValidPath() above, because the references might
|
||||
not be valid yet. */
|
||||
for (auto& i : infos)
|
||||
for (auto& i : infos) {
|
||||
if (isDerivation(i.path)) {
|
||||
// FIXME: inefficient; we already loaded the
|
||||
// derivation in addValidPath().
|
||||
|
|
@ -960,6 +1005,7 @@ void LocalStore::registerValidPaths(const ValidPathInfos& infos) {
|
|||
readDerivation(realStoreDir + "/" + baseNameOf(i.path));
|
||||
checkDerivationOutputs(i.path, drv);
|
||||
}
|
||||
}
|
||||
|
||||
/* Do a topological sort of the paths. This will throw an
|
||||
error if a cycle is detected and roll back the
|
||||
|
|
@ -989,8 +1035,9 @@ void LocalStore::invalidatePath(State& state, const Path& path) {
|
|||
|
||||
const PublicKeys& LocalStore::getPublicKeys() {
|
||||
auto state(_state.lock());
|
||||
if (!state->publicKeys)
|
||||
if (!state->publicKeys) {
|
||||
state->publicKeys = std::make_unique<PublicKeys>(getDefaultPublicKeys());
|
||||
}
|
||||
return *state->publicKeys;
|
||||
}
|
||||
|
||||
|
|
@ -1039,15 +1086,17 @@ void LocalStore::addToStore(const ValidPathInfo& info, Source& source,
|
|||
|
||||
auto hashResult = hashSink.finish();
|
||||
|
||||
if (hashResult.first != info.narHash)
|
||||
if (hashResult.first != info.narHash) {
|
||||
throw Error(
|
||||
"hash mismatch importing path '%s';\n wanted: %s\n got: %s",
|
||||
info.path, info.narHash.to_string(), hashResult.first.to_string());
|
||||
}
|
||||
|
||||
if (hashResult.second != info.narSize)
|
||||
if (hashResult.second != info.narSize) {
|
||||
throw Error(
|
||||
"size mismatch importing path '%s';\n wanted: %s\n got: %s",
|
||||
info.path, info.narSize, hashResult.second);
|
||||
}
|
||||
|
||||
autoGC();
|
||||
|
||||
|
|
@ -1130,10 +1179,11 @@ Path LocalStore::addToStore(const string& name, const Path& _srcPath,
|
|||
method for very large paths, but `copyPath' is mainly used for
|
||||
small files. */
|
||||
StringSink sink;
|
||||
if (recursive)
|
||||
if (recursive) {
|
||||
dumpPath(srcPath, sink, filter);
|
||||
else
|
||||
} else {
|
||||
sink.s = make_ref<std::string>(readFile(srcPath));
|
||||
}
|
||||
|
||||
return addToStoreFromDump(*sink.s, name, recursive, hashAlgo, repair);
|
||||
}
|
||||
|
|
@ -1206,10 +1256,11 @@ void LocalStore::invalidatePathChecked(const Path& path) {
|
|||
PathSet referrers;
|
||||
queryReferrers(*state, path, referrers);
|
||||
referrers.erase(path); /* ignore self-references */
|
||||
if (!referrers.empty())
|
||||
if (!referrers.empty()) {
|
||||
throw PathInUse(
|
||||
format("cannot delete path '%1%' because it is in use by %2%") %
|
||||
path % showPaths(referrers));
|
||||
}
|
||||
invalidatePath(*state, path);
|
||||
}
|
||||
|
||||
|
|
@ -1238,8 +1289,9 @@ bool LocalStore::verifyStore(bool checkContents, RepairFlag repair) {
|
|||
|
||||
fdGCLock = -1;
|
||||
|
||||
for (auto& i : validPaths2)
|
||||
for (auto& i : validPaths2) {
|
||||
verifyPath(i, store, done, validPaths, repair, errors);
|
||||
}
|
||||
|
||||
/* Optionally, check the content hashes (slow). */
|
||||
if (checkContents) {
|
||||
|
|
@ -1328,13 +1380,14 @@ void LocalStore::verifyPath(const Path& path, const PathSet& store,
|
|||
bool canInvalidate = true;
|
||||
PathSet referrers;
|
||||
queryReferrers(path, referrers);
|
||||
for (auto& i : referrers)
|
||||
for (auto& i : referrers) {
|
||||
if (i != path) {
|
||||
verifyPath(i, store, done, validPaths, repair, errors);
|
||||
if (validPaths.find(i) != validPaths.end()) {
|
||||
canInvalidate = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (canInvalidate) {
|
||||
LOG(WARNING) << "path '" << path
|
||||
|
|
@ -1463,10 +1516,12 @@ 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(), 0755) == -1)
|
||||
if (chmod(dir.c_str(), 0755) == -1) {
|
||||
throw SysError("changing permissions of directory '%s'", dir);
|
||||
if (chown(dir.c_str(), userId, getgid()) == -1)
|
||||
}
|
||||
if (chown(dir.c_str(), userId, getgid()) == -1) {
|
||||
throw SysError("changing owner of directory '%s'", dir);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
58
third_party/nix/src/libstore/misc.cc
vendored
58
third_party/nix/src/libstore/misc.cc
vendored
|
|
@ -47,35 +47,44 @@ void Store::computeFSClosure(const PathSet& startPaths, PathSet& paths_,
|
|||
if (flipDirection) {
|
||||
PathSet referrers;
|
||||
queryReferrers(path, referrers);
|
||||
for (auto& ref : referrers)
|
||||
for (auto& ref : referrers) {
|
||||
if (ref != path) {
|
||||
enqueue(ref);
|
||||
}
|
||||
}
|
||||
|
||||
if (includeOutputs)
|
||||
if (includeOutputs) {
|
||||
for (auto& i : queryValidDerivers(path)) {
|
||||
enqueue(i);
|
||||
}
|
||||
}
|
||||
|
||||
if (includeDerivers && isDerivation(path))
|
||||
for (auto& i : queryDerivationOutputs(path))
|
||||
if (isValidPath(i) && queryPathInfo(i)->deriver == path)
|
||||
if (includeDerivers && isDerivation(path)) {
|
||||
for (auto& i : queryDerivationOutputs(path)) {
|
||||
if (isValidPath(i) && queryPathInfo(i)->deriver == path) {
|
||||
enqueue(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
for (auto& ref : info->references)
|
||||
for (auto& ref : info->references) {
|
||||
if (ref != path) {
|
||||
enqueue(ref);
|
||||
}
|
||||
}
|
||||
|
||||
if (includeOutputs && isDerivation(path))
|
||||
for (auto& i : queryDerivationOutputs(path))
|
||||
if (includeOutputs && isDerivation(path)) {
|
||||
for (auto& i : queryDerivationOutputs(path)) {
|
||||
if (isValidPath(i)) {
|
||||
enqueue(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (includeDerivers && isValidPath(info->deriver))
|
||||
if (includeDerivers && isValidPath(info->deriver)) {
|
||||
enqueue(info->deriver);
|
||||
}
|
||||
}
|
||||
|
||||
{
|
||||
|
|
@ -105,7 +114,9 @@ void Store::computeFSClosure(const PathSet& startPaths, PathSet& paths_,
|
|||
|
||||
{
|
||||
auto state(state_.lock());
|
||||
while (state->pending) state.wait(done);
|
||||
while (state->pending) {
|
||||
state.wait(done);
|
||||
}
|
||||
if (state->exc) {
|
||||
std::rethrow_exception(state->exc);
|
||||
}
|
||||
|
|
@ -154,9 +165,10 @@ void Store::queryMissing(const PathSet& targets, PathSet& willBuild_,
|
|||
state->willBuild.insert(drvPath);
|
||||
}
|
||||
|
||||
for (auto& i : drv.inputDrvs)
|
||||
for (auto& i : drv.inputDrvs) {
|
||||
pool.enqueue(
|
||||
std::bind(doPath, makeDrvPathWithOutputs(i.first, i.second)));
|
||||
}
|
||||
};
|
||||
|
||||
auto checkOutput = [&](const Path& drvPath, ref<Derivation> drv,
|
||||
|
|
@ -181,8 +193,9 @@ void Store::queryMissing(const PathSet& targets, PathSet& willBuild_,
|
|||
drvState->left--;
|
||||
drvState->outPaths.insert(outPath);
|
||||
if (!drvState->left) {
|
||||
for (auto& path : drvState->outPaths)
|
||||
for (auto& path : drvState->outPaths) {
|
||||
pool.enqueue(std::bind(doPath, path));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -211,20 +224,24 @@ void Store::queryMissing(const PathSet& targets, PathSet& willBuild_,
|
|||
ParsedDerivation parsedDrv(i2.first, drv);
|
||||
|
||||
PathSet invalid;
|
||||
for (auto& j : drv.outputs)
|
||||
if (wantOutput(j.first, i2.second) && !isValidPath(j.second.path))
|
||||
for (auto& j : drv.outputs) {
|
||||
if (wantOutput(j.first, i2.second) && !isValidPath(j.second.path)) {
|
||||
invalid.insert(j.second.path);
|
||||
}
|
||||
}
|
||||
if (invalid.empty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (settings.useSubstitutes && parsedDrv.substitutesAllowed()) {
|
||||
auto drvState = make_ref<Sync<DrvState>>(DrvState(invalid.size()));
|
||||
for (auto& output : invalid)
|
||||
for (auto& output : invalid) {
|
||||
pool.enqueue(std::bind(checkOutput, i2.first,
|
||||
make_ref<Derivation>(drv), output, drvState));
|
||||
} else
|
||||
}
|
||||
} else {
|
||||
mustBuildDrv(i2.first, drv);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (isValidPath(path)) {
|
||||
|
|
@ -250,8 +267,9 @@ void Store::queryMissing(const PathSet& targets, PathSet& willBuild_,
|
|||
state->narSize += info->second.narSize;
|
||||
}
|
||||
|
||||
for (auto& ref : info->second.references)
|
||||
for (auto& ref : info->second.references) {
|
||||
pool.enqueue(std::bind(doPath, ref));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
|
@ -269,10 +287,11 @@ Paths Store::topoSortPaths(const PathSet& paths) {
|
|||
std::function<void(const Path& path, const Path* parent)> dfsVisit;
|
||||
|
||||
dfsVisit = [&](const Path& path, const Path* parent) {
|
||||
if (parents.find(path) != parents.end())
|
||||
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;
|
||||
|
|
@ -286,12 +305,13 @@ Paths Store::topoSortPaths(const PathSet& paths) {
|
|||
} catch (InvalidPath&) {
|
||||
}
|
||||
|
||||
for (auto& i : references)
|
||||
for (auto& i : references) {
|
||||
/* Don't traverse into paths that don't exist. That can
|
||||
happen due to substitutes for non-existent paths. */
|
||||
if (i != path && paths.find(i) != paths.end()) {
|
||||
dfsVisit(i, &path);
|
||||
}
|
||||
}
|
||||
|
||||
sorted.push_front(path);
|
||||
parents.erase(path);
|
||||
|
|
|
|||
25
third_party/nix/src/libstore/nar-accessor.cc
vendored
25
third_party/nix/src/libstore/nar-accessor.cc
vendored
|
|
@ -45,14 +45,17 @@ struct NarAccessor : public FSAccessor {
|
|||
|
||||
void createMember(const Path& path, NarMember member) {
|
||||
size_t level = std::count(path.begin(), path.end(), '/');
|
||||
while (parents.size() > level) parents.pop();
|
||||
while (parents.size() > level) {
|
||||
parents.pop();
|
||||
}
|
||||
|
||||
if (parents.empty()) {
|
||||
acc.root = std::move(member);
|
||||
parents.push(&acc.root);
|
||||
} else {
|
||||
if (parents.top()->type != FSAccessor::Type::tDirectory)
|
||||
if (parents.top()->type != FSAccessor::Type::tDirectory) {
|
||||
throw Error("NAR file missing parent directory of path '%s'", path);
|
||||
}
|
||||
auto result = parents.top()->children.emplace(baseNameOf(path),
|
||||
std::move(member));
|
||||
parents.push(&result.first->second);
|
||||
|
|
@ -118,8 +121,9 @@ struct NarAccessor : public FSAccessor {
|
|||
} else if (type == "symlink") {
|
||||
member.type = FSAccessor::Type::tSymlink;
|
||||
member.target = v.value("target", "");
|
||||
} else
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
};
|
||||
|
||||
json v = json::parse(listing);
|
||||
|
|
@ -157,8 +161,9 @@ struct NarAccessor : public FSAccessor {
|
|||
|
||||
NarMember& get(const Path& path) {
|
||||
auto result = find(path);
|
||||
if (result == nullptr)
|
||||
if (result == nullptr) {
|
||||
throw Error("NAR file does not contain path '%1%'", path);
|
||||
}
|
||||
return *result;
|
||||
}
|
||||
|
||||
|
|
@ -173,9 +178,10 @@ struct NarAccessor : public FSAccessor {
|
|||
StringSet readDirectory(const Path& path) override {
|
||||
auto i = get(path);
|
||||
|
||||
if (i.type != FSAccessor::Type::tDirectory)
|
||||
if (i.type != FSAccessor::Type::tDirectory) {
|
||||
throw Error(format("path '%1%' inside NAR file is not a directory") %
|
||||
path);
|
||||
}
|
||||
|
||||
StringSet res;
|
||||
for (auto& child : i.children) {
|
||||
|
|
@ -187,9 +193,10 @@ struct NarAccessor : public FSAccessor {
|
|||
|
||||
std::string readFile(const Path& path) override {
|
||||
auto i = get(path);
|
||||
if (i.type != FSAccessor::Type::tRegular)
|
||||
if (i.type != FSAccessor::Type::tRegular) {
|
||||
throw Error(format("path '%1%' inside NAR file is not a regular file") %
|
||||
path);
|
||||
}
|
||||
|
||||
if (getNarBytes) {
|
||||
return getNarBytes(i.start, i.size);
|
||||
|
|
@ -201,8 +208,9 @@ struct NarAccessor : public FSAccessor {
|
|||
|
||||
std::string readLink(const Path& path) override {
|
||||
auto i = get(path);
|
||||
if (i.type != FSAccessor::Type::tSymlink)
|
||||
if (i.type != FSAccessor::Type::tSymlink) {
|
||||
throw Error(format("path '%1%' inside NAR file is not a symlink") % path);
|
||||
}
|
||||
return i.target;
|
||||
}
|
||||
};
|
||||
|
|
@ -241,8 +249,9 @@ void listNar(JSONPlaceholder& res, ref<FSAccessor> accessor, const Path& path,
|
|||
if (recurse) {
|
||||
auto res3 = res2.placeholder(name);
|
||||
listNar(res3, accessor, path + "/" + name, true);
|
||||
} else
|
||||
} else {
|
||||
res2.object(name);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -76,8 +76,9 @@ class NarInfoDiskCacheImpl : public NarInfoDiskCache {
|
|||
|
||||
state->db = SQLite(dbPath);
|
||||
|
||||
if (sqlite3_busy_timeout(state->db, 60 * 60 * 1000) != SQLITE_OK)
|
||||
if (sqlite3_busy_timeout(state->db, 60 * 60 * 1000) != SQLITE_OK) {
|
||||
throwSQLiteError(state->db, "setting timeout");
|
||||
}
|
||||
|
||||
// We can always reproduce the cache.
|
||||
state->db.exec("pragma synchronous = off");
|
||||
|
|
@ -224,12 +225,15 @@ class NarInfoDiskCacheImpl : public NarInfoDiskCache {
|
|||
narInfo->fileSize = queryNAR.getInt(5);
|
||||
narInfo->narHash = Hash(queryNAR.getStr(6));
|
||||
narInfo->narSize = queryNAR.getInt(7);
|
||||
for (auto& r : tokenizeString<Strings>(queryNAR.getStr(8), " "))
|
||||
for (auto& r : tokenizeString<Strings>(queryNAR.getStr(8), " ")) {
|
||||
narInfo->references.insert(cache.storeDir + "/" + r);
|
||||
if (!queryNAR.isNull(9))
|
||||
}
|
||||
if (!queryNAR.isNull(9)) {
|
||||
narInfo->deriver = cache.storeDir + "/" + queryNAR.getStr(9);
|
||||
for (auto& sig : tokenizeString<Strings>(queryNAR.getStr(10), " "))
|
||||
}
|
||||
for (auto& sig : tokenizeString<Strings>(queryNAR.getStr(10), " ")) {
|
||||
narInfo->sigs.insert(sig);
|
||||
}
|
||||
narInfo->ca = queryNAR.getStr(11);
|
||||
|
||||
return {oValid, narInfo};
|
||||
|
|
|
|||
18
third_party/nix/src/libstore/nar-info.cc
vendored
18
third_party/nix/src/libstore/nar-info.cc
vendored
|
|
@ -40,19 +40,19 @@ NarInfo::NarInfo(const Store& store, const std::string& s,
|
|||
corrupt();
|
||||
}
|
||||
path = value;
|
||||
} else if (name == "URL")
|
||||
} else if (name == "URL") {
|
||||
url = value;
|
||||
else if (name == "Compression")
|
||||
} else if (name == "Compression") {
|
||||
compression = value;
|
||||
else if (name == "FileHash")
|
||||
} else if (name == "FileHash") {
|
||||
fileHash = parseHashField(value);
|
||||
else if (name == "FileSize") {
|
||||
} else if (name == "FileSize") {
|
||||
if (!string2Int(value, fileSize)) {
|
||||
corrupt();
|
||||
}
|
||||
} else if (name == "NarHash")
|
||||
} else if (name == "NarHash") {
|
||||
narHash = parseHashField(value);
|
||||
else if (name == "NarSize") {
|
||||
} else if (name == "NarSize") {
|
||||
if (!string2Int(value, narSize)) {
|
||||
corrupt();
|
||||
}
|
||||
|
|
@ -76,11 +76,11 @@ NarInfo::NarInfo(const Store& store, const std::string& s,
|
|||
}
|
||||
deriver = p;
|
||||
}
|
||||
} else if (name == "System")
|
||||
} else if (name == "System") {
|
||||
system = value;
|
||||
else if (name == "Sig")
|
||||
} else if (name == "Sig") {
|
||||
sigs.insert(value);
|
||||
else if (name == "CA") {
|
||||
} else if (name == "CA") {
|
||||
if (!ca.empty()) {
|
||||
corrupt();
|
||||
}
|
||||
|
|
|
|||
12
third_party/nix/src/libstore/optimise-store.cc
vendored
12
third_party/nix/src/libstore/optimise-store.cc
vendored
|
|
@ -17,10 +17,12 @@ namespace nix {
|
|||
|
||||
static void makeWritable(const Path& path) {
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
if (lstat(path.c_str(), &st)) {
|
||||
throw SysError(format("getting attributes of path '%1%'") % path);
|
||||
if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1)
|
||||
}
|
||||
if (chmod(path.c_str(), st.st_mode | S_IWUSR) == -1) {
|
||||
throw SysError(format("changing writability of '%1%'") % path);
|
||||
}
|
||||
}
|
||||
|
||||
struct MakeReadOnly {
|
||||
|
|
@ -98,8 +100,9 @@ void LocalStore::optimisePath_(OptimiseStats& stats, const Path& path,
|
|||
checkInterrupt();
|
||||
|
||||
struct stat st;
|
||||
if (lstat(path.c_str(), &st))
|
||||
if (lstat(path.c_str(), &st)) {
|
||||
throw SysError(format("getting attributes of path '%1%'") % path);
|
||||
}
|
||||
|
||||
#if __APPLE__
|
||||
/* HFS/macOS has some undocumented security feature disabling hardlinking for
|
||||
|
|
@ -192,8 +195,9 @@ retry:
|
|||
/* Yes! We've seen a file with the same contents. Replace the
|
||||
current file with a hard link to that file. */
|
||||
struct stat stLink;
|
||||
if (lstat(linkPath.c_str(), &stLink))
|
||||
if (lstat(linkPath.c_str(), &stLink)) {
|
||||
throw SysError(format("getting attributes of path '%1%'") % linkPath);
|
||||
}
|
||||
|
||||
if (st.st_ino == stLink.st_ino) {
|
||||
DLOG(INFO) << path << " is already linked to " << linkPath;
|
||||
|
|
|
|||
|
|
@ -20,40 +20,44 @@ std::optional<std::string> ParsedDerivation::getStringAttr(
|
|||
const std::string& name) const {
|
||||
if (structuredAttrs) {
|
||||
auto i = structuredAttrs->find(name);
|
||||
if (i == structuredAttrs->end())
|
||||
if (i == structuredAttrs->end()) {
|
||||
return {};
|
||||
else {
|
||||
if (!i->is_string())
|
||||
} else {
|
||||
if (!i->is_string()) {
|
||||
throw Error("attribute '%s' of derivation '%s' must be a string", name,
|
||||
drvPath);
|
||||
}
|
||||
return i->get<std::string>();
|
||||
}
|
||||
} else {
|
||||
auto i = drv.env.find(name);
|
||||
if (i == drv.env.end())
|
||||
if (i == drv.env.end()) {
|
||||
return {};
|
||||
else
|
||||
} else {
|
||||
return i->second;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool ParsedDerivation::getBoolAttr(const std::string& name, bool def) const {
|
||||
if (structuredAttrs) {
|
||||
auto i = structuredAttrs->find(name);
|
||||
if (i == structuredAttrs->end())
|
||||
if (i == structuredAttrs->end()) {
|
||||
return def;
|
||||
else {
|
||||
if (!i->is_boolean())
|
||||
} else {
|
||||
if (!i->is_boolean()) {
|
||||
throw Error("attribute '%s' of derivation '%s' must be a Boolean", name,
|
||||
drvPath);
|
||||
}
|
||||
return i->get<bool>();
|
||||
}
|
||||
} else {
|
||||
auto i = drv.env.find(name);
|
||||
if (i == drv.env.end())
|
||||
if (i == drv.env.end()) {
|
||||
return def;
|
||||
else
|
||||
} else {
|
||||
return i->second == "1";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -61,48 +65,54 @@ std::optional<Strings> ParsedDerivation::getStringsAttr(
|
|||
const std::string& name) const {
|
||||
if (structuredAttrs) {
|
||||
auto i = structuredAttrs->find(name);
|
||||
if (i == structuredAttrs->end())
|
||||
if (i == structuredAttrs->end()) {
|
||||
return {};
|
||||
else {
|
||||
if (!i->is_array())
|
||||
} else {
|
||||
if (!i->is_array()) {
|
||||
throw Error(
|
||||
"attribute '%s' of derivation '%s' must be a list of strings", name,
|
||||
drvPath);
|
||||
}
|
||||
Strings res;
|
||||
for (auto j = i->begin(); j != i->end(); ++j) {
|
||||
if (!j->is_string())
|
||||
if (!j->is_string()) {
|
||||
throw Error(
|
||||
"attribute '%s' of derivation '%s' must be a list of strings",
|
||||
name, drvPath);
|
||||
}
|
||||
res.push_back(j->get<std::string>());
|
||||
}
|
||||
return res;
|
||||
}
|
||||
} else {
|
||||
auto i = drv.env.find(name);
|
||||
if (i == drv.env.end())
|
||||
if (i == drv.env.end()) {
|
||||
return {};
|
||||
else
|
||||
} else {
|
||||
return tokenizeString<Strings>(i->second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
StringSet ParsedDerivation::getRequiredSystemFeatures() const {
|
||||
StringSet res;
|
||||
for (auto& i : getStringsAttr("requiredSystemFeatures").value_or(Strings()))
|
||||
for (auto& i : getStringsAttr("requiredSystemFeatures").value_or(Strings())) {
|
||||
res.insert(i);
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
bool ParsedDerivation::canBuildLocally() const {
|
||||
if (drv.platform != settings.thisSystem.get() &&
|
||||
!settings.extraPlatforms.get().count(drv.platform) && !drv.isBuiltin())
|
||||
!settings.extraPlatforms.get().count(drv.platform) && !drv.isBuiltin()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
for (auto& feature : getRequiredSystemFeatures())
|
||||
for (auto& feature : getRequiredSystemFeatures()) {
|
||||
if (!settings.systemFeatures.get().count(feature)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
|
|
|||
25
third_party/nix/src/libstore/pathlocks.cc
vendored
25
third_party/nix/src/libstore/pathlocks.cc
vendored
|
|
@ -18,8 +18,9 @@ AutoCloseFD openLockFile(const Path& path, bool create) {
|
|||
AutoCloseFD fd;
|
||||
|
||||
fd = open(path.c_str(), O_CLOEXEC | O_RDWR | (create ? O_CREAT : 0), 0600);
|
||||
if (!fd && (create || errno != ENOENT))
|
||||
if (!fd && (create || errno != ENOENT)) {
|
||||
throw SysError(format("opening lock file '%1%'") % path);
|
||||
}
|
||||
|
||||
return fd;
|
||||
}
|
||||
|
|
@ -37,22 +38,24 @@ void deleteLockFile(const Path& path, int fd) {
|
|||
|
||||
bool lockFile(int fd, LockType lockType, bool wait) {
|
||||
int type;
|
||||
if (lockType == ltRead)
|
||||
if (lockType == ltRead) {
|
||||
type = LOCK_SH;
|
||||
else if (lockType == ltWrite)
|
||||
} else if (lockType == ltWrite) {
|
||||
type = LOCK_EX;
|
||||
else if (lockType == ltNone)
|
||||
} else if (lockType == ltNone) {
|
||||
type = LOCK_UN;
|
||||
else
|
||||
} else {
|
||||
abort();
|
||||
}
|
||||
|
||||
if (wait) {
|
||||
while (flock(fd, type) != 0) {
|
||||
checkInterrupt();
|
||||
if (errno != EINTR)
|
||||
if (errno != EINTR) {
|
||||
throw SysError(format("acquiring/releasing lock"));
|
||||
else
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
while (flock(fd, type | LOCK_NB) != 0) {
|
||||
|
|
@ -118,16 +121,18 @@ bool PathLocks::lockPaths(const PathSet& paths, const string& waitMsg,
|
|||
/* Check that the lock file hasn't become stale (i.e.,
|
||||
hasn't been unlinked). */
|
||||
struct stat st;
|
||||
if (fstat(fd.get(), &st) == -1)
|
||||
if (fstat(fd.get(), &st) == -1) {
|
||||
throw SysError(format("statting lock file '%1%'") % lockPath);
|
||||
if (st.st_size != 0)
|
||||
}
|
||||
if (st.st_size != 0) {
|
||||
/* This lock file has been unlinked, so we're holding
|
||||
a lock on a deleted file. This means that other
|
||||
processes may create and acquire a lock on
|
||||
`lockPath', and proceed. So we must retry. */
|
||||
DLOG(INFO) << "open lock file '" << lockPath << "' has become stale";
|
||||
else
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Use borrow so that the descriptor isn't closed. */
|
||||
|
|
|
|||
23
third_party/nix/src/libstore/profiles.cc
vendored
23
third_party/nix/src/libstore/profiles.cc
vendored
|
|
@ -28,10 +28,11 @@ static int parseName(const string& profileName, const string& name) {
|
|||
return -1;
|
||||
}
|
||||
int n;
|
||||
if (string2Int(string(s, 0, p), n) && n >= 0)
|
||||
if (string2Int(string(s, 0, p), n) && n >= 0) {
|
||||
return n;
|
||||
else
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
Generations findGenerations(Path profile, int& curGen) {
|
||||
|
|
@ -47,8 +48,9 @@ Generations findGenerations(Path profile, int& curGen) {
|
|||
gen.path = profileDir + "/" + i.name;
|
||||
gen.number = n;
|
||||
struct stat st;
|
||||
if (lstat(gen.path.c_str(), &st) != 0)
|
||||
if (lstat(gen.path.c_str(), &st) != 0) {
|
||||
throw SysError(format("statting '%1%'") % gen.path);
|
||||
}
|
||||
gen.creationTime = st.st_mtime;
|
||||
gens.push_back(gen);
|
||||
}
|
||||
|
|
@ -105,8 +107,9 @@ Path createGeneration(ref<LocalFSStore> store, Path profile, Path outPath) {
|
|||
}
|
||||
|
||||
static void removeFile(const Path& path) {
|
||||
if (remove(path.c_str()) == -1)
|
||||
if (remove(path.c_str()) == -1) {
|
||||
throw SysError(format("cannot unlink '%1%'") % path);
|
||||
}
|
||||
}
|
||||
|
||||
void deleteGeneration(const Path& profile, unsigned int gen) {
|
||||
|
|
@ -134,9 +137,10 @@ void deleteGenerations(const Path& profile,
|
|||
int curGen;
|
||||
Generations gens = findGenerations(profile, curGen);
|
||||
|
||||
if (gensToDelete.find(curGen) != gensToDelete.end())
|
||||
if (gensToDelete.find(curGen) != gensToDelete.end()) {
|
||||
throw Error(format("cannot delete current generation of profile %1%'") %
|
||||
profile);
|
||||
}
|
||||
|
||||
for (auto& i : gens) {
|
||||
if (gensToDelete.find(i.number) == gensToDelete.end()) {
|
||||
|
|
@ -176,10 +180,11 @@ void deleteOldGenerations(const Path& profile, bool dryRun) {
|
|||
int curGen;
|
||||
Generations gens = findGenerations(profile, curGen);
|
||||
|
||||
for (auto& i : gens)
|
||||
for (auto& i : gens) {
|
||||
if (i.number != curGen) {
|
||||
deleteGeneration2(profile, i.number, dryRun);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deleteGenerationsOlderThan(const Path& profile, time_t t, bool dryRun) {
|
||||
|
|
@ -190,7 +195,7 @@ void deleteGenerationsOlderThan(const Path& profile, time_t t, bool dryRun) {
|
|||
Generations gens = findGenerations(profile, curGen);
|
||||
|
||||
bool canDelete = false;
|
||||
for (auto i = gens.rbegin(); i != gens.rend(); ++i)
|
||||
for (auto i = gens.rbegin(); i != gens.rend(); ++i) {
|
||||
if (canDelete) {
|
||||
assert(i->creationTime < t);
|
||||
if (i->number != curGen) {
|
||||
|
|
@ -203,6 +208,7 @@ void deleteGenerationsOlderThan(const Path& profile, time_t t, bool dryRun) {
|
|||
time. */
|
||||
canDelete = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void deleteGenerationsOlderThan(const Path& profile, const string& timeSpec,
|
||||
|
|
@ -211,8 +217,9 @@ void deleteGenerationsOlderThan(const Path& profile, const string& timeSpec,
|
|||
string strDays = string(timeSpec, 0, timeSpec.size() - 1);
|
||||
int days;
|
||||
|
||||
if (!string2Int(strDays, days) || days < 1)
|
||||
if (!string2Int(strDays, days) || days < 1) {
|
||||
throw Error(format("invalid number of days specifier '%1%'") % timeSpec);
|
||||
}
|
||||
|
||||
time_t oldTime = curTime - days * 24 * 3600;
|
||||
|
||||
|
|
|
|||
6
third_party/nix/src/libstore/references.cc
vendored
6
third_party/nix/src/libstore/references.cc
vendored
|
|
@ -21,20 +21,22 @@ static void search(const unsigned char* s, size_t len, StringSet& hashes,
|
|||
for (unsigned int i = 0; i < 256; ++i) {
|
||||
isBase32[i] = false;
|
||||
}
|
||||
for (unsigned int i = 0; i < base32Chars.size(); ++i)
|
||||
for (unsigned int i = 0; i < base32Chars.size(); ++i) {
|
||||
isBase32[(unsigned char)base32Chars[i]] = true;
|
||||
}
|
||||
initialised = true;
|
||||
}
|
||||
|
||||
for (size_t i = 0; i + refLength <= len;) {
|
||||
int j;
|
||||
bool match = true;
|
||||
for (j = refLength - 1; j >= 0; --j)
|
||||
for (j = refLength - 1; j >= 0; --j) {
|
||||
if (!isBase32[(unsigned char)s[i + j]]) {
|
||||
i += j + 1;
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!match) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -48,9 +48,10 @@ std::pair<ref<FSAccessor>, Path> RemoteFSAccessor::fetch(const Path& path_) {
|
|||
auto storePath = store->toStorePath(path);
|
||||
std::string restPath = std::string(path, storePath.size());
|
||||
|
||||
if (!store->isValidPath(storePath))
|
||||
if (!store->isValidPath(storePath)) {
|
||||
throw InvalidPath(format("path '%1%' is not a valid store path") %
|
||||
storePath);
|
||||
}
|
||||
|
||||
auto i = nars.find(storePath);
|
||||
if (i != nars.end()) {
|
||||
|
|
@ -73,8 +74,9 @@ std::pair<ref<FSAccessor>, Path> RemoteFSAccessor::fetch(const Path& path_) {
|
|||
throw SysError("opening NAR cache file '%s'", cacheFile);
|
||||
}
|
||||
|
||||
if (lseek(fd.get(), offset, SEEK_SET) != (off_t)offset)
|
||||
if (lseek(fd.get(), offset, SEEK_SET) != (off_t)offset) {
|
||||
throw SysError("seeking in '%s'", cacheFile);
|
||||
}
|
||||
|
||||
std::string buf(length, 0);
|
||||
readFull(fd.get(), (unsigned char*)buf.data(), length);
|
||||
|
|
|
|||
43
third_party/nix/src/libstore/remote-store.cc
vendored
43
third_party/nix/src/libstore/remote-store.cc
vendored
|
|
@ -57,9 +57,10 @@ RemoteStore::RemoteStore(const Params& params)
|
|||
})) {}
|
||||
|
||||
ref<RemoteStore::Connection> RemoteStore::openConnectionWrapper() {
|
||||
if (failed)
|
||||
if (failed) {
|
||||
throw Error("opening a connection to remote store '%s' previously failed",
|
||||
getUri());
|
||||
}
|
||||
try {
|
||||
return openConnection();
|
||||
} catch (...) {
|
||||
|
|
@ -105,12 +106,14 @@ ref<RemoteStore::Connection> UDSRemoteStore::openConnection() {
|
|||
|
||||
struct sockaddr_un addr;
|
||||
addr.sun_family = AF_UNIX;
|
||||
if (socketPath.size() + 1 >= sizeof(addr.sun_path))
|
||||
if (socketPath.size() + 1 >= sizeof(addr.sun_path)) {
|
||||
throw Error(format("socket path '%1%' is too long") % socketPath);
|
||||
}
|
||||
strcpy(addr.sun_path, socketPath.c_str());
|
||||
|
||||
if (::connect(conn->fd.get(), (struct sockaddr*)&addr, sizeof(addr)) == -1)
|
||||
if (::connect(conn->fd.get(), (struct sockaddr*)&addr, sizeof(addr)) == -1) {
|
||||
throw SysError(format("cannot connect to daemon at '%1%'") % socketPath);
|
||||
}
|
||||
|
||||
conn->from.fd = conn->fd.get();
|
||||
conn->to.fd = conn->fd.get();
|
||||
|
|
@ -134,18 +137,21 @@ void RemoteStore::initConnection(Connection& conn) {
|
|||
|
||||
conn.from >> conn.daemonVersion;
|
||||
if (GET_PROTOCOL_MAJOR(conn.daemonVersion) !=
|
||||
GET_PROTOCOL_MAJOR(PROTOCOL_VERSION))
|
||||
GET_PROTOCOL_MAJOR(PROTOCOL_VERSION)) {
|
||||
throw Error("Nix daemon protocol version not supported");
|
||||
if (GET_PROTOCOL_MINOR(conn.daemonVersion) < 10)
|
||||
}
|
||||
if (GET_PROTOCOL_MINOR(conn.daemonVersion) < 10) {
|
||||
throw Error("the Nix daemon version is too old");
|
||||
}
|
||||
conn.to << PROTOCOL_VERSION;
|
||||
|
||||
if (GET_PROTOCOL_MINOR(conn.daemonVersion) >= 14) {
|
||||
int cpu = sameMachine() && settings.lockCPU ? lockToCurrentCPU() : -1;
|
||||
if (cpu != -1)
|
||||
if (cpu != -1) {
|
||||
conn.to << 1 << cpu;
|
||||
else
|
||||
} else {
|
||||
conn.to << 0;
|
||||
}
|
||||
}
|
||||
|
||||
if (GET_PROTOCOL_MINOR(conn.daemonVersion) >= 11) {
|
||||
|
|
@ -249,10 +255,11 @@ PathSet RemoteStore::queryValidPaths(const PathSet& paths,
|
|||
auto conn(getConnection());
|
||||
if (GET_PROTOCOL_MINOR(conn->daemonVersion) < 12) {
|
||||
PathSet res;
|
||||
for (auto& i : paths)
|
||||
for (auto& i : paths) {
|
||||
if (isValidPath(i)) {
|
||||
res.insert(i);
|
||||
}
|
||||
}
|
||||
return res;
|
||||
} else {
|
||||
conn->to << wopQueryValidPaths << paths;
|
||||
|
|
@ -344,8 +351,9 @@ void RemoteStore::queryPathInfoUncached(
|
|||
conn.processStderr();
|
||||
} catch (Error& e) {
|
||||
// Ugly backwards compatibility hack.
|
||||
if (e.msg().find("is not valid") != std::string::npos)
|
||||
if (e.msg().find("is not valid") != std::string::npos) {
|
||||
throw InvalidPath(e.what());
|
||||
}
|
||||
throw;
|
||||
}
|
||||
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 17) {
|
||||
|
|
@ -456,9 +464,10 @@ void RemoteStore::addToStore(const ValidPathInfo& info, Source& source,
|
|||
Path RemoteStore::addToStore(const string& name, const Path& _srcPath,
|
||||
bool recursive, HashType hashAlgo,
|
||||
PathFilter& filter, RepairFlag repair) {
|
||||
if (repair)
|
||||
if (repair) {
|
||||
throw Error(
|
||||
"repairing is not supported when building through the Nix daemon");
|
||||
}
|
||||
|
||||
auto conn(getConnection());
|
||||
|
||||
|
|
@ -483,10 +492,12 @@ Path RemoteStore::addToStore(const string& name, const Path& _srcPath,
|
|||
} catch (SysError& e) {
|
||||
/* Daemon closed while we were sending the path. Probably OOM
|
||||
or I/O error. */
|
||||
if (e.errNo == EPIPE) try {
|
||||
if (e.errNo == EPIPE) {
|
||||
try {
|
||||
conn.processStderr();
|
||||
} catch (EndOfFile& e) {
|
||||
}
|
||||
}
|
||||
throw;
|
||||
}
|
||||
|
||||
|
|
@ -495,9 +506,10 @@ Path RemoteStore::addToStore(const string& name, const Path& _srcPath,
|
|||
|
||||
Path RemoteStore::addTextToStore(const string& name, const string& s,
|
||||
const PathSet& references, RepairFlag repair) {
|
||||
if (repair)
|
||||
if (repair) {
|
||||
throw Error(
|
||||
"repairing is not supported when building through the Nix daemon");
|
||||
}
|
||||
|
||||
auto conn(getConnection());
|
||||
conn->to << wopAddTextToStore << name << s << references;
|
||||
|
|
@ -511,15 +523,16 @@ void RemoteStore::buildPaths(const PathSet& drvPaths, BuildMode buildMode) {
|
|||
conn->to << wopBuildPaths;
|
||||
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 13) {
|
||||
conn->to << drvPaths;
|
||||
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 15)
|
||||
if (GET_PROTOCOL_MINOR(conn->daemonVersion) >= 15) {
|
||||
conn->to << buildMode;
|
||||
else
|
||||
} else
|
||||
/* Old daemons did not take a 'buildMode' parameter, so we
|
||||
need to validate it here on the client side. */
|
||||
if (buildMode != bmNormal)
|
||||
if (buildMode != bmNormal) {
|
||||
throw Error(
|
||||
"repairing or checking is not supported when building through the "
|
||||
"Nix daemon");
|
||||
}
|
||||
} else {
|
||||
/* For backwards compatibility with old daemons, strip output
|
||||
identifiers. */
|
||||
|
|
|
|||
24
third_party/nix/src/libstore/sqlite.cc
vendored
24
third_party/nix/src/libstore/sqlite.cc
vendored
|
|
@ -31,8 +31,9 @@ namespace nix {
|
|||
SQLite::SQLite(const Path& path) {
|
||||
if (sqlite3_open_v2(path.c_str(), &db,
|
||||
SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE,
|
||||
0) != SQLITE_OK)
|
||||
0) != SQLITE_OK) {
|
||||
throw Error(format("cannot open SQLite database '%s'") % path);
|
||||
}
|
||||
}
|
||||
|
||||
SQLite::~SQLite() {
|
||||
|
|
@ -47,24 +48,27 @@ SQLite::~SQLite() {
|
|||
|
||||
void SQLite::exec(const std::string& stmt) {
|
||||
retrySQLite<void>([&]() {
|
||||
if (sqlite3_exec(db, stmt.c_str(), 0, 0, 0) != SQLITE_OK)
|
||||
if (sqlite3_exec(db, stmt.c_str(), 0, 0, 0) != SQLITE_OK) {
|
||||
throwSQLiteError(db, format("executing SQLite statement '%s'") % stmt);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void SQLiteStmt::create(sqlite3* db, const string& sql) {
|
||||
checkInterrupt();
|
||||
assert(!stmt);
|
||||
if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, 0) != SQLITE_OK)
|
||||
if (sqlite3_prepare_v2(db, sql.c_str(), -1, &stmt, 0) != SQLITE_OK) {
|
||||
throwSQLiteError(db, fmt("creating statement '%s'", sql));
|
||||
}
|
||||
this->db = db;
|
||||
this->sql = sql;
|
||||
}
|
||||
|
||||
SQLiteStmt::~SQLiteStmt() {
|
||||
try {
|
||||
if (stmt && sqlite3_finalize(stmt) != SQLITE_OK)
|
||||
if (stmt && sqlite3_finalize(stmt) != SQLITE_OK) {
|
||||
throwSQLiteError(db, fmt("finalizing statement '%s'", sql));
|
||||
}
|
||||
} catch (...) {
|
||||
ignoreException();
|
||||
}
|
||||
|
|
@ -83,8 +87,9 @@ SQLiteStmt::Use& SQLiteStmt::Use::operator()(const std::string& value,
|
|||
bool notNull) {
|
||||
if (notNull) {
|
||||
if (sqlite3_bind_text(stmt, curArg++, value.c_str(), -1,
|
||||
SQLITE_TRANSIENT) != SQLITE_OK)
|
||||
SQLITE_TRANSIENT) != SQLITE_OK) {
|
||||
throwSQLiteError(stmt.db, "binding argument");
|
||||
}
|
||||
} else {
|
||||
bind();
|
||||
}
|
||||
|
|
@ -93,8 +98,9 @@ SQLiteStmt::Use& SQLiteStmt::Use::operator()(const std::string& value,
|
|||
|
||||
SQLiteStmt::Use& SQLiteStmt::Use::operator()(int64_t value, bool notNull) {
|
||||
if (notNull) {
|
||||
if (sqlite3_bind_int64(stmt, curArg++, value) != SQLITE_OK)
|
||||
if (sqlite3_bind_int64(stmt, curArg++, value) != SQLITE_OK) {
|
||||
throwSQLiteError(stmt.db, "binding argument");
|
||||
}
|
||||
} else {
|
||||
bind();
|
||||
}
|
||||
|
|
@ -113,14 +119,16 @@ int SQLiteStmt::Use::step() { return sqlite3_step(stmt); }
|
|||
void SQLiteStmt::Use::exec() {
|
||||
int r = step();
|
||||
assert(r != SQLITE_ROW);
|
||||
if (r != SQLITE_DONE)
|
||||
if (r != SQLITE_DONE) {
|
||||
throwSQLiteError(stmt.db, fmt("executing SQLite statement '%s'", stmt.sql));
|
||||
}
|
||||
}
|
||||
|
||||
bool SQLiteStmt::Use::next() {
|
||||
int r = step();
|
||||
if (r != SQLITE_DONE && r != SQLITE_ROW)
|
||||
if (r != SQLITE_DONE && r != SQLITE_ROW) {
|
||||
throwSQLiteError(stmt.db, fmt("executing SQLite query '%s'", stmt.sql));
|
||||
}
|
||||
return r == SQLITE_ROW;
|
||||
}
|
||||
|
||||
|
|
|
|||
21
third_party/nix/src/libstore/ssh.cc
vendored
21
third_party/nix/src/libstore/ssh.cc
vendored
|
|
@ -10,13 +10,15 @@ SSHMaster::SSHMaster(const std::string& host, const std::string& keyFile,
|
|||
useMaster(useMaster && !fakeSSH),
|
||||
compress(compress),
|
||||
logFD(logFD) {
|
||||
if (host == "" || hasPrefix(host, "-"))
|
||||
if (host == "" || hasPrefix(host, "-")) {
|
||||
throw Error("invalid SSH host name '%s'", host);
|
||||
}
|
||||
}
|
||||
|
||||
void SSHMaster::addCommonSSHOpts(Strings& args) {
|
||||
for (auto& i : tokenizeString<Strings>(getEnv("NIX_SSHOPTS")))
|
||||
for (auto& i : tokenizeString<Strings>(getEnv("NIX_SSHOPTS"))) {
|
||||
args.push_back(i);
|
||||
}
|
||||
if (!keyFile.empty()) {
|
||||
args.insert(args.end(), {"-i", keyFile});
|
||||
}
|
||||
|
|
@ -44,12 +46,15 @@ std::unique_ptr<SSHMaster::Connection> SSHMaster::startCommand(
|
|||
close(in.writeSide.get());
|
||||
close(out.readSide.get());
|
||||
|
||||
if (dup2(in.readSide.get(), STDIN_FILENO) == -1)
|
||||
if (dup2(in.readSide.get(), STDIN_FILENO) == -1) {
|
||||
throw SysError("duping over stdin");
|
||||
if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
|
||||
}
|
||||
if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1) {
|
||||
throw SysError("duping over stdout");
|
||||
if (logFD != -1 && dup2(logFD, STDERR_FILENO) == -1)
|
||||
}
|
||||
if (logFD != -1 && dup2(logFD, STDERR_FILENO) == -1) {
|
||||
throw SysError("duping over stderr");
|
||||
}
|
||||
|
||||
Strings args;
|
||||
|
||||
|
|
@ -112,8 +117,9 @@ Path SSHMaster::startMaster() {
|
|||
|
||||
close(out.readSide.get());
|
||||
|
||||
if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1)
|
||||
if (dup2(out.writeSide.get(), STDOUT_FILENO) == -1) {
|
||||
throw SysError("duping over stdout");
|
||||
}
|
||||
|
||||
Strings args = {"ssh", host.c_str(),
|
||||
"-M", "-N",
|
||||
|
|
@ -136,8 +142,9 @@ Path SSHMaster::startMaster() {
|
|||
} catch (EndOfFile& e) {
|
||||
}
|
||||
|
||||
if (reply != "started")
|
||||
if (reply != "started") {
|
||||
throw Error("failed to start SSH master connection to '%s'", host);
|
||||
}
|
||||
|
||||
return state->socketPath;
|
||||
}
|
||||
|
|
|
|||
76
third_party/nix/src/libstore/store-api.cc
vendored
76
third_party/nix/src/libstore/store-api.cc
vendored
|
|
@ -25,18 +25,21 @@ bool Store::isStorePath(const Path& path) const {
|
|||
}
|
||||
|
||||
void Store::assertStorePath(const Path& path) const {
|
||||
if (!isStorePath(path))
|
||||
if (!isStorePath(path)) {
|
||||
throw Error(format("path '%1%' is not in the Nix store") % path);
|
||||
}
|
||||
}
|
||||
|
||||
Path Store::toStorePath(const Path& path) const {
|
||||
if (!isInStore(path))
|
||||
if (!isInStore(path)) {
|
||||
throw Error(format("path '%1%' is not in the Nix store") % path);
|
||||
}
|
||||
Path::size_type slash = path.find('/', storeDir.size() + 1);
|
||||
if (slash == Path::npos)
|
||||
if (slash == Path::npos) {
|
||||
return path;
|
||||
else
|
||||
} else {
|
||||
return Path(path, 0, slash);
|
||||
}
|
||||
}
|
||||
|
||||
Path Store::followLinksToStore(const Path& _path) const {
|
||||
|
|
@ -48,8 +51,9 @@ Path Store::followLinksToStore(const Path& _path) const {
|
|||
string target = readLink(path);
|
||||
path = absPath(target, dirOf(path));
|
||||
}
|
||||
if (!isInStore(path))
|
||||
if (!isInStore(path)) {
|
||||
throw Error(format("path '%1%' is not in the Nix store") % path);
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
|
|
@ -86,17 +90,20 @@ void checkStoreName(const string& name) {
|
|||
|
||||
/* Disallow names starting with a dot for possible security
|
||||
reasons (e.g., "." and ".."). */
|
||||
if (string(name, 0, 1) == ".")
|
||||
if (string(name, 0, 1) == ".") {
|
||||
throw Error(baseError % "it is illegal to start the name with a period");
|
||||
}
|
||||
/* Disallow names longer than 211 characters. ext4’s max is 256,
|
||||
but we need extra space for the hash and .chroot extensions. */
|
||||
if (name.length() > 211)
|
||||
if (name.length() > 211) {
|
||||
throw Error(baseError % "name must be less than 212 characters");
|
||||
for (auto& i : name)
|
||||
}
|
||||
for (auto& i : name) {
|
||||
if (!((i >= 'A' && i <= 'Z') || (i >= 'a' && i <= 'z') ||
|
||||
(i >= '0' && i <= '9') || validChars.find(i) != string::npos)) {
|
||||
throw Error(baseError % (format("the '%1%' character is invalid") % i));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* Store paths have the following form:
|
||||
|
|
@ -261,9 +268,10 @@ bool Store::isValidPath(const Path& storePath) {
|
|||
|
||||
bool valid = isValidPathUncached(storePath);
|
||||
|
||||
if (diskCache && !valid)
|
||||
if (diskCache && !valid) {
|
||||
// FIXME: handle valid = true case.
|
||||
diskCache->upsertNarInfo(getUri(), hashPart, 0);
|
||||
}
|
||||
|
||||
return valid;
|
||||
}
|
||||
|
|
@ -306,8 +314,9 @@ void Store::queryPathInfo(const Path& storePath,
|
|||
auto res = state.lock()->pathInfoCache.get(hashPart);
|
||||
if (res) {
|
||||
stats.narInfoReadAverted++;
|
||||
if (!*res)
|
||||
if (!*res) {
|
||||
throw InvalidPath(format("path '%s' is not valid") % storePath);
|
||||
}
|
||||
return callback(ref<ValidPathInfo>(*res));
|
||||
}
|
||||
}
|
||||
|
|
@ -323,8 +332,9 @@ void Store::queryPathInfo(const Path& storePath,
|
|||
res.first == NarInfoDiskCache::oInvalid ? 0 : res.second);
|
||||
if (res.first == NarInfoDiskCache::oInvalid ||
|
||||
(res.second->path != storePath &&
|
||||
storePathToName(storePath) != ""))
|
||||
storePathToName(storePath) != "")) {
|
||||
throw InvalidPath(format("path '%s' is not valid") % storePath);
|
||||
}
|
||||
}
|
||||
return callback(ref<ValidPathInfo>(res.second));
|
||||
}
|
||||
|
|
@ -483,8 +493,9 @@ void Store::pathInfoToJSON(JSONPlaceholder& jsonOut, const PathSet& storePaths,
|
|||
jsonPath.attr("deriver", info->deriver);
|
||||
}
|
||||
|
||||
if (info->registrationTime)
|
||||
if (info->registrationTime) {
|
||||
jsonPath.attr("registrationTime", info->registrationTime);
|
||||
}
|
||||
|
||||
if (info->ultimate) {
|
||||
jsonPath.attr("ultimate", info->ultimate);
|
||||
|
|
@ -504,12 +515,15 @@ void Store::pathInfoToJSON(JSONPlaceholder& jsonOut, const PathSet& storePaths,
|
|||
if (!narInfo->url.empty()) {
|
||||
jsonPath.attr("url", narInfo->url);
|
||||
}
|
||||
if (narInfo->fileHash)
|
||||
if (narInfo->fileHash) {
|
||||
jsonPath.attr("downloadHash", narInfo->fileHash.to_string());
|
||||
if (narInfo->fileSize)
|
||||
}
|
||||
if (narInfo->fileSize) {
|
||||
jsonPath.attr("downloadSize", narInfo->fileSize);
|
||||
if (showClosureSize)
|
||||
}
|
||||
if (showClosureSize) {
|
||||
jsonPath.attr("closureDownloadSize", closureSizes.second);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -544,10 +558,11 @@ const Store::Stats& Store::getStats() {
|
|||
}
|
||||
|
||||
void Store::buildPaths(const PathSet& paths, BuildMode buildMode) {
|
||||
for (auto& path : paths)
|
||||
for (auto& path : paths) {
|
||||
if (isDerivation(path)) {
|
||||
unsupported("buildPaths");
|
||||
}
|
||||
}
|
||||
|
||||
if (queryValidPaths(paths).size() != paths.size()) {
|
||||
unsupported("buildPaths");
|
||||
|
|
@ -621,10 +636,11 @@ void copyPaths(ref<Store> srcStore, ref<Store> dstStore,
|
|||
PathSet valid = dstStore->queryValidPaths(storePaths, substitute);
|
||||
|
||||
PathSet missing;
|
||||
for (auto& path : storePaths)
|
||||
for (auto& path : storePaths) {
|
||||
if (!valid.count(path)) {
|
||||
missing.insert(path);
|
||||
}
|
||||
}
|
||||
|
||||
if (missing.empty()) {
|
||||
return;
|
||||
|
|
@ -729,10 +745,11 @@ string showPaths(const PathSet& paths) {
|
|||
}
|
||||
|
||||
std::string ValidPathInfo::fingerprint() const {
|
||||
if (narSize == 0 || !narHash)
|
||||
if (narSize == 0 || !narHash) {
|
||||
throw Error(format("cannot calculate fingerprint of path '%s' because its "
|
||||
"size/hash is not known") %
|
||||
path);
|
||||
}
|
||||
return "1;" + path + ";" + narHash.to_string(Base32) + ";" +
|
||||
std::to_string(narSize) + ";" + concatStringsSep(",", references);
|
||||
}
|
||||
|
|
@ -749,10 +766,11 @@ bool ValidPathInfo::isContentAddressed(const Store& store) const {
|
|||
|
||||
if (hasPrefix(ca, "text:")) {
|
||||
Hash hash(std::string(ca, 5));
|
||||
if (store.makeTextPath(storePathToName(path), hash, references) == path)
|
||||
if (store.makeTextPath(storePathToName(path), hash, references) == path) {
|
||||
return true;
|
||||
else
|
||||
} else {
|
||||
warn();
|
||||
}
|
||||
}
|
||||
|
||||
else if (hasPrefix(ca, "fixed:")) {
|
||||
|
|
@ -760,10 +778,11 @@ bool ValidPathInfo::isContentAddressed(const Store& store) const {
|
|||
Hash hash(std::string(ca, recursive ? 8 : 6));
|
||||
if (references.empty() &&
|
||||
store.makeFixedOutputPath(recursive, hash, storePathToName(path)) ==
|
||||
path)
|
||||
path) {
|
||||
return true;
|
||||
else
|
||||
} else {
|
||||
warn();
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
|
|
@ -776,10 +795,11 @@ size_t ValidPathInfo::checkSignatures(const Store& store,
|
|||
}
|
||||
|
||||
size_t good = 0;
|
||||
for (auto& sig : sigs)
|
||||
for (auto& sig : sigs) {
|
||||
if (checkSignature(publicKeys, sig)) {
|
||||
good++;
|
||||
}
|
||||
}
|
||||
return good;
|
||||
}
|
||||
|
||||
|
|
@ -838,16 +858,18 @@ std::pair<std::string, Store::Params> splitUriAndParams(
|
|||
std::string decoded;
|
||||
for (size_t i = 0; i < value.size();) {
|
||||
if (value[i] == '%') {
|
||||
if (i + 2 >= value.size())
|
||||
if (i + 2 >= value.size()) {
|
||||
throw Error("invalid URI parameter '%s'", value);
|
||||
}
|
||||
try {
|
||||
decoded += std::stoul(std::string(value, i + 1, 2), 0, 16);
|
||||
i += 3;
|
||||
} catch (...) {
|
||||
throw Error("invalid URI parameter '%s'", value);
|
||||
}
|
||||
} else
|
||||
} else {
|
||||
decoded += value[i++];
|
||||
}
|
||||
}
|
||||
params[s.substr(0, e)] = decoded;
|
||||
}
|
||||
|
|
@ -880,9 +902,9 @@ StoreType getStoreType(const std::string& uri, const std::string& stateDir) {
|
|||
} else if (uri == "local" || hasPrefix(uri, "/")) {
|
||||
return tLocal;
|
||||
} else if (uri == "" || uri == "auto") {
|
||||
if (access(stateDir.c_str(), R_OK | W_OK) == 0)
|
||||
if (access(stateDir.c_str(), R_OK | W_OK) == 0) {
|
||||
return tLocal;
|
||||
else if (pathExists(settings.nixDaemonSocketFile)) {
|
||||
} else if (pathExists(settings.nixDaemonSocketFile)) {
|
||||
return tDaemon;
|
||||
} else {
|
||||
return tLocal;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue