archive

package
v1.0.2 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 9, 2026 License: Apache-2.0 Imports: 11 Imported by: 0

Documentation

Overview

Package archive provides archive format detection by extension and signature.

DetectFormat uses the filename extension to select an ArchiveReader (ZIPReader for .zip, TARReader for .tar/.tar.gz/.tgz/.tar.bz2/.tbz2). DetectFormatBySignature analyzes the first bytes of the stream (needed for stdin).

Index

Constants

View Source
const MaxNameLength = 4096

MaxNameLength is the maximum length of an archive entry name in bytes. Names longer than this limit are truncated with a "... (truncated)" suffix to prevent attacks via extremely long paths (display corruption, log truncation, excessive memory consumption). The value matches POSIX PATH_MAX (4096 bytes).

Variables

This section is empty.

Functions

func IsZIP

func IsZIP(ra io.ReaderAt) bool

IsZIP checks for the PK\x03\x04 signature at the beginning of the data.

Types

type ArchiveFileMode

type ArchiveFileMode uint32

type ArchiveReader

type ArchiveReader interface {
	ReadEntries(r io.ReaderAt, maxEntries int) ([]Entry, error)

	Format() string
}

func DetectFormat

func DetectFormat(path string) (ArchiveReader, error)

DetectFormat determines the archive format from the filename extension. Supported extensions: .zip, .tar, .tar.gz/.tgz, .tar.bz2/.tbz2, .tar.xz/.txz. Unknown extensions return an error instead of silently falling back to TAR.

func DetectFormatBySignature

func DetectFormatBySignature(data []byte) (ArchiveReader, error)

DetectFormatBySignature determines the archive format from the first bytes of the stream. Used only for stdin, where there is no filename extension.

Signatures:

  • ZIP: PK\x03\x04 (4 bytes)
  • Gzip: \x1f\x8b (2 bytes)
  • Bzip2: BZh (3 bytes, where h is a digit '1'-'9')

If the signature is not recognized, plain TAR is assumed (TAR has no magic signature). This function never returns an error for unrecognized formats — it falls back to TARReader with TarPlain.

type Entry

type Entry struct {
	Name       string
	Size       uint64
	Compressed uint64
	Mode       ArchiveFileMode
	Symlink    string

	// HeaderOffset is the byte offset of the entry header within the archive.
	// For ZIP: always 0 (the public archive/zip API does not expose the offset).
	// For plain TAR: real file offset.
	// For compressed TAR (.gz/.bz2): position in the compressed stream (countingReader
	// wraps the original io.SectionReader, not the decompressed stream).
	//   Note: the value does NOT correspond to a position in the decompressed
	//   TAR — the relationship between compressed and decompressed positions is
	//   nonlinear. For compressed formats, HeaderOffset is informational only.
	HeaderOffset int64

	// MagicBytes holds the first 8 bytes of the file content (or fewer for short files).
	// Used by the polyglot rule to check for nested archive signatures
	// (ZIP: PK\x03\x04, Gzip: \x1f\x8b) without extracting to disk.
	// For directories and symlinks: nil.
	MagicBytes []byte
}

Entry represents metadata for a single archive entry.

func (*Entry) IsDirectory

func (e *Entry) IsDirectory() bool
func (e *Entry) ValidSymlink() string

ValidSymlink returns the symlink target if the entry is a symbolic link. For TAR, the target is read from the Linkname header field (no body extraction). For ZIP, the symlink target is stored in file data and is inaccessible due to P-02 (No extraction) — in this case "" is returned but Mode contains ModeSymlink.

type TARReader

type TARReader struct {
	Compression TarCompression
}

TARReader reads TAR archive metadata sequentially (ADR-003: Streaming). Supports: .tar, .tar.gz (.tgz), .tar.bz2 (.tbz2). XZ compression (.tar.xz) is not supported — no stdlib package in Go (ADR-001).

File contents are never extracted to disk; they are skipped via io.Discard when advancing to the next header.

func (*TARReader) Format

func (tr *TARReader) Format() string

Format returns the archive type ("tar").

func (*TARReader) ReadEntries

func (tr *TARReader) ReadEntries(ra io.ReaderAt, maxEntries int) ([]Entry, error)

ReadEntries reads TAR headers sequentially up to maxEntries+1. The ra parameter must implement io.ReaderAt (e.g., *os.File). For compressed formats (TarGzip, TarBzip2), ra must point to the compressed file — decompression is handled internally. If maxEntries <= 0, there is no limit.

type TarCompression

type TarCompression int

TarCompression is the TAR compression type.

const (
	TarPlain TarCompression = iota // No compression (.tar)
	TarGzip                        // Gzip (.tar.gz, .tgz)
	TarBzip2                       // Bzip2 (.tar.bz2, .tbz2)
	TarXz                          // XZ (.tar.xz, .txz)
)

func DetectTARCompression

func DetectTARCompression(filename string) TarCompression

DetectTARCompression determines the TAR compression type from the filename extension. Comparison is case-insensitive. Supported extensions:

  • .tar → TarPlain
  • .tar.gz, .tgz → TarGzip
  • .tar.bz2, .tbz2 → TarBzip2
  • .tar.xz, .txz → TarXz

Unknown extensions return TarPlain.

type ZIPReader

type ZIPReader struct{}

ZIPReader reads ZIP archive metadata from the central directory. Files are never extracted to disk — only headers are read.

func (*ZIPReader) Format

func (r *ZIPReader) Format() string

Format returns the archive type ("zip").

func (*ZIPReader) ReadEntries

func (r *ZIPReader) ReadEntries(ra io.ReaderAt, maxEntries int) ([]Entry, error)

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL