diff options
Diffstat (limited to 'vendor/github.com/spf13/afero/basepath.go')
-rw-r--r-- | vendor/github.com/spf13/afero/basepath.go | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/vendor/github.com/spf13/afero/basepath.go b/vendor/github.com/spf13/afero/basepath.go new file mode 100644 index 0000000..616ff8f --- /dev/null +++ b/vendor/github.com/spf13/afero/basepath.go | |||
@@ -0,0 +1,180 @@ | |||
1 | package afero | ||
2 | |||
3 | import ( | ||
4 | "os" | ||
5 | "path/filepath" | ||
6 | "runtime" | ||
7 | "strings" | ||
8 | "time" | ||
9 | ) | ||
10 | |||
11 | var _ Lstater = (*BasePathFs)(nil) | ||
12 | |||
13 | // The BasePathFs restricts all operations to a given path within an Fs. | ||
14 | // The given file name to the operations on this Fs will be prepended with | ||
15 | // the base path before calling the base Fs. | ||
16 | // Any file name (after filepath.Clean()) outside this base path will be | ||
17 | // treated as non existing file. | ||
18 | // | ||
19 | // Note that it does not clean the error messages on return, so you may | ||
20 | // reveal the real path on errors. | ||
21 | type BasePathFs struct { | ||
22 | source Fs | ||
23 | path string | ||
24 | } | ||
25 | |||
26 | type BasePathFile struct { | ||
27 | File | ||
28 | path string | ||
29 | } | ||
30 | |||
31 | func (f *BasePathFile) Name() string { | ||
32 | sourcename := f.File.Name() | ||
33 | return strings.TrimPrefix(sourcename, filepath.Clean(f.path)) | ||
34 | } | ||
35 | |||
36 | func NewBasePathFs(source Fs, path string) Fs { | ||
37 | return &BasePathFs{source: source, path: path} | ||
38 | } | ||
39 | |||
40 | // on a file outside the base path it returns the given file name and an error, | ||
41 | // else the given file with the base path prepended | ||
42 | func (b *BasePathFs) RealPath(name string) (path string, err error) { | ||
43 | if err := validateBasePathName(name); err != nil { | ||
44 | return name, err | ||
45 | } | ||
46 | |||
47 | bpath := filepath.Clean(b.path) | ||
48 | path = filepath.Clean(filepath.Join(bpath, name)) | ||
49 | if !strings.HasPrefix(path, bpath) { | ||
50 | return name, os.ErrNotExist | ||
51 | } | ||
52 | |||
53 | return path, nil | ||
54 | } | ||
55 | |||
56 | func validateBasePathName(name string) error { | ||
57 | if runtime.GOOS != "windows" { | ||
58 | // Not much to do here; | ||
59 | // the virtual file paths all look absolute on *nix. | ||
60 | return nil | ||
61 | } | ||
62 | |||
63 | // On Windows a common mistake would be to provide an absolute OS path | ||
64 | // We could strip out the base part, but that would not be very portable. | ||
65 | if filepath.IsAbs(name) { | ||
66 | return os.ErrNotExist | ||
67 | } | ||
68 | |||
69 | return nil | ||
70 | } | ||
71 | |||
72 | func (b *BasePathFs) Chtimes(name string, atime, mtime time.Time) (err error) { | ||
73 | if name, err = b.RealPath(name); err != nil { | ||
74 | return &os.PathError{Op: "chtimes", Path: name, Err: err} | ||
75 | } | ||
76 | return b.source.Chtimes(name, atime, mtime) | ||
77 | } | ||
78 | |||
79 | func (b *BasePathFs) Chmod(name string, mode os.FileMode) (err error) { | ||
80 | if name, err = b.RealPath(name); err != nil { | ||
81 | return &os.PathError{Op: "chmod", Path: name, Err: err} | ||
82 | } | ||
83 | return b.source.Chmod(name, mode) | ||
84 | } | ||
85 | |||
86 | func (b *BasePathFs) Name() string { | ||
87 | return "BasePathFs" | ||
88 | } | ||
89 | |||
90 | func (b *BasePathFs) Stat(name string) (fi os.FileInfo, err error) { | ||
91 | if name, err = b.RealPath(name); err != nil { | ||
92 | return nil, &os.PathError{Op: "stat", Path: name, Err: err} | ||
93 | } | ||
94 | return b.source.Stat(name) | ||
95 | } | ||
96 | |||
97 | func (b *BasePathFs) Rename(oldname, newname string) (err error) { | ||
98 | if oldname, err = b.RealPath(oldname); err != nil { | ||
99 | return &os.PathError{Op: "rename", Path: oldname, Err: err} | ||
100 | } | ||
101 | if newname, err = b.RealPath(newname); err != nil { | ||
102 | return &os.PathError{Op: "rename", Path: newname, Err: err} | ||
103 | } | ||
104 | return b.source.Rename(oldname, newname) | ||
105 | } | ||
106 | |||
107 | func (b *BasePathFs) RemoveAll(name string) (err error) { | ||
108 | if name, err = b.RealPath(name); err != nil { | ||
109 | return &os.PathError{Op: "remove_all", Path: name, Err: err} | ||
110 | } | ||
111 | return b.source.RemoveAll(name) | ||
112 | } | ||
113 | |||
114 | func (b *BasePathFs) Remove(name string) (err error) { | ||
115 | if name, err = b.RealPath(name); err != nil { | ||
116 | return &os.PathError{Op: "remove", Path: name, Err: err} | ||
117 | } | ||
118 | return b.source.Remove(name) | ||
119 | } | ||
120 | |||
121 | func (b *BasePathFs) OpenFile(name string, flag int, mode os.FileMode) (f File, err error) { | ||
122 | if name, err = b.RealPath(name); err != nil { | ||
123 | return nil, &os.PathError{Op: "openfile", Path: name, Err: err} | ||
124 | } | ||
125 | sourcef, err := b.source.OpenFile(name, flag, mode) | ||
126 | if err != nil { | ||
127 | return nil, err | ||
128 | } | ||
129 | return &BasePathFile{sourcef, b.path}, nil | ||
130 | } | ||
131 | |||
132 | func (b *BasePathFs) Open(name string) (f File, err error) { | ||
133 | if name, err = b.RealPath(name); err != nil { | ||
134 | return nil, &os.PathError{Op: "open", Path: name, Err: err} | ||
135 | } | ||
136 | sourcef, err := b.source.Open(name) | ||
137 | if err != nil { | ||
138 | return nil, err | ||
139 | } | ||
140 | return &BasePathFile{File: sourcef, path: b.path}, nil | ||
141 | } | ||
142 | |||
143 | func (b *BasePathFs) Mkdir(name string, mode os.FileMode) (err error) { | ||
144 | if name, err = b.RealPath(name); err != nil { | ||
145 | return &os.PathError{Op: "mkdir", Path: name, Err: err} | ||
146 | } | ||
147 | return b.source.Mkdir(name, mode) | ||
148 | } | ||
149 | |||
150 | func (b *BasePathFs) MkdirAll(name string, mode os.FileMode) (err error) { | ||
151 | if name, err = b.RealPath(name); err != nil { | ||
152 | return &os.PathError{Op: "mkdir", Path: name, Err: err} | ||
153 | } | ||
154 | return b.source.MkdirAll(name, mode) | ||
155 | } | ||
156 | |||
157 | func (b *BasePathFs) Create(name string) (f File, err error) { | ||
158 | if name, err = b.RealPath(name); err != nil { | ||
159 | return nil, &os.PathError{Op: "create", Path: name, Err: err} | ||
160 | } | ||
161 | sourcef, err := b.source.Create(name) | ||
162 | if err != nil { | ||
163 | return nil, err | ||
164 | } | ||
165 | return &BasePathFile{File: sourcef, path: b.path}, nil | ||
166 | } | ||
167 | |||
168 | func (b *BasePathFs) LstatIfPossible(name string) (os.FileInfo, bool, error) { | ||
169 | name, err := b.RealPath(name) | ||
170 | if err != nil { | ||
171 | return nil, false, &os.PathError{Op: "lstat", Path: name, Err: err} | ||
172 | } | ||
173 | if lstater, ok := b.source.(Lstater); ok { | ||
174 | return lstater.LstatIfPossible(name) | ||
175 | } | ||
176 | fi, err := b.source.Stat(name) | ||
177 | return fi, false, err | ||
178 | } | ||
179 | |||
180 | // vim: ts=4 sw=4 noexpandtab nolist syn=go | ||