diff options
Diffstat (limited to 'libnm-core/nm-setting.c')
| -rw-r--r-- | libnm-core/nm-setting.c | 385 |
1 files changed, 290 insertions, 95 deletions
diff --git a/libnm-core/nm-setting.c b/libnm-core/nm-setting.c index a75302f0..dfb2bed9 100644 --- a/libnm-core/nm-setting.c +++ b/libnm-core/nm-setting.c @@ -715,7 +715,7 @@ _nm_setting_to_dbus (NMSetting *setting, g_variant_builder_init (&builder, NM_VARIANT_TYPE_SETTING); - n_properties = _nm_setting_gendata_get_all (setting, &gendata_keys, NULL); + n_properties = _nm_setting_option_get_all (setting, &gendata_keys, NULL); for (i = 0; i < n_properties; i++) { g_variant_builder_add (&builder, "{sv}", @@ -873,7 +873,18 @@ init_from_dbus (NMSetting *setting, g_hash_table_remove (keys, key); } - _nm_setting_gendata_notify (setting, TRUE); + _nm_setting_option_notify (setting, TRUE); + + /* Currently, only NMSettingEthtool supports gendata based options, and + * that one has no other properties (except "name"). That means, we + * consumed all options above. + * + * In the future it may be interesting to have settings that are both + * based on gendata and regular properties. In that case, we would need + * to handle this case differently. */ + nm_assert (nm_streq (G_OBJECT_TYPE_NAME (setting), "NMSettingEthtool")); + nm_assert (sett_info->property_infos_len == 1); + return TRUE; } @@ -1781,7 +1792,7 @@ nm_setting_enumerate_values (NMSetting *setting, /* the properties of this setting are not real GObject properties. * Hence, this API makes little sense (or does it?). Still, call * @func with each value. */ - n_properties = _nm_setting_gendata_get_all (setting, &names, NULL); + n_properties = _nm_setting_option_get_all (setting, &names, NULL); if (n_properties > 0) { gs_strfreev char **keys = g_strdupv ((char **) names); GHashTable *h = _gendata_hash (setting, FALSE)->hash; @@ -2378,7 +2389,7 @@ _gendata_hash (NMSetting *setting, gboolean create_if_necessary) } GHashTable * -_nm_setting_gendata_hash (NMSetting *setting, gboolean create_if_necessary) +_nm_setting_option_hash (NMSetting *setting, gboolean create_if_necessary) { GenData *gendata; @@ -2387,8 +2398,8 @@ _nm_setting_gendata_hash (NMSetting *setting, gboolean create_if_necessary) } void -_nm_setting_gendata_notify (NMSetting *setting, - gboolean names_changed) +_nm_setting_option_notify (NMSetting *setting, + gboolean names_changed) { GenData *gendata; @@ -2422,23 +2433,10 @@ out: _nm_setting_emit_property_changed (setting); } -GVariant * -nm_setting_gendata_get (NMSetting *setting, - const char *name) -{ - GenData *gendata; - - g_return_val_if_fail (NM_IS_SETTING (setting), NULL); - g_return_val_if_fail (name, NULL); - - gendata = _gendata_hash (setting, FALSE); - return gendata ? g_hash_table_lookup (gendata->hash, name) : NULL; -} - guint -_nm_setting_gendata_get_all (NMSetting *setting, - const char *const**out_names, - GVariant *const**out_values) +_nm_setting_option_get_all (NMSetting *setting, + const char *const**out_names, + GVariant *const**out_values) { GenData *gendata; GHashTable *hash; @@ -2484,125 +2482,322 @@ out_zero: } /** - * nm_setting_gendata_get_all_names: + * nm_setting_option_get_all_names: * @setting: the #NMSetting * @out_len: (allow-none) (out): * - * Gives the number of generic data elements and optionally returns all their - * key names and values. This API is low level access and unless you know what you - * are doing, it might not be what you want. + * Gives the name of all set options. * * Returns: (array length=out_len zero-terminated=1) (transfer none): * A %NULL terminated array of key names. If no names are present, this returns * %NULL. The returned array and the names are owned by %NMSetting and might be invalidated - * soon. + * by the next operation. * - * Since: 1.14 + * Since: 1.26 **/ const char *const* -nm_setting_gendata_get_all_names (NMSetting *setting, - guint *out_len) +nm_setting_option_get_all_names (NMSetting *setting, + guint *out_len) { const char *const*names; guint len; g_return_val_if_fail (NM_IS_SETTING (setting), NULL); - len = _nm_setting_gendata_get_all (setting, &names, NULL); + len = _nm_setting_option_get_all (setting, &names, NULL); NM_SET_OUT (out_len, len); return names; } -/** - * nm_setting_gendata_get_all_values: - * @setting: the #NMSetting - * - * Gives the number of generic data elements and optionally returns all their - * key names and values. This API is low level access and unless you know what you - * are doing, it might not be what you want. - * - * Returns: (array zero-terminated=1) (transfer none): - * A %NULL terminated array of #GVariant. If no data is present, this returns - * %NULL. The returned array and the variants are owned by %NMSetting and might be invalidated - * soon. The sort order of nm_setting_gendata_get_all_names() and nm_setting_gendata_get_all_values() - * is consistent. That means, the nth value has the nth name returned by nm_setting_gendata_get_all_names(). - * - * Since: 1.14 - **/ -GVariant *const* -nm_setting_gendata_get_all_values (NMSetting *setting) +gboolean +_nm_setting_option_clear (NMSetting *setting, + const char *optname) { - GVariant *const*values; + GHashTable *ht; - g_return_val_if_fail (NM_IS_SETTING (setting), NULL); + nm_assert (NM_IS_SETTING (setting)); + nm_assert (nm_str_not_empty (optname)); + + ht = _nm_setting_option_hash (setting, FALSE); + if (!ht) + return FALSE; - _nm_setting_gendata_get_all (setting, NULL, &values); - return values; + return g_hash_table_remove (ht, optname); } +/** + * nm_setting_option_clear_by_name: + * @setting: the #NMSetting + * @predicate: (allow-none) (scope call): the predicate for which names + * should be clear. + * If the predicate returns %TRUE for an option name, the option + * gets removed. If %NULL, all options will be removed. + * + * Since: 1.26 + */ void -_nm_setting_gendata_to_gvalue (NMSetting *setting, - GValue *value) +nm_setting_option_clear_by_name (NMSetting *setting, + NMUtilsPredicateStr predicate) { - GenData *gendata; - GHashTable *new; - const char *key; - GVariant *val; + GHashTable *hash; GHashTableIter iter; + const char *name; + gboolean changed = FALSE; - nm_assert (NM_IS_SETTING (setting)); - nm_assert (value); - nm_assert (G_TYPE_CHECK_VALUE_TYPE ((value), G_TYPE_HASH_TABLE)); + g_return_if_fail (NM_IS_SETTING (setting)); - new = g_hash_table_new_full (nm_str_hash, g_str_equal, g_free, (GDestroyNotify) g_variant_unref); + hash = _nm_setting_option_hash (NM_SETTING (setting), FALSE); + if (!hash) + return; - gendata = _gendata_hash (setting, FALSE); - if (gendata) { - g_hash_table_iter_init (&iter, gendata->hash); - while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) - g_hash_table_insert (new, g_strdup (key), g_variant_ref (val)); + if (!predicate) { + changed = (g_hash_table_size (hash) > 0); + if (changed) + g_hash_table_remove_all (hash); + } else { + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, (gpointer *) &name, NULL)) { + if (predicate (name)) { + g_hash_table_iter_remove (&iter); + changed = TRUE; + } + } } - g_value_take_boxed (value, new); + if (changed) + _nm_setting_option_notify (setting, TRUE); } -gboolean -_nm_setting_gendata_reset_from_hash (NMSetting *setting, - GHashTable *new) +/*****************************************************************************/ + +/** + * nm_setting_option_get: + * @setting: the #NMSetting + * @opt_name: the option name to request. + * + * Returns: (transfer none): the #GVariant or %NULL if the option + * is not set. + * + * Since: 1.26. + */ +GVariant * +nm_setting_option_get (NMSetting *setting, + const char *opt_name) { GenData *gendata; - GHashTableIter iter; - const char *key; - GVariant *val; - guint num; - nm_assert (NM_IS_SETTING (setting)); - nm_assert (new); + g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); + g_return_val_if_fail (opt_name, FALSE); - num = new ? g_hash_table_size (new) : 0; + gendata = _gendata_hash (setting, FALSE); + return gendata ? g_hash_table_lookup (gendata->hash, opt_name) : NULL; +} + +/** + * nm_setting_option_get_boolean: + * @setting: the #NMSetting + * @opt_name: the option to get + * @out_value: (allow-none) (out): the optional output value. + * If the option is unset, %FALSE will be returned. + * + * Returns: %TRUE if @opt_name is set to a boolean variant. + * + * Since: 1.26 + */ +gboolean +nm_setting_option_get_boolean (NMSetting *setting, + const char *opt_name, + gboolean *out_value) +{ + GVariant *v; - gendata = _gendata_hash (setting, num > 0); + v = nm_setting_option_get (NM_SETTING (setting), opt_name); + if ( v + && g_variant_is_of_type (v, G_VARIANT_TYPE_BOOLEAN)) { + NM_SET_OUT (out_value, g_variant_get_boolean (v)); + return TRUE; + } + NM_SET_OUT (out_value, FALSE); + return FALSE; +} - if (num == 0) { - if ( !gendata - || g_hash_table_size (gendata->hash) == 0) - return FALSE; +/** + * nm_setting_option_get_uint32: + * @setting: the #NMSetting + * @opt_name: the option to get + * @out_value: (allow-none) (out): the optional output value. + * If the option is unset, 0 will be returned. + * + * Returns: %TRUE if @opt_name is set to a uint32 variant. + * + * Since: 1.26 + */ +gboolean +nm_setting_option_get_uint32 (NMSetting *setting, + const char *opt_name, + guint32 *out_value) +{ + GVariant *v; - g_hash_table_remove_all (gendata->hash); - _nm_setting_gendata_notify (setting, TRUE); + v = nm_setting_option_get (NM_SETTING (setting), opt_name); + if ( v + && g_variant_is_of_type (v, G_VARIANT_TYPE_UINT32)) { + NM_SET_OUT (out_value, g_variant_get_uint32 (v)); return TRUE; } + NM_SET_OUT (out_value, 0); + return FALSE; +} + +/** + * nm_setting_option_set: + * @setting: the #NMSetting + * @opt_name: the option name to set + * @variant: (allow-none): the variant to set. + * + * If @variant is %NULL, this clears the option if it is set. + * Otherwise, @variant is set as the option. If @variant is + * a floating reference, it will be consumed. + * + * Note that not all setting types support options. It is a bug + * setting a variant to a setting that doesn't support it. + * Currently only #NMSettingEthtool supports it. + * + * Since: 1.26 + */ +void +nm_setting_option_set (NMSetting *setting, + const char *opt_name, + GVariant *variant) +{ + GVariant *old_variant; + gboolean changed_name; + gboolean changed_value; + GHashTable *hash; - /* let's not bother to find out whether the new hash has any different - * content the current gendata. Just replace it. */ - g_hash_table_remove_all (gendata->hash); - if (num > 0) { - g_hash_table_iter_init (&iter, new); - while (g_hash_table_iter_next (&iter, (gpointer *) &key, (gpointer *) &val)) - g_hash_table_insert (gendata->hash, g_strdup (key), g_variant_ref (val)); + g_return_if_fail (NM_IS_SETTING (setting)); + g_return_if_fail (opt_name); + + hash = _nm_setting_option_hash (setting, variant != NULL); + + if (!variant) { + if (hash) { + if (g_hash_table_remove (hash, opt_name)) + _nm_setting_option_notify (setting, TRUE); + } + return; } - _nm_setting_gendata_notify (setting, TRUE); - return TRUE; + + /* Currently, it is a bug setting any option, unless the setting type supports it. + * And currently, only NMSettingEthtool supports it. + * + * In the future, more setting types may support it. Or we may relax this so + * that options can be attached to all setting types (to indicate "unsupported" + * settings for forward compatibility). + * + * As it is today, internal code will only add gendata options to NMSettingEthtool, + * and there exists not public API to add such options. Still, it is permissible + * to call get(), clear() and set(variant=NULL) also on settings that don't support + * it, as these operations don't add options. + */ + g_return_if_fail (_nm_setting_class_get_sett_info (NM_SETTING_GET_CLASS (setting))->detail.gendata_info); + + old_variant = g_hash_table_lookup (hash, opt_name); + + changed_name = (old_variant == NULL); + changed_value = changed_name + || !g_variant_equal (old_variant, variant); + + /* We always want to replace the variant, even if it has + * the same value according to g_variant_equal(). The reason + * is that we want to take a reference on @variant, because + * that is what the user might expect. */ + g_hash_table_insert (hash, + g_strdup (opt_name), + g_variant_ref_sink (variant)); + + if (changed_value) + _nm_setting_option_notify (setting, !changed_name); +} + +/** + * nm_setting_option_set_boolean: + * @setting: the #NMSetting + * @value: the value to set. + * + * Like nm_setting_option_set() to set a boolean GVariant. + * + * Since: 1.26 + */ +void +nm_setting_option_set_boolean (NMSetting *setting, + const char *opt_name, + gboolean value) +{ + GVariant *old_variant; + gboolean changed_name; + gboolean changed_value; + GHashTable *hash; + + g_return_if_fail (NM_IS_SETTING (setting)); + g_return_if_fail (opt_name); + + value = (!!value); + + hash = _nm_setting_option_hash (setting, TRUE); + + old_variant = g_hash_table_lookup (hash, opt_name); + + changed_name = (old_variant == NULL); + changed_value = changed_name + || ( !g_variant_is_of_type (old_variant, G_VARIANT_TYPE_BOOLEAN) + || g_variant_get_boolean (old_variant) != value); + + g_hash_table_insert (hash, + g_strdup (opt_name), + g_variant_ref_sink (g_variant_new_boolean (value))); + + if (changed_value) + _nm_setting_option_notify (setting, !changed_name); +} + +/** + * nm_setting_option_set_uint32: + * @setting: the #NMSetting + * @value: the value to set. + * + * Like nm_setting_option_set() to set a uint32 GVariant. + * + * Since: 1.26 + */ +void +nm_setting_option_set_uint32 (NMSetting *setting, + const char *opt_name, + guint32 value) +{ + GVariant *old_variant; + gboolean changed_name; + gboolean changed_value; + GHashTable *hash; + + g_return_if_fail (NM_IS_SETTING (setting)); + g_return_if_fail (opt_name); + + hash = _nm_setting_option_hash (setting, TRUE); + + old_variant = g_hash_table_lookup (hash, opt_name); + + changed_name = (old_variant == NULL); + changed_value = changed_name + || ( !g_variant_is_of_type (old_variant, G_VARIANT_TYPE_UINT32) + || g_variant_get_uint32 (old_variant) != value); + + g_hash_table_insert (hash, + g_strdup (opt_name), + g_variant_ref_sink (g_variant_new_uint32 (value))); + + if (changed_value) + _nm_setting_option_notify (setting, !changed_name); } /*****************************************************************************/ |