mirror of
https://github.com/nodejs/node.git
synced 2024-11-21 10:59:27 +00:00
fs: convert to u8 string for filesystem path
PR-URL: https://github.com/nodejs/node/pull/54653 Fixes: https://github.com/nodejs/node/issues/54476 Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com> Reviewed-By: Joyee Cheung <joyeec9h3@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
parent
5116578b8a
commit
77ca5ca075
@ -3130,15 +3130,16 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
|
||||
ToNamespacedPath(env, &src);
|
||||
THROW_IF_INSUFFICIENT_PERMISSIONS(
|
||||
env, permission::PermissionScope::kFileSystemRead, src.ToStringView());
|
||||
auto src_path = std::filesystem::path(src.ToStringView());
|
||||
|
||||
auto src_path = std::filesystem::path(src.ToU8StringView());
|
||||
|
||||
BufferValue dest(isolate, args[1]);
|
||||
CHECK_NOT_NULL(*dest);
|
||||
ToNamespacedPath(env, &dest);
|
||||
THROW_IF_INSUFFICIENT_PERMISSIONS(
|
||||
env, permission::PermissionScope::kFileSystemWrite, dest.ToStringView());
|
||||
auto dest_path = std::filesystem::path(dest.ToStringView());
|
||||
|
||||
auto dest_path = std::filesystem::path(dest.ToU8StringView());
|
||||
bool dereference = args[2]->IsTrue();
|
||||
bool recursive = args[3]->IsTrue();
|
||||
|
||||
@ -3146,6 +3147,7 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
|
||||
auto src_status = dereference
|
||||
? std::filesystem::symlink_status(src_path, error_code)
|
||||
: std::filesystem::status(src_path, error_code);
|
||||
|
||||
if (error_code) {
|
||||
#ifdef _WIN32
|
||||
int errorno = uv_translate_sys_error(error_code.value());
|
||||
@ -3169,34 +3171,41 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
|
||||
if (!error_code) {
|
||||
// Check if src and dest are identical.
|
||||
if (std::filesystem::equivalent(src_path, dest_path)) {
|
||||
std::string message =
|
||||
"src and dest cannot be the same " + dest_path.string();
|
||||
return THROW_ERR_FS_CP_EINVAL(env, message.c_str());
|
||||
std::u8string message =
|
||||
u8"src and dest cannot be the same " + dest_path.u8string();
|
||||
return THROW_ERR_FS_CP_EINVAL(
|
||||
env, reinterpret_cast<const char*>(message.c_str()));
|
||||
}
|
||||
|
||||
const bool dest_is_dir =
|
||||
dest_status.type() == std::filesystem::file_type::directory;
|
||||
|
||||
if (src_is_dir && !dest_is_dir) {
|
||||
std::string message = "Cannot overwrite non-directory " +
|
||||
src_path.string() + " with directory " +
|
||||
dest_path.string();
|
||||
return THROW_ERR_FS_CP_DIR_TO_NON_DIR(env, message.c_str());
|
||||
std::u8string message = u8"Cannot overwrite non-directory " +
|
||||
src_path.u8string() + u8" with directory " +
|
||||
dest_path.u8string();
|
||||
return THROW_ERR_FS_CP_DIR_TO_NON_DIR(
|
||||
env, reinterpret_cast<const char*>(message.c_str()));
|
||||
}
|
||||
|
||||
if (!src_is_dir && dest_is_dir) {
|
||||
std::string message = "Cannot overwrite directory " + dest_path.string() +
|
||||
" with non-directory " + src_path.string();
|
||||
return THROW_ERR_FS_CP_NON_DIR_TO_DIR(env, message.c_str());
|
||||
std::u8string message = u8"Cannot overwrite directory " +
|
||||
dest_path.u8string() + u8" with non-directory " +
|
||||
src_path.u8string();
|
||||
return THROW_ERR_FS_CP_NON_DIR_TO_DIR(
|
||||
env, reinterpret_cast<const char*>(message.c_str()));
|
||||
}
|
||||
}
|
||||
|
||||
std::string dest_path_str = dest_path.string();
|
||||
std::u8string dest_path_str = dest_path.u8string();
|
||||
|
||||
// Check if dest_path is a subdirectory of src_path.
|
||||
if (src_is_dir && dest_path_str.starts_with(src_path.string())) {
|
||||
std::string message = "Cannot copy " + src_path.string() +
|
||||
" to a subdirectory of self " + dest_path.string();
|
||||
return THROW_ERR_FS_CP_EINVAL(env, message.c_str());
|
||||
if (src_is_dir && dest_path_str.starts_with(src_path.u8string())) {
|
||||
std::u8string message = u8"Cannot copy " + src_path.u8string() +
|
||||
u8" to a subdirectory of self " +
|
||||
dest_path.u8string();
|
||||
return THROW_ERR_FS_CP_EINVAL(
|
||||
env, reinterpret_cast<const char*>(message.c_str()));
|
||||
}
|
||||
|
||||
auto dest_parent = dest_path.parent_path();
|
||||
@ -3207,9 +3216,11 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
|
||||
dest_parent.parent_path() != dest_parent) {
|
||||
if (std::filesystem::equivalent(
|
||||
src_path, dest_path.parent_path(), error_code)) {
|
||||
std::string message = "Cannot copy " + src_path.string() +
|
||||
" to a subdirectory of self " + dest_path.string();
|
||||
return THROW_ERR_FS_CP_EINVAL(env, message.c_str());
|
||||
std::u8string message = u8"Cannot copy " + src_path.u8string() +
|
||||
u8" to a subdirectory of self " +
|
||||
dest_path.u8string();
|
||||
return THROW_ERR_FS_CP_EINVAL(
|
||||
env, reinterpret_cast<const char*>(message.c_str()));
|
||||
}
|
||||
|
||||
// If equivalent fails, it's highly likely that dest_parent does not exist
|
||||
@ -3221,25 +3232,29 @@ static void CpSyncCheckPaths(const FunctionCallbackInfo<Value>& args) {
|
||||
}
|
||||
|
||||
if (src_is_dir && !recursive) {
|
||||
std::string message =
|
||||
"Recursive option not enabled, cannot copy a directory: " +
|
||||
src_path.string();
|
||||
return THROW_ERR_FS_EISDIR(env, message.c_str());
|
||||
std::u8string message =
|
||||
u8"Recursive option not enabled, cannot copy a directory: " +
|
||||
src_path.u8string();
|
||||
return THROW_ERR_FS_EISDIR(env,
|
||||
reinterpret_cast<const char*>(message.c_str()));
|
||||
}
|
||||
|
||||
switch (src_status.type()) {
|
||||
case std::filesystem::file_type::socket: {
|
||||
std::string message = "Cannot copy a socket file: " + dest_path.string();
|
||||
return THROW_ERR_FS_CP_SOCKET(env, message.c_str());
|
||||
std::u8string message = u8"Cannot copy a socket file: " + dest_path_str;
|
||||
return THROW_ERR_FS_CP_SOCKET(
|
||||
env, reinterpret_cast<const char*>(message.c_str()));
|
||||
}
|
||||
case std::filesystem::file_type::fifo: {
|
||||
std::string message = "Cannot copy a FIFO pipe: " + dest_path.string();
|
||||
return THROW_ERR_FS_CP_FIFO_PIPE(env, message.c_str());
|
||||
std::u8string message = u8"Cannot copy a FIFO pipe: " + dest_path_str;
|
||||
return THROW_ERR_FS_CP_FIFO_PIPE(
|
||||
env, reinterpret_cast<const char*>(message.c_str()));
|
||||
}
|
||||
case std::filesystem::file_type::unknown: {
|
||||
std::string message =
|
||||
"Cannot copy an unknown file type: " + dest_path.string();
|
||||
return THROW_ERR_FS_CP_UNKNOWN(env, message.c_str());
|
||||
std::u8string message =
|
||||
u8"Cannot copy an unknown file type: " + dest_path_str;
|
||||
return THROW_ERR_FS_CP_UNKNOWN(
|
||||
env, reinterpret_cast<const char*>(message.c_str()));
|
||||
}
|
||||
default:
|
||||
break;
|
||||
|
@ -562,6 +562,10 @@ class BufferValue : public MaybeStackBuffer<char> {
|
||||
inline std::string_view ToStringView() const {
|
||||
return std::string_view(out(), length());
|
||||
}
|
||||
inline std::u8string_view ToU8StringView() const {
|
||||
return std::u8string_view(reinterpret_cast<const char8_t*>(out()),
|
||||
length());
|
||||
}
|
||||
};
|
||||
|
||||
#define SPREAD_BUFFER_ARG(val, name) \
|
||||
|
3
test/fixtures/copy/utf/新建文件夹/index.js
vendored
Normal file
3
test/fixtures/copy/utf/新建文件夹/index.js
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
module.exports = {
|
||||
purpose: 'testing copy'
|
||||
};
|
@ -30,6 +30,14 @@ function nextdir() {
|
||||
|
||||
// Synchronous implementation of copy.
|
||||
|
||||
// It copies a nested folder containing UTF characters.
|
||||
{
|
||||
const src = './test/fixtures/copy/utf/新建文件夹';
|
||||
const dest = nextdir();
|
||||
cpSync(src, dest, mustNotMutateObjectDeep({ recursive: true }));
|
||||
assertDirEquivalent(src, dest);
|
||||
}
|
||||
|
||||
// It copies a nested folder structure with files and folders.
|
||||
{
|
||||
const src = './test/fixtures/copy/kitchen-sink';
|
||||
|
Loading…
Reference in New Issue
Block a user