| // Copyright 2020 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. | 
 |  | 
 | // Package tzdata provides an embedded copy of the timezone database. | 
 | // If this package is imported anywhere in the program, then if | 
 | // the time package cannot find tzdata files on the system, | 
 | // it will use this embedded information. | 
 | // | 
 | // Importing this package will increase the size of a program by about | 
 | // 450 KB. | 
 | // | 
 | // This package should normally be imported by a program's main package, | 
 | // not by a library. Libraries normally shouldn't decide whether to | 
 | // include the timezone database in a program. | 
 | // | 
 | // This package will be automatically imported if you build with | 
 | // -tags timetzdata. | 
 | package tzdata | 
 |  | 
 | // The test for this package is time/tzdata_test.go. | 
 |  | 
 | import ( | 
 | 	"errors" | 
 | 	"syscall" | 
 | 	_ "unsafe" // for go:linkname | 
 | ) | 
 |  | 
 | // registerLoadFromEmbeddedTZData is defined in package time. | 
 | // | 
 | //go:linkname registerLoadFromEmbeddedTZData time.registerLoadFromEmbeddedTZData | 
 | func registerLoadFromEmbeddedTZData(func(string) (string, error)) | 
 |  | 
 | func init() { | 
 | 	registerLoadFromEmbeddedTZData(loadFromEmbeddedTZData) | 
 | } | 
 |  | 
 | // get4s returns the little-endian 32-bit value at the start of s. | 
 | func get4s(s string) int { | 
 | 	if len(s) < 4 { | 
 | 		return 0 | 
 | 	} | 
 | 	return int(s[0]) | int(s[1])<<8 | int(s[2])<<16 | int(s[3])<<24 | 
 | } | 
 |  | 
 | // get2s returns the little-endian 16-bit value at the start of s. | 
 | func get2s(s string) int { | 
 | 	if len(s) < 2 { | 
 | 		return 0 | 
 | 	} | 
 | 	return int(s[0]) | int(s[1])<<8 | 
 | } | 
 |  | 
 | // loadFromEmbeddedTZData returns the contents of the file with the given | 
 | // name in an uncompressed zip file, where the contents of the file can | 
 | // be found in embeddedTzdata. | 
 | // This is similar to time.loadTzinfoFromZip. | 
 | func loadFromEmbeddedTZData(name string) (string, error) { | 
 | 	const ( | 
 | 		zecheader = 0x06054b50 | 
 | 		zcheader  = 0x02014b50 | 
 | 		ztailsize = 22 | 
 |  | 
 | 		zheadersize = 30 | 
 | 		zheader     = 0x04034b50 | 
 | 	) | 
 |  | 
 | 	// zipdata is provided by zzipdata.go, | 
 | 	// which is generated by cmd/dist during make.bash. | 
 | 	z := zipdata | 
 |  | 
 | 	idx := len(z) - ztailsize | 
 | 	n := get2s(z[idx+10:]) | 
 | 	idx = get4s(z[idx+16:]) | 
 |  | 
 | 	for i := 0; i < n; i++ { | 
 | 		// See time.loadTzinfoFromZip for zip entry layout. | 
 | 		if get4s(z[idx:]) != zcheader { | 
 | 			break | 
 | 		} | 
 | 		meth := get2s(z[idx+10:]) | 
 | 		size := get4s(z[idx+24:]) | 
 | 		namelen := get2s(z[idx+28:]) | 
 | 		xlen := get2s(z[idx+30:]) | 
 | 		fclen := get2s(z[idx+32:]) | 
 | 		off := get4s(z[idx+42:]) | 
 | 		zname := z[idx+46 : idx+46+namelen] | 
 | 		idx += 46 + namelen + xlen + fclen | 
 | 		if zname != name { | 
 | 			continue | 
 | 		} | 
 | 		if meth != 0 { | 
 | 			return "", errors.New("unsupported compression for " + name + " in embedded tzdata") | 
 | 		} | 
 |  | 
 | 		// See time.loadTzinfoFromZip for zip per-file header layout. | 
 | 		idx = off | 
 | 		if get4s(z[idx:]) != zheader || | 
 | 			get2s(z[idx+8:]) != meth || | 
 | 			get2s(z[idx+26:]) != namelen || | 
 | 			z[idx+30:idx+30+namelen] != name { | 
 | 			return "", errors.New("corrupt embedded tzdata") | 
 | 		} | 
 | 		xlen = get2s(z[idx+28:]) | 
 | 		idx += 30 + namelen + xlen | 
 | 		return z[idx : idx+size], nil | 
 | 	} | 
 |  | 
 | 	return "", syscall.ENOENT | 
 | } |