Skip to content

Commit 0589e19

Browse files
committed
feat(memfs): locking
1 parent ddeee0c commit 0589e19

File tree

1 file changed

+39
-11
lines changed

1 file changed

+39
-11
lines changed

memfs/memfs.go

Lines changed: 39 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -44,6 +44,9 @@ func (fi fileInfo) Sys() interface{} {
4444
}
4545

4646
func (fi fileInfo) Size() int64 {
47+
if fi.dir {
48+
return 0
49+
}
4750
fi.mutex.RLock()
4851
l := len(*(fi.buf))
4952
fi.mutex.RUnlock()
@@ -54,6 +57,11 @@ func (fi fileInfo) IsDir() bool {
5457
return fi.dir
5558
}
5659

60+
// ModTime returns the modification time.
61+
// Modification time is updated on:
62+
// - Creation
63+
// - Rename
64+
// - Open
5765
func (fi fileInfo) ModTime() time.Time {
5866
return fi.modTime
5967
}
@@ -88,6 +96,8 @@ func MemFS() vfs.Filesystem {
8896

8997
// Mkdir creates a new directory with given permissions
9098
func (fs *memFS) Mkdir(name string, perm os.FileMode) error {
99+
fs.lock.Lock()
100+
defer fs.lock.Unlock()
91101
name = filepath.Clean(name)
92102
base := filepath.Base(name)
93103
parent, fi, err := fs.fileInfo(name)
@@ -99,11 +109,12 @@ func (fs *memFS) Mkdir(name string, perm os.FileMode) error {
99109
}
100110

101111
fi = &fileInfo{
102-
name: base,
103-
dir: true,
104-
mode: perm,
105-
parent: parent,
106-
fs: fs,
112+
name: base,
113+
dir: true,
114+
mode: perm,
115+
parent: parent,
116+
modTime: time.Now(),
117+
fs: fs,
107118
}
108119
parent.childs[base] = fi
109120
return nil
@@ -122,6 +133,9 @@ func (f byName) Less(i, j int) bool { return f[i].Name() < f[j].Name() }
122133
func (f byName) Swap(i, j int) { f[i], f[j] = f[j], f[i] }
123134

124135
func (fs *memFS) ReadDir(path string) ([]os.FileInfo, error) {
136+
fs.lock.RLock()
137+
defer fs.lock.RUnlock()
138+
125139
path = filepath.Clean(path)
126140
_, fi, err := fs.fileInfo(path)
127141
if err != nil {
@@ -199,6 +213,9 @@ func checkFlag(flag int, flags int) bool {
199213
// If success the returned File can be used for I/O. Otherwise an error is returned, which
200214
// is a *os.PathError and can be extracted for further information.
201215
func (fs *memFS) OpenFile(name string, flag int, perm os.FileMode) (vfs.File, error) {
216+
fs.lock.Lock()
217+
defer fs.lock.Unlock()
218+
202219
name = filepath.Clean(name)
203220
base := filepath.Base(name)
204221
fiParent, fiNode, err := fs.fileInfo(name)
@@ -215,11 +232,12 @@ func (fs *memFS) OpenFile(name string, flag int, perm os.FileMode) (vfs.File, er
215232
}
216233
}
217234
fiNode = &fileInfo{
218-
name: base,
219-
dir: false,
220-
mode: perm,
221-
parent: fiParent,
222-
fs: fs,
235+
name: base,
236+
dir: false,
237+
mode: perm,
238+
parent: fiParent,
239+
modTime: time.Now(),
240+
fs: fs,
223241
}
224242
fiParent.childs[base] = fiNode
225243
} else { // find existing
@@ -230,7 +248,7 @@ func (fs *memFS) OpenFile(name string, flag int, perm os.FileMode) (vfs.File, er
230248
return nil, &os.PathError{"open", name, ErrIsDirectory}
231249
}
232250
}
233-
251+
fiNode.modTime = time.Now()
234252
return fiNode.file(flag)
235253
}
236254

@@ -276,6 +294,9 @@ func (f *woFile) Read(p []byte) (n int, err error) {
276294
}
277295

278296
func (fs *memFS) Remove(name string) error {
297+
fs.lock.Lock()
298+
defer fs.lock.Unlock()
299+
279300
name = filepath.Clean(name)
280301
fiParent, fiNode, err := fs.fileInfo(name)
281302
if err != nil {
@@ -290,6 +311,9 @@ func (fs *memFS) Remove(name string) error {
290311
}
291312

292313
func (fs *memFS) Rename(oldpath, newpath string) error {
314+
fs.lock.Lock()
315+
defer fs.lock.Unlock()
316+
293317
// OldPath
294318
oldpath = filepath.Clean(oldpath)
295319
// oldDir, oldBase := filepath.Split(oldpath)
@@ -317,11 +341,15 @@ func (fs *memFS) Rename(oldpath, newpath string) error {
317341
delete(fiOldParent.childs, fiOld.name)
318342
fiOld.parent = fiNewParent
319343
fiOld.name = newBase
344+
fiOld.modTime = time.Now()
320345
fiNewParent.childs[fiOld.name] = fiOld
321346
return nil
322347
}
323348

324349
func (fs *memFS) Stat(name string) (os.FileInfo, error) {
350+
fs.lock.RLock()
351+
defer fs.lock.RUnlock()
352+
325353
name = filepath.Clean(name)
326354
// dir, base := filepath.Split(name)
327355
_, fi, err := fs.fileInfo(name)

0 commit comments

Comments
 (0)