]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/spf13/afero/memmap.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / spf13 / afero / memmap.go
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
14 package afero
15
16 import (
17 "fmt"
18 "log"
19 "os"
20 "path/filepath"
21 "strings"
22 "sync"
23 "time"
24
25 "github.com/spf13/afero/mem"
26 )
27
28 type MemMapFs struct {
29 mu sync.RWMutex
30 data map[string]*mem.FileData
31 init sync.Once
32 }
33
34 func NewMemMapFs() Fs {
35 return &MemMapFs{}
36 }
37
38 func (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
48 func (*MemMapFs) Name() string { return "MemMapFS" }
49
50 func (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
60 func (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
76 func (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
86 func (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
111 func (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
128 func (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
149 func (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
161 func 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
174 func (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
182 func (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
190 func (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
202 func (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
212 func (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
245 func (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
263 func (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
284 func (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
311 func (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
320 func (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
337 func (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
354 func (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 // }