Commit graph

317 commits

Author SHA1 Message Date
Beniamino Galvani
e896488e1e shared: add nm_auto_decref_json
(cherry picked from commit 5efa9ff348)
2019-02-17 20:44:41 +01:00
Beniamino Galvani
67994f0e6f udev: remove unneeded NULL checks
self->monitor cannot be NULL there.

(cherry picked from commit 3e4b30b2b1)
2018-12-12 14:54:23 +01:00
Beniamino Galvani
19b7a4c167 udev: increase receive buffer size
With the default 128KiB buffer size it is easy to lose events. For
example when 64 interfaces appear at the same time, we lose events for
the last 16. Increase the buffer size to 4MiB.

https://bugzilla.redhat.com/show_bug.cgi?id=1651578
(cherry picked from commit 5780a2893b)
2018-12-12 14:54:22 +01:00
Thomas Haller
0a4bbb18fe shared: expose siphash24() related functionality in nm-hash-utils.h
CSiphash is a first class citizen, it's fine to use everwhere where we
need it.

NMHash wraps CSiphash and provides three things:

1) Convenience macros that make hashing nicer to use.

2) it uses a randomly generated, per-run hash seed, that can be combined
   with a guint static seed.

3) it's a general API for hashing data. It nowhere promises that it
   actually uses siphash24, although currently it does everywhere.
   NMHash is not (officially) siphash24.

Add API nm_hash_siphash42_init() and nm_hash_siphash42() to "nm-hash-utils.h",
that exposes (2) for use with regular CSiphash. You of course no longer
get the convenice macros (1) but you get plain siphash24 (which
NMHash does not give (3)).

While at it, also add a nm_hash_complete_u64(). Usually, for hasing we
want guint types. But we don't need to hide the fact, that the
underlying value is first uint64. Expose it.

(cherry picked from commit db791db4e1)
2018-12-12 14:40:55 +01:00
Thomas Haller
d0f516a2bd shared: add nm_utils_error_is_notfound() helper
Inspired by bolt's bolt_err_notfound() in "bolt-error.c".

(cherry picked from commit b7fc328a66)
2018-12-12 11:47:49 +01:00
Thomas Haller
7c07c59aa3 shared: add NM_MAX_WITH_CMP() macro
(cherry picked from commit e0191d4201)
2018-12-11 09:31:38 +01:00
Thomas Haller
b4626ba2e7 shared: add nm_utils_checksum_get_digest*() helper
The GChecksum API is cumbersome to use.

For example, g_checksum_get_digest() requires a length input/output
argument. At the same time, GChecksum does not allow you to query its
checksum-type nor the desired digest-length. When you have a GChecksum
at hand, you must always know the digest-length you are going to use.
So, the length parameter is only good for asserting.

Add a macro to make that more convenient.

Benefits: it's less lines of code, and we always do all the asserts
that are due.

(cherry picked from commit 3746845204)
2018-11-14 14:17:34 +01:00
Thomas Haller
907968ae84 shared: use atomic operation for accessing global hash seed
- fix thread-safety by adding a memory barrier (g_atomic_pointer_get())
  to the double-checked locking pattern when initializing the hash key.

- generate the random data outside the lock. Calling nm_utils_random_bytes()
  within the lock is ugly, because we don't want to assume that the function
  has no side effects which are prone to dead-lock. There is no problem attempting
  to generate the random data without lock, and only use it when the race is won.

(cherry picked from commit 80220024cc)
2018-11-14 14:17:34 +01:00
Thomas Haller
e2d777ff13 core/tests: allow temporarily suppressing logging during tests
Often, during tests we want to assert against the logged messages.
In fact, most tests enable assertions for all logging and enforce
them with g_test_assert_expected_messages(). So, this is common.

However, sometimes it can be cumbersome to understand which logging
lines will be produced. For example, the next commits will call
nm_dhcp_manager_get() during the tests, which initializes NMDhcpManager
and logs a message which plugin was selected (or an additional warning,
if the selected plugin was not found). The availability of the DHCP plugin
depends on searching the path for "/usr/bin/dhclient", so from testing code
it's hard to determine what will be logged.

Instead, add a way to temporarily disable logging during testing.

