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
uv_pipe_init(uv_loop_t * loop,uv_pipe_t * handle,int ipc)33 int uv_pipe_init(uv_loop_t* loop, uv_pipe_t* handle, int ipc) {
34 uv__stream_init(loop, (uv_stream_t*)handle, UV_NAMED_PIPE);
35 handle->shutdown_req = NULL;
36 handle->connect_req = NULL;
37 handle->pipe_fname = NULL;
38 handle->ipc = ipc;
39 return 0;
40 }
41
42
uv_pipe_bind(uv_pipe_t * handle,const char * name)43 int uv_pipe_bind(uv_pipe_t* handle, const char* name) {
44 struct sockaddr_un saddr;
45 const char* pipe_fname;
46 int sockfd;
47 int err;
48
49 pipe_fname = NULL;
50
51 /* Already bound? */
52 if (uv__stream_fd(handle) >= 0)
53 return UV_EINVAL;
54 if (uv__is_closing(handle)) {
55 return UV_EINVAL;
56 }
57 /* Make a copy of the file name, it outlives this function's scope. */
58 pipe_fname = uv__strdup(name);
59 if (pipe_fname == NULL)
60 return UV_ENOMEM;
61
62 /* We've got a copy, don't touch the original any more. */
63 name = NULL;
64
65 err = uv__socket(AF_UNIX, SOCK_STREAM, 0);
66 if (err < 0)
67 goto err_socket;
68 sockfd = err;
69
70 memset(&saddr, 0, sizeof saddr);
71 uv__strscpy(saddr.sun_path, pipe_fname, sizeof(saddr.sun_path));
72 saddr.sun_family = AF_UNIX;
73
74 if (bind(sockfd, (struct sockaddr*)&saddr, sizeof saddr)) {
75 err = UV__ERR(errno);
76 /* Convert ENOENT to EACCES for compatibility with Windows. */
77 if (err == UV_ENOENT)
78 err = UV_EACCES;
79
80 uv__close(sockfd);
81 goto err_socket;
82 }
83
84 /* Success. */
85 handle->flags |= UV_HANDLE_BOUND;
86 handle->pipe_fname = pipe_fname; /* Is a strdup'ed copy. */
87 handle->io_watcher.fd = sockfd;
88 return 0;
89
90 err_socket:
91 uv__free((void*)pipe_fname);
92 return err;
93 }
94
95
uv__pipe_listen(uv_pipe_t * handle,int backlog,uv_connection_cb cb)96 int uv__pipe_listen(uv_pipe_t* handle, int backlog, uv_connection_cb cb) {
97 if (uv__stream_fd(handle) == -1)
98 return UV_EINVAL;
99
100 if (handle->ipc)
101 return UV_EINVAL;
102
103 #if defined(__MVS__) || defined(__PASE__)
104 /* On zOS, backlog=0 has undefined behaviour */
105 /* On IBMi PASE, backlog=0 leads to "Connection refused" error */
106 if (backlog == 0)
107 backlog = 1;
108 else if (backlog < 0)
109 backlog = SOMAXCONN;
110 #endif
111
112 if (listen(uv__stream_fd(handle), backlog))
113 return UV__ERR(errno);
114
115 handle->connection_cb = cb;
116 handle->io_watcher.cb = uv__server_io;
117 uv__io_start(handle->loop, &handle->io_watcher, POLLIN);
118 return 0;
119 }
120
121
uv__pipe_close(uv_pipe_t * handle)122 void uv__pipe_close(uv_pipe_t* handle) {
123 if (handle->pipe_fname) {
124 /*
125 * Unlink the file system entity before closing the file descriptor.
126 * Doing it the other way around introduces a race where our process
127 * unlinks a socket with the same name that's just been created by
128 * another thread or process.
129 */
130 unlink(handle->pipe_fname);
131 uv__free((void*)handle->pipe_fname);
132 handle->pipe_fname = NULL;
133 }
134
135 uv__stream_close((uv_stream_t*)handle);
136 }
137
138
uv_pipe_open(uv_pipe_t * handle,uv_file fd)139 int uv_pipe_open(uv_pipe_t* handle, uv_file fd) {
140 int flags;
141 int mode;
142 int err;
143 flags = 0;
144
145 if (uv__fd_exists(handle->loop, fd))
146 return UV_EEXIST;
147
148 do
149 mode = fcntl(fd, F_GETFL);
150 while (mode == -1 && errno == EINTR);
151
152 if (mode == -1)
153 return UV__ERR(errno); /* according to docs, must be EBADF */
154
155 err = uv__nonblock(fd, 1);
156 if (err)
157 return err;
158
159 #if defined(__APPLE__)
160 err = uv__stream_try_select((uv_stream_t*) handle, &fd);
161 if (err)
162 return err;
163 #endif /* defined(__APPLE__) */
164
165 mode &= O_ACCMODE;
166 if (mode != O_WRONLY)
167 flags |= UV_HANDLE_READABLE;
168 if (mode != O_RDONLY)
169 flags |= UV_HANDLE_WRITABLE;
170
171 return uv__stream_open((uv_stream_t*)handle, fd, flags);
172 }
173
174
uv_pipe_connect(uv_connect_t * req,uv_pipe_t * handle,const char * name,uv_connect_cb cb)175 void uv_pipe_connect(uv_connect_t* req,
176 uv_pipe_t* handle,
177 const char* name,
178 uv_connect_cb cb) {
179 struct sockaddr_un saddr;
180 int new_sock;
181 int err;
182 int r;
183
184 new_sock = (uv__stream_fd(handle) == -1);
185
186 if (new_sock) {
187 err = uv__socket(AF_UNIX, SOCK_STREAM, 0);
188 if (err < 0)
189 goto out;
190 handle->io_watcher.fd = err;
191 }
192
193 memset(&saddr, 0, sizeof saddr);
194 uv__strscpy(saddr.sun_path, name, sizeof(saddr.sun_path));
195 saddr.sun_family = AF_UNIX;
196
197 do {
198 r = connect(uv__stream_fd(handle),
199 (struct sockaddr*)&saddr, sizeof saddr);
200 }
201 while (r == -1 && errno == EINTR);
202
203 if (r == -1 && errno != EINPROGRESS) {
204 err = UV__ERR(errno);
205 #if defined(__CYGWIN__) || defined(__MSYS__)
206 /* EBADF is supposed to mean that the socket fd is bad, but
207 Cygwin reports EBADF instead of ENOTSOCK when the file is
208 not a socket. We do not expect to see a bad fd here
209 (e.g. due to new_sock), so translate the error. */
210 if (err == UV_EBADF)
211 err = UV_ENOTSOCK;
212 #endif
213 goto out;
214 }
215
216 err = 0;
217 if (new_sock) {
218 err = uv__stream_open((uv_stream_t*)handle,
219 uv__stream_fd(handle),
220 UV_HANDLE_READABLE | UV_HANDLE_WRITABLE);
221 }
222
223 if (err == 0)
224 uv__io_start(handle->loop, &handle->io_watcher, POLLOUT);
225
226 out:
227 handle->delayed_error = err;
228 handle->connect_req = req;
229
230 uv__req_init(handle->loop, req, UV_CONNECT);
231 req->handle = (uv_stream_t*)handle;
232 req->cb = cb;
233 QUEUE_INIT(&req->queue);
234
235 /* Force callback to run on next tick in case of error. */
236 if (err)
237 uv__io_feed(handle->loop, &handle->io_watcher);
238
239 }
240
241
uv__pipe_getsockpeername(const uv_pipe_t * handle,uv__peersockfunc func,char * buffer,size_t * size)242 static int uv__pipe_getsockpeername(const uv_pipe_t* handle,
243 uv__peersockfunc func,
244 char* buffer,
245 size_t* size) {
246 struct sockaddr_un sa;
247 socklen_t addrlen;
248 int err;
249
250 addrlen = sizeof(sa);
251 memset(&sa, 0, addrlen);
252 err = uv__getsockpeername((const uv_handle_t*) handle,
253 func,
254 (struct sockaddr*) &sa,
255 (int*) &addrlen);
256 if (err < 0) {
257 *size = 0;
258 return err;
259 }
260
261 #if defined(__linux__)
262 if (sa.sun_path[0] == 0)
263 /* Linux abstract namespace */
264 addrlen -= offsetof(struct sockaddr_un, sun_path);
265 else
266 #endif
267 addrlen = strlen(sa.sun_path);
268
269
270 if ((size_t)addrlen >= *size) {
271 *size = addrlen + 1;
272 return UV_ENOBUFS;
273 }
274
275 memcpy(buffer, sa.sun_path, addrlen);
276 *size = addrlen;
277
278 /* only null-terminate if it's not an abstract socket */
279 if (buffer[0] != '\0')
280 buffer[addrlen] = '\0';
281
282 return 0;
283 }
284
285
uv_pipe_getsockname(const uv_pipe_t * handle,char * buffer,size_t * size)286 int uv_pipe_getsockname(const uv_pipe_t* handle, char* buffer, size_t* size) {
287 return uv__pipe_getsockpeername(handle, getsockname, buffer, size);
288 }
289
290
uv_pipe_getpeername(const uv_pipe_t * handle,char * buffer,size_t * size)291 int uv_pipe_getpeername(const uv_pipe_t* handle, char* buffer, size_t* size) {
292 return uv__pipe_getsockpeername(handle, getpeername, buffer, size);
293 }
294
295
uv_pipe_pending_instances(uv_pipe_t * handle,int count)296 void uv_pipe_pending_instances(uv_pipe_t* handle, int count) {
297 }
298
299
uv_pipe_pending_count(uv_pipe_t * handle)300 int uv_pipe_pending_count(uv_pipe_t* handle) {
301 uv__stream_queued_fds_t* queued_fds;
302
303 if (!handle->ipc)
304 return 0;
305
306 if (handle->accepted_fd == -1)
307 return 0;
308
309 if (handle->queued_fds == NULL)
310 return 1;
311
312 queued_fds = handle->queued_fds;
313 return queued_fds->offset + 1;
314 }
315
316
uv_pipe_pending_type(uv_pipe_t * handle)317 uv_handle_type uv_pipe_pending_type(uv_pipe_t* handle) {
318 if (!handle->ipc)
319 return UV_UNKNOWN_HANDLE;
320
321 if (handle->accepted_fd == -1)
322 return UV_UNKNOWN_HANDLE;
323 else
324 return uv_guess_handle(handle->accepted_fd);
325 }
326
327
uv_pipe_chmod(uv_pipe_t * handle,int mode)328 int uv_pipe_chmod(uv_pipe_t* handle, int mode) {
329 unsigned desired_mode;
330 struct stat pipe_stat;
331 char* name_buffer;
332 size_t name_len;
333 int r;
334
335 if (handle == NULL || uv__stream_fd(handle) == -1)
336 return UV_EBADF;
337
338 if (mode != UV_READABLE &&
339 mode != UV_WRITABLE &&
340 mode != (UV_WRITABLE | UV_READABLE))
341 return UV_EINVAL;
342
343 /* Unfortunately fchmod does not work on all platforms, we will use chmod. */
344 name_len = 0;
345 r = uv_pipe_getsockname(handle, NULL, &name_len);
346 if (r != UV_ENOBUFS)
347 return r;
348
349 name_buffer = uv__malloc(name_len);
350 if (name_buffer == NULL)
351 return UV_ENOMEM;
352
353 r = uv_pipe_getsockname(handle, name_buffer, &name_len);
354 if (r != 0) {
355 uv__free(name_buffer);
356 return r;
357 }
358
359 /* stat must be used as fstat has a bug on Darwin */
360 if (stat(name_buffer, &pipe_stat) == -1) {
361 uv__free(name_buffer);
362 return -errno;
363 }
364
365 desired_mode = 0;
366 if (mode & UV_READABLE)
367 desired_mode |= S_IRUSR | S_IRGRP | S_IROTH;
368 if (mode & UV_WRITABLE)
369 desired_mode |= S_IWUSR | S_IWGRP | S_IWOTH;
370
371 /* Exit early if pipe already has desired mode. */
372 if ((pipe_stat.st_mode & desired_mode) == desired_mode) {
373 uv__free(name_buffer);
374 return 0;
375 }
376
377 pipe_stat.st_mode |= desired_mode;
378
379 r = chmod(name_buffer, pipe_stat.st_mode);
380 uv__free(name_buffer);
381
382 return r != -1 ? 0 : UV__ERR(errno);
383 }
384
385
uv_pipe(uv_os_fd_t fds[2],int read_flags,int write_flags)386 int uv_pipe(uv_os_fd_t fds[2], int read_flags, int write_flags) {
387 uv_os_fd_t temp[2];
388 int err;
389 #if defined(__FreeBSD__) || defined(__linux__)
390 int flags = O_CLOEXEC;
391
392 if ((read_flags & UV_NONBLOCK_PIPE) && (write_flags & UV_NONBLOCK_PIPE))
393 flags |= UV_FS_O_NONBLOCK;
394
395 if (pipe2(temp, flags))
396 return UV__ERR(errno);
397
398 if (flags & UV_FS_O_NONBLOCK) {
399 fds[0] = temp[0];
400 fds[1] = temp[1];
401 return 0;
402 }
403 #else
404 if (pipe(temp))
405 return UV__ERR(errno);
406
407 if ((err = uv__cloexec(temp[0], 1)))
408 goto fail;
409
410 if ((err = uv__cloexec(temp[1], 1)))
411 goto fail;
412 #endif
413
414 if (read_flags & UV_NONBLOCK_PIPE)
415 if ((err = uv__nonblock(temp[0], 1)))
416 goto fail;
417
418 if (write_flags & UV_NONBLOCK_PIPE)
419 if ((err = uv__nonblock(temp[1], 1)))
420 goto fail;
421
422 fds[0] = temp[0];
423 fds[1] = temp[1];
424 return 0;
425
426 fail:
427 uv__close(temp[0]);
428 uv__close(temp[1]);
429 return err;
430 }
431
432
uv__make_pipe(int fds[2],int flags)433 int uv__make_pipe(int fds[2], int flags) {
434 return uv_pipe(fds,
435 flags & UV_NONBLOCK_PIPE,
436 flags & UV_NONBLOCK_PIPE);
437 }
438