Fix EPERM on WSL2 9P + EFS by replacing fs.copyFileSync with read+write shim#33
Open
WeathermanTony wants to merge 1 commit into
Open
Fix EPERM on WSL2 9P + EFS by replacing fs.copyFileSync with read+write shim#33WeathermanTony wants to merge 1 commit into
WeathermanTony wants to merge 1 commit into
Conversation
fs.copyFileSync (and the underlying libuv uv_fs_copyfile) uses Linux's copy_file_range syscall as a fast path. That syscall fails with EPERM when the destination is on a Windows volume mounted via WSL2 9P AND the destination directory has the EFS Encrypted attribute. This makes `openwolf init` and `openwolf update` unusable on any Windows-EFS path opened from WSL. Plain read+write avoids copy_file_range and works in all cases. Add safeCopyFile to utils/fs-safe.ts (matching the existing safe-write pattern) and replace all 12 fs.copyFileSync call sites in cli/init.ts and cli/update.ts. Reproduction: 1. On Windows, mark a directory EFS-encrypted (cipher /e <dir>) 2. Open WSL2, cd into the directory via /mnt/<drive> 3. openwolf init -> EPERM at fs.copyFileSync of OPENWOLF.md After this change: init and update succeed; new files inherit the parent's Encrypted attribute correctly via standard NTFS inheritance. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
openwolf initandopenwolf updatefail withEPERMwhen run from WSL2 on a Windows path that's EFS-encrypted. Root cause is not OpenWolf — it's a libuv quirk:fs.copyFileSyncuses thecopy_file_rangesyscall on Linux as a fast path, and that syscall fails on the WSL2 9P filesystem when the destination directory has the NTFSEncryptedattribute. Plainread()+write()works fine in the same conditions.This PR adds a
safeCopyFileshim inutils/fs-safe.ts(matching the existingwriteJSON/writeTextsafe-write pattern) and routes all 12fs.copyFileSynccall sites incli/init.tsandcli/update.tsthrough it.Reproduction
After this PR:
initandupdatesucceed; new files correctly inherit the parent'sEncryptedattribute via standard NTFS inheritance.Why a shim instead of switching to streams or
cpfs-safe.tsstyle (already wrapswriteFileSyncfor the Windows-rename quirk)fs.copyFileSync— every call site is a one-token renameread+writeis fine for the file sizes OpenWolf copies (small templates and hook scripts; not multi-GB blobs wherecopy_file_rangewould actually matter)Verified isolation of the bug
Test plan
/mnt/j/...openwolf initruns to completion (13 template files copied, hooks registered, daemon started)Encryptedattributepnpm exec tscbuilds clean with no new diagnosticscopyFileSyncfor the contents OpenWolf copies (small text/JS files), so this should be a no-op on any platform🤖 Generated with Claude Code