summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2019-01-09 09:08:39 +0100
committerThomas Haller <thaller@redhat.com>2019-01-11 11:48:47 +0100
commit885c872d5a542f820afdf4e8ca59c55f39467c7a (patch)
tree1982a91850189b7b13ba9c309c26236fae2b2e8f
parent5aace3dfea61b2409d6b62127853bd5ed4721bf2 (diff)
downloadNetworkManager-885c872d5a542f820afdf4e8ca59c55f39467c7a.tar.gz
libnm: rework compare_property() implementation for NMSetting
NMSetting's compare_property() has and had two callers: nm_setting_compare() and nm_setting_diff(). compare_property() accepts a NMSettingCompareFlags argument, but at the same time, both callers have another complex (and inconsistent!) set of pre-checks for shortcuting the call of compare_property(): should_compare_prop(). Merge should_compare_prop() into compare_property(). This way, nm_setting_compare() and nm_setting_diff() has less additional code, and are simpler to follow. Especially nm_setting_compare() is now trivial. And nm_setting_diff() is still complicated, but not related to the question how the property compares or whether it should be compared at all. If you want to know whether it should be compared, all you need to do now is follow NMSettingClass.compare_property(). This changes function pointer NMSettingClass.compare_property(), which is public API. However, no user can actually use this (and shall not!), because _nm_setting_class_commit_full() etc. is private API. A user outside of libnm-core cannot create his/her own subclasses of NMSetting, and never could in the past. So, this API/ABI change doesn't matter.
-rw-r--r--libnm-core/nm-setting-bond.c54
-rw-r--r--libnm-core/nm-setting-connection.c31
-rw-r--r--libnm-core/nm-setting-ip-config.c50
-rw-r--r--libnm-core/nm-setting-private.h5
-rw-r--r--libnm-core/nm-setting-sriov.c34
-rw-r--r--libnm-core/nm-setting-tc-config.c39
-rw-r--r--libnm-core/nm-setting-team-port.c80
-rw-r--r--libnm-core/nm-setting-team.c73
-rw-r--r--libnm-core/nm-setting-user.c37
-rw-r--r--libnm-core/nm-setting-vpn.c88
-rw-r--r--libnm-core/nm-setting-wired.c22
-rw-r--r--libnm-core/nm-setting-wireless.c23
-rw-r--r--libnm-core/nm-setting.c354
-rw-r--r--libnm-core/nm-setting.h18
14 files changed, 506 insertions, 402 deletions
diff --git a/libnm-core/nm-setting-bond.c b/libnm-core/nm-setting-bond.c
index 0c84b3a01c..7bf7612aee 100644
--- a/libnm-core/nm-setting-bond.c
+++ b/libnm-core/nm-setting-bond.c
@@ -811,15 +811,15 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
/*****************************************************************************/
static gboolean
-options_hash_match (NMSettingBond *s_bond,
- GHashTable *options1,
- GHashTable *options2,
+options_equal_asym (NMSettingBond *s_bond,
+ NMSettingBond *s_bond2,
NMSettingCompareFlags flags)
{
+ GHashTable *options2 = NM_SETTING_BOND_GET_PRIVATE (s_bond2)->options;
GHashTableIter iter;
const char *key, *value, *value2;
- g_hash_table_iter_init (&iter, options1);
+ g_hash_table_iter_init (&iter, NM_SETTING_BOND_GET_PRIVATE (s_bond)->options);
while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &value)) {
if (NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) {
@@ -841,15 +841,10 @@ options_hash_match (NMSettingBond *s_bond,
value2 = g_hash_table_lookup (options2, "num_grat_arp");
}
- if (value2) {
- if (nm_streq (value, value2))
- continue;
- } else {
- if (nm_streq (value, nm_setting_bond_get_option_default (s_bond, key)))
- continue;
- }
-
- return FALSE;
+ if (!value2)
+ value2 = nm_setting_bond_get_option_default (s_bond2, key);
+ if (!nm_streq (value, value2))
+ return FALSE;
}
return TRUE;
@@ -857,31 +852,32 @@ options_hash_match (NMSettingBond *s_bond,
static gboolean
options_equal (NMSettingBond *s_bond,
- GHashTable *options1,
- GHashTable *options2,
+ NMSettingBond *s_bond2,
NMSettingCompareFlags flags)
{
- return options_hash_match (s_bond, options1, options2, flags)
- && options_hash_match (s_bond, options2, options1, flags);
+ return options_equal_asym (s_bond, s_bond2, flags)
+ && options_equal_asym (s_bond2, s_bond, flags);
}
-static gboolean
-compare_property (NMSetting *setting,
+static NMTernary
+compare_property (const NMSettInfoSetting *sett_info,
+ guint property_idx,
+ NMSetting *setting,
NMSetting *other,
- const GParamSpec *prop_spec,
NMSettingCompareFlags flags)
{
- NMSettingClass *setting_class;
-
- if (nm_streq0 (prop_spec->name, NM_SETTING_BOND_OPTIONS)) {
- return options_equal (NM_SETTING_BOND (setting),
- NM_SETTING_BOND_GET_PRIVATE (setting)->options,
- NM_SETTING_BOND_GET_PRIVATE (other)->options,
- flags);
+ if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_BOND_OPTIONS)) {
+ return ( !other
+ || options_equal (NM_SETTING_BOND (setting),
+ NM_SETTING_BOND (other),
+ flags));
}
- setting_class = NM_SETTING_CLASS (nm_setting_bond_parent_class);
- return setting_class->compare_property (setting, other, prop_spec, flags);
+ return NM_SETTING_CLASS (nm_setting_bond_parent_class)->compare_property (sett_info,
+ property_idx,
+ setting,
+ other,
+ flags);
}
/*****************************************************************************/
diff --git a/libnm-core/nm-setting-connection.c b/libnm-core/nm-setting-connection.c
index 3c3a4dcee5..12a2af5bec 100644
--- a/libnm-core/nm-setting-connection.c
+++ b/libnm-core/nm-setting-connection.c
@@ -1281,23 +1281,26 @@ nm_setting_connection_no_interface_name (NMSetting *setting,
return TRUE;
}
-static gboolean
-compare_property (NMSetting *setting,
+static NMTernary
+compare_property (const NMSettInfoSetting *sett_info,
+ guint property_idx,
+ NMSetting *setting,
NMSetting *other,
- const GParamSpec *prop_spec,
NMSettingCompareFlags flags)
{
- /* Handle ignore ID */
- if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_ID)
- && g_strcmp0 (prop_spec->name, NM_SETTING_CONNECTION_ID) == 0)
- return TRUE;
-
- /* Handle ignore timestamp */
- if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP)
- && g_strcmp0 (prop_spec->name, NM_SETTING_CONNECTION_TIMESTAMP) == 0)
- return TRUE;
-
- return NM_SETTING_CLASS (nm_setting_connection_parent_class)->compare_property (setting, other, prop_spec, flags);
+ if ( NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_IGNORE_ID)
+ && nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_CONNECTION_ID))
+ return NM_TERNARY_DEFAULT;
+
+ if ( NM_FLAGS_HAS(flags, NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP)
+ && nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_CONNECTION_TIMESTAMP))
+ return NM_TERNARY_DEFAULT;
+
+ return NM_SETTING_CLASS (nm_setting_connection_parent_class)->compare_property (sett_info,
+ property_idx,
+ setting,
+ other,
+ flags);
}
static void
diff --git a/libnm-core/nm-setting-ip-config.c b/libnm-core/nm-setting-ip-config.c
index 23e211f2e8..3e20263247 100644
--- a/libnm-core/nm-setting-ip-config.c
+++ b/libnm-core/nm-setting-ip-config.c
@@ -2612,44 +2612,52 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
return TRUE;
}
-static gboolean
-compare_property (NMSetting *setting,
+static NMTernary
+compare_property (const NMSettInfoSetting *sett_info,
+ guint property_idx,
+ NMSetting *setting,
NMSetting *other,
- const GParamSpec *prop_spec,
NMSettingCompareFlags flags)
{
- NMSettingIPConfigPrivate *a_priv, *b_priv;
- NMSettingClass *setting_class;
+ NMSettingIPConfigPrivate *a_priv;
+ NMSettingIPConfigPrivate *b_priv;
guint i;
- if (nm_streq (prop_spec->name, NM_SETTING_IP_CONFIG_ADDRESSES)) {
- a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
- b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (other);
+ if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_IP_CONFIG_ADDRESSES)) {
+ if (other) {
+ a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (other);
- if (a_priv->addresses->len != b_priv->addresses->len)
- return FALSE;
- for (i = 0; i < a_priv->addresses->len; i++) {
- if (!_nm_ip_address_equal (a_priv->addresses->pdata[i], b_priv->addresses->pdata[i], TRUE))
+ if (a_priv->addresses->len != b_priv->addresses->len)
return FALSE;
+ for (i = 0; i < a_priv->addresses->len; i++) {
+ if (!_nm_ip_address_equal (a_priv->addresses->pdata[i], b_priv->addresses->pdata[i], TRUE))
+ return FALSE;
+ }
}
return TRUE;
}
- if (nm_streq (prop_spec->name, NM_SETTING_IP_CONFIG_ROUTES)) {
- a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
- b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (other);
+ if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_IP_CONFIG_ROUTES)) {
+ if (other) {
+ a_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (setting);
+ b_priv = NM_SETTING_IP_CONFIG_GET_PRIVATE (other);
- if (a_priv->routes->len != b_priv->routes->len)
- return FALSE;
- for (i = 0; i < a_priv->routes->len; i++) {
- if (!nm_ip_route_equal_full (a_priv->routes->pdata[i], b_priv->routes->pdata[i], NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS))
+ if (a_priv->routes->len != b_priv->routes->len)
return FALSE;
+ for (i = 0; i < a_priv->routes->len; i++) {
+ if (!nm_ip_route_equal_full (a_priv->routes->pdata[i], b_priv->routes->pdata[i], NM_IP_ROUTE_EQUAL_CMP_FLAGS_WITH_ATTRS))
+ return FALSE;
+ }
}
return TRUE;
}
- setting_class = NM_SETTING_CLASS (nm_setting_ip_config_parent_class);
- return setting_class->compare_property (setting, other, prop_spec, flags);
+ return NM_SETTING_CLASS (nm_setting_ip_config_parent_class)->compare_property (sett_info,
+ property_idx,
+ setting,
+ other,
+ flags);
}
/*****************************************************************************/
diff --git a/libnm-core/nm-setting-private.h b/libnm-core/nm-setting-private.h
index 49d27336fa..2f46bc6770 100644
--- a/libnm-core/nm-setting-private.h
+++ b/libnm-core/nm-setting-private.h
@@ -201,6 +201,11 @@ gboolean _nm_setting_use_legacy_property (NMSetting *setting,
GPtrArray *_nm_setting_need_secrets (NMSetting *setting);
+gboolean _nm_setting_should_compare_secret_property (NMSetting *setting,
+ NMSetting *other,
+ const char *secret_name,
+ NMSettingCompareFlags flags);
+
/*****************************************************************************/
#endif /* NM_SETTING_PRIVATE_H */
diff --git a/libnm-core/nm-setting-sriov.c b/libnm-core/nm-setting-sriov.c
index b7756e3506..fa32f55cde 100644
--- a/libnm-core/nm-setting-sriov.c
+++ b/libnm-core/nm-setting-sriov.c
@@ -1188,29 +1188,37 @@ get_property (GObject *object, guint prop_id,
}
}
-static gboolean
-compare_property (NMSetting *setting,
+static NMTernary
+compare_property (const NMSettInfoSetting *sett_info,
+ guint property_idx,
+ NMSetting *setting,
NMSetting *other,
- const GParamSpec *prop_spec,
NMSettingCompareFlags flags)
{
- NMSettingSriov *a = NM_SETTING_SRIOV (setting);
- NMSettingSriov *b = NM_SETTING_SRIOV (other);
- NMSettingClass *setting_class;
+ NMSettingSriov *a;
+ NMSettingSriov *b;
guint i;
- if (nm_streq (prop_spec->name, NM_SETTING_SRIOV_VFS)) {
- if (a->vfs->len != b->vfs->len)
- return FALSE;
- for (i = 0; i < a->vfs->len; i++) {
- if (!nm_sriov_vf_equal (a->vfs->pdata[i], b->vfs->pdata[i]))
+ if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_SRIOV_VFS)) {
+ if (other) {
+ a = NM_SETTING_SRIOV (setting);
+ b = NM_SETTING_SRIOV (other);
+
+ if (a->vfs->len != b->vfs->len)
return FALSE;
+ for (i = 0; i < a->vfs->len; i++) {
+ if (!nm_sriov_vf_equal (a->vfs->pdata[i], b->vfs->pdata[i]))
+ return FALSE;
+ }
}
return TRUE;
}
- setting_class = NM_SETTING_CLASS (nm_setting_sriov_parent_class);
- return setting_class->compare_property (setting, other, prop_spec, flags);
+ return NM_SETTING_CLASS (nm_setting_sriov_parent_class)->compare_property (sett_info,
+ property_idx,
+ setting,
+ other,
+ flags);
}
static void
diff --git a/libnm-core/nm-setting-tc-config.c b/libnm-core/nm-setting-tc-config.c
index 43015d3708..4fe3c0fd96 100644
--- a/libnm-core/nm-setting-tc-config.c
+++ b/libnm-core/nm-setting-tc-config.c
@@ -1233,39 +1233,46 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
return TRUE;
}
-static gboolean
-compare_property (NMSetting *setting,
+static NMTernary
+compare_property (const NMSettInfoSetting *sett_info,
+ guint property_idx,
+ NMSetting *setting,
NMSetting *other,
- const GParamSpec *prop_spec,
NMSettingCompareFlags flags)
{
NMSettingTCConfig *a_tc_config = NM_SETTING_TC_CONFIG (setting);
NMSettingTCConfig *b_tc_config = NM_SETTING_TC_CONFIG (other);
- NMSettingClass *setting_class;
guint i;
- if (nm_streq (prop_spec->name, NM_SETTING_TC_CONFIG_QDISCS)) {
- if (a_tc_config->qdiscs->len != b_tc_config->qdiscs->len)
- return FALSE;
- for (i = 0; i < a_tc_config->qdiscs->len; i++) {
- if (!nm_tc_qdisc_equal (a_tc_config->qdiscs->pdata[i], b_tc_config->qdiscs->pdata[i]))
+ if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_TC_CONFIG_QDISCS)) {
+ if (other) {
+ if (a_tc_config->qdiscs->len != b_tc_config->qdiscs->len)
return FALSE;
+ for (i = 0; i < a_tc_config->qdiscs->len; i++) {
+ if (!nm_tc_qdisc_equal (a_tc_config->qdiscs->pdata[i], b_tc_config->qdiscs->pdata[i]))
+ return FALSE;
+ }
}
return TRUE;
}
- if (nm_streq (prop_spec->name, NM_SETTING_TC_CONFIG_TFILTERS)) {
- if (a_tc_config->tfilters->len != b_tc_config->tfilters->len)
- return FALSE;
- for (i = 0; i < a_tc_config->tfilters->len; i++) {
- if (!nm_tc_tfilter_equal (a_tc_config->tfilters->pdata[i], b_tc_config->tfilters->pdata[i]))
+ if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_TC_CONFIG_TFILTERS)) {
+ if (other) {
+ if (a_tc_config->tfilters->len != b_tc_config->tfilters->len)
return FALSE;
+ for (i = 0; i < a_tc_config->tfilters->len; i++) {
+ if (!nm_tc_tfilter_equal (a_tc_config->tfilters->pdata[i], b_tc_config->tfilters->pdata[i]))
+ return FALSE;
+ }
}
return TRUE;
}
- setting_class = NM_SETTING_CLASS (nm_setting_tc_config_parent_class);
- return setting_class->compare_property (setting, other, prop_spec, flags);
+ return NM_SETTING_CLASS (nm_setting_tc_config_parent_class)->compare_property (sett_info,
+ property_idx,
+ setting,
+ other,
+ flags);
}
static void
diff --git a/libnm-core/nm-setting-team-port.c b/libnm-core/nm-setting-team-port.c
index 1901386c62..3ba2d44e08 100644
--- a/libnm-core/nm-setting-team-port.c
+++ b/libnm-core/nm-setting-team-port.c
@@ -401,48 +401,68 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
return TRUE;
}
-static gboolean
-compare_property (NMSetting *setting,
+static NMTernary
+compare_property (const NMSettInfoSetting *sett_info,
+ guint property_idx,
+ NMSetting *setting,
NMSetting *other,
- const GParamSpec *prop_spec,
NMSettingCompareFlags flags)
{
- NMSettingClass *setting_class;
- NMSettingTeamPortPrivate *a_priv, *b_priv;
+ NMSettingTeamPortPrivate *a_priv;
+ NMSettingTeamPortPrivate *b_priv;
guint i, j;
- /* If we are trying to match a connection in order to assume it (and thus
- * @flags contains INFERRABLE), use the "relaxed" matching for team
- * configuration. Otherwise, for all other purposes (including connection
- * comparison before an update), resort to the default string comparison.
- */
- if ( NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)
- && nm_streq0 (prop_spec->name, NM_SETTING_TEAM_PORT_CONFIG)) {
- return _nm_utils_team_config_equal (NM_SETTING_TEAM_PORT_GET_PRIVATE (setting)->config,
- NM_SETTING_TEAM_PORT_GET_PRIVATE (other)->config,
- TRUE);
- }
- if (nm_streq0 (prop_spec->name, NM_SETTING_TEAM_PORT_LINK_WATCHERS)) {
- a_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
- b_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (other);
+ if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_TEAM_PORT_LINK_WATCHERS)) {
- if (a_priv->link_watchers->len != b_priv->link_watchers->len)
- return FALSE;
- for (i = 0; i < a_priv->link_watchers->len; i++) {
- for (j = 0; j < b_priv->link_watchers->len; j++) {
- if (nm_team_link_watcher_equal (a_priv->link_watchers->pdata[i],
- b_priv->link_watchers->pdata[j])) {
- break;
+ if (NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE))
+ return NM_TERNARY_DEFAULT;
+
+ if (other) {
+ a_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
+ b_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (other);
+
+ if (a_priv->link_watchers->len != b_priv->link_watchers->len)
+ return FALSE;
+ for (i = 0; i < a_priv->link_watchers->len; i++) {
+ for (j = 0; j < b_priv->link_watchers->len; j++) {
+ if (nm_team_link_watcher_equal (a_priv->link_watchers->pdata[i],
+ b_priv->link_watchers->pdata[j])) {
+ break;
+ }
}
+ if (j == b_priv->link_watchers->len)
+ return FALSE;
}
- if (j == b_priv->link_watchers->len)
- return FALSE;
}
return TRUE;
}
- setting_class = NM_SETTING_CLASS (nm_setting_team_port_parent_class);
- return setting_class->compare_property (setting, other, prop_spec, flags);
+ if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_TEAM_PORT_CONFIG)) {
+ if (other) {
+ a_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (setting);
+ b_priv = NM_SETTING_TEAM_PORT_GET_PRIVATE (other);
+
+ if (NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) {
+ /* If we are trying to match a connection in order to assume it (and thus
+ * @flags contains INFERRABLE), use the "relaxed" matching for team
+ * configuration. Otherwise, for all other purposes (including connection
+ * comparison before an update), resort to the default string comparison. */
+ return _nm_utils_team_config_equal (a_priv->config,
+ b_priv->config,
+ TRUE);
+ }
+
+ return nm_streq0 (a_priv->config, b_priv->config);
+ }
+
+ return TRUE;
+ }
+
+ return NM_SETTING_CLASS (nm_setting_team_port_parent_class)->compare_property (sett_info,
+ property_idx,
+ setting,
+ other,
+ flags);
}
static void
diff --git a/libnm-core/nm-setting-team.c b/libnm-core/nm-setting-team.c
index 0ca47e83fa..4021aa0cb8 100644
--- a/libnm-core/nm-setting-team.c
+++ b/libnm-core/nm-setting-team.c
@@ -1297,38 +1297,33 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
return TRUE;
}
-static gboolean
-compare_property (NMSetting *setting,
+static NMTernary
+compare_property (const NMSettInfoSetting *sett_info,
+ guint property_idx,
+ NMSetting *setting,
NMSetting *other,
- const GParamSpec *prop_spec,
NMSettingCompareFlags flags)
{
NMSettingTeamPrivate *a_priv, *b_priv;
- NMSettingClass *setting_class;
guint i, j;
- /* If we are trying to match a connection in order to assume it (and thus
- * @flags contains INFERRABLE), use the "relaxed" matching for team
- * configuration. Otherwise, for all other purposes (including connection
- * comparison before an update), resort to the default string comparison.
- */
- if ( NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)
- && nm_streq0 (prop_spec->name, NM_SETTING_TEAM_CONFIG)) {
- return _nm_utils_team_config_equal (NM_SETTING_TEAM_GET_PRIVATE (setting)->config,
- NM_SETTING_TEAM_GET_PRIVATE (other)->config,
- FALSE);
- }
- if (nm_streq0 (prop_spec->name, NM_SETTING_TEAM_LINK_WATCHERS)) {
- a_priv = NM_SETTING_TEAM_GET_PRIVATE (setting);
- b_priv = NM_SETTING_TEAM_GET_PRIVATE (other);
+ if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_TEAM_LINK_WATCHERS)) {
- if (a_priv->link_watchers->len != b_priv->link_watchers->len)
- return FALSE;
- for (i = 0; i < a_priv->link_watchers->len; i++) {
- for (j = 0; j < b_priv->link_watchers->len; j++) {
- if (nm_team_link_watcher_equal (a_priv->link_watchers->pdata[i],
- b_priv->link_watchers->pdata[j])) {
- break;
+ if (NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE))
+ return NM_TERNARY_DEFAULT;
+
+ if (other) {
+ a_priv = NM_SETTING_TEAM_GET_PRIVATE (setting);
+ b_priv = NM_SETTING_TEAM_GET_PRIVATE (other);
+
+ if (a_priv->link_watchers->len != b_priv->link_watchers->len)
+ return FALSE;
+ for (i = 0; i < a_priv->link_watchers->len; i++) {
+ for (j = 0; j < b_priv->link_watchers->len; j++) {
+ if (nm_team_link_watcher_equal (a_priv->link_watchers->pdata[i],
+ b_priv->link_watchers->pdata[j])) {
+ break;
+ }
}
if (j == b_priv->link_watchers->len)
return FALSE;
@@ -1337,8 +1332,32 @@ compare_property (NMSetting *setting,
return TRUE;
}
- setting_class = NM_SETTING_CLASS (nm_setting_team_parent_class);
- return setting_class->compare_property (setting, other, prop_spec, flags);
+ if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_TEAM_CONFIG)) {
+ if (other) {
+ a_priv = NM_SETTING_TEAM_GET_PRIVATE (setting);
+ b_priv = NM_SETTING_TEAM_GET_PRIVATE (other);
+
+ if (NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)) {
+ /* If we are trying to match a connection in order to assume it (and thus
+ * @flags contains INFERRABLE), use the "relaxed" matching for team
+ * configuration. Otherwise, for all other purposes (including connection
+ * comparison before an update), resort to the default string comparison. */
+ return _nm_utils_team_config_equal (a_priv->config,
+ b_priv->config,
+ TRUE);
+ }
+
+ return nm_streq0 (a_priv->config, b_priv->config);
+ }
+
+ return TRUE;
+ }
+
+ return NM_SETTING_CLASS (nm_setting_team_parent_class)->compare_property (sett_info,
+ property_idx,
+ setting,
+ other,
+ flags);
}
static void
diff --git a/libnm-core/nm-setting-user.c b/libnm-core/nm-setting-user.c
index d72c909462..cef02092c8 100644
--- a/libnm-core/nm-setting-user.c
+++ b/libnm-core/nm-setting-user.c
@@ -395,33 +395,34 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
return TRUE;
}
-static gboolean
-compare_property (NMSetting *setting,
+static NMTernary
+compare_property (const NMSettInfoSetting *sett_info,
+ guint property_idx,
+ NMSetting *setting,
NMSetting *other,
- const GParamSpec *prop_spec,
NMSettingCompareFlags flags)
{
NMSettingUserPrivate *priv, *pri2;
- g_return_val_if_fail (NM_IS_SETTING_USER (setting), FALSE);
- g_return_val_if_fail (NM_IS_SETTING_USER (other), FALSE);
-
- if (!nm_streq0 (prop_spec->name, NM_SETTING_USER_DATA))
- goto call_parent;
+ if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_USER_DATA)) {
- priv = NM_SETTING_USER_GET_PRIVATE (NM_SETTING_USER (setting));
- pri2 = NM_SETTING_USER_GET_PRIVATE (NM_SETTING_USER (other));
-
- if (!nm_utils_hash_table_equal (priv->data, pri2->data, TRUE, g_str_equal))
- return FALSE;
+ if (NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE))
+ return NM_TERNARY_DEFAULT;
- if (!nm_utils_hash_table_equal (priv->data_invalid, pri2->data_invalid, TRUE, g_str_equal))
- return FALSE;
+ if (!other)
+ return TRUE;
- return TRUE;
+ priv = NM_SETTING_USER_GET_PRIVATE (NM_SETTING_USER (setting));
+ pri2 = NM_SETTING_USER_GET_PRIVATE (NM_SETTING_USER (other));
+ return nm_utils_hash_table_equal (priv->data, pri2->data, TRUE, g_str_equal)
+ && nm_utils_hash_table_equal (priv->data_invalid, pri2->data_invalid, TRUE, g_str_equal);
+ }
-call_parent:
- return NM_SETTING_CLASS (nm_setting_user_parent_class)->compare_property (setting, other, prop_spec, flags);
+ return NM_SETTING_CLASS (nm_setting_user_parent_class)->compare_property (sett_info,
+ property_idx,
+ setting,
+ other,
+ flags);
}
/*****************************************************************************/
diff --git a/libnm-core/nm-setting-vpn.c b/libnm-core/nm-setting-vpn.c
index d485b2a802..b0c13b1573 100644
--- a/libnm-core/nm-setting-vpn.c
+++ b/libnm-core/nm-setting-vpn.c
@@ -765,77 +765,63 @@ need_secrets (NMSetting *setting)
return g_ptr_array_sized_new (1);
}
-static gboolean
-_compare_secrets (NMSettingVpn *a,
- NMSettingVpn *b,
- NMSettingCompareFlags flags)
+static NMTernary
+compare_property_secrets (NMSettingVpn *a,
+ NMSettingVpn *b,
+ NMSettingCompareFlags flags)
{
- GHashTable *a_secrets;
GHashTableIter iter;
const char *key, *val;
+ int run;
- a_secrets = NM_SETTING_VPN_GET_PRIVATE (a)->secrets;
- g_hash_table_iter_init (&iter, a_secrets);
- while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &val)) {
- NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
- NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+ if (NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_FUZZY))
+ return NM_TERNARY_DEFAULT;
+ if (NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS))
+ return NM_TERNARY_DEFAULT;
- nm_setting_get_secret_flags (NM_SETTING (a), key, &a_secret_flags, NULL);
- nm_setting_get_secret_flags (NM_SETTING (b), key, &b_secret_flags, NULL);
+ if (!b)
+ return TRUE;
- /* If the secret flags aren't the same, the settings aren't the same */
- if (a_secret_flags != b_secret_flags)
- return FALSE;
+ for (run = 0; run < 2; run++) {
+ NMSettingVpn *current_a = (run == 0) ? a : b;
+ NMSettingVpn *current_b = (run == 0) ? b : a;
- if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
- && (a_secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
- continue;
+ g_hash_table_iter_init (&iter, NM_SETTING_VPN_GET_PRIVATE (current_a)->secrets);
+ while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &val)) {
- if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
- && (a_secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
- continue;
+ if (nm_streq0 (val, nm_setting_vpn_get_secret (current_b, key)))
+ continue;
+ if (!_nm_setting_should_compare_secret_property (NM_SETTING (current_a),
+ NM_SETTING (current_b),
+ key,
+ flags))
+ continue;
- /* Now compare the values themselves */
- if (g_strcmp0 (val, nm_setting_vpn_get_secret (b, key)) != 0)
return FALSE;
+ }
}
return TRUE;
}
-static gboolean
-compare_one_secret (NMSettingVpn *a,
- NMSettingVpn *b,
- NMSettingCompareFlags flags)
-{
- if (!_compare_secrets (a, b, flags))
- return FALSE;
- if (!_compare_secrets (b, a, flags))
- return FALSE;
-
- return TRUE;
-}
-
-static gboolean
-compare_property (NMSetting *setting,
+static NMTernary
+compare_property (const NMSettInfoSetting *sett_info,
+ guint property_idx,
+ NMSetting *setting,
NMSetting *other,
- const GParamSpec *prop_spec,
NMSettingCompareFlags flags)
{
- gboolean same;
-
- /* We only need to treat the 'secrets' property specially */
- if (g_strcmp0 (prop_spec->name, NM_SETTING_VPN_SECRETS) != 0)
- return NM_SETTING_CLASS (nm_setting_vpn_parent_class)->compare_property (setting, other, prop_spec, flags);
-
- /* Compare A to B to ensure everything in A is found in B */
- same = compare_one_secret (NM_SETTING_VPN (setting), NM_SETTING_VPN (other), flags);
- if (same) {
- /* And then B to A to ensure everything in B is also found in A */
- same = compare_one_secret (NM_SETTING_VPN (other), NM_SETTING_VPN (setting), flags);
+ if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_VPN_SECRETS)) {
+ if (NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE))
+ return NM_TERNARY_DEFAULT;
+ return compare_property_secrets (NM_SETTING_VPN (setting), NM_SETTING_VPN (other), flags);
}
- return same;
+ return NM_SETTING_CLASS (nm_setting_vpn_parent_class)->compare_property (sett_info,
+ property_idx,
+ setting,
+ other,
+ flags);
}
static gboolean
diff --git a/libnm-core/nm-setting-wired.c b/libnm-core/nm-setting-wired.c
index 5a005b2f63..96467c02c3 100644
--- a/libnm-core/nm-setting-wired.c
+++ b/libnm-core/nm-setting-wired.c
@@ -775,21 +775,25 @@ verify (NMSetting *setting, NMConnection *connection, GError **error)
return TRUE;
}
-static gboolean
-compare_property (NMSetting *setting,
+static NMTernary
+compare_property (const NMSettInfoSetting *sett_info,
+ guint property_idx,
+ NMSetting *setting,
NMSetting *other,
- const GParamSpec *prop_spec,
NMSettingCompareFlags flags)
{
- NMSettingClass *setting_class;
- if (nm_streq (prop_spec->name, NM_SETTING_WIRED_CLONED_MAC_ADDRESS)) {
- return nm_streq0 (NM_SETTING_WIRED_GET_PRIVATE (setting)->cloned_mac_address,
- NM_SETTING_WIRED_GET_PRIVATE (other)->cloned_mac_address);
+ if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_WIRED_CLONED_MAC_ADDRESS)) {
+ return !other
+ || nm_streq0 (NM_SETTING_WIRED_GET_PRIVATE (setting)->cloned_mac_address,
+ NM_SETTING_WIRED_GET_PRIVATE (other)->cloned_mac_address);
}
- setting_class = NM_SETTING_CLASS (nm_setting_wired_parent_class);
- return setting_class->compare_property (setting, other, prop_spec, flags);
+ return NM_SETTING_CLASS (nm_setting_wired_parent_class)->compare_property (sett_info,
+ property_idx,
+ setting,
+ other,
+ flags);
}
static GVariant *
diff --git a/libnm-core/nm-setting-wireless.c b/libnm-core/nm-setting-wireless.c
index cfa79b54f6..dcba8d81e3 100644
--- a/libnm-core/nm-setting-wireless.c
+++ b/libnm-core/nm-setting-wireless.c
@@ -929,21 +929,24 @@ mac_addr_rand_ok:
return TRUE;
}
-static gboolean
-compare_property (NMSetting *setting,
+static NMTernary
+compare_property (const NMSettInfoSetting *sett_info,
+ guint property_idx,
+ NMSetting *setting,
NMSetting *other,
- const GParamSpec *prop_spec,
NMSettingCompareFlags flags)
{
- NMSettingClass *setting_class;
-
- if (nm_streq (prop_spec->name, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS)) {
- return nm_streq0 (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->cloned_mac_address,
- NM_SETTING_WIRELESS_GET_PRIVATE (other)->cloned_mac_address);
+ if (nm_streq (sett_info->property_infos[property_idx].name, NM_SETTING_WIRELESS_CLONED_MAC_ADDRESS)) {
+ return !other
+ || nm_streq0 (NM_SETTING_WIRELESS_GET_PRIVATE (setting)->cloned_mac_address,
+ NM_SETTING_WIRELESS_GET_PRIVATE (other)->cloned_mac_address);
}
- setting_class = NM_SETTING_CLASS (nm_setting_wireless_parent_class);
- return setting_class->compare_property (setting, other, prop_spec, flags);
+ return NM_SETTING_CLASS (nm_setting_wireless_parent_class)->compare_property (sett_info,
+ property_idx,
+ setting,
+ other,
+ flags);
}
/*****************************************************************************/
diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c
index ab4567ca5c..bea47b3509 100644
--- a/libnm-core/nm-setting.c
+++ b/libnm-core/nm-setting.c
@@ -86,11 +86,6 @@ G_DEFINE_ABSTRACT_TYPE (NMSetting, nm_setting, G_TYPE_OBJECT)
static GenData *_gendata_hash (NMSetting *setting, gboolean create_if_necessary);
-static gboolean should_compare_prop (gboolean for_diff,
- NMSetting *setting,
- const NMSettInfoProperty *property_info,
- NMSettingCompareFlags comp_flags);
-
/*****************************************************************************/
static NMSettingPriority
@@ -1246,58 +1241,148 @@ _nm_setting_verify_secret_string (const char *str,
return TRUE;
}
-static gboolean
-compare_property (NMSetting *setting,
+gboolean
+_nm_setting_should_compare_secret_property (NMSetting *setting,
+ NMSetting *other,
+ const char *secret_name,
+ NMSettingCompareFlags flags)
+{
+ NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+ NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+
+ nm_assert (NM_IS_SETTING (setting));
+ nm_assert (!other || G_OBJECT_TYPE (setting) == G_OBJECT_TYPE (other));
+
+ /* secret_name must be a valid secret for @setting. */
+ nm_assert (nm_setting_get_secret_flags (setting, secret_name, NULL, NULL));
+
+ if (!NM_FLAGS_ANY (flags, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS
+ | NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS))
+ return TRUE;
+
+ nm_setting_get_secret_flags (setting, secret_name, &a_secret_flags, NULL);
+ if (other) {
+ if (!nm_setting_get_secret_flags (other, secret_name, &b_secret_flags, NULL)) {
+ /* secret-name may not be a valid secret for @other. That is fine, we ignore that
+ * and treat @b_secret_flags as NM_SETTING_SECRET_FLAG_NONE.
+ *
+ * This can happen with VPN secrets, where the caller knows that @secret_name
+ * is a secret for setting, but it may not be a secret for @other. Accept that.
+ *
+ * Mark @other as missing. */
+ other = NULL;
+ }
+ }
+
+ /* when @setting has the secret-flags that should be ignored,
+ * we skip the comparisong if:
+ *
+ * - @other is not present,
+ * - @other does not have a secret named @secret_name
+ * - @other also has the secret flat to be ignored.
+ *
+ * This makes the check symmetric (aside the fact that @setting must
+ * have the secret while @other may not -- which is asymetric). */
+ if ( NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
+ && NM_FLAGS_HAS (a_secret_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)
+ && ( !other
+ || NM_FLAGS_HAS (b_secret_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED)))
+ return FALSE;
+
+ if ( NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
+ && NM_FLAGS_HAS (a_secret_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED)
+ && ( !other
+ || NM_FLAGS_HAS (b_secret_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED)))
+ return FALSE;
+
+ return TRUE;
+}
+
+static NMTernary
+compare_property (const NMSettInfoSetting *sett_info,
+ guint property_idx,
+ NMSetting *setting,
NMSetting *other,
- const GParamSpec *prop_spec,
NMSettingCompareFlags flags)
{
- const NMSettInfoProperty *property;
- GVariant *value1, *value2;
- int cmp;
+ const NMSettInfoProperty *property_info = &sett_info->property_infos[property_idx];
+ const GParamSpec *param_spec = property_info->param_spec;
+
+ if (!param_spec)
+ return NM_TERNARY_DEFAULT;
- /* Handle compare flags */
- if (prop_spec->flags & NM_SETTING_PARAM_SECRET) {
- NMSettingSecretFlags a_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
- NMSettingSecretFlags b_secret_flags = NM_SETTING_SECRET_FLAG_NONE;
+ if ( NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_FUZZY)
+ && NM_FLAGS_ANY (param_spec->flags, NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET))
+ return NM_TERNARY_DEFAULT;
- g_return_val_if_fail (!NM_IS_SETTING_VPN (setting), FALSE);
+ if ( NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)
+ && !NM_FLAGS_HAS (param_spec->flags, NM_SETTING_PARAM_INFERRABLE))
+ return NM_TERNARY_DEFAULT;
- if (!nm_setting_get_secret_flags (setting, prop_spec->name, &a_secret_flags, NULL))
- g_return_val_if_reached (FALSE);
- if (!nm_setting_get_secret_flags (other, prop_spec->name, &b_secret_flags, NULL))
- g_return_val_if_reached (FALSE);
+ if ( NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY)
+ && NM_FLAGS_HAS (param_spec->flags, NM_SETTING_PARAM_REAPPLY_IMMEDIATELY))
+ return NM_TERNARY_DEFAULT;
- /* If the secret flags aren't the same the settings aren't the same */
- if (a_secret_flags != b_secret_flags)
- return FALSE;
+ if ( NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
+ && NM_FLAGS_HAS (param_spec->flags, NM_SETTING_PARAM_SECRET))
+ return NM_TERNARY_DEFAULT;
- /* Check for various secret flags that might cause us to ignore comparing
- * this property.
- */
- if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
- && (a_secret_flags & NM_SETTING_SECRET_FLAG_AGENT_OWNED))
- return TRUE;
+ if (nm_streq (param_spec->name, NM_SETTING_NAME))
+ return NM_TERNARY_DEFAULT;
- if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
- && (a_secret_flags & NM_SETTING_SECRET_FLAG_NOT_SAVED))
- return TRUE;
+ if ( NM_FLAGS_HAS (param_spec->flags, NM_SETTING_PARAM_SECRET)
+ && !_nm_setting_should_compare_secret_property (setting,
+ other,
+ param_spec->name,
+ flags))
+ return NM_TERNARY_DEFAULT;
+
+ if (other) {
+ gs_unref_variant GVariant *value1 = NULL;
+ gs_unref_variant GVariant *value2 = NULL;
+
+ value1 = get_property_for_dbus (setting, property_info, TRUE);
+ value2 = get_property_for_dbus (other, property_info, TRUE);
+
+ if (nm_property_compare (value1, value2) != 0)
+ return NM_TERNARY_FALSE;
}
- property = _nm_sett_info_property_get (NM_SETTING_GET_CLASS (setting), prop_spec->name);
- g_return_val_if_fail (property != NULL, FALSE);
+ return NM_TERNARY_TRUE;
+}
+
+static NMTernary
+_compare_property (const NMSettInfoSetting *sett_info,
+ guint property_idx,
+ NMSetting *setting,
+ NMSetting *other,
+ NMSettingCompareFlags flags)
+{
+ NMTernary compare_result;
+
+ nm_assert (sett_info);
+ nm_assert (NM_IS_SETTING_CLASS (sett_info->setting_class));
+ nm_assert (property_idx < sett_info->property_infos_len);
+ nm_assert (NM_SETTING_GET_CLASS (setting) == sett_info->setting_class);
+ nm_assert (!other || NM_SETTING_GET_CLASS (other) == sett_info->setting_class);
- value1 = get_property_for_dbus (setting, property, TRUE);
- value2 = get_property_for_dbus (other, property, TRUE);
+ compare_result = NM_SETTING_GET_CLASS (setting)->compare_property (sett_info,
+ property_idx,
+ setting,
+ other,
+ flags);
- cmp = nm_property_compare (value1, value2);
+ nm_assert (NM_IN_SET (compare_result, NM_TERNARY_DEFAULT,
+ NM_TERNARY_FALSE,
+ NM_TERNARY_TRUE));
- if (value1)
- g_variant_unref (value1);
- if (value2)
- g_variant_unref (value2);
+ /* check that the inferable flag and the GObject property flag corresponds. */
+ nm_assert ( !NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)
+ || !sett_info->property_infos[property_idx].param_spec
+ || NM_FLAGS_HAS (sett_info->property_infos[property_idx].param_spec->flags, NM_SETTING_PARAM_INFERRABLE)
+ || compare_result == NM_TERNARY_DEFAULT);
- return cmp == 0;
+ return compare_result;
}
/**
@@ -1340,89 +1425,13 @@ nm_setting_compare (NMSetting *a,
}
for (i = 0; i < sett_info->property_infos_len; i++) {
- const NMSettInfoProperty *property_info = &sett_info->property_infos[i];
-
- if (!should_compare_prop (FALSE, a, property_info, flags))
- continue;
-
- if (!NM_SETTING_GET_CLASS (a)->compare_property (a, b, property_info->param_spec, flags))
+ if (_compare_property (sett_info, i, a, b, flags) == NM_TERNARY_FALSE)
return FALSE;
}
return TRUE;
}
-static gboolean
-should_compare_prop (gboolean for_diff,
- NMSetting *setting,
- const NMSettInfoProperty *property_info,
- NMSettingCompareFlags comp_flags)
-{
- const GParamSpec *param_spec = property_info->param_spec;
-
- if (!param_spec)
- return FALSE;
-
- if ( NM_FLAGS_HAS (comp_flags, NM_SETTING_COMPARE_FLAG_FUZZY)
- && NM_FLAGS_ANY (param_spec->flags, NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET))
- return FALSE;
-
- if ( NM_FLAGS_HAS (comp_flags, NM_SETTING_COMPARE_FLAG_INFERRABLE)
- && !NM_FLAGS_HAS (param_spec->flags, NM_SETTING_PARAM_INFERRABLE))
- return FALSE;
-
- if ( NM_FLAGS_HAS (comp_flags, NM_SETTING_COMPARE_FLAG_IGNORE_REAPPLY_IMMEDIATELY)
- && NM_FLAGS_HAS (param_spec->flags, NM_SETTING_PARAM_REAPPLY_IMMEDIATELY))
- return FALSE;
-
- if ( NM_FLAGS_HAS (comp_flags, NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
- && NM_FLAGS_HAS (param_spec->flags, NM_SETTING_PARAM_SECRET))
- return FALSE;
-
- if (nm_streq (param_spec->name, NM_SETTING_NAME))
- return FALSE;
-
- if ( for_diff
- && NM_FLAGS_ANY (comp_flags, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS
- | NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
- && NM_FLAGS_HAS (param_spec->flags, NM_SETTING_PARAM_SECRET)) {
- NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE;
-
- if ( NM_IS_SETTING_VPN (setting)
- && nm_streq (param_spec->name, NM_SETTING_VPN_SECRETS)) {
- /* FIXME: NMSettingVPN:NM_SETTING_VPN_SECRETS has NM_SETTING_PARAM_SECRET.
- * nm_setting_get_secret_flags() quite possibly fails, but it might succeed if the
- * setting accidentally uses a key "secrets". */
- return TRUE;
- }
-
- if (!nm_setting_get_secret_flags (setting, param_spec->name, &secret_flags, NULL))
- g_return_val_if_reached (FALSE);
-
- if ( NM_FLAGS_HAS (comp_flags, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS)
- && NM_FLAGS_HAS (secret_flags, NM_SETTING_SECRET_FLAG_AGENT_OWNED))
- return FALSE;
-
- if ( NM_FLAGS_HAS (comp_flags, NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
- && NM_FLAGS_HAS (secret_flags, NM_SETTING_SECRET_FLAG_NOT_SAVED))
- return FALSE;
- }
-
- if ( for_diff
- && NM_FLAGS_HAS (comp_flags, NM_SETTING_COMPARE_FLAG_IGNORE_ID)
- && NM_IS_SETTING_CONNECTION (setting)
- && nm_streq (param_spec->name, NM_SETTING_CONNECTION_ID))
- return FALSE;
-
- if ( for_diff
- && NM_FLAGS_HAS (comp_flags, NM_SETTING_COMPARE_FLAG_IGNORE_TIMESTAMP)
- && NM_IS_SETTING_CONNECTION (setting)
- && nm_streq (param_spec->name, NM_SETTING_CONNECTION_TIMESTAMP))
- return FALSE;
-
- return TRUE;
-}
-
static void
_setting_diff_add_result (GHashTable *results, const char *prop_name, NMSettingDiffResult r)
{
@@ -1554,65 +1563,92 @@ nm_setting_diff (NMSetting *a,
}
} else {
for (i = 0; i < sett_info->property_infos_len; i++) {
- const NMSettInfoProperty *property_info = &sett_info->property_infos[i];
- GParamSpec *prop_spec;
NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN;
+ const NMSettInfoProperty *property_info;
+ NMTernary compare_result;
+ GParamSpec *prop_spec;
- if (!should_compare_prop (TRUE, a, property_info, flags))
+ compare_result = _compare_property (sett_info, i, a, b, flags);
+ if (compare_result == NM_TERNARY_DEFAULT)
continue;
- prop_spec = property_info->param_spec;
+ if ( NM_FLAGS_ANY (flags, NM_SETTING_COMPARE_FLAG_IGNORE_AGENT_OWNED_SECRETS
+ | NM_SETTING_COMPARE_FLAG_IGNORE_NOT_SAVED_SECRETS)
+ && b
+ && compare_result == NM_TERNARY_FALSE) {
+ /* we have setting @b and the property is not the same. But we also are instructed
+ * to ignore secrets based on the flags.
+ *
+ * Note that compare_property() called with two settings will ignore secrets
+ * based on the flags, but it will do so if *both* settings have the flag we
+ * look for. So that is symetric behavior and good.
+ *
+ * But for the purpose of diff(), we do a asymmetric comparison because and
+ * we want to skip testing the property if setting @a alone indicates to do
+ * so.
+ *
+ * We need to double-check whether the property should be ignored by
+ * looking at @a alone. */
+ if (_compare_property (sett_info, i, a, NULL, flags) == NM_TERNARY_DEFAULT)
+ continue;
+ }
compared_any = TRUE;
- if (b) {
- gboolean different;
-
- different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags);
- if (different) {
- gboolean a_is_default, b_is_default;
- GValue value = G_VALUE_INIT;
-
- g_value_init (&value, prop_spec->value_type);
- g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
- a_is_default = g_param_value_defaults (prop_spec, &value);
-
- g_value_reset (&value);
- g_object_get_property (G_OBJECT (b), prop_spec->name, &value);
- b_is_default = g_param_value_defaults (prop_spec, &value);
+ property_info = &sett_info->property_infos[i];
+ prop_spec = property_info->param_spec;
- g_value_unset (&value);
- if ((flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT) == 0) {
- if (!a_is_default)
- r |= a_result;
- if (!b_is_default)
- r |= b_result;
- } else {
+ if (b) {
+ if (compare_result == NM_TERNARY_FALSE) {
+ if (prop_spec) {
+ gboolean a_is_default, b_is_default;
+ GValue value = G_VALUE_INIT;
+
+ g_value_init (&value, prop_spec->value_type);
+ g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
+ a_is_default = g_param_value_defaults (prop_spec, &value);
+
+ g_value_reset (&value);
+ g_object_get_property (G_OBJECT (b), prop_spec->name, &value);
+ b_is_default = g_param_value_defaults (prop_spec, &value);
+
+ g_value_unset (&value);
+ if (!NM_FLAGS_HAS (flags, NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT)) {
+ if (!a_is_default)
+ r |= a_result;
+ if (!b_is_default)
+ r |= b_result;
+ } else {
+ r |= a_result | b_result;
+ if (a_is_default)
+ r |= a_result_default;
+ if (b_is_default)
+ r |= b_result_default;
+ }
+ } else
r |= a_result | b_result;
- if (a_is_default)
- r |= a_result_default;
- if (b_is_default)
- r |= b_result_default;
- }
}
} else if ((flags & (NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT | NM_SETTING_COMPARE_FLAG_DIFF_RESULT_NO_DEFAULT)) == 0)
r = a_result; /* only in A */
else {
- GValue value = G_VALUE_INIT;
+ if (prop_spec) {
+ GValue value = G_VALUE_INIT;
- g_value_init (&value, prop_spec->value_type);
- g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
- if (!g_param_value_defaults (prop_spec, &value))
- r |= a_result;
- else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT)
- r |= a_result | a_result_default;
+ g_value_init (&value, prop_spec->value_type);
+ g_object_get_property (G_OBJECT (a), prop_spec->name, &value);
+ if (!g_param_value_defaults (prop_spec, &value))
+ r |= a_result;
+ else if (flags & NM_SETTING_COMPARE_FLAG_DIFF_RESULT_WITH_DEFAULT)
+ r |= a_result | a_result_default;
- g_value_unset (&value);
+ g_value_unset (&value);
+ } else
+ r |= a_result;
}
if (r != NM_SETTING_DIFF_RESULT_UNKNOWN) {
diff_found = TRUE;
- _setting_diff_add_result (*results, prop_spec->name, r);
+ _setting_diff_add_result (*results, property_info->name, r);
}
}
}
diff --git a/libnm-core/nm-setting.h b/libnm-core/nm-setting.h
index 3576bdc663..326b533f12 100644
--- a/libnm-core/nm-setting.h
+++ b/libnm-core/nm-setting.h
@@ -169,6 +169,7 @@ typedef gboolean (*NMSettingClearSecretsWithFlagsFn) (NMSetting *setting,
gpointer user_data);
struct _NMMetaSettingInfo;
+struct _NMSettInfoSetting;
typedef struct {
GObjectClass parent;
@@ -204,11 +205,18 @@ typedef struct {
NMSettingClearSecretsWithFlagsFn func,
gpointer user_data);
- /* Returns TRUE if the given property contains the same value in both settings */
- gboolean (*compare_property) (NMSetting *setting,
- NMSetting *other,
- const GParamSpec *prop_spec,
- NMSettingCompareFlags flags);
+ /* compare_property() returns a ternary, where DEFAULT means that the property should not
+ * be compared due to the compare @flags. A TRUE/FALSE result means that the property is
+ * equal/not-equal.
+ *
+ * @other may be %NULL, in which case the function only determines whether
+ * the setting should be compared (TRUE) or not (DEFAULT). */
+ /*< private >*/
+ NMTernary (*compare_property) (const struct _NMSettInfoSetting *sett_info,
+ guint property_idx,
+ NMSetting *setting,
+ NMSetting *other,
+ NMSettingCompareFlags flags);
/*< private >*/
const struct _NMMetaSettingInfo *setting_info;