glib: Update from 2.56.0 to 2.56.1
[termux-packages] / packages / glib / glib-gtimezone.c.patch
CommitLineData
dcaafa88
FF
1diff -u -r ../glib-2.54.2/glib/gtimezone.c ./glib/gtimezone.c
2--- ../glib-2.54.2/glib/gtimezone.c 2017-07-14 01:03:39.000000000 +0200
507b3347 3+++ ./glib/gtimezone.c 2018-01-07 23:20:34.447775267 +0100
4601842b 4@@ -43,6 +43,10 @@
8aef3a59
FF
5 #include <windows.h>
6 #endif
7
8+#ifdef __ANDROID__
8aef3a59
FF
9+#include <sys/system_properties.h>
10+#endif
11+
12 /**
13 * SECTION:timezone
14 * @title: GTimeZone
507b3347 15@@ -392,7 +396,131 @@
dcaafa88
FF
16 gtz->transitions = NULL;
17 }
18
19-#ifdef G_OS_UNIX
8aef3a59 20+#ifdef __ANDROID__
ada1b36f 21+/* Android uses a 'persist.sys.timezone' system property for the
6acf9d4a
FF
22+ * current timezone instead of a /etc/localtime file:
23+ * https://android.googlesource.com/platform/ndk/+/android-2.2_r1/docs/system/libc/OVERVIEW.TXT#67
24+ *
25+ * There are no files under /usr/share/zoneinfo - instead a single
26+ * /system/usr/share/zoneinfo/tzdata file is used which contains all
27+ * files compiled together with the following tool:
28+ * https://android.googlesource.com/platform/system/timezone/+/master/zone_compactor/main/java/ZoneCompactor.java
29+ */
30+static GBytes *
dcaafa88
FF
31+zone_info_android (const gchar *identifier)
32+{
69fd9a5c 33+ char sys_timezone[PROP_VALUE_MAX];
4601842b
FF
34+ GMappedFile *file;
35+ gchar *tzdata;
36+ gsize tzdata_length;
37+ const gsize index_entry_size = 52;
38+ gint32 header_index_offset, header_data_offset;
39+ gint32 entry_count, current_index;
40+ char* entry_name;
41+ gint32 entry_offset, entry_length;
507b3347
FF
42+ guint32 entry_name_start, entry_name_end;
43+ guint32 zoneinfo_start, zoneinfo_end;
4601842b 44+ GBytes *zoneinfo;
507b3347 45+ GError *error = NULL;
dcaafa88
FF
46+
47+ if (identifier == NULL)
48+ {
022cbc0f 49+ if (__system_property_get ("persist.sys.timezone", sys_timezone) < 1)
6acf9d4a
FF
50+ {
51+ g_warning ("__system_property_get(\"persist.sys.timezone\") failed");
52+ return NULL;
53+ }
dcaafa88 54+ identifier = sys_timezone;
8aef3a59 55+ }
dcaafa88 56+
507b3347 57+ file = g_mapped_file_new ("/system/usr/share/zoneinfo/tzdata", FALSE, &error);
4601842b
FF
58+ if (file == NULL)
59+ {
507b3347
FF
60+ g_warning ("Failed mapping tzdata file: %s", error->message);
61+ g_error_free (error);
4601842b
FF
62+ return NULL;
63+ }
8aef3a59 64+
4601842b
FF
65+ tzdata = g_mapped_file_get_contents (file);
66+ tzdata_length = g_mapped_file_get_length (file);
67+ if (tzdata == NULL || tzdata_length < 24)
dcaafa88 68+ {
4601842b 69+ g_warning ("Too small tzdata file");
dcaafa88
FF
70+ goto error;
71+ }
72+
4601842b
FF
73+ header_index_offset = gint32_from_be (*((gint32_be*) (tzdata + 12)));
74+ header_data_offset = gint32_from_be (*((gint32_be*) (tzdata + 16)));
dcaafa88 75+
507b3347
FF
76+ if (header_index_offset < 0 || header_data_offset < 0 || header_data_offset < index_entry_size)
77+ {
78+ g_warning ("Invalid tzdata content");
79+ goto error;
80+ }
81+
4601842b
FF
82+ entry_count = (header_data_offset - header_index_offset) / index_entry_size;
83+ if (entry_count < 1)
dcaafa88 84+ {
507b3347 85+ g_warning ("No index entry found");
4601842b
FF
86+ goto error;
87+ }
dcaafa88 88+
4601842b
FF
89+ current_index = 0;
90+ while (current_index < entry_count)
91+ {
507b3347
FF
92+ if (!g_uint_checked_mul(&entry_name_start, current_index, index_entry_size) ||
93+ !g_uint_checked_add(&entry_name_start, entry_name_start, header_index_offset) ||
94+ !g_uint_checked_add(&entry_name_end, entry_name_start, 40))
95+ {
96+ g_warning ("Overflow when computing entry name offset");
97+ goto error;
98+ }
99+
100+ entry_name = tzdata + entry_name_start;
101+
4601842b
FF
102+ /* The name should be null terminated within the 40 chars. */
103+ if (memchr (entry_name, 0, 40) == NULL)
dcaafa88 104+ {
507b3347 105+ g_warning ("Invalid index entry");
4601842b
FF
106+ goto error;
107+ }
dcaafa88 108+
4601842b
FF
109+ if (strcmp (entry_name, identifier) == 0)
110+ {
111+ entry_offset = gint32_from_be (*(gint32_be*) (entry_name + 40));
112+ entry_length = gint32_from_be (*(gint32_be*) (entry_name + 44));
507b3347 113+ if (entry_length == 0 || entry_length > 65536)
dcaafa88 114+ {
507b3347
FF
115+ /* Use a reasonable but arbitrary max length of an entry. */
116+ g_warning ("Invalid zoneinfo entry length");
dcaafa88
FF
117+ goto error;
118+ }
507b3347
FF
119+
120+ if (!g_uint_checked_add(&zoneinfo_start, header_data_offset, entry_offset) ||
121+ !g_uint_checked_add(&zoneinfo_end, zoneinfo_start, entry_length) ||
122+ zoneinfo_end > tzdata_length)
ada1b36f 123+ {
507b3347 124+ g_warning ("Too large zoneinfo entry length");
ada1b36f
FF
125+ goto error;
126+ }
127+
507b3347 128+ zoneinfo = g_bytes_new_with_free_func (tzdata + zoneinfo_start,
4601842b
FF
129+ entry_length,
130+ (GDestroyNotify)g_mapped_file_unref,
131+ g_mapped_file_ref (file));
132+ g_mapped_file_unref (file);
133+ return zoneinfo;
8aef3a59 134+ }
4601842b 135+ current_index++;
8aef3a59 136+ }
dcaafa88 137+
8aef3a59 138+error:
4601842b 139+ g_mapped_file_unref (file);
8aef3a59 140+ return NULL;
dcaafa88
FF
141+}
142+
143+#elif defined(G_OS_UNIX)
144+
145 static GBytes*
146 zone_info_unix (const gchar *identifier)
147 {
507b3347 148@@ -436,6 +564,10 @@
8aef3a59 149 return zoneinfo;
8aef3a59
FF
150 }
151
dcaafa88
FF
152+#endif
153+
154+#ifdef G_OS_UNIX
155+
8aef3a59 156 static void
dcaafa88
FF
157 init_zone_from_iana_info (GTimeZone *gtz, GBytes *zoneinfo)
158 {
507b3347 159@@ -1387,7 +1519,11 @@
dcaafa88
FF
160 if (tz->t_info == NULL)
161 {
162 #ifdef G_OS_UNIX
163+# ifdef __ANDROID__
164+ GBytes *zoneinfo = zone_info_android (identifier);
165+# else
166 GBytes *zoneinfo = zone_info_unix (identifier);
167+# endif
168 if (!zoneinfo)
169 zone_for_constant_offset (tz, "UTC");
170 else