Skip to content

fs: pass symlink type in cp when filter is provided#62654

Open
shulaoda wants to merge 2 commits into
nodejs:mainfrom
shulaoda:04-10-fs_pass_symlink_type_in_cp_when_filter_is_provided
Open

fs: pass symlink type in cp when filter is provided#62654
shulaoda wants to merge 2 commits into
nodejs:mainfrom
shulaoda:04-10-fs_pass_symlink_type_in_cp_when_filter_is_provided

Conversation

@shulaoda
Copy link
Copy Markdown

@shulaoda shulaoda commented Apr 9, 2026

When fs.cp/fs.cpSync is called with both verbatimSymlinks: true and a filter function, directory symlinks are incorrectly created as file symlinks on Windows.

Root cause

fs.cp takes two code paths:

  • Without filter: the C++ fast path (cpSyncCopyDir) uses std::filesystem::copy_symlink() which preserves the symlink type automatically.
  • With filter: the JS fallback path calls symlinkSync(resolvedSrc, dest) without a type parameter. On Windows, symlinkSync tries to auto-detect the type by stat-ing the resolved target at the destination. During a recursive copy, the target directory may not yet exist at the destination (e.g. linked/ is copied before packages/ in alphabetical order), so stat fails and type defaults to 'file' creating a file symlink instead of a directory symlink.

Fix

Detect the symlink type from the source (which always exists) using internalModuleStat(src) and pass it explicitly to symlinkSync/symlink. The onLink function already computed srcIsDir for subdirectory validation but only after the early-return paths this change moves it before those returns and threads the derived symlinkType through to all symlinkSync/symlink call sites.

Both the sync (cp-sync.js) and async (cp.js) implementations are fixed.

Test

Added two test files that verify directory symlinks are preserved when copying with verbatimSymlinks: true and a filter function:

  • test-fs-cp-sync-verbatim-dir-symlinks-with-filter.mjs
  • test-fs-cp-async-verbatim-dir-symlinks-with-filter.mjs

Fixes: #62653

@shulaoda shulaoda marked this pull request as ready for review April 9, 2026 16:25
@nodejs-github-bot nodejs-github-bot added fs Issues and PRs related to the fs subsystem / file system. needs-ci PRs that need a full CI run. labels Apr 9, 2026
@shulaoda shulaoda force-pushed the 04-10-fs_pass_symlink_type_in_cp_when_filter_is_provided branch from 993264d to 979dcbe Compare May 17, 2026 02:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

fs Issues and PRs related to the fs subsystem / file system. needs-ci PRs that need a full CI run.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

fs.cp creates file symlink instead of directory symlink on Windows when filter is provided

5 participants