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