|
@@ -2,11 +2,11 @@ package vessel
|
|
|
|
|
|
import (
|
|
|
"archive/zip"
|
|
|
- "fmt"
|
|
|
"io"
|
|
|
"net/http"
|
|
|
"os"
|
|
|
- "path"
|
|
|
+ "path/filepath"
|
|
|
+ "time"
|
|
|
)
|
|
|
|
|
|
// File implements an http.File
|
|
@@ -22,7 +22,6 @@ var _ http.File = (*File)(nil)
|
|
|
func newFile(z *zip.File) (*File, error) {
|
|
|
r, err := z.Open()
|
|
|
if err != nil {
|
|
|
- fmt.Printf("Open: %s -> %w\n", z.Name, err)
|
|
|
return nil, err
|
|
|
}
|
|
|
return &File{
|
|
@@ -33,7 +32,7 @@ func newFile(z *zip.File) (*File, error) {
|
|
|
|
|
|
// Readdir implements http.File
|
|
|
func (f *File) Readdir(count int) ([]os.FileInfo, error) {
|
|
|
- fmt.Printf("read dir: %s\n", f.zip.Name)
|
|
|
+ log.Log("read dir: %s\n", f.zip.Name)
|
|
|
return nil, os.ErrPermission
|
|
|
}
|
|
|
|
|
@@ -61,6 +60,63 @@ func (f *File) Close() error {
|
|
|
return f.r.Close()
|
|
|
}
|
|
|
|
|
|
+// File implements an http.File
|
|
|
+type Dir struct {
|
|
|
+ name string
|
|
|
+ mode os.FileMode
|
|
|
+ files []os.FileInfo
|
|
|
+}
|
|
|
+
|
|
|
+// verify we implement the http.File interface
|
|
|
+var _ http.File = (*Dir)(nil)
|
|
|
+var _ os.FileInfo = (*Dir)(nil)
|
|
|
+
|
|
|
+// Readdir implements http.File
|
|
|
+func (f *Dir) Readdir(count int) ([]os.FileInfo, error) {
|
|
|
+ return f.files[:count], nil
|
|
|
+}
|
|
|
+
|
|
|
+// Stat implements http.File
|
|
|
+func (f *Dir) Stat() (os.FileInfo, error) {
|
|
|
+ return f, nil
|
|
|
+}
|
|
|
+
|
|
|
+// Seek implements io.Seeker
|
|
|
+func (f *Dir) Seek(offset int64, whence int) (int64, error) {
|
|
|
+ return 0, os.ErrInvalid
|
|
|
+}
|
|
|
+
|
|
|
+// Read implements io.Reader
|
|
|
+func (f *Dir) Read(p []byte) (n int, err error) {
|
|
|
+ return 0, io.EOF
|
|
|
+}
|
|
|
+
|
|
|
+// Close implements io.Closer
|
|
|
+func (f *Dir) Close() error {
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
+// implement file info interface as well
|
|
|
+func (f *Dir) Name() string {
|
|
|
+ return f.name
|
|
|
+}
|
|
|
+
|
|
|
+func (f *Dir) Size() int64 {
|
|
|
+ return 0
|
|
|
+}
|
|
|
+func (f *Dir) Mode() os.FileMode {
|
|
|
+ return f.mode
|
|
|
+}
|
|
|
+func (f *Dir) ModTime() time.Time {
|
|
|
+ return time.Now()
|
|
|
+}
|
|
|
+func (f *Dir) IsDir() bool {
|
|
|
+ return true
|
|
|
+}
|
|
|
+func (f *Dir) Sys() interface{} {
|
|
|
+ return nil
|
|
|
+}
|
|
|
+
|
|
|
// FileSystem implements an http filesystem access to the bundle
|
|
|
type FileSystem struct {
|
|
|
b *Bundle
|
|
@@ -69,24 +125,80 @@ type FileSystem struct {
|
|
|
// verify we implement the http.FileSystem interface
|
|
|
var _ http.FileSystem = (*FileSystem)(nil)
|
|
|
|
|
|
-// Open opens a file in the filesystem
|
|
|
-func (f *FileSystem) Open(name string) (http.File, error) {
|
|
|
+func (f *FileSystem) get(name string) (*zip.File, error) {
|
|
|
zr, err := zip.NewReader(f.b, f.b.Size())
|
|
|
if err != nil {
|
|
|
return nil, os.ErrNotExist
|
|
|
}
|
|
|
|
|
|
- name = path.Join(zr.File[0].Name, name)
|
|
|
- fmt.Printf("Open: %s\n", name)
|
|
|
-
|
|
|
for idx := range zr.File {
|
|
|
z := zr.File[idx]
|
|
|
if z.Name == name {
|
|
|
- if !z.FileInfo().IsDir() {
|
|
|
- return newFile(z)
|
|
|
- }
|
|
|
- return nil, os.ErrNotExist
|
|
|
+ return z, nil
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return nil, os.ErrNotExist
|
|
|
+
|
|
|
+}
|
|
|
+
|
|
|
+// Open opens a file in the filesystem
|
|
|
+func (f *FileSystem) Open(name string) (http.File, error) {
|
|
|
+ log.Log("vessel.FileSystem Open: %s\n", name)
|
|
|
+ if filepath.Dir(name) == name {
|
|
|
+ // directory fetch
|
|
|
+ files, err := f.Dir(name)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
}
|
|
|
+
|
|
|
+ return &Dir{
|
|
|
+ name: name,
|
|
|
+ mode: os.ModeDir,
|
|
|
+ files: files,
|
|
|
+ }, nil
|
|
|
}
|
|
|
+
|
|
|
+ z, err := f.get(name)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+
|
|
|
+ if !z.FileInfo().IsDir() {
|
|
|
+ return newFile(z)
|
|
|
+ }
|
|
|
+
|
|
|
return nil, os.ErrNotExist
|
|
|
}
|
|
|
+
|
|
|
+func (f *FileSystem) Stat(name string) (os.FileInfo, error) {
|
|
|
+ z, err := f.get(name)
|
|
|
+ if err != nil {
|
|
|
+ return nil, err
|
|
|
+ }
|
|
|
+ return z.FileInfo(), nil
|
|
|
+}
|
|
|
+
|
|
|
+func (f *FileSystem) Dir(path string) ([]os.FileInfo, error) {
|
|
|
+ zr, err := zip.NewReader(f.b, f.b.Size())
|
|
|
+ if err != nil {
|
|
|
+ return nil, os.ErrNotExist
|
|
|
+ }
|
|
|
+
|
|
|
+ found := false
|
|
|
+ ls := make([]os.FileInfo, 0)
|
|
|
+ for idx := range zr.File {
|
|
|
+ z := zr.File[idx]
|
|
|
+
|
|
|
+ d := filepath.Dir(z.Name)
|
|
|
+ if d == path && !z.FileInfo().IsDir() {
|
|
|
+ found = true
|
|
|
+ ls = append(ls, z.FileInfo())
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if !found {
|
|
|
+ return nil, os.ErrNotExist
|
|
|
+ }
|
|
|
+
|
|
|
+ return ls, nil
|
|
|
+}
|