github.com/bpfs/defs@v0.0.15/afero/tarfs/file.go (about) 1 package tarfs 2 3 import ( 4 "archive/tar" 5 "bytes" 6 "os" 7 "path/filepath" 8 "sort" 9 "syscall" 10 11 "github.com/bpfs/defs/afero" 12 ) 13 14 type File struct { 15 h *tar.Header 16 data *bytes.Reader 17 closed bool 18 fs *Fs 19 } 20 21 func (f *File) Close() error { 22 if f.closed { 23 return afero.ErrFileClosed 24 } 25 26 f.closed = true 27 f.h = nil 28 f.data = nil 29 f.fs = nil 30 31 return nil 32 } 33 34 func (f *File) Read(p []byte) (n int, err error) { 35 if f.closed { 36 return 0, afero.ErrFileClosed 37 } 38 39 if f.h.Typeflag == tar.TypeDir { 40 return 0, syscall.EISDIR 41 } 42 43 return f.data.Read(p) 44 } 45 46 func (f *File) ReadAt(p []byte, off int64) (n int, err error) { 47 if f.closed { 48 return 0, afero.ErrFileClosed 49 } 50 51 if f.h.Typeflag == tar.TypeDir { 52 return 0, syscall.EISDIR 53 } 54 55 return f.data.ReadAt(p, off) 56 } 57 58 func (f *File) Seek(offset int64, whence int) (int64, error) { 59 if f.closed { 60 return 0, afero.ErrFileClosed 61 } 62 63 if f.h.Typeflag == tar.TypeDir { 64 return 0, syscall.EISDIR 65 } 66 67 return f.data.Seek(offset, whence) 68 } 69 70 func (f *File) Write(p []byte) (n int, err error) { return 0, syscall.EROFS } 71 72 func (f *File) WriteAt(p []byte, off int64) (n int, err error) { return 0, syscall.EROFS } 73 74 func (f *File) Name() string { 75 return filepath.Join(splitpath(f.h.Name)) 76 } 77 78 func (f *File) getDirectoryNames() ([]string, error) { 79 d, ok := f.fs.files[f.Name()] 80 if !ok { 81 return nil, &os.PathError{Op: "readdir", Path: f.Name(), Err: syscall.ENOENT} 82 } 83 84 var names []string 85 for n := range d { 86 names = append(names, n) 87 } 88 sort.Strings(names) 89 90 return names, nil 91 } 92 93 func (f *File) Readdir(count int) ([]os.FileInfo, error) { 94 if f.closed { 95 return nil, afero.ErrFileClosed 96 } 97 98 if !f.h.FileInfo().IsDir() { 99 return nil, syscall.ENOTDIR 100 } 101 102 names, err := f.getDirectoryNames() 103 if err != nil { 104 return nil, err 105 } 106 107 d := f.fs.files[f.Name()] 108 var fi []os.FileInfo 109 for _, n := range names { 110 if n == "" { 111 continue 112 } 113 114 f := d[n] 115 fi = append(fi, f.h.FileInfo()) 116 if count > 0 && len(fi) >= count { 117 break 118 } 119 } 120 121 return fi, nil 122 } 123 124 func (f *File) Readdirnames(n int) ([]string, error) { 125 fi, err := f.Readdir(n) 126 if err != nil { 127 return nil, err 128 } 129 130 var names []string 131 for _, f := range fi { 132 names = append(names, f.Name()) 133 } 134 135 return names, nil 136 } 137 138 func (f *File) Stat() (os.FileInfo, error) { return f.h.FileInfo(), nil } 139 140 func (f *File) Sync() error { return nil } 141 142 func (f *File) Truncate(size int64) error { return syscall.EROFS } 143 144 func (f *File) WriteString(s string) (ret int, err error) { return 0, syscall.EROFS }