Cygwin: introduce fhandler_process_fd and add stat(2) handling
move special fd symlink code into own fhandler_process_fd class to simplify further additions to /proc/PID/fd/DESCRIPTOR symlink handling. Add a method to handle stat(2) on such a proc fd symlink by handle. This allows correct reply from stat(2) if the target file has been deleted. This eventually fixes `awk -f /dev/fd/3 3<<eof'. Signed-off-by: Corinna Vinschen <corinna@vinschen.de>
This commit is contained in:
@ -321,166 +321,6 @@ out:
|
||||
return res;
|
||||
}
|
||||
|
||||
fhandler_base *
|
||||
fhandler_process::fd_reopen (int flags)
|
||||
{
|
||||
const char *path;
|
||||
char *e;
|
||||
int fd;
|
||||
HANDLE proc = NULL;
|
||||
HANDLE hdl = NULL;
|
||||
fhandler_base *fh = NULL;
|
||||
|
||||
path = get_name () + proc_len + 1;
|
||||
pid = strtoul (path, &e, 10);
|
||||
path = e + 4;
|
||||
fd = strtoul (path, &e, 10);
|
||||
if (e == path || *e != '\0')
|
||||
{
|
||||
set_errno (ENOENT);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
if (pid == myself->pid)
|
||||
{
|
||||
cygheap_fdget cfd (fd);
|
||||
if (cfd < 0)
|
||||
return NULL;
|
||||
fh = build_fh_pc (cfd->pc);
|
||||
if (!fh)
|
||||
goto err_out;
|
||||
fh->set_io_handle (cfd->get_handle ());
|
||||
}
|
||||
else
|
||||
{
|
||||
size_t size;
|
||||
path_conv pc;
|
||||
|
||||
pinfo p (pid);
|
||||
if (!p)
|
||||
{
|
||||
set_errno (ENOENT);
|
||||
return NULL;
|
||||
}
|
||||
if (!(proc = OpenProcess (PROCESS_DUP_HANDLE, false, p->dwProcessId)))
|
||||
{
|
||||
__seterrno ();
|
||||
return NULL;
|
||||
}
|
||||
void *buf = p->file_pathconv (fd, size);
|
||||
if (size == 0)
|
||||
{
|
||||
set_errno (EPERM);
|
||||
goto err_out;
|
||||
}
|
||||
hdl = pc.deserialize (buf);
|
||||
if (!DuplicateHandle (proc, hdl, GetCurrentProcess (), &hdl,
|
||||
0, FALSE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
__seterrno ();
|
||||
hdl = NULL;
|
||||
goto err_out;
|
||||
}
|
||||
fh = build_fh_pc (pc);
|
||||
if (!fh)
|
||||
goto err_out;
|
||||
fh->set_io_handle (hdl);
|
||||
}
|
||||
if (!fh->open_with_arch (flags, 0))
|
||||
{
|
||||
delete fh;
|
||||
fh = NULL;
|
||||
}
|
||||
err_out:
|
||||
if (hdl)
|
||||
CloseHandle (hdl);
|
||||
if (proc)
|
||||
CloseHandle (proc);
|
||||
return fh;
|
||||
}
|
||||
|
||||
int
|
||||
fhandler_process::link (const char *newpath)
|
||||
{
|
||||
const char *path;
|
||||
int fd;
|
||||
char *e;
|
||||
|
||||
path = get_name () + proc_len + 1;
|
||||
pid = atoi (path);
|
||||
while (*path != 0 && !isdirsep (*path))
|
||||
path++;
|
||||
if (*path == 0)
|
||||
goto err_out;
|
||||
|
||||
virt_tab_t *entry;
|
||||
entry = virt_tab_search (path + 1, true, process_tab, PROCESS_LINK_COUNT);
|
||||
if (!entry || entry->fhandler != FH_PROCESSFD)
|
||||
goto err_out;
|
||||
if (path[3] != '/' || path[4] == '\0')
|
||||
goto err_out;
|
||||
|
||||
fd = strtoul (path + 4, &e, 10);
|
||||
if (fd < 0 || e == path + 4 || (*e != '/' && *e != '\0'))
|
||||
goto err_out;
|
||||
if (pid == myself->pid)
|
||||
{
|
||||
cygheap_fdget cfd (fd);
|
||||
if (cfd < 0)
|
||||
goto err_out;
|
||||
return cfd->link (newpath);
|
||||
}
|
||||
else
|
||||
{
|
||||
HANDLE proc;
|
||||
size_t size;
|
||||
void *buf;
|
||||
path_conv pc;
|
||||
HANDLE hdl;
|
||||
fhandler_base *fh = NULL;
|
||||
int ret = -1;
|
||||
|
||||
pinfo p (pid);
|
||||
if (!p)
|
||||
{
|
||||
set_errno (ENOENT);
|
||||
return -1;
|
||||
}
|
||||
if (!(proc = OpenProcess (PROCESS_DUP_HANDLE, false, p->dwProcessId)))
|
||||
goto err_out;
|
||||
buf = p->file_pathconv (fd, size);
|
||||
if (size == 0)
|
||||
{
|
||||
set_errno (EPERM);
|
||||
goto err_out_close_proc;
|
||||
}
|
||||
hdl = pc.deserialize (buf);
|
||||
if (!DuplicateHandle (proc, hdl, GetCurrentProcess (), &hdl,
|
||||
0, FALSE, DUPLICATE_SAME_ACCESS))
|
||||
{
|
||||
__seterrno ();
|
||||
goto err_out_close_proc;
|
||||
}
|
||||
fh = build_fh_pc (pc);
|
||||
if (!fh)
|
||||
goto err_out_close_dup;
|
||||
|
||||
fh->set_io_handle (hdl);
|
||||
ret = fh->link (newpath);
|
||||
delete fh;
|
||||
|
||||
err_out_close_dup:
|
||||
CloseHandle (hdl);
|
||||
err_out_close_proc:
|
||||
CloseHandle (proc);
|
||||
return ret;
|
||||
}
|
||||
|
||||
err_out:
|
||||
set_errno (EPERM);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct process_fd_t {
|
||||
const char *path;
|
||||
_pinfo *p;
|
||||
|
Reference in New Issue
Block a user