2007-10-23 Dan Williams <dcbw@redhat.com>

* libnm-util/nm-setting.c
	  libnm-util/nm-setting.c
		- (nm_setting_compare): implement
		- (default_setting_compare_fn, do_one_compare, compare_gvalue_hash,
		   compare_one_hash_gvalue): compare the contents of a setting

	* libnm-util/nm-connection.c
		- (nm_connection_compare): implement



git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3013 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Dan Williams
2007-10-23 20:41:10 +00:00
parent 5bd382de25
commit aedced3964
4 changed files with 290 additions and 2 deletions

View File

@@ -1,3 +1,14 @@
2007-10-23 Dan Williams <dcbw@redhat.com>
* libnm-util/nm-setting.c
libnm-util/nm-setting.c
- (nm_setting_compare): implement
- (default_setting_compare_fn, do_one_compare, compare_gvalue_hash,
compare_one_hash_gvalue): compare the contents of a setting
* libnm-util/nm-connection.c
- (nm_connection_compare): implement
2007-10-23 Dan Williams <dcbw@redhat.com>
* src/nm-activation-request.c

View File

@@ -155,18 +155,59 @@ nm_connection_replace_settings (NMConnection *connection,
return TRUE;
}
typedef struct {
NMConnection *other;
gboolean failed;
} CompareConnectionInfo;
static void
compare_one_setting (gpointer key, gpointer value, gpointer user_data)
{
NMSetting *setting = (NMSetting *) value;
CompareConnectionInfo *info = (CompareConnectionInfo *) user_data;
NMSetting *other_setting;
NMConnectionPrivate *other_priv;
if (info->failed)
return;
other_priv = NM_CONNECTION_GET_PRIVATE (info->other);
other_setting = g_hash_table_lookup (other_priv->settings, setting->name);
if (!other_setting)
goto failed;
info->failed = nm_setting_compare (setting, other_setting, FALSE) ? FALSE : TRUE;
return;
failed:
info->failed = TRUE;
}
gboolean
nm_connection_compare (NMConnection *connection, NMConnection *other)
{
NMConnectionPrivate *priv;
CompareConnectionInfo info = { other, FALSE };
if (!connection && !other)
return TRUE;
if (!connection || !other)
return FALSE;
/* FIXME: Implement */
priv = NM_CONNECTION_GET_PRIVATE (connection);
g_hash_table_foreach (priv->settings, compare_one_setting, &info);
if (info.failed == FALSE) {
/* compare A to B, then if that is the same compare B to A to ensure
* that keys that are in B but not A will make the comparison fail.
*/
info.failed = FALSE;
info.other = connection;
priv = NM_CONNECTION_GET_PRIVATE (other);
g_hash_table_foreach (priv->settings, compare_one_setting, &info);
}
return FALSE;
return info.failed ? FALSE : TRUE;
}
gboolean

View File

