aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libstore/build/local-derivation-goal.cc24
-rw-r--r--src/libstore/builtins/buildenv.cc18
-rw-r--r--src/libutil/util.cc20
-rw-r--r--src/libutil/util.hh6
4 files changed, 38 insertions, 30 deletions
diff --git a/src/libstore/build/local-derivation-goal.cc b/src/libstore/build/local-derivation-goal.cc
index 0709dcbcb..c373ed27f 100644
--- a/src/libstore/build/local-derivation-goal.cc
+++ b/src/libstore/build/local-derivation-goal.cc
@@ -2044,13 +2044,13 @@ void LocalDerivationGoal::runChild()
i.first, i.second.source);
std::string path = i.first;
- struct stat st;
- if (lstat(path.c_str(), &st)) {
- if (i.second.optional && errno == ENOENT)
+ auto optSt = maybeLstat(path.c_str());
+ if (!optSt) {
+ if (i.second.optional)
continue;
- throw SysError("getting attributes of path '%s", path);
+ throw SysError("getting attributes of required path '%s", path);
}
- if (S_ISDIR(st.st_mode))
+ if (S_ISDIR(optSt->st_mode))
sandboxProfile += fmt("\t(subpath \"%s\")\n", path);
else
sandboxProfile += fmt("\t(literal \"%s\")\n", path);
@@ -2260,14 +2260,12 @@ SingleDrvOutputs LocalDerivationGoal::registerOutputs()
continue;
}
- struct stat st;
- if (lstat(actualPath.c_str(), &st) == -1) {
- if (errno == ENOENT)
- throw BuildError(
- "builder for '%s' failed to produce output path for output '%s' at '%s'",
- worker.store.printStorePath(drvPath), outputName, actualPath);
- throw SysError("getting attributes of path '%s'", actualPath);
- }
+ auto optSt = maybeLstat(actualPath.c_str());
+ if (!optSt)
+ throw BuildError(
+ "builder for '%s' failed to produce output path for output '%s' at '%s'",
+ worker.store.printStorePath(drvPath), outputName, actualPath);
+ struct stat & st = *optSt;
#ifndef __CYGWIN__
/* Check that the output is not group or world writable, as
diff --git a/src/libstore/builtins/buildenv.cc b/src/libstore/builtins/buildenv.cc
index eb68d5a33..61c729d27 100644
--- a/src/libstore/builtins/buildenv.cc
+++ b/src/libstore/builtins/buildenv.cc
@@ -63,9 +63,9 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
continue;
else if (S_ISDIR(srcSt.st_mode)) {
- struct stat dstSt;
- auto res = lstat(dstFile.c_str(), &dstSt);
- if (res == 0) {
+ auto dstStOpt = maybeLstat(dstFile.c_str());
+ if (dstStOpt) {
+ auto & dstSt = *dstStOpt;
if (S_ISDIR(dstSt.st_mode)) {
createLinks(state, srcFile, dstFile, priority);
continue;
@@ -81,14 +81,13 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
createLinks(state, srcFile, dstFile, priority);
continue;
}
- } else if (errno != ENOENT)
- throw SysError("getting status of '%1%'", dstFile);
+ }
}
else {
- struct stat dstSt;
- auto res = lstat(dstFile.c_str(), &dstSt);
- if (res == 0) {
+ auto dstStOpt = maybeLstat(dstFile.c_str());
+ if (dstStOpt) {
+ auto & dstSt = *dstStOpt;
if (S_ISLNK(dstSt.st_mode)) {
auto prevPriority = state.priorities[dstFile];
if (prevPriority == priority)
@@ -103,8 +102,7 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
throw SysError("unlinking '%1%'", dstFile);
} else if (S_ISDIR(dstSt.st_mode))
throw Error("collision between non-directory '%1%' and directory '%2%'", srcFile, dstFile);
- } else if (errno != ENOENT)
- throw SysError("getting status of '%1%'", dstFile);
+ }
}
createSymlink(srcFile, dstFile);
diff --git a/src/libutil/util.cc b/src/libutil/util.cc
index 5cd4df8e6..dc724db3e 100644
--- a/src/libutil/util.cc
+++ b/src/libutil/util.cc
@@ -256,16 +256,22 @@ struct stat lstat(const Path & path)
return st;
}
+std::optional<struct stat> maybeLstat(const Path & path)
+{
+ std::optional<struct stat> st{std::in_place};
+ if (lstat(path.c_str(), &*st))
+ {
+ if (errno == ENOENT || errno == ENOTDIR)
+ st.reset();
+ else
+ throw SysError("getting status of '%s'", path);
+ }
+ return st;
+}
bool pathExists(const Path & path)
{
- int res;
- struct stat st;
- res = lstat(path.c_str(), &st);
- if (!res) return true;
- if (errno != ENOENT && errno != ENOTDIR)
- throw SysError("getting status of %1%", path);
- return false;
+ return maybeLstat(path).has_value();
}
bool pathAccessible(const Path & path)
diff --git a/src/libutil/util.hh b/src/libutil/util.hh
index 29a70447e..61df6c4f8 100644
--- a/src/libutil/util.hh
+++ b/src/libutil/util.hh
@@ -115,6 +115,12 @@ struct stat stat(const Path & path);
struct stat lstat(const Path & path);
/**
+ * `lstat` the given path if it exists.
+ * @return std::nullopt if the path doesn't exist, or an optional containing the result of `lstat` otherwise
+ */
+std::optional<struct stat> maybeLstat(const Path & path);
+
+/**
* @return true iff the given path exists.
*/
bool pathExists(const Path & path);