aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/spf13/afero/memmap.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/spf13/afero/memmap.go')
-rw-r--r--vendor/github.com/spf13/afero/memmap.go365
1 files changed, 365 insertions, 0 deletions
diff --git a/vendor/github.com/spf13/afero/memmap.go b/vendor/github.com/spf13/afero/memmap.go
new file mode 100644
index 0000000..09498e7
--- /dev/null
+++ b/vendor/github.com/spf13/afero/memmap.go
@@ -0,0 +1,365 @@
1// Copyright © 2014 Steve Francia <spf@spf13.com>.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6// http://www.apache.org/licenses/LICENSE-2.0
7//
8// Unless required by applicable law or agreed to in writing, software
9// distributed under the License is distributed on an "AS IS" BASIS,
10// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11// See the License for the specific language governing permissions and
12// limitations under the License.
13
14package afero
15
16import (
17 "fmt"
18 "log"
19 "os"
20 "path/filepath"
21 "strings"
22 "sync"
23 "time"
24
25 "github.com/spf13/afero/mem"
26)
27
28type MemMapFs struct {
29 mu sync.RWMutex
30 data map[string]*mem.FileData
31 init sync.Once
32}
33
34func NewMemMapFs() Fs {
35 return &MemMapFs{}
36}
37
38func (m *MemMapFs) getData() map[string]*mem.FileData {
39 m.init.Do(func() {
40 m.data = make(map[string]*mem.FileData)
41 // Root should always exist, right?
42 // TODO: what about windows?
43 m.data[FilePathSeparator] = mem.CreateDir(FilePathSeparator)
44 })
45 return m.data
46}
47
48func (*MemMapFs) Name() string { return "MemMapFS" }
49
50func (m *MemMapFs) Create(name string) (File, error) {
51 name = normalizePath(name)
52 m.mu.Lock()
53 file := mem.CreateFile(name)
54 m.getData()[name] = file
55 m.registerWithParent(file)
56 m.mu.Unlock()
57 return mem.NewFileHandle(file), nil
58}
59
60func (m *MemMapFs) unRegisterWithParent(fileName string) error {
61 f, err := m.lockfreeOpen(fileName)
62 if err != nil {
63 return err
64 }
65 parent := m.findParent(f)
66 if parent == nil {
67 log.Panic("parent of ", f.Name(), " is nil")
68 }
69
70 parent.Lock()
71 mem.RemoveFromMemDir(parent, f)
72 parent.Unlock()
73 return nil
74}
75
76func (m *MemMapFs) findParent(f *mem.FileData) *mem.FileData {
77 pdir, _ := filepath.Split(f.Name())
78 pdir = filepath.Clean(pdir)
79 pfile, err := m.lockfreeOpen(pdir)
80 if err != nil {
81 return nil
82 }
83 return pfile
84}
85
86func (m *MemMapFs) registerWithParent(f *mem.FileData) {
87 if f == nil {
88 return
89 }
90 parent := m.findParent(f)
91 if parent == nil {
92 pdir := filepath.Dir(filepath.Clean(f.Name()))
93 err := m.lockfreeMkdir(pdir, 0777)
94 if err != nil {
95 //log.Println("Mkdir error:", err)
96 return
97 }
98 parent, err = m.lockfreeOpen(pdir)
99 if err != nil {
100 //log.Println("Open after Mkdir error:", err)
101 return
102 }
103 }
104
105 parent.Lock()
106 mem.InitializeDir(parent)
107 mem.AddToMemDir(parent, f)
108 parent.Unlock()
109}
110
111func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error {
112 name = normalizePath(name)
113 x, ok := m.getData()[name]
114 if ok {
115 // Only return ErrFileExists if it's a file, not a directory.
116 i := mem.FileInfo{FileData: x}
117 if !i.IsDir() {
118 return ErrFileExists
119 }
120 } else {
121 item := mem.CreateDir(name)
122 m.getData()[name] = item
123 m.registerWithParent(item)
124 }
125 return nil
126}
127
128func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
129 name = normalizePath(name)
130
131 m.mu.RLock()
132 _, ok := m.getData()[name]
133 m.mu.RUnlock()
134 if ok {
135 return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists}
136 }
137
138 m.mu.Lock()
139 item := mem.CreateDir(name)
140 m.getData()[name] = item
141 m.registerWithParent(item)
142 m.mu.Unlock()
143
144 m.Chmod(name, perm|os.ModeDir)
145
146 return nil
147}
148
149func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error {
150 err := m.Mkdir(path, perm)
151 if err != nil {
152 if err.(*os.PathError).Err == ErrFileExists {
153 return nil
154 }
155 return err
156 }
157 return nil
158}
159
160// Handle some relative paths
161func normalizePath(path string) string {
162 path = filepath.Clean(path)
163
164 switch path {
165 case ".":
166 return FilePathSeparator
167 case "..":
168 return FilePathSeparator
169 default:
170 return path
171 }
172}
173
174func (m *MemMapFs) Open(name string) (File, error) {
175 f, err := m.open(name)
176 if f != nil {
177 return mem.NewReadOnlyFileHandle(f), err
178 }
179 return nil, err
180}
181
182func (m *MemMapFs) openWrite(name string) (File, error) {
183 f, err := m.open(name)
184 if f != nil {
185 return mem.NewFileHandle(f), err
186 }
187 return nil, err
188}
189
190func (m *MemMapFs) open(name string) (*mem.FileData, error) {
191 name = normalizePath(name)
192
193 m.mu.RLock()
194 f, ok := m.getData()[name]
195 m.mu.RUnlock()
196 if !ok {
197 return nil, &os.PathError{Op: "open", Path: name, Err: ErrFileNotFound}
198 }
199 return f, nil
200}
201
202func (m *MemMapFs) lockfreeOpen(name string) (*mem.FileData, error) {
203 name = normalizePath(name)
204 f, ok := m.getData()[name]
205 if ok {
206 return f, nil
207 } else {
208 return nil, ErrFileNotFound
209 }
210}
211
212func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
213 chmod := false
214 file, err := m.openWrite(name)
215 if os.IsNotExist(err) && (flag&os.O_CREATE > 0) {
216 file, err = m.Create(name)
217 chmod = true
218 }
219 if err != nil {
220 return nil, err
221 }
222 if flag == os.O_RDONLY {
223 file = mem.NewReadOnlyFileHandle(file.(*mem.File).Data())
224 }
225 if flag&os.O_APPEND > 0 {
226 _, err = file.Seek(0, os.SEEK_END)
227 if err != nil {
228 file.Close()
229 return nil, err
230 }
231 }
232 if flag&os.O_TRUNC > 0 && flag&(os.O_RDWR|os.O_WRONLY) > 0 {
233 err = file.Truncate(0)
234 if err != nil {
235 file.Close()
236 return nil, err
237 }
238 }
239 if chmod {
240 m.Chmod(name, perm)
241 }
242 return file, nil
243}
244
245func (m *MemMapFs) Remove(name string) error {
246 name = normalizePath(name)
247
248 m.mu.Lock()
249 defer m.mu.Unlock()
250
251 if _, ok := m.getData()[name]; ok {
252 err := m.unRegisterWithParent(name)
253 if err != nil {
254 return &os.PathError{Op: "remove", Path: name, Err: err}
255 }
256 delete(m.getData(), name)
257 } else {
258 return &os.PathError{Op: "remove", Path: name, Err: os.ErrNotExist}
259 }
260 return nil
261}
262
263func (m *MemMapFs) RemoveAll(path string) error {
264 path = normalizePath(path)
265 m.mu.Lock()
266 m.unRegisterWithParent(path)
267 m.mu.Unlock()
268
269 m.mu.RLock()
270 defer m.mu.RUnlock()
271
272 for p, _ := range m.getData() {
273 if strings.HasPrefix(p, path) {
274 m.mu.RUnlock()
275 m.mu.Lock()
276 delete(m.getData(), p)
277 m.mu.Unlock()
278 m.mu.RLock()
279 }
280 }
281 return nil
282}
283
284func (m *MemMapFs) Rename(oldname, newname string) error {
285 oldname = normalizePath(oldname)
286 newname = normalizePath(newname)
287
288 if oldname == newname {
289 return nil
290 }
291
292 m.mu.RLock()
293 defer m.mu.RUnlock()
294 if _, ok := m.getData()[oldname]; ok {
295 m.mu.RUnlock()
296 m.mu.Lock()
297 m.unRegisterWithParent(oldname)
298 fileData := m.getData()[oldname]
299 delete(m.getData(), oldname)
300 mem.ChangeFileName(fileData, newname)
301 m.getData()[newname] = fileData
302 m.registerWithParent(fileData)
303 m.mu.Unlock()
304 m.mu.RLock()
305 } else {
306 return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound}
307 }
308 return nil
309}
310
311func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
312 f, err := m.Open(name)
313 if err != nil {
314 return nil, err
315 }
316 fi := mem.GetFileInfo(f.(*mem.File).Data())
317 return fi, nil
318}
319
320func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
321 name = normalizePath(name)
322
323 m.mu.RLock()
324 f, ok := m.getData()[name]
325 m.mu.RUnlock()
326 if !ok {
327 return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound}
328 }
329
330 m.mu.Lock()
331 mem.SetMode(f, mode)
332 m.mu.Unlock()
333
334 return nil
335}
336
337func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
338 name = normalizePath(name)
339
340 m.mu.RLock()
341 f, ok := m.getData()[name]
342 m.mu.RUnlock()
343 if !ok {
344 return &os.PathError{Op: "chtimes", Path: name, Err: ErrFileNotFound}
345 }
346
347 m.mu.Lock()
348 mem.SetModTime(f, mtime)
349 m.mu.Unlock()
350
351 return nil
352}
353
354func (m *MemMapFs) List() {
355 for _, x := range m.data {
356 y := mem.FileInfo{FileData: x}
357 fmt.Println(x.Name(), y.Size())
358 }
359}
360
361// func debugMemMapList(fs Fs) {
362// if x, ok := fs.(*MemMapFs); ok {
363// x.List()
364// }
365// }