diff options
-rw-r--r-- | ChangeLog | 15 | ||||
-rw-r--r-- | libio/fileops.c | 89 | ||||
-rw-r--r-- | libio/iofopen.c | 17 | ||||
-rw-r--r-- | libio/libioP.h | 5 | ||||
-rw-r--r-- | libio/tst-widetext.c | 6 | ||||
-rw-r--r-- | libio/wfileops.c | 68 | ||||
-rw-r--r-- | stdio-common/tst-rndseek.c | 26 |
7 files changed, 158 insertions, 68 deletions
@@ -1,3 +1,18 @@ +2002-01-19 Ulrich Drepper <drepper@redhat.com> + + * libio/fileops.c (_IO_file_underflow_mmap): Don't define as static. + Set offset if read end wasn't the buffer end. + (_IO_file_seekoff_mmap): New function. + (_IO_file_xsgetn_mmap): New function. + (_IO_file_jumps_mmap): Use the two new functions. + * libio/wfileops.c (_IO_wfile_underflow_mmap): Handle end read buffer + != end buffer. + * libio/libioP.h: Declare _IO_file_seekoff_mmap and + _IO_file_underflow_mmap. + * libio/iofopen.c: Don't position file descriptor at end of file. + * libio/tst-widetext.c: Improve error messages. + * stdio-common/tst-rndseek.c: Likewise. + 2002-01-18 Ulrich Drepper <drepper@redhat.com> * sysdeps/unix/sysv/linux/bits/statvfs.h: Avoid warning about comma at diff --git a/libio/fileops.c b/libio/fileops.c index 32fa524..60481b1 100644 --- a/libio/fileops.c +++ b/libio/fileops.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993, 1995, 1997-2000, 2001 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1995, 1997-2001, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Per Bothner <bothner@cygnus.com>. @@ -33,6 +33,7 @@ #include "libioP.h" #include <assert.h> #include <fcntl.h> +#include <sys/param.h> #include <sys/types.h> #include <sys/stat.h> #include <string.h> @@ -558,7 +559,7 @@ _IO_new_file_underflow (fp) /* Special callback replacing the underflow callbacks if we mmap the file. */ -static int +int _IO_file_underflow_mmap (_IO_FILE *fp) { if (fp->_IO_read_end < fp->_IO_buf_end) @@ -576,6 +577,7 @@ _IO_file_underflow_mmap (_IO_FILE *fp) return EOF; } + fp->_offset = fp->_IO_buf_end - fp->_IO_buf_base; fp->_IO_read_end = fp->_IO_buf_end; return *fp->_IO_read_ptr; } @@ -857,6 +859,52 @@ resync: return offset; } +_IO_off64_t +_IO_file_seekoff_mmap (fp, offset, dir, mode) + _IO_FILE *fp; + _IO_off64_t offset; + int dir; + int mode; +{ + _IO_off64_t result; + + if (mode == 0) + dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */ + + switch (dir) + { + case _IO_seek_cur: + /* Adjust for read-ahead (bytes is buffer). */ + offset += fp->_IO_read_ptr - fp->_IO_read_base; + break; + case _IO_seek_set: + break; + case _IO_seek_end: + offset = fp->_IO_read_end - fp->_IO_read_base + offset; + break; + } + /* At this point, dir==_IO_seek_set. */ + + if (offset < 0) + /* No negative offsets are valid. */ + return EOF; + + /* If we are only interested in the current position we've found it now. */ + if (mode == 0) + return offset; + + result = _IO_SYSSEEK (fp, offset, 0); + if (result < 0) + return EOF; + + _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + offset, + fp->_IO_buf_base + offset); + + _IO_mask_flags (fp, 0, _IO_EOF_SEEN); + + return offset; +} + _IO_ssize_t _IO_file_read (fp, buf, size) _IO_FILE *fp; @@ -1122,6 +1170,39 @@ _IO_file_xsgetn (fp, data, n) return n - want; } +static _IO_size_t _IO_file_xsgetn_mmap __P ((_IO_FILE *, void *, _IO_size_t)); +static _IO_size_t +_IO_file_xsgetn_mmap (fp, data, n) + _IO_FILE *fp; + void *data; + _IO_size_t n; +{ + register _IO_size_t have; + char *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; + else + { + have = MIN (have, n); + memcpy (data, read_ptr, have); + fp->_IO_read_ptr = read_ptr + have; + } + + return have; +} + struct _IO_jump_t _IO_file_jumps = { JUMP_INIT_DUMMY, @@ -1155,8 +1236,8 @@ struct _IO_jump_t _IO_file_jumps_mmap = JUMP_INIT(uflow, _IO_default_uflow), JUMP_INIT(pbackfail, _IO_default_pbackfail), JUMP_INIT(xsputn, _IO_new_file_xsputn), - JUMP_INIT(xsgetn, _IO_file_xsgetn), - JUMP_INIT(seekoff, _IO_new_file_seekoff), + JUMP_INIT(xsgetn, _IO_file_xsgetn_mmap), + JUMP_INIT(seekoff, _IO_file_seekoff_mmap), JUMP_INIT(seekpos, _IO_default_seekpos), JUMP_INIT(setbuf, _IO_new_file_setbuf), JUMP_INIT(sync, _IO_new_file_sync), diff --git a/libio/iofopen.c b/libio/iofopen.c index e4821cb..e3b9838 100644 --- a/libio/iofopen.c +++ b/libio/iofopen.c @@ -67,25 +67,12 @@ __fopen_maybe_mmap (fp) # endif if (p != MAP_FAILED) { - if ( -# ifdef _G_LSEEK64 - _G_LSEEK64 (fp->_fileno, st.st_size, SEEK_SET) -# else - __lseek (fp->_fileno, st.st_size, SEEK_SET) -# endif - != st.st_size) - { - /* We cannot search the file. Don't mmap then. */ - __munmap (p, st.st_size); - return fp; - } - /* OK, we managed to map the file. Set the buffer up and use a special jump table with simplified underflow functions which never tries to read anything from the file. */ _IO_setb (fp, p, (char *) p + st.st_size, 0); - _IO_setg (fp, p, p, (char *) p + st.st_size); + _IO_setg (fp, p, p, p); if (fp->_mode <= 0) _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_file_jumps_mmap; @@ -93,7 +80,7 @@ __fopen_maybe_mmap (fp) _IO_JUMPS ((struct _IO_FILE_plus *) fp) = &_IO_wfile_jumps_mmap; fp->_wide_data->_wide_vtable = &_IO_wfile_jumps_mmap; - fp->_offset = st.st_size; + fp->_offset = 0; } } } diff --git a/libio/libioP.h b/libio/libioP.h index f9f44cc..e25a6e7 100644 --- a/libio/libioP.h +++ b/libio/libioP.h @@ -1,4 +1,4 @@ -/* Copyright (C) 1993,1997,1998,1999,2000,2001 Free Software Foundation, Inc. +/* Copyright (C) 1993, 1997-2001, 2002 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 @@ -486,12 +486,15 @@ extern int _IO_old_fsetpos64 __P ((_IO_FILE *, const _IO_fpos64_t *)); extern int _IO_file_doallocate __P ((_IO_FILE *)); extern _IO_FILE* _IO_file_setbuf __P ((_IO_FILE *, char *, _IO_ssize_t)); extern _IO_off64_t _IO_file_seekoff __P ((_IO_FILE *, _IO_off64_t, int, int)); +extern _IO_off64_t _IO_file_seekoff_mmap __P ((_IO_FILE *, _IO_off64_t, int, + int)); extern _IO_size_t _IO_file_xsputn __P ((_IO_FILE *, const void *, _IO_size_t)); extern _IO_size_t _IO_file_xsgetn __P ((_IO_FILE *, void *, _IO_size_t)); extern int _IO_file_stat __P ((_IO_FILE *, void *)); extern int _IO_file_close __P ((_IO_FILE *)); extern int _IO_file_close_mmap __P ((_IO_FILE *)); extern int _IO_file_underflow __P ((_IO_FILE *)); +extern int _IO_file_underflow_mmap __P ((_IO_FILE *)); extern int _IO_file_overflow __P ((_IO_FILE *, int)); #define _IO_file_is_open(__fp) ((__fp)->_fileno != -1) extern void _IO_file_init __P ((struct _IO_FILE_plus *)); diff --git a/libio/tst-widetext.c b/libio/tst-widetext.c index 3842403..7a98f64 100644 --- a/libio/tst-widetext.c +++ b/libio/tst-widetext.c @@ -1,6 +1,6 @@ /* Test program for the wide character stream functions handling larger amounts of text. - Copyright (C) 2000 Free Software Foundation, Inc. + Copyright (C) 2000, 2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Contributed by Ulrich Drepper <drepper@cygnus.com>. @@ -212,7 +212,7 @@ main (void) /* Make sure there is nothing left. */ if (fgetc (fp) != EOF) { - printf ("%Zd: more input avilable", __LINE__); + printf ("%Zd: more input available\n", __LINE__); status = 1; } @@ -347,7 +347,7 @@ main (void) /* Make sure there is nothing left. */ if (fgetc (fp) != EOF) { - printf ("%Zd: more input avilable", __LINE__); + printf ("%Zd: more input available\n", __LINE__); status = 1; } diff --git a/libio/wfileops.c b/libio/wfileops.c index 35d201b..54624f0 100644 --- a/libio/wfileops.c +++ b/libio/wfileops.c @@ -1,4 +1,4 @@ -/* Copyright (C) 1993,95,97,98,99,2000,2001 Free Software Foundation, Inc. +/* Copyright (C) 1993,95,97,98,99,2000,2001,2002 Free Software Foundation, Inc. This file is part of the GNU C Library. Written by Ulrich Drepper <drepper@cygnus.com>. Based on the single byte version by Per Bothner <bothner@cygnus.com>. @@ -313,6 +313,7 @@ _IO_wfile_underflow_mmap (_IO_FILE *fp) { struct _IO_codecvt *cd; enum __codecvt_result status; + const char *read_stop; if (__builtin_expect (fp->_flags & _IO_NO_READS, 0)) { @@ -326,45 +327,48 @@ _IO_wfile_underflow_mmap (_IO_FILE *fp) cd = fp->_codecvt; /* Maybe there is something left in the external buffer. */ - if (fp->_IO_read_ptr < fp->_IO_read_end) + if (fp->_IO_read_ptr >= fp->_IO_read_end + /* No. But maybe the read buffer is not fully set up. */ + && _IO_file_underflow_mmap (fp) == EOF) { - /* There is more in the external. Convert it. */ - const char *read_stop = (const char *) fp->_IO_read_ptr; + /* Nothing available. */ + fp->_flags |= _IO_EOF_SEEN; + return WEOF; + } + + /* There is more in the external. Convert it. */ + read_stop = (const char *) fp->_IO_read_ptr; - if (fp->_wide_data->_IO_buf_base == NULL) + if (fp->_wide_data->_IO_buf_base == NULL) + { + /* Maybe we already have a push back pointer. */ + if (fp->_wide_data->_IO_save_base != NULL) { - /* Maybe we already have a push back pointer. */ - if (fp->_wide_data->_IO_save_base != NULL) - { - free (fp->_wide_data->_IO_save_base); - fp->_flags &= ~_IO_IN_BACKUP; - } - _IO_wdoallocbuf (fp); + free (fp->_wide_data->_IO_save_base); + fp->_flags &= ~_IO_IN_BACKUP; } + _IO_wdoallocbuf (fp); + } - fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; - fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr = - fp->_wide_data->_IO_buf_base; - status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, - fp->_IO_read_ptr, fp->_IO_read_end, - &read_stop, - fp->_wide_data->_IO_read_ptr, - fp->_wide_data->_IO_buf_end, - &fp->_wide_data->_IO_read_end); - - fp->_IO_read_ptr = (char *) read_stop; + fp->_wide_data->_IO_last_state = fp->_wide_data->_IO_state; + fp->_wide_data->_IO_read_base = fp->_wide_data->_IO_read_ptr = + fp->_wide_data->_IO_buf_base; + status = (*cd->__codecvt_do_in) (cd, &fp->_wide_data->_IO_state, + fp->_IO_read_ptr, fp->_IO_read_end, + &read_stop, + fp->_wide_data->_IO_read_ptr, + fp->_wide_data->_IO_buf_end, + &fp->_wide_data->_IO_read_end); - /* If we managed to generate some text return the next character. */ - if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) - return *fp->_wide_data->_IO_read_ptr; + fp->_IO_read_ptr = (char *) read_stop; - /* There is some garbage at the end of the file. */ - __set_errno (EILSEQ); - fp->_flags |= _IO_ERR_SEEN; - return WEOF; - } + /* If we managed to generate some text return the next character. */ + if (fp->_wide_data->_IO_read_ptr < fp->_wide_data->_IO_read_end) + return *fp->_wide_data->_IO_read_ptr; - fp->_flags |= _IO_EOF_SEEN; + /* There is some garbage at the end of the file. */ + __set_errno (EILSEQ); + fp->_flags |= _IO_ERR_SEEN; return WEOF; } diff --git a/stdio-common/tst-rndseek.c b/stdio-common/tst-rndseek.c index 82a4cfd..41d99e4 100644 --- a/stdio-common/tst-rndseek.c +++ b/stdio-common/tst-rndseek.c @@ -15,7 +15,7 @@ static int do_test (void); static int -fp_test (FILE *fp) +fp_test (const char *name, FILE *fp) { int result = 0; int rounds = 10000; @@ -28,7 +28,7 @@ fp_test (FILE *fp) if (fseek (fp, idx, SEEK_SET) != 0) { - printf ("%d: fseek failed: %m\n", rounds); + printf ("%s: %d: fseek failed: %m\n", name, rounds); result = 1; break; } @@ -37,8 +37,8 @@ fp_test (FILE *fp) ch2 = tempdata[idx]; if (ch1 != ch2) { - printf ("%d: character at index %d not what is expected ('%c' vs '%c')\n", - rounds, idx, ch1, ch2); + printf ("%s: %d: character at index %d not what is expected ('%c' vs '%c')\n", + name, rounds, idx, ch1, ch2); result = 1; break; } @@ -47,8 +47,8 @@ fp_test (FILE *fp) ch2 = tempdata[idx + 1]; if (ch1 != ch2) { - printf ("%d: character at index %d not what is expected ('%c' vs '%c')\n", - rounds, idx + 1, ch1, ch2); + printf ("%s: %d: character at index %d not what is expected ('%c' vs '%c')\n", + name, rounds, idx + 1, ch1, ch2); result = 1; break; } @@ -83,7 +83,7 @@ do_test (void) /* First create some temporary data. */ for (i = 0; i < sizeof (tempdata); ++i) - tempdata[i] = (char) random (); + tempdata[i] = 'a' + random () % 26; /* Write this data to a file. */ if (TEMP_FAILURE_RETRY (write (fd, tempdata, sizeof (tempdata))) @@ -121,23 +121,23 @@ do_test (void) } } - result = fp_test (fp); + result = fp_test ("fdopen(\"r\")", fp); fp = fopen (fname, "r"); - result |= fp_test (fp); + result |= fp_test ("fopen(\"r\")", fp); fp = fopen64 (fname, "r"); - result |= fp_test (fp); + result |= fp_test ("fopen64(\"r\")", fp); /* The "rw" mode will prevent the mmap-using code from being used. */ fp = fdopen (fd, "rw"); - result = fp_test (fp); + result = fp_test ("fdopen(\"rw\")", fp); fp = fopen (fname, "rw"); - result |= fp_test (fp); + result |= fp_test ("fopen(\"rw\")", fp); fp = fopen64 (fname, "rw"); - result |= fp_test (fp); + result |= fp_test ("fopen64(\"rw\")", fp); return result; } |