Skip to content

Commit 77ca5ca

Browse files
jazellyjasnell
authored andcommitted
fs: convert to u8 string for filesystem path
PR-URL: #54653 Fixes: #54476 Reviewed-By: Yagiz Nizipli <[email protected]> Reviewed-By: Antoine du Hamel <[email protected]> Reviewed-By: Joyee Cheung <[email protected]> Reviewed-By: James M Snell <[email protected]>
1 parent 5116578 commit 77ca5ca

File tree

4 files changed

+61
-31
lines changed

4 files changed

+61
-31
lines changed

src/node_file.cc

+46-31
Original file line numberDiff line numberDiff line change
@@ -3130,22 +3130,24 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
31303130
ToNamespacedPath(env, &src);
31313131
THROW_IF_INSUFFICIENT_PERMISSIONS(
31323132
env, permission::PermissionScope::kFileSystemRead, src.ToStringView());
3133-
auto src_path = std::filesystem::path(src.ToStringView());
3133+
3134+
auto src_path = std::filesystem::path(src.ToU8StringView());
31343135

31353136
BufferValue dest(isolate, args[1]);
31363137
CHECK_NOT_NULL(*dest);
31373138
ToNamespacedPath(env, &dest);
31383139
THROW_IF_INSUFFICIENT_PERMISSIONS(
31393140
env, permission::PermissionScope::kFileSystemWrite, dest.ToStringView());
3140-
auto dest_path = std::filesystem::path(dest.ToStringView());
31413141

3142+
auto dest_path = std::filesystem::path(dest.ToU8StringView());
31423143
bool dereference = args[2]->IsTrue();
31433144
bool recursive = args[3]->IsTrue();
31443145

