gnome-panel r11024 - in trunk: . applets/clock



Author: vuntz
Date: Thu Apr 10 02:38:33 2008
New Revision: 11024
URL: http://svn.gnome.org/viewvc/gnome-panel?rev=11024&view=rev

Log:
2008-04-10  Vincent Untz  <vuntz gnome org>

	* configure.in: add gio check for CLOCK_MECHANISM, because of the use
	of system-timezone.c

2008-04-10  Vincent Untz  <vuntz gnome org>

	Rewrite the code to set the system timezone. It should work on most
	distributions now, instead of only the ones doing the same thing as
	Fedora. Like the rewrite to get the timezone, it helps improve the
	world.

	* Makefile.am: fix typo and add system-timezone.[ch] to
	gnome_clock_applet_mechanism_SOURCES
	* gnome-clock-applet-mechanism.c:
	(gnome_clock_applet_mechanism_set_timezone): just call
	system_timezone_set_from_file()
	* system-timezone.[ch]: add clear comments and some code to easily test
	the functions
	Also add comments on our current knowledge about system timezones on
	the various distributions.
	(system_timezone_constructor),
	(system_timezone_finalize): fix the same singleton issue as the one
	fixed in the previous commit
	(system_timezone_write_etc_timezone),
	(system_timezone_write_key_file),
	(system_timezone_write_etc_TIMEZONE),
	(system_timezone_write_etc_sysconfig_clock),
	(system_timezone_write_etc_sysconfig_clock_alt),
	(system_timezone_write_etc_conf_d_clock),
	(system_timezone_is_zone_file_valid),
	(system_timezone_set_etc_timezone),
	(system_timezone_update_config), (system_timezone_set_from_file),
	(system_timezone_set), (system_timezone_error_quark): well, all new. To
	do some magic things. Some code is loosely based on what was in
	gnome-clock-applet-mechanism.c


Modified:
   trunk/ChangeLog
   trunk/applets/clock/ChangeLog
   trunk/applets/clock/Makefile.am
   trunk/applets/clock/gnome-clock-applet-mechanism.c
   trunk/applets/clock/system-timezone.c
   trunk/applets/clock/system-timezone.h
   trunk/configure.in

Modified: trunk/applets/clock/Makefile.am
==============================================================================
--- trunk/applets/clock/Makefile.am	(original)
+++ trunk/applets/clock/Makefile.am	Thu Apr 10 02:38:33 2008
@@ -66,7 +66,7 @@
 	clock-zonetable.c	\
 	clock-zonetable.h	\
 	system-timezone.c	\
-	system-timzone.h	\
+	system-timezone.h	\
 	$(BUILT_SOURCES)	\
 	$(CALENDAR_SOURCES)	\
 	$(SETTIME_SOURCES)
@@ -126,7 +126,9 @@
 gnome_clock_applet_mechanism_SOURCES =		\
 	gnome-clock-applet-mechanism.c		\
 	gnome-clock-applet-mechanism.h		\
-	gnome-clock-applet-mechanism-main.c
+	gnome-clock-applet-mechanism-main.c	\
+	system-timezone.c			\
+	system-timezone.h
 
 if HAVE_POLKIT
 BUILT_SOURCES += gnome-clock-applet-mechanism-glue.h

Modified: trunk/applets/clock/gnome-clock-applet-mechanism.c
==============================================================================
--- trunk/applets/clock/gnome-clock-applet-mechanism.c	(original)
+++ trunk/applets/clock/gnome-clock-applet-mechanism.c	Thu Apr 10 02:38:33 2008
@@ -39,6 +39,8 @@
 
 #include <polkit-dbus/polkit-dbus.h>
 
+#include "system-timezone.h"
+
 #include "gnome-clock-applet-mechanism.h"
 #include "gnome-clock-applet-mechanism-glue.h"
 
@@ -470,12 +472,10 @@
 
 
 gboolean
