afero icon indicating copy to clipboard operation
afero copied to clipboard

Renaming a file using MemMapFs behaves differently to OsFs

Open stumoss opened this issue 3 years ago • 0 comments

The memory mapped FS differs in behaviour when renaming a file compared with the OsFs one. Essentially in a memory mapped filesystem the Rename() operation takes effect on any existing afero.File instances pointing to the file which gets renamed.

package main

import (
	"log"

	"github.com/spf13/afero"
)

func main() {
	// fs := afero.NewOsFs()
	fs := afero.NewMemMapFs()

	f, err := afero.TempFile(fs, "", "temp*")
	if err != nil {
		log.Fatal(err)
	}
	ogFName := f.Name()

	log.Printf("Pre-rename: %s", f.Name())

	err = f.Close()
	if err != nil {
		log.Fatal(err)
	}

	err = fs.Rename(f.Name(), "new-name")
	if err != nil {
		log.Fatal(err)
	}

	log.Printf("Post-rename: %s", f.Name())

	err = fs.RemoveAll(f.Name())
	if err != nil {
		log.Fatal(err)
	}

	err = fs.RemoveAll(ogFName)
	if err != nil {
		log.Fatal(err)
	}
}

Using OsFs

go run main.go
2021/11/10 14:28:28 Pre-rename: /tmp/temp796650521
2021/11/10 14:28:28 Post-rename: /tmp/temp796650521

Using MemMapFs

go run main.go
2021/11/10 14:28:34 Pre-rename: /tmp/temp291024985
2021/11/10 14:28:34 Post-rename: new-name

I think the issue lies in the following code because the mem.FileData is a pointer and that gets copied into the new location within the map:

 if _, ok := m.getData()[oldname]; ok { 
 	m.mu.RUnlock() 
 	m.mu.Lock() 
 	m.unRegisterWithParent(oldname) 
 	fileData := m.getData()[oldname]      // <------ This fileData is already referenced by our afero.File variable.
 	delete(m.getData(), oldname) 
 	mem.ChangeFileName(fileData, newname)  // <---- This alters the name which results in our afero.File.Name() getting updated too.
 	m.getData()[newname] = fileData
 	m.registerWithParent(fileData, 0) 
 	m.mu.Unlock() 
 	m.mu.RLock() 

https://github.com/spf13/afero/blob/949437f3b7e2f3ca7ad553780aec516d0fc310d2/memmap.go#L303-L313

stumoss avatar Nov 10 '21 14:11 stumoss