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:
11
ChangeLog
11
ChangeLog
@@ -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
|
||||
|
@@ -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
|
||||
|
@@ -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 */
|
||||
|
||||
|
@@ -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);
|
||||
|
Reference in New Issue
Block a user