@@ -55,11 +55,13 @@ func (*MemMapFs) Name() string { return "MemMapFS" }
5555
5656func (m * MemMapFs ) Create (name string ) (File , error ) {
5757 name = normalizePath (name )
58- m .mu .Lock ()
5958 file := mem .CreateFile (name )
60- m .getData ()[name ] = file
59+
60+ m .mu .Lock ()
61+ defer m .mu .Unlock ()
62+
6163 m .registerWithParent (file , 0 )
62- m .mu . Unlock ()
64+ m .getData ()[ name ] = file
6365 return mem .NewFileHandle (file ), nil
6466}
6567
@@ -162,18 +164,17 @@ func (m *MemMapFs) Mkdir(name string, perm os.FileMode) error {
162164 }
163165
164166 m .mu .Lock ()
165- // Dobule check that it doesn't exist.
166- if _ , ok := m . getData ()[ name ]; ok {
167- m . mu . Unlock ()
167+ defer m . mu . Unlock ()
168+
169+ if _ , ok := m . getData ()[ name ]; ok { // Recheck.
168170 return & os.PathError {Op : "mkdir" , Path : name , Err : ErrFileExists }
169171 }
172+
170173 item := mem .CreateDir (name )
171174 mem .SetMode (item , os .ModeDir | perm )
172175 m .getData ()[name ] = item
173176 m .registerWithParent (item , perm )
174- m .mu .Unlock ()
175-
176- return m .setFileMode (name , perm | os .ModeDir )
177+ return nil
177178}
178179
179180func (m * MemMapFs ) MkdirAll (path string , perm os.FileMode ) error {
@@ -253,8 +254,9 @@ func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, erro
253254 if err != nil {
254255 return nil , err
255256 }
257+ fileData := file .(* mem.File ).Data ()
256258 if flag == os .O_RDONLY {
257- file = mem .NewReadOnlyFileHandle (file .( * mem. File ). Data () )
259+ file = mem .NewReadOnlyFileHandle (fileData )
258260 }
259261 if flag & os .O_APPEND > 0 {
260262 _ , err = file .Seek (0 , io .SeekEnd )
@@ -271,7 +273,7 @@ func (m *MemMapFs) OpenFile(name string, flag int, perm os.FileMode) (File, erro
271273 }
272274 }
273275 if chmod {
274- return file , m . setFileMode ( name , perm )
276+ mem . SetMode ( fileData , perm )
275277 }
276278 return file , nil
277279}
@@ -296,20 +298,19 @@ func (m *MemMapFs) Remove(name string) error {
296298
297299func (m * MemMapFs ) RemoveAll (path string ) error {
298300 path = normalizePath (path )
299- m .mu .Lock ()
300- m .unRegisterWithParent (path )
301- m .mu .Unlock ()
302301
303- m .mu .RLock ()
304- defer m .mu .RUnlock ()
302+ // The lock must be held throughout to ensure atomic consistency
303+ // between the parent registry and getData. This is a limitation
304+ // of the current data model.
305+ m .mu .Lock ()
306+ defer m .mu .Unlock ()
305307
308+ if err := m .unRegisterWithParent (path ); err != nil {
309+ return nil
310+ }
306311 for p := range m .getData () {
307312 if p == path || strings .HasPrefix (p , path + FilePathSeparator ) {
308- m .mu .RUnlock ()
309- m .mu .Lock ()
310313 delete (m .getData (), p )
311- m .mu .Unlock ()
312- m .mu .RLock ()
313314 }
314315 }
315316 return nil
@@ -324,32 +325,32 @@ func (m *MemMapFs) Rename(oldname, newname string) error {
324325 }
325326
326327 m .mu .RLock ()
327- defer m .mu .RUnlock ()
328- if _ , ok := m .getData ()[oldname ]; ok {
329- m .mu .RUnlock ()
330- m .mu .Lock ()
331- err := m .unRegisterWithParent (oldname )
332- if err != nil {
333- return err
334- }
328+ _ , ok := m .getData ()[oldname ]
329+ m .mu .RUnlock ()
330+ if ! ok {
331+ return & os.PathError {Op : "rename" , Path : oldname , Err : ErrFileNotFound }
332+ }
335333
336- fileData := m .getData ()[oldname ]
337- mem .ChangeFileName (fileData , newname )
338- m .getData ()[newname ] = fileData
334+ m .mu .Lock ()
335+ defer m .mu .Unlock ()
339336
340- err = m .renameDescendants (oldname , newname )
341- if err != nil {
342- return err
343- }
337+ err : = m .unRegisterWithParent (oldname )
338+ if err != nil {
339+ return err
340+ }
344341
345- delete (m .getData (), oldname )
342+ fileData := m .getData ()[oldname ]
343+ mem .ChangeFileName (fileData , newname )
344+ m .getData ()[newname ] = fileData
346345
347- m .registerWithParent (fileData , 0 )
348- m .mu .Unlock ()
349- m .mu .RLock ()
350- } else {
351- return & os.PathError {Op : "rename" , Path : oldname , Err : ErrFileNotFound }
346+ err = m .renameDescendants (oldname , newname )
347+ if err != nil {
348+ return err
352349 }
350+
351+ delete (m .getData (), oldname )
352+
353+ m .registerWithParent (fileData , 0 )
353354 return nil
354355}
355356
@@ -391,6 +392,7 @@ func (m *MemMapFs) Stat(name string) (os.FileInfo, error) {
391392}
392393
393394func (m * MemMapFs ) Chmod (name string , mode os.FileMode ) error {
395+ name = normalizePath (name )
394396 mode &= chmodBits
395397
396398 m .mu .RLock ()
@@ -400,25 +402,7 @@ func (m *MemMapFs) Chmod(name string, mode os.FileMode) error {
400402 return & os.PathError {Op : "chmod" , Path : name , Err : ErrFileNotFound }
401403 }
402404 prevOtherBits := mem .GetFileInfo (f ).Mode () & ^ chmodBits
403-
404- mode = prevOtherBits | mode
405- return m .setFileMode (name , mode )
406- }
407-
408- func (m * MemMapFs ) setFileMode (name string , mode os.FileMode ) error {
409- name = normalizePath (name )
410-
411- m .mu .RLock ()
412- f , ok := m .getData ()[name ]
413- m .mu .RUnlock ()
414- if ! ok {
415- return & os.PathError {Op : "chmod" , Path : name , Err : ErrFileNotFound }
416- }
417-
418- m .mu .Lock ()
419- mem .SetMode (f , mode )
420- m .mu .Unlock ()
421-
405+ mem .SetMode (f , prevOtherBits | mode )
422406 return nil
423407}
424408
@@ -431,10 +415,7 @@ func (m *MemMapFs) Chown(name string, uid, gid int) error {
431415 if ! ok {
432416 return & os.PathError {Op : "chown" , Path : name , Err : ErrFileNotFound }
433417 }
434-
435- mem .SetUID (f , uid )
436- mem .SetGID (f , gid )
437-
418+ mem .SetUIDGID (f , uid , gid )
438419 return nil
439420}
440421
@@ -447,11 +428,7 @@ func (m *MemMapFs) Chtimes(name string, atime time.Time, mtime time.Time) error
447428 if ! ok {
448429 return & os.PathError {Op : "chtimes" , Path : name , Err : ErrFileNotFound }
449430 }
450-
451- m .mu .Lock ()
452431 mem .SetModTime (f , mtime )
453- m .mu .Unlock ()
454-
455432 return nil
456433}
457434
0 commit comments