Source file
src/time/zoneinfo_android.go
1
2
3
4
5
6
7
8
9 package time
10
11 import (
12 "errors"
13 "syscall"
14 )
15
16 var platformZoneSources = []string{
17 "/system/usr/share/zoneinfo/tzdata",
18 "/data/misc/zoneinfo/current/tzdata",
19 }
20
21 func initLocal() {
22
23 localLoc = *UTC
24 }
25
26 func init() {
27 loadTzinfoFromTzdata = androidLoadTzinfoFromTzdata
28 }
29
30 var allowGorootSource = true
31
32 func gorootZoneSource(goroot string) (string, bool) {
33 if goroot == "" || !allowGorootSource {
34 return "", false
35 }
36 return goroot + "/lib/time/zoneinfo.zip", true
37 }
38
39 func androidLoadTzinfoFromTzdata(file, name string) ([]byte, error) {
40 const (
41 headersize = 12 + 3*4
42 namesize = 40
43 entrysize = namesize + 3*4
44 )
45 if len(name) > namesize {
46 return nil, errors.New(name + " is longer than the maximum zone name length (40 bytes)")
47 }
48 fd, err := open(file)
49 if err != nil {
50 return nil, err
51 }
52 defer closefd(fd)
53
54 buf := make([]byte, headersize)
55 if err := preadn(fd, buf, 0); err != nil {
56 return nil, errors.New("corrupt tzdata file " + file)
57 }
58 d := dataIO{buf, false}
59 if magic := d.read(6); string(magic) != "tzdata" {
60 return nil, errors.New("corrupt tzdata file " + file)
61 }
62 d = dataIO{buf[12:], false}
63 indexOff, _ := d.big4()
64 dataOff, _ := d.big4()
65 indexSize := dataOff - indexOff
66 entrycount := indexSize / entrysize
67 buf = make([]byte, indexSize)
68 if err := preadn(fd, buf, int(indexOff)); err != nil {
69 return nil, errors.New("corrupt tzdata file " + file)
70 }
71 for i := 0; i < int(entrycount); i++ {
72 entry := buf[i*entrysize : (i+1)*entrysize]
73
74 if string(entry[:len(name)]) != name {
75 continue
76 }
77 d := dataIO{entry[namesize:], false}
78 off, _ := d.big4()
79 size, _ := d.big4()
80 buf := make([]byte, size)
81 if err := preadn(fd, buf, int(off+dataOff)); err != nil {
82 return nil, errors.New("corrupt tzdata file " + file)
83 }
84 return buf, nil
85 }
86 return nil, syscall.ENOENT
87 }
88
View as plain text