Skip to content

Commit 5357338

Browse files
jazellyaduh95
authored andcommitted
fs: use wstring on Windows paths
Co-authored-by: Antoine du Hamel <duhamelantoine1995@gmail.com> PR-URL: #55171 Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com>
1 parent 0e873c3 commit 5357338

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
@@ -3033,6 +3033,55 @@ static void GetFormatOfExtensionlessFile(
30333033
return args.GetReturnValue().Set(EXTENSIONLESS_FORMAT_JAVASCRIPT);
30343034
}
30353035

3036+
#ifdef _WIN32
3037+
std::wstring ConvertToWideString(const std::string& str) {
3038+
int size_needed = MultiByteToWideChar(
3039+
CP_UTF8, 0, &str[0], static_cast<int>(str.size()), nullptr, 0);
3040+
std::wstring wstrTo(size_needed, 0);
3041+
MultiByteToWideChar(CP_UTF8,
3042+
0,
3043+
&str[0],
3044+
static_cast<int>(str.size()),
3045+
&wstrTo[0],
3046+
size_needed);
3047+
return wstrTo;
3048+
}
3049+
3050+
#define BufferValueToPath(str) \
3051+
std::filesystem::path(ConvertToWideString(str.ToString()))
3052+
3053+
std::string ConvertWideToUTF8(const std::wstring& wstr) {
3054+
if (wstr.empty()) return std::string();
3055+
3056+
int size_needed = WideCharToMultiByte(CP_UTF8,
3057+
0,
3058+
&wstr[0],
3059+
static_cast<int>(wstr.size()),
3060+
nullptr,
3061+
0,
3062+
nullptr,
3063+
nullptr);
3064+
std::string strTo(size_needed, 0);
3065+
WideCharToMultiByte(CP_UTF8,
3066+
0,
3067+
&wstr[0],
3068+
static_cast<int>(wstr.size()),
3069+
&strTo[0],
3070+
size_needed,
3071+
nullptr,
3072+
nullptr);
3073+
return strTo;
3074+
}
3075+
3076+
#define PathToString(path) ConvertWideToUTF8(path.wstring());
3077+
3078+
#else // _WIN32
3079+
3080+
#define BufferValueToPath(str) std::filesystem::path(str.ToStringView());
3081+
#define PathToString(path) path.native();
3082+
3083+
#endif // _WIN32
3084+
30363085
static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
30373086
Environment* env = Environment::GetCurrent(args);
30383087
Isolate* isolate = env->isolate();
@@ -3045,15 +3094,15 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
30453094
THROW_IF_INSUFFICIENT_PERMISSIONS(
30463095
env, permission::PermissionScope::kFileSystemRead, src.ToStringView());
30473096

3048-
auto src_path = std::filesystem::path(src.ToU8StringView());
3097+
auto src_path = BufferValueToPath(src);
30493098

30503099
BufferValue dest(isolate, args[1]);
30513100
CHECK_NOT_NULL(*dest);
30523101
ToNamespacedPath(env, &dest);
30533102
THROW_IF_INSUFFICIENT_PERMISSIONS(
30543103
env, permission::PermissionScope::kFileSystemWrite, dest.ToStringView());
30553104

3056-
auto dest_path = std::filesystem::path(dest.ToU8StringView());
3105+
auto dest_path = BufferValueToPath(dest);
30573106
bool dereference = args[2]->IsTrue();
30583107
bool recursive = args[3]->IsTrue();
30593108

@@ -3082,47 +3131,41 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
30823131
(src_status.type() == std::filesystem::file_type::directory) ||
30833132
(dereference && src_status.type() == std::filesystem::file_type::symlink);
30843133

3134+
auto src_path_str = PathToString(src_path);
3135+
auto dest_path_str = PathToString(dest_path);
3136+
30853137
if (!error_code) {
30863138
// Check if src and dest are identical.
30873139
if (std::filesystem::equivalent(src_path, dest_path)) {
3088-
std::u8string message =
3089-
u8"src and dest cannot be the same " + dest_path.u8string();
3090-
return THROW_ERR_FS_CP_EINVAL(
3091-
env, reinterpret_cast<const char*>(message.c_str()));
3140+
std::string message = "src and dest cannot be the same %s";
3141+
return THROW_ERR_FS_CP_EINVAL(env, message.c_str(), dest_path_str);
30923142
}
30933143

30943144
const bool dest_is_dir =
30953145
dest_status.type() == std::filesystem::file_type::directory;
3096-
30973146
if (src_is_dir && !dest_is_dir) {
3098-
std::u8string message = u8"Cannot overwrite non-directory " +
3099-
src_path.u8string() + u8" with directory " +
3100-
dest_path.u8string();
3147+
std::string message =
3148+
"Cannot overwrite non-directory %s with directory %s";
31013149
return THROW_ERR_FS_CP_DIR_TO_NON_DIR(
3102-
env, reinterpret_cast<const char*>(message.c_str()));
3150+
env, message.c_str(), src_path_str, dest_path_str);
31033151
}
31043152

