Commit graph

142 commits

Author SHA1 Message Date
Thomas Haller
32c81a29d5
shared: also reimplement g_atomic_pointer_set() macro
It's not strictly necessary, because contrary to g_atomic_pointer_get()
and g_atomic_pointer_compare_and_exchange(), glib's variant for the
setter is mostly fine.

Still, reimplement it, because we use typeof() eagerly and can thus add
more static checks than glib.

(cherry picked from commit 7c60e984b6)
(cherry picked from commit 6ded463f36)
(cherry picked from commit 976b358be6)
(cherry picked from commit 296a770a85)
2021-06-10 16:59:53 +02:00
Thomas Haller
17c83d09eb
shared: add a compat implementation for g_atomic_pointer_get()
With glib2-2.67.0-1.fc34.x86_64.rpm, clang-11.0.0-2.fc34.x86_64.rpm, we
get a failure for g_atomic_pointer_get():

    ../shared/nm-glib-aux/nm-hash-utils.c:38:9: error: passing 'typeof (*(&global_seed)) *' (aka 'const unsigned char *volatile *') to parameter of type 'const guint8 **' (aka 'const unsigned char **') discards qualifiers [-Werror,-Wincompatible-pointer-types-discards-qualifiers]
        g = g_atomic_pointer_get(&global_seed);
            ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /usr/include/glib-2.0/glib/gatomic.h:112:38: note: expanded from macro 'g_atomic_pointer_get'
        __atomic_load (gapg_temp_atomic, &gapg_temp_newval, __ATOMIC_SEQ_CST); \
                                         ^~~~~~~~~~~~~~~~~
    ../shared/nm-glib-aux/nm-hash-utils.c:109:32: error: passing 'typeof (*(&global_seed)) *' (aka 'const unsigned char *volatile *') to parameter of type 'const guint8 **' (aka 'const unsigned char **') discards qualifiers [-Werror,-Wincompatible-pointer-types-discards-qualifiers]
        return ((*((const guint *) _get_hash_key())) ^ static_seed) ?: 3679500967u;
                                   ^~~~~~~~~~~~~~~
    ../shared/nm-glib-aux/nm-hash-utils.c:84:14: note: expanded from macro '_get_hash_key'
            _g = g_atomic_pointer_get(&global_seed); \
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /usr/include/glib-2.0/glib/gatomic.h:112:38: note: expanded from macro 'g_atomic_pointer_get'
        __atomic_load (gapg_temp_atomic, &gapg_temp_newval, __ATOMIC_SEQ_CST); \
                                         ^~~~~~~~~~~~~~~~~
    ../shared/nm-glib-aux/nm-hash-utils.c:123:9: error: passing 'typeof (*(&global_seed)) *' (aka 'const unsigned char *volatile *') to parameter of type 'const guint8 **' (aka 'const unsigned char **') discards qualifiers [-Werror,-Wincompatible-pointer-types-discards-qualifiers]
        g = _get_hash_key();
            ^~~~~~~~~~~~~~~
    ../shared/nm-glib-aux/nm-hash-utils.c:84:14: note: expanded from macro '_get_hash_key'
            _g = g_atomic_pointer_get(&global_seed); \
                 ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    /usr/include/glib-2.0/glib/gatomic.h:112:38: note: expanded from macro 'g_atomic_pointer_get'
        __atomic_load (gapg_temp_atomic, &gapg_temp_newval, __ATOMIC_SEQ_CST); \
                                         ^~~~~~~~~~~~~~~~~

(cherry picked from commit 5e57ea37f0)
(cherry picked from commit 1e4cfba6dc)
(cherry picked from commit 446cac18cc)
(cherry picked from commit af4d01b51b)
2021-06-10 16:59:52 +02:00
Thomas Haller
e333a28b97
glib: always re-implement g_steal_pointer()
g_steal_pointer() is marked as GLIB_AVAILABLE_STATIC_INLINE_IN_2_44,
that means we get a deprecated warning. Avoid that. We anyway
re-implement the macro so that we can use it before 2.44 and so
that it always does the typeof() cast.

