mirror of
https://sourceware.org/git/glibc.git
synced 2024-11-21 20:40:05 +00: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:
parent
bd25564e1e
commit
94b7cc3711
16
ChangeLog
16
ChangeLog
@ -1,5 +1,21 @@
|
|||||||
2011-05-15 Ulrich Drepper <drepper@gmail.com>
|
2011-05-15 Ulrich Drepper <drepper@gmail.com>
|
||||||
|
|
||||||
|
* libio/freopen.c (freopen): Don't close old file descriptor
|
||||||
|
before the new one is opened. Instead dup the new file descriptor
|
||||||
|
to the old one after the new stream is created.
|
||||||
|
* libio/freopen64.c (freopen64): Likewise.
|
||||||
|
* libio/libio.h: Define _IO_FLAGS2_NOCLOSE and _IO_FLAGS2_CLOEXEC.
|
||||||
|
* libio/fileops.c (_IO_new_file_close_it): Handle new
|
||||||
|
_IO_FLAGS2_NOCLOSE flag.
|
||||||
|
(_IO_new_file_fopen): Set _IO_FLAGS2_CLOEXEC for "e" mode.
|
||||||
|
If _IO_file_open didn't set FD_CLOEXEC do it after the call.
|
||||||
|
* libio/oldfileops.c (_IO_old_file_close_it): Handle new
|
||||||
|
_IO_FLAGS2_NOCLOSE flag.
|
||||||
|
* include/unistd.h: Add hidden_proto for dup3.
|
||||||
|
Define __have_dup3.
|
||||||
|
* io/dup3.c: Define hidden symbol.
|
||||||
|
* sysdeps/unix/sysv/linux/kernel-features.h: Define __ASSUME_DUP3.
|
||||||
|
|
||||||
[BZ #7101]
|
[BZ #7101]
|
||||||
* posix/getopt.c (_getopt_internal_r): List all ambigious possibilities
|
* posix/getopt.c (_getopt_internal_r): List all ambigious possibilities
|
||||||
when an incomplete long option is used.
|
when an incomplete long option is used.
|
||||||
|
@ -79,6 +79,7 @@ char *__canonicalize_directory_name_internal (__const char *__thisdir,
|
|||||||
extern int __dup (int __fd);
|
extern int __dup (int __fd);
|
||||||
extern int __dup2 (int __fd, int __fd2);
|
extern int __dup2 (int __fd, int __fd2);
|
||||||
libc_hidden_proto (__dup2)
|
libc_hidden_proto (__dup2)
|
||||||
|
libc_hidden_proto (dup3)
|
||||||
extern int __execve (__const char *__path, char *__const __argv[],
|
extern int __execve (__const char *__path, char *__const __argv[],
|
||||||
char *__const __envp[]);
|
char *__const __envp[]);
|
||||||
extern long int __pathconf (__const char *__path, int __name);
|
extern long int __pathconf (__const char *__path, int __name);
|
||||||
@ -175,6 +176,7 @@ extern int __have_sock_cloexec;
|
|||||||
SOCK_CLOEXEC. Avoid defining separate variables for all of them
|
SOCK_CLOEXEC. Avoid defining separate variables for all of them
|
||||||
unless it is really necessary. */
|
unless it is really necessary. */
|
||||||
#define __have_pipe2 __have_sock_cloexec
|
#define __have_pipe2 __have_sock_cloexec
|
||||||
|
#define __have_dup3 __have_sock_cloexec
|
||||||
|
|
||||||
extern int __getlogin_r_loginuid (char *name, size_t namesize)
|
extern int __getlogin_r_loginuid (char *name, size_t namesize)
|
||||||
attribute_hidden;
|
attribute_hidden;
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
/* Copyright (C) 2008 Free Software Foundation, Inc.
|
/* Copyright (C) 2008, 2011 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -43,6 +43,7 @@ dup3 (fd, fd2, flags)
|
|||||||
__set_errno (ENOSYS);
|
__set_errno (ENOSYS);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
libc_hidden_def (dup3)
|
||||||
stub_warning (dup3)
|
stub_warning (dup3)
|
||||||
|
|
||||||
#include <stub-tag.h>
|
#include <stub-tag.h>
|
||||||
|
@ -180,7 +180,8 @@ _IO_new_file_close_it (fp)
|
|||||||
|
|
||||||
INTUSE(_IO_unsave_markers) (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. */
|
/* Free buffer. */
|
||||||
#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
|
#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
|
||||||
@ -328,11 +329,12 @@ _IO_new_file_fopen (fp, filename, mode, is32not64)
|
|||||||
case 'c':
|
case 'c':
|
||||||
fp->_flags2 |= _IO_FLAGS2_NOTCANCEL;
|
fp->_flags2 |= _IO_FLAGS2_NOTCANCEL;
|
||||||
continue;
|
continue;
|
||||||
#ifdef O_CLOEXEC
|
|
||||||
case 'e':
|
case 'e':
|
||||||
|
#ifdef O_CLOEXEC
|
||||||
oflags |= O_CLOEXEC;
|
oflags |= O_CLOEXEC;
|
||||||
continue;
|
|
||||||
#endif
|
#endif
|
||||||
|
fp->_flags2 |= _IO_FLAGS2_CLOEXEC;
|
||||||
|
continue;
|
||||||
default:
|
default:
|
||||||
/* Ignore. */
|
/* Ignore. */
|
||||||
continue;
|
continue;
|
||||||
@ -343,6 +345,18 @@ _IO_new_file_fopen (fp, filename, mode, is32not64)
|
|||||||
result = _IO_file_open (fp, filename, omode|oflags, oprot, read_write,
|
result = _IO_file_open (fp, filename, omode|oflags, oprot, read_write,
|
||||||
is32not64);
|
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
|
#ifdef _LIBC
|
||||||
if (result != NULL)
|
if (result != NULL)
|
||||||
|
@ -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.
|
Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
@ -28,7 +28,9 @@
|
|||||||
|
|
||||||
#include "libioP.h"
|
#include "libioP.h"
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <shlib-compat.h>
|
#include <shlib-compat.h>
|
||||||
#include <fd_to_filename.h>
|
#include <fd_to_filename.h>
|
||||||
@ -40,17 +42,14 @@ freopen (filename, mode, fp)
|
|||||||
FILE* fp;
|
FILE* fp;
|
||||||
{
|
{
|
||||||
FILE *result;
|
FILE *result;
|
||||||
int fd = -1;
|
|
||||||
CHECK_FILE (fp, NULL);
|
CHECK_FILE (fp, NULL);
|
||||||
if (!(fp->_flags & _IO_IS_FILEBUF))
|
if (!(fp->_flags & _IO_IS_FILEBUF))
|
||||||
return NULL;
|
return NULL;
|
||||||
_IO_acquire_lock (fp);
|
_IO_acquire_lock (fp);
|
||||||
if (filename == NULL && _IO_fileno (fp) >= 0)
|
int fd = _IO_fileno (fp);
|
||||||
{
|
const char *gfilename = (filename == NULL && fd >= 0
|
||||||
fd = __dup (_IO_fileno (fp));
|
? fd_to_filename (fd) : filename);
|
||||||
if (fd != -1)
|
fp->_flags2 |= _IO_FLAGS2_NOCLOSE;
|
||||||
filename = fd_to_filename (fd);
|
|
||||||
}
|
|
||||||
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
|
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
|
||||||
if (&_IO_stdin_used == NULL)
|
if (&_IO_stdin_used == NULL)
|
||||||
{
|
{
|
||||||
@ -61,7 +60,7 @@ freopen (filename, mode, fp)
|
|||||||
up here. */
|
up here. */
|
||||||
_IO_old_file_close_it (fp);
|
_IO_old_file_close_it (fp);
|
||||||
_IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_old_file_jumps;
|
_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
|
else
|
||||||
#endif
|
#endif
|
||||||
@ -70,18 +69,53 @@ freopen (filename, mode, fp)
|
|||||||
_IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps;
|
_IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps;
|
||||||
if (_IO_vtable_offset (fp) == 0 && fp->_wide_data != NULL)
|
if (_IO_vtable_offset (fp) == 0 && fp->_wide_data != NULL)
|
||||||
fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
|
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)
|
if (result != NULL)
|
||||||
result = __fopen_maybe_mmap (result);
|
result = __fopen_maybe_mmap (result);
|
||||||
}
|
}
|
||||||
|
fp->_flags2 &= ~_IO_FLAGS2_NOCLOSE;
|
||||||
if (result != NULL)
|
if (result != NULL)
|
||||||
/* unbound stream orientation */
|
|
||||||
result->_mode = 0;
|
|
||||||
if (fd != -1)
|
|
||||||
{
|
{
|
||||||
__close (fd);
|
/* unbound stream orientation */
|
||||||
free ((char *) filename);
|
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);
|
_IO_release_lock (fp);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
@ -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.
|
Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
@ -28,7 +28,9 @@
|
|||||||
|
|
||||||
#include "libioP.h"
|
#include "libioP.h"
|
||||||
#include "stdio.h"
|
#include "stdio.h"
|
||||||
|
#include <fcntl.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <fd_to_filename.h>
|
#include <fd_to_filename.h>
|
||||||
|
|
||||||
@ -40,32 +42,63 @@ freopen64 (filename, mode, fp)
|
|||||||
{
|
{
|
||||||
#ifdef _G_OPEN64
|
#ifdef _G_OPEN64
|
||||||
FILE *result;
|
FILE *result;
|
||||||
int fd = -1;
|
|
||||||
CHECK_FILE (fp, NULL);
|
CHECK_FILE (fp, NULL);
|
||||||
if (!(fp->_flags & _IO_IS_FILEBUF))
|
if (!(fp->_flags & _IO_IS_FILEBUF))
|
||||||
return NULL;
|
return NULL;
|
||||||
_IO_acquire_lock (fp);
|
_IO_acquire_lock (fp);
|
||||||
if (filename == NULL && _IO_fileno (fp) >= 0)
|
int fd = _IO_fileno (fp);
|
||||||
{
|
const char *gfilename = (filename == NULL && fd >= 0
|
||||||
fd = __dup (_IO_fileno (fp));
|
? fd_to_filename (fd) : filename);
|
||||||
if (fd != -1)
|
fp->_flags2 |= _IO_FLAGS2_NOCLOSE;
|
||||||
filename = fd_to_filename (fd);
|
|
||||||
}
|
|
||||||
INTUSE(_IO_file_close_it) (fp);
|
INTUSE(_IO_file_close_it) (fp);
|
||||||
_IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps;
|
_IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps;
|
||||||
if (_IO_vtable_offset (fp) == 0 && fp->_wide_data != NULL)
|
if (_IO_vtable_offset (fp) == 0 && fp->_wide_data != NULL)
|
||||||
fp->_wide_data->_wide_vtable = &_IO_wfile_jumps;
|
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)
|
if (result != NULL)
|
||||||
result = __fopen_maybe_mmap (result);
|
result = __fopen_maybe_mmap (result);
|
||||||
if (result != NULL)
|
if (result != NULL)
|
||||||
/* unbound stream orientation */
|
|
||||||
result->_mode = 0;
|
|
||||||
if (fd != -1)
|
|
||||||
{
|
{
|
||||||
__close (fd);
|
/* unbound stream orientation */
|
||||||
free ((char *) filename);
|
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);
|
_IO_release_lock (fp);
|
||||||
return result;
|
return result;
|
||||||
#else
|
#else
|
||||||
|
@ -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.
|
This file is part of the GNU C Library.
|
||||||
Written by Per Bothner <bothner@cygnus.com>.
|
Written by Per Bothner <bothner@cygnus.com>.
|
||||||
|
|
||||||
@ -145,6 +145,8 @@
|
|||||||
#define _IO_FLAGS2_USER_WBUF 8
|
#define _IO_FLAGS2_USER_WBUF 8
|
||||||
#ifdef _LIBC
|
#ifdef _LIBC
|
||||||
# define _IO_FLAGS2_SCANF_STD 16
|
# define _IO_FLAGS2_SCANF_STD 16
|
||||||
|
# define _IO_FLAGS2_NOCLOSE 32
|
||||||
|
# define _IO_FLAGS2_CLOEXEC 64
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* These are "formatting flags" matching the iostream fmtflags enum values. */
|
/* These are "formatting flags" matching the iostream fmtflags enum values. */
|
||||||
|
@ -155,7 +155,8 @@ _IO_old_file_close_it (fp)
|
|||||||
|
|
||||||
INTUSE(_IO_unsave_markers) (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. */
|
/* Free buffer. */
|
||||||
INTUSE(_IO_setb) (fp, NULL, NULL, 0);
|
INTUSE(_IO_setb) (fp, NULL, NULL, 0);
|
||||||
@ -676,7 +677,7 @@ _IO_old_file_write (f, data, n)
|
|||||||
{
|
{
|
||||||
f->_flags |= _IO_ERR_SEEN;
|
f->_flags |= _IO_ERR_SEEN;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
to_do -= count;
|
to_do -= count;
|
||||||
data = (void *) ((char *) data + 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);
|
do_write = to_do - (block_size >= 128 ? to_do % block_size : 0);
|
||||||
|
|
||||||
if (do_write)
|
if (do_write)
|
||||||
{
|
{
|
||||||
count = old_do_write (f, s, do_write);
|
count = old_do_write (f, s, do_write);
|
||||||
to_do -= count;
|
to_do -= count;
|
||||||
if (count < do_write)
|
if (count < do_write)
|
||||||
return n - to_do;
|
return n - to_do;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Now write out the remainder. Normally, this will fit in the
|
/* Now write out the remainder. Normally, this will fit in the
|
||||||
buffer, but it's somewhat messier for line-buffered files,
|
buffer, but it's somewhat messier for line-buffered files,
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
/* Set flags signalling availability of kernel features based on given
|
/* Set flags signalling availability of kernel features based on given
|
||||||
kernel version number.
|
kernel version number.
|
||||||
Copyright (C) 1999-2009, 2010 Free Software Foundation, Inc.
|
Copyright (C) 1999-2009, 2010, 2011 Free Software Foundation, Inc.
|
||||||
This file is part of the GNU C Library.
|
This file is part of the GNU C Library.
|
||||||
|
|
||||||
The GNU C Library is free software; you can redistribute it and/or
|
The GNU C Library is free software; you can redistribute it and/or
|
||||||
@ -496,6 +496,7 @@
|
|||||||
# define __ASSUME_PIPE2 1
|
# define __ASSUME_PIPE2 1
|
||||||
# define __ASSUME_EVENTFD2 1
|
# define __ASSUME_EVENTFD2 1
|
||||||
# define __ASSUME_SIGNALFD4 1
|
# define __ASSUME_SIGNALFD4 1
|
||||||
|
# define __ASSUME_DUP3 1
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* Support for the accept4 syscall was added in 2.6.28. */
|
/* Support for the accept4 syscall was added in 2.6.28. */
|
||||||
|
Loading…
Reference in New Issue
Block a user