31053153
if (!src_is_dir && dest_is_dir) {
3106-
std::u8string message = u8"Cannot overwrite directory " +
3107-
dest_path.u8string() + u8" with non-directory " +
3108-
src_path.u8string();
3154+
std::string message =
3155+
"Cannot overwrite directory %s with non-directory %s";
31093156
return THROW_ERR_FS_CP_NON_DIR_TO_DIR(
3110-
env, reinterpret_cast<const char*>(message.c_str()));
3157+
env, message.c_str(), dest_path_str, src_path_str);
31113158
}
31123159
}
31133160

3114-
std::u8string dest_path_str = dest_path.u8string();
3115-
std::u8string src_path_str = src_path.u8string();
31163161
if (!src_path_str.ends_with(std::filesystem::path::preferred_separator)) {
31173162
src_path_str += std::filesystem::path::preferred_separator;
31183163
}
31193164
// Check if dest_path is a subdirectory of src_path.
31203165
if (src_is_dir && dest_path_str.starts_with(src_path_str)) {
3121-
std::u8string message = u8"Cannot copy " + src_path.u8string() +
3122-
u8" to a subdirectory of self " +
3123-
dest_path.u8string();
3166+
std::string message = "Cannot copy %s to a subdirectory of self %s";
31243167
return THROW_ERR_FS_CP_EINVAL(
3125-
env, reinterpret_cast<const char*>(message.c_str()));
3168+
env, message.c_str(), src_path_str, dest_path_str);
31263169
}
31273170

31283171
auto dest_parent = dest_path.parent_path();
@@ -3133,11 +3176,9 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
31333176
dest_parent.parent_path() != dest_parent) {
31343177
if (std::filesystem::equivalent(
31353178
src_path, dest_path.parent_path(), error_code)) {
3136-
std::u8string message = u8"Cannot copy " + src_path.u8string() +
3137-
u8" to a subdirectory of self " +
3138-
dest_path.u8string();
3179+
std::string message = "Cannot copy %s to a subdirectory of self %s";
31393180
return THROW_ERR_FS_CP_EINVAL(
3140-
env, reinterpret_cast<const char*>(message.c_str()));
3181+
env, message.c_str(), src_path_str, dest_path_str);
31413182
}
31423183

31433184
// If equivalent fails, it's highly likely that dest_parent does not exist
@@ -3149,29 +3190,23 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
31493190
}
31503191

31513192
if (src_is_dir && !recursive) {
3152-
std::u8string message =
3153-
u8"Recursive option not enabled, cannot copy a directory: " +
3154-
src_path.u8string();
3155-
return THROW_ERR_FS_EISDIR(env,
3156-
reinterpret_cast<const char*>(message.c_str()));
3193+
std::string message =
3194+
"Recursive option not enabled, cannot copy a directory: %s";
3195+
return THROW_ERR_FS_EISDIR(env, message.c_str(), src_path_str);
31573196
}
31583197

31593198
switch (src_status.type()) {
31603199
case std::filesystem::file_type::socket: {
3161-
std::u8string message = u8"Cannot copy a socket file: " + dest_path_str;
3162-
return THROW_ERR_FS_CP_SOCKET(
3163-
env, reinterpret_cast<const char*>(message.c_str()));
3200+
std::string message = "Cannot copy a socket file: %s";
3201+
return THROW_ERR_FS_CP_SOCKET(env, message.c_str(), dest_path_str);
31643202
}
31653203
case std::filesystem::file_type::fifo: {
3166-
std::u8string message = u8"Cannot copy a FIFO pipe: " + dest_path_str;
3167-
return THROW_ERR_FS_CP_FIFO_PIPE(
3168-
env, reinterpret_cast<const char*>(message.c_str()));
3204+
std::string message = "Cannot copy a FIFO pipe: %s";
3205+
return THROW_ERR_FS_CP_FIFO_PIPE(env, message.c_str(), dest_path_str);
31693206
}
31703207
case std::filesystem::file_type::unknown: {
3171-
std::u8string message =
3172-
u8"Cannot copy an unknown file type: " + dest_path_str;
3173-
return THROW_ERR_FS_CP_UNKNOWN(
3174-
env, reinterpret_cast<const char*>(message.c_str()));
3208+
std::string message = "Cannot copy an unknown file type: %s";
3209+
return THROW_ERR_FS_CP_UNKNOWN(env, message.c_str(), dest_path_str);
31753210
}
31763211
default:
31773212
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)