26
"github.com/spf13/afero/mem"
29
const chmodBits = os.ModePerm | os.ModeSetuid | os.ModeSetgid | os.ModeSticky
33
data map[string]*mem.FileData
37
func NewMemMapFs() Fs {
41
func (m *MemMapFs) getData() map[string]*mem.FileData {
43
m.data = make(map[string]*mem.FileData)
46
root := mem.CreateDir(FilePathSeparator)
47
mem.SetMode(root, os.ModeDir|0o755)
48
m.data[FilePathSeparator] = root
53
func (*MemMapFs) Name() string { return "MemMapFS" }
55
func (m *MemMapFs) Create(name string) (File, error) {
56
name = normalizePath(name)
58
file := mem.CreateFile(name)
59
m.getData()[name] = file
60
m.registerWithParent(file, 0)
62
return mem.NewFileHandle(file), nil
65
func (m *MemMapFs) unRegisterWithParent(fileName string) error {
66
f, err := m.lockfreeOpen(fileName)
70
parent := m.findParent(f)
72
log.Panic("parent of ", f.Name(), " is nil")
76
mem.RemoveFromMemDir(parent, f)
81
func (m *MemMapFs) findParent(f *mem.FileData) *mem.FileData {
82
pdir, _ := filepath.Split(f.Name())
83
pdir = filepath.Clean(pdir)
84
pfile, err := m.lockfreeOpen(pdir)
91
func (m *MemMapFs) registerWithParent(f *mem.FileData, perm os.FileMode) {
95
parent := m.findParent(f)
97
pdir := filepath.Dir(filepath.Clean(f.Name()))
98
err := m.lockfreeMkdir(pdir, perm)
103
parent, err = m.lockfreeOpen(pdir)
111
mem.InitializeDir(parent)
112
mem.AddToMemDir(parent, f)
116
func (m *MemMapFs) lockfreeMkdir(name string, perm os.FileMode) error {
117
name = normalizePath(name)
118
x, ok := m.getData()[name]
121
i := mem.FileInfo{FileData: x}
126
item := mem.CreateDir(name)
127
mem.SetMode(item, os.ModeDir|perm)
128
m.getData()[name] = item
129
m.registerWithParent(item, perm)
134
func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
136
name = normalizePath(name)
139
_, ok := m.getData()[name]
142
return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists}
147
if _, ok := m.getData()[name]; ok {
149
return &os.PathError{Op: "mkdir", Path: name, Err: ErrFileExists}
151
item := mem.CreateDir(name)
152
mem.SetMode(item, os.ModeDir|perm)
153
m.getData()[name] = item
154
m.registerWithParent(item, perm)
157
return m.setFileMode(name, perm|os.ModeDir)
160
func (m *MemMapFs) MkdirAll(path string, perm os.FileMode) error {
161
err := m.Mkdir(path, perm)
163
if err.(*os.PathError).Err == ErrFileExists {
172
func normalizePath(path string) string {
173
path = filepath.Clean(path)
177
return FilePathSeparator
179
return FilePathSeparator
185
func (m *MemMapFs) Open(name string) (File, error) {
186
f, err := m.open(name)
188
return mem.NewReadOnlyFileHandle(f), err
193
func (m *MemMapFs) openWrite(name string) (File, error) {
194
f, err := m.open(name)
196
return mem.NewFileHandle(f), err
201
func (m *MemMapFs) open(name string) (*mem.FileData, error) {
202
name = normalizePath(name)
205
f, ok := m.getData()[name]
208
return nil, &os.PathError{Op: "open", Path: name, Err: ErrFileNotFound}
213
func (m *MemMapFs) lockfreeOpen(name string) (*mem.FileData, error) {
214
name = normalizePath(name)
215
f, ok := m.getData()[name]
219
return nil, ErrFileNotFound
223
func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, error) {
226
file, err := m.openWrite(name)
227
if err == nil && (flag&os.O_EXCL > 0) {
228
return nil, &os.PathError{Op: "open", Path: name, Err: ErrFileExists}
230
if os.IsNotExist(err) && (flag&os.O_CREATE > 0) {
231
file, err = m.Create(name)
237
if flag == os.O_RDONLY {
238
file = mem.NewReadOnlyFileHandle(file.(*mem.File).Data())
240
if flag&os.O_APPEND > 0 {
241
_, err = file.Seek(0, io.SeekEnd)
247
if flag&os.O_TRUNC > 0 && flag&(os.O_RDWR|os.O_WRONLY) > 0 {
248
err = file.Truncate(0)
255
return file, m.setFileMode(name, perm)
260
func (m *MemMapFs) Remove(name string) error {
261
name = normalizePath(name)
266
if _, ok := m.getData()[name]; ok {
267
err := m.unRegisterWithParent(name)
269
return &os.PathError{Op: "remove", Path: name, Err: err}
271
delete(m.getData(), name)
273
return &os.PathError{Op: "remove", Path: name, Err: os.ErrNotExist}
278
func (m *MemMapFs) RemoveAll(path string) error {
279
path = normalizePath(path)
281
m.unRegisterWithParent(path)
287
for p := range m.getData() {
288
if p == path || strings.HasPrefix(p, path+FilePathSeparator) {
291
delete(m.getData(), p)
299
func (m *MemMapFs) Rename(oldname, newname string) error {
300
oldname = normalizePath(oldname)
301
newname = normalizePath(newname)
303
if oldname == newname {
309
if _, ok := m.getData()[oldname]; ok {
312
m.unRegisterWithParent(oldname)
313
fileData := m.getData()[oldname]
314
delete(m.getData(), oldname)
315
mem.ChangeFileName(fileData, newname)
316
m.getData()[newname] = fileData
317
m.registerWithParent(fileData, 0)
321
return &os.PathError{Op: "rename", Path: oldname, Err: ErrFileNotFound}
324
for p, fileData := range m.getData() {
325
if strings.HasPrefix(p, oldname+FilePathSeparator) {
328
delete(m.getData(), p)
329
p := strings.Replace(p, oldname, newname, 1)
330
m.getData()[p] = fileData
338
func (m *MemMapFs) LstatIfPossible(name string) (os.FileInfo, bool, error) {
339
fileInfo, err := m.Stat(name)
340
return fileInfo, false, err
343
func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
344
f, err := m.Open(name)
348
fi := mem.GetFileInfo(f.(*mem.File).Data())
352
func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
356
f, ok := m.getData()[name]
359
return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound}
361
prevOtherBits := mem.GetFileInfo(f).Mode() & ^chmodBits
363
mode = prevOtherBits | mode
364
return m.setFileMode(name, mode)
367
func (m *MemMapFs) setFileMode(name string, mode os.FileMode) error {
368
name = normalizePath(name)
371
f, ok := m.getData()[name]
374
return &os.PathError{Op: "chmod", Path: name, Err: ErrFileNotFound}
384
func (m *MemMapFs) Chown(name string, uid, gid int) error {
385
name = normalizePath(name)
388
f, ok := m.getData()[name]
391
return &os.PathError{Op: "chown", Path: name, Err: ErrFileNotFound}
400
func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error {
401
name = normalizePath(name)
404
f, ok := m.getData()[name]
407
return &os.PathError{Op: "chtimes", Path: name, Err: ErrFileNotFound}
411
mem.SetModTime(f, mtime)
417
func (m *MemMapFs) List() {
418
for _, x := range m.data {
419
y := mem.FileInfo{FileData: x}
420
fmt.Println(x.Name(), y.Size())