NetworkManager r3663 - in trunk: . marshallers system-settings/plugins/ifcfg-fedora



Author: dcbw
Date: Tue May 13 16:53:50 2008
New Revision: 3663
URL: http://svn.gnome.org/viewvc/NetworkManager?rev=3663&view=rev

Log:
2008-05-13  Dan Williams  <dcbw redhat com>

	* marshallers/nm-marshal.list
		- Add VOID:POINTER,STRING marshaller for ifcfg-fedora plugin

	* system-settings/plugins/ifcfg-fedora/Makefile.am
	  system-settings/plugins/ifcfg-fedora/nm-inotify-helper.c
	  system-settings/plugins/ifcfg-fedora/nm-inotify-helper.h
		- Implement a minimal inotify helper for watch paths for IN_CLOSE_WRITE
			events.  Solely for use watching ifcfg files to pick up changes
			to their hardlinks, since GIO doesn't support this yet (bgo #532815)

	* system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.c
		- (nm_ifcfg_connection_class_init): new 'ifcfg-changed' signal when the
			file contents change
		- (finalize): clean up inotify watches
		- (nm_ifcfg_connection_new): store keyfile; inotify watch the keyfile
			and the connection ifcfg for changes on their hardlinks
		- (files_changed_cb): proxy the changed signal back out to listeners

	* system-settings/plugins/ifcfg-fedora/plugin.c
		- (dir_changed): 
		- (connection_ifcfg_changed): re-read the connection when the ifcfg
			changes
		- (read_one_connection): connect to change signals on the new connection
		- (dir_changed, connection_changed_handler,
		   handle_connection_remove_or_new): break out connection change
			handling and connection new/remove handling so it can be used from
			both the GFileMonitor callback and the NMIfcfgConnection changed
			signals

	* system-settings/plugins/ifcfg-fedora/reader.c
	  system-settings/plugins/ifcfg-fedora/reader.h
		- (connection_from_file): return the keyfile path the connection would use



Added:
   trunk/system-settings/plugins/ifcfg-fedora/nm-inotify-helper.c
   trunk/system-settings/plugins/ifcfg-fedora/nm-inotify-helper.h
Modified:
   trunk/ChangeLog
   trunk/marshallers/nm-marshal.list
   trunk/system-settings/plugins/ifcfg-fedora/Makefile.am
   trunk/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.c
   trunk/system-settings/plugins/ifcfg-fedora/plugin.c
   trunk/system-settings/plugins/ifcfg-fedora/reader.c
   trunk/system-settings/plugins/ifcfg-fedora/reader.h

Modified: trunk/marshallers/nm-marshal.list
==============================================================================
--- trunk/marshallers/nm-marshal.list	(original)
+++ trunk/marshallers/nm-marshal.list	Tue May 13 16:53:50 2008
@@ -13,4 +13,4 @@
 VOID:STRING,INT
 VOID:STRING,UINT
 VOID:OBJECT,OBJECT,ENUM
-
+VOID:POINTER,STRING

Modified: trunk/system-settings/plugins/ifcfg-fedora/Makefile.am
==============================================================================
--- trunk/system-settings/plugins/ifcfg-fedora/Makefile.am	(original)
+++ trunk/system-settings/plugins/ifcfg-fedora/Makefile.am	Tue May 13 16:53:50 2008
@@ -10,7 +10,9 @@
 	nm-ifcfg-connection.h \
 	reader.c \
 	reader.h \
-	common.h
+	common.h \
+	nm-inotify-helper.c \
+	nm-inotify-helper.h
 
 libnm_settings_plugin_ifcfg_fedora_la_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
@@ -21,6 +23,7 @@
 	-I$(top_srcdir)/include \
 	-I$(top_srcdir)/libnm-glib \
 	-I$(top_srcdir)/libnm-util \
+	-I$(top_builddir)/marshallers \
 	-DSYSCONFDIR=\"$(sysconfdir)\"
 
 libnm_settings_plugin_ifcfg_fedora_la_LDFLAGS = -module -avoid-version
@@ -28,7 +31,8 @@
 	$(GLIB_LIBS) \
 	$(GMODULE_LIBS) \
 	$(top_builddir)/libnm-util/libnm-util.la \
