Skip to content

Commit 999d23f

Browse files
committed
src: fix cpSyncCopyDir to dereference symlinks when dereference option is set
When fs.cpSync() is called with {dereference: true}, symlinks in the source directory should be followed and their targets copied to the destination instead of creating new symlinks. This behavior was correctly implemented in the JavaScript version of cpSync, but was lost when the inner copyDir loop was migrated to C++ in CpSyncCopyDir(). The dereference parameter was captured but only used for error-condition checks, not to decide whether to create a symlink or copy the actual content. Fix by checking dereference before creating symlinks: when true, copy the actual file (using copy_file) or recurse into the actual directory (using copy_dir_contents) that the symlink points to. Fixes: #59168
1 parent 61102cd commit 999d23f

File tree

1 file changed

+32
-5
lines changed

1 file changed

+32
-5
lines changed

src/node_file.cc

Lines changed: 32 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3595,16 +3595,43 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
35953595
}
35963596
auto symlink_target_absolute = std::filesystem::weakly_canonical(
35973597
std::filesystem::absolute(src / symlink_target));
3598-
if (dir_entry.is_directory()) {
3598+
if (dereference) {
3599+
// When dereference is true, copy the actual content the symlink
3600+
// points to rather than creating a new symlink at the destination.
3601+
error.clear();
3602+
if (std::filesystem::is_directory(symlink_target_absolute, error)) {
3603+
std::filesystem::create_directory(dest_file_path, error);
3604+
if (error) {
3605+
env->ThrowStdErrException(error, "cp", dest_str.c_str());
3606+
return false;
3607+
}
3608+
auto success =
3609+
copy_dir_contents(symlink_target_absolute, dest_file_path);
3610+
if (!success) return false;
3611+
} else {
3612+
error.clear();
3613+
std::filesystem::copy_file(
3614+
symlink_target_absolute, dest_file_path, file_copy_opts,
3615+
error);
3616+
if (error) {
3617+
env->ThrowStdErrException(error, "cp", dest_str.c_str());
3618+
return false;
3619+
}
3620+
}
3621+
} else if (dir_entry.is_directory()) {
35993622
std::filesystem::create_directory_symlink(
36003623
symlink_target_absolute, dest_file_path, error);
3624+
if (error) {
3625+
env->ThrowStdErrException(error, "cp", dest_str.c_str());
3626+
return false;
3627+
}
36013628
} else {
36023629
std::filesystem::create_symlink(
36033630
symlink_target_absolute, dest_file_path, error);
3604-
}
3605-
if (error) {
3606-
env->ThrowStdErrException(error, "cp", dest_str.c_str());
3607-
return false;
3631+
if (error) {
3632+
env->ThrowStdErrException(error, "cp", dest_str.c_str());
3633+
return false;
3634+
}
36083635
}
36093636
}
36103637
} else if (dir_entry.is_directory()) {

0 commit comments

Comments
 (0)