glib: Patch timezone handling for Android
authorFredrik Fornwall <fredrik@fornwall.net>
Mon, 12 Sep 2016 21:57:40 +0000 (17:57 -0400)
committerFredrik Fornwall <fredrik@fornwall.net>
Mon, 12 Sep 2016 21:57:40 +0000 (17:57 -0400)
packages/glib/build.sh
packages/glib/glib-gtimezone.c.patch [new file with mode: 0644]

index 234a96a..da9f32f 100755 (executable)
@@ -2,7 +2,7 @@ TERMUX_PKG_HOMEPAGE=https://developer.gnome.org/glib/
 TERMUX_PKG_DESCRIPTION="Library providing core building blocks for libraries and applications written in C"
 _TERMUX_GLIB_MAJOR_VERSION=2.48
 TERMUX_PKG_VERSION=${_TERMUX_GLIB_MAJOR_VERSION}.2
-TERMUX_PKG_BUILD_REVISION=1
+TERMUX_PKG_BUILD_REVISION=2
 TERMUX_PKG_SRCURL=http://ftp.gnome.org/pub/gnome/sources/glib/${_TERMUX_GLIB_MAJOR_VERSION}/glib-${TERMUX_PKG_VERSION}.tar.xz
 TERMUX_PKG_DEPENDS="libffi, pcre"
 TERMUX_PKG_RM_AFTER_INSTALL="share/gtk-doc share/locale share/glib-2.0/gettext share/gdb/auto-load share/glib-2.0/codegen share/glib-2.0/gdb bin/gtester-report bin/glib-mkenums bin/glib-gettextize bin/gdbus-codegen"
diff --git a/packages/glib/glib-gtimezone.c.patch b/packages/glib/glib-gtimezone.c.patch
new file mode 100644 (file)
index 0000000..886298d
--- /dev/null
@@ -0,0 +1,99 @@
+diff -u -r ../glib-2.48.2/glib/gtimezone.c ./glib/gtimezone.c
+--- ../glib-2.48.2/glib/gtimezone.c    2016-08-17 12:07:29.000000000 -0400
++++ ./glib/gtimezone.c 2016-09-12 16:52:41.864974630 -0400
+@@ -43,6 +43,11 @@
+ #include <windows.h>
+ #endif
++#ifdef __ANDROID__
++#include <fcntl.h>
++#include <sys/system_properties.h>
++#endif
++
+ /**
+  * SECTION:timezone
+  * @title: GTimeZone
+@@ -396,6 +400,75 @@
+ static GBytes*
+ zone_info_unix (const gchar *identifier)
+ {
++#ifdef __ANDROID__
++  /* Android does not have /etc/localtime but uses a system property for the
++     the current timezone. There are no files under /usr/share/zoneinfo,
++     instead a single /system/usr/share/zoneinfo/tzdata which are all zoneinfo
++     files compiled together with the following tool:
++     https://android.googlesource.com/platform/external/icu/+/master/tools/ZoneCompactor.java */
++  struct tzdata_header {
++    char version[12];
++    uint32_t index_offset, data_offset, zonetab_offset;
++  } __attribute__((packed)) header;
++
++  struct tzdata_index_entry {
++    char name[40];
++    uint32_t offset, length, unused;
++  } __attribute__((packed)) entry;
++
++  if (identifier == NULL) {
++    char sys_timezone[PROP_VALUE_MAX];
++    if (__system_property_get("persist.sys.timezone", sys_timezone) < 1) {
++      g_warning("__system_property_get(\"persist.sys.timezone\") failed\n");
++      return NULL;
++    }
++    identifier = sys_timezone;
++  }
++  if (identifier != NULL) {
++    int tzdata_fd = open("/system/usr/share/zoneinfo/tzdata", O_RDONLY);
++    if (tzdata_fd < 0) {
++      g_warning("Failed opening tzdata");
++      return NULL;
++    }
++    if (read(tzdata_fd, &header, sizeof(header)) < (ssize_t) sizeof(header)) {
++      g_warning("Failed reading tzdata header");
++      goto error;
++    }
++    header.index_offset = htonl(header.index_offset);
++    header.data_offset = htonl(header.data_offset);
++
++    uint32_t current_offset = header.index_offset;
++    while (current_offset < header.data_offset) {
++      if (read(tzdata_fd, &entry, sizeof(entry)) < (ssize_t) sizeof(entry)) {
++        g_warning("Failed reading tzdata index entry");
++        goto error;
++      }
++      if (strcmp(entry.name, identifier) == 0) {
++        entry.offset = htonl(entry.offset);
++        entry.length = htonl(entry.length);
++        if (entry.length == 0) {
++          g_warning("Invalid tzdata entry with length zero");
++          goto error;
++        }
++        if (lseek(tzdata_fd, header.data_offset + entry.offset, SEEK_SET) == -1) {
++          g_warning("Failed seeking to tzdata entry");
++          goto error;
++        }
++        guint8* data = g_malloc(entry.length);
++        if (read(tzdata_fd, data, entry.length) < entry.length) {
++          g_warning("Failed reading tzdata entry");
++          g_free(data);
++          goto error;
++        }
++        close(tzdata_fd);
++        return g_bytes_new_take(data, entry.length);
++      }
++    }
++error:
++    close(tzdata_fd);
++  }
++  return NULL;
++#else
+   gchar *filename;
+   GMappedFile *file = NULL;
+   GBytes *zoneinfo = NULL;
+@@ -434,6 +497,7 @@
+     }
+   g_free (filename);
+   return zoneinfo;
++#endif
+ }
+ static void