-	$(top_builddir)/libnm-glib/libnm_glib.la
+	$(top_builddir)/libnm-glib/libnm_glib.la \
+	$(top_builddir)/marshallers/libmarshallers.la
 
 if NO_GIO
 libnm_settings_plugin_ifcfg_fedora_la_LIBADD += \

Modified: trunk/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.c
==============================================================================
--- trunk/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.c	(original)
+++ trunk/system-settings/plugins/ifcfg-fedora/nm-ifcfg-connection.c	Tue May 13 16:53:50 2008
@@ -38,14 +38,20 @@
 #include "nm-ifcfg-connection.h"
 #include "nm-system-config-hal-manager.h"
 #include "reader.h"
+#include "nm-inotify-helper.h"
 
 G_DEFINE_TYPE (NMIfcfgConnection, nm_ifcfg_connection, NM_TYPE_EXPORTED_CONNECTION)
 
 #define NM_IFCFG_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_IFCFG_CONNECTION, NMIfcfgConnectionPrivate))
 
 typedef struct {
+	gulong ih_event_id;
+
 	char *filename;
+	int file_wd;
+
 	char *keyfile;
+	int keyfile_wd;
 
 	char *udi;
 	gboolean unmanaged;
@@ -64,6 +70,14 @@
 	LAST_PROP
 };
 
+/* Signals */
+enum {
+	IFCFG_CHANGED,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
 static char *
 get_ether_device_udi (DBusGConnection *g_connection, GByteArray *mac, GSList *devices)
 {
@@ -205,6 +219,22 @@
 	priv->daid = 0;
 }
 
+static void
+files_changed_cb (NMInotifyHelper *ih,
+                  struct inotify_event *evt,
+                  const char *path,
+                  gpointer user_data)
+{
+	NMIfcfgConnection *self = NM_IFCFG_CONNECTION (user_data);
+	NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self);
+
+	if ((evt->wd != priv->file_wd) && (evt->wd != priv->keyfile_wd))
+		return;
+
+	/* push the event up to the plugin */
+	g_signal_emit (self, signals[IFCFG_CHANGED], 0);
+}
+
 NMIfcfgConnection *
 nm_ifcfg_connection_new (const char *filename,
                          DBusGConnection *g_connection,
@@ -212,13 +242,16 @@
                          GError **error)
 {
 	GObject *object;
+	NMIfcfgConnectionPrivate *priv;
 	NMConnection *wrapped;
 	gboolean unmanaged = FALSE;
 	char *udi;
+	char *keyfile = NULL;
+	NMInotifyHelper *ih;
 
 	g_return_val_if_fail (filename != NULL, NULL);
 
-	wrapped = connection_from_file (filename, &unmanaged, error);
+	wrapped = connection_from_file (filename, &unmanaged, &keyfile, error);
 	if (!wrapped)
 		return NULL;
 
@@ -230,14 +263,26 @@
 	                                   NM_IFCFG_CONNECTION_UDI, udi,
 	                                   NM_EXPORTED_CONNECTION_CONNECTION, wrapped,
 	                                   NULL);
-	if (object && !udi) {
-		NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object);
+	if (!object)
+		goto out;
 
+	priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object);
+
+	if (!udi) {
 		priv->hal_mgr = g_object_ref (hal_mgr);
 		priv->g_connection = dbus_g_connection_ref (g_connection);
 		priv->daid = g_signal_connect (priv->hal_mgr, "device-added", G_CALLBACK (device_added_cb), object);
 	}
 
+	ih = nm_inotify_helper_get ();
+	priv->ih_event_id = g_signal_connect (ih, "event", G_CALLBACK (files_changed_cb), object);
+
+	priv->file_wd = nm_inotify_helper_add_watch (ih, filename);
+
+	priv->keyfile = keyfile;
+	priv->keyfile_wd = nm_inotify_helper_add_watch (ih, keyfile);
+
+out:
 	g_object_unref (wrapped);
 	g_free (udi);
 	return (NMIfcfgConnection *) object;
@@ -310,13 +355,25 @@
 {
 	NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (object);
 	NMConnection *wrapped;
+	NMInotifyHelper *ih;
+
+	g_free (priv->udi);
 
 	wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (object));
 	if (wrapped)
 		nm_connection_clear_secrets (wrapped);
 
