Skip to content

Commit 1c32663

Browse files
committed
split volume into readerVolume and fileVolume
1 parent f9a53be commit 1c32663

File tree

5 files changed

+100
-80
lines changed

5 files changed

+100
-80
lines changed

archive.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ var (
2424
ErrDecoderOutOfData = errors.New("rardecode: decoder expected more data than is in packed file")
2525
ErrArchiveEncrypted = errors.New("rardecode: archive encrypted, password required")
2626
ErrArchivedFileEncrypted = errors.New("rardecode: archived files encrypted, password required")
27-
errVolumeEnd = errors.New("rardecode: archive volume end")
27+
ErrMultiVolume = errors.New("rardecode: multi-volume archive continues in next file")
2828
errVolumeOrArchiveEnd = errors.New("rardecode: archive or volume end")
2929
)
3030

archive15.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -467,7 +467,7 @@ func (a *archive15) nextBlock(br *bufVolumeReader) (*fileBlockHeader, error) {
467467
if h.flags&endArcNotLast == 0 || !a.multi {
468468
return nil, io.EOF
469469
}
470-
return nil, errVolumeEnd
470+
return nil, ErrMultiVolume
471471
default:
472472
if h.dataSize > 0 {
473473
err = br.Discard(h.dataSize) // skip over block data

archive50.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ func (a *archive50) nextBlock(br *bufVolumeReader) (*fileBlockHeader, error) {
600600
if flags&endArc5NotLast == 0 || !a.multi {
601601
return nil, io.EOF
602602
}
603-
return nil, errVolumeEnd
603+
return nil, ErrMultiVolume
604604
default:
605605
if h.dataSize > 0 {
606606
err = br.Discard(h.dataSize) // skip over block data

reader.go

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,7 @@ func newFileBlockList(blocks ...*fileBlockHeader) *fileBlockList {
164164

165165
// packedFileReader provides sequential access to packed files in a RAR archive.
166166
type packedFileReader struct {
167-
v *volume
167+
v volume
168168
h *fileBlockHeader // current file header
169169
dr *decodeReader
170170
blocks *fileBlockList
@@ -178,7 +178,12 @@ func (f *packedFileReader) init(blocks *fileBlockList) error {
178178
return nil
179179
}
180180

181-
func (f *packedFileReader) Close() error { return f.v.Close() }
181+
func (f *packedFileReader) Close() error {
182+
if cl, ok := f.v.(io.Closer); ok {
183+
return cl.Close()
184+
}
185+
return nil
186+
}
182187

183188
func (f *packedFileReader) Stat() (fs.FileInfo, error) {
184189
if f.h == nil {
@@ -202,6 +207,8 @@ func (f *packedFileReader) nextBlock() error {
202207
if err == io.EOF {
203208
// archive ended, but file hasn't
204209
return ErrUnexpectedArcEnd
210+
} else if err == errVolumeOrArchiveEnd {
211+
return ErrMultiVolume
205212
}
206213
return err
207214
}
@@ -227,6 +234,9 @@ func (f *packedFileReader) nextFile() (*fileBlockList, error) {
227234
}
228235
h, err := f.v.nextBlock() // get next file block
229236
if err != nil {
237+
if err == errVolumeOrArchiveEnd {
238+
err = io.EOF
239+
}
230240
return nil, err
231241
}
232242
if !h.first {
@@ -311,7 +321,7 @@ func (pr *packedFileReader) newArchiveFile(blocks *fileBlockList) (archiveFile,
311321
return r, nil
312322
}
313323

314-
func newPackedFileReader(v *volume, opts *options) archiveFile {
324+
func newPackedFileReader(v volume, opts *options) archiveFile {
315325
return &packedFileReader{v: v, opt: opts}
316326
}
317327

@@ -442,7 +452,7 @@ func (r *Reader) Next() (*FileHeader, error) {
442452
return &h.FileHeader, nil
443453
}
444454

445-
func newReader(v *volume, opts *options) Reader {
455+
func newReader(v volume, opts *options) Reader {
446456
pr := newPackedFileReader(v, opts)
447457
return Reader{f: pr}
448458
}

volume.go

Lines changed: 83 additions & 73 deletions
Original file line numberDiff line numberDiff line change
@@ -78,20 +78,21 @@ func getOptions(opts []Option) *options {
7878
return opt
7979
}
8080

81-
// volume extends a archiveBlockReader to be used across multiple
82-
// files in a multi-volume archive
83-
type volume struct {
81+
type volume interface {
82+
byteReader
83+
nextBlock() (*fileBlockHeader, error)
84+
}
85+
86+
type readerVolume struct {
8487
br *bufVolumeReader // buffered reader for current volume file
8588
n int64 // bytes left in current block
8689
num int // current volume number
8790
ver int // archive file format version
88-
cl io.Closer
8991
arc archiveBlockReader
90-
vm *volumeManager
9192
opt *options
9293
}
9394

94-
func (v *volume) init(r io.Reader, volnum int) error {
95+
func (v *readerVolume) init(r io.Reader, volnum int) error {
9596
var err error
9697
if v.br == nil {
9798
v.br, err = newBufVolumeReader(r, v.opt.bsize)
@@ -125,73 +126,25 @@ func (v *volume) init(r io.Reader, volnum int) error {
125126
return nil
126127
}
127128

128-
func (v *volume) Close() error {
129-
if v.cl != nil {
130-
err := v.cl.Close()
131-
v.cl = nil
132-
return err
133-
}
134-
return nil
135-
}
136-
137-
func (v *volume) open(volnum int) error {
138-
if v.vm == nil {
139-
return ErrFileNameRequired
140-
}
141-
err := v.Close()
142-
if err != nil {
143-
return err
144-
}
145-
f, err := v.vm.openVolumeFile(volnum)
146-
if err != nil {
147-
return err
148-
}
149-
err = v.init(f, volnum)
150-
if err != nil {
151-
f.Close()
152-
return err
153-
}
154-
v.cl = f
155-
return nil
156-
}
157-
158-
func (v *volume) nextBlock() (*fileBlockHeader, error) {
129+
func (v *readerVolume) nextBlock() (*fileBlockHeader, error) {
159130
if v.n > 0 {
160131
err := v.br.Discard(v.n)
161132
if err != nil {
162133
return nil, err
163134
}
135+
v.n = 0
164136
}
165-
for {
166-
f, err := v.arc.nextBlock(v.br)
167-
if err == nil {
168-
f.volnum = v.num
169-
f.dataOff = v.br.off
170-
v.n = f.PackedSize
171-
return f, nil
172-
}
173-
nextVol := v.num + 1
174-
if err == errVolumeEnd {
175-
err = v.open(nextVol)
176-
if err != nil {
177-
return nil, err
178-
}
179-
} else if err == errVolumeOrArchiveEnd {
180-
err = v.open(nextVol)
181-
if err != nil {
182-
// new volume doesnt exist, assume end of archive
183-
if errors.Is(err, fs.ErrNotExist) {
184-
return nil, io.EOF
185-
}
186-
return nil, err
187-
}
188-
} else {
189-
return nil, err
190-
}
137+
f, err := v.arc.nextBlock(v.br)
138+
if err != nil {
139+
return nil, err
191140
}
141+
f.volnum = v.num
142+
f.dataOff = v.br.off
143+
v.n = f.PackedSize
144+
return f, nil
192145
}
193146

194-
func (v *volume) Read(p []byte) (int, error) {
147+
func (v *readerVolume) Read(p []byte) (int, error) {
195148
if v.n == 0 {
196149
return 0, io.EOF
197150
}
@@ -206,7 +159,7 @@ func (v *volume) Read(p []byte) (int, error) {
206159
return n, err
207160
}
208161

209-
func (v *volume) ReadByte() (byte, error) {
162+
func (v *readerVolume) ReadByte() (byte, error) {
210163
if v.n == 0 {
211164
return 0, io.EOF
212165
}
@@ -219,15 +172,69 @@ func (v *volume) ReadByte() (byte, error) {
219172
return b, err
220173
}
221174

222-
func newVolume(r io.Reader, opt *options, volnum int) (*volume, error) {
223-
v := &volume{opt: opt}
175+
func newVolume(r io.Reader, opt *options, volnum int) (*readerVolume, error) {
176+
v := &readerVolume{opt: opt}
224177
err := v.init(r, volnum)
225178
if err != nil {
226179
return nil, err
227180
}
228181
return v, nil
229182
}
230183

184+
type fileVolume struct {
185+
*readerVolume
186+
f fs.File
187+
vm *volumeManager
188+
}
189+
190+
func (v *fileVolume) Close() error { return v.f.Close() }
191+
192+
func (v *fileVolume) open(volnum int) error {
193+
err := v.Close()
194+
if err != nil {
195+
return err
196+
}
197+
f, err := v.vm.openVolumeFile(volnum)
198+
if err != nil {
199+
return err
200+
}
201+
err = v.readerVolume.init(f, volnum)
202+
if err != nil {
203+
f.Close()
204+
return err
205+
}
206+
v.f = f
207+
return nil
208+
}
209+
210+
func (v *fileVolume) openNext() error { return v.open(v.num + 1) }
211+
212+
func (v *fileVolume) nextBlock() (*fileBlockHeader, error) {
213+
for {
214+
h, err := v.readerVolume.nextBlock()
215+
if err == nil {
216+
return h, nil
217+
}
218+
if err == ErrMultiVolume {
219+
err = v.openNext()
220+
if err != nil {
221+
return nil, err
222+
}
223+
} else if err == errVolumeOrArchiveEnd {
224+
err = v.openNext()
225+
if err != nil {
226+
// new volume doesnt exist, assume end of archive
227+
if errors.Is(err, fs.ErrNotExist) {
228+
return nil, io.EOF
229+
}
230+
return nil, err
231+
}
232+
} else {
233+
return nil, err
234+
}
235+
}
236+
}
237+
231238
func nextNewVolName(file string) string {
232239
var inDigit bool
233240
var m []int
@@ -385,7 +392,7 @@ func (vm *volumeManager) openVolumeFile(volnum int) (fs.File, error) {
385392
return vm.opt.fs.Open(vm.dir + file)
386393
}
387394

388-
func (vm *volumeManager) newVolume(volnum int) (*volume, error) {
395+
func (vm *volumeManager) newVolume(volnum int) (*fileVolume, error) {
389396
f, err := vm.openVolumeFile(volnum)
390397
if err != nil {
391398
return nil, err
@@ -395,12 +402,15 @@ func (vm *volumeManager) newVolume(volnum int) (*volume, error) {
395402
f.Close()
396403
return nil, err
397404
}
398-
v.cl = f
399-
v.vm = vm
400-
return v, nil
405+
mv := &fileVolume{
406+
readerVolume: v,
407+
f: f,
408+
vm: vm,
409+
}
410+
return mv, nil
401411
}
402412

403-
func (vm *volumeManager) openBlockOffset(h *fileBlockHeader, offset int64) (*volume, error) {
413+
func (vm *volumeManager) openBlockOffset(h *fileBlockHeader, offset int64) (*fileVolume, error) {
404414
v, err := vm.newVolume(h.volnum)
405415
if err != nil {
406416
return nil, err
@@ -436,7 +446,7 @@ func (vm *volumeManager) openArchiveFile(blocks *fileBlockList) (archiveFile, er
436446
return f, nil
437447
}
438448

439-
func openVolume(filename string, opts *options) (*volume, error) {
449+
func openVolume(filename string, opts *options) (*fileVolume, error) {
440450
dir, file := filepath.Split(filename)
441451
vm := &volumeManager{
442452
dir: dir,

0 commit comments

Comments
 (0)