mirror of
git://sourceware.org/git/glibc.git
synced 2025-02-23 13:09:58 +08:00
Fix file descriptor position after fclose
fclose should leave the file descriptor position after the last read or written byte.
This commit is contained in:
parent
320a5dc07b
commit
fcabc0f8b1
@ -1,3 +1,11 @@
|
|||||||
|
2011-05-13 Ulrich Drepper <drepper@gmail.com>
|
||||||
|
|
||||||
|
[BZ #12724]
|
||||||
|
* libio/fileops.c (_IO_new_file_close_it): Always flush when
|
||||||
|
currently writing and seek to current position when not.
|
||||||
|
* libio/Makefile (tests): Add bug-fclose1.
|
||||||
|
* libio/bug-fclose1.c: New file.
|
||||||
|
|
||||||
2011-05-12 Ulrich Drepper <drepper@gmail.com>
|
2011-05-12 Ulrich Drepper <drepper@gmail.com>
|
||||||
|
|
||||||
[BZ #12511]
|
[BZ #12511]
|
||||||
|
5
NEWS
5
NEWS
@ -1,4 +1,4 @@
|
|||||||
GNU C Library NEWS -- history of user-visible changes. 2011-5-11
|
GNU C Library NEWS -- history of user-visible changes. 2011-5-13
|
||||||
Copyright (C) 1992-2009, 2010, 2011 Free Software Foundation, Inc.
|
Copyright (C) 1992-2009, 2010, 2011 Free Software Foundation, Inc.
|
||||||
See the end for copying conditions.
|
See the end for copying conditions.
|
||||||
|
|
||||||
@ -13,7 +13,8 @@ Version 2.14
|
|||||||
12052, 12158, 12178, 12200, 12346, 12393, 12420, 12445, 12449, 12454,
|
12052, 12158, 12178, 12200, 12346, 12393, 12420, 12445, 12449, 12454,
|
||||||
12460, 12469, 12489, 12509, 12510, 12511, 12518, 12527, 12541, 12545,
|
12460, 12469, 12489, 12509, 12510, 12511, 12518, 12527, 12541, 12545,
|
||||||
12551, 12583, 12587, 12597, 12611, 12625, 12631, 12650, 12653, 12655,
|
12551, 12583, 12587, 12597, 12611, 12625, 12631, 12650, 12653, 12655,
|
||||||
12660, 12681, 12685, 12711, 12713, 12714, 12717, 12723, 12734, 12738
|
12660, 12681, 12685, 12711, 12713, 12714, 12717, 12723, 12724, 12734,
|
||||||
|
12738
|
||||||
|
|
||||||
* The RPC implementation in libc is obsoleted. Old programs keep working
|
* The RPC implementation in libc is obsoleted. Old programs keep working
|
||||||
but new programs cannot be linked with the routines in libc anymore.
|
but new programs cannot be linked with the routines in libc anymore.
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
# Copyright (C) 1995-2004,2006,2007,2008,2009 Free Software Foundation, Inc.
|
# Copyright (C) 1995-2004,2006-2009,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
|
||||||
@ -58,7 +58,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
|
|||||||
tst-memstream1 tst-memstream2 \
|
tst-memstream1 tst-memstream2 \
|
||||||
tst-wmemstream1 tst-wmemstream2 \
|
tst-wmemstream1 tst-wmemstream2 \
|
||||||
bug-memstream1 bug-wmemstream1 \
|
bug-memstream1 bug-wmemstream1 \
|
||||||
tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos
|
tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos bug-fclose1
|
||||||
test-srcs = test-freopen
|
test-srcs = test-freopen
|
||||||
|
|
||||||
all: # Make this the default target; it will be defined in Rules.
|
all: # Make this the default target; it will be defined in Rules.
|
||||||
|
132
libio/bug-fclose1.c
Normal file
132
libio/bug-fclose1.c
Normal file
@ -0,0 +1,132 @@
|
|||||||
|
// BZ #12724
|
||||||
|
|
||||||
|
static void do_prepare (void);
|
||||||
|
#define PREPARE(argc, argv) do_prepare ()
|
||||||
|
static int do_test (void);
|
||||||
|
#define TEST_FUNCTION do_test()
|
||||||
|
#include "../test-skeleton.c"
|
||||||
|
|
||||||
|
|
||||||
|
static int fd;
|
||||||
|
|
||||||
|
|
||||||
|
static void
|
||||||
|
do_prepare (void)
|
||||||
|
{
|
||||||
|
fd = create_temp_file ("bug-fclose1.", NULL);
|
||||||
|
if (fd == -1)
|
||||||
|
{
|
||||||
|
printf ("cannot create temporary file: %m\n");
|
||||||
|
exit (1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int
|
||||||
|
do_test (void)
|
||||||
|
{
|
||||||
|
static const char pattern[] = "hello world";
|
||||||
|
|
||||||
|
/* Prepare a seekable file. */
|
||||||
|
if (write (fd, pattern, sizeof pattern) != sizeof pattern)
|
||||||
|
{
|
||||||
|
printf ("cannot write pattern: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (lseek (fd, 1, SEEK_SET) != 1)
|
||||||
|
{
|
||||||
|
printf ("cannot seek after write: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Create an output stream visiting the file; when it is closed, all
|
||||||
|
other file descriptors visiting the file must see the new file
|
||||||
|
position. */
|
||||||
|
int fd2 = dup (fd);
|
||||||
|
if (fd2 < 0)
|
||||||
|
{
|
||||||
|
printf ("cannot duplicate descriptor for writing: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
FILE *f = fdopen (fd2, "w");
|
||||||
|
if (f == NULL)
|
||||||
|
{
|
||||||
|
printf ("first fdopen failed: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (fputc (pattern[1], f) != pattern[1])
|
||||||
|
{
|
||||||
|
printf ("fputc failed: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (fclose (f) != 0)
|
||||||
|
{
|
||||||
|
printf ("first fclose failed: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
if (lseek (fd2, 0, SEEK_CUR) != -1)
|
||||||
|
{
|
||||||
|
printf ("lseek after fclose after write did not fail\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (errno != EBADF)
|
||||||
|
{
|
||||||
|
printf ("lseek after fclose after write did not fail with EBADF: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
off_t o = lseek (fd, 0, SEEK_CUR);
|
||||||
|
if (o != 2)
|
||||||
|
{
|
||||||
|
printf ("\
|
||||||
|
lseek on original descriptor after first fclose returned %ld, expected 2\n",
|
||||||
|
(long int) o);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Likewise for an input stream. */
|
||||||
|
fd2 = dup (fd);
|
||||||
|
if (fd2 < 0)
|
||||||
|
{
|
||||||
|
printf ("cannot duplicate descriptor for reading: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
f = fdopen (fd2, "r");
|
||||||
|
if (f == NULL)
|
||||||
|
{
|
||||||
|
printf ("second fdopen failed: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
char c = fgetc (f);
|
||||||
|
if (c != pattern[2])
|
||||||
|
{
|
||||||
|
printf ("getc returned %c, expected %c\n", c, pattern[2]);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (fclose (f) != 0)
|
||||||
|
{
|
||||||
|
printf ("second fclose failed: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
errno = 0;
|
||||||
|
if (lseek (fd2, 0, SEEK_CUR) != -1)
|
||||||
|
{
|
||||||
|
printf ("lseek after fclose after read did not fail\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (errno != EBADF)
|
||||||
|
{
|
||||||
|
printf ("lseek after fclose after read did not fail with EBADF: %m\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
o = lseek (fd, 0, SEEK_CUR);
|
||||||
|
if (o != 3)
|
||||||
|
{
|
||||||
|
printf ("\
|
||||||
|
lseek on original descriptor after second fclose returned %ld, expected 3\n",
|
||||||
|
(long int) o);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
@ -160,19 +160,25 @@ int
|
|||||||
_IO_new_file_close_it (fp)
|
_IO_new_file_close_it (fp)
|
||||||
_IO_FILE *fp;
|
_IO_FILE *fp;
|
||||||
{
|
{
|
||||||
int write_status, close_status;
|
|
||||||
if (!_IO_file_is_open (fp))
|
if (!_IO_file_is_open (fp))
|
||||||
return EOF;
|
return EOF;
|
||||||
|
|
||||||
if ((fp->_flags & _IO_NO_WRITES) == 0
|
int write_status;
|
||||||
&& (fp->_flags & _IO_CURRENTLY_PUTTING) != 0)
|
if (_IO_in_put_mode (fp))
|
||||||
write_status = _IO_do_flush (fp);
|
write_status = _IO_do_flush (fp);
|
||||||
else
|
else if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
|
||||||
write_status = 0;
|
&& !_IO_in_backup (fp))
|
||||||
|
{
|
||||||
|
off64_t o = _IO_SEEKOFF (fp, 0, _IO_seek_cur, 0);
|
||||||
|
if (o == WEOF)
|
||||||
|
write_status = EOF;
|
||||||
|
else
|
||||||
|
write_status = _IO_SYSSEEK (fp, o, SEEK_SET) < 0 ? EOF : 0;
|
||||||
|
}
|
||||||
|
|
||||||
INTUSE(_IO_unsave_markers) (fp);
|
INTUSE(_IO_unsave_markers) (fp);
|
||||||
|
|
||||||
close_status = _IO_SYSCLOSE (fp);
|
int close_status = _IO_SYSCLOSE (fp);
|
||||||
|
|
||||||
/* Free buffer. */
|
/* Free buffer. */
|
||||||
#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
|
#if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T
|
||||||
|
Loading…
Reference in New Issue
Block a user