Cygwin: pinfo: use stpcpy where appropriate
[newlib-cygwin.git] / winsup / cygwin / dtable.cc
blob9508f3e0bb39ba72a40a825692b9983452232004
1 /* dtable.cc: file descriptor support.
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 #define __INSIDE_CYGWIN_NET__
11 #include "winsup.h"
12 #include <stdlib.h>
13 #include <stdio.h>
14 #include <unistd.h>
15 #include <wchar.h>
17 #define USE_SYS_TYPES_FD_SET
18 #include <winsock.h>
19 #include "pinfo.h"
20 #include "cygerrno.h"
21 #include "perprocess.h"
22 #include "path.h"
23 #include "fhandler.h"
24 #include "select.h"
25 #include "dtable.h"
26 #include "cygheap.h"
27 #include "tls_pbuf.h"
28 #include "ntdll.h"
29 #include "shared_info.h"
31 static const DWORD std_consts[] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE,
32 STD_ERROR_HANDLE};
34 static bool handle_to_fn (HANDLE, char *);
36 #define WCLEN(x) ((sizeof (x) / sizeof (WCHAR)) - 1)
37 static const char unknown_file[] = "some disk file";
38 static const WCHAR DEV_NULL[] = L"\\Device\\Null";
39 static const WCHAR DEV_SOCKET[] = L"\\Device\\Afd";
41 static const WCHAR DEVICE_PREFIX[] = L"\\device\\";
42 static const size_t DEVICE_PREFIX_LEN WCLEN (DEVICE_PREFIX);
44 static const WCHAR DEV_NAMED_PIPE[] = L"\\Device\\NamedPipe\\";
45 static const size_t DEV_NAMED_PIPE_LEN = WCLEN (DEV_NAMED_PIPE);
47 static const WCHAR DEV_REMOTE[] = L"\\Device\\LanmanRedirector\\";
48 static const size_t DEV_REMOTE_LEN = WCLEN (DEV_REMOTE);
50 static const WCHAR DEV_REMOTE1[] = L"\\Device\\WinDfs\\Root\\";
51 static const size_t DEV_REMOTE1_LEN = WCLEN (DEV_REMOTE1);
53 /* Set aside space for the table of fds */
54 void
55 dtable_init ()
57 if (!cygheap->fdtab.size)
58 cygheap->fdtab.extend (NOFILE_INCR, 0);
61 void
62 set_std_handle (int fd)
64 fhandler_base *fh = cygheap->fdtab[fd];
65 if (fd == 0)
66 SetStdHandle (std_consts[fd], fh ? fh->get_handle () : NULL);
67 else if (fd <= 2)
68 SetStdHandle (std_consts[fd], fh ? fh->get_output_handle () : NULL);
71 int
72 dtable::extend (size_t howmuch, size_t min)
74 size_t new_size = size + howmuch;
75 fhandler_base **newfds;
77 if (new_size <= OPEN_MAX)
78 /* ok */;
79 else if (size < OPEN_MAX && min < OPEN_MAX)
80 new_size = OPEN_MAX;
81 else
83 set_errno (EMFILE);
84 return 0;
87 /* Try to allocate more space for fd table. We can't call realloc ()
88 here to preserve old table if memory allocation fails */
90 if (!(newfds = (fhandler_base **) ccalloc (HEAP_ARGV, new_size, sizeof newfds[0])))
92 debug_printf ("calloc failed");
93 set_errno (ENOMEM);
94 return 0;
96 if (fds)
98 memcpy (newfds, fds, size * sizeof (fds[0]));
99 cfree (fds);
102 size = new_size;
103 fds = newfds;
104 debug_printf ("size %ld, fds %p", size, fds);
105 return 1;
108 void
109 dtable::get_debugger_info ()
111 extern bool jit_debug;
112 if (!jit_debug && being_debugged ())
114 char std[3][sizeof ("/dev/ptyNNNN")];
115 std[0][0] = std[1][0] = std [2][0] = '\0';
116 char buf[sizeof ("cYgstd %x") + 64];
117 sprintf (buf, "cYgstd %p %zx %x", &std, sizeof (std[0]), 3);
118 OutputDebugString (buf);
119 for (int i = 0; i < 3; i++)
120 if (std[i][0])
122 HANDLE h = GetStdHandle (std_consts[i]);
123 fhandler_base *fh = build_fh_name (std[i]);
124 if (!fh)
125 continue;
126 fds[i] = fh;
127 if (!fh->open ((i ? (i == 2 ? O_RDWR : O_WRONLY) : O_RDONLY)
128 | O_BINARY, 0777))
129 release (i);
130 else
132 CloseHandle (h);
133 /* Copy to Windows' idea of a standard handle, otherwise
134 we have invalid standard handles when calling Windows
135 functions (small_printf and strace might suffer, too). */
136 SetStdHandle (std_consts[i], i ? fh->get_output_handle ()
137 : fh->get_handle ());
143 /* Initialize the file descriptor/handle mapping table.
144 This function should only be called when a cygwin function is invoked
145 by a non-cygwin function, i.e., it should only happen very rarely. */
147 void
148 dtable::stdio_init ()
150 if (myself->cygstarted || ISSTATE (myself, PID_CYGPARENT))
152 tty_min *t = cygwin_shared->tty.get_cttyp ();
153 if (t && t->is_console)
154 init_console_handler (true);
155 return;
158 HANDLE in = GetStdHandle (STD_INPUT_HANDLE);
159 HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE);
160 HANDLE err = GetStdHandle (STD_ERROR_HANDLE);
162 init_std_file_from_handle (0, in);
164 /* STD_ERROR_HANDLE has been observed to be the same as
165 STD_OUTPUT_HANDLE. We need separate handles (e.g. using pipes
166 to pass data from child to parent). */
167 /* CV 2008-10-17: Under debugger control, std fd's have been potentially
168 initialized in dtable::get_debugger_info (). In this case
169 init_std_file_from_handle is a no-op, so, even if out == err we don't
170 want to duplicate the handle since it will be unused. */
171 if (out == err && (!being_debugged () || not_open (2)))
173 /* Since this code is not invoked for forked tasks, we don't have
174 to worry about the close-on-exec flag here. */
175 if (!DuplicateHandle (GetCurrentProcess (), out,
176 GetCurrentProcess (), &err,
177 0, TRUE, DUPLICATE_SAME_ACCESS))
179 /* If that fails, do this as a fall back. */
180 err = out;
181 system_printf ("couldn't make stderr distinct from stdout, %E");
185 init_std_file_from_handle (1, out);
186 init_std_file_from_handle (2, err);
189 const int dtable::initial_archetype_size;
191 fhandler_base *
192 dtable::find_archetype (device& dev)
194 for (unsigned i = 0; i < farchetype; i++)
195 if (archetypes[i]->get_device () == (dev_t) dev)
196 return archetypes[i];
197 return NULL;
200 fhandler_base **
201 dtable::add_archetype ()
203 if (farchetype++ >= narchetypes)
204 archetypes = (fhandler_base **) crealloc_abort (archetypes, (narchetypes += initial_archetype_size) * sizeof archetypes[0]);
205 return archetypes + farchetype - 1;
208 void
209 dtable::delete_archetype (fhandler_base *fh)
211 for (unsigned i = 0; i < farchetype; i++)
212 if (fh == archetypes[i])
214 debug_printf ("deleting element %d for %s(%d/%d)", i, fh->get_name (),
215 fh->dev ().get_major (), fh->dev ().get_minor ());
216 if (i < --farchetype)
217 archetypes[i] = archetypes[farchetype];
218 break;
221 delete fh;
225 dtable::find_unused_handle (size_t start)
227 /* When extending, try to allocate a NOFILE_INCR chunk
228 following the empty fd. */
229 size_t extendby = NOFILE_INCR + ((start >= size) ? 1 + start - size : 0);
231 /* This do loop should only ever execute twice. */
232 int res = -1;
235 for (size_t i = start; i < size; i++)
236 if (fds[i] == NULL)
238 res = (int) i;
239 goto out;
242 while (extend (extendby, start));
243 out:
244 return res;
247 void
248 dtable::release (int fd)
250 if (fds[fd]->need_fixup_before ())
251 dec_need_fixup_before ();
252 fds[fd]->dec_refcnt ();
253 fds[fd] = NULL;
254 if (fd <= 2)
255 set_std_handle (fd);
258 extern "C" int
259 cygwin_attach_handle_to_fd (char *name, int fd, HANDLE handle, mode_t bin,
260 DWORD myaccess)
262 cygheap->fdtab.lock ();
263 if (fd == -1)
264 fd = cygheap->fdtab.find_unused_handle ();
265 fhandler_base *fh = build_fh_name (name);
266 if (!fh)
267 fd = -1;
268 else
270 cygheap->fdtab[fd] = fh;
271 cygheap->fdtab[fd]->inc_refcnt ();
272 fh->init (handle, myaccess, bin ?: fh->pc_binmode ());
274 cygheap->fdtab.unlock ();
275 return fd;
278 void
279 dtable::init_std_file_from_handle (int fd, HANDLE handle)
281 tmp_pathbuf tp;
282 CONSOLE_SCREEN_BUFFER_INFO buf;
283 DCB dcb;
284 unsigned bin = O_BINARY;
285 device dev;
287 first_fd_for_open = 0;
289 if (!not_open (fd))
290 return;
292 SetLastError (0);
293 DWORD access = 0;
294 DWORD ft = GetFileType (handle);
295 char *name = tp.c_get ();
296 name[0] = '\0';
297 if (ft == FILE_TYPE_UNKNOWN && GetLastError () == ERROR_INVALID_HANDLE)
298 /* can't figure out what this is */;
299 else if (ft == FILE_TYPE_PIPE)
301 int rcv = 0, len = sizeof (int);
303 if (handle_to_fn (handle, name))
304 dev.parse (name);
305 else if (strcmp (name, ":sock:") == 0
306 /* NtQueryObject returns an error when called on an LSP socket
307 handle. fhandler_socket::set_socket_handle tries to fetch
308 the underlying base socket, but this might fail. */
309 || (strcmp (name, unknown_file) == 0
310 && !::getsockopt ((SOCKET) handle, SOL_SOCKET, SO_RCVBUF,
311 (char *) &rcv, &len)))
313 /* socket */
314 dev = *af_inet_dev;
315 name[0] = '\0';
317 else if (fd == 0)
318 dev = *piper_dev;
319 else
320 dev = *pipew_dev;
322 else if (GetConsoleScreenBufferInfo (handle, &buf)
323 || GetNumberOfConsoleInputEvents (handle, (DWORD *) &buf))
325 /* Console I/O */
326 if (CTTY_IS_VALID (myself->ctty))
327 dev.parse (myself->ctty);
328 else
330 dev.parse (FH_CONSOLE);
331 CloseHandle (handle);
332 handle = INVALID_HANDLE_VALUE;
335 else if (GetCommState (handle, &dcb))
336 /* FIXME: Not right - assumes ttyS0 */
337 dev.parse (DEV_SERIAL_MAJOR, 0);
338 else
339 /* Try to figure it out from context - probably a disk file */
340 handle_to_fn (handle, name);
342 if (!name[0] && !dev)
343 fds[fd] = NULL;
344 else
346 fhandler_base *fh;
348 if (dev)
349 fh = build_fh_dev (dev);
350 else
351 fh = build_fh_name (name);
353 if (!fh)
354 return;
356 if (name[0])
358 bin = fh->pc_binmode ();
359 if (!bin)
361 bin = fh->get_default_fmode (O_RDWR);
362 if (!bin && dev)
363 bin = O_BINARY;
367 IO_STATUS_BLOCK io;
368 FILE_ACCESS_INFORMATION fai;
369 int openflags = O_BINARY;
371 /* Console windows are no kernel objects up to Windows 7/2008R2, so the
372 access mask returned by NtQueryInformationFile is meaningless. CMD
373 always hands down stdin handles as R/O handles, but our tty slave
374 sides are R/W. */
375 if (fh->is_tty ())
377 openflags |= O_RDWR;
378 access |= GENERIC_READ | GENERIC_WRITE;
380 else if (!iscons_dev (dev)
381 && NT_SUCCESS (NtQueryInformationFile (handle, &io, &fai,
382 sizeof fai,
383 FileAccessInformation)))
385 if (fai.AccessFlags & FILE_WRITE_DATA)
387 openflags |= O_WRONLY;
388 access |= GENERIC_WRITE;
390 if (fai.AccessFlags & FILE_READ_DATA)
392 openflags |= openflags & O_WRONLY ? O_RDWR : O_RDONLY;
393 access |= GENERIC_READ;
396 else if (fd == 0)
398 openflags |= O_RDONLY;
399 access |= GENERIC_READ;
401 else
403 openflags |= O_WRONLY;
404 access |= GENERIC_WRITE; /* Should be rdwr for stderr but not sure that's
405 possible for some versions of handles */
407 if (!fh->init (handle, access, bin))
408 api_fatal ("couldn't initialize fd %d for %s", fd, fh->get_name ());
409 if (fh->ispipe ())
411 fhandler_pipe *fhp = (fhandler_pipe *) fh;
412 fhp->set_pipe_buf_size ();
413 /* Set read pipe always to nonblocking */
414 fhp->set_pipe_non_blocking (fhp->get_device () == FH_PIPER ?
415 true : fhp->is_nonblocking ());
418 if (!fh->open_setup (openflags))
419 api_fatal ("open_setup failed, %E");
420 fh->usecount = 0;
421 cygheap->fdtab[fd] = fh;
422 cygheap->fdtab[fd]->inc_refcnt ();
423 set_std_handle (fd);
424 paranoid_printf ("fd %d, handle %p", fd, handle);
425 fh->post_open_setup (fd);
429 #define cnew(name, ...) \
430 ({ \
431 void* ptr = (void*) ccalloc (HEAP_FHANDLER, 1, sizeof (name)); \
432 ptr ? new (ptr) name (__VA_ARGS__) : NULL; \
435 #define cnew_no_ctor(name, ...) \
436 ({ \
437 void* ptr = (void*) ccalloc (HEAP_FHANDLER, 1, sizeof (name)); \
438 ptr ? new (ptr) name (ptr) : NULL; \
441 fhandler_base *
442 build_fh_name (const char *name, unsigned opt, suffix_info *si)
444 path_conv pc (name, opt | PC_NULLEMPTY | PC_POSIX, si);
445 if (pc.error)
447 fhandler_base *fh = cnew (fhandler_nodevice);
448 if (fh)
449 fh->set_error (pc.error);
450 set_errno (fh ? pc.error : EMFILE);
451 return fh;
454 return build_fh_pc (pc);
457 fhandler_base *
458 build_fh_dev (const device& dev, const char *unix_name)
460 path_conv pc (dev);
461 if (unix_name)
462 pc.set_posix (unix_name);
463 else
464 pc.set_posix (dev.name ());
465 return build_fh_pc (pc);
468 #define fh_unset ((fhandler_base *) 1)
469 static device last_tty_dev;
470 #define fh_last_tty_dev ((fhandler_termios *) cygheap->fdtab.find_archetype (last_tty_dev))
472 static fhandler_base *
473 fh_alloc (path_conv& pc)
475 fhandler_base *fh = fh_unset;
476 fhandler_base *fhraw = NULL;
478 switch (pc.dev.get_major ())
480 case DEV_PTYS_MAJOR:
481 fh = cnew (fhandler_pty_slave, pc.dev.get_minor ());
482 break;
483 case DEV_PTYM_MAJOR:
484 fh = cnew (fhandler_pty_master, pc.dev.get_minor ());
485 break;
486 case DEV_FLOPPY_MAJOR:
487 case DEV_CDROM_MAJOR:
488 case DEV_SD_MAJOR:
489 case DEV_SD1_MAJOR ... DEV_SD7_MAJOR:
490 case DEV_SD_HIGHPART_START ... DEV_SD_HIGHPART_END:
491 fh = cnew (fhandler_dev_floppy);
492 break;
493 case DEV_TAPE_MAJOR:
494 fh = cnew (fhandler_dev_tape);
495 break;
496 case DEV_SERIAL_MAJOR:
497 fh = cnew (fhandler_serial);
498 break;
499 case DEV_CONS_MAJOR:
500 fh = cnew (fhandler_console, pc.dev);
501 break;
502 default:
503 switch ((dev_t) pc.dev)
505 case FH_CONSOLE:
506 case FH_CONIN:
507 case FH_CONOUT:
508 fh = cnew (fhandler_console, pc.dev);
509 break;
510 case FH_PTMX:
511 if (pc.isopen ())
512 fh = cnew (fhandler_pty_master, -1, (dev_t) pc.dev);
513 else
514 fhraw = cnew_no_ctor (fhandler_pty_master, -1);
515 break;
516 case FH_WINDOWS:
517 fh = cnew (fhandler_windows);
518 break;
519 case FH_FIFO:
520 fh = cnew (fhandler_fifo);
521 break;
522 case FH_PIPE:
523 case FH_PIPER:
524 case FH_PIPEW:
525 fh = cnew (fhandler_pipe);
526 break;
527 case FH_INET:
528 fh = cnew (fhandler_socket_inet);
529 break;
530 case FH_LOCAL:
531 fh = cnew (fhandler_socket_local);
532 break;
533 #ifdef __WITH_AF_UNIX
534 case FH_UNIX:
535 fh = cnew (fhandler_socket_unix);
536 break;
537 #endif /* __WITH_AF_UNIX */
538 case FH_FS:
539 fh = cnew (fhandler_disk_file);
540 break;
541 case FH_NULL:
542 fh = cnew (fhandler_dev_null);
543 break;
544 case FH_ZERO:
545 case FH_FULL:
546 fh = cnew (fhandler_dev_zero);
547 break;
548 case FH_RANDOM:
549 case FH_URANDOM:
550 fh = cnew (fhandler_dev_random);
551 break;
552 case FH_CLIPBOARD:
553 fh = cnew (fhandler_dev_clipboard);
554 break;
555 case FH_OSS_MIXER:
556 fh = cnew (fhandler_dev_mixer);
557 break;
558 case FH_OSS_DSP:
559 fh = cnew (fhandler_dev_dsp);
560 break;
561 case FH_PROC:
562 fh = cnew (fhandler_proc);
563 break;
564 case FH_REGISTRY:
565 fh = cnew (fhandler_registry);
566 break;
567 case FH_PROCESS:
568 fh = cnew (fhandler_process);
569 break;
570 case FH_PROCESSFD:
571 fh = cnew (fhandler_process_fd);
572 break;
573 case FH_PROCNET:
574 fh = cnew (fhandler_procnet);
575 break;
576 case FH_PROCSYS:
577 fh = cnew (fhandler_procsys);
578 break;
579 case FH_PROCSYSVIPC:
580 fh = cnew (fhandler_procsysvipc);
581 break;
582 case FH_NETDRIVE:
583 fh = cnew (fhandler_netdrive);
584 break;
585 case FH_DEV:
586 fh = cnew (fhandler_dev);
587 break;
588 case FH_DEV_DISK:
589 fh = cnew (fhandler_dev_disk);
590 break;
591 case FH_DEV_FD:
592 fh = cnew (fhandler_dev_fd);
593 break;
594 case FH_CYGDRIVE:
595 fh = cnew (fhandler_cygdrive);
596 break;
597 case FH_SIGNALFD:
598 fh = cnew (fhandler_signalfd);
599 break;
600 case FH_TIMERFD:
601 fh = cnew (fhandler_timerfd);
602 break;
603 case FH_MQUEUE:
604 fh = cnew (fhandler_mqueue);
605 break;
606 case FH_TTY:
607 if (!pc.isopen ())
609 if (CTTY_IS_VALID (myself->ctty))
611 if (iscons_dev (myself->ctty))
612 fhraw = cnew_no_ctor (fhandler_console, -1);
613 else
614 fhraw = cnew_no_ctor (fhandler_pty_slave, -1);
616 debug_printf ("not called from open for /dev/tty");
618 else if (!CTTY_IS_VALID (myself->ctty) && last_tty_dev
619 && !myself->set_ctty (fh_last_tty_dev, 0))
620 debug_printf ("no /dev/tty assigned");
621 else if (CTTY_IS_VALID (myself->ctty))
623 debug_printf ("determining /dev/tty assignment for ctty %p", myself->ctty);
624 if (iscons_dev (myself->ctty))
625 fh = cnew (fhandler_console, pc.dev);
626 else
627 fh = cnew (fhandler_pty_slave,
628 minor (myself->ctty), (dev_t) pc.dev);
629 if (fh->dev () != FH_NADA)
630 fh->set_name ("/dev/tty");
632 break;
636 /* If `fhraw' is set that means that this fhandler is just a dummy
637 set up for stat(). Mock it up for use by stat without actually
638 trying to do any real initialization. */
639 if (fhraw)
641 fh = fhraw;
642 fh->set_name (pc);
643 if (fh->use_archetype ())
644 fh->archetype = fh;
646 if (fh == fh_unset)
647 fh = cnew (fhandler_nodevice);
648 else if (fh->dev () == FH_ERROR)
650 if (!pc.isopen () && pc.dev.isfs ())
651 fh->dev () = pc.dev; /* Special case: This file actually exists on
652 disk and we're not trying to open it so just
653 return the info from pc. */
654 else
656 delete fh;
657 fh = NULL;
660 return fh;
663 fhandler_base *
664 build_fh_pc (path_conv& pc)
666 fhandler_base *fh = fh_alloc (pc);
668 if (!fh)
670 set_errno (ENXIO);
671 goto out;
674 if (!fh->use_archetype ())
675 fh->set_name (pc);
676 else if ((fh->archetype = cygheap->fdtab.find_archetype (fh->dev ())))
678 debug_printf ("found an archetype for %s(%d/%d) io_handle %p", fh->get_name (), fh->dev ().get_major (), fh->dev ().get_minor (),
679 fh->archetype->get_handle ());
680 if (!fh->get_name ())
681 fh->set_name (fh->archetype->dev ().name ());
683 else if (cygwin_finished_initializing && !pc.isopen ())
684 fh->set_name (pc);
685 else
687 if (!fh->get_name ())
688 fh->set_name (fh->dev ().native ());
689 fh->archetype = fh->clone ();
690 debug_printf ("created an archetype (%p) for %s(%d/%d)", fh->archetype, fh->get_name (), fh->dev ().get_major (), fh->dev ().get_minor ());
691 fh->archetype->archetype = NULL;
692 *cygheap->fdtab.add_archetype () = fh->archetype;
696 /* Keep track of the last tty-like thing opened. We could potentially want
697 to open it if /dev/tty is referenced. */
698 if (CTTY_IS_VALID (myself->ctty) || !fh->is_tty () || !pc.isctty_capable ())
699 last_tty_dev = FH_NADA;
700 else
701 last_tty_dev = fh->dev ();
703 out:
704 debug_printf ("fh %p, dev %08x", fh, fh ? (dev_t) fh->dev () : 0);
705 return fh;
708 fhandler_base *
709 dtable::dup_worker (fhandler_base *oldfh, int flags)
711 fhandler_base *newfh = oldfh->clone ();
712 if (!newfh)
713 debug_printf ("clone failed");
714 else
716 if (!oldfh->archetype)
717 newfh->set_handle (NULL);
719 newfh->pc.close_conv_handle ();
720 if (oldfh->dup (newfh, flags))
722 delete newfh;
723 newfh = NULL;
724 debug_printf ("oldfh->dup failed");
726 else
728 /* Don't increment refcnt here since we don't know if this is a
729 allocated fd. So we leave this chore to the caller. */
731 newfh->usecount = 0;
732 newfh->archetype_usecount (1);
734 /* The O_CLOEXEC flag enforces close-on-exec behaviour. */
735 newfh->set_close_on_exec (!!(flags & O_CLOEXEC));
736 debug_printf ("duped '%s' old %p, new %p", oldfh->get_name (),
737 oldfh->get_handle (), newfh->get_handle ());
740 return newfh;
744 dtable::dup3 (int oldfd, int newfd, int flags)
746 int res = -1;
747 fhandler_base *newfh = NULL; // = NULL to avoid an incorrect warning
749 debug_printf ("dup3 (%d, %d, %y)", oldfd, newfd, flags);
750 lock ();
751 bool do_unlock = true;
752 bool unlock_on_return;
753 if (!(flags & O_EXCL))
754 unlock_on_return = true; /* Relinquish lock on return */
755 else
757 flags &= ~O_EXCL;
758 unlock_on_return = false; /* Return with lock set on success */
761 if (not_open (oldfd))
763 syscall_printf ("fd %d not open", oldfd);
764 set_errno (EBADF);
765 goto done;
767 if (newfd >= OPEN_MAX || newfd < 0)
769 syscall_printf ("new fd out of bounds: %d", newfd);
770 set_errno (EBADF);
771 goto done;
773 if ((flags & ~O_CLOEXEC) != 0)
775 syscall_printf ("invalid flags value %y", flags);
776 set_errno (EINVAL);
777 return -1;
780 if ((newfh = dup_worker (fds[oldfd], flags)) == NULL)
782 res = -1;
783 goto done;
786 debug_printf ("newfh->io_handle %p, oldfh->io_handle %p, new win32_name %p, old win32_name %p",
787 newfh->get_handle (), fds[oldfd]->get_handle (), newfh->get_win32_name (), fds[oldfd]->get_win32_name ());
789 if (!not_open (newfd))
790 close (newfd);
791 else if ((size_t) newfd >= size
792 && find_unused_handle (newfd) < 0)
793 /* couldn't extend fdtab */
795 newfh->close ();
796 res = -1;
797 goto done;
800 fds[newfd] = newfh;
802 if ((res = newfd) <= 2)
803 set_std_handle (res);
804 do_unlock = unlock_on_return;
806 done:
807 if (do_unlock)
808 unlock ();
809 syscall_printf ("%R = dup3(%d, %d, %y)", res, oldfd, newfd, flags);
811 return res;
814 bool
815 dtable::select_read (int fd, select_stuff *ss)
817 if (not_open (fd))
819 set_errno (EBADF);
820 return false;
822 fhandler_base *fh = fds[fd];
823 select_record *s = fh->select_read (ss);
824 s->fd = fd;
825 if (!s->fh)
826 s->fh = fh;
827 s->thread_errno = 0;
828 debug_printf ("%s fd %d", fh->get_name (), fd);
829 return true;
832 bool
833 dtable::select_write (int fd, select_stuff *ss)
835 if (not_open (fd))
837 set_errno (EBADF);
838 return NULL;
840 fhandler_base *fh = fds[fd];
841 select_record *s = fh->select_write (ss);
842 s->fd = fd;
843 s->fh = fh;
844 s->thread_errno = 0;
845 debug_printf ("%s fd %d", fh->get_name (), fd);
846 return true;
849 bool
850 dtable::select_except (int fd, select_stuff *ss)
852 if (not_open (fd))
854 set_errno (EBADF);
855 return NULL;
857 fhandler_base *fh = fds[fd];
858 select_record *s = fh->select_except (ss);
859 s->fd = fd;
860 s->fh = fh;
861 s->thread_errno = 0;
862 debug_printf ("%s fd %d", fh->get_name (), fd);
863 return true;
866 void
867 dtable::move_fd (int from, int to)
869 // close (to); /* It is assumed that this is close-on-exec */
870 fds[to] = fds[from];
871 fds[from] = NULL;
874 void
875 dtable::set_file_pointers_for_exec ()
877 /* This is not POSIX-compliant so the function is only called for
878 non-Cygwin processes. */
879 LARGE_INTEGER eof = { QuadPart: 0 };
881 lock ();
882 fhandler_base *fh;
883 for (size_t i = 0; i < size; i++)
884 if ((fh = fds[i]) != NULL && fh->get_flags () & O_APPEND)
885 SetFilePointerEx (fh->get_handle (), eof, NULL, FILE_END);
886 unlock ();
889 void
890 dtable::fixup_close (size_t i, fhandler_base *fh)
892 if (fh->archetype)
894 debug_printf ("closing fd %d since it is an archetype", i);
895 fh->close_with_arch ();
897 release (i);
900 void
901 dtable::fixup_after_exec ()
903 first_fd_for_open = 0;
904 fhandler_base *fh;
905 for (size_t i = 0; i < size; i++)
906 if ((fh = fds[i]) != NULL)
908 fh->clear_readahead ();
909 fh->fixup_after_exec ();
910 /* Close the handle if it's close-on-exec or if an error was detected
911 (typically with opening a console in a gui app) by fixup_after_exec.
913 if (fh->close_on_exec () || (!fh->nohandle () && !fh->get_handle ()))
914 fixup_close (i, fh);
915 else if (fh->get_popen_pid ())
916 close (i);
917 else if (i == 0)
918 SetStdHandle (std_consts[i], fh->get_handle ());
919 else if (i <= 2)
920 SetStdHandle (std_consts[i], fh->get_output_handle ());
922 if (cygheap->ctty)
923 cygheap->ctty->fixup_after_exec ();
926 void
927 dtable::fixup_after_fork (HANDLE parent)
929 fhandler_base *fh;
930 for (size_t i = 0; i < size; i++)
931 if ((fh = fds[i]) != NULL)
933 if (fh->close_on_exec () || fh->need_fork_fixup ())
935 debug_printf ("fd %d (%s)", i, fh->get_name ());
936 fh->fixup_after_fork (parent);
937 if (!fh->nohandle () && !fh->get_handle ())
939 /* This should actually never happen but it's here to make sure
940 we don't crash due to access of an unopened file handle. */
941 fixup_close (i, fh);
942 continue;
945 if (i == 0)
946 SetStdHandle (std_consts[i], fh->get_handle ());
947 else if (i <= 2)
948 SetStdHandle (std_consts[i], fh->get_output_handle ());
951 if (cygheap->ctty)
952 cygheap->ctty->fixup_after_fork (parent);
955 static void
956 decode_tty (char *buf, WCHAR *w32)
958 int ttyn = wcstol (w32, NULL, 10);
959 __ptsname (buf, ttyn);
962 /* Try to derive posix filename from given handle. Return true if
963 the handle is associated with a cygwin tty. */
964 static bool
965 handle_to_fn (HANDLE h, char *posix_fn)
967 tmp_pathbuf tp;
968 ULONG len = 0;
969 WCHAR *maxmatchdos = NULL;
970 PWCHAR device = tp.w_get ();
971 int maxmatchlen = 0;
972 OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION *) tp.w_get ();
974 NTSTATUS status = NtQueryObject (h, ObjectNameInformation, ntfn, 65536, &len);
975 if (!NT_SUCCESS (status))
976 debug_printf ("NtQueryObject failed, %y", status);
977 // NT seems to do this on an unopened file
978 else if (!ntfn->Name.Buffer)
979 debug_printf ("nt->Name.Buffer == NULL");
980 else
982 WCHAR *w32 = ntfn->Name.Buffer;
983 size_t w32len = ntfn->Name.Length / sizeof (WCHAR);
984 w32[w32len] = L'\0';
986 if (wcscasecmp (w32, DEV_NULL) == 0)
988 strcpy (posix_fn, "/dev/null");
989 return false;
992 if (wcscasecmp (w32, DEV_SOCKET) == 0)
994 strcpy (posix_fn, ":sock:");
995 return false;
998 if (wcsncasecmp (w32, DEV_NAMED_PIPE, DEV_NAMED_PIPE_LEN) == 0)
1000 w32 += DEV_NAMED_PIPE_LEN;
1001 if (wcsncmp (w32, L"cygwin-", WCLEN (L"cygwin-")) != 0)
1002 return false;
1003 w32 += WCLEN (L"cygwin-");
1004 /* Check for installation key and trailing dash. */
1005 w32len = cygheap->installation_key.Length / sizeof (WCHAR);
1006 if (w32len
1007 && wcsncmp (w32, cygheap->installation_key.Buffer, w32len) != 0)
1008 return false;
1009 w32 += w32len;
1010 if (*w32 != L'-')
1011 return false;
1012 ++w32;
1013 bool istty = wcsncmp (w32, L"pty", WCLEN (L"pty")) == 0;
1014 if (istty)
1015 decode_tty (posix_fn, w32 + WCLEN (L"pty"));
1016 else if (wcsncmp (w32, L"pipe", WCLEN (L"pipe")) == 0)
1017 strcpy (posix_fn, "/dev/pipe");
1018 return istty;
1021 WCHAR fnbuf[64 * 1024];
1022 if (wcsncasecmp (w32, DEVICE_PREFIX, DEVICE_PREFIX_LEN) != 0
1023 || !QueryDosDeviceW (NULL, fnbuf, sizeof (fnbuf) / sizeof (WCHAR)))
1025 sys_wcstombs (posix_fn, NT_MAX_PATH, w32, w32len);
1026 return false;
1029 for (WCHAR *s = fnbuf; *s; s = wcschr (s, '\0') + 1)
1031 if (!QueryDosDeviceW (s, device, NT_MAX_PATH))
1032 continue;
1033 if (wcschr (s, ':') == NULL)
1034 continue;
1035 WCHAR *q = wcsrchr (device, ';');
1036 if (q)
1038 WCHAR *r = wcschr (q, '\\');
1039 if (r)
1040 wcscpy (q, r + 1);
1042 int devlen = wcslen (device);
1043 if (device[devlen - 1] == L'\\')
1044 device[--devlen] = L'\0';
1045 if (devlen < maxmatchlen)
1046 continue;
1047 if (wcsncmp (device, w32, devlen) != 0||
1048 (w32[devlen] != L'\0' && w32[devlen] != L'\\'))
1049 continue;
1050 maxmatchlen = devlen;
1051 maxmatchdos = s;
1052 debug_printf ("current match '%W' = '%W'\n", s, device);
1055 if (maxmatchlen)
1057 WCHAR *p = wcschr (w32 + DEVICE_PREFIX_LEN, L'\\');
1058 size_t n = wcslen (maxmatchdos);
1059 WCHAR ch;
1060 if (!p)
1061 ch = L'\0';
1062 else
1064 if (maxmatchdos[n - 1] == L'\\')
1065 n--;
1066 w32 += maxmatchlen - n;
1067 ch = L'\\';
1069 memcpy (w32, maxmatchdos, n * sizeof (WCHAR));
1070 w32[n] = ch;
1072 else if (wcsncmp (w32, DEV_REMOTE, DEV_REMOTE_LEN) == 0)
1074 w32 += DEV_REMOTE_LEN - 2;
1075 *w32 = L'\\';
1076 debug_printf ("remote drive");
1078 else if (wcsncmp (w32, DEV_REMOTE1, DEV_REMOTE1_LEN) == 0)
1080 w32 += DEV_REMOTE1_LEN - 2;
1081 *w32 = L'\\';
1082 debug_printf ("remote drive");
1085 cygwin_conv_path (CCP_WIN_W_TO_POSIX | CCP_ABSOLUTE, w32, posix_fn,
1086 NT_MAX_PATH);
1088 debug_printf ("derived path '%W', posix '%s'", w32, posix_fn);
1089 return false;
1092 strcpy (posix_fn, unknown_file);
1093 return false;
1096 void
1097 dtable::fixup_before_fork (DWORD target_proc_id)
1099 lock ();
1100 fhandler_base *fh;
1101 for (size_t i = 0; i < size; i++)
1102 if ((fh = fds[i]) != NULL)
1104 debug_printf ("fd %d (%s)", i, fh->get_name ());
1105 fh->fixup_before_fork_exec (target_proc_id);
1107 unlock ();
1110 void
1111 dtable::fixup_before_exec (DWORD target_proc_id)
1113 lock ();
1114 fhandler_base *fh;
1115 for (size_t i = 0; i < size; i++)
1116 if ((fh = fds[i]) != NULL && !fh->close_on_exec ())
1118 debug_printf ("fd %d (%s)", i, fh->get_name ());
1119 fh->fixup_before_fork_exec (target_proc_id);
1121 unlock ();