1
0
mirror of https://sourceware.org/git/glibc.git synced 2025-07-28 00:21:52 +03:00

Fix a few problems in fopen and freopen

fopen should set the FD_CLOEXEC flag if requested evenif the kernel does
not support an aotmic operation.

freopen should reuse the file descriptor for the stream.  This is
especially important for calls to change the standard streams (stin,
stdout, stderr).
This commit is contained in:
Ulrich Drepper
2011-05-15 15:28:46 -04:00
parent bd25564e1e
commit 94b7cc3711
9 changed files with 143 additions and 39 deletions

View File

@ -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;
}