]>
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
7 systemd is free software; you can redistribute it and/or modify it
8 under the terms of the GNU Lesser General Public License as published by
9 the Free Software Foundation; either version 2.1 of the License, or
10 (at your option) any later version.
12 systemd is distributed in the hope that it will be useful, but
13 WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 Lesser General Public License for more details.
17 You should have received a copy of the GNU Lesser General Public License
18 along with systemd; If not, see <http://www.gnu.org/licenses/>.
29 #include "time-util.h"
31 int flush_fd(int fd
) {
32 struct pollfd pollfd
= {
38 /* Read from the specified file descriptor, until POLLIN is not set anymore, throwing away everything
39 * read. Note that some file descriptors (notable IP sockets) will trigger POLLIN even when no data can be read
40 * (due to IP packet checksum mismatches), hence this function is only safe to be non-blocking if the fd used
41 * was set to non-blocking too. */
48 r
= poll(&pollfd
, 1, 0);
58 l
= read(fd
, buf
, sizeof(buf
));
75 ssize_t
loop_read(int fd
, void *buf
, size_t nbytes
, bool do_poll
) {
82 /* If called with nbytes == 0, let's call read() at least
83 * once, to validate the operation */
85 if (nbytes
> (size_t) SSIZE_MAX
)
91 k
= read(fd
, p
, nbytes
);
96 if (errno
== EAGAIN
&& do_poll
) {
98 /* We knowingly ignore any return value here,
99 * and expect that any error/EOF is reported
102 (void) fd_wait_for_event(fd
, POLLIN
, USEC_INFINITY
);
106 return n
> 0 ? n
: -errno
;
112 assert((size_t) k
<= nbytes
);
117 } while (nbytes
> 0);
122 int loop_read_exact(int fd
, void *buf
, size_t nbytes
, bool do_poll
) {
125 n
= loop_read(fd
, buf
, nbytes
, do_poll
);
128 if ((size_t) n
!= nbytes
)
134 int loop_write(int fd
, const void *buf
, size_t nbytes
, bool do_poll
) {
135 const uint8_t *p
= buf
;
140 if (nbytes
> (size_t) SSIZE_MAX
)
146 k
= write(fd
, p
, nbytes
);
151 if (errno
== EAGAIN
&& do_poll
) {
152 /* We knowingly ignore any return value here,
153 * and expect that any error/EOF is reported
156 (void) fd_wait_for_event(fd
, POLLOUT
, USEC_INFINITY
);
163 if (_unlikely_(nbytes
> 0 && k
== 0)) /* Can't really happen */
166 assert((size_t) k
<= nbytes
);
170 } while (nbytes
> 0);
175 int pipe_eof(int fd
) {
176 struct pollfd pollfd
= {
178 .events
= POLLIN
|POLLHUP
,
183 r
= poll(&pollfd
, 1, 0);
190 return pollfd
.revents
& POLLHUP
;
193 int fd_wait_for_event(int fd
, int event
, usec_t t
) {
195 struct pollfd pollfd
= {
203 r
= ppoll(&pollfd
, 1, t
== USEC_INFINITY
? NULL
: timespec_store(&ts
, t
), NULL
);
209 return pollfd
.revents
;
212 static size_t nul_length(const uint8_t *p
, size_t sz
) {
227 ssize_t
sparse_write(int fd
, const void *p
, size_t sz
, size_t run_length
) {
228 const uint8_t *q
, *w
, *e
;
236 n
= nul_length(q
, e
- q
);
238 /* If there are more than the specified run length of
239 * NUL bytes, or if this is the beginning or the end
240 * of the buffer, then seek instead of write */
241 if ((n
> run_length
) ||
243 (n
> 0 && q
+ n
>= e
)) {
245 l
= write(fd
, w
, q
- w
);
252 if (lseek(fd
, n
, SEEK_CUR
) == (off_t
) -1)
264 l
= write(fd
, w
, q
- w
);
271 return q
- (const uint8_t*) p
;