diff options
Diffstat (limited to 'libnm-core/nm-setting.c')
-rw-r--r-- | libnm-core/nm-setting.c | 218 |
1 files changed, 117 insertions, 101 deletions
diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index 460dafac7d..ba606d5a47 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -22,6 +22,7 @@ #include <string.h> #include <glib/gi18n.h> +#include <gio/gio.h> #include "nm-setting.h" #include "nm-setting-private.h" @@ -104,7 +105,6 @@ _ensure_registered (void) #if !GLIB_CHECK_VERSION (2, 35, 0) g_type_init (); #endif - _nm_value_transforms_register (); registered_settings = g_hash_table_new (g_str_hash, g_str_equal); registered_settings_by_type = g_hash_table_new (_nm_gtype_hash, _nm_gtype_equal); } @@ -272,31 +272,81 @@ _nm_setting_compare_priority (gconstpointer a, gconstpointer b) /*************************************************************/ +static const GVariantType * +variant_type_for_gtype (GType type) +{ + if (type == G_TYPE_BOOLEAN) + return G_VARIANT_TYPE_BOOLEAN; + else if (type == G_TYPE_UCHAR) + return G_VARIANT_TYPE_BYTE; + else if (type == G_TYPE_INT) + return G_VARIANT_TYPE_INT32; + else if (type == G_TYPE_UINT) + return G_VARIANT_TYPE_UINT32; + else if (type == G_TYPE_STRING) + return G_VARIANT_TYPE_STRING; + else if (type == G_TYPE_DOUBLE) + return G_VARIANT_TYPE_DOUBLE; + else + g_assert_not_reached (); +} + +static GVariant * +get_property_for_dbus (NMSetting *setting, GParamSpec *prop_spec, gboolean ignore_default) +{ + GValue prop_value = { 0, }; + GVariant *dbus_value; + + g_value_init (&prop_value, prop_spec->value_type); + g_object_get_property (G_OBJECT (setting), prop_spec->name, &prop_value); + + if (ignore_default && g_param_value_defaults (prop_spec, &prop_value)) { + g_value_unset (&prop_value); + return NULL; + } + + if (NM_IS_PARAM_SPEC_DBUS (prop_spec)) + dbus_value = _nm_param_spec_dbus_value_to_dbus (NM_PARAM_SPEC_DBUS (prop_spec), &prop_value); + else + dbus_value = g_dbus_gvalue_to_gvariant (&prop_value, variant_type_for_gtype (prop_value.g_type)); + + g_value_unset (&prop_value); + return dbus_value; +} + static void -destroy_gvalue (gpointer data) +set_property_from_dbus (NMSetting *setting, GParamSpec *prop_spec, GVariant *dbus_value) { - GValue *value = (GValue *) data; + GValue prop_value = { 0, }; + + g_value_init (&prop_value, prop_spec->value_type); + if (NM_IS_PARAM_SPEC_DBUS (prop_spec)) { + _nm_param_spec_dbus_value_from_dbus (NM_PARAM_SPEC_DBUS (prop_spec), + dbus_value, &prop_value); + } else + g_dbus_gvariant_to_gvalue (dbus_value, &prop_value); - g_value_unset (value); - g_slice_free (GValue, value); + g_object_set_property (G_OBJECT (setting), prop_spec->name, &prop_value); + g_value_unset (&prop_value); } /** - * nm_setting_to_hash: + * nm_setting_to_variant: * @setting: the #NMSetting * @flags: hash flags, e.g. %NM_SETTING_HASH_FLAG_ALL * - * Converts the #NMSetting into a #GHashTable mapping each setting property - * name to a GValue describing that property, suitable for marshalling over - * D-Bus or serializing. The mapping is string to GValue. + * Converts the #NMSetting into a #GVariant of type #NM_VARIANT_TYPE_SETTING + * (`a{sv}`), mapping each setting property name to a value describing that + * property, suitable for marshalling over D-Bus or serializing. * - * Returns: (transfer full) (element-type utf8 GObject.Value): a new #GHashTable - * describing the setting's properties + * Returns: (transfer none): a new floating #GVariant describing the setting's + * properties **/ -GHashTable * -nm_setting_to_hash (NMSetting *setting, NMSettingHashFlags flags) +GVariant * +nm_setting_to_variant (NMSetting *setting, NMSettingHashFlags flags) { - GHashTable *hash; + GVariantBuilder builder; + GVariant *dbus_value, *ret; GParamSpec **property_specs; guint n_property_specs; guint i; @@ -310,12 +360,10 @@ nm_setting_to_hash (NMSetting *setting, NMSettingHashFlags flags) return NULL; } - hash = g_hash_table_new_full (g_str_hash, g_str_equal, - (GDestroyNotify) g_free, destroy_gvalue); + g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING); for (i = 0; i < n_property_specs; i++) { GParamSpec *prop_spec = property_specs[i]; - GValue *value; /* Don't serialize properties that can't be deserialized */ if ( !(prop_spec->flags & G_PARAM_WRITABLE) @@ -325,60 +373,46 @@ nm_setting_to_hash (NMSetting *setting, NMSettingHashFlags flags) if ( (flags & NM_SETTING_HASH_FLAG_NO_SECRETS) && (prop_spec->flags & NM_SETTING_PARAM_SECRET)) continue; + if ( (flags & NM_SETTING_HASH_FLAG_ONLY_SECRETS) && !(prop_spec->flags & NM_SETTING_PARAM_SECRET)) continue; - value = g_slice_new0 (GValue); - g_value_init (value, prop_spec->value_type); - g_object_get_property (G_OBJECT (setting), prop_spec->name, value); - - /* Don't serialize values with default values */ - if (g_param_value_defaults (prop_spec, value)) { - destroy_gvalue (value); - continue; - } - - if (NM_IS_PARAM_SPEC_DBUS (prop_spec)) { - GValue *dbus_value = g_slice_new0 (GValue); - - _nm_param_spec_dbus_value_to_dbus (NM_PARAM_SPEC_DBUS (prop_spec), - value, dbus_value); - destroy_gvalue (value); - value = dbus_value; - } - - g_hash_table_insert (hash, g_strdup (prop_spec->name), value); + dbus_value = get_property_for_dbus (setting, prop_spec, TRUE); + if (dbus_value) + g_variant_builder_add (&builder, "{sv}", prop_spec->name, dbus_value); } g_free (property_specs); + ret = g_variant_builder_end (&builder); + /* Don't return empty hashes, except for base types */ - if (g_hash_table_size (hash) < 1 && !_nm_setting_is_base_type (setting)) { - g_hash_table_destroy (hash); - hash = NULL; + if (g_variant_n_children (ret) < 1 && !_nm_setting_is_base_type (setting)) { + g_variant_unref (ret); + ret = NULL; } - return hash; + return ret; } /** - * nm_setting_new_from_hash: + * nm_setting_new_from_variant: * @setting_type: the #NMSetting type which the hash contains properties for - * @hash: (element-type utf8 GObject.Value): the #GHashTable containing a - * string to GValue mapping of properties that apply to the setting + * @variant: the #GVariant containing an %NM_VARIANT_TYPE_SETTING dictionary mapping + * property names to values * * Creates a new #NMSetting object and populates that object with the properties - * contained in the hash table, using each hash key as the property to set, - * and each hash value as the value to set that property to. Setting properties - * are strongly typed, thus the GValue type of the hash value must be correct. - * See the documentation on each #NMSetting object subclass for the correct - * property names and value types. + * contained in the vardict, using each key as the property to set, and each + * value as the value to set that property to. Setting properties are strongly + * typed, thus the #GVariantType of the dict value must be correct. See the + * documentation on each #NMSetting object subclass for the correct property + * names and value types. * * Returns: a new #NMSetting object populated with the properties from the * hash table, or %NULL on failure **/ NMSetting * -nm_setting_new_from_hash (GType setting_type, GHashTable *hash) +nm_setting_new_from_variant (GType setting_type, GVariant *variant) { NMSetting *setting; GObjectClass *class; @@ -387,7 +421,7 @@ nm_setting_new_from_hash (GType setting_type, GHashTable *hash) int i; g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (setting_type), NULL); - g_return_val_if_fail (hash != NULL, NULL); + g_return_val_if_fail (g_variant_is_of_type (variant, NM_VARIANT_TYPE_SETTING), NULL); class = g_type_class_ref (setting_type); property_specs = g_object_class_list_properties (class, &n_property_specs); @@ -403,26 +437,18 @@ nm_setting_new_from_hash (GType setting_type, GHashTable *hash) for (i = 0; i < n_property_specs; i++) { GParamSpec *prop_spec = property_specs[i]; - GValue *value; + GVariant *value; if ( !(prop_spec->flags & G_PARAM_WRITABLE) || (prop_spec->flags & G_PARAM_CONSTRUCT_ONLY)) continue; - value = g_hash_table_lookup (hash, prop_spec->name); + value = g_variant_lookup_value (variant, prop_spec->name, NULL); if (!value) continue; - if (NM_IS_PARAM_SPEC_DBUS (prop_spec)) { - GValue prop_value = { 0, }; - - g_value_init (&prop_value, prop_spec->value_type); - _nm_param_spec_dbus_value_from_dbus (NM_PARAM_SPEC_DBUS (prop_spec), - value, &prop_value); - g_object_set_property (G_OBJECT (setting), prop_spec->name, &prop_value); - g_value_unset (&prop_value); - } else - g_object_set_property (G_OBJECT (setting), prop_spec->name, value); + set_property_from_dbus (setting, prop_spec, value); + g_variant_unref (value); } return setting; @@ -977,10 +1003,9 @@ nm_setting_need_secrets (NMSetting *setting) } static int -update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **error) +update_one_secret (NMSetting *setting, const char *key, GVariant *value, GError **error) { GParamSpec *prop_spec; - GValue transformed_value = G_VALUE_INIT; prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key); if (!prop_spec) { @@ -995,76 +1020,67 @@ update_one_secret (NMSetting *setting, const char *key, GValue *value, GError ** if (!(prop_spec->flags & NM_SETTING_PARAM_SECRET)) return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; - if (g_value_type_compatible (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (prop_spec))) { - if (G_VALUE_HOLDS_STRING (value) && G_IS_PARAM_SPEC_STRING (prop_spec)) { - /* String is expected to be a common case. Handle it specially and check whether - * the value is already set. Otherwise, we just reset the property and - * assume the value got modified. */ - char *v; - - g_object_get (G_OBJECT (setting), prop_spec->name, &v, NULL); - if (g_strcmp0 (v, g_value_get_string (value)) == 0) { - g_free (v); - return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; - } + if ( g_variant_is_of_type (value, G_VARIANT_TYPE_STRING) + && G_IS_PARAM_SPEC_STRING (prop_spec)) { + /* String is expected to be a common case. Handle it specially and check + * whether the value is already set. Otherwise, we just reset the + * property and assume the value got modified. + */ + char *v; + + g_object_get (G_OBJECT (setting), prop_spec->name, &v, NULL); + if (g_strcmp0 (v, g_variant_get_string (value, NULL)) == 0) { g_free (v); + return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; } - g_object_set_property (G_OBJECT (setting), prop_spec->name, value); - return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; + g_free (v); } - if (g_value_transform (value, &transformed_value)) { - g_object_set_property (G_OBJECT (setting), prop_spec->name, &transformed_value); - g_value_unset (&transformed_value); - return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; - } - g_set_error (error, - NM_SETTING_ERROR, - NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, - "%s", key); - return NM_SETTING_UPDATE_SECRET_ERROR; + + set_property_from_dbus (setting, prop_spec, value); + return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; } /** * nm_setting_update_secrets: * @setting: the #NMSetting - * @secrets: (element-type utf8 GObject.Value): a #GHashTable mapping - * string to #GValue of setting property names and secrets + * @secrets: a vardict mapping property names to secrets * @error: location to store error, or %NULL * - * Update the setting's secrets, given a hash table of secrets intended for that + * Update the setting's secrets, given a vardict of secrets intended for that * setting (deserialized from D-Bus for example). * * Returns: %TRUE if the secrets were successfully updated, %FALSE on failure to * update one or more of the secrets. **/ gboolean -nm_setting_update_secrets (NMSetting *setting, GHashTable *secrets, GError **error) +nm_setting_update_secrets (NMSetting *setting, GVariant *secrets, GError **error) { return _nm_setting_update_secrets (setting, secrets, error) != NM_SETTING_UPDATE_SECRET_ERROR; } NMSettingUpdateSecretResult -_nm_setting_update_secrets (NMSetting *setting, GHashTable *secrets, GError **error) +_nm_setting_update_secrets (NMSetting *setting, GVariant *secrets, GError **error) { - GHashTableIter iter; - gpointer key, data; + GVariantIter iter; + const char *secret_key; + GVariant *secret_value; GError *tmp_error = NULL; NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_UPDATE_SECRET_ERROR); - g_return_val_if_fail (secrets != NULL, NM_SETTING_UPDATE_SECRET_ERROR); + g_return_val_if_fail (g_variant_is_of_type (secrets, NM_VARIANT_TYPE_SETTING), NM_SETTING_UPDATE_SECRET_ERROR); if (error) g_return_val_if_fail (*error == NULL, NM_SETTING_UPDATE_SECRET_ERROR); - g_hash_table_iter_init (&iter, secrets); - while (g_hash_table_iter_next (&iter, &key, &data)) { + g_variant_iter_init (&iter, secrets); + while (g_variant_iter_next (&iter, "{&sv}", &secret_key, &secret_value)) { int success; - const char *secret_key = (const char *) key; - GValue *secret_value = (GValue *) data; success = NM_SETTING_GET_CLASS (setting)->update_one_secret (setting, secret_key, secret_value, &tmp_error); g_assert (!((success == NM_SETTING_UPDATE_SECRET_ERROR) ^ (!!tmp_error))); + g_variant_unref (secret_value); + if (success == NM_SETTING_UPDATE_SECRET_ERROR) { g_propagate_error (error, tmp_error); return NM_SETTING_UPDATE_SECRET_ERROR; |