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