+	ih = nm_inotify_helper_get ();
+
+	g_signal_handler_disconnect (ih, priv->ih_event_id);
+
 	g_free (priv->filename);
-	g_free (priv->udi);
+	if (priv->file_wd >= 0)
+		nm_inotify_helper_remove_watch (ih, priv->file_wd);
+
+	g_free (priv->keyfile);
+	if (priv->keyfile_wd >= 0)
+		nm_inotify_helper_remove_watch (ih, priv->keyfile_wd);
 
 	if (priv->hal_mgr) {
 		if (priv->daid)
@@ -419,4 +476,13 @@
 						  "UDI",
 						  NULL,
 						  G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+	signals[IFCFG_CHANGED] =
+		g_signal_new ("ifcfg-changed",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              0, NULL, NULL,
+		              g_cclosure_marshal_VOID__VOID,
+		              G_TYPE_NONE, 0);
 }
+

Added: trunk/system-settings/plugins/ifcfg-fedora/nm-inotify-helper.c
==============================================================================
--- (empty file)
+++ trunk/system-settings/plugins/ifcfg-fedora/nm-inotify-helper.c	Tue May 13 16:53:50 2008
@@ -0,0 +1,211 @@
+/* -*- 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
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#include <unistd.h>
+#include <string.h>
+#include <sys/inotify.h>
+#include <glib.h>
+
+#include "nm-marshal.h"
+#include "nm-inotify-helper.h"
+
+G_DEFINE_TYPE (NMInotifyHelper, nm_inotify_helper, G_TYPE_OBJECT)
+
+#define NM_INOTIFY_HELPER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_INOTIFY_HELPER, NMInotifyHelperPrivate))
+
+typedef struct {
+	int ifd;
+
+	GHashTable *wd_refs;
+} NMInotifyHelperPrivate;
+
+/* Signals */
+enum {
+	EVENT,
+	LAST_SIGNAL
+};
+
+static guint signals[LAST_SIGNAL] = { 0 };
+
+int
+nm_inotify_helper_add_watch (NMInotifyHelper *self, const char *path)
+{
+	NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE (self);
+	int wd;
+	guint32 refcount;
+
+	g_return_val_if_fail (priv->ifd >= 0, -1);
+
+	/* We only care about modifications since we're just trying to get change
+	 * notifications on hardlinks.
+	 */
+
+	wd = inotify_add_watch (priv->ifd, path, IN_CLOSE_WRITE);
+	if (wd < 0)
+		return -1;
+
+	refcount = GPOINTER_TO_UINT (g_hash_table_lookup (priv->wd_refs, GINT_TO_POINTER (wd)));
+	refcount++;
+	g_hash_table_replace (priv->wd_refs, GINT_TO_POINTER (wd), GUINT_TO_POINTER (refcount));
+
+	return wd;
+}
+
+void
+nm_inotify_helper_remove_watch (NMInotifyHelper *self, int wd)
+{
+	NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE (self);
+	guint32 refcount;
+
+	g_return_if_fail (priv->ifd >= 0);
+
+	refcount = GPOINTER_TO_UINT (g_hash_table_lookup (priv->wd_refs, GINT_TO_POINTER (wd)));
+	if (!refcount)
+		return;
+
+	refcount--;
+	if (!refcount) {
+		g_hash_table_remove (priv->wd_refs, GINT_TO_POINTER (wd));
+		inotify_rm_watch (priv->ifd, wd);
+	} else
+		g_hash_table_replace (priv->wd_refs, GINT_TO_POINTER (wd), GUINT_TO_POINTER (refcount));
+}
+
+static gboolean
+inotify_event_handler (GIOChannel *channel, GIOCondition cond, gpointer user_data)
+{
+	NMInotifyHelper *self = NM_INOTIFY_HELPER (user_data);
+	struct inotify_event evt;
+
+	/* read the notifications from the watch descriptor */
+	while (g_io_channel_read_chars (channel, (gchar *) &evt, sizeof (struct inotify_event), NULL, NULL) == G_IO_STATUS_NORMAL) {
+		gchar filename[PATH_MAX + 1];
+
+		filename[0] = '\0';
+		if (evt.len > 0) {
+			g_io_channel_read_chars (channel,
+			                        filename,
+			                        evt.len > PATH_MAX ? PATH_MAX : evt.len,
+			                        NULL, NULL);
+		}
+
+		if (!(evt.mask & IN_IGNORED))
+			g_signal_emit (self, signals[EVENT], 0, &evt, &filename[0]);
+	}
+
+	return TRUE;
+}
+
+static gboolean
+init_inotify (NMInotifyHelper *self)
+{
+	NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE (self);
+	GIOChannel *channel;
+	guint source_id;
+
+	priv->ifd = inotify_init ();
+	if (priv->ifd == -1) {
+		g_warning ("%s: couldn't initialize inotify", __func__);
+		return FALSE;
+	}
+
+	/* Watch the inotify descriptor for file/directory change events */
+	channel = g_io_channel_unix_new (priv->ifd);
+	if (!channel) {
+		g_warning ("%s: couldn't create new GIOChannel", __func__);
+		close (priv->ifd);
+		priv->ifd = -1;
+		return FALSE;
+	}
+
+	g_io_channel_set_flags (channel, G_IO_FLAG_NONBLOCK, NULL);
+	g_io_channel_set_encoding (channel, NULL, NULL); 
+
+	source_id = g_io_add_watch (channel,
+	                            G_IO_IN | G_IO_ERR,
+	                            (GIOFunc) inotify_event_handler,
+	                            (gpointer) self);
+	g_io_channel_unref (channel);
+	return TRUE;
+}
+
+NMInotifyHelper *
+nm_inotify_helper_get (void)
+{
+	static NMInotifyHelper *singleton = NULL;
+
+	if (!singleton) {
+		singleton = (NMInotifyHelper *) g_object_new (NM_TYPE_INOTIFY_HELPER, NULL);
+		if (!singleton)
+			return NULL;
+
+		if (!init_inotify (singleton)) {
+			g_object_unref (singleton);
+			return NULL;
+		}
+	} else
+		g_object_ref (singleton);
+
+	g_assert (singleton);
+	return singleton;
+}
+
+static void
+nm_inotify_helper_init (NMInotifyHelper *self)
+{
+	NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE (self);
+
+	priv->wd_refs = g_hash_table_new (g_direct_hash, g_direct_equal);
+}
+
+static void
+finalize (GObject *object)
+{
+	NMInotifyHelperPrivate *priv = NM_INOTIFY_HELPER_GET_PRIVATE (object);
+
+	if (priv->ifd >= 0)
+		close (priv->ifd);
+
+	g_hash_table_destroy (priv->wd_refs);
+
+	G_OBJECT_CLASS (nm_inotify_helper_parent_class)->finalize (object);
+}
+
+static void
+nm_inotify_helper_class_init (NMInotifyHelperClass *klass)
+{
+	GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+	g_type_class_add_private (klass, sizeof (NMInotifyHelperPrivate));
+
+	/* Virtual methods */
+	object_class->finalize = finalize;
+
+	/* Signals */
+	signals[EVENT] =
+		g_signal_new ("event",
+		              G_OBJECT_CLASS_TYPE (object_class),
+		              G_SIGNAL_RUN_LAST,
+		              G_STRUCT_OFFSET (NMInotifyHelperClass, event),
+		              NULL, NULL,
+		              nm_marshal_VOID__POINTER_STRING,
+		              G_TYPE_NONE, 2, G_TYPE_POINTER, G_TYPE_STRING);
+}
+