@@ -12,6 +12,7 @@
static GHashTable * nm_setting_hash (NMSetting *setting);
static gboolean nm_setting_populate_from_hash_default (NMSetting *setting, GHashTable *table);
static void default_setting_clear_secrets (NMSetting *setting);
static gboolean default_setting_compare_fn (NMSetting *setting, NMSetting *other, gboolean two_way);
gboolean
nm_setting_populate_from_hash (NMSetting *setting, GHashTable *hash)
@@ -155,6 +156,22 @@ nm_setting_enumerate_values (NMSetting *setting,
};
}
gboolean
nm_setting_compare (NMSetting *setting, NMSetting *other, gboolean two_way)
{
g_return_val_if_fail (setting != NULL, FALSE);
g_return_val_if_fail (other != NULL, FALSE);
g_return_val_if_fail (setting->name != NULL, FALSE);
g_return_val_if_fail (other->name != NULL, FALSE);
g_return_val_if_fail (strcmp (setting->name, other->name) == 0, FALSE);
if (!setting->compare_fn)
return default_setting_compare_fn (setting, other, two_way);
return setting->compare_fn (setting, other, two_way);
}
/***********************************************************************/
/* Helper functions for converting NMSetting to hash table. */
@@ -570,6 +587,219 @@ next:
}
}
typedef struct {
GHashTable *other;
gboolean failed;
} GValueHashCompareInfo;
static void
compare_one_hash_gvalue (gpointer key, gpointer value, gpointer user_data)
{
GValueHashCompareInfo *info = (GValueHashCompareInfo *) user_data;
GValue *val = (GValue *) value;
GValue *other_val;
if (info->failed)
return;
other_val = g_hash_table_lookup (info->other, key);
if (!other_val)
goto failed;
if (G_VALUE_TYPE (val) != G_VALUE_TYPE (other_val))
goto failed;
switch (G_VALUE_TYPE (val)) {
case G_TYPE_STRING: {
const char *a_str = g_value_get_string (val);
const char *b_str = g_value_get_string (other_val);
if ((!a_str && b_str) || (a_str && !b_str))
goto failed;
if (!a_str && !b_str)
break;
if (strcmp (a_str, b_str) != 0)
goto failed;
break;
}
default:
g_warning ("%s: unhandled GValue type %s", __func__, G_VALUE_TYPE_NAME (val));
goto failed;
break;
}
return;
failed:
info->failed = TRUE;
}
static gboolean
compare_gvalue_hash (GHashTable *a, GHashTable *b)
{
GValueHashCompareInfo info = { b, FALSE };
g_return_val_if_fail (a != NULL, FALSE);
g_return_val_if_fail (b != NULL, FALSE);
g_hash_table_foreach (a, compare_one_hash_gvalue, &info);
return info.failed ? FALSE : TRUE;
}
static gboolean
do_one_compare (NMSetting *a, NMSetting *b)
{
SettingMember *m;
g_return_if_fail (a != NULL);
g_return_if_fail (b != NULL);
m = a->_members;
while (m->key) {
/* Ignore secrets since they aren't always supposed to be in the setting */
if (m->secret == FALSE)
goto next;
switch (m->type) {
case NM_S_TYPE_STRING: {
char **a_val = (char **) G_STRUCT_MEMBER_P (a, m->offset);
char **b_val = (char **) G_STRUCT_MEMBER_P (b, m->offset);
if ((*a_val && !*b_val) || (!*a_val && *b_val))
return FALSE;
if (*a_val && *b_val && strcmp (*a_val, *b_val))
return FALSE;
break;
}
case NM_S_TYPE_BOOL: {
gboolean *a_val = (gboolean *) G_STRUCT_MEMBER_P (a, m->offset);
gboolean *b_val = (gboolean *) G_STRUCT_MEMBER_P (b, m->offset);
if (*a_val != *b_val)
return FALSE;
break;
}
case NM_S_TYPE_UINT32: {
guint32 *a_val = (guint32 *) G_STRUCT_MEMBER_P (a, m->offset);
guint32 *b_val = (guint32 *) G_STRUCT_MEMBER_P (b, m->offset);
if (*a_val != *b_val)
return FALSE;
break;
}
case NM_S_TYPE_UINT64: {
guint64 *a_val = (guint64 *) G_STRUCT_MEMBER_P (a, m->offset);
guint64 *b_val = (guint64 *) G_STRUCT_MEMBER_P (b, m->offset);
if (*a_val != *b_val)
return FALSE;
break;
}
case NM_S_TYPE_BYTE_ARRAY: {
GByteArray **a_val = (GByteArray **) G_STRUCT_MEMBER_P (a, m->offset);
GByteArray **b_val = (GByteArray **) G_STRUCT_MEMBER_P (b, m->offset);
if ((*a_val && !*b_val) || (!*a_val && *b_val))
return FALSE;
if (*a_val && *b_val) {
if ((*a_val)->len != (*b_val)->len)
return FALSE;
if (memcmp ((*a_val)->data, (*b_val)->data, (*a_val)->len))
return FALSE;
}
break;
}
case NM_S_TYPE_UINT_ARRAY: {
GArray **a_val = (GArray **) G_STRUCT_MEMBER_P (a, m->offset);
GArray **b_val = (GArray **) G_STRUCT_MEMBER_P (b, m->offset);
if ((*a_val && !*b_val) || (!*a_val && *b_val))
return FALSE;
if (*a_val && *b_val) {
if ((*a_val)->len != (*b_val)->len)
return FALSE;
if (memcmp ((*a_val)->data, (*b_val)->data, (*a_val)->len))
return FALSE;
}
break;
}
case NM_S_TYPE_STRING_ARRAY: {
GSList **a_val = (GSList **) G_STRUCT_MEMBER_P (a, m->offset);
GSList **b_val = (GSList **) G_STRUCT_MEMBER_P (b, m->offset);
GSList *a_iter;
for (a_iter = *a_val; a_iter; a_iter = g_slist_next (a_iter)) {
const char *a_str = a_iter->data;
GSList *b_iter;
gboolean found = FALSE;
for (b_iter = *b_val; b_iter; b_iter = g_slist_next (b_iter)) {
const char *b_str = b_iter->data;
if (!a_str && !b_str) {
found = TRUE;
break;
}
if (a_str && b_str && !strcmp (a_str, b_str)) {
found = TRUE;
break;
}
}
if (!found)
return FALSE;
}
break;
}
case NM_S_TYPE_IP4_ADDRESSES: {
GSList **a_val = (GSList **) G_STRUCT_MEMBER_P (a, m->offset);
GSList **b_val = (GSList **) G_STRUCT_MEMBER_P (b, m->offset);
GSList *a_iter;
for (a_iter = *a_val; a_iter; a_iter = g_slist_next (a_iter)) {
NMSettingIP4Address *a_addr = (NMSettingIP4Address *) a_iter->data;
GSList *b_iter;
gboolean found = FALSE;
g_assert (a_addr);
for (b_iter = *b_val; b_iter; b_iter = g_slist_next (b_iter)) {
NMSettingIP4Address *b_addr = (NMSettingIP4Address *) b_iter->data;
g_assert (b_addr);
if ( (a_addr->address == b_addr->address)
&& (a_addr->netmask == b_addr->netmask)
&& (a_addr->gateway == b_addr->gateway)) {
found = TRUE;
break;
}
}
if (!found)
return FALSE;
}
break;
}
case NM_S_TYPE_GVALUE_HASH: {
GHashTable **a_val = (GHashTable **) G_STRUCT_MEMBER_P (a, m->offset);
GHashTable **b_val = (GHashTable **) G_STRUCT_MEMBER_P (b, m->offset);
if (!compare_gvalue_hash (*a_val, *b_val))
return FALSE;
break;
}
default:
break;
}
next:
m++;
}
}
static gboolean
default_setting_compare_fn (NMSetting *setting, NMSetting *other, gboolean two_way)
{
gboolean same;
same = do_one_compare (setting, other);
/* compare A to B, then if that is the same compare B to A to ensure
* that keys that are in B but not A will make the comparison fail.
*/
if (two_way && (same == TRUE))
return do_one_compare (other, setting);
return same;
}
/* Connection */

