summaryrefslogtreecommitdiff
path: root/libnm-util/nm-setting.c
diff options
context:
space:
mode:
authorDan Williams <dcbw@redhat.com>2011-02-22 23:36:43 -0600
committerDan Williams <dcbw@redhat.com>2011-02-22 23:36:43 -0600
commit54918e32e49c26c3f6289a1743e6eb2b02eb215e (patch)
tree5c8575594ac5908fd483e7b3628afb5bae4c2b6c /libnm-util/nm-setting.c
parent5444a3569352312118e3ad0b37f61afc5842b190 (diff)
downloadNetworkManager-54918e32e49c26c3f6289a1743e6eb2b02eb215e.tar.gz
libnm-util: add nm_connection_diff()
Returns a list of keys that differ between the settings in each connection. nm_connection_compare() can't do that.
Diffstat (limited to 'libnm-util/nm-setting.c')
-rw-r--r--libnm-util/nm-setting.c150
1 files changed, 137 insertions, 13 deletions
diff --git a/libnm-util/nm-setting.c b/libnm-util/nm-setting.c
index b5a8b71f64..f134754b18 100644
--- a/libnm-util/nm-setting.c
+++ b/libnm-util/nm-setting.c
@@ -332,6 +332,29 @@ nm_setting_verify (NMSetting *setting, GSList *all_settings, GError **error)
return TRUE;
}
+static inline gboolean
+should_compare_prop (NMSetting *setting,
+ const char *prop_name,
+ NMSettingCompareFlags comp_flags,
+ GParamFlags prop_flags)
+{
+ /* Fuzzy compare ignores secrets and properties defined with the FUZZY_IGNORE flag */
+ if ( (comp_flags & NM_SETTING_COMPARE_FLAG_FUZZY)
+ && (prop_flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)))
+ return FALSE;
+
+ if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS)
+ && (prop_flags & NM_SETTING_PARAM_SECRET))
+ return FALSE;
+
+ if ( (comp_flags & NM_SETTING_COMPARE_FLAG_IGNORE_ID)
+ && NM_IS_SETTING_CONNECTION (setting)
+ && !strcmp (prop_name, NM_SETTING_CONNECTION_ID))
+ return FALSE;
+
+ return TRUE;
+}
+
/**
* nm_setting_compare:
* @a: a #NMSetting
@@ -370,19 +393,8 @@ nm_setting_compare (NMSetting *a,
GValue value1 = { 0 };
GValue value2 = { 0 };
- /* Fuzzy compare ignores secrets and properties defined with the
- * FUZZY_IGNORE flag
- */
- if ( (flags & NM_SETTING_COMPARE_FLAG_FUZZY)
- && (prop_spec->flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET)))
- continue;
-
- if ((flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS) && (prop_spec->flags & NM_SETTING_PARAM_SECRET))
- continue;
-
- if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_ID)
- && !strcmp (nm_setting_get_name (a), NM_SETTING_CONNECTION_SETTING_NAME)
- && !strcmp (prop_spec->name, NM_SETTING_CONNECTION_ID))
+ /* Handle compare flags */
+ if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags))
continue;
g_value_init (&value1, prop_spec->value_type);
@@ -403,6 +415,118 @@ nm_setting_compare (NMSetting *a,
}
/**
+ * nm_setting_diff:
+ * @a: a #NMSetting
+ * @b: a second #NMSetting to compare with the first
+ * @flags: compare flags, e.g. %NM_SETTING_COMPARE_FLAG_EXACT
+ * @invert_results: this parameter is used internally by libnm-util and should
+ * be set to %FALSE. If %TRUE inverts the meaning of the #NMSettingDiffResult.
+ * @results: (element-type utf8 guint32): if the settings differ, on return a
+ * hash table mapping the differing keys to one or more #NMSettingDiffResult
+ * values OR-ed together. If the settings do not differ, any hash table passed
+ * in is unmodified. If no hash table is passed in, a new one is created.
+ *
+ * Compares two #NMSetting objects for similarity, with comparison behavior
+ * modified by a set of flags. See the documentation for #NMSettingCompareFlags
+ * for a description of each flag's behavior. If the settings differ, the keys
+ * of each setting that differ from the other are added to @results, mapped to
+ * one or more #NMSettingDiffResult values.
+ *
+ * Returns: %TRUE if the settings contain the same values, %FALSE if they do not
+ **/
+gboolean
+nm_setting_diff (NMSetting *a,
+ NMSetting *b,
+ NMSettingCompareFlags flags,
+ gboolean invert_results,
+ GHashTable **results)
+{
+ GParamSpec **property_specs;
+ guint n_property_specs;
+ guint i;
+ NMSettingDiffResult a_result = NM_SETTING_DIFF_RESULT_IN_A;
+ NMSettingDiffResult b_result = NM_SETTING_DIFF_RESULT_IN_B;
+ gboolean results_created = FALSE;
+
+ g_return_val_if_fail (results != NULL, FALSE);
+ g_return_val_if_fail (a != NULL, FALSE);
+ g_return_val_if_fail (NM_IS_SETTING (a), FALSE);
+ if (b) {
+ g_return_val_if_fail (NM_IS_SETTING (b), FALSE);
+ g_return_val_if_fail (G_OBJECT_TYPE (a) == G_OBJECT_TYPE (b), FALSE);
+ }
+
+ /* If the caller is calling this function in a pattern like this to get
+ * complete diffs:
+ *
+ * nm_setting_diff (A, B, FALSE, &results);
+ * nm_setting_diff (B, A, TRUE, &results);
+ *
+ * and wants us to invert the results so that the second invocation comes
+ * out correctly, do that here.
+ */
+ if (invert_results) {
+ a_result = NM_SETTING_DIFF_RESULT_IN_B;
+ b_result = NM_SETTING_DIFF_RESULT_IN_A;
+ }
+
+ if (*results == NULL) {
+ *results = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ results_created = TRUE;
+ }
+
+ /* And now all properties */
+ property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (a), &n_property_specs);
+
+ for (i = 0; i < n_property_specs; i++) {
+ GParamSpec *prop_spec = property_specs[i];
+ GValue a_value = { 0 }, b_value = { 0 };
+ NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN, tmp;
+ gboolean different = TRUE;
+
+ /* Handle compare flags */
+ if (!should_compare_prop (a, prop_spec->name, flags, prop_spec->flags))
+ continue;
+ if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0)
+ continue;
+
+ if (b) {
+ g_value_init (&a_value, prop_spec->value_type);
+ g_object_get_property (G_OBJECT (a), prop_spec->name, &a_value);
+
+ g_value_init (&b_value, prop_spec->value_type);
+ g_object_get_property (G_OBJECT (b), prop_spec->name, &b_value);
+
+ different = !!g_param_values_cmp (prop_spec, &a_value, &b_value);
+ if (different) {
+ if (!g_param_value_defaults (prop_spec, &a_value))
+ r |= a_result;
+ if (!g_param_value_defaults (prop_spec, &b_value))
+ r |= b_result;
+ }
+
+ g_value_unset (&a_value);
+ g_value_unset (&b_value);
+ } else
+ r = a_result; /* only in A */
+
+ if (different) {
+ tmp = GPOINTER_TO_UINT (g_hash_table_lookup (*results, prop_spec->name));
+ g_hash_table_insert (*results, g_strdup (prop_spec->name), GUINT_TO_POINTER (tmp | r));
+ }
+ }
+ g_free (property_specs);
+
+ /* Don't return an empty hash table */
+ if (results_created && !g_hash_table_size (*results)) {
+ g_hash_table_destroy (*results);
+ *results = NULL;
+ }
+
+ return !(*results);
+}
+
+/**
* nm_setting_enumerate_values:
* @setting: the #NMSetting
* @func: (scope call): user-supplied function called for each property of the setting