* dtable.cc: Define various device-related string constants as wide character

constants.
(dtable::init_std_file_from_handle): Reorganize pipe handling to try to catch
special tty case.
(build_fh_name_worker): Declare for common use.
(build_fh_name): Define char version.
(build_fh_name): Define (currently unused) UNICODE_STRING version.
(decode_tty): Detect if pipe is actually a cygwin tty, returning the tty name
in the buffer.
(handle_to_fn): Reorganize to use wide characters.
* dtable.h (build_fh_name): Declare (currently unused) UNICODE_STRING version.
* fhandler_tty.cc (fhandler_pty_master::setup): Use
fhandler_pipe::create_selectable to create a pipe with a given name.
* pipe.cc (pipe_handler): Make returned handle inheritable.
(fhandler_pipe::create_selectable): Take an optional name.  Use a standard
cygwin introducer for the name.
* path.cc (path_conv::check): Make first argument const.
* path.h (path_conv::check): Ditto for declaration.
(path_conv::path_conv): Ditto for UNICODE_STRING version.
This commit is contained in:
Christopher Faylor 2008-03-22 21:04:16 +00:00
parent b00c2ef98f
commit 1ffe3e67b1
9 changed files with 239 additions and 156 deletions

View File

@ -1,3 +1,27 @@
2008-03-22 Christopher Faylor <me+cygwin@cgf.cx>
* dtable.cc: Define various device-related string constants as wide
character constants.
(dtable::init_std_file_from_handle): Reorganize pipe handling to try to
catch special tty case.
(build_fh_name_worker): Declare for common use.
(build_fh_name): Define char version.
(build_fh_name): Define (currently unused) UNICODE_STRING version.
(decode_tty): Detect if pipe is actually a cygwin tty, returning the
tty name in the buffer.
(handle_to_fn): Reorganize to use wide characters.
* dtable.h (build_fh_name): Declare (currently unused) UNICODE_STRING
version.
* fhandler_tty.cc (fhandler_pty_master::setup): Use
fhandler_pipe::create_selectable to create a pipe with a given name.
* pipe.cc (pipe_handler): Make returned handle inheritable.
(fhandler_pipe::create_selectable): Take an optional name. Use a
standard cygwin introducer for the name.
* path.cc (path_conv::check): Make first argument const.
* path.h (path_conv::check): Ditto for declaration.
(path_conv::path_conv): Ditto for UNICODE_STRING version.
2008-03-18 Corinna Vinschen <corinna@vinschen.de>
* include/sys/cygwin.h: Revert erroneous move of `#ifdef WINVER' to
@ -241,7 +265,7 @@
* cygtls.cc (_cygtls::remove): Free temporary TLS path buffers.
* cygtls.h (TP_NUM_C_BUFS): Define.
(TP_NUM_W_BUFS): Define.
(class tls_pathbuf): New class to store pointers to thread local
(class tls_pathbuf): New class to store pointers to thread local
temporary path buffers.
(_local_storage::pathbufs): New member.
* environ.cc (win_env::add_cache): Use temporary TLS path buffer instead

View File

@ -18,8 +18,8 @@ details. */
#include <unistd.h>
#include <sys/cygwin.h>
#include <assert.h>
#include <ntdef.h>
#include <winnls.h>
#include <wchar.h>
#define USE_SYS_TYPES_FD_SET
#include <winsock.h>
@ -35,23 +35,26 @@ details. */
#include "ntdll.h"
#include "shared_info.h"
static const char NO_COPY unknown_file[] = "some disk file";
static const NO_COPY DWORD std_consts[] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE,
STD_ERROR_HANDLE};
static const char *handle_to_fn (HANDLE, char *);
static void handle_to_fn (HANDLE, char *);
#define DEVICE_PREFIX "\\device\\"
#define DEVICE_PREFIX_LEN sizeof (DEVICE_PREFIX) - 1
#define REMOTE "\\Device\\LanmanRedirector\\"
#define REMOTE_LEN sizeof (REMOTE) - 1
#define REMOTE1 "\\Device\\WinDfs\\Root\\"
#define REMOTE1_LEN sizeof (REMOTE1) - 1
#define NAMED_PIPE "\\Device\\NamedPipe\\"
#define NAMED_PIPE_LEN sizeof (NAMED_PIPE) - 1
#define POSIX_NAMED_PIPE "/Device/NamedPipe/"
#define POSIX_NAMED_PIPE_LEN sizeof (POSIX_NAMED_PIPE) - 1
#define WCLEN(x) ((sizeof (x) / sizeof (WCHAR)) - 1)
char unknown_file[] = "some disk file";
const WCHAR DEV_NULL[] = L"\\Device\\Null";
const WCHAR DEVICE_PREFIX[] = L"\\device\\";
const size_t DEVICE_PREFIX_LEN WCLEN (DEVICE_PREFIX);
static const WCHAR DEV_NAMED_PIPE[] = L"\\Device\\NamedPipe\\";
static const size_t DEV_NAMED_PIPE_LEN = WCLEN (DEV_NAMED_PIPE);
static const WCHAR DEV_REMOTE[] = L"\\Device\\LanmanRedirector\\";
static const size_t DEV_REMOTE_LEN = WCLEN (DEV_REMOTE);
static const WCHAR DEV_REMOTE1[] = L"\\Device\\WinDfs\\Root\\";
static const size_t DEV_REMOTE1_LEN = WCLEN (DEV_REMOTE1);
/* Set aside space for the table of fds */
void
@ -262,7 +265,6 @@ cygwin_attach_handle_to_fd (char *name, int fd, HANDLE handle, mode_t bin,
void
dtable::init_std_file_from_handle (int fd, HANDLE handle)
{
const char *name = NULL;
CONSOLE_SCREEN_BUFFER_INFO buf;
struct sockaddr sa;
int sal = sizeof (sa);
@ -278,55 +280,63 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle)
return;
SetLastError (0);
DWORD access = 0;
DWORD ft = GetFileType (handle);
if (ft != FILE_TYPE_UNKNOWN || GetLastError () != ERROR_INVALID_HANDLE)
char name[NT_MAX_PATH];
name[0] = '\0';
if (ft == FILE_TYPE_PIPE)
{
/* See if we can consoleify it */
if (GetConsoleScreenBufferInfo (handle, &buf))
{
if (ISSTATE (myself, PID_USETTY))
dev.parse (FH_TTY);
else
dev = *console_dev;
}
else if (GetNumberOfConsoleInputEvents (handle, (DWORD *) &buf))
{
if (ISSTATE (myself, PID_USETTY))
dev.parse (FH_TTY);
else
dev = *console_dev;
}
else if (wsock_started && getpeername ((SOCKET) handle, &sa, &sal) == 0)
dev = *tcp_dev;
else if (GetCommState (handle, &dcb))
dev.parse (DEV_TTYS_MAJOR, 0);
handle_to_fn (handle, name);
if (name[0])
/* ok */;
else if (fd == 0)
dev = *piper_dev;
else
{
name = handle_to_fn (handle, tp.c_get ());
if (!strncasematch (name, POSIX_NAMED_PIPE, POSIX_NAMED_PIPE_LEN))
/* nothing */;
else if (fd == 0)
dev = *piper_dev;
else
dev = *pipew_dev;
}
dev = *pipew_dev;
}
else if (ft == FILE_TYPE_UNKNOWN && GetLastError () == ERROR_INVALID_HANDLE)
/* can't figure out what this is */;
else if (GetConsoleScreenBufferInfo (handle, &buf))
{
/* Console output */
if (ISSTATE (myself, PID_USETTY))
dev.parse (FH_TTY);
else
dev = *console_dev;
}
else if (GetNumberOfConsoleInputEvents (handle, (DWORD *) &buf))
{
/* Console input */
if (ISSTATE (myself, PID_USETTY))
dev.parse (FH_TTY);
else
dev = *console_dev;
}
else if (wsock_started && getpeername ((SOCKET) handle, &sa, &sal) == 0)
/* socket */
dev = *tcp_dev;
else if (GetCommState (handle, &dcb))
/* serial */
dev.parse (DEV_TTYS_MAJOR, 0);
else
/* Try to figure it out from context - probably a disk file */
handle_to_fn (handle, name);
if (!name && !dev)
if (!name[0] && !dev)
fds[fd] = NULL;
else
{
fhandler_base *fh;
if (dev)
fh = build_fh_dev (dev, name);
fh = build_fh_dev (dev);
else
fh = build_fh_name (name);
if (fh)
cygheap->fdtab[fd] = fh;
if (name)
if (name[0])
{
bin = fh->pc_binmode ();
if (!bin)
@ -337,7 +347,6 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle)
}
}
DWORD access;
if (dev == FH_TTY || dev == FH_CONSOLE)
access = GENERIC_READ | GENERIC_WRITE;
else if (fd == 0)
@ -352,10 +361,10 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle)
}
#define cnew(name) new ((void *) ccalloc (HEAP_FHANDLER, 1, sizeof (name))) name
fhandler_base *
build_fh_name (const char *name, HANDLE h, unsigned opt, suffix_info *si)
static fhandler_base *
build_fh_name_worker (path_conv& pc, HANDLE h, unsigned opt, suffix_info *si)
{
path_conv pc (name, opt | PC_NULLEMPTY | PC_POSIX, si);
if (pc.error)
{
fhandler_base *fh = cnew (fhandler_nodevice) ();
@ -370,6 +379,20 @@ build_fh_name (const char *name, HANDLE h, unsigned opt, suffix_info *si)
return build_fh_pc (pc);
}
fhandler_base *
build_fh_name (const char *name, HANDLE h, unsigned opt, suffix_info *si)
{
path_conv pc (name, opt | PC_NULLEMPTY | PC_POSIX, si);
return build_fh_name_worker (pc, h, opt, si);
}
#define cnew(name) new ((void *) ccalloc (HEAP_FHANDLER, 1, sizeof (name))) name
fhandler_base *
build_fh_name (const UNICODE_STRING *name, HANDLE h, unsigned opt, suffix_info *si)
{
path_conv pc (name, opt | PC_NULLEMPTY | PC_POSIX, si);
return build_fh_name_worker (pc, h, opt, si);
}
fhandler_base *
build_fh_dev (const device& dev, const char *unix_name)
@ -843,124 +866,134 @@ dtable::vfork_child_fixup ()
}
#endif /*NEWVFORK*/
static const char *
void decode_tty (WCHAR *w32, char *buf)
{
int ttyn = wcstol (w32, NULL, 10);
__small_sprintf (buf, "/dev/tty%d", ttyn);
}
static void
handle_to_fn (HANDLE h, char *posix_fn)
{
tmp_pathbuf tp;
OBJECT_NAME_INFORMATION *ntfn;
const size_t len = sizeof (OBJECT_NAME_INFORMATION)
+ NT_MAX_PATH * sizeof (WCHAR);
char *fnbuf = (char *) alloca (len);
ULONG len = 0;
OBJECT_NAME_INFORMATION dummy_oni;
WCHAR *maxmatchdos = NULL;
int maxmatchlen = 0;
memset (fnbuf, 0, len);
ntfn = (OBJECT_NAME_INFORMATION *) fnbuf;
ntfn->Name.MaximumLength = (NT_MAX_PATH - 1) * sizeof (WCHAR);
ntfn->Name.Buffer = (WCHAR *) (ntfn + 1);
NtQueryObject (h, ObjectNameInformation, &dummy_oni, sizeof (dummy_oni), &len);
if (!len)
{
debug_printf ("NtQueryObject failed 1");
goto unknown;
}
OBJECT_NAME_INFORMATION *ntfn = (OBJECT_NAME_INFORMATION *) alloca (len + sizeof (WCHAR));
NTSTATUS res = NtQueryObject (h, ObjectNameInformation, ntfn, len, NULL);
if (!NT_SUCCESS (res))
{
strcpy (posix_fn, unknown_file);
debug_printf ("NtQueryObject failed");
return unknown_file;
debug_printf ("NtQueryObject failed 2");
goto unknown;
}
// NT seems to do this on an unopened file
if (!ntfn->Name.Buffer)
{
debug_printf ("nt->Name.Buffer == NULL");
return NULL;
goto unknown;
}
ntfn->Name.Buffer[ntfn->Name.Length / sizeof (WCHAR)] = 0;
WCHAR *w32 = ntfn->Name.Buffer;
size_t w32len = ntfn->Name.Length / sizeof (WCHAR);
w32[w32len] = L'\0';
char *win32_fn = tp.c_get ();
sys_wcstombs (win32_fn, NT_MAX_PATH, ntfn->Name.Buffer,
ntfn->Name.Length / sizeof (WCHAR));
debug_printf ("nt name '%s'", win32_fn);
if (!strncasematch (win32_fn, DEVICE_PREFIX, DEVICE_PREFIX_LEN)
|| !QueryDosDevice (NULL, fnbuf, len))
return strcpy (posix_fn, win32_fn);
char *p = strechr (win32_fn + DEVICE_PREFIX_LEN, '\\');
int n = p - win32_fn;
int maxmatchlen = 0;
char *maxmatchdos = NULL;
char *device = tp.c_get ();
for (char *s = fnbuf; *s; s = strchr (s, '\0') + 1)
if (wcscasecmp (w32, DEV_NULL) == 0)
{
device[NT_MAX_PATH - 1] = '\0';
if (strchr (s, ':') == NULL)
strcpy (posix_fn, "/dev/null");
return;
}
if (wcsncasecmp (w32, DEV_NAMED_PIPE, DEV_NAMED_PIPE_LEN) == 0)
{
w32 += DEV_NAMED_PIPE_LEN;
if (wcsncmp (w32, L"cygwin-tty", WCLEN (L"cygwin-tty")) == 0)
decode_tty (w32 + WCLEN (L"cygwin-tty"), posix_fn);
return;
}
WCHAR fnbuf[64 * 1024];
if (wcsncasecmp (w32, DEVICE_PREFIX, DEVICE_PREFIX_LEN) != 0
|| !QueryDosDeviceW (NULL, fnbuf, sizeof (fnbuf)))
{
sys_wcstombs (posix_fn, NT_MAX_PATH, w32, w32len);
return;
}
for (WCHAR *s = fnbuf; *s; s = wcschr (s, '\0') + 1)
{
WCHAR device[NT_MAX_PATH];
if (!QueryDosDeviceW (s, device, sizeof (device)))
continue;
if (!QueryDosDevice (s, device, NT_MAX_PATH - 1))
if (wcschr (s, ':') == NULL)
continue;
char *q = strrchr (device, ';');
WCHAR *q = wcsrchr (device, ';');
if (q)
{
char *r = strchr (q, '\\');
WCHAR *r = wcschr (q, '\\');
if (r)
strcpy (q, r + 1);
wcscpy (q, r + 1);
}
int devlen = strlen (device);
if (device[devlen - 1] == '\\')
device[--devlen] = '\0';
int devlen = wcslen (device);
if (device[devlen - 1] == L'\\')
device[--devlen] = L'\0';
if (devlen < maxmatchlen)
continue;
if (!strncasematch (device, win32_fn, devlen) ||
(win32_fn[devlen] != '\0' && win32_fn[devlen] != '\\'))
if (wcsncmp (device, w32, devlen) != 0||
(w32[devlen] != L'\0' && w32[devlen] != L'\\'))
continue;
maxmatchlen = devlen;
maxmatchdos = s;
debug_printf ("current match '%s'", device);
debug_printf ("current match '%W' = '%W'\n", s, device);
}
char *w32 = win32_fn;
bool justslash = false;
if (maxmatchlen)
{
n = strlen (maxmatchdos);
if (maxmatchdos[n - 1] == '\\')
n--;
w32 += maxmatchlen - n;
memcpy (w32, maxmatchdos, n);
w32[n] = '\\';
WCHAR *p = wcschr (w32 + DEVICE_PREFIX_LEN, L'\\');
size_t n = wcslen (maxmatchdos);
WCHAR ch;
if (!p)
ch = L'\0';
else
{
if (maxmatchdos[n - 1] == L'\\')
n--;
w32 += maxmatchlen - n;
ch = L'\\';
}
memcpy (w32, maxmatchdos, n * sizeof (WCHAR));
w32[n] = ch;
}
else if (strncasematch (w32, NAMED_PIPE, NAMED_PIPE_LEN))
else if (wcsncmp (w32, DEV_REMOTE, DEV_REMOTE_LEN) == 0)
{
debug_printf ("pipe");
justslash = true;
}
else if (strncasematch (w32, REMOTE, REMOTE_LEN))
{
w32 += REMOTE_LEN - 2;
*w32 = '\\';
w32 += DEV_REMOTE_LEN - 2;
*w32 = L'\\';
debug_printf ("remote drive");
justslash = true;
}
else if (strncasematch (w32, REMOTE1, REMOTE1_LEN))
else if (wcsncmp (w32, DEV_REMOTE1, DEV_REMOTE1_LEN) == 0)
{
w32 += REMOTE1_LEN - 2;
*w32 = '\\';
w32 += DEV_REMOTE1_LEN - 2;
*w32 = L'\\';
debug_printf ("remote drive");
justslash = true;
}
if (!justslash)
cygwin_conv_path (CCP_WIN_A_TO_POSIX | CCP_ABSOLUTE, w32, posix_fn,
NT_MAX_PATH);
else
{
char *s, *d;
for (s = w32, d = posix_fn; *s; s++, d++)
if (*s == '\\')
*d = '/';
else
*d = *s;
*d = 0;
}
cygwin_conv_path (CCP_WIN_W_TO_POSIX | CCP_ABSOLUTE, w32, posix_fn,
NT_MAX_PATH);
debug_printf ("derived path '%s', posix '%s'", w32, posix_fn);
return posix_fn;
debug_printf ("derived path '%W', posix '%s'", w32, posix_fn);
return;
unknown:
strcpy (posix_fn, unknown_file);
}

View File

@ -90,7 +90,8 @@ public:
};
fhandler_base *build_fh_dev (const device&, const char * = NULL);
fhandler_base *build_fh_name (const char *unix_name, HANDLE = NULL, unsigned = 0, suffix_info * = NULL);
fhandler_base *build_fh_name (const char *, HANDLE = NULL, unsigned = 0, suffix_info * = NULL);
fhandler_base *build_fh_name (const UNICODE_STRING *, HANDLE = NULL, unsigned = 0, suffix_info * = NULL);
fhandler_base *build_fh_pc (path_conv& pc);
void dtable_init ();

View File

@ -551,7 +551,7 @@ public:
int ready_for_read (int fd, DWORD howlong);
void init (HANDLE, DWORD, mode_t);
static int create (fhandler_pipe *[2], unsigned, int);
static int create_selectable (LPSECURITY_ATTRIBUTES, HANDLE&, HANDLE&, DWORD);
static int create_selectable (LPSECURITY_ATTRIBUTES, HANDLE&, HANDLE&, DWORD, const char * = NULL);
};
enum fifo_state

View File

@ -1352,6 +1352,7 @@ fhandler_tty_master::init_console ()
bool
fhandler_pty_master::setup (bool ispty)
{
int res;
tty& t = *cygwin_shared->tty[get_unit ()];
tcinit (&t, true); /* Set termios information. Force initialization. */
@ -1362,13 +1363,24 @@ fhandler_pty_master::setup (bool ispty)
/* Create communication pipes */
/* FIXME: should this be sec_none_nih? */
if (!CreatePipe (&from_master, &get_output_handle (), &sec_all, 128 * 1024))
/* Create communication pipes */
char pipename[sizeof("ttyNNNN-from-master")];
__small_sprintf (pipename, "tty%d-from-master", get_unit ());
res = fhandler_pipe::create_selectable (&sec_all_nih, from_master,
get_output_handle (), 128 * 1024,
pipename);
if (res)
{
errstr = "input pipe";
goto err;
}
if (!CreatePipe (&get_io_handle (), &to_master, &sec_all, 128 * 1024))
__small_sprintf (pipename, "tty%d-to-master", get_unit ());
res = fhandler_pipe::create_selectable (&sec_all_nih, get_io_handle (),
to_master, 128 * 1024, pipename);
if (res)
{
errstr = "output pipe";
goto err;
@ -1380,7 +1392,7 @@ fhandler_pty_master::setup (bool ispty)
need_nl = 0;
/* We do not open allow the others to open us (for handle duplication)
/* We do not allow others to open us (for handle duplication)
but rely on cygheap->inherited_ctty for descendant processes.
In the future the cygserver may allow access by others. */

View File

@ -1,7 +1,7 @@
/* miscfuncs.cc: misc funcs that don't belong anywhere else
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004,
2005, 2006, 2007 Red Hat, Inc.
2005, 2006, 2007, 2008 Red Hat, Inc.
This file is part of Cygwin.

View File

@ -1,7 +1,7 @@
/* path.cc: path support.
/* path.cc: path support.
Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
2006, 2007 Red Hat, Inc.
2006, 2007, 2008 Red Hat, Inc.
This file is part of Cygwin.
@ -790,7 +790,7 @@ getfileattr (const char *path, bool managed) /* path has to be always absolute.
realy nothing but converting to char *, until path_conv handles
wide-char paths directly. */
void
path_conv::check (PUNICODE_STRING src, unsigned opt,
path_conv::check (const UNICODE_STRING *src, unsigned opt,
const suffix_info *suffixes)
{
tmp_pathbuf tp;

View File

@ -199,7 +199,7 @@ class path_conv
void set_has_symlinks () {path_flags |= PATH_HAS_SYMLINKS;}
void set_exec (int x = 1) {path_flags |= x ? PATH_EXEC : PATH_NOTEXEC;}
void check (PUNICODE_STRING upath, unsigned opt = PC_SYM_FOLLOW,
void check (const UNICODE_STRING *upath, unsigned opt = PC_SYM_FOLLOW,
const suffix_info *suffixes = NULL) __attribute__ ((regparm(3)));
void check (const char *src, unsigned opt = PC_SYM_FOLLOW,
const suffix_info *suffixes = NULL) __attribute__ ((regparm(3)));
@ -217,7 +217,7 @@ class path_conv
check (src, opt, suffixes);
}
path_conv (PUNICODE_STRING src, unsigned opt = PC_SYM_FOLLOW,
path_conv (const UNICODE_STRING *src, unsigned opt = PC_SYM_FOLLOW,
const suffix_info *suffixes = NULL)
{
check (src, opt | PC_NULLEMPTY, suffixes);
@ -300,10 +300,10 @@ enum fe_types
FE_CWD = 4, /* Search CWD for program */
FE_DLL = 8 /* Search for DLLs, not executables. */
};
const char * __stdcall find_exec (const char *name, path_conv& buf,
const char *winenv = "PATH=",
unsigned opt = FE_NADA,
const char **known_suffix = NULL)
const char *__stdcall find_exec (const char *name, path_conv& buf,
const char *winenv = "PATH=",
unsigned opt = FE_NADA,
const char **known_suffix = NULL)
__attribute__ ((regparm(3)));
/* Common macros for checking for invalid path names */

View File

@ -59,7 +59,7 @@ static DWORD WINAPI
pipe_handler (LPVOID in_ps)
{
pipesync ps = *(pipesync *) in_ps;
HANDLE in, out;
HANDLE h, in, out;
DWORD err = fhandler_pipe::create_selectable (&sec_none_nih, in, out, 0);
if (err)
{
@ -67,7 +67,8 @@ pipe_handler (LPVOID in_ps)
system_printf ("couldn't create a shadow pipe for non-cygwin pipe I/O, %E");
return 0;
}
((pipesync *) in_ps)->ret_handle = ps.reader ? in : out;
h = ((pipesync *) in_ps)->ret_handle = ps.reader ? in : out;
SetHandleInformation (h, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT);
SetEvent (ps.ev);
char buf[4096];
@ -124,6 +125,7 @@ pipesync::pipesync (HANDLE f, DWORD is_reader):
system_printf ("couldn't create synchronization event for non-cygwin pipe, %E");
goto out;
}
debug_printf ("created thread synchronization event %p", ev);
non_cygwin_h = f;
reader = !!is_reader;
ret_handle = NULL;
@ -153,7 +155,6 @@ out:
return;
}
#define WINPIPE "\\\\.\\pipe\\"
void
fhandler_pipe::init (HANDLE f, DWORD a, mode_t mode)
{
@ -324,6 +325,8 @@ fhandler_pipe::dup (fhandler_base *child)
return res;
}
#define PIPE_INTRO "\\\\.\\pipe\\cygwin-"
/* Create a pipe, and return handles to the read and write ends,
just like CreatePipe, but ensure that the write end permits
FILE_READ_ATTRIBUTES access, on later versions of win32 where
@ -333,7 +336,7 @@ fhandler_pipe::dup (fhandler_base *child)
unlike CreatePipe, which returns a bool for success or failure. */
int
fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE& r,
HANDLE& w, DWORD psize)
HANDLE& w, DWORD psize, const char *name)
{
/* Default to error. */
r = w = INVALID_HANDLE_VALUE;
@ -342,20 +345,26 @@ fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE& r,
if (psize < PIPE_BUF)
psize = PIPE_BUF;
char pipename[MAX_PATH];
char pipename[MAX_PATH] = PIPE_INTRO;
/* FIXME: Eventually make ttys work with overlapped I/O. */
DWORD overlapped = name ? 0 : FILE_FLAG_OVERLAPPED;
/* Retry CreateNamedPipe as long as the pipe name is in use.
Retrying will probably never be necessary, but we want
to be as robust as possible. */
while (1)
DWORD err;
do
{
static volatile ULONG pipe_unique_id;
__small_sprintf (pipename, "\\\\.\\pipe\\cygwin-%p-%p", myself->pid,
InterlockedIncrement ((LONG *) &pipe_unique_id));
if (!name)
__small_sprintf (pipename + strlen(PIPE_INTRO), "%p-%p", myself->pid,
InterlockedIncrement ((LONG *) &pipe_unique_id));
else
strcpy (pipename + strlen(PIPE_INTRO), name);
debug_printf ("CreateNamedPipe: name %s, size %lu", pipename, psize);
err = 0;
/* Use CreateNamedPipe instead of CreatePipe, because the latter
returns a write handle that does not permit FILE_READ_ATTRIBUTES
access, on versions of win32 earlier than WinXP SP2.
@ -365,7 +374,7 @@ fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE& r,
the pipe was not created earlier by some other process, even if
the pid has been reused. We avoid FILE_FLAG_FIRST_PIPE_INSTANCE
because that is only available for Win2k SP2 and WinXP. */
r = CreateNamedPipe (pipename, PIPE_ACCESS_INBOUND | FILE_FLAG_OVERLAPPED,
r = CreateNamedPipe (pipename, PIPE_ACCESS_INBOUND | overlapped,
PIPE_TYPE_BYTE | PIPE_READMODE_BYTE, 1, psize,
psize, NMPWAIT_USE_DEFAULT_WAIT, sa_ptr);
@ -376,7 +385,7 @@ fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE& r,
break;
}
DWORD err = GetLastError ();
err = GetLastError ();
switch (err)
{
case ERROR_PIPE_BUSY:
@ -397,13 +406,17 @@ fhandler_pipe::create_selectable (LPSECURITY_ATTRIBUTES sa_ptr, HANDLE& r,
}
}
}
while (!name);
if (err)
return err;
debug_printf ("CreateFile: name %s", pipename);
/* Open the named pipe for writing.
Be sure to permit FILE_READ_ATTRIBUTES access. */
w = CreateFile (pipename, GENERIC_WRITE | FILE_READ_ATTRIBUTES, 0, sa_ptr,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
OPEN_EXISTING, overlapped, 0);
if (!w || w == INVALID_HANDLE_VALUE)
{