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)) {