[glib/glib-2-66: 1/6] gtimezone: Split out fallback timezone identification for unix




commit 7124b91e218ba2b8d067aa72d852f342254e1750
Author: António Fernandes <antoniof gnome org>
Date:   Wed Sep 23 18:13:47 2020 +0100

    gtimezone: Split out fallback timezone identification for unix
    
    When the TZ environment variable is not set, we get the local timezone
    identifier by reading specific files.
    
    We are going to need these identifiers earlier, so split this logic into
    its own function, in preparation for the next commit.
    
    Based on idea proposed by Sebastian Keller <skeller gnome org>.

 glib/gtimezone.c | 127 ++++++++++++++++++++++++++++++++-----------------------
 1 file changed, 73 insertions(+), 54 deletions(-)
---
diff --git a/glib/gtimezone.c b/glib/gtimezone.c
index ef67ec50b..d90a9bb73 100644
--- a/glib/gtimezone.c
+++ b/glib/gtimezone.c
@@ -438,11 +438,80 @@ zone_for_constant_offset (GTimeZone *gtz, const gchar *name)
 }
 
 #ifdef G_OS_UNIX
+static gchar *
+zone_identifier_unix (void)
+{
+  gchar *resolved_identifier = NULL;
+  gsize prefix_len = 0;
+  gchar *canonical_path = NULL;
+  GError *read_link_err = NULL;
+  const gchar *tzdir;
+
+  /* Resolve the actual timezone pointed to by /etc/localtime. */
+  resolved_identifier = g_file_read_link ("/etc/localtime", &read_link_err);
+  if (resolved_identifier == NULL)
+    {
+      gboolean not_a_symlink = g_error_matches (read_link_err,
+                                                G_FILE_ERROR,
+                                                G_FILE_ERROR_INVAL);
+      g_clear_error (&read_link_err);
+
+      /* Fallback to the content of /var/db/zoneinfo or /etc/timezone
+       * if /etc/localtime is not a symlink. /var/db/zoneinfo is
+       * where 'tzsetup' program on FreeBSD and DragonflyBSD stores
+       * the timezone chosen by the user. /etc/timezone is where user
+       * choice is expressed on Gentoo OpenRC and others. */
+      if (not_a_symlink && (g_file_get_contents ("/var/db/zoneinfo",
+                                                 &resolved_identifier,
+                                                 NULL, NULL) ||
+                            g_file_get_contents ("/etc/timezone",
+                                                 &resolved_identifier,
+                                                 NULL, NULL)))
+        g_strchomp (resolved_identifier);
+      else
+        {
+          /* Error */
+          g_assert (resolved_identifier == NULL);
+          goto out;
+        }
+    }
+  else
+    {
+      /* Resolve relative path */
+      canonical_path = g_canonicalize_filename (resolved_identifier, "/etc");
+      g_free (resolved_identifier);
+      resolved_identifier = g_steal_pointer (&canonical_path);
+    }
+
+  tzdir = g_getenv ("TZDIR");
+  if (tzdir == NULL)
+    tzdir = "/usr/share/zoneinfo";
+
+  /* Strip the prefix and slashes if possible. */
+  if (g_str_has_prefix (resolved_identifier, tzdir))
+    {
+      prefix_len = strlen (tzdir);
+      while (*(resolved_identifier + prefix_len) == '/')
+        prefix_len++;
+    }
+
+  if (prefix_len > 0)
+    memmove (resolved_identifier, resolved_identifier + prefix_len,
+             strlen (resolved_identifier) - prefix_len + 1  /* nul terminator */);
+
+  g_assert (resolved_identifier != NULL);
+
+out:
+  g_free (canonical_path);
+
+  return resolved_identifier;
+}
+
 static GBytes*
 zone_info_unix (const gchar  *identifier,
                 gchar       **out_identifier)
 {
-  gchar *filename;
+  gchar *filename = NULL;
   GMappedFile *file = NULL;
   GBytes *zoneinfo = NULL;
   gchar *resolved_identifier = NULL;
@@ -470,61 +539,11 @@ zone_info_unix (const gchar  *identifier,
     }
   else
     {
-      gsize prefix_len = 0;
-      gchar *canonical_path = NULL;
-      GError *read_link_err = NULL;
-
-      filename = g_strdup ("/etc/localtime");
-
-      /* Resolve the actual timezone pointed to by /etc/localtime. */
-      resolved_identifier = g_file_read_link (filename, &read_link_err);
+      resolved_identifier = zone_identifier_unix ();
       if (resolved_identifier == NULL)
-        {
-          gboolean not_a_symlink = g_error_matches (read_link_err,
-                                                    G_FILE_ERROR,
-                                                    G_FILE_ERROR_INVAL);
-          g_clear_error (&read_link_err);
-
-          /* Fallback to the content of /var/db/zoneinfo or /etc/timezone
-           * if /etc/localtime is not a symlink. /var/db/zoneinfo is
-           * where 'tzsetup' program on FreeBSD and DragonflyBSD stores
-           * the timezone chosen by the user. /etc/timezone is where user
-           * choice is expressed on Gentoo OpenRC and others. */
-          if (not_a_symlink && (g_file_get_contents ("/var/db/zoneinfo",
-                                                     &resolved_identifier,
-                                                     NULL, NULL) ||
-                                g_file_get_contents ("/etc/timezone",
-                                                     &resolved_identifier,
-                                                     NULL, NULL)))
-            g_strchomp (resolved_identifier);
-          else
-            {
-              /* Error */
-              g_assert (resolved_identifier == NULL);
-              goto out;
-            }
-        }
-      else
-        {
-          /* Resolve relative path */
-          canonical_path = g_canonicalize_filename (resolved_identifier, "/etc");
-          g_free (resolved_identifier);
-          resolved_identifier = g_steal_pointer (&canonical_path);
-        }
+        goto out;
 
-      /* Strip the prefix and slashes if possible. */
-      if (g_str_has_prefix (resolved_identifier, tzdir))
-        {
-          prefix_len = strlen (tzdir);
-          while (*(resolved_identifier + prefix_len) == '/')
-            prefix_len++;
-        }
-
-      if (prefix_len > 0)
-        memmove (resolved_identifier, resolved_identifier + prefix_len,
-                 strlen (resolved_identifier) - prefix_len + 1  /* nul terminator */);
-
-      g_free (canonical_path);
+      filename = g_strdup ("/etc/localtime");
     }
 
   file = g_mapped_file_new (filename, FALSE, NULL);


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