1 // Copyright 2016 The Go Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style
3 // license that can be found in the LICENSE file.
5 // Parse the "tzdata" packed timezone file used on Android.
6 // The format is lifted from ZoneInfoDB.java and ZoneInfo.java in
7 // java/libcore/util in the AOSP.
16 var zoneSources
= []string{
17 "/system/usr/share/zoneinfo/tzdata",
18 "/data/misc/zoneinfo/current/tzdata",
19 runtime
.GOROOT() + "/lib/time/zoneinfo.zip",
23 // TODO(elias.naur): getprop persist.sys.timezone
28 loadTzinfoFromTzdata
= androidLoadTzinfoFromTzdata
31 func androidLoadTzinfoFromTzdata(file
, name
string) ([]byte, error
) {
35 entrysize
= namesize
+ 3*4
37 if len(name
) > namesize
{
38 return nil, errors
.New(name
+ " is longer than the maximum zone name length (40 bytes)")
46 buf
:= make([]byte, headersize
)
47 if err
:= preadn(fd
, buf
, 0); err
!= nil {
48 return nil, errors
.New("corrupt tzdata file " + file
)
50 d
:= dataIO
{buf
, false}
51 if magic
:= d
.read(6); string(magic
) != "tzdata" {
52 return nil, errors
.New("corrupt tzdata file " + file
)
54 d
= dataIO
{buf
[12:], false}
55 indexOff
, _
:= d
.big4()
56 dataOff
, _
:= d
.big4()
57 indexSize
:= dataOff
- indexOff
58 entrycount
:= indexSize
/ entrysize
59 buf
= make([]byte, indexSize
)
60 if err
:= preadn(fd
, buf
, int(indexOff
)); err
!= nil {
61 return nil, errors
.New("corrupt tzdata file " + file
)
63 for i
:= 0; i
< int(entrycount
); i
++ {
64 entry
:= buf
[i
*entrysize
: (i
+1)*entrysize
]
65 // len(name) <= namesize is checked at function entry
66 if string(entry
[:len(name
)]) != name
{
69 d
:= dataIO
{entry
[namesize
:], false}
72 buf
:= make([]byte, size
)
73 if err
:= preadn(fd
, buf
, int(off
+dataOff
)); err
!= nil {
74 return nil, errors
.New("corrupt tzdata file " + file
)
78 return nil, errors
.New("cannot find " + name
+ " in tzdata file " + file
)