about summary refs log tree commit diff
path: root/src/settings/nm-settings-plugin.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/settings/nm-settings-plugin.c')
-rw-r--r--src/settings/nm-settings-plugin.c252
1 files changed, 179 insertions, 73 deletions
diff --git a/src/settings/nm-settings-plugin.c b/src/settings/nm-settings-plugin.c
index e7275631..09010931 100644
--- a/src/settings/nm-settings-plugin.c
+++ b/src/settings/nm-settings-plugin.c
@@ -1,4 +1,3 @@
-/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 /* NetworkManager system settings service
  *
  * This program is free software; you can redistribute it and/or modify
@@ -23,12 +22,14 @@
 
 #include "nm-settings-plugin.h"
 
+#include "nm-utils.h"
+#include "nm-core-internal.h"
+
 #include "nm-settings-connection.h"
 
 /*****************************************************************************/
 
 enum {
-	CONNECTION_ADDED,
 	UNMANAGED_SPECS_CHANGED,
 	UNRECOGNIZED_SPECS_CHANGED,
 
@@ -41,114 +42,228 @@ G_DEFINE_TYPE (NMSettingsPlugin, nm_settings_plugin, G_TYPE_OBJECT)
 
 /*****************************************************************************/
 
-void
-nm_settings_plugin_initialize (NMSettingsPlugin *self)
+int
+nm_settings_plugin_cmp_by_priority (const NMSettingsPlugin *a,
+                                    const NMSettingsPlugin *b,
+                                    const GSList *plugin_list)
 {
-	g_return_if_fail (NM_IS_SETTINGS_PLUGIN (self));
+	nm_assert (NM_IS_SETTINGS_PLUGIN (a));
+	nm_assert (NM_IS_SETTINGS_PLUGIN (b));
 
-	if (NM_SETTINGS_PLUGIN_GET_CLASS (self)->initialize)
-		NM_SETTINGS_PLUGIN_GET_CLASS (self)->initialize (self);
+	if (a != b) {
+		int idx_a = g_slist_index ((GSList *) plugin_list, a);
+		int idx_b = g_slist_index ((GSList *) plugin_list, b);
+
+		/* the plugins must be found in the list. */
+		nm_assert (idx_a >= 0);
+		nm_assert (idx_b >= 0);
+
+		/* plugins that appear first in @plugin_list have higher priority.
+		 * That means: smaller index -> higher priority. Reverse sort. */
+		NM_CMP_DIRECT (idx_b, idx_a);
+	}
+
+	return 0;
 }
 
+/*****************************************************************************/
+
 GSList *
-nm_settings_plugin_get_connections (NMSettingsPlugin *self)
+nm_settings_plugin_get_unmanaged_specs (NMSettingsPlugin *self)
 {
+	NMSettingsPluginClass *klass;
+
 	g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), NULL);
 
-	if (NM_SETTINGS_PLUGIN_GET_CLASS (self)->get_connections)
-		return NM_SETTINGS_PLUGIN_GET_CLASS (self)->get_connections (self);
-	return NULL;
+	klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
+	if (!klass->get_unmanaged_specs)
+		return NULL;
+	return klass->get_unmanaged_specs (self);
 }
 
-gboolean
-nm_settings_plugin_load_connection (NMSettingsPlugin *self,
-                                    const char *filename)
+GSList *
+nm_settings_plugin_get_unrecognized_specs (NMSettingsPlugin *self)
 {
-	g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), FALSE);
+	NMSettingsPluginClass *klass;
 
-	if (NM_SETTINGS_PLUGIN_GET_CLASS (self)->load_connection)
-		return NM_SETTINGS_PLUGIN_GET_CLASS (self)->load_connection (self, filename);
-	return FALSE;
+	g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), NULL);
+
+	klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
+	if (!klass->get_unrecognized_specs)
+		return NULL;
+	return klass->get_unrecognized_specs (self);
 }
 
 void
-nm_settings_plugin_reload_connections (NMSettingsPlugin *self)
+nm_settings_plugin_reload_connections (NMSettingsPlugin *self,
+                                       NMSettingsPluginConnectionLoadCallback callback,
+                                       gpointer user_data)
 {
+	NMSettingsPluginClass *klass;
+
 	g_return_if_fail (NM_IS_SETTINGS_PLUGIN (self));
+	g_return_if_fail (callback);
 
-	if (NM_SETTINGS_PLUGIN_GET_CLASS (self)->reload_connections)
-		NM_SETTINGS_PLUGIN_GET_CLASS (self)->reload_connections (self);
+	klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
+	if (klass->reload_connections)
+		klass->reload_connections (self, callback, user_data);
 }
 
