summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/fhandler_process.cc
diff options
context:
space:
mode:
Diffstat (limited to 'winsup/cygwin/fhandler_process.cc')
-rw-r--r--winsup/cygwin/fhandler_process.cc39
1 files changed, 29 insertions, 10 deletions
diff --git a/winsup/cygwin/fhandler_process.cc b/winsup/cygwin/fhandler_process.cc
index e2de05b3c..161050b3b 100644
--- a/winsup/cygwin/fhandler_process.cc
+++ b/winsup/cygwin/fhandler_process.cc
@@ -1,7 +1,7 @@
/* fhandler_process.cc: fhandler for /proc/<pid> virtual filesystem
Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010, 2011, 2012,
- 2013, 2014 Red Hat, Inc.
+ 2013, 2014, 2015 Red Hat, Inc.
This file is part of Cygwin.
@@ -77,7 +77,7 @@ static const virt_tab_t process_tab[] =
{ _VN ("uid"), FH_PROCESS, virt_file, format_process_uid },
{ _VN ("winexename"), FH_PROCESS, virt_file, format_process_winexename },
{ _VN ("winpid"), FH_PROCESS, virt_file, format_process_winpid },
- { NULL, 0, FH_NADA, virt_none, NULL }
+ { NULL, 0, FH_NADA, virt_none, NULL }
};
static const int PROCESS_LINK_COUNT =
@@ -111,11 +111,11 @@ fhandler_process::exists ()
fileid = entry - process_tab;
return entry->type;
}
- if (entry->type == virt_directory)
+ if (entry->type == virt_directory) /* fd subdir only */
{
fileid = entry - process_tab;
if (fill_filebuf ())
- return virt_symlink;
+ return fd_type;
/* Check for nameless device entries. */
path = strrchr (path, '/');
if (path && *++path)
@@ -325,6 +325,7 @@ out:
struct process_fd_t {
const char *path;
_pinfo *p;
+ virtual_ftype_t *fd_type;
};
bool
@@ -350,7 +351,7 @@ fhandler_process::fill_filebuf ()
{
if (process_tab[fileid].fhandler == FH_PROCESSFD)
{
- process_fd_t fd = { path, p };
+ process_fd_t fd = { path, p , &fd_type };
filesize = process_tab[fileid].format_func (&fd, filebuf);
}
else
@@ -366,20 +367,27 @@ format_process_fd (void *data, char *&destbuf)
_pinfo *p = ((process_fd_t *) data)->p;
const char *path = ((process_fd_t *) data)->path;
size_t fs = 0;
- char *fdp = strrchr (path, '/');
-
- if (!fdp || *++fdp == 'f') /* The "fd" directory itself. */
+ /* path looks like "$PID/fd", "$PID/fd/", "$PID/fd/[0-9]*". In the latter
+ case a trailing slash and more followup chars are allowed, provided the
+ descriptor symlink points to a directory. */
+ char *fdp = strchr (path, '/') + 3;
+ /* The "fd" directory itself? */
+ if (fdp[0] =='\0' || (fdp[0] == '/' && fdp[1] == '\0'))
{
if (destbuf)
cfree (destbuf);
destbuf = p->fds (fs);
+ *((process_fd_t *) data)->fd_type = virt_symlink;
}
else
{
+ char *e;
+ int fd;
+
if (destbuf)
cfree (destbuf);
- int fd = atoi (fdp);
- if (fd < 0 || (fd == 0 && !isdigit (*fdp)))
+ fd = strtol (++fdp, &e, 10);
+ if (fd < 0 || e == fdp || (*e != '/' && *e != '\0'))
{
set_errno (ENOENT);
return 0;
@@ -390,6 +398,17 @@ format_process_fd (void *data, char *&destbuf)
set_errno (ENOENT);
return 0;
}
+ if (*e == '\0')
+ *((process_fd_t *) data)->fd_type = virt_symlink;
+ else /* trailing path */
+ {
+ char *newbuf = (char *) cmalloc_abort (HEAP_STR, strlen (destbuf)
+ + strlen (e) + 1);
+ stpcpy (stpcpy (newbuf, destbuf), e);
+ cfree (destbuf);
+ destbuf = newbuf;
+ *((process_fd_t *) data)->fd_type = virt_fsdir;
+ }
}
return fs;
}