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

63 lines
1.3 KiB
Go

package archive
import (
"archive/zip"
"context"
"fmt"
"git.kmsign.ru/royalcat/tstor/src/vfs"
"github.com/royalcat/ctxio"
)
var _ archiveLoader = ZipLoader
func ZipLoader(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 := ctxio.IoReaderAt(ctx, f)
zr, err := zip.NewReader(reader, size)
if err != nil {
return nil, err
}
out := make(map[string]fileEntry)
for i := range zr.File {
zipFile := zr.File[i]
if zipFile.FileInfo().IsDir() {
continue
}
i := i
af := func(ctx context.Context) (ctxio.ReadCloser, error) {
reader := ctxio.IoReaderAt(ctx, f)
zr, err := zip.NewReader(reader, size)
if err != nil {
return nil, fmt.Errorf("failed to create zip reader: %w", err)
}
rc, err := zr.File[i].Open()
if err != nil {
return nil, fmt.Errorf("failed to open file in zip archive: %w", err)
}
return ctxio.WrapIoReadCloser(rc), nil
}
info := zipFile.FileInfo()
rr := newRandomReaderFromLinear(archiveFileIndex{archiveHash: hash, filename: zipFile.Name}, info.Size(), af)
out[vfs.AbsPath(zipFile.Name)] = fileEntry{
FileInfo: info,
open: func(ctx context.Context) (vfs.File, error) {
return newArchiveFile(info.Name(), info.Size(), rr), nil
},
}
}
return out, nil
}