v2api: fix Rename trying to overwrite itself

We used to do this

  [pid 99182] renameat2(14, "Y_4DAxKvj1QnXmJx2AkrKA", 15, ".", RENAME_NOREPLACE <unfinished ...>

which was not the intention.
This commit is contained in:
Jakob Unterwurzacher 2020-07-12 13:53:47 +02:00
parent f3a0dbabee
commit 230d92c4f4

View File

@ -453,6 +453,7 @@ func (n *Node) Symlink(ctx context.Context, target, name string, out *fuse.Entry
} }
// Rename - FUSE call. // Rename - FUSE call.
// This function is called on the PARENT DIRECTORY of `name`.
// //
// Symlink-safe through Renameat(). // Symlink-safe through Renameat().
func (n *Node) Rename(ctx context.Context, name string, newParent fs.InodeEmbedder, newName string, flags uint32) (errno syscall.Errno) { func (n *Node) Rename(ctx context.Context, name string, newParent fs.InodeEmbedder, newName string, flags uint32) (errno syscall.Errno) {
@ -463,7 +464,7 @@ func (n *Node) Rename(ctx context.Context, name string, newParent fs.InodeEmbedd
defer syscall.Close(dirfd) defer syscall.Close(dirfd)
n2 := toNode(newParent) n2 := toNode(newParent)
dirfd2, cName2, errno := n2.prepareAtSyscall("") dirfd2, cName2, errno := n2.prepareAtSyscall(newName)
if errno != 0 { if errno != 0 {
return return
} }
@ -491,7 +492,7 @@ func (n *Node) Rename(ctx context.Context, name string, newParent fs.InodeEmbedd
// Actual rename // Actual rename
tlog.Debug.Printf("Renameat %d/%s -> %d/%s\n", dirfd, cName, dirfd2, cName2) tlog.Debug.Printf("Renameat %d/%s -> %d/%s\n", dirfd, cName, dirfd2, cName2)
err = unix.Renameat2(dirfd, cName, dirfd2, cName2, uint(flags)) err = unix.Renameat2(dirfd, cName, dirfd2, cName2, uint(flags))
if err == syscall.ENOTEMPTY || err == syscall.EEXIST { if (flags&unix.RENAME_NOREPLACE == 0) && (err == syscall.ENOTEMPTY || err == syscall.EEXIST) {
// If an empty directory is overwritten we will always get an error as // If an empty directory is overwritten we will always get an error as
// the "empty" directory will still contain gocryptfs.diriv. // the "empty" directory will still contain gocryptfs.diriv.
// Interestingly, ext4 returns ENOTEMPTY while xfs returns EEXIST. // Interestingly, ext4 returns ENOTEMPTY while xfs returns EEXIST.