View File

@@ -24,6 +24,10 @@ typedef GPtrArray *(*NMSettingNeedSecretsFn) (NMSetting *setting);
typedef void (*NMSettingClearSecretsFn) (NMSetting *setting);
typedef gboolean (*NMSettingCompareFn) (NMSetting *setting,
NMSetting *other,
gboolean two_way);
typedef void (*NMSettingDestroyFn) (NMSetting *setting);
typedef void (*NMSettingValueIterFn) (NMSetting *setting,
@@ -63,6 +67,7 @@ struct _NMSetting {
NMSettingUpdateSecretsFn update_secrets_fn;
NMSettingNeedSecretsFn need_secrets_fn;
NMSettingClearSecretsFn clear_secrets_fn;
NMSettingCompareFn compare_fn;
NMSettingDestroyFn destroy_fn;
};
@@ -70,6 +75,7 @@ gboolean nm_settings_verify_all (GHashTable *all_settings);
gboolean nm_setting_populate_from_hash (NMSetting *setting, GHashTable *hash);
gboolean nm_setting_verify (NMSetting *setting);
gboolean nm_setting_compare (NMSetting *setting, NMSetting *other, gboolean two_way);
GHashTable *nm_setting_to_hash (NMSetting *setting);
gboolean nm_setting_update_secrets (NMSetting *setting, GHashTable *secrets);
GPtrArray * nm_setting_need_secrets (NMSetting *setting);