zip

Imports

Imports #

"bufio"
"encoding/binary"
"errors"
"hash"
"hash/crc32"
"internal/godebug"
"io"
"io/fs"
"os"
"path"
"path/filepath"
"slices"
"strings"
"sync"
"time"
"compress/flate"
"errors"
"io"
"sync"
"io/fs"
"path"
"time"
"bufio"
"encoding/binary"
"errors"
"hash"
"hash/crc32"
"io"
"io/fs"
"strings"
"unicode/utf8"

Constants & Variables

Deflate const #

Compression methods.

const Deflate uint16 = 8

ErrAlgorithm var #

var ErrAlgorithm = *ast.CallExpr

ErrChecksum var #

var ErrChecksum = *ast.CallExpr

ErrFormat var #

var ErrFormat = *ast.CallExpr

ErrInsecurePath var #

var ErrInsecurePath = *ast.CallExpr

Store const #

Compression methods.

const Store uint16 = 0

compressors var #

var compressors sync.Map

creatorFAT const #

Constants for the first byte in CreatorVersion.

const creatorFAT = 0

creatorMacOSX const #

const creatorMacOSX = 19

creatorNTFS const #

const creatorNTFS = 11

creatorUnix const #

const creatorUnix = 3

creatorVFAT const #

const creatorVFAT = 14

dataDescriptor64Len const #

const dataDescriptor64Len = 24

dataDescriptorLen const #

const dataDescriptorLen = 16

dataDescriptorSignature const #

const dataDescriptorSignature = 0x08074b50

decompressors var #

var decompressors sync.Map

directory64EndLen const #

const directory64EndLen = 56

directory64EndSignature const #

const directory64EndSignature = 0x06064b50

directory64LocLen const #

const directory64LocLen = 20

directory64LocSignature const #

const directory64LocSignature = 0x07064b50

directoryEndLen const #

const directoryEndLen = 22

directoryEndSignature const #

const directoryEndSignature = 0x06054b50

directoryHeaderLen const #

const directoryHeaderLen = 46

directoryHeaderSignature const #

const directoryHeaderSignature = 0x02014b50

dotFile var #

var dotFile = *ast.UnaryExpr

errLongExtra var #

var errLongExtra = *ast.CallExpr

errLongName var #

var errLongName = *ast.CallExpr

extTimeExtraID const #

const extTimeExtraID = 0x5455

fileHeaderLen const #

const fileHeaderLen = 30

fileHeaderSignature const #

const fileHeaderSignature = 0x04034b50

flateReaderPool var #

var flateReaderPool sync.Pool

flateWriterPool var #

var flateWriterPool sync.Pool

infoZipUnixExtraID const #

const infoZipUnixExtraID = 0x5855

msdosDir const #

const msdosDir = 0x10

msdosReadOnly const #

const msdosReadOnly = 0x01

ntfsExtraID const #

const ntfsExtraID = 0x000a

s_IFBLK const #

const s_IFBLK = 0x6000

s_IFCHR const #

const s_IFCHR = 0x2000

s_IFDIR const #

const s_IFDIR = 0x4000

s_IFIFO const #

const s_IFIFO = 0x1000

s_IFLNK const #

const s_IFLNK = 0xa000

s_IFMT const #

Unix constants. The specification doesn't mention them, but these seem to be the values agreed on by tools.

const s_IFMT = 0xf000

s_IFREG const #

const s_IFREG = 0x8000

s_IFSOCK const #

const s_IFSOCK = 0xc000

s_ISGID const #

const s_ISGID = 0x400

s_ISUID const #

const s_ISUID = 0x800

s_ISVTX const #

const s_ISVTX = 0x200

uint16max const #

Limits for non zip64 files.

const uint16max = *ast.BinaryExpr

uint32max const #

const uint32max = *ast.BinaryExpr

unixExtraID const #

const unixExtraID = 0x000d

zip64ExtraID const #

Extra header IDs. IDs 0..31 are reserved for official use by PKWARE. IDs above that range are defined by third-party vendors. Since ZIP lacked high precision timestamps (nor an official specification of the timezone used for the date fields), many competing extra fields have been invented. Pervasive use effectively makes them "official". See http://mdfs.net/Docs/Comp/Archiving/Zip/ExtraField

const zip64ExtraID = 0x0001

zipVersion20 const #

Version numbers.

const zipVersion20 = 20

zipVersion45 const #

const zipVersion45 = 45

zipinsecurepath var #

var zipinsecurepath = *ast.CallExpr

