2011-08-17 21:42:24 +02:00
|
|
|
This reverts the following patch from upstream PR 12724,
|
|
|
|
which can cause surprising changes in fclose behaviour when multiple
|
|
|
|
file handles refer to the same file (fclose on one changes file position
|
|
|
|
on the other).
|
|
|
|
See bnc #711829.
|
|
|
|
|
|
|
|
git diff -R 'fcabc0f8b185f9e0a9289720be5ede6c39b3bf21^!'
|
|
|
|
|
|
|
|
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>
|
|
|
|
|
|
|
|
[BZ #12511]
|
2012-11-13 12:56:09 +01:00
|
|
|
Index: glibc-2.16.90/libio/Makefile
|
2012-08-28 14:25:24 +02:00
|
|
|
===================================================================
|
2012-11-13 12:56:09 +01:00
|
|
|
--- glibc-2.16.90.orig/libio/Makefile
|
|
|
|
+++ glibc-2.16.90/libio/Makefile
|
|
|
|
@@ -59,7 +59,7 @@ tests = tst_swprintf tst_wprintf tst_sws
|
2011-08-17 21:42:24 +02:00
|
|
|
tst-memstream1 tst-memstream2 \
|
|
|
|
tst-wmemstream1 tst-wmemstream2 \
|
|
|
|
bug-memstream1 bug-wmemstream1 \
|
2012-11-27 23:33:58 +01:00
|
|
|
- tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos bug-fclose1 tst-fseek \
|
|
|
|
+ tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos tst-fseek \
|
|
|
|
tst-fwrite-error
|
2012-11-13 12:56:09 +01:00
|
|
|
ifeq (yes,$(build-shared))
|
|
|
|
# Add test-fopenloc only if shared library is enabled since it depends on
|
|
|
|
Index: glibc-2.16.90/libio/bug-fclose1.c
|
2012-08-28 14:25:24 +02:00
|
|
|
===================================================================
|
2012-11-13 12:56:09 +01:00
|
|
|
--- glibc-2.16.90.orig/libio/bug-fclose1.c
|
2011-08-17 21:42:24 +02:00
|
|
|
+++ /dev/null
|
|
|
|
@@ -1,132 +0,0 @@
|
|
|
|
-// 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;
|
|
|
|
-}
|
2012-11-13 12:56:09 +01:00
|
|
|
Index: glibc-2.16.90/libio/fileops.c
|
2011-08-17 21:42:24 +02:00
|
|
|
===================================================================
|
2012-11-13 12:56:09 +01:00
|
|
|
--- glibc-2.16.90.orig/libio/fileops.c
|
|
|
|
+++ glibc-2.16.90/libio/fileops.c
|
2012-08-28 14:25:24 +02:00
|
|
|
@@ -155,21 +155,13 @@ int
|
2011-08-17 21:42:24 +02:00
|
|
|
_IO_new_file_close_it (fp)
|
|
|
|
_IO_FILE *fp;
|
|
|
|
{
|
|
|
|
+ int write_status;
|
|
|
|
if (!_IO_file_is_open (fp))
|
|
|
|
return EOF;
|
|
|
|
|
|
|
|
- int write_status;
|
|
|
|
- if (_IO_in_put_mode (fp))
|
|
|
|
+ if ((fp->_flags & _IO_NO_WRITES) == 0
|
|
|
|
+ && (fp->_flags & _IO_CURRENTLY_PUTTING) != 0)
|
|
|
|
write_status = _IO_do_flush (fp);
|
|
|
|
- else if (fp->_offset != _IO_pos_BAD && fp->_IO_read_base != NULL
|
|
|
|
- && !_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;
|
|
|
|
- }
|
|
|
|
else
|
|
|
|
write_status = 0;
|
|
|
|
|