diff options
Diffstat (limited to 'libnm-util/nm-setting.c')
| -rw-r--r-- | libnm-util/nm-setting.c | 568 |
1 files changed, 410 insertions, 158 deletions
diff --git a/libnm-util/nm-setting.c b/libnm-util/nm-setting.c index a3186284..0e8a06c4 100644 --- a/libnm-util/nm-setting.c +++ b/libnm-util/nm-setting.c @@ -29,6 +29,7 @@ #include "nm-setting-private.h" #include "nm-setting-connection.h" #include "nm-utils.h" +#include "nm-utils-private.h" /** * SECTION:nm-setting @@ -37,7 +38,7 @@ * * Each #NMSetting contains properties that describe configuration that applies * to a specific network layer (like IPv4 or IPv6 configuration) or device type - * (like Ethernet, or WiFi). A collection of individual settings together + * (like Ethernet, or Wi-Fi). A collection of individual settings together * make up an #NMConnection. Each property is strongly typed and usually has * a number of allowed values. See each #NMSetting subclass for a description * of properties and allowed values. @@ -65,7 +66,14 @@ G_DEFINE_ABSTRACT_TYPE (NMSetting, nm_setting, G_TYPE_OBJECT) #define NM_SETTING_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SETTING, NMSettingPrivate)) typedef struct { - char *name; + const char *name; + GType type; + guint32 priority; + GQuark error_quark; +} SettingInfo; + +typedef struct { + const SettingInfo *info; } NMSettingPrivate; enum { @@ -75,6 +83,197 @@ enum { PROP_LAST }; +/*************************************************************/ + +static GHashTable *registered_settings = NULL; +static GHashTable *registered_settings_by_type = NULL; + +static gboolean +_nm_gtype_equal (gconstpointer v1, gconstpointer v2) +{ + return *((const GType *) v1) == *((const GType *) v2); +} +static guint +_nm_gtype_hash (gconstpointer v) +{ + return *((const GType *) v); +} + +static void __attribute__((constructor)) +_ensure_registered (void) +{ + if (G_UNLIKELY (registered_settings == NULL)) { +#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); + } +} + +#define _ensure_setting_info(self, priv) \ + G_STMT_START { \ + NMSettingPrivate *_priv_esi = (priv); \ + if (G_UNLIKELY (!_priv_esi->info)) { \ + _priv_esi->info = _nm_setting_lookup_setting_by_type (G_OBJECT_TYPE (self)); \ + g_assert (_priv_esi->info); \ + } \ + } G_STMT_END + +/*************************************************************/ + +/* + * _nm_register_setting: + * @name: the name of the #NMSetting object to register + * @type: the #GType of the #NMSetting + * @priority: the sort priority of the setting, see below + * @error_quark: the setting's error quark + * + * INTERNAL ONLY: registers a setting's internal properties, like its priority + * and its error quark type, with libnm-util. + * + * A setting's priority should roughly follow the OSI layer model, but it also + * controls which settings get asked for secrets first. Thus settings which + * relate to things that must be working first, like hardware, should get a + * higher priority than things which layer on top of the hardware. For example, + * the GSM/CDMA settings should provide secrets before the PPP setting does, + * because a PIN is required to unlock the device before PPP can even start. + * Even settings without secrets should be assigned the right priority. + * + * 0: reserved for the Connection setting + * + * 1: hardware-related settings like Ethernet, Wi-Fi, InfiniBand, Bridge, etc. + * These priority 1 settings are also "base types", which means that at least + * one of them is required for the connection to be valid, and their name is + * valid in the 'type' property of the Connection setting. + * + * 2: hardware-related auxiliary settings that require a base setting to be + * successful first, like Wi-Fi security, 802.1x, etc. + * + * 3: hardware-independent settings that are required before IP connectivity + * can be established, like PPP, PPPoE, etc. + * + * 4: IP-level stuff + */ +void +(_nm_register_setting) (const char *name, + const GType type, + const guint32 priority, + const GQuark error_quark) +{ + SettingInfo *info; + + g_return_if_fail (name != NULL && *name); + g_return_if_fail (type != G_TYPE_INVALID); + g_return_if_fail (type != G_TYPE_NONE); + g_return_if_fail (error_quark != 0); + g_return_if_fail (priority <= 4); + + _ensure_registered (); + + if (G_LIKELY ((info = g_hash_table_lookup (registered_settings, name)))) { + g_return_if_fail (info->type == type); + g_return_if_fail (info->error_quark == error_quark); + g_return_if_fail (info->priority == priority); + g_return_if_fail (g_strcmp0 (info->name, name) == 0); + return; + } + g_return_if_fail (g_hash_table_lookup (registered_settings_by_type, &type) == NULL); + + if (priority == 0) + g_assert_cmpstr (name, ==, NM_SETTING_CONNECTION_SETTING_NAME); + + info = g_slice_new0 (SettingInfo); + info->type = type; + info->priority = priority; + info->error_quark = error_quark; + info->name = name; + g_hash_table_insert (registered_settings, (void *) info->name, info); + g_hash_table_insert (registered_settings_by_type, &info->type, info); +} + +static const SettingInfo * +_nm_setting_lookup_setting_by_type (GType type) +{ + _ensure_registered (); + return g_hash_table_lookup (registered_settings_by_type, &type); +} + +static guint32 +_get_setting_type_priority (GType type) +{ + const SettingInfo *info; + + g_return_val_if_fail (g_type_is_a (type, NM_TYPE_SETTING), G_MAXUINT32); + + info = _nm_setting_lookup_setting_by_type (type); + return info->priority; +} + +gboolean +_nm_setting_type_is_base_type (GType type) +{ + /* Historical oddity: PPPoE is a base-type even though it's not + * priority 1. It needs to be sorted *after* lower-level stuff like + * Wi-Fi security or 802.1x for secrets, but it's still allowed as a + * base type. + */ + return _get_setting_type_priority (type) == 1 || (type == NM_TYPE_SETTING_PPPOE); +} + +gboolean +_nm_setting_is_base_type (NMSetting *setting) +{ + return _nm_setting_type_is_base_type (G_OBJECT_TYPE (setting)); +} + +GType +_nm_setting_lookup_setting_type (const char *name) +{ + SettingInfo *info; + + g_return_val_if_fail (name != NULL, G_TYPE_NONE); + + _ensure_registered (); + + info = g_hash_table_lookup (registered_settings, name); + return info ? info->type : G_TYPE_INVALID; +} + +GType +_nm_setting_lookup_setting_type_by_quark (GQuark error_quark) +{ + SettingInfo *info; + GHashTableIter iter; + + _ensure_registered (); + + g_hash_table_iter_init (&iter, registered_settings); + while (g_hash_table_iter_next (&iter, NULL, (gpointer) &info)) { + if (info->error_quark == error_quark) + return info->type; + } + return G_TYPE_INVALID; +} + +gint +_nm_setting_compare_priority (gconstpointer a, gconstpointer b) +{ + guint32 prio_a, prio_b; + + prio_a = _get_setting_type_priority (G_OBJECT_TYPE (a)); + prio_b = _get_setting_type_priority (G_OBJECT_TYPE (b)); + + if (prio_a < prio_b) + return -1; + else if (prio_a == prio_b) + return 0; + return 1; +} + +/*************************************************************/ + static void destroy_gvalue (gpointer data) { @@ -104,7 +303,6 @@ nm_setting_to_hash (NMSetting *setting, NMSettingHashFlags flags) guint n_property_specs; guint i; - g_return_val_if_fail (setting != NULL, NULL); g_return_val_if_fail (NM_IS_SETTING (setting), NULL); property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); @@ -121,7 +319,8 @@ nm_setting_to_hash (NMSetting *setting, NMSettingHashFlags flags) GParamSpec *prop_spec = property_specs[i]; GValue *value; - if (!(prop_spec->flags & NM_SETTING_PARAM_SERIALIZE)) + /* 'name' doesn't get serialized */ + if (strcmp (g_param_spec_get_name (prop_spec), NM_SETTING_NAME) == 0) continue; if ( (flags & NM_SETTING_HASH_FLAG_NO_SECRETS) @@ -144,8 +343,8 @@ nm_setting_to_hash (NMSetting *setting, NMSettingHashFlags flags) } g_free (property_specs); - /* Don't return empty hashes */ - if (g_hash_table_size (hash) < 1) { + /* 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; } @@ -153,39 +352,6 @@ nm_setting_to_hash (NMSetting *setting, NMSettingHashFlags flags) return hash; } -typedef struct { - GObjectClass *class; - guint n_params; - GParameter *params; -} NMSettingFromHashInfo; - -static void -one_property_cb (gpointer key, gpointer val, gpointer user_data) -{ - const char *prop_name = (char *) key; - GValue *src_value = (GValue *) val; - NMSettingFromHashInfo *info = (NMSettingFromHashInfo *) user_data; - GValue *dst_value = &info->params[info->n_params].value; - GParamSpec *param_spec; - - param_spec = g_object_class_find_property (info->class, prop_name); - if (!param_spec || !(param_spec->flags & NM_SETTING_PARAM_SERIALIZE)) { - /* Oh, we're so nice and only warn, maybe it should be a fatal error? */ - g_warning ("Ignoring invalid property '%s'", prop_name); - return; - } - - g_value_init (dst_value, G_VALUE_TYPE (src_value)); - if (g_value_transform (src_value, dst_value)) { - info->params[info->n_params].name = prop_name; - info->n_params++; - } else { - g_warning ("Ignoring property '%s' with invalid type (%s)", - prop_name, G_VALUE_TYPE_NAME (src_value)); - g_value_unset (dst_value); - } -} - /** * nm_setting_new_from_hash: * @setting_type: the #NMSetting type which the hash contains properties for @@ -205,28 +371,53 @@ one_property_cb (gpointer key, gpointer val, gpointer user_data) NMSetting * nm_setting_new_from_hash (GType setting_type, GHashTable *hash) { + GHashTableIter iter; NMSetting *setting; - NMSettingFromHashInfo info; + const char *prop_name; + GValue *src_value; + GObjectClass *class; + guint n_params = 0; + GParameter *params; int i; g_return_val_if_fail (G_TYPE_IS_INSTANTIATABLE (setting_type), NULL); g_return_val_if_fail (hash != NULL, NULL); - info.class = g_type_class_ref (setting_type); - info.n_params = 0; - info.params = g_new0 (GParameter, g_hash_table_size (hash)); + /* g_type_class_ref() ensures the setting class is created if it hasn't + * already been used. + */ + class = g_type_class_ref (setting_type); + params = g_new0 (GParameter, g_hash_table_size (hash)); + + g_hash_table_iter_init (&iter, hash); + while (g_hash_table_iter_next (&iter, (gpointer) &prop_name, (gpointer) &src_value)) { + GValue *dst_value = ¶ms[n_params].value; + GParamSpec *param_spec; + + param_spec = g_object_class_find_property (class, prop_name); + if (!param_spec) { + /* Oh, we're so nice and only warn, maybe it should be a fatal error? */ + g_warning ("Ignoring invalid property '%s'", prop_name); + continue; + } - g_hash_table_foreach (hash, one_property_cb, &info); + g_value_init (dst_value, G_VALUE_TYPE (src_value)); + if (g_value_transform (src_value, dst_value)) + params[n_params++].name = prop_name; + else { + g_warning ("Ignoring property '%s' with invalid type (%s)", + prop_name, G_VALUE_TYPE_NAME (src_value)); + g_value_unset (dst_value); + } + } - setting = (NMSetting *) g_object_newv (setting_type, info.n_params, info.params); + setting = (NMSetting *) g_object_newv (setting_type, n_params, params); - for (i = 0; i < info.n_params; i++) { - GValue *v = &info.params[i].value; - g_value_unset (v); - } + for (i = 0; i < n_params; i++) + g_value_unset (¶ms[i].value); - g_free (info.params); - g_type_class_unref (info.class); + g_free (params); + g_type_class_unref (class); return setting; } @@ -238,7 +429,7 @@ duplicate_setting (NMSetting *setting, GParamFlags flags, gpointer user_data) { - if (flags & G_PARAM_WRITABLE) + if ((flags & (G_PARAM_WRITABLE | G_PARAM_CONSTRUCT_ONLY)) == G_PARAM_WRITABLE) g_object_set_property (G_OBJECT (user_data), name, value); } @@ -267,6 +458,28 @@ nm_setting_duplicate (NMSetting *setting) return NM_SETTING (dup); } +static gint +find_setting_by_name (gconstpointer a, gconstpointer b) +{ + NMSetting *setting = NM_SETTING (a); + const char *str = (const char *) b; + + return strcmp (nm_setting_get_name (setting), str); +} + +NMSetting * +nm_setting_find_in_list (GSList *settings_list, + const char *setting_name) +{ + GSList *found; + + found = g_slist_find_custom (settings_list, setting_name, find_setting_by_name); + if (found) + return found->data; + else + return NULL; +} + /** * nm_setting_get_name: * @setting: the #NMSetting @@ -279,9 +492,12 @@ nm_setting_duplicate (NMSetting *setting) const char * nm_setting_get_name (NMSetting *setting) { - g_return_val_if_fail (NM_IS_SETTING (setting), NULL); + NMSettingPrivate *priv; - return NM_SETTING_GET_PRIVATE (setting)->name; + g_return_val_if_fail (NM_IS_SETTING (setting), NULL); + priv = NM_SETTING_GET_PRIVATE (setting); + _ensure_setting_info (setting, priv); + return priv->info->name; } /** @@ -302,8 +518,7 @@ gboolean nm_setting_verify (NMSetting *setting, GSList *all_settings, GError **error) { g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); - if (error) - g_return_val_if_fail (*error == NULL, FALSE); + g_return_val_if_fail (!error || *error == NULL, FALSE); if (NM_SETTING_GET_CLASS (setting)->verify) return NM_SETTING_GET_CLASS (setting)->verify (setting, all_settings, error); @@ -317,8 +532,8 @@ compare_property (NMSetting *setting, const GParamSpec *prop_spec, NMSettingCompareFlags flags) { - GValue value1 = { 0 }; - GValue value2 = { 0 }; + GValue value1 = G_VALUE_INIT; + GValue value2 = G_VALUE_INIT; gboolean different; /* Handle compare flags */ @@ -398,6 +613,9 @@ nm_setting_compare (NMSetting *a, && (prop_spec->flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET))) continue; + if ((flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_spec->flags & NM_SETTING_PARAM_INFERRABLE)) + continue; + if ( (flags & NM_SETTING_COMPARE_FLAG_IGNORE_SECRETS) && (prop_spec->flags & NM_SETTING_PARAM_SECRET)) continue; @@ -420,6 +638,9 @@ should_compare_prop (NMSetting *setting, && (prop_flags & (NM_SETTING_PARAM_FUZZY_IGNORE | NM_SETTING_PARAM_SECRET))) return FALSE; + if ((comp_flags & NM_SETTING_COMPARE_FLAG_INFERRABLE) && !(prop_flags & NM_SETTING_PARAM_INFERRABLE)) + return FALSE; + if (prop_flags & NM_SETTING_PARAM_SECRET) { NMSettingSecretFlags secret_flags = NM_SETTING_SECRET_FLAG_NONE; @@ -481,7 +702,6 @@ nm_setting_diff (NMSetting *a, gboolean results_created = FALSE; g_return_val_if_fail (results != NULL, FALSE); - g_return_val_if_fail (a != NULL, FALSE); g_return_val_if_fail (NM_IS_SETTING (a), FALSE); if (b) { g_return_val_if_fail (NM_IS_SETTING (b), FALSE); @@ -512,7 +732,6 @@ nm_setting_diff (NMSetting *a, for (i = 0; i < n_property_specs; i++) { GParamSpec *prop_spec = property_specs[i]; - GValue a_value = { 0 }, b_value = { 0 }; NMSettingDiffResult r = NM_SETTING_DIFF_RESULT_UNKNOWN, tmp; gboolean different = TRUE; @@ -523,22 +742,22 @@ nm_setting_diff (NMSetting *a, continue; if (b) { - g_value_init (&a_value, prop_spec->value_type); - g_object_get_property (G_OBJECT (a), prop_spec->name, &a_value); - - g_value_init (&b_value, prop_spec->value_type); - g_object_get_property (G_OBJECT (b), prop_spec->name, &b_value); - - different = !!g_param_values_cmp (prop_spec, &a_value, &b_value); + different = !NM_SETTING_GET_CLASS (a)->compare_property (a, b, prop_spec, flags); if (different) { - if (!g_param_value_defaults (prop_spec, &a_value)) + GValue value = G_VALUE_INIT; + + g_value_init (&value, prop_spec->value_type); + g_object_get_property (G_OBJECT (a), prop_spec->name, &value); + if (!g_param_value_defaults (prop_spec, &value)) r |= a_result; - if (!g_param_value_defaults (prop_spec, &b_value)) + + g_value_reset (&value); + g_object_get_property (G_OBJECT (b), prop_spec->name, &value); + if (!g_param_value_defaults (prop_spec, &value)) r |= b_result; - } - g_value_unset (&a_value); - g_value_unset (&b_value); + g_value_unset (&value); + } } else r = a_result; /* only in A */ @@ -582,7 +801,7 @@ nm_setting_enumerate_values (NMSetting *setting, property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); for (i = 0; i < n_property_specs; i++) { GParamSpec *prop_spec = property_specs[i]; - GValue value = { 0 }; + GValue value = G_VALUE_INIT; g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (prop_spec)); g_object_get_property (G_OBJECT (setting), prop_spec->name, &value); @@ -604,46 +823,68 @@ nm_setting_enumerate_values (NMSetting *setting, void nm_setting_clear_secrets (NMSetting *setting) { + _nm_setting_clear_secrets (setting); +} + +gboolean +_nm_setting_clear_secrets (NMSetting *setting) +{ GParamSpec **property_specs; guint n_property_specs; guint i; + gboolean changed = FALSE; - g_return_if_fail (NM_IS_SETTING (setting)); + g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); for (i = 0; i < n_property_specs; i++) { GParamSpec *prop_spec = property_specs[i]; - GValue value = { 0 }; if (prop_spec->flags & NM_SETTING_PARAM_SECRET) { + GValue value = G_VALUE_INIT; + g_value_init (&value, prop_spec->value_type); - g_param_value_set_default (prop_spec, &value); - g_object_set_property (G_OBJECT (setting), prop_spec->name, &value); + g_object_get_property (G_OBJECT (setting), prop_spec->name, &value); + if (!g_param_value_defaults (prop_spec, &value)) { + g_param_value_set_default (prop_spec, &value); + g_object_set_property (G_OBJECT (setting), prop_spec->name, &value); + changed = TRUE; + } g_value_unset (&value); } } g_free (property_specs); + + return changed; } -static void +static gboolean clear_secrets_with_flags (NMSetting *setting, GParamSpec *pspec, NMSettingClearSecretsWithFlagsFn func, gpointer user_data) { - GValue value = { 0 }; NMSettingSecretFlags flags = NM_SETTING_SECRET_FLAG_NONE; + gboolean changed = FALSE; /* Clear the secret if the user function says to do so */ nm_setting_get_secret_flags (setting, pspec->name, &flags, NULL); if (func (setting, pspec->name, flags, user_data) == TRUE) { + GValue value = G_VALUE_INIT; + g_value_init (&value, pspec->value_type); - g_param_value_set_default (pspec, &value); - g_object_set_property (G_OBJECT (setting), pspec->name, &value); + g_object_get_property (G_OBJECT (setting), pspec->name, &value); + if (!g_param_value_defaults (pspec, &value)) { + g_param_value_set_default (pspec, &value); + g_object_set_property (G_OBJECT (setting), pspec->name, &value); + changed = TRUE; + } g_value_unset (&value); } + + return changed; } /** @@ -660,25 +901,35 @@ nm_setting_clear_secrets_with_flags (NMSetting *setting, NMSettingClearSecretsWithFlagsFn func, gpointer user_data) { + _nm_setting_clear_secrets_with_flags (setting, func, user_data); +} + +gboolean +_nm_setting_clear_secrets_with_flags (NMSetting *setting, + NMSettingClearSecretsWithFlagsFn func, + gpointer user_data) +{ GParamSpec **property_specs; guint n_property_specs; guint i; + gboolean changed = FALSE; - g_return_if_fail (setting); - g_return_if_fail (NM_IS_SETTING (setting)); - g_return_if_fail (func != NULL); + g_return_val_if_fail (setting, FALSE); + g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); + g_return_val_if_fail (func != NULL, FALSE); property_specs = g_object_class_list_properties (G_OBJECT_GET_CLASS (setting), &n_property_specs); for (i = 0; i < n_property_specs; i++) { if (property_specs[i]->flags & NM_SETTING_PARAM_SECRET) { - NM_SETTING_GET_CLASS (setting)->clear_secrets_with_flags (setting, - property_specs[i], - func, - user_data); + changed |= NM_SETTING_GET_CLASS (setting)->clear_secrets_with_flags (setting, + property_specs[i], + func, + user_data); } } g_free (property_specs); + return changed; } /** @@ -708,12 +959,11 @@ nm_setting_need_secrets (NMSetting *setting) return secrets; } -static gboolean +static int update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **error) { GParamSpec *prop_spec; - GValue transformed_value = { 0 }; - gboolean success = FALSE; + GValue transformed_value = G_VALUE_INIT; prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key); if (!prop_spec) { @@ -721,27 +971,40 @@ update_one_secret (NMSetting *setting, const char *key, GValue *value, GError ** NM_SETTING_ERROR, NM_SETTING_ERROR_PROPERTY_NOT_FOUND, "%s", key); - return FALSE; + return NM_SETTING_UPDATE_SECRET_ERROR; } /* Silently ignore non-secrets */ if (!(prop_spec->flags & NM_SETTING_PARAM_SECRET)) - return TRUE; + 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; + } + g_free (v); + } g_object_set_property (G_OBJECT (setting), prop_spec->name, value); - success = TRUE; - } else if (g_value_transform (value, &transformed_value)) { + return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; + } + if (g_value_transform (value, &transformed_value)) { g_object_set_property (G_OBJECT (setting), prop_spec->name, &transformed_value); g_value_unset (&transformed_value); - success = TRUE; - } else { - g_set_error (error, - NM_SETTING_ERROR, - NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, - "%s", key); + return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; } - return success; + g_set_error (error, + NM_SETTING_ERROR, + NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, + "%s", key); + return NM_SETTING_UPDATE_SECRET_ERROR; } /** @@ -760,29 +1023,41 @@ update_one_secret (NMSetting *setting, const char *key, GValue *value, GError ** gboolean nm_setting_update_secrets (NMSetting *setting, GHashTable *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) +{ GHashTableIter iter; gpointer key, data; GError *tmp_error = NULL; + NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED; - g_return_val_if_fail (setting != NULL, FALSE); - g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); - g_return_val_if_fail (secrets != NULL, FALSE); + 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); if (error) - g_return_val_if_fail (*error == NULL, FALSE); + 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)) { + int success; const char *secret_key = (const char *) key; GValue *secret_value = (GValue *) data; - NM_SETTING_GET_CLASS (setting)->update_one_secret (setting, secret_key, secret_value, &tmp_error); - if (tmp_error) { + 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))); + + if (success == NM_SETTING_UPDATE_SECRET_ERROR) { g_propagate_error (error, tmp_error); - return FALSE; + return NM_SETTING_UPDATE_SECRET_ERROR; } + + if (success == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED) + result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED; } - return TRUE; + return result; } static gboolean @@ -851,7 +1126,6 @@ nm_setting_get_secret_flags (NMSetting *setting, NMSettingSecretFlags *out_flags, GError **error) { - g_return_val_if_fail (setting != NULL, FALSE); g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); g_return_val_if_fail (secret_name != NULL, FALSE); @@ -883,7 +1157,7 @@ set_secret_flags (NMSetting *setting, * @flags: the #NMSettingSecretFlags for the secret * @error: location to store error, or %NULL * - * For a given secret, retrieves the #NMSettingSecretFlags describing how to + * For a given secret, stores the #NMSettingSecretFlags describing how to * handle that secret. * * Returns: %TRUE on success (if the given secret name was a valid property of @@ -895,7 +1169,6 @@ nm_setting_set_secret_flags (NMSetting *setting, NMSettingSecretFlags flags, GError **error) { - g_return_val_if_fail (setting != NULL, FALSE); g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); g_return_val_if_fail (secret_name != NULL, FALSE); g_return_val_if_fail (flags <= NM_SETTING_SECRET_FLAGS_ALL, FALSE); @@ -934,11 +1207,13 @@ nm_setting_to_string (NMSetting *setting) for (i = 0; i < n_property_specs; i++) { GParamSpec *prop_spec = property_specs[i]; - GValue value = { 0 }; + GValue value = G_VALUE_INIT; char *value_str; - gboolean is_serializable; gboolean is_default; + if (strcmp (prop_spec->name, NM_SETTING_NAME) == 0) + continue; + g_value_init (&value, prop_spec->value_type); g_object_get_property (G_OBJECT (setting), prop_spec->name, &value); @@ -946,22 +1221,14 @@ nm_setting_to_string (NMSetting *setting) g_string_append_printf (string, "\t%s : %s", prop_spec->name, value_str); g_free (value_str); - is_serializable = prop_spec->flags & NM_SETTING_PARAM_SERIALIZE; is_default = g_param_value_defaults (prop_spec, &value); - g_value_unset (&value); - if (is_serializable || is_default) { - g_string_append (string, " ("); - - if (is_serializable) - g_string_append_c (string, 's'); - if (is_default) - g_string_append_c (string, 'd'); - - g_string_append_c (string, ')'); - } - + g_string_append (string, " ("); + g_string_append_c (string, 's'); + if (is_default) + g_string_append_c (string, 'd'); + g_string_append_c (string, ')'); g_string_append_c (string, '\n'); } @@ -1001,48 +1268,34 @@ nm_setting_init (NMSetting *setting) static GObject* constructor (GType type, - guint n_construct_params, - GObjectConstructParam *construct_params) + guint n_construct_params, + GObjectConstructParam *construct_params) { GObject *object; - NMSettingPrivate *priv; object = G_OBJECT_CLASS (nm_setting_parent_class)->constructor (type, - n_construct_params, - construct_params); - if (!object) - return NULL; - - priv = NM_SETTING_GET_PRIVATE (object); - if (!priv->name) { - g_warning ("Setting name is not set."); - g_object_unref (object); - object = NULL; - } + n_construct_params, + construct_params); + _ensure_setting_info (object, NM_SETTING_GET_PRIVATE (object)); return object; } static void -finalize (GObject *object) -{ - NMSettingPrivate *priv = NM_SETTING_GET_PRIVATE (object); - - g_free (priv->name); - - G_OBJECT_CLASS (nm_setting_parent_class)->finalize (object); -} - -static void set_property (GObject *object, guint prop_id, - const GValue *value, GParamSpec *pspec) + const GValue *value, GParamSpec *pspec) { NMSettingPrivate *priv = NM_SETTING_GET_PRIVATE (object); switch (prop_id) { case PROP_NAME: - g_free (priv->name); - priv->name = g_value_dup_string (value); + /* The setter for NAME is deprecated and should not be used anymore. + * Keep the setter for NAME to remain backward compatible. + * Only assert that the caller does not try to set the name to a different value + * then the registered name, which would be extra wrong. + **/ + _ensure_setting_info (object, priv); + g_return_if_fail (!g_strcmp0 (priv->info->name, g_value_get_string (value))); break; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -1052,7 +1305,7 @@ set_property (GObject *object, guint prop_id, static void get_property (GObject *object, guint prop_id, - GValue *value, GParamSpec *pspec) + GValue *value, GParamSpec *pspec) { NMSetting *setting = NM_SETTING (object); @@ -1077,7 +1330,6 @@ nm_setting_class_init (NMSettingClass *setting_class) object_class->constructor = constructor; object_class->set_property = set_property; object_class->get_property = get_property; - object_class->finalize = finalize; setting_class->update_one_secret = update_one_secret; setting_class->get_secret_flags = get_secret_flags; @@ -1092,7 +1344,7 @@ nm_setting_class_init (NMSettingClass *setting_class) * * The setting's name, which uniquely identifies the setting within the * connection. Each setting type has a name unique to that type, for - * example 'ppp' or 'wireless' or 'wired'. + * example "ppp" or "wireless" or "wired". **/ g_object_class_install_property (object_class, PROP_NAME, |