diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:23:18 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-16 19:23:18 +0000 |
commit | 43a123c1ae6613b3efeed291fa552ecd909d3acf (patch) | |
tree | fd92518b7024bc74031f78a1cf9e454b65e73665 /src/time/zoneinfo_android.go | |
parent | Initial commit. (diff) | |
download | golang-1.20-upstream.tar.xz golang-1.20-upstream.zip |
Adding upstream version 1.20.14.upstream/1.20.14upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/time/zoneinfo_android.go')
-rw-r--r-- | src/time/zoneinfo_android.go | 87 |
1 files changed, 87 insertions, 0 deletions
diff --git a/src/time/zoneinfo_android.go b/src/time/zoneinfo_android.go new file mode 100644 index 0000000..e4f688d --- /dev/null +++ b/src/time/zoneinfo_android.go @@ -0,0 +1,87 @@ +// Copyright 2016 The Go Authors. All rights reserved. +// Use of this source code is governed by a BSD-style +// license that can be found in the LICENSE file. + +// Parse the "tzdata" packed timezone file used on Android. +// The format is lifted from ZoneInfoDB.java and ZoneInfo.java in +// java/libcore/util in the AOSP. + +package time + +import ( + "errors" + "syscall" +) + +var platformZoneSources = []string{ + "/system/usr/share/zoneinfo/tzdata", + "/data/misc/zoneinfo/current/tzdata", +} + +func initLocal() { + // TODO(elias.naur): getprop persist.sys.timezone + localLoc = *UTC +} + +func init() { + loadTzinfoFromTzdata = androidLoadTzinfoFromTzdata +} + +var allowGorootSource = true + +func gorootZoneSource(goroot string) (string, bool) { + if goroot == "" || !allowGorootSource { + return "", false + } + return goroot + "/lib/time/zoneinfo.zip", true +} + +func androidLoadTzinfoFromTzdata(file, name string) ([]byte, error) { + const ( + headersize = 12 + 3*4 + namesize = 40 + entrysize = namesize + 3*4 + ) + if len(name) > namesize { + return nil, errors.New(name + " is longer than the maximum zone name length (40 bytes)") + } + fd, err := open(file) + if err != nil { + return nil, err + } + defer closefd(fd) + + buf := make([]byte, headersize) + if err := preadn(fd, buf, 0); err != nil { + return nil, errors.New("corrupt tzdata file " + file) + } + d := dataIO{buf, false} + if magic := d.read(6); string(magic) != "tzdata" { + return nil, errors.New("corrupt tzdata file " + file) + } + d = dataIO{buf[12:], false} + indexOff, _ := d.big4() + dataOff, _ := d.big4() + indexSize := dataOff - indexOff + entrycount := indexSize / entrysize + buf = make([]byte, indexSize) + if err := preadn(fd, buf, int(indexOff)); err != nil { + return nil, errors.New("corrupt tzdata file " + file) + } + for i := 0; i < int(entrycount); i++ { + entry := buf[i*entrysize : (i+1)*entrysize] + // len(name) <= namesize is checked at function entry + if string(entry[:len(name)]) != name { + continue + } + d := dataIO{entry[namesize:], false} + off, _ := d.big4() + size, _ := d.big4() + buf := make([]byte, size) + if err := preadn(fd, buf, int(off+dataOff)); err != nil { + return nil, errors.New("corrupt tzdata file " + file) + } + return buf, nil + } + return nil, syscall.ENOENT +} |