summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin')
-rw-r--r--winsup/cygwin/ChangeLog14
-rw-r--r--winsup/cygwin/cygheap.h1
-rw-r--r--winsup/cygwin/path.cc5
-rw-r--r--winsup/cygwin/pinfo.cc79
-rw-r--r--winsup/cygwin/pinfo.h6
-rw-r--r--winsup/cygwin/pipe.cc119
6 files changed, 184 insertions, 40 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index a2936bf40..a612dfab3 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,17 @@
+2005-02-06 Corinna Vinschen <corinna@vinschen.de>
+
+ * path.cc (path_conv::check): Leave symlink expansion loop in case
+ a not-ENOENT error happens.
+
+ * cygheap.h (cygheap_fdmanip::fhandler_pipe *): New cast operator.
+ * pinfo.cc (_pinfo::commune_recv): Add PICOM_PIPE_FHANDLER handling.
+ (_pinfo::commune_send): Ditto.
+ (_pinfo::pipe_fhandler): New method.
+ * pinfo.h (enum picom): Add PICOM_PIPE_FHANDLER.
+ (_pinfo::pipe_fhandler): Declare.
+ * pipe.cc (fhandler_pipe::open): Rewrite. Allow to open foreign
+ pipe handles.
+
2005-02-03 Christopher Faylor <cgf@timesys.com>
* cygthread.h (cygthread::terminate_thread): Reflect return value.
diff --git a/winsup/cygwin/cygheap.h b/winsup/cygwin/cygheap.h
index 43723244d..e75afe9ce 100644
--- a/winsup/cygwin/cygheap.h
+++ b/winsup/cygwin/cygheap.h
@@ -321,6 +321,7 @@ class cygheap_fdmanip
operator int &() {return fd;}
operator fhandler_base* &() {return *fh;}
operator fhandler_socket* () const {return reinterpret_cast<fhandler_socket *> (*fh);}
+ operator fhandler_pipe* () const {return reinterpret_cast<fhandler_pipe *> (*fh);}
void operator = (fhandler_base *fh) {*this->fh = fh;}
fhandler_base *operator -> () const {return *fh;}
bool isopen () const
diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc
index 055aa1986..7294d2267 100644
--- a/winsup/cygwin/path.cc
+++ b/winsup/cygwin/path.cc
@@ -764,6 +764,11 @@ is_virtual_symlink:
else
break;
}
+ else if (sym.error != ENOENT) /* E. g. EACCES */
+ {
+ error = sym.error;
+ goto out;
+ }
/* No existing file found. */
}
diff --git a/winsup/cygwin/pinfo.cc b/winsup/cygwin/pinfo.cc
index 69dcb142c..7805eb43d 100644
--- a/winsup/cygwin/pinfo.cc
+++ b/winsup/cygwin/pinfo.cc
@@ -506,6 +506,34 @@ _pinfo::commune_recv ()
}
break;
}
+ case PICOM_PIPE_FHANDLER:
+ {
+ HANDLE hdl;
+ if (!ReadFile (__fromthem, &hdl, sizeof hdl, &nr, NULL)
+ || nr != sizeof hdl)
+ {
+ sigproc_printf ("ReadFile hdl failed, %E");
+ CloseHandle (hp);
+ goto out;
+ }
+ CloseHandle (__fromthem); __fromthem = NULL;
+ CloseHandle (hp);
+ unsigned int n = 0;
+ cygheap_fdenum cfd;
+ while (cfd.next () >= 0)
+ if (cfd->get_handle () == hdl)
+ {
+ fhandler_pipe *fh = cfd;
+ n = sizeof *fh;
+ if (!WriteFile (__tothem, &n, sizeof n, &nr, NULL))
+ sigproc_printf ("WriteFile sizeof hdl failed, %E");
+ else if (!WriteFile (__tothem, fh, n, &nr, NULL))
+ sigproc_printf ("WriteFile hdl failed, %E");
+ }
+ if (!n && !WriteFile (__tothem, &n, sizeof n, &nr, NULL))
+ sigproc_printf ("WriteFile sizeof hdl failed, %E");
+ break;
+ }
case PICOM_FD:
{
int fd;
@@ -518,7 +546,7 @@ _pinfo::commune_recv ()
}
CloseHandle (__fromthem); __fromthem = NULL;
CloseHandle (hp);
- unsigned int n;
+ unsigned int n = 0;
cygheap_fdget cfd (fd);
if (cfd < 0)
n = strlen (strcpy (path, "")) + 1;
@@ -659,6 +687,17 @@ _pinfo::commune_send (DWORD code, ...)
size_t n;
switch (code)
{
+ case PICOM_PIPE_FHANDLER:
+ {
+ HANDLE hdl = va_arg (args, HANDLE);
+ if (!WriteFile (tothem, &hdl, sizeof hdl, &nr, NULL)
+ || nr != sizeof hdl)
+ {
+ __seterrno ();
+ goto err;
+ }
+ }
+ goto business_as_usual;
case PICOM_FD:
{
int fd = va_arg (args, int);
@@ -669,25 +708,31 @@ _pinfo::commune_send (DWORD code, ...)
goto err;
}
}
- /*FALLTHRU*/
+ goto business_as_usual;
case PICOM_CMDLINE:
case PICOM_CWD:
case PICOM_ROOT:
case PICOM_FDS:
+ business_as_usual:
if (!ReadFile (fromthem, &n, sizeof n, &nr, NULL) || nr != sizeof n)
{
__seterrno ();
goto err;
}
- res.s = (char *) malloc (n);
- char *p;
- for (p = res.s; ReadFile (fromthem, p, n, &nr, NULL); p += nr)
- continue;
- if ((unsigned) (p - res.s) != n)
- {
- __seterrno ();
- goto err;
- }
+ if (!n)
+ res.s = NULL;
+ else
+ {
+ res.s = (char *) malloc (n);
+ char *p;
+ for (p = res.s; ReadFile (fromthem, p, n, &nr, NULL); p += nr)
+ continue;
+ if ((unsigned) (p - res.s) != n)
+ {
+ __seterrno ();
+ goto err;
+ }
+ }
res.n = n;
break;
case PICOM_FIFO:
@@ -740,6 +785,18 @@ out:
return res;
}
+fhandler_pipe *
+_pinfo::pipe_fhandler (HANDLE hdl, size_t &n)
+{
+ if (!this || !pid)
+ return NULL;
+ if (pid == myself->pid)
+ return NULL;
+ commune_result cr = commune_send (PICOM_PIPE_FHANDLER, hdl);
+ n = cr.n;
+ return (fhandler_pipe *) cr.s;
+}
+
char *
_pinfo::fd (int fd, size_t &n)
{
diff --git a/winsup/cygwin/pinfo.h b/winsup/cygwin/pinfo.h
index 705a1a599..7a502c100 100644
--- a/winsup/cygwin/pinfo.h
+++ b/winsup/cygwin/pinfo.h
@@ -27,12 +27,15 @@ enum picom
PICOM_CWD = 3,
PICOM_ROOT = 4,
PICOM_FDS = 5,
- PICOM_FD = 6
+ PICOM_FD = 6,
+ PICOM_PIPE_FHANDLER = 7
};
#define EXITCODE_SET 0x80000000
#define EXITCODE_NOSET 0x40000000
+class fhandler_pipe;
+
class _pinfo
{
public:
@@ -110,6 +113,7 @@ public:
void commune_recv ();
commune_result commune_send (DWORD, ...);
bool alive ();
+ fhandler_pipe *pipe_fhandler (HANDLE hdl, size_t &);
char *fd (int fd, size_t &);
char *fds (size_t &);
char *root (size_t &);
diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc
index 58cf0109d..ee4b7ad6f 100644
--- a/winsup/cygwin/pipe.cc
+++ b/winsup/cygwin/pipe.cc
@@ -36,43 +36,106 @@ fhandler_pipe::fhandler_pipe ()
{
}
+extern "C" int sscanf (const char *, const char *, ...);
+
int
fhandler_pipe::open (int flags, mode_t mode)
{
- const char *path = get_name ();
- debug_printf ("path: %s", path);
- if (!strncmp (get_name (), "/proc/", 6))
+ HANDLE proc, pipe_hdl, nio_hdl = NULL, nwrp_hdl = NULL;
+ fhandler_pipe *fh = NULL;
+ size_t size;
+ int pid, rwflags = (flags & O_ACCMODE);
+
+ if (flags & O_CREAT)
+ {
+ set_errno (EACCES);
+ return 0;
+ }
+ sscanf (get_name (), "/proc/%d/fd/pipe:[%d]", &pid, (int *) &pipe_hdl);
+ if (pid == myself->pid)
{
- char *c;
- HANDLE hdl;
- int pid = strtol (path += 6, &c, 10);
- if (!pid || !c || *c != '/')
- goto out;
- path = c;
- if (strncmp (path, "/fd/pipe:[", 10))
- goto out;
- path += 10;
- hdl = (HANDLE) atoi (path);
- if (pid == myself->pid)
- {
- cygheap_fdenum cfd;
- while (cfd.next () >= 0)
+ cygheap_fdenum cfd;
+ while (cfd.next () >= 0)
+ {
+ if (cfd->get_handle () != pipe_hdl)
+ continue;
+ if ((rwflags == O_RDONLY && !(cfd->get_access () & GENERIC_READ))
+ || (rwflags == O_WRONLY && !(cfd->get_access () & GENERIC_WRITE)))
{
- if (cfd->get_handle () == hdl)
- {
- if (!cfd->dup (this))
- return 1;
- return 0;
- }
+ set_errno (EACCES);
+ return 0;
}
+ if (!cfd->dup (this))
+ return 1;
+ return 0;
}
- else
- {
- /* TODO: Open pipes of different process. Is that possible? */
- }
+ set_errno (ENOENT);
+ return 0;
+ }
+
+ pinfo p (pid);
+ if (!p)
+ {
+ set_errno (ESRCH);
+ return 0;
+ }
+ if (!(proc = OpenProcess (PROCESS_DUP_HANDLE, false, p->dwProcessId)))
+ {
+ __seterrno ();
+ return 0;
+ }
+ if (!(fh = p->pipe_fhandler (pipe_hdl, size)) || !size)
+ {
+ set_errno (ENOENT);
+ goto out;
+ }
+ /* Too bad, but Windows only allows the same access mode when dup'ing
+ the pipe. */
+ if ((rwflags == O_RDONLY && !(fh->get_access () & GENERIC_READ))
+ || (rwflags == O_WRONLY && !(fh->get_access () & GENERIC_WRITE)))
+ {
+ set_errno (EACCES);
+ goto out;
+ }
+ if (!DuplicateHandle (proc, pipe_hdl, hMainProc, &nio_hdl,
+ 0, false, DUPLICATE_SAME_ACCESS))
+ {
+ __seterrno ();
+ goto out;
+ }
+ if (fh->writepipe_exists
+ && !DuplicateHandle (proc, fh->writepipe_exists,
+ hMainProc, &nwrp_hdl,
+ 0, false, DUPLICATE_SAME_ACCESS))
+ {
+ __seterrno ();
+ goto out;
+ }
+ if (fh->read_state)
+ {
+ create_read_state (2);
+ need_fork_fixup (true);
+ ProtectHandle1 (read_state, read_state);
}
+ if (fh->get_guard ())
+ create_guard ((flags & O_NOINHERIT) ? &sec_none_nih : &sec_none);
+ init (nio_hdl, fh->get_access (), mode & O_TEXT ?: O_BINARY);
+ writepipe_exists = nwrp_hdl;
+ if (flags & O_NOINHERIT)
+ close_on_exec (true);
+ uninterruptible_io (fh->uninterruptible_io ());
+ free (fh);
+ CloseHandle (proc);
+ return 1;
out:
- set_errno (ENXIO);
+ if (nwrp_hdl)
+ CloseHandle (nwrp_hdl);
+ if (nio_hdl)
+ CloseHandle (nio_hdl);
+ if (fh)
+ free (fh);
+ if (proc)
+ CloseHandle (proc);
return 0;
}