blob: d64fad123e297e6d1b9dff904dc9113e1e3052d2 [file] [log] [blame]
James Kuszmaul3224b8e2022-01-07 19:00:39 -08001#include "aos/util/scoped_pipe.h"
2
3#include <fcntl.h>
Austin Schuh60e77942022-05-16 17:48:24 -07004
James Kuszmaul3224b8e2022-01-07 19:00:39 -08005#include "glog/logging.h"
6
7namespace aos::util {
8
9ScopedPipe::ScopedPipe(int fd) : fd_(fd) {}
10
11ScopedPipe::~ScopedPipe() {
12 if (fd_ != -1) {
13 PCHECK(close(fd_) != -1);
14 }
15}
16
17ScopedPipe::ScopedPipe(ScopedPipe &&scoped_pipe) : fd_(scoped_pipe.fd_) {
18 scoped_pipe.fd_ = -1;
19}
20
21ScopedPipe &ScopedPipe::operator=(ScopedPipe &&scoped_pipe) {
22 if (fd_ != -1) {
23 PCHECK(close(fd_) != -1);
24 }
25 fd_ = scoped_pipe.fd_;
26 scoped_pipe.fd_ = -1;
27 return *this;
28}
29
James Kuszmauld42edb42022-01-07 18:00:16 -080030ScopedPipe::PipePair ScopedPipe::MakePipe() {
James Kuszmaul3224b8e2022-01-07 19:00:39 -080031 int fds[2];
32 PCHECK(pipe(fds) != -1);
33 PCHECK(fcntl(fds[0], F_SETFL, fcntl(fds[0], F_GETFL) | O_NONBLOCK) != -1);
34 PCHECK(fcntl(fds[1], F_SETFL, fcntl(fds[1], F_GETFL) | O_NONBLOCK) != -1);
James Kuszmauld42edb42022-01-07 18:00:16 -080035 return {std::unique_ptr<ScopedReadPipe>(new ScopedReadPipe(fds[0])),
36 std::unique_ptr<ScopedWritePipe>(new ScopedWritePipe(fds[1]))};
37}
38
39void ScopedPipe::SetCloexec() {
40 // FD_CLOEXEC is the only known file descriptor flag, but call GETFD just in
41 // case.
42 int flags = fcntl(fd(), F_GETFD);
43 PCHECK(flags != -1);
44 PCHECK(fcntl(fd(), F_SETFD, flags | FD_CLOEXEC) != -1);
James Kuszmaul3224b8e2022-01-07 19:00:39 -080045}
46
James Kuszmaul731a05d2022-01-07 17:59:26 -080047size_t ScopedPipe::ScopedReadPipe::Read(std::string *buffer) {
48 CHECK_NOTNULL(buffer);
49 constexpr ssize_t kBufferSize = 1024;
50 const size_t original_size = buffer->size();
51 size_t read_bytes = 0;
52 while (true) {
53 buffer->resize(buffer->size() + kBufferSize);
54 const ssize_t result =
55 read(fd(), buffer->data() + buffer->size() - kBufferSize, kBufferSize);
56 if (result == -1) {
57 if (errno == EAGAIN || errno == EWOULDBLOCK) {
Austin Schuh0d164112023-08-17 12:50:51 -070058 buffer->resize(original_size + read_bytes);
59 return read_bytes;
James Kuszmaul731a05d2022-01-07 17:59:26 -080060 }
61 PLOG(FATAL) << "Error on reading pipe.";
62 } else if (result < kBufferSize) {
63 read_bytes += result;
64 buffer->resize(original_size + read_bytes);
65 break;
66 } else {
67 CHECK_EQ(result, kBufferSize);
68 read_bytes += result;
69 }
70 }
71 return read_bytes;
72}
73
James Kuszmaul3224b8e2022-01-07 19:00:39 -080074std::optional<uint32_t> ScopedPipe::ScopedReadPipe::Read() {
75 uint32_t buf;
76 ssize_t result = read(fd(), &buf, sizeof(buf));
77 if (result == sizeof(buf)) {
78 return buf;
79 } else {
80 return std::nullopt;
81 }
82}
83
84void ScopedPipe::ScopedWritePipe::Write(uint32_t data) {
85 ssize_t result = write(fd(), &data, sizeof(data));
86 PCHECK(result != -1);
James Kuszmaul731a05d2022-01-07 17:59:26 -080087 CHECK_EQ(static_cast<size_t>(result), sizeof(data));
88}
89
90void ScopedPipe::ScopedWritePipe::Write(absl::Span<const uint8_t> data) {
91 ssize_t result = write(fd(), data.data(), data.size());
92 PCHECK(result != -1);
93 CHECK_EQ(static_cast<size_t>(result), data.size());
James Kuszmaul3224b8e2022-01-07 19:00:39 -080094}
95
96} // namespace aos::util