diff options
-rw-r--r-- | ChangeLog | 12 | ||||
-rw-r--r-- | libio/fileops.c | 42 | ||||
-rw-r--r-- | libio/iofopen.c | 12 | ||||
-rw-r--r-- | stdio-common/Makefile | 2 | ||||
-rw-r--r-- | stdio-common/tst-fdopen.c | 49 | ||||
-rw-r--r-- | stdio-common/tst-ungetc.c | 12 |
6 files changed, 116 insertions, 13 deletions
diff --git a/ChangeLog b/ChangeLog index 1e881130a9..4823a621a5 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,15 @@ +2002-02-25 Jakub Jelinek <jakub@redhat.com> + + * libio/iofopen.c (__fopen_maybe_mmap): Set the initial + position to fp->_offset if it is set. + * stdio-common/Makefile (tests): Add tst-fdopen. + * stdio-common/tst-fdopen.c: New test. + +2002-02-25 Jakub Jelinek <jakub@redhat.com> + + * libio/fileops.c (_IO_file_xsgetn_mmap): Handle reading from backup. + * stdio-common/tst-ungetc.c (main): Add another test. + 2002-02-25 Ulrich Drepper <drepper@redhat.com> * assert/assert-perr.c: Use INTUSE to reference functions and variables 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; } } } diff --git a/stdio-common/Makefile b/stdio-common/Makefile index b72e71efa2..2212df2745 100644 --- a/stdio-common/Makefile +++ b/stdio-common/Makefile @@ -56,7 +56,7 @@ tests := tstscanf test_rdwr test-popen tstgetln test-fseek \ scanf1 scanf2 scanf3 scanf4 scanf5 scanf7 scanf8 scanf9 scanf10 \ scanf11 scanf12 tst-tmpnam tst-cookie tst-obprintf tst-sscanf \ tst-swprintf tst-fseek tst-fmemopen test-vfprintf tst-gets \ - tst-perror tst-sprintf tst-rndseek + tst-perror tst-sprintf tst-rndseek tst-fdopen test-srcs = tst-unbputc tst-printf diff --git a/stdio-common/tst-fdopen.c b/stdio-common/tst-fdopen.c new file mode 100644 index 0000000000..bbdc4c88e9 --- /dev/null +++ b/stdio-common/tst-fdopen.c @@ -0,0 +1,49 @@ +/* Test for fdopen bugs. */ + +#include <stdio.h> +#include <unistd.h> +#include <fcntl.h> + +#define assert(x) \ + if (!(x)) \ + { \ + fputs ("test failed: " #x "\n", stderr); \ + retval = 1; \ + goto the_end; \ + } + +char buffer[256]; + +int +main (int argc, char *argv[]) +{ + char *name; + FILE *fp = NULL; + int retval = 0; + int c, fd; + + name = tmpnam (NULL); + fp = fopen (name, "w"); + assert (fp != NULL) + fputs ("foobar and baz", fp); + fclose (fp); + fp = NULL; + + fd = open (name, O_RDONLY); + assert (fd != -1); + assert (lseek (fd, 5, SEEK_SET) == 5); + /* The file position indicator associated with the new stream is set to + the position indicated by the file offset associated with the file + descriptor. */ + fp = fdopen (fd, "r"); + assert (fp != NULL); + assert (getc (fp) == 'r'); + assert (getc (fp) == ' '); + +the_end: + if (fp != NULL) + fclose (fp); + unlink (name); + + return retval; +} diff --git a/stdio-common/tst-ungetc.c b/stdio-common/tst-ungetc.c index 08819b7765..2cadf1cdaa 100644 --- a/stdio-common/tst-ungetc.c +++ b/stdio-common/tst-ungetc.c @@ -18,6 +18,7 @@ main (int argc, char *argv[]) FILE *fp = NULL; int retval = 0; int c; + char buffer[64]; name = tmpnam (NULL); fp = fopen (name, "w"); @@ -40,6 +41,17 @@ main (int argc, char *argv[]) assert (feof (fp) == 0); assert (getc (fp) == c); assert (getc (fp) == EOF); + fclose (fp); + fp = NULL; + + fp = fopen (name, "r"); + assert (fp != NULL); + assert (getc (fp) == 'b'); + assert (getc (fp) == 'l'); + assert (ungetc ('b', fp) == 'b'); + assert (fread (buffer, 1, 64, fp) == 2); + assert (buffer[0] == 'b'); + assert (buffer[1] == 'a'); the_end: if (fp != NULL) |