-GSList *
-nm_settings_plugin_get_unmanaged_specs (NMSettingsPlugin *self)
+NMSettingsPluginConnectionLoadEntry *
+nm_settings_plugin_create_connection_load_entries (const char *const*filenames,
+                                                   gsize *out_len)
 {
-	g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), NULL);
+	NMSettingsPluginConnectionLoadEntry *entries;
+	gsize len;
+	gsize i;
+
+	len = NM_PTRARRAY_LEN (filenames);
+	if (len == 0) {
+		*out_len = 0;
+		return NULL;
+	}
+
+	entries = g_new (NMSettingsPluginConnectionLoadEntry, len);
+	for (i = 0; i < len; i++) {
+		entries[i] = (NMSettingsPluginConnectionLoadEntry) {
+			.filename = filenames[i],
+			.error    = NULL,
+			.handled  = FALSE,
+		};
+	}
 
-	if (NM_SETTINGS_PLUGIN_GET_CLASS (self)->get_unmanaged_specs)
-		return NM_SETTINGS_PLUGIN_GET_CLASS (self)->get_unmanaged_specs (self);
-	return NULL;
+	*out_len = len;
+	return entries;
 }
 
-GSList *
-nm_settings_plugin_get_unrecognized_specs (NMSettingsPlugin *self)
+void
+nm_settings_plugin_load_connections (NMSettingsPlugin *self,
+                                     NMSettingsPluginConnectionLoadEntry *entries,
+                                     gsize n_entries,
+                                     NMSettingsPluginConnectionLoadCallback callback,
+                                     gpointer user_data)
 {
-	g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), NULL);
+	NMSettingsPluginClass *klass;
 
-	if (NM_SETTINGS_PLUGIN_GET_CLASS (self)->get_unrecognized_specs)
-		return NM_SETTINGS_PLUGIN_GET_CLASS (self)->get_unrecognized_specs (self);
-	return NULL;
+	g_return_if_fail (NM_IS_SETTINGS_PLUGIN (self));
+
+	klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
+	if (klass->load_connections)
+		klass->load_connections (self, entries, n_entries, callback, user_data);
 }
 
-/**
- * nm_settings_plugin_add_connection:
- * @self: the #NMSettingsPlugin
- * @connection: the source connection to create a plugin-specific
- * #NMSettingsConnection from
- * @save_to_disk: %TRUE to save the connection to disk immediately, %FALSE to
- * not save to disk
- * @error: on return, a location to store any errors that may occur
- *
- * Creates a new #NMSettingsConnection for the given source @connection.  If the
- * plugin cannot handle the given connection type, it should return %NULL and
- * set @error.  The plugin owns the returned object and the caller must reference
- * the object if it wishes to continue using it.
- *
- * Returns: the new #NMSettingsConnection or %NULL
- */
-NMSettingsConnection *
+void
+nm_settings_plugin_load_connections_done (NMSettingsPlugin *self)
+{
+	NMSettingsPluginClass *klass;
+
+	g_return_if_fail (NM_IS_SETTINGS_PLUGIN (self));
+
+	klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
+	if (klass->load_connections_done)
+		klass->load_connections_done (self);
+}
+
+gboolean
 nm_settings_plugin_add_connection (NMSettingsPlugin *self,
                                    NMConnection *connection,
-                                   gboolean save_to_disk,
+                                   NMSettingsStorage **out_storage,
+                                   NMConnection **out_connection,
                                    GError **error)
 {
 	NMSettingsPluginClass *klass;
 
-	g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), NULL);
-	g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
+	g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), FALSE);
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+
+#if NM_MORE_ASSERTS > 5
+	nm_assert (nm_connection_verify (connection, NULL));
+#endif
+
+	NM_SET_OUT (out_storage, NULL);
+	NM_SET_OUT (out_connection, NULL);
 
 	klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
 	if (!klass->add_connection) {
 		g_set_error_literal (error, NM_SETTINGS_ERROR, NM_SETTINGS_ERROR_NOT_SUPPORTED,
-		                     "Plugin does not support adding connections");
-		return NULL;
+		                     "settings plugin does not support adding connections");
+		return FALSE;
 	}
