From d2a00b547b64a9e9e35eaa2d47c55f5943d321e1 Mon Sep 17 00:00:00 2001 From: Bartosz Sosnowski Date: Thu, 19 Jul 2018 16:34:46 +0200 Subject: [PATCH] fs: add uv_open_osfhandle Adds uv_open_osfhandle to complete uv_get_osfhandle Ref: https://github.com/nodejs/node/issues/15433 Ref: https://github.com/nodejs/node-addon-api/issues/304 --- docs/src/fs.rst | 9 +++++++++ include/uv.h | 1 + src/unix/core.c | 3 +++ src/win/handle.c | 4 ++++ test/test-fs.c | 46 ++++++++++++++++++++++++++++++++++++++++++++++ test/test-list.h | 2 ++ 6 files changed, 65 insertions(+) diff --git a/docs/src/fs.rst b/docs/src/fs.rst index f383e5b10cd9..dc783b0ce508 100644 --- a/docs/src/fs.rst +++ b/docs/src/fs.rst @@ -403,6 +403,15 @@ Helper functions .. versionadded:: 1.12.0 +.. c:function:: int uv_open_osfhandle(int os_fd) + + For a OS-dependent handle, get the file descriptor in the C runtime. + On UNIX, returns the ``os_fd`` intact. On Windows, this calls `_open_osfhandle `_. + Note that the return value is still owned by the CRT, + any attempts to close it or to use it after closing the handle may lead to malfunction. + + .. versionadded:: 1.22.1 + File open constants ------------------- diff --git a/include/uv.h b/include/uv.h index a8b305793d4b..c6919d315145 100644 --- a/include/uv.h +++ b/include/uv.h @@ -1065,6 +1065,7 @@ UV_EXTERN int uv_set_process_title(const char* title); UV_EXTERN int uv_resident_set_memory(size_t* rss); UV_EXTERN int uv_uptime(double* uptime); UV_EXTERN uv_os_fd_t uv_get_osfhandle(int fd); +UV_EXTERN int uv_open_osfhandle(uv_os_fd_t os_fd); typedef struct { long tv_sec; diff --git a/src/unix/core.c b/src/unix/core.c index 066c9bee32e2..2680209911bd 100644 --- a/src/unix/core.c +++ b/src/unix/core.c @@ -1338,6 +1338,9 @@ uv_os_fd_t uv_get_osfhandle(int fd) { return fd; } +int uv_open_osfhandle(uv_os_fd_t os_fd) { + return os_fd; +} uv_pid_t uv_os_getpid(void) { return getpid(); diff --git a/src/win/handle.c b/src/win/handle.c index 738d7ff3248a..9d76c3f54209 100644 --- a/src/win/handle.c +++ b/src/win/handle.c @@ -157,3 +157,7 @@ int uv_is_closing(const uv_handle_t* handle) { uv_os_fd_t uv_get_osfhandle(int fd) { return uv__get_osfhandle(fd); } + +int uv_open_osfhandle(uv_os_fd_t os_fd) { + return _open_osfhandle((intptr_t) os_fd, 0); +} diff --git a/test/test-fs.c b/test/test-fs.c index 57da39891a5c..9c1e8bec205f 100644 --- a/test/test-fs.c +++ b/test/test-fs.c @@ -3069,6 +3069,52 @@ TEST_IMPL(get_osfhandle_valid_handle) { return 0; } +TEST_IMPL(open_osfhandle_valid_handle) { + int r; + uv_os_fd_t handle; + int fd; + + /* Setup. */ + unlink("test_file"); + + loop = uv_default_loop(); + + r = uv_fs_open(NULL, + &open_req1, + "test_file", + O_RDWR | O_CREAT, + S_IWUSR | S_IRUSR, + NULL); + ASSERT(r >= 0); + ASSERT(open_req1.result >= 0); + uv_fs_req_cleanup(&open_req1); + + handle = uv_get_osfhandle(open_req1.result); +#ifdef _WIN32 + ASSERT(handle != INVALID_HANDLE_VALUE); +#else + ASSERT(handle >= 0); +#endif + + fd = uv_open_osfhandle(handle); +#ifdef _WIN32 + ASSERT(fd > 0); +#else + ASSERT(fd == open_req1.result); +#endif + + r = uv_fs_close(NULL, &close_req, open_req1.result, NULL); + ASSERT(r == 0); + ASSERT(close_req.result == 0); + uv_fs_req_cleanup(&close_req); + + /* Cleanup. */ + unlink("test_file"); + + MAKE_VALGRIND_HAPPY(); + return 0; +} + TEST_IMPL(fs_file_pos_after_op_with_offset) { int r; diff --git a/test/test-list.h b/test/test-list.h index 24ba37461eb4..6c490e1d5d39 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -334,6 +334,7 @@ TEST_DECLARE (fs_rename_to_existing_file) TEST_DECLARE (fs_write_multiple_bufs) TEST_DECLARE (fs_read_write_null_arguments) TEST_DECLARE (get_osfhandle_valid_handle) +TEST_DECLARE (open_osfhandle_valid_handle) TEST_DECLARE (fs_write_alotof_bufs) TEST_DECLARE (fs_write_alotof_bufs_with_offset) TEST_DECLARE (fs_file_pos_after_op_with_offset) @@ -887,6 +888,7 @@ TASK_LIST_START TEST_ENTRY (fs_fchmod_archive_readonly) #endif TEST_ENTRY (get_osfhandle_valid_handle) + TEST_ENTRY (open_osfhandle_valid_handle) TEST_ENTRY (threadpool_queue_work_simple) TEST_ENTRY (threadpool_queue_work_einval) TEST_ENTRY (threadpool_multiple_event_loops)