Move PosixSourceAccessor into its own file

This commit is contained in:
Eelco Dolstra 2023-10-23 11:05:50 +02:00
parent bcf5c31950
commit 34a42f0d0a
6 changed files with 122 additions and 109 deletions

View file

@ -1,4 +1,5 @@
#include "fs-input-accessor.hh" #include "fs-input-accessor.hh"
#include "posix-source-accessor.hh"
#include "store-api.hh" #include "store-api.hh"
namespace nix { namespace nix {

View file

@ -14,7 +14,7 @@
#include "archive.hh" #include "archive.hh"
#include "util.hh" #include "util.hh"
#include "config.hh" #include "config.hh"
#include "source-accessor.hh" #include "posix-source-accessor.hh"
namespace nix { namespace nix {

View file

@ -0,0 +1,86 @@
#include "posix-source-accessor.hh"
namespace nix {
void PosixSourceAccessor::readFile(
const CanonPath & path,
Sink & sink,
std::function<void(uint64_t)> sizeCallback)
{
// FIXME: add O_NOFOLLOW since symlinks should be resolved by the
// caller?
AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
if (!fd)
throw SysError("opening file '%1%'", path);
struct stat st;
if (fstat(fd.get(), &st) == -1)
throw SysError("statting file");
sizeCallback(st.st_size);
off_t left = st.st_size;
std::vector<unsigned char> buf(64 * 1024);
while (left) {
checkInterrupt();
ssize_t rd = read(fd.get(), buf.data(), (size_t) std::min(left, (off_t) buf.size()));
if (rd == -1) {
if (errno != EINTR)
throw SysError("reading from file '%s'", showPath(path));
}
else if (rd == 0)
throw SysError("unexpected end-of-file reading '%s'", showPath(path));
else {
assert(rd <= left);
sink({(char *) buf.data(), (size_t) rd});
left -= rd;
}
}
}
bool PosixSourceAccessor::pathExists(const CanonPath & path)
{
return nix::pathExists(path.abs());
}
SourceAccessor::Stat PosixSourceAccessor::lstat(const CanonPath & path)
{
auto st = nix::lstat(path.abs());
mtime = std::max(mtime, st.st_mtime);
return Stat {
.type =
S_ISREG(st.st_mode) ? tRegular :
S_ISDIR(st.st_mode) ? tDirectory :
S_ISLNK(st.st_mode) ? tSymlink :
tMisc,
.isExecutable = S_ISREG(st.st_mode) && st.st_mode & S_IXUSR
};
}
SourceAccessor::DirEntries PosixSourceAccessor::readDirectory(const CanonPath & path)
{
DirEntries res;
for (auto & entry : nix::readDirectory(path.abs())) {
std::optional<Type> type;
switch (entry.type) {
case DT_REG: type = Type::tRegular; break;
case DT_LNK: type = Type::tSymlink; break;
case DT_DIR: type = Type::tDirectory; break;
}
res.emplace(entry.name, type);
}
return res;
}
std::string PosixSourceAccessor::readLink(const CanonPath & path)
{
return nix::readLink(path.abs());
}
std::optional<CanonPath> PosixSourceAccessor::getPhysicalPath(const CanonPath & path)
{
return path;
}
}

View file

@ -0,0 +1,34 @@
#pragma once
#include "source-accessor.hh"
namespace nix {
/**
* A source accessor that uses the Unix filesystem.
*/
struct PosixSourceAccessor : SourceAccessor
{
/**
* The most recent mtime seen by lstat(). This is a hack to
* support dumpPathAndGetMtime(). Should remove this eventually.
*/
time_t mtime = 0;
void readFile(
const CanonPath & path,
Sink & sink,
std::function<void(uint64_t)> sizeCallback) override;
bool pathExists(const CanonPath & path) override;
Stat lstat(const CanonPath & path) override;
DirEntries readDirectory(const CanonPath & path) override;
std::string readLink(const CanonPath & path) override;
std::optional<CanonPath> getPhysicalPath(const CanonPath & path) override;
};
}

View file

@ -55,85 +55,4 @@ std::string SourceAccessor::showPath(const CanonPath & path)
return path.abs(); return path.abs();
} }
void PosixSourceAccessor::readFile(
const CanonPath & path,
Sink & sink,
std::function<void(uint64_t)> sizeCallback)
{
// FIXME: add O_NOFOLLOW since symlinks should be resolved by the
// caller?
AutoCloseFD fd = open(path.c_str(), O_RDONLY | O_CLOEXEC);
if (!fd)
throw SysError("opening file '%1%'", path);
struct stat st;
if (fstat(fd.get(), &st) == -1)
throw SysError("statting file");
sizeCallback(st.st_size);
off_t left = st.st_size;
std::vector<unsigned char> buf(64 * 1024);
while (left) {
checkInterrupt();
ssize_t rd = read(fd.get(), buf.data(), (size_t) std::min(left, (off_t) buf.size()));
if (rd == -1) {
if (errno != EINTR)
throw SysError("reading from file '%s'", showPath(path));
}
else if (rd == 0)
throw SysError("unexpected end-of-file reading '%s'", showPath(path));
else {
assert(rd <= left);
sink({(char *) buf.data(), (size_t) rd});
left -= rd;
}
}
}
bool PosixSourceAccessor::pathExists(const CanonPath & path)
{
return nix::pathExists(path.abs());
}
SourceAccessor::Stat PosixSourceAccessor::lstat(const CanonPath & path)
{
auto st = nix::lstat(path.abs());
mtime = std::max(mtime, st.st_mtime);
return Stat {
.type =
S_ISREG(st.st_mode) ? tRegular :
S_ISDIR(st.st_mode) ? tDirectory :
S_ISLNK(st.st_mode) ? tSymlink :
tMisc,
.isExecutable = S_ISREG(st.st_mode) && st.st_mode & S_IXUSR
};
}
SourceAccessor::DirEntries PosixSourceAccessor::readDirectory(const CanonPath & path)
{
DirEntries res;
for (auto & entry : nix::readDirectory(path.abs())) {
std::optional<Type> type;
switch (entry.type) {
case DT_REG: type = Type::tRegular; break;
case DT_LNK: type = Type::tSymlink; break;
case DT_DIR: type = Type::tDirectory; break;
}
res.emplace(entry.name, type);
}
return res;
}
std::string PosixSourceAccessor::readLink(const CanonPath & path)
{
return nix::readLink(path.abs());
}
std::optional<CanonPath> PosixSourceAccessor::getPhysicalPath(const CanonPath & path)
{
return path;
}
} }

View file

@ -104,31 +104,4 @@ struct SourceAccessor
virtual std::string showPath(const CanonPath & path); virtual std::string showPath(const CanonPath & path);
}; };
/**
* A source accessor that uses the Unix filesystem.
*/
struct PosixSourceAccessor : SourceAccessor
{
/**
* The most recent mtime seen by lstat(). This is a hack to
* support dumpPathAndGetMtime(). Should remove this eventually.
*/
time_t mtime = 0;
void readFile(
const CanonPath & path,
Sink & sink,
std::function<void(uint64_t)> sizeCallback) override;
bool pathExists(const CanonPath & path) override;
Stat lstat(const CanonPath & path) override;
DirEntries readDirectory(const CanonPath & path) override;
std::string readLink(const CanonPath & path) override;
std::optional<CanonPath> getPhysicalPath(const CanonPath & path) override;
};
} }