From baecd3b243a66fd54779c9ce170e47b40e2dbddb Mon Sep 17 00:00:00 2001 From: Yage Hu Date: Thu, 13 Jun 2024 11:24:41 -0700 Subject: [PATCH] Add docs for uv_fs_openat Signed-off-by: Yage Hu --- docs/src/fs.rst | 12 +++++++++++- include/uv.h | 2 +- src/unix/fs.c | 2 +- src/win/fs.c | 40 ++++++++++++++++++++++++++++++++-------- test/test-fs.c | 30 +++++++++++++++--------------- 5 files changed, 60 insertions(+), 26 deletions(-) diff --git a/docs/src/fs.rst b/docs/src/fs.rst index 891ee74c..659cc380 100644 --- a/docs/src/fs.rst +++ b/docs/src/fs.rst @@ -108,7 +108,8 @@ Data types UV_FS_READDIR, UV_FS_CLOSEDIR, UV_FS_MKSTEMP, - UV_FS_LUTIME + UV_FS_LUTIME, + UV_FS_OPENAT } uv_fs_type; .. c:type:: uv_statfs_t @@ -227,6 +228,15 @@ API in binary mode. Because of this the O_BINARY and O_TEXT flags are not supported. +.. c:function:: int uv_fs_openat(uv_loop_t* loop, uv_fs_t* req, uv_file file, const char* path, int flags, int mode, uv_fs_cb cb) + + Equivalent to :man:`openat(2)`. + + .. note:: + On Windows libuv uses `NtCreateFile` and thus the file is always opened + in binary mode. Because of this the O_BINARY and O_TEXT flags are not + supported. + .. c:function:: int uv_fs_read(uv_loop_t* loop, uv_fs_t* req, uv_file file, const uv_buf_t bufs[], unsigned int nbufs, int64_t offset, uv_fs_cb cb) Equivalent to :man:`preadv(2)`. If the `offset` argument is `-1`, then diff --git a/include/uv.h b/include/uv.h index b5744a8d..8883f158 100644 --- a/include/uv.h +++ b/include/uv.h @@ -1442,7 +1442,7 @@ UV_EXTERN int uv_fs_open(uv_loop_t* loop, uv_fs_cb cb); UV_EXTERN int uv_fs_openat(uv_loop_t* loop, uv_fs_t* req, - uv_os_fd_t file, + uv_file file, const char* path, int flags, int mode, diff --git a/src/unix/fs.c b/src/unix/fs.c index 40b57465..e58a275f 100644 --- a/src/unix/fs.c +++ b/src/unix/fs.c @@ -2044,7 +2044,7 @@ int uv_fs_open(uv_loop_t* loop, int uv_fs_openat(uv_loop_t* loop, uv_fs_t* req, - uv_os_fd_t file, + uv_file file, const char* path, int flags, int mode, diff --git a/src/win/fs.c b/src/win/fs.c index ebcc2921..31a3fce3 100644 --- a/src/win/fs.c +++ b/src/win/fs.c @@ -641,7 +641,7 @@ void fs__openat(uv_fs_t* req) { UNICODE_STRING str; IO_STATUS_BLOCK isb; OBJECT_ATTRIBUTES obj; - int current_umask; + int fd, current_umask; int flags = req->fs.info.file_flags; struct uv__fd_info_s fd_info; @@ -808,11 +808,19 @@ void fs__openat(uv_fs_t* req) { options |= FILE_DIRECTORY_FILE; } + HANDLE dir = (HANDLE) _get_osfhandle(req->fs.info.fd_out); + if (dir == INVALID_HANDLE_VALUE) { + fprintf(stderr, "get_osfhandle\n"); + SET_REQ_WIN32_ERROR(req, (DWORD) UV_EBADF); + return; + } + + pRtlInitUnicodeString(&str, req->file.pathw); InitializeObjectAttributes(&obj, &str, OBJ_CASE_INSENSITIVE, - req->fs.info.hFile_out, + dir, NULL); NTSTATUS status = pNtCreateFile(&file, @@ -829,7 +837,7 @@ void fs__openat(uv_fs_t* req) { if (!NT_SUCCESS(status)) { ULONG error = pRtlNtStatusToDosError(status); - if ((isb.Information & FILE_EXISTS != 0) && (flags & UV_FS_O_CREAT) && + if (((isb.Information & FILE_EXISTS) != 0) && (flags & UV_FS_O_CREAT) && !(flags & UV_FS_O_EXCL)) { /* Special case: when FILE_EXISTS happens and UV_FS_O_CREAT was * specified, it means the path referred to a directory. */ @@ -840,6 +848,22 @@ void fs__openat(uv_fs_t* req) { return; } + fd = _open_osfhandle((intptr_t) file, flags); + if (fd < 0) { + /* The only known failure mode for _open_osfhandle() is EMFILE, in which + * case GetLastError() will return zero. However we'll try to handle other + * errors as well, should they ever occur. + */ + if (errno == EMFILE) + SET_REQ_UV_ERROR(req, UV_EMFILE, ERROR_TOO_MANY_OPEN_FILES); + else if (GetLastError() != ERROR_SUCCESS) + SET_REQ_WIN32_ERROR(req, GetLastError()); + else + SET_REQ_WIN32_ERROR(req, (DWORD) UV_UNKNOWN); + CloseHandle(file); + return; + } + if (flags & UV_FS_O_FILEMAP) { FILE_STANDARD_INFO file_info; if (!GetFileInformationByHandleEx(file, @@ -881,10 +905,10 @@ void fs__openat(uv_fs_t* req) { } } - uv__fd_hash_add(file, &fd_info); + uv__fd_hash_add(fd, &fd_info); } - SET_REQ_RESULT(req, (uintptr_t)file); + SET_REQ_RESULT(req, fd); return; einval: @@ -3155,7 +3179,7 @@ int uv_fs_open(uv_loop_t* loop, uv_fs_t* req, const char* path, int flags, int uv_fs_openat(uv_loop_t* loop, uv_fs_t* req, - uv_os_fd_t handle, + uv_file handle, const char* path, int flags, int mode, @@ -3169,10 +3193,10 @@ int uv_fs_openat(uv_loop_t* loop, return req->result; } - req->fs.info.hFile_out = handle; + req->fs.info.fd_out = handle; req->fs.info.file_flags = flags; req->fs.info.mode = mode; - POST0; + POST; } diff --git a/test/test-fs.c b/test/test-fs.c index 6213912d..4aaff2f2 100644 --- a/test/test-fs.c +++ b/test/test-fs.c @@ -3022,8 +3022,8 @@ TEST_IMPL(fs_scandir_early_exit) { TEST_IMPL(fs_openat) { int r; uv_fs_t req; - uv_os_fd_t fd; - uv_os_fd_t dirfd; + uv_file fd; + uv_file dirfd; /* Setup. */ unlink("test/fixtures/test_dir/test_file_not_exist"); @@ -3049,7 +3049,7 @@ TEST_IMPL(fs_openat) { ASSERT_GE(r, 0); uv_fs_req_cleanup(&req); - dirfd = (uv_os_fd_t) req.result; + dirfd = (uv_file) r; r = uv_fs_open(NULL, &req, @@ -3057,9 +3057,9 @@ TEST_IMPL(fs_openat) { UV_FS_O_RDWR | UV_FS_O_CREAT, S_IWUSR | S_IRUSR, NULL); - ASSERT_OK(r); + ASSERT_GE(r, 0); uv_fs_req_cleanup(&req); - fd = (uv_os_fd_t) req.result; + fd = r; r = uv_fs_close(NULL, &req, fd, NULL); ASSERT_OK(r); uv_fs_req_cleanup(&req); @@ -3073,9 +3073,9 @@ TEST_IMPL(fs_openat) { UV_FS_O_RDWR | UV_FS_O_CREAT, S_IWUSR | S_IRUSR, NULL); - ASSERT_OK(r); + ASSERT_GE(r, 0); uv_fs_req_cleanup(&req); - fd = (uv_os_fd_t) req.result; + fd = (uv_file) r; r = uv_fs_close(NULL, &req, fd, NULL); ASSERT_OK(r); uv_fs_req_cleanup(&req); @@ -3090,14 +3090,14 @@ TEST_IMPL(fs_openat) { UV_FS_O_RDWR | UV_FS_O_CREAT, S_IWUSR | S_IRUSR, openat_cb_simple); - ASSERT_OK(r); + ASSERT_GE(r, 0); ASSERT_OK(openat_cb_count); uv_run(loop, UV_RUN_DEFAULT); ASSERT_EQ(1, openat_cb_count); uv_fs_req_cleanup(&req); - fd = (uv_os_fd_t) req.result; + fd = (uv_file) req.result; r = uv_fs_close(NULL, &req, fd, NULL); ASSERT_OK(r); uv_fs_req_cleanup(&req); @@ -3112,9 +3112,9 @@ TEST_IMPL(fs_openat) { UV_FS_O_RDONLY | UV_FS_O_DIRECTORY, S_IWUSR | S_IRUSR, NULL); - ASSERT_OK(r); + ASSERT_GE(r, 0); uv_fs_req_cleanup(&req); - fd = (uv_os_fd_t) req.result; + fd = (uv_file) req.result; r = uv_fs_close(NULL, &req, fd, NULL); ASSERT_OK(r); uv_fs_req_cleanup(&req); @@ -3129,9 +3129,9 @@ TEST_IMPL(fs_openat) { UV_FS_O_RDWR | UV_FS_O_CREAT, S_IWUSR | S_IRUSR, NULL); - ASSERT_OK(r); + ASSERT_GE(r, 0); uv_fs_req_cleanup(&req); - fd = (uv_os_fd_t) req.result; + fd = (uv_file) req.result; r = uv_fs_close(NULL, &req, fd, NULL); ASSERT_OK(r); uv_fs_req_cleanup(&req); @@ -3159,10 +3159,10 @@ TEST_IMPL(fs_openat) { UV_FS_O_RDONLY, 0, NULL); - ASSERT_OK(r); + ASSERT_GE(r, 0); uv_fs_req_cleanup(&req); - fd = (uv_os_fd_t) req.result; + fd = (uv_file) req.result; iov = uv_buf_init(test_buf, sizeof(test_buf)); r = uv_fs_write(NULL,