glib: Update gtimezone.c patch after review
[termux-packages] / packages / glib / glib-gtimezone.c.patch
CommitLineData
69fd9a5c
FF
1Patch submitted at https://bugzilla.gnome.org/show_bug.cgi?id=771304
2
dcaafa88
FF
3diff -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
ada1b36f 6@@ -43,6 +43,14 @@
8aef3a59
FF
7 #include <windows.h>
8 #endif
9
10+#ifdef __ANDROID__
c780e809 11+#include <arpa/inet.h>
ada1b36f 12+#include <errno.h>
8aef3a59
FF
13+#include <fcntl.h>
14+#include <sys/system_properties.h>
c780e809 15+#include <unistd.h>
8aef3a59
FF
16+#endif
17+
18 /**
19 * SECTION:timezone
20 * @title: GTimeZone
6acf9d4a 21@@ -392,7 +399,117 @@
dcaafa88
FF
22 gtz->transitions = NULL;
23 }
24
25-#ifdef G_OS_UNIX
8aef3a59 26+#ifdef __ANDROID__
ada1b36f 27+/* Android uses a 'persist.sys.timezone' system property for the
6acf9d4a
FF
28+ * current timezone instead of a /etc/localtime file:
29+ * https://android.googlesource.com/platform/ndk/+/android-2.2_r1/docs/system/libc/OVERVIEW.TXT#67
30+ *
31+ * There are no files under /usr/share/zoneinfo - instead a single
32+ * /system/usr/share/zoneinfo/tzdata file is used which contains all
33+ * files compiled together with the following tool:
34+ * https://android.googlesource.com/platform/system/timezone/+/master/zone_compactor/main/java/ZoneCompactor.java
35+ */
36+static GBytes *
dcaafa88
FF
37+zone_info_android (const gchar *identifier)
38+{
39+ struct tzdata_header
40+ {
41+ char version[12];
42+ uint32_t index_offset;
43+ uint32_t data_offset;
44+ uint32_t zonetab_offset;
8aef3a59
FF
45+ } __attribute__((packed)) header;
46+
dcaafa88
FF
47+ struct tzdata_index_entry
48+ {
49+ char name[40];
50+ uint32_t offset;
51+ uint32_t length;
52+ uint32_t unused;
8aef3a59
FF
53+ } __attribute__((packed)) entry;
54+
69fd9a5c 55+ char sys_timezone[PROP_VALUE_MAX];
022cbc0f 56+ int tzdata_fd;
dcaafa88
FF
57+
58+ if (identifier == NULL)
59+ {
022cbc0f 60+ if (__system_property_get ("persist.sys.timezone", sys_timezone) < 1)
6acf9d4a
FF
61+ {
62+ g_warning ("__system_property_get(\"persist.sys.timezone\") failed");
63+ return NULL;
64+ }
dcaafa88 65+ identifier = sys_timezone;
8aef3a59 66+ }
dcaafa88 67+
6acf9d4a 68+ tzdata_fd = TEMP_FAILURE_RETRY (open ("/system/usr/share/zoneinfo/tzdata", O_RDONLY));
dcaafa88
FF
69+ if (tzdata_fd < 0)
70+ {
022cbc0f 71+ g_warning ("Failed opening tzdata");
dcaafa88 72+ return NULL;
8aef3a59 73+ }
8aef3a59 74+
6acf9d4a 75+ if (TEMP_FAILURE_RETRY (read (tzdata_fd, &header, sizeof(header)) < (ssize_t) sizeof (header)))
dcaafa88 76+ {
022cbc0f 77+ g_warning ("Failed reading tzdata header");
dcaafa88
FF
78+ goto error;
79+ }
80+
022cbc0f
FF
81+ header.index_offset = htonl (header.index_offset);
82+ header.data_offset = htonl (header.data_offset);
dcaafa88
FF
83+
84+ uint32_t current_offset = header.index_offset;
85+ while (current_offset < header.data_offset)
86+ {
6acf9d4a 87+ if (TEMP_FAILURE_RETRY (read (tzdata_fd, &entry, sizeof(entry)) < (ssize_t) sizeof (entry)))
dcaafa88 88+ {
022cbc0f 89+ g_warning ("Failed reading tzdata index entry");
8aef3a59
FF
90+ goto error;
91+ }
dcaafa88 92+
022cbc0f 93+ if (strcmp (entry.name, identifier) == 0)
dcaafa88 94+ {
022cbc0f
FF
95+ entry.offset = htonl (entry.offset);
96+ entry.length = htonl (entry.length);
dcaafa88
FF
97+ if (entry.length == 0)
98+ {
022cbc0f 99+ g_warning ("Invalid tzdata entry with length zero");
dcaafa88
FF
100+ goto error;
101+ }
102+
6acf9d4a 103+ if (TEMP_FAILURE_RETRY (lseek (tzdata_fd, header.data_offset + entry.offset, SEEK_SET) == -1))
dcaafa88 104+ {
022cbc0f 105+ g_warning ("Failed seeking to tzdata entry");
dcaafa88
FF
106+ goto error;
107+ }
108+
ada1b36f
FF
109+ /* Use a reasonable but arbitrary max length of an entry. */
110+ if (entry.length > 65536)
111+ {
112+ g_warning ("Too large tzdata entry length");
113+ goto error;
114+ }
115+
022cbc0f 116+ guint8* data = g_malloc (entry.length);
6acf9d4a 117+ if (TEMP_FAILURE_RETRY (read (tzdata_fd, data, entry.length) < entry.length))
dcaafa88 118+ {
022cbc0f
FF
119+ g_warning ("Failed reading tzdata entry");
120+ g_free (data);
dcaafa88
FF
121+ goto error;
122+ }
123+
022cbc0f
FF
124+ close (tzdata_fd);
125+ return g_bytes_new_take (data, entry.length);
8aef3a59 126+ }
8aef3a59 127+ }
dcaafa88 128+
8aef3a59 129+error:
022cbc0f 130+ close (tzdata_fd);
dcaafa88 131+
8aef3a59 132+ return NULL;
dcaafa88
FF
133+}
134+
135+#elif defined(G_OS_UNIX)
136+
137 static GBytes*
138 zone_info_unix (const gchar *identifier)
139 {
140@@ -436,6 +541,10 @@
8aef3a59 141 return zoneinfo;
8aef3a59
FF
142 }
143
dcaafa88
FF
144+#endif
145+
146+#ifdef G_OS_UNIX
147+
8aef3a59 148 static void
dcaafa88
FF
149 init_zone_from_iana_info (GTimeZone *gtz, GBytes *zoneinfo)
150 {
151@@ -1387,7 +1496,11 @@
152 if (tz->t_info == NULL)
153 {
154 #ifdef G_OS_UNIX
155+# ifdef __ANDROID__
156+ GBytes *zoneinfo = zone_info_android (identifier);
157+# else
158 GBytes *zoneinfo = zone_info_unix (identifier);
159+# endif
160 if (!zoneinfo)
161 zone_for_constant_offset (tz, "UTC");
162 else