Added: trunk/system-settings/plugins/ifcfg-fedora/nm-inotify-helper.h
==============================================================================
--- (empty file)
+++ trunk/system-settings/plugins/ifcfg-fedora/nm-inotify-helper.h	Tue May 13 16:53:50 2008
@@ -0,0 +1,54 @@
+/* -*- 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
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ * (C) Copyright 2008 Red Hat, Inc.
+ */
+
+#ifndef __INOTIFY_HELPER_H__
+#define __INOTIFY_HELPER_H__
+
+#include <glib.h>
+#include <glib-object.h>
+#include <sys/inotify.h>
+
+#define NM_TYPE_INOTIFY_HELPER            (nm_inotify_helper_get_type ())
+#define NM_INOTIFY_HELPER(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_INOTIFY_HELPER, NMInotifyHelper))
+#define NM_INOTIFY_HELPER_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_INOTIFY_HELPER, NMInotifyHelperClass))
+#define NM_IS_INOTIFY_HELPER(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_INOTIFY_HELPER))
+#define NM_IS_INOTIFY_HELPER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_INOTIFY_HELPER))
+#define NM_INOTIFY_HELPER_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_INOTIFY_HELPER, NMInotifyHelperClass))
+
+typedef struct {
+	GObject parent;
+} NMInotifyHelper;
+
+typedef struct {
+	GObjectClass parent;
+
+	/* signals */
+	void (* event) (NMInotifyHelper *helper, struct inotify_event *evt, const char *filename);
+} NMInotifyHelperClass;
+
+GType nm_inotify_helper_get_type (void);
+
+NMInotifyHelper * nm_inotify_helper_get (void);
+
+int nm_inotify_helper_add_watch (NMInotifyHelper *helper, const char *path);
+
+void nm_inotify_helper_remove_watch (NMInotifyHelper *helper, int wd);
+
+#endif  /* __INOTIFY_HELPER_H__ */

Modified: trunk/system-settings/plugins/ifcfg-fedora/plugin.c
==============================================================================
--- trunk/system-settings/plugins/ifcfg-fedora/plugin.c	(original)
+++ trunk/system-settings/plugins/ifcfg-fedora/plugin.c	Tue May 13 16:53:50 2008
@@ -52,6 +52,18 @@
 
 static void system_config_interface_init (NMSystemConfigInterface *system_config_interface_class);
 
+static void connection_changed_handler (SCPluginIfcfg *plugin,
+                                        const char *path,
+                                        NMIfcfgConnection *connection,
+                                        gboolean *do_remove,
+                                        gboolean *do_new);
+
+static void handle_connection_remove_or_new (SCPluginIfcfg *plugin,
+                                             const char *path,
+                                             NMIfcfgConnection *connection,
+                                             gboolean do_remove,
+                                             gboolean do_new);
+
 G_DEFINE_TYPE_EXTENDED (SCPluginIfcfg, sc_plugin_ifcfg, G_TYPE_OBJECT, 0,
 						G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE,
 											   system_config_interface_init))
@@ -123,6 +135,20 @@
 	g_signal_emit_by_name (SC_PLUGIN_IFCFG (user_data), "unmanaged-devices-changed");
 }
 
+static void
+connection_ifcfg_changed (NMIfcfgConnection *connection, gpointer user_data)
+{
+	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
+	gboolean do_remove = FALSE, do_new = FALSE;
+	const char *path;
+
+	path = nm_ifcfg_connection_get_filename (connection);
+	g_return_if_fail (path != NULL);
+
+	connection_changed_handler (plugin, path, connection, &do_remove, &do_new);
+	handle_connection_remove_or_new (plugin, path, connection, do_remove, do_new);
+}
+
 static NMIfcfgConnection *
 read_one_connection (SCPluginIfcfg *plugin, const char *filename)
 {
@@ -159,6 +185,10 @@
 			g_signal_connect (G_OBJECT (connection), "notify::unmanaged",
 			                  G_CALLBACK (connection_unmanaged_changed), plugin);
 		}
+
+		/* watch changes of ifcfg hardlinks */
+		g_signal_connect (G_OBJECT (connection), "ifcfg-changed",
+		                  G_CALLBACK (connection_ifcfg_changed), plugin);
 	} else {
 		PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "    error: %s",
 		              error->message ? error->message : "(unknown)");
@@ -169,7 +199,7 @@
 }
 
 static gboolean
-should_ignore_file (const char *basename, const char *tag)
+check_suffix (const char *basename, const char *tag)
 {
 	int len, tag_len;
 
@@ -183,6 +213,28 @@
 	return FALSE;
 }
 
