}
/**
- * nm_connection_replace_settings:
+ * _nm_connection_replace_settings:
* @connection: a #NMConnection
* @new_settings: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION, with the new settings
+ * @parse_flags: flags.
* @error: location to store error, or %NULL
*
* Replaces @connection's settings with @new_settings (which must be
* be deserialized (in which case @connection will be unchanged).
**/
gboolean
-nm_connection_replace_settings (NMConnection *connection,
- GVariant *new_settings,
- GError **error)
+_nm_connection_replace_settings (NMConnection *connection,
+ GVariant *new_settings,
+ NMSettingParseFlags parse_flags,
+ GError **error)
{
NMConnectionPrivate *priv;
GVariantIter iter;
g_return_val_if_fail (g_variant_is_of_type (new_settings, NM_VARIANT_TYPE_CONNECTION), FALSE);
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+ nm_assert (!NM_FLAGS_ANY (parse_flags, ~NM_SETTING_PARSE_FLAGS_ALL));
+ nm_assert (!NM_FLAGS_ALL (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT | NM_SETTING_PARSE_FLAGS_BEST_EFFORT));
+
priv = NM_CONNECTION_GET_PRIVATE (connection);
- if (!validate_permissions_type (new_settings, error))
+ if ( !NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT)
+ && !validate_permissions_type (new_settings, error))
return FALSE;
g_variant_iter_init (&iter, new_settings);
while (g_variant_iter_next (&iter, "{&s@a{sv}}", &setting_name, &setting_dict)) {
+ gs_unref_variant GVariant *setting_dict_free = NULL;
+ GError *local = NULL;
NMSetting *setting;
GType type;
+ setting_dict_free = setting_dict;
+
type = nm_setting_lookup_type (setting_name);
if (type == G_TYPE_INVALID) {
+ if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT))
+ continue;
g_set_error_literal (error,
NM_CONNECTION_ERROR,
NM_CONNECTION_ERROR_INVALID_SETTING,
_("unknown setting name"));
g_prefix_error (error, "%s: ", setting_name);
- g_variant_unref (setting_dict);
g_slist_free_full (settings, g_object_unref);
return FALSE;
}
- setting = _nm_setting_new_from_dbus (type, setting_dict, new_settings, error);
- g_variant_unref (setting_dict);
+ for (s = settings; s; s = s->next) {
+ if (G_OBJECT_TYPE (s->data) == type) {
+ if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_STRICT)) {
+ g_set_error_literal (error,
+ NM_CONNECTION_ERROR,
+ NM_CONNECTION_ERROR_INVALID_SETTING,
+ _("duplicate setting name"));
+ g_prefix_error (error, "%s: ", setting_name);
+ g_slist_free_full (settings, g_object_unref);
+ return FALSE;
+ }
+ /* last wins. */
+ g_object_unref (s->data);
+ settings = g_slist_delete_link (settings, s);
+ break;
+ }
+ }
+
+ setting = _nm_setting_new_from_dbus (type, setting_dict, new_settings, parse_flags, &local);
if (!setting) {
+ if (NM_FLAGS_HAS (parse_flags, NM_SETTING_PARSE_FLAGS_BEST_EFFORT))
+ continue;
+ g_propagate_error (error, local);
g_slist_free_full (settings, g_object_unref);
return FALSE;
}
} else
changed = (settings != NULL);
+ /* Note: @settings might be empty in which case the connection
+ * has no NMSetting instances... which is fine, just something
+ * to be aware of. */
for (s = settings; s; s = s->next)
_nm_connection_add_setting (connection, s->data);
return TRUE;
}
+/**
+ * nm_connection_replace_settings:
+ * @connection: a #NMConnection
+ * @new_settings: a #GVariant of type %NM_VARIANT_TYPE_CONNECTION, with the new settings
+ * @error: location to store error, or %NULL
+ *
+ * Replaces @connection's settings with @new_settings (which must be
+ * syntactically valid, and describe a known type of connection, but does not
+ * need to result in a connection that passes nm_connection_verify()).
+ *
+ * Returns: %TRUE if connection was updated, %FALSE if @new_settings could not
+ * be deserialized (in which case @connection will be unchanged).
+ **/
+gboolean
+nm_connection_replace_settings (NMConnection *connection,
+ GVariant *new_settings,
+ GError **error)
+{
+ return _nm_connection_replace_settings (connection, new_settings, NM_SETTING_PARSE_FLAGS_NONE, error);
+}
+
/**
* nm_connection_replace_settings_from_connection:
* @connection: a #NMConnection