...

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		"runtime"
    14		"syscall"
    15	)
    16	
    17	var zoneSources = []string{
    18		"/system/usr/share/zoneinfo/tzdata",
    19		"/data/misc/zoneinfo/current/tzdata",
    20		runtime.GOROOT() + "/lib/time/zoneinfo.zip",
    21	}
    22	
    23	func initLocal() {
    24		// TODO(elias.naur): getprop persist.sys.timezone
    25		localLoc = *UTC
    26	}
    27	
    28	func init() {
    29		loadTzinfoFromTzdata = androidLoadTzinfoFromTzdata
    30	}
    31	
    32	func androidLoadTzinfoFromTzdata(file, name string) ([]byte, error) {
    33		const (
    34			headersize = 12 + 3*4
    35			namesize   = 40
    36			entrysize  = namesize + 3*4
    37		)
    38		if len(name) > namesize {
    39			return nil, errors.New(name + " is longer than the maximum zone name length (40 bytes)")
    40		}
    41		fd, err := open(file)
    42		if err != nil {
    43			return nil, err
    44		}
    45		defer closefd(fd)
    46	
    47		buf := make([]byte, headersize)
    48		if err := preadn(fd, buf, 0); err != nil {
    49			return nil, errors.New("corrupt tzdata file " + file)
    50		}
    51		d := dataIO{buf, false}
    52		if magic := d.read(6); string(magic) != "tzdata" {
    53			return nil, errors.New("corrupt tzdata file " + file)
    54		}
    55		d = dataIO{buf[12:], false}
    56		indexOff, _ := d.big4()
    57		dataOff, _ := d.big4()
    58		indexSize := dataOff - indexOff
    59		entrycount := indexSize / entrysize
    60		buf = make([]byte, indexSize)
    61		if err := preadn(fd, buf, int(indexOff)); err != nil {
    62			return nil, errors.New("corrupt tzdata file " + file)
    63		}
    64		for i := 0; i < int(entrycount); i++ {
    65			entry := buf[i*entrysize : (i+1)*entrysize]
    66			// len(name) <= namesize is checked at function entry
    67			if string(entry[:len(name)]) != name {
    68				continue
    69			}
    70			d := dataIO{entry[namesize:], false}
    71			off, _ := d.big4()
    72			size, _ := d.big4()
    73			buf := make([]byte, size)
    74			if err := preadn(fd, buf, int(off+dataOff)); err != nil {
    75				return nil, errors.New("corrupt tzdata file " + file)
    76			}
    77			return buf, nil
    78		}
    79		return nil, syscall.ENOENT
    80	}
    81	

View as plain text