]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/io-util.c
1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 This file is part of systemd.
5 Copyright 2010 Lennart Poettering
16 #include "time-util.h"
18 int flush_fd(int fd
) {
19 struct pollfd pollfd
= {
25 /* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything
26 * read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read
27 * (due to IP packet checksum mismatches), hence this function is only safe to be non-blocking if the fd used
28 * was set to non-blocking too. */
35 r
= poll(&pollfd
, 1, 0);
45 l
= read(fd
, buf
, sizeof(buf
));
62 ssize_t
loop_read(int fd
, void *buf
, size_t nbytes
, bool do_poll
) {
69 /* If called with nbytes == 0, let's call read() at least
70 * once, to validate the operation */
72 if (nbytes
> (size_t) SSIZE_MAX
)
78 k
= read(fd
, p
, nbytes
);
83 if (errno
== EAGAIN
&& do_poll
) {
85 /* We knowingly ignore any return value here,
86 * and expect that any error/EOF is reported
89 (void) fd_wait_for_event(fd
, POLLIN
, USEC_INFINITY
);
93 return n
> 0 ? n
: -errno
;
99 assert((size_t) k
<= nbytes
);
104 } while (nbytes
> 0);
109 int loop_read_exact(int fd
, void *buf
, size_t nbytes
, bool do_poll
) {
112 n
= loop_read(fd
, buf
, nbytes
, do_poll
);
115 if ((size_t) n
!= nbytes
)
121 int loop_write(int fd
, const void *buf
, size_t nbytes
, bool do_poll
) {
122 const uint8_t *p
= buf
;
127 if (_unlikely_(nbytes
> (size_t) SSIZE_MAX
))
133 k
= write(fd
, p
, nbytes
);
138 if (errno
== EAGAIN
&& do_poll
) {
139 /* We knowingly ignore any return value here,
140 * and expect that any error/EOF is reported
143 (void) fd_wait_for_event(fd
, POLLOUT
, USEC_INFINITY
);
150 if (_unlikely_(nbytes
> 0 && k
== 0)) /* Can't really happen */
153 assert((size_t) k
<= nbytes
);
157 } while (nbytes
> 0);
162 int pipe_eof(int fd
) {
163 struct pollfd pollfd
= {
165 .events
= POLLIN
|POLLHUP
,
170 r
= poll(&pollfd
, 1, 0);
177 return pollfd
.revents
& POLLHUP
;
180 int fd_wait_for_event(int fd
, int event
, usec_t t
) {
182 struct pollfd pollfd
= {
190 r
= ppoll(&pollfd
, 1, t
== USEC_INFINITY
? NULL
: timespec_store(&ts
, t
), NULL
);
196 return pollfd
.revents
;
199 static size_t nul_length(const uint8_t *p
, size_t sz
) {
214 ssize_t
sparse_write(int fd
, const void *p
, size_t sz
, size_t run_length
) {
215 const uint8_t *q
, *w
, *e
;
223 n
= nul_length(q
, e
- q
);
225 /* If there are more than the specified run length of
226 * NUL bytes, or if this is the beginning or the end
227 * of the buffer, then seek instead of write */
228 if ((n
> run_length
) ||
230 (n
> 0 && q
+ n
>= e
)) {
232 l
= write(fd
, w
, q
- w
);
239 if (lseek(fd
, n
, SEEK_CUR
) == (off_t
) -1)
251 l
= write(fd
, w
, q
- w
);
258 return q
- (const uint8_t*) p
;