@@ -11,24 +11,22 @@ import (
11
11
"time"
12
12
13
13
"gopkg.in/src-d/go-billy.v2"
14
+ "gopkg.in/src-d/go-billy.v2/helper/chroot"
14
15
)
15
16
16
17
const separator = filepath .Separator
17
18
18
19
// Memory a very convenient filesystem based on memory files
19
20
type Memory struct {
20
- base string
21
- s * storage
21
+ s * storage
22
22
23
23
tempCount int
24
24
}
25
25
26
26
//New returns a new Memory filesystem.
27
- func New () * Memory {
28
- return & Memory {
29
- base : string (separator ),
30
- s : newStorage (),
31
- }
27
+ func New () billy.Filesystem {
28
+ fs := & Memory {s : newStorage ()}
29
+ return chroot .New (fs , string (separator ))
32
30
}
33
31
34
32
func (fs * Memory ) Create (filename string ) (billy.File , error ) {
@@ -40,44 +38,30 @@ func (fs *Memory) Open(filename string) (billy.File, error) {
40
38
}
41
39
42
40
func (fs * Memory ) OpenFile (filename string , flag int , perm os.FileMode ) (billy.File , error ) {
43
- fullpath := fs .fullpath (filename )
44
- f , err := fs .getFromStorage (fullpath )
45
-
46
- switch {
47
- case os .IsNotExist (err ):
41
+ f , has := fs .s .Get (filename )
42
+ if ! has {
48
43
if ! isCreate (flag ) {
49
44
return nil , os .ErrNotExist
50
45
}
51
46
52
47
var err error
53
- f , err = fs .s .New (fullpath , perm , flag )
48
+ f , err = fs .s .New (filename , perm , flag )
54
49
if err != nil {
55
50
return nil , err
56
51
}
57
- case err == nil :
58
- if target , isLink := fs .resolveLink (fullpath , f ); isLink {
52
+ } else {
53
+ if target , isLink := fs .resolveLink (filename , f ); isLink {
59
54
return fs .OpenFile (target , flag , perm )
60
55
}
61
- default :
62
- return nil , err
63
56
}
64
57
65
58
if f .mode .IsDir () {
66
59
return nil , fmt .Errorf ("cannot open directory: %s" , filename )
67
60
}
68
61
69
- filename , err = filepath .Rel (fs .base , fullpath )
70
- if err != nil {
71
- return nil , err
72
- }
73
-
74
62
return f .Duplicate (filename , perm , flag ), nil
75
63
}
76
64
77
- func (fs * Memory ) fullpath (path string ) string {
78
- return clean (fs .Join (fs .base , path ))
79
- }
80
-
81
65
var errNotLink = errors .New ("not a link" )
82
66
83
67
func (fs * Memory ) resolveLink (fullpath string , f * file ) (target string , isLink bool ) {
@@ -90,8 +74,7 @@ func (fs *Memory) resolveLink(fullpath string, f *file) (target string, isLink b
90
74
target = fs .Join (filepath .Dir (fullpath ), target )
91
75
}
92
76
93
- rel , _ := filepath .Rel (fs .base , target )
94
- return rel , true
77
+ return target , true
95
78
}
96
79
97
80
// On Windows OS, IsAbs validates if a path is valid based on if stars with a
@@ -102,15 +85,15 @@ func isAbs(path string) bool {
102
85
}
103
86
104
87
func (fs * Memory ) Stat (filename string ) (os.FileInfo , error ) {
105
- fullpath := fs .fullpath (filename )
106
- f , err := fs .getFromStorage (fullpath )
107
- if err != nil {
108
- return nil , err
88
+ f , has := fs .s .Get (filename )
89
+ if ! has {
90
+ return nil , os .ErrNotExist
109
91
}
110
92
111
93
fi , _ := f .Stat ()
112
94
113
- if target , isLink := fs .resolveLink (fullpath , f ); isLink {
95
+ var err error
96
+ if target , isLink := fs .resolveLink (filename , f ); isLink {
114
97
fi , err = fs .Stat (target )
115
98
if err != nil {
116
99
return nil , err
@@ -125,25 +108,23 @@ func (fs *Memory) Stat(filename string) (os.FileInfo, error) {
125
108
}
126
109
127
110
func (fs * Memory ) Lstat (filename string ) (os.FileInfo , error ) {
128
- fullpath := fs .fullpath (filename )
129
- f , err := fs .getFromStorage (fullpath )
130
- if err != nil {
131
- return nil , err
111
+ f , has := fs .s .Get (filename )
112
+ if ! has {
113
+ return nil , os .ErrNotExist
132
114
}
133
115
134
116
return f .Stat ()
135
117
}
136
118
137
119
func (fs * Memory ) ReadDir (path string ) ([]os.FileInfo , error ) {
138
- fullpath := fs .fullpath (path )
139
- if f , err := fs .getFromStorage (fullpath ); err == nil {
140
- if target , isLink := fs .resolveLink (fullpath , f ); isLink {
120
+ if f , has := fs .s .Get (path ); has {
121
+ if target , isLink := fs .resolveLink (path , f ); isLink {
141
122
return fs .ReadDir (target )
142
123
}
143
124
}
144
125
145
126
var entries []os.FileInfo
146
- for _ , f := range fs .s .Children (fullpath ) {
127
+ for _ , f := range fs .s .Children (path ) {
147
128
fi , _ := f .Stat ()
148
129
entries = append (entries , fi )
149
130
}
@@ -152,9 +133,7 @@ func (fs *Memory) ReadDir(path string) ([]os.FileInfo, error) {
152
133
}
153
134
154
135
func (fs * Memory ) MkdirAll (path string , perm os.FileMode ) error {
155
- fullpath := fs .Join (fs .base , path )
156
-
157
- _ , err := fs .s .New (fullpath , perm | os .ModeDir , 0 )
136
+ _ , err := fs .s .New (path , perm | os .ModeDir , 0 )
158
137
return err
159
138
}
160
139
@@ -179,30 +158,15 @@ func (fs *Memory) TempFile(dir, prefix string) (billy.File, error) {
179
158
func (fs * Memory ) getTempFilename (dir , prefix string ) string {
180
159
fs .tempCount ++
181
160
filename := fmt .Sprintf ("%s_%d_%d" , prefix , fs .tempCount , time .Now ().UnixNano ())
182
- return fs .Join (fs . base , dir , filename )
161
+ return fs .Join (dir , filename )
183
162
}
184
163
185
164
func (fs * Memory ) Rename (from , to string ) error {
186
- from = fs .Join (fs .base , from )
187
- if err := fs .validate (from ); err != nil {
188
- return err
189
- }
190
-
191
- to = fs .Join (fs .base , to )
192
- if err := fs .validate (to ); err != nil {
193
- return err
194
- }
195
-
196
165
return fs .s .Rename (from , to )
197
166
}
198
167
199
168
func (fs * Memory ) Remove (filename string ) error {
200
- fullpath := fs .Join (fs .base , filename )
201
- if err := fs .validate (fullpath ); err != nil {
202
- return err
203
- }
204
-
205
- return fs .s .Remove (fullpath )
169
+ return fs .s .Remove (filename )
206
170
}
207
171
208
172
func (fs * Memory ) Join (elem ... string ) string {
@@ -219,42 +183,19 @@ func (fs *Memory) Symlink(target, link string) error {
219
183
return err
220
184
}
221
185
222
- if fs .isTargetOutBounders (link , target ) {
223
- return billy .ErrCrossedBoundary
224
- }
225
-
226
- return billy .WriteFile (fs , clean (link ), []byte (clean (target )), 0777 | os .ModeSymlink )
227
- }
228
-
229
- func (fs * Memory ) isTargetOutBounders (link , target string ) bool {
230
- fulllink := fs .Join (fs .base , link )
231
- fullpath := fs .Join (filepath .Dir (fulllink ), target )
232
- target , err := filepath .Rel (fs .base , fullpath )
233
- if err != nil {
234
- return true
235
- }
236
-
237
- return isCrossBoundaries (target )
238
- }
239
-
240
- func isCrossBoundaries (path string ) bool {
241
- path = filepath .ToSlash (path )
242
- path = filepath .Clean (path )
243
-
244
- return strings .HasPrefix (path , ".." )
186
+ return billy .WriteFile (fs , link , []byte (target ), 0777 | os .ModeSymlink )
245
187
}
246
188
247
189
func (fs * Memory ) Readlink (link string ) (string , error ) {
248
- fullpath := fs .fullpath (link )
249
- f , err := fs .getFromStorage (fullpath )
250
- if err != nil {
251
- return "" , err
190
+ f , has := fs .s .Get (link )
191
+ if ! has {
192
+ return "" , os .ErrNotExist
252
193
}
253
194
254
195
if ! isSymlink (f .mode ) {
255
196
return "" , & os.PathError {
256
197
Op : "readlink" ,
257
- Path : fullpath ,
198
+ Path : link ,
258
199
Err : fmt .Errorf ("not a symlink" ),
259
200
}
260
201
}
@@ -263,41 +204,11 @@ func (fs *Memory) Readlink(link string) (string, error) {
263
204
}
264
205
265
206
func (fs * Memory ) Chroot (path string ) (billy.Basic , error ) {
266
- fullpath := fs .Join (fs .base , path )
267
- if err := fs .validate (fullpath ); err != nil {
268
- return nil , err
269
- }
270
-
271
- return & Memory {
272
- base : fullpath ,
273
- s : fs .s ,
274
- }, nil
207
+ return nil , billy .ErrNotSupported
275
208
}
276
209
277
210
func (fs * Memory ) Root () string {
278
- return fs .base
279
- }
280
-
281
- func (fs * Memory ) getFromStorage (fullpath string ) (* file , error ) {
282
- if err := fs .validate (fullpath ); err != nil {
283
- return nil , err
284
- }
285
-
286
- f , has := fs .s .Get (fullpath )
287
- if ! has {
288
- return nil , os .ErrNotExist
289
- }
290
-
291
- return f , nil
292
- }
293
-
294
- func (fs * Memory ) validate (fullpath string ) error {
295
- relpath , _ := filepath .Rel (fs .base , fullpath )
296
- if strings .HasPrefix (relpath , ".." ) {
297
- return billy .ErrCrossedBoundary
298
- }
299
-
300
- return nil
211
+ return string (separator )
301
212
}
302
213
303
214
type file struct {
0 commit comments