changeset 12392:2d61b44981dc

unistd-safer: allow preservation of cloexec status via flag If cloexec is in use, allow the ability to preserve cloexec flag across *_safer functions. * lib/unistd-safer.h (dup_safer_flag, fd_safer_flag): New prototypes. * lib/dup-safer.c (dup_safer_flag): New function. * lib/fd-safer.c (fd_safer_flag): Likewise. * modules/cloexec (configure.ac): Set witness. Signed-off-by: Eric Blake <ebb9@byu.net>
author Eric Blake <ebb9@byu.net>
date Sat, 05 Dec 2009 06:36:33 -0700
parents 5d8d7c606ce6
children dee22a21badb
files ChangeLog lib/dup-safer.c lib/fd-safer.c lib/unistd-safer.h modules/cloexec
diffstat 5 files changed, 75 insertions(+), 3 deletions(-) [+]
line wrap: on
line diff
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,12 @@
 2009-12-05  Eric Blake  <ebb9@byu.net>
 
+	unistd-safer: allow preservation of cloexec status via flag
+	* lib/unistd-safer.h (dup_safer_flag, fd_safer_flag): New
+	prototypes.
+	* lib/dup-safer.c (dup_safer_flag): New function.
+	* lib/fd-safer.c (fd_safer_flag): Likewise.
+	* modules/cloexec (configure.ac): Set witness.
+
 	test-dup2: enhance test
 	* modules/dup2-tests (Depends-on): Add cloexec.
 	* tests/test-dup2.c (main): Enhance test.
--- a/lib/dup-safer.c
+++ b/lib/dup-safer.c
@@ -23,7 +23,6 @@
 #include "unistd-safer.h"
 
 #include <fcntl.h>
-
 #include <unistd.h>
 
 /* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or
@@ -40,3 +39,34 @@
   return fd_safer (dup (fd));
 #endif
 }
+
+#if GNULIB_CLOEXEC
+
+# include "cloexec.h"
+
+# ifndef O_CLOEXEC
+#  define O_CLOEXEC 0
+# endif
+
+/* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or
+   STDERR_FILENO.  If FLAG contains O_CLOEXEC, behave like
+   fcntl(F_DUPFD_CLOEXEC) rather than fcntl(F_DUPFD).  */
+
+int
+dup_safer_flag (int fd, int flag)
+{
+  if (flag & O_CLOEXEC)
+    {
+# if defined F_DUPFD_CLOEXEC && !REPLACE_FCHDIR
+      return fcntl (fd, F_DUPFD_CLOEXEC, STDERR_FILENO + 1);
+# else
+      /* fd_safer_flag calls us back, but eventually the recursion
+         unwinds and does the right thing.  */
+      fd = dup_cloexec (fd);
+      return fd_safer_flag (fd, flag);
+# endif
+    }
+  return dup_safer (fd);
+}
+
+#endif
--- a/lib/fd-safer.c
+++ b/lib/fd-safer.c
@@ -48,3 +48,32 @@
 
   return fd;
 }
+
+#if GNULIB_CLOEXEC
+
+/* Return FD, unless FD would be a copy of standard input, output, or
+   error; in that case, return a duplicate of FD, closing FD.  If FLAG
+   contains O_CLOEXEC, the returned FD will have close-on-exec
+   semantics.  On failure to duplicate, close FD, set errno, and
+   return -1.  Preserve errno if FD is negative, so that the caller
+   can always inspect errno when the returned value is negative.
+
+   This function is usefully wrapped around functions that return file
+   descriptors, e.g., fd_safer_flag (open ("file", O_RDONLY | flag), flag).  */
+
+int
+fd_safer_flag (int fd, int flag)
+{
+  if (STDIN_FILENO <= fd && fd <= STDERR_FILENO)
+    {
+      int f = dup_safer_flag (fd, flag);
+      int e = errno;
+      close (fd);
+      errno = e;
+      fd = f;
+    }
+
+  return fd;
+}
+
+#endif /* GNULIB_CLOEXEC */
--- a/lib/unistd-safer.h
+++ b/lib/unistd-safer.h
@@ -1,6 +1,6 @@
 /* Invoke unistd-like functions, but avoid some glitches.
 
-   Copyright (C) 2001, 2003, 2005 Free Software Foundation, Inc.
+   Copyright (C) 2001, 2003, 2005, 2009 Free Software Foundation, Inc.
 
    This program is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
@@ -15,8 +15,13 @@
    You should have received a copy of the GNU General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
 
-/* Written by Paul Eggert.  */
+/* Written by Paul Eggert and Eric Blake.  */
 
 int dup_safer (int);
 int fd_safer (int);
 int pipe_safer (int[2]);
+
+#if GNULIB_CLOEXEC
+int dup_safer_flag (int, int);
+int fd_safer_flag (int, int);
+#endif
--- a/modules/cloexec
+++ b/modules/cloexec
@@ -12,6 +12,7 @@
 
 configure.ac:
 gl_CLOEXEC
+gl_MODULE_INDICATOR([cloexec])
 
 Makefile.am: