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