...
1 package tarfs
2
3 import (
4 "archive/tar"
5 "bytes"
6 "os"
7 "path/filepath"
8 "sort"
9 "syscall"
10
11 "github.com/spf13/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 }
145
View as plain text