Switch to upstream OpenBSD fread/fvwrite.

Change-Id: I3dc11083693bc8d99edc0cbcc6f70dc9e5dc6565
diff --git a/libc/Android.mk b/libc/Android.mk
index 605aee5..869bdd1 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -75,8 +75,6 @@
     bionic/time64.c \
     bionic/unlockpt.c \
     stdio/findfp.c \
-    stdio/fread.c \
-    stdio/fvwrite.c \
     stdio/snprintf.c\
     stdio/sprintf.c \
     stdlib/atexit.c \
@@ -363,12 +361,14 @@
     upstream-openbsd/lib/libc/stdio/fpurge.c \
     upstream-openbsd/lib/libc/stdio/fputc.c \
     upstream-openbsd/lib/libc/stdio/fputs.c \
+    upstream-openbsd/lib/libc/stdio/fread.c \
     upstream-openbsd/lib/libc/stdio/freopen.c \
     upstream-openbsd/lib/libc/stdio/fscanf.c \
     upstream-openbsd/lib/libc/stdio/fseek.c \
     upstream-openbsd/lib/libc/stdio/fsetpos.c \
     upstream-openbsd/lib/libc/stdio/ftell.c \
     upstream-openbsd/lib/libc/stdio/funopen.c \
+    upstream-openbsd/lib/libc/stdio/fvwrite.c \
     upstream-openbsd/lib/libc/stdio/fwalk.c \
     upstream-openbsd/lib/libc/stdio/getc.c \
     upstream-openbsd/lib/libc/stdio/getchar.c \