+static gboolean
+should_ignore_file (const char *filename)
+{
+	char *basename;
+	gboolean ignore = TRUE;
+
+	g_return_val_if_fail (filename != NULL, TRUE);
+
+	basename = g_path_get_basename (filename);
+	g_return_val_if_fail (basename != NULL, TRUE);
+
+	if (   !strncmp (basename, IFCFG_TAG, strlen (IFCFG_TAG))
+		&& !check_suffix (basename, BAK_TAG)
+		&& !check_suffix (basename, TILDE_TAG)
+		&& !check_suffix (basename, ORIG_TAG)
+		&& !check_suffix (basename, REJ_TAG))
+		ignore = FALSE;
+
+	g_free (basename);
+	return ignore;
+}
+
 static void
 read_connections (SCPluginIfcfg *plugin)
 {
@@ -196,14 +248,7 @@
 		while ((item = g_dir_read_name (dir))) {
 			char *full_path;
 
-			if (strncmp (item, IFCFG_TAG, strlen (IFCFG_TAG)))
-				continue;
-
-			/* ignore some files */
-			if (   should_ignore_file (item, BAK_TAG)
-			    || should_ignore_file (item, TILDE_TAG)
-			    || should_ignore_file (item, ORIG_TAG)
-			    || should_ignore_file (item, REJ_TAG))
+			if (should_ignore_file (item))
 				continue;
 
 			full_path = g_build_filename (IFCFG_DIR, item, NULL);
@@ -221,93 +266,91 @@
 /* Monitoring */
 
 static void
-dir_changed (GFileMonitor *monitor,
-		   GFile *file,
-		   GFile *other_file,
-		   GFileMonitorEvent event_type,
-		   gpointer user_data)
+connection_changed_handler (SCPluginIfcfg *plugin,
+                            const char *path,
+                            NMIfcfgConnection *connection,
+                            gboolean *do_remove,
+                            gboolean *do_new)
 {
-	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
 	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
-	char *name;
-	NMIfcfgConnection *connection;
-	gboolean do_remove = FALSE, do_new = FALSE;
+	NMIfcfgConnection *tmp;
+	GError *error = NULL;
+	GHashTable *settings;
+	gboolean new_unmanaged, old_unmanaged;
 
-	name = g_file_get_path (file);
-	connection = g_hash_table_lookup (priv->connections, name);
+	g_return_if_fail (plugin != NULL);
+	g_return_if_fail (path != NULL);
+	g_return_if_fail (connection != NULL);
+	g_return_if_fail (do_remove != NULL);
+	g_return_if_fail (do_new != NULL);
+
+	PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "updating %s", path);
+
+	tmp = (NMIfcfgConnection *) nm_ifcfg_connection_new (path, priv->g_connection, priv->hal_mgr, &error);
+	if (!tmp) {
+		/* couldn't read connection; remove it */
 
-	switch (event_type) {
-	case G_FILE_MONITOR_EVENT_DELETED:
-		if (connection) {
-			PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "removed %s.", name);
-			do_remove = TRUE;
+		PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    error: %s",
+		             error->message ? error->message : "(unknown)");
+		g_error_free (error);
+
+		PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "removed %s.", path);
+		*do_remove = TRUE;
+		return;
+	}
+
+	/* Successfully read connection changes */
+
+	old_unmanaged = nm_ifcfg_connection_get_unmanaged (NM_IFCFG_CONNECTION (connection));
+	new_unmanaged = nm_ifcfg_connection_get_unmanaged (NM_IFCFG_CONNECTION (tmp));
+
+	if (new_unmanaged) {
+		if (!old_unmanaged) {
+			/* Unexport the connection by destroying it, then re-creating it as unmanaged */
+			*do_remove = *do_new = TRUE;
 		}
-		break;
-	case G_FILE_MONITOR_EVENT_CREATED:
-	case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
-		if (connection) {
-			/* Update */
-			NMIfcfgConnection *tmp;
-			GError *error = NULL;
+	} else {
+		NMConnection *old_wrapped, *new_wrapped;
 
-			PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "updating %s", name);
+		if (old_unmanaged)  /* no longer unmanaged */
+			g_signal_emit_by_name (plugin, "connection-added", connection);
 
-			tmp = (NMIfcfgConnection *) nm_ifcfg_connection_new (name, priv->g_connection, priv->hal_mgr, &error);
-			if (tmp) {
-				GHashTable *settings;
-				gboolean new_unmanaged, old_unmanaged;
-
-				old_unmanaged = nm_ifcfg_connection_get_unmanaged (NM_IFCFG_CONNECTION (connection));
-				new_unmanaged = nm_ifcfg_connection_get_unmanaged (NM_IFCFG_CONNECTION (tmp));
-
-				if (new_unmanaged) {
-					if (!old_unmanaged) {
-						/* Unexport the connection by destroying it, then re-creating it as unmanaged */
-						do_remove = do_new = TRUE;
-					}
-				} else {
-					NMConnection *old_wrapped, *new_wrapped;
-
-					if (old_unmanaged)  /* no longer unmanaged */
-						g_signal_emit_by_name (plugin, "connection-added", connection);
-
-					new_wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (tmp));
-					old_wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (connection));
-
-					/* Only update if different */
-					if (!nm_connection_compare (new_wrapped, old_wrapped, COMPARE_FLAGS_EXACT)) {
-						settings = nm_connection_to_hash (new_wrapped);
-						nm_exported_connection_update (NM_EXPORTED_CONNECTION (connection), settings, NULL);
-						g_hash_table_destroy (settings);
-					}
-
-					/* Update unmanaged status */
-					g_object_set (connection, "unmanaged", new_unmanaged, NULL);
-					g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
-				}
-				g_object_unref (tmp);
-			} else {
-				/* couldn't read connection; remove it */
-
-				PLUGIN_WARN (IFCFG_PLUGIN_NAME, "    error: %s",
-				             error->message ? error->message : "(unknown)");
-				g_error_free (error);
-
-				PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "removed %s.", name);
-				do_remove = TRUE;
-			}
-		} else {
-			do_new = TRUE;
+		new_wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (tmp));
+		old_wrapped = nm_exported_connection_get_connection (NM_EXPORTED_CONNECTION (connection));
+
+		/* Only update if different */
+		if (!nm_connection_compare (new_wrapped, old_wrapped, COMPARE_FLAGS_EXACT)) {
+			settings = nm_connection_to_hash (new_wrapped);
+			nm_exported_connection_update (NM_EXPORTED_CONNECTION (connection), settings, NULL);
+			g_hash_table_destroy (settings);
 		}
