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