diff --git a/libc/stdio/fread.c b/libc/stdio/fread.c
deleted file mode 100644
index 649db17..0000000
--- a/libc/stdio/fread.c
+++ /dev/null
@@ -1,175 +0,0 @@
-/*	$OpenBSD: fread.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
-/*-
- * Copyright (c) 1990, 1993
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- *    may be used to endorse or promote products derived from this software
- *    without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdio.h>
-#include <string.h>
-#include <errno.h>
-#include "local.h"
-
-static int
-lflush(FILE *fp)
-{
-    if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
-        return (__sflush_locked(fp));
-    return (0);
-}
-
-size_t
-fread(void *buf, size_t size, size_t count, FILE *fp)
-{
-    size_t resid;
-    char *p;
-    int r;
-    size_t total;
-
-    /*
-     * The ANSI standard requires a return value of 0 for a count
-     * or a size of 0.  Peculiarily, it imposes no such requirements
-     * on fwrite; it only requires fread to be broken.
-     */
-    if ((resid = count * size) == 0)
-        return (0);
-    FLOCKFILE(fp);
-    if (fp->_r < 0)
-        fp->_r = 0;
-    total = resid;
-    p = buf;
-
-#if 1  /* BIONIC: optimize unbuffered reads */
-    if (fp->_flags & __SNBF && fp->_ur == 0)
-    {
-        /* the following comes mainly from __srefill(), with slight
-         * modifications
-         */
-
-        /* make sure stdio is set up */
-        if (!__sdidinit)
-            __sinit();
-
-        fp->_r = 0;     /* largely a convenience for callers */
-
-        /* SysV does not make this test; take it out for compatibility */
-        if (fp->_flags & __SEOF) {
-            FUNLOCKFILE(fp);
-            return (EOF);
-        }
-
-        /* if not already reading, have to be reading and writing */
-        if ((fp->_flags & __SRD) == 0) {
-            if ((fp->_flags & __SRW) == 0) {
-                fp->_flags |= __SERR;
-                FUNLOCKFILE(fp);
-                errno = EBADF;
-                return (EOF);
-            }
-            /* switch to reading */
-            if (fp->_flags & __SWR) {
-                if (__sflush(fp)) {
-                    FUNLOCKFILE(fp);
-                    return (EOF);
-                }
-                fp->_flags &= ~__SWR;
-                fp->_w = 0;
-                fp->_lbfsize = 0;
-            }
-            fp->_flags |= __SRD;
-        } else {
-            /*
-             * We were reading.  If there is an ungetc buffer,
-             * we must have been reading from that.  Drop it,
-             * restoring the previous buffer (if any).  If there
-             * is anything in that buffer, return.
-             */
-            if (HASUB(fp)) {
-                FREEUB(fp);
-            }
-        }
-
-        /*
-         * Before reading from a line buffered or unbuffered file,
-         * flush all line buffered output files, per the ANSI C
-         * standard.
-         */
-
-        if (fp->_flags & (__SLBF|__SNBF)) {
-            /* Ignore this file in _fwalk to deadlock. */
-            fp->_flags |= __SIGN;
-            (void) _fwalk(lflush);
-            fp->_flags &= ~__SIGN;
-
-            /* Now flush this file without locking it. */
-            if ((fp->_flags & (__SLBF|__SWR)) == (__SLBF|__SWR))
-                __sflush(fp);
-        }
-
-        while (resid > 0) {
-            int   len = (*fp->_read)(fp->_cookie, p, resid );
-            fp->_flags &= ~__SMOD;
-            if (len <= 0) {
-                if (len == 0)
-                    fp->_flags |= __SEOF;
-                else {
-                    fp->_flags |= __SERR;
-                }
-                FUNLOCKFILE(fp);
-                return ((total - resid) / size);
-            }
-            p     += len;
-            resid -= len;
-        }
-        FUNLOCKFILE(fp);
-        return (count);
-    }
-    else
-#endif
-    {
-        while (resid > (size_t)(r = fp->_r)) {
-            (void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
-            fp->_p += r;
-            /* fp->_r = 0 ... done in __srefill */
-            p += r;
-            resid -= r;
-            if (__srefill(fp)) {
-                /* no more input: return partial result */
-                FUNLOCKFILE(fp);
-                return ((total - resid) / size);
-            }
-        }
-    }
-
-    (void)memcpy((void *)p, (void *)fp->_p, resid);
-    fp->_r -= resid;
-    fp->_p += resid;
-    FUNLOCKFILE(fp);
-    return (count);
-}
diff --git a/libc/upstream-openbsd/lib/libc/stdio/fread.c b/libc/upstream-openbsd/lib/libc/stdio/fread.c
new file mode 100644
index 0000000..430865d
--- /dev/null
+++ b/libc/upstream-openbsd/lib/libc/stdio/fread.c
@@ -0,0 +1,74 @@
+/*	$OpenBSD: fread.c,v 1.11 2009/11/21 09:53:44 guenther Exp $ */
+/*-
+ * Copyright (c) 1990, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * Chris Torek.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include "local.h"
+
+size_t
+fread(void *buf, size_t size, size_t count, FILE *fp)
+{
+	size_t resid;
+	char *p;
+	int r;
+	size_t total;
+
+	/*
+	 * ANSI and SUSv2 require a return value of 0 if size or count are 0.
+	 */
+	if ((resid = count * size) == 0)
+		return (0);
+	FLOCKFILE(fp);
+	_SET_ORIENTATION(fp, -1);
+	if (fp->_r < 0)
+		fp->_r = 0;
+	total = resid;
+	p = buf;
+	while (resid > (r = fp->_r)) {
+		(void)memcpy((void *)p, (void *)fp->_p, (size_t)r);
+		fp->_p += r;
+		/* fp->_r = 0 ... done in __srefill */
+		p += r;
+		resid -= r;
+		if (__srefill(fp)) {
+			/* no more input: return partial result */
+			FUNLOCKFILE(fp);
+			return ((total - resid) / size);
+		}
+	}
+	(void)memcpy((void *)p, (void *)fp->_p, resid);
+	fp->_r -= resid;
+	fp->_p += resid;
+	FUNLOCKFILE(fp);
+	return (count);
+}
diff --git a/libc/stdio/fvwrite.c b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c
similarity index 89%
rename from libc/stdio/fvwrite.c
rename to libc/upstream-openbsd/lib/libc/stdio/fvwrite.c
index 39d0604..1088991 100644
--- a/libc/stdio/fvwrite.c
+++ b/libc/upstream-openbsd/lib/libc/stdio/fvwrite.c
@@ -1,4 +1,4 @@
-/*	$OpenBSD: fvwrite.c,v 1.14 2005/08/08 08:05:36 espie Exp $ */
+/*	$OpenBSD: fvwrite.c,v 1.17 2009/11/09 00:18:27 kurt Exp $ */
 /*-
  * Copyright (c) 1990, 1993
  *	The Regents of the University of California.  All rights reserved.
@@ -44,11 +44,11 @@
  * This routine is large and unsightly, but most of the ugliness due
  * to the three different kinds of output buffering is handled here.
  */
