diff options
| author | Joel Klinghed <the_jk@yahoo.com> | 2017-09-26 20:09:31 +0200 |
|---|---|---|
| committer | Joel Klinghed <the_jk@yahoo.com> | 2017-09-26 20:09:31 +0200 |
| commit | c85b624d28564a6f785b25000e2b7825592a919d (patch) | |
| tree | 647b756c824b470b35f1371eb869e9534ed6c1bb /src/io.cc | |
Initial commit
Diffstat (limited to 'src/io.cc')
| -rw-r--r-- | src/io.cc | 167 |
1 files changed, 167 insertions, 0 deletions
diff --git a/src/io.cc b/src/io.cc new file mode 100644 index 0000000..bc70eee --- /dev/null +++ b/src/io.cc @@ -0,0 +1,167 @@ +#include "common.hh" + +#include <errno.h> +#include <unistd.h> + +#include "io.hh" + +namespace { + +bool do_read(int fd, void* dst, size_t max, size_t* got) { + auto d = reinterpret_cast<char*>(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<char const*>(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 |
