[newlib-cygwin] Cygwin: introduce fhandler_process_fd and add stat(2) handling
Corinna Vinschen
corinna@sourceware.org
Sun Jan 6 19:42:00 GMT 2019
https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=7aca27b4fe553657d057dce90de13be97068fd4a
commit 7aca27b4fe553657d057dce90de13be97068fd4a
Author: Corinna Vinschen <corinna@vinschen.de>
Date: Sun Jan 6 20:18:14 2019 +0100
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>
Diff:
---
winsup/cygwin/Makefile.in | 1 +
winsup/cygwin/dtable.cc | 4 +-
winsup/cygwin/fhandler.h | 32 ++++++-
winsup/cygwin/fhandler_process.cc | 160 -----------------------------------
winsup/cygwin/fhandler_process_fd.cc | 153 +++++++++++++++++++++++++++++++++
winsup/cygwin/syscalls.cc | 3 +-
6 files changed, 189 insertions(+), 164 deletions(-)
diff --git a/winsup/cygwin/Makefile.in b/winsup/cygwin/Makefile.in
index fb0195f..75c73bf 100644
--- a/winsup/cygwin/Makefile.in
+++ b/winsup/cygwin/Makefile.in
@@ -288,6 +288,7 @@ DLL_OFILES:= \
fhandler_nodevice.o \
fhandler_proc.o \
fhandler_process.o \
+ fhandler_process_fd.o \
fhandler_procnet.o \
fhandler_procsys.o \
fhandler_procsysvipc.o \
diff --git a/winsup/cygwin/dtable.cc b/winsup/cygwin/dtable.cc
index 0ebeef0..780deb5 100644
--- a/winsup/cygwin/dtable.cc
+++ b/winsup/cygwin/dtable.cc
@@ -552,9 +552,11 @@ fh_alloc (path_conv& pc)
fh = cnew (fhandler_registry);
break;
case FH_PROCESS:
- case FH_PROCESSFD:
fh = cnew (fhandler_process);
break;
+ case FH_PROCESSFD:
+ fh = cnew (fhandler_process_fd);
+ break;
case FH_PROCNET:
fh = cnew (fhandler_procnet);
break;
diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h
index 1c751c1..e32c219 100644
--- a/winsup/cygwin/fhandler.h
+++ b/winsup/cygwin/fhandler.h
@@ -2545,6 +2545,7 @@ class fhandler_registry: public fhandler_proc
class pinfo;
class fhandler_process: public fhandler_proc
{
+ protected:
pid_t pid;
virtual_ftype_t fd_type;
public:
@@ -2554,8 +2555,6 @@ class fhandler_process: public fhandler_proc
int closedir (DIR *);
int __reg3 readdir (DIR *, dirent *);
int open (int flags, mode_t mode = 0);
- virtual fhandler_base *fd_reopen (int);
- int __reg2 link (const char *);
int __reg2 fstat (struct stat *buf);
bool fill_filebuf ();
@@ -2577,6 +2576,34 @@ class fhandler_process: public fhandler_proc
}
};
+class fhandler_process_fd : public fhandler_process
+{
+ fhandler_base *fetch_fh (HANDLE &);
+
+ public:
+ fhandler_process_fd () : fhandler_process () {}
+ fhandler_process_fd (void *) {}
+
+ virtual fhandler_base *fd_reopen (int);
+ int __reg2 fstat (struct stat *buf);
+ virtual int __reg2 link (const char *);
+
+ void copyto (fhandler_base *x)
+ {
+ x->pc.free_strings ();
+ *reinterpret_cast<fhandler_process_fd *> (x) = *this;
+ x->reset (this);
+ }
+
+ fhandler_process_fd *clone (cygheap_types malloc_type = HEAP_FHANDLER)
+ {
+ void *ptr = (void *) ccalloc (malloc_type, 1, sizeof (fhandler_process_fd));
+ fhandler_process_fd *fh = new (ptr) fhandler_process_fd (ptr);
+ copyto (fh);
+ return fh;
+ }
+};
+
class fhandler_procnet: public fhandler_proc
{
pid_t pid;
@@ -2638,6 +2665,7 @@ typedef union
char __pipe[sizeof (fhandler_pipe)];
char __proc[sizeof (fhandler_proc)];
char __process[sizeof (fhandler_process)];
+ char __process_fd[sizeof (fhandler_process_fd)];
char __procnet[sizeof (fhandler_procnet)];
char __procsys[sizeof (fhandler_procsys)];
char __procsysvipc[sizeof (fhandler_procsysvipc)];
diff --git a/winsup/cygwin/fhandler_process.cc b/winsup/cygwin/fhandler_process.cc
index a523148..24ef7d0 100644
--- a/winsup/cygwin/fhandler_process.cc
+++ b/winsup/cygwin/fhandler_process.cc
@@ -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;
diff --git a/winsup/cygwin/fhandler_process_fd.cc b/winsup/cygwin/fhandler_process_fd.cc
new file mode 100644
index 0000000..06d37c0
--- /dev/null
+++ b/winsup/cygwin/fhandler_process_fd.cc
@@ -0,0 +1,153 @@
+/* fhandler_process_fd.cc: fhandler for /proc/<pid>/fd/<desc> operations
+
+This file is part of Cygwin.
+
+This software is a copyrighted work licensed under the terms of the
+Cygwin license. Please consult the file "CYGWIN_LICENSE" for
+details. */
+
+#include "winsup.h"
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/cygwin.h>
+#include "cygerrno.h"
+#include "security.h"
+#include "path.h"
+#include "fhandler.h"
+#include "fhandler_virtual.h"
+#include "pinfo.h"
+#include "shared_info.h"
+#include "dtable.h"
+#include "cygheap.h"
+#include "ntdll.h"
+#include "cygtls.h"
+#include "mount.h"
+#include "tls_pbuf.h"
+#include <sys/sysmacros.h>
+#include <sys/param.h>
+#include <ctype.h>
+
+
+fhandler_base *
+fhandler_process_fd::fetch_fh (HANDLE &out_hdl)
+{
+ const char *path;
+ char *e;
+ int fd;
+ HANDLE proc;
+ HANDLE hdl = NULL;
+ path_conv pc;
+
+ path = get_name () + proc_len + 1;
+ pid = strtoul (path, &e, 10);
+ path = e + 4;
+ fd = strtoul (path, &e, 10);
+
+ out_hdl = NULL;
+ if (pid == myself->pid)
+ {
+ cygheap_fdget cfd (fd, true);
+ if (cfd < 0)
+ return NULL;
+ proc = GetCurrentProcess ();
+ pc << cfd->pc;
+ hdl = cfd->get_handle ();
+ }
+ else
+ {
+ pinfo p (pid);
+ if (!p)
+ {
+ set_errno (ENOENT);
+ return NULL;
+ }
+ proc = OpenProcess (PROCESS_DUP_HANDLE, false, p->dwProcessId);
+ if (!proc)
+ {
+ __seterrno ();
+ return NULL;
+ }
+ size_t size;
+ void *buf = p->file_pathconv (fd, size);
+ if (size == 0)
+ {
+ set_errno (EPERM);
+ CloseHandle (proc);
+ return NULL;
+ }
+ hdl = pc.deserialize (buf);
+ }
+ BOOL ret = DuplicateHandle (proc, hdl, GetCurrentProcess (), &hdl,
+ 0, FALSE, DUPLICATE_SAME_ACCESS);
+ if (proc != GetCurrentProcess ())
+ CloseHandle (proc);
+ if (!ret)
+ {
+ __seterrno ();
+ CloseHandle (hdl);
+ return NULL;
+ }
+ fhandler_base *fh = build_fh_pc (pc);
+ if (!fh)
+ {
+ CloseHandle (hdl);
+ return NULL;
+ }
+ out_hdl = hdl;
+ return fh;
+}
+
+fhandler_base *
+fhandler_process_fd::fd_reopen (int flags)
+{
+ fhandler_base *fh;
+ HANDLE hdl;
+
+ fh = fetch_fh (hdl);
+ if (!fh)
+ return NULL;
+ fh->set_io_handle (hdl);
+ int ret = fh->open_with_arch (flags, 0);
+ CloseHandle (hdl);
+ if (!ret)
+ {
+ delete fh;
+ fh = NULL;
+ }
+ return fh;
+}
+
+int __reg2
+fhandler_process_fd::fstat (struct stat *statbuf)
+{
+ if (!pc.follow_fd_symlink ())
+ return fhandler_process::fstat (statbuf);
+
+ fhandler_base *fh;
+ HANDLE hdl;
+
+ fh = fetch_fh (hdl);
+ if (!fh)
+ return -1;
+ fh->set_io_handle (hdl);
+ int ret = fh->fstat (statbuf);
+ CloseHandle (hdl);
+ delete fh;
+ return ret;
+}
+
+int
+fhandler_process_fd::link (const char *newpath)
+{
+ fhandler_base *fh;
+ HANDLE hdl;
+
+ fh = fetch_fh (hdl);
+ if (!fh)
+ return -1;
+ fh->set_io_handle (hdl);
+ int ret = fh->link (newpath);
+ CloseHandle (hdl);
+ delete fh;
+ return ret;
+}
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 60f66a6..5bb33bf 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -2005,7 +2005,8 @@ extern "C" int
stat64 (const char *__restrict name, struct stat *__restrict buf)
{
syscall_printf ("entering");
- path_conv pc (name, PC_SYM_FOLLOW | PC_POSIX | PC_KEEP_HANDLE,
+ path_conv pc (name, PC_SYM_FOLLOW | PC_POSIX | PC_KEEP_HANDLE
+ | PC_SYM_NOFOLLOW_PROCFD,
stat_suffixes);
return stat_worker (pc, buf);
}
More information about the Cygwin-cvs
mailing list