Line data Source code
1 : /* SPDX-License-Identifier: GPL-2.0-only */
2 : /*
3 : * Copyright (c) 2023 Meta Platforms, Inc. and affiliates.
4 : */
5 :
6 : #pragma once
7 :
8 : #include <assert.h>
9 : #include <errno.h>
10 : #include <stdbool.h>
11 : #include <stddef.h>
12 : #include <stdlib.h>
13 : #include <string.h>
14 : #include <strings.h>
15 :
16 : extern const char *strerrordesc_np(int errnum);
17 :
18 : #define _BF_APPLY0(t, s, dummy)
19 : #define _BF_APPLY1(t, s, a) t(a)
20 : #define _BF_APPLY2(t, s, a, b) t(a) s t(b)
21 : #define _BF_APPLY3(t, s, a, b, c) \
22 : t(a) s t(b) \
23 : s t(c)
24 : #define _BF_APPLY4(t, s, a, b, c, d) \
25 : t(a) s t(b) \
26 : s t(c) \
27 : s t(d)
28 : #define _BF_APPLY5(t, s, a, b, c, d, e) \
29 : t(a) s t(b) \
30 : s t(c) \
31 : s t(d) \
32 : s t(e)
33 : #define _BF_APPLY6(t, s, a, b, c, d, e, f) \
34 : t(a) s t(b) \
35 : s t(c) \
36 : s t(d) \
37 : s t(e) \
38 : s t(f)
39 : #define _BF_APPLY7(t, s, a, b, c, d, e, f, g) \
40 : t(a) s t(b) \
41 : s t(c) \
42 : s t(d) \
43 : s t(e) \
44 : s t(f) \
45 : s t(g)
46 : #define _BF_APPLY8(t, s, a, b, c, d, e, f, g, h) \
47 : t(a) s t(b) \
48 : s t(c) \
49 : s t(d) \
50 : s t(e) \
51 : s t(f) \
52 : s t(g) \
53 : s t(h)
54 : #define _BF_APPLY9(t, s, a, b, c, d, e, f, g, h, i) \
55 : t(a) s t(b) \
56 : s t(c) \
57 : s t(d) \
58 : s t(e) \
59 : s t(f) \
60 : s t(g) \
61 : s t(h) \
62 : s t(i)
63 : #define _BF_APPLY10(t, s, a, b, c, d, e, f, g, h, i, j) \
64 : t(a) s t(b) \
65 : s t(c) \
66 : s t(d) \
67 : s t(e) \
68 : s t(f) \
69 : s t(g) \
70 : s t(h) \
71 : s t(i) \
72 : s t(j)
73 :
74 : #define __BF_NUM_ARGS1(dummy, x10, x9, x8, x7, x6, x5, x4, x3, x2, x1, x0, \
75 : ...) \
76 : x0
77 : #define _BF_NUM_ARGS(...) \
78 : __BF_NUM_ARGS1(dummy, ##__VA_ARGS__, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
79 : #define ___BF_APPLY_ALL(t, s, n, ...) _BF_APPLY##n(t, s, __VA_ARGS__)
80 : #define __BF_APPLY_ALL(t, s, n, ...) ___BF_APPLY_ALL(t, s, n, __VA_ARGS__)
81 : #define _BF_APPLY_ALL(t, s, ...) \
82 : __BF_APPLY_ALL(t, s, _BF_NUM_ARGS(__VA_ARGS__), __VA_ARGS__)
83 :
84 : #define BF_BASE_10 10
85 : #define BF_BASE_16 16
86 :
87 : #define _BF_ALIGNED(addr, mask) (((addr) & (mask)) == 0)
88 : #define BF_ALIGNED_64(addr) _BF_ALIGNED(addr, 0x07)
89 : #define BF_ALIGNED_32(addr) _BF_ALIGNED(addr, 0x03)
90 : #define BF_ALIGNED_16(addr) _BF_ALIGNED(addr, 0x01)
91 :
92 : /**
93 : * @brief Generate a bitflag from multiple values.
94 : *
95 : * Enumeration are used extensively to define related values. Thanks to
96 : * enumeration's continuous values, they are used as array indexes to convert
97 : * them into strings.
98 : *
99 : * However, they can sometimes be combined, leading to very wordy code, e.g.
100 : * `1 << ENUM_VAL_1 | 1 << ENUM_VAL_5`.
101 : *
102 : * `BF_FLAGS` can be used to replace the wordy code with a simpler macro call,
103 : * e.g. `BF_FLAGS(ENUL_VAL_1, ENUM_VAL_5)`. It will automatically create an
104 : * integer with the enumeration values as a set bit index in the bitflag.
105 : *
106 : * @return Bitflag for variadic values.
107 : */
108 : #define BF_FLAGS(...) _BF_APPLY_ALL(BF_FLAG, |, __VA_ARGS__)
109 :
110 : /**
111 : * @brief Shift 1 by `n` to create a flag.
112 : *
113 : * @see `BF_FLAGS`
114 : *
115 : * @return `1 << n` to be used as a flag.
116 : */
117 : #define BF_FLAG(n) (1 << (n))
118 :
119 : #define bf_packed __attribute__((packed))
120 : #define bf_aligned(x) __attribute__((aligned(x)))
121 : #define bf_unused __attribute__((unused))
122 :
123 : #ifndef bf_assert
124 : #define bf_assert(x) assert(x)
125 : #endif
126 :
127 : #define bf_static_assert(expr, msg) _Static_assert((expr), msg)
128 :
129 : #define BF_STR(s) _BF_STR(s)
130 : #define _BF_STR(s) #s
131 :
132 : /**
133 : * @brief Generate a build error if an enumeration to string mapping array
134 : * contains fewer entries than members in the enumeration.
135 : *
136 : * @param array Array containing the mapping between the enumeration values and
137 : * ther string representation.
138 : * @param n_values Number of values in the enumeration, usually the
139 : * `_BF_$NAME_MAX` enumeration value.
140 : */
141 : #define static_assert_enum_mapping(array, n_values) \
142 : static_assert(ARRAY_SIZE(array) == (n_values), \
143 : "missing entries in " BF_STR(array) " array");
144 :
145 : /**
146 : * Mark a variable as unused, to prevent the compiler from emitting a warning.
147 : *
148 : * @param x The variable to mark as unused.
149 : */
150 : #define UNUSED(x) (void)(x)
151 :
152 : /**
153 : * Set @p ptr to NULL and return its previous value.
154 : *
155 : * Inspired from systemd's TAKE_PTR() macro, which is itself inspired from
156 : * Rust's Option::take() method:
157 : * https://doc.rust-lang.org/std/option/enum.Option.html#method.take
158 : *
159 : * @param var Variable to return the value of.
160 : * @param type Type of @p var.
161 : * @param nullvalue Value to set @p var to.
162 : * @return Value of @p var before it was set to @p nullvalue.
163 : */
164 : #define TAKE_GENERIC(var, type, nullvalue) \
165 : ({ \
166 : /* NOLINTBEGIN: do not enclose 'type' in parentheses */ \
167 : type *_pvar_ = &(var); \
168 : type _var_ = *_pvar_; \
169 : type _nullvalue_ = nullvalue; \
170 : /* NOLINTEND */ \
171 : *_pvar_ = _nullvalue_; \
172 : _var_; \
173 : })
174 :
175 : #define TAKE_PTR_TYPE(ptr, type) TAKE_GENERIC(ptr, type, NULL)
176 : #define TAKE_PTR(ptr) TAKE_PTR_TYPE(ptr, typeof(ptr))
177 : #define TAKE_STRUCT_TYPE(s, type) TAKE_GENERIC(s, type, {})
178 : #define TAKE_STRUCT(s) TAKE_STRUCT_TYPE(s, typeof(s))
179 : #define TAKE_FD(fd) TAKE_GENERIC(fd, int, -1)
180 :
181 : /**
182 : * Get the number of element in an array.
183 : *
184 : * @param x The array.
185 : * @return size_t The number of elements in the array.
186 : */
187 : #define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
188 :
189 : #define _cleanup_free_ __attribute__((__cleanup__(freep)))
190 : #define _cleanup_close_ __attribute__((__cleanup__(closep)))
191 :
192 : /**
193 : * Return a string describing the given error code.
194 : *
195 : * This function must be used over strerror(), which is marked at mt-unsafe.
196 : *
197 : * @param v Error code, can be positive or negative.
198 : */
199 : #define bf_strerror(v) strerrordesc_np(abs(v))
200 :
201 : /**
202 : * Swap two values.
203 : *
204 : * @param a First value to swap.
205 : * @param b Second value to swap.
206 : */
207 : #define bf_swap(a, b) \
208 : do { \
209 : typeof(a) __a = (a); \
210 : (a) = (b); \
211 : (b) = __a; \
212 : } while (0)
213 :
214 : #define bf_min(a, b) \
215 : ({ \
216 : __typeof__(a) _a = (a); \
217 : __typeof__(b) _b = (b); \
218 : _a < _b ? _a : _b; \
219 : })
220 :
221 : #define bf_max(a, b) \
222 : ({ \
223 : __typeof__(a) _a = (a); \
224 : __typeof__(b) _b = (b); \
225 : _a > _b ? _a : _b; \
226 : })
227 :
228 : /**
229 : * @brief Strip whitespace from the beginning of a string.
230 : *
231 : * @param str String to trim. Can't be NULL.
232 : * @return Trimmed version of `str`, as a pointer to a character of `str`.
233 : */
234 : char *bf_ltrim(char *str);
235 :
236 : /**
237 : * @brief Strip whitespace from the end of a string.
238 : *
239 : * `str` will be modified to insert `\0` after the last non-whitespace
240 : * character.
241 : * @param str String to trim. Can't be NULL.
242 : * @return Trimmed version of `str`, as a pointer to a character of `str`.
243 : */
244 : char *bf_rtrim(char *str);
245 :
246 : /**
247 : * @brief Strip whitespace from the beginning and the end of a string.
248 : *
249 : * `str` will be modified to insert `\0` after the last non-whitespace
250 : * character.
251 : *
252 : * @param str String to trim. Can't be NULL.
253 : * @return Trimmed version of `str`, as a pointer to a character of `str`.
254 : */
255 : char *bf_trim(char *str);
256 :
257 : /**
258 : * Free a pointer and set it to NULL.
259 : *
260 : * @param ptr Pointer to free.
261 : */
262 101 : static inline void freep(void *ptr)
263 : {
264 139 : free(*(void **)ptr);
265 426 : *(void **)ptr = NULL;
266 176 : }
267 :
268 : /**
269 : * Close a file descriptor and set it to -1.
270 : *
271 : * `bpfilter` uses `-1` as neutral value for file descriptor, meaning it
272 : * doesn't represent an open file yet. Once closed, a file descriptor should
273 : * be reset to `-1`.
274 : *
275 : * `closep` is used to close a file descriptor. If the file descriptor is
276 : * `-1`, then nothing it done. Otherwise, it is closed and reset to `-1`.
277 : *
278 : * If the call to `close` fails, a warning is printed, and the file descriptor
279 : * is assumed to be already closed.
280 : *
281 : * @todo Ensure file descriptors are always initialized to -1, and closed using
282 : * ``closep``.
283 : *
284 : * @param fd File descriptor to close. Can't be NULL.
285 : */
286 : void closep(int *fd);
287 :
288 : /**
289 : * Duplicate a memory region.
290 : *
291 : * Allocate a new buffer of size @p len and copy @p src into it. Requirements
292 : * applicable to @p src and @p len:
293 : * - If @p src is NULL, @p len must be 0. In this case, NULL is returned.
294 : * - If @p src is non-NULL, a new buffer of @p len bytes will be allocated to
295 : * store the first @p len bytes of @p src. This new buffer is then returned.
296 : *
297 : * Unless NULL is returned, the new buffer is owned by the caller.
298 : *
299 : * @param src Source buffer to copy to @p dst.
300 : * @param len Number of bytes to copy to @p dst.
301 : * @return Pointer to the new buffer, or NULL on failure.
302 : */
303 0 : static inline void *bf_memdup(const void *src, size_t len)
304 : {
305 : void *dst;
306 :
307 0 : if (!src)
308 : return NULL;
309 :
310 0 : dst = malloc(len);
311 0 : if (!dst)
312 : return NULL;
313 :
314 0 : return memcpy(dst, src, len);
315 : }
316 :
317 : /**
318 : * Copy @p len bytes from @p src to @p dst.
319 : *
320 : * Allow for @p src to be NULL and/or @p len to be zero:
321 : * - If @p src is NULL, @p len must be equal 0. @p dst is not modified.
322 : * - If @p src is not NULL, @p len can be equal to 0, in which case @p dst is
323 : * not modified.
324 : *
325 : * @param dst Destination buffer. Can't be NULL, and must be big enough to store
326 : * @p len bytes from @p src.
327 : * @param src Source buffer to copy to @p dst.
328 : * @param len Number of bytes to copy to @p dst.
329 : * @return Pointer to @p dst.
330 : */
331 54 : static inline void *bf_memcpy(void *dst, const void *src, size_t len)
332 : {
333 54 : bf_assert(dst);
334 54 : bf_assert(src ? 1 : len == 0);
335 :
336 54 : if (!src || !len)
337 : return dst;
338 :
339 53 : return memcpy(dst, src, len);
340 : }
341 :
342 : /**
343 : * Reallocate @p ptr into a new buffer of size @p size.
344 : *
345 : * Behaves similarly to realloc(), except that @p ptr is left unchanged if
346 : * allocation fails, and an error is returned.
347 : *
348 : * @param ptr Memory buffer to grow. Can't be NULL.
349 : * @param size New size of the memory buffer.
350 : * @return 0 on success, or a negative errno value on failure.
351 : */
352 : int bf_realloc(void **ptr, size_t size);
353 :
354 : /**
355 : * @brief Check if strings are equal.
356 : *
357 : * If any of `lhs`, `rhs` is NULL, the strings are considered inequal.
358 : *
359 : * @param lhs First string.
360 : * @param rhs Second string.
361 : * @return True if both strings are equal.
362 : */
363 1387 : static inline bool bf_streq(const char *lhs, const char *rhs)
364 : {
365 1387 : if (!lhs || !rhs)
366 : return false;
367 :
368 1387 : return strcmp(lhs, rhs) == 0;
369 : }
370 :
371 : /**
372 : * @brief Similar to `bf_streq`, except it compares only the first `n`
373 : * characters.
374 : *
375 : * If any of `lhs`, `rhs` is NULL, the strings are considered inequal.
376 : *
377 : * @param lhs First string.
378 : * @param rhs Second string.
379 : * @param n Number of characters to compare.
380 : * @return True if both strings are equal.
381 : */
382 : static inline bool bf_strneq(const char *lhs, const char *rhs, size_t n)
383 : {
384 : if (!lhs || !rhs)
385 : return false;
386 :
387 : return strncmp(lhs, rhs, n);
388 : }
389 :
390 : /**
391 : * @brief Case insensitive alternative to `bf_streq`.
392 : */
393 236 : static inline bool bf_streq_i(const char *lhs, const char *rhs)
394 : {
395 236 : if (!lhs || !rhs)
396 : return false;
397 :
398 96 : return strcasecmp(lhs, rhs) == 0;
399 : }
400 :
401 : /**
402 : * Copy a string to a buffer.
403 : *
404 : * @p src is copied to @p dst . If @p src is too long, at most @p len bytes are
405 : * copied (including the termination character).
406 : *
407 : * @param dst Destination buffer. Can't be NULL.
408 : * @param len Length of the destination buffer. The function will not copy more
409 : * than @p len bytes to @p dst , including @c \0 . Can't be 0.
410 : * @param src Soucre buffer to copy from. Will only be copied up to the
411 : * termination character if it fits. Can't be NULL.
412 : * @return 0 on success, or @c -E2BIG if @p src can't fit in @p dst .
413 : */
414 : int bf_strncpy(char *dst, size_t len, const char *src);
415 :
416 : /**
417 : * Read the contents of a file into a buffer.
418 : *
419 : * @param path Path to the file to read. Can't be NULL.
420 : * @param buf Pointer to a pointer to a buffer. The buffer will be allocated
421 : * automatically. The caller is responsible to free it. If @ref
422 : * bf_read_file fails, @p buf is left unchanged.
423 : * @param len Length of the allocated buffer. Populated by the function.
424 : * @return 0 on success, negative errno value on error.
425 : */
426 : int bf_read_file(const char *path, void **buf, size_t *len);
427 :
428 : /**
429 : * Write the contents of a buffer into a file.
430 : *
431 : * @param path Path to the file to write. Can't be NULL.
432 : * @param buf Buffer to write.
433 : * @param len Number of bytes to write the to file.
434 : * @return 0 on success, negative errno value on error.
435 : */
436 : int bf_write_file(const char *path, const void *buf, size_t len);
|