From e67679fcac44be77bd0be880e9a938b9f300f2dd Mon Sep 17 00:00:00 2001 From: Ken Brown Date: Thu, 18 Feb 2021 10:18:41 -0500 Subject: [PATCH] Cygwin: define fhandler_fifo::fstat Previously fstat on a FIFO would call fhandler_base::fstat. The latter is not appropriate if fhandler_fifo::open has already been called (and O_PATH is not set), for the following reason. If a FIFO has been opened as a writer or duplexer, then it has an io_handle that is a pipe handle rather than a file handle. fhandler_base::fstat will use this handle and potentially return incorrect results. If the FIFO has been opened as a reader, then it has no io_handle, and a call to fhandler_base::fstat will lead to a call to fhandler_base::open. Opening the fhandler a second time can change it in undesired ways; for example, it can modify the flags and status_flags. The new fhandler_fifo::fstat avoids these problems by creating an fhandler_disk_file and calling its fstat method in case fhandler_fifo::open has already been called and O_PATH is not set. --- winsup/cygwin/fhandler.h | 1 + winsup/cygwin/fhandler_fifo.cc | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/winsup/cygwin/fhandler.h b/winsup/cygwin/fhandler.h index 12c45a5d7..21e1df172 100644 --- a/winsup/cygwin/fhandler.h +++ b/winsup/cygwin/fhandler.h @@ -1511,6 +1511,7 @@ public: ssize_t __reg3 raw_write (const void *ptr, size_t ulen); void fixup_after_fork (HANDLE); void fixup_after_exec (); + int __reg2 fstat (struct stat *buf); int __reg2 fstatvfs (struct statvfs *buf); select_record *select_read (select_stuff *); select_record *select_write (select_stuff *); diff --git a/winsup/cygwin/fhandler_fifo.cc b/winsup/cygwin/fhandler_fifo.cc index 8b67037cb..365f14053 100644 --- a/winsup/cygwin/fhandler_fifo.cc +++ b/winsup/cygwin/fhandler_fifo.cc @@ -1494,6 +1494,29 @@ errout: len = (size_t) -1; } +int __reg2 +fhandler_fifo::fstat (struct stat *buf) +{ + if (reader || writer || duplexer) + { + /* fhandler_fifo::open has been called, and O_PATH is not set. + We don't want to call fhandler_base::fstat. In the writer + and duplexer cases we have a handle, but it's a pipe handle + rather than a file handle, so it's not suitable for stat. In + the reader case we don't have a handle, but + fhandler_base::fstat would call fhandler_base::open, which + would modify the flags and status_flags. */ + fhandler_disk_file fh (pc); + fh.get_device () = FH_FS; + int res = fh.fstat (buf); + buf->st_dev = buf->st_rdev = dev (); + buf->st_mode = dev ().mode (); + buf->st_size = 0; + return res; + } + return fhandler_base::fstat (buf); +} + int __reg2 fhandler_fifo::fstatvfs (struct statvfs *sfs) {