31453146
std::error_code error_code;
31463147
auto src_status = dereference
31473148
? std::filesystem::symlink_status(src_path, error_code)
31483149
: std::filesystem::status(src_path, error_code);
3150+
31493151
if (error_code) {
31503152
#ifdef _WIN32
31513153
int errorno = uv_translate_sys_error(error_code.value());
@@ -3169,34 +3171,41 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
31693171
if (!error_code) {
31703172
// Check if src and dest are identical.
31713173
if (std::filesystem::equivalent(src_path, dest_path)) {
3172-
std::string message =
3173-
"src and dest cannot be the same " + dest_path.string();
3174-
return THROW_ERR_FS_CP_EINVAL(env, message.c_str());
3174+
std::u8string message =
3175+
u8"src and dest cannot be the same " + dest_path.u8string();
3176+
return THROW_ERR_FS_CP_EINVAL(
3177+
env, reinterpret_cast<const char*>(message.c_str()));
31753178
}
31763179

31773180
const bool dest_is_dir =
31783181
dest_status.type() == std::filesystem::file_type::directory;
31793182

31803183
if (src_is_dir && !dest_is_dir) {
3181-
std::string message = "Cannot overwrite non-directory " +
3182-
src_path.string() + " with directory " +
3183-
dest_path.string();
3184-
return THROW_ERR_FS_CP_DIR_TO_NON_DIR(env, message.c_str());
3184+
std::u8string message = u8"Cannot overwrite non-directory " +
3185+
src_path.u8string() + u8" with directory " +
3186+
dest_path.u8string();
3187+
return THROW_ERR_FS_CP_DIR_TO_NON_DIR(
3188+
env, reinterpret_cast<const char*>(message.c_str()));
31853189
}
31863190

31873191
if (!src_is_dir && dest_is_dir) {
3188-
std::string message = "Cannot overwrite directory " + dest_path.string() +
3189-
" with non-directory " + src_path.string();
3190-
return THROW_ERR_FS_CP_NON_DIR_TO_DIR(env, message.c_str());
3192+
std::u8string message = u8"Cannot overwrite directory " +
3193+
dest_path.u8string() + u8" with non-directory " +
3194+
src_path.u8string();
3195+
return THROW_ERR_FS_CP_NON_DIR_TO_DIR(
3196+
env, reinterpret_cast<const char*>(message.c_str()));
31913197
}
31923198
}
31933199

3194-
std::string dest_path_str = dest_path.string();
3200+
std::u8string dest_path_str = dest_path.u8string();
3201+
31953202
// Check if dest_path is a subdirectory of src_path.
3196-
if (src_is_dir && dest_path_str.starts_with(src_path.string())) {
3197-
std::string message = "Cannot copy " + src_path.string() +
3198-
" to a subdirectory of self " + dest_path.string();
3199-
return THROW_ERR_FS_CP_EINVAL(env, message.c_str());
3203+
if (src_is_dir && dest_path_str.starts_with(src_path.u8string())) {
3204+
std::u8string message = u8"Cannot copy " + src_path.u8string() +
3205+
u8" to a subdirectory of self " +
3206+
dest_path.u8string();
3207+
return THROW_ERR_FS_CP_EINVAL(
3208+
env, reinterpret_cast<const char*>(message.c_str()));
32003209
}
32013210

32023211
auto dest_parent = dest_path.parent_path();
@@ -3207,9 +3216,11 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
32073216
dest_parent.parent_path() != dest_parent) {
32083217
if (std::filesystem::equivalent(
32093218
src_path, dest_path.parent_path(), error_code)) {
3210-
std::string message = "Cannot copy " + src_path.string() +
3211-
" to a subdirectory of self " + dest_path.string();
3212-
return THROW_ERR_FS_CP_EINVAL(env, message.c_str());
3219+
std::u8string message = u8"Cannot copy " + src_path.u8string() +
3220+
u8" to a subdirectory of self " +
3221+
dest_path.u8string();
3222+
return THROW_ERR_FS_CP_EINVAL(
3223+
env, reinterpret_cast<const char*>(message.c_str()));
32133224
}
32143225

32153226
// If equivalent fails, it's highly likely that dest_parent does not exist
@@ -3221,25 +3232,29 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
32213232
}
32223233

32233234
if (src_is_dir && !recursive) {
3224-
std::string message =
3225-
"Recursive option not enabled, cannot copy a directory: " +
3226-
src_path.string();
3227-
return THROW_ERR_FS_EISDIR(env, message.c_str());
3235+
std::u8string message =
3236+
u8"Recursive option not enabled, cannot copy a directory: " +
3237+
src_path.u8string();
3238+
return THROW_ERR_FS_EISDIR(env,
3239+
reinterpret_cast<const char*>(message.c_str()));
32283240
}
32293241

32303242
switch (src_status.type()) {
32313243
case std::filesystem::file_type::socket: {
3232-
std::string message = "Cannot copy a socket file: " + dest_path.string();
3233-
return THROW_ERR_FS_CP_SOCKET(env, message.c_str());
3244+
std::u8string message = u8"Cannot copy a socket file: " + dest_path_str;
3245+
return THROW_ERR_FS_CP_SOCKET(
3246+
env, reinterpret_cast<const char*>(message.c_str()));
32343247
}
32353248
case std::filesystem::file_type::fifo: {
3236-
std::string message = "Cannot copy a FIFO pipe: " + dest_path.string();
3237-
return THROW_ERR_FS_CP_FIFO_PIPE(env, message.c_str());
3249+
std::u8string message = u8"Cannot copy a FIFO pipe: " + dest_path_str;
3250+
return THROW_ERR_FS_CP_FIFO_PIPE(
3251+
env, reinterpret_cast<const char*>(message.c_str()));
32383252
}
32393253
case std::filesystem::file_type::unknown: {
3240-
std::string message =
3241-
"Cannot copy an unknown file type: " + dest_path.string();
3242-
return THROW_ERR_FS_CP_UNKNOWN(env, message.c_str());
3254+
std::u8string message =
3255+
u8"Cannot copy an unknown file type: " + dest_path_str;
3256+
return THROW_ERR_FS_CP_UNKNOWN(
3257+
env, reinterpret_cast<const char*>(message.c_str()));
32433258
}
32443259
default:
32453260
break;

src/util.h

+4
Original file line numberDiff line numberDiff line change
@@ -562,6 +562,10 @@ class BufferValue : public MaybeStackBuffer<char> {
562562
inline std::string_view ToStringView() const {
563563
return std::string_view(out(), length());
564564
}
565+
inline std::u8string_view ToU8StringView() const {
566+
return std::u8string_view(reinterpret_cast<const char8_t*>(out()),
567+
length());
568+
}
565569
};
566570

567571
#define SPREAD_BUFFER_ARG(val, name) \
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
module.exports = {
2+
purpose: 'testing copy'
3+
};

test/parallel/test-fs-cp.mjs

+8
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,14 @@ function nextdir() {
3030

3131
// Synchronous implementation of copy.
3232

33+
// It copies a nested folder containing UTF characters.
34+
{
35+
const src = './test/fixtures/copy/utf/新建文件夹';
36+
const dest = nextdir();
37+
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
38+
assertDirEquivalent(src, dest);
39+
}
40+
3341
// It copies a nested folder structure with files and folders.
3442
{
3543
const src = './test/fixtures/copy/kitchen-sink';

0 commit comments

Comments
 (0)