mirror of
https://github.com/nodejs/node.git
synced 2026-10-28 10:15:07 +08:00
deps: cherry-pick libuv/libuv@e640dc9
Signed-off-by: ulofiai <monsterking@tutamail.com> PR-URL: https://github.com/nodejs/node/pull/65118 Fixes: https://github.com/nodejs/node/issues/63638 Refs: https://github.com/libuv/libuv/pull/5152 Refs: https://github.com/libuv/libuv/commit/e640dc93c79e1b930e320853a5f9f65fa489158d Reviewed-By: Antoine du Hamel <duhamelantoine1995@gmail.com>
This commit is contained in:
1 parent
9cf2ce75f2
commit
38e3955691
2 files changed
+115
-27
No files matched your search
Vendored
+24
-10
@@ -63,13 +63,17 @@ static void uv__fs_event_queue_readdirchanges(uv_loop_t* loop,
|
||||
handle->req_pending = 1;
|
||||
}
|
||||
|
||||
static void uv__relative_path(const WCHAR* filename,
|
||||
const WCHAR* dir,
|
||||
WCHAR** relpath) {
|
||||
/* Compute the path of `filename` relative to the watched directory `dir`.
|
||||
* Returns 0 on success, -1 if `filename` is not actually prefixed by `dir`,
|
||||
* which can happen if the directory is a short path. */
|
||||
static int uv__relative_path(const WCHAR* filename,
|
||||
const WCHAR* dir,
|
||||
WCHAR** relpath) {
|
||||
size_t relpathlen;
|
||||
size_t filenamelen = wcslen(filename);
|
||||
size_t dirlen = wcslen(dir);
|
||||
assert(!_wcsnicmp(filename, dir, dirlen));
|
||||
if (filenamelen <= dirlen || _wcsnicmp(filename, dir, dirlen) != 0)
|
||||
return -1;
|
||||
if (dirlen > 0 && dir[dirlen - 1] == '\\')
|
||||
dirlen--;
|
||||
relpathlen = filenamelen - dirlen - 1;
|
||||
@@ -78,6 +82,7 @@ static void uv__relative_path(const WCHAR* filename,
|
||||
uv_fatal_error(ERROR_OUTOFMEMORY, "uv__malloc");
|
||||
wcsncpy(*relpath, filename + dirlen + 1, relpathlen);
|
||||
(*relpath)[relpathlen] = L'\0';
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int uv__split_path(const WCHAR* filename, WCHAR** dir,
|
||||
@@ -517,12 +522,21 @@ void uv__process_fs_event_req(uv_loop_t* loop, uv_req_t* req,
|
||||
|
||||
if (long_filenamew) {
|
||||
/* Get the file name out of the long path. */
|
||||
uv__relative_path(long_filenamew,
|
||||
handle->dirw,
|
||||
&filenamew);
|
||||
uv__free(long_filenamew);
|
||||
long_filenamew = filenamew;
|
||||
sizew = -1;
|
||||
if (uv__relative_path(long_filenamew,
|
||||
handle->dirw,
|
||||
&filenamew) == 0) {
|
||||
uv__free(long_filenamew);
|
||||
long_filenamew = filenamew;
|
||||
sizew = -1;
|
||||
} else {
|
||||
/* The resolved long path was not prefixed by the watched
|
||||
* directory (e.g. short name vs long name mismatch),
|
||||
* fall back to the name given by ReadDirectoryChangesW. */
|
||||
uv__free(long_filenamew);
|
||||
long_filenamew = NULL;
|
||||
filenamew = file_info->FileName;
|
||||
sizew = file_info->FileNameLength / sizeof(WCHAR);
|
||||
}
|
||||
} else {
|
||||
/* We couldn't get the long filename, use the one reported. */
|
||||
filenamew = file_info->FileName;
|
||||
|
||||
Vendored
+91
-17
@@ -587,32 +587,107 @@ TEST_IMPL(fs_event_watch_dir_recursive) {
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
static char short_path_file[MAX_PATH];
|
||||
|
||||
static void short_path_timer_cb(uv_timer_t* handle) {
|
||||
++timer_cb_called;
|
||||
touch_file(short_path_file);
|
||||
}
|
||||
|
||||
/* Try to create a unique watch directory that has a 8.3 short component
|
||||
under `parent` ("" means the cwd). If it's successful, fills `watch_dir`
|
||||
and `short_dir` with the long and short forms of the created directory
|
||||
respectively, and returns 1. Otherwise removes the directory created
|
||||
and returns 0. */
|
||||
static int short_path_make(const char* parent,
|
||||
char* watch_dir, size_t watch_n,
|
||||
char* short_dir, size_t short_n) {
|
||||
uv_fs_t req;
|
||||
char tmpl[MAX_PATH];
|
||||
WCHAR watch_dirw[MAX_PATH];
|
||||
WCHAR short_dirw[MAX_PATH];
|
||||
WCHAR long_dirw[MAX_PATH];
|
||||
size_t pathlen;
|
||||
int r;
|
||||
|
||||
if (parent[0] != '\0')
|
||||
r = snprintf(tmpl, sizeof(tmpl), "%s\\watch_dirXXXXXX", parent);
|
||||
else
|
||||
r = snprintf(tmpl, sizeof(tmpl), "watch_dirXXXXXX");
|
||||
if (r < 0 || (size_t) r >= sizeof(tmpl))
|
||||
return 0;
|
||||
|
||||
r = uv_fs_mkdtemp(NULL, &req, tmpl, NULL);
|
||||
if (r != 0) {
|
||||
uv_fs_req_cleanup(&req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Copy the created path out before cleaning up the request that owns it. */
|
||||
pathlen = strlen(req.path);
|
||||
memcpy(watch_dir, req.path, pathlen + 1);
|
||||
uv_fs_req_cleanup(&req);
|
||||
|
||||
/* The caller appends "\\file1" to both watch_dir and short_dir. If there is
|
||||
no room for that suffix, skip this location. */
|
||||
if (pathlen + sizeof("\\file1") <= watch_n &&
|
||||
MultiByteToWideChar(CP_UTF8, 0, watch_dir, -1,
|
||||
watch_dirw, ARRAY_SIZE(watch_dirw)) != 0 &&
|
||||
GetShortPathNameW(watch_dirw, short_dirw, ARRAY_SIZE(short_dirw)) != 0 &&
|
||||
GetLongPathNameW(watch_dirw, long_dirw, ARRAY_SIZE(long_dirw)) != 0 &&
|
||||
_wcsicmp(short_dirw, long_dirw) != 0 &&
|
||||
WideCharToMultiByte(CP_UTF8, 0, short_dirw, -1,
|
||||
short_dir, (int) short_n, NULL, NULL) != 0)
|
||||
return 1;
|
||||
|
||||
uv_fs_rmdir(NULL, &req, watch_dir, NULL);
|
||||
uv_fs_req_cleanup(&req);
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(fs_event_watch_dir_short_path) {
|
||||
uv_loop_t* loop;
|
||||
uv_fs_t req;
|
||||
char temp_path[MAX_PATH];
|
||||
char watch_dir[MAX_PATH];
|
||||
char watch_file[MAX_PATH];
|
||||
char short_dir[MAX_PATH];
|
||||
size_t temp_len;
|
||||
int has_shortnames;
|
||||
int r;
|
||||
|
||||
/* Setup */
|
||||
loop = uv_default_loop();
|
||||
delete_file("watch_dir/file1");
|
||||
delete_dir("watch_dir/");
|
||||
create_dir("watch_dir");
|
||||
create_file("watch_dir/file1");
|
||||
|
||||
/* Newer version of Windows ship with
|
||||
HKLM\SYSTEM\CurrentControlSet\Control\FileSystem\NtfsDisable8dot3NameCreation
|
||||
not equal to 0. So we verify the files we created are addressable by a 8.3
|
||||
short name */
|
||||
has_shortnames = uv_fs_stat(NULL, &req, "watch_~1", NULL) != UV_ENOENT;
|
||||
/* This test needs the watched directory to have an 8.3 short component. The
|
||||
generated "watch_dirXXXXXX" name is > 8 chars, so it gets a short alias on
|
||||
volumes where 8.3 name creation is enabled. For non-system volumes on
|
||||
newer Windows it's disabled by default (NtfsDisable8dot3NameCreation=3).
|
||||
The temp dir and the cwd may be on different volumes, so try each and use
|
||||
whichever has a short alias, and skip if neither does. */
|
||||
has_shortnames = 0;
|
||||
temp_len = sizeof(temp_path);
|
||||
if (uv_os_tmpdir(temp_path, &temp_len) == 0)
|
||||
has_shortnames = short_path_make(temp_path,
|
||||
watch_dir, sizeof(watch_dir),
|
||||
short_dir, sizeof(short_dir));
|
||||
if (!has_shortnames)
|
||||
has_shortnames = short_path_make("",
|
||||
watch_dir, sizeof(watch_dir),
|
||||
short_dir, sizeof(short_dir));
|
||||
|
||||
if (has_shortnames) {
|
||||
snprintf(watch_file, sizeof(watch_file), "%s\\file1", watch_dir);
|
||||
/* short_path_file is used in the timer callback to touch the file. */
|
||||
snprintf(short_path_file, sizeof(short_path_file), "%s\\file1", short_dir);
|
||||
/* The directory was just created, so file1 cannot exist yet. */
|
||||
create_file(watch_file);
|
||||
|
||||
r = uv_fs_event_init(loop, &fs_event);
|
||||
ASSERT_OK(r);
|
||||
r = uv_fs_event_start(&fs_event, fs_event_cb_dir, "watch_~1", 0);
|
||||
r = uv_fs_event_start(&fs_event, fs_event_cb_dir, short_dir, 0);
|
||||
ASSERT_OK(r);
|
||||
r = uv_timer_init(loop, &timer);
|
||||
ASSERT_OK(r);
|
||||
r = uv_timer_start(&timer, timer_cb_file, 100, 0);
|
||||
r = uv_timer_start(&timer, short_path_timer_cb, 100, 0);
|
||||
ASSERT_OK(r);
|
||||
|
||||
uv_run(loop, UV_RUN_DEFAULT);
|
||||
@@ -620,12 +695,11 @@ TEST_IMPL(fs_event_watch_dir_short_path) {
|
||||
ASSERT_EQ(1, fs_event_cb_called);
|
||||
ASSERT_EQ(1, timer_cb_called);
|
||||
ASSERT_EQ(1, close_cb_called);
|
||||
/* Cleanup */
|
||||
delete_file(watch_file);
|
||||
delete_dir(watch_dir);
|
||||
}
|
||||
|
||||
/* Cleanup */
|
||||
delete_file("watch_dir/file1");
|
||||
delete_dir("watch_dir/");
|
||||
|
||||
MAKE_VALGRIND_HAPPY(loop);
|
||||
|
||||
if (!has_shortnames)
|
||||
|
||||
Reference in new issue
Block a user