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:
Corinna Vinschen
2019-01-06 20:18:14 +01:00
parent ba12614f79
commit 7aca27b4fe
6 changed files with 189 additions and 164 deletions

View File

@ -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;