Skip to content

Commit d9494a7

Browse files
jazellyaduh95
andcommittedOct 19, 2024
fs: use wstring on Windows paths
Co-authored-by: Antoine du Hamel <[email protected]> PR-URL: #55171 Reviewed-By: Rafael Gonzaga <[email protected]>
1 parent dd5a08d commit d9494a7

File tree

2 files changed

+76
-41
lines changed

2 files changed

+76
-41
lines changed
 

‎src/node_file.cc

+75-40
Original file line numberDiff line numberDiff line change
@@ -3127,6 +3127,55 @@ static void GetFormatOfExtensionlessFile(
31273127
return args.GetReturnValue().Set(EXTENSIONLESS_FORMAT_JAVASCRIPT);
31283128
}
31293129

3130+
#ifdef _WIN32
3131+
std::wstring ConvertToWideString(const std::string& str) {
3132+
int size_needed = MultiByteToWideChar(
3133+
CP_UTF8, 0, &str[0], static_cast<int>(str.size()), nullptr, 0);
3134+
std::wstring wstrTo(size_needed, 0);
3135+
MultiByteToWideChar(CP_UTF8,
3136+
0,
3137+
&str[0],
3138+
static_cast<int>(str.size()),
3139+
&wstrTo[0],
3140+
size_needed);
3141+
return wstrTo;
3142+
}
3143+
3144+
#define BufferValueToPath(str) \
3145+
std::filesystem::path(ConvertToWideString(str.ToString()))
3146+
3147+
std::string ConvertWideToUTF8(const std::wstring& wstr) {
3148+
if (wstr.empty()) return std::string();
3149+
3150+
int size_needed = WideCharToMultiByte(CP_UTF8,
3151+
0,
3152+
&wstr[0],
3153+
static_cast<int>(wstr.size()),
3154+
nullptr,
3155+
0,
3156+
nullptr,
3157+
nullptr);
3158+
std::string strTo(size_needed, 0);
3159+
WideCharToMultiByte(CP_UTF8,
3160+
0,
3161+
&wstr[0],
3162+
static_cast<int>(wstr.size()),
3163+
&strTo[0],
3164+
size_needed,
3165+
nullptr,
3166+
nullptr);
3167+
return strTo;
3168+
}
3169+
3170+
#define PathToString(path) ConvertWideToUTF8(path.wstring());
3171+
3172+
#else // _WIN32
3173+
3174+
#define BufferValueToPath(str) std::filesystem::path(str.ToStringView());
3175+
#define PathToString(path) path.native();
3176+
3177+
#endif // _WIN32
3178+
31303179
static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
31313180
Environment* env = Environment::GetCurrent(args);
31323181
Isolate* isolate = env->isolate();
@@ -3139,15 +3188,15 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
31393188
THROW_IF_INSUFFICIENT_PERMISSIONS(
31403189
env, permission::PermissionScope::kFileSystemRead, src.ToStringView());
31413190

3142-
auto src_path = std::filesystem::path(src.ToU8StringView());
3191+
auto src_path = BufferValueToPath(src);
31433192

31443193
BufferValue dest(isolate, args[1]);
31453194
CHECK_NOT_NULL(*dest);
31463195
ToNamespacedPath(env, &dest);
31473196
THROW_IF_INSUFFICIENT_PERMISSIONS(
31483197
env, permission::PermissionScope::kFileSystemWrite, dest.ToStringView());
31493198

3150-
auto dest_path = std::filesystem::path(dest.ToU8StringView());
3199+
auto dest_path = BufferValueToPath(dest);
31513200
bool dereference = args[2]->IsTrue();
31523201
bool recursive = args[3]->IsTrue();
31533202

@@ -3176,47 +3225,41 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
31763225
(src_status.type() == std::filesystem::file_type::directory) ||
31773226
(dereference && src_status.type() == std::filesystem::file_type::symlink);
31783227

3228+
auto src_path_str = PathToString(src_path);
3229+
auto dest_path_str = PathToString(dest_path);
3230+
31793231
if (!error_code) {
31803232
// Check if src and dest are identical.
31813233
if (std::filesystem::equivalent(src_path, dest_path)) {
3182-
std::u8string message =
3183-
u8"src and dest cannot be the same " + dest_path.u8string();
3184-
return THROW_ERR_FS_CP_EINVAL(
3185-
env, reinterpret_cast<const char*>(message.c_str()));
3234+
std::string message = "src and dest cannot be the same %s";
3235+
return THROW_ERR_FS_CP_EINVAL(env, message.c_str(), dest_path_str);
31863236
}
31873237

31883238
const bool dest_is_dir =
31893239
dest_status.type() == std::filesystem::file_type::directory;
3190-
31913240
if (src_is_dir && !dest_is_dir) {
3192-
std::u8string message = u8"Cannot overwrite non-directory " +
3193-
src_path.u8string() + u8" with directory " +
3194-
dest_path.u8string();
3241+
std::string message =
3242+
"Cannot overwrite non-directory %s with directory %s";
31953243
return THROW_ERR_FS_CP_DIR_TO_NON_DIR(
3196-
env, reinterpret_cast<const char*>(message.c_str()));
3244+
env, message.c_str(), src_path_str, dest_path_str);
31973245
}
31983246

