mirror of
https://sourceware.org/git/glibc.git
synced 2025-07-29 11:41:21 +03:00
Don't flush write buffer for ftell
[BZ #5298] Use write pointer state along with the file offset and/or the read pointers to get the current file position.
This commit is contained in:
@ -1,3 +1,10 @@
|
|||||||
|
2012-09-28 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||||
|
|
||||||
|
[BZ #5298]
|
||||||
|
* libio/fileops.c (_IO_new_file_seekoff): Don't flush buffer
|
||||||
|
for ftell. Compute offsets from write pointers instead.
|
||||||
|
* libio/wfileops.c (_IO_wfile_seekoff): Likewise.
|
||||||
|
|
||||||
2012-09-28 Siddhesh Poyarekar <siddhesh@redhat.com>
|
2012-09-28 Siddhesh Poyarekar <siddhesh@redhat.com>
|
||||||
|
|
||||||
[BZ #14543]
|
[BZ #14543]
|
||||||
|
13
NEWS
13
NEWS
@ -9,12 +9,13 @@ Version 2.17
|
|||||||
|
|
||||||
* The following bugs are resolved with this release:
|
* The following bugs are resolved with this release:
|
||||||
|
|
||||||
1349, 3479, 5044, 5400, 6778, 6808, 9685, 9914, 10014, 10038, 11607,
|
1349, 3479, 5044, 5298, 5400, 6778, 6808, 9685, 9914, 10014, 10038,
|
||||||
13412, 13542, 13629, 13679, 13696, 13717, 13741, 13939, 13966, 14042,
|
11607, 13412, 13542, 13629, 13679, 13696, 13717, 13741, 13939, 13966,
|
||||||
14090, 14150, 14151, 14154, 14157, 14166, 14173, 14195, 14237, 14252,
|
14042, 14090, 14150, 14151, 14154, 14157, 14166, 14173, 14195, 14237,
|
||||||
14283, 14298, 14303, 14307, 14328, 14331, 14336, 14337, 14347, 14349,
|
14252, 14283, 14298, 14303, 14307, 14328, 14331, 14336, 14337, 14347,
|
||||||
14376, 14459, 14476, 14505, 14510, 14516, 14518, 14519, 14530, 14532,
|
14349, 14376, 14459, 14476, 14505, 14510, 14516, 14518, 14519, 14530,
|
||||||
14538, 14543, 14544, 14545, 14562, 14576, 14579, 14583, 14587, 14621.
|
14532, 14538, 14543, 14544, 14545, 14562, 14576, 14579, 14583, 14587,
|
||||||
|
14621.
|
||||||
|
|
||||||
* Support for STT_GNU_IFUNC symbols added for s390 and s390x.
|
* Support for STT_GNU_IFUNC symbols added for s390 and s390x.
|
||||||
Optimized versions of memcpy, memset, and memcmp added for System z10 and
|
Optimized versions of memcpy, memset, and memcmp added for System z10 and
|
||||||
|
@ -978,6 +978,9 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
|
|||||||
int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
|
int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
|
||||||
&& fp->_IO_write_base == fp->_IO_write_ptr);
|
&& fp->_IO_write_base == fp->_IO_write_ptr);
|
||||||
|
|
||||||
|
bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base
|
||||||
|
|| _IO_in_put_mode (fp));
|
||||||
|
|
||||||
if (mode == 0)
|
if (mode == 0)
|
||||||
dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
|
dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
|
||||||
|
|
||||||
@ -988,10 +991,8 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
|
|||||||
which assumes file_ptr() is eGptr. Anyway, since we probably
|
which assumes file_ptr() is eGptr. Anyway, since we probably
|
||||||
end up flushing when we close(), it doesn't make much difference.)
|
end up flushing when we close(), it doesn't make much difference.)
|
||||||
FIXME: simulate mem-mapped files. */
|
FIXME: simulate mem-mapped files. */
|
||||||
|
else if (was_writing && _IO_switch_to_get_mode (fp))
|
||||||
if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
|
return EOF;
|
||||||
if (_IO_switch_to_get_mode (fp))
|
|
||||||
return EOF;
|
|
||||||
|
|
||||||
if (fp->_IO_buf_base == NULL)
|
if (fp->_IO_buf_base == NULL)
|
||||||
{
|
{
|
||||||
@ -1010,7 +1011,17 @@ _IO_new_file_seekoff (fp, offset, dir, mode)
|
|||||||
{
|
{
|
||||||
case _IO_seek_cur:
|
case _IO_seek_cur:
|
||||||
/* Adjust for read-ahead (bytes is buffer). */
|
/* Adjust for read-ahead (bytes is buffer). */
|
||||||
offset -= fp->_IO_read_end - fp->_IO_read_ptr;
|
if (mode != 0 || !was_writing)
|
||||||
|
offset -= fp->_IO_read_end - fp->_IO_read_ptr;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
/* _IO_read_end coincides with fp._offset, so the actual file position
|
||||||
|
is fp._offset - (_IO_read_end - new_write_ptr). This is fine
|
||||||
|
even if fp._offset is not set, since fp->_IO_read_end is then at
|
||||||
|
_IO_buf_base and this adjustment is for unbuffered output. */
|
||||||
|
offset -= fp->_IO_read_end - fp->_IO_write_ptr;
|
||||||
|
}
|
||||||
|
|
||||||
if (fp->_offset == _IO_pos_BAD)
|
if (fp->_offset == _IO_pos_BAD)
|
||||||
{
|
{
|
||||||
if (mode != 0)
|
if (mode != 0)
|
||||||
|
116
libio/wfileops.c
116
libio/wfileops.c
@ -613,6 +613,10 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
|||||||
&& (fp->_wide_data->_IO_write_base
|
&& (fp->_wide_data->_IO_write_base
|
||||||
== fp->_wide_data->_IO_write_ptr));
|
== fp->_wide_data->_IO_write_ptr));
|
||||||
|
|
||||||
|
bool was_writing = ((fp->_wide_data->_IO_write_ptr
|
||||||
|
> fp->_wide_data->_IO_write_base)
|
||||||
|
|| _IO_in_put_mode (fp));
|
||||||
|
|
||||||
if (mode == 0)
|
if (mode == 0)
|
||||||
{
|
{
|
||||||
/* XXX For wide stream with backup store it is not very
|
/* XXX For wide stream with backup store it is not very
|
||||||
@ -644,11 +648,8 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
|||||||
which assumes file_ptr() is eGptr. Anyway, since we probably
|
which assumes file_ptr() is eGptr. Anyway, since we probably
|
||||||
end up flushing when we close(), it doesn't make much difference.)
|
end up flushing when we close(), it doesn't make much difference.)
|
||||||
FIXME: simulate mem-mapped files. */
|
FIXME: simulate mem-mapped files. */
|
||||||
|
else if (was_writing && _IO_switch_to_wget_mode (fp))
|
||||||
if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base
|
return WEOF;
|
||||||
|| _IO_in_put_mode (fp))
|
|
||||||
if (_IO_switch_to_wget_mode (fp))
|
|
||||||
return WEOF;
|
|
||||||
|
|
||||||
if (fp->_wide_data->_IO_buf_base == NULL)
|
if (fp->_wide_data->_IO_buf_base == NULL)
|
||||||
{
|
{
|
||||||
@ -679,29 +680,104 @@ _IO_wfile_seekoff (fp, offset, dir, mode)
|
|||||||
cv = fp->_codecvt;
|
cv = fp->_codecvt;
|
||||||
clen = (*cv->__codecvt_do_encoding) (cv);
|
clen = (*cv->__codecvt_do_encoding) (cv);
|
||||||
|
|
||||||
if (clen > 0)
|
if (mode != 0 || !was_writing)
|
||||||
{
|
{
|
||||||
offset -= (fp->_wide_data->_IO_read_end
|
if (clen > 0)
|
||||||
- fp->_wide_data->_IO_read_ptr) * clen;
|
{
|
||||||
/* Adjust by readahead in external buffer. */
|
offset -= (fp->_wide_data->_IO_read_end
|
||||||
offset -= fp->_IO_read_end - fp->_IO_read_ptr;
|
- 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;
|
||||||
|
|
||||||
|
flushed:
|
||||||
|
delta = (fp->_wide_data->_IO_read_ptr
|
||||||
|
- fp->_wide_data->_IO_read_base);
|
||||||
|
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
|
||||||
|
nread = (*cv->__codecvt_do_length) (cv,
|
||||||
|
&fp->_wide_data->_IO_state,
|
||||||
|
fp->_IO_read_base,
|
||||||
|
fp->_IO_read_end, delta);
|
||||||
|
fp->_IO_read_ptr = fp->_IO_read_base + nread;
|
||||||
|
fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_read_ptr;
|
||||||
|
offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
int nread;
|
char *new_write_ptr = fp->_IO_write_ptr;
|
||||||
|
|
||||||
delta = fp->_wide_data->_IO_read_ptr - fp->_wide_data->_IO_read_base;
|
if (clen > 0)
|
||||||
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
|
offset += (fp->_wide_data->_IO_write_ptr
|
||||||
nread = (*cv->__codecvt_do_length) (cv, &fp->_wide_data->_IO_state,
|
- fp->_wide_data->_IO_write_base) / clen;
|
||||||
fp->_IO_read_base,
|
else
|
||||||
fp->_IO_read_end, delta);
|
{
|
||||||
fp->_IO_read_ptr = fp->_IO_read_base + nread;
|
enum __codecvt_result status;
|
||||||
fp->_wide_data->_IO_read_end = fp->_wide_data->_IO_read_ptr;
|
delta = (fp->_wide_data->_IO_write_ptr
|
||||||
offset -= fp->_IO_read_end - fp->_IO_read_base - nread;
|
- fp->_wide_data->_IO_write_base);
|
||||||
|
const wchar_t *write_base = fp->_wide_data->_IO_write_base;
|
||||||
|
|
||||||
|
/* FIXME: This actually ends up in two iterations of conversion,
|
||||||
|
one here and the next when the buffer actually gets flushed.
|
||||||
|
It may be possible to optimize this in future so that
|
||||||
|
wdo_write identifies already converted content and does not
|
||||||
|
redo it. In any case, this is much better than having to
|
||||||
|
flush buffers for every ftell. */
|
||||||
|
do
|
||||||
|
{
|
||||||
|
/* Ugh, no point trying to avoid the flush. Just do it
|
||||||
|
and go back to how it was with the read mode. */
|
||||||
|
if (delta > 0 && new_write_ptr == fp->_IO_buf_end)
|
||||||
|
{
|
||||||
|
if (_IO_switch_to_wget_mode (fp))
|
||||||
|
return WEOF;
|
||||||
|
goto flushed;
|
||||||
|
}
|
||||||
|
|
||||||
|
const wchar_t *new_wbase = fp->_wide_data->_IO_write_base;
|
||||||
|
fp->_wide_data->_IO_state = fp->_wide_data->_IO_last_state;
|
||||||
|
status = (*cv->__codecvt_do_out) (cv,
|
||||||
|
&fp->_wide_data->_IO_state,
|
||||||
|
write_base,
|
||||||
|
write_base + delta,
|
||||||
|
&new_wbase,
|
||||||
|
new_write_ptr,
|
||||||
|
fp->_IO_buf_end,
|
||||||
|
&new_write_ptr);
|
||||||
|
|
||||||
|
delta -= new_wbase - write_base;
|
||||||
|
|
||||||
|
/* If there was an error, then return WEOF.
|
||||||
|
TODO: set buffer state. */
|
||||||
|
if (__builtin_expect (status == __codecvt_error, 0))
|
||||||
|
return WEOF;
|
||||||
|
}
|
||||||
|
while (delta > 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* _IO_read_end coincides with fp._offset, so the actual file position
|
||||||
|
is fp._offset - (_IO_read_end - new_write_ptr). This is fine
|
||||||
|
even if fp._offset is not set, since fp->_IO_read_end is then at
|
||||||
|
_IO_buf_base and this adjustment is for unbuffered output. */
|
||||||
|
offset -= fp->_IO_read_end - new_write_ptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (fp->_offset == _IO_pos_BAD)
|
if (fp->_offset == _IO_pos_BAD)
|
||||||
goto dumb;
|
{
|
||||||
|
if (mode != 0)
|
||||||
|
goto dumb;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
result = _IO_SYSSEEK (fp, 0, dir);
|
||||||
|
if (result == EOF)
|
||||||
|
return result;
|
||||||
|
fp->_offset = result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/* Make offset absolute, assuming current pointer is file_ptr(). */
|
/* Make offset absolute, assuming current pointer is file_ptr(). */
|
||||||
offset += fp->_offset;
|
offset += fp->_offset;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user