Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Fix fsetpos on wide stream.
  • Loading branch information
Andreas Schwab authored and Ulrich Drepper committed Sep 3, 2009
1 parent 22bb992 commit 5d2e697
Show file tree
Hide file tree
Showing 4 changed files with 97 additions and 36 deletions.
7 changes: 7 additions & 0 deletions ChangeLog
@@ -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):
Expand Down
2 changes: 1 addition & 1 deletion libio/Makefile
Expand Up @@ -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.
Expand Down
75 changes: 75 additions & 0 deletions libio/bug-wsetpos.c
@@ -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;
}
49 changes: 14 additions & 35 deletions libio/wfileops.c
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
Expand Down Expand Up @@ -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;
Expand Down

0 comments on commit 5d2e697

Please sign in to comment.