-		break;
-	default:
-		break;
+
+		/* Update unmanaged status */
+		g_object_set (connection, "unmanaged", new_unmanaged, NULL);
+		g_signal_emit_by_name (plugin, "unmanaged-devices-changed");
 	}
+	g_object_unref (tmp);
+}
+
+static void
+handle_connection_remove_or_new (SCPluginIfcfg *plugin,
+                                 const char *path,
+                                 NMIfcfgConnection *connection,
+                                 gboolean do_remove,
+                                 gboolean do_new)
+{
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+
+	g_return_if_fail (plugin != NULL);
+	g_return_if_fail (path != NULL);
 
 	if (do_remove) {
-		gboolean unmanaged = nm_ifcfg_connection_get_unmanaged (connection);
+		gboolean unmanaged;
+
+		g_return_if_fail (connection != NULL);
 
-		g_hash_table_remove (priv->connections, name);
+		unmanaged = nm_ifcfg_connection_get_unmanaged (connection);
+		g_hash_table_remove (priv->connections, path);
 		nm_exported_connection_signal_removed (NM_EXPORTED_CONNECTION (connection));
 
 		/* Emit unmanaged changes _after_ removing the connection */
@@ -316,12 +359,53 @@
 	}
 
 	if (do_new) {
-		connection = read_one_connection (plugin, name);
+		connection = read_one_connection (plugin, path);
 		if (connection) {
 			if (!nm_ifcfg_connection_get_unmanaged (NM_IFCFG_CONNECTION (connection)))
 				g_signal_emit_by_name (plugin, "connection-added", connection);
 		}
 	}
+}
+
+static void
+dir_changed (GFileMonitor *monitor,
+		   GFile *file,
+		   GFile *other_file,
+		   GFileMonitorEvent event_type,
+		   gpointer user_data)
+{
+	SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
+	SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (plugin);
+	char *name;
+	NMIfcfgConnection *connection;
+	gboolean do_remove = FALSE, do_new = FALSE;
+
+	name = g_file_get_path (file);
+	if (should_ignore_file (name)) {
+		g_free (name);
+		return;
+	}
+
+	connection = g_hash_table_lookup (priv->connections, name);
+	if (!connection) {
+		do_new = TRUE;
+	} else {
+		switch (event_type) {
+		case G_FILE_MONITOR_EVENT_DELETED:
+			PLUGIN_PRINT (IFCFG_PLUGIN_NAME, "removed %s.", name);
+			do_remove = TRUE;
+			break;
+		case G_FILE_MONITOR_EVENT_CREATED:
+		case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
+			/* Update */
+			connection_changed_handler (plugin, name, connection, &do_remove, &do_new);
+			break;
+		default:
+			break;
+		}
+	}
+
+	handle_connection_remove_or_new (plugin, name, connection, do_remove, do_new);
 
 	g_free (name);
 }

