This is the mail archive of the
libstdc++@gcc.gnu.org
mailing list for the libstdc++ project.
[Patch] libstdc++/21286
- From: Paolo Carlini <pcarlini at suse dot de>
- To: libstdc++ <libstdc++ at gcc dot gnu dot org>
- Date: Sat, 30 Apr 2005 01:11:27 +0200
- Subject: [Patch] libstdc++/21286
Hi,
the below is what I have prepared with Nathan: basically, in order to
correctly implement the exact requirements of istream::read also in
presence of short reads (possible with pipes, f.i.) we need to loop
until either zero chars are read or error (-1) is returned. I'm punting
for now on a testcase, since would be very brittle, depending on the
choice of n, the presence of the data in the cache, and so on, but I can
guarantee that the issue is fixed, in the radical way ;)
As you can see, a nice side effect is that we can remove the workaround
for 20806, since that hidden stripping of '\r' that DOS performs is
equivalent to short but unharmful reads.
Tested x86-linux (also the interactive tests, to be safe, but here we
are not involving the sync_filebuf and in any case touching only xsgetn,
*not* underflow)
Paolo.
//////////////////
2005-04-30 Paolo Carlini <pcarlini@suse.de>
Nathan Myers <ncm@cantrip.org>
PR libstdc++/21286
* include/bits/fstream.tcc (basic_filebuf<>::xsgetn):
Loop on short reads; remove the work-around for
libstdc++/20806, not needed anymore.
diff -urN libstdc++-v3-orig/include/bits/fstream.tcc libstdc++-v3/include/bits/fstream.tcc
--- libstdc++-v3-orig/include/bits/fstream.tcc 2005-04-08 19:31:30.000000000 +0200
+++ libstdc++-v3/include/bits/fstream.tcc 2005-04-30 00:19:31.000000000 +0200
@@ -531,15 +531,8 @@
const bool __testin = _M_mode & ios_base::in;
const streamsize __buflen = _M_buf_size > 1 ? _M_buf_size - 1 : 1;
-#if _GLIBCXX_HAVE_DOS_BASED_FILESYSTEM
- // About this workaround, see libstdc++/20806.
- const bool __testbinary = _M_mode & ios_base::binary;
- if (__n > __buflen && __check_facet(_M_codecvt).always_noconv()
- && __testin && __testbinary && !_M_writing)
-#else
if (__n > __buflen && __check_facet(_M_codecvt).always_noconv()
&& __testin && !_M_writing)
-#endif
{
// First, copy the chars already present in the buffer.
const streamsize __avail = this->egptr() - this->gptr();
@@ -555,13 +548,28 @@
__n -= __avail;
}
- const streamsize __len = _M_file.xsgetn(reinterpret_cast<char*>(__s),
- __n);
- if (__len == -1)
- __throw_ios_failure(__N("basic_filebuf::xsgetn "
- "error reading the file"));
- __ret += __len;
- if (__len == __n)
+ // Need to loop in case of short reads (relatively common
+ // with pipes).
+ streamsize __len;
+ for (;;)
+ {
+ __len = _M_file.xsgetn(reinterpret_cast<char*>(__s),
+ __n);
+ if (__len == -1)
+ __throw_ios_failure(__N("basic_filebuf::xsgetn "
+ "error reading the file"));
+ if (__len == 0)
+ break;
+
+ __n -= __len;
+ __ret += __len;
+ if (__n == 0)
+ break;
+
+ __s += __len;
+ }
+
+ if (__n == 0)
{
_M_set_buffer(0);
_M_reading = true;