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