1 diff -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
3 +++ ./glib/gtimezone.c 2018-01-07 23:20:34.447775267 +0100
9 +#include <sys/system_properties.h>
16 gtz->transitions = NULL;
21 +/* Android uses a 'persist.sys.timezone' system property for the
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
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
31 +zone_info_android (const gchar *identifier)
33 + char sys_timezone[PROP_VALUE_MAX];
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;
41 + gint32 entry_offset, entry_length;
42 + guint32 entry_name_start, entry_name_end;
43 + guint32 zoneinfo_start, zoneinfo_end;
45 + GError *error = NULL;
47 + if (identifier == NULL)
49 + if (__system_property_get ("persist.sys.timezone", sys_timezone) < 1)
51 + g_warning ("__system_property_get(\"persist.sys.timezone\") failed");
54 + identifier = sys_timezone;
57 + file = g_mapped_file_new ("/system/usr/share/zoneinfo/tzdata", FALSE, &error);
60 + g_warning ("Failed mapping tzdata file: %s", error->message);
61 + g_error_free (error);
65 + tzdata = g_mapped_file_get_contents (file);
66 + tzdata_length = g_mapped_file_get_length (file);
67 + if (tzdata == NULL || tzdata_length < 24)
69 + g_warning ("Too small tzdata file");
73 + header_index_offset = gint32_from_be (*((gint32_be*) (tzdata + 12)));
74 + header_data_offset = gint32_from_be (*((gint32_be*) (tzdata + 16)));
76 + if (header_index_offset < 0 || header_data_offset < 0 || header_data_offset < index_entry_size)
78 + g_warning ("Invalid tzdata content");
82 + entry_count = (header_data_offset - header_index_offset) / index_entry_size;
83 + if (entry_count < 1)
85 + g_warning ("No index entry found");
90 + while (current_index < entry_count)
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))
96 + g_warning ("Overflow when computing entry name offset");
100 + entry_name = tzdata + entry_name_start;
102 + /* The name should be null terminated within the 40 chars. */
103 + if (memchr (entry_name, 0, 40) == NULL)
105 + g_warning ("Invalid index entry");
109 + if (strcmp (entry_name, identifier) == 0)
111 + entry_offset = gint32_from_be (*(gint32_be*) (entry_name + 40));
112 + entry_length = gint32_from_be (*(gint32_be*) (entry_name + 44));
113 + if (entry_length == 0 || entry_length > 65536)
115 + /* Use a reasonable but arbitrary max length of an entry. */
116 + g_warning ("Invalid zoneinfo entry length");
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)
124 + g_warning ("Too large zoneinfo entry length");
128 + zoneinfo = g_bytes_new_with_free_func (tzdata + zoneinfo_start,
130 + (GDestroyNotify)g_mapped_file_unref,
131 + g_mapped_file_ref (file));
132 + g_mapped_file_unref (file);
139 + g_mapped_file_unref (file);
143 +#elif defined(G_OS_UNIX)
146 zone_info_unix (const gchar *identifier)
157 init_zone_from_iana_info (GTimeZone *gtz, GBytes *zoneinfo)
159 @@ -1387,7 +1519,11 @@
160 if (tz->t_info == NULL)
164 + GBytes *zoneinfo = zone_info_android (identifier);
166 GBytes *zoneinfo = zone_info_unix (identifier);
169 zone_for_constant_offset (tz, "UTC");