unix: fix uv_pipe_chmod() on macOS

According to its man page, there is a bug in fstat()
on macOS related to pipes. This commit replaces a
fstat() call in uv_pipe_chmod() with a stat() call in
order to get the correct permissions.

PR-URL: https://github.com/libuv/libuv/pull/1635
Reviewed-By: Colin Ihrig <cjihrig@gmail.com>
Reviewed-By: Santiago Gimeno <santiago.gimeno@gmail.com>
This commit is contained in:
zzzjim 2017-11-19 15:40:09 -06:00 committed by cjihrig
parent 9afb013574
commit 19855c03ba
No known key found for this signature in database
GPG Key ID: 7434390BDBE9B9C5
2 changed files with 44 additions and 15 deletions

View File

@ -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);

View File

@ -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);