This commit is contained in:
11soda11 2026-03-31 13:01:44 +00:00 committed by GitHub
commit 25026f2bf6
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 42 additions and 56 deletions

View File

@ -191,8 +191,6 @@ static int fs__readlink_handle(HANDLE handle,
WCHAR* w_target;
DWORD w_target_len;
DWORD bytes;
size_t i;
size_t len;
if (!DeviceIoControl(handle,
FSCTL_GET_REPARSE_POINT,
@ -303,38 +301,6 @@ static int fs__readlink_handle(HANDLE handle,
w_target += 4;
w_target_len -= 4;
} else if (reparse_data->ReparseTag == IO_REPARSE_TAG_APPEXECLINK) {
/* String #3 in the list has the target filename. */
if (reparse_data->AppExecLinkReparseBuffer.StringCount < 3) {
SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
return -1;
}
w_target = reparse_data->AppExecLinkReparseBuffer.StringList;
/* The StringList buffer contains a list of strings separated by "\0", */
/* with "\0\0" terminating the list. Move to the 3rd string in the list: */
for (i = 0; i < 2; ++i) {
len = wcslen(w_target);
if (len == 0) {
SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
return -1;
}
w_target += len + 1;
}
w_target_len = wcslen(w_target);
if (w_target_len == 0) {
SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
return -1;
}
/* Make sure it is an absolute path. */
if (!(w_target_len >= 3 &&
((w_target[0] >= L'a' && w_target[0] <= L'z') ||
(w_target[0] >= L'A' && w_target[0] <= L'Z')) &&
w_target[1] == L':' &&
w_target[2] == L'\\')) {
SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
return -1;
}
} else {
/* Reparse tag does not indicate a symlink. */
SetLastError(ERROR_SYMLINK_NOT_SUPPORTED);
@ -345,6 +311,33 @@ static int fs__readlink_handle(HANDLE handle,
return uv_utf16_to_wtf8(w_target, w_target_len, target_ptr, target_len_ptr);
}
/* CreateFileW wrapper. Treats reparse points which windows can't resolve as regular files */
static HANDLE fs__create_file(WCHAR* path, DWORD desired_access, int do_lstat) {
if (!do_lstat) {
HANDLE handle;
handle = CreateFileW(path,
desired_access,
FILE_SHARE_READ | FILE_SHARE_WRITE |
FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (handle != INVALID_HANDLE_VALUE
|| GetLastError() != ERROR_CANT_ACCESS_FILE)
return handle;
}
return CreateFileW(path,
desired_access,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_FLAG_BACKUP_SEMANTICS | FILE_FLAG_OPEN_REPARSE_POINT,
NULL);
}
static int fs__capture_path(uv_fs_t* req,
const char* path,
@ -2216,17 +2209,7 @@ static DWORD fs__stat_impl_from_path(WCHAR* path,
}
/* If the new API does not exist, use the old API. */
flags = FILE_FLAG_BACKUP_SEMANTICS;
if (do_lstat)
flags |= FILE_FLAG_OPEN_REPARSE_POINT;
handle = CreateFileW(path,
FILE_READ_ATTRIBUTES,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
flags,
NULL);
handle = fs__create_file(path, FILE_READ_ATTRIBUTES, do_lstat);
if (handle == INVALID_HANDLE_VALUE) {
ret = GetLastError();

View File

@ -4177,10 +4177,6 @@ typedef struct _REPARSE_DATA_BUFFER {
struct {
UCHAR DataBuffer[1];
} GenericReparseBuffer;
struct {
ULONG StringCount;
WCHAR StringList[1];
} AppExecLinkReparseBuffer;
};
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
@ -4589,9 +4585,6 @@ typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
#ifndef IO_REPARSE_TAG_LX_SYMLINK
# define IO_REPARSE_TAG_LX_SYMLINK (0xA000001DL)
#endif
#ifndef IO_REPARSE_TAG_APPEXECLINK
# define IO_REPARSE_TAG_APPEXECLINK (0x8000001BL)
#endif
typedef VOID (NTAPI *PIO_APC_ROUTINE)
(PVOID ApcContext,

View File

@ -2790,7 +2790,7 @@ TEST_FS_IMPL(fs_readlink_lx_symlink) {
return 0;
}
TEST_FS_IMPL(fs_lstat_windows_store_apps) {
TEST_FS_IMPL(fs_stat_windows_store_apps) {
uv_loop_t* loop;
char localappdata[MAX_PATH];
char windowsapps_path[MAX_PATH];
@ -2798,6 +2798,7 @@ TEST_FS_IMPL(fs_lstat_windows_store_apps) {
size_t len;
int r;
uv_fs_t req;
uv_fs_t lstat_req;
uv_fs_t stat_req;
uv_dirent_t dirent;
@ -2835,7 +2836,16 @@ TEST_FS_IMPL(fs_lstat_windows_store_apps) {
dirent.name) < 0) {
continue;
}
ASSERT_OK(uv_fs_lstat(loop, &stat_req, file_path, NULL));
ASSERT_OK(uv_fs_lstat(loop, &lstat_req, file_path, NULL));
ASSERT_OK(uv_fs_stat(loop, &stat_req, file_path, NULL));
/* Appexeclinks should be treated as regular files,
* so stat should return the same info as lstat
* see https://github.com/libuv/libuv/pull/4936#issuecomment-3703811492
* */
ASSERT_OK(strcmp(stat_req.path, lstat_req.path));
ASSERT_OK(memcmp(&stat_req.statbuf, &lstat_req.statbuf,
sizeof(stat_req.statbuf)));
}
MAKE_VALGRIND_HAPPY(loop);
return 0;

View File

@ -392,7 +392,7 @@ TEST_FS_DECLARE (fs_symlink_dir)
TEST_FS_DECLARE (fs_symlink_junction)
TEST_FS_DECLARE (fs_non_symlink_reparse_point)
TEST_FS_DECLARE (fs_readlink_lx_symlink)
TEST_FS_DECLARE (fs_lstat_windows_store_apps)
TEST_FS_DECLARE (fs_stat_windows_store_apps)
TEST_FS_DECLARE (fs_open_flags)
#endif
#if defined(_WIN32) && !defined(USING_UV_SHARED)
@ -1132,7 +1132,7 @@ TASK_LIST_START
TEST_FS_ENTRY (fs_symlink_junction)
TEST_FS_ENTRY (fs_non_symlink_reparse_point)
TEST_FS_ENTRY (fs_readlink_lx_symlink)
TEST_FS_ENTRY (fs_lstat_windows_store_apps)
TEST_FS_ENTRY (fs_stat_windows_store_apps)
TEST_FS_ENTRY (fs_open_flags)
#endif
#if defined(_WIN32) && !defined(USING_UV_SHARED)