From b93022a82dc523bcb731c2f69fb6e602c79060b5 Mon Sep 17 00:00:00 2001 From: Corinna Vinschen Date: Mon, 7 Jan 2019 19:33:11 +0100 Subject: [PATCH] Cygwin: open: support Linux-specific O_PATH flag Signed-off-by: Corinna Vinschen --- 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 22fa10688..2dc0068c9 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 1a7513763..9f5e0094f 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 3f93160d8..242ef60cd 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 d7d480fda..f48790a8a 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 6896b880f..59a0081e1 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 03a6a3aaf..c9e63a6ba 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 b99a21e8e..d6f81cab9 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 a1a529d32..b55e031bc 100644 --- a/winsup/doc/new-features.xml +++ b/winsup/doc/new-features.xml @@ -37,6 +37,10 @@ aforementioned new ioctl's on the command line. Support for exFAT. + +Support Linux-specific open(2) flag O_PATH. + + clock_nanosleep, pthread_condattr_setclock and timer_create now support all clocks, except CLOCK_PROCESS_CPUTIME_ID and CLOCK_THREAD_CPUTIME_ID.