Commit 123bf9ee authored by Thomas Haller's avatar Thomas Haller

libnm-util: raise CHANGED signal in nm_connection_update_secrets only on change

This changes behaviour of nm_connection_update_secrets() in that it will
now return %TRUE, if there are no secrets to be cleared. Seems more
correct, to return success if there is nothing to do.
Signed-off-by: Thomas Haller's avatarThomas Haller <thaller@redhat.com>
parent 0f382131
...@@ -676,11 +676,12 @@ nm_connection_update_secrets (NMConnection *connection, ...@@ -676,11 +676,12 @@ nm_connection_update_secrets (NMConnection *connection,
GError **error) GError **error)
{ {
NMSetting *setting; NMSetting *setting;
gboolean success = FALSE, updated = FALSE; gboolean success = TRUE, updated = FALSE;
GHashTable *setting_hash = NULL; GHashTable *setting_hash = NULL;
GHashTableIter iter; GHashTableIter iter;
const char *key; const char *key;
gboolean hashed_connection = FALSE; gboolean hashed_connection = FALSE;
int success_detail;
g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE); g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
g_return_val_if_fail (secrets != NULL, FALSE); g_return_val_if_fail (secrets != NULL, FALSE);
...@@ -721,15 +722,20 @@ nm_connection_update_secrets (NMConnection *connection, ...@@ -721,15 +722,20 @@ nm_connection_update_secrets (NMConnection *connection,
/* The hashed connection that didn't contain any secrets for /* The hashed connection that didn't contain any secrets for
* @setting_name; just return success. * @setting_name; just return success.
*/ */
success = TRUE; return TRUE;
} }
} }
if (!success) { g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
updated = success = nm_setting_update_secrets (setting, success_detail = _nm_setting_update_secrets (setting,
setting_hash ? setting_hash : secrets, setting_hash ? setting_hash : secrets,
error); error);
} g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
if (success_detail == NM_SETTING_UPDATE_SECRET_ERROR)
return FALSE;
if (success_detail == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
updated = TRUE;
} else { } else {
if (!hashed_connection) { if (!hashed_connection) {
g_set_error_literal (error, g_set_error_literal (error,
...@@ -739,9 +745,9 @@ nm_connection_update_secrets (NMConnection *connection, ...@@ -739,9 +745,9 @@ nm_connection_update_secrets (NMConnection *connection,
return FALSE; return FALSE;
} }
/* Update each setting with any secrets from the hashed connection */ /* check first, whether all the settings exist... */
g_hash_table_iter_init (&iter, secrets); g_hash_table_iter_init (&iter, secrets);
while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &setting_hash)) { while (g_hash_table_iter_next (&iter, (gpointer) &key, NULL)) {
setting = nm_connection_get_setting_by_name (connection, key); setting = nm_connection_get_setting_by_name (connection, key);
if (!setting) { if (!setting) {
g_set_error_literal (error, g_set_error_literal (error,
...@@ -750,13 +756,24 @@ nm_connection_update_secrets (NMConnection *connection, ...@@ -750,13 +756,24 @@ nm_connection_update_secrets (NMConnection *connection,
key); key);
return FALSE; return FALSE;
} }
}
/* Update each setting with any secrets from the hashed connection */
g_hash_table_iter_init (&iter, secrets);
while (g_hash_table_iter_next (&iter, (gpointer) &key, (gpointer) &setting_hash)) {
/* Update the secrets for this setting */ /* Update the secrets for this setting */
success = nm_setting_update_secrets (setting, setting_hash, error); setting = nm_connection_get_setting_by_name (connection, key);
if (success)
updated = TRUE; g_signal_handlers_block_by_func (setting, (GCallback) setting_changed_cb, connection);
else success_detail = _nm_setting_update_secrets (setting, setting_hash, error);
g_signal_handlers_unblock_by_func (setting, (GCallback) setting_changed_cb, connection);
if (success_detail == NM_SETTING_UPDATE_SECRET_ERROR) {
success = FALSE;
break; break;
}
if (success_detail == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
updated = TRUE;
} }
} }
......
...@@ -42,6 +42,15 @@ GType _nm_setting_lookup_setting_type (const char *name); ...@@ -42,6 +42,15 @@ GType _nm_setting_lookup_setting_type (const char *name);
GType _nm_setting_lookup_setting_type_by_quark (GQuark error_quark); GType _nm_setting_lookup_setting_type_by_quark (GQuark error_quark);
gint _nm_setting_compare_priority (gconstpointer a, gconstpointer b); gint _nm_setting_compare_priority (gconstpointer a, gconstpointer b);
typedef enum NMSettingUpdateSecretResult {
NM_SETTING_UPDATE_SECRET_ERROR = FALSE,
NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED = TRUE,
NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED = 2,
} NMSettingUpdateSecretResult;
NMSettingUpdateSecretResult _nm_setting_update_secrets (NMSetting *setting,
GHashTable *secrets,
GError **error);
gboolean _nm_setting_clear_secrets (NMSetting *setting); gboolean _nm_setting_clear_secrets (NMSetting *setting);
gboolean _nm_setting_clear_secrets_with_flags (NMSetting *setting, gboolean _nm_setting_clear_secrets_with_flags (NMSetting *setting,
NMSettingClearSecretsWithFlagsFn func, NMSettingClearSecretsWithFlagsFn func,
......
...@@ -429,7 +429,7 @@ verify (NMSetting *setting, GSList *all_settings, GError **error) ...@@ -429,7 +429,7 @@ verify (NMSetting *setting, GSList *all_settings, GError **error)
return TRUE; return TRUE;
} }
static gboolean static NMSettingUpdateSecretResult
update_secret_string (NMSetting *setting, update_secret_string (NMSetting *setting,
const char *key, const char *key,
const char *value, const char *value,
...@@ -437,21 +437,24 @@ update_secret_string (NMSetting *setting, ...@@ -437,21 +437,24 @@ update_secret_string (NMSetting *setting,
{ {
NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting); NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
g_return_val_if_fail (key != NULL, FALSE); g_return_val_if_fail (key != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
g_return_val_if_fail (value != NULL, FALSE); g_return_val_if_fail (value != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
if (!value || !strlen (value)) { if (!value || !strlen (value)) {
g_set_error (error, NM_SETTING_ERROR, g_set_error (error, NM_SETTING_ERROR,
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
"Secret %s was empty", key); "Secret %s was empty", key);
return FALSE; return NM_SETTING_UPDATE_SECRET_ERROR;
} }
if (g_strcmp0 (g_hash_table_lookup (priv->secrets, key), value) == 0)
return NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
g_hash_table_insert (priv->secrets, g_strdup (key), g_strdup (value)); g_hash_table_insert (priv->secrets, g_strdup (key), g_strdup (value));
return TRUE; return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
} }
static gboolean static NMSettingUpdateSecretResult
update_secret_hash (NMSetting *setting, update_secret_hash (NMSetting *setting,
GHashTable *secrets, GHashTable *secrets,
GError **error) GError **error)
...@@ -459,8 +462,9 @@ update_secret_hash (NMSetting *setting, ...@@ -459,8 +462,9 @@ update_secret_hash (NMSetting *setting,
NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting); NMSettingVPNPrivate *priv = NM_SETTING_VPN_GET_PRIVATE (setting);
GHashTableIter iter; GHashTableIter iter;
const char *name, *value; const char *name, *value;
NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
g_return_val_if_fail (secrets != NULL, FALSE); g_return_val_if_fail (secrets != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
/* Make sure the items are valid */ /* Make sure the items are valid */
g_hash_table_iter_init (&iter, secrets); g_hash_table_iter_init (&iter, secrets);
...@@ -469,14 +473,14 @@ update_secret_hash (NMSetting *setting, ...@@ -469,14 +473,14 @@ update_secret_hash (NMSetting *setting,
g_set_error_literal (error, NM_SETTING_ERROR, g_set_error_literal (error, NM_SETTING_ERROR,
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
"Secret name was empty"); "Secret name was empty");
return FALSE; return NM_SETTING_UPDATE_SECRET_ERROR;
} }
if (!value || !strlen (value)) { if (!value || !strlen (value)) {
g_set_error (error, NM_SETTING_ERROR, g_set_error (error, NM_SETTING_ERROR,
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
"Secret %s value was empty", name); "Secret %s value was empty", name);
return FALSE; return NM_SETTING_UPDATE_SECRET_ERROR;
} }
} }
...@@ -492,19 +496,23 @@ update_secret_hash (NMSetting *setting, ...@@ -492,19 +496,23 @@ update_secret_hash (NMSetting *setting,
continue; continue;
} }
if (g_strcmp0 (g_hash_table_lookup (priv->secrets, name), value) == 0)
continue;
g_hash_table_insert (priv->secrets, g_strdup (name), g_strdup (value)); g_hash_table_insert (priv->secrets, g_strdup (name), g_strdup (value));
result = NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
} }
return TRUE; return result;
} }
static gboolean static int
update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **error) update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **error)
{ {
gboolean success = FALSE; NMSettingUpdateSecretResult success = NM_SETTING_UPDATE_SECRET_ERROR;
g_return_val_if_fail (key != NULL, FALSE); g_return_val_if_fail (key != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
g_return_val_if_fail (value != NULL, FALSE); g_return_val_if_fail (value != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
if (G_VALUE_HOLDS_STRING (value)) { if (G_VALUE_HOLDS_STRING (value)) {
/* Passing the string properties individually isn't correct, and won't /* Passing the string properties individually isn't correct, and won't
...@@ -522,7 +530,7 @@ update_one_secret (NMSetting *setting, const char *key, GValue *value, GError ** ...@@ -522,7 +530,7 @@ update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **
} else } else
g_set_error_literal (error, NM_SETTING_ERROR, NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, key); g_set_error_literal (error, NM_SETTING_ERROR, NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH, key);
if (success) if (success == NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED)
g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_SECRETS); g_object_notify (G_OBJECT (setting), NM_SETTING_VPN_SECRETS);
return success; return success;
......
...@@ -951,12 +951,11 @@ nm_setting_need_secrets (NMSetting *setting) ...@@ -951,12 +951,11 @@ nm_setting_need_secrets (NMSetting *setting)
return secrets; return secrets;
} }
static gboolean static int
update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **error) update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **error)
{ {
GParamSpec *prop_spec; GParamSpec *prop_spec;
GValue transformed_value = G_VALUE_INIT; GValue transformed_value = G_VALUE_INIT;
gboolean success = FALSE;
prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key); prop_spec = g_object_class_find_property (G_OBJECT_GET_CLASS (setting), key);
if (!prop_spec) { if (!prop_spec) {
...@@ -964,27 +963,40 @@ update_one_secret (NMSetting *setting, const char *key, GValue *value, GError ** ...@@ -964,27 +963,40 @@ update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **
NM_SETTING_ERROR, NM_SETTING_ERROR,
NM_SETTING_ERROR_PROPERTY_NOT_FOUND, NM_SETTING_ERROR_PROPERTY_NOT_FOUND,
"%s", key); "%s", key);
return FALSE; return NM_SETTING_UPDATE_SECRET_ERROR;
} }
/* Silently ignore non-secrets */ /* Silently ignore non-secrets */
if (!(prop_spec->flags & NM_SETTING_PARAM_SECRET)) 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_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); g_object_set_property (G_OBJECT (setting), prop_spec->name, value);
success = TRUE; return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
} else if (g_value_transform (value, &transformed_value)) { }
if (g_value_transform (value, &transformed_value)) {
g_object_set_property (G_OBJECT (setting), prop_spec->name, &transformed_value); g_object_set_property (G_OBJECT (setting), prop_spec->name, &transformed_value);
g_value_unset (&transformed_value); g_value_unset (&transformed_value);
success = TRUE; return NM_SETTING_UPDATE_SECRET_SUCCESS_MODIFIED;
} else {
g_set_error (error,
NM_SETTING_ERROR,
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
"%s", key);
} }
return success; g_set_error (error,
NM_SETTING_ERROR,
NM_SETTING_ERROR_PROPERTY_TYPE_MISMATCH,
"%s", key);
return NM_SETTING_UPDATE_SECRET_ERROR;
} }
/** /**
...@@ -1002,29 +1014,42 @@ update_one_secret (NMSetting *setting, const char *key, GValue *value, GError ** ...@@ -1002,29 +1014,42 @@ update_one_secret (NMSetting *setting, const char *key, GValue *value, GError **
**/ **/
gboolean gboolean
nm_setting_update_secrets (NMSetting *setting, GHashTable *secrets, GError **error) 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; GHashTableIter iter;
gpointer key, data; gpointer key, data;
GError *tmp_error = NULL; GError *tmp_error = NULL;
NMSettingUpdateSecretResult result = NM_SETTING_UPDATE_SECRET_SUCCESS_UNCHANGED;
g_return_val_if_fail (NM_IS_SETTING (setting), FALSE); g_return_val_if_fail (NM_IS_SETTING (setting), NM_SETTING_UPDATE_SECRET_ERROR);
g_return_val_if_fail (secrets != NULL, FALSE); g_return_val_if_fail (secrets != NULL, NM_SETTING_UPDATE_SECRET_ERROR);
if (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); g_hash_table_iter_init (&iter, secrets);
while (g_hash_table_iter_next (&iter, &key, &data)) { while (g_hash_table_iter_next (&iter, &key, &data)) {
int success;
const char *secret_key = (const char *) key; const char *secret_key = (const char *) key;
GValue *secret_value = (GValue *) data; GValue *secret_value = (GValue *) data;
NM_SETTING_GET_CLASS (setting)->update_one_secret (setting, secret_key, secret_value, &tmp_error); success = NM_SETTING_GET_CLASS (setting)->update_one_secret (setting, secret_key, secret_value, &tmp_error);
if (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); 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 static gboolean
......
...@@ -177,7 +177,7 @@ typedef struct { ...@@ -177,7 +177,7 @@ typedef struct {
GPtrArray *(*need_secrets) (NMSetting *setting); GPtrArray *(*need_secrets) (NMSetting *setting);
gboolean (*update_one_secret) (NMSetting *setting, int (*update_one_secret) (NMSetting *setting,
const char *key, const char *key,
GValue *value, GValue *value,
GError **error); GError **error);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment