/src/librdkafka/src/rdposix.h
Line | Count | Source |
1 | | /* |
2 | | * librdkafka - Apache Kafka C library |
3 | | * |
4 | | * Copyright (c) 2012-2022, Magnus Edenhill |
5 | | * All rights reserved. |
6 | | * |
7 | | * Redistribution and use in source and binary forms, with or without |
8 | | * modification, are permitted provided that the following conditions are met: |
9 | | * |
10 | | * 1. Redistributions of source code must retain the above copyright notice, |
11 | | * this list of conditions and the following disclaimer. |
12 | | * 2. Redistributions in binary form must reproduce the above copyright notice, |
13 | | * this list of conditions and the following disclaimer in the documentation |
14 | | * and/or other materials provided with the distribution. |
15 | | * |
16 | | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" |
17 | | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE |
18 | | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE |
19 | | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE |
20 | | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR |
21 | | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF |
22 | | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS |
23 | | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN |
24 | | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) |
25 | | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
26 | | * POSSIBILITY OF SUCH DAMAGE. |
27 | | */ |
28 | | |
29 | | /** |
30 | | * POSIX system support |
31 | | */ |
32 | | #ifndef _RDPOSIX_H_ |
33 | | #define _RDPOSIX_H_ |
34 | | |
35 | | #include <unistd.h> |
36 | | #include <stdio.h> |
37 | | #include <sys/time.h> |
38 | | #include <inttypes.h> |
39 | | #include <fcntl.h> |
40 | | #include <errno.h> |
41 | | #include <string.h> |
42 | | |
43 | | /** |
44 | | * Types |
45 | | */ |
46 | | |
47 | | |
48 | | /** |
49 | | * Annotations, attributes, optimizers |
50 | | */ |
51 | | #ifndef likely |
52 | | #define likely(x) __builtin_expect((x), 1) |
53 | | #endif |
54 | | #ifndef unlikely |
55 | | #define unlikely(x) __builtin_expect((x), 0) |
56 | | #endif |
57 | | |
58 | | #define RD_UNUSED __attribute__((unused)) |
59 | | #define RD_INLINE inline |
60 | | #define RD_WARN_UNUSED_RESULT __attribute__((warn_unused_result)) |
61 | | #define RD_NORETURN __attribute__((noreturn)) |
62 | | #define RD_IS_CONSTANT(p) __builtin_constant_p((p)) |
63 | | #define RD_TLS __thread |
64 | | |
65 | | /** |
66 | | * Allocation |
67 | | */ |
68 | | #if !defined(__FreeBSD__) && !defined(__OpenBSD__) |
69 | | /* alloca(3) is in stdlib on FreeBSD */ |
70 | | #include <alloca.h> |
71 | | #endif |
72 | | |
73 | | #define rd_alloca(N) alloca(N) |
74 | | |
75 | | |
76 | | /** |
77 | | * Strings, formatting, printf, .. |
78 | | */ |
79 | | |
80 | | /* size_t and ssize_t format strings */ |
81 | | #define PRIusz "zu" |
82 | | #define PRIdsz "zd" |
83 | | |
84 | | #ifndef RD_FORMAT |
85 | | #define RD_FORMAT(...) __attribute__((format(__VA_ARGS__))) |
86 | | #endif |
87 | | #define rd_snprintf(...) snprintf(__VA_ARGS__) |
88 | | #define rd_vsnprintf(...) vsnprintf(__VA_ARGS__) |
89 | | |
90 | | #define rd_strcasecmp(A, B) strcasecmp(A, B) |
91 | | #define rd_strncasecmp(A, B, N) strncasecmp(A, B, N) |
92 | | |
93 | | |
94 | | #ifdef HAVE_STRCASESTR |
95 | | #define rd_strcasestr(HAYSTACK, NEEDLE) strcasestr(HAYSTACK, NEEDLE) |
96 | | #else |
97 | | #define rd_strcasestr(HAYSTACK, NEEDLE) _rd_strcasestr(HAYSTACK, NEEDLE) |
98 | | #endif |
99 | | |
100 | | |
101 | | /** |
102 | | * Errors |
103 | | */ |
104 | | |
105 | | |
106 | | #define rd_set_errno(err) (errno = (err)) |
107 | | |
108 | | #if HAVE_STRERROR_R |
109 | | static RD_INLINE RD_UNUSED const char *rd_strerror(int err) { |
110 | | static RD_TLS char ret[128]; |
111 | | |
112 | | #if defined(__GLIBC__) && defined(_GNU_SOURCE) |
113 | | return strerror_r(err, ret, sizeof(ret)); |
114 | | #else /* XSI version */ |
115 | | int r; |
116 | | /* The r assignment is to catch the case where |
117 | | * _GNU_SOURCE is not defined but the GNU version is |
118 | | * picked up anyway. */ |
119 | | r = strerror_r(err, ret, sizeof(ret)); |
120 | | if (unlikely(r)) |
121 | | rd_snprintf(ret, sizeof(ret), "strerror_r(%d) failed (ret %d)", |
122 | | err, r); |
123 | | return ret; |
124 | | #endif |
125 | | } |
126 | | #else |
127 | | #define rd_strerror(err) strerror(err) |
128 | | #endif |
129 | | |
130 | | |
131 | | /** |
132 | | * Atomics |
133 | | */ |
134 | | #include "rdatomic.h" |
135 | | |
136 | | /** |
137 | | * Misc |
138 | | */ |
139 | | |
140 | | /** |
141 | | * Microsecond sleep. |
142 | | * Will retry on signal interrupt unless *terminate is true. |
143 | | */ |
144 | 0 | static RD_INLINE RD_UNUSED void rd_usleep(int usec, rd_atomic32_t *terminate) { |
145 | 0 | struct timespec req = {usec / 1000000, (long)(usec % 1000000) * 1000}; |
146 | 0 |
|
147 | 0 | /* Retry until complete (issue #272), unless terminating. */ |
148 | 0 | while (nanosleep(&req, &req) == -1 && |
149 | 0 | (errno == EINTR && (!terminate || !rd_atomic32_get(terminate)))) |
150 | 0 | ; |
151 | 0 | } Unexecuted instantiation: fuzz_regex.c:rd_usleep Unexecuted instantiation: regexp.c:rd_usleep |
152 | | |
153 | | |
154 | | |
155 | | #define rd_gettimeofday(tv, tz) gettimeofday(tv, tz) |
156 | | |
157 | | |
158 | | #ifndef __COVERITY__ |
159 | 4.97k | #define rd_assert(EXPR) assert(EXPR) |
160 | | #else |
161 | | extern void __coverity_panic__(void); |
162 | | #define rd_assert(EXPR) \ |
163 | | do { \ |
164 | | if (!(EXPR)) \ |
165 | | __coverity_panic__(); \ |
166 | | } while (0) |
167 | | #endif |
168 | | |
169 | | |
170 | | static RD_INLINE RD_UNUSED const char *rd_getenv(const char *env, |
171 | 0 | const char *def) { |
172 | 0 | const char *tmp; |
173 | 0 | tmp = getenv(env); |
174 | 0 | if (tmp && *tmp) |
175 | 0 | return tmp; |
176 | 0 | return def; |
177 | 0 | } Unexecuted instantiation: fuzz_regex.c:rd_getenv Unexecuted instantiation: regexp.c:rd_getenv |
178 | | |
179 | | |
180 | | /** |
181 | | * Empty struct initializer |
182 | | */ |
183 | | #define RD_ZERO_INIT \ |
184 | | {} |
185 | | |
186 | | /** |
187 | | * Sockets, IO |
188 | | */ |
189 | | |
190 | | /** @brief Socket type */ |
191 | | typedef int rd_socket_t; |
192 | | |
193 | | /** @brief Socket API error return value */ |
194 | | #define RD_SOCKET_ERROR (-1) |
195 | | |
196 | | /** @brief Last socket error */ |
197 | | #define rd_socket_errno errno |
198 | | |
199 | | |
200 | | /** @brief String representation of socket error */ |
201 | | #define rd_socket_strerror(ERR) rd_strerror(ERR) |
202 | | |
203 | | /** @brief poll() struct type */ |
204 | | typedef struct pollfd rd_pollfd_t; |
205 | | |
206 | | /** @brief poll(2) */ |
207 | | #define rd_socket_poll(POLLFD, FDCNT, TIMEOUT_MS) \ |
208 | | poll(POLLFD, FDCNT, TIMEOUT_MS) |
209 | | |
210 | | /** |
211 | | * @brief Set socket to non-blocking |
212 | | * @returns 0 on success or errno on failure. |
213 | | */ |
214 | 0 | static RD_UNUSED int rd_fd_set_nonblocking(int fd) { |
215 | 0 | int fl = fcntl(fd, F_GETFL, 0); |
216 | 0 | if (fl == -1 || fcntl(fd, F_SETFL, fl | O_NONBLOCK) == -1) |
217 | 0 | return errno; |
218 | 0 | return 0; |
219 | 0 | } Unexecuted instantiation: fuzz_regex.c:rd_fd_set_nonblocking Unexecuted instantiation: regexp.c:rd_fd_set_nonblocking |
220 | | |
221 | | /** |
222 | | * @brief Create non-blocking pipe |
223 | | * @returns 0 on success or errno on failure |
224 | | */ |
225 | 0 | static RD_UNUSED int rd_pipe_nonblocking(rd_socket_t *fds) { |
226 | 0 | if (pipe(fds) == -1 || rd_fd_set_nonblocking(fds[0]) == -1 || |
227 | 0 | rd_fd_set_nonblocking(fds[1])) |
228 | 0 | return errno; |
229 | 0 |
|
230 | 0 | /* Minimize buffer sizes to avoid a large number |
231 | 0 | * of signaling bytes to accumulate when |
232 | 0 | * io-signalled queue is not being served for a while. */ |
233 | 0 | #ifdef F_SETPIPE_SZ |
234 | 0 | /* Linux automatically rounds the pipe size up |
235 | 0 | * to the minimum size. */ |
236 | 0 | fcntl(fds[0], F_SETPIPE_SZ, 100); |
237 | 0 | fcntl(fds[1], F_SETPIPE_SZ, 100); |
238 | 0 | #endif |
239 | 0 | return 0; |
240 | 0 | } Unexecuted instantiation: fuzz_regex.c:rd_pipe_nonblocking Unexecuted instantiation: regexp.c:rd_pipe_nonblocking |
241 | | #define rd_socket_read(fd, buf, sz) read(fd, buf, sz) |
242 | | #define rd_socket_write(fd, buf, sz) write(fd, buf, sz) |
243 | | #define rd_socket_close(fd) close(fd) |
244 | | |
245 | | /* File IO */ |
246 | | #define rd_write(fd, buf, sz) write(fd, buf, sz) |
247 | | #define rd_open(path, flags, mode) open(path, flags, mode) |
248 | | #define rd_close(fd) close(fd) |
249 | | |
250 | | #endif /* _RDPOSIX_H_ */ |