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
9 #define __INSIDE_CYGWIN_NET__
17 #define USE_SYS_TYPES_FD_SET
21 #include "perprocess.h"
29 #include "shared_info.h"
31 static const DWORD std_consts
[] = {STD_INPUT_HANDLE
, STD_OUTPUT_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 */
57 if (!cygheap
->fdtab
.size
)
58 cygheap
->fdtab
.extend (NOFILE_INCR
, 0);
62 set_std_handle (int fd
)
64 fhandler_base
*fh
= cygheap
->fdtab
[fd
];
66 SetStdHandle (std_consts
[fd
], fh
? fh
->get_handle () : NULL
);
68 SetStdHandle (std_consts
[fd
], fh
? fh
->get_output_handle () : NULL
);
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
)
79 else if (size
< OPEN_MAX
&& min
< OPEN_MAX
)
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");
98 memcpy (newfds
, fds
, size
* sizeof (fds
[0]));
104 debug_printf ("size %ld, fds %p", size
, fds
);
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
++)
122 HANDLE h
= GetStdHandle (std_consts
[i
]);
123 fhandler_base
*fh
= build_fh_name (std
[i
]);
127 if (!fh
->open ((i
? (i
== 2 ? O_RDWR
: O_WRONLY
) : O_RDONLY
)
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. */
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);
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. */
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
;
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
];
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;
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
];
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. */
235 for (size_t i
= start
; i
< size
; i
++)
242 while (extend (extendby
, start
));
248 dtable::release (int fd
)
250 if (fds
[fd
]->need_fixup_before ())
251 dec_need_fixup_before ();
252 fds
[fd
]->dec_refcnt ();
259 cygwin_attach_handle_to_fd (char *name
, int fd
, HANDLE handle
, mode_t bin
,
262 cygheap
->fdtab
.lock ();
264 fd
= cygheap
->fdtab
.find_unused_handle ();
265 fhandler_base
*fh
= build_fh_name (name
);
270 cygheap
->fdtab
[fd
] = fh
;
271 cygheap
->fdtab
[fd
]->inc_refcnt ();
272 fh
->init (handle
, myaccess
, bin
?: fh
->pc_binmode ());
274 cygheap
->fdtab
.unlock ();
279 dtable::init_std_file_from_handle (int fd
, HANDLE handle
)
282 CONSOLE_SCREEN_BUFFER_INFO buf
;
284 unsigned bin
= O_BINARY
;
287 first_fd_for_open
= 0;
294 DWORD ft
= GetFileType (handle
);
295 char *name
= tp
.c_get ();
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
))
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
)))
322 else if (GetConsoleScreenBufferInfo (handle
, &buf
)
323 || GetNumberOfConsoleInputEvents (handle
, (DWORD
*) &buf
))
326 if (CTTY_IS_VALID (myself
->ctty
))
327 dev
.parse (myself
->ctty
);
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);
339 /* Try to figure it out from context - probably a disk file */
340 handle_to_fn (handle
, name
);
342 if (!name
[0] && !dev
)
349 fh
= build_fh_dev (dev
);
351 fh
= build_fh_name (name
);
358 bin
= fh
->pc_binmode ();
361 bin
= fh
->get_default_fmode (O_RDWR
);
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
378 access
|= GENERIC_READ
| GENERIC_WRITE
;
380 else if (!iscons_dev (dev
)
381 && NT_SUCCESS (NtQueryInformationFile (handle
, &io
, &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
;
398 openflags
|= O_RDONLY
;
399 access
|= GENERIC_READ
;
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 ());
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");
421 cygheap
->fdtab
[fd
] = fh
;
422 cygheap
->fdtab
[fd
]->inc_refcnt ();
424 paranoid_printf ("fd %d, handle %p", fd
, handle
);
425 fh
->post_open_setup (fd
);
429 #define cnew(name, ...) \
431 void* ptr = (void*) ccalloc (HEAP_FHANDLER, 1, sizeof (name)); \
432 ptr ? new (ptr) name (__VA_ARGS__) : NULL; \
435 #define cnew_no_ctor(name, ...) \
437 void* ptr = (void*) ccalloc (HEAP_FHANDLER, 1, sizeof (name)); \
438 ptr ? new (ptr) name (ptr) : NULL; \
442 build_fh_name (const char *name
, unsigned opt
, suffix_info
*si
)
444 path_conv
pc (name
, opt
| PC_NULLEMPTY
| PC_POSIX
, si
);
447 fhandler_base
*fh
= cnew (fhandler_nodevice
);
449 fh
->set_error (pc
.error
);
450 set_errno (fh
? pc
.error
: EMFILE
);
454 return build_fh_pc (pc
);
458 build_fh_dev (const device
& dev
, const char *unix_name
)
462 pc
.set_posix (unix_name
);
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 ())
481 fh
= cnew (fhandler_pty_slave
, pc
.dev
.get_minor ());
484 fh
= cnew (fhandler_pty_master
, pc
.dev
.get_minor ());
486 case DEV_FLOPPY_MAJOR
:
487 case DEV_CDROM_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
);
494 fh
= cnew (fhandler_dev_tape
);
496 case DEV_SERIAL_MAJOR
:
497 fh
= cnew (fhandler_serial
);
500 fh
= cnew (fhandler_console
, pc
.dev
);
503 switch ((dev_t
) pc
.dev
)
508 fh
= cnew (fhandler_console
, pc
.dev
);
512 fh
= cnew (fhandler_pty_master
, -1, (dev_t
) pc
.dev
);
514 fhraw
= cnew_no_ctor (fhandler_pty_master
, -1);
517 fh
= cnew (fhandler_windows
);
520 fh
= cnew (fhandler_fifo
);
525 fh
= cnew (fhandler_pipe
);
528 fh
= cnew (fhandler_socket_inet
);
531 fh
= cnew (fhandler_socket_local
);
533 #ifdef __WITH_AF_UNIX
535 fh
= cnew (fhandler_socket_unix
);
537 #endif /* __WITH_AF_UNIX */
539 fh
= cnew (fhandler_disk_file
);
542 fh
= cnew (fhandler_dev_null
);
546 fh
= cnew (fhandler_dev_zero
);
550 fh
= cnew (fhandler_dev_random
);
553 fh
= cnew (fhandler_dev_clipboard
);
556 fh
= cnew (fhandler_dev_mixer
);
559 fh
= cnew (fhandler_dev_dsp
);
562 fh
= cnew (fhandler_proc
);
565 fh
= cnew (fhandler_registry
);
568 fh
= cnew (fhandler_process
);
571 fh
= cnew (fhandler_process_fd
);
574 fh
= cnew (fhandler_procnet
);
577 fh
= cnew (fhandler_procsys
);
580 fh
= cnew (fhandler_procsysvipc
);
583 fh
= cnew (fhandler_netdrive
);
586 fh
= cnew (fhandler_dev
);
589 fh
= cnew (fhandler_dev_disk
);
592 fh
= cnew (fhandler_dev_fd
);
595 fh
= cnew (fhandler_cygdrive
);
598 fh
= cnew (fhandler_signalfd
);
601 fh
= cnew (fhandler_timerfd
);
604 fh
= cnew (fhandler_mqueue
);
609 if (CTTY_IS_VALID (myself
->ctty
))
611 if (iscons_dev (myself
->ctty
))
612 fhraw
= cnew_no_ctor (fhandler_console
, -1);
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
);
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");
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. */
643 if (fh
->use_archetype ())
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. */
664 build_fh_pc (path_conv
& pc
)
666 fhandler_base
*fh
= fh_alloc (pc
);
674 if (!fh
->use_archetype ())
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 ())
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
;
701 last_tty_dev
= fh
->dev ();
704 debug_printf ("fh %p, dev %08x", fh
, fh
? (dev_t
) fh
->dev () : 0);
709 dtable::dup_worker (fhandler_base
*oldfh
, int flags
)
711 fhandler_base
*newfh
= oldfh
->clone ();
713 debug_printf ("clone failed");
716 if (!oldfh
->archetype
)
717 newfh
->set_handle (NULL
);
719 newfh
->pc
.close_conv_handle ();
720 if (oldfh
->dup (newfh
, flags
))
724 debug_printf ("oldfh->dup failed");
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. */
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 ());
744 dtable::dup3 (int oldfd
, int newfd
, int flags
)
747 fhandler_base
*newfh
= NULL
; // = NULL to avoid an incorrect warning
749 debug_printf ("dup3 (%d, %d, %y)", oldfd
, newfd
, flags
);
751 bool do_unlock
= true;
752 bool unlock_on_return
;
753 if (!(flags
& O_EXCL
))
754 unlock_on_return
= true; /* Relinquish lock on return */
758 unlock_on_return
= false; /* Return with lock set on success */
761 if (not_open (oldfd
))
763 syscall_printf ("fd %d not open", oldfd
);
767 if (newfd
>= OPEN_MAX
|| newfd
< 0)
769 syscall_printf ("new fd out of bounds: %d", newfd
);
773 if ((flags
& ~O_CLOEXEC
) != 0)
775 syscall_printf ("invalid flags value %y", flags
);
780 if ((newfh
= dup_worker (fds
[oldfd
], flags
)) == NULL
)
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
))
791 else if ((size_t) newfd
>= size
792 && find_unused_handle (newfd
) < 0)
793 /* couldn't extend fdtab */
802 if ((res
= newfd
) <= 2)
803 set_std_handle (res
);
804 do_unlock
= unlock_on_return
;
809 syscall_printf ("%R = dup3(%d, %d, %y)", res
, oldfd
, newfd
, flags
);
815 dtable::select_read (int fd
, select_stuff
*ss
)
822 fhandler_base
*fh
= fds
[fd
];
823 select_record
*s
= fh
->select_read (ss
);
828 debug_printf ("%s fd %d", fh
->get_name (), fd
);
833 dtable::select_write (int fd
, select_stuff
*ss
)
840 fhandler_base
*fh
= fds
[fd
];
841 select_record
*s
= fh
->select_write (ss
);
845 debug_printf ("%s fd %d", fh
->get_name (), fd
);
850 dtable::select_except (int fd
, select_stuff
*ss
)
857 fhandler_base
*fh
= fds
[fd
];
858 select_record
*s
= fh
->select_except (ss
);
862 debug_printf ("%s fd %d", fh
->get_name (), fd
);
867 dtable::move_fd (int from
, int to
)
869 // close (to); /* It is assumed that this is close-on-exec */
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 };
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
);
890 dtable::fixup_close (size_t i
, fhandler_base
*fh
)
894 debug_printf ("closing fd %d since it is an archetype", i
);
895 fh
->close_with_arch ();
901 dtable::fixup_after_exec ()
903 first_fd_for_open
= 0;
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 ()))
915 else if (fh
->get_popen_pid ())
918 SetStdHandle (std_consts
[i
], fh
->get_handle ());
920 SetStdHandle (std_consts
[i
], fh
->get_output_handle ());
923 cygheap
->ctty
->fixup_after_exec ();
927 dtable::fixup_after_fork (HANDLE parent
)
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. */
946 SetStdHandle (std_consts
[i
], fh
->get_handle ());
948 SetStdHandle (std_consts
[i
], fh
->get_output_handle ());
952 cygheap
->ctty
->fixup_after_fork (parent
);
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. */
965 handle_to_fn (HANDLE h
, char *posix_fn
)
969 WCHAR
*maxmatchdos
= NULL
;
970 PWCHAR device
= tp
.w_get ();
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");
982 WCHAR
*w32
= ntfn
->Name
.Buffer
;
983 size_t w32len
= ntfn
->Name
.Length
/ sizeof (WCHAR
);
986 if (wcscasecmp (w32
, DEV_NULL
) == 0)
988 strcpy (posix_fn
, "/dev/null");
992 if (wcscasecmp (w32
, DEV_SOCKET
) == 0)
994 strcpy (posix_fn
, ":sock:");
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)
1003 w32
+= WCLEN (L
"cygwin-");
1004 /* Check for installation key and trailing dash. */
1005 w32len
= cygheap
->installation_key
.Length
/ sizeof (WCHAR
);
1007 && wcsncmp (w32
, cygheap
->installation_key
.Buffer
, w32len
) != 0)
1013 bool istty
= wcsncmp (w32
, L
"pty", WCLEN (L
"pty")) == 0;
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");
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
);
1029 for (WCHAR
*s
= fnbuf
; *s
; s
= wcschr (s
, '\0') + 1)
1031 if (!QueryDosDeviceW (s
, device
, NT_MAX_PATH
))
1033 if (wcschr (s
, ':') == NULL
)
1035 WCHAR
*q
= wcsrchr (device
, ';');
1038 WCHAR
*r
= wcschr (q
, '\\');
1042 int devlen
= wcslen (device
);
1043 if (device
[devlen
- 1] == L
'\\')
1044 device
[--devlen
] = L
'\0';
1045 if (devlen
< maxmatchlen
)
1047 if (wcsncmp (device
, w32
, devlen
) != 0||
1048 (w32
[devlen
] != L
'\0' && w32
[devlen
] != L
'\\'))
1050 maxmatchlen
= devlen
;
1052 debug_printf ("current match '%W' = '%W'\n", s
, device
);
1057 WCHAR
*p
= wcschr (w32
+ DEVICE_PREFIX_LEN
, L
'\\');
1058 size_t n
= wcslen (maxmatchdos
);
1064 if (maxmatchdos
[n
- 1] == L
'\\')
1066 w32
+= maxmatchlen
- n
;
1069 memcpy (w32
, maxmatchdos
, n
* sizeof (WCHAR
));
1072 else if (wcsncmp (w32
, DEV_REMOTE
, DEV_REMOTE_LEN
) == 0)
1074 w32
+= DEV_REMOTE_LEN
- 2;
1076 debug_printf ("remote drive");
1078 else if (wcsncmp (w32
, DEV_REMOTE1
, DEV_REMOTE1_LEN
) == 0)
1080 w32
+= DEV_REMOTE1_LEN
- 2;
1082 debug_printf ("remote drive");
1085 cygwin_conv_path (CCP_WIN_W_TO_POSIX
| CCP_ABSOLUTE
, w32
, posix_fn
,
1088 debug_printf ("derived path '%W', posix '%s'", w32
, posix_fn
);
1092 strcpy (posix_fn
, unknown_file
);
1097 dtable::fixup_before_fork (DWORD target_proc_id
)
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
);
1111 dtable::fixup_before_exec (DWORD target_proc_id
)
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
);