Skip to content

Commit 1a71ee2

Browse files
fs: fix cpSync to handle non-ASCII characters
Fixes: #61878
1 parent 6b5178f commit 1a71ee2

File tree

2 files changed

+34
-5
lines changed

2 files changed

+34
-5
lines changed

src/node_file.cc

Lines changed: 11 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3425,15 +3425,18 @@ static void CpSyncOverrideFile(const FunctionCallbackInfo<Value>& args) {
34253425
THROW_IF_INSUFFICIENT_PERMISSIONS(
34263426
env, permission::PermissionScope::kFileSystemWrite, dest.ToStringView());
34273427

3428+
auto src_path = src.ToPath();
3429+
auto dest_path = dest.ToPath();
3430+
34283431
std::error_code error;
34293432

3430-
if (!std::filesystem::remove(*dest, error)) {
3433+
if (!std::filesystem::remove(dest_path, error)) {
34313434
return env->ThrowStdErrException(error, "unlink", *dest);
34323435
}
34333436

34343437
if (mode == 0) {
34353438
// if no mode is specified use the faster std::filesystem API
3436-
if (!std::filesystem::copy_file(*src, *dest, error)) {
3439+
if (!std::filesystem::copy_file(src_path, dest_path, error)) {
34373440
return env->ThrowStdErrException(error, "cp", *dest);
34383441
}
34393442
} else {
@@ -3446,7 +3449,7 @@ static void CpSyncOverrideFile(const FunctionCallbackInfo<Value>& args) {
34463449
}
34473450

34483451
if (preserve_timestamps) {
3449-
CopyUtimes(*src, *dest, env);
3452+
CopyUtimes(src_path, dest_path, env);
34503453
}
34513454
}
34523455

@@ -3489,8 +3492,11 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
34893492
bool verbatim_symlinks = args[5]->IsTrue();
34903493
bool preserve_timestamps = args[6]->IsTrue();
34913494

3495+
auto src_path = src.ToPath();
3496+
auto dest_path = dest.ToPath();
3497+
34923498
std::error_code error;
3493-
std::filesystem::create_directories(*dest, error);
3499+
std::filesystem::create_directories(dest_path, error);
34943500
if (error) {
34953501
return env->ThrowStdErrException(error, "cp", *dest);
34963502
}
@@ -3632,7 +3638,7 @@ static void CpSyncCopyDir(const FunctionCallbackInfo<Value>& args) {
36323638
return true;
36333639
};
36343640

3635-
copy_dir_contents(std::filesystem::path(*src), std::filesystem::path(*dest));
3641+
copy_dir_contents(src_path, dest_path);
36363642
}
36373643

36383644
BindingData::FilePathIsFileReturnType BindingData::FilePathIsFile(
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
// Regression test for https://github.com/nodejs/node/issues/61878
2+
// fs.cpSync should copy files when destination path has UTF characters.
3+
import '../common/index.mjs';
4+
import { cpSync, mkdirSync, readdirSync, readFileSync, writeFileSync } from 'node:fs';
5+
import { join } from 'node:path';
6+
import assert from 'node:assert';
7+
import tmpdir from '../common/tmpdir.js';
8+
9+
tmpdir.refresh();
10+
11+
const src = join(tmpdir.path, 'src');
12+
mkdirSync(join(src, 'subdir'), { recursive: true });
13+
writeFileSync(join(src, 'file1.txt'), 'Hello World');
14+
writeFileSync(join(src, 'subdir', 'nested.txt'), 'Nested File');
15+
16+
const dest = join(tmpdir.path, 'Eyjafjallajökull-Pranckevičius');
17+
cpSync(src, dest, { recursive: true, force: true });
18+
19+
const destFiles = readdirSync(dest);
20+
assert.ok(destFiles.includes('file1.txt'));
21+
assert.strictEqual(readFileSync(join(dest, 'file1.txt'), 'utf8'), 'Hello World');
22+
assert.ok(destFiles.includes('subdir'));
23+
assert.strictEqual(readFileSync(join(dest, 'subdir', 'nested.txt'), 'utf8'), 'Nested File');

0 commit comments

Comments
 (0)