NetworkManager/src/libnm-client-impl/nm-object.c
Thomas Haller 615221a99c format: reformat source tree with clang-format 13.0
We use clang-format for automatic formatting of our source files.
Since clang-format is actively maintained software, the actual
formatting depends on the used version of clang-format. That is
unfortunate and painful, but really unavoidable unless clang-format
would be strictly bug-compatible.

So the version that we must use is from the current Fedora release, which
is also tested by our gitlab-ci. Previously, we were using Fedora 34 with
clang-tools-extra-12.0.1-1.fc34.x86_64.

As Fedora 35 comes along, we need to update our formatting as Fedora 35
comes with version "13.0.0~rc1-1.fc35".
An alternative would be to freeze on version 12, but that has different
problems (like, it's cumbersome to rebuild clang 12 on Fedora 35 and it
would be cumbersome for our developers which are on Fedora 35 to use a
clang that they cannot easily install).

The (differently painful) solution is to reformat from time to time, as we
switch to a new Fedora (and thus clang) version.
Usually we would expect that such a reformatting brings minor changes.
But this time, the changes are huge. That is mentioned in the release
notes [1] as

  Makes PointerAligment: Right working with AlignConsecutiveDeclarations. (Fixes https://llvm.org/PR27353)

[1] https://releases.llvm.org/13.0.0/tools/clang/docs/ReleaseNotes.html#clang-format
2021-11-29 09:31:09 +00:00

338 lines
9.8 KiB
C

/* SPDX-License-Identifier: LGPL-2.1-or-later */
/*
* Copyright (C) 2007 - 2008 Novell, Inc.
* Copyright (C) 2007 - 2012 Red Hat, Inc.
*/
#include "libnm-client-impl/nm-default-libnm.h"
#include "nm-object.h"
#include <stdlib.h>
#include <stdio.h>
#include "nm-utils.h"
#include "nm-dbus-interface.h"
#include "nm-object-private.h"
#include "nm-dbus-helpers.h"
#include "nm-client.h"
#include "libnm-core-intern/nm-core-internal.h"
#include "c-list/src/c-list.h"
/*****************************************************************************/
NM_GOBJECT_PROPERTIES_DEFINE_BASE(PROP_PATH, PROP_CLIENT, );
typedef struct _NMObjectPrivate {
NMClient *client;
NMLDBusObject *dbobj;
} NMObjectPrivate;
G_DEFINE_ABSTRACT_TYPE(NMObject, nm_object, G_TYPE_OBJECT);
#define NM_OBJECT_GET_PRIVATE(self) _NM_GET_PRIVATE_PTR(self, NMObject, NM_IS_OBJECT)
static NMObjectClass *_nm_object_class = NULL;
/*****************************************************************************/
static gpointer
_nm_object_get_private(NMObjectClass *klass, NMObject *self, guint16 extra_offset)
{
char *ptr;
nm_assert(klass->priv_ptr_offset > 0);
ptr = (char *) self;
ptr += klass->priv_ptr_offset;
if (klass->priv_ptr_indirect)
ptr = *((gpointer *) ptr);
return ptr + extra_offset;
}
NMLDBusObject *
_nm_object_get_dbobj(gpointer self)
{
return NM_OBJECT_GET_PRIVATE(self)->dbobj;
}
const char *
_nm_object_get_path(gpointer self)
{
return NM_OBJECT_GET_PRIVATE(self)->dbobj->dbus_path->str;
}
NMClient *
_nm_object_get_client(gpointer self)
{
return NM_OBJECT_GET_PRIVATE(self)->client;
}
/**
* nm_object_get_path:
* @object: a #NMObject
*
* Gets the DBus path of the #NMObject.
*
* Returns: the object's path. This is the internal string used by the
* object, and must not be modified.
*
* Note that the D-Bus path of an NMObject never changes, even
* if the instance gets removed from the cache. To find out
* whether the object is still alive/cached, check nm_object_get_client().
**/
const char *
nm_object_get_path(NMObject *object)
{
g_return_val_if_fail(NM_IS_OBJECT(object), NULL);
return _nm_object_get_path(object);
}
/**
* nm_object_get_client:
* @object: a #NMObject
*
* Returns the #NMClient instance in which object is cached.
* Also, if the object got removed from the client cached,
* this returns %NULL. So it can be used to check whether the
* object is still alive.
*
* Returns: (transfer none): the #NMClient cache in which the
* object can be found, or %NULL if the object is no longer
* cached.
*
* Since: 1.24
**/
NMClient *
nm_object_get_client(NMObject *object)
{
g_return_val_if_fail(NM_IS_OBJECT(object), NULL);
return _nm_object_get_client(object);
}
/*****************************************************************************/
static void
clear_properties(NMObject *self, NMClient *client)
{
NMObjectClass *klass = NM_OBJECT_GET_CLASS(self);
const _NMObjectClassFieldInfo *p;
nm_assert(NM_IS_OBJECT(self));
nm_assert(!client || NM_IS_CLIENT(client));
for (p = klass->property_o_info; p; p = p->parent) {
nml_dbus_property_o_clear_many(_nm_object_get_private(p->klass, self, p->offset),
p->num,
client);
}
for (p = klass->property_ao_info; p; p = p->parent) {
nml_dbus_property_ao_clear_many(_nm_object_get_private(p->klass, self, p->offset),
p->num,
client);
}
}
/*****************************************************************************/
static gboolean
is_ready(NMObject *self)
{
NMObjectClass *klass = NM_OBJECT_GET_CLASS(self);
NMClient *client = _nm_object_get_client(self);
const _NMObjectClassFieldInfo *p;
guint16 i;
nm_assert(NM_IS_CLIENT(client));
for (p = klass->property_o_info; p; p = p->parent) {
NMLDBusPropertyO *fields = _nm_object_get_private(p->klass, self, p->offset);
for (i = 0; i < p->num; i++) {
if (!nml_dbus_property_o_is_ready(&fields[i]))
return FALSE;
}
}
for (p = klass->property_ao_info; p; p = p->parent) {
NMLDBusPropertyAO *fields = _nm_object_get_private(p->klass, self, p->offset);
for (i = 0; i < p->num; i++) {
if (!nml_dbus_property_ao_is_ready(&fields[i]))
return FALSE;
}
}
return TRUE;
}
static void
obj_changed_notify(NMObject *self)
{
NMObjectClass *klass = NM_OBJECT_GET_CLASS(self);
NMClient *client = _nm_object_get_client(self);
const _NMObjectClassFieldInfo *p;
nm_assert(NM_IS_CLIENT(client));
for (p = klass->property_o_info; p; p = p->parent) {
nml_dbus_property_o_notify_changed_many(_nm_object_get_private(p->klass, self, p->offset),
p->num,
client);
}
for (p = klass->property_ao_info; p; p = p->parent) {
nml_dbus_property_ao_notify_changed_many(_nm_object_get_private(p->klass, self, p->offset),
p->num,
client);
}
}
/*****************************************************************************/
static void
register_client(NMObject *self, NMClient *client, NMLDBusObject *dbobj)
{
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE(self);
nm_assert(!priv->client);
nm_assert(NML_IS_DBUS_OBJECT(dbobj));
nm_assert(dbobj->nmobj == G_OBJECT(self));
priv->client = client;
priv->dbobj = nml_dbus_object_ref(dbobj);
}
static void
unregister_client(NMObject *self, NMClient *client, NMLDBusObject *dbobj)
{
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE(self);
nm_assert(NM_IS_CLIENT(client));
nm_assert(priv->client == client);
priv->client = NULL;
_nm_client_queue_notify_object(client, self, obj_properties[PROP_CLIENT]);
clear_properties(self, client);
}
/*****************************************************************************/
static void
get_property(GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
{
NMObject *self = NM_OBJECT(object);
switch (prop_id) {
case PROP_PATH:
g_value_set_string(value, nm_object_get_path(self));
break;
case PROP_CLIENT:
g_value_set_object(value, nm_object_get_client(self));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID(object, prop_id, pspec);
break;
}
}
/*****************************************************************************/
static void
nm_object_init(NMObject *object)
{
NMObject *self = NM_OBJECT(object);
NMObjectPrivate *priv;
priv = G_TYPE_INSTANCE_GET_PRIVATE(self, NM_TYPE_OBJECT, NMObjectPrivate);
self->_priv = priv;
c_list_init(&self->obj_base.queue_notify_lst);
NML_DBUS_LOG(_NML_NMCLIENT_LOG_LEVEL_COERCE(NML_DBUS_LOG_LEVEL_TRACE),
"nmobj[" NM_HASH_OBFUSCATE_PTR_FMT "]: creating",
NM_HASH_OBFUSCATE_PTR(self));
}
static void
dispose(GObject *object)
{
NMObject *self = NM_OBJECT(object);
NMObjectPrivate *priv = NM_OBJECT_GET_PRIVATE(self);
if (!self->obj_base.is_disposing) {
NML_DBUS_LOG(_NML_NMCLIENT_LOG_LEVEL_COERCE(NML_DBUS_LOG_LEVEL_TRACE),
"nmobj[" NM_HASH_OBFUSCATE_PTR_FMT "]: disposing",
NM_HASH_OBFUSCATE_PTR(self));
}
self->obj_base.is_disposing = TRUE;
nm_assert(c_list_is_empty(&self->obj_base.queue_notify_lst));
nm_assert(!priv->client);
nm_assert(!priv->dbobj || !priv->dbobj->nmobj);
clear_properties(self, NULL);
G_OBJECT_CLASS(nm_object_parent_class)->dispose(object);
nm_clear_pointer(&priv->dbobj, nml_dbus_object_unref);
}
static void
nm_object_class_init(NMObjectClass *klass)
{
GObjectClass *object_class = G_OBJECT_CLASS(klass);
_nm_object_class = klass;
g_type_class_add_private(klass, sizeof(NMObjectPrivate));
object_class->get_property = get_property;
object_class->dispose = dispose;
klass->register_client = register_client;
klass->unregister_client = unregister_client;
klass->is_ready = is_ready;
klass->obj_changed_notify = obj_changed_notify;
/**
* NMObject:path:
*
* The D-Bus object path.
*
* The D-Bus path of an object instance never changes, even if the object
* gets removed from the cache. To see whether the object is still in the
* cache, check NMObject:client.
**/
obj_properties[PROP_PATH] = g_param_spec_string(NM_OBJECT_PATH,
"",
"",
NULL,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
/**
* NMObject:client:
*
* The NMClient instance as returned by nm_object_get_client().
*
* When an NMObject gets removed from the NMClient cache,
* the NMObject:path property stays unchanged, but this client
* instance gets reset to %NULL. You can use this property to
* track removal of the object from the cache.
*
* Since: 1.34
**/
obj_properties[PROP_CLIENT] = g_param_spec_object(NM_OBJECT_CLIENT,
"",
"",
NM_TYPE_CLIENT,
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
g_object_class_install_properties(object_class, _PROPERTY_ENUMS_LAST, obj_properties);
}