chiark / gitweb /
glib: Update gtimezone.c patch as upstream wants
[termux-packages] / packages / glib / glib-gtimezone.c.patch
1 Patch submitted at https://bugzilla.gnome.org/show_bug.cgi?id=771304
2
3 diff -u -r ../glib-2.54.2/glib/gtimezone.c ./glib/gtimezone.c
4 --- ../glib-2.54.2/glib/gtimezone.c     2017-07-14 01:03:39.000000000 +0200
5 +++ ./glib/gtimezone.c  2017-12-09 02:03:46.797229494 +0100
6 @@ -43,6 +43,13 @@
7  #include <windows.h>
8  #endif
9  
10 +#ifdef __ANDROID__
11 +#include <arpa/inet.h>
12 +#include <fcntl.h>
13 +#include <sys/system_properties.h>
14 +#include <unistd.h>
15 +#endif
16 +
17  /**
18   * SECTION:timezone
19   * @title: GTimeZone
20 @@ -392,7 +399,105 @@
21    gtz->transitions = NULL;
22  }
23  
24 -#ifdef G_OS_UNIX
25 +#ifdef __ANDROID__
26 +/* Android does not have /etc/localtime but uses a system property for the
27 +   the current timezone. There are no files under /usr/share/zoneinfo,
28 +   instead a single /system/usr/share/zoneinfo/tzdata which are all zoneinfo
29 +   files compiled together with the following tool:
30 +   https://android.googlesource.com/platform/external/icu/+/master/tools/ZoneCompactor.java */
31 +static GBytes*
32 +zone_info_android (const gchar *identifier)
33 +{
34 +  struct tzdata_header
35 +  {
36 +    char     version[12];
37 +    uint32_t index_offset;
38 +    uint32_t data_offset;
39 +    uint32_t zonetab_offset;
40 +  } __attribute__((packed)) header;
41 +
42 +  struct tzdata_index_entry
43 +  {
44 +    char     name[40];
45 +    uint32_t offset;
46 +    uint32_t length;
47 +    uint32_t unused;
48 +  } __attribute__((packed)) entry;
49 +
50 +  char sys_timezone[PROP_VALUE_MAX];
51 +
52 +  if (identifier == NULL)
53 +    {
54 +      if (__system_property_get("persist.sys.timezone", sys_timezone) < 1)
55 +      {
56 +        g_warning("__system_property_get(\"persist.sys.timezone\") failed\n");
57 +        return NULL;
58 +      }
59 +      identifier = sys_timezone;
60 +    }
61 +
62 +  int tzdata_fd = open("/system/usr/share/zoneinfo/tzdata", O_RDONLY);
63 +  if (tzdata_fd < 0)
64 +  {
65 +    g_warning("Failed opening tzdata");
66 +    return NULL;
67 +  }
68 +
69 +  if (read(tzdata_fd, &header, sizeof(header)) < (ssize_t) sizeof(header))
70 +  {
71 +    g_warning("Failed reading tzdata header");
72 +    goto error;
73 +  }
74 +
75 +  header.index_offset = htonl(header.index_offset);
76 +  header.data_offset = htonl(header.data_offset);
77 +
78 +  uint32_t current_offset = header.index_offset;
79 +  while (current_offset < header.data_offset)
80 +    {
81 +      if (read(tzdata_fd, &entry, sizeof(entry)) < (ssize_t) sizeof(entry))
82 +      {
83 +        g_warning("Failed reading tzdata index entry");
84 +        goto error;
85 +      }
86 +
87 +      if (strcmp(entry.name, identifier) == 0)
88 +        {
89 +          entry.offset = htonl(entry.offset);
90 +          entry.length = htonl(entry.length);
91 +          if (entry.length == 0)
92 +            {
93 +              g_warning("Invalid tzdata entry with length zero");
94 +              goto error;
95 +            }
96 +
97 +          if (lseek(tzdata_fd, header.data_offset + entry.offset, SEEK_SET) == -1)
98 +            {
99 +              g_warning("Failed seeking to tzdata entry");
100 +              goto error;
101 +            }
102 +
103 +          guint8* data = g_malloc(entry.length);
104 +          if (read(tzdata_fd, data, entry.length) < entry.length)
105 +            {
106 +              g_warning("Failed reading tzdata entry");
107 +              g_free(data);
108 +              goto error;
109 +            }
110 +
111 +          close(tzdata_fd);
112 +          return g_bytes_new_take(data, entry.length);
113 +        }
114 +    }
115 +
116 +error:
117 +  close(tzdata_fd);
118 +
119 +  return NULL;
120 +}
121 +
122 +#elif defined(G_OS_UNIX)
123 +
124  static GBytes*
125  zone_info_unix (const gchar *identifier)
126  {
127 @@ -436,6 +541,10 @@
128    return zoneinfo;
129  }
130  
131 +#endif
132 +
133 +#ifdef G_OS_UNIX
134 +
135  static void
136  init_zone_from_iana_info (GTimeZone *gtz, GBytes *zoneinfo)
137  {
138 @@ -1387,7 +1496,11 @@
139    if (tz->t_info == NULL)
140      {
141  #ifdef G_OS_UNIX
142 +# ifdef __ANDROID__
143 +      GBytes *zoneinfo = zone_info_android (identifier);
144 +# else
145        GBytes *zoneinfo = zone_info_unix (identifier);
146 +# endif
147        if (!zoneinfo)
148          zone_for_constant_offset (tz, "UTC");
149        else