mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2026-05-09 09:28:06 +02:00
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 <thaller@redhat.com>
This commit is contained in:
parent
0f38213129
commit
123bf9eea4
5 changed files with 108 additions and 49 deletions
|
|
@ -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,
|
||||||
/* 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,
|
||||||
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,
|
||||||
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);
|
||||||
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)
|
||||||
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,
|
||||||
{
|
{
|
||||||
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,
|
||||||
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,
|
||||||
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,
|
||||||
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 **
|
||||||
} 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)
|
||||||
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 **
|
||||||
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 **
|
||||||
**/
|
**/
|
||||||
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 {
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue