]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/pipe.cc
* Merge in cygwin-64bit-branch.
[newlib-cygwin.git] / winsup / cygwin / pipe.cc
CommitLineData
f02f1f14 1/* pipe.cc: pipe for Cygwin.
1fd5e000 2
e1ab5e68 3 Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
61522196 4 2008, 2009, 2010, 2011, 2012, 2013 Hat, Inc.
1fd5e000
CF
5
6This file is part of Cygwin.
7
8This software is a copyrighted work licensed under the terms of the
9Cygwin license. Please consult the file "CYGWIN_LICENSE" for
10details. */
11
45586380
CF
12/* FIXME: Should this really be fhandler_pipe.cc? */
13
4c8d72de 14#include "winsup.h"
6644c628 15#include <stdlib.h>
49f7ea16 16#include <sys/socket.h>
9e2baf8d 17#include "cygerrno.h"
6b91b8d5 18#include "security.h"
47063f00 19#include "path.h"
7ac61736 20#include "fhandler.h"
bccd5e0d 21#include "dtable.h"
0381fec6 22#include "cygheap.h"
35f879a6 23#include "pinfo.h"
526b0fbc 24#include "shared_info.h"
35f879a6 25
7ac61736 26fhandler_pipe::fhandler_pipe ()
2aeef065 27 : fhandler_base_overlapped (), popen_pid (0)
5e733918 28{
779ece3c 29 max_atomic_write = DEFAULT_PIPEBUFSIZE;
b040009e 30 need_fork_fixup (true);
5e733918
CF
31}
32
3c4f2024 33int
8528ecbd 34fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode)
634a4140 35{
824d8518
CF
36 /* FIXME: Have to clean this up someday
37 FIXME: Do we have to check for both !get_win32_name() and
38 !*get_win32_name()? */
39 if ((!get_win32_name () || !*get_win32_name ()) && get_name ())
634a4140 40 {
824d8518
CF
41 char *d;
42 const char *s;
634a4140 43 char *hold_normalized_name = (char *) alloca (strlen (get_name ()) + 1);
824d8518 44 for (s = get_name (), d = hold_normalized_name; *s; s++, d++)
634a4140
CF
45 if (*s == '/')
46 *d = '\\';
47 else
48 *d = *s;
49 *d = '\0';
50 set_name (hold_normalized_name);
51 }
52
53 bool opened_properly = a & FILE_CREATE_PIPE_INSTANCE;
54 a &= ~FILE_CREATE_PIPE_INSTANCE;
8528ecbd 55 fhandler_base::init (f, a, mode);
e70fdfb9 56 close_on_exec (mode & O_CLOEXEC);
5151c80c
CF
57 if (opened_properly)
58 setup_overlapped ();
59 else
60 destroy_overlapped ();
3c4f2024 61 return 1;
634a4140
CF
62}
63
7d880770
CV
64extern "C" int sscanf (const char *, const char *, ...);
65
e8309efd
CV
66int
67fhandler_pipe::open (int flags, mode_t mode)
68{
8ae1d98d 69 HANDLE proc, pipe_hdl, nio_hdl = NULL;
7d880770
CV
70 fhandler_pipe *fh = NULL;
71 size_t size;
72 int pid, rwflags = (flags & O_ACCMODE);
f62412f2 73 bool inh;
7d880770 74
61522196
CV
75 sscanf (get_name (), "/proc/%d/fd/pipe:[%lu]",
76 &pid, (unsigned long *) &pipe_hdl);
7d880770
CV
77 if (pid == myself->pid)
78 {
16bbf0cc 79 cygheap_fdenum cfd (true);
7d880770
CV
80 while (cfd.next () >= 0)
81 {
82 if (cfd->get_handle () != pipe_hdl)
83 continue;
84 if ((rwflags == O_RDONLY && !(cfd->get_access () & GENERIC_READ))
85 || (rwflags == O_WRONLY && !(cfd->get_access () & GENERIC_WRITE)))
01a94cf8 86 {
7d880770
CV
87 set_errno (EACCES);
88 return 0;
01a94cf8 89 }
23771fa1 90 cfd->copyto (this);
f5a51f91
CV
91 set_io_handle (NULL);
92 pc.reset_conv_handle ();
23771fa1 93 if (!cfd->dup (this, flags))
7d880770
CV
94 return 1;
95 return 0;
01a94cf8 96 }
7d880770
CV
97 set_errno (ENOENT);
98 return 0;
99 }
100
101 pinfo p (pid);
102 if (!p)
103 {
104 set_errno (ESRCH);
105 return 0;
106 }
107 if (!(proc = OpenProcess (PROCESS_DUP_HANDLE, false, p->dwProcessId)))
108 {
109 __seterrno ();
110 return 0;
111 }
112 if (!(fh = p->pipe_fhandler (pipe_hdl, size)) || !size)
113 {
114 set_errno (ENOENT);
115 goto out;
116 }
117 /* Too bad, but Windows only allows the same access mode when dup'ing
118 the pipe. */
119 if ((rwflags == O_RDONLY && !(fh->get_access () & GENERIC_READ))
120 || (rwflags == O_WRONLY && !(fh->get_access () & GENERIC_WRITE)))
121 {
122 set_errno (EACCES);
123 goto out;
124 }
e70fdfb9 125 inh = !(flags & O_CLOEXEC);
f16706de 126 if (!DuplicateHandle (proc, pipe_hdl, GetCurrentProcess (), &nio_hdl,
8ae1d98d 127 0, inh, DUPLICATE_SAME_ACCESS))
7d880770
CV
128 {
129 __seterrno ();
130 goto out;
131 }
7d880770 132 init (nio_hdl, fh->get_access (), mode & O_TEXT ?: O_BINARY);
0d8efc42 133 cfree (fh);
7d880770
CV
134 CloseHandle (proc);
135 return 1;
01a94cf8 136out:
7d880770
CV
137 if (nio_hdl)
138 CloseHandle (nio_hdl);
139 if (fh)
140 free (fh);
141 if (proc)
142 CloseHandle (proc);
e8309efd
CV
143 return 0;
144}
145
61522196
CV
146off_t
147fhandler_pipe::lseek (off_t offset, int whence)
5e733918 148{
61522196 149 debug_printf ("(%D, %d)", offset, whence);
5e733918
CF
150 set_errno (ESPIPE);
151 return -1;
152}
153
7636b585 154int
61522196 155fhandler_pipe::fadvise (off_t offset, off_t length, int advice)
7636b585
CV
156{
157 set_errno (ESPIPE);
158 return -1;
159}
160
161int
61522196 162fhandler_pipe::ftruncate (off_t length, bool allow_truncate)
7636b585
CV
163{
164 set_errno (allow_truncate ? EINVAL : ESPIPE);
165 return -1;
166}
167
b040009e
CF
168char *
169fhandler_pipe::get_proc_fd_name (char *buf)
4f27e288 170{
61522196 171 __small_sprintf (buf, "pipe:[%lu]", get_handle ());
4f27e288
CV
172 return buf;
173}
174
5e733918 175int
23771fa1 176fhandler_pipe::dup (fhandler_base *child, int flags)
5e733918 177{
f7239090 178 fhandler_pipe *ftp = (fhandler_pipe *) child;
c16548b2 179 ftp->set_popen_pid (0);
f7239090 180
d9c0e3ec 181 int res;
23771fa1 182 if (get_handle () && fhandler_base_overlapped::dup (child, flags))
d9c0e3ec 183 res = -1;
b040009e 184 else
d9c0e3ec 185 res = 0;
35f879a6 186
f7239090
CF
187 debug_printf ("res %d", res);
188 return res;
5e733918
CF
189}
190
1ffe3e67
CF
191#define PIPE_INTRO "\\\\.\\pipe\\cygwin-"
192
6644c628
CF
193/* Create a pipe, and return handles to the read and write ends,
194 just like CreatePipe, but ensure that the write end permits
195 FILE_READ_ATTRIBUTES access, on later versions of win32 where
196 this is supported. This access is needed by NtQueryInformationFile,
197 which is used to implement select and nonblocking writes.
fb201f92 198 Note that the return value is either 0 or GetLastError,
6644c628 199 unlike CreatePipe, which returns a bool for success or failure. */
9f65451e
CF
200DWORD
201fhandler_pipe::create (LPSECURITY_ATTRIBUTES sa_ptr, PHANDLE r, PHANDLE w,
202 DWORD psize, const char *name, DWORD open_mode)
6644c628
CF
203{
204 /* Default to error. */
cd071d13
CF
205 if (r)
206 *r = NULL;
207 if (w)
208 *w = NULL;
6644c628
CF
209
210 /* Ensure that there is enough pipe buffer space for atomic writes. */
9f65451e 211 if (!psize)
779ece3c 212 psize = DEFAULT_PIPEBUFSIZE;
6644c628 213
526b0fbc 214 char pipename[MAX_PATH];
28c8ae66
CF
215 size_t len = __small_sprintf (pipename, PIPE_INTRO "%S-",
216 &cygheap->installation_key);
61522196
CV
217 DWORD pipe_mode = PIPE_READMODE_BYTE
218 | (wincap.has_pipe_reject_remote_clients ()
219 ? PIPE_REJECT_REMOTE_CLIENTS : 0);
ea17849f
CF
220 if (!name)
221 pipe_mode |= pipe_byte ? PIPE_TYPE_BYTE : PIPE_TYPE_MESSAGE;
222 else
348b56b5 223 pipe_mode |= PIPE_TYPE_MESSAGE;
526b0fbc 224
348b56b5 225 if (!name || (open_mode & PIPE_ADD_PID))
28c8ae66
CF
226 {
227 len += __small_sprintf (pipename + len, "%u-", GetCurrentProcessId ());
228 open_mode &= ~PIPE_ADD_PID;
229 }
230
348b56b5
CF
231 if (name)
232 len += __small_sprintf (pipename + len, "%s", name);
233
61522196 234 open_mode |= PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE;
6644c628
CF
235
236 /* Retry CreateNamedPipe as long as the pipe name is in use.
237 Retrying will probably never be necessary, but we want
238 to be as robust as possible. */
cd071d13
CF
239 DWORD err = 0;
240 while (r && !*r)
6644c628 241 {
fb201f92 242 static volatile ULONG pipe_unique_id;
1ffe3e67 243 if (!name)
ea17849f
CF
244 __small_sprintf (pipename + len, "pipe-%p",
245 InterlockedIncrement ((LONG *) &pipe_unique_id));
6644c628 246
61522196 247 debug_printf ("name %s, size %u, mode %s", pipename, psize,
ea17849f
CF
248 (pipe_mode & PIPE_TYPE_MESSAGE)
249 ? "PIPE_TYPE_MESSAGE" : "PIPE_TYPE_BYTE");
6644c628
CF
250
251 /* Use CreateNamedPipe instead of CreatePipe, because the latter
d584454c
CF
252 returns a write handle that does not permit FILE_READ_ATTRIBUTES
253 access, on versions of win32 earlier than WinXP SP2.
254 CreatePipe also stupidly creates a full duplex pipe, which is
255 a waste, since only a single direction is actually used.
256 It's important to only allow a single instance, to ensure that
257 the pipe was not created earlier by some other process, even if
61522196 258 the pid has been reused.
31d2bedc
CF
259
260 Note that the write side of the pipe is opened as PIPE_TYPE_MESSAGE.
261 This *seems* to more closely mimic Linux pipe behavior and is
262 definitely required for pty handling since fhandler_pty_master
263 writes to the pipe in chunks, terminated by newline when CANON mode
264 is specified. */
ea17849f 265 *r = CreateNamedPipe (pipename, open_mode, pipe_mode, 1, psize,
fb201f92 266 psize, NMPWAIT_USE_DEFAULT_WAIT, sa_ptr);
6644c628 267
cd071d13 268 if (*r != INVALID_HANDLE_VALUE)
d584454c 269 {
cd071d13
CF
270 debug_printf ("pipe read handle %p", *r);
271 err = 0;
d584454c
CF
272 break;
273 }
6644c628 274
1ffe3e67 275 err = GetLastError ();
6644c628 276 switch (err)
d584454c
CF
277 {
278 case ERROR_PIPE_BUSY:
279 /* The pipe is already open with compatible parameters.
280 Pick a new name and retry. */
cd071d13 281 debug_printf ("pipe busy", !name ? ", retrying" : "");
5f38ec46 282 if (!name)
cd071d13 283 *r = NULL;
fb201f92 284 break;
d584454c
CF
285 case ERROR_ACCESS_DENIED:
286 /* The pipe is already open with incompatible parameters.
287 Pick a new name and retry. */
cd071d13 288 debug_printf ("pipe access denied%s", !name ? ", retrying" : "");
5f38ec46 289 if (!name)
cd071d13 290 *r = NULL;
fb201f92
CF
291 break;
292 default:
d9c0e3ec
CF
293 {
294 err = GetLastError ();
cd071d13 295 debug_printf ("failed, %E");
d9c0e3ec 296 }
d584454c 297 }
6644c628 298 }
1ffe3e67
CF
299
300 if (err)
6644c628 301 {
cd071d13 302 *r = NULL;
6644c628
CF
303 return err;
304 }
305
cd071d13
CF
306 if (!w)
307 debug_printf ("pipe write handle NULL");
308 else
309 {
310 debug_printf ("CreateFile: name %s", pipename);
311
312 /* Open the named pipe for writing.
313 Be sure to permit FILE_READ_ATTRIBUTES access. */
314 DWORD access = GENERIC_WRITE | FILE_READ_ATTRIBUTES;
315 if ((open_mode & PIPE_ACCESS_DUPLEX) == PIPE_ACCESS_DUPLEX)
316 access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
317 *w = CreateFile (pipename, access, 0, sa_ptr, OPEN_EXISTING,
318 open_mode & FILE_FLAG_OVERLAPPED, 0);
319
320 if (!*w || *w == INVALID_HANDLE_VALUE)
321 {
322 /* Failure. */
323 DWORD err = GetLastError ();
1ad58ee7 324 debug_printf ("CreateFile failed, r %p, %E", r);
cd071d13
CF
325 if (r)
326 CloseHandle (*r);
327 *w = NULL;
328 return err;
329 }
330
331 debug_printf ("pipe write handle %p", *w);
332 }
6644c628
CF
333
334 /* Success. */
fb201f92 335 return 0;
6644c628
CF
336}
337
35f879a6 338int
be1cabba 339fhandler_pipe::create (fhandler_pipe *fhs[2], unsigned psize, int mode)
1fd5e000 340{
1fd5e000 341 HANDLE r, w;
e70fdfb9 342 SECURITY_ATTRIBUTES *sa = sec_none_cloexec (mode);
9e1fd6bc 343 int res = -1;
1fd5e000 344
9f65451e 345 int ret = create (sa, &r, &w, psize, NULL, FILE_FLAG_OVERLAPPED);
fb201f92 346 if (ret)
9e1fd6bc
CV
347 __seterrno_from_win_error (ret);
348 else if ((fhs[0] = (fhandler_pipe *) build_fh_dev (*piper_dev)) == NULL)
8528ecbd 349 {
9e1fd6bc
CV
350 CloseHandle (r);
351 CloseHandle (w);
352 }
353 else if ((fhs[1] = (fhandler_pipe *) build_fh_dev (*pipew_dev)) == NULL)
354 {
355 delete fhs[0];
356 CloseHandle (w);
8528ecbd 357 }
7ac61736 358 else
1fd5e000 359 {
8528ecbd
CF
360 mode |= mode & O_TEXT ?: O_BINARY;
361 fhs[0]->init (r, FILE_CREATE_PIPE_INSTANCE | GENERIC_READ, mode);
362 fhs[1]->init (w, FILE_CREATE_PIPE_INSTANCE | GENERIC_WRITE, mode);
7ac61736 363 res = 0;
1fd5e000
CF
364 }
365
61522196 366 debug_printf ("%R = pipe([%p, %p], %d, %y)", res, fhs[0], fhs[1], psize, mode);
57bf29e8 367 return res;
1fd5e000
CF
368}
369
49f7ea16
CF
370int
371fhandler_pipe::ioctl (unsigned int cmd, void *p)
372{
373 int n;
374
375 switch (cmd)
376 {
377 case FIONREAD:
378 if (get_device () == FH_PIPEW)
379 {
380 set_errno (EINVAL);
381 return -1;
382 }
383 if (!PeekNamedPipe (get_handle (), NULL, 0, NULL, (DWORD *) &n, NULL))
384 {
385 __seterrno ();
386 return -1;
387 }
388 break;
389 default:
390 return fhandler_base::ioctl (cmd, p);
391 break;
392 }
393 *(int *) p = n;
394 return 0;
395}
396
3323df7e
CV
397int __stdcall
398fhandler_pipe::fstatvfs (struct statvfs *sfs)
399{
400 set_errno (EBADF);
401 return -1;
402}
403
6e75c72b 404static int __reg3
b11797ad 405pipe_worker (int filedes[2], unsigned int psize, int mode)
1fd5e000 406{
7ac61736 407 fhandler_pipe *fhs[2];
56c387b1
CV
408 int res = fhandler_pipe::create (fhs, psize, mode);
409 if (!res)
7ac61736
CF
410 {
411 cygheap_fdnew fdin;
412 cygheap_fdnew fdout (fdin, false);
2aeef065
CF
413 char buf[sizeof ("/dev/fd/pipe:[2147483647]")];
414 __small_sprintf (buf, "/dev/fd/pipe:[%d]", (int) fdin);
415 fhs[0]->pc.set_normalized_path (buf);
416 __small_sprintf (buf, "pipe:[%d]", (int) fdout);
417 fhs[1]->pc.set_normalized_path (buf);
7ac61736
CF
418 fdin = fhs[0];
419 fdout = fhs[1];
420 filedes[0] = fdin;
421 filedes[1] = fdout;
1b23b30b 422 }
b11797ad
CF
423 return res;
424}
425
426extern "C" int
427_pipe (int filedes[2], unsigned int psize, int mode)
428{
429 int res = pipe_worker (filedes, psize, mode);
430 int read, write;
431 if (res != 0)
432 read = write = -1;
433 else
434 {
435 read = filedes[0];
436 write = filedes[1];
7ac61736 437 }
61522196 438 syscall_printf ("%R = _pipe([%d, %d], %u, %y)", res, read, write, psize, mode);
7ac61736 439 return res;
1fd5e000
CF
440}
441
442extern "C" int
56c387b1 443pipe (int filedes[2])
1fd5e000 444{
b11797ad
CF
445 int res = pipe_worker (filedes, DEFAULT_PIPEBUFSIZE, O_BINARY);
446 int read, write;
447 if (res != 0)
448 read = write = -1;
449 else
450 {
451 read = filedes[0];
452 write = filedes[1];
453 }
454 syscall_printf ("%R = pipe([%d, %d])", res, read, write);
455 return res;
1fd5e000 456}
e70fdfb9
CV
457
458extern "C" int
459pipe2 (int filedes[2], int mode)
460{
b11797ad
CF
461 int res = pipe_worker (filedes, DEFAULT_PIPEBUFSIZE, mode);
462 int read, write;
463 if (res != 0)
464 read = write = -1;
465 else
466 {
467 read = filedes[0];
468 write = filedes[1];
469 }
61522196 470 syscall_printf ("%R = pipe2([%d, %d], %y)", res, read, write, mode);
b11797ad 471 return res;
e70fdfb9 472}
This page took 0.50256 seconds and 5 git commands to generate.