summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2015-03-13 16:35:23 +0100
committerThomas Haller <thaller@redhat.com>2015-03-20 13:19:20 +0100
commit58f08c8c9ce3602f31d2fdfaa2cc9ecca4713532 (patch)
treeeedd9bedb25046b5b7d94c56ff8e644fe9e7b979
parente50fbe466b01823e97540d91a1452d994cfcb11e (diff)
downloadNetworkManager-58f08c8c9ce3602f31d2fdfaa2cc9ecca4713532.tar.gz
libnm: sort properties for nm_setting_enumerate_values()
The sort order of nm_setting_enumerate_values() affects the order in which keyfile writer serializes the properties. Have a defined, stable sort order by sorting the properties by name (with prefering id,uuid,type for NMSettingConnection).
-rw-r--r--libnm-core/nm-setting.c35
1 files changed, 35 insertions, 0 deletions
diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c
index 2730742654..a292bfca6e 100644
--- a/libnm-core/nm-setting.c
+++ b/libnm-core/nm-setting.c
@@ -1314,6 +1314,33 @@ nm_setting_diff (NMSetting *a,
return !(*results);
}
+#define CMP_AND_RETURN(n_a, n_b, name) \
+ G_STMT_START { \
+ gboolean _is = (strcmp (n_a, ""name) == 0); \
+ \
+ if (_is || (strcmp (n_b, ""name) == 0)) \
+ return _is ? -1 : 1; \
+ } G_STMT_END;
+
+static int
+_enumerate_values_sort (GParamSpec **p_a, GParamSpec **p_b, GType *p_type)
+{
+ const char *n_a = (*p_a)->name;
+ const char *n_b = (*p_b)->name;
+ int c = strcmp (n_a, n_b);
+
+ if (c) {
+ if (*p_type == NM_TYPE_SETTING_CONNECTION) {
+ /* for [connection], report first id, uuid, type in that order. */
+ CMP_AND_RETURN (n_a, n_b, NM_SETTING_CONNECTION_ID);
+ CMP_AND_RETURN (n_a, n_b, NM_SETTING_CONNECTION_UUID);
+ CMP_AND_RETURN (n_a, n_b, NM_SETTING_CONNECTION_TYPE);
+ }
+ }
+ return c;
+}
+#undef CMP_AND_RETURN
+
/**
* nm_setting_enumerate_values:
* @setting: the #NMSetting
@@ -1331,11 +1358,19 @@ nm_setting_enumerate_values (NMSetting *setting,
GParamSpec **property_specs;
guint n_property_specs;
int i;
+ GType type;
g_return_if_fail (NM_IS_SETTING (setting));
g_return_if_fail (func != NULL);
property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs);
+
+ /* sort the properties. This has an effect on the order in which keyfile
+ * prints them. */
+ type = G_OBJECT_TYPE (setting);
+ g_qsort_with_data (property_specs, n_property_specs, sizeof (gpointer),
+ (GCompareDataFunc) _enumerate_values_sort, &type);
+
for (i = 0; i < n_property_specs; i++) {
GParamSpec *prop_spec = property_specs[i];
GValue value = G_VALUE_INIT;