(cherry picked from commit 35cecd32fd)
2018-11-14 12:38:05 +01:00
Thomas Haller
5fe1728d1f shared: add NM_MAKE_STRV() macro
(cherry picked from commit a15756d990)
2018-11-14 10:36:15 +01:00
Thomas Haller
ae5a09d720 keyfile: split automatically setting ID/UUID for keyfile
keyfile already supports omitting the "connection.id" and
"connection.uuid". In that case, the ID would be taken from the
keyfile's name, and the UUID was generated by md5 hashing the
full filename.

No longer do this during nm_keyfile_read(), instead let all
callers call nm_keyfile_read_ensure_*() to their liking. This is done
for two reasons:

 - a minor reason is, that one day we want to expose keyfile API
   as public API. That means, we also want to read keyfiles from
   stdin, where there is no filename available. The implementation
   which parses stdio needs to define their own way of auto-generating
   ID and UUID. Note how nm_keyfile_read()'s API no longer takes a
   filename as argument, which would be awkward for the stdin case.

 - Currently, we only support one keyfile directory, which (configurably)
   is "/etc/NetworkManager/system-connections".
   In the future, we want to support multiple keyfile dirctories, like
   "/var/run/NetworkManager/profiles" or "/usr/lib/NetworkManager/profiles".
   Here we want that a file "foo" (which does not specify a UUID) gets the
   same UUID regardless of the directory it is in. That seems better, because
   then the UUID won't change as you move the file between directories.
   Yes, that means, that the same UUID will be provided by multiple
   files, but NetworkManager must already cope with that situation anyway.
   Unfortunately, the UUID generation scheme hashes the full path. That
   means, we must hash the path name of the file "foo" inside the
   original "system-connections" directory.
   Refactor the code so that it accounds for a difference between the
   filename of the keyfile, and the profile_dir used for generating
   the UUID.

(cherry picked from commit 837d44ffa4)
2018-10-19 00:14:54 +02:00
Thomas Haller
2c685fc3e0 shared: add nm_strndup_a() helper
(cherry picked from commit ba491a6674)
2018-10-19 00:13:08 +02:00
Thomas Haller
79ddb280de shared: add _nm_utils_ascii_str_to_uint64() helper
(cherry picked from commit c0d292d255)
2018-10-17 16:39:16 +02:00
Thomas Haller
1d718cd16f libnm-core: fix int comparisons in team setting
(cherry picked from commit 72b4541771)
2018-10-07 14:15:22 +02:00
Beniamino Galvani
8fb85b1f5b shared/nm-utils: avoid a coverity warning
1. NetworkManager-1.14.0/shared/nm-utils/nm-shared-utils.c:1242: value_overwrite: Overwriting previous write to "ch" with value from "v".
 2. NetworkManager-1.14.0/shared/nm-utils/nm-shared-utils.c:1239: assigned_value: Assigning value from "++str[0]" to "ch" here, but that stored value is overwritten before it can be used.
 #  1237|   				if (ch >= '0' && ch <= '7') {
 #  1238|   					v = v * 8 + (ch - '0');
 #  1239|-> 					ch = (++str)[0];
 #  1240|   				}
 #  1241|   			}

Don't assign ch when it is going to be overwritten.

(cherry picked from commit e4154895ff)
2018-10-07 14:15:18 +02:00
Thomas Haller
99380fbcea shared: add nm_errno() and nm_utils_error_set_errno() helper
(cherry picked from commit 4186ddb58b)
2018-09-12 10:40:07 +02:00
Thomas Haller
c3808550eb shared: change nm_utils_strbuf_seek_end() handling truncated strings
Ok, I changed my mind.

The new behavior seems to make more sense to me. Not that it matters,
because we always use nm_utils_strbuf*() API with buffers that we expect
to be large enough to contain the result. And when truncation occurs,
we usually don't care much about it. That is, there is no code that
uses nm_utils_strbuf*() API and handles string truncation in particular.
2018-09-07 18:13:10 +02:00
Thomas Haller
62d14e1884 platform/wireguard: rework parsing wireguard links in platform
- previously, parsing wireguard genl data resulted in memory corruption:

  - _wireguard_update_from_allowedips_nla() takes pointers to

      allowedip = &g_array_index (buf->allowedips, NMWireGuardAllowedIP, buf->allowedips->len - 1);

    but resizing the GArray will invalidate this pointer. This happens
    when there are multiple allowed-ips to parse.

  - there was some confusion who owned the allowedips pointers.
    _wireguard_peers_cpy() and _vt_cmd_obj_dispose_lnk_wireguard()
    assumed each peer owned their own chunk, but _wireguard_get_link_properties()
    would not duplicate the memory properly.

