]>
Commit | Line | Data |
---|---|---|
db9ecf05 | 1 | /* SPDX-License-Identifier: LGPL-2.1-or-later */ |
c004493c LP |
2 | #pragma once |
3 | ||
c4febde9 | 4 | #include <poll.h> |
c004493c | 5 | #include <stdbool.h> |
11c3a366 TA |
6 | #include <stddef.h> |
7 | #include <stdint.h> | |
afc5dbf3 LP |
8 | #include <sys/types.h> |
9 | #include <sys/uio.h> | |
c004493c | 10 | |
11c3a366 | 11 | #include "macro.h" |
c004493c LP |
12 | #include "time-util.h" |
13 | ||
14 | int flush_fd(int fd); | |
15 | ||
16 | ssize_t loop_read(int fd, void *buf, size_t nbytes, bool do_poll); | |
17 | int loop_read_exact(int fd, void *buf, size_t nbytes, bool do_poll); | |
18 | int loop_write(int fd, const void *buf, size_t nbytes, bool do_poll); | |
19 | ||
20 | int pipe_eof(int fd); | |
21 | ||
c4febde9 | 22 | int ppoll_usec(struct pollfd *fds, size_t nfds, usec_t timeout); |
c004493c LP |
23 | int fd_wait_for_event(int fd, int event, usec_t timeout); |
24 | ||
25 | ssize_t sparse_write(int fd, const void *p, size_t sz, size_t run_length); | |
afc5dbf3 | 26 | |
da6053d0 | 27 | static inline size_t IOVEC_TOTAL_SIZE(const struct iovec *i, size_t n) { |
2f9d1da9 | 28 | size_t r = 0; |
afc5dbf3 | 29 | |
2f9d1da9 | 30 | for (size_t j = 0; j < n; j++) |
afc5dbf3 LP |
31 | r += i[j].iov_len; |
32 | ||
33 | return r; | |
34 | } | |
35 | ||
32f65484 ZJS |
36 | static inline bool IOVEC_INCREMENT(struct iovec *i, size_t n, size_t k) { |
37 | /* Returns true if there is nothing else to send (bytes written cover all of the iovec), | |
38 | * false if there's still work to do. */ | |
afc5dbf3 | 39 | |
32f65484 | 40 | for (size_t j = 0; j < n; j++) { |
afc5dbf3 LP |
41 | size_t sub; |
42 | ||
32f65484 ZJS |
43 | if (i[j].iov_len == 0) |
44 | continue; | |
45 | if (k == 0) | |
46 | return false; | |
afc5dbf3 LP |
47 | |
48 | sub = MIN(i[j].iov_len, k); | |
49 | i[j].iov_len -= sub; | |
50 | i[j].iov_base = (uint8_t*) i[j].iov_base + sub; | |
51 | k -= sub; | |
52 | } | |
53 | ||
32f65484 ZJS |
54 | assert(k == 0); /* Anything else would mean that we wrote more bytes than available, |
55 | * or the kernel reported writing more bytes than sent. */ | |
56 | return true; | |
afc5dbf3 | 57 | } |
a90fb858 LP |
58 | |
59 | static inline bool FILE_SIZE_VALID(uint64_t l) { | |
60 | /* ftruncate() and friends take an unsigned file size, but actually cannot deal with file sizes larger than | |
61 | * 2^63 since the kernel internally handles it as signed value. This call allows checking for this early. */ | |
62 | ||
63 | return (l >> 63) == 0; | |
64 | } | |
65 | ||
66 | static inline bool FILE_SIZE_VALID_OR_INFINITY(uint64_t l) { | |
67 | ||
68 | /* Same as above, but allows one extra value: -1 as indication for infinity. */ | |
69 | ||
f5fbe71d | 70 | if (l == UINT64_MAX) |
a90fb858 LP |
71 | return true; |
72 | ||
73 | return FILE_SIZE_VALID(l); | |
74 | ||
75 | } | |
e6a7ec4b | 76 | |
65e7d565 | 77 | #define IOVEC_NULL (struct iovec) {} |
ce16d177 YW |
78 | #define IOVEC_MAKE(base, len) (struct iovec) { .iov_base = (base), .iov_len = (len) } |
79 | #define IOVEC_MAKE_STRING(string) \ | |
de5cc016 YW |
80 | ({ \ |
81 | char *_s = (char*) (string); \ | |
82 | IOVEC_MAKE(_s, strlen(_s)); \ | |
83 | }) | |
084eeb86 ZJS |
84 | |
85 | char* set_iovec_string_field(struct iovec *iovec, size_t *n_iovec, const char *field, const char *value); | |
30a0554e | 86 | char* set_iovec_string_field_free(struct iovec *iovec, size_t *n_iovec, const char *field, char *value); |
11e6d971 FB |
87 | |
88 | struct iovec_wrapper { | |
89 | struct iovec *iovec; | |
90 | size_t count; | |
11e6d971 FB |
91 | }; |
92 | ||
93 | struct iovec_wrapper *iovw_new(void); | |
94 | struct iovec_wrapper *iovw_free(struct iovec_wrapper *iovw); | |
95 | struct iovec_wrapper *iovw_free_free(struct iovec_wrapper *iovw); | |
6257e2fb LP |
96 | |
97 | DEFINE_TRIVIAL_CLEANUP_FUNC(struct iovec_wrapper*, iovw_free_free); | |
98 | ||
11e6d971 | 99 | void iovw_free_contents(struct iovec_wrapper *iovw, bool free_vectors); |
3e4d0f6c | 100 | |
11e6d971 | 101 | int iovw_put(struct iovec_wrapper *iovw, void *data, size_t len); |
3e4d0f6c ZJS |
102 | static inline int iovw_consume(struct iovec_wrapper *iovw, void *data, size_t len) { |
103 | /* Move data into iovw or free on error */ | |
82ee54b2 LP |
104 | int r; |
105 | ||
106 | r = iovw_put(iovw, data, len); | |
3e4d0f6c ZJS |
107 | if (r < 0) |
108 | free(data); | |
82ee54b2 | 109 | |
3e4d0f6c ZJS |
110 | return r; |
111 | } | |
112 | ||
82ee54b2 LP |
113 | static inline bool iovw_isempty(const struct iovec_wrapper *iovw) { |
114 | return !iovw || iovw->count == 0; | |
115 | } | |
116 | ||
ae41fdb6 FB |
117 | int iovw_put_string_field(struct iovec_wrapper *iovw, const char *field, const char *value); |
118 | int iovw_put_string_field_free(struct iovec_wrapper *iovw, const char *field, char *value); | |
11e6d971 FB |
119 | void iovw_rebase(struct iovec_wrapper *iovw, char *old, char *new); |
120 | size_t iovw_size(struct iovec_wrapper *iovw); | |
3746131a | 121 | int iovw_append(struct iovec_wrapper *target, const struct iovec_wrapper *source); |
253a83ea LP |
122 | |
123 | void iovec_array_free(struct iovec *iov, size_t n); |