+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
-/* 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>.
#include "libioP.h"
#include <assert.h>
#include <fcntl.h>
+#include <sys/param.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <string.h>
/* 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)
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;
}
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;
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,
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),
# 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;
_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;
}
}
}
-/* 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
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 *));
/* 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>.
/* 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;
}
/* 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;
}
-/* 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>.
{
struct _IO_codecvt *cd;
enum __codecvt_result status;
+ const char *read_stop;
if (__builtin_expect (fp->_flags & _IO_NO_READS, 0))
{
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;
}
static int
-fp_test (FILE *fp)
+fp_test (const char *name, FILE *fp)
{
int result = 0;
int rounds = 10000;
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;
}
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;
}
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;
}
/* 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)))
}
}
- 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;
}