Resolves: #577950
- Backport of upstream BZ #5298. Don't flush buffer for ftell. Compute offsets from write pointers instead. (#577950)
This commit is contained in:
parent
ba20a858e0
commit
1e5f839b46
194
glibc-rh577950.patch
Normal file
194
glibc-rh577950.patch
Normal file
@ -0,0 +1,194 @@
|
||||
diff -Nrup a/libio/fileops.c b/libio/fileops.c
|
||||
--- a/libio/fileops.c 2012-06-30 15:12:34.000000000 -0400
|
||||
+++ b/libio/fileops.c 2012-11-28 12:27:00.297009479 -0500
|
||||
@@ -978,6 +978,9 @@ _IO_new_file_seekoff (fp, offset, dir, m
|
||||
int must_be_exact = (fp->_IO_read_base == fp->_IO_read_end
|
||||
&& 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)
|
||||
dir = _IO_seek_cur, offset = 0; /* Don't move any pointers. */
|
||||
|
||||
@@ -988,10 +991,8 @@ _IO_new_file_seekoff (fp, offset, dir, m
|
||||
which assumes file_ptr() is eGptr. Anyway, since we probably
|
||||
end up flushing when we close(), it doesn't make much difference.)
|
||||
FIXME: simulate mem-papped files. */
|
||||
-
|
||||
- if (fp->_IO_write_ptr > fp->_IO_write_base || _IO_in_put_mode (fp))
|
||||
- if (_IO_switch_to_get_mode (fp))
|
||||
- return EOF;
|
||||
+ else if (was_writing && _IO_switch_to_get_mode (fp))
|
||||
+ return EOF;
|
||||
|
||||
if (fp->_IO_buf_base == NULL)
|
||||
{
|
||||
@@ -1010,7 +1011,17 @@ _IO_new_file_seekoff (fp, offset, dir, m
|
||||
{
|
||||
case _IO_seek_cur:
|
||||
/* 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 (mode != 0)
|
||||
diff -Nrup a/libio/wfileops.c b/libio/wfileops.c
|
||||
--- a/libio/wfileops.c 2012-11-28 10:47:08.906188748 -0500
|
||||
+++ b/libio/wfileops.c 2012-11-28 12:34:06.285439028 -0500
|
||||
@@ -611,6 +611,10 @@ _IO_wfile_seekoff (fp, offset, dir, mode
|
||||
&& (fp->_wide_data->_IO_write_base
|
||||
== 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)
|
||||
{
|
||||
/* XXX For wide stream with backup store it is not very
|
||||
@@ -642,11 +646,8 @@ _IO_wfile_seekoff (fp, offset, dir, mode
|
||||
which assumes file_ptr() is eGptr. Anyway, since we probably
|
||||
end up flushing when we close(), it doesn't make much difference.)
|
||||
FIXME: simulate mem-mapped files. */
|
||||
-
|
||||
- if (fp->_wide_data->_IO_write_ptr > fp->_wide_data->_IO_write_base
|
||||
- || _IO_in_put_mode (fp))
|
||||
- if (_IO_switch_to_wget_mode (fp))
|
||||
- return WEOF;
|
||||
+ else if (was_writing && _IO_switch_to_wget_mode (fp))
|
||||
+ return WEOF;
|
||||
|
||||
if (fp->_wide_data->_IO_buf_base == NULL)
|
||||
{
|
||||
@@ -677,29 +678,104 @@ _IO_wfile_seekoff (fp, offset, dir, mode
|
||||
cv = fp->_codecvt;
|
||||
clen = (*cv->__codecvt_do_encoding) (cv);
|
||||
|
||||
- if (clen > 0)
|
||||
+ if (mode != 0 || !was_writing)
|
||||
{
|
||||
- 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;
|
||||
+ if (clen > 0)
|
||||
+ {
|
||||
+ 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;
|
||||
+
|
||||
+ 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
|
||||
{
|
||||
- int nread;
|
||||
+ char *new_write_ptr = fp->_IO_write_ptr;
|
||||
|
||||
- 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;
|
||||
+ if (clen > 0)
|
||||
+ offset += (fp->_wide_data->_IO_write_ptr
|
||||
+ - fp->_wide_data->_IO_write_base) / clen;
|
||||
+ else
|
||||
+ {
|
||||
+ enum __codecvt_result status;
|
||||
+ delta = (fp->_wide_data->_IO_write_ptr
|
||||
+ - 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)
|
||||
- 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(). */
|
||||
offset += fp->_offset;
|
||||
|
||||
Binary files a/libio/.wfileops.c.swp and b/libio/.wfileops.c.swp differ
|
10
glibc.spec
10
glibc.spec
@ -28,7 +28,7 @@
|
||||
Summary: The GNU libc libraries
|
||||
Name: glibc
|
||||
Version: %{glibcversion}
|
||||
Release: 24%{?dist}
|
||||
Release: 25%{?dist}
|
||||
# GPLv2+ is used in a bunch of programs, LGPLv2+ is used for libraries.
|
||||
# Things that are linked directly into dynamically linked programs
|
||||
# and shared libraries (e.g. crt files, lib*_nonshared.a) have an additional
|
||||
@ -188,6 +188,9 @@ Patch2039: %{name}-rh854337.patch
|
||||
# Upstream BZ 14583
|
||||
Patch2040: %{name}-rh857236.patch
|
||||
|
||||
# Upstream BZ 5298
|
||||
Patch2041: %{name}-rh577950.patch
|
||||
|
||||
Patch2042: %{name}-rh864820.patch
|
||||
|
||||
Buildroot: %{_tmppath}/%{name}-%{version}-%{release}-root-%(%{__id_u} -n)
|
||||
@ -454,6 +457,7 @@ rm -rf %{glibcportsdir}
|
||||
%patch1038 -p1
|
||||
%patch2039 -p1
|
||||
%patch2040 -p1
|
||||
%patch2041 -p1
|
||||
%patch1041 -p1
|
||||
%patch2042 -p1
|
||||
%patch1042 -p1
|
||||
@ -1269,6 +1273,10 @@ rm -f *.filelist*
|
||||
%endif
|
||||
|
||||
%changelog
|
||||
* Wed Nov 28 2012 Patsy Franklin <pfrankli@redhat.com> - 2.16-25
|
||||
- Backport of upstream BZ #5298. Don't flush buffer for ftell.
|
||||
Compute offsets from write pointers instead. (#577950)
|
||||
|
||||
* Thu Nov 8 2012 Jeff Law <law@redhat.com> - 2.16-24
|
||||
- Add hwcaps for transactional execution on s390[x] (#804768)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user