[evolution-data-server] Bug #680687 - System timezone name differs from set in Gnome



commit a429796949cabf292120d451bc58ceda2e54280c
Author: Milan Crha <mcrha redhat com>
Date:   Fri Jul 27 12:36:42 2012 +0200

    Bug #680687 - System timezone name differs from set in Gnome

 calendar/libecal/e-cal-system-timezone.c |   95 +++++++++++++++++++++++++-----
 1 files changed, 80 insertions(+), 15 deletions(-)
---
diff --git a/calendar/libecal/e-cal-system-timezone.c b/calendar/libecal/e-cal-system-timezone.c
index bf7d523..dd51836 100644
--- a/calendar/libecal/e-cal-system-timezone.c
+++ b/calendar/libecal/e-cal-system-timezone.c
@@ -412,10 +412,10 @@ system_timezone_read_etc_localtime_content (GHashTable *ical_zones)
 	static gchar *last_timezone = NULL;
 	static GStaticRecMutex mutex = G_STATIC_REC_MUTEX_INIT;
 
-	struct stat  stat_localtime;
-	gchar	*localtime_content = NULL;
-	gsize	localtime_content_len = -1;
-	gchar	*retval, *fallback = NULL;
+	struct stat stat_localtime;
+	gchar *localtime_content = NULL;
+	gsize localtime_content_len = -1;
+	gchar *retval, *fallback = NULL;
 
 	if (g_stat (ETC_LOCALTIME, &stat_localtime) != 0)
 		return NULL;
@@ -478,13 +478,7 @@ system_timezone_read_etc_localtime_content (GHashTable *ical_zones)
 typedef gchar * (*GetSystemTimezone) (GHashTable *ical_zones);
 /* The order of the functions here define the priority of the methods used
  * to find the timezone. First method has higher priority. */
-static GetSystemTimezone get_system_timezone_methods[] = {
-	/* cheap and "more correct" than data from a config file */
-	system_timezone_read_etc_localtime_softlink,
-	/* reading /etc/timezone directly. Expensive since we have to stat
-	 * many files, but it returns always correct values, even on KDE */
-	system_timezone_read_etc_localtime_content,
-	system_timezone_read_etc_localtime_hardlink,
+static GetSystemTimezone get_system_timezone_methods_config[] = {
 	/* reading various config files */
 	system_timezone_read_etc_timezone,
 	system_timezone_read_etc_sysconfig_clock,
@@ -496,6 +490,14 @@ static GetSystemTimezone get_system_timezone_methods[] = {
 	NULL
 };
 
+static GetSystemTimezone get_system_timezone_methods_slow[] = {
+	/* reading /etc/timezone directly. Expensive since we have to stat
+	 * many files, but it returns always correct values, even on KDE */
+	system_timezone_read_etc_localtime_content,
+	system_timezone_read_etc_localtime_hardlink,
+	NULL
+};
+
 static gboolean
 system_timezone_is_valid (const gchar *tz,
                           GHashTable *ical_zones)
@@ -523,7 +525,7 @@ system_timezone_find (void)
 	GHashTable *ical_zones;
 	icalarray *builtin_timezones;
 	gint ii;
-	gchar *tz;
+	gchar *tz, *config_tz = NULL;
 
 	/* return only timezones known to libical */
 	ical_zones = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
@@ -543,11 +545,74 @@ system_timezone_find (void)
 			g_hash_table_insert (ical_zones, g_strdup (location), GINT_TO_POINTER (1));
 	}
 
-	for (ii = 0; get_system_timezone_methods[ii] != NULL; ii++) {
-		tz = get_system_timezone_methods[ii] (ical_zones);
+	/* softlink is the best option, it points to the correct file */
+	tz = system_timezone_read_etc_localtime_softlink (ical_zones);
+	if (system_timezone_is_valid (tz, ical_zones)) {
+		g_hash_table_destroy (ical_zones);
+		return tz;
+	}
+
+	g_free (tz);
+
+	config_tz = NULL;
+
+	/* read correct timezone name from config file; checking
+	   on /etc/localtime content can pick wrong timezone name,
+	   even the file is same
+	 */
+	for (ii = 0; get_system_timezone_methods_config[ii] != NULL; ii++) {
+		config_tz = get_system_timezone_methods_config[ii] (ical_zones);
+
+		if (system_timezone_is_valid (config_tz, ical_zones)) {
+			break;
+		}
+
+		g_free (config_tz);
+		config_tz = NULL;
+	}
+
+	if (config_tz) {
+		struct stat stat_localtime;
+		gchar *localtime_content = NULL;
+		gsize localtime_content_len = -1;
+
+		if (g_stat (ETC_LOCALTIME, &stat_localtime) == 0 &&
+		    S_ISREG (stat_localtime.st_mode) &&
+		    g_file_get_contents (ETC_LOCALTIME,
+					 &localtime_content,
+					 &localtime_content_len,
+					 NULL)) {
+			struct stat stat_config_tz;
+			gchar *filename = g_build_filename (SYSTEM_ZONEINFODIR, config_tz, NULL);
+
+			if (filename &&
+			    g_stat (filename, &stat_config_tz) == 0 &&
+			    files_are_identical_content (&stat_localtime,
+				&stat_config_tz,
+				localtime_content,
+				localtime_content_len,
+				filename)) {
+				g_free (filename);
+				g_free (localtime_content);
+
+				/* corresponding file name to config_tz matches /etc/localtime,
+				   thus that's the correct one - return it as system timezone;
+				   bonus is that it might match configured system timezone name too
+				*/
+				return config_tz;
+			}
+			g_free (filename);
+		}
+
+		g_free (localtime_content);
+	}
+
+	for (ii = 0; get_system_timezone_methods_slow[ii] != NULL; ii++) {
+		tz = get_system_timezone_methods_slow[ii] (ical_zones);
 
 		if (system_timezone_is_valid (tz, ical_zones)) {
 			g_hash_table_destroy (ical_zones);
+			g_free (config_tz);
 			return tz;
 		}
 
@@ -556,7 +621,7 @@ system_timezone_find (void)
 
 	g_hash_table_destroy (ical_zones);
 
-	return NULL;
+	return config_tz;
 }
 
 #else /* G_OS_WIN32 */



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