char[] is not a char *; it can not go NULL.
test-ifupdown.c:147:27: error: address of array 'n->name' will always evaluate
to 'true' [-Werror,-Wpointer-bool-conversion]
g_assert (b->name && n->name);
test-ifupdown.c:156:27: error: address of array 'm->key' will always evaluate
to 'true' [-Werror,-Wpointer-bool-conversion]
g_assert (k->key && m->key);
Does not address the issues that the existing logging is much too verbose
and does not provide necessary context for what it's complaining. The
logging messages should be improved.
At least, the logging macro gives all messages a "ifupdown: " prefix.
Don't listen to udev to find out about devices. First of all, using udev
for this is already very wrong, because we have the platform cache.
Anyway, all that the device information is used, is pointless as well.
Drop it.
It's pointless because:
The entires in eni_ifaces are already indexed by the interface name.
Likewise, all NMIfupdownConnection set "connection.interface-name" to
restict the profile by name.
/e/n/i matches devices is by name, that's it. We don't need udev to
look up the MAC address (by name!!) to later ignore/match devices
by MAC address. Especially, because NetworkMaanger can already
restrict profiles to devices based on the interface name.
Likewise, NetworkMaanger can use the interface name for the
unmanaged-specs.
It's wrong to extend the on-disk configuration from /e/n/i with runtime
information from udev, especially, because other NetworkMaanger layers
are perfectly content using the interface name for this purpose.
Also, bind_device_to_connection() was fundamentally wrong. It's wrong
to modify the settings connection at random moments (on udev event).
If at all, that should only happen during connection load/reload.
This may have been necessary a long time ago, when unmanaged devices were
not expressed by device-match-specs, but by the HAL UDI. That was since
improved, for example by commit c9067d8fed.
The "connections" hash contains a mapping of block->name (iface) to the
NMSettingsConnection. The "eni_ifaces" hash contains the name of all
blocks which are mentioned, but for which no connection was created.
Merge the two hashes. We don't need to keep track of whether a
connections was successfully created ("connections"), but the
same name also has a non-connection block. This information is
unnecessary, so one hash is enough.
@unmanage_well_known directly depends on the "ifupdown.managed" setting from
NetworkManager.conf. Rename it (and invert the meaning) so that this
relation ship becomes clearer.
Also, the double negation of "if (!unmanaged_well_known)" hurts the
brain.
This is only useful for testing. But since the managed flag is configurable
via NetworkManager.conf, there is no point in having a define as well. If
you want to test it, just configure it.
And if you really want to patch the code, then patch
"priv->unmanage_well_known" to be always TRUE.
- use _NMLOG() macro and give logging message a sensible prefix
- downgrade logging severity. Most of these messages are not
important to warrant <info> or <warn> level.
- the logging is generally rather bad. Messages like
"bind-to-connection: locking wired connection setting"
don't indicate which profile is locked to which MAC address.
TODO.
- use gs_unref_hashtable for managing lifetime
- only allocate the hashtable if necessary, and use g_hash_table_add()
which is optimized by HashTable.
- actually copy the block->name that is used as key. While not
necessary at the moment, it is very ugly how ifparser_getfirst()
returns static data. Optimally, this would be fixed and we create
and destroy the parser results. Hence, ensure the lifetime of
the key.
- initialize the hash tables in the plugins constructor, not during
initialize().
- let all dictionaries own a copy/reference of the keys and values, and
properly free them when the values are removed. In general, avoid
leaks by properly managing lifetimes.
- in @eni_ifaces, don't add a pointless dummy value "known". It has
overhead for no benefit.
NMSettingsPlugin was a glib interface, not a regular GObject
instance. Accordingly, settings plugins would implement this interface
instead of subclassing a parent type.
Refactor the code, and make NMSettingsPlugin a GObject type. Plugins
are now required to subclass this type.
Glib interfaces are more cumbersome than helpful. At least, unless
there is a good reason for using them.
Our settings plugins are all internal API and are entirely under
our control. It also means, this change is fine, as there are no
implementations outside of this source tree.
Using interfaces do would allow more flexibility in implementing the
settings plugin.
For example, the plugin would be able to derive from any other GObject
type, like NMKimchiRefrigerator. But why would we even? Let's not add monster
classes that implement house appliances beside NMSettingsPluginInterface.
The settings plugin should have one purpose only: being a settings plugin.
Hence, requiring it to subclass NMSettingsPlugin is more than resonable. We
don't need interfaces for this.
Now that NMSettingsPlugin is a regular object instance, it may also have
state, and potentially could provide common functionality for the plugin
implementation -- if that turns out to be useful. Arguably, an interface can
have state too, for example by attaching the state somewhere else (like
NMConnection does). But let's just say no.
On a minor note, this also avoids some tiny overhead that comes with
glib interfaces.
The virtual function init() naturally leads to calling the wrapper
function nm_settings_plugin_init(). However, such ${TYPE}_init() functions
are generated by G_DEFINE_TYPE().
Rename to avoid the naming conflict, which will matter next, when the
interface will be converted to a regular GObject class.
Note that while these are settings plugin, there is no public
or stable API which we need to preserve.
NMConnection is an interface, which is implemented by the types
NMSimpleConnection (libnm-core), NMSettingsConnection (src) and
NMRemoteConnection (libnm).
NMSettingsConnection does a lot of things already:
1) it "is-a" NMDBusObject and exports the API of a connection profile
on D-Bus
2) it interacts with NMSettings and contains functionality
for tracking the profiles.
3) it is the base-class of types like NMSKeyfileConnection and
NMIfcfgConnection. These handle how the profile is persisted
on disk.
4) it implements NMConnection interface, to itself track the
settings of the profile.
3) and 4) would be better implemented via delegation than inheritance.
Address 4) and don't let NMSettingsConnection implemente the NMConnection
interface. Instead, a settings-connection references now a NMSimpleConnection
instance, to which it delegates for keeping the actual profiles.
Advantages:
- by delegating, there is a clearer separation of what
NMSettingsConnection does. For example, in C we often required
casts from NMSettingsConnection to NMConnection. NMConnection
is a very trivial object with very little logic. When we have
a NMConnection instance at hand, it's good to know that it is
*only* that simple instead of also being an entire
NMSettingsConnection instance.
The main purpose of this patch is to simplify the code by separating
the NMConnection from the NMSettingsConnection. We should generally
be aware whether we handle a NMSettingsConnection or a trivial
NMConnection instance. Now, because NMSettingsConnection no longer
"is-a" NMConnection, this distinction is apparent.
- NMConnection is implemented as an interface and we create
NMSimpleConnection instances whenever we need a real instance.
In GLib, interfaces have a performance overhead, that we needlessly
pay all the time. With this change, we no longer require
NMConnection to be an interface. Thus, in the future we could compile
a version of libnm-core for the daemon, where NMConnection is not an
interface but a GObject implementation akin to NMSimpleConnection.
- In the previous implementation, we cannot treat NMConnection immutable
and copy-on-write.
For example, when NMDevice needs a snapshot of the activated
profile as applied-connection, all it can do is clone the entire
NMSettingsConnection as a NMSimpleConnection.
Likewise, when we get a NMConnection instance and want to keep
a reference to it, we cannot do that, because we never know
who also references and modifies the instance.
By separating NMSettingsConnection we could in the future have
NMConnection immutable and copy-on-write, to avoid all unnecessary
clones.
1) the command line gets shorter. I frequently run `make V=1` to see
the command line arguments for the compiler, and there is a lot
of noise.
2) define each of these variables at one place. This makes it easy
to verify that for all compilation units, a particular
define has the same value. Previously that was not obvious or
even not the case (see commit e5d1a71396
and commit d63cf1ef2f).
The point is to avoid redundancy.
3) not all compilation units need all defines. In fact, most modules
would only need a few of these defines. We aimed to pass the necessary
minium of defines to each compilation unit, but that was non-obvious
to get right and often we set a define that wasn't used. See for example
"src_settings_plugins_ibft_cppflags" which needlessly had "-DSYSCONFDIR".
This question is now entirely avoided by just defining all variables in
a header. We don't care to find the minimum, because every component
gets anyway all defines from the header.
4) this also avoids the situation, where a module that previously did
not use a particular define gets modified to require it. Previously,
that would have required to identify the missing define, and add
it to the CFLAGS of the complation unit. Since every compilation
now includes "config-extra.h", all defines are available everywhere.
5) the fact that each define is now available in all compilation units
could be perceived as a downside. But it isn't, because these defines
should have a unique name and one specific value. Defining the same
name with different values, or refer to the same value by different
names is a bug, not a desirable feature. Since these defines should
be unique accross the entire tree, there is no problem in providing
them to every compilation unit.
6) the reason why we generate "config-extra.h" this way, instead of using
AC_DEFINE() in configure.ac, is due to the particular handling of
autoconf for directory variables. See [1].
With meson, it would be trivial to put them into "config.h.meson".
While that is not easy with autoconf, the "config-extra.h" workaround
seems still preferable to me.
[1] https://www.gnu.org/software/autoconf/manual/autoconf-2.63/html_node/Installation-Directory-Variables.html
We commonly don't use the glib typedefs for char/short/int/long,
but their C types directly.
$ git grep '\<g\(char\|short\|int\|long\|float\|double\)\>' | wc -l
587
$ git grep '\<\(char\|short\|int\|long\|float\|double\)\>' | wc -l
21114
One could argue that using the glib typedefs is preferable in
public API (of our glib based libnm library) or where it clearly
is related to glib, like during
g_object_set (obj, PROPERTY, (gint) value, NULL);
However, that argument does not seem strong, because in practice we don't
follow that argument today, and seldomly use the glib typedefs.
Also, the style guide for this would be hard to formalize, because
"using them where clearly related to a glib" is a very loose suggestion.
Also note that glib typedefs will always just be typedefs of the
underlying C types. There is no danger of glib changing the meaning
of these typedefs (because that would be a major API break of glib).
A simple style guide is instead: don't use these typedefs.
No manual actions, I only ran the bash script:
FILES=($(git ls-files '*.[hc]'))
sed -i \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>\( [^ ]\)/\1\2/g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\> /\1 /g' \
-e 's/\<g\(char\|short\|int\|long\|float\|double\)\>/\1/g' \
"${FILES[@]}"
Use two common defines NM_BUILD_SRCDIR and NM_BUILD_BUILDDIR
for specifying the location of srcdir and builddir.
Note that this is only relevant for tests, as they expect
a certain layout of the directories, to find files that concern
them.
Coccinelle:
@@
expression a, b;
@@
-a ? a : b
+a ?: b
Applied with:
spatch --sp-file ternary.cocci --in-place --smpl-spacing --dir .
With some manual adjustments on spots that Cocci didn't catch for
reasons unknown.
Thanks to the marvelous effort of the GNU compiler developer we can now
spare a couple of bits that could be used for more important things,
like this commit message. Standards commitees yet have to catch up.
There are multiple tests with the same in different directories; add a
unique prefix to test names so that it is clear from the output which
one is running.
We commonly only allow tabs at the beginning of a line, not
afterwards. The reason for this style is so that the code
looks formated right with tabstop=4 and tabstop=8.
We also unconditionally use them with autotools.
Also, the detection for have_version_script does
not seem correct to me. At least, it didn't work
with clang.
Some targets are missing dependencies on some generated sources in
the meson port. These makes the build to fail due to missing source
files on a highly parallelized build.
These dependencies have been resolved by taking advantage of meson's
internal dependencies which can be used to pass source files,
include directories, libraries and compiler flags.
One of such internal dependencies called `core_dep` was already in
use. However, in order to avoid any confusion with another new
internal dependency called `nm_core_dep`, which is used to include
directories and source files from the `libnm-core` directory, the
`core_dep` dependency has been renamed to `nm_dep`.
These changes have allowed minimizing the build details which are
inherited by using those dependencies. The parallelized build has
also been improved.
When building with assertions, they nm_assert() for the
type. Otherwise, they are identical to a C cast.
Also, where possible, don't cast at all, but adjust
the type instead.
Also, there were a few missing casts.