Fix fsetpos on wide stream.

This commit is contained in:
Andreas Schwab 2009-09-02 19:45:33 -07:00 committed by Ulrich Drepper
parent 22bb992d51
commit 5d2e69766a
4 changed files with 97 additions and 36 deletions

View File

@ -1,3 +1,10 @@
2009-09-02 Andreas Schwab <schwab@redhat.com>
* libio/wfileops.c (_IO_wfile_seekoff): Account for readahead in
external buffer. Always discard readahead in internal buffer.
* libio/Makefile (tests): Add bug-wsetpos.
* libio/bug-wsetpos.c: New file.
2009-09-02 Jakub Jelinek <jakub@redhat.com> 2009-09-02 Jakub Jelinek <jakub@redhat.com>
* sysdeps/x86_64/multiarch/strstr-c.c (__strstr_sse42, __strstr_sse2): * sysdeps/x86_64/multiarch/strstr-c.c (__strstr_sse42, __strstr_sse2):

View File

@ -58,7 +58,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
tst-memstream1 tst-memstream2 \ tst-memstream1 tst-memstream2 \
tst-wmemstream1 tst-wmemstream2 \ tst-wmemstream1 tst-wmemstream2 \
bug-memstream1 bug-wmemstream1 \ bug-memstream1 bug-wmemstream1 \
tst-setvbuf1 tst-popen1 tst-fgetwc tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos
test-srcs = test-freopen test-srcs = test-freopen
all: # Make this the default target; it will be defined in Rules. all: # Make this the default target; it will be defined in Rules.

75
libio/bug-wsetpos.c Normal file
View File

@ -0,0 +1,75 @@
/* Test program for fsetpos on a wide character stream. */
#include <assert.h>
#include <stdio.h>
#include <wchar.h>
static void do_prepare (void);
#define PREPARE(argc, argv) do_prepare ()
static int do_test (void);
#define TEST_FUNCTION do_test ()
#include <test-skeleton.c>
static const char pattern[] = "12345";
static char *temp_file;
static void
do_prepare (void)
{
int fd = create_temp_file ("bug-wsetpos.", &temp_file);
if (fd == -1)
{
printf ("cannot create temporary file: %m\n");
exit (1);
}
write (fd, pattern, sizeof (pattern));
close (fd);
}
static int
do_test (void)
{
FILE *fp = fopen (temp_file, "r");
fpos_t pos;
wchar_t c;
if (fp == NULL)
{
printf ("fdopen: %m\n");
return 1;
}
c = fgetwc (fp); assert (c == L'1');
c = fgetwc (fp); assert (c == L'2');
if (fgetpos (fp, &pos) == EOF)
{
printf ("fgetpos: %m\n");
return 1;
}
rewind (fp);
if (ferror (fp))
{
printf ("rewind: %m\n");
return 1;
}
c = fgetwc (fp); assert (c == L'1');
if (fsetpos (fp, &pos) == EOF)
{
printf ("fsetpos: %m\n");
return 1;
}
c = fgetwc (fp);
if (c != L'3')
{
puts ("fsetpos failed");
return 1;
}
puts ("Test succeeded.");
return 0;
}

View File

@ -631,8 +631,12 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
clen = (*cv->__codecvt_do_encoding) (cv); clen = (*cv->__codecvt_do_encoding) (cv);
if (clen > 0) if (clen > 0)
offset -= (fp->_wide_data->_IO_read_end {
- fp->_wide_data->_IO_read_ptr) * clen; offset -= (fp->_wide_data->_IO_read_end
- fp->_wide_data->_IO_read_ptr) * clen;
/* Adjust by readahead in external buffer. */
offset -= fp->_IO_read_end - fp->_IO_read_ptr;
}
else else
{ {
int nread; int nread;
@ -690,39 +694,11 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
fp->_IO_buf_base + (offset - start_offset), fp->_IO_buf_base + (offset - start_offset),
fp->_IO_read_end); fp->_IO_read_end);
_IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base); _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
_IO_wsetg (fp, fp->_wide_data->_IO_buf_base,
/* Now set the pointer for the internal buffer. This fp->_wide_data->_IO_buf_base,
might be an iterative process. Though the read fp->_wide_data->_IO_buf_base);
pointer is somewhere in the current external buffer _IO_wsetp (fp, fp->_wide_data->_IO_buf_base,
this does not mean we can convert this whole buffer fp->_wide_data->_IO_buf_base);
at once fitting in the internal buffer. */
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
read_ptr_copy = fp->_IO_read_base;
fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_base;
do
{
wchar_t buffer[1024];
wchar_t *ignore;
status = (*cd->__codecvt_do_in) (cd,
&fp->_wide_data->_IO_state,
read_ptr_copy,
fp->_IO_read_ptr,
&read_ptr_copy,
buffer,
buffer
+ (sizeof (buffer)
/ sizeof (buffer[0])),
&ignore);
if (status != __codecvt_ok && status != __codecvt_partial)
{
fp->_flags |= _IO_ERR_SEEN;
goto dumb;
}
}
while (read_ptr_copy != fp->_IO_read_ptr);
fp->_wide_data->_IO_read_ptr = fp->_wide_data->_IO_read_base;
_IO_mask_flags (fp, 0, _IO_EOF_SEEN); _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
goto resync; goto resync;
} }
@ -760,6 +736,9 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
_IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta, _IO_setg (fp, fp->_IO_buf_base, fp->_IO_buf_base + delta,
fp->_IO_buf_base + count); fp->_IO_buf_base + count);
_IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base); _IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
_IO_wsetg (fp, fp->_wide_data->_IO_buf_base,
fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base);
_IO_wsetp (fp, fp->_wide_data->_IO_buf_base, fp->_wide_data->_IO_buf_base);
fp->_offset = result + count; fp->_offset = result + count;
_IO_mask_flags (fp, 0, _IO_EOF_SEEN); _IO_mask_flags (fp, 0, _IO_EOF_SEEN);
return offset; return offset;