Welcome to mirror list, hosted at ThFree Co, Russian Federation.

cygwin.com/git/newlib-cygwin.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
path: root/winsup
diff options
context:
space:
mode:
authorChristopher Faylor <me@cgf.cx>2007-12-17 00:21:23 +0300
committerChristopher Faylor <me@cgf.cx>2007-12-17 00:21:23 +0300
commit634a41403c1439e1c6f3ee4252cf5a091bcc6921 (patch)
tree5e21dbc7f97ec39c0dc988b2e00de45ff6348fa2 /winsup
parent68adeb7cdee53b09835d35ee43948c5d1b330fcd (diff)
* dtable.cc (POSIX_NAMED_PIPE): New define.
(POSIX_NAMED_PIPE_LEN): Ditto. (dtable::add_archetype): Use crealloc_abort. (dtable::init_std_file_from_handle): Specifically detect pipe stdin/stdout. Pass name to build_fh_dev so that proper name is recorded. Use binmode of fh if it is set before using get_default_mode. Set proper read/write access when calling init(). (handle_to_fn): Handle pipes. * fhandler.cc (fhandler_base::wait_overlapped): Add some debugging. * fhandler.h (fhandler_base::set_name): Default to just setting the path_conv name. (fhandler_pipe::init): Declare. * pipe.cc (struct pipesync): New struct. (getov_result): New function. Blocks and retrieves the result of an overlay I/O operation. (pipe_handler): New function. (pipesync::pipesync): New function. Initializer for pipesync struct. (handler_pipe::init): Define. Detects attempts to set up a "native" pipe fhandler and creates a thread which accepts input from or output to the non-cygwin pipe, creating a cygwin pipe wrapper around the non-cygwin pipe. (fhandler_pipe::create): Add pipe-specific flags to call to init(). * exceptions.cc (ctrl_c_handler): Lock process while we determine what to do.
Diffstat (limited to 'winsup')
-rw-r--r--winsup/cygwin/ChangeLog28
-rw-r--r--winsup/cygwin/dtable.cc86
-rw-r--r--winsup/cygwin/exceptions.cc1
-rw-r--r--winsup/cygwin/fhandler.cc3
-rw-r--r--winsup/cygwin/fhandler.h2
-rw-r--r--winsup/cygwin/pipe.cc157
6 files changed, 247 insertions, 30 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index eb54da9f8..4ea56f4e1 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,31 @@
+2007-12-16 Christopher Faylor <me+cygwin@cgf.cx>
+
+ * dtable.cc (POSIX_NAMED_PIPE): New define.
+ (POSIX_NAMED_PIPE_LEN): Ditto.
+ (dtable::add_archetype): Use crealloc_abort.
+ (dtable::init_std_file_from_handle): Specifically detect pipe
+ stdin/stdout. Pass name to build_fh_dev so that proper name is
+ recorded. Use binmode of fh if it is set before using
+ get_default_mode. Set proper read/write access when calling init().
+ (handle_to_fn): Handle pipes.
+ * fhandler.cc (fhandler_base::wait_overlapped): Add some debugging.
+ * fhandler.h (fhandler_base::set_name): Default to just setting the
+ path_conv name.
+ (fhandler_pipe::init): Declare.
+ * pipe.cc (struct pipesync): New struct.
+ (getov_result): New function. Blocks and retrieves the result of an
+ overlay I/O operation.
+ (pipe_handler): New function.
+ (pipesync::pipesync): New function. Initializer for pipesync struct.
+ (handler_pipe::init): Define. Detects attempts to set up a "native"
+ pipe fhandler and creates a thread which accepts input from or output
+ to the non-cygwin pipe, creating a cygwin pipe wrapper around the
+ non-cygwin pipe.
+ (fhandler_pipe::create): Add pipe-specific flags to call to init().
+
+ * exceptions.cc (ctrl_c_handler): Lock process while we determine what
+ to do.
+
2007-12-14 Corinna Vinschen <corinna@vinschen.de>
* include/cygwin/socket.h: Include sys/uio.h instead of cygwin/uio.h.
diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc
index 575384650..6fcf7086e 100644
--- a/winsup/cygwin/dtable.cc
+++ b/winsup/cygwin/dtable.cc
@@ -41,6 +41,17 @@ static const NO_COPY DWORD std_consts[] = {STD_INPUT_HANDLE, STD_OUTPUT_HANDLE,
static const char *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
+
/* Set aside space for the table of fds */
void
dtable_init ()
@@ -187,7 +198,7 @@ fhandler_base **
dtable::add_archetype ()
{
if (farchetype++ >= narchetypes)
- archetypes = (fhandler_base **) crealloc (archetypes, (narchetypes += initial_archetype_size) * sizeof archetypes[0]);
+ archetypes = (fhandler_base **) crealloc_abort (archetypes, (narchetypes += initial_archetype_size) * sizeof archetypes[0]);
return archetypes + farchetype - 1;
}
@@ -283,13 +294,6 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle)
else
dev = *console_dev;
}
- else if (ft == FILE_TYPE_PIPE)
- {
- if (fd == 0)
- dev = *piper_dev;
- else
- dev = *pipew_dev;
- }
else if (wsock_started && getpeername ((SOCKET) handle, &sa, &sal) == 0)
dev = *tcp_dev;
else if (GetCommState (handle, &dcb))
@@ -297,7 +301,12 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle)
else
{
name = handle_to_fn (handle, (char *) alloca (CYG_MAX_PATH + 100));
- bin = 0;
+ if (!strncasematch (name, POSIX_NAMED_PIPE, POSIX_NAMED_PIPE_LEN))
+ /* nothing */;
+ else if (fd == 0)
+ dev = *piper_dev;
+ else
+ dev = *pipew_dev;
}
}
@@ -308,25 +317,31 @@ dtable::init_std_file_from_handle (int fd, HANDLE handle)
fhandler_base *fh;
if (dev)
- fh = build_fh_dev (dev);
+ fh = build_fh_dev (dev, name);
else
fh = build_fh_name (name);
if (fh)
cygheap->fdtab[fd] = fh;
- if (!bin)
+ if (name)
{
- bin = fh->get_default_fmode (O_RDWR);
- if (bin)
- /* nothing */;
- else if (dev)
- bin = O_BINARY;
- else if (name != unknown_file)
- bin = fh->pc_binmode ();
+ bin = fh->pc_binmode ();
+ if (!bin)
+ {
+ bin = fh->get_default_fmode (O_RDWR);
+ if (!bin && dev)
+ bin = O_BINARY;
+ }
}
- fh->init (handle, GENERIC_READ | GENERIC_WRITE, bin);
+ DWORD access;
+ if (fd == 0)
+ access = GENERIC_READ;
+ else
+ access = GENERIC_WRITE; /* Should be rdwr for stderr but not sure that's
+ possible for some versions of handles */
+ fh->init (handle, access, bin);
set_std_handle (fd);
paranoid_printf ("fd %d, handle %p", fd, handle);
}
@@ -824,11 +839,6 @@ dtable::vfork_child_fixup ()
}
#endif /*NEWVFORK*/
-#define DEVICE_PREFIX "\\device\\"
-#define DEVICE_PREFIX_LEN sizeof (DEVICE_PREFIX) - 1
-#define REMOTE "\\Device\\LanmanRedirector\\"
-#define REMOTE_LEN sizeof (REMOTE) - 1
-
static const char *
handle_to_fn (HANDLE h, char *posix_fn)
{
@@ -900,6 +910,7 @@ handle_to_fn (HANDLE h, char *posix_fn)
}
char *w32 = win32_fn;
+ bool justslash = false;
if (maxmatchlen)
{
n = strlen (maxmatchdos);
@@ -909,15 +920,38 @@ handle_to_fn (HANDLE h, char *posix_fn)
memcpy (w32, maxmatchdos, n);
w32[n] = '\\';
}
+ else if (strncasematch (w32, NAMED_PIPE, NAMED_PIPE_LEN))
+ {
+ debug_printf ("pipe");
+ justslash = true;
+ }
else if (strncasematch (w32, REMOTE, REMOTE_LEN))
{
w32 += REMOTE_LEN - 2;
*w32 = '\\';
debug_printf ("remote drive");
+ justslash = true;
+ }
+ else if (strncasematch (w32, REMOTE1, REMOTE1_LEN))
+ {
+ w32 += REMOTE1_LEN - 2;
+ *w32 = '\\';
+ debug_printf ("remote drive");
+ justslash = true;
}
+ if (!justslash)
+ cygwin_conv_to_full_posix_path (w32, posix_fn);
+ else
+ {
+ char *s, *d;
+ for (s = w32, d = posix_fn; *s; s++, d++)
+ if (*s == '\\')
+ *d = '/';
+ else
+ *d = *s;
+ }
- debug_printf ("derived path '%s'", w32);
- cygwin_conv_to_full_posix_path (w32, posix_fn);
+ debug_printf ("derived path '%s', posix '%s'", w32, posix_fn);
return posix_fn;
}
diff --git a/winsup/cygwin/exceptions.cc b/winsup/cygwin/exceptions.cc
index 06a9b5409..fc361b59b 100644
--- a/winsup/cygwin/exceptions.cc
+++ b/winsup/cygwin/exceptions.cc
@@ -888,6 +888,7 @@ static BOOL WINAPI
ctrl_c_handler (DWORD type)
{
static bool saw_close;
+ lock_process now;
if (!cygwin_finished_initializing)
{
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index bc30a396c..a479d1b28 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -1639,6 +1639,7 @@ fhandler_base::wait_overlapped (bool& res, bool writing, DWORD *bytes)
switch (WaitForMultipleObjects (n, w4, false, INFINITE))
{
case WAIT_OBJECT_0:
+ debug_printf ("normal read");
if (!bytes ||
GetOverlappedResult (h, get_overlapped (), bytes, false))
res = 1;
@@ -1649,12 +1650,14 @@ fhandler_base::wait_overlapped (bool& res, bool writing, DWORD *bytes)
}
break;
case WAIT_OBJECT_0 + 1:
+ debug_printf ("got a signal");
CancelIo (h);
set_errno (EINTR);
res = 0;
break;
default:
err = GetLastError ();
+ debug_printf ("WFMO error, %E");
goto err;
break;
}
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 665dd51e1..45588fef9 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -149,6 +149,7 @@ class fhandler_base
path_conv pc;
virtual void set_name (path_conv &pc);
+ virtual void set_name (const char *s) {pc.set_normalized_path (s, false);}
int error () const {return pc.error;}
void set_error (int error) {pc.error = error;}
bool exists () const {return pc.exists ();}
@@ -546,6 +547,7 @@ public:
int __stdcall fadvise (_off64_t, _off64_t, int) __attribute__ ((regparm (3)));
int __stdcall ftruncate (_off64_t, bool) __attribute__ ((regparm (3)));
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);
};
diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc
index b9314aa4f..a6e4fff56 100644
--- a/winsup/cygwin/pipe.cc
+++ b/winsup/cygwin/pipe.cc
@@ -34,6 +34,157 @@ fhandler_pipe::fhandler_pipe ()
need_fork_fixup (true);
}
+struct pipesync
+{
+ bool reader;
+ HANDLE ev, non_cygwin_h, ret_handle;
+ pipesync(HANDLE, DWORD);
+ int operator == (int x) const {return !!ev;}
+ static DWORD WINAPI handler (LPVOID *);
+};
+
+inline bool
+getov_result (HANDLE h, DWORD& nbytes, LPOVERLAPPED ov)
+{
+ if (ov && (GetLastError () != ERROR_IO_PENDING
+ || !GetOverlappedResult (h, ov, &nbytes, true)))
+ {
+ __seterrno ();
+ return false;
+ }
+ return true;
+}
+
+static DWORD WINAPI
+pipe_handler (LPVOID in_ps)
+{
+ pipesync ps = *(pipesync *) in_ps;
+ HANDLE in, out;
+ DWORD err = fhandler_pipe::create_selectable (&sec_none_nih, in, out, 0);
+ if (err)
+ {
+ SetLastError (err);
+ 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;
+ SetEvent (ps.ev);
+
+ char buf[4096];
+ DWORD read_bytes, write_bytes;
+ HANDLE hread, hwrite, hclose;
+ OVERLAPPED ov, *rov, *wov;
+ memset (&ov, 0, sizeof (ov));
+ ov.hEvent = CreateEvent (&sec_none_nih, true, false, NULL);
+ if (ps.reader)
+ {
+ hread = ps.non_cygwin_h;
+ hclose = hwrite = out;
+ wov = &ov;
+ rov = NULL;
+ }
+ else
+ {
+ hclose = hread = in;
+ hwrite = ps.non_cygwin_h;
+ rov = &ov;
+ wov = NULL;
+ }
+
+ while (1)
+ {
+ ResetEvent (ov.hEvent);
+ BOOL res = ReadFile (hread, buf, 4096, &read_bytes, rov);
+ if (!res && !getov_result (hread, read_bytes, rov))
+ break;
+ if (!read_bytes)
+ break;
+
+ res = WriteFile (hwrite, buf, read_bytes, &write_bytes, wov);
+ if (!res && !getov_result (hwrite, write_bytes, wov))
+ break;
+ if (write_bytes != read_bytes)
+ break;
+ }
+
+ err = GetLastError ();
+ CloseHandle (ov.hEvent);
+ CloseHandle (hclose);
+ CloseHandle (ps.non_cygwin_h);
+ SetLastError (err);
+ return 0;
+}
+
+
+pipesync::pipesync (HANDLE f, DWORD is_reader):
+ reader (false), ret_handle (NULL)
+{
+ ev = CreateEvent (&sec_none_nih, true, false, NULL);
+ if (!ev)
+ {
+ system_printf ("couldn't create synchronization event for non-cygwin pipe, %E");
+ goto out;
+ }
+ non_cygwin_h = f;
+ reader = !!is_reader;
+ ret_handle = NULL;
+
+ DWORD tid;
+ HANDLE ht = CreateThread (&sec_none_nih, 0, pipe_handler, this, 0, &tid);
+
+ if (!ht)
+ goto out;
+ CloseHandle (ht);
+
+ switch (WaitForSingleObject (ev, INFINITE))
+ {
+ case WAIT_OBJECT_0:
+ break;
+ default:
+ system_printf ("WFSO failed waiting for synchronization event for non-cygwin pipe, %E");
+ break;
+ }
+
+out:
+ if (ev)
+ {
+ CloseHandle (ev);
+ ev = NULL;
+ }
+ return;
+}
+
+#define WINPIPE "\\\\.\\pipe\\"
+void
+fhandler_pipe::init (HANDLE f, DWORD a, mode_t bin)
+{
+ // FIXME: Have to clean this up someday
+ if (!*get_win32_name () && get_name ())
+ {
+ char *hold_normalized_name = (char *) alloca (strlen (get_name ()) + 1);
+ strcpy (hold_normalized_name, get_name ());
+ char *s, *d;
+ for (s = hold_normalized_name, d = (char *) get_win32_name (); *s; s++, d++)
+ if (*s == '/')
+ *d = '\\';
+ else
+ *d = *s;
+ *d = '\0';
+ set_name (hold_normalized_name);
+ }
+
+ bool opened_properly = a & FILE_CREATE_PIPE_INSTANCE;
+ a &= ~FILE_CREATE_PIPE_INSTANCE;
+ if (!opened_properly)
+ {
+ pipesync ps (f, a & GENERIC_READ);
+ f = ps.ret_handle;
+ }
+
+ fhandler_base::init (f, a, bin);
+ setup_overlapped ();
+}
+
extern "C" int sscanf (const char *, const char *, ...);
int
@@ -284,16 +435,14 @@ fhandler_pipe::create (fhandler_pipe *fhs[2], unsigned psize, int mode)
fhs[1] = (fhandler_pipe *) build_fh_dev (*pipew_dev);
int binmode = mode & O_TEXT ?: O_BINARY;
- fhs[0]->init (r, GENERIC_READ, binmode);
- fhs[1]->init (w, GENERIC_WRITE, binmode);
+ fhs[0]->init (r, FILE_CREATE_PIPE_INSTANCE | GENERIC_READ, binmode);
+ fhs[1]->init (w, FILE_CREATE_PIPE_INSTANCE | GENERIC_WRITE, binmode);
if (mode & O_NOINHERIT)
{
fhs[0]->close_on_exec (true);
fhs[1]->close_on_exec (true);
}
- fhs[0]->setup_overlapped ();
- fhs[1]->setup_overlapped ();
res = 0;
}