Type Aliases

Compressor type #

A Compressor returns a new compressing writer, writing to w. The WriteCloser's Close method must be used to flush pending data to w. The Compressor itself must be safe to invoke from multiple goroutines simultaneously, but each returned writer will be used only by one goroutine at a time.

type Compressor func(w io.Writer) (io.WriteCloser, error)

Decompressor type #

A Decompressor returns a new decompressing reader, reading from r. The [io.ReadCloser]'s Close method must be used to release associated resources. The Decompressor itself must be safe to invoke from multiple goroutines simultaneously, but each returned reader will be used only by one goroutine at a time.

type Decompressor func(r io.Reader) io.ReadCloser

readBuf type #

type readBuf []byte

writeBuf type #

type writeBuf []byte

Interfaces

fileInfoDirEntry interface #

type fileInfoDirEntry interface {
fs.FileInfo
fs.DirEntry
}

Structs

File struct #

A File is a single file in a ZIP archive. The file information is in the embedded [FileHeader]. The file content can be accessed by calling [File.Open].

type File struct {
FileHeader
zip *Reader
zipr io.ReaderAt
headerOffset int64
zip64 bool
}

FileHeader struct #

FileHeader describes a file within a ZIP file. See the [ZIP specification] for details. [ZIP specification]: https://support.pkware.com/pkzip/appnote

type FileHeader struct {
Name string
Comment string
NonUTF8 bool
CreatorVersion uint16
ReaderVersion uint16
Flags uint16
Method uint16
Modified time.Time
ModifiedTime uint16
ModifiedDate uint16
CRC32 uint32
CompressedSize uint32
UncompressedSize uint32
CompressedSize64 uint64
UncompressedSize64 uint64
Extra []byte
ExternalAttrs uint32
}

ReadCloser struct #

A ReadCloser is a [Reader] that must be closed when no longer needed.

type ReadCloser struct {
f *os.File
Reader
}

Reader struct #

A Reader serves content from a ZIP archive.

type Reader struct {
r io.ReaderAt
File []*File
Comment string
decompressors map[uint16]Decompressor
baseOffset int64
fileListOnce sync.Once
fileList []fileListEntry
}

Writer struct #

Writer implements a zip file writer.

type Writer struct {
cw *countWriter
dir []*header
last *fileWriter
closed bool
compressors map[uint16]Compressor
comment string
testHookCloseSizeOffset func(size uint64, offset uint64)
}

checksumReader struct #

type checksumReader struct {
rc io.ReadCloser
hash hash.Hash32
nread uint64
f *File
desr io.Reader
err error
}

countWriter struct #

type countWriter struct {
w io.Writer
count int64
}

dirReader struct #

type dirReader struct {
err error
}

dirWriter struct #

type dirWriter struct {

}

directoryEnd struct #

type directoryEnd struct {
diskNbr uint32
dirDiskNbr uint32
dirRecordsThisDisk uint64
directoryRecords uint64
directorySize uint64
directoryOffset uint64
commentLen uint16
comment string
}

fileListEntry struct #

A fileListEntry is a File and its ename. If file == nil, the fileListEntry describes a directory without metadata.

type fileListEntry struct {
name string
file *File
isDir bool
isDup bool
}

fileWriter struct #

type fileWriter struct {
*header
zipw io.Writer
rawCount *countWriter
comp io.WriteCloser
compCount *countWriter
crc32 hash.Hash32
closed bool
}

headerFileInfo struct #

headerFileInfo implements [fs.FileInfo].

type headerFileInfo struct {
fh *FileHeader
}

nopCloser struct #

type nopCloser struct {
io.Writer
}

openDir struct #

type openDir struct {
e *fileListEntry
files []fileListEntry
offset int
}

pooledFlateReader struct #

type pooledFlateReader struct {
mu sync.Mutex
fr io.ReadCloser
}

pooledFlateWriter struct #

type pooledFlateWriter struct {
mu sync.Mutex
fw *flate.Writer
}

Functions

AddFS method #

AddFS adds the files from fs.FS to the archive. It walks the directory tree starting at the root of the filesystem adding each file to the zip using deflate while maintaining the directory structure.

func (w *Writer) AddFS(fsys fs.FS) error

Close method #

func (r *dirReader) Close() error

Close method #

func (w *pooledFlateWriter) Close() error

Close method #

func (w nopCloser) Close() error

Close method #

func (d *openDir) Close() error

Close method #

Close closes the Zip file, rendering it unusable for I/O.

