]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/dtable.cc
Remove unneeded header files from source files throughout.
[newlib-cygwin.git] / winsup / cygwin / dtable.cc
CommitLineData
9015e0fb 1/* dtable.cc: file descriptor support.
1fd5e000 2
731028b3 3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
a7d2cc16 4 2005, 2006, 2007, 2008 Red 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
12#define __INSIDE_CYGWIN_NET__
13
4c8d72de 14#include "winsup.h"
1fd5e000
CF
15#include <sys/socket.h>
16#include <stdlib.h>
17#include <stdio.h>
1fd5e000 18#include <unistd.h>
1ffe3e67 19#include <wchar.h>
1fd5e000 20
a1299ba5 21#define USE_SYS_TYPES_FD_SET
d0b178fe 22#include <winsock.h>
e2ebe117 23#include "pinfo.h"
9e2baf8d 24#include "cygerrno.h"
95a8465b 25#include "perprocess.h"
bccd5e0d 26#include "path.h"
7ac61736 27#include "fhandler.h"
bccd5e0d 28#include "dtable.h"
0381fec6 29#include "cygheap.h"
ab5d348d 30#include "tls_pbuf.h"
2402700d 31#include "ntdll.h"
f09acf77 32#include "shared_info.h"
1fd5e000 33
57c89867 34static const NO_COPY DWORD std_consts[] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE,
083abe54 35 STD_ERROR_HANDLE};
164a681c 36
88f0dc31 37static bool handle_to_fn (HANDLE, char *);
1ffe3e67
CF
38
39#define WCLEN(x) ((sizeof (x) / sizeof (WCHAR)) - 1)
40char unknown_file[] = "some disk file";
41const WCHAR DEV_NULL[] = L"\\Device\\Null";
42
43const WCHAR DEVICE_PREFIX[] = L"\\device\\";
44const size_t DEVICE_PREFIX_LEN WCLEN (DEVICE_PREFIX);
45
46static const WCHAR DEV_NAMED_PIPE[] = L"\\Device\\NamedPipe\\";
47static const size_t DEV_NAMED_PIPE_LEN = WCLEN (DEV_NAMED_PIPE);
dd76747b 48
1ffe3e67
CF
49static const WCHAR DEV_REMOTE[] = L"\\Device\\LanmanRedirector\\";
50static const size_t DEV_REMOTE_LEN = WCLEN (DEV_REMOTE);
51
52static const WCHAR DEV_REMOTE1[] = L"\\Device\\WinDfs\\Root\\";
53static const size_t DEV_REMOTE1_LEN = WCLEN (DEV_REMOTE1);
634a4140 54
1fd5e000
CF
55/* Set aside space for the table of fds */
56void
2d1d1eb1 57dtable_init ()
1fd5e000 58{
0381fec6 59 if (!cygheap->fdtab.size)
c729f227 60 cygheap->fdtab.extend (NOFILE_INCR);
1fd5e000
CF
61}
62
63void __stdcall
64set_std_handle (int fd)
65{
66 if (fd == 0)
0381fec6 67 SetStdHandle (std_consts[fd], cygheap->fdtab[fd]->get_handle ());
164a681c 68 else if (fd <= 2)
0381fec6 69 SetStdHandle (std_consts[fd], cygheap->fdtab[fd]->get_output_handle ());
1fd5e000
CF
70}
71
72int
9015e0fb 73dtable::extend (int howmuch)
1fd5e000
CF
74{
75 int new_size = size + howmuch;
76 fhandler_base **newfds;
77
78 if (howmuch <= 0)
79 return 0;
80
4d782b42
CF
81 if (new_size > (100 * NOFILE_INCR))
82 {
83 set_errno (EMFILE);
84 return 0;
85 }
86
c729f227 87 /* Try to allocate more space for fd table. We can't call realloc ()
1fd5e000
CF
88 here to preserve old table if memory allocation fails */
89
b0e82b74 90 if (!(newfds = (fhandler_base **) ccalloc (HEAP_ARGV, new_size, sizeof newfds[0])))
1fd5e000
CF
91 {
92 debug_printf ("calloc failed");
4d782b42 93 set_errno (ENOMEM);
1fd5e000
CF
94 return 0;
95 }
96 if (fds)
97 {
4d782b42 98 memcpy (newfds, fds, size * sizeof (fds[0]));
3301015b 99 cfree (fds);
1fd5e000
CF
100 }
101
102 size = new_size;
103 fds = newfds;
41f42725 104 debug_printf ("size %d, fds %p", size, fds);
1fd5e000
CF
105 return 1;
106}
107
083abe54
CF
108void
109dtable::get_debugger_info ()
110{
918a268c 111 if (being_debugged ())
083abe54
CF
112 {
113 char std[3][sizeof ("/dev/ttyNNNN")];
114 std[0][0] = std[1][0] = std [2][0] = '\0';
115 char buf[sizeof ("cYgstd %x") + 32];
116 sprintf (buf, "cYgstd %x %x %x", (unsigned) &std, sizeof (std[0]), 3);
117 OutputDebugString (buf);
118 for (int i = 0; i < 3; i++)
119 if (std[i][0])
120 {
083abe54 121 HANDLE h = GetStdHandle (std_consts[i]);
7ac61736 122 fhandler_base *fh = build_fh_name (std[i]);
083abe54
CF
123 if (!fh)
124 continue;
7ac61736 125 fds[i] = fh;
061095b5
CV
126 if (!fh->open ((i ? (i == 2 ? O_RDWR : O_WRONLY) : O_RDONLY)
127 | O_BINARY, 0777))
083abe54
CF
128 release (i);
129 else
130 CloseHandle (h);
131 }
132 }
133}
134
1fd5e000 135/* Initialize the file descriptor/handle mapping table.
10dedaaa
CF
136 This function should only be called when a cygwin function is invoked
137 by a non-cygwin function, i.e., it should only happen very rarely. */
1fd5e000
CF
138
139void
083abe54 140dtable::stdio_init ()
1fd5e000 141{
b98ebf54 142 extern void set_console_ctty ();
1fd5e000
CF
143 /* Set these before trying to output anything from strace.
144 Also, always set them even if we're to pick up our parent's fds
145 in case they're missed. */
146
8cb359d9 147 if (myself->cygstarted || ISSTATE (myself, PID_CYGPARENT))
3eb92a58 148 {
f09acf77
CF
149 tty_min *t = cygwin_shared->tty.get_tty (myself->ctty);
150 if (t && t->getpgid () == myself->pid && t->gethwnd ())
151 init_console_handler (true);
3eb92a58
CF
152 return;
153 }
1fd5e000 154
083abe54
CF
155 HANDLE in = GetStdHandle (STD_INPUT_HANDLE);
156 HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE);
157 HANDLE err = GetStdHandle (STD_ERROR_HANDLE);
1fd5e000 158
54030e21 159 init_std_file_from_handle (0, in);
083abe54
CF
160
161 /* STD_ERROR_HANDLE has been observed to be the same as
162 STD_OUTPUT_HANDLE. We need separate handles (e.g. using pipes
163 to pass data from child to parent). */
164 if (out == err)
165 {
166 /* Since this code is not invoked for forked tasks, we don't have
167 to worry about the close-on-exec flag here. */
b040009e
CF
168 if (!DuplicateHandle (hMainProc, out, hMainProc, &err, 0, true,
169 DUPLICATE_SAME_ACCESS))
1fd5e000 170 {
083abe54
CF
171 /* If that fails, do this as a fall back. */
172 err = out;
173 system_printf ("couldn't make stderr distinct from stdout");
1fd5e000 174 }
1fd5e000 175 }
083abe54 176
54030e21
CF
177 init_std_file_from_handle (1, out);
178 init_std_file_from_handle (2, err);
65438ec6 179
083abe54
CF
180 /* Assign the console as the controlling tty for this process if we actually
181 have a console and no other controlling tty has been assigned. */
65438ec6 182 if (!fhandler_console::need_invisible () && myself->ctty < 0)
083abe54 183 set_console_ctty ();
1fd5e000
CF
184}
185
8e10c431
CF
186const int dtable::initial_archetype_size;
187
188fhandler_base *
189dtable::find_archetype (device& dev)
190{
191 for (unsigned i = 0; i < farchetype; i++)
192 if (archetypes[i]->get_device () == (unsigned) dev)
193 return archetypes[i];
194 return NULL;
195}
196
197fhandler_base **
198dtable::add_archetype ()
199{
200 if (farchetype++ >= narchetypes)
634a4140 201 archetypes = (fhandler_base **) crealloc_abort (archetypes, (narchetypes += initial_archetype_size) * sizeof archetypes[0]);
8e10c431
CF
202 return archetypes + farchetype - 1;
203}
204
205void
206dtable::delete_archetype (fhandler_base *fh)
207{
8ed5c9b6 208 for (unsigned i = 0; i < farchetype; i++)
8e10c431
CF
209 if (fh == archetypes[i])
210 {
8ed5c9b6 211 debug_printf ("deleting element %d for %s", i, fh->get_name ());
8e10c431
CF
212 if (i < --farchetype)
213 archetypes[i] = archetypes[farchetype];
214 break;
215 }
216
217 delete fh;
218}
219
1fd5e000 220int
9015e0fb 221dtable::find_unused_handle (int start)
1fd5e000 222{
1fd5e000
CF
223 do
224 {
e773b7cf 225 for (size_t i = start; i < size; i++)
91892f50
CF
226 /* See if open -- no need for overhead of not_open */
227 if (fds[i] == NULL)
1fd5e000
CF
228 return i;
229 }
230 while (extend (NOFILE_INCR));
231 return -1;
232}
233
234void
9015e0fb 235dtable::release (int fd)
1fd5e000
CF
236{
237 if (!not_open (fd))
238 {
7ac61736
CF
239 if (fds[fd]->need_fixup_before ())
240 dec_need_fixup_before ();
9279515a 241 fhandler_base *arch = fds[fd]->archetype;
166b2571 242 delete fds[fd];
9279515a
CF
243 if (arch && !arch->usecount)
244 cygheap->fdtab.delete_archetype (arch);
1fd5e000
CF
245 fds[fd] = NULL;
246 }
247}
248
45586380 249extern "C" int
ebd645e7
CF
250cygwin_attach_handle_to_fd (char *name, int fd, HANDLE handle, mode_t bin,
251 DWORD myaccess)
252{
253 if (fd == -1)
254 fd = cygheap->fdtab.find_unused_handle ();
7ac61736
CF
255 fhandler_base *fh = build_fh_name (name);
256 cygheap->fdtab[fd] = fh;
257 fh->init (handle, myaccess, bin ?: fh->pc_binmode ());
ebd645e7
CF
258 return fd;
259}
260
1fd5e000 261void
54030e21 262dtable::init_std_file_from_handle (int fd, HANDLE handle)
1fd5e000 263{
ebd645e7
CF
264 CONSOLE_SCREEN_BUFFER_INFO buf;
265 struct sockaddr sa;
266 int sal = sizeof (sa);
267 DCB dcb;
abb58a6d 268 unsigned bin = O_BINARY;
7ac61736 269 device dev;
ab5d348d 270 tmp_pathbuf tp;
ebd645e7 271
7ac61736 272 dev.devn = 0; /* FIXME: device */
ebd645e7 273 first_fd_for_open = 0;
1ac6d1a1 274
083abe54
CF
275 if (!not_open (fd))
276 return;
277
cef69559 278 SetLastError (0);
1ffe3e67 279 DWORD access = 0;
cef69559 280 DWORD ft = GetFileType (handle);
1ffe3e67
CF
281 char name[NT_MAX_PATH];
282 name[0] = '\0';
88f0dc31
CF
283 if (ft == FILE_TYPE_UNKNOWN && GetLastError () == ERROR_INVALID_HANDLE)
284 /* can't figure out what this is */;
285 else if (ft == FILE_TYPE_PIPE)
1fd5e000 286 {
88f0dc31 287 if (handle_to_fn (handle, name))
1ffe3e67
CF
288 /* ok */;
289 else if (fd == 0)
290 dev = *piper_dev;
4ab6034f 291 else
1ffe3e67 292 dev = *pipew_dev;
88f0dc31
CF
293 if (name[0])
294 access = FILE_CREATE_PIPE_INSTANCE;
4ab6034f 295 }
1ffe3e67
CF
296 else if (GetConsoleScreenBufferInfo (handle, &buf))
297 {
298 /* Console output */
299 if (ISSTATE (myself, PID_USETTY))
300 dev.parse (FH_TTY);
301 else
302 dev = *console_dev;
303 }
304 else if (GetNumberOfConsoleInputEvents (handle, (DWORD *) &buf))
305 {
306 /* Console input */
307 if (ISSTATE (myself, PID_USETTY))
308 dev.parse (FH_TTY);
309 else
310 dev = *console_dev;
311 }
312 else if (wsock_started && getpeername ((SOCKET) handle, &sa, &sal) == 0)
313 /* socket */
314 dev = *tcp_dev;
315 else if (GetCommState (handle, &dcb))
316 /* serial */
317 dev.parse (DEV_TTYS_MAJOR, 0);
318 else
319 /* Try to figure it out from context - probably a disk file */
320 handle_to_fn (handle, name);
cef69559 321
1ffe3e67 322 if (!name[0] && !dev)
cef69559
CF
323 fds[fd] = NULL;
324 else
4ab6034f 325 {
7ac61736
CF
326 fhandler_base *fh;
327
328 if (dev)
1ffe3e67 329 fh = build_fh_dev (dev);
7ac61736
CF
330 else
331 fh = build_fh_name (name);
332
333 if (fh)
334 cygheap->fdtab[fd] = fh;
335
1ffe3e67 336 if (name[0])
abb58a6d 337 {
634a4140
CF
338 bin = fh->pc_binmode ();
339 if (!bin)
340 {
341 bin = fh->get_default_fmode (O_RDWR);
342 if (!bin && dev)
343 bin = O_BINARY;
344 }
abb58a6d 345 }
9655ff26 346
4248960e 347 if (dev == FH_TTY || dev == FH_CONSOLE)
88f0dc31 348 access |= GENERIC_READ | GENERIC_WRITE;
4248960e 349 else if (fd == 0)
88f0dc31 350 access |= GENERIC_READ;
70300fdb 351 else
88f0dc31 352 access |= GENERIC_WRITE; /* Should be rdwr for stderr but not sure that's
634a4140
CF
353 possible for some versions of handles */
354 fh->init (handle, access, bin);
cef69559
CF
355 set_std_handle (fd);
356 paranoid_printf ("fd %d, handle %p", fd, handle);
1fd5e000 357 }
1fd5e000
CF
358}
359
dcb091ca 360#define cnew(name) new ((void *) ccalloc (HEAP_FHANDLER, 1, sizeof (name))) name
1ffe3e67
CF
361
362static fhandler_base *
363build_fh_name_worker (path_conv& pc, HANDLE h, unsigned opt, suffix_info *si)
1fd5e000 364{
4ab6034f
CF
365 if (pc.error)
366 {
e00700cd 367 fhandler_base *fh = cnew (fhandler_nodevice) ();
6a7bea70
CF
368 if (fh)
369 fh->set_error (pc.error);
370 set_errno (fh ? pc.error : EMFILE);
e00700cd 371 return fh;
1fd5e000
CF
372 }
373
7ac61736
CF
374 if (!pc.exists () && h)
375 pc.fillin (h);
2402700d 376
7ac61736 377 return build_fh_pc (pc);
1fd5e000 378}
1ffe3e67
CF
379fhandler_base *
380build_fh_name (const char *name, HANDLE h, unsigned opt, suffix_info *si)
381{
382 path_conv pc (name, opt | PC_NULLEMPTY | PC_POSIX, si);
383 return build_fh_name_worker (pc, h, opt, si);
384}
385
88f0dc31 386#if 0 /* Not needed yet */
1ffe3e67
CF
387#define cnew(name) new ((void *) ccalloc (HEAP_FHANDLER, 1, sizeof (name))) name
388fhandler_base *
389build_fh_name (const UNICODE_STRING *name, HANDLE h, unsigned opt, suffix_info *si)
390{
391 path_conv pc (name, opt | PC_NULLEMPTY | PC_POSIX, si);
392 return build_fh_name_worker (pc, h, opt, si);
393}
88f0dc31 394#endif
1fd5e000
CF
395
396fhandler_base *
7ac61736 397build_fh_dev (const device& dev, const char *unix_name)
ff938546 398{
7ac61736 399 path_conv pc (dev);
7ac61736 400 if (unix_name)
861ef997 401 pc.set_normalized_path (unix_name, false);
7ac61736 402 else
861ef997 403 pc.set_normalized_path (dev.name, false);
7ac61736 404 return build_fh_pc (pc);
ff938546
CF
405}
406
6a7bea70 407#define fh_unset ((fhandler_base *) 1)
ff938546 408fhandler_base *
7ac61736 409build_fh_pc (path_conv& pc)
1fd5e000 410{
6a7bea70 411 fhandler_base *fh = fh_unset;
1fd5e000 412
7b02cb30
CF
413 switch (pc.dev.major)
414 {
415 case DEV_TTYS_MAJOR:
416 fh = cnew (fhandler_tty_slave) ();
417 break;
418 case DEV_TTYM_MAJOR:
419 fh = cnew (fhandler_tty_master) ();
420 break;
421 case DEV_CYGDRIVE_MAJOR:
422 fh = cnew (fhandler_cygdrive) ();
423 break;
424 case DEV_FLOPPY_MAJOR:
425 case DEV_CDROM_MAJOR:
426 case DEV_SD_MAJOR:
cc9dbc90 427 case DEV_SD1_MAJOR:
9e3f289f
CV
428 case DEV_SD2_MAJOR:
429 case DEV_SD3_MAJOR:
430 case DEV_SD4_MAJOR:
431 case DEV_SD5_MAJOR:
432 case DEV_SD6_MAJOR:
433 case DEV_SD7_MAJOR:
7b02cb30
CF
434 fh = cnew (fhandler_dev_floppy) ();
435 break;
436 case DEV_TAPE_MAJOR:
437 fh = cnew (fhandler_dev_tape) ();
438 break;
439 case DEV_SERIAL_MAJOR:
440 fh = cnew (fhandler_serial) ();
441 break;
442 default:
443 switch (pc.dev)
444 {
445 case FH_CONSOLE:
446 case FH_CONIN:
447 case FH_CONOUT:
448 fh = cnew (fhandler_console) ();
449 break;
450 case FH_PTYM:
451 fh = cnew (fhandler_pty_master) ();
452 break;
453 case FH_WINDOWS:
454 fh = cnew (fhandler_windows) ();
455 break;
456 case FH_FIFO:
457 fh = cnew (fhandler_fifo) ();
458 break;
459 case FH_PIPE:
460 case FH_PIPER:
461 case FH_PIPEW:
462 fh = cnew (fhandler_pipe) ();
463 break;
464 case FH_TCP:
465 case FH_UDP:
466 case FH_ICMP:
467 case FH_UNIX:
468 case FH_STREAM:
469 case FH_DGRAM:
470 fh = cnew (fhandler_socket) ();
471 break;
472 case FH_FS:
473 fh = cnew (fhandler_disk_file) ();
474 break;
475 case FH_NULL:
476 fh = cnew (fhandler_dev_null) ();
477 break;
478 case FH_ZERO:
479 case FH_FULL:
480 fh = cnew (fhandler_dev_zero) ();
481 break;
482 case FH_RANDOM:
483 case FH_URANDOM:
484 fh = cnew (fhandler_dev_random) ();
485 break;
486 case FH_MEM:
487 case FH_PORT:
488 fh = cnew (fhandler_dev_mem) ();
489 break;
490 case FH_CLIPBOARD:
491 fh = cnew (fhandler_dev_clipboard) ();
492 break;
493 case FH_OSS_DSP:
494 fh = cnew (fhandler_dev_dsp) ();
495 break;
496 case FH_PROC:
497 fh = cnew (fhandler_proc) ();
498 break;
499 case FH_REGISTRY:
500 fh = cnew (fhandler_registry) ();
501 break;
502 case FH_PROCESS:
503 fh = cnew (fhandler_process) ();
504 break;
96d7dee2
CV
505 case FH_PROCNET:
506 fh = cnew (fhandler_procnet) ();
507 break;
7b02cb30
CF
508 case FH_NETDRIVE:
509 fh = cnew (fhandler_netdrive) ();
510 break;
511 case FH_TTY:
0e1ba888 512 {
7b02cb30
CF
513 if (myself->ctty == TTY_CONSOLE)
514 fh = cnew (fhandler_console) ();
515 else if (myself->ctty >= 0)
516 fh = cnew (fhandler_tty_slave) ();
0e1ba888 517 break;
7b02cb30
CF
518 }
519 case FH_KMSG:
520 fh = cnew (fhandler_mailslot) ();
521 break;
0e1ba888 522 }
7b02cb30 523 }
7ac61736 524
2e82c935
CF
525 if (fh == fh_unset)
526 fh = cnew (fhandler_nodevice) ();
527
528 if (fh)
529 fh->set_name (pc);
6a7bea70 530 else
2e82c935 531 set_errno (EMFILE);
7ac61736
CF
532
533 debug_printf ("fh %p", fh);
534 return fh;
1fd5e000
CF
535}
536
537fhandler_base *
9015e0fb 538dtable::dup_worker (fhandler_base *oldfh)
1fd5e000 539{
7ac61736 540 fhandler_base *newfh = build_fh_pc (oldfh->pc);
6a7bea70
CF
541 if (!newfh)
542 debug_printf ("build_fh_pc failed");
543 else
1fd5e000 544 {
6a7bea70
CF
545 *newfh = *oldfh;
546 newfh->set_io_handle (NULL);
dcb091ca 547 if (oldfh->dup (newfh))
6a7bea70
CF
548 {
549 cfree (newfh);
550 debug_printf ("oldfh->dup failed");
551 }
552 else
553 {
554 newfh->close_on_exec (false);
555 debug_printf ("duped '%s' old %p, new %p", oldfh->get_name (), oldfh->get_io_handle (), newfh->get_io_handle ());
556 }
1fd5e000 557 }
1fd5e000
CF
558 return newfh;
559}
560
561int
9015e0fb 562dtable::dup2 (int oldfd, int newfd)
1fd5e000
CF
563{
564 int res = -1;
565 fhandler_base *newfh = NULL; // = NULL to avoid an incorrect warning
566
567 MALLOC_CHECK;
568 debug_printf ("dup2 (%d, %d)", oldfd, newfd);
2d1d1eb1 569 lock ();
1fd5e000
CF
570
571 if (not_open (oldfd))
572 {
5a449743 573 syscall_printf ("fd %d not open", oldfd);
1fd5e000
CF
574 set_errno (EBADF);
575 goto done;
576 }
577
4c78be52
CF
578 if (newfd < 0)
579 {
580 syscall_printf ("new fd out of bounds: %d", newfd);
581 set_errno (EBADF);
582 goto done;
583 }
584
1fd5e000
CF
585 if (newfd == oldfd)
586 {
587 res = 0;
588 goto done;
589 }
590
591 if ((newfh = dup_worker (fds[oldfd])) == NULL)
592 {
593 res = -1;
594 goto done;
595 }
596
4c78be52
CF
597 debug_printf ("newfh->io_handle %p, oldfh->io_handle %p",
598 newfh->get_io_handle (), fds[oldfd]->get_io_handle ());
b0e82b74 599
4c78be52 600 if (!not_open (newfd))
5ec14fe4 601 close (newfd);
4c78be52
CF
602 else if ((size_t) newfd < size)
603 /* nothing to do */;
604 else if (find_unused_handle (newfd) < 0)
5a449743 605 {
4c78be52
CF
606 newfh->close ();
607 res = -1;
5a449743
CF
608 goto done;
609 }
b0e82b74 610
1fd5e000 611 fds[newfd] = newfh;
dd4f0b23 612
1fd5e000
CF
613 if ((res = newfd) <= 2)
614 set_std_handle (res);
615
1fd5e000 616done:
4c78be52 617 MALLOC_CHECK;
2d1d1eb1 618 unlock ();
1fd5e000
CF
619 syscall_printf ("%d = dup2 (%d, %d)", res, oldfd, newfd);
620
621 return res;
622}
623
624select_record *
9015e0fb 625dtable::select_read (int fd, select_record *s)
1fd5e000 626{
b0e82b74 627 if (not_open (fd))
1fd5e000
CF
628 {
629 set_errno (EBADF);
630 return NULL;
631 }
b0e82b74 632 fhandler_base *fh = fds[fd];
1fd5e000
CF
633 s = fh->select_read (s);
634 s->fd = fd;
635 s->fh = fh;
169c465a 636 s->thread_errno = 0;
1fd5e000
CF
637 debug_printf ("%s fd %d", fh->get_name (), fd);
638 return s;
639}
640
641select_record *
9015e0fb 642dtable::select_write (int fd, select_record *s)
1fd5e000 643{
b0e82b74 644 if (not_open (fd))
1fd5e000
CF
645 {
646 set_errno (EBADF);
647 return NULL;
648 }
b0e82b74 649 fhandler_base *fh = fds[fd];
1fd5e000
CF
650 s = fh->select_write (s);
651 s->fd = fd;
652 s->fh = fh;
169c465a 653 s->thread_errno = 0;
1fd5e000
CF
654 debug_printf ("%s fd %d", fh->get_name (), fd);
655 return s;
656}
657
658select_record *
9015e0fb 659dtable::select_except (int fd, select_record *s)
1fd5e000 660{
b0e82b74 661 if (not_open (fd))
1fd5e000
CF
662 {
663 set_errno (EBADF);
664 return NULL;
665 }
b0e82b74 666 fhandler_base *fh = fds[fd];
1fd5e000
CF
667 s = fh->select_except (s);
668 s->fd = fd;
669 s->fh = fh;
169c465a 670 s->thread_errno = 0;
1fd5e000
CF
671 debug_printf ("%s fd %d", fh->get_name (), fd);
672 return s;
673}
674
b0e82b74
CF
675/* Function to walk the fd table after an exec and perform
676 per-fhandler type fixups. */
dd4f0b23
CV
677void
678dtable::fixup_before_fork (DWORD target_proc_id)
679{
2d1d1eb1 680 lock ();
dd4f0b23
CV
681 fhandler_base *fh;
682 for (size_t i = 0; i < size; i++)
683 if ((fh = fds[i]) != NULL)
684 {
c729f227 685 debug_printf ("fd %d (%s)", i, fh->get_name ());
dd4f0b23
CV
686 fh->fixup_before_fork_exec (target_proc_id);
687 }
2d1d1eb1 688 unlock ();
dd4f0b23
CV
689}
690
c16548b2
CF
691void
692dtable::move_fd (int from, int to)
693{
694 // close (to); /* It is assumed that this is close-on-exec */
695 fds[to] = fds[from];
696 fds[from] = NULL;
697}
698
dd4f0b23
CV
699void
700dtable::fixup_before_exec (DWORD target_proc_id)
701{
2d1d1eb1 702 lock ();
dd4f0b23
CV
703 fhandler_base *fh;
704 for (size_t i = 0; i < size; i++)
56551a9b 705 if ((fh = fds[i]) != NULL && !fh->close_on_exec ())
dd4f0b23 706 {
c729f227 707 debug_printf ("fd %d (%s)", i, fh->get_name ());
dd4f0b23
CV
708 fh->fixup_before_fork_exec (target_proc_id);
709 }
2d1d1eb1 710 unlock ();
dd4f0b23
CV
711}
712
fef1edbc
CF
713void
714dtable::set_file_pointers_for_exec ()
715{
cce64750
CV
716/* This is not POSIX-compliant so the function is only called for
717 non-Cygwin processes. */
ad4e943f 718 LONG off_high = 0;
2d1d1eb1 719 lock ();
fef1edbc
CF
720 fhandler_base *fh;
721 for (size_t i = 0; i < size; i++)
722 if ((fh = fds[i]) != NULL && fh->get_flags () & O_APPEND)
ad4e943f 723 SetFilePointer (fh->get_handle (), 0, &off_high, FILE_END);
2d1d1eb1 724 unlock ();
fef1edbc
CF
725}
726
b0e82b74 727void
52806019 728dtable::fixup_after_exec ()
1fd5e000 729{
b0e82b74 730 first_fd_for_open = 0;
2e78b61d 731 fhandler_base *fh;
b0e82b74 732 for (size_t i = 0; i < size; i++)
2e78b61d 733 if ((fh = fds[i]) != NULL)
4f7ac76a 734 {
2e78b61d 735 fh->clear_readahead ();
59297e04 736 fh->fixup_after_exec ();
56551a9b 737 if (fh->close_on_exec ())
8ed5c9b6
CF
738 {
739 if (fh->archetype)
578e142a
CF
740 {
741 debug_printf ("closing fd %d since it is an archetype", i);
742 fh->close ();
743 }
8ed5c9b6
CF
744 release (i);
745 }
59297e04
CF
746 else if (i == 0)
747 SetStdHandle (std_consts[i], fh->get_io_handle ());
748 else if (i <= 2)
749 SetStdHandle (std_consts[i], fh->get_output_handle ());
4f7ac76a 750 }
1fd5e000
CF
751}
752
753void
9015e0fb 754dtable::fixup_after_fork (HANDLE parent)
1fd5e000 755{
b0e82b74 756 fhandler_base *fh;
1fd5e000 757 for (size_t i = 0; i < size; i++)
b0e82b74 758 if ((fh = fds[i]) != NULL)
1fd5e000 759 {
56551a9b 760 if (fh->close_on_exec () || fh->need_fork_fixup ())
1fd5e000 761 {
c729f227 762 debug_printf ("fd %d (%s)", i, fh->get_name ());
1fd5e000
CF
763 fh->fixup_after_fork (parent);
764 }
f3acbe3e
CF
765 if (i == 0)
766 SetStdHandle (std_consts[i], fh->get_io_handle ());
767 else if (i <= 2)
768 SetStdHandle (std_consts[i], fh->get_output_handle ());
1fd5e000 769 }
1fd5e000
CF
770}
771
f7239090 772#ifdef NEWVFORK
1fd5e000 773int
9015e0fb 774dtable::vfork_child_dup ()
1fd5e000
CF
775{
776 fhandler_base **newtable;
2d1d1eb1 777 lock ();
c729f227 778 newtable = (fhandler_base **) ccalloc (HEAP_ARGV, size, sizeof (fds[0]));
1fd5e000
CF
779 int res = 1;
780
928eca7a 781 /* Remove impersonation */
70249d56 782 cygheap->user.deimpersonate ();
9279515a 783 if (cygheap->ctty)
e9737793
CF
784 {
785 cygheap->ctty->usecount++;
59297e04 786 cygheap->console_count++;
e9737793
CF
787 report_tty_counts (cygheap->ctty, "vfork dup", "incremented ", "");
788 }
928eca7a 789
1fd5e000
CF
790 for (size_t i = 0; i < size; i++)
791 if (not_open (i))
792 continue;
a7670c1e 793 else if ((newtable[i] = dup_worker (fds[i])) != NULL)
56551a9b 794 newtable[i]->set_close_on_exec (fds[i]->close_on_exec ());
a7670c1e 795 else
1fd5e000
CF
796 {
797 res = 0;
1fd5e000
CF
798 goto out;
799 }
b0e82b74 800
1fd5e000
CF
801 fds_on_hold = fds;
802 fds = newtable;
c729f227 803
1fd5e000 804out:
380aaf2d 805 /* Restore impersonation */
70249d56 806 cygheap->user.reimpersonate ();
380aaf2d 807
2d1d1eb1 808 unlock ();
1fd5e000
CF
809 return 1;
810}
811
812void
9015e0fb 813dtable::vfork_parent_restore ()
1fd5e000 814{
2d1d1eb1 815 lock ();
1fd5e000 816
001197ae 817 fhandler_tty_slave *ctty_on_hold = cygheap->ctty_on_hold;
f9fb1149 818 close_all_files ();
1fd5e000
CF
819 fhandler_base **deleteme = fds;
820 fds = fds_on_hold;
821 fds_on_hold = NULL;
b0e82b74 822 cfree (deleteme);
2d1d1eb1 823 unlock ();
e80cbe3e 824
42f5993f
CF
825 if (cygheap->ctty != ctty_on_hold)
826 {
827 cygheap->ctty = ctty_on_hold; // revert
828 cygheap->ctty->close (); // Undo previous bump of this archetype
829 }
e80cbe3e 830 cygheap->ctty_on_hold = NULL;
0381fec6
CF
831}
832
833void
834dtable::vfork_child_fixup ()
835{
836 if (!fds_on_hold)
837 return;
a7670c1e 838 debug_printf ("here");
0381fec6
CF
839 fhandler_base **saveme = fds;
840 fds = fds_on_hold;
841
842 fhandler_base *fh;
9279515a
CF
843 for (int i = 0; i < (int) size; i++)
844 if ((fh = fds[i]) != NULL)
0381fec6 845 {
0381fec6 846 fh->clear_readahead ();
56551a9b 847 if (!fh->archetype && fh->close_on_exec ())
cdcfe4e8
CF
848 release (i);
849 else
850 {
851 fh->close ();
9279515a 852 release (i);
cdcfe4e8 853 }
0381fec6
CF
854 }
855
856 fds = saveme;
857 cfree (fds_on_hold);
858 fds_on_hold = NULL;
859
e80cbe3e
CF
860 if (cygheap->ctty_on_hold)
861 {
862 cygheap->ctty_on_hold->close ();
863 cygheap->ctty_on_hold = NULL;
864 }
1fd5e000 865}
f7239090 866#endif /*NEWVFORK*/
2402700d 867
88f0dc31
CF
868static void
869decode_tty (char *buf, WCHAR *w32)
1ffe3e67
CF
870{
871 int ttyn = wcstol (w32, NULL, 10);
872 __small_sprintf (buf, "/dev/tty%d", ttyn);
873}
874
88f0dc31
CF
875/* Try to derive posix filename from given handle. Return true if
876 the handle is associated with a cygwin tty. */
877static bool
2402700d
CF
878handle_to_fn (HANDLE h, char *posix_fn)
879{
ab5d348d 880 tmp_pathbuf tp;
1ffe3e67
CF
881 ULONG len = 0;
882 OBJECT_NAME_INFORMATION dummy_oni;
883 WCHAR *maxmatchdos = NULL;
884 int maxmatchlen = 0;
2402700d 885
1ffe3e67
CF
886 NtQueryObject (h, ObjectNameInformation, &dummy_oni, sizeof (dummy_oni), &len);
887 if (!len)
888 {
889 debug_printf ("NtQueryObject failed 1");
890 goto unknown;
891 }
2402700d 892
1ffe3e67 893 OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION *) alloca (len + sizeof (WCHAR));
ab5d348d 894 NTSTATUS res = NtQueryObject (h, ObjectNameInformation, ntfn, len, NULL);
cef69559 895
ee4388c4 896 if (!NT_SUCCESS (res))
2402700d 897 {
1ffe3e67
CF
898 debug_printf ("NtQueryObject failed 2");
899 goto unknown;
2402700d 900 }
2bb6b3e5
CF
901
902 // NT seems to do this on an unopened file
903 if (!ntfn->Name.Buffer)
904 {
905 debug_printf ("nt->Name.Buffer == NULL");
1ffe3e67 906 goto unknown;
2bb6b3e5
CF
907 }
908
1ffe3e67
CF
909 WCHAR *w32 = ntfn->Name.Buffer;
910 size_t w32len = ntfn->Name.Length / sizeof (WCHAR);
911 w32[w32len] = L'\0';
2402700d 912
1ffe3e67
CF
913 if (wcscasecmp (w32, DEV_NULL) == 0)
914 {
915 strcpy (posix_fn, "/dev/null");
88f0dc31 916 return false;
1ffe3e67 917 }
5bf785a0 918
1ffe3e67
CF
919 if (wcsncasecmp (w32, DEV_NAMED_PIPE, DEV_NAMED_PIPE_LEN) == 0)
920 {
921 w32 += DEV_NAMED_PIPE_LEN;
88f0dc31
CF
922 if (wcsncmp (w32, L"cygwin-", WCLEN (L"cygwin-")) != 0)
923 return false;
924 w32 += WCLEN (L"cygwin-");
925 bool istty = wcsncmp (w32, L"tty", WCLEN (L"tty")) == 0;
926 if (istty)
927 decode_tty (posix_fn, w32 + WCLEN (L"tty"));
928 else if (wcsncmp (w32, L"pipe", WCLEN (L"pipe")) == 0)
929 strcpy (posix_fn, "/dev/pipe");
930 return istty;
1ffe3e67 931 }
2402700d 932
1ffe3e67
CF
933
934 WCHAR fnbuf[64 * 1024];
935 if (wcsncasecmp (w32, DEVICE_PREFIX, DEVICE_PREFIX_LEN) != 0
936 || !QueryDosDeviceW (NULL, fnbuf, sizeof (fnbuf)))
937 {
938 sys_wcstombs (posix_fn, NT_MAX_PATH, w32, w32len);
88f0dc31 939 return false;
1ffe3e67
CF
940 }
941
942 for (WCHAR *s = fnbuf; *s; s = wcschr (s, '\0') + 1)
2402700d 943 {
1ffe3e67
CF
944 WCHAR device[NT_MAX_PATH];
945 if (!QueryDosDeviceW (s, device, sizeof (device)))
2402700d 946 continue;
1ffe3e67 947 if (wcschr (s, ':') == NULL)
2402700d 948 continue;
1ffe3e67 949 WCHAR *q = wcsrchr (device, ';');
37be5a67
CF
950 if (q)
951 {
1ffe3e67 952 WCHAR *r = wcschr (q, '\\');
37be5a67 953 if (r)
1ffe3e67 954 wcscpy (q, r + 1);
37be5a67 955 }
1ffe3e67
CF
956 int devlen = wcslen (device);
957 if (device[devlen - 1] == L'\\')
958 device[--devlen] = L'\0';
37be5a67
CF
959 if (devlen < maxmatchlen)
960 continue;
1ffe3e67
CF
961 if (wcsncmp (device, w32, devlen) != 0||
962 (w32[devlen] != L'\0' && w32[devlen] != L'\\'))
2402700d 963 continue;
37be5a67
CF
964 maxmatchlen = devlen;
965 maxmatchdos = s;
1ffe3e67 966 debug_printf ("current match '%W' = '%W'\n", s, device);
37be5a67
CF
967 }
968
37be5a67
CF
969 if (maxmatchlen)
970 {
1ffe3e67
CF
971 WCHAR *p = wcschr (w32 + DEVICE_PREFIX_LEN, L'\\');
972 size_t n = wcslen (maxmatchdos);
973 WCHAR ch;
974 if (!p)
975 ch = L'\0';
976 else
977 {
978 if (maxmatchdos[n - 1] == L'\\')
979 n--;
980 w32 += maxmatchlen - n;
981 ch = L'\\';
982 }
983 memcpy (w32, maxmatchdos, n * sizeof (WCHAR));
984 w32[n] = ch;
634a4140 985 }
1ffe3e67 986 else if (wcsncmp (w32, DEV_REMOTE, DEV_REMOTE_LEN) == 0)
ce006ffa 987 {
1ffe3e67
CF
988 w32 += DEV_REMOTE_LEN - 2;
989 *w32 = L'\\';
ce006ffa 990 debug_printf ("remote drive");
634a4140 991 }
1ffe3e67 992 else if (wcsncmp (w32, DEV_REMOTE1, DEV_REMOTE1_LEN) == 0)
634a4140 993 {
1ffe3e67
CF
994 w32 += DEV_REMOTE1_LEN - 2;
995 *w32 = L'\\';
634a4140 996 debug_printf ("remote drive");
ce006ffa
CF
997 }
998
1ffe3e67
CF
999 cygwin_conv_path (CCP_WIN_W_TO_POSIX | CCP_ABSOLUTE, w32, posix_fn,
1000 NT_MAX_PATH);
1001
1002 debug_printf ("derived path '%W', posix '%s'", w32, posix_fn);
88f0dc31 1003 return false;
2402700d 1004
1ffe3e67
CF
1005unknown:
1006 strcpy (posix_fn, unknown_file);
88f0dc31 1007 return false;
2402700d 1008}
This page took 0.396473 seconds and 5 git commands to generate.