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.
This commit is contained in:
Ulrich Drepper 2002-01-19 17:51:34 +00:00
parent 53e9699b6d
commit 284749da8b
7 changed files with 162 additions and 72 deletions

View File

@ -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

View File

@ -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),

View File

@ -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;
}
}
}

View File

@ -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 *));

View File

@ -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;
}

View File

@ -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;
if (fp->_wide_data->_IO_buf_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);
}
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;
/* 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;
/* There is some garbage at the end of the file. */
__set_errno (EILSEQ);
fp->_flags |= _IO_ERR_SEEN;
/* Nothing available. */
fp->_flags |= _IO_EOF_SEEN;
return WEOF;
}
fp->_flags |= _IO_EOF_SEEN;
/* There is more in the external. Convert it. */
read_stop = (const char *) fp->_IO_read_ptr;
if (fp->_wide_data->_IO_buf_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);
}
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;
/* 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;
/* There is some garbage at the end of the file. */
__set_errno (EILSEQ);
fp->_flags |= _IO_ERR_SEEN;
return WEOF;
}

View File

@ -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;
}