]> Cypherpunks repositories - gostls13.git/commitdiff
Revert "time: enable ZONEINFO tzdata file support and error reporting"
authorRuss Cox <rsc@golang.org>
Wed, 15 Nov 2017 17:53:30 +0000 (17:53 +0000)
committerRuss Cox <rsc@golang.org>
Thu, 16 Nov 2017 14:58:12 +0000 (14:58 +0000)
This reverts commit 630d176e7d5e42e21d176d1b9d48de0e03e7cec8.

Reason for revert: the CL moves a parser for what appears to be an
Android-specific file format into the main code and makes it available
on all platforms. Android-specific file formats should be limited to
Android.

Change-Id: I3f19fe03673d65ed1446a0dcf95e5986053e10c0
Reviewed-on: https://go-review.googlesource.com/77950
Reviewed-by: Brad Fitzpatrick <bradfitz@golang.org>
Run-TryBot: Russ Cox <rsc@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>

src/time/zoneinfo.go
src/time/zoneinfo_android.go
src/time/zoneinfo_read.go

index 4e2a207200f66d167de368be1df24a33d326ffcc..4424b4410687760b193f56d073f57d93d7bce473 100644 (file)
@@ -272,7 +272,7 @@ var zoneinfoOnce sync.Once
 //
 // The time zone database needed by LoadLocation may not be
 // present on all systems, especially non-Unix systems.
-// LoadLocation looks in the directory, uncompressed zip file, or tzdata file
+// LoadLocation looks in the directory or uncompressed zip file
 // named by the ZONEINFO environment variable, if any, then looks in
 // known installation locations on Unix systems,
 // and finally looks in $GOROOT/lib/time/zoneinfo.zip.
@@ -292,13 +292,14 @@ func LoadLocation(name string) (*Location, error) {
                env, _ := syscall.Getenv("ZONEINFO")
                zoneinfo = &env
        })
-       sources := zoneSources
        if *zoneinfo != "" {
-               sources = make([]string, len(zoneSources)+1)
-               sources[0] = *zoneinfo
-               copy(sources[1:], zoneSources)
+               if zoneData, err := loadTzinfoFromDirOrZip(*zoneinfo, name); err == nil {
+                       if z, err := newLocationFromTzinfo(name, zoneData); err == nil {
+                               return z, nil
+                       }
+               }
        }
-       return loadLocation(name, sources)
+       return loadLocation(name, zoneSources)
 }
 
 // containsDotDot reports whether s contains "..".
index 677b06e7e57a9bdafed43bc02bf32bae92adc5f9..40c8ae04ea04f535f7ccbc4146629221dc389437 100644 (file)
@@ -9,6 +9,7 @@
 package time
 
 import (
+       "errors"
        "runtime"
 )
 
@@ -22,3 +23,57 @@ func initLocal() {
        // TODO(elias.naur): getprop persist.sys.timezone
        localLoc = *UTC
 }
+
+func init() {
+       loadTzinfoFromTzdata = androidLoadTzinfoFromTzdata
+}
+
+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 := data{buf, false}
+       if magic := d.read(6); string(magic) != "tzdata" {
+               return nil, errors.New("corrupt tzdata file " + file)
+       }
+       d = data{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 := data{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, errors.New("cannot find " + name + " in tzdata file " + file)
+}
index 22658fc28af2e99b3839d177bb38d6cca429066d..eaaaf1f2b4c23639da16be39e03e6587d3db0c5f 100644 (file)
@@ -220,6 +220,18 @@ func newLocationFromTzinfo(name string, Tzinfo []byte) (*Location, error) {
        return l, nil
 }
 
+// loadTzinfoFromDirOrZip returns the contents of the file with the given name
+// in dir. dir can either be an uncompressed zip file, or a directory.
+func loadTzinfoFromDirOrZip(dir, name string) ([]byte, error) {
+       if len(dir) > 4 && dir[len(dir)-4:] == ".zip" {
+               return loadTzinfoFromZip(dir, name)
+       }
+       if dir != "" {
+               name = dir + "/" + name
+       }
+       return readFile(name)
+}
+
 // There are 500+ zoneinfo files. Rather than distribute them all
 // individually, we ship them in an uncompressed zip file.
 // Used this way, the zip file format serves as a commonly readable
@@ -351,61 +363,13 @@ func loadTzinfoFromZip(zipfile, name string) ([]byte, error) {
                return buf, nil
        }
 
-       return nil, syscall.ENOENT
+       return nil, errors.New("cannot find " + name + " in zip file " + zipfile)
 }
 
 // loadTzinfoFromTzdata returns the time zone information of the time zone
 // with the given name, from a tzdata database file as they are typically
 // found on android.
-func loadTzinfoFromTzdata(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 := data{buf, false}
-       if magic := d.read(6); string(magic) != "tzdata" {
-               return nil, errors.New("corrupt tzdata file " + file)
-       }
-       d = data{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 := data{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
-}
+var loadTzinfoFromTzdata func(file, name string) ([]byte, error)
 
 // loadTzinfo returns the time zone information of the time zone
 // with the given name, from a given source. A source may be a
@@ -414,13 +378,8 @@ func loadTzinfoFromTzdata(file, name string) ([]byte, error) {
 func loadTzinfo(name string, source string) ([]byte, error) {
        if len(source) >= 6 && source[len(source)-6:] == "tzdata" {
                return loadTzinfoFromTzdata(source, name)
-       } else if len(source) > 4 && source[len(source)-4:] == ".zip" {
-               return loadTzinfoFromZip(source, name)
-       }
-       if source != "" {
-               name = source + "/" + name
        }
-       return readFile(name)
+       return loadTzinfoFromDirOrZip(source, name)
 }
 
 // loadLocation returns the Location with the given name from one of