diff options
author | John Ericson <John.Ericson@Obsidian.Systems> | 2024-03-30 11:23:29 -0400 |
---|---|---|
committer | K900 <me@0upti.me> | 2024-04-11 15:43:41 +0300 |
commit | aeee22e5a17404b10dd14b5289e302eaf546e1aa (patch) | |
tree | 3bed2463ffd9916104b95fcb58be5537d65f800c | |
parent | 99845e0e01eaa2120b10c22591c43c4305f5ba51 (diff) |
Merge pull request #10362 from obsidiansystems/maybeLstat
Factor out `nix::maybeLstat`
(cherry-picked from commit 9b88e5284608116b7db0dbd3d5dd7a33b90d52d7)
Change-Id: Id890525e847c890fad6593c594772826ac4d1d50
-rw-r--r-- | src/libstore/build/local-derivation-goal.cc | 24 | ||||
-rw-r--r-- | src/libstore/builtins/buildenv.cc | 18 | ||||
-rw-r--r-- | src/libutil/util.cc | 20 | ||||
-rw-r--r-- | src/libutil/util.hh | 6 |
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); |