[newlib-cygwin] Cygwin: open: support Linux-specific O_PATH flag

Corinna Vinschen corinna@sourceware.org
Mon Jan 7 18:36:00 GMT 2019


https://sourceware.org/git/gitweb.cgi?p=newlib-cygwin.git;h=b93022a82dc523bcb731c2f69fb6e602c79060b5

commit b93022a82dc523bcb731c2f69fb6e602c79060b5
Author: Corinna Vinschen <corinna@vinschen.de>
Date:   Mon Jan 7 19:33:11 2019 +0100

    Cygwin: open: support Linux-specific O_PATH flag
    
    Signed-off-by: Corinna Vinschen <corinna@vinschen.de>

Diff:
---
 newlib/libc/include/sys/_default_fcntl.h |  2 ++
 winsup/cygwin/fhandler.cc                |  3 +++
 winsup/cygwin/ioctl.cc                   |  5 +++++
 winsup/cygwin/mmap.cc                    |  5 +++++
 winsup/cygwin/ntea.cc                    | 20 +++++++++++++++++
 winsup/cygwin/release/2.12.0             |  2 ++
 winsup/cygwin/syscalls.cc                | 37 ++++++++++++++++++++++++++++----
 winsup/doc/new-features.xml              |  4 ++++
 8 files changed, 74 insertions(+), 4 deletions(-)

