wip
This commit is contained in:
parent
2cefb9db98
commit
b97dcc8d8f
52 changed files with 7570 additions and 555 deletions
src/host/vfs
|
@ -8,7 +8,6 @@ import (
|
|||
"path"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"sync"
|
||||
|
||||
"git.kmsign.ru/royalcat/tstor/src/iio"
|
||||
"github.com/bodgit/sevenzip"
|
||||
|
@ -17,34 +16,79 @@ import (
|
|||
|
||||
var ArchiveFactories = map[string]FsFactory{
|
||||
".zip": func(f File) (Filesystem, error) {
|
||||
return NewArchive(f, f.Size(), ZipLoader), nil
|
||||
stat, err := f.Stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewArchive(stat.Name(), f, stat.Size(), ZipLoader), nil
|
||||
},
|
||||
".rar": func(f File) (Filesystem, error) {
|
||||
return NewArchive(f, f.Size(), RarLoader), nil
|
||||
stat, err := f.Stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewArchive(stat.Name(), f, stat.Size(), RarLoader), nil
|
||||
},
|
||||
".7z": func(f File) (Filesystem, error) {
|
||||
return NewArchive(f, f.Size(), SevenZipLoader), nil
|
||||
stat, err := f.Stat()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return NewArchive(stat.Name(), f, stat.Size(), SevenZipLoader), nil
|
||||
},
|
||||
}
|
||||
|
||||
type ArchiveLoader func(r iio.Reader, size int64) (map[string]*archiveFile, error)
|
||||
type archiveLoader func(r iio.Reader, size int64) (map[string]*archiveFile, error)
|
||||
|
||||
var _ Filesystem = &archive{}
|
||||
|
||||
type archive struct {
|
||||
name string
|
||||
|
||||
r iio.Reader
|
||||
|
||||
size int64
|
||||
|
||||
files func() (map[string]*archiveFile, error)
|
||||
files func() (map[string]File, error)
|
||||
}
|
||||
|
||||
func NewArchive(r iio.Reader, size int64, loader ArchiveLoader) *archive {
|
||||
func NewArchive(name string, r iio.Reader, size int64, loader archiveLoader) *archive {
|
||||
return &archive{
|
||||
name: name,
|
||||
r: r,
|
||||
size: size,
|
||||
files: sync.OnceValues(func() (map[string]*archiveFile, error) {
|
||||
return loader(r, size)
|
||||
files: OnceValueWOErr(func() (map[string]File, error) {
|
||||
zipFiles, err := loader(r, size)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
// TODO make optional
|
||||
singleDir := true
|
||||
for k := range zipFiles {
|
||||
if !strings.HasPrefix(k, "/"+name+"/") {
|
||||
singleDir = false
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
files := make(map[string]File, len(zipFiles))
|
||||
for k, v := range zipFiles {
|
||||
// TODO make optional
|
||||
if strings.Contains(k, "/__MACOSX/") {
|
||||
continue
|
||||
}
|
||||
|
||||
if singleDir {
|
||||
k, _ = strings.CutPrefix(k, "/"+name)
|
||||
}
|
||||
|
||||
files[k] = v
|
||||
}
|
||||
|
||||
// FIXME
|
||||
files["/.forcegallery"] = NewMemoryFile(".forcegallery", []byte{})
|
||||
|
||||
return files, nil
|
||||
}),
|
||||
}
|
||||
}
|
||||
|
@ -80,7 +124,7 @@ func (afs *archive) Stat(filename string) (fs.FileInfo, error) {
|
|||
}
|
||||
|
||||
if file, ok := files[filename]; ok {
|
||||
return newFileInfo(path.Base(filename), file.Size()), nil
|
||||
return file.Stat()
|
||||
}
|
||||
|
||||
for p, _ := range files {
|
||||
|
@ -90,7 +134,6 @@ func (afs *archive) Stat(filename string) (fs.FileInfo, error) {
|
|||
}
|
||||
|
||||
return nil, ErrNotExist
|
||||
|
||||
}
|
||||
|
||||
var _ File = &archiveFile{}
|
||||
|
@ -162,7 +205,7 @@ func (d *archiveFile) ReadAt(p []byte, off int64) (n int, err error) {
|
|||
return d.reader.ReadAt(p, off)
|
||||
}
|
||||
|
||||
var _ ArchiveLoader = ZipLoader
|
||||
var _ archiveLoader = ZipLoader
|
||||
|
||||
func ZipLoader(reader iio.Reader, size int64) (map[string]*archiveFile, error) {
|
||||
zr, err := zip.NewReader(reader, size)
|
||||
|
@ -171,14 +214,14 @@ func ZipLoader(reader iio.Reader, size int64) (map[string]*archiveFile, error) {
|
|||
}
|
||||
|
||||
out := make(map[string]*archiveFile)
|
||||
for _, f := range zr.File {
|
||||
f := f
|
||||
if f.FileInfo().IsDir() {
|
||||
for i := range zr.File {
|
||||
zipFile := zr.File[i]
|
||||
if zipFile.FileInfo().IsDir() {
|
||||
continue
|
||||
}
|
||||
|
||||
rf := func() (iio.Reader, error) {
|
||||
zr, err := f.Open()
|
||||
zr, err := zipFile.Open()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
@ -186,16 +229,13 @@ func ZipLoader(reader iio.Reader, size int64) (map[string]*archiveFile, error) {
|
|||
return iio.NewDiskTeeReader(zr)
|
||||
}
|
||||
|
||||
n := filepath.Join(string(os.PathSeparator), f.Name)
|
||||
af := NewArchiveFile(f.Name, rf, f.FileInfo().Size())
|
||||
|
||||
out[n] = af
|
||||
out[AbsPath(zipFile.Name)] = NewArchiveFile(zipFile.Name, rf, zipFile.FileInfo().Size())
|
||||
}
|
||||
|
||||
return out, nil
|
||||
}
|
||||
|
||||
var _ ArchiveLoader = SevenZipLoader
|
||||
var _ archiveLoader = SevenZipLoader
|
||||
|
||||
func SevenZipLoader(reader iio.Reader, size int64) (map[string]*archiveFile, error) {
|
||||
r, err := sevenzip.NewReader(reader, size)
|
||||
|
@ -228,7 +268,7 @@ func SevenZipLoader(reader iio.Reader, size int64) (map[string]*archiveFile, err
|
|||
return out, nil
|
||||
}
|
||||
|
||||
var _ ArchiveLoader = RarLoader
|
||||
var _ archiveLoader = RarLoader
|
||||
|
||||
func RarLoader(reader iio.Reader, size int64) (map[string]*archiveFile, error) {
|
||||
r, err := rardecode.NewReader(iio.NewSeekerWrapper(reader, size))
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue