Add archive/zip from go1.7rc5 tag

In preparation to patch in some custom functionality (parallel
compression and zero-decompress zip to zip copying)

Change-Id: I96a36efc09c715f6b55290af40ebfdde9ae72e33
diff --git a/third_party/zip/struct.go b/third_party/zip/struct.go
new file mode 100644
index 0000000..e92d02f
--- /dev/null
+++ b/third_party/zip/struct.go
@@ -0,0 +1,313 @@
+// Copyright 2010 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 zip provides support for reading and writing ZIP archives.
+
+See: https://www.pkware.com/documents/casestudies/APPNOTE.TXT
+
+This package does not support disk spanning.
+
+A note about ZIP64:
+
+To be backwards compatible the FileHeader has both 32 and 64 bit Size
+fields. The 64 bit fields will always contain the correct value and
+for normal archives both fields will be the same. For files requiring
+the ZIP64 format the 32 bit fields will be 0xffffffff and the 64 bit
+fields must be used instead.
+*/
+package zip
+
+import (
+	"os"
+	"path"
+	"time"
+)
+
+// Compression methods.
+const (
+	Store   uint16 = 0
+	Deflate uint16 = 8
+)
+
+const (
+	fileHeaderSignature      = 0x04034b50
+	directoryHeaderSignature = 0x02014b50
+	directoryEndSignature    = 0x06054b50
+	directory64LocSignature  = 0x07064b50
+	directory64EndSignature  = 0x06064b50
+	dataDescriptorSignature  = 0x08074b50 // de-facto standard; required by OS X Finder
+	fileHeaderLen            = 30         // + filename + extra
+	directoryHeaderLen       = 46         // + filename + extra + comment
+	directoryEndLen          = 22         // + comment
+	dataDescriptorLen        = 16         // four uint32: descriptor signature, crc32, compressed size, size
+	dataDescriptor64Len      = 24         // descriptor with 8 byte sizes
+	directory64LocLen        = 20         //
+	directory64EndLen        = 56         // + extra
+
+	// Constants for the first byte in CreatorVersion
+	creatorFAT    = 0
+	creatorUnix   = 3
+	creatorNTFS   = 11
+	creatorVFAT   = 14
+	creatorMacOSX = 19
+
+	// version numbers
+	zipVersion20 = 20 // 2.0
+	zipVersion45 = 45 // 4.5 (reads and writes zip64 archives)
+
+	// limits for non zip64 files
+	uint16max = (1 << 16) - 1
+	uint32max = (1 << 32) - 1
+
+	// extra header id's
+	zip64ExtraId = 0x0001 // zip64 Extended Information Extra Field
+)
+
+// FileHeader describes a file within a zip file.
+// See the zip spec for details.
+type FileHeader struct {
+	// Name is the name of the file.
+	// It must be a relative path: it must not start with a drive
+	// letter (e.g. C:) or leading slash, and only forward slashes
+	// are allowed.
+	Name string
+
+	CreatorVersion     uint16
+	ReaderVersion      uint16
+	Flags              uint16
+	Method             uint16
+	ModifiedTime       uint16 // MS-DOS time
+	ModifiedDate       uint16 // MS-DOS date
+	CRC32              uint32
+	CompressedSize     uint32 // Deprecated: Use CompressedSize64 instead.
+	UncompressedSize   uint32 // Deprecated: Use UncompressedSize64 instead.
+	CompressedSize64   uint64
+	UncompressedSize64 uint64
+	Extra              []byte
+	ExternalAttrs      uint32 // Meaning depends on CreatorVersion
+	Comment            string
+}
+
+// FileInfo returns an os.FileInfo for the FileHeader.
+func (h *FileHeader) FileInfo() os.FileInfo {
+	return headerFileInfo{h}
+}
+
+// headerFileInfo implements os.FileInfo.
+type headerFileInfo struct {
+	fh *FileHeader
+}
+
+func (fi headerFileInfo) Name() string { return path.Base(fi.fh.Name) }
+func (fi headerFileInfo) Size() int64 {
+	if fi.fh.UncompressedSize64 > 0 {
+		return int64(fi.fh.UncompressedSize64)
+	}
+	return int64(fi.fh.UncompressedSize)
+}
+func (fi headerFileInfo) IsDir() bool        { return fi.Mode().IsDir() }
+func (fi headerFileInfo) ModTime() time.Time { return fi.fh.ModTime() }
+func (fi headerFileInfo) Mode() os.FileMode  { return fi.fh.Mode() }
+func (fi headerFileInfo) Sys() interface{}   { return fi.fh }
+
+// FileInfoHeader creates a partially-populated FileHeader from an
+// os.FileInfo.
+// Because os.FileInfo's Name method returns only the base name of
+// the file it describes, it may be necessary to modify the Name field
+// of the returned header to provide the full path name of the file.
+func FileInfoHeader(fi os.FileInfo) (*FileHeader, error) {
+	size := fi.Size()
+	fh := &FileHeader{
+		Name:               fi.Name(),
+		UncompressedSize64: uint64(size),
+	}
+	fh.SetModTime(fi.ModTime())
+	fh.SetMode(fi.Mode())
+	if fh.UncompressedSize64 > uint32max {
+		fh.UncompressedSize = uint32max
+	} else {
+		fh.UncompressedSize = uint32(fh.UncompressedSize64)
+	}
+	return fh, nil
+}
+
+type directoryEnd struct {
+	diskNbr            uint32 // unused
+	dirDiskNbr         uint32 // unused
+	dirRecordsThisDisk uint64 // unused
+	directoryRecords   uint64
+	directorySize      uint64
+	directoryOffset    uint64 // relative to file
+	commentLen         uint16
+	comment            string
+}
+
+// msDosTimeToTime converts an MS-DOS date and time into a time.Time.
+// The resolution is 2s.
+// See: http://msdn.microsoft.com/en-us/library/ms724247(v=VS.85).aspx
+func msDosTimeToTime(dosDate, dosTime uint16) time.Time {
+	return time.Date(
+		// date bits 0-4: day of month; 5-8: month; 9-15: years since 1980
+		int(dosDate>>9+1980),
+		time.Month(dosDate>>5&0xf),
+		int(dosDate&0x1f),
+
+		// time bits 0-4: second/2; 5-10: minute; 11-15: hour
+		int(dosTime>>11),
+		int(dosTime>>5&0x3f),
+		int(dosTime&0x1f*2),
+		0, // nanoseconds
+
+		time.UTC,
+	)
+}
+
+// timeToMsDosTime converts a time.Time to an MS-DOS date and time.
+// The resolution is 2s.
+// See: http://msdn.microsoft.com/en-us/library/ms724274(v=VS.85).aspx
+func timeToMsDosTime(t time.Time) (fDate uint16, fTime uint16) {
+	t = t.In(time.UTC)
+	fDate = uint16(t.Day() + int(t.Month())<<5 + (t.Year()-1980)<<9)
+	fTime = uint16(t.Second()/2 + t.Minute()<<5 + t.Hour()<<11)
+	return
+}
+
+// ModTime returns the modification time in UTC.
+// The resolution is 2s.
+func (h *FileHeader) ModTime() time.Time {
+	return msDosTimeToTime(h.ModifiedDate, h.ModifiedTime)
+}
+
+// SetModTime sets the ModifiedTime and ModifiedDate fields to the given time in UTC.
+// The resolution is 2s.
+func (h *FileHeader) SetModTime(t time.Time) {
+	h.ModifiedDate, h.ModifiedTime = timeToMsDosTime(t)
+}
+
+const (
+	// Unix constants. The specification doesn't mention them,
+	// but these seem to be the values agreed on by tools.
+	s_IFMT   = 0xf000
+	s_IFSOCK = 0xc000
+	s_IFLNK  = 0xa000
+	s_IFREG  = 0x8000
+	s_IFBLK  = 0x6000
+	s_IFDIR  = 0x4000
+	s_IFCHR  = 0x2000
+	s_IFIFO  = 0x1000
+	s_ISUID  = 0x800
+	s_ISGID  = 0x400
+	s_ISVTX  = 0x200
+
+	msdosDir      = 0x10
+	msdosReadOnly = 0x01
+)
+
+// Mode returns the permission and mode bits for the FileHeader.
+func (h *FileHeader) Mode() (mode os.FileMode) {
+	switch h.CreatorVersion >> 8 {
+	case creatorUnix, creatorMacOSX:
+		mode = unixModeToFileMode(h.ExternalAttrs >> 16)
+	case creatorNTFS, creatorVFAT, creatorFAT:
+		mode = msdosModeToFileMode(h.ExternalAttrs)
+	}
+	if len(h.Name) > 0 && h.Name[len(h.Name)-1] == '/' {
+		mode |= os.ModeDir
+	}
+	return mode
+}
+
+// SetMode changes the permission and mode bits for the FileHeader.
+func (h *FileHeader) SetMode(mode os.FileMode) {
+	h.CreatorVersion = h.CreatorVersion&0xff | creatorUnix<<8
+	h.ExternalAttrs = fileModeToUnixMode(mode) << 16
+
+	// set MSDOS attributes too, as the original zip does.
+	if mode&os.ModeDir != 0 {
+		h.ExternalAttrs |= msdosDir
+	}
+	if mode&0200 == 0 {
+		h.ExternalAttrs |= msdosReadOnly
+	}
+}
+
+// isZip64 reports whether the file size exceeds the 32 bit limit
+func (fh *FileHeader) isZip64() bool {
+	return fh.CompressedSize64 >= uint32max || fh.UncompressedSize64 >= uint32max
+}
+
+func msdosModeToFileMode(m uint32) (mode os.FileMode) {
+	if m&msdosDir != 0 {
+		mode = os.ModeDir | 0777
+	} else {
+		mode = 0666
+	}
+	if m&msdosReadOnly != 0 {
+		mode &^= 0222
+	}
+	return mode
+}
+
+func fileModeToUnixMode(mode os.FileMode) uint32 {
+	var m uint32
+	switch mode & os.ModeType {
+	default:
+		m = s_IFREG
+	case os.ModeDir:
+		m = s_IFDIR
+	case os.ModeSymlink:
+		m = s_IFLNK
+	case os.ModeNamedPipe:
+		m = s_IFIFO
+	case os.ModeSocket:
+		m = s_IFSOCK
+	case os.ModeDevice:
+		if mode&os.ModeCharDevice != 0 {
+			m = s_IFCHR
+		} else {
+			m = s_IFBLK
+		}
+	}
+	if mode&os.ModeSetuid != 0 {
+		m |= s_ISUID
+	}
+	if mode&os.ModeSetgid != 0 {
+		m |= s_ISGID
+	}
+	if mode&os.ModeSticky != 0 {
+		m |= s_ISVTX
+	}
+	return m | uint32(mode&0777)
+}
+
+func unixModeToFileMode(m uint32) os.FileMode {
+	mode := os.FileMode(m & 0777)
+	switch m & s_IFMT {
+	case s_IFBLK:
+		mode |= os.ModeDevice
+	case s_IFCHR:
+		mode |= os.ModeDevice | os.ModeCharDevice
+	case s_IFDIR:
+		mode |= os.ModeDir
+	case s_IFIFO:
+		mode |= os.ModeNamedPipe
+	case s_IFLNK:
+		mode |= os.ModeSymlink
+	case s_IFREG:
+		// nothing to do
+	case s_IFSOCK:
+		mode |= os.ModeSocket
+	}
+	if m&s_ISGID != 0 {
+		mode |= os.ModeSetgid
+	}
+	if m&s_ISUID != 0 {
+		mode |= os.ModeSetuid
+	}
+	if m&s_ISVTX != 0 {
+		mode |= os.ModeSticky
+	}
+	return mode
+}