[PATCH] IFUPDOWN - hostname read/write support



Implement system hostname support for debian/ubuntu

Make nm-inotify-helper from ifcfg-fedora plugin usable
for other plugins too


=== modified file 'ChangeLog'
--- a/ChangeLog	2008-10-03 21:51:57 +0000
+++ b/ChangeLog	2008-10-06 08:22:23 +0000
@@ -1,8 +1,36 @@
+2008-10-03  Alexander Sack  <asac ubuntu com>
+
+	Implement system hostname support for debian/ubuntu
+
+	* system-settings/plugins/ifupdown/plugin.c
+		- (GObject__set_property, GObject__get_property, SCPluginIfupdown_init, update_system_hostname, get_hostname):
+			implement hostname property that watches and
+			parses /etc/hostname
+
+
+	Make nm-inotify-helper from ifcfg-fedora plugin usable
+	for other plugins too
+
+	* system-settings/plugins/ifcfg-fedora/nm-inotify-helper.c (deleted)
+	  system-settings/plugins/ifcfg-fedora/nm-inotify-helper.h (deleted)
+	  system-settings/src/nm-inotify-helper.c (NEW)
+	  system-settings/src/nm-inotify-helper.h (NEW)
+	  system-settings/plugins/ifcfg-fedora/Makefile.am
+	  system-settings/src/Makefile.am
+		- make inotify available for all system plugins and
+			adjust ifcfg-fedora build accordingly
+
+	* system-settings/plugins/ifupdown/plugin.c
+		- (GObject__get_property): extend announced capabilities; add
+			NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME support
+		- (GObject__set_property,write_system_hostname): implement
+			NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME capability.
+
 2008-10-02  Alexander Sack  <asac ubuntu com>
 
 	Implement support for wep-tx-keyidx in ifupdown system
 	config plugin.
 
 	* system-settings/plugins/ifupdown/parser.c
 		- (update_wireless_security_setting_from_if_block): introduce
 			free_type_mapping func table; rename a few local

=== modified file 'system-settings/plugins/ifcfg-fedora/Makefile.am'
--- a/system-settings/plugins/ifcfg-fedora/Makefile.am	2008-05-13 16:53:50 +0000
+++ b/system-settings/plugins/ifcfg-fedora/Makefile.am	2008-10-02 22:32:18 +0000
@@ -5,19 +5,17 @@ libnm_settings_plugin_ifcfg_fedora_la_SO
 	shvar.c \
 	shvar.h \
 	plugin.c \
 	plugin.h \
 	nm-ifcfg-connection.c \
 	nm-ifcfg-connection.h \
 	reader.c \
 	reader.h \
-	common.h \
-	nm-inotify-helper.c \
-	nm-inotify-helper.h
+	common.h
 
 libnm_settings_plugin_ifcfg_fedora_la_CPPFLAGS = \
 	$(GLIB_CFLAGS) \
 	$(GMODULE_CFLAGS) \
 	$(DBUS_CFLAGS) \
 	-DG_DISABLE_DEPRECATED \
 	-I${top_srcdir}/system-settings/src \
 	-I$(top_srcdir)/include \