(cherry picked from commit edfe9fa9a2)
(cherry picked from commit 6936a0613c)
2020-09-08 15:17:27 +02:00
Antonio Cardace
5913e4cee9
initrd: fix memory leak
Signed-off-by: Antonio Cardace <acardace@redhat.com>
Fixes: 9f9609555d ('initrd: add configuration generator')
(cherry picked from commit d5c05d07c7)
(cherry picked from commit bba54613eb)
(cherry picked from commit 67bb9896b3)
2020-09-04 13:58:01 +02:00
Thomas Haller
ff8ba801f3
shared: add nm_utils_buf_utf8safe_escape_cp() helper
(cherry picked from commit 393bc8c8f6)
(cherry picked from commit 10b0260d19)
2020-08-28 12:28:05 +02:00
Thomas Haller
eec2740d71 all: use wrappers for g_ascii_strtoll(), g_ascii_strtoull(), g_ascii_strtod()
Sometimes these function may set errno to unexpected values like EAGAIN.
This causes confusion. Avoid that by using our own wrappers that retry
in that case. For example, in rhbz#1797915 we have failures like:

    errno = 0;
    v = g_ascii_strtoll ("10", 0, &end);
    if (errno != 0)
        g_assert_not_reached ();

as g_ascii_strtoll() would return 10, but also set errno to EAGAIN.

Work around that by using wrapper functions that retry. This certainly
should be fixed in glib (or glibc), but the issues are severe enough to
warrant a workaround.

Note that our workarounds are very defensive. We only retry 2 times, if
we get an unexpected errno value. This is in the hope to recover from
a spurious EAGAIN. It won't recover from other errors.

https://bugzilla.redhat.com/show_bug.cgi?id=1797915
(cherry picked from commit 7e49f4a199)
2020-04-02 07:45:39 +02:00
Thomas Haller
95565bef77 shared: add nm_g_ascii_strtoull() to workaround bug
(cherry picked from commit 3b58c5fef4)
2020-04-02 07:45:37 +02:00
Thomas Haller
f8cae1ed18 shared: add nm_g_ascii_strtod() to workaround bug
(cherry picked from commit 35a9f632a8)
2020-04-02 07:45:36 +02:00
Thomas Haller
6836679878 shared: add nm_g_ascii_strtoll() to workaround bug
(cherry picked from commit f4446e34c6)
2020-04-02 07:45:22 +02:00
Thomas Haller
a5c465848a shared: add NM_SWAP() macro
(cherry picked from commit cec06138f1)
2020-03-26 22:22:55 +01:00
Thomas Haller
82237a3344 shared/trivial: add code comment to nm_utils_ifname_valid_kernel()
(cherry picked from commit eb74d5f65f)
2020-02-18 13:28:49 +01:00
Thomas Haller
9bbb021b4f shared: check for valid UTF-8 in nm_utils_ifname_valid()
The interface name might come from the command line or from a filename
(like during nm_vpn_wireguard_import()). It's not clear that this
is valid UTF-8. Asserting against that requires the caller to ensure
that the encoding is valid. That is cumbersome, especially since we anyway
check. Just report a regular error.

(cherry picked from commit 82fb8b00b4)
2020-02-18 13:28:48 +01:00
Antonio Cardace
88d0d80d09 nm-shared-utils: relax ovs ifname check to accept any (non-space) ASCII printable char
quoting 'man ovs-vswitchd.conf.db':
"The name must be alphanumeric and must not contain forward or backward
slashes."

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.

https://bugzilla.redhat.com/show_bug.cgi?id=1788432

Fixes: e7d72a14f6 ('libnm-core: use different ifname validation function for OVS bridges, ports and interfaces')
(cherry picked from commit ed5a647ad1)
2020-02-18 13:12:59 +01:00
Thomas Haller
b1dcfcb7b7 shared: fix returning out_len from nm_utils_hash_values_to_array()
The only affected caller is nm_modem_manager_get_modems(), which
is used by NMDeviceBt for DUN connections. This is rather bad.