func (rc *ReadCloser) Close() error

Close method #

func (r *pooledFlateReader) Close() error

Close method #

func (r *checksumReader) Close() error

Close method #

Close finishes writing the zip file by writing the central directory. It does not close the underlying writer.

func (w *Writer) Close() error

Copy method #

Copy copies the file f (obtained from a [Reader]) into w. It copies the raw form directly bypassing decompression, compression, and validation.

func (w *Writer) Copy(f *File) error

Create method #

Create adds a file to the zip file using the provided name. It returns a [Writer] to which the file contents should be written. The file contents will be compressed using the [Deflate] method. The name 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. To create a directory instead of a file, add a trailing slash to the name. Duplicate names will not overwrite previous entries and are appended to the zip file. The file's contents must be written to the [io.Writer] before the next call to [Writer.Create], [Writer.CreateHeader], or [Writer.Close].

func (w *Writer) Create(name string) (io.Writer, error)

CreateHeader method #

CreateHeader adds a file to the zip archive using the provided [FileHeader] for the file metadata. [Writer] takes ownership of fh and may mutate its fields. The caller must not modify fh after calling [Writer.CreateHeader]. This returns a [Writer] to which the file contents should be written. The file's contents must be written to the io.Writer before the next call to [Writer.Create], [Writer.CreateHeader], [Writer.CreateRaw], or [Writer.Close].

func (w *Writer) CreateHeader(fh *FileHeader) (io.Writer, error)

CreateRaw method #

CreateRaw adds a file to the zip archive using the provided [FileHeader] and returns a [Writer] to which the file contents should be written. The file's contents must be written to the io.Writer before the next call to [Writer.Create], [Writer.CreateHeader], [Writer.CreateRaw], or [Writer.Close]. In contrast to [Writer.CreateHeader], the bytes passed to Writer are not compressed. CreateRaw's argument is stored in w. If the argument is a pointer to the embedded [FileHeader] in a [File] obtained from a [Reader] created from in-memory data, then w will refer to all of that memory.

func (w *Writer) CreateRaw(fh *FileHeader) (io.Writer, error)

DataOffset method #

DataOffset returns the offset of the file's possibly-compressed data, relative to the beginning of the zip file. Most callers should instead use [File.Open], which transparently decompresses data and verifies checksums.

func (f *File) DataOffset() (offset int64, err error)

FileInfo method #

FileInfo returns an fs.FileInfo for the [FileHeader].

func (h *FileHeader) FileInfo() fs.FileInfo

FileInfoHeader function #

FileInfoHeader creates a partially-populated [FileHeader] from an fs.FileInfo. Because fs.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. If compression is desired, callers should set the FileHeader.Method field; it is unset by default.

func FileInfoHeader(fi fs.FileInfo) (*FileHeader, error)

Flush method #

Flush flushes any buffered data to the underlying writer. Calling Flush is not normally necessary; calling Close is sufficient.

func (w *Writer) Flush() error

Info method #

func (f *fileListEntry) Info() (fs.FileInfo, error)

Info method #

func (fi headerFileInfo) Info() (fs.FileInfo, error)

IsDir method #

func (f *fileListEntry) IsDir() bool

IsDir method #

func (fi headerFileInfo) IsDir() bool

ModTime method #

func (fi headerFileInfo) ModTime() time.Time

ModTime method #

func (f *fileListEntry) ModTime() time.Time

ModTime method #

ModTime returns the modification time in UTC using the legacy [ModifiedDate] and [ModifiedTime] fields. Deprecated: Use [Modified] instead.

func (h *FileHeader) ModTime() time.Time

Mode method #

Mode returns the permission and mode bits for the [FileHeader].

func (h *FileHeader) Mode() (mode fs.FileMode)

Mode method #

func (fi headerFileInfo) Mode() fs.FileMode

Mode method #

func (f *fileListEntry) Mode() fs.FileMode

Name method #

Only used for directories.

func (f *fileListEntry) Name() string

Name method #

func (fi headerFileInfo) Name() string

NewReader function #

NewReader returns a new [Reader] reading from r, which is assumed to have the given size in bytes. If any file inside the archive uses a non-local name (as defined by [filepath.IsLocal]) or a name containing backslashes and the GODEBUG environment variable contains `zipinsecurepath=0`, NewReader returns the reader with an [ErrInsecurePath] error. A future version of Go may introduce this behavior by default. Programs that want to accept non-local names can ignore the [ErrInsecurePath] error and use the returned reader.

