Skip to content

Commit 4826e79

Browse files
committed
memfs & osfs: based on helper chroot
1 parent 0e32e1f commit 4826e79

File tree

6 files changed

+54
-300
lines changed

6 files changed

+54
-300
lines changed

helper/chroot/chroot.go

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ func (fs *ChrootHelper) Symlink(target, link string) error {
166166

167167
// only rewrite target if it's already absolute
168168
if filepath.IsAbs(target) || strings.HasPrefix(target, string(filepath.Separator)) {
169-
target = string(os.PathSeparator) + fs.Join(fs.Root(), target)
169+
target = fs.Join(fs.Root(), target)
170170
}
171171

172172
if fs.isTargetOutBounders(link, target) {
@@ -207,8 +207,7 @@ func (fs *ChrootHelper) Readlink(link string) (string, error) {
207207
return target, nil
208208
}
209209

210-
base := string(os.PathSeparator) + fs.base
211-
target, err = filepath.Rel(base, target)
210+
target, err = filepath.Rel(fs.base, target)
212211
if err != nil {
213212
return "", err
214213
}

memfs/memory.go

Lines changed: 32 additions & 121 deletions
Original file line numberDiff line numberDiff line change
@@ -11,24 +11,22 @@ import (
1111
"time"
1212

1313
"gopkg.in/src-d/go-billy.v2"
14+
"gopkg.in/src-d/go-billy.v2/helper/chroot"
1415
)
1516

1617
const separator = filepath.Separator
1718

1819
// Memory a very convenient filesystem based on memory files
1920
type Memory struct {
20-
base string
21-
s *storage
21+
s *storage
2222

2323
tempCount int
2424
}
2525

2626
//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))
3230
}
3331

3432
func (fs *Memory) Create(filename string) (billy.File, error) {
@@ -40,44 +38,30 @@ func (fs *Memory) Open(filename string) (billy.File, error) {
4038
}
4139

4240
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 {
4843
if !isCreate(flag) {
4944
return nil, os.ErrNotExist
5045
}
5146

5247
var err error
53-
f, err = fs.s.New(fullpath, perm, flag)
48+
f, err = fs.s.New(filename, perm, flag)
5449
if err != nil {
5550
return nil, err
5651
}
57-
case err == nil:
58-
if target, isLink := fs.resolveLink(fullpath, f); isLink {
52+
} else {
53+
if target, isLink := fs.resolveLink(filename, f); isLink {
5954
return fs.OpenFile(target, flag, perm)
6055
}
61-
default:
62-
return nil, err
6356
}
6457

6558
if f.mode.IsDir() {
6659
return nil, fmt.Errorf("cannot open directory: %s", filename)
6760
}
6861

69-
filename, err = filepath.Rel(fs.base, fullpath)
70-
if err != nil {
71-
return nil, err
72-
}
73-
7462
return f.Duplicate(filename, perm, flag), nil
7563
}
7664

77-
func (fs *Memory) fullpath(path string) string {
78-
return clean(fs.Join(fs.base, path))
79-
}
80-
8165
var errNotLink = errors.New("not a link")
8266

8367
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
9074
target = fs.Join(filepath.Dir(fullpath), target)
9175
}
9276

93-
rel, _ := filepath.Rel(fs.base, target)
94-
return rel, true
77+
return target, true
9578
}
9679

9780
// 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 {
10285
}
10386

10487
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
10991
}
11092

11193
fi, _ := f.Stat()
11294

113-
if target, isLink := fs.resolveLink(fullpath, f); isLink {
95+
var err error
96+
if target, isLink := fs.resolveLink(filename, f); isLink {
11497
fi, err = fs.Stat(target)
11598
if err != nil {
11699
return nil, err
@@ -125,25 +108,23 @@ func (fs *Memory) Stat(filename string) (os.FileInfo, error) {
125108
}
126109

127110
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
132114
}
133115

134116
return f.Stat()
135117
}
136118

137119
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 {
141122
return fs.ReadDir(target)
142123
}
143124
}
144125

145126
var entries []os.FileInfo
146-
for _, f := range fs.s.Children(fullpath) {
127+
for _, f := range fs.s.Children(path) {
147128
fi, _ := f.Stat()
148129
entries = append(entries, fi)
149130
}
@@ -152,9 +133,7 @@ func (fs *Memory) ReadDir(path string) ([]os.FileInfo, error) {
152133
}
153134

154135
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)
158137
return err
159138
}
160139

@@ -179,30 +158,15 @@ func (fs *Memory) TempFile(dir, prefix string) (billy.File, error) {
179158
func (fs *Memory) getTempFilename(dir, prefix string) string {
180159
fs.tempCount++
181160
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)
183162
}
184163

185164
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-
196165
return fs.s.Rename(from, to)
197166
}
198167

199168
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)
206170
}
207171

208172
func (fs *Memory) Join(elem ...string) string {
@@ -219,42 +183,19 @@ func (fs *Memory) Symlink(target, link string) error {
219183
return err
220184
}
221185

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)
245187
}
246188

247189
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
252193
}
253194

254195
if !isSymlink(f.mode) {
255196
return "", &os.PathError{
256197
Op: "readlink",
257-
Path: fullpath,
198+
Path: link,
258199
Err: fmt.Errorf("not a symlink"),
259200
}
260201
}
@@ -263,41 +204,11 @@ func (fs *Memory) Readlink(link string) (string, error) {
263204
}
264205

265206
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
275208
}
276209

277210
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)
301212
}
302213

303214
type file struct {

memfs/storage.go

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@ import (
88
)
99

1010
type storage struct {
11-
boundary string
1211
files map[string]*file
1312
children map[string]map[string]*file
1413
}

0 commit comments

Comments
 (0)