Port: port/pr-33-fix/copyfile-efs-wsl2#9
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>
|
Now I have everything I need. Let me analyze the diff thoroughly. PR #9 Code Review:
|
| Severity | Count | Issue |
|---|---|---|
| 🔴 Critical | 1 | Non-atomic write risks partial/corrupt destination files |
| 🟡 Warning | 2 | Undocumented empty catch; silent dir creation changes stated contract |
The core fix (using read+write instead of copy_file_range) is correct and necessary. The main concern before merging is aligning safeCopyFile with the atomic write pattern already established in fs-safe.ts, particularly for hook scripts that Claude Code runs directly.
|
Autofixer skipped: merge conflicts with main detected. |
4 similar comments
|
Autofixer skipped: merge conflicts with main detected. |
|
Autofixer skipped: merge conflicts with main detected. |
|
Autofixer skipped: merge conflicts with main detected. |
|
Autofixer skipped: merge conflicts with main detected. |
Resolved conflict in src/cli/init.ts: kept main's refactored structure (helpers extracted to hook-settings.ts and templates.ts) while applying the safeCopyFile shim from this branch to writeHooks, writeSettings, and writeClaudeRules. Preserved the upgrade-vs-fresh-init summary from HEAD; dropped the undefined daemonStatus reference and the ~250 lines of inline helpers that duplicated what main already extracted. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
…1, WR-01, WR-02) - Wrap write in temp+rename pattern (matches writeJSON/writeText) so an interrupted copy leaves no partially-written hook script at the destination (CR-01) - On write/rename failure, unlink the tmp file before re-throwing so no orphan is left behind - Add explanatory comment to the empty chmod catch block (WR-01) - Update docstring to note the two semantic differences from fs.copyFileSync: read+write bypass and silent dest-dir creation (WR-02) Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
|
✅ Autofixer applied. Build and tests passed. Promoting to Ready for Review. |
Ported from upstream cytostack/openwolf. Needs review before merge.