summaryrefslogtreecommitdiff
path: root/src/io.cc
diff options
context:
space:
mode:
Diffstat (limited to 'src/io.cc')
-rw-r--r--src/io.cc167
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