diff options
author | Jakob Unterwurzacher | 2022-01-22 12:28:27 +0100 |
---|---|---|
committer | Jakob Unterwurzacher | 2022-01-22 12:28:27 +0100 |
commit | b7cac4ffd07733ab6bcd0d33345de3306a8a5a59 (patch) | |
tree | ac8d9f593bcdce3abd7a8bb4d62e4ca7e6b986c2 | |
parent | 3ca2b1983dbab14e3769efd126098cbca6fb2ffd (diff) |
fusefrontend: support RENAME_WHITEOUT, RENAME_EXCHANGE
Both new internal test and xfstests generic/013 are happy.
https://github.com/rfjakob/gocryptfs/issues/641
-rw-r--r-- | internal/fusefrontend/node.go | 23 | ||||
-rw-r--r-- | internal/syscallcompat/sys_darwin.go | 4 | ||||
-rw-r--r-- | internal/syscallcompat/sys_linux.go | 4 |
3 files changed, 17 insertions, 14 deletions
diff --git a/internal/fusefrontend/node.go b/internal/fusefrontend/node.go index ead77c9..688cc0d 100644 --- a/internal/fusefrontend/node.go +++ b/internal/fusefrontend/node.go @@ -391,23 +391,17 @@ func (n *Node) Symlink(ctx context.Context, target, name string, out *fuse.Entry return inode, 0 } -// xfstests generic/013 now also exercises RENAME_EXCHANGE and RENAME_WHITEOUT, -// uncovering lots of problems with longnames -// -// Reject those flags with syscall.EINVAL. // If we can handle the flags, this function returns 0. func rejectRenameFlags(flags uint32) syscall.Errno { - // Normal rename, we can handle that - if flags == 0 { + switch flags { + case 0, syscallcompat.RENAME_NOREPLACE, syscallcompat.RENAME_EXCHANGE, syscallcompat.RENAME_WHITEOUT: return 0 - } - // We also can handle RENAME_NOREPLACE - if flags == syscallcompat.RENAME_NOREPLACE { + case syscallcompat.RENAME_NOREPLACE | syscallcompat.RENAME_WHITEOUT: return 0 + default: + tlog.Warn.Printf("rejectRenameFlags: unknown flag combination 0x%x", flags) + return syscall.EINVAL } - // We cannot handle RENAME_EXCHANGE and RENAME_WHITEOUT yet. - // Needs extra code for .name files. - return syscall.EINVAL } // Rename - FUSE call. @@ -472,6 +466,11 @@ func (n *Node) Rename(ctx context.Context, name string, newParent fs.InodeEmbedd } return fs.ToErrno(err) } + if flags&syscallcompat.RENAME_EXCHANGE != 0 || flags&syscallcompat.RENAME_WHITEOUT != 0 { + // These flags mean that there is now a new file at cName and we + // should NOT delete its longname file. + return 0 + } if nametransform.IsLongContent(cName) { nametransform.DeleteLongNameAt(dirfd, cName) } diff --git a/internal/syscallcompat/sys_darwin.go b/internal/syscallcompat/sys_darwin.go index de795a4..7b8773c 100644 --- a/internal/syscallcompat/sys_darwin.go +++ b/internal/syscallcompat/sys_darwin.go @@ -21,8 +21,10 @@ const ( // O_PATH is only defined on Linux O_PATH = 0 - // RENAME_NOREPLACE is only defined on Linux + // Only defined on Linux RENAME_NOREPLACE = 0 + RENAME_WHITEOUT = 0 + RENAME_EXCHANGE = 0 // KAUTH_UID_NONE and KAUTH_GID_NONE are special values to // revert permissions to the process credentials. diff --git a/internal/syscallcompat/sys_linux.go b/internal/syscallcompat/sys_linux.go index 961d1c9..a64b27e 100644 --- a/internal/syscallcompat/sys_linux.go +++ b/internal/syscallcompat/sys_linux.go @@ -28,8 +28,10 @@ const ( // O_PATH is only defined on Linux O_PATH = unix.O_PATH - // RENAME_NOREPLACE is only defined on Linux + // Only defined on Linux RENAME_NOREPLACE = unix.RENAME_NOREPLACE + RENAME_WHITEOUT = unix.RENAME_WHITEOUT + RENAME_EXCHANGE = unix.RENAME_EXCHANGE ) var preallocWarn sync.Once |