• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  * http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 
16 #include "pipe.h"
17 
18 #include "failure_retry.h"
19 
20 #include <vector>
21 #include <array>
22 #include <cerrno>
23 
24 #include <unistd.h>
25 #include <fcntl.h>
26 #include <poll.h>
27 
28 namespace panda::os::unix {
29 
CreatePipe()30 std::pair<UniqueFd, UniqueFd> CreatePipe()
31 {
32     constexpr size_t FD_NUM = 2;
33     std::array<int, FD_NUM> fds {};
34     // NOLINTNEXTLINE(android-cloexec-pipe)
35     if (PANDA_FAILURE_RETRY(pipe(fds.data())) == -1) {
36         return std::pair<UniqueFd, UniqueFd>();
37     }
38     return std::pair<UniqueFd, UniqueFd>(UniqueFd(fds[0]), UniqueFd(fds[1]));
39 }
40 
SetFdNonblocking(const UniqueFd & fd)41 int SetFdNonblocking(const UniqueFd &fd)
42 {
43     size_t flags;
44 #ifdef O_NONBLOCK
45     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg)
46     int res = fcntl(fd.Get(), F_GETFL, 0);
47     if (res < 0) {
48         flags = 0;
49     } else {
50         flags = static_cast<size_t>(res);
51     }
52     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg, hicpp-signed-bitwise)
53     return fcntl(fd.Get(), F_SETFL, flags | O_NONBLOCK);
54 #else
55     flags = 1;
56     return ioctl(fd, FIONBIO, &flags);
57 #endif
58 }
59 
ReadFromPipe(const UniqueFd & pipe_fd,void * buf,size_t size)60 Expected<size_t, Error> ReadFromPipe(const UniqueFd &pipe_fd, void *buf, size_t size)
61 {
62     ssize_t bytes_read = PANDA_FAILURE_RETRY(read(pipe_fd.Get(), buf, size));
63     if (bytes_read < 0) {
64         return Unexpected(Error(errno));
65     }
66     return {static_cast<size_t>(bytes_read)};
67 }
68 
WriteToPipe(const UniqueFd & pipe_fd,const void * buf,size_t size)69 Expected<size_t, Error> WriteToPipe(const UniqueFd &pipe_fd, const void *buf, size_t size)
70 {
71     ssize_t bytes_written = PANDA_FAILURE_RETRY(write(pipe_fd.Get(), buf, size));
72     if (bytes_written < 0) {
73         return Unexpected(Error(errno));
74     }
75     return {static_cast<size_t>(bytes_written)};
76 }
77 
WaitForEvent(const UniqueFd * handles,size_t size,EventType type)78 Expected<size_t, Error> WaitForEvent(const UniqueFd *handles, size_t size, EventType type)
79 {
80     uint16_t poll_events;
81     switch (type) {
82         case EventType::READY:
83             poll_events = POLLIN;
84             break;
85 
86         default:
87             return Unexpected(Error("Unknown event type"));
88     }
89 
90     // Initialize poll set
91     std::vector<pollfd> pollfds(size);
92     for (size_t i = 0; i < size; i++) {
93         pollfds[i].fd = handles[i].Get();  // NOLINT(cppcoreguidelines-pro-bounds-pointer-arithmetic)
94         pollfds[i].events = static_cast<int16_t>(poll_events);
95     }
96 
97     while (true) {
98         int res = PANDA_FAILURE_RETRY(poll(pollfds.data(), size, -1));
99         if (res == -1) {
100             return Unexpected(Error(errno));
101         }
102 
103         for (size_t i = 0; i < size; i++) {
104             if ((static_cast<size_t>(pollfds[i].revents) & poll_events) == poll_events) {
105                 return {i};
106             }
107         }
108     }
109 }
110 
Dup2(const UniqueFd & source,const UniqueFd & target)111 std::optional<Error> Dup2(const UniqueFd &source, const UniqueFd &target)
112 {
113     if (!source.IsValid()) {
114         return Error("Source fd is invalid");
115     }
116     if (PANDA_FAILURE_RETRY(dup2(source.Get(), target.Get())) == -1) {
117         return Error(errno);
118     }
119     return {};
120 }
121 
122 }  // namespace panda::os::unix
123