]>
git.ipfire.org Git - thirdparty/systemd.git/blob - src/basic/io-util.c
1 /* SPDX-License-Identifier: LGPL-2.1-or-later */
8 #include "errno-util.h"
10 #include "iovec-util.h"
11 #include "string-util.h"
12 #include "time-util.h"
14 int flush_fd(int fd
) {
17 /* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything
18 * read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read
19 * (due to IP packet checksum mismatches), hence this function is only safe to be non-blocking if the fd used
20 * was set to non-blocking too. */
27 r
= fd_wait_for_event(fd
, POLLIN
, 0);
37 l
= read(fd
, buf
, sizeof(buf
));
53 ssize_t
loop_read(int fd
, void *buf
, size_t nbytes
, bool do_poll
) {
54 uint8_t *p
= ASSERT_PTR(buf
);
59 /* If called with nbytes == 0, let's call read() at least once, to validate the operation */
61 if (nbytes
> (size_t) SSIZE_MAX
)
67 k
= read(fd
, p
, nbytes
);
72 if (errno
== EAGAIN
&& do_poll
) {
74 /* We knowingly ignore any return value here,
75 * and expect that any error/EOF is reported
78 (void) fd_wait_for_event(fd
, POLLIN
, USEC_INFINITY
);
82 return n
> 0 ? n
: -errno
;
88 assert((size_t) k
<= nbytes
);
98 int loop_read_exact(int fd
, void *buf
, size_t nbytes
, bool do_poll
) {
101 n
= loop_read(fd
, buf
, nbytes
, do_poll
);
104 if ((size_t) n
!= nbytes
)
110 int loop_write_full(int fd
, const void *buf
, size_t nbytes
, usec_t timeout
) {
116 assert(buf
|| nbytes
== 0);
119 static const dummy_t dummy
[0];
120 assert_cc(sizeof(dummy
) == 0);
121 p
= (const void*) dummy
; /* Some valid pointer, in case NULL was specified */
123 if (nbytes
== SIZE_MAX
)
124 nbytes
= strlen(buf
);
125 else if (_unlikely_(nbytes
> (size_t) SSIZE_MAX
))
131 /* When timeout is 0 or USEC_INFINITY this is not used. But we initialize it to a sensible value. */
132 end
= timestamp_is_set(timeout
) ? usec_add(now(CLOCK_MONOTONIC
), timeout
) : USEC_INFINITY
;
137 k
= write(fd
, p
, nbytes
);
142 if (errno
!= EAGAIN
|| timeout
== 0)
147 if (timeout
== USEC_INFINITY
)
148 wait_for
= USEC_INFINITY
;
150 usec_t t
= now(CLOCK_MONOTONIC
);
154 wait_for
= usec_sub_unsigned(end
, t
);
157 r
= fd_wait_for_event(fd
, POLLOUT
, wait_for
);
158 if (timeout
== USEC_INFINITY
|| ERRNO_IS_NEG_TRANSIENT(r
))
159 /* If timeout == USEC_INFINITY we knowingly ignore any return value
160 * here, and expect that any error/EOF is reported via write() */
168 if (_unlikely_(nbytes
> 0 && k
== 0)) /* Can't really happen */
171 assert((size_t) k
<= nbytes
);
175 } while (nbytes
> 0);
180 int pipe_eof(int fd
) {
183 r
= fd_wait_for_event(fd
, POLLIN
, 0);
187 return !!(r
& POLLHUP
);
190 int ppoll_usec(struct pollfd
*fds
, size_t nfds
, usec_t timeout
) {
193 assert(fds
|| nfds
== 0);
195 /* This is a wrapper around ppoll() that does primarily two things:
197 * ✅ Takes a usec_t instead of a struct timespec
199 * ✅ Guarantees that if an invalid fd is specified we return EBADF (i.e. converts POLLNVAL to
200 * EBADF). This is done because EBADF is a programming error usually, and hence should bubble up
201 * as error, and not be eaten up as non-error POLLNVAL event.
203 * ⚠️ ⚠️ ⚠️ Note that this function does not add any special handling for EINTR. Don't forget
204 * poll()/ppoll() will return with EINTR on any received signal always, there is no automatic
205 * restarting via SA_RESTART available. Thus, typically you want to handle EINTR not as an error,
206 * but just as reason to restart things, under the assumption you use a more appropriate mechanism
207 * to handle signals, such as signalfd() or signal handlers. ⚠️ ⚠️ ⚠️
213 r
= ppoll(fds
, nfds
, timeout
== USEC_INFINITY
? NULL
: TIMESPEC_STORE(timeout
), NULL
);
219 for (size_t i
= 0, n
= r
; i
< nfds
&& n
> 0; i
++) {
220 if (fds
[i
].revents
== 0)
222 if (fds
[i
].revents
& POLLNVAL
)
230 int fd_wait_for_event(int fd
, int event
, usec_t timeout
) {
231 struct pollfd pollfd
= {
237 /* ⚠️ ⚠️ ⚠️ Keep in mind you almost certainly want to handle -EINTR gracefully in the caller, see
238 * ppoll_usec() above! ⚠️ ⚠️ ⚠️ */
240 r
= ppoll_usec(&pollfd
, 1, timeout
);
244 return pollfd
.revents
;
247 static size_t nul_length(const uint8_t *p
, size_t sz
) {
262 ssize_t
sparse_write(int fd
, const void *p
, size_t sz
, size_t run_length
) {
263 const uint8_t *q
, *w
, *e
;
271 n
= nul_length(q
, e
- q
);
273 /* If there are more than the specified run length of
274 * NUL bytes, or if this is the beginning or the end
275 * of the buffer, then seek instead of write */
276 if ((n
> run_length
) ||
278 (n
> 0 && q
+ n
>= e
)) {
280 l
= write(fd
, w
, q
- w
);
287 if (lseek(fd
, n
, SEEK_CUR
) == (off_t
) -1)
299 l
= write(fd
, w
, q
- w
);
306 return q
- (const uint8_t*) p
;