NetworkManager r4018 - in trunk: . system-settings/plugins/keyfile



Author: dcbw
Date: Wed Aug 27 03:09:14 2008
New Revision: 4018
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=4018&view=rev

Log:
2008-08-26  Dan Williams  <dcbw redhat com>

	* system-settings/plugins/keyfile/nm-keyfile-connection.c
		- (update): Update filename of the connection if the connection id
			was changed

	* system-settings/plugins/keyfile/plugin.c
		- (dir_changed): first pass at handling connection renames correctly

	* system-settings/plugins/keyfile/writer.c
	  system-settings/plugins/keyfile/writer.h
		- (write_connection): replace '/' with '*' when writing out the filename
			from the connection id



Modified:
   trunk/ChangeLog
   trunk/system-settings/plugins/keyfile/nm-keyfile-connection.c
   trunk/system-settings/plugins/keyfile/plugin.c
   trunk/system-settings/plugins/keyfile/writer.c
   trunk/system-settings/plugins/keyfile/writer.h

Modified: trunk/system-settings/plugins/keyfile/nm-keyfile-connection.c
==============================================================================
--- trunk/system-settings/plugins/keyfile/nm-keyfile-connection.c	(original)
+++ trunk/system-settings/plugins/keyfile/nm-keyfile-connection.c	Wed Aug 27 03:09:14 2008
@@ -1,4 +1,4 @@
-/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
+/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
 
 #include <string.h>
 #include <glib/gstdio.h>
@@ -31,8 +31,8 @@
 	g_return_val_if_fail (filename != NULL, NULL);
 
 	return (NMKeyfileConnection *) g_object_new (NM_TYPE_KEYFILE_CONNECTION,
-										NM_KEYFILE_CONNECTION_FILENAME, filename,
-										NULL);
+	                                             NM_KEYFILE_CONNECTION_FILENAME, filename,
+	                                             NULL);
 }
 
 const char *
@@ -51,14 +51,26 @@
 
 static gboolean
 update (NMExportedConnection *exported,
-	   GHashTable *new_settings,
-	   GError **error)
+        GHashTable *new_settings,
+        GError **error)
 {
+	NMKeyfileConnectionPrivate *priv = NM_KEYFILE_CONNECTION_GET_PRIVATE (exported);
 	gboolean success;
 
 	success = NM_EXPORTED_CONNECTION_CLASS (nm_keyfile_connection_parent_class)->update (exported, new_settings, error);
-	if (success)
-		success = write_connection (nm_exported_connection_get_connection (exported), error);
+	if (success) {
+		NMConnection *connection;
+		char *filename = NULL;
+
+		connection = nm_exported_connection_get_connection (exported);
+		success = write_connection (connection, &filename, error);
+		if (success && filename && strcmp (priv->filename, filename)) {
+			/* Update the filename if it changed */
+			g_free (priv->filename);
+			priv->filename = filename;
+		} else
+			g_free (filename);
+	}
 
 	return success;
 }
@@ -116,7 +128,7 @@
 		GError *error = NULL;
 
 		s_con->uuid = nm_utils_uuid_generate ();
-		if (!write_connection (wrapped, &error)) {
+		if (!write_connection (wrapped, NULL, &error)) {
 			g_warning ("Couldn't update connection %s with a UUID: (%d) %s",
 			           s_con->id, error ? error->code : 0,
 			           error ? error->message : "unknown");

Modified: trunk/system-settings/plugins/keyfile/plugin.c
==============================================================================
--- trunk/system-settings/plugins/keyfile/plugin.c	(original)
+++ trunk/system-settings/plugins/keyfile/plugin.c	Wed Aug 27 03:09:14 2008
@@ -4,6 +4,7 @@
 #include <sys/stat.h>
 #include <unistd.h>
 #include <sys/types.h>
+#include <string.h>
 #include <gmodule.h>
 #include <glib.h>
 #include <glib/gstdio.h>
@@ -42,25 +43,10 @@
 	gboolean disposed;
 } SCPluginKeyfilePrivate;
 
-static NMKeyfileConnection *
-read_one_connection (NMSystemConfigInterface *config, const char *filename)
-{
-	SCPluginKeyfilePrivate *priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (config);
-	NMKeyfileConnection *connection;
-
-	connection = nm_keyfile_connection_new (filename);
-	if (connection) {
-		g_hash_table_insert (priv->hash,
-						 (gpointer) nm_keyfile_connection_get_filename (connection),
-						 g_object_ref (connection));
-	}
-
-	return connection;
-}
-
 static void
 read_connections (NMSystemConfigInterface *config)
 {
+	SCPluginKeyfilePrivate *priv = SC_PLUGIN_KEYFILE_GET_PRIVATE (config);
 	GDir *dir;
 	GError *err = NULL;
 
@@ -69,10 +55,16 @@
 		const char *item;
 
 		while ((item = g_dir_read_name (dir))) {
+			NMKeyfileConnection *connection;
 			char *full_path;
 
 			full_path = g_build_filename (KEYFILE_DIR, item, NULL);
-			read_one_connection (config, full_path);
+			connection = nm_keyfile_connection_new (full_path);
+			if (connection) {
+				g_hash_table_insert (priv->hash,
+				                     (gpointer) nm_keyfile_connection_get_filename (connection),
+				                     connection);
+			}
 			g_free (full_path);
 		}
 
@@ -83,6 +75,45 @@
 	}
 }
 
