Documentation
¶
Overview ¶
Package archive reads the headers of RAR (4.x and 5.x) and 7z archives and maps each inner file onto byte ranges (extents) of the archive volumes, so that store-mode members can be streamed (with native decryption when needed) out of the volumes without extracting anything.
Every volume is accessed through an io.ReaderAt whose reads may be expensive (each one can trigger a network fetch), so the parsers read only header bytes, in small exact-size chunks, and never touch file data.
Index ¶
Constants ¶
const SignatureLen = 8
SignatureLen is the number of leading bytes Detect needs to recognise every supported format.
Variables ¶
var ( ErrNotArchive = errors.New("archive: not a recognised archive") ErrCompressed = errors.New("archive: compressed (not store mode)") ErrEncrypted = errors.New("archive: encrypted") ErrPasswordRequired = fmt.Errorf("archive: password required: %w", ErrEncrypted) ErrBadPassword = fmt.Errorf("archive: incorrect password: %w", ErrEncrypted) ErrSolid = errors.New("archive: solid archive") ErrUnsupported = errors.New("archive: unsupported archive feature") ErrCorrupt = errors.New("archive: corrupt or truncated header") ErrMissingVolume = errors.New("archive: missing volume") )
Sentinel errors. Errors returned by this package wrap one of these (via fmt.Errorf with %w) so callers can test them with errors.Is.
Functions ¶
This section is empty.
Types ¶
type Encryption ¶ added in v0.2.4
Encryption describes the CBC-encrypted logical stream formed by a member's Extents. Size excludes block padding; Offset locates this member within that plaintext stream (a 7z folder can contain several members). Keys are ephemeral parser results and must not be persisted or included in diagnostic JSON. CBC provides confidentiality, not authentication: archive password checks and checksums must be validated separately by the format reader.
type Extent ¶
type Extent struct {
Volume int // index into the volumes slice passed in
Offset int64 // byte offset inside that volume
Size int64
}
Extent is a contiguous byte range inside one volume.
func SplitExtents ¶
SplitExtents maps extents expressed as offsets in the concatenated stream (Volume must be 0, as returned by List7z over a MultiReader) onto extents of the individual volumes passed to NewMultiReader. Volumes with Size <= 0 keep their index but never receive extents.
type Format ¶
type Format int
Format identifies an archive container format.
type Member ¶
type Member struct {
Name string
Size int64 // unpacked size
Stored bool
Encrypted bool
Solid bool
Dir bool
Method string // human-readable, e.g. "store", "rar5:m3", "lzma", "copy", "aes"
Extents []Extent // in order; ciphertext ranges when Encryption is non-nil
Encryption *Encryption // ephemeral decryption metadata; nil for plain/unsupported encryption
}
Member is one inner file mapped onto volume byte ranges.
func ComposeRAR ¶
ComposeRAR joins per-volume listings (vols in volume order) into members. A file that starts in volume i and continues (SplitAfter) is followed into volume i+1, whose first file header must be the continuation (SplitBefore, same name); otherwise the result wraps ErrMissingVolume (the set ends early or a volume number is skipped) or ErrCorrupt.
Extents of stored members cover exactly the member bytes; extents of other members cover their packed (compressed and/or encrypted) data.
func List7z ¶
List7z parses a 7z archive. r is the full archive (for a multi-volume .7z.001/.002… set pass the concatenation, e.g. a MultiReader; SplitExtents maps the result back onto the individual volumes). Extents use Volume 0 and offsets in r. Only stored (Copy-only) members have extents.
func List7zWithPassword ¶ added in v0.2.4
func List7zWithPassword(ctx context.Context, r io.ReaderAt, size int64, password string) ([]Member, error)
List7zWithPassword lists an archive and prepares seekable decryption for stored encrypted members. Keys live only with the returned member plans.
func ListRAR ¶
ListRAR reads every volume (in order) with ReadRARVolume and composes the members. Extent volume indexes refer to vols.
func (*Member) Streamable ¶
Streamable returns nil if the member can be read directly from its extents, else an error wrapping ErrEncrypted, ErrSolid or ErrCompressed (checked in that order), or ErrUnsupported for a directory.
type MemberReader ¶
type MemberReader struct {
// contains filtered or unexported fields
}
MemberReader is an io.ReaderAt over a stored member's bytes.
func NewMemberReader ¶
func NewMemberReader(m Member, vols []Volume) (*MemberReader, error)
NewMemberReader returns a reader over the bytes of a stored member. It fails with the Streamable error if the member cannot be read directly, and with ErrMissingVolume or ErrCorrupt if the extents do not fit vols.
type MultiReader ¶
type MultiReader struct {
// contains filtered or unexported fields
}
MultiReader is an io.ReaderAt over the concatenation of volumes, e.g. a split .7z.001/.7z.002… set.
func NewMultiReader ¶
func NewMultiReader(vols []Volume) *MultiReader
NewMultiReader returns a reader over the concatenation of vols in order. Volumes with Size <= 0 contribute no bytes.
func (*MultiReader) ReadAt ¶
func (m *MultiReader) ReadAt(p []byte, off int64) (int, error)
ReadAt implements io.ReaderAt.
func (*MultiReader) Size ¶
func (m *MultiReader) Size() int64
Size returns the total size of all volumes.
type RARFile ¶
type RARFile struct {
Name string // path inside the archive, '/'-separated
HeaderOffset int64 // offset of the block header in this volume
DataOffset int64 // offset of this file's data in this volume
PackedSize int64 // bytes of this file's data stored in this volume
UnpackedSize int64 // total unpacked size of the whole file (-1 if unknown)
Method int // raw method: RAR4 0x30..0x35, RAR5 0..5
Stored bool // RAR4 method 0x30 / RAR5 method 0
Encryption *Encryption `json:"-"`
Encrypted bool // RAR4 LHD_PASSWORD, RAR5 file encryption extra record
Solid bool // RAR4 LHD_SOLID / RAR5 compression-info solid bit
Dir bool
SplitBefore bool // continued from previous volume
SplitAfter bool // continues in next volume
CRC32 uint32
HasCRC bool
}
RARFile is one file header found in one RAR volume.
type RAROptions ¶
type RAROptions struct {
// MaxFiles stops parsing after this many file headers (0 = no limit).
MaxFiles int
Password string `json:"-"`
Context context.Context
PasswordCache *RARPasswordCache
}
RAROptions tunes ReadRARVolume.
type RARPasswordCache ¶ added in v0.2.4
type RARPasswordCache struct {
// contains filtered or unexported fields
}
RARPasswordCache shares at most 16 derived keys across volume parses. Its zero value is usable; discard it with the archive plan.
type RARVolume ¶
type RARVolume struct {
Format Format // FormatRAR4 or FormatRAR5
MultiVolume bool // archive is part of a volume set
First bool // first volume (also true for a single-volume archive)
Number int // 0-based volume number when known, else -1
Solid bool // archive-level solid flag
NewNumbering bool // RAR4 MHD_NEWNUMBERING (name.partNN.rar)
Files []RARFile
DataStart int64 // offset of the first byte after the main archive header
EndFound bool // end-of-archive block was read
MoreVolumes bool // end block says another volume follows (only meaningful if EndFound)
}
RARVolume is the parsed header listing of one volume.
func ReadRARVolume ¶
ReadRARVolume parses the block headers of one RAR4 or RAR5 volume without reading file data. It stops at the end-of-archive block, at size, after a file header with SplitAfter set (nothing streamable follows it in this volume, so the end block is not read), or after opts.MaxFiles file headers. opts may be nil.
Encrypted headers require opts.Password; derived keys remain ephemeral. Unknown block types are skipped. Header CRCs are verified (ErrCorrupt on mismatch).
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package archivetest builds small RAR 4.x / RAR 5.0 archives (and Copy-mode 7z archives) for tests.
|
Package archivetest builds small RAR 4.x / RAR 5.0 archives (and Copy-mode 7z archives) for tests. |