-gnome_clock_applet_mechanism_set_timezone (GnomeClockAppletMechanism    *mechanism,
-                                           const char                   *zone_file,
-                                           DBusGMethodInvocation        *context)
+gnome_clock_applet_mechanism_set_timezone (GnomeClockAppletMechanism *mechanism,
+                                           const char                *zone_file,
+                                           DBusGMethodInvocation     *context)
 {
-        char *data;
-        gsize len;
         GError *error;
 
         reset_killtimer ();
@@ -484,87 +484,28 @@
         if (!_check_polkit_for_action (mechanism, context, "org.gnome.clockapplet.mechanism.settimezone"))
                 return FALSE;
 
-        /* First, check the zone_file is properly rooted (TODO: May be OS specific) */
-        if (!g_str_has_prefix (zone_file, "/usr/share/zoneinfo/")) {
-                error = g_error_new (GNOME_CLOCK_APPLET_MECHANISM_ERROR,
-                                     GNOME_CLOCK_APPLET_MECHANISM_ERROR_INVALID_TIMEZONE_FILE,
-                                     "Timezone file needs to be somewhere under /usr/share/zoneinfo");
-                dbus_g_method_return_error (context, error);
-                g_error_free (error);
-                return FALSE;
-        }
+        error = NULL;
 
-        /* Second, check it's a regular file that exists */
-        if (!g_file_test (zone_file, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_REGULAR)) {
-                error = g_error_new (GNOME_CLOCK_APPLET_MECHANISM_ERROR,
-                                     GNOME_CLOCK_APPLET_MECHANISM_ERROR_INVALID_TIMEZONE_FILE,
-                                     "No such timezone file %s", zone_file);
-                dbus_g_method_return_error (context, error);
-                g_error_free (error);
-                return FALSE;
-        }
+        if (!system_timezone_set_from_file (zone_file, &error)) {
+                GError *error2;
+                int     code;
 
-        /* Now copy the file to /etc/localtime. This is what we do on
-         * Red Hat / Fedora; to handle updates of tzdata
-         * /etc/sysconfig/clock has a ZONE="<timezone>" entry that is
-         * used to regenerate /etc/localtime.
-         *
-         * TODO: Check if /etc/localtime is a symlink and write out a symlink
-         *       into /usr/share/zoneinfo instead.
-         */
+                if (error->code == SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE)
+                        code = GNOME_CLOCK_APPLET_MECHANISM_ERROR_INVALID_TIMEZONE_FILE;
+                else 
+                        code = GNOME_CLOCK_APPLET_MECHANISM_ERROR_GENERAL;
 
-        error = NULL;
-        if (!g_file_get_contents (zone_file, &data, &len, &error)) {
-                GError *error2;
                 error2 = g_error_new (GNOME_CLOCK_APPLET_MECHANISM_ERROR,
-                                      GNOME_CLOCK_APPLET_MECHANISM_ERROR_GENERAL,
-                                      "Error reading timezone file %s: %s", zone_file, error->message);
-                g_error_free (error);
-                dbus_g_method_return_error (context, error2);
-                g_error_free (error2);
-                return FALSE;
-        }
+                                      code, error->message);
 
-        /* Verify it's a tzfile (see tzfile(5))
-         *
-         * TODO: is there glibc API for this? 
-         */
-        if (data[0] != 'T' ||
-            data[1] != 'Z' ||
-            data[2] != 'i' ||
-            data[3] != 'f') {
-                error = g_error_new (GNOME_CLOCK_APPLET_MECHANISM_ERROR,
-                                     GNOME_CLOCK_APPLET_MECHANISM_ERROR_GENERAL,
-                                     "File %s is not a timezone file", zone_file);
-                dbus_g_method_return_error (context, error);
                 g_error_free (error);
-                g_free (data);
-                return FALSE;
-        }
 
-        if (!g_file_set_contents ("/etc/localtime", data, len, &error)) {
-                GError *error2;
-                error2 = g_error_new (GNOME_CLOCK_APPLET_MECHANISM_ERROR,
-                                      GNOME_CLOCK_APPLET_MECHANISM_ERROR_GENERAL,
-                                      "Error writing timezone data to /etc/localtime: %s", error->message);
-                g_error_free (error);
                 dbus_g_method_return_error (context, error2);
                 g_error_free (error2);
-                g_free (data);
-                return FALSE;
-        }
-        g_free (data);
 
-        /* OS specific bits here: */
-
-	/* FMQ: openSUSE uses "TIMEZONE=", not "ZONE=" */
-        data = g_strdup_printf ("\"%s\"", zone_file + sizeof ("/usr/share/zoneinfo"));
-        if (!_rh_update_etc_sysconfig_clock (context, "ZONE=", data)) {
-                g_free (data);
                 return FALSE;
         }
-        g_free (data);
-        
+
         dbus_g_method_return (context);
         return TRUE;
 }

Modified: trunk/applets/clock/system-timezone.c
==============================================================================
--- trunk/applets/clock/system-timezone.c	(original)
+++ trunk/applets/clock/system-timezone.c	Thu Apr 10 02:38:33 2008
@@ -1,7 +1,3 @@
-/* To compile a test program, do:
- * gcc -DSYSTZ_TEST -Wall -o system-timezone `pkg-config --cflags --libs glib-2.0` system-timezone.c
- */
-
 /* System timezone handling
  *
  * Copyright (C) 2008 Novell, Inc.
@@ -44,27 +40,50 @@
  * Largely based on Michael Fulbright's work on Anaconda.
  */
 
+/* To compile a test program, do:
+ * $ gcc -DSYSTZ_GET_TEST -Wall -o system-timezone-get `pkg-config --cflags --libs glib-2.0 gobject-2.0 gio-2.0` system-timezone.c
+ * or:
+ * $ gcc -DSYSTZ_SET_TEST -Wall -o system-timezone-set `pkg-config --cflags --libs glib-2.0 gobject-2.0 gio-2.0` system-timezone.c
+ *
+ * You can then read the system timezone with:
+ * $ system-timezone-get
+ * and simulate a set of system timezone (in /tmp/etc/...) with:
+ * $ system-timezone-set "Europe/Paris"
+ */
+
+
 /* FIXME: it'd be nice to filter out the timezones that we might get when
  * parsing config files that are not in zone.tab */
 
 #include <string.h>
+#include <unistd.h>
 
 #include <glib.h>
 #include <glib/gstdio.h>
+#include <gio/gio.h>
+
+#include "system-timezone.h"
 
 /* Files that we look at and that should be monitored */
 #define CHECK_NB 5
+#ifndef SYSTZ_SET_TEST
 #define ETC_TIMEZONE        "/etc/timezone"
 #define ETC_TIMEZONE_MAJ    "/etc/TIMEZONE"
 #define ETC_SYSCONFIG_CLOCK "/etc/sysconfig/clock"
 #define ETC_CONF_D_CLOCK    "/etc/conf.d/clock"
 #define ETC_LOCALTIME       "/etc/localtime"
+#else
+/* Filenames that will be writable for testing */
+#define TEST_PREFIX         "/tmp/systz-test"
+#define ETC_TIMEZONE        TEST_PREFIX"/etc/timezone"
+#define ETC_TIMEZONE_MAJ    TEST_PREFIX"/etc/TIMEZONE"
+#define ETC_SYSCONFIG_CLOCK TEST_PREFIX"/etc/sysconfig/clock"
+#define ETC_CONF_D_CLOCK    TEST_PREFIX"/etc/conf.d/clock"
+#define ETC_LOCALTIME       TEST_PREFIX"/etc/localtime"
+#endif /* SYSTZ_SET_TEST */
 
-#ifndef SYSTZ_TEST
-
-#include <gio/gio.h>
-
-#include "system-timezone.h"
+/* The first 4 characters in a timezone file, from tzfile.h */
+#define TZ_MAGIC "TZif"
 
 static char *files_to_check[CHECK_NB] = {
         ETC_TIMEZONE,
@@ -74,6 +93,8 @@
         ETC_LOCALTIME
 };
 
+static GObject *systz_singleton = NULL;
+
 G_DEFINE_TYPE (SystemTimezone, system_timezone, G_TYPE_OBJECT)
 
 typedef struct {
@@ -168,13 +189,13 @@
                              guint                  n_construct_properties,
                              GObjectConstructParam *construct_properties)
 {
-        static GObject *obj = NULL;
+        GObject *obj;
         SystemTimezonePrivate *priv;
         int i;
 
         /* This is a singleton, we don't need to have it per-applet */
-        if (obj)
-                return g_object_ref (obj);
+        if (systz_singleton)
+                return g_object_ref (systz_singleton);
 
         obj = G_OBJECT_CLASS (system_timezone_parent_class)->constructor (
                                                 type,
@@ -203,7 +224,9 @@
                                           obj);
         }
 
