aboutsummaryrefslogtreecommitdiff
path: root/libgo/go/time/zoneinfo_read.go
diff options
context:
space:
mode:
Diffstat (limited to 'libgo/go/time/zoneinfo_read.go')
-rw-r--r--libgo/go/time/zoneinfo_read.go40
1 files changed, 39 insertions, 1 deletions
diff --git a/libgo/go/time/zoneinfo_read.go b/libgo/go/time/zoneinfo_read.go
index 1e559a6..c242972 100644
--- a/libgo/go/time/zoneinfo_read.go
+++ b/libgo/go/time/zoneinfo_read.go
@@ -13,8 +13,22 @@ import (
"errors"
"runtime"
"syscall"
+ _ "unsafe" // for go:linkname
)
+// registerLoadFromEmbeddedTZData is called by the time/tzdata package,
+// if it is imported.
+//go:linkname registerLoadFromEmbeddedTZData
+func registerLoadFromEmbeddedTZData(f func(string) (string, error)) {
+ loadFromEmbeddedTZData = f
+}
+
+// loadFromEmbeddedTZData is used to load a specific tzdata file
+// from tzdata information embedded in the binary itself.
+// This is set when the time/tzdata package is imported,
+// via registerLoadFromEmbeddedTzdata.
+var loadFromEmbeddedTZData func(zipname string) (string, error)
+
// maxFileSize is the max permitted size of files read by readFile.
// As reference, the zoneinfo.zip distributed by Go is ~350 KB,
// so 10MB is overkill.
@@ -78,6 +92,13 @@ func (d *dataIO) byte() (n byte, ok bool) {
return p[0], true
}
+// read returns the read of the data in the buffer.
+func (d *dataIO) rest() []byte {
+ r := d.p
+ d.p = nil
+ return r
+}
+
// Make a string by stopping at the first NUL
func byteString(p []byte) string {
for i := 0; i < len(p); i++ {
@@ -213,6 +234,12 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
return nil, badData
}
+ var extend string
+ rest := d.rest()
+ if len(rest) > 2 && rest[0] == '\n' && rest[len(rest)-1] == '\n' {
+ extend = string(rest[1 : len(rest)-1])
+ }
+
// Now we can build up a useful data structure.
// First the zone information.
// utcoff[4] isdst[1] nameindex[1]
@@ -289,7 +316,7 @@ func LoadLocationFromTZData(name string, data []byte) (*Location, error) {
}
// Committed to succeed.
- l := &Location{zone: zone, tx: tx, name: name}
+ l := &Location{zone: zone, tx: tx, name: name, extend: extend}
// Fill in the cache with information about right now,
// since that will be the most common lookup.
@@ -486,6 +513,17 @@ func loadLocation(name string, sources []string) (z *Location, firstErr error) {
firstErr = err
}
}
+ if loadFromEmbeddedTZData != nil {
+ zonedata, err := loadFromEmbeddedTZData(name)
+ if err == nil {
+ if z, err = LoadLocationFromTZData(name, []byte(zonedata)); err == nil {
+ return z, nil
+ }
+ }
+ if firstErr == nil && err != syscall.ENOENT {
+ firstErr = err
+ }
+ }
if firstErr != nil {
return nil, firstErr
}