diff options
Diffstat (limited to 'src/io.cc')
| -rw-r--r-- | src/io.cc | 90 |
1 files changed, 90 insertions, 0 deletions
diff --git a/src/io.cc b/src/io.cc new file mode 100644 index 0000000..5c33ea2 --- /dev/null +++ b/src/io.cc @@ -0,0 +1,90 @@ +// -*- mode: c++; c-basic-offset: 2; -*- + +#include "common.hh" + +#include <algorithm> +#include <cerrno> +#include <limits> +#include <unistd.h> + +#include "io.hh" + +namespace io { + +ssize_t read(int fd, void* buf, size_t max) { + while (true) { + ssize_t ret = ::read(fd, buf, max); + if (ret != -1 || errno != EINTR) return ret; + } +} + +ssize_t write(int fd, void const* buf, size_t max) { + while (true) { + ssize_t ret = ::write(fd, buf, max); + if (ret != -1 || errno != EINTR) return ret; + } +} + +bool read_all(int fd, void* buf, size_t size) { + auto data = reinterpret_cast<char*>(buf); + auto end = data + size; + while (data < end) { + ssize_t ret = ::read(fd, data, std::min( + std::numeric_limits<ssize_t>::max(), end - data)); + if (ret < 0) { + if (errno == EINTR) continue; + return false; + } + if (ret == 0) return false; + data += ret; + } + return true; +} + +bool write_all(int fd, void const* buf, size_t size) { + auto data = reinterpret_cast<char const*>(buf); + auto end = data + size; + while (data < end) { + ssize_t ret = ::write(fd, data, std::min( + std::numeric_limits<ssize_t>::max(), end - data)); + if (ret < 0) { + if (errno == EINTR) continue; + return false; + } + if (ret == 0) return false; + data += ret; + } + return true; +} + +bool auto_fd::reset() { + if (fd_ >= 0) { + auto tmp = fd_; + fd_ = -1; + return close(tmp) != 0; + } + return true; +} + +void auto_pipe::reset() { + if (read_ >= 0) { + assert(write_ >= 0); + close(read_); + close(write_); + read_ = -1; + write_ = -1; + } +} + +bool auto_pipe::open() { + reset(); + int fd[2]; + if (pipe(fd) != 0) { + return false; + } + read_ = fd[0]; + write_ = fd[1]; + return true; +} + +} // namespace io |