-        return obj;
+        systz_singleton = obj;
+
+        return systz_singleton;
 }
 
 static void
@@ -228,6 +251,10 @@
         }
 
         G_OBJECT_CLASS (system_timezone_parent_class)->finalize (obj);
+
+        g_assert (obj == systz_singleton);
+
+        systz_singleton = NULL;
 }
 
 static void
@@ -261,7 +288,35 @@
                 g_free (new_tz);
 }
 
-#endif /* SYSTZ_TEST */
+
+/*
+ * Code to deal with the system timezone on all distros.
+ * There's no dependency on the SystemTimezone GObject here.
+ *
+ * Here's what we know:
+ *
+ *  + /etc/localtime contains the binary data of the timezone.
+ *    It can be a symlink to the actual data file, a hard link to the data
+ *    file, or just a copy. So we can determine the timezone with this
+ *    (reading the symlink, comparing inodes, or comparing content).
+ *
+ *  + However, most distributions also have the timezone setting
+ *    configured somewhere else. This might be better to read it from there.
+ *
+ *    Fedora/Mandriva: the ZONE key in /etc/sysconfig/clock
+ *    openSUSE: the TIMEZONE key in /etc/sysconfig/clock
+ *    Gentoo (old): the ZONE key in /etc/conf.d/clock
+ *    Debian/Ubuntu/Gentoo (new): content of /etc/timezone
+ *    Solaris/OpenSolaris: the TZ key in /etc/TIMEZONE
+ *
+ *    FIXME: reading the system-tools-backends, it seems there's this too:
+ *           ArchLinux: the TIMEZONE key in /etc/rc.conf
+ *           Solaris: the TZ key in /etc/default/init
+ *                    /etc/TIMEZONE seems to be a link to /etc/default/init
+ *
+ * First, some functions to handle those system config files.
+ *
+ */
 
 /* This works for Debian and derivatives (including Ubuntu) */
 static char *
@@ -294,6 +349,35 @@
         return NULL;
 }
 
+static gboolean
+system_timezone_write_etc_timezone (const char  *tz,
+                                    GError     **error)
+{
+        char     *content;
+        GError   *our_error;
+        gboolean  retval;
+
+        if (!g_file_test (ETC_TIMEZONE, G_FILE_TEST_IS_REGULAR))
+                return TRUE;
+
+        content = g_strdup_printf ("%s\n", tz);
+
+        our_error = NULL;
+        retval = g_file_set_contents (ETC_TIMEZONE, content, -1, &our_error);
+        g_free (content);
+
+        if (!retval) {
+                g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+                             SYSTEM_TIMEZONE_ERROR_GENERAL,
+                             ETC_TIMEZONE" cannot be overwritten: %s",
+                             our_error->message);
+                g_error_free (our_error);
+        }
+
+        return retval;
+}
+
+
 /* Read a file that looks like a key-file (but there's no need for groups)
  * and get the last value for a specific key */
 static char *
@@ -353,6 +437,87 @@
         return retval;
 }
 
+static gboolean
+system_timezone_write_key_file (const char  *filename,
+                                const char  *key,
+                                const char  *value,
+                                GError     **error)
+{
+        GError        *our_error;
+        char          *content;
+        unsigned int   len;
+        char          *key_eq;
+        char         **lines;
+        gboolean       replaced;
+        gboolean       retval;
+        int            n;
+        
+        if (!g_file_test (filename, G_FILE_TEST_IS_REGULAR))
+                return TRUE;
+
+        our_error = NULL;
+
+        if (!g_file_get_contents (filename, &content, &len, &our_error)) {
+                g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+                             SYSTEM_TIMEZONE_ERROR_GENERAL,
+                             "%s cannot be read: %s",
+                             filename, our_error->message);
+                g_error_free (our_error);
+                return FALSE;
+        }
+
+        lines = g_strsplit (content, "\n", 0);
+        g_free (content);
+
+        key_eq = g_strdup_printf ("%s=", key);
+        replaced = FALSE;
+
+        for (n = 0; lines[n] != NULL; n++) {
+                if (g_str_has_prefix (lines[n], key_eq)) {
+                        char     *old_value;
+                        gboolean  use_quotes;
+
+                        old_value = lines[n] + strlen (key_eq);
+                        g_strstrip (old_value);
+                        use_quotes = old_value[0] == '\"';
+
+                        g_free (lines[n]);
+
+                        if (use_quotes)
+                                lines[n] = g_strdup_printf ("%s\"%s\"",
+                                                            key_eq, value);
+                        else
+                                lines[n] = g_strdup_printf ("%s%s",
+                                                            key_eq, value);
+
+                        replaced = TRUE;
+                }
+        }
+
+        g_free (key_eq);
+
+        if (!replaced) {
+                g_strfreev (lines);
+                return TRUE;
+        }
+
+        content = g_strjoinv ("\n", lines);
+        g_strfreev (lines);
+
+        retval = g_file_set_contents (filename, content, -1, &our_error);
+        g_free (content);
+
+        if (!retval) {
+                g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+                             SYSTEM_TIMEZONE_ERROR_GENERAL,
+                             "%s cannot be overwritten: %s",
+                             filename, our_error->message);
+                g_error_free (our_error);
+        }
+
+        return retval;
+}
+
 /* This works for Solaris/OpenSolaris */
 static char *
 system_timezone_read_etc_TIMEZONE (void)