- rework memory handling for allowed_ips. Now, the NMPObjectLnkWireGuard
  keeps a pointer _allowed_ips_buf. This buffer contains the instances for
  all peers.
  The parsing of the netlink message is the complicated part, because
  we don't know upfront how many peers/allowed-ips we receive. During
  construction, the tracking of peers/allowed-ips is complicated,
  via a CList/GArray. At the end of that, we prettify the data
  representation and put everything into two buffers. That is more
  efficient and simpler for user afterwards. This moves complexity
  to the way how the object is created, vs. how it is used later.

- ensure that we nm_explicit_bzero() private-key and preshared-key. However,
  that only works to a certain point, because our netlink library does not
  ensure that no data is leaked.

- don't use a "struct sockaddr" union for the peer's endpoint. Instead,
  use a combintation of endpoint_family, endpoint_port, and
  endpoint_addr.

- a lot of refactoring.
2018-09-07 11:24:17 +02:00
Thomas Haller
0a8248af10 shared: add nm_utils_strbuf_seek_end() helper 2018-09-07 11:24:17 +02:00
Thomas Haller
0feeeaac63 shared: add nm_utils_mem_all_zero() 2018-09-07 11:24:17 +02:00
Thomas Haller
085a369446 all: avoid g_memdup()
By using nm_memdup().

Except in shared/nm-utils/nm-compat.c, which may not include
"shared/nm-utils/nm-shared-utils.h".
2018-09-07 11:24:17 +02:00
Thomas Haller
1fb8fbbc99 shared: add nm_memdup() as replacement for g_memdup()
I think g_memdup() is dangerous for integer overflow. There
is no need for accepting this danger, just use our own nm_memdup()
which does not have this flaw.
2018-09-07 11:24:17 +02:00
Thomas Haller
c366c155f1 shared: rename PROP_0 in NM_GOBJECT_PROPERTIES_DEFINE() and skip it in nm_gobject_notify_together()
PROP_0 is how we commonly name this property when we don't use
NM_GOBJECT_PROPERTIES_DEFINE(). Rename it.

Also, allow to skip PROP_0 in nm_gobject_notify_together(), that
is handy to optionally invoke a notification, like

  nm_gobject_notify_together (obj,
                              PROP_SOMETHING,
                              changed ? PROP_OTHER : PROP_0);
2018-09-04 07:38:30 +02:00
Thomas Haller
ff163d9d0d shared: move file-get-contents and file-set-contents helper to shared/
These functions are not specific to "src/". Also, they will be needed
by outside of "src/" soon.
2018-09-04 07:38:30 +02:00
Thomas Haller
6ee7453bc1 shared: add "nm-io-utils.h" 2018-09-04 07:38:30 +02:00
Thomas Haller
c5c0ffdfd0 shared: add nm_gbytes_equal0() helper
Like g_bytes_equal(), except that it accepts %NULL arguments.
2018-09-04 07:38:30 +02:00
Thomas Haller
4c4c85eab0 shared: add _NM_INT_NOT_NEGATIVE() helper 2018-09-04 07:38:30 +02:00
Thomas Haller
5bb8e2fa4d shared: add nm_utils_hexchar_to_int() 2018-09-04 07:38:30 +02:00
Thomas Haller
b232508707 shared: add nm-secret-utils.h helper
We already had nm_free_secret() to clear the secret out
of a NUL terminated string. That works well for secrets
which are strings, it can be used with a cleanup attribute
(nm_auto_free_secret) and as a cleanup function for a
GBytes.

However, it does not work for secrets which are binary.
For those, we must also track the length of the allocated
data and clear it.

Add two new structs NMSecretPtr and NMSecretBuf to help
with that.
2018-09-04 07:38:30 +02:00
Thomas Haller
74815fd8e0 shared: drop unnecessary NM_AUTO_DEFINE_FCN_STRUCT() macro
It serves no purpose, as it just directly calls the function. We don't
need to define this intermediary.
2018-09-04 07:38:30 +02:00
Thomas Haller
f15d82bc91 shared: add nm_auto_unref_bytearray macro
Internally, GByteArray is actually a GArray, so it would be safe to
use "gs_unref_array" macro. However, that is rather ugly, and means
to rely on an internal implementation detail of GByteArray.

