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