func NewReader(r io.ReaderAt, size int64) (*Reader, error)

NewWriter function #

NewWriter returns a new [Writer] writing a zip file to w.

func NewWriter(w io.Writer) *Writer

Open method #

Open opens the named file in the ZIP archive, using the semantics of fs.FS.Open: paths are always slash separated, with no leading / or ../ elements.

func (r *Reader) Open(name string) (fs.File, error)

Open method #

Open returns a [ReadCloser] that provides access to the [File]'s contents. Multiple files may be read concurrently.

func (f *File) Open() (io.ReadCloser, error)

OpenRaw method #

OpenRaw returns a [Reader] that provides access to the [File]'s contents without decompression.

func (f *File) OpenRaw() (io.Reader, error)

OpenReader function #

OpenReader will open the Zip file specified by name and return a ReadCloser. If any file inside the archive uses a non-local name (as defined by [filepath.IsLocal]) or a name containing backslashes and the GODEBUG environment variable contains `zipinsecurepath=0`, OpenReader returns the reader with an ErrInsecurePath error. A future version of Go may introduce this behavior by default. Programs that want to accept non-local names can ignore the ErrInsecurePath error and use the returned reader.

func OpenReader(name string) (*ReadCloser, error)

Read method #

func (r *dirReader) Read([]byte) (int, error)

Read method #

func (d *openDir) Read([]byte) (int, error)

Read method #

func (r *pooledFlateReader) Read(p []byte) (n int, err error)

Read method #

func (r *checksumReader) Read(b []byte) (n int, err error)

ReadDir method #

func (d *openDir) ReadDir(count int) ([]fs.DirEntry, error)

RegisterCompressor method #

RegisterCompressor registers or overrides a custom compressor for a specific method ID. If a compressor for a given method is not found, [Writer] will default to looking up the compressor at the package level.

func (w *Writer) RegisterCompressor(method uint16, comp Compressor)

RegisterCompressor function #

RegisterCompressor registers custom compressors for a specified method ID. The common methods [Store] and [Deflate] are built in.

func RegisterCompressor(method uint16, comp Compressor)

RegisterDecompressor function #

RegisterDecompressor allows custom decompressors for a specified method ID. The common methods [Store] and [Deflate] are built in.

func RegisterDecompressor(method uint16, dcomp Decompressor)

RegisterDecompressor method #

RegisterDecompressor registers or overrides a custom decompressor for a specific method ID. If a decompressor for a given method is not found, [Reader] will default to looking up the decompressor at the package level.

func (r *Reader) RegisterDecompressor(method uint16, dcomp Decompressor)

SetComment method #

SetComment sets the end-of-central-directory comment field. It can only be called before [Writer.Close].

func (w *Writer) SetComment(comment string) error

SetModTime method #

SetModTime sets the [Modified], [ModifiedTime], and [ModifiedDate] fields to the given time in UTC. Deprecated: Use [Modified] instead.

func (h *FileHeader) SetModTime(t time.Time)

SetMode method #

SetMode changes the permission and mode bits for the [FileHeader].

func (h *FileHeader) SetMode(mode fs.FileMode)

SetOffset method #

SetOffset sets the offset of the beginning of the zip data within the underlying writer. It should be used when the zip data is appended to an existing file, such as a binary executable. It must be called before any data is written.

func (w *Writer) SetOffset(n int64)

Size method #

func (fi headerFileInfo) Size() int64

Size method #

func (f *fileListEntry) Size() int64

Stat method #

func (d *openDir) Stat() (fs.FileInfo, error)

Stat method #

func (r *checksumReader) Stat() (fs.FileInfo, error)

String method #

func (f *fileListEntry) String() string

String method #

func (fi headerFileInfo) String() string

Sys method #

func (f *fileListEntry) Sys() any

Sys method #

func (fi headerFileInfo) Sys() any

Type method #

func (fi headerFileInfo) Type() fs.FileMode

Type method #

func (f *fileListEntry) Type() fs.FileMode

Write method #

func (w *fileWriter) Write(p []byte) (int, error)

Write method #

func (dirWriter) Write(b []byte) (int, error)

Write method #

func (w *countWriter) Write(p []byte) (int, error)

Write method #

func (w *pooledFlateWriter) Write(p []byte) (n int, err error)

close method #

func (w *fileWriter) close() error

compressor method #

func (w *Writer) compressor(method uint16) Compressor

compressor function #

func compressor(method uint16) Compressor

decompressor function #

func decompressor(method uint16) Decompressor

decompressor method #

