about summary refs log tree commit diff
diff options
context:
space:
mode:
authorUlrich Drepper <drepper@redhat.com>2003-09-06 05:16:44 +0000
committerUlrich Drepper <drepper@redhat.com>2003-09-06 05:16:44 +0000
commit483b8cc6cfd531611f6141b288a5e16e8010905c (patch)
tree4a1bc7ace3f9f72ed854b2e708aeaa0037757bdc
parentedc7ae4623eeb9a8112a6f89fbc91aae9f90cb6a (diff)
downloadglibc-483b8cc6cfd531611f6141b288a5e16e8010905c.tar.gz
glibc-483b8cc6cfd531611f6141b288a5e16e8010905c.tar.xz
glibc-483b8cc6cfd531611f6141b288a5e16e8010905c.zip
(_IO_new_file_overflow): Handle switching to write mode from read of backup buffer.
-rw-r--r--libio/fileops.c23
1 files changed, 17 insertions, 6 deletions
diff --git a/libio/fileops.c b/libio/fileops.c
index be683cd91e..1a633190c7 100644
--- a/libio/fileops.c
+++ b/libio/fileops.c
@@ -841,12 +841,23 @@ _IO_new_file_overflow (f, ch)
 	 makes room for subsequent output.
 	 Otherwise, set the read pointers to _IO_read_end (leaving that
 	 alone, so it can continue to correspond to the external position). */
-      if (f->_IO_read_ptr == f->_IO_buf_end)
-	f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
-      f->_IO_write_ptr = f->_IO_read_ptr;
-      f->_IO_write_base = f->_IO_write_ptr;
-      f->_IO_write_end = f->_IO_buf_end;
-      f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
+      if (__builtin_expect (_IO_in_backup (f), 0))
+	{
+	  size_t nbackup = f->_IO_read_end - f->_IO_read_ptr;
+	  _IO_free_backup_area (f);
+	  f->_IO_read_base -= MIN (nbackup,
+				   f->_IO_read_base - f->_IO_buf_base);
+	  f->_IO_read_ptr = f->_IO_read_base;
+	}
+      else
+	{
+	  if (f->_IO_read_ptr == f->_IO_buf_end)
+	    f->_IO_read_end = f->_IO_read_ptr = f->_IO_buf_base;
+	  f->_IO_write_ptr = f->_IO_read_ptr;
+	  f->_IO_write_base = f->_IO_write_ptr;
+	  f->_IO_write_end = f->_IO_buf_end;
+	  f->_IO_read_base = f->_IO_read_ptr = f->_IO_read_end;
+	}
 
       f->_flags |= _IO_CURRENTLY_PUTTING;
       if (f->_mode <= 0 && f->_flags & (_IO_LINE_BUF+_IO_UNBUFFERED))