-
-	return klass->add_connection (self, connection, save_to_disk, error);
+	return klass->add_connection (self,
+	                              connection,
+	                              out_storage,
+	                              out_connection,
+	                              error);
 }
 
-/*****************************************************************************/
+gboolean
+nm_settings_plugin_update_connection (NMSettingsPlugin *self,
+                                      NMSettingsStorage *storage,
+                                      NMConnection *connection,
+                                      NMSettingsStorage **out_storage,
+                                      NMConnection **out_connection,
+                                      GError **error)
+{
+	NMSettingsPluginClass *klass = NULL;
 
-void
-_nm_settings_plugin_emit_signal_connection_added (NMSettingsPlugin *self,
-                                                  NMSettingsConnection *sett_conn)
+	g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), FALSE);
+	g_return_val_if_fail (NM_IS_SETTINGS_STORAGE (storage), FALSE);
+	g_return_val_if_fail (nm_settings_storage_get_plugin (storage) == self, FALSE);
+	g_return_val_if_fail (NM_IS_CONNECTION (connection), FALSE);
+
+#if NM_MORE_ASSERTS > 5
+	nm_assert (nm_connection_verify (connection, NULL));
+	nm_assert (nm_streq (nm_connection_get_uuid (connection), nm_settings_storage_get_uuid (storage)));
+#endif
+
+	klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
+
+	NM_SET_OUT (out_storage, NULL);
+	NM_SET_OUT (out_connection, NULL);
+
+	if (!klass->update_connection) {
+		g_set_error (error,
+		             NM_SETTINGS_ERROR,
+		             NM_SETTINGS_ERROR_NOT_SUPPORTED,
+		             "settings plugin does not support modifying connections");
+		return FALSE;
+	}
+	return klass->update_connection (self,
+	                                 storage,
+	                                 connection,
+	                                 out_storage,
+	                                 out_connection,
+	                                 error);
+}
+
+gboolean
+nm_settings_plugin_delete_connection (NMSettingsPlugin *self,
+                                      NMSettingsStorage *storage,
+                                      GError **error)
 {
-	nm_assert (NM_IS_SETTINGS_PLUGIN (self));
-	nm_assert (NM_IS_SETTINGS_CONNECTION (sett_conn));
+	NMSettingsPluginClass *klass = NULL;
+
+	g_return_val_if_fail (NM_IS_SETTINGS_PLUGIN (self), FALSE);
+	g_return_val_if_fail (NM_IS_SETTINGS_STORAGE (storage), FALSE);
+	g_return_val_if_fail (nm_settings_storage_get_plugin (storage) == self, FALSE);
+
+	klass = NM_SETTINGS_PLUGIN_GET_CLASS (self);
 
-	g_signal_emit (self, signals[CONNECTION_ADDED], 0, sett_conn);
+	if (!klass->delete_connection) {
+		g_set_error (error,
+		             NM_SETTINGS_ERROR,
+		             NM_SETTINGS_ERROR_NOT_SUPPORTED,
+		             "settings plugin does not support deleting connections");
+		return FALSE;
+	}
+
+	return klass->delete_connection (self,
+	                                 storage,
+	                                 error);
 }
 
+/*****************************************************************************/
+
 void
 _nm_settings_plugin_emit_signal_unmanaged_specs_changed (NMSettingsPlugin *self)
 {
@@ -177,15 +292,6 @@ nm_settings_plugin_class_init (NMSettingsPluginClass *klass)
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
-	signals[CONNECTION_ADDED] =
-	    g_signal_new (NM_SETTINGS_PLUGIN_CONNECTION_ADDED,
-	                  G_OBJECT_CLASS_TYPE (object_class),
-	                  G_SIGNAL_RUN_FIRST,
-	                  0, NULL, NULL,
-	                  g_cclosure_marshal_VOID__OBJECT,
-	                  G_TYPE_NONE, 1,
-	                  NM_TYPE_SETTINGS_CONNECTION);
-
 	signals[UNMANAGED_SPECS_CHANGED] =
 	    g_signal_new (NM_SETTINGS_PLUGIN_UNMANAGED_SPECS_CHANGED,
 	                  G_OBJECT_CLASS_TYPE (object_class),