diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index 87d0ffe7c..f177b3a53 100644 --- a/winsup/cygwin/ChangeLog +++ b/winsup/cygwin/ChangeLog @@ -1,3 +1,21 @@ +2015-01-22 Corinna Vinschen + + * 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. + 2015-01-21 Corinna Vinschen * uinfo.cc (pwdgrp::fetch_account_from_windows): Allow fetching gid, diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 0128815e7..5fa6fe222 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -1,7 +1,7 @@ /* fhandler.h Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, 2006, - 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc. + 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Red Hat, Inc. This file is part of Cygwin. @@ -2064,6 +2064,7 @@ class pinfo; class fhandler_process: public fhandler_proc { pid_t pid; + virtual_ftype_t fd_type; public: fhandler_process (); virtual_ftype_t exists(); 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/ 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; } diff --git a/winsup/cygwin/path.cc b/winsup/cygwin/path.cc index dc8b97fc3..ff6751583 100644 --- a/winsup/cygwin/path.cc +++ b/winsup/cygwin/path.cc @@ -1,7 +1,7 @@ /* path.cc: path support. Copyright 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005, - 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014 Red Hat, Inc. + 2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013, 2014, 2015 Red Hat, Inc. This file is part of Cygwin. @@ -747,6 +747,8 @@ path_conv::check (const char *src, unsigned opt, full_path = THIS_path; } + retry_fs_via_processfd: + /* Convert to native path spec sans symbolic link info. */ error = mount_table->conv_to_win32_path (path_copy, full_path, dev, &sym.pflags); @@ -796,6 +798,29 @@ path_conv::check (const char *src, unsigned opt, fh->fill_filebuf (); symlen = sym.set (fh->get_filebuf ()); } + else if (file_type == virt_fsdir && dev == FH_PROCESS) + { + /* FIXME: This is YA bad hack to workaround that + we're checking for isvirtual_dev at this point. + This should only happen if the file is actually + a virtual file, and NOT already if the preceeding + path components constitute a virtual file. + + Anyway, what we do here is this: If the descriptor + symlink points to a dir, and if there are trailing + path components, it's actually pointing somewhere + else. The format_process_fd function returns the + full path, resolved symlink plus trailing path + components, in its filebuf. This is a POSIX path + we know nothing about, so we have to convert it to + native again, calling conv_to_win32_path. Since + basically nothing happened yet, just copy it over + into full_path and jump back to the + conv_to_win32_path call. What a mess. */ + stpcpy (path_copy, fh->get_filebuf ()); + delete fh; + goto retry_fs_via_processfd; + } delete fh; } switch (file_type) diff --git a/winsup/cygwin/release/1.7.34 b/winsup/cygwin/release/1.7.34 index f9a618c51..44a0cc435 100644 --- a/winsup/cygwin/release/1.7.34 +++ b/winsup/cygwin/release/1.7.34 @@ -82,3 +82,6 @@ Bug Fixes Addresses: https://cygwin.com/ml/cygwin/2015-01/msg00259.html https://cygwin.com/ml/cygwin/2015-01/msg00269.html +- Fix handling of /proc/$PID/fd/... paths with trailing path components + beyond the symlink path itself. + Addresses: https://cygwin.com/ml/cygwin/2015-01/msg00293.html