Instead, add a cleanup macro for GByteArray.
2018-09-04 07:38:30 +02:00
Thomas Haller
f38cbce653 shared: add nm_utils_gbytes_equal_mem() util 2018-08-30 11:17:09 +02:00
Thomas Haller
e3c944d565 systemd: merge branch systemd into master
https://github.com/NetworkManager/NetworkManager/pull/186
2018-08-27 10:40:34 +02:00
Thomas Haller
8aa8d74710 systemd: update code from upstream (2018-08-26)
This is a direct dump from systemd git.

======

SYSTEMD_DIR=../systemd
COMMIT=56663345dfb1dd3ff23cac5fbc955aba54477efa

(
  cd "$SYSTEMD_DIR"
  git checkout "$COMMIT"
  git reset --hard
  git clean -fdx
)

git ls-files :/src/systemd/src/ \
             :/shared/nm-utils/unaligned.h | \
  xargs -d '\n' rm -f

nm_copy_sd() {
    mkdir -p "./src/systemd/$(dirname "$1")"
    cp "$SYSTEMD_DIR/$1" "./src/systemd/$1"
}

nm_copy_sd_shared() {
    mkdir -p "./shared/nm-utils/"
    cp "$SYSTEMD_DIR/$1" "./shared/nm-utils/${1##*/}"
}

