tstor/daemons/archive/rar.go
royalcat 832f5b9710
Some checks failed
docker / build-docker (push) Has been cancelled
wip
2025-01-20 05:18:15 +03:00

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
}