func (r *Reader) decompressor(method uint16) Decompressor

detectUTF8 function #

detectUTF8 reports whether s is a valid UTF-8 string, and whether the string must be considered UTF-8 encoding (i.e., not compatible with CP-437, ASCII, or any other common encoding).

func detectUTF8(s string) (valid bool, require bool)

fileEntryCompare function #

func fileEntryCompare(x string, y string) int

fileModeToUnixMode function #

func fileModeToUnixMode(mode fs.FileMode) uint32

findBodyOffset method #

findBodyOffset does the minimum work to verify the file has a header and returns the file body offset.

func (f *File) findBodyOffset() (int64, error)

findDirectory64End function #

findDirectory64End tries to read the zip64 locator just before the directory end and returns the offset of the zip64 directory end if found.

func findDirectory64End(r io.ReaderAt, directoryEndOffset int64) (int64, error)

findSignatureInBlock function #

func findSignatureInBlock(b []byte) int

hasDataDescriptor method #

func (h *FileHeader) hasDataDescriptor() bool

init method #

func (r *Reader) init(rdr io.ReaderAt, size int64) error

init function #

func init()

initFileList method #

func (r *Reader) initFileList()

isZip64 method #

isZip64 reports whether the file size exceeds the 32 bit limit

func (h *FileHeader) isZip64() bool

msDosTimeToTime function #

msDosTimeToTime converts an MS-DOS date and time into a time.Time. The resolution is 2s. See: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-dosdatetimetofiletime

func msDosTimeToTime(dosDate uint16, dosTime uint16) time.Time

msdosModeToFileMode function #

func msdosModeToFileMode(m uint32) (mode fs.FileMode)

newFlateReader function #

func newFlateReader(r io.Reader) io.ReadCloser

newFlateWriter function #

func newFlateWriter(w io.Writer) io.WriteCloser

openLookup method #

func (r *Reader) openLookup(name string) *fileListEntry

openReadDir method #

func (r *Reader) openReadDir(dir string) []fileListEntry

prepare method #

prepare performs the bookkeeping operations required at the start of CreateHeader and CreateRaw.

func (w *Writer) prepare(fh *FileHeader) error

readDataDescriptor function #

func readDataDescriptor(r io.Reader, f *File) error

readDirectory64End function #

readDirectory64End reads the zip64 directory end and updates the directory end with the zip64 directory end values.

func readDirectory64End(r io.ReaderAt, offset int64, d *directoryEnd) (err error)

readDirectoryEnd function #

func readDirectoryEnd(r io.ReaderAt, size int64) (dir *directoryEnd, baseOffset int64, err error)

readDirectoryHeader function #

readDirectoryHeader attempts to read a directory header from r. It returns io.ErrUnexpectedEOF if it cannot read a complete header, and ErrFormat if it doesn't find a valid header signature.

func readDirectoryHeader(f *File, r io.Reader) error

split function #

func split(name string) (dir string, elem string, isDir bool)

stat method #

func (f *fileListEntry) stat() (fileInfoDirEntry, error)

sub method #

func (b *readBuf) sub(n int) readBuf

timeToMsDosTime function #

timeToMsDosTime converts a time.Time to an MS-DOS date and time. The resolution is 2s. See: https://learn.microsoft.com/en-us/windows/win32/api/winbase/nf-winbase-filetimetodosdatetime

func timeToMsDosTime(t time.Time) (fDate uint16, fTime uint16)

timeZone function #

timeZone returns a *time.Location based on the provided offset. If the offset is non-sensible, then this uses an offset of zero.

func timeZone(offset time.Duration) *time.Location

toValidName function #

toValidName coerces name to be a valid name for fs.FS.Open.

func toValidName(name string) string

uint16 method #

func (b *readBuf) uint16() uint16

uint16 method #

func (b *writeBuf) uint16(v uint16)

uint32 method #

func (b *readBuf) uint32() uint32

uint32 method #

func (b *writeBuf) uint32(v uint32)

uint64 method #

func (b *readBuf) uint64() uint64

uint64 method #

func (b *writeBuf) uint64(v uint64)

uint8 method #

func (b *readBuf) uint8() uint8

uint8 method #

func (b *writeBuf) uint8(v uint8)

unixModeToFileMode function #

func unixModeToFileMode(m uint32) fs.FileMode

writeDataDescriptor method #

func (w *fileWriter) writeDataDescriptor() error

writeHeader function #

func writeHeader(w io.Writer, h *header) error

Generated with Arrow