On Tue, Mar 30, 2010 at 2:45 PM, Eric Blake <ebl...@redhat.com> wrote:
> But this is still the right thing to do, so it is only a misleading
> comment in the commit log.

In the end I opted to support O_CREAT, with the attached patch.

James.
From 4968d14544e0dc1a0519d3bbdefbcf8027f5c3ab Mon Sep 17 00:00:00 2001
From: James Youngman <j...@gnu.org>
Date: Tue, 30 Mar 2010 20:34:13 +0100
Subject: [PATCH] Support O_CREAT in open_cloexec.
To: findutils-patches@gnu.org

* lib/fdleak.c: Include <stdarg.h> and "cloexec.h".
(open_cloexec): Support O_CREAT.  Use O_CLOEXEC if it is available.
(O_CLOEXEC): #define to 0 if not already #defined.
* import-gnulib.config (modules): Import modules open (for
PROMOTED_MODE_T) and stdbool (for 'true').
* lib/fdleak.h: Update prototype of open_cloexec to allow mode to
be passed.

Signed-off-by: James Youngman <j...@gnu.org>
---
 ChangeLog            |   19 +++++++++++++++----
 configure.ac         |    3 +++
 import-gnulib.config |    2 ++
 lib/fdleak.c         |   38 ++++++++++++++++++++++++--------------
 lib/fdleak.h         |    2 +-
 5 files changed, 45 insertions(+), 19 deletions(-)

diff --git a/ChangeLog b/ChangeLog
index 38498ba..7f27bb1 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,15 +1,26 @@
 2010-03-30  James Youngman  <j...@gnu.org>
 
+	Support O_CREAT in open_cloexec.
+	* lib/fdleak.c: Include <stdarg.h> and "cloexec.h".
+	(open_cloexec): Support O_CREAT.  Use O_CLOEXEC if it is available.
+	(O_CLOEXEC): #define to 0 if not already #defined.
+	* lib/fdleak.h: Update prototype of open_cloexec to allow mode to
+	be passed.
+
+	* import-gnulib.config (modules): Import modules open (for
+	PROMOTED_MODE_T) and stdbool (for 'true').
+
+	Tolerate the absence of getrusage.
 	* configure.ac: Check for <sys/resource.h> and the getrusage
 	function.
 	* lib/fdleak.c: Don't #include <sys/resource.h> if we don't have it.
 	(get_max_fd): If neither /proc/self/fd not getrusage is available,
 	return _POSIX_OPEN_MAX.
-	(remember_non_cloexec_fds): Also check for leaks in file
-	descriptors 0, 1, 2, just in case the caller closed them.
+
+	Detect leaks in file descriptors 0, 1, 2.
+	* lib/fdleak.c: (remember_non_cloexec_fds): Also check for leaks
+	in file descriptors 0, 1, 2, just in case the caller closed them.
 	(find_first_leaked_fd): Likewise.
-	(open_cloexec): Make sure we are not creating a file (for some odd
-	system where O_CREAT is 0).
 
 2009-08-16  James Youngman  <j...@gnu.org>
 
diff --git a/configure.ac b/configure.ac
index 7647934..1de0328 100644
--- a/configure.ac
+++ b/configure.ac
@@ -145,6 +145,9 @@ AC_TYPE_MODE_T
 AC_STRUCT_ST_BLOCKS
 AC_CHECK_MEMBERS([struct stat.st_rdev])
 
+dnl fdleak.c uses PROMOTED_MODE_T, which is defined by gnulib.
+gl_PROMOTED_TYPE_MODE_T
+
 AC_MSG_CHECKING([whether we should use struct dirent.d_type, if available])
 if test x$ac_cv_d_type = xno; then
    AC_MSG_RESULT([no])
diff --git a/import-gnulib.config b/import-gnulib.config
index 833a9e6..b8288f1 100644
--- a/import-gnulib.config
+++ b/import-gnulib.config
@@ -60,6 +60,7 @@ mbsstr
 mktime
 modechange
 mountlist
+open
 pathmax
 progname
 quotearg
@@ -70,6 +71,7 @@ savedir
 selinux-at
 stat-macros
 stat-time
+stdbool
 stdint
 stpcpy
 strcasestr
diff --git a/lib/fdleak.c b/lib/fdleak.c
index 992ecfd..243c2ed 100644
--- a/lib/fdleak.c
+++ b/lib/fdleak.c
@@ -25,10 +25,13 @@
 #include <limits.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <stdarg.h>
 #include <assert.h>
+#include <stdbool.h>
 
 #include "dirent-safer.h"
 #include "extendbuf.h"
+#include "cloexec.h"
 #include "fdleak.h"
 #include "error.h"
 
@@ -54,6 +57,9 @@ static int *non_cloexec_fds;
 static size_t num_cloexec_fds;
 
 
+#if !defined(O_CLOEXEC)
+#define O_CLOEXEC 0
+#endif
 
 /* Determine the value of the largest open fd, on systems that
  * offer /proc/self/fd. */
@@ -296,25 +302,29 @@ find_first_leaked_fd (const int* prev_non_cloexec_fds, size_t n)
 }
 
 int
-open_cloexec (const char *path, int flags)
+open_cloexec (const char *path, int flags, ...)
 {
   int fd;
+  mode_t mode = 0;
 
-  /* Make sure we don't accidentally create a file, since we
-   * aren't passing a mode argument. */
-  assert ((flags & O_CREAT) == 0);
+  if (flags & O_CREAT)
+    {
+      /* this code is copied from gnulib's open-safer.c. */
+      va_list ap;
+      va_start (ap, flags);
 
-  fd = open (path, flags
-#if defined O_CLOEXEC
-	     |O_CLOEXEC
-#endif
-	     );
-  if (fd < 0)
-    return fd;
+      /* We have to use PROMOTED_MODE_T instead of mode_t, otherwise GCC 4
+         creates crashing code when 'mode_t' is smaller than 'int'.  */
+      mode = va_arg (ap, PROMOTED_MODE_T);
 
-#if !defined O_CLOEXEC
-  make_fd_cloexec (fd);
-#endif
+      va_end (ap);
+    }
+
+  fd = open (path, flags|O_CLOEXEC, mode);
+  if ((fd >= 0) && !O_CLOEXEC)
+    {
+      set_cloexec_flag (fd, true);
+    }
   return fd;
 }
 
diff --git a/lib/fdleak.h b/lib/fdleak.h
index 47b01cb..0bb6d51 100644
--- a/lib/fdleak.h
+++ b/lib/fdleak.h
@@ -19,5 +19,5 @@ void remember_non_cloexec_fds (void);
 void forget_non_cloexec_fds (void);
 void complain_about_leaky_fds (void);
 
-int open_cloexec(const char *path, int flags);
+int open_cloexec(const char *path, int flags, ...);
 
-- 
1.5.6.5

_______________________________________________
Findutils-patches mailing list
Findutils-patches@gnu.org
http://lists.gnu.org/mailman/listinfo/findutils-patches

Reply via email to