]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/dtable.cc
Throughout, update copyrights to reflect dates which correspond to main-branch
[newlib-cygwin.git] / winsup / cygwin / dtable.cc
CommitLineData
9015e0fb 1/* dtable.cc: file descriptor support.
1fd5e000 2
bc837d22
CF
3 Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006,
4 2007, 2008, 2009, 2010, 2011, 2012 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 <stdlib.h>
16#include <stdio.h>
1fd5e000 17#include <unistd.h>
1ffe3e67 18#include <wchar.h>
1fd5e000 19
a1299ba5 20#define USE_SYS_TYPES_FD_SET
d0b178fe 21#include <winsock.h>
e2ebe117 22#include "pinfo.h"
9e2baf8d 23#include "cygerrno.h"
95a8465b 24#include "perprocess.h"
bccd5e0d 25#include "path.h"
7ac61736 26#include "fhandler.h"
b4fa8164 27#include "select.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)
c8a66289
CF
40static const char unknown_file[] = "some disk file";
41static const WCHAR DEV_NULL[] = L"\\Device\\Null";
019fc8d8 42static const WCHAR DEV_SOCKET[] = L"\\Device\\Afd";
1ffe3e67 43
c8a66289
CF
44static const WCHAR DEVICE_PREFIX[] = L"\\device\\";
45static const size_t DEVICE_PREFIX_LEN WCLEN (DEVICE_PREFIX);
1ffe3e67
CF
46
47static const WCHAR DEV_NAMED_PIPE[] = L"\\Device\\NamedPipe\\";
48static const size_t DEV_NAMED_PIPE_LEN = WCLEN (DEV_NAMED_PIPE);
dd76747b 49
1ffe3e67
CF
50static const WCHAR DEV_REMOTE[] = L"\\Device\\LanmanRedirector\\";
51static const size_t DEV_REMOTE_LEN = WCLEN (DEV_REMOTE);
52
53static const WCHAR DEV_REMOTE1[] = L"\\Device\\WinDfs\\Root\\";
54static const size_t DEV_REMOTE1_LEN = WCLEN (DEV_REMOTE1);
634a4140 55
1fd5e000
CF
56/* Set aside space for the table of fds */
57void
2d1d1eb1 58dtable_init ()
1fd5e000 59{
0381fec6 60 if (!cygheap->fdtab.size)
c729f227 61 cygheap->fdtab.extend (NOFILE_INCR);
1fd5e000
CF
62}
63
64void __stdcall
65set_std_handle (int fd)
66{
30fa1549 67 fhandler_base *fh = cygheap->fdtab[fd];
1fd5e000 68 if (fd == 0)
30fa1549 69 SetStdHandle (std_consts[fd], fh ? fh->get_handle () : NULL);
164a681c 70 else if (fd <= 2)
30fa1549 71 SetStdHandle (std_consts[fd], fh ? fh->get_output_handle () : NULL);
1fd5e000
CF
72}
73
74int
9015e0fb 75dtable::extend (int howmuch)
1fd5e000
CF
76{
77 int new_size = size + howmuch;
78 fhandler_base **newfds;
79
80 if (howmuch <= 0)
81 return 0;
82
29bca9bb 83 if (new_size > OPEN_MAX_MAX)
4d782b42
CF
84 {
85 set_errno (EMFILE);
86 return 0;
87 }
88
c729f227 89 /* Try to allocate more space for fd table. We can't call realloc ()
1fd5e000
CF
90 here to preserve old table if memory allocation fails */
91
b0e82b74 92 if (!(newfds = (fhandler_base **) ccalloc (HEAP_ARGV, new_size, sizeof newfds[0])))
1fd5e000
CF
93 {
94 debug_printf ("calloc failed");
4d782b42 95 set_errno (ENOMEM);
1fd5e000
CF
96 return 0;
97 }
98 if (fds)
99 {
4d782b42 100 memcpy (newfds, fds, size * sizeof (fds[0]));
3301015b 101 cfree (fds);
1fd5e000
CF
102 }
103
104 size = new_size;
105 fds = newfds;
41f42725 106 debug_printf ("size %d, fds %p", size, fds);
1fd5e000
CF
107 return 1;
108}
109
083abe54
CF
110void
111dtable::get_debugger_info ()
112{
3c4f2024
CF
113 extern bool jit_debug;
114 if (!jit_debug && being_debugged ())
083abe54 115 {
23771fa1 116 char std[3][sizeof ("/dev/ptyNNNN")];
083abe54
CF
117 std[0][0] = std[1][0] = std [2][0] = '\0';
118 char buf[sizeof ("cYgstd %x") + 32];
119 sprintf (buf, "cYgstd %x %x %x", (unsigned) &std, sizeof (std[0]), 3);
120 OutputDebugString (buf);
121 for (int i = 0; i < 3; i++)
122 if (std[i][0])
123 {
083abe54 124 HANDLE h = GetStdHandle (std_consts[i]);
7ac61736 125 fhandler_base *fh = build_fh_name (std[i]);
083abe54
CF
126 if (!fh)
127 continue;
7ac61736 128 fds[i] = fh;
061095b5
CV
129 if (!fh->open ((i ? (i == 2 ? O_RDWR : O_WRONLY) : O_RDONLY)
130 | O_BINARY, 0777))
083abe54
CF
131 release (i);
132 else
8f19b4b6
CV
133 {
134 CloseHandle (h);
135 /* Copy to Windows' idea of a standard handle, otherwise
136 we have invalid standard handles when calling Windows
137 functions (small_printf and strace might suffer, too). */
138 SetStdHandle (std_consts[i], i ? fh->get_output_handle ()
139 : fh->get_handle ());
140 }
083abe54
CF
141 }
142 }
143}
144
1fd5e000 145/* Initialize the file descriptor/handle mapping table.
10dedaaa
CF
146 This function should only be called when a cygwin function is invoked
147 by a non-cygwin function, i.e., it should only happen very rarely. */
1fd5e000
CF
148
149void
083abe54 150dtable::stdio_init ()
1fd5e000 151{
8cb359d9 152 if (myself->cygstarted || ISSTATE (myself, PID_CYGPARENT))
3eb92a58 153 {
44d2fc0a 154 tty_min *t = cygwin_shared->tty.get_cttyp ();
a345dc55 155 if (t && t->is_console)
f09acf77 156 init_console_handler (true);
3eb92a58
CF
157 return;
158 }
1fd5e000 159
083abe54
CF
160 HANDLE in = GetStdHandle (STD_INPUT_HANDLE);
161 HANDLE out = GetStdHandle (STD_OUTPUT_HANDLE);
162 HANDLE err = GetStdHandle (STD_ERROR_HANDLE);
1fd5e000 163
54030e21 164 init_std_file_from_handle (0, in);
083abe54
CF
165
166 /* STD_ERROR_HANDLE has been observed to be the same as
167 STD_OUTPUT_HANDLE. We need separate handles (e.g. using pipes
168 to pass data from child to parent). */
edf5a5bd
CV
169 /* CV 2008-10-17: Under debugger control, std fd's have been potentially
170 initialized in dtable::get_debugger_info (). In this case
171 init_std_file_from_handle is a no-op, so, even if out == err we don't
172 want to duplicate the handle since it will be unused. */
8f19b4b6 173 if (out == err && (!being_debugged () || not_open (2)))
083abe54
CF
174 {
175 /* Since this code is not invoked for forked tasks, we don't have
176 to worry about the close-on-exec flag here. */
7bdbf062
CV
177 if (!DuplicateHandle (GetCurrentProcess (), out,
178 GetCurrentProcess (), &err,
179 0, TRUE, DUPLICATE_SAME_ACCESS))
1fd5e000 180 {
083abe54
CF
181 /* If that fails, do this as a fall back. */
182 err = out;
7bdbf062 183 system_printf ("couldn't make stderr distinct from stdout, %E");
1fd5e000 184 }
1fd5e000 185 }
083abe54 186
54030e21
CF
187 init_std_file_from_handle (1, out);
188 init_std_file_from_handle (2, err);
1fd5e000
CF
189}
190
8e10c431
CF
191const int dtable::initial_archetype_size;
192
193fhandler_base *
194dtable::find_archetype (device& dev)
195{
196 for (unsigned i = 0; i < farchetype; i++)
44d2fc0a 197 if (archetypes[i]->get_device () == (DWORD) dev)
8e10c431
CF
198 return archetypes[i];
199 return NULL;
200}
201
202fhandler_base **
203dtable::add_archetype ()
204{
205 if (farchetype++ >= narchetypes)
634a4140 206 archetypes = (fhandler_base **) crealloc_abort (archetypes, (narchetypes += initial_archetype_size) * sizeof archetypes[0]);
8e10c431
CF
207 return archetypes + farchetype - 1;
208}
209
210void
211dtable::delete_archetype (fhandler_base *fh)
212{
8ed5c9b6 213 for (unsigned i = 0; i < farchetype; i++)
8e10c431
CF
214 if (fh == archetypes[i])
215 {
6ae28c22
CF
216 debug_printf ("deleting element %d for %s(%d/%d)", i, fh->get_name (),
217 fh->dev ().get_major (), fh->dev ().get_minor ());
8e10c431
CF
218 if (i < --farchetype)
219 archetypes[i] = archetypes[farchetype];
220 break;
221 }
222
223 delete fh;
224}
225
1fd5e000 226int
9015e0fb 227dtable::find_unused_handle (int start)
1fd5e000 228{
1fd5e000
CF
229 do
230 {
e773b7cf 231 for (size_t i = start; i < size; i++)
91892f50
CF
232 /* See if open -- no need for overhead of not_open */
233 if (fds[i] == NULL)
1fd5e000
CF
234 return i;
235 }
236 while (extend (NOFILE_INCR));
237 return -1;
238}
239
0646a508 240void
9015e0fb 241dtable::release (int fd)
1fd5e000 242{
0646a508
CF
243 if (fds[fd]->need_fixup_before ())
244 dec_need_fixup_before ();
3143cb7c 245 fds[fd]->dec_refcnt ();
0646a508 246 fds[fd] = NULL;
30fa1549
CF
247 if (fd <= 2)
248 set_std_handle (fd);
1fd5e000
CF
249}
250
45586380 251extern "C" int
ebd645e7
CF
252cygwin_attach_handle_to_fd (char *name, int fd, HANDLE handle, mode_t bin,
253 DWORD myaccess)
254{
255 if (fd == -1)
256 fd = cygheap->fdtab.find_unused_handle ();
7ac61736 257 fhandler_base *fh = build_fh_name (name);
e5b7e4d1
CF
258 if (!fh)
259 return -1;
7ac61736 260 cygheap->fdtab[fd] = fh;
3143cb7c 261 cygheap->fdtab[fd]->inc_refcnt ();
7ac61736 262 fh->init (handle, myaccess, bin ?: fh->pc_binmode ());
ebd645e7
CF
263 return fd;
264}
265
1fd5e000 266void
54030e21 267dtable::init_std_file_from_handle (int fd, HANDLE handle)
1fd5e000 268{
5e7c84e5 269 tmp_pathbuf tp;
ebd645e7 270 CONSOLE_SCREEN_BUFFER_INFO buf;
ebd645e7 271 DCB dcb;
abb58a6d 272 unsigned bin = O_BINARY;
44d2fc0a 273 device dev = {};
ebd645e7
CF
274
275 first_fd_for_open = 0;
1ac6d1a1 276
083abe54
CF
277 if (!not_open (fd))
278 return;
279
cef69559 280 SetLastError (0);
1ffe3e67 281 DWORD access = 0;
cef69559 282 DWORD ft = GetFileType (handle);
5e7c84e5 283 char *name = tp.c_get ();
1ffe3e67 284 name[0] = '\0';
88f0dc31
CF
285 if (ft == FILE_TYPE_UNKNOWN && GetLastError () == ERROR_INVALID_HANDLE)
286 /* can't figure out what this is */;
287 else if (ft == FILE_TYPE_PIPE)
1fd5e000 288 {
019fc8d8
CV
289 int rcv = 0, len = sizeof (int);
290
88f0dc31 291 if (handle_to_fn (handle, name))
02a33ea7 292 dev.parse (name);
019fc8d8 293 else if (strcmp (name, ":sock:") == 0
02dbd9ae
CV
294 /* NtQueryObject returns an error when called on an LSP socket
295 handle. While fdsock now tries to fetch the underlying
296 base socket, this only works on Vista and later. */
019fc8d8
CV
297 || (strcmp (name, unknown_file) == 0
298 && !::getsockopt ((SOCKET) handle, SOL_SOCKET, SO_RCVBUF,
299 (char *) &rcv, &len)))
300 {
301 /* socket */
302 dev = *tcp_dev;
303 name[0] = '\0';
304 }
1ffe3e67
CF
305 else if (fd == 0)
306 dev = *piper_dev;
4ab6034f 307 else
1ffe3e67 308 dev = *pipew_dev;
4ab6034f 309 }
92ddb742 310 else if (GetConsoleScreenBufferInfo (handle, &buf)
b86f999a 311 || GetNumberOfConsoleInputEvents (handle, (DWORD *) &buf))
1ffe3e67 312 {
92ddb742 313 /* Console I/O */
c75b5b2d 314 if (myself->ctty > 0)
44d2fc0a 315 dev.parse (myself->ctty);
1ffe3e67 316 else
6ae28c22
CF
317 {
318 dev.parse (FH_CONSOLE);
319 CloseHandle (handle);
320 handle = INVALID_HANDLE_VALUE;
321 }
1ffe3e67 322 }
1ffe3e67 323 else if (GetCommState (handle, &dcb))
92ddb742
CF
324 /* FIXME: Not right - assumes ttyS0 */
325 dev.parse (DEV_SERIAL_MAJOR, 0);
1ffe3e67
CF
326 else
327 /* Try to figure it out from context - probably a disk file */
328 handle_to_fn (handle, name);
cef69559 329
1ffe3e67 330 if (!name[0] && !dev)
cef69559
CF
331 fds[fd] = NULL;
332 else
4ab6034f 333 {
7ac61736
CF
334 fhandler_base *fh;
335
336 if (dev)
1ffe3e67 337 fh = build_fh_dev (dev);
7ac61736
CF
338 else
339 fh = build_fh_name (name);
340
e5b7e4d1
CF
341 if (!fh)
342 return;
343
1ffe3e67 344 if (name[0])
abb58a6d 345 {
634a4140
CF
346 bin = fh->pc_binmode ();
347 if (!bin)
348 {
349 bin = fh->get_default_fmode (O_RDWR);
350 if (!bin && dev)
351 bin = O_BINARY;
352 }
abb58a6d 353 }
9655ff26 354
02a33ea7
CV
355 IO_STATUS_BLOCK io;
356 FILE_ACCESS_INFORMATION fai;
6ae28c22 357 int openflags = O_BINARY;
02a33ea7
CV
358
359 /* Console windows are not kernel objects, so the access mask returned
179bee57
CV
360 by NtQueryInformationFile is meaningless. CMD always hands down
361 stdin handles as R/O handles, but our tty slave sides are R/W. */
06f46dc3 362 if (fh->is_tty ())
6ae28c22
CF
363 {
364 openflags |= O_RDWR;
365 access |= GENERIC_READ | GENERIC_WRITE;
366 }
367 else if (!iscons_dev (dev)
368 && NT_SUCCESS (NtQueryInformationFile (handle, &io, &fai,
369 sizeof fai,
370 FileAccessInformation)))
02a33ea7 371 {
02a33ea7 372 if (fai.AccessFlags & FILE_WRITE_DATA)
6ae28c22
CF
373 {
374 openflags |= O_WRONLY;
375 access |= GENERIC_WRITE;
376 }
377 if (fai.AccessFlags & FILE_READ_DATA)
378 {
379 openflags |= openflags & O_WRONLY ? O_RDWR : O_RDONLY;
380 access |= GENERIC_READ;
381 }
02a33ea7 382 }
4248960e 383 else if (fd == 0)
6ae28c22
CF
384 {
385 openflags |= O_RDONLY;
386 access |= GENERIC_READ;
387 }
70300fdb 388 else
6ae28c22
CF
389 {
390 openflags |= O_WRONLY;
391 access |= GENERIC_WRITE; /* Should be rdwr for stderr but not sure that's
392 possible for some versions of handles */
393 }
394 if (!fh->init (handle, access, bin))
3c4f2024 395 api_fatal ("couldn't initialize fd %d for %s", fd, fh->get_name ());
1ae0a7c5 396
6ae28c22
CF
397 fh->open_setup (openflags);
398 fh->usecount = 0;
1ae0a7c5 399 cygheap->fdtab[fd] = fh;
3143cb7c 400 cygheap->fdtab[fd]->inc_refcnt ();
1ae0a7c5 401 set_std_handle (fd);
cef69559 402 paranoid_printf ("fd %d, handle %p", fd, handle);
1fd5e000 403 }
1fd5e000
CF
404}
405
3d938be6
CV
406#define cnew(name, ...) \
407 ({ \
408 void* ptr = (void*) ccalloc (HEAP_FHANDLER, 1, sizeof (name)); \
c38da4ee 409 ptr ? new (ptr) name (__VA_ARGS__) : NULL; \
3d938be6 410 })
1ffe3e67 411
23771fa1
CF
412#define cnew_no_ctor(name, ...) \
413 ({ \
414 void* ptr = (void*) ccalloc (HEAP_FHANDLER, 1, sizeof (name)); \
415 ptr ? new (ptr) name (ptr) : NULL; \
416 })
417
4ee93264
CV
418fhandler_base *
419build_fh_name (const char *name, unsigned opt, suffix_info *si)
1fd5e000 420{
4ee93264 421 path_conv pc (name, opt | PC_NULLEMPTY | PC_POSIX, si);
4ab6034f
CF
422 if (pc.error)
423 {
3d938be6
CV
424 fhandler_base *fh = cnew (fhandler_nodevice);
425 if (fh)
6a7bea70
CF
426 fh->set_error (pc.error);
427 set_errno (fh ? pc.error : EMFILE);
e00700cd 428 return fh;
1fd5e000
CF
429 }
430
7ac61736 431 return build_fh_pc (pc);
1fd5e000
CF
432}
433
434fhandler_base *
7ac61736 435build_fh_dev (const device& dev, const char *unix_name)
ff938546 436{
7ac61736 437 path_conv pc (dev);
7ac61736 438 if (unix_name)
a9e9da89 439 pc.set_normalized_path (unix_name);
7ac61736 440 else
a9e9da89 441 pc.set_normalized_path (dev.name);
7ac61736 442 return build_fh_pc (pc);
ff938546
CF
443}
444
6a7bea70 445#define fh_unset ((fhandler_base *) 1)
6ae28c22
CF
446static device last_tty_dev;
447#define fh_last_tty_dev ((fhandler_termios *) cygheap->fdtab.find_archetype (last_tty_dev))
23771fa1 448
92ddb742 449static fhandler_base *
23771fa1 450fh_alloc (path_conv& pc)
1fd5e000 451{
6a7bea70 452 fhandler_base *fh = fh_unset;
23771fa1 453 fhandler_base *fhraw = NULL;
1fd5e000 454
23771fa1 455 switch (pc.dev.get_major ())
7b02cb30 456 {
38d732a1 457 case DEV_PTYS_MAJOR:
23771fa1
CF
458 fh = cnew (fhandler_pty_slave, pc.dev.get_minor ());
459 break;
38d732a1 460 case DEV_PTYM_MAJOR:
23771fa1 461 fh = cnew (fhandler_pty_master, pc.dev.get_minor ());
7b02cb30 462 break;
7b02cb30
CF
463 case DEV_FLOPPY_MAJOR:
464 case DEV_CDROM_MAJOR:
465 case DEV_SD_MAJOR:
cc9dbc90 466 case DEV_SD1_MAJOR:
9e3f289f
CV
467 case DEV_SD2_MAJOR:
468 case DEV_SD3_MAJOR:
469 case DEV_SD4_MAJOR:
470 case DEV_SD5_MAJOR:
471 case DEV_SD6_MAJOR:
472 case DEV_SD7_MAJOR:
3d938be6 473 fh = cnew (fhandler_dev_floppy);
7b02cb30
CF
474 break;
475 case DEV_TAPE_MAJOR:
3d938be6 476 fh = cnew (fhandler_dev_tape);
7b02cb30
CF
477 break;
478 case DEV_SERIAL_MAJOR:
3d938be6 479 fh = cnew (fhandler_serial);
7b02cb30 480 break;
44d2fc0a 481 case DEV_CONS_MAJOR:
23771fa1 482 fh = cnew (fhandler_console, pc.dev);
44d2fc0a 483 break;
7b02cb30 484 default:
6c95669d 485 switch ((DWORD) pc.dev)
7b02cb30
CF
486 {
487 case FH_CONSOLE:
488 case FH_CONIN:
489 case FH_CONOUT:
23771fa1 490 fh = cnew (fhandler_console, pc.dev);
7b02cb30 491 break;
23771fa1
CF
492 case FH_PTMX:
493 if (pc.isopen ())
494 fh = cnew (fhandler_pty_master, -1);
495 else
1b23b30b 496 fhraw = cnew_no_ctor (fhandler_pty_master, -1);
7b02cb30
CF
497 break;
498 case FH_WINDOWS:
3d938be6 499 fh = cnew (fhandler_windows);
7b02cb30
CF
500 break;
501 case FH_FIFO:
3d938be6 502 fh = cnew (fhandler_fifo);
7b02cb30
CF
503 break;
504 case FH_PIPE:
505 case FH_PIPER:
506 case FH_PIPEW:
3d938be6 507 fh = cnew (fhandler_pipe);
7b02cb30
CF
508 break;
509 case FH_TCP:
510 case FH_UDP:
511 case FH_ICMP:
512 case FH_UNIX:
513 case FH_STREAM:
514 case FH_DGRAM:
3d938be6 515 fh = cnew (fhandler_socket);
7b02cb30
CF
516 break;
517 case FH_FS:
3d938be6 518 fh = cnew (fhandler_disk_file);
7b02cb30
CF
519 break;
520 case FH_NULL:
3d938be6 521 fh = cnew (fhandler_dev_null);
7b02cb30
CF
522 break;
523 case FH_ZERO:
524 case FH_FULL:
3d938be6 525 fh = cnew (fhandler_dev_zero);
7b02cb30
CF
526 break;
527 case FH_RANDOM:
528 case FH_URANDOM:
3d938be6 529 fh = cnew (fhandler_dev_random);
7b02cb30
CF
530 break;
531 case FH_MEM:
73447abb 532 case FH_KMEM:
7b02cb30 533 case FH_PORT:
3d938be6 534 fh = cnew (fhandler_dev_mem);
7b02cb30
CF
535 break;
536 case FH_CLIPBOARD:
3d938be6 537 fh = cnew (fhandler_dev_clipboard);
7b02cb30
CF
538 break;
539 case FH_OSS_DSP:
3d938be6 540 fh = cnew (fhandler_dev_dsp);
7b02cb30
CF
541 break;
542 case FH_PROC:
3d938be6 543 fh = cnew (fhandler_proc);
7b02cb30
CF
544 break;
545 case FH_REGISTRY:
3d938be6 546 fh = cnew (fhandler_registry);
7b02cb30
CF
547 break;
548 case FH_PROCESS:
38f50ae4 549 case FH_PROCESSFD:
3d938be6 550 fh = cnew (fhandler_process);
7b02cb30 551 break;
96d7dee2 552 case FH_PROCNET:
3d938be6 553 fh = cnew (fhandler_procnet);
96d7dee2 554 break;
43f65cdd 555 case FH_PROCSYS:
3d938be6 556 fh = cnew (fhandler_procsys);
43f65cdd 557 break;
d68288f6 558 case FH_PROCSYSVIPC:
3d938be6 559 fh = cnew (fhandler_procsysvipc);
d68288f6 560 break;
7b02cb30 561 case FH_NETDRIVE:
3d938be6 562 fh = cnew (fhandler_netdrive);
7b02cb30 563 break;
1f312200
CV
564 case FH_DEV:
565 fh = cnew (fhandler_dev);
566 break;
f7c8c454
CV
567 case FH_CYGDRIVE:
568 fh = cnew (fhandler_cygdrive);
569 break;
7b02cb30 570 case FH_TTY:
23771fa1 571 if (!pc.isopen ())
38d732a1 572 {
1b23b30b 573 fhraw = cnew_no_ctor (fhandler_console, -1);
6ae28c22
CF
574 debug_printf ("not called from open for /dev/tty");
575 }
576 else if (myself->ctty <= 0 && last_tty_dev
577 && !myself->set_ctty (fh_last_tty_dev, 0))
578 debug_printf ("no /dev/tty assigned");
579 else if (myself->ctty > 0)
580 {
581 debug_printf ("determining /dev/tty assignment for ctty %p", myself->ctty);
38d732a1
CF
582 if (iscons_dev (myself->ctty))
583 fh = cnew (fhandler_console, pc.dev);
584 else
585 fh = cnew (fhandler_pty_slave, myself->ctty);
6ae28c22
CF
586 if (fh->dev () != FH_NADA)
587 fh->set_name ("/dev/tty");
38d732a1 588 }
23771fa1 589 break;
7b02cb30 590 case FH_KMSG:
3d938be6 591 fh = cnew (fhandler_mailslot);
7b02cb30 592 break;
0e1ba888 593 }
7b02cb30 594 }
7ac61736 595
23771fa1
CF
596 /* If `fhraw' is set that means that this fhandler is just a dummy
597 set up for stat(). Mock it up for use by stat without actually
598 trying to do any real initialization. */
599 if (fhraw)
600 {
601 fh = fhraw;
602 fh->set_name (pc);
603 if (fh->use_archetype ())
604 fh->archetype = fh;
605 }
2e82c935 606 if (fh == fh_unset)
3d938be6 607 fh = cnew (fhandler_nodevice);
23771fa1
CF
608 else if (fh->dev () == FH_ERROR)
609 {
8b4bd082 610 if (!pc.isopen () && pc.dev.isfs ())
080f275b 611 fh->dev () = pc.dev; /* Special case: This file actually exists on
8b4bd082
CF
612 disk and we're not trying to open it so just
613 return the info from pc. */
080f275b
CF
614 else
615 {
616 delete fh;
617 fh = NULL;
618 }
23771fa1 619 }
92ddb742
CF
620 return fh;
621}
622
623fhandler_base *
6ae28c22 624build_fh_pc (path_conv& pc)
92ddb742 625{
23771fa1 626 fhandler_base *fh = fh_alloc (pc);
2e82c935 627
1c1b04b8 628 if (!fh)
9e1fd6bc 629 {
23771fa1 630 set_errno (ENXIO);
9e1fd6bc
CV
631 goto out;
632 }
7ac61736 633
92ddb742 634 if (!fh->use_archetype ())
6ae28c22 635 fh->set_name (pc);
92ddb742 636 else if ((fh->archetype = cygheap->fdtab.find_archetype (fh->dev ())))
6ae28c22
CF
637 {
638 debug_printf ("found an archetype for %s(%d/%d) io_handle %p", fh->get_name (), fh->dev ().get_major (), fh->dev ().get_minor (),
639 fh->archetype->get_io_handle ());
640 if (!fh->get_name ())
641 fh->set_name (fh->archetype->dev ().name);
642 }
643 else if (cygwin_finished_initializing && !pc.isopen ())
644 fh->set_name (pc);
92ddb742
CF
645 else
646 {
6ae28c22
CF
647 if (!fh->get_name ())
648 fh->set_name (fh->dev ().name);
23771fa1
CF
649 fh->archetype = fh->clone ();
650 debug_printf ("created an archetype (%p) for %s(%d/%d)", fh->archetype, fh->get_name (), fh->dev ().get_major (), fh->dev ().get_minor ());
92ddb742
CF
651 fh->archetype->archetype = NULL;
652 *cygheap->fdtab.add_archetype () = fh->archetype;
653 }
654
6ae28c22
CF
655
656 /* Keep track of the last tty-like thing opened. We could potentially want
657 to open it if /dev/tty is referenced. */
23771fa1 658 if (myself->ctty > 0 || !fh->is_tty () || !pc.isctty_capable ())
6ae28c22
CF
659 last_tty_dev = FH_NADA;
660 else
661 last_tty_dev = fh->dev ();
23771fa1 662
c3a9063f 663out:
6ae28c22 664 debug_printf ("fh %p, dev %p", fh, fh ? (DWORD) fh->dev () : 0);
7ac61736 665 return fh;
1fd5e000
CF
666}
667
668fhandler_base *
e70fdfb9 669dtable::dup_worker (fhandler_base *oldfh, int flags)
1fd5e000 670{
1c1b04b8
CV
671 /* Don't call set_name in build_fh_pc. It will be called in
672 fhandler_base::operator= below. Calling it twice will result
673 in double allocation. */
23771fa1 674 fhandler_base *newfh = oldfh->clone ();
6a7bea70
CF
675 if (!newfh)
676 debug_printf ("build_fh_pc failed");
677 else
1fd5e000 678 {
92ddb742
CF
679 if (!oldfh->archetype)
680 newfh->set_io_handle (NULL);
23771fa1 681
5a0d1edb 682 newfh->pc.reset_conv_handle ();
23771fa1 683 if (oldfh->dup (newfh, flags))
6a7bea70 684 {
1c1b04b8
CV
685 delete newfh;
686 newfh = NULL;
6a7bea70
CF
687 debug_printf ("oldfh->dup failed");
688 }
689 else
690 {
8fa8b3a3
CF
691 /* Don't increment refcnt here since we don't know if this is a
692 allocated fd. So we leave this chore to the caller. */
693
92ddb742
CF
694 newfh->usecount = 0;
695 newfh->archetype_usecount (1);
8fa8b3a3 696
e70fdfb9 697 /* The O_CLOEXEC flag enforces close-on-exec behaviour. */
92ddb742 698 newfh->set_close_on_exec (!!(flags & O_CLOEXEC));
4eb5175d
CF
699 debug_printf ("duped '%s' old %p, new %p", oldfh->get_name (),
700 oldfh->get_io_handle (), newfh->get_io_handle ());
6a7bea70 701 }
1fd5e000 702 }
1fd5e000
CF
703 return newfh;
704}
705
706int
e70fdfb9 707dtable::dup3 (int oldfd, int newfd, int flags)
1fd5e000
CF
708{
709 int res = -1;
710 fhandler_base *newfh = NULL; // = NULL to avoid an incorrect warning
711
712 MALLOC_CHECK;
e70fdfb9 713 debug_printf ("dup3 (%d, %d, %p)", oldfd, newfd, flags);
2d1d1eb1 714 lock ();
3143cb7c 715 bool do_unlock = true;
b9c61a8d
CF
716 bool unlock_on_return;
717 if (!(flags & O_EXCL))
718 unlock_on_return = true; /* Relinquish lock on return */
719 else
720 {
721 flags &= ~O_EXCL;
722 unlock_on_return = false; /* Return with lock set on success */
723 }
1fd5e000
CF
724
725 if (not_open (oldfd))
726 {
5a449743 727 syscall_printf ("fd %d not open", oldfd);
1fd5e000
CF
728 set_errno (EBADF);
729 goto done;
730 }
f6187d46 731 if (newfd >= OPEN_MAX_MAX || newfd < 0)
4c78be52
CF
732 {
733 syscall_printf ("new fd out of bounds: %d", newfd);
734 set_errno (EBADF);
735 goto done;
736 }
e70fdfb9 737 if ((flags & ~O_CLOEXEC) != 0)
1fd5e000 738 {
e70fdfb9
CV
739 syscall_printf ("invalid flags value %x", flags);
740 set_errno (EINVAL);
741 return -1;
1fd5e000
CF
742 }
743
23771fa1
CF
744 /* This is a temporary kludge until all utilities can catch up with
745 a change in behavior that implements linux functionality: opening
746 a tty should not automatically cause it to become the controlling
747 tty for the process. */
748 if (newfd > 2)
749 flags |= O_NOCTTY;
750
e70fdfb9 751 if ((newfh = dup_worker (fds[oldfd], flags)) == NULL)
1fd5e000
CF
752 {
753 res = -1;
754 goto done;
755 }
756
a9934559
CF
757 debug_printf ("newfh->io_handle %p, oldfh->io_handle %p, new win32_name %p, old win32_name %p",
758 newfh->get_io_handle (), fds[oldfd]->get_io_handle (), newfh->get_win32_name (), fds[oldfd]->get_win32_name ());
b0e82b74 759
4c78be52 760 if (!not_open (newfd))
5ec14fe4 761 close (newfd);
8fa8b3a3
CF
762 else if ((size_t) newfd > size
763 && find_unused_handle (newfd) < 0)
764 /* couldn't extend fdtab */
5a449743 765 {
4c78be52
CF
766 newfh->close ();
767 res = -1;
5a449743
CF
768 goto done;
769 }
b0e82b74 770
1fd5e000 771 fds[newfd] = newfh;
dd4f0b23 772
1fd5e000
CF
773 if ((res = newfd) <= 2)
774 set_std_handle (res);
b9c61a8d 775 do_unlock = unlock_on_return;
1fd5e000 776
1fd5e000 777done:
4c78be52 778 MALLOC_CHECK;
3143cb7c
CF
779 if (do_unlock)
780 unlock ();
b9aa8149 781 syscall_printf ("%R = dup3(%d, %d, %p)", res, oldfd, newfd, flags);
1fd5e000
CF
782
783 return res;
784}
785
b4fa8164
CF
786bool
787dtable::select_read (int fd, select_stuff *ss)
1fd5e000 788{
b0e82b74 789 if (not_open (fd))
1fd5e000
CF
790 {
791 set_errno (EBADF);
b4fa8164 792 return false;
1fd5e000 793 }
b0e82b74 794 fhandler_base *fh = fds[fd];
b4fa8164 795 select_record *s = fh->select_read (ss);
1fd5e000 796 s->fd = fd;
c7ef20e7
CF
797 if (!s->fh)
798 s->fh = fh;
169c465a 799 s->thread_errno = 0;
1fd5e000 800 debug_printf ("%s fd %d", fh->get_name (), fd);
b4fa8164 801 return true;
1fd5e000
CF
802}
803
b4fa8164
CF
804bool
805dtable::select_write (int fd, select_stuff *ss)
1fd5e000 806{
b0e82b74 807 if (not_open (fd))
1fd5e000
CF
808 {
809 set_errno (EBADF);
810 return NULL;
811 }
b0e82b74 812 fhandler_base *fh = fds[fd];
b4fa8164 813 select_record *s = fh->select_write (ss);
1fd5e000
CF
814 s->fd = fd;
815 s->fh = fh;
169c465a 816 s->thread_errno = 0;
106e3acf 817 debug_printf ("%s fd %d", fh->get_name (), fd);
b4fa8164 818 return true;
1fd5e000
CF
819}
820
b4fa8164
CF
821bool
822dtable::select_except (int fd, select_stuff *ss)
1fd5e000 823{
b0e82b74 824 if (not_open (fd))
1fd5e000
CF
825 {
826 set_errno (EBADF);
827 return NULL;
828 }
b0e82b74 829 fhandler_base *fh = fds[fd];
b4fa8164 830 select_record *s = fh->select_except (ss);
1fd5e000
CF
831 s->fd = fd;
832 s->fh = fh;
169c465a 833 s->thread_errno = 0;
1fd5e000 834 debug_printf ("%s fd %d", fh->get_name (), fd);
b4fa8164 835 return true;
1fd5e000
CF
836}
837
c16548b2
CF
838void
839dtable::move_fd (int from, int to)
840{
841 // close (to); /* It is assumed that this is close-on-exec */
842 fds[to] = fds[from];
843 fds[from] = NULL;
844}
845
fef1edbc
CF
846void
847dtable::set_file_pointers_for_exec ()
848{
cce64750
CV
849/* This is not POSIX-compliant so the function is only called for
850 non-Cygwin processes. */
ad4e943f 851 LONG off_high = 0;
2d1d1eb1 852 lock ();
fef1edbc
CF
853 fhandler_base *fh;
854 for (size_t i = 0; i < size; i++)
855 if ((fh = fds[i]) != NULL && fh->get_flags () & O_APPEND)
ad4e943f 856 SetFilePointer (fh->get_handle (), 0, &off_high, FILE_END);
2d1d1eb1 857 unlock ();
fef1edbc
CF
858}
859
881beea8
CF
860void
861dtable::fixup_close (size_t i, fhandler_base *fh)
862{
863 if (fh->archetype)
864 {
865 debug_printf ("closing fd %d since it is an archetype", i);
866 fh->close_with_arch ();
867 }
868 release (i);
869}
870
b0e82b74 871void
52806019 872dtable::fixup_after_exec ()
1fd5e000 873{
b0e82b74 874 first_fd_for_open = 0;
2e78b61d 875 fhandler_base *fh;
b0e82b74 876 for (size_t i = 0; i < size; i++)
2e78b61d 877 if ((fh = fds[i]) != NULL)
4f7ac76a 878 {
2e78b61d 879 fh->clear_readahead ();
59297e04 880 fh->fixup_after_exec ();
881beea8
CF
881 /* Close the handle if it's close-on-exec or if an error was detected
882 (typically with opening a console in a gui app) by fixup_after_exec.
883 */
55dcba98 884 if (fh->close_on_exec () || (!fh->nohandle () && !fh->get_io_handle ()))
881beea8 885 fixup_close (i, fh);
421ba492
CF
886 else if (fh->get_popen_pid ())
887 close (i);
59297e04
CF
888 else if (i == 0)
889 SetStdHandle (std_consts[i], fh->get_io_handle ());
890 else if (i <= 2)
891 SetStdHandle (std_consts[i], fh->get_output_handle ());
4f7ac76a 892 }
1fd5e000
CF
893}
894
895void
9015e0fb 896dtable::fixup_after_fork (HANDLE parent)
1fd5e000 897{
b0e82b74 898 fhandler_base *fh;
1fd5e000 899 for (size_t i = 0; i < size; i++)
b0e82b74 900 if ((fh = fds[i]) != NULL)
1fd5e000 901 {
56551a9b 902 if (fh->close_on_exec () || fh->need_fork_fixup ())
1fd5e000 903 {
c729f227 904 debug_printf ("fd %d (%s)", i, fh->get_name ());
1fd5e000 905 fh->fixup_after_fork (parent);
55dcba98 906 if (!fh->nohandle () && !fh->get_io_handle ())
881beea8
CF
907 {
908 /* This should actually never happen but it's here to make sure
909 we don't crash due to access of an unopened file handle. */
910 fixup_close (i, fh);
911 continue;
912 }
1fd5e000 913 }
f3acbe3e
CF
914 if (i == 0)
915 SetStdHandle (std_consts[i], fh->get_io_handle ());
916 else if (i <= 2)
917 SetStdHandle (std_consts[i], fh->get_output_handle ());
1fd5e000 918 }
1fd5e000
CF
919}
920
88f0dc31
CF
921static void
922decode_tty (char *buf, WCHAR *w32)
1ffe3e67
CF
923{
924 int ttyn = wcstol (w32, NULL, 10);
92601445 925 __ptsname (buf, ttyn);
1ffe3e67
CF
926}
927
88f0dc31
CF
928/* Try to derive posix filename from given handle. Return true if
929 the handle is associated with a cygwin tty. */
930static bool
2402700d
CF
931handle_to_fn (HANDLE h, char *posix_fn)
932{
ab5d348d 933 tmp_pathbuf tp;
1ffe3e67 934 ULONG len = 0;
1ffe3e67 935 WCHAR *maxmatchdos = NULL;
5e7c84e5 936 PWCHAR device = tp.w_get ();
1ffe3e67 937 int maxmatchlen = 0;
019fc8d8
CV
938 OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION *) tp.w_get ();
939
940 NTSTATUS status = NtQueryObject (h, ObjectNameInformation, ntfn, 65536, &len);
941 if (!NT_SUCCESS (status))
942 debug_printf ("NtQueryObject failed, %p", status);
943 // NT seems to do this on an unopened file
944 else if (!ntfn->Name.Buffer)
945 debug_printf ("nt->Name.Buffer == NULL");
7b9e380f 946 else
1ffe3e67 947 {
019fc8d8
CV
948 WCHAR *w32 = ntfn->Name.Buffer;
949 size_t w32len = ntfn->Name.Length / sizeof (WCHAR);
950 w32[w32len] = L'\0';
2bb6b3e5 951
019fc8d8
CV
952 if (wcscasecmp (w32, DEV_NULL) == 0)
953 {
954 strcpy (posix_fn, "/dev/null");
955 return false;
956 }
2bb6b3e5 957
019fc8d8
CV
958 if (wcscasecmp (w32, DEV_SOCKET) == 0)
959 {
960 strcpy (posix_fn, ":sock:");
961 return false;
962 }
2402700d 963
019fc8d8
CV
964 if (wcsncasecmp (w32, DEV_NAMED_PIPE, DEV_NAMED_PIPE_LEN) == 0)
965 {
966 w32 += DEV_NAMED_PIPE_LEN;
967 if (wcsncmp (w32, L"cygwin-", WCLEN (L"cygwin-")) != 0)
968 return false;
969 w32 += WCLEN (L"cygwin-");
526b0fbc 970 /* Check for installation key and trailing dash. */
8895d962
CV
971 w32len = cygheap->installation_key.Length / sizeof (WCHAR);
972 if (w32len
973 && wcsncmp (w32, cygheap->installation_key.Buffer, w32len) != 0)
526b0fbc
CV
974 return false;
975 w32 += w32len;
976 if (*w32 != L'-')
977 return false;
978 ++w32;
2ae8e0e4 979 bool istty = wcsncmp (w32, L"pty", WCLEN (L"pty")) == 0;
019fc8d8 980 if (istty)
2ae8e0e4 981 decode_tty (posix_fn, w32 + WCLEN (L"pty"));
019fc8d8
CV
982 else if (wcsncmp (w32, L"pipe", WCLEN (L"pipe")) == 0)
983 strcpy (posix_fn, "/dev/pipe");
984 return istty;
985 }
5bf785a0 986
019fc8d8
CV
987 WCHAR fnbuf[64 * 1024];
988 if (wcsncasecmp (w32, DEVICE_PREFIX, DEVICE_PREFIX_LEN) != 0
989 || !QueryDosDeviceW (NULL, fnbuf, sizeof (fnbuf)))
990 {
991 sys_wcstombs (posix_fn, NT_MAX_PATH, w32, w32len);
992 return false;
993 }
2402700d 994
019fc8d8
CV
995 for (WCHAR *s = fnbuf; *s; s = wcschr (s, '\0') + 1)
996 {
5e7c84e5 997 if (!QueryDosDeviceW (s, device, NT_MAX_PATH))
019fc8d8
CV
998 continue;
999 if (wcschr (s, ':') == NULL)
1000 continue;
1001 WCHAR *q = wcsrchr (device, ';');
1002 if (q)
7b9e380f 1003 {
019fc8d8
CV
1004 WCHAR *r = wcschr (q, '\\');
1005 if (r)
1006 wcscpy (q, r + 1);
7b9e380f 1007 }
019fc8d8
CV
1008 int devlen = wcslen (device);
1009 if (device[devlen - 1] == L'\\')
1010 device[--devlen] = L'\0';
1011 if (devlen < maxmatchlen)
1012 continue;
1013 if (wcsncmp (device, w32, devlen) != 0||
1014 (w32[devlen] != L'\0' && w32[devlen] != L'\\'))
1015 continue;
1016 maxmatchlen = devlen;
1017 maxmatchdos = s;
1018 debug_printf ("current match '%W' = '%W'\n", s, device);
1019 }
1ffe3e67 1020
019fc8d8
CV
1021 if (maxmatchlen)
1022 {
1023 WCHAR *p = wcschr (w32 + DEVICE_PREFIX_LEN, L'\\');
1024 size_t n = wcslen (maxmatchdos);
1025 WCHAR ch;
1026 if (!p)
1027 ch = L'\0';
1028 else
7b9e380f 1029 {
019fc8d8
CV
1030 if (maxmatchdos[n - 1] == L'\\')
1031 n--;
1032 w32 += maxmatchlen - n;
1033 ch = L'\\';
7b9e380f 1034 }
019fc8d8
CV
1035 memcpy (w32, maxmatchdos, n * sizeof (WCHAR));
1036 w32[n] = ch;
1037 }
1038 else if (wcsncmp (w32, DEV_REMOTE, DEV_REMOTE_LEN) == 0)
1039 {
1040 w32 += DEV_REMOTE_LEN - 2;
1041 *w32 = L'\\';
1042 debug_printf ("remote drive");
1043 }
1044 else if (wcsncmp (w32, DEV_REMOTE1, DEV_REMOTE1_LEN) == 0)
1045 {
1046 w32 += DEV_REMOTE1_LEN - 2;
1047 *w32 = L'\\';
1048 debug_printf ("remote drive");
1049 }
1ffe3e67 1050
019fc8d8
CV
1051 cygwin_conv_path (CCP_WIN_W_TO_POSIX | CCP_ABSOLUTE, w32, posix_fn,
1052 NT_MAX_PATH);
37be5a67 1053
019fc8d8
CV
1054 debug_printf ("derived path '%W', posix '%s'", w32, posix_fn);
1055 return false;
634a4140 1056 }
2402700d 1057
1ffe3e67 1058 strcpy (posix_fn, unknown_file);
88f0dc31 1059 return false;
2402700d 1060}
b14f53a8
CV
1061
1062void
1063dtable::fixup_before_fork (DWORD target_proc_id)
1064{
1065 lock ();
1066 fhandler_base *fh;
1067 for (size_t i = 0; i < size; i++)
1068 if ((fh = fds[i]) != NULL)
1069 {
b86f999a
CF
1070 debug_printf ("fd %d (%s)", i, fh->get_name ());
1071 fh->fixup_before_fork_exec (target_proc_id);
b14f53a8
CV
1072 }
1073 unlock ();
b86f999a
CF
1074}
1075
b14f53a8
CV
1076void
1077dtable::fixup_before_exec (DWORD target_proc_id)
1078{
1079 lock ();
1080 fhandler_base *fh;
1081 for (size_t i = 0; i < size; i++)
1082 if ((fh = fds[i]) != NULL && !fh->close_on_exec ())
1083 {
b86f999a
CF
1084 debug_printf ("fd %d (%s)", i, fh->get_name ());
1085 fh->fixup_before_fork_exec (target_proc_id);
b14f53a8
CV
1086 }
1087 unlock ();
b86f999a 1088}
This page took 0.553469 seconds and 5 git commands to generate.