Skip to content

fuse: implement renamex on macOS - #108

Open
rui-augusta wants to merge 1 commit into
winfsp:masterfrom
rui-augusta:macos-renamex
Open

rui-augusta wants to merge 1 commit into
winfsp:masterfrom
rui-augusta:macos-renamex

Conversation

@rui-augusta

@rui-augusta rui-augusta commented Sep 17, 2026 •

Copy link
Copy Markdown

Fixes #107.

struct fuse_operations.renamex was never filled in, so on macOS with the FSKit backend every rename returned ENOSYS. The FSKit backend does not fall back to .rename.

The macOS flags map onto the ones Rename3 already defines, so a file system written against cgofuse sees one flag vocabulary:

renamex Rename3
RENAME_EXCL RENAME_NOREPLACE
RENAME_SWAP RENAME_EXCHANGE
RENAME_SECLUDE ENOTSUP

A file system that implements Rename only needs more than that, because an ordinary rename arrives with RENAME_EXCL rather than no flags at all, and the existing hostRename answers any non-zero flag with EINVAL. Such a file system would stay broken for the common case, so RENAME_EXCL is handled here: the destination is checked, EEXIST if it is taken, otherwise the plain Rename. RENAME_SWAP is answered with ENOTSUP, which is what renamex_np(2) specifies for a flag the file system does not support; a file system that wants it can implement Rename3.

Tested on macOS 26.5.2 with macFUSE 5.3.3, Go 1.26, using the memfs example over -o backend=fskit: rename of a file, rename of a directory, rename within a subdirectory, and a move across directories all work, where each previously failed with ENOSYS. Rename over an existing name returns ENOTSUP for memfs, as described above. go build and go vet pass on macOS and the cgo-less Windows build compiles; I have no Linux toolchain here, though the C change sits inside #if defined(__APPLE__) and the Go side is platform independent.

I could not exercise the kext backend; it is not available on macOS 26.

The macFUSE FSKit backend routes renames through renamex, which was never
filled in, so every rename failed with ENOSYS. An ordinary rename arrives with
RENAME_EXCL and a rename over an existing name with RENAME_SWAP.

The macOS flags map onto the ones Rename3 already defines: RENAME_EXCL to
RENAME_NOREPLACE and RENAME_SWAP to RENAME_EXCHANGE. A file system that
implements Rename only would otherwise remain broken for the ordinary case, so
RENAME_EXCL is handled here by checking the destination first; RENAME_SWAP and
RENAME_SECLUDE return ENOTSUP.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Development

Successfully merging this pull request may close these issues.

macOS: renames fail with ENOSYS on the FSKit backend

1 participant