Fixes: 4154d9618c ('bluetooth: refactor BlueZ handling and let NMBluezManager cache ObjectManager data')
Fixes: e688e70b37 ('shared: add nm_utils_hash_values_to_array() helper')
(cherry picked from commit 037507f790)
2020-02-17 17:55:52 +01:00
Antonio Cardace
2cf568bd8f nm-shared-utils: add nm_utils_ifname_valid*() to shared utils
Move the body of nm_utils_is_valid_iface_name() to
nm_utils_ifname_valid_kernel() so that it's shared between NM and
clients.

(cherry picked from commit 550f538564)
2020-02-17 17:26:47 +01:00
Beniamino Galvani
047ab7f4af shared: redefine G_SOURCE_FUNC
G_SOURCE_FUNC has attribute GLIB_AVAILABLE_MACRO_IN_2_58, which means
that the compiler will emit a warning when GLIB_VERSION_MAX_ALLOWED <
GLIB_VERSION_2_58. We currently define GLIB_VERSION_MAX_ALLOWED as
GLIB_VERSION_2_40. Redefine the macro to fix the following build error
when using glib >= 2.63.5 (the version in which the attribute was
added):

  CC       shared/nm-glib-aux/libnm_glib_aux_la-nm-shared-utils.lo
 shared/nm-glib-aux/nm-shared-utils.c: In function ‘nm_g_unix_fd_source_new’:
 shared/nm-glib-aux/nm-shared-utils.c:3679:13: error: Not available before  [-Werror]
  3679 |  g_source_set_callback (source, G_SOURCE_FUNC (source_func), user_data, destroy_notify);

Fixes: 9c5741ccd2 ('shared/nm-glib: add compat implementation for G_SOURCE_FUNC()')
(cherry picked from commit 7f801685b2)
2020-02-05 14:33:11 +01:00
Thomas Haller
0d59038583 shared: add nm_source_func_unref_gobject() helper
(cherry picked from commit 1afabd5ffd)
2020-01-16 12:50:14 +01:00
Beniamino Galvani
9e5bb9d62f shared: add missing va_end() to _nm_dbus_error_is()
Found by covscan:

   NetworkManager-1.22.0/shared/nm-glib-aux/nm-dbus-aux.c:361:
   missing_va_end: va_end was not called for "ap".

Fixes: ce36494c0a ('shared: add nm_dbus_error_is() helper')
(cherry picked from commit 0de4fd6ebc)
2019-12-18 10:04:34 +01:00
Thomas Haller
e20c8d8ad5 shared: implement _LOGx() macros using log levels that are themself defines
"nm-glib-aux/nm-logging-fwd.h" provides macros like _LOGD() to be reused
by various parts which implement logging (by defining _NMLOG() accordingly).

libnm also has logging, however it uses different logging levels
aside LOGD_DEBUG.

Instead, implement _LOGD() using a define _LOGL_DEBUG, so that libnm can
redefine thos _LOGL_DEBUG defines and use the _LOGD() macro.

