diff options
author | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2011-05-15 12:22:50 +0000 |
---|---|---|
committer | joseph <joseph@7b3dc134-2b1b-0410-93df-9e9f96275f8d> | 2011-05-15 12:22:50 +0000 |
commit | bc5b8c65ef17547cbab9141d66798bbb3cae9c2a (patch) | |
tree | c41d5e47bf1ebffbe2fc7461f0131e7a8b16dc49 /libc/libio | |
parent | c0ce886c9f6b0580924e4f21180602f5e72d6570 (diff) | |
download | eglibc2-bc5b8c65ef17547cbab9141d66798bbb3cae9c2a.tar.gz |
Merge changes between r13800 and r13831 from /fsf/trunk.
git-svn-id: svn://svn.eglibc.org/trunk@13832 7b3dc134-2b1b-0410-93df-9e9f96275f8d
Diffstat (limited to 'libc/libio')
-rw-r--r-- | libc/libio/Makefile | 4 | ||||
-rw-r--r-- | libc/libio/bug-fclose1.c | 132 | ||||
-rw-r--r-- | libc/libio/fileops.c | 16 | ||||
-rw-r--r-- | libc/libio/tst_putwc.c | 11 |
4 files changed, 153 insertions, 10 deletions
diff --git a/libc/libio/Makefile b/libc/libio/Makefile index 6df1f4ba0..dd083c640 100644 --- a/libc/libio/Makefile +++ b/libc/libio/Makefile @@ -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. # The GNU C Library is free software; you can redistribute it and/or @@ -67,7 +67,7 @@ tests = test-fmemopen tst-ext tst-ext2 \ tst-mmap2-eofsync tst-mmap-offend bug-fopena+ \ bug-ungetc2 bug-ungetc3 bug-ungetc4 \ tst-memstream1 tst-memstream2 \ - bug-memstream1 tst-popen1 + bug-memstream1 tst-popen1 bug-fclose1 tests-$(OPTION_EGLIBC_LOCALE_CODE) \ += tst-swscanf tst-fgetws tst-fopenloc tst-setvbuf1 \ tst-ungetwc1 tst-ungetwc2 bug-ftell bug-ungetwc2 \ diff --git a/libc/libio/bug-fclose1.c b/libc/libio/bug-fclose1.c new file mode 100644 index 000000000..f1e09f5d4 --- /dev/null +++ b/libc/libio/bug-fclose1.c @@ -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; +} diff --git a/libc/libio/fileops.c b/libc/libio/fileops.c index 9b03a9c55..1f7356540 100644 --- a/libc/libio/fileops.c +++ b/libc/libio/fileops.c @@ -161,19 +161,27 @@ int _IO_new_file_close_it (fp) _IO_FILE *fp; { - int write_status, close_status; if (!_IO_file_is_open (fp)) return EOF; - if ((fp->_flags & _IO_NO_WRITES) == 0 - && (fp->_flags & _IO_CURRENTLY_PUTTING) != 0) + int write_status; + if (_IO_in_put_mode (fp)) 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; INTUSE(_IO_unsave_markers) (fp); - close_status = _IO_SYSCLOSE (fp); + int close_status = _IO_SYSCLOSE (fp); /* Free buffer. */ #if defined _LIBC || defined _GLIBCPP_USE_WCHAR_T diff --git a/libc/libio/tst_putwc.c b/libc/libio/tst_putwc.c index 1fd21e26c..c6e7a9dbd 100644 --- a/libc/libio/tst_putwc.c +++ b/libc/libio/tst_putwc.c @@ -1,5 +1,5 @@ /* Simple test of putwc in the C locale. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2011 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>, 2000. @@ -74,13 +74,16 @@ do_test (void) /* Now close the file, open it again, and read again. */ if (fclose (fp) != 0) { - printf ("failure during fclose(): %m"); + printf ("failure during fclose: %m\n"); res = 1; } fp = fopen (outname, "r"); if (fp == NULL) - error (EXIT_FAILURE, errno, "cannot reopen file"); + { + printf ("cannot reopen file: %m\n"); + return 1; + } /* We can remove the file now. */ remove (outname); @@ -104,7 +107,7 @@ do_test (void) if (fclose (fp) != 0) { - puts ("failure during fclose()"); + printf ("failure during fclose: %m\n"); res = 1; } |