mirror of
https://github.com/bitechdev/ResolveSpec.git
synced 2025-12-31 17:28:58 +00:00
113 lines
1.9 KiB
Go
113 lines
1.9 KiB
Go
package zipfs
|
|
|
|
import (
|
|
"archive/zip"
|
|
"fmt"
|
|
"io"
|
|
"io/fs"
|
|
"os"
|
|
)
|
|
|
|
type ZipFS struct {
|
|
*zip.Reader
|
|
}
|
|
|
|
func NewZipFS(r *zip.Reader) *ZipFS {
|
|
return &ZipFS{r}
|
|
}
|
|
|
|
func (z *ZipFS) Open(name string) (fs.File, error) {
|
|
for _, f := range z.File {
|
|
if f.Name == name {
|
|
rc, err := f.Open()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return &ZipFile{f, rc, 0}, nil
|
|
}
|
|
}
|
|
return nil, os.ErrNotExist
|
|
}
|
|
|
|
type ZipFile struct {
|
|
*zip.File
|
|
rc io.ReadCloser
|
|
offset int64
|
|
}
|
|
|
|
func (f *ZipFile) Stat() (fs.FileInfo, error) {
|
|
if f.File != nil {
|
|
return f.FileInfo(), nil
|
|
}
|
|
return nil, fmt.Errorf("no file")
|
|
}
|
|
|
|
func (f *ZipFile) Close() error {
|
|
if f.rc != nil {
|
|
return f.rc.Close()
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (f *ZipFile) Read(b []byte) (int, error) {
|
|
if f.rc == nil {
|
|
var err error
|
|
f.rc, err = f.Open()
|
|
if err != nil {
|
|
return 0, err
|
|
}
|
|
}
|
|
n, err := f.rc.Read(b)
|
|
f.offset += int64(n)
|
|
if err == io.EOF {
|
|
f.rc.Close()
|
|
f.rc = nil
|
|
}
|
|
return n, err
|
|
|
|
}
|
|
func (f *ZipFile) Seek(offset int64, whence int) (int64, error) {
|
|
if f.rc != nil {
|
|
f.rc.Close()
|
|
f.rc = nil
|
|
}
|
|
switch whence {
|
|
case io.SeekStart:
|
|
if offset < 0 {
|
|
return 0, &fs.PathError{Op: "seek", Path: f.Name, Err: fmt.Errorf("negative position")}
|
|
}
|
|
f.offset = offset
|
|
case io.SeekCurrent:
|
|
if f.offset+offset < 0 {
|
|
return 0, &fs.PathError{Op: "seek", Path: f.Name, Err: fmt.Errorf("negative position")}
|
|
}
|
|
f.offset += offset
|
|
case io.SeekEnd:
|
|
size := int64(f.UncompressedSize64)
|
|
if size+offset < 0 {
|
|
return 0, &fs.PathError{Op: "seek", Path: f.Name, Err: fmt.Errorf("negative position")}
|
|
}
|
|
f.offset = size + offset
|
|
}
|
|
return f.offset, nil
|
|
}
|
|
|
|
/*
|
|
func main() {
|
|
r, err := zip.OpenReader("path/to/your.zip")
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer r.Close()
|
|
|
|
fs := NewZipFS(&r.Reader)
|
|
file, err := fs.Open(path.Join("path", "to", "file"))
|
|
if err != nil {
|
|
log.Fatal(err)
|
|
}
|
|
defer file.Close()
|
|
|
|
// Now you can use 'file' as a fs.File
|
|
}
|
|
*/
|