diff --git a/src/win/pipe.c b/src/win/pipe.c index bbd86f65..7a787150 100644 --- a/src/win/pipe.c +++ b/src/win/pipe.c @@ -905,18 +905,6 @@ int uv_pipe_bind2(uv_pipe_t* handle, } if (use_uds_pipe) { - int exists; - err = uv__win_uds_pipe_file_exists(name_copy, &exists); - if (err) { - goto error; - } - - /* The uds file must not exist before bind. */ - if (exists) { - err = UV_EEXIST; - goto error; - } - /* Only use 1 pending instance when use unix domain socket, cause * call AcceptEx multiple times seems result in multiple accept events. * Not the expected queue behavior, that only one of them is triggered. */ @@ -952,13 +940,33 @@ int uv_pipe_bind2(uv_pipe_t* handle, if (err) { goto error; } - + #if defined(UV__ENABLE_WIN_UDS_PIPE) if (use_uds_pipe) { + int exists; + err = uv__win_uds_pipe_file_exists(handle->pathname, &exists); + if (err) { + goto error; + } + + /* The uds file must not exist before bind. */ + if (exists) { + err = UV_EEXIST; + goto error; + } + int uds_err = pipe_alloc_accept_unix_domain_socket( loop, handle, &handle->pipe.serv.accept_reqs[0], handle->pathname, TRUE); if (uds_err) { - err = uv_translate_sys_error(uds_err); + if (uds_err == WSAENETDOWN) { + /* + * Typically it means the file at pathname cannot be created, + * possibly bad parent directory in path. + */ + err = UV_EINVAL; + } else { + err = uv_translate_sys_error(uds_err); + } goto error; } @@ -1131,20 +1139,6 @@ int uv_pipe_connect2(uv_connect_t* req, memcpy(name_copy, name, namelen); name_copy[namelen] = '\0'; - if (use_uds_pipe) { - int exists; - err = uv__win_uds_pipe_file_exists(name_copy, &exists); - if (err) { - goto error; - } - - /* The uds file must have been created by server. */ - if (!exists) { - err = UV_ENOENT; - goto error; - } - } - if (handle->flags & UV_HANDLE_PIPESERVER) { err = ERROR_INVALID_PARAMETER; goto error; @@ -1170,9 +1164,21 @@ int uv_pipe_connect2(uv_connect_t* req, err = ERROR_NO_UNICODE_TRANSLATION; goto error; } - + #if defined(UV__ENABLE_WIN_UDS_PIPE) if (use_uds_pipe) { + int exists; + err = uv__win_uds_pipe_file_exists(handle->pathname, &exists); + if (err) { + goto error; + } + + /* The uds file must have been created by server. */ + if (!exists) { + err = UV_ENOENT; + goto error; + } + /* * If prefix is not "\\.\pipe", we assume it is a Unix Domain Socket. * Although "NamedPipe" is a Windows concept, however in libuv, it has diff --git a/test/test-list.h b/test/test-list.h index b946511e..50d191bd 100644 --- a/test/test-list.h +++ b/test/test-list.h @@ -216,6 +216,7 @@ TEST_DECLARE (pipe_sendmsg) TEST_DECLARE (pipe_server_close) #ifdef _WIN32 TEST_DECLARE (pipe_win_uds) +TEST_DECLARE (pipe_win_uds_bad_name) #endif TEST_DECLARE (connection_fail) TEST_DECLARE (connection_fail_doesnt_auto_close) @@ -633,6 +634,7 @@ TASK_LIST_START TEST_ENTRY_CUSTOM (pipe_set_non_blocking, 0, 0, 20000) #ifdef _WIN32 TEST_ENTRY (pipe_win_uds) + TEST_ENTRY (pipe_win_uds_bad_name) #endif TEST_ENTRY (pipe_set_chmod) diff --git a/test/test-pipe-win-uds.c b/test/test-pipe-win-uds.c index 41077236..c7827542 100644 --- a/test/test-pipe-win-uds.c +++ b/test/test-pipe-win-uds.c @@ -24,6 +24,10 @@ #ifdef _WIN32 +#if !defined(__MINGW32__) && !defined(__MINGW64__) +#define UV_SUPPORTS_WIN_UDS +#endif + static int close_cb_called = 0; static int server_connect_cb_called = 0; static int client_connect_cb_called = 0; @@ -94,7 +98,7 @@ static void server_connect_cb(uv_stream_t *handle, int status) { } TEST_IMPL(pipe_win_uds) { -#if !defined(__MINGW32__) && !defined(__MINGW64__) +#if defined(UV_SUPPORTS_WIN_UDS) int r; uv_fs_t fs; uv_connect_t req; @@ -135,4 +139,45 @@ TEST_IMPL(pipe_win_uds) { return 0; } + +static void bad_name_connect_cb(uv_connect_t *connect_req, int status) { + ASSERT_EQ(status, UV_ENOENT); +} + + +TEST_IMPL(pipe_win_uds_bad_name) { +#if defined(UV_SUPPORTS_WIN_UDS) + int r; + uv_connect_t req; + uv_pipe_t pipe_server_1; + uv_pipe_t pipe_server_2; + uv_pipe_t pipe_client_1; + const char * path_1 = "not/exist/file/path"; + const char * path_2 = "test/fixtures/empty_file"; + + // Bind server 1 which has a bad path + r = uv_pipe_init_ex(uv_default_loop(), &pipe_server_1, UV_PIPE_INIT_WIN_UDS); + ASSERT_OK(r); + r = uv_pipe_bind(&pipe_server_1, path_1); + ASSERT_EQ(r, UV_EINVAL); + + // Bind server 2 which file exists + r = uv_pipe_init_ex(uv_default_loop(), &pipe_server_2, UV_PIPE_INIT_WIN_UDS); + ASSERT_OK(r); + r = uv_pipe_bind(&pipe_server_2, path_2); + ASSERT_EQ(r, UV_EEXIST); + + // Connect client to server with bad name + r = uv_pipe_init_ex(uv_default_loop(), &pipe_client_1, UV_PIPE_INIT_WIN_UDS); + ASSERT_OK(r); + uv_pipe_connect(&req, &pipe_client_1, path_1, bad_name_connect_cb); + + // Run the loop + uv_run(uv_default_loop(), UV_RUN_DEFAULT); +#endif + + MAKE_VALGRIND_HAPPY(uv_default_loop()); + return 0; +} + #endif