Re: [PATCH] Cygwin: introduce close_range

2024-01-14 Thread Christian Franke

Jon Turney wrote:

On 14/01/2024 16:07, Christian Franke wrote:

Recently I learned about the existence and usefulness of close_range():
https://github.com/smartmontools/smartmontools/issues/235

https://man.freebsd.org/cgi/man.cgi?query=close_range=2
https://man7.org/linux/man-pages/man2/close_range.2.html

Note that the above Linux man page is not fully correct. The include 
file "linux/close_range.h" exists, but provides only the defines. It 
is sufficient to include "unistd.h" as on FreeBSD.


The attached patch adds this to Cygwin. It does not implement the 
Linux-specific CLOSE_RANGE_UNSHARE as I have no idea how to do this :-)


This API should also be mentioned in the
"System interfaces compatible with GNU or Linux extensions" section of 
doc/posix.xml





Thanks for the info. I used the recent "Cygwin: introduce fallocate(2)" 
patch as a blueprint for which other files should be changed (fallocate 
is also missing in the posix.xml file).


I will provide a new patch soon which also fixes an unlikely but 
possible corner case: Pass a value larger than MAX_INT as lower limit.




Re: [PATCH] Cygwin: introduce close_range

2024-01-14 Thread Jon Turney

On 14/01/2024 16:07, Christian Franke wrote:

Recently I learned about the existence and usefulness of close_range():
https://github.com/smartmontools/smartmontools/issues/235

https://man.freebsd.org/cgi/man.cgi?query=close_range=2
https://man7.org/linux/man-pages/man2/close_range.2.html

Note that the above Linux man page is not fully correct. The include 
file "linux/close_range.h" exists, but provides only the defines. It is 
sufficient to include "unistd.h" as on FreeBSD.


The attached patch adds this to Cygwin. It does not implement the 
Linux-specific CLOSE_RANGE_UNSHARE as I have no idea how to do this :-)


This API should also be mentioned in the
"System interfaces compatible with GNU or Linux extensions" section of 
doc/posix.xml




[PATCH] Cygwin: introduce close_range

2024-01-14 Thread Christian Franke

Recently I learned about the existence and usefulness of close_range():
https://github.com/smartmontools/smartmontools/issues/235

https://man.freebsd.org/cgi/man.cgi?query=close_range=2
https://man7.org/linux/man-pages/man2/close_range.2.html

Note that the above Linux man page is not fully correct. The include 
file "linux/close_range.h" exists, but provides only the defines. It is 
sufficient to include "unistd.h" as on FreeBSD.


The attached patch adds this to Cygwin. It does not implement the 
Linux-specific CLOSE_RANGE_UNSHARE as I have no idea how to do this :-)


--
Regards,
Christian

From 2393e82a62e19e29e61ef3253e227c19ae7222eb Mon Sep 17 00:00:00 2001
From: Christian Franke 
Date: Sun, 14 Jan 2024 16:54:17 +0100
Subject: [PATCH] Cygwin: introduce close_range

This function closes or sets the close-on-exec flag for a specified
range of file descriptors.  It is available on FreeBSD and Linux.

Signed-off-by: Christian Franke 
---
 newlib/libc/include/sys/unistd.h   |  6 
 winsup/cygwin/cygwin.din   |  1 +
 winsup/cygwin/include/cygwin/version.h |  3 +-
 winsup/cygwin/release/3.5.0|  2 ++
 winsup/cygwin/syscalls.cc  | 42 ++
 winsup/doc/new-features.xml|  4 +++
 6 files changed, 57 insertions(+), 1 deletion(-)

diff --git a/newlib/libc/include/sys/unistd.h b/newlib/libc/include/sys/unistd.h
index 25532251c..f5f1963c8 100644
--- a/newlib/libc/include/sys/unistd.h
+++ b/newlib/libc/include/sys/unistd.h
@@ -26,6 +26,12 @@ int chown (const char *__path, uid_t __owner, gid_t 
__group);
 int chroot (const char *__path);
 #endif
 int close (int __fildes);
