mattermost-community-enterp.../vendor/github.com/nwaples/rardecode/v2/bufio.go
Claude ec1f89217a Merge: Complete Mattermost Server with Community Enterprise
Full Mattermost server source with integrated Community Enterprise features.
Includes vendor directory for offline/air-gapped builds.

Structure:
- enterprise-impl/: Enterprise feature implementations
- enterprise-community/: Init files that register implementations
- enterprise/: Bridge imports (community_imports.go)
- vendor/: All dependencies for offline builds

Build (online):
  go build ./cmd/mattermost

Build (offline/air-gapped):
  go build -mod=vendor ./cmd/mattermost

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
2025-12-17 23:59:07 +09:00

260 lines
4.5 KiB
Go

package rardecode
import (
"bytes"
"errors"
"io"
"io/fs"
)
const (
maxSfxSize = 0x100000 // maximum number of bytes to read when searching for RAR signature
sigPrefix = "Rar!\x1A\x07"
sigPrefixLen = len(sigPrefix)
maxEmptyReads = 100
minBufSize = 32
defaultBufSize = 4096
)
var (
ErrNoSig = errors.New("rardecode: RAR signature not found")
ErrNegativeRead = errors.New("rardecode: negative read from Reader")
)
type bufVolumeReader struct {
r io.Reader
sr io.Seeker
buf []byte
i int
n int
off int64
err error
ver int
}
func (br *bufVolumeReader) readErr() error {
err := br.err
br.err = nil
return err
}
func (br *bufVolumeReader) fill() error {
if br.err != nil {
return br.readErr()
}
br.i = 0
for i := 0; i < maxEmptyReads; i++ {
br.n, br.err = br.r.Read(br.buf)
if br.n > 0 {
return nil
}
if br.n < 0 {
return ErrNegativeRead
}
if br.err != nil {
return br.readErr()
}
}
return io.ErrNoProgress
}
func (br *bufVolumeReader) canSeek() bool {
return br.sr != nil
}
func (br *bufVolumeReader) seek(offset int64) error {
if br.sr == nil {
return fs.ErrInvalid
}
start := br.off - int64(br.i)
end := start + int64(br.n)
if offset >= start && offset <= end {
diff := offset - br.off
br.off += diff
br.i += int(diff)
return nil
}
_, err := br.sr.Seek(offset, io.SeekStart)
if err != nil {
return err
}
br.i = 0
br.n = 0
br.off = offset
return nil
}
func (br *bufVolumeReader) Read(p []byte) (int, error) {
if br.i == br.n {
err := br.fill()
if err != nil {
return 0, err
}
}
n := copy(p, br.buf[br.i:br.n])
br.i += n
br.off += int64(n)
return n, nil
}
func (br *bufVolumeReader) ReadByte() (byte, error) {
if br.i == br.n {
err := br.fill()
if err != nil {
return 0, err
}
}
c := br.buf[br.i]
br.i++
br.off++
return c, nil
}
func (br *bufVolumeReader) Discard(n int64) error {
buffered := int64(br.n - br.i)
if buffered >= n {
br.i += int(n)
br.off += n
return nil
}
// empty buffer
n -= buffered
br.i = 0
br.n = 0
br.off += buffered
// try seek
if sr, ok := br.r.(io.Seeker); ok {
_, err := sr.Seek(n, io.SeekCurrent)
if err != nil {
return err
}
br.off += n
return nil
}
// copy to discard writer
written, err := io.CopyN(io.Discard, br.r, n)
br.off += written
return err
}
func (br *bufVolumeReader) writeToN(w io.Writer, n int64) (int64, error) {
if n == 0 {
return 0, nil
}
var err error
todo := n
startOffset := br.off
for todo != 0 && err == nil {
if br.i == br.n {
err = br.fill()
if err != nil {
break
}
}
buf := br.buf[br.i:br.n]
if todo > 0 && todo < int64(len(buf)) {
buf = buf[:todo]
}
var l int
l, err = w.Write(buf)
br.i += l
br.off += int64(l)
if todo > 0 {
todo -= int64(l)
}
}
if todo < 0 && err == io.EOF {
err = nil
}
return br.off - startOffset, nil
}
// findSig searches for the RAR signature and version at the beginning of a file.
// It searches no more than maxSfxSize bytes from the file start.
func (br *bufVolumeReader) findSig() (int, error) {
for br.off <= maxSfxSize {
if br.i == br.n {
err := br.fill()
if err != nil {
return 0, err
}
}
n := bytes.IndexByte(br.buf[br.i:br.n], sigPrefix[0])
if n < 0 {
br.off += int64(n)
continue
}
br.i += n
br.off += int64(n)
// ensure enough bytes available in buffer
buffered := br.n - br.i
if buffered < sigPrefixLen+2 {
br.n = copy(br.buf, br.buf[br.i:br.n])
br.i = 0
l, err := io.ReadAtLeast(br.r, br.buf[br.n:], sigPrefixLen+2-buffered)
br.n += l
if err != nil {
if errors.Is(err, io.ErrUnexpectedEOF) {
err = ErrNoSig
}
return 0, err
}
}
if !bytes.HasPrefix(br.buf[br.i:br.n], []byte(sigPrefix)) {
br.i++
br.off++
continue
}
br.i += sigPrefixLen
br.off += int64(sigPrefixLen)
ver := int(br.buf[br.i])
if ver == 0 {
br.i++
br.off++
} else if br.buf[br.i+1] == 0 {
br.i += 2
br.off += 2
} else {
continue
}
return ver, nil
}
return 0, ErrNoSig
}
func (br *bufVolumeReader) Reset(r io.Reader) error {
br.r = r
br.sr, _ = r.(io.Seeker)
br.i = 0
br.n = 0
br.off = 0
ver, err := br.findSig()
if err != nil {
if errors.Is(err, io.EOF) {
return ErrNoSig
}
return err
}
br.ver = ver
return nil
}
func newBufVolumeReader(r io.Reader, size int) (*bufVolumeReader, error) {
if size == 0 {
size = defaultBufSize
} else {
size = max(minBufSize, size)
}
br := &bufVolumeReader{
buf: make([]byte, size),
}
err := br.Reset(r)
if err != nil {
return nil, err
}
return br, nil
}