aboutsummaryrefslogtreecommitdiff
path: root/libio
diff options
context:
space:
mode:
Diffstat (limited to 'libio')
-rw-r--r--libio/fileops.c42
-rw-r--r--libio/iofopen.c12
2 files changed, 42 insertions, 12 deletions
diff --git a/libio/fileops.c b/libio/fileops.c
index 92f1be49e7..dd8960ef03 100644
--- a/libio/fileops.c
+++ b/libio/fileops.c
@@ -1197,28 +1197,54 @@ _IO_file_xsgetn_mmap (fp, data, n)
{
register _IO_size_t have;
char *read_ptr = fp->_IO_read_ptr;
+ register char *s = (char *) data;
have = fp->_IO_read_end - fp->_IO_read_ptr;
if (have < n)
{
- /* Maybe the read buffer is not yet fully set up. */
- fp->_IO_read_ptr = fp->_IO_read_end;
- if (fp->_IO_read_end < fp->_IO_buf_end
- && _IO_file_underflow_mmap (fp) != EOF)
- have = fp->_IO_read_end - read_ptr;
+ if (__builtin_expect (_IO_in_backup (fp), 0))
+ {
+#ifdef _LIBC
+ s = __mempcpy (s, read_ptr, have);
+#else
+ memcpy (s, read_ptr, have);
+ s += have;
+#endif
+ n -= have;
+ _IO_switch_to_main_get_area (fp);
+ read_ptr = fp->_IO_read_ptr;
+ have = fp->_IO_read_end - fp->_IO_read_ptr;
+ }
+
+ if (have < n)
+ {
+ /* Maybe the read buffer is not yet fully set up. */
+ fp->_IO_read_ptr = fp->_IO_read_end;
+ if (fp->_IO_read_end < fp->_IO_buf_end
+ && _IO_file_underflow_mmap (fp) != EOF)
+ have = fp->_IO_read_end - read_ptr;
+ }
}
if (have == 0)
- fp->_flags |= _IO_EOF_SEEN;
+ {
+ if (s == (char *) data)
+ fp->_flags |= _IO_EOF_SEEN;
+ }
else
{
have = MIN (have, n);
- memcpy (data, read_ptr, have);
+#ifdef _LIBC
+ s = __mempcpy (s, read_ptr, have);
+#else
+ memcpy (s, read_ptr, have);
+ s += have;
+#endif
fp->_IO_read_ptr = read_ptr + have;
}
- return have;
+ return s - (char *) data;
}
struct _IO_jump_t _IO_file_jumps =
diff --git a/libio/iofopen.c b/libio/iofopen.c
index 4bb780de13..c1681a4a10 100644
--- a/libio/iofopen.c
+++ b/libio/iofopen.c
@@ -53,7 +53,9 @@ __fopen_maybe_mmap (fp)
if (_IO_SYSSTAT (fp, &st) == 0
&& S_ISREG (st.st_mode) && st.st_size != 0
/* Limit the file size to 1MB for 32-bit machines. */
- && (sizeof (ptrdiff_t) > 4 || st.st_size < 1*1024*1024))
+ && (sizeof (ptrdiff_t) > 4 || st.st_size < 1*1024*1024)
+ /* Sanity check. */
+ && (fp->_offset == _IO_pos_BAD || fp->_offset <= st.st_size))
{
/* Try to map the file. */
void *p;
@@ -72,15 +74,17 @@ __fopen_maybe_mmap (fp)
underflow functions which never tries to read
anything from the file. */
INTUSE(_IO_setb) (fp, p, (char *) p + st.st_size, 0);
- _IO_setg (fp, p, p, p);
+
+ if (fp->_offset == _IO_pos_BAD)
+ fp->_offset = 0;
+
+ _IO_setg (fp, p, p + fp->_offset, p + fp->_offset);
if (fp->_mode <= 0)
_IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps_mmap;
else
_IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_wfile_jumps_mmap;
fp->_wide_data->_wide_vtable = &_IO_wfile_jumps_mmap;
-
- fp->_offset = 0;
}
}
}