@@ -3738,23 +3738,64 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
37383738 &isolate](std::filesystem::path src,
37393739 std::filesystem::path dest) {
37403740 std::error_code error;
3741- for (auto dir_entry : std::filesystem::directory_iterator (src)) {
3742- auto dest_file_path = dest / dir_entry.path ().filename ();
3741+
3742+ // Use libuv's uv_fs_scandir instead of std::filesystem::directory_iterator
3743+ // to avoid crashes with non-ASCII paths (especially GBK-encoded paths on Windows
3744+ // when running inside Electron with a buggy libc++ implementation).
3745+ auto src_str = ConvertPathToUTF8 (src);
3746+ uv_fs_t scandir_req;
3747+ int rc = uv_fs_scandir (nullptr , &scandir_req, src_str.c_str (), 0 , nullptr );
3748+ if (rc < 0 ) {
3749+ env->ThrowUVException (rc, " scandir" , src_str.c_str ());
3750+ uv_fs_req_cleanup (&scandir_req);
3751+ return false ;
3752+ }
3753+
3754+ uv_dirent_t ent;
3755+ while ((rc = uv_fs_scandir_next (&scandir_req, &ent)) != UV_EOF) {
3756+ if (rc < 0 ) {
3757+ env->ThrowUVException (rc, " scandir" , src_str.c_str ());
3758+ uv_fs_req_cleanup (&scandir_req);
3759+ return false ;
3760+ }
3761+
3762+ auto entry_name = std::filesystem::path (ent.name );
3763+ auto entry_path = src / entry_name;
3764+ auto dest_file_path = dest / entry_name;
37433765 auto dest_str = ConvertPathToUTF8 (dest);
3744-
3745- if (dir_entry.is_symlink ()) {
3766+
3767+ // Get entry type using uv_fs_lstat
3768+ uv_fs_t stat_req;
3769+ auto entry_path_str = ConvertPathToUTF8 (entry_path);
3770+ rc = uv_fs_lstat (nullptr , &stat_req, entry_path_str.c_str (), nullptr );
3771+ if (rc < 0 ) {
3772+ env->ThrowUVException (rc, " lstat" , entry_path_str.c_str ());
3773+ uv_fs_req_cleanup (&stat_req);
3774+ uv_fs_req_cleanup (&scandir_req);
3775+ return false ;
3776+ }
3777+
3778+ const uv_stat_t * stat = static_cast <const uv_stat_t *>(stat_req.ptr );
3779+ bool is_symlink = S_ISLNK (stat->st_mode );
3780+ bool is_directory = S_ISDIR (stat->st_mode );
3781+ bool is_regular = S_ISREG (stat->st_mode );
3782+ uv_fs_req_cleanup (&stat_req);
3783+
3784+ if (is_symlink) {
37463785 if (verbatim_symlinks) {
37473786 std::filesystem::copy_symlink (
3748- dir_entry. path () , dest_file_path, error);
3787+ entry_path , dest_file_path, error);
37493788 if (error) {
37503789 env->ThrowStdErrException (error, " cp" , dest_str.c_str ());
3790+ uv_fs_req_cleanup (&scandir_req);
37513791 return false ;
37523792 }
37533793 } else {
37543794 auto symlink_target =
3755- std::filesystem::read_symlink (dir_entry. path () .c_str (), error);
3795+ std::filesystem::read_symlink (entry_path .c_str (), error);
37563796 if (error) {
37573797 env->ThrowStdErrException (error, " cp" , dest_str.c_str ());
3798+ uv_fs_req_cleanup (&scandir_req);
37583799 return false ;
37593800 }
37603801
@@ -3764,6 +3805,7 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
37643805 std::filesystem::read_symlink (dest_file_path.c_str (), error);
37653806 if (error) {
37663807 env->ThrowStdErrException (error, " cp" , dest_str.c_str ());
3808+ uv_fs_req_cleanup (&scandir_req);
37673809 return false ;
37683810 }
37693811
@@ -3774,6 +3816,7 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
37743816 " Cannot copy %s to a subdirectory of self %s" ;
37753817 THROW_ERR_FS_CP_EINVAL (
37763818 env, message, symlink_target, current_dest_symlink_target);
3819+ uv_fs_req_cleanup (&scandir_req);
37773820 return false ;
37783821 }
37793822
@@ -3786,6 +3829,7 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
37863829 " cannot overwrite %s with %s" ;
37873830 THROW_ERR_FS_CP_SYMLINK_TO_SUBDIRECTORY (
37883831 env, message, current_dest_symlink_target, symlink_target);
3832+ uv_fs_req_cleanup (&scandir_req);
37893833 return false ;
37903834 }
37913835
@@ -3795,6 +3839,7 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
37953839 std::filesystem::remove (dest_file_path, error);
37963840 if (error) {
37973841 env->ThrowStdErrException (error, " cp" , dest_str.c_str ());
3842+ uv_fs_req_cleanup (&scandir_req);
37983843 return false ;
37993844 }
38003845 } else if (std::filesystem::is_regular_file (dest_file_path)) {
@@ -3804,13 +3849,14 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
38043849 std::make_error_code (std::errc::file_exists),
38053850 " cp" ,
38063851 dest_file_path_str.c_str ());
3852+ uv_fs_req_cleanup (&scandir_req);
38073853 return false ;
38083854 }
38093855 }
38103856 }
38113857 auto symlink_target_absolute = std::filesystem::weakly_canonical (
38123858 std::filesystem::absolute (src / symlink_target));
3813- if (dir_entry. is_directory () ) {
3859+ if (is_directory) {
38143860 std::filesystem::create_directory_symlink (
38153861 symlink_target_absolute, dest_file_path, error);
38163862 } else {
@@ -3819,37 +3865,42 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
38193865 }
38203866 if (error) {
38213867 env->ThrowStdErrException (error, " cp" , dest_str.c_str ());
3868+ uv_fs_req_cleanup (&scandir_req);
38223869 return false ;
38233870 }
38243871 }
3825- } else if (dir_entry.is_directory ()) {
3826- auto entry_dir_path = src / dir_entry.path ().filename ();
3872+ } else if (is_directory) {
38273873 std::filesystem::create_directory (dest_file_path);
3828- auto success = copy_dir_contents (entry_dir_path , dest_file_path);
3874+ auto success = copy_dir_contents (entry_path , dest_file_path);
38293875 if (!success) {
3876+ uv_fs_req_cleanup (&scandir_req);
38303877 return false ;
38313878 }
3832- } else if (dir_entry. is_regular_file () ) {
3879+ } else if (is_regular ) {
38333880 std::filesystem::copy_file (
3834- dir_entry. path () , dest_file_path, file_copy_opts, error);
3881+ entry_path , dest_file_path, file_copy_opts, error);
38353882 if (error) {
38363883 if (error.value () == EEXIST) {
38373884 THROW_ERR_FS_CP_EEXIST (isolate,
38383885 " [ERR_FS_CP_EEXIST]: Target already exists: "
38393886 " cp returned EEXIST (%s already exists)" ,
38403887 dest_file_path);
3888+ uv_fs_req_cleanup (&scandir_req);
38413889 return false ;
38423890 }
38433891 env->ThrowStdErrException (error, " cp" , dest_str.c_str ());
3892+ uv_fs_req_cleanup (&scandir_req);
38443893 return false ;
38453894 }
38463895
38473896 if (preserve_timestamps &&
3848- !CopyUtimes (dir_entry.path (), dest_file_path, env)) {
3897+ !CopyUtimes (entry_path, dest_file_path, env)) {
3898+ uv_fs_req_cleanup (&scandir_req);
38493899 return false ;
38503900 }
38513901 }
38523902 }
3903+ uv_fs_req_cleanup (&scandir_req);
38533904 return true ;
38543905 };
38553906
0 commit comments