]> git.ipfire.org Git - thirdparty/glibc.git/commitdiff
hurd: Implement close_range and closefrom
authorSergey Bugaev <bugaevc@gmail.com>
Sat, 6 Nov 2021 15:35:24 +0000 (18:35 +0300)
committerSamuel Thibault <samuel.thibault@ens-lyon.org>
Sun, 7 Nov 2021 15:16:11 +0000 (16:16 +0100)
The close_range () function implements the same API as the Linux and
FreeBSD syscalls. It operates atomically and reliably. The specified
upper bound is clamped to the actual size of the file descriptor table;
it is expected that the most common use case is with last = UINT_MAX.

Like in the Linux syscall, it is also possible to pass the
CLOSE_RANGE_CLOEXEC flag to mark the file descriptors in the range
cloexec instead of acually closing them.

Also, add a Hurd version of the closefrom () function. Since unlike on
Linux, close_range () cannot fail due to being unuspported by the
running kernel, a fallback implementation is never necessary.

Signed-off-by: Sergey Bugaev <bugaevc@gmail.com>
Message-Id: <20211106153524.82700-1-bugaevc@gmail.com>

sysdeps/mach/hurd/Makefile
sysdeps/mach/hurd/Versions
sysdeps/mach/hurd/bits/unistd_ext.h [new file with mode: 0644]
sysdeps/mach/hurd/close_range.c [new file with mode: 0644]
sysdeps/mach/hurd/closefrom.c [new file with mode: 0644]
sysdeps/mach/hurd/i386/libc.abilist

index 17bb643c18d9a1cedd1d34d869d7257bde9a5c33..9acbe80f261487ffbaea74a89ae2c870ef943b5f 100644 (file)
@@ -196,7 +196,7 @@ sysdep_routines += cthreads
 endif
 
 ifeq (io, $(subdir))
-sysdep_routines += f_setlk close_nocancel close_nocancel_nostatus \
+sysdep_routines += f_setlk close_nocancel close_nocancel_nostatus close_range \
                   fcntl_nocancel open_nocancel openat_nocancel read_nocancel \
                   pread64_nocancel write_nocancel pwrite64_nocancel \
                   wait4_nocancel \
index 89dabd04853c727188d6a66289ad474ff4911955..d75e674bb6768a270c80571e0c8ac4aabf894749 100644 (file)
@@ -10,6 +10,9 @@ libc {
   GLIBC_2.32 {
     mremap;
   }
+  GLIBC_2.35 {
+    close_range;
+  }
   GLIBC_PRIVATE {
     # Functions shared with the dynamic linker
     __access; __access_noerrno; __libc_read; __libc_write; __libc_lseek64;
diff --git a/sysdeps/mach/hurd/bits/unistd_ext.h b/sysdeps/mach/hurd/bits/unistd_ext.h
new file mode 100644 (file)
index 0000000..288f504
--- /dev/null
@@ -0,0 +1,34 @@
+/* System-specific extensions of <unistd.h>, Hurd version.
+   Copyright (C) 2019-2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#ifndef _UNISTD_H
+# error "Never include <bits/unistd_ext.h> directly; use <unistd.h> instead."
+#endif
+
+#ifdef __USE_GNU
+
+/* Set the FD_CLOEXEC bit instead of closing the file descriptor.  */
+#define CLOSE_RANGE_CLOEXEC (1U << 2)
+
+/* Close the file descriptors from FIRST up to LAST, inclusive.
+   If CLOSE_RANGE_CLOEXEC is set in FLAGS, set the FD_CLOEXEC flag
+   instead of closing.  */
+extern int close_range (unsigned int __first, unsigned int __last,
+                       int __flags) __THROW;
+
+#endif /* __USE_GNU  */
diff --git a/sysdeps/mach/hurd/close_range.c b/sysdeps/mach/hurd/close_range.c
new file mode 100644 (file)
index 0000000..d6a2eab
--- /dev/null
@@ -0,0 +1,67 @@
+/* Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+#include <hurd.h>
+#include <hurd/fd.h>
+
+/* Close the file descriptors from FIRST up to LAST, inclusive.
+   If CLOSE_RANGE_CLOEXEC is set in FLAGS, set the FD_CLOEXEC flag
+   instead of closing.  */
+int
+__close_range (unsigned int first, unsigned int last,
+               int flags)
+{
+  int i;
+
+  if (first > last)
+    return __hurd_fail (EINVAL);
+  if (flags & ~CLOSE_RANGE_CLOEXEC)
+    return __hurd_fail (EINVAL);
+
+  HURD_CRITICAL_BEGIN;
+  __mutex_lock (&_hurd_dtable_lock);
+
+  for (i = first; i <= last && i < _hurd_dtablesize; i++)
+    {
+      struct hurd_fd *fd = _hurd_dtable[i];
+
+      if (fd == NULL || fd->port.port == MACH_PORT_NULL)
+        continue;
+
+      __spin_lock (&fd->port.lock);
+
+      if (flags & CLOSE_RANGE_CLOEXEC)
+        fd->flags |= FD_CLOEXEC;
+      else
+        {
+          _hurd_port_set (&fd->ctty, MACH_PORT_NULL);
+          _hurd_port_locked_set (&fd->port, MACH_PORT_NULL);
+        }
+
+      __spin_unlock (&fd->port.lock);
+    }
+
+  __mutex_unlock (&_hurd_dtable_lock);
+  HURD_CRITICAL_END;
+
+  return 0;
+}
+
+libc_hidden_def (__close_range)
+strong_alias (__close_range, __libc_close_range)
+weak_alias (__close_range, close_range)
diff --git a/sysdeps/mach/hurd/closefrom.c b/sysdeps/mach/hurd/closefrom.c
new file mode 100644 (file)
index 0000000..5d667cf
--- /dev/null
@@ -0,0 +1,29 @@
+/* Close a range of file descriptors.  Hurd version.
+   Copyright (C) 2021 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <https://www.gnu.org/licenses/>.  */
+
+#include <unistd.h>
+#include <sys/param.h>
+
+void
+__closefrom (int lowfd)
+{
+  int l = MAX (0, lowfd);
+
+  (void) __close_range (l, ~0U, 0);
+}
+weak_alias (__closefrom, closefrom)
index e849d6fa35456b4b0405ee6b793792f1298f4821..d8375b1073f70cc2398da7a1e101acfa48edd377 100644 (file)
@@ -2286,6 +2286,7 @@ GLIBC_2.34 shm_open F
 GLIBC_2.34 shm_unlink F
 GLIBC_2.34 timespec_getres F
 GLIBC_2.35 __memcmpeq F
+GLIBC_2.35 close_range F
 GLIBC_2.4 __confstr_chk F
 GLIBC_2.4 __fgets_chk F
 GLIBC_2.4 __fgets_unlocked_chk F