69 lines
1.6 KiB
Go
69 lines
1.6 KiB
Go
package archive
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"io"
|
|
|
|
"git.kmsign.ru/royalcat/tstor/pkg/ioutils"
|
|
"git.kmsign.ru/royalcat/tstor/src/vfs"
|
|
"github.com/nwaples/rardecode/v2"
|
|
"github.com/royalcat/ctxio"
|
|
)
|
|
|
|
var _ archiveLoader = RarLoader
|
|
|
|
func RarLoader(ctx context.Context, archivePath string, f vfs.File, size int64) (map[string]fileEntry, error) {
|
|
hash, err := vfs.FileHash(ctx, f)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
reader := ioutils.WrapIoReadSeeker(ctx, f, size)
|
|
|
|
r, err := rardecode.NewReader(reader)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
out := make(map[string]fileEntry)
|
|
for {
|
|
header, err := r.Next()
|
|
if err == io.EOF {
|
|
break
|
|
}
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
name := header.Name
|
|
af := func(ctx context.Context) (ctxio.ReadCloser, error) {
|
|
reader := ioutils.WrapIoReadSeeker(ctx, f, size)
|
|
r, err := rardecode.NewReader(reader)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
for header, err := r.Next(); err != io.EOF; header, err = r.Next() {
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if header.Name == name {
|
|
return ctxio.NopCloser(ctxio.WrapIoReader(r)), nil
|
|
}
|
|
}
|
|
return nil, fmt.Errorf("file with name '%s' not found", name)
|
|
}
|
|
|
|
rr := newRandomReaderFromLinear(archiveFileIndex{archiveHash: hash, filename: header.Name}, header.UnPackedSize, af)
|
|
|
|
out[vfs.AbsPath(header.Name)] = fileEntry{
|
|
FileInfo: vfs.NewFileInfo(header.Name, header.UnPackedSize, header.ModificationTime),
|
|
open: func(ctx context.Context) (vfs.File, error) {
|
|
return newArchiveFile(header.Name, header.UnPackedSize, rr), nil
|
|
},
|
|
}
|
|
}
|
|
|
|
return out, nil
|
|
}
|