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.
17 var zoneSources
= []string{
18 "/system/usr/share/zoneinfo/tzdata",
19 "/data/misc/zoneinfo/current/tzdata",
20 runtime
.GOROOT() + "/lib/time/zoneinfo.zip",
24 // TODO(elias.naur): getprop persist.sys.timezone
29 loadTzinfoFromTzdata
= androidLoadTzinfoFromTzdata
32 func androidLoadTzinfoFromTzdata(file
, name
string) ([]byte, error
) {
36 entrysize
= namesize
+ 3*4
38 if len(name
) > namesize
{
39 return nil, errors
.New(name
+ " is longer than the maximum zone name length (40 bytes)")
47 buf
:= make([]byte, headersize
)
48 if err
:= preadn(fd
, buf
, 0); err
!= nil {
49 return nil, errors
.New("corrupt tzdata file " + file
)
51 d
:= dataIO
{buf
, false}
52 if magic
:= d
.read(6); string(magic
) != "tzdata" {
53 return nil, errors
.New("corrupt tzdata file " + file
)
55 d
= dataIO
{buf
[12:], false}
56 indexOff
, _
:= d
.big4()
57 dataOff
, _
:= d
.big4()
58 indexSize
:= dataOff
- indexOff
59 entrycount
:= indexSize
/ entrysize
60 buf
= make([]byte, indexSize
)
61 if err
:= preadn(fd
, buf
, int(indexOff
)); err
!= nil {
62 return nil, errors
.New("corrupt tzdata file " + file
)
64 for i
:= 0; i
< int(entrycount
); i
++ {
65 entry
:= buf
[i
*entrysize
: (i
+1)*entrysize
]
66 // len(name) <= namesize is checked at function entry
67 if string(entry
[:len(name
)]) != name
{
70 d
:= dataIO
{entry
[namesize
:], false}
73 buf
:= make([]byte, size
)
74 if err
:= preadn(fd
, buf
, int(off
+dataOff
)); err
!= nil {
75 return nil, errors
.New("corrupt tzdata file " + file
)
79 return nil, syscall
.ENOENT