Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/libfetchers/git.cc
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ namespace {
// old version of git, which will ignore unrecognized `-c` options.
const std::string gitInitialBranch = "__nix_dummy_branch";

bool isCacheFileWithinTtl(time_t now, const struct stat & st)
bool isCacheFileWithinTtl(time_t now, const PosixStat & st)
{
return st.st_mtime + static_cast<time_t>(settings.tarballTtl) > now;
}
Expand Down Expand Up @@ -113,11 +113,11 @@ std::optional<std::string> readHeadCached(const std::string & actualUrl, bool sh
std::filesystem::path headRefFile = cacheDir / "HEAD";

time_t now = time(0);
struct stat st;
auto st = maybeStat(headRefFile);
std::optional<std::string> cachedRef;
if (stat(headRefFile.string().c_str(), &st) == 0) {
if (st) {
cachedRef = readHead(cacheDir);
if (cachedRef != std::nullopt && *cachedRef != gitInitialBranch && isCacheFileWithinTtl(now, st)) {
if (cachedRef != std::nullopt && *cachedRef != gitInitialBranch && isCacheFileWithinTtl(now, *st)) {
debug("using cached HEAD ref '%s' for repo '%s'", *cachedRef, actualUrl);
return cachedRef;
}
Expand Down Expand Up @@ -819,10 +819,10 @@ struct GitInputScheme : InputScheme
if (getAllRefsAttr(input)) {
doFetch = true;
} else {
/* If the local ref is older than tarball-ttl seconds, do a
/* If the local ref is older than 'tarball-ttl' seconds, do a
git fetch to update the local ref to the remote ref. */
struct stat st;
doFetch = stat(localRefFile.string().c_str(), &st) != 0 || !isCacheFileWithinTtl(now, st);
auto st = maybeStat(localRefFile);
doFetch = !st || !isCacheFileWithinTtl(now, *st);
}
}

Expand Down
15 changes: 5 additions & 10 deletions src/libstore/builtins/buildenv.cc
Original file line number Diff line number Diff line change
Expand Up @@ -50,17 +50,12 @@ static void createLinks(State & state, const Path & srcDir, const Path & dstDir,
auto srcFile = (std::filesystem::path{srcDir} / name).string();
auto dstFile = (std::filesystem::path{dstDir} / name).string();

struct stat srcSt;
try {
if (stat(srcFile.c_str(), &srcSt) == -1)
throw SysError("getting status of '%1%'", srcFile);
} catch (SystemError & e) {
if (e.is(std::errc::no_such_file_or_directory) || e.is(std::errc::not_a_directory)) {
warn("skipping dangling symlink '%s'", dstFile);
continue;
}
throw;
auto srcStOpt = maybeStat(srcFile.c_str());
if (!srcStOpt) {
warn("skipping dangling symlink '%s'", dstFile);
continue;
}
auto & srcSt = *srcStOpt;

/* The files below are special-cased to that they don't show
* up in user profiles, either because they are useless, or
Expand Down
6 changes: 2 additions & 4 deletions src/libstore/gc.cc
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ void LocalStore::createTempRootsFile()

/* Check whether the garbage collector didn't get in our
way. */
struct stat st;
PosixStat st;
if (fstat(fromDescriptorReadOnly(fdTempRoots->get()), &st) == -1)
throw SysError("statting '%1%'", fnTempRoots);
if (st.st_size == 0)
Expand Down Expand Up @@ -901,9 +901,7 @@ void LocalStore::collectGarbage(const GCOptions & options, GCResults & results)
accounting. */
}

struct stat st;
if (stat(linksDir.c_str(), &st) == -1)
throw SysError("statting '%1%'", linksDir);
auto st = stat(linksDir);
int64_t overhead =
#ifdef _WIN32
0
Expand Down
8 changes: 3 additions & 5 deletions src/libstore/local-store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -167,9 +167,7 @@ LocalStore::LocalStore(ref<const Config> config)
printError(
"warning: the group '%1%' specified in 'build-users-group' does not exist", settings.buildUsersGroup);
else if (!config->readOnly) {
struct stat st;
if (stat(config->realStoreDir.get().c_str(), &st))
throw SysError("getting attributes of path '%1%'", config->realStoreDir);
auto st = stat(config->realStoreDir.get());

if (st.st_uid != 0 || st.st_gid != gr->gr_gid || (st.st_mode & ~S_IFMT) != perm) {
if (chown(config->realStoreDir.get().c_str(), 0, gr->gr_gid) == -1)
Expand Down Expand Up @@ -200,8 +198,8 @@ LocalStore::LocalStore(ref<const Config> config)
needed, we reserve some dummy space that we can free just
before doing a garbage collection. */
try {
struct stat st;
if (stat(reservedPath.c_str(), &st) == -1 || st.st_size != gcSettings.reservedSize) {
auto st = maybeStat(reservedPath);
if (!st || st->st_size != gcSettings.reservedSize) {
AutoCloseFD fd = toDescriptor(open(
reservedPath.c_str(),
O_WRONLY | O_CREAT
Expand Down
4 changes: 2 additions & 2 deletions src/libstore/optimise-store.cc
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ void LocalStore::optimisePath_(

/* Maybe delete the link, if it has been corrupted. */
if (std::filesystem::exists(std::filesystem::symlink_status(linkPath))) {
auto stLink = lstat(linkPath.string());
auto stLink = lstat(linkPath);
if (st.st_size != stLink.st_size || (repair && hash != ({
hashPath(
makeFSSourceAccessor(linkPath),
Expand Down Expand Up @@ -215,7 +215,7 @@ void LocalStore::optimisePath_(

/* Yes! We've seen a file with the same contents. Replace the
current file with a hard link to that file. */
auto stLink = lstat(linkPath.string());
auto stLink = lstat(linkPath);

if (st.st_ino == stLink.st_ino) {
debug("%1% is already linked to %2%", PathFmt(path), PathFmt(linkPath));
Expand Down
4 changes: 2 additions & 2 deletions src/libstore/posix-fs-canonicalise.cc
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ namespace nix {

const time_t mtimeStore = 1; /* 1 second into the epoch */

static void canonicaliseTimestampAndPermissions(const Path & path, const struct stat & st)
static void canonicaliseTimestampAndPermissions(const Path & path, const PosixStat & st)
{
if (!S_ISLNK(st.st_mode)) {

Expand All @@ -31,7 +31,7 @@ static void canonicaliseTimestampAndPermissions(const Path & path, const struct

#ifndef _WIN32 // TODO implement
if (st.st_mtime != mtimeStore) {
struct stat st2 = st;
PosixStat st2 = st;
st2.st_mtime = mtimeStore, setWriteTime(path, st2);
}
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/libstore/unix/build/derivation-builder.cc
Original file line number Diff line number Diff line change
Expand Up @@ -1419,7 +1419,7 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
scratchOutputsInverse.insert_or_assign(path, outputName);

std::map<std::string, std::variant<AlreadyRegistered, PerhapsNeedToRegister>> outputReferencesIfUnregistered;
std::map<std::string, struct stat> outputStats;
std::map<std::string, PosixStat> outputStats;
for (auto & [outputName, _] : drv.outputs) {
auto scratchOutput = get(scratchOutputs, outputName);
assert(scratchOutput);
Expand Down Expand Up @@ -1448,7 +1448,7 @@ SingleDrvOutputs DerivationBuilderImpl::registerOutputs()
store.printStorePath(drvPath),
outputName,
PathFmt(actualPath));
struct stat & st = *optSt;
PosixStat & st = *optSt;

#ifndef __CYGWIN__
/* Check that the output is not group or world writable, as
Expand Down
3 changes: 2 additions & 1 deletion src/libstore/unix/pathlocks.cc
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
#include "nix/store/pathlocks.hh"
#include "nix/util/file-system.hh"
#include "nix/util/util.hh"
#include "nix/util/sync.hh"
#include "nix/util/signals.hh"
Expand Down Expand Up @@ -110,7 +111,7 @@ bool PathLocks::lockPaths(const std::set<std::filesystem::path> & paths, const s

/* Check that the lock file hasn't become stale (i.e.,
hasn't been unlinked). */
struct stat st;
PosixStat st;
if (fstat(fd.get(), &st) == -1)
throw SysError("statting lock file %1%", PathFmt(lockPath));
if (st.st_size != 0)
Expand Down
51 changes: 34 additions & 17 deletions src/libutil/file-system.cc
Original file line number Diff line number Diff line change
Expand Up @@ -193,40 +193,57 @@ bool isDirOrInDir(const std::filesystem::path & path, const std::filesystem::pat
return path == dir || isInDir(path, dir);
}

struct stat stat(const Path & path)
{
struct stat st;
if (stat(path.c_str(), &st))
throw SysError("getting status of '%1%'", path);
return st;
}

#ifdef _WIN32
# define STAT stat
# define STAT _wstat64
# define LSTAT _wstat64
#else
# define STAT lstat
# define STAT stat
# define LSTAT lstat
#endif

struct stat lstat(const Path & path)
PosixStat stat(const std::filesystem::path & path)
{
struct stat st;
PosixStat st;
if (STAT(path.c_str(), &st))
throw SysError("getting status of '%1%'", path);
throw SysError("getting status of %s", PathFmt(path));
return st;
}

PosixStat lstat(const std::filesystem::path & path)
{
PosixStat st;
if (LSTAT(path.c_str(), &st))
throw SysError("getting status of %s", PathFmt(path));
return st;
}

std::optional<struct stat> maybeLstat(const Path & path)
std::optional<PosixStat> maybeStat(const std::filesystem::path & path)
{
std::optional<struct stat> st{std::in_place};
std::optional<PosixStat> st{std::in_place};
if (STAT(path.c_str(), &*st)) {
if (errno == ENOENT || errno == ENOTDIR)
st.reset();
else
throw SysError("getting status of '%s'", path);
throw SysError("getting status of %s", PathFmt(path));
}
return st;
}

std::optional<PosixStat> maybeLstat(const std::filesystem::path & path)
{
std::optional<PosixStat> st{std::in_place};
if (LSTAT(path.c_str(), &*st)) {
if (errno == ENOENT || errno == ENOTDIR)
st.reset();
else
throw SysError("getting status of %s", PathFmt(path));
}
return st;
}

#undef STAT
#undef LSTAT

bool pathExists(const std::filesystem::path & path)
{
return maybeLstat(path.string()).has_value();
Expand Down Expand Up @@ -641,7 +658,7 @@ void replaceSymlink(const std::filesystem::path & target, const std::filesystem:
}
}

void setWriteTime(const std::filesystem::path & path, const struct stat & st)
void setWriteTime(const std::filesystem::path & path, const PosixStat & st)
{
setWriteTime(path, st.st_atime, st.st_mtime, S_ISLNK(st.st_mode));
}
Expand Down
2 changes: 1 addition & 1 deletion src/libutil/fs-sink.cc
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ void RestoreRegularFile::isExecutable()
// Windows doesn't have a notion of executable file permissions we
// care about here, right?
#ifndef _WIN32
struct stat st;
PosixStat st;
if (fstat(fd.get(), &st) == -1)
throw SysError("fstat");
if (fchmod(fd.get(), st.st_mode | (S_IXUSR | S_IXGRP | S_IXOTH)) == -1)
Expand Down
26 changes: 21 additions & 5 deletions src/libutil/include/nix/util/file-system.hh
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include <unistd.h>
#ifdef _WIN32
# include <windef.h>
# include <wchar.h>
#endif

#include <functional>
Expand Down Expand Up @@ -110,16 +111,31 @@ bool isInDir(const std::filesystem::path & path, const std::filesystem::path & d
*/
bool isDirOrInDir(const std::filesystem::path & path, const std::filesystem::path & dir);

/**
* `struct stat` is not 64-bit everywhere on Windows.
*/
using PosixStat =
#ifdef _WIN32
struct ::__stat64
#else
struct ::stat
#endif
;

/**
* Get status of `path`.
*/
struct stat stat(const Path & path);
struct stat lstat(const Path & path);
PosixStat lstat(const std::filesystem::path & path);
/**
* Get status of `path` following symlinks.
*/
PosixStat stat(const std::filesystem::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);
std::optional<PosixStat> maybeLstat(const std::filesystem::path & path);
std::optional<PosixStat> maybeStat(const std::filesystem::path & path);

/**
* @return true iff the given path exists.
Expand Down Expand Up @@ -260,9 +276,9 @@ void setWriteTime(
std::optional<bool> isSymlink = std::nullopt);

/**
* Convenience wrapper that takes all arguments from the `struct stat`.
* Convenience wrapper that takes all arguments from the `PosixStat`.
*/
void setWriteTime(const std::filesystem::path & path, const struct stat & st);
void setWriteTime(const std::filesystem::path & path, const PosixStat & st);

/**
* Create a symlink.
Expand Down
2 changes: 1 addition & 1 deletion src/libutil/include/nix/util/posix-source-accessor.hh
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ private:
*/
void assertNoSymlinks(CanonPath path);

std::optional<struct stat> cachedLstat(const CanonPath & path);
std::optional<PosixStat> cachedLstat(const CanonPath & path);

std::filesystem::path makeAbsPath(const CanonPath & path);
};
Expand Down
6 changes: 3 additions & 3 deletions src/libutil/posix-source-accessor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ void PosixSourceAccessor::readFile(const CanonPath & path, Sink & sink, std::fun
if (!fd)
throw SysError("opening file '%1%'", ap.string());

struct stat st;
PosixStat st;
if (fstat(fromDescriptorReadOnly(fd.get()), &st) == -1)
throw SysError("statting file");

Expand Down Expand Up @@ -87,9 +87,9 @@ bool PosixSourceAccessor::pathExists(const CanonPath & path)
return nix::pathExists(makeAbsPath(path).string());
}

std::optional<struct stat> PosixSourceAccessor::cachedLstat(const CanonPath & path)
std::optional<PosixStat> PosixSourceAccessor::cachedLstat(const CanonPath & path)
{
using Cache = boost::concurrent_flat_map<Path, std::optional<struct stat>>;
using Cache = boost::concurrent_flat_map<Path, std::optional<PosixStat>>;
static Cache cache;

// Note: we convert std::filesystem::path to Path because the
Expand Down
2 changes: 1 addition & 1 deletion src/libutil/unix/file-descriptor.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ void pollFD(int fd, int events)

std::string readFile(int fd)
{
struct stat st;
PosixStat st;
if (fstat(fd, &st) == -1)
throw SysError("statting file");

Expand Down
2 changes: 1 addition & 1 deletion src/libutil/unix/file-system.cc
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,7 @@ static void _deletePath(
std::string name(path.filename());
assert(name != "." && name != ".." && !name.empty());

struct stat st;
PosixStat st;
if (fstatat(parentfd, name.c_str(), &st, AT_SYMLINK_NOFOLLOW) == -1) {
if (errno == ENOENT)
return;
Expand Down
22 changes: 10 additions & 12 deletions src/libutil/unix/users.cc
Original file line number Diff line number Diff line change
Expand Up @@ -35,18 +35,16 @@ std::filesystem::path getHome()
auto homeDir = getEnv("HOME");
if (homeDir) {
// Only use $HOME if doesn't exist or is owned by the current user.
struct stat st;
int result = stat(homeDir->c_str(), &st);
if (result != 0) {
if (errno != ENOENT) {
warn(
"couldn't stat $HOME ('%s') for reason other than not existing ('%d'), falling back to the one defined in the 'passwd' file",
*homeDir,
errno);
homeDir.reset();
}
} else if (st.st_uid != geteuid()) {
unownedUserHomeDir.swap(homeDir);
try {
auto st = maybeStat(homeDir->c_str());
if (st && st->st_uid != geteuid())
unownedUserHomeDir.swap(homeDir);
} catch (SysError & e) {
warn(
"couldn't stat $HOME ('%s') for reason other than not existing, falling back to the one defined in the 'passwd' file: %s",
*homeDir,
e.what());
homeDir.reset();
}
}
if (!homeDir) {
Expand Down
Loading
Loading