@@ -361,6 +526,14 @@
                                               "TZ");
 }
 
+static gboolean
+system_timezone_write_etc_TIMEZONE (const char  *tz,
+                                    GError     **error)
+{
+        return system_timezone_write_key_file (ETC_TIMEZONE_MAJ,
+                                               "TZ", tz, error);
+}
+
 /* This works for Fedora and Mandriva */
 static char *
 system_timezone_read_etc_sysconfig_clock (void)
@@ -369,6 +542,14 @@
                                               "ZONE");
 }
 
+static gboolean
+system_timezone_write_etc_sysconfig_clock (const char  *tz,
+                                           GError     **error)
+{
+        return system_timezone_write_key_file (ETC_SYSCONFIG_CLOCK,
+                                               "ZONE", tz, error);
+}
+
 /* This works for openSUSE */
 static char *
 system_timezone_read_etc_sysconfig_clock_alt (void)
@@ -377,6 +558,14 @@
                                               "TIMEZONE");
 }
 
+static gboolean
+system_timezone_write_etc_sysconfig_clock_alt (const char  *tz,
+                                               GError     **error)
+{
+        return system_timezone_write_key_file (ETC_SYSCONFIG_CLOCK,
+                                               "TIMEZONE", tz, error);
+}
+
 /* This works for old Gentoo */
 static char *
 system_timezone_read_etc_conf_d_clock (void)
@@ -385,6 +574,20 @@
                                               "TIMEZONE");
 }
 
+static gboolean
+system_timezone_write_etc_conf_d_clock (const char  *tz,
+                                        GError     **error)
+{
+        return system_timezone_write_key_file (ETC_CONF_D_CLOCK,
+                                               "TIMEZONE", tz, error);
+}
+
+/*
+ *
+ * First, getting the timezone.
+ *
+ */
+
 /* Read the soft symlink from /etc/localtime */
 static char *
 system_timezone_read_etc_localtime_softlink (void)
@@ -606,7 +809,196 @@
         return g_strdup ("UTC");
 }
 
