diff options
Diffstat (limited to 'libio')
-rw-r--r-- | libio/fileops.c | 20 | ||||
-rw-r--r-- | libio/freopen.c | 64 | ||||
-rw-r--r-- | libio/freopen64.c | 61 | ||||
-rw-r--r-- | libio/libio.h | 4 | ||||
-rw-r--r-- | libio/oldfileops.c | 9 |
5 files changed, 121 insertions, 37 deletions
diff --git a/libio/fileops.c b/libio/fileops.c index 343afa6..2b696ab 100644 --- a/libio/fileops.c +++ b/libio/fileops.c @@ -180,7 +180,8 @@ _IO_new_file_close_it (fp) INTUSE(_IO_unsave_markers) (fp); - int close_status = _IO_SYSCLOSE (fp); + int close_status = ((fp->_flags2 & _IO_FLAGS2_NOCLOSE) == 0 + ? _IO_SYSCLOSE (fp) : 0); /* Free buffer. */ #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T @@ -328,11 +329,12 @@ _IO_new_file_fopen (fp, filename, mode, is32not64) case 'c': fp->_flags2 |= _IO_FLAGS2_NOTCANCEL; continue; -#ifdef O_CLOEXEC case 'e': +#ifdef O_CLOEXEC oflags |= O_CLOEXEC; - continue; #endif + fp->_flags2 |= _IO_FLAGS2_CLOEXEC; + continue; default: /* Ignore. */ continue; @@ -343,6 +345,18 @@ _IO_new_file_fopen (fp, filename, mode, is32not64) result = _IO_file_open (fp, filename, omode|oflags, oprot, read_write, is32not64); +#ifndef __ASSUME_O_CLOEXEC + if ((fp->_flags2 & _IO_FLAGS2_CLOEXEC) != 0 && __have_o_cloexec <= 0) + { + if (__have_o_cloexec == 0) + { + int flags = __fcntl (fd, F_GETFD); + __have_o_cloexec = (flags & FD_CLOEXEC) == 0 ? -1 : 1; + } + if (__have_o_cloexec < 0) + __fcntl (fd, F_SETFD, FD_CLOEXEC); + } +#endif #ifdef _LIBC if (result != NULL) diff --git a/libio/freopen.c b/libio/freopen.c index d80815f..20eda9d 100644 --- a/libio/freopen.c +++ b/libio/freopen.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993,95,96,97,98,2000,2001,2002,2003,2008 +/* Copyright (C) 1993,95,96,97,98,2000,2001,2002,2003,2008,2011 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -28,7 +28,9 @@ #include "libioP.h" #include "stdio.h" +#include <fcntl.h> #include <stdlib.h> +#include <unistd.h> #include <shlib-compat.h> #include <fd_to_filename.h> @@ -40,17 +42,14 @@ freopen (filename, mode, fp) FILE* fp; { FILE *result; - int fd = -1; CHECK_FILE (fp, NULL); if (!(fp->_flags & _IO_IS_FILEBUF)) return NULL; _IO_acquire_lock (fp); - if (filename == NULL && _IO_fileno (fp) >= 0) - { - fd = __dup (_IO_fileno (fp)); - if (fd != -1) - filename = fd_to_filename (fd); - } + int fd = _IO_fileno (fp); + const char *gfilename = (filename == NULL && fd >= 0 + ? fd_to_filename (fd) : filename); + fp->_flags2 |= _IO_FLAGS2_NOCLOSE; #if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1) if (&_IO_stdin_used == NULL) { @@ -61,7 +60,7 @@ freopen (filename, mode, fp) up here. */ _IO_old_file_close_it (fp); _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_old_file_jumps; - result = _IO_old_file_fopen (fp, filename, mode); + result = _IO_old_file_fopen (fp, gfilename, mode); } else #endif @@ -70,18 +69,53 @@ freopen (filename, mode, fp) _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps; if (_IO_vtable_offset (fp) == 0 && fp->_wide_data != NULL) fp->_wide_data->_wide_vtable = &_IO_wfile_jumps; - result = INTUSE(_IO_file_fopen) (fp, filename, mode, 1); + result = INTUSE(_IO_file_fopen) (fp, gfilename, mode, 1); if (result != NULL) result = __fopen_maybe_mmap (result); } + fp->_flags2 &= ~_IO_FLAGS2_NOCLOSE; if (result != NULL) - /* unbound stream orientation */ - result->_mode = 0; - if (fd != -1) { - __close (fd); - free ((char *) filename); + /* unbound stream orientation */ + result->_mode = 0; + + if (fd != -1) + { +#ifdef O_CLOEXEC +# ifndef __ASSUME_DUP3 + int newfd; + if (__have_dup3 < 0) + newfd = -1; + else + newfd = +# endif + dup3 (_IO_fileno (result), fd, + (result->_flags2 & _IO_FLAGS2_CLOEXEC) != 0 + ? O_CLOEXEC : 0); +#else +# define newfd 1 +#endif + +#ifndef __ASSUME_DUP3 + if (newfd < 0) + { + if (errno == ENOSYS) + __have_dup3 = -1; + + dup2 (_IO_fileno (result), fd); + if ((result->_flags2 & _IO_FLAGS2_CLOEXEC) != 0) + __fcntl (fd, F_SETFD, FD_CLOEXEC); + } +#endif + __close (_IO_fileno (result)); + _IO_fileno (result) = fd; + } } + else if (fd != -1) + __close (fd); + if (filename == NULL) + free ((char *) gfilename); + _IO_release_lock (fp); return result; } diff --git a/libio/freopen64.c b/libio/freopen64.c index 2dad6d7..99045c6 100644 --- a/libio/freopen64.c +++ b/libio/freopen64.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993,1995,1996,1997,1998,2000,2001,2002, 2003, 2008 +/* Copyright (C) 1993,1995,1996,1997,1998,2000,2001,2002, 2003, 2008, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. @@ -28,7 +28,9 @@ #include "libioP.h" #include "stdio.h" +#include <fcntl.h> #include <stdlib.h> +#include <unistd.h> #include <fd_to_filename.h> @@ -40,32 +42,63 @@ freopen64 (filename, mode, fp) { #ifdef _G_OPEN64 FILE *result; - int fd = -1; CHECK_FILE (fp, NULL); if (!(fp->_flags & _IO_IS_FILEBUF)) return NULL; _IO_acquire_lock (fp); - if (filename == NULL && _IO_fileno (fp) >= 0) - { - fd = __dup (_IO_fileno (fp)); - if (fd != -1) - filename = fd_to_filename (fd); - } + int fd = _IO_fileno (fp); + const char *gfilename = (filename == NULL && fd >= 0 + ? fd_to_filename (fd) : filename); + fp->_flags2 |= _IO_FLAGS2_NOCLOSE; INTUSE(_IO_file_close_it) (fp); _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps; if (_IO_vtable_offset (fp) == 0 && fp->_wide_data != NULL) fp->_wide_data->_wide_vtable = &_IO_wfile_jumps; - result = INTUSE(_IO_file_fopen) (fp, filename, mode, 0); + result = INTUSE(_IO_file_fopen) (fp, gfilename, mode, 0); + fp->_flags2 &= ~_IO_FLAGS2_NOCLOSE; if (result != NULL) result = __fopen_maybe_mmap (result); if (result != NULL) - /* unbound stream orientation */ - result->_mode = 0; - if (fd != -1) { - __close (fd); - free ((char *) filename); + /* unbound stream orientation */ + result->_mode = 0; + + if (fd != -1) + { +#ifdef O_CLOEXEC +# ifndef __ASSUME_DUP3 + int newfd; + if (__have_dup3 < 0) + newfd = -1; + else + newfd = +# endif + dup3 (_IO_fileno (result), fd, + (result->_flags2 & _IO_FLAGS2_CLOEXEC) != 0 + ? O_CLOEXEC : 0); +#else +# define newfd 1 +#endif + +#ifndef __ASSUME_DUP3 + if (newfd < 0) + { + if (errno == ENOSYS) + __have_dup3 = -1; + + dup2 (_IO_fileno (result), fd); + if ((result->_flags2 & _IO_FLAGS2_CLOEXEC) != 0) + __fcntl (fd, F_SETFD, FD_CLOEXEC); + } +#endif + __close (_IO_fileno (result)); + _IO_fileno (result) = fd; + } } + else if (fd != -1) + __close (fd); + if (filename == NULL) + free ((char *) gfilename); _IO_release_lock (fp); return result; #else diff --git a/libio/libio.h b/libio/libio.h index 3c9f2bd..bebc112 100644 --- a/libio/libio.h +++ b/libio/libio.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1991-1995,1997-2006,2007,2009 Free Software Foundation, Inc. +/* Copyright (C) 1991-1995,1997-2006,2007,2009,2011 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Per Bothner <bothner@cygnus.com>. @@ -145,6 +145,8 @@ #define _IO_FLAGS2_USER_WBUF 8 #ifdef _LIBC # define _IO_FLAGS2_SCANF_STD 16 +# define _IO_FLAGS2_NOCLOSE 32 +# define _IO_FLAGS2_CLOEXEC 64 #endif /* These are "formatting flags" matching the iostream fmtflags enum values. */ diff --git a/libio/oldfileops.c b/libio/oldfileops.c index be99a25..3e3daa8 100644 --- a/libio/oldfileops.c +++ b/libio/oldfileops.c @@ -155,7 +155,8 @@ _IO_old_file_close_it (fp) INTUSE(_IO_unsave_markers) (fp); - close_status = _IO_SYSCLOSE (fp); + close_status = ((fp->_flags2 & _IO_FLAGS2_NOCLOSE) == 0 + ? _IO_SYSCLOSE (fp) : 0); /* Free buffer. */ INTUSE(_IO_setb) (fp, NULL, NULL, 0); @@ -676,7 +677,7 @@ _IO_old_file_write (f, data, n) { f->_flags |= _IO_ERR_SEEN; break; - } + } to_do -= count; data = (void *) ((char *) data + count); } @@ -763,12 +764,12 @@ _IO_old_file_xsputn (f, data, n) do_write = to_do - (block_size >= 128 ? to_do % block_size : 0); if (do_write) - { + { count = old_do_write (f, s, do_write); to_do -= count; if (count < do_write) return n - to_do; - } + } /* Now write out the remainder. Normally, this will fit in the buffer, but it's somewhat messier for line-buffered files, |