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:
Vincent Ambo 2020-05-19 20:47:23 +01:00
parent cf40d08908
commit 3908732181
84 changed files with 2601 additions and 1554 deletions

View file

@ -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

File diff suppressed because it is too large Load diff

View file

@ -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
}

View file

@ -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, ",[");

View file

@ -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) {

View file

@ -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;

View file

@ -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();

View file

@ -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());
}
}
}

View file

@ -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",

View file

@ -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;

View file

@ -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;
}

View file

@ -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();

View file

@ -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

View file

@ -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);
}
}
}

View file

@ -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);

View file

@ -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;

View file

@ -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};

View file

@ -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();
}

View file

@ -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;

View file

@ -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;
}

View file

@ -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. */

View file

@ -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;

View file

@ -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;
}

View file

@ -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);

View file

@ -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. */

View file

@ -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;
}

View file

@ -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;
}

View file

@ -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. ext4s 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;