-#ifdef SYSTZ_TEST
+/*
+ *
+ * Now, setting the timezone.
+ *
+ */
+
+static gboolean
+system_timezone_is_zone_file_valid (const char  *zone_file,
+                                    GError     **error)
+{
+        GError       *our_error;
+        GIOChannel   *channel;
+        GIOStatus     status;
+        char          buffer[strlen (TZ_MAGIC)];
+        unsigned int  read;
+
+        /* First, check the zone_file is properly rooted */
+        if (!g_str_has_prefix (zone_file, SYSTEM_ZONEINFODIR"/")) {
+                g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+                             SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE,
+                             "Timezone file needs to be under "SYSTEM_ZONEINFODIR);
+                return FALSE;
+        }
+
+        /* Second, check it's a regular file that exists */
+        if (!g_file_test (zone_file, G_FILE_TEST_IS_REGULAR)) {
+                g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+                             SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE,
+                             "No such timezone file %s", zone_file);
+                return FALSE;
+        }
+
+        /* Third, check that it's a tzfile (see tzfile(5)). The file has a 4
+         * bytes header which is TZ_MAGIC.
+         *
+         * TODO: is there glibc API for this? */
+        our_error = NULL;
+        channel = g_io_channel_new_file (zone_file, "r", &our_error);
+        if (!our_error)
+                status = g_io_channel_read_chars (channel,
+                                                  buffer, strlen (TZ_MAGIC),
+                                                  &read, &our_error);
+        if (channel)
+                g_io_channel_unref (channel);
+
+        if (our_error) {
+                g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+                             SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE,
+                             "Timezone file %s cannot be read: %s",
+                             zone_file, our_error->message);
+                g_error_free (our_error);
+                return FALSE;
+        }
+
+        if (read != 4 || strcmp (buffer, TZ_MAGIC) != 0) {
+                g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+                             SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE,
+                             "%s is not a timezone file",
+                             zone_file);
+                return FALSE;
+        }
+
+        return TRUE;
+}
+
+static gboolean
+system_timezone_set_etc_timezone (const char  *zone_file,
+                                  GError     **error)
+{
+        GError       *our_error;
+        char         *content;
+        unsigned int  len;
+
+        if (!system_timezone_is_zone_file_valid (zone_file, error))
+                return FALSE;
+
+        /* If /etc/localtime is a symlink, write a symlink */
+        if (g_file_test (ETC_LOCALTIME, G_FILE_TEST_IS_SYMLINK)) {
+                if (g_unlink (ETC_LOCALTIME) == 0 &&
+                    symlink (zone_file, ETC_LOCALTIME) == 0)
+                        return TRUE;
+
+                /* If we couldn't symlink the file, we'll just fallback on
+                 * copying it */
+        }
+
+        /* Else copy the file to /etc/localtime. We explicitly avoid doing
+         * hard links since they break with different partitions */
+        our_error = NULL;
+        if (!g_file_get_contents (zone_file, &content, &len, &our_error)) {
+                g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+                             SYSTEM_TIMEZONE_ERROR_GENERAL,
+                             "Timezone file %s cannot be read: %s",
+                             zone_file, our_error->message);
+                g_error_free (our_error);
+                return FALSE;
+        }
+
+        if (!g_file_set_contents (ETC_LOCALTIME, content, len, &our_error)) {
+                g_set_error (error, SYSTEM_TIMEZONE_ERROR,
+                             SYSTEM_TIMEZONE_ERROR_GENERAL,
+                             ETC_LOCALTIME" cannot be overwritten: %s",
+                             our_error->message);
+                g_error_free (our_error);
+                g_free (content);
+                return FALSE;
+        }
+
+        g_free (content);
+
+        return TRUE;
+}
+
+typedef gboolean (*SetSystemTimezone) (const char  *tz,
+                                       GError     **error);
+static SetSystemTimezone set_system_timezone_methods[] = {
+        system_timezone_write_etc_timezone,
+        system_timezone_write_etc_TIMEZONE,
+        system_timezone_write_etc_sysconfig_clock,
+        system_timezone_write_etc_sysconfig_clock_alt,
+        system_timezone_write_etc_conf_d_clock,
+        NULL
+};
+
+static gboolean
+system_timezone_update_config (const char  *tz,
+                               GError     **error)
+{
+        int i;
+
+        for (i = 0; set_system_timezone_methods[i] != NULL; i++) {
+                if (!set_system_timezone_methods[i] (tz, error))
+                        return FALSE;
+                /* FIXME: maybe continue to change all config files if
+                 * possible? */
+        }
+
+        return TRUE;
+}
+
+gboolean
+system_timezone_set_from_file (const char  *zone_file,
+                               GError     **error)
+{
+        const char *tz;
+
+        g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+        tz = zone_file + strlen (SYSTEM_ZONEINFODIR"/");
+
+        /* FIXME: is it right to return FALSE even when /etc/localtime was
+         * changed but not the config files? */
+        return (system_timezone_set_etc_timezone (zone_file, error) &&
+                system_timezone_update_config (tz, error));
+}
+
+gboolean
+system_timezone_set (const char  *tz,
+                     GError     **error)
+{
+        char     *zone_file;
+        gboolean  retval;
+
+        g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+        zone_file = g_build_filename (SYSTEM_ZONEINFODIR, tz, NULL);
+
+        /* FIXME: is it right to return FALSE even when /etc/localtime was
+         * changed but not the config files? */
+        retval = system_timezone_set_etc_timezone (zone_file, error) &&
+                 system_timezone_update_config (tz, error);
+
+        g_free (zone_file);
+
+        return retval;
+}
+
+GQuark
+system_timezone_error_quark (void)
+{
+        static GQuark ret = 0;
+
+        if (ret == 0) {
+                ret = g_quark_from_static_string ("system-timezone-error");
+        }
+
+        return ret;
+}
+
+#ifdef SYSTZ_GET_TEST
 int
 main (int    argc,
       char **argv)