+typedef struct {
+	const char *uuid;
+	NMKeyfileConnection *found;
+} FindByUUIDInfo;
+
+static void
+find_by_uuid (gpointer key, gpointer data, gpointer user_data)
+{
+	NMKeyfileConnection *keyfile = NM_KEYFILE_CONNECTION (key);
+	FindByUUIDInfo *info = user_data;
+	NMConnection *connection;
+	NMSettingConnection *s_con;
+
+	if (info->found)
+		return;
+
+	connection = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (keyfile));
+	s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
+	if (s_con && s_con->uuid) {
+		if (!strcmp (info->uuid, s_con->uuid))
+			info->found = keyfile;
+	}
+}
+
+static gboolean
+update_connection_settings (NMExportedConnection *orig,
+                            NMExportedConnection *new,
+                            GError **error)
+{
+	GHashTable *settings;
+	gboolean success;
+
+	settings = nm_connection_to_hash (nm_exported_connection_get_connection (new));
+	success = nm_exported_connection_update (orig, settings, error);
+	g_hash_table_destroy (settings);
+
+	return success;
+}
+
 /* Monitoring */
 
 static void
@@ -103,8 +134,11 @@
 	switch (event_type) {
 	case G_FILE_MONITOR_EVENT_DELETED:
 		if (connection) {
+			/* Removing from the hash table should drop the last reference */
+			g_object_ref (connection);
 			g_hash_table_remove (priv->hash, name);
 			nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (connection));
+			g_object_unref (connection);
 		}
 		break;
 	case G_FILE_MONITOR_EVENT_CREATED:
@@ -115,18 +149,75 @@
 
 			tmp = (NMExportedConnection *) nm_keyfile_connection_new (name);
 			if (tmp) {
-				GHashTable *settings;
+				GError *error = NULL;
 
-				settings = nm_connection_to_hash (nm_exported_connection_get_connection (tmp));
-				nm_exported_connection_update (NM_EXPORTED_CONNECTION (connection), settings, NULL);
-				g_hash_table_destroy (settings);
+				if (!update_connection_settings (NM_EXPORTED_CONNECTION (connection), tmp, &error)) {
+					g_warning ("%s: couldn't update connection settings: (%d) %s",
+					           __func__, error ? error->code : 0,
+					           error ? error->message : "unknown");
+					g_error_free (error);
+				}
 				g_object_unref (tmp);
 			}
 		} else {
 			/* New */
-			connection = read_one_connection (config, name);
-			if (connection)
-				g_signal_emit_by_name (config, "connection-added", connection);
+			connection = nm_keyfile_connection_new (name);
+			if (connection) {
+				NMConnection *tmp;
+				NMSettingConnection *s_con;
+				NMKeyfileConnection *found = NULL;
+
+				/* Connection renames will show up as different files but with
+				 * the same UUID.  Try to find the original connection.
+				 */
+				tmp = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (connection));
+				s_con = (NMSettingConnection *) nm_connection_get_setting (tmp, NM_TYPE_SETTING_CONNECTION);
+				if (s_con && s_con->uuid) {
+					FindByUUIDInfo info = { .found = NULL, .uuid = s_con->uuid };
+
+					g_hash_table_foreach (priv->hash, find_by_uuid, &info);
+					found = info.found;
+				}
+
+				/* A connection rename is treated just like an update except
+				 * there's a bit more housekeeping with the hash table.
+				 */
+				if (found) {
+					const char *old_filename = nm_keyfile_connection_get_filename (connection);
+					GError *error = NULL;
+
+					/* Removing from the hash table should drop the last reference,
+					 * but of course we want to keep the connection around.
+					 */
+					g_object_ref (found);
+					g_hash_table_remove (priv->hash, old_filename);
+
+					/* Updating settings should update the NMKeyfileConnection's
+					 * filename property too.
+					 */
+					if (!update_connection_settings (NM_EXPORTED_CONNECTION (found),
+					                                 NM_EXPORTED_CONNECTION (connection),
+					                                 &error)) {
+						g_warning ("%s: couldn't update connection settings: (%d) %s",
+						           __func__, error ? error->code : 0,
+						           error ? error->message : "unknown");
+						g_error_free (error);
+					}
+
+					/* Re-insert the connection back into the hash with the new filename */
+					g_hash_table_insert (priv->hash,
+					                     (gpointer) nm_keyfile_connection_get_filename (found),
+					                     found);
+
+					/* Get rid of the temporary connection */
+					g_object_unref (connection);
+				} else {
+					g_hash_table_insert (priv->hash,
+					                     (gpointer) nm_keyfile_connection_get_filename (connection),
+					                     connection);
+					g_signal_emit_by_name (config, "connection-added", connection);
+				}
+			}
 		}
 		break;
 	default:
@@ -186,7 +277,7 @@
                 NMConnection *connection,
                 GError **error)
 {
-	return write_connection (connection, error);
+	return write_connection (connection, NULL, error);
 }
 
 /* GObject */

Modified: trunk/system-settings/plugins/keyfile/writer.c
==============================================================================
--- trunk/system-settings/plugins/keyfile/writer.c	(original)
+++ trunk/system-settings/plugins/keyfile/writer.c	Wed Aug 27 03:09:14 2008
@@ -263,15 +263,38 @@
 	}
 }
 
+char *
+writer_id_to_filename (const char *id)
+{
+	char *filename, *f;
+	const char *i = id;
+
+	f = filename = g_malloc0 (strlen (id) + 1);
+
+	/* Convert '/' to '*' */
+	while (*i) {
+		if (*i == '/')
+			*f++ = '*';
+		else
+			*f++ = *i;
+		i++;
+	}
+
+	return filename;
+}
+
 gboolean
-write_connection (NMConnection *connection, GError **error)
+write_connection (NMConnection *connection, char **out_path, GError **error)
 {
 	NMSettingConnection *s_con;
 	GKeyFile *key_file;
 	char *data;
 	gsize len;
 	gboolean success = FALSE;
-	GError *err = NULL;
+	char *filename, *path;
+
+	if (out_path)
+		g_return_val_if_fail (*out_path == NULL, FALSE);
 
 	s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
 	if (!s_con)
@@ -279,30 +302,28 @@
 
 	key_file = g_key_file_new ();
 	nm_connection_for_each_setting_value (connection, write_setting_value, key_file);
-	data = g_key_file_to_data (key_file, &len, &err);
-
-	if (!err) {
-		char *filename;
-
-		filename = g_build_filename (KEYFILE_DIR, s_con->id, NULL);
-		g_file_set_contents (filename, data, len, &err);
-		chmod (filename, S_IRUSR | S_IWUSR);
-		if (chown (filename, 0, 0) < 0) {
-			g_warning ("Error chowning '%s': %d", filename, errno);
-			unlink (filename);
-		} else
-			success = TRUE;
-
-		g_free (filename);
-	}
-
-	if (err) {
-		g_warning ("Error while saving connection: %s", err->message);
-		g_error_free (err);
+	data = g_key_file_to_data (key_file, &len, error);
+	if (!data)
+		goto out;
+
+	filename = writer_id_to_filename (s_con->id);
+	path = g_build_filename (KEYFILE_DIR, filename, NULL);
+	g_free (filename);
+
+	g_file_set_contents (path, data, len, error);
+	chmod (path, S_IRUSR | S_IWUSR);
+	if (chown (path, 0, 0) < 0) {
+		g_warning ("Error chowning '%s': %d", path, errno);
+		unlink (path);
+	} else {
+		if (out_path)
+			*out_path = g_strdup (path);
+		success = TRUE;
 	}
+	g_free (path);
 
+out:
 	g_free (data);
 	g_key_file_free (key_file);
-
 	return success;
 }

Modified: trunk/system-settings/plugins/keyfile/writer.h
==============================================================================
--- trunk/system-settings/plugins/keyfile/writer.h	(original)
+++ trunk/system-settings/plugins/keyfile/writer.h	Wed Aug 27 03:09:14 2008
@@ -6,6 +6,8 @@
 #include <glib.h>
 #include <nm-connection.h>
 
-gboolean write_connection (NMConnection *connection, GError **error);
+gboolean write_connection (NMConnection *connection, char **out_path, GError **error);
+
+char *writer_id_to_filename (const char *id);
 
 #endif /* _KEYFILE_PLUGIN_WRITER_H */



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]