glib: Update gtimezone.c patch after review
[termux-packages] / packages / glib / glib-gtimezone.c.patch
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 2017-12-21 23:47:57.704190589 +0100
4 @@ -43,6 +43,10 @@
5 #include <windows.h>
6 #endif
7
8 +#ifdef __ANDROID__
9 +#include <sys/system_properties.h>
10 +#endif
11 +
12 /**
13 * SECTION:timezone
14 * @title: GTimeZone
15 @@ -392,7 +396,109 @@
16 gtz->transitions = NULL;
17 }
18
19 -#ifdef G_OS_UNIX
20 +#ifdef __ANDROID__
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
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 *
31 +zone_info_android (const gchar *identifier)
32 +{
33 + char sys_timezone[PROP_VALUE_MAX];
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;
42 + GBytes *zoneinfo;
43 +
44 + if (identifier == NULL)
45 + {
46 + if (__system_property_get ("persist.sys.timezone", sys_timezone) < 1)
47 + {
48 + g_warning ("__system_property_get(\"persist.sys.timezone\") failed");
49 + return NULL;
50 + }
51 + identifier = sys_timezone;
52 + }
53 +
54 + file = g_mapped_file_new ("/system/usr/share/zoneinfo/tzdata", FALSE, NULL);
55 + if (file == NULL)
56 + {
57 + g_warning ("Failed mapping tzdata file");
58 + return NULL;
59 + }
60 +
61 + tzdata = g_mapped_file_get_contents (file);
62 + tzdata_length = g_mapped_file_get_length (file);
63 + if (tzdata == NULL || tzdata_length < 24)
64 + {
65 + g_warning ("Too small tzdata file");
66 + goto error;
67 + }
68 +
69 + header_index_offset = gint32_from_be (*((gint32_be*) (tzdata + 12)));
70 + header_data_offset = gint32_from_be (*((gint32_be*) (tzdata + 16)));
71 +
72 + entry_count = (header_data_offset - header_index_offset) / index_entry_size;
73 + if (entry_count < 1)
74 + {
75 + g_warning("No index entry found");
76 + goto error;
77 + }
78 +
79 + current_index = 0;
80 + while (current_index < entry_count)
81 + {
82 + entry_name = tzdata + header_index_offset + current_index * index_entry_size;
83 + /* The name should be null terminated within the 40 chars. */
84 + if (memchr (entry_name, 0, 40) == NULL)
85 + {
86 + g_warning("Invalid index entry");
87 + goto error;
88 + }
89 +
90 + if (strcmp (entry_name, identifier) == 0)
91 + {
92 + entry_offset = gint32_from_be (*(gint32_be*) (entry_name + 40));
93 + entry_length = gint32_from_be (*(gint32_be*) (entry_name + 44));
94 + if (entry_length == 0)
95 + {
96 + g_warning ("Invalid tzdata entry with length zero");
97 + goto error;
98 + }
99 + else if (entry_length > 65536 || header_data_offset + entry_offset + entry_length > tzdata_length)
100 + {
101 + /* Use a reasonable but arbitrary max length of an entry. */
102 + g_warning ("Too large tzdata entry length");
103 + goto error;
104 + }
105 +
106 + zoneinfo = g_bytes_new_with_free_func (tzdata + header_data_offset + entry_offset,
107 + entry_length,
108 + (GDestroyNotify)g_mapped_file_unref,
109 + g_mapped_file_ref (file));
110 + g_mapped_file_unref (file);
111 + return zoneinfo;
112 + }
113 + current_index++;
114 + }
115 +
116 +error:
117 + g_mapped_file_unref (file);
118 + return NULL;
119 +}
120 +
121 +#elif defined(G_OS_UNIX)
122 +
123 static GBytes*
124 zone_info_unix (const gchar *identifier)
125 {
126 @@ -436,6 +542,10 @@
127 return zoneinfo;
128 }
129
130 +#endif
131 +
132 +#ifdef G_OS_UNIX
133 +
134 static void
135 init_zone_from_iana_info (GTimeZone *gtz, GBytes *zoneinfo)
136 {
137 @@ -1387,7 +1497,11 @@
138 if (tz->t_info == NULL)
139 {
140 #ifdef G_OS_UNIX
141 +# ifdef __ANDROID__
142 + GBytes *zoneinfo = zone_info_android (identifier);
143 +# else
144 GBytes *zoneinfo = zone_info_unix (identifier);
145 +# endif
146 if (!zoneinfo)
147 zone_for_constant_offset (tz, "UTC");
148 else