mirror of git://sourceware.org/git/glibc.git
Fix fsetpos on wide stream.
This commit is contained in:
parent
22bb992d51
commit
5d2e69766a
|
@ -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>
|
||||
|
||||
* sysdeps/x86_64/multiarch/strstr-c.c (__strstr_sse42, __strstr_sse2):
|
||||
|
|
|
@ -58,7 +58,7 @@ tests = tst_swprintf tst_wprintf tst_swscanf tst_wscanf tst_getwc tst_putwc \
|
|||
tst-memstream1 tst-memstream2 \
|
||||
tst-wmemstream1 tst-wmemstream2 \
|
||||
bug-memstream1 bug-wmemstream1 \
|
||||
tst-setvbuf1 tst-popen1 tst-fgetwc
|
||||
tst-setvbuf1 tst-popen1 tst-fgetwc bug-wsetpos
|
||||
test-srcs = test-freopen
|
||||
|
||||
all: # Make this the default target; it will be defined in Rules.
|
||||
|
|
|
@ -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;
|
||||
}
|
|
@ -631,8 +631,12 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
|||
clen = (*cv->__codecvt_do_encoding) (cv);
|
||||
|
||||
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
|
||||
{
|
||||
int nread;
|
||||
|
@ -690,39 +694,11 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
|||
fp->_IO_buf_base + (offset - start_offset),
|
||||
fp->_IO_read_end);
|
||||
_IO_setp (fp, fp->_IO_buf_base, fp->_IO_buf_base);
|
||||
|
||||
/* Now set the pointer for the internal buffer. This
|
||||
might be an iterative process. Though the read
|
||||
pointer is somewhere in the current external buffer
|
||||
this does not mean we can convert this whole buffer
|
||||
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_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);
|
||||
_IO_mask_flags (fp, 0, _IO_EOF_SEEN);
|
||||
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,
|
||||
fp->_IO_buf_base + count);
|
||||
_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;
|
||||
_IO_mask_flags (fp, 0, _IO_EOF_SEEN);
|
||||
return offset;
|
||||
|
|
Loading…
Reference in New Issue