+#ifndef file_h
+#define file_h
+
+#include <fcntl.h>
+#include <unistd.h>
+#include "types.h"
+#include <sys/socket.h>
+
+class file_t {
+ private:
+ int fd_;
+
+ class flags_t {
+ private:
+ const file_t & f_;
+ int flags_;
+ public:
+ flags_t(const file_t & f) : f_(f), flags_(fcntl(f_.fd_, F_GETFL, NULL)) { }
+ ~flags_t() { fcntl(f_.fd_, F_SETFL, flags_); }
+ operator int & () { return flags_; }
+ };
+ public:
+ inline file_t(int fd=-1) : fd_(fd) {}
+ inline file_t(const file_t &) = delete;
+ inline file_t(file_t && other) : fd_(-1) { std::swap(fd_, other.fd_); }
+ inline ~file_t() { if (fd_ != -1) ::close(fd_); }
+ static inline void pipe(file_t *ends) {
+ int fds[2];
+ VERIFY(::pipe(fds) == 0);
+ ends[0].fd_ = fds[0];
+ ends[1].fd_ = fds[1];
+ }
+ inline operator int() const { if (fd_ == -1) throw "no fd"; return fd_; }
+ inline flags_t flags() const { return *this; }
+ inline void close() {
+ ::close(fd_);
+ fd_ = -1;
+ }
+ template <class T>
+ inline ssize_t read(T & t) const { return ::read(fd_, &t, sizeof(T)); }
+ inline ssize_t read(void * t, size_t n) const { return ::read(fd_, t, n); }
+ template <class T>
+ inline ssize_t write(const T & t) const { return ::write(fd_, &t, sizeof(T)); }
+ inline ssize_t write(const void * t, size_t n) const { return ::write(fd_, t, n); }
+};
+
+class socket_t : public file_t {
+ public:
+ socket_t(int fd=-1) : file_t(fd) {}
+ template <class T>
+ int setsockopt(int level, int option, T && value) {
+ return ::setsockopt(*this, level, option, &value, sizeof(T));
+ }
+};
+
+#endif