1
0
Fork 0
mirror of https://github.com/NixOS/nix synced 2025-06-29 06:21:14 +02:00

Start factoring out Unix assumptions

This splits files and adds new identifiers in preperation for supporting
windows, but no Windows-specific code is actually added yet.

Co-authored-by: Robert Hensing <roberth@users.noreply.github.com>
This commit is contained in:
John Ericson 2024-03-29 15:59:14 -04:00
parent 852391765d
commit 02fa20622f
34 changed files with 352 additions and 296 deletions

View file

@ -8,74 +8,14 @@
namespace nix {
std::string readFile(int fd)
{
struct stat st;
if (fstat(fd, &st) == -1)
throw SysError("statting file");
return drainFD(fd, true, st.st_size);
}
void readFull(int fd, char * buf, size_t count)
{
while (count) {
checkInterrupt();
ssize_t res = read(fd, buf, count);
if (res == -1) {
if (errno == EINTR) continue;
throw SysError("reading from file");
}
if (res == 0) throw EndOfFile("unexpected end-of-file");
count -= res;
buf += res;
}
}
void writeFull(int fd, std::string_view s, bool allowInterrupts)
{
while (!s.empty()) {
if (allowInterrupts) checkInterrupt();
ssize_t res = write(fd, s.data(), s.size());
if (res == -1 && errno != EINTR)
throw SysError("writing to file");
if (res > 0)
s.remove_prefix(res);
}
}
std::string readLine(int fd)
{
std::string s;
while (1) {
checkInterrupt();
char ch;
// FIXME: inefficient
ssize_t rd = read(fd, &ch, 1);
if (rd == -1) {
if (errno != EINTR)
throw SysError("reading a line");
} else if (rd == 0)
throw EndOfFile("unexpected EOF reading a line");
else {
if (ch == '\n') return s;
s += ch;
}
}
}
void writeLine(int fd, std::string s)
void writeLine(Descriptor fd, std::string s)
{
s += '\n';
writeFull(fd, s);
}
std::string drainFD(int fd, bool block, const size_t reserveSize)
std::string drainFD(Descriptor fd, bool block, const size_t reserveSize)
{
// the parser needs two extra bytes to append terminating characters, other users will
// not care very much about the extra memory.
@ -85,50 +25,18 @@ std::string drainFD(int fd, bool block, const size_t reserveSize)
}
void drainFD(int fd, Sink & sink, bool block)
{
// silence GCC maybe-uninitialized warning in finally
int saved = 0;
if (!block) {
saved = fcntl(fd, F_GETFL);
if (fcntl(fd, F_SETFL, saved | O_NONBLOCK) == -1)
throw SysError("making file descriptor non-blocking");
}
Finally finally([&] {
if (!block) {
if (fcntl(fd, F_SETFL, saved) == -1)
throw SysError("making file descriptor blocking");
}
});
std::vector<unsigned char> buf(64 * 1024);
while (1) {
checkInterrupt();
ssize_t rd = read(fd, buf.data(), buf.size());
if (rd == -1) {
if (!block && (errno == EAGAIN || errno == EWOULDBLOCK))
break;
if (errno != EINTR)
throw SysError("reading from file");
}
else if (rd == 0) break;
else sink({reinterpret_cast<char *>(buf.data()), size_t(rd)});
}
}
//////////////////////////////////////////////////////////////////////
AutoCloseFD::AutoCloseFD() : fd{-1} {}
AutoCloseFD::AutoCloseFD() : fd{INVALID_DESCRIPTOR} {}
AutoCloseFD::AutoCloseFD(int fd) : fd{fd} {}
AutoCloseFD::AutoCloseFD(Descriptor fd) : fd{fd} {}
AutoCloseFD::AutoCloseFD(AutoCloseFD && that) : fd{that.fd}
{
that.fd = -1;
that.fd = INVALID_DESCRIPTOR;
}
@ -136,7 +44,7 @@ AutoCloseFD & AutoCloseFD::operator =(AutoCloseFD && that)
{
close();
fd = that.fd;
that.fd = -1;
that.fd = INVALID_DESCRIPTOR;
return *this;
}
@ -151,7 +59,7 @@ AutoCloseFD::~AutoCloseFD()
}
int AutoCloseFD::get() const
Descriptor AutoCloseFD::get() const
{
return fd;
}
@ -159,56 +67,46 @@ int AutoCloseFD::get() const
void AutoCloseFD::close()
{
if (fd != -1) {
if (::close(fd) == -1)
if (fd != INVALID_DESCRIPTOR) {
if(::close(fd) == -1)
/* This should never happen. */
throw SysError("closing file descriptor %1%", fd);
fd = -1;
fd = INVALID_DESCRIPTOR;
}
}
void AutoCloseFD::fsync()
{
if (fd != -1) {
int result;
if (fd != INVALID_DESCRIPTOR) {
int result;
result =
#if __APPLE__
result = ::fcntl(fd, F_FULLFSYNC);
::fcntl(fd, F_FULLFSYNC)
#else
result = ::fsync(fd);
::fsync(fd)
#endif
if (result == -1)
throw SysError("fsync file descriptor %1%", fd);
}
;
if (result == -1)
throw SysError("fsync file descriptor %1%", fd);
}
}
AutoCloseFD::operator bool() const
{
return fd != -1;
return fd != INVALID_DESCRIPTOR;
}
int AutoCloseFD::release()
Descriptor AutoCloseFD::release()
{
int oldFD = fd;
fd = -1;
Descriptor oldFD = fd;
fd = INVALID_DESCRIPTOR;
return oldFD;
}
void Pipe::create()
{
int fds[2];
#if HAVE_PIPE2
if (pipe2(fds, O_CLOEXEC) != 0) throw SysError("creating pipe");
#else
if (pipe(fds) != 0) throw SysError("creating pipe");
closeOnExec(fds[0]);
closeOnExec(fds[1]);
#endif
readSide = fds[0];
writeSide = fds[1];
}
//////////////////////////////////////////////////////////////////////
void Pipe::close()
@ -217,38 +115,4 @@ void Pipe::close()
writeSide.close();
}
//////////////////////////////////////////////////////////////////////
void closeMostFDs(const std::set<int> & exceptions)
{
#if __linux__
try {
for (auto & s : readDirectory("/proc/self/fd")) {
auto fd = std::stoi(s.name);
if (!exceptions.count(fd)) {
debug("closing leaked FD %d", fd);
close(fd);
}
}
return;
} catch (SystemError &) {
}
#endif
int maxFD = 0;
maxFD = sysconf(_SC_OPEN_MAX);
for (int fd = 0; fd < maxFD; ++fd)
if (!exceptions.count(fd))
close(fd); /* ignore result */
}
void closeOnExec(int fd)
{
int prev;
if ((prev = fcntl(fd, F_GETFD, 0)) == -1 ||
fcntl(fd, F_SETFD, prev | FD_CLOEXEC) == -1)
throw SysError("setting close-on-exec flag");
}
}