31993247
if (!src_is_dir && dest_is_dir) {
3200-
std::u8string message = u8"Cannot overwrite directory " +
3201-
dest_path.u8string() + u8" with non-directory " +
3202-
src_path.u8string();
3248+
std::string message =
3249+
"Cannot overwrite directory %s with non-directory %s";
32033250
return THROW_ERR_FS_CP_NON_DIR_TO_DIR(
3204-
env, reinterpret_cast<const char*>(message.c_str()));
3251+
env, message.c_str(), dest_path_str, src_path_str);
32053252
}
32063253
}
32073254

3208-
std::u8string dest_path_str = dest_path.u8string();
3209-
std::u8string src_path_str = src_path.u8string();
32103255
if (!src_path_str.ends_with(std::filesystem::path::preferred_separator)) {
32113256
src_path_str += std::filesystem::path::preferred_separator;
32123257
}
32133258
// Check if dest_path is a subdirectory of src_path.
32143259
if (src_is_dir && dest_path_str.starts_with(src_path_str)) {
3215-
std::u8string message = u8"Cannot copy " + src_path.u8string() +
3216-
u8" to a subdirectory of self " +
3217-
dest_path.u8string();
3260+
std::string message = "Cannot copy %s to a subdirectory of self %s";
32183261
return THROW_ERR_FS_CP_EINVAL(
3219-
env, reinterpret_cast<const char*>(message.c_str()));
3262+
env, message.c_str(), src_path_str, dest_path_str);
32203263
}
32213264

32223265
auto dest_parent = dest_path.parent_path();
@@ -3227,11 +3270,9 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
32273270
dest_parent.parent_path() != dest_parent) {
32283271
if (std::filesystem::equivalent(
32293272
src_path, dest_path.parent_path(), error_code)) {
3230-
std::u8string message = u8"Cannot copy " + src_path.u8string() +
3231-
u8" to a subdirectory of self " +
3232-
dest_path.u8string();
3273+
std::string message = "Cannot copy %s to a subdirectory of self %s";
32333274
return THROW_ERR_FS_CP_EINVAL(
3234-
env, reinterpret_cast<const char*>(message.c_str()));
3275+
env, message.c_str(), src_path_str, dest_path_str);
32353276
}
32363277

32373278
// If equivalent fails, it's highly likely that dest_parent does not exist
@@ -3243,29 +3284,23 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
32433284
}
32443285

32453286
if (src_is_dir && !recursive) {
3246-
std::u8string message =
3247-
u8"Recursive option not enabled, cannot copy a directory: " +
3248-
src_path.u8string();
3249-
return THROW_ERR_FS_EISDIR(env,
3250-
reinterpret_cast<const char*>(message.c_str()));
3287+
std::string message =
3288+
"Recursive option not enabled, cannot copy a directory: %s";
3289+
return THROW_ERR_FS_EISDIR(env, message.c_str(), src_path_str);
32513290
}
32523291

32533292
switch (src_status.type()) {
32543293
case std::filesystem::file_type::socket: {
3255-
std::u8string message = u8"Cannot copy a socket file: " + dest_path_str;
3256-
return THROW_ERR_FS_CP_SOCKET(
3257-
env, reinterpret_cast<const char*>(message.c_str()));
3294+
std::string message = "Cannot copy a socket file: %s";
3295+
return THROW_ERR_FS_CP_SOCKET(env, message.c_str(), dest_path_str);
32583296
}
32593297
case std::filesystem::file_type::fifo: {
3260-
std::u8string message = u8"Cannot copy a FIFO pipe: " + dest_path_str;
3261-
return THROW_ERR_FS_CP_FIFO_PIPE(
3262-
env, reinterpret_cast<const char*>(message.c_str()));
3298+
std::string message = "Cannot copy a FIFO pipe: %s";
3299+
return THROW_ERR_FS_CP_FIFO_PIPE(env, message.c_str(), dest_path_str);
32633300
}
32643301
case std::filesystem::file_type::unknown: {
3265-
std::u8string message =
3266-
u8"Cannot copy an unknown file type: " + dest_path_str;
3267-
return THROW_ERR_FS_CP_UNKNOWN(
3268-
env, reinterpret_cast<const char*>(message.c_str()));
3302+
std::string message = "Cannot copy an unknown file type: %s";
3303+
return THROW_ERR_FS_CP_UNKNOWN(env, message.c_str(), dest_path_str);
32693304
}
32703305
default:
32713306
break;

‎test/parallel/test-fs-cp.mjs

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ tmpdir.refresh();
2525

2626
let dirc = 0;
2727
function nextdir(dirname) {
28-
return tmpdir.resolve(dirname || `copy_${++dirc}`);
28+
return tmpdir.resolve(dirname || `copy_%${++dirc}`);
2929
}
3030

3131
// Synchronous implementation of copy.

0 commit comments

Comments
 (0)
Please sign in to comment.