Source file src/time/zoneinfo_android.go

     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.
     4  
     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.
     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  	// TODO(elias.naur): getprop persist.sys.timezone
    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  		// len(name) <= namesize is checked at function entry
    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