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

libio: Flush stream at freopen (BZ#21037)

As POSIX states [1] a freopen call should first flush the stream as if by a
call fflush.  C99 (n1256) and C11 (n1570) only states the function should
first close any file associated with the specific stream.  Although current
implementation only follow C specification, current BSD and other libc
implementation (musl) are in sync with POSIX and fflush the stream.

This patch change freopen{64} to fflush the stream before actually reopening
it (or returning if the stream does not support reopen).  It also changes the
Linux implementation to avoid a dynamic allocation on 'fd_to_filename'.

Checked on x86_64-linux-gnu.

	[BZ #21037]
	* libio/Makefile (tests): Add tst-memstream4 and tst-wmemstream4.
	* libio/freopen.c (freopen): Sync stream before reopen and adjust to
	new fd_to_filename interface.
	* libio/freopen64.c (freopen64): Likewise.
	* libio/tst-memstream.h: New file.
	* libio/tst-memstream4.c: Likewise.
	* libio/tst-wmemstream4.c: Likewise.
	* sysdeps/generic/fd_to_filename.h (fd_to_filename): Change signature.
	* sysdeps/unix/sysv/linux/fd_to_filename.h (fd_to_filename): Likewise
	and remove internal dynamic allocation.

[1] http://pubs.opengroup.org/onlinepubs/9699919799/
This commit is contained in:
Adhemerval Zanella
2017-07-13 16:43:24 -03:00
parent d0e91e8c4e
commit 0b727ed4d6
9 changed files with 213 additions and 48 deletions

View File

@ -24,28 +24,34 @@
This exception applies to code released by its copyright holders
in files containing the exception. */
#include "libioP.h"
#include "stdio.h"
#include <stdio.h>
#include <fcntl.h>
#include <stdlib.h>
#include <unistd.h>
#include <shlib-compat.h>
#include <libioP.h>
#include <fd_to_filename.h>
#include <kernel-features.h>
#include <shlib-compat.h>
FILE *
freopen (const char *filename, const char *mode, FILE *fp)
{
FILE *result;
FILE *result = NULL;
char fdfilename[FD_TO_FILENAME_SIZE];
CHECK_FILE (fp, NULL);
if (!(fp->_flags & _IO_IS_FILEBUF))
return NULL;
_IO_acquire_lock (fp);
/* First flush the stream (failure should be ignored). */
_IO_SYNC (fp);
if (!(fp->_flags & _IO_IS_FILEBUF))
goto end;
int fd = _IO_fileno (fp);
const char *gfilename = (filename == NULL && fd >= 0
? fd_to_filename (fd) : filename);
const char *gfilename
= filename != NULL ? filename : fd_to_filename (fd, fdfilename);
fp->_flags2 |= _IO_FLAGS2_NOCLOSE;
#if SHLIB_COMPAT (libc, GLIBC_2_0, GLIBC_2_1)
if (&_IO_stdin_used == NULL)
@ -101,9 +107,6 @@ freopen (const char *filename, const char *mode, FILE *fp)
__close (fd);
end:
if (filename == NULL)
free ((char *) gfilename);
_IO_release_lock (fp);
return result;
}