comparison third_party/libuv/src/unix/pipe.c @ 160:948de3f54cea

[ThirdParty] Added libuv
author June Park <parkjune1995@gmail.com>
date Wed, 14 Jan 2026 19:39:52 -0800
parents
children
comparison
equal deleted inserted replaced
159:05cf9467a1c3 160:948de3f54cea
1 /* Copyright Joyent, Inc. and other Node contributors. All rights reserved.
2 *
3 * Permission is hereby granted, free of charge, to any person obtaining a copy
4 * of this software and associated documentation files (the "Software"), to
5 * deal in the Software without restriction, including without limitation the
6 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
7 * sell copies of the Software, and to permit persons to whom the Software is
8 * furnished to do so, subject to the following conditions:
9 *
10 * The above copyright notice and this permission notice shall be included in
11 * all copies or substantial portions of the Software.
12 *
13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
14 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
15 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
16 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
17 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
18 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
19 * IN THE SOFTWARE.
20 */
21
22 #include "uv.h"
23 #include "internal.h"
24
25 #include <assert.h>
26 #include <errno.h>
27 #include <string.h>
28 #include <sys/un.h>
29 #include <unistd.h>
30 #include <stdlib.h>
31
32
33 /* Does the file path contain embedded nul bytes? */
34 static int includes_invalid_nul(const char *s, size_t n) {
35 if (n == 0)
36 return 0;
37 #ifdef __linux__
38 /* Accept abstract socket namespace paths, throughout which nul bytes have
39 * no special significance ("\0foo\0bar").
40 */
41 if (s[0] == '\0')
42 return 0;
43 #endif
44 return NULL != memchr(s, '\0', n);
45 }
46
47
48 int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
49 uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
50 handle->shutdown_req = NULL;
51 handle->connect_req = NULL;
52 handle->pipe_fname = NULL;
53 handle->ipc = ipc;
54 return 0;
55 }
56
57
58 int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
59 return uv_pipe_bind2(handle, name, strlen(name), 0);
60 }
61
62
63 int uv_pipe_bind2(uv_pipe_t* handle,
64 const char* name,
65 size_t namelen,
66 unsigned int flags) {
67 struct sockaddr_un saddr;
68 char* pipe_fname;
69 int sockfd;
70 int err;
71 socklen_t addrlen;
72
73 pipe_fname = NULL;
74
75 if (flags & ~UV_PIPE_NO_TRUNCATE)
76 return UV_EINVAL;
77
78 if (name == NULL)
79 return UV_EINVAL;
80
81 /* namelen==0 on Linux means autobind the listen socket in the abstract
82 * socket namespace, see `man 7 unix` for details.
83 */
84 #if !defined(__linux__)
85 if (namelen == 0)
86 return UV_EINVAL;
87 #endif
88
89 if (includes_invalid_nul(name, namelen))
90 return UV_EINVAL;
91
92 if (flags & UV_PIPE_NO_TRUNCATE)
93 if (namelen > sizeof(saddr.sun_path))
94 return UV_EINVAL;
95
96 /* Truncate long paths. Documented behavior. */
97 if (namelen > sizeof(saddr.sun_path))
98 namelen = sizeof(saddr.sun_path);
99
100 /* Already bound? */
101 if (uv__stream_fd(handle) >= 0)
102 return UV_EINVAL;
103
104 if (uv__is_closing(handle))
105 return UV_EINVAL;
106
107 /* Make a copy of the file path unless it is an abstract socket.
108 * We unlink the file later but abstract sockets disappear
109 * automatically since they're not real file system entities.
110 */
111 if (*name == '\0') {
112 addrlen = offsetof(struct sockaddr_un, sun_path) + namelen;
113 } else {
114 pipe_fname = uv__malloc(namelen + 1);
115 if (pipe_fname == NULL)
116 return UV_ENOMEM;
117 memcpy(pipe_fname, name, namelen);
118 pipe_fname[namelen] = '\0';
119 addrlen = sizeof saddr;
120 }
121
122 err = uv__socket(AF_UNIX, SOCK_STREAM, 0);
123 if (err < 0)
124 goto err_socket;
125 sockfd = err;
126
127 memset(&saddr, 0, sizeof saddr);
128 memcpy(&saddr.sun_path, name, namelen);
129 saddr.sun_family = AF_UNIX;
130
131 if (bind(sockfd, (struct sockaddr*)&saddr, addrlen)) {
132 err = UV__ERR(errno);
133 /* Convert ENOENT to EACCES for compatibility with Windows. */
134 if (err == UV_ENOENT)
135 err = UV_EACCES;
136
137 uv__close(sockfd);
138 goto err_socket;
139 }
140
141 /* Success. */
142 handle->flags |= UV_HANDLE_BOUND;
143 handle->pipe_fname = pipe_fname; /* NULL or a copy of |name| */
144 handle->io_watcher.fd = sockfd;
145 return 0;
146
147 err_socket:
148 uv__free(pipe_fname);
149 return err;
150 }
151
152
153 int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
154 if (uv__stream_fd(handle) == -1)
155 return UV_EINVAL;
156
157 if (handle->ipc)
158 return UV_EINVAL;
159
160 #if defined(__MVS__) || defined(__PASE__)
161 /* On zOS, backlog=0 has undefined behaviour */
162 /* On IBMi PASE, backlog=0 leads to "Connection refused" error */
163 if (backlog == 0)
164 backlog = 1;
165 else if (backlog < 0)
166 backlog = SOMAXCONN;
167 #endif
168
169 if (listen(uv__stream_fd(handle), backlog))
170 return UV__ERR(errno);
171
172 handle->connection_cb = cb;
173 handle->io_watcher.cb = uv__server_io;
174 uv__io_start(handle->loop, &handle->io_watcher, POLLIN);
175 return 0;
176 }
177
178
179 void uv__pipe_close(uv_pipe_t* handle) {
180 if (handle->pipe_fname) {
181 /*
182 * Unlink the file system entity before closing the file descriptor.
183 * Doing it the other way around introduces a race where our process
184 * unlinks a socket with the same name that's just been created by
185 * another thread or process.
186 */
187 unlink(handle->pipe_fname);
188 uv__free((void*)handle->pipe_fname);
189 handle->pipe_fname = NULL;
190 }
191
192 uv__stream_close((uv_stream_t*)handle);
193 }
194
195
196 int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
197 int flags;
198 int mode;
199 int err;
200 flags = 0;
201
202 if (uv__fd_exists(handle->loop, fd))
203 return UV_EEXIST;
204
205 do
206 mode = fcntl(fd, F_GETFL);
207 while (mode == -1 && errno == EINTR);
208
209 if (mode == -1)
210 return UV__ERR(errno); /* according to docs, must be EBADF */
211
212 err = uv__nonblock(fd, 1);
213 if (err)
214 return err;
215
216 #if defined(__APPLE__)
217 err = uv__stream_try_select((uv_stream_t*) handle, &fd);
218 if (err)
219 return err;
220 #endif /* defined(__APPLE__) */
221
222 mode &= O_ACCMODE;
223 if (mode != O_WRONLY)
224 flags |= UV_HANDLE_READABLE;
225 if (mode != O_RDONLY)
226 flags |= UV_HANDLE_WRITABLE;
227
228 return uv__stream_open((uv_stream_t*)handle, fd, flags);
229 }
230
231
232 void uv_pipe_connect(uv_connect_t* req,
233 uv_pipe_t* handle,
234 const char* name,
235 uv_connect_cb cb) {
236 int err;
237
238 err = uv_pipe_connect2(req, handle, name, strlen(name), 0, cb);
239
240 if (err) {
241 handle->delayed_error = err;
242 handle->connect_req = req;
243
244 uv__req_init(handle->loop, req, UV_CONNECT);
245 req->handle = (uv_stream_t*) handle;
246 req->cb = cb;
247 uv__queue_init(&req->queue);
248
249 /* Force callback to run on next tick in case of error. */
250 uv__io_feed(handle->loop, &handle->io_watcher);
251 }
252 }
253
254
255 int uv_pipe_connect2(uv_connect_t* req,
256 uv_pipe_t* handle,
257 const char* name,
258 size_t namelen,
259 unsigned int flags,
260 uv_connect_cb cb) {
261 struct sockaddr_un saddr;
262 int new_sock;
263 int err;
264 int r;
265 socklen_t addrlen;
266
267 if (flags & ~UV_PIPE_NO_TRUNCATE)
268 return UV_EINVAL;
269
270 if (name == NULL)
271 return UV_EINVAL;
272
273 if (namelen == 0)
274 return UV_EINVAL;
275
276 if (includes_invalid_nul(name, namelen))
277 return UV_EINVAL;
278
279 if (flags & UV_PIPE_NO_TRUNCATE)
280 if (namelen > sizeof(saddr.sun_path))
281 return UV_EINVAL;
282
283 /* Truncate long paths. Documented behavior. */
284 if (namelen > sizeof(saddr.sun_path))
285 namelen = sizeof(saddr.sun_path);
286
287 new_sock = (uv__stream_fd(handle) == -1);
288
289 if (new_sock) {
290 err = uv__socket(AF_UNIX, SOCK_STREAM, 0);
291 if (err < 0)
292 goto out;
293 handle->io_watcher.fd = err;
294 }
295
296 memset(&saddr, 0, sizeof saddr);
297 memcpy(&saddr.sun_path, name, namelen);
298 saddr.sun_family = AF_UNIX;
299
300 if (*name == '\0')
301 addrlen = offsetof(struct sockaddr_un, sun_path) + namelen;
302 else
303 addrlen = sizeof saddr;
304
305 do {
306 r = connect(uv__stream_fd(handle), (struct sockaddr*)&saddr, addrlen);
307 }
308 while (r == -1 && errno == EINTR);
309
310 if (r == -1 && errno != EINPROGRESS) {
311 err = UV__ERR(errno);
312 #if defined(__CYGWIN__) || defined(__MSYS__)
313 /* EBADF is supposed to mean that the socket fd is bad, but
314 Cygwin reports EBADF instead of ENOTSOCK when the file is
315 not a socket. We do not expect to see a bad fd here
316 (e.g. due to new_sock), so translate the error. */
317 if (err == UV_EBADF)
318 err = UV_ENOTSOCK;
319 #endif
320 goto out;
321 }
322
323 err = 0;
324 if (new_sock) {
325 err = uv__stream_open((uv_stream_t*)handle,
326 uv__stream_fd(handle),
327 UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
328 }
329
330 if (err == 0)
331 uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
332
333 out:
334 handle->delayed_error = err;
335 handle->connect_req = req;
336
337 uv__req_init(handle->loop, req, UV_CONNECT);
338 req->handle = (uv_stream_t*) handle;
339 req->cb = cb;
340 uv__queue_init(&req->queue);
341
342 /* Force callback to run on next tick in case of error. */
343 if (err)
344 uv__io_feed(handle->loop, &handle->io_watcher);
345
346 return 0;
347 }
348
349
350 static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
351 uv__peersockfunc func,
352 char* buffer,
353 size_t* size) {
354 #if defined(__linux__)
355 static const int is_linux = 1;
356 #else
357 static const int is_linux = 0;
358 #endif
359 struct sockaddr_un sa;
360 socklen_t addrlen;
361 size_t slop;
362 char* p;
363 int err;
364
365 if (buffer == NULL || size == NULL || *size == 0)
366 return UV_EINVAL;
367
368 addrlen = sizeof(sa);
369 memset(&sa, 0, addrlen);
370 err = uv__getsockpeername((const uv_handle_t*) handle,
371 func,
372 (struct sockaddr*) &sa,
373 (int*) &addrlen);
374 if (err < 0) {
375 *size = 0;
376 return err;
377 }
378
379 slop = 1;
380 if (is_linux && sa.sun_path[0] == '\0') {
381 /* Linux abstract namespace. Not zero-terminated. */
382 slop = 0;
383 addrlen -= offsetof(struct sockaddr_un, sun_path);
384 } else {
385 p = memchr(sa.sun_path, '\0', sizeof(sa.sun_path));
386 if (p == NULL)
387 p = ARRAY_END(sa.sun_path);
388 addrlen = p - sa.sun_path;
389 }
390
391 if ((size_t)addrlen + slop > *size) {
392 *size = addrlen + slop;
393 return UV_ENOBUFS;
394 }
395
396 memcpy(buffer, sa.sun_path, addrlen);
397 *size = addrlen;
398
399 /* only null-terminate if it's not an abstract socket */
400 if (buffer[0] != '\0')
401 buffer[addrlen] = '\0';
402
403 return 0;
404 }
405
406
407 int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) {
408 return uv__pipe_getsockpeername(handle, getsockname, buffer, size);
409 }
410
411
412 int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {
413 return uv__pipe_getsockpeername(handle, getpeername, buffer, size);
414 }
415
416
417 void uv_pipe_pending_instances(uv_pipe_t* handle, int count) {
418 }
419
420
421 int uv_pipe_pending_count(uv_pipe_t* handle) {
422 uv__stream_queued_fds_t* queued_fds;
423
424 if (!handle->ipc)
425 return 0;
426
427 if (handle->accepted_fd == -1)
428 return 0;
429
430 if (handle->queued_fds == NULL)
431 return 1;
432
433 queued_fds = handle->queued_fds;
434 return queued_fds->offset + 1;
435 }
436
437
438 uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
439 if (!handle->ipc)
440 return UV_UNKNOWN_HANDLE;
441
442 if (handle->accepted_fd == -1)
443 return UV_UNKNOWN_HANDLE;
444 else
445 return uv_guess_handle(handle->accepted_fd);
446 }
447
448
449 int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
450 char name_buffer[1 + UV__PATH_MAX];
451 int desired_mode;
452 size_t name_len;
453 const char* name;
454 int fd;
455 int r;
456
457 if (handle == NULL)
458 return UV_EBADF;
459
460 fd = uv__stream_fd(handle);
461 if (fd == -1)
462 return UV_EBADF;
463
464 if (mode != UV_READABLE &&
465 mode != UV_WRITABLE &&
466 mode != (UV_WRITABLE | UV_READABLE))
467 return UV_EINVAL;
468
469 desired_mode = 0;
470 if (mode & UV_READABLE)
471 desired_mode |= S_IRUSR | S_IRGRP | S_IROTH;
472 if (mode & UV_WRITABLE)
473 desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
474
475 /* fchmod on macOS and (Free|Net|Open)BSD does not support UNIX sockets. */
476 if (fchmod(fd, desired_mode))
477 if (errno != EINVAL && errno != EOPNOTSUPP)
478 return UV__ERR(errno);
479
480 /* Fall back to chmod. */
481 name_len = sizeof(name_buffer);
482 r = uv_pipe_getsockname(handle, name_buffer, &name_len);
483 if (r != 0)
484 return r;
485 name = name_buffer;
486
487 /* On some platforms, getsockname returns an empty string, and we try with pipe_fname. */
488 if (name_len == 0 && handle->pipe_fname != NULL)
489 name = handle->pipe_fname;
490
491 if (chmod(name, desired_mode))
492 return UV__ERR(errno);
493
494 return 0;
495 }
496
497
498 int uv_pipe(uv_os_fd_t fds[2], int read_flags, int write_flags) {
499 uv_os_fd_t temp[2];
500 int err;
501 #if defined(__linux__) || \
502 defined(__FreeBSD__) || \
503 defined(__OpenBSD__) || \
504 defined(__DragonFly__) || \
505 defined(__NetBSD__) || \
506 defined(__illumos__) || \
507 (defined(UV__SOLARIS_11_4) && UV__SOLARIS_11_4)
508 int flags = O_CLOEXEC;
509
510 if ((read_flags & UV_NONBLOCK_PIPE) && (write_flags & UV_NONBLOCK_PIPE))
511 flags |= UV_FS_O_NONBLOCK;
512
513 if (pipe2(temp, flags))
514 return UV__ERR(errno);
515
516 if (flags & UV_FS_O_NONBLOCK) {
517 fds[0] = temp[0];
518 fds[1] = temp[1];
519 return 0;
520 }
521 #else
522 if (pipe(temp))
523 return UV__ERR(errno);
524
525 if ((err = uv__cloexec(temp[0], 1)))
526 goto fail;
527
528 if ((err = uv__cloexec(temp[1], 1)))
529 goto fail;
530 #endif
531
532 if (read_flags & UV_NONBLOCK_PIPE)
533 if ((err = uv__nonblock(temp[0], 1)))
534 goto fail;
535
536 if (write_flags & UV_NONBLOCK_PIPE)
537 if ((err = uv__nonblock(temp[1], 1)))
538 goto fail;
539
540 fds[0] = temp[0];
541 fds[1] = temp[1];
542 return 0;
543
544 fail:
545 uv__close(temp[0]);
546 uv__close(temp[1]);
547 return err;
548 }
549
550
551 int uv__make_pipe(int fds[2], int flags) {
552 return uv_pipe(fds,
553 flags & UV_NONBLOCK_PIPE,
554 flags & UV_NONBLOCK_PIPE);
555 }