diff options
| author | Michael Biebl <biebl@debian.org> | 2022-01-13 22:30:39 +0100 |
|---|---|---|
| committer | Michael Biebl <biebl@debian.org> | 2022-01-13 22:30:39 +0100 |
| commit | 88c227d90a6b7b388c5c85d72802a0ca8f05ed5c (patch) | |
| tree | 71f32df6617802270e8a78574bd8e1637dc532f4 /src/libnm-glib-aux | |
| parent | e74c568b07b50b97873fb4ee1d776dedefbd54d6 (diff) | |
New upstream version 1.34.0 upstream/1.34.0
Diffstat (limited to 'src/libnm-glib-aux')
25 files changed, 2089 insertions, 1466 deletions
diff --git a/src/libnm-glib-aux/nm-dbus-aux.c b/src/libnm-glib-aux/nm-dbus-aux.c index f4f53a7d..454bd2d8 100644 --- a/src/libnm-glib-aux/nm-dbus-aux.c +++ b/src/libnm-glib-aux/nm-dbus-aux.c @@ -403,3 +403,90 @@ _nm_dbus_error_is(GError *error, ...) return FALSE; } + +/*****************************************************************************/ + +typedef struct { + GDBusConnection **p_dbus_connection; + GError ** p_error; +} BusGetData; + +static void +_bus_get_cb(GObject *source, GAsyncResult *result, gpointer user_data) +{ + BusGetData *data = user_data; + + *data->p_dbus_connection = g_bus_get_finish(result, data->p_error); +} + +/** + * nm_g_bus_get_blocking: + * @cancellable: (allow-none): a #GCancellable to abort the operation. + * @error: (allow-none): the error. + * + * This calls g_bus_get(), but iterates the current (thread-default) GMainContext + * until the response is ready. As such, it's similar to g_bus_get_sync(), + * but it allows to cancel the operation (without having multiple threads). + * + * Returns: (transfer full): the new #GDBusConnection or %NULL on error. + */ +GDBusConnection * +nm_g_bus_get_blocking(GCancellable *cancellable, GError **error) +{ + gs_free_error GError *local_error = NULL; + gs_unref_object GDBusConnection *dbus_connection = NULL; + GMainContext * main_context = g_main_context_get_thread_default(); + BusGetData data = { + .p_dbus_connection = &dbus_connection, + .p_error = &local_error, + }; + + g_bus_get(G_BUS_TYPE_SYSTEM, cancellable, _bus_get_cb, &data); + + while (!dbus_connection && !local_error) + g_main_context_iteration(main_context, TRUE); + + if (!dbus_connection) { + g_propagate_error(error, g_steal_pointer(&local_error)); + return NULL; + } + + return g_steal_pointer(&dbus_connection); +} + +/*****************************************************************************/ + +void +nm_dbus_connection_call_blocking_callback(GObject *source, GAsyncResult *res, gpointer user_data) +{ + NMDBusConnectionCallBlockingData *data = user_data; + + nm_assert(data); + nm_assert(!data->result); + nm_assert(!data->error); + + data->result = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &data->error); +} + +GVariant * +nm_dbus_connection_call_blocking(NMDBusConnectionCallBlockingData *data, GError **error) +{ + GMainContext *main_context = g_main_context_get_thread_default(); + gs_free_error GError *local_error = NULL; + gs_unref_variant GVariant *result = NULL; + + nm_assert(data); + + while (!data->result && !data->error) + g_main_context_iteration(main_context, TRUE); + + local_error = g_steal_pointer(&data->error); + result = g_steal_pointer(&data->result); + + if (!result) { + g_propagate_error(error, g_steal_pointer(&local_error)); + return NULL; + } + + return g_steal_pointer(&result); +} diff --git a/src/libnm-glib-aux/nm-dbus-aux.h b/src/libnm-glib-aux/nm-dbus-aux.h index 65a91311..420a0c55 100644 --- a/src/libnm-glib-aux/nm-dbus-aux.h +++ b/src/libnm-glib-aux/nm-dbus-aux.h @@ -84,6 +84,29 @@ void nm_dbus_connection_call_get_name_owner(GDBusConnection * d NMDBusConnectionCallGetNameOwnerCb callback, gpointer user_data); +static inline void +nm_dbus_connection_call_request_name(GDBusConnection * dbus_connection, + const char * name, + guint32 flags, + int timeout_msec, + GCancellable * cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_dbus_connection_call(dbus_connection, + DBUS_SERVICE_DBUS, + DBUS_PATH_DBUS, + DBUS_INTERFACE_DBUS, + "RequestName", + g_variant_new("(su)", name, flags), + G_VARIANT_TYPE("(u)"), + G_DBUS_CALL_FLAGS_NONE, + timeout_msec, + cancellable, + callback, + user_data); +} + static inline guint nm_dbus_connection_signal_subscribe_properties_changed(GDBusConnection * dbus_connection, const char * bus_name, @@ -215,4 +238,30 @@ gboolean _nm_dbus_error_is(GError *error, ...) G_GNUC_NULL_TERMINATED; /*****************************************************************************/ +GDBusConnection *nm_g_bus_get_blocking(GCancellable *cancellable, GError **error); + +/*****************************************************************************/ + +typedef struct { + GVariant *result; + GError * error; +} NMDBusConnectionCallBlockingData; + +void +nm_dbus_connection_call_blocking_callback(GObject *source, GAsyncResult *res, gpointer user_data); + +GVariant *nm_dbus_connection_call_blocking(NMDBusConnectionCallBlockingData *data, GError **error); + +/*****************************************************************************/ + +static inline gboolean +nm_g_variant_tuple_get_u(GVariant *v, guint32 *out_u) +{ + if (g_variant_is_of_type(v, G_VARIANT_TYPE("(u)"))) { + g_variant_get(v, "(u)", out_u); + return TRUE; + } + return FALSE; +} + #endif /* __NM_DBUS_AUX_H__ */ diff --git a/src/libnm-glib-aux/nm-default-glib.h b/src/libnm-glib-aux/nm-default-glib.h index e5ccd47f..9d04ddc4 100644 --- a/src/libnm-glib-aux/nm-default-glib.h +++ b/src/libnm-glib-aux/nm-default-glib.h @@ -18,21 +18,21 @@ #include <glib.h> #if defined(_NETWORKMANAGER_COMPILATION_GLIB_I18N_PROG) - #if defined(_NETWORKMANAGER_COMPILATION_GLIB_I18N_LIB) - #error Cannot define _NETWORKMANAGER_COMPILATION_GLIB_I18N_LIB and _NETWORKMANAGER_COMPILATION_GLIB_I18N_PROG together - #endif - #undef _NETWORKMANAGER_COMPILATION_GLIB_I18N_PROG - #include <glib/gi18n.h> +#if defined(_NETWORKMANAGER_COMPILATION_GLIB_I18N_LIB) +#error Cannot define _NETWORKMANAGER_COMPILATION_GLIB_I18N_LIB and _NETWORKMANAGER_COMPILATION_GLIB_I18N_PROG together +#endif +#undef _NETWORKMANAGER_COMPILATION_GLIB_I18N_PROG +#include <glib/gi18n.h> #elif defined(_NETWORKMANAGER_COMPILATION_GLIB_I18N_LIB) - #undef _NETWORKMANAGER_COMPILATION_GLIB_I18N_LIB - #include <glib/gi18n-lib.h> +#undef _NETWORKMANAGER_COMPILATION_GLIB_I18N_LIB +#include <glib/gi18n-lib.h> #endif /*****************************************************************************/ #if NM_MORE_ASSERTS == 0 - #ifndef G_DISABLE_CAST_CHECKS - /* Unless compiling with G_DISABLE_CAST_CHECKS, glib performs type checking +#ifndef G_DISABLE_CAST_CHECKS +/* Unless compiling with G_DISABLE_CAST_CHECKS, glib performs type checking * during G_VARIANT_TYPE() via g_variant_type_checked_(). This is not necessary * because commonly this cast is needed during something like * @@ -54,9 +54,9 @@ * * Just patch G_VARIANT_TYPE() to perform no check. */ - #undef G_VARIANT_TYPE - #define G_VARIANT_TYPE(type_string) ((const GVariantType *) (type_string)) - #endif +#undef G_VARIANT_TYPE +#define G_VARIANT_TYPE(type_string) ((const GVariantType *) (type_string)) +#endif #endif /*****************************************************************************/ diff --git a/src/libnm-glib-aux/nm-gassert-patch.h b/src/libnm-glib-aux/nm-gassert-patch.h index bac8697c..e4ea23e4 100644 --- a/src/libnm-glib-aux/nm-gassert-patch.h +++ b/src/libnm-glib-aux/nm-gassert-patch.h @@ -25,50 +25,50 @@ _nm_g_return_if_fail_warning(const char *log_domain, const char *file, int line) g_return_if_fail_warning(log_domain, file_buf, "<dropped>"); } - #define g_return_if_fail_warning(log_domain, pretty_function, expression) \ - _nm_g_return_if_fail_warning(log_domain, __FILE__, __LINE__) +#define g_return_if_fail_warning(log_domain, pretty_function, expression) \ + _nm_g_return_if_fail_warning(log_domain, __FILE__, __LINE__) - #define g_assertion_message_expr(domain, file, line, func, expr) \ - g_assertion_message_expr(domain, file, line, "<unknown-fcn>", (expr) ? "<dropped>" : NULL) +#define g_assertion_message_expr(domain, file, line, func, expr) \ + g_assertion_message_expr(domain, file, line, "<unknown-fcn>", (expr) ? "<dropped>" : NULL) - #undef g_return_val_if_reached - #define g_return_val_if_reached(val) \ - G_STMT_START \ - { \ - g_log(G_LOG_DOMAIN, \ - G_LOG_LEVEL_CRITICAL, \ - "file %s: line %d (%s): should not be reached", \ - __FILE__, \ - __LINE__, \ - "<dropped>"); \ - return (val); \ - } \ - G_STMT_END +#undef g_return_val_if_reached +#define g_return_val_if_reached(val) \ + G_STMT_START \ + { \ + g_log(G_LOG_DOMAIN, \ + G_LOG_LEVEL_CRITICAL, \ + "file %s: line %d (%s): should not be reached", \ + __FILE__, \ + __LINE__, \ + "<dropped>"); \ + return (val); \ + } \ + G_STMT_END - #undef g_return_if_reached - #define g_return_if_reached() \ - G_STMT_START \ - { \ - g_log(G_LOG_DOMAIN, \ - G_LOG_LEVEL_CRITICAL, \ - "file %s: line %d (%s): should not be reached", \ - __FILE__, \ - __LINE__, \ - "<dropped>"); \ - return; \ - } \ - G_STMT_END +#undef g_return_if_reached +#define g_return_if_reached() \ + G_STMT_START \ + { \ + g_log(G_LOG_DOMAIN, \ + G_LOG_LEVEL_CRITICAL, \ + "file %s: line %d (%s): should not be reached", \ + __FILE__, \ + __LINE__, \ + "<dropped>"); \ + return; \ + } \ + G_STMT_END #endif /*****************************************************************************/ #if NM_MORE_ASSERTS == 0 - #define NM_ASSERT_G_RETURN_EXPR(expr) "<dropped>" - #define NM_ASSERT_NO_MSG 1 +#define NM_ASSERT_G_RETURN_EXPR(expr) "<dropped>" +#define NM_ASSERT_NO_MSG 1 #else - #define NM_ASSERT_G_RETURN_EXPR(expr) "" expr "" - #define NM_ASSERT_NO_MSG 0 +#define NM_ASSERT_G_RETURN_EXPR(expr) "" expr "" +#define NM_ASSERT_NO_MSG 0 #endif /*****************************************************************************/ diff --git a/src/libnm-glib-aux/nm-glib.h b/src/libnm-glib-aux/nm-glib.h index 66e5c16e..49470d92 100644 --- a/src/libnm-glib-aux/nm-glib.h +++ b/src/libnm-glib-aux/nm-glib.h @@ -9,21 +9,21 @@ /*****************************************************************************/ #ifndef __NM_MACROS_INTERNAL_H__ - #error "nm-glib.h requires nm-macros-internal.h. Do not include this directly" +#error "nm-glib.h requires nm-macros-internal.h. Do not include this directly" #endif /*****************************************************************************/ #ifdef __clang__ - #undef G_GNUC_BEGIN_IGNORE_DEPRECATIONS - #undef G_GNUC_END_IGNORE_DEPRECATIONS +#undef G_GNUC_BEGIN_IGNORE_DEPRECATIONS +#undef G_GNUC_END_IGNORE_DEPRECATIONS - #define G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ - _Pragma("clang diagnostic push") \ - _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") +#define G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ + _Pragma("clang diagnostic push") \ + _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"") - #define G_GNUC_END_IGNORE_DEPRECATIONS _Pragma("clang diagnostic pop") +#define G_GNUC_END_IGNORE_DEPRECATIONS _Pragma("clang diagnostic pop") #endif @@ -47,23 +47,23 @@ __g_type_ensure(GType type) #if !GLIB_CHECK_VERSION(2, 34, 0) - #define g_clear_pointer(pp, destroy) \ - G_STMT_START \ - { \ - G_STATIC_ASSERT(sizeof *(pp) == sizeof(gpointer)); \ - /* Only one access, please */ \ - gpointer *_pp = (gpointer *) (pp); \ - gpointer _p; \ - /* This assignment is needed to avoid a gcc warning */ \ - GDestroyNotify _destroy = (GDestroyNotify) (destroy); \ - \ - _p = *_pp; \ - if (_p) { \ - *_pp = NULL; \ - _destroy(_p); \ - } \ - } \ - G_STMT_END +#define g_clear_pointer(pp, destroy) \ + G_STMT_START \ + { \ + G_STATIC_ASSERT(sizeof *(pp) == sizeof(gpointer)); \ + /* Only one access, please */ \ + gpointer *_pp = (gpointer *) (pp); \ + gpointer _p; \ + /* This assignment is needed to avoid a gcc warning */ \ + GDestroyNotify _destroy = (GDestroyNotify) (destroy); \ + \ + _p = *_pp; \ + if (_p) { \ + *_pp = NULL; \ + _destroy(_p); \ + } \ + } \ + G_STMT_END #endif @@ -71,94 +71,94 @@ __g_type_ensure(GType type) #if !GLIB_CHECK_VERSION(2, 34, 0) - /* These are used to clean up the output of test programs; we can just let +/* These are used to clean up the output of test programs; we can just let * them no-op in older glib. */ - #define g_test_expect_message(log_domain, log_level, pattern) - #define g_test_assert_expected_messages() +#define g_test_expect_message(log_domain, log_level, pattern) +#define g_test_assert_expected_messages() #else - /* We build with -DGLIB_MAX_ALLOWED_VERSION set to 2.32 to make sure we don't +/* We build with -DGLIB_MAX_ALLOWED_VERSION set to 2.32 to make sure we don't * accidentally use new API that we shouldn't. But we don't want warnings for * the APIs that we emulate above. */ - #define g_test_expect_message(domain, level, format...) \ - G_STMT_START \ - { \ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ - g_test_expect_message(domain, level, format); \ - G_GNUC_END_IGNORE_DEPRECATIONS \ - } \ - G_STMT_END - - #define g_test_assert_expected_messages_internal(domain, file, line, func) \ - G_STMT_START \ - { \ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ - g_test_assert_expected_messages_internal(domain, file, line, func); \ - G_GNUC_END_IGNORE_DEPRECATIONS \ - } \ - G_STMT_END +#define g_test_expect_message(domain, level, format...) \ + G_STMT_START \ + { \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ + g_test_expect_message(domain, level, format); \ + G_GNUC_END_IGNORE_DEPRECATIONS \ + } \ + G_STMT_END + +#define g_test_assert_expected_messages_internal(domain, file, line, func) \ + G_STMT_START \ + { \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ + g_test_assert_expected_messages_internal(domain, file, line, func); \ + G_GNUC_END_IGNORE_DEPRECATIONS \ + } \ + G_STMT_END #endif /*****************************************************************************/ #if GLIB_CHECK_VERSION(2, 35, 0) - /* For glib >= 2.36, g_type_init() is deprecated. +/* For glib >= 2.36, g_type_init() is deprecated. * But since 2.35.1 (7c42ab23b55c43ab96d0ac2124b550bf1f49c1ec) this function * does nothing. Replace the call with empty statement. */ - #define nm_g_type_init() \ - G_STMT_START \ - { \ - (void) 0; \ - } \ - G_STMT_END +#define nm_g_type_init() \ + G_STMT_START \ + { \ + (void) 0; \ + } \ + G_STMT_END #else - #define nm_g_type_init() \ - G_STMT_START \ - { \ - g_type_init(); \ - } \ - G_STMT_END +#define nm_g_type_init() \ + G_STMT_START \ + { \ + g_type_init(); \ + } \ + G_STMT_END #endif /*****************************************************************************/ /* g_test_initialized() is only available since glib 2.36. */ #if !GLIB_CHECK_VERSION(2, 36, 0) - #define g_test_initialized() (g_test_config_vars->test_initialized) +#define g_test_initialized() (g_test_config_vars->test_initialized) #endif /*****************************************************************************/ /* g_assert_cmpmem() is only available since glib 2.46. */ #if !GLIB_CHECK_VERSION(2, 45, 7) - #define g_assert_cmpmem(m1, l1, m2, l2) \ - G_STMT_START \ - { \ - gconstpointer __m1 = m1, __m2 = m2; \ - int __l1 = l1, __l2 = l2; \ - if (__l1 != __l2) \ - g_assertion_message_cmpnum(G_LOG_DOMAIN, \ - __FILE__, \ - __LINE__, \ - G_STRFUNC, \ - #l1 " (len(" #m1 ")) == " #l2 " (len(" #m2 "))", \ - __l1, \ - "==", \ - __l2, \ - 'i'); \ - else if (memcmp(__m1, __m2, __l1) != 0) \ - g_assertion_message(G_LOG_DOMAIN, \ - __FILE__, \ - __LINE__, \ - G_STRFUNC, \ - "assertion failed (" #m1 " == " #m2 ")"); \ - } \ - G_STMT_END +#define g_assert_cmpmem(m1, l1, m2, l2) \ + G_STMT_START \ + { \ + gconstpointer __m1 = m1, __m2 = m2; \ + int __l1 = l1, __l2 = l2; \ + if (__l1 != __l2) \ + g_assertion_message_cmpnum(G_LOG_DOMAIN, \ + __FILE__, \ + __LINE__, \ + G_STRFUNC, \ + #l1 " (len(" #m1 ")) == " #l2 " (len(" #m2 "))", \ + __l1, \ + "==", \ + __l2, \ + 'i'); \ + else if (memcmp(__m1, __m2, __l1) != 0) \ + g_assertion_message(G_LOG_DOMAIN, \ + __FILE__, \ + __LINE__, \ + G_STRFUNC, \ + "assertion failed (" #m1 " == " #m2 ")"); \ + } \ + G_STMT_END #endif /*****************************************************************************/ @@ -288,21 +288,21 @@ _nm_g_ptr_array_insert(GPtrArray *array, int index_, gpointer data) #endif #if !GLIB_CHECK_VERSION(2, 40, 0) - #define g_ptr_array_insert(array, index, data) \ - G_STMT_START \ - { \ - _nm_g_ptr_array_insert(array, index, data); \ - } \ - G_STMT_END +#define g_ptr_array_insert(array, index, data) \ + G_STMT_START \ + { \ + _nm_g_ptr_array_insert(array, index, data); \ + } \ + G_STMT_END #else - #define g_ptr_array_insert(array, index, data) \ - G_STMT_START \ - { \ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ - g_ptr_array_insert(array, index, data); \ - G_GNUC_END_IGNORE_DEPRECATIONS \ - } \ - G_STMT_END +#define g_ptr_array_insert(array, index, data) \ + G_STMT_START \ + { \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ + g_ptr_array_insert(array, index, data); \ + G_GNUC_END_IGNORE_DEPRECATIONS \ + } \ + G_STMT_END #endif /*****************************************************************************/ @@ -327,37 +327,37 @@ _g_key_file_save_to_file(GKeyFile *key_file, const char *filename, GError **erro return success; } - #define g_key_file_save_to_file(key_file, filename, error) \ - _g_key_file_save_to_file(key_file, filename, error) +#define g_key_file_save_to_file(key_file, filename, error) \ + _g_key_file_save_to_file(key_file, filename, error) #else - #define g_key_file_save_to_file(key_file, filename, error) \ - ({ \ - gboolean _success; \ - \ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ - _success = g_key_file_save_to_file(key_file, filename, error); \ - G_GNUC_END_IGNORE_DEPRECATIONS \ - _success; \ - }) +#define g_key_file_save_to_file(key_file, filename, error) \ + ({ \ + gboolean _success; \ + \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ + _success = g_key_file_save_to_file(key_file, filename, error); \ + G_GNUC_END_IGNORE_DEPRECATIONS \ + _success; \ + }) #endif /*****************************************************************************/ #if GLIB_CHECK_VERSION(2, 36, 0) - #define g_credentials_get_unix_pid(creds, error) \ - ({ \ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS(g_credentials_get_unix_pid)((creds), (error)); \ - G_GNUC_END_IGNORE_DEPRECATIONS \ - }) +#define g_credentials_get_unix_pid(creds, error) \ + ({ \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS(g_credentials_get_unix_pid)((creds), (error)); \ + G_GNUC_END_IGNORE_DEPRECATIONS \ + }) #else - #define g_credentials_get_unix_pid(creds, error) \ - ({ \ - struct ucred *native_creds; \ - \ - native_creds = g_credentials_get_native((creds), G_CREDENTIALS_TYPE_LINUX_UCRED); \ - g_assert(native_creds); \ - native_creds->pid; \ - }) +#define g_credentials_get_unix_pid(creds, error) \ + ({ \ + struct ucred *native_creds; \ + \ + native_creds = g_credentials_get_native((creds), G_CREDENTIALS_TYPE_LINUX_UCRED); \ + g_assert(native_creds); \ + native_creds->pid; \ + }) #endif /*****************************************************************************/ @@ -387,38 +387,39 @@ _nm_g_hash_table_get_keys_as_array(GHashTable *hash_table, guint *length) } #endif #if !GLIB_CHECK_VERSION(2, 40, 0) - #define g_hash_table_get_keys_as_array(hash_table, length) \ - ({ _nm_g_hash_table_get_keys_as_array(hash_table, length); }) +#define g_hash_table_get_keys_as_array(hash_table, length) \ + ({ _nm_g_hash_table_get_keys_as_array(hash_table, length); }) #else - #define g_hash_table_get_keys_as_array(hash_table, length) \ - ({ \ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS(g_hash_table_get_keys_as_array) \ - ((hash_table), (length)); \ - G_GNUC_END_IGNORE_DEPRECATIONS \ - }) +#define g_hash_table_get_keys_as_array(hash_table, length) \ + ({ \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS(g_hash_table_get_keys_as_array) \ + ((hash_table), (length)); \ + G_GNUC_END_IGNORE_DEPRECATIONS \ + }) #endif /*****************************************************************************/ #ifndef g_info - /* g_info was only added with 2.39.2 */ - #define g_info(...) g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, __VA_ARGS__) +/* g_info was only added with 2.39.2 */ +#define g_info(...) g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, __VA_ARGS__) #endif /*****************************************************************************/ #ifdef g_steal_pointer - #undef g_steal_pointer +#undef g_steal_pointer #endif -#define g_steal_pointer(pp) \ - ({ \ - typeof(*(pp)) *const _pp = (pp); \ - typeof(*_pp) _p = *_pp; \ - _nm_unused const void *const _p_type_check = _p; \ - \ - *_pp = NULL; \ - _p; \ +#define g_steal_pointer(pp) \ + ({ \ + typeof(*(pp)) *const _pp = (pp); \ + typeof(*_pp) _p = *_pp; \ + \ + _NM_ENSURE_POINTER(_p); \ + \ + *_pp = NULL; \ + _p; \ }) /*****************************************************************************/ @@ -460,7 +461,7 @@ _nm_g_variant_new_take_string(char *string) return value; #elif !GLIB_CHECK_VERSION(2, 38, 0) GVariant *value; - GBytes * bytes; + GBytes *bytes; g_return_val_if_fail(string != NULL, NULL); g_return_val_if_fail(g_utf8_validate(string, -1, NULL), NULL); @@ -494,17 +495,17 @@ _nm_printf(1, 2) static inline GVariant *_nm_g_variant_new_printf(const char *fo return g_variant_new_take_string(string); } - #define g_variant_new_printf(...) _nm_g_variant_new_printf(__VA_ARGS__) +#define g_variant_new_printf(...) _nm_g_variant_new_printf(__VA_ARGS__) #else - #define g_variant_new_printf(...) \ - ({ \ - GVariant *_v; \ - \ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ - _v = g_variant_new_printf(__VA_ARGS__); \ - G_GNUC_END_IGNORE_DEPRECATIONS \ - _v; \ - }) +#define g_variant_new_printf(...) \ + ({ \ + GVariant *_v; \ + \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ + _v = g_variant_new_printf(__VA_ARGS__); \ + G_GNUC_END_IGNORE_DEPRECATIONS \ + _v; \ + }) #endif /*****************************************************************************/ @@ -525,11 +526,11 @@ _nm_printf(1, 2) static inline GVariant *_nm_g_variant_new_printf(const char *fo /*****************************************************************************/ #ifndef g_autofree - /* we still don't rely on recent glib to provide g_autofree. Hence, we continue +/* we still don't rely on recent glib to provide g_autofree. Hence, we continue * to use our gs_* free macros that we took from libgsystem. * * To ease migration towards g_auto*, add a compat define for g_autofree. */ - #define g_autofree gs_free +#define g_autofree gs_free #endif /*****************************************************************************/ @@ -553,7 +554,7 @@ _nm_g_value_unset(GValue *value) if (value->g_type != 0) g_value_unset(value); } - #define g_value_unset _nm_g_value_unset +#define g_value_unset _nm_g_value_unset #endif /* G_PID_FORMAT was added only in 2.53.5. Define it ourself. @@ -571,7 +572,7 @@ _nm_g_value_unset(GValue *value) /* G_SOURCE_FUNC was added in 2.57.2. */ #undef G_SOURCE_FUNC -#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void)) (f)) +#define G_SOURCE_FUNC(f) ((GSourceFunc) (void (*)(void))(f)) /*****************************************************************************/ @@ -666,30 +667,39 @@ g_hash_table_steal_extended(GHashTable * hash_table, return FALSE; } #else - #define g_hash_table_steal_extended(hash_table, lookup_key, stolen_key, stolen_value) \ - ({ \ - gpointer *_stolen_key = (stolen_key); \ - gpointer *_stolen_value = (stolen_value); \ - \ - /* we cannot allow NULL arguments, because then we would leak the values in +#define g_hash_table_steal_extended(hash_table, lookup_key, stolen_key, stolen_value) \ + ({ \ + gpointer *_stolen_key = (stolen_key); \ + gpointer *_stolen_value = (stolen_value); \ + \ + /* we cannot allow NULL arguments, because then we would leak the values in * the compat implementation. */ \ - g_assert(_stolen_key); \ - g_assert(_stolen_value); \ - \ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ - g_hash_table_steal_extended(hash_table, lookup_key, _stolen_key, _stolen_value); \ - G_GNUC_END_IGNORE_DEPRECATIONS \ - }) + g_assert(_stolen_key); \ + g_assert(_stolen_value); \ + \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ + g_hash_table_steal_extended(hash_table, lookup_key, _stolen_key, _stolen_value); \ + G_GNUC_END_IGNORE_DEPRECATIONS \ + }) #endif /*****************************************************************************/ -__attribute__(( - __deprecated__("Don't use g_cancellable_reset(). Create a new cancellable instead."))) void -_nm_g_cancellable_reset(GCancellable *cancellable); +_nm_deprecated("Don't use this API") void _nm_forbidden_glib_api_0(void); +_nm_deprecated("Don't use this API") void _nm_forbidden_glib_api_n(gconstpointer arg0, ...); #undef g_cancellable_reset -#define g_cancellable_reset(cancellable) _nm_g_cancellable_reset(cancellable) +#define g_cancellable_reset(cancellable) _nm_forbidden_glib_api_n(cancellable) + +#undef g_idle_remove_by_data +#define g_idle_remove_by_data(data) _nm_forbidden_glib_api_n(data) + +#undef g_source_remove_by_funcs_user_data +#define g_source_remove_by_funcs_user_data(funcs, user_data) \ + _nm_forbidden_glib_api_n(funcs, user_data) + +#undef g_source_remove_by_user_data +#define g_source_remove_by_user_data(user_data) _nm_forbidden_glib_api_n(user_data) /*****************************************************************************/ diff --git a/src/libnm-glib-aux/nm-hash-utils.c b/src/libnm-glib-aux/nm-hash-utils.c index 10fc097c..a6949ebd 100644 --- a/src/libnm-glib-aux/nm-hash-utils.c +++ b/src/libnm-glib-aux/nm-hash-utils.c @@ -255,7 +255,7 @@ nm_ppdirect_equal(gconstpointer a, gconstpointer b) /*****************************************************************************/ guint -nm_gbytes_hash(gconstpointer p) +nm_g_bytes_hash(gconstpointer p) { GBytes * ptr = (GBytes *) p; gconstpointer arr; @@ -266,7 +266,7 @@ nm_gbytes_hash(gconstpointer p) } guint -nm_pgbytes_hash(gconstpointer p) +nm_pg_bytes_hash(gconstpointer p) { GBytes *const *ptr = p; gconstpointer arr; @@ -277,7 +277,7 @@ nm_pgbytes_hash(gconstpointer p) } gboolean -nm_pgbytes_equal(gconstpointer a, gconstpointer b) +nm_pg_bytes_equal(gconstpointer a, gconstpointer b) { GBytes *const *ptr_a = a; GBytes *const *ptr_b = b; diff --git a/src/libnm-glib-aux/nm-hash-utils.h b/src/libnm-glib-aux/nm-hash-utils.h index e79fb894..d7de2de4 100644 --- a/src/libnm-glib-aux/nm-hash-utils.h +++ b/src/libnm-glib-aux/nm-hash-utils.h @@ -122,138 +122,26 @@ nm_hash_update_bool(NMHashState *state, bool val) nm_hash_update(state, &val, sizeof(val)); } -#define _NM_HASH_COMBINE_BOOLS_x_1(t, y) ((y) ? ((t) (1ull << 0)) : ((t) 0ull)) -#define _NM_HASH_COMBINE_BOOLS_x_2(t, y, ...) \ - ((y) ? ((t) (1ull << 1)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_1(t, __VA_ARGS__) -#define _NM_HASH_COMBINE_BOOLS_x_3(t, y, ...) \ - ((y) ? ((t) (1ull << 2)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_2(t, __VA_ARGS__) -#define _NM_HASH_COMBINE_BOOLS_x_4(t, y, ...) \ - ((y) ? ((t) (1ull << 3)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_3(t, __VA_ARGS__) -#define _NM_HASH_COMBINE_BOOLS_x_5(t, y, ...) \ - ((y) ? ((t) (1ull << 4)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_4(t, __VA_ARGS__) -#define _NM_HASH_COMBINE_BOOLS_x_6(t, y, ...) \ - ((y) ? ((t) (1ull << 5)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_5(t, __VA_ARGS__) -#define _NM_HASH_COMBINE_BOOLS_x_7(t, y, ...) \ - ((y) ? ((t) (1ull << 6)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_6(t, __VA_ARGS__) -#define _NM_HASH_COMBINE_BOOLS_x_8(t, y, ...) \ - ((y) ? ((t) (1ull << 7)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_7(t, __VA_ARGS__) -#define _NM_HASH_COMBINE_BOOLS_x_9(t, y, ...) \ - ((y) ? ((t) (1ull << 8)) : ((t) 0ull)) \ - | (G_STATIC_ASSERT_EXPR(sizeof(t) >= 2), (_NM_HASH_COMBINE_BOOLS_x_8(t, __VA_ARGS__))) -#define _NM_HASH_COMBINE_BOOLS_x_10(t, y, ...) \ - ((y) ? ((t) (1ull << 9)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_9(t, __VA_ARGS__) -#define _NM_HASH_COMBINE_BOOLS_x_11(t, y, ...) \ - ((y) ? ((t) (1ull << 10)) : ((t) 0ull)) | _NM_HASH_COMBINE_BOOLS_x_10(t, __VA_ARGS__) -#define _NM_HASH_COMBINE_BOOLS_n2(t, n, ...) _NM_HASH_COMBINE_BOOLS_x_##n(t, __VA_ARGS__) -#define _NM_HASH_COMBINE_BOOLS_n(t, n, ...) _NM_HASH_COMBINE_BOOLS_n2(t, n, __VA_ARGS__) - -#define NM_HASH_COMBINE_BOOLS(type, ...) \ - ((type) (_NM_HASH_COMBINE_BOOLS_n(type, NM_NARG(__VA_ARGS__), __VA_ARGS__))) +#define _NM_HASH_COMBINE_BOOLS_OP(x, n) ((x) ? NM_BIT((n)) : 0u) + +#define NM_HASH_COMBINE_BOOLS(type, ...) \ + ((type) (NM_STATIC_ASSERT_EXPR_1(NM_NARG(__VA_ARGS__) <= 8 * sizeof(type)) \ + ? (NM_VA_ARGS_FOREACH(, , |, _NM_HASH_COMBINE_BOOLS_OP, __VA_ARGS__)) \ + : 0)) #define nm_hash_update_bools(state, ...) \ nm_hash_update_val(state, NM_HASH_COMBINE_BOOLS(guint8, __VA_ARGS__)) -#define _NM_HASH_COMBINE_VALS_typ_x_1(y) typeof(y) _v1; -#define _NM_HASH_COMBINE_VALS_typ_x_2(y, ...) \ - typeof(y) _v2; \ - _NM_HASH_COMBINE_VALS_typ_x_1(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_3(y, ...) \ - typeof(y) _v3; \ - _NM_HASH_COMBINE_VALS_typ_x_2(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_4(y, ...) \ - typeof(y) _v4; \ - _NM_HASH_COMBINE_VALS_typ_x_3(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_5(y, ...) \ - typeof(y) _v5; \ - _NM_HASH_COMBINE_VALS_typ_x_4(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_6(y, ...) \ - typeof(y) _v6; \ - _NM_HASH_COMBINE_VALS_typ_x_5(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_7(y, ...) \ - typeof(y) _v7; \ - _NM_HASH_COMBINE_VALS_typ_x_6(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_8(y, ...) \ - typeof(y) _v8; \ - _NM_HASH_COMBINE_VALS_typ_x_7(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_9(y, ...) \ - typeof(y) _v9; \ - _NM_HASH_COMBINE_VALS_typ_x_8(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_10(y, ...) \ - typeof(y) _v10; \ - _NM_HASH_COMBINE_VALS_typ_x_9(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_11(y, ...) \ - typeof(y) _v11; \ - _NM_HASH_COMBINE_VALS_typ_x_10(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_12(y, ...) \ - typeof(y) _v12; \ - _NM_HASH_COMBINE_VALS_typ_x_11(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_13(y, ...) \ - typeof(y) _v13; \ - _NM_HASH_COMBINE_VALS_typ_x_12(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_14(y, ...) \ - typeof(y) _v14; \ - _NM_HASH_COMBINE_VALS_typ_x_13(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_15(y, ...) \ - typeof(y) _v15; \ - _NM_HASH_COMBINE_VALS_typ_x_14(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_16(y, ...) \ - typeof(y) _v16; \ - _NM_HASH_COMBINE_VALS_typ_x_15(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_17(y, ...) \ - typeof(y) _v17; \ - _NM_HASH_COMBINE_VALS_typ_x_16(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_18(y, ...) \ - typeof(y) _v18; \ - _NM_HASH_COMBINE_VALS_typ_x_17(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_19(y, ...) \ - typeof(y) _v19; \ - _NM_HASH_COMBINE_VALS_typ_x_18(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_x_20(y, ...) \ - typeof(y) _v20; \ - _NM_HASH_COMBINE_VALS_typ_x_19(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_n2(n, ...) _NM_HASH_COMBINE_VALS_typ_x_##n(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_typ_n(n, ...) _NM_HASH_COMBINE_VALS_typ_n2(n, __VA_ARGS__) - -#define _NM_HASH_COMBINE_VALS_val_x_1(y) ._v1 = (y), -#define _NM_HASH_COMBINE_VALS_val_x_2(y, ...) ._v2 = (y), _NM_HASH_COMBINE_VALS_val_x_1(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_3(y, ...) ._v3 = (y), _NM_HASH_COMBINE_VALS_val_x_2(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_4(y, ...) ._v4 = (y), _NM_HASH_COMBINE_VALS_val_x_3(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_5(y, ...) ._v5 = (y), _NM_HASH_COMBINE_VALS_val_x_4(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_6(y, ...) ._v6 = (y), _NM_HASH_COMBINE_VALS_val_x_5(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_7(y, ...) ._v7 = (y), _NM_HASH_COMBINE_VALS_val_x_6(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_8(y, ...) ._v8 = (y), _NM_HASH_COMBINE_VALS_val_x_7(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_9(y, ...) ._v9 = (y), _NM_HASH_COMBINE_VALS_val_x_8(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_10(y, ...) \ - ._v10 = (y), _NM_HASH_COMBINE_VALS_val_x_9(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_11(y, ...) \ - ._v11 = (y), _NM_HASH_COMBINE_VALS_val_x_10(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_12(y, ...) \ - ._v12 = (y), _NM_HASH_COMBINE_VALS_val_x_11(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_13(y, ...) \ - ._v13 = (y), _NM_HASH_COMBINE_VALS_val_x_12(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_14(y, ...) \ - ._v14 = (y), _NM_HASH_COMBINE_VALS_val_x_13(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_15(y, ...) \ - ._v15 = (y), _NM_HASH_COMBINE_VALS_val_x_14(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_16(y, ...) \ - ._v16 = (y), _NM_HASH_COMBINE_VALS_val_x_15(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_17(y, ...) \ - ._v17 = (y), _NM_HASH_COMBINE_VALS_val_x_16(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_18(y, ...) \ - ._v18 = (y), _NM_HASH_COMBINE_VALS_val_x_17(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_19(y, ...) \ - ._v19 = (y), _NM_HASH_COMBINE_VALS_val_x_18(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_x_20(y, ...) \ - ._v20 = (y), _NM_HASH_COMBINE_VALS_val_x_19(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_n2(n, ...) _NM_HASH_COMBINE_VALS_val_x_##n(__VA_ARGS__) -#define _NM_HASH_COMBINE_VALS_val_n(n, ...) _NM_HASH_COMBINE_VALS_val_n2(n, __VA_ARGS__) +#define _NM_HASH_COMBINE_VALS_TYPE_OP(x, idx) typeof(x) _v##idx; +#define _NM_HASH_COMBINE_VALS_INIT_OP(x, idx) ._v##idx = (x), /* NM_HASH_COMBINE_VALS() is faster then nm_hash_update_val() as it combines multiple * calls to nm_hash_update() using a packed structure. */ -#define NM_HASH_COMBINE_VALS(var, ...) \ - const struct _nm_packed { \ - _NM_HASH_COMBINE_VALS_typ_n(NM_NARG(__VA_ARGS__), __VA_ARGS__) \ - } var _nm_alignas(guint64) = {_NM_HASH_COMBINE_VALS_val_n(NM_NARG(__VA_ARGS__), __VA_ARGS__)} +#define NM_HASH_COMBINE_VALS(var, ...) \ + const struct _nm_packed { \ + NM_VA_ARGS_FOREACH(, , , _NM_HASH_COMBINE_VALS_TYPE_OP, __VA_ARGS__) \ + } var _nm_alignas(guint64) = { \ + NM_VA_ARGS_FOREACH(, , , _NM_HASH_COMBINE_VALS_INIT_OP, __VA_ARGS__)} /* nm_hash_update_vals() is faster then nm_hash_update_val() as it combines multiple * calls to nm_hash_update() using a packed structure. */ @@ -301,15 +189,15 @@ nm_hash_update_str(NMHashState *state, const char *str) } #if _NM_CC_SUPPORT_GENERIC - /* Like nm_hash_update_str(), but restricted to arrays only. nm_hash_update_str() only works +/* Like nm_hash_update_str(), but restricted to arrays only. nm_hash_update_str() only works * with a @str argument that cannot be NULL. If you have a string pointer, that is never NULL, use * nm_hash_update() instead. */ - #define nm_hash_update_strarr(state, str) \ - (_Generic(&(str), const char(*)[sizeof(str)] \ - : nm_hash_update_str((state), (str)), char(*)[sizeof(str)] \ - : nm_hash_update_str((state), (str)))) +#define nm_hash_update_strarr(state, str) \ + (_Generic(&(str), const char(*)[sizeof(str)] \ + : nm_hash_update_str((state), (str)), char(*)[sizeof(str)] \ + : nm_hash_update_str((state), (str)))) #else - #define nm_hash_update_strarr(state, str) nm_hash_update_str((state), (str)) +#define nm_hash_update_strarr(state, str) nm_hash_update_str((state), (str)) #endif guint nm_hash_ptr(gconstpointer ptr); @@ -379,11 +267,11 @@ gboolean nm_ppdirect_equal(gconstpointer a, gconstpointer b); /*****************************************************************************/ -guint nm_gbytes_hash(gconstpointer p); -#define nm_gbytes_equal g_bytes_equal +guint nm_g_bytes_hash(gconstpointer p); +#define nm_g_bytes_equal g_bytes_equal -guint nm_pgbytes_hash(gconstpointer p); -gboolean nm_pgbytes_equal(gconstpointer a, gconstpointer b); +guint nm_pg_bytes_hash(gconstpointer p); +gboolean nm_pg_bytes_equal(gconstpointer a, gconstpointer b); /*****************************************************************************/ diff --git a/src/libnm-glib-aux/nm-io-utils.c b/src/libnm-glib-aux/nm-io-utils.c index 87478a2d..85a81f69 100644 --- a/src/libnm-glib-aux/nm-io-utils.c +++ b/src/libnm-glib-aux/nm-io-utils.c @@ -7,9 +7,11 @@ #include "nm-io-utils.h" -#include <sys/types.h> -#include <sys/stat.h> #include <fcntl.h> +#include <sys/socket.h> +#include <sys/stat.h> +#include <sys/types.h> +#include <sys/un.h> #include "nm-str-buf.h" #include "nm-shared-utils.h" @@ -628,3 +630,96 @@ next:; g_ptr_array_add(arr, NULL); return (char **) g_ptr_array_free(arr, FALSE); } + +/*****************************************************************************/ + +/* taken from systemd's sockaddr_un_set_path(). */ +int +nm_io_sockaddr_un_set(struct sockaddr_un *ret, NMOptionBool is_abstract, const char *path) +{ + gsize l; + + g_return_val_if_fail(ret, -EINVAL); + g_return_val_if_fail(path, -EINVAL); + nm_assert_is_ternary(is_abstract); + + if (is_abstract == NM_OPTION_BOOL_DEFAULT) + is_abstract = nm_io_sockaddr_un_path_is_abstract(path, &path); + + l = strlen(path); + if (l < 1) + return -EINVAL; + if (l > sizeof(ret->sun_path) - 1) + return -EINVAL; + + if (!is_abstract) { + if (path[0] != '/') { + /* non-abstract paths must be absolute. */ + return -EINVAL; + } + } + + memset(ret, 0, nm_offsetof(struct sockaddr_un, sun_path)); + ret->sun_family = AF_UNIX; + + if (is_abstract) { + ret->sun_path[0] = '\0'; + memcpy(&ret->sun_path[1], path, NM_MIN(l + 1, sizeof(ret->sun_path) - 1)); + } else + memcpy(&ret->sun_path, path, l + 1); + + /* For pathname addresses, we return the size with the trailing NUL. + * For abstract addresses, we return the size without the trailing NUL + * (which may not be even written). But as abstract sockets also have + * a NUL at the beginning of sun_path, the total length is always + * calculated the same. */ + return (nm_offsetof(struct sockaddr_un, sun_path) + 1) + l; +} + +/*****************************************************************************/ + +/* taken from systemd's sd_notify(). */ +int +nm_sd_notify(const char *state) +{ + struct sockaddr_un sockaddr; + struct iovec iovec; + struct msghdr msghdr = { + .msg_iov = &iovec, + .msg_iovlen = 1, + .msg_name = &sockaddr, + }; + nm_auto_close int fd = -1; + const char * e; + int r; + + if (!state) + g_return_val_if_reached(-EINVAL); + + e = getenv("NOTIFY_SOCKET"); + if (!e) + return 0; + + r = nm_io_sockaddr_un_set(&sockaddr, NM_OPTION_BOOL_DEFAULT, e); + if (r < 0) + return r; + msghdr.msg_namelen = r; + + fd = socket(AF_UNIX, SOCK_DGRAM | SOCK_CLOEXEC, 0); + if (fd < 0) + return -NM_ERRNO_NATIVE(errno); + + /* systemd calls here fd_set_sndbuf(fd, SNDBUF_SIZE) .We don't bother. */ + + iovec = (struct iovec){ + .iov_base = (gpointer) state, + .iov_len = strlen(state), + }; + + /* systemd sends ucred, if geteuid()/getegid() does not match getuid()/getgid(). We don't bother. */ + + if (sendmsg(fd, &msghdr, MSG_NOSIGNAL) < 0) + return -NM_ERRNO_NATIVE(errno); + + return 0; +} diff --git a/src/libnm-glib-aux/nm-io-utils.h b/src/libnm-glib-aux/nm-io-utils.h index 31ff6d05..479d0e51 100644 --- a/src/libnm-glib-aux/nm-io-utils.h +++ b/src/libnm-glib-aux/nm-io-utils.h @@ -60,4 +60,21 @@ void nm_g_subprocess_terminate_in_background(GSubprocess *subprocess, int timeou char **nm_utils_find_mkstemp_files(const char *dirname, const char *filename); +static inline gboolean +nm_io_sockaddr_un_path_is_abstract(const char *path, const char **out_path) +{ + if (path && path[0] == '@') { + NM_SET_OUT(out_path, &path[1]); + return TRUE; + } + NM_SET_OUT(out_path, path); + return FALSE; +} + +struct sockaddr_un; + +int nm_io_sockaddr_un_set(struct sockaddr_un *ret, NMOptionBool is_abstract, const char *path); + +int nm_sd_notify(const char *state); + #endif /* __NM_IO_UTILS_H__ */ diff --git a/src/libnm-glib-aux/nm-jansson.h b/src/libnm-glib-aux/nm-jansson.h index 6173a7ac..a907d2bb 100644 --- a/src/libnm-glib-aux/nm-jansson.h +++ b/src/libnm-glib-aux/nm-jansson.h @@ -10,20 +10,20 @@ #if WITH_JANSSON - #include <jansson.h> - - /* Added in Jansson v2.8 */ - #ifndef json_object_foreach_safe - #define json_object_foreach_safe(object, n, key, value) \ - for (key = json_object_iter_key(json_object_iter(object)), \ - n = json_object_iter_next(object, json_object_key_to_iter(key)); \ - key && (value = json_object_iter_value(json_object_key_to_iter(key))); \ - key = json_object_iter_key(n), \ - n = json_object_iter_next(object, json_object_key_to_iter(key))) - #endif +#include <jansson.h> + +/* Added in Jansson v2.8 */ +#ifndef json_object_foreach_safe +#define json_object_foreach_safe(object, n, key, value) \ + for (key = json_object_iter_key(json_object_iter(object)), \ + n = json_object_iter_next(object, json_object_key_to_iter(key)); \ + key && (value = json_object_iter_value(json_object_key_to_iter(key))); \ + key = json_object_iter_key(n), \ + n = json_object_iter_next(object, json_object_key_to_iter(key))) +#endif NM_AUTO_DEFINE_FCN0(json_t *, _nm_auto_decref_json, json_decref); - #define nm_auto_decref_json nm_auto(_nm_auto_decref_json) +#define nm_auto_decref_json nm_auto(_nm_auto_decref_json) #endif /* WITH_JANSON */ diff --git a/src/libnm-glib-aux/nm-json-aux.c b/src/libnm-glib-aux/nm-json-aux.c index dc67d6d5..0a3b25f8 100644 --- a/src/libnm-glib-aux/nm-json-aux.c +++ b/src/libnm-glib-aux/nm-json-aux.c @@ -16,7 +16,7 @@ * program). But that needs to be fixed by the json libraries, and it is by adding * symbol versioning in recent versions. */ #ifndef RTLD_DEEPBIND - #define RTLD_DEEPBIND 0 +#define RTLD_DEEPBIND 0 #endif /*****************************************************************************/ @@ -174,7 +174,7 @@ _nm_json_vt_internal_load(void) #elif !WITH_JANSSON && !defined(JANSSON_SONAME) soname = NULL; #else - #error "WITH_JANSON and JANSSON_SONAME are defined inconsistently." +#error "WITH_JANSON and JANSSON_SONAME are defined inconsistently." #endif if (!soname) diff --git a/src/libnm-glib-aux/nm-json-aux.h b/src/libnm-glib-aux/nm-json-aux.h index 936e9146..088d67a9 100644 --- a/src/libnm-glib-aux/nm-json-aux.h +++ b/src/libnm-glib-aux/nm-json-aux.h @@ -271,6 +271,49 @@ nm_jansson_json_as_int64(const NMJsonVt *vt, const nm_json_t *elem, gint64 *out_ } static inline int +nm_jansson_json_as_uint32(const NMJsonVt *vt, const nm_json_t *elem, guint32 *out_val) +{ + nm_json_int_t v; + + if (!elem) + return 0; + + if (!nm_json_is_integer(elem)) + return -EINVAL; + + v = vt->nm_json_integer_value(elem); + if (v < 0) + return -ERANGE; + if (v > (guint64) G_MAXUINT32) + return -ERANGE; + + NM_SET_OUT(out_val, v); + return 1; +} + +static inline int +nm_jansson_json_as_uint(const NMJsonVt *vt, const nm_json_t *elem, guint *out_val) +{ + nm_json_int_t v; + + if (!elem) + return 0; + + if (!nm_json_is_integer(elem)) + return -EINVAL; + + v = vt->nm_json_integer_value(elem); + if (v < 0) + return -ERANGE; + + if (v > (guint64) G_MAXUINT) + return -ERANGE; + + NM_SET_OUT(out_val, v); + return 1; +} + +static inline int nm_jansson_json_as_uint64(const NMJsonVt *vt, const nm_json_t *elem, guint64 *out_val) { nm_json_int_t v; @@ -328,17 +371,27 @@ nm_value_type_to_json(NMValueType value_type, GString *gstr, gconstpointer p_fie nm_json_gstr_append_int64(gstr, *((const gint32 *) p_field)); return; case NM_VALUE_TYPE_INT: + case NM_VALUE_TYPE_ENUM: nm_json_gstr_append_int64(gstr, *((const int *) p_field)); return; case NM_VALUE_TYPE_INT64: nm_json_gstr_append_int64(gstr, *((const gint64 *) p_field)); return; + case NM_VALUE_TYPE_UINT32: + nm_json_gstr_append_uint64(gstr, *((const guint32 *) p_field)); + return; + case NM_VALUE_TYPE_UINT: + case NM_VALUE_TYPE_FLAGS: + nm_json_gstr_append_uint64(gstr, *((const guint *) p_field)); + return; case NM_VALUE_TYPE_UINT64: nm_json_gstr_append_uint64(gstr, *((const guint64 *) p_field)); return; case NM_VALUE_TYPE_STRING: nm_json_gstr_append_string(gstr, *((const char *const *) p_field)); return; + case NM_VALUE_TYPE_BYTES: + case NM_VALUE_TYPE_NONE: case NM_VALUE_TYPE_UNSPEC: break; } @@ -357,9 +410,15 @@ nm_value_type_from_json(const NMJsonVt * vt, case NM_VALUE_TYPE_INT32: return (nm_jansson_json_as_int32(vt, elem, out_val) > 0); case NM_VALUE_TYPE_INT: + case NM_VALUE_TYPE_ENUM: return (nm_jansson_json_as_int(vt, elem, out_val) > 0); case NM_VALUE_TYPE_INT64: return (nm_jansson_json_as_int64(vt, elem, out_val) > 0); + case NM_VALUE_TYPE_UINT32: + return (nm_jansson_json_as_uint32(vt, elem, out_val) > 0); + case NM_VALUE_TYPE_UINT: + case NM_VALUE_TYPE_FLAGS: + return (nm_jansson_json_as_uint(vt, elem, out_val) > 0); case NM_VALUE_TYPE_UINT64: return (nm_jansson_json_as_uint64(vt, elem, out_val) > 0); @@ -368,6 +427,8 @@ nm_value_type_from_json(const NMJsonVt * vt, case NM_VALUE_TYPE_STRING: return (nm_jansson_json_as_string(vt, elem, out_val) > 0); + case NM_VALUE_TYPE_BYTES: + case NM_VALUE_TYPE_NONE: case NM_VALUE_TYPE_UNSPEC: break; } diff --git a/src/libnm-glib-aux/nm-logging-base.c b/src/libnm-glib-aux/nm-logging-base.c index e11bd9f3..cc19ef15 100644 --- a/src/libnm-glib-aux/nm-logging-base.c +++ b/src/libnm-glib-aux/nm-logging-base.c @@ -6,6 +6,8 @@ #include <syslog.h> +#include "nm-time-utils.h" + /*****************************************************************************/ const LogLevelDesc nm_log_level_desc[_LOGL_N] = { @@ -77,3 +79,61 @@ _nm_log_parse_level(const char *level, NMLogLevel *out_level) return FALSE; } + +/*****************************************************************************/ + +volatile NMLogLevel _nm_logging_enabled_value = LOGL_TRACE; + +void +_nm_logging_enabled_init(const char *level_str) +{ + NMLogLevel level; + + if (!_nm_log_parse_level(level_str, &level)) + level = LOGL_WARN; + else if (level == _LOGL_KEEP) + level = LOGL_WARN; + + _nm_logging_enabled_value = level; +} + +/*****************************************************************************/ + +void +_nm_log_simple_printf(NMLogLevel level, const char *fmt, ...) +{ + gs_free char *msg_heap = NULL; + char msg_stack[700]; + const char * msg; + const char * level_str; + gint64 ts; + + ts = nm_utils_clock_gettime_nsec(CLOCK_BOOTTIME); + + msg = nm_vsprintf_buf_or_alloc(fmt, fmt, msg_stack, &msg_heap, NULL); + + switch (level) { + case LOGL_TRACE: + level_str = "<trace>"; + break; + case LOGL_DEBUG: + level_str = "<debug>"; + break; + case LOGL_INFO: + level_str = "<info> "; + break; + case LOGL_WARN: + level_str = "<warn> "; + break; + default: + nm_assert(level == LOGL_ERR); + level_str = "<error>"; + break; + } + + g_print("[%" G_GINT64_FORMAT ".%05" G_GINT64_FORMAT "] %s %s\n", + ts / NM_UTILS_NSEC_PER_SEC, + (ts / (NM_UTILS_NSEC_PER_SEC / 10000)) % 10000, + level_str, + msg); +} diff --git a/src/libnm-glib-aux/nm-logging-base.h b/src/libnm-glib-aux/nm-logging-base.h index 136f0c04..3d76b378 100644 --- a/src/libnm-glib-aux/nm-logging-base.h +++ b/src/libnm-glib-aux/nm-logging-base.h @@ -25,4 +25,20 @@ extern const LogLevelDesc nm_log_level_desc[_LOGL_N]; gboolean _nm_log_parse_level(const char *level, NMLogLevel *out_level); +/*****************************************************************************/ + +extern volatile NMLogLevel _nm_logging_enabled_value; + +static inline gboolean +_nm_logging_enabled(NMLogLevel level) +{ + return level >= _nm_logging_enabled_value; +} + +void _nm_logging_enabled_init(const char *level_str); + +/*****************************************************************************/ + +void _nm_log_simple_printf(NMLogLevel level, const char *fmt, ...) _nm_printf(2, 3); + #endif /* __NM_LOGGING_BASE_H__ */ diff --git a/src/libnm-glib-aux/nm-logging-fwd.h b/src/libnm-glib-aux/nm-logging-fwd.h index 0ede91b2..3e999c4a 100644 --- a/src/libnm-glib-aux/nm-logging-fwd.h +++ b/src/libnm-glib-aux/nm-logging-fwd.h @@ -182,28 +182,28 @@ extern void _nm_utils_monotonic_timestamp_initialized(const struct timespec *tp, /* _LOGT() and _LOGt() both log with level TRACE, but the latter is disabled by default, * unless building with --with-more-logging. */ #if NM_MORE_LOGGING - #define _LOGt_ENABLED(...) _NMLOG_ENABLED(_LOGL_TRACE, ##__VA_ARGS__) - #define _LOGt(...) _NMLOG(_LOGL_TRACE, __VA_ARGS__) - #define _LOGt_err(errsv, ...) _NMLOG_err(errsv, _LOGL_TRACE, __VA_ARGS__) +#define _LOGt_ENABLED(...) _NMLOG_ENABLED(_LOGL_TRACE, ##__VA_ARGS__) +#define _LOGt(...) _NMLOG(_LOGL_TRACE, __VA_ARGS__) +#define _LOGt_err(errsv, ...) _NMLOG_err(errsv, _LOGL_TRACE, __VA_ARGS__) #else - /* still call the logging macros to get compile time checks, but they will be optimized out. */ - #define _LOGt_ENABLED(...) (FALSE && (_NMLOG_ENABLED(_LOGL_TRACE, ##__VA_ARGS__))) - #define _LOGt(...) \ - G_STMT_START \ - { \ - if (FALSE) { \ - _NMLOG(_LOGL_TRACE, __VA_ARGS__); \ - } \ - } \ - G_STMT_END - #define _LOGt_err(errsv, ...) \ - G_STMT_START \ - { \ - if (FALSE) { \ - _NMLOG_err(errsv, _LOGL_TRACE, __VA_ARGS__); \ - } \ - } \ - G_STMT_END +/* still call the logging macros to get compile time checks, but they will be optimized out. */ +#define _LOGt_ENABLED(...) (FALSE && (_NMLOG_ENABLED(_LOGL_TRACE, ##__VA_ARGS__))) +#define _LOGt(...) \ + G_STMT_START \ + { \ + if (FALSE) { \ + _NMLOG(_LOGL_TRACE, __VA_ARGS__); \ + } \ + } \ + G_STMT_END +#define _LOGt_err(errsv, ...) \ + G_STMT_START \ + { \ + if (FALSE) { \ + _NMLOG_err(errsv, _LOGL_TRACE, __VA_ARGS__); \ + } \ + } \ + G_STMT_END #endif /*****************************************************************************/ @@ -236,28 +236,28 @@ extern void _nm_utils_monotonic_timestamp_initialized(const struct timespec *tp, #define _LOG2E_err(errsv, ...) _NMLOG2_err(errsv, _LOGL_ERR, __VA_ARGS__) #if NM_MORE_LOGGING - #define _LOG2t_ENABLED(...) _NMLOG2_ENABLED(_LOGL_TRACE, ##__VA_ARGS__) - #define _LOG2t(...) _NMLOG2(_LOGL_TRACE, __VA_ARGS__) - #define _LOG2t_err(errsv, ...) _NMLOG2_err(errsv, _LOGL_TRACE, __VA_ARGS__) +#define _LOG2t_ENABLED(...) _NMLOG2_ENABLED(_LOGL_TRACE, ##__VA_ARGS__) +#define _LOG2t(...) _NMLOG2(_LOGL_TRACE, __VA_ARGS__) +#define _LOG2t_err(errsv, ...) _NMLOG2_err(errsv, _LOGL_TRACE, __VA_ARGS__) #else - /* still call the logging macros to get compile time checks, but they will be optimized out. */ - #define _LOG2t_ENABLED(...) (FALSE && (_NMLOG2_ENABLED(_LOGL_TRACE, ##__VA_ARGS__))) - #define _LOG2t(...) \ - G_STMT_START \ - { \ - if (FALSE) { \ - _NMLOG2(_LOGL_TRACE, __VA_ARGS__); \ - } \ - } \ - G_STMT_END - #define _LOG2t_err(errsv, ...) \ - G_STMT_START \ - { \ - if (FALSE) { \ - _NMLOG2_err(errsv, _LOGL_TRACE, __VA_ARGS__); \ - } \ - } \ - G_STMT_END +/* still call the logging macros to get compile time checks, but they will be optimized out. */ +#define _LOG2t_ENABLED(...) (FALSE && (_NMLOG2_ENABLED(_LOGL_TRACE, ##__VA_ARGS__))) +#define _LOG2t(...) \ + G_STMT_START \ + { \ + if (FALSE) { \ + _NMLOG2(_LOGL_TRACE, __VA_ARGS__); \ + } \ + } \ + G_STMT_END +#define _LOG2t_err(errsv, ...) \ + G_STMT_START \ + { \ + if (FALSE) { \ + _NMLOG2_err(errsv, _LOGL_TRACE, __VA_ARGS__); \ + } \ + } \ + G_STMT_END #endif #define _NMLOG3_ENABLED(level) (nm_logging_enabled((level), (_NMLOG3_DOMAIN))) @@ -281,28 +281,28 @@ extern void _nm_utils_monotonic_timestamp_initialized(const struct timespec *tp, #define _LOG3E_err(errsv, ...) _NMLOG3_err(errsv, _LOGL_ERR, __VA_ARGS__) #if NM_MORE_LOGGING - #define _LOG3t_ENABLED(...) _NMLOG3_ENABLED(_LOGL_TRACE, ##__VA_ARGS__) - #define _LOG3t(...) _NMLOG3(_LOGL_TRACE, __VA_ARGS__) - #define _LOG3t_err(errsv, ...) _NMLOG3_err(errsv, _LOGL_TRACE, __VA_ARGS__) +#define _LOG3t_ENABLED(...) _NMLOG3_ENABLED(_LOGL_TRACE, ##__VA_ARGS__) +#define _LOG3t(...) _NMLOG3(_LOGL_TRACE, __VA_ARGS__) +#define _LOG3t_err(errsv, ...) _NMLOG3_err(errsv, _LOGL_TRACE, __VA_ARGS__) #else - /* still call the logging macros to get compile time checks, but they will be optimized out. */ - #define _LOG3t_ENABLED(...) (FALSE && (_NMLOG3_ENABLED(_LOGL_TRACE, ##__VA_ARGS__))) - #define _LOG3t(...) \ - G_STMT_START \ - { \ - if (FALSE) { \ - _NMLOG3(_LOGL_TRACE, __VA_ARGS__); \ - } \ - } \ - G_STMT_END - #define _LOG3t_err(errsv, ...) \ - G_STMT_START \ - { \ - if (FALSE) { \ - _NMLOG3_err(errsv, _LOGL_TRACE, __VA_ARGS__); \ - } \ - } \ - G_STMT_END +/* still call the logging macros to get compile time checks, but they will be optimized out. */ +#define _LOG3t_ENABLED(...) (FALSE && (_NMLOG3_ENABLED(_LOGL_TRACE, ##__VA_ARGS__))) +#define _LOG3t(...) \ + G_STMT_START \ + { \ + if (FALSE) { \ + _NMLOG3(_LOGL_TRACE, __VA_ARGS__); \ + } \ + } \ + G_STMT_END +#define _LOG3t_err(errsv, ...) \ + G_STMT_START \ + { \ + if (FALSE) { \ + _NMLOG3_err(errsv, _LOGL_TRACE, __VA_ARGS__); \ + } \ + } \ + G_STMT_END #endif /*****************************************************************************/ diff --git a/src/libnm-glib-aux/nm-macros-internal.h b/src/libnm-glib-aux/nm-macros-internal.h index f2d81e1c..e7ee7f38 100644 --- a/src/libnm-glib-aux/nm-macros-internal.h +++ b/src/libnm-glib-aux/nm-macros-internal.h @@ -13,6 +13,7 @@ #include <string.h> #include <gio/gio.h> +#include <glib-unix.h> /*****************************************************************************/ @@ -42,10 +43,6 @@ /*****************************************************************************/ -#define nm_offsetofend(t, m) (G_STRUCT_OFFSET(t, m) + sizeof(((t *) NULL)->m)) - -/*****************************************************************************/ - #define gs_free nm_auto_g_free #define gs_unref_object nm_auto_unref_object #define gs_unref_variant nm_auto_unref_variant @@ -155,280 +152,6 @@ _nm_auto_freev(gpointer ptr) /*****************************************************************************/ -#define _NM_MACRO_SELECT_ARG_64(_1, \ - _2, \ - _3, \ - _4, \ - _5, \ - _6, \ - _7, \ - _8, \ - _9, \ - _10, \ - _11, \ - _12, \ - _13, \ - _14, \ - _15, \ - _16, \ - _17, \ - _18, \ - _19, \ - _20, \ - _21, \ - _22, \ - _23, \ - _24, \ - _25, \ - _26, \ - _27, \ - _28, \ - _29, \ - _30, \ - _31, \ - _32, \ - _33, \ - _34, \ - _35, \ - _36, \ - _37, \ - _38, \ - _39, \ - _40, \ - _41, \ - _42, \ - _43, \ - _44, \ - _45, \ - _46, \ - _47, \ - _48, \ - _49, \ - _50, \ - _51, \ - _52, \ - _53, \ - _54, \ - _55, \ - _56, \ - _57, \ - _58, \ - _59, \ - _60, \ - _61, \ - _62, \ - _63, \ - N, \ - ...) \ - N - -/* http://stackoverflow.com/a/2124385/354393 - * https://stackoverflow.com/questions/11317474/macro-to-count-number-of-arguments - */ - -#define NM_NARG(...) \ - _NM_MACRO_SELECT_ARG_64(, \ - ##__VA_ARGS__, \ - 62, \ - 61, \ - 60, \ - 59, \ - 58, \ - 57, \ - 56, \ - 55, \ - 54, \ - 53, \ - 52, \ - 51, \ - 50, \ - 49, \ - 48, \ - 47, \ - 46, \ - 45, \ - 44, \ - 43, \ - 42, \ - 41, \ - 40, \ - 39, \ - 38, \ - 37, \ - 36, \ - 35, \ - 34, \ - 33, \ - 32, \ - 31, \ - 30, \ - 29, \ - 28, \ - 27, \ - 26, \ - 25, \ - 24, \ - 23, \ - 22, \ - 21, \ - 20, \ - 19, \ - 18, \ - 17, \ - 16, \ - 15, \ - 14, \ - 13, \ - 12, \ - 11, \ - 10, \ - 9, \ - 8, \ - 7, \ - 6, \ - 5, \ - 4, \ - 3, \ - 2, \ - 1, \ - 0) -#define NM_NARG_MAX1(...) \ - _NM_MACRO_SELECT_ARG_64(, \ - ##__VA_ARGS__, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 1, \ - 0) -#define NM_NARG_MAX2(...) \ - _NM_MACRO_SELECT_ARG_64(, \ - ##__VA_ARGS__, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 2, \ - 1, \ - 0) - -#define _NM_MACRO_CALL(macro, ...) macro(__VA_ARGS__) - -/*****************************************************************************/ - #define _NM_MACRO_COMMA_IF_ARGS(...) \ _NM_MACRO_CALL(G_PASTE(__NM_MACRO_COMMA_IF_ARGS_, NM_NARG_MAX1(__VA_ARGS__)), __VA_ARGS__) #define __NM_MACRO_COMMA_IF_ARGS_0() @@ -449,9 +172,9 @@ _nm_auto_freev(gpointer ptr) /*****************************************************************************/ #if defined(__GNUC__) - #define _NM_PRAGMA_WARNING_DO(warning) G_STRINGIFY(GCC diagnostic ignored warning) +#define _NM_PRAGMA_WARNING_DO(warning) G_STRINGIFY(GCC diagnostic ignored warning) #elif defined(__clang__) - #define _NM_PRAGMA_WARNING_DO(warning) G_STRINGIFY(clang diagnostic ignored warning) +#define _NM_PRAGMA_WARNING_DO(warning) G_STRINGIFY(clang diagnostic ignored warning) #endif /* you can only suppress a specific warning that the compiler @@ -461,23 +184,22 @@ _nm_auto_freev(gpointer ptr) * same name for the same warning. */ #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) - #define NM_PRAGMA_WARNING_DISABLE(warning) \ - _Pragma("GCC diagnostic push") _Pragma(_NM_PRAGMA_WARNING_DO(warning)) +#define NM_PRAGMA_WARNING_DISABLE(warning) \ + _Pragma("GCC diagnostic push") _Pragma(_NM_PRAGMA_WARNING_DO(warning)) #elif defined(__clang__) - #define NM_PRAGMA_WARNING_DISABLE(warning) \ - _Pragma("clang diagnostic push") \ - _Pragma(_NM_PRAGMA_WARNING_DO("-Wunknown-warning-option")) \ - _Pragma(_NM_PRAGMA_WARNING_DO(warning)) +#define NM_PRAGMA_WARNING_DISABLE(warning) \ + _Pragma("clang diagnostic push") _Pragma(_NM_PRAGMA_WARNING_DO("-Wunknown-warning-option")) \ + _Pragma(_NM_PRAGMA_WARNING_DO(warning)) #else - #define NM_PRAGMA_WARNING_DISABLE(warning) +#define NM_PRAGMA_WARNING_DISABLE(warning) #endif #if defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 6)) - #define NM_PRAGMA_WARNING_REENABLE _Pragma("GCC diagnostic pop") +#define NM_PRAGMA_WARNING_REENABLE _Pragma("GCC diagnostic pop") #elif defined(__clang__) - #define NM_PRAGMA_WARNING_REENABLE _Pragma("clang diagnostic pop") +#define NM_PRAGMA_WARNING_REENABLE _Pragma("clang diagnostic pop") #else - #define NM_PRAGMA_WARNING_REENABLE +#define NM_PRAGMA_WARNING_REENABLE #endif /*****************************************************************************/ @@ -502,37 +224,9 @@ NM_G_ERROR_MSG(GError *error) /*****************************************************************************/ -#ifndef _NM_CC_SUPPORT_AUTO_TYPE - #if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) - #define _NM_CC_SUPPORT_AUTO_TYPE 1 - #else - #define _NM_CC_SUPPORT_AUTO_TYPE 0 - #endif -#endif - -#ifndef _NM_CC_SUPPORT_GENERIC - /* In the meantime, NetworkManager requires C11 and _Generic() should always be available. - * However, shared/nm-utils may also be used in VPN/applet, which possibly did not yet - * bump the C standard requirement. Leave this for the moment, but eventually we can - * drop it. - * - * Technically, gcc 4.9 already has some support for _Generic(). But there seems - * to be issues with propagating "const char *[5]" to "const char **". Only assume - * we have _Generic() since gcc 5. */ - #if (defined(__GNUC__) && __GNUC__ >= 5) || (defined(__clang__)) - #define _NM_CC_SUPPORT_GENERIC 1 - #else - #define _NM_CC_SUPPORT_GENERIC 0 - #endif -#endif - -#if _NM_CC_SUPPORT_AUTO_TYPE - #define _nm_auto_type __auto_type -#endif - #if _NM_CC_SUPPORT_GENERIC - #define _NM_CONSTCAST_FULL_1(type, obj_expr, obj) \ - (_Generic ((obj_expr), \ +#define _NM_CONSTCAST_FULL_1(type, obj_expr, obj) \ + (_Generic ((obj_expr), \ const void *const: ((const type *) (obj)), \ const void * : ((const type *) (obj)), \ void *const: (( type *) (obj)), \ @@ -541,8 +235,8 @@ NM_G_ERROR_MSG(GError *error) const type * : ((const type *) (obj)), \ type *const: (( type *) (obj)), \ type * : (( type *) (obj)))) - #define _NM_CONSTCAST_FULL_2(type, obj_expr, obj, alias_type2) \ - (_Generic ((obj_expr), \ +#define _NM_CONSTCAST_FULL_2(type, obj_expr, obj, alias_type2) \ + (_Generic ((obj_expr), \ const void *const: ((const type *) (obj)), \ const void * : ((const type *) (obj)), \ void *const: (( type *) (obj)), \ @@ -555,8 +249,8 @@ NM_G_ERROR_MSG(GError *error) const type * : ((const type *) (obj)), \ type *const: (( type *) (obj)), \ type * : (( type *) (obj)))) - #define _NM_CONSTCAST_FULL_3(type, obj_expr, obj, alias_type2, alias_type3) \ - (_Generic ((obj_expr), \ +#define _NM_CONSTCAST_FULL_3(type, obj_expr, obj, alias_type2, alias_type3) \ + (_Generic ((obj_expr), \ const void *const: ((const type *) (obj)), \ const void * : ((const type *) (obj)), \ void *const: (( type *) (obj)), \ @@ -573,8 +267,8 @@ NM_G_ERROR_MSG(GError *error) const type * : ((const type *) (obj)), \ type *const: (( type *) (obj)), \ type * : (( type *) (obj)))) - #define _NM_CONSTCAST_FULL_4(type, obj_expr, obj, alias_type2, alias_type3, alias_type4) \ - (_Generic ((obj_expr), \ +#define _NM_CONSTCAST_FULL_4(type, obj_expr, obj, alias_type2, alias_type3, alias_type4) \ + (_Generic ((obj_expr), \ const void *const: ((const type *) (obj)), \ const void * : ((const type *) (obj)), \ void *const: (( type *) (obj)), \ @@ -595,34 +289,34 @@ NM_G_ERROR_MSG(GError *error) const type * : ((const type *) (obj)), \ type *const: (( type *) (obj)), \ type * : (( type *) (obj)))) - #define _NM_CONSTCAST_FULL_x(type, obj_expr, obj, n, ...) \ - (_NM_CONSTCAST_FULL_##n(type, obj_expr, obj, ##__VA_ARGS__)) - #define _NM_CONSTCAST_FULL_y(type, obj_expr, obj, n, ...) \ - (_NM_CONSTCAST_FULL_x(type, obj_expr, obj, n, ##__VA_ARGS__)) - #define NM_CONSTCAST_FULL(type, obj_expr, obj, ...) \ - (_NM_CONSTCAST_FULL_y(type, obj_expr, obj, NM_NARG(dummy, ##__VA_ARGS__), ##__VA_ARGS__)) +#define _NM_CONSTCAST_FULL_x(type, obj_expr, obj, n, ...) \ + (_NM_CONSTCAST_FULL_##n(type, obj_expr, obj, ##__VA_ARGS__)) +#define _NM_CONSTCAST_FULL_y(type, obj_expr, obj, n, ...) \ + (_NM_CONSTCAST_FULL_x(type, obj_expr, obj, n, ##__VA_ARGS__)) +#define NM_CONSTCAST_FULL(type, obj_expr, obj, ...) \ + (_NM_CONSTCAST_FULL_y(type, obj_expr, obj, NM_NARG(dummy, ##__VA_ARGS__), ##__VA_ARGS__)) #else - #define NM_CONSTCAST_FULL(type, obj_expr, obj, ...) ((type *) (obj)) +#define NM_CONSTCAST_FULL(type, obj_expr, obj, ...) ((type *) (obj)) #endif #define NM_CONSTCAST(type, obj, ...) NM_CONSTCAST_FULL(type, (obj), (obj), ##__VA_ARGS__) #if _NM_CC_SUPPORT_GENERIC - #define NM_UNCONST_PTR(type, arg) \ - _Generic((arg), const type * : ((type *) (arg)), type * : ((type *) (arg))) +#define NM_UNCONST_PTR(type, arg) \ + _Generic((arg), const type * : ((type *) (arg)), type * : ((type *) (arg))) #else - #define NM_UNCONST_PTR(type, arg) ((type *) (arg)) +#define NM_UNCONST_PTR(type, arg) ((type *) (arg)) #endif #if _NM_CC_SUPPORT_GENERIC - #define NM_UNCONST_PPTR(type, arg) \ - _Generic ((arg), \ +#define NM_UNCONST_PPTR(type, arg) \ + _Generic ((arg), \ const type * *: ((type **) (arg)), \ type * *: ((type **) (arg)), \ const type *const*: ((type **) (arg)), \ type *const*: ((type **) (arg))) #else - #define NM_UNCONST_PPTR(type, arg) ((type **) (arg)) +#define NM_UNCONST_PPTR(type, arg) ((type **) (arg)) #endif #define NM_GOBJECT_CAST(type, obj, is_check, ...) \ @@ -649,71 +343,42 @@ NM_G_ERROR_MSG(GError *error) _ptr; \ }) -#if _NM_CC_SUPPORT_GENERIC - /* returns @value, if the type of @value matches @type. - * This requires support for C11 _Generic(). If no support is - * present, this returns @value directly. - * - * It's useful to check the let the compiler ensure that @value is - * of a certain type. */ - #define _NM_ENSURE_TYPE(type, value) (_Generic((value), type : (value))) - #define _NM_ENSURE_TYPE_CONST(type, value) \ - (_Generic((value), const type \ - : ((const type) (value)), const type const \ - : ((const type) (value)), type \ - : ((const type) (value)), type const \ - : ((const type) (value)))) -#else - #define _NM_ENSURE_TYPE(type, value) (value) - #define _NM_ENSURE_TYPE_CONST(type, value) ((const type) (value)) -#endif - -#if _NM_CC_SUPPORT_GENERIC && (!defined(__clang__) || __clang_major__ > 3) - #define NM_STRUCT_OFFSET_ENSURE_TYPE(type, container, field) \ - (_Generic((&(((container *) NULL)->field))[0], type : G_STRUCT_OFFSET(container, field))) -#else - #define NM_STRUCT_OFFSET_ENSURE_TYPE(type, container, field) G_STRUCT_OFFSET(container, field) -#endif - /* Casts (arg) to (type**), but also having a compile time check that * the arg is some sort of pointer to a pointer. * * The only purpose of this macro is some additional compile time safety, * that the argument is a pointer to pointer. But then it will C cast any kind * of such argument. */ -#define NM_CAST_PPTR(type, arg) \ - ({ \ - typeof(*(arg)) *const _arg = (arg); \ - typeof(*_arg) _arg2 = _arg ? *_arg : NULL; \ - _nm_unused const void *const _arg3 = _arg2; \ - \ - (type **) _arg; \ +#define NM_CAST_PPTR(type, arg) \ + ({ \ + _NM_ENSURE_POINTER(*(arg)); \ + (type **) (arg); \ }) #if _NM_CC_SUPPORT_GENERIC - /* these macros cast (value) to - * - "const char **" (for "MC", mutable-const) - * - "const char *const*" (for "CC", const-const) - * The point is to do this cast, but only accepting pointers - * that are compatible already. - * - * The problem is, if you add a function like g_strdupv(), the input - * argument is not modified (CC), but you want to make it work also - * for "char **". C doesn't allow this form of casting (for good reasons), - * so the function makes a choice like g_strdupv(char**). That means, - * every time you want to call it with a const argument, you need to - * explicitly cast it. - * - * These macros do the cast, but they only accept a compatible input - * type, otherwise they will fail compilation. - */ - #define NM_CAST_STRV_MC(value) \ - (_Generic ((value), \ +/* these macros cast (value) to + * - "const char **" (for "MC", mutable-const) + * - "const char *const*" (for "CC", const-const) + * The point is to do this cast, but only accepting pointers + * that are compatible already. + * + * The problem is, if you add a function like g_strdupv(), the input + * argument is not modified (CC), but you want to make it work also + * for "char **". C doesn't allow this form of casting (for good reasons), + * so the function makes a choice like g_strdupv(char**). That means, + * every time you want to call it with a const argument, you need to + * explicitly cast it. + * + * These macros do the cast, but they only accept a compatible input + * type, otherwise they will fail compilation. + */ +#define NM_CAST_STRV_MC(value) \ + (_Generic ((value), \ const char * *: (const char * *) (value), \ char * *: (const char * *) (value), \ void *: (const char * *) (value))) - #define NM_CAST_STRV_CC(value) \ - (_Generic ((value), \ +#define NM_CAST_STRV_CC(value) \ + (_Generic ((value), \ const char *const*: (const char *const*) (value), \ const char * *: (const char *const*) (value), \ char *const*: (const char *const*) (value), \ @@ -727,18 +392,18 @@ NM_G_ERROR_MSG(GError *error) const void *const: (const char *const*) (value), \ void *const: (const char *const*) (value))) #else - #define NM_CAST_STRV_MC(value) ((const char **) (value)) - #define NM_CAST_STRV_CC(value) ((const char *const *) (value)) +#define NM_CAST_STRV_MC(value) ((const char **) (value)) +#define NM_CAST_STRV_CC(value) ((const char *const *) (value)) #endif #if _NM_CC_SUPPORT_GENERIC - #define NM_PROPAGATE_CONST(test_expr, ptr) \ - (_Generic ((test_expr), \ +#define NM_PROPAGATE_CONST(test_expr, ptr) \ + (_Generic ((test_expr), \ const typeof (*(test_expr)) *: ((const typeof (*(ptr)) *) (ptr)), \ default: (_Generic ((test_expr), \ typeof (*(test_expr)) *: (ptr))))) #else - #define NM_PROPAGATE_CONST(test_expr, ptr) (ptr) +#define NM_PROPAGATE_CONST(test_expr, ptr) (ptr) #endif /* with the way it is implemented, the caller may or may not pass a trailing @@ -958,16 +623,16 @@ nm_str_realloc(char *str) #define _NM_GET_PRIVATE(self, type, is_check, ...) \ (&(NM_GOBJECT_CAST_NON_NULL(type, (self), is_check, ##__VA_ARGS__)->_priv)) #if _NM_CC_SUPPORT_AUTO_TYPE - #define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) \ - ({ \ - _nm_auto_type _self_get_private = \ - NM_GOBJECT_CAST_NON_NULL(type, (self), is_check, ##__VA_ARGS__); \ - \ - NM_PROPAGATE_CONST(_self_get_private, _self_get_private->_priv); \ - }) +#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) \ + ({ \ + _nm_auto_type _self_get_private = \ + NM_GOBJECT_CAST_NON_NULL(type, (self), is_check, ##__VA_ARGS__); \ + \ + NM_PROPAGATE_CONST(_self_get_private, _self_get_private->_priv); \ + }) #else - #define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) \ - (NM_GOBJECT_CAST_NON_NULL(type, (self), is_check, ##__VA_ARGS__)->_priv) +#define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) \ + (NM_GOBJECT_CAST_NON_NULL(type, (self), is_check, ##__VA_ARGS__)->_priv) #endif /*****************************************************************************/ @@ -1225,6 +890,12 @@ nm_g_variant_take_ref(GVariant *v) return v; } +static inline gboolean +nm_g_variant_equal(GVariant *a, GVariant *b) +{ + return (a == b) || (a && b && g_variant_equal(a, b)); +} + /*****************************************************************************/ #define NM_DIV_ROUND_UP(x, y) \ @@ -1245,27 +916,21 @@ nm_g_variant_take_ref(GVariant *v) return (v); \ } #define NM_UTILS_LOOKUP_ITEM(v, n) \ - (void) 0; \ -case v: \ - return (n); \ - (void) 0 + case v: \ + return (n); #define NM_UTILS_LOOKUP_STR_ITEM(v, n) NM_UTILS_LOOKUP_ITEM(v, "" n "") #define NM_UTILS_LOOKUP_ITEM_IGNORE(v) \ - (void) 0; \ -case v: \ - break; \ - (void) 0 + case v: \ + break; #define NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER() \ - (void) 0; \ -default: \ - break; \ - (void) 0 + default: \ + break; #define NM_UTILS_LOOKUP_DEFINE(fcn_name, lookup_type, result_type, unknown_val, ...) \ result_type fcn_name(lookup_type val) \ { \ switch (val) { \ - (void) 0, __VA_ARGS__(void) 0; \ + NM_VA_ARGS_JOIN(, __VA_ARGS__) \ }; \ { \ unknown_val; \ @@ -1471,17 +1136,15 @@ nm_strcmp_p(gconstpointer a, gconstpointer b) /*****************************************************************************/ static inline int -_NM_IN_STRSET_ASCII_CASE_op_streq(const char *x, const char *s) +_NM_IN_STRSET_EVAL_op_streq_ascii_case(const char *x1, const char *x) { - return s && g_ascii_strcasecmp(x, s) == 0; + return x && g_ascii_strcasecmp(x1, x) == 0; } -#define NM_IN_STRSET_ASCII_CASE(x, ...) \ - _NM_IN_STRSET_EVAL_N(||, \ - _NM_IN_STRSET_ASCII_CASE_op_streq, \ - x, \ - NM_NARG(__VA_ARGS__), \ - __VA_ARGS__) +#define _NM_IN_STRSET_EVAL_OP_STREQ_ASCII_CASE(x, idx) \ + _NM_IN_STRSET_EVAL_op_streq_ascii_case(_x1, x) +#define NM_IN_STRSET_ASCII_CASE(x1, ...) \ + _NM_IN_STRSET_EVAL(||, _NM_IN_STRSET_EVAL_OP_STREQ_ASCII_CASE, x1, __VA_ARGS__) #define NM_STR_HAS_SUFFIX_ASCII_CASE(str, suffix) \ ({ \ @@ -1511,6 +1174,25 @@ _NM_IN_STRSET_ASCII_CASE_op_streq(const char *x, const char *s) /*****************************************************************************/ +static inline int +nm_memcmp_n(gconstpointer p1, gsize len1, gconstpointer p2, gsize len2, gsize element_size) +{ + nm_assert(element_size > 0); + + NM_CMP_DIRECT(len1, len2); + if (len1 > 0) + NM_CMP_DIRECT_MEMCMP(p1, p2, len1 * element_size); + return 0; +} + +static inline int +nm_memeq_n(gconstpointer p1, gsize len1, gconstpointer p2, gsize len2, gsize element_size) +{ + return nm_memcmp_n(p1, len1, p2, len2, element_size) == 0; +} + +/*****************************************************************************/ + /* like g_memdup(). The difference is that the @size argument is of type * gsize, while g_memdup() has type guint. Since, the size of container types * like GArray is guint as well, this means trying to g_memdup() an @@ -1668,28 +1350,28 @@ _nm_strndup_a_step(char *s, const char *str, gsize len) * * Instead, this generic macro is supposed to handle all integers correctly. */ #if _NM_CC_SUPPORT_GENERIC - #define nm_strdup_int(val) \ - _Generic((val), char \ - : g_strdup_printf("%d", (int) (val)), \ - \ - signed char \ - : g_strdup_printf("%d", (signed) (val)), signed short \ - : g_strdup_printf("%d", (signed) (val)), signed \ - : g_strdup_printf("%d", (signed) (val)), signed long \ - : g_strdup_printf("%ld", (signed long) (val)), signed long long \ - : g_strdup_printf("%lld", (signed long long) (val)), \ - \ - unsigned char \ - : g_strdup_printf("%u", (unsigned) (val)), unsigned short \ - : g_strdup_printf("%u", (unsigned) (val)), unsigned \ - : g_strdup_printf("%u", (unsigned) (val)), unsigned long \ - : g_strdup_printf("%lu", (unsigned long) (val)), unsigned long long \ - : g_strdup_printf("%llu", (unsigned long long) (val))) +#define nm_strdup_int(val) \ + _Generic((val), char \ + : g_strdup_printf("%d", (int) (val)), \ + \ + signed char \ + : g_strdup_printf("%d", (signed) (val)), signed short \ + : g_strdup_printf("%d", (signed) (val)), signed \ + : g_strdup_printf("%d", (signed) (val)), signed long \ + : g_strdup_printf("%ld", (signed long) (val)), signed long long \ + : g_strdup_printf("%lld", (signed long long) (val)), \ + \ + unsigned char \ + : g_strdup_printf("%u", (unsigned) (val)), unsigned short \ + : g_strdup_printf("%u", (unsigned) (val)), unsigned \ + : g_strdup_printf("%u", (unsigned) (val)), unsigned long \ + : g_strdup_printf("%lu", (unsigned long) (val)), unsigned long long \ + : g_strdup_printf("%llu", (unsigned long long) (val))) #else - #define nm_strdup_int(val) \ - ((sizeof(val) == sizeof(guint64) && ((typeof(val)) -1) > 0) \ - ? g_strdup_printf("%" G_GUINT64_FORMAT, (guint64) (val)) \ - : g_strdup_printf("%" G_GINT64_FORMAT, (gint64) (val))) +#define nm_strdup_int(val) \ + ((sizeof(val) == sizeof(guint64) && ((typeof(val)) -1) > 0) \ + ? g_strdup_printf("%" G_GUINT64_FORMAT, (guint64) (val)) \ + : g_strdup_printf("%" G_GINT64_FORMAT, (gint64) (val))) #endif /*****************************************************************************/ @@ -1877,7 +1559,7 @@ nm_decode_version(guint version, guint *major, guint *minor, guint *micro) /*****************************************************************************/ #ifdef _G_BOOLEAN_EXPR - /* g_assert() uses G_LIKELY(), which in turn uses _G_BOOLEAN_EXPR(). +/* g_assert() uses G_LIKELY(), which in turn uses _G_BOOLEAN_EXPR(). * As glib's implementation uses a local variable _g_boolean_var_, * we cannot do * g_assert (some_macro ()); @@ -1887,8 +1569,8 @@ nm_decode_version(guint version, guint *major, guint *minor, guint *micro) * * Workaround that by re-defining _G_BOOLEAN_EXPR() **/ - #undef _G_BOOLEAN_EXPR - #define _G_BOOLEAN_EXPR(expr) NM_BOOLEAN_EXPR(expr) +#undef _G_BOOLEAN_EXPR +#define _G_BOOLEAN_EXPR(expr) NM_BOOLEAN_EXPR(expr) #endif /*****************************************************************************/ @@ -1913,4 +1595,22 @@ NM_AUTO_DEFINE_FCN_VOID0(GMutex *, _nm_auto_unlock_g_mutex, g_mutex_unlock); /*****************************************************************************/ +static inline GObject * +nm_g_object_freeze_notify(gpointer obj) +{ + if (obj) + g_object_freeze_notify(obj); + return obj; +} + +static inline void +nm_g_object_thaw_notify_clear(GObject **p_obj) +{ + nm_clear_pointer(p_obj, g_object_thaw_notify); +} + +#define nm_auto_g_object_thaw_notify nm_auto(nm_g_object_thaw_notify_clear) + +/*****************************************************************************/ + #endif /* __NM_MACROS_INTERNAL_H__ */ diff --git a/src/libnm-glib-aux/nm-random-utils.c b/src/libnm-glib-aux/nm-random-utils.c index b055bc3f..2f42f3f6 100644 --- a/src/libnm-glib-aux/nm-random-utils.c +++ b/src/libnm-glib-aux/nm-random-utils.c @@ -12,9 +12,9 @@ #include <sys/syscall.h> #if USE_SYS_RANDOM_H - #include <sys/random.h> +#include <sys/random.h> #else - #include <linux/random.h> +#include <linux/random.h> #endif #include "nm-shared-utils.h" @@ -23,15 +23,15 @@ /*****************************************************************************/ #if !defined(SYS_getrandom) && defined(__NR_getrandom) - #define SYS_getrandom __NR_getrandom +#define SYS_getrandom __NR_getrandom #endif #ifndef GRND_NONBLOCK - #define GRND_NONBLOCK 0x01 +#define GRND_NONBLOCK 0x01 #endif #ifndef GRND_INSECURE - #define GRND_INSECURE 0x04 +#define GRND_INSECURE 0x04 #endif #if !HAVE_GETRANDOM && defined(SYS_getrandom) @@ -40,8 +40,8 @@ getrandom(void *buf, size_t buflen, unsigned flags) { return syscall(SYS_getrandom, buf, buflen, flags); } - #undef HAVE_GETRANDOM - #define HAVE_GETRANDOM 1 +#undef HAVE_GETRANDOM +#define HAVE_GETRANDOM 1 #endif /*****************************************************************************/ diff --git a/src/libnm-glib-aux/nm-ref-string.h b/src/libnm-glib-aux/nm-ref-string.h index df37d583..6950d1b9 100644 --- a/src/libnm-glib-aux/nm-ref-string.h +++ b/src/libnm-glib-aux/nm-ref-string.h @@ -152,6 +152,18 @@ NM_REF_STRING_UPCAST(const char *str) return rstr; } +static inline NMRefString * +nm_ref_string_ref_upcast(const char *str) +{ + return nm_ref_string_ref(NM_REF_STRING_UPCAST(str)); +} + +static inline void +nm_ref_string_unref_upcast(const char *str) +{ + nm_ref_string_unref(NM_REF_STRING_UPCAST(str)); +} + static inline gboolean nm_ref_string_reset_str(NMRefString **ptr, const char *str) { diff --git a/src/libnm-glib-aux/nm-shared-utils.c b/src/libnm-glib-aux/nm-shared-utils.c index 81852aea..9d1a1bf1 100644 --- a/src/libnm-glib-aux/nm-shared-utils.c +++ b/src/libnm-glib-aux/nm-shared-utils.c @@ -12,7 +12,6 @@ #include <poll.h> #include <fcntl.h> #include <sys/syscall.h> -#include <glib-unix.h> #include <net/if.h> #include <net/ethernet.h> #include <pthread.h> @@ -100,6 +99,29 @@ nm_ip_addr_set_from_untrusted(int addr_family, return TRUE; } +gboolean +nm_ip_addr_set_from_variant(int addr_family, gpointer dst, GVariant *variant, int *out_addr_family) +{ + gconstpointer bytes; + gsize len; + + g_return_val_if_fail(dst, FALSE); + g_return_val_if_fail(variant, FALSE); + + /* This function always expects IP addressea a byte arrays ("ay"). Note that + * several NetworkManager API uses "u" (32 bit unsigned intergers) for IPv4 addresses. + * So this function won't work in those cases. + * + * Btw, using "u" for IPv4 address messes badly with the endianness (host + * vs network byte order). Don't do that. + */ + g_return_val_if_fail(g_variant_is_of_type(variant, G_VARIANT_TYPE("ay")), FALSE); + + bytes = g_variant_get_fixed_array(variant, &len, sizeof(guint8)); + + return nm_ip_addr_set_from_untrusted(addr_family, dst, bytes, len, out_addr_family); +} + /*****************************************************************************/ G_STATIC_ASSERT(ETH_ALEN == sizeof(struct ether_addr)); @@ -141,9 +163,9 @@ _nm_utils_inet6_is_token(const struct in6_addr *in6addr) * token. */ void -nm_utils_ipv6_addr_set_interface_identifier(struct in6_addr *addr, const NMUtilsIPv6IfaceId iid) +nm_utils_ipv6_addr_set_interface_identifier(struct in6_addr *addr, const NMUtilsIPv6IfaceId *iid) { - memcpy(addr->s6_addr + 8, &iid.id_u8, 8); + memcpy(addr->s6_addr + 8, &iid->id_u8, 8); } /** @@ -199,8 +221,8 @@ nm_utils_ipv6_interface_identifier_get_from_token(NMUtilsIPv6IfaceId *iid, const * Returns: the input buffer filled with the id as string. */ const char * -nm_utils_inet6_interface_identifier_to_token(NMUtilsIPv6IfaceId iid, - char buf[static INET6_ADDRSTRLEN]) +nm_utils_inet6_interface_identifier_to_token(const NMUtilsIPv6IfaceId *iid, + char buf[static INET6_ADDRSTRLEN]) { struct in6_addr i6_token = {.s6_addr = { 0, @@ -264,7 +286,7 @@ _nm_assert_on_main_thread(void) /*****************************************************************************/ void -nm_utils_strbuf_append_c(char **buf, gsize *len, char c) +nm_strbuf_append_c(char **buf, gsize *len, char c) { switch (*len) { case 0: @@ -284,7 +306,7 @@ nm_utils_strbuf_append_c(char **buf, gsize *len, char c) } void -nm_utils_strbuf_append_bin(char **buf, gsize *len, gconstpointer str, gsize str_len) +nm_strbuf_append_bin(char **buf, gsize *len, gconstpointer str, gsize str_len) { switch (*len) { case 0: @@ -319,7 +341,7 @@ nm_utils_strbuf_append_bin(char **buf, gsize *len, gconstpointer str, gsize str_ } void -nm_utils_strbuf_append_str(char **buf, gsize *len, const char *str) +nm_strbuf_append_str(char **buf, gsize *len, const char *str) { gsize src_len; @@ -353,7 +375,7 @@ nm_utils_strbuf_append_str(char **buf, gsize *len, const char *str) } void -nm_utils_strbuf_append(char **buf, gsize *len, const char *format, ...) +nm_strbuf_append(char **buf, gsize *len, const char *format, ...) { char * p = *buf; va_list args; @@ -376,25 +398,25 @@ nm_utils_strbuf_append(char **buf, gsize *len, const char *format, ...) } /** - * nm_utils_strbuf_seek_end: + * nm_strbuf_seek_end: * @buf: the input/output buffer * @len: the input/output length of the buffer. * - * Commonly, one uses nm_utils_strbuf_append*(), to incrementally + * Commonly, one uses nm_strbuf_append*(), to incrementally * append strings to the buffer. However, sometimes we need to use * existing API to write to the buffer. * After doing so, we want to adjust the buffer counter. * Essentially, * * g_snprintf (buf, len, ...); - * nm_utils_strbuf_seek_end (&buf, &len); + * nm_strbuf_seek_end (&buf, &len); * * is almost the same as * - * nm_utils_strbuf_append (&buf, &len, ...); + * nm_strbuf_append (&buf, &len, ...); * * The only difference is the behavior when the string got truncated: - * nm_utils_strbuf_append() will recognize that and set the remaining + * nm_strbuf_append() will recognize that and set the remaining * length to zero. * * In general, the behavior is: @@ -412,13 +434,13 @@ nm_utils_strbuf_append(char **buf, gsize *len, const char *format, ...) * the NUL byte. This would happen with * * strncpy (buf, long_str, len); - * nm_utils_strbuf_seek_end (&buf, &len). + * nm_strbuf_seek_end (&buf, &len). * * where strncpy() does truncate the string and not NUL terminate it. - * nm_utils_strbuf_seek_end() would then NUL terminate it. + * nm_strbuf_seek_end() would then NUL terminate it. */ void -nm_utils_strbuf_seek_end(char **buf, gsize *len) +nm_strbuf_seek_end(char **buf, gsize *len) { gsize l; char *end; @@ -455,7 +477,7 @@ truncate: /*****************************************************************************/ GBytes * -nm_gbytes_get_empty(void) +nm_g_bytes_get_empty(void) { static GBytes *bytes = NULL; GBytes * b; @@ -487,8 +509,18 @@ nm_g_bytes_new_from_str(const char *str) return g_bytes_new_take(nm_memdup(str, l + 1u), l); } +GBytes * +nm_g_bytes_new_from_variant_ay(GVariant *var) +{ + if (!var) + return NULL; + if (!g_variant_is_of_type(var, G_VARIANT_TYPE_BYTESTRING)) + g_return_val_if_reached(NULL); + return g_variant_get_data_as_bytes(var); +} + /** - * nm_utils_gbytes_equal_mem: + * nm_g_bytes_equal_mem: * @bytes: (allow-none): a #GBytes array to compare. Note that * %NULL is treated like an #GBytes array of length zero. * @mem_data: the data pointer with @mem_len bytes @@ -498,7 +530,7 @@ nm_g_bytes_new_from_str(const char *str) * special case, a %NULL @bytes is treated like an empty array. */ gboolean -nm_utils_gbytes_equal_mem(GBytes *bytes, gconstpointer mem_data, gsize mem_len) +nm_g_bytes_equal_mem(GBytes *bytes, gconstpointer mem_data, gsize mem_len) { gconstpointer p; gsize l; @@ -516,7 +548,7 @@ nm_utils_gbytes_equal_mem(GBytes *bytes, gconstpointer mem_data, gsize mem_len) } GVariant * -nm_utils_gbytes_to_variant_ay(GBytes *bytes) +nm_g_bytes_to_variant_ay(const GBytes *bytes) { const guint8 *p = NULL; gsize l = 0; @@ -524,7 +556,7 @@ nm_utils_gbytes_to_variant_ay(GBytes *bytes) if (!bytes) { /* for convenience, accept NULL to return an empty variant */ } else - p = g_bytes_get_data(bytes, &l); + p = g_bytes_get_data((GBytes *) bytes, &l); return nm_g_variant_new_ay(p, l); } @@ -560,6 +592,12 @@ nm_g_variant_singleton_u_0(void) } GVariant * +nm_g_variant_singleton_i_0(void) +{ + return _variant_singleton_get(g_variant_new_int32(0)); +} + +GVariant * nm_g_variant_singleton_b(gboolean value) { return value ? _variant_singleton_get(g_variant_new_boolean(TRUE)) @@ -603,6 +641,24 @@ _variant_singleton_get_array_init(GVariant **p_singleton, const char *variant_ty }) GVariant * +nm_g_variant_singleton_au(void) +{ + return _variant_singleton_get_array("u"); +} + +GVariant * +nm_g_variant_singleton_aay(void) +{ + return _variant_singleton_get_array("ay"); +} + +GVariant * +nm_g_variant_singleton_as(void) +{ + return _variant_singleton_get_array("s"); +} + +GVariant * nm_g_variant_singleton_aLsvI(void) { return _variant_singleton_get_array("{sv}"); @@ -620,10 +676,37 @@ nm_g_variant_singleton_aaLsvI(void) return _variant_singleton_get_array("a{sv}"); } +GVariant * +nm_g_variant_singleton_ao(void) +{ + return _variant_singleton_get_array("o"); +} + +GVariant * +nm_g_variant_maybe_singleton_i(gint32 value) +{ + /* Warning: this function always returns a non-floating reference + * that must be consumed (and later unrefed) by the caller. + * + * The instance is either a singleton instance or a newly created + * instance. + * + * The idea of this is that common values (zero) can use the immutable + * singleton/flyweight instance and avoid allocating a new instance in + * the (presumable) common case. + */ + switch (value) { + case 0: + return g_variant_ref(nm_g_variant_singleton_i_0()); + default: + return g_variant_take_ref(g_variant_new_int32(value)); + } +} + /*****************************************************************************/ GHashTable * -nm_utils_strdict_clone(GHashTable *src) +nm_strdict_clone(GHashTable *src) { GHashTable * dst; GHashTableIter iter; @@ -645,7 +728,7 @@ nm_utils_strdict_clone(GHashTable *src) * Returns a floating reference. */ GVariant * -nm_utils_strdict_to_variant_ass(GHashTable *strdict) +nm_strdict_to_variant_ass(GHashTable *strdict) { gs_free NMUtilsNamedValue *values_free = NULL; NMUtilsNamedValue values_prepared[20]; @@ -666,7 +749,7 @@ nm_utils_strdict_to_variant_ass(GHashTable *strdict) /*****************************************************************************/ GVariant * -nm_utils_strdict_to_variant_asv(GHashTable *strdict) +nm_strdict_to_variant_asv(GHashTable *strdict) { gs_free NMUtilsNamedValue *values_free = NULL; NMUtilsNamedValue values_prepared[20]; @@ -715,7 +798,7 @@ nm_strquote(char *buf, gsize buf_len, const char *str) const char *const buf0 = buf; if (!str) { - nm_utils_strbuf_append_str(&buf, &buf_len, "(null)"); + nm_strbuf_append_str(&buf, &buf_len, "(null)"); goto out; } @@ -734,7 +817,7 @@ nm_strquote(char *buf, gsize buf_len, const char *str) *(buf++) = '"'; buf_len--; - nm_utils_strbuf_append_str(&buf, &buf_len, str); + nm_strbuf_append_str(&buf, &buf_len, str); /* if the string was too long we indicate truncation with a * '^' instead of a closing quote. */ @@ -762,7 +845,7 @@ out: /*****************************************************************************/ -char _nm_utils_to_string_buffer[]; +_nm_thread_local char _nm_utils_to_string_buffer[] = {0}; void nm_utils_to_string_buffer_init(char **buf, gsize *len) @@ -818,7 +901,7 @@ nm_utils_flags2str(const NMUtilsFlags2StrDesc *descs, if (!flags) { for (i = 0; i < n_descs; i++) { if (!descs[i].flag) { - nm_utils_strbuf_append_str(&p, &len, descs[i].name); + nm_strbuf_append_str(&p, &len, descs[i].name); break; } } @@ -830,14 +913,14 @@ nm_utils_flags2str(const NMUtilsFlags2StrDesc *descs, flags &= ~descs[i].flag; if (buf[0] != '\0') - nm_utils_strbuf_append_c(&p, &len, ','); - nm_utils_strbuf_append_str(&p, &len, descs[i].name); + nm_strbuf_append_c(&p, &len, ','); + nm_strbuf_append_str(&p, &len, descs[i].name); } } if (flags) { if (buf[0] != '\0') - nm_utils_strbuf_append_c(&p, &len, ','); - nm_utils_strbuf_append(&p, &len, "0x%x", flags); + nm_strbuf_append_c(&p, &len, ','); + nm_strbuf_append(&p, &len, "0x%x", flags); } return buf; }; @@ -1733,7 +1816,7 @@ _char_lookup_has_all(const CharLookupTable *lookup, const char *candidates) } /** - * nm_utils_strsplit_set_full: + * nm_strsplit_set_full: * @str: the string to split. * @delimiters: the set of delimiters. * @flags: additional flags for controlling the operation. @@ -1747,7 +1830,7 @@ _char_lookup_has_all(const CharLookupTable *lookup, const char *candidates) * This never returns an empty array. * * Returns: %NULL if @str is %NULL or "". - * If @str only contains delimiters and %NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY + * If @str only contains delimiters and %NM_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY * is not set, it also returns %NULL. * Otherwise, a %NULL terminated strv array containing the split words. * (delimiter characters are removed). @@ -1758,7 +1841,7 @@ _char_lookup_has_all(const CharLookupTable *lookup, const char *candidates) * like "g_strstrip((char *) iter[0])". */ const char ** -nm_utils_strsplit_set_full(const char *str, const char *delimiters, NMUtilsStrsplitSetFlags flags) +nm_strsplit_set_full(const char *str, const char *delimiters, NMUtilsStrsplitSetFlags flags) { const char ** ptr; gsize num_tokens; @@ -1767,12 +1850,11 @@ nm_utils_strsplit_set_full(const char *str, const char *delimiters, NMUtilsStrsp const char * c_str; char * s; CharLookupTable ch_lookup; - const gboolean f_escaped = NM_FLAGS_HAS(flags, NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED); + const gboolean f_escaped = NM_FLAGS_HAS(flags, NM_STRSPLIT_SET_FLAGS_ESCAPED); const gboolean f_allow_escaping = - f_escaped || NM_FLAGS_HAS(flags, NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING); - const gboolean f_preserve_empty = - NM_FLAGS_HAS(flags, NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY); - const gboolean f_strstrip = NM_FLAGS_HAS(flags, NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP); + f_escaped || NM_FLAGS_HAS(flags, NM_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING); + const gboolean f_preserve_empty = NM_FLAGS_HAS(flags, NM_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY); + const gboolean f_strstrip = NM_FLAGS_HAS(flags, NM_STRSPLIT_SET_FLAGS_STRSTRIP); if (!str) return NULL; @@ -1791,8 +1873,8 @@ nm_utils_strsplit_set_full(const char *str, const char *delimiters, NMUtilsStrsp } if (!str[0]) { - /* We return %NULL here, also with NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY. - * That makes nm_utils_strsplit_set_full() with NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY + /* We return %NULL here, also with NM_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY. + * That makes nm_strsplit_set_full() with NM_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY * different from g_strsplit_set(), which would in this case return an empty array. * If you need to handle %NULL, and "" specially, then check the input string first. */ return NULL; @@ -2175,7 +2257,7 @@ nm_utils_escaped_tokens_options_split(char *str, const char **out_key, const cha * with the flags "EXTRACT_UNQUOTE | EXTRACT_RELAX". This is what * systemd uses to parse /proc/cmdline, and we do too. * - * Splits the string. We have nm_utils_strsplit_set() which + * Splits the string. We have nm_strsplit_set() which * supports a variety of flags. However, extending that already * complex code to also support quotation and escaping is hard. * Instead, add a naive implementation. @@ -2262,7 +2344,7 @@ nm_utils_strsplit_quoted(const char *str) /*****************************************************************************/ /** - * nm_utils_strv_find_first: + * _nm_strv_find_first: * @list: the strv list to search * @len: the length of the list, or a negative value if @list is %NULL terminated. * @needle: the value to search for. The search is done using strcmp(). @@ -2275,7 +2357,7 @@ nm_utils_strsplit_quoted(const char *str) * Returns: index of first occurrence or -1 if @needle is not found in @list. */ gssize -nm_utils_strv_find_first(char **list, gssize len, const char *needle) +_nm_strv_find_first(const char *const *list, gssize len, const char *needle) { gssize i; @@ -2337,13 +2419,80 @@ nm_strv_has_duplicate(const char *const *strv, gssize len, gboolean is_sorted) return FALSE; } +gboolean +nm_strv_is_same_unordered(const char *const *strv1, + gssize len1, + const char *const *strv2, + gssize len2) +{ + gs_free const char **ss1_free = NULL; + gs_free const char **ss2_free = NULL; + gsize l2; + gsize l; + gsize i; + + if (len1 < 0) + l = NM_PTRARRAY_LEN(strv1); + else + l = (gsize) len1; + + if (len2 < 0) + l2 = NM_PTRARRAY_LEN(strv2); + else + l2 = (gsize) len2; + + if (l != l2) + return FALSE; + + if (l == 0) { + /* An empty array. We treat (NULL, -1), (NULL, 0) and ([...], 0) + * all the same. */ + return TRUE; + } + + if (l > 1) { + strv1 = nm_memdup_maybe_a(300, strv1, sizeof(char *) * l, &ss1_free); + strv2 = nm_memdup_maybe_a(300, strv2, sizeof(char *) * l2, &ss2_free); + _nm_strv_sort((const char **) strv1, l); + _nm_strv_sort((const char **) strv2, l); + } + + for (i = 0; i < l; i++) { + if (!nm_streq0(strv1[i], strv2[i])) + return FALSE; + } + + return TRUE; +} + +const char ** +nm_strv_cleanup_const(const char **strv, gboolean skip_empty, gboolean skip_repeated) +{ + gsize i; + gsize j; + + if (!strv || !*strv) + return strv; + + if (!skip_empty && !skip_repeated) + return strv; + + j = 0; + for (i = 0; strv[i]; i++) { + if ((skip_empty && !*strv[i]) + || (skip_repeated && nm_strv_find_first(strv, j, strv[i]) >= 0)) + continue; + strv[j++] = strv[i]; + } + strv[j] = NULL; + return strv; +} + char ** -_nm_utils_strv_cleanup(char ** strv, - gboolean strip_whitespace, - gboolean skip_empty, - gboolean skip_repeated) +nm_strv_cleanup(char **strv, gboolean strip_whitespace, gboolean skip_empty, gboolean skip_repeated) { - guint i, j; + gsize i; + gsize j; if (!strv || !*strv) return strv; @@ -2359,7 +2508,7 @@ _nm_utils_strv_cleanup(char ** strv, j = 0; for (i = 0; strv[i]; i++) { if ((skip_empty && !*strv[i]) - || (skip_repeated && nm_utils_strv_find_first(strv, j, strv[i]) >= 0)) + || (skip_repeated && nm_strv_find_first(strv, j, strv[i]) >= 0)) g_free(strv[i]); else strv[j++] = strv[i]; @@ -3762,7 +3911,7 @@ nm_utils_hashtable_cmp(const GHashTable *a, } char ** -nm_utils_strv_make_deep_copied(const char **strv) +nm_strv_make_deep_copied(const char **strv) { gsize i; @@ -3779,7 +3928,7 @@ nm_utils_strv_make_deep_copied(const char **strv) } char ** -nm_utils_strv_make_deep_copied_n(const char **strv, gsize len) +nm_strv_make_deep_copied_n(const char **strv, gsize len) { gsize i; @@ -3822,7 +3971,7 @@ nm_utils_strv_make_deep_copied_n(const char **strv, gsize len) * cloned or not. */ char ** -_nm_utils_strv_dup(const char *const *strv, gssize len, gboolean deep_copied) +_nm_strv_dup(const char *const *strv, gssize len, gboolean deep_copied) { gsize i, l; char **v; @@ -3858,7 +4007,7 @@ _nm_utils_strv_dup(const char *const *strv, gssize len, gboolean deep_copied) } const char ** -_nm_utils_strv_dup_packed(const char *const *strv, gssize len) +_nm_strv_dup_packed(const char *const *strv, gssize len) { gs_free gsize *str_len_free = NULL; @@ -4219,7 +4368,7 @@ nm_utils_get_start_time_for_pid(pid_t pid, char *out_state, pid_t *out_ppid) state = p[0]; - tokens = nm_utils_strsplit_set(p, " "); + tokens = nm_strsplit_set(p, " "); if (NM_PTRARRAY_LEN(tokens) < 20) goto fail; @@ -4247,7 +4396,7 @@ fail: /*****************************************************************************/ /** - * _nm_utils_strv_sort: + * _nm_strv_sort: * @strv: pointer containing strings that will be sorted * in-place, %NULL is allowed, unless @len indicates * that there are more elements. @@ -4261,7 +4410,7 @@ fail: * comparison. */ void -_nm_utils_strv_sort(const char **strv, gssize len) +_nm_strv_sort(const char **strv, gssize len) { GCompareDataFunc cmp; gsize l; @@ -4283,7 +4432,7 @@ _nm_utils_strv_sort(const char **strv, gssize len) } /** - * _nm_utils_strv_cmp_n: + * _nm_strv_cmp_n: * @strv1: a string array * @len1: the length of @strv1, or -1 for NULL terminated array. * @strv2: a string array @@ -4306,7 +4455,7 @@ _nm_utils_strv_sort(const char **strv, gssize len) * Returns: 0 if the arrays are equal (using strcmp). **/ int -_nm_utils_strv_cmp_n(const char *const *strv1, gssize len1, const char *const *strv2, gssize len2) +_nm_strv_cmp_n(const char *const *strv1, gssize len1, const char *const *strv2, gssize len2) { gsize n, n2; @@ -5015,12 +5164,12 @@ nm_g_unix_signal_source_new(int signum, } GSource * -nm_g_unix_fd_source_new(int fd, - GIOCondition io_condition, - int priority, - gboolean (*source_func)(int fd, GIOCondition condition, gpointer user_data), - gpointer user_data, - GDestroyNotify destroy_notify) +nm_g_unix_fd_source_new(int fd, + GIOCondition io_condition, + int priority, + GUnixFDSourceFunc source_func, + gpointer user_data, + GDestroyNotify destroy_notify) { GSource *source; @@ -5032,6 +5181,23 @@ nm_g_unix_fd_source_new(int fd, return source; } +GSource * +nm_g_child_watch_source_new(GPid pid, + int priority, + GChildWatchFunc handler, + gpointer user_data, + GDestroyNotify notify) +{ + GSource *source; + + source = g_child_watch_source_new(pid); + + if (priority != G_PRIORITY_DEFAULT) + g_source_set_priority(source, priority); + g_source_set_callback(source, G_SOURCE_FUNC(handler), user_data, notify); + return source; +} + /*****************************************************************************/ #define _CTX_LOG(fmt, ...) \ @@ -6363,6 +6529,35 @@ nm_utils_get_process_exit_status_desc(int status) /*****************************************************************************/ +gboolean +nm_utils_validate_hostname(const char *hostname) +{ + const char *p; + gboolean dot = TRUE; + + if (!hostname || !hostname[0]) + return FALSE; + + for (p = hostname; *p; p++) { + if (*p == '.') { + if (dot) + return FALSE; + dot = TRUE; + } else { + if (!g_ascii_isalnum(*p) && (*p != '-') && (*p != '_')) + return FALSE; + dot = FALSE; + } + } + + if (dot) + return FALSE; + + return (p - hostname <= HOST_NAME_MAX); +} + +/*****************************************************************************/ + typedef struct { CList lst; gpointer tls_data; @@ -6437,3 +6632,33 @@ nm_utils_thread_local_register_destroy(gpointer tls_data, GDestroyNotify destroy entry->destroy_notify = destroy_notify; c_list_link_tail(lst_head, &entry->lst); } + +/*****************************************************************************/ + +static gboolean +_iterate_for_msec_timeout(gpointer user_data) +{ + GSource **p_source = user_data; + + nm_clear_g_source_inst(p_source); + return G_SOURCE_CONTINUE; +} + +void +nm_g_main_context_iterate_for_msec(GMainContext *context, guint timeout_msec) +{ + GSource *source; + + /* In production is this function not very useful. It is however useful to + * have in the toolbox for printf debugging. */ + + source = g_timeout_source_new(timeout_msec); + g_source_set_callback(source, _iterate_for_msec_timeout, &source, NULL); + + if (!context) + context = g_main_context_default(); + + g_source_attach(source, context); + while (source) + g_main_context_iteration(context, TRUE); +} diff --git a/src/libnm-glib-aux/nm-shared-utils.h b/src/libnm-glib-aux/nm-shared-utils.h index dcf37cd3..8dd53dcf 100644 --- a/src/libnm-glib-aux/nm-shared-utils.h +++ b/src/libnm-glib-aux/nm-shared-utils.h @@ -18,6 +18,7 @@ typedef enum _nm_packed { NM_OPTION_BOOL_TRUE = 1, } NMOptionBool; +#define nm_assert_is_bool(value) nm_assert(NM_IN_SET((value), 0, 1)) #define nm_assert_is_ternary(value) nm_assert(NM_IN_SET((value), -1, 0, 1)) /*****************************************************************************/ @@ -35,19 +36,19 @@ pid_t nm_utils_gettid(void); gboolean _nm_assert_on_main_thread(void); #if NM_MORE_ASSERTS > 5 - #define NM_ASSERT_ON_MAIN_THREAD() \ - G_STMT_START \ - { \ - nm_assert(_nm_assert_on_main_thread()); \ - } \ - G_STMT_END +#define NM_ASSERT_ON_MAIN_THREAD() \ + G_STMT_START \ + { \ + nm_assert(_nm_assert_on_main_thread()); \ + } \ + G_STMT_END #else - #define NM_ASSERT_ON_MAIN_THREAD() \ - G_STMT_START \ - { \ - ; \ - } \ - G_STMT_END +#define NM_ASSERT_ON_MAIN_THREAD() \ + G_STMT_START \ + { \ + ; \ + } \ + G_STMT_END #endif /*****************************************************************************/ @@ -79,20 +80,20 @@ _NM_INT_NOT_NEGATIVE(gssize val) * Together with the G_STATIC_ASSERT(), we make sure that this is always satisfied. */ G_STATIC_ASSERT(sizeof(int) == sizeof(gint32)); #if _NM_CC_SUPPORT_GENERIC - #define _NM_INT_LE_MAXINT32(value) \ - ({ \ - _nm_unused typeof(value) _value = (value); \ - \ - _Generic((value), int : TRUE); \ - }) +#define _NM_INT_LE_MAXINT32(value) \ + ({ \ + _nm_unused typeof(value) _value = (value); \ + \ + _Generic((value), int : TRUE); \ + }) #else - #define _NM_INT_LE_MAXINT32(value) \ - ({ \ - _nm_unused typeof(value) _value = (value); \ - _nm_unused const int * _p_value = &_value; \ - \ - TRUE; \ - }) +#define _NM_INT_LE_MAXINT32(value) \ + ({ \ + _nm_unused typeof(value) _value = (value); \ + _nm_unused const int * _p_value = &_value; \ + \ + TRUE; \ + }) #endif /*****************************************************************************/ @@ -247,7 +248,6 @@ extern const NMIPAddr nm_ip_addr_zero; static inline int nm_ip_addr_cmp(int addr_family, gconstpointer a, gconstpointer b) { - nm_assert_addr_family(addr_family); nm_assert(a); nm_assert(b); @@ -264,20 +264,27 @@ static inline gboolean nm_ip_addr_is_null(int addr_family, gconstpointer addr) { nm_assert(addr); - if (addr_family == AF_INET6) - return IN6_IS_ADDR_UNSPECIFIED((const struct in6_addr *) addr); - nm_assert(addr_family == AF_INET); - return ((const struct in_addr *) addr)->s_addr == 0; + + if (NM_IS_IPv4(addr_family)) { + in_addr_t t; + + /* also for in_addr_t type (AF_INET), we accept that the pointer might + * be unaligned. */ + memcpy(&t, addr, sizeof(t)); + return t == 0; + } + + return IN6_IS_ADDR_UNSPECIFIED((const struct in6_addr *) addr); } static inline void nm_ip_addr_set(int addr_family, gpointer dst, gconstpointer src) { - nm_assert_addr_family(addr_family); nm_assert(dst); nm_assert(src); - memcpy(dst, src, NM_IS_IPv4(addr_family) ? sizeof(in_addr_t) : sizeof(struct in6_addr)); + /* this MUST use memcpy() (or similar means) to support unaligned src/dst pointers. */ + memcpy(dst, src, nm_utils_addr_family_to_size(addr_family)); } static inline NMIPAddr @@ -308,6 +315,9 @@ gboolean nm_ip_addr_set_from_untrusted(int addr_family, gsize src_len, int * out_addr_family); +gboolean +nm_ip_addr_set_from_variant(int addr_family, gpointer dst, GVariant *variant, int *out_addr_family); + static inline gboolean nm_ip4_addr_is_localhost(in_addr_t addr4) { @@ -365,8 +375,8 @@ typedef struct _NMUtilsIPv6IfaceId { } \ } -void nm_utils_ipv6_addr_set_interface_identifier(struct in6_addr * addr, - const NMUtilsIPv6IfaceId iid); +void nm_utils_ipv6_addr_set_interface_identifier(struct in6_addr * addr, + const NMUtilsIPv6IfaceId *iid); void nm_utils_ipv6_interface_identifier_get_from_addr(NMUtilsIPv6IfaceId * iid, const struct in6_addr *addr); @@ -374,7 +384,7 @@ void nm_utils_ipv6_interface_identifier_get_from_addr(NMUtilsIPv6IfaceId * iid gboolean nm_utils_ipv6_interface_identifier_get_from_token(NMUtilsIPv6IfaceId *iid, const char * token); -const char *nm_utils_inet6_interface_identifier_to_token(NMUtilsIPv6IfaceId iid, +const char *nm_utils_inet6_interface_identifier_to_token(const NMUtilsIPv6IfaceId *iid, char buf[static INET6_ADDRSTRLEN]); gboolean nm_utils_get_ipv6_interface_identifier(NMLinkType link_type, @@ -559,25 +569,25 @@ extern const void *const _NM_PTRARRAY_EMPTY[1]; #define NM_STRV_EMPTY_CC() NM_PTRARRAY_EMPTY(const char *) static inline void -_nm_utils_strbuf_init(char *buf, gsize len, char **p_buf_ptr, gsize *p_buf_len) +nm_strbuf_init(char *buf, gsize len, char **p_buf_ptr, gsize *p_buf_len) { NM_SET_OUT(p_buf_len, len); NM_SET_OUT(p_buf_ptr, buf); buf[0] = '\0'; } -#define nm_utils_strbuf_init(buf, p_buf_ptr, p_buf_len) \ +#define nm_strbuf_init_arr(buf, p_buf_ptr, p_buf_len) \ G_STMT_START \ { \ G_STATIC_ASSERT(G_N_ELEMENTS(buf) == sizeof(buf) && sizeof(buf) > sizeof(char *)); \ - _nm_utils_strbuf_init((buf), sizeof(buf), (p_buf_ptr), (p_buf_len)); \ + nm_strbuf_init((buf), sizeof(buf), (p_buf_ptr), (p_buf_len)); \ } \ G_STMT_END -void nm_utils_strbuf_append(char **buf, gsize *len, const char *format, ...) _nm_printf(3, 4); -void nm_utils_strbuf_append_c(char **buf, gsize *len, char c); -void nm_utils_strbuf_append_str(char **buf, gsize *len, const char *str); -void nm_utils_strbuf_append_bin(char **buf, gsize *len, gconstpointer str, gsize str_len); -void nm_utils_strbuf_seek_end(char **buf, gsize *len); +void nm_strbuf_append(char **buf, gsize *len, const char *format, ...) _nm_printf(3, 4); +void nm_strbuf_append_c(char **buf, gsize *len, char c); +void nm_strbuf_append_str(char **buf, gsize *len, const char *str); +void nm_strbuf_append_bin(char **buf, gsize *len, gconstpointer str, gsize str_len); +void nm_strbuf_seek_end(char **buf, gsize *len); const char *nm_strquote(char *buf, gsize buf_len, const char *str); @@ -589,24 +599,25 @@ nm_utils_is_separator(const char c) /*****************************************************************************/ -GBytes *nm_gbytes_get_empty(void); +GBytes *nm_g_bytes_get_empty(void); GBytes *nm_g_bytes_new_from_str(const char *str); +GBytes *nm_g_bytes_new_from_variant_ay(GVariant *var); static inline gboolean -nm_gbytes_equal0(GBytes *a, GBytes *b) +nm_g_bytes_equal0(const GBytes *a, const GBytes *b) { return a == b || (a && b && g_bytes_equal(a, b)); } -gboolean nm_utils_gbytes_equal_mem(GBytes *bytes, gconstpointer mem_data, gsize mem_len); +gboolean nm_g_bytes_equal_mem(GBytes *bytes, gconstpointer mem_data, gsize mem_len); -GVariant *nm_utils_gbytes_to_variant_ay(GBytes *bytes); +GVariant *nm_g_bytes_to_variant_ay(const GBytes *bytes); -GHashTable *nm_utils_strdict_clone(GHashTable *src); +GHashTable *nm_strdict_clone(GHashTable *src); -GVariant *nm_utils_strdict_to_variant_ass(GHashTable *strdict); -GVariant *nm_utils_strdict_to_variant_asv(GHashTable *strdict); +GVariant *nm_strdict_to_variant_ass(GHashTable *strdict); +GVariant *nm_strdict_to_variant_asv(GHashTable *strdict); /*****************************************************************************/ @@ -650,95 +661,105 @@ int nm_utils_dbus_path_cmp(const char *dbus_path_a, const char *dbus_path_b); /*****************************************************************************/ typedef enum { - NM_UTILS_STRSPLIT_SET_FLAGS_NONE = 0, + NM_STRSPLIT_SET_FLAGS_NONE = 0, /* by default, strsplit will coalesce consecutive delimiters and remove * them from the result. If this flag is present, empty values are preserved * and returned. * - * When combined with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, if a value gets + * When combined with %NM_STRSPLIT_SET_FLAGS_STRSTRIP, if a value gets * empty after strstrip(), it also gets removed. */ - NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY = (1u << 0), + NM_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY = (1u << 0), - /* %NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING means that delimiters prefixed + /* %NM_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING means that delimiters prefixed * by a backslash are not treated as a separator. Such delimiters and their escape * character are copied to the current word without unescaping them. In general, - * nm_utils_strsplit_set_full() does not remove any backslash escape characters + * nm_strsplit_set_full() does not remove any backslash escape characters * and does no unescaping. It only considers them for skipping to split at * an escaped delimiter. * - * If this is combined with (or implied by %NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED), then + * If this is combined with (or implied by %NM_STRSPLIT_SET_FLAGS_ESCAPED), then * the backslash escapes are removed from the result. */ - NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING = (1u << 1), + NM_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING = (1u << 1), /* If flag is set, does the same as g_strstrip() on the returned tokens. * This will remove leading and trailing ascii whitespaces (g_ascii_isspace() * and NM_ASCII_SPACES). * - * - when combined with !%NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, + * - when combined with !%NM_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY, * empty tokens will be removed (and %NULL will be returned if that * results in an empty string array). - * - when combined with %NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING, + * - when combined with %NM_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING, * trailing whitespace escaped by backslash are not stripped. */ - NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP = (1u << 2), + NM_STRSPLIT_SET_FLAGS_STRSTRIP = (1u << 2), - /* This implies %NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING. + /* This implies %NM_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING. * * This will do a final run over all tokens and remove all backslash * escape characters that * - precede a delimiter. * - precede a backslash. - * - precede a whitespace (only with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP). + * - precede a whitespace (only with %NM_STRSPLIT_SET_FLAGS_STRSTRIP). * - * Note that with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP, it is only + * Note that with %NM_STRSPLIT_SET_FLAGS_STRSTRIP, it is only * necessary to escape the very last whitespace (if the delimiters * are not whitespace themself). So, technically, it would be sufficient * to only unescape a backslash before the last whitespace and the user * still could express everything. However, such a rule would be complicated - * to understand, so when using backslash escaping with nm_utils_strsplit_set_full(), + * to understand, so when using backslash escaping with nm_strsplit_set_full(), * then all characters (including backslash) are treated verbatim, except: * * - "\\$DELIMITER" (escaped delimiter) * - "\\\\" (escaped backslash) - * - "\\$SPACE" (escaped space) (only with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP). + * - "\\$SPACE" (escaped space) (only with %NM_STRSPLIT_SET_FLAGS_STRSTRIP). * * Note that all other escapes like "\\n" or "\\001" are left alone. * That makes the escaping/unescaping rules simple. Also, for the most part * a text is just taken as-is, with little additional rules. Only backslashes * need extra care, and then only if they proceed one of the relevant characters. */ - NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED = (1u << 3), + NM_STRSPLIT_SET_FLAGS_ESCAPED = (1u << 3), } NMUtilsStrsplitSetFlags; const char ** -nm_utils_strsplit_set_full(const char *str, const char *delimiter, NMUtilsStrsplitSetFlags flags); +nm_strsplit_set_full(const char *str, const char *delimiter, NMUtilsStrsplitSetFlags flags); static inline const char ** -nm_utils_strsplit_set_with_empty(const char *str, const char *delimiters) +nm_strsplit_set_with_empty(const char *str, const char *delimiters) { /* this returns the same result as g_strsplit_set(str, delimiters, -1), except * it does not deep-clone the strv array. * Also, for @str == "", this returns %NULL while g_strsplit_set() would return * an empty strv array. */ - return nm_utils_strsplit_set_full(str, delimiters, NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY); + return nm_strsplit_set_full(str, delimiters, NM_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY); } static inline const char ** -nm_utils_strsplit_set(const char *str, const char *delimiters) +nm_strsplit_set(const char *str, const char *delimiters) { - return nm_utils_strsplit_set_full(str, delimiters, NM_UTILS_STRSPLIT_SET_FLAGS_NONE); + return nm_strsplit_set_full(str, delimiters, NM_STRSPLIT_SET_FLAGS_NONE); } -gssize nm_utils_strv_find_first(char **list, gssize len, const char *needle); +gssize _nm_strv_find_first(const char *const *list, gssize len, const char *needle); + +#define nm_strv_find_first(list, len, needle) \ + _nm_strv_find_first(NM_CAST_STRV_CC(list), (len), (needle)) gboolean nm_strv_has_duplicate(const char *const *list, gssize len, gboolean is_sorted); -char **_nm_utils_strv_cleanup(char ** strv, - gboolean strip_whitespace, - gboolean skip_empty, - gboolean skip_repeated); +const char **nm_strv_cleanup_const(const char **strv, gboolean skip_empty, gboolean skip_repeated); + +char **nm_strv_cleanup(char ** strv, + gboolean strip_whitespace, + gboolean skip_empty, + gboolean skip_repeated); + +gboolean nm_strv_is_same_unordered(const char *const *strv1, + gssize len1, + const char *const *strv2, + gssize len2); /*****************************************************************************/ @@ -753,10 +774,9 @@ nm_copy_func_g_strdup(gconstpointer arg, gpointer user_data) static inline const char ** nm_utils_escaped_tokens_split(const char *str, const char *delimiters) { - return nm_utils_strsplit_set_full(str, - delimiters, - NM_UTILS_STRSPLIT_SET_FLAGS_ESCAPED - | NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP); + return nm_strsplit_set_full(str, + delimiters, + NM_STRSPLIT_SET_FLAGS_ESCAPED | NM_STRSPLIT_SET_FLAGS_STRSTRIP); } typedef enum { @@ -879,10 +899,10 @@ char **nm_utils_strsplit_quoted(const char *str); static inline const char ** nm_utils_escaped_tokens_options_split_list(const char *str) { - return nm_utils_strsplit_set_full(str, - ",", - NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP - | NM_UTILS_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING); + return nm_strsplit_set_full(str, + ",", + NM_STRSPLIT_SET_FLAGS_STRSTRIP + | NM_STRSPLIT_SET_FLAGS_ALLOW_ESCAPING); } void nm_utils_escaped_tokens_options_split(char *str, const char **out_key, const char **out_val); @@ -1033,7 +1053,7 @@ int _nm_utils_ascii_str_to_bool(const char *str, int default_value); /*****************************************************************************/ -extern char _nm_utils_to_string_buffer[2096]; +extern _nm_thread_local char _nm_utils_to_string_buffer[2096]; void nm_utils_to_string_buffer_init(char **buf, gsize *len); gboolean nm_utils_to_string_buffer_init_null(gconstpointer obj, char **buf, gsize *len); @@ -1069,16 +1089,12 @@ const char *nm_utils_flags2str(const NMUtilsFlags2StrDesc *descs, /*****************************************************************************/ #define NM_UTILS_ENUM2STR(v, n) \ - (void) 0; \ -case v: \ - s = "" n ""; \ - break; \ - (void) 0 + case v: \ + s = "" n ""; \ + break; #define NM_UTILS_ENUM2STR_IGNORE(v) \ - (void) 0; \ -case v: \ - break; \ - (void) 0 + case v: \ + break; #define NM_UTILS_ENUM2STR_DEFINE_FULL(fcn_name, lookup_type, int_fmt, ...) \ const char *fcn_name(lookup_type val, char *buf, gsize len) \ @@ -1087,7 +1103,7 @@ case v: \ if (len) { \ const char *s = NULL; \ switch (val) { \ - (void) 0, __VA_ARGS__(void) 0; \ + NM_VA_ARGS_JOIN(, __VA_ARGS__) \ }; \ if (s) \ g_strlcpy(buf, s, len); \ @@ -1107,14 +1123,26 @@ case v: \ static inline void _nm_g_slice_free_fcn_##mem_size(gpointer mem_block) \ { \ g_slice_free1(mem_size, mem_block); \ - } + } \ + _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON -_nm_g_slice_free_fcn_define(1) _nm_g_slice_free_fcn_define(2) _nm_g_slice_free_fcn_define(4) - _nm_g_slice_free_fcn_define(8) _nm_g_slice_free_fcn_define(10) _nm_g_slice_free_fcn_define(12) - _nm_g_slice_free_fcn_define(16) _nm_g_slice_free_fcn_define(32) +_nm_g_slice_free_fcn_define(1); +_nm_g_slice_free_fcn_define(2); +_nm_g_slice_free_fcn_define(4); +_nm_g_slice_free_fcn_define(8); +_nm_g_slice_free_fcn_define(10); +_nm_g_slice_free_fcn_define(12); +_nm_g_slice_free_fcn_define(16); +_nm_g_slice_free_fcn_define(32); + +_nm_warn_unused_result static inline GDestroyNotify +_nm_get_warn_unused_result_gdestroynotify(GDestroyNotify f) +{ + return f; +} #define nm_g_slice_free_fcn1(mem_size) \ - ({ \ + _nm_get_warn_unused_result_gdestroynotify(({ \ void (*_fcn)(gpointer); \ \ /* If mem_size is a compile time constant, the compiler @@ -1153,8 +1181,9 @@ _nm_g_slice_free_fcn_define(1) _nm_g_slice_free_fcn_define(2) _nm_g_slice_free_f _fcn = NULL; \ break; \ } \ + \ _fcn; \ - }) + })) /** * nm_g_slice_free_fcn: @@ -1185,7 +1214,8 @@ _nm_g_slice_free_fcn_define(1) _nm_g_slice_free_fcn_define(2) _nm_g_slice_free_f _error && _error->domain == (err_domain) && NM_IN_SET(_error->code, __VA_ARGS__); \ }) - static inline void nm_g_set_error_take(GError **error, GError *error_take) +static inline void +nm_g_set_error_take(GError **error, GError *error_take) { if (!error_take) g_return_if_reached(); @@ -1420,21 +1450,41 @@ GParamSpec *nm_g_object_class_find_property_from_gtype(GType gtype, const char * ((const _c_type *) _param_spec); \ }) +#define _NM_G_PARAM_SPEC_CAST_IS_A(param_spec, _value_type, _c_type) \ + ({ \ + const GParamSpec *const _param_spec = (param_spec); \ + \ + nm_assert(!_param_spec || g_type_is_a(_param_spec->value_type, _value_type)); \ + ((const _c_type *) _param_spec); \ + }) + #define NM_G_PARAM_SPEC_CAST_BOOLEAN(param_spec) \ _NM_G_PARAM_SPEC_CAST(param_spec, G_TYPE_BOOLEAN, GParamSpecBoolean) +#define NM_G_PARAM_SPEC_CAST_INT(param_spec) \ + _NM_G_PARAM_SPEC_CAST(param_spec, G_TYPE_INT, GParamSpecInt) #define NM_G_PARAM_SPEC_CAST_UINT(param_spec) \ _NM_G_PARAM_SPEC_CAST(param_spec, G_TYPE_UINT, GParamSpecUInt) #define NM_G_PARAM_SPEC_CAST_UINT64(param_spec) \ _NM_G_PARAM_SPEC_CAST(param_spec, G_TYPE_UINT64, GParamSpecUInt64) +#define NM_G_PARAM_SPEC_CAST_ENUM(param_spec) \ + _NM_G_PARAM_SPEC_CAST_IS_A(param_spec, G_TYPE_ENUM, GParamSpecEnum) +#define NM_G_PARAM_SPEC_CAST_FLAGS(param_spec) \ + _NM_G_PARAM_SPEC_CAST_IS_A(param_spec, G_TYPE_FLAGS, GParamSpecFlags) #define NM_G_PARAM_SPEC_CAST_STRING(param_spec) \ _NM_G_PARAM_SPEC_CAST(param_spec, G_TYPE_STRING, GParamSpecString) #define NM_G_PARAM_SPEC_GET_DEFAULT_BOOLEAN(param_spec) \ (NM_G_PARAM_SPEC_CAST_BOOLEAN(NM_ENSURE_NOT_NULL(param_spec))->default_value) +#define NM_G_PARAM_SPEC_GET_DEFAULT_INT(param_spec) \ + (NM_G_PARAM_SPEC_CAST_INT(NM_ENSURE_NOT_NULL(param_spec))->default_value) #define NM_G_PARAM_SPEC_GET_DEFAULT_UINT(param_spec) \ (NM_G_PARAM_SPEC_CAST_UINT(NM_ENSURE_NOT_NULL(param_spec))->default_value) #define NM_G_PARAM_SPEC_GET_DEFAULT_UINT64(param_spec) \ (NM_G_PARAM_SPEC_CAST_UINT64(NM_ENSURE_NOT_NULL(param_spec))->default_value) +#define NM_G_PARAM_SPEC_GET_DEFAULT_ENUM(param_spec) \ + (NM_G_PARAM_SPEC_CAST_ENUM(NM_ENSURE_NOT_NULL(param_spec))->default_value) +#define NM_G_PARAM_SPEC_GET_DEFAULT_FLAGS(param_spec) \ + (NM_G_PARAM_SPEC_CAST_FLAGS(NM_ENSURE_NOT_NULL(param_spec))->default_value) #define NM_G_PARAM_SPEC_GET_DEFAULT_STRING(param_spec) \ (NM_G_PARAM_SPEC_CAST_STRING(NM_ENSURE_NOT_NULL(param_spec))->default_value) @@ -1498,10 +1548,17 @@ char *nm_utils_str_utf8safe_escape_take(char *str, NMUtilsStrUtf8SafeFlags flags GVariant *nm_g_variant_singleton_b(gboolean value); GVariant *nm_g_variant_singleton_u_0(void); +GVariant *nm_g_variant_singleton_i_0(void); GVariant *nm_g_variant_singleton_s_empty(void); +GVariant *nm_g_variant_singleton_au(void); +GVariant *nm_g_variant_singleton_aay(void); +GVariant *nm_g_variant_singleton_as(void); GVariant *nm_g_variant_singleton_aLsvI(void); GVariant *nm_g_variant_singleton_aLsaLsvII(void); GVariant *nm_g_variant_singleton_aaLsvI(void); +GVariant *nm_g_variant_singleton_ao(void); + +GVariant *nm_g_variant_maybe_singleton_i(gint32 v); static inline void nm_g_variant_unref_floating(GVariant *var) @@ -1599,6 +1656,19 @@ nm_g_variant_builder_add_sv_str(GVariantBuilder *builder, const char *key, const static inline void nm_g_source_destroy_and_unref(GSource *source) { + /* Note that calling g_source_destroy() on a currently attached source, + * will destroy the user-data of the callback right away (and not only + * during the last g_source_unref()). + * + * It also means, that if the user data itself has the reference to the + * source, then this will lead to crash: + * + * g_source_destroy(user_data->my_source); + * // ups, user_data was destroyed (if source was attached). + * g_source_unref(user_data->my_source); + * + * nm_g_source_destroy_and_unref() and nm_clear_g_source_inst() does not + * suffer from this problem. */ g_source_destroy(source); g_source_unref(source); } @@ -1673,19 +1743,25 @@ GSource *nm_g_timeout_source_new_seconds(guint timeout_sec, gpointer user_data, GDestroyNotify destroy_notify); -GSource * - nm_g_unix_fd_source_new(int fd, - GIOCondition io_condition, - int priority, - gboolean (*source_func)(int fd, GIOCondition condition, gpointer user_data), - gpointer user_data, - GDestroyNotify destroy_notify); +GSource *nm_g_unix_fd_source_new(int fd, + GIOCondition io_condition, + int priority, + GUnixFDSourceFunc source_func, + gpointer user_data, + GDestroyNotify destroy_notify); + GSource *nm_g_unix_signal_source_new(int signum, int priority, GSourceFunc handler, gpointer user_data, GDestroyNotify notify); +GSource *nm_g_child_watch_source_new(GPid pid, + int priority, + GChildWatchFunc handler, + gpointer user_data, + GDestroyNotify notify); + static inline GSource * nm_g_source_attach(GSource *source, GMainContext *context) { @@ -1693,10 +1769,25 @@ nm_g_source_attach(GSource *source, GMainContext *context) return source; } +static inline void +nm_g_idle_add(GSourceFunc func, gpointer user_data) +{ + /* g_idle_add() is discouraged because it relies on the guint source IDs. + * + * Usually, you would want to use nm_g_idle_add_source() which returns a GSource* + * instance. + * + * However, if you don't care to ever call g_source_remove() on the source ID, then + * g_idle_add() is fine. But our checkpatch script would complain about it. In + * that case use nm_g_idle_add(), which makes it clear that you really want to + * use g_idle_add() and ignore the source ID. */ + g_idle_add(func, user_data); +} + static inline GSource * nm_g_idle_add_source(GSourceFunc func, gpointer user_data) { - /* G convenience function to attach a new timeout source to the default GMainContext. + /* A convenience function to attach a new timeout source to the default GMainContext. * In that sense it's very similar to g_idle_add() except that it returns a * reference to the new source. */ return nm_g_source_attach(nm_g_idle_source_new(G_PRIORITY_DEFAULT, func, user_data, NULL), @@ -1706,7 +1797,7 @@ nm_g_idle_add_source(GSourceFunc func, gpointer user_data) static inline GSource * nm_g_timeout_add_source(guint timeout_msec, GSourceFunc func, gpointer user_data) { - /* G convenience function to attach a new timeout source to the default GMainContext. + /* A convenience function to attach a new timeout source to the default GMainContext. * In that sense it's very similar to g_timeout_add() except that it returns a * reference to the new source. */ return nm_g_source_attach( @@ -1715,9 +1806,9 @@ nm_g_timeout_add_source(guint timeout_msec, GSourceFunc func, gpointer user_data } static inline GSource * -nm_g_timeout_add_source_seconds(guint timeout_sec, GSourceFunc func, gpointer user_data) +nm_g_timeout_add_seconds_source(guint timeout_sec, GSourceFunc func, gpointer user_data) { - /* G convenience function to attach a new timeout source to the default GMainContext. + /* A convenience function to attach a new timeout source to the default GMainContext. * In that sense it's very similar to g_timeout_add_seconds() except that it returns a * reference to the new source. */ return nm_g_source_attach( @@ -1746,6 +1837,36 @@ nm_g_timeout_add_source_approx(guint timeout_msec, return nm_g_source_attach(source, NULL); } +static inline GSource * +nm_g_unix_fd_add_source(int fd, + GIOCondition condition, + GUnixFDSourceFunc function, + gpointer user_data) +{ + /* A convenience function to attach a new unix-fd source to the default GMainContext. + * In that sense it's very similar to g_unix_fd_add() except that it returns a + * reference to the new source. */ + return nm_g_source_attach( + nm_g_unix_fd_source_new(fd, condition, G_PRIORITY_DEFAULT, function, user_data, NULL), + NULL); +} + +static inline GSource * +nm_g_unix_signal_add_source(int signum, GSourceFunc handler, gpointer user_data) +{ + return nm_g_source_attach( + nm_g_unix_signal_source_new(signum, G_PRIORITY_DEFAULT, handler, user_data, NULL), + NULL); +} + +static inline GSource * +nm_g_child_watch_add_source(GPid pid, GChildWatchFunc handler, gpointer user_data) +{ + return nm_g_source_attach( + nm_g_child_watch_source_new(pid, G_PRIORITY_DEFAULT, handler, user_data, NULL), + NULL); +} + NM_AUTO_DEFINE_FCN0(GMainContext *, _nm_auto_unref_gmaincontext, g_main_context_unref); #define nm_auto_unref_gmaincontext nm_auto(_nm_auto_unref_gmaincontext) @@ -1801,6 +1922,16 @@ nm_g_main_context_push_thread_default_if_necessary(GMainContext *context) return context; } +static inline void +nm_g_main_context_iterate_ready(GMainContext *context) +{ + while (g_main_context_iteration(context, FALSE)) { + ; + } +} + +void nm_g_main_context_iterate_for_msec(GMainContext *context, guint timeout_msec); + /*****************************************************************************/ static inline int @@ -1893,7 +2024,7 @@ gpointer *nm_utils_hash_values_to_array(GHashTable * hash, guint * out_len); static inline const char ** -nm_utils_strdict_get_keys(const GHashTable *hash, gboolean sorted, guint *out_length) +nm_strdict_get_keys(const GHashTable *hash, gboolean sorted, guint *out_length) { return (const char **) nm_utils_hash_keys_to_array((GHashTable *) hash, sorted ? nm_strcmp_p_with_data : NULL, @@ -1924,26 +2055,26 @@ int nm_utils_hashtable_cmp(const GHashTable *a, GCompareDataFunc cmp_values, gpointer user_data); -char **nm_utils_strv_make_deep_copied(const char **strv); +char **nm_strv_make_deep_copied(const char **strv); -char **nm_utils_strv_make_deep_copied_n(const char **strv, gsize len); +char **nm_strv_make_deep_copied_n(const char **strv, gsize len); static inline char ** -nm_utils_strv_make_deep_copied_nonnull(const char **strv) +nm_strv_make_deep_copied_nonnull(const char **strv) { - return nm_utils_strv_make_deep_copied(strv) ?: g_new0(char *, 1); + return nm_strv_make_deep_copied(strv) ?: g_new0(char *, 1); } -char **_nm_utils_strv_dup(const char *const *strv, gssize len, gboolean deep_copied); +char **_nm_strv_dup(const char *const *strv, gssize len, gboolean deep_copied); -#define nm_utils_strv_dup(strv, len, deep_copied) \ - _nm_utils_strv_dup(NM_CAST_STRV_CC(strv), (len), (deep_copied)) +#define nm_strv_dup(strv, len, deep_copied) \ + _nm_strv_dup(NM_CAST_STRV_CC(strv), (len), (deep_copied)) -const char **_nm_utils_strv_dup_packed(const char *const *strv, gssize len); +const char **_nm_strv_dup_packed(const char *const *strv, gssize len); -#define nm_utils_strv_dup_packed(strv, len) _nm_utils_strv_dup_packed(NM_CAST_STRV_CC(strv), (len)) +#define nm_strv_dup_packed(strv, len) _nm_strv_dup_packed(NM_CAST_STRV_CC(strv), (len)) -#define nm_utils_strv_dup_shallow_maybe_a(alloca_maxlen, strv, len, to_free) \ +#define nm_strv_dup_shallow_maybe_a(alloca_maxlen, strv, len, to_free) \ ({ \ const char *const *const _strv = NM_CAST_STRV_CC(strv); \ const gssize _len = (len); \ @@ -1994,6 +2125,28 @@ nm_g_array_unref(GArray *arr) g_array_unref(arr); } +#define nm_g_array_first(arr, type) \ + ({ \ + GArray *const _arr = (arr); \ + guint _len; \ + \ + nm_assert(_arr); \ + _len = _arr->len; \ + nm_assert(_len > 0); \ + &g_array_index(arr, type, 0); \ + }) + +#define nm_g_array_last(arr, type) \ + ({ \ + GArray *const _arr = (arr); \ + guint _len; \ + \ + nm_assert(_arr); \ + _len = _arr->len; \ + nm_assert(_len > 0); \ + &g_array_index(arr, type, _len - 1u); \ + }) + #define nm_g_array_append_new(arr, type) \ ({ \ GArray *const _arr = (arr); \ @@ -2091,17 +2244,17 @@ GPtrArray *_nm_g_ptr_array_copy(GPtrArray * array, * Note that the @element_free_func MUST correspond to free function set in @array. */ #if GLIB_CHECK_VERSION(2, 62, 0) - #define nm_g_ptr_array_copy(array, func, user_data, element_free_func) \ - ({ \ - _nm_unused GDestroyNotify const _element_free_func = (element_free_func); \ - \ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS; \ - g_ptr_array_copy((array), (func), (user_data)); \ - G_GNUC_END_IGNORE_DEPRECATIONS; \ - }) +#define nm_g_ptr_array_copy(array, func, user_data, element_free_func) \ + ({ \ + _nm_unused GDestroyNotify const _element_free_func = (element_free_func); \ + \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS; \ + g_ptr_array_copy((array), (func), (user_data)); \ + G_GNUC_END_IGNORE_DEPRECATIONS; \ + }) #else - #define nm_g_ptr_array_copy(array, func, user_data, element_free_func) \ - _nm_g_ptr_array_copy((array), (func), (user_data), (element_free_func)) +#define nm_g_ptr_array_copy(array, func, user_data, element_free_func) \ + _nm_g_ptr_array_copy((array), (func), (user_data), (element_free_func)) #endif /*****************************************************************************/ @@ -2165,7 +2318,7 @@ gssize nm_utils_ptrarray_find_binary_search_range(gconstpointer * list, gssize * out_idx_first, gssize * out_idx_last); -#define nm_utils_strv_find_binary_search(strv, len, needle) \ +#define nm_strv_find_binary_search(strv, len, needle) \ ({ \ const char *const *const _strv = NM_CAST_STRV_CC(strv); \ const gsize _len = (len); \ @@ -2192,16 +2345,89 @@ gssize nm_utils_ptrarray_find_first(gconstpointer *list, gssize len, gconstpoint /*****************************************************************************/ -void _nm_utils_strv_sort(const char **strv, gssize len); -#define nm_utils_strv_sort(strv, len) _nm_utils_strv_sort(NM_CAST_STRV_MC(strv), len) +void _nm_strv_sort(const char **strv, gssize len); +#define nm_strv_sort(strv, len) _nm_strv_sort(NM_CAST_STRV_MC(strv), len) + +int _nm_strv_cmp_n(const char *const *strv1, gssize len1, const char *const *strv2, gssize len2); + +#define nm_strv_cmp_n(strv1, len1, strv2, len2) \ + _nm_strv_cmp_n(NM_CAST_STRV_CC(strv1), (len1), NM_CAST_STRV_CC(strv2), (len2)) + +/* This is like nm_strv_cmp_n(). The difference is that a NULL strv array (strv=NULL,len=-1) + * is treated the same as an empty one (with len=0). */ +#define nm_strv_cmp_n_null(strv1, len1, strv2, len2) \ + ({ \ + const char *const *const _strv1 = NM_CAST_STRV_CC(strv1); \ + const char *const *const _strv2 = NM_CAST_STRV_CC(strv2); \ + const gssize _len1 = (len1); \ + const gssize _len2 = (len2); \ + \ + _nm_strv_cmp_n(_strv1, \ + (_len1 >= 0 ? _len1 : (_strv1 ? -1 : 0)), \ + _strv2, \ + (_len2 >= 0 ? _len2 : (_strv2 ? -1 : 0))); \ + }) + +#define nm_strv_equal_n(strv1, len1, strv2, len2) \ + (nm_strv_cmp_n((strv1), (len1), (strv2), (len2)) == 0) -int -_nm_utils_strv_cmp_n(const char *const *strv1, gssize len1, const char *const *strv2, gssize len2); +#define nm_strv_equal(strv1, strv2) nm_strv_equal_n((strv1), -1, (strv2), -1) -#define nm_utils_strv_cmp_n(strv1, len1, strv2, len2) \ - _nm_utils_strv_cmp_n(NM_CAST_STRV_CC(strv1), (len1), NM_CAST_STRV_CC(strv2), (len2)) +#define nm_strv_equal_n_null(strv1, len1, strv2, len2) \ + (nm_strv_cmp_n_null((strv1), (len1), (strv2), (len2)) == 0) -#define nm_utils_strv_equal(strv1, strv2) (nm_utils_strv_cmp_n((strv1), -1, (strv2), -1) == 0) +/*****************************************************************************/ + +/* nm_arr_insert_at() does @arr[@idx] = @value, but first memmove's + * the elements @arr[@idx..@len-1] one element up. That means, @arr currently + * has @len valid elements, but it must have space for one more element, + * which will be overwritten. + * + * The use case is to have a sorted array (nm_strv_find_binary_search()) and + * to insert the element at he desired index. The caller must make sure that + * @len is large enough to contain one more element. */ +#define nm_arr_insert_at(arr, len, idx, value) \ + G_STMT_START \ + { \ + typeof(*(arr)) *const _arr = (arr); \ + typeof(len) _len = (len); \ + typeof(idx) _idx = (idx); \ + const gsize _len2 = (_len); \ + const gsize _idx2 = (_idx); \ + \ + nm_assert(_arr); \ + nm_assert(_NM_INT_NOT_NEGATIVE(_len)); \ + nm_assert(_NM_INT_NOT_NEGATIVE(_idx)); \ + nm_assert(_idx <= _len); \ + \ + if (_idx2 != _len2) \ + memmove(&_arr[_idx2 + 1u], &_arr[_idx2], sizeof(_arr[0]) * (_len2 - _idx2)); \ + \ + _arr[_idx2] = (value); \ + } \ + G_STMT_END + +/* nm_arr_remove_at() removes the element at arr[idx], by memmove'ing + * the elements from arr[idx+1..len-1] down. All it does is one memmove(), + * if there is anything to move. */ +#define nm_arr_remove_at(arr, len, idx) \ + G_STMT_START \ + { \ + typeof(*(arr)) *const _arr = (arr); \ + typeof(len) _len = (len); \ + typeof(idx) _idx = (idx); \ + const gsize _len2 = (_len); \ + const gsize _idx2 = (_idx); \ + \ + nm_assert(_arr); \ + nm_assert(_len > 0); \ + nm_assert(_NM_INT_NOT_NEGATIVE(_idx)); \ + nm_assert(_idx < _len); \ + \ + if (_idx2 != _len2 - 1u) \ + memmove(&_arr[_idx2], &_arr[_idx2 + 1u], sizeof(_arr[0]) * ((_len2 - 1u) - _idx2)); \ + } \ + G_STMT_END /*****************************************************************************/ @@ -2406,7 +2632,7 @@ nm_strv_ptrarray_find_first(const GPtrArray *strv, const char *str) { if (!strv) return -1; - return nm_utils_strv_find_first((char **) strv->pdata, strv->len, str); + return nm_strv_find_first((const char *const *) strv->pdata, strv->len, str); } static inline gboolean @@ -2418,14 +2644,14 @@ nm_strv_ptrarray_contains(const GPtrArray *strv, const char *str) static inline int nm_strv_ptrarray_cmp(const GPtrArray *a, const GPtrArray *b) { - /* nm_utils_strv_cmp_n() will treat NULL and empty arrays the same. + /* nm_strv_cmp_n() will treat NULL and empty arrays the same. * That means, an empty strv array can both be represented by NULL * and an array of length zero. * If you need to distinguish between these case, do that yourself. */ - return nm_utils_strv_cmp_n((const char *const *) nm_g_ptr_array_pdata(a), - nm_g_ptr_array_len(a), - (const char *const *) nm_g_ptr_array_pdata(b), - nm_g_ptr_array_len(b)); + return nm_strv_cmp_n((const char *const *) nm_g_ptr_array_pdata(a), + nm_g_ptr_array_len(a), + (const char *const *) nm_g_ptr_array_pdata(b), + nm_g_ptr_array_len(b)); } /*****************************************************************************/ @@ -2750,7 +2976,7 @@ guint nm_utils_parse_debug_string(const char *string, const GDebugKey *keys, gui /*****************************************************************************/ static inline gboolean -nm_utils_strdup_reset(char **dst, const char *src) +nm_strdup_reset(char **dst, const char *src) { char *old; @@ -2765,12 +2991,12 @@ nm_utils_strdup_reset(char **dst, const char *src) } static inline gboolean -nm_utils_strdup_reset_take(char **dst, char *src) +nm_strdup_reset_take(char **dst, char *src) { char *old; nm_assert(dst); - nm_assert(src != *dst); + nm_assert(!src || src != *dst); if (nm_streq0(*dst, src)) { if (src) @@ -2854,7 +3080,7 @@ nm_strvarray_get_strv_non_empty_dup(GArray *arr, guint *length) NM_SET_OUT(length, arr->len); strv = &g_array_index(arr, const char *, 0); - return nm_utils_strv_dup(strv, arr->len, TRUE); + return nm_strv_dup(strv, arr->len, TRUE); } static inline const char *const * @@ -2988,6 +3214,8 @@ void nm_crypto_md5_hash(const guint8 *salt, char *nm_utils_get_process_exit_status_desc(int status); +gboolean nm_utils_validate_hostname(const char *hostname); + /*****************************************************************************/ void nm_utils_thread_local_register_destroy(gpointer tls_data, GDestroyNotify destroy_notify); diff --git a/src/libnm-glib-aux/nm-test-utils.h b/src/libnm-glib-aux/nm-test-utils.h index ff8eb606..253aaf0e 100644 --- a/src/libnm-glib-aux/nm-test-utils.h +++ b/src/libnm-glib-aux/nm-test-utils.h @@ -81,8 +81,8 @@ *******************************************************************************/ #if defined(NM_ASSERT_NO_MSG) && NM_ASSERT_NO_MSG - #undef g_return_if_fail_warning - #undef g_assertion_message_expr +#undef g_return_if_fail_warning +#undef g_assertion_message_expr #endif #include <arpa/inet.h> @@ -693,42 +693,42 @@ nmtst_test_quick(void) } #if GLIB_CHECK_VERSION(2, 34, 0) - #undef g_test_expect_message - #define g_test_expect_message(...) \ - G_STMT_START \ - { \ - g_assert(nmtst_initialized()); \ - if (__nmtst_internal.assert_logging && __nmtst_internal.no_expect_message) { \ - g_debug("nmtst: assert-logging: g_test_expect_message %s", \ - G_STRINGIFY((__VA_ARGS__))); \ - } else { \ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ - g_test_expect_message(__VA_ARGS__); \ - G_GNUC_END_IGNORE_DEPRECATIONS \ - } \ - } \ - G_STMT_END - #undef g_test_assert_expected_messages_internal - #define g_test_assert_expected_messages_internal(domain, file, line, func) \ - G_STMT_START \ - { \ - const char *_domain = (domain); \ - const char *_file = (file); \ - const char *_func = (func); \ - int _line = (line); \ - \ - if (__nmtst_internal.assert_logging && __nmtst_internal.no_expect_message) \ - g_debug("nmtst: assert-logging: g_test_assert_expected_messages(%s, %s:%d, %s)", \ - _domain ?: "", \ - _file ?: "", \ - _line, \ - _func ?: ""); \ - \ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ - g_test_assert_expected_messages_internal(_domain, _file, _line, _func); \ - G_GNUC_END_IGNORE_DEPRECATIONS \ - } \ - G_STMT_END +#undef g_test_expect_message +#define g_test_expect_message(...) \ + G_STMT_START \ + { \ + g_assert(nmtst_initialized()); \ + if (__nmtst_internal.assert_logging && __nmtst_internal.no_expect_message) { \ + g_debug("nmtst: assert-logging: g_test_expect_message %s", \ + G_STRINGIFY((__VA_ARGS__))); \ + } else { \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ + g_test_expect_message(__VA_ARGS__); \ + G_GNUC_END_IGNORE_DEPRECATIONS \ + } \ + } \ + G_STMT_END +#undef g_test_assert_expected_messages_internal +#define g_test_assert_expected_messages_internal(domain, file, line, func) \ + G_STMT_START \ + { \ + const char *_domain = (domain); \ + const char *_file = (file); \ + const char *_func = (func); \ + int _line = (line); \ + \ + if (__nmtst_internal.assert_logging && __nmtst_internal.no_expect_message) \ + g_debug("nmtst: assert-logging: g_test_assert_expected_messages(%s, %s:%d, %s)", \ + _domain ?: "", \ + _file ?: "", \ + _line, \ + _func ?: ""); \ + \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ + g_test_assert_expected_messages_internal(_domain, _file, _line, _func); \ + G_GNUC_END_IGNORE_DEPRECATIONS \ + } \ + G_STMT_END #endif #define NMTST_EXPECT(domain, level, msg) g_test_expect_message(domain, level, msg) @@ -1032,7 +1032,7 @@ nmtst_rand_perm_strv(const char *const *strv) /* this returns a (scrambled) SHALLOW copy of the strv array! */ n = NM_PTRARRAY_LEN(strv); - res = (const char **) (nm_utils_strv_dup(strv, n, FALSE) ?: g_new0(char *, 1)); + res = (const char **) (nm_strv_dup(strv, n, FALSE) ?: g_new0(char *, 1)); nmtst_rand_perm(NULL, res, res, sizeof(char *), n); return res; } @@ -1238,7 +1238,7 @@ _nmtst_main_loop_quit_on_notify(GObject *object, GParamSpec *pspec, gpointer use g_main_loop_quit(loop); } -#define nmtst_main_loop_quit_on_notify ((GCallback) _nmtst_main_loop_quit_on_notify) +#define nmtst_main_loop_quit_on_notify (G_CALLBACK(_nmtst_main_loop_quit_on_notify)) #define nmtst_main_context_iterate_until_full(context, timeout_msec, poll_msec, condition) \ ({ \ @@ -1458,6 +1458,19 @@ next:; /*****************************************************************************/ +/* uses an expression statement to copy and return @arg. The use is for functions + * like nmtst_inet4_from_string(), which return a static (thread-local) variable. + * If you use such a statement twice, the result will be overwritten. The macro + * prevents that. */ +#define NMTST_COPY(arg) \ + ({ \ + typeof(arg) _arg = (arg); \ + \ + _arg; \ + }) + +/*****************************************************************************/ + #define __define_nmtst_static(NUM, SIZE) \ static inline const char *nmtst_static_##SIZE##_##NUM(const char *str) \ { \ @@ -1475,9 +1488,9 @@ __define_nmtst_static(01, 1024) __define_nmtst_static(02, 1024) __define_nmtst_s #if defined(__NM_UTILS_H__) || defined(NM_UTILS_H) - #define NMTST_UUID_INIT(uuid) \ - gs_free char * _nmtst_hidden_##uuid = nm_utils_uuid_generate(); \ - const char *const uuid = _nmtst_hidden_##uuid +#define NMTST_UUID_INIT(uuid) \ + gs_free char * _nmtst_hidden_##uuid = nm_utils_uuid_generate(); \ + const char *const uuid = _nmtst_hidden_##uuid static inline const char *nmtst_uuid_generate(void) { @@ -1819,13 +1832,13 @@ _nmtst_assert_resolve_relative_path_equals(const char *f1, #ifdef __NETWORKMANAGER_LOGGING_H__ - #define NMTST_EXPECT_NM(level, msg) NMTST_EXPECT("NetworkManager", level, msg) +#define NMTST_EXPECT_NM(level, msg) NMTST_EXPECT("NetworkManager", level, msg) - #define NMTST_EXPECT_NM_ERROR(msg) NMTST_EXPECT_NM(G_LOG_LEVEL_MESSAGE, "*<error> [*] " msg) - #define NMTST_EXPECT_NM_WARN(msg) NMTST_EXPECT_NM(G_LOG_LEVEL_MESSAGE, "*<warn> [*] " msg) - #define NMTST_EXPECT_NM_INFO(msg) NMTST_EXPECT_NM(G_LOG_LEVEL_INFO, "*<info> [*] " msg) - #define NMTST_EXPECT_NM_DEBUG(msg) NMTST_EXPECT_NM(G_LOG_LEVEL_DEBUG, "*<debug> [*] " msg) - #define NMTST_EXPECT_NM_TRACE(msg) NMTST_EXPECT_NM(G_LOG_LEVEL_DEBUG, "*<trace> [*] " msg) +#define NMTST_EXPECT_NM_ERROR(msg) NMTST_EXPECT_NM(G_LOG_LEVEL_MESSAGE, "*<error> [*] " msg) +#define NMTST_EXPECT_NM_WARN(msg) NMTST_EXPECT_NM(G_LOG_LEVEL_MESSAGE, "*<warn> [*] " msg) +#define NMTST_EXPECT_NM_INFO(msg) NMTST_EXPECT_NM(G_LOG_LEVEL_INFO, "*<info> [*] " msg) +#define NMTST_EXPECT_NM_DEBUG(msg) NMTST_EXPECT_NM(G_LOG_LEVEL_DEBUG, "*<debug> [*] " msg) +#define NMTST_EXPECT_NM_TRACE(msg) NMTST_EXPECT_NM(G_LOG_LEVEL_DEBUG, "*<trace> [*] " msg) static inline void nmtst_init_with_logging(int *argc, char ***argv, const char *log_level, const char *log_domains) @@ -1982,16 +1995,38 @@ nmtst_assert_route_attribute_boolean(NMIPRoute *route, const char *name, gboolea #if (defined(__NM_SIMPLE_CONNECTION_H__) && defined(__NM_SETTING_CONNECTION_H__)) \ || (defined(NM_CONNECTION_H)) +#define nmtst_connection_assert_setting(connection, gtype) \ + ({ \ + const GType _gtype = (gtype); \ + gpointer _ptr; \ + \ + _ptr = nm_connection_get_setting((connection), (_gtype)); \ + g_assert(NM_IS_SETTING(_ptr)); \ + g_assert(G_OBJECT_TYPE(_ptr) == _gtype); \ + _ptr; \ + }) + +#define nmtst_connection_assert_no_setting(connection, gtype) \ + G_STMT_START \ + { \ + const GType _gtype = (gtype); \ + gpointer _ptr; \ + \ + _ptr = nm_connection_get_setting((connection), (_gtype)); \ + g_assert(!_ptr); \ + } \ + G_STMT_END + static inline NMConnection * nmtst_clone_connection(NMConnection *connection) { g_assert(NM_IS_CONNECTION(connection)); - #if defined(__NM_SIMPLE_CONNECTION_H__) +#if defined(__NM_SIMPLE_CONNECTION_H__) return nm_simple_connection_new_clone(connection); - #else +#else return nm_connection_duplicate(connection); - #endif +#endif } static inline NMConnection * @@ -2015,11 +2050,11 @@ nmtst_create_minimal_connection(const char * id, if (type) { GType type_g; - #if defined(__NM_SIMPLE_CONNECTION_H__) +#if defined(__NM_SIMPLE_CONNECTION_H__) type_g = nm_setting_lookup_type(type); - #else +#else type_g = nm_connection_lookup_setting_type(type); - #endif +#endif g_assert(type_g != G_TYPE_INVALID); @@ -2027,11 +2062,11 @@ nmtst_create_minimal_connection(const char * id, g_assert(NM_IS_SETTING(s_base)); } - #if defined(__NM_SIMPLE_CONNECTION_H__) +#if defined(__NM_SIMPLE_CONNECTION_H__) con = nm_simple_connection_new(); - #else +#else con = nm_connection_new(); - #endif +#endif g_assert(con); @@ -2096,8 +2131,8 @@ _nmtst_connection_normalize(NMConnection *connection, ...) return was_modified; } - #define nmtst_connection_normalize(connection, ...) \ - _nmtst_connection_normalize(connection, ##__VA_ARGS__, NULL) +#define nmtst_connection_normalize(connection, ...) \ + _nmtst_connection_normalize(connection, ##__VA_ARGS__, NULL) static inline NMConnection * _nmtst_connection_duplicate_and_normalize(NMConnection *connection, ...) @@ -2112,8 +2147,8 @@ _nmtst_connection_duplicate_and_normalize(NMConnection *connection, ...) return connection; } - #define nmtst_connection_duplicate_and_normalize(connection, ...) \ - _nmtst_connection_duplicate_and_normalize(connection, ##__VA_ARGS__, NULL) +#define nmtst_connection_duplicate_and_normalize(connection, ...) \ + _nmtst_connection_duplicate_and_normalize(connection, ##__VA_ARGS__, NULL) static inline void nmtst_assert_connection_equals(NMConnection *a, @@ -2152,7 +2187,7 @@ nmtst_assert_connection_equals(NMConnection *a, } } - #ifdef __NM_KEYFILE_INTERNAL_H__ +#ifdef __NM_KEYFILE_INTERNAL_H__ { nm_auto_unref_keyfile GKeyFile *kf_a = NULL, *kf_b = NULL; gs_free char * str_a = NULL, *str_b = NULL; @@ -2174,7 +2209,7 @@ nmtst_assert_connection_equals(NMConnection *a, "the difference*):\n%s", str_b); } - #endif +#endif } g_assert(compare); g_assert(!out_settings); @@ -2308,8 +2343,8 @@ nmtst_assert_setting_verifies(NMSetting *setting) g_assert(success); } - #if defined(__NM_SIMPLE_CONNECTION_H__) && NM_CHECK_VERSION(1, 10, 0) \ - && (!defined(NM_VERSION_MAX_ALLOWED) || NM_VERSION_MAX_ALLOWED >= NM_VERSION_1_10) +#if defined(__NM_SIMPLE_CONNECTION_H__) && NM_CHECK_VERSION(1, 10, 0) \ + && (!defined(NM_VERSION_MAX_ALLOWED) || NM_VERSION_MAX_ALLOWED >= NM_VERSION_1_10) static inline void _nmtst_assert_connection_has_settings(NMConnection *connection, gboolean has_at_least, @@ -2363,13 +2398,13 @@ _nmtst_assert_connection_has_settings(NMConnection *connection, has_str); } } - #define nmtst_assert_connection_has_settings(connection, ...) \ - _nmtst_assert_connection_has_settings((connection), TRUE, TRUE, __VA_ARGS__, NULL) - #define nmtst_assert_connection_has_settings_at_least(connection, ...) \ - _nmtst_assert_connection_has_settings((connection), TRUE, FALSE, __VA_ARGS__, NULL) - #define nmtst_assert_connection_has_settings_at_most(connection, ...) \ - _nmtst_assert_connection_has_settings((connection), FALSE, TRUE, __VA_ARGS__, NULL) - #endif +#define nmtst_assert_connection_has_settings(connection, ...) \ + _nmtst_assert_connection_has_settings((connection), TRUE, TRUE, __VA_ARGS__, NULL) +#define nmtst_assert_connection_has_settings_at_least(connection, ...) \ + _nmtst_assert_connection_has_settings((connection), TRUE, FALSE, __VA_ARGS__, NULL) +#define nmtst_assert_connection_has_settings_at_most(connection, ...) \ + _nmtst_assert_connection_has_settings((connection), FALSE, TRUE, __VA_ARGS__, NULL) +#endif static inline void nmtst_assert_setting_verify_fails(NMSetting *setting, @@ -2485,8 +2520,8 @@ nmtst_assert_hwaddr_equals(gconstpointer hwaddr1, hwaddr1_len); } } - #define nmtst_assert_hwaddr_equals(hwaddr1, hwaddr1_len, expected) \ - nmtst_assert_hwaddr_equals(hwaddr1, hwaddr1_len, expected, __FILE__, __LINE__) +#define nmtst_assert_hwaddr_equals(hwaddr1, hwaddr1_len, expected) \ + nmtst_assert_hwaddr_equals(hwaddr1, hwaddr1_len, expected, __FILE__, __LINE__) #endif #if defined(__NM_SIMPLE_CONNECTION_H__) && defined(__NM_SETTING_CONNECTION_H__) \ @@ -2547,89 +2582,89 @@ _nmtst_variant_new_vardict(int dummy, ...) return g_variant_builder_end(&builder); } - #define nmtst_variant_new_vardict(...) _nmtst_variant_new_vardict(0, __VA_ARGS__, NULL) - - #define nmtst_assert_variant_is_of_type(variant, type) \ - G_STMT_START \ - { \ - GVariant *_variantx = (variant); \ - \ - g_assert(_variantx); \ - g_assert(g_variant_is_of_type(_variantx, (type))); \ - } \ - G_STMT_END - - #define nmtst_assert_variant_uint32(variant, val) \ - G_STMT_START \ - { \ - GVariant *_variant = (variant); \ - \ - nmtst_assert_variant_is_of_type(_variant, G_VARIANT_TYPE_UINT32); \ - g_assert_cmpint(g_variant_get_uint32(_variant), ==, (val)); \ - } \ - G_STMT_END - - #define nmtst_assert_variant_string(variant, str) \ - G_STMT_START \ - { \ - gsize _l; \ - GVariant * _variant = (variant); \ - const char *_str = (str); \ +#define nmtst_variant_new_vardict(...) _nmtst_variant_new_vardict(0, __VA_ARGS__, NULL) + +#define nmtst_assert_variant_is_of_type(variant, type) \ + G_STMT_START \ + { \ + GVariant *_variantx = (variant); \ + \ + g_assert(_variantx); \ + g_assert(g_variant_is_of_type(_variantx, (type))); \ + } \ + G_STMT_END + +#define nmtst_assert_variant_uint32(variant, val) \ + G_STMT_START \ + { \ + GVariant *_variant = (variant); \ + \ + nmtst_assert_variant_is_of_type(_variant, G_VARIANT_TYPE_UINT32); \ + g_assert_cmpint(g_variant_get_uint32(_variant), ==, (val)); \ + } \ + G_STMT_END + +#define nmtst_assert_variant_string(variant, str) \ + G_STMT_START \ + { \ + gsize _l; \ + GVariant * _variant = (variant); \ + const char *_str = (str); \ + \ + nmtst_assert_variant_is_of_type(_variant, G_VARIANT_TYPE_STRING); \ + g_assert(_str); \ + g_assert_cmpstr(g_variant_get_string(_variant, &_l), ==, _str); \ + g_assert_cmpint(_l, ==, strlen(_str)); \ + } \ + G_STMT_END + +#ifdef __NM_SHARED_UTILS_H__ +#define _nmtst_assert_variant_bytestring_cmp_str(_ptr, _ptr2, _len) \ + G_STMT_START \ + { \ + if (memcmp(_ptr2, _ptr, _len) != 0) { \ + gs_free char *_x1 = NULL; \ + gs_free char *_x2 = NULL; \ + const char * _xx1; \ + const char * _xx2; \ + \ + _xx1 = nm_utils_buf_utf8safe_escape(_ptr, \ + _len, \ + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, \ + &_x1); \ + _xx2 = nm_utils_buf_utf8safe_escape(_ptr2, \ + _len, \ + NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, \ + &_x2); \ + g_assert_cmpstr(_xx1, ==, _xx2); \ + g_assert_not_reached(); \ + } \ + } \ + G_STMT_END +#else +#define _nmtst_assert_variant_bytestring_cmp_str(_ptr, _ptr2, _len) \ + G_STMT_START {} \ + G_STMT_END +#endif + +#define nmtst_assert_variant_bytestring(variant, ptr, len) \ + G_STMT_START \ + { \ + GVariant * _variant = (variant); \ + gconstpointer _ptr = (ptr); \ + gconstpointer _ptr2; \ + gsize _len = (len); \ + gsize _len2; \ \ - nmtst_assert_variant_is_of_type(_variant, G_VARIANT_TYPE_STRING); \ - g_assert(_str); \ - g_assert_cmpstr(g_variant_get_string(_variant, &_l), ==, _str); \ - g_assert_cmpint(_l, ==, strlen(_str)); \ + nmtst_assert_variant_is_of_type(_variant, G_VARIANT_TYPE_BYTESTRING); \ + _ptr2 = g_variant_get_fixed_array(_variant, &_len2, 1); \ + g_assert_cmpint(_len2, ==, _len); \ + if (_len != 0 && _ptr) { \ + _nmtst_assert_variant_bytestring_cmp_str(_ptr, _ptr2, _len); \ + g_assert_cmpmem(_ptr2, _len2, _ptr, _len); \ } \ - G_STMT_END - - #ifdef __NM_SHARED_UTILS_H__ - #define _nmtst_assert_variant_bytestring_cmp_str(_ptr, _ptr2, _len) \ - G_STMT_START \ - { \ - if (memcmp(_ptr2, _ptr, _len) != 0) { \ - gs_free char *_x1 = NULL; \ - gs_free char *_x2 = NULL; \ - const char * _xx1; \ - const char * _xx2; \ - \ - _xx1 = nm_utils_buf_utf8safe_escape(_ptr, \ - _len, \ - NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, \ - &_x1); \ - _xx2 = nm_utils_buf_utf8safe_escape(_ptr2, \ - _len, \ - NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, \ - &_x2); \ - g_assert_cmpstr(_xx1, ==, _xx2); \ - g_assert_not_reached(); \ - } \ - } \ - G_STMT_END - #else - #define _nmtst_assert_variant_bytestring_cmp_str(_ptr, _ptr2, _len) \ - G_STMT_START {} \ - G_STMT_END - #endif - - #define nmtst_assert_variant_bytestring(variant, ptr, len) \ - G_STMT_START \ - { \ - GVariant * _variant = (variant); \ - gconstpointer _ptr = (ptr); \ - gconstpointer _ptr2; \ - gsize _len = (len); \ - gsize _len2; \ - \ - nmtst_assert_variant_is_of_type(_variant, G_VARIANT_TYPE_BYTESTRING); \ - _ptr2 = g_variant_get_fixed_array(_variant, &_len2, 1); \ - g_assert_cmpint(_len2, ==, _len); \ - if (_len != 0 && _ptr) { \ - _nmtst_assert_variant_bytestring_cmp_str(_ptr, _ptr2, _len); \ - g_assert_cmpmem(_ptr2, _len2, _ptr, _len); \ - } \ - } \ - G_STMT_END + } \ + G_STMT_END typedef enum { NMTST_VARIANT_EDITOR_CONNECTION, @@ -2637,120 +2672,117 @@ typedef enum { NMTST_VARIANT_EDITOR_PROPERTY } NmtstVariantEditorPhase; - #define NMTST_VARIANT_EDITOR(__connection_variant, __code) \ - G_STMT_START \ - { \ - GVariantIter __connection_iter, *__setting_iter; \ - GVariantBuilder __connection_builder, __setting_builder; \ - const char * __cur_setting_name, *__cur_property_name; \ - GVariant * __property_val; \ - NmtstVariantEditorPhase __phase; \ - \ - g_variant_builder_init(&__connection_builder, NM_VARIANT_TYPE_CONNECTION); \ - g_variant_iter_init(&__connection_iter, __connection_variant); \ - \ - __phase = NMTST_VARIANT_EDITOR_CONNECTION; \ - __cur_setting_name = NULL; \ - __cur_property_name = NULL; \ - __code; \ - while (g_variant_iter_next(&__connection_iter, \ - "{&sa{sv}}", \ - &__cur_setting_name, \ - &__setting_iter)) { \ - g_variant_builder_init(&__setting_builder, NM_VARIANT_TYPE_SETTING); \ - __phase = NMTST_VARIANT_EDITOR_SETTING; \ - __cur_property_name = NULL; \ - __code; \ - \ - while (__cur_setting_name \ - && g_variant_iter_next(__setting_iter, \ - "{&sv}", \ - &__cur_property_name, \ - &__property_val)) { \ - __phase = NMTST_VARIANT_EDITOR_PROPERTY; \ - __code; \ - \ - if (__cur_property_name) { \ - g_variant_builder_add(&__setting_builder, \ - "{sv}", \ - __cur_property_name, \ - __property_val); \ - } \ - g_variant_unref(__property_val); \ - } \ - \ - if (__cur_setting_name) \ - g_variant_builder_add(&__connection_builder, \ - "{sa{sv}}", \ - __cur_setting_name, \ - &__setting_builder); \ - else \ - g_variant_builder_clear(&__setting_builder); \ - g_variant_iter_free(__setting_iter); \ - } \ - \ - g_variant_unref(__connection_variant); \ - \ - __connection_variant = g_variant_builder_end(&__connection_builder); \ - } \ - G_STMT_END; - - #define NMTST_VARIANT_ADD_SETTING(__setting_name, __setting_variant) \ - G_STMT_START \ - { \ - if (__phase == NMTST_VARIANT_EDITOR_CONNECTION) \ - g_variant_builder_add(&__connection_builder, \ - "{s@a{sv}}", \ - __setting_name, \ - __setting_variant); \ - } \ - G_STMT_END - - #define NMTST_VARIANT_DROP_SETTING(__setting_name) \ - G_STMT_START \ - { \ - if (__phase == NMTST_VARIANT_EDITOR_SETTING && __cur_setting_name) { \ - if (!strcmp(__cur_setting_name, __setting_name)) \ - __cur_setting_name = NULL; \ - } \ - } \ - G_STMT_END - - #define NMTST_VARIANT_ADD_PROPERTY(__setting_name, __property_name, __format_string, __value) \ - G_STMT_START \ - { \ - if (__phase == NMTST_VARIANT_EDITOR_SETTING) { \ - if (!strcmp(__cur_setting_name, __setting_name)) { \ - g_variant_builder_add(&__setting_builder, \ - "{sv}", \ - __property_name, \ - g_variant_new(__format_string, __value)); \ - } \ - } \ - } \ - G_STMT_END - - #define NMTST_VARIANT_DROP_PROPERTY(__setting_name, __property_name) \ - G_STMT_START \ - { \ - if (__phase == NMTST_VARIANT_EDITOR_PROPERTY && __cur_property_name) { \ - if (!strcmp(__cur_setting_name, __setting_name) \ - && !strcmp(__cur_property_name, __property_name)) \ - __cur_property_name = NULL; \ +#define NMTST_VARIANT_EDITOR(__connection_variant, __code) \ + G_STMT_START \ + { \ + GVariantIter __connection_iter, *__setting_iter; \ + GVariantBuilder __connection_builder, __setting_builder; \ + const char * __cur_setting_name, *__cur_property_name; \ + GVariant * __property_val; \ + NmtstVariantEditorPhase __phase; \ + \ + g_variant_builder_init(&__connection_builder, NM_VARIANT_TYPE_CONNECTION); \ + g_variant_iter_init(&__connection_iter, __connection_variant); \ + \ + __phase = NMTST_VARIANT_EDITOR_CONNECTION; \ + __cur_setting_name = NULL; \ + __cur_property_name = NULL; \ + __code; \ + while (g_variant_iter_next(&__connection_iter, \ + "{&sa{sv}}", \ + &__cur_setting_name, \ + &__setting_iter)) { \ + g_variant_builder_init(&__setting_builder, NM_VARIANT_TYPE_SETTING); \ + __phase = NMTST_VARIANT_EDITOR_SETTING; \ + __cur_property_name = NULL; \ + __code; \ + \ + while (__cur_setting_name \ + && g_variant_iter_next(__setting_iter, \ + "{&sv}", \ + &__cur_property_name, \ + &__property_val)) { \ + __phase = NMTST_VARIANT_EDITOR_PROPERTY; \ + __code; \ + \ + if (__cur_property_name) { \ + g_variant_builder_add(&__setting_builder, \ + "{sv}", \ + __cur_property_name, \ + __property_val); \ + } \ + g_variant_unref(__property_val); \ } \ + \ + if (__cur_setting_name) \ + g_variant_builder_add(&__connection_builder, \ + "{sa{sv}}", \ + __cur_setting_name, \ + &__setting_builder); \ + else \ + g_variant_builder_clear(&__setting_builder); \ + g_variant_iter_free(__setting_iter); \ } \ - G_STMT_END - - #define NMTST_VARIANT_CHANGE_PROPERTY(__setting_name, \ - __property_name, \ - __format_string, \ - __value) \ - G_STMT_START \ - { \ - NMTST_VARIANT_DROP_PROPERTY(__setting_name, __property_name); \ - NMTST_VARIANT_ADD_PROPERTY(__setting_name, __property_name, __format_string, __value); \ - } \ - G_STMT_END + \ + g_variant_unref(__connection_variant); \ + \ + __connection_variant = g_variant_builder_end(&__connection_builder); \ + } \ + G_STMT_END; + +#define NMTST_VARIANT_ADD_SETTING(__setting_name, __setting_variant) \ + G_STMT_START \ + { \ + if (__phase == NMTST_VARIANT_EDITOR_CONNECTION) \ + g_variant_builder_add(&__connection_builder, \ + "{s@a{sv}}", \ + __setting_name, \ + __setting_variant); \ + } \ + G_STMT_END + +#define NMTST_VARIANT_DROP_SETTING(__setting_name) \ + G_STMT_START \ + { \ + if (__phase == NMTST_VARIANT_EDITOR_SETTING && __cur_setting_name) { \ + if (!strcmp(__cur_setting_name, __setting_name)) \ + __cur_setting_name = NULL; \ + } \ + } \ + G_STMT_END + +#define NMTST_VARIANT_ADD_PROPERTY(__setting_name, __property_name, __format_string, __value) \ + G_STMT_START \ + { \ + if (__phase == NMTST_VARIANT_EDITOR_SETTING) { \ + if (!strcmp(__cur_setting_name, __setting_name)) { \ + g_variant_builder_add(&__setting_builder, \ + "{sv}", \ + __property_name, \ + g_variant_new(__format_string, __value)); \ + } \ + } \ + } \ + G_STMT_END + +#define NMTST_VARIANT_DROP_PROPERTY(__setting_name, __property_name) \ + G_STMT_START \ + { \ + if (__phase == NMTST_VARIANT_EDITOR_PROPERTY && __cur_property_name) { \ + if (!strcmp(__cur_setting_name, __setting_name) \ + && !strcmp(__cur_property_name, __property_name)) \ + __cur_property_name = NULL; \ + } \ + } \ + G_STMT_END + +#define NMTST_VARIANT_CHANGE_PROPERTY(__setting_name, __property_name, __format_string, __value) \ + G_STMT_START \ + { \ + NMTST_VARIANT_DROP_PROPERTY(__setting_name, __property_name); \ + NMTST_VARIANT_ADD_PROPERTY(__setting_name, __property_name, __format_string, __value); \ + } \ + G_STMT_END #endif /* __NM_CONNECTION_H__ */ @@ -2857,4 +2889,20 @@ nmtst_ip_address_new(int addr_family, const char *str) /*****************************************************************************/ +#define nmtst_gbytes_from_arr(...) \ + ({ \ + const guint8 _arr[] = {__VA_ARGS__}; \ + \ + g_bytes_new(_arr, sizeof(_arr)); \ + }) + +#define nmtst_gbytes_from_str(str) \ + ({ \ + const char *const _str = (str); \ + \ + g_bytes_new(_str, strlen(_str)); \ + }) + +/*****************************************************************************/ + #endif /* __NM_TEST_UTILS_H__ */ diff --git a/src/libnm-glib-aux/nm-uuid.c b/src/libnm-glib-aux/nm-uuid.c index 2c6e218a..e7f67c70 100644 --- a/src/libnm-glib-aux/nm-uuid.c +++ b/src/libnm-glib-aux/nm-uuid.c @@ -9,6 +9,13 @@ /*****************************************************************************/ +const NMUuid nm_uuid_ns_zero = + NM_UUID_INIT(00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00); + +/* arbitrarily chosen namespace UUID for nm_uuid_generate_from_strings() */ +const NMUuid nm_uuid_ns_1 = + NM_UUID_INIT(b4, 25, e9, fb, 75, 98, 44, b4, 9e, 3b, 5a, 2e, 3a, aa, 49, 05); + char * nm_uuid_unparse_case(const NMUuid *uuid, char out_str[static 37], gboolean upper_case) { @@ -171,7 +178,7 @@ nm_uuid_is_valid_nmlegacy(const char *str) } /* While we accept here bogus strings as UUIDs, they must contain only - * hexdigits and '-', and they must be eithr 36 or 40 chars long. */ + * hexdigits and '-', and they must be either 36 or 40 chars long. */ if ((num_dashes == 4) && (p - str == 36)) return TRUE; @@ -234,16 +241,20 @@ nm_uuid_is_valid_nm(const char *str, nm_assert(strlen(str) < G_N_ELEMENTS(str_lower)); /* normalize first to lower-case. */ - g_strlcpy(str_lower, str, sizeof(str_lower)); - for (i = 0; str_lower[i]; i++) - str_lower[i] = g_ascii_tolower(str_lower[i]); + for (i = 0; str[i]; i++) { + nm_assert(i < G_N_ELEMENTS(str_lower)); + str_lower[i] = g_ascii_tolower(str[i]); + } + nm_assert(i < G_N_ELEMENTS(str_lower)); + str_lower[i] = '\0'; /* The namespace UUID is chosen randomly. */ - nm_uuid_generate_from_string(&uuid, - str_lower, - -1, - NM_UUID_TYPE_VERSION5, - "4e72f709-ca95-4405-9053-1f43294a618c"); + nm_uuid_generate_from_string( + &uuid, + str_lower, + -1, + NM_UUID_TYPE_VERSION5, + &NM_UUID_INIT(4e, 72, f7, 09, ca, 95, 44, 05, 90, 53, 1f, 43, 29, 4a, 61, 8c)); nm_uuid_unparse(&uuid, out_normalized_str); } return TRUE; @@ -299,11 +310,11 @@ nm_uuid_generate_random_str(char buf[static 37]) * Returns: the input @uuid. This function cannot fail. **/ NMUuid * -nm_uuid_generate_from_string(NMUuid * uuid, - const char *s, - gssize slen, - NMUuidType uuid_type, - gpointer type_args) +nm_uuid_generate_from_string(NMUuid * uuid, + const char * s, + gssize slen, + NMUuidType uuid_type, + const NMUuid *type_args) { g_return_val_if_fail(uuid, FALSE); g_return_val_if_fail(slen == 0 || s, FALSE); @@ -313,26 +324,20 @@ nm_uuid_generate_from_string(NMUuid * uuid, switch (uuid_type) { case NM_UUID_TYPE_LEGACY: - g_return_val_if_fail(!type_args, NULL); + nm_assert(!type_args); nm_crypto_md5_hash(NULL, 0, (guint8 *) s, slen, (guint8 *) uuid, sizeof(*uuid)); break; case NM_UUID_TYPE_VERSION3: case NM_UUID_TYPE_VERSION5: { - NMUuid ns_uuid; - - if (type_args) { - /* type_args can be a name space UUID. Interpret it as (char *) */ - if (!nm_uuid_parse(type_args, &ns_uuid)) - g_return_val_if_reached(NULL); - } else - ns_uuid = (NMUuid){}; + if (!type_args) + type_args = &nm_uuid_ns_zero; if (uuid_type == NM_UUID_TYPE_VERSION3) { nm_crypto_md5_hash((guint8 *) s, slen, - (guint8 *) &ns_uuid, - sizeof(ns_uuid), + (guint8 *) type_args, + sizeof(*type_args), (guint8 *) uuid, sizeof(*uuid)); } else { @@ -343,7 +348,7 @@ nm_uuid_generate_from_string(NMUuid * uuid, } digest; sum = g_checksum_new(G_CHECKSUM_SHA1); - g_checksum_update(sum, (guchar *) &ns_uuid, sizeof(ns_uuid)); + g_checksum_update(sum, (guchar *) type_args, sizeof(*type_args)); g_checksum_update(sum, (guchar *) s, slen); nm_utils_checksum_get_digest(sum, digest.sha1); @@ -377,10 +382,10 @@ nm_uuid_generate_from_string(NMUuid * uuid, * object's #NMSettingConnection:id: property **/ char * -nm_uuid_generate_from_string_str(const char *s, - gssize slen, - NMUuidType uuid_type, - gpointer type_args) +nm_uuid_generate_from_string_str(const char * s, + gssize slen, + NMUuidType uuid_type, + const NMUuid *type_args) { NMUuid uuid; @@ -405,7 +410,7 @@ char * nm_uuid_generate_from_strings(const char *string1, ...) { if (!string1) - return nm_uuid_generate_from_string_str(NULL, 0, NM_UUID_TYPE_VERSION3, NM_UUID_NS1); + return nm_uuid_generate_from_string_str(NULL, 0, NM_UUID_TYPE_VERSION3, &nm_uuid_ns_1); { nm_auto_str_buf NMStrBuf str = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_104, FALSE); @@ -425,6 +430,6 @@ nm_uuid_generate_from_strings(const char *string1, ...) return nm_uuid_generate_from_string_str(nm_str_buf_get_str_unsafe(&str), str.len, NM_UUID_TYPE_VERSION3, - NM_UUID_NS1); + &nm_uuid_ns_1); } } diff --git a/src/libnm-glib-aux/nm-uuid.h b/src/libnm-glib-aux/nm-uuid.h index 10302bd8..504ec789 100644 --- a/src/libnm-glib-aux/nm-uuid.h +++ b/src/libnm-glib-aux/nm-uuid.h @@ -7,6 +7,28 @@ typedef struct _NMUuid { guint8 uuid[16]; } NMUuid; +#define NM_UUID_INIT_ZERO() ((NMUuid){.uuid = {0}}) + +#define NM_UUID_INIT(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15) \ + ((NMUuid){ \ + .uuid = {(0x##a0), \ + (0x##a1), \ + (0x##a2), \ + (0x##a3), \ + (0x##a4), \ + (0x##a5), \ + (0x##a6), \ + (0x##a7), \ + (0x##a8), \ + (0x##a9), \ + (0x##a10), \ + (0x##a11), \ + (0x##a12), \ + (0x##a13), \ + (0x##a14), \ + (0x##a15)}, \ + }) + char *nm_uuid_unparse_case(const NMUuid *uuid, char out_str[static 37], gboolean upper_case); static inline char * @@ -73,25 +95,30 @@ char *nm_uuid_generate_random_str(char buf[static 37]); /*****************************************************************************/ +extern const NMUuid nm_uuid_ns_zero; +extern const NMUuid nm_uuid_ns_1; + +#define NM_UUID_NS_ZERO "00000000-0000-0000-0000-000000000000" +#define NM_UUID_NS_1 "b425e9fb-7598-44b4-9e3b-5a2e3aaa4905" + +/*****************************************************************************/ + typedef enum { NM_UUID_TYPE_LEGACY = 0, NM_UUID_TYPE_VERSION3 = 3, NM_UUID_TYPE_VERSION5 = 5, } NMUuidType; -NMUuid *nm_uuid_generate_from_string(NMUuid * uuid, - const char *s, - gssize slen, - NMUuidType uuid_type, - gpointer type_args); - -char *nm_uuid_generate_from_string_str(const char *s, - gssize slen, - NMUuidType uuid_type, - gpointer type_args); +NMUuid *nm_uuid_generate_from_string(NMUuid * uuid, + const char * s, + gssize slen, + NMUuidType uuid_type, + const NMUuid *type_args); -/* arbitrarily chosen namespace UUID for nm_uuid_generate_from_strings() */ -#define NM_UUID_NS1 "b425e9fb-7598-44b4-9e3b-5a2e3aaa4905" +char *nm_uuid_generate_from_string_str(const char * s, + gssize slen, + NMUuidType uuid_type, + const NMUuid *type_args); char *nm_uuid_generate_from_strings(const char *string1, ...) G_GNUC_NULL_TERMINATED; diff --git a/src/libnm-glib-aux/nm-value-type.h b/src/libnm-glib-aux/nm-value-type.h index f1cce480..0addeec6 100644 --- a/src/libnm-glib-aux/nm-value-type.h +++ b/src/libnm-glib-aux/nm-value-type.h @@ -7,13 +7,27 @@ #define __NM_VALUE_TYPE_H__ typedef enum _nm_packed { + NM_VALUE_TYPE_NONE = 0, NM_VALUE_TYPE_UNSPEC = 1, NM_VALUE_TYPE_BOOL = 2, NM_VALUE_TYPE_INT32 = 3, NM_VALUE_TYPE_INT = 4, NM_VALUE_TYPE_INT64 = 5, - NM_VALUE_TYPE_UINT64 = 6, - NM_VALUE_TYPE_STRING = 7, + NM_VALUE_TYPE_UINT32 = 6, + NM_VALUE_TYPE_UINT = 7, + NM_VALUE_TYPE_UINT64 = 8, + + /* Flags are for G_TYPE_FLAGS. That is, internally they are tracked + * as a guint, they have a g_param_spec_flags() property and they are + * serialized on D-Bus as "u". */ + NM_VALUE_TYPE_FLAGS = 9, + + /* G_TYPE_ENUM */ + NM_VALUE_TYPE_ENUM = 10, + + NM_VALUE_TYPE_STRING = 11, + + NM_VALUE_TYPE_BYTES = 12, } NMValueType; /*****************************************************************************/ @@ -35,37 +49,37 @@ typedef union { } NMValueTypUnion; - /* Set the NMValueTypUnion. You can also assign the member directly. +/* Set the NMValueTypUnion. You can also assign the member directly. * The only purpose of this is that it also returns a pointer to the * union. So, you can do * * ptr = NM_VALUE_TYP_UNION_SET (&value_typ_union_storage, v_bool, TRUE); */ - #define NM_VALUE_TYP_UNION_SET(_arg, _type, _val) \ - ({ \ - NMValueTypUnion *const _arg2 = (_arg); \ - \ - *_arg2 = (NMValueTypUnion){ \ - ._type = (_val), \ - }; \ - _arg2; \ - }) +#define NM_VALUE_TYP_UNION_SET(_arg, _type, _val) \ + ({ \ + NMValueTypUnion *const _arg2 = (_arg); \ + \ + *_arg2 = (NMValueTypUnion){ \ + ._type = (_val), \ + }; \ + _arg2; \ + }) typedef struct { bool has; NMValueTypUnion val; } NMValueTypUnioMaybe; - #define NM_VALUE_TYP_UNIO_MAYBE_SET(_arg, _type, _val) \ - ({ \ - NMValueTypUnioMaybe *const _arg2 = (_arg); \ - \ - *_arg2 = (NMValueTypUnioMaybe){ \ - .has = TRUE, \ - .val._type = (_val), \ - }; \ - _arg2; \ - }) +#define NM_VALUE_TYP_UNIO_MAYBE_SET(_arg, _type, _val) \ + ({ \ + NMValueTypUnioMaybe *const _arg2 = (_arg); \ + \ + *_arg2 = (NMValueTypUnioMaybe){ \ + .has = TRUE, \ + .val._type = (_val), \ + }; \ + _arg2; \ + }) /*****************************************************************************/ @@ -80,16 +94,27 @@ nm_value_type_cmp(NMValueType value_type, gconstpointer p_a, gconstpointer p_b) NM_CMP_DIRECT(*((const gint32 *) p_a), *((const gint32 *) p_b)); return 0; case NM_VALUE_TYPE_INT: + case NM_VALUE_TYPE_ENUM: NM_CMP_DIRECT(*((const int *) p_a), *((const int *) p_b)); return 0; case NM_VALUE_TYPE_INT64: NM_CMP_DIRECT(*((const gint64 *) p_a), *((const gint64 *) p_b)); return 0; + case NM_VALUE_TYPE_UINT32: + NM_CMP_DIRECT(*((const guint32 *) p_a), *((const guint32 *) p_b)); + return 0; + case NM_VALUE_TYPE_UINT: + case NM_VALUE_TYPE_FLAGS: + NM_CMP_DIRECT(*((const guint *) p_a), *((const guint *) p_b)); + return 0; case NM_VALUE_TYPE_UINT64: NM_CMP_DIRECT(*((const guint64 *) p_a), *((const guint64 *) p_b)); return 0; case NM_VALUE_TYPE_STRING: return nm_strcmp0(*((const char *const *) p_a), *((const char *const *) p_b)); + case NM_VALUE_TYPE_BYTES: + return nm_g_bytes_equal0(*((const GBytes *const *) p_a), *((const GBytes *const *) p_b)); + case NM_VALUE_TYPE_NONE: case NM_VALUE_TYPE_UNSPEC: break; } @@ -114,21 +139,39 @@ nm_value_type_copy(NMValueType value_type, gpointer dst, gconstpointer src) (*((gint32 *) dst) = *((const gint32 *) src)); return; case NM_VALUE_TYPE_INT: + case NM_VALUE_TYPE_ENUM: (*((int *) dst) = *((const int *) src)); return; case NM_VALUE_TYPE_INT64: (*((gint64 *) dst) = *((const gint64 *) src)); return; + case NM_VALUE_TYPE_UINT32: + (*((guint32 *) dst) = *((const guint32 *) src)); + return; + case NM_VALUE_TYPE_UINT: + case NM_VALUE_TYPE_FLAGS: + (*((guint *) dst) = *((const guint *) src)); + return; case NM_VALUE_TYPE_UINT64: (*((guint64 *) dst) = *((const guint64 *) src)); return; case NM_VALUE_TYPE_STRING: /* self assignment safe! */ if (*((char **) dst) != *((const char *const *) src)) { - g_free(*((char **) dst)); + _nm_unused char *old = *((char **) dst); + *((char **) dst) = g_strdup(*((const char *const *) src)); } return; + case NM_VALUE_TYPE_BYTES: + /* self assignment safe! */ + if (*((GBytes **) dst) != *((const GBytes *const *) src)) { + _nm_unused gs_unref_bytes GBytes *old = *((GBytes **) dst); + + *((GBytes **) dst) = g_bytes_ref(*((GBytes *const *) src)); + } + return; + case NM_VALUE_TYPE_NONE: case NM_VALUE_TYPE_UNSPEC: break; } @@ -151,12 +194,16 @@ nm_value_type_get_from_variant(NMValueType value_type, case NM_VALUE_TYPE_INT64: *((gint64 *) dst) = g_variant_get_int64(variant); return; + case NM_VALUE_TYPE_UINT32: + *((guint32 *) dst) = g_variant_get_uint32(variant); + return; case NM_VALUE_TYPE_UINT64: *((guint64 *) dst) = g_variant_get_uint64(variant); return; case NM_VALUE_TYPE_STRING: if (clone) { - g_free(*((char **) dst)); + _nm_unused gs_free char *old = *((char **) dst); + *((char **) dst) = g_variant_dup_string(variant, NULL); } else { /* we don't clone the string, nor free the previous value. */ @@ -164,11 +211,16 @@ nm_value_type_get_from_variant(NMValueType value_type, } return; + case NM_VALUE_TYPE_BYTES: case NM_VALUE_TYPE_INT: - /* "int" also does not have a define variant type, because it's not - * clear how many bits we would need. */ + case NM_VALUE_TYPE_UINT: + case NM_VALUE_TYPE_ENUM: + case NM_VALUE_TYPE_FLAGS: + /* These types don't have a defined variant type, because it's not + * clear how many bits we would need or how to handle the type. */ /* fall-through */ + case NM_VALUE_TYPE_NONE: case NM_VALUE_TYPE_UNSPEC: break; } @@ -178,7 +230,8 @@ nm_value_type_get_from_variant(NMValueType value_type, static inline GVariant * nm_value_type_to_variant(NMValueType value_type, gconstpointer src) { - const char *v_string; + const char * v_string; + const GBytes *v_bytes; switch (value_type) { case NM_VALUE_TYPE_BOOL: @@ -187,17 +240,26 @@ nm_value_type_to_variant(NMValueType value_type, gconstpointer src) return g_variant_new_int32(*((const gint32 *) src)); case NM_VALUE_TYPE_INT64: return g_variant_new_int64(*((const gint64 *) src)); + case NM_VALUE_TYPE_UINT32: + return g_variant_new_uint32(*((const guint32 *) src)); case NM_VALUE_TYPE_UINT64: return g_variant_new_uint64(*((const guint64 *) src)); case NM_VALUE_TYPE_STRING: v_string = *((const char *const *) src); return v_string ? g_variant_new_string(v_string) : NULL; + case NM_VALUE_TYPE_BYTES: + v_bytes = *((const GBytes *const *) src); + return v_bytes ? nm_g_bytes_to_variant_ay(v_bytes) : NULL; case NM_VALUE_TYPE_INT: - /* "int" also does not have a define variant type, because it's not - * clear how many bits we would need. */ + case NM_VALUE_TYPE_UINT: + case NM_VALUE_TYPE_ENUM: + case NM_VALUE_TYPE_FLAGS: + /* These types don't have a defined variant type, because it's not + * clear how many bits we would need or how to handle the type. */ /* fall-through */ + case NM_VALUE_TYPE_NONE: case NM_VALUE_TYPE_UNSPEC: break; } @@ -215,16 +277,24 @@ nm_value_type_get_variant_type(NMValueType value_type) return G_VARIANT_TYPE_INT32; case NM_VALUE_TYPE_INT64: return G_VARIANT_TYPE_INT64; + case NM_VALUE_TYPE_UINT32: + return G_VARIANT_TYPE_UINT32; case NM_VALUE_TYPE_UINT64: return G_VARIANT_TYPE_UINT64; case NM_VALUE_TYPE_STRING: return G_VARIANT_TYPE_STRING; + case NM_VALUE_TYPE_BYTES: + return G_VARIANT_TYPE_BYTESTRING; case NM_VALUE_TYPE_INT: - /* "int" also does not have a define variant type, because it's not - * clear how many bits we would need. */ + case NM_VALUE_TYPE_UINT: + case NM_VALUE_TYPE_ENUM: + case NM_VALUE_TYPE_FLAGS: + /* These types don't have a defined variant type, because it's not + * clear how many bits we would need or how to handle the type. */ /* fall-through */ + case NM_VALUE_TYPE_NONE: case NM_VALUE_TYPE_UNSPEC: break; } @@ -232,7 +302,7 @@ nm_value_type_get_variant_type(NMValueType value_type) return NULL; } - /*****************************************************************************/ +/*****************************************************************************/ #endif /* NM_VALUE_TYPE_DEFINE_FUNCTIONS */ diff --git a/src/libnm-glib-aux/tests/test-shared-general.c b/src/libnm-glib-aux/tests/test-shared-general.c index 4a7b6790..9674f228 100644 --- a/src/libnm-glib-aux/tests/test-shared-general.c +++ b/src/libnm-glib-aux/tests/test-shared-general.c @@ -31,6 +31,31 @@ G_STATIC_ASSERT(4 == _nm_alignof(NMIPAddr)); /*****************************************************************************/ static void +test_nm_static_assert(void) +{ + int v1[NM_STATIC_ASSERT_EXPR_1(1)]; + typeof(NM_STATIC_ASSERT_EXPR_1(1)) v_int; + int * p_int; + + G_STATIC_ASSERT(sizeof(v1) == sizeof(int)); + G_STATIC_ASSERT(NM_STATIC_ASSERT_EXPR_1(1) == 1); + G_STATIC_ASSERT(NM_STATIC_ASSERT_EXPR_1(NM_STATIC_ASSERT_EXPR_1(1)) == 1); + G_STATIC_ASSERT(NM_STATIC_ASSERT_EXPR_1(NM_STATIC_ASSERT_EXPR_1(NM_STATIC_ASSERT_EXPR_1(1))) + == 1); + + g_assert(NM_STATIC_ASSERT_EXPR_1(2) == 1); + + p_int = &v_int; + g_assert(&v_int == p_int); + + (void) NM_STATIC_ASSERT_EXPR_1(2 > 1); + + NM_STATIC_ASSERT_EXPR_VOID(2 > 1); +} + +/*****************************************************************************/ + +static void test_gpid(void) { const int *int_ptr; @@ -390,8 +415,8 @@ test_strv_cmp(void) _strv_cmp_fuzz_input((a1), _l1, &_a1_free_shallow, &_a1_free_deep, &_a1, &_a1x); \ _strv_cmp_fuzz_input((a2), _l2, &_a2_free_shallow, &_a2_free_deep, &_a2, &_a2x); \ \ - _c1 = nm_utils_strv_cmp_n(_a1, _l1, _a2, _l2); \ - _c2 = nm_utils_strv_cmp_n(_a2, _l2, _a1, _l1); \ + _c1 = nm_strv_cmp_n(_a1, _l1, _a2, _l2); \ + _c2 = nm_strv_cmp_n(_a2, _l2, _a1, _l1); \ if (equal) { \ g_assert_cmpint(_c1, ==, 0); \ g_assert_cmpint(_c2, ==, 0); \ @@ -402,8 +427,8 @@ test_strv_cmp(void) \ /* Compare with self. _strv_cmp_fuzz_input() randomly swapped the arguments (_a1 and _a1x). * Either way, the arrays must compare equal to their semantically equal alternative. */ \ - g_assert_cmpint(nm_utils_strv_cmp_n(_a1, _l1, _a1x, _l1), ==, 0); \ - g_assert_cmpint(nm_utils_strv_cmp_n(_a2, _l2, _a2x, _l2), ==, 0); \ + g_assert_cmpint(nm_strv_cmp_n(_a1, _l1, _a1x, _l1), ==, 0); \ + g_assert_cmpint(nm_strv_cmp_n(_a2, _l2, _a2x, _l2), ==, 0); \ \ _strv_cmp_free_deep(_a1_free_deep, _l1); \ _strv_cmp_free_deep(_a2_free_deep, _l2); \ @@ -1006,10 +1031,10 @@ again: else g_assert(!data); - g_assert(nm_utils_strv_cmp_n((const char *const *) strv->pdata, - strv->len, - (const char *const *) strv2->pdata, - strv2->len) + g_assert(nm_strv_cmp_n((const char *const *) strv->pdata, + strv->len, + (const char *const *) strv2->pdata, + strv2->len) == 0); } } @@ -1097,15 +1122,14 @@ test_strv_dup_packed(void) g_assert(NM_PTRARRAY_LEN(strv_src) == strv_len); strv_cpy = - nm_utils_strv_dup_packed(strv_src, - nmtst_get_rand_bool() ? (gssize) strv_len : (gssize) -1); + nm_strv_dup_packed(strv_src, nmtst_get_rand_bool() ? (gssize) strv_len : (gssize) -1); if (strv_len == 0) g_assert(!strv_cpy); else g_assert(strv_cpy); g_assert(NM_PTRARRAY_LEN(strv_cpy) == strv_len); if (strv_cpy) - g_assert(nm_utils_strv_equal(strv_cpy, strv_src)); + g_assert(nm_strv_equal(strv_cpy, strv_src)); } } @@ -1395,6 +1419,7 @@ main(int argc, char **argv) { nmtst_init(&argc, &argv, TRUE); + g_test_add_func("/general/test_nm_static_assert", test_nm_static_assert); g_test_add_func("/general/test_gpid", test_gpid); g_test_add_func("/general/test_monotonic_timestamp", test_monotonic_timestamp); g_test_add_func("/general/test_nmhash", test_nmhash); |