* 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.
This commit is contained in:
Corinna Vinschen 2005-02-06 11:15:29 +00:00
parent 85a798d6e7
commit 7d880770d3
6 changed files with 187 additions and 43 deletions

View File

@ -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> 2005-02-03 Christopher Faylor <cgf@timesys.com>
* cygthread.h (cygthread::terminate_thread): Reflect return value. * cygthread.h (cygthread::terminate_thread): Reflect return value.

View File

@ -321,6 +321,7 @@ class cygheap_fdmanip
operator int &() {return fd;} operator int &() {return fd;}
operator fhandler_base* &() {return *fh;} operator fhandler_base* &() {return *fh;}
operator fhandler_socket* () const {return reinterpret_cast<fhandler_socket *> (*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;} void operator = (fhandler_base *fh) {*this->fh = fh;}
fhandler_base *operator -> () const {return *fh;} fhandler_base *operator -> () const {return *fh;}
bool isopen () const bool isopen () const

View File

@ -764,6 +764,11 @@ is_virtual_symlink:
else else
break; break;
} }
else if (sym.error != ENOENT) /* E. g. EACCES */
{
error = sym.error;
goto out;
}
/* No existing file found. */ /* No existing file found. */
} }

View File

@ -506,6 +506,34 @@ _pinfo::commune_recv ()
} }
break; 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: case PICOM_FD:
{ {
int fd; int fd;
@ -518,7 +546,7 @@ _pinfo::commune_recv ()
} }
CloseHandle (__fromthem); __fromthem = NULL; CloseHandle (__fromthem); __fromthem = NULL;
CloseHandle (hp); CloseHandle (hp);
unsigned int n; unsigned int n = 0;
cygheap_fdget cfd (fd); cygheap_fdget cfd (fd);
if (cfd < 0) if (cfd < 0)
n = strlen (strcpy (path, "")) + 1; n = strlen (strcpy (path, "")) + 1;
@ -659,6 +687,17 @@ _pinfo::commune_send (DWORD code, ...)
size_t n; size_t n;
switch (code) 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: case PICOM_FD:
{ {
int fd = va_arg (args, int); int fd = va_arg (args, int);
@ -669,25 +708,31 @@ _pinfo::commune_send (DWORD code, ...)
goto err; goto err;
} }
} }
/*FALLTHRU*/ goto business_as_usual;
case PICOM_CMDLINE: case PICOM_CMDLINE:
case PICOM_CWD: case PICOM_CWD:
case PICOM_ROOT: case PICOM_ROOT:
case PICOM_FDS: case PICOM_FDS:
business_as_usual:
if (!ReadFile (fromthem, &n, sizeof n, &nr, NULL) || nr != sizeof n) if (!ReadFile (fromthem, &n, sizeof n, &nr, NULL) || nr != sizeof n)
{ {
__seterrno (); __seterrno ();
goto err; goto err;
} }
res.s = (char *) malloc (n); if (!n)
char *p; res.s = NULL;
for (p = res.s; ReadFile (fromthem, p, n, &nr, NULL); p += nr) else
continue; {
if ((unsigned) (p - res.s) != n) res.s = (char *) malloc (n);
{ char *p;
__seterrno (); for (p = res.s; ReadFile (fromthem, p, n, &nr, NULL); p += nr)
goto err; continue;
} if ((unsigned) (p - res.s) != n)
{
__seterrno ();
goto err;
}
}
res.n = n; res.n = n;
break; break;
case PICOM_FIFO: case PICOM_FIFO:
@ -740,6 +785,18 @@ out:
return res; 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 * char *
_pinfo::fd (int fd, size_t &n) _pinfo::fd (int fd, size_t &n)
{ {

View File

@ -27,12 +27,15 @@ enum picom
PICOM_CWD = 3, PICOM_CWD = 3,
PICOM_ROOT = 4, PICOM_ROOT = 4,
PICOM_FDS = 5, PICOM_FDS = 5,
PICOM_FD = 6 PICOM_FD = 6,
PICOM_PIPE_FHANDLER = 7
}; };
#define EXITCODE_SET 0x80000000 #define EXITCODE_SET 0x80000000
#define EXITCODE_NOSET 0x40000000 #define EXITCODE_NOSET 0x40000000
class fhandler_pipe;
class _pinfo class _pinfo
{ {
public: public:
@ -110,6 +113,7 @@ public:
void commune_recv (); void commune_recv ();
commune_result commune_send (DWORD, ...); commune_result commune_send (DWORD, ...);
bool alive (); bool alive ();
fhandler_pipe *pipe_fhandler (HANDLE hdl, size_t &);
char *fd (int fd, size_t &); char *fd (int fd, size_t &);
char *fds (size_t &); char *fds (size_t &);
char *root (size_t &); char *root (size_t &);

View File

@ -36,43 +36,106 @@ fhandler_pipe::fhandler_pipe ()
{ {
} }
extern "C" int sscanf (const char *, const char *, ...);
int int
fhandler_pipe::open (int flags, mode_t mode) fhandler_pipe::open (int flags, mode_t mode)
{ {
const char *path = get_name (); HANDLE proc, pipe_hdl, nio_hdl = NULL, nwrp_hdl = NULL;
debug_printf ("path: %s", path); fhandler_pipe *fh = NULL;
if (!strncmp (get_name (), "/proc/", 6)) size_t size;
int pid, rwflags = (flags & O_ACCMODE);
if (flags & O_CREAT)
{ {
char *c; set_errno (EACCES);
HANDLE hdl; return 0;
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)
{
if (cfd->get_handle () == hdl)
{
if (!cfd->dup (this))
return 1;
return 0;
}
}
}
else
{
/* TODO: Open pipes of different process. Is that possible? */
}
} }
sscanf (get_name (), "/proc/%d/fd/pipe:[%d]", &pid, (int *) &pipe_hdl);
if (pid == myself->pid)
{
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)))
{
set_errno (EACCES);
return 0;
}
if (!cfd->dup (this))
return 1;
return 0;
}
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: 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; return 0;
} }