aboutsummaryrefslogtreecommitdiff
path: root/src/base/platform/unix/UnixFile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/base/platform/unix/UnixFile.cpp')
-rw-r--r--src/base/platform/unix/UnixFile.cpp96
1 files changed, 96 insertions, 0 deletions
diff --git a/src/base/platform/unix/UnixFile.cpp b/src/base/platform/unix/UnixFile.cpp
new file mode 100644
index 00000000..b9af109a
--- /dev/null
+++ b/src/base/platform/unix/UnixFile.cpp
@@ -0,0 +1,96 @@
+#include "cru/base/platform/unix/UnixFile.h"
+#include "cru/base/Exception.h"
+#include "cru/base/log/Logger.h"
+
+#include <fcntl.h>
+#include <sys/fcntl.h>
+#include <unistd.h>
+
+namespace cru::platform::unix {
+
+UnixFileDescriptor::UnixFileDescriptor()
+ : descriptor_(-1), auto_close_(false) {}
+
+UnixFileDescriptor::UnixFileDescriptor(int descriptor, bool auto_close,
+ std::function<int(int)> close)
+ : descriptor_(descriptor),
+ auto_close_(auto_close),
+ close_(std::move(close)) {}
+
+UnixFileDescriptor::~UnixFileDescriptor() {
+ constexpr auto kLogTag = u"cru::platform::unix::UnixFileDescriptor";
+ if (this->IsValid() && this->IsAutoClose()) {
+ if (!this->DoClose()) {
+ CRU_LOG_TAG_ERROR(u"Failed to close file descriptor {}, errno {}.",
+ descriptor_, errno);
+ }
+ }
+}
+
+UnixFileDescriptor::UnixFileDescriptor(UnixFileDescriptor&& other) noexcept
+ : descriptor_(other.descriptor_),
+ auto_close_(other.auto_close_),
+ close_(std::move(other.close_)) {
+ other.descriptor_ = -1;
+ other.auto_close_ = false;
+ other.close_ = nullptr;
+}
+
+UnixFileDescriptor& UnixFileDescriptor::operator=(
+ UnixFileDescriptor&& other) noexcept {
+ if (this != &other) {
+ if (this->IsValid()) {
+ this->Close();
+ }
+ this->descriptor_ = other.descriptor_;
+ this->auto_close_ = other.auto_close_;
+ this->close_ = other.close_;
+ other.descriptor_ = -1;
+ other.auto_close_ = false;
+ other.close_ = nullptr;
+ }
+ return *this;
+}
+
+bool UnixFileDescriptor::IsValid() const { return this->descriptor_ >= 0; }
+
+int UnixFileDescriptor::GetValue() const {
+ if (!this->IsValid()) {
+ throw Exception("Can't get value of an invalid unix file descriptor.");
+ }
+ return this->descriptor_;
+}
+
+void UnixFileDescriptor::Close() {
+ if (!this->IsValid()) {
+ throw Exception("Can't close an invalid unix file descriptor.");
+ }
+ if (!this->DoClose()) {
+ throw ErrnoException(u"Failed to call close on file descriptor.");
+ }
+ descriptor_ = -1;
+ auto_close_ = false;
+}
+
+bool UnixFileDescriptor::DoClose() {
+ if (this->close_) {
+ return this->close_(this->descriptor_) == 0;
+ } else {
+ return ::close(this->descriptor_) == 0;
+ }
+}
+
+UniDirectionalUnixPipeResult OpenUniDirectionalPipe(UnixPipeFlag flags) {
+ int fds[2];
+ if (::pipe(fds) != 0) {
+ throw ErrnoException(u"Failed to create unix pipe.");
+ }
+
+ if (flags & UnixPipeFlags::NonBlock) {
+ ::fcntl(fds[0], F_SETFL, O_NONBLOCK);
+ ::fcntl(fds[1], F_SETFL, O_NONBLOCK);
+ }
+
+ return {UnixFileDescriptor(fds[0]), UnixFileDescriptor(fds[1])};
+}
+} // namespace cru::platform::unix