Here's a diff that fakes up a FILE like we do in other parts of
stdio for unbuffered I/O.  This lets us call __srefill() normally.
If __srefill() returns an error, copy the flags back to the real
FILE *.

 - todd

Index: lib/libc/stdio/fread.c
===================================================================
RCS file: /cvs/src/lib/libc/stdio/fread.c,v
retrieving revision 1.15
diff -u -p -u -r1.15 fread.c
--- lib/libc/stdio/fread.c      21 Sep 2016 04:38:56 -0000      1.15
+++ lib/libc/stdio/fread.c      13 Dec 2018 17:24:34 -0000
@@ -69,18 +69,39 @@ fread(void *buf, size_t size, size_t cou
        total = resid;
        p = buf;
 
+       /*
+        * If we're unbuffered we know that the buffer in fp is empty so
+        * we can read directly into buf.  This is much faster than a
+        * series of one byte reads into fp->_nbuf.
+        */
        if ((fp->_flags & __SNBF) != 0) {
-               /*
-                * We know if we're unbuffered that our buffer is empty, so
-                * we can just read directly. This is much faster than the
-                * loop below which will perform a series of one byte reads.
-                */
-               while (resid > 0 && (r = (*fp->_read)(fp->_cookie, p, resid)) > 
0) {
-                       p += r;
-                       resid -= r;
+               FILE fake;
+               struct __sfileext fakeext;
+
+               _FILEEXT_SETUP(&fake, &fakeext);
+               /* copy the important variables */
+               fake._flags = fp->_flags;
+               fake._file = fp->_file;
+               fake._cookie = fp->_cookie;
+               fake._read = fp->_read;
+
+               /* set up the buffer */
+               fake._bf._base = buf;
+               fake._bf._size = total;
+               fake._lbfsize = 0;      /* not line buffered */
+
+               while (resid > 0) {
+                       if (__srefill(&fake)) {
+                               /* no more input: return partial result */
+                               count = (total - resid) / size;
+                               fp->_flags |= (fake._flags & (__SERR|__SEOF));
+                               break;
+                       }
+                       fake._p += fake._r;
+                       resid -= fake._r;
                }
                FUNLOCKFILE(fp);
-               return ((total - resid) / size);
+               return (count);
        }
 
        while (resid > (r = fp->_r)) {

Reply via email to