aboutsummaryrefslogtreecommitdiff
path: root/winsup/cygwin/pipe.cc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2005-02-06 11:15:29 +0000
committerCorinna Vinschen <corinna@vinschen.de>2005-02-06 11:15:29 +0000
commit7d880770d3b714835e2f0871e0d27c512f3c81b2 (patch)
treee2bf2c92a3a73b9d7cf34ed87ff0a865e05687d5 /winsup/cygwin/pipe.cc
parent85a798d6e755f4db4c04d92ecde1e5409a62cd59 (diff)
downloadnewlib-7d880770d3b714835e2f0871e0d27c512f3c81b2.zip
newlib-7d880770d3b714835e2f0871e0d27c512f3c81b2.tar.gz
newlib-7d880770d3b714835e2f0871e0d27c512f3c81b2.tar.bz2
* 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.
Diffstat (limited to 'winsup/cygwin/pipe.cc')
-rw-r--r--winsup/cygwin/pipe.cc119
1 files changed, 91 insertions, 28 deletions
diff --git a/winsup/cygwin/pipe.cc b/winsup/cygwin/pipe.cc
index 58cf010..ee4b7ad 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;
}