From 1dc6e1d5d336da291359bfc82c111d3761b870f4 Mon Sep 17 00:00:00 2001 From: Yage Hu Date: Tue, 18 Jun 2024 16:19:07 -0700 Subject: [PATCH] Support absolute Windows path Signed-off-by: Yage Hu --- src/win/fs.c | 40 +++++++++++++++++++++++++++++++++------- test/test-fs.c | 29 ++++++++++++++++++++++++++--- 2 files changed, 59 insertions(+), 10 deletions(-) diff --git a/src/win/fs.c b/src/win/fs.c index 60f49997..1efd04be 100644 --- a/src/win/fs.c +++ b/src/win/fs.c @@ -35,6 +35,7 @@ /* requires , included via "uv.h" above, but needs to be included before our "winapi.h", included via "internal.h" below. */ #include +#include #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) { diff --git a/test/test-fs.c b/test/test-fs.c index b45a453d..b27f9cf0 100644 --- a/test/test-fs.c +++ b/test/test-fs.c @@ -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");