=== removed file 'system-settings/plugins/ifcfg-fedora/nm-inotify-helper.c'
--- a/system-settings/plugins/ifcfg-fedora/nm-inotify-helper.c	2008-08-26 09:34:31 +0000
+++ b/system-settings/plugins/ifcfg-fedora/nm-inotify-helper.c	1970-01-01 00:00:00 +0000
@@ -1,211 +0,0 @@
-/* -*- 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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);
-}
-

=== removed file 'system-settings/plugins/ifcfg-fedora/nm-inotify-helper.h'
--- a/system-settings/plugins/ifcfg-fedora/nm-inotify-helper.h	2008-06-26 18:31:52 +0000
+++ b/system-settings/plugins/ifcfg-fedora/nm-inotify-helper.h	1970-01-01 00:00:00 +0000
@@ -1,54 +0,0 @@
-/* -*- 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.,
- * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 file 'system-settings/plugins/ifupdown/plugin.c'
--- a/system-settings/plugins/ifupdown/plugin.c	2008-09-18 15:29:59 +0000
+++ b/system-settings/plugins/ifupdown/plugin.c	2008-10-04 17:09:53 +0000
@@ -36,32 +36,37 @@
 #include "nm-setting-ip4-config.h"
 #include "nm-setting-wireless.h"
 #include "nm-setting-wired.h"
 #include "nm-setting-ppp.h"
 
 #include "nm-ifupdown-connection.h"
 #include "plugin.h"
 #include "parser.h"
+#include "nm-inotify-helper.h"
 
 #include <nm-utils.h>
 #include <sha1.h>
 
 #include <arpa/inet.h>
 
 #define IFUPDOWN_PLUGIN_NAME "ifupdown"
 #define IFUPDOWN_PLUGIN_INFO "(C) 2008 Canonical Ltd.  To report bugs please use the NetworkManager mailing list."
+#define IFUPDOWN_SYSTEM_HOSTNAME_FILE "/etc/hostname"
 
 typedef struct {
 
 	DBusGConnection *g_connection;
 	NMSystemConfigHalManager *hal_mgr;
 
 	GHashTable *iface_connections;
-	
+	gchar* hostname;
+
+	gulong inotify_event_id;
+	int inotify_system_hostname_wd;
 } SCPluginIfupdownPrivate;
 
 static void
 system_config_interface_init (NMSystemConfigInterface *system_config_interface_class);
 
 G_DEFINE_TYPE_EXTENDED (SCPluginIfupdown, sc_plugin_ifupdown, G_TYPE_OBJECT, 0,
 				    G_IMPLEMENT_INTERFACE (NM_TYPE_SYSTEM_CONFIG_INTERFACE,
 									  system_config_interface_init))
@@ -100,21 +105,36 @@ SCPluginIfupdown_connection_added (NMSys
 static void
 SCPluginIfupdown_unmanaged_devices_changed (NMSystemConfigInterface *config);
 
 static void
 GObject__get_property (GObject *object, guint prop_id,
 				   GValue *value, GParamSpec *pspec);
 
 static void
+GObject__set_property (GObject *object, guint prop_id,
+				   const GValue *value, GParamSpec *pspec);
+
+static void
 GObject__dispose (GObject *object);
 
 static void
 GObject__finalize (GObject *object);
 
+/* other helpers */
+static const char *
+get_hostname (NMSystemConfigInterface *config);
+
+
+static void
+update_system_hostname(NMInotifyHelper *inotify_helper,
+                       struct inotify_event *evt,
+                       const char *path,
+                       NMSystemConfigInterface *config);
+
 
 static void
 system_config_interface_init (NMSystemConfigInterface *system_config_interface_class)
 {
 	system_config_interface_class->init = SCPluginIfupdown_init;
 	system_config_interface_class->get_connections = SCPluginIfupdown_get_connections;
 	system_config_interface_class->get_unmanaged_devices = SCPluginIfupdown_get_unmanaged_devices;
 	system_config_interface_class->connection_added = SCPluginIfupdown_connection_added;
@@ -126,16 +146,17 @@ sc_plugin_ifupdown_class_init (SCPluginI
 {
 	GObjectClass *object_class = G_OBJECT_CLASS (req_class);
 
 	g_type_class_add_private (req_class, sizeof (SCPluginIfupdownPrivate));
 
 	object_class->dispose = GObject__dispose;
 	object_class->finalize = GObject__finalize;
 	object_class->get_property = GObject__get_property;
+	object_class->set_property = GObject__set_property;
 
 	g_object_class_override_property (object_class,
 	                                  NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME,
 	                                  NM_SYSTEM_CONFIG_INTERFACE_NAME);
 
 	g_object_class_override_property (object_class,
 	                                  NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO,
 	                                  NM_SYSTEM_CONFIG_INTERFACE_INFO);
@@ -151,23 +172,35 @@ sc_plugin_ifupdown_class_init (SCPluginI
 
 static void
 SCPluginIfupdown_init (NMSystemConfigInterface *config,
 				   NMSystemConfigHalManager *hal_manager)
 {
 	SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (config);
 	GHashTable *auto_ifaces = g_hash_table_new (g_str_hash, g_str_equal);
 	if_block *block = NULL;
+	NMInotifyHelper *inotify_helper;
 
 	if(!priv->iface_connections)
 		priv->iface_connections = g_hash_table_new (g_str_hash, g_str_equal);
 
 	PLUGIN_PRINT("SCPlugin-Ifupdown", "init!");
 	priv->hal_mgr = g_object_ref (hal_manager);
 
+	inotify_helper = nm_inotify_helper_get ();
+	priv->inotify_event_id = g_signal_connect (inotify_helper,
+									   "event",
+									   G_CALLBACK (update_system_hostname),
+									   config);
+
+	priv->inotify_system_hostname_wd =
+		nm_inotify_helper_add_watch (inotify_helper, IFUPDOWN_SYSTEM_HOSTNAME_FILE);
+
+	update_system_hostname(inotify_helper, NULL, NULL, config);
+
 	ifparser_init();
 	block = ifparser_getfirst();
 
 	while(block) {
 		if(!strcmp("auto", block->type)) {
 			g_hash_table_insert (auto_ifaces, block->name, "auto");
 		} else if (!strcmp ("iface", block->type) && strcmp ("lo", block->name)) {
 			NMExportedConnection *connection = g_hash_table_lookup(priv->iface_connections, block->name);
@@ -260,58 +293,153 @@ static void
 SCPluginIfupdown_unmanaged_devices_changed (NMSystemConfigInterface *config)
 {
 	PLUGIN_PRINT("SCPlugin-Ifdown", "unmanaged_devices_changed ... started");
 	g_return_if_fail (config != NULL);
 
 	PLUGIN_PRINT("SCPlugin-Ifdown", "unmanaged_devices_changed ... ended");
 }
 
+static const char *
+get_hostname (NMSystemConfigInterface *config)
+{
+	SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (config);
+	return priv->hostname;
+}
+
+static void
+update_system_hostname(NMInotifyHelper *inotify_helper,
+                       struct inotify_event *evt,
+                       const char *path,
+                       NMSystemConfigInterface *config)
+{
+	SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (config);
+	gchar *hostname_file = NULL;
+	gsize hostname_file_len = 0;
+	GError *error = NULL;
+
+	PLUGIN_PRINT ("SCPlugin-Ifupdown", "update_system_hostname");
+
+	if (evt && evt->wd != priv->inotify_system_hostname_wd)
+		return;
+
+	if(!g_file_get_contents ( IFUPDOWN_SYSTEM_HOSTNAME_FILE,
+						 &hostname_file,
+						 &hostname_file_len,
+						 &error)) {
+		nm_warning ("update_system_hostname() - couldn't read "
+				  IFUPDOWN_SYSTEM_HOSTNAME_FILE " (%d/%s)",
+				  error->code, error->message);
+		return;
+	}
+
+	if (priv->hostname)
+		g_free(priv->hostname);
+
+	priv->hostname = g_strstrip(hostname_file);
+
+	g_object_notify (G_OBJECT (config), NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME);
+}
+
+static void
+write_system_hostname(NMSystemConfigInterface *config,
+				  const char *newhostname)
+{
+	GError *error = NULL;
+	SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (config);
+	PLUGIN_PRINT ("SCPlugin-Ifupdown", "write_system_hostname: %s", newhostname);
+
+	g_return_if_fail (newhostname);
+
+	if(!g_file_set_contents ( IFUPDOWN_SYSTEM_HOSTNAME_FILE,
+						 newhostname,
+						 -1,
+						 &error)) {
+		nm_warning ("update_system_hostname() - couldn't write hostname (%s) to "
+				  IFUPDOWN_SYSTEM_HOSTNAME_FILE " (%d/%s)",
+				  newhostname, error->code, error->message);	
+	} else {
+		priv->hostname = g_strdup (newhostname);
+	}
+	g_object_notify (G_OBJECT (config), NM_SYSTEM_CONFIG_INTERFACE_HOSTNAME);
+}
+
+
 static void
 sc_plugin_ifupdown_init (SCPluginIfupdown *plugin)
 {
 	SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (plugin);
 	GError *error = NULL;
 
 	priv->g_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
 	if (!priv->g_connection) {
-		PLUGIN_PRINT (IFUPDOWN_PLUGIN_NAME, "    dbus-glib error: %s",
+		PLUGIN_PRINT ("SCPlugin-Ifupdown", "    dbus-glib error: %s",
 		              error->message ? error->message : "(unknown)");
 		g_error_free (error);
 	}
 }
 
 static void
 GObject__get_property (GObject *object, guint prop_id,
 				   GValue *value, GParamSpec *pspec)
 {
+	NMSystemConfigInterface *self = NM_SYSTEM_CONFIG_INTERFACE (object);
+
 	switch (prop_id) {
 	case NM_SYSTEM_CONFIG_INTERFACE_PROP_NAME:
 		g_value_set_string (value, IFUPDOWN_PLUGIN_NAME);
 		break;
 	case NM_SYSTEM_CONFIG_INTERFACE_PROP_INFO:
 		g_value_set_string (value, IFUPDOWN_PLUGIN_INFO);
 		break;
 	case NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES:
-		g_value_set_uint (value, NM_SYSTEM_CONFIG_INTERFACE_CAP_NONE);
+		g_value_set_uint (value, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME);
 		break;
 	case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME:
-		g_value_set_string (value, "");
+		{
+			g_value_set_string (value, get_hostname(self));
+			break;
+		}
+	default:
+		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
+	}
+}
+
+static void
+GObject__set_property (GObject *object, guint prop_id,
+				   const GValue *value, GParamSpec *pspec)
+{
+	switch (prop_id) {
+	case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME:
+		{
+			const gchar *hostname = g_value_get_string (value);
+			if (hostname && strlen (hostname) < 1)
+				hostname = NULL;
+			write_system_hostname(NM_SYSTEM_CONFIG_INTERFACE(object),
+							  hostname);
+			break;
+		}
 	default:
 		G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
 		break;
 	}
 }
 
 static void
 GObject__dispose (GObject *object)
 {
 	SCPluginIfupdown *plugin = SC_PLUGIN_IFUPDOWN (object);
 	SCPluginIfupdownPrivate *priv = SC_PLUGIN_IFUPDOWN_GET_PRIVATE (plugin);
+	NMInotifyHelper *inotify_helper = nm_inotify_helper_get ();
+
+	g_signal_handler_disconnect (inotify_helper, priv->inotify_event_id);
+
+	if (priv->inotify_system_hostname_wd >= 0)
+		nm_inotify_helper_remove_watch (inotify_helper, priv->inotify_system_hostname_wd);
 
 	g_object_unref (priv->hal_mgr);
 	G_OBJECT_CLASS (sc_plugin_ifupdown_parent_class)->dispose (object);
 }
 
 static void
 GObject__finalize (GObject *object)
 {

=== modified file 'system-settings/src/Makefile.am'
--- a/system-settings/src/Makefile.am	2008-07-16 07:37:10 +0000
+++ b/system-settings/src/Makefile.am	2008-10-02 22:32:18 +0000
@@ -8,16 +8,18 @@ sbin_PROGRAMS = nm-system-settings
 
 BUILT_SOURCES = \
 	nm-settings-system-glue.h
 
 nm_system_settings_SOURCES = \
 	dbus-settings.c \
 	dbus-settings.h \
 	main.c \
+	nm-inotify-helper.c \
+	nm-inotify-helper.h \
 	nm-polkit-helpers.c \
 	nm-polkit-helpers.h \
 	nm-system-config-error.c \
 	nm-system-config-error.h \
 	nm-system-config-interface.c \
 	nm-system-config-interface.h \
 	nm-system-config-hal-manager.c \
 	nm-system-config-hal-manager.h \

=== added file 'system-settings/src/nm-inotify-helper.c'
--- a/system-settings/src/nm-inotify-helper.c	1970-01-01 00:00:00 +0000
+++ b/system-settings/src/nm-inotify-helper.c	2008-10-02 22:32:18 +0000
@@ -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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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 file 'system-settings/src/nm-inotify-helper.h'
--- a/system-settings/src/nm-inotify-helper.h	1970-01-01 00:00:00 +0000
+++ b/system-settings/src/nm-inotify-helper.h	2008-10-02 22:32:18 +0000
@@ -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.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 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__ */



 - Alexander



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