]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/io-util.c
18baadb1fed767ddb014c3d8d108a1436bf000e9
1 /* SPDX-License-Identifier: LGPL-2.1+ */
10 #include "string-util.h"
11 #include "time-util.h"
13 int flush_fd(int fd
) {
16 /* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything
17 * read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read
18 * (due to IP packet checksum mismatches), hence this function is only safe to be non-blocking if the fd used
19 * was set to non-blocking too. */
26 r
= fd_wait_for_event(fd
, POLLIN
, 0);
36 l
= read(fd
, buf
, sizeof(buf
));
52 ssize_t
loop_read(int fd
, void *buf
, size_t nbytes
, bool do_poll
) {
59 /* If called with nbytes == 0, let's call read() at least
60 * once, to validate the operation */
62 if (nbytes
> (size_t) SSIZE_MAX
)
68 k
= read(fd
, p
, nbytes
);
73 if (errno
== EAGAIN
&& do_poll
) {
75 /* We knowingly ignore any return value here,
76 * and expect that any error/EOF is reported
79 (void) fd_wait_for_event(fd
, POLLIN
, USEC_INFINITY
);
83 return n
> 0 ? n
: -errno
;
89 assert((size_t) k
<= nbytes
);
99 int loop_read_exact(int fd
, void *buf
, size_t nbytes
, bool do_poll
) {
102 n
= loop_read(fd
, buf
, nbytes
, do_poll
);
105 if ((size_t) n
!= nbytes
)
111 int loop_write(int fd
, const void *buf
, size_t nbytes
, bool do_poll
) {
112 const uint8_t *p
= buf
;
117 if (_unlikely_(nbytes
> (size_t) SSIZE_MAX
))
123 k
= write(fd
, p
, nbytes
);
128 if (errno
== EAGAIN
&& do_poll
) {
129 /* We knowingly ignore any return value here,
130 * and expect that any error/EOF is reported
133 (void) fd_wait_for_event(fd
, POLLOUT
, USEC_INFINITY
);
140 if (_unlikely_(nbytes
> 0 && k
== 0)) /* Can't really happen */
143 assert((size_t) k
<= nbytes
);
147 } while (nbytes
> 0);
152 int pipe_eof(int fd
) {
155 r
= fd_wait_for_event(fd
, POLLIN
, 0);
161 return !!(r
& POLLHUP
);
164 int fd_wait_for_event(int fd
, int event
, usec_t t
) {
166 struct pollfd pollfd
= {
174 r
= ppoll(&pollfd
, 1, t
== USEC_INFINITY
? NULL
: timespec_store(&ts
, t
), NULL
);
180 if (pollfd
.revents
& POLLNVAL
)
183 return pollfd
.revents
;
186 static size_t nul_length(const uint8_t *p
, size_t sz
) {
201 ssize_t
sparse_write(int fd
, const void *p
, size_t sz
, size_t run_length
) {
202 const uint8_t *q
, *w
, *e
;
210 n
= nul_length(q
, e
- q
);
212 /* If there are more than the specified run length of
213 * NUL bytes, or if this is the beginning or the end
214 * of the buffer, then seek instead of write */
215 if ((n
> run_length
) ||
217 (n
> 0 && q
+ n
>= e
)) {
219 l
= write(fd
, w
, q
- w
);
226 if (lseek(fd
, n
, SEEK_CUR
) == (off_t
) -1)
238 l
= write(fd
, w
, q
- w
);
245 return q
- (const uint8_t*) p
;
248 char* set_iovec_string_field(struct iovec
*iovec
, size_t *n_iovec
, const char *field
, const char *value
) {
251 x
= strjoin(field
, value
);
253 iovec
[(*n_iovec
)++] = IOVEC_MAKE_STRING(x
);
257 char* set_iovec_string_field_free(struct iovec
*iovec
, size_t *n_iovec
, const char *field
, char *value
) {
260 x
= set_iovec_string_field(iovec
, n_iovec
, field
, value
);
265 struct iovec_wrapper
*iovw_new(void) {
266 return malloc0(sizeof(struct iovec_wrapper
));
269 void iovw_free_contents(struct iovec_wrapper
*iovw
, bool free_vectors
) {
271 for (size_t i
= 0; i
< iovw
->count
; i
++)
272 free(iovw
->iovec
[i
].iov_base
);
274 iovw
->iovec
= mfree(iovw
->iovec
);
276 iovw
->size_bytes
= 0;
279 struct iovec_wrapper
*iovw_free_free(struct iovec_wrapper
*iovw
) {
280 iovw_free_contents(iovw
, true);
285 struct iovec_wrapper
*iovw_free(struct iovec_wrapper
*iovw
) {
286 iovw_free_contents(iovw
, false);
291 int iovw_put(struct iovec_wrapper
*iovw
, void *data
, size_t len
) {
292 if (iovw
->count
>= IOV_MAX
)
295 if (!GREEDY_REALLOC(iovw
->iovec
, iovw
->size_bytes
, iovw
->count
+ 1))
298 iovw
->iovec
[iovw
->count
++] = IOVEC_MAKE(data
, len
);
302 int iovw_put_string_field(struct iovec_wrapper
*iovw
, const char *field
, const char *value
) {
303 _cleanup_free_
char *x
= NULL
;
306 x
= strjoin(field
, value
);
310 r
= iovw_put(iovw
, x
, strlen(x
));
317 int iovw_put_string_field_free(struct iovec_wrapper
*iovw
, const char *field
, char *value
) {
318 _cleanup_free_ _unused_
char *free_ptr
= value
;
320 return iovw_put_string_field(iovw
, field
, value
);
323 void iovw_rebase(struct iovec_wrapper
*iovw
, char *old
, char *new) {
326 for (i
= 0; i
< iovw
->count
; i
++)
327 iovw
->iovec
[i
].iov_base
= (char *)iovw
->iovec
[i
].iov_base
- old
+ new;
330 size_t iovw_size(struct iovec_wrapper
*iovw
) {
333 for (i
= 0; i
< iovw
->count
; i
++)
334 n
+= iovw
->iovec
[i
].iov_len
;