Line data Source code
1 : /* SPDX-License-Identifier: LGPL-2.1+ */
2 :
3 : #include <errno.h>
4 : #include <limits.h>
5 : #include <poll.h>
6 : #include <stdio.h>
7 : #include <time.h>
8 : #include <unistd.h>
9 :
10 : #include "io-util.h"
11 : #include "string-util.h"
12 : #include "time-util.h"
13 :
14 21 : int flush_fd(int fd) {
15 21 : struct pollfd pollfd = {
16 : .fd = fd,
17 : .events = POLLIN,
18 : };
19 21 : int count = 0;
20 :
21 : /* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything
22 : * read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read
23 : * (due to IP packet checksum mismatches), hence this function is only safe to be non-blocking if the fd used
24 : * was set to non-blocking too. */
25 :
26 14 : for (;;) {
27 : char buf[LINE_MAX];
28 : ssize_t l;
29 : int r;
30 :
31 35 : r = poll(&pollfd, 1, 0);
32 35 : if (r < 0) {
33 0 : if (errno == EINTR)
34 0 : continue;
35 :
36 21 : return -errno;
37 :
38 35 : } else if (r == 0)
39 21 : return count;
40 :
41 14 : l = read(fd, buf, sizeof(buf));
42 14 : if (l < 0) {
43 :
44 0 : if (errno == EINTR)
45 0 : continue;
46 :
47 0 : if (errno == EAGAIN)
48 0 : return count;
49 :
50 0 : return -errno;
51 14 : } else if (l == 0)
52 0 : return count;
53 :
54 14 : count += (int) l;
55 : }
56 : }
57 :
58 725 : ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
59 725 : uint8_t *p = buf;
60 725 : ssize_t n = 0;
61 :
62 725 : assert(fd >= 0);
63 725 : assert(buf);
64 :
65 : /* If called with nbytes == 0, let's call read() at least
66 : * once, to validate the operation */
67 :
68 725 : if (nbytes > (size_t) SSIZE_MAX)
69 0 : return -EINVAL;
70 :
71 : do {
72 : ssize_t k;
73 :
74 776 : k = read(fd, p, nbytes);
75 776 : if (k < 0) {
76 0 : if (errno == EINTR)
77 0 : continue;
78 :
79 0 : if (errno == EAGAIN && do_poll) {
80 :
81 : /* We knowingly ignore any return value here,
82 : * and expect that any error/EOF is reported
83 : * via read() */
84 :
85 0 : (void) fd_wait_for_event(fd, POLLIN, USEC_INFINITY);
86 0 : continue;
87 : }
88 :
89 0 : return n > 0 ? n : -errno;
90 : }
91 :
92 776 : if (k == 0)
93 51 : return n;
94 :
95 725 : assert((size_t) k <= nbytes);
96 :
97 725 : p += k;
98 725 : nbytes -= k;
99 725 : n += k;
100 725 : } while (nbytes > 0);
101 :
102 674 : return n;
103 : }
104 :
105 674 : int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) {
106 : ssize_t n;
107 :
108 674 : n = loop_read(fd, buf, nbytes, do_poll);
109 674 : if (n < 0)
110 0 : return (int) n;
111 674 : if ((size_t) n != nbytes)
112 0 : return -EIO;
113 :
114 674 : return 0;
115 : }
116 :
117 52 : int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
118 52 : const uint8_t *p = buf;
119 :
120 52 : assert(fd >= 0);
121 52 : assert(buf);
122 :
123 52 : if (_unlikely_(nbytes > (size_t) SSIZE_MAX))
124 0 : return -EINVAL;
125 :
126 : do {
127 : ssize_t k;
128 :
129 52 : k = write(fd, p, nbytes);
130 52 : if (k < 0) {
131 0 : if (errno == EINTR)
132 0 : continue;
133 :
134 0 : if (errno == EAGAIN && do_poll) {
135 : /* We knowingly ignore any return value here,
136 : * and expect that any error/EOF is reported
137 : * via write() */
138 :
139 0 : (void) fd_wait_for_event(fd, POLLOUT, USEC_INFINITY);
140 0 : continue;
141 : }
142 :
143 0 : return -errno;
144 : }
145 :
146 52 : if (_unlikely_(nbytes > 0 && k == 0)) /* Can't really happen */
147 0 : return -EIO;
148 :
149 52 : assert((size_t) k <= nbytes);
150 :
151 52 : p += k;
152 52 : nbytes -= k;
153 52 : } while (nbytes > 0);
154 :
155 52 : return 0;
156 : }
157 :
158 0 : int pipe_eof(int fd) {
159 0 : struct pollfd pollfd = {
160 : .fd = fd,
161 : .events = POLLIN|POLLHUP,
162 : };
163 :
164 : int r;
165 :
166 0 : r = poll(&pollfd, 1, 0);
167 0 : if (r < 0)
168 0 : return -errno;
169 :
170 0 : if (r == 0)
171 0 : return 0;
172 :
173 0 : return pollfd.revents & POLLHUP;
174 : }
175 :
176 7 : int fd_wait_for_event(int fd, int event, usec_t t) {
177 :
178 7 : struct pollfd pollfd = {
179 : .fd = fd,
180 : .events = event,
181 : };
182 :
183 : struct timespec ts;
184 : int r;
185 :
186 7 : r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
187 7 : if (r < 0)
188 0 : return -errno;
189 7 : if (r == 0)
190 0 : return 0;
191 :
192 7 : return pollfd.revents;
193 : }
194 :
195 58 : static size_t nul_length(const uint8_t *p, size_t sz) {
196 58 : size_t n = 0;
197 :
198 110 : while (sz > 0) {
199 105 : if (*p != 0)
200 53 : break;
201 :
202 52 : n++;
203 52 : p++;
204 52 : sz--;
205 : }
206 :
207 58 : return n;
208 : }
209 :
210 5 : ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length) {
211 : const uint8_t *q, *w, *e;
212 : ssize_t l;
213 :
214 5 : q = w = p;
215 5 : e = q + sz;
216 63 : while (q < e) {
217 : size_t n;
218 :
219 58 : n = nul_length(q, e - q);
220 :
221 : /* If there are more than the specified run length of
222 : * NUL bytes, or if this is the beginning or the end
223 : * of the buffer, then seek instead of write */
224 58 : if ((n > run_length) ||
225 54 : (n > 0 && q == p) ||
226 7 : (n > 0 && q + n >= e)) {
227 9 : if (q > w) {
228 6 : l = write(fd, w, q - w);
229 6 : if (l < 0)
230 0 : return -errno;
231 6 : if (l != q -w)
232 0 : return -EIO;
233 : }
234 :
235 9 : if (lseek(fd, n, SEEK_CUR) == (off_t) -1)
236 0 : return -errno;
237 :
238 9 : q += n;
239 9 : w = q;
240 49 : } else if (n > 0)
241 5 : q += n;
242 : else
243 44 : q++;
244 : }
245 :
246 5 : if (q > w) {
247 0 : l = write(fd, w, q - w);
248 0 : if (l < 0)
249 0 : return -errno;
250 0 : if (l != q - w)
251 0 : return -EIO;
252 : }
253 :
254 5 : return q - (const uint8_t*) p;
255 : }
256 :
257 0 : char* set_iovec_string_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value) {
258 : char *x;
259 :
260 0 : x = strjoin(field, value);
261 0 : if (x)
262 0 : iovec[(*n_iovec)++] = IOVEC_MAKE_STRING(x);
263 0 : return x;
264 : }
265 :
266 0 : char* set_iovec_string_field_free(struct iovec *iovec, size_t *n_iovec, const char *field, char *value) {
267 : char *x;
268 :
269 0 : x = set_iovec_string_field(iovec, n_iovec, field, value);
270 0 : free(value);
271 0 : return x;
272 : }
273 :
274 0 : struct iovec_wrapper *iovw_new(void) {
275 0 : return malloc0(sizeof(struct iovec_wrapper));
276 : }
277 :
278 2 : void iovw_free_contents(struct iovec_wrapper *iovw, bool free_vectors) {
279 2 : if (free_vectors)
280 0 : for (size_t i = 0; i < iovw->count; i++)
281 0 : free(iovw->iovec[i].iov_base);
282 :
283 2 : iovw->iovec = mfree(iovw->iovec);
284 2 : iovw->count = 0;
285 2 : iovw->size_bytes = 0;
286 2 : }
287 :
288 0 : struct iovec_wrapper *iovw_free_free(struct iovec_wrapper *iovw) {
289 0 : iovw_free_contents(iovw, true);
290 :
291 0 : return mfree(iovw);
292 : }
293 :
294 0 : struct iovec_wrapper *iovw_free(struct iovec_wrapper *iovw) {
295 0 : iovw_free_contents(iovw, false);
296 :
297 0 : return mfree(iovw);
298 : }
299 :
300 7 : int iovw_put(struct iovec_wrapper *iovw, void *data, size_t len) {
301 7 : if (iovw->count >= IOV_MAX)
302 0 : return -E2BIG;
303 :
304 7 : if (!GREEDY_REALLOC(iovw->iovec, iovw->size_bytes, iovw->count + 1))
305 0 : return log_oom();
306 :
307 7 : iovw->iovec[iovw->count++] = IOVEC_MAKE(data, len);
308 7 : return 0;
309 : }
310 :
311 0 : int iovw_put_string_field(struct iovec_wrapper *iovw, const char *field, const char *value) {
312 0 : _cleanup_free_ char *x = NULL;
313 : int r;
314 :
315 0 : x = strjoin(field, value);
316 0 : if (!x)
317 0 : return log_oom();
318 :
319 0 : r = iovw_put(iovw, x, strlen(x));
320 0 : if (r >= 0)
321 0 : TAKE_PTR(x);
322 :
323 0 : return r;
324 : }
325 :
326 0 : int iovw_put_string_field_free(struct iovec_wrapper *iovw, const char *field, char *value) {
327 0 : _cleanup_free_ _unused_ char *free_ptr = value;
328 :
329 0 : return iovw_put_string_field(iovw, field, value);
330 : }
331 :
332 2 : void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new) {
333 : size_t i;
334 :
335 2 : for (i = 0; i < iovw->count; i++)
336 0 : iovw->iovec[i].iov_base = (char *)iovw->iovec[i].iov_base - old + new;
337 2 : }
338 :
339 0 : size_t iovw_size(struct iovec_wrapper *iovw) {
340 0 : size_t n = 0, i;
341 :
342 0 : for (i = 0; i < iovw->count; i++)
343 0 : n += iovw->iovec[i].iov_len;
344 :
345 0 : return n;
346 : }
|