Modified: trunk/system-settings/plugins/ifcfg-fedora/reader.c
==============================================================================
--- trunk/system-settings/plugins/ifcfg-fedora/reader.c	(original)
+++ trunk/system-settings/plugins/ifcfg-fedora/reader.c	Tue May 13 16:53:50 2008
@@ -379,13 +379,12 @@
 	return success;
 }
 
-static shvarFile *
-get_keys_ifcfg (const char *parent)
+static char *
+get_keys_file_path (const char *parent)
 {
 	char *ifcfg_name;
 	char *keys_file = NULL;
 	char *tmp = NULL;
-	shvarFile *ifcfg = NULL;
 
 	ifcfg_name = get_ifcfg_name (parent);
 	if (!ifcfg_name)
@@ -396,15 +395,25 @@
 		goto out;
 
 	keys_file = g_strdup_printf ("%s/" KEYS_TAG "%s", tmp, ifcfg_name);
-	if (!keys_file)
-		goto out;
-
-	ifcfg = svNewFile (keys_file);
 
 out:
-	g_free (keys_file);
 	g_free (tmp);
 	g_free (ifcfg_name);
+	return keys_file;
+}
+
+static shvarFile *
+get_keys_ifcfg (const char *parent)
+{
+	shvarFile *ifcfg = NULL;
+	char *keys_file;
+
+	keys_file = get_keys_file_path (parent);
+	if (!keys_file)
+		return NULL;
+
+	ifcfg = svNewFile (keys_file);
+	g_free (keys_file);
 	return ifcfg;
 }
 
@@ -789,7 +798,10 @@
 }
 
 NMConnection *
-connection_from_file (const char *filename, gboolean *ignored, GError **error)
+connection_from_file (const char *filename,
+                      gboolean *ignored,
+                      char **keyfile,
+                      GError **error)
 {
 	NMConnection *connection = NULL;
 	shvarFile *parsed;
@@ -800,6 +812,8 @@
 
 	g_return_val_if_fail (filename != NULL, NULL);
 	g_return_val_if_fail (ignored != NULL, NULL);
+	g_return_val_if_fail (keyfile != NULL, NULL);
+	g_return_val_if_fail (*keyfile == NULL, NULL);
 
 	ifcfg_name = get_ifcfg_name (filename);
 	if (!ifcfg_name) {
@@ -897,6 +911,8 @@
 		             "Connection was invalid");
 	}
 
+	*keyfile = get_keys_file_path (filename);
+
 done:
 	svCloseFile (parsed);
 	return connection;

Modified: trunk/system-settings/plugins/ifcfg-fedora/reader.h
==============================================================================
--- trunk/system-settings/plugins/ifcfg-fedora/reader.h	(original)
+++ trunk/system-settings/plugins/ifcfg-fedora/reader.h	Tue May 13 16:53:50 2008
@@ -24,6 +24,9 @@
 #include <glib.h>
 #include <nm-connection.h>
 
-NMConnection *connection_from_file (const char *filename, gboolean *ignored, GError **error);
+NMConnection *connection_from_file (const char *filename,
+                                    gboolean *ignored,
+                                    char **keyfile,
+                                    GError **error);
 
 #endif  /* __READER_H__ */



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