+#if defined(__CYGWIN__) && (__BSD_VISIBLE || __GNU_VISIBLE)
+/* Available on FreeBSD (__BSD_VISIBLE) and Linux (__GNU_VISIBLE). */
+int close_range (unsigned int __firstfd, unsigned int __lastfd, int 
__flags);
+/*  CLOSE_RANGE_UNSHARE 0x01 */ /* Linux only, not yet supported. */
+#define CLOSE_RANGE_CLOEXEC 0x02
+#endif
 #if __POSIX_VISIBLE >= 199209
 size_t confstr (int __name, char *__buf, size_t __len);
 #endif
diff --git a/winsup/cygwin/cygwin.din b/winsup/cygwin/cygwin.din
index 9b76ce67a..9e354acc6 100644
--- a/winsup/cygwin/cygwin.din
+++ b/winsup/cygwin/cygwin.din
@@ -347,6 +347,7 @@ clog10l NOSIGFE
 clogf NOSIGFE
 clogl NOSIGFE
 close SIGFE
+close_range SIGFE
 closedir SIGFE
 closelog SIGFE
 cnd_broadcast SIGFE
diff --git a/winsup/cygwin/include/cygwin/version.h 
b/winsup/cygwin/include/cygwin/version.h
index c8177c2b1..3036878c4 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -484,12 +484,13 @@ details. */
   347: Add c16rtomb, c32rtomb, mbrtoc16, mbrtoc32.
   348: Add c8rtomb, mbrtoc.
   349: Add fallocate.
+  350: Add close_range.
 
   Note that we forgot to bump the api for ualarm, strtoll, strtoull,
   sigaltstack, sethostname. */
 
 #define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 349
+#define CYGWIN_VERSION_API_MINOR 350
 
 /* There is also a compatibity version number associated with the shared memory
regions.  It is incremented when incompatible changes are made to the shared
diff --git a/winsup/cygwin/release/3.5.0 b/winsup/cygwin/release/3.5.0
index d0a6c2fc8..6209064a6 100644
--- a/winsup/cygwin/release/3.5.0
+++ b/winsup/cygwin/release/3.5.0
@@ -43,6 +43,8 @@ What's new:
 
 - New API calls: c8rtomb, c16rtomb, c32rtomb, mbrtoc8, mbrtoc16, mbrtoc32.
 
+- New API call: close_range (available on FreeBSD and Linux).
+
 - New API call: fallocate (Linux-specific).
 
 - Implement OSS-based sound mixer device (/dev/mixer).
diff --git a/winsup/cygwin/syscalls.cc b/winsup/cygwin/syscalls.cc
index 486db1db6..aba864475 100644
--- a/winsup/cygwin/syscalls.cc
+++ b/winsup/cygwin/syscalls.cc
@@ -85,6 +85,48 @@ close_all_files (bool norelease)
   cygheap->fdtab.unlock ();
 }
 
+/* Close or set the close-on-exec flag for all open file descriptors
+   from firstfd to lastfd.
+   Available on FreeBSD since 13 and Linux since 5.9 */
+extern "C" int
+close_range (unsigned int firstfd, unsigned int lastfd, int flags)
+{
+  pthread_testcancel ();
+
+  if (!(firstfd <= lastfd && (!flags || flags == CLOSE_RANGE_CLOEXEC)))
+{
+  set_errno (EINVAL);
+  return -1;
+}
+
+  cygheap->fdtab.lock ();
+
+  int size = (int) (lastfd < cygheap->fdtab.size ? lastfd + 1 :
+   cygheap->fdtab.size);
+
+  for (int i = (int) firstfd; i < size; i++)
+{
+  cygheap_fdget cfd (i, false, false);
+  if (cfd < 0)
+   continue;
+
+  if (!flags)
+   {
+ syscall_printf ("closing fd %d", i);
+ cfd->close_with_arch ();
+ cfd.release ();
+   }
+  else /* CLOSE_RANGE_CLOEXEC */
+   {
+ syscall_printf ("set FD_CLOEXEC on fd %d", i);
+ cfd->fcntl (F_SETFD, FD_CLOEXEC);
+   }
+}
+
+  cygheap->fdtab.unlock ();
+  return 0;
+}
+
 extern "C" int
 dup (int fd)
 {
diff --git a/winsup/doc/new-features.xml