aboutsummaryrefslogtreecommitdiff
path: root/src/base/platform/unix/UnixFile.cpp
diff options
context:
space:
mode:
authorYuqian Yang <crupest@crupest.life>2025-09-02 22:29:11 +0800
committerYuqian Yang <crupest@crupest.life>2025-09-03 01:52:38 +0800
commit545a638929218a83d194402b3d52f5bffd87d9eb (patch)
treef659f671fec17f3ef7dced31f3a1f59673d18690 /src/base/platform/unix/UnixFile.cpp
parent5035f18f44f675af2faa4019b6de14b3f3aab270 (diff)
downloadcru-545a638929218a83d194402b3d52f5bffd87d9eb.tar.gz
cru-545a638929218a83d194402b3d52f5bffd87d9eb.tar.bz2
cru-545a638929218a83d194402b3d52f5bffd87d9eb.zip
UnixFileDescriptor.
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