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