summaryrefslogtreecommitdiffstats
path: root/winsup/cygwin/fhandler_process.cc
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2015-01-22 13:46:12 +0000
committerCorinna Vinschen <corinna@vinschen.de>2015-01-22 13:46:12 +0000
commit185784962a8f35695800dfeaa49da4a4209df6ad (patch)
tree41554d436b87eabad0d4194fd1058355014eb085 /winsup/cygwin/fhandler_process.cc
parent638dd243f28e693471630152345777c21d5a00c6 (diff)
downloadcygnal-185784962a8f35695800dfeaa49da4a4209df6ad.tar.gz
cygnal-185784962a8f35695800dfeaa49da4a4209df6ad.tar.bz2
cygnal-185784962a8f35695800dfeaa49da4a4209df6ad.zip
* fhandler.h (class fhandler_process): Add fd_type member.
* fhandler_process.cc (process_tab): Fix indentation. (fhandler_process::exists): Rely on format_process_fd returning file type in fd_type. (struct process_fd_t): Add fd_type member. (fhandler_process::fill_filebuf): Allow format_process_fd to set this->fd_type member. (format_process_fd): Fix path evaluation to allow recognizing trailing path components. Fix check for file descriptor path component. Return virt_symlink in fd_type if no trailing path compenents exist, return virt_fsdir otherwise and copy full resulting path into destbuf. * path.cc (path_conv::check): If /proc/$PID/fd symlink has trailing path components, reparse resulting path as if it's the incoming path. Add comment to wail over the outdated and hackish check method, and to explain what we do here.
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;
}