summaryrefslogtreecommitdiffstats
path: root/libc/tzcode
diff options
context:
space:
mode:
authorElliott Hughes <enh@google.com>2012-10-18 10:59:27 -0700
committerAndroid Git Automerger <android-git-automerger@android.com>2012-10-18 10:59:27 -0700
commit1b315363c22fdf53d77fc83ec0bbada32e73ccc7 (patch)
tree1b9cca13108d197c7cd87c7bca0d7c481ad512a0 /libc/tzcode
parente5c8ced4f95e97b2fadc0c64fbdbeeb023677035 (diff)
parent5ae762a393168932602eb7269a7d30a53de1c83c (diff)
downloadbionic-1b315363c22fdf53d77fc83ec0bbada32e73ccc7.zip
bionic-1b315363c22fdf53d77fc83ec0bbada32e73ccc7.tar.gz
bionic-1b315363c22fdf53d77fc83ec0bbada32e73ccc7.tar.bz2
am 5ae762a3: Merge "Pull bionic\'s time zone data from the new single \'tzdata\' file."
* commit '5ae762a393168932602eb7269a7d30a53de1c83c': Pull bionic's time zone data from the new single 'tzdata' file.
Diffstat (limited to 'libc/tzcode')
-rw-r--r--libc/tzcode/localtime.c124
1 files changed, 85 insertions, 39 deletions
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index e442a03..c329e32 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -37,8 +37,7 @@ static char elsieid[] = "@(#)localtime.c 8.3";
#define TZ_ABBR_ERR_CHAR '_'
#endif /* !defined TZ_ABBR_ERR_CHAR */
-#define INDEXFILE "/system/usr/share/zoneinfo/zoneinfo.idx"
-#define DATAFILE "/system/usr/share/zoneinfo/zoneinfo.dat"
+#define TZDATA_PATH "/system/usr/share/zoneinfo/tzdata"
#define NAMELEN 40
#define INTLEN 4
#define READLEN (NAMELEN + 3 * INTLEN)
@@ -205,6 +204,7 @@ struct rule {
/* NOTE: all internal functions assume that _tzLock() was already called */
+static int __bionic_open_tzdata(const char*, int*);
static long detzcode P((const char * codep));
static time_t detzcode64 P((const char * codep));
static int differ_by_repeat P((time_t t1, time_t t0));
@@ -470,44 +470,8 @@ register const int doextend;
return -1;
}
if ((fid = open(name, OPEN_MODE)) == -1) {
- char buf[READLEN];
- char name[NAMELEN + 1];
- int fidix = open(INDEXFILE, OPEN_MODE);
- int off = -1;
-
- XLOG(( "tzload: could not open '%s', trying '%s'\n", fullname, INDEXFILE ));
- if (fidix < 0) {
- XLOG(( "tzload: could not find '%s'\n", INDEXFILE ));
- return -1;
- }
-
- while (read(fidix, buf, sizeof(buf)) == sizeof(buf)) {
- memcpy(name, buf, NAMELEN);
- name[NAMELEN] = '\0';
-
- if (strcmp(name, origname) == 0) {
- off = toint((unsigned char *) buf + NAMELEN);
- toread = toint((unsigned char *) buf + NAMELEN + INTLEN);
- break;
- }
- }
-
- close(fidix);
-
- if (off < 0) {
- XLOG(( "tzload: invalid offset (%d)\n", off ));
- return -1;
- }
-
- fid = open(DATAFILE, OPEN_MODE);
-
+ fid = __bionic_open_tzdata(origname, &toread);
if (fid < 0) {
- XLOG(( "tzload: could not open '%s'\n", DATAFILE ));
- return -1;
- }
-
- if (lseek(fid, off, SEEK_SET) < 0) {
- XLOG(( "tzload: could not seek to %d in '%s'\n", off, DATAFILE ));
return -1;
}
}
@@ -2228,3 +2192,85 @@ time_t t;
}
#endif /* defined STD_INSPIRED */
+
+#include <stdint.h>
+#include <sys/endian.h>
+
+static int __bionic_open_tzdata(const char* olson_id, int* data_size) {
+ int fd = TEMP_FAILURE_RETRY(open(TZDATA_PATH, OPEN_MODE));
+ if (fd == -1) {
+ fprintf(stderr, "__bionic_open_tzdata: could not open \"%s\": %s\n", TZDATA_PATH, strerror(errno));
+ return -1;
+ }
+
+ // byte[12] tzdata_version -- "tzdata2012f\0"
+ // int file_format_version -- 1
+ // int index_offset
+ // int data_offset
+ // int zonetab_offset
+ struct bionic_tzdata_header {
+ char tzdata_version[12];
+ int32_t file_format_version;
+ int32_t index_offset;
+ int32_t data_offset;
+ int32_t zonetab_offset;
+ } header;
+ if (TEMP_FAILURE_RETRY(read(fd, &header, sizeof(header))) != sizeof(header)) {
+ fprintf(stderr, "__bionic_open_tzdata: could not read header: %s\n", strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ if (strncmp(header.tzdata_version, "tzdata", 6) != 0 || header.tzdata_version[11] != 0) {
+ fprintf(stderr, "__bionic_open_tzdata: bad magic: %s\n", header.tzdata_version);
+ close(fd);
+ return -1;
+ }
+ if (ntohl(header.file_format_version) != 1) {
+ fprintf(stderr, "__bionic_open_tzdata: bad file format version: %d\n", header.file_format_version);
+ close(fd);
+ return -1;
+ }
+
+#if 0
+ fprintf(stderr, "version: %s (%d)\n", header.tzdata_version, ntohl(header.file_format_version));
+ fprintf(stderr, "index_offset = %d\n", ntohl(header.index_offset));
+ fprintf(stderr, "data_offset = %d\n", ntohl(header.data_offset));
+ fprintf(stderr, "zonetab_offset = %d\n", ntohl(header.zonetab_offset));
+#endif
+
+ if (TEMP_FAILURE_RETRY(lseek(fd, ntohl(header.index_offset), SEEK_SET)) == -1) {
+ fprintf(stderr, "__bionic_open_tzdata: couldn't seek to index: %s\n", strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ off_t specific_zone_offset = -1;
+
+ unsigned char buf[READLEN];
+ while (read(fd, buf, sizeof(buf)) == sizeof(buf)) {
+ char this_id[NAMELEN + 1];
+ memcpy(this_id, buf, NAMELEN);
+ this_id[NAMELEN] = '\0';
+
+ if (strcmp(this_id, olson_id) == 0) {
+ specific_zone_offset = toint(buf + NAMELEN) + ntohl(header.data_offset);
+ *data_size = toint(buf + NAMELEN + INTLEN);
+ break;
+ }
+ }
+
+ if (specific_zone_offset == -1) {
+ XLOG(("__bionic_open_tzdata: couldn't find zone \"%s\"\n", olson_id));
+ close(fd);
+ return -1;
+ }
+
+ if (TEMP_FAILURE_RETRY(lseek(fd, specific_zone_offset, SEEK_SET)) == -1) {
+ fprintf(stderr, "__bionic_open_tzdata: could not seek to %ld: %s\n", specific_zone_offset, strerror(errno));
+ close(fd);
+ return -1;
+ }
+
+ return fd;
+}