diff options
Diffstat (limited to 'src/contrib')
-rw-r--r-- | src/contrib/Makefile.inc | 1 | ||||
-rw-r--r-- | src/contrib/asan.h | 13 | ||||
-rw-r--r-- | src/contrib/atomic.h | 73 | ||||
-rw-r--r-- | src/contrib/files.c | 23 | ||||
-rw-r--r-- | src/contrib/files.h | 9 | ||||
-rw-r--r-- | src/contrib/json.c | 7 | ||||
-rw-r--r-- | src/contrib/json.h | 7 | ||||
-rw-r--r-- | src/contrib/mempattern.c | 10 | ||||
-rw-r--r-- | src/contrib/spinlock.h | 80 | ||||
-rw-r--r-- | src/contrib/string.c | 20 | ||||
-rw-r--r-- | src/contrib/string.h | 4 | ||||
-rw-r--r-- | src/contrib/time.h | 5 |
12 files changed, 156 insertions, 96 deletions
diff --git a/src/contrib/Makefile.inc b/src/contrib/Makefile.inc index e1577d5..d64c2eb 100644 --- a/src/contrib/Makefile.inc +++ b/src/contrib/Makefile.inc @@ -24,6 +24,7 @@ EXTRA_DIST += \ libcontrib_la_SOURCES = \ contrib/asan.h \ + contrib/atomic.h \ contrib/base32hex.c \ contrib/base32hex.h \ contrib/base64.c \ diff --git a/src/contrib/asan.h b/src/contrib/asan.h index 5feb2c1..ef6fe66 100644 --- a/src/contrib/asan.h +++ b/src/contrib/asan.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2015 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -25,13 +25,20 @@ #if __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) void __asan_poison_memory_region(void const volatile *addr, size_t size); void __asan_unpoison_memory_region(void const volatile *addr, size_t size); +#if defined(__GNUC__) && !defined(__clang__) /* A faulty GCC workaround. */ + #pragma GCC diagnostic push + #pragma GCC diagnostic ignored "-Wmaybe-uninitialized" +#endif #define ASAN_POISON_MEMORY_REGION(addr, size) \ __asan_poison_memory_region((addr), (size)) +#if defined(__GNUC__) && !defined(__clang__) /* End of the workaround. */ + #pragma GCC diagnostic pop +#endif #define ASAN_UNPOISON_MEMORY_REGION(addr, size) \ __asan_unpoison_memory_region((addr), (size)) -#else +#else /* __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) */ #define ASAN_POISON_MEMORY_REGION(addr, size) \ ((void)(addr), (void)(size)) #define ASAN_UNPOISON_MEMORY_REGION(addr, size) \ ((void)(addr), (void)(size)) -#endif +#endif /* __has_feature(address_sanitizer) || defined(__SANITIZE_ADDRESS__) */ diff --git a/src/contrib/atomic.h b/src/contrib/atomic.h new file mode 100644 index 0000000..b8dace1 --- /dev/null +++ b/src/contrib/atomic.h @@ -0,0 +1,73 @@ +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see <https://www.gnu.org/licenses/>. + */ + +/*! + * \brief C11 atomic operations with fallbacks. + */ + +#pragma once + +#ifdef HAVE_C11_ATOMIC /* C11 */ + #define KNOT_HAVE_ATOMIC + + #include <stdatomic.h> + + #define ATOMIC_SET(dst, val) atomic_store_explicit(&(dst), (val), memory_order_relaxed) + #define ATOMIC_GET(src) atomic_load_explicit(&(src), memory_order_relaxed) + #define ATOMIC_ADD(dst, val) (void)atomic_fetch_add_explicit(&(dst), (val), memory_order_relaxed) + #define ATOMIC_SUB(dst, val) (void)atomic_fetch_sub_explicit(&(dst), (val), memory_order_relaxed) + #define ATOMIC_XCHG(dst, val) atomic_exchange_explicit(&(dst), (val), memory_order_relaxed) + + typedef atomic_uint_fast16_t knot_atomic_uint16_t; + typedef atomic_uint_fast64_t knot_atomic_uint64_t; + typedef atomic_size_t knot_atomic_size_t; + typedef _Atomic (void *) knot_atomic_ptr_t; + typedef atomic_bool knot_atomic_bool; +#elif defined(HAVE_GCC_ATOMIC) /* GCC __atomic */ + #define KNOT_HAVE_ATOMIC + + #include <stdint.h> + #include <stdbool.h> + + #define ATOMIC_SET(dst, val) __atomic_store_n(&(dst), (val), __ATOMIC_RELAXED) + #define ATOMIC_GET(src) __atomic_load_n(&(src), __ATOMIC_RELAXED) + #define ATOMIC_ADD(dst, val) __atomic_add_fetch(&(dst), (val), __ATOMIC_RELAXED) + #define ATOMIC_SUB(dst, val) __atomic_sub_fetch(&(dst), (val), __ATOMIC_RELAXED) + #define ATOMIC_XCHG(dst, val) __atomic_exchange_n(&(dst), (val), __ATOMIC_RELAXED) + + typedef uint16_t knot_atomic_uint16_t; + typedef uint64_t knot_atomic_uint64_t; + typedef size_t knot_atomic_size_t; + typedef void* knot_atomic_ptr_t; + typedef bool knot_atomic_bool; +#else /* Fallback, non-atomic. */ + #warning "Atomic operations not availabe, using unreliable replacement." + + #include <stdint.h> + #include <stdbool.h> + + #define ATOMIC_SET(dst, val) ((dst) = (val)) + #define ATOMIC_GET(src) (src) + #define ATOMIC_ADD(dst, val) ((dst) += (val)) + #define ATOMIC_SUB(dst, val) ((dst) -= (val)) + #define ATOMIC_XCHG(dst, val) ({ __typeof__ (dst) _z = (dst); (dst) = (val); _z; }) + + typedef uint16_t knot_atomic_uint16_t; + typedef uint64_t knot_atomic_uint64_t; + typedef size_t knot_atomic_size_t; + typedef void* knot_atomic_ptr_t; + typedef bool knot_atomic_bool; +#endif diff --git a/src/contrib/files.c b/src/contrib/files.c index 5b38469..f3a4b78 100644 --- a/src/contrib/files.c +++ b/src/contrib/files.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -92,16 +92,29 @@ static int remove_file(const char *path, const struct stat *stat, int type, stru { (void)stat; (void)ftw; - if (type == FTW_DP) { + + switch (type) { + case FTW_D: + case FTW_DNR: + case FTW_DP: return rmdir(path); - } else { + default: return unlink(path); } } -bool remove_path(const char *path) +static int remove_in_dir(const char *path, const struct stat *stat, int type, struct FTW *ftw) +{ + return (ftw->level > 0) ? remove_file(path, stat, type, ftw) : 0; +} + +int remove_path(const char *path, bool keep_apex) { - return (0 == nftw(path, remove_file, 1, FTW_DEPTH | FTW_PHYS)); + if (0 != nftw(path, keep_apex ? remove_in_dir : remove_file, + 1, FTW_DEPTH | FTW_PHYS)) { + return knot_map_errno(); + } + return KNOT_EOK; } int make_dir(const char *path, mode_t mode, bool ignore_existing) diff --git a/src/contrib/files.h b/src/contrib/files.h index c505ac8..4250a47 100644 --- a/src/contrib/files.h +++ b/src/contrib/files.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -52,9 +52,12 @@ bool same_path(const char *path1, const char *path2); /*! * \brief Delete file or directory (recursive). * - * \return true on success, false when one or more files failed to be removed. + * \param[in] path Absolute path or a relative path suffix; a string. + * \param[in] keep_apex If true, don't remove the starting point (apex). + * + * \return KNOT_E* */ -bool remove_path(const char *path); +int remove_path(const char *path, bool keep_apex); /*! * Equivalent to mkdir(2), can succeed if the directory already exists. diff --git a/src/contrib/json.c b/src/contrib/json.c index d44da87..5173f90 100644 --- a/src/contrib/json.c +++ b/src/contrib/json.c @@ -217,6 +217,13 @@ void jsonw_int(jsonw_t *w, const char *key, int value) fprintf(w->out, "%d", value); } +void jsonw_double(jsonw_t *w, const char *key, double value) +{ + assert(w); + + align_key(w, key); + fprintf(w->out, "%.4f", value); +} void jsonw_bool(jsonw_t *w, const char *key, bool value) { diff --git a/src/contrib/json.h b/src/contrib/json.h index cf8abe6..17513bc 100644 --- a/src/contrib/json.h +++ b/src/contrib/json.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -82,6 +82,11 @@ void jsonw_ulong(jsonw_t *w, const char *key, unsigned long value); void jsonw_int(jsonw_t *w, const char *key, int value); /*! + * Write double as JSON. + */ +void jsonw_double(jsonw_t *w, const char *key, double value); + +/*! * Write boolean value as JSON. */ void jsonw_bool(jsonw_t *w, const char *key, bool value); diff --git a/src/contrib/mempattern.c b/src/contrib/mempattern.c index f57139d..f86f0ac 100644 --- a/src/contrib/mempattern.c +++ b/src/contrib/mempattern.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2017 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2024 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -114,9 +114,15 @@ void mm_ctx_init(knot_mm_t *mm) mm->free = free; } +// UBSAN type punning workaround +static void *mp_alloc_wrap(void *ctx, size_t size) +{ + return mp_alloc(ctx, size); +} + void mm_ctx_mempool(knot_mm_t *mm, size_t chunk_size) { mm->ctx = mp_new(chunk_size); - mm->alloc = (knot_mm_alloc_t)mp_alloc; + mm->alloc = mp_alloc_wrap; mm->free = mm_nofree; } diff --git a/src/contrib/spinlock.h b/src/contrib/spinlock.h index 837f500..a7ec5ec 100644 --- a/src/contrib/spinlock.h +++ b/src/contrib/spinlock.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -15,48 +15,23 @@ */ /*! - * \brief Multiplatform spinlock. + * \brief A C11 spinlock (POSIX pthread spinlock as a fallback). */ #pragma once #if (__STDC_VERSION__ >= 201112L) && !defined(__STDC_NO_ATOMICS__) -/* Not tested and activated yet. */ -/* #define HAVE_STDATOMIC */ -#endif - -#if defined(__APPLE__) -# if defined(MAC_OS_X_VERSION_10_12) || \ - MAC_OS_X_VERSION_MAX_ALLOWED >= MAC_OS_X_VERSION_10_12 -# define APPLE_SPIN_NEW -# else -# define APPLE_SPIN_OLD -# endif /* MAC_OS_X_VERSION_10_12 ... */ -#endif /* __APPLE__ */ - -#if defined(HAVE_SYNC_ATOMIC) || defined(HAVE_ATOMIC) -# include <stdbool.h> -#elif defined(HAVE_STDATOMIC) -# include <stdbool.h> -# include <stdatomic.h> -#elif defined(APPLE_SPIN_NEW) -# include <os/lock.h> -#elif defined(APPLE_SPIN_OLD) -# include <libkern/OSAtomic.h> + #define HAVE_STDATOMIC + #include <stdatomic.h> + #include <stdbool.h> #else /* POSIX pthread spinlock. */ -# include <pthread.h> + #include <pthread.h> #endif /*! \brief Spinlock lock variable type. */ typedef -#if defined(HAVE_SYNC_ATOMIC) || defined(HAVE_ATOMIC) - bool /*!< Spinlock lock - a simple & fast atomic version. */ -#elif defined(HAVE_STDATOMIC) +#if defined(HAVE_STDATOMIC) atomic_bool /*!< Spinlock lock - a simple & fast atomic version, C11 */ -#elif defined(APPLE_SPIN_NEW) - os_unfair_lock /*!< Spinlock lock - a newer macOS version (macOS >= 10.12). */ -#elif defined(APPLE_SPIN_OLD) - OSSpinLock /*!< Spinlock lock - an older macOS version (macOS < 10.12). */ #else /* POSIX */ pthread_spinlock_t /*!< Spinlock lock - a POSIX pthread version. */ #endif @@ -65,14 +40,8 @@ typedef /*! \brief Initialize the spinlock pointed to by the parameter "lock". */ static inline void knot_spin_init(knot_spin_t *lock) { -#if defined(HAVE_SYNC_ATOMIC) || defined(HAVE_ATOMIC) - *lock = false; -#elif defined(HAVE_STDATOMIC) +#if defined(HAVE_STDATOMIC) atomic_init(lock, false); -#elif defined(APPLE_SPIN_NEW) - *lock = OS_UNFAIR_LOCK_INIT; -#elif defined(APPLE_SPIN_OLD) - *lock = OS_SPINLOCK_INIT; #else /* POSIX */ pthread_spin_init(lock, PTHREAD_PROCESS_PRIVATE); #endif @@ -81,8 +50,7 @@ static inline void knot_spin_init(knot_spin_t *lock) /*! \brief Destroy the spinlock pointed to by the parameter "lock". */ static inline void knot_spin_destroy(knot_spin_t *lock) { -#if defined(HAVE_SYNC_ATOMIC) || defined(HAVE_ATOMIC) || defined(HAVE_STDATOMIC) || \ - defined(APPLE_SPIN_NEW) || defined(APPLE_SPIN_OLD) +#if defined(HAVE_STDATOMIC) /* Nothing needed here. */ #else /* POSIX */ pthread_spin_destroy(lock); @@ -92,23 +60,11 @@ static inline void knot_spin_destroy(knot_spin_t *lock) /*! \brief Lock the spinlock pointed to by the parameter "lock". */ static inline void knot_spin_lock(knot_spin_t *lock) { -#if defined(HAVE_SYNC_ATOMIC) - while (__sync_lock_test_and_set(lock, 1)) { - } -#elif defined(HAVE_ATOMIC) - int expected = 0; - while (!__atomic_compare_exchange_n(lock, &expected, 1, false, __ATOMIC_RELAXED, __ATOMIC_RELAXED)) { - expected = 0; - } -#elif defined(HAVE_STDATOMIC) - int expected = 0; - while (!atomic_compare_exchange_strong(lock, &expected, false)) { - expected = 0; +#if defined(HAVE_STDATOMIC) + bool expected = false; + while (!atomic_compare_exchange_strong(lock, &expected, true)) { + expected = false; } -#elif defined(APPLE_SPIN_NEW) - os_unfair_lock_lock(lock); -#elif defined(APPLE_SPIN_OLD) - OSSpinLockLock(lock); #else /* POSIX */ pthread_spin_lock(lock); #endif @@ -117,16 +73,8 @@ static inline void knot_spin_lock(knot_spin_t *lock) /*! \brief Unlock the spinlock pointed to by the parameter "lock". */ static inline void knot_spin_unlock(knot_spin_t *lock) { -#if defined(HAVE_SYNC_ATOMIC) - __sync_lock_release(lock); -#elif defined(HAVE_ATOMIC) - __atomic_clear(lock, __ATOMIC_RELAXED); -#elif defined(HAVE_STDATOMIC) +#if defined(HAVE_STDATOMIC) atomic_store(lock, false); -#elif defined(APPLE_SPIN_NEW) - os_unfair_lock_unlock(lock); -#elif defined(APPLE_SPIN_OLD) - OSSpinLockUnlock(lock); #else /* POSIX */ pthread_spin_unlock(lock); #endif diff --git a/src/contrib/string.c b/src/contrib/string.c index 272116e..6fa2d0a 100644 --- a/src/contrib/string.c +++ b/src/contrib/string.c @@ -1,4 +1,4 @@ -/* Copyright (C) 2021 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -26,16 +26,16 @@ /* #include <string.h> is needed. */ #elif defined(HAVE_EXPLICIT_MEMSET) /* #include <string.h> is needed. */ -#elif defined(HAVE_GNUTLS_MEMSET) - #include <gnutls/gnutls.h> #else - #define USE_CUSTOM_MEMSET + #include <gnutls/gnutls.h> #endif #include "contrib/string.h" #include "contrib/ctype.h" #include "contrib/tolower.h" +const char *configure_summary = CONFIGURE_SUMMARY; + uint8_t *memdup(const uint8_t *data, size_t data_size) { uint8_t *result = (uint8_t *)malloc(data_size); @@ -137,11 +137,6 @@ int const_time_memcmp(const void *s1, const void *s2, size_t n) return equal; } -#if defined(USE_CUSTOM_MEMSET) -typedef void *(*memset_t)(void *, int, size_t); -static volatile memset_t volatile_memset = memset; -#endif - void *memzero(void *s, size_t n) { #if defined(HAVE_EXPLICIT_BZERO) /* In OpenBSD since 5.5. */ @@ -161,14 +156,9 @@ void *memzero(void *s, size_t n) return s; #elif defined(HAVE_EXPLICIT_MEMSET) /* In NetBSD since 7.0. */ return explicit_memset(s, 0, n); -#elif defined(HAVE_GNUTLS_MEMSET) /* In GnuTLS since 3.4.0. */ +#else gnutls_memset(s, 0, n); return s; -#else /* Knot custom solution as a fallback. */ - /* Warning: the use of the return value is *probably* needed - * so as to avoid the volatile_memset() to be optimized out. - */ - return volatile_memset(s, 0, n); #endif } diff --git a/src/contrib/string.h b/src/contrib/string.h index ad3c990..3e113b1 100644 --- a/src/contrib/string.h +++ b/src/contrib/string.h @@ -1,4 +1,4 @@ -/* Copyright (C) 2022 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> +/* Copyright (C) 2023 CZ.NIC, z.s.p.o. <knot-dns@labs.nic.cz> This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,6 +24,8 @@ #include <stddef.h> #include <stdint.h> +extern const char *configure_summary; + /*! * \brief Create a copy of a binary buffer. * diff --git a/src/contrib/time.h b/src/contrib/time.h index 20d241e..b12b366 100644 --- a/src/contrib/time.h +++ b/src/contrib/time.h @@ -88,6 +88,11 @@ inline static int knot_time_cmp(knot_time_t a, knot_time_t b) { return (a == b ? 0 : 1) * ((a && b) == 0 ? -1 : 1) * (a < b ? -1 : 1); } +inline static bool knot_time_lt (knot_time_t a, knot_time_t b) { return knot_time_cmp(a, b) < 0; } +inline static bool knot_time_leq(knot_time_t a, knot_time_t b) { return knot_time_cmp(a, b) <= 0; } +inline static bool knot_time_eq (knot_time_t a, knot_time_t b) { return knot_time_cmp(a, b) == 0; } +inline static bool knot_time_geq(knot_time_t a, knot_time_t b) { return knot_time_cmp(a, b) >= 0; } +inline static bool knot_time_gt (knot_time_t a, knot_time_t b) { return knot_time_cmp(a, b) > 0; } /*! * \brief Return the smaller (=earlier) from given two timestamps. |