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