summary refs log tree commit diff
path: root/libio/fileops.c
diff options
context:
space:
mode:
Diffstat (limited to 'libio/fileops.c')
-rw-r--r--libio/fileops.c12
1 files changed, 10 insertions, 2 deletions
diff --git a/libio/fileops.c b/libio/fileops.c
index c75accdaf8..15e30a43c8 100644
--- a/libio/fileops.c
+++ b/libio/fileops.c
@@ -781,7 +781,8 @@ _IO_file_xsgetn (fp, data, n)
      void *data;
      _IO_size_t n;
 {
-  register _IO_size_t want, have, count;
+  register _IO_size_t want, have;
+  register _IO_ssize_t count;
   register char *s = data;
 
   want = n;
@@ -815,7 +816,7 @@ _IO_file_xsgetn (fp, data, n)
 	  /* If we now want less than a buffer, underflow and repeat
 	     the copy.  Otherwise, _IO_SYSREAD directly to
 	     the user buffer. */
-	  if (fp->_IO_buf_base && want < fp->_IO_buf_end - fp->_IO_buf_base)
+	  if (fp->_IO_buf_base && want <= fp->_IO_buf_end - fp->_IO_buf_base)
 	    {
 	      if (__underflow (fp) == EOF)
 		break;
@@ -823,6 +824,11 @@ _IO_file_xsgetn (fp, data, n)
 	      continue;
 	    }
 
+	  /* These must be set before the sysread as we might longjmp out
+	     waiting for input. */
+	  _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base, fp->_IO_buf_base);
+	  _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
+
 	  count = _IO_SYSREAD (fp, s, want);
 	  if (count <= 0)
 	    {
@@ -836,6 +842,8 @@ _IO_file_xsgetn (fp, data, n)
 
 	  s += count;
 	  want -= count;
+	  if (fp->_offset != _IO_pos_BAD)
+	    _IO_pos_adjust (fp->_offset, count);
 	}
     }