(cherry picked from commit 1b00fd2fd2)
2019-12-16 18:54:12 +01:00
Thomas Haller
452f14216a shared: add nm_dbus_error_is() helper
(cherry picked from commit ce36494c0a)
2019-12-16 18:54:12 +01:00
Thomas Haller
d8cc6af058 shared/glib: reimplement g_atomic_pointer_compare_and_exchange() macro
With glib 2.63.2 and clang 9.0.0 (Fedora 32) we get compile errors:

  ../clients/cloud-setup/nmcs-provider-ec2.c:51:8: error: incompatible pointer types passing 'typeof ((((void *)0))) *' (aka 'void **') to parameter of type 'const char **' [-Werror,-Wincompatible-pointer-types]
                  if (!g_atomic_pointer_compare_and_exchange (&base_cached, NULL, base))
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  /usr/include/glib-2.0/glib/gatomic.h:192:44: note: expanded from macro 'g_atomic_pointer_compare_and_exchange'
      __atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \
                                             ^~~~~~~~~~~~~~
  ../src/devices/bluetooth/nm-bluez-manager.c:2836:2: error: incompatible pointer types passing 'typeof ((((void *)0))) *' (aka 'void **') to parameter of type 'const NMBtVTableNetworkServer **' (aka 'const struct _NMBtVTableNetworkServer **') [-Werror,-Wincompatible-pointer-types]
          g_atomic_pointer_compare_and_exchange (&nm_bt_vtable_network_server, NULL, &priv->vtable_network_server);
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  /usr/include/glib-2.0/glib/gatomic.h:192:44: note: expanded from macro 'g_atomic_pointer_compare_and_exchange'
      __atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \
                                             ^~~~~~~~~~~~~~
  ../src/devices/bluetooth/nm-bluez-manager.c:2853:2: error: passing 'typeof ((&priv->vtable_network_server)) *' (aka 'struct _NMBtVTableNetworkServer **') to parameter of type 'const NMBtVTableNetworkServer **' (aka 'const struct _NMBtVTableNetworkServer **') discards qualifiers in nested pointer types [-Werror,-Wincompatible-pointer-types-discards-qualifiers]
          g_atomic_pointer_compare_and_exchange (&nm_bt_vtable_network_server, &priv->vtable_network_server, NULL);
          ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  /usr/include/glib-2.0/glib/gatomic.h:192:44: note: expanded from macro 'g_atomic_pointer_compare_and_exchange'
      __atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \
                                             ^~~~~~~~~~~~~~
  ../src/devices/nm-device.c:8857:8: error: incompatible pointer types passing 'typeof ((((void *)0))) *' (aka 'void **') to parameter of type 'GBytes **' (aka 'struct _GBytes **') [-Werror,-Wincompatible-pointer-types]
                  if (!g_atomic_pointer_compare_and_exchange (&global_duid, NULL, p)) {
                       ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
  /usr/include/glib-2.0/glib/gatomic.h:192:44: note: expanded from macro 'g_atomic_pointer_compare_and_exchange'
      __atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST) ? TRUE : FALSE; \
                                             ^~~~~~~~~~~~~~

The issue happens because glib passes the "atomic" argument to

  __atomic_compare_exchange_n ((atomic), &gapcae_oldval, (newval), FALSE, __ATOMIC_SEQ_CST, __ATOMIC_SEQ_CST)

without cast, and clang 9 seems to be picky about const pointers.
Add our own version of the macro that does better casts while also having
better compile time checks for valid arguments.

(cherry picked from commit f5b0713651)
2019-12-13 13:48:00 +01:00
Thomas Haller
f17bb012fe shared: add nm_utils_parse_inaddr_bin_full() to support legacy IPv4 formats as inet_aton()
inet_aton() also supports IPv4 addresses in octal (with a leading '0')
or where not all 4 digits of the address are present.

Add nm_utils_parse_inaddr_bin_full() to optionally fallback to
parse the address with inet_aton().

Note taht inet_aton() also supports all crazy formats, including
ignoring trailing garbage after a whitespace. We don't want to accept
that in general.

Note that even in legacy format we:

  - accept everything that inet_pton() would accept

  - additionally, we also accept some forms which inet_aton() would
    accept, but not all.

That means, the legacy format that we accept is a superset of
inet_pton() and a subset of inet_aton(). Which is desirable.

(cherry picked from commit 8fbf67d138)
2019-12-05 13:12:04 +01:00
Thomas Haller
fc19cbb589 shared: add nm_utils_addr_family_from_size() helper
(cherry picked from commit 06a976358b)
2019-12-05 13:12:04 +01:00
Thomas Haller
2b6f5a305c shared: add nm_utils_error_new() and nm_utils_error_new_cancelled() helper 2019-11-28 19:20:33 +01:00
Thomas Haller
40012e2aa8 shared: move log level info from core to "nm-logging-base.h"
We have our NM specific logging and log levels. Maybe we should
not have that, and instead only rely on syslog (like systemd)
or glog(). Anyway, currently we have one way and it makes sense
that this is also used outside from "src".

Move the helper function to parse log levels from string to
"nm-logging-base.h" so that we can use the same logging levels
outside of core.

