#include "common.hh" #include #include #include "io.hh" namespace { bool do_read(int fd, void* dst, size_t max, size_t* got) { auto d = reinterpret_cast(dst); size_t pos = 0; while (true) { auto ret = ::read(fd, d + pos, max - pos); if (ret < 0) { if (errno == EINTR) continue; if (got && (errno == EAGAIN || errno == EWOULDBLOCK)) { *got = pos; return true; } return false; } if (ret == 0) { if (got) { *got = pos; return true; } return false; } pos += ret; if (got) { *got = pos; return true; } if (pos == max) { return true; } } } bool do_write(int fd, void const* src, size_t size, size_t* wrote) { auto s = reinterpret_cast(src); size_t pos = 0; while (true) { auto ret = ::write(fd, s + pos, size - pos); if (ret < 0) { if (errno == EINTR) continue; if (wrote && (errno == EAGAIN || errno == EWOULDBLOCK)) { *wrote = pos; return true; } return false; } if (ret == 0) { if (wrote) { *wrote = pos; return true; } return false; } pos += ret; if (pos == size) { if (wrote) *wrote = pos; return true; } } } } // namespace namespace io { pipe::pipe() { fd_[0] = fd_[1] = -1; } pipe::pipe(pipe&& pipe) { fd_[0] = pipe.fd_[0]; fd_[1] = pipe.fd_[1]; pipe.fd_[0] = -1; pipe.fd_[1] = -1; } pipe::~pipe() { reset(); } bool pipe::open() { reset(); if (::pipe(fd_) == 0) return true; fd_[0] = fd_[1] = -1; return false; } void pipe::reset() { if (fd_[0] == -1) return; ::close(fd_[0]); ::close(fd_[1]); fd_[0] = fd_[1] = -1; } void pipe::swap(pipe& pipe) { auto x = pipe.fd_[0]; pipe.fd_[0] = fd_[0]; fd_[0] = x; x = pipe.fd_[1]; pipe.fd_[1] = fd_[1]; fd_[1] = x; } unique_fd::unique_fd() : fd_(-1) { } unique_fd::unique_fd(int fd) : fd_(fd) { } unique_fd::unique_fd(unique_fd&& fd) : fd_(fd.release()) { } unique_fd::~unique_fd() { reset(); } void unique_fd::reset() { if (fd_ == -1) return; ::close(fd_); fd_ = -1; } void unique_fd::reset(int fd) { if (fd_ == fd) return; reset(); fd_ = fd; } void unique_fd::swap(unique_fd& fd) { auto x = fd.fd_; fd.fd_ = fd_; fd_ = x; } int unique_fd::release() { auto ret = fd_; fd_ = -1; return ret; } bool read(pipe const& pipe, void* dst, size_t max, size_t* got) { return do_read(pipe.read(), dst, max, got); } bool write(pipe const& pipe, void const* src, size_t size, size_t* wrote) { return do_write(pipe.write(), src, size, wrote); } bool read(unique_fd const& fd, void* dst, size_t max, size_t* got) { return do_read(fd.get(), dst, max, got); } bool write(unique_fd const& fd, void const* src, size_t size, size_t* wrote) { return do_write(fd.get(), src, size, wrote); } } // namespace io