1 | |
2 | |
3 | |
4 | |
5 | |
6 | |
7 | |
8 | |
9 | |
10 | #include "lldb/Host/posix/PipePosix.h" |
11 | |
12 | #include <errno(*__errno_location ()).h> |
13 | #include <fcntl.h> |
14 | #include <unistd.h> |
15 | #include <sys/types.h> |
16 | |
17 | using namespace lldb; |
18 | using namespace lldb_private; |
19 | |
20 | int PipePosix::kInvalidDescriptor = -1; |
21 | |
22 | enum PIPES { READ, WRITE }; |
23 | |
24 | |
25 | |
26 | #if defined(__linux__1) || (defined(__FreeBSD__) && __FreeBSD__ >= 10) |
27 | #define PIPE2_SUPPORTED1 1 |
28 | #else |
29 | #define PIPE2_SUPPORTED1 0 |
30 | #endif |
31 | |
32 | namespace |
33 | { |
34 | |
35 | #if defined(FD_CLOEXEC1) && !PIPE2_SUPPORTED1 |
36 | bool SetCloexecFlag(int fd) |
37 | { |
38 | int flags = ::fcntl(fd, F_GETFD1); |
39 | if (flags == -1) |
40 | return false; |
41 | return (::fcntl(fd, F_SETFD2, flags | FD_CLOEXEC1) == 0); |
42 | } |
43 | #endif |
44 | |
45 | } |
46 | |
47 | PipePosix::PipePosix() |
48 | { |
49 | m_fds[READ] = PipePosix::kInvalidDescriptor; |
50 | m_fds[WRITE] = PipePosix::kInvalidDescriptor; |
51 | } |
52 | |
53 | PipePosix::~PipePosix() |
54 | { |
55 | Close(); |
56 | } |
57 | |
58 | Error |
59 | PipePosix::CreateNew(bool child_processes_inherit) |
60 | { |
61 | Error error; |
62 | if (CanRead() || CanWrite()) |
63 | { |
64 | error.SetError(EINVAL22, eErrorTypePOSIX); |
65 | return error; |
66 | } |
67 | |
68 | #if PIPE2_SUPPORTED1 |
69 | if (::pipe2(m_fds, (child_processes_inherit) ? 0 : O_CLOEXEC02000000) == 0) |
70 | return error; |
71 | #else |
72 | if (::pipe(m_fds) == 0) |
73 | { |
74 | #ifdef FD_CLOEXEC1 |
75 | if (!child_processes_inherit) |
76 | { |
77 | if (!SetCloexecFlag(m_fds[0]) || !SetCloexecFlag(m_fds[1])) |
78 | { |
79 | error.SetErrorToErrno(); |
80 | Close(); |
81 | return error; |
82 | } |
83 | } |
84 | #endif |
85 | return error; |
86 | } |
87 | #endif |
88 | |
89 | m_fds[READ] = PipePosix::kInvalidDescriptor; |
90 | m_fds[WRITE] = PipePosix::kInvalidDescriptor; |
91 | error.SetErrorToErrno(); |
92 | return error; |
93 | } |
94 | |
95 | Error |
96 | PipePosix::CreateNew(llvm::StringRef name, bool child_process_inherit) |
97 | { |
98 | Error error; |
99 | if (CanRead() || CanWrite()) |
100 | error.SetErrorString("Pipe is already opened"); |
101 | else if (name.empty()) |
102 | error.SetErrorString("Cannot create named pipe with empty name."); |
103 | else |
104 | error.SetErrorString("Not implemented"); |
105 | return error; |
106 | } |
107 | |
108 | Error |
109 | PipePosix::OpenAsReader(llvm::StringRef name, bool child_process_inherit) |
110 | { |
111 | Error error; |
112 | if (CanRead() || CanWrite()) |
113 | error.SetErrorString("Pipe is already opened"); |
114 | else if (name.empty()) |
115 | error.SetErrorString("Cannot open named pipe with empty name."); |
116 | else |
117 | error.SetErrorString("Not implemented"); |
118 | return error; |
119 | } |
120 | |
121 | Error |
122 | PipePosix::OpenAsWriter(llvm::StringRef name, bool child_process_inherit) |
123 | { |
124 | Error error; |
125 | if (CanRead() || CanWrite()) |
126 | error.SetErrorString("Pipe is already opened"); |
127 | else if (name.empty()) |
128 | error.SetErrorString("Cannot create named pipe with empty name."); |
129 | else |
130 | error.SetErrorString("Not implemented"); |
131 | return error; |
132 | } |
133 | |
134 | int |
135 | PipePosix::GetReadFileDescriptor() const |
136 | { |
137 | return m_fds[READ]; |
138 | } |
139 | |
140 | int |
141 | PipePosix::GetWriteFileDescriptor() const |
142 | { |
143 | return m_fds[WRITE]; |
144 | } |
145 | |
146 | int |
147 | PipePosix::ReleaseReadFileDescriptor() |
148 | { |
149 | const int fd = m_fds[READ]; |
150 | m_fds[READ] = PipePosix::kInvalidDescriptor; |
151 | return fd; |
152 | } |
153 | |
154 | int |
155 | PipePosix::ReleaseWriteFileDescriptor() |
156 | { |
157 | const int fd = m_fds[WRITE]; |
158 | m_fds[WRITE] = PipePosix::kInvalidDescriptor; |
159 | return fd; |
160 | } |
161 | |
162 | void |
163 | PipePosix::Close() |
164 | { |
165 | CloseReadFileDescriptor(); |
166 | CloseWriteFileDescriptor(); |
167 | } |
168 | |
169 | bool |
170 | PipePosix::CanRead() const |
171 | { |
172 | return m_fds[READ] != PipePosix::kInvalidDescriptor; |
173 | } |
174 | |
175 | bool |
176 | PipePosix::CanWrite() const |
177 | { |
178 | return m_fds[WRITE] != PipePosix::kInvalidDescriptor; |
179 | } |
180 | |
181 | void |
182 | PipePosix::CloseReadFileDescriptor() |
183 | { |
184 | if (CanRead()) |
185 | { |
186 | int err; |
187 | err = close(m_fds[READ]); |
188 | m_fds[READ] = PipePosix::kInvalidDescriptor; |
189 | } |
190 | } |
191 | |
192 | void |
193 | PipePosix::CloseWriteFileDescriptor() |
194 | { |
195 | if (CanWrite()) |
196 | { |
197 | int err; |
198 | err = close(m_fds[WRITE]); |
| Value stored to 'err' is never read |
199 | m_fds[WRITE] = PipePosix::kInvalidDescriptor; |
200 | } |
201 | } |
202 | |
203 | Error |
204 | PipePosix::Read(void *buf, size_t num_bytes, size_t &bytes_read) |
205 | { |
206 | bytes_read = 0; |
207 | Error error; |
208 | |
209 | if (CanRead()) |
210 | { |
211 | const int fd = GetReadFileDescriptor(); |
212 | int result = read(fd, buf, num_bytes); |
213 | if (result >= 0) |
214 | bytes_read = result; |
215 | else |
216 | error.SetErrorToErrno(); |
217 | } |
218 | else |
219 | error.SetError(EINVAL22, eErrorTypePOSIX); |
220 | |
221 | return error; |
222 | } |
223 | |
224 | Error |
225 | PipePosix::ReadWithTimeout(void *buf, size_t num_bytes, const std::chrono::milliseconds &duration, size_t &bytes_read) |
226 | { |
227 | bytes_read = 0; |
228 | Error error; |
229 | error.SetErrorString("Not implemented"); |
230 | return error; |
231 | } |
232 | |
233 | Error |
234 | PipePosix::Write(const void *buf, size_t num_bytes, size_t &bytes_written) |
235 | { |
236 | bytes_written = 0; |
237 | Error error; |
238 | |
239 | if (CanWrite()) |
240 | { |
241 | const int fd = GetWriteFileDescriptor(); |
242 | int result = write(fd, buf, num_bytes); |
243 | if (result >= 0) |
244 | bytes_written = result; |
245 | else |
246 | error.SetErrorToErrno(); |
247 | } |
248 | else |
249 | error.SetError(EINVAL22, eErrorTypePOSIX); |
250 | |
251 | return error; |
252 | } |