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:
@ -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;
|
||||
}
|
||||
|
Reference in New Issue
Block a user