Skip to content

Commit

Permalink
Merge pull request NixOS#10362 from obsidiansystems/maybeLstat
Browse files Browse the repository at this point in the history
Factor out `nix::maybeLstat`

(cherry-picked from commit 9b88e52)

Change-Id: Id890525e847c890fad6593c594772826ac4d1d50
  • Loading branch information
Ericson2314 authored and K900 committed Apr 11, 2024
1 parent 99845e0 commit aeee22e
Show file tree
Hide file tree
Showing 4 changed files with 38 additions and 30 deletions.
24 changes: 11 additions & 13 deletions src/libstore/build/local-derivation-goal.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down
18 changes: 8 additions & 10 deletions src/libstore/builtins/buildenv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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)
Expand All @@ -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);
Expand Down
20 changes: 13 additions & 7 deletions src/libutil/util.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
6 changes: 6 additions & 0 deletions src/libutil/util.hh
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,12 @@ bool isDirOrInDir(std::string_view path, std::string_view dir);
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.
*/
Expand Down

0 comments on commit aeee22e

Please sign in to comment.