This moves code that is currently GPL2+ licensed to
LGPL2.1+. However as far as I see, this code was entirely written
by Red Hat employees who would not object with this change. Also,
it's as obvious and trivial as it gets.
2019-11-28 19:20:33 +01:00
Thomas Haller
32d3a3f7ef shared: cleanup include guard for nm-logging-fwd.h 2019-11-28 19:20:33 +01:00
Thomas Haller
41d81e6893 shared/logging: add "nm-logging-base.h"
We have "nm-logging-fwd.h", which (as the name implies) is header-only.
Add instead a "nm-logging-base.c", which also contains implementation for
logging functions that are not only useful under "src/nm-logging.c"
2019-11-28 19:20:33 +01:00
Thomas Haller
4fad8c7c64 shared: add nm_utils_g_main_context_create_integrate_source() for integrating a GMainContext in another
We will rework NMClient entirely. Then, the synchronous initialization will also use
the asynchronous code paths. The difference will be that with synchronous initialization,
all D-Bus interaction will be done with an internal GMainContext as current thread default,
and that internal context will run until initialization completes.

Note that even after initialization completes, it cannot be swapped back to the user's
(outer) GMainContext. That is because contexts are essentially the queue for our
D-Bus events, and we cannot swap from one queue to the other in a race
free manner (or a full resync). In other words, the two contexts are not in sync,
so after using the internal context NMClient needs to stick to that (at least, until
the name owner gets lost, which gives an opportunity to resync and switch back to the
user's main context).

We thus need to hook the internal (inner) GMainContext with the user's (outer) context,
so when the user iterates the outer context, events on the inner context get dispatched.

Add nm_utils_g_main_context_create_integrate_source() to create such a GSource for
integrating two contexts.

Note that the use-case here is limited: the integrated, inner main context must
not be explicitly iterated except from being dispatched by the integrating
source. Otherwise, you'd get recursive runs, possible deadlocks and general
ugliness. NMClient must show restrain how to use the inner context while it is
integrated.
2019-11-25 12:58:33 +01:00
Thomas Haller
45c9f3c39b shared: make NM_STRUCT_OFFSET_ENSURE_TYPE() work with arrays
Some compilers don't convert arrays as _Generic() type selectors to
their pointer type. That means, for those compilers the generic type
would be an array and not a pointer. Work around that by adding zero
to the pointer/array argument.

Also, I cannot get this to work with "clang-3.4.2-9.el7". Disable it
for that compiler. The value of the generic check is anyway that it only
needs to work with some compiler combinations. That will trigger a
compilation failure and we can fix the implementation also for compilers
that don't support the macro.

See-also: http://www.open-std.org/jtc1/sc22/wg14/www/docs/n1930.htm
2019-11-25 12:58:33 +01:00
Thomas Haller
b8b8ef7600 shared: mark _notify() function as "_nm_unused"
There are two macros: NM_GOBJECT_PROPERTIES_DEFINE_BASE() and
NM_GOBJECT_PROPERTIES_DEFINE(). The former just defines the
property enums and the obj_properties array. The latter also
defines the functions _notify() and _nm_gobject_notify_together_impl().

That means, depending on whether you actually use _notify(), you have
to choose one of the macros. I think that is unnecessarily cumbersome.
Let's mark the function as _nm_unused so that the compiler doesn't
complain about the unused function. I don't think it's a problem
to use NM_GOBJECT_PROPERTIES_DEFINE() even if you don't actually use
_notify().
2019-11-25 12:58:33 +01:00
Thomas Haller
58811e019d shared: add nm_auto_unref_gmaincontext macro 2019-11-25 12:58:33 +01:00
Thomas Haller
bc9baf0fd5 shared: add nm_pint_hash()/nm_pint_equals() utils 2019-11-25 12:58:33 +01:00
Thomas Haller
033c2b82c2 core: move _LOG*() macros to "shared/nm-glib-aux/nm-logging-fwd.h"
We preferably should use our convenience macros like _LOGD().
Since those macros expand to _NMLOG() (which needs to be defined
separately), we can move it to "nm-logging-fwd.h" and reuse.
2019-11-22 15:32:52 +01:00
Thomas Haller
ec868916c8 shared: move nm_utils_ip._address_clear_host_address() helpers to shared 2019-11-22 15:32:52 +01:00
Thomas Haller
2ef5014f98 shared: add nm_clear_g_source_inst()
glib really likes the numeric source IDs. That is, g_idle_add(), g_timeout_add(),
etc. return those IDs, that can then be destroyed with g_remove_source() (or
nm_clear_g_source()).

I think these numeric IDs are really not great.

- API like g_idle_add() and g_remove_source() only works with the g_main_context_get_default()
  instance. That means, you cannot use this API for any other contexts. If you'd insist on using
  numeric IDs, you'd need to call g_main_context_find_source_by_id() on the right context
  first (but you'd also have to track the context alongside the ID).
- g_remove_source() requires first a call to g_main_context_find_source_by_id(). This involves
  taking a mutex and doing an extra hash lookup.

Instead, it often seems preferable to use the GSource instance directly. It works
with any context, it can be referenced and unreferenced, and it can be destroyed, and
avoids the overhead of g_main_context_find_source_by_id().

The only downside really is that keeping a GSource pointer takes one pointer size, while
the guint source ID is usually only 4 bytes.

Anyway, I think we should deal more with GSource instances directly. Hence, add this
convenience macro, that works like nm_clear_g_source().
2019-11-22 15:32:52 +01:00
Thomas Haller
c40ff42ae6 shared: add nm_g_*_source_new() and nm_g_source_attach() helpers
Small utilities to make is more convenient to create and attach GSource
instances.
2019-11-22 15:32:52 +01:00
Thomas Haller
9c5741ccd2 shared/nm-glib: add compat implementation for G_SOURCE_FUNC()
G_SOURCE_FUNC() was only added in glib 2.58.
2019-11-22 15:32:52 +01:00
Beniamino Galvani
97a8785148 nettools: enable logging 2019-11-22 10:24:49 +01:00
Thomas Haller
42026f9fb3 shared: add nm_utils_monotonic_timestamp_from_boottime() util
We sometimes have a CLOCK_BOOTTIME and need to convert it
to NetworkManager's monotonic timestamps.
2019-11-20 14:54:39 +01:00
Thomas Haller
afa54fdfd5 shared: add nm_g_main_context_push_thread_default*() and nm_auto helper 2019-11-07 11:34:36 +01:00
Thomas Haller
3b95905ae3 shared: add nm_auto_destroy_and_unref_gsource macro 2019-11-07 11:34:36 +01:00
Thomas Haller
01335ecec6 shared: assert in nm_ref_string_unref() for valid NMRefString instance 2019-11-07 11:34:36 +01:00
Thomas Haller
15fe8ad851 shared: add nm_dbus_path_not_empty() helper 2019-11-07 11:34:36 +01:00
Thomas Haller
9b2d5742c1 shared: add nm_g_set_error_take*() util 2019-11-07 11:34:36 +01:00
Thomas Haller
d21439eaa0 shared: add nm_ppdirect_hash()/nm_ppdirect_equal() helpers
Useful for hashing pointers to a pointer to a pointer, and
compare the resulting pointer directly. This will be actually
used.
2019-11-07 11:34:36 +01:00
Thomas Haller
86352ceaf8 shared: add NM_STRUCT_OFFSET_ENSURE_TYPE() helper 2019-11-07 11:34:36 +01:00
Thomas Haller
1c4acc89f1 shared: add NM_IS_REF_STRING() helper 2019-10-27 14:30:51 +01:00
Thomas Haller
a75dccad78 shared: add @deep_copied argument to nm_utils_strv_dup() 2019-10-27 14:30:51 +01:00
Thomas Haller
69de5ee4e9 shared: move nm_utils_parse_debug_string() from core to shared 2019-10-18 22:09:18 +02:00
Thomas Haller
308beb85fe shared: add nm_c_list_for_each_entry_prev() helper macro
It's non-trivial to get this right. Add the macro for iterating the list
in reverse.
2019-10-18 22:09:18 +02:00