diff --git a/src/libutil/serialise.cc b/src/libutil/serialise.cc index 66a64a6be..e3a53c0d0 100644 --- a/src/libutil/serialise.cc +++ b/src/libutil/serialise.cc @@ -2,6 +2,7 @@ #include "util.hh" #include +#include namespace nix { @@ -38,7 +39,28 @@ void FdSink::flush() void FdSource::operator () (unsigned char * data, unsigned int len) { - readFull(fd, data, len); + if (!buffer) buffer = new unsigned char[bufSize]; + + while (len) { + if (!bufPosIn) { + /* Read as much data as is available (up to the buffer + size). */ + checkInterrupt(); + ssize_t n = read(fd, (char *) buffer, bufSize); + if (n == -1) { + if (errno == EINTR) continue; + throw SysError("reading from file"); + } + if (n == 0) throw EndOfFile("unexpected end-of-file"); + bufPosIn = n; + } + + /* Copy out the data in the buffer. */ + size_t n = len > bufPosIn - bufPosOut ? bufPosIn - bufPosOut : len; + memcpy(data, buffer + bufPosOut, n); + data += n; bufPosOut += n; len -= n; + if (bufPosIn == bufPosOut) bufPosIn = bufPosOut = 0; + } } diff --git a/src/libutil/serialise.hh b/src/libutil/serialise.hh index 711bd5e6c..b8d4d7a84 100644 --- a/src/libutil/serialise.hh +++ b/src/libutil/serialise.hh @@ -38,9 +38,7 @@ struct FdSink : Sink FdSink() : fd(-1), bufSize(32 * 1024), bufPos(0), buffer(0) { } FdSink(int fd, unsigned int bufSize = 32 * 1024) - : fd(fd), bufSize(bufSize), bufPos(0), buffer(0) - { - } + : fd(fd), bufSize(bufSize), bufPos(0), buffer(0) { } ~FdSink() { @@ -58,15 +56,17 @@ struct FdSink : Sink struct FdSource : Source { int fd; + unsigned int bufSize, bufPosIn, bufPosOut; + unsigned char * buffer; - FdSource() - { - fd = -1; - } + FdSource() : fd(-1), bufSize(32 * 1024), bufPosIn(0), bufPosOut(0), buffer(0) { } - FdSource(int fd) + FdSource(int fd, unsigned int bufSize = 32 * 1024) + : fd(fd), bufSize(bufSize), bufPosIn(0), bufPosOut(0), buffer(0) { } + + ~FdSource() { - this->fd = fd; + if (buffer) delete[] buffer; } void operator () (unsigned char * data, unsigned int len);