win, fs: add IO_REPARSE_TAG_APPEXECLINK support
Adds support for IO_REPARSE_TAG_APPEXECLINK reparse points, used by Windows Store. Ref: https://github.com/nodejs/node/issues/33024 PR-URL: https://github.com/libuv/libuv/pull/2812 Reviewed-By: Ben Noordhuis <info@bnoordhuis.nl> Reviewed-By: Richard Lau <riclau@uk.ibm.com>
This commit is contained in:
parent
457285827c
commit
e7ebae2624
@ -72,6 +72,7 @@ int uv_translate_sys_error(int sys_errno) {
|
||||
case ERROR_NOACCESS: return UV_EACCES;
|
||||
case WSAEACCES: return UV_EACCES;
|
||||
case ERROR_ELEVATION_REQUIRED: return UV_EACCES;
|
||||
case ERROR_CANT_ACCESS_FILE: return UV_EACCES;
|
||||
case ERROR_ADDRESS_ALREADY_ASSOCIATED: return UV_EADDRINUSE;
|
||||
case WSAEADDRINUSE: return UV_EADDRINUSE;
|
||||
case WSAEADDRNOTAVAIL: return UV_EADDRNOTAVAIL;
|
||||
|
||||
34
src/win/fs.c
34
src/win/fs.c
@ -322,6 +322,8 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
|
||||
WCHAR* w_target;
|
||||
DWORD w_target_len;
|
||||
DWORD bytes;
|
||||
size_t i;
|
||||
size_t len;
|
||||
|
||||
if (!DeviceIoControl(handle,
|
||||
FSCTL_GET_REPARSE_POINT,
|
||||
@ -406,6 +408,38 @@ INLINE static int fs__readlink_handle(HANDLE handle, char** target_ptr,
|
||||
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);
|
||||
|
||||
@ -4152,6 +4152,10 @@ typedef const UNICODE_STRING *PCUNICODE_STRING;
|
||||
struct {
|
||||
UCHAR DataBuffer[1];
|
||||
} GenericReparseBuffer;
|
||||
struct {
|
||||
ULONG StringCount;
|
||||
WCHAR StringList[1];
|
||||
} AppExecLinkReparseBuffer;
|
||||
};
|
||||
} REPARSE_DATA_BUFFER, *PREPARSE_DATA_BUFFER;
|
||||
#endif
|
||||
@ -4517,6 +4521,9 @@ typedef struct _SYSTEM_PROCESSOR_PERFORMANCE_INFORMATION {
|
||||
#ifndef IO_REPARSE_TAG_SYMLINK
|
||||
# define IO_REPARSE_TAG_SYMLINK (0xA000000CL)
|
||||
#endif
|
||||
#ifndef IO_REPARSE_TAG_APPEXECLINK
|
||||
# define IO_REPARSE_TAG_APPEXECLINK (0x8000001BL)
|
||||
#endif
|
||||
|
||||
typedef VOID (NTAPI *PIO_APC_ROUTINE)
|
||||
(PVOID ApcContext,
|
||||
|
||||
@ -2453,6 +2453,57 @@ TEST_IMPL(fs_non_symlink_reparse_point) {
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
|
||||
TEST_IMPL(fs_lstat_windows_store_apps) {
|
||||
uv_loop_t* loop;
|
||||
char localappdata[MAX_PATH];
|
||||
char windowsapps_path[MAX_PATH];
|
||||
char file_path[MAX_PATH];
|
||||
size_t len;
|
||||
int r;
|
||||
uv_fs_t req;
|
||||
uv_fs_t stat_req;
|
||||
uv_dirent_t dirent;
|
||||
|
||||
loop = uv_default_loop();
|
||||
ASSERT_NOT_NULL(loop);
|
||||
len = sizeof(localappdata);
|
||||
r = uv_os_getenv("LOCALAPPDATA", localappdata, &len);
|
||||
if (r == UV_ENOENT) {
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return TEST_SKIP;
|
||||
}
|
||||
ASSERT_EQ(r, 0);
|
||||
r = snprintf(windowsapps_path,
|
||||
sizeof(localappdata),
|
||||
"%s\\Microsoft\\WindowsApps",
|
||||
localappdata);
|
||||
ASSERT_GT(r, 0);
|
||||
if (uv_fs_opendir(loop, &req, windowsapps_path, NULL) != 0) {
|
||||
/* If we cannot read the directory, skip the test. */
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return TEST_SKIP;
|
||||
}
|
||||
if (uv_fs_scandir(loop, &req, windowsapps_path, 0, NULL) <= 0) {
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return TEST_SKIP;
|
||||
}
|
||||
while (uv_fs_scandir_next(&req, &dirent) != UV_EOF) {
|
||||
if (dirent.type != UV_DIRENT_LINK) {
|
||||
continue;
|
||||
}
|
||||
if (snprintf(file_path,
|
||||
sizeof(file_path),
|
||||
"%s\\%s",
|
||||
windowsapps_path,
|
||||
dirent.name) < 0) {
|
||||
continue;
|
||||
}
|
||||
ASSERT_EQ(uv_fs_lstat(loop, &stat_req, file_path, NULL), 0);
|
||||
}
|
||||
MAKE_VALGRIND_HAPPY();
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
@ -346,6 +346,7 @@ TEST_DECLARE (fs_symlink_dir)
|
||||
#ifdef _WIN32
|
||||
TEST_DECLARE (fs_symlink_junction)
|
||||
TEST_DECLARE (fs_non_symlink_reparse_point)
|
||||
TEST_DECLARE (fs_lstat_windows_store_apps)
|
||||
TEST_DECLARE (fs_open_flags)
|
||||
#endif
|
||||
#if defined(_WIN32) && !defined(USING_UV_SHARED)
|
||||
@ -979,6 +980,7 @@ TASK_LIST_START
|
||||
#ifdef _WIN32
|
||||
TEST_ENTRY (fs_symlink_junction)
|
||||
TEST_ENTRY (fs_non_symlink_reparse_point)
|
||||
TEST_ENTRY (fs_lstat_windows_store_apps)
|
||||
TEST_ENTRY (fs_open_flags)
|
||||
#endif
|
||||
#if defined(_WIN32) && !defined(USING_UV_SHARED)
|
||||
|
||||
Loading…
Reference in New Issue
Block a user