fusefrontend: Fix longname handling for renames with existing target
Fixes https://github.com/rfjakob/gocryptfs/issues/170 Steps to reproduce the problem: * Create a regular forward mount point * Create a file with a shortname and one with a long filename * Try to run 'mv <shortname> <longname>' This should actually work and replace the existing file, but instead it fails with: mv: cannot move '<shortname>' to '<longname>': File exists The problem is the creation of the .name file. If the target already exists we can safely ignore the EEXIST error and just keep the existing .name file.
This commit is contained in:
parent
d257bb34c1
commit
9f56b33e0c
@ -517,7 +517,13 @@ func (fs *FS) Rename(oldPath string, newPath string, context *fuse.Context) (cod
|
||||
finalNewPath = cNewName
|
||||
// Create destination .name file
|
||||
err = fs.nameTransform.WriteLongName(newDirFd, cNewName, newPath)
|
||||
if err != nil {
|
||||
// Failure to write the .name file is expected when the target path already
|
||||
// exists. Since hashes are pretty unique, there is no need to modify the
|
||||
// file anyway. We still set newDirFd to nil to ensure that we do not delete
|
||||
// the file on error.
|
||||
if err == syscall.EEXIST {
|
||||
newDirFd = nil
|
||||
} else if err != nil {
|
||||
return fuse.ToStatus(err)
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +114,11 @@ func (n *NameTransform) WriteLongName(dirfd *os.File, hashName string, plainName
|
||||
fdRaw, err := syscallcompat.Openat(int(dirfd.Fd()), hashName+LongNameSuffix,
|
||||
syscall.O_WRONLY|syscall.O_CREAT|syscall.O_EXCL, 0600)
|
||||
if err != nil {
|
||||
tlog.Warn.Printf("WriteLongName: Openat: %v", err)
|
||||
// Don't warn if the file already exists - this is allowed for renames
|
||||
// and should be handled by the caller.
|
||||
if err != syscall.EEXIST {
|
||||
tlog.Warn.Printf("WriteLongName: Openat: %v", err)
|
||||
}
|
||||
return err
|
||||
}
|
||||
fd := os.NewFile(uintptr(fdRaw), hashName+LongNameSuffix)
|
||||
|
@ -544,7 +544,7 @@ func TestLongNames(t *testing.T) {
|
||||
if !test_helpers.VerifyExistence(wd + n255x) {
|
||||
t.Errorf("n255x is not in directory listing")
|
||||
}
|
||||
// Rename long to long
|
||||
// Rename long to long (target does not exist)
|
||||
n255y := string(bytes.Repeat([]byte("y"), 255))
|
||||
err = os.Rename(wd+n255x, wd+n255y)
|
||||
if err != nil {
|
||||
@ -553,7 +553,20 @@ func TestLongNames(t *testing.T) {
|
||||
if !test_helpers.VerifyExistence(wd + n255y) {
|
||||
t.Errorf("n255y is not in directory listing")
|
||||
}
|
||||
// Rename long to short
|
||||
// Rename long to long (target exists)
|
||||
f, err = os.Create(wd + n255x)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not create n255x: %v", err)
|
||||
}
|
||||
f.Close()
|
||||
err = os.Rename(wd+n255x, wd+n255y)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not rename n255x to n255y: %v", err)
|
||||
}
|
||||
if !test_helpers.VerifyExistence(wd + n255y) {
|
||||
t.Errorf("n255y is not in directory listing")
|
||||
}
|
||||
// Rename long to short (target does not exist)
|
||||
err = os.Rename(wd+n255y, wd+"short")
|
||||
if err != nil {
|
||||
t.Fatalf("Could not rename n255y to short: %v", err)
|
||||
@ -561,7 +574,20 @@ func TestLongNames(t *testing.T) {
|
||||
if !test_helpers.VerifyExistence(wd + "short") {
|
||||
t.Errorf("short is not in directory listing")
|
||||
}
|
||||
// Rename short to long
|
||||
// Rename long to short (target exists)
|
||||
f, err = os.Create(wd + n255y)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not create n255y: %v", err)
|
||||
}
|
||||
f.Close()
|
||||
err = os.Rename(wd+n255y, wd+"short")
|
||||
if err != nil {
|
||||
t.Fatalf("Could not rename n255y to short: %v", err)
|
||||
}
|
||||
if !test_helpers.VerifyExistence(wd + "short") {
|
||||
t.Errorf("short is not in directory listing")
|
||||
}
|
||||
// Rename short to long (target does not exist)
|
||||
err = os.Rename(wd+"short", wd+n255x)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not rename short to n255x: %v", err)
|
||||
@ -569,6 +595,19 @@ func TestLongNames(t *testing.T) {
|
||||
if !test_helpers.VerifyExistence(wd + n255x) {
|
||||
t.Errorf("255x is not in directory listing II")
|
||||
}
|
||||
// Rename short to long (target exists)
|
||||
f, err = os.Create(wd + "short")
|
||||
if err != nil {
|
||||
t.Fatalf("Could not create short: %v", err)
|
||||
}
|
||||
f.Close()
|
||||
err = os.Rename(wd+"short", wd+n255x)
|
||||
if err != nil {
|
||||
t.Fatalf("Could not rename short to n255x: %v", err)
|
||||
}
|
||||
if !test_helpers.VerifyExistence(wd + n255x) {
|
||||
t.Errorf("n255x is not in directory listing")
|
||||
}
|
||||
// Unlink
|
||||
err = syscall.Unlink(wd + n255x)
|
||||
if err != nil {
|
||||
|
Loading…
x
Reference in New Issue
Block a user