diff options
Diffstat (limited to 'shared/nm-utils')
| -rw-r--r-- | shared/nm-utils/c-list-util.c | 88 | ||||
| -rw-r--r-- | shared/nm-utils/c-list-util.h | 2 | ||||
| -rw-r--r-- | shared/nm-utils/c-list.h | 397 | ||||
| -rw-r--r-- | shared/nm-utils/nm-c-list.h | 81 | ||||
| -rw-r--r-- | shared/nm-utils/nm-compat.c | 95 | ||||
| -rw-r--r-- | shared/nm-utils/nm-compat.h | 53 | ||||
| -rw-r--r-- | shared/nm-utils/nm-dedup-multi.c | 6 | ||||
| -rw-r--r-- | shared/nm-utils/nm-dedup-multi.h | 2 | ||||
| -rw-r--r-- | shared/nm-utils/nm-enum-utils.c | 47 | ||||
| -rw-r--r-- | shared/nm-utils/nm-enum-utils.h | 5 | ||||
| -rw-r--r-- | shared/nm-utils/nm-glib.h | 382 | ||||
| -rw-r--r-- | shared/nm-utils/nm-hash-utils.c | 134 | ||||
| -rw-r--r-- | shared/nm-utils/nm-hash-utils.h | 13 | ||||
| -rw-r--r-- | shared/nm-utils/nm-jansson.h | 46 | ||||
| -rw-r--r-- | shared/nm-utils/nm-macros-internal.h | 245 | ||||
| -rw-r--r-- | shared/nm-utils/nm-obj.h | 2 | ||||
| -rw-r--r-- | shared/nm-utils/nm-shared-utils.c | 244 | ||||
| -rw-r--r-- | shared/nm-utils/nm-shared-utils.h | 166 | ||||
| -rw-r--r-- | shared/nm-utils/nm-test-utils.h | 70 | ||||
| -rw-r--r-- | shared/nm-utils/siphash24.c | 17 | ||||
| -rw-r--r-- | shared/nm-utils/unaligned.h | 61 |
21 files changed, 979 insertions, 1177 deletions
diff --git a/shared/nm-utils/c-list-util.c b/shared/nm-utils/c-list-util.c index 44ca26a5..070323c6 100644 --- a/shared/nm-utils/c-list-util.c +++ b/shared/nm-utils/c-list-util.c @@ -58,35 +58,39 @@ c_list_relink (CList *lst) /*****************************************************************************/ static CList * -_c_list_srt_split (CList *ls) +_c_list_sort (CList *ls, + CListSortCmp cmp, + const void *user_data) { - CList *ls2; + CList *ls1, *ls2; + CList head; + if (!ls->next) + return ls; + + /* split list in two halfs @ls1 and @ls2. */ + ls1 = ls; ls2 = ls; ls = ls->next; - if (!ls) - return NULL; - do { + while (ls) { ls = ls->next; if (!ls) break; ls = ls->next; ls2 = ls2->next; - } while (ls); - ls = ls2->next; - ls2->next = NULL; - return ls; -} + } + ls = ls2; + ls2 = ls->next; + ls->next = NULL; -static CList * -_c_list_srt_merge (CList *ls1, - CList *ls2, - CListSortCmp cmp, - const void *user_data) -{ - CList *ls; - CList head; + /* recurse */ + ls1 = _c_list_sort (ls1, cmp, user_data); + if (!ls2) + return ls1; + + ls2 = _c_list_sort (ls2, cmp, user_data); + /* merge */ ls = &head; for (;;) { /* while invoking the @cmp function, the list @@ -111,54 +115,6 @@ _c_list_srt_merge (CList *ls1, return head.next; } -typedef struct { - CList *ls1; - CList *ls2; - char ls1_sorted; -} SortStack; - -static CList * -_c_list_sort (CList *ls, - CListSortCmp cmp, - const void *user_data) -{ - /* reserve a huge stack-size. We need roughly log2(n) entries, hence this - * is much more we will ever need. We don't guard for stack-overflow either. */ - SortStack stack_arr[70]; - SortStack *stack_head = stack_arr; - - stack_arr[0].ls1 = ls; - - /* A simple top-down, non-recursive, stable merge-sort. - * - * Maybe natural merge-sort would be better, to do better for - * partially sorted lists. */ -_split: - stack_head[0].ls2 = _c_list_srt_split (stack_head[0].ls1); - if (stack_head[0].ls2) { - stack_head[0].ls1_sorted = 0; - stack_head[1].ls1 = stack_head[0].ls1; - stack_head++; - goto _split; - } - -_backtrack: - if (stack_head == stack_arr) - return stack_arr[0].ls1; - - stack_head--; - if (!stack_head[0].ls1_sorted) { - stack_head[0].ls1 = stack_head[1].ls1; - stack_head[0].ls1_sorted = 1; - stack_head[1].ls1 = stack_head[0].ls2; - stack_head++; - goto _split; - } - - stack_head[0].ls1 = _c_list_srt_merge (stack_head[0].ls1, stack_head[1].ls1, cmp, user_data); - goto _backtrack; -} - /** * c_list_sort_headless: * @lst: the list. diff --git a/shared/nm-utils/c-list-util.h b/shared/nm-utils/c-list-util.h index e87f1c19..199583cf 100644 --- a/shared/nm-utils/c-list-util.h +++ b/shared/nm-utils/c-list-util.h @@ -22,7 +22,7 @@ #ifndef __C_LIST_UTIL_H__ #define __C_LIST_UTIL_H__ -#include "c-list/src/c-list.h" +#include "c-list.h" /*****************************************************************************/ diff --git a/shared/nm-utils/c-list.h b/shared/nm-utils/c-list.h new file mode 100644 index 00000000..a3c4053b --- /dev/null +++ b/shared/nm-utils/c-list.h @@ -0,0 +1,397 @@ +#pragma once + +/* + * Circular Double Linked List Implementation in Standard ISO-C11 + * + * This implements a generic circular double linked list. List entries must + * embed the CList object, which provides pointers to the next and previous + * element. Insertion and removal can be done in O(1) due to the double links. + * Furthermore, the list is circular, thus allows access to front/tail in O(1) + * as well, even if you only have a single head pointer (which is not how the + * list is usually operated, though). + * + * Note that you are free to use the list implementation without a head + * pointer. However, usual operation uses a single CList object as head, which + * is itself linked in the list and as such must be identified as list head. + * This allows very simply list operations and avoids a lot of special cases. + * Most importantly, you can unlink entries without requiring a head pointer. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#include <stddef.h> + +typedef struct CList CList; + +/** + * struct CList - Entry of a circular double linked list + * @next: next entry + * @prev: previous entry + * + * Each entry in a list must embed a CList object. This object contains + * pointers to its next and previous elements, which can be freely accessed by + * the API user at any time. Note that the list is circular, and the list head + * is linked in the list as well. + * + * The list head must be initialized via C_LIST_INIT before use. There is no + * reason to initialize entry objects before linking them. However, if you need + * a boolean state that tells you whether the entry is linked or not, you should + * initialize the entry via C_LIST_INIT as well. + */ +struct CList { + CList *next; + CList *prev; +}; + +#define C_LIST_INIT(_var) { .next = &(_var), .prev = &(_var) } + +/** + * c_list_init() - initialize list entry + * @what: list entry to initialize + */ +static inline void c_list_init(CList *what) { + *what = (CList)C_LIST_INIT(*what); +} + +/** + * c_list_entry() - get parent container of list entry + * @_what: list entry, or NULL + * @_t: type of parent container + * @_m: member name of list entry in @_t + * + * If the list entry @_what is embedded into a surrounding structure, this will + * turn the list entry pointer @_what into a pointer to the parent container + * (using offsetof(3), or sometimes called container_of(3)). + * + * If @_what is NULL, this will also return NULL. + * + * Return: Pointer to parent container, or NULL. + */ +#define c_list_entry(_what, _t, _m) \ + ((_t *)(void *)(((unsigned long)(void *)(_what) ?: \ + offsetof(_t, _m)) - offsetof(_t, _m))) + +/** + * c_list_is_linked() - check whether an entry is linked + * @what: entry to check, or NULL + * + * Return: True if @what is linked in a list, false if not. + */ +static inline _Bool c_list_is_linked(const CList *what) { + return what && what->next != what; +} + +/** + * c_list_is_empty() - check whether a list is empty + * @list: list to check, or NULL + * + * Return: True if @list is empty, false if not. + */ +static inline _Bool c_list_is_empty(const CList *list) { + return !list || !c_list_is_linked(list); +} + +/** + * c_list_link_before() - link entry into list + * @where: linked list entry used as anchor + * @what: entry to link + * + * This links @what directly in front of @where. @where can either be a list + * head or any entry in the list. + * + * If @where points to the list head, this effectively links @what as new tail + * element. Hence, the macro c_list_link_tail() is an alias to this. + * + * @what is not inspected prior to being linked. Hence, it better not be linked + * into another list, or the other list will be corrupted. + */ +static inline void c_list_link_before(CList *where, CList *what) { + CList *prev = where->prev, *next = where; + + next->prev = what; + what->next = next; + what->prev = prev; + prev->next = what; +} +#define c_list_link_tail(_list, _what) c_list_link_before((_list), (_what)) + +/** + * c_list_link_after() - link entry into list + * @where: linked list entry used as anchor + * @what: entry to link + * + * This links @what directly after @where. @where can either be a list head or + * any entry in the list. + * + * If @where points to the list head, this effectively links @what as new front + * element. Hence, the macro c_list_link_front() is an alias to this. + * + * @what is not inspected prior to being linked. Hence, it better not be linked + * into another list, or the other list will be corrupted. + */ +static inline void c_list_link_after(CList *where, CList *what) { + CList *prev = where, *next = where->next; + + next->prev = what; + what->next = next; + what->prev = prev; + prev->next = what; +} +#define c_list_link_front(_list, _what) c_list_link_after((_list), (_what)) + +/** + * c_list_unlink_stale() - unlink element from list + * @what: element to unlink + * + * This unlinks @what. If @what was initialized via C_LIST_INIT(), it has no + * effect. If @what was never linked, nor initialized, behavior is undefined. + * + * Note that this does not modify @what. It just modifies the previous and next + * elements in the list to no longer reference @what. If you want to make sure + * @what is re-initialized after removal, use c_list_unlink(). + */ +static inline void c_list_unlink_stale(CList *what) { + CList *prev = what->prev, *next = what->next; + + next->prev = prev; + prev->next = next; +} + +/** + * c_list_unlink() - unlink element from list and re-initialize + * @what: element to unlink + * + * This is like c_list_unlink_stale() but re-initializes @what after removal. + */ +static inline void c_list_unlink(CList *what) { + /* condition is not needed, but avoids STOREs in fast-path */ + if (c_list_is_linked(what)) { + c_list_unlink_stale(what); + *what = (CList)C_LIST_INIT(*what); + } +} + +/** + * c_list_swap() - exchange the contents of two lists + * @list1: the list to operate on + * @list2: the list to operate on + * + * This replaces the contents of the list @list1 with the contents + * of @list2, and vice versa. + */ +static inline void c_list_swap(CList *list1, CList *list2) { + CList t; + + /* make neighbors of list1 point to list2, and vice versa */ + t = *list1; + t.next->prev = list2; + t.prev->next = list2; + t = *list2; + t.next->prev = list1; + t.prev->next = list1; + + /* swap list1 and list2 now that their neighbors were fixed up */ + t = *list1; + *list1 = *list2; + *list2 = t; +} + +/** + * c_list_splice() - splice one list into another + * @target: the list to splice into + * @source: the list to splice + * + * This removes all the entries from @source and splice them into @target. + * The order of the two lists is preserved and the source is appended + * to the end of target. + * + * On return, the source list will be empty. + */ +static inline void c_list_splice(CList *target, CList *source) { + if (!c_list_is_empty(source)) { + /* attach the front of @source to the tail of @target */ + source->next->prev = target->prev; + target->prev->next = source->next; + + /* attach the tail of @source to the front of @target */ + source->prev->next = target; + target->prev = source->prev; + + /* clear source */ + *source = (CList)C_LIST_INIT(*source); + } +} + +/** + * c_list_for_each() - loop over all list entries + * @_iter: iterator to use + * @_list: list to loop over + * + * This is a macro to use as for-loop to iterate an entire list. It is meant as + * convenience macro. Feel free to code your own loop iterator. + */ +#define c_list_for_each(_iter, _list) \ + for (_iter = (_list)->next; \ + (_iter) != (_list); \ + _iter = (_iter)->next) + + +/** + * c_list_for_each_safe() - loop over all list entries, safe for removal + * @_iter: iterator to use + * @_safe: used to store pointer to next element + * @_list: list to loop over + * + * This is a macro to use as for-loop to iterate an entire list, safe against + * removal of the current element. It is meant as convenience macro. Feel free + * to code your own loop iterator. + * + * Note that this fetches the next element prior to executing the loop body. + * This makes it safe against removal of the current entry, but it will go + * havoc if you remove other list entries. You better not modify anything but + * the current list entry. + */ +#define c_list_for_each_safe(_iter, _safe, _list) \ + for (_iter = (_list)->next, _safe = (_iter)->next; \ + (_iter) != (_list); \ + _iter = (_safe), _safe = (_safe)->next) + +/** + * c_list_for_each_entry() - loop over all list entries + * @_iter: iterator to use + * @_list: list to loop over + * @_m: member name of CList object in list type + * + * This combines c_list_for_each() with c_list_entry(), making it easy to + * iterate over a list of a specific type. + */ +#define c_list_for_each_entry(_iter, _list, _m) \ + for (_iter = c_list_entry((_list)->next, __typeof__(*_iter), _m); \ + &(_iter)->_m != (_list); \ + _iter = c_list_entry((_iter)->_m.next, __typeof__(*_iter), _m)) + +/** + * c_list_for_each_entry_safe() - loop over all list entries, safe for removal + * @_iter: iterator to use + * @_safe: used to store pointer to next element + * @_list: list to loop over + * @_m: member name of CList object in list type + * + * This combines c_list_for_each_safe() with c_list_entry(), making it easy to + * iterate over a list of a specific type. + */ +#define c_list_for_each_entry_safe(_iter, _safe, _list, _m) \ + for (_iter = c_list_entry((_list)->next, __typeof__(*_iter), _m), \ + _safe = c_list_entry((_iter)->_m.next, __typeof__(*_iter), _m); \ + &(_iter)->_m != (_list); \ + _iter = (_safe), \ + _safe = c_list_entry((_safe)->_m.next, __typeof__(*_iter), _m)) \ + +/** + * c_list_first() - return pointer to first element, or NULL if empty + * @list: list to operate on, or NULL + * + * This returns a pointer to the first element, or NULL if empty. This never + * returns a pointer to the list head. + * + * Return: Pointer to first list element, or NULL if empty. + */ +static inline CList *c_list_first(CList *list) { + return c_list_is_empty(list) ? NULL : list->next; +} + +/** + * c_list_last() - return pointer to last element, or NULL if empty + * @list: list to operate on, or NULL + * + * This returns a pointer to the last element, or NULL if empty. This never + * returns a pointer to the list head. + * + * Return: Pointer to last list element, or NULL if empty. + */ +static inline CList *c_list_last(CList *list) { + return c_list_is_empty(list) ? NULL : list->prev; +} + +/** + * c_list_first_entry() - return pointer to first entry, or NULL if empty + * @_list: list to operate on, or NULL + * @_t: type of list entries + * @_m: name of CList member in @_t + * + * This is like c_list_first(), but also applies c_list_entry() on the result. + * + * Return: Pointer to first list entry, or NULL if empty. + */ +#define c_list_first_entry(_list, _t, _m) \ + c_list_entry(c_list_first(_list), _t, _m) + +/** + * c_list_last_entry() - return pointer to last entry, or NULL if empty + * @_list: list to operate on, or NULL + * @_t: type of list entries + * @_m: name of CList member in @_t + * + * This is like c_list_last(), but also applies c_list_entry() on the result. + * + * Return: Pointer to last list entry, or NULL if empty. + */ +#define c_list_last_entry(_list, _t, _m) \ + c_list_entry(c_list_last(_list), _t, _m) + +/** + * c_list_length() - return number of linked entries, excluding the head + * @list: list to operate on + * + * Returns the number of entries in the list, excluding the list head @list. + * That is, for a list that is empty according to c_list_is_empty(), the + * returned length is 0. This requires to iterate the list and has thus O(n) + * runtime. + * + * Note that this function is meant for debugging purposes only. If you need + * the list size during normal operation, you should maintain a counter + * separately. + * + * Return: Number of items in @list. + */ +static inline unsigned long c_list_length(const CList *list) { + unsigned long n = 0; + const CList *iter; + + c_list_for_each(iter, list) + ++n; + + return n; +} + +/** + * c_list_contains() - check whether an entry is linked in a certain list + * @list: list to operate on + * @what: entry to look for + * + * This checks whether @what is linked into @list. This requires a linear + * search through the list, as such runs in O(n). Note that the list-head is + * considered part of the list, and hence this returns true if @what equals + * @list. + * + * Note that this function is meant for debugging purposes, and consistency + * checks. You should always be aware whether your objects are linked in a + * specific list. + * + * Return: True if @what is in @list, false otherwise. + */ +static inline _Bool c_list_contains(const CList *list, const CList *what) { + const CList *iter; + + c_list_for_each(iter, list) + if (what == iter) + return 1; + + return what == list; +} + +#ifdef __cplusplus +} +#endif diff --git a/shared/nm-utils/nm-c-list.h b/shared/nm-utils/nm-c-list.h deleted file mode 100644 index b43d1441..00000000 --- a/shared/nm-utils/nm-c-list.h +++ /dev/null @@ -1,81 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 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 void * -nm_c_list_elem_get (CList *lst) -{ - if (!lst) - return NULL; - return c_list_entry (lst, NMCListElem, lst)->data; -} - -static inline void -nm_c_list_elem_free (NMCListElem *elem) -{ - if (elem) { - c_list_unlink_stale (&elem->lst); - g_slice_free (NMCListElem, elem); - } -} - -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))) { - if (free_fcn) - free_fcn (elem->data); - c_list_unlink_stale (&elem->lst); - g_slice_free (NMCListElem, elem); - } -} - -#endif /* __NM_C_LIST_H__ */ diff --git a/shared/nm-utils/nm-compat.c b/shared/nm-utils/nm-compat.c deleted file mode 100644 index 90328c06..00000000 --- a/shared/nm-utils/nm-compat.c +++ /dev/null @@ -1,95 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. - */ - -#include "nm-default.h" - -#include "nm-compat.h" - -/*****************************************************************************/ - -static void -_get_keys_cb (const char *key, const char *val, gpointer user_data) -{ - GPtrArray *a = user_data; - - g_ptr_array_add (a, g_strdup (key)); -} - -static const char ** -_get_keys (NMSettingVpn *setting, - gboolean is_secrets, - guint *out_length) -{ - guint len; - const char **keys = NULL; - GPtrArray *a; - - nm_assert (NM_IS_SETTING_VPN (setting)); - - if (is_secrets) - len = nm_setting_vpn_get_num_secrets (setting); - else - len = nm_setting_vpn_get_num_data_items (setting); - - a = g_ptr_array_sized_new (len + 1); - - if (is_secrets) - nm_setting_vpn_foreach_secret (setting, _get_keys_cb, a); - else - nm_setting_vpn_foreach_data_item (setting, _get_keys_cb, a); - - len = a->len; - if (len) { - g_ptr_array_sort (a, nm_strcmp_p); - g_ptr_array_add (a, NULL); - keys = g_memdup (a->pdata, a->len * sizeof (gpointer)); - - /* we need to cache the keys *somewhere*. */ - g_object_set_qdata_full (G_OBJECT (setting), - is_secrets - ? NM_CACHED_QUARK ("libnm._nm_setting_vpn_get_secret_keys") - : NM_CACHED_QUARK ("libnm._nm_setting_vpn_get_data_keys"), - g_ptr_array_free (a, FALSE), - (GDestroyNotify) g_strfreev); - } else - g_ptr_array_free (a, TRUE); - - NM_SET_OUT (out_length, len); - return keys; -} - -const char ** -_nm_setting_vpn_get_data_keys (NMSettingVpn *setting, - guint *out_length) -{ - g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL); - - return _get_keys (setting, FALSE, out_length); -} - -const char ** -_nm_setting_vpn_get_secret_keys (NMSettingVpn *setting, - guint *out_length) -{ - g_return_val_if_fail (NM_IS_SETTING_VPN (setting), NULL); - - return _get_keys (setting, TRUE, out_length); -} diff --git a/shared/nm-utils/nm-compat.h b/shared/nm-utils/nm-compat.h deleted file mode 100644 index 52341690..00000000 --- a/shared/nm-utils/nm-compat.h +++ /dev/null @@ -1,53 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* NetworkManager -- Network link manager - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the - * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, - * Boston, MA 02110-1301 USA. - * - * (C) Copyright 2017 Red Hat, Inc. - */ - -#ifndef __NM_COMPAT_H__ -#define __NM_COMPAT_H__ - -#include "nm-setting-vpn.h" - -const char **_nm_setting_vpn_get_data_keys (NMSettingVpn *setting, - guint *out_length); - -const char **_nm_setting_vpn_get_secret_keys (NMSettingVpn *setting, - guint *out_length); - -#if NM_CHECK_VERSION (1, 11, 0) -#define nm_setting_vpn_get_data_keys(setting, out_length) \ - ({ \ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ - nm_setting_vpn_get_data_keys (setting, out_length); \ - G_GNUC_END_IGNORE_DEPRECATIONS \ - }) -#define nm_setting_vpn_get_secret_keys(setting, out_length) \ - ({ \ - G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ - nm_setting_vpn_get_secret_keys (setting, out_length); \ - G_GNUC_END_IGNORE_DEPRECATIONS \ - }) -#else -#define nm_setting_vpn_get_data_keys(setting, out_length) \ - _nm_setting_vpn_get_data_keys (setting, out_length) -#define nm_setting_vpn_get_secret_keys(setting, out_length) \ - _nm_setting_vpn_get_secret_keys (setting, out_length) -#endif - -#endif /* __NM_COMPAT_H__ */ diff --git a/shared/nm-utils/nm-dedup-multi.c b/shared/nm-utils/nm-dedup-multi.c index fc134e25..59b647ed 100644 --- a/shared/nm-utils/nm-dedup-multi.c +++ b/shared/nm-utils/nm-dedup-multi.c @@ -386,10 +386,10 @@ _add (NMDedupMultiIndex *self, head_entry->len++; if ( add_head_entry - && !g_hash_table_add (self->idx_entries, head_entry)) + && !nm_g_hash_table_add (self->idx_entries, head_entry)) nm_assert_not_reached (); - if (!g_hash_table_add (self->idx_entries, entry)) + if (!nm_g_hash_table_add (self->idx_entries, entry)) nm_assert_not_reached (); NM_SET_OUT (out_entry, entry); @@ -870,7 +870,7 @@ nm_dedup_multi_index_obj_intern (NMDedupMultiIndex *self, nm_assert (obj_new); nm_assert (!obj_new->_multi_idx); - if (!g_hash_table_add (self->idx_objs, (gpointer) obj_new)) + if (!nm_g_hash_table_add (self->idx_objs, (gpointer) obj_new)) nm_assert_not_reached (); ((NMDedupMultiObj *) obj_new)->_multi_idx = self; diff --git a/shared/nm-utils/nm-dedup-multi.h b/shared/nm-utils/nm-dedup-multi.h index 8d482de9..6286d6a4 100644 --- a/shared/nm-utils/nm-dedup-multi.h +++ b/shared/nm-utils/nm-dedup-multi.h @@ -115,7 +115,7 @@ void nm_dedup_multi_index_obj_release (NMDedupMultiIndex *self, /* 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 + * The NMDedupMultiIdxTypeClass determines it's behavior, but you can have * multiple instances (of the same class). * * For example, NMIP4Config can have idx-type to put there all IPv4 Routes. diff --git a/shared/nm-utils/nm-enum-utils.c b/shared/nm-utils/nm-enum-utils.c index b9bc6e88..70a8b415 100644 --- a/shared/nm-utils/nm-enum-utils.c +++ b/shared/nm-utils/nm-enum-utils.c @@ -64,10 +64,10 @@ _enum_is_valid_flags_nick (const char *str) char * _nm_utils_enum_to_str_full (GType type, int value, - const char *flags_separator, - const NMUtilsEnumValueInfo *value_infos) + const char *flags_separator) { - nm_auto_unref_gtypeclass GTypeClass *class = NULL; + GTypeClass *class; + char *ret; if ( flags_separator && ( !flags_separator[0] @@ -79,17 +79,12 @@ _nm_utils_enum_to_str_full (GType type, if (G_IS_ENUM_CLASS (class)) { 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 (class), value); if ( !enum_value || !_enum_is_valid_enum_nick (enum_value->value_nick)) - return g_strdup_printf ("%d", value); + ret = g_strdup_printf ("%d", value); else - return g_strdup (enum_value->value_nick); + ret = strdup (enum_value->value_nick); } else if (G_IS_FLAGS_CLASS (class)) { GFlagsValue *flags_value; GString *str = g_string_new (""); @@ -97,28 +92,6 @@ _nm_utils_enum_to_str_full (GType type, flags_separator = flags_separator ?: " "; - 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 (str->len) - g_string_append (str, flags_separator); - g_string_append (str, 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 (class), uvalue); if (str->len) @@ -132,12 +105,12 @@ _nm_utils_enum_to_str_full (GType type, g_string_append (str, flags_value->value_nick); uvalue &= ~flags_value->value; } while (uvalue); + ret = g_string_free (str, FALSE); + } else + g_return_val_if_reached (NULL); -flags_done: - return g_string_free (str, FALSE); - } - - g_return_val_if_reached (NULL); + g_type_class_unref (class); + return ret; } static const NMUtilsEnumValueInfo * diff --git a/shared/nm-utils/nm-enum-utils.h b/shared/nm-utils/nm-enum-utils.h index d6dae859..b78d9191 100644 --- a/shared/nm-utils/nm-enum-utils.h +++ b/shared/nm-utils/nm-enum-utils.h @@ -31,10 +31,7 @@ typedef struct _NMUtilsEnumValueInfo { int value; } NMUtilsEnumValueInfo; -char *_nm_utils_enum_to_str_full (GType type, - int value, - const char *sep, - const NMUtilsEnumValueInfo *value_infos); +char *_nm_utils_enum_to_str_full (GType type, int value, const char *sep); gboolean _nm_utils_enum_from_str_full (GType type, const char *str, int *out_value, diff --git a/shared/nm-utils/nm-glib.h b/shared/nm-utils/nm-glib.h index f1498dc4..599890e0 100644 --- a/shared/nm-utils/nm-glib.h +++ b/shared/nm-utils/nm-glib.h @@ -14,7 +14,7 @@ * with this program; if not, write to the Free Software Foundation, Inc., * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. * - * Copyright 2008 - 2018 Red Hat, Inc. + * Copyright 2008 - 2011 Red Hat, Inc. */ #ifndef __NM_GLIB_H__ @@ -40,6 +40,84 @@ #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 + +/* 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 {\ @@ -68,6 +146,239 @@ nm_glib_check_version (guint major, guint minor, guint micro) && 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 gchar *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 + + +#if !GLIB_CHECK_VERSION (2, 34, 0) +#define G_DEFINE_QUARK(QN, q_n) \ +GQuark \ +q_n##_quark (void) \ +{ \ + static GQuark q; \ + \ + if G_UNLIKELY (q == 0) \ + q = g_quark_from_static_string (#QN); \ + \ + return q; \ +} +#endif + + +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, + gint index_, + gpointer data) +{ + g_return_if_fail (array); + g_return_if_fail (index_ >= -1); + g_return_if_fail (index_ <= (gint) array->len); + + g_ptr_array_add (array, data); + + if (index_ != -1 && index_ != (gint) (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 gchar *filename, + GError **error) +{ + gchar *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 + #if !GLIB_CHECK_VERSION(2, 44, 0) static inline gpointer g_steal_pointer (gpointer pp) @@ -109,17 +420,70 @@ _nm_g_strv_contains (const gchar * const *strv, } #define g_strv_contains _nm_g_strv_contains +static inline GVariant * +_nm_g_variant_new_take_string (gchar *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 + #if !GLIB_CHECK_VERSION (2, 56, 0) #define g_object_ref(Obj) ((typeof(Obj)) g_object_ref (Obj)) #define g_object_ref_sink(Obj) ((typeof(Obj)) g_object_ref_sink (Obj)) #endif -#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 - #endif /* __NM_GLIB_H__ */ diff --git a/shared/nm-utils/nm-hash-utils.c b/shared/nm-utils/nm-hash-utils.c index 8d8c21ce..c563140e 100644 --- a/shared/nm-utils/nm-hash-utils.c +++ b/shared/nm-utils/nm-hash-utils.c @@ -28,8 +28,6 @@ #include "nm-shared-utils.h" #include "nm-random-utils.h" -#include "siphash24.c" - /*****************************************************************************/ #define HASH_KEY_SIZE 16u @@ -37,77 +35,33 @@ 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) +_get_hash_key (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]; - } g_arr _nm_alignas (guint64); - static gsize g_lock; + static const guint8 *volatile global_seed = NULL; const guint8 *g; - struct siphash siph_state; - uint64_t h; - guint *p; g = global_seed; - if (G_LIKELY (g != NULL)) { - nm_assert (g == g_arr.v8); - return g; - } - - if (g_once_init_enter (&g_lock)) { - - nm_utils_random_bytes (g_arr.v8, sizeof (g_arr.v8)); - - /* use siphash() of the key-size, to mangle the first guint. Otherwise, - * the first guint has only the entropy that nm_utils_random_bytes() - * generated for the first 4 bytes and relies on a good random generator. */ - siphash24_init (&siph_state, g_arr.v8); - siphash24_compress (g_arr.v8, sizeof (g_arr.v8), &siph_state); - h = siphash24_finalize (&siph_state); - p = (guint *) g_arr.v8; - if (sizeof (guint) < sizeof (h)) - *p = *p ^ ((guint) (h & 0xFFFFFFFFu)) ^ ((guint) (h >> 32)); - else - *p = *p ^ ((guint) (h & 0xFFFFFFFFu)); - - g_atomic_pointer_compare_and_exchange (&global_seed, NULL, g_arr.v8); - g_once_init_leave (&g_lock, 1); + if (G_UNLIKELY (g == NULL)) { + /* the returned hash is aligned to guin64, hence, it is save + * to use it as guint* or guint64* pointer. */ + static union { + guint8 v8[HASH_KEY_SIZE]; + } g_arr _nm_alignas (guint64); + static gsize g_lock; + + if (g_once_init_enter (&g_lock)) { + nm_utils_random_bytes (g_arr.v8, sizeof (g_arr.v8)); + g_atomic_pointer_compare_and_exchange (&global_seed, NULL, g_arr.v8); + g = g_arr.v8; + g_once_init_leave (&g_lock, 1); + } else { + g = global_seed; + nm_assert (g); + } } - nm_assert (global_seed == g_arr.v8); - return g_arr.v8; -} - -#define _get_hash_key() \ - ({ \ - const guint8 *_g; \ - \ - _g = global_seed; \ - if (G_UNLIKELY (_g == NULL)) \ - _g = _get_hash_key_init (); \ - _g; \ - }) - -guint -nm_hash_static (guint static_seed) -{ - /* note that we only xor the static_seed with the key. - * We don't use siphash24(), which would mix the bits better. - * Note that this doesn't matter, because static_seed is not - * supposed to be a value that you are hashing (for that, use - * full siphash24()). - * Instead, different callers may set a different static_seed - * so that nm_hash_str(NULL) != nm_hash_ptr(NULL). - * - * Also, ensure that we don't return zero. - */ - return ((*((const guint *) _get_hash_key ())) ^ static_seed) - ?: static_seed ?: 3679500967u; + return g; } void @@ -129,10 +83,11 @@ 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); + if (str) { + nm_hash_init (&h, 1867854211u); + nm_hash_update_str (&h, str); + } else + nm_hash_init (&h, 842995561u); return nm_hash_complete (&h); } @@ -145,13 +100,16 @@ nm_str_hash (gconstpointer str) guint nm_hash_ptr (gconstpointer ptr) { - NMHashState h; + guint 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); + h = ((const guint *) _get_hash_key ())[0]; + + if (sizeof (ptr) <= sizeof (guint)) + h = h ^ ((guint) ((uintptr_t) ptr)); + else + h = h ^ ((guint) (((guint64) (uintptr_t) ptr) >> 32)) ^ ((guint) ((uintptr_t) ptr)); + + return h ?: 2907677551u; } guint @@ -159,27 +117,3 @@ 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)); -} diff --git a/shared/nm-utils/nm-hash-utils.h b/shared/nm-utils/nm-hash-utils.h index 3bd3f652..276e1ebe 100644 --- a/shared/nm-utils/nm-hash-utils.h +++ b/shared/nm-utils/nm-hash-utils.h @@ -31,8 +31,6 @@ struct _NMHashState { typedef struct _NMHashState NMHashState; -guint nm_hash_static (guint static_seed); - void nm_hash_init (NMHashState *state, guint static_seed); static inline guint @@ -209,15 +207,4 @@ guint nm_direct_hash (gconstpointer str); guint nm_hash_str (const char *str); guint nm_str_hash (gconstpointer str); -/*****************************************************************************/ - -/* 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); - -/*****************************************************************************/ - #endif /* __NM_HASH_UTILS_H__ */ diff --git a/shared/nm-utils/nm-jansson.h b/shared/nm-utils/nm-jansson.h deleted file mode 100644 index b00c75c6..00000000 --- a/shared/nm-utils/nm-jansson.h +++ /dev/null @@ -1,46 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */ -/* - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - * Copyright 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.7 */ -#ifndef json_boolean_value -#define json_boolean_value json_is_true -#endif - -/* 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 - -#endif /* WITH_JANSON */ - -#endif /* __NM_JANSSON_H__ */ diff --git a/shared/nm-utils/nm-macros-internal.h b/shared/nm-utils/nm-macros-internal.h index cc7205a4..29678bb6 100644 --- a/shared/nm-utils/nm-macros-internal.h +++ b/shared/nm-utils/nm-macros-internal.h @@ -35,12 +35,6 @@ #define _nm_alignof(type) __alignof (type) #define _nm_alignas(type) _nm_align (_nm_alignof (type)) -#if __GNUC__ >= 7 -#define _nm_fallthrough __attribute__ ((fallthrough)) -#else -#define _nm_fallthrough -#endif - /*****************************************************************************/ #ifdef thread_local @@ -76,30 +70,6 @@ static inline int nm_close (int fd); GS_DEFINE_CLEANUP_FUNCTION(void*, _nm_auto_free_impl, free) static inline void -nm_free_secret (char *secret) -{ - if (secret) { - memset (secret, 0, strlen (secret)); - g_free (secret); - } -} - -static inline void -_nm_auto_free_secret_impl (char **v) -{ - nm_free_secret (*v); -} - -/** - * 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_impl) - -static inline void _nm_auto_unset_gvalue_impl (GValue *v) { g_value_unset (v); @@ -271,8 +241,7 @@ NM_G_ERROR_MSG (GError *error) gsize _n = 0; \ \ if (_array) { \ - _nm_unused gconstpointer _type_check_is_pointer = _array[0]; \ - \ + _nm_unused typeof (*(_array[0])) *_array_check = _array[0]; \ while (_array[_n]) \ _n++; \ } \ @@ -390,28 +359,6 @@ NM_G_ERROR_MSG (GError *error) #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); \ @@ -441,41 +388,6 @@ NM_G_ERROR_MSG (GError *error) #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 ith 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))) -#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)), \ @@ -829,32 +741,6 @@ nm_g_object_unref (gpointer obj) _changed; \ }) -#define nm_clear_pointer(pp, destroy) \ - ({ \ - typeof (*(pp)) *_pp = (pp); \ - typeof (*_pp) _p; \ - gboolean _changed = FALSE; \ - \ - if ( _pp \ - && (_p = *_pp)) { \ - _nm_unused gconstpointer _p_check_is_pointer = _p; \ - \ - *_pp = NULL; \ - /* g_clear_pointer() assigns @destroy first to a local variable, so that - * you can call "g_clear_pointer (pp, (GDestroyNotify) destroy);" without - * gcc emitting a warning. We don't do that, hence, you cannot cast - * "destroy" first. - * - * On the upside: you are not supposed to cast fcn, because the pointer - * types are preserved. If you really need a cast, you should cast @pp. - * But that is hardly ever necessary. */ \ - (destroy) (_p); \ - \ - _changed = TRUE; \ - } \ - _changed; \ - }) - /* basically, replaces * g_clear_pointer (&location, g_free) * with @@ -865,20 +751,42 @@ nm_g_object_unref (gpointer obj) * pointer or points to a const-pointer. */ #define nm_clear_g_free(pp) \ - nm_clear_pointer (pp, g_free) + ({ \ + typeof (*(pp)) *_pp = (pp); \ + typeof (**_pp) *_p; \ + gboolean _changed = FALSE; \ + \ + if ( _pp \ + && (_p = *_pp)) { \ + *_pp = NULL; \ + g_free (_p); \ + _changed = TRUE; \ + } \ + _changed; \ + }) #define nm_clear_g_object(pp) \ - nm_clear_pointer (pp, g_object_unref) + ({ \ + typeof (*(pp)) *_pp = (pp); \ + typeof (**_pp) *_p; \ + gboolean _changed = FALSE; \ + \ + if ( _pp \ + && (_p = *_pp)) { \ + nm_assert (G_IS_OBJECT (_p)); \ + *_pp = NULL; \ + g_object_unref (_p); \ + _changed = TRUE; \ + } \ + _changed; \ + }) static inline gboolean nm_clear_g_source (guint *id) { - guint v; - - if ( id - && (v = *id)) { + if (id && *id) { + g_source_remove (*id); *id = 0; - g_source_remove (v); return TRUE; } return FALSE; @@ -887,12 +795,9 @@ nm_clear_g_source (guint *id) static inline gboolean nm_clear_g_signal_handler (gpointer self, gulong *id) { - gulong v; - - if ( id - && (v = *id)) { + if (id && *id) { + g_signal_handler_disconnect (self, *id); *id = 0; - g_signal_handler_disconnect (self, v); return TRUE; } return FALSE; @@ -901,12 +806,9 @@ nm_clear_g_signal_handler (gpointer self, gulong *id) static inline gboolean nm_clear_g_variant (GVariant **variant) { - GVariant *v; - - if ( variant - && (v = *variant)) { + if (variant && *variant) { + g_variant_unref (*variant); *variant = NULL; - g_variant_unref (v); return TRUE; } return FALSE; @@ -915,13 +817,10 @@ nm_clear_g_variant (GVariant **variant) static inline gboolean nm_clear_g_cancellable (GCancellable **cancellable) { - GCancellable *v; - - if ( cancellable - && (v = *cancellable)) { + if (cancellable && *cancellable) { + g_cancellable_cancel (*cancellable); + g_object_unref (*cancellable); *cancellable = NULL; - g_cancellable_cancel (v); - g_object_unref (v); return TRUE; } return FALSE; @@ -1092,6 +991,35 @@ nm_strcmp_p (gconstpointer a, gconstpointer 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. + **/ +static inline 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); +} + +static inline 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; +} + /*****************************************************************************/ /* Taken from systemd's UNIQ_T and UNIQ macros. */ @@ -1222,28 +1150,6 @@ nm_decode_version (guint version, guint *major, guint *minor, guint *micro) _buf; \ }) -/* 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) + _name_len < 200) \ - _buf2 = nm_sprintf_bufa (NM_STRLEN (format) + _name_len, format, _name); \ - else { \ - _buf2 = g_strdup_printf (format, _name); \ - *_p_val_to_free = _buf2; \ - } \ - (const char *) _buf2; \ - }) - /*****************************************************************************/ /** @@ -1319,25 +1225,6 @@ nm_decode_version (guint version, guint *major, guint *minor, guint *micro) /*****************************************************************************/ -/** - * nm_steal_int: - * @p_val: pointer to an int type. - * - * Returns: *p_val and sets *p_val to zero the same time. - * Accepts %NULL, in which case also numeric 0 will be returned. - */ -#define nm_steal_int(p_val) \ - ({ \ - typeof (p_val) const _p_val = (p_val); \ - typeof (*_p_val) _val = 0; \ - \ - if ( _p_val \ - && (_val = *_p_val)) { \ - *_p_val = 0; \ - } \ - _val; \ - }) - static inline int nm_steal_fd (int *p_fd) { diff --git a/shared/nm-utils/nm-obj.h b/shared/nm-utils/nm-obj.h index 4edd1f3e..1a9d4868 100644 --- a/shared/nm-utils/nm-obj.h +++ b/shared/nm-utils/nm-obj.h @@ -56,7 +56,7 @@ struct _NMObjBaseClass { * 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 + * For that to work, you must properly set the GTypeClass instance (and it's * GType). * * Note that to implement a NMObjBaseClass that is *not* a GTypeClass, you wouldn't diff --git a/shared/nm-utils/nm-shared-utils.c b/shared/nm-utils/nm-shared-utils.c index 6937065c..0b343afd 100644 --- a/shared/nm-utils/nm-shared-utils.c +++ b/shared/nm-utils/nm-shared-utils.c @@ -499,56 +499,6 @@ _nm_utils_ascii_str_to_int64 (const char *str, guint base, gint64 min, gint64 ma /*****************************************************************************/ -/* 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_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; -} - -/*****************************************************************************/ - /** * nm_utils_strsplit_set: * @str: the string to split. @@ -1165,197 +1115,3 @@ nm_utils_fd_read_loop_exact (int fd, void *buf, size_t nbytes, bool do_poll) return 0; } - -NMUtilsNamedValue * -nm_utils_named_values_from_str_dict (GHashTable *hash, guint *out_len) -{ - GHashTableIter iter; - NMUtilsNamedValue *values; - guint i, len; - - if ( !hash - || !(len = g_hash_table_size (hash))) { - NM_SET_OUT (out_len, 0); - return NULL; - } - - i = 0; - values = g_new (NMUtilsNamedValue, len + 1); - g_hash_table_iter_init (&iter, hash); - while (g_hash_table_iter_next (&iter, - (gpointer *) &values[i].name, - (gpointer *) &values[i].value_ptr)) - i++; - nm_assert (i == len); - values[i].name = NULL; - values[i].value_ptr = NULL; - - if (len > 1) { - g_qsort_with_data (values, len, sizeof (values[0]), - nm_utils_named_entry_cmp_with_data, NULL); - } - - NM_SET_OUT (out_len, len); - return values; -} - -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; -} - -char ** -nm_utils_strv_make_deep_copied (const char **strv) -{ - gsize i; - - /* it takes a strv dictionary, 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; -} - -/*****************************************************************************/ - -/** - * 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 gchar *contents = NULL; - size_t length; - gs_strfreev gchar **tokens = NULL; - guint num_tokens; - gchar *p; - char state = ' '; - gint64 ppid = 0; - - start_time = 0; - contents = NULL; - - g_return_val_if_fail (pid > 0, 0); - - nm_sprintf_buf (filename, "/proc/%"G_GUINT64_FORMAT"/stat", (guint64) 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 == NULL) - goto fail; - p += 2; /* skip ') ' */ - if (p - contents >= (int) length) - goto fail; - - state = p[0]; - - tokens = g_strsplit (p, " ", 0); - - num_tokens = g_strv_length (tokens); - - if (num_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, all first @len elements in @strv must be - * non-NULL, valid strings. - * - * Ascending sort of the array @strv inplace, using plain strcmp() string - * comparison. - */ -void -_nm_utils_strv_sort (const char **strv, gssize len) -{ - gsize l; - - l = len < 0 ? (gsize) NM_PTRARRAY_LEN (strv) : (gsize) len; - - if (l <= 1) - return; - - nm_assert (l <= (gsize) G_MAXINT); - - g_qsort_with_data (strv, - l, - sizeof (const char *), - nm_strcmp_p_with_data, - NULL); -} diff --git a/shared/nm-utils/nm-shared-utils.h b/shared/nm-utils/nm-shared-utils.h index 84325bb7..d6d829cd 100644 --- a/shared/nm-utils/nm-shared-utils.h +++ b/shared/nm-utils/nm-shared-utils.h @@ -326,18 +326,12 @@ _nm_g_slice_free_fcn_define (16) /* 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) == 12) \ - || ((mem_size) == 16)); \ - switch ((mem_size)) { \ + 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 12: _fcn = _nm_g_slice_free_fcn_12; break; \ + case 12: _fcn = _nm_g_slice_free_fcn_12; break; \ case 16: _fcn = _nm_g_slice_free_fcn_16; break; \ default: g_assert_not_reached (); _fcn = NULL; break; \ } \ @@ -421,29 +415,6 @@ char *nm_utils_str_utf8safe_unescape_cp (const char *str); char *nm_utils_str_utf8safe_escape_take (char *str, NMUtilsStrUtf8SafeFlags flags); -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); -} - -/*****************************************************************************/ - -int nm_strcmp_p_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 { @@ -464,35 +435,6 @@ typedef struct { #define nm_utils_named_entry_cmp nm_strcmp_p #define nm_utils_named_entry_cmp_with_data nm_strcmp_p_with_data -NMUtilsNamedValue *nm_utils_named_values_from_str_dict (GHashTable *hash, guint *out_len); - -gpointer *nm_utils_hash_keys_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); -} - -char **nm_utils_strv_make_deep_copied (const char **strv); - -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); -} - -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) - /*****************************************************************************/ #define NM_UTILS_NS_PER_SECOND ((gint64) 1000000000) @@ -507,108 +449,4 @@ int nm_utils_fd_read_loop_exact (int fd, void *buf, size_t nbytes, bool do_poll) /*****************************************************************************/ -static inline const char * -nm_utils_dbus_normalize_object_path (const char *path) -{ - /* D-Bus does not allow an empty object path. Hence, whenever we mean NULL / no-object - * on D-Bus, it's path is actually "/". - * - * Normalize that away, and return %NULL in that case. */ - if (path && path[0] == '/' && path[1] == '\0') - return NULL; - return path; -} - -#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); - -/*****************************************************************************/ - #endif /* __NM_SHARED_UTILS_H__ */ diff --git a/shared/nm-utils/nm-test-utils.h b/shared/nm-utils/nm-test-utils.h index cc33a1ae..126546ec 100644 --- a/shared/nm-utils/nm-test-utils.h +++ b/shared/nm-utils/nm-test-utils.h @@ -21,10 +21,6 @@ #ifndef __NM_TEST_UTILS_H__ #define __NM_TEST_UTILS_H__ -#if defined(NETWORKMANAGER_COMPILATION) && !defined(NETWORKMANAGER_COMPILATION_TEST) -#error Need to mark the compilation with NETWORKMANAGER_COMPILATION_TEST. -#endif - /******************************************************************************* * HOWTO run tests. * @@ -162,14 +158,6 @@ g_assert_not_reached (); \ } G_STMT_END -#define nmtst_assert_nonnull(command) \ - ({ \ - typeof (*(command)) *_ptr = (command); \ - \ - g_assert (_ptr && (TRUE || (command))); \ - _ptr; \ - }) - #define nmtst_assert_success(success, error) \ G_STMT_START { \ g_assert_no_error (error); \ @@ -340,6 +328,8 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_ __nmtst_internal.assert_logging = !!assert_logging; + nm_g_type_init (); + is_debug = g_test_verbose (); nmtst_debug = g_getenv ("NMTST_DEBUG"); @@ -434,11 +424,6 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_ g_array_append_val (debug_messages, msg); } } else { - /* We're intentionally assigning a value to static variables - * s_tests_x and p_tests_x without using it afterwards, just - * so that valgrind doesn't complain about the leak. */ - NM_PRAGMA_WARNING_DISABLE("-Wunused-but-set-variable") - /* g_test_init() is a variadic function, so we cannot pass it * (variadic) arguments. If you need to pass additional parameters, * call nmtst_init() with argc==NULL and call g_test_init() yourself. */ @@ -512,8 +497,6 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_ s_tests = NULL; } } - - NM_PRAGMA_WARNING_REENABLE } if (test_quick_set) @@ -546,8 +529,13 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_ *out_set_logging = TRUE; #endif g_assert (success); +#if GLIB_CHECK_VERSION(2,34,0) if (__nmtst_internal.no_expect_message) g_log_set_always_fatal (G_LOG_FATAL_MASK); +#else + /* g_test_expect_message() is a NOP, so allow any messages */ + g_log_set_always_fatal (G_LOG_FATAL_MASK); +#endif } else if (__nmtst_internal.no_expect_message) { /* We have a test that would be assert_logging, but the user specified no_expect_message. * This transforms g_test_expect_message() into a NOP, but we also have to relax @@ -567,9 +555,14 @@ __nmtst_init (int *argc, char ***argv, gboolean assert_logging, const char *log_ } #endif } else { +#if GLIB_CHECK_VERSION(2,34,0) /* We were called not to set logging levels. This means, that the user * expects to assert against (all) messages. Any uncought message is fatal. */ g_log_set_always_fatal (G_LOG_LEVEL_MASK); +#else + /* g_test_expect_message() is a NOP, so allow any messages */ + g_log_set_always_fatal (G_LOG_FATAL_MASK); +#endif } if ((!__nmtst_internal.assert_logging || (__nmtst_internal.assert_logging && __nmtst_internal.no_expect_message)) && @@ -636,6 +629,7 @@ nmtst_test_quick (void) return __nmtst_internal.test_quick; } +#if GLIB_CHECK_VERSION(2,34,0) #undef g_test_expect_message #define g_test_expect_message(...) \ G_STMT_START { \ @@ -643,7 +637,9 @@ nmtst_test_quick (void) if (__nmtst_internal.assert_logging && __nmtst_internal.no_expect_message) { \ g_debug ("nmtst: assert-logging: g_test_expect_message %s", G_STRINGIFY ((__VA_ARGS__))); \ } else { \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ g_test_expect_message (__VA_ARGS__); \ + G_GNUC_END_IGNORE_DEPRECATIONS \ } \ } G_STMT_END #undef g_test_assert_expected_messages_internal @@ -657,21 +653,10 @@ nmtst_test_quick (void) if (__nmtst_internal.assert_logging && __nmtst_internal.no_expect_message) \ g_debug ("nmtst: assert-logging: g_test_assert_expected_messages(%s, %s:%d, %s)", _domain?:"", _file?:"", _line, _func?:""); \ \ + G_GNUC_BEGIN_IGNORE_DEPRECATIONS \ g_test_assert_expected_messages_internal (_domain, _file, _line, _func); \ + G_GNUC_END_IGNORE_DEPRECATIONS \ } G_STMT_END - -#define NMTST_EXPECT(domain, level, msg) g_test_expect_message (domain, level, msg) - -#if (NETWORKMANAGER_COMPILATION) & NM_NETWORKMANAGER_COMPILATION_WITH_LIBNM_UTIL -#define NMTST_EXPECT_LIBNM_U(level, msg) NMTST_EXPECT ("libnm-util", level, msg) -#define NMTST_EXPECT_LIBNM_G(level, msg) NMTST_EXPECT ("libnm-glib", level, msg) - -#define NMTST_EXPECT_LIBNM_U_CRITICAL(msg) NMTST_EXPECT_LIBNM_U (G_LOG_LEVEL_CRITICAL, msg) -#define NMTST_EXPECT_LIBNM_G_CRITICAL(msg) NMTST_EXPECT_LIBNM_G (G_LOG_LEVEL_CRITICAL, msg) -#else -#define NMTST_EXPECT_LIBNM(level, msg) NMTST_EXPECT ("libnm", level, msg) - -#define NMTST_EXPECT_LIBNM_CRITICAL(msg) NMTST_EXPECT_LIBNM (G_LOG_LEVEL_CRITICAL, msg) #endif /*****************************************************************************/ @@ -816,12 +801,6 @@ nmtst_get_rand_int (void) return g_rand_int (nmtst_get_rand ()); } -static inline gboolean -nmtst_get_rand_bool (void) -{ - return nmtst_get_rand_int () % 2; -} - static inline gpointer nmtst_rand_buf (GRand *rand, gpointer buffer, gsize buffer_length) { @@ -933,7 +912,7 @@ _nmtst_main_loop_run_timeout (gpointer user_data) } static inline gboolean -nmtst_main_loop_run (GMainLoop *loop, guint timeout_ms) +nmtst_main_loop_run (GMainLoop *loop, int timeout_ms) { GSource *source = NULL; guint id = 0; @@ -949,9 +928,6 @@ nmtst_main_loop_run (GMainLoop *loop, guint timeout_ms) g_main_loop_run (loop); - if (source && loopx) - g_source_destroy (source); - /* if the timeout was reached, return FALSE. */ return loopx != NULL; } @@ -1523,12 +1499,13 @@ _nmtst_connection_normalize (NMConnection *connection, ...) static inline NMConnection * _nmtst_connection_duplicate_and_normalize (NMConnection *connection, ...) { + gboolean was_modified; va_list args; connection = nmtst_clone_connection (connection); va_start (args, connection); - _nmtst_connection_normalize_v (connection, args); + was_modified = _nmtst_connection_normalize_v (connection, args); va_end (args); return connection; @@ -1720,7 +1697,7 @@ nmtst_assert_setting_verifies (NMSetting *setting) g_assert (success); } -#if defined(__NM_SIMPLE_CONNECTION_H__) && NM_CHECK_VERSION (1, 10, 0) && (!defined (NM_VERSION_MAX_ALLOWED) || NM_VERSION_MAX_ALLOWED >= NM_VERSION_1_10) +#if defined(__NM_SIMPLE_CONNECTION_H__) static inline void _nmtst_assert_connection_has_settings (NMConnection *connection, gboolean has_at_least, gboolean has_at_most, ...) { @@ -1738,7 +1715,7 @@ _nmtst_assert_connection_has_settings (NMConnection *connection, gboolean has_at va_start (ap, has_at_most); while ((name = va_arg (ap, const char *))) { - if (!g_hash_table_add (names, (gpointer) name)) + if (!nm_g_hash_table_add (names, (gpointer) name)) g_assert_not_reached (); g_ptr_array_add (names_arr, (gpointer) name); } @@ -1774,7 +1751,8 @@ _nmtst_assert_connection_has_settings (NMConnection *connection, gboolean has_at #define nmtst_assert_connection_has_settings(connection, ...) _nmtst_assert_connection_has_settings ((connection), TRUE, TRUE, __VA_ARGS__, NULL) #define nmtst_assert_connection_has_settings_at_least(connection, ...) _nmtst_assert_connection_has_settings ((connection), TRUE, FALSE, __VA_ARGS__, NULL) #define nmtst_assert_connection_has_settings_at_most(connection, ...) _nmtst_assert_connection_has_settings ((connection), FALSE, TRUE, __VA_ARGS__, NULL) -#endif + +#endif /* __NM_SIMPLE_CONNECTION_H__ */ static inline void nmtst_assert_setting_verify_fails (NMSetting *setting, diff --git a/shared/nm-utils/siphash24.c b/shared/nm-utils/siphash24.c index 8e59afb2..3a5a635d 100644 --- a/shared/nm-utils/siphash24.c +++ b/shared/nm-utils/siphash24.c @@ -19,8 +19,7 @@ #include "nm-default.h" -#define assert(cond) nm_assert (cond) -#define _fallthrough_ _nm_fallthrough +#define assert(cond) nm_assert (cond) #include <stdio.h> @@ -131,25 +130,25 @@ void siphash24_compress(const void *_in, size_t inlen, struct siphash *state) { switch (left) { case 7: state->padding |= ((uint64_t) in[6]) << 48; - _fallthrough_; + /* fall through */ case 6: state->padding |= ((uint64_t) in[5]) << 40; - _fallthrough_; + /* fall through */ case 5: state->padding |= ((uint64_t) in[4]) << 32; - _fallthrough_; + /* fall through */ case 4: state->padding |= ((uint64_t) in[3]) << 24; - _fallthrough_; + /* fall through */ case 3: state->padding |= ((uint64_t) in[2]) << 16; - _fallthrough_; + /* fall through */ case 2: state->padding |= ((uint64_t) in[1]) << 8; - _fallthrough_; + /* fall through */ case 1: state->padding |= ((uint64_t) in[0]); - _fallthrough_; + /* fall through */ case 0: break; } diff --git a/shared/nm-utils/unaligned.h b/shared/nm-utils/unaligned.h index 73302b42..7c847a3c 100644 --- a/shared/nm-utils/unaligned.h +++ b/shared/nm-utils/unaligned.h @@ -1,4 +1,3 @@ -/* SPDX-License-Identifier: LGPL-2.1+ */ #pragma once /*** @@ -26,77 +25,89 @@ /* BE */ static inline uint16_t unaligned_read_be16(const void *_u) { - const struct __attribute__((packed, may_alias)) { uint16_t x; } *u = _u; + const uint8_t *u = _u; - return be16toh(u->x); + return (((uint16_t) u[0]) << 8) | + ((uint16_t) u[1]); } static inline uint32_t unaligned_read_be32(const void *_u) { - const struct __attribute__((packed, may_alias)) { uint32_t x; } *u = _u; + const uint8_t *u = _u; - return be32toh(u->x); + return (((uint32_t) unaligned_read_be16(u)) << 16) | + ((uint32_t) unaligned_read_be16(u + 2)); } static inline uint64_t unaligned_read_be64(const void *_u) { - const struct __attribute__((packed, may_alias)) { uint64_t x; } *u = _u; + const uint8_t *u = _u; - return be64toh(u->x); + return (((uint64_t) unaligned_read_be32(u)) << 32) | + ((uint64_t) unaligned_read_be32(u + 4)); } static inline void unaligned_write_be16(void *_u, uint16_t a) { - struct __attribute__((packed, may_alias)) { uint16_t x; } *u = _u; + uint8_t *u = _u; - u->x = be16toh(a); + u[0] = (uint8_t) (a >> 8); + u[1] = (uint8_t) a; } static inline void unaligned_write_be32(void *_u, uint32_t a) { - struct __attribute__((packed, may_alias)) { uint32_t x; } *u = _u; + uint8_t *u = _u; - u->x = be32toh(a); + unaligned_write_be16(u, (uint16_t) (a >> 16)); + unaligned_write_be16(u + 2, (uint16_t) a); } static inline void unaligned_write_be64(void *_u, uint64_t a) { - struct __attribute__((packed, may_alias)) { uint64_t x; } *u = _u; + uint8_t *u = _u; - u->x = be64toh(a); + unaligned_write_be32(u, (uint32_t) (a >> 32)); + unaligned_write_be32(u + 4, (uint32_t) a); } /* LE */ static inline uint16_t unaligned_read_le16(const void *_u) { - const struct __attribute__((packed, may_alias)) { uint16_t x; } *u = _u; + const uint8_t *u = _u; - return le16toh(u->x); + return (((uint16_t) u[1]) << 8) | + ((uint16_t) u[0]); } static inline uint32_t unaligned_read_le32(const void *_u) { - const struct __attribute__((packed, may_alias)) { uint32_t x; } *u = _u; + const uint8_t *u = _u; - return le32toh(u->x); + return (((uint32_t) unaligned_read_le16(u + 2)) << 16) | + ((uint32_t) unaligned_read_le16(u)); } static inline uint64_t unaligned_read_le64(const void *_u) { - const struct __attribute__((packed, may_alias)) { uint64_t x; } *u = _u; + const uint8_t *u = _u; - return le64toh(u->x); + return (((uint64_t) unaligned_read_le32(u + 4)) << 32) | + ((uint64_t) unaligned_read_le32(u)); } static inline void unaligned_write_le16(void *_u, uint16_t a) { - struct __attribute__((packed, may_alias)) { uint16_t x; } *u = _u; + uint8_t *u = _u; - u->x = le16toh(a); + u[0] = (uint8_t) a; + u[1] = (uint8_t) (a >> 8); } static inline void unaligned_write_le32(void *_u, uint32_t a) { - struct __attribute__((packed, may_alias)) { uint32_t x; } *u = _u; + uint8_t *u = _u; - u->x = le32toh(a); + unaligned_write_le16(u, (uint16_t) a); + unaligned_write_le16(u + 2, (uint16_t) (a >> 16)); } static inline void unaligned_write_le64(void *_u, uint64_t a) { - struct __attribute__((packed, may_alias)) { uint64_t x; } *u = _u; + uint8_t *u = _u; - u->x = le64toh(a); + unaligned_write_le32(u, (uint32_t) a); + unaligned_write_le32(u + 4, (uint32_t) (a >> 32)); } #if __BYTE_ORDER == __BIG_ENDIAN |