nm_copy_sd "src/basic/alloc-util.c"
nm_copy_sd "src/basic/alloc-util.h"
nm_copy_sd "src/basic/async.h"
nm_copy_sd "src/basic/env-util.c"
nm_copy_sd "src/basic/env-util.h"
nm_copy_sd "src/basic/escape.c"
nm_copy_sd "src/basic/escape.h"
nm_copy_sd "src/basic/ether-addr-util.c"
nm_copy_sd "src/basic/ether-addr-util.h"
nm_copy_sd "src/basic/extract-word.c"
nm_copy_sd "src/basic/extract-word.h"
nm_copy_sd "src/basic/fileio.c"
nm_copy_sd "src/basic/fileio.h"
nm_copy_sd "src/basic/fd-util.c"
nm_copy_sd "src/basic/fd-util.h"
nm_copy_sd "src/basic/fs-util.c"
nm_copy_sd "src/basic/fs-util.h"
nm_copy_sd "src/basic/hash-funcs.c"
nm_copy_sd "src/basic/hash-funcs.h"
nm_copy_sd "src/basic/hashmap.c"
nm_copy_sd "src/basic/hashmap.h"
nm_copy_sd "src/basic/hexdecoct.c"
nm_copy_sd "src/basic/hexdecoct.h"
nm_copy_sd "src/basic/hostname-util.c"
nm_copy_sd "src/basic/hostname-util.h"
nm_copy_sd "src/basic/in-addr-util.c"
nm_copy_sd "src/basic/in-addr-util.h"
nm_copy_sd "src/basic/io-util.c"
nm_copy_sd "src/basic/io-util.h"
nm_copy_sd "src/basic/list.h"
nm_copy_sd "src/basic/log.h"
nm_copy_sd "src/basic/macro.h"
nm_copy_sd "src/basic/mempool.h"
nm_copy_sd "src/basic/mempool.c"
nm_copy_sd "src/basic/parse-util.c"
nm_copy_sd "src/basic/parse-util.h"
nm_copy_sd "src/basic/path-util.c"
nm_copy_sd "src/basic/path-util.h"
nm_copy_sd "src/basic/prioq.h"
nm_copy_sd "src/basic/prioq.c"
nm_copy_sd "src/basic/process-util.h"
nm_copy_sd "src/basic/process-util.c"
nm_copy_sd "src/basic/random-util.c"
nm_copy_sd "src/basic/random-util.h"
nm_copy_sd "src/basic/refcnt.h"
nm_copy_sd "src/basic/set.h"
nm_copy_sd "src/basic/signal-util.h"
nm_copy_sd "src/basic/siphash24.h"
nm_copy_sd "src/basic/socket-util.c"
nm_copy_sd "src/basic/socket-util.h"
nm_copy_sd "src/basic/sparse-endian.h"
nm_copy_sd "src/basic/stat-util.c"
nm_copy_sd "src/basic/stat-util.h"
nm_copy_sd "src/basic/stdio-util.h"
nm_copy_sd "src/basic/string-table.c"
nm_copy_sd "src/basic/string-table.h"
nm_copy_sd "src/basic/string-util.c"
nm_copy_sd "src/basic/string-util.h"
nm_copy_sd "src/basic/strv.c"
nm_copy_sd "src/basic/strv.h"
nm_copy_sd "src/basic/time-util.c"
nm_copy_sd "src/basic/time-util.h"
nm_copy_sd "src/basic/umask-util.h"
nm_copy_sd_shared "src/basic/unaligned.h"
nm_copy_sd "src/basic/utf8.c"
nm_copy_sd "src/basic/utf8.h"
nm_copy_sd "src/basic/util.c"
nm_copy_sd "src/basic/util.h"
nm_copy_sd "src/libsystemd-network/arp-util.c"
nm_copy_sd "src/libsystemd-network/arp-util.h"
nm_copy_sd "src/libsystemd-network/dhcp6-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp6-network.c"
nm_copy_sd "src/libsystemd-network/dhcp6-option.c"
nm_copy_sd "src/libsystemd-network/dhcp6-protocol.h"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.c"
nm_copy_sd "src/libsystemd-network/dhcp-identifier.h"
nm_copy_sd "src/libsystemd-network/dhcp-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-lease-internal.h"
nm_copy_sd "src/libsystemd-network/dhcp-network.c"
nm_copy_sd "src/libsystemd-network/dhcp-option.c"
nm_copy_sd "src/libsystemd-network/dhcp-packet.c"
nm_copy_sd "src/libsystemd-network/dhcp-protocol.h"
nm_copy_sd "src/libsystemd-network/lldp-internal.h"
nm_copy_sd "src/libsystemd-network/lldp-neighbor.c"
nm_copy_sd "src/libsystemd-network/lldp-neighbor.h"
nm_copy_sd "src/libsystemd-network/lldp-network.c"
nm_copy_sd "src/libsystemd-network/lldp-network.h"
nm_copy_sd "src/libsystemd-network/network-internal.c"
nm_copy_sd "src/libsystemd-network/network-internal.h"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp6-lease.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-client.c"
nm_copy_sd "src/libsystemd-network/sd-dhcp-lease.c"
nm_copy_sd "src/libsystemd-network/sd-ipv4ll.c"
nm_copy_sd "src/libsystemd-network/sd-ipv4acd.c"
nm_copy_sd "src/libsystemd-network/sd-lldp.c"
nm_copy_sd "src/libsystemd/sd-event/sd-event.c"
nm_copy_sd "src/libsystemd/sd-id128/id128-util.c"
nm_copy_sd "src/libsystemd/sd-id128/id128-util.h"
nm_copy_sd "src/libsystemd/sd-id128/sd-id128.c"
nm_copy_sd "src/shared/dns-domain.c"
nm_copy_sd "src/shared/dns-domain.h"
nm_copy_sd "src/systemd/_sd-common.h"
nm_copy_sd "src/systemd/sd-dhcp6-client.h"
nm_copy_sd "src/systemd/sd-dhcp6-lease.h"
nm_copy_sd "src/systemd/sd-dhcp-client.h"
nm_copy_sd "src/systemd/sd-dhcp-lease.h"
nm_copy_sd "src/systemd/sd-event.h"
nm_copy_sd "src/systemd/sd-ndisc.h"
nm_copy_sd "src/systemd/sd-id128.h"
nm_copy_sd "src/systemd/sd-ipv4acd.h"
nm_copy_sd "src/systemd/sd-ipv4ll.h"
nm_copy_sd "src/systemd/sd-lldp.h"
2018-08-26 15:48:17 +02:00
Thomas Haller
57c371e32f shared: add nm_utils_buf_utf8safe_escape() util
We already have nm_utils_str_utf8safe_escape() to convert a
NUL termianted string to an UTF-8 string. nm_utils_str_utf8safe_escape()
operates under the assumption, that the input strig is already valid UTF-8
and returns the input string verbatim. That way, in the common expected
cases, the string just looks like a regular UTF-8 string.
However, in case there are invalid UTF-8 sequences (or a backslash
escape characters), the function will use backslash escaping to encode
the input string as a valid UTF-8 sequence. Note that the escaped
sequence, can be reverted to the original non-UTF-8 string via
unescape.
An example, where this is useful are file names or interface names.
Which are not in a defined encoding, but NUL terminated and commonly ASCII or
UTF-8 encoded.

Extend this, to also handle not NUL terminated buffers. The same
applies, except that the process cannot be reverted via g_strcompress()
-- because the NUL character cannot be unescaped.

This will be useful to escape a Wi-Fi SSID. Commonly we expect the SSID
to be in UTF-8/ASCII encoding and we want to print it verbatim. Only
if that is not the case, we fallback to backslash escaping. However, the
orginal value can be fully recovered via unescape(). The difference
between an SSID and a filename is, that the former can contain '\0'
bytes.
2018-08-22 10:49:34 +02:00
Thomas Haller
c06a55958b shared: add nm_utils_gbytes_to_variant_ay() util 2018-08-22 10:49:30 +02:00
Lubomir Rintel
3e8eef5389 utils/test: don't assert on debug level messages
They come and go in GLib core for all sorts of purposes. Don't let that
break our tests.
2018-08-11 11:45:03 +02:00
Beniamino Galvani
6a51d393b2 shared: add @allow_escaping argument to @nm_utils_strsplit_set 2018-08-11 09:41:07 +02:00
Beniamino Galvani
e0bbaf6a39 shared: add space escape functions 2018-08-11 09:41:07 +02:00
Thomas Haller
b7c8e3dbfa shared: add NM_DIV_ROUND_UP() helper macro
Inspired by ethtool's DIV_ROUND_UP() and systemd's DIV_ROUND_UP().
2018-08-10 10:38:19 +02:00
Thomas Haller
a587d32467 shared: move nm_utils_ptrarray_find_binary_search() to shared utils 2018-08-10 10:38:19 +02:00
Thomas Haller
d32da2daaa shared: move nm_utils_array_find_binary_search() to shared utils 2018-08-10 10:38:19 +02:00
Thomas Haller
b5bdfdc773 shared: add nm_utils_hash_table_equal() util
Add utility function to compare the content of two
hash tables for equality.
2018-08-10 10:38:19 +02:00
Thomas Haller
852abf3d3d all/style: write elvis operator ?: without space
By far most of the time, we write "?:" and not "? :". Adjust
the few places that don't.
2018-08-09 17:06:18 +02:00
Thomas Haller
ccf6bdb0e2 shared: add nm_gobject_notify_together() helper
NM_GOBJECT_PROPERTIES_DEFINE() defines a helper function
_notify() to emit a GObject property changed notification.

Add another helper function to emit multiple notifications
together, and freeze/thaw the notification before.

This is particularly useful, because our D-Bus glue in
"nm-dbus-object.c" hooks into dispatch_properties_changed(),
to emit a combined PropertiesChanged signal for multiple
properties. By carefully freezing/thawing the notifications,
the exported objects can combine changes of multiple properties
in one D-Bus signal.

This helper is here to make that simpler.

Note that the compiler still has no problem to inline _notify()
entirey. So, in a non-debug build, there is little difference in
the generated code. It can even nicely inline calls like

    nm_gobject_notify_together (self, PROP_ADDRESS_DATA,
                                      PROP_ADDRESSES);
2018-08-01 14:26:36 +02:00
Lubomir Rintel
9c6ff7fe18 build: do not randomize tests by default
We don't want the users to default to running the code paths in tests that
we didn't check before. They may end up failing randomly.
2018-07-24 20:10:45 +02:00
Thomas Haller
246b747540 shared: add special error codes to NM_UTILS_ERROR
Will be used next.
2018-07-24 09:39:09 +02:00
Thomas Haller
0ee782d03e shared: add nm_utils_error_set*() helper macros
Add helper macros to type less.
2018-07-24 09:39:09 +02:00
Thomas Haller
0d3bb64008 shared: support zero arguments for NM_NARG() macro
It relies on the GCC extension ##__VA_ARGS__, but we
do that on various places already.

Also add a test.
2018-07-24 09:39:09 +02:00
Thomas Haller
196d7c8ca5 shared: use nm_auto() macro to define other nm_auto_* macros 2018-07-18 10:27:39 +02:00