Cygwin: pinfo: use stpcpy where appropriate
[newlib-cygwin.git] / winsup / cygwin / fhandler / pipe.cc
blob1a97108b5d62c9f7e6f8287c6425aaa6faf731c3
1 /* fhandler_pipe.cc: pipes for Cygwin.
3 This file is part of Cygwin.
5 This software is a copyrighted work licensed under the terms of the
6 Cygwin license. Please consult the file "CYGWIN_LICENSE" for
7 details. */
9 #include "winsup.h"
10 #include <stdlib.h>
11 #include <sys/socket.h>
12 #include "cygerrno.h"
13 #include "security.h"
14 #include "path.h"
15 #include "fhandler.h"
16 #include "dtable.h"
17 #include "cygheap.h"
18 #include "pinfo.h"
19 #include "shared_info.h"
20 #include "tls_pbuf.h"
21 #include <assert.h>
23 /* This is only to be used for writing. When reading,
24 STATUS_PIPE_EMPTY simply means there's no data to be read. */
25 #define STATUS_PIPE_IS_CLOSED(status) \
26 ({ NTSTATUS _s = (status); \
27 _s == STATUS_PIPE_CLOSING \
28 || _s == STATUS_PIPE_BROKEN \
29 || _s == STATUS_PIPE_EMPTY; })
31 fhandler_pipe_fifo::fhandler_pipe_fifo ()
32 : fhandler_base (), pipe_buf_size (DEFAULT_PIPEBUFSIZE)
37 fhandler_pipe::fhandler_pipe ()
38 : fhandler_pipe_fifo (), popen_pid (0)
40 need_fork_fixup (true);
43 /* The following function is intended for fhandler_pipe objects
44 created by the second version of fhandler_pipe::create below. See
45 the comment preceding the latter.
47 In addition to setting the blocking mode of the pipe handle, it
48 also sets the pipe's read mode to byte_stream unconditionally. */
49 void
50 fhandler_pipe::set_pipe_non_blocking (bool nonblocking)
52 NTSTATUS status;
53 IO_STATUS_BLOCK io;
54 FILE_PIPE_INFORMATION fpi;
56 fpi.ReadMode = FILE_PIPE_BYTE_STREAM_MODE;
57 fpi.CompletionMode = nonblocking ? FILE_PIPE_COMPLETE_OPERATION
58 : FILE_PIPE_QUEUE_OPERATION;
59 status = NtSetInformationFile (get_handle (), &io, &fpi, sizeof fpi,
60 FilePipeInformation);
61 if (!NT_SUCCESS (status))
62 debug_printf ("NtSetInformationFile(FilePipeInformation): %y", status);
65 int
66 fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode, int64_t uniq_id)
68 /* FIXME: Have to clean this up someday
69 FIXME: Do we have to check for both !get_win32_name() and
70 !*get_win32_name()? */
71 if ((!get_win32_name () || !*get_win32_name ()) && get_name ())
73 char *d;
74 const char *s;
75 char *hold_normalized_name = (char *) alloca (strlen (get_name ()) + 1);
76 for (s = get_name (), d = hold_normalized_name; *s; s++, d++)
77 if (*s == '/')
78 *d = '\\';
79 else
80 *d = *s;
81 *d = '\0';
82 set_name (hold_normalized_name);
85 bool opened_properly = a & FILE_CREATE_PIPE_INSTANCE;
86 a &= ~FILE_CREATE_PIPE_INSTANCE;
87 fhandler_base::init (f, a, mode);
88 close_on_exec (mode & O_CLOEXEC);
89 set_ino (uniq_id);
90 set_unique_id (uniq_id | !!(mode & GENERIC_WRITE));
91 if (opened_properly)
92 /* Set read pipe always nonblocking to allow signal handling
93 even with FILE_SYNCHRONOUS_IO_NONALERT. */
94 set_pipe_non_blocking (get_device () == FH_PIPER ?
95 true : is_nonblocking ());
96 return 1;
99 extern "C" int sscanf (const char *, const char *, ...);
102 fhandler_pipe::open (int flags, mode_t mode)
104 HANDLE proc, nio_hdl = NULL;
105 int64_t uniq_id;
106 fhandler_pipe *fh = NULL, *fhr = NULL, *fhw = NULL;
107 size_t size;
108 int pid, rwflags = (flags & O_ACCMODE);
109 bool inh;
110 bool got_one = false;
112 if (sscanf (get_name (), "/proc/%d/fd/pipe:[%llu]",
113 &pid, (long long *) &uniq_id) < 2)
115 set_errno (ENOENT);
116 return 0;
118 if (pid == myself->pid)
120 cygheap_fdenum cfd (true);
121 while (cfd.next () >= 0)
123 /* Windows doesn't allow to copy a pipe HANDLE with another access
124 mode. So we check for read and write side of pipe and try to
125 find the one matching the requested access mode. */
126 if (cfd->get_unique_id () == uniq_id)
127 got_one = true;
128 else if (cfd->get_unique_id () == uniq_id + 1)
129 got_one = true;
130 else
131 continue;
132 if ((rwflags == O_RDONLY && !(cfd->get_access () & GENERIC_READ))
133 || (rwflags == O_WRONLY && !(cfd->get_access () & GENERIC_WRITE)))
134 continue;
135 copy_from (cfd);
136 set_handle (NULL);
137 pc.close_conv_handle ();
138 if (!cfd->dup (this, flags))
139 return 1;
140 return 0;
142 /* Found the pipe but access mode didn't match? EACCES.
143 Otherwise ENOENT */
144 set_errno (got_one ? EACCES : ENOENT);
145 return 0;
148 pinfo p (pid);
149 if (!p)
151 set_errno (ESRCH);
152 return 0;
154 if (!(proc = OpenProcess (PROCESS_DUP_HANDLE, false, p->dwProcessId)))
156 __seterrno ();
157 return 0;
159 fhr = p->pipe_fhandler (uniq_id, size);
160 if (fhr && rwflags == O_RDONLY)
161 fh = fhr;
162 else
164 fhw = p->pipe_fhandler (uniq_id + 1, size);
165 if (fhw && rwflags == O_WRONLY)
166 fh = fhw;
168 if (!fh)
170 /* Too bad, but Windows only allows the same access mode when dup'ing
171 the pipe. */
172 set_errno (fhr || fhw ? EACCES : ENOENT);
173 goto out;
175 inh = !(flags & O_CLOEXEC);
176 if (!DuplicateHandle (proc, fh->get_handle (), GetCurrentProcess (),
177 &nio_hdl, 0, inh, DUPLICATE_SAME_ACCESS))
179 __seterrno ();
180 goto out;
182 init (nio_hdl, fh->get_access (), mode & O_TEXT ?: O_BINARY,
183 fh->get_plain_ino ());
184 cfree (fh);
185 CloseHandle (proc);
186 return 1;
187 out:
188 if (nio_hdl)
189 CloseHandle (nio_hdl);
190 if (fh)
191 free (fh);
192 if (proc)
193 CloseHandle (proc);
194 return 0;
197 bool
198 fhandler_pipe::open_setup (int flags)
200 bool read_mtx_created = false;
202 if (!fhandler_base::open_setup (flags))
203 goto err;
204 if (get_dev () == FH_PIPER && !read_mtx)
206 SECURITY_ATTRIBUTES *sa = sec_none_cloexec (flags);
207 read_mtx = CreateMutex (sa, FALSE, NULL);
208 if (read_mtx)
209 read_mtx_created = true;
210 else
212 debug_printf ("CreateMutex read_mtx failed: %E");
213 goto err;
216 if (!hdl_cnt_mtx)
218 SECURITY_ATTRIBUTES *sa = sec_none_cloexec (flags);
219 hdl_cnt_mtx = CreateMutex (sa, FALSE, NULL);
220 if (!hdl_cnt_mtx)
222 debug_printf ("CreateMutex hdl_cnt_mtx failed: %E");
223 goto err_close_read_mtx;
226 return true;
228 err_close_read_mtx:
229 if (read_mtx_created)
230 CloseHandle (read_mtx);
231 err:
232 return false;
235 off_t
236 fhandler_pipe::lseek (off_t offset, int whence)
238 debug_printf ("(%D, %d)", offset, whence);
239 set_errno (ESPIPE);
240 return -1;
244 fhandler_pipe::fadvise (off_t offset, off_t length, int advice)
246 return ESPIPE;
250 fhandler_pipe::fallocate (int mode, off_t offset, off_t length)
252 return (mode & __FALLOC_FL_TRUNCATE) ? EINVAL : ESPIPE;
255 char *
256 fhandler_pipe::get_proc_fd_name (char *buf)
258 __small_sprintf (buf, "pipe:[%U]", get_plain_ino ());
259 return buf;
262 void
263 fhandler_pipe::release_select_sem (const char *from)
265 LONG n_release;
266 if (get_dev () == FH_PIPER) /* Number of select() and writer */
267 n_release = get_obj_handle_count (select_sem)
268 - get_obj_handle_count (read_mtx);
269 else /* Number of select() call and reader */
270 n_release = get_obj_handle_count (select_sem)
271 - get_obj_handle_count (get_handle ());
272 debug_printf("%s(%s) release %d", from,
273 get_dev () == FH_PIPER ? "PIPER" : "PIPEW", n_release);
274 if (n_release)
275 ReleaseSemaphore (select_sem, n_release, NULL);
278 void
279 fhandler_pipe::raw_read (void *ptr, size_t& len)
281 size_t nbytes = 0;
282 NTSTATUS status = STATUS_SUCCESS;
283 IO_STATUS_BLOCK io;
284 ULONGLONG t0 = GetTickCount64 (); /* Init timer */
285 const ULONGLONG t0_threshold = 20;
287 if (!len)
288 return;
290 DWORD timeout = is_nonblocking () ? 0 : INFINITE;
291 DWORD waitret = cygwait (read_mtx, timeout);
292 switch (waitret)
294 case WAIT_OBJECT_0:
295 break;
296 case WAIT_TIMEOUT:
297 set_errno (EAGAIN);
298 len = (size_t) -1;
299 return;
300 case WAIT_SIGNALED:
301 set_errno (EINTR);
302 len = (size_t) -1;
303 return;
304 case WAIT_CANCELED:
305 pthread::static_cancel_self ();
306 /* NOTREACHED */
307 default:
308 /* Should not reach here. */
309 __seterrno ();
310 len = (size_t) -1;
311 return;
313 while (nbytes < len)
315 ULONG_PTR nbytes_now = 0;
316 ULONG len1 = (ULONG) (len - nbytes);
317 DWORD select_sem_timeout = 0;
319 FILE_PIPE_LOCAL_INFORMATION fpli;
320 status = NtQueryInformationFile (get_handle (), &io,
321 &fpli, sizeof (fpli),
322 FilePipeLocalInformation);
323 if (NT_SUCCESS (status))
325 if (fpli.ReadDataAvailable == 0 && nbytes != 0)
326 break;
328 else if (nbytes != 0)
329 break;
330 status = NtReadFile (get_handle (), NULL, NULL, NULL, &io, ptr,
331 len1, NULL, NULL);
332 if (isclosed ()) /* A signal handler might have closed the fd. */
334 set_errno (EBADF);
335 nbytes = (size_t) -1;
337 else if (NT_SUCCESS (status) || status == STATUS_BUFFER_OVERFLOW)
339 nbytes_now = io.Information;
340 ptr = ((char *) ptr) + nbytes_now;
341 nbytes += nbytes_now;
342 if (select_sem && nbytes_now > 0)
343 release_select_sem ("raw_read");
345 else
347 /* Some errors are not really errors. Detect such cases here. */
348 switch (status)
350 case STATUS_END_OF_FILE:
351 case STATUS_PIPE_BROKEN:
352 /* This is really EOF. */
353 break;
354 case STATUS_PIPE_LISTENING:
355 case STATUS_PIPE_EMPTY:
356 if (nbytes != 0)
357 break;
358 if (is_nonblocking ())
360 set_errno (EAGAIN);
361 nbytes = (size_t) -1;
362 break;
364 /* If the pipe is a non-cygwin pipe, select_sem trick
365 does not work. As a result, the following cygwait()
366 will return only after timeout occurs. This causes
367 performance degradation. However, setting timeout
368 to zero causes high CPU load. So, set timeout to
369 non-zero only when select_sem is valid or pipe is
370 not ready to read for more than t0_threshold.
371 This prevents both the performance degradation and
372 the high CPU load. */
373 if (select_sem || GetTickCount64 () - t0 > t0_threshold)
374 select_sem_timeout = 1;
375 waitret = cygwait (select_sem, select_sem_timeout);
376 if (waitret == WAIT_CANCELED)
377 pthread::static_cancel_self ();
378 else if (waitret == WAIT_SIGNALED)
380 set_errno (EINTR);
381 nbytes = (size_t) -1;
382 break;
384 continue;
385 default:
386 __seterrno_from_nt_status (status);
387 nbytes = (size_t) -1;
388 break;
392 if ((nbytes_now == 0 && !NT_SUCCESS (status))
393 || status == STATUS_BUFFER_OVERFLOW)
394 break;
396 ReleaseMutex (read_mtx);
397 len = nbytes;
400 bool
401 fhandler_pipe::reader_closed ()
403 if (!query_hdl)
404 return false;
405 WaitForSingleObject (hdl_cnt_mtx, INFINITE);
406 int n_reader = get_obj_handle_count (query_hdl);
407 int n_writer = get_obj_handle_count (get_handle ());
408 ReleaseMutex (hdl_cnt_mtx);
409 return n_reader == n_writer;
412 ssize_t
413 fhandler_pipe_fifo::raw_write (const void *ptr, size_t len)
415 size_t nbytes = 0;
416 ULONG chunk;
417 NTSTATUS status = STATUS_SUCCESS;
418 IO_STATUS_BLOCK io;
419 HANDLE evt;
421 if (!len)
422 return 0;
424 if (reader_closed ())
426 set_errno (EPIPE);
427 raise (SIGPIPE);
428 return -1;
431 if (len <= pipe_buf_size || pipe_buf_size == 0)
432 chunk = len;
433 else if (is_nonblocking ())
434 chunk = len = pipe_buf_size;
435 else
436 chunk = pipe_buf_size;
438 if (!(evt = CreateEvent (NULL, false, false, NULL)))
440 __seterrno ();
441 return -1;
444 /* Write in chunks, accumulating a total. If there's an error, just
445 return the accumulated total unless the first write fails, in
446 which case return -1. */
447 while (nbytes < len)
449 ULONG_PTR nbytes_now = 0;
450 size_t left = len - nbytes;
451 ULONG len1;
452 DWORD waitret = WAIT_OBJECT_0;
454 if (left > chunk)
455 len1 = chunk;
456 else
457 len1 = (ULONG) left;
458 /* NtWriteFile returns success with # of bytes written == 0 if writing
459 on a non-blocking pipe fails because the pipe buffer doesn't have
460 sufficient space.
462 POSIX requires
463 - A write request for {PIPE_BUF} or fewer bytes shall have the
464 following effect: if there is sufficient space available in the
465 pipe, write() shall transfer all the data and return the number
466 of bytes requested. Otherwise, write() shall transfer no data and
467 return -1 with errno set to [EAGAIN].
469 - A write request for more than {PIPE_BUF} bytes shall cause one
470 of the following:
472 - When at least one byte can be written, transfer what it can and
473 return the number of bytes written. When all data previously
474 written to the pipe is read, it shall transfer at least {PIPE_BUF}
475 bytes.
477 - When no data can be written, transfer no data, and return -1 with
478 errno set to [EAGAIN]. */
479 while (len1 > 0)
481 status = NtWriteFile (get_handle (), evt, NULL, NULL, &io,
482 (PVOID) ptr, len1, NULL, NULL);
483 if (status == STATUS_PENDING)
485 while (WAIT_TIMEOUT ==
486 (waitret = cygwait (evt, (DWORD) 0, cw_cancel | cw_sig)))
488 if (reader_closed ())
490 CancelIo (get_handle ());
491 set_errno (EPIPE);
492 raise (SIGPIPE);
493 goto out;
495 else
496 cygwait (select_sem, 10);
498 /* If io.Status is STATUS_CANCELLED after CancelIo, IO has
499 actually been cancelled and io.Information contains the
500 number of bytes processed so far.
501 Otherwise IO has been finished regulary and io.Status
502 contains valid success or error information. */
503 CancelIo (get_handle ());
504 if (waitret == WAIT_SIGNALED && io.Status != STATUS_CANCELLED)
505 waitret = WAIT_OBJECT_0;
507 if (waitret == WAIT_CANCELED)
508 status = STATUS_THREAD_CANCELED;
509 else if (waitret == WAIT_SIGNALED)
510 status = STATUS_THREAD_SIGNALED;
511 else
512 status = io.Status;
514 if (!is_nonblocking () || !NT_SUCCESS (status) || io.Information > 0
515 || len <= PIPE_BUF)
516 break;
517 len1 >>= 1;
519 if (isclosed ()) /* A signal handler might have closed the fd. */
521 if (waitret == WAIT_OBJECT_0)
522 set_errno (EBADF);
523 else
524 __seterrno ();
526 else if (NT_SUCCESS (status)
527 || status == STATUS_THREAD_CANCELED
528 || status == STATUS_THREAD_SIGNALED)
530 nbytes_now = io.Information;
531 ptr = ((char *) ptr) + nbytes_now;
532 nbytes += nbytes_now;
533 if (select_sem && nbytes_now > 0)
534 release_select_sem ("raw_write");
535 /* 0 bytes returned? EAGAIN. See above. */
536 if (NT_SUCCESS (status) && nbytes == 0)
537 set_errno (EAGAIN);
539 else if (STATUS_PIPE_IS_CLOSED (status))
541 set_errno (EPIPE);
542 raise (SIGPIPE);
544 else
545 __seterrno_from_nt_status (status);
547 if (nbytes_now == 0)
548 break;
550 out:
551 CloseHandle (evt);
552 if (status == STATUS_THREAD_SIGNALED && nbytes == 0)
553 set_errno (EINTR);
554 else if (status == STATUS_THREAD_CANCELED)
555 pthread::static_cancel_self ();
556 return nbytes ?: -1;
559 void
560 fhandler_pipe::set_close_on_exec (bool val)
562 fhandler_base::set_close_on_exec (val);
563 if (read_mtx)
564 set_no_inheritance (read_mtx, val);
565 if (select_sem)
566 set_no_inheritance (select_sem, val);
567 if (query_hdl)
568 set_no_inheritance (query_hdl, val);
569 set_no_inheritance (hdl_cnt_mtx, val);
572 void
573 fhandler_pipe::fixup_after_fork (HANDLE parent)
575 fork_fixup (parent, hdl_cnt_mtx, "hdl_cnt_mtx");
576 WaitForSingleObject (hdl_cnt_mtx, INFINITE);
577 if (read_mtx)
578 fork_fixup (parent, read_mtx, "read_mtx");
579 if (select_sem)
580 fork_fixup (parent, select_sem, "select_sem");
581 if (query_hdl)
582 fork_fixup (parent, query_hdl, "query_hdl");
583 if (query_hdl_close_req_evt)
584 fork_fixup (parent, query_hdl_close_req_evt, "query_hdl_close_req_evt");
586 fhandler_base::fixup_after_fork (parent);
587 ReleaseMutex (hdl_cnt_mtx);
591 fhandler_pipe::dup (fhandler_base *child, int flags)
593 fhandler_pipe *ftp = (fhandler_pipe *) child;
594 ftp->set_popen_pid (0);
596 int res = 0;
597 WaitForSingleObject (hdl_cnt_mtx, INFINITE);
598 if (fhandler_base::dup (child, flags))
599 res = -1;
600 else if (read_mtx &&
601 !DuplicateHandle (GetCurrentProcess (), read_mtx,
602 GetCurrentProcess (), &ftp->read_mtx,
603 0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
605 __seterrno ();
606 ftp->close ();
607 res = -1;
609 else if (select_sem &&
610 !DuplicateHandle (GetCurrentProcess (), select_sem,
611 GetCurrentProcess (), &ftp->select_sem,
612 0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
614 __seterrno ();
615 ftp->close ();
616 res = -1;
618 else if (query_hdl &&
619 !DuplicateHandle (GetCurrentProcess (), query_hdl,
620 GetCurrentProcess (), &ftp->query_hdl,
621 0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
623 __seterrno ();
624 ftp->close ();
625 res = -1;
627 else if (!DuplicateHandle (GetCurrentProcess (), hdl_cnt_mtx,
628 GetCurrentProcess (), &ftp->hdl_cnt_mtx,
629 0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
631 __seterrno ();
632 ftp->close ();
633 res = -1;
635 else if (query_hdl_close_req_evt &&
636 !DuplicateHandle (GetCurrentProcess (), query_hdl_close_req_evt,
637 GetCurrentProcess (),
638 &ftp->query_hdl_close_req_evt,
639 0, !(flags & O_CLOEXEC), DUPLICATE_SAME_ACCESS))
641 __seterrno ();
642 ftp->close ();
643 res = -1;
645 ReleaseMutex (hdl_cnt_mtx);
647 debug_printf ("res %d", res);
648 return res;
652 fhandler_pipe::close ()
654 if (select_sem)
656 release_select_sem ("close");
657 CloseHandle (select_sem);
659 if (read_mtx)
660 CloseHandle (read_mtx);
661 WaitForSingleObject (hdl_cnt_mtx, INFINITE);
662 if (query_hdl)
663 CloseHandle (query_hdl);
664 if (query_hdl_close_req_evt)
665 CloseHandle (query_hdl_close_req_evt);
666 int ret = fhandler_base::close ();
667 ReleaseMutex (hdl_cnt_mtx);
668 CloseHandle (hdl_cnt_mtx);
669 if (query_hdl_proc)
670 CloseHandle (query_hdl_proc);
671 return ret;
674 #define PIPE_INTRO "\\\\.\\pipe\\cygwin-"
676 /* Create a pipe, and return handles to the read and write ends,
677 just like CreatePipe, but ensure that the write end permits
678 FILE_READ_ATTRIBUTES access, on later versions of win32 where
679 this is supported. This access is needed by NtQueryInformationFile,
680 which is used to implement select and nonblocking writes.
681 Note that the return value is either 0 or GetLastError,
682 unlike CreatePipe, which returns a bool for success or failure. */
683 DWORD
684 fhandler_pipe::create (LPSECURITY_ATTRIBUTES sa_ptr, PHANDLE r, PHANDLE w,
685 DWORD psize, const char *name, DWORD open_mode,
686 int64_t *unique_id)
688 /* Default to error. */
689 if (r)
690 *r = NULL;
691 if (w)
692 *w = NULL;
694 /* Ensure that there is enough pipe buffer space for atomic writes. */
695 if (!psize)
696 psize = DEFAULT_PIPEBUFSIZE;
698 char pipename[MAX_PATH];
699 size_t len = __small_sprintf (pipename, PIPE_INTRO "%S-",
700 &cygheap->installation_key);
701 DWORD pipe_mode = PIPE_READMODE_BYTE | PIPE_REJECT_REMOTE_CLIENTS;
702 if (!name)
703 pipe_mode |= pipe_byte ? PIPE_TYPE_BYTE : PIPE_TYPE_MESSAGE;
704 else
705 pipe_mode |= PIPE_TYPE_MESSAGE;
707 if (!name || (open_mode & PIPE_ADD_PID))
709 len += __small_sprintf (pipename + len, "%u-", GetCurrentProcessId ());
710 open_mode &= ~PIPE_ADD_PID;
713 if (name)
714 len += __small_sprintf (pipename + len, "%s", name);
716 open_mode |= PIPE_ACCESS_INBOUND | FILE_FLAG_FIRST_PIPE_INSTANCE;
718 /* Retry CreateNamedPipe as long as the pipe name is in use.
719 Retrying will probably never be necessary, but we want
720 to be as robust as possible. */
721 DWORD err = 0;
722 while (r && !*r)
724 static volatile ULONG pipe_unique_id;
725 if (!name)
727 LONG id = InterlockedIncrement ((LONG *) &pipe_unique_id);
728 __small_sprintf (pipename + len, "pipe-%p", id);
729 if (unique_id)
730 *unique_id = ((int64_t) id << 32 | GetCurrentProcessId ());
733 debug_printf ("name %s, size %u, mode %s", pipename, psize,
734 (pipe_mode & PIPE_TYPE_MESSAGE)
735 ? "PIPE_TYPE_MESSAGE" : "PIPE_TYPE_BYTE");
737 /* Use CreateNamedPipe instead of CreatePipe, because the latter
738 returns a write handle that does not permit FILE_READ_ATTRIBUTES
739 access, on versions of win32 earlier than WinXP SP2.
740 CreatePipe also stupidly creates a full duplex pipe, which is
741 a waste, since only a single direction is actually used.
742 It's important to only allow a single instance, to ensure that
743 the pipe was not created earlier by some other process, even if
744 the pid has been reused.
746 Note that the write side of the pipe is opened as PIPE_TYPE_MESSAGE.
747 This *seems* to more closely mimic Linux pipe behavior and is
748 definitely required for pty handling since fhandler_pty_master
749 writes to the pipe in chunks, terminated by newline when CANON mode
750 is specified. */
751 *r = CreateNamedPipe (pipename, open_mode, pipe_mode, 1, psize,
752 psize, NMPWAIT_USE_DEFAULT_WAIT, sa_ptr);
754 if (*r != INVALID_HANDLE_VALUE)
756 debug_printf ("pipe read handle %p", *r);
757 err = 0;
758 break;
761 err = GetLastError ();
762 switch (err)
764 case ERROR_PIPE_BUSY:
765 /* The pipe is already open with compatible parameters.
766 Pick a new name and retry. */
767 debug_printf ("pipe busy", !name ? ", retrying" : "");
768 if (!name)
769 *r = NULL;
770 break;
771 case ERROR_ACCESS_DENIED:
772 /* The pipe is already open with incompatible parameters.
773 Pick a new name and retry. */
774 debug_printf ("pipe access denied%s", !name ? ", retrying" : "");
775 if (!name)
776 *r = NULL;
777 break;
778 default:
780 err = GetLastError ();
781 debug_printf ("failed, %E");
786 if (err)
788 *r = NULL;
789 return err;
792 if (!w)
793 debug_printf ("pipe write handle NULL");
794 else
796 debug_printf ("CreateFile: name %s", pipename);
798 /* Open the named pipe for writing.
799 Be sure to permit FILE_READ_ATTRIBUTES access. */
800 DWORD access = GENERIC_WRITE | FILE_READ_ATTRIBUTES;
801 if ((open_mode & PIPE_ACCESS_DUPLEX) == PIPE_ACCESS_DUPLEX)
802 access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
803 *w = CreateFile (pipename, access, 0, sa_ptr, OPEN_EXISTING,
804 open_mode & FILE_FLAG_OVERLAPPED, 0);
806 if (!*w || *w == INVALID_HANDLE_VALUE)
808 /* Failure. */
809 DWORD err = GetLastError ();
810 debug_printf ("CreateFile failed, r %p, %E", r);
811 if (r)
812 CloseHandle (*r);
813 *w = NULL;
814 return err;
817 debug_printf ("pipe write handle %p", *w);
820 /* Success. */
821 return 0;
824 inline static bool
825 is_running_as_service (void)
827 return check_token_membership (well_known_service_sid)
828 || cygheap->user.saved_sid () == well_known_system_sid;
831 /* The next version of fhandler_pipe::create used to call the previous
832 version. But the read handle created by the latter doesn't have
833 FILE_WRITE_ATTRIBUTES access unless the pipe is created with
834 PIPE_ACCESS_DUPLEX, and it doesn't seem possible to add that access
835 right. This causes set_pipe_non_blocking to fail.
837 To fix this we will define a helper function 'nt_create' that is
838 similar to the above fhandler_pipe::create but uses
839 NtCreateNamedPipeFile instead of CreateNamedPipe; this gives more
840 flexibility in setting the access rights. We will use this helper
841 function in the version of fhandler_pipe::create below, which
842 suffices for all of our uses of set_pipe_non_blocking. For
843 simplicity, nt_create will omit the 'open_mode' and 'name'
844 parameters, which aren't needed for our purposes. */
846 static int nt_create (LPSECURITY_ATTRIBUTES, HANDLE &, HANDLE &, DWORD,
847 int64_t *);
850 fhandler_pipe::create (fhandler_pipe *fhs[2], unsigned psize, int mode)
852 HANDLE r, w;
853 SECURITY_ATTRIBUTES *sa = sec_none_cloexec (mode);
854 int res = -1;
855 int64_t unique_id;
857 int ret = nt_create (sa, r, w, psize, &unique_id);
858 if (ret)
860 __seterrno_from_win_error (ret);
861 goto out;
863 if ((fhs[0] = (fhandler_pipe *) build_fh_dev (*piper_dev)) == NULL)
864 goto err_close_rw_handle;
865 if ((fhs[1] = (fhandler_pipe *) build_fh_dev (*pipew_dev)) == NULL)
866 goto err_delete_fhs0;
867 mode |= mode & O_TEXT ?: O_BINARY;
868 fhs[0]->init (r, FILE_CREATE_PIPE_INSTANCE | GENERIC_READ, mode, unique_id);
869 fhs[1]->init (w, FILE_CREATE_PIPE_INSTANCE | GENERIC_WRITE, mode, unique_id);
871 /* For the read side of the pipe, add a mutex. See raw_read for the
872 usage. */
873 fhs[0]->read_mtx = CreateMutexW (sa, FALSE, NULL);
874 if (!fhs[0]->read_mtx)
875 goto err_delete_fhs1;
877 fhs[0]->select_sem = CreateSemaphore (sa, 0, INT32_MAX, NULL);
878 if (!fhs[0]->select_sem)
879 goto err_close_read_mtx;
880 if (!DuplicateHandle (GetCurrentProcess (), fhs[0]->select_sem,
881 GetCurrentProcess (), &fhs[1]->select_sem,
882 0, sa->bInheritHandle, DUPLICATE_SAME_ACCESS))
883 goto err_close_select_sem0;
885 if (is_running_as_service () &&
886 !DuplicateHandle (GetCurrentProcess (), r,
887 GetCurrentProcess (), &fhs[1]->query_hdl,
888 FILE_READ_DATA, sa->bInheritHandle, 0))
889 goto err_close_select_sem1;
891 fhs[0]->hdl_cnt_mtx = CreateMutexW (sa, FALSE, NULL);
892 if (!fhs[0]->hdl_cnt_mtx)
893 goto err_close_query_hdl;
894 if (!DuplicateHandle (GetCurrentProcess (), fhs[0]->hdl_cnt_mtx,
895 GetCurrentProcess (), &fhs[1]->hdl_cnt_mtx,
896 0, sa->bInheritHandle, DUPLICATE_SAME_ACCESS))
897 goto err_close_hdl_cnt_mtx0;
899 if (fhs[1]->query_hdl)
901 fhs[1]->query_hdl_close_req_evt = CreateEvent (sa, TRUE, FALSE, NULL);
902 if (!fhs[1]->query_hdl_close_req_evt)
903 goto err_close_hdl_cnt_mtx1;
906 res = 0;
907 goto out;
909 err_close_hdl_cnt_mtx1:
910 CloseHandle (fhs[1]->hdl_cnt_mtx);
911 err_close_hdl_cnt_mtx0:
912 CloseHandle (fhs[0]->hdl_cnt_mtx);
913 err_close_query_hdl:
914 if (fhs[1]->query_hdl)
915 CloseHandle (fhs[1]->query_hdl);
916 err_close_select_sem1:
917 CloseHandle (fhs[1]->select_sem);
918 err_close_select_sem0:
919 CloseHandle (fhs[0]->select_sem);
920 err_close_read_mtx:
921 CloseHandle (fhs[0]->read_mtx);
922 err_delete_fhs1:
923 delete fhs[1];
924 err_delete_fhs0:
925 delete fhs[0];
926 err_close_rw_handle:
927 NtClose (r);
928 NtClose (w);
929 out:
930 debug_printf ("%R = pipe([%p, %p], %d, %y)",
931 res, fhs[0], fhs[1], psize, mode);
932 return res;
935 static int
936 nt_create (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE &r, HANDLE &w,
937 DWORD psize, int64_t *unique_id)
939 NTSTATUS status;
940 HANDLE npfsh;
941 ACCESS_MASK access;
942 OBJECT_ATTRIBUTES attr;
943 IO_STATUS_BLOCK io;
944 LARGE_INTEGER timeout;
946 /* Default to error. */
947 r = NULL;
948 w = NULL;
950 status = fhandler_base::npfs_handle (npfsh);
951 if (!NT_SUCCESS (status))
953 __seterrno_from_nt_status (status);
954 return GetLastError ();
957 /* Ensure that there is enough pipe buffer space for atomic writes. */
958 if (!psize)
959 psize = DEFAULT_PIPEBUFSIZE;
961 UNICODE_STRING pipename;
962 WCHAR pipename_buf[MAX_PATH];
963 size_t len = __small_swprintf (pipename_buf, L"%S-%u-",
964 &cygheap->installation_key,
965 GetCurrentProcessId ());
967 access = GENERIC_READ | FILE_WRITE_ATTRIBUTES | SYNCHRONIZE;
968 access |= FILE_WRITE_EA; /* Add this right as a marker of cygwin read pipe */
970 ULONG pipe_type = pipe_byte ? FILE_PIPE_BYTE_STREAM_TYPE
971 : FILE_PIPE_MESSAGE_TYPE;
973 /* Retry NtCreateNamedPipeFile as long as the pipe name is in use.
974 Retrying will probably never be necessary, but we want
975 to be as robust as possible. */
976 DWORD err = 0;
977 while (!r)
979 static volatile ULONG pipe_unique_id;
980 LONG id = InterlockedIncrement ((LONG *) &pipe_unique_id);
981 __small_swprintf (pipename_buf + len, L"pipe-nt-%p", id);
982 if (unique_id)
983 *unique_id = ((int64_t) id << 32 | GetCurrentProcessId ());
985 debug_printf ("name %W, size %u, mode %s", pipename_buf, psize,
986 (pipe_type & FILE_PIPE_MESSAGE_TYPE)
987 ? "PIPE_TYPE_MESSAGE" : "PIPE_TYPE_BYTE");
989 RtlInitUnicodeString (&pipename, pipename_buf);
991 InitializeObjectAttributes (&attr, &pipename,
992 sa_ptr->bInheritHandle ? OBJ_INHERIT : 0,
993 npfsh, sa_ptr->lpSecurityDescriptor);
995 timeout.QuadPart = -500000;
996 /* Set FILE_SYNCHRONOUS_IO_NONALERT flag so that native
997 C# programs work with cygwin pipe. */
998 status = NtCreateNamedPipeFile (&r, access, &attr, &io,
999 FILE_SHARE_READ | FILE_SHARE_WRITE,
1000 FILE_CREATE,
1001 FILE_SYNCHRONOUS_IO_NONALERT, pipe_type,
1002 FILE_PIPE_BYTE_STREAM_MODE,
1003 0, 1, psize, psize, &timeout);
1005 if (NT_SUCCESS (status))
1007 debug_printf ("pipe read handle %p", r);
1008 err = 0;
1009 break;
1012 switch (status)
1014 case STATUS_PIPE_BUSY:
1015 case STATUS_INSTANCE_NOT_AVAILABLE:
1016 case STATUS_PIPE_NOT_AVAILABLE:
1017 /* The pipe is already open with compatible parameters.
1018 Pick a new name and retry. */
1019 debug_printf ("pipe busy, retrying");
1020 r = NULL;
1021 break;
1022 case STATUS_ACCESS_DENIED:
1023 /* The pipe is already open with incompatible parameters.
1024 Pick a new name and retry. */
1025 debug_printf ("pipe access denied, retrying");
1026 r = NULL;
1027 break;
1028 default:
1030 __seterrno_from_nt_status (status);
1031 err = GetLastError ();
1032 debug_printf ("failed, %E");
1033 r = NULL;
1038 if (err)
1040 r = NULL;
1041 return err;
1044 debug_printf ("NtOpenFile: name %S", &pipename);
1046 access = GENERIC_WRITE | FILE_READ_ATTRIBUTES | SYNCHRONIZE;
1047 status = NtOpenFile (&w, access, &attr, &io, 0, 0);
1048 if (!NT_SUCCESS (status))
1050 DWORD err = GetLastError ();
1051 debug_printf ("NtOpenFile failed, r %p, %E", r);
1052 if (r)
1053 NtClose (r);
1054 w = NULL;
1055 return err;
1058 /* Success. */
1059 return 0;
1062 /* Called by dtable::init_std_file_from_handle for stdio handles
1063 inherited from non-Cygwin processes. */
1064 void
1065 fhandler_pipe::set_pipe_buf_size ()
1067 NTSTATUS status;
1068 IO_STATUS_BLOCK io;
1069 FILE_PIPE_LOCAL_INFORMATION fpli;
1071 status = NtQueryInformationFile (get_handle (), &io, &fpli, sizeof fpli,
1072 FilePipeLocalInformation);
1073 if (NT_SUCCESS (status))
1074 pipe_buf_size = fpli.InboundQuota;
1078 fhandler_pipe::ioctl (unsigned int cmd, void *p)
1080 int n;
1082 switch (cmd)
1084 case FIONREAD:
1085 if (get_device () == FH_PIPEW)
1087 set_errno (EINVAL);
1088 return -1;
1090 if (!PeekNamedPipe (get_handle (), NULL, 0, NULL, (DWORD *) &n, NULL))
1092 __seterrno ();
1093 return -1;
1095 break;
1096 default:
1097 return fhandler_base::ioctl (cmd, p);
1098 break;
1100 *(int *) p = n;
1101 return 0;
1105 fhandler_pipe::fcntl (int cmd, intptr_t arg)
1107 if (cmd != F_SETFL)
1108 return fhandler_base::fcntl (cmd, arg);
1110 const bool was_nonblocking = is_nonblocking ();
1111 int res = fhandler_base::fcntl (cmd, arg);
1112 const bool now_nonblocking = is_nonblocking ();
1113 /* Do not set blocking mode for read pipe to allow signal handling
1114 even with FILE_SYNCHRONOUS_IO_NONALERT. */
1115 if (now_nonblocking != was_nonblocking && get_device () != FH_PIPER)
1116 set_pipe_non_blocking (now_nonblocking);
1117 return res;
1121 fhandler_pipe::fstat (struct stat *buf)
1123 int ret = fhandler_base::fstat (buf);
1124 if (!ret)
1126 buf->st_dev = FH_PIPE;
1127 if (!(buf->st_ino = get_plain_ino ()))
1128 sscanf (get_name (), "/proc/%*d/fd/pipe:[%llu]",
1129 (long long *) &buf->st_ino);
1131 return ret;
1135 fhandler_pipe::fstatvfs (struct statvfs *sfs)
1137 set_errno (EBADF);
1138 return -1;
1141 HANDLE
1142 fhandler_pipe::temporary_query_hdl ()
1144 if (get_dev () != FH_PIPEW)
1145 return NULL;
1147 ULONG len;
1148 NTSTATUS status;
1149 tmp_pathbuf tp;
1150 OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION *) tp.w_get ();
1152 /* Try process handle opened and pipe handle value cached first
1153 in order to reduce overhead. */
1154 if (query_hdl_proc && query_hdl_value)
1156 HANDLE h;
1157 if (!DuplicateHandle (query_hdl_proc, query_hdl_value,
1158 GetCurrentProcess (), &h, FILE_READ_DATA, 0, 0))
1159 goto cache_err;
1160 /* Check name */
1161 status = NtQueryObject (h, ObjectNameInformation, ntfn, 65536, &len);
1162 if (!NT_SUCCESS (status) || !ntfn->Name.Buffer)
1163 goto hdl_err;
1164 ntfn->Name.Buffer[ntfn->Name.Length / sizeof (WCHAR)] = L'\0';
1165 uint64_t key;
1166 DWORD pid;
1167 LONG id;
1168 if (swscanf (ntfn->Name.Buffer,
1169 L"\\Device\\NamedPipe\\%llx-%u-pipe-nt-0x%x",
1170 &key, &pid, &id) == 3 &&
1171 key == pipename_key && pid == pipename_pid && id == pipename_id)
1172 return h;
1173 hdl_err:
1174 CloseHandle (h);
1175 cache_err:
1176 CloseHandle (query_hdl_proc);
1177 query_hdl_proc = NULL;
1178 query_hdl_value = NULL;
1181 status = NtQueryObject (get_handle (), ObjectNameInformation, ntfn,
1182 65536, &len);
1183 if (!NT_SUCCESS (status) || !ntfn->Name.Buffer)
1184 return NULL; /* Non cygwin pipe? */
1185 WCHAR name[MAX_PATH];
1186 int namelen = min (ntfn->Name.Length / sizeof (WCHAR), MAX_PATH-1);
1187 memcpy (name, ntfn->Name.Buffer, namelen * sizeof (WCHAR));
1188 name[namelen] = L'\0';
1189 if (swscanf (name, L"\\Device\\NamedPipe\\%llx-%u-pipe-nt-0x%x",
1190 &pipename_key, &pipename_pid, &pipename_id) != 3)
1191 return NULL; /* Non cygwin pipe? */
1193 return get_query_hdl_per_process (name, ntfn); /* Since Win8 */
1196 HANDLE
1197 fhandler_pipe::get_query_hdl_per_process (WCHAR *name,
1198 OBJECT_NAME_INFORMATION *ntfn)
1200 NTSTATUS status;
1201 ULONG len;
1202 DWORD n_process = 256;
1203 PSYSTEM_PROCESS_INFORMATION spi;
1205 { /* Enumerate processes */
1206 DWORD nbytes = n_process * sizeof (SYSTEM_PROCESS_INFORMATION);
1207 spi = (PSYSTEM_PROCESS_INFORMATION) HeapAlloc (GetProcessHeap (),
1208 0, nbytes);
1209 if (!spi)
1210 return NULL;
1211 status = NtQuerySystemInformation (SystemProcessInformation,
1212 spi, nbytes, &len);
1213 if (NT_SUCCESS (status))
1214 break;
1215 HeapFree (GetProcessHeap (), 0, spi);
1216 n_process *= 2;
1218 while (n_process < (1L<<20) && status == STATUS_INFO_LENGTH_MISMATCH);
1219 if (!NT_SUCCESS (status))
1220 return NULL;
1222 /* In most cases, it is faster to check the processes in reverse order.
1223 To do this, store PIDs into an array. */
1224 DWORD *proc_pids = (DWORD *) HeapAlloc (GetProcessHeap (), 0,
1225 n_process * sizeof (DWORD));
1226 if (!proc_pids)
1228 HeapFree (GetProcessHeap (), 0, spi);
1229 return NULL;
1231 PSYSTEM_PROCESS_INFORMATION p = spi;
1232 n_process = 0;
1233 while (true)
1235 proc_pids[n_process++] = (DWORD)(intptr_t) p->UniqueProcessId;
1236 if (!p->NextEntryOffset)
1237 break;
1238 p = (PSYSTEM_PROCESS_INFORMATION) ((char *) p + p->NextEntryOffset);
1240 HeapFree (GetProcessHeap (), 0, spi);
1242 for (LONG i = (LONG) n_process - 1; i >= 0; i--)
1244 HANDLE proc = OpenProcess (PROCESS_DUP_HANDLE
1245 | PROCESS_QUERY_INFORMATION,
1246 0, proc_pids[i]);
1247 if (!proc)
1248 continue;
1250 /* Retrieve process handles */
1251 DWORD n_handle = 256;
1252 PPROCESS_HANDLE_SNAPSHOT_INFORMATION phi;
1255 DWORD nbytes = 2 * sizeof (ULONG_PTR) +
1256 n_handle * sizeof (PROCESS_HANDLE_TABLE_ENTRY_INFO);
1257 phi = (PPROCESS_HANDLE_SNAPSHOT_INFORMATION)
1258 HeapAlloc (GetProcessHeap (), 0, nbytes);
1259 if (!phi)
1260 goto close_proc;
1261 /* NtQueryInformationProcess can return STATUS_SUCCESS with
1262 invalid handle data for certain processes. See
1263 https://github.com/processhacker/processhacker/blob/05f5e9fa477dcaa1709d9518170d18e1b3b8330d/phlib/native.c#L5754.
1264 We need to ensure that NumberOfHandles is zero in this
1265 case to avoid a crash in the for loop below. */
1266 phi->NumberOfHandles = 0;
1267 status = NtQueryInformationProcess (proc, ProcessHandleInformation,
1268 phi, nbytes, &len);
1269 if (NT_SUCCESS (status))
1270 break;
1271 HeapFree (GetProcessHeap (), 0, phi);
1272 n_handle *= 2;
1274 while (n_handle < (1L<<20) && status == STATUS_INFO_LENGTH_MISMATCH);
1275 if (!NT_SUCCESS (status))
1276 goto close_proc;
1278 /* Sanity check in case Microsoft changes
1279 NtQueryInformationProcess and the initialization of
1280 NumberOfHandles above is no longer sufficient. */
1281 assert (phi->NumberOfHandles <= n_handle);
1282 for (ULONG j = 0; j < phi->NumberOfHandles; j++)
1284 /* Check for the peculiarity of cygwin read pipe */
1285 const ULONG access = FILE_READ_DATA | FILE_READ_EA
1286 | FILE_WRITE_EA /* marker */
1287 | FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES
1288 | READ_CONTROL | SYNCHRONIZE;
1289 if (phi->Handles[j].GrantedAccess != access)
1290 continue;
1292 /* Retrieve handle */
1293 HANDLE h = (HANDLE)(intptr_t) phi->Handles[j].HandleValue;
1294 BOOL res = DuplicateHandle (proc, h, GetCurrentProcess (), &h,
1295 FILE_READ_DATA, 0, 0);
1296 if (!res)
1297 continue;
1299 /* Check object name */
1300 status = NtQueryObject (h, ObjectNameInformation,
1301 ntfn, 65536, &len);
1302 if (!NT_SUCCESS (status) || !ntfn->Name.Buffer)
1303 goto close_handle;
1304 ntfn->Name.Buffer[ntfn->Name.Length / sizeof (WCHAR)] = L'\0';
1305 if (wcscmp (name, ntfn->Name.Buffer) == 0)
1307 query_hdl_proc = proc;
1308 query_hdl_value = (HANDLE)(intptr_t) phi->Handles[j].HandleValue;
1309 HeapFree (GetProcessHeap (), 0, phi);
1310 HeapFree (GetProcessHeap (), 0, proc_pids);
1311 return h;
1313 close_handle:
1314 CloseHandle (h);
1316 HeapFree (GetProcessHeap (), 0, phi);
1317 close_proc:
1318 CloseHandle (proc);
1320 HeapFree (GetProcessHeap (), 0, proc_pids);
1321 return NULL;