On some platforms (like FreeBSD, Darwin, GNU/Hurd, ...), `getsockname`
returns an empty string for sockets in the UNIX domain.

On FreeBSD and Darwin, the `kqueue` event loop implementation will call
`fcntl` with `F_KINFO`/`F_GETPATH` to get the path of the file before
calling the final system interfaces.

On other platforms that do not use kqueue (for example, GNU/Hurd uses
posix-poll), the path cannot be got in these way and `uv__stat`
will be called with an empty string resulting in an error.

However, we do have stored the path info in `pipe_fname` of `uv_pipe_t`,
so we can try to use this if `getsockname` returns an empty string.
---
 src/unix/pipe.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/src/unix/pipe.c b/src/unix/pipe.c
index 6bfe6cf2..1884b3ac 100644
--- a/src/unix/pipe.c
+++ b/src/unix/pipe.c
@@ -450,6 +450,7 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
   unsigned desired_mode;
   struct stat pipe_stat;
   char name_buffer[1 + UV__PATH_MAX];
+  const char* name = name_buffer;
   size_t name_len;
   int r;
 
@@ -467,8 +468,11 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
   if (r != 0)
     return r;
 
+  if (name_len == 0 && handle->pipe_fname != NULL)
+    name = handle->pipe_fname;
+
   /* stat must be used as fstat has a bug on Darwin */
-  if (uv__stat(name_buffer, &pipe_stat) == -1)
+  if (uv__stat(name, &pipe_stat) == -1)
     return UV__ERR(errno);
 
   desired_mode = 0;
@@ -483,7 +487,7 @@ int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
 
   pipe_stat.st_mode |= desired_mode;
 
-  r = chmod(name_buffer, pipe_stat.st_mode);
+  r = chmod(name, pipe_stat.st_mode);
 
   return r != -1 ? 0 : UV__ERR(errno);
 }
-- 
Yuqian Yang <crup...@crupest.life>

Reply via email to