summaryrefslogtreecommitdiff
path: root/shared
diff options
context:
space:
mode:
Diffstat (limited to 'shared')
-rw-r--r--shared/meson.build67
-rw-r--r--shared/nm-glib-aux/nm-c-list.h180
-rw-r--r--shared/nm-glib-aux/nm-dbus-aux.c292
-rw-r--r--shared/nm-glib-aux/nm-dbus-aux.h202
-rw-r--r--shared/nm-glib-aux/nm-dedup-multi.c1065
-rw-r--r--shared/nm-glib-aux/nm-dedup-multi.h407
-rw-r--r--shared/nm-glib-aux/nm-default-glib-i18n-lib.h21
-rw-r--r--shared/nm-glib-aux/nm-default-glib-i18n-prog.h21
-rw-r--r--shared/nm-glib-aux/nm-default-glib.h75
-rw-r--r--shared/nm-glib-aux/nm-enum-utils.c368
-rw-r--r--shared/nm-glib-aux/nm-enum-utils.h32
-rw-r--r--shared/nm-glib-aux/nm-errno.c181
-rw-r--r--shared/nm-glib-aux/nm-errno.h171
-rw-r--r--shared/nm-glib-aux/nm-gassert-patch.h76
-rw-r--r--shared/nm-glib-aux/nm-glib.h707
-rw-r--r--shared/nm-glib-aux/nm-hash-utils.c286
-rw-r--r--shared/nm-glib-aux/nm-hash-utils.h442
-rw-r--r--shared/nm-glib-aux/nm-io-utils.c480
-rw-r--r--shared/nm-glib-aux/nm-io-utils.h58
-rw-r--r--shared/nm-glib-aux/nm-jansson.h30
-rw-r--r--shared/nm-glib-aux/nm-json-aux.c286
-rw-r--r--shared/nm-glib-aux/nm-json-aux.h312
-rw-r--r--shared/nm-glib-aux/nm-keyfile-aux.c373
-rw-r--r--shared/nm-glib-aux/nm-keyfile-aux.h55
-rw-r--r--shared/nm-glib-aux/nm-logging-base.c79
-rw-r--r--shared/nm-glib-aux/nm-logging-base.h28
-rw-r--r--shared/nm-glib-aux/nm-logging-fwd.h308
-rw-r--r--shared/nm-glib-aux/nm-macros-internal.h1815
-rw-r--r--shared/nm-glib-aux/nm-obj.h66
-rw-r--r--shared/nm-glib-aux/nm-random-utils.c148
-rw-r--r--shared/nm-glib-aux/nm-random-utils.h11
-rw-r--r--shared/nm-glib-aux/nm-ref-string.c203
-rw-r--r--shared/nm-glib-aux/nm-ref-string.h79
-rw-r--r--shared/nm-glib-aux/nm-secret-utils.c178
-rw-r--r--shared/nm-glib-aux/nm-secret-utils.h273
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.c5710
-rw-r--r--shared/nm-glib-aux/nm-shared-utils.h2480
-rw-r--r--shared/nm-glib-aux/nm-str-buf.h488
-rw-r--r--shared/nm-glib-aux/nm-time-utils.c328
-rw-r--r--shared/nm-glib-aux/nm-time-utils.h47
-rw-r--r--shared/nm-glib-aux/nm-value-type.h209
-rw-r--r--shared/nm-glib-aux/tests/meson.build35
-rw-r--r--shared/nm-glib-aux/tests/test-json-aux.c165
-rw-r--r--shared/nm-glib-aux/tests/test-shared-general.c1289
-rw-r--r--shared/nm-log-core/nm-logging.c1035
-rw-r--r--shared/nm-log-core/nm-logging.h189
-rw-r--r--shared/nm-log-null/nm-logging-null.c36
-rw-r--r--shared/nm-utils/nm-vpn-editor-plugin-call.h2
48 files changed, 1 insertions, 21387 deletions
diff --git a/shared/meson.build b/shared/meson.build
index fb9d8d38cb..a3c62abfcb 100644
--- a/shared/meson.build
+++ b/shared/meson.build
@@ -106,70 +106,3 @@ libnm_std_aux = static_library(
],
include_directories: top_inc,
)
-
-libnm_glib_aux = static_library(
- 'nm-glib-aux',
- sources: files(
- 'nm-glib-aux/nm-dbus-aux.c',
- 'nm-glib-aux/nm-dedup-multi.c',
- 'nm-glib-aux/nm-enum-utils.c',
- 'nm-glib-aux/nm-errno.c',
- 'nm-glib-aux/nm-hash-utils.c',
- 'nm-glib-aux/nm-io-utils.c',
- 'nm-glib-aux/nm-json-aux.c',
- 'nm-glib-aux/nm-keyfile-aux.c',
- 'nm-glib-aux/nm-logging-base.c',
- 'nm-glib-aux/nm-random-utils.c',
- 'nm-glib-aux/nm-ref-string.c',
- 'nm-glib-aux/nm-secret-utils.c',
- 'nm-glib-aux/nm-shared-utils.c',
- 'nm-glib-aux/nm-time-utils.c',
- ),
- dependencies: glib_nm_default_dep,
- link_with: [
- libc_siphash,
- libnm_std_aux,
- ],
-)
-
-libnm_glib_aux_dep = declare_dependency(
- include_directories: [
- shared_inc,
- top_inc,
- ],
- dependencies: [
- glib_nm_default_dep,
- ],
-)
-
-libnm_glib_aux_dep_link = declare_dependency(
- dependencies: libnm_glib_aux_dep,
- link_with: libnm_glib_aux,
-)
-
-libnm_log_core = static_library(
- 'nm-log-core',
- sources: 'nm-log-core/nm-logging.c',
- dependencies: [
- glib_nm_default_dep,
- libsystemd_dep,
- ],
-)
-
-libnm_log_core_dep = declare_dependency(
- include_directories: shared_inc,
- dependencies: [
- libnm_glib_aux_dep_link,
- ],
- link_with: libnm_log_core,
-)
-
-libnm_log_null = static_library(
- 'nm-log-null',
- sources: 'nm-log-null/nm-logging-null.c',
- dependencies: glib_nm_default_dep,
-)
-
-if enable_tests
- subdir('nm-glib-aux/tests')
-endif
diff --git a/shared/nm-glib-aux/nm-c-list.h b/shared/nm-glib-aux/nm-c-list.h
deleted file mode 100644
index 6dd3ac720f..0000000000
--- a/shared/nm-glib-aux/nm-c-list.h
+++ /dev/null
@@ -1,180 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2014 Red Hat, Inc.
- */
-
-#ifndef __NM_C_LIST_H__
-#define __NM_C_LIST_H__
-
-#include "c-list/src/c-list.h"
-
-/*****************************************************************************/
-
-#define nm_c_list_contains_entry(list, what, member) \
- ({ \
- typeof(what) _what = (what); \
- \
- _what &&c_list_contains(list, &_what->member); \
- })
-
-/*****************************************************************************/
-
-typedef struct {
- CList lst;
- void *data;
-} NMCListElem;
-
-static inline NMCListElem *
-nm_c_list_elem_new_stale(void *data)
-{
- NMCListElem *elem;
-
- elem = g_slice_new(NMCListElem);
- elem->data = data;
- return elem;
-}
-
-static inline gboolean
-nm_c_list_elem_free_full(NMCListElem *elem, GDestroyNotify free_fcn)
-{
- if (!elem)
- return FALSE;
- c_list_unlink_stale(&elem->lst);
- if (free_fcn)
- free_fcn(elem->data);
- g_slice_free(NMCListElem, elem);
- return TRUE;
-}
-
-static inline gboolean
-nm_c_list_elem_free(NMCListElem *elem)
-{
- return nm_c_list_elem_free_full(elem, NULL);
-}
-
-static inline void *
-nm_c_list_elem_free_steal(NMCListElem *elem)
-{
- gpointer data;
-
- if (!elem)
- return NULL;
- data = elem->data;
- nm_c_list_elem_free_full(elem, NULL);
- return data;
-}
-
-static inline void
-nm_c_list_elem_free_all(CList *head, GDestroyNotify free_fcn)
-{
- NMCListElem *elem;
-
- while ((elem = c_list_first_entry(head, NMCListElem, lst)))
- nm_c_list_elem_free_full(elem, free_fcn);
-}
-
-#define nm_c_list_elem_find_first(head, arg, predicate) \
- ({ \
- CList *const _head = (head); \
- NMCListElem *_result = NULL; \
- NMCListElem *_elem; \
- \
- c_list_for_each_entry (_elem, _head, lst) { \
- void *const arg = _elem->data; \
- \
- if (predicate) { \
- _result = _elem; \
- break; \
- } \
- } \
- _result; \
- })
-
-/**
- * nm_c_list_elem_find_first_ptr:
- * @head: the @CList head of a list containing #NMCListElem elements.
- * Note that the head is not itself part of the list.
- * @needle: the needle pointer.
- *
- * Iterates the list and returns the first #NMCListElem with the matching @needle,
- * using pointer equality.
- *
- * Returns: the found list element or %NULL if not found.
- */
-static inline NMCListElem *
-nm_c_list_elem_find_first_ptr(CList *head, gconstpointer needle)
-{
- return nm_c_list_elem_find_first(head, x, x == needle);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_c_list_move_before:
- * @lst: the list element to which @elem will be prepended.
- * @elem: the list element to move.
- *
- * This unlinks @elem from the current list and linkes it before
- * @lst. This is like c_list_link_before(), except that @elem must
- * be initialized and linked. Note that @elem may be linked in @lst
- * or in another list. In both cases it gets moved.
- *
- * Returns: %TRUE if there were any changes. %FALSE if elem was already
- * linked at the right place.
- */
-static inline gboolean
-nm_c_list_move_before(CList *lst, CList *elem)
-{
- nm_assert(lst);
- nm_assert(elem);
-
- if (lst != elem && lst->prev != elem) {
- c_list_unlink_stale(elem);
- c_list_link_before(lst, elem);
- return TRUE;
- }
- return FALSE;
-}
-#define nm_c_list_move_tail(lst, elem) nm_c_list_move_before(lst, elem)
-
-/**
- * nm_c_list_move_after:
- * @lst: the list element to which @elem will be prepended.
- * @elem: the list element to move.
- *
- * This unlinks @elem from the current list and linkes it after
- * @lst. This is like c_list_link_after(), except that @elem must
- * be initialized and linked. Note that @elem may be linked in @lst
- * or in another list. In both cases it gets moved.
- *
- * Returns: %TRUE if there were any changes. %FALSE if elem was already
- * linked at the right place.
- */
-static inline gboolean
-nm_c_list_move_after(CList *lst, CList *elem)
-{
- nm_assert(lst);
- nm_assert(elem);
-
- if (lst != elem && lst->next != elem) {
- c_list_unlink_stale(elem);
- c_list_link_after(lst, elem);
- return TRUE;
- }
- return FALSE;
-}
-#define nm_c_list_move_front(lst, elem) nm_c_list_move_after(lst, elem)
-
-#define nm_c_list_free_all(lst, type, member, destroy_fcn) \
- G_STMT_START \
- { \
- CList *const _lst = (lst); \
- type * _elem; \
- \
- while ((_elem = c_list_first_entry(_lst, type, member))) { \
- destroy_fcn(_elem); \
- } \
- } \
- G_STMT_END
-
-#endif /* __NM_C_LIST_H__ */
diff --git a/shared/nm-glib-aux/nm-dbus-aux.c b/shared/nm-glib-aux/nm-dbus-aux.c
deleted file mode 100644
index ec409ff1fa..0000000000
--- a/shared/nm-glib-aux/nm-dbus-aux.c
+++ /dev/null
@@ -1,292 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2019 Red Hat, Inc.
- */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-dbus-aux.h"
-
-/*****************************************************************************/
-
-static void
-_nm_dbus_connection_call_get_name_owner_cb(GObject *source, GAsyncResult *res, gpointer user_data)
-{
- gs_unref_variant GVariant *ret = NULL;
- gs_free_error GError * error = NULL;
- const char * owner = NULL;
- gpointer orig_user_data;
- NMDBusConnectionCallGetNameOwnerCb callback;
-
- nm_utils_user_data_unpack(user_data, &orig_user_data, &callback);
-
- ret = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &error);
- if (ret)
- g_variant_get(ret, "(&s)", &owner);
-
- callback(owner, error, orig_user_data);
-}
-
-void
-nm_dbus_connection_call_get_name_owner(GDBusConnection * dbus_connection,
- const char * service_name,
- int timeout_msec,
- GCancellable * cancellable,
- NMDBusConnectionCallGetNameOwnerCb callback,
- gpointer user_data)
-{
- nm_assert(callback);
-
- g_dbus_connection_call(dbus_connection,
- DBUS_SERVICE_DBUS,
- DBUS_PATH_DBUS,
- DBUS_INTERFACE_DBUS,
- "GetNameOwner",
- g_variant_new("(s)", service_name),
- G_VARIANT_TYPE("(s)"),
- G_DBUS_CALL_FLAGS_NONE,
- timeout_msec,
- cancellable,
- _nm_dbus_connection_call_get_name_owner_cb,
- nm_utils_user_data_pack(user_data, callback));
-}
-
-/*****************************************************************************/
-
-static void
-_nm_dbus_connection_call_default_cb(GObject *source, GAsyncResult *res, gpointer user_data)
-{
- gs_unref_variant GVariant *ret = NULL;
- gs_free_error GError * error = NULL;
- gpointer orig_user_data;
- NMDBusConnectionCallDefaultCb callback;
-
- nm_utils_user_data_unpack(user_data, &orig_user_data, &callback);
-
- ret = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &error);
-
- nm_assert((!!ret) != (!!error));
-
- callback(ret, error, orig_user_data);
-}
-
-void
-nm_dbus_connection_call_get_all(GDBusConnection * dbus_connection,
- const char * bus_name,
- const char * object_path,
- const char * interface_name,
- int timeout_msec,
- GCancellable * cancellable,
- NMDBusConnectionCallDefaultCb callback,
- gpointer user_data)
-{
- nm_assert(callback);
-
- g_dbus_connection_call(dbus_connection,
- bus_name,
- object_path,
- DBUS_INTERFACE_PROPERTIES,
- "GetAll",
- g_variant_new("(s)", interface_name),
- G_VARIANT_TYPE("(a{sv})"),
- G_DBUS_CALL_FLAGS_NONE,
- timeout_msec,
- cancellable,
- _nm_dbus_connection_call_default_cb,
- nm_utils_user_data_pack(user_data, callback));
-}
-
-void
-nm_dbus_connection_call_set(GDBusConnection * dbus_connection,
- const char * bus_name,
- const char * object_path,
- const char * interface_name,
- const char * property_name,
- GVariant * value,
- int timeout_msec,
- GCancellable * cancellable,
- NMDBusConnectionCallDefaultCb callback,
- gpointer user_data)
-{
- g_dbus_connection_call(dbus_connection,
- bus_name,
- object_path,
- DBUS_INTERFACE_PROPERTIES,
- "Set",
- g_variant_new("(ssv)", interface_name, property_name, value),
- G_VARIANT_TYPE("()"),
- G_DBUS_CALL_FLAGS_NONE,
- timeout_msec,
- cancellable,
- callback ? _nm_dbus_connection_call_default_cb : NULL,
- callback ? nm_utils_user_data_pack(user_data, callback) : NULL);
-}
-
-/*****************************************************************************/
-
-static void
-_nm_dbus_connection_call_get_managed_objects_cb(GObject * source,
- GAsyncResult *res,
- gpointer user_data)
-{
- gs_unref_variant GVariant *ret = NULL;
- gs_unref_variant GVariant *arg = NULL;
- gs_free_error GError * error = NULL;
- gpointer orig_user_data;
- NMDBusConnectionCallDefaultCb callback;
-
- nm_utils_user_data_unpack(user_data, &orig_user_data, &callback);
-
- ret = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), res, &error);
-
- nm_assert((!!ret) != (!!error));
-
- if (ret) {
- nm_assert(g_variant_is_of_type(ret, G_VARIANT_TYPE("(a{oa{sa{sv}}})")));
- arg = g_variant_get_child_value(ret, 0);
- }
-
- callback(arg, error, orig_user_data);
-}
-
-void
-nm_dbus_connection_call_get_managed_objects(GDBusConnection * dbus_connection,
- const char * bus_name,
- const char * object_path,
- GDBusCallFlags flags,
- int timeout_msec,
- GCancellable * cancellable,
- NMDBusConnectionCallDefaultCb callback,
- gpointer user_data)
-{
- nm_assert(callback);
-
- g_dbus_connection_call(dbus_connection,
- bus_name,
- object_path,
- DBUS_INTERFACE_OBJECT_MANAGER,
- "GetManagedObjects",
- NULL,
- G_VARIANT_TYPE("(a{oa{sa{sv}}})"),
- flags,
- timeout_msec,
- cancellable,
- _nm_dbus_connection_call_get_managed_objects_cb,
- nm_utils_user_data_pack(user_data, callback));
-}
-
-/*****************************************************************************/
-
-static void
-_call_finish_cb(GObject * source,
- GAsyncResult *result,
- gpointer user_data,
- gboolean return_void,
- gboolean strip_dbus_error)
-{
- gs_unref_object GTask *task = user_data;
- gs_unref_variant GVariant *ret = NULL;
- GError * error = NULL;
-
- nm_assert(G_IS_DBUS_CONNECTION(source));
- nm_assert(G_IS_TASK(user_data));
-
- ret = g_dbus_connection_call_finish(G_DBUS_CONNECTION(source), result, &error);
- if (!ret) {
- if (strip_dbus_error)
- g_dbus_error_strip_remote_error(error);
- g_task_return_error(task, error);
- return;
- }
-
- if (!return_void)
- g_task_return_pointer(task, g_steal_pointer(&ret), (GDestroyNotify) g_variant_unref);
- else {
- nm_assert(g_variant_is_of_type(ret, G_VARIANT_TYPE("()")));
- g_task_return_boolean(task, TRUE);
- }
-}
-
-/**
- * nm_dbus_connection_call_finish_void_cb:
- *
- * A default callback to pass as callback to g_dbus_connection_call().
- *
- * - user_data must be a GTask, whose reference will be consumed by the
- * callback.
- * - the return GVariant must be a empty tuple "()".
- * - the GTask is returned either with error or TRUE boolean.
- */
-void
-nm_dbus_connection_call_finish_void_cb(GObject *source, GAsyncResult *result, gpointer user_data)
-{
- _call_finish_cb(source, result, user_data, TRUE, FALSE);
-}
-
-/**
- * nm_dbus_connection_call_finish_void_strip_dbus_error_cb:
- *
- * Like nm_dbus_connection_call_finish_void_cb(). The difference
- * is that on error this will first call g_dbus_error_strip_remote_error() on the error.
- */
-void
-nm_dbus_connection_call_finish_void_strip_dbus_error_cb(GObject * source,
- GAsyncResult *result,
- gpointer user_data)
-{
- _call_finish_cb(source, result, user_data, TRUE, TRUE);
-}
-
-/**
- * nm_dbus_connection_call_finish_variant_cb:
- *
- * A default callback to pass as callback to g_dbus_connection_call().
- *
- * - user_data must be a GTask, whose reference will be consumed by the
- * callback.
- * - the GTask is returned either with error or with a pointer containing the GVariant.
- */
-void
-nm_dbus_connection_call_finish_variant_cb(GObject *source, GAsyncResult *result, gpointer user_data)
-{
- _call_finish_cb(source, result, user_data, FALSE, FALSE);
-}
-
-/**
- * nm_dbus_connection_call_finish_variant_strip_dbus_error_cb:
- *
- * Like nm_dbus_connection_call_finish_variant_strip_dbus_error_cb(). The difference
- * is that on error this will first call g_dbus_error_strip_remote_error() on the error.
- */
-void
-nm_dbus_connection_call_finish_variant_strip_dbus_error_cb(GObject * source,
- GAsyncResult *result,
- gpointer user_data)
-{
- _call_finish_cb(source, result, user_data, FALSE, TRUE);
-}
-
-/*****************************************************************************/
-
-gboolean
-_nm_dbus_error_is(GError *error, ...)
-{
- gs_free char *dbus_error = NULL;
- const char * name;
- va_list ap;
-
- dbus_error = g_dbus_error_get_remote_error(error);
- if (!dbus_error)
- return FALSE;
-
- va_start(ap, error);
- while ((name = va_arg(ap, const char *))) {
- if (nm_streq(dbus_error, name)) {
- va_end(ap);
- return TRUE;
- }
- }
- va_end(ap);
-
- return FALSE;
-}
diff --git a/shared/nm-glib-aux/nm-dbus-aux.h b/shared/nm-glib-aux/nm-dbus-aux.h
deleted file mode 100644
index 4e3ae22d82..0000000000
--- a/shared/nm-glib-aux/nm-dbus-aux.h
+++ /dev/null
@@ -1,202 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2019 Red Hat, Inc.
- */
-
-#ifndef __NM_DBUS_AUX_H__
-#define __NM_DBUS_AUX_H__
-
-#include "nm-std-aux/nm-dbus-compat.h"
-
-/*****************************************************************************/
-
-static inline gboolean
-nm_clear_g_dbus_connection_signal(GDBusConnection *dbus_connection, guint *id)
-{
- guint v;
-
- if (id && (v = *id)) {
- *id = 0;
- g_dbus_connection_signal_unsubscribe(dbus_connection, v);
- return TRUE;
- }
- return FALSE;
-}
-
-/*****************************************************************************/
-
-typedef void (*NMDBusConnectionCallDefaultCb)(GVariant *result, GError *error, gpointer user_data);
-
-/*****************************************************************************/
-
-static inline void
-nm_dbus_connection_call_start_service_by_name(GDBusConnection * dbus_connection,
- const char * name,
- 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,
- "StartServiceByName",
- g_variant_new("(su)", name, 0u),
- G_VARIANT_TYPE("(u)"),
- G_DBUS_CALL_FLAGS_NONE,
- timeout_msec,
- cancellable,
- callback,
- user_data);
-}
-
-/*****************************************************************************/
-
-static inline guint
-nm_dbus_connection_signal_subscribe_name_owner_changed(GDBusConnection * dbus_connection,
- const char * service_name,
- GDBusSignalCallback callback,
- gpointer user_data,
- GDestroyNotify user_data_free_func)
-
-{
- return g_dbus_connection_signal_subscribe(dbus_connection,
- DBUS_SERVICE_DBUS,
- DBUS_INTERFACE_DBUS,
- "NameOwnerChanged",
- DBUS_PATH_DBUS,
- service_name,
- G_DBUS_SIGNAL_FLAGS_NONE,
- callback,
- user_data,
- user_data_free_func);
-}
-
-typedef void (*NMDBusConnectionCallGetNameOwnerCb)(const char *name_owner,
- GError * error,
- gpointer user_data);
-
-void nm_dbus_connection_call_get_name_owner(GDBusConnection * dbus_connection,
- const char * service_name,
- int timeout_msec,
- GCancellable * cancellable,
- NMDBusConnectionCallGetNameOwnerCb callback,
- gpointer user_data);
-
-static inline guint
-nm_dbus_connection_signal_subscribe_properties_changed(GDBusConnection * dbus_connection,
- const char * bus_name,
- const char * object_path,
- const char * interface_name,
- GDBusSignalCallback callback,
- gpointer user_data,
- GDestroyNotify user_data_free_func)
-
-{
- nm_assert(bus_name);
-
- /* it seems that using a non-unique name causes problems that we get signals
- * also from unrelated senders. Usually, you are anyway monitoring the name-owner,
- * so you should have the unique name at hand.
- *
- * If not, investigate this, ensure that it works, and lift this restriction. */
- nm_assert(g_dbus_is_unique_name(bus_name));
-
- return g_dbus_connection_signal_subscribe(dbus_connection,
- bus_name,
- DBUS_INTERFACE_PROPERTIES,
- "PropertiesChanged",
- object_path,
- interface_name,
- G_DBUS_SIGNAL_FLAGS_NONE,
- callback,
- user_data,
- user_data_free_func);
-}
-
-void nm_dbus_connection_call_get_all(GDBusConnection * dbus_connection,
- const char * bus_name,
- const char * object_path,
- const char * interface_name,
- int timeout_msec,
- GCancellable * cancellable,
- NMDBusConnectionCallDefaultCb callback,
- gpointer user_data);
-
-void nm_dbus_connection_call_set(GDBusConnection * dbus_connection,
- const char * bus_name,
- const char * object_path,
- const char * interface_name,
- const char * property_name,
- GVariant * value,
- int timeout_msec,
- GCancellable * cancellable,
- NMDBusConnectionCallDefaultCb callback,
- gpointer user_data);
-
-/*****************************************************************************/
-
-static inline guint
-nm_dbus_connection_signal_subscribe_object_manager(GDBusConnection * dbus_connection,
- const char * service_name,
- const char * object_path,
- const char * signal_name,
- GDBusSignalCallback callback,
- gpointer user_data,
- GDestroyNotify user_data_free_func)
-{
- return g_dbus_connection_signal_subscribe(dbus_connection,
- service_name,
- DBUS_INTERFACE_OBJECT_MANAGER,
- signal_name,
- object_path,
- NULL,
- G_DBUS_SIGNAL_FLAGS_NONE,
- callback,
- user_data,
- user_data_free_func);
-}
-
-void nm_dbus_connection_call_get_managed_objects(GDBusConnection * dbus_connection,
- const char * bus_name,
- const char * object_path,
- GDBusCallFlags flags,
- int timeout_msec,
- GCancellable * cancellable,
- NMDBusConnectionCallDefaultCb callback,
- gpointer user_data);
-
-/*****************************************************************************/
-
-void
-nm_dbus_connection_call_finish_void_cb(GObject *source, GAsyncResult *result, gpointer user_data);
-
-void nm_dbus_connection_call_finish_void_strip_dbus_error_cb(GObject * source,
- GAsyncResult *result,
- gpointer user_data);
-
-void nm_dbus_connection_call_finish_variant_cb(GObject * source,
- GAsyncResult *result,
- gpointer user_data);
-
-void nm_dbus_connection_call_finish_variant_strip_dbus_error_cb(GObject * source,
- GAsyncResult *result,
- gpointer user_data);
-
-/*****************************************************************************/
-
-gboolean _nm_dbus_error_is(GError *error, ...) G_GNUC_NULL_TERMINATED;
-
-#define nm_dbus_error_is(error, ...) \
- ({ \
- GError *const _error = (error); \
- \
- _error &&_nm_dbus_error_is(_error, __VA_ARGS__, NULL); \
- })
-
-#define NM_DBUS_ERROR_NAME_UNKNOWN_METHOD "org.freedesktop.DBus.Error.UnknownMethod"
-
-/*****************************************************************************/
-
-#endif /* __NM_DBUS_AUX_H__ */
diff --git a/shared/nm-glib-aux/nm-dedup-multi.c b/shared/nm-glib-aux/nm-dedup-multi.c
deleted file mode 100644
index 99da3b3502..0000000000
--- a/shared/nm-glib-aux/nm-dedup-multi.c
+++ /dev/null
@@ -1,1065 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2017 Red Hat, Inc.
- */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-dedup-multi.h"
-
-#include "nm-hash-utils.h"
-#include "nm-c-list.h"
-
-/*****************************************************************************/
-
-typedef struct {
- /* the stack-allocated lookup entry. It has a compatible
- * memory layout with NMDedupMultiEntry and NMDedupMultiHeadEntry.
- *
- * It is recognizable by having lst_entries_sentinel.next set to NULL.
- * Contrary to the other entries, which have lst_entries.next
- * always non-NULL.
- * */
- CList lst_entries_sentinel;
- const NMDedupMultiObj * obj;
- const NMDedupMultiIdxType *idx_type;
- bool lookup_head;
-} LookupEntry;
-
-struct _NMDedupMultiIndex {
- int ref_count;
- GHashTable *idx_entries;
- GHashTable *idx_objs;
-};
-
-/*****************************************************************************/
-
-static void
-ASSERT_idx_type(const NMDedupMultiIdxType *idx_type)
-{
- nm_assert(idx_type);
-#if NM_MORE_ASSERTS > 10
- nm_assert(idx_type->klass);
- nm_assert(idx_type->klass->idx_obj_id_hash_update);
- nm_assert(idx_type->klass->idx_obj_id_equal);
- nm_assert(!!idx_type->klass->idx_obj_partition_hash_update
- == !!idx_type->klass->idx_obj_partition_equal);
- nm_assert(idx_type->lst_idx_head.next);
-#endif
-}
-
-void
-nm_dedup_multi_idx_type_init(NMDedupMultiIdxType *idx_type, const NMDedupMultiIdxTypeClass *klass)
-{
- nm_assert(idx_type);
- nm_assert(klass);
-
- *idx_type = (NMDedupMultiIdxType){
- .klass = klass,
- .lst_idx_head = C_LIST_INIT(idx_type->lst_idx_head),
- };
-
- ASSERT_idx_type(idx_type);
-}
-
-/*****************************************************************************/
-
-static NMDedupMultiEntry *
-_entry_lookup_obj(const NMDedupMultiIndex * self,
- const NMDedupMultiIdxType *idx_type,
- const NMDedupMultiObj * obj)
-{
- const LookupEntry stack_entry = {
- .obj = obj,
- .idx_type = idx_type,
- .lookup_head = FALSE,
- };
-
- ASSERT_idx_type(idx_type);
- return g_hash_table_lookup(self->idx_entries, &stack_entry);
-}
-
-static NMDedupMultiHeadEntry *
-_entry_lookup_head(const NMDedupMultiIndex * self,
- const NMDedupMultiIdxType *idx_type,
- const NMDedupMultiObj * obj)
-{
- NMDedupMultiHeadEntry *head_entry;
- const LookupEntry stack_entry = {
- .obj = obj,
- .idx_type = idx_type,
- .lookup_head = TRUE,
- };
-
- ASSERT_idx_type(idx_type);
-
- if (!idx_type->klass->idx_obj_partition_equal) {
- if (c_list_is_empty(&idx_type->lst_idx_head))
- head_entry = NULL;
- else {
- nm_assert(c_list_length(&idx_type->lst_idx_head) == 1);
- head_entry = c_list_entry(idx_type->lst_idx_head.next, NMDedupMultiHeadEntry, lst_idx);
- }
- nm_assert(head_entry == g_hash_table_lookup(self->idx_entries, &stack_entry));
- return head_entry;
- }
-
- return g_hash_table_lookup(self->idx_entries, &stack_entry);
-}
-
-static void
-_entry_unpack(const NMDedupMultiEntry * entry,
- const NMDedupMultiIdxType **out_idx_type,
- const NMDedupMultiObj ** out_obj,
- gboolean * out_lookup_head)
-{
- const NMDedupMultiHeadEntry *head_entry;
- const LookupEntry * lookup_entry;
-
- nm_assert(entry);
-
- G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(LookupEntry, lst_entries_sentinel)
- == G_STRUCT_OFFSET(NMDedupMultiEntry, lst_entries));
- G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMDedupMultiEntry, lst_entries)
- == G_STRUCT_OFFSET(NMDedupMultiHeadEntry, lst_entries_head));
- G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMDedupMultiEntry, obj)
- == G_STRUCT_OFFSET(NMDedupMultiHeadEntry, idx_type));
- G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(NMDedupMultiEntry, is_head)
- == G_STRUCT_OFFSET(NMDedupMultiHeadEntry, is_head));
-
- if (!entry->lst_entries.next) {
- /* the entry is stack-allocated by _entry_lookup(). */
- lookup_entry = (LookupEntry *) entry;
- *out_obj = lookup_entry->obj;
- *out_idx_type = lookup_entry->idx_type;
- *out_lookup_head = lookup_entry->lookup_head;
- } else if (entry->is_head) {
- head_entry = (NMDedupMultiHeadEntry *) entry;
- nm_assert(!c_list_is_empty(&head_entry->lst_entries_head));
- *out_obj =
- c_list_entry(head_entry->lst_entries_head.next, NMDedupMultiEntry, lst_entries)->obj;
- *out_idx_type = head_entry->idx_type;
- *out_lookup_head = TRUE;
- } else {
- *out_obj = entry->obj;
- *out_idx_type = entry->head->idx_type;
- *out_lookup_head = FALSE;
- }
-
- nm_assert(NM_IN_SET(*out_lookup_head, FALSE, TRUE));
- ASSERT_idx_type(*out_idx_type);
-
- /* for lookup of the head, we allow to omit object, but only
- * if the idx_type does not partition the objects. Otherwise, we
- * require a obj to compare. */
- nm_assert(!*out_lookup_head || (*out_obj || !(*out_idx_type)->klass->idx_obj_partition_equal));
-
- /* lookup of the object requires always an object. */
- nm_assert(*out_lookup_head || *out_obj);
-}
-
-static guint
-_dict_idx_entries_hash(const NMDedupMultiEntry *entry)
-{
- const NMDedupMultiIdxType *idx_type;
- const NMDedupMultiObj * obj;
- gboolean lookup_head;
- NMHashState h;
-
- _entry_unpack(entry, &idx_type, &obj, &lookup_head);
-
- nm_hash_init(&h, 1914869417u);
- if (idx_type->klass->idx_obj_partition_hash_update) {
- nm_assert(obj);
- idx_type->klass->idx_obj_partition_hash_update(idx_type, obj, &h);
- }
-
- if (!lookup_head)
- idx_type->klass->idx_obj_id_hash_update(idx_type, obj, &h);
-
- nm_hash_update_val(&h, idx_type);
- return nm_hash_complete(&h);
-}
-
-static gboolean
-_dict_idx_entries_equal(const NMDedupMultiEntry *entry_a, const NMDedupMultiEntry *entry_b)
-{
- const NMDedupMultiIdxType *idx_type_a, *idx_type_b;
- const NMDedupMultiObj * obj_a, *obj_b;
- gboolean lookup_head_a, lookup_head_b;
-
- _entry_unpack(entry_a, &idx_type_a, &obj_a, &lookup_head_a);
- _entry_unpack(entry_b, &idx_type_b, &obj_b, &lookup_head_b);
-
- if (idx_type_a != idx_type_b || lookup_head_a != lookup_head_b)
- return FALSE;
- if (!nm_dedup_multi_idx_type_partition_equal(idx_type_a, obj_a, obj_b))
- return FALSE;
- if (!lookup_head_a && !nm_dedup_multi_idx_type_id_equal(idx_type_a, obj_a, obj_b))
- return FALSE;
- return TRUE;
-}
-
-/*****************************************************************************/
-
-static gboolean
-_add(NMDedupMultiIndex * self,
- NMDedupMultiIdxType * idx_type,
- const NMDedupMultiObj * obj,
- NMDedupMultiEntry * entry,
- NMDedupMultiIdxMode mode,
- const NMDedupMultiEntry * entry_order,
- NMDedupMultiHeadEntry * head_existing,
- const NMDedupMultiEntry **out_entry,
- const NMDedupMultiObj ** out_obj_old)
-{
- NMDedupMultiHeadEntry *head_entry;
- const NMDedupMultiObj *obj_new, *obj_old;
- gboolean add_head_entry = FALSE;
-
- nm_assert(self);
- ASSERT_idx_type(idx_type);
- nm_assert(obj);
- nm_assert(NM_IN_SET(mode,
- NM_DEDUP_MULTI_IDX_MODE_PREPEND,
- NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
- NM_DEDUP_MULTI_IDX_MODE_APPEND,
- NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE));
- nm_assert(!head_existing || head_existing->idx_type == idx_type);
- nm_assert(({
- const NMDedupMultiHeadEntry *_h;
- gboolean _ok = TRUE;
- if (head_existing) {
- _h = nm_dedup_multi_index_lookup_head(self, idx_type, obj);
- if (head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING)
- _ok = (_h == NULL);
- else
- _ok = (_h == head_existing);
- }
- _ok;
- }));
-
- if (entry) {
- gboolean changed = FALSE;
-
- nm_dedup_multi_entry_set_dirty(entry, FALSE);
-
- nm_assert(!head_existing || entry->head == head_existing);
- nm_assert(!entry_order || entry_order->head == entry->head);
- nm_assert(!entry_order || c_list_contains(&entry->lst_entries, &entry_order->lst_entries));
- nm_assert(!entry_order || c_list_contains(&entry_order->lst_entries, &entry->lst_entries));
-
- switch (mode) {
- case NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE:
- if (entry_order) {
- if (nm_c_list_move_before((CList *) &entry_order->lst_entries, &entry->lst_entries))
- changed = TRUE;
- } else {
- if (nm_c_list_move_front((CList *) &entry->head->lst_entries_head,
- &entry->lst_entries))
- changed = TRUE;
- }
- break;
- case NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE:
- if (entry_order) {
- if (nm_c_list_move_after((CList *) &entry_order->lst_entries, &entry->lst_entries))
- changed = TRUE;
- } else {
- if (nm_c_list_move_tail((CList *) &entry->head->lst_entries_head,
- &entry->lst_entries))
- changed = TRUE;
- }
- break;
- case NM_DEDUP_MULTI_IDX_MODE_PREPEND:
- case NM_DEDUP_MULTI_IDX_MODE_APPEND:
- break;
- };
-
- nm_assert(obj->klass == ((const NMDedupMultiObj *) entry->obj)->klass);
- if (obj == entry->obj || obj->klass->obj_full_equal(obj, entry->obj)) {
- NM_SET_OUT(out_entry, entry);
- NM_SET_OUT(out_obj_old, nm_dedup_multi_obj_ref(entry->obj));
- return changed;
- }
-
- obj_new = nm_dedup_multi_index_obj_intern(self, obj);
-
- obj_old = entry->obj;
- entry->obj = obj_new;
-
- NM_SET_OUT(out_entry, entry);
- if (out_obj_old)
- *out_obj_old = obj_old;
- else
- nm_dedup_multi_obj_unref(obj_old);
- return TRUE;
- }
-
- if (idx_type->klass->idx_obj_partitionable
- && !idx_type->klass->idx_obj_partitionable(idx_type, obj)) {
- /* this object cannot be partitioned by this idx_type. */
- nm_assert(!head_existing || head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING);
- NM_SET_OUT(out_entry, NULL);
- NM_SET_OUT(out_obj_old, NULL);
- return FALSE;
- }
-
- obj_new = nm_dedup_multi_index_obj_intern(self, obj);
-
- if (!head_existing)
- head_entry = _entry_lookup_head(self, idx_type, obj_new);
- else if (head_existing == NM_DEDUP_MULTI_HEAD_ENTRY_MISSING)
- head_entry = NULL;
- else
- head_entry = head_existing;
-
- if (!head_entry) {
- head_entry = g_slice_new0(NMDedupMultiHeadEntry);
- head_entry->is_head = TRUE;
- head_entry->idx_type = idx_type;
- c_list_init(&head_entry->lst_entries_head);
- c_list_link_tail(&idx_type->lst_idx_head, &head_entry->lst_idx);
- add_head_entry = TRUE;
- } else
- nm_assert(c_list_contains(&idx_type->lst_idx_head, &head_entry->lst_idx));
-
- if (entry_order) {
- nm_assert(!add_head_entry);
- nm_assert(entry_order->head == head_entry);
- nm_assert(c_list_contains(&head_entry->lst_entries_head, &entry_order->lst_entries));
- nm_assert(c_list_contains(&entry_order->lst_entries, &head_entry->lst_entries_head));
- }
-
- entry = g_slice_new0(NMDedupMultiEntry);
- entry->obj = obj_new;
- entry->head = head_entry;
-
- switch (mode) {
- case NM_DEDUP_MULTI_IDX_MODE_PREPEND:
- case NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE:
- if (entry_order)
- c_list_link_before((CList *) &entry_order->lst_entries, &entry->lst_entries);
- else
- c_list_link_front(&head_entry->lst_entries_head, &entry->lst_entries);
- break;
- default:
- if (entry_order)
- c_list_link_after((CList *) &entry_order->lst_entries, &entry->lst_entries);
- else
- c_list_link_tail(&head_entry->lst_entries_head, &entry->lst_entries);
- break;
- };
-
- idx_type->len++;
- head_entry->len++;
-
- if (add_head_entry && !g_hash_table_add(self->idx_entries, head_entry))
- nm_assert_not_reached();
-
- if (!g_hash_table_add(self->idx_entries, entry))
- nm_assert_not_reached();
-
- NM_SET_OUT(out_entry, entry);
- NM_SET_OUT(out_obj_old, NULL);
- return TRUE;
-}
-
-gboolean
-nm_dedup_multi_index_add(NMDedupMultiIndex * self,
- NMDedupMultiIdxType * idx_type,
- /*const NMDedupMultiObj * */ gconstpointer obj,
- NMDedupMultiIdxMode mode,
- const NMDedupMultiEntry ** out_entry,
- /* const NMDedupMultiObj ** */ gpointer out_obj_old)
-{
- NMDedupMultiEntry *entry;
-
- g_return_val_if_fail(self, FALSE);
- g_return_val_if_fail(idx_type, FALSE);
- g_return_val_if_fail(obj, FALSE);
- g_return_val_if_fail(NM_IN_SET(mode,
- NM_DEDUP_MULTI_IDX_MODE_PREPEND,
- NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
- NM_DEDUP_MULTI_IDX_MODE_APPEND,
- NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE),
- FALSE);
-
- entry = _entry_lookup_obj(self, idx_type, obj);
- return _add(self, idx_type, obj, entry, mode, NULL, NULL, out_entry, out_obj_old);
-}
-
-/* nm_dedup_multi_index_add_full:
- * @self: the index instance.
- * @idx_type: the index handle for storing @obj.
- * @obj: the NMDedupMultiObj instance to add.
- * @mode: whether to append or prepend the new item. If @entry_order is given,
- * the entry will be sorted after/before, instead of appending/prepending to
- * the entire list. If a comparable object is already tracked, then it may
- * still be resorted by specifying one of the "FORCE" modes.
- * @entry_order: if not NULL, the new entry will be sorted before or after @entry_order.
- * If given, @entry_order MUST be tracked by @self, and the object it points to MUST
- * be in the same partition tracked by @idx_type. That is, they must have the same
- * head_entry and it means, you must ensure that @entry_order and the created/modified
- * entry will share the same head.
- * @entry_existing: if not NULL, it safes a hash lookup of the entry where the
- * object will be placed in. You can omit this, and it will be automatically
- * detected (at the expense of an additional hash lookup).
- * Basically, this is the result of nm_dedup_multi_index_lookup_obj(),
- * with the peculiarity that if you know that @obj is not yet tracked,
- * you may specify %NM_DEDUP_MULTI_ENTRY_MISSING.
- * @head_existing: an optional argument to safe a lookup for the head. If specified,
- * it must be identical to nm_dedup_multi_index_lookup_head(), with the peculiarity
- * that if the head is not yet tracked, you may specify %NM_DEDUP_MULTI_HEAD_ENTRY_MISSING
- * @out_entry: if give, return the added entry. This entry may have already exists (update)
- * or be newly created. If @obj is not partitionable according to @idx_type, @obj
- * is not to be added and it returns %NULL.
- * @out_obj_old: if given, return the previously contained object. It only
- * returns a object, if a matching entry was tracked previously, not if a
- * new entry was created. Note that when passing @out_obj_old you obtain a reference
- * to the boxed object and MUST return it with nm_dedup_multi_obj_unref().
- *
- * Adds and object to the index.
- *
- * Return: %TRUE if anything changed, %FALSE if nothing changed.
- */
-gboolean
-nm_dedup_multi_index_add_full(NMDedupMultiIndex * self,
- NMDedupMultiIdxType * idx_type,
- /*const NMDedupMultiObj * */ gconstpointer obj,
- NMDedupMultiIdxMode mode,
- const NMDedupMultiEntry * entry_order,
- const NMDedupMultiEntry * entry_existing,
- const NMDedupMultiHeadEntry * head_existing,
- const NMDedupMultiEntry ** out_entry,
- /* const NMDedupMultiObj ** */ gpointer out_obj_old)
-{
- NMDedupMultiEntry *entry;
-
- g_return_val_if_fail(self, FALSE);
- g_return_val_if_fail(idx_type, FALSE);
- g_return_val_if_fail(obj, FALSE);
- g_return_val_if_fail(NM_IN_SET(mode,
- NM_DEDUP_MULTI_IDX_MODE_PREPEND,
- NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
- NM_DEDUP_MULTI_IDX_MODE_APPEND,
- NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE),
- FALSE);
-
- if (entry_existing == NULL)
- entry = _entry_lookup_obj(self, idx_type, obj);
- else if (entry_existing == NM_DEDUP_MULTI_ENTRY_MISSING) {
- nm_assert(!_entry_lookup_obj(self, idx_type, obj));
- entry = NULL;
- } else {
- nm_assert(entry_existing == _entry_lookup_obj(self, idx_type, obj));
- entry = (NMDedupMultiEntry *) entry_existing;
- }
- return _add(self,
- idx_type,
- obj,
- entry,
- mode,
- entry_order,
- (NMDedupMultiHeadEntry *) head_existing,
- out_entry,
- out_obj_old);
-}
-
-/*****************************************************************************/
-
-static void
-_remove_entry(NMDedupMultiIndex *self, NMDedupMultiEntry *entry, gboolean *out_head_entry_removed)
-{
- const NMDedupMultiObj *obj;
- NMDedupMultiHeadEntry *head_entry;
- NMDedupMultiIdxType * idx_type;
-
- nm_assert(self);
- nm_assert(entry);
- nm_assert(entry->obj);
- nm_assert(entry->head);
- nm_assert(!c_list_is_empty(&entry->lst_entries));
- nm_assert(g_hash_table_lookup(self->idx_entries, entry) == entry);
-
- head_entry = (NMDedupMultiHeadEntry *) entry->head;
- obj = entry->obj;
-
- nm_assert(head_entry);
- nm_assert(head_entry->len > 0);
- nm_assert(g_hash_table_lookup(self->idx_entries, head_entry) == head_entry);
-
- idx_type = (NMDedupMultiIdxType *) head_entry->idx_type;
- ASSERT_idx_type(idx_type);
-
- nm_assert(idx_type->len >= head_entry->len);
- if (--head_entry->len > 0) {
- nm_assert(idx_type->len > 1);
- idx_type->len--;
- head_entry = NULL;
- }
-
- NM_SET_OUT(out_head_entry_removed, head_entry != NULL);
-
- if (!g_hash_table_remove(self->idx_entries, entry))
- nm_assert_not_reached();
-
- if (head_entry && !g_hash_table_remove(self->idx_entries, head_entry))
- nm_assert_not_reached();
-
- c_list_unlink_stale(&entry->lst_entries);
- g_slice_free(NMDedupMultiEntry, entry);
-
- if (head_entry) {
- nm_assert(c_list_is_empty(&head_entry->lst_entries_head));
- c_list_unlink_stale(&head_entry->lst_idx);
- g_slice_free(NMDedupMultiHeadEntry, head_entry);
- }
-
- nm_dedup_multi_obj_unref(obj);
-}
-
-static guint
-_remove_head(NMDedupMultiIndex * self,
- NMDedupMultiHeadEntry *head_entry,
- gboolean remove_all /* otherwise just dirty ones */,
- gboolean mark_survivors_dirty)
-{
- guint n;
- gboolean head_entry_removed;
- CList * iter_entry, *iter_entry_safe;
-
- nm_assert(self);
- nm_assert(head_entry);
- nm_assert(head_entry->len > 0);
- nm_assert(head_entry->len == c_list_length(&head_entry->lst_entries_head));
- nm_assert(g_hash_table_lookup(self->idx_entries, head_entry) == head_entry);
-
- n = 0;
- c_list_for_each_safe (iter_entry, iter_entry_safe, &head_entry->lst_entries_head) {
- NMDedupMultiEntry *entry;
-
- entry = c_list_entry(iter_entry, NMDedupMultiEntry, lst_entries);
- if (remove_all || entry->dirty) {
- _remove_entry(self, entry, &head_entry_removed);
- n++;
- if (head_entry_removed)
- break;
- } else if (mark_survivors_dirty)
- nm_dedup_multi_entry_set_dirty(entry, TRUE);
- }
-
- return n;
-}
-
-static guint
-_remove_idx_entry(NMDedupMultiIndex * self,
- NMDedupMultiIdxType *idx_type,
- gboolean remove_all /* otherwise just dirty ones */,
- gboolean mark_survivors_dirty)
-{
- guint n;
- CList *iter_idx, *iter_idx_safe;
-
- nm_assert(self);
- ASSERT_idx_type(idx_type);
-
- n = 0;
- c_list_for_each_safe (iter_idx, iter_idx_safe, &idx_type->lst_idx_head) {
- n += _remove_head(self,
- c_list_entry(iter_idx, NMDedupMultiHeadEntry, lst_idx),
- remove_all,
- mark_survivors_dirty);
- }
- return n;
-}
-
-guint
-nm_dedup_multi_index_remove_entry(NMDedupMultiIndex *self, gconstpointer entry)
-{
- g_return_val_if_fail(self, 0);
-
- nm_assert(entry);
-
- if (!((NMDedupMultiEntry *) entry)->is_head) {
- _remove_entry(self, (NMDedupMultiEntry *) entry, NULL);
- return 1;
- }
- return _remove_head(self, (NMDedupMultiHeadEntry *) entry, TRUE, FALSE);
-}
-
-guint
-nm_dedup_multi_index_remove_obj(NMDedupMultiIndex * self,
- NMDedupMultiIdxType * idx_type,
- /*const NMDedupMultiObj * */ gconstpointer obj,
- /*const NMDedupMultiObj ** */ gconstpointer *out_obj)
-{
- const NMDedupMultiEntry *entry;
-
- entry = nm_dedup_multi_index_lookup_obj(self, idx_type, obj);
- if (!entry) {
- NM_SET_OUT(out_obj, NULL);
- return 0;
- }
-
- /* since we are about to remove the object, we obviously pass
- * a reference to @out_obj, the caller MUST unref the object,
- * if he chooses to provide @out_obj. */
- NM_SET_OUT(out_obj, nm_dedup_multi_obj_ref(entry->obj));
-
- _remove_entry(self, (NMDedupMultiEntry *) entry, NULL);
- return 1;
-}
-
-guint
-nm_dedup_multi_index_remove_head(NMDedupMultiIndex * self,
- NMDedupMultiIdxType * idx_type,
- /*const NMDedupMultiObj * */ gconstpointer obj)
-{
- const NMDedupMultiHeadEntry *entry;
-
- entry = nm_dedup_multi_index_lookup_head(self, idx_type, obj);
- return entry ? _remove_head(self, (NMDedupMultiHeadEntry *) entry, TRUE, FALSE) : 0;
-}
-
-guint
-nm_dedup_multi_index_remove_idx(NMDedupMultiIndex *self, NMDedupMultiIdxType *idx_type)
-{
- g_return_val_if_fail(self, 0);
- g_return_val_if_fail(idx_type, 0);
-
- return _remove_idx_entry(self, idx_type, TRUE, FALSE);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_dedup_multi_index_lookup_obj:
- * @self: the index cache
- * @idx_type: the lookup index type
- * @obj: the object to lookup. This means the match is performed
- * according to NMDedupMultiIdxTypeClass's idx_obj_id_equal()
- * of @idx_type.
- *
- * Returns: the cache entry or %NULL if the entry wasn't found.
- */
-const NMDedupMultiEntry *
-nm_dedup_multi_index_lookup_obj(const NMDedupMultiIndex * self,
- const NMDedupMultiIdxType * idx_type,
- /*const NMDedupMultiObj * */ gconstpointer obj)
-{
- g_return_val_if_fail(self, FALSE);
- g_return_val_if_fail(idx_type, FALSE);
- g_return_val_if_fail(obj, FALSE);
-
- nm_assert(idx_type && idx_type->klass);
- return _entry_lookup_obj(self, idx_type, obj);
-}
-
-/**
- * nm_dedup_multi_index_lookup_head:
- * @self: the index cache
- * @idx_type: the lookup index type
- * @obj: the object to lookup, of type "const NMDedupMultiObj *".
- * Depending on the idx_type, you *must* also provide a selector
- * object, even when looking up the list head. That is, because
- * the idx_type implementation may choose to partition the objects
- * in distinct list, so you need a selector object to know which
- * list head to lookup.
- *
- * Returns: the cache entry or %NULL if the entry wasn't found.
- */
-const NMDedupMultiHeadEntry *
-nm_dedup_multi_index_lookup_head(const NMDedupMultiIndex * self,
- const NMDedupMultiIdxType * idx_type,
- /*const NMDedupMultiObj * */ gconstpointer obj)
-{
- g_return_val_if_fail(self, FALSE);
- g_return_val_if_fail(idx_type, FALSE);
-
- return _entry_lookup_head(self, idx_type, obj);
-}
-
-/*****************************************************************************/
-
-void
-nm_dedup_multi_index_dirty_set_head(NMDedupMultiIndex * self,
- const NMDedupMultiIdxType * idx_type,
- /*const NMDedupMultiObj * */ gconstpointer obj)
-{
- NMDedupMultiHeadEntry *head_entry;
- CList * iter_entry;
-
- g_return_if_fail(self);
- g_return_if_fail(idx_type);
-
- head_entry = _entry_lookup_head(self, idx_type, obj);
- if (!head_entry)
- return;
-
- c_list_for_each (iter_entry, &head_entry->lst_entries_head) {
- NMDedupMultiEntry *entry;
-
- entry = c_list_entry(iter_entry, NMDedupMultiEntry, lst_entries);
- nm_dedup_multi_entry_set_dirty(entry, TRUE);
- }
-}
-
-void
-nm_dedup_multi_index_dirty_set_idx(NMDedupMultiIndex *self, const NMDedupMultiIdxType *idx_type)
-{
- CList *iter_idx, *iter_entry;
-
- g_return_if_fail(self);
- g_return_if_fail(idx_type);
-
- c_list_for_each (iter_idx, &idx_type->lst_idx_head) {
- NMDedupMultiHeadEntry *head_entry;
-
- head_entry = c_list_entry(iter_idx, NMDedupMultiHeadEntry, lst_idx);
- c_list_for_each (iter_entry, &head_entry->lst_entries_head) {
- NMDedupMultiEntry *entry;
-
- entry = c_list_entry(iter_entry, NMDedupMultiEntry, lst_entries);
- nm_dedup_multi_entry_set_dirty(entry, TRUE);
- }
- }
-}
-
-/**
- * nm_dedup_multi_index_dirty_remove_idx:
- * @self: the index instance
- * @idx_type: the index-type to select the objects.
- * @mark_survivors_dirty: while the function removes all entries that are
- * marked as dirty, if @set_dirty is true, the surviving objects
- * will be marked dirty right away.
- *
- * Deletes all entries for @idx_type that are marked dirty. Only
- * non-dirty objects survive. If @mark_survivors_dirty is set to TRUE, the survivors
- * are marked as dirty right away.
- *
- * Returns: number of deleted entries.
- */
-guint
-nm_dedup_multi_index_dirty_remove_idx(NMDedupMultiIndex * self,
- NMDedupMultiIdxType *idx_type,
- gboolean mark_survivors_dirty)
-{
- g_return_val_if_fail(self, 0);
- g_return_val_if_fail(idx_type, 0);
-
- return _remove_idx_entry(self, idx_type, FALSE, mark_survivors_dirty);
-}
-
-/*****************************************************************************/
-
-static guint
-_dict_idx_objs_hash(const NMDedupMultiObj *obj)
-{
- NMHashState h;
-
- nm_hash_init(&h, 1748638583u);
- obj->klass->obj_full_hash_update(obj, &h);
- return nm_hash_complete(&h);
-}
-
-static gboolean
-_dict_idx_objs_equal(const NMDedupMultiObj *obj_a, const NMDedupMultiObj *obj_b)
-{
- return obj_a == obj_b
- || (obj_a->klass == obj_b->klass && obj_a->klass->obj_full_equal(obj_a, obj_b));
-}
-
-void
-nm_dedup_multi_index_obj_release(NMDedupMultiIndex * self,
- /* const NMDedupMultiObj * */ gconstpointer obj)
-{
- nm_assert(self);
- nm_assert(obj);
- nm_assert(g_hash_table_lookup(self->idx_objs, obj) == obj);
- nm_assert(((const NMDedupMultiObj *) obj)->_multi_idx == self);
-
- ((NMDedupMultiObj *) obj)->_multi_idx = NULL;
- if (!g_hash_table_remove(self->idx_objs, obj))
- nm_assert_not_reached();
-}
-
-gconstpointer
-nm_dedup_multi_index_obj_find(NMDedupMultiIndex * self,
- /* const NMDedupMultiObj * */ gconstpointer obj)
-{
- g_return_val_if_fail(self, NULL);
- g_return_val_if_fail(obj, NULL);
-
- return g_hash_table_lookup(self->idx_objs, obj);
-}
-
-gconstpointer
-nm_dedup_multi_index_obj_intern(NMDedupMultiIndex * self,
- /* const NMDedupMultiObj * */ gconstpointer obj)
-{
- const NMDedupMultiObj *obj_new = obj;
- const NMDedupMultiObj *obj_old;
-
- nm_assert(self);
- nm_assert(obj_new);
-
- if (obj_new->_multi_idx == self) {
- nm_assert(g_hash_table_lookup(self->idx_objs, obj_new) == obj_new);
- nm_dedup_multi_obj_ref(obj_new);
- return obj_new;
- }
-
- obj_old = g_hash_table_lookup(self->idx_objs, obj_new);
- nm_assert(obj_old != obj_new);
-
- if (obj_old) {
- nm_assert(obj_old->_multi_idx == self);
- nm_dedup_multi_obj_ref(obj_old);
- return obj_old;
- }
-
- if (nm_dedup_multi_obj_needs_clone(obj_new))
- obj_new = nm_dedup_multi_obj_clone(obj_new);
- else
- obj_new = nm_dedup_multi_obj_ref(obj_new);
-
- nm_assert(obj_new);
- nm_assert(!obj_new->_multi_idx);
-
- if (!g_hash_table_add(self->idx_objs, (gpointer) obj_new))
- nm_assert_not_reached();
-
- ((NMDedupMultiObj *) obj_new)->_multi_idx = self;
- return obj_new;
-}
-
-void
-nm_dedup_multi_obj_unref(const NMDedupMultiObj *obj)
-{
- if (obj) {
- nm_assert(obj->_ref_count > 0);
- nm_assert(obj->_ref_count != NM_OBJ_REF_COUNT_STACKINIT);
-
-again:
- if (--(((NMDedupMultiObj *) obj)->_ref_count) <= 0) {
- if (obj->_multi_idx) {
- /* restore the ref-count to 1 and release the object first
- * from the index. Then, retry again to unref. */
- ((NMDedupMultiObj *) obj)->_ref_count++;
- nm_dedup_multi_index_obj_release(obj->_multi_idx, obj);
- nm_assert(obj->_ref_count == 1);
- nm_assert(!obj->_multi_idx);
- goto again;
- }
-
- obj->klass->obj_destroy((NMDedupMultiObj *) obj);
- }
- }
-}
-
-gboolean
-nm_dedup_multi_obj_needs_clone(const NMDedupMultiObj *obj)
-{
- nm_assert(obj);
-
- if (obj->_multi_idx || obj->_ref_count == NM_OBJ_REF_COUNT_STACKINIT)
- return TRUE;
-
- if (obj->klass->obj_needs_clone && obj->klass->obj_needs_clone(obj))
- return TRUE;
-
- return FALSE;
-}
-
-const NMDedupMultiObj *
-nm_dedup_multi_obj_clone(const NMDedupMultiObj *obj)
-{
- const NMDedupMultiObj *o;
-
- nm_assert(obj);
-
- o = obj->klass->obj_clone(obj);
- nm_assert(o);
- nm_assert(o->_ref_count == 1);
- return o;
-}
-
-gconstpointer *
-nm_dedup_multi_objs_to_array_head(const NMDedupMultiHeadEntry * head_entry,
- NMDedupMultiFcnSelectPredicate predicate,
- gpointer user_data,
- guint * out_len)
-{
- gconstpointer *result;
- CList * iter;
- guint i;
-
- if (!head_entry) {
- NM_SET_OUT(out_len, 0);
- return NULL;
- }
-
- result = g_new(gconstpointer, head_entry->len + 1);
- i = 0;
- c_list_for_each (iter, &head_entry->lst_entries_head) {
- const NMDedupMultiObj *obj = c_list_entry(iter, NMDedupMultiEntry, lst_entries)->obj;
-
- if (!predicate || predicate(obj, user_data)) {
- nm_assert(i < head_entry->len);
- result[i++] = obj;
- }
- }
-
- if (i == 0) {
- g_free(result);
- NM_SET_OUT(out_len, 0);
- return NULL;
- }
-
- nm_assert(i <= head_entry->len);
- NM_SET_OUT(out_len, i);
- result[i++] = NULL;
- return result;
-}
-
-GPtrArray *
-nm_dedup_multi_objs_to_ptr_array_head(const NMDedupMultiHeadEntry * head_entry,
- NMDedupMultiFcnSelectPredicate predicate,
- gpointer user_data)
-{
- GPtrArray *result;
- CList * iter;
-
- if (!head_entry)
- return NULL;
-
- result = g_ptr_array_new_full(head_entry->len, (GDestroyNotify) nm_dedup_multi_obj_unref);
- c_list_for_each (iter, &head_entry->lst_entries_head) {
- const NMDedupMultiObj *obj = c_list_entry(iter, NMDedupMultiEntry, lst_entries)->obj;
-
- if (!predicate || predicate(obj, user_data))
- g_ptr_array_add(result, (gpointer) nm_dedup_multi_obj_ref(obj));
- }
-
- if (result->len == 0) {
- g_ptr_array_unref(result);
- return NULL;
- }
- return result;
-}
-
-/**
- * nm_dedup_multi_entry_reorder:
- * @entry: the entry to reorder. It must not be NULL (and tracked in an index).
- * @entry_order: (allow-none): an optional other entry. It MUST be in the same
- * list as entry. If given, @entry will be ordered after/before @entry_order.
- * If left at %NULL, @entry will be moved to the front/end of the list.
- * @order_after: if @entry_order is given, %TRUE means to move @entry after
- * @entry_order (otherwise before).
- * If @entry_order is %NULL, %TRUE means to move @entry to the tail of the list
- * (otherwise the beginning). Note that "tail of the list" here means that @entry
- * will be linked before the head of the circular list.
- *
- * Returns: %TRUE, if anything was changed. Otherwise, @entry was already at the
- * right place and nothing was done.
- */
-gboolean
-nm_dedup_multi_entry_reorder(const NMDedupMultiEntry *entry,
- const NMDedupMultiEntry *entry_order,
- gboolean order_after)
-{
- nm_assert(entry);
-
- if (!entry_order) {
- const NMDedupMultiHeadEntry *head_entry = entry->head;
-
- if (order_after) {
- if (nm_c_list_move_tail((CList *) &head_entry->lst_entries_head,
- (CList *) &entry->lst_entries))
- return TRUE;
- } else {
- if (nm_c_list_move_front((CList *) &head_entry->lst_entries_head,
- (CList *) &entry->lst_entries))
- return TRUE;
- }
- } else {
- if (order_after) {
- if (nm_c_list_move_after((CList *) &entry_order->lst_entries,
- (CList *) &entry->lst_entries))
- return TRUE;
- } else {
- if (nm_c_list_move_before((CList *) &entry_order->lst_entries,
- (CList *) &entry->lst_entries))
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/*****************************************************************************/
-
-NMDedupMultiIndex *
-nm_dedup_multi_index_new(void)
-{
- NMDedupMultiIndex *self;
-
- self = g_slice_new0(NMDedupMultiIndex);
- self->ref_count = 1;
- self->idx_entries =
- g_hash_table_new((GHashFunc) _dict_idx_entries_hash, (GEqualFunc) _dict_idx_entries_equal);
- self->idx_objs =
- g_hash_table_new((GHashFunc) _dict_idx_objs_hash, (GEqualFunc) _dict_idx_objs_equal);
- return self;
-}
-
-NMDedupMultiIndex *
-nm_dedup_multi_index_ref(NMDedupMultiIndex *self)
-{
- g_return_val_if_fail(self, NULL);
- g_return_val_if_fail(self->ref_count > 0, NULL);
-
- self->ref_count++;
- return self;
-}
-
-NMDedupMultiIndex *
-nm_dedup_multi_index_unref(NMDedupMultiIndex *self)
-{
- GHashTableIter iter;
- const NMDedupMultiIdxType *idx_type;
- NMDedupMultiEntry * entry;
- const NMDedupMultiObj * obj;
-
- g_return_val_if_fail(self, NULL);
- g_return_val_if_fail(self->ref_count > 0, NULL);
-
- if (--self->ref_count > 0)
- return NULL;
-
-more:
- g_hash_table_iter_init(&iter, self->idx_entries);
- while (g_hash_table_iter_next(&iter, (gpointer *) &entry, NULL)) {
- if (entry->is_head)
- idx_type = ((NMDedupMultiHeadEntry *) entry)->idx_type;
- else
- idx_type = entry->head->idx_type;
- _remove_idx_entry(self, (NMDedupMultiIdxType *) idx_type, TRUE, FALSE);
- goto more;
- }
-
- nm_assert(g_hash_table_size(self->idx_entries) == 0);
-
- g_hash_table_iter_init(&iter, self->idx_objs);
- while (g_hash_table_iter_next(&iter, (gpointer *) &obj, NULL)) {
- nm_assert(obj->_multi_idx == self);
- ((NMDedupMultiObj *) obj)->_multi_idx = NULL;
- }
- g_hash_table_remove_all(self->idx_objs);
-
- g_hash_table_unref(self->idx_entries);
- g_hash_table_unref(self->idx_objs);
-
- g_slice_free(NMDedupMultiIndex, self);
- return NULL;
-}
diff --git a/shared/nm-glib-aux/nm-dedup-multi.h b/shared/nm-glib-aux/nm-dedup-multi.h
deleted file mode 100644
index 1c0761bf1e..0000000000
--- a/shared/nm-glib-aux/nm-dedup-multi.h
+++ /dev/null
@@ -1,407 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2017 Red Hat, Inc.
- */
-
-#ifndef __NM_DEDUP_MULTI_H__
-#define __NM_DEDUP_MULTI_H__
-
-#include "nm-obj.h"
-#include "nm-std-aux/c-list-util.h"
-
-/*****************************************************************************/
-
-struct _NMHashState;
-
-typedef struct _NMDedupMultiObj NMDedupMultiObj;
-typedef struct _NMDedupMultiObjClass NMDedupMultiObjClass;
-typedef struct _NMDedupMultiIdxType NMDedupMultiIdxType;
-typedef struct _NMDedupMultiIdxTypeClass NMDedupMultiIdxTypeClass;
-typedef struct _NMDedupMultiEntry NMDedupMultiEntry;
-typedef struct _NMDedupMultiHeadEntry NMDedupMultiHeadEntry;
-typedef struct _NMDedupMultiIndex NMDedupMultiIndex;
-
-typedef enum _NMDedupMultiIdxMode {
- NM_DEDUP_MULTI_IDX_MODE_PREPEND,
-
- NM_DEDUP_MULTI_IDX_MODE_PREPEND_FORCE,
-
- /* append new objects to the end of the list.
- * If the object is already in the cache, don't move it. */
- NM_DEDUP_MULTI_IDX_MODE_APPEND,
-
- /* like NM_DEDUP_MULTI_IDX_MODE_APPEND, but if the object
- * is already in the cache, move it to the end. */
- NM_DEDUP_MULTI_IDX_MODE_APPEND_FORCE,
-} NMDedupMultiIdxMode;
-
-/*****************************************************************************/
-
-struct _NMDedupMultiObj {
- union {
- NMObjBaseInst parent;
- const NMDedupMultiObjClass *klass;
- };
- NMDedupMultiIndex *_multi_idx;
- guint _ref_count;
-};
-
-struct _NMDedupMultiObjClass {
- NMObjBaseClass parent;
-
- const NMDedupMultiObj *(*obj_clone)(const NMDedupMultiObj *obj);
-
- gboolean (*obj_needs_clone)(const NMDedupMultiObj *obj);
-
- void (*obj_destroy)(NMDedupMultiObj *obj);
-
- /* the NMDedupMultiObj can be deduplicated. For that the obj_full_hash_update()
- * and obj_full_equal() compare *all* fields of the object, even minor ones. */
- void (*obj_full_hash_update)(const NMDedupMultiObj *obj, struct _NMHashState *h);
- gboolean (*obj_full_equal)(const NMDedupMultiObj *obj_a, const NMDedupMultiObj *obj_b);
-};
-
-/*****************************************************************************/
-
-static inline const NMDedupMultiObj *
-nm_dedup_multi_obj_ref(const NMDedupMultiObj *obj)
-{
- /* ref and unref accept const pointers. Objects is supposed to be shared
- * and kept immutable. Disallowing to take/return a reference to a const
- * NMPObject is cumbersome, because callers are precisely expected to
- * keep a ref on the otherwise immutable object. */
-
- nm_assert(obj);
- nm_assert(obj->_ref_count != NM_OBJ_REF_COUNT_STACKINIT);
- nm_assert(obj->_ref_count > 0);
-
- ((NMDedupMultiObj *) obj)->_ref_count++;
- return obj;
-}
-
-void nm_dedup_multi_obj_unref(const NMDedupMultiObj *obj);
-const NMDedupMultiObj *nm_dedup_multi_obj_clone(const NMDedupMultiObj *obj);
-gboolean nm_dedup_multi_obj_needs_clone(const NMDedupMultiObj *obj);
-
-gconstpointer nm_dedup_multi_index_obj_intern(NMDedupMultiIndex * self,
- /* const NMDedupMultiObj * */ gconstpointer obj);
-
-void nm_dedup_multi_index_obj_release(NMDedupMultiIndex * self,
- /* const NMDedupMultiObj * */ gconstpointer obj);
-
-/* const NMDedupMultiObj * */ gconstpointer
-nm_dedup_multi_index_obj_find(NMDedupMultiIndex * self,
- /* const NMDedupMultiObj * */ gconstpointer obj);
-
-/*****************************************************************************/
-
-/* the NMDedupMultiIdxType is an access handle under which you can store and
- * retrieve NMDedupMultiObj instances in NMDedupMultiIndex.
- *
- * The NMDedupMultiIdxTypeClass determines its behavior, but you can have
- * multiple instances (of the same class).
- *
- * For example, NMIP4Config can have idx-type to put there all IPv4 Routes.
- * This idx-type instance is private to the NMIP4Config instance. Basically,
- * the NMIP4Config instance uses the idx-type to maintain an ordered list
- * of routes in NMDedupMultiIndex.
- *
- * However, a NMDedupMultiIdxType may also partition the set of objects
- * in multiple distinct lists. NMIP4Config doesn't do that (because instead
- * of creating one idx-type for IPv4 and IPv6 routes, it just cretaes
- * to distinct idx-types, one for each address family.
- * This partitioning is used by NMPlatform to maintain a lookup index for
- * routes by ifindex. As the ifindex is dynamic, it does not create an
- * idx-type instance for each ifindex. Instead, it has one idx-type for
- * all routes. But whenever accessing NMDedupMultiIndex with an NMDedupMultiObj,
- * the partitioning NMDedupMultiIdxType takes into account the NMDedupMultiObj
- * instance to associate it with the right list.
- *
- * Hence, a NMDedupMultiIdxEntry has a list of possibly multiple NMDedupMultiHeadEntry
- * instances, which each is the head for a list of NMDedupMultiEntry instances.
- * In the platform example, the NMDedupMultiHeadEntry partition the indexed objects
- * by their ifindex. */
-struct _NMDedupMultiIdxType {
- union {
- NMObjBaseInst parent;
- const NMDedupMultiIdxTypeClass *klass;
- };
-
- CList lst_idx_head;
-
- guint len;
-};
-
-void nm_dedup_multi_idx_type_init(NMDedupMultiIdxType * idx_type,
- const NMDedupMultiIdxTypeClass *klass);
-
-struct _NMDedupMultiIdxTypeClass {
- NMObjBaseClass parent;
-
- void (*idx_obj_id_hash_update)(const NMDedupMultiIdxType *idx_type,
- const NMDedupMultiObj * obj,
- struct _NMHashState * h);
- gboolean (*idx_obj_id_equal)(const NMDedupMultiIdxType *idx_type,
- const NMDedupMultiObj * obj_a,
- const NMDedupMultiObj * obj_b);
-
- /* an NMDedupMultiIdxTypeClass which implements partitioning of the
- * tracked objects, must implement the idx_obj_partition*() functions.
- *
- * idx_obj_partitionable() may return NULL if the object cannot be tracked.
- * For example, a index for routes by ifindex, may not want to track any
- * routes that don't have a valid ifindex. If the idx-type says that the
- * object is not partitionable, it is never added to the NMDedupMultiIndex. */
- gboolean (*idx_obj_partitionable)(const NMDedupMultiIdxType *idx_type,
- const NMDedupMultiObj * obj);
- void (*idx_obj_partition_hash_update)(const NMDedupMultiIdxType *idx_type,
- const NMDedupMultiObj * obj,
- struct _NMHashState * h);
- gboolean (*idx_obj_partition_equal)(const NMDedupMultiIdxType *idx_type,
- const NMDedupMultiObj * obj_a,
- const NMDedupMultiObj * obj_b);
-};
-
-static inline gboolean
-nm_dedup_multi_idx_type_id_equal(const NMDedupMultiIdxType * idx_type,
- /* const NMDedupMultiObj * */ gconstpointer obj_a,
- /* const NMDedupMultiObj * */ gconstpointer obj_b)
-{
- nm_assert(idx_type);
- return obj_a == obj_b || idx_type->klass->idx_obj_id_equal(idx_type, obj_a, obj_b);
-}
-
-static inline gboolean
-nm_dedup_multi_idx_type_partition_equal(const NMDedupMultiIdxType * idx_type,
- /* const NMDedupMultiObj * */ gconstpointer obj_a,
- /* const NMDedupMultiObj * */ gconstpointer obj_b)
-{
- nm_assert(idx_type);
- if (idx_type->klass->idx_obj_partition_equal) {
- nm_assert(obj_a);
- nm_assert(obj_b);
- return obj_a == obj_b || idx_type->klass->idx_obj_partition_equal(idx_type, obj_a, obj_b);
- }
- return TRUE;
-}
-
-/*****************************************************************************/
-
-struct _NMDedupMultiEntry {
- /* this is the list of all entries that share the same head entry.
- * All entries compare equal according to idx_obj_partition_equal(). */
- CList lst_entries;
-
- /* const NMDedupMultiObj * */ gconstpointer obj;
-
- bool is_head;
- bool dirty;
-
- const NMDedupMultiHeadEntry *head;
-};
-
-struct _NMDedupMultiHeadEntry {
- /* this is the list of all entries that share the same head entry.
- * All entries compare equal according to idx_obj_partition_equal(). */
- CList lst_entries_head;
-
- const NMDedupMultiIdxType *idx_type;
-
- bool is_head;
-
- guint len;
-
- CList lst_idx;
-};
-
-/*****************************************************************************/
-
-static inline gconstpointer
-nm_dedup_multi_entry_get_obj(const NMDedupMultiEntry *entry)
-{
- /* convenience method that allows to skip the %NULL check on
- * @entry. Think of the NULL-conditional operator ?. of C# */
- return entry ? entry->obj : NULL;
-}
-
-/*****************************************************************************/
-
-static inline void
-nm_dedup_multi_entry_set_dirty(const NMDedupMultiEntry *entry, gboolean dirty)
-{
- /* NMDedupMultiEntry is always exposed as a const object, because it is not
- * supposed to be modified outside NMDedupMultiIndex API. Except the "dirty"
- * flag. In C++ speak, it is a mutable field.
- *
- * Add this inline function, to cast-away constness and set the dirty flag. */
- nm_assert(entry);
- ((NMDedupMultiEntry *) entry)->dirty = dirty;
-}
-
-/*****************************************************************************/
-
-NMDedupMultiIndex *nm_dedup_multi_index_new(void);
-NMDedupMultiIndex *nm_dedup_multi_index_ref(NMDedupMultiIndex *self);
-NMDedupMultiIndex *nm_dedup_multi_index_unref(NMDedupMultiIndex *self);
-
-static inline void
-_nm_auto_unref_dedup_multi_index(NMDedupMultiIndex **v)
-{
- if (*v)
- nm_dedup_multi_index_unref(*v);
-}
-#define nm_auto_unref_dedup_multi_index nm_auto(_nm_auto_unref_dedup_multi_index)
-
-#define NM_DEDUP_MULTI_ENTRY_MISSING ((const NMDedupMultiEntry *) GUINT_TO_POINTER(1))
-#define NM_DEDUP_MULTI_HEAD_ENTRY_MISSING ((const NMDedupMultiHeadEntry *) GUINT_TO_POINTER(1))
-
-gboolean nm_dedup_multi_index_add_full(NMDedupMultiIndex * self,
- NMDedupMultiIdxType * idx_type,
- /*const NMDedupMultiObj * */ gconstpointer obj,
- NMDedupMultiIdxMode mode,
- const NMDedupMultiEntry * entry_order,
- const NMDedupMultiEntry * entry_existing,
- const NMDedupMultiHeadEntry * head_existing,
- const NMDedupMultiEntry ** out_entry,
- /* const NMDedupMultiObj ** */ gpointer out_obj_old);
-
-gboolean nm_dedup_multi_index_add(NMDedupMultiIndex * self,
- NMDedupMultiIdxType * idx_type,
- /*const NMDedupMultiObj * */ gconstpointer obj,
- NMDedupMultiIdxMode mode,
- const NMDedupMultiEntry ** out_entry,
- /* const NMDedupMultiObj ** */ gpointer out_obj_old);
-
-const NMDedupMultiEntry *
-nm_dedup_multi_index_lookup_obj(const NMDedupMultiIndex * self,
- const NMDedupMultiIdxType * idx_type,
- /*const NMDedupMultiObj * */ gconstpointer obj);
-
-const NMDedupMultiHeadEntry *
-nm_dedup_multi_index_lookup_head(const NMDedupMultiIndex * self,
- const NMDedupMultiIdxType * idx_type,
- /*const NMDedupMultiObj * */ gconstpointer obj);
-
-guint nm_dedup_multi_index_remove_entry(NMDedupMultiIndex *self, gconstpointer entry);
-
-guint nm_dedup_multi_index_remove_obj(NMDedupMultiIndex * self,
- NMDedupMultiIdxType * idx_type,
- /*const NMDedupMultiObj * */ gconstpointer obj,
- /*const NMDedupMultiObj ** */ gconstpointer *out_obj);
-
-guint nm_dedup_multi_index_remove_head(NMDedupMultiIndex * self,
- NMDedupMultiIdxType * idx_type,
- /*const NMDedupMultiObj * */ gconstpointer obj);
-
-guint nm_dedup_multi_index_remove_idx(NMDedupMultiIndex *self, NMDedupMultiIdxType *idx_type);
-
-void nm_dedup_multi_index_dirty_set_head(NMDedupMultiIndex * self,
- const NMDedupMultiIdxType * idx_type,
- /*const NMDedupMultiObj * */ gconstpointer obj);
-
-void nm_dedup_multi_index_dirty_set_idx(NMDedupMultiIndex * self,
- const NMDedupMultiIdxType *idx_type);
-
-guint nm_dedup_multi_index_dirty_remove_idx(NMDedupMultiIndex * self,
- NMDedupMultiIdxType *idx_type,
- gboolean mark_survivors_dirty);
-
-/*****************************************************************************/
-
-typedef struct _NMDedupMultiIter {
- const CList * _head;
- const CList * _next;
- const NMDedupMultiEntry *current;
-} NMDedupMultiIter;
-
-static inline void
-nm_dedup_multi_iter_init(NMDedupMultiIter *iter, const NMDedupMultiHeadEntry *head)
-{
- g_return_if_fail(iter);
-
- if (head && !c_list_is_empty(&head->lst_entries_head)) {
- iter->_head = &head->lst_entries_head;
- iter->_next = head->lst_entries_head.next;
- } else {
- iter->_head = NULL;
- iter->_next = NULL;
- }
- iter->current = NULL;
-}
-
-static inline gboolean
-nm_dedup_multi_iter_next(NMDedupMultiIter *iter)
-{
- g_return_val_if_fail(iter, FALSE);
-
- if (!iter->_next)
- return FALSE;
-
- /* we always look ahead for the next. This way, the user
- * may delete the current entry (but no other entries). */
- iter->current = c_list_entry(iter->_next, NMDedupMultiEntry, lst_entries);
- if (iter->_next->next == iter->_head)
- iter->_next = NULL;
- else
- iter->_next = iter->_next->next;
- return TRUE;
-}
-
-#define nm_dedup_multi_iter_for_each(iter, head_entry) \
- for (nm_dedup_multi_iter_init((iter), (head_entry)); nm_dedup_multi_iter_next((iter));)
-
-/*****************************************************************************/
-
-typedef gboolean (*NMDedupMultiFcnSelectPredicate)(/* const NMDedupMultiObj * */ gconstpointer obj,
- gpointer user_data);
-
-gconstpointer *nm_dedup_multi_objs_to_array_head(const NMDedupMultiHeadEntry * head_entry,
- NMDedupMultiFcnSelectPredicate predicate,
- gpointer user_data,
- guint * out_len);
-GPtrArray * nm_dedup_multi_objs_to_ptr_array_head(const NMDedupMultiHeadEntry * head_entry,
- NMDedupMultiFcnSelectPredicate predicate,
- gpointer user_data);
-
-static inline const NMDedupMultiEntry *
-nm_dedup_multi_head_entry_get_idx(const NMDedupMultiHeadEntry *head_entry, int idx)
-{
- CList *iter;
-
- if (head_entry) {
- if (idx >= 0) {
- c_list_for_each (iter, &head_entry->lst_entries_head) {
- if (idx-- == 0)
- return c_list_entry(iter, NMDedupMultiEntry, lst_entries);
- }
- } else {
- for (iter = head_entry->lst_entries_head.prev; iter != &head_entry->lst_entries_head;
- iter = iter->prev) {
- if (++idx == 0)
- return c_list_entry(iter, NMDedupMultiEntry, lst_entries);
- }
- }
- }
- return NULL;
-}
-
-static inline void
-nm_dedup_multi_head_entry_sort(const NMDedupMultiHeadEntry *head_entry,
- CListSortCmp cmp,
- gconstpointer user_data)
-{
- if (head_entry) {
- /* the head entry can be sorted directly without messing up the
- * index to which it belongs. Of course, this does mess up any
- * NMDedupMultiIter instances. */
- c_list_sort((CList *) &head_entry->lst_entries_head, cmp, user_data);
- }
-}
-
-gboolean nm_dedup_multi_entry_reorder(const NMDedupMultiEntry *entry,
- const NMDedupMultiEntry *entry_order,
- gboolean order_after);
-
-/*****************************************************************************/
-
-#endif /* __NM_DEDUP_MULTI_H__ */
diff --git a/shared/nm-glib-aux/nm-default-glib-i18n-lib.h b/shared/nm-glib-aux/nm-default-glib-i18n-lib.h
deleted file mode 100644
index 9393d1921e..0000000000
--- a/shared/nm-glib-aux/nm-default-glib-i18n-lib.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2015 Red Hat, Inc.
- */
-
-#ifndef __NM_DEFAULT_GLIB_I18N_LIB_H__
-#define __NM_DEFAULT_GLIB_I18N_LIB_H__
-
-/*****************************************************************************/
-
-#define _NETWORKMANAGER_COMPILATION_GLIB_I18N_LIB
-
-#include "nm-glib-aux/nm-default-glib.h"
-
-#undef NETWORKMANAGER_COMPILATION
-#define NETWORKMANAGER_COMPILATION \
- (NM_NETWORKMANAGER_COMPILATION_GLIB | NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_LIB)
-
-/*****************************************************************************/
-
-#endif /* __NM_DEFAULT_GLIB_I18N_LIB_H__ */
diff --git a/shared/nm-glib-aux/nm-default-glib-i18n-prog.h b/shared/nm-glib-aux/nm-default-glib-i18n-prog.h
deleted file mode 100644
index 0abe807b9d..0000000000
--- a/shared/nm-glib-aux/nm-default-glib-i18n-prog.h
+++ /dev/null
@@ -1,21 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2015 Red Hat, Inc.
- */
-
-#ifndef __NM_DEFAULT_GLIB_I18N_PROG_H__
-#define __NM_DEFAULT_GLIB_I18N_PROG_H__
-
-/*****************************************************************************/
-
-#define _NETWORKMANAGER_COMPILATION_GLIB_I18N_PROG
-
-#include "nm-glib-aux/nm-default-glib.h"
-
-#undef NETWORKMANAGER_COMPILATION
-#define NETWORKMANAGER_COMPILATION \
- (NM_NETWORKMANAGER_COMPILATION_GLIB | NM_NETWORKMANAGER_COMPILATION_WITH_GLIB_I18N_PROG)
-
-/*****************************************************************************/
-
-#endif /* __NM_DEFAULT_GLIB_I18N_PROG_H__ */
diff --git a/shared/nm-glib-aux/nm-default-glib.h b/shared/nm-glib-aux/nm-default-glib.h
deleted file mode 100644
index 34b23f7761..0000000000
--- a/shared/nm-glib-aux/nm-default-glib.h
+++ /dev/null
@@ -1,75 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2015 Red Hat, Inc.
- */
-
-#ifndef __NM_DEFAULT_GLIB_H__
-#define __NM_DEFAULT_GLIB_H__
-
-/*****************************************************************************/
-
-#include "nm-std-aux/nm-default-std.h"
-
-#undef NETWORKMANAGER_COMPILATION
-#define NETWORKMANAGER_COMPILATION NM_NETWORKMANAGER_COMPILATION_WITH_GLIB
-
-/*****************************************************************************/
-
-#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>
-#elif defined(_NETWORKMANAGER_COMPILATION_GLIB_I18N_LIB)
- #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
- * during G_VARIANT_TYPE() via g_variant_type_checked_(). This is not necessary
- * because commonly this cast is needed during something like
- *
- * g_variant_builder_init (&props, G_VARIANT_TYPE ("a{sv}"));
- *
- * Note that in if the variant type would be invalid, the check still
- * wouldn't make the buggy code magically work. Instead of passing a
- * bogus type string (bad), it would pass %NULL to g_variant_builder_init()
- * (also bad).
- *
- * Also, a function like g_variant_builder_init() already validates
- * the input type via something like
- *
- * g_return_if_fail (g_variant_type_is_container (type));
- *
- * So, by having G_VARIANT_TYPE() also validate the type, we validate
- * twice, whereas the first validation is rather pointless because it
- * doesn't prevent the function to be called with invalid arguments.
- *
- * Just patch G_VARIANT_TYPE() to perform no check.
- */
- #undef G_VARIANT_TYPE
- #define G_VARIANT_TYPE(type_string) ((const GVariantType *) (type_string))
- #endif
-#endif
-
-/*****************************************************************************/
-
-#include "nm-gassert-patch.h"
-
-#include "nm-std-aux/nm-std-aux.h"
-#include "nm-std-aux/nm-std-utils.h"
-#include "nm-glib-aux/nm-macros-internal.h"
-#include "nm-glib-aux/nm-shared-utils.h"
-#include "nm-glib-aux/nm-errno.h"
-#include "nm-glib-aux/nm-hash-utils.h"
-
-/*****************************************************************************/
-
-#endif /* __NM_DEFAULT_GLIB_H__ */
diff --git a/shared/nm-glib-aux/nm-enum-utils.c b/shared/nm-glib-aux/nm-enum-utils.c
deleted file mode 100644
index b06f2bb2fb..0000000000
--- a/shared/nm-glib-aux/nm-enum-utils.c
+++ /dev/null
@@ -1,368 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2017 Red Hat, Inc.
- */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-enum-utils.h"
-#include "nm-str-buf.h"
-
-/*****************************************************************************/
-
-#define IS_FLAGS_SEPARATOR(ch) (NM_IN_SET((ch), ' ', '\t', ',', '\n', '\r'))
-
-static void
-_ASSERT_enum_values_info(GType type, const NMUtilsEnumValueInfo *value_infos)
-{
-#if NM_MORE_ASSERTS > 5
- nm_auto_unref_gtypeclass GTypeClass *klass = NULL;
- gs_unref_hashtable GHashTable *ht = NULL;
-
- klass = g_type_class_ref(type);
-
- g_assert(G_IS_ENUM_CLASS(klass) || G_IS_FLAGS_CLASS(klass));
-
- if (!value_infos)
- return;
-
- ht = g_hash_table_new(g_str_hash, g_str_equal);
-
- for (; value_infos->nick; value_infos++) {
- g_assert(value_infos->nick[0]);
-
- /* duplicate nicks make no sense!! */
- g_assert(!g_hash_table_contains(ht, value_infos->nick));
- g_hash_table_add(ht, (gpointer) value_infos->nick);
-
- if (G_IS_ENUM_CLASS(klass)) {
- GEnumValue *enum_value;
-
- enum_value = g_enum_get_value_by_nick(G_ENUM_CLASS(klass), value_infos->nick);
- if (enum_value) {
- /* we do allow specifying the same name via @value_infos and @type.
- * That might make sense, if @type comes from a library where older versions
- * of the library don't yet support the value. In this case, the caller can
- * provide the nick via @value_infos, to support the older library version.
- * And then, when actually running against a newer library version where
- * @type knows the nick, we have this situation.
- *
- * Another reason for specifying a nick both in @value_infos and @type,
- * is to specify an alias which is not used with highest preference. For
- * example, if you add an alias "disabled" for "none" (both numerically
- * equal), then the first alias in @value_infos will be preferred over
- * the name from @type. So, to still use "none" as preferred name, you may
- * explicitly specify the "none" alias in @value_infos before "disabled".
- *
- * However, what never is allowed, is to use a name (nick) to re-number
- * the value. That is, if both @value_infos and @type contain a particular
- * nick, their numeric values must agree as well.
- * Allowing this, would be very confusing, because the name would have a different
- * value from the regular GLib GEnum API.
- */
- g_assert(enum_value->value == value_infos->value);
- }
- } else {
- GFlagsValue *flags_value;
-
- flags_value = g_flags_get_value_by_nick(G_FLAGS_CLASS(klass), value_infos->nick);
- if (flags_value) {
- /* see ENUM case above. */
- g_assert(flags_value->value == (guint) value_infos->value);
- }
- }
- }
-#endif
-}
-
-static gboolean
-_is_hex_string(const char *str, gboolean allow_sign)
-{
- if (allow_sign && str[0] == '-')
- str++;
- return str[0] == '0' && str[1] == 'x' && str[2]
- && NM_STRCHAR_ALL(&str[2], ch, g_ascii_isxdigit(ch));
-}
-
-static gboolean
-_is_dec_string(const char *str, gboolean allow_sign)
-{
- if (allow_sign && str[0] == '-')
- str++;
- return str[0] && NM_STRCHAR_ALL(&str[0], ch, g_ascii_isdigit(ch));
-}
-
-static gboolean
-_enum_is_valid_enum_nick(const char *str)
-{
- return str[0] && !NM_STRCHAR_ANY(str, ch, g_ascii_isspace(ch)) && !_is_dec_string(str, TRUE)
- && !_is_hex_string(str, TRUE);
-}
-
-static gboolean
-_enum_is_valid_flags_nick(const char *str)
-{
- return str[0] && !NM_STRCHAR_ANY(str, ch, IS_FLAGS_SEPARATOR(ch)) && !_is_dec_string(str, FALSE)
- && !_is_hex_string(str, FALSE);
-}
-
-char *
-_nm_utils_enum_to_str_full(GType type,
- int value,
- const char * flags_separator,
- const NMUtilsEnumValueInfo *value_infos)
-{
- nm_auto_unref_gtypeclass GTypeClass *klass = NULL;
-
- _ASSERT_enum_values_info(type, value_infos);
-
- if (flags_separator
- && (!flags_separator[0] || NM_STRCHAR_ANY(flags_separator, ch, !IS_FLAGS_SEPARATOR(ch))))
- g_return_val_if_reached(NULL);
-
- klass = g_type_class_ref(type);
-
- if (G_IS_ENUM_CLASS(klass)) {
- GEnumValue *enum_value;
-
- for (; value_infos && value_infos->nick; value_infos++) {
- if (value_infos->value == value)
- return g_strdup(value_infos->nick);
- }
-
- enum_value = g_enum_get_value(G_ENUM_CLASS(klass), value);
- if (!enum_value || !_enum_is_valid_enum_nick(enum_value->value_nick))
- return g_strdup_printf("%d", value);
- else
- return g_strdup(enum_value->value_nick);
- } else if (G_IS_FLAGS_CLASS(klass)) {
- unsigned uvalue = (unsigned) value;
- GFlagsValue *flags_value;
- NMStrBuf strbuf;
-
- flags_separator = flags_separator ?: " ";
-
- nm_str_buf_init(&strbuf, 16, FALSE);
-
- for (; value_infos && value_infos->nick; value_infos++) {
- nm_assert(_enum_is_valid_flags_nick(value_infos->nick));
-
- if (uvalue == 0) {
- if (value_infos->value != 0)
- continue;
- } else {
- if (!NM_FLAGS_ALL(uvalue, (unsigned) value_infos->value))
- continue;
- }
-
- if (strbuf.len)
- nm_str_buf_append(&strbuf, flags_separator);
- nm_str_buf_append(&strbuf, value_infos->nick);
- uvalue &= ~((unsigned) value_infos->value);
- if (uvalue == 0) {
- /* we printed all flags. Done. */
- goto flags_done;
- }
- }
-
- do {
- flags_value = g_flags_get_first_value(G_FLAGS_CLASS(klass), uvalue);
- if (strbuf.len)
- nm_str_buf_append(&strbuf, flags_separator);
- if (!flags_value || !_enum_is_valid_flags_nick(flags_value->value_nick)) {
- if (uvalue)
- nm_str_buf_append_printf(&strbuf, "0x%x", uvalue);
- break;
- }
- nm_str_buf_append(&strbuf, flags_value->value_nick);
- uvalue &= ~flags_value->value;
- } while (uvalue);
-
-flags_done:
- return nm_str_buf_finalize(&strbuf, NULL);
- }
-
- g_return_val_if_reached(NULL);
-}
-
-static const NMUtilsEnumValueInfo *
-_find_value_info(const NMUtilsEnumValueInfo *value_infos, const char *needle)
-{
- if (value_infos) {
- for (; value_infos->nick; value_infos++) {
- if (nm_streq(needle, value_infos->nick))
- return value_infos;
- }
- }
- return NULL;
-}
-
-gboolean
-_nm_utils_enum_from_str_full(GType type,
- const char * str,
- int * out_value,
- char ** err_token,
- const NMUtilsEnumValueInfo *value_infos)
-{
- nm_auto_unref_gtypeclass GTypeClass *klass = NULL;
- gboolean ret = FALSE;
- int value = 0;
- gs_free char * str_clone = NULL;
- char * s;
- gint64 v64;
- const NMUtilsEnumValueInfo * nick;
-
- g_return_val_if_fail(str, FALSE);
-
- _ASSERT_enum_values_info(type, value_infos);
-
- s = nm_strdup_maybe_a(300, nm_str_skip_leading_spaces(str), &str_clone);
- g_strchomp(s);
-
- klass = g_type_class_ref(type);
-
- if (G_IS_ENUM_CLASS(klass)) {
- GEnumValue *enum_value;
-
- G_STATIC_ASSERT(G_MAXINT < G_MAXINT64);
- G_STATIC_ASSERT(G_MININT > G_MININT64);
-
- if (s[0]) {
- if (_is_hex_string(s, TRUE)) {
- if (s[0] == '-') {
- v64 = _nm_utils_ascii_str_to_int64(&s[3],
- 16,
- -((gint64) G_MAXINT),
- -((gint64) G_MININT),
- G_MAXINT64);
- if (v64 != G_MAXINT64) {
- value = (int) (-v64);
- ret = TRUE;
- }
- } else {
- v64 = _nm_utils_ascii_str_to_int64(&s[2], 16, G_MININT, G_MAXINT, G_MAXINT64);
- if (v64 != G_MAXINT64) {
- value = (int) v64;
- ret = TRUE;
- }
- }
- } else if (_is_dec_string(s, TRUE)) {
- v64 = _nm_utils_ascii_str_to_int64(s, 10, G_MININT, G_MAXINT, G_MAXINT64);
- if (v64 != G_MAXINT64) {
- value = (int) v64;
- ret = TRUE;
- }
- } else if ((nick = _find_value_info(value_infos, s))) {
- value = nick->value;
- ret = TRUE;
- } else if ((enum_value = g_enum_get_value_by_nick(G_ENUM_CLASS(klass), s))) {
- value = enum_value->value;
- ret = TRUE;
- }
- }
- } else if (G_IS_FLAGS_CLASS(klass)) {
- GFlagsValue *flags_value;
- unsigned uvalue = 0;
-
- ret = TRUE;
- while (s[0]) {
- char *s_end;
-
- for (s_end = s; s_end[0]; s_end++) {
- if (IS_FLAGS_SEPARATOR(s_end[0])) {
- s_end[0] = '\0';
- s_end++;
- break;
- }
- }
-
- if (s[0]) {
- if (_is_hex_string(s, FALSE)) {
- v64 = _nm_utils_ascii_str_to_int64(&s[2], 16, 0, G_MAXUINT, -1);
- if (v64 == -1) {
- ret = FALSE;
- break;
- }
- uvalue |= (unsigned) v64;
- } else if (_is_dec_string(s, FALSE)) {
- v64 = _nm_utils_ascii_str_to_int64(s, 10, 0, G_MAXUINT, -1);
- if (v64 == -1) {
- ret = FALSE;
- break;
- }
- uvalue |= (unsigned) v64;
- } else if ((nick = _find_value_info(value_infos, s)))
- uvalue |= (unsigned) nick->value;
- else if ((flags_value = g_flags_get_value_by_nick(G_FLAGS_CLASS(klass), s)))
- uvalue |= flags_value->value;
- else {
- ret = FALSE;
- break;
- }
- }
-
- s = s_end;
- }
-
- value = (int) uvalue;
- } else
- g_return_val_if_reached(FALSE);
-
- NM_SET_OUT(err_token, !ret && s[0] ? g_strdup(s) : NULL);
- NM_SET_OUT(out_value, ret ? value : 0);
- return ret;
-}
-
-const char **
-_nm_utils_enum_get_values(GType type, int from, int to)
-{
- GTypeClass *klass;
- GPtrArray * array;
- int i;
- char sbuf[64];
-
- klass = g_type_class_ref(type);
- array = g_ptr_array_new();
-
- if (G_IS_ENUM_CLASS(klass)) {
- GEnumClass *enum_class = G_ENUM_CLASS(klass);
- GEnumValue *enum_value;
-
- for (i = 0; i < enum_class->n_values; i++) {
- enum_value = &enum_class->values[i];
- if (enum_value->value >= from && enum_value->value <= to) {
- if (_enum_is_valid_enum_nick(enum_value->value_nick))
- g_ptr_array_add(array, (gpointer) enum_value->value_nick);
- else
- g_ptr_array_add(
- array,
- (gpointer) g_intern_string(nm_sprintf_buf(sbuf, "%d", enum_value->value)));
- }
- }
- } else if (G_IS_FLAGS_CLASS(klass)) {
- GFlagsClass *flags_class = G_FLAGS_CLASS(klass);
- GFlagsValue *flags_value;
-
- for (i = 0; i < flags_class->n_values; i++) {
- flags_value = &flags_class->values[i];
- if (flags_value->value >= (guint) from && flags_value->value <= (guint) to) {
- if (_enum_is_valid_flags_nick(flags_value->value_nick))
- g_ptr_array_add(array, (gpointer) flags_value->value_nick);
- else
- g_ptr_array_add(
- array,
- (gpointer) g_intern_string(
- nm_sprintf_buf(sbuf, "0x%x", (unsigned) flags_value->value)));
- }
- }
- } else {
- g_type_class_unref(klass);
- g_ptr_array_free(array, TRUE);
- g_return_val_if_reached(NULL);
- }
-
- g_type_class_unref(klass);
- g_ptr_array_add(array, NULL);
-
- return (const char **) g_ptr_array_free(array, FALSE);
-}
diff --git a/shared/nm-glib-aux/nm-enum-utils.h b/shared/nm-glib-aux/nm-enum-utils.h
deleted file mode 100644
index 89be54e77f..0000000000
--- a/shared/nm-glib-aux/nm-enum-utils.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2017 Red Hat, Inc.
- */
-
-#ifndef __NM_ENUM_UTILS_H__
-#define __NM_ENUM_UTILS_H__
-
-/*****************************************************************************/
-
-typedef struct _NMUtilsEnumValueInfo {
- /* currently, this is only used for _nm_utils_enum_from_str_full() to
- * declare additional aliases for values. */
- const char *nick;
- int value;
-} NMUtilsEnumValueInfo;
-
-char * _nm_utils_enum_to_str_full(GType type,
- int value,
- const char * sep,
- const NMUtilsEnumValueInfo *value_infos);
-gboolean _nm_utils_enum_from_str_full(GType type,
- const char * str,
- int * out_value,
- char ** err_token,
- const NMUtilsEnumValueInfo *value_infos);
-
-const char **_nm_utils_enum_get_values(GType type, int from, int to);
-
-/*****************************************************************************/
-
-#endif /* __NM_ENUM_UTILS_H__ */
diff --git a/shared/nm-glib-aux/nm-errno.c b/shared/nm-glib-aux/nm-errno.c
deleted file mode 100644
index 668606cacd..0000000000
--- a/shared/nm-glib-aux/nm-errno.c
+++ /dev/null
@@ -1,181 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2018 Red Hat, Inc.
- */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-errno.h"
-
-#include <pthread.h>
-
-/*****************************************************************************/
-
-static NM_UTILS_LOOKUP_STR_DEFINE(
- _geterror,
-#if 0
- enum _NMErrno,
-#else
- int,
-#endif
- NM_UTILS_LOOKUP_DEFAULT(NULL),
-
- NM_UTILS_LOOKUP_STR_ITEM(NME_ERRNO_SUCCESS, "NME_ERRNO_SUCCESS"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_ERRNO_OUT_OF_RANGE, "NME_ERRNO_OUT_OF_RANGE"),
-
- NM_UTILS_LOOKUP_STR_ITEM(NME_UNSPEC, "NME_UNSPEC"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_BUG, "NME_BUG"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_NATIVE_ERRNO, "NME_NATIVE_ERRNO"),
-
- NM_UTILS_LOOKUP_STR_ITEM(NME_NL_ATTRSIZE, "NME_NL_ATTRSIZE"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_NL_BAD_SOCK, "NME_NL_BAD_SOCK"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_NL_DUMP_INTR, "NME_NL_DUMP_INTR"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_NL_MSG_OVERFLOW, "NME_NL_MSG_OVERFLOW"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_NL_MSG_TOOSHORT, "NME_NL_MSG_TOOSHORT"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_NL_MSG_TRUNC, "NME_NL_MSG_TRUNC"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_NL_SEQ_MISMATCH, "NME_NL_SEQ_MISMATCH"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_NL_NOADDR, "NME_NL_NOADDR"),
-
- NM_UTILS_LOOKUP_STR_ITEM(NME_PL_NOT_FOUND, "not-found"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_PL_EXISTS, "exists"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_PL_WRONG_TYPE, "wrong-type"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_PL_NOT_SLAVE, "not-slave"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_PL_NO_FIRMWARE, "no-firmware"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_PL_OPNOTSUPP, "not-supported"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_PL_NETLINK, "netlink"),
- NM_UTILS_LOOKUP_STR_ITEM(NME_PL_CANT_SET_MTU, "cant-set-mtu"),
-
- NM_UTILS_LOOKUP_ITEM_IGNORE(_NM_ERRNO_MININT),
- NM_UTILS_LOOKUP_ITEM_IGNORE(_NM_ERRNO_RESERVED_LAST_PLUS_1), );
-
-/**
- * nm_strerror():
- * @nmerr: the NetworkManager specific errno to be converted
- * to string.
- *
- * NetworkManager specific error numbers reserve a range in "errno.h" with
- * our own defines. For numbers that don't fall into this range, the numbers
- * are identical to the common error numbers.
- *
- * Identical to strerror(), g_strerror(), nm_strerror_native() for error numbers
- * that are not in the reserved range of NetworkManager specific errors.
- *
- * Returns: (transfer none): the string representation of the error number.
- */
-const char *
-nm_strerror(int nmerr)
-{
- const char *s;
-
- nmerr = nm_errno(nmerr);
-
- if (nmerr >= _NM_ERRNO_RESERVED_FIRST) {
- s = _geterror(nmerr);
- if (s)
- return s;
- }
- return nm_strerror_native(nmerr);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_strerror_native_r:
- * @errsv: the errno to convert to string.
- * @buf: the output buffer where to write the string to.
- * @buf_size: the length of buffer.
- *
- * This is like strerror_r(), with one difference: depending on the
- * locale, the returned string is guaranteed to be valid UTF-8.
- * Also, there is some confusion as to whether to use glibc's
- * strerror_r() or the POXIX/XSI variant. This is abstracted
- * by the function.
- *
- * Note that the returned buffer may also be a statically allocated
- * buffer, and not the input buffer @buf. Consequently, the returned
- * string may be longer than @buf_size.
- *
- * Returns: (transfer none): a NUL terminated error message. This is either a static
- * string (that is never freed), or the provided @buf argument.
- */
-const char *
-nm_strerror_native_r(int errsv, char *buf, gsize buf_size)
-{
- char *buf2;
-
- nm_assert(buf);
- nm_assert(buf_size > 0);
-
-#if (!defined(__GLIBC__) && !defined(__UCLIBC__)) || ((_POSIX_C_SOURCE >= 200112L) && !_GNU_SOURCE)
- /* XSI-compliant */
- {
- int errno_saved = errno;
-
- if (strerror_r(errsv, buf, buf_size) != 0) {
- g_snprintf(buf, buf_size, "Unspecified errno %d", errsv);
- errno = errno_saved;
- }
- buf2 = buf;
- }
-#else
- /* GNU-specific */
- buf2 = strerror_r(errsv, buf, buf_size);
-#endif
-
- /* like g_strerror(), ensure that the error message is UTF-8. */
- if (!g_get_charset(NULL) && !g_utf8_validate(buf2, -1, NULL)) {
- gs_free char *msg = NULL;
-
- msg = g_locale_to_utf8(buf2, -1, NULL, NULL, NULL);
- if (msg) {
- g_strlcpy(buf, msg, buf_size);
- buf2 = buf;
- }
- }
-
- return buf2;
-}
-
-/**
- * nm_strerror_native:
- * @errsv: the errno integer from <errno.h>
- *
- * Like strerror(), but strerror() is not thread-safe and not guaranteed
- * to be UTF-8.
- *
- * g_strerror() is a thread-safe variant of strerror(), however it caches
- * all returned strings in a dictionary. That means, using this on untrusted
- * error numbers can result in this cache to grow without limits.
- *
- * Instead, return a tread-local buffer. This way, it's thread-safe.
- *
- * There is a downside to this: subsequent calls of nm_strerror_native()
- * overwrite the error message.
- *
- * Returns: (transfer none): the text representation of the error number.
- */
-const char *
-nm_strerror_native(int errsv)
-{
- static _nm_thread_local char *buf_static = NULL;
- char * buf;
-
- buf = buf_static;
- if (G_UNLIKELY(!buf)) {
- int errno_saved = errno;
- pthread_key_t key;
-
- buf = g_malloc(NM_STRERROR_BUFSIZE);
- buf_static = buf;
-
- if (pthread_key_create(&key, g_free) != 0 || pthread_setspecific(key, buf) != 0) {
- /* Failure. We will leak the buffer when the thread exits.
- *
- * Nothing we can do about it really. For Debug builds we fail with an assertion. */
- nm_assert_not_reached();
- }
- errno = errno_saved;
- }
-
- return nm_strerror_native_r(errsv, buf, NM_STRERROR_BUFSIZE);
-}
diff --git a/shared/nm-glib-aux/nm-errno.h b/shared/nm-glib-aux/nm-errno.h
deleted file mode 100644
index 62c8379f83..0000000000
--- a/shared/nm-glib-aux/nm-errno.h
+++ /dev/null
@@ -1,171 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_ERRNO_H__
-#define __NM_ERRNO_H__
-
-#include <errno.h>
-
-/*****************************************************************************/
-
-enum _NMErrno {
- _NM_ERRNO_MININT = G_MININT,
- _NM_ERRNO_MAXINT = G_MAXINT,
- _NM_ERRNO_RESERVED_FIRST = 100000,
-
- /* when we cannot represent a number as positive number, we resort to this
- * number. Basically, the values G_MININT, -NME_ERRNO_SUCCESS, NME_ERRNO_SUCCESS
- * and G_MAXINT all map to the same value. */
- NME_ERRNO_OUT_OF_RANGE = G_MAXINT,
-
- /* Indicate that the original errno was zero. Zero denotes *no error*, but we know something
- * went wrong and we want to report some error. This is a placeholder to mean, something
- * was wrong, but errno was zero. */
- NME_ERRNO_SUCCESS = G_MAXINT - 1,
-
- /* an unspecified error. */
- NME_UNSPEC = _NM_ERRNO_RESERVED_FIRST,
-
- /* A bug, for example when an assertion failed.
- * Should never happen. */
- NME_BUG,
-
- /* a native error number (from <errno.h>) cannot be mapped as
- * an nm-error, because it is in the range [_NM_ERRNO_RESERVED_FIRST,
- * _NM_ERRNO_RESERVED_LAST]. */
- NME_NATIVE_ERRNO,
-
- /* netlink errors. */
- NME_NL_SEQ_MISMATCH,
- NME_NL_MSG_TRUNC,
- NME_NL_MSG_TOOSHORT,
- NME_NL_DUMP_INTR,
- NME_NL_ATTRSIZE,
- NME_NL_BAD_SOCK,
- NME_NL_NOADDR,
- NME_NL_MSG_OVERFLOW,
-
- /* platform errors. */
- NME_PL_NOT_FOUND,
- NME_PL_EXISTS,
- NME_PL_WRONG_TYPE,
- NME_PL_NOT_SLAVE,
- NME_PL_NO_FIRMWARE,
- NME_PL_OPNOTSUPP,
- NME_PL_NETLINK,
- NME_PL_CANT_SET_MTU,
-
- _NM_ERRNO_RESERVED_LAST_PLUS_1,
- _NM_ERRNO_RESERVED_LAST = _NM_ERRNO_RESERVED_LAST_PLUS_1 - 1,
-};
-
-/*****************************************************************************/
-
-/* When we receive an errno from a system function, we can safely assume
- * that the error number is not negative. We rely on that, and possibly just
- * "return -errsv;" to signal an error. We also rely on that, because libc
- * is our trusted base: meaning, if it cannot even succeed at setting errno
- * according to specification, all bets are off.
- *
- * This macro returns the input argument, and asserts that the error variable
- * is positive.
- *
- * In a sense, the macro is related to nm_errno_native() function, but the difference
- * is that this macro asserts that @errsv is positive, while nm_errno_native() coerces
- * negative values to be non-negative. */
-#define NM_ERRNO_NATIVE(errsv) \
- ({ \
- const int _errsv_x = (errsv); \
- \
- nm_assert(_errsv_x > 0); \
- _errsv_x; \
- })
-
-/* Normalize native errno.
- *
- * Our API may return native error codes (<errno.h>) as negative values. This function
- * takes such an errno, and normalizes it to their positive value.
- *
- * The special values G_MININT and zero are coerced to NME_ERRNO_OUT_OF_RANGE and NME_ERRNO_SUCCESS
- * respectively.
- * Other values are coerced to their inverse.
- * Other positive values are returned unchanged.
- *
- * Basically, this normalizes errsv to be positive (taking care of two pathological cases).
- */
-static inline int
-nm_errno_native(int errsv)
-{
- switch (errsv) {
- case 0:
- return NME_ERRNO_SUCCESS;
- case G_MININT:
- return NME_ERRNO_OUT_OF_RANGE;
- default:
- return errsv >= 0 ? errsv : -errsv;
- }
-}
-
-/* Normalizes an nm-error to be positive.
- *
- * Various API returns negative error codes, and this function converts the negative
- * value to its positive.
- *
- * Note that @nmerr is on the domain of NetworkManager specific error numbers,
- * which is not the same as the native error numbers (errsv from <errno.h>). But
- * as far as normalizing goes, nm_errno() does exactly the same remapping as
- * nm_errno_native(). */
-static inline int
-nm_errno(int nmerr)
-{
- return nm_errno_native(nmerr);
-}
-
-/* this maps a native errno to a (always non-negative) nm-error number.
- *
- * Note that nm-error numbers are embedded into the range of regular
- * errno. The only difference is, that nm-error numbers reserve a
- * range (_NM_ERRNO_RESERVED_FIRST, _NM_ERRNO_RESERVED_LAST) for their
- * own purpose.
- *
- * That means, converting an errno to nm-error number means in
- * most cases just returning itself.
- * Only pathological cases need special handling:
- *
- * - 0 is mapped to NME_ERRNO_SUCCESS;
- * - G_MININT is mapped to NME_ERRNO_OUT_OF_RANGE;
- * - values in the range of (+/-) [_NM_ERRNO_RESERVED_FIRST, _NM_ERRNO_RESERVED_LAST]
- * are mapped to NME_NATIVE_ERRNO
- * - all other values are their (positive) absolute value.
- */
-static inline int
-nm_errno_from_native(int errsv)
-{
- switch (errsv) {
- case 0:
- return NME_ERRNO_SUCCESS;
- case G_MININT:
- return NME_ERRNO_OUT_OF_RANGE;
- default:
- if (errsv < 0)
- errsv = -errsv;
- return G_UNLIKELY(errsv >= _NM_ERRNO_RESERVED_FIRST && errsv <= _NM_ERRNO_RESERVED_LAST)
- ? NME_NATIVE_ERRNO
- : errsv;
- }
-}
-
-const char *nm_strerror(int nmerr);
-
-/*****************************************************************************/
-
-#define NM_STRERROR_BUFSIZE 1024
-
-const char *nm_strerror_native_r(int errsv, char *buf, gsize buf_size);
-const char *nm_strerror_native(int errsv);
-
-/*****************************************************************************/
-
-#endif /* __NM_ERRNO_H__ */
diff --git a/shared/nm-glib-aux/nm-gassert-patch.h b/shared/nm-glib-aux/nm-gassert-patch.h
deleted file mode 100644
index bac8697c0e..0000000000
--- a/shared/nm-glib-aux/nm-gassert-patch.h
+++ /dev/null
@@ -1,76 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2015 Red Hat, Inc.
- */
-
-#ifndef __NM_GASSERT_PATCH_H__
-#define __NM_GASSERT_PATCH_H__
-
-/*****************************************************************************/
-
-#if NM_MORE_ASSERTS == 0
-
-/* glib assertions (g_return_*(), g_assert*()) contain a textual representation
- * of the checked statement. This part of the assertion blows up the size of the
- * binary. Unless we compile a debug-build with NM_MORE_ASSERTS, drop these
- * parts. Note that the failed assertion still prints the file and line where the
- * assertion fails. That shall suffice. */
-
-static inline void
-_nm_g_return_if_fail_warning(const char *log_domain, const char *file, int line)
-{
- char file_buf[256 + 15];
-
- g_snprintf(file_buf, sizeof(file_buf), "((%s:%d))", file, 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_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_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
-
-#else
- #define NM_ASSERT_G_RETURN_EXPR(expr) "" expr ""
- #define NM_ASSERT_NO_MSG 0
-#endif
-
-/*****************************************************************************/
-
-#endif /* __NM_GASSERT_PATCH_H__ */
diff --git a/shared/nm-glib-aux/nm-glib.h b/shared/nm-glib-aux/nm-glib.h
deleted file mode 100644
index befb8d9013..0000000000
--- a/shared/nm-glib-aux/nm-glib.h
+++ /dev/null
@@ -1,707 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2008 - 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_GLIB_H__
-#define __NM_GLIB_H__
-
-/*****************************************************************************/
-
-#ifndef __NM_MACROS_INTERNAL_H__
- #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
-
- #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")
-
-#endif
-
-/*****************************************************************************/
-
-static inline void
-__g_type_ensure(GType type)
-{
-#if !GLIB_CHECK_VERSION(2, 34, 0)
- if (G_UNLIKELY(type == (GType) -1))
- g_error("can't happen");
-#else
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS;
- g_type_ensure(type);
- G_GNUC_END_IGNORE_DEPRECATIONS;
-#endif
-}
-#define g_type_ensure __g_type_ensure
-
-/*****************************************************************************/
-
-#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
-
-#endif
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION(2, 34, 0)
-
- /* 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()
-
-#else
-
- /* 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
-
-#endif
-
-/*****************************************************************************/
-
-#if GLIB_CHECK_VERSION(2, 35, 0)
- /* 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
-#else
- #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)
-#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
-#endif
-
-/*****************************************************************************/
-
-/* Rumtime check for glib version. First do a compile time check which
- * (if satisfied) shortcuts the runtime check. */
-static inline gboolean
-nm_glib_check_version(guint major, guint minor, guint micro)
-{
- return GLIB_CHECK_VERSION(major, minor, micro)
- || ((glib_major_version > major)
- || (glib_major_version == major && glib_minor_version > minor)
- || (glib_major_version == major && glib_minor_version == minor
- && glib_micro_version < micro));
-}
-
-/*****************************************************************************/
-
-/* g_test_skip() is only available since glib 2.38. Add a compatibility wrapper. */
-static inline void
-__nmtst_g_test_skip(const char *msg)
-{
-#if GLIB_CHECK_VERSION(2, 38, 0)
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- g_test_skip(msg);
- G_GNUC_END_IGNORE_DEPRECATIONS
-#else
- g_debug("%s", msg);
-#endif
-}
-#define g_test_skip __nmtst_g_test_skip
-
-/*****************************************************************************/
-
-/* g_test_add_data_func_full() is only available since glib 2.34. Add a compatibility wrapper. */
-static inline void
-__g_test_add_data_func_full(const char * testpath,
- gpointer test_data,
- GTestDataFunc test_func,
- GDestroyNotify data_free_func)
-{
-#if GLIB_CHECK_VERSION(2, 34, 0)
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- g_test_add_data_func_full(testpath, test_data, test_func, data_free_func);
- G_GNUC_END_IGNORE_DEPRECATIONS
-#else
- g_return_if_fail(testpath != NULL);
- g_return_if_fail(testpath[0] == '/');
- g_return_if_fail(test_func != NULL);
-
- g_test_add_vtable(testpath,
- 0,
- test_data,
- NULL,
- (GTestFixtureFunc) test_func,
- (GTestFixtureFunc) data_free_func);
-#endif
-}
-#define g_test_add_data_func_full __g_test_add_data_func_full
-
-/*****************************************************************************/
-
-static inline gboolean
-nm_g_hash_table_replace(GHashTable *hash, gpointer key, gpointer value)
-{
- /* glib 2.40 added a return value indicating whether the key already existed
- * (910191597a6c2e5d5d460e9ce9efb4f47d9cc63c). */
-#if GLIB_CHECK_VERSION(2, 40, 0)
- return g_hash_table_replace(hash, key, value);
-#else
- gboolean contained = g_hash_table_contains(hash, key);
-
- g_hash_table_replace(hash, key, value);
- return !contained;
-#endif
-}
-
-static inline gboolean
-nm_g_hash_table_insert(GHashTable *hash, gpointer key, gpointer value)
-{
- /* glib 2.40 added a return value indicating whether the key already existed
- * (910191597a6c2e5d5d460e9ce9efb4f47d9cc63c). */
-#if GLIB_CHECK_VERSION(2, 40, 0)
- return g_hash_table_insert(hash, key, value);
-#else
- gboolean contained = g_hash_table_contains(hash, key);
-
- g_hash_table_insert(hash, key, value);
- return !contained;
-#endif
-}
-
-static inline gboolean
-nm_g_hash_table_add(GHashTable *hash, gpointer key)
-{
- /* glib 2.40 added a return value indicating whether the key already existed
- * (910191597a6c2e5d5d460e9ce9efb4f47d9cc63c). */
-#if GLIB_CHECK_VERSION(2, 40, 0)
- return g_hash_table_add(hash, key);
-#else
- gboolean contained = g_hash_table_contains(hash, key);
-
- g_hash_table_add(hash, key);
- return !contained;
-#endif
-}
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION(2, 40, 0) || defined(NM_GLIB_COMPAT_H_TEST)
-static inline void
-_nm_g_ptr_array_insert(GPtrArray *array, int index_, gpointer data)
-{
- g_return_if_fail(array);
- g_return_if_fail(index_ >= -1);
- g_return_if_fail(index_ <= (int) array->len);
-
- g_ptr_array_add(array, data);
-
- if (index_ != -1 && index_ != (int) (array->len - 1)) {
- memmove(&(array->pdata[index_ + 1]),
- &(array->pdata[index_]),
- (array->len - index_ - 1) * sizeof(gpointer));
- array->pdata[index_] = 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
-#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
-#endif
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION(2, 40, 0)
-static inline gboolean
-_g_key_file_save_to_file(GKeyFile *key_file, const char *filename, GError **error)
-{
- char * contents;
- gboolean success;
- gsize length;
-
- g_return_val_if_fail(key_file != NULL, FALSE);
- g_return_val_if_fail(filename != NULL, FALSE);
- g_return_val_if_fail(error == NULL || *error == NULL, FALSE);
-
- contents = g_key_file_to_data(key_file, &length, NULL);
- g_assert(contents != NULL);
-
- success = g_file_set_contents(filename, contents, length, error);
- g_free(contents);
-
- return success;
-}
- #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; \
- })
-#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 \
- })
-#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; \
- })
-#endif
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION(2, 40, 0) || defined(NM_GLIB_COMPAT_H_TEST)
-static inline gpointer *
-_nm_g_hash_table_get_keys_as_array(GHashTable *hash_table, guint *length)
-{
- GHashTableIter iter;
- gpointer key, *ret;
- guint i = 0;
-
- g_return_val_if_fail(hash_table, NULL);
-
- ret = g_new0(gpointer, g_hash_table_size(hash_table) + 1);
- g_hash_table_iter_init(&iter, hash_table);
-
- while (g_hash_table_iter_next(&iter, &key, NULL))
- ret[i++] = key;
-
- ret[i] = NULL;
-
- if (length)
- *length = i;
-
- return ret;
-}
-#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); })
-#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 \
- })
-#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__)
-#endif
-
-/*****************************************************************************/
-
-static inline gpointer
-_nm_g_steal_pointer(gpointer pp)
-{
- gpointer *ptr = (gpointer *) pp;
- gpointer ref;
-
- ref = *ptr;
- *ptr = NULL;
-
- return ref;
-}
-
-#if !GLIB_CHECK_VERSION(2, 44, 0)
-static inline gpointer
-g_steal_pointer(gpointer pp)
-{
- return _nm_g_steal_pointer(pp);
-}
-#endif
-
-#ifdef g_steal_pointer
- #undef g_steal_pointer
-#endif
-#define g_steal_pointer(pp) ((typeof(*(pp))) _nm_g_steal_pointer(pp))
-
-/*****************************************************************************/
-
-static inline gboolean
-_nm_g_strv_contains(const char *const *strv, const char *str)
-{
-#if !GLIB_CHECK_VERSION(2, 44, 0)
- g_return_val_if_fail(strv != NULL, FALSE);
- g_return_val_if_fail(str != NULL, FALSE);
-
- for (; *strv != NULL; strv++) {
- if (g_str_equal(str, *strv))
- return TRUE;
- }
-
- return FALSE;
-#else
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- return g_strv_contains(strv, str);
- G_GNUC_END_IGNORE_DEPRECATIONS
-#endif
-}
-#define g_strv_contains _nm_g_strv_contains
-
-/*****************************************************************************/
-
-static inline GVariant *
-_nm_g_variant_new_take_string(char *string)
-{
-#if !GLIB_CHECK_VERSION(2, 36, 0)
- GVariant *value;
-
- g_return_val_if_fail(string != NULL, NULL);
- g_return_val_if_fail(g_utf8_validate(string, -1, NULL), NULL);
-
- value = g_variant_new_string(string);
- g_free(string);
- return value;
-#elif !GLIB_CHECK_VERSION(2, 38, 0)
- GVariant *value;
- GBytes * bytes;
-
- g_return_val_if_fail(string != NULL, NULL);
- g_return_val_if_fail(g_utf8_validate(string, -1, NULL), NULL);
-
- bytes = g_bytes_new_take(string, strlen(string) + 1);
- value = g_variant_new_from_bytes(G_VARIANT_TYPE_STRING, bytes, TRUE);
- g_bytes_unref(bytes);
-
- return value;
-#else
- G_GNUC_BEGIN_IGNORE_DEPRECATIONS
- return g_variant_new_take_string(string);
- G_GNUC_END_IGNORE_DEPRECATIONS
-#endif
-}
-#define g_variant_new_take_string _nm_g_variant_new_take_string
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION(2, 38, 0)
-_nm_printf(1, 2) static inline GVariant *_nm_g_variant_new_printf(const char *format_string, ...)
-{
- char * string;
- va_list ap;
-
- g_return_val_if_fail(format_string, NULL);
-
- va_start(ap, format_string);
- string = g_strdup_vprintf(format_string, ap);
- va_end(ap);
-
- return g_variant_new_take_string(string);
-}
- #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; \
- })
-#endif
-
-/*****************************************************************************/
-
-/* Recent glib also casts the results to typeof(Obj), but only if
- *
- * ( defined(g_has_typeof) && GLIB_VERSION_MAX_ALLOWED >= GLIB_VERSION_2_56 )
- *
- * Since we build NetworkManager with older GLIB_VERSION_MAX_ALLOWED, it's
- * not taking effect.
- *
- * Override this. */
-#undef g_object_ref
-#undef g_object_ref_sink
-#define g_object_ref(Obj) ((typeof(Obj)) g_object_ref(Obj))
-#define g_object_ref_sink(Obj) ((typeof(Obj)) g_object_ref_sink(Obj))
-
-/*****************************************************************************/
-
-#ifndef g_autofree
- /* 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
-#endif
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION(2, 47, 1)
-/* Older versions of g_value_unset() only allowed to unset a GValue which
- * was initialized previously. This was relaxed ([1], [2], [3]).
- *
- * Our nm_auto_unset_gvalue macro requires to be able to call g_value_unset().
- * Also, it is our general practice to allow for that. Add a compat implementation.
- *
- * [1] https://gitlab.gnome.org/GNOME/glib/commit/4b2d92a864f1505f1b08eb639d74293fa32681da
- * [2] commit "Allow passing unset GValues to g_value_unset()"
- * [3] https://bugzilla.gnome.org/show_bug.cgi?id=755766
- */
-static inline void
-_nm_g_value_unset(GValue *value)
-{
- g_return_if_fail(value);
-
- if (value->g_type != 0)
- g_value_unset(value);
-}
- #define g_value_unset _nm_g_value_unset
-#endif
-
-/* G_PID_FORMAT was added only in 2.53.5. Define it ourself.
- *
- * If this was about "pid_t", we would check SIZEOF_PID_T, and set
- * PRIi32/PRIi16, like systemd does. But it's actually about
- * GPid, which glib typedefs as an "int".
- *
- * There is a test_gpid() that check that GPid is really a typedef
- * for int. */
-#undef G_PID_FORMAT
-#define G_PID_FORMAT "i"
-
-/*****************************************************************************/
-
-/* G_SOURCE_FUNC was added in 2.57.2. */
-#undef G_SOURCE_FUNC
-#define G_SOURCE_FUNC(f) ((GSourceFunc)(void (*)(void))(f))
-
-/*****************************************************************************/
-
-/* g_atomic_pointer_get() is implemented as a macro, and it is also used for
- * (gsize *) arguments. However, that leads to compiler warnings in certain
- * configurations. Work around it, by redefining the macro. */
-static inline gpointer
-_g_atomic_pointer_get(void **atomic)
-{
- return g_atomic_pointer_get(atomic);
-}
-#undef g_atomic_pointer_get
-#define g_atomic_pointer_get(atomic) \
- ({ \
- typeof(*atomic) *const _atomic = (atomic); \
- \
- /* g_atomic_pointer_get() is used by glib also for (gsize *) pointers,
- * not only pointers to pointers. We thus don't enforce that (*atomic)
- * is a pointer, but of suitable size/alignment. */ \
- \
- G_STATIC_ASSERT(sizeof(*_atomic) == sizeof(gpointer)); \
- G_STATIC_ASSERT(_nm_alignof(*_atomic) == _nm_alignof(gpointer)); \
- (void) (0 ? (gpointer) * (_atomic) : NULL); \
- \
- (typeof(*_atomic)) _g_atomic_pointer_get((void **) _atomic); \
- })
-
-/* Reimplement g_atomic_pointer_set() macro too. Our variant does more type
- * checks. */
-static inline void
-_g_atomic_pointer_set(void **atomic, void *newval)
-{
- return g_atomic_pointer_set(atomic, newval);
-}
-#undef g_atomic_pointer_set
-#define g_atomic_pointer_set(atomic, newval) \
- ({ \
- typeof(*atomic) *const _atomic = (atomic); \
- typeof(*_atomic) const _newval = (newval); \
- _nm_unused gconstpointer const _val_type_check = _newval; \
- \
- (void) (0 ? (gpointer) * (_atomic) : NULL); \
- \
- _g_atomic_pointer_set((void **) _atomic, (void *) _newval); \
- })
-
-/* Glib implements g_atomic_pointer_compare_and_exchange() as a macro.
- * For one, to inline the atomic operation and also to perform some type checks
- * on the arguments.
- * Depending on compiler and glib version, glib passes the arguments as they
- * are to __atomic_compare_exchange_n(). Some clang version don't accept const
- * pointers there. Reimplement the macro to get that right, but with stronger
- * type checks (as we use typeof()). Had one job. */
-static inline gboolean
-_g_atomic_pointer_compare_and_exchange(void **atomic, void *oldval, void *newval)
-{
- return g_atomic_pointer_compare_and_exchange(atomic, oldval, newval);
-}
-#undef g_atomic_pointer_compare_and_exchange
-#define g_atomic_pointer_compare_and_exchange(atomic, oldval, newval) \
- ({ \
- typeof(*atomic) *const _atomic = (atomic); \
- typeof(*_atomic) const _oldval = (oldval); \
- typeof(*_atomic) const _newval = (newval); \
- _nm_unused gconstpointer const _val_type_check = _oldval; \
- \
- (void) (0 ? (gpointer) * (_atomic) : NULL); \
- \
- _g_atomic_pointer_compare_and_exchange((void **) _atomic, \
- (void *) _oldval, \
- (void *) _newval); \
- })
-
-/*****************************************************************************/
-
-#if !GLIB_CHECK_VERSION(2, 58, 0)
-static inline gboolean
-g_hash_table_steal_extended(GHashTable * hash_table,
- gconstpointer lookup_key,
- gpointer * stolen_key,
- gpointer * stolen_value)
-{
- g_assert(stolen_key);
- g_assert(stolen_value);
-
- if (g_hash_table_lookup_extended(hash_table, lookup_key, stolen_key, stolen_value)) {
- g_hash_table_steal(hash_table, lookup_key);
- return TRUE;
- }
- *stolen_key = NULL;
- *stolen_value = NULL;
- 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
- * 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 \
- })
-#endif
-
-/*****************************************************************************/
-
-__attribute__((
- __deprecated__("Don't use g_cancellable_reset(). Create a new cancellable instead."))) void
-_nm_g_cancellable_reset(GCancellable *cancellable);
-
-#undef g_cancellable_reset
-#define g_cancellable_reset(cancellable) _nm_g_cancellable_reset(cancellable)
-
-/*****************************************************************************/
-
-#endif /* __NM_GLIB_H__ */
diff --git a/shared/nm-glib-aux/nm-hash-utils.c b/shared/nm-glib-aux/nm-hash-utils.c
deleted file mode 100644
index 29349b1d0d..0000000000
--- a/shared/nm-glib-aux/nm-hash-utils.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2017 Red Hat, Inc.
- */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-hash-utils.h"
-
-#include <stdint.h>
-
-#include "nm-shared-utils.h"
-#include "nm-random-utils.h"
-
-/*****************************************************************************/
-
-#define HASH_KEY_SIZE 16u
-#define HASH_KEY_SIZE_GUINT ((HASH_KEY_SIZE + sizeof(guint) - 1) / sizeof(guint))
-
-G_STATIC_ASSERT(sizeof(guint) * HASH_KEY_SIZE_GUINT >= HASH_KEY_SIZE);
-
-static const guint8 *volatile global_seed = NULL;
-
-static const guint8 *
-_get_hash_key_init(void)
-{
- /* the returned hash is aligned to guin64, hence, it is safe
- * to use it as guint* or guint64* pointer. */
- static union {
- guint8 v8[HASH_KEY_SIZE];
- guint _align_as_uint;
- guint32 _align_as_uint32;
- guint64 _align_as_uint64;
- } g_arr;
- const guint8 *g;
-
-again:
- g = g_atomic_pointer_get(&global_seed);
- if (!G_UNLIKELY(g)) {
- static gsize g_lock;
- uint64_t h;
- union {
- guint vuint;
- guint8 v8[HASH_KEY_SIZE];
- guint8 _extra_entropy[3 * HASH_KEY_SIZE];
- } t_arr;
-
- nm_utils_random_bytes(&t_arr, sizeof(t_arr));
-
- /* We only initialize one random hash key. So we can spend some effort
- * of getting this right. For one, we collect more random bytes than
- * necessary.
- *
- * Then, the first guint of the seed should have all the entropy that we could
- * obtain in sizeof(t_arr). For that, siphash(t_arr) and xor the first guint
- * with hash.
- * The first guint is especially interesting for nm_hash_static() below that
- * doesn't use siphash itself. */
- h = c_siphash_hash(t_arr.v8, (const guint8 *) &t_arr, sizeof(t_arr));
- if (sizeof(h) > sizeof(guint))
- t_arr.vuint = t_arr.vuint ^ ((guint)(h & G_MAXUINT)) ^ ((guint)(h >> 32));
- else
- t_arr.vuint = t_arr.vuint ^ ((guint)(h & G_MAXUINT));
-
- if (!g_once_init_enter(&g_lock)) {
- /* lost a race. The random key is already initialized. */
- goto again;
- }
-
- memcpy(g_arr.v8, t_arr.v8, HASH_KEY_SIZE);
- g = g_arr.v8;
- g_atomic_pointer_set(&global_seed, g);
- g_once_init_leave(&g_lock, 1);
- }
-
- nm_assert(g == g_arr.v8);
- return g;
-}
-
-#define _get_hash_key() \
- ({ \
- const guint8 *_g; \
- \
- _g = g_atomic_pointer_get(&global_seed); \
- if (G_UNLIKELY(!_g)) \
- _g = _get_hash_key_init(); \
- _g; \
- })
-
-guint
-nm_hash_static(guint static_seed)
-{
- /* Note that we only xor the static_seed with the first guint of the key.
- *
- * We don't use siphash, which would mix the bits better with _get_hash_key().
- * Note that nm_hash_static() isn't used to hash the static_seed. Instead, it
- * is used to get a unique hash value in a static context. That means, every
- * caller is responsible to choose a static_seed that is sufficiently
- * distinct from all other callers. In other words, static_seed should be a
- * unique constant with good entropy.
- *
- * Note that _get_hash_key_init() already xored the first guint of the
- * key with the siphash of the entire static key. That means, even if
- * we got bad randomness for the first guint, the first guint is also
- * mixed with the randomness of the entire random key.
- *
- * Also, ensure that we don't return zero (like for nm_hash_complete()).
- */
- return ((*((const guint *) _get_hash_key())) ^ static_seed) ?: 3679500967u;
-}
-
-void
-nm_hash_siphash42_init(CSipHash *h, guint static_seed)
-{
- const guint8 *g;
- union {
- guint64 _align_as_uint64;
- guint arr[HASH_KEY_SIZE_GUINT];
- } seed;
-
- nm_assert(h);
-
- g = _get_hash_key();
- memcpy(&seed, g, HASH_KEY_SIZE);
- seed.arr[0] ^= static_seed;
- c_siphash_init(h, (const guint8 *) &seed);
-}
-
-guint
-nm_hash_str(const char *str)
-{
- NMHashState h;
-
- if (!str)
- return nm_hash_static(1867854211u);
- nm_hash_init(&h, 1867854211u);
- nm_hash_update_str(&h, str);
- return nm_hash_complete(&h);
-}
-
-guint
-nm_str_hash(gconstpointer str)
-{
- return nm_hash_str(str);
-}
-
-guint
-nm_hash_ptr(gconstpointer ptr)
-{
- NMHashState h;
-
- if (!ptr)
- return nm_hash_static(2907677551u);
- nm_hash_init(&h, 2907677551u);
- nm_hash_update(&h, &ptr, sizeof(ptr));
- return nm_hash_complete(&h);
-}
-
-guint
-nm_direct_hash(gconstpointer ptr)
-{
- return nm_hash_ptr(ptr);
-}
-
-/*****************************************************************************/
-
-guint
-nm_pstr_hash(gconstpointer p)
-{
- const char *const *s = p;
-
- if (!s)
- return nm_hash_static(101061439u);
- return nm_hash_str(*s);
-}
-
-gboolean
-nm_pstr_equal(gconstpointer a, gconstpointer b)
-{
- const char *const *s1 = a;
- const char *const *s2 = b;
-
- return (s1 == s2) || (s1 && s2 && nm_streq0(*s1, *s2));
-}
-
-guint
-nm_pint_hash(gconstpointer p)
-{
- const int *s = p;
-
- if (!s)
- return nm_hash_static(298377461u);
- return nm_hash_val(1208815757u, *s);
-}
-
-gboolean
-nm_pint_equals(gconstpointer a, gconstpointer b)
-{
- const int *s1 = a;
- const int *s2 = a;
-
- return s1 == s2 || (s1 && s2 && *s1 == *s2);
-}
-
-guint
-nm_pdirect_hash(gconstpointer p)
-{
- const void *const *s = p;
-
- if (!s)
- return nm_hash_static(1852748873u);
- return nm_direct_hash(*s);
-}
-
-gboolean
-nm_pdirect_equal(gconstpointer a, gconstpointer b)
-{
- const void *const *s1 = a;
- const void *const *s2 = b;
-
- return (s1 == s2) || (s1 && s2 && *s1 == *s2);
-}
-
-guint
-nm_ppdirect_hash(gconstpointer p)
-{
- const void *const *const *s = p;
-
- if (!s)
- return nm_hash_static(396534869u);
- if (!*s)
- return nm_hash_static(1476102263u);
- return nm_direct_hash(**s);
-}
-
-gboolean
-nm_ppdirect_equal(gconstpointer a, gconstpointer b)
-{
- const void *const *const *s1 = a;
- const void *const *const *s2 = b;
-
- if (s1 == s2)
- return TRUE;
- if (!s1 || !s2)
- return FALSE;
-
- if (*s1 == *s2)
- return TRUE;
- if (!*s1 || !*s2)
- return FALSE;
-
- return **s1 == **s2;
-}
-
-/*****************************************************************************/
-
-guint
-nm_gbytes_hash(gconstpointer p)
-{
- GBytes * ptr = (GBytes *) p;
- gconstpointer arr;
- gsize len;
-
- arr = g_bytes_get_data(ptr, &len);
- return nm_hash_mem(792701303u, arr, len);
-}
-
-guint
-nm_pgbytes_hash(gconstpointer p)
-{
- GBytes *const *ptr = p;
- gconstpointer arr;
- gsize len;
-
- arr = g_bytes_get_data(*ptr, &len);
- return nm_hash_mem(1470631313u, arr, len);
-}
-
-gboolean
-nm_pgbytes_equal(gconstpointer a, gconstpointer b)
-{
- GBytes *const *ptr_a = a;
- GBytes *const *ptr_b = b;
-
- return g_bytes_equal(*ptr_a, *ptr_b);
-}
diff --git a/shared/nm-glib-aux/nm-hash-utils.h b/shared/nm-glib-aux/nm-hash-utils.h
deleted file mode 100644
index a7b8677bf5..0000000000
--- a/shared/nm-glib-aux/nm-hash-utils.h
+++ /dev/null
@@ -1,442 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2017 Red Hat, Inc.
- */
-
-#ifndef __NM_HASH_UTILS_H__
-#define __NM_HASH_UTILS_H__
-
-#include "c-siphash/src/c-siphash.h"
-#include "nm-macros-internal.h"
-
-/*****************************************************************************/
-
-#define NM_HASH_SEED_16(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af) \
- ((const guint8[16]){a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, aa, ab, ac, ad, ae, af})
-
-void nm_hash_siphash42_init(CSipHash *h, guint static_seed);
-
-/* Siphash24 of binary buffer @arr and @len, using the randomized seed from
- * other NMHash functions.
- *
- * Note, that this is guaranteed to use siphash42 under the hood (contrary to
- * all other NMHash API, which leave this undefined). That matters at the point,
- * where the caller needs to be sure that a reasonably strong hashing algorithm
- * is used. (Yes, NMHash is all about siphash24, but otherwise that is not promised
- * anywhere).
- *
- * Another difference is, that this returns guint64 (not guint like other NMHash functions).
- *
- * Another difference is, that this may also return zero (not like nm_hash_complete()).
- *
- * Then, why not use c_siphash_hash() directly? Because this also uses the randomized,
- * per-run hash-seed like nm_hash_init(). So, you get siphash24 with a random
- * seed (which is cached for the current run of the program).
- */
-static inline guint64
-nm_hash_siphash42(guint static_seed, const void *ptr, gsize n)
-{
- CSipHash h;
-
- nm_hash_siphash42_init(&h, static_seed);
- c_siphash_append(&h, ptr, n);
- return c_siphash_finalize(&h);
-}
-
-/*****************************************************************************/
-
-struct _NMHashState {
- CSipHash _state;
-};
-
-typedef struct _NMHashState NMHashState;
-
-guint nm_hash_static(guint static_seed);
-
-static inline void
-nm_hash_init(NMHashState *state, guint static_seed)
-{
- nm_assert(state);
-
- nm_hash_siphash42_init(&state->_state, static_seed);
-}
-
-static inline guint64
-nm_hash_complete_u64(NMHashState *state)
-{
- nm_assert(state);
-
- /* this returns the native u64 hash value. Note that this differs
- * from nm_hash_complete() in two ways:
- *
- * - the type, guint64 vs. guint.
- * - nm_hash_complete() never returns zero.
- *
- * In practice, nm_hash*() API is implemented via siphash24, so this returns
- * the siphash24 value. But that is not guaranteed by the API, and if you need
- * siphash24 directly, use c_siphash_*() and nm_hash_siphash42*() API. */
- return c_siphash_finalize(&state->_state);
-}
-
-static inline guint
-nm_hash_complete(NMHashState *state)
-{
- guint64 h;
-
- h = nm_hash_complete_u64(state);
-
- /* we don't ever want to return a zero hash.
- *
- * NMPObject requires that in _idx_obj_part(), and it's just a good idea. */
- return (((guint)(h >> 32)) ^ ((guint) h)) ?: 1396707757u;
-}
-
-static inline void
-nm_hash_update(NMHashState *state, const void *ptr, gsize n)
-{
- nm_assert(state);
- nm_assert(n == 0 || ptr);
-
- /* Note: the data passed in here might be sensitive data (secrets),
- * that we should nm_explicit_bzero() afterwards. However, since
- * we are using siphash24 with a random key, that is not really
- * necessary. Something to keep in mind, if we ever move away from
- * this hash implementation. */
- c_siphash_append(&state->_state, ptr, n);
-}
-
-#define nm_hash_update_val(state, val) \
- G_STMT_START \
- { \
- typeof(val) _val = (val); \
- \
- nm_hash_update((state), &_val, sizeof(_val)); \
- } \
- G_STMT_END
-
-#define nm_hash_update_valp(state, val) nm_hash_update((state), (val), sizeof(*(val)))
-
-static inline void
-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_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__)
-
-/* 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__)}
-
-/* nm_hash_update_vals() is faster then nm_hash_update_val() as it combines multiple
- * calls to nm_hash_update() using a packed structure. */
-#define nm_hash_update_vals(state, ...) \
- G_STMT_START \
- { \
- NM_HASH_COMBINE_VALS(_val, __VA_ARGS__); \
- \
- nm_hash_update((state), &_val, sizeof(_val)); \
- } \
- G_STMT_END
-
-static inline void
-nm_hash_update_mem(NMHashState *state, const void *ptr, gsize n)
-{
- /* This also hashes the length of the data. That means,
- * hashing two consecutive binary fields (of arbitrary
- * length), will hash differently. That is,
- * [[1,1], []] differs from [[1],[1]].
- *
- * If you have a constant length (sizeof), use nm_hash_update()
- * instead. */
- nm_hash_update(state, &n, sizeof(n));
- if (n > 0)
- nm_hash_update(state, ptr, n);
-}
-
-static inline void
-nm_hash_update_str0(NMHashState *state, const char *str)
-{
- if (str)
- nm_hash_update_mem(state, str, strlen(str));
- else {
- gsize n = G_MAXSIZE;
-
- nm_hash_update(state, &n, sizeof(n));
- }
-}
-
-static inline void
-nm_hash_update_str(NMHashState *state, const char *str)
-{
- nm_assert(str);
- nm_hash_update(state, str, strlen(str) + 1);
-}
-
-#if _NM_CC_SUPPORT_GENERIC
- /* 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))))
-#else
- #define nm_hash_update_strarr(state, str) nm_hash_update_str((state), (str))
-#endif
-
-guint nm_hash_ptr(gconstpointer ptr);
-guint nm_direct_hash(gconstpointer str);
-
-guint nm_hash_str(const char *str);
-guint nm_str_hash(gconstpointer str);
-
-#define nm_hash_val(static_seed, val) \
- ({ \
- NMHashState _h; \
- \
- nm_hash_init(&_h, (static_seed)); \
- nm_hash_update_val(&_h, (val)); \
- nm_hash_complete(&_h); \
- })
-
-static inline guint
-nm_hash_mem(guint static_seed, const void *ptr, gsize n)
-{
- NMHashState h;
-
- if (n == 0)
- return nm_hash_static(static_seed);
- nm_hash_init(&h, static_seed);
- nm_hash_update(&h, ptr, n);
- return nm_hash_complete(&h);
-}
-
-/*****************************************************************************/
-
-/* nm_pstr_*() are for hashing keys that are pointers to strings,
- * that is, "const char *const*" types, using strcmp(). */
-
-guint nm_pstr_hash(gconstpointer p);
-
-gboolean nm_pstr_equal(gconstpointer a, gconstpointer b);
-
-/*****************************************************************************/
-
-/* nm_pint_*() are for hashing keys that are pointers to int values,
- * that is, "const int *" types. */
-
-guint nm_pint_hash(gconstpointer p);
-gboolean nm_pint_equals(gconstpointer a, gconstpointer b);
-
-G_STATIC_ASSERT(sizeof(int) == sizeof(guint32));
-#define nm_puint32_hash nm_pint_hash
-#define nm_puint32_equals nm_pint_equals
-
-/*****************************************************************************/
-
-/* this hashes/compares the pointer value that we point to. Basically,
- * (*((const void *const*) a) == *((const void *const*) b)). */
-
-guint nm_pdirect_hash(gconstpointer p);
-
-gboolean nm_pdirect_equal(gconstpointer a, gconstpointer b);
-
-/* this hashes/compares the direct pointer value by following pointers to
- * pointers 2 times.
- * (**((const void *const*const*) a) == **((const void *const*const*) b)). */
-
-guint nm_ppdirect_hash(gconstpointer p);
-
-gboolean nm_ppdirect_equal(gconstpointer a, gconstpointer b);
-
-/*****************************************************************************/
-
-guint nm_gbytes_hash(gconstpointer p);
-#define nm_gbytes_equal g_bytes_equal
-
-guint nm_pgbytes_hash(gconstpointer p);
-gboolean nm_pgbytes_equal(gconstpointer a, gconstpointer b);
-
-/*****************************************************************************/
-
-#define NM_HASH_OBFUSCATE_PTR_FMT "%016" G_GINT64_MODIFIER "x"
-
-/* sometimes we want to log a pointer directly, for providing context/information about
- * the message that get logged. Logging pointer values directly defeats ASLR, so we should
- * not do that. This returns a "unsigned long long" value that can be used
- * instead.
- *
- * Note that there is a chance that two different pointer values hash to the same obfuscated
- * value. So beware of that when reviewing logs. However, such a collision is very unlikely. */
-static inline guint64
-nm_hash_obfuscate_ptr(guint static_seed, gconstpointer val)
-{
- NMHashState h;
-
- nm_hash_init(&h, static_seed);
- nm_hash_update_val(&h, val);
- return nm_hash_complete_u64(&h);
-}
-
-/* if you want to log obfuscated pointer for a certain context (like, NMPRuleManager
- * logging user-tags), then you are advised to use nm_hash_obfuscate_ptr() with your
- * own, unique static-seed.
- *
- * However, for example the singleton constructors log the obfuscated pointer values
- * for all singletons, so they must all be obfuscated with the same seed. So, this
- * macro uses a particular static seed that should be used by when comparing pointer
- * values in a global context. */
-#define NM_HASH_OBFUSCATE_PTR(ptr) (nm_hash_obfuscate_ptr(1678382159u, ptr))
-
-#define NM_HASH_OBFUSCATE_PTR_STR(ptr, buf) \
- ({ \
- gconstpointer _ptr = (ptr); \
- \
- _ptr ? nm_sprintf_buf(buf, "[" NM_HASH_OBFUSCATE_PTR_FMT "]", NM_HASH_OBFUSCATE_PTR(_ptr)) \
- : "(null)"; \
- })
-
-static inline const char *
-nm_hash_obfuscated_ptr_str(gconstpointer ptr, char buf[static 17])
-{
- int l;
-
- nm_assert(buf);
- l = g_snprintf(buf, 17, NM_HASH_OBFUSCATE_PTR_FMT, NM_HASH_OBFUSCATE_PTR(ptr));
- nm_assert(l < 17);
- return buf;
-}
-
-#define nm_hash_obfuscated_ptr_str_a(ptr) (nm_hash_obfuscated_ptr_str((ptr), g_alloca(17)))
-
-/*****************************************************************************/
-
-#endif /* __NM_HASH_UTILS_H__ */
diff --git a/shared/nm-glib-aux/nm-io-utils.c b/shared/nm-glib-aux/nm-io-utils.c
deleted file mode 100644
index 429591ad22..0000000000
--- a/shared/nm-glib-aux/nm-io-utils.c
+++ /dev/null
@@ -1,480 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2018 Red Hat, Inc.
- */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-io-utils.h"
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "nm-str-buf.h"
-#include "nm-shared-utils.h"
-#include "nm-secret-utils.h"
-#include "nm-errno.h"
-
-/*****************************************************************************/
-
-_nm_printf(4, 5) static int _get_contents_error(GError ** error,
- int errsv,
- int * out_errsv,
- const char *format,
- ...)
-{
- nm_assert(NM_ERRNO_NATIVE(errsv));
-
- if (error) {
- gs_free char *msg = NULL;
- va_list args;
- char bstrerr[NM_STRERROR_BUFSIZE];
-
- va_start(args, format);
- msg = g_strdup_vprintf(format, args);
- va_end(args);
- g_set_error(error,
- G_FILE_ERROR,
- g_file_error_from_errno(errsv),
- "%s: %s",
- msg,
- nm_strerror_native_r(errsv, bstrerr, sizeof(bstrerr)));
- }
-
- nm_assert(errsv > 0);
- NM_SET_OUT(out_errsv, errsv);
-
- return FALSE;
-}
-#define _get_contents_error_errno(error, out_errsv, ...) \
- ({ \
- int _errsv = (errno); \
- \
- _get_contents_error(error, _errsv, out_errsv, __VA_ARGS__); \
- })
-
-/**
- * nm_utils_fd_get_contents:
- * @fd: open file descriptor to read. The fd will not be closed,
- * but don't rely on its state afterwards.
- * @close_fd: if %TRUE, @fd will be closed by the function.
- * Passing %TRUE here might safe a syscall for dup().
- * @max_length: allocate at most @max_length bytes. If the
- * file is larger, reading will fail. Set to zero to use
- * a very large default.
- * WARNING: @max_length is here to avoid a crash for huge/unlimited files.
- * For example, stat(/sys/class/net/enp0s25/ifindex) gives a filesize of
- * 4K, although the actual real is small. @max_length is the memory
- * allocated in the process of reading the file, thus it must be at least
- * the size reported by fstat.
- * If you set it to 1K, read will fail because fstat() claims the
- * file is larger.
- * @flags: %NMUtilsFileGetContentsFlags for reading the file.
- * @contents: the output buffer with the file read. It is always
- * NUL terminated. The buffer is at most @max_length long, including
- * the NUL byte. That is, it reads only files up to a length of
- * @max_length - 1 bytes.
- * @length: optional output argument of the read file size.
- * @out_errsv: (allow-none) (out): on error, a positive errno. or zero.
- * @error:
- *
- *
- * A reimplementation of g_file_get_contents() with a few differences:
- * - accepts an open fd, instead of a path name. This allows you to
- * use openat().
- * - limits the maximum filesize to max_length.
- *
- * Returns: TRUE on success.
- */
-gboolean
-nm_utils_fd_get_contents(int fd,
- gboolean close_fd,
- gsize max_length,
- NMUtilsFileGetContentsFlags flags,
- char ** contents,
- gsize * length,
- int * out_errsv,
- GError ** error)
-{
- nm_auto_close int fd_keeper = close_fd ? fd : -1;
- struct stat stat_buf;
- gs_free char * str = NULL;
- const bool do_bzero_mem = NM_FLAGS_HAS(flags, NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET);
- int errsv;
-
- g_return_val_if_fail(fd >= 0, FALSE);
- g_return_val_if_fail(contents && !*contents, FALSE);
- g_return_val_if_fail(!error || !*error, FALSE);
-
- NM_SET_OUT(length, 0);
-
- if (fstat(fd, &stat_buf) < 0)
- return _get_contents_error_errno(error, out_errsv, "failure during fstat");
-
- if (!max_length) {
- /* default to a very large size, but not extreme */
- max_length = 2 * 1024 * 1024;
- }
-
- if (stat_buf.st_size > 0 && S_ISREG(stat_buf.st_mode)) {
- const gsize n_stat = stat_buf.st_size;
- ssize_t n_read;
-
- if (n_stat > max_length - 1)
- return _get_contents_error(error,
- EMSGSIZE,
- out_errsv,
- "file too large (%zu+1 bytes with maximum %zu bytes)",
- n_stat,
- max_length);
-
- str = g_try_malloc(n_stat + 1);
- if (!str)
- return _get_contents_error(error,
- ENOMEM,
- out_errsv,
- "failure to allocate buffer of %zu+1 bytes",
- n_stat);
-
- n_read = nm_utils_fd_read_loop(fd, str, n_stat, TRUE);
- if (n_read < 0) {
- if (do_bzero_mem)
- nm_explicit_bzero(str, n_stat);
- return _get_contents_error(error,
- -n_read,
- out_errsv,
- "error reading %zu bytes from file descriptor",
- n_stat);
- }
- str[n_read] = '\0';
-
- if (n_read < n_stat) {
- if (!(str = nm_secret_mem_try_realloc_take(str, do_bzero_mem, n_stat + 1, n_read + 1)))
- return _get_contents_error(error,
- ENOMEM,
- out_errsv,
- "failure to reallocate buffer with %zu bytes",
- n_read + 1);
- }
- NM_SET_OUT(length, n_read);
- } else {
- nm_auto_fclose FILE *f = NULL;
- char buf[4096];
- gsize n_have, n_alloc;
- int fd2;
-
- if (fd_keeper >= 0)
- fd2 = nm_steal_fd(&fd_keeper);
- else {
- fd2 = fcntl(fd, F_DUPFD_CLOEXEC, 0);
- if (fd2 < 0)
- return _get_contents_error_errno(error, out_errsv, "error during dup");
- }
-
- if (!(f = fdopen(fd2, "r"))) {
- errsv = errno;
- nm_close(fd2);
- return _get_contents_error(error, errsv, out_errsv, "failure during fdopen");
- }
-
- n_have = 0;
- n_alloc = 0;
-
- while (!feof(f)) {
- gsize n_read;
-
- n_read = fread(buf, 1, sizeof(buf), f);
- errsv = errno;
- if (ferror(f)) {
- if (do_bzero_mem)
- nm_explicit_bzero(buf, sizeof(buf));
- return _get_contents_error(error, errsv, out_errsv, "error during fread");
- }
-
- if (n_have > G_MAXSIZE - 1 - n_read || n_have + n_read + 1 > max_length) {
- if (do_bzero_mem)
- nm_explicit_bzero(buf, sizeof(buf));
- return _get_contents_error(
- error,
- EMSGSIZE,
- out_errsv,
- "file stream too large (%zu+1 bytes with maximum %zu bytes)",
- (n_have > G_MAXSIZE - 1 - n_read) ? G_MAXSIZE : n_have + n_read,
- max_length);
- }
-
- if (n_have + n_read + 1 >= n_alloc) {
- gsize old_n_alloc = n_alloc;
-
- if (n_alloc != 0) {
- nm_assert(str);
- if (n_alloc >= max_length / 2)
- n_alloc = max_length;
- else
- n_alloc *= 2;
- } else {
- nm_assert(!str);
- n_alloc = NM_MIN(n_read + 1, sizeof(buf));
- }
-
- if (!(str = nm_secret_mem_try_realloc_take(str,
- do_bzero_mem,
- old_n_alloc,
- n_alloc))) {
- if (do_bzero_mem)
- nm_explicit_bzero(buf, sizeof(buf));
- return _get_contents_error(error,
- ENOMEM,
- out_errsv,
- "failure to allocate buffer of %zu bytes",
- n_alloc);
- }
- }
-
- memcpy(str + n_have, buf, n_read);
- n_have += n_read;
- }
-
- if (do_bzero_mem)
- nm_explicit_bzero(buf, sizeof(buf));
-
- if (n_alloc == 0)
- str = g_new0(char, 1);
- else {
- str[n_have] = '\0';
- if (n_have + 1 < n_alloc) {
- if (!(str = nm_secret_mem_try_realloc_take(str, do_bzero_mem, n_alloc, n_have + 1)))
- return _get_contents_error(error,
- ENOMEM,
- out_errsv,
- "failure to truncate buffer to %zu bytes",
- n_have + 1);
- }
- }
-
- NM_SET_OUT(length, n_have);
- }
-
- *contents = g_steal_pointer(&str);
- NM_SET_OUT(out_errsv, 0);
- return TRUE;
-}
-
-/**
- * nm_utils_file_get_contents:
- * @dirfd: optional file descriptor to use openat(). If negative, use plain open().
- * @filename: the filename to open. Possibly relative to @dirfd.
- * @max_length: allocate at most @max_length bytes.
- * WARNING: see nm_utils_fd_get_contents() hint about @max_length.
- * @flags: %NMUtilsFileGetContentsFlags for reading the file.
- * @contents: the output buffer with the file read. It is always
- * NUL terminated. The buffer is at most @max_length long, including
- * the NUL byte. That is, it reads only files up to a length of
- * @max_length - 1 bytes.
- * @length: optional output argument of the read file size.
- * @out_errsv: (allow-none) (out): on error, a positive errno. or zero.
- * @error:
- *
- * A reimplementation of g_file_get_contents() with a few differences:
- * - accepts an @dirfd to open @filename relative to that path via openat().
- * - limits the maximum filesize to max_length.
- * - uses O_CLOEXEC on internal file descriptor
- * - optionally returns the native errno on failure.
- *
- * Returns: TRUE on success.
- */
-gboolean
-nm_utils_file_get_contents(int dirfd,
- const char * filename,
- gsize max_length,
- NMUtilsFileGetContentsFlags flags,
- char ** contents,
- gsize * length,
- int * out_errsv,
- GError ** error)
-{
- int fd;
-
- g_return_val_if_fail(filename && filename[0], FALSE);
- g_return_val_if_fail(contents && !*contents, FALSE);
-
- NM_SET_OUT(length, 0);
-
- if (dirfd >= 0) {
- fd = openat(dirfd, filename, O_RDONLY | O_CLOEXEC);
- if (fd < 0) {
- return _get_contents_error_errno(error,
- out_errsv,
- "Failed to open file \"%s\" with openat",
- filename);
- }
- } else {
- fd = open(filename, O_RDONLY | O_CLOEXEC);
- if (fd < 0) {
- return _get_contents_error_errno(error,
- out_errsv,
- "Failed to open file \"%s\"",
- filename);
- }
- }
- return nm_utils_fd_get_contents(fd,
- TRUE,
- max_length,
- flags,
- contents,
- length,
- out_errsv,
- error);
-}
-
-/*****************************************************************************/
-
-/*
- * Copied from GLib's g_file_set_contents() et al., but allows
- * specifying a mode for the new file.
- */
-gboolean
-nm_utils_file_set_contents(const char *filename,
- const char *contents,
- gssize length,
- mode_t mode,
- int * out_errsv,
- GError ** error)
-{
- gs_free char *tmp_name = NULL;
- struct stat statbuf;
- int errsv;
- gssize s;
- int fd;
-
- g_return_val_if_fail(filename, FALSE);
- g_return_val_if_fail(contents || !length, FALSE);
- g_return_val_if_fail(!error || !*error, FALSE);
- g_return_val_if_fail(length >= -1, FALSE);
-
- if (length == -1)
- length = strlen(contents);
-
- tmp_name = g_strdup_printf("%s.XXXXXX", filename);
- fd = g_mkstemp_full(tmp_name, O_RDWR | O_CLOEXEC, mode);
- if (fd < 0) {
- return _get_contents_error_errno(error, out_errsv, "failed to create file %s", tmp_name);
- }
-
- while (length > 0) {
- s = write(fd, contents, length);
- if (s < 0) {
- errsv = NM_ERRNO_NATIVE(errno);
- if (errsv == EINTR)
- continue;
-
- nm_close(fd);
- unlink(tmp_name);
- return _get_contents_error(error,
- errsv,
- out_errsv,
- "failed to write to file %s",
- tmp_name);
- }
-
- g_assert(s <= length);
-
- contents += s;
- length -= s;
- }
-
- /* If the final destination exists and is > 0 bytes, we want to sync the
- * newly written file to ensure the data is on disk when we rename over
- * the destination. Otherwise, if we get a system crash we can lose both
- * the new and the old file on some filesystems. (I.E. those that don't
- * guarantee the data is written to the disk before the metadata.)
- */
- if (lstat(filename, &statbuf) == 0 && statbuf.st_size > 0) {
- if (fsync(fd) != 0) {
- errsv = NM_ERRNO_NATIVE(errno);
- nm_close(fd);
- unlink(tmp_name);
- return _get_contents_error(error, errsv, out_errsv, "failed to fsync %s", tmp_name);
- }
- }
-
- nm_close(fd);
-
- if (rename(tmp_name, filename)) {
- errsv = NM_ERRNO_NATIVE(errno);
- unlink(tmp_name);
- return _get_contents_error(error,
- errsv,
- out_errsv,
- "failed rename %s to %s",
- tmp_name,
- filename);
- }
-
- return TRUE;
-}
-
-/**
- * nm_utils_file_stat:
- * @filename: the filename to stat.
- * @out_st: (allow-none) (out): if given, this will be passed to stat().
- *
- * Just wraps stat() and gives the errno number as function result instead
- * of setting the errno (though, errno is also set). It's only for convenience
- * with
- *
- * if (nm_utils_file_stat (filename, NULL) == -ENOENT) {
- * }
- *
- * Returns: 0 on success a negative errno on failure. */
-int
-nm_utils_file_stat(const char *filename, struct stat *out_st)
-{
- struct stat st;
-
- if (stat(filename, out_st ?: &st) != 0)
- return -NM_ERRNO_NATIVE(errno);
- return 0;
-}
-
-/**
- * nm_utils_fd_read:
- * @fd: the fd to read from.
- * @out_string: (out): output string where read bytes will be stored.
- *
- * Returns: <0 on failure, which is -(errno).
- * 0 on EOF.
- * >0 on success, which is the number of bytes read. */
-gssize
-nm_utils_fd_read(int fd, NMStrBuf *out_string)
-{
- gsize buf_available;
- gssize n_read;
- int errsv;
-
- g_return_val_if_fail(fd >= 0, -1);
- g_return_val_if_fail(out_string, -1);
-
- /* If the buffer size is 0, we allocate NM_UTILS_GET_NEXT_REALLOC_SIZE_1000 (1000 bytes)
- * the first time. Afterwards, the buffer grows exponentially.
- *
- * Note that with @buf_available, we always would read as much buffer as we actually
- * have reserved. */
- nm_str_buf_maybe_expand(out_string, NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, FALSE);
-
- buf_available = out_string->allocated - out_string->len;
-
- n_read = read(fd, &((nm_str_buf_get_str_unsafe(out_string))[out_string->len]), buf_available);
- if (n_read < 0) {
- errsv = errno;
- return -NM_ERRNO_NATIVE(errsv);
- }
-
- if (n_read > 0) {
- nm_assert((gsize) n_read <= buf_available);
- nm_str_buf_set_size(out_string, out_string->len + (gsize) n_read, TRUE, FALSE);
- }
-
- return n_read;
-}
diff --git a/shared/nm-glib-aux/nm-io-utils.h b/shared/nm-glib-aux/nm-io-utils.h
deleted file mode 100644
index 8182f5cf60..0000000000
--- a/shared/nm-glib-aux/nm-io-utils.h
+++ /dev/null
@@ -1,58 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_IO_UTILS_H__
-#define __NM_IO_UTILS_H__
-
-#include "nm-macros-internal.h"
-
-/*****************************************************************************/
-
-/**
- * NMUtilsFileGetContentsFlags:
- * @NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE: no flag
- * @NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET: if present, ensure that no
- * data is left in memory. Essentially, it means to call nm_explicit_bzero()
- * to not leave key material on the heap (when reading secrets).
- */
-typedef enum {
- NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE = 0,
- NM_UTILS_FILE_GET_CONTENTS_FLAG_SECRET = (1 << 0),
-} NMUtilsFileGetContentsFlags;
-
-gboolean nm_utils_fd_get_contents(int fd,
- gboolean close_fd,
- gsize max_length,
- NMUtilsFileGetContentsFlags flags,
- char ** contents,
- gsize * length,
- int * out_errsv,
- GError ** error);
-
-gboolean nm_utils_file_get_contents(int dirfd,
- const char * filename,
- gsize max_length,
- NMUtilsFileGetContentsFlags flags,
- char ** contents,
- gsize * length,
- int * out_errsv,
- GError ** error);
-
-gboolean nm_utils_file_set_contents(const char *filename,
- const char *contents,
- gssize length,
- mode_t mode,
- int * out_errsv,
- GError ** error);
-
-struct _NMStrBuf;
-
-gssize nm_utils_fd_read(int fd, struct _NMStrBuf *out_string);
-
-struct stat;
-
-int nm_utils_file_stat(const char *filename, struct stat *out_st);
-
-#endif /* __NM_IO_UTILS_H__ */
diff --git a/shared/nm-glib-aux/nm-jansson.h b/shared/nm-glib-aux/nm-jansson.h
deleted file mode 100644
index 6173a7ac61..0000000000
--- a/shared/nm-glib-aux/nm-jansson.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_JANSSON_H__
-#define __NM_JANSSON_H__
-
-/* you need to include at least "config.h" first, possibly "nm-default.h". */
-
-#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
-
-NM_AUTO_DEFINE_FCN0(json_t *, _nm_auto_decref_json, json_decref);
- #define nm_auto_decref_json nm_auto(_nm_auto_decref_json)
-
-#endif /* WITH_JANSON */
-
-#endif /* __NM_JANSSON_H__ */
diff --git a/shared/nm-glib-aux/nm-json-aux.c b/shared/nm-glib-aux/nm-json-aux.c
deleted file mode 100644
index 97ee606fe0..0000000000
--- a/shared/nm-glib-aux/nm-json-aux.c
+++ /dev/null
@@ -1,286 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2017 - 2019 Red Hat, Inc.
- */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-json-aux.h"
-
-#include <dlfcn.h>
-
-/*****************************************************************************/
-
-/* If RTLD_DEEPBIND isn't available just ignore it. This can cause problems
- * with jansson, json-glib, and cjson symbols clashing (and as such crashing the
- * 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
-#endif
-
-/*****************************************************************************/
-
-static void
-_gstr_append_string_len(GString *gstr, const char *str, gsize len)
-{
- g_string_append_c(gstr, '\"');
-
- while (len > 0) {
- gsize n;
- const char *end;
- gboolean valid;
-
- nm_assert(len > 0);
-
- valid = g_utf8_validate(str, len, &end);
-
- nm_assert(end && end >= str && end <= &str[len]);
-
- if (end > str) {
- const char *s;
-
- for (s = str; s < end; s++) {
- nm_assert(s[0] != '\0');
-
- if (s[0] < 0x20) {
- const char *text;
-
- switch (s[0]) {
- case '\\':
- text = "\\\\";
- break;
- case '\"':
- text = "\\\"";
- break;
- case '\b':
- text = "\\b";
- break;
- case '\f':
- text = "\\f";
- break;
- case '\n':
- text = "\\n";
- break;
- case '\r':
- text = "\\r";
- break;
- case '\t':
- text = "\\t";
- break;
- default:
- g_string_append_printf(gstr, "\\u%04X", (guint) s[0]);
- continue;
- }
- g_string_append(gstr, text);
- continue;
- }
-
- if (NM_IN_SET(s[0], '\\', '\"'))
- g_string_append_c(gstr, '\\');
- g_string_append_c(gstr, s[0]);
- }
- } else
- nm_assert(!valid);
-
- if (valid) {
- nm_assert(end == &str[len]);
- break;
- }
-
- nm_assert(end < &str[len]);
-
- if (end[0] == '\0') {
- /* there is a NUL byte in the string. Technically this is valid UTF-8, so we
- * encode it there. However, this will likely result in a truncated string when
- * parsing. */
- g_string_append(gstr, "\\u0000");
- } else {
- /* the character is not valid UTF-8. There is nothing we can do about it, because
- * JSON can only contain UTF-8 and even the escape sequences can only escape Unicode
- * codepoints (but not binary).
- *
- * The argument is not a string (in any known encoding), hence we cannot represent
- * it as a JSON string (which are unicode strings).
- *
- * Print an underscore instead of the invalid char :) */
- g_string_append_c(gstr, '_');
- }
-
- n = str - end;
- nm_assert(n < len);
- n++;
- str += n;
- len -= n;
- }
-
- g_string_append_c(gstr, '\"');
-}
-
-void
-nm_json_gstr_append_string_len(GString *gstr, const char *str, gsize n)
-{
- g_return_if_fail(gstr);
-
- _gstr_append_string_len(gstr, str, n);
-}
-
-void
-nm_json_gstr_append_string(GString *gstr, const char *str)
-{
- g_return_if_fail(gstr);
-
- if (!str)
- g_string_append(gstr, "null");
- else
- _gstr_append_string_len(gstr, str, strlen(str));
-}
-
-void
-nm_json_gstr_append_obj_name(GString *gstr, const char *key, char start_container)
-{
- g_return_if_fail(gstr);
- g_return_if_fail(key);
-
- nm_json_gstr_append_string(gstr, key);
-
- if (start_container != '\0') {
- nm_assert(NM_IN_SET(start_container, '[', '{'));
- g_string_append_printf(gstr, ": %c ", start_container);
- } else
- g_string_append(gstr, ": ");
-}
-
-/*****************************************************************************/
-
-typedef struct {
- NMJsonVt vt;
- void * dl_handle;
-} NMJsonVtInternal;
-
-static NMJsonVtInternal *
-_nm_json_vt_internal_load(void)
-{
- NMJsonVtInternal *v;
- const char * soname;
- void * handle;
-
- v = g_new0(NMJsonVtInternal, 1);
-
-#if WITH_JANSSON && defined(JANSSON_SONAME)
- G_STATIC_ASSERT_EXPR(NM_STRLEN(JANSSON_SONAME) > 0);
- nm_assert(strlen(JANSSON_SONAME) > 0);
- soname = JANSSON_SONAME;
-#elif !WITH_JANSSON && !defined(JANSSON_SONAME)
- soname = NULL;
-#else
- #error "WITH_JANSON and JANSSON_SONAME are defined inconsistently."
-#endif
-
- if (!soname)
- return v;
-
- handle = dlopen(soname,
- RTLD_LAZY | RTLD_LOCAL | RTLD_NODELETE
-#if !defined(ASAN_BUILD)
- | RTLD_DEEPBIND
-#endif
- | 0);
- if (!handle)
- return v;
-
-#define TRY_BIND_SYMBOL(symbol) \
- G_STMT_START \
- { \
- void *_sym = dlsym(handle, #symbol); \
- \
- if (!_sym) \
- goto fail_symbol; \
- v->vt.nm_##symbol = _sym; \
- } \
- G_STMT_END
-
- TRY_BIND_SYMBOL(json_array);
- TRY_BIND_SYMBOL(json_array_append_new);
- TRY_BIND_SYMBOL(json_array_get);
- TRY_BIND_SYMBOL(json_array_size);
- TRY_BIND_SYMBOL(json_delete);
- TRY_BIND_SYMBOL(json_dumps);
- TRY_BIND_SYMBOL(json_false);
- TRY_BIND_SYMBOL(json_integer);
- TRY_BIND_SYMBOL(json_integer_value);
- TRY_BIND_SYMBOL(json_loads);
- TRY_BIND_SYMBOL(json_object);
- TRY_BIND_SYMBOL(json_object_del);
- TRY_BIND_SYMBOL(json_object_get);
- TRY_BIND_SYMBOL(json_object_iter);
- TRY_BIND_SYMBOL(json_object_iter_key);
- TRY_BIND_SYMBOL(json_object_iter_next);
- TRY_BIND_SYMBOL(json_object_iter_value);
- TRY_BIND_SYMBOL(json_object_key_to_iter);
- TRY_BIND_SYMBOL(json_object_set_new);
- TRY_BIND_SYMBOL(json_object_size);
- TRY_BIND_SYMBOL(json_string);
- TRY_BIND_SYMBOL(json_string_value);
- TRY_BIND_SYMBOL(json_true);
-
- v->vt.loaded = TRUE;
- v->dl_handle = handle;
- return v;
-
-fail_symbol:
- dlclose(&handle);
- *v = (NMJsonVtInternal){};
- return v;
-}
-
-const NMJsonVt *_nm_json_vt_ptr = NULL;
-
-const NMJsonVt *
-_nm_json_vt_init(void)
-{
- NMJsonVtInternal *v;
-
-again:
- v = g_atomic_pointer_get((gpointer *) &_nm_json_vt_ptr);
- if (G_UNLIKELY(!v)) {
- v = _nm_json_vt_internal_load();
- if (!g_atomic_pointer_compare_and_exchange((gpointer *) &_nm_json_vt_ptr, NULL, v)) {
- if (v->dl_handle)
- dlclose(v->dl_handle);
- g_free(v);
- goto again;
- }
-
- /* we transfer ownership. */
- }
-
- nm_assert(v && v == g_atomic_pointer_get((gpointer *) &_nm_json_vt_ptr));
- return &v->vt;
-}
-
-const NMJsonVt *
-nmtst_json_vt_reset(gboolean loaded)
-{
- NMJsonVtInternal *v_old;
- NMJsonVtInternal *v;
-
- v_old = g_atomic_pointer_get((gpointer *) &_nm_json_vt_ptr);
-
- if (!loaded) {
- /* load a fake instance for testing. */
- v = g_new0(NMJsonVtInternal, 1);
- } else
- v = _nm_json_vt_internal_load();
-
- if (!g_atomic_pointer_compare_and_exchange((gpointer *) &_nm_json_vt_ptr, v_old, v))
- g_assert_not_reached();
-
- if (v_old) {
- if (v_old->dl_handle)
- dlclose(v_old->dl_handle);
- g_free((gpointer *) v_old);
- }
-
- return v->vt.loaded ? &v->vt : NULL;
-}
diff --git a/shared/nm-glib-aux/nm-json-aux.h b/shared/nm-glib-aux/nm-json-aux.h
deleted file mode 100644
index 99759a8d27..0000000000
--- a/shared/nm-glib-aux/nm-json-aux.h
+++ /dev/null
@@ -1,312 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2017 - 2019 Red Hat, Inc.
- */
-
-#ifndef __NM_JSON_AUX_H__
-#define __NM_JSON_AUX_H__
-
-#include "nm-value-type.h"
-
-/*****************************************************************************/
-
-static inline GString *
-nm_json_gstr_append_delimiter(GString *gstr)
-{
- g_string_append(gstr, ", ");
- return gstr;
-}
-
-void nm_json_gstr_append_string_len(GString *gstr, const char *str, gsize n);
-
-void nm_json_gstr_append_string(GString *gstr, const char *str);
-
-static inline void
-nm_json_gstr_append_bool(GString *gstr, gboolean v)
-{
- g_string_append(gstr, v ? "true" : "false");
-}
-
-static inline void
-nm_json_gstr_append_int64(GString *gstr, gint64 v)
-{
- g_string_append_printf(gstr, "%" G_GINT64_FORMAT, v);
-}
-
-void nm_json_gstr_append_obj_name(GString *gstr, const char *key, char start_container);
-
-/*****************************************************************************/
-
-#define NM_JSON_REJECT_DUPLICATES 0x1
-
-typedef enum {
- NM_JSON_OBJECT,
- NM_JSON_ARRAY,
- NM_JSON_STRING,
- NM_JSON_INTEGER,
- NM_JSON_REAL,
- NM_JSON_TRUE,
- NM_JSON_FALSE,
- NM_JSON_NULL,
-} nm_json_type;
-
-typedef struct nm_json_t {
- nm_json_type type;
- volatile size_t refcount;
-} nm_json_t;
-
-typedef long long nm_json_int_t;
-
-#define NM_JSON_ERROR_TEXT_LENGTH 160
-#define NM_JSON_ERROR_SOURCE_LENGTH 80
-
-typedef struct nm_json_error_t {
- int line;
- int column;
- int position;
- char source[NM_JSON_ERROR_SOURCE_LENGTH];
- char text[NM_JSON_ERROR_TEXT_LENGTH];
-} nm_json_error_t;
-
-typedef struct {
- gboolean loaded;
- char *(*nm_json_dumps)(const nm_json_t *json, size_t flags);
- const char *(*nm_json_object_iter_key)(void *iter);
- const char *(*nm_json_string_value)(const nm_json_t *json);
- int (*nm_json_array_append_new)(nm_json_t *json, nm_json_t *value);
- int (*nm_json_object_del)(nm_json_t *json, const char *key);
- int (*nm_json_object_set_new)(nm_json_t *json, const char *key, nm_json_t *value);
- nm_json_int_t (*nm_json_integer_value)(const nm_json_t *json);
- nm_json_t *(*nm_json_array)(void);
- nm_json_t *(*nm_json_array_get)(const nm_json_t *json, size_t index);
- nm_json_t *(*nm_json_false)(void);
- nm_json_t *(*nm_json_integer)(nm_json_int_t value);
- nm_json_t *(*nm_json_loads)(const char *string, size_t flags, nm_json_error_t *error);
- nm_json_t *(*nm_json_object)(void);
- nm_json_t *(*nm_json_object_get)(const nm_json_t *json, const char *key);
- nm_json_t *(*nm_json_object_iter_value)(void *);
- nm_json_t *(*nm_json_string)(const char *value);
- nm_json_t *(*nm_json_true)(void);
- size_t (*nm_json_array_size)(const nm_json_t *json);
- size_t (*nm_json_object_size)(const nm_json_t *json);
- void (*nm_json_delete)(nm_json_t *json);
- void *(*nm_json_object_iter)(nm_json_t *json);
- void *(*nm_json_object_iter_next)(nm_json_t *json, void *iter);
- void *(*nm_json_object_key_to_iter)(const char *key);
-} NMJsonVt;
-
-extern const NMJsonVt *_nm_json_vt_ptr;
-
-const NMJsonVt *_nm_json_vt_init(void);
-
-static inline const NMJsonVt *
-_nm_json_vt(void)
-{
- const NMJsonVt *vt;
-
- vt = g_atomic_pointer_get((gpointer *) &_nm_json_vt_ptr);
- if (G_UNLIKELY(!vt)) {
- vt = _nm_json_vt_init();
- nm_assert(vt);
- }
- return vt;
-}
-
-static inline const NMJsonVt *
-nm_json_vt(void)
-{
- const NMJsonVt *vt;
-
- vt = _nm_json_vt();
- return vt->loaded ? vt : NULL;
-}
-
-static inline const NMJsonVt *
-nm_json_vt_assert(void)
-{
- const NMJsonVt *vt;
-
- vt = _nm_json_vt();
- nm_assert(vt->loaded);
- return vt;
-}
-
-const NMJsonVt *nmtst_json_vt_reset(gboolean loaded);
-
-/*****************************************************************************/
-
-#define nm_json_boolean(vt, val) ((val) ? (vt)->nm_json_true() : (vt)->nm_json_false())
-
-static inline void
-nm_json_decref(const NMJsonVt *vt, nm_json_t *json)
-{
- /* Our ref-counting is not threadsafe, unlike libjansson's. But we never
- * share one json_t instance between threads, and if we would, we would very likely
- * wrap a mutex around it. */
- if (json && json->refcount != (size_t) -1 && --json->refcount == 0)
- vt->nm_json_delete(json);
-}
-
-static inline void
-_nm_auto_decref_json(nm_json_t **p_json)
-{
- if (*p_json && (*p_json)->refcount != (size_t) -1 && --(*p_json)->refcount == 0)
- nm_json_vt()->nm_json_delete(*p_json);
-}
-
-#define nm_auto_decref_json nm_auto(_nm_auto_decref_json)
-
-/*****************************************************************************/
-
-/* the following are implemented as pure macros in jansson.h.
- * They can be used directly, however, add a nm_json* variant,
- * to make it explict we don't accidentally use jansson ABI. */
-
-#define nm_json_typeof(json) ((json)->type)
-#define nm_json_is_object(json) ((json) && nm_json_typeof(json) == NM_JSON_OBJECT)
-#define nm_json_is_array(json) ((json) && nm_json_typeof(json) == NM_JSON_ARRAY)
-#define nm_json_is_string(json) ((json) && nm_json_typeof(json) == NM_JSON_STRING)
-#define nm_json_is_integer(json) ((json) && nm_json_typeof(json) == NM_JSON_INTEGER)
-#define nm_json_is_real(json) ((json) && nm_json_typeof(json) == NM_JSON_REAL)
-#define nm_json_is_number(json) (nm_json_is_integer(json) || nm_json_is_real(json))
-#define nm_json_is_true(json) ((json) && nm_json_typeof(json) == NM_JSON_TRUE)
-#define nm_json_is_false(json) ((json) && nm_json_typeof(json) == NM_JSON_FALSE)
-#define nm_json_boolean_value nm_json_is_true
-#define nm_json_is_boolean(json) (nm_json_is_true(json) || nm_json_is_false(json))
-#define nm_json_is_null(json) ((json) && nm_json_typeof(json) == NM_JSON_NULL)
-
-#define nm_json_array_foreach(vt, array, index, value) \
- for (index = 0; \
- index < vt->nm_json_array_size(array) && (value = vt->nm_json_array_get(array, index)); \
- index++)
-
-#define nm_json_object_foreach(vt, object, key, value) \
- for (key = vt->nm_json_object_iter_key(vt->nm_json_object_iter(object)); \
- key && (value = vt->nm_json_object_iter_value(vt->nm_json_object_key_to_iter(key))); \
- key = vt->nm_json_object_iter_key( \
- vt->nm_json_object_iter_next(object, vt->nm_json_object_key_to_iter(key))))
-
-/*****************************************************************************/
-
-static inline int
-nm_jansson_json_as_bool(const nm_json_t *elem, bool *out_val)
-{
- if (!elem)
- return 0;
-
- if (!nm_json_is_boolean(elem))
- return -EINVAL;
-
- NM_SET_OUT(out_val, nm_json_boolean_value(elem));
- return 1;
-}
-
-static inline int
-nm_jansson_json_as_int32(const NMJsonVt *vt, const nm_json_t *elem, gint32 *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 < (gint64) G_MININT32 || v > (gint64) G_MAXINT32)
- return -ERANGE;
-
- NM_SET_OUT(out_val, v);
- return 1;
-}
-
-static inline int
-nm_jansson_json_as_int(const NMJsonVt *vt, const nm_json_t *elem, int *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 < (gint64) G_MININT || v > (gint64) G_MAXINT)
- return -ERANGE;
-
- NM_SET_OUT(out_val, v);
- return 1;
-}
-
-static inline int
-nm_jansson_json_as_string(const NMJsonVt *vt, const nm_json_t *elem, const char **out_val)
-{
- if (!elem)
- return 0;
-
- if (!nm_json_is_string(elem))
- return -EINVAL;
-
- NM_SET_OUT(out_val, vt->nm_json_string_value(elem));
- return 1;
-}
-
-/*****************************************************************************/
-
-#ifdef NM_VALUE_TYPE_DEFINE_FUNCTIONS
-
-static inline void
-nm_value_type_to_json(NMValueType value_type, GString *gstr, gconstpointer p_field)
-{
- nm_assert(p_field);
- nm_assert(gstr);
-
- switch (value_type) {
- case NM_VALUE_TYPE_BOOL:
- nm_json_gstr_append_bool(gstr, *((const bool *) p_field));
- return;
- case NM_VALUE_TYPE_INT32:
- nm_json_gstr_append_int64(gstr, *((const gint32 *) p_field));
- return;
- case NM_VALUE_TYPE_INT:
- nm_json_gstr_append_int64(gstr, *((const int *) p_field));
- return;
- case NM_VALUE_TYPE_STRING:
- nm_json_gstr_append_string(gstr, *((const char *const *) p_field));
- return;
- case NM_VALUE_TYPE_UNSPEC:
- break;
- }
- nm_assert_not_reached();
-}
-
-static inline gboolean
-nm_value_type_from_json(const NMJsonVt * vt,
- NMValueType value_type,
- const nm_json_t *elem,
- gpointer out_val)
-{
- switch (value_type) {
- case NM_VALUE_TYPE_BOOL:
- return (nm_jansson_json_as_bool(elem, out_val) > 0);
- case NM_VALUE_TYPE_INT32:
- return (nm_jansson_json_as_int32(vt, elem, out_val) > 0);
- case NM_VALUE_TYPE_INT:
- return (nm_jansson_json_as_int(vt, elem, out_val) > 0);
-
- /* warning: this overwrites/leaks the previous value. You better have *out_val
- * point to uninitialized memory or NULL. */
- case NM_VALUE_TYPE_STRING:
- return (nm_jansson_json_as_string(vt, elem, out_val) > 0);
-
- case NM_VALUE_TYPE_UNSPEC:
- break;
- }
- nm_assert_not_reached();
- return FALSE;
-}
-
-#endif /* NM_VALUE_TYPE_DEFINE_FUNCTIONS */
-
-#endif /* __NM_JSON_AUX_H__ */
diff --git a/shared/nm-glib-aux/nm-keyfile-aux.c b/shared/nm-glib-aux/nm-keyfile-aux.c
deleted file mode 100644
index b59627128f..0000000000
--- a/shared/nm-glib-aux/nm-keyfile-aux.c
+++ /dev/null
@@ -1,373 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2019 Red Hat, Inc.
- */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-keyfile-aux.h"
-
-#include <syslog.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-
-#include "nm-io-utils.h"
-
-/*****************************************************************************/
-
-struct _NMKeyFileDB {
- NMKeyFileDBLogFcn log_fcn;
- NMKeyFileDBGotDirtyFcn got_dirty_fcn;
- gpointer user_data;
- const char * group_name;
- GKeyFile * kf;
- guint ref_count;
-
- bool is_started : 1;
- bool dirty : 1;
- bool destroyed : 1;
-
- char filename[];
-};
-
-#define _NMLOG(self, syslog_level, fmt, ...) \
- G_STMT_START \
- { \
- NMKeyFileDB *_self = (self); \
- \
- nm_assert(_self); \
- nm_assert(!_self->destroyed); \
- \
- if (_self->log_fcn) { \
- _self->log_fcn(_self, (syslog_level), _self->user_data, "" fmt "", ##__VA_ARGS__); \
- }; \
- } \
- G_STMT_END
-
-#define _LOGD(...) _NMLOG(self, LOG_DEBUG, __VA_ARGS__)
-
-static gboolean
-_IS_KEY_FILE_DB(NMKeyFileDB *self, gboolean require_is_started, gboolean allow_destroyed)
-{
- if (self == NULL)
- return FALSE;
- if (self->ref_count <= 0) {
- nm_assert_not_reached();
- return FALSE;
- }
- if (require_is_started && !self->is_started)
- return FALSE;
- if (!allow_destroyed && self->destroyed)
- return FALSE;
- return TRUE;
-}
-
-/*****************************************************************************/
-
-NMKeyFileDB *
-nm_key_file_db_new(const char * filename,
- const char * group_name,
- NMKeyFileDBLogFcn log_fcn,
- NMKeyFileDBGotDirtyFcn got_dirty_fcn,
- gpointer user_data)
-{
- NMKeyFileDB *self;
- gsize l_filename;
- gsize l_group;
-
- g_return_val_if_fail(filename && filename[0], NULL);
- g_return_val_if_fail(group_name && group_name[0], NULL);
-
- l_filename = strlen(filename);
- l_group = strlen(group_name);
-
- self = g_malloc0(sizeof(NMKeyFileDB) + l_filename + 1 + l_group + 1);
- self->ref_count = 1;
- self->log_fcn = log_fcn;
- self->got_dirty_fcn = got_dirty_fcn;
- self->user_data = user_data;
- self->kf = g_key_file_new();
- g_key_file_set_list_separator(self->kf, ',');
- memcpy(self->filename, filename, l_filename + 1);
- self->group_name = &self->filename[l_filename + 1];
- memcpy((char *) self->group_name, group_name, l_group + 1);
-
- return self;
-}
-
-NMKeyFileDB *
-nm_key_file_db_ref(NMKeyFileDB *self)
-{
- if (!self)
- return NULL;
-
- g_return_val_if_fail(_IS_KEY_FILE_DB(self, FALSE, TRUE), NULL);
-
- nm_assert(self->ref_count < G_MAXUINT);
- self->ref_count++;
- return self;
-}
-
-void
-nm_key_file_db_unref(NMKeyFileDB *self)
-{
- if (!self)
- return;
-
- g_return_if_fail(_IS_KEY_FILE_DB(self, FALSE, TRUE));
-
- if (--self->ref_count > 0)
- return;
-
- g_key_file_unref(self->kf);
-
- g_free(self);
-}
-
-/* destroy() is like unref, but it also makes the instance unusable.
- * All changes afterwards fail with an assertion.
- *
- * The point is that NMKeyFileDB is ref-counted in principle. But there
- * is a primary owner who also provides the log_fcn().
- *
- * When the primary owner goes out of scope and gives up the reference, it does
- * not want to receive any log notifications anymore.
- *
- * The way NMKeyFileDB is intended to be used is in a very strict context:
- * NMSettings owns the NMKeyFileDB instance and receives logging notifications.
- * It's also the last one to persist the data to disk. Afterwards, no other user
- * is supposed to be around and do anything with NMKeyFileDB. But since NMKeyFileDB
- * is ref-counted it's hard to ensure that this is truly honored. So we start
- * asserting at that point.
- */
-void
-nm_key_file_db_destroy(NMKeyFileDB *self)
-{
- if (!self)
- return;
-
- g_return_if_fail(_IS_KEY_FILE_DB(self, FALSE, FALSE));
- g_return_if_fail(!self->destroyed);
-
- self->destroyed = TRUE;
- nm_key_file_db_unref(self);
-}
-
-/*****************************************************************************/
-
-/* nm_key_file_db_start() is supposed to be called right away, after creating the
- * instance.
- *
- * It's not done as separate step after nm_key_file_db_new(), because we want to log,
- * and the log_fcn returns the self pointer (which we should not expose before
- * nm_key_file_db_new() returns. */
-void
-nm_key_file_db_start(NMKeyFileDB *self)
-{
- gs_free char *contents = NULL;
- gsize contents_len;
- gs_free_error GError *error = NULL;
-
- g_return_if_fail(_IS_KEY_FILE_DB(self, FALSE, FALSE));
- g_return_if_fail(!self->is_started);
-
- self->is_started = TRUE;
-
- if (!nm_utils_file_get_contents(-1,
- self->filename,
- 20 * 1024 * 1024,
- NM_UTILS_FILE_GET_CONTENTS_FLAG_NONE,
- &contents,
- &contents_len,
- NULL,
- &error)) {
- _LOGD("failed to read \"%s\": %s", self->filename, error->message);
- return;
- }
-
- if (!g_key_file_load_from_data(self->kf,
- contents,
- contents_len,
- G_KEY_FILE_KEEP_COMMENTS,
- &error)) {
- _LOGD("failed to load keyfile \"%s\": %s", self->filename, error->message);
- return;
- }
-
- _LOGD("loaded keyfile-db for \"%s\"", self->filename);
-}
-
-/*****************************************************************************/
-
-const char *
-nm_key_file_db_get_filename(NMKeyFileDB *self)
-{
- g_return_val_if_fail(_IS_KEY_FILE_DB(self, FALSE, TRUE), NULL);
-
- return self->filename;
-}
-
-gboolean
-nm_key_file_db_is_dirty(NMKeyFileDB *self)
-{
- g_return_val_if_fail(_IS_KEY_FILE_DB(self, FALSE, TRUE), FALSE);
-
- return self->dirty;
-}
-
-/*****************************************************************************/
-
-char *
-nm_key_file_db_get_value(NMKeyFileDB *self, const char *key)
-{
- g_return_val_if_fail(_IS_KEY_FILE_DB(self, TRUE, TRUE), NULL);
-
- return g_key_file_get_value(self->kf, self->group_name, key, NULL);
-}
-
-char **
-nm_key_file_db_get_string_list(NMKeyFileDB *self, const char *key, gsize *out_len)
-{
- g_return_val_if_fail(_IS_KEY_FILE_DB(self, TRUE, TRUE), NULL);
-
- return g_key_file_get_string_list(self->kf, self->group_name, key, out_len, NULL);
-}
-
-/*****************************************************************************/
-
-static void
-_got_dirty(NMKeyFileDB *self, const char *key)
-{
- nm_assert(_IS_KEY_FILE_DB(self, TRUE, FALSE));
- nm_assert(!self->dirty);
-
- _LOGD("updated entry for %s.%s", self->group_name, key);
-
- self->dirty = TRUE;
- if (self->got_dirty_fcn)
- self->got_dirty_fcn(self, self->user_data);
-}
-
-/*****************************************************************************/
-
-void
-nm_key_file_db_remove_key(NMKeyFileDB *self, const char *key)
-{
- gboolean got_dirty = FALSE;
-
- g_return_if_fail(_IS_KEY_FILE_DB(self, TRUE, FALSE));
-
- if (!key)
- return;
-
- if (!self->dirty) {
- gs_free_error GError *error = NULL;
-
- g_key_file_has_key(self->kf, self->group_name, key, &error);
- got_dirty = (error != NULL);
- }
- g_key_file_remove_key(self->kf, self->group_name, key, NULL);
-
- if (got_dirty)
- _got_dirty(self, key);
-}
-
-void
-nm_key_file_db_set_value(NMKeyFileDB *self, const char *key, const char *value)
-{
- gs_free char *old_value = NULL;
- gboolean got_dirty = FALSE;
-
- g_return_if_fail(_IS_KEY_FILE_DB(self, TRUE, FALSE));
- g_return_if_fail(key);
-
- if (!value) {
- nm_key_file_db_remove_key(self, key);
- return;
- }
-
- if (!self->dirty) {
- gs_free_error GError *error = NULL;
-
- old_value = g_key_file_get_value(self->kf, self->group_name, key, &error);
- if (error)
- got_dirty = TRUE;
- }
-
- g_key_file_set_value(self->kf, self->group_name, key, value);
-
- if (!self->dirty && !got_dirty) {
- gs_free_error GError *error = NULL;
- gs_free char * new_value = NULL;
-
- new_value = g_key_file_get_value(self->kf, self->group_name, key, &error);
- if (error || !new_value || !nm_streq0(old_value, new_value))
- got_dirty = TRUE;
- }
-
- if (got_dirty)
- _got_dirty(self, key);
-}
-
-void
-nm_key_file_db_set_string_list(NMKeyFileDB * self,
- const char * key,
- const char *const *value,
- gssize len)
-{
- gs_free char *old_value = NULL;
- gboolean got_dirty = FALSE;
-
- g_return_if_fail(_IS_KEY_FILE_DB(self, TRUE, FALSE));
- g_return_if_fail(key);
-
- if (!value) {
- nm_key_file_db_remove_key(self, key);
- return;
- }
-
- if (!self->dirty) {
- gs_free_error GError *error = NULL;
-
- old_value = g_key_file_get_value(self->kf, self->group_name, key, &error);
- if (error)
- got_dirty = TRUE;
- }
-
- if (len < 0)
- len = NM_PTRARRAY_LEN(value);
-
- g_key_file_set_string_list(self->kf, self->group_name, key, value, len);
-
- if (!self->dirty && !got_dirty) {
- gs_free_error GError *error = NULL;
- gs_free char * new_value = NULL;
-
- new_value = g_key_file_get_value(self->kf, self->group_name, key, &error);
- if (error || !new_value || !nm_streq0(old_value, new_value))
- got_dirty = TRUE;
- }
-
- if (got_dirty)
- _got_dirty(self, key);
-}
-
-/*****************************************************************************/
-
-void
-nm_key_file_db_to_file(NMKeyFileDB *self, gboolean force)
-{
- gs_free_error GError *error = NULL;
-
- g_return_if_fail(_IS_KEY_FILE_DB(self, TRUE, FALSE));
-
- if (!force && !self->dirty)
- return;
-
- self->dirty = FALSE;
-
- if (!g_key_file_save_to_file(self->kf, self->filename, &error)) {
- _LOGD("failure to write keyfile \"%s\": %s", self->filename, error->message);
- } else
- _LOGD("write keyfile: \"%s\"", self->filename);
-}
diff --git a/shared/nm-glib-aux/nm-keyfile-aux.h b/shared/nm-glib-aux/nm-keyfile-aux.h
deleted file mode 100644
index 72d2f418f9..0000000000
--- a/shared/nm-glib-aux/nm-keyfile-aux.h
+++ /dev/null
@@ -1,55 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2019 Red Hat, Inc.
- */
-
-#ifndef __NM_KEYFILE_AUX_H__
-#define __NM_KEYFILE_AUX_H__
-
-/*****************************************************************************/
-
-typedef struct _NMKeyFileDB NMKeyFileDB;
-
-typedef void (*NMKeyFileDBLogFcn)(NMKeyFileDB *self,
- int syslog_level,
- gpointer user_data,
- const char * fmt,
- ...) G_GNUC_PRINTF(4, 5);
-
-typedef void (*NMKeyFileDBGotDirtyFcn)(NMKeyFileDB *self, gpointer user_data);
-
-NMKeyFileDB *nm_key_file_db_new(const char * filename,
- const char * group,
- NMKeyFileDBLogFcn log_fcn,
- NMKeyFileDBGotDirtyFcn got_dirty_fcn,
- gpointer user_data);
-
-void nm_key_file_db_start(NMKeyFileDB *self);
-
-NMKeyFileDB *nm_key_file_db_ref(NMKeyFileDB *self);
-void nm_key_file_db_unref(NMKeyFileDB *self);
-
-void nm_key_file_db_destroy(NMKeyFileDB *self);
-
-const char *nm_key_file_db_get_filename(NMKeyFileDB *self);
-
-gboolean nm_key_file_db_is_dirty(NMKeyFileDB *self);
-
-char *nm_key_file_db_get_value(NMKeyFileDB *self, const char *key);
-
-char **nm_key_file_db_get_string_list(NMKeyFileDB *self, const char *key, gsize *out_len);
-
-void nm_key_file_db_remove_key(NMKeyFileDB *self, const char *key);
-
-void nm_key_file_db_set_value(NMKeyFileDB *self, const char *key, const char *value);
-
-void nm_key_file_db_set_string_list(NMKeyFileDB * self,
- const char * key,
- const char *const *value,
- gssize len);
-
-void nm_key_file_db_to_file(NMKeyFileDB *self, gboolean force);
-
-/*****************************************************************************/
-
-#endif /* __NM_KEYFILE_AUX_H__ */
diff --git a/shared/nm-glib-aux/nm-logging-base.c b/shared/nm-glib-aux/nm-logging-base.c
deleted file mode 100644
index 66b591b21e..0000000000
--- a/shared/nm-glib-aux/nm-logging-base.c
+++ /dev/null
@@ -1,79 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-logging-base.h"
-
-#include <syslog.h>
-
-/*****************************************************************************/
-
-const LogLevelDesc level_desc[_LOGL_N] = {
- [LOGL_TRACE] =
- {
- "TRACE",
- "<trace>",
- LOG_DEBUG,
- G_LOG_LEVEL_DEBUG,
- },
- [LOGL_DEBUG] =
- {
- "DEBUG",
- "<debug>",
- LOG_DEBUG,
- G_LOG_LEVEL_DEBUG,
- },
- [LOGL_INFO] =
- {
- "INFO",
- "<info>",
- LOG_INFO,
- G_LOG_LEVEL_INFO,
- },
- [LOGL_WARN] =
- {
- "WARN",
- "<warn>",
- LOG_WARNING,
- G_LOG_LEVEL_MESSAGE,
- },
- [LOGL_ERR] =
- {
- "ERR",
- "<error>",
- LOG_ERR,
- G_LOG_LEVEL_MESSAGE,
- },
- [_LOGL_OFF] =
- {
- "OFF",
- NULL,
- 0,
- 0,
- },
- [_LOGL_KEEP] =
- {
- "KEEP",
- NULL,
- 0,
- 0,
- },
-};
-
-gboolean
-_nm_log_parse_level(const char *level, NMLogLevel *out_level)
-{
- int i;
-
- if (!level)
- return FALSE;
-
- for (i = 0; i < (int) G_N_ELEMENTS(level_desc); i++) {
- if (!g_ascii_strcasecmp(level_desc[i].name, level)) {
- NM_SET_OUT(out_level, i);
- return TRUE;
- }
- }
-
- return FALSE;
-}
diff --git a/shared/nm-glib-aux/nm-logging-base.h b/shared/nm-glib-aux/nm-logging-base.h
deleted file mode 100644
index d9ac03c796..0000000000
--- a/shared/nm-glib-aux/nm-logging-base.h
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#ifndef __NM_LOGGING_BASE_H__
-#define __NM_LOGGING_BASE_H__
-
-#include "nm-logging-fwd.h"
-
-typedef struct {
- const char *name;
- const char *level_str;
-
- /* nm-logging uses syslog internally. Note that the three most-verbose syslog levels
- * are LOG_DEBUG, LOG_INFO and LOG_NOTICE. Journal already highlights LOG_NOTICE
- * as special.
- *
- * On the other hand, we have three levels LOGL_TRACE, LOGL_DEBUG and LOGL_INFO,
- * which are regular messages not to be highlighted. For that reason, we must map
- * LOGL_TRACE and LOGL_DEBUG both to syslog level LOG_DEBUG. */
- int syslog_level;
-
- GLogLevelFlags g_log_level;
-} LogLevelDesc;
-
-extern const LogLevelDesc level_desc[_LOGL_N];
-
-gboolean _nm_log_parse_level(const char *level, NMLogLevel *out_level);
-
-#endif /* __NM_LOGGING_BASE_H__ */
diff --git a/shared/nm-glib-aux/nm-logging-fwd.h b/shared/nm-glib-aux/nm-logging-fwd.h
deleted file mode 100644
index df0bb161e1..0000000000
--- a/shared/nm-glib-aux/nm-logging-fwd.h
+++ /dev/null
@@ -1,308 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2006 - 2018 Red Hat, Inc.
- * Copyright (C) 2006 - 2008 Novell, Inc.
- */
-
-#ifndef __NM_LOGGING_FWD_H__
-#define __NM_LOGGING_FWD_H__
-
-/* Log domains */
-
-typedef enum { /*< skip >*/
- LOGD_NONE = 0LL,
- LOGD_PLATFORM = (1LL << 0), /* Platform services */
- LOGD_RFKILL = (1LL << 1),
- LOGD_ETHER = (1LL << 2),
- LOGD_WIFI = (1LL << 3),
- LOGD_BT = (1LL << 4),
- LOGD_MB = (1LL << 5), /* mobile broadband */
- LOGD_DHCP4 = (1LL << 6),
- LOGD_DHCP6 = (1LL << 7),
- LOGD_PPP = (1LL << 8),
- LOGD_WIFI_SCAN = (1LL << 9),
- LOGD_IP4 = (1LL << 10),
- LOGD_IP6 = (1LL << 11),
- LOGD_AUTOIP4 = (1LL << 12),
- LOGD_DNS = (1LL << 13),
- LOGD_VPN = (1LL << 14),
- LOGD_SHARING = (1LL << 15), /* Connection sharing/dnsmasq */
- LOGD_SUPPLICANT = (1LL << 16), /* Wi-Fi and 802.1x */
- LOGD_AGENTS = (1LL << 17), /* Secret agents */
- LOGD_SETTINGS = (1LL << 18), /* Settings */
- LOGD_SUSPEND = (1LL << 19), /* Suspend/Resume */
- LOGD_CORE = (1LL << 20), /* Core daemon and policy stuff */
- LOGD_DEVICE = (1LL << 21), /* Device state and activation */
- LOGD_OLPC = (1LL << 22),
- LOGD_INFINIBAND = (1LL << 23),
- LOGD_FIREWALL = (1LL << 24),
- LOGD_ADSL = (1LL << 25),
- LOGD_BOND = (1LL << 26),
- LOGD_VLAN = (1LL << 27),
- LOGD_BRIDGE = (1LL << 28),
- LOGD_DBUS_PROPS = (1LL << 29),
- LOGD_TEAM = (1LL << 30),
- LOGD_CONCHECK = (1LL << 31),
- LOGD_DCB = (1LL << 32), /* Data Center Bridging */
- LOGD_DISPATCH = (1LL << 33),
- LOGD_AUDIT = (1LL << 34),
- LOGD_SYSTEMD = (1LL << 35),
- LOGD_VPN_PLUGIN = (1LL << 36),
- LOGD_PROXY = (1LL << 37),
-
- __LOGD_MAX,
- LOGD_ALL = (((__LOGD_MAX - 1LL) << 1) - 1LL),
- LOGD_DEFAULT = LOGD_ALL & ~(LOGD_DBUS_PROPS | LOGD_WIFI_SCAN | LOGD_VPN_PLUGIN | 0),
-
- /* aliases: */
- LOGD_DHCP = LOGD_DHCP4 | LOGD_DHCP6,
- LOGD_IP = LOGD_IP4 | LOGD_IP6,
-
-#define LOGD_DHCPX(is_ipv4) ((is_ipv4) ? LOGD_DHCP4 : LOGD_DHCP6)
-#define LOGD_IPX(is_ipv4) ((is_ipv4) ? LOGD_IP4 : LOGD_IP6)
-
-} NMLogDomain;
-
-/* Log levels */
-typedef enum { /*< skip >*/
- LOGL_TRACE,
- LOGL_DEBUG,
- LOGL_INFO,
- LOGL_WARN,
- LOGL_ERR,
-
- _LOGL_N_REAL, /* the number of actual logging levels */
-
- _LOGL_OFF = _LOGL_N_REAL, /* special logging level that is always disabled. */
- _LOGL_KEEP, /* special logging level to indicate that the logging level should not be changed. */
-
- _LOGL_N, /* the number of logging levels including "OFF" */
-} NMLogLevel;
-
-gboolean _nm_log_enabled_impl(gboolean mt_require_locking, NMLogLevel level, NMLogDomain domain);
-
-void _nm_log_impl(const char *file,
- guint line,
- const char *func,
- gboolean mt_require_locking,
- NMLogLevel level,
- NMLogDomain domain,
- int error,
- const char *ifname,
- const char *con_uuid,
- const char *fmt,
- ...) _nm_printf(10, 11);
-
-static inline NMLogLevel
-nm_log_level_from_syslog(int syslog_level)
-{
- switch (syslog_level) {
- case 0 /* LOG_EMERG */:
- return LOGL_ERR;
- case 1 /* LOG_ALERT */:
- return LOGL_ERR;
- case 2 /* LOG_CRIT */:
- return LOGL_ERR;
- case 3 /* LOG_ERR */:
- return LOGL_ERR;
- case 4 /* LOG_WARNING */:
- return LOGL_WARN;
- case 5 /* LOG_NOTICE */:
- return LOGL_INFO;
- case 6 /* LOG_INFO */:
- return LOGL_DEBUG;
- case 7 /* LOG_DEBUG */:
- return LOGL_TRACE;
- default:
- return syslog_level >= 0 ? LOGL_TRACE : LOGL_ERR;
- }
-}
-
-static inline int
-nm_log_level_to_syslog(NMLogLevel nm_level)
-{
- switch (nm_level) {
- case LOGL_ERR:
- return 3; /* LOG_ERR */
- case LOGL_WARN:
- return 4; /* LOG_WARN */
- case LOGL_INFO:
- return 5; /* LOG_NOTICE */
- case LOGL_DEBUG:
- return 6; /* LOG_INFO */
- case LOGL_TRACE:
- return 7; /* LOG_DEBUG */
- default:
- return 0; /* LOG_EMERG */
- }
-}
-
-/*****************************************************************************/
-
-struct timespec;
-
-/* this function must be implemented to handle the notification when
- * the first monotonic-timestamp is fetched. */
-extern void _nm_utils_monotonic_timestamp_initialized(const struct timespec *tp,
- gint64 offset_sec,
- gboolean is_boottime);
-
-/*****************************************************************************/
-
-#define _LOGL_TRACE LOGL_TRACE
-#define _LOGL_DEBUG LOGL_DEBUG
-#define _LOGL_INFO LOGL_INFO
-#define _LOGL_WARN LOGL_WARN
-#define _LOGL_ERR LOGL_ERR
-
-/* This is the default definition of _NMLOG_ENABLED(). Special implementations
- * might want to undef this and redefine it. */
-#define _NMLOG_ENABLED(level) (nm_logging_enabled((level), (_NMLOG_DOMAIN)))
-
-#define _LOGT(...) _NMLOG(_LOGL_TRACE, __VA_ARGS__)
-#define _LOGD(...) _NMLOG(_LOGL_DEBUG, __VA_ARGS__)
-#define _LOGI(...) _NMLOG(_LOGL_INFO, __VA_ARGS__)
-#define _LOGW(...) _NMLOG(_LOGL_WARN, __VA_ARGS__)
-#define _LOGE(...) _NMLOG(_LOGL_ERR, __VA_ARGS__)
-
-#define _LOGT_ENABLED(...) _NMLOG_ENABLED(_LOGL_TRACE, ##__VA_ARGS__)
-#define _LOGD_ENABLED(...) _NMLOG_ENABLED(_LOGL_DEBUG, ##__VA_ARGS__)
-#define _LOGI_ENABLED(...) _NMLOG_ENABLED(_LOGL_INFO, ##__VA_ARGS__)
-#define _LOGW_ENABLED(...) _NMLOG_ENABLED(_LOGL_WARN, ##__VA_ARGS__)
-#define _LOGE_ENABLED(...) _NMLOG_ENABLED(_LOGL_ERR, ##__VA_ARGS__)
-
-#define _LOGT_err(errsv, ...) _NMLOG_err(errsv, _LOGL_TRACE, __VA_ARGS__)
-#define _LOGD_err(errsv, ...) _NMLOG_err(errsv, _LOGL_DEBUG, __VA_ARGS__)
-#define _LOGI_err(errsv, ...) _NMLOG_err(errsv, _LOGL_INFO, __VA_ARGS__)
-#define _LOGW_err(errsv, ...) _NMLOG_err(errsv, _LOGL_WARN, __VA_ARGS__)
-#define _LOGE_err(errsv, ...) _NMLOG_err(errsv, _LOGL_ERR, __VA_ARGS__)
-
-/* _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__)
-#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
-#endif
-
-/*****************************************************************************/
-
-/* Some implementation define a second set of logging macros, for a separate
- * use. As with the _LOGD() macro family above, the exact implementation
- * depends on the file that uses them.
- * Still, it encourages a common pattern to have the common set of macros
- * like _LOG2D(), _LOG2I(), etc. and have _LOG2t() which by default
- * is disabled at compile time. */
-
-#define _NMLOG2_ENABLED(level) (nm_logging_enabled((level), (_NMLOG2_DOMAIN)))
-
-#define _LOG2T(...) _NMLOG2(_LOGL_TRACE, __VA_ARGS__)
-#define _LOG2D(...) _NMLOG2(_LOGL_DEBUG, __VA_ARGS__)
-#define _LOG2I(...) _NMLOG2(_LOGL_INFO, __VA_ARGS__)
-#define _LOG2W(...) _NMLOG2(_LOGL_WARN, __VA_ARGS__)
-#define _LOG2E(...) _NMLOG2(_LOGL_ERR, __VA_ARGS__)
-
-#define _LOG2T_ENABLED(...) _NMLOG2_ENABLED(_LOGL_TRACE, ##__VA_ARGS__)
-#define _LOG2D_ENABLED(...) _NMLOG2_ENABLED(_LOGL_DEBUG, ##__VA_ARGS__)
-#define _LOG2I_ENABLED(...) _NMLOG2_ENABLED(_LOGL_INFO, ##__VA_ARGS__)
-#define _LOG2W_ENABLED(...) _NMLOG2_ENABLED(_LOGL_WARN, ##__VA_ARGS__)
-#define _LOG2E_ENABLED(...) _NMLOG2_ENABLED(_LOGL_ERR, ##__VA_ARGS__)
-
-#define _LOG2T_err(errsv, ...) _NMLOG2_err(errsv, _LOGL_TRACE, __VA_ARGS__)
-#define _LOG2D_err(errsv, ...) _NMLOG2_err(errsv, _LOGL_DEBUG, __VA_ARGS__)
-#define _LOG2I_err(errsv, ...) _NMLOG2_err(errsv, _LOGL_INFO, __VA_ARGS__)
-#define _LOG2W_err(errsv, ...) _NMLOG2_err(errsv, _LOGL_WARN, __VA_ARGS__)
-#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__)
-#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
-#endif
-
-#define _NMLOG3_ENABLED(level) (nm_logging_enabled((level), (_NMLOG3_DOMAIN)))
-
-#define _LOG3T(...) _NMLOG3(_LOGL_TRACE, __VA_ARGS__)
-#define _LOG3D(...) _NMLOG3(_LOGL_DEBUG, __VA_ARGS__)
-#define _LOG3I(...) _NMLOG3(_LOGL_INFO, __VA_ARGS__)
-#define _LOG3W(...) _NMLOG3(_LOGL_WARN, __VA_ARGS__)
-#define _LOG3E(...) _NMLOG3(_LOGL_ERR, __VA_ARGS__)
-
-#define _LOG3T_ENABLED(...) _NMLOG3_ENABLED(_LOGL_TRACE, ##__VA_ARGS__)
-#define _LOG3D_ENABLED(...) _NMLOG3_ENABLED(_LOGL_DEBUG, ##__VA_ARGS__)
-#define _LOG3I_ENABLED(...) _NMLOG3_ENABLED(_LOGL_INFO, ##__VA_ARGS__)
-#define _LOG3W_ENABLED(...) _NMLOG3_ENABLED(_LOGL_WARN, ##__VA_ARGS__)
-#define _LOG3E_ENABLED(...) _NMLOG3_ENABLED(_LOGL_ERR, ##__VA_ARGS__)
-
-#define _LOG3T_err(errsv, ...) _NMLOG3_err(errsv, _LOGL_TRACE, __VA_ARGS__)
-#define _LOG3D_err(errsv, ...) _NMLOG3_err(errsv, _LOGL_DEBUG, __VA_ARGS__)
-#define _LOG3I_err(errsv, ...) _NMLOG3_err(errsv, _LOGL_INFO, __VA_ARGS__)
-#define _LOG3W_err(errsv, ...) _NMLOG3_err(errsv, _LOGL_WARN, __VA_ARGS__)
-#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__)
-#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
-#endif
-
-/*****************************************************************************/
-
-#endif /* __NM_LOGGING_FWD_H__ */
diff --git a/shared/nm-glib-aux/nm-macros-internal.h b/shared/nm-glib-aux/nm-macros-internal.h
deleted file mode 100644
index 113a67a0d2..0000000000
--- a/shared/nm-glib-aux/nm-macros-internal.h
+++ /dev/null
@@ -1,1815 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2012 Colin Walters <walters@verbum.org>.
- * Copyright (C) 2014 Red Hat, Inc.
- */
-
-#ifndef __NM_MACROS_INTERNAL_H__
-#define __NM_MACROS_INTERNAL_H__
-
-#include <stdio.h>
-#include <stdlib.h>
-#include <errno.h>
-#include <string.h>
-
-#include <gio/gio.h>
-
-/*****************************************************************************/
-
-/* most of our code is single-threaded with a mainloop. Hence, we usually don't need
- * any thread-safety. Sometimes, we do need thread-safety (nm-logging), but we can
- * avoid locking if we are on the main-thread by:
- *
- * - modifications of shared data is done infrequently and only from the
- * main-thread (nm_logging_setup())
- * - read-only access is done frequently (nm_logging_enabled())
- * - from the main-thread, we can do that without locking (because
- * all modifications are also done on the main thread.
- * - from other threads, we need locking. But this is expected to be
- * done infrequently too. Important is the lock-free fast-path on the
- * main-thread.
- *
- * By defining NM_THREAD_SAFE_ON_MAIN_THREAD you indicate that this code runs
- * on the main-thread. It is by default defined to "1". If you have code that
- * is also used on another thread, redefine the define to 0 (to opt in into
- * the slow-path).
- */
-#define NM_THREAD_SAFE_ON_MAIN_THREAD 1
-
-/*****************************************************************************/
-
-#include "nm-glib.h"
-
-/*****************************************************************************/
-
-#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
-#define gs_unref_array nm_auto_unref_array
-#define gs_unref_ptrarray nm_auto_unref_ptrarray
-#define gs_unref_hashtable nm_auto_unref_hashtable
-#define gs_unref_bytes nm_auto_unref_bytes
-#define gs_strfreev nm_auto_strfreev
-#define gs_free_error nm_auto_free_error
-
-/*****************************************************************************/
-
-NM_AUTO_DEFINE_FCN_VOID0(void *, _nm_auto_g_free, g_free);
-#define nm_auto_g_free nm_auto(_nm_auto_g_free)
-
-NM_AUTO_DEFINE_FCN_VOID0(GObject *, _nm_auto_unref_object, g_object_unref);
-#define nm_auto_unref_object nm_auto(_nm_auto_unref_object)
-
-NM_AUTO_DEFINE_FCN0(GVariant *, _nm_auto_unref_variant, g_variant_unref);
-#define nm_auto_unref_variant nm_auto(_nm_auto_unref_variant)
-
-NM_AUTO_DEFINE_FCN0(GArray *, _nm_auto_unref_array, g_array_unref);
-#define nm_auto_unref_array nm_auto(_nm_auto_unref_array)
-
-NM_AUTO_DEFINE_FCN0(GPtrArray *, _nm_auto_unref_ptrarray, g_ptr_array_unref);
-#define nm_auto_unref_ptrarray nm_auto(_nm_auto_unref_ptrarray)
-
-NM_AUTO_DEFINE_FCN0(GHashTable *, _nm_auto_unref_hashtable, g_hash_table_unref);
-#define nm_auto_unref_hashtable nm_auto(_nm_auto_unref_hashtable)
-
-NM_AUTO_DEFINE_FCN0(GSList *, _nm_auto_free_slist, g_slist_free);
-#define nm_auto_free_slist nm_auto(_nm_auto_free_slist)
-
-NM_AUTO_DEFINE_FCN0(GBytes *, _nm_auto_unref_bytes, g_bytes_unref);
-#define nm_auto_unref_bytes nm_auto(_nm_auto_unref_bytes)
-
-NM_AUTO_DEFINE_FCN0(char **, _nm_auto_strfreev, g_strfreev);
-#define nm_auto_strfreev nm_auto(_nm_auto_strfreev)
-
-NM_AUTO_DEFINE_FCN0(GError *, _nm_auto_free_error, g_error_free);
-#define nm_auto_free_error nm_auto(_nm_auto_free_error)
-
-NM_AUTO_DEFINE_FCN0(GKeyFile *, _nm_auto_unref_keyfile, g_key_file_unref);
-#define nm_auto_unref_keyfile nm_auto(_nm_auto_unref_keyfile)
-
-NM_AUTO_DEFINE_FCN0(GVariantIter *, _nm_auto_free_variant_iter, g_variant_iter_free);
-#define nm_auto_free_variant_iter nm_auto(_nm_auto_free_variant_iter)
-
-NM_AUTO_DEFINE_FCN0(GVariantBuilder *, _nm_auto_unref_variant_builder, g_variant_builder_unref);
-#define nm_auto_unref_variant_builder nm_auto(_nm_auto_unref_variant_builder)
-
-#define nm_auto_clear_variant_builder nm_auto(g_variant_builder_clear)
-
-NM_AUTO_DEFINE_FCN0(GList *, _nm_auto_free_list, g_list_free);
-#define nm_auto_free_list nm_auto(_nm_auto_free_list)
-
-NM_AUTO_DEFINE_FCN0(GChecksum *, _nm_auto_checksum_free, g_checksum_free);
-#define nm_auto_free_checksum nm_auto(_nm_auto_checksum_free)
-
-#define nm_auto_unset_gvalue nm_auto(g_value_unset)
-
-NM_AUTO_DEFINE_FCN_VOID0(void *, _nm_auto_unref_gtypeclass, g_type_class_unref);
-#define nm_auto_unref_gtypeclass nm_auto(_nm_auto_unref_gtypeclass)
-
-NM_AUTO_DEFINE_FCN0(GByteArray *, _nm_auto_unref_bytearray, g_byte_array_unref);
-#define nm_auto_unref_bytearray nm_auto(_nm_auto_unref_bytearray)
-
-static inline void
-_nm_auto_free_gstring(GString **str)
-{
- if (*str)
- g_string_free(*str, TRUE);
-}
-#define nm_auto_free_gstring nm_auto(_nm_auto_free_gstring)
-
-static inline void
-_nm_auto_protect_errno(int *p_saved_errno)
-{
- errno = *p_saved_errno;
-}
-#define NM_AUTO_PROTECT_ERRNO(errsv_saved) \
- nm_auto(_nm_auto_protect_errno) _nm_unused const int errsv_saved = (errno)
-
-NM_AUTO_DEFINE_FCN0(GSource *, _nm_auto_unref_gsource, g_source_unref);
-#define nm_auto_unref_gsource nm_auto(_nm_auto_unref_gsource)
-
-NM_AUTO_DEFINE_FCN0(guint, _nm_auto_remove_source, g_source_remove);
-#define nm_auto_remove_source nm_auto(_nm_auto_remove_source)
-
-NM_AUTO_DEFINE_FCN0(GIOChannel *, _nm_auto_unref_io_channel, g_io_channel_unref);
-#define nm_auto_unref_io_channel nm_auto(_nm_auto_unref_io_channel)
-
-NM_AUTO_DEFINE_FCN0(GMainLoop *, _nm_auto_unref_gmainloop, g_main_loop_unref);
-#define nm_auto_unref_gmainloop nm_auto(_nm_auto_unref_gmainloop)
-
-NM_AUTO_DEFINE_FCN0(GOptionContext *, _nm_auto_free_option_context, g_option_context_free);
-#define nm_auto_free_option_context nm_auto(_nm_auto_free_option_context)
-
-static inline void
-_nm_auto_freev(gpointer ptr)
-{
- gpointer **p = ptr;
- gpointer * _ptr;
-
- if (*p) {
- for (_ptr = *p; *_ptr; _ptr++)
- g_free(*_ptr);
- g_free(*p);
- }
-}
-/* g_free a NULL terminated array of pointers, with also freeing each
- * pointer with g_free(). It essentially does the same as
- * gs_strfreev / g_strfreev(), but not restricted to strv arrays. */
-#define nm_auto_freev nm_auto(_nm_auto_freev)
-
-/*****************************************************************************/
-
-#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()
-#define __NM_MACRO_COMMA_IF_ARGS_1(...) ,
-
-/*****************************************************************************/
-
-/* http://stackoverflow.com/a/11172679 */
-#define _NM_UTILS_MACRO_FIRST(...) __NM_UTILS_MACRO_FIRST_HELPER(__VA_ARGS__, throwaway)
-#define __NM_UTILS_MACRO_FIRST_HELPER(first, ...) first
-
-#define _NM_UTILS_MACRO_REST(...) \
- _NM_MACRO_CALL(G_PASTE(__NM_UTILS_MACRO_REST_, NM_NARG_MAX2(__VA_ARGS__)), __VA_ARGS__)
-#define __NM_UTILS_MACRO_REST_0()
-#define __NM_UTILS_MACRO_REST_1(first)
-#define __NM_UTILS_MACRO_REST_2(first, ...) , __VA_ARGS__
-
-/*****************************************************************************/
-
-#if defined(__GNUC__)
- #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)
-#endif
-
-/* you can only suppress a specific warning that the compiler
- * understands. Otherwise you will get another compiler warning
- * about invalid pragma option.
- * It's not that bad however, because gcc and clang often have the
- * 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))
-#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))
-#else
- #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")
-#elif defined(__clang__)
- #define NM_PRAGMA_WARNING_REENABLE _Pragma("clang diagnostic pop")
-#else
- #define NM_PRAGMA_WARNING_REENABLE
-#endif
-
-/*****************************************************************************/
-
-/**
- * NM_G_ERROR_MSG:
- * @error: (allow-none): the #GError instance
- *
- * All functions must follow the convention that when they
- * return a failure, they must also set the GError to a valid
- * message. For external API however, we want to be extra
- * careful before accessing the error instance. Use NM_G_ERROR_MSG()
- * which is safe to use on NULL.
- *
- * Returns: the error message.
- **/
-static inline const char *
-NM_G_ERROR_MSG(GError *error)
-{
- return error ? (error->message ?: "(null)") : "(no-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. */
- #if (defined(__GNUC__) && (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 9))) \
- || (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), \
- const void *const: ((const type *) (obj)), \
- const void * : ((const type *) (obj)), \
- void *const: (( type *) (obj)), \
- void * : (( type *) (obj)), \
- const type *const: ((const type *) (obj)), \
- 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), \
- const void *const: ((const type *) (obj)), \
- const void * : ((const type *) (obj)), \
- void *const: (( type *) (obj)), \
- void * : (( type *) (obj)), \
- const alias_type2 *const: ((const type *) (obj)), \
- const alias_type2 * : ((const type *) (obj)), \
- alias_type2 *const: (( type *) (obj)), \
- alias_type2 * : (( type *) (obj)), \
- const type *const: ((const type *) (obj)), \
- 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), \
- const void *const: ((const type *) (obj)), \
- const void * : ((const type *) (obj)), \
- void *const: (( type *) (obj)), \
- void * : (( type *) (obj)), \
- const alias_type2 *const: ((const type *) (obj)), \
- const alias_type2 * : ((const type *) (obj)), \
- alias_type2 *const: (( type *) (obj)), \
- alias_type2 * : (( type *) (obj)), \
- const alias_type3 *const: ((const type *) (obj)), \
- const alias_type3 * : ((const type *) (obj)), \
- alias_type3 *const: (( type *) (obj)), \
- alias_type3 * : (( type *) (obj)), \
- const type *const: ((const type *) (obj)), \
- 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), \
- const void *const: ((const type *) (obj)), \
- const void * : ((const type *) (obj)), \
- void *const: (( type *) (obj)), \
- void * : (( type *) (obj)), \
- const alias_type2 *const: ((const type *) (obj)), \
- const alias_type2 * : ((const type *) (obj)), \
- alias_type2 *const: (( type *) (obj)), \
- alias_type2 * : (( type *) (obj)), \
- const alias_type3 *const: ((const type *) (obj)), \
- const alias_type3 * : ((const type *) (obj)), \
- alias_type3 *const: (( type *) (obj)), \
- alias_type3 * : (( type *) (obj)), \
- const alias_type4 *const: ((const type *) (obj)), \
- const alias_type4 * : ((const type *) (obj)), \
- alias_type4 *const: (( type *) (obj)), \
- alias_type4 * : (( type *) (obj)), \
- const type *const: ((const type *) (obj)), \
- 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__))
-#else
- #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)))
-#else
- #define NM_UNCONST_PTR(type, arg) ((type *) (arg))
-#endif
-
-#if _NM_CC_SUPPORT_GENERIC
- #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))
-#endif
-
-#define NM_GOBJECT_CAST(type, obj, is_check, ...) \
- ({ \
- const void *_obj = (obj); \
- \
- nm_assert(_obj || (is_check(_obj))); \
- NM_CONSTCAST_FULL(type, (obj), _obj, GObject, ##__VA_ARGS__); \
- })
-
-#define NM_GOBJECT_CAST_NON_NULL(type, obj, is_check, ...) \
- ({ \
- const void *_obj = (obj); \
- \
- nm_assert(is_check(_obj)); \
- NM_CONSTCAST_FULL(type, (obj), _obj, GObject, ##__VA_ARGS__); \
- })
-
-#define NM_ENSURE_NOT_NULL(ptr) \
- ({ \
- typeof(ptr) _ptr = (ptr); \
- \
- nm_assert(_ptr != NULL); \
- _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
-
-#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), \
- const char * *: (const char * *) (value), \
- char * *: (const char * *) (value), \
- void *: (const char * *) (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), \
- char * *: (const char *const*) (value), \
- const void *: (const char *const*) (value), \
- void *: (const char *const*) (value), \
- const char *const*const: (const char *const*) (value), \
- const char * *const: (const char *const*) (value), \
- char *const*const: (const char *const*) (value), \
- char * *const: (const char *const*) (value), \
- 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))
-#endif
-
-#if _NM_CC_SUPPORT_GENERIC
- #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)
-#endif
-
-/* with the way it is implemented, the caller may or may not pass a trailing
- * ',' and it will work. However, this makes the macro unsuitable for initializing
- * an array. */
-#define NM_MAKE_STRV(...) \
- ((const char *const[(sizeof(((const char *const[]){__VA_ARGS__})) / sizeof(const char *)) \
- + 1]){__VA_ARGS__})
-
-/*****************************************************************************/
-
-/* NM_CACHED_QUARK() returns the GQuark for @string, but caches
- * it in a static variable to speed up future lookups.
- *
- * @string must be a string literal.
- */
-#define NM_CACHED_QUARK(string) \
- ({ \
- static GQuark _nm_cached_quark = 0; \
- \
- (G_LIKELY(_nm_cached_quark != 0) \
- ? _nm_cached_quark \
- : (_nm_cached_quark = g_quark_from_static_string("" string ""))); \
- })
-
-/* NM_CACHED_QUARK_FCN() is essentially the same as G_DEFINE_QUARK
- * with two differences:
- * - @string must be a quoted string-literal
- * - @fcn must be the full function name, while G_DEFINE_QUARK() appends
- * "_quark" to the function name.
- * Both properties of G_DEFINE_QUARK() are non favorable, because you can no
- * longer grep for string/fcn -- unless you are aware that you are searching
- * for G_DEFINE_QUARK() and omit quotes / append _quark(). With NM_CACHED_QUARK_FCN(),
- * ctags/cscope can locate the use of @fcn (though it doesn't recognize that
- * NM_CACHED_QUARK_FCN() defines it).
- */
-#define NM_CACHED_QUARK_FCN(string, fcn) \
- GQuark fcn(void) \
- { \
- return NM_CACHED_QUARK(string); \
- } \
- _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON
-
-/*****************************************************************************/
-
-static inline GString *
-nm_gstring_prepare(GString **l)
-{
- if (*l)
- g_string_set_size(*l, 0);
- else
- *l = g_string_sized_new(30);
- return *l;
-}
-
-static inline GString *
-nm_gstring_add_space_delimiter(GString *str)
-{
- if (str->len > 0)
- g_string_append_c(str, ' ');
- return str;
-}
-
-static inline gboolean
-nm_str_is_empty(const char *str)
-{
- /* %NULL is also accepted, and also "empty". */
- return !str || !str[0];
-}
-
-static inline const char *
-nm_str_not_empty(const char *str)
-{
- return !nm_str_is_empty(str) ? str : NULL;
-}
-
-static inline char *
-nm_strdup_not_empty(const char *str)
-{
- return !nm_str_is_empty(str) ? g_strdup(str) : NULL;
-}
-
-static inline char *
-nm_str_realloc(char *str)
-{
- gs_free char *s = str;
-
- /* Returns a new clone of @str and frees @str. The point is that @str
- * possibly points to a larger chunck of memory. We want to freshly allocate
- * a buffer.
- *
- * We could use realloc(), but that might not do anything or leave
- * @str in its memory pool for chunks of a different size (bad for
- * fragmentation).
- *
- * This is only useful when we want to keep the buffer around for a long
- * time and want to re-allocate a more optimal buffer. */
-
- return g_strdup(s);
-}
-
-/*****************************************************************************/
-
-#define NM_PRINT_FMT_QUOTED2(cond, prefix, str, str_else) \
- (cond) ? (prefix) : "", (cond) ? (str) : (str_else)
-#define NM_PRINT_FMT_QUOTED(cond, prefix, str, suffix, str_else) \
- (cond) ? (prefix) : "", (cond) ? (str) : (str_else), (cond) ? (suffix) : ""
-#define NM_PRINT_FMT_QUOTE_STRING(arg) NM_PRINT_FMT_QUOTED((arg), "\"", (arg), "\"", "(null)")
-#define NM_PRINT_FMT_QUOTE_REF_STRING(arg) \
- NM_PRINT_FMT_QUOTED((arg), "\"", (arg)->str, "\"", "(null)")
-
-/*****************************************************************************/
-
-/* redefine assertions to use g_assert*() */
-#undef _nm_assert_call
-#undef _nm_assert_call_not_reached
-#define _nm_assert_call(cond) g_assert(cond)
-#define _nm_assert_call_not_reached() g_assert_not_reached()
-
-/* Usage:
- *
- * if (NM_MORE_ASSERT_ONCE (5)) { extra_check (); }
- *
- * This will only run the check once, and only if NM_MORE_ASSERT is >= than
- * more_assert_level.
- */
-#define NM_MORE_ASSERT_ONCE(more_assert_level) \
- ((NM_MORE_ASSERTS >= (more_assert_level)) && ({ \
- static volatile int _assert_once = 0; \
- \
- G_STATIC_ASSERT_EXPR((more_assert_level) > 0); \
- \
- G_UNLIKELY(_assert_once == 0 && g_atomic_int_compare_and_exchange(&_assert_once, 0, 1)); \
- }))
-
-/*****************************************************************************/
-
-#define NM_GOBJECT_PROPERTIES_DEFINE_BASE_FULL(suffix, ...) \
- typedef enum { \
- PROP_0##suffix, \
- __VA_ARGS__ _PROPERTY_ENUMS_LAST##suffix, \
- } _PropertyEnums##suffix; \
- static GParamSpec *obj_properties##suffix[_PROPERTY_ENUMS_LAST##suffix] = { \
- NULL, \
- }
-
-#define NM_GOBJECT_PROPERTIES_DEFINE_NOTIFY(suffix, obj_type) \
- static inline void _nm_gobject_notify_together_impl##suffix( \
- obj_type * obj, \
- guint n, \
- const _PropertyEnums##suffix *props) \
- { \
- GObject *const gobj = (GObject *) obj; \
- GParamSpec * pspec_first = NULL; \
- gboolean frozen = FALSE; \
- \
- nm_assert(G_IS_OBJECT(obj)); \
- nm_assert(n > 0); \
- \
- while (n-- > 0) { \
- const _PropertyEnums##suffix prop = *props++; \
- GParamSpec * pspec; \
- \
- if (prop == PROP_0##suffix) \
- continue; \
- \
- nm_assert((gsize) prop < G_N_ELEMENTS(obj_properties##suffix)); \
- pspec = obj_properties##suffix[prop]; \
- nm_assert(pspec); \
- \
- if (!frozen) { \
- if (!pspec_first) { \
- pspec_first = pspec; \
- continue; \
- } \
- frozen = TRUE; \
- g_object_freeze_notify(gobj); \
- g_object_notify_by_pspec(gobj, pspec_first); \
- } \
- g_object_notify_by_pspec(gobj, pspec); \
- } \
- \
- if (frozen) \
- g_object_thaw_notify(gobj); \
- else if (pspec_first) \
- g_object_notify_by_pspec(gobj, pspec_first); \
- } \
- \
- _nm_unused static inline void _notify##suffix(obj_type *obj, _PropertyEnums##suffix prop) \
- { \
- _nm_gobject_notify_together_impl##suffix(obj, 1, &prop); \
- } \
- _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON
-
-#define NM_GOBJECT_PROPERTIES_DEFINE_BASE(...) \
- NM_GOBJECT_PROPERTIES_DEFINE_BASE_FULL(, __VA_ARGS__);
-
-#define NM_GOBJECT_PROPERTIES_DEFINE_FULL(suffix, obj_type, ...) \
- NM_GOBJECT_PROPERTIES_DEFINE_BASE_FULL(suffix, __VA_ARGS__); \
- NM_GOBJECT_PROPERTIES_DEFINE_NOTIFY(suffix, obj_type)
-
-#define NM_GOBJECT_PROPERTIES_DEFINE(obj_type, ...) \
- NM_GOBJECT_PROPERTIES_DEFINE_FULL(, obj_type, __VA_ARGS__)
-
-/* invokes _notify() for all arguments (of type _PropertyEnums). Note, that if
- * there are more than one prop arguments, this will involve a freeze/thaw
- * of GObject property notifications. */
-#define nm_gobject_notify_together_full(suffix, obj, ...) \
- _nm_gobject_notify_together_impl##suffix(obj, \
- NM_NARG(__VA_ARGS__), \
- (const _PropertyEnums##suffix[]){__VA_ARGS__})
-
-#define nm_gobject_notify_together(obj, ...) nm_gobject_notify_together_full(, obj, __VA_ARGS__)
-
-/*****************************************************************************/
-
-#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); \
- })
-#else
- #define _NM_GET_PRIVATE_PTR(self, type, is_check, ...) \
- (NM_GOBJECT_CAST_NON_NULL(type, (self), is_check, ##__VA_ARGS__)->_priv)
-#endif
-
-/*****************************************************************************/
-
-static inline gpointer
-nm_g_object_ref(gpointer obj)
-{
- /* g_object_ref() doesn't accept NULL. */
- if (obj)
- g_object_ref(obj);
- return obj;
-}
-#define nm_g_object_ref(obj) ((typeof(obj)) nm_g_object_ref(obj))
-
-static inline void
-nm_g_object_unref(gpointer obj)
-{
- /* g_object_unref() doesn't accept NULL. Usually, we workaround that
- * by using g_clear_object(), but sometimes that is not convenient
- * (for example as destroy function for a hash table that can contain
- * NULL values). */
- if (obj)
- g_object_unref(obj);
-}
-
-/* Assigns GObject @obj to destination @pp, and takes an additional ref.
- * The previous value of @pp is unrefed.
- *
- * It makes sure to first increase the ref-count of @obj, and handles %NULL
- * @obj correctly.
- * */
-#define nm_g_object_ref_set(pp, obj) \
- ({ \
- typeof(*(pp)) *const _pp = (pp); \
- typeof(*_pp) const _obj = (obj); \
- typeof(*_pp) _p; \
- gboolean _changed = FALSE; \
- \
- nm_assert(!_pp || !*_pp || G_IS_OBJECT(*_pp)); \
- nm_assert(!_obj || G_IS_OBJECT(_obj)); \
- \
- if (_pp && ((_p = *_pp) != _obj)) { \
- nm_g_object_ref(_obj); \
- *_pp = _obj; \
- nm_g_object_unref(_p); \
- _changed = TRUE; \
- } \
- _changed; \
- })
-
-#define nm_g_object_ref_set_take(pp, obj) \
- ({ \
- typeof(*(pp)) *const _pp = (pp); \
- typeof(*_pp) const _obj = (obj); \
- typeof(*_pp) _p; \
- gboolean _changed = FALSE; \
- \
- nm_assert(!_pp || !*_pp || G_IS_OBJECT(*_pp)); \
- nm_assert(!_obj || G_IS_OBJECT(_obj)); \
- \
- if (_pp && ((_p = *_pp) != _obj)) { \
- *_pp = _obj; \
- nm_g_object_unref(_p); \
- _changed = TRUE; \
- } else \
- nm_g_object_unref(_obj); \
- _changed; \
- })
-
-/* basically, replaces
- * g_clear_pointer (&location, g_free)
- * with
- * nm_clear_g_free (&location)
- *
- * Another advantage is that by using a macro and typeof(), it is more
- * typesafe and gives you for example a compiler warning when pp is a const
- * pointer or points to a const-pointer.
- */
-#define nm_clear_g_free(pp) nm_clear_pointer(pp, g_free)
-
-/* Our nm_clear_pointer() is more typesafe than g_clear_pointer() and
- * should be preferred.
- *
- * For g_clear_object() that is not the case (because g_object_unref()
- * anyway takes a void pointer). So using g_clear_object() is fine.
- *
- * Still have a nm_clear_g_object() because that returns a boolean
- * indication whether anything was cleared. */
-#define nm_clear_g_object(pp) nm_clear_pointer(pp, g_object_unref)
-
-/**
- * nm_clear_error:
- * @err: a pointer to pointer to a #GError.
- *
- * This is like g_clear_error(). The only difference is
- * that this is an inline function.
- */
-static inline void
-nm_clear_error(GError **err)
-{
- if (err && *err) {
- g_error_free(*err);
- *err = NULL;
- }
-}
-
-/* Patch g_clear_error() to use nm_clear_error(), which is inlineable
- * and visible to the compiler. For example gs_free_error attribute only
- * frees the error after checking that it's not %NULL. So, in many cases
- * the compiler knows that gs_free_error has no effect and can optimize
- * the call away. By making g_clear_error() inlineable, we give the compiler
- * more chance to detect that the function actually has no effect. */
-#define g_clear_error(ptr) nm_clear_error(ptr)
-
-static inline gboolean
-nm_clear_g_source(guint *id)
-{
- guint v;
-
- if (id && (v = *id)) {
- *id = 0;
- g_source_remove(v);
- return TRUE;
- }
- return FALSE;
-}
-
-static inline gboolean
-nm_clear_g_signal_handler(gpointer self, gulong *id)
-{
- gulong v;
-
- if (id && (v = *id)) {
- *id = 0;
- g_signal_handler_disconnect(self, v);
- return TRUE;
- }
- return FALSE;
-}
-
-static inline gboolean
-nm_clear_g_variant(GVariant **variant)
-{
- GVariant *v;
-
- if (variant && (v = *variant)) {
- *variant = NULL;
- g_variant_unref(v);
- return TRUE;
- }
- return FALSE;
-}
-
-static inline gboolean
-nm_clear_g_cancellable(GCancellable **cancellable)
-{
- GCancellable *v;
-
- if (cancellable && (v = *cancellable)) {
- *cancellable = NULL;
- g_cancellable_cancel(v);
- g_object_unref(v);
- return TRUE;
- }
- return FALSE;
-}
-
-/* If @cancellable_id is not 0, clear it and call g_cancellable_disconnect().
- * @cancellable may be %NULL, if there is nothing to disconnect.
- *
- * It's like nm_clear_g_signal_handler(), except that it uses g_cancellable_disconnect()
- * instead of g_signal_handler_disconnect().
- *
- * Note the warning in glib documentation about dead-lock and what g_cancellable_disconnect()
- * actually does. */
-static inline gboolean
-nm_clear_g_cancellable_disconnect(GCancellable *cancellable, gulong *cancellable_id)
-{
- gulong id;
-
- if (cancellable_id && (id = *cancellable_id) != 0) {
- *cancellable_id = 0;
- g_cancellable_disconnect(cancellable, id);
- return TRUE;
- }
- return FALSE;
-}
-
-/*****************************************************************************/
-
-static inline const char *
-nm_dbus_path_not_empty(const char *str)
-{
- nm_assert(!str || str[0] == '/');
- return !str || (str[0] == '/' && str[1] == '\0') ? NULL : str;
-}
-
-/*****************************************************************************/
-
-/* GVariantType is basically a C string. But G_VARIANT_TYPE() is not suitable
- * to initialize a static variable (because it evaluates a function check that
- * the string is valid). Add an alternative macro that does the plain cast.
- *
- * Here you loose the assertion check that G_VARIANT_TYPE() to ensure the
- * string is valid. */
-#define NM_G_VARIANT_TYPE(fmt) ((const GVariantType *) ("" fmt ""))
-
-static inline GVariant *
-nm_g_variant_ref(GVariant *v)
-{
- if (v)
- g_variant_ref(v);
- return v;
-}
-
-static inline GVariant *
-nm_g_variant_ref_sink(GVariant *v)
-{
- if (v)
- g_variant_ref_sink(v);
- return v;
-}
-
-static inline void
-nm_g_variant_unref(GVariant *v)
-{
- if (v)
- g_variant_unref(v);
-}
-
-static inline GVariant *
-nm_g_variant_take_ref(GVariant *v)
-{
- if (v)
- g_variant_take_ref(v);
- return v;
-}
-
-/*****************************************************************************/
-
-#define NM_DIV_ROUND_UP(x, y) \
- ({ \
- const typeof(x) _x = (x); \
- const typeof(y) _y = (y); \
- \
- (_x / _y + !!(_x % _y)); \
- })
-
-/*****************************************************************************/
-
-#define NM_UTILS_LOOKUP_DEFAULT(v) return (v)
-#define NM_UTILS_LOOKUP_DEFAULT_WARN(v) g_return_val_if_reached(v)
-#define NM_UTILS_LOOKUP_DEFAULT_NM_ASSERT(v) \
- { \
- nm_assert_not_reached(); \
- return (v); \
- }
-#define NM_UTILS_LOOKUP_ITEM(v, n) \
- (void) 0; \
-case v: \
- return (n); \
- (void) 0
-#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
-#define NM_UTILS_LOOKUP_ITEM_IGNORE_OTHER() \
- (void) 0; \
-default: \
- break; \
- (void) 0
-
-#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; \
- }; \
- { \
- unknown_val; \
- } \
- } \
- _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON
-
-#define NM_UTILS_LOOKUP_STR_DEFINE(fcn_name, lookup_type, unknown_val, ...) \
- NM_UTILS_LOOKUP_DEFINE(fcn_name, lookup_type, const char *, unknown_val, __VA_ARGS__)
-
-/* Call the string-lookup-table function @fcn_name. If the function returns
- * %NULL, the numeric index is converted to string using a alloca() buffer.
- * Beware: this macro uses alloca(). */
-#define NM_UTILS_LOOKUP_STR_A(fcn_name, idx) \
- ({ \
- typeof(idx) _idx = (idx); \
- const char *_s; \
- \
- _s = fcn_name(_idx); \
- if (!_s) { \
- _s = g_alloca(30); \
- \
- g_snprintf((char *) _s, 30, "(%lld)", (long long) _idx); \
- } \
- _s; \
- })
-
-/*****************************************************************************/
-
-/* check if @flags has exactly one flag (@check) set. You should call this
- * only with @check being a compile time constant and a power of two. */
-#define NM_FLAGS_HAS(flags, check) \
- (G_STATIC_ASSERT_EXPR((check) > 0 && ((check) & ((check) -1)) == 0), \
- NM_FLAGS_ANY((flags), (check)))
-
-#define NM_FLAGS_ANY(flags, check) ((((flags) & (check)) != 0) ? TRUE : FALSE)
-#define NM_FLAGS_ALL(flags, check) ((((flags) & (check)) == (check)) ? TRUE : FALSE)
-
-#define NM_FLAGS_SET(flags, val) \
- ({ \
- const typeof(flags) _flags = (flags); \
- const typeof(flags) _val = (val); \
- \
- _flags | _val; \
- })
-
-#define NM_FLAGS_UNSET(flags, val) \
- ({ \
- const typeof(flags) _flags = (flags); \
- const typeof(flags) _val = (val); \
- \
- _flags &(~_val); \
- })
-
-#define NM_FLAGS_ASSIGN(flags, val, assign) \
- ({ \
- const typeof(flags) _flags = (flags); \
- const typeof(flags) _val = (val); \
- \
- (assign) ? _flags | (_val) : _flags &(~_val); \
- })
-
-#define NM_FLAGS_ASSIGN_MASK(flags, mask, val) \
- ({ \
- const typeof(flags) _flags = (flags); \
- const typeof(flags) _mask = (mask); \
- const typeof(flags) _val = (val); \
- \
- ((_flags & ~_mask) | (_mask & _val)); \
- })
-
-/*****************************************************************************/
-
-#define _NM_BACKPORT_SYMBOL_IMPL(version, \
- return_type, \
- orig_func, \
- versioned_func, \
- args_typed, \
- args) \
- return_type versioned_func args_typed; \
- _nm_externally_visible return_type versioned_func args_typed \
- { \
- return orig_func args; \
- } \
- return_type orig_func args_typed; \
- __asm__(".symver " G_STRINGIFY(versioned_func) ", " G_STRINGIFY(orig_func) "@" G_STRINGIFY( \
- version))
-
-#define NM_BACKPORT_SYMBOL(version, return_type, func, args_typed, args) \
- _NM_BACKPORT_SYMBOL_IMPL(version, return_type, func, _##func##_##version, args_typed, args)
-
-/*****************************************************************************/
-
-/* mirrors g_ascii_isspace() and what we consider spaces in general. */
-#define NM_ASCII_SPACES " \n\t\r\f"
-
-/* Like NM_ASCII_SPACES, but without "\f" (0x0c, Formfeed Page Break).
- * This is what for example systemd calls WHITESPACE and what it uses to tokenize
- * the kernel command line. */
-#define NM_ASCII_WHITESPACES " \n\t\r"
-
-#define nm_str_skip_leading_spaces(str) \
- ({ \
- typeof(*(str)) * _str_sls = (str); \
- _nm_unused const char *const _str_type_check = _str_sls; \
- \
- if (_str_sls) { \
- while (g_ascii_isspace(_str_sls[0])) \
- _str_sls++; \
- } \
- _str_sls; \
- })
-
-static inline char *
-nm_strstrip(char *str)
-{
- /* g_strstrip doesn't like NULL. */
- return str ? g_strstrip(str) : NULL;
-}
-
-static inline const char *
-nm_strstrip_avoid_copy(const char *str, char **str_free)
-{
- gsize l;
- char *s;
-
- nm_assert(str_free && !*str_free);
-
- if (!str)
- return NULL;
-
- str = nm_str_skip_leading_spaces(str);
- l = strlen(str);
- if (l == 0 || !g_ascii_isspace(str[l - 1]))
- return str;
- while (l > 0 && g_ascii_isspace(str[l - 1]))
- l--;
-
- s = g_new(char, l + 1);
- memcpy(s, str, l);
- s[l] = '\0';
- *str_free = s;
- return s;
-}
-
-#define nm_strstrip_avoid_copy_a(alloca_maxlen, str, out_str_free) \
- ({ \
- const char *_str_ssac = (str); \
- char ** _out_str_free_ssac = (out_str_free); \
- \
- G_STATIC_ASSERT_EXPR((alloca_maxlen) > 0); \
- \
- nm_assert(_out_str_free_ssac || ((alloca_maxlen) > (str ? strlen(str) : 0u))); \
- nm_assert(!_out_str_free_ssac || !*_out_str_free_ssac); \
- \
- if (_str_ssac) { \
- _str_ssac = nm_str_skip_leading_spaces(_str_ssac); \
- if (_str_ssac[0] != '\0') { \
- gsize _l = strlen(_str_ssac); \
- \
- if (g_ascii_isspace(_str_ssac[--_l])) { \
- while (_l > 0 && g_ascii_isspace(_str_ssac[_l - 1])) { \
- _l--; \
- } \
- _str_ssac = nm_strndup_a((alloca_maxlen), _str_ssac, _l, _out_str_free_ssac); \
- } \
- } \
- } \
- \
- _str_ssac; \
- })
-
-static inline gboolean
-nm_str_is_stripped(const char *str)
-{
- if (str && str[0]) {
- if (g_ascii_isspace(str[0]) || g_ascii_isspace(str[strlen(str) - 1]))
- return FALSE;
- }
- return TRUE;
-}
-
-/* g_ptr_array_sort()'s compare function takes pointers to the
- * value. Thus, you cannot use strcmp directly. You can use
- * nm_strcmp_p().
- *
- * Like strcmp(), this function is not forgiving to accept %NULL. */
-static inline int
-nm_strcmp_p(gconstpointer a, gconstpointer b)
-{
- const char *s1 = *((const char **) a);
- const char *s2 = *((const char **) b);
-
- return strcmp(s1, s2);
-}
-
-/*****************************************************************************/
-
-static inline int
-_NM_IN_STRSET_ASCII_CASE_op_streq(const char *x, const char *s)
-{
- return s && g_ascii_strcasecmp(x, s) == 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_STR_HAS_SUFFIX_ASCII_CASE(str, suffix) \
- ({ \
- const char *const _str_has_suffix = (str); \
- size_t _l; \
- \
- nm_assert(strlen(suffix) == NM_STRLEN(suffix)); \
- \
- (_str_has_suffix && ((_l = strlen(_str_has_suffix)) >= NM_STRLEN(suffix)) \
- && (g_ascii_strcasecmp(&_str_has_suffix[_l - NM_STRLEN(suffix)], "" suffix "") == 0)); \
- })
-
-#define NM_STR_HAS_SUFFIX_ASCII_CASE_WITH_MORE(str, suffix) \
- ({ \
- const char *const _str_has_suffix = (str); \
- size_t _l; \
- \
- nm_assert(strlen(suffix) == NM_STRLEN(suffix)); \
- \
- (_str_has_suffix && ((_l = strlen(_str_has_suffix)) > NM_STRLEN(suffix)) \
- && (g_ascii_strcasecmp(&_str_has_suffix[_l - NM_STRLEN(suffix)], "" suffix "") == 0)); \
- })
-
-/*****************************************************************************/
-
-#define nm_g_slice_free(ptr) g_slice_free(typeof(*(ptr)), ptr)
-
-/*****************************************************************************/
-
-/* 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
- * array,
- * g_memdup (array->data, array->len * sizeof (ElementType))
- * will lead to integer overflow, if there are more than G_MAXUINT/sizeof(ElementType)
- * bytes. That seems unnecessarily dangerous to me.
- * nm_memdup() avoids that, because its size argument is always large enough
- * to contain all data that a GArray can hold.
- *
- * Another minor difference to g_memdup() is that the glib version also
- * returns %NULL if @data is %NULL. E.g. g_memdup(NULL, 1)
- * gives %NULL, but nm_memdup(NULL, 1) crashes. I think that
- * is desirable, because @size MUST be correct at all times. @size
- * may be zero, but one must not claim to have non-zero bytes when
- * passing a %NULL @data pointer.
- */
-static inline gpointer
-nm_memdup(gconstpointer data, gsize size)
-{
- gpointer p;
-
- if (size == 0)
- return NULL;
- p = g_malloc(size);
- memcpy(p, data, size);
- return p;
-}
-
-#define nm_malloc_maybe_a(alloca_maxlen, bytes, to_free) \
- ({ \
- const gsize _bytes = (bytes); \
- typeof(to_free) _to_free = (to_free); \
- typeof(*_to_free) _ptr; \
- \
- G_STATIC_ASSERT_EXPR((alloca_maxlen) <= 500u); \
- G_STATIC_ASSERT_EXPR((alloca_maxlen) > 0u); \
- nm_assert(_to_free && !*_to_free); \
- \
- if (G_LIKELY(_bytes <= (alloca_maxlen))) { \
- _ptr = _bytes > 0u ? g_alloca(_bytes) : NULL; \
- } else { \
- _ptr = g_malloc(_bytes); \
- *_to_free = _ptr; \
- }; \
- \
- _ptr; \
- })
-
-#define nm_malloc0_maybe_a(alloca_maxlen, bytes, to_free) \
- ({ \
- const gsize _bytes = (bytes); \
- typeof(to_free) _to_free = (to_free); \
- typeof(*_to_free) _ptr; \
- \
- G_STATIC_ASSERT_EXPR((alloca_maxlen) <= 500u); \
- G_STATIC_ASSERT_EXPR((alloca_maxlen) > 0u); \
- nm_assert(_to_free && !*_to_free); \
- \
- if (G_LIKELY(_bytes <= (alloca_maxlen))) { \
- if (_bytes > 0u) { \
- _ptr = g_alloca(_bytes); \
- memset(_ptr, 0, _bytes); \
- } else \
- _ptr = NULL; \
- } else { \
- _ptr = g_malloc0(_bytes); \
- *_to_free = _ptr; \
- }; \
- \
- _ptr; \
- })
-
-#define nm_memdup_maybe_a(alloca_maxlen, data, size, to_free) \
- ({ \
- const gsize _size = (size); \
- typeof(to_free) _to_free_md = (to_free); \
- typeof(*_to_free_md) _ptr_md = NULL; \
- \
- nm_assert(_to_free_md && !*_to_free_md); \
- \
- if (_size > 0u) { \
- _ptr_md = nm_malloc_maybe_a((alloca_maxlen), _size, _to_free_md); \
- memcpy(_ptr_md, (data), _size); \
- } \
- \
- _ptr_md; \
- })
-
-static inline char *
-_nm_strndup_a_step(char *s, const char *str, gsize len)
-{
- NM_PRAGMA_WARNING_DISABLE("-Wstringop-truncation");
- NM_PRAGMA_WARNING_DISABLE("-Wstringop-overflow");
- if (len > 0)
- strncpy(s, str, len);
- s[len] = '\0';
- return s;
- NM_PRAGMA_WARNING_REENABLE;
- NM_PRAGMA_WARNING_REENABLE;
-}
-
-/* Similar to g_strndup(), however, if the string (including the terminating
- * NUL char) fits into alloca_maxlen, this will alloca() the memory.
- *
- * It's a mix of strndup() and strndupa(), but deciding based on @alloca_maxlen
- * which one to use.
- *
- * In case malloc() is necessary, @out_str_free will be set (this string
- * must be freed afterwards). It is permissible to pass %NULL as @out_str_free,
- * if you ensure that len < alloca_maxlen.
- *
- * Note that just like g_strndup(), this always returns a buffer with @len + 1
- * bytes, even if strlen(@str) is shorter than that (NUL terminated early). We fill
- * the buffer with strncpy(), which means, that @str is copied up to the first
- * NUL character and then filled with NUL characters. */
-#define nm_strndup_a(alloca_maxlen, str, len, out_str_free) \
- ({ \
- const gsize _alloca_maxlen_snd = (alloca_maxlen); \
- const char *const _str_snd = (str); \
- const gsize _len_snd = (len); \
- char **const _out_str_free_snd = (out_str_free); \
- char * _s_snd; \
- \
- G_STATIC_ASSERT_EXPR((alloca_maxlen) <= 300); \
- \
- if (_out_str_free_snd && _len_snd >= _alloca_maxlen_snd) { \
- _s_snd = g_malloc(_len_snd + 1); \
- *_out_str_free_snd = _s_snd; \
- } else { \
- g_assert(_len_snd < _alloca_maxlen_snd); \
- _s_snd = g_alloca(_len_snd + 1); \
- } \
- _nm_strndup_a_step(_s_snd, _str_snd, _len_snd); \
- })
-
-#define nm_strdup_maybe_a(alloca_maxlen, str, out_str_free) \
- ({ \
- const char *const _str_snd = (str); \
- \
- (char *) nm_memdup_maybe_a(alloca_maxlen, \
- _str_snd, \
- _str_snd ? strlen(_str_snd) + 1u : 0u, \
- out_str_free); \
- })
-
-/*****************************************************************************/
-
-/* generic macro to convert an int to a (heap allocated) string.
- *
- * Usually, an inline function nm_strdup_int64() would be enough. However,
- * that cannot be used for guint64. So, we would also need nm_strdup_uint64().
- * This causes subtle error potential, because the caller needs to ensure to
- * use the right one (and compiler isn't going to help as it silently casts).
- *
- * 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)))
-#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)))
-#endif
-
-/*****************************************************************************/
-
-static inline guint
-nm_encode_version(guint major, guint minor, guint micro)
-{
- /* analog to the preprocessor macro NM_ENCODE_VERSION(). */
- return (major << 16) | (minor << 8) | micro;
-}
-
-static inline void
-nm_decode_version(guint version, guint *major, guint *minor, guint *micro)
-{
- *major = (version & 0xFFFF0000u) >> 16;
- *minor = (version & 0x0000FF00u) >> 8;
- *micro = (version & 0x000000FFu);
-}
-
-/*****************************************************************************/
-
-/* taken from systemd's DECIMAL_STR_MAX()
- *
- * Returns the number of chars needed to format variables of the
- * specified type as a decimal string. Adds in extra space for a
- * negative '-' prefix (hence works correctly on signed
- * types). Includes space for the trailing NUL. */
-#define NM_DECIMAL_STR_MAX(type) \
- (2 \
- + (sizeof(type) <= 1 ? 3 \
- : sizeof(type) <= 2 ? 5 \
- : sizeof(type) <= 4 ? 10 \
- : sizeof(type) <= 8 ? 20 \
- : sizeof(int[-2 * (sizeof(type) > 8)])))
-
-/*****************************************************************************/
-
-/* if @str is NULL, return "(null)". Otherwise, allocate a buffer using
- * alloca() of and fill it with @str. @str will be quoted with double quote.
- * If @str is longer then @trunc_at, the string is truncated and the closing
- * quote is instead '^' to indicate truncation.
- *
- * Thus, the maximum stack allocated buffer will be @trunc_at+3. The maximum
- * buffer size must be a constant and not larger than 300. */
-#define nm_strquote_a(trunc_at, str) \
- ({ \
- const char *const _str = (str); \
- \
- (_str ? ({ \
- const gsize _trunc_at = (trunc_at); \
- const gsize _strlen_trunc = NM_MIN(strlen(_str), _trunc_at); \
- char * _buf; \
- \
- G_STATIC_ASSERT_EXPR((trunc_at) <= 300); \
- \
- _buf = g_alloca(_strlen_trunc + 3); \
- _buf[0] = '"'; \
- memcpy(&_buf[1], _str, _strlen_trunc); \
- _buf[_strlen_trunc + 1] = _str[_strlen_trunc] ? '^' : '"'; \
- _buf[_strlen_trunc + 2] = '\0'; \
- _buf; \
- }) \
- : "(null)"); \
- })
-
-#define nm_sprintf_buf(buf, format, ...) \
- ({ \
- char *_buf = (buf); \
- int _buf_len; \
- \
- /* some static assert trying to ensure that the buffer is statically allocated.
- * It disallows a buffer size of sizeof(gpointer) to catch that. */ \
- G_STATIC_ASSERT(G_N_ELEMENTS(buf) == sizeof(buf) && sizeof(buf) != sizeof(char *)); \
- _buf_len = g_snprintf(_buf, sizeof(buf), "" format "", ##__VA_ARGS__); \
- nm_assert(_buf_len < sizeof(buf)); \
- _buf; \
- })
-
-/* it is "unsafe" because @bufsize must not be a constant expression and
- * there is no check at compiletime. Regardless of that, the buffer size
- * must not be larger than 300 bytes, as this gets stack allocated. */
-#define nm_sprintf_buf_unsafe_a(bufsize, format, ...) \
- ({ \
- char *_buf; \
- int _buf_len; \
- typeof(bufsize) _bufsize = (bufsize); \
- \
- nm_assert(_bufsize <= 300); \
- \
- _buf = g_alloca(_bufsize); \
- _buf_len = g_snprintf(_buf, _bufsize, "" format "", ##__VA_ARGS__); \
- nm_assert(_buf_len >= 0 && _buf_len < _bufsize); \
- _buf; \
- })
-
-#define nm_sprintf_bufa(bufsize, format, ...) \
- ({ \
- G_STATIC_ASSERT_EXPR((bufsize) <= 300); \
- nm_sprintf_buf_unsafe_a((bufsize), format, ##__VA_ARGS__); \
- })
-
-/* aims to alloca() a buffer and fill it with printf(format, name).
- * Note that format must not contain any format specifier except
- * "%s".
- * If the resulting string would be too large for stack allocation,
- * it allocates a buffer with g_malloc() and assigns it to *p_val_to_free. */
-#define nm_construct_name_a(format, name, p_val_to_free) \
- ({ \
- const char *const _name = (name); \
- char **const _p_val_to_free = (p_val_to_free); \
- const gsize _name_len = strlen(_name); \
- char * _buf2; \
- \
- nm_assert(_p_val_to_free && !*_p_val_to_free); \
- if (NM_STRLEN(format) <= 290 && _name_len < (gsize)(290 - NM_STRLEN(format))) \
- _buf2 = nm_sprintf_buf_unsafe_a(NM_STRLEN(format) + _name_len, format, _name); \
- else { \
- _buf2 = g_strdup_printf(format, _name); \
- *_p_val_to_free = _buf2; \
- } \
- (const char *) _buf2; \
- })
-
-/*****************************************************************************/
-
-#ifdef _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 ());
- * where some_macro() itself expands to ({g_assert(); ...}).
- * In other words, you cannot have a g_assert() inside a g_assert()
- * without getting a -Werror=shadow failure.
- *
- * Workaround that by re-defining _G_BOOLEAN_EXPR()
- **/
- #undef _G_BOOLEAN_EXPR
- #define _G_BOOLEAN_EXPR(expr) NM_BOOLEAN_EXPR(expr)
-#endif
-
-/*****************************************************************************/
-
-#define NM_PID_T_INVAL ((pid_t) -1)
-
-/*****************************************************************************/
-
-NM_AUTO_DEFINE_FCN_VOID0(GMutex *, _nm_auto_unlock_g_mutex, g_mutex_unlock);
-
-#define nm_auto_unlock_g_mutex nm_auto(_nm_auto_unlock_g_mutex)
-
-#define _NM_G_MUTEX_LOCKED(lock, uniq) \
- nm_auto_unlock_g_mutex GMutex *NM_UNIQ_T(nm_lock, uniq) = (lock)
-
-#define NM_G_MUTEX_LOCKED(lock) _NM_G_MUTEX_LOCKED(lock, NM_UNIQ)
-
-/*****************************************************************************/
-
-#endif /* __NM_MACROS_INTERNAL_H__ */
diff --git a/shared/nm-glib-aux/nm-obj.h b/shared/nm-glib-aux/nm-obj.h
deleted file mode 100644
index 2062f66180..0000000000
--- a/shared/nm-glib-aux/nm-obj.h
+++ /dev/null
@@ -1,66 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2017 Red Hat, Inc.
- */
-
-#ifndef __NM_OBJ_H__
-#define __NM_OBJ_H__
-
-/*****************************************************************************/
-
-#define NM_OBJ_REF_COUNT_STACKINIT (G_MAXINT)
-
-typedef struct _NMObjBaseInst NMObjBaseInst;
-typedef struct _NMObjBaseClass NMObjBaseClass;
-
-struct _NMObjBaseInst {
- /* The first field of NMObjBaseInst is compatible with GObject.
- * Basically, NMObjBaseInst is an abstract base type of GTypeInstance.
- *
- * If you do it right, you may derive a type of NMObjBaseInst as a proper GTypeInstance.
- * That involves allocating a GType for it, which can be inconvenient because
- * a GType is dynamically created (and the class can no longer be immutable
- * memory).
- *
- * Even if your implementation of NMObjBaseInst is not a full fledged GType(Instance),
- * you still can use GTypeInstances in the same context as you can decide based on the
- * NMObjBaseClass with what kind of object you are dealing with.
- *
- * Basically, the only thing NMObjBaseInst gives you is access to an
- * NMObjBaseClass instance.
- */
- union {
- const NMObjBaseClass *klass;
- GTypeInstance g_type_instance;
- };
-};
-
-struct _NMObjBaseClass {
- /* NMObjBaseClass is the base class of all NMObjBaseInst implementations.
- * Note that it is also an abstract super class of GTypeInstance, that means
- * you may implement a NMObjBaseClass as a subtype of GTypeClass.
- *
- * For that to work, you must properly set the GTypeClass instance (and its
- * GType).
- *
- * Note that to implement a NMObjBaseClass that is *not* a GTypeClass, you wouldn't
- * set the GType. Hence, this field is only useful for type implementations that actually
- * extend GTypeClass.
- *
- * In a way it is wrong that NMObjBaseClass has the GType member, because it is
- * a base class of GTypeClass and doesn't necessarily use the GType. However,
- * it is here so that G_TYPE_CHECK_INSTANCE_TYPE() and friends work correctly
- * on any NMObjectClass. That means, while not necessary, it is convenient that
- * a NMObjBaseClass has all members of GTypeClass.
- * Also note that usually you have only one instance of a certain type, so this
- * wastes just a few bytes for the unneeded GType.
- */
- union {
- GType g_type;
- GTypeClass g_type_class;
- };
-};
-
-/*****************************************************************************/
-
-#endif /* __NM_OBJ_H__ */
diff --git a/shared/nm-glib-aux/nm-random-utils.c b/shared/nm-glib-aux/nm-random-utils.c
deleted file mode 100644
index c95d368dd3..0000000000
--- a/shared/nm-glib-aux/nm-random-utils.c
+++ /dev/null
@@ -1,148 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2017 Red Hat, Inc.
- */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-random-utils.h"
-
-#include <fcntl.h>
-
-#if USE_SYS_RANDOM_H
- #include <sys/random.h>
-#else
- #include <linux/random.h>
-#endif
-
-#include "nm-shared-utils.h"
-
-/*****************************************************************************/
-
-/**
- * nm_utils_random_bytes:
- * @p: the buffer to fill
- * @n: the number of bytes to write to @p.
- *
- * Uses getrandom() or reads /dev/urandom to fill the buffer
- * with random data. If all fails, as last fallback it uses
- * GRand to fill the buffer with pseudo random numbers.
- * The function always succeeds in writing some random numbers
- * to the buffer. The return value of FALSE indicates that the
- * obtained bytes are probably not of good randomness.
- *
- * Returns: whether the written bytes are good. If you
- * don't require good randomness, you can ignore the return
- * value.
- *
- * Note that if calling getrandom() fails because there is not enough
- * entropy (at early boot), the function will read /dev/urandom.
- * Which of course, still has low entropy, and cause kernel to log
- * a warning.
- */
-gboolean
-nm_utils_random_bytes(void *p, size_t n)
-{
- int fd;
- int r;
- gboolean has_high_quality = TRUE;
- gboolean urandom_success;
- guint8 * buf = p;
- gboolean avoid_urandom = FALSE;
-
- g_return_val_if_fail(p, FALSE);
- g_return_val_if_fail(n > 0, FALSE);
-
-#if HAVE_GETRANDOM
- {
- static gboolean have_syscall = TRUE;
-
- if (have_syscall) {
- r = getrandom(buf, n, GRND_NONBLOCK);
- if (r > 0) {
- if ((size_t) r == n)
- return TRUE;
-
- /* no or partial read. There is not enough entropy.
- * Fill the rest reading from urandom, and remember that
- * some bits are not high quality. */
- nm_assert(r < n);
- buf += r;
- n -= r;
- has_high_quality = FALSE;
-
- /* At this point, we don't want to read /dev/urandom, because
- * the entropy pool is low (early boot?), and asking for more
- * entropy causes kernel messages to be logged.
- *
- * We use our fallback via GRand. Note that g_rand_new() also
- * tries to seed itself with data from /dev/urandom, but since
- * we reuse the instance, it shouldn't matter. */
- avoid_urandom = TRUE;
- } else {
- if (errno == ENOSYS) {
- /* no support for getrandom(). We don't know whether
- * we urandom will give us good quality. Assume yes. */
- have_syscall = FALSE;
- } else {
- /* unknown error. We'll read urandom below, but we don't have
- * high-quality randomness. */
- has_high_quality = FALSE;
- }
- }
- }
- }
-#endif
-
- urandom_success = FALSE;
- if (!avoid_urandom) {
-fd_open:
- fd = open("/dev/urandom", O_RDONLY | O_CLOEXEC | O_NOCTTY);
- if (fd < 0) {
- r = errno;
- if (r == EINTR)
- goto fd_open;
- } else {
- r = nm_utils_fd_read_loop_exact(fd, buf, n, TRUE);
- nm_close(fd);
- if (r >= 0)
- urandom_success = TRUE;
- }
- }
-
- if (!urandom_success) {
- static _nm_thread_local GRand *rand = NULL;
- gsize i;
- int j;
-
- /* we failed to fill the bytes reading from urandom.
- * Fill the bits using GRand pseudo random numbers.
- *
- * We don't have good quality.
- */
- has_high_quality = FALSE;
-
- if (G_UNLIKELY(!rand))
- rand = g_rand_new();
-
- nm_assert(n > 0);
- i = 0;
- for (;;) {
- const union {
- guint32 v32;
- guint8 v8[4];
- } v = {
- .v32 = g_rand_int(rand),
- };
-
- for (j = 0; j < 4;) {
- buf[i++] = v.v8[j++];
- if (i >= n)
- goto done;
- }
- }
-done:;
- }
-
- return has_high_quality;
-}
diff --git a/shared/nm-glib-aux/nm-random-utils.h b/shared/nm-glib-aux/nm-random-utils.h
deleted file mode 100644
index d0eae1033b..0000000000
--- a/shared/nm-glib-aux/nm-random-utils.h
+++ /dev/null
@@ -1,11 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2017 Red Hat, Inc.
- */
-
-#ifndef __NM_RANDOM_UTILS_H__
-#define __NM_RANDOM_UTILS_H__
-
-gboolean nm_utils_random_bytes(void *p, size_t n);
-
-#endif /* __NM_RANDOM_UTILS_H__ */
diff --git a/shared/nm-glib-aux/nm-ref-string.c b/shared/nm-glib-aux/nm-ref-string.c
deleted file mode 100644
index 1084c47f8a..0000000000
--- a/shared/nm-glib-aux/nm-ref-string.c
+++ /dev/null
@@ -1,203 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-ref-string.h"
-
-/*****************************************************************************/
-
-typedef struct {
- NMRefString r;
- volatile int ref_count;
- char str_data[];
-} RefString;
-
-G_LOCK_DEFINE_STATIC(gl_lock);
-static GHashTable *gl_hash;
-
-/* the first field of NMRefString is a pointer to the NUL terminated string.
- * This also allows to compare strings with nm_pstr_equal(), although, pointer
- * equality might be better. */
-G_STATIC_ASSERT(G_STRUCT_OFFSET(NMRefString, str) == 0);
-G_STATIC_ASSERT(G_STRUCT_OFFSET(RefString, r) == 0);
-G_STATIC_ASSERT(G_STRUCT_OFFSET(RefString, r.str) == 0);
-
-/*****************************************************************************/
-
-static guint
-_ref_string_hash(gconstpointer ptr)
-{
- const RefString *a = ptr;
- NMHashState h;
-
- nm_hash_init(&h, 1463435489u);
- nm_hash_update(&h, a->r.str, a->r.len);
- return nm_hash_complete(&h);
-}
-
-static gboolean
-_ref_string_equal(gconstpointer pa, gconstpointer pb)
-{
- const RefString *a = pa;
- const RefString *b = pb;
-
- return a->r.len == b->r.len && memcmp(a->r.str, b->r.str, a->r.len) == 0;
-}
-
-/*****************************************************************************/
-
-static void
-_ASSERT(const RefString *rstr0)
-{
- int r;
-
- nm_assert(rstr0);
-
- if (NM_MORE_ASSERTS > 0) {
- r = g_atomic_int_get(&rstr0->ref_count);
- nm_assert(r > 0);
- nm_assert(r < G_MAXINT);
- }
-
- nm_assert(rstr0->r.str == rstr0->str_data);
- nm_assert(rstr0->r.str[rstr0->r.len] == '\0');
-
- if (NM_MORE_ASSERTS > 10) {
- G_LOCK(gl_lock);
- r = g_atomic_int_get(&rstr0->ref_count);
- nm_assert(r > 0);
- nm_assert(r < G_MAXINT);
-
- nm_assert(rstr0 == g_hash_table_lookup(gl_hash, rstr0));
- G_UNLOCK(gl_lock);
- }
-}
-
-/**
- * nm_ref_string_new_len:
- * @cstr: the string to intern. Must contain @len bytes.
- * If @len is zero, @cstr may be %NULL. Note that it is
- * acceptable that the string contains a NUL character
- * within the first @len bytes. That is, the string is
- * not treated as a NUL terminated string, but as binary.
- * Also, contrary to strncpy(), this will read all the
- * first @len bytes. It won't stop at the first NUL.
- * @len: the length of the string (usually there is no NUL character
- * within the first @len bytes, but that would be acceptable as well
- * to add binary data).
- *
- * Note that the resulting NMRefString instance will always be NUL terminated
- * (at position @len).
- *
- * Note that NMRefString are always interned/deduplicated. If such a string
- * already exists, the existing instance will be referred and returned.
- *
- *
- * Since all NMRefString are shared and interned, you may use
- * pointer equality to compare them. Note that if a NMRefString contains
- * a NUL character (meaning, if
- *
- * strlen (nm_ref_string_get_str (str)) != nm_ref_string_get_len (str)
- *
- * ), then pointer in-equality does not mean that the NUL terminated strings
- * are also unequal. In other words, for strings that contain NUL characters,
- *
- * if (str1 != str2)
- * assert (!nm_streq0 (nm_ref_string_get_str (str1), nm_ref_string_get_str (str2)));
- *
- * might not hold!
- *
- *
- * NMRefString is thread-safe.
- *
- * Returns: (transfer full): the interned string. This is
- * never %NULL, but note that %NULL is also a valid NMRefString.
- * The result must be unrefed with nm_ref_string_unref().
- */
-NMRefString *
-nm_ref_string_new_len(const char *cstr, gsize len)
-{
- RefString *rstr0;
-
- G_LOCK(gl_lock);
-
- if (G_UNLIKELY(!gl_hash)) {
- gl_hash = g_hash_table_new_full(_ref_string_hash, _ref_string_equal, g_free, NULL);
- rstr0 = NULL;
- } else {
- NMRefString rr_lookup = {
- .len = len,
- .str = cstr,
- };
-
- rstr0 = g_hash_table_lookup(gl_hash, &rr_lookup);
- }
-
- if (rstr0) {
- nm_assert(({
- int r = g_atomic_int_get(&rstr0->ref_count);
-
- (r >= 0 && r < G_MAXINT);
- }));
- g_atomic_int_inc(&rstr0->ref_count);
- } else {
- rstr0 = g_malloc(sizeof(RefString) + 1 + len);
- rstr0->ref_count = 1;
- *((gsize *) &rstr0->r.len) = len;
- *((const char **) &rstr0->r.str) = rstr0->str_data;
- if (len > 0)
- memcpy(rstr0->str_data, cstr, len);
- rstr0->str_data[len] = '\0';
-
- if (!g_hash_table_add(gl_hash, rstr0))
- nm_assert_not_reached();
- }
-
- G_UNLOCK(gl_lock);
-
- return &rstr0->r;
-}
-
-NMRefString *
-nm_ref_string_ref(NMRefString *rstr)
-{
- RefString *const rstr0 = (RefString *) rstr;
-
- if (!rstr)
- return NULL;
-
- _ASSERT(rstr0);
-
- g_atomic_int_inc(&rstr0->ref_count);
- return &rstr0->r;
-}
-
-void
-_nm_ref_string_unref_non_null(NMRefString *rstr)
-{
- RefString *const rstr0 = (RefString *) rstr;
- int r;
-
- _ASSERT(rstr0);
-
- /* fast-path: first try to decrement the ref-count without bringing it
- * to zero. */
- r = rstr0->ref_count;
- if (G_LIKELY(r > 1 && g_atomic_int_compare_and_exchange(&rstr0->ref_count, r, r - 1)))
- return;
-
- /* We apparently are about to return the last reference. Take a lock. */
-
- G_LOCK(gl_lock);
-
- nm_assert(g_hash_table_lookup(gl_hash, rstr0) == rstr0);
-
- if (G_LIKELY(g_atomic_int_dec_and_test(&rstr0->ref_count))) {
- if (!g_hash_table_remove(gl_hash, rstr0))
- nm_assert_not_reached();
- }
-
- G_UNLOCK(gl_lock);
-}
-
-/*****************************************************************************/
diff --git a/shared/nm-glib-aux/nm-ref-string.h b/shared/nm-glib-aux/nm-ref-string.h
deleted file mode 100644
index 97c263b08f..0000000000
--- a/shared/nm-glib-aux/nm-ref-string.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#ifndef __NM_REF_STRING_H__
-#define __NM_REF_STRING_H__
-
-/*****************************************************************************/
-
-typedef struct _NMRefString {
- const char *const str;
- const gsize len;
-} NMRefString;
-
-/*****************************************************************************/
-
-NMRefString *nm_ref_string_new_len(const char *cstr, gsize len);
-
-static inline NMRefString *
-nm_ref_string_new(const char *cstr)
-{
- return cstr ? nm_ref_string_new_len(cstr, strlen(cstr)) : NULL;
-}
-
-NMRefString *nm_ref_string_ref(NMRefString *rstr);
-void _nm_ref_string_unref_non_null(NMRefString *rstr);
-
-static inline void
-nm_ref_string_unref(NMRefString *rstr)
-{
- if (rstr)
- _nm_ref_string_unref_non_null(rstr);
-}
-
-NM_AUTO_DEFINE_FCN_VOID0(NMRefString *, _nm_auto_ref_string, _nm_ref_string_unref_non_null);
-#define nm_auto_ref_string nm_auto(_nm_auto_ref_string)
-
-/*****************************************************************************/
-
-static inline const char *
-nm_ref_string_get_str(NMRefString *rstr)
-{
- return rstr ? rstr->str : NULL;
-}
-
-static inline gsize
-nm_ref_string_get_len(NMRefString *rstr)
-{
- return rstr ? rstr->len : 0u;
-}
-
-static inline gboolean
-nm_ref_string_equals_str(NMRefString *rstr, const char *s)
-{
- /* Note that rstr->len might be greater than strlen(rstr->str). This function does
- * not cover that and would ignore everything after the first NUL byte. If you need
- * that distinction, this function is not for you. */
-
- return rstr ? (s && nm_streq(rstr->str, s)) : (s == NULL);
-}
-
-static inline gboolean
-NM_IS_REF_STRING(const NMRefString *rstr)
-{
-#if NM_MORE_ASSERTS > 10
- if (rstr) {
- nm_auto_ref_string NMRefString *r2 = NULL;
-
- r2 = nm_ref_string_new_len(rstr->str, rstr->len);
- nm_assert(rstr == r2);
- }
-#endif
-
- /* Technically, %NULL is also a valid NMRefString (according to nm_ref_string_new(),
- * nm_ref_string_get_str() and nm_ref_string_unref()). However, NM_IS_REF_STRING()
- * does not think so. If callers want to allow %NULL, they need to check
- * separately. */
- return !!rstr;
-}
-
-#endif /* __NM_REF_STRING_H__ */
diff --git a/shared/nm-glib-aux/nm-secret-utils.c b/shared/nm-glib-aux/nm-secret-utils.c
deleted file mode 100644
index 8188b503a3..0000000000
--- a/shared/nm-glib-aux/nm-secret-utils.c
+++ /dev/null
@@ -1,178 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2018 Red Hat, Inc.
- * Copyright (C) 2015 - 2019 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
- */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-secret-utils.h"
-
-#include <malloc.h>
-
-/*****************************************************************************/
-
-void
-nm_explicit_bzero(void *s, gsize n)
-{
- /* gracefully handle n == 0. This is important, callers rely on it. */
- if (G_UNLIKELY(n == 0))
- return;
-
- nm_assert(s);
-
-#if defined(HAVE_DECL_EXPLICIT_BZERO) && HAVE_DECL_EXPLICIT_BZERO
- explicit_bzero(s, n);
-#else
- {
- volatile guint8 *p = s;
-
- memset(s, '\0', n);
- while (n-- > 0)
- *(p++) = '\0';
- }
-#endif
-}
-
-void
-nm_free_secret(char *secret)
-{
- gsize len;
-
- if (!secret)
- return;
-
-#if GLIB_CHECK_VERSION(2, 44, 0)
- /* Here we mix malloc() and g_malloc() API. Usually we avoid this,
- * however since glib 2.44.0 we are in fact guaranteed that g_malloc()/g_free()
- * just wraps malloc()/free(), so this is actually fine.
- *
- * See https://gitlab.gnome.org/GNOME/glib/commit/3be6ed60aa58095691bd697344765e715a327fc1
- */
- len = malloc_usable_size(secret);
-#else
- len = strlen(secret);
-#endif
-
- nm_explicit_bzero(secret, len);
- g_free(secret);
-}
-
-/*****************************************************************************/
-
-char *
-nm_secret_strchomp(char *secret)
-{
- gsize len;
-
- g_return_val_if_fail(secret, NULL);
-
- /* it's actually identical to g_strchomp(). However,
- * the glib function does not document, that it clears the
- * memory. For @secret, we don't only want to truncate trailing
- * spaces, we want to overwrite them with NUL. */
-
- len = strlen(secret);
- while (len--) {
- if (g_ascii_isspace((guchar) secret[len]))
- secret[len] = '\0';
- else
- break;
- }
-
- return secret;
-}
-
-/*****************************************************************************/
-
-GBytes *
-nm_secret_copy_to_gbytes(gconstpointer mem, gsize mem_len)
-{
- NMSecretBuf *b;
-
- if (mem_len == 0)
- return g_bytes_new_static("", 0);
-
- nm_assert(mem);
-
- /* NUL terminate the buffer.
- *
- * The entire buffer is already malloc'ed and likely has some room for padding.
- * Thus, in many situations, this additional byte will cause no overhead in
- * practice.
- *
- * Even if it causes an overhead, do it just for safety. Yes, the returned
- * bytes is not a NUL terminated string and no user must rely on this. Do
- * not treat binary data as NUL terminated strings, unless you know what
- * you are doing. Anyway, defensive FTW.
- */
-
- b = nm_secret_buf_new(mem_len + 1);
- memcpy(b->bin, mem, mem_len);
- b->bin[mem_len] = 0;
- return nm_secret_buf_to_gbytes_take(b, mem_len);
-}
-
-/*****************************************************************************/
-
-NMSecretBuf *
-nm_secret_buf_new(gsize len)
-{
- NMSecretBuf *secret;
-
- nm_assert(len > 0);
-
- secret = g_malloc(sizeof(NMSecretBuf) + len);
- *((gsize *) &(secret->len)) = len;
- return secret;
-}
-
-static void
-_secret_buf_free(gpointer user_data)
-{
- NMSecretBuf *secret = user_data;
-
- nm_assert(secret);
- nm_assert(secret->len > 0);
-
- nm_explicit_bzero(secret->bin, secret->len);
- g_free(user_data);
-}
-
-GBytes *
-nm_secret_buf_to_gbytes_take(NMSecretBuf *secret, gssize actual_len)
-{
- nm_assert(secret);
- nm_assert(secret->len > 0);
- nm_assert(actual_len == -1 || (actual_len >= 0 && actual_len <= secret->len));
- return g_bytes_new_with_free_func(secret->bin,
- actual_len >= 0 ? (gsize) actual_len : secret->len,
- _secret_buf_free,
- secret);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_utils_memeqzero_secret:
- * @data: the data pointer to check (may be %NULL if @length is zero).
- * @length: the number of bytes to check.
- *
- * Checks that all bytes are zero. This always takes the same amount
- * of time to prevent timing attacks.
- *
- * Returns: whether all bytes are zero.
- */
-gboolean
-nm_utils_memeqzero_secret(gconstpointer data, gsize length)
-{
- const guint8 *const key = data;
- volatile guint8 acc = 0;
- gsize i;
-
- for (i = 0; i < length; i++) {
- acc |= key[i];
- asm volatile("" : "=r"(acc) : "0"(acc));
- }
- return 1 & ((acc - 1) >> 8);
-}
diff --git a/shared/nm-glib-aux/nm-secret-utils.h b/shared/nm-glib-aux/nm-secret-utils.h
deleted file mode 100644
index ac27963571..0000000000
--- a/shared/nm-glib-aux/nm-secret-utils.h
+++ /dev/null
@@ -1,273 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_SECRET_UTILS_H__
-#define __NM_SECRET_UTILS_H__
-
-#include "nm-macros-internal.h"
-
-/*****************************************************************************/
-
-void nm_explicit_bzero(void *s, gsize n);
-
-/*****************************************************************************/
-
-char *nm_secret_strchomp(char *secret);
-
-/*****************************************************************************/
-
-void nm_free_secret(char *secret);
-
-NM_AUTO_DEFINE_FCN0(char *, _nm_auto_free_secret, nm_free_secret);
-/**
- * nm_auto_free_secret:
- *
- * Call g_free() on a variable location when it goes out of scope.
- * Also, previously, calls memset(loc, 0, strlen(loc)) to clear out
- * the secret.
- */
-#define nm_auto_free_secret nm_auto(_nm_auto_free_secret)
-
-/*****************************************************************************/
-
-GBytes *nm_secret_copy_to_gbytes(gconstpointer mem, gsize mem_len);
-
-/*****************************************************************************/
-
-/* NMSecretPtr is a pair of malloc'ed data pointer and the length of the
- * data. The purpose is to use it in combination with nm_auto_clear_secret_ptr
- * which ensures that the data pointer (with all len bytes) is cleared upon
- * cleanup. */
-typedef struct {
- gsize len;
-
- /* the data pointer. This pointer must be allocated with malloc (at least
- * when used with nm_secret_ptr_clear()). */
- union {
- char * str;
- void * ptr;
- guint8 *bin;
- };
-} NMSecretPtr;
-
-static inline void
-nm_secret_ptr_bzero(NMSecretPtr *secret)
-{
- if (secret) {
- if (secret->len > 0) {
- if (secret->ptr)
- nm_explicit_bzero(secret->ptr, secret->len);
- }
- }
-}
-
-#define nm_auto_bzero_secret_ptr nm_auto(nm_secret_ptr_bzero)
-
-static inline void
-nm_secret_ptr_clear(NMSecretPtr *secret)
-{
- if (secret) {
- if (secret->len > 0) {
- if (secret->ptr)
- nm_explicit_bzero(secret->ptr, secret->len);
- secret->len = 0;
- }
- nm_clear_g_free(&secret->ptr);
- }
-}
-
-#define nm_auto_clear_secret_ptr nm_auto(nm_secret_ptr_clear)
-
-#define NM_SECRET_PTR_INIT() \
- ((const NMSecretPtr){ \
- .len = 0, \
- .ptr = NULL, \
- })
-
-#define NM_SECRET_PTR_STATIC(_len) \
- ((const NMSecretPtr){ \
- .len = _len, \
- .ptr = ((guint8[_len]){}), \
- })
-
-#define NM_SECRET_PTR_ARRAY(_arr) \
- ((const NMSecretPtr){ \
- .len = G_N_ELEMENTS(_arr) * sizeof((_arr)[0]), \
- .ptr = &((_arr)[0]), \
- })
-
-static inline void
-nm_secret_ptr_clear_static(const NMSecretPtr *secret)
-{
- if (secret) {
- if (secret->len > 0) {
- nm_assert(secret->ptr);
- nm_explicit_bzero(secret->ptr, secret->len);
- }
- }
-}
-
-#define nm_auto_clear_static_secret_ptr nm_auto(nm_secret_ptr_clear_static)
-
-static inline void
-nm_secret_ptr_move(NMSecretPtr *dst, NMSecretPtr *src)
-{
- if (dst && dst != src) {
- *dst = *src;
- src->len = 0;
- src->ptr = NULL;
- }
-}
-
-/*****************************************************************************/
-
-typedef struct {
- const gsize len;
- union {
- char str[0];
- guint8 bin[0];
- };
-} NMSecretBuf;
-
-static inline void
-_nm_auto_free_secret_buf(NMSecretBuf **ptr)
-{
- NMSecretBuf *b = *ptr;
-
- if (b) {
- nm_assert(b->len > 0);
- nm_explicit_bzero(b->bin, b->len);
- g_free(b);
- }
-}
-#define nm_auto_free_secret_buf nm_auto(_nm_auto_free_secret_buf)
-
-NMSecretBuf *nm_secret_buf_new(gsize len);
-
-GBytes *nm_secret_buf_to_gbytes_take(NMSecretBuf *secret, gssize actual_len);
-
-/*****************************************************************************/
-
-gboolean nm_utils_memeqzero_secret(gconstpointer data, gsize length);
-
-/*****************************************************************************/
-
-/**
- * nm_secret_mem_realloc:
- * @m_old: the current buffer of length @cur_len.
- * @do_bzero_mem: if %TRUE, bzero the old buffer
- * @cur_len: the current buffer length of @m_old. It is necessary for bzero.
- * @new_len: the desired new length
- *
- * If @do_bzero_mem is false, this is like g_realloc().
- * Otherwise, this will allocate a new buffer of the desired size, copy over the
- * old data, and bzero the old buffer before freeing it. As such, it also behaves
- * similar to g_realloc(), with the overhead of nm_explicit_bzero() and using
- * malloc/free instead of realloc().
- *
- * Returns: the new allocated buffer. Think of it behaving like g_realloc().
- */
-static inline gpointer
-nm_secret_mem_realloc(gpointer m_old, gboolean do_bzero_mem, gsize cur_len, gsize new_len)
-{
- gpointer m_new;
-
- nm_assert(m_old || cur_len == 0);
-
- if (do_bzero_mem && G_LIKELY(cur_len > 0)) {
- m_new = g_malloc(new_len);
- if (G_LIKELY(new_len > 0))
- memcpy(m_new, m_old, NM_MIN(cur_len, new_len));
- nm_explicit_bzero(m_old, cur_len);
- g_free(m_old);
- } else
- m_new = g_realloc(m_old, new_len);
-
- return m_new;
-}
-
-/**
- * nm_secret_mem_try_realloc:
- * @m_old: the current buffer of length @cur_len.
- * @do_bzero_mem: if %TRUE, bzero the old buffer
- * @cur_len: the current buffer length of @m_old. It is necessary for bzero.
- * @new_len: the desired new length
- *
- * If @do_bzero_mem is false, this is like g_try_realloc().
- * Otherwise, this will try to allocate a new buffer of the desired size, copy over the
- * old data, and bzero the old buffer before freeing it. As such, it also behaves
- * similar to g_try_realloc(), with the overhead of nm_explicit_bzero() and using
- * malloc/free instead of realloc().
- *
- * Returns: the new allocated buffer or NULL. Think of it behaving like g_try_realloc().
- */
-static inline gpointer
-nm_secret_mem_try_realloc(gpointer m_old, gboolean do_bzero_mem, gsize cur_len, gsize new_len)
-{
- gpointer m_new;
-
- nm_assert(m_old || cur_len == 0);
-
- if (do_bzero_mem && G_LIKELY(cur_len > 0)) {
- if (G_UNLIKELY(new_len == 0))
- m_new = NULL;
- else {
- m_new = g_try_malloc(new_len);
- if (!m_new)
- return NULL;
- memcpy(m_new, m_old, NM_MIN(cur_len, new_len));
- }
- nm_explicit_bzero(m_old, cur_len);
- g_free(m_old);
- return m_new;
- }
-
- return g_try_realloc(m_old, new_len);
-}
-
-/**
- * nm_secret_mem_try_realloc_take:
- * @m_old: the current buffer of length @cur_len.
- * @do_bzero_mem: if %TRUE, bzero the old buffer
- * @cur_len: the current buffer length of @m_old. It is necessary for bzero.
- * @new_len: the desired new length
- *
- * This works like nm_secret_mem_try_realloc(), which is not unlike g_try_realloc().
- * The difference is, if we fail to allocate a new buffer, then @m_old will be
- * freed (and possibly cleared). This differs from plain realloc(), where the
- * old buffer is unchanged if the operation fails.
- *
- * Returns: the new allocated buffer or NULL. Think of it behaving like g_try_realloc()
- * but it will always free @m_old.
- */
-static inline gpointer
-nm_secret_mem_try_realloc_take(gpointer m_old, gboolean do_bzero_mem, gsize cur_len, gsize new_len)
-{
- gpointer m_new;
-
- nm_assert(m_old || cur_len == 0);
-
- if (do_bzero_mem && G_LIKELY(cur_len > 0)) {
- if (G_UNLIKELY(new_len == 0))
- m_new = NULL;
- else {
- m_new = g_try_malloc(new_len);
- if (G_LIKELY(m_new))
- memcpy(m_new, m_old, NM_MIN(cur_len, new_len));
- }
- nm_explicit_bzero(m_old, cur_len);
- g_free(m_old);
- return m_new;
- }
-
- m_new = g_try_realloc(m_old, new_len);
- if (G_UNLIKELY(!m_new && new_len > 0))
- g_free(m_old);
- return m_new;
-}
-
-/*****************************************************************************/
-
-#endif /* __NM_SECRET_UTILS_H__ */
diff --git a/shared/nm-glib-aux/nm-shared-utils.c b/shared/nm-glib-aux/nm-shared-utils.c
deleted file mode 100644
index 3215a33b5b..0000000000
--- a/shared/nm-glib-aux/nm-shared-utils.c
+++ /dev/null
@@ -1,5710 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2016 Red Hat, Inc.
- */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-shared-utils.h"
-
-#include <pwd.h>
-#include <arpa/inet.h>
-#include <poll.h>
-#include <fcntl.h>
-#include <sys/syscall.h>
-#include <glib-unix.h>
-#include <net/if.h>
-#include <net/ethernet.h>
-
-#include "nm-errno.h"
-#include "nm-str-buf.h"
-
-G_STATIC_ASSERT(sizeof(NMEtherAddr) == 6);
-G_STATIC_ASSERT(_nm_alignof(NMEtherAddr) == 1);
-
-G_STATIC_ASSERT(sizeof(NMUtilsNamedEntry) == sizeof(const char *));
-G_STATIC_ASSERT(G_STRUCT_OFFSET(NMUtilsNamedValue, value_ptr) == sizeof(const char *));
-
-/*****************************************************************************/
-
-const char _nm_hexchar_table_lower[16] = "0123456789abcdef";
-const char _nm_hexchar_table_upper[16] = "0123456789ABCDEF";
-
-const void *const _NM_PTRARRAY_EMPTY[1] = {NULL};
-
-/*****************************************************************************/
-
-const NMIPAddr nm_ip_addr_zero = {};
-
-/* this initializes a struct in_addr/in6_addr and allows for untrusted
- * arguments (like unsuitable @addr_family or @src_len). It's almost safe
- * in the sense that it verifies input arguments strictly. Also, it
- * uses memcpy() to access @src, so alignment is not an issue.
- *
- * Only potential pitfalls:
- *
- * - it allows for @addr_family to be AF_UNSPEC. If that is the case (and the
- * caller allows for that), the caller MUST provide @out_addr_family.
- * - when setting @dst to an IPv4 address, the trailing bytes are not touched.
- * Meaning, if @dst is an NMIPAddr union, only the first bytes will be set.
- * If that matter to you, clear @dst before. */
-gboolean
-nm_ip_addr_set_from_untrusted(int addr_family,
- gpointer dst,
- gconstpointer src,
- gsize src_len,
- int * out_addr_family)
-{
- nm_assert(dst);
-
- switch (addr_family) {
- case AF_UNSPEC:
- if (!out_addr_family) {
- /* when the callers allow undefined @addr_family, they must provide
- * an @out_addr_family argument. */
- nm_assert_not_reached();
- return FALSE;
- }
- switch (src_len) {
- case sizeof(struct in_addr):
- addr_family = AF_INET;
- break;
- case sizeof(struct in6_addr):
- addr_family = AF_INET6;
- break;
- default:
- return FALSE;
- }
- break;
- case AF_INET:
- if (src_len != sizeof(struct in_addr))
- return FALSE;
- break;
- case AF_INET6:
- if (src_len != sizeof(struct in6_addr))
- return FALSE;
- break;
- default:
- /* when the callers allow undefined @addr_family, they must provide
- * an @out_addr_family argument. */
- nm_assert(out_addr_family);
- return FALSE;
- }
-
- nm_assert(src);
-
- memcpy(dst, src, src_len);
- NM_SET_OUT(out_addr_family, addr_family);
- return TRUE;
-}
-
-/*****************************************************************************/
-
-G_STATIC_ASSERT(ETH_ALEN == sizeof(struct ether_addr));
-G_STATIC_ASSERT(ETH_ALEN == 6);
-
-/*****************************************************************************/
-
-pid_t
-nm_utils_gettid(void)
-{
- return (pid_t) syscall(SYS_gettid);
-}
-
-/* Used for asserting that this function is called on the main-thread.
- * The main-thread is determined by remembering the thread-id
- * of when the function was called the first time.
- *
- * When forking, the thread-id is again reset upon first call. */
-gboolean
-_nm_assert_on_main_thread(void)
-{
- G_LOCK_DEFINE_STATIC(lock);
- static pid_t seen_tid;
- static pid_t seen_pid;
- pid_t tid;
- pid_t pid;
- gboolean success = FALSE;
-
- tid = nm_utils_gettid();
- nm_assert(tid != 0);
-
- G_LOCK(lock);
-
- if (G_LIKELY(tid == seen_tid)) {
- /* we don't care about false positives (when the process forked, and the thread-id
- * is accidentally re-used) . It's for assertions only. */
- success = TRUE;
- } else {
- pid = getpid();
- nm_assert(pid != 0);
-
- if (seen_tid == 0 || seen_pid != pid) {
- /* either this is the first time we call the function, or the process
- * forked. In both cases, remember the thread-id. */
- seen_tid = tid;
- seen_pid = pid;
- success = TRUE;
- }
- }
-
- G_UNLOCK(lock);
-
- return success;
-}
-
-/*****************************************************************************/
-
-void
-nm_utils_strbuf_append_c(char **buf, gsize *len, char c)
-{
- switch (*len) {
- case 0:
- return;
- case 1:
- (*buf)[0] = '\0';
- *len = 0;
- (*buf)++;
- return;
- default:
- (*buf)[0] = c;
- (*buf)[1] = '\0';
- (*len)--;
- (*buf)++;
- return;
- }
-}
-
-void
-nm_utils_strbuf_append_bin(char **buf, gsize *len, gconstpointer str, gsize str_len)
-{
- switch (*len) {
- case 0:
- return;
- case 1:
- if (str_len == 0) {
- (*buf)[0] = '\0';
- return;
- }
- (*buf)[0] = '\0';
- *len = 0;
- (*buf)++;
- return;
- default:
- if (str_len == 0) {
- (*buf)[0] = '\0';
- return;
- }
- if (str_len >= *len) {
- memcpy(*buf, str, *len - 1);
- (*buf)[*len - 1] = '\0';
- *buf = &(*buf)[*len];
- *len = 0;
- } else {
- memcpy(*buf, str, str_len);
- *buf = &(*buf)[str_len];
- (*buf)[0] = '\0';
- *len -= str_len;
- }
- return;
- }
-}
-
-void
-nm_utils_strbuf_append_str(char **buf, gsize *len, const char *str)
-{
- gsize src_len;
-
- switch (*len) {
- case 0:
- return;
- case 1:
- if (!str || !*str) {
- (*buf)[0] = '\0';
- return;
- }
- (*buf)[0] = '\0';
- *len = 0;
- (*buf)++;
- return;
- default:
- if (!str || !*str) {
- (*buf)[0] = '\0';
- return;
- }
- src_len = g_strlcpy(*buf, str, *len);
- if (src_len >= *len) {
- *buf = &(*buf)[*len];
- *len = 0;
- } else {
- *buf = &(*buf)[src_len];
- *len -= src_len;
- }
- return;
- }
-}
-
-void
-nm_utils_strbuf_append(char **buf, gsize *len, const char *format, ...)
-{
- char * p = *buf;
- va_list args;
- int retval;
-
- if (*len == 0)
- return;
-
- va_start(args, format);
- retval = g_vsnprintf(p, *len, format, args);
- va_end(args);
-
- if ((gsize) retval >= *len) {
- *buf = &p[*len];
- *len = 0;
- } else {
- *buf = &p[retval];
- *len -= retval;
- }
-}
-
-/**
- * nm_utils_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
- * 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);
- *
- * is almost the same as
- *
- * nm_utils_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
- * length to zero.
- *
- * In general, the behavior is:
- *
- * - if *len is zero, do nothing
- * - if the buffer contains a NUL byte within the first *len characters,
- * the buffer is pointed to the NUL byte and len is adjusted. In this
- * case, the remaining *len is always >= 1.
- * In particular, that is also the case if the NUL byte is at the very last
- * position ((*buf)[*len -1]). That happens, when the previous operation
- * either fit the string exactly into the buffer or the string was truncated
- * by g_snprintf(). The difference cannot be determined.
- * - if the buffer contains no NUL bytes within the first *len characters,
- * write NUL at the last position, set *len to zero, and point *buf past
- * the NUL byte. This would happen with
- *
- * strncpy (buf, long_str, len);
- * nm_utils_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.
- */
-void
-nm_utils_strbuf_seek_end(char **buf, gsize *len)
-{
- gsize l;
- char *end;
-
- nm_assert(len);
- nm_assert(buf && *buf);
-
- if (*len <= 1) {
- if (*len == 1 && (*buf)[0])
- goto truncate;
- return;
- }
-
- end = memchr(*buf, 0, *len);
- if (end) {
- l = end - *buf;
- nm_assert(l < *len);
-
- *buf = end;
- *len -= l;
- return;
- }
-
-truncate:
- /* hm, no NUL character within len bytes.
- * Just NUL terminate the array and consume them
- * all. */
- *buf += *len;
- (*buf)[-1] = '\0';
- *len = 0;
- return;
-}
-
-/*****************************************************************************/
-
-GBytes *
-nm_gbytes_get_empty(void)
-{
- static GBytes *bytes = NULL;
- GBytes * b;
-
-again:
- b = g_atomic_pointer_get(&bytes);
- if (G_UNLIKELY(!b)) {
- b = g_bytes_new_static("", 0);
- if (!g_atomic_pointer_compare_and_exchange(&bytes, NULL, b)) {
- g_bytes_unref(b);
- goto again;
- }
- }
- return b;
-}
-
-GBytes *
-nm_g_bytes_new_from_str(const char *str)
-{
- gsize l;
-
- if (!str)
- return NULL;
-
- /* the returned array is guaranteed to have a trailing '\0'
- * character *after* the length. */
-
- l = strlen(str);
- return g_bytes_new_take(nm_memdup(str, l + 1u), l);
-}
-
-/**
- * nm_utils_gbytes_equals:
- * @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
- * @mem_len: the length of the data pointer
- *
- * Returns: %TRUE if @bytes contains the same data as @mem_data. As a
- * 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)
-{
- gconstpointer p;
- gsize l;
-
- if (!bytes) {
- /* as a special case, let %NULL GBytes compare identical
- * to an empty array. */
- return (mem_len == 0);
- }
-
- p = g_bytes_get_data(bytes, &l);
- return l == mem_len
- && (mem_len == 0 /* allow @mem_data to be %NULL */
- || memcmp(p, mem_data, mem_len) == 0);
-}
-
-GVariant *
-nm_utils_gbytes_to_variant_ay(GBytes *bytes)
-{
- const guint8 *p;
- gsize l;
-
- if (!bytes) {
- /* for convenience, accept NULL to return an empty variant */
- return g_variant_new_array(G_VARIANT_TYPE_BYTE, NULL, 0);
- }
-
- p = g_bytes_get_data(bytes, &l);
- return g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, p, l, 1);
-}
-
-/*****************************************************************************/
-
-#define _variant_singleton_get(create_variant) \
- ({ \
- static GVariant *_singleton = NULL; \
- GVariant * _v; \
- \
-again: \
- _v = g_atomic_pointer_get(&_singleton); \
- if (G_UNLIKELY(!_v)) { \
- _v = (create_variant); \
- nm_assert(_v); \
- nm_assert(g_variant_is_floating(_v)); \
- g_variant_ref_sink(_v); \
- if (!g_atomic_pointer_compare_and_exchange(&_singleton, NULL, _v)) { \
- g_variant_unref(_v); \
- goto again; \
- } \
- } \
- _v; \
- })
-
-GVariant *
-nm_g_variant_singleton_u_0(void)
-{
- return _variant_singleton_get(g_variant_new_uint32(0));
-}
-
-/*****************************************************************************/
-
-GHashTable *
-nm_utils_strdict_clone(GHashTable *src)
-{
- GHashTable * dst;
- GHashTableIter iter;
- const char * key;
- const char * val;
-
- if (!src)
- return NULL;
-
- dst = g_hash_table_new_full(nm_str_hash, g_str_equal, g_free, g_free);
- g_hash_table_iter_init(&iter, src);
- while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &val))
- g_hash_table_insert(dst, g_strdup(key), g_strdup(val));
- return dst;
-}
-
-/* Convert a hash table with "char *" keys and values to an "a{ss}" GVariant.
- * The keys will be sorted asciibetically.
- * Returns a floating reference.
- */
-GVariant *
-nm_utils_strdict_to_variant_ass(GHashTable *strdict)
-{
- gs_free NMUtilsNamedValue *values_free = NULL;
- NMUtilsNamedValue values_prepared[20];
- const NMUtilsNamedValue * values;
- GVariantBuilder builder;
- guint i;
- guint n;
-
- values = nm_utils_named_values_from_strdict(strdict, &n, values_prepared, &values_free);
-
- g_variant_builder_init(&builder, G_VARIANT_TYPE("a{ss}"));
- for (i = 0; i < n; i++) {
- g_variant_builder_add(&builder, "{ss}", values[i].name, values[i].value_str);
- }
- return g_variant_builder_end(&builder);
-}
-
-/*****************************************************************************/
-
-GVariant *
-nm_utils_strdict_to_variant_asv(GHashTable *strdict)
-{
- gs_free NMUtilsNamedValue *values_free = NULL;
- NMUtilsNamedValue values_prepared[20];
- const NMUtilsNamedValue * values;
- GVariantBuilder builder;
- guint i;
- guint n;
-
- values = nm_utils_named_values_from_strdict(strdict, &n, values_prepared, &values_free);
-
- g_variant_builder_init(&builder, G_VARIANT_TYPE("a{sv}"));
- for (i = 0; i < n; i++) {
- g_variant_builder_add(&builder,
- "{sv}",
- values[i].name,
- g_variant_new_string(values[i].value_str));
- }
- return g_variant_builder_end(&builder);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_strquote:
- * @buf: the output buffer of where to write the quoted @str argument.
- * @buf_len: the size of @buf.
- * @str: (allow-none): the string to quote.
- *
- * Writes @str to @buf with quoting. The resulting buffer
- * is always NUL terminated, unless @buf_len is zero.
- * If @str is %NULL, it writes "(null)".
- *
- * If @str needs to be truncated, the closing quote is '^' instead
- * of '"'.
- *
- * This is similar to nm_strquote_a(), which however uses alloca()
- * to allocate a new buffer. Also, here @buf_len is the size of @buf,
- * while nm_strquote_a() has the number of characters to print. The latter
- * doesn't include the quoting.
- *
- * Returns: the input buffer with the quoted string.
- */
-const char *
-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)");
- goto out;
- }
-
- if (G_UNLIKELY(buf_len <= 2)) {
- switch (buf_len) {
- case 2:
- *(buf++) = '^';
- /* fall-through */
- case 1:
- *(buf++) = '\0';
- break;
- }
- goto out;
- }
-
- *(buf++) = '"';
- buf_len--;
-
- nm_utils_strbuf_append_str(&buf, &buf_len, str);
-
- /* if the string was too long we indicate truncation with a
- * '^' instead of a closing quote. */
- if (G_UNLIKELY(buf_len <= 1)) {
- switch (buf_len) {
- case 1:
- buf[-1] = '^';
- break;
- case 0:
- buf[-2] = '^';
- break;
- default:
- nm_assert_not_reached();
- break;
- }
- } else {
- nm_assert(buf_len >= 2);
- *(buf++) = '"';
- *(buf++) = '\0';
- }
-
-out:
- return buf0;
-}
-
-/*****************************************************************************/
-
-char _nm_utils_to_string_buffer[];
-
-void
-nm_utils_to_string_buffer_init(char **buf, gsize *len)
-{
- if (!*buf) {
- *buf = _nm_utils_to_string_buffer;
- *len = sizeof(_nm_utils_to_string_buffer);
- }
-}
-
-gboolean
-nm_utils_to_string_buffer_init_null(gconstpointer obj, char **buf, gsize *len)
-{
- nm_utils_to_string_buffer_init(buf, len);
- if (!obj) {
- g_strlcpy(*buf, "(null)", *len);
- return FALSE;
- }
- return TRUE;
-}
-
-/*****************************************************************************/
-
-const char *
-nm_utils_flags2str(const NMUtilsFlags2StrDesc *descs,
- gsize n_descs,
- unsigned flags,
- char * buf,
- gsize len)
-{
- gsize i;
- char *p;
-
-#if NM_MORE_ASSERTS > 10
- nm_assert(descs);
- nm_assert(n_descs > 0);
- for (i = 0; i < n_descs; i++) {
- gsize j;
-
- nm_assert(descs[i].name && descs[i].name[0]);
- for (j = 0; j < i; j++)
- nm_assert(descs[j].flag != descs[i].flag);
- }
-#endif
-
- nm_utils_to_string_buffer_init(&buf, &len);
-
- if (!len)
- return buf;
-
- buf[0] = '\0';
- p = buf;
- if (!flags) {
- for (i = 0; i < n_descs; i++) {
- if (!descs[i].flag) {
- nm_utils_strbuf_append_str(&p, &len, descs[i].name);
- break;
- }
- }
- return buf;
- }
-
- for (i = 0; flags && i < n_descs; i++) {
- if (descs[i].flag && NM_FLAGS_ALL(flags, descs[i].flag)) {
- 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);
- }
- }
- if (flags) {
- if (buf[0] != '\0')
- nm_utils_strbuf_append_c(&p, &len, ',');
- nm_utils_strbuf_append(&p, &len, "0x%x", flags);
- }
- return buf;
-};
-
-/*****************************************************************************/
-
-/**
- * _nm_utils_ip4_prefix_to_netmask:
- * @prefix: a CIDR prefix
- *
- * Returns: the netmask represented by the prefix, in network byte order
- **/
-guint32
-_nm_utils_ip4_prefix_to_netmask(guint32 prefix)
-{
- return prefix < 32 ? ~htonl(0xFFFFFFFFu >> prefix) : 0xFFFFFFFFu;
-}
-
-gconstpointer
-nm_utils_ipx_address_clear_host_address(int family, gpointer dst, gconstpointer src, guint8 plen)
-{
- g_return_val_if_fail(dst, NULL);
-
- switch (family) {
- case AF_INET:
- g_return_val_if_fail(plen <= 32, NULL);
-
- if (!src) {
- /* allow "self-assignment", by specifying %NULL as source. */
- src = dst;
- }
-
- *((guint32 *) dst) = nm_utils_ip4_address_clear_host_address(*((guint32 *) src), plen);
- break;
- case AF_INET6:
- nm_utils_ip6_address_clear_host_address(dst, src, plen);
- break;
- default:
- g_return_val_if_reached(NULL);
- }
- return dst;
-}
-
-/* nm_utils_ip4_address_clear_host_address:
- * @addr: source ip6 address
- * @plen: prefix length of network
- *
- * returns: the input address, with the host address set to 0.
- */
-in_addr_t
-nm_utils_ip4_address_clear_host_address(in_addr_t addr, guint8 plen)
-{
- return addr & _nm_utils_ip4_prefix_to_netmask(plen);
-}
-
-/* nm_utils_ip6_address_clear_host_address:
- * @dst: destination output buffer, will contain the network part of the @src address
- * @src: source ip6 address
- * @plen: prefix length of network
- *
- * Note: this function is self assignment safe, to update @src inplace, set both
- * @dst and @src to the same destination or set @src NULL.
- */
-const struct in6_addr *
-nm_utils_ip6_address_clear_host_address(struct in6_addr * dst,
- const struct in6_addr *src,
- guint8 plen)
-{
- g_return_val_if_fail(plen <= 128, NULL);
- g_return_val_if_fail(dst, NULL);
-
- if (!src)
- src = dst;
-
- if (plen < 128) {
- guint nbytes = plen / 8;
- guint nbits = plen % 8;
-
- if (nbytes && dst != src)
- memcpy(dst, src, nbytes);
- if (nbits) {
- dst->s6_addr[nbytes] = (src->s6_addr[nbytes] & (0xFF << (8 - nbits)));
- nbytes++;
- }
- if (nbytes <= 15)
- memset(&dst->s6_addr[nbytes], 0, 16 - nbytes);
- } else if (src != dst)
- *dst = *src;
-
- return dst;
-}
-
-int
-nm_utils_ip6_address_same_prefix_cmp(const struct in6_addr *addr_a,
- const struct in6_addr *addr_b,
- guint8 plen)
-{
- int nbytes;
- guint8 va, vb, m;
-
- if (plen >= 128)
- NM_CMP_DIRECT_MEMCMP(addr_a, addr_b, sizeof(struct in6_addr));
- else {
- nbytes = plen / 8;
- if (nbytes)
- NM_CMP_DIRECT_MEMCMP(addr_a, addr_b, nbytes);
-
- plen = plen % 8;
- if (plen != 0) {
- m = ~((1 << (8 - plen)) - 1);
- va = ((((const guint8 *) addr_a))[nbytes]) & m;
- vb = ((((const guint8 *) addr_b))[nbytes]) & m;
- NM_CMP_DIRECT(va, vb);
- }
- }
- return 0;
-}
-
-/*****************************************************************************/
-
-guint32
-_nm_utils_ip4_get_default_prefix0(in_addr_t ip)
-{
- /* The function is originally from ipcalc.c of Red Hat's initscripts. */
- switch (ntohl(ip) >> 24) {
- case 0 ... 127:
- return 8; /* Class A */
- case 128 ... 191:
- return 16; /* Class B */
- case 192 ... 223:
- return 24; /* Class C */
- }
- return 0;
-}
-
-guint32
-_nm_utils_ip4_get_default_prefix(in_addr_t ip)
-{
- return _nm_utils_ip4_get_default_prefix0(ip) ?: 24;
-}
-
-gboolean
-nm_utils_ip_is_site_local(int addr_family, const void *address)
-{
- in_addr_t addr4;
-
- switch (addr_family) {
- case AF_INET:
- /* RFC1918 private addresses
- * 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16 */
- addr4 = ntohl(*((const in_addr_t *) address));
- return (addr4 & 0xff000000) == 0x0a000000 || (addr4 & 0xfff00000) == 0xac100000
- || (addr4 & 0xffff0000) == 0xc0a80000;
- case AF_INET6:
- return IN6_IS_ADDR_SITELOCAL(address);
- default:
- g_return_val_if_reached(FALSE);
- }
-}
-
-/*****************************************************************************/
-
-static gboolean
-_parse_legacy_addr4(const char *text, in_addr_t *out_addr, GError **error)
-{
- gs_free char * s_free = NULL;
- struct in_addr a1;
- guint8 bin[sizeof(a1)];
- char * s;
- int i;
-
- if (inet_aton(text, &a1) != 1) {
- g_set_error_literal(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_INVALID_ARGUMENT,
- "address invalid according to inet_aton()");
- return FALSE;
- }
-
- /* OK, inet_aton() accepted the format. That's good, because we want
- * to accept IPv4 addresses in octal format, like 255.255.000.000.
- * That's what "legacy" means here. inet_pton() doesn't accept those.
- *
- * But inet_aton() also ignores trailing garbage and formats with fewer than
- * 4 digits. That is just too crazy and we don't do that. Perform additional checks
- * and reject some forms that inet_aton() accepted.
- *
- * Note that we still should (of course) accept everything that inet_pton()
- * accepts. However this code never gets called if inet_pton() succeeds
- * (see below, aside the assertion code). */
-
- if (NM_STRCHAR_ANY(text, ch, (!(ch >= '0' && ch <= '9') && !NM_IN_SET(ch, '.', 'x')))) {
- /* We only accepts '.', digits, and 'x' for "0x". */
- g_set_error_literal(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_INVALID_ARGUMENT,
- "contains an invalid character");
- return FALSE;
- }
-
- s = nm_memdup_maybe_a(300, text, strlen(text) + 1, &s_free);
-
- for (i = 0; i < G_N_ELEMENTS(bin); i++) {
- char * current_token = s;
- gint32 v;
-
- s = strchr(s, '.');
- if (s) {
- s[0] = '\0';
- s++;
- }
-
- if ((i == G_N_ELEMENTS(bin) - 1) != (s == NULL)) {
- /* Exactly for the last digit, we expect to have no more following token.
- * But this isn't the case. Abort. */
- g_set_error(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_INVALID_ARGUMENT,
- "wrong number of tokens (index %d, token '%s')",
- i,
- s);
- return FALSE;
- }
-
- v = _nm_utils_ascii_str_to_int64(current_token, 0, 0, 0xFF, -1);
- if (v == -1) {
- int errsv = errno;
-
- /* we do accept octal and hex (even with leading "0x"). But something
- * about this token is wrong. */
- g_set_error(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_INVALID_ARGUMENT,
- "invalid token '%s': %s (%d)",
- current_token,
- nm_strerror_native(errsv),
- errsv);
- return FALSE;
- }
-
- bin[i] = v;
- }
-
- if (memcmp(bin, &a1, sizeof(bin)) != 0) {
- /* our parsing did not agree with what inet_aton() gave. Something
- * is wrong. Abort. */
- g_set_error(
- error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_INVALID_ARGUMENT,
- "inet_aton() result 0x%08x differs from computed value 0x%02hhx%02hhx%02hhx%02hhx",
- a1.s_addr,
- bin[0],
- bin[1],
- bin[2],
- bin[3]);
- return FALSE;
- }
-
- *out_addr = a1.s_addr;
- return TRUE;
-}
-
-gboolean
-nm_utils_parse_inaddr_bin_full(int addr_family,
- gboolean accept_legacy,
- const char *text,
- int * out_addr_family,
- gpointer out_addr)
-{
- NMIPAddr addrbin;
-
- g_return_val_if_fail(text, FALSE);
-
- if (addr_family == AF_UNSPEC) {
- g_return_val_if_fail(!out_addr || out_addr_family, FALSE);
- addr_family = strchr(text, ':') ? AF_INET6 : AF_INET;
- } else
- g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), FALSE);
-
- if (inet_pton(addr_family, text, &addrbin) != 1) {
- if (accept_legacy && addr_family == AF_INET
- && _parse_legacy_addr4(text, &addrbin.addr4, NULL)) {
- /* The address is in some legacy format which inet_aton() accepts, but not inet_pton().
- * Most likely octal digits (leading zeros). We accept the address. */
- } else
- return FALSE;
- }
-
-#if NM_MORE_ASSERTS > 10
- if (addr_family == AF_INET) {
- gs_free_error GError *error = NULL;
- in_addr_t a;
-
- /* The legacy parser should accept everything that inet_pton() accepts too. Meaning,
- * it should strictly parse *more* formats. And of course, parse it the same way. */
- if (!_parse_legacy_addr4(text, &a, &error)) {
- char buf[INET_ADDRSTRLEN];
-
- g_error("unexpected assertion failure: could parse \"%s\" as %s, but not accepted by "
- "legacy parser: %s",
- text,
- _nm_utils_inet4_ntop(addrbin.addr4, buf),
- error->message);
- }
- nm_assert(addrbin.addr4 == a);
- }
-#endif
-
- NM_SET_OUT(out_addr_family, addr_family);
- if (out_addr)
- nm_ip_addr_set(addr_family, out_addr, &addrbin);
- return TRUE;
-}
-
-gboolean
-nm_utils_parse_inaddr(int addr_family, const char *text, char **out_addr)
-{
- NMIPAddr addrbin;
- char addrstr_buf[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
-
- g_return_val_if_fail(text, FALSE);
-
- if (addr_family == AF_UNSPEC)
- addr_family = strchr(text, ':') ? AF_INET6 : AF_INET;
- else
- g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), FALSE);
-
- if (inet_pton(addr_family, text, &addrbin) != 1)
- return FALSE;
-
- NM_SET_OUT(out_addr,
- g_strdup(inet_ntop(addr_family, &addrbin, addrstr_buf, sizeof(addrstr_buf))));
- return TRUE;
-}
-
-gboolean
-nm_utils_parse_inaddr_prefix_bin(int addr_family,
- const char *text,
- int * out_addr_family,
- gpointer out_addr,
- int * out_prefix)
-{
- gs_free char *addrstr_free = NULL;
- int prefix = -1;
- const char * slash;
- const char * addrstr;
- NMIPAddr addrbin;
-
- g_return_val_if_fail(text, FALSE);
-
- if (addr_family == AF_UNSPEC) {
- g_return_val_if_fail(!out_addr || out_addr_family, FALSE);
- addr_family = strchr(text, ':') ? AF_INET6 : AF_INET;
- } else
- g_return_val_if_fail(NM_IN_SET(addr_family, AF_INET, AF_INET6), FALSE);
-
- slash = strchr(text, '/');
- if (slash)
- addrstr = nm_strndup_a(300, text, slash - text, &addrstr_free);
- else
- addrstr = text;
-
- if (inet_pton(addr_family, addrstr, &addrbin) != 1)
- return FALSE;
-
- if (slash) {
- /* For IPv4, `ip addr add` supports the prefix-length as a netmask. We don't
- * do that. */
- prefix =
- _nm_utils_ascii_str_to_int64(&slash[1], 10, 0, addr_family == AF_INET ? 32 : 128, -1);
- if (prefix == -1)
- return FALSE;
- }
-
- NM_SET_OUT(out_addr_family, addr_family);
- if (out_addr)
- nm_ip_addr_set(addr_family, out_addr, &addrbin);
- NM_SET_OUT(out_prefix, prefix);
- return TRUE;
-}
-
-gboolean
-nm_utils_parse_inaddr_prefix(int addr_family, const char *text, char **out_addr, int *out_prefix)
-{
- NMIPAddr addrbin;
- char addrstr_buf[MAX(INET_ADDRSTRLEN, INET6_ADDRSTRLEN)];
-
- if (!nm_utils_parse_inaddr_prefix_bin(addr_family, text, &addr_family, &addrbin, out_prefix))
- return FALSE;
- NM_SET_OUT(out_addr,
- g_strdup(inet_ntop(addr_family, &addrbin, addrstr_buf, sizeof(addrstr_buf))));
- return TRUE;
-}
-
-gboolean
-nm_utils_parse_next_line(const char **inout_ptr,
- gsize * inout_len,
- const char **out_line,
- gsize * out_line_len)
-{
- gboolean eol_is_carriage_return;
- const char *line_start;
- gsize line_len;
-
- nm_assert(inout_ptr);
- nm_assert(inout_len);
- nm_assert(*inout_len == 0 || *inout_ptr);
- nm_assert(out_line);
- nm_assert(out_line_len);
-
- if (G_UNLIKELY(*inout_len == 0))
- return FALSE;
-
- line_start = *inout_ptr;
-
- eol_is_carriage_return = FALSE;
- for (line_len = 0;; line_len++) {
- if (line_len >= *inout_len) {
- /* if we consumed the entire line, we place the pointer at
- * one character after the end. */
- *inout_ptr = &line_start[line_len];
- *inout_len = 0;
- goto done;
- }
- switch (line_start[line_len]) {
- case '\r':
- eol_is_carriage_return = TRUE;
- /* fall-through*/
- case '\0':
- case '\n':
- *inout_ptr = &line_start[line_len + 1];
- *inout_len = *inout_len - line_len - 1u;
- if (eol_is_carriage_return && *inout_len > 0 && (*inout_ptr)[0] == '\n') {
- /* also consume "\r\n" as one. */
- (*inout_len)--;
- (*inout_ptr)++;
- }
- goto done;
- }
- }
-
-done:
- *out_line = line_start;
- *out_line_len = line_len;
- return TRUE;
-}
-
-/*****************************************************************************/
-
-gboolean
-nm_utils_ipaddr_is_valid(int addr_family, const char *str_addr)
-{
- nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6));
-
- return str_addr && nm_utils_parse_inaddr_bin(addr_family, str_addr, NULL, NULL);
-}
-
-gboolean
-nm_utils_ipaddr_is_normalized(int addr_family, const char *str_addr)
-{
- NMIPAddr addr;
- char sbuf[NM_UTILS_INET_ADDRSTRLEN];
-
- nm_assert(NM_IN_SET(addr_family, AF_UNSPEC, AF_INET, AF_INET6));
-
- if (!str_addr)
- return FALSE;
-
- if (!nm_utils_parse_inaddr_bin(addr_family, str_addr, &addr_family, &addr))
- return FALSE;
-
- nm_utils_inet_ntop(addr_family, &addr, sbuf);
- return nm_streq(sbuf, str_addr);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_g_ascii_strtoll()
- * @nptr: the string to parse
- * @endptr: the pointer on the first invalid chars
- * @base: the base.
- *
- * This wraps g_ascii_strtoll() and should in almost all cases behave identical
- * to it.
- *
- * However, it seems there are situations where g_ascii_strtoll() might set
- * errno to some unexpected value EAGAIN. Possibly this is related to creating
- * the C locale during
- *
- * #ifdef USE_XLOCALE
- * return strtoll_l (nptr, endptr, base, get_C_locale ());
- *
- * This wrapper tries to workaround that condition.
- */
-gint64
-nm_g_ascii_strtoll(const char *nptr, char **endptr, guint base)
-{
- int try_count = 2;
- gint64 v;
- const int errsv_orig = errno;
- int errsv;
-
- nm_assert(nptr);
- nm_assert(base == 0u || (base >= 2u && base <= 36u));
-
-again:
- errno = 0;
- v = g_ascii_strtoll(nptr, endptr, base);
- errsv = errno;
-
- if (errsv == 0) {
- if (errsv_orig != 0)
- errno = errsv_orig;
- return v;
- }
-
- if (errsv == ERANGE && NM_IN_SET(v, G_MININT64, G_MAXINT64))
- return v;
-
- if (errsv == EINVAL && v == 0 && nptr && nptr[0] == '\0')
- return v;
-
- if (try_count-- > 0)
- goto again;
-
-#if NM_MORE_ASSERTS
- g_critical("g_ascii_strtoll() for \"%s\" failed with errno=%d (%s) and v=%" G_GINT64_FORMAT,
- nptr,
- errsv,
- nm_strerror_native(errsv),
- v);
-#endif
-
- return v;
-}
-
-/* See nm_g_ascii_strtoll() */
-guint64
-nm_g_ascii_strtoull(const char *nptr, char **endptr, guint base)
-{
- int try_count = 2;
- guint64 v;
- const int errsv_orig = errno;
- int errsv;
-
- nm_assert(nptr);
- nm_assert(base == 0u || (base >= 2u && base <= 36u));
-
-again:
- errno = 0;
- v = g_ascii_strtoull(nptr, endptr, base);
- errsv = errno;
-
- if (errsv == 0) {
- if (errsv_orig != 0)
- errno = errsv_orig;
- return v;
- }
-
- if (errsv == ERANGE && NM_IN_SET(v, G_MAXUINT64))
- return v;
-
- if (errsv == EINVAL && v == 0 && nptr && nptr[0] == '\0')
- return v;
-
- if (try_count-- > 0)
- goto again;
-
-#if NM_MORE_ASSERTS
- g_critical("g_ascii_strtoull() for \"%s\" failed with errno=%d (%s) and v=%" G_GUINT64_FORMAT,
- nptr,
- errsv,
- nm_strerror_native(errsv),
- v);
-#endif
-
- return v;
-}
-
-/* see nm_g_ascii_strtoll(). */
-double
-nm_g_ascii_strtod(const char *nptr, char **endptr)
-{
- int try_count = 2;
- double v;
- int errsv;
-
- nm_assert(nptr);
-
-again:
- v = g_ascii_strtod(nptr, endptr);
- errsv = errno;
-
- if (errsv == 0)
- return v;
-
- if (errsv == ERANGE)
- return v;
-
- if (try_count-- > 0)
- goto again;
-
-#if NM_MORE_ASSERTS
- g_critical("g_ascii_strtod() for \"%s\" failed with errno=%d (%s) and v=%f",
- nptr,
- errsv,
- nm_strerror_native(errsv),
- v);
-#endif
-
- /* Not really much else to do. Return the parsed value and leave errno set
- * to the unexpected value. */
- return v;
-}
-
-/* _nm_utils_ascii_str_to_int64:
- *
- * A wrapper for g_ascii_strtoll, that checks whether the whole string
- * can be successfully converted to a number and is within a given
- * range. On any error, @fallback will be returned and %errno will be set
- * to a non-zero value. On success, %errno will be set to zero, check %errno
- * for errors. Any trailing or leading (ascii) white space is ignored and the
- * functions is locale independent.
- *
- * The function is guaranteed to return a value between @min and @max
- * (inclusive) or @fallback. Also, the parsing is rather strict, it does
- * not allow for any unrecognized characters, except leading and trailing
- * white space.
- **/
-gint64
-_nm_utils_ascii_str_to_int64(const char *str, guint base, gint64 min, gint64 max, gint64 fallback)
-{
- gint64 v;
- const char *s = NULL;
-
- str = nm_str_skip_leading_spaces(str);
- if (!str || !str[0]) {
- errno = EINVAL;
- return fallback;
- }
-
- errno = 0;
- v = nm_g_ascii_strtoll(str, (char **) &s, base);
-
- if (errno != 0)
- return fallback;
-
- if (s[0] != '\0') {
- s = nm_str_skip_leading_spaces(s);
- if (s[0] != '\0') {
- errno = EINVAL;
- return fallback;
- }
- }
- if (v > max || v < min) {
- errno = ERANGE;
- return fallback;
- }
-
- return v;
-}
-
-guint64
-_nm_utils_ascii_str_to_uint64(const char *str,
- guint base,
- guint64 min,
- guint64 max,
- guint64 fallback)
-{
- guint64 v;
- const char *s = NULL;
-
- if (str) {
- while (g_ascii_isspace(str[0]))
- str++;
- }
- if (!str || !str[0]) {
- errno = EINVAL;
- return fallback;
- }
-
- errno = 0;
- v = nm_g_ascii_strtoull(str, (char **) &s, base);
-
- if (errno != 0)
- return fallback;
- if (s[0] != '\0') {
- while (g_ascii_isspace(s[0]))
- s++;
- if (s[0] != '\0') {
- errno = EINVAL;
- return fallback;
- }
- }
- if (v > max || v < min) {
- errno = ERANGE;
- return fallback;
- }
-
- if (v != 0 && str[0] == '-') {
- /* As documented, g_ascii_strtoull() accepts negative values, and returns their
- * absolute value. We don't. */
- errno = ERANGE;
- return fallback;
- }
-
- return v;
-}
-
-/*****************************************************************************/
-
-int
-nm_strcmp_with_data(gconstpointer a, gconstpointer b, gpointer user_data)
-{
- const char *s1 = a;
- const char *s2 = b;
-
- return strcmp(s1, s2);
-}
-
-/* like nm_strcmp_p(), suitable for g_ptr_array_sort_with_data().
- * g_ptr_array_sort() just casts nm_strcmp_p() to a function of different
- * signature. I guess, in glib there are knowledgeable people that ensure
- * that this additional argument doesn't cause problems due to different ABI
- * for every architecture that glib supports.
- * For NetworkManager, we'd rather avoid such stunts.
- **/
-int
-nm_strcmp_p_with_data(gconstpointer a, gconstpointer b, gpointer user_data)
-{
- const char *s1 = *((const char **) a);
- const char *s2 = *((const char **) b);
-
- return strcmp(s1, s2);
-}
-
-int
-nm_strcmp0_p_with_data(gconstpointer a, gconstpointer b, gpointer user_data)
-{
- const char *s1 = *((const char **) a);
- const char *s2 = *((const char **) b);
-
- return nm_strcmp0(s1, s2);
-}
-
-int
-nm_strcmp_ascii_case_with_data(gconstpointer a, gconstpointer b, gpointer user_data)
-{
- const char *s1 = a;
- const char *s2 = b;
-
- return g_ascii_strcasecmp(s1, s2);
-}
-
-int
-nm_cmp_uint32_p_with_data(gconstpointer p_a, gconstpointer p_b, gpointer user_data)
-{
- const guint32 a = *((const guint32 *) p_a);
- const guint32 b = *((const guint32 *) p_b);
-
- if (a < b)
- return -1;
- if (a > b)
- return 1;
- return 0;
-}
-
-int
-nm_cmp_int2ptr_p_with_data(gconstpointer p_a, gconstpointer p_b, gpointer user_data)
-{
- /* p_a and p_b are two pointers to a pointer, where the pointer is
- * interpreted as a integer using GPOINTER_TO_INT().
- *
- * That is the case of a hash-table that uses GINT_TO_POINTER() to
- * convert integers as pointers, and the resulting keys-as-array
- * array. */
- const int a = GPOINTER_TO_INT(*((gconstpointer *) p_a));
- const int b = GPOINTER_TO_INT(*((gconstpointer *) p_b));
-
- if (a < b)
- return -1;
- if (a > b)
- return 1;
- return 0;
-}
-
-/*****************************************************************************/
-
-const char *
-nm_utils_dbus_path_get_last_component(const char *dbus_path)
-{
- if (dbus_path) {
- dbus_path = strrchr(dbus_path, '/');
- if (dbus_path)
- return dbus_path + 1;
- }
- return NULL;
-}
-
-static gint64
-_dbus_path_component_as_num(const char *p)
-{
- gint64 n;
-
- /* no odd stuff. No leading zeros, only a non-negative, decimal integer.
- *
- * Otherwise, there would be multiple ways to encode the same number "10"
- * and "010". That is just confusing. A number has no leading zeros,
- * if it has, it's not a number (as far as we are concerned here). */
- if (p[0] == '0') {
- if (p[1] != '\0')
- return -1;
- else
- return 0;
- }
- if (!(p[0] >= '1' && p[0] <= '9'))
- return -1;
- if (!NM_STRCHAR_ALL(&p[1], ch, (ch >= '0' && ch <= '9')))
- return -1;
- n = _nm_utils_ascii_str_to_int64(p, 10, 0, G_MAXINT64, -1);
- nm_assert(n == -1 || nm_streq0(p, nm_sprintf_bufa(100, "%" G_GINT64_FORMAT, n)));
- return n;
-}
-
-int
-nm_utils_dbus_path_cmp(const char *dbus_path_a, const char *dbus_path_b)
-{
- const char *l_a, *l_b;
- gsize plen;
- gint64 n_a, n_b;
-
- /* compare function for two D-Bus paths. It behaves like
- * strcmp(), except, if both paths have the same prefix,
- * and both end in a (positive) number, then the paths
- * will be sorted by number. */
-
- NM_CMP_SELF(dbus_path_a, dbus_path_b);
-
- /* if one or both paths have no slash (and no last component)
- * compare the full paths directly. */
- if (!(l_a = nm_utils_dbus_path_get_last_component(dbus_path_a))
- || !(l_b = nm_utils_dbus_path_get_last_component(dbus_path_b)))
- goto comp_full;
-
- /* check if both paths have the same prefix (up to the last-component). */
- plen = l_a - dbus_path_a;
- if (plen != (l_b - dbus_path_b))
- goto comp_full;
- NM_CMP_RETURN(strncmp(dbus_path_a, dbus_path_b, plen));
-
- n_a = _dbus_path_component_as_num(l_a);
- n_b = _dbus_path_component_as_num(l_b);
- if (n_a == -1 && n_b == -1)
- goto comp_l;
-
- /* both components must be convertible to a number. If they are not,
- * (and only one of them is), then we must always strictly sort numeric parts
- * after non-numeric components. If we wouldn't, we wouldn't have
- * a total order.
- *
- * An example of a not total ordering would be:
- * "8" < "010" (numeric)
- * "0x" < "8" (lexical)
- * "0x" > "010" (lexical)
- * We avoid this, by forcing that a non-numeric entry "0x" always sorts
- * before numeric entries.
- *
- * Additionally, _dbus_path_component_as_num() would also reject "010" as
- * not a valid number.
- */
- if (n_a == -1)
- return -1;
- if (n_b == -1)
- return 1;
-
- NM_CMP_DIRECT(n_a, n_b);
- nm_assert(nm_streq(dbus_path_a, dbus_path_b));
- return 0;
-
-comp_full:
- NM_CMP_DIRECT_STRCMP0(dbus_path_a, dbus_path_b);
- return 0;
-comp_l:
- NM_CMP_DIRECT_STRCMP0(l_a, l_b);
- nm_assert(nm_streq(dbus_path_a, dbus_path_b));
- return 0;
-}
-
-/*****************************************************************************/
-
-typedef struct {
- union {
- guint8 table[256];
- guint64 _dummy_for_alignment;
- };
-} CharLookupTable;
-
-static void
-_char_lookup_table_set_one(CharLookupTable *lookup, char ch)
-{
- lookup->table[(guint8) ch] = 1;
-}
-
-static void
-_char_lookup_table_set_all(CharLookupTable *lookup, const char *candidates)
-{
- while (candidates[0] != '\0')
- _char_lookup_table_set_one(lookup, (candidates++)[0]);
-}
-
-static void
-_char_lookup_table_init(CharLookupTable *lookup, const char *candidates)
-{
- *lookup = (CharLookupTable){
- .table = {0},
- };
- if (candidates)
- _char_lookup_table_set_all(lookup, candidates);
-}
-
-static gboolean
-_char_lookup_has(const CharLookupTable *lookup, char ch)
-{
- /* with some optimization levels, the compiler thinks this code
- * might access uninitialized @lookup. It is not -- when you look at the
- * callers of this function. */
- NM_PRAGMA_WARNING_DISABLE("-Wmaybe-uninitialized")
- nm_assert(lookup->table[(guint8) '\0'] == 0);
- return lookup->table[(guint8) ch] != 0;
- NM_PRAGMA_WARNING_REENABLE
-}
-
-static gboolean
-_char_lookup_has_all(const CharLookupTable *lookup, const char *candidates)
-{
- if (candidates) {
- while (candidates[0] != '\0') {
- if (!_char_lookup_has(lookup, (candidates++)[0]))
- return FALSE;
- }
- }
- return TRUE;
-}
-
-/**
- * nm_utils_strsplit_set_full:
- * @str: the string to split.
- * @delimiters: the set of delimiters.
- * @flags: additional flags for controlling the operation.
- *
- * This is a replacement for g_strsplit_set() which avoids copying
- * each word once (the entire strv array), but instead copies it once
- * and all words point into that internal copy.
- *
- * Note that for @str %NULL and "", this always returns %NULL too. That differs
- * from g_strsplit_set(), which would return an empty strv array for "".
- * 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
- * is not set, it also returns %NULL.
- * Otherwise, a %NULL terminated strv array containing the split words.
- * (delimiter characters are removed).
- * The strings to which the result strv array points to are allocated
- * after the returned result itself. Don't free the strings themself,
- * but free everything with g_free().
- * It is however safe and allowed to modify the individual strings in-place,
- * like "g_strstrip((char *) iter[0])".
- */
-const char **
-nm_utils_strsplit_set_full(const char *str, const char *delimiters, NMUtilsStrsplitSetFlags flags)
-{
- const char ** ptr;
- gsize num_tokens;
- gsize i_token;
- gsize str_len_p1;
- 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_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);
-
- if (!str)
- return NULL;
-
- if (!delimiters) {
- nm_assert_not_reached();
- delimiters = " \t\n";
- }
- _char_lookup_table_init(&ch_lookup, delimiters);
-
- nm_assert(!f_allow_escaping || !_char_lookup_has(&ch_lookup, '\\'));
-
- if (!f_preserve_empty) {
- while (_char_lookup_has(&ch_lookup, str[0]))
- str++;
- }
-
- 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
- * 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;
- }
-
-#define _char_is_escaped(str_start, str_cur) \
- ({ \
- const char *const _str_start = (str_start); \
- const char *const _str_cur = (str_cur); \
- const char * _str_i = (_str_cur); \
- \
- while (_str_i > _str_start && _str_i[-1] == '\\') \
- _str_i--; \
- (((_str_cur - _str_i) % 2) != 0); \
- })
-
- num_tokens = 1;
- c_str = str;
- while (TRUE) {
- while (G_LIKELY(!_char_lookup_has(&ch_lookup, c_str[0]))) {
- if (c_str[0] == '\0')
- goto done1;
- c_str++;
- }
-
- /* we assume escapings are not frequent. After we found
- * this delimiter, check whether it was escaped by counting
- * the backslashed before. */
- if (f_allow_escaping && _char_is_escaped(str, c_str)) {
- /* the delimiter is escaped. This was not an accepted delimiter. */
- c_str++;
- continue;
- }
-
- c_str++;
-
- /* if we drop empty tokens, then we now skip over all consecutive delimiters. */
- if (!f_preserve_empty) {
- while (_char_lookup_has(&ch_lookup, c_str[0]))
- c_str++;
- if (c_str[0] == '\0')
- break;
- }
-
- num_tokens++;
- }
-
-done1:
-
- nm_assert(c_str[0] == '\0');
-
- str_len_p1 = (c_str - str) + 1;
-
- nm_assert(str[str_len_p1 - 1] == '\0');
-
- ptr = g_malloc((sizeof(const char *) * (num_tokens + 1)) + str_len_p1);
- s = (char *) &ptr[num_tokens + 1];
- memcpy(s, str, str_len_p1);
-
- i_token = 0;
-
- while (TRUE) {
- nm_assert(i_token < num_tokens);
- ptr[i_token++] = s;
-
- if (s[0] == '\0') {
- nm_assert(f_preserve_empty);
- goto done2;
- }
- nm_assert(f_preserve_empty || !_char_lookup_has(&ch_lookup, s[0]));
-
- while (!_char_lookup_has(&ch_lookup, s[0])) {
- if (G_UNLIKELY(s[0] == '\\' && f_allow_escaping)) {
- s++;
- if (s[0] == '\0')
- goto done2;
- s++;
- } else if (s[0] == '\0')
- goto done2;
- else
- s++;
- }
-
- nm_assert(_char_lookup_has(&ch_lookup, s[0]));
- s[0] = '\0';
- s++;
-
- if (!f_preserve_empty) {
- while (_char_lookup_has(&ch_lookup, s[0]))
- s++;
- if (s[0] == '\0')
- goto done2;
- }
- }
-
-done2:
- nm_assert(i_token == num_tokens);
- ptr[i_token] = NULL;
-
- if (f_strstrip) {
- gsize i;
-
- i_token = 0;
- for (i = 0; ptr[i]; i++) {
- s = (char *) nm_str_skip_leading_spaces(ptr[i]);
- if (s[0] != '\0') {
- char *s_last;
-
- s_last = &s[strlen(s) - 1];
- while (s_last > s && g_ascii_isspace(s_last[0])
- && (!f_allow_escaping || !_char_is_escaped(s, s_last)))
- (s_last--)[0] = '\0';
- }
-
- if (!f_preserve_empty && s[0] == '\0')
- continue;
-
- ptr[i_token++] = s;
- }
-
- if (i_token == 0) {
- g_free(ptr);
- return NULL;
- }
- ptr[i_token] = NULL;
- }
-
- if (f_escaped) {
- gsize i, j;
-
- /* We no longer need ch_lookup for its original purpose. Modify it, so it
- * can detect the delimiters, '\\', and (optionally) whitespaces. */
- _char_lookup_table_set_one(&ch_lookup, '\\');
- if (f_strstrip)
- _char_lookup_table_set_all(&ch_lookup, NM_ASCII_SPACES);
-
- for (i_token = 0; ptr[i_token]; i_token++) {
- s = (char *) ptr[i_token];
- j = 0;
- for (i = 0; s[i] != '\0';) {
- if (s[i] == '\\' && _char_lookup_has(&ch_lookup, s[i + 1]))
- i++;
- s[j++] = s[i++];
- }
- s[j] = '\0';
- }
- }
-
- nm_assert(ptr && ptr[0]);
- return ptr;
-}
-
-/*****************************************************************************/
-
-const char *
-nm_utils_escaped_tokens_escape_full(const char * str,
- const char * delimiters,
- const char * delimiters_as_needed,
- NMUtilsEscapedTokensEscapeFlags flags,
- char ** out_to_free)
-{
- CharLookupTable ch_lookup;
- CharLookupTable ch_lookup_as_needed;
- gboolean has_ch_lookup_as_needed = FALSE;
- char * ret;
- gsize str_len;
- gsize alloc_len;
- gsize n_escapes;
- gsize i, j;
- gboolean escape_leading_space;
- gboolean escape_trailing_space;
- gboolean escape_backslash_as_needed;
-
- nm_assert(
- !delimiters_as_needed
- || (delimiters_as_needed[0]
- && NM_FLAGS_HAS(flags,
- NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_AS_NEEDED)));
-
- if (!str || str[0] == '\0') {
- *out_to_free = NULL;
- return str;
- }
-
- str_len = strlen(str);
-
- _char_lookup_table_init(&ch_lookup, delimiters);
- if (!delimiters || NM_FLAGS_HAS(flags, NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_SPACES)) {
- flags &= ~(NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_LEADING_SPACE
- | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_TRAILING_SPACE);
- _char_lookup_table_set_all(&ch_lookup, NM_ASCII_SPACES);
- }
-
- if (NM_FLAGS_HAS(flags, NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_ALWAYS)) {
- _char_lookup_table_set_one(&ch_lookup, '\\');
- escape_backslash_as_needed = FALSE;
- } else if (_char_lookup_has(&ch_lookup, '\\'))
- escape_backslash_as_needed = FALSE;
- else {
- escape_backslash_as_needed =
- NM_FLAGS_HAS(flags, NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_AS_NEEDED);
- if (escape_backslash_as_needed) {
- if (NM_FLAGS_ANY(flags,
- NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_LEADING_SPACE
- | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_TRAILING_SPACE)
- && !_char_lookup_has_all(&ch_lookup, NM_ASCII_SPACES)) {
- /* ESCAPE_LEADING_SPACE and ESCAPE_TRAILING_SPACE implies that we escape backslash
- * before whitespaces. */
- if (!has_ch_lookup_as_needed) {
- has_ch_lookup_as_needed = TRUE;
- _char_lookup_table_init(&ch_lookup_as_needed, NULL);
- }
- _char_lookup_table_set_all(&ch_lookup_as_needed, NM_ASCII_SPACES);
- }
- if (delimiters_as_needed && !_char_lookup_has_all(&ch_lookup, delimiters_as_needed)) {
- if (!has_ch_lookup_as_needed) {
- has_ch_lookup_as_needed = TRUE;
- _char_lookup_table_init(&ch_lookup_as_needed, NULL);
- }
- _char_lookup_table_set_all(&ch_lookup_as_needed, delimiters_as_needed);
- }
- }
- }
-
- escape_leading_space =
- NM_FLAGS_HAS(flags, NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_LEADING_SPACE)
- && g_ascii_isspace(str[0]) && !_char_lookup_has(&ch_lookup, str[0]);
- if (str_len == 1)
- escape_trailing_space = FALSE;
- else {
- escape_trailing_space =
- NM_FLAGS_HAS(flags, NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_TRAILING_SPACE)
- && g_ascii_isspace(str[str_len - 1]) && !_char_lookup_has(&ch_lookup, str[str_len - 1]);
- }
-
- n_escapes = 0;
- for (i = 0; str[i] != '\0'; i++) {
- if (_char_lookup_has(&ch_lookup, str[i]))
- n_escapes++;
- else if (str[i] == '\\' && escape_backslash_as_needed
- && (_char_lookup_has(&ch_lookup, str[i + 1]) || NM_IN_SET(str[i + 1], '\0', '\\')
- || (has_ch_lookup_as_needed
- && _char_lookup_has(&ch_lookup_as_needed, str[i + 1]))))
- n_escapes++;
- }
- if (escape_leading_space)
- n_escapes++;
- if (escape_trailing_space)
- n_escapes++;
-
- if (n_escapes == 0u) {
- *out_to_free = NULL;
- return str;
- }
-
- alloc_len = str_len + n_escapes + 1u;
- ret = g_new(char, alloc_len);
-
- j = 0;
- i = 0;
-
- if (escape_leading_space) {
- ret[j++] = '\\';
- ret[j++] = str[i++];
- }
- for (; str[i] != '\0'; i++) {
- if (_char_lookup_has(&ch_lookup, str[i]))
- ret[j++] = '\\';
- else if (str[i] == '\\' && escape_backslash_as_needed
- && (_char_lookup_has(&ch_lookup, str[i + 1]) || NM_IN_SET(str[i + 1], '\0', '\\')
- || (has_ch_lookup_as_needed
- && _char_lookup_has(&ch_lookup_as_needed, str[i + 1]))))
- ret[j++] = '\\';
- ret[j++] = str[i];
- }
- if (escape_trailing_space) {
- nm_assert(!_char_lookup_has(&ch_lookup, ret[j - 1]) && g_ascii_isspace(ret[j - 1]));
- ret[j] = ret[j - 1];
- ret[j - 1] = '\\';
- j++;
- }
-
- nm_assert(j == alloc_len - 1);
- ret[j] = '\0';
- nm_assert(strlen(ret) == j);
-
- *out_to_free = ret;
- return ret;
-}
-
-/**
- * nm_utils_escaped_tokens_options_split:
- * @str: the src string. This string will be modified in-place.
- * The output values will point into @str.
- * @out_key: (allow-none): the returned output key. This will always be set to @str
- * itself. @str will be modified to contain only the unescaped, truncated
- * key name.
- * @out_val: returns the parsed (and unescaped) value or %NULL, if @str contains
- * no '=' delimiter.
- *
- * Honors backslash escaping to parse @str as "key=value" pairs. Optionally, if no '='
- * is present, @out_val will be returned as %NULL. Backslash can be used to escape
- * '=', ',', '\\', and ascii whitespace. Other backslash sequences are taken verbatim.
- *
- * For keys, '=' obviously must be escaped. For values, that is optional because an
- * unescaped '=' is just taken verbatim. For example, in a key, the sequence "\\="
- * must be escaped as "\\\\\\=". For the value, that works too, but "\\\\=" is also
- * accepted.
- *
- * Unescaped Space around the key and value are also removed. Space in general must
- * not be escaped, unless they are at the beginning or the end of key/value.
- */
-void
-nm_utils_escaped_tokens_options_split(char *str, const char **out_key, const char **out_val)
-{
- const char *val = NULL;
- gsize i;
- gsize j;
- gsize last_space_idx;
- gboolean last_space_has;
-
- nm_assert(str);
-
- i = 0;
- while (g_ascii_isspace(str[i]))
- i++;
-
- j = 0;
- last_space_idx = 0;
- last_space_has = FALSE;
- while (str[i] != '\0') {
- if (g_ascii_isspace(str[i])) {
- if (!last_space_has) {
- last_space_has = TRUE;
- last_space_idx = j;
- }
- } else {
- if (str[i] == '\\') {
- if (NM_IN_SET(str[i + 1u], '\\', ',', '=') || g_ascii_isspace(str[i + 1u]))
- i++;
- } else if (str[i] == '=') {
- /* Encounter an unescaped '=' character. When we still parse the key, this
- * is the separator we were waiting for. If we are parsing the value,
- * we take the character verbatim. */
- if (!val) {
- if (last_space_has) {
- str[last_space_idx] = '\0';
- j = last_space_idx + 1;
- last_space_has = FALSE;
- } else
- str[j++] = '\0';
- val = &str[j];
- i++;
- while (g_ascii_isspace(str[i]))
- i++;
- continue;
- }
- }
- last_space_has = FALSE;
- }
- str[j++] = str[i++];
- }
-
- if (last_space_has)
- str[last_space_idx] = '\0';
- else
- str[j] = '\0';
-
- *out_key = str;
- *out_val = val;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_utils_strsplit_quoted:
- * @str: the string to split (e.g. from /proc/cmdline).
- *
- * This basically does that systemd's extract_first_word() does
- * 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
- * supports a variety of flags. However, extending that already
- * complex code to also support quotation and escaping is hard.
- * Instead, add a naive implementation.
- *
- * Returns: (transfer full): the split string.
- */
-char **
-nm_utils_strsplit_quoted(const char *str)
-{
- gs_unref_ptrarray GPtrArray *arr = NULL;
- gs_free char * str_out = NULL;
- CharLookupTable ch_lookup;
-
- nm_assert(str);
-
- _char_lookup_table_init(&ch_lookup, NM_ASCII_WHITESPACES);
-
- for (;;) {
- char quote;
- gsize j;
-
- while (_char_lookup_has(&ch_lookup, str[0]))
- str++;
-
- if (str[0] == '\0')
- break;
-
- if (!str_out)
- str_out = g_new(char, strlen(str) + 1);
-
- quote = '\0';
- j = 0;
- for (;;) {
- if (str[0] == '\\') {
- str++;
- if (str[0] == '\0')
- break;
- str_out[j++] = str[0];
- str++;
- continue;
- }
- if (quote) {
- if (str[0] == '\0')
- break;
- if (str[0] == quote) {
- quote = '\0';
- str++;
- continue;
- }
- str_out[j++] = str[0];
- str++;
- continue;
- }
- if (str[0] == '\0')
- break;
- if (NM_IN_SET(str[0], '\'', '"')) {
- quote = str[0];
- str++;
- continue;
- }
- if (_char_lookup_has(&ch_lookup, str[0])) {
- str++;
- break;
- }
- str_out[j++] = str[0];
- str++;
- }
-
- if (!arr)
- arr = g_ptr_array_new();
- g_ptr_array_add(arr, g_strndup(str_out, j));
- }
-
- if (!arr)
- return g_new0(char *, 1);
-
- g_ptr_array_add(arr, NULL);
-
- /* We want to return an optimally sized strv array, with no excess
- * memory allocated. Hence, clone once more. */
- return nm_memdup(arr->pdata, sizeof(char *) * arr->len);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_utils_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().
- *
- * Searches @list for @needle and returns the index of the first match (based
- * on strcmp()).
- *
- * For convenience, @list has type 'char**' instead of 'const char **'.
- *
- * 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)
-{
- gssize i;
-
- if (len > 0) {
- g_return_val_if_fail(list, -1);
-
- if (!needle) {
- /* if we search a list with known length, %NULL is a valid @needle. */
- for (i = 0; i < len; i++) {
- if (!list[i])
- return i;
- }
- } else {
- for (i = 0; i < len; i++) {
- if (list[i] && !strcmp(needle, list[i]))
- return i;
- }
- }
- } else if (len < 0) {
- g_return_val_if_fail(needle, -1);
-
- if (list) {
- for (i = 0; list[i]; i++) {
- if (strcmp(needle, list[i]) == 0)
- return i;
- }
- }
- }
- return -1;
-}
-
-char **
-_nm_utils_strv_cleanup(char ** strv,
- gboolean strip_whitespace,
- gboolean skip_empty,
- gboolean skip_repeated)
-{
- guint i, j;
-
- if (!strv || !*strv)
- return strv;
-
- if (strip_whitespace) {
- /* we only modify the strings pointed to by @strv if @strip_whitespace is
- * requested. Otherwise, the strings themselves are untouched. */
- for (i = 0; strv[i]; i++)
- g_strstrip(strv[i]);
- }
- if (!skip_empty && !skip_repeated)
- return 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))
- g_free(strv[i]);
- else
- strv[j++] = strv[i];
- }
- strv[j] = NULL;
- return strv;
-}
-
-/*****************************************************************************/
-
-GPtrArray *
-_nm_g_ptr_array_copy(GPtrArray * array,
- GCopyFunc func,
- gpointer user_data,
- GDestroyNotify element_free_func)
-{
- GPtrArray *new_array;
- guint i;
-
- g_return_val_if_fail(array, NULL);
-
- new_array = g_ptr_array_new_full(array->len, element_free_func);
- for (i = 0; i < array->len; i++) {
- g_ptr_array_add(new_array, func ? func(array->pdata[i], user_data) : array->pdata[i]);
- }
- return new_array;
-}
-
-/*****************************************************************************/
-
-int
-_nm_utils_ascii_str_to_bool(const char *str, int default_value)
-{
- gs_free char *str_free = NULL;
-
- if (!str)
- return default_value;
-
- str = nm_strstrip_avoid_copy_a(300, str, &str_free);
- if (str[0] == '\0')
- return default_value;
-
- if (!g_ascii_strcasecmp(str, "true") || !g_ascii_strcasecmp(str, "yes")
- || !g_ascii_strcasecmp(str, "on") || !g_ascii_strcasecmp(str, "1"))
- return TRUE;
-
- if (!g_ascii_strcasecmp(str, "false") || !g_ascii_strcasecmp(str, "no")
- || !g_ascii_strcasecmp(str, "off") || !g_ascii_strcasecmp(str, "0"))
- return FALSE;
-
- return default_value;
-}
-
-/*****************************************************************************/
-
-NM_CACHED_QUARK_FCN("nm-manager-error-quark", nm_manager_error_quark);
-
-NM_CACHED_QUARK_FCN("nm-utils-error-quark", nm_utils_error_quark);
-
-void
-nm_utils_error_set_cancelled(GError **error, gboolean is_disposing, const char *instance_name)
-{
- if (is_disposing) {
- g_set_error(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_CANCELLED_DISPOSING,
- "Disposing %s instance",
- instance_name && *instance_name ? instance_name : "source");
- } else {
- g_set_error_literal(error, G_IO_ERROR, G_IO_ERROR_CANCELLED, "Request cancelled");
- }
-}
-
-gboolean
-nm_utils_error_is_cancelled_or_disposing(GError *error)
-{
- if (error) {
- if (error->domain == G_IO_ERROR)
- return NM_IN_SET(error->code, G_IO_ERROR_CANCELLED);
- if (error->domain == NM_UTILS_ERROR)
- return NM_IN_SET(error->code, NM_UTILS_ERROR_CANCELLED_DISPOSING);
- }
- return FALSE;
-}
-
-gboolean
-nm_utils_error_is_notfound(GError *error)
-{
- if (error) {
- if (error->domain == G_IO_ERROR)
- return NM_IN_SET(error->code, G_IO_ERROR_NOT_FOUND);
- if (error->domain == G_FILE_ERROR)
- return NM_IN_SET(error->code, G_FILE_ERROR_NOENT);
- }
- return FALSE;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_g_object_set_property:
- * @object: the target object
- * @property_name: the property name
- * @value: the #GValue to set
- * @error: (allow-none): optional error argument
- *
- * A reimplementation of g_object_set_property(), but instead
- * returning an error instead of logging a warning. All g_object_set*()
- * versions in glib require you to not pass invalid types or they will
- * log a g_warning() -- without reporting an error. We don't want that,
- * so we need to hack error checking around it.
- *
- * Returns: whether the value was successfully set.
- */
-gboolean
-nm_g_object_set_property(GObject * object,
- const char * property_name,
- const GValue *value,
- GError ** error)
-{
- GParamSpec * pspec;
- nm_auto_unset_gvalue GValue tmp_value = G_VALUE_INIT;
- GObjectClass * klass;
-
- g_return_val_if_fail(G_IS_OBJECT(object), FALSE);
- g_return_val_if_fail(property_name != NULL, FALSE);
- g_return_val_if_fail(G_IS_VALUE(value), FALSE);
- g_return_val_if_fail(!error || !*error, FALSE);
-
- /* g_object_class_find_property() does g_param_spec_get_redirect_target(),
- * where we differ from a plain g_object_set_property(). */
- pspec = g_object_class_find_property(G_OBJECT_GET_CLASS(object), property_name);
-
- if (!pspec) {
- g_set_error(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- _("object class '%s' has no property named '%s'"),
- G_OBJECT_TYPE_NAME(object),
- property_name);
- return FALSE;
- }
- if (!(pspec->flags & G_PARAM_WRITABLE)) {
- g_set_error(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- _("property '%s' of object class '%s' is not writable"),
- pspec->name,
- G_OBJECT_TYPE_NAME(object));
- return FALSE;
- }
- if ((pspec->flags & G_PARAM_CONSTRUCT_ONLY)) {
- g_set_error(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- _("construct property \"%s\" for object '%s' can't be set after construction"),
- pspec->name,
- G_OBJECT_TYPE_NAME(object));
- return FALSE;
- }
-
- klass = g_type_class_peek(pspec->owner_type);
- if (klass == NULL) {
- g_set_error(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- _("'%s::%s' is not a valid property name; '%s' is not a GObject subtype"),
- g_type_name(pspec->owner_type),
- pspec->name,
- g_type_name(pspec->owner_type));
- return FALSE;
- }
-
- /* provide a copy to work from, convert (if necessary) and validate */
- g_value_init(&tmp_value, pspec->value_type);
- if (!g_value_transform(value, &tmp_value)) {
- g_set_error(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- _("unable to set property '%s' of type '%s' from value of type '%s'"),
- pspec->name,
- g_type_name(pspec->value_type),
- G_VALUE_TYPE_NAME(value));
- return FALSE;
- }
- if (g_param_value_validate(pspec, &tmp_value) && !(pspec->flags & G_PARAM_LAX_VALIDATION)) {
- gs_free char *contents = g_strdup_value_contents(value);
-
- g_set_error(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- _("value \"%s\" of type '%s' is invalid or out of range for property '%s' of "
- "type '%s'"),
- contents,
- G_VALUE_TYPE_NAME(value),
- pspec->name,
- g_type_name(pspec->value_type));
- return FALSE;
- }
-
- g_object_set_property(object, property_name, &tmp_value);
- return TRUE;
-}
-
-#define _set_property(object, property_name, gtype, gtype_set, value, error) \
- G_STMT_START \
- { \
- nm_auto_unset_gvalue GValue gvalue = {0}; \
- \
- g_value_init(&gvalue, gtype); \
- gtype_set(&gvalue, (value)); \
- return nm_g_object_set_property((object), (property_name), &gvalue, (error)); \
- } \
- G_STMT_END
-
-gboolean
-nm_g_object_set_property_string(GObject * object,
- const char *property_name,
- const char *value,
- GError ** error)
-{
- _set_property(object, property_name, G_TYPE_STRING, g_value_set_string, value, error);
-}
-
-gboolean
-nm_g_object_set_property_string_static(GObject * object,
- const char *property_name,
- const char *value,
- GError ** error)
-{
- _set_property(object, property_name, G_TYPE_STRING, g_value_set_static_string, value, error);
-}
-
-gboolean
-nm_g_object_set_property_string_take(GObject * object,
- const char *property_name,
- char * value,
- GError ** error)
-{
- _set_property(object, property_name, G_TYPE_STRING, g_value_take_string, value, error);
-}
-
-gboolean
-nm_g_object_set_property_boolean(GObject * object,
- const char *property_name,
- gboolean value,
- GError ** error)
-{
- _set_property(object, property_name, G_TYPE_BOOLEAN, g_value_set_boolean, !!value, error);
-}
-
-gboolean
-nm_g_object_set_property_char(GObject * object,
- const char *property_name,
- gint8 value,
- GError ** error)
-{
- /* glib says about G_TYPE_CHAR:
- *
- * The type designated by G_TYPE_CHAR is unconditionally an 8-bit signed integer.
- *
- * This is always a (signed!) char. */
- _set_property(object, property_name, G_TYPE_CHAR, g_value_set_schar, value, error);
-}
-
-gboolean
-nm_g_object_set_property_uchar(GObject * object,
- const char *property_name,
- guint8 value,
- GError ** error)
-{
- _set_property(object, property_name, G_TYPE_UCHAR, g_value_set_uchar, value, error);
-}
-
-gboolean
-nm_g_object_set_property_int(GObject *object, const char *property_name, int value, GError **error)
-{
- _set_property(object, property_name, G_TYPE_INT, g_value_set_int, value, error);
-}
-
-gboolean
-nm_g_object_set_property_int64(GObject * object,
- const char *property_name,
- gint64 value,
- GError ** error)
-{
- _set_property(object, property_name, G_TYPE_INT64, g_value_set_int64, value, error);
-}
-
-gboolean
-nm_g_object_set_property_uint(GObject * object,
- const char *property_name,
- guint value,
- GError ** error)
-{
- _set_property(object, property_name, G_TYPE_UINT, g_value_set_uint, value, error);
-}
-
-gboolean
-nm_g_object_set_property_uint64(GObject * object,
- const char *property_name,
- guint64 value,
- GError ** error)
-{
- _set_property(object, property_name, G_TYPE_UINT64, g_value_set_uint64, value, error);
-}
-
-gboolean
-nm_g_object_set_property_flags(GObject * object,
- const char *property_name,
- GType gtype,
- guint value,
- GError ** error)
-{
- nm_assert(({
- nm_auto_unref_gtypeclass GTypeClass *gtypeclass = g_type_class_ref(gtype);
- G_IS_FLAGS_CLASS(gtypeclass);
- }));
- _set_property(object, property_name, gtype, g_value_set_flags, value, error);
-}
-
-gboolean
-nm_g_object_set_property_enum(GObject * object,
- const char *property_name,
- GType gtype,
- int value,
- GError ** error)
-{
- nm_assert(({
- nm_auto_unref_gtypeclass GTypeClass *gtypeclass = g_type_class_ref(gtype);
- G_IS_ENUM_CLASS(gtypeclass);
- }));
- _set_property(object, property_name, gtype, g_value_set_enum, value, error);
-}
-
-GParamSpec *
-nm_g_object_class_find_property_from_gtype(GType gtype, const char *property_name)
-{
- nm_auto_unref_gtypeclass GObjectClass *gclass = NULL;
-
- gclass = g_type_class_ref(gtype);
- return g_object_class_find_property(gclass, property_name);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_g_type_find_implementing_class_for_property:
- * @gtype: the GObject type which has a property @pname
- * @pname: the name of the property to look up
- *
- * This is only a helper function for printf debugging. It's not
- * used in actual code. Hence, the function just asserts that
- * @pname and @gtype arguments are suitable. It cannot fail.
- *
- * Returns: the most ancestor type of @gtype, that
- * implements the property @pname. It means, it
- * searches the type hierarchy to find the type
- * that added @pname.
- */
-GType
-nm_g_type_find_implementing_class_for_property(GType gtype, const char *pname)
-{
- nm_auto_unref_gtypeclass GObjectClass *klass = NULL;
- GParamSpec * pspec;
-
- g_return_val_if_fail(pname, G_TYPE_INVALID);
-
- klass = g_type_class_ref(gtype);
- g_return_val_if_fail(G_IS_OBJECT_CLASS(klass), G_TYPE_INVALID);
-
- pspec = g_object_class_find_property(klass, pname);
- g_return_val_if_fail(pspec, G_TYPE_INVALID);
-
- gtype = G_TYPE_FROM_CLASS(klass);
-
- while (TRUE) {
- nm_auto_unref_gtypeclass GObjectClass *k = NULL;
-
- k = g_type_class_ref(g_type_parent(gtype));
-
- g_return_val_if_fail(G_IS_OBJECT_CLASS(k), G_TYPE_INVALID);
-
- if (g_object_class_find_property(k, pname) != pspec)
- return gtype;
-
- gtype = G_TYPE_FROM_CLASS(k);
- }
-}
-
-/*****************************************************************************/
-
-static void
-_str_buf_append_c_escape_octal(NMStrBuf *strbuf, char ch)
-{
- nm_str_buf_append_c4(strbuf,
- '\\',
- '0' + ((char) ((((guchar) ch) >> 6) & 07)),
- '0' + ((char) ((((guchar) ch) >> 3) & 07)),
- '0' + ((char) ((((guchar) ch)) & 07)));
-}
-
-/**
- * nm_utils_buf_utf8safe_unescape:
- * @str: (allow-none): the string to unescape. The string itself is a NUL terminated
- * ASCII string, that can have C-style backslash escape sequences (which
- * are to be unescaped). Non-ASCII characters (e.g. UTF-8) are taken verbatim, so
- * it doesn't care that this string is UTF-8. However, usually this is a UTF-8 encoded
- * string.
- * @flags: flags for unescaping. The following flags are supported.
- * %NM_UTILS_STR_UTF8_SAFE_UNESCAPE_STRIP_SPACES performs a g_strstrip() on the input string,
- * but preserving escaped spaces. For example, "a\\t " gives "a\t" (that is, the escaped space does
- * not get stripped). Likewise, the invalid escape sequence "a\\ " results in "a " (stripping
- * the unescaped space, but preserving the escaped one).
- * @out_len: (out): the length of the parsed string.
- * @to_free: (out): if @str requires unescaping, the function will clone the string. In
- * that case, the allocated buffer will be returned here.
- *
- * See C-style escapes at https://en.wikipedia.org/wiki/Escape_sequences_in_C#Table_of_escape_sequences.
- * Note that hex escapes ("\\xhh") and unicode escapes ("\\uhhhh", "\\Uhhhhhhhh") are not supported.
- *
- * Also, this function is very similar to g_strcompress() but without issuing g_warning()
- * assertions and proper handling of "\\000" escape sequences.
- *
- * Invalid escape sequences (or non-UTF-8 input) are gracefully accepted. For example "\\ "
- * is an invalid escape sequence, in this case the backslash is removed and " " gets returned.
- *
- * The function never leaks secrets in memory.
- *
- * Returns: the unescaped buffer of length @out_len. If @str is %NULL, this returns %NULL
- * and sets @out_len to 0. Otherwise, a non-%NULL binary buffer is returned with
- * @out_len bytes. Note that the binary buffer is guaranteed to be NUL terminated. That
- * is @result[@out_len] is NUL.
- * Note that the result is binary, and may have embedded NUL characters and non-UTF-8.
- * If the function can avoid cloning the input string, it will return a pointer inside
- * the input @str. For example, if there is no backslash, no cloning is necessary. In that
- * case, @to_free will be %NULL. Otherwise, @to_free is set to a newly allocated buffer
- * containing the unescaped string and returned.
- */
-gconstpointer
-nm_utils_buf_utf8safe_unescape(const char * str,
- NMUtilsStrUtf8SafeFlags flags,
- gsize * out_len,
- gpointer * to_free)
-{
- gboolean strip_spaces = NM_FLAGS_HAS(flags, NM_UTILS_STR_UTF8_SAFE_UNESCAPE_STRIP_SPACES);
- NMStrBuf strbuf;
- const char *s;
- gsize len;
-
- g_return_val_if_fail(to_free, NULL);
- g_return_val_if_fail(out_len, NULL);
-
- if (!str) {
- *out_len = 0;
- *to_free = NULL;
- return NULL;
- }
-
- if (strip_spaces)
- str = nm_str_skip_leading_spaces(str);
-
- len = strlen(str);
-
- s = memchr(str, '\\', len);
- if (!s) {
- if (strip_spaces && len > 0 && g_ascii_isspace(str[len - 1])) {
- len--;
- while (len > 0 && g_ascii_isspace(str[len - 1]))
- len--;
- *out_len = len;
- return (*to_free = g_strndup(str, len));
- }
- *out_len = len;
- *to_free = NULL;
- return str;
- }
-
- nm_str_buf_init(&strbuf, len + 1u, FALSE);
-
- nm_str_buf_append_len(&strbuf, str, s - str);
- str = s;
-
- for (;;) {
- char ch;
- guint v;
-
- nm_assert(str[0] == '\\');
-
- ch = (++str)[0];
-
- if (ch == '\0') {
- /* error. Trailing '\\' */
- break;
- }
-
- if (ch >= '0' && ch <= '9') {
- v = ch - '0';
- ch = (++str)[0];
- if (ch >= '0' && ch <= '7') {
- v = v * 8 + (ch - '0');
- ch = (++str)[0];
- if (ch >= '0' && ch <= '7') {
- /* technically, escape sequences larger than \3FF are out of range
- * and invalid. We don't check for that, and do the same as
- * g_strcompress(): silently clip the value with & 0xFF. */
- v = v * 8 + (ch - '0');
- ++str;
- }
- }
- ch = v;
- } else {
- switch (ch) {
- case 'b':
- ch = '\b';
- break;
- case 'f':
- ch = '\f';
- break;
- case 'n':
- ch = '\n';
- break;
- case 'r':
- ch = '\r';
- break;
- case 't':
- ch = '\t';
- break;
- case 'v':
- ch = '\v';
- break;
- default:
- /* Here we handle "\\\\", but all other unexpected escape sequences are really a bug.
- * Take them literally, after removing the escape character */
- break;
- }
- str++;
- }
-
- nm_str_buf_append_c(&strbuf, ch);
-
- s = strchr(str, '\\');
- if (!s) {
- gsize l = strlen(str);
-
- if (strip_spaces) {
- while (l > 0 && g_ascii_isspace(str[l - 1]))
- l--;
- }
- nm_str_buf_append_len(&strbuf, str, l);
- break;
- }
-
- nm_str_buf_append_len(&strbuf, str, s - str);
- str = s;
- }
-
- /* assert that no reallocation was necessary. For one, unescaping should
- * never result in a longer string than the input. Also, when unescaping
- * secrets, we want to ensure that we don't leak secrets in memory. */
- nm_assert(strbuf.allocated == len + 1u);
-
- return (*to_free = nm_str_buf_finalize(&strbuf, out_len));
-}
-
-/**
- * nm_utils_buf_utf8safe_escape:
- * @buf: byte array, possibly in utf-8 encoding, may have NUL characters.
- * @buflen: the length of @buf in bytes, or -1 if @buf is a NUL terminated
- * string.
- * @flags: #NMUtilsStrUtf8SafeFlags flags
- * @to_free: (out): return the pointer location of the string
- * if a copying was necessary.
- *
- * Based on the assumption, that @buf contains UTF-8 encoded bytes,
- * this will return valid UTF-8 sequence, and invalid sequences
- * will be escaped with backslash (C escaping, like g_strescape()).
- * This is sanitize non UTF-8 characters. The result is valid
- * UTF-8.
- *
- * The operation can be reverted with nm_utils_buf_utf8safe_unescape().
- * Note that if, and only if @buf contains no NUL bytes, the operation
- * can also be reverted with g_strcompress().
- *
- * Depending on @flags, valid UTF-8 characters are not escaped at all
- * (except the escape character '\\'). This is the difference to g_strescape(),
- * which escapes all non-ASCII characters. This allows to pass on
- * valid UTF-8 characters as-is and can be directly shown to the user
- * as UTF-8 -- with exception of the backslash escape character,
- * invalid UTF-8 sequences, and other (depending on @flags).
- *
- * Returns: the escaped input buffer, as valid UTF-8. If no escaping
- * is necessary, it returns the input @buf. Otherwise, an allocated
- * string @to_free is returned which must be freed by the caller
- * with g_free. The escaping can be reverted by g_strcompress().
- **/
-const char *
-nm_utils_buf_utf8safe_escape(gconstpointer buf,
- gssize buflen,
- NMUtilsStrUtf8SafeFlags flags,
- char ** to_free)
-{
- const char *const str = buf;
- const char * p = NULL;
- const char * s;
- gboolean nul_terminated = FALSE;
- NMStrBuf strbuf;
-
- g_return_val_if_fail(to_free, NULL);
-
- *to_free = NULL;
-
- if (buflen == 0)
- return NULL;
-
- if (buflen < 0) {
- if (!str)
- return NULL;
- buflen = strlen(str);
- if (buflen == 0)
- return str;
- nul_terminated = TRUE;
- }
-
- if (g_utf8_validate(str, buflen, &p) && nul_terminated) {
- /* note that g_utf8_validate() does not allow NUL character inside @str. Good.
- * We can treat @str like a NUL terminated string. */
- if (!NM_STRCHAR_ANY(
- str,
- ch,
- (ch == '\\'
- || (NM_FLAGS_HAS(flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL) && ch < ' ')
- || (NM_FLAGS_HAS(flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII)
- && ((guchar) ch) >= 127))))
- return str;
- }
-
- nm_str_buf_init(&strbuf, buflen + 5, NM_FLAGS_HAS(flags, NM_UTILS_STR_UTF8_SAFE_FLAG_SECRET));
-
- s = str;
- do {
- buflen -= p - s;
- nm_assert(buflen >= 0);
-
- for (; s < p; s++) {
- char ch = s[0];
-
- nm_assert(ch);
- if (ch == '\\')
- nm_str_buf_append_c2(&strbuf, '\\', '\\');
- else if ((NM_FLAGS_HAS(flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL) && ch < ' ')
- || (NM_FLAGS_HAS(flags, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII)
- && ((guchar) ch) >= 127))
- _str_buf_append_c_escape_octal(&strbuf, ch);
- else
- nm_str_buf_append_c(&strbuf, ch);
- }
-
- if (buflen <= 0)
- break;
-
- _str_buf_append_c_escape_octal(&strbuf, p[0]);
-
- buflen--;
- if (buflen == 0)
- break;
-
- s = &p[1];
- (void) g_utf8_validate(s, buflen, &p);
- } while (TRUE);
-
- return (*to_free = nm_str_buf_finalize(&strbuf, NULL));
-}
-
-const char *
-nm_utils_buf_utf8safe_escape_bytes(GBytes *bytes, NMUtilsStrUtf8SafeFlags flags, char **to_free)
-{
- gconstpointer p;
- gsize l;
-
- if (bytes)
- p = g_bytes_get_data(bytes, &l);
- else {
- p = NULL;
- l = 0;
- }
-
- return nm_utils_buf_utf8safe_escape(p, l, flags, to_free);
-}
-
-char *
-nm_utils_buf_utf8safe_escape_cp(gconstpointer buf, gssize buflen, NMUtilsStrUtf8SafeFlags flags)
-{
- const char *s_const;
- char * s;
-
- s_const = nm_utils_buf_utf8safe_escape(buf, buflen, flags, &s);
- nm_assert(!s || s == s_const);
- return s ?: g_strdup(s_const);
-}
-
-/*****************************************************************************/
-
-const char *
-nm_utils_str_utf8safe_unescape(const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free)
-{
- const char *res;
- gsize len;
-
- g_return_val_if_fail(to_free, NULL);
-
- res = nm_utils_buf_utf8safe_unescape(str, flags, &len, (gpointer *) to_free);
-
- nm_assert((!res && len == 0) || (strlen(res) <= len));
-
- return res;
-}
-
-/**
- * nm_utils_str_utf8safe_escape:
- * @str: NUL terminated input string, possibly in utf-8 encoding
- * @flags: #NMUtilsStrUtf8SafeFlags flags
- * @to_free: (out): return the pointer location of the string
- * if a copying was necessary.
- *
- * Returns the possible non-UTF-8 NUL terminated string @str
- * and uses backslash escaping (C escaping, like g_strescape())
- * to sanitize non UTF-8 characters. The result is valid
- * UTF-8.
- *
- * The operation can be reverted with g_strcompress() or
- * nm_utils_str_utf8safe_unescape().
- *
- * Depending on @flags, valid UTF-8 characters are not escaped at all
- * (except the escape character '\\'). This is the difference to g_strescape(),
- * which escapes all non-ASCII characters. This allows to pass on
- * valid UTF-8 characters as-is and can be directly shown to the user
- * as UTF-8 -- with exception of the backslash escape character,
- * invalid UTF-8 sequences, and other (depending on @flags).
- *
- * Returns: the escaped input string, as valid UTF-8. If no escaping
- * is necessary, it returns the input @str. Otherwise, an allocated
- * string @to_free is returned which must be freed by the caller
- * with g_free. The escaping can be reverted by g_strcompress().
- **/
-const char *
-nm_utils_str_utf8safe_escape(const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free)
-{
- return nm_utils_buf_utf8safe_escape(str, -1, flags, to_free);
-}
-
-/**
- * nm_utils_str_utf8safe_escape_cp:
- * @str: NUL terminated input string, possibly in utf-8 encoding
- * @flags: #NMUtilsStrUtf8SafeFlags flags
- *
- * Like nm_utils_str_utf8safe_escape(), except the returned value
- * is always a copy of the input and must be freed by the caller.
- *
- * Returns: the escaped input string in UTF-8 encoding. The returned
- * value should be freed with g_free().
- * The escaping can be reverted by g_strcompress().
- **/
-char *
-nm_utils_str_utf8safe_escape_cp(const char *str, NMUtilsStrUtf8SafeFlags flags)
-{
- char *s;
-
- nm_utils_str_utf8safe_escape(str, flags, &s);
- return s ?: g_strdup(str);
-}
-
-char *
-nm_utils_str_utf8safe_unescape_cp(const char *str, NMUtilsStrUtf8SafeFlags flags)
-{
- char *s;
-
- str = nm_utils_str_utf8safe_unescape(str, flags, &s);
- return s ?: g_strdup(str);
-}
-
-char *
-nm_utils_str_utf8safe_escape_take(char *str, NMUtilsStrUtf8SafeFlags flags)
-{
- char *str_to_free;
-
- nm_utils_str_utf8safe_escape(str, flags, &str_to_free);
- if (str_to_free) {
- g_free(str);
- return str_to_free;
- }
- return str;
-}
-
-/*****************************************************************************/
-
-/* taken from systemd's fd_wait_for_event(). Note that the timeout
- * is here in nano-seconds, not micro-seconds. */
-int
-nm_utils_fd_wait_for_event(int fd, int event, gint64 timeout_nsec)
-{
- struct pollfd pollfd = {
- .fd = fd,
- .events = event,
- };
- struct timespec ts, *pts;
- int r;
-
- if (timeout_nsec < 0)
- pts = NULL;
- else {
- ts.tv_sec = (time_t)(timeout_nsec / NM_UTILS_NSEC_PER_SEC);
- ts.tv_nsec = (long int) (timeout_nsec % NM_UTILS_NSEC_PER_SEC);
- pts = &ts;
- }
-
- r = ppoll(&pollfd, 1, pts, NULL);
- if (r < 0)
- return -NM_ERRNO_NATIVE(errno);
- if (r == 0)
- return 0;
- return pollfd.revents;
-}
-
-/* taken from systemd's loop_read() */
-ssize_t
-nm_utils_fd_read_loop(int fd, void *buf, size_t nbytes, bool do_poll)
-{
- uint8_t *p = buf;
- ssize_t n = 0;
-
- g_return_val_if_fail(fd >= 0, -EINVAL);
- g_return_val_if_fail(buf, -EINVAL);
-
- /* If called with nbytes == 0, let's call read() at least
- * once, to validate the operation */
-
- if (nbytes > (size_t) SSIZE_MAX)
- return -EINVAL;
-
- do {
- ssize_t k;
-
- k = read(fd, p, nbytes);
- if (k < 0) {
- int errsv = errno;
-
- if (errsv == EINTR)
- continue;
-
- if (errsv == EAGAIN && do_poll) {
- /* We knowingly ignore any return value here,
- * and expect that any error/EOF is reported
- * via read() */
-
- (void) nm_utils_fd_wait_for_event(fd, POLLIN, -1);
- continue;
- }
-
- return n > 0 ? n : -NM_ERRNO_NATIVE(errsv);
- }
-
- if (k == 0)
- return n;
-
- g_assert((size_t) k <= nbytes);
-
- p += k;
- nbytes -= k;
- n += k;
- } while (nbytes > 0);
-
- return n;
-}
-
-/* taken from systemd's loop_read_exact() */
-int
-nm_utils_fd_read_loop_exact(int fd, void *buf, size_t nbytes, bool do_poll)
-{
- ssize_t n;
-
- n = nm_utils_fd_read_loop(fd, buf, nbytes, do_poll);
- if (n < 0)
- return (int) n;
- if ((size_t) n != nbytes)
- return -EIO;
-
- return 0;
-}
-
-/*****************************************************************************/
-
-void
-nm_utils_named_value_clear_with_g_free(NMUtilsNamedValue *val)
-{
- if (val) {
- gs_free gpointer x_name = NULL;
- gs_free gpointer x_value = NULL;
-
- x_name = (gpointer) g_steal_pointer(&val->name);
- x_value = g_steal_pointer(&val->value_ptr);
- }
-}
-
-G_STATIC_ASSERT(G_STRUCT_OFFSET(NMUtilsNamedValue, name) == 0);
-
-NMUtilsNamedValue *
-nm_utils_named_values_from_strdict_full(GHashTable * hash,
- guint * out_len,
- GCompareDataFunc compare_func,
- gpointer user_data,
- NMUtilsNamedValue * provided_buffer,
- guint provided_buffer_len,
- NMUtilsNamedValue **out_allocated_buffer)
-{
- GHashTableIter iter;
- NMUtilsNamedValue *values;
- guint i, len;
-
- nm_assert(provided_buffer_len == 0 || provided_buffer);
- nm_assert(!out_allocated_buffer || !*out_allocated_buffer);
-
- if (!hash || !(len = g_hash_table_size(hash))) {
- NM_SET_OUT(out_len, 0);
- return NULL;
- }
-
- if (provided_buffer_len >= len + 1) {
- /* the buffer provided by the caller is large enough. Use it. */
- values = provided_buffer;
- } else {
- /* allocate a new buffer. */
- values = g_new(NMUtilsNamedValue, len + 1);
- NM_SET_OUT(out_allocated_buffer, values);
- }
-
- i = 0;
- g_hash_table_iter_init(&iter, hash);
- while (g_hash_table_iter_next(&iter, (gpointer *) &values[i].name, &values[i].value_ptr))
- i++;
- nm_assert(i == len);
- values[i].name = NULL;
- values[i].value_ptr = NULL;
-
- if (compare_func)
- nm_utils_named_value_list_sort(values, len, compare_func, user_data);
-
- NM_SET_OUT(out_len, len);
- return values;
-}
-
-gssize
-nm_utils_named_value_list_find(const NMUtilsNamedValue *arr,
- gsize len,
- const char * name,
- gboolean sorted)
-{
- gsize i;
-
- nm_assert(name);
-
-#if NM_MORE_ASSERTS > 5
- {
- for (i = 0; i < len; i++) {
- const NMUtilsNamedValue *v = &arr[i];
-
- nm_assert(v->name);
- if (sorted && i > 0)
- nm_assert(strcmp(arr[i - 1].name, v->name) < 0);
- }
- }
-
- nm_assert(!sorted || nm_utils_named_value_list_is_sorted(arr, len, FALSE, NULL, NULL));
-#endif
-
- if (sorted) {
- return nm_utils_array_find_binary_search(arr,
- sizeof(NMUtilsNamedValue),
- len,
- &name,
- nm_strcmp_p_with_data,
- NULL);
- }
- for (i = 0; i < len; i++) {
- if (nm_streq(arr[i].name, name))
- return i;
- }
- return ~((gssize) len);
-}
-
-gboolean
-nm_utils_named_value_list_is_sorted(const NMUtilsNamedValue *arr,
- gsize len,
- gboolean accept_duplicates,
- GCompareDataFunc compare_func,
- gpointer user_data)
-{
- gsize i;
- int c_limit;
-
- if (len == 0)
- return TRUE;
-
- g_return_val_if_fail(arr, FALSE);
-
- if (!compare_func)
- compare_func = nm_strcmp_p_with_data;
-
- c_limit = accept_duplicates ? 0 : -1;
-
- for (i = 1; i < len; i++) {
- int c;
-
- c = compare_func(&arr[i - 1], &arr[i], user_data);
- if (c > c_limit)
- return FALSE;
- }
- return TRUE;
-}
-
-void
-nm_utils_named_value_list_sort(NMUtilsNamedValue *arr,
- gsize len,
- GCompareDataFunc compare_func,
- gpointer user_data)
-{
- if (len == 0)
- return;
-
- g_return_if_fail(arr);
-
- if (len == 1)
- return;
-
- g_qsort_with_data(arr,
- len,
- sizeof(NMUtilsNamedValue),
- compare_func ?: nm_strcmp_p_with_data,
- user_data);
-}
-
-/*****************************************************************************/
-
-gpointer *
-nm_utils_hash_keys_to_array(GHashTable * hash,
- GCompareDataFunc compare_func,
- gpointer user_data,
- guint * out_len)
-{
- guint len;
- gpointer *keys;
-
- /* by convention, we never return an empty array. In that
- * case, always %NULL. */
- if (!hash || g_hash_table_size(hash) == 0) {
- NM_SET_OUT(out_len, 0);
- return NULL;
- }
-
- keys = g_hash_table_get_keys_as_array(hash, &len);
- if (len > 1 && compare_func) {
- g_qsort_with_data(keys, len, sizeof(gpointer), compare_func, user_data);
- }
- NM_SET_OUT(out_len, len);
- return keys;
-}
-
-gpointer *
-nm_utils_hash_values_to_array(GHashTable * hash,
- GCompareDataFunc compare_func,
- gpointer user_data,
- guint * out_len)
-{
- GHashTableIter iter;
- gpointer value;
- gpointer * arr;
- guint i, len;
-
- if (!hash || (len = g_hash_table_size(hash)) == 0u) {
- NM_SET_OUT(out_len, 0);
- return NULL;
- }
-
- arr = g_new(gpointer, ((gsize) len) + 1);
- i = 0;
- g_hash_table_iter_init(&iter, hash);
- while (g_hash_table_iter_next(&iter, NULL, (gpointer *) &value))
- arr[i++] = value;
-
- nm_assert(i == len);
- arr[len] = NULL;
-
- if (len > 1 && compare_func) {
- g_qsort_with_data(arr, len, sizeof(gpointer), compare_func, user_data);
- }
-
- NM_SET_OUT(out_len, len);
- return arr;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_utils_hashtable_equal:
- * @a: one #GHashTable
- * @b: other #GHashTable
- * @treat_null_as_empty: if %TRUE, when either @a or @b is %NULL, it is
- * treated like an empty hash. It means, a %NULL hash will compare equal
- * to an empty hash.
- * @equal_func: the equality function, for comparing the values.
- * If %NULL, the values are not compared. In that case, the function
- * only checks, if both dictionaries have the same keys -- according
- * to @b's key equality function.
- * Note that the values of @a will be passed as first argument
- * to @equal_func.
- *
- * Compares two hash tables, whether they have equal content.
- * This only makes sense, if @a and @b have the same key types and
- * the same key compare-function.
- *
- * Returns: %TRUE, if both dictionaries have the same content.
- */
-gboolean
-nm_utils_hashtable_equal(const GHashTable *a,
- const GHashTable *b,
- gboolean treat_null_as_empty,
- GEqualFunc equal_func)
-{
- guint n;
- GHashTableIter iter;
- gconstpointer key, v_a, v_b;
-
- if (a == b)
- return TRUE;
- if (!treat_null_as_empty) {
- if (!a || !b)
- return FALSE;
- }
-
- n = a ? g_hash_table_size((GHashTable *) a) : 0;
- if (n != (b ? g_hash_table_size((GHashTable *) b) : 0))
- return FALSE;
-
- if (n > 0) {
- g_hash_table_iter_init(&iter, (GHashTable *) a);
- while (g_hash_table_iter_next(&iter, (gpointer *) &key, (gpointer *) &v_a)) {
- if (!g_hash_table_lookup_extended((GHashTable *) b, key, NULL, (gpointer *) &v_b))
- return FALSE;
- if (equal_func && !equal_func(v_a, v_b))
- return FALSE;
- }
- }
-
- return TRUE;
-}
-
-static gboolean
-_utils_hashtable_equal(GHashTable * hash_a,
- GHashTable * hash_b,
- GCompareDataFunc cmp_values,
- gpointer user_data)
-{
- GHashTableIter h;
- gpointer a_key;
- gpointer a_val;
- gpointer b_val;
-
- nm_assert(hash_a);
- nm_assert(hash_b);
- nm_assert(hash_a != hash_b);
- nm_assert(g_hash_table_size(hash_a) == g_hash_table_size(hash_b));
-
- /* We rely on both hashes to have the same hash/equal function. Otherwise, we would have to iterate
- * both hashes and check whether all keys/values are present in the respective other hash (which
- * would be O(n^2), since we couldn't use the plain lookup function. That is not a useful thing
- * for this function. */
-
- g_hash_table_iter_init(&h, hash_a);
- while (g_hash_table_iter_next(&h, &a_key, &a_val)) {
- if (!g_hash_table_lookup_extended(hash_b, a_key, NULL, &b_val))
- return FALSE;
-
- if (!cmp_values) {
- /* we accept %NULL compare function to indicate that we don't care about the key. */
- continue;
- }
-
- if (cmp_values(a_val, b_val, user_data) != 0)
- return FALSE;
- }
-
- return TRUE;
-}
-
-/**
- * nm_utils_hashtable_cmp_equal:
- * @a: (allow-none): the hash table or %NULL
- * @b: (allow-none): the other hash table or %NULL
- * @cmp_values: (allow-none): if %NULL, only the keys
- * will be compared. Otherwise, this function is used to
- * check whether all keys are equal.
- * @user_data: the argument for @cmp_values.
- *
- * It is required that both @a and @b have the same hash and equals
- * function.
- *
- * Returns: %TRUE, if both keys have the same keys and (if
- * @cmp_values is given) all values are the same.
- */
-gboolean
-nm_utils_hashtable_cmp_equal(const GHashTable *a,
- const GHashTable *b,
- GCompareDataFunc cmp_values,
- gpointer user_data)
-{
- GHashTable *hash_a = (GHashTable *) a;
- GHashTable *hash_b = (GHashTable *) b;
- gboolean same;
- guint size;
-
- if (hash_a == hash_b)
- return TRUE;
-
- if (!hash_a || !hash_b)
- return FALSE;
-
- size = g_hash_table_size(hash_a);
- if (size != g_hash_table_size(hash_b))
- return FALSE;
-
- if (size == 0)
- return TRUE;
-
- same = _utils_hashtable_equal(hash_a, hash_b, cmp_values, user_data);
-
-#if NM_MORE_ASSERTS > 5
- nm_assert(same == _utils_hashtable_equal(hash_b, hash_a, cmp_values, user_data));
-#endif
-
- return same;
-}
-
-typedef struct {
- gpointer key;
- gpointer val;
-} HashTableCmpData;
-
-typedef struct {
- GCompareDataFunc cmp_keys;
- gpointer user_data;
-} HashTableUserData;
-
-static int
-_hashtable_cmp_func(gconstpointer a, gconstpointer b, gpointer user_data)
-{
- const HashTableUserData *d = user_data;
- const HashTableCmpData * d_a = *((const HashTableCmpData *const *) a);
- const HashTableCmpData * d_b = *((const HashTableCmpData *const *) b);
-
- NM_CMP_RETURN(d->cmp_keys(d_a, d_b, d->user_data));
- return 0;
-}
-
-/**
- * nm_utils_hashtable_cmp:
- * @a: (allow-none): the hash to compare. May be %NULL.
- * @b: (allow-none): the other hash to compare. May be %NULL.
- * @do_fast_precheck: if %TRUE, assume that the hashes are equal
- * and that it is worth calling nm_utils_hashtable_cmp_equal() first.
- * That requires, that both hashes have the same equals function
- * which is compatible with the @cmp_keys function.
- * @cmp_keys: the compare function for keys. Usually, the hash/equal function
- * of both hashes corresponds to this function. If you set @do_fast_precheck
- * to false, then this is not a requirement.
- * @cmp_values: (allow-none): if %NULL, only the keys are compared.
- * Otherwise, the values must are also compared with this function.
- *
- * Both hashes must have keys/values of the same domain, so that
- * they can be effectively compared with @cmp_keys and @cmp_values.
- *
- * %NULL hashes compare equal to %NULL, but not to empty hashes.
- *
- * Returns: 0 if both hashes are equal, or -1 or 1 if one of the hashes
- * sorts before/after.
- */
-int
-nm_utils_hashtable_cmp(const GHashTable *a,
- const GHashTable *b,
- gboolean do_fast_precheck,
- GCompareDataFunc cmp_keys,
- GCompareDataFunc cmp_values,
- gpointer user_data)
-{
- GHashTable *hash_a = (GHashTable *) a;
- GHashTable *hash_b = (GHashTable *) b;
- gs_free HashTableCmpData *cmp_array_free = NULL;
- HashTableCmpData * cmp_array_a;
- HashTableCmpData * cmp_array_b;
- GHashTableIter h;
- gpointer i_key;
- gpointer i_val;
- gsize size2;
- guint size;
- guint i;
-
- nm_assert(cmp_keys);
-
- NM_CMP_SELF(hash_a, hash_b);
-
- size = g_hash_table_size(hash_a);
-
- NM_CMP_DIRECT(size, g_hash_table_size(hash_b));
-
- if (size == 0)
- return 0;
-
- if (do_fast_precheck) {
- gboolean same;
-
- /* we expect that the hashes are equal and the caller ensures us that they
- * use the same hash/equal functions. Do a fast path check first...
- *
- * It's unclear whether this is worth it. The full comparison is O(n*ln(n)),
- * while the fast check (using the hash lookup) is O(n). But then, the pre-check
- * makes additional requirements on the hash's hash/equal functions -- the
- * full comparison does not make such requirements. */
- same = _utils_hashtable_equal(hash_a, hash_b, cmp_values, user_data);
-#if NM_MORE_ASSERTS > 5
- nm_assert(same == _utils_hashtable_equal(hash_b, hash_a, cmp_values, user_data));
-#endif
- if (same)
- return 0;
- }
-
- size2 = ((gsize) size) * 2u;
- if (size2 > 600u / sizeof(HashTableCmpData)) {
- cmp_array_free = g_new(HashTableCmpData, size2);
- cmp_array_a = cmp_array_free;
- } else
- cmp_array_a = g_newa(HashTableCmpData, size2);
- cmp_array_b = &cmp_array_a[size];
-
- i = 0;
- g_hash_table_iter_init(&h, hash_a);
- while (g_hash_table_iter_next(&h, &i_key, &i_val)) {
- nm_assert(i < size);
- cmp_array_a[i++] = (HashTableCmpData){
- .key = i_key,
- .val = i_val,
- };
- }
- nm_assert(i == size);
-
- i = 0;
- g_hash_table_iter_init(&h, hash_b);
- while (g_hash_table_iter_next(&h, &i_key, &i_val)) {
- nm_assert(i < size);
- cmp_array_b[i++] = (HashTableCmpData){
- .key = i_key,
- .val = i_val,
- };
- }
- nm_assert(i == size);
-
- g_qsort_with_data(cmp_array_a,
- size,
- sizeof(HashTableCmpData),
- _hashtable_cmp_func,
- &((HashTableUserData){
- .cmp_keys = cmp_keys,
- .user_data = user_data,
- }));
-
- g_qsort_with_data(cmp_array_b,
- size,
- sizeof(HashTableCmpData),
- _hashtable_cmp_func,
- &((HashTableUserData){
- .cmp_keys = cmp_keys,
- .user_data = user_data,
- }));
-
- for (i = 0; i < size; i++) {
- NM_CMP_RETURN(cmp_keys(cmp_array_a[i].key, cmp_array_b[i].key, user_data));
- }
-
- if (cmp_values) {
- for (i = 0; i < size; i++) {
- NM_CMP_RETURN(cmp_values(cmp_array_a[i].val, cmp_array_b[i].val, user_data));
- }
- }
-
- /* the fast-precheck should have already told that the arrays are equal. */
- nm_assert(!do_fast_precheck);
-
- return 0;
-}
-
-char **
-nm_utils_strv_make_deep_copied(const char **strv)
-{
- gsize i;
-
- /* it takes a strv list, and copies each
- * strings. Note that this updates @strv *in-place*
- * and returns it. */
-
- if (!strv)
- return NULL;
- for (i = 0; strv[i]; i++)
- strv[i] = g_strdup(strv[i]);
-
- return (char **) strv;
-}
-
-char **
-nm_utils_strv_make_deep_copied_n(const char **strv, gsize len)
-{
- gsize i;
-
- /* it takes a strv array with len elements, and copies each
- * strings. Note that this updates @strv *in-place*
- * and returns it. */
-
- if (!strv)
- return NULL;
- for (i = 0; i < len; i++)
- strv[i] = g_strdup(strv[i]);
-
- return (char **) strv;
-}
-
-/**
- * @strv: the strv array to copy. It may be %NULL if @len
- * is negative or zero (in which case %NULL will be returned).
- * @len: the length of strings in @str. If negative, strv is assumed
- * to be a NULL terminated array.
- * @deep_copied: if %TRUE, clones the individual strings. In that case,
- * the returned array must be freed with g_strfreev(). Otherwise, the
- * strings themself are not copied. You must take care of who owns the
- * strings yourself.
- *
- * Like g_strdupv(), with two differences:
- *
- * - accepts a @len parameter for non-null terminated strv array.
- *
- * - this never returns an empty strv array, but always %NULL if
- * there are no strings.
- *
- * Note that if @len is non-negative, then it still must not
- * contain any %NULL pointers within the first @len elements.
- * Otherwise, you would leak elements if you try to free the
- * array with g_strfreev(). Allowing that would be error prone.
- *
- * Returns: (transfer full): a clone of the strv array. Always
- * %NULL terminated. Depending on @deep_copied, the strings are
- * cloned or not.
- */
-char **
-_nm_utils_strv_dup(const char *const *strv, gssize len, gboolean deep_copied)
-{
- gsize i, l;
- char **v;
-
- if (len < 0)
- l = NM_PTRARRAY_LEN(strv);
- else
- l = len;
- if (l == 0) {
- /* this function never returns an empty strv array. If you
- * need that, handle it yourself. */
- return NULL;
- }
-
- v = g_new(char *, l + 1);
- for (i = 0; i < l; i++) {
- if (G_UNLIKELY(!strv[i])) {
- /* NULL strings are not allowed. Clear the remainder of the array
- * and return it (with assertion failure). */
- l++;
- for (; i < l; i++)
- v[i] = NULL;
- g_return_val_if_reached(v);
- }
-
- if (deep_copied)
- v[i] = g_strdup(strv[i]);
- else
- v[i] = (char *) strv[i];
- }
- v[l] = NULL;
- return v;
-}
-
-const char **
-_nm_utils_strv_dup_packed(const char *const *strv, gssize len)
-
-{
- gs_free gsize *str_len_free = NULL;
- gsize * str_len;
- const char ** result;
- gsize mem_len;
- gsize pre_len;
- gsize len2;
- char * sbuf;
- gsize i;
-
- nm_assert(len >= -1);
-
- if (G_LIKELY(len < 0)) {
- if (!strv || !strv[0]) {
- /* This function never returns an empty strv array. If you need that, handle it
- * yourself. */
- return NULL;
- }
- len2 = NM_PTRARRAY_LEN(strv);
- } else {
- if (len == 0)
- return NULL;
- len2 = len;
- }
-
- if (len2 > 300u / sizeof(gsize)) {
- str_len_free = g_new(gsize, len2);
- str_len = str_len_free;
- } else
- str_len = g_newa(gsize, len2);
-
- mem_len = 0;
- for (i = 0; i < len2; i++) {
- gsize l;
-
- if (G_LIKELY(strv[i]))
- l = strlen(strv[i]) + 1u;
- else
- l = 0;
- str_len[i] = l;
- mem_len += l;
- }
-
- pre_len = sizeof(const char *) * (len2 + 1u);
-
- result = g_malloc(pre_len + mem_len);
- sbuf = &(((char *) result)[pre_len]);
- for (i = 0; i < len2; i++) {
- gsize l;
-
- if (G_UNLIKELY(!strv[i])) {
- /* Technically there is no problem with accepting NULL strings. But that
- * does not really result in a strv array, and likely this only happens due
- * to a bug. We want to catch such bugs by asserting.
- *
- * We clear the remainder of the buffer and fail with an assertion. */
- len2++;
- for (; i < len2; i++)
- result[i] = NULL;
- g_return_val_if_reached(result);
- }
-
- result[i] = sbuf;
-
- l = str_len[i];
- memcpy(sbuf, strv[i], l);
- sbuf += l;
- }
- result[i] = NULL;
- nm_assert(i == len2);
- nm_assert(sbuf == (&((const char *) result)[pre_len]) + mem_len);
-
- return result;
-}
-
-/*****************************************************************************/
-
-gssize
-nm_utils_ptrarray_find_binary_search(gconstpointer * list,
- gsize len,
- gconstpointer needle,
- GCompareDataFunc cmpfcn,
- gpointer user_data,
- gssize * out_idx_first,
- gssize * out_idx_last)
-{
- gssize imin, imax, imid, i2min, i2max, i2mid;
- int cmp;
-
- g_return_val_if_fail(list || !len, ~((gssize) 0));
- g_return_val_if_fail(cmpfcn, ~((gssize) 0));
-
- imin = 0;
- if (len > 0) {
- imax = len - 1;
-
- while (imin <= imax) {
- imid = imin + (imax - imin) / 2;
-
- cmp = cmpfcn(list[imid], needle, user_data);
- if (cmp == 0) {
- /* we found a matching entry at index imid.
- *
- * Does the caller request the first/last index as well (in case that
- * there are multiple entries which compare equal). */
-
- if (out_idx_first) {
- i2min = imin;
- i2max = imid + 1;
- while (i2min <= i2max) {
- i2mid = i2min + (i2max - i2min) / 2;
-
- cmp = cmpfcn(list[i2mid], needle, user_data);
- if (cmp == 0)
- i2max = i2mid - 1;
- else {
- nm_assert(cmp < 0);
- i2min = i2mid + 1;
- }
- }
- *out_idx_first = i2min;
- }
- if (out_idx_last) {
- i2min = imid + 1;
- i2max = imax;
- while (i2min <= i2max) {
- i2mid = i2min + (i2max - i2min) / 2;
-
- cmp = cmpfcn(list[i2mid], needle, user_data);
- if (cmp == 0)
- i2min = i2mid + 1;
- else {
- nm_assert(cmp > 0);
- i2max = i2mid - 1;
- }
- }
- *out_idx_last = i2min - 1;
- }
- return imid;
- }
-
- if (cmp < 0)
- imin = imid + 1;
- else
- imax = imid - 1;
- }
- }
-
- /* return the inverse of @imin. This is a negative number, but
- * also is ~imin the position where the value should be inserted. */
- imin = ~imin;
- NM_SET_OUT(out_idx_first, imin);
- NM_SET_OUT(out_idx_last, imin);
- return imin;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_utils_array_find_binary_search:
- * @list: the list to search. It must be sorted according to @cmpfcn ordering.
- * @elem_size: the size in bytes of each element in the list
- * @len: the number of elements in @list
- * @needle: the value that is searched
- * @cmpfcn: the compare function. The elements @list are passed as first
- * argument to @cmpfcn, while @needle is passed as second. Usually, the
- * needle is the same data type as inside the list, however, that is
- * not necessary, as long as @cmpfcn takes care to cast the two arguments
- * accordingly.
- * @user_data: optional argument passed to @cmpfcn
- *
- * Performs binary search for @needle in @list. On success, returns the
- * (non-negative) index where the compare function found the searched element.
- * On success, it returns a negative value. Note that the return negative value
- * is the bitwise inverse of the position where the element should be inserted.
- *
- * If the list contains multiple matching elements, an arbitrary index is
- * returned.
- *
- * Returns: the index to the element in the list, or the (negative, bitwise inverted)
- * position where it should be.
- */
-gssize
-nm_utils_array_find_binary_search(gconstpointer list,
- gsize elem_size,
- gsize len,
- gconstpointer needle,
- GCompareDataFunc cmpfcn,
- gpointer user_data)
-{
- gssize imin, imax, imid;
- int cmp;
-
- g_return_val_if_fail(list || !len, ~((gssize) 0));
- g_return_val_if_fail(cmpfcn, ~((gssize) 0));
- g_return_val_if_fail(elem_size > 0, ~((gssize) 0));
-
- imin = 0;
- if (len == 0)
- return ~imin;
-
- imax = len - 1;
-
- while (imin <= imax) {
- imid = imin + (imax - imin) / 2;
-
- cmp = cmpfcn(&((const char *) list)[elem_size * imid], needle, user_data);
- if (cmp == 0)
- return imid;
-
- if (cmp < 0)
- imin = imid + 1;
- else
- imax = imid - 1;
- }
-
- /* return the inverse of @imin. This is a negative number, but
- * also is ~imin the position where the value should be inserted. */
- return ~imin;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_utils_get_start_time_for_pid:
- * @pid: the process identifier
- * @out_state: return the state character, like R, S, Z. See `man 5 proc`.
- * @out_ppid: parent process id
- *
- * Originally copied from polkit source (src/polkit/polkitunixprocess.c)
- * and adjusted.
- *
- * Returns: the timestamp when the process started (by parsing /proc/$PID/stat).
- * If an error occurs (e.g. the process does not exist), 0 is returned.
- *
- * The returned start time counts since boot, in the unit HZ (with HZ usually being (1/100) seconds)
- **/
-guint64
-nm_utils_get_start_time_for_pid(pid_t pid, char *out_state, pid_t *out_ppid)
-{
- guint64 start_time;
- char filename[256];
- gs_free char * contents = NULL;
- size_t length;
- gs_free const char **tokens = NULL;
- char * p;
- char state = ' ';
- gint64 ppid = 0;
-
- start_time = 0;
- contents = NULL;
-
- g_return_val_if_fail(pid > 0, 0);
-
- G_STATIC_ASSERT_EXPR(sizeof(GPid) >= sizeof(pid_t));
-
- nm_sprintf_buf(filename, "/proc/%" G_PID_FORMAT "/stat", (GPid) pid);
-
- if (!g_file_get_contents(filename, &contents, &length, NULL))
- goto fail;
-
- /* start time is the token at index 19 after the '(process name)' entry - since only this
- * field can contain the ')' character, search backwards for this to avoid malicious
- * processes trying to fool us
- */
- p = strrchr(contents, ')');
- if (!p)
- goto fail;
- p += 2; /* skip ') ' */
- if (p - contents >= (int) length)
- goto fail;
-
- state = p[0];
-
- tokens = nm_utils_strsplit_set(p, " ");
-
- if (NM_PTRARRAY_LEN(tokens) < 20)
- goto fail;
-
- if (out_ppid) {
- ppid = _nm_utils_ascii_str_to_int64(tokens[1], 10, 1, G_MAXINT, 0);
- if (ppid == 0)
- goto fail;
- }
-
- start_time = _nm_utils_ascii_str_to_int64(tokens[19], 10, 1, G_MAXINT64, 0);
- if (start_time == 0)
- goto fail;
-
- NM_SET_OUT(out_state, state);
- NM_SET_OUT(out_ppid, ppid);
- return start_time;
-
-fail:
- NM_SET_OUT(out_state, ' ');
- NM_SET_OUT(out_ppid, 0);
- return 0;
-}
-
-/*****************************************************************************/
-
-/**
- * _nm_utils_strv_sort:
- * @strv: pointer containing strings that will be sorted
- * in-place, %NULL is allowed, unless @len indicates
- * that there are more elements.
- * @len: the number of elements in strv. If negative,
- * strv must be a NULL terminated array and the length
- * will be calculated first. If @len is a positive
- * number, @strv is allowed to contain %NULL strings
- * too.
- *
- * Ascending sort of the array @strv inplace, using plain strcmp() string
- * comparison.
- */
-void
-_nm_utils_strv_sort(const char **strv, gssize len)
-{
- GCompareDataFunc cmp;
- gsize l;
-
- if (len < 0) {
- l = NM_PTRARRAY_LEN(strv);
- cmp = nm_strcmp_p_with_data;
- } else {
- l = len;
- cmp = nm_strcmp0_p_with_data;
- }
-
- if (l <= 1)
- return;
-
- nm_assert(l <= (gsize) G_MAXINT);
-
- g_qsort_with_data(strv, l, sizeof(const char *), cmp, NULL);
-}
-
-/**
- * _nm_utils_strv_cmp_n:
- * @strv1: a string array
- * @len1: the length of @strv1, or -1 for NULL terminated array.
- * @strv2: a string array
- * @len2: the length of @strv2, or -1 for NULL terminated array.
- *
- * Note that
- * - len == -1 && strv == NULL
- * is treated like a %NULL argument and compares differently from
- * other arrays.
- *
- * Note that an empty array can be represented as
- * - len == -1 && strv && !strv[0]
- * - len == 0 && !strv
- * - len == 0 && strv
- * These 3 forms all compare equal.
- * It also means, if length is 0, then it is permissible for strv to be %NULL.
- *
- * The strv arrays may contain %NULL strings (if len is positive).
- *
- * 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)
-{
- gsize n, n2;
-
- if (len1 < 0) {
- if (!strv1)
- return (len2 < 0 && !strv2) ? 0 : -1;
- n = NM_PTRARRAY_LEN(strv1);
- } else
- n = len1;
-
- if (len2 < 0) {
- if (!strv2)
- return 1;
- n2 = NM_PTRARRAY_LEN(strv2);
- } else
- n2 = len2;
-
- NM_CMP_DIRECT(n, n2);
- for (; n > 0; n--, strv1++, strv2++)
- NM_CMP_DIRECT_STRCMP0(*strv1, *strv2);
- return 0;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_utils_g_slist_find_str:
- * @list: the #GSList with NUL terminated strings to search
- * @needle: the needle string to look for.
- *
- * Search the list for @needle and return the first found match
- * (or %NULL if not found). Uses strcmp() for finding the first matching
- * element.
- *
- * Returns: the #GSList element with @needle as string value or
- * %NULL if not found.
- */
-GSList *
-nm_utils_g_slist_find_str(const GSList *list, const char *needle)
-{
- nm_assert(needle);
-
- for (; list; list = list->next) {
- nm_assert(list->data);
- if (nm_streq(list->data, needle))
- return (GSList *) list;
- }
- return NULL;
-}
-
-/**
- * nm_utils_g_slist_strlist_cmp:
- * @a: the left #GSList of strings
- * @b: the right #GSList of strings to compare.
- *
- * Compares two string lists. The data elements are compared with
- * strcmp(), allowing %NULL elements.
- *
- * Returns: 0, 1, or -1, depending on how the lists compare.
- */
-int
-nm_utils_g_slist_strlist_cmp(const GSList *a, const GSList *b)
-{
- while (TRUE) {
- if (!a)
- return !b ? 0 : -1;
- if (!b)
- return 1;
- NM_CMP_DIRECT_STRCMP0(a->data, b->data);
- a = a->next;
- b = b->next;
- }
-}
-
-char *
-nm_utils_g_slist_strlist_join(const GSList *a, const char *separator)
-{
- GString *str = NULL;
-
- if (!a)
- return NULL;
-
- for (; a; a = a->next) {
- if (!str)
- str = g_string_new(NULL);
- else
- g_string_append(str, separator);
- g_string_append(str, a->data);
- }
- return g_string_free(str, FALSE);
-}
-
-/*****************************************************************************/
-
-NMUtilsUserData *
-_nm_utils_user_data_pack(int nargs, gconstpointer *args)
-{
- int i;
- gpointer *data;
-
- nm_assert(nargs > 0);
- nm_assert(args);
-
- data = g_slice_alloc(((gsize) nargs) * sizeof(gconstpointer));
- for (i = 0; i < nargs; i++)
- data[i] = (gpointer) args[i];
- return (NMUtilsUserData *) data;
-}
-
-void
-_nm_utils_user_data_unpack(NMUtilsUserData *user_data, int nargs, ...)
-{
- gpointer *data = (gpointer *) user_data;
- va_list ap;
- int i;
-
- nm_assert(data);
- nm_assert(nargs > 0);
-
- va_start(ap, nargs);
- for (i = 0; i < nargs; i++) {
- gpointer *dst;
-
- dst = va_arg(ap, gpointer *);
- nm_assert(dst);
-
- *dst = data[i];
- }
- va_end(ap);
-
- g_slice_free1(((gsize) nargs) * sizeof(gconstpointer), data);
-}
-
-/*****************************************************************************/
-
-typedef struct {
- gpointer callback_user_data;
- GCancellable * cancellable;
- GSource * source;
- NMUtilsInvokeOnIdleCallback callback;
- gulong cancelled_id;
-} InvokeOnIdleData;
-
-static gboolean
-_nm_utils_invoke_on_idle_cb_idle(gpointer user_data)
-{
- InvokeOnIdleData *data = user_data;
-
- nm_clear_g_signal_handler(data->cancellable, &data->cancelled_id);
-
- data->callback(data->callback_user_data, data->cancellable);
-
- nm_g_object_unref(data->cancellable);
- g_source_destroy(data->source);
- nm_g_slice_free(data);
- return G_SOURCE_REMOVE;
-}
-
-static void
-_nm_utils_invoke_on_idle_cb_cancelled(GCancellable *cancellable, InvokeOnIdleData *data)
-{
- /* on cancellation, we invoke the callback synchronously. */
- nm_clear_g_signal_handler(data->cancellable, &data->cancelled_id);
- nm_clear_g_source_inst(&data->source);
- data->callback(data->callback_user_data, data->cancellable);
- nm_g_object_unref(data->cancellable);
- nm_g_slice_free(data);
-}
-
-static void
-_nm_utils_invoke_on_idle_start(gboolean use_timeout,
- guint timeout_msec,
- GCancellable * cancellable,
- NMUtilsInvokeOnIdleCallback callback,
- gpointer callback_user_data)
-{
- InvokeOnIdleData *data;
- GSource * source;
-
- g_return_if_fail(callback);
-
- data = g_slice_new(InvokeOnIdleData);
- *data = (InvokeOnIdleData){
- .callback = callback,
- .callback_user_data = callback_user_data,
- .cancellable = nm_g_object_ref(cancellable),
- .cancelled_id = 0,
- };
-
- if (cancellable) {
- if (g_cancellable_is_cancelled(cancellable)) {
- /* the cancellable is already cancelled. We ignore the timeout
- * and always schedule an idle action. */
- use_timeout = FALSE;
- } else {
- /* if we are passed a non-cancelled cancellable, we register to the "cancelled"
- * signal an invoke the callback synchronously (from the signal handler).
- *
- * We don't do that,
- * - if the cancellable is already cancelled (because we don't want to invoke
- * the callback synchronously from the caller).
- * - if we have no cancellable at hand. */
- data->cancelled_id = g_signal_connect(cancellable,
- "cancelled",
- G_CALLBACK(_nm_utils_invoke_on_idle_cb_cancelled),
- data);
- }
- }
-
- if (use_timeout) {
- source = nm_g_timeout_source_new(timeout_msec,
- G_PRIORITY_DEFAULT,
- _nm_utils_invoke_on_idle_cb_idle,
- data,
- NULL);
- } else {
- source =
- nm_g_idle_source_new(G_PRIORITY_DEFAULT, _nm_utils_invoke_on_idle_cb_idle, data, NULL);
- }
-
- /* use the current thread default context. */
- g_source_attach(source, g_main_context_get_thread_default());
-
- data->source = source;
-}
-
-void
-nm_utils_invoke_on_idle(GCancellable * cancellable,
- NMUtilsInvokeOnIdleCallback callback,
- gpointer callback_user_data)
-{
- _nm_utils_invoke_on_idle_start(FALSE, 0, cancellable, callback, callback_user_data);
-}
-
-void
-nm_utils_invoke_on_timeout(guint timeout_msec,
- GCancellable * cancellable,
- NMUtilsInvokeOnIdleCallback callback,
- gpointer callback_user_data)
-{
- _nm_utils_invoke_on_idle_start(TRUE, timeout_msec, cancellable, callback, callback_user_data);
-}
-
-/*****************************************************************************/
-
-int
-nm_utils_getpagesize(void)
-{
- static volatile int val = 0;
- long l;
- int v;
-
- v = g_atomic_int_get(&val);
-
- if (G_UNLIKELY(v == 0)) {
- l = sysconf(_SC_PAGESIZE);
-
- g_return_val_if_fail(l > 0 && l < G_MAXINT, 4 * 1024);
-
- v = (int) l;
- if (!g_atomic_int_compare_and_exchange(&val, 0, v)) {
- v = g_atomic_int_get(&val);
- g_return_val_if_fail(v > 0, 4 * 1024);
- }
- }
-
- nm_assert(v > 0);
-#if NM_MORE_ASSERTS > 5
- nm_assert(v == getpagesize());
- nm_assert(v == sysconf(_SC_PAGESIZE));
-#endif
-
- return v;
-}
-
-gboolean
-nm_utils_memeqzero(gconstpointer data, gsize length)
-{
- const unsigned char *p = data;
- int len;
-
- /* Taken from https://github.com/rustyrussell/ccan/blob/9d2d2c49f053018724bcc6e37029da10b7c3d60d/ccan/mem/mem.c#L92,
- * CC-0 licensed. */
-
- /* Check first 16 bytes manually */
- for (len = 0; len < 16; len++) {
- if (!length)
- return TRUE;
- if (*p)
- return FALSE;
- p++;
- length--;
- }
-
- /* Now we know that's zero, memcmp with self. */
- return memcmp(data, p, length) == 0;
-}
-
-/**
- * nm_utils_bin2hexstr_full:
- * @addr: pointer of @length bytes. If @length is zero, this may
- * also be %NULL.
- * @length: number of bytes in @addr. May also be zero, in which
- * case this will return an empty string.
- * @delimiter: either '\0', otherwise the output string will have the
- * given delimiter character between each two hex numbers.
- * @upper_case: if TRUE, use upper case ASCII characters for hex.
- * @out: if %NULL, the function will allocate a new buffer of
- * either (@length*2+1) or (@length*3) bytes, depending on whether
- * a @delimiter is specified. In that case, the allocated buffer will
- * be returned and must be freed by the caller.
- * If not %NULL, the buffer must already be preallocated and contain
- * at least (@length*2+1) or (@length*3) bytes, depending on the delimiter.
- * If @length is zero, then of course at least one byte will be allocated
- * or @out (if given) must contain at least room for the trailing NUL byte.
- *
- * Returns: the binary value converted to a hex string. If @out is given,
- * this always returns @out. If @out is %NULL, a newly allocated string
- * is returned. This never returns %NULL, for buffers of length zero
- * an empty string is returned.
- */
-char *
-nm_utils_bin2hexstr_full(gconstpointer addr,
- gsize length,
- char delimiter,
- gboolean upper_case,
- char * out)
-{
- const guint8 *in = addr;
- const char * LOOKUP = upper_case ? "0123456789ABCDEF" : "0123456789abcdef";
- char * out0;
-
- if (out)
- out0 = out;
- else {
- out0 = out =
- g_new(char, length == 0 ? 1u : (delimiter == '\0' ? length * 2u + 1u : length * 3u));
- }
-
- /* @out must contain at least @length*3 bytes if @delimiter is set,
- * otherwise, @length*2+1. */
-
- if (length > 0) {
- nm_assert(in);
- for (;;) {
- const guint8 v = *in++;
-
- *out++ = LOOKUP[v >> 4];
- *out++ = LOOKUP[v & 0x0F];
- length--;
- if (!length)
- break;
- if (delimiter)
- *out++ = delimiter;
- }
- }
-
- *out = '\0';
- return out0;
-}
-
-guint8 *
-nm_utils_hexstr2bin_full(const char *hexstr,
- gboolean allow_0x_prefix,
- gboolean delimiter_required,
- gboolean hexdigit_pairs_required,
- const char *delimiter_candidates,
- gsize required_len,
- guint8 * buffer,
- gsize buffer_len,
- gsize * out_len)
-{
- const char *in = hexstr;
- guint8 * out = buffer;
- gboolean delimiter_has = TRUE;
- guint8 delimiter = '\0';
- gsize len;
-
- nm_assert(hexstr);
- nm_assert(buffer);
- nm_assert(required_len > 0 || out_len);
-
- if (allow_0x_prefix && in[0] == '0' && in[1] == 'x')
- in += 2;
-
- while (TRUE) {
- const guint8 d1 = in[0];
- guint8 d2;
- int i1, i2;
-
- i1 = nm_utils_hexchar_to_int(d1);
- if (i1 < 0)
- goto fail;
-
- /* If there's no leading zero (ie "aa:b:cc") then fake it */
- d2 = in[1];
- if (d2 && (i2 = nm_utils_hexchar_to_int(d2)) >= 0) {
- *out++ = (i1 << 4) + i2;
- d2 = in[2];
- if (!d2)
- break;
- in += 2;
- } else {
- /* Fake leading zero */
- *out++ = i1;
- if (!d2) {
- if (!delimiter_has || hexdigit_pairs_required) {
- /* when using no delimiter, there must be pairs of hex chars */
- goto fail;
- }
- break;
- } else if (hexdigit_pairs_required)
- goto fail;
- in += 1;
- }
-
- if (--buffer_len == 0)
- goto fail;
-
- if (delimiter_has) {
- if (d2 != delimiter) {
- if (delimiter)
- goto fail;
- if (delimiter_candidates) {
- while (delimiter_candidates[0]) {
- if (delimiter_candidates++[0] == d2)
- delimiter = d2;
- }
- }
- if (!delimiter) {
- if (delimiter_required)
- goto fail;
- delimiter_has = FALSE;
- continue;
- }
- }
- in++;
- }
- }
-
- len = out - buffer;
- if (required_len == 0 || len == required_len) {
- NM_SET_OUT(out_len, len);
- return buffer;
- }
-
-fail:
- NM_SET_OUT(out_len, 0);
- return NULL;
-}
-
-guint8 *
-nm_utils_hexstr2bin_alloc(const char *hexstr,
- gboolean allow_0x_prefix,
- gboolean delimiter_required,
- const char *delimiter_candidates,
- gsize required_len,
- gsize * out_len)
-{
- guint8 *buffer;
- gsize buffer_len, len;
-
- if (G_UNLIKELY(!hexstr)) {
- NM_SET_OUT(out_len, 0);
- g_return_val_if_fail(hexstr, NULL);
- }
-
- nm_assert(required_len > 0 || out_len);
-
- if (allow_0x_prefix && hexstr[0] == '0' && hexstr[1] == 'x')
- hexstr += 2;
-
- if (!hexstr[0])
- goto fail;
-
- if (required_len > 0)
- buffer_len = required_len;
- else
- buffer_len = strlen(hexstr) / 2 + 3;
-
- buffer = g_malloc(buffer_len);
-
- if (nm_utils_hexstr2bin_full(hexstr,
- FALSE,
- delimiter_required,
- FALSE,
- delimiter_candidates,
- required_len,
- buffer,
- buffer_len,
- &len)) {
- NM_SET_OUT(out_len, len);
- return buffer;
- }
-
- g_free(buffer);
-
-fail:
- NM_SET_OUT(out_len, 0);
- return NULL;
-}
-
-/*****************************************************************************/
-
-GVariant *
-nm_utils_gvariant_vardict_filter(GVariant *src,
- gboolean (*filter_fcn)(const char *key,
- GVariant * val,
- char ** out_key,
- GVariant ** out_val,
- gpointer user_data),
- gpointer user_data)
-{
- GVariantIter iter;
- GVariantBuilder builder;
- const char * key;
- GVariant * val;
-
- g_return_val_if_fail(src && g_variant_is_of_type(src, G_VARIANT_TYPE_VARDICT), NULL);
- g_return_val_if_fail(filter_fcn, NULL);
-
- g_variant_builder_init(&builder, G_VARIANT_TYPE_VARDICT);
-
- g_variant_iter_init(&iter, src);
- while (g_variant_iter_next(&iter, "{&sv}", &key, &val)) {
- _nm_unused gs_unref_variant GVariant *val_free = val;
- gs_free char * key2 = NULL;
- gs_unref_variant GVariant *val2 = NULL;
-
- if (filter_fcn(key, val, &key2, &val2, user_data)) {
- g_variant_builder_add(&builder, "{sv}", key2 ?: key, val2 ?: val);
- }
- }
-
- return g_variant_builder_end(&builder);
-}
-
-static gboolean
-_gvariant_vardict_filter_drop_one(const char *key,
- GVariant * val,
- char ** out_key,
- GVariant ** out_val,
- gpointer user_data)
-{
- return !nm_streq(key, user_data);
-}
-
-GVariant *
-nm_utils_gvariant_vardict_filter_drop_one(GVariant *src, const char *key)
-{
- return nm_utils_gvariant_vardict_filter(src, _gvariant_vardict_filter_drop_one, (gpointer) key);
-}
-
-/*****************************************************************************/
-
-static gboolean
-debug_key_matches(const char *key, const char *token, guint length)
-{
- /* may not call GLib functions: see note in g_parse_debug_string() */
- for (; length; length--, key++, token++) {
- char k = (*key == '_') ? '-' : g_ascii_tolower(*key);
- char t = (*token == '_') ? '-' : g_ascii_tolower(*token);
-
- if (k != t)
- return FALSE;
- }
-
- return *key == '\0';
-}
-
-/**
- * nm_utils_parse_debug_string:
- * @string: the string to parse
- * @keys: the debug keys
- * @nkeys: number of entries in @keys
- *
- * Similar to g_parse_debug_string(), but does not special
- * case "help" or "all".
- *
- * Returns: the flags
- */
-guint
-nm_utils_parse_debug_string(const char *string, const GDebugKey *keys, guint nkeys)
-{
- guint i;
- guint result = 0;
- const char *q;
-
- if (string == NULL)
- return 0;
-
- while (*string) {
- q = strpbrk(string, ":;, \t");
- if (!q)
- q = string + strlen(string);
-
- for (i = 0; i < nkeys; i++) {
- if (debug_key_matches(keys[i].key, string, q - string))
- result |= keys[i].value;
- }
-
- string = q;
- if (*string)
- string++;
- }
-
- return result;
-}
-
-/*****************************************************************************/
-
-GSource *
-nm_g_idle_source_new(int priority,
- GSourceFunc func,
- gpointer user_data,
- GDestroyNotify destroy_notify)
-{
- GSource *source;
-
- source = g_idle_source_new();
- if (priority != G_PRIORITY_DEFAULT)
- g_source_set_priority(source, priority);
- g_source_set_callback(source, func, user_data, destroy_notify);
- return source;
-}
-
-GSource *
-nm_g_timeout_source_new(guint timeout_msec,
- int priority,
- GSourceFunc func,
- gpointer user_data,
- GDestroyNotify destroy_notify)
-{
- GSource *source;
-
- source = g_timeout_source_new(timeout_msec);
- if (priority != G_PRIORITY_DEFAULT)
- g_source_set_priority(source, priority);
- g_source_set_callback(source, func, user_data, destroy_notify);
- return source;
-}
-
-GSource *
-nm_g_timeout_source_new_seconds(guint timeout_sec,
- int priority,
- GSourceFunc func,
- gpointer user_data,
- GDestroyNotify destroy_notify)
-{
- GSource *source;
-
- source = g_timeout_source_new_seconds(timeout_sec);
- if (priority != G_PRIORITY_DEFAULT)
- g_source_set_priority(source, priority);
- g_source_set_callback(source, func, user_data, destroy_notify);
- return source;
-}
-
-GSource *
-nm_g_unix_signal_source_new(int signum,
- int priority,
- GSourceFunc handler,
- gpointer user_data,
- GDestroyNotify notify)
-{
- GSource *source;
-
- source = g_unix_signal_source_new(signum);
-
- if (priority != G_PRIORITY_DEFAULT)
- g_source_set_priority(source, priority);
- g_source_set_callback(source, handler, user_data, notify);
- return source;
-}
-
-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 *source;
-
- source = g_unix_fd_source_new(fd, io_condition);
-
- if (priority != G_PRIORITY_DEFAULT)
- g_source_set_priority(source, priority);
- g_source_set_callback(source, G_SOURCE_FUNC(source_func), user_data, destroy_notify);
- return source;
-}
-
-/*****************************************************************************/
-
-#define _CTX_LOG(fmt, ...) \
- G_STMT_START \
- { \
- if (FALSE) { \
- gint64 _ts = g_get_monotonic_time() / 100; \
- \
- g_printerr(">>>> [%" G_GINT64_FORMAT ".%05" G_GINT64_FORMAT "] [src:%p]: " fmt "\n", \
- _ts / 10000, \
- _ts % 10000, \
- (ctx_src), \
- ##__VA_ARGS__); \
- } \
- } \
- G_STMT_END
-
-typedef struct {
- int fd;
- guint events;
- guint registered_events;
- union {
- int one;
- int *many;
- } idx;
- gpointer tag;
- bool stale : 1;
- bool has_many_idx : 1;
-} PollData;
-
-typedef struct {
- GSource source;
- GMainContext *context;
- GHashTable * fds;
- GPollFD * fds_arr;
- guint fds_len;
- int max_priority;
- bool acquired : 1;
-} CtxIntegSource;
-
-static void
-_poll_data_free(gpointer user_data)
-{
- PollData *poll_data = user_data;
-
- if (poll_data->has_many_idx)
- g_free(poll_data->idx.many);
- nm_g_slice_free(poll_data);
-}
-
-static void
-_ctx_integ_source_reacquire(CtxIntegSource *ctx_src)
-{
- if (G_LIKELY(ctx_src->acquired && g_main_context_is_owner(ctx_src->context)))
- return;
-
- /* the parent context now iterates on a different thread.
- * We need to release and reacquire the inner context. */
-
- if (ctx_src->acquired)
- g_main_context_release(ctx_src->context);
-
- if (G_UNLIKELY(!g_main_context_acquire(ctx_src->context))) {
- /* Nobody is supposed to reacquire the context while we use it. This is a bug
- * of the user. */
- ctx_src->acquired = FALSE;
- g_return_if_reached();
- }
- ctx_src->acquired = TRUE;
-}
-
-static gboolean
-_ctx_integ_source_prepare(GSource *source, int *out_timeout)
-{
- CtxIntegSource *ctx_src = ((CtxIntegSource *) source);
- int max_priority;
- int timeout = -1;
- gboolean any_ready;
- GHashTableIter h_iter;
- PollData * poll_data;
- gboolean fds_changed;
- GPollFD new_fds_stack[300u / sizeof(GPollFD)];
- gs_free GPollFD *new_fds_heap = NULL;
- GPollFD * new_fds;
- guint new_fds_len;
- guint new_fds_alloc;
- guint i;
-
- _CTX_LOG("prepare...");
-
- _ctx_integ_source_reacquire(ctx_src);
-
- any_ready = g_main_context_prepare(ctx_src->context, &max_priority);
-
- new_fds_alloc = NM_MAX(G_N_ELEMENTS(new_fds_stack), ctx_src->fds_len);
-
- if (new_fds_alloc > G_N_ELEMENTS(new_fds_stack)) {
- new_fds_heap = g_new(GPollFD, new_fds_alloc);
- new_fds = new_fds_heap;
- } else
- new_fds = new_fds_stack;
-
- for (;;) {
- int l;
-
- nm_assert(new_fds_alloc <= (guint) G_MAXINT);
-
- l = g_main_context_query(ctx_src->context,
- max_priority,
- &timeout,
- new_fds,
- (int) new_fds_alloc);
- nm_assert(l >= 0);
-
- new_fds_len = (guint) l;
-
- if (G_LIKELY(new_fds_len <= new_fds_alloc))
- break;
-
- new_fds_alloc = new_fds_len;
- g_free(new_fds_heap);
- new_fds_heap = g_new(GPollFD, new_fds_alloc);
- new_fds = new_fds_heap;
- }
-
- fds_changed = FALSE;
- if (new_fds_len != ctx_src->fds_len)
- fds_changed = TRUE;
- else {
- for (i = 0; i < new_fds_len; i++) {
- if (new_fds[i].fd != ctx_src->fds_arr[i].fd
- || new_fds[i].events != ctx_src->fds_arr[i].events) {
- fds_changed = TRUE;
- break;
- }
- }
- }
-
- if (G_UNLIKELY(fds_changed)) {
- g_free(ctx_src->fds_arr);
- ctx_src->fds_len = new_fds_len;
- if (G_LIKELY(new_fds == new_fds_stack) || new_fds_alloc != new_fds_len)
- ctx_src->fds_arr = nm_memdup(new_fds, sizeof(*new_fds) * new_fds_len);
- else
- ctx_src->fds_arr = g_steal_pointer(&new_fds_heap);
-
- g_hash_table_iter_init(&h_iter, ctx_src->fds);
- while (g_hash_table_iter_next(&h_iter, (gpointer *) &poll_data, NULL))
- poll_data->stale = TRUE;
-
- for (i = 0; i < ctx_src->fds_len; i++) {
- const GPollFD *fd = &ctx_src->fds_arr[i];
-
- poll_data = g_hash_table_lookup(ctx_src->fds, &fd->fd);
-
- if (G_UNLIKELY(!poll_data)) {
- poll_data = g_slice_new(PollData);
- *poll_data = (PollData){
- .fd = fd->fd,
- .idx.one = i,
- .has_many_idx = FALSE,
- .events = fd->events,
- .registered_events = 0,
- .tag = NULL,
- .stale = FALSE,
- };
- g_hash_table_add(ctx_src->fds, poll_data);
- nm_assert(poll_data == g_hash_table_lookup(ctx_src->fds, &fd->fd));
- continue;
- }
-
- if (G_LIKELY(poll_data->stale)) {
- if (poll_data->has_many_idx) {
- g_free(poll_data->idx.many);
- poll_data->has_many_idx = FALSE;
- }
- poll_data->events = fd->events;
- poll_data->idx.one = i;
- poll_data->stale = FALSE;
- continue;
- }
-
- /* How odd. We have duplicate FDs. In fact, currently g_main_context_query() always
- * coalesces the FDs and this cannot happen. However, that is not documented behavior,
- * so we should not rely on that. So we need to keep a list of indexes... */
- poll_data->events |= fd->events;
- if (!poll_data->has_many_idx) {
- int idx0;
-
- idx0 = poll_data->idx.one;
- poll_data->has_many_idx = TRUE;
- poll_data->idx.many = g_new(int, 4);
- poll_data->idx.many[0] = 2; /* number allocated */
- poll_data->idx.many[1] = 2; /* number used */
- poll_data->idx.many[2] = idx0;
- poll_data->idx.many[3] = i;
- } else {
- if (poll_data->idx.many[0] == poll_data->idx.many[1]) {
- poll_data->idx.many[0] *= 2;
- poll_data->idx.many =
- g_realloc(poll_data->idx.many, sizeof(int) * (2 + poll_data->idx.many[0]));
- }
- poll_data->idx.many[2 + poll_data->idx.many[1]] = i;
- poll_data->idx.many[1]++;
- }
- }
-
- g_hash_table_iter_init(&h_iter, ctx_src->fds);
- while (g_hash_table_iter_next(&h_iter, (gpointer *) &poll_data, NULL)) {
- if (poll_data->stale) {
- nm_assert(poll_data->tag);
- nm_assert(poll_data->events == poll_data->registered_events);
- _CTX_LOG("prepare: remove poll fd=%d, events=0x%x",
- poll_data->fd,
- poll_data->events);
- g_source_remove_unix_fd(&ctx_src->source, poll_data->tag);
- g_hash_table_iter_remove(&h_iter);
- continue;
- }
- if (!poll_data->tag) {
- _CTX_LOG("prepare: add poll fd=%d, events=0x%x", poll_data->fd, poll_data->events);
- poll_data->registered_events = poll_data->events;
- poll_data->tag = g_source_add_unix_fd(&ctx_src->source,
- poll_data->fd,
- poll_data->registered_events);
- continue;
- }
- if (poll_data->registered_events != poll_data->events) {
- _CTX_LOG("prepare: update poll fd=%d, events=0x%x",
- poll_data->fd,
- poll_data->events);
- poll_data->registered_events = poll_data->events;
- g_source_modify_unix_fd(&ctx_src->source,
- poll_data->tag,
- poll_data->registered_events);
- }
- }
- }
-
- NM_SET_OUT(out_timeout, timeout);
- ctx_src->max_priority = max_priority;
-
- _CTX_LOG("prepare: done, any-ready=%d, timeout=%d, max-priority=%d",
- any_ready,
- timeout,
- max_priority);
-
- /* we always need to poll, because we have some file descriptors. */
- return FALSE;
-}
-
-static gboolean
-_ctx_integ_source_check(GSource *source)
-{
- CtxIntegSource *ctx_src = ((CtxIntegSource *) source);
- GHashTableIter h_iter;
- gboolean some_ready;
- PollData * poll_data;
-
- nm_assert(ctx_src->context);
-
- _CTX_LOG("check");
-
- _ctx_integ_source_reacquire(ctx_src);
-
- g_hash_table_iter_init(&h_iter, ctx_src->fds);
- while (g_hash_table_iter_next(&h_iter, (gpointer *) &poll_data, NULL)) {
- guint revents;
-
- revents = g_source_query_unix_fd(&ctx_src->source, poll_data->tag);
- if (G_UNLIKELY(poll_data->has_many_idx)) {
- int num = poll_data->idx.many[1];
- int *p_idx = &poll_data->idx.many[2];
-
- for (; num > 0; num--, p_idx++)
- ctx_src->fds_arr[*p_idx].revents = revents;
- } else
- ctx_src->fds_arr[poll_data->idx.one].revents = revents;
- }
-
- nm_assert(ctx_src->fds_len <= (guint) G_MAXINT);
-
- some_ready = g_main_context_check(ctx_src->context,
- ctx_src->max_priority,
- ctx_src->fds_arr,
- (int) ctx_src->fds_len);
-
- _CTX_LOG("check (some-ready=%d)...", some_ready);
-
- return some_ready;
-}
-
-static gboolean
-_ctx_integ_source_dispatch(GSource *source, GSourceFunc callback, gpointer user_data)
-{
- CtxIntegSource *ctx_src = ((CtxIntegSource *) source);
-
- nm_assert(ctx_src->context);
-
- _ctx_integ_source_reacquire(ctx_src);
-
- _CTX_LOG("dispatch");
-
- g_main_context_dispatch(ctx_src->context);
-
- return G_SOURCE_CONTINUE;
-}
-
-static void
-_ctx_integ_source_finalize(GSource *source)
-{
- CtxIntegSource *ctx_src = ((CtxIntegSource *) source);
- GHashTableIter h_iter;
- PollData * poll_data;
-
- g_return_if_fail(ctx_src->context);
-
- _CTX_LOG("finalize...");
-
- g_hash_table_iter_init(&h_iter, ctx_src->fds);
- while (g_hash_table_iter_next(&h_iter, (gpointer *) &poll_data, NULL)) {
- nm_assert(poll_data->tag);
- _CTX_LOG("prepare: remove poll fd=%d, events=0x%x", poll_data->fd, poll_data->events);
- g_source_remove_unix_fd(&ctx_src->source, poll_data->tag);
- g_hash_table_iter_remove(&h_iter);
- }
-
- nm_clear_pointer(&ctx_src->fds, g_hash_table_unref);
- nm_clear_g_free(&ctx_src->fds_arr);
- ctx_src->fds_len = 0;
-
- if (ctx_src->acquired) {
- ctx_src->acquired = FALSE;
- g_main_context_release(ctx_src->context);
- }
-
- nm_clear_pointer(&ctx_src->context, g_main_context_unref);
-}
-
-static GSourceFuncs ctx_integ_source_funcs = {
- .prepare = _ctx_integ_source_prepare,
- .check = _ctx_integ_source_check,
- .dispatch = _ctx_integ_source_dispatch,
- .finalize = _ctx_integ_source_finalize,
-};
-
-/**
- * nm_utils_g_main_context_create_integrate_source:
- * @inner_context: the inner context that will be integrated to an
- * outer #GMainContext.
- *
- * By integrating the inner context with an outer context, when iterating the outer
- * context sources on the inner context will be dispatched. Note that while the
- * created source exists, the @inner_context will be acquired. The user gets restricted
- * what to do with the inner context. In particular while the inner context is integrated,
- * the user should not acquire the inner context again or explicitly iterate it. What
- * the user of course still can (and wants to) do is attaching new sources to the inner
- * context.
- *
- * Note that GSource has a priority. While each context dispatches events based on
- * their source's priorities, the outer context dispatches to the inner context
- * only with one priority (the priority of the created source). That is, the sources
- * from the two contexts are kept separate and are not sorted by their priorities.
- *
- * Returns: a newly created GSource that should be attached to the
- * outer context.
- */
-GSource *
-nm_utils_g_main_context_create_integrate_source(GMainContext *inner_context)
-{
- CtxIntegSource *ctx_src;
-
- g_return_val_if_fail(inner_context, NULL);
-
- if (!g_main_context_acquire(inner_context)) {
- /* We require to acquire the context while it's integrated. We need to keep it acquired
- * for the entire duration.
- *
- * This is also necessary because g_source_attach() only wakes up the context, if
- * the context is currently acquired. */
- g_return_val_if_reached(NULL);
- }
-
- ctx_src = (CtxIntegSource *) g_source_new(&ctx_integ_source_funcs, sizeof(CtxIntegSource));
-
- g_source_set_name(&ctx_src->source, "ContextIntegrateSource");
-
- ctx_src->context = g_main_context_ref(inner_context);
- ctx_src->fds = g_hash_table_new_full(nm_pint_hash, nm_pint_equals, _poll_data_free, NULL);
- ctx_src->fds_len = 0;
- ctx_src->fds_arr = NULL;
- ctx_src->acquired = TRUE;
- ctx_src->max_priority = G_MAXINT;
-
- _CTX_LOG("create new integ-source for %p", inner_context);
-
- return &ctx_src->source;
-}
-
-/*****************************************************************************/
-
-void
-nm_utils_ifname_cpy(char *dst, const char *name)
-{
- int i;
-
- g_return_if_fail(dst);
- g_return_if_fail(name && name[0]);
-
- nm_assert(nm_utils_ifname_valid_kernel(name, NULL));
-
- /* ensures NUL padding of the entire IFNAMSIZ buffer. */
-
- for (i = 0; i < (int) IFNAMSIZ && name[i] != '\0'; i++)
- dst[i] = name[i];
-
- nm_assert(name[i] == '\0');
-
- for (; i < (int) IFNAMSIZ; i++)
- dst[i] = '\0';
-}
-
-/*****************************************************************************/
-
-gboolean
-nm_utils_ifname_valid_kernel(const char *name, GError **error)
-{
- int i;
-
- /* This function follows kernel's interface validation
- * function dev_valid_name() in net/core/dev.c.
- */
-
- if (!name) {
- g_set_error_literal(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- _("interface name is missing"));
- return FALSE;
- }
-
- if (name[0] == '\0') {
- g_set_error_literal(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- _("interface name is too short"));
- return FALSE;
- }
-
- if (name[0] == '.' && (name[1] == '\0' || (name[1] == '.' && name[2] == '\0'))) {
- g_set_error_literal(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- _("interface name is reserved"));
- return FALSE;
- }
-
- for (i = 0; i < IFNAMSIZ; i++) {
- char ch = name[i];
-
- if (ch == '\0')
- return TRUE;
- if (NM_IN_SET(ch, '/', ':') || g_ascii_isspace(ch)) {
- g_set_error_literal(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- _("interface name contains an invalid character"));
- return FALSE;
- }
- }
-
- g_set_error_literal(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- _("interface name is longer than 15 characters"));
- return FALSE;
-}
-
-/*****************************************************************************/
-
-static gboolean
-_nm_utils_ifname_valid_kernel(const char *name, GError **error)
-{
- if (!nm_utils_ifname_valid_kernel(name, error))
- return FALSE;
-
- if (strchr(name, '%')) {
- /* Kernel's dev_valid_name() accepts (almost) any binary up to 15 chars.
- * However, '%' is treated special as a format specifier. Try
- *
- * ip link add 'dummy%dx' type dummy
- *
- * Don't allow that for "connection.interface-name", which either
- * matches an existing netdev name (thus, it cannot have a '%') or
- * is used to configure a name (in which case we don't want kernel
- * to replace the format specifier). */
- g_set_error_literal(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- _("'%%' is not allowed in interface names"));
- return FALSE;
- }
-
- if (NM_IN_STRSET(name, "all", "default", "bonding_masters")) {
- /* Certain names are not allowed. The "all" and "default" names are reserved
- * due to their directories in "/proc/sys/net/ipv4/conf/" and "/proc/sys/net/ipv6/conf/".
- *
- * Also, there is "/sys/class/net/bonding_masters" file.
- */
- nm_utils_error_set(error,
- NM_UTILS_ERROR_UNKNOWN,
- _("'%s' is not allowed as interface name"),
- name);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-_nm_utils_ifname_valid_ovs(const char *name, GError **error)
-{
- const char *ch;
-
- /* OVS actually accepts a wider range of chars (all printable UTF-8 chars),
- * NetworkManager restricts this to ASCII char as it's a safer option for
- * now since OVS is not well documented on this matter.
- **/
- for (ch = name; *ch; ++ch) {
- if (*ch == '\\' || *ch == '/' || !g_ascii_isgraph(*ch)) {
- g_set_error_literal(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- _("interface name must be alphanumerical with "
- "no forward or backward slashes"));
- return FALSE;
- }
- };
- return TRUE;
-}
-
-gboolean
-nm_utils_ifname_valid(const char *name, NMUtilsIfaceType type, GError **error)
-{
- g_return_val_if_fail(!error || !(*error), FALSE);
-
- if (!name || !(name[0])) {
- g_set_error_literal(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- _("interface name must not be empty"));
- return FALSE;
- }
-
- if (!g_utf8_validate(name, -1, NULL)) {
- g_set_error_literal(error,
- NM_UTILS_ERROR,
- NM_UTILS_ERROR_UNKNOWN,
- _("interface name must be UTF-8 encoded"));
- return FALSE;
- }
-
- switch (type) {
- case NMU_IFACE_KERNEL:
- return _nm_utils_ifname_valid_kernel(name, error);
- case NMU_IFACE_OVS:
- return _nm_utils_ifname_valid_ovs(name, error);
- case NMU_IFACE_OVS_AND_KERNEL:
- return _nm_utils_ifname_valid_kernel(name, error)
- && _nm_utils_ifname_valid_ovs(name, error);
- case NMU_IFACE_ANY:
- {
- gs_free_error GError *local = NULL;
-
- if (_nm_utils_ifname_valid_kernel(name, error ? &local : NULL))
- return TRUE;
- if (_nm_utils_ifname_valid_ovs(name, NULL))
- return TRUE;
- if (error)
- g_propagate_error(error, g_steal_pointer(&local));
- return FALSE;
- }
- }
-
- g_return_val_if_reached(FALSE);
-}
-
-/*****************************************************************************/
-
-void
-_nm_str_buf_ensure_size(NMStrBuf *strbuf, gsize new_size, gboolean reserve_exact)
-{
- _nm_str_buf_assert(strbuf);
-
- /* Currently, this only supports strictly growing the buffer. */
- nm_assert(new_size > strbuf->_priv_allocated);
-
- if (!reserve_exact) {
- new_size = nm_utils_get_next_realloc_size(!strbuf->_priv_do_bzero_mem, new_size);
- }
-
- strbuf->_priv_str = nm_secret_mem_realloc(strbuf->_priv_str,
- strbuf->_priv_do_bzero_mem,
- strbuf->_priv_allocated,
- new_size);
- strbuf->_priv_allocated = new_size;
-}
-
-void
-nm_str_buf_append_printf(NMStrBuf *strbuf, const char *format, ...)
-{
- va_list args;
- gsize available;
- int l;
-
- _nm_str_buf_assert(strbuf);
-
- available = strbuf->_priv_allocated - strbuf->_priv_len;
-
- nm_assert(available < G_MAXULONG);
-
- va_start(args, format);
- l = g_vsnprintf(&strbuf->_priv_str[strbuf->_priv_len], available, format, args);
- va_end(args);
-
- nm_assert(l >= 0);
- nm_assert(l < G_MAXINT);
-
- if ((gsize) l >= available) {
- gsize l2;
-
- if (l == 0)
- return;
-
- l2 = ((gsize) l) + 1u;
-
- nm_str_buf_maybe_expand(strbuf, l2, FALSE);
-
- va_start(args, format);
- l = g_vsnprintf(&strbuf->_priv_str[strbuf->_priv_len], l2, format, args);
- va_end(args);
-
- nm_assert(l >= 0);
- nm_assert((gsize) l == l2 - 1u);
- }
-
- strbuf->_priv_len += (gsize) l;
-}
-
-/*****************************************************************************/
-
-/**
- * nm_indirect_g_free:
- * @arg: a pointer to a pointer that is to be freed.
- *
- * This does the same as nm_clear_g_free(arg) (g_clear_pointer (arg, g_free)).
- * This is for example useful when you have a GArray with pointers and a
- * clear function to free them. g_array_set_clear_func()'s destroy notify
- * function gets a pointer to the array location, so we have to follow
- * the first pointer.
- */
-void
-nm_indirect_g_free(gpointer arg)
-{
- gpointer *p = arg;
-
- nm_clear_g_free(p);
-}
-
-/*****************************************************************************/
-
-static char *
-attribute_escape(const char *src, char c1, char c2)
-{
- char *ret, *dest;
-
- dest = ret = g_malloc(strlen(src) * 2 + 1);
-
- while (*src) {
- if (*src == c1 || *src == c2 || *src == '\\')
- *dest++ = '\\';
- *dest++ = *src++;
- }
- *dest++ = '\0';
-
- return ret;
-}
-
-void
-_nm_utils_format_variant_attributes_full(GString * str,
- const NMUtilsNamedValue * values,
- guint num_values,
- const NMVariantAttributeSpec *const *spec,
- char attr_separator,
- char key_value_separator)
-{
- const NMVariantAttributeSpec *const *s;
- const char * name, *value;
- GVariant * variant;
- char * escaped;
- char buf[64];
- char sep = 0;
- guint i;
-
- for (i = 0; i < num_values; i++) {
- name = values[i].name;
- variant = values[i].value_ptr;
- value = NULL;
- s = NULL;
-
- if (spec) {
- for (s = spec; *s; s++) {
- if (nm_streq0((*s)->name, name))
- break;
- }
-
- if (!*s)
- continue;
- }
-
- if (g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT32))
- value = nm_sprintf_buf(buf, "%u", g_variant_get_uint32(variant));
- else if (g_variant_is_of_type(variant, G_VARIANT_TYPE_INT32))
- value = nm_sprintf_buf(buf, "%d", (int) g_variant_get_int32(variant));
- else if (g_variant_is_of_type(variant, G_VARIANT_TYPE_UINT64))
- value = nm_sprintf_buf(buf, "%" G_GUINT64_FORMAT, g_variant_get_uint64(variant));
- else if (g_variant_is_of_type(variant, G_VARIANT_TYPE_BYTE))
- value = nm_sprintf_buf(buf, "%hhu", g_variant_get_byte(variant));
- else if (g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN))
- value = g_variant_get_boolean(variant) ? "true" : "false";
- else if (g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING))
- value = g_variant_get_string(variant, NULL);
- else if (g_variant_is_of_type(variant, G_VARIANT_TYPE_BYTESTRING)) {
- /* FIXME: there is no guarantee that the byte array
- * is valid UTF-8.*/
- value = g_variant_get_bytestring(variant);
- } else
- continue;
-
- if (sep)
- g_string_append_c(str, sep);
-
- escaped = attribute_escape(name, attr_separator, key_value_separator);
- g_string_append(str, escaped);
- g_free(escaped);
-
- if (!s || !*s || !(*s)->no_value) {
- g_string_append_c(str, key_value_separator);
-
- escaped = attribute_escape(value, attr_separator, key_value_separator);
- g_string_append(str, escaped);
- g_free(escaped);
- }
-
- sep = attr_separator;
- }
-}
-
-char *
-_nm_utils_format_variant_attributes(GHashTable * attributes,
- const NMVariantAttributeSpec *const *spec,
- char attr_separator,
- char key_value_separator)
-{
- gs_free NMUtilsNamedValue *values_free = NULL;
- NMUtilsNamedValue values_prepared[20];
- const NMUtilsNamedValue * values;
- GString * str = NULL;
- guint len;
-
- g_return_val_if_fail(attr_separator, NULL);
- g_return_val_if_fail(key_value_separator, NULL);
-
- if (!attributes)
- return NULL;
-
- values = nm_utils_named_values_from_strdict(attributes, &len, values_prepared, &values_free);
- if (len == 0)
- return NULL;
-
- str = g_string_new("");
- _nm_utils_format_variant_attributes_full(str,
- values,
- len,
- spec,
- attr_separator,
- key_value_separator);
- return g_string_free(str, FALSE);
-}
-
-/*****************************************************************************/
-
-gboolean
-nm_utils_is_localhost(const char *name)
-{
- static const char *const NAMES[] = {
- "localhost",
- "localhost4",
- "localhost6",
- "localhost.localdomain",
- "localhost4.localdomain4",
- "localhost6.localdomain6",
- };
- gsize name_len;
- int i;
-
- if (!name)
- return FALSE;
-
- /* This tries to identify local host and domain names
- * described in RFC6761 plus the redhatism of localdomain.
- *
- * Similar to systemd's is_localhost(). */
-
- name_len = strlen(name);
-
- if (name_len == 0)
- return FALSE;
-
- if (name[name_len - 1] == '.') {
- /* one trailing dot is fine. Hide it. */
- name_len--;
- }
-
- for (i = 0; i < (int) G_N_ELEMENTS(NAMES); i++) {
- const char *n = NAMES[i];
- gsize l = strlen(n);
- gsize s;
-
- if (name_len < l)
- continue;
-
- s = name_len - l;
-
- if (g_ascii_strncasecmp(&name[s], n, l) != 0)
- continue;
-
- /* we accept the name if it is equal to one of the well-known names,
- * or if it is some prefix, a '.' and the well-known name. */
- if (s == 0)
- return TRUE;
- if (name[s - 1] == '.')
- return TRUE;
- }
-
- return FALSE;
-}
-
-gboolean
-nm_utils_is_specific_hostname(const char *name)
-{
- if (nm_str_is_empty(name))
- return FALSE;
-
- if (nm_streq(name, "(none)")) {
- /* This is not a special hostname. Probably an artefact by somebody wrongly
- * printing NULL. */
- return FALSE;
- }
-
- if (nm_utils_is_localhost(name))
- return FALSE;
-
- /* FIXME: properly validate the hostname, like systemd's hostname_is_valid() */
-
- return TRUE;
-}
-
-/*****************************************************************************/
-
-/* taken from systemd's uid_to_name(). */
-char *
-nm_utils_uid_to_name(uid_t uid)
-{
- gs_free char *buf_heap = NULL;
- char buf_stack[4096];
- gsize bufsize;
- char * buf;
-
- bufsize = sizeof(buf_stack);
- buf = buf_stack;
-
- for (;;) {
- struct passwd pwbuf;
- struct passwd *pw = NULL;
- int r;
-
- r = getpwuid_r(uid, &pwbuf, buf, bufsize, &pw);
- if (r == 0 && pw)
- return nm_strdup_not_empty(pw->pw_name);
-
- if (r != ERANGE)
- return NULL;
-
- if (bufsize > G_MAXSIZE / 2u)
- return NULL;
-
- bufsize *= 2u;
- g_free(buf_heap);
- buf_heap = g_malloc(bufsize);
- buf = buf_heap;
- }
-}
-
-/* taken from systemd's nss_user_record_by_name() */
-gboolean
-nm_utils_name_to_uid(const char *name, uid_t *out_uid)
-{
- gs_free char *buf_heap = NULL;
- char buf_stack[4096];
- gsize bufsize;
- char * buf;
-
- if (!name)
- return nm_assert_unreachable_val(FALSE);
-
- bufsize = sizeof(buf_stack);
- buf = buf_stack;
-
- for (;;) {
- struct passwd *result;
- struct passwd pwd;
- int r;
-
- r = getpwnam_r(name, &pwd, buf, bufsize, &result);
- if (r == 0) {
- if (!result)
- return FALSE;
- NM_SET_OUT(out_uid, pwd.pw_uid);
- return TRUE;
- }
-
- if (r != ERANGE)
- return FALSE;
-
- if (bufsize > G_MAXSIZE / 2u)
- return FALSE;
-
- bufsize *= 2u;
- g_free(buf_heap);
- buf_heap = g_malloc(bufsize);
- buf = buf_heap;
- }
-}
diff --git a/shared/nm-glib-aux/nm-shared-utils.h b/shared/nm-glib-aux/nm-shared-utils.h
deleted file mode 100644
index 7d330458c1..0000000000
--- a/shared/nm-glib-aux/nm-shared-utils.h
+++ /dev/null
@@ -1,2480 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2016 Red Hat, Inc.
- */
-
-#ifndef __NM_SHARED_UTILS_H__
-#define __NM_SHARED_UTILS_H__
-
-#include <netinet/in.h>
-
-/*****************************************************************************/
-
-/* An optional boolean (like NMTernary, with identical numerical
- * enum values). Note that this enum type is _nm_packed! */
-typedef enum _nm_packed {
- NM_OPTION_BOOL_DEFAULT = -1,
- NM_OPTION_BOOL_FALSE = 0,
- NM_OPTION_BOOL_TRUE = 1,
-} NMOptionBool;
-
-/*****************************************************************************/
-
-static inline gboolean
-nm_is_ascii(char ch)
-{
- return ((uint8_t) ch) < 128;
-}
-
-/*****************************************************************************/
-
-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
-#else
- #define NM_ASSERT_ON_MAIN_THREAD() \
- G_STMT_START \
- { \
- ; \
- } \
- G_STMT_END
-#endif
-
-/*****************************************************************************/
-
-static inline gboolean
-_NM_INT_NOT_NEGATIVE(gssize val)
-{
- /* whether an enum (without negative values) is a signed int, depends on compiler options
- * and compiler implementation.
- *
- * When using such an enum for accessing an array, one naturally wants to check
- * that the enum is not negative. However, the compiler doesn't like a plain
- * comparison "enum_val >= 0", because (if the enum is unsigned), it will warn
- * that the expression is always true *duh*. Not even a cast to a signed
- * type helps to avoid the compiler warning in any case.
- *
- * The sole purpose of this function is to avoid a compiler warning, when checking
- * that an enum is not negative. */
- return val >= 0;
-}
-
-/* check whether the integer value is smaller than G_MAXINT32. This macro exists
- * for the sole purpose, that a plain "((int) value <= G_MAXINT32)" comparison
- * may cause the compiler or coverity that this check is always TRUE. But the
- * check depends on compile time and the size of C type "int". Of course, most
- * of the time in is gint32 and an int value is always <= G_MAXINT32. The check
- * exists to catch cases where that is not true.
- *
- * 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); \
- })
-#else
- #define _NM_INT_LE_MAXINT32(value) \
- ({ \
- _nm_unused typeof(value) _value = (value); \
- _nm_unused const int *_p_value = &_value; \
- \
- TRUE; \
- })
-#endif
-
-/*****************************************************************************/
-
-typedef struct {
- guint8 ether_addr_octet[6 /*ETH_ALEN*/];
-} NMEtherAddr;
-
-#define NM_ETHER_ADDR_FORMAT_STR "%02X:%02X:%02X:%02X:%02X:%02X"
-
-#define NM_ETHER_ADDR_FORMAT_VAL(x) \
- (x)->ether_addr_octet[0], (x)->ether_addr_octet[1], (x)->ether_addr_octet[2], \
- (x)->ether_addr_octet[3], (x)->ether_addr_octet[4], (x)->ether_addr_octet[5]
-
-#define _NM_ETHER_ADDR_INIT(a0, a1, a2, a3, a4, a5) \
- { \
- .ether_addr_octet = { \
- (a0), \
- (a1), \
- (a2), \
- (a3), \
- (a4), \
- (a5), \
- }, \
- }
-
-#define NM_ETHER_ADDR_INIT(...) ((NMEtherAddr) _NM_ETHER_ADDR_INIT(__VA_ARGS__))
-
-static inline int
-nm_ether_addr_cmp(const NMEtherAddr *a, const NMEtherAddr *b)
-{
- NM_CMP_SELF(a, b);
- NM_CMP_DIRECT_MEMCMP(a, b, sizeof(NMEtherAddr));
- return 0;
-}
-
-static inline gboolean
-nm_ether_addr_equal(const NMEtherAddr *a, const NMEtherAddr *b)
-{
- return nm_ether_addr_cmp(a, b) == 0;
-}
-
-/*****************************************************************************/
-
-typedef struct {
- union {
- guint8 addr_ptr[1];
- in_addr_t addr4;
- struct in_addr addr4_struct;
- struct in6_addr addr6;
-
- /* NMIPAddr is really a union for IP addresses.
- * However, as ethernet addresses fit in here nicely, use
- * it also for an ethernet MAC address. */
- guint8 ether_addr_octet[6 /*ETH_ALEN*/];
- NMEtherAddr ether_addr;
-
- guint8 array[sizeof(struct in6_addr)];
- };
-} NMIPAddr;
-
-#define NM_IP_ADDR_INIT \
- { \
- .array = { 0 } \
- }
-
-extern const NMIPAddr nm_ip_addr_zero;
-
-#define nm_ether_addr_zero (nm_ip_addr_zero.ether_addr)
-
-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);
-
- return memcmp(a, b, nm_utils_addr_family_to_size(addr_family));
-}
-
-static inline gboolean
-nm_ip_addr_equal(int addr_family, gconstpointer a, gconstpointer b)
-{
- return nm_ip_addr_cmp(addr_family, a, b) == 0;
-}
-
-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;
-}
-
-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, (addr_family != AF_INET6) ? sizeof(in_addr_t) : sizeof(struct in6_addr));
-}
-
-gboolean nm_ip_addr_set_from_untrusted(int addr_family,
- gpointer dst,
- gconstpointer src,
- gsize src_len,
- int * out_addr_family);
-
-static inline gboolean
-nm_ip4_addr_is_localhost(in_addr_t addr4)
-{
- return (addr4 & htonl(0xFF000000u)) == htonl(0x7F000000u);
-}
-
-/*****************************************************************************/
-
-struct ether_addr;
-
-static inline int
-nm_utils_ether_addr_cmp(const struct ether_addr *a1, const struct ether_addr *a2)
-{
- nm_assert(a1);
- nm_assert(a2);
- return memcmp(a1, a2, 6 /*ETH_ALEN*/);
-}
-
-static inline gboolean
-nm_utils_ether_addr_equal(const struct ether_addr *a1, const struct ether_addr *a2)
-{
- return nm_utils_ether_addr_cmp(a1, a2) == 0;
-}
-
-/*****************************************************************************/
-
-#define NM_UTILS_INET_ADDRSTRLEN INET6_ADDRSTRLEN
-
-static inline const char *
-nm_utils_inet_ntop(int addr_family, gconstpointer addr, char *dst)
-{
- const char *s;
-
- const char *inet_ntop(int af, const void *src, char *dst, socklen_t size);
-
- nm_assert_addr_family(addr_family);
- nm_assert(addr);
- nm_assert(dst);
-
- s = inet_ntop(addr_family,
- addr,
- dst,
- addr_family == AF_INET6 ? INET6_ADDRSTRLEN : INET_ADDRSTRLEN);
- nm_assert(s);
- return s;
-}
-
-static inline const char *
-_nm_utils_inet4_ntop(in_addr_t addr, char dst[static INET_ADDRSTRLEN])
-{
- return nm_utils_inet_ntop(AF_INET, &addr, dst);
-}
-
-static inline const char *
-_nm_utils_inet6_ntop(const struct in6_addr *addr, char dst[static INET6_ADDRSTRLEN])
-{
- return nm_utils_inet_ntop(AF_INET6, addr, dst);
-}
-
-static inline char *
-nm_utils_inet_ntop_dup(int addr_family, gconstpointer addr)
-{
- char buf[NM_UTILS_INET_ADDRSTRLEN];
-
- return g_strdup(nm_utils_inet_ntop(addr_family, addr, buf));
-}
-
-static inline char *
-nm_utils_inet4_ntop_dup(in_addr_t addr)
-{
- return nm_utils_inet_ntop_dup(AF_INET, &addr);
-}
-
-static inline char *
-nm_utils_inet6_ntop_dup(const struct in6_addr *addr)
-{
- return nm_utils_inet_ntop_dup(AF_INET6, addr);
-}
-
-/*****************************************************************************/
-
-gboolean nm_utils_ipaddr_is_valid(int addr_family, const char *str_addr);
-
-gboolean nm_utils_ipaddr_is_normalized(int addr_family, const char *str_addr);
-
-/*****************************************************************************/
-
-gboolean nm_utils_memeqzero(gconstpointer data, gsize length);
-
-/*****************************************************************************/
-
-extern const void *const _NM_PTRARRAY_EMPTY[1];
-
-#define NM_PTRARRAY_EMPTY(type) ((type const *) _NM_PTRARRAY_EMPTY)
-
-static inline void
-_nm_utils_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) \
- 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)); \
- } \
- 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);
-
-const char *nm_strquote(char *buf, gsize buf_len, const char *str);
-
-static inline gboolean
-nm_utils_is_separator(const char c)
-{
- return NM_IN_SET(c, ' ', '\t');
-}
-
-/*****************************************************************************/
-
-GBytes *nm_gbytes_get_empty(void);
-
-GBytes *nm_g_bytes_new_from_str(const char *str);
-
-static inline gboolean
-nm_gbytes_equal0(GBytes *a, 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);
-
-GVariant *nm_utils_gbytes_to_variant_ay(GBytes *bytes);
-
-GHashTable *nm_utils_strdict_clone(GHashTable *src);
-
-GVariant *nm_utils_strdict_to_variant_ass(GHashTable *strdict);
-GVariant *nm_utils_strdict_to_variant_asv(GHashTable *strdict);
-
-/*****************************************************************************/
-
-GVariant *nm_utils_gvariant_vardict_filter(GVariant *src,
- gboolean (*filter_fcn)(const char *key,
- GVariant * val,
- char ** out_key,
- GVariant ** out_val,
- gpointer user_data),
- gpointer user_data);
-
-GVariant *nm_utils_gvariant_vardict_filter_drop_one(GVariant *src, const char *key);
-
-/*****************************************************************************/
-
-static inline int
-nm_utils_hexchar_to_int(char ch)
-{
- G_STATIC_ASSERT_EXPR('0' < 'A');
- G_STATIC_ASSERT_EXPR('A' < 'a');
-
- if (ch >= '0') {
- if (ch <= '9')
- return ch - '0';
- if (ch >= 'A') {
- if (ch <= 'F')
- return ((int) ch) + (10 - (int) 'A');
- if (ch >= 'a' && ch <= 'f')
- return ((int) ch) + (10 - (int) 'a');
- }
- }
- return -1;
-}
-
-/*****************************************************************************/
-
-const char *nm_utils_dbus_path_get_last_component(const char *dbus_path);
-
-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,
-
- /* 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
- * empty after strstrip(), it also gets removed. */
- NM_UTILS_STRSPLIT_SET_FLAGS_PRESERVE_EMPTY = (1u << 0),
-
- /* %NM_UTILS_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
- * 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
- * the backslash escapes are removed from the result.
- */
- NM_UTILS_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,
- * 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,
- * trailing whitespace escaped by backslash are not stripped. */
- NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP = (1u << 2),
-
- /* This implies %NM_UTILS_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.
- * - preceed a whitespace (with %NM_UTILS_STRSPLIT_SET_FLAGS_STRSTRIP).
- *
- * Note that with %NM_UTILS_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(),
- * then all characters (including backslash) are treated verbatim, except:
- *
- * - "\\$DELIMITER" (escaped delimiter)
- * - "\\\\" (escaped backslash)
- * - "\\$SPACE" (escaped space) (with %NM_UTILS_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),
-
-} NMUtilsStrsplitSetFlags;
-
-const char **
-nm_utils_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)
-{
- /* 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);
-}
-
-static inline const char **
-nm_utils_strsplit_set(const char *str, const char *delimiters)
-{
- return nm_utils_strsplit_set_full(str, delimiters, NM_UTILS_STRSPLIT_SET_FLAGS_NONE);
-}
-
-gssize nm_utils_strv_find_first(char **list, gssize len, const char *needle);
-
-char **_nm_utils_strv_cleanup(char ** strv,
- gboolean strip_whitespace,
- gboolean skip_empty,
- gboolean skip_repeated);
-
-/*****************************************************************************/
-
-static inline gpointer
-nm_copy_func_g_strdup(gconstpointer arg, gpointer user_data)
-{
- return g_strdup(arg);
-}
-
-/*****************************************************************************/
-
-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);
-}
-
-typedef enum {
- NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_NONE = 0,
- NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_SPACES = (1ull << 0),
- NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_LEADING_SPACE = (1ull << 1),
- NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_TRAILING_SPACE = (1ull << 2),
-
- /* Backslash characters will be escaped as "\\\\" if they precede another
- * character that makes it necessary. Such characters are:
- *
- * 1) before another '\\' backslash.
- * 2) before any delimiter in @delimiters.
- * 3) before any delimiter in @delimiters_as_needed.
- * 4) before a white space, if ESCAPE_LEADING_SPACE or ESCAPE_TRAILING_SPACE is set.
- * 5) before the end of the word
- *
- * Rule 4) is an extension. It's not immediately clear why with ESCAPE_LEADING_SPACE
- * and ESCAPE_TRAILING_SPACE we want *all* backslashes before a white space escaped.
- * The reason is, that we obviously want to use ESCAPE_LEADING_SPACE and ESCAPE_TRAILING_SPACE
- * in cases, where we later parse the backslash escaped strings back, but allowing to strip
- * unescaped white spaces. That means, we want that " a " gets escaped as "\\ a\\ ".
- * On the other hand, we also want that " a\\ b " gets escaped as "\\ a\\\\ b\\ ",
- * and not "\\ a\\ b\\ ". Because otherwise, the parser would need to treat "\\ "
- * differently depending on whether the sequence is at the beginning, end or middle
- * of the word.
- *
- * Rule 5) is also not immediately obvious. When used with ESCAPE_TRAILING_SPACE,
- * we clearly want to allow that an escaped word can have arbitrary
- * whitespace suffixes. That's why this mode exists. So we must escape "a\\" as
- * "a\\\\", so that appending " " does not change the meaning.
- * Also without ESCAPE_TRAILING_SPACE, we want in general that we can concatenate
- * two escaped words without changing their meaning. If the words would be "a\\"
- * and "," (with ',' being a delimiter), then the result must be "a\\\\" and "\\,"
- * so that the concatenated word ("a\\\\\\,") is still the same. If we would escape
- * them instead as "a\\" + "\\,", then the concatenated word would be "a\\\\," and
- * different.
- * */
- NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_AS_NEEDED = (1ull << 3),
-
- NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_ALWAYS = (1ull << 4),
-} NMUtilsEscapedTokensEscapeFlags;
-
-const char *nm_utils_escaped_tokens_escape_full(const char *str,
- const char *delimiters,
- const char *delimiters_as_needed,
- NMUtilsEscapedTokensEscapeFlags flags,
- char ** out_to_free);
-
-static inline const char *
-nm_utils_escaped_tokens_escape(const char *str, const char *delimiters, char **out_to_free)
-{
- return nm_utils_escaped_tokens_escape_full(
- str,
- delimiters,
- NULL,
- NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_ALWAYS
- | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_TRAILING_SPACE,
- out_to_free);
-}
-
-/**
- * nm_utils_escaped_tokens_escape_unnecessary:
- * @str: the string to check for "escape"
- * @delimiters: the delimiters
- *
- * This asserts that calling nm_utils_escaped_tokens_escape()
- * on @str has no effect and returns @str directly. This is only
- * for asserting that @str is safe to not require any escaping.
- *
- * Returns: @str
- */
-static inline const char *
-nm_utils_escaped_tokens_escape_unnecessary(const char *str, const char *delimiters)
-{
-#if NM_MORE_ASSERTS > 0
-
- nm_assert(str);
- nm_assert(delimiters);
-
- {
- gs_free char *str_to_free = NULL;
- const char * str0;
-
- str0 = nm_utils_escaped_tokens_escape(str, delimiters, &str_to_free);
- nm_assert(str0 == str);
- nm_assert(!str_to_free);
- }
-#endif
-
- return str;
-}
-
-static inline void
-nm_utils_escaped_tokens_escape_gstr_assert(const char *str,
- const char *delimiters,
- GString * gstring)
-{
- g_string_append(gstring, nm_utils_escaped_tokens_escape_unnecessary(str, delimiters));
-}
-
-static inline GString *
-nm_utils_escaped_tokens_escape_gstr(const char *str, const char *delimiters, GString *gstring)
-{
- gs_free char *str_to_free = NULL;
-
- nm_assert(str);
- nm_assert(gstring);
-
- g_string_append(gstring, nm_utils_escaped_tokens_escape(str, delimiters, &str_to_free));
- return gstring;
-}
-
-/*****************************************************************************/
-
-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);
-}
-
-void nm_utils_escaped_tokens_options_split(char *str, const char **out_key, const char **out_val);
-
-static inline const char *
-nm_utils_escaped_tokens_options_escape_key(const char *key, char **out_to_free)
-{
- return nm_utils_escaped_tokens_escape_full(
- key,
- ",=",
- NULL,
- NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_AS_NEEDED
- | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_LEADING_SPACE
- | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_TRAILING_SPACE,
- out_to_free);
-}
-
-static inline const char *
-nm_utils_escaped_tokens_options_escape_val(const char *val, char **out_to_free)
-{
- return nm_utils_escaped_tokens_escape_full(
- val,
- ",",
- "=",
- NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_BACKSLASH_AS_NEEDED
- | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_LEADING_SPACE
- | NM_UTILS_ESCAPED_TOKENS_ESCAPE_FLAGS_ESCAPE_TRAILING_SPACE,
- out_to_free);
-}
-
-/*****************************************************************************/
-
-#define NM_UTILS_CHECKSUM_LENGTH_MD5 16
-#define NM_UTILS_CHECKSUM_LENGTH_SHA1 20
-#define NM_UTILS_CHECKSUM_LENGTH_SHA256 32
-
-#define nm_utils_checksum_get_digest(sum, arr) \
- G_STMT_START \
- { \
- GChecksum *const _sum = (sum); \
- gsize _len; \
- \
- G_STATIC_ASSERT_EXPR(sizeof(arr) == NM_UTILS_CHECKSUM_LENGTH_MD5 \
- || sizeof(arr) == NM_UTILS_CHECKSUM_LENGTH_SHA1 \
- || sizeof(arr) == NM_UTILS_CHECKSUM_LENGTH_SHA256); \
- G_STATIC_ASSERT_EXPR(sizeof(arr) == G_N_ELEMENTS(arr)); \
- \
- nm_assert(_sum); \
- \
- _len = G_N_ELEMENTS(arr); \
- \
- g_checksum_get_digest(_sum, (arr), &_len); \
- nm_assert(_len == G_N_ELEMENTS(arr)); \
- } \
- G_STMT_END
-
-#define nm_utils_checksum_get_digest_len(sum, buf, len) \
- G_STMT_START \
- { \
- GChecksum *const _sum = (sum); \
- const gsize _len0 = (len); \
- gsize _len; \
- \
- nm_assert(NM_IN_SET(_len0, \
- NM_UTILS_CHECKSUM_LENGTH_MD5, \
- NM_UTILS_CHECKSUM_LENGTH_SHA1, \
- NM_UTILS_CHECKSUM_LENGTH_SHA256)); \
- nm_assert(_sum); \
- \
- _len = _len0; \
- g_checksum_get_digest(_sum, (buf), &_len); \
- nm_assert(_len == _len0); \
- } \
- G_STMT_END
-
-/*****************************************************************************/
-
-guint32 _nm_utils_ip4_prefix_to_netmask(guint32 prefix);
-guint32 _nm_utils_ip4_get_default_prefix0(in_addr_t ip);
-guint32 _nm_utils_ip4_get_default_prefix(in_addr_t ip);
-
-gconstpointer
-nm_utils_ipx_address_clear_host_address(int family, gpointer dst, gconstpointer src, guint8 plen);
-in_addr_t nm_utils_ip4_address_clear_host_address(in_addr_t addr, guint8 plen);
-const struct in6_addr *nm_utils_ip6_address_clear_host_address(struct in6_addr * dst,
- const struct in6_addr *src,
- guint8 plen);
-int nm_utils_ip6_address_same_prefix_cmp(const struct in6_addr *addr_a,
- const struct in6_addr *addr_b,
- guint8 plen);
-
-gboolean nm_utils_ip_is_site_local(int addr_family, const void *address);
-
-/*****************************************************************************/
-
-gboolean nm_utils_parse_inaddr_bin_full(int addr_family,
- gboolean accept_legacy,
- const char *text,
- int * out_addr_family,
- gpointer out_addr);
-static inline gboolean
-nm_utils_parse_inaddr_bin(int addr_family,
- const char *text,
- int * out_addr_family,
- gpointer out_addr)
-{
- return nm_utils_parse_inaddr_bin_full(addr_family, FALSE, text, out_addr_family, out_addr);
-}
-
-gboolean nm_utils_parse_inaddr(int addr_family, const char *text, char **out_addr);
-
-gboolean nm_utils_parse_inaddr_prefix_bin(int addr_family,
- const char *text,
- int * out_addr_family,
- gpointer out_addr,
- int * out_prefix);
-
-gboolean
-nm_utils_parse_inaddr_prefix(int addr_family, const char *text, char **out_addr, int *out_prefix);
-
-gboolean nm_utils_parse_next_line(const char **inout_ptr,
- gsize * inout_len,
- const char **out_line,
- gsize * out_line_len);
-
-gint64 nm_g_ascii_strtoll(const char *nptr, char **endptr, guint base);
-
-guint64 nm_g_ascii_strtoull(const char *nptr, char **endptr, guint base);
-
-double nm_g_ascii_strtod(const char *nptr, char **endptr);
-
-gint64
-_nm_utils_ascii_str_to_int64(const char *str, guint base, gint64 min, gint64 max, gint64 fallback);
-guint64 _nm_utils_ascii_str_to_uint64(const char *str,
- guint base,
- guint64 min,
- guint64 max,
- guint64 fallback);
-
-int _nm_utils_ascii_str_to_bool(const char *str, int default_value);
-
-/*****************************************************************************/
-
-extern 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);
-
-/*****************************************************************************/
-
-typedef struct {
- unsigned flag;
- const char *name;
-} NMUtilsFlags2StrDesc;
-
-#define NM_UTILS_FLAGS2STR(f, n) \
- { \
- .flag = f, .name = "" n, \
- }
-
-#define NM_UTILS_FLAGS2STR_DEFINE(fcn_name, flags_type, ...) \
- const char *fcn_name(flags_type flags, char *buf, gsize len) \
- { \
- static const NMUtilsFlags2StrDesc descs[] = {__VA_ARGS__}; \
- G_STATIC_ASSERT(sizeof(flags_type) <= sizeof(unsigned)); \
- \
- return nm_utils_flags2str(descs, G_N_ELEMENTS(descs), flags, buf, len); \
- } \
- _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON
-
-const char *nm_utils_flags2str(const NMUtilsFlags2StrDesc *descs,
- gsize n_descs,
- unsigned flags,
- char * buf,
- gsize len);
-
-/*****************************************************************************/
-
-#define NM_UTILS_ENUM2STR(v, n) \
- (void) 0; \
-case v: \
- s = "" n ""; \
- break; \
- (void) 0
-#define NM_UTILS_ENUM2STR_IGNORE(v) \
- (void) 0; \
-case v: \
- break; \
- (void) 0
-
-#define NM_UTILS_ENUM2STR_DEFINE_FULL(fcn_name, lookup_type, int_fmt, ...) \
- const char *fcn_name(lookup_type val, char *buf, gsize len) \
- { \
- nm_utils_to_string_buffer_init(&buf, &len); \
- if (len) { \
- const char *s = NULL; \
- switch (val) { \
- (void) 0, __VA_ARGS__(void) 0; \
- }; \
- if (s) \
- g_strlcpy(buf, s, len); \
- else \
- g_snprintf(buf, len, "(%" int_fmt ")", val); \
- } \
- return buf; \
- } \
- _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON
-
-#define NM_UTILS_ENUM2STR_DEFINE(fcn_name, lookup_type, ...) \
- NM_UTILS_ENUM2STR_DEFINE_FULL(fcn_name, lookup_type, "d", __VA_ARGS__)
-
-/*****************************************************************************/
-
-#define _nm_g_slice_free_fcn_define(mem_size) \
- static inline void _nm_g_slice_free_fcn_##mem_size(gpointer mem_block) \
- { \
- g_slice_free1(mem_size, mem_block); \
- }
-
-_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)
-
-#define nm_g_slice_free_fcn1(mem_size) \
- ({ \
- void (*_fcn)(gpointer); \
- \
- /* If mem_size is a compile time constant, the compiler
- * will be able to optimize this. Hence, you don't want
- * to call this with a non-constant size argument. */ \
- G_STATIC_ASSERT_EXPR(((mem_size) == 1) || ((mem_size) == 2) || ((mem_size) == 4) \
- || ((mem_size) == 8) || ((mem_size) == 10) || ((mem_size) == 12) \
- || ((mem_size) == 16) || ((mem_size) == 32)); \
- switch ((mem_size)) { \
- case 1: \
- _fcn = _nm_g_slice_free_fcn_1; \
- break; \
- case 2: \
- _fcn = _nm_g_slice_free_fcn_2; \
- break; \
- case 4: \
- _fcn = _nm_g_slice_free_fcn_4; \
- break; \
- case 8: \
- _fcn = _nm_g_slice_free_fcn_8; \
- break; \
- case 10: \
- _fcn = _nm_g_slice_free_fcn_10; \
- break; \
- case 12: \
- _fcn = _nm_g_slice_free_fcn_12; \
- break; \
- case 16: \
- _fcn = _nm_g_slice_free_fcn_16; \
- break; \
- case 32: \
- _fcn = _nm_g_slice_free_fcn_32; \
- break; \
- default: \
- g_assert_not_reached(); \
- _fcn = NULL; \
- break; \
- } \
- _fcn; \
- })
-
-/**
- * nm_g_slice_free_fcn:
- * @type: type argument for sizeof() operator that you would
- * pass to g_slice_new().
- *
- * Returns: a function pointer with GDestroyNotify signature
- * for g_slice_free(type,*).
- *
- * Only certain types are implemented. You'll get a compile time
- * error for the wrong types. */
-#define nm_g_slice_free_fcn(type) (nm_g_slice_free_fcn1(sizeof(type)))
-
-#define nm_g_slice_free_fcn_gint64 (nm_g_slice_free_fcn(gint64))
-
-/*****************************************************************************/
-
-/* Like g_error_matches() however:
- * - as macro it is always inlined.
- * - the @domain is usually a error quark getter function that cannot
- * be inlined. This macro calls the getter only if there is an error (lazy).
- * - accept a list of allowed codes, instead of only one.
- */
-#define nm_g_error_matches(error, err_domain, ...) \
- ({ \
- const GError *const _error = (error); \
- \
- _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)
-{
- if (!error_take)
- g_return_if_reached();
- if (!error) {
- g_error_free(error_take);
- return;
- }
- if (*error) {
- g_error_free(error_take);
- g_return_if_reached();
- }
- *error = error_take;
-}
-
-#define nm_g_set_error_take_lazy(error, error_take_lazy) \
- G_STMT_START \
- { \
- GError **_error = (error); \
- \
- if (_error) \
- nm_g_set_error_take(_error, (error_take_lazy)); \
- } \
- G_STMT_END
-
-/**
- * NMUtilsError:
- * @NM_UTILS_ERROR_UNKNOWN: unknown or unclassified error
- * @NM_UTILS_ERROR_CANCELLED_DISPOSING: when disposing an object that has
- * pending asynchronous operations, the operation is cancelled with this
- * error reason. Depending on the usage, this might indicate a bug because
- * usually the target object should stay alive as long as there are pending
- * operations.
- * @NM_UTILS_ERROR_NOT_READY: the failure is related to being currently
- * not ready to perform the operation.
- *
- * @NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE: used for a very particular
- * purpose during nm_device_check_connection_compatible() to indicate that
- * the profile does not match the device already because their type differs.
- * That is, there is a fundamental reason of trying to check a profile that
- * cannot possibly match on this device.
- * @NM_UTILS_ERROR_CONNECTION_AVAILABLE_UNMANAGED_DEVICE: used for a very particular
- * purpose during nm_device_check_connection_available(), to indicate that the
- * device is not available because it is unmanaged.
- * @NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY: the profile is currently not
- * available/compatible with the device, but this may be only temporary.
- *
- * @NM_UTILS_ERROR_SETTING_MISSING: the setting is missing
- *
- * @NM_UTILS_ERROR_INVALID_ARGUMENT: invalid argument.
- */
-typedef enum {
- NM_UTILS_ERROR_UNKNOWN = 0, /*< nick=Unknown >*/
- NM_UTILS_ERROR_CANCELLED_DISPOSING, /*< nick=CancelledDisposing >*/
- NM_UTILS_ERROR_INVALID_ARGUMENT, /*< nick=InvalidArgument >*/
- NM_UTILS_ERROR_NOT_READY, /*< nick=NotReady >*/
-
- /* the following codes have a special meaning and are exactly used for
- * nm_device_check_connection_compatible() and nm_device_check_connection_available().
- *
- * Actually, their meaning is not very important (so, don't think too
- * hard about the name of these error codes). What is important, is their
- * relative order (i.e. the integer value of the codes). When manager
- * searches for a suitable device, it will check all devices whether
- * a profile can be activated. If they all fail, it will pick the error
- * message from the device that returned the *highest* error code,
- * in the hope that this message makes the most sense for the caller.
- * */
- NM_UTILS_ERROR_CONNECTION_AVAILABLE_INCOMPATIBLE,
- NM_UTILS_ERROR_CONNECTION_AVAILABLE_UNMANAGED_DEVICE,
- NM_UTILS_ERROR_CONNECTION_AVAILABLE_TEMPORARY,
-
- NM_UTILS_ERROR_SETTING_MISSING,
-
-} NMUtilsError;
-
-#define NM_UTILS_ERROR (nm_utils_error_quark())
-GQuark nm_utils_error_quark(void);
-
-GQuark nm_manager_error_quark(void);
-#define _NM_MANAGER_ERROR (nm_manager_error_quark())
-
-#define _NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL 10
-#define _NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN 11
-
-void nm_utils_error_set_cancelled(GError **error, gboolean is_disposing, const char *instance_name);
-
-static inline GError *
-nm_utils_error_new_cancelled(gboolean is_disposing, const char *instance_name)
-{
- GError *error = NULL;
-
- nm_utils_error_set_cancelled(&error, is_disposing, instance_name);
- return error;
-}
-
-gboolean nm_utils_error_is_cancelled_or_disposing(GError *error);
-
-static inline gboolean
-nm_utils_error_is_cancelled(GError *error)
-{
- return error && error->code == G_IO_ERROR_CANCELLED && error->domain == G_IO_ERROR;
-}
-
-gboolean nm_utils_error_is_notfound(GError *error);
-
-static inline void
-nm_utils_error_set_literal(GError **error, int error_code, const char *literal)
-{
- g_set_error_literal(error, NM_UTILS_ERROR, error_code, literal);
-}
-
-#define nm_utils_error_set(error, error_code, ...) \
- G_STMT_START \
- { \
- if (NM_NARG(__VA_ARGS__) == 1) { \
- g_set_error_literal((error), \
- NM_UTILS_ERROR, \
- (error_code), \
- _NM_UTILS_MACRO_FIRST(__VA_ARGS__)); \
- } else { \
- g_set_error((error), NM_UTILS_ERROR, (error_code), __VA_ARGS__); \
- } \
- } \
- G_STMT_END
-
-#define nm_utils_error_set_errno(error, errsv, fmt, ...) \
- G_STMT_START \
- { \
- char _bstrerr[NM_STRERROR_BUFSIZE]; \
- \
- g_set_error((error), \
- NM_UTILS_ERROR, \
- NM_UTILS_ERROR_UNKNOWN, \
- fmt, \
- ##__VA_ARGS__, \
- nm_strerror_native_r( \
- ({ \
- const int _errsv = (errsv); \
- \
- (_errsv >= 0 ? _errsv \
- : (G_UNLIKELY(_errsv == G_MININT) ? G_MAXINT : -errsv)); \
- }), \
- _bstrerr, \
- sizeof(_bstrerr))); \
- } \
- G_STMT_END
-
-#define nm_utils_error_new(error_code, ...) \
- ((NM_NARG(__VA_ARGS__) == 1) \
- ? g_error_new_literal(NM_UTILS_ERROR, (error_code), _NM_UTILS_MACRO_FIRST(__VA_ARGS__)) \
- : g_error_new(NM_UTILS_ERROR, (error_code), __VA_ARGS__))
-
-/*****************************************************************************/
-
-gboolean nm_g_object_set_property(GObject * object,
- const char * property_name,
- const GValue *value,
- GError ** error);
-
-gboolean nm_g_object_set_property_string(GObject * object,
- const char *property_name,
- const char *value,
- GError ** error);
-
-gboolean nm_g_object_set_property_string_static(GObject * object,
- const char *property_name,
- const char *value,
- GError ** error);
-
-gboolean nm_g_object_set_property_string_take(GObject * object,
- const char *property_name,
- char * value,
- GError ** error);
-
-gboolean nm_g_object_set_property_boolean(GObject * object,
- const char *property_name,
- gboolean value,
- GError ** error);
-
-gboolean nm_g_object_set_property_char(GObject * object,
- const char *property_name,
- gint8 value,
- GError ** error);
-
-gboolean nm_g_object_set_property_uchar(GObject * object,
- const char *property_name,
- guint8 value,
- GError ** error);
-
-gboolean
-nm_g_object_set_property_int(GObject *object, const char *property_name, int value, GError **error);
-
-gboolean nm_g_object_set_property_int64(GObject * object,
- const char *property_name,
- gint64 value,
- GError ** error);
-
-gboolean nm_g_object_set_property_uint(GObject * object,
- const char *property_name,
- guint value,
- GError ** error);
-
-gboolean nm_g_object_set_property_uint64(GObject * object,
- const char *property_name,
- guint64 value,
- GError ** error);
-
-gboolean nm_g_object_set_property_flags(GObject * object,
- const char *property_name,
- GType gtype,
- guint value,
- GError ** error);
-
-gboolean nm_g_object_set_property_enum(GObject * object,
- const char *property_name,
- GType gtype,
- int value,
- GError ** error);
-
-GParamSpec *nm_g_object_class_find_property_from_gtype(GType gtype, const char *property_name);
-
-/*****************************************************************************/
-
-#define _NM_G_PARAM_SPEC_CAST(param_spec, _value_type, _c_type) \
- ({ \
- const GParamSpec *const _param_spec = (param_spec); \
- \
- nm_assert(!_param_spec || _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_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_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_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)
-
-/*****************************************************************************/
-
-GType nm_g_type_find_implementing_class_for_property(GType gtype, const char *pname);
-
-/*****************************************************************************/
-
-typedef enum {
- NM_UTILS_STR_UTF8_SAFE_FLAG_NONE = 0,
-
- /* This flag only has an effect during escaping. */
- NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL = 0x0001,
-
- /* This flag only has an effect during escaping. */
- NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_NON_ASCII = 0x0002,
-
- /* This flag only has an effect during escaping to ensure we
- * don't leak secrets in memory. Note that during unescape we
- * know the maximum result size from the beginning, and no
- * reallocation happens. Thus, unescape always avoids leaking
- * secrets already. */
- NM_UTILS_STR_UTF8_SAFE_FLAG_SECRET = 0x0004,
-
- /* This flag only has an effect during unescaping. It means
- * that non-escaped whitespaces (g_ascii_isspace()) will be
- * stripped from the front and end of the string. Note that
- * this flag is only useful for gracefully accepting user input
- * with spaces. With this flag, escape and unescape may no longer
- * yield the original input. */
- NM_UTILS_STR_UTF8_SAFE_UNESCAPE_STRIP_SPACES = 0x0008,
-} NMUtilsStrUtf8SafeFlags;
-
-const char *nm_utils_buf_utf8safe_escape(gconstpointer buf,
- gssize buflen,
- NMUtilsStrUtf8SafeFlags flags,
- char ** to_free);
-char *
-nm_utils_buf_utf8safe_escape_cp(gconstpointer buf, gssize buflen, NMUtilsStrUtf8SafeFlags flags);
-const char *
-nm_utils_buf_utf8safe_escape_bytes(GBytes *bytes, NMUtilsStrUtf8SafeFlags flags, char **to_free);
-gconstpointer nm_utils_buf_utf8safe_unescape(const char * str,
- NMUtilsStrUtf8SafeFlags flags,
- gsize * out_len,
- gpointer * to_free);
-
-const char *
-nm_utils_str_utf8safe_escape(const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free);
-const char *
-nm_utils_str_utf8safe_unescape(const char *str, NMUtilsStrUtf8SafeFlags flags, char **to_free);
-
-char *nm_utils_str_utf8safe_escape_cp(const char *str, NMUtilsStrUtf8SafeFlags flags);
-char *nm_utils_str_utf8safe_unescape_cp(const char *str, NMUtilsStrUtf8SafeFlags flags);
-
-char *nm_utils_str_utf8safe_escape_take(char *str, NMUtilsStrUtf8SafeFlags flags);
-
-GVariant *nm_g_variant_singleton_u_0(void);
-
-static inline void
-nm_g_variant_unref_floating(GVariant *var)
-{
- /* often a function wants to keep a reference to an input variant.
- * It uses g_variant_ref_sink() to either increase the ref-count,
- * or take ownership of a possibly floating reference.
- *
- * If the function doesn't actually want to do anything with the
- * input variant, it still must make sure that a passed in floating
- * reference is consumed. Hence, this helper which:
- *
- * - does nothing if @var is not floating
- * - unrefs (consumes) @var if it is floating. */
- if (g_variant_is_floating(var))
- g_variant_unref(var);
-}
-
-#define nm_g_variant_lookup(dictionary, ...) \
- ({ \
- GVariant *const _dictionary = (dictionary); \
- \
- (_dictionary && g_variant_lookup(_dictionary, __VA_ARGS__)); \
- })
-
-static inline GVariant *
-nm_g_variant_lookup_value(GVariant *dictionary, const char *key, const GVariantType *expected_type)
-{
- return dictionary ? g_variant_lookup_value(dictionary, key, expected_type) : NULL;
-}
-
-static inline gboolean
-nm_g_variant_is_of_type(GVariant *value, const GVariantType *type)
-{
- return value && g_variant_is_of_type(value, type);
-}
-
-static inline GVariant *
-nm_g_variant_new_ay_inaddr(int addr_family, gconstpointer addr)
-{
- return g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE,
- addr ?: &nm_ip_addr_zero,
- nm_utils_addr_family_to_size(addr_family),
- 1);
-}
-
-static inline GVariant *
-nm_g_variant_new_ay_in4addr(in_addr_t addr)
-{
- return nm_g_variant_new_ay_inaddr(AF_INET, &addr);
-}
-
-static inline GVariant *
-nm_g_variant_new_ay_in6addr(const struct in6_addr *addr)
-{
- return nm_g_variant_new_ay_inaddr(AF_INET6, addr);
-}
-
-static inline void
-nm_g_variant_builder_add_sv(GVariantBuilder *builder, const char *key, GVariant *val)
-{
- g_variant_builder_add(builder, "{sv}", key, val);
-}
-
-static inline void
-nm_g_variant_builder_add_sv_bytearray(GVariantBuilder *builder,
- const char * key,
- const guint8 * arr,
- gsize len)
-{
- g_variant_builder_add(builder,
- "{sv}",
- key,
- g_variant_new_fixed_array(G_VARIANT_TYPE_BYTE, arr, len, 1));
-}
-
-static inline void
-nm_g_variant_builder_add_sv_uint32(GVariantBuilder *builder, const char *key, guint32 val)
-{
- nm_g_variant_builder_add_sv(builder, key, g_variant_new_uint32(val));
-}
-
-static inline void
-nm_g_variant_builder_add_sv_str(GVariantBuilder *builder, const char *key, const char *str)
-{
- nm_g_variant_builder_add_sv(builder, key, g_variant_new_string(str));
-}
-
-static inline void
-nm_g_source_destroy_and_unref(GSource *source)
-{
- g_source_destroy(source);
- g_source_unref(source);
-}
-
-#define nm_clear_g_source_inst(ptr) (nm_clear_pointer((ptr), nm_g_source_destroy_and_unref))
-
-NM_AUTO_DEFINE_FCN0(GSource *, _nm_auto_destroy_and_unref_gsource, nm_g_source_destroy_and_unref);
-#define nm_auto_destroy_and_unref_gsource nm_auto(_nm_auto_destroy_and_unref_gsource)
-
-NM_AUTO_DEFINE_FCN0(GMainContext *, _nm_auto_pop_gmaincontext, g_main_context_pop_thread_default);
-#define nm_auto_pop_gmaincontext nm_auto(_nm_auto_pop_gmaincontext)
-
-static inline gboolean
-nm_source_func_unref_gobject(gpointer user_data)
-{
- nm_assert(G_IS_OBJECT(user_data));
- g_object_unref(user_data);
- return G_SOURCE_REMOVE;
-}
-
-GSource *nm_g_idle_source_new(int priority,
- GSourceFunc func,
- gpointer user_data,
- GDestroyNotify destroy_notify);
-
-GSource *nm_g_timeout_source_new(guint timeout_msec,
- int priority,
- GSourceFunc func,
- gpointer user_data,
- GDestroyNotify destroy_notify);
-
-GSource *nm_g_timeout_source_new_seconds(guint timeout_sec,
- int priority,
- GSourceFunc func,
- 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_signal_source_new(int signum,
- int priority,
- GSourceFunc handler,
- gpointer user_data,
- GDestroyNotify notify);
-
-static inline GSource *
-nm_g_source_attach(GSource *source, GMainContext *context)
-{
- g_source_attach(source, context);
- return source;
-}
-
-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.
- * 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),
- NULL);
-}
-
-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.
- * 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(
- nm_g_timeout_source_new(timeout_msec, G_PRIORITY_DEFAULT, func, user_data, NULL),
- NULL);
-}
-
-static inline GSource *
-nm_g_timeout_add_source_seconds(guint timeout_sec, GSourceFunc func, gpointer user_data)
-{
- /* G 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(
- nm_g_timeout_source_new_seconds(timeout_sec, G_PRIORITY_DEFAULT, func, user_data, NULL),
- NULL);
-}
-
-static inline GSource *
-nm_g_timeout_add_source_approx(guint timeout_msec,
- guint timeout_sec_threshold,
- GSourceFunc func,
- gpointer user_data)
-{
- GSource *source;
-
- /* If timeout_msec is larger or equal than a threshold, then we use g_timeout_source_new_seconds()
- * instead. */
- if (timeout_msec / 1000u >= timeout_sec_threshold)
- source = nm_g_timeout_source_new_seconds(timeout_msec / 1000u,
- G_PRIORITY_DEFAULT,
- func,
- user_data,
- NULL);
- else
- source = nm_g_timeout_source_new(timeout_msec, G_PRIORITY_DEFAULT, func, user_data, NULL);
- return nm_g_source_attach(source, 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)
-
-static inline GMainContext *
-nm_g_main_context_push_thread_default(GMainContext *context)
-{
- /* This function is to work together with nm_auto_pop_gmaincontext. */
- if (G_UNLIKELY(!context))
- context = g_main_context_default();
- g_main_context_push_thread_default(context);
- return context;
-}
-
-static inline gboolean
-nm_g_main_context_is_thread_default(GMainContext *context)
-{
- GMainContext *cur_context;
-
- cur_context = g_main_context_get_thread_default();
- if (cur_context == context)
- return TRUE;
-
- if (G_UNLIKELY(!cur_context))
- cur_context = g_main_context_default();
- else if (G_UNLIKELY(!context))
- context = g_main_context_default();
- else
- return FALSE;
-
- return (cur_context == context);
-}
-
-static inline GMainContext *
-nm_g_main_context_push_thread_default_if_necessary(GMainContext *context)
-{
- GMainContext *cur_context;
-
- cur_context = g_main_context_get_thread_default();
- if (cur_context == context)
- return NULL;
-
- if (G_UNLIKELY(!cur_context)) {
- cur_context = g_main_context_default();
- if (cur_context == context)
- return NULL;
- } else if (G_UNLIKELY(!context)) {
- context = g_main_context_default();
- if (cur_context == context)
- return NULL;
- }
-
- g_main_context_push_thread_default(context);
- return context;
-}
-
-/*****************************************************************************/
-
-static inline int
-nm_utf8_collate0(const char *a, const char *b)
-{
- if (!a)
- return !b ? 0 : -1;
- if (!b)
- return 1;
- return g_utf8_collate(a, b);
-}
-
-int nm_strcmp_with_data(gconstpointer a, gconstpointer b, gpointer user_data);
-int nm_strcmp_p_with_data(gconstpointer a, gconstpointer b, gpointer user_data);
-int nm_strcmp0_p_with_data(gconstpointer a, gconstpointer b, gpointer user_data);
-int nm_strcmp_ascii_case_with_data(gconstpointer a, gconstpointer b, gpointer user_data);
-int nm_cmp_uint32_p_with_data(gconstpointer p_a, gconstpointer p_b, gpointer user_data);
-int nm_cmp_int2ptr_p_with_data(gconstpointer p_a, gconstpointer p_b, gpointer user_data);
-
-/*****************************************************************************/
-
-typedef struct {
- const char *name;
-} NMUtilsNamedEntry;
-
-typedef struct {
- union {
- NMUtilsNamedEntry named_entry;
- const char * name;
- };
- union {
- const char *value_str;
- gpointer value_ptr;
- };
-} NMUtilsNamedValue;
-
-#define NM_UTILS_NAMED_VALUE_INIT(n, v) \
- { \
- .name = (n), .value_ptr = (v) \
- }
-
-NMUtilsNamedValue *
-nm_utils_named_values_from_strdict_full(GHashTable * hash,
- guint * out_len,
- GCompareDataFunc compare_func,
- gpointer user_data,
- NMUtilsNamedValue * provided_buffer,
- guint provided_buffer_len,
- NMUtilsNamedValue **out_allocated_buffer);
-
-#define nm_utils_named_values_from_strdict(hash, out_len, array, out_allocated_buffer) \
- nm_utils_named_values_from_strdict_full((hash), \
- (out_len), \
- nm_strcmp_p_with_data, \
- NULL, \
- (array), \
- G_N_ELEMENTS(array), \
- (out_allocated_buffer))
-
-gssize nm_utils_named_value_list_find(const NMUtilsNamedValue *arr,
- gsize len,
- const char * name,
- gboolean sorted);
-
-gboolean nm_utils_named_value_list_is_sorted(const NMUtilsNamedValue *arr,
- gsize len,
- gboolean accept_duplicates,
- GCompareDataFunc compare_func,
- gpointer user_data);
-
-void nm_utils_named_value_list_sort(NMUtilsNamedValue *arr,
- gsize len,
- GCompareDataFunc compare_func,
- gpointer user_data);
-
-void nm_utils_named_value_clear_with_g_free(NMUtilsNamedValue *val);
-
-/*****************************************************************************/
-
-gpointer *nm_utils_hash_keys_to_array(GHashTable * hash,
- GCompareDataFunc compare_func,
- gpointer user_data,
- guint * out_len);
-
-gpointer *nm_utils_hash_values_to_array(GHashTable * hash,
- GCompareDataFunc compare_func,
- gpointer user_data,
- guint * out_len);
-
-static inline const char **
-nm_utils_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,
- NULL,
- out_length);
-}
-
-gboolean nm_utils_hashtable_equal(const GHashTable *a,
- const GHashTable *b,
- gboolean treat_null_as_empty,
- GEqualFunc equal_func);
-
-gboolean nm_utils_hashtable_cmp_equal(const GHashTable *a,
- const GHashTable *b,
- GCompareDataFunc cmp_values,
- gpointer user_data);
-
-static inline gboolean
-nm_utils_hashtable_same_keys(const GHashTable *a, const GHashTable *b)
-{
- return nm_utils_hashtable_cmp_equal(a, b, NULL, NULL);
-}
-
-int nm_utils_hashtable_cmp(const GHashTable *a,
- const GHashTable *b,
- gboolean do_fast_precheck,
- GCompareDataFunc cmp_keys,
- GCompareDataFunc cmp_values,
- gpointer user_data);
-
-char **nm_utils_strv_make_deep_copied(const char **strv);
-
-char **nm_utils_strv_make_deep_copied_n(const char **strv, gsize len);
-
-static inline char **
-nm_utils_strv_make_deep_copied_nonnull(const char **strv)
-{
- return nm_utils_strv_make_deep_copied(strv) ?: g_new0(char *, 1);
-}
-
-char **_nm_utils_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))
-
-const char **_nm_utils_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))
-
-/*****************************************************************************/
-
-GSList *nm_utils_g_slist_find_str(const GSList *list, const char *needle);
-
-int nm_utils_g_slist_strlist_cmp(const GSList *a, const GSList *b);
-
-char *nm_utils_g_slist_strlist_join(const GSList *a, const char *separator);
-
-/*****************************************************************************/
-
-static inline guint
-nm_g_array_len(const GArray *arr)
-{
- return arr ? arr->len : 0u;
-}
-
-static inline void
-nm_g_array_unref(GArray *arr)
-{
- if (arr)
- g_array_unref(arr);
-}
-
-#define nm_g_array_append_new(arr, type) \
- ({ \
- GArray *const _arr = (arr); \
- guint _len; \
- \
- nm_assert(_arr); \
- _len = _arr->len; \
- nm_assert(_len < G_MAXUINT); \
- g_array_set_size(_arr, _len + 1u); \
- &g_array_index(arr, type, _len); \
- })
-
-/*****************************************************************************/
-
-static inline GPtrArray *
-nm_g_ptr_array_ref(GPtrArray *arr)
-{
- return arr ? g_ptr_array_ref(arr) : NULL;
-}
-
-static inline void
-nm_g_ptr_array_unref(GPtrArray *arr)
-{
- if (arr)
- g_ptr_array_unref(arr);
-}
-
-#define nm_g_ptr_array_set(pdst, val) \
- ({ \
- GPtrArray **_pdst = (pdst); \
- GPtrArray * _val = (val); \
- gboolean _changed = FALSE; \
- \
- nm_assert(_pdst); \
- \
- if (*_pdst != _val) { \
- _nm_unused gs_unref_ptrarray GPtrArray *_old = *_pdst; \
- \
- *_pdst = nm_g_ptr_array_ref(_val); \
- _changed = TRUE; \
- } \
- _changed; \
- })
-
-#define nm_g_ptr_array_set_take(pdst, val) \
- ({ \
- GPtrArray **_pdst = (pdst); \
- GPtrArray * _val = (val); \
- gboolean _changed = FALSE; \
- \
- nm_assert(_pdst); \
- \
- if (*_pdst != _val) { \
- _nm_unused gs_unref_ptrarray GPtrArray *_old = *_pdst; \
- \
- *_pdst = _val; \
- _changed = TRUE; \
- } else { \
- nm_g_ptr_array_unref(_val); \
- } \
- _changed; \
- })
-
-static inline guint
-nm_g_ptr_array_len(const GPtrArray *arr)
-{
- return arr ? arr->len : 0u;
-}
-
-static inline gpointer *
-nm_g_ptr_array_pdata(const GPtrArray *arr)
-{
- return arr ? arr->pdata : NULL;
-}
-
-GPtrArray *_nm_g_ptr_array_copy(GPtrArray * array,
- GCopyFunc func,
- gpointer user_data,
- GDestroyNotify element_free_func);
-
-/**
- * nm_g_ptr_array_copy:
- * @array: the #GPtrArray to clone.
- * @func: the copy function.
- * @user_data: the user data for the copy function
- * @element_free_func: the free function of the elements. @array MUST have
- * the same element_free_func. This argument is only used on older
- * glib, that doesn't support g_ptr_array_copy().
- *
- * This is a replacement for g_ptr_array_copy(), which is not available
- * before glib 2.62. Since GPtrArray does not allow to access the internal
- * element_free_func, we cannot add a compatibility implementation of g_ptr_array_copy()
- * and the user must provide a suitable destroy function.
- *
- * 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; \
- })
-#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))
-#endif
-
-/*****************************************************************************/
-
-static inline GHashTable *
-nm_g_hash_table_ref(GHashTable *hash)
-{
- return hash ? g_hash_table_ref(hash) : NULL;
-}
-
-static inline void
-nm_g_hash_table_unref(GHashTable *hash)
-{
- if (hash)
- g_hash_table_unref(hash);
-}
-
-static inline guint
-nm_g_hash_table_size(GHashTable *hash)
-{
- return hash ? g_hash_table_size(hash) : 0u;
-}
-
-static inline gpointer
-nm_g_hash_table_lookup(GHashTable *hash, gconstpointer key)
-{
- return hash ? g_hash_table_lookup(hash, key) : NULL;
-}
-
-static inline gboolean
-nm_g_hash_table_contains(GHashTable *hash, gconstpointer key)
-{
- return hash ? g_hash_table_contains(hash, key) : FALSE;
-}
-
-static inline gboolean
-nm_g_hash_table_remove(GHashTable *hash, gconstpointer key)
-{
- return hash ? g_hash_table_remove(hash, key) : FALSE;
-}
-
-/*****************************************************************************/
-
-gssize nm_utils_ptrarray_find_binary_search(gconstpointer * list,
- gsize len,
- gconstpointer needle,
- GCompareDataFunc cmpfcn,
- gpointer user_data,
- gssize * out_idx_first,
- gssize * out_idx_last);
-
-gssize nm_utils_array_find_binary_search(gconstpointer list,
- gsize elem_size,
- gsize len,
- gconstpointer needle,
- GCompareDataFunc cmpfcn,
- gpointer user_data);
-
-/*****************************************************************************/
-
-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)
-
-int
-_nm_utils_strv_cmp_n(const char *const *strv1, gssize len1, const char *const *strv2, gssize len2);
-
-#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_utils_strv_equal(strv1, strv2) (nm_utils_strv_cmp_n((strv1), -1, (strv2), -1) == 0)
-
-/*****************************************************************************/
-
-#define NM_UTILS_NSEC_PER_SEC ((gint64) 1000000000)
-#define NM_UTILS_USEC_PER_SEC ((gint64) 1000000)
-#define NM_UTILS_MSEC_PER_SEC ((gint64) 1000)
-#define NM_UTILS_NSEC_PER_MSEC ((gint64) 1000000)
-
-static inline gint64
-NM_UTILS_NSEC_TO_MSEC_CEIL(gint64 nsec)
-{
- return (nsec + (NM_UTILS_NSEC_PER_MSEC - 1)) / NM_UTILS_NSEC_PER_MSEC;
-}
-
-/*****************************************************************************/
-
-int nm_utils_fd_wait_for_event(int fd, int event, gint64 timeout_nsec);
-ssize_t nm_utils_fd_read_loop(int fd, void *buf, size_t nbytes, bool do_poll);
-int nm_utils_fd_read_loop_exact(int fd, void *buf, size_t nbytes, bool do_poll);
-
-/*****************************************************************************/
-
-#define NM_DEFINE_GDBUS_ARG_INFO_FULL(name_, ...) \
- ((GDBusArgInfo *) (&((const GDBusArgInfo){.ref_count = -1, .name = name_, __VA_ARGS__})))
-
-#define NM_DEFINE_GDBUS_ARG_INFO(name_, a_signature) \
- NM_DEFINE_GDBUS_ARG_INFO_FULL(name_, .signature = a_signature, )
-
-#define NM_DEFINE_GDBUS_ARG_INFOS(...) \
- ((GDBusArgInfo **) ((const GDBusArgInfo *[]){ \
- __VA_ARGS__ NULL, \
- }))
-
-#define NM_DEFINE_GDBUS_PROPERTY_INFO(name_, ...) \
- ((GDBusPropertyInfo *) (&( \
- (const GDBusPropertyInfo){.ref_count = -1, .name = name_, __VA_ARGS__})))
-
-#define NM_DEFINE_GDBUS_PROPERTY_INFO_READABLE(name_, m_signature) \
- NM_DEFINE_GDBUS_PROPERTY_INFO(name_, \
- .signature = m_signature, \
- .flags = G_DBUS_PROPERTY_INFO_FLAGS_READABLE, )
-
-#define NM_DEFINE_GDBUS_PROPERTY_INFOS(...) \
- ((GDBusPropertyInfo **) ((const GDBusPropertyInfo *[]){ \
- __VA_ARGS__ NULL, \
- }))
-
-#define NM_DEFINE_GDBUS_SIGNAL_INFO_INIT(name_, ...) \
- { \
- .ref_count = -1, .name = name_, __VA_ARGS__ \
- }
-
-#define NM_DEFINE_GDBUS_SIGNAL_INFO(name_, ...) \
- ((GDBusSignalInfo *) (&( \
- (const GDBusSignalInfo) NM_DEFINE_GDBUS_SIGNAL_INFO_INIT(name_, __VA_ARGS__))))
-
-#define NM_DEFINE_GDBUS_SIGNAL_INFOS(...) \
- ((GDBusSignalInfo **) ((const GDBusSignalInfo *[]){ \
- __VA_ARGS__ NULL, \
- }))
-
-#define NM_DEFINE_GDBUS_METHOD_INFO_INIT(name_, ...) \
- { \
- .ref_count = -1, .name = name_, __VA_ARGS__ \
- }
-
-#define NM_DEFINE_GDBUS_METHOD_INFO(name_, ...) \
- ((GDBusMethodInfo *) (&( \
- (const GDBusMethodInfo) NM_DEFINE_GDBUS_METHOD_INFO_INIT(name_, __VA_ARGS__))))
-
-#define NM_DEFINE_GDBUS_METHOD_INFOS(...) \
- ((GDBusMethodInfo **) ((const GDBusMethodInfo *[]){ \
- __VA_ARGS__ NULL, \
- }))
-
-#define NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(name_, ...) \
- { \
- .ref_count = -1, .name = name_, __VA_ARGS__ \
- }
-
-#define NM_DEFINE_GDBUS_INTERFACE_INFO(name_, ...) \
- ((GDBusInterfaceInfo *) (&( \
- (const GDBusInterfaceInfo) NM_DEFINE_GDBUS_INTERFACE_INFO_INIT(name_, __VA_ARGS__))))
-
-#define NM_DEFINE_GDBUS_INTERFACE_VTABLE(...) \
- ((GDBusInterfaceVTable *) (&((const GDBusInterfaceVTable){__VA_ARGS__})))
-
-/*****************************************************************************/
-
-guint64 nm_utils_get_start_time_for_pid(pid_t pid, char *out_state, pid_t *out_ppid);
-
-static inline gboolean
-nm_utils_process_state_is_dead(char pstate)
-{
- /* "/proc/[pid]/stat" returns a state as the 3rd fields (see `man 5 proc`).
- * Some of these states indicate the process is effectively dead (or a zombie).
- */
- return NM_IN_SET(pstate, 'Z', 'x', 'X');
-}
-
-/*****************************************************************************/
-
-typedef struct _NMUtilsUserData NMUtilsUserData;
-
-NMUtilsUserData *_nm_utils_user_data_pack(int nargs, gconstpointer *args);
-
-#define nm_utils_user_data_pack(...) \
- _nm_utils_user_data_pack(NM_NARG(__VA_ARGS__), (gconstpointer[]){__VA_ARGS__})
-
-void _nm_utils_user_data_unpack(NMUtilsUserData *user_data, int nargs, ...);
-
-#define nm_utils_user_data_unpack(user_data, ...) \
- _nm_utils_user_data_unpack(user_data, NM_NARG(__VA_ARGS__), __VA_ARGS__)
-
-/*****************************************************************************/
-
-typedef void (*NMUtilsInvokeOnIdleCallback)(gpointer user_data, GCancellable *cancellable);
-
-void nm_utils_invoke_on_idle(GCancellable * cancellable,
- NMUtilsInvokeOnIdleCallback callback,
- gpointer callback_user_data);
-
-void nm_utils_invoke_on_timeout(guint timeout_msec,
- GCancellable * cancellable,
- NMUtilsInvokeOnIdleCallback callback,
- gpointer callback_user_data);
-
-/*****************************************************************************/
-
-GSource *nm_utils_g_main_context_create_integrate_source(GMainContext *internal);
-
-/*****************************************************************************/
-
-static inline GPtrArray *
-nm_strv_ptrarray_ensure(GPtrArray **p_arr)
-{
- nm_assert(p_arr);
-
- if (G_UNLIKELY(!*p_arr))
- *p_arr = g_ptr_array_new_with_free_func(g_free);
-
- return *p_arr;
-}
-
-static inline const char *const *
-nm_strv_ptrarray_get_unsafe(GPtrArray *arr, guint *out_len)
-{
- /* warning: the GPtrArray is not NULL terminated. So, it
- * isn't really a strv array (sorry the misnomer). That's why
- * the function is potentially "unsafe" and you must provide a
- * out_len parameter. */
- if (!arr || arr->len == 0) {
- *out_len = 0;
- return NULL;
- }
- *out_len = arr->len;
- return (const char *const *) arr->pdata;
-}
-
-static inline GPtrArray *
-nm_strv_ptrarray_clone(const GPtrArray *src, gboolean null_if_empty)
-{
- if (!src || (null_if_empty && src->len == 0))
- return NULL;
- return nm_g_ptr_array_copy((GPtrArray *) src, nm_copy_func_g_strdup, NULL, g_free);
-}
-
-static inline void
-nm_strv_ptrarray_add_string_take(GPtrArray *cmd, char *str)
-{
- nm_assert(cmd);
- nm_assert(str);
-
- g_ptr_array_add(cmd, str);
-}
-
-static inline void
-nm_strv_ptrarray_add_string_dup(GPtrArray *cmd, const char *str)
-{
- nm_strv_ptrarray_add_string_take(cmd, g_strdup(str));
-}
-
-#define nm_strv_ptrarray_add_string_concat(cmd, ...) \
- nm_strv_ptrarray_add_string_take((cmd), g_strconcat(__VA_ARGS__, NULL))
-
-#define nm_strv_ptrarray_add_string_printf(cmd, ...) \
- nm_strv_ptrarray_add_string_take((cmd), g_strdup_printf(__VA_ARGS__))
-
-#define nm_strv_ptrarray_add_int(cmd, val) \
- nm_strv_ptrarray_add_string_take((cmd), nm_strdup_int(val))
-
-static inline void
-nm_strv_ptrarray_take_gstring(GPtrArray *cmd, GString **gstr)
-{
- nm_assert(gstr && *gstr);
-
- nm_strv_ptrarray_add_string_take(cmd, g_string_free(g_steal_pointer(gstr), FALSE));
-}
-
-static inline gssize
-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);
-}
-
-static inline gboolean
-nm_strv_ptrarray_contains(const GPtrArray *strv, const char *str)
-{
- return nm_strv_ptrarray_find_first(strv, str) >= 0;
-}
-
-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.
- * 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));
-}
-
-/*****************************************************************************/
-
-int nm_utils_getpagesize(void);
-
-/*****************************************************************************/
-
-extern const char _nm_hexchar_table_lower[16];
-extern const char _nm_hexchar_table_upper[16];
-
-static inline char
-nm_hexchar(int x, gboolean upper_case)
-{
- return upper_case ? _nm_hexchar_table_upper[x & 15] : _nm_hexchar_table_lower[x & 15];
-}
-
-char *nm_utils_bin2hexstr_full(gconstpointer addr,
- gsize length,
- char delimiter,
- gboolean upper_case,
- char * out);
-
-#define nm_utils_bin2hexstr_a(addr, length, delimiter, upper_case, str_to_free) \
- ({ \
- gconstpointer _addr = (addr); \
- gsize _length = (length); \
- char _delimiter = (delimiter); \
- char ** _str_to_free = (str_to_free); \
- char * _s; \
- gsize _s_len; \
- \
- nm_assert(_str_to_free); \
- \
- _s_len = _length == 0 ? 1u : (_delimiter == '\0' ? _length * 2u + 1u : _length * 3u); \
- if (_s_len < 100) \
- _s = g_alloca(_s_len); \
- else { \
- _s = g_malloc(_s_len); \
- *_str_to_free = _s; \
- } \
- nm_utils_bin2hexstr_full(_addr, _length, _delimiter, (upper_case), _s); \
- })
-
-static inline const char *
-nm_ether_addr_to_string(const NMEtherAddr *ether_addr, char sbuf[static(sizeof(NMEtherAddr) * 3)])
-{
- nm_assert(ether_addr);
- nm_assert(sbuf);
-
- return nm_utils_bin2hexstr_full(ether_addr, sizeof(NMEtherAddr), ':', TRUE, sbuf);
-}
-
-#define nm_ether_addr_to_string_a(ether_addr) \
- nm_ether_addr_to_string((ether_addr), g_alloca(sizeof(NMEtherAddr) * 3))
-
-guint8 *nm_utils_hexstr2bin_full(const char *hexstr,
- gboolean allow_0x_prefix,
- gboolean delimiter_required,
- gboolean hexdigit_pairs_required,
- const char *delimiter_candidates,
- gsize required_len,
- guint8 * buffer,
- gsize buffer_len,
- gsize * out_len);
-
-#define nm_utils_hexstr2bin_buf(hexstr, \
- allow_0x_prefix, \
- delimiter_required, \
- delimiter_candidates, \
- buffer) \
- nm_utils_hexstr2bin_full((hexstr), \
- (allow_0x_prefix), \
- (delimiter_required), \
- FALSE, \
- (delimiter_candidates), \
- G_N_ELEMENTS(buffer), \
- (buffer), \
- G_N_ELEMENTS(buffer), \
- NULL)
-
-guint8 *nm_utils_hexstr2bin_alloc(const char *hexstr,
- gboolean allow_0x_prefix,
- gboolean delimiter_required,
- const char *delimiter_candidates,
- gsize required_len,
- gsize * out_len);
-
-/**
- * _nm_utils_hwaddr_aton:
- * @asc: the ASCII representation of a hardware address
- * @buffer: buffer to store the result into. Must have
- * at least a size of @buffer_length.
- * @buffer_length: the length of the input buffer @buffer.
- * The result must fit into that buffer, otherwise
- * the function fails and returns %NULL.
- * @out_length: the output length in case of success.
- *
- * Parses @asc and converts it to binary form in @buffer.
- * Bytes in @asc can be separated by colons (:), or hyphens (-), but not mixed.
- *
- * It is like nm_utils_hwaddr_aton(), but contrary to that it
- * can parse addresses of any length. That is, you don't need
- * to know the length before-hand.
- *
- * Return value: @buffer, or %NULL if @asc couldn't be parsed.
- */
-static inline guint8 *
-_nm_utils_hwaddr_aton(const char *asc, gpointer buffer, gsize buffer_length, gsize *out_length)
-{
- g_return_val_if_fail(asc, NULL);
- g_return_val_if_fail(buffer, NULL);
- g_return_val_if_fail(buffer_length > 0, NULL);
- g_return_val_if_fail(out_length, NULL);
-
- return nm_utils_hexstr2bin_full(asc,
- FALSE,
- TRUE,
- FALSE,
- ":-",
- 0,
- buffer,
- buffer_length,
- out_length);
-}
-
-static inline guint8 *
-_nm_utils_hwaddr_aton_exact(const char *asc, gpointer buffer, gsize buffer_length)
-{
- g_return_val_if_fail(asc, NULL);
- g_return_val_if_fail(buffer, NULL);
- g_return_val_if_fail(buffer_length > 0, NULL);
-
- return nm_utils_hexstr2bin_full(asc,
- FALSE,
- TRUE,
- FALSE,
- ":-",
- buffer_length,
- buffer,
- buffer_length,
- NULL);
-}
-
-static inline const char *
-_nm_utils_hwaddr_ntoa(gconstpointer addr,
- gsize addr_len,
- gboolean upper_case,
- char * buf,
- gsize buf_len)
-{
- g_return_val_if_fail(addr, NULL);
- g_return_val_if_fail(addr_len > 0, NULL);
- g_return_val_if_fail(buf, NULL);
- if (buf_len < addr_len * 3)
- g_return_val_if_reached(NULL);
-
- return nm_utils_bin2hexstr_full(addr, addr_len, ':', upper_case, buf);
-}
-
-/*****************************************************************************/
-
-#define _NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(fcn_name, \
- value_type, \
- value_type_result, \
- entry_cmd, \
- unknown_val_cmd, \
- get_operator, \
- ...) \
- value_type_result fcn_name(const char *name) \
- { \
- static const struct { \
- const char *name; \
- value_type value; \
- } LIST[] = {__VA_ARGS__}; \
- \
- if (NM_MORE_ASSERT_ONCE(5)) { \
- int i; \
- \
- for (i = 0; i < G_N_ELEMENTS(LIST); i++) { \
- nm_assert(LIST[i].name); \
- if (i > 0) \
- nm_assert(strcmp(LIST[i - 1].name, LIST[i].name) < 0); \
- } \
- } \
- \
- { \
- entry_cmd; \
- } \
- \
- if (G_LIKELY(name)) { \
- G_STATIC_ASSERT(G_N_ELEMENTS(LIST) > 1); \
- G_STATIC_ASSERT(G_N_ELEMENTS(LIST) < G_MAXINT / 2 - 10); \
- int imin = 0; \
- int imax = (G_N_ELEMENTS(LIST) - 1); \
- int imid = (G_N_ELEMENTS(LIST) - 1) / 2; \
- \
- for (;;) { \
- const int cmp = strcmp(LIST[imid].name, name); \
- \
- if (G_UNLIKELY(cmp == 0)) \
- return get_operator(LIST[imid].value); \
- \
- if (cmp < 0) \
- imin = imid + 1; \
- else \
- imax = imid - 1; \
- \
- if (G_UNLIKELY(imin > imax)) \
- break; \
- \
- /* integer overflow cannot happen, because LIST is shorter than G_MAXINT/2. */ \
- imid = (imin + imax) / 2; \
- } \
- } \
- \
- { \
- unknown_val_cmd; \
- } \
- } \
- _NM_DUMMY_STRUCT_FOR_TRAILING_SEMICOLON
-
-#define NM_UTILS_STRING_TABLE_LOOKUP_STRUCT_DEFINE(fcn_name, \
- result_type, \
- entry_cmd, \
- unknown_val_cmd, \
- ...) \
- _NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(fcn_name, \
- result_type, \
- const result_type *, \
- entry_cmd, \
- unknown_val_cmd, \
- &, \
- __VA_ARGS__)
-
-#define NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(fcn_name, \
- result_type, \
- entry_cmd, \
- unknown_val_cmd, \
- ...) \
- _NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(fcn_name, \
- result_type, \
- result_type, \
- entry_cmd, \
- unknown_val_cmd, \
- , \
- __VA_ARGS__)
-
-/*****************************************************************************/
-
-static inline GTask *
-nm_g_task_new(gpointer source_object,
- GCancellable * cancellable,
- gpointer source_tag,
- GAsyncReadyCallback callback,
- gpointer callback_data)
-{
- GTask *task;
-
- task = g_task_new(source_object, cancellable, callback, callback_data);
- if (source_tag)
- g_task_set_source_tag(task, source_tag);
- return task;
-}
-
-static inline gboolean
-nm_g_task_is_valid(gpointer task, gpointer source_object, gpointer source_tag)
-{
- return g_task_is_valid(task, source_object) && g_task_get_source_tag(task) == source_tag;
-}
-
-guint nm_utils_parse_debug_string(const char *string, const GDebugKey *keys, guint nkeys);
-
-/*****************************************************************************/
-
-static inline gboolean
-nm_utils_strdup_reset(char **dst, const char *src)
-{
- char *old;
-
- nm_assert(dst);
-
- if (nm_streq0(*dst, src))
- return FALSE;
- old = *dst;
- *dst = g_strdup(src);
- g_free(old);
- return TRUE;
-}
-
-static inline gboolean
-nm_utils_strdup_reset_take(char **dst, char *src)
-{
- char *old;
-
- nm_assert(dst);
- nm_assert(src != *dst);
-
- if (nm_streq0(*dst, src)) {
- if (src)
- g_free(src);
- return FALSE;
- }
- old = *dst;
- *dst = src;
- g_free(old);
- return TRUE;
-}
-
-void nm_indirect_g_free(gpointer arg);
-
-/*****************************************************************************/
-
-void nm_utils_ifname_cpy(char *dst, const char *name);
-
-typedef enum {
- NMU_IFACE_ANY,
- NMU_IFACE_KERNEL,
- NMU_IFACE_OVS,
- NMU_IFACE_OVS_AND_KERNEL,
-} NMUtilsIfaceType;
-
-gboolean nm_utils_ifname_valid_kernel(const char *name, GError **error);
-
-gboolean nm_utils_ifname_valid(const char *name, NMUtilsIfaceType type, GError **error);
-
-/*****************************************************************************/
-
-static inline GArray *
-nm_strvarray_ensure(GArray **p)
-{
- if (!*p) {
- *p = g_array_new(TRUE, FALSE, sizeof(char *));
- g_array_set_clear_func(*p, nm_indirect_g_free);
- }
- return *p;
-}
-
-static inline void
-nm_strvarray_add(GArray *array, const char *str)
-{
- char *s;
-
- s = g_strdup(str);
- g_array_append_val(array, s);
-}
-
-static inline const char *const *
-nm_strvarray_get_strv_non_empty(GArray *arr, guint *length)
-{
- if (!arr || arr->len == 0) {
- NM_SET_OUT(length, 0);
- return NULL;
- }
-
- NM_SET_OUT(length, arr->len);
- return &g_array_index(arr, const char *, 0);
-}
-
-static inline const char *const *
-nm_strvarray_get_strv(GArray **arr, guint *length)
-{
- if (!*arr) {
- NM_SET_OUT(length, 0);
- return (const char *const *) arr;
- }
-
- NM_SET_OUT(length, (*arr)->len);
- return &g_array_index(*arr, const char *, 0);
-}
-
-static inline void
-nm_strvarray_set_strv(GArray **array, const char *const *strv)
-{
- gs_unref_array GArray *array_old = NULL;
-
- array_old = g_steal_pointer(array);
-
- if (!strv || !strv[0])
- return;
-
- nm_strvarray_ensure(array);
- for (; strv[0]; strv++)
- nm_strvarray_add(*array, strv[0]);
-}
-
-static inline gboolean
-nm_strvarray_remove_first(GArray *strv, const char *needle)
-{
- guint i;
-
- nm_assert(needle);
-
- if (strv) {
- for (i = 0; i < strv->len; i++) {
- if (nm_streq(needle, g_array_index(strv, const char *, i))) {
- g_array_remove_index(strv, i);
- return TRUE;
- }
- }
- }
- return FALSE;
-}
-
-/*****************************************************************************/
-
-struct _NMVariantAttributeSpec {
- char * name;
- const GVariantType *type;
- bool v4 : 1;
- bool v6 : 1;
- bool no_value : 1;
- bool consumes_rest : 1;
- char str_type;
-};
-
-typedef struct _NMVariantAttributeSpec NMVariantAttributeSpec;
-
-void _nm_utils_format_variant_attributes_full(GString * str,
- const NMUtilsNamedValue * values,
- guint num_values,
- const NMVariantAttributeSpec *const *spec,
- char attr_separator,
- char key_value_separator);
-
-char *_nm_utils_format_variant_attributes(GHashTable * attributes,
- const NMVariantAttributeSpec *const *spec,
- char attr_separator,
- char key_value_separator);
-
-/*****************************************************************************/
-
-gboolean nm_utils_is_localhost(const char *name);
-
-gboolean nm_utils_is_specific_hostname(const char *name);
-
-char * nm_utils_uid_to_name(uid_t uid);
-gboolean nm_utils_name_to_uid(const char *name, uid_t *out_uid);
-
-#endif /* __NM_SHARED_UTILS_H__ */
diff --git a/shared/nm-glib-aux/nm-str-buf.h b/shared/nm-glib-aux/nm-str-buf.h
deleted file mode 100644
index cb0d3fb189..0000000000
--- a/shared/nm-glib-aux/nm-str-buf.h
+++ /dev/null
@@ -1,488 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#ifndef __NM_STR_BUF_H__
-#define __NM_STR_BUF_H__
-
-#include "nm-shared-utils.h"
-#include "nm-secret-utils.h"
-
-/*****************************************************************************/
-
-/* NMStrBuf is not unlike GString. The main difference is that it can use
- * nm_explicit_bzero() when growing the buffer. */
-typedef struct _NMStrBuf {
- char *_priv_str;
-
- /* The unions only exist because we allow/encourage read-only access
- * to the "len" and "allocated" fields, but modifying the fields is
- * only allowed to the NMStrBuf implementation itself. */
- union {
- /*const*/ gsize len;
- gsize _priv_len;
- };
- union {
- /*const*/ gsize allocated;
- gsize _priv_allocated;
- };
-
- bool _priv_do_bzero_mem;
-} NMStrBuf;
-
-/*****************************************************************************/
-
-static inline void
-_nm_str_buf_assert(const NMStrBuf *strbuf)
-{
- nm_assert(strbuf);
- nm_assert((!!strbuf->_priv_str) == (strbuf->_priv_allocated > 0));
- nm_assert(strbuf->_priv_len <= strbuf->_priv_allocated);
-}
-
-static inline NMStrBuf
-NM_STR_BUF_INIT(gsize allocated, gboolean do_bzero_mem)
-{
- NMStrBuf strbuf = {
- ._priv_str = allocated ? g_malloc(allocated) : NULL,
- ._priv_allocated = allocated,
- ._priv_len = 0,
- ._priv_do_bzero_mem = do_bzero_mem,
- };
-
- return strbuf;
-}
-
-static inline void
-nm_str_buf_init(NMStrBuf *strbuf, gsize len, bool do_bzero_mem)
-{
- nm_assert(strbuf);
- *strbuf = NM_STR_BUF_INIT(len, do_bzero_mem);
- _nm_str_buf_assert(strbuf);
-}
-
-void _nm_str_buf_ensure_size(NMStrBuf *strbuf, gsize new_size, gboolean reserve_exact);
-
-static inline void
-nm_str_buf_maybe_expand(NMStrBuf *strbuf, gsize reserve, gboolean reserve_exact)
-{
- _nm_str_buf_assert(strbuf);
- nm_assert(strbuf->_priv_len < G_MAXSIZE - reserve);
-
- /* @reserve is the extra space that we require. */
- if (G_UNLIKELY(reserve > strbuf->_priv_allocated - strbuf->_priv_len))
- _nm_str_buf_ensure_size(strbuf, strbuf->_priv_len + reserve, reserve_exact);
-}
-
-/*****************************************************************************/
-
-/**
- * nm_str_buf_set_size:
- * @strbuf: the initialized #NMStrBuf
- * @new_len: the new length
- * @honor_do_bzero_mem: if %TRUE, the shrunk memory will be cleared, if
- * do_bzero_mem is set. This should be usually set to %TRUE, unless
- * you know that the shrunk memory does not contain data that requires to be
- * cleared. When growing the size, this value has no effect.
- * @reserve_exact: when growing the buffer, reserve the exact amount of bytes.
- * If %FALSE, the buffer may allocate more memory than requested to grow
- * exponentially.
- *
- * This is like g_string_set_size(). If new_len is smaller than the
- * current length, the string gets truncated (excess memory will be cleared).
- *
- * When extending the length, the added bytes are undefined (like with
- * g_string_set_size(). Likewise, if you first pre-allocate a buffer with
- * nm_str_buf_maybe_expand(), then write to the bytes, and finally set
- * the appropriate size, then that works as expected (by not clearing the
- * pre-existing, grown buffer).
- */
-static inline void
-nm_str_buf_set_size(NMStrBuf *strbuf,
- gsize new_len,
- gboolean honor_do_bzero_mem,
- gboolean reserve_exact)
-{
- _nm_str_buf_assert(strbuf);
-
- if (new_len < strbuf->_priv_len) {
- if (honor_do_bzero_mem && strbuf->_priv_do_bzero_mem) {
- /* we only clear the memory that we wrote to. */
- nm_explicit_bzero(&strbuf->_priv_str[new_len], strbuf->_priv_len - new_len);
- }
- } else if (new_len > strbuf->_priv_len) {
- nm_str_buf_maybe_expand(strbuf,
- new_len - strbuf->_priv_len + (reserve_exact ? 0u : 1u),
- reserve_exact);
- } else
- return;
-
- strbuf->_priv_len = new_len;
-}
-
-/*****************************************************************************/
-
-static inline void
-nm_str_buf_erase(NMStrBuf *strbuf, gsize pos, gssize len, gboolean honor_do_bzero_mem)
-{
- gsize new_len;
-
- _nm_str_buf_assert(strbuf);
-
- nm_assert(pos <= strbuf->_priv_len);
-
- if (len == 0)
- return;
-
- if (len < 0) {
- /* truncate the string before pos */
- nm_assert(len == -1);
- new_len = pos;
- } else {
- gsize l = len;
-
- nm_assert(l <= strbuf->_priv_len - pos);
-
- new_len = strbuf->_priv_len - l;
- if (pos + l < strbuf->_priv_len) {
- memmove(&strbuf->_priv_str[pos],
- &strbuf->_priv_str[pos + l],
- strbuf->_priv_len - (pos + l));
- }
- }
-
- nm_assert(new_len <= strbuf->_priv_len);
- nm_str_buf_set_size(strbuf, new_len, honor_do_bzero_mem, TRUE);
-}
-
-/*****************************************************************************/
-
-static inline void
-nm_str_buf_append_c_repeated(NMStrBuf *strbuf, char ch, guint len)
-{
- if (len > 0) {
- nm_str_buf_maybe_expand(strbuf, len + 1, FALSE);
- do {
- strbuf->_priv_str[strbuf->_priv_len++] = ch;
- } while (--len > 0);
- }
-}
-
-static inline void
-nm_str_buf_append_c(NMStrBuf *strbuf, char ch)
-{
- nm_str_buf_maybe_expand(strbuf, 2, FALSE);
- strbuf->_priv_str[strbuf->_priv_len++] = ch;
-}
-
-static inline void
-nm_str_buf_append_c2(NMStrBuf *strbuf, char ch0, char ch1)
-{
- nm_str_buf_maybe_expand(strbuf, 3, FALSE);
- strbuf->_priv_str[strbuf->_priv_len++] = ch0;
- strbuf->_priv_str[strbuf->_priv_len++] = ch1;
-}
-
-static inline void
-nm_str_buf_append_c4(NMStrBuf *strbuf, char ch0, char ch1, char ch2, char ch3)
-{
- nm_str_buf_maybe_expand(strbuf, 5, FALSE);
- strbuf->_priv_str[strbuf->_priv_len++] = ch0;
- strbuf->_priv_str[strbuf->_priv_len++] = ch1;
- strbuf->_priv_str[strbuf->_priv_len++] = ch2;
- strbuf->_priv_str[strbuf->_priv_len++] = ch3;
-}
-
-static inline void
-nm_str_buf_append_c_hex(NMStrBuf *strbuf, char ch, gboolean upper_case)
-{
- nm_str_buf_maybe_expand(strbuf, 3, FALSE);
- strbuf->_priv_str[strbuf->_priv_len++] = nm_hexchar(((guchar) ch) >> 4, upper_case);
- strbuf->_priv_str[strbuf->_priv_len++] = nm_hexchar((guchar) ch, upper_case);
-}
-
-static inline void
-nm_str_buf_append_len(NMStrBuf *strbuf, const char *str, gsize len)
-{
- _nm_str_buf_assert(strbuf);
-
- if (len > 0) {
- nm_str_buf_maybe_expand(strbuf, len + 1, FALSE);
- memcpy(&strbuf->_priv_str[strbuf->_priv_len], str, len);
- strbuf->_priv_len += len;
- }
-}
-
-static inline char *
-nm_str_buf_append_len0(NMStrBuf *strbuf, const char *str, gsize len)
-{
- _nm_str_buf_assert(strbuf);
-
- /* this is basically like nm_str_buf_append_len() and
- * nm_str_buf_get_str() in one. */
-
- nm_str_buf_maybe_expand(strbuf, len + 1u, FALSE);
- if (len > 0) {
- memcpy(&strbuf->_priv_str[strbuf->_priv_len], str, len);
- strbuf->_priv_len += len;
- }
- strbuf->_priv_str[strbuf->_priv_len] = '\0';
- return strbuf->_priv_str;
-}
-
-static inline void
-nm_str_buf_append(NMStrBuf *strbuf, const char *str)
-{
- nm_assert(str);
-
- nm_str_buf_append_len(strbuf, str, strlen(str));
-}
-
-static inline char *
-nm_str_buf_append0(NMStrBuf *strbuf, const char *str)
-{
- nm_assert(str);
-
- return nm_str_buf_append_len0(strbuf, str, strlen(str));
-}
-
-void nm_str_buf_append_printf(NMStrBuf *strbuf, const char *format, ...) _nm_printf(2, 3);
-
-static inline void
-nm_str_buf_ensure_trailing_c(NMStrBuf *strbuf, char ch)
-{
- _nm_str_buf_assert(strbuf);
-
- if (strbuf->_priv_len == 0 || strbuf->_priv_str[strbuf->_priv_len - 1] != ch)
- nm_str_buf_append_c(strbuf, ch);
-}
-
-static inline NMStrBuf *
-nm_str_buf_append_required_delimiter(NMStrBuf *strbuf, char delimiter)
-{
- _nm_str_buf_assert(strbuf);
-
- /* appends the @delimiter if it is required (that is, if the
- * string is not empty). */
- if (strbuf->len > 0)
- nm_str_buf_append_c(strbuf, delimiter);
- return strbuf;
-}
-
-static inline void
-nm_str_buf_append_dirty(NMStrBuf *strbuf, gsize len)
-{
- _nm_str_buf_assert(strbuf);
-
- /* this append @len bytes to the buffer, but it does not
- * initialize them! */
- if (len > 0) {
- nm_str_buf_maybe_expand(strbuf, len, FALSE);
- strbuf->_priv_len += len;
- }
-}
-
-static inline void
-nm_str_buf_append_c_len(NMStrBuf *strbuf, char ch, gsize len)
-{
- _nm_str_buf_assert(strbuf);
-
- if (len > 0) {
- nm_str_buf_maybe_expand(strbuf, len, FALSE);
- memset(&strbuf->_priv_str[strbuf->_priv_len], ch, len);
- strbuf->_priv_len += len;
- }
-}
-
-/*****************************************************************************/
-
-static inline NMStrBuf *
-nm_str_buf_reset(NMStrBuf *strbuf)
-{
- _nm_str_buf_assert(strbuf);
-
- if (strbuf->_priv_len > 0) {
- if (strbuf->_priv_do_bzero_mem) {
- /* we only clear the memory that we wrote to. */
- nm_explicit_bzero(strbuf->_priv_str, strbuf->_priv_len);
- }
- strbuf->_priv_len = 0;
- }
-
- return strbuf;
-}
-
-/*****************************************************************************/
-
-/* Calls nm_utils_escaped_tokens_escape() on @str and appends the
- * result to @strbuf. */
-static inline void
-nm_utils_escaped_tokens_escape_strbuf(const char *str, const char *delimiters, NMStrBuf *strbuf)
-{
- gs_free char *str_to_free = NULL;
-
- nm_assert(str);
-
- nm_str_buf_append(strbuf, nm_utils_escaped_tokens_escape(str, delimiters, &str_to_free));
-}
-
-/* Calls nm_utils_escaped_tokens_escape_unnecessary() on @str and appends the
- * string to @strbuf. */
-static inline void
-nm_utils_escaped_tokens_escape_strbuf_assert(const char *str,
- const char *delimiters,
- NMStrBuf * strbuf)
-{
- nm_str_buf_append(strbuf, nm_utils_escaped_tokens_escape_unnecessary(str, delimiters));
-}
-
-/*****************************************************************************/
-
-static inline gboolean
-nm_str_buf_is_initalized(NMStrBuf *strbuf)
-{
- nm_assert(strbuf);
-#if NM_MORE_ASSERTS
- if (strbuf->_priv_str)
- _nm_str_buf_assert(strbuf);
-#endif
- return !!strbuf->_priv_str;
-}
-
-/**
- * nm_str_buf_get_str:
- * @strbuf: the #NMStrBuf instance
- *
- * Returns the NUL terminated internal string.
- *
- * While constructing the string, the intermediate buffer
- * is not NUL terminated (this makes it different from GString).
- * Usually, one would build the string and retrieve it at the
- * end with nm_str_buf_finalize(). This returns the NUL terminated
- * buffer that was appended so far. Contrary to nm_str_buf_finalize(), you
- * can still append more data to the buffer and this does not transfer ownership
- * of the string.
- *
- * Returns: (transfer none): the internal string. The string
- * is of length "strbuf->len", which may be larger if the
- * returned string contains NUL characters (binary). The terminating
- * NUL character is always present after "strbuf->len" characters.
- * If currently no buffer is allocated, this will return %NULL.
- */
-static inline char *
-nm_str_buf_get_str(NMStrBuf *strbuf)
-{
- _nm_str_buf_assert(strbuf);
-
- if (!strbuf->_priv_str)
- return NULL;
-
- nm_str_buf_maybe_expand(strbuf, 1, FALSE);
- strbuf->_priv_str[strbuf->_priv_len] = '\0';
- return strbuf->_priv_str;
-}
-
-static inline char *
-nm_str_buf_get_str_unsafe(NMStrBuf *strbuf)
-{
- _nm_str_buf_assert(strbuf);
- return strbuf->_priv_str;
-}
-
-static inline char *
-nm_str_buf_get_str_at_unsafe(NMStrBuf *strbuf, gsize index)
-{
- _nm_str_buf_assert(strbuf);
-
- /* it is acceptable to ask for a pointer at the end of the buffer -- even
- * if there is no data there. The caller is anyway required to take care
- * of the length (that's the "unsafe" part), and in that case, the length
- * is merely zero. */
- nm_assert(index <= strbuf->allocated);
-
- if (!strbuf->_priv_str)
- return NULL;
-
- return &strbuf->_priv_str[index];
-}
-
-static inline char
-nm_str_buf_get_char(const NMStrBuf *strbuf, gsize index)
-{
- _nm_str_buf_assert(strbuf);
- nm_assert(index < strbuf->allocated);
- return strbuf->_priv_str[index];
-}
-
-/**
- * nm_str_buf_finalize:
- * @strbuf: an initilized #NMStrBuf
- * @out_len: (out): (allow-none): optional output
- * argument with the length of the returned string.
- *
- * Returns: (transfer full): the string of the buffer
- * which must be freed by the caller. The @strbuf
- * is afterwards in undefined state, though it can be
- * reused after nm_str_buf_init().
- * Note that if no string is allocated yet (after nm_str_buf_init() with
- * length zero), this will return %NULL. */
-static inline char *
-nm_str_buf_finalize(NMStrBuf *strbuf, gsize *out_len)
-{
- _nm_str_buf_assert(strbuf);
-
- NM_SET_OUT(out_len, strbuf->_priv_len);
-
- if (!strbuf->_priv_str)
- return NULL;
-
- nm_str_buf_maybe_expand(strbuf, 1, TRUE);
- strbuf->_priv_str[strbuf->_priv_len] = '\0';
-
- /* the buffer is in invalid state afterwards, however, we clear it
- * so far, that nm_auto_str_buf and nm_str_buf_destroy() is happy. */
- return g_steal_pointer(&strbuf->_priv_str);
-}
-
-static inline GBytes *
-nm_str_buf_finalize_to_gbytes(NMStrBuf *strbuf)
-{
- char *s;
- gsize l;
-
- /* this always returns a non-NULL, newly allocated GBytes instance.
- * The data buffer always has an additional NUL character after
- * the data, and the data is allocated with malloc.
- *
- * That means, the caller who takes ownership of the GBytes can
- * safely modify the content of the buffer (including the additional
- * NUL sentinel). */
- s = nm_str_buf_finalize(strbuf, &l);
- return g_bytes_new_take(s ?: g_new0(char, 1), l);
-}
-
-/**
- * nm_str_buf_destroy:
- * @strbuf: an initialized #NMStrBuf
- *
- * Frees the associated memory of @strbuf. The buffer
- * afterwards is in undefined state, but can be re-initialized
- * with nm_str_buf_init().
- */
-static inline void
-nm_str_buf_destroy(NMStrBuf *strbuf)
-{
- if (!strbuf->_priv_str)
- return;
- _nm_str_buf_assert(strbuf);
- if (strbuf->_priv_do_bzero_mem)
- nm_explicit_bzero(strbuf->_priv_str, strbuf->_priv_len);
- g_free(strbuf->_priv_str);
-
- /* the buffer is in invalid state afterwards, however, we clear it
- * so far, that nm_auto_str_buf is happy when calling
- * nm_str_buf_destroy() again. */
- strbuf->_priv_str = NULL;
-}
-
-#define nm_auto_str_buf nm_auto(nm_str_buf_destroy)
-
-#endif /* __NM_STR_BUF_H__ */
diff --git a/shared/nm-glib-aux/nm-time-utils.c b/shared/nm-glib-aux/nm-time-utils.c
deleted file mode 100644
index df98176a12..0000000000
--- a/shared/nm-glib-aux/nm-time-utils.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2018 Red Hat, Inc.
- */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-time-utils.h"
-
-#include "nm-logging-fwd.h"
-
-/*****************************************************************************/
-
-typedef struct {
- /* the offset to the native clock, in seconds. */
- gint64 offset_sec;
- clockid_t clk_id;
-} GlobalState;
-
-static const GlobalState *volatile p_global_state;
-
-static const GlobalState *
-_t_init_global_state(void)
-{
- static GlobalState global_state = {};
- static gsize init_once = 0;
- const GlobalState *p;
- clockid_t clk_id;
- struct timespec tp;
- gint64 offset_sec;
- int r;
-
- clk_id = CLOCK_BOOTTIME;
- r = clock_gettime(clk_id, &tp);
- if (r == -1 && errno == EINVAL) {
- clk_id = CLOCK_MONOTONIC;
- r = clock_gettime(clk_id, &tp);
- }
-
- /* The only failure we tolerate is that CLOCK_BOOTTIME is not supported.
- * Other than that, we rely on kernel to not fail on this. */
- g_assert(r == 0);
- g_assert(tp.tv_nsec >= 0 && tp.tv_nsec < NM_UTILS_NSEC_PER_SEC);
-
- /* Calculate an offset for the time stamp.
- *
- * We always want positive values, because then we can initialize
- * a timestamp with 0 and be sure, that it will be less then any
- * value nm_utils_get_monotonic_timestamp_*() might return.
- * For this to be true also for nm_utils_get_monotonic_timestamp_sec() at
- * early boot, we have to shift the timestamp to start counting at
- * least from 1 second onward.
- *
- * Another advantage of shifting is, that this way we make use of the whole 31 bit
- * range of signed int, before the time stamp for nm_utils_get_monotonic_timestamp_sec()
- * wraps (~68 years).
- **/
- offset_sec = (-((gint64) tp.tv_sec)) + 1;
-
- if (!g_once_init_enter(&init_once)) {
- /* there was a race. We expect the pointer to be fully initialized now. */
- p = g_atomic_pointer_get(&p_global_state);
- g_assert(p);
- return p;
- }
-
- global_state.offset_sec = offset_sec;
- global_state.clk_id = clk_id;
- p = &global_state;
- g_atomic_pointer_set(&p_global_state, p);
- g_once_init_leave(&init_once, 1);
-
- _nm_utils_monotonic_timestamp_initialized(&tp, p->offset_sec, p->clk_id == CLOCK_BOOTTIME);
-
- return p;
-}
-
-#define _t_get_global_state() \
- ({ \
- const GlobalState *_p; \
- \
- _p = g_atomic_pointer_get(&p_global_state); \
- (G_LIKELY(_p) ? _p : _t_init_global_state()); \
- })
-
-#define _t_clock_gettime_eval(p, tp) \
- ({ \
- struct timespec *const _tp = (tp); \
- const GlobalState *const _p2 = (p); \
- int _r; \
- \
- nm_assert(_tp); \
- \
- _r = clock_gettime(_p2->clk_id, _tp); \
- \
- nm_assert(_r == 0); \
- nm_assert(_tp->tv_nsec >= 0 && _tp->tv_nsec < NM_UTILS_NSEC_PER_SEC); \
- \
- _p2; \
- })
-
-#define _t_clock_gettime(tp) _t_clock_gettime_eval(_t_get_global_state(), tp);
-
-/*****************************************************************************/
-
-/**
- * nm_utils_get_monotonic_timestamp_nsec:
- *
- * Returns: a monotonically increasing time stamp in nanoseconds,
- * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
- *
- * The returned value will start counting at an undefined point
- * in the past and will always be positive.
- *
- * All the nm_utils_get_monotonic_timestamp_*sec functions return the same
- * timestamp but in different scales (nsec, usec, msec, sec).
- **/
-gint64
-nm_utils_get_monotonic_timestamp_nsec(void)
-{
- const GlobalState *p;
- struct timespec tp;
-
- p = _t_clock_gettime(&tp);
-
- /* Although the result will always be positive, we return a signed
- * integer, which makes it easier to calculate time differences (when
- * you want to subtract signed values).
- **/
- return (((gint64) tp.tv_sec) + p->offset_sec) * NM_UTILS_NSEC_PER_SEC + tp.tv_nsec;
-}
-
-/**
- * nm_utils_get_monotonic_timestamp_usec:
- *
- * Returns: a monotonically increasing time stamp in microseconds,
- * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
- *
- * The returned value will start counting at an undefined point
- * in the past and will always be positive.
- *
- * All the nm_utils_get_monotonic_timestamp_*sec functions return the same
- * timestamp but in different scales (nsec, usec, msec, sec).
- **/
-gint64
-nm_utils_get_monotonic_timestamp_usec(void)
-{
- const GlobalState *p;
- struct timespec tp;
-
- p = _t_clock_gettime(&tp);
-
- /* Although the result will always be positive, we return a signed
- * integer, which makes it easier to calculate time differences (when
- * you want to subtract signed values).
- **/
- return (((gint64) tp.tv_sec) + p->offset_sec) * ((gint64) G_USEC_PER_SEC)
- + (tp.tv_nsec / (NM_UTILS_NSEC_PER_SEC / G_USEC_PER_SEC));
-}
-
-/**
- * nm_utils_get_monotonic_timestamp_msec:
- *
- * Returns: a monotonically increasing time stamp in milliseconds,
- * starting at an unspecified offset. See clock_gettime(), %CLOCK_BOOTTIME.
- *
- * The returned value will start counting at an undefined point
- * in the past and will always be positive.
- *
- * All the nm_utils_get_monotonic_timestamp_*sec functions return the same
- * timestamp but in different scales (nsec, usec, msec, sec).
- **/
-gint64
-nm_utils_get_monotonic_timestamp_msec(void)
-{
- const GlobalState *p;
- struct timespec tp;
-
- p = _t_clock_gettime(&tp);
-
- /* Although the result will always be positive, we return a signed
- * integer, which makes it easier to calculate time differences (when
- * you want to subtract signed values).
- **/
- return (((gint64) tp.tv_sec) + p->offset_sec) * ((gint64) 1000)
- + (tp.tv_nsec / (NM_UTILS_NSEC_PER_SEC / 1000));
-}
-
-/**
- * nm_utils_get_monotonic_timestamp_sec:
- *
- * Returns: nm_utils_get_monotonic_timestamp_msec() in seconds (throwing
- * away sub second parts). The returned value will always be positive.
- *
- * This value wraps after roughly 68 years which should be fine for any
- * practical purpose.
- *
- * All the nm_utils_get_monotonic_timestamp_*sec functions return the same
- * timestamp but in different scales (nsec, usec, msec, sec).
- **/
-gint32
-nm_utils_get_monotonic_timestamp_sec(void)
-{
- const GlobalState *p;
- struct timespec tp;
-
- p = _t_clock_gettime(&tp);
-
- return (((gint64) tp.tv_sec) + p->offset_sec);
-}
-
-/**
- * nm_utils_monotonic_timestamp_as_boottime:
- * @timestamp: the monotonic-timestamp that should be converted into CLOCK_BOOTTIME.
- * @timestamp_nsec_per_tick: How many nanoseconds make one unit of @timestamp? E.g. if
- * @timestamp is in unit seconds, pass %NM_UTILS_NSEC_PER_SEC; if @timestamp is
- * in nanoseconds, pass 1; if @timestamp is in milliseconds, pass %NM_UTILS_NSEC_PER_SEC/1000.
- * This must be a multiple of 10, and between 1 and %NM_UTILS_NSEC_PER_SEC.
- *
- * Returns: the monotonic-timestamp as CLOCK_BOOTTIME, as returned by clock_gettime().
- * The unit is the same as the passed in @timestamp based on @timestamp_nsec_per_tick.
- * E.g. if you passed @timestamp in as seconds, it will return boottime in seconds.
- *
- * Note that valid monotonic-timestamps are always positive numbers (counting roughly since
- * the application is running). However, it might make sense to calculate a timestamp from
- * before the application was running, hence negative @timestamp is allowed. The result
- * in that case might also be a negative timestamp (in CLOCK_BOOTTIME), which would indicate
- * that the timestamp lies in the past before the machine was booted.
- *
- * On older kernels that don't support CLOCK_BOOTTIME, the returned time is instead CLOCK_MONOTONIC.
- **/
-gint64
-nm_utils_monotonic_timestamp_as_boottime(gint64 timestamp, gint64 timestamp_nsec_per_tick)
-{
- const GlobalState *p;
- gint64 offset;
-
- /* only support nsec-per-tick being a multiple of 10. */
- g_return_val_if_fail(timestamp_nsec_per_tick == 1
- || (timestamp_nsec_per_tick > 0
- && timestamp_nsec_per_tick <= NM_UTILS_NSEC_PER_SEC
- && timestamp_nsec_per_tick % 10 == 0),
- -1);
-
- /* if the caller didn't yet ever fetch a monotonic-timestamp, he cannot pass any meaningful
- * value (because he has no idea what these timestamps would be). That would be a bug. */
- nm_assert(g_atomic_pointer_get(&p_global_state));
-
- p = _t_get_global_state();
-
- nm_assert(p->offset_sec <= 0);
-
- /* calculate the offset of monotonic-timestamp to boottime. offset_s is <= 1. */
- offset = p->offset_sec * (NM_UTILS_NSEC_PER_SEC / timestamp_nsec_per_tick);
-
- nm_assert(offset <= 0 && offset > G_MININT64);
-
- /* check for overflow (note that offset is non-positive). */
- g_return_val_if_fail(timestamp < G_MAXINT64 + offset, G_MAXINT64);
-
- return timestamp - offset;
-}
-
-/**
- * nm_utils_monotonic_timestamp_from_boottime:
- * @boottime: the timestamp from CLOCK_BOOTTIME (or CLOCK_MONOTONIC, if
- * kernel does not support CLOCK_BOOTTIME and monotonic timestamps are based
- * on CLOCK_MONOTONIC).
- * @timestamp_nsec_per_tick: the scale in which @boottime is. If @boottime is in
- * nano seconds, this should be 1. If it is in milli seconds, this should be
- * %NM_UTILS_NSEC_PER_SEC/1000, etc.
- *
- * Returns: the same timestamp in monotonic timestamp scale.
- *
- * Note that commonly monotonic timestamps are positive. But they may not
- * be positive in this case. That's when boottime is taken from a time before
- * the monotonic timestamps started counting. So, that means a zero or negative
- * value is still a valid timestamp.
- *
- * This is the inverse of nm_utils_monotonic_timestamp_as_boottime().
- */
-gint64
-nm_utils_monotonic_timestamp_from_boottime(guint64 boottime, gint64 timestamp_nsec_per_tick)
-{
- const GlobalState *p;
- gint64 offset;
-
- /* only support nsec-per-tick being a multiple of 10. */
- g_return_val_if_fail(timestamp_nsec_per_tick == 1
- || (timestamp_nsec_per_tick > 0
- && timestamp_nsec_per_tick <= NM_UTILS_NSEC_PER_SEC
- && timestamp_nsec_per_tick % 10 == 0),
- -1);
-
- p = _t_get_global_state();
-
- nm_assert(p->offset_sec <= 0);
-
- /* calculate the offset of monotonic-timestamp to boottime. offset_s is <= 1. */
- offset = p->offset_sec * (NM_UTILS_NSEC_PER_SEC / timestamp_nsec_per_tick);
-
- nm_assert(offset <= 0 && offset > G_MININT64);
-
- /* check for overflow (note that offset is non-positive). */
- g_return_val_if_fail(boottime < G_MAXINT64, G_MAXINT64);
-
- return (gint64) boottime + offset;
-}
-
-gint64
-nm_utils_clock_gettime_nsec(clockid_t clockid)
-{
- struct timespec tp;
-
- if (clock_gettime(clockid, &tp) != 0)
- return -NM_ERRNO_NATIVE(errno);
- return nm_utils_timespec_to_nsec(&tp);
-}
-
-gint64
-nm_utils_clock_gettime_msec(clockid_t clockid)
-{
- struct timespec tp;
-
- if (clock_gettime(clockid, &tp) != 0)
- return -NM_ERRNO_NATIVE(errno);
- return nm_utils_timespec_to_msec(&tp);
-}
diff --git a/shared/nm-glib-aux/nm-time-utils.h b/shared/nm-glib-aux/nm-time-utils.h
deleted file mode 100644
index 3c3e935f8d..0000000000
--- a/shared/nm-glib-aux/nm-time-utils.h
+++ /dev/null
@@ -1,47 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2018 Red Hat, Inc.
- */
-
-#ifndef __NM_TIME_UTILS_H__
-#define __NM_TIME_UTILS_H__
-
-#include <time.h>
-
-static inline gint64
-nm_utils_timespec_to_nsec(const struct timespec *ts)
-{
- return (((gint64) ts->tv_sec) * ((gint64) NM_UTILS_NSEC_PER_SEC)) + ((gint64) ts->tv_nsec);
-}
-
-static inline gint64
-nm_utils_timespec_to_msec(const struct timespec *ts)
-{
- return (((gint64) ts->tv_sec) * ((gint64) 1000))
- + (((gint64) ts->tv_nsec) / ((gint64) NM_UTILS_NSEC_PER_SEC / 1000));
-}
-
-gint64 nm_utils_get_monotonic_timestamp_nsec(void);
-gint64 nm_utils_get_monotonic_timestamp_usec(void);
-gint64 nm_utils_get_monotonic_timestamp_msec(void);
-gint32 nm_utils_get_monotonic_timestamp_sec(void);
-
-gint64 nm_utils_monotonic_timestamp_as_boottime(gint64 timestamp, gint64 timestamp_ticks_per_nsec);
-gint64 nm_utils_monotonic_timestamp_from_boottime(guint64 boottime, gint64 timestamp_nsec_per_tick);
-
-static inline gint64
-nm_utils_get_monotonic_timestamp_nsec_cached(gint64 *cache_now)
-{
- return (*cache_now) ?: (*cache_now = nm_utils_get_monotonic_timestamp_nsec());
-}
-
-static inline gint64
-nm_utils_get_monotonic_timestamp_msec_cached(gint64 *cache_now)
-{
- return (*cache_now) ?: (*cache_now = nm_utils_get_monotonic_timestamp_msec());
-}
-
-gint64 nm_utils_clock_gettime_nsec(clockid_t clockid);
-gint64 nm_utils_clock_gettime_msec(clockid_t clockid);
-
-#endif /* __NM_TIME_UTILS_H__ */
diff --git a/shared/nm-glib-aux/nm-value-type.h b/shared/nm-glib-aux/nm-value-type.h
deleted file mode 100644
index f9edebdb6c..0000000000
--- a/shared/nm-glib-aux/nm-value-type.h
+++ /dev/null
@@ -1,209 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2019 Red Hat, Inc.
- */
-
-#ifndef __NM_VALUE_TYPE_H__
-#define __NM_VALUE_TYPE_H__
-
-typedef enum {
- NM_VALUE_TYPE_UNSPEC = 1,
- NM_VALUE_TYPE_BOOL = 2,
- NM_VALUE_TYPE_INT32 = 3,
- NM_VALUE_TYPE_INT = 4,
- NM_VALUE_TYPE_STRING = 5,
-} NMValueType;
-
-/*****************************************************************************/
-
-#ifdef NM_VALUE_TYPE_DEFINE_FUNCTIONS
-
-typedef union {
- bool v_bool;
- gint32 v_int32;
- int v_int;
- const char *v_string;
-
- /* for convenience, also let the union contain other pointer types. These are
- * for NM_VALUE_TYPE_UNSPEC. */
- gconstpointer * v_ptr;
- const GPtrArray *v_ptrarray;
-
-} NMValueTypUnion;
-
- /* 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; \
- })
-
-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; \
- })
-
-/*****************************************************************************/
-
-static inline int
-nm_value_type_cmp(NMValueType value_type, gconstpointer p_a, gconstpointer p_b)
-{
- switch (value_type) {
- case NM_VALUE_TYPE_BOOL:
- NM_CMP_DIRECT(*((const bool *) p_a), *((const bool *) p_b));
- return 0;
- case NM_VALUE_TYPE_INT32:
- NM_CMP_DIRECT(*((const gint32 *) p_a), *((const gint32 *) p_b));
- return 0;
- case NM_VALUE_TYPE_INT:
- NM_CMP_DIRECT(*((const int *) p_a), *((const int *) 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_UNSPEC:
- break;
- }
- nm_assert_not_reached();
- return 0;
-}
-
-static inline gboolean
-nm_value_type_equal(NMValueType value_type, gconstpointer p_a, gconstpointer p_b)
-{
- return nm_value_type_cmp(value_type, p_a, p_b) == 0;
-}
-
-static inline void
-nm_value_type_copy(NMValueType value_type, gpointer dst, gconstpointer src)
-{
- switch (value_type) {
- case NM_VALUE_TYPE_BOOL:
- (*((bool *) dst) = *((const bool *) src));
- return;
- case NM_VALUE_TYPE_INT32:
- (*((gint32 *) dst) = *((const gint32 *) src));
- return;
- case NM_VALUE_TYPE_INT:
- (*((int *) dst) = *((const int *) src));
- return;
- case NM_VALUE_TYPE_STRING:
- /* self assignment safe! */
- if (*((char **) dst) != *((const char *const *) src)) {
- g_free(*((char **) dst));
- *((char **) dst) = g_strdup(*((const char *const *) src));
- }
- return;
- case NM_VALUE_TYPE_UNSPEC:
- break;
- }
- nm_assert_not_reached();
-}
-
-static inline void
-nm_value_type_get_from_variant(NMValueType value_type,
- gpointer dst,
- GVariant * variant,
- gboolean clone)
-{
- switch (value_type) {
- case NM_VALUE_TYPE_BOOL:
- *((bool *) dst) = g_variant_get_boolean(variant);
- return;
- case NM_VALUE_TYPE_INT32:
- *((gint32 *) dst) = g_variant_get_int32(variant);
- return;
- case NM_VALUE_TYPE_STRING:
- if (clone) {
- g_free(*((char **) dst));
- *((char **) dst) = g_variant_dup_string(variant, NULL);
- } else {
- /* we don't clone the string, nor free the previous value. */
- *((const char **) dst) = g_variant_get_string(variant, NULL);
- }
- return;
-
- 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. */
-
- /* fall-through */
- case NM_VALUE_TYPE_UNSPEC:
- break;
- }
- nm_assert_not_reached();
-}
-
-static inline GVariant *
-nm_value_type_to_variant(NMValueType value_type, gconstpointer src)
-{
- const char *v_string;
-
- switch (value_type) {
- case NM_VALUE_TYPE_BOOL:
- return g_variant_new_boolean(*((const bool *) src));
- case NM_VALUE_TYPE_INT32:
- return g_variant_new_int32(*((const gint32 *) 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_INT:
- /* "int" also does not have a define variant type, because it's not
- * clear how many bits we would need. */
-
- /* fall-through */
- case NM_VALUE_TYPE_UNSPEC:
- break;
- }
- nm_assert_not_reached();
- return NULL;
-}
-
-static inline const GVariantType *
-nm_value_type_get_variant_type(NMValueType value_type)
-{
- switch (value_type) {
- case NM_VALUE_TYPE_BOOL:
- return G_VARIANT_TYPE_BOOLEAN;
- case NM_VALUE_TYPE_INT32:
- return G_VARIANT_TYPE_INT32;
- case NM_VALUE_TYPE_STRING:
- return G_VARIANT_TYPE_STRING;
-
- 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. */
-
- /* fall-through */
- case NM_VALUE_TYPE_UNSPEC:
- break;
- }
- nm_assert_not_reached();
- return NULL;
-}
-
- /*****************************************************************************/
-
-#endif /* NM_VALUE_TYPE_DEFINE_FUNCTIONS */
-
-#endif /* __NM_VALUE_TYPE_H__ */
diff --git a/shared/nm-glib-aux/tests/meson.build b/shared/nm-glib-aux/tests/meson.build
deleted file mode 100644
index 38dfff0c6c..0000000000
--- a/shared/nm-glib-aux/tests/meson.build
+++ /dev/null
@@ -1,35 +0,0 @@
-# SPDX-License-Identifier: LGPL-2.1-or-later
-
-exe = executable(
- 'test-shared-general',
- 'test-shared-general.c',
- dependencies: libnm_glib_aux_dep_link,
- link_with: libnm_log_null,
-)
-
-test(
- 'shared/nm-glib-aux/test-shared-general',
- test_script,
- args: test_args + [exe.full_path()],
- timeout: default_test_timeout,
-)
-
-if jansson_dep.found()
- exe = executable(
- 'test-json-aux',
- 'test-json-aux.c',
- dependencies: [
- libnm_glib_aux_dep_link,
- jansson_dep,
- dl_dep,
- ],
- link_with: libnm_log_null,
- )
-
- test(
- 'shared/nm-glib-aux/test-json-aux',
- test_script,
- args: test_args + [exe.full_path()],
- timeout: default_test_timeout,
- )
-endif
diff --git a/shared/nm-glib-aux/tests/test-json-aux.c b/shared/nm-glib-aux/tests/test-json-aux.c
deleted file mode 100644
index b07d673fa6..0000000000
--- a/shared/nm-glib-aux/tests/test-json-aux.c
+++ /dev/null
@@ -1,165 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-
-#include "nm-glib-aux/nm-default-glib-i18n-prog.h"
-
-#include <jansson.h>
-
-#include "nm-glib-aux/nm-json-aux.h"
-
-#include "nm-utils/nm-test-utils.h"
-
-/*****************************************************************************/
-
-static void
-test_jansson(void)
-{
- const NMJsonVt * vt;
- nm_auto_decref_json nm_json_t *js1 = NULL;
- nm_auto_decref_json nm_json_t *js2 = NULL;
-
-#define _ASSERT_FIELD(type1, type2, field) \
- G_STMT_START \
- { \
- G_STATIC_ASSERT_EXPR(sizeof(((type1 *) NULL)->field) == sizeof(((type2 *) NULL)->field)); \
- G_STATIC_ASSERT_EXPR(G_STRUCT_OFFSET(type1, field) == G_STRUCT_OFFSET(type2, field)); \
- } \
- G_STMT_END
-
- G_STATIC_ASSERT_EXPR(NM_JSON_REJECT_DUPLICATES == JSON_REJECT_DUPLICATES);
-
- G_STATIC_ASSERT_EXPR(sizeof(nm_json_type) == sizeof(json_type));
-
- G_STATIC_ASSERT_EXPR((int) NM_JSON_OBJECT == JSON_OBJECT);
- G_STATIC_ASSERT_EXPR((int) NM_JSON_ARRAY == JSON_ARRAY);
- G_STATIC_ASSERT_EXPR((int) NM_JSON_STRING == JSON_STRING);
- G_STATIC_ASSERT_EXPR((int) NM_JSON_INTEGER == JSON_INTEGER);
- G_STATIC_ASSERT_EXPR((int) NM_JSON_REAL == JSON_REAL);
- G_STATIC_ASSERT_EXPR((int) NM_JSON_TRUE == JSON_TRUE);
- G_STATIC_ASSERT_EXPR((int) NM_JSON_FALSE == JSON_FALSE);
- G_STATIC_ASSERT_EXPR((int) NM_JSON_NULL == JSON_NULL);
-
- G_STATIC_ASSERT_EXPR(sizeof(nm_json_int_t) == sizeof(json_int_t));
-
- G_STATIC_ASSERT_EXPR(sizeof(nm_json_t) == sizeof(json_t));
- _ASSERT_FIELD(nm_json_t, json_t, refcount);
- _ASSERT_FIELD(nm_json_t, json_t, type);
-
- G_STATIC_ASSERT_EXPR(NM_JSON_ERROR_TEXT_LENGTH == JSON_ERROR_TEXT_LENGTH);
- G_STATIC_ASSERT_EXPR(NM_JSON_ERROR_SOURCE_LENGTH == JSON_ERROR_SOURCE_LENGTH);
-
- G_STATIC_ASSERT_EXPR(sizeof(nm_json_error_t) == sizeof(json_error_t));
- _ASSERT_FIELD(nm_json_error_t, json_error_t, line);
- _ASSERT_FIELD(nm_json_error_t, json_error_t, column);
- _ASSERT_FIELD(nm_json_error_t, json_error_t, position);
- _ASSERT_FIELD(nm_json_error_t, json_error_t, source);
- _ASSERT_FIELD(nm_json_error_t, json_error_t, text);
-
- vt = nm_json_vt();
-
- g_assert(vt);
- g_assert(vt->loaded);
-
- js1 = vt->nm_json_loads("{ \"a\": 5 }", 0, NULL);
- g_assert(js1);
- nm_json_decref(vt, g_steal_pointer(&js1));
-
- js2 = vt->nm_json_loads("{ \"a\": 6 }", 0, NULL);
- g_assert(js2);
-
-#define CHECK_FCN(vt, fcn, nm_type, js_type) \
- G_STMT_START \
- { \
- const NMJsonVt *const _vt = (vt); \
- _nm_unused nm_type = (_vt->nm_##fcn); \
- _nm_unused js_type = (fcn); \
- \
- g_assert(_vt->nm_##fcn); \
- g_assert(_f_nm); \
- g_assert(_f_js); \
- g_assert(_f_nm == _vt->nm_##fcn); \
- } \
- G_STMT_END
-
- CHECK_FCN(vt, json_array, nm_json_t * (*_f_nm)(void), json_t * (*_f_js)(void) );
- CHECK_FCN(vt,
- json_array_append_new,
- int (*_f_nm)(nm_json_t *, nm_json_t *),
- int (*_f_js)(json_t *, json_t *));
- CHECK_FCN(vt,
- json_array_get,
- nm_json_t * (*_f_nm)(const nm_json_t *, gsize),
- json_t * (*_f_js)(const json_t *, size_t));
- CHECK_FCN(vt,
- json_array_size,
- gsize(*_f_nm)(const nm_json_t *),
- size_t(*_f_js)(const json_t *));
- CHECK_FCN(vt, json_delete, void (*_f_nm)(nm_json_t *), void (*_f_js)(json_t *));
- CHECK_FCN(vt,
- json_dumps,
- char *(*_f_nm)(const nm_json_t *, gsize),
- char *(*_f_js)(const json_t *, size_t));
- CHECK_FCN(vt, json_false, nm_json_t * (*_f_nm)(void), json_t * (*_f_js)(void) );
- CHECK_FCN(vt, json_integer, nm_json_t * (*_f_nm)(nm_json_int_t), json_t * (*_f_js)(json_int_t));
- CHECK_FCN(vt,
- json_integer_value,
- nm_json_int_t(*_f_nm)(const nm_json_t *),
- json_int_t(*_f_js)(const json_t *));
- CHECK_FCN(vt,
- json_loads,
- nm_json_t * (*_f_nm)(const char *, gsize, nm_json_error_t *),
- json_t * (*_f_js)(const char *, size_t, json_error_t *) );
- CHECK_FCN(vt, json_object, nm_json_t * (*_f_nm)(void), json_t * (*_f_js)(void) );
- CHECK_FCN(vt,
- json_object_del,
- int (*_f_nm)(nm_json_t *, const char *),
- int (*_f_js)(json_t *, const char *));
- CHECK_FCN(vt,
- json_object_get,
- nm_json_t * (*_f_nm)(const nm_json_t *, const char *),
- json_t * (*_f_js)(const json_t *, const char *) );
- CHECK_FCN(vt, json_object_iter, void *(*_f_nm)(nm_json_t *), void *(*_f_js)(json_t *) );
- CHECK_FCN(vt,
- json_object_iter_key,
- const char *(*_f_nm)(void *),
- const char *(*_f_js)(void *) );
- CHECK_FCN(vt,
- json_object_iter_next,
- void *(*_f_nm)(nm_json_t *, void *),
- void *(*_f_js)(json_t *, void *) );
- CHECK_FCN(vt, json_object_iter_value, nm_json_t * (*_f_nm)(void *), json_t * (*_f_js)(void *) );
- CHECK_FCN(vt,
- json_object_key_to_iter,
- void *(*_f_nm)(const char *),
- void *(*_f_js)(const char *) );
- CHECK_FCN(vt,
- json_object_set_new,
- int (*_f_nm)(nm_json_t *, const char *, nm_json_t *),
- int (*_f_js)(json_t *, const char *, json_t *));
- CHECK_FCN(vt,
- json_object_size,
- gsize(*_f_nm)(const nm_json_t *),
- size_t(*_f_js)(const json_t *));
- CHECK_FCN(vt,
- json_string,
- nm_json_t * (*_f_nm)(const char *),
- json_t * (*_f_js)(const char *) );
- CHECK_FCN(vt,
- json_string_value,
- const char *(*_f_nm)(const nm_json_t *),
- const char *(*_f_js)(const json_t *) );
- CHECK_FCN(vt, json_true, nm_json_t * (*_f_nm)(void), json_t * (*_f_js)(void) );
-}
-
-/*****************************************************************************/
-
-NMTST_DEFINE();
-
-int
-main(int argc, char **argv)
-{
- nmtst_init(&argc, &argv, TRUE);
-
- g_test_add_func("/general/test_jansson", test_jansson);
-
- return g_test_run();
-}
diff --git a/shared/nm-glib-aux/tests/test-shared-general.c b/shared/nm-glib-aux/tests/test-shared-general.c
deleted file mode 100644
index f42c6fb108..0000000000
--- a/shared/nm-glib-aux/tests/test-shared-general.c
+++ /dev/null
@@ -1,1289 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2018 Red Hat, Inc.
- */
-
-#include "nm-glib-aux/nm-default-glib-i18n-prog.h"
-
-#include "nm-std-aux/unaligned.h"
-#include "nm-glib-aux/nm-random-utils.h"
-#include "nm-glib-aux/nm-str-buf.h"
-#include "nm-glib-aux/nm-time-utils.h"
-#include "nm-glib-aux/nm-ref-string.h"
-
-#include "nm-utils/nm-test-utils.h"
-
-/*****************************************************************************/
-
-G_STATIC_ASSERT(NM_AF_UNSPEC == AF_UNSPEC);
-G_STATIC_ASSERT(NM_AF_INET == AF_INET);
-G_STATIC_ASSERT(NM_AF_INET6 == AF_INET6);
-
-G_STATIC_ASSERT(NM_AF_INET_SIZE == sizeof(in_addr_t));
-G_STATIC_ASSERT(NM_AF_INET_SIZE == sizeof(struct in_addr));
-G_STATIC_ASSERT(NM_AF_INET6_SIZE == sizeof(struct in6_addr));
-
-G_STATIC_ASSERT(4 == _nm_alignof(in_addr_t));
-G_STATIC_ASSERT(4 == _nm_alignof(struct in_addr));
-G_STATIC_ASSERT(4 == _nm_alignof(struct in6_addr));
-G_STATIC_ASSERT(4 == _nm_alignof(NMIPAddr));
-
-/*****************************************************************************/
-
-static void
-test_gpid(void)
-{
- const int *int_ptr;
- GPid pid = 42;
-
- /* We redefine G_PID_FORMAT, because it's only available since glib 2.53.5.
- *
- * Also, this is the format for GPid, which for glib is always a typedef
- * for "int". Add a check for that here.
- *
- * G_PID_FORMAT is not about pid_t, which might be a smaller int, and which we would
- * check with SIZEOF_PID_T. */
- G_STATIC_ASSERT(sizeof(GPid) == sizeof(int));
-
- g_assert_cmpstr("" G_PID_FORMAT, ==, "i");
-
- /* check that it's really "int". We will get a compiler warning, if that's not
- * the case. */
- int_ptr = &pid;
- g_assert_cmpint(*int_ptr, ==, 42);
-}
-
-/*****************************************************************************/
-
-static void
-test_monotonic_timestamp(void)
-{
- g_assert(nm_utils_get_monotonic_timestamp_sec() > 0);
-}
-
-/*****************************************************************************/
-
-static void
-test_nmhash(void)
-{
- int rnd;
-
- nm_utils_random_bytes(&rnd, sizeof(rnd));
-
- g_assert(nm_hash_val(555, 4) != 0);
-}
-
-/*****************************************************************************/
-
-static const char *
-_make_strv_foo(void)
-{
- return "foo";
-}
-
-static const char *const *const _tst_make_strv_1 = NM_MAKE_STRV("1", "2");
-
-static void
-test_make_strv(void)
-{
- const char *const *v1a = NM_MAKE_STRV("a");
- const char *const *v1b = NM_MAKE_STRV("a", );
- const char *const *v2a = NM_MAKE_STRV("a", "b");
- const char *const *v2b = NM_MAKE_STRV("a", "b", );
- const char *const v3[] = {
- "a",
- "b",
- };
- const char *const *v4b = NM_MAKE_STRV("a", _make_strv_foo(), );
-
- g_assert(NM_PTRARRAY_LEN(v1a) == 1);
- g_assert(NM_PTRARRAY_LEN(v1b) == 1);
- g_assert(NM_PTRARRAY_LEN(v2a) == 2);
- g_assert(NM_PTRARRAY_LEN(v2b) == 2);
-
- g_assert(NM_PTRARRAY_LEN(_tst_make_strv_1) == 2);
- g_assert_cmpstr(_tst_make_strv_1[0], ==, "1");
- g_assert_cmpstr(_tst_make_strv_1[1], ==, "2");
- /* writing the static read-only variable leads to crash .*/
- //((char **) _tst_make_strv_1)[0] = NULL;
- //((char **) _tst_make_strv_1)[2] = "c";
-
- G_STATIC_ASSERT_EXPR(G_N_ELEMENTS(v3) == 2);
-
- g_assert(NM_PTRARRAY_LEN(v4b) == 2);
-
- G_STATIC_ASSERT_EXPR(G_N_ELEMENTS(NM_MAKE_STRV("a", "b")) == 3);
- G_STATIC_ASSERT_EXPR(G_N_ELEMENTS(NM_MAKE_STRV("a", "b", )) == 3);
-
- nm_strquote_a(300, "");
-}
-
-/*****************************************************************************/
-
-typedef enum {
- TEST_NM_STRDUP_ENUM_m1 = -1,
- TEST_NM_STRDUP_ENUM_3 = 3,
-} TestNMStrdupIntEnum;
-
-static void
-test_nm_strdup_int(void)
-{
-#define _NM_STRDUP_INT_TEST(num, str) \
- G_STMT_START \
- { \
- gs_free char *_s1 = NULL; \
- \
- _s1 = nm_strdup_int((num)); \
- \
- g_assert(_s1); \
- g_assert_cmpstr(_s1, ==, str); \
- } \
- G_STMT_END
-
-#define _NM_STRDUP_INT_TEST_TYPED(type, num) \
- G_STMT_START \
- { \
- type _num = ((type) num); \
- \
- _NM_STRDUP_INT_TEST(_num, G_STRINGIFY(num)); \
- } \
- G_STMT_END
-
- _NM_STRDUP_INT_TEST_TYPED(char, 0);
- _NM_STRDUP_INT_TEST_TYPED(char, 1);
- _NM_STRDUP_INT_TEST_TYPED(guint8, 0);
- _NM_STRDUP_INT_TEST_TYPED(gint8, 25);
- _NM_STRDUP_INT_TEST_TYPED(char, 47);
- _NM_STRDUP_INT_TEST_TYPED(short, 47);
- _NM_STRDUP_INT_TEST_TYPED(int, 47);
- _NM_STRDUP_INT_TEST_TYPED(long, 47);
- _NM_STRDUP_INT_TEST_TYPED(unsigned char, 47);
- _NM_STRDUP_INT_TEST_TYPED(unsigned short, 47);
- _NM_STRDUP_INT_TEST_TYPED(unsigned, 47);
- _NM_STRDUP_INT_TEST_TYPED(unsigned long, 47);
- _NM_STRDUP_INT_TEST_TYPED(gint64, 9223372036854775807);
- _NM_STRDUP_INT_TEST_TYPED(gint64, -9223372036854775807);
- _NM_STRDUP_INT_TEST_TYPED(guint64, 0);
- _NM_STRDUP_INT_TEST_TYPED(guint64, 9223372036854775807);
-
- _NM_STRDUP_INT_TEST(TEST_NM_STRDUP_ENUM_m1, "-1");
- _NM_STRDUP_INT_TEST(TEST_NM_STRDUP_ENUM_3, "3");
-}
-
-/*****************************************************************************/
-
-static void
-test_nm_strndup_a(void)
-{
- int run;
-
- for (run = 0; run < 20; run++) {
- gs_free char *input = NULL;
- char ch;
- gsize i, l;
-
- input = g_strnfill(nmtst_get_rand_uint32() % 20, 'x');
-
- for (i = 0; input[i]; i++) {
- while ((ch = ((char) nmtst_get_rand_uint32())) == '\0') {
- /* repeat. */
- }
- input[i] = ch;
- }
-
- {
- gs_free char *dup_free = NULL;
- const char * dup;
-
- l = strlen(input) + 1;
- dup = nm_strndup_a(10, input, l - 1, &dup_free);
- g_assert_cmpstr(dup, ==, input);
- if (strlen(dup) < 10)
- g_assert(!dup_free);
- else
- g_assert(dup == dup_free);
- }
-
- {
- gs_free char *dup_free = NULL;
- const char * dup;
-
- l = nmtst_get_rand_uint32() % 23;
- dup = nm_strndup_a(10, input, l, &dup_free);
- g_assert(strncmp(dup, input, l) == 0);
- g_assert(strlen(dup) <= l);
- if (l < 10)
- g_assert(!dup_free);
- else
- g_assert(dup == dup_free);
- if (strlen(input) < l)
- g_assert(nm_utils_memeqzero(&dup[strlen(input)], l - strlen(input)));
- }
- }
-}
-
-/*****************************************************************************/
-
-static void
-test_nm_ip4_addr_is_localhost(void)
-{
- g_assert(nm_ip4_addr_is_localhost(nmtst_inet4_from_string("127.0.0.0")));
- g_assert(nm_ip4_addr_is_localhost(nmtst_inet4_from_string("127.0.0.1")));
- g_assert(nm_ip4_addr_is_localhost(nmtst_inet4_from_string("127.5.0.1")));
- g_assert(!nm_ip4_addr_is_localhost(nmtst_inet4_from_string("126.5.0.1")));
- g_assert(!nm_ip4_addr_is_localhost(nmtst_inet4_from_string("128.5.0.1")));
- g_assert(!nm_ip4_addr_is_localhost(nmtst_inet4_from_string("129.5.0.1")));
-}
-
-/*****************************************************************************/
-
-static void
-test_unaligned(void)
-{
- int shift;
-
- for (shift = 0; shift <= 32; shift++) {
- guint8 buf[100] = {};
- guint8 val = 0;
-
- while (val == 0)
- val = nmtst_get_rand_uint32() % 256;
-
- buf[shift] = val;
-
- g_assert_cmpint(unaligned_read_le64(&buf[shift]), ==, (guint64) val);
- g_assert_cmpint(unaligned_read_be64(&buf[shift]), ==, ((guint64) val) << 56);
- g_assert_cmpint(unaligned_read_ne64(&buf[shift]), !=, 0);
-
- g_assert_cmpint(unaligned_read_le32(&buf[shift]), ==, (guint32) val);
- g_assert_cmpint(unaligned_read_be32(&buf[shift]), ==, ((guint32) val) << 24);
- g_assert_cmpint(unaligned_read_ne32(&buf[shift]), !=, 0);
-
- g_assert_cmpint(unaligned_read_le16(&buf[shift]), ==, (guint16) val);
- g_assert_cmpint(unaligned_read_be16(&buf[shift]), ==, ((guint16) val) << 8);
- g_assert_cmpint(unaligned_read_ne16(&buf[shift]), !=, 0);
- }
-}
-
-/*****************************************************************************/
-
-static void
-_strv_cmp_fuzz_input(const char *const * in,
- gssize l,
- const char *** out_strv_free_shallow,
- char *** out_strv_free_deep,
- const char *const **out_s1,
- const char *const **out_s2)
-{
- const char **strv;
- gsize i;
-
- /* Fuzz the input argument. It will return two output arrays that are semantically
- * equal the input. */
-
- if (nmtst_get_rand_bool()) {
- char **ss;
-
- if (l < 0)
- ss = g_strdupv((char **) in);
- else if (l == 0) {
- ss = nmtst_get_rand_bool() ? NULL : g_new0(char *, 1);
- } else {
- ss = nm_memdup(in, sizeof(const char *) * l);
- for (i = 0; i < (gsize) l; i++)
- ss[i] = g_strdup(ss[i]);
- }
- strv = (const char **) ss;
- *out_strv_free_deep = ss;
- } else {
- if (l < 0) {
- strv = in ? nm_memdup(in, sizeof(const char *) * (NM_PTRARRAY_LEN(in) + 1)) : NULL;
- } else if (l == 0) {
- strv = nmtst_get_rand_bool() ? NULL : g_new0(const char *, 1);
- } else
- strv = nm_memdup(in, sizeof(const char *) * l);
- *out_strv_free_shallow = strv;
- }
-
- *out_s1 = in;
- *out_s2 = strv;
-
- if (nmtst_get_rand_bool()) {
- /* randomly swap the original and the clone. That means, out_s1 is either
- * the input argument (as-is) or the sementically equal clone. */
- NM_SWAP(out_s1, out_s2);
- }
- if (nmtst_get_rand_bool()) {
- /* randomly make s1 and s2 the same. This is for testing that
- * comparing two identical pointers yields the same result. */
- *out_s2 = *out_s1;
- }
-}
-
-static void
-_strv_cmp_free_deep(char **strv, gssize len)
-{
- gssize i;
-
- if (strv) {
- if (len < 0)
- g_strfreev(strv);
- else {
- for (i = 0; i < len; i++)
- g_free(strv[i]);
- g_free(strv);
- }
- }
-}
-
-static void
-test_strv_cmp(void)
-{
- const char *const strv0[1] = {};
- const char *const strv1[2] = {
- "",
- };
-
-#define _STRV_CMP(a1, l1, a2, l2, equal) \
- G_STMT_START \
- { \
- gssize _l1 = (l1); \
- gssize _l2 = (l2); \
- const char *const * _a1; \
- const char *const * _a2; \
- const char *const * _a1x; \
- const char *const * _a2x; \
- char ** _a1_free_deep = NULL; \
- char ** _a2_free_deep = NULL; \
- gs_free const char **_a1_free_shallow = NULL; \
- gs_free const char **_a2_free_shallow = NULL; \
- int _c1, _c2; \
- \
- _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); \
- if (equal) { \
- g_assert_cmpint(_c1, ==, 0); \
- g_assert_cmpint(_c2, ==, 0); \
- } else { \
- g_assert_cmpint(_c1, ==, -1); \
- g_assert_cmpint(_c2, ==, 1); \
- } \
- \
- /* 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); \
- \
- _strv_cmp_free_deep(_a1_free_deep, _l1); \
- _strv_cmp_free_deep(_a2_free_deep, _l2); \
- } \
- G_STMT_END
-
- _STRV_CMP(NULL, -1, NULL, -1, TRUE);
-
- _STRV_CMP(NULL, -1, NULL, 0, FALSE);
- _STRV_CMP(NULL, -1, strv0, 0, FALSE);
- _STRV_CMP(NULL, -1, strv0, -1, FALSE);
-
- _STRV_CMP(NULL, 0, NULL, 0, TRUE);
- _STRV_CMP(NULL, 0, strv0, 0, TRUE);
- _STRV_CMP(NULL, 0, strv0, -1, TRUE);
- _STRV_CMP(strv0, 0, strv0, 0, TRUE);
- _STRV_CMP(strv0, 0, strv0, -1, TRUE);
- _STRV_CMP(strv0, -1, strv0, -1, TRUE);
-
- _STRV_CMP(NULL, 0, strv1, -1, FALSE);
- _STRV_CMP(NULL, 0, strv1, 1, FALSE);
- _STRV_CMP(strv0, 0, strv1, -1, FALSE);
- _STRV_CMP(strv0, 0, strv1, 1, FALSE);
- _STRV_CMP(strv0, -1, strv1, -1, FALSE);
- _STRV_CMP(strv0, -1, strv1, 1, FALSE);
-
- _STRV_CMP(strv1, -1, strv1, 1, TRUE);
- _STRV_CMP(strv1, 1, strv1, 1, TRUE);
-}
-
-/*****************************************************************************/
-
-static void
-_do_strstrip_avoid_copy(const char *str)
-{
- gs_free char *str1 = g_strdup(str);
- gs_free char *str2 = g_strdup(str);
- gs_free char *str3 = NULL;
- gs_free char *str4 = NULL;
- const char * s3;
- const char * s4;
-
- if (str1)
- g_strstrip(str1);
-
- nm_strstrip(str2);
-
- g_assert_cmpstr(str1, ==, str2);
-
- s3 = nm_strstrip_avoid_copy(str, &str3);
- g_assert_cmpstr(str1, ==, s3);
-
- s4 = nm_strstrip_avoid_copy_a(10, str, &str4);
- g_assert_cmpstr(str1, ==, s4);
- g_assert(!str == !s4);
- g_assert(!s4 || strlen(s4) <= strlen(str));
- if (s4 && s4 == &str[strlen(str) - strlen(s4)]) {
- g_assert(!str4);
- g_assert(s3 == s4);
- } else if (s4 && strlen(s4) >= 10) {
- g_assert(str4);
- g_assert(s4 == str4);
- } else
- g_assert(!str4);
-
- if (!nm_streq0(str1, str))
- _do_strstrip_avoid_copy(str1);
-}
-
-static void
-test_strstrip_avoid_copy(void)
-{
- _do_strstrip_avoid_copy(NULL);
- _do_strstrip_avoid_copy("");
- _do_strstrip_avoid_copy(" ");
- _do_strstrip_avoid_copy(" a ");
- _do_strstrip_avoid_copy(" 012345678 ");
- _do_strstrip_avoid_copy(" 0123456789 ");
- _do_strstrip_avoid_copy(" 01234567890 ");
- _do_strstrip_avoid_copy(" 012345678901 ");
-}
-
-/*****************************************************************************/
-
-static void
-test_nm_utils_bin2hexstr(void)
-{
- int n_run;
-
- for (n_run = 0; n_run < 500; n_run++) {
- guint8 buf[100];
- guint8 buf2[G_N_ELEMENTS(buf) + 1];
- gsize len = nmtst_get_rand_uint32() % (G_N_ELEMENTS(buf) + 1);
- char strbuf1[G_N_ELEMENTS(buf) * 3];
- gboolean allocate = nmtst_get_rand_bool();
- char delimiter = nmtst_get_rand_bool() ? ':' : '\0';
- gboolean upper_case = nmtst_get_rand_bool();
- gboolean hexdigit_pairs_mangled;
- gsize expected_strlen;
- char * str_hex;
- gsize required_len;
- gboolean outlen_set;
- gsize outlen;
- guint8 * bin2;
- guint i, j;
-
- nmtst_rand_buf(NULL, buf, len);
-
- if (len == 0)
- expected_strlen = 0;
- else if (delimiter != '\0')
- expected_strlen = (len * 3u) - 1;
- else
- expected_strlen = len * 2u;
-
- g_assert_cmpint(expected_strlen, <, G_N_ELEMENTS(strbuf1));
-
- str_hex =
- nm_utils_bin2hexstr_full(buf, len, delimiter, upper_case, !allocate ? strbuf1 : NULL);
-
- g_assert(str_hex);
- if (!allocate)
- g_assert(str_hex == strbuf1);
- g_assert_cmpint(strlen(str_hex), ==, expected_strlen);
-
- g_assert(NM_STRCHAR_ALL(
- str_hex,
- ch,
- (ch >= '0' && ch <= '9') || ch == delimiter
- || (upper_case ? (ch >= 'A' && ch <= 'F') : (ch >= 'a' && ch <= 'f'))));
-
- hexdigit_pairs_mangled = FALSE;
- if (delimiter && len > 1 && nmtst_get_rand_bool()) {
- /* randomly convert "0?" sequences to single digits, so we can get hexdigit_pairs_required
- * parameter. */
- g_assert(strlen(str_hex) >= 5);
- g_assert(str_hex[2] == delimiter);
- i = 0;
- j = 0;
- for (;;) {
- g_assert(g_ascii_isxdigit(str_hex[i]));
- g_assert(g_ascii_isxdigit(str_hex[i + 1]));
- g_assert(NM_IN_SET(str_hex[i + 2], delimiter, '\0'));
- if (str_hex[i] == '0' && nmtst_get_rand_bool()) {
- i++;
- str_hex[j++] = str_hex[i++];
- hexdigit_pairs_mangled = TRUE;
- } else {
- str_hex[j++] = str_hex[i++];
- str_hex[j++] = str_hex[i++];
- }
- if (str_hex[i] == '\0') {
- str_hex[j] = '\0';
- break;
- }
- g_assert(str_hex[i] == delimiter);
- str_hex[j++] = str_hex[i++];
- }
- }
-
- required_len = nmtst_get_rand_bool() ? len : 0u;
-
- outlen_set = required_len == 0 || nmtst_get_rand_bool();
-
- memset(buf2, 0, sizeof(buf2));
-
- bin2 = nm_utils_hexstr2bin_full(str_hex,
- nmtst_get_rand_bool(),
- delimiter != '\0' && nmtst_get_rand_bool(),
- !hexdigit_pairs_mangled && nmtst_get_rand_bool(),
- delimiter != '\0'
- ? nmtst_rand_select((const char *) ":", ":-")
- : nmtst_rand_select((const char *) ":", ":-", "", NULL),
- required_len,
- buf2,
- len,
- outlen_set ? &outlen : NULL);
- if (len > 0) {
- g_assert(bin2);
- g_assert(bin2 == buf2);
- } else
- g_assert(!bin2);
-
- if (outlen_set)
- g_assert_cmpint(outlen, ==, len);
-
- g_assert_cmpmem(buf, len, buf2, len);
-
- g_assert(buf2[len] == '\0');
-
- if (hexdigit_pairs_mangled) {
- /* we mangled the hexstr to contain single digits. Trying to parse with
- * hexdigit_pairs_required must now fail. */
- bin2 = nm_utils_hexstr2bin_full(
- str_hex,
- nmtst_get_rand_bool(),
- delimiter != '\0' && nmtst_get_rand_bool(),
- TRUE,
- delimiter != '\0' ? nmtst_rand_select((const char *) ":", ":-")
- : nmtst_rand_select((const char *) ":", ":-", "", NULL),
- required_len,
- buf2,
- len,
- outlen_set ? &outlen : NULL);
- g_assert(!bin2);
- }
-
- if (allocate)
- g_free(str_hex);
- }
-}
-
-/*****************************************************************************/
-
-static void
-test_nm_ref_string(void)
-{
- nm_auto_ref_string NMRefString *s1 = NULL;
- NMRefString * s2;
-
- s1 = nm_ref_string_new("hallo");
- g_assert(s1);
- g_assert_cmpstr(s1->str, ==, "hallo");
- g_assert_cmpint(s1->len, ==, strlen("hallo"));
-
- s2 = nm_ref_string_new("hallo");
- g_assert(s2 == s1);
- nm_ref_string_unref(s2);
-
- s2 = nm_ref_string_new(NULL);
- g_assert(!s2);
- nm_ref_string_unref(s2);
-
-#define STR_WITH_NUL "hallo\0test\0"
- s2 = nm_ref_string_new_len(STR_WITH_NUL, NM_STRLEN(STR_WITH_NUL));
- g_assert(s2);
- g_assert_cmpstr(s2->str, ==, "hallo");
- g_assert_cmpint(s2->len, ==, NM_STRLEN(STR_WITH_NUL));
- g_assert_cmpint(s2->len, >, strlen(s2->str));
- g_assert_cmpmem(s2->str, s2->len, STR_WITH_NUL, NM_STRLEN(STR_WITH_NUL));
- g_assert(s2->str[s2->len] == '\0');
- nm_ref_string_unref(s2);
-}
-
-/*****************************************************************************/
-
-static NM_UTILS_STRING_TABLE_LOOKUP_DEFINE(
- _do_string_table_lookup,
- int,
- { ; },
- { return -1; },
- {"0", 0},
- {"1", 1},
- {"2", 2},
- {"3", 3}, );
-
-static void
-test_string_table_lookup(void)
-{
- const char *const args[] = {
- NULL,
- "0",
- "1",
- "2",
- "3",
- "x",
- };
- int i;
-
- for (i = 0; i < G_N_ELEMENTS(args); i++) {
- const char *needle = args[i];
- const int val2 = _nm_utils_ascii_str_to_int64(needle, 10, 0, 100, -1);
- int val;
-
- val = _do_string_table_lookup(needle);
- g_assert_cmpint(val, ==, val2);
- }
-}
-
-/*****************************************************************************/
-
-static void
-test_nm_utils_get_next_realloc_size(void)
-{
- static const struct {
- gsize requested;
- gsize reserved_true;
- gsize reserved_false;
- } test_data[] = {
- {0, 8, 8},
- {1, 8, 8},
- {8, 8, 8},
- {9, 16, 16},
- {16, 16, 16},
- {17, 32, 32},
- {32, 32, 32},
- {33, 40, 40},
- {40, 40, 40},
- {41, 104, 104},
- {104, 104, 104},
- {105, 232, 232},
- {232, 232, 232},
- {233, 488, 488},
- {488, 488, 488},
- {489, 1000, 1000},
- {1000, 1000, 1000},
- {1001, 2024, 2024},
- {2024, 2024, 2024},
- {2025, 4072, 4072},
- {4072, 4072, 4072},
- {4073, 8168, 8168},
- {8168, 8168, 8168},
- {8169, 12264, 16360},
- {12263, 12264, 16360},
- {12264, 12264, 16360},
- {12265, 16360, 16360},
- {16360, 16360, 16360},
- {16361, 20456, 32744},
- {20456, 20456, 32744},
- {20457, 24552, 32744},
- {24552, 24552, 32744},
- {24553, 28648, 32744},
- {28648, 28648, 32744},
- {28649, 32744, 32744},
- {32744, 32744, 32744},
- {32745, 36840, 65512},
- {36840, 36840, 65512},
- {G_MAXSIZE - 0x1000u, G_MAXSIZE, G_MAXSIZE},
- {G_MAXSIZE - 25u, G_MAXSIZE, G_MAXSIZE},
- {G_MAXSIZE - 24u, G_MAXSIZE, G_MAXSIZE},
- {G_MAXSIZE - 1u, G_MAXSIZE, G_MAXSIZE},
- {G_MAXSIZE, G_MAXSIZE, G_MAXSIZE},
- {NM_UTILS_GET_NEXT_REALLOC_SIZE_32,
- NM_UTILS_GET_NEXT_REALLOC_SIZE_32,
- NM_UTILS_GET_NEXT_REALLOC_SIZE_32},
- {NM_UTILS_GET_NEXT_REALLOC_SIZE_40,
- NM_UTILS_GET_NEXT_REALLOC_SIZE_40,
- NM_UTILS_GET_NEXT_REALLOC_SIZE_40},
- {NM_UTILS_GET_NEXT_REALLOC_SIZE_104,
- NM_UTILS_GET_NEXT_REALLOC_SIZE_104,
- NM_UTILS_GET_NEXT_REALLOC_SIZE_104},
- {NM_UTILS_GET_NEXT_REALLOC_SIZE_1000,
- NM_UTILS_GET_NEXT_REALLOC_SIZE_1000,
- NM_UTILS_GET_NEXT_REALLOC_SIZE_1000},
- };
- guint i;
-
- G_STATIC_ASSERT_EXPR(NM_UTILS_GET_NEXT_REALLOC_SIZE_104 == 104u);
- G_STATIC_ASSERT_EXPR(NM_UTILS_GET_NEXT_REALLOC_SIZE_1000 == 1000u);
-
- for (i = 0; i < G_N_ELEMENTS(test_data) + 5000u; i++) {
- gsize requested0;
-
- if (i < G_N_ELEMENTS(test_data))
- requested0 = test_data[i].requested;
- else {
- /* find some interesting random values for testing. */
- switch (nmtst_get_rand_uint32() % 5) {
- case 0:
- requested0 = nmtst_get_rand_size();
- break;
- case 1:
- /* values close to G_MAXSIZE. */
- requested0 = G_MAXSIZE - (nmtst_get_rand_uint32() % 12000u);
- break;
- case 2:
- /* values around G_MAXSIZE/2. */
- requested0 = (G_MAXSIZE / 2u) + 6000u - (nmtst_get_rand_uint32() % 12000u);
- break;
- case 3:
- /* values around powers of 2. */
- requested0 = (((gsize) 1) << (nmtst_get_rand_uint32() % (sizeof(gsize) * 8u)))
- + 6000u - (nmtst_get_rand_uint32() % 12000u);
- break;
- case 4:
- /* values around 4k borders. */
- requested0 = (nmtst_get_rand_size() & ~((gsize) 0xFFFu)) + 30u
- - (nmtst_get_rand_uint32() % 60u);
- break;
- default:
- g_assert_not_reached();
- }
- }
-
- {
- const gsize requested = requested0;
- gsize reserved_true;
- gsize reserved_false;
- bool truncated_true = FALSE;
- bool truncated_false = FALSE;
-
- if (sizeof(gsize) > 4 && requested > SIZE_MAX / 2u - 24u) {
- reserved_false = G_MAXSSIZE;
- truncated_false = TRUE;
- } else
- reserved_false = nm_utils_get_next_realloc_size(FALSE, requested);
-
- if (sizeof(gsize) > 4 && requested > SIZE_MAX - 0x1000u - 24u) {
- reserved_true = G_MAXSSIZE;
- truncated_true = TRUE;
- } else
- reserved_true = nm_utils_get_next_realloc_size(TRUE, requested);
-
- g_assert_cmpuint(reserved_true, >, 0);
- g_assert_cmpuint(reserved_false, >, 0);
- if (!truncated_true)
- g_assert_cmpuint(reserved_true, >=, requested);
- if (!truncated_false)
- g_assert_cmpuint(reserved_false, >=, requested);
- if (!truncated_true && !truncated_false)
- g_assert_cmpuint(reserved_false, >=, reserved_true);
-
- if (i < G_N_ELEMENTS(test_data)) {
- if (!truncated_true)
- g_assert_cmpuint(reserved_true, ==, test_data[i].reserved_true);
- if (!truncated_false)
- g_assert_cmpuint(reserved_false, ==, test_data[i].reserved_false);
- }
-
- /* reserved_false is generally the next power of two - 24. */
- if (reserved_false == G_MAXSIZE)
- g_assert_cmpuint(requested, >, G_MAXSIZE / 2u - 24u);
- else if (!reserved_false) {
- g_assert_cmpuint(reserved_false, <=, G_MAXSIZE - 24u);
- if (reserved_false >= 40) {
- const gsize _pow2 = reserved_false + 24u;
-
- /* reserved_false must always be a power of two minus 24. */
- g_assert_cmpuint(_pow2, >=, 64u);
- g_assert_cmpuint(_pow2, >, requested);
- g_assert(nm_utils_is_power_of_two(_pow2));
-
- /* but _pow2/2 must also be smaller than what we requested. */
- g_assert_cmpuint(_pow2 / 2u - 24u, <, requested);
- } else {
- /* smaller values are hard-coded. */
- }
- }
-
- /* reserved_true is generally the next 4k border - 24. */
- if (reserved_true == G_MAXSIZE)
- g_assert_cmpuint(requested, >, G_MAXSIZE - 0x1000u - 24u);
- else if (!truncated_true) {
- g_assert_cmpuint(reserved_true, <=, G_MAXSIZE - 24u);
- if (reserved_true > 8168u) {
- const gsize page_border = reserved_true + 24u;
-
- /* reserved_true must always be aligned to 4k (minus 24). */
- g_assert_cmpuint(page_border % 0x1000u, ==, 0);
- if (requested > 0x1000u - 24u) {
- /* page_border not be more than 4k above requested. */
- g_assert_cmpuint(page_border, >=, 0x1000u - 24u);
- g_assert_cmpuint(page_border - 0x1000u - 24u, <, requested);
- }
- } else {
- /* for smaller sizes, reserved_true and reserved_false are the same. */
- g_assert_cmpuint(reserved_true, ==, reserved_false);
- }
- }
- }
- }
-}
-
-/*****************************************************************************/
-
-static void
-test_nm_str_buf(void)
-{
- guint i_run;
-
- for (i_run = 0; TRUE; i_run++) {
- nm_auto_str_buf NMStrBuf strbuf = {};
- nm_auto_free_gstring GString *gstr = NULL;
- int i, j, k;
- int c;
-
- nm_str_buf_init(&strbuf, nmtst_get_rand_uint32() % 200u + 1u, nmtst_get_rand_bool());
-
- if (i_run < 1000) {
- c = nmtst_get_rand_word_length(NULL);
- for (i = 0; i < c; i++)
- nm_str_buf_append_c(&strbuf, '0' + (i % 10));
- gstr = g_string_new(nm_str_buf_get_str(&strbuf));
- j = nmtst_get_rand_uint32() % (strbuf.len + 1);
- k = nmtst_get_rand_uint32() % (strbuf.len - j + 2) - 1;
-
- nm_str_buf_erase(&strbuf, j, k, nmtst_get_rand_bool());
- g_string_erase(gstr, j, k);
- g_assert_cmpstr(gstr->str, ==, nm_str_buf_get_str(&strbuf));
- } else
- return;
- }
-}
-
-/*****************************************************************************/
-
-static void
-test_nm_utils_parse_next_line(void)
-{
- const char *data;
- const char *data0;
- gsize data_len;
- const char *line_start;
- gsize line_len;
- int i_run;
- gsize j, k;
-
- data = NULL;
- data_len = 0;
- g_assert(!nm_utils_parse_next_line(&data, &data_len, &line_start, &line_len));
-
- for (i_run = 0; i_run < 1000; i_run++) {
- gs_unref_ptrarray GPtrArray *strv = g_ptr_array_new_with_free_func(g_free);
- gs_unref_ptrarray GPtrArray *strv2 = g_ptr_array_new_with_free_func(g_free);
- gsize strv_len = nmtst_get_rand_word_length(NULL);
- nm_auto_str_buf NMStrBuf strbuf = NM_STR_BUF_INIT(0, nmtst_get_rand_bool());
-
- /* create a list of random words. */
- for (j = 0; j < strv_len; j++) {
- gsize w_len = nmtst_get_rand_word_length(NULL);
- NMStrBuf w_buf =
- NM_STR_BUF_INIT(nmtst_get_rand_uint32() % (w_len + 1), nmtst_get_rand_bool());
-
- for (k = 0; k < w_len; k++)
- nm_str_buf_append_c(&w_buf, '0' + (k % 10));
- nm_str_buf_maybe_expand(&w_buf, 1, TRUE);
- g_ptr_array_add(strv, nm_str_buf_finalize(&w_buf, NULL));
- }
-
- /* join the list of random words with (random) line delimiters
- * ("\0", "\n", "\r" or EOF). */
- for (j = 0; j < strv_len; j++) {
- nm_str_buf_append(&strbuf, strv->pdata[j]);
-again:
- switch (nmtst_get_rand_uint32() % 5) {
- case 0:
- nm_str_buf_append_c(&strbuf, '\0');
- break;
- case 1:
- if (strbuf.len > 0
- && (nm_str_buf_get_str_unsafe(&strbuf))[strbuf.len - 1] == '\r') {
- /* the previous line was empty and terminated by "\r". We
- * must not join with "\n". Retry. */
- goto again;
- }
- nm_str_buf_append_c(&strbuf, '\n');
- break;
- case 2:
- nm_str_buf_append_c(&strbuf, '\r');
- break;
- case 3:
- nm_str_buf_append(&strbuf, "\r\n");
- break;
- case 4:
- /* the last word randomly is delimited or not, but not if the last
- * word is "". */
- if (j + 1 < strv_len) {
- /* it's not the last word. Retry. */
- goto again;
- }
- g_assert(j == strv_len - 1);
- if (((const char *) strv->pdata[j])[0] == '\0') {
- /* if the last word was "", we need a delimiter (to parse it back).
- * Retry. */
- goto again;
- }
- /* The final delimiter gets omitted. It's EOF. */
- break;
- }
- }
-
- data0 = nm_str_buf_get_str_unsafe(&strbuf);
- if (!data0 && nmtst_get_rand_bool()) {
- nm_str_buf_maybe_expand(&strbuf, 1, TRUE);
- data0 = nm_str_buf_get_str_unsafe(&strbuf);
- g_assert(data0);
- }
- data_len = strbuf.len;
- g_assert((data_len > 0 && data0) || data_len == 0);
- data = data0;
- while (nm_utils_parse_next_line(&data, &data_len, &line_start, &line_len)) {
- g_assert(line_start);
- g_assert(line_start >= data0);
- g_assert(line_start < &data0[strbuf.len]);
- g_assert(!memchr(line_start, '\0', line_len));
- g_ptr_array_add(strv2, g_strndup(line_start, line_len));
- }
- g_assert(data_len == 0);
- if (data0)
- g_assert(data == &data0[strbuf.len]);
- 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)
- == 0);
- }
-}
-
-/*****************************************************************************/
-
-static void
-test_in_strset_ascii_case(void)
-{
- const char *x;
-
- x = NULL;
- g_assert(NM_IN_STRSET_ASCII_CASE(x, NULL));
- g_assert(NM_IN_STRSET_ASCII_CASE(x, NULL, "b"));
- g_assert(!NM_IN_STRSET_ASCII_CASE(x, "b"));
-
- x = "b";
- g_assert(NM_IN_STRSET(x, "b"));
- g_assert(NM_IN_STRSET_ASCII_CASE(x, "b"));
- g_assert(!NM_IN_STRSET(x, "B"));
- g_assert(NM_IN_STRSET_ASCII_CASE(x, "B"));
-}
-
-/*****************************************************************************/
-
-static void
-test_is_specific_hostname(void)
-{
- g_assert(!nm_utils_is_specific_hostname(NULL));
- g_assert(!nm_utils_is_specific_hostname(""));
- g_assert(!nm_utils_is_specific_hostname("(none)"));
- g_assert(nm_utils_is_specific_hostname("(NONE)"));
-
- g_assert(!nm_utils_is_specific_hostname("localhost"));
- g_assert(!nm_utils_is_specific_hostname("lOcalHost"));
- g_assert(!nm_utils_is_specific_hostname("LOCALHOST"));
-
- g_assert(!nm_utils_is_specific_hostname("LOCALHOST.localdomain"));
-
- g_assert(nm_utils_is_specific_hostname("xlocalhost"));
- g_assert(nm_utils_is_specific_hostname("lOcalHxost"));
- g_assert(nm_utils_is_specific_hostname("LOCALxHOST"));
-
- g_assert(!nm_utils_is_specific_hostname("foo.LOCALHOST"));
- g_assert(!nm_utils_is_specific_hostname("foo.LOCALHOsT6."));
- g_assert(!nm_utils_is_specific_hostname("foo.LOCALHOsT6.localdomain6"));
- g_assert(!nm_utils_is_specific_hostname(".LOCALHOsT6.localdomain6"));
- g_assert(!nm_utils_is_specific_hostname("LOCALHOsT6.localdomain6"));
- g_assert(!nm_utils_is_specific_hostname("LOCALHOsT6.localdomain6."));
- g_assert(nm_utils_is_specific_hostname("LOCALHOsT6.localdomain."));
-
- g_assert(nm_utils_is_specific_hostname(" "));
-}
-
-/*****************************************************************************/
-
-static void
-test_strv_dup_packed(void)
-{
- gs_unref_ptrarray GPtrArray *src = NULL;
- int i_run;
-
- src = g_ptr_array_new_with_free_func(g_free);
-
- for (i_run = 0; i_run < 500; i_run++) {
- const int strv_len = nmtst_get_rand_word_length(NULL);
- gs_free const char **strv_cpy = NULL;
- const char *const * strv_src;
- int i, j;
-
- g_ptr_array_set_size(src, 0);
- for (i = 0; i < strv_len; i++) {
- const int word_len = nmtst_get_rand_word_length(NULL);
- NMStrBuf sbuf = NM_STR_BUF_INIT(0, nmtst_get_rand_bool());
-
- for (j = 0; j < word_len; j++)
- nm_str_buf_append_c(&sbuf, 'a' + (nmtst_get_rand_uint32() % 20));
-
- g_ptr_array_add(src, nm_str_buf_finalize(&sbuf, NULL) ?: g_new0(char, 1));
- }
- g_ptr_array_add(src, NULL);
-
- strv_src = (const char *const *) src->pdata;
- g_assert(strv_src);
- 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);
- 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));
- }
-}
-
-/*****************************************************************************/
-
-static int
-_hash_func_cmp_direct(gconstpointer a, gconstpointer b, gpointer user_data)
-{
- NM_CMP_DIRECT(GPOINTER_TO_INT(a), GPOINTER_TO_INT(b));
- return 0;
-}
-
-static void
-test_utils_hashtable_cmp(void)
-{
- static struct {
- int val_i;
- const char *val_s;
- } vals[] = {
- {
- 0,
- "0",
- },
- {
- 1,
- "1",
- },
- {
- 2,
- "2",
- },
- {
- 3,
- "3",
- },
- {
- 4,
- "4",
- },
- {
- 5,
- "5",
- },
- {
- 6,
- "6",
- },
- {
- 7,
- "7",
- },
- {
- 8,
- "8",
- },
- {
- 9,
- "9",
- },
- {
- 0,
- "a",
- },
- {
- 1,
- "a",
- },
- {
- 2,
- "a",
- },
- {
- 3,
- "a",
- },
- {
- 4,
- "a",
- },
- {
- 5,
- "a",
- },
- {
- 0,
- "0",
- },
- {
- 0,
- "1",
- },
- {
- 0,
- "2",
- },
- {
- 0,
- "3",
- },
- {
- 0,
- "4",
- },
- {
- 0,
- "5",
- },
- };
- guint test_run;
- int is_num_key;
-
- for (test_run = 0; test_run < 30; test_run++) {
- for (is_num_key = 0; is_num_key < 2; is_num_key++) {
- GHashFunc func_key_hash = is_num_key ? nm_direct_hash : nm_str_hash;
- GEqualFunc func_key_equal = is_num_key ? g_direct_equal : g_str_equal;
- GCompareDataFunc func_key_cmp =
- is_num_key ? _hash_func_cmp_direct : (GCompareDataFunc) nm_strcmp_with_data;
- GCompareDataFunc func_val_cmp =
- !is_num_key ? _hash_func_cmp_direct : (GCompareDataFunc) nm_strcmp_with_data;
- gs_unref_hashtable GHashTable *h1 = NULL;
- gs_unref_hashtable GHashTable *h2 = NULL;
- gboolean has_same_keys;
- guint i, n;
-
- h1 = g_hash_table_new(func_key_hash, func_key_equal);
- h2 = g_hash_table_new(func_key_hash, func_key_equal);
-
- n = nmtst_get_rand_word_length(NULL);
- for (i = 0; i < n; i++) {
- typeof(vals[0]) *v = &vals[nmtst_get_rand_uint32() % G_N_ELEMENTS(vals)];
- gconstpointer v_key = is_num_key ? GINT_TO_POINTER(v->val_i) : v->val_s;
- gconstpointer v_val = !is_num_key ? GINT_TO_POINTER(v->val_i) : v->val_s;
-
- g_hash_table_insert(h1, (gpointer) v_key, (gpointer) v_val);
- g_hash_table_insert(h2, (gpointer) v_key, (gpointer) v_val);
- }
-
- g_assert(nm_utils_hashtable_same_keys(h1, h2));
- g_assert(nm_utils_hashtable_cmp_equal(h1, h2, NULL, NULL));
- g_assert(nm_utils_hashtable_cmp_equal(h1, h2, func_val_cmp, NULL));
- g_assert(nm_utils_hashtable_cmp(h1, h2, FALSE, func_key_cmp, NULL, NULL) == 0);
- g_assert(nm_utils_hashtable_cmp(h1, h2, TRUE, func_key_cmp, NULL, NULL) == 0);
- g_assert(nm_utils_hashtable_cmp(h1, h2, FALSE, func_key_cmp, func_val_cmp, NULL) == 0);
- g_assert(nm_utils_hashtable_cmp(h1, h2, TRUE, func_key_cmp, func_val_cmp, NULL) == 0);
-
- n = nmtst_get_rand_word_length(NULL) + 1;
- has_same_keys = TRUE;
- for (i = 0; i < n; i++) {
-again:
-{
- typeof(vals[0]) *v = &vals[nmtst_get_rand_uint32() % G_N_ELEMENTS(vals)];
- gconstpointer v_key = is_num_key ? GINT_TO_POINTER(v->val_i) : v->val_s;
- gconstpointer v_val = !is_num_key ? GINT_TO_POINTER(v->val_i) : v->val_s;
- gpointer v_key2;
- gpointer v_val2;
-
- if (g_hash_table_lookup_extended(h1, v_key, &v_key2, &v_val2)) {
- g_assert(func_key_cmp(v_key, v_key2, NULL) == 0);
- if (func_val_cmp(v_val, v_val2, NULL) == 0)
- goto again;
- } else
- has_same_keys = FALSE;
-
- g_hash_table_insert(h2, (gpointer) v_key, (gpointer) v_val);
-}
- }
-
- if (has_same_keys) {
- g_assert(nm_utils_hashtable_same_keys(h1, h2));
- g_assert(nm_utils_hashtable_cmp_equal(h1, h2, NULL, NULL));
- g_assert(nm_utils_hashtable_cmp(h1, h2, FALSE, func_key_cmp, NULL, NULL) == 0);
- g_assert(nm_utils_hashtable_cmp(h1, h2, TRUE, func_key_cmp, NULL, NULL) == 0);
- } else {
- g_assert(!nm_utils_hashtable_same_keys(h1, h2));
- g_assert(!nm_utils_hashtable_cmp_equal(h1, h2, NULL, NULL));
- g_assert(nm_utils_hashtable_cmp(h1, h2, FALSE, func_key_cmp, NULL, NULL) != 0);
- g_assert(nm_utils_hashtable_cmp(h1, h2, TRUE, func_key_cmp, NULL, NULL) != 0);
- }
- g_assert(!nm_utils_hashtable_cmp_equal(h1, h2, func_val_cmp, NULL));
- g_assert(nm_utils_hashtable_cmp(h1, h2, FALSE, func_key_cmp, func_val_cmp, NULL) != 0);
- g_assert(nm_utils_hashtable_cmp(h1, h2, TRUE, func_key_cmp, func_val_cmp, NULL) != 0);
- }
- }
-}
-
-/*****************************************************************************/
-
-NMTST_DEFINE();
-
-int
-main(int argc, char **argv)
-{
- nmtst_init(&argc, &argv, TRUE);
-
- 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);
- g_test_add_func("/general/test_nm_make_strv", test_make_strv);
- g_test_add_func("/general/test_nm_strdup_int", test_nm_strdup_int);
- g_test_add_func("/general/test_nm_strndup_a", test_nm_strndup_a);
- g_test_add_func("/general/test_nm_ip4_addr_is_localhost", test_nm_ip4_addr_is_localhost);
- g_test_add_func("/general/test_unaligned", test_unaligned);
- g_test_add_func("/general/test_strv_cmp", test_strv_cmp);
- g_test_add_func("/general/test_strstrip_avoid_copy", test_strstrip_avoid_copy);
- g_test_add_func("/general/test_nm_utils_bin2hexstr", test_nm_utils_bin2hexstr);
- g_test_add_func("/general/test_nm_ref_string", test_nm_ref_string);
- g_test_add_func("/general/test_string_table_lookup", test_string_table_lookup);
- g_test_add_func("/general/test_nm_utils_get_next_realloc_size",
- test_nm_utils_get_next_realloc_size);
- g_test_add_func("/general/test_nm_str_buf", test_nm_str_buf);
- g_test_add_func("/general/test_nm_utils_parse_next_line", test_nm_utils_parse_next_line);
- g_test_add_func("/general/test_in_strset_ascii_case", test_in_strset_ascii_case);
- g_test_add_func("/general/test_is_specific_hostname", test_is_specific_hostname);
- g_test_add_func("/general/test_strv_dup_packed", test_strv_dup_packed);
- g_test_add_func("/general/test_utils_hashtable_cmp", test_utils_hashtable_cmp);
-
- return g_test_run();
-}
diff --git a/shared/nm-log-core/nm-logging.c b/shared/nm-log-core/nm-logging.c
deleted file mode 100644
index cf3c3a8657..0000000000
--- a/shared/nm-log-core/nm-logging.c
+++ /dev/null
@@ -1,1035 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2006 - 2012 Red Hat, Inc.
- * Copyright (C) 2006 - 2008 Novell, Inc.
- */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-logging.h"
-
-#include <dlfcn.h>
-#include <syslog.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <sys/wait.h>
-#include <sys/stat.h>
-#include <strings.h>
-
-#if SYSTEMD_JOURNAL
- #define SD_JOURNAL_SUPPRESS_LOCATION
- #include <systemd/sd-journal.h>
-#endif
-
-#include "nm-glib-aux/nm-logging-base.h"
-#include "nm-glib-aux/nm-time-utils.h"
-
-/*****************************************************************************/
-
-/* Notes about thread-safety:
- *
- * NetworkManager generally is single-threaded and uses a (GLib) mainloop.
- * However, nm-logging is in parts thread-safe. That means:
- *
- * - functions that configure logging (nm_logging_init(), nm_logging_setup()) and
- * most other functions MUST be called only from the main-thread. These functions
- * are expected to be called infrequently, so they may or may not use a mutex
- * (but the overhead is negligible here).
- *
- * - functions that do the actual logging logging (nm_log(), nm_logging_enabled()) are
- * thread-safe and may be used from multiple threads.
- * - When called from the not-main-thread, @mt_require_locking must be set to %TRUE.
- * In this case, a Mutex will be used for accessing the global state.
- * - When called from the main-thread, they may optionally pass @mt_require_locking %FALSE.
- * This avoids extra locking and is in particular interesting for nm_logging_enabled(),
- * which is expected to be called frequently and from the main-thread.
- *
- * Note that the logging macros honor %NM_THREAD_SAFE_ON_MAIN_THREAD define, to automatically
- * set @mt_require_locking. That means, by default %NM_THREAD_SAFE_ON_MAIN_THREAD is "1",
- * and code that only runs on the main-thread (which is the majority), can get away
- * without locking.
- */
-
-/*****************************************************************************/
-
-G_STATIC_ASSERT(LOG_EMERG == 0);
-G_STATIC_ASSERT(LOG_ALERT == 1);
-G_STATIC_ASSERT(LOG_CRIT == 2);
-G_STATIC_ASSERT(LOG_ERR == 3);
-G_STATIC_ASSERT(LOG_WARNING == 4);
-G_STATIC_ASSERT(LOG_NOTICE == 5);
-G_STATIC_ASSERT(LOG_INFO == 6);
-G_STATIC_ASSERT(LOG_DEBUG == 7);
-
-/* We have more then 32 logging domains. Assert that it compiles to a 64 bit sized enum */
-G_STATIC_ASSERT(sizeof(NMLogDomain) >= sizeof(guint64));
-
-/* Combined domains */
-#define LOGD_ALL_STRING "ALL"
-#define LOGD_DEFAULT_STRING "DEFAULT"
-#define LOGD_DHCP_STRING "DHCP"
-#define LOGD_IP_STRING "IP"
-
-/*****************************************************************************/
-
-typedef enum {
- LOG_BACKEND_GLIB,
- LOG_BACKEND_SYSLOG,
- LOG_BACKEND_JOURNAL,
-} LogBackend;
-
-typedef struct {
- NMLogDomain num;
- const char *name;
-} LogDesc;
-
-typedef struct {
- char *logging_domains_to_string;
-} GlobalMain;
-
-typedef struct {
- NMLogLevel log_level;
- bool uses_syslog : 1;
- bool init_pre_done : 1;
- bool init_done : 1;
- bool debug_stderr : 1;
- const char *prefix;
- const char *syslog_identifier;
-
- /* before we setup syslog (during start), the backend defaults to GLIB, meaning:
- * we use g_log() for all logging. At that point, the application is not yet supposed
- * to do any logging and doing so indicates a bug.
- *
- * Afterwards, the backend is either SYSLOG or JOURNAL. From that point, also
- * g_log() is redirected to this backend via a logging handler. */
- LogBackend log_backend;
-} Global;
-
-/*****************************************************************************/
-
-G_LOCK_DEFINE_STATIC(log);
-
-/* This data must only be accessed from the main-thread (and as
- * such does not need any lock). */
-static GlobalMain gl_main = {};
-
-static union {
- /* a union with an immutable and a mutable alias for the Global.
- * Since nm-logging must be thread-safe, we must take care at which
- * places we only read value ("imm") and where we modify them ("mut"). */
- Global mut;
- const Global imm;
-} gl = {
- .imm =
- {
- /* nm_logging_setup ("INFO", LOGD_DEFAULT_STRING, NULL, NULL); */
- .log_level = LOGL_INFO,
- .log_backend = LOG_BACKEND_GLIB,
- .syslog_identifier = "SYSLOG_IDENTIFIER=" G_LOG_DOMAIN,
- .prefix = "",
- },
-};
-
-NMLogDomain _nm_logging_enabled_state[_LOGL_N_REAL] = {
- /* nm_logging_setup ("INFO", LOGD_DEFAULT_STRING, NULL, NULL);
- *
- * Note: LOGD_VPN_PLUGIN is special and must be disabled for
- * DEBUG and TRACE levels. */
- [LOGL_INFO] = LOGD_DEFAULT,
- [LOGL_WARN] = LOGD_DEFAULT,
- [LOGL_ERR] = LOGD_DEFAULT,
-};
-
-/*****************************************************************************/
-
-static const LogDesc domain_desc[] = {
- {LOGD_PLATFORM, "PLATFORM"},
- {LOGD_RFKILL, "RFKILL"},
- {LOGD_ETHER, "ETHER"},
- {LOGD_WIFI, "WIFI"},
- {LOGD_BT, "BT"},
- {LOGD_MB, "MB"},
- {LOGD_DHCP4, "DHCP4"},
- {LOGD_DHCP6, "DHCP6"},
- {LOGD_PPP, "PPP"},
- {LOGD_WIFI_SCAN, "WIFI_SCAN"},
- {LOGD_IP4, "IP4"},
- {LOGD_IP6, "IP6"},
- {LOGD_AUTOIP4, "AUTOIP4"},
- {LOGD_DNS, "DNS"},
- {LOGD_VPN, "VPN"},
- {LOGD_SHARING, "SHARING"},
- {LOGD_SUPPLICANT, "SUPPLICANT"},
- {LOGD_AGENTS, "AGENTS"},
- {LOGD_SETTINGS, "SETTINGS"},
- {LOGD_SUSPEND, "SUSPEND"},
- {LOGD_CORE, "CORE"},
- {LOGD_DEVICE, "DEVICE"},
- {LOGD_OLPC, "OLPC"},
- {LOGD_INFINIBAND, "INFINIBAND"},
- {LOGD_FIREWALL, "FIREWALL"},
- {LOGD_ADSL, "ADSL"},
- {LOGD_BOND, "BOND"},
- {LOGD_VLAN, "VLAN"},
- {LOGD_BRIDGE, "BRIDGE"},
- {LOGD_DBUS_PROPS, "DBUS_PROPS"},
- {LOGD_TEAM, "TEAM"},
- {LOGD_CONCHECK, "CONCHECK"},
- {LOGD_DCB, "DCB"},
- {LOGD_DISPATCH, "DISPATCH"},
- {LOGD_AUDIT, "AUDIT"},
- {LOGD_SYSTEMD, "SYSTEMD"},
- {LOGD_VPN_PLUGIN, "VPN_PLUGIN"},
- {LOGD_PROXY, "PROXY"},
- {0},
-};
-
-/*****************************************************************************/
-
-static char *_domains_to_string(gboolean include_level_override,
- NMLogLevel log_level,
- const NMLogDomain log_state[static _LOGL_N_REAL]);
-
-/*****************************************************************************/
-
-static gboolean
-_syslog_identifier_valid_domain(const char *domain)
-{
- char c;
-
- if (!domain || !domain[0])
- return FALSE;
-
- /* we pass the syslog identifier as format string. No funny stuff. */
-
- for (; (c = domain[0]); domain++) {
- if ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z') || (c >= '0' && c <= '9')
- || NM_IN_SET(c, '-', '_'))
- continue;
- return FALSE;
- }
- return TRUE;
-}
-
-static gboolean
-_syslog_identifier_assert(const char *syslog_identifier)
-{
- g_assert(syslog_identifier);
- g_assert(g_str_has_prefix(syslog_identifier, "SYSLOG_IDENTIFIER="));
- g_assert(_syslog_identifier_valid_domain(&syslog_identifier[NM_STRLEN("SYSLOG_IDENTIFIER=")]));
- return TRUE;
-}
-
-static const char *
-syslog_identifier_domain(const char *syslog_identifier)
-{
- nm_assert(_syslog_identifier_assert(syslog_identifier));
- return &syslog_identifier[NM_STRLEN("SYSLOG_IDENTIFIER=")];
-}
-
-#if SYSTEMD_JOURNAL
-static const char *
-syslog_identifier_full(const char *syslog_identifier)
-{
- nm_assert(_syslog_identifier_assert(syslog_identifier));
- return &syslog_identifier[0];
-}
-#endif
-
-/*****************************************************************************/
-
-static gboolean
-match_log_level(const char *level, NMLogLevel *out_level, GError **error)
-{
- if (_nm_log_parse_level(level, out_level))
- return TRUE;
-
- g_set_error(error,
- _NM_MANAGER_ERROR,
- _NM_MANAGER_ERROR_UNKNOWN_LOG_LEVEL,
- _("Unknown log level '%s'"),
- level);
- return FALSE;
-}
-
-gboolean
-nm_logging_setup(const char *level, const char *domains, char **bad_domains, GError **error)
-{
- GString * unrecognized = NULL;
- NMLogDomain cur_log_state[_LOGL_N_REAL];
- NMLogDomain new_log_state[_LOGL_N_REAL];
- NMLogLevel cur_log_level;
- NMLogLevel new_log_level;
- gs_free const char **domains_v = NULL;
- gsize i_d;
- int i;
- gboolean had_platform_debug;
- gs_free char * domains_free = NULL;
-
- NM_ASSERT_ON_MAIN_THREAD();
-
- g_return_val_if_fail(!bad_domains || !*bad_domains, FALSE);
- g_return_val_if_fail(!error || !*error, FALSE);
-
- cur_log_level = gl.imm.log_level;
- memcpy(cur_log_state, _nm_logging_enabled_state, sizeof(cur_log_state));
-
- new_log_level = cur_log_level;
-
- if (!domains || !*domains) {
- domains_free = _domains_to_string(FALSE, cur_log_level, cur_log_state);
- domains = domains_free;
- }
-
- for (i = 0; i < G_N_ELEMENTS(new_log_state); i++)
- new_log_state[i] = 0;
-
- if (level && *level) {
- if (!match_log_level(level, &new_log_level, error))
- return FALSE;
- if (new_log_level == _LOGL_KEEP) {
- new_log_level = cur_log_level;
- for (i = 0; i < G_N_ELEMENTS(new_log_state); i++)
- new_log_state[i] = cur_log_state[i];
- }
- }
-
- domains_v = nm_utils_strsplit_set(domains, ", ");
- for (i_d = 0; domains_v && domains_v[i_d]; i_d++) {
- const char * s = domains_v[i_d];
- const char * p;
- const LogDesc *diter;
- NMLogLevel domain_log_level;
- NMLogDomain bits;
-
- /* LOGD_VPN_PLUGIN is protected, that is, when setting ALL or DEFAULT,
- * it does not enable the verbose levels DEBUG and TRACE, because that
- * may expose sensitive data. */
- NMLogDomain protect = LOGD_NONE;
-
- p = strchr(s, ':');
- if (p) {
- *((char *) p) = '\0';
- if (!match_log_level(p + 1, &domain_log_level, error))
- return FALSE;
- } else
- domain_log_level = new_log_level;
-
- bits = 0;
-
- if (domains_free) {
- /* The caller didn't provide any domains to set (`nmcli general logging level DEBUG`).
- * We reset all domains that were previously set, but we still want to protect
- * VPN_PLUGIN domain. */
- protect = LOGD_VPN_PLUGIN;
- }
-
- /* Check for combined domains */
- if (!g_ascii_strcasecmp(s, LOGD_ALL_STRING)) {
- bits = LOGD_ALL;
- protect = LOGD_VPN_PLUGIN;
- } else if (!g_ascii_strcasecmp(s, LOGD_DEFAULT_STRING)) {
- bits = LOGD_DEFAULT;
- protect = LOGD_VPN_PLUGIN;
- } else if (!g_ascii_strcasecmp(s, LOGD_DHCP_STRING))
- bits = LOGD_DHCP;
- else if (!g_ascii_strcasecmp(s, LOGD_IP_STRING))
- bits = LOGD_IP;
-
- /* Check for compatibility domains */
- else if (!g_ascii_strcasecmp(s, "HW"))
- bits = LOGD_PLATFORM;
- else if (!g_ascii_strcasecmp(s, "WIMAX"))
- continue;
-
- else {
- for (diter = &domain_desc[0]; diter->name; diter++) {
- if (!g_ascii_strcasecmp(diter->name, s)) {
- bits = diter->num;
- break;
- }
- }
-
- if (!bits) {
- if (!bad_domains) {
- g_set_error(error,
- _NM_MANAGER_ERROR,
- _NM_MANAGER_ERROR_UNKNOWN_LOG_DOMAIN,
- _("Unknown log domain '%s'"),
- s);
- return FALSE;
- }
-
- if (unrecognized)
- g_string_append(unrecognized, ", ");
- else
- unrecognized = g_string_new(NULL);
- g_string_append(unrecognized, s);
- continue;
- }
- }
-
- if (domain_log_level == _LOGL_KEEP) {
- for (i = 0; i < G_N_ELEMENTS(new_log_state); i++)
- new_log_state[i] = (new_log_state[i] & ~bits) | (cur_log_state[i] & bits);
- } else {
- for (i = 0; i < G_N_ELEMENTS(new_log_state); i++) {
- if (i < domain_log_level)
- new_log_state[i] &= ~bits;
- else {
- new_log_state[i] |= bits;
- if ((protect & bits) && i < LOGL_INFO)
- new_log_state[i] &= ~protect;
- }
- }
- }
- }
-
- nm_clear_g_free(&gl_main.logging_domains_to_string);
-
- had_platform_debug = _nm_logging_enabled_lockfree(LOGL_DEBUG, LOGD_PLATFORM);
-
- G_LOCK(log);
-
- gl.mut.log_level = new_log_level;
- for (i = 0; i < G_N_ELEMENTS(new_log_state); i++)
- _nm_logging_enabled_state[i] = new_log_state[i];
-
- G_UNLOCK(log);
-
- if (had_platform_debug && !_nm_logging_enabled_lockfree(LOGL_DEBUG, LOGD_PLATFORM)) {
- /* when debug logging is enabled, platform will cache all access to
- * sysctl. When the user disables debug-logging, we want to clear that
- * cache right away. */
- _nm_logging_clear_platform_logging_cache();
- }
-
- if (unrecognized)
- *bad_domains = g_string_free(unrecognized, FALSE);
-
- return TRUE;
-}
-
-const char *
-nm_logging_level_to_string(void)
-{
- NM_ASSERT_ON_MAIN_THREAD();
-
- return level_desc[gl.imm.log_level].name;
-}
-
-const char *
-nm_logging_all_levels_to_string(void)
-{
- static GString *str;
-
- if (G_UNLIKELY(!str)) {
- int i;
-
- str = g_string_new(NULL);
- for (i = 0; i < G_N_ELEMENTS(level_desc); i++) {
- if (str->len)
- g_string_append_c(str, ',');
- g_string_append(str, level_desc[i].name);
- }
- }
-
- return str->str;
-}
-
-const char *
-nm_logging_domains_to_string(void)
-{
- NM_ASSERT_ON_MAIN_THREAD();
-
- if (G_UNLIKELY(!gl_main.logging_domains_to_string)) {
- gl_main.logging_domains_to_string =
- _domains_to_string(TRUE, gl.imm.log_level, _nm_logging_enabled_state);
- }
-
- return gl_main.logging_domains_to_string;
-}
-
-static char *
-_domains_to_string(gboolean include_level_override,
- NMLogLevel log_level,
- const NMLogDomain log_state[static _LOGL_N_REAL])
-{
- const LogDesc *diter;
- GString * str;
- int i;
-
- /* We don't just return g_strdup() the logging domains that were set during
- * nm_logging_setup(), because we want to expand "DEFAULT" and "ALL".
- */
-
- str = g_string_sized_new(75);
- for (diter = &domain_desc[0]; diter->name; diter++) {
- /* If it's set for any lower level, it will also be set for LOGL_ERR */
- if (!(diter->num & log_state[LOGL_ERR]))
- continue;
-
- if (str->len)
- g_string_append_c(str, ',');
- g_string_append(str, diter->name);
-
- if (!include_level_override)
- continue;
-
- /* Check if it's logging at a lower level than the default. */
- for (i = 0; i < log_level; i++) {
- if (diter->num & log_state[i]) {
- g_string_append_printf(str, ":%s", level_desc[i].name);
- break;
- }
- }
- /* Check if it's logging at a higher level than the default. */
- if (!(diter->num & log_state[log_level])) {
- for (i = log_level + 1; i < _LOGL_N_REAL; i++) {
- if (diter->num & log_state[i]) {
- g_string_append_printf(str, ":%s", level_desc[i].name);
- break;
- }
- }
- }
- }
- return g_string_free(str, FALSE);
-}
-
-static char _all_logging_domains_to_str[273];
-
-const char *
-nm_logging_all_domains_to_string(void)
-{
- static const char *volatile str = NULL;
- const char *s;
-
-again:
- s = g_atomic_pointer_get(&str);
- if (G_UNLIKELY(!s)) {
- static gsize once = 0;
- const LogDesc *diter;
- gsize buf_l;
- char * buf_p;
-
- if (!g_once_init_enter(&once))
- goto again;
-
- buf_p = _all_logging_domains_to_str;
- buf_l = sizeof(_all_logging_domains_to_str);
-
- nm_utils_strbuf_append_str(&buf_p, &buf_l, LOGD_DEFAULT_STRING);
- for (diter = &domain_desc[0]; diter->name; diter++) {
- nm_utils_strbuf_append_c(&buf_p, &buf_l, ',');
- nm_utils_strbuf_append_str(&buf_p, &buf_l, diter->name);
- if (diter->num == LOGD_DHCP6)
- nm_utils_strbuf_append_str(&buf_p, &buf_l, "," LOGD_DHCP_STRING);
- else if (diter->num == LOGD_IP6)
- nm_utils_strbuf_append_str(&buf_p, &buf_l, "," LOGD_IP_STRING);
- }
- nm_utils_strbuf_append_str(&buf_p, &buf_l, LOGD_ALL_STRING);
-
- /* Did you modify the logging domains (or their names)? Adjust the size of
- * _all_logging_domains_to_str buffer above to have the exact size. */
- nm_assert(strlen(_all_logging_domains_to_str) == sizeof(_all_logging_domains_to_str) - 1);
- nm_assert(buf_l == 1);
-
- s = _all_logging_domains_to_str;
- g_atomic_pointer_set(&str, s);
- g_once_init_leave(&once, 1);
- }
-
- return s;
-}
-
-/**
- * nm_logging_get_level:
- * @domain: find the lowest enabled logging level for the
- * given domain. If this is a set of multiple
- * domains, the most verbose level will be returned.
- *
- * Returns: the lowest (most verbose) logging level for the
- * give @domain, or %_LOGL_OFF if it is disabled.
- **/
-NMLogLevel
-nm_logging_get_level(NMLogDomain domain)
-{
- NMLogLevel sl = _LOGL_OFF;
-
- G_STATIC_ASSERT(LOGL_TRACE == 0);
- while (sl > LOGL_TRACE && _nm_logging_enabled_lockfree(sl - 1, domain))
- sl--;
- return sl;
-}
-
-gboolean
-_nm_logging_enabled_locking(NMLogLevel level, NMLogDomain domain)
-{
- gboolean v;
-
- G_LOCK(log);
- v = _nm_logging_enabled_lockfree(level, domain);
- G_UNLOCK(log);
- return v;
-}
-
-gboolean
-_nm_log_enabled_impl(gboolean mt_require_locking, NMLogLevel level, NMLogDomain domain)
-{
- return nm_logging_enabled_mt(mt_require_locking, level, domain);
-}
-
-#if SYSTEMD_JOURNAL
-static void
-_iovec_set(struct iovec *iov, const void *str, gsize len)
-{
- iov->iov_base = (void *) str;
- iov->iov_len = len;
-}
-
-static void
-_iovec_set_string(struct iovec *iov, const char *str)
-{
- _iovec_set(iov, str, strlen(str));
-}
-
- #define _iovec_set_string_literal(iov, str) _iovec_set((iov), "" str "", NM_STRLEN(str))
-
-_nm_printf(3, 4) static void _iovec_set_format(struct iovec *iov,
- char ** iov_free,
- const char * format,
- ...)
-{
- va_list ap;
- char * str;
-
- va_start(ap, format);
- str = g_strdup_vprintf(format, ap);
- va_end(ap);
-
- _iovec_set_string(iov, str);
- *iov_free = str;
-}
-
- #define _iovec_set_format_a(iov, reserve_extra, format, ...) \
- G_STMT_START \
- { \
- const gsize _size = (reserve_extra) + (NM_STRLEN(format) + 3); \
- char *const _buf = g_alloca(_size); \
- int _len; \
- \
- G_STATIC_ASSERT_EXPR((reserve_extra) + (NM_STRLEN(format) + 3) <= 96); \
- \
- _len = g_snprintf(_buf, _size, "" format "", ##__VA_ARGS__); \
- \
- nm_assert(_len >= 0); \
- nm_assert(_len < _size); \
- nm_assert(_len == strlen(_buf)); \
- \
- _iovec_set((iov), _buf, _len); \
- } \
- G_STMT_END
-
- #define _iovec_set_format_str_a(iov, max_str_len, format, str_arg) \
- G_STMT_START \
- { \
- const char *_str_arg = (str_arg); \
- \
- nm_assert(_str_arg &&strlen(_str_arg) < (max_str_len)); \
- _iovec_set_format_a((iov), (max_str_len), format, str_arg); \
- } \
- G_STMT_END
-
-#endif
-
-void
-_nm_log_impl(const char *file,
- guint line,
- const char *func,
- gboolean mt_require_locking,
- NMLogLevel level,
- NMLogDomain domain,
- int error,
- const char *ifname,
- const char *conn_uuid,
- const char *fmt,
- ...)
-{
- va_list args;
- char * msg;
- GTimeVal tv;
- int errsv;
- const NMLogDomain *cur_log_state;
- NMLogDomain cur_log_state_copy[_LOGL_N_REAL];
- Global g_copy;
- const Global * g;
-
- if (G_UNLIKELY(mt_require_locking)) {
- G_LOCK(log);
- /* we evaluate logging-enabled under lock. There is still a race that
- * we might log the message below *after* logging was disabled. That means,
- * when disabling logging, we might still log messages. */
- if (!_nm_logging_enabled_lockfree(level, domain)) {
- G_UNLOCK(log);
- return;
- }
- g_copy = gl.imm;
- memcpy(cur_log_state_copy, _nm_logging_enabled_state, sizeof(cur_log_state_copy));
- G_UNLOCK(log);
- g = &g_copy;
- cur_log_state = cur_log_state_copy;
- } else {
- NM_ASSERT_ON_MAIN_THREAD();
- if (!_nm_logging_enabled_lockfree(level, domain))
- return;
- g = &gl.imm;
- cur_log_state = _nm_logging_enabled_state;
- }
-
- (void) cur_log_state;
-
- errsv = errno;
-
- /* Make sure that %m maps to the specified error */
- if (error != 0) {
- if (error < 0)
- error = -error;
- errno = error;
- }
-
- va_start(args, fmt);
- msg = g_strdup_vprintf(fmt, args);
- va_end(args);
-
-#define MESSAGE_FMT "%s%-7s [%ld.%04ld] %s"
-#define MESSAGE_ARG(prefix, tv, msg) \
- prefix, level_desc[level].level_str, (tv).tv_sec, ((tv).tv_usec / 100), (msg)
-
- g_get_current_time(&tv);
-
- if (g->debug_stderr)
- g_printerr(MESSAGE_FMT "\n", MESSAGE_ARG(g->prefix, tv, msg));
-
- switch (g->log_backend) {
-#if SYSTEMD_JOURNAL
- case LOG_BACKEND_JOURNAL:
- {
- gint64 now, boottime;
- struct iovec iov_data[15];
- struct iovec * iov = iov_data;
- char * iov_free_data[5];
- char ** iov_free = iov_free_data;
- const LogDesc *diter;
- NMLogDomain dom_all;
- char s_log_domains_buf[NM_STRLEN("NM_LOG_DOMAINS=") + sizeof(_all_logging_domains_to_str)];
- char *s_log_domains;
- gsize l_log_domains;
-
- now = nm_utils_get_monotonic_timestamp_nsec();
- boottime = nm_utils_monotonic_timestamp_as_boottime(now, 1);
-
- _iovec_set_format_a(iov++, 30, "PRIORITY=%d", level_desc[level].syslog_level);
- _iovec_set_format(iov++,
- iov_free++,
- "MESSAGE=" MESSAGE_FMT,
- MESSAGE_ARG(g->prefix, tv, msg));
- _iovec_set_string(iov++, syslog_identifier_full(g->syslog_identifier));
- _iovec_set_format_a(iov++, 30, "SYSLOG_PID=%ld", (long) getpid());
-
- dom_all = domain;
- s_log_domains = s_log_domains_buf;
- l_log_domains = sizeof(s_log_domains_buf);
-
- nm_utils_strbuf_append_str(&s_log_domains, &l_log_domains, "NM_LOG_DOMAINS=");
- for (diter = &domain_desc[0]; dom_all != 0 && diter->name; diter++) {
- if (!NM_FLAGS_ANY(dom_all, diter->num))
- continue;
- if (dom_all != domain)
- nm_utils_strbuf_append_c(&s_log_domains, &l_log_domains, ',');
- nm_utils_strbuf_append_str(&s_log_domains, &l_log_domains, diter->name);
- dom_all &= ~diter->num;
- }
- nm_assert(l_log_domains > 0);
- _iovec_set(iov++, s_log_domains_buf, s_log_domains - s_log_domains_buf);
-
- G_STATIC_ASSERT_EXPR(LOG_FAC(LOG_DAEMON) == 3);
- _iovec_set_string_literal(iov++, "SYSLOG_FACILITY=3");
- _iovec_set_format_str_a(iov++, 15, "NM_LOG_LEVEL=%s", level_desc[level].name);
- if (func)
- _iovec_set_format(iov++, iov_free++, "CODE_FUNC=%s", func);
- _iovec_set_format(iov++, iov_free++, "CODE_FILE=%s", file ?: "");
- _iovec_set_format_a(iov++, 20, "CODE_LINE=%u", line);
- _iovec_set_format_a(iov++,
- 60,
- "TIMESTAMP_MONOTONIC=%lld.%06lld",
- (long long) (now / NM_UTILS_NSEC_PER_SEC),
- (long long) ((now % NM_UTILS_NSEC_PER_SEC) / 1000));
- _iovec_set_format_a(iov++,
- 60,
- "TIMESTAMP_BOOTTIME=%lld.%06lld",
- (long long) (boottime / NM_UTILS_NSEC_PER_SEC),
- (long long) ((boottime % NM_UTILS_NSEC_PER_SEC) / 1000));
- if (error != 0)
- _iovec_set_format_a(iov++, 30, "ERRNO=%d", error);
- if (ifname)
- _iovec_set_format(iov++, iov_free++, "NM_DEVICE=%s", ifname);
- if (conn_uuid)
- _iovec_set_format(iov++, iov_free++, "NM_CONNECTION=%s", conn_uuid);
-
- nm_assert(iov <= &iov_data[G_N_ELEMENTS(iov_data)]);
- nm_assert(iov_free <= &iov_free_data[G_N_ELEMENTS(iov_free_data)]);
-
- sd_journal_sendv(iov_data, iov - iov_data);
-
- for (; --iov_free >= iov_free_data;)
- g_free(*iov_free);
- } break;
-#endif
- case LOG_BACKEND_SYSLOG:
- syslog(level_desc[level].syslog_level, MESSAGE_FMT, MESSAGE_ARG(g->prefix, tv, msg));
- break;
- default:
- g_log(syslog_identifier_domain(g->syslog_identifier),
- level_desc[level].g_log_level,
- MESSAGE_FMT,
- MESSAGE_ARG(g->prefix, tv, msg));
- break;
- }
-
- g_free(msg);
-
- errno = errsv;
-}
-
-/*****************************************************************************/
-
-void
-_nm_utils_monotonic_timestamp_initialized(const struct timespec *tp,
- gint64 offset_sec,
- gboolean is_boottime)
-{
- NM_ASSERT_ON_MAIN_THREAD();
-
- if (_nm_logging_enabled_lockfree(LOGL_DEBUG, LOGD_CORE)) {
- time_t now = time(NULL);
- struct tm tm;
- char s[255];
-
- strftime(s, sizeof(s), "%Y-%m-%d %H:%M:%S", localtime_r(&now, &tm));
- nm_log_dbg(LOGD_CORE,
- "monotonic timestamp started counting 1.%09ld seconds ago with "
- "an offset of %lld.0 seconds to %s (local time is %s)",
- tp->tv_nsec,
- (long long) -offset_sec,
- is_boottime ? "CLOCK_BOOTTIME" : "CLOCK_MONOTONIC",
- s);
- }
-}
-
-/*****************************************************************************/
-
-static void
-nm_log_handler(const char *log_domain, GLogLevelFlags level, const char *message, gpointer ignored)
-{
- int syslog_priority;
-
- switch (level & G_LOG_LEVEL_MASK) {
- case G_LOG_LEVEL_ERROR:
- syslog_priority = LOG_CRIT;
- break;
- case G_LOG_LEVEL_CRITICAL:
- syslog_priority = LOG_ERR;
- break;
- case G_LOG_LEVEL_WARNING:
- syslog_priority = LOG_WARNING;
- break;
- case G_LOG_LEVEL_MESSAGE:
- syslog_priority = LOG_NOTICE;
- break;
- case G_LOG_LEVEL_DEBUG:
- syslog_priority = LOG_DEBUG;
- break;
- case G_LOG_LEVEL_INFO:
- default:
- syslog_priority = LOG_INFO;
- break;
- }
-
- /* we don't need any locking here. The glib log handler gets only registered
- * once during nm_logging_init() and the global data is not modified afterwards. */
- nm_assert(gl.imm.init_done);
-
- if (gl.imm.debug_stderr)
- g_printerr("%s%s\n", gl.imm.prefix, message ?: "");
-
- switch (gl.imm.log_backend) {
-#if SYSTEMD_JOURNAL
- case LOG_BACKEND_JOURNAL:
- {
- gint64 now, boottime;
-
- now = nm_utils_get_monotonic_timestamp_nsec();
- boottime = nm_utils_monotonic_timestamp_as_boottime(now, 1);
-
- sd_journal_send("PRIORITY=%d",
- syslog_priority,
- "MESSAGE=%s%s",
- gl.imm.prefix,
- message ?: "",
- syslog_identifier_full(gl.imm.syslog_identifier),
- "SYSLOG_PID=%ld",
- (long) getpid(),
- "SYSLOG_FACILITY=3",
- "GLIB_DOMAIN=%s",
- log_domain ?: "",
- "GLIB_LEVEL=%d",
- (int) (level & G_LOG_LEVEL_MASK),
- "TIMESTAMP_MONOTONIC=%lld.%06lld",
- (long long) (now / NM_UTILS_NSEC_PER_SEC),
- (long long) ((now % NM_UTILS_NSEC_PER_SEC) / 1000),
- "TIMESTAMP_BOOTTIME=%lld.%06lld",
- (long long) (boottime / NM_UTILS_NSEC_PER_SEC),
- (long long) ((boottime % NM_UTILS_NSEC_PER_SEC) / 1000),
- NULL);
- } break;
-#endif
- default:
- syslog(syslog_priority, "%s%s", gl.imm.prefix, message ?: "");
- break;
- }
-}
-
-gboolean
-nm_logging_syslog_enabled(void)
-{
- NM_ASSERT_ON_MAIN_THREAD();
-
- return gl.imm.uses_syslog;
-}
-
-void
-nm_logging_init_pre(const char *syslog_identifier, char *prefix_take)
-{
- /* this function may be called zero or one times, and only
- * - on the main thread
- * - not after nm_logging_init(). */
-
- NM_ASSERT_ON_MAIN_THREAD();
-
- if (gl.imm.init_pre_done)
- g_return_if_reached();
-
- if (gl.imm.init_done)
- g_return_if_reached();
-
- if (!_syslog_identifier_valid_domain(syslog_identifier))
- g_return_if_reached();
-
- if (!prefix_take || !prefix_take[0])
- g_return_if_reached();
-
- G_LOCK(log);
-
- gl.mut.init_pre_done = TRUE;
-
- gl.mut.syslog_identifier = g_strdup_printf("SYSLOG_IDENTIFIER=%s", syslog_identifier);
- nm_assert(_syslog_identifier_assert(gl.imm.syslog_identifier));
-
- /* we pass the allocated string on and never free it. */
- gl.mut.prefix = prefix_take;
-
- G_UNLOCK(log);
-}
-
-void
-nm_logging_init(const char *logging_backend, gboolean debug)
-{
- gboolean fetch_monotonic_timestamp = FALSE;
- gboolean obsolete_debug_backend = FALSE;
- LogBackend x_log_backend;
-
- /* this function may be called zero or one times, and only on the
- * main thread. */
-
- NM_ASSERT_ON_MAIN_THREAD();
-
- nm_assert(NM_IN_STRSET("" NM_CONFIG_DEFAULT_LOGGING_BACKEND,
- NM_LOG_CONFIG_BACKEND_JOURNAL,
- NM_LOG_CONFIG_BACKEND_SYSLOG));
-
- if (gl.imm.init_done)
- g_return_if_reached();
-
- if (!logging_backend)
- logging_backend = "" NM_CONFIG_DEFAULT_LOGGING_BACKEND;
-
- if (nm_streq(logging_backend, NM_LOG_CONFIG_BACKEND_DEBUG)) {
- /* "debug" was wrongly documented as a valid logging backend. It makes no sense however,
- * because printing to stderr only makes sense when not demonizing. Whether to daemonize
- * is only controlled via command line arguments (--no-daemon, --debug) and not via the
- * logging backend from configuration.
- *
- * Fall back to the default. */
- logging_backend = "" NM_CONFIG_DEFAULT_LOGGING_BACKEND;
- obsolete_debug_backend = TRUE;
- }
-
- G_LOCK(log);
-
-#if SYSTEMD_JOURNAL
- if (!nm_streq(logging_backend, NM_LOG_CONFIG_BACKEND_SYSLOG)) {
- x_log_backend = LOG_BACKEND_JOURNAL;
-
- /* We only log the monotonic-timestamp with structured logging (journal).
- * Only in this case, fetch the timestamp. */
- fetch_monotonic_timestamp = TRUE;
- } else
-#endif
- {
- x_log_backend = LOG_BACKEND_SYSLOG;
- openlog(syslog_identifier_domain(gl.imm.syslog_identifier), LOG_PID, LOG_DAEMON);
- }
-
- gl.mut.init_done = TRUE;
- gl.mut.log_backend = x_log_backend;
- gl.mut.uses_syslog = TRUE;
- gl.mut.debug_stderr = debug;
-
- g_log_set_handler(syslog_identifier_domain(gl.imm.syslog_identifier),
- G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL | G_LOG_FLAG_RECURSION,
- nm_log_handler,
- NULL);
-
- G_UNLOCK(log);
-
- if (fetch_monotonic_timestamp) {
- /* ensure we read a monotonic timestamp. Reading the timestamp the first
- * time causes a logging message. We don't want to do that during _nm_log_impl. */
- nm_utils_get_monotonic_timestamp_nsec();
- }
-
- if (obsolete_debug_backend)
- nm_log_dbg(LOGD_CORE,
- "config: ignore deprecated logging backend 'debug', fallback to '%s'",
- logging_backend);
-
- if (nm_streq(logging_backend, NM_LOG_CONFIG_BACKEND_SYSLOG)) {
- /* good */
- } else if (nm_streq(logging_backend, NM_LOG_CONFIG_BACKEND_JOURNAL)) {
-#if !SYSTEMD_JOURNAL
- nm_log_warn(LOGD_CORE,
- "config: logging backend 'journal' is not available, fallback to 'syslog'");
-#endif
- } else {
- nm_log_warn(LOGD_CORE,
- "config: invalid logging backend '%s', fallback to '%s'",
- logging_backend,
-#if SYSTEMD_JOURNAL
- NM_LOG_CONFIG_BACKEND_JOURNAL
-#else
- NM_LOG_CONFIG_BACKEND_SYSLOG
-#endif
- );
- }
-}
diff --git a/shared/nm-log-core/nm-logging.h b/shared/nm-log-core/nm-logging.h
deleted file mode 100644
index d3143d3973..0000000000
--- a/shared/nm-log-core/nm-logging.h
+++ /dev/null
@@ -1,189 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0-or-later */
-/*
- * Copyright (C) 2006 - 2012 Red Hat, Inc.
- * Copyright (C) 2006 - 2008 Novell, Inc.
- */
-
-#ifndef __NETWORKMANAGER_LOGGING_H__
-#define __NETWORKMANAGER_LOGGING_H__
-
-#ifdef __NM_TEST_UTILS_H__
- #error nm-test-utils.h must be included as last header
-#endif
-
-#include "nm-glib-aux/nm-logging-fwd.h"
-
-#define NM_LOG_CONFIG_BACKEND_DEBUG "debug"
-#define NM_LOG_CONFIG_BACKEND_SYSLOG "syslog"
-#define NM_LOG_CONFIG_BACKEND_JOURNAL "journal"
-
-#define nm_log_err(domain, ...) nm_log(LOGL_ERR, (domain), NULL, NULL, __VA_ARGS__)
-#define nm_log_warn(domain, ...) nm_log(LOGL_WARN, (domain), NULL, NULL, __VA_ARGS__)
-#define nm_log_info(domain, ...) nm_log(LOGL_INFO, (domain), NULL, NULL, __VA_ARGS__)
-#define nm_log_dbg(domain, ...) nm_log(LOGL_DEBUG, (domain), NULL, NULL, __VA_ARGS__)
-#define nm_log_trace(domain, ...) nm_log(LOGL_TRACE, (domain), NULL, NULL, __VA_ARGS__)
-
-//#define _NM_LOG_FUNC G_STRFUNC
-#define _NM_LOG_FUNC NULL
-
-/* A wrapper for the _nm_log_impl() function that adds call site information.
- * Contrary to nm_log(), it unconditionally calls the function without
- * checking whether logging for the given level and domain is enabled. */
-#define _nm_log_mt(mt_require_locking, level, domain, error, ifname, con_uuid, ...) \
- G_STMT_START \
- { \
- _nm_log_impl(__FILE__, \
- __LINE__, \
- _NM_LOG_FUNC, \
- (mt_require_locking), \
- (level), \
- (domain), \
- (error), \
- (ifname), \
- (con_uuid), \
- ""__VA_ARGS__); \
- } \
- G_STMT_END
-
-#define _nm_log(level, domain, error, ifname, con_uuid, ...) \
- _nm_log_mt(!(NM_THREAD_SAFE_ON_MAIN_THREAD), \
- level, \
- domain, \
- error, \
- ifname, \
- con_uuid, \
- __VA_ARGS__)
-
-/* nm_log() only evaluates its argument list after checking
- * whether logging for the given level/domain is enabled. */
-#define nm_log(level, domain, ifname, con_uuid, ...) \
- G_STMT_START \
- { \
- if (nm_logging_enabled((level), (domain))) { \
- _nm_log(level, domain, 0, ifname, con_uuid, __VA_ARGS__); \
- } \
- } \
- G_STMT_END
-
-#define _nm_log_ptr(level, domain, ifname, con_uuid, self, prefix, ...) \
- nm_log((level), \
- (domain), \
- (ifname), \
- (con_uuid), \
- "%s[" NM_HASH_OBFUSCATE_PTR_FMT "] " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
- (prefix) ?: "", \
- NM_HASH_OBFUSCATE_PTR(self) _NM_UTILS_MACRO_REST(__VA_ARGS__))
-
-static inline gboolean
-_nm_log_ptr_is_debug(NMLogLevel level)
-{
- return level <= LOGL_DEBUG;
-}
-
-/* log a message for an object (with providing a generic @self pointer) */
-#define nm_log_ptr(level, domain, ifname, con_uuid, self, prefix, ...) \
- G_STMT_START \
- { \
- if (_nm_log_ptr_is_debug(level)) { \
- _nm_log_ptr((level), (domain), (ifname), (con_uuid), (self), (prefix), __VA_ARGS__); \
- } else { \
- const char *__prefix = (prefix); \
- \
- nm_log((level), \
- (domain), \
- (ifname), \
- (con_uuid), \
- "%s%s" _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
- __prefix ?: "", \
- __prefix ? " " : "" _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
- } \
- } \
- G_STMT_END
-
-#define _nm_log_obj(level, domain, ifname, con_uuid, self, prefix, ...) \
- _nm_log_ptr((level), (domain), (ifname), (con_uuid), (self), prefix, __VA_ARGS__)
-
-/* log a message for an object (with providing a @self pointer to a GObject).
- * Contrary to nm_log_ptr(), @self must be a GObject type (or %NULL).
- * As of now, nm_log_obj() is identical to nm_log_ptr(), but we might change that */
-#define nm_log_obj(level, domain, ifname, con_uuid, self, prefix, ...) \
- nm_log_ptr((level), (domain), (ifname), (con_uuid), (self), prefix, __VA_ARGS__)
-
-const char *nm_logging_level_to_string(void);
-const char *nm_logging_domains_to_string(void);
-
-/*****************************************************************************/
-
-extern NMLogDomain _nm_logging_enabled_state[_LOGL_N_REAL];
-
-static inline gboolean
-_nm_logging_enabled_lockfree(NMLogLevel level, NMLogDomain domain)
-{
- nm_assert(((guint) level) < G_N_ELEMENTS(_nm_logging_enabled_state));
- return (((guint) level) < G_N_ELEMENTS(_nm_logging_enabled_state))
- && !!(_nm_logging_enabled_state[level] & domain);
-}
-
-gboolean _nm_logging_enabled_locking(NMLogLevel level, NMLogDomain domain);
-
-static inline gboolean
-nm_logging_enabled_mt(gboolean mt_require_locking, NMLogLevel level, NMLogDomain domain)
-{
- if (mt_require_locking)
- return _nm_logging_enabled_locking(level, domain);
-
- NM_ASSERT_ON_MAIN_THREAD();
- return _nm_logging_enabled_lockfree(level, domain);
-}
-
-#define nm_logging_enabled(level, domain) \
- nm_logging_enabled_mt(!(NM_THREAD_SAFE_ON_MAIN_THREAD), level, domain)
-
-/*****************************************************************************/
-
-NMLogLevel nm_logging_get_level(NMLogDomain domain);
-
-const char *nm_logging_all_levels_to_string(void);
-const char *nm_logging_all_domains_to_string(void);
-
-gboolean
-nm_logging_setup(const char *level, const char *domains, char **bad_domains, GError **error);
-
-void nm_logging_init_pre(const char *syslog_identifier, char *prefix_take);
-
-void nm_logging_init(const char *logging_backend, gboolean debug);
-
-gboolean nm_logging_syslog_enabled(void);
-
-/*****************************************************************************/
-
-#define __NMLOG_DEFAULT(level, domain, prefix, ...) \
- G_STMT_START \
- { \
- nm_log((level), \
- (domain), \
- NULL, \
- NULL, \
- "%s: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
- (prefix) _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
- } \
- G_STMT_END
-
-#define __NMLOG_DEFAULT_WITH_ADDR(level, domain, prefix, ...) \
- G_STMT_START \
- { \
- nm_log((level), \
- (domain), \
- NULL, \
- NULL, \
- "%s[" NM_HASH_OBFUSCATE_PTR_FMT "]: " _NM_UTILS_MACRO_FIRST(__VA_ARGS__), \
- (prefix), \
- NM_HASH_OBFUSCATE_PTR(self) _NM_UTILS_MACRO_REST(__VA_ARGS__)); \
- } \
- G_STMT_END
-
-/*****************************************************************************/
-
-extern void _nm_logging_clear_platform_logging_cache(void);
-
-#endif /* __NETWORKMANAGER_LOGGING_H__ */
diff --git a/shared/nm-log-null/nm-logging-null.c b/shared/nm-log-null/nm-logging-null.c
deleted file mode 100644
index 63f1a82f44..0000000000
--- a/shared/nm-log-null/nm-logging-null.c
+++ /dev/null
@@ -1,36 +0,0 @@
-/* SPDX-License-Identifier: LGPL-2.1-or-later */
-/*
- * Copyright (C) 2018 Red Hat, Inc.
- */
-
-#include "nm-glib-aux/nm-default-glib-i18n-lib.h"
-
-#include "nm-glib-aux/nm-logging-fwd.h"
-
-/*****************************************************************************/
-
-gboolean
-_nm_log_enabled_impl(gboolean mt_require_locking, NMLogLevel level, NMLogDomain domain)
-{
- return FALSE;
-}
-
-void
-_nm_log_impl(const char *file,
- guint line,
- const char *func,
- gboolean mt_require_locking,
- NMLogLevel level,
- NMLogDomain domain,
- int error,
- const char *ifname,
- const char *con_uuid,
- const char *fmt,
- ...)
-{}
-
-void
-_nm_utils_monotonic_timestamp_initialized(const struct timespec *tp,
- gint64 offset_sec,
- gboolean is_boottime)
-{}
diff --git a/shared/nm-utils/nm-vpn-editor-plugin-call.h b/shared/nm-utils/nm-vpn-editor-plugin-call.h
index 5772b843ab..be0a6772e2 100644
--- a/shared/nm-utils/nm-vpn-editor-plugin-call.h
+++ b/shared/nm-utils/nm-vpn-editor-plugin-call.h
@@ -17,7 +17,7 @@
#include <NetworkManager.h>
/* we make use of other internal header files, you need those too. */
-#include "nm-glib-aux/nm-macros-internal.h"
+#include "libnm-glib-aux/nm-macros-internal.h"
/*****************************************************************************/