diff --git a/src/unix/pipe.c b/src/unix/pipe.c index e640bf29..2c578dcb 100644 --- a/src/unix/pipe.c +++ b/src/unix/pipe.c @@ -319,21 +319,6 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) { mode != (UV_WRITABLE | UV_READABLE)) return UV_EINVAL; - if (fstat(uv__stream_fd(handle), &pipe_stat) == -1) - return UV__ERR(errno); - - desired_mode = 0; - if (mode & UV_READABLE) - desired_mode |= S_IRUSR | S_IRGRP | S_IROTH; - if (mode & UV_WRITABLE) - desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH; - - /* Exit early if pipe already has desired mode. */ - if ((pipe_stat.st_mode & desired_mode) == desired_mode) - return 0; - - pipe_stat.st_mode |= desired_mode; - /* Unfortunately fchmod does not work on all platforms, we will use chmod. */ name_len = 0; r = uv_pipe_getsockname(handle, NULL, &name_len); @@ -350,6 +335,26 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) { return r; } + /* stat must be used as fstat has a bug on Darwin */ + if (stat(name_buffer, &pipe_stat) == -1) { + uv__free(name_buffer); + return -errno; + } + + desired_mode = 0; + if (mode & UV_READABLE) + desired_mode |= S_IRUSR | S_IRGRP | S_IROTH; + if (mode & UV_WRITABLE) + desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH; + + /* Exit early if pipe already has desired mode. */ + if ((pipe_stat.st_mode & desired_mode) == desired_mode) { + uv__free(name_buffer); + return 0; + } + + pipe_stat.st_mode |= desired_mode; + r = chmod(name_buffer, pipe_stat.st_mode); uv__free(name_buffer); diff --git a/test/test-pipe-set-fchmod.c b/test/test-pipe-set-fchmod.c index 59f0e6f5..de4932dc 100644 --- a/test/test-pipe-set-fchmod.c +++ b/test/test-pipe-set-fchmod.c @@ -27,6 +27,9 @@ TEST_IMPL(pipe_set_chmod) { uv_pipe_t pipe_handle; uv_loop_t* loop; int r; +#ifndef _WIN32 + struct stat stat_buf; +#endif loop = uv_default_loop(); @@ -44,12 +47,33 @@ TEST_IMPL(pipe_set_chmod) { RETURN_SKIP("Insufficient privileges to alter pipe fmode"); } ASSERT(r == 0); +#ifndef _WIN32 + stat(TEST_PIPENAME, &stat_buf); + ASSERT(stat_buf.st_mode & S_IRUSR); + ASSERT(stat_buf.st_mode & S_IRGRP); + ASSERT(stat_buf.st_mode & S_IROTH); +#endif r = uv_pipe_chmod(&pipe_handle, UV_WRITABLE); ASSERT(r == 0); +#ifndef _WIN32 + stat(TEST_PIPENAME, &stat_buf); + ASSERT(stat_buf.st_mode & S_IWUSR); + ASSERT(stat_buf.st_mode & S_IWGRP); + ASSERT(stat_buf.st_mode & S_IWOTH); +#endif r = uv_pipe_chmod(&pipe_handle, UV_WRITABLE | UV_READABLE); ASSERT(r == 0); +#ifndef _WIN32 + stat(TEST_PIPENAME, &stat_buf); + ASSERT(stat_buf.st_mode & S_IRUSR); + ASSERT(stat_buf.st_mode & S_IRGRP); + ASSERT(stat_buf.st_mode & S_IROTH); + ASSERT(stat_buf.st_mode & S_IWUSR); + ASSERT(stat_buf.st_mode & S_IWGRP); + ASSERT(stat_buf.st_mode & S_IWOTH); +#endif r = uv_pipe_chmod(NULL, UV_WRITABLE | UV_READABLE); ASSERT(r == UV_EBADF);