From 14449a1dacca44c4f933d5fc207c7fa56e6c0fb7 Mon Sep 17 00:00:00 2001 From: Eric Blake Date: Sat, 5 Dec 2009 06:36:33 -0700 Subject: [PATCH] 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 --- ChangeLog | 7 +++++++ lib/dup-safer.c | 32 +++++++++++++++++++++++++++++++- lib/fd-safer.c | 29 +++++++++++++++++++++++++++++ lib/unistd-safer.h | 9 +++++++-- modules/cloexec | 1 + 5 files changed, 75 insertions(+), 3 deletions(-) diff --git a/ChangeLog b/ChangeLog index 0c1c87070..20535a05c 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,5 +1,12 @@ 2009-12-05 Eric Blake + 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. diff --git a/lib/dup-safer.c b/lib/dup-safer.c index 22b96babf..2af8b6a47 100644 --- a/lib/dup-safer.c +++ b/lib/dup-safer.c @@ -23,7 +23,6 @@ #include "unistd-safer.h" #include - #include /* Like dup, but do not return STDIN_FILENO, STDOUT_FILENO, or @@ -40,3 +39,34 @@ dup_safer (int fd) 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 diff --git a/lib/fd-safer.c b/lib/fd-safer.c index fb9900180..d2e1309c8 100644 --- a/lib/fd-safer.c +++ b/lib/fd-safer.c @@ -48,3 +48,32 @@ fd_safer (int fd) 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 */ diff --git a/lib/unistd-safer.h b/lib/unistd-safer.h index 033e857d7..af7d4ea6b 100644 --- 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 . */ -/* 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 diff --git a/modules/cloexec b/modules/cloexec index 7e41fec05..7d987de66 100644 --- a/modules/cloexec +++ b/modules/cloexec @@ -12,6 +12,7 @@ stdbool configure.ac: gl_CLOEXEC +gl_MODULE_INDICATOR([cloexec]) Makefile.am: -- 2.11.0