OSDN Git Service

* dcrt0.cc (wow64_respawn): New static variable.
[pf3gnuchains/pf3gnuchains4x.git] / winsup / cygwin / pipe.cc
1 /* pipe.cc: pipe for Cygwin.
2
3    Copyright 1996, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007,
4    2008, 2009, 2010, 2011 Hat, Inc.
5
6 This file is part of Cygwin.
7
8 This software is a copyrighted work licensed under the terms of the
9 Cygwin license.  Please consult the file "CYGWIN_LICENSE" for
10 details. */
11
12 /* FIXME: Should this really be fhandler_pipe.cc? */
13
14 #include "winsup.h"
15 #include <stdlib.h>
16 #include <sys/socket.h>
17 #include "cygerrno.h"
18 #include "security.h"
19 #include "path.h"
20 #include "fhandler.h"
21 #include "dtable.h"
22 #include "cygheap.h"
23 #include "pinfo.h"
24 #include "shared_info.h"
25
26 fhandler_pipe::fhandler_pipe ()
27   : fhandler_base_overlapped (), popen_pid (0)
28 {
29   max_atomic_write = DEFAULT_PIPEBUFSIZE;
30   need_fork_fixup (true);
31 }
32
33 int
34 fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode)
35 {
36   /* FIXME: Have to clean this up someday
37      FIXME: Do we have to check for both !get_win32_name() and
38      !*get_win32_name()? */
39   if ((!get_win32_name () || !*get_win32_name ()) && get_name ())
40     {
41       char *d;
42       const char *s;
43       char *hold_normalized_name = (char *) alloca (strlen (get_name ()) + 1);
44       for (s = get_name (), d = hold_normalized_name; *s; s++, d++)
45         if (*s == '/')
46           *d = '\\';
47         else
48           *d = *s;
49       *d = '\0';
50       set_name (hold_normalized_name);
51     }
52
53   bool opened_properly = a & FILE_CREATE_PIPE_INSTANCE;
54   a &= ~FILE_CREATE_PIPE_INSTANCE;
55   fhandler_base::init (f, a, mode);
56   close_on_exec (mode & O_CLOEXEC);
57   if (opened_properly)
58     setup_overlapped ();
59   else
60     destroy_overlapped ();
61   return 1;
62 }
63
64 extern "C" int sscanf (const char *, const char *, ...);
65
66 int
67 fhandler_pipe::open (int flags, mode_t mode)
68 {
69   HANDLE proc, pipe_hdl, nio_hdl = NULL;
70   fhandler_pipe *fh = NULL;
71   size_t size;
72   int pid, rwflags = (flags & O_ACCMODE);
73   bool inh;
74
75   sscanf (get_name (), "/proc/%d/fd/pipe:[%d]", &pid, (int *) &pipe_hdl);
76   if (pid == myself->pid)
77     {
78       cygheap_fdenum cfd (true);
79       while (cfd.next () >= 0)
80         {
81           if (cfd->get_handle () != pipe_hdl)
82             continue;
83           if ((rwflags == O_RDONLY && !(cfd->get_access () & GENERIC_READ))
84               || (rwflags == O_WRONLY && !(cfd->get_access () & GENERIC_WRITE)))
85             {
86               set_errno (EACCES);
87               return 0;
88             }
89           cfd->copyto (this);
90           set_io_handle (NULL);
91           pc.reset_conv_handle ();
92           if (!cfd->dup (this, flags))
93             return 1;
94           return 0;
95         }
96       set_errno (ENOENT);
97       return 0;
98     }
99
100   pinfo p (pid);
101   if (!p)
102     {
103       set_errno (ESRCH);
104       return 0;
105     }
106   if (!(proc = OpenProcess (PROCESS_DUP_HANDLE, false, p->dwProcessId)))
107     {
108       __seterrno ();
109       return 0;
110     }
111   if (!(fh = p->pipe_fhandler (pipe_hdl, size)) || !size)
112     {
113       set_errno (ENOENT);
114       goto out;
115     }
116   /* Too bad, but Windows only allows the same access mode when dup'ing
117      the pipe. */
118   if ((rwflags == O_RDONLY && !(fh->get_access () & GENERIC_READ))
119       || (rwflags == O_WRONLY && !(fh->get_access () & GENERIC_WRITE)))
120     {
121       set_errno (EACCES);
122       goto out;
123     }
124   inh = !(flags & O_CLOEXEC);
125   if (!DuplicateHandle (proc, pipe_hdl, GetCurrentProcess (), &nio_hdl,
126                         0, inh, DUPLICATE_SAME_ACCESS))
127     {
128       __seterrno ();
129       goto out;
130     }
131   init (nio_hdl, fh->get_access (), mode & O_TEXT ?: O_BINARY);
132   cfree (fh);
133   CloseHandle (proc);
134   return 1;
135 out:
136   if (nio_hdl)
137     CloseHandle (nio_hdl);
138   if (fh)
139     free (fh);
140   if (proc)
141     CloseHandle (proc);
142   return 0;
143 }
144
145 _off64_t
146 fhandler_pipe::lseek (_off64_t offset, int whence)
147 {
148   debug_printf ("(%d, %d)", offset, whence);
149   set_errno (ESPIPE);
150   return -1;
151 }
152
153 int
154 fhandler_pipe::fadvise (_off64_t offset, _off64_t length, int advice)
155 {
156   set_errno (ESPIPE);
157   return -1;
158 }
159
160 int
161 fhandler_pipe::ftruncate (_off64_t length, bool allow_truncate)
162 {
163   set_errno (allow_truncate ? EINVAL : ESPIPE);
164   return -1;
165 }
166
167 char *
168 fhandler_pipe::get_proc_fd_name (char *buf)
169 {
170   __small_sprintf (buf, "pipe:[%d]", get_handle ());
171   return buf;
172 }
173
174 int
175 fhandler_pipe::dup (fhandler_base *child, int flags)
176 {
177   fhandler_pipe *ftp = (fhandler_pipe *) child;
178   ftp->set_popen_pid (0);
179
180   int res;
181   if (get_handle () && fhandler_base_overlapped::dup (child, flags))
182     res = -1;
183   else
184     res = 0;
185
186   debug_printf ("res %d", res);
187   return res;
188 }
189
190 #define PIPE_INTRO "\\\\.\\pipe\\cygwin-"
191
192 /* Create a pipe, and return handles to the read and write ends,
193    just like CreatePipe, but ensure that the write end permits
194    FILE_READ_ATTRIBUTES access, on later versions of win32 where
195    this is supported.  This access is needed by NtQueryInformationFile,
196    which is used to implement select and nonblocking writes.
197    Note that the return value is either 0 or GetLastError,
198    unlike CreatePipe, which returns a bool for success or failure.  */
199 DWORD
200 fhandler_pipe::create (LPSECURITY_ATTRIBUTES sa_ptr, PHANDLE r, PHANDLE w,
201                        DWORD psize, const char *name, DWORD open_mode)
202 {
203   /* Default to error. */
204   if (r)
205     *r = NULL;
206   if (w)
207     *w = NULL;
208
209   /* Ensure that there is enough pipe buffer space for atomic writes.  */
210   if (!psize)
211     psize = DEFAULT_PIPEBUFSIZE;
212
213   char pipename[MAX_PATH];
214   const size_t len = __small_sprintf (pipename, PIPE_INTRO "%S-",
215                                       &installation_key);
216   if (name)
217     strcpy (pipename + len, name);
218
219   open_mode |= PIPE_ACCESS_INBOUND;
220
221   /* Retry CreateNamedPipe as long as the pipe name is in use.
222      Retrying will probably never be necessary, but we want
223      to be as robust as possible.  */
224   DWORD err = 0;
225   while (r && !*r)
226     {
227       static volatile ULONG pipe_unique_id;
228       if (!name)
229         __small_sprintf (pipename + len, "pipe-%p-%p", myself->pid,
230                         InterlockedIncrement ((LONG *) &pipe_unique_id));
231
232       debug_printf ("CreateNamedPipe: name %s, size %lu", pipename, psize);
233
234       /* Use CreateNamedPipe instead of CreatePipe, because the latter
235          returns a write handle that does not permit FILE_READ_ATTRIBUTES
236          access, on versions of win32 earlier than WinXP SP2.
237          CreatePipe also stupidly creates a full duplex pipe, which is
238          a waste, since only a single direction is actually used.
239          It's important to only allow a single instance, to ensure that
240          the pipe was not created earlier by some other process, even if
241          the pid has been reused.  We avoid FILE_FLAG_FIRST_PIPE_INSTANCE
242          because that is only available for Win2k SP2 and WinXP.
243
244          Note that the write side of the pipe is opened as PIPE_TYPE_MESSAGE.
245          This *seems* to more closely mimic Linux pipe behavior and is
246          definitely required for pty handling since fhandler_pty_master
247          writes to the pipe in chunks, terminated by newline when CANON mode
248          is specified.  */
249       *r = CreateNamedPipe (pipename, open_mode,
250                            PIPE_TYPE_MESSAGE | PIPE_READMODE_BYTE, 1, psize,
251                            psize, NMPWAIT_USE_DEFAULT_WAIT, sa_ptr);
252
253       if (*r != INVALID_HANDLE_VALUE)
254         {
255           debug_printf ("pipe read handle %p", *r);
256           err = 0;
257           break;
258         }
259
260       err = GetLastError ();
261       switch (err)
262         {
263         case ERROR_PIPE_BUSY:
264           /* The pipe is already open with compatible parameters.
265              Pick a new name and retry.  */
266           debug_printf ("pipe busy", !name ? ", retrying" : "");
267           if (!name)
268             *r = NULL;
269           break;
270         case ERROR_ACCESS_DENIED:
271           /* The pipe is already open with incompatible parameters.
272              Pick a new name and retry.  */
273           debug_printf ("pipe access denied%s", !name ? ", retrying" : "");
274           if (!name)
275             *r = NULL;
276           break;
277         default:
278           {
279             err = GetLastError ();
280             debug_printf ("failed, %E");
281           }
282         }
283     }
284
285   if (err)
286     {
287       *r = NULL;
288       return err;
289     }
290
291   if (!w)
292     debug_printf ("pipe write handle NULL");
293   else
294     {
295       debug_printf ("CreateFile: name %s", pipename);
296
297       /* Open the named pipe for writing.
298          Be sure to permit FILE_READ_ATTRIBUTES access.  */
299       DWORD access = GENERIC_WRITE | FILE_READ_ATTRIBUTES;
300       if ((open_mode & PIPE_ACCESS_DUPLEX) == PIPE_ACCESS_DUPLEX)
301         access |= GENERIC_READ | FILE_WRITE_ATTRIBUTES;
302       *w = CreateFile (pipename, access, 0, sa_ptr, OPEN_EXISTING,
303                       open_mode & FILE_FLAG_OVERLAPPED, 0);
304
305       if (!*w || *w == INVALID_HANDLE_VALUE)
306         {
307           /* Failure. */
308           DWORD err = GetLastError ();
309           debug_printf ("CreateFile failed, %E");
310           if (r)
311             CloseHandle (*r);
312           *w = NULL;
313           return err;
314         }
315
316       debug_printf ("pipe write handle %p", *w);
317     }
318
319   /* Success. */
320   return 0;
321 }
322
323 int
324 fhandler_pipe::create (fhandler_pipe *fhs[2], unsigned psize, int mode)
325 {
326   HANDLE r, w;
327   SECURITY_ATTRIBUTES *sa = sec_none_cloexec (mode);
328   int res = -1;
329
330   int ret = create (sa, &r, &w, psize, NULL, FILE_FLAG_OVERLAPPED);
331   if (ret)
332     __seterrno_from_win_error (ret);
333   else if ((fhs[0] = (fhandler_pipe *) build_fh_dev (*piper_dev)) == NULL)
334     {
335       CloseHandle (r);
336       CloseHandle (w);
337     }
338   else if ((fhs[1] = (fhandler_pipe *) build_fh_dev (*pipew_dev)) == NULL)
339     {
340       delete fhs[0];
341       CloseHandle (w);
342     }
343   else
344     {
345       mode |= mode & O_TEXT ?: O_BINARY;
346       fhs[0]->init (r, FILE_CREATE_PIPE_INSTANCE | GENERIC_READ, mode);
347       fhs[1]->init (w, FILE_CREATE_PIPE_INSTANCE | GENERIC_WRITE, mode);
348       res = 0;
349     }
350
351   debug_printf ("%R = pipe([%p, %p], %d, %p)", res, fhs[0], fhs[1], psize, mode);
352   return res;
353 }
354
355 int
356 fhandler_pipe::ioctl (unsigned int cmd, void *p)
357 {
358   int n;
359
360   switch (cmd)
361     {
362     case FIONREAD:
363       if (get_device () == FH_PIPEW)
364         {
365           set_errno (EINVAL);
366           return -1;
367         }
368       if (!PeekNamedPipe (get_handle (), NULL, 0, NULL, (DWORD *) &n, NULL))
369         {
370           __seterrno ();
371           return -1;
372         }
373       break;
374     default:
375       return fhandler_base::ioctl (cmd, p);
376       break;
377     }
378   *(int *) p = n;
379   return 0;
380 }
381
382 int __stdcall
383 fhandler_pipe::fstatvfs (struct statvfs *sfs)
384 {
385   set_errno (EBADF);
386   return -1;
387 }
388
389 static int __attribute__ ((regparm (3)))
390 pipe_worker (int filedes[2], unsigned int psize, int mode)
391 {
392   fhandler_pipe *fhs[2];
393   int res = fhandler_pipe::create (fhs, psize, mode);
394   if (!res)
395     {
396       cygheap_fdnew fdin;
397       cygheap_fdnew fdout (fdin, false);
398       char buf[sizeof ("/dev/fd/pipe:[2147483647]")];
399       __small_sprintf (buf, "/dev/fd/pipe:[%d]", (int) fdin);
400       fhs[0]->pc.set_normalized_path (buf);
401       __small_sprintf (buf, "pipe:[%d]", (int) fdout);
402       fhs[1]->pc.set_normalized_path (buf);
403       fdin = fhs[0];
404       fdout = fhs[1];
405       filedes[0] = fdin;
406       filedes[1] = fdout;
407     } 
408   return res;
409 }
410
411 extern "C" int
412 _pipe (int filedes[2], unsigned int psize, int mode)
413 {
414   int res = pipe_worker (filedes, psize, mode);
415   int read, write;
416   if (res != 0)
417     read = write = -1;
418   else
419     {
420       read = filedes[0];
421       write = filedes[1];
422     }
423   syscall_printf ("%R = _pipe([%d, %d], %u, %p)", res, read, write, psize, mode);
424   return res;
425 }
426
427 extern "C" int
428 pipe (int filedes[2])
429 {
430   int res = pipe_worker (filedes, DEFAULT_PIPEBUFSIZE, O_BINARY);
431   int read, write;
432   if (res != 0)
433     read = write = -1;
434   else
435     {
436       read = filedes[0];
437       write = filedes[1];
438     }
439   syscall_printf ("%R = pipe([%d, %d])", res, read, write);
440   return res;
441 }
442
443 extern "C" int
444 pipe2 (int filedes[2], int mode)
445 {
446   int res = pipe_worker (filedes, DEFAULT_PIPEBUFSIZE, mode);
447   int read, write;
448   if (res != 0)
449     read = write = -1;
450   else
451     {
452       read = filedes[0];
453       write = filedes[1];
454     }
455   syscall_printf ("%R = pipe2([%d, %d], %p)", res, read, write, mode);
456   return res;
457 }