summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog9
-rw-r--r--include/fcntl.h4
-rw-r--r--io/Makefile2
-rw-r--r--io/have_o_cloexec.c24
-rw-r--r--login/utmp_file.c8
-rw-r--r--sysdeps/unix/opendir.c32
6 files changed, 71 insertions, 8 deletions
diff --git a/ChangeLog b/ChangeLog
index 169bb7edaa..833ece1969 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,14 @@
2007-08-02 Ulrich Drepper <drepper@redhat.com>
+ * io/Makefile (aux): Add have_o_cloexec.
+ * include/fcntl.h: Declare __have_o_cloexec.
+ * io/have_o_cloexec.c: New file.
+ * sysdeps/unix/opendir.c (__opendir): Use O_CLOEXEC is available.
+ (__alloc_dir): If O_CLOEXEC has been used, don't duplicate the
+ fcntl call if not necessary.
+ * login/utmp_file.c (setutent_file): Use __have_o_cloexec instead
+ of local variable.
+
* sysdeps/unix/opendir.c (__alloc_dir): Don't initialize ->data.
Avoid memset, add explicit initialization.
* sysdeps/unix/dirstream.h (struct __dirstream): Move data elemtn
diff --git a/include/fcntl.h b/include/fcntl.h
index 1e919befb6..d5e5ddff02 100644
--- a/include/fcntl.h
+++ b/include/fcntl.h
@@ -41,4 +41,8 @@ extern void __atfct_seterrno_2 (int errval, int fd1, const char *buf1,
/* Flag determining whether the *at system calls are available. */
extern int __have_atfcts attribute_hidden;
+#ifdef O_CLOEXEC
+extern int __have_o_cloexec attribute_hidden;
+#endif
+
#endif
diff --git a/io/Makefile b/io/Makefile
index da589b118a..1acda4c8b6 100644
--- a/io/Makefile
+++ b/io/Makefile
@@ -54,6 +54,8 @@ routines := \
sendfile sendfile64 \
utimensat futimens
+aux := have_o_cloexec
+
# These routines will be omitted from the libc shared object.
# Instead the static object files will be included in a special archive
# linked against when the shared library will be used.
diff --git a/io/have_o_cloexec.c b/io/have_o_cloexec.c
new file mode 100644
index 0000000000..a83e8a4487
--- /dev/null
+++ b/io/have_o_cloexec.c
@@ -0,0 +1,24 @@
+/* Copyright (C) 2007 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, write to the Free
+ Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
+ 02111-1307 USA. */
+
+#include <fcntl.h>
+#include <kernel-features.h>
+
+#if defined O_CLOEXEC && !defined __ASSUME_O_CLOEXEC
+int __have_o_cloexec;
+#endif
diff --git a/login/utmp_file.c b/login/utmp_file.c
index 4a9e409454..a1c6a25716 100644
--- a/login/utmp_file.c
+++ b/login/utmp_file.c
@@ -157,9 +157,7 @@ setutent_file (void)
#ifndef __ASSUME_O_CLOEXEC
# ifdef O_CLOEXEC
- static int have_o_cloexec;
-
- if (have_o_cloexec <= 0)
+ if (__have_o_cloexec <= 0)
# endif
{
/* We have to make sure the file is `closed on exec'. */
@@ -167,8 +165,8 @@ setutent_file (void)
if (result >= 0)
{
# ifdef O_CLOEXEC
- if (have_o_cloexec == 0)
- have_o_cloexec = (result & FD_CLOEXEC) ? 1 : -1;
+ if (__have_o_cloexec == 0)
+ __have_o_cloexec = (result & FD_CLOEXEC) ? 1 : -1;
# endif
result = fcntl_not_cancel (file_fd, F_SETFD,
diff --git a/sysdeps/unix/opendir.c b/sysdeps/unix/opendir.c
index 36fb6f458d..34f5b719d3 100644
--- a/sysdeps/unix/opendir.c
+++ b/sysdeps/unix/opendir.c
@@ -31,6 +31,7 @@
#include <dirstream.h>
#include <not-cancel.h>
+#include <kernel-features.h>
/* opendir() must not accidentally open something other than a directory.
@@ -110,7 +111,11 @@ __opendir (const char *name)
}
}
- int fd = open_not_cancel_2 (name, O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE);
+ int flags = O_RDONLY|O_NDELAY|EXTRA_FLAGS|O_LARGEFILE;
+#ifdef O_CLOEXEC
+ flags |= O_CLOEXEC;
+#endif
+ int fd = open_not_cancel_2 (name, flags);
if (__builtin_expect (fd, 0) < 0)
return NULL;
@@ -138,12 +143,33 @@ __opendir (const char *name)
weak_alias (__opendir, opendir)
+#ifdef __ASSUME_O_CLOEXEC
+# define check_have_o_cloexec(fd) 1
+#else
+static int
+check_have_o_cloexec (int fd)
+{
+ if (__have_o_cloexec == 0)
+ __have_o_cloexec = (__fcntl (fd, F_GETFD, 0) & FD_CLOEXEC) == 0 ? -1 : 1;
+ return __have_o_cloexec > 0;
+}
+#endif
+
+
DIR *
internal_function
__alloc_dir (int fd, bool close_fd, const struct stat64 *statp)
{
- if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
- goto lose;
+ /* We always have to set the close-on-exit flag if the user provided
+ the file descriptor. Otherwise only if we have no working
+ O_CLOEXEC support. */
+#ifdef O_CLOEXEC
+ if (! close_fd || ! check_have_o_cloexec (fd))
+#endif
+ {
+ if (__builtin_expect (__fcntl (fd, F_SETFD, FD_CLOEXEC), 0) < 0)
+ goto lose;
+ }
size_t allocation;
#ifdef _STATBUF_ST_BLKSIZE