-__LIBC_HIDDEN__ int
+int
 __sfvwrite(FILE *fp, struct __suio *uio)
 {
 	size_t len;
-	const char *p;
+	char *p;
 	struct __siov *iov;
 	int w, s;
 	char *nl;
@@ -82,11 +82,7 @@
 		 */
 		do {
 			GETIOV(;);
-#if 1  /* BIONIC: don't limit to 1KB writes */
-			w = (*fp->_write)(fp->_cookie, p, len);
-#else
-			w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ2));
-#endif
+			w = (*fp->_write)(fp->_cookie, p, MIN(len, BUFSIZ));
 			if (w <= 0)
 				goto err;
 			p += w;
@@ -107,7 +103,7 @@
 		do {
 			GETIOV(;);
 			if ((fp->_flags & (__SALC | __SSTR)) ==
-			    (__SALC | __SSTR) && fp->_w < (int)len) {
+			    (__SALC | __SSTR) && fp->_w < len) {
 				size_t blen = fp->_p - fp->_bf._base;
 				unsigned char *_base;
 				int _size;
@@ -116,7 +112,7 @@
 				_size = fp->_bf._size;
 				do {
 					_size = (_size << 1) + 1;
-				} while (_size < (int)(blen + len));
+				} while (_size < blen + len);
 				_base = realloc(fp->_bf._base, _size + 1);
 				if (_base == NULL)
 					goto err;
@@ -127,20 +123,20 @@
 			}
 			w = fp->_w;
 			if (fp->_flags & __SSTR) {
-				if ((int)len < w)
+				if (len < w)
 					w = len;
 				COPY(w);	/* copy MIN(fp->_w,len), */
 				fp->_w -= w;
 				fp->_p += w;
 				w = len;	/* but pretend copied all */
-			} else if (fp->_p > fp->_bf._base && (int)len > w) {
+			} else if (fp->_p > fp->_bf._base && len > w) {
 				/* fill and flush */
 				COPY(w);
 				/* fp->_w -= w; */ /* unneeded */
 				fp->_p += w;
-				if (fflush(fp))
+				if (__sflush(fp))
 					goto err;
-			} else if ((int)len >= (w = fp->_bf._size)) {
+			} else if (len >= (w = fp->_bf._size)) {
 				/* write directly */
 				w = (*fp->_write)(fp->_cookie, p, w);
 				if (w <= 0)
@@ -169,21 +165,21 @@
 			GETIOV(nlknown = 0);
 			if (!nlknown) {
 				nl = memchr((void *)p, '\n', len);
-				nldist = nl ? nl + 1 - p : (int)len + 1;
+				nldist = nl ? nl + 1 - p : len + 1;
 				nlknown = 1;
 			}
-			s = MIN((int)len, nldist);
+			s = MIN(len, nldist);
 			w = fp->_w + fp->_bf._size;
 			if (fp->_p > fp->_bf._base && s > w) {
 				COPY(w);
 				/* fp->_w -= w; */
 				fp->_p += w;
-				if (fflush(fp))
+				if (__sflush(fp))
 					goto err;
 			} else if (s >= (w = fp->_bf._size)) {
 				w = (*fp->_write)(fp->_cookie, p, w);
 				if (w <= 0)
-					goto err;
+				 	goto err;
 			} else {
 				w = s;
 				COPY(w);
@@ -192,7 +188,7 @@
 			}
 			if ((nldist -= w) == 0) {
 				/* copied the newline: flush and forget */
-				if (fflush(fp))
+				if (__sflush(fp))
 					goto err;
 				nlknown = 0;
 			}