Commit | Line | Data |
---|---|---|
69fd9a5c FF |
1 | Patch submitted at https://bugzilla.gnome.org/show_bug.cgi?id=771304 |
2 | ||
dcaafa88 FF |
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 | |
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 |