Branch data 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 : 84 : int flush_fd(int fd) {
15 : 84 : struct pollfd pollfd = {
16 : : .fd = fd,
17 : : .events = POLLIN,
18 : : };
19 : 84 : 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 : 56 : for (;;) {
27 : : char buf[LINE_MAX];
28 : : ssize_t l;
29 : : int r;
30 : :
31 : 140 : r = poll(&pollfd, 1, 0);
32 [ - + ]: 140 : if (r < 0) {
33 [ # # ]: 0 : if (errno == EINTR)
34 : 0 : continue;
35 : :
36 : 84 : return -errno;
37 : :
38 [ + + ]: 140 : } else if (r == 0)
39 : 84 : return count;
40 : :
41 : 56 : l = read(fd, buf, sizeof(buf));
42 [ - + ]: 56 : 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 [ - + ]: 56 : } else if (l == 0)
52 : 0 : return count;
53 : :
54 : 56 : count += (int) l;
55 : : }
56 : : }
57 : :
58 : 3034 : ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll) {
59 : 3034 : uint8_t *p = buf;
60 : 3034 : ssize_t n = 0;
61 : :
62 [ - + ]: 3034 : assert(fd >= 0);
63 [ - + ]: 3034 : assert(buf);
64 : :
65 : : /* If called with nbytes == 0, let's call read() at least
66 : : * once, to validate the operation */
67 : :
68 [ - + ]: 3034 : if (nbytes > (size_t) SSIZE_MAX)
69 : 0 : return -EINVAL;
70 : :
71 : : do {
72 : : ssize_t k;
73 : :
74 : 3238 : k = read(fd, p, nbytes);
75 [ - + ]: 3238 : 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 [ + + ]: 3238 : if (k == 0)
93 : 204 : return n;
94 : :
95 [ - + ]: 3034 : assert((size_t) k <= nbytes);
96 : :
97 : 3034 : p += k;
98 : 3034 : nbytes -= k;
99 : 3034 : n += k;
100 [ + + ]: 3034 : } while (nbytes > 0);
101 : :
102 : 2830 : return n;
103 : : }
104 : :
105 : 2830 : int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll) {
106 : : ssize_t n;
107 : :
108 : 2830 : n = loop_read(fd, buf, nbytes, do_poll);
109 [ - + ]: 2830 : if (n < 0)
110 : 0 : return (int) n;
111 [ - + ]: 2830 : if ((size_t) n != nbytes)
112 : 0 : return -EIO;
113 : :
114 : 2830 : return 0;
115 : : }
116 : :
117 : 208 : int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll) {
118 : 208 : const uint8_t *p = buf;
119 : :
120 [ - + ]: 208 : assert(fd >= 0);
121 [ - + ]: 208 : assert(buf);
122 : :
123 [ - + ]: 208 : if (_unlikely_(nbytes > (size_t) SSIZE_MAX))
124 : 0 : return -EINVAL;
125 : :
126 : : do {
127 : : ssize_t k;
128 : :
129 : 208 : k = write(fd, p, nbytes);
130 [ - + ]: 208 : 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 [ + - - + ]: 208 : if (_unlikely_(nbytes > 0 && k == 0)) /* Can't really happen */
147 : 0 : return -EIO;
148 : :
149 [ - + ]: 208 : assert((size_t) k <= nbytes);
150 : :
151 : 208 : p += k;
152 : 208 : nbytes -= k;
153 [ - + ]: 208 : } while (nbytes > 0);
154 : :
155 : 208 : 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 : 28 : int fd_wait_for_event(int fd, int event, usec_t t) {
177 : :
178 : 28 : struct pollfd pollfd = {
179 : : .fd = fd,
180 : : .events = event,
181 : : };
182 : :
183 : : struct timespec ts;
184 : : int r;
185 : :
186 [ + - ]: 28 : r = ppoll(&pollfd, 1, t == USEC_INFINITY ? NULL : timespec_store(&ts, t), NULL);
187 [ - + ]: 28 : if (r < 0)
188 : 0 : return -errno;
189 [ - + ]: 28 : if (r == 0)
190 : 0 : return 0;
191 : :
192 : 28 : return pollfd.revents;
193 : : }
194 : :
195 : 232 : static size_t nul_length(const uint8_t *p, size_t sz) {
196 : 232 : size_t n = 0;
197 : :
198 [ + + ]: 440 : while (sz > 0) {
199 [ + + ]: 420 : if (*p != 0)
200 : 212 : break;
201 : :
202 : 208 : n++;
203 : 208 : p++;
204 : 208 : sz--;
205 : : }
206 : :
207 : 232 : return n;
208 : : }
209 : :
210 : 20 : 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 : 20 : q = w = p;
215 : 20 : e = q + sz;
216 [ + + ]: 252 : while (q < e) {
217 : : size_t n;
218 : :
219 : 232 : 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 [ + + + + ]: 232 : if ((n > run_length) ||
225 [ + + + + ]: 216 : (n > 0 && q == p) ||
226 [ + + ]: 28 : (n > 0 && q + n >= e)) {
227 [ + + ]: 36 : if (q > w) {
228 : 24 : l = write(fd, w, q - w);
229 [ - + ]: 24 : if (l < 0)
230 : 0 : return -errno;
231 [ - + ]: 24 : if (l != q -w)
232 : 0 : return -EIO;
233 : : }
234 : :
235 [ - + ]: 36 : if (lseek(fd, n, SEEK_CUR) == (off_t) -1)
236 : 0 : return -errno;
237 : :
238 : 36 : q += n;
239 : 36 : w = q;
240 [ + + ]: 196 : } else if (n > 0)
241 : 20 : q += n;
242 : : else
243 : 176 : q++;
244 : : }
245 : :
246 [ - + ]: 20 : 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 : 20 : 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 : 8 : void iovw_free_contents(struct iovec_wrapper *iovw, bool free_vectors) {
279 [ - + ]: 8 : if (free_vectors)
280 [ # # ]: 0 : for (size_t i = 0; i < iovw->count; i++)
281 : 0 : free(iovw->iovec[i].iov_base);
282 : :
283 : 8 : iovw->iovec = mfree(iovw->iovec);
284 : 8 : iovw->count = 0;
285 : 8 : iovw->size_bytes = 0;
286 : 8 : }
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 : 28 : int iovw_put(struct iovec_wrapper *iovw, void *data, size_t len) {
301 [ - + ]: 28 : if (iovw->count >= IOV_MAX)
302 : 0 : return -E2BIG;
303 : :
304 [ - + ]: 28 : if (!GREEDY_REALLOC(iovw->iovec, iovw->size_bytes, iovw->count + 1))
305 : 0 : return log_oom();
306 : :
307 : 28 : iovw->iovec[iovw->count++] = IOVEC_MAKE(data, len);
308 : 28 : 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 : 8 : void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new) {
333 : : size_t i;
334 : :
335 [ - + ]: 8 : for (i = 0; i < iovw->count; i++)
336 : 0 : iovw->iovec[i].iov_base = (char *)iovw->iovec[i].iov_base - old + new;
337 : 8 : }
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 : : }
|