diff --git a/ChangeLog b/ChangeLog index fe8f5c3735..21da44ff23 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,18 @@ +2008-05-07 Dan Williams + + * system-settings/plugins/keyfile/reader.c + - (read_one_setting_value): handle IP address items separately + - (read_array_of_uint): read IPv4 DNS option as a string array + - (read_array_of_array_of_uint): read IPv4 address tuples as a string + array + + * system-settings/plugins/keyfile/writer.c + - (write_setting_value): handle IP address items separately + - (write_array_of_uint): handle IPv4 DNS option as a string array, + not an array of uint, so that it's user-editable + - (write_array_of_array_of_uint): handle IPv4 address tuples as string + arrays, so they are user-editable + 2008-05-07 Dan Williams * system-settings/plugins/keyfile/Makefile.am diff --git a/system-settings/plugins/keyfile/reader.c b/system-settings/plugins/keyfile/reader.c index 05cc73a00f..5c59bb23b8 100644 --- a/system-settings/plugins/keyfile/reader.c +++ b/system-settings/plugins/keyfile/reader.c @@ -5,11 +5,133 @@ #include #include #include +#include +#include +#include +#include "nm-dbus-glib-types.h" #include "reader.h" -#define DBUS_TYPE_G_ARRAY_OF_UINT (dbus_g_type_get_collection ("GArray", G_TYPE_UINT)) -#define DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_ARRAY_OF_UINT)) +static gboolean +read_array_of_uint (GKeyFile *file, + NMSetting *setting, + const char *key) +{ + GArray *array = NULL; + gsize length; + int i; + + if (NM_IS_SETTING_IP4_CONFIG (setting) && !strcmp (key, NM_SETTING_IP4_CONFIG_DNS)) { + char **list, **iter; + int ret; + + list = g_key_file_get_string_list (file, setting->name, key, &length, NULL); + if (!list || !g_strv_length (list)) + return TRUE; + + array = g_array_sized_new (FALSE, FALSE, sizeof (guint32), length); + for (iter = list; *iter; iter++) { + struct in_addr addr; + + ret = inet_pton (AF_INET, *iter, &addr); + if (ret <= 0) { + g_warning ("%s: ignoring invalid DNS server address '%s'", __func__, *iter); + continue; + } + + g_array_append_val (array, addr.s_addr); + } + } else { + gint *tmp; + + tmp = g_key_file_get_integer_list (file, setting->name, key, &length, NULL); + + array = g_array_sized_new (FALSE, FALSE, sizeof (guint32), length); + for (i = 0; i < length; i++) + g_array_append_val (array, tmp[i]); + } + + if (array) { + g_object_set (setting, key, array, NULL); + g_array_free (array, TRUE); + } + + return TRUE; +} + +static void +free_one_address (gpointer data, gpointer user_data) +{ + g_array_free ((GArray *) data, TRUE); +} + +static gboolean +read_array_of_array_of_uint (GKeyFile *file, + NMSetting *setting, + const char *key) +{ + GPtrArray *addresses; + int i = 0; + + /* Only handle IPv4 addresses for now */ + if ( !NM_IS_SETTING_IP4_CONFIG (setting) + || strcmp (key, NM_SETTING_IP4_CONFIG_ADDRESSES)) + return FALSE; + + addresses = g_ptr_array_sized_new (3); + + /* Look for individual addresses */ + while (i++ < 1000) { + gchar **tmp, **iter; + char *key_name; + gsize length = 0; + int ret; + GArray *address; + guint32 empty = 0; + + key_name = g_strdup_printf ("address%d", i); + tmp = g_key_file_get_string_list (file, setting->name, key_name, &length, NULL); + g_free (key_name); + + if (!tmp || !length) + break; /* all done */ + + if ((length < 2) || (length > 3)) { + g_warning ("%s: ignoring invalid IPv4 address item '%s'", __func__, key_name); + goto next; + } + + /* convert the string array into IP addresses */ + address = g_array_sized_new (FALSE, TRUE, sizeof (guint32), 3); + for (iter = tmp; *iter; iter++) { + struct in_addr addr; + + ret = inet_pton (AF_INET, *iter, &addr); + if (ret <= 0) { + g_warning ("%s: ignoring invalid IPv4 %s element '%s'", __func__, key_name, *iter); + g_array_free (address, TRUE); + goto next; + } + + g_array_append_val (address, addr.s_addr); + } + + /* fill in blank gateway if not specified */ + if (address->len == 2) + g_array_append_val (address, empty); + + g_ptr_array_add (addresses, address); + +next: + g_strfreev (tmp); + } + + g_object_set (setting, key, addresses, NULL); + + g_ptr_array_foreach (addresses, free_one_address, NULL); + g_ptr_array_free (addresses, TRUE); + return TRUE; +} static void read_one_setting_value (NMSetting *setting, @@ -21,8 +143,17 @@ read_one_setting_value (NMSetting *setting, GKeyFile *file = (GKeyFile *) user_data; GType type; GError *err = NULL; + gboolean check_for_key = TRUE; - if (!g_key_file_has_key (file, setting->name, key, &err)) { + /* Setting name gets picked up from the keyfile's section name instead */ + if (!strcmp (key, NM_SETTING_NAME)) + return; + + /* IPv4 addresses don't have the exact key name */ + if (NM_IS_SETTING_IP4_CONFIG (setting) && !strcmp (key, NM_SETTING_IP4_CONFIG_ADDRESSES)) + check_for_key = FALSE; + + if (check_for_key && !g_key_file_has_key (file, setting->name, key, &err)) { if (err) { g_warning ("Error loading setting '%s' value: %s", setting->name, err->message); g_error_free (err); @@ -111,22 +242,15 @@ read_one_setting_value (NMSetting *setting, /* FIXME */ g_warning ("Implement me"); } else if (type == DBUS_TYPE_G_UINT_ARRAY) { - gint *tmp; - GArray *array; - gsize length; - int i; - - tmp = g_key_file_get_integer_list (file, setting->name, key, &length, NULL); - - array = g_array_sized_new (FALSE, FALSE, sizeof (guint32), length); - for (i = 0; i < length; i++) - g_array_append_val (array, tmp[i]); - - g_object_set (setting, key, array, NULL); - g_array_free (array, TRUE); + if (!read_array_of_uint (file, setting, key)) { + g_warning ("Unhandled setting property type (read): '%s/%s' : '%s'", + setting->name, key, G_VALUE_TYPE_NAME (value)); + } } else if (type == DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT) { - /* FIXME */ - g_warning ("Implement me"); + if (!read_array_of_array_of_uint (file, setting, key)) { + g_warning ("Unhandled setting property type (read): '%s/%s' : '%s'", + setting->name, key, G_VALUE_TYPE_NAME (value)); + } } else { g_warning ("Unhandled setting property type (read): '%s/%s' : '%s'", setting->name, key, G_VALUE_TYPE_NAME (value)); diff --git a/system-settings/plugins/keyfile/writer.c b/system-settings/plugins/keyfile/writer.c index daef9c709d..8a994e8af5 100644 --- a/system-settings/plugins/keyfile/writer.c +++ b/system-settings/plugins/keyfile/writer.c @@ -6,11 +6,101 @@ #include #include #include +#include +#include +#include +#include "nm-dbus-glib-types.h" #include "writer.h" -#define DBUS_TYPE_G_ARRAY_OF_UINT (dbus_g_type_get_collection ("GArray", G_TYPE_UINT)) -#define DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT (dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_ARRAY_OF_UINT)) +static gboolean +write_array_of_uint (GKeyFile *file, + NMSetting *setting, + const char *key, + const GValue *value) +{ + GArray *array; + int i; + + array = (GArray *) g_value_get_boxed (value); + if (!array || !array->len) + return TRUE; + + if (NM_IS_SETTING_IP4_CONFIG (setting) && !strcmp (key, NM_SETTING_IP4_CONFIG_DNS)) { + char **list; + + list = g_new0 (char *, array->len + 1); + + for (i = 0; i < array->len; i++) { + char buf[INET_ADDRSTRLEN + 1]; + struct in_addr addr; + + addr.s_addr = g_array_index (array, guint32, i); + list[i] = g_strdup (inet_ntop (AF_INET, &addr, buf, sizeof (buf))); + } + + g_key_file_set_string_list (file, setting->name, key, (const char **) list, array->len); + g_strfreev (list); + } else { + int *tmp_array; + + tmp_array = g_new (gint, array->len); + for (i = 0; i < array->len; i++) + tmp_array[i] = g_array_index (array, int, i); + + g_key_file_set_integer_list (file, setting->name, key, tmp_array, array->len); + g_free (tmp_array); + } + + return TRUE; +} + +static gboolean +write_array_of_array_of_uint (GKeyFile *file, + NMSetting *setting, + const char *key, + const GValue *value) +{ + GPtrArray *array; + int i, j; + + /* Only handle IPv4 addresses for now */ + if ( !NM_IS_SETTING_IP4_CONFIG (setting) + || strcmp (key, NM_SETTING_IP4_CONFIG_ADDRESSES)) + return FALSE; + + array = (GPtrArray *) g_value_get_boxed (value); + if (!array || !array->len) + return TRUE; + + for (i = 0, j = 0; i < array->len; i++, j++) { + GArray *tuple = g_ptr_array_index (array, i); + char buf[INET_ADDRSTRLEN + 1]; + struct in_addr addr; + char *list[3] = { NULL, NULL, NULL }; + char *key_name; + + addr.s_addr = g_array_index (tuple, guint32, 0); + list[0] = g_strdup (inet_ntop (AF_INET, &addr, buf, sizeof (buf))); + + addr.s_addr = g_array_index (tuple, guint32, 1); + list[1] = g_strdup (inet_ntop (AF_INET, &addr, buf, sizeof (buf))); + + addr.s_addr = g_array_index (tuple, guint32, 2); + if (addr.s_addr) + list[2] = g_strdup (inet_ntop (AF_INET, &addr, buf, sizeof (buf))); + + key_name = g_strdup_printf ("address%d", j + 1); + g_key_file_set_string_list (file, setting->name, key_name, (const char **) list, list[2] ? 3 : 2); + g_free (key_name); + + g_free (list[0]); + g_free (list[1]); + g_free (list[2]); + } + + return TRUE; +} static void write_setting_value (NMSetting *setting, @@ -24,6 +114,10 @@ write_setting_value (NMSetting *setting, type = G_VALUE_TYPE (value); + /* Setting name gets picked up from the keyfile's section name instead */ + if (!strcmp (key, NM_SETTING_NAME)) + return; + if (type == G_TYPE_STRING) { const char *str; @@ -79,44 +173,19 @@ write_setting_value (NMSetting *setting, /* FIXME */ g_warning ("Implement me"); } else if (type == DBUS_TYPE_G_UINT_ARRAY) { - GArray *array; - - array = (GArray *) g_value_get_boxed (value); - if (array && array->len > 0) { - int *tmp_array; - int i; - - tmp_array = g_new (gint, array->len); - for (i = 0; i < array->len; i++) - tmp_array[i] = (int) array->data[i]; - - g_key_file_set_integer_list (file, setting->name, key, tmp_array, array->len); - g_free (tmp_array); + if (!write_array_of_uint (file, setting, key, value)) { + g_warning ("Unhandled setting property type (write) '%s/%s' : '%s'", + setting->name, key, g_type_name (type)); } } else if (type == DBUS_TYPE_G_ARRAY_OF_ARRAY_OF_UINT) { - GPtrArray *array; - - array = (GPtrArray *) g_value_get_boxed (value); - if (array && array->len > 0) { - int i, j; - int* list; - - list = g_new (int, array->len * 3); - - for (i = 0, j = 0; i < array->len; i++) { - GArray *tuple = g_ptr_array_index (array, i); - - list[j++] = g_array_index (tuple, guint32, 0); - list[j++] = g_array_index (tuple, guint32, 1); - list[j++] = tuple->len == 3 ? g_array_index (tuple, guint32, 2) : 0; - } - - g_key_file_set_integer_list (file, setting->name, key, list, j); - g_free (list); + if (!write_array_of_array_of_uint (file, setting, key, value)) { + g_warning ("Unhandled setting property type (write) '%s/%s' : '%s'", + setting->name, key, g_type_name (type)); } - } else + } else { g_warning ("Unhandled setting property type (write) '%s/%s' : '%s'", setting->name, key, g_type_name (type)); + } } gboolean