diff --git a/newlib/libc/include/sys/_default_fcntl.h b/newlib/libc/include/sys/_default_fcntl.h
index 22fa106..2dc0068 100644
--- a/newlib/libc/include/sys/_default_fcntl.h
+++ b/newlib/libc/include/sys/_default_fcntl.h
@@ -35,6 +35,7 @@ extern "C" {
 #if defined (__CYGWIN__)
 #define	_FTMPFILE	0x800000
 #define	_FNOATIME	0x1000000
+#define	_FPATH		0x2000000
 #endif
 
 #define	O_ACCMODE	(O_RDONLY|O_WRONLY|O_RDWR)
@@ -80,6 +81,7 @@ extern "C" {
 #if __GNU_VISIBLE
 #define O_TMPFILE	_FTMPFILE
 #define O_NOATIME	_FNOATIME
+#define O_PATH		_FPATH
 #endif
 #endif
 
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index 1a75137..9f5e009 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -549,6 +549,9 @@ fhandler_base::open (int flags, mode_t mode)
 
   syscall_printf ("(%S, %y)", pc.get_nt_native_path (), flags);
 
+  if (flags & O_PATH)
+    query_open (query_read_attributes);
+
   /* Allow to reopen from handle.  This is utilized by
      open ("/proc/PID/fd/DESCRIPTOR", ...); */
   if (get_handle ())
diff --git a/winsup/cygwin/ioctl.cc b/winsup/cygwin/ioctl.cc
index 3f93160..242ef60 100644
--- a/winsup/cygwin/ioctl.cc
+++ b/winsup/cygwin/ioctl.cc
@@ -32,6 +32,11 @@ ioctl (int fd, int cmd, ...)
 
   debug_printf ("ioctl(fd %d, cmd %y)", fd, cmd);
   int res;
+  if (cfd->get_flags () & O_PATH)
+    {
+      set_errno (EBADF);
+      return -1;
+    }
   /* FIXME: This stinks.  There are collisions between cmd types
      depending on whether fd is associated with a pty master or not.
      Something to fix for Cygwin2.  CGF 2006-06-04 */
diff --git a/winsup/cygwin/mmap.cc b/winsup/cygwin/mmap.cc
index d7d480f..f48790a 100644
--- a/winsup/cygwin/mmap.cc
+++ b/winsup/cygwin/mmap.cc
@@ -930,6 +930,11 @@ mmap64 (void *addr, size_t len, int prot, int flags, int fd, off_t off)
       cygheap_fdget cfd (fd);
       if (cfd < 0)
 	goto out;
+      if (cfd->get_flags () & O_PATH)
+	{
+	  set_errno (EBADF);
+	  goto out;
+	}
 
       fh = cfd;
 
diff --git a/winsup/cygwin/ntea.cc b/winsup/cygwin/ntea.cc
index 6896b88..59a0081 100644
--- a/winsup/cygwin/ntea.cc
+++ b/winsup/cygwin/ntea.cc
@@ -426,6 +426,11 @@ fgetxattr (int fd, const char *name, void *value, size_t size)
   cygheap_fdget cfd (fd);
   if (cfd < 0)
     res = -1;
+  else if (cfd->get_flags () & O_PATH)
+    {
+      set_errno (EBADF);
+      res = -1;
+    }
   else
     res = cfd->fgetxattr (name, value, size);
   return res;
@@ -453,6 +458,11 @@ flistxattr (int fd, char *list, size_t size)
   cygheap_fdget cfd (fd);
   if (cfd < 0)
     res = -1;
+  else if (cfd->get_flags () & O_PATH)
+    {
+      set_errno (EBADF);
+      res = -1;
+    }
   else
     res = cfd->fgetxattr (NULL, list, size);
   return res;
@@ -523,6 +533,11 @@ fsetxattr (int fd, const char *name, const void *value, size_t size, int flags)
   cygheap_fdget cfd (fd);
   if (cfd < 0)
     res = -1;
+  else if (cfd->get_flags () & O_PATH)
+    {
+      set_errno (EBADF);
+      res = -1;
+    }
   else
     res = cfd->fsetxattr (name, value, size, flags);
   return res;
@@ -550,6 +565,11 @@ fremovexattr (int fd, const char *name)
   cygheap_fdget cfd (fd);
   if (cfd < 0)
     res = -1;
+  else if (cfd->get_flags () & O_PATH)
+    {
+      set_errno (EBADF);
+      res = -1;
+    }
   else
     res = cfd->fsetxattr (name, NULL, 0, 0);
   return res;
diff --git a/winsup/cygwin/release/2.12.0 b/winsup/cygwin/release/2.12.0
index 03a6a3a..c9e63a6 100644
--- a/winsup/cygwin/release/2.12.0
+++ b/winsup/cygwin/release/2.12.0
@@ -20,6 +20,8 @@ What's new:
 
 - Support for exFAT.
 
+- Support Linux-specific open(2) flag O_PATH.
+
 
 What changed:
 -------------
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index b99a21e..d6f81ca 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -1193,7 +1193,8 @@ read (int fd, void *ptr, size_t len)
       if (cfd < 0)
 	__leave;
 
-      if ((cfd->get_flags () & O_ACCMODE) == O_WRONLY)
+      if ((cfd->get_flags () & O_PATH)
+	  || (cfd->get_flags () & O_ACCMODE) == O_WRONLY)
 	{
 	  set_errno (EBADF);
 	  __leave;
@@ -1235,7 +1236,8 @@ readv (int fd, const struct iovec *const iov, const int iovcnt)
 	  __leave;
 	}
 
-      if ((cfd->get_flags () & O_ACCMODE) == O_WRONLY)
+      if ((cfd->get_flags () & O_PATH)
+	  || (cfd->get_flags () & O_ACCMODE) == O_WRONLY)
 	{
 	  set_errno (EBADF);
 	  __leave;
@@ -1263,6 +1265,11 @@ pread (int fd, void *ptr, size_t len, off_t off)
   cygheap_fdget cfd (fd);
   if (cfd < 0)
     res = -1;
+  else if (cfd->get_flags () & O_PATH)
+    {
+      set_errno (EBADF);
+      res = -1;
+    }
   else
     res = cfd->pread (ptr, len, off);
 
@@ -1283,7 +1290,8 @@ write (int fd, const void *ptr, size_t len)
       if (cfd < 0)
 	__leave;
 
-      if ((cfd->get_flags () & O_ACCMODE) == O_RDONLY)
+      if ((cfd->get_flags () & O_PATH)
+	  || (cfd->get_flags () & O_ACCMODE) == O_RDONLY)
 	{
 	  set_errno (EBADF);
 	  __leave;
@@ -1326,7 +1334,8 @@ writev (const int fd, const struct iovec *const iov, const int iovcnt)
 	  __leave;
 	}
 
-      if ((cfd->get_flags () & O_ACCMODE) == O_RDONLY)
+      if ((cfd->get_flags () & O_PATH)
+	  || (cfd->get_flags () & O_ACCMODE) == O_RDONLY)
 	{
 	  set_errno (EBADF);
 	  __leave;
@@ -1358,6 +1367,11 @@ pwrite (int fd, void *ptr, size_t len, off_t off)
   cygheap_fdget cfd (fd);
   if (cfd < 0)
     res = -1;
+  else if (cfd->get_flags () & O_PATH)
+    {
+      set_errno (EBADF);
+      res = -1;
+    }
   else
     res = cfd->pwrite (ptr, len, off);
 
@@ -1398,6 +1412,11 @@ open (const char *unix_path, int flags, ...)
       if (fd < 0)
 	__leave;		/* errno already set */
 
+      /* When O_PATH is specified in flags, flag bits other than O_CLOEXEC,
+	 O_DIRECTORY, and O_NOFOLLOW are ignored. */
+      if (flags & O_PATH)
+	flags &= (O_PATH | O_CLOEXEC | O_DIRECTORY | O_NOFOLLOW);
+
       int opt = PC_OPEN | PC_SYM_NOFOLLOW_PROCFD;
       opt |= (flags & (O_NOFOLLOW | O_EXCL)) ? PC_SYM_NOFOLLOW
 					     : PC_SYM_FOLLOW;
@@ -1685,6 +1704,11 @@ fchown32 (int fd, uid_t uid, gid_t gid)
       syscall_printf ("-1 = fchown (%d,...)", fd);
       return -1;
     }
+  else if (cfd->get_flags () & O_PATH)
+    {
+      set_errno (EBADF);
+      return -1;
+    }
 
   int res = cfd->fchown (uid, gid);
 
@@ -1756,6 +1780,11 @@ fchmod (int fd, mode_t mode)
       syscall_printf ("-1 = fchmod (%d, 0%o)", fd, mode);
       return -1;
     }
+  else if (cfd->get_flags () & O_PATH)
+    {
+      set_errno (EBADF);
+      return -1;
+    }
 
   return cfd->fchmod (FILTERED_MODE (mode));
 }
diff --git a/winsup/doc/new-features.xml b/winsup/doc/new-features.xml
index a1a529d..b55e031 100644
--- a/winsup/doc/new-features.xml
+++ b/winsup/doc/new-features.xml
@@ -38,6 +38,10 @@ Support for exFAT.
 </para></listitem>
 
 <listitem><para>
+Support Linux-specific open(2) flag O_PATH.
+</para></listitem>
+
+<listitem><para>
 clock_nanosleep, pthread_condattr_setclock and timer_create now support
 all clocks, except CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID.
 </para></listitem>



More information about the Cygwin-cvs mailing list