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 }