1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108
|
package rardecode
import (
"errors"
"hash"
)
const (
_ = iota
decode20Ver
decode29Ver
decode50Ver
decode70Ver
archiveVersion15 = 0
archiveVersion50 = 1
)
var (
ErrCorruptBlockHeader = errors.New("rardecode: corrupt block header")
ErrCorruptFileHeader = errors.New("rardecode: corrupt file header")
ErrBadHeaderCRC = errors.New("rardecode: bad header crc")
ErrUnknownDecoder = errors.New("rardecode: unknown decoder version")
ErrDecoderOutOfData = errors.New("rardecode: decoder expected more data than is in packed file")
ErrArchiveEncrypted = errors.New("rardecode: archive encrypted, password required")
ErrArchivedFileEncrypted = errors.New("rardecode: archived files encrypted, password required")
ErrMultiVolume = errors.New("rardecode: multi-volume archive continues in next file")
errVolumeOrArchiveEnd = errors.New("rardecode: archive or volume end")
)
type readBuf []byte
func (b *readBuf) byte() byte {
v := (*b)[0]
*b = (*b)[1:]
return v
}
func (b *readBuf) uint16() uint16 {
v := uint16((*b)[0]) | uint16((*b)[1])<<8
*b = (*b)[2:]
return v
}
func (b *readBuf) uint32() uint32 {
v := uint32((*b)[0]) | uint32((*b)[1])<<8 | uint32((*b)[2])<<16 | uint32((*b)[3])<<24
*b = (*b)[4:]
return v
}
func (b *readBuf) uint64() uint64 {
v := uint64((*b)[0]) | uint64((*b)[1])<<8 | uint64((*b)[2])<<16 | uint64((*b)[3])<<24 |
uint64((*b)[4])<<32 | uint64((*b)[5])<<40 | uint64((*b)[6])<<48 | uint64((*b)[7])<<56
*b = (*b)[8:]
return v
}
func (b *readBuf) bytes(n int) []byte {
v := (*b)[:n]
*b = (*b)[n:]
return v
}
func (b *readBuf) uvarint() uint64 {
var x uint64
var s uint
for i, n := range *b {
if n < 0x80 {
*b = (*b)[i+1:]
return x | uint64(n)<<s
}
x |= uint64(n&0x7f) << s
s += 7
}
// if we run out of bytes, just return 0
*b = (*b)[len(*b):]
return 0
}
// fileBlockHeader represents a file block in a RAR archive.
// Files may comprise one or more file blocks.
// Solid files retain decode tables and dictionary from previous solid files in the archive.
type fileBlockHeader struct {
first bool // first block in file
last bool // last block in file
arcSolid bool // archive is solid
dataOff int64 // offset to data for file block in archive volume
packedOff int64 // offset to data in packed file
blocknum int // number for current block in file
volnum int // archive volume number
winSize int64 // decode window size
hash func() hash.Hash // hash used for file checksum
hashKey []byte // optional hmac key to be used calculate file checksum
sum []byte // expected checksum for file contents
decVer int // decoder to use for file
key []byte // key for AES, non-empty if file encrypted
iv []byte // iv for AES, non-empty if file encrypted
errs []error // errors to return when trying to read file body
FileHeader
}
// archiveBlockReader returns the next fileBlockHeader in an archive volume.
type archiveBlockReader interface {
init(br *bufVolumeReader) (int, error) // init volume and returns optional (>=0) volume number
nextBlock(br *bufVolumeReader) (*fileBlockHeader, error) // reads the volume and returns the next fileBlockHeader
useOldNaming() bool
}
|