github.com/bpfs/defs@v0.0.15/afero/zipfs/fs.go (about) 1 package zipfs 2 3 import ( 4 "archive/zip" 5 "os" 6 "path/filepath" 7 "syscall" 8 "time" 9 10 "github.com/bpfs/defs/afero" 11 ) 12 13 type Fs struct { 14 r *zip.Reader 15 files map[string]map[string]*zip.File 16 } 17 18 func splitpath(name string) (dir, file string) { 19 name = filepath.ToSlash(name) 20 if len(name) == 0 || name[0] != '/' { 21 name = "/" + name 22 } 23 name = filepath.Clean(name) 24 dir, file = filepath.Split(name) 25 dir = filepath.Clean(dir) 26 return 27 } 28 29 func New(r *zip.Reader) afero.Fs { 30 fs := &Fs{r: r, files: make(map[string]map[string]*zip.File)} 31 for _, file := range r.File { 32 d, f := splitpath(file.Name) 33 if _, ok := fs.files[d]; !ok { 34 fs.files[d] = make(map[string]*zip.File) 35 } 36 if _, ok := fs.files[d][f]; !ok { 37 fs.files[d][f] = file 38 } 39 if file.FileInfo().IsDir() { 40 dirname := filepath.Join(d, f) 41 if _, ok := fs.files[dirname]; !ok { 42 fs.files[dirname] = make(map[string]*zip.File) 43 } 44 } 45 } 46 return fs 47 } 48 49 func (fs *Fs) Create(name string) (afero.File, error) { return nil, syscall.EPERM } 50 51 func (fs *Fs) Mkdir(name string, perm os.FileMode) error { return syscall.EPERM } 52 53 func (fs *Fs) MkdirAll(path string, perm os.FileMode) error { return syscall.EPERM } 54 55 func (fs *Fs) Open(name string) (afero.File, error) { 56 d, f := splitpath(name) 57 if f == "" { 58 return &File{fs: fs, isdir: true}, nil 59 } 60 if _, ok := fs.files[d]; !ok { 61 return nil, &os.PathError{Op: "stat", Path: name, Err: syscall.ENOENT} 62 } 63 file, ok := fs.files[d][f] 64 if !ok { 65 return nil, &os.PathError{Op: "stat", Path: name, Err: syscall.ENOENT} 66 } 67 return &File{fs: fs, zipfile: file, isdir: file.FileInfo().IsDir()}, nil 68 } 69 70 func (fs *Fs) OpenFile(name string, flag int, perm os.FileMode) (afero.File, error) { 71 if flag != os.O_RDONLY { 72 return nil, syscall.EPERM 73 } 74 return fs.Open(name) 75 } 76 77 func (fs *Fs) Remove(name string) error { return syscall.EPERM } 78 79 func (fs *Fs) RemoveAll(path string) error { return syscall.EPERM } 80 81 func (fs *Fs) Rename(oldname, newname string) error { return syscall.EPERM } 82 83 type pseudoRoot struct{} 84 85 func (p *pseudoRoot) Name() string { return string(filepath.Separator) } 86 func (p *pseudoRoot) Size() int64 { return 0 } 87 func (p *pseudoRoot) Mode() os.FileMode { return os.ModeDir | os.ModePerm } 88 func (p *pseudoRoot) ModTime() time.Time { return time.Now() } 89 func (p *pseudoRoot) IsDir() bool { return true } 90 func (p *pseudoRoot) Sys() interface{} { return nil } 91 92 func (fs *Fs) Stat(name string) (os.FileInfo, error) { 93 d, f := splitpath(name) 94 if f == "" { 95 return &pseudoRoot{}, nil 96 } 97 if _, ok := fs.files[d]; !ok { 98 return nil, &os.PathError{Op: "stat", Path: name, Err: syscall.ENOENT} 99 } 100 file, ok := fs.files[d][f] 101 if !ok { 102 return nil, &os.PathError{Op: "stat", Path: name, Err: syscall.ENOENT} 103 } 104 return file.FileInfo(), nil 105 } 106 107 func (fs *Fs) Name() string { return "zipfs" } 108 109 func (fs *Fs) Chmod(name string, mode os.FileMode) error { return syscall.EPERM } 110 111 func (fs *Fs) Chown(name string, uid, gid int) error { return syscall.EPERM } 112 113 func (fs *Fs) Chtimes(name string, atime time.Time, mtime time.Time) error { return syscall.EPERM }