Merge "Make uselocale(3) claim its pthread key in an ELF constructor."
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/bionic/wchar.cpp b/libc/bionic/wchar.cpp
index a507808..021d14b 100644
--- a/libc/bionic/wchar.cpp
+++ b/libc/bionic/wchar.cpp
@@ -250,6 +250,9 @@
     // TODO: UTF-8 support.
     if ((*src)[i] > 0x7f) {
       errno = EILSEQ;
+      if (dst != NULL) {
+        *src = &(*src)[i];
+      }
       return static_cast<size_t>(-1);
     }
     if (dst != NULL) {
diff --git a/libc/include/locale.h b/libc/include/locale.h
index 6989851..7fd8c2c 100644
--- a/libc/include/locale.h
+++ b/libc/include/locale.h
@@ -33,21 +33,19 @@
 
 __BEGIN_DECLS
 
-enum {
-    LC_CTYPE     = 0,
-    LC_NUMERIC   = 1,
-    LC_TIME      = 2,
-    LC_COLLATE   = 3,
-    LC_MONETARY  = 4,
-    LC_MESSAGES  = 5,
-    LC_ALL       = 6,
-    LC_PAPER     = 7,
-    LC_NAME      = 8,
-    LC_ADDRESS   = 9,
-    LC_TELEPHONE      = 10,
-    LC_MEASUREMENT    = 11,
-    LC_IDENTIFICATION = 12
-};
+#define LC_CTYPE           0
+#define LC_NUMERIC         1
+#define LC_TIME            2
+#define LC_COLLATE         3
+#define LC_MONETARY        4
+#define LC_MESSAGES        5
+#define LC_ALL             6
+#define LC_PAPER           7
+#define LC_NAME            8
+#define LC_ADDRESS         9
+#define LC_TELEPHONE      10
+#define LC_MEASUREMENT    11
+#define LC_IDENTIFICATION 12
 
 #define LC_CTYPE_MASK          (1 << LC_CTYPE)
 #define LC_NUMERIC_MASK        (1 << LC_NUMERIC)
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;
 			}
diff --git a/tests/wchar_test.cpp b/tests/wchar_test.cpp
index 0a63b00..d5d27ed 100644
--- a/tests/wchar_test.cpp
+++ b/tests/wchar_test.cpp
@@ -58,8 +58,8 @@
 }
 
 TEST(wchar, wcstombs_wcrtombs) {
-  wchar_t chars[] = { L'h', L'e', L'l', L'l', L'o', 0 };
-  wchar_t bad_chars[] = { L'h', L'i', 666, 0 };
+  const wchar_t chars[] = { L'h', L'e', L'l', L'l', L'o', 0 };
+  const wchar_t bad_chars[] = { L'h', L'i', 666, 0 };
   const wchar_t* src;
   char bytes[BUFSIZ];