Support absolute Windows path

Signed-off-by: Yage Hu <me@huyage.dev>
This commit is contained in:
Yage Hu 2024-06-18 16:19:07 -07:00
parent bddf83220e
commit 1dc6e1d5d3
2 changed files with 59 additions and 10 deletions

View File

@ -35,6 +35,7 @@
/* <winioctl.h> requires <windows.h>, included via "uv.h" above, but needs to
be included before our "winapi.h", included via "internal.h" below. */
#include <winioctl.h>
#include <shlwapi.h>
#include "internal.h"
#include "req-inl.h"
@ -732,6 +733,7 @@ void fs__openat(uv_fs_t* req) {
int flags = req->fs.info.file_flags;
struct uv__fd_info_s fd_info;
WCHAR * path = req->file.pathw;
size_t path_len = wcslen(path);
struct path rebuilt_path;
int i;
@ -740,11 +742,23 @@ void fs__openat(uv_fs_t* req) {
if (path[i] == L'/')
path[i] = L'\\';
HANDLE dir_handle = (HANDLE) _get_osfhandle(req->fs.info.fd_out);
HANDLE root_dir_handle = dir_handle;
if (dir_handle == INVALID_HANDLE_VALUE) {
SET_REQ_WIN32_ERROR(req, (DWORD) UV_EBADF);
return;
HANDLE root_dir_handle = 0;
HANDLE dir_handle;
BOOL is_absolute = FALSE;
if (
(path_len > 0 && path[0] == L'\\') ||
(path_len > 2 && path[1] == L':' && path[2] == L'\\')
) is_absolute = TRUE;
if (!is_absolute) {
dir_handle = (HANDLE) _get_osfhandle(req->fs.info.fd_out);
if (dir_handle == INVALID_HANDLE_VALUE) {
SET_REQ_WIN32_ERROR(req, (DWORD) UV_EBADF);
return;
}
root_dir_handle = dir_handle;
}
uv__path_init(&rebuilt_path);
@ -757,7 +771,7 @@ void fs__openat(uv_fs_t* req) {
// Do nothing.
} else if (!wcscmp(L"..", token)) {
// If rebuilt_path is empty, set it to the path of the parent direcotry.
if (rebuilt_path.len == 0) {
if (rebuilt_path.len == 0 && !is_absolute) {
DWORD dir_path_len = GetFinalPathNameByHandleW(dir_handle, NULL, 0, VOLUME_NAME_DOS);
if (dir_path_len == 0) {
SET_REQ_WIN32_ERROR(req, GetLastError());
@ -797,7 +811,7 @@ void fs__openat(uv_fs_t* req) {
}
// Then pop the last component.
uv__path_pop(&rebuilt_path);
if (rebuilt_path.len > 0) uv__path_pop(&rebuilt_path);
} else {
uv__path_push(&rebuilt_path, token);
}
@ -805,6 +819,18 @@ void fs__openat(uv_fs_t* req) {
token = wcstok_s(NULL, L"\\", &next_token);
}
if (is_absolute) {
// Prepend the path with the NT object directory prefix.
WCHAR * buf = uv__malloc((rebuilt_path.len + 1) * sizeof(WCHAR));
memcpy(buf, rebuilt_path.buf, (rebuilt_path.len + 1) * sizeof(WCHAR));
uv__path_set(&rebuilt_path, L"\\??");
uv__path_push(&rebuilt_path, buf);
uv__free(buf);
}
wprintf(L"%d %s\n", root_dir_handle, rebuilt_path.buf);
/* Adjust flags to be compatible with the memory file mapping. Save the
* original flags to emulate the correct behavior. */
if (flags & UV_FS_O_FILEMAP) {

View File

@ -3257,6 +3257,32 @@ TEST_IMPL(fs_openat) {
uv_fs_req_cleanup(&req);
}
{
r = uv_fs_realpath(NULL, &req, "test/fixtures/file", NULL);
ASSERT_OK(r);
size_t len = strlen(req.ptr);
char * abs_path = malloc(len + 1);
memcpy(abs_path, req.ptr, len + 1);
uv_fs_req_cleanup(&req);
r = uv_fs_openat(NULL,
&req,
dir,
abs_path,
UV_FS_O_RDONLY,
0,
NULL);
ASSERT_GE(r, 0);
free(abs_path);
fd = (uv_file) req.result;
uv_fs_req_cleanup(&req);
r = uv_fs_close(NULL, &req, fd, NULL);
ASSERT_OK(r);
uv_fs_req_cleanup(&req);
}
r = uv_fs_close(NULL, &req, dir, NULL);
ASSERT_OK(r);
uv_fs_req_cleanup(&req);
@ -3270,10 +3296,7 @@ TEST_IMPL(fs_openat) {
unlink("test/fixtures/test_dir/test_file");
unlink("test/fixtures/test_dir/link");
unlink("test/fixtures/test_dir/nested_dir/file");
<<<<<<< HEAD
=======
unlink("test/fixtures/file");
>>>>>>> 8e91f4974c9681fd1aaf7b42fcb493a3b587ac2f
rmdir("test/fixtures/test_dir/nested_dir");
rmdir("test/fixtures/test_dir");