Branch data 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 : 507 : static inline void freep(void *ptr)
263 : : {
264 : 24241 : free(*(void **)ptr);
265 : 20408 : *(void **)ptr = NULL;
266 : 6894 : }
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 : 5 : static inline void *bf_memdup(const void *src, size_t len)
304 : : {
305 : : void *dst;
306 : :
307 [ - + ]: 5 : if (!src)
308 : : return NULL;
309 : :
310 : 5 : dst = malloc(len);
311 [ - + ]: 5 : if (!dst)
312 : : return NULL;
313 : :
314 : 5 : 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 : 1754 : static inline void *bf_memcpy(void *dst, const void *src, size_t len)
332 : : {
333 : : bf_assert(dst);
334 : : bf_assert(src ? 1 : len == 0);
335 : :
336 [ + + ]: 1754 : if (!src || !len)
337 : : return dst;
338 : :
339 : 1672 : 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 : 52794 : static inline bool bf_streq(const char *lhs, const char *rhs)
364 : : {
365 [ + + ]: 52794 : if (!lhs || !rhs)
366 : : return false;
367 : :
368 : 52791 : 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 : 64097 : static inline bool bf_streq_i(const char *lhs, const char *rhs)
394 : : {
395 [ + + ]: 64097 : if (!lhs || !rhs)
396 : : return false;
397 : :
398 : 5513 : 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);
|