@@ -619,4 +1011,42 @@
 
         return 0;
 }
-#endif /* SYSTZ_TEST */
+#endif /* SYSTZ_GET_TEST */
+
+#ifdef SYSTZ_SET_TEST
+int
+main (int    argc,
+      char **argv)
+{
+        GError *error;
+        char   *dirname;
+
+        if (argc != 2) {
+                g_print ("Usage: %s TIMEZONE\n", argv[0]);
+                return 1;
+        }
+
+        dirname = g_path_get_dirname (ETC_TIMEZONE);
+        g_mkdir_with_parents (dirname, 0755);
+        g_free (dirname);
+        dirname = g_path_get_dirname (ETC_SYSCONFIG_CLOCK);
+        g_mkdir_with_parents (dirname, 0755);
+        g_free (dirname);
+        dirname = g_path_get_dirname (ETC_CONF_D_CLOCK);
+        g_mkdir_with_parents (dirname, 0755);
+        g_free (dirname);
+
+        error = NULL;
+        if (!system_timezone_set (argv[1], &error)) {
+                g_print ("%s\n", error->message);
+                g_error_free (error);
+                return 1;
+        }
+
+        g_print (TEST_PREFIX" is the test directory where files "
+                 "were written (feel free to populate this directory with "
+                 "files that should be modified by this program).\n");
+
+        return 0;
+}
+#endif /* SYSTZ_SET_TEST */

Modified: trunk/applets/clock/system-timezone.h
==============================================================================
--- trunk/applets/clock/system-timezone.h	(original)
+++ trunk/applets/clock/system-timezone.h	Thu Apr 10 02:38:33 2008
@@ -61,5 +61,23 @@
 const char *system_timezone_get (SystemTimezone *systz);
 const char *system_timezone_get_env (SystemTimezone *systz);
 
+/* Functions to set the timezone. They won't be used by the applet, but
+ * by a program with more privileges */
+
+#define SYSTEM_TIMEZONE_ERROR system_timezone_error_quark ()
+GQuark system_timezone_error_quark (void);
+
+typedef enum
+{
+        SYSTEM_TIMEZONE_ERROR_GENERAL,
+        SYSTEM_TIMEZONE_ERROR_INVALID_TIMEZONE_FILE,
+        SYSTEM_TIMEZONE_NUM_ERRORS
+} SystemTimezoneError;
+
+gboolean system_timezone_set_from_file (const char  *zone_file,
+                                        GError     **error);
+gboolean system_timezone_set (const char  *tz,
+                              GError     **error);
+
 G_END_DECLS
 #endif /* __SYSTEM_TIMEZONE_H__ */

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Thu Apr 10 02:38:33 2008
@@ -1,4 +1,4 @@
-AC_INIT([gnome-panel], [2.22.2],
+AC_INIT([gnome-panel], [2.22.1.2],
         [http://bugzilla.gnome.org/enter_bug.cgi?product=gnome-panel])
 AM_CONFIG_HEADER(config.h)
 AM_INIT_AUTOMAKE([1.9 no-dist-gzip dist-bzip2])
@@ -116,7 +116,7 @@
 AC_SUBST(CLOCK_LIBS)
 
 dnl Hmm, we already checked for these above.  Is there a way to avoid checking twice?
-PKG_CHECK_MODULES(CLOCK_MECHANISM, [ gthread-2.0 dbus-glib-1 ])
+PKG_CHECK_MODULES(CLOCK_MECHANISM, [ gthread-2.0 gio-2.0 dbus-glib-1 ])
 AC_SUBST(CLOCK_MECHANISM_CFLAGS)
 AC_SUBST(CLOCK_MECHANISM_LIBS)
 



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