diff options
author | Siddhesh Poyarekar <siddhesh@redhat.com> | 2014-12-04 08:08:37 +0530 |
---|---|---|
committer | Siddhesh Poyarekar <siddhesh@redhat.com> | 2014-12-04 08:08:37 +0530 |
commit | be349d7042de84c3c5157a5c1fbcad580aed33e1 (patch) | |
tree | e49154ef02c2b02573693a3af1a773d5ea3f2470 /libio/fileops.c | |
parent | e3d6dba5dfe2e125b15ea1dd36c8dfa373bb4956 (diff) | |
download | glibc-be349d7042de84c3c5157a5c1fbcad580aed33e1.tar glibc-be349d7042de84c3c5157a5c1fbcad580aed33e1.tar.gz glibc-be349d7042de84c3c5157a5c1fbcad580aed33e1.tar.bz2 glibc-be349d7042de84c3c5157a5c1fbcad580aed33e1.zip |
ftell: seek to end only when there are unflushed bytes (BZ #17647)
Currently we seek to end of file if there are unflushed writes or the
stream is in write mode, to get the current offset for writing in
append mode, which is the end of file. The latter case (i.e. stream
is in write mode, but no unflushed writes) is unnecessary since it
will only happen when the stream has just been flushed, in which case
the recorded offset ought to be reliable.
Removing that case lets ftell give the correct offset when it follows
an ftruncate. The latter truncates the file, but does not change the
file position, due to which it is permissible to call ftell without an
intervening fseek call.
Tested on x86_64 to verify that the added test case fails without the
patch and succeeds with it, and that there are no additional
regressions due to it.
[BZ #17647]
* libio/fileops.c (do_ftell): Seek only when there are
unflushed writes.
* libio/wfileops.c (do_ftell_wide): Likewise.
* libio/tst-ftell-active-handler.c (do_ftruncate_test): New
test case.
(do_one_test): Call it.
Diffstat (limited to 'libio/fileops.c')
-rw-r--r-- | libio/fileops.c | 7 |
1 files changed, 3 insertions, 4 deletions
diff --git a/libio/fileops.c b/libio/fileops.c index e0d7b76eda..dca359179f 100644 --- a/libio/fileops.c +++ b/libio/fileops.c @@ -943,15 +943,14 @@ do_ftell (_IO_FILE *fp) yet. */ if (fp->_IO_buf_base != NULL) { - bool was_writing = (fp->_IO_write_ptr > fp->_IO_write_base - || _IO_in_put_mode (fp)); + bool unflushed_writes = fp->_IO_write_ptr > fp->_IO_write_base; bool append_mode = (fp->_flags & _IO_IS_APPENDING) == _IO_IS_APPENDING; /* When we have unflushed writes in append mode, seek to the end of the file and record that offset. This is the only time we change the file stream state and it is safe since the file handle is active. */ - if (was_writing && append_mode) + if (unflushed_writes && append_mode) { result = _IO_SYSSEEK (fp, 0, _IO_seek_end); if (result == _IO_pos_BAD) @@ -961,7 +960,7 @@ do_ftell (_IO_FILE *fp) } /* Adjust for unflushed data. */ - if (!was_writing) + if (!unflushed_writes) offset -= fp->_IO_read_end - fp->_IO_read_ptr; /* We don't trust _IO_read_end to represent the current file offset when writing in append mode because the value would have to be shifted to |