Commit | Line | Data |
---|---|---|
8aef3a59 FF |
1 | diff -u -r ../glib-2.48.2/glib/gtimezone.c ./glib/gtimezone.c |
2 | --- ../glib-2.48.2/glib/gtimezone.c 2016-08-17 12:07:29.000000000 -0400 | |
3 | +++ ./glib/gtimezone.c 2016-09-12 16:52:41.864974630 -0400 | |
4 | @@ -43,6 +43,11 @@ | |
5 | #include <windows.h> | |
6 | #endif | |
7 | ||
8 | +#ifdef __ANDROID__ | |
9 | +#include <fcntl.h> | |
10 | +#include <sys/system_properties.h> | |
11 | +#endif | |
12 | + | |
13 | /** | |
14 | * SECTION:timezone | |
15 | * @title: GTimeZone | |
16 | @@ -396,6 +400,75 @@ | |
17 | static GBytes* | |
18 | zone_info_unix (const gchar *identifier) | |
19 | { | |
20 | +#ifdef __ANDROID__ | |
21 | + /* Android does not have /etc/localtime but uses a system property for the | |
22 | + the current timezone. There are no files under /usr/share/zoneinfo, | |
23 | + instead a single /system/usr/share/zoneinfo/tzdata which are all zoneinfo | |
24 | + files compiled together with the following tool: | |
25 | + https://android.googlesource.com/platform/external/icu/+/master/tools/ZoneCompactor.java */ | |
26 | + struct tzdata_header { | |
27 | + char version[12]; | |
28 | + uint32_t index_offset, data_offset, zonetab_offset; | |
29 | + } __attribute__((packed)) header; | |
30 | + | |
31 | + struct tzdata_index_entry { | |
32 | + char name[40]; | |
33 | + uint32_t offset, length, unused; | |
34 | + } __attribute__((packed)) entry; | |
35 | + | |
36 | + if (identifier == NULL) { | |
37 | + char sys_timezone[PROP_VALUE_MAX]; | |
38 | + if (__system_property_get("persist.sys.timezone", sys_timezone) < 1) { | |
39 | + g_warning("__system_property_get(\"persist.sys.timezone\") failed\n"); | |
40 | + return NULL; | |
41 | + } | |
42 | + identifier = sys_timezone; | |
43 | + } | |
44 | + if (identifier != NULL) { | |
45 | + int tzdata_fd = open("/system/usr/share/zoneinfo/tzdata", O_RDONLY); | |
46 | + if (tzdata_fd < 0) { | |
47 | + g_warning("Failed opening tzdata"); | |
48 | + return NULL; | |
49 | + } | |
50 | + if (read(tzdata_fd, &header, sizeof(header)) < (ssize_t) sizeof(header)) { | |
51 | + g_warning("Failed reading tzdata header"); | |
52 | + goto error; | |
53 | + } | |
54 | + header.index_offset = htonl(header.index_offset); | |
55 | + header.data_offset = htonl(header.data_offset); | |
56 | + | |
57 | + uint32_t current_offset = header.index_offset; | |
58 | + while (current_offset < header.data_offset) { | |
59 | + if (read(tzdata_fd, &entry, sizeof(entry)) < (ssize_t) sizeof(entry)) { | |
60 | + g_warning("Failed reading tzdata index entry"); | |
61 | + goto error; | |
62 | + } | |
63 | + if (strcmp(entry.name, identifier) == 0) { | |
64 | + entry.offset = htonl(entry.offset); | |
65 | + entry.length = htonl(entry.length); | |
66 | + if (entry.length == 0) { | |
67 | + g_warning("Invalid tzdata entry with length zero"); | |
68 | + goto error; | |
69 | + } | |
70 | + if (lseek(tzdata_fd, header.data_offset + entry.offset, SEEK_SET) == -1) { | |
71 | + g_warning("Failed seeking to tzdata entry"); | |
72 | + goto error; | |
73 | + } | |
74 | + guint8* data = g_malloc(entry.length); | |
75 | + if (read(tzdata_fd, data, entry.length) < entry.length) { | |
76 | + g_warning("Failed reading tzdata entry"); | |
77 | + g_free(data); | |
78 | + goto error; | |
79 | + } | |
80 | + close(tzdata_fd); | |
81 | + return g_bytes_new_take(data, entry.length); | |
82 | + } | |
83 | + } | |
84 | +error: | |
85 | + close(tzdata_fd); | |
86 | + } | |
87 | + return NULL; | |
88 | +#else | |
89 | gchar *filename; | |
90 | GMappedFile *file = NULL; | |
91 | GBytes *zoneinfo = NULL; | |
92 | @@ -434,6 +497,7 @@ | |
93 | } | |
94 | g_free (filename); | |
95 | return zoneinfo; | |
96 | +#endif | |
97 | } | |
98 | ||
99 | static void |