There is no advantage in having these as macros. Make them
inline functions, compiler should be able to decide that they
are in fact inlinable.
Also, don't call g_strcmp0() for nm_streq0(). It means we first
have to call glib function, only to call a glibc function. No need
for this abstraction.
Contrary to g_str_has_suffix(), it exploits the fact the the suffix length
is known at compile time. No need to call a glib function, to find out what
we already know, to call strcmp().
Instead just calculate the string length and call memcmp().
Yes, C has a preprocessor and nm_streq() currently is a macro.
Still, macros should very much behave like regular functions.
For example, no unexpected side-effects aside what a regular function
would have, evaluating all arguments exactly once, or no side-effects
w.r.t. the order in which arguments are evaluated.
In some cases, we deviate from that for good reasons. For example
NM_IN_SET() may not evaluate all arguments. _LOGD() may not evaluate
any arguments, and NM_UTILS_LOOKUP_STR_DEFINE() is not a function-like
macro at all.
Still, that is not the case here. We avoid to misuse macros to write
code that does not look like C.
Previously, we might have a pending action 'waiting-for-supplicant'
registered, although the device was not waiting:
<info> [1549611177.5815] device (wlan0): supplicant interface state: starting -> ready
<debug> [1549611177.5816] device[0x55d1781ae5d0] (p2p-dev-wlan0): P2P: Releasing WPA supplicant interfaces.
<debug> [1549611177.5816] device[0x55d1781ae5d0] (p2p-dev-wlan0): P2P: WPA supplicant management interface changed to /fi/w1/wpa_supplicant1/Interfaces/1.
<trace> [1549611177.5816] device[0x55d1781ae5d0] (p2p-dev-wlan0): remove_pending_action (0): 'waiting-for-supplicant' not pending (expected)
<debug> [1549611177.5816] device[0x55d1781ae5d0] (p2p-dev-wlan0): constructed (NMDeviceWifiP2P)
<debug> [1549611177.5816] device[0x55d1781ae5d0] (p2p-dev-wlan0): add_pending_action (1): 'waiting-for-supplicant'
The previous commit already fixed this bug by dropping the constructor
property for NM_DEVICE_WIFI_P2P_MGMT_IFACE.
Still, refactor handling of pending actions to keep track of whether we
have a pending action registered.
We already have a setter function nm_device_wifi_p2p_set_mgmt_iface()
as we may need to change the mgmt-iface later on. Use that to set the
supplicant interface instead of a constructor property.
That makes the object creation simpler, because nothing noteworthy
happens, until the very last statement in constructed() to add the
pending action.
Subsequent calls to nm_strerror_native() overwrite the previous
buffer. That is potentially dangerious. At least functions in
shared/nm-utils (which are lower-layer utilities) should not do
that and instead use a stack-local buffer. That is because these
functions should not make assumptions about the way they are called.
On the other end, nmcli passing the return-value of nm_strerror_native()
to g_print() is clearly OK because the higher layers are in control of
when the call nm_strerror_native() -- by relying that lower layers don't
interfere.
We have various options for strerror(), with ups and downsides:
- strerror()
- returns pointer that is overwritten on next call. It's convenient
to use, but dangerous.
- not thread-safe.
- not guaranteed to be UTF-8.
- strerror_r()
- takes input buffer and is less convenient to use. At least, we
are in control of when the buffer gets overwritten.
- there is a Posix/XSI and a glibc variant, making it sligthly
inconvenient to used. This could be solved by a wrapper we implement.
- thread-safe.
- not guaranteed to be UTF-8.
- g_strerror()
- convenient and safe to use. Also the buffer is never released for the
remainder of the program.
- passing untrusted error numbers to g_strerror() can result in a
denial of service, as the internal buffer grows until out-of-memory.
- thread-safe.
- guaranteed to be UTF-8 (depending on locale).
Add our own wrapper nm_strerror_native(). It is:
- convenient to use (returning a buffer that does not require
management).
- slightly dangerous as the buffer gets overwritten on the next call
(like strerror()).
- thread-safe.
- guaranteed to be UTF-8 (depending on locale).
- doesn't keep an unlimited cache of strings, unlike g_strerror().
You can't have it all. g_strerror() is leaking all generated error messages.
I think that is unacceptable, because it would mean we need to
keep track where our error numbers come from (and trust libraries we
use to only set a restricted set of known error numbers).
Use the NM_ERRNO_NATIVE() macro that asserts that these errno numbers are
indeed positive. Using the macro also serves as a documentation of what
the meaning of these numbers is.
That is often not obvious, whether we have an nm_errno(), an nm_errno_native()
(from <errno.h>), or another error number (e.g. WaitForNlResponseResult). This
situation already improved by merging netlink error codes (nle),
NMPlatformError enum and <errno.h> as nm_errno(). But we still must
always be careful about not to mix error codes from different
domains or transform them appropriately (like nm_errno_from_native()).
The native error numbers (from <errno.h>) and our nmerr extention on top
of them are almost the same. But there are peculiarities.
Both errno and nmerr must be positive values. That is because some API
(systemd) like to return negative error codes. So, a positive errno and
its negative counter part indicate the same error. We need normalization
functions that make an error number positive (these are nm_errno() and
nm_errno_native()).
This means, G_MININT needs special treatment, because it cannot be
represented as a positive integer. Also, zero needs special
treatment, because we want to encode an error, and zero already encodes
no-error. Take care of these special cases.
On top of that, nmerr reserves a range within native error numbers for
NetworkManager specific failure codes. So we need to transition from native
numbers to nmerr numbers via nm_errno_from_native().
Take better care of some special cases and clean them up.
Also add NM_ERRNO_NATIVE() macro. While nm_errno_native() coerces a
value in the suitable range, NM_ERRNO_NATIVE() asserts that the number
is already positive (and returns it as-is). It's use is only for
asserting and implicitly documenting the requirements we have on the
number passed to it.
Using strtol() correctly proves to be hard.
Usually, we want to also check that the end pointer is points to the end
of the string. Othewise, we silently accept trailing garbage.
When the logging level is DEBUG or TRACE, we keep all the sysctl
values we read in a cache to log how they change. Currently there is
no limit on the size of this cache and it can take a large amount of
memory.
Implement a LRU cache where the oldest entries are deleted to make
space for new ones.
https://github.com/NetworkManager/NetworkManager/pull/294
nm_ip_route_get_prefix() and plen are guint type, hence the following
is not correct:
plen = nm_ip_route_get_prefix (route1);
r = plen - nm_ip_route_get_prefix (route2);
if (r)
return r > 0 ? 1 : -1;
Use the macro, it gets subtle cases like this right.
Fixes: b32bb36c61
This enables -Werror for meson builds on gitlab-ci and semaphore.
Not on Travis, the compiler there is too old, giving too many bogus
warnings.
This reverts commit 928d68d04a ("m4:
disable -Wmissing-braces for newer clang").
The right way is IN6_ADDR_INIT_ANY.
While at it, don't initialize multiple variables in the same line.
../src/devices/nm-device-ip-tunnel.c:153:29: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
struct in6_addr local6 = { 0 }, remote6 = { 0 };
^
{}
NMIPAddr contains an unnamed union. We have to either explicitly
initialize one field, or omit it.
../shared/nm-utils/nm-shared-utils.c:38:36: error: suggest braces around initialization of subobject [-Werror,-Wmissing-braces]
const NMIPAddr nm_ip_addr_zero = { 0 };
^
{}
The cast is bogus and leads to a compiler warning:
[424/583] Compiling C object src/devices/wifi/914a32e@@nm-device-plugin-wifi@sha/nm-device-iwd.c.o.
In file included from ../shared/nm-default.h:293,
from ../src/devices/wifi/nm-device-iwd.c:21:
../src/devices/wifi/nm-device-iwd.c: In function ‘nm_device_iwd_set_dbus_object’:
../src/devices/wifi/nm-device-iwd.c:2404:28: warning: dereferencing type-punned pointer will break strict-aliasing rules [-Wstrict-aliasing]
if (!nm_g_object_ref_set ((GObject **) &priv->dbus_obj, (GObject *) object))
../shared/nm-utils/nm-macros-internal.h:1048:13: note: in definition of macro ‘nm_g_object_ref_set’
typeof (*(pp)) *const _pp = (pp); \
^~
The test should check the behavior with "const typeof(a)" in a macro,
where "a" itself is const. For that we don't need a double const
declaration of v2.
Also, that fixes an actual compiler warning:
../src/tests/test-general.c: In function ‘test_duplicate_decl_specifier’:
../src/tests/test-general.c:1669:8: warning: duplicate ‘const’ declaration specifier [-Wduplicate-decl-specifier]
const const int v2 = 3;
^~~~~
It's not useful for us.
In file included from ../src/systemd/src/libsystemd/sd-event/sd-event.c:14:
../src/systemd/src/libsystemd/sd-event/event-source.h:195:36: error: field 'buffer' with variable sized type 'union inotify_event_buffer' not at the end of a struct or class is a GNU extension [-Werror,-Wgnu-variable-sized-type-not-at-end]
union inotify_event_buffer buffer;
^