resolved conflicts for merge of 50a83255 to gingerbread-plus-aosp

Change-Id: Idf1971120bbdd52676f95aa3aa69f62342dc012e
diff --git a/libc/Android.mk b/libc/Android.mk
index aae80da..65c49ac 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -187,7 +187,6 @@
 	string/strcat.c \
 	string/strchr.c \
 	string/strcoll.c \
-	string/strcpy.c \
 	string/strcspn.c \
 	string/strdup.c \
 	string/strerror.c \
@@ -230,6 +229,7 @@
 	wchar/wcsstr.c \
 	wchar/wcstok.c \
 	wchar/wcswidth.c \
+	wchar/wcsxfrm.c \
 	wchar/wmemchr.c \
 	wchar/wmemcmp.c \
 	wchar/wmemcpy.c \
@@ -241,13 +241,14 @@
 	inet/inet_ntoa.c \
 	inet/inet_ntop.c \
 	inet/inet_pton.c \
+	inet/ether_aton.c \
+	inet/ether_ntoa.c \
 	tzcode/asctime.c \
 	tzcode/difftime.c \
 	tzcode/localtime.c \
 	tzcode/strftime.c \
 	tzcode/strptime.c \
 	bionic/__set_errno.c \
-	bionic/_rand48.c \
 	bionic/cpuacct.c \
 	bionic/arc4random.c \
 	bionic/basename.c \
@@ -270,6 +271,10 @@
 	bionic/md5.c \
 	bionic/pututline.c \
 	bionic/realpath.c \
+	bionic/sched_getaffinity.c \
+	bionic/sched_getcpu.c \
+	bionic/sched_cpualloc.c \
+	bionic/sched_cpucount.c \
 	bionic/semaphore.c \
 	bionic/sha1.c \
 	bionic/ssp.c \
@@ -354,10 +359,11 @@
 	arch-arm/bionic/setjmp.S \
 	arch-arm/bionic/sigsetjmp.S \
 	arch-arm/bionic/strlen.c.arm \
+	arch-arm/bionic/strcpy.S \
+	arch-arm/bionic/strcmp.S \
 	arch-arm/bionic/syscall.S \
 	string/memmove.c.arm \
 	string/bcopy.c \
-	string/strcmp.c \
 	string/strncmp.c \
 	unistd/socketcalls.c
 
@@ -365,6 +371,7 @@
 # can set breakpoints in them without messing
 # up any thumb code.
 libc_common_src_files += \
+	bionic/pthread-atfork.c.arm \
 	bionic/pthread-rwlocks.c.arm \
 	bionic/pthread-timers.c.arm \
 	bionic/ptrace.c.arm
@@ -391,6 +398,7 @@
 	arch-x86/bionic/_exit_with_stack_teardown.S \
 	arch-x86/bionic/setjmp.S \
 	arch-x86/bionic/_setjmp.S \
+	arch-x86/bionic/sigsetjmp.S \
 	arch-x86/bionic/vfork.S \
 	arch-x86/bionic/syscall.S \
 	arch-x86/string/bcopy_wrapper.S \
@@ -402,6 +410,8 @@
 	arch-x86/string/strcmp_wrapper.S \
 	arch-x86/string/strncmp_wrapper.S \
 	arch-x86/string/strlen_wrapper.S \
+	string/strcpy.c \
+	bionic/pthread-atfork.c \
 	bionic/pthread-rwlocks.c \
 	bionic/pthread-timers.c \
 	bionic/ptrace.c
@@ -441,6 +451,8 @@
 	string/strncmp.c \
 	string/memcmp.c \
 	string/strlen.c \
+	string/strcpy.c \
+	bionic/pthread-atfork.c \
 	bionic/pthread-rwlocks.c \
 	bionic/pthread-timers.c \
 	bionic/ptrace.c \
@@ -467,7 +479,8 @@
 		-DINET6 \
 		-I$(LOCAL_PATH)/private \
 		-DUSE_DL_PREFIX \
-		-DPOSIX_MISTAKE
+		-DPOSIX_MISTAKE \
+                -DLOG_ON_HEAP_ERROR \
 
 # these macro definitions are required to implement the
 # 'timezone' and 'daylight' global variables, as well as
@@ -527,6 +540,10 @@
 		$(LOCAL_PATH)/string  \
 		$(LOCAL_PATH)/stdio
 
+# Needed to access private/__dso_handle.S from
+# crtbegin_xxx.S and crtend_xxx.S
+#
+libc_crt_target_cflags += -I$(LOCAL_PATH)/private
 
 # Define the libc run-time (crt) support object files that must be built,
 # which are needed to build all other objects (shared/static libs and
diff --git a/libc/NOTICE b/libc/NOTICE
index e8076b5..d9e6818 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -1,5 +1,5 @@
 
-Copyright (c) 2005-2008, The Android Open Source Project
+Copyright (c) 2005-2010, The Android Open Source Project
 All rights reserved.
 
 Redistribution and use in source and binary forms, with or without
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 0850b82..356f69b 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -76,6 +76,8 @@
 pid_t   vfork(void)  190,-1,190
 int     setregid:setregid32(gid_t, gid_t)  204
 int     chroot(const char *)  61
+# IMPORTANT: Even though <sys/prctl.h> declares prctl(int,...), the syscall stub must take 6 arguments
+#            to match the kernel implementation.
 int     prctl(int option, unsigned int arg2, unsigned int arg3, unsigned int arg4, unsigned int arg5)  172
 int     capget(cap_user_header_t header, cap_user_data_t data) 184
 int     capset(cap_user_header_t header, const cap_user_data_t data) 185
@@ -85,8 +87,8 @@
 # file descriptors
 ssize_t     read (int, void*, size_t)        3
 ssize_t     write (int, const void*, size_t)       4
-ssize_t     __pread64:pread64 (int, void *, size_t, off_t, off_t) 180
-ssize_t     __pwrite64:pwrite64 (int, void *, size_t, off_t, off_t) 181
+ssize_t     pread64 (int, void *, size_t, off64_t) 180
+ssize_t     pwrite64 (int, void *, size_t, off64_t) 181
 int         __open:open (const char*, int, mode_t)  5
 int         __openat:openat (int, const char*, int, mode_t)  322,295
 int         close (int)                      6
@@ -116,6 +118,7 @@
 int         dup2(int, int)   63
 int         select:_newselect(int, struct fd_set *, struct fd_set *, struct fd_set *, struct timeval *)  142
 int         ftruncate(int, off_t)  93
+int         ftruncate64(int, off64_t) 194
 int         getdents:getdents64(unsigned int, struct dirent *, unsigned int)   217,220
 int         fsync(int)  118
 int         fdatasync(int) 148
@@ -229,6 +232,9 @@
 int sched_get_priority_max(int policy)  159
 int sched_get_priority_min(int policy)  160
 int sched_rr_get_interval(pid_t pid, struct timespec *interval)  161
+int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set) 241
+int __sched_getaffinity:sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set)  242
+int __getcpu:getcpu(unsigned *cpu, unsigned *node, void *unused) 345,318,318
 
 # io priorities
 int ioprio_set(int which, int who, int ioprio) 314,289,288
diff --git a/libc/arch-arm/bionic/strcmp.S b/libc/arch-arm/bionic/strcmp.S
new file mode 100644
index 0000000..9fdbd56
--- /dev/null
+++ b/libc/arch-arm/bionic/strcmp.S
@@ -0,0 +1,321 @@
+/*
+ * Copyright (c) 2011 The Android Open Source Project
+ * Copyright (c) 2008 ARM Ltd
+ * All rights reserved.
+ *
+ * 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. The name of the company may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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 <machine/cpu-features.h>
+
+	.text
+
+	.global strcmp
+	.type strcmp, %function
+	.align 4
+
+#ifdef __ARMEB__
+#define SHFT2LSB lsl
+#define SHFT2LSBEQ lsleq
+#define SHFT2MSB lsr
+#define SHFT2MSBEQ lsreq
+#define MSB 0x000000ff
+#define LSB 0xff000000
+#else
+#define SHFT2LSB lsr
+#define SHFT2LSBEQ lsreq
+#define SHFT2MSB lsl
+#define SHFT2MSBEQ lsleq
+#define MSB 0xff000000
+#define LSB 0x000000ff
+#endif
+
+#define magic1(REG) REG
+#define magic2(REG) REG, lsl #7
+
+strcmp:
+	.fnstart
+	PLD(r0, #0)
+	PLD(r1, #0)
+	eor	r2, r0, r1
+	tst	r2, #3
+
+	/* Strings not at same byte offset from a word boundary.  */
+	bne	.Lstrcmp_unaligned
+	ands	r2, r0, #3
+	bic	r0, r0, #3
+	bic	r1, r1, #3
+	ldr	ip, [r0], #4
+	it	eq
+	ldreq	r3, [r1], #4
+	beq	1f
+
+	/* Although s1 and s2 have identical initial alignment, they are
+	 * not currently word aligned.  Rather than comparing bytes,
+	 * make sure that any bytes fetched from before the addressed
+	 * bytes are forced to 0xff.  Then they will always compare
+	 * equal.
+	 */
+	eor	r2, r2, #3
+	lsl	r2, r2, #3
+	mvn	r3, #MSB
+	SHFT2LSB	r2, r3, r2
+	ldr	r3, [r1], #4
+	orr	ip, ip, r2
+	orr	r3, r3, r2
+1:
+	/* Load the 'magic' constant 0x01010101. */
+	str	r4, [sp, #-4]!
+	mov	r4, #1
+	orr	r4, r4, r4, lsl #8
+	orr	r4, r4, r4, lsl #16
+	.p2align	2
+4:
+	PLD(r0, #8)
+	PLD(r1, #8)
+	sub	r2, ip, magic1(r4)
+	cmp	ip, r3
+	itttt	eq
+
+	/* check for any zero bytes in first word */
+	biceq	r2, r2, ip
+	tsteq	r2, magic2(r4)
+	ldreq	ip, [r0], #4
+	ldreq	r3, [r1], #4
+	beq	4b
+2:
+	/* There's a zero or a different byte in the word */
+	SHFT2MSB	r0, ip, #24
+	SHFT2LSB	ip, ip, #8
+	cmp	r0, #1
+	it	cs
+	cmpcs	r0, r3, SHFT2MSB #24
+	it	eq
+	SHFT2LSBEQ r3, r3, #8
+	beq	2b
+	/* On a big-endian machine, r0 contains the desired byte in bits
+	 * 0-7; on a little-endian machine they are in bits 24-31.  In
+	 * both cases the other bits in r0 are all zero.  For r3 the
+	 * interesting byte is at the other end of the word, but the
+	 * other bits are not necessarily zero.  We need a signed result
+	 * representing the differnece in the unsigned bytes, so for the
+	 * little-endian case we can't just shift the interesting bits up.
+	 */
+#ifdef __ARMEB__
+	sub	r0, r0, r3, lsr #24
+#else
+	and	r3, r3, #255
+	/* No RSB instruction in Thumb2 */
+#ifdef __thumb2__
+	lsr	r0, r0, #24
+	sub	r0, r0, r3
+#else
+	rsb	r0, r3, r0, lsr #24
+#endif
+#endif
+	ldr	r4, [sp], #4
+	bx	lr
+	.fnend
+
+.Lstrcmp_unaligned:
+	wp1 .req r0
+	wp2 .req r1
+	b1  .req r2
+	w1  .req r4
+	w2  .req r5
+	t1  .req ip
+	@ r3 is scratch
+
+	/* First of all, compare bytes until wp1(sp1) is word-aligned. */
+1:
+	tst	wp1, #3
+	beq	2f
+	ldrb	r2, [wp1], #1
+	ldrb	r3, [wp2], #1
+	cmp	r2, #1
+	it	cs
+	cmpcs	r2, r3
+	beq	1b
+	sub	r0, r2, r3
+	bx	lr
+
+2:
+	str	r5, [sp, #-4]!
+	str	r4, [sp, #-4]!
+	mov	b1, #1
+	orr	b1, b1, b1, lsl #8
+	orr	b1, b1, b1, lsl #16
+
+	and	t1, wp2, #3
+	bic	wp2, wp2, #3
+	ldr	w1, [wp1], #4
+	ldr	w2, [wp2], #4
+	cmp	t1, #2
+	beq	2f
+	bhi	3f
+
+	/* Critical inner Loop: Block with 3 bytes initial overlap */
+	.p2align	2
+1:
+	bic	t1, w1, #MSB
+	cmp	t1, w2, SHFT2LSB #8
+	sub	r3, w1, b1
+	bic	r3, r3, w1
+	bne	4f
+	ands	r3, r3, b1, lsl #7
+	it	eq
+	ldreq	w2, [wp2], #4
+	bne	5f
+	eor	t1, t1, w1
+	cmp	t1, w2, SHFT2MSB #24
+	bne	6f
+	ldr	w1, [wp1], #4
+	b	1b
+4:
+	SHFT2LSB	w2, w2, #8
+	b	8f
+
+5:
+#ifdef __ARMEB__
+	/* The syndrome value may contain false ones if the string ends
+	 * with the bytes 0x01 0x00
+	 */
+	tst	w1, #0xff000000
+	itt	ne
+	tstne	w1, #0x00ff0000
+	tstne	w1, #0x0000ff00
+	beq	7f
+#else
+	bics	r3, r3, #0xff000000
+	bne	7f
+#endif
+	ldrb	w2, [wp2]
+	SHFT2LSB	t1, w1, #24
+#ifdef __ARMEB__
+	lsl	w2, w2, #24
+#endif
+	b	8f
+
+6:
+	SHFT2LSB	t1, w1, #24
+	and	w2, w2, #LSB
+	b	8f
+
+	/* Critical inner Loop: Block with 2 bytes initial overlap */
+	.p2align	2
+2:
+	SHFT2MSB	t1, w1, #16
+	sub	r3, w1, b1
+	SHFT2LSB	t1, t1, #16
+	bic	r3, r3, w1
+	cmp	t1, w2, SHFT2LSB #16
+	bne	4f
+	ands	r3, r3, b1, lsl #7
+	it	eq
+	ldreq	w2, [wp2], #4
+	bne	5f
+	eor	t1, t1, w1
+	cmp	t1, w2, SHFT2MSB #16
+	bne	6f
+	ldr	w1, [wp1], #4
+	b	2b
+
+5:
+#ifdef __ARMEB__
+	/* The syndrome value may contain false ones if the string ends
+	 * with the bytes 0x01 0x00
+	 */
+	tst	w1, #0xff000000
+	it	ne
+	tstne	w1, #0x00ff0000
+	beq	7f
+#else
+	lsls	r3, r3, #16
+	bne	7f
+#endif
+	ldrh	w2, [wp2]
+	SHFT2LSB	t1, w1, #16
+#ifdef __ARMEB__
+	lsl	w2, w2, #16
+#endif
+	b	8f
+
+6:
+	SHFT2MSB	w2, w2, #16
+	SHFT2LSB	t1, w1, #16
+4:
+	SHFT2LSB	w2, w2, #16
+	b	8f
+
+	/* Critical inner Loop: Block with 1 byte initial overlap */
+	.p2align	2
+3:
+	and	t1, w1, #LSB
+	cmp	t1, w2, SHFT2LSB #24
+	sub	r3, w1, b1
+	bic	r3, r3, w1
+	bne	4f
+	ands	r3, r3, b1, lsl #7
+	it	eq
+	ldreq	w2, [wp2], #4
+	bne	5f
+	eor	t1, t1, w1
+	cmp	t1, w2, SHFT2MSB #8
+	bne	6f
+	ldr	w1, [wp1], #4
+	b	3b
+4:
+	SHFT2LSB	w2, w2, #24
+	b	8f
+5:
+	/* The syndrome value may contain false ones if the string ends
+	 * with the bytes 0x01 0x00
+	 */
+	tst	w1, #LSB
+	beq	7f
+	ldr	w2, [wp2], #4
+6:
+	SHFT2LSB	t1, w1, #8
+	bic	w2, w2, #MSB
+	b	8f
+7:
+	mov	r0, #0
+	ldr	r4, [sp], #4
+	ldr	r5, [sp], #4
+	bx	lr
+
+8:
+	and	r2, t1, #LSB
+	and	r0, w2, #LSB
+	cmp	r0, #1
+	it	cs
+	cmpcs	r0, r2
+	itt	eq
+	SHFT2LSBEQ	t1, t1, #8
+	SHFT2LSBEQ	w2, w2, #8
+	beq	8b
+	sub	r0, r2, r0
+	ldr	r4, [sp], #4
+	ldr	r5, [sp], #4
+	bx	lr
diff --git a/libc/arch-arm/bionic/strcpy.S b/libc/arch-arm/bionic/strcpy.S
new file mode 100644
index 0000000..70c353f
--- /dev/null
+++ b/libc/arch-arm/bionic/strcpy.S
@@ -0,0 +1,138 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (c) 2008 ARM Ltd
+ * All rights reserved.
+ *
+ * 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. The name of the company may not be used to endorse or promote
+ *    products derived from this software without specific prior written
+ *    permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``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 ARM LTD 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.
+ *
+ * Android adaptation and tweak by Jim Huang <jserv@0xlab.org>.
+ */
+
+#include <machine/cpu-features.h>
+
+	.text
+
+	.global strcpy
+	.type strcpy, %function
+	.align 4
+
+strcpy:
+	.fnstart
+	PLD(r1, #0)
+	eor	r2, r0, r1
+	mov	ip, r0
+	tst	r2, #3
+	bne	4f
+	tst	r1, #3
+	bne	3f
+5:
+	str	r5, [sp, #-4]!
+	mov	r5, #0x01
+	orr	r5, r5, r5, lsl #8
+	orr	r5, r5, r5, lsl #16
+
+	str	r4, [sp, #-4]!
+	tst	r1, #4
+	ldr	r3, [r1], #4
+	beq	2f
+	sub	r2, r3, r5
+	bics	r2, r2, r3
+	tst	r2, r5, lsl #7
+	itt	eq
+	streq	r3, [ip], #4
+	ldreq	r3, [r1], #4
+	bne	1f
+       /* Inner loop.  We now know that r1 is 64-bit aligned, so we
+	  can safely fetch up to two words.  This allows us to avoid
+	  load stalls.  */
+	.p2align 2
+2:
+	PLD(r1, #8)
+	ldr	r4, [r1], #4
+	sub	r2, r3, r5
+	bics	r2, r2, r3
+	tst	r2, r5, lsl #7
+	sub	r2, r4, r5
+	bne	1f
+	str	r3, [ip], #4
+	bics	r2, r2, r4
+	tst	r2, r5, lsl #7
+	itt	eq
+	ldreq	r3, [r1], #4
+	streq	r4, [ip], #4
+	beq	2b
+	mov	r3, r4
+1:
+#ifdef __ARMEB__
+	rors	r3, r3, #24
+#endif
+	strb	r3, [ip], #1
+	tst	r3, #0xff
+#ifdef __ARMEL__
+	ror	r3, r3, #8
+#endif
+	bne	1b
+	ldr	r4, [sp], #4
+	ldr	r5, [sp], #4
+	bx	lr
+
+       /* Strings have the same offset from word alignment, but it's
+	  not zero.  */
+3:
+	tst	r1, #1
+	beq	1f
+	ldrb	r2, [r1], #1
+	strb	r2, [ip], #1
+	cmp	r2, #0
+	it	eq
+	bxeq	lr
+1:
+	tst	r1, #2
+	beq	5b
+	ldrh	r2, [r1], #2
+#ifdef __ARMEB__
+	tst	r2, #0xff00
+	iteet	ne
+	strneh	r2, [ip], #2
+	lsreq	r2, r2, #8
+	streqb	r2, [ip]
+	tstne	r2, #0xff
+#else
+	tst	r2, #0xff
+	itet	ne
+	strneh	r2, [ip], #2
+	streqb	r2, [ip]
+	tstne	r2, #0xff00
+#endif
+	bne	5b
+	bx	lr
+
+       /* src and dst do not have a common word-alignement.  Fall back to
+	  byte copying.  */
+4:
+	ldrb	r2, [r1], #1
+	strb	r2, [ip], #1
+	cmp	r2, #0
+	bne	4b
+	bx	lr
diff --git a/libc/arch-arm/include/endian.h b/libc/arch-arm/include/endian.h
index 04204ed..6de0889 100644
--- a/libc/arch-arm/include/endian.h
+++ b/libc/arch-arm/include/endian.h
@@ -1,10 +1,89 @@
 /*	$OpenBSD: endian.h,v 1.3 2005/12/13 00:35:23 millert Exp $	*/
 
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ */
+
+#ifndef _ARM_ENDIAN_H_
+#define _ARM_ENDIAN_H_
+
+#ifdef __GNUC__
+
+/*
+ * REV and REV16 weren't available on ARM5 or ARM4.
+ * We don't include <machine/cpu-features.h> because it pollutes the
+ * namespace with macros like PLD.
+ */
+#if !defined __ARM_ARCH_5__ && !defined __ARM_ARCH_5T__ && \
+    !defined __ARM_ARCH_5TE__ && !defined __ARM_ARCH_5TEJ__ && \
+    !defined __ARM_ARCH_4T__ && !defined __ARM_ARCH_4__
+
+/* According to RealView Assembler User's Guide, REV and REV16 are available
+ * in Thumb code and 16-bit instructions when used in Thumb-2 code.
+ *
+ * REV Rd, Rm
+ *   Rd and Rm must both be Lo registers.
+ *
+ * REV16 Rd, Rm
+ *   Rd and Rm must both be Lo registers.
+ *
+ * The +l constraint takes care of this without constraining us in ARM mode.
+ */
+#define __swap16md(x) ({                                        \
+    register u_int16_t _x = (x);                                \
+    __asm volatile ("rev16 %0, %0" : "+l" (_x));                \
+    _x;                                                         \
+})
+
+#define __swap32md(x) ({                                        \
+    register u_int32_t _x = (x);                                \
+    __asm volatile ("rev %0, %0" : "+l" (_x));                  \
+    _x;                                                         \
+})
+
+#define __swap64md(x) ({                                        \
+    u_int64_t _swap64md_x = (x);                                \
+    (u_int64_t) __swap32md(_swap64md_x >> 32) |                 \
+        (u_int64_t) __swap32md(_swap64md_x & 0xffffffff) << 32; \
+})
+
+/* Tell sys/endian.h we have MD variants of the swap macros.  */
+#define MD_SWAP
+
+#endif  /* __ARM_ARCH__ */
+#endif  /* __GNUC__ */
+
 #ifdef __ARMEB__
 #define _BYTE_ORDER _BIG_ENDIAN
 #else
 #define _BYTE_ORDER _LITTLE_ENDIAN
 #endif
-#define	__STRICT_ALIGNMENT
+#define __STRICT_ALIGNMENT
 #include <sys/types.h>
 #include <sys/endian.h>
+
+#endif  /* !_ARM_ENDIAN_H_ */
diff --git a/libc/arch-arm/include/machine/cpu-features.h b/libc/arch-arm/include/machine/cpu-features.h
index 39c1db3..80d3fda 100644
--- a/libc/arch-arm/include/machine/cpu-features.h
+++ b/libc/arch-arm/include/machine/cpu-features.h
@@ -185,6 +185,7 @@
 #endif
 
 /* Assembly-only macros */
+#ifdef __ASSEMBLY__
 
 /* define a handy PLD(address) macro since the cache preload
  * is an optional opcode
@@ -195,4 +196,6 @@
 #  define  PLD(reg,offset)    /* nothing */
 #endif
 
+#endif /* ! __ASSEMBLY__ */
+
 #endif /* _ARM_MACHINE_CPU_FEATURES_H */
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index ba78c18..5210d6c 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -41,8 +41,8 @@
 syscall_src += arch-arm/syscalls/acct.S
 syscall_src += arch-arm/syscalls/read.S
 syscall_src += arch-arm/syscalls/write.S
-syscall_src += arch-arm/syscalls/__pread64.S
-syscall_src += arch-arm/syscalls/__pwrite64.S
+syscall_src += arch-arm/syscalls/pread64.S
+syscall_src += arch-arm/syscalls/pwrite64.S
 syscall_src += arch-arm/syscalls/__open.S
 syscall_src += arch-arm/syscalls/__openat.S
 syscall_src += arch-arm/syscalls/close.S
@@ -70,6 +70,7 @@
 syscall_src += arch-arm/syscalls/dup2.S
 syscall_src += arch-arm/syscalls/select.S
 syscall_src += arch-arm/syscalls/ftruncate.S
+syscall_src += arch-arm/syscalls/ftruncate64.S
 syscall_src += arch-arm/syscalls/getdents.S
 syscall_src += arch-arm/syscalls/fsync.S
 syscall_src += arch-arm/syscalls/fdatasync.S
@@ -153,6 +154,9 @@
 syscall_src += arch-arm/syscalls/sched_get_priority_max.S
 syscall_src += arch-arm/syscalls/sched_get_priority_min.S
 syscall_src += arch-arm/syscalls/sched_rr_get_interval.S
+syscall_src += arch-arm/syscalls/sched_setaffinity.S
+syscall_src += arch-arm/syscalls/__sched_getaffinity.S
+syscall_src += arch-arm/syscalls/__getcpu.S
 syscall_src += arch-arm/syscalls/ioprio_set.S
 syscall_src += arch-arm/syscalls/ioprio_get.S
 syscall_src += arch-arm/syscalls/uname.S
diff --git a/libc/arch-arm/syscalls/__getcpu.S b/libc/arch-arm/syscalls/__getcpu.S
new file mode 100644
index 0000000..ed6927a
--- /dev/null
+++ b/libc/arch-arm/syscalls/__getcpu.S
@@ -0,0 +1,19 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type __getcpu, #function
+    .globl __getcpu
+    .align 4
+    .fnstart
+
+__getcpu:
+    .save   {r4, r7}
+    stmfd   sp!, {r4, r7}
+    ldr     r7, =__NR_getcpu
+    swi     #0
+    ldmfd   sp!, {r4, r7}
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+    .fnend
diff --git a/libc/arch-arm/syscalls/__sched_getaffinity.S b/libc/arch-arm/syscalls/__sched_getaffinity.S
new file mode 100644
index 0000000..71f2b1d
--- /dev/null
+++ b/libc/arch-arm/syscalls/__sched_getaffinity.S
@@ -0,0 +1,19 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type __sched_getaffinity, #function
+    .globl __sched_getaffinity
+    .align 4
+    .fnstart
+
+__sched_getaffinity:
+    .save   {r4, r7}
+    stmfd   sp!, {r4, r7}
+    ldr     r7, =__NR_sched_getaffinity
+    swi     #0
+    ldmfd   sp!, {r4, r7}
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+    .fnend
diff --git a/libc/arch-arm/syscalls/ftruncate64.S b/libc/arch-arm/syscalls/ftruncate64.S
new file mode 100644
index 0000000..37b4744
--- /dev/null
+++ b/libc/arch-arm/syscalls/ftruncate64.S
@@ -0,0 +1,19 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type ftruncate64, #function
+    .globl ftruncate64
+    .align 4
+    .fnstart
+
+ftruncate64:
+    .save   {r4, r7}
+    stmfd   sp!, {r4, r7}
+    ldr     r7, =__NR_ftruncate64
+    swi     #0
+    ldmfd   sp!, {r4, r7}
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+    .fnend
diff --git a/libc/arch-arm/syscalls/__pread64.S b/libc/arch-arm/syscalls/pread64.S
similarity index 85%
rename from libc/arch-arm/syscalls/__pread64.S
rename to libc/arch-arm/syscalls/pread64.S
index ea645e1..a54084c 100644
--- a/libc/arch-arm/syscalls/__pread64.S
+++ b/libc/arch-arm/syscalls/pread64.S
@@ -2,12 +2,12 @@
 #include <sys/linux-syscalls.h>
 
     .text
-    .type __pread64, #function
-    .globl __pread64
+    .type pread64, #function
+    .globl pread64
     .align 4
     .fnstart
 
-__pread64:
+pread64:
     mov     ip, sp
     .save   {r4, r5, r6, r7}
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/__pwrite64.S b/libc/arch-arm/syscalls/pwrite64.S
similarity index 85%
rename from libc/arch-arm/syscalls/__pwrite64.S
rename to libc/arch-arm/syscalls/pwrite64.S
index d1263be..f9d56b2 100644
--- a/libc/arch-arm/syscalls/__pwrite64.S
+++ b/libc/arch-arm/syscalls/pwrite64.S
@@ -2,12 +2,12 @@
 #include <sys/linux-syscalls.h>
 
     .text
-    .type __pwrite64, #function
-    .globl __pwrite64
+    .type pwrite64, #function
+    .globl pwrite64
     .align 4
     .fnstart
 
-__pwrite64:
+pwrite64:
     mov     ip, sp
     .save   {r4, r5, r6, r7}
     stmfd   sp!, {r4, r5, r6, r7}
diff --git a/libc/arch-arm/syscalls/sched_setaffinity.S b/libc/arch-arm/syscalls/sched_setaffinity.S
new file mode 100644
index 0000000..aedf8f3
--- /dev/null
+++ b/libc/arch-arm/syscalls/sched_setaffinity.S
@@ -0,0 +1,19 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type sched_setaffinity, #function
+    .globl sched_setaffinity
+    .align 4
+    .fnstart
+
+sched_setaffinity:
+    .save   {r4, r7}
+    stmfd   sp!, {r4, r7}
+    ldr     r7, =__NR_sched_setaffinity
+    swi     #0
+    ldmfd   sp!, {r4, r7}
+    movs    r0, r0
+    bxpl    lr
+    b       __set_syscall_errno
+    .fnend
diff --git a/libc/arch-sh/syscalls.mk b/libc/arch-sh/syscalls.mk
index a87419d..9575905 100644
--- a/libc/arch-sh/syscalls.mk
+++ b/libc/arch-sh/syscalls.mk
@@ -45,8 +45,8 @@
 syscall_src += arch-sh/syscalls/acct.S
 syscall_src += arch-sh/syscalls/read.S
 syscall_src += arch-sh/syscalls/write.S
-syscall_src += arch-sh/syscalls/__pread64.S
-syscall_src += arch-sh/syscalls/__pwrite64.S
+syscall_src += arch-sh/syscalls/pread64.S
+syscall_src += arch-sh/syscalls/pwrite64.S
 syscall_src += arch-sh/syscalls/__open.S
 syscall_src += arch-sh/syscalls/__openat.S
 syscall_src += arch-sh/syscalls/close.S
@@ -73,6 +73,7 @@
 syscall_src += arch-sh/syscalls/dup2.S
 syscall_src += arch-sh/syscalls/select.S
 syscall_src += arch-sh/syscalls/ftruncate.S
+syscall_src += arch-sh/syscalls/ftruncate64.S
 syscall_src += arch-sh/syscalls/getdents.S
 syscall_src += arch-sh/syscalls/fsync.S
 syscall_src += arch-sh/syscalls/fdatasync.S
@@ -142,6 +143,9 @@
 syscall_src += arch-sh/syscalls/sched_get_priority_max.S
 syscall_src += arch-sh/syscalls/sched_get_priority_min.S
 syscall_src += arch-sh/syscalls/sched_rr_get_interval.S
+syscall_src += arch-sh/syscalls/sched_setaffinity.S
+syscall_src += arch-sh/syscalls/__sched_getaffinity.S
+syscall_src += arch-sh/syscalls/__getcpu.S
 syscall_src += arch-sh/syscalls/ioprio_set.S
 syscall_src += arch-sh/syscalls/ioprio_get.S
 syscall_src += arch-sh/syscalls/uname.S
diff --git a/libc/arch-sh/syscalls/__pwrite64.S b/libc/arch-sh/syscalls/__getcpu.S
similarity index 63%
copy from libc/arch-sh/syscalls/__pwrite64.S
copy to libc/arch-sh/syscalls/__getcpu.S
index a722242..125387b 100644
--- a/libc/arch-sh/syscalls/__pwrite64.S
+++ b/libc/arch-sh/syscalls/__getcpu.S
@@ -2,22 +2,19 @@
 #include <sys/linux-syscalls.h>
 
     .text
-    .type __pwrite64, @function
-    .globl __pwrite64
+    .type __getcpu, @function
+    .globl __getcpu
     .align 4
 
-__pwrite64:
-
-    /* get ready for additonal arg */
-    mov.l   @r15, r0
+__getcpu:
 
     /* invoke trap */
     mov.l   0f, r3  /* trap num */
-    trapa   #(5 + 0x10)
+    trapa   #(3 + 0x10)
 
     /* check return value */
     cmp/pz  r0
-    bt      __NR_pwrite64_end
+    bt      __NR_getcpu_end
 
     /* keep error number */
     sts.l   pr, @-r15
@@ -26,10 +23,10 @@
     mov     r0, r4
     lds.l   @r15+, pr
 
-__NR_pwrite64_end:
+__NR_getcpu_end:
     rts
     nop
 
     .align  2
-0:  .long   __NR_pwrite64
+0:  .long   __NR_getcpu
 1:  .long   __set_syscall_errno
diff --git a/libc/arch-sh/syscalls/__pwrite64.S b/libc/arch-sh/syscalls/__sched_getaffinity.S
similarity index 63%
copy from libc/arch-sh/syscalls/__pwrite64.S
copy to libc/arch-sh/syscalls/__sched_getaffinity.S
index a722242..7e8be6a 100644
--- a/libc/arch-sh/syscalls/__pwrite64.S
+++ b/libc/arch-sh/syscalls/__sched_getaffinity.S
@@ -2,22 +2,19 @@
 #include <sys/linux-syscalls.h>
 
     .text
-    .type __pwrite64, @function
-    .globl __pwrite64
+    .type __sched_getaffinity, @function
+    .globl __sched_getaffinity
     .align 4
 
-__pwrite64:
-
-    /* get ready for additonal arg */
-    mov.l   @r15, r0
+__sched_getaffinity:
 
     /* invoke trap */
     mov.l   0f, r3  /* trap num */
-    trapa   #(5 + 0x10)
+    trapa   #(3 + 0x10)
 
     /* check return value */
     cmp/pz  r0
-    bt      __NR_pwrite64_end
+    bt      __NR_sched_getaffinity_end
 
     /* keep error number */
     sts.l   pr, @-r15
@@ -26,10 +23,10 @@
     mov     r0, r4
     lds.l   @r15+, pr
 
-__NR_pwrite64_end:
+__NR_sched_getaffinity_end:
     rts
     nop
 
     .align  2
-0:  .long   __NR_pwrite64
+0:  .long   __NR_sched_getaffinity
 1:  .long   __set_syscall_errno
diff --git a/libc/arch-sh/syscalls/__pwrite64.S b/libc/arch-sh/syscalls/ftruncate64.S
similarity index 63%
copy from libc/arch-sh/syscalls/__pwrite64.S
copy to libc/arch-sh/syscalls/ftruncate64.S
index a722242..f4c7c1e 100644
--- a/libc/arch-sh/syscalls/__pwrite64.S
+++ b/libc/arch-sh/syscalls/ftruncate64.S
@@ -2,22 +2,19 @@
 #include <sys/linux-syscalls.h>
 
     .text
-    .type __pwrite64, @function
-    .globl __pwrite64
+    .type ftruncate64, @function
+    .globl ftruncate64
     .align 4
 
-__pwrite64:
-
-    /* get ready for additonal arg */
-    mov.l   @r15, r0
+ftruncate64:
 
     /* invoke trap */
     mov.l   0f, r3  /* trap num */
-    trapa   #(5 + 0x10)
+    trapa   #(3 + 0x10)
 
     /* check return value */
     cmp/pz  r0
-    bt      __NR_pwrite64_end
+    bt      __NR_ftruncate64_end
 
     /* keep error number */
     sts.l   pr, @-r15
@@ -26,10 +23,10 @@
     mov     r0, r4
     lds.l   @r15+, pr
 
-__NR_pwrite64_end:
+__NR_ftruncate64_end:
     rts
     nop
 
     .align  2
-0:  .long   __NR_pwrite64
+0:  .long   __NR_ftruncate64
 1:  .long   __set_syscall_errno
diff --git a/libc/arch-sh/syscalls/__pread64.S b/libc/arch-sh/syscalls/pread64.S
similarity index 89%
rename from libc/arch-sh/syscalls/__pread64.S
rename to libc/arch-sh/syscalls/pread64.S
index 474add3..702a402 100644
--- a/libc/arch-sh/syscalls/__pread64.S
+++ b/libc/arch-sh/syscalls/pread64.S
@@ -2,11 +2,11 @@
 #include <sys/linux-syscalls.h>
 
     .text
-    .type __pread64, @function
-    .globl __pread64
+    .type pread64, @function
+    .globl pread64
     .align 4
 
-__pread64:
+pread64:
 
     /* get ready for additonal arg */
     mov.l   @r15, r0
diff --git a/libc/arch-sh/syscalls/__pwrite64.S b/libc/arch-sh/syscalls/pwrite64.S
similarity index 89%
rename from libc/arch-sh/syscalls/__pwrite64.S
rename to libc/arch-sh/syscalls/pwrite64.S
index a722242..3f6c192 100644
--- a/libc/arch-sh/syscalls/__pwrite64.S
+++ b/libc/arch-sh/syscalls/pwrite64.S
@@ -2,11 +2,11 @@
 #include <sys/linux-syscalls.h>
 
     .text
-    .type __pwrite64, @function
-    .globl __pwrite64
+    .type pwrite64, @function
+    .globl pwrite64
     .align 4
 
-__pwrite64:
+pwrite64:
 
     /* get ready for additonal arg */
     mov.l   @r15, r0
diff --git a/libc/arch-sh/syscalls/__pwrite64.S b/libc/arch-sh/syscalls/sched_setaffinity.S
similarity index 63%
copy from libc/arch-sh/syscalls/__pwrite64.S
copy to libc/arch-sh/syscalls/sched_setaffinity.S
index a722242..9dda3b4 100644
--- a/libc/arch-sh/syscalls/__pwrite64.S
+++ b/libc/arch-sh/syscalls/sched_setaffinity.S
@@ -2,22 +2,19 @@
 #include <sys/linux-syscalls.h>
 
     .text
-    .type __pwrite64, @function
-    .globl __pwrite64
+    .type sched_setaffinity, @function
+    .globl sched_setaffinity
     .align 4
 
-__pwrite64:
-
-    /* get ready for additonal arg */
-    mov.l   @r15, r0
+sched_setaffinity:
 
     /* invoke trap */
     mov.l   0f, r3  /* trap num */
-    trapa   #(5 + 0x10)
+    trapa   #(3 + 0x10)
 
     /* check return value */
     cmp/pz  r0
-    bt      __NR_pwrite64_end
+    bt      __NR_sched_setaffinity_end
 
     /* keep error number */
     sts.l   pr, @-r15
@@ -26,10 +23,10 @@
     mov     r0, r4
     lds.l   @r15+, pr
 
-__NR_pwrite64_end:
+__NR_sched_setaffinity_end:
     rts
     nop
 
     .align  2
-0:  .long   __NR_pwrite64
+0:  .long   __NR_sched_setaffinity
 1:  .long   __set_syscall_errno
diff --git a/libc/arch-x86/bionic/sigsetjmp.S b/libc/arch-x86/bionic/sigsetjmp.S
new file mode 100644
index 0000000..c990a05
--- /dev/null
+++ b/libc/arch-x86/bionic/sigsetjmp.S
@@ -0,0 +1,92 @@
+/* $OpenBSD: sigsetjmp.S,v 1.7 2005/08/07 11:30:38 espie Exp $ */
+/*-
+ * Copyright (c) 1990 The Regents of the University of California.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to Berkeley by
+ * William Jolitz.
+ *
+ * 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 <machine/asm.h>
+
+ENTRY(sigsetjmp)
+	movl	4(%esp),%ecx
+	movl	8(%esp),%eax
+	movl	%eax,28(%ecx)
+	testl	%eax,%eax
+	jz	1f
+
+	PIC_PROLOGUE
+	pushl	$0
+#ifdef PIC
+	call	PIC_PLT(_C_LABEL(sigblock))
+#else
+	call	_C_LABEL(sigblock)
+#endif
+	addl	$4,%esp
+	PIC_EPILOGUE
+
+	movl	4(%esp),%ecx
+	movl	%eax,24(%ecx)
+1:	movl	0(%esp),%edx
+	movl	%edx, 0(%ecx)
+	movl	%ebx, 4(%ecx)
+	movl	%esp, 8(%ecx)
+	movl	%ebp,12(%ecx)
+	movl	%esi,16(%ecx)
+	movl	%edi,20(%ecx)
+	xorl	%eax,%eax
+	ret
+
+ENTRY(siglongjmp)
+	movl	4(%esp),%edx
+	cmpl	$0,28(%edx)
+	jz	1f
+
+	PIC_PROLOGUE
+	pushl	24(%edx)
+#ifdef PIC
+	call	PIC_PLT(_C_LABEL(sigsetmask))
+#else
+	call	_C_LABEL(sigsetmask)
+#endif
+	addl	$4,%esp
+	PIC_EPILOGUE
+
+1:	movl	4(%esp),%edx
+	movl	8(%esp),%eax
+	movl	0(%edx),%ecx
+	movl	4(%edx),%ebx
+	movl	8(%edx),%esp
+	movl	12(%edx),%ebp
+	movl	16(%edx),%esi
+	movl	20(%edx),%edi
+	testl	%eax,%eax
+	jnz	2f
+	incl	%eax
+2:	movl	%ecx,0(%esp)
+	ret
diff --git a/libc/arch-x86/bionic/syscall.S b/libc/arch-x86/bionic/syscall.S
index 71abe6b..3cca85c 100644
--- a/libc/arch-x86/bionic/syscall.S
+++ b/libc/arch-x86/bionic/syscall.S
@@ -20,18 +20,15 @@
     .align 4
 
 syscall:
-    push    %eax
     push    %ebx
-    push    %ecx
-    push    %edx
     push    %esi
     push    %edi
-    mov     28(%esp),%eax
-    mov     32(%esp),%ebx
-    mov     36(%esp),%ecx
-    mov     40(%esp),%edx
-    mov     44(%esp),%esi
-    mov     48(%esp),%edi
+    mov     16(%esp),%eax
+    mov     20(%esp),%ebx
+    mov     24(%esp),%ecx
+    mov     28(%esp),%edx
+    mov     32(%esp),%esi
+    mov     36(%esp),%edi
 
     int     $0x80
 
@@ -45,8 +42,5 @@
 1:
     pop    %edi
     pop    %esi
-    pop    %edx
-    pop    %ecx
     pop    %ebx
-    pop    %eax
     ret
diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk
index 420a91e..e8c6a77 100644
--- a/libc/arch-x86/syscalls.mk
+++ b/libc/arch-x86/syscalls.mk
@@ -44,8 +44,8 @@
 syscall_src += arch-x86/syscalls/acct.S
 syscall_src += arch-x86/syscalls/read.S
 syscall_src += arch-x86/syscalls/write.S
-syscall_src += arch-x86/syscalls/__pread64.S
-syscall_src += arch-x86/syscalls/__pwrite64.S
+syscall_src += arch-x86/syscalls/pread64.S
+syscall_src += arch-x86/syscalls/pwrite64.S
 syscall_src += arch-x86/syscalls/__open.S
 syscall_src += arch-x86/syscalls/__openat.S
 syscall_src += arch-x86/syscalls/close.S
@@ -73,6 +73,7 @@
 syscall_src += arch-x86/syscalls/dup2.S
 syscall_src += arch-x86/syscalls/select.S
 syscall_src += arch-x86/syscalls/ftruncate.S
+syscall_src += arch-x86/syscalls/ftruncate64.S
 syscall_src += arch-x86/syscalls/getdents.S
 syscall_src += arch-x86/syscalls/fsync.S
 syscall_src += arch-x86/syscalls/fdatasync.S
@@ -156,6 +157,9 @@
 syscall_src += arch-x86/syscalls/sched_get_priority_max.S
 syscall_src += arch-x86/syscalls/sched_get_priority_min.S
 syscall_src += arch-x86/syscalls/sched_rr_get_interval.S
+syscall_src += arch-x86/syscalls/sched_setaffinity.S
+syscall_src += arch-x86/syscalls/__sched_getaffinity.S
+syscall_src += arch-x86/syscalls/__getcpu.S
 syscall_src += arch-x86/syscalls/ioprio_set.S
 syscall_src += arch-x86/syscalls/ioprio_get.S
 syscall_src += arch-x86/syscalls/uname.S
diff --git a/libc/arch-x86/syscalls/__getcpu.S b/libc/arch-x86/syscalls/__getcpu.S
new file mode 100644
index 0000000..0381799
--- /dev/null
+++ b/libc/arch-x86/syscalls/__getcpu.S
@@ -0,0 +1,29 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type __getcpu, @function
+    .globl __getcpu
+    .align 4
+
+__getcpu:
+    pushl   %ebx
+    pushl   %ecx
+    pushl   %edx
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
+    mov     24(%esp), %edx
+    movl    $__NR_getcpu, %eax
+    int     $0x80
+    cmpl    $-129, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %edx
+    popl    %ecx
+    popl    %ebx
+    ret
diff --git a/libc/arch-x86/syscalls/__sched_getaffinity.S b/libc/arch-x86/syscalls/__sched_getaffinity.S
new file mode 100644
index 0000000..43bfa50
--- /dev/null
+++ b/libc/arch-x86/syscalls/__sched_getaffinity.S
@@ -0,0 +1,29 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type __sched_getaffinity, @function
+    .globl __sched_getaffinity
+    .align 4
+
+__sched_getaffinity:
+    pushl   %ebx
+    pushl   %ecx
+    pushl   %edx
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
+    mov     24(%esp), %edx
+    movl    $__NR_sched_getaffinity, %eax
+    int     $0x80
+    cmpl    $-129, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %edx
+    popl    %ecx
+    popl    %ebx
+    ret
diff --git a/libc/arch-x86/syscalls/ftruncate64.S b/libc/arch-x86/syscalls/ftruncate64.S
new file mode 100644
index 0000000..66835ab
--- /dev/null
+++ b/libc/arch-x86/syscalls/ftruncate64.S
@@ -0,0 +1,29 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type ftruncate64, @function
+    .globl ftruncate64
+    .align 4
+
+ftruncate64:
+    pushl   %ebx
+    pushl   %ecx
+    pushl   %edx
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
+    mov     24(%esp), %edx
+    movl    $__NR_ftruncate64, %eax
+    int     $0x80
+    cmpl    $-129, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %edx
+    popl    %ecx
+    popl    %ebx
+    ret
diff --git a/libc/arch-x86/syscalls/__pread64.S b/libc/arch-x86/syscalls/pread64.S
similarity index 90%
rename from libc/arch-x86/syscalls/__pread64.S
rename to libc/arch-x86/syscalls/pread64.S
index 3114673..eb004a9 100644
--- a/libc/arch-x86/syscalls/__pread64.S
+++ b/libc/arch-x86/syscalls/pread64.S
@@ -2,11 +2,11 @@
 #include <sys/linux-syscalls.h>
 
     .text
-    .type __pread64, @function
-    .globl __pread64
+    .type pread64, @function
+    .globl pread64
     .align 4
 
-__pread64:
+pread64:
     pushl   %ebx
     pushl   %ecx
     pushl   %edx
diff --git a/libc/arch-x86/syscalls/__pwrite64.S b/libc/arch-x86/syscalls/pwrite64.S
similarity index 90%
rename from libc/arch-x86/syscalls/__pwrite64.S
rename to libc/arch-x86/syscalls/pwrite64.S
index 28f6536..01389f8 100644
--- a/libc/arch-x86/syscalls/__pwrite64.S
+++ b/libc/arch-x86/syscalls/pwrite64.S
@@ -2,11 +2,11 @@
 #include <sys/linux-syscalls.h>
 
     .text
-    .type __pwrite64, @function
-    .globl __pwrite64
+    .type pwrite64, @function
+    .globl pwrite64
     .align 4
 
-__pwrite64:
+pwrite64:
     pushl   %ebx
     pushl   %ecx
     pushl   %edx
diff --git a/libc/arch-x86/syscalls/sched_setaffinity.S b/libc/arch-x86/syscalls/sched_setaffinity.S
new file mode 100644
index 0000000..5fa51ef
--- /dev/null
+++ b/libc/arch-x86/syscalls/sched_setaffinity.S
@@ -0,0 +1,29 @@
+/* autogenerated by gensyscalls.py */
+#include <sys/linux-syscalls.h>
+
+    .text
+    .type sched_setaffinity, @function
+    .globl sched_setaffinity
+    .align 4
+
+sched_setaffinity:
+    pushl   %ebx
+    pushl   %ecx
+    pushl   %edx
+    mov     16(%esp), %ebx
+    mov     20(%esp), %ecx
+    mov     24(%esp), %edx
+    movl    $__NR_sched_setaffinity, %eax
+    int     $0x80
+    cmpl    $-129, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %edx
+    popl    %ecx
+    popl    %ebx
+    ret
diff --git a/libc/bionic/__set_errno.c b/libc/bionic/__set_errno.c
index c72d4f7..163d404 100644
--- a/libc/bionic/__set_errno.c
+++ b/libc/bionic/__set_errno.c
@@ -40,6 +40,7 @@
  * (tail-called in the case of 0-4 arg versions)
  */
 
+__LIBC_HIDDEN__
 int __set_syscall_errno(int n)
 {
         /* some syscalls, mmap() for example, have valid return
diff --git a/libc/bionic/_rand48.c b/libc/bionic/_rand48.c
deleted file mode 100644
index e422781..0000000
--- a/libc/bionic/_rand48.c
+++ /dev/null
@@ -1,47 +0,0 @@
-/*
- * Copyright (c) 1993 Martin Birgmeier
- * All rights reserved.
- *
- * You may redistribute unmodified or modified versions of this source
- * code provided that the above copyright notice and this and the
- * following conditions are retained.
- *
- * This software is provided ``as is'', and comes with no warranties
- * of any kind. I shall in no event be liable for anything that happens
- * to anyone/anything when using this software.
- */
-
-#include <sys/cdefs.h>
-#include "rand48.h"
-
-unsigned short _rand48_seed[3] = {
-	RAND48_SEED_0,
-	RAND48_SEED_1,
-	RAND48_SEED_2
-};
-unsigned short _rand48_mult[3] = {
-	RAND48_MULT_0,
-	RAND48_MULT_1,
-	RAND48_MULT_2
-};
-unsigned short _rand48_add = RAND48_ADD;
-
-void
-_dorand48(unsigned short xseed[3])
-{
-	unsigned long accu;
-	unsigned short temp[2];
-
-	accu = (unsigned long) _rand48_mult[0] * (unsigned long) xseed[0] +
-	 (unsigned long) _rand48_add;
-	temp[0] = (unsigned short) accu;	/* lower 16 bits */
-	accu >>= sizeof(unsigned short) * 8;
-	accu += (unsigned long) _rand48_mult[0] * (unsigned long) xseed[1] +
-	 (unsigned long) _rand48_mult[1] * (unsigned long) xseed[0];
-	temp[1] = (unsigned short) accu;	/* middle 16 bits */
-	accu >>= sizeof(unsigned short) * 8;
-	accu += _rand48_mult[0] * xseed[2] + _rand48_mult[1] * xseed[1] + _rand48_mult[2] * xseed[0];
-	xseed[0] = temp[0];
-	xseed[1] = temp[1];
-	xseed[2] = (unsigned short) accu;
-}
diff --git a/libc/bionic/dlmalloc.c b/libc/bionic/dlmalloc.c
index 19fbb75..8c75e9c 100644
--- a/libc/bionic/dlmalloc.c
+++ b/libc/bionic/dlmalloc.c
@@ -2265,13 +2265,53 @@
 
 #else /* PROCEED_ON_ERROR */
 
-#ifndef CORRUPTION_ERROR_ACTION
-#define CORRUPTION_ERROR_ACTION(m) ABORT
-#endif /* CORRUPTION_ERROR_ACTION */
+/* The following Android-specific code is used to print an informative
+ * fatal error message to the log when we detect that a heap corruption
+ * was detected. We need to be careful about not using a log function
+ * that may require an allocation here!
+ */
+#ifdef LOG_ON_HEAP_ERROR
 
-#ifndef USAGE_ERROR_ACTION
-#define USAGE_ERROR_ACTION(m,p) ABORT
-#endif /* USAGE_ERROR_ACTION */
+#  include <private/logd.h>
+
+static void __bionic_heap_error(const char* msg, const char* function)
+{
+    /* We format the buffer explicitely, i.e. without using snprintf()
+     * which may use malloc() internally. Not something we can trust
+     * if we just detected a corrupted heap.
+     */
+    char buffer[256];
+    strlcpy(buffer, "@@@ ABORTING: ", sizeof(buffer));
+    strlcat(buffer, msg, sizeof(buffer));
+    if (function != NULL) {
+        strlcat(buffer, " IN ", sizeof(buffer));
+        strlcat(buffer, function, sizeof(buffer));
+    }
+    __libc_android_log_write(ANDROID_LOG_FATAL,"libc",buffer);
+    abort();
+}
+
+#  ifndef CORRUPTION_ERROR_ACTION
+#    define CORRUPTION_ERROR_ACTION(m)  \
+    __bionic_heap_error("HEAP MEMORY CORRUPTION", __FUNCTION__)
+#  endif
+#  ifndef USAGE_ERROR_ACTION
+#    define USAGE_ERROR_ACTION(m,p)   \
+    __bionic_heap_error("INVALID HEAP ADDRESS", __FUNCTION__)
+#  endif
+
+#else /* !LOG_ON_HEAP_ERROR */
+
+#  ifndef CORRUPTION_ERROR_ACTION
+#    define CORRUPTION_ERROR_ACTION(m) ABORT
+#  endif /* CORRUPTION_ERROR_ACTION */
+
+#  ifndef USAGE_ERROR_ACTION
+#    define USAGE_ERROR_ACTION(m,p) ABORT
+#  endif /* USAGE_ERROR_ACTION */
+
+#endif /* !LOG_ON_HEAP_ERROR */
+
 
 #endif /* PROCEED_ON_ERROR */
 
diff --git a/libc/bionic/drand48.c b/libc/bionic/drand48.c
index fd48196..93272cf 100644
--- a/libc/bionic/drand48.c
+++ b/libc/bionic/drand48.c
@@ -15,10 +15,10 @@
 
 #include "rand48.h"
 
-extern unsigned short _rand48_seed[3];
+extern unsigned short __rand48_seed[3];
 
 double
 drand48(void)
 {
-	return erand48(_rand48_seed);
+	return erand48(__rand48_seed);
 }
diff --git a/libc/bionic/erand48.c b/libc/bionic/erand48.c
index 843ff34..4ecbead 100644
--- a/libc/bionic/erand48.c
+++ b/libc/bionic/erand48.c
@@ -18,7 +18,7 @@
 double
 erand48(unsigned short xseed[3])
 {
-	_dorand48(xseed);
+	__dorand48(xseed);
 	return ldexp((double) xseed[0], -48) +
 	       ldexp((double) xseed[1], -32) +
 	       ldexp((double) xseed[2], -16);
diff --git a/libc/bionic/fork.c b/libc/bionic/fork.c
index 79b8fff..0eedb01 100644
--- a/libc/bionic/fork.c
+++ b/libc/bionic/fork.c
@@ -41,9 +41,12 @@
      * of error, or in the parent process
      */
     __timer_table_start_stop(1);
+    __bionic_atfork_run_prepare();
+
     ret = __fork();
     if (ret != 0) {  /* not a child process */
         __timer_table_start_stop(0);
+        __bionic_atfork_run_parent();
     } else {
         /*
          * Newly created process must update cpu accounting.
@@ -52,6 +55,7 @@
          * as a parameter.
          */
         cpuacct_add(getuid());
+        __bionic_atfork_run_child();
     }
     return ret;
 }
diff --git a/libc/bionic/libc_init_common.c b/libc/bionic/libc_init_common.c
index f7579bd..b6a6379 100644
--- a/libc/bionic/libc_init_common.c
+++ b/libc/bionic/libc_init_common.c
@@ -62,7 +62,7 @@
     static pthread_internal_t  thread;
     static void*               tls_area[BIONIC_TLS_SLOTS];
 
-    /* setup pthread runtime and maint thread descriptor */
+    /* setup pthread runtime and main thread descriptor */
     unsigned stacktop = (__get_sp() & ~(PAGE_SIZE - 1)) + PAGE_SIZE;
     unsigned stacksize = 128 * 1024;
     unsigned stackbottom = stacktop - stacksize;
diff --git a/libc/bionic/libc_init_dynamic.c b/libc/bionic/libc_init_dynamic.c
index f64b6f2..4bb2a81 100644
--- a/libc/bionic/libc_init_dynamic.c
+++ b/libc/bionic/libc_init_dynamic.c
@@ -61,7 +61,7 @@
 
 void __libc_preinit(void)
 {
-    /* Read the ELF data pointer form a special slot of the
+    /* Read the ELF data pointer from a special slot of the
      * TLS area, then call __libc_init_common with it.
      *
      * Note that:
diff --git a/libc/bionic/logd_write.c b/libc/bionic/logd_write.c
index 63dfd59..2bc39fa 100644
--- a/libc/bionic/logd_write.c
+++ b/libc/bionic/logd_write.c
@@ -48,6 +48,16 @@
 
 #include <pthread.h>
 
+/* IMPORTANT IMPORTANT IMPORTANT: TECHNICAL NOTE
+ *
+ * Some of the functions below can be called when our malloc() implementation
+ * has detected that the heap is corrupted, or even from a signal handler.
+ *
+ * These functions should *not* use a function that allocates heap memory
+ * or is not signal-safe. Using direct system calls is acceptable, and we
+ * also assume that pthread_mutex_lock/unlock can be used too.
+ */
+
 #define LOG_BUF_SIZE    1024
 
 typedef enum {
@@ -77,9 +87,10 @@
     { __write_to_log_init, -1, "/dev/"LOGGER_LOG_RADIO }
 };
 
+/* Important: see technical note at start of source file */
 static int __write_to_log_null(log_id_t log_id, struct iovec *vec)
 {
-    /* 
+    /*
      * ALTERED behaviour from previous version
      * always returns successful result
      */
@@ -97,23 +108,21 @@
  *  it's supposed, that log_id contains valid id always.
  *  this check must be performed in higher level functions
  */
+/* Important: see technical note at start of source file */
 static int __write_to_log_kernel(log_id_t log_id, struct iovec *vec)
 {
-    ssize_t ret;
-
-    do {
-        ret = writev(log_channels[log_id].fd, vec, 3);
-    } while ((ret < 0) && (errno == EINTR));
-
-    return ret;
+    return TEMP_FAILURE_RETRY( writev(log_channels[log_id].fd, vec, 3) );
 }
 
+/* Important: see technical note at start of source file */
 static int __write_to_log_init(log_id_t log_id, struct iovec *vec)
 {
     if ((LOG_ID_NONE < log_id) && (log_id < LOG_ID_MAX)) {
+        int fd;
+
         pthread_mutex_lock(&log_init_lock);
 
-        int fd = open(log_channels[log_id].path, O_WRONLY);
+        fd = TEMP_FAILURE_RETRY(open(log_channels[log_id].path, O_WRONLY));
 
         log_channels[log_id].logger =
             (fd < 0) ? __write_to_log_null : __write_to_log_kernel;
@@ -130,7 +139,9 @@
     return -1;
 }
 
-static int __android_log_write(int prio, const char *tag, const char *msg)
+/* Important: see technical note at start of source file */
+__LIBC_HIDDEN__
+int __libc_android_log_write(int prio, const char *tag, const char *msg)
 {
     struct iovec vec[3];
     log_id_t log_id = LOG_ID_MAIN;
@@ -151,7 +162,11 @@
     return log_channels[log_id].logger(log_id, vec);
 }
 
-
+/* The functions below are not designed to be called from a heap panic
+ * function or from a signal handler. As such, they are free to use complex
+ * C library functions like vsnprintf()
+ */
+__LIBC_HIDDEN__
 int __libc_android_log_vprint(int prio, const char *tag, const char *fmt,
                               va_list ap)
 {
@@ -159,9 +174,10 @@
 
     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
 
-    return __android_log_write(prio, tag, buf);
+    return __libc_android_log_write(prio, tag, buf);
 }
 
+__LIBC_HIDDEN__
 int __libc_android_log_print(int prio, const char *tag, const char *fmt, ...)
 {
     va_list ap;
@@ -171,20 +187,21 @@
     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
     va_end(ap);
 
-    return __android_log_write(prio, tag, buf);
+    return __libc_android_log_write(prio, tag, buf);
 }
 
+__LIBC_HIDDEN__
 int __libc_android_log_assert(const char *cond, const char *tag,
 			      const char *fmt, ...)
 {
     va_list ap;
-    char buf[LOG_BUF_SIZE];    
+    char buf[LOG_BUF_SIZE];
 
     va_start(ap, fmt);
     vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
     va_end(ap);
 
-    __android_log_write(ANDROID_LOG_FATAL, tag, buf);
+    __libc_android_log_write(ANDROID_LOG_FATAL, tag, buf);
 
     exit(1);
 
diff --git a/libc/bionic/malloc_debug_common.c b/libc/bionic/malloc_debug_common.c
index f05576c..b9fcbc4 100644
--- a/libc/bionic/malloc_debug_common.c
+++ b/libc/bionic/malloc_debug_common.c
@@ -84,7 +84,6 @@
         //
         // This is used for sorting, not determination of equality, so we don't
         // need to compare the bit flags.
-        int result;
         if (alloc1 > alloc2) {
             result = -1;
         } else if (alloc1 < alloc2) {
@@ -120,6 +119,7 @@
             totalMemory == NULL || backtraceSize == NULL) {
         return;
     }
+    *totalMemory = 0;
 
     pthread_mutex_lock(&gAllocationsMutex);
 
@@ -127,7 +127,6 @@
         *info = NULL;
         *overallSize = 0;
         *infoSize = 0;
-        *totalMemory = 0;
         *backtraceSize = 0;
         goto done;
     }
diff --git a/libc/bionic/md5.c b/libc/bionic/md5.c
index 087786f..16674f1 100644
--- a/libc/bionic/md5.c
+++ b/libc/bionic/md5.c
@@ -38,6 +38,7 @@
         "$NetBSD: md5.c,v 1.1.1.4 2002/09/12 12:41:42 joda Exp $");
 #endif
 
+#include <endian.h>
 #include "md5.h"
 #include "hash.h"
 
@@ -178,8 +179,11 @@
 /*
  * From `Performance analysis of MD5' by Joseph D. Touch <touch@isi.edu>
  */
+#if !defined(__BYTE_ORDER) || !defined (__BIG_ENDIAN)
+#error __BYTE_ORDER macros not defined
+#endif
 
-#if defined(WORDS_BIGENDIAN)
+#if __BYTE_ORDER == __BIG_ENDIAN
 static inline u_int32_t
 swap_u_int32_t (u_int32_t t)
 {
@@ -217,7 +221,7 @@
     p += l;
     len -= l;
     if(offset == 64){
-#if defined(WORDS_BIGENDIAN)
+#if __BYTE_ORDER == __BIG_ENDIAN
       int i;
       u_int32_t current[16];
       struct x32 *u = (struct x32*)m->save;
diff --git a/libc/bionic/pthread-atfork.c b/libc/bionic/pthread-atfork.c
new file mode 100644
index 0000000..3a5189d
--- /dev/null
+++ b/libc/bionic/pthread-atfork.c
@@ -0,0 +1,123 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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 <stdlib.h>
+#include <errno.h>
+#include <pthread.h>
+#include <sys/queue.h>
+
+static pthread_mutex_t handler_mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+
+struct atfork_t
+{
+    CIRCLEQ_ENTRY(atfork_t) entries;
+
+    void (*prepare)(void);
+    void (*child)(void);
+    void (*parent)(void);
+};
+static CIRCLEQ_HEAD(atfork_head_t, atfork_t) atfork_head = \
+    CIRCLEQ_HEAD_INITIALIZER(atfork_head);
+
+void __bionic_atfork_run_prepare()
+{
+    struct atfork_t *cursor;
+
+    /* We will lock this here, and unlock it in the parent and child functions.
+     * This ensures that nobody can modify the handler array between the calls
+     * to the prepare and parent/child handlers.
+     *
+     * TODO: If a handler mucks with the list, it could cause problems.  Right
+     *       now it's ok because all they can do is add new items to the end
+     *       of the list, but if/when we implement cleanup in dlclose() things
+     *       will get more interesting...
+     */
+    pthread_mutex_lock(&handler_mutex);
+
+    /* Call pthread_atfork() prepare handlers.  Posix states that the prepare
+     * handlers should be called in the reverse order of the parent/child
+     * handlers, so we iterate backwards.
+     */
+    for (cursor = atfork_head.cqh_last;
+         cursor != (void*)&atfork_head;
+         cursor = cursor->entries.cqe_prev) {
+        if (cursor->prepare != NULL) {
+            cursor->prepare();
+        }
+    }
+}
+
+void __bionic_atfork_run_child()
+{
+    struct atfork_t *cursor;
+
+    /* Call pthread_atfork() child handlers */
+    for (cursor = atfork_head.cqh_first;
+         cursor != (void*)&atfork_head;
+         cursor = cursor->entries.cqe_next) {
+        if (cursor->child != NULL) {
+            cursor->child();
+        }
+    }
+
+    pthread_mutex_unlock(&handler_mutex);
+}
+
+void __bionic_atfork_run_parent()
+{
+    struct atfork_t *cursor;
+
+    /* Call pthread_atfork() parent handlers */
+    for (cursor = atfork_head.cqh_first;
+         cursor != (void*)&atfork_head;
+         cursor = cursor->entries.cqe_next) {
+        if (cursor->parent != NULL) {
+            cursor->parent();
+        }
+    }
+
+    pthread_mutex_unlock(&handler_mutex);
+}
+
+int pthread_atfork(void (*prepare)(void), void (*parent)(void), void(*child)(void))
+{
+    struct atfork_t *entry = malloc(sizeof(struct atfork_t));
+
+    if (entry == NULL) {
+        return ENOMEM;
+    }
+
+    entry->prepare = prepare;
+    entry->parent = parent;
+    entry->child = child;
+
+    pthread_mutex_lock(&handler_mutex);
+    CIRCLEQ_INSERT_TAIL(&atfork_head, entry, entries);
+    pthread_mutex_unlock(&handler_mutex);
+
+    return 0;
+}
diff --git a/libc/bionic/pthread-timers.c b/libc/bionic/pthread-timers.c
index 7b9c99e..ae04029 100644
--- a/libc/bionic/pthread-timers.c
+++ b/libc/bionic/pthread-timers.c
@@ -260,7 +260,7 @@
  ** requirements: the timers of fork child processes must be
  ** disarmed but not deleted.
  **/
-void
+__LIBC_HIDDEN__ void
 __timer_table_start_stop( int  stop )
 {
     if (__timer_table != NULL) {
diff --git a/libc/bionic/pthread.c b/libc/bionic/pthread.c
index 180914e..0a0854d 100644
--- a/libc/bionic/pthread.c
+++ b/libc/bionic/pthread.c
@@ -202,6 +202,9 @@
 
     // Wait for our creating thread to release us. This lets it have time to
     // notify gdb about this thread before it starts doing anything.
+    //
+    // This also provides the memory barrier needed to ensure that all memory
+    // accesses previously made by the creating thread are visible to us.
     pthread_mutex_t * start_mutex = (pthread_mutex_t *)&tls[TLS_SLOT_SELF];
     pthread_mutex_lock(start_mutex);
     pthread_mutex_destroy(start_mutex);
@@ -270,7 +273,7 @@
 }
 
 /*
- * Create a new thread. The thread's stack is layed out like so:
+ * Create a new thread. The thread's stack is laid out like so:
  *
  * +---------------------------+
  * |     pthread_internal_t    |
@@ -340,6 +343,10 @@
 
     // Create a mutex for the thread in TLS_SLOT_SELF to wait on once it starts so we can keep
     // it from doing anything until after we notify the debugger about it
+    //
+    // This also provides the memory barrier we need to ensure that all
+    // memory accesses previously performed by this thread are visible to
+    // the new thread.
     start_mutex = (pthread_mutex_t *) &tls[TLS_SLOT_SELF];
     pthread_mutex_init(start_mutex, NULL);
     pthread_mutex_lock(start_mutex);
@@ -1427,6 +1434,18 @@
             break;
     }
 
+    /*
+     * Ensure that all memory accesses previously made by this thread are
+     * visible to the woken thread(s).  On the other side, the "wait"
+     * code will issue any necessary barriers when locking the mutex.
+     *
+     * This may not strictly be necessary -- if the caller follows
+     * recommended practice and holds the mutex before signaling the cond
+     * var, the mutex ops will provide correct semantics.  If they don't
+     * hold the mutex, they're subject to race conditions anyway.
+     */
+    ANDROID_MEMBAR_FULL();
+
     __futex_wake_ex(&cond->value, COND_IS_SHARED(cond), counter);
     return 0;
 }
@@ -1845,7 +1864,13 @@
      */
     int ret, old_errno = errno;
 
-    ret = __rt_sigprocmask(how, set, oset, _NSIG / 8);
+    /* Use NSIG which corresponds to the number of signals in
+     * our 32-bit sigset_t implementation. As such, this function, or
+     * anything that deals with sigset_t cannot manage real-time signals
+     * (signo >= 32). We might want to introduce sigset_rt_t as an
+     * extension to do so in the future.
+     */
+    ret = __rt_sigprocmask(how, set, oset, NSIG / 8);
     if (ret < 0)
         ret = errno;
 
@@ -1873,12 +1898,16 @@
 int  pthread_once( pthread_once_t*  once_control,  void (*init_routine)(void) )
 {
     static pthread_mutex_t   once_lock = PTHREAD_RECURSIVE_MUTEX_INITIALIZER;
+    volatile pthread_once_t* ocptr = once_control;
 
-    if (*once_control == PTHREAD_ONCE_INIT) {
+    pthread_once_t tmp = *ocptr;
+    ANDROID_MEMBAR_FULL();
+    if (tmp == PTHREAD_ONCE_INIT) {
         pthread_mutex_lock( &once_lock );
-        if (*once_control == PTHREAD_ONCE_INIT) {
+        if (*ocptr == PTHREAD_ONCE_INIT) {
             (*init_routine)();
-            *once_control = ~PTHREAD_ONCE_INIT;
+            ANDROID_MEMBAR_FULL();
+            *ocptr = ~PTHREAD_ONCE_INIT;
         }
         pthread_mutex_unlock( &once_lock );
     }
diff --git a/libc/bionic/pthread_internal.h b/libc/bionic/pthread_internal.h
index eb4e80c..655b8f3 100644
--- a/libc/bionic/pthread_internal.h
+++ b/libc/bionic/pthread_internal.h
@@ -109,6 +109,9 @@
 
 /* needed by fork.c */
 extern void __timer_table_start_stop(int  stop);
+extern void __bionic_atfork_run_prepare();
+extern void __bionic_atfork_run_child();
+extern void __bionic_atfork_run_parent();
 
 __END_DECLS
 
diff --git a/libc/bionic/rand48.h b/libc/bionic/rand48.h
deleted file mode 100644
index 0a3d83d..0000000
--- a/libc/bionic/rand48.h
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * Copyright (c) 1993 Martin Birgmeier
- * All rights reserved.
- *
- * You may redistribute unmodified or modified versions of this source
- * code provided that the above copyright notice and this and the
- * following conditions are retained.
- *
- * This software is provided ``as is'', and comes with no warranties
- * of any kind. I shall in no event be liable for anything that happens
- * to anyone/anything when using this software.
- *
- * $FreeBSD: src/lib/libc/gen/rand48.h,v 1.2 2002/02/01 01:32:19 obrien Exp $
- */
-
-#ifndef _RAND48_H_
-#define _RAND48_H_
-
-#include <math.h>
-#include <stdlib.h>
-
-void		_dorand48(unsigned short[3]);
-
-#define	RAND48_SEED_0	(0x330e)
-#define	RAND48_SEED_1	(0xabcd)
-#define	RAND48_SEED_2	(0x1234)
-#define	RAND48_MULT_0	(0xe66d)
-#define	RAND48_MULT_1	(0xdeec)
-#define	RAND48_MULT_2	(0x0005)
-#define	RAND48_ADD	(0x000b)
-
-#endif /* _RAND48_H_ */
diff --git a/libc/bionic/realpath.c b/libc/bionic/realpath.c
index 274a3a0..4cb847b 100644
--- a/libc/bionic/realpath.c
+++ b/libc/bionic/realpath.c
@@ -1,9 +1,6 @@
+/*	$OpenBSD: realpath.c,v 1.13 2005/08/08 08:05:37 espie Exp $ */
 /*
- * Copyright (c) 1994
- *	The Regents of the University of California.  All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Jan-Simon Pendry.
+ * Copyright (c) 2003 Constantin S. Svintsoff <kostik@iclub.nsu.ru>
  *
  * Redistribution and use in source and binary forms, with or without
  * modification, are permitted provided that the following conditions
@@ -13,18 +10,14 @@
  * 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. All advertising materials mentioning features or use of this software
- *    must display the following acknowledgement:
- *	This product includes software developed by the University of
- *	California, Berkeley and its contributors.
- * 4. 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.
+ * 3. The names of the authors may not 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
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR 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)
@@ -34,133 +27,164 @@
  * SUCH DAMAGE.
  */
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)realpath.c	8.1 (Berkeley) 2/16/94";
-static char rcsid[] =
-"$FreeBSD: /repoman/r/ncvs/src/lib/libc/stdlib/realpath.c,v 1.6.2.1 2003/08/03 23:47:39 nectar Exp $";
-#endif /* LIBC_SCCS and not lint */
-
 #include <sys/param.h>
 #include <sys/stat.h>
 
 #include <errno.h>
-#include <fcntl.h>
 #include <stdlib.h>
 #include <string.h>
 #include <unistd.h>
 
 /*
- * char *realpath(const char *path, char resolved_path[MAXPATHLEN]);
+ * char *realpath(const char *path, char resolved[PATH_MAX]);
  *
  * Find the real name of path, by removing all ".", ".." and symlink
  * components.  Returns (resolved) on success, or (NULL) on failure,
  * in which case the path which caused trouble is left in (resolved).
  */
 char *
-realpath(path, resolved)
-	const char *path;
-	char *resolved;
+realpath(const char *path, char resolved[PATH_MAX])
 {
 	struct stat sb;
-	int fd, n, rootd, serrno;
-	char *p, *q, wbuf[MAXPATHLEN];
-      int symlinks = 0;
+	char *p, *q, *s;
+	size_t left_len, resolved_len;
+	unsigned symlinks;
+	int serrno, slen;
+	char left[PATH_MAX], next_token[PATH_MAX], symlink[PATH_MAX];
 
-	/* Save the starting point. */
-	if ((fd = open(".", O_RDONLY)) < 0) {
-		(void)strcpy(resolved, ".");
+	serrno = errno;
+	symlinks = 0;
+	if (path[0] == '/') {
+		resolved[0] = '/';
+		resolved[1] = '\0';
+		if (path[1] == '\0')
+			return (resolved);
+		resolved_len = 1;
+		left_len = strlcpy(left, path + 1, sizeof(left));
+	} else {
+		if (getcwd(resolved, PATH_MAX) == NULL) {
+			strlcpy(resolved, ".", PATH_MAX);
+			return (NULL);
+		}
+		resolved_len = strlen(resolved);
+		left_len = strlcpy(left, path, sizeof(left));
+	}
+	if (left_len >= sizeof(left) || resolved_len >= PATH_MAX) {
+		errno = ENAMETOOLONG;
 		return (NULL);
 	}
 
 	/*
-	 * Find the dirname and basename from the path to be resolved.
-	 * Change directory to the dirname component.
-	 * lstat the basename part.
-	 *     if it is a symlink, read in the value and loop.
-	 *     if it is a directory, then change to that directory.
-	 * get the current directory name and append the basename.
+	 * Iterate over path components in `left'.
 	 */
-	(void)strncpy(resolved, path, MAXPATHLEN - 1);
-	resolved[MAXPATHLEN - 1] = '\0';
-loop:
-	q = strrchr(resolved, '/');
-	if (q != NULL) {
-		p = q + 1;
-		if (q == resolved)
-			q = "/";
-		else {
-			do {
-				--q;
-			} while (q > resolved && *q == '/');
-			q[1] = '\0';
-			q = resolved;
-		}
-		if (chdir(q) < 0)
-			goto err1;
-	} else
-		p = resolved;
-
-	/* Deal with the last component. */
-	if (*p != '\0' && lstat(p, &sb) == 0) {
-		if (S_ISLNK(sb.st_mode)) {
-                      if (++symlinks > MAXSYMLINKS) {
-                              errno = ELOOP;
-                              goto err1;
-                      }
-			n = readlink(p, resolved, MAXPATHLEN - 1);
-			if (n < 0)
-				goto err1;
-			resolved[n] = '\0';
-			goto loop;
-		}
-		if (S_ISDIR(sb.st_mode)) {
-			if (chdir(p) < 0)
-				goto err1;
-			p = "";
-		}
-	}
-
-	/*
-	 * Save the last component name and get the full pathname of
-	 * the current directory.
-	 */
-	(void)strcpy(wbuf, p);
-	if (getcwd(resolved, MAXPATHLEN) == 0)
-		goto err1;
-
-	/*
-	 * Join the two strings together, ensuring that the right thing
-	 * happens if the last component is empty, or the dirname is root.
-	 */
-	if (resolved[0] == '/' && resolved[1] == '\0')
-		rootd = 1;
-	else
-		rootd = 0;
-
-	if (*wbuf) {
-		if (strlen(resolved) + strlen(wbuf) + (1-rootd) + 1 >
-		    MAXPATHLEN) {
+	while (left_len != 0) {
+		/*
+		 * Extract the next path component and adjust `left'
+		 * and its length.
+		 */
+		p = strchr(left, '/');
+		s = p ? p : left + left_len;
+		if (s - left >= sizeof(next_token)) {
 			errno = ENAMETOOLONG;
-			goto err1;
+			return (NULL);
 		}
-		if (rootd == 0)
-			(void)strcat(resolved, "/");
-		(void)strcat(resolved, wbuf);
+		memcpy(next_token, left, s - left);
+		next_token[s - left] = '\0';
+		left_len -= s - left;
+		if (p != NULL)
+			memmove(left, s + 1, left_len + 1);
+		if (resolved[resolved_len - 1] != '/') {
+			if (resolved_len + 1 >= PATH_MAX) {
+				errno = ENAMETOOLONG;
+				return (NULL);
+			}
+			resolved[resolved_len++] = '/';
+			resolved[resolved_len] = '\0';
+		}
+		if (next_token[0] == '\0')
+			continue;
+		else if (strcmp(next_token, ".") == 0)
+			continue;
+		else if (strcmp(next_token, "..") == 0) {
+			/*
+			 * Strip the last path component except when we have
+			 * single "/"
+			 */
+			if (resolved_len > 1) {
+				resolved[resolved_len - 1] = '\0';
+				q = strrchr(resolved, '/') + 1;
+				*q = '\0';
+				resolved_len = q - resolved;
+			}
+			continue;
+		}
+
+		/*
+		 * Append the next path component and lstat() it. If
+		 * lstat() fails we still can return successfully if
+		 * there are no more path components left.
+		 */
+		resolved_len = strlcat(resolved, next_token, PATH_MAX);
+		if (resolved_len >= PATH_MAX) {
+			errno = ENAMETOOLONG;
+			return (NULL);
+		}
+		if (lstat(resolved, &sb) != 0) {
+			if (errno == ENOENT && p == NULL) {
+				errno = serrno;
+				return (resolved);
+			}
+			return (NULL);
+		}
+		if (S_ISLNK(sb.st_mode)) {
+			if (symlinks++ > MAXSYMLINKS) {
+				errno = ELOOP;
+				return (NULL);
+			}
+			slen = readlink(resolved, symlink, sizeof(symlink) - 1);
+			if (slen < 0)
+				return (NULL);
+			symlink[slen] = '\0';
+			if (symlink[0] == '/') {
+				resolved[1] = 0;
+				resolved_len = 1;
+			} else if (resolved_len > 1) {
+				/* Strip the last path component. */
+				resolved[resolved_len - 1] = '\0';
+				q = strrchr(resolved, '/') + 1;
+				*q = '\0';
+				resolved_len = q - resolved;
+			}
+
+			/*
+			 * If there are any path components left, then
+			 * append them to symlink. The result is placed
+			 * in `left'.
+			 */
+			if (p != NULL) {
+				if (symlink[slen - 1] != '/') {
+					if (slen + 1 >= sizeof(symlink)) {
+						errno = ENAMETOOLONG;
+						return (NULL);
+					}
+					symlink[slen] = '/';
+					symlink[slen + 1] = 0;
+				}
+				left_len = strlcat(symlink, left, sizeof(left));
+				if (left_len >= sizeof(left)) {
+					errno = ENAMETOOLONG;
+					return (NULL);
+				}
+			}
+			left_len = strlcpy(left, symlink, sizeof(left));
+		}
 	}
 
-	/* Go back to where we came from. */
-	if (fchdir(fd) < 0) {
-		serrno = errno;
-		goto err2;
-	}
-
-	/* It's okay if the close fails, what's an fd more or less? */
-	(void)close(fd);
+	/*
+	 * Remove trailing slash except when the resolved pathname
+	 * is a single "/".
+	 */
+	if (resolved_len > 1 && resolved[resolved_len - 1] == '/')
+		resolved[resolved_len - 1] = '\0';
 	return (resolved);
-
-err1:	serrno = errno;
-	(void)fchdir(fd);
-err2:	(void)close(fd);
-	errno = serrno;
-	return (NULL);
 }
diff --git a/libc/bionic/sched_cpualloc.c b/libc/bionic/sched_cpualloc.c
new file mode 100644
index 0000000..30964bc
--- /dev/null
+++ b/libc/bionic/sched_cpualloc.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ */
+#define _GNU_SOURCE 1
+#include <sched.h>
+#include <stdlib.h>
+
+cpu_set_t* __sched_cpualloc(size_t count)
+{
+    return (cpu_set_t*) malloc(CPU_ALLOC_SIZE(count));
+}
+
+void __sched_cpufree(cpu_set_t* set)
+{
+    free(set);
+}
diff --git a/libc/bionic/sched_cpucount.c b/libc/bionic/sched_cpucount.c
new file mode 100644
index 0000000..9458dc8
--- /dev/null
+++ b/libc/bionic/sched_cpucount.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ */
+#define _GNU_SOURCE 1
+#include <sched.h>
+
+int __sched_cpucount(size_t setsize, cpu_set_t* set)
+{
+    int nn = 0, nn_max = setsize / sizeof(__CPU_BITTYPE);
+    int count = 0;
+
+    for ( ; nn < nn_max; nn++ )
+        count += __builtin_popcount(set->__bits[nn]);
+
+    return count;
+}
diff --git a/libc/bionic/sched_getaffinity.c b/libc/bionic/sched_getaffinity.c
new file mode 100644
index 0000000..7313822
--- /dev/null
+++ b/libc/bionic/sched_getaffinity.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ */
+#define _GNU_SOURCE 1
+#include <sched.h>
+
+int  sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set)
+{
+    int ret = __sched_getaffinity(pid, setsize, set);
+    if (ret >= 0) {
+        if ((size_t)ret < setsize) {
+            memset((char*)set + ret, '\0', setsize - (size_t)ret);
+        }
+        ret = 0;
+    }
+    return ret;
+}
diff --git a/libc/bionic/sched_getcpu.c b/libc/bionic/sched_getcpu.c
new file mode 100644
index 0000000..954df37
--- /dev/null
+++ b/libc/bionic/sched_getcpu.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ */
+#define _GNU_SOURCE 1
+#include <sched.h>
+
+extern int  __getcpu(unsigned *cpu, unsigned *node, void* unused);
+
+int  sched_getcpu(void)
+{
+    unsigned cpu;
+    if (__getcpu(&cpu, NULL, NULL) < 0)
+        return 0;
+
+    return (int)cpu;
+}
diff --git a/libc/bionic/stubs.c b/libc/bionic/stubs.c
index d495674..a01d64c 100644
--- a/libc/bionic/stubs.c
+++ b/libc/bionic/stubs.c
@@ -40,8 +40,8 @@
 /** Thread-specific state for the stubs functions
  **/
 
-pthread_once_t   the_once = PTHREAD_ONCE_INIT;
-pthread_key_t    the_key;
+static pthread_once_t   the_once = PTHREAD_ONCE_INIT;
+static pthread_key_t    the_key;
 
 typedef struct {
     struct passwd  passwd;
diff --git a/libc/bionic/time64.c b/libc/bionic/time64.c
index 1e1f881..9aa5d4f 100644
--- a/libc/bionic/time64.c
+++ b/libc/bionic/time64.c
@@ -364,7 +364,7 @@
 }
 
 
-void copy_tm_to_TM(const struct tm *src, struct TM *dest) {
+static void copy_tm_to_TM(const struct tm *src, struct TM *dest) {
     if( src == NULL ) {
         memset(dest, 0, sizeof(*dest));
     }
@@ -396,7 +396,7 @@
 }
 
 
-void copy_TM_to_tm(const struct TM *src, struct tm *dest) {
+static void copy_TM_to_tm(const struct TM *src, struct tm *dest) {
     if( src == NULL ) {
         memset(dest, 0, sizeof(*dest));
     }
@@ -735,14 +735,14 @@
 }
 
 
-int valid_tm_wday( const struct TM* date ) {
+static int valid_tm_wday( const struct TM* date ) {
     if( 0 <= date->tm_wday && date->tm_wday <= 6 )
         return 1;
     else
         return 0;
 }
 
-int valid_tm_mon( const struct TM* date ) {
+static int valid_tm_mon( const struct TM* date ) {
     if( 0 <= date->tm_mon && date->tm_mon <= 11 )
         return 1;
     else
diff --git a/libc/bionic/time64_config.h b/libc/bionic/time64_config.h
index 53bcecf..1385045 100644
--- a/libc/bionic/time64_config.h
+++ b/libc/bionic/time64_config.h
@@ -33,7 +33,7 @@
 */
 #define HAS_GMTIME_R
 #define HAS_LOCALTIME_R
-/*#define HAS_TIMEGM */
+#define HAS_TIMEGM
 
 
 /* Details of non-standard tm struct elements.
diff --git a/libc/docs/CHANGES.TXT b/libc/docs/CHANGES.TXT
index 4d094d0..98b7fcf 100644
--- a/libc/docs/CHANGES.TXT
+++ b/libc/docs/CHANGES.TXT
@@ -1,7 +1,26 @@
 Bionic ChangeLog:
 -----------------
 
-Differences between current and Android 2.2:
+Differences between current and Android 2.3:
+
+- <android/api-level.h>: Added new header to define __ANDROID_API__ to
+  a constant integer corresponding to the native API level. This header
+  also exists in the NDK's platform headers.
+
+- <sys/cdefs.h>: Include <android/api-level.h>
+
+- <time.h>: Add timegm(), timelocal(), time2posix() and posix2time()
+
+- <sched.h>: Add sched_getcpu(), sched_getaffinity(), sched_setaffinity(),
+  cpu_set_t and related macros (e.g. CPU_SETSIZE, CPU_ZERO, CPU_SET, ...)
+
+- <unistd.h>: Add ftruncate64().
+
+- <signal.h>: Changed the definition of SIGRTMAX to 64. However, note that
+  sigset_t is only 32-bit and cannot deal with real-time signals.
+
+-------------------------------------------------------------------------------
+Differences between Android 2.3 and Android 2.2:
 
 - <pthread.h>: Add reader/writer locks implementation. Add sanity
   checking to pthread_mutex_destroy() (e.g. a locked mutex will return
@@ -70,6 +89,8 @@
 - <sys/vfs.h>: fixed implementation of fstatfs() (also fixes fpathconf()
   which uses it).
 
+- Added an implementation of pthread_atfork()
+
 - <dlfcn.h>: fixed dlopen() implementation to support dlopen(NULL, ...).
   This allows one to look at the dynamic symbols exported by an executable.
 
diff --git a/libc/include/android/api-level.h b/libc/include/android/api-level.h
new file mode 100644
index 0000000..611fdfb
--- /dev/null
+++ b/libc/include/android/api-level.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2008 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ */
+#ifndef ANDROID_API_LEVEL_H
+#define ANDROID_API_LEVEL_H
+
+#define __ANDROID_API__ 10
+
+#endif /* ANDROID_API_LEVEL_H */
diff --git a/libc/include/byteswap.h b/libc/include/byteswap.h
index 16d2ad4..74b0e91 100644
--- a/libc/include/byteswap.h
+++ b/libc/include/byteswap.h
@@ -28,7 +28,8 @@
 #ifndef _BYTESWAP_H_
 #define _BYTESWAP_H_
 
-#include <sys/endian.h>
+/* endian.h rather than sys/endian.h so we get the machine-specific file. */
+#include <endian.h>
 
 #define  bswap_16(x)   swap16(x)
 #define  bswap_32(x)   swap32(x)
diff --git a/libc/include/net/if_ether.h b/libc/include/net/if_ether.h
index 121f9ac..8daa16b 100644
--- a/libc/include/net/if_ether.h
+++ b/libc/include/net/if_ether.h
@@ -34,6 +34,8 @@
 #ifndef _NET_IF_ETHER_H_
 #define _NET_IF_ETHER_H_
 
+#include <sys/types.h>
+
 #ifdef _KERNEL
 #ifdef _KERNEL_OPT
 #include "opt_mbuftrace.h"
diff --git a/libc/include/netdb.h b/libc/include/netdb.h
index c2e08ea..9491364 100644
--- a/libc/include/netdb.h
+++ b/libc/include/netdb.h
@@ -209,8 +209,8 @@
 void endprotoent(void);
 void endservent(void);
 void freehostent(struct hostent *);
-struct hostent	*gethostbyaddr(const char *, int, int);
-int gethostbyaddr_r(const char *, int, int, struct hostent *, char *, size_t, struct hostent **, int *);
+struct hostent	*gethostbyaddr(const void *, int, int);
+int gethostbyaddr_r(const void *, int, int, struct hostent *, char *, size_t, struct hostent **, int *);
 struct hostent	*gethostbyname(const char *);
 int gethostbyname_r(const char *, struct hostent *, char *, size_t, struct hostent **, int *);
 struct hostent	*gethostbyname2(const char *, int);
diff --git a/libc/include/netinet/icmp6.h b/libc/include/netinet/icmp6.h
new file mode 100644
index 0000000..fbc8234
--- /dev/null
+++ b/libc/include/netinet/icmp6.h
@@ -0,0 +1,730 @@
+/*	$NetBSD: icmp6.h,v 1.40 2009/10/31 22:32:17 christos Exp $	*/
+/*	$KAME: icmp6.h,v 1.84 2003/04/23 10:26:51 itojun Exp $	*/
+
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * 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 project 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 PROJECT 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 PROJECT 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.
+ */
+
+/*
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ *
+ *	@(#)ip_icmp.h	8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _NETINET_ICMP6_H_
+#define _NETINET_ICMP6_H_
+
+#define ICMPV6_PLD_MAXLEN	1232	/* IPV6_MMTU - sizeof(struct ip6_hdr)
+					   - sizeof(struct icmp6_hdr) */
+
+struct icmp6_hdr {
+	u_int8_t	icmp6_type;	/* type field */
+	u_int8_t	icmp6_code;	/* code field */
+	u_int16_t	icmp6_cksum;	/* checksum field */
+	union {
+		u_int32_t	icmp6_un_data32[1]; /* type-specific field */
+		u_int16_t	icmp6_un_data16[2]; /* type-specific field */
+		u_int8_t	icmp6_un_data8[4];  /* type-specific field */
+	} icmp6_dataun;
+} __packed;
+
+#define icmp6_data32	icmp6_dataun.icmp6_un_data32
+#define icmp6_data16	icmp6_dataun.icmp6_un_data16
+#define icmp6_data8	icmp6_dataun.icmp6_un_data8
+#define icmp6_pptr	icmp6_data32[0]		/* parameter prob */
+#define icmp6_mtu	icmp6_data32[0]		/* packet too big */
+#define icmp6_id	icmp6_data16[0]		/* echo request/reply */
+#define icmp6_seq	icmp6_data16[1]		/* echo request/reply */
+#define icmp6_maxdelay	icmp6_data16[0]		/* mcast group membership */
+
+#define ICMP6_DST_UNREACH		1	/* dest unreachable, codes: */
+#define ICMP6_PACKET_TOO_BIG		2	/* packet too big */
+#define ICMP6_TIME_EXCEEDED		3	/* time exceeded, code: */
+#define ICMP6_PARAM_PROB		4	/* ip6 header bad */
+
+#define ICMP6_ECHO_REQUEST		128	/* echo service */
+#define ICMP6_ECHO_REPLY		129	/* echo reply */
+#define MLD_LISTENER_QUERY		130 	/* multicast listener query */
+#define MLD_LISTENER_REPORT		131	/* multicast listener report */
+#define MLD_LISTENER_DONE		132	/* multicast listener done */
+
+/* RFC2292 decls */
+#define ICMP6_MEMBERSHIP_QUERY		130	/* group membership query */
+#define ICMP6_MEMBERSHIP_REPORT		131	/* group membership report */
+#define ICMP6_MEMBERSHIP_REDUCTION	132	/* group membership termination */
+
+#ifndef _KERNEL
+/* the followings are for backward compatibility to old KAME apps. */
+#define MLD6_LISTENER_QUERY	MLD_LISTENER_QUERY
+#define MLD6_LISTENER_REPORT	MLD_LISTENER_REPORT
+#define MLD6_LISTENER_DONE	MLD_LISTENER_DONE
+#endif
+
+#define ND_ROUTER_SOLICIT		133	/* router solicitation */
+#define ND_ROUTER_ADVERT		134	/* router advertisement */
+#define ND_NEIGHBOR_SOLICIT		135	/* neighbor solicitation */
+#define ND_NEIGHBOR_ADVERT		136	/* neighbor advertisement */
+#define ND_REDIRECT			137	/* redirect */
+
+#define ICMP6_ROUTER_RENUMBERING	138	/* router renumbering */
+
+#define ICMP6_WRUREQUEST		139	/* who are you request */
+#define ICMP6_WRUREPLY			140	/* who are you reply */
+#define ICMP6_FQDN_QUERY		139	/* FQDN query */
+#define ICMP6_FQDN_REPLY		140	/* FQDN reply */
+#define ICMP6_NI_QUERY			139	/* node information request */
+#define ICMP6_NI_REPLY			140	/* node information reply */
+
+/* The definitions below are experimental. TBA */
+#define MLD_MTRACE_RESP			200	/* mtrace response(to sender) */
+#define MLD_MTRACE			201	/* mtrace messages */
+
+#ifndef _KERNEL
+/* the followings are for backward compatibility to old KAME apps. */
+#define MLD6_MTRACE_RESP	MLD_MTRACE_RESP
+#define MLD6_MTRACE		MLD_MTRACE
+#endif
+
+#define ICMP6_MAXTYPE			201
+
+#define ICMP6_DST_UNREACH_NOROUTE	0	/* no route to destination */
+#define ICMP6_DST_UNREACH_ADMIN	 	1	/* administratively prohibited */
+#define ICMP6_DST_UNREACH_NOTNEIGHBOR	2	/* not a neighbor(obsolete) */
+#define ICMP6_DST_UNREACH_BEYONDSCOPE	2	/* beyond scope of source address */
+#define ICMP6_DST_UNREACH_ADDR		3	/* address unreachable */
+#define ICMP6_DST_UNREACH_NOPORT	4	/* port unreachable */
+
+#define ICMP6_TIME_EXCEED_TRANSIT 	0	/* ttl==0 in transit */
+#define ICMP6_TIME_EXCEED_REASSEMBLY	1	/* ttl==0 in reass */
+
+#define ICMP6_PARAMPROB_HEADER 	 	0	/* erroneous header field */
+#define ICMP6_PARAMPROB_NEXTHEADER	1	/* unrecognized next header */
+#define ICMP6_PARAMPROB_OPTION		2	/* unrecognized option */
+
+#define ICMP6_INFOMSG_MASK		0x80	/* all informational messages */
+
+#define ICMP6_NI_SUBJ_IPV6	0	/* Query Subject is an IPv6 address */
+#define ICMP6_NI_SUBJ_FQDN	1	/* Query Subject is a Domain name */
+#define ICMP6_NI_SUBJ_IPV4	2	/* Query Subject is an IPv4 address */
+
+#define ICMP6_NI_SUCCESS	0	/* node information successful reply */
+#define ICMP6_NI_REFUSED	1	/* node information request is refused */
+#define ICMP6_NI_UNKNOWN	2	/* unknown Qtype */
+
+#define ICMP6_ROUTER_RENUMBERING_COMMAND  0	/* rr command */
+#define ICMP6_ROUTER_RENUMBERING_RESULT   1	/* rr result */
+#define ICMP6_ROUTER_RENUMBERING_SEQNUM_RESET   255	/* rr seq num reset */
+
+/* Used in kernel only */
+#define ND_REDIRECT_ONLINK	0	/* redirect to an on-link node */
+#define ND_REDIRECT_ROUTER	1	/* redirect to a better router */
+
+/*
+ * Multicast Listener Discovery
+ */
+struct mld_hdr {
+	struct icmp6_hdr	mld_icmp6_hdr;
+	struct in6_addr		mld_addr; /* multicast address */
+} __packed;
+
+/* definitions to provide backward compatibility to old KAME applications */
+#ifndef _KERNEL
+#define mld6_hdr	mld_hdr
+#define mld6_type	mld_type
+#define mld6_code	mld_code
+#define mld6_cksum	mld_cksum
+#define mld6_maxdelay	mld_maxdelay
+#define mld6_reserved	mld_reserved
+#define mld6_addr	mld_addr
+#endif
+
+/* shortcut macro definitions */
+#define mld_type	mld_icmp6_hdr.icmp6_type
+#define mld_code	mld_icmp6_hdr.icmp6_code
+#define mld_cksum	mld_icmp6_hdr.icmp6_cksum
+#define mld_maxdelay	mld_icmp6_hdr.icmp6_data16[0]
+#define mld_reserved	mld_icmp6_hdr.icmp6_data16[1]
+
+#define MLD_MINLEN			24
+
+/*
+ * Neighbor Discovery
+ */
+
+struct nd_router_solicit {	/* router solicitation */
+	struct icmp6_hdr 	nd_rs_hdr;
+	/* could be followed by options */
+} __packed;
+
+#define nd_rs_type	nd_rs_hdr.icmp6_type
+#define nd_rs_code	nd_rs_hdr.icmp6_code
+#define nd_rs_cksum	nd_rs_hdr.icmp6_cksum
+#define nd_rs_reserved	nd_rs_hdr.icmp6_data32[0]
+
+struct nd_router_advert {	/* router advertisement */
+	struct icmp6_hdr	nd_ra_hdr;
+	u_int32_t		nd_ra_reachable;	/* reachable time */
+	u_int32_t		nd_ra_retransmit;	/* retransmit timer */
+	/* could be followed by options */
+} __packed;
+
+#define nd_ra_type		nd_ra_hdr.icmp6_type
+#define nd_ra_code		nd_ra_hdr.icmp6_code
+#define nd_ra_cksum		nd_ra_hdr.icmp6_cksum
+#define nd_ra_curhoplimit	nd_ra_hdr.icmp6_data8[0]
+#define nd_ra_flags_reserved	nd_ra_hdr.icmp6_data8[1]
+#define ND_RA_FLAG_MANAGED	0x80
+#define ND_RA_FLAG_OTHER	0x40
+#define ND_RA_FLAG_HOME_AGENT	0x20
+
+/*
+ * Router preference values based on RFC4199.
+ */
+#define ND_RA_FLAG_RTPREF_MASK	0x18 /* 00011000 */
+
+#define ND_RA_FLAG_RTPREF_HIGH	0x08 /* 00001000 */
+#define ND_RA_FLAG_RTPREF_MEDIUM	0x00 /* 00000000 */
+#define ND_RA_FLAG_RTPREF_LOW	0x18 /* 00011000 */
+#define ND_RA_FLAG_RTPREF_RSV	0x10 /* 00010000 */
+
+#define nd_ra_router_lifetime	nd_ra_hdr.icmp6_data16[1]
+
+struct nd_neighbor_solicit {	/* neighbor solicitation */
+	struct icmp6_hdr	nd_ns_hdr;
+	struct in6_addr		nd_ns_target;	/*target address */
+	/* could be followed by options */
+} __packed;
+
+#define nd_ns_type		nd_ns_hdr.icmp6_type
+#define nd_ns_code		nd_ns_hdr.icmp6_code
+#define nd_ns_cksum		nd_ns_hdr.icmp6_cksum
+#define nd_ns_reserved		nd_ns_hdr.icmp6_data32[0]
+
+struct nd_neighbor_advert {	/* neighbor advertisement */
+	struct icmp6_hdr	nd_na_hdr;
+	struct in6_addr		nd_na_target;	/* target address */
+	/* could be followed by options */
+} __packed;
+
+#define nd_na_type		nd_na_hdr.icmp6_type
+#define nd_na_code		nd_na_hdr.icmp6_code
+#define nd_na_cksum		nd_na_hdr.icmp6_cksum
+#define nd_na_flags_reserved	nd_na_hdr.icmp6_data32[0]
+#if BYTE_ORDER == BIG_ENDIAN
+#define ND_NA_FLAG_ROUTER		0x80000000
+#define ND_NA_FLAG_SOLICITED		0x40000000
+#define ND_NA_FLAG_OVERRIDE		0x20000000
+#else
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define ND_NA_FLAG_ROUTER		0x80
+#define ND_NA_FLAG_SOLICITED		0x40
+#define ND_NA_FLAG_OVERRIDE		0x20
+#endif
+#endif
+
+struct nd_redirect {		/* redirect */
+	struct icmp6_hdr	nd_rd_hdr;
+	struct in6_addr		nd_rd_target;	/* target address */
+	struct in6_addr		nd_rd_dst;	/* destination address */
+	/* could be followed by options */
+} __packed;
+
+#define nd_rd_type		nd_rd_hdr.icmp6_type
+#define nd_rd_code		nd_rd_hdr.icmp6_code
+#define nd_rd_cksum		nd_rd_hdr.icmp6_cksum
+#define nd_rd_reserved		nd_rd_hdr.icmp6_data32[0]
+
+struct nd_opt_hdr {		/* Neighbor discovery option header */
+	u_int8_t	nd_opt_type;
+	u_int8_t	nd_opt_len;
+	/* followed by option specific data*/
+} __packed;
+
+#define ND_OPT_SOURCE_LINKADDR		1
+#define ND_OPT_TARGET_LINKADDR		2
+#define ND_OPT_PREFIX_INFORMATION	3
+#define ND_OPT_REDIRECTED_HEADER	4
+#define ND_OPT_MTU			5
+#define ND_OPT_ADVINTERVAL		7
+#define ND_OPT_HOMEAGENT_INFO		8
+#define ND_OPT_SOURCE_ADDRLIST		9
+#define ND_OPT_TARGET_ADDRLIST		10
+#define ND_OPT_RDNSS			25
+/* draft-ietf-ipngwg-router-preference, not officially assigned yet */
+#define ND_OPT_ROUTE_INFO		200
+/* draft-ietf-mobileip-hmipv6, not officially assigned yet */
+#define ND_OPT_MAP			201
+
+struct nd_opt_route_info {	/* route info */
+	u_int8_t	nd_opt_rti_type;
+	u_int8_t	nd_opt_rti_len;
+	u_int8_t	nd_opt_rti_prefixlen;
+	u_int8_t	nd_opt_rti_flags;
+	u_int32_t	nd_opt_rti_lifetime;
+	/* prefix follows */
+};
+
+struct nd_opt_prefix_info {	/* prefix information */
+	u_int8_t	nd_opt_pi_type;
+	u_int8_t	nd_opt_pi_len;
+	u_int8_t	nd_opt_pi_prefix_len;
+	u_int8_t	nd_opt_pi_flags_reserved;
+	u_int32_t	nd_opt_pi_valid_time;
+	u_int32_t	nd_opt_pi_preferred_time;
+	u_int32_t	nd_opt_pi_reserved2;
+	struct in6_addr	nd_opt_pi_prefix;
+} __packed;
+
+#define ND_OPT_PI_FLAG_ONLINK		0x80
+#define ND_OPT_PI_FLAG_AUTO		0x40
+
+struct nd_opt_rd_hdr {		/* redirected header */
+	u_int8_t	nd_opt_rh_type;
+	u_int8_t	nd_opt_rh_len;
+	u_int16_t	nd_opt_rh_reserved1;
+	u_int32_t	nd_opt_rh_reserved2;
+	/* followed by IP header and data */
+} __packed;
+
+struct nd_opt_mtu {		/* MTU option */
+	u_int8_t	nd_opt_mtu_type;
+	u_int8_t	nd_opt_mtu_len;
+	u_int16_t	nd_opt_mtu_reserved;
+	u_int32_t	nd_opt_mtu_mtu;
+} __packed;
+
+struct nd_opt_rdnss {		/* RDNSS option RFC 5006 */
+	u_int8_t	nd_opt_rdnss_type;
+	u_int8_t	nd_opt_rdnss_len;
+	u_int16_t	nd_opt_rdnss_reserved;
+	u_int32_t	nd_opt_rdnss_lifetime;
+	/* followed by list of IP prefixes */
+} __packed;
+
+/*
+ * icmp6 namelookup
+ */
+
+struct icmp6_namelookup {
+	struct icmp6_hdr 	icmp6_nl_hdr;
+	u_int8_t	icmp6_nl_nonce[8];
+	int32_t		icmp6_nl_ttl;
+#if 0
+	u_int8_t	icmp6_nl_len;
+	u_int8_t	icmp6_nl_name[3];
+#endif
+	/* could be followed by options */
+} __packed;
+
+/*
+ * icmp6 node information
+ */
+struct icmp6_nodeinfo {
+	struct icmp6_hdr icmp6_ni_hdr;
+	u_int8_t icmp6_ni_nonce[8];
+	/* could be followed by reply data */
+} __packed;
+
+#define ni_type		icmp6_ni_hdr.icmp6_type
+#define ni_code		icmp6_ni_hdr.icmp6_code
+#define ni_cksum	icmp6_ni_hdr.icmp6_cksum
+#define ni_qtype	icmp6_ni_hdr.icmp6_data16[0]
+#define ni_flags	icmp6_ni_hdr.icmp6_data16[1]
+
+#define NI_QTYPE_NOOP		0 /* NOOP  */
+#define NI_QTYPE_SUPTYPES	1 /* Supported Qtypes */
+#define NI_QTYPE_FQDN		2 /* FQDN (draft 04) */
+#define NI_QTYPE_DNSNAME	2 /* DNS Name */
+#define NI_QTYPE_NODEADDR	3 /* Node Addresses */
+#define NI_QTYPE_IPV4ADDR	4 /* IPv4 Addresses */
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define NI_SUPTYPE_FLAG_COMPRESS	0x1
+#define NI_FQDN_FLAG_VALIDTTL		0x1
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define NI_SUPTYPE_FLAG_COMPRESS	0x0100
+#define NI_FQDN_FLAG_VALIDTTL		0x0100
+#endif
+
+#ifdef NAME_LOOKUPS_04
+#if BYTE_ORDER == BIG_ENDIAN
+#define NI_NODEADDR_FLAG_LINKLOCAL	0x1
+#define NI_NODEADDR_FLAG_SITELOCAL	0x2
+#define NI_NODEADDR_FLAG_GLOBAL		0x4
+#define NI_NODEADDR_FLAG_ALL		0x8
+#define NI_NODEADDR_FLAG_TRUNCATE	0x10
+#define NI_NODEADDR_FLAG_ANYCAST	0x20 /* just experimental. not in spec */
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define NI_NODEADDR_FLAG_LINKLOCAL	0x0100
+#define NI_NODEADDR_FLAG_SITELOCAL	0x0200
+#define NI_NODEADDR_FLAG_GLOBAL		0x0400
+#define NI_NODEADDR_FLAG_ALL		0x0800
+#define NI_NODEADDR_FLAG_TRUNCATE	0x1000
+#define NI_NODEADDR_FLAG_ANYCAST	0x2000 /* just experimental. not in spec */
+#endif
+#else  /* draft-ietf-ipngwg-icmp-name-lookups-05 (and later?) */
+#if BYTE_ORDER == BIG_ENDIAN
+#define NI_NODEADDR_FLAG_TRUNCATE	0x1
+#define NI_NODEADDR_FLAG_ALL		0x2
+#define NI_NODEADDR_FLAG_COMPAT		0x4
+#define NI_NODEADDR_FLAG_LINKLOCAL	0x8
+#define NI_NODEADDR_FLAG_SITELOCAL	0x10
+#define NI_NODEADDR_FLAG_GLOBAL		0x20
+#define NI_NODEADDR_FLAG_ANYCAST	0x40 /* just experimental. not in spec */
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define NI_NODEADDR_FLAG_TRUNCATE	0x0100
+#define NI_NODEADDR_FLAG_ALL		0x0200
+#define NI_NODEADDR_FLAG_COMPAT		0x0400
+#define NI_NODEADDR_FLAG_LINKLOCAL	0x0800
+#define NI_NODEADDR_FLAG_SITELOCAL	0x1000
+#define NI_NODEADDR_FLAG_GLOBAL		0x2000
+#define NI_NODEADDR_FLAG_ANYCAST	0x4000 /* just experimental. not in spec */
+#endif
+#endif
+
+struct ni_reply_fqdn {
+	u_int32_t ni_fqdn_ttl;	/* TTL */
+	u_int8_t ni_fqdn_namelen; /* length in octets of the FQDN */
+	u_int8_t ni_fqdn_name[3]; /* XXX: alignment */
+} __packed;
+
+/*
+ * Router Renumbering. as router-renum-08.txt
+ */
+struct icmp6_router_renum {	/* router renumbering header */
+	struct icmp6_hdr	rr_hdr;
+	u_int8_t	rr_segnum;
+	u_int8_t	rr_flags;
+	u_int16_t	rr_maxdelay;
+	u_int32_t	rr_reserved;
+} __packed;
+
+#define ICMP6_RR_FLAGS_TEST		0x80
+#define ICMP6_RR_FLAGS_REQRESULT	0x40
+#define ICMP6_RR_FLAGS_FORCEAPPLY	0x20
+#define ICMP6_RR_FLAGS_SPECSITE		0x10
+#define ICMP6_RR_FLAGS_PREVDONE		0x08
+
+#define rr_type		rr_hdr.icmp6_type
+#define rr_code		rr_hdr.icmp6_code
+#define rr_cksum	rr_hdr.icmp6_cksum
+#define rr_seqnum 	rr_hdr.icmp6_data32[0]
+
+struct rr_pco_match {		/* match prefix part */
+	u_int8_t	rpm_code;
+	u_int8_t	rpm_len;
+	u_int8_t	rpm_ordinal;
+	u_int8_t	rpm_matchlen;
+	u_int8_t	rpm_minlen;
+	u_int8_t	rpm_maxlen;
+	u_int16_t	rpm_reserved;
+	struct	in6_addr	rpm_prefix;
+} __packed;
+
+#define RPM_PCO_ADD		1
+#define RPM_PCO_CHANGE		2
+#define RPM_PCO_SETGLOBAL	3
+#define RPM_PCO_MAX		4
+
+struct rr_pco_use {		/* use prefix part */
+	u_int8_t	rpu_uselen;
+	u_int8_t	rpu_keeplen;
+	u_int8_t	rpu_ramask;
+	u_int8_t	rpu_raflags;
+	u_int32_t	rpu_vltime;
+	u_int32_t	rpu_pltime;
+	u_int32_t	rpu_flags;
+	struct	in6_addr rpu_prefix;
+} __packed;
+#define ICMP6_RR_PCOUSE_RAFLAGS_ONLINK	0x80
+#define ICMP6_RR_PCOUSE_RAFLAGS_AUTO	0x40
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME     0x80000000
+#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME     0x40000000
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define ICMP6_RR_PCOUSE_FLAGS_DECRVLTIME     0x80
+#define ICMP6_RR_PCOUSE_FLAGS_DECRPLTIME     0x40
+#endif
+
+struct rr_result {		/* router renumbering result message */
+	u_int16_t	rrr_flags;
+	u_int8_t	rrr_ordinal;
+	u_int8_t	rrr_matchedlen;
+	u_int32_t	rrr_ifid;
+	struct	in6_addr rrr_prefix;
+} __packed;
+#if BYTE_ORDER == BIG_ENDIAN
+#define ICMP6_RR_RESULT_FLAGS_OOB		0x0002
+#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN		0x0001
+#elif BYTE_ORDER == LITTLE_ENDIAN
+#define ICMP6_RR_RESULT_FLAGS_OOB		0x0200
+#define ICMP6_RR_RESULT_FLAGS_FORBIDDEN		0x0100
+#endif
+
+/*
+ * icmp6 filter structures.
+ */
+
+struct icmp6_filter {
+	u_int32_t icmp6_filt[8];
+};
+
+#define	ICMP6_FILTER_SETPASSALL(filterp) \
+	(void)memset(filterp, 0xff, sizeof(struct icmp6_filter))
+#define	ICMP6_FILTER_SETBLOCKALL(filterp) \
+	(void)memset(filterp, 0x00, sizeof(struct icmp6_filter))
+#define	ICMP6_FILTER_SETPASS(type, filterp) \
+	(((filterp)->icmp6_filt[(type) >> 5]) |= (1 << ((type) & 31)))
+#define	ICMP6_FILTER_SETBLOCK(type, filterp) \
+	(((filterp)->icmp6_filt[(type) >> 5]) &= ~(1 << ((type) & 31)))
+#define	ICMP6_FILTER_WILLPASS(type, filterp) \
+	((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) != 0)
+#define	ICMP6_FILTER_WILLBLOCK(type, filterp) \
+	((((filterp)->icmp6_filt[(type) >> 5]) & (1 << ((type) & 31))) == 0)
+
+/*
+ * Variables related to this implementation
+ * of the internet control message protocol version 6.
+ */
+
+/*
+ * IPv6 ICMP statistics.
+ * Each counter is an unsigned 64-bit value.
+ */
+#define	ICMP6_STAT_ERROR	0	/* # of calls to icmp6_error */
+#define	ICMP6_STAT_CANTERROR	1	/* no error (old was icmp) */
+#define	ICMP6_STAT_TOOFREQ	2	/* no error (rate limitation) */
+#define	ICMP6_STAT_OUTHIST	3	/* # of output messages */
+		/* space for 256 counters */
+#define	ICMP6_STAT_BADCODE	259	/* icmp6_code out of range */
+#define	ICMP6_STAT_TOOSHORT	260	/* packet < sizeof(struct icmp6_hdr) */
+#define	ICMP6_STAT_CHECKSUM	261	/* bad checksum */
+#define	ICMP6_STAT_BADLEN	262	/* calculated bound mismatch */
+	/*
+	 * number of responses; this member is inherited from the netinet code,
+	 * but for netinet6 code, it is already available in outhist[].
+	 */
+#define	ICMP6_STAT_REFLECT	263
+#define	ICMP6_STAT_INHIST	264	/* # of input messages */
+		/* space for 256 counters */
+#define	ICMP6_STAT_ND_TOOMANYOPT 520	/* too many ND options */
+#define	ICMP6_STAT_OUTERRHIST	521
+		/* space for 13 counters */
+#define	ICMP6_STAT_PMTUCHG	534	/* path MTU changes */
+#define	ICMP6_STAT_ND_BADOPT	535	/* bad ND options */
+#define	ICMP6_STAT_BADNS	536	/* bad neighbor solicititation */
+#define	ICMP6_STAT_BADNA	537	/* bad neighbor advertisement */
+#define	ICMP6_STAT_BADRS	538	/* bad router solicitiation */
+#define	ICMP6_STAT_BADRA	539	/* bad router advertisement */
+#define	ICMP6_STAT_BADREDIRECT	540	/* bad redirect message */
+
+#define	ICMP6_NSTATS		541
+
+#define	ICMP6_ERRSTAT_DST_UNREACH_NOROUTE	0
+#define	ICMP6_ERRSTAT_DST_UNREACH_ADMIN		1
+#define	ICMP6_ERRSTAT_DST_UNREACH_BEYONDSCOPE	2
+#define	ICMP6_ERRSTAT_DST_UNREACH_ADDR		3
+#define	ICMP6_ERRSTAT_DST_UNREACH_NOPORT	4
+#define	ICMP6_ERRSTAT_PACKET_TOO_BIG		5
+#define	ICMP6_ERRSTAT_TIME_EXCEED_TRANSIT	6
+#define	ICMP6_ERRSTAT_TIME_EXCEED_REASSEMBLY	7
+#define	ICMP6_ERRSTAT_PARAMPROB_HEADER		8
+#define	ICMP6_ERRSTAT_PARAMPROB_NEXTHEADER	9
+#define	ICMP6_ERRSTAT_PARAMPROB_OPTION		10
+#define	ICMP6_ERRSTAT_REDIRECT			11
+#define	ICMP6_ERRSTAT_UNKNOWN			12
+
+/*
+ * Names for ICMP sysctl objects
+ */
+#define ICMPV6CTL_STATS		1
+#define ICMPV6CTL_REDIRACCEPT	2	/* accept/process redirects */
+#define ICMPV6CTL_REDIRTIMEOUT	3	/* redirect cache time */
+#if 0	/*obsoleted*/
+#define ICMPV6CTL_ERRRATELIMIT	5	/* ICMPv6 error rate limitation */
+#endif
+#define ICMPV6CTL_ND6_PRUNE	6
+#define ICMPV6CTL_ND6_DELAY	8
+#define ICMPV6CTL_ND6_UMAXTRIES	9
+#define ICMPV6CTL_ND6_MMAXTRIES		10
+#define ICMPV6CTL_ND6_USELOOPBACK	11
+/*#define ICMPV6CTL_ND6_PROXYALL	12	obsoleted, do not reuse here */
+#define ICMPV6CTL_NODEINFO	13
+#define ICMPV6CTL_ERRPPSLIMIT	14	/* ICMPv6 error pps limitation */
+#define ICMPV6CTL_ND6_MAXNUDHINT	15
+#define ICMPV6CTL_MTUDISC_HIWAT	16
+#define ICMPV6CTL_MTUDISC_LOWAT	17
+#define ICMPV6CTL_ND6_DEBUG	18
+#define ICMPV6CTL_ND6_DRLIST	19
+#define ICMPV6CTL_ND6_PRLIST	20
+#define	ICMPV6CTL_ND6_MAXQLEN	24
+#define ICMPV6CTL_MAXID		25
+
+#define ICMPV6CTL_NAMES { \
+	{ 0, 0 }, \
+	{ 0, 0 }, \
+	{ "rediraccept", CTLTYPE_INT }, \
+	{ "redirtimeout", CTLTYPE_INT }, \
+	{ 0, 0 }, \
+	{ 0, 0 }, \
+	{ "nd6_prune", CTLTYPE_INT }, \
+	{ 0, 0 }, \
+	{ "nd6_delay", CTLTYPE_INT }, \
+	{ "nd6_umaxtries", CTLTYPE_INT }, \
+	{ "nd6_mmaxtries", CTLTYPE_INT }, \
+	{ "nd6_useloopback", CTLTYPE_INT }, \
+	{ 0, 0 }, \
+	{ "nodeinfo", CTLTYPE_INT }, \
+	{ "errppslimit", CTLTYPE_INT }, \
+	{ "nd6_maxnudhint", CTLTYPE_INT }, \
+	{ "mtudisc_hiwat", CTLTYPE_INT }, \
+	{ "mtudisc_lowat", CTLTYPE_INT }, \
+	{ "nd6_debug", CTLTYPE_INT }, \
+	{ 0, 0 }, \
+	{ 0, 0 }, \
+	{ 0, 0 }, \
+	{ 0, 0 }, \
+	{ 0, 0 }, \
+	{ "nd6_maxqueuelen", CTLTYPE_INT }, \
+}
+
+#define RTF_PROBEMTU	RTF_PROTO1
+
+#ifdef _KERNEL
+struct	rtentry;
+struct	rttimer;
+struct	in6_multi;
+
+void	icmp6_init(void);
+void	icmp6_paramerror(struct mbuf *, int);
+void	icmp6_error(struct mbuf *, int, int, int);
+void	icmp6_error2(struct mbuf *, int, int, int, struct ifnet *);
+int	icmp6_input(struct mbuf **, int *, int);
+void	icmp6_fasttimo(void);
+void	icmp6_reflect(struct mbuf *, size_t);
+void	icmp6_prepare(struct mbuf *);
+void	icmp6_redirect_input(struct mbuf *, int);
+void	icmp6_redirect_output(struct mbuf *, struct rtentry *);
+int	icmp6_sysctl(int *, u_int, void *, size_t *, void *, size_t);
+
+void	icmp6_statinc(u_int);
+
+struct	ip6ctlparam;
+void	icmp6_mtudisc_update(struct ip6ctlparam *, int);
+void	icmp6_mtudisc_callback_register(void (*)(struct in6_addr *));
+
+/* XXX: is this the right place for these macros? */
+#define icmp6_ifstat_inc(ifp, tag) \
+do {								\
+	if (ifp)						\
+		((struct in6_ifextra *)((ifp)->if_afdata[AF_INET6]))->icmp6_ifstat->tag++; \
+} while (/*CONSTCOND*/ 0)
+
+#define icmp6_ifoutstat_inc(ifp, type, code) \
+do { \
+		icmp6_ifstat_inc(ifp, ifs6_out_msg); \
+		switch(type) { \
+		 case ICMP6_DST_UNREACH: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_dstunreach); \
+			 if (code == ICMP6_DST_UNREACH_ADMIN) \
+				 icmp6_ifstat_inc(ifp, ifs6_out_adminprohib); \
+			 break; \
+		 case ICMP6_PACKET_TOO_BIG: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_pkttoobig); \
+			 break; \
+		 case ICMP6_TIME_EXCEEDED: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_timeexceed); \
+			 break; \
+		 case ICMP6_PARAM_PROB: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_paramprob); \
+			 break; \
+		 case ICMP6_ECHO_REQUEST: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_echo); \
+			 break; \
+		 case ICMP6_ECHO_REPLY: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_echoreply); \
+			 break; \
+		 case MLD_LISTENER_QUERY: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_mldquery); \
+			 break; \
+		 case MLD_LISTENER_REPORT: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_mldreport); \
+			 break; \
+		 case MLD_LISTENER_DONE: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_mlddone); \
+			 break; \
+		 case ND_ROUTER_SOLICIT: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_routersolicit); \
+			 break; \
+		 case ND_ROUTER_ADVERT: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_routeradvert); \
+			 break; \
+		 case ND_NEIGHBOR_SOLICIT: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_neighborsolicit); \
+			 break; \
+		 case ND_NEIGHBOR_ADVERT: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_neighboradvert); \
+			 break; \
+		 case ND_REDIRECT: \
+			 icmp6_ifstat_inc(ifp, ifs6_out_redirect); \
+			 break; \
+		} \
+} while (/*CONSTCOND*/ 0)
+
+extern int	icmp6_rediraccept;	/* accept/process redirects */
+extern int	icmp6_redirtimeout;	/* cache time for redirect routes */
+#endif /* _KERNEL */
+
+#endif /* !_NETINET_ICMP6_H_ */
diff --git a/libc/include/netinet/in.h b/libc/include/netinet/in.h
index 0ebd926..7a4b6c7 100644
--- a/libc/include/netinet/in.h
+++ b/libc/include/netinet/in.h
@@ -38,6 +38,8 @@
 
 #define IPPORT_RESERVED  1024
 
+#define INET_ADDRSTRLEN 16
+
 extern int bindresvport (int sd, struct sockaddr_in *sin);
 
 static const struct in6_addr in6addr_any = IN6ADDR_ANY_INIT;
diff --git a/libc/include/netinet/in6.h b/libc/include/netinet/in6.h
index efd5c0a..580a510 100644
--- a/libc/include/netinet/in6.h
+++ b/libc/include/netinet/in6.h
@@ -78,6 +78,9 @@
 #define IPV6_ADDR_MC_SCOPE(a)	\
 	((a)->s6_addr[1] & 0x0f)
 
+#define IN6_IS_ADDR_MC_NODELOCAL(a)     \
+	(IN6_IS_ADDR_MULTICAST(a) &&  \
+	 (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_NODELOCAL))
 #define IN6_IS_ADDR_MC_LINKLOCAL(a)	\
 	(IN6_IS_ADDR_MULTICAST(a) &&  \
 	 (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_LINKLOCAL))
@@ -87,7 +90,9 @@
 #define IN6_IS_ADDR_MC_ORGLOCAL(a)     \
 	(IN6_IS_ADDR_MULTICAST(a) &&  \
 	 (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_ORGLOCAL))
-
+#define IN6_IS_ADDR_MC_GLOBAL(a)       \
+	(IN6_IS_ADDR_MULTICAST(a) &&  \
+	 (IPV6_ADDR_MC_SCOPE(a) == IPV6_ADDR_SCOPE_GLOBAL))
 
 #define IN6_ARE_ADDR_EQUAL(a, b)			\
     (memcmp(&(a)->s6_addr[0], &(b)->s6_addr[0], sizeof(struct in6_addr)) == 0)
diff --git a/libc/include/netinet/ip.h b/libc/include/netinet/ip.h
index 541905c..629ed77 100644
--- a/libc/include/netinet/ip.h
+++ b/libc/include/netinet/ip.h
@@ -83,7 +83,7 @@
 #define	IPTOS_LOWDELAY		0x10
 #define	IPTOS_THROUGHPUT	0x08
 #define	IPTOS_RELIABILITY	0x04
-/*	IPTOS_LOWCOST		0x02 XXX */
+#define	IPTOS_MINCOST		0x02
 #if 1
 /* ECN RFC3168 obsoletes RFC2481, and these will be deprecated soon. */
 #define IPTOS_CE		0x01	/* congestion experienced */
diff --git a/libc/include/netinet/ip6.h b/libc/include/netinet/ip6.h
new file mode 100644
index 0000000..aa816c2
--- /dev/null
+++ b/libc/include/netinet/ip6.h
@@ -0,0 +1,319 @@
+/*	$NetBSD: ip6.h,v 1.23 2007/12/25 18:33:46 perry Exp $	*/
+/*	$KAME: ip6.h,v 1.45 2003/06/05 04:46:38 keiichi Exp $	*/
+
+/*
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * 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 project 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 PROJECT 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 PROJECT 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.
+ */
+
+/*
+ * Copyright (c) 1982, 1986, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * 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.
+ *
+ *	@(#)ip.h	8.1 (Berkeley) 6/10/93
+ */
+
+#ifndef _NETINET_IP6_H_
+#define _NETINET_IP6_H_
+
+/*
+ * Definition for internet protocol version 6.
+ * RFC 2460
+ */
+
+struct ip6_hdr {
+	union {
+		struct ip6_hdrctl {
+			u_int32_t ip6_un1_flow;	/* 20 bits of flow-ID */
+			u_int16_t ip6_un1_plen;	/* payload length */
+			u_int8_t  ip6_un1_nxt;	/* next header */
+			u_int8_t  ip6_un1_hlim;	/* hop limit */
+		} ip6_un1;
+		u_int8_t ip6_un2_vfc;	/* 4 bits version, top 4 bits class */
+	} ip6_ctlun;
+	struct in6_addr ip6_src;	/* source address */
+	struct in6_addr ip6_dst;	/* destination address */
+} __packed;
+
+#define ip6_vfc		ip6_ctlun.ip6_un2_vfc
+#define ip6_flow	ip6_ctlun.ip6_un1.ip6_un1_flow
+#define ip6_plen	ip6_ctlun.ip6_un1.ip6_un1_plen
+#define ip6_nxt		ip6_ctlun.ip6_un1.ip6_un1_nxt
+#define ip6_hlim	ip6_ctlun.ip6_un1.ip6_un1_hlim
+#define ip6_hops	ip6_ctlun.ip6_un1.ip6_un1_hlim
+
+#define IPV6_VERSION		0x60
+#define IPV6_VERSION_MASK	0xf0
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define IPV6_FLOWINFO_MASK	0x0fffffff	/* flow info (28 bits) */
+#define IPV6_FLOWLABEL_MASK	0x000fffff	/* flow label (20 bits) */
+#else
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define IPV6_FLOWINFO_MASK	0xffffff0f	/* flow info (28 bits) */
+#define IPV6_FLOWLABEL_MASK	0xffff0f00	/* flow label (20 bits) */
+#endif /* LITTLE_ENDIAN */
+#endif
+#if 1
+/* ECN bits proposed by Sally Floyd */
+#define IP6TOS_CE		0x01	/* congestion experienced */
+#define IP6TOS_ECT		0x02	/* ECN-capable transport */
+#endif
+
+#ifdef _KERNEL
+/*
+ * for IPv6 pseudo header checksum
+ * XXX nonstandard
+ */
+struct ip6_hdr_pseudo {
+	struct in6_addr ip6ph_src;
+	struct in6_addr ip6ph_dst;
+	u_int32_t	ip6ph_len;
+	u_int8_t	ip6ph_zero[3];
+	u_int8_t	ip6ph_nxt;
+} __packed;
+#endif
+
+/*
+ * Extension Headers
+ */
+
+struct	ip6_ext {
+	u_int8_t ip6e_nxt;
+	u_int8_t ip6e_len;
+} __packed;
+
+/* Hop-by-Hop options header */
+/* XXX should we pad it to force alignment on an 8-byte boundary? */
+struct ip6_hbh {
+	u_int8_t ip6h_nxt;	/* next header */
+	u_int8_t ip6h_len;	/* length in units of 8 octets */
+	/* followed by options */
+} __packed;
+
+/* Destination options header */
+/* XXX should we pad it to force alignment on an 8-byte boundary? */
+struct ip6_dest {
+	u_int8_t ip6d_nxt;	/* next header */
+	u_int8_t ip6d_len;	/* length in units of 8 octets */
+	/* followed by options */
+} __packed;
+
+/* Option types and related macros */
+#define IP6OPT_PAD1		0x00	/* 00 0 00000 */
+#define IP6OPT_PADN		0x01	/* 00 0 00001 */
+#define IP6OPT_JUMBO		0xC2	/* 11 0 00010 = 194 */
+#define IP6OPT_NSAP_ADDR	0xC3	/* 11 0 00011 */
+#define IP6OPT_TUNNEL_LIMIT	0x04	/* 00 0 00100 */
+#define IP6OPT_RTALERT		0x05	/* 00 0 00101 (KAME definition) */
+#define IP6OPT_ROUTER_ALERT	0x05	/* (RFC3542 def, recommended) */
+
+#define IP6OPT_RTALERT_LEN	4
+#define IP6OPT_RTALERT_MLD	0	/* Datagram contains an MLD message */
+#define IP6OPT_RTALERT_RSVP	1	/* Datagram contains an RSVP message */
+#define IP6OPT_RTALERT_ACTNET	2 	/* contains an Active Networks msg */
+#define IP6OPT_MINLEN		2
+
+#define IP6OPT_TYPE(o)		((o) & 0xC0)
+#define IP6OPT_TYPE_SKIP	0x00
+#define IP6OPT_TYPE_DISCARD	0x40
+#define IP6OPT_TYPE_FORCEICMP	0x80
+#define IP6OPT_TYPE_ICMP	0xC0
+
+#define IP6OPT_MUTABLE		0x20
+
+/* IPv6 options: common part */
+struct ip6_opt {
+	u_int8_t ip6o_type;
+	u_int8_t ip6o_len;
+} __packed;
+
+/* Jumbo Payload Option */
+struct ip6_opt_jumbo {
+	u_int8_t ip6oj_type;
+	u_int8_t ip6oj_len;
+	u_int8_t ip6oj_jumbo_len[4];
+} __packed;
+#define IP6OPT_JUMBO_LEN 6
+
+/* NSAP Address Option */
+struct ip6_opt_nsap {
+	u_int8_t ip6on_type;
+	u_int8_t ip6on_len;
+	u_int8_t ip6on_src_nsap_len;
+	u_int8_t ip6on_dst_nsap_len;
+	/* followed by source NSAP */
+	/* followed by destination NSAP */
+} __packed;
+
+/* Tunnel Limit Option */
+struct ip6_opt_tunnel {
+	u_int8_t ip6ot_type;
+	u_int8_t ip6ot_len;
+	u_int8_t ip6ot_encap_limit;
+} __packed;
+
+/* Router Alert Option */
+struct ip6_opt_router {
+	u_int8_t ip6or_type;
+	u_int8_t ip6or_len;
+	u_int8_t ip6or_value[2];
+} __packed;
+/* Router alert values (in network byte order) */
+#if BYTE_ORDER == BIG_ENDIAN
+#define IP6_ALERT_MLD	0x0000
+#define IP6_ALERT_RSVP	0x0001
+#define IP6_ALERT_AN	0x0002
+#else
+#if BYTE_ORDER == LITTLE_ENDIAN
+#define IP6_ALERT_MLD	0x0000
+#define IP6_ALERT_RSVP	0x0100
+#define IP6_ALERT_AN	0x0200
+#endif /* LITTLE_ENDIAN */
+#endif
+
+/* Routing header */
+struct ip6_rthdr {
+	u_int8_t  ip6r_nxt;	/* next header */
+	u_int8_t  ip6r_len;	/* length in units of 8 octets */
+	u_int8_t  ip6r_type;	/* routing type */
+	u_int8_t  ip6r_segleft;	/* segments left */
+	/* followed by routing type specific data */
+} __packed;
+
+/* Type 0 Routing header */
+struct ip6_rthdr0 {
+	u_int8_t  ip6r0_nxt;		/* next header */
+	u_int8_t  ip6r0_len;		/* length in units of 8 octets */
+	u_int8_t  ip6r0_type;		/* always zero */
+	u_int8_t  ip6r0_segleft;	/* segments left */
+	u_int32_t ip6r0_reserved;	/* reserved field */
+} __packed;
+
+/* Fragment header */
+struct ip6_frag {
+	u_int8_t  ip6f_nxt;		/* next header */
+	u_int8_t  ip6f_reserved;	/* reserved field */
+	u_int16_t ip6f_offlg;		/* offset, reserved, and flag */
+	u_int32_t ip6f_ident;		/* identification */
+} __packed;
+
+#if BYTE_ORDER == BIG_ENDIAN
+#define IP6F_OFF_MASK		0xfff8	/* mask out offset from _offlg */
+#define IP6F_RESERVED_MASK	0x0006	/* reserved bits in ip6f_offlg */
+#define IP6F_MORE_FRAG		0x0001	/* more-fragments flag */
+#else /* BYTE_ORDER == LITTLE_ENDIAN */
+#define IP6F_OFF_MASK		0xf8ff	/* mask out offset from _offlg */
+#define IP6F_RESERVED_MASK	0x0600	/* reserved bits in ip6f_offlg */
+#define IP6F_MORE_FRAG		0x0100	/* more-fragments flag */
+#endif /* BYTE_ORDER == LITTLE_ENDIAN */
+
+/*
+ * Internet implementation parameters.
+ */
+#define IPV6_MAXHLIM	255	/* maximum hoplimit */
+#define IPV6_DEFHLIM	64	/* default hlim */
+#define IPV6_FRAGTTL	120	/* ttl for fragment packets, in slowtimo tick */
+#define IPV6_HLIMDEC	1	/* subtracted when forwarding */
+
+#define IPV6_MMTU	1280	/* minimal MTU and reassembly. 1024 + 256 */
+#define IPV6_MAXPACKET	65535	/* ip6 max packet size without Jumbo payload*/
+
+#ifdef _KERNEL
+/*
+ * IP6_EXTHDR_GET ensures that intermediate protocol header (from "off" to
+ * "len") is located in single mbuf, on contiguous memory region.
+ * The pointer to the region will be returned to pointer variable "val",
+ * with type "typ".
+ * IP6_EXTHDR_GET0 does the same, except that it aligns the structure at the
+ * very top of mbuf.  GET0 is likely to make memory copy than GET.
+ *
+ * XXX we're now testing this, needs m_pulldown()
+ */
+#define IP6_EXTHDR_GET(val, typ, m, off, len) \
+do {									\
+	struct mbuf *_t;						\
+	int _tmp;							\
+	if ((m)->m_len >= (off) + (len))				\
+		(val) = (typ)(mtod((m), char *) + (off));		\
+	else {								\
+		_t = m_pulldown((m), (off), (len), &_tmp);		\
+		if (_t) {						\
+			if (_t->m_len < _tmp + (len))			\
+				panic("m_pulldown malfunction");	\
+			(val) = (typ)(mtod(_t, char *) + _tmp);	\
+		} else {						\
+			(val) = (typ)NULL;				\
+			(m) = NULL;					\
+		}							\
+	}								\
+} while (/*CONSTCOND*/ 0)
+
+#define IP6_EXTHDR_GET0(val, typ, m, off, len) \
+do {									\
+	struct mbuf *_t;						\
+	if ((off) == 0 && (m)->m_len >= len)				\
+		(val) = (typ)mtod((m), void *);			\
+	else {								\
+		_t = m_pulldown((m), (off), (len), NULL);		\
+		if (_t) {						\
+			if (_t->m_len < (len))				\
+				panic("m_pulldown malfunction");	\
+			(val) = (typ)mtod(_t, void *);			\
+		} else {						\
+			(val) = (typ)NULL;				\
+			(m) = NULL;					\
+		}							\
+	}								\
+} while (/*CONSTCOND*/ 0)
+#endif /*_KERNEL*/
+
+#endif /* !_NETINET_IP6_H_ */
diff --git a/libc/include/pthread.h b/libc/include/pthread.h
index 99e747a..9d05769 100644
--- a/libc/include/pthread.h
+++ b/libc/include/pthread.h
@@ -103,7 +103,7 @@
 /*
  * Prototypes
  */
-#if __cplusplus
+#ifdef __cplusplus
 extern "C" {
 #endif
 
@@ -233,7 +233,7 @@
     void*            reserved[4];  /* for future extensibility */
 } pthread_rwlock_t;
 
-#define PTHREAD_RWLOCK_INITIALIZER  { PTHREAD_MUTEX_INITIALIZER, 0, NULL, 0, 0 }
+#define PTHREAD_RWLOCK_INITIALIZER  { PTHREAD_MUTEX_INITIALIZER, PTHREAD_COND_INITIALIZER, 0, 0, 0, 0, { NULL, NULL, NULL, NULL } }
 
 int pthread_rwlockattr_init(pthread_rwlockattr_t *attr);
 int pthread_rwlockattr_destroy(pthread_rwlockattr_t *attr);
@@ -268,6 +268,8 @@
 
 int pthread_setname_np(pthread_t thid, const char *thname);
 
+int pthread_atfork(void (*prepare)(void), void (*parent)(void), void(*child)(void));
+
 typedef void  (*__pthread_cleanup_func_t)(void*);
 
 typedef struct __pthread_cleanup_t {
@@ -300,7 +302,7 @@
         __pthread_cleanup_pop( &__cleanup, (execute)); \
     } while (0);
 
-#if __cplusplus
+#ifdef __cplusplus
 } /* extern "C" */
 #endif
 
diff --git a/libc/include/resolv.h b/libc/include/resolv.h
index 4247d68..bb21c23 100644
--- a/libc/include/resolv.h
+++ b/libc/include/resolv.h
@@ -34,6 +34,7 @@
 #include <sys/socket.h>
 #include <stdio.h>
 #include <arpa/nameser.h>
+#include <netinet/in.h>
 
 __BEGIN_DECLS
 
@@ -49,6 +50,21 @@
 extern int   b64_ntop(u_char const *, size_t, char *, size_t);
 extern int   b64_pton(char const *, u_char *, size_t);
 
+/* Set name of default interface */
+extern void _resolv_set_default_iface(const char* ifname);
+
+/* set name servers for an interface */
+extern void _resolv_set_nameservers_for_iface(const char* ifname, char** servers, int numservers);
+
+/* tell resolver of the address of an interface */
+extern void _resolv_set_addr_of_iface(const char* ifname, struct in_addr* addr);
+
+/* flush the cache associated with the default interface */
+extern void _resolv_flush_cache_for_default_iface();
+
+/* flush the cache associated with a certain interface */
+extern void _resolv_flush_cache_for_iface(const char* ifname);
+
 __END_DECLS
 
 #endif /* _RESOLV_H_ */
diff --git a/libc/include/sched.h b/libc/include/sched.h
index e702470..ca72da7 100644
--- a/libc/include/sched.h
+++ b/libc/include/sched.h
@@ -73,6 +73,162 @@
 extern int clone(int (*fn)(void *), void *child_stack, int flags, void*  arg, ...);
 #endif
 
+/* Support for cpu thread affinity */
+#ifdef _GNU_SOURCE
+
+extern int sched_getcpu(void);
+
+
+/* Our implementation supports up to 32 independent CPUs, which is also
+ * the maximum supported by the kernel at the moment. GLibc uses 1024 by
+ * default.
+ *
+ * If you want to use more than that, you should use CPU_ALLOC() / CPU_FREE()
+ * and the CPU_XXX_S() macro variants.
+ */
+#define CPU_SETSIZE   32
+
+#define __CPU_BITTYPE    unsigned long int  /* mandated by the kernel  */
+#define __CPU_BITSHIFT   5                  /* should be log2(BITTYPE) */
+#define __CPU_BITS       (1 << __CPU_BITSHIFT)
+#define __CPU_ELT(x)     ((x) >> __CPU_BITSHIFT)
+#define __CPU_MASK(x)    ((__CPU_BITTYPE)1 << ((x) & (__CPU_BITS-1)))
+
+typedef struct {
+    __CPU_BITTYPE  __bits[ CPU_SETSIZE / __CPU_BITS ];
+} cpu_set_t;
+
+extern int sched_setaffinity(pid_t pid, size_t setsize, const cpu_set_t* set);
+
+extern int sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set);
+
+/* Provide optimized implementation for 32-bit cpu_set_t */
+#if CPU_SETSIZE == __CPU_BITS
+
+#  define CPU_ZERO(set_)   \
+    do{ \
+        (set_)->__bits[0] = 0; \
+    }while(0)
+
+#  define CPU_SET(cpu_,set_) \
+    do {\
+        size_t __cpu = (cpu_); \
+        if (__cpu < CPU_SETSIZE) \
+            (set_)->__bits[0] |= __CPU_MASK(__cpu); \
+    }while (0)
+
+#  define CPU_CLR(cpu_,set_) \
+    do {\
+        size_t __cpu = (cpu_); \
+        if (__cpu < CPU_SETSIZE) \
+            (set_)->__bits[0] &= ~__CPU_MASK(__cpu); \
+    }while (0)
+
+#  define CPU_ISSET(cpu_, set_) \
+    (__extension__({\
+        size_t  __cpu = (cpu_); \
+        (cpu_ < CPU_SETSIZE) \
+            ? ((set_)->__bits[0] & __CPU_MASK(__cpu)) != 0 \
+            : 0; \
+    }))
+
+#  define CPU_EQUAL(set1_, set2_) \
+    ((set1_)->__bits[0] == (set2_)->__bits[0])
+
+#  define __CPU_OP(dst_, set1_, set2_, op_) \
+    do { \
+        (dst_)->__bits[0] = (set1_)->__bits[0] op_ (set2_)->__bits[0]; \
+    } while (0)
+
+#  define CPU_COUNT(set_)  __builtin_popcountl((set_)->__bits[0])
+
+#else /* CPU_SETSIZE != __CPU_BITS */
+
+#  define CPU_ZERO(set_)          CPU_ZERO_S(sizeof(cpu_set_t), set_)
+#  define CPU_SET(cpu_,set_)      CPU_SET_S(cpu_,sizeof(cpu_set_t),set_)
+#  define CPU_CLR(cpu_,set_)      CPU_CLR_S(cpu_,sizeof(cpu_set_t),set_)
+#  define CPU_ISSET(cpu_,set_)    CPU_ISSET_S(cpu_,sizeof(cpu_set_t),set_)
+#  define CPU_COUNT(set_)         CPU_COUNT_S(sizeof(cpu_set_t),set_)
+#  define CPU_EQUAL(set1_,set2_)  CPU_EQUAL_S(sizeof(cpu_set_t),set1_,set2_)
+
+#  define __CPU_OP(dst_,set1_,set2_,op_)  __CPU_OP_S(sizeof(cpu_set_t),dst_,set1_,set2_,op_)
+
+#endif /* CPU_SETSIZE != __CPU_BITS */
+
+#define CPU_AND(set1_,set2_)   __CPU_OP(set1_,set2_,&)
+#define CPU_OR(set1_,set2_)    __CPU_OP(set1_,set2_,|)
+#define CPU_XOR(set1_,set2_)   __CPU_OP(set1_,set2_,^)
+
+/* Support for dynamically-allocated cpu_set_t */
+
+#define CPU_ALLOC_SIZE(count) \
+    __CPU_ELT((count) + (__CPU_BITS-1))*sizeof(__CPU_BITTYPE)
+
+#define CPU_ALLOC(count)   __sched_cpualloc((count));
+#define CPU_FREE(set)      __sched_cpufree((set))
+
+extern cpu_set_t* __sched_cpualloc(size_t count);
+extern void       __sched_cpufree(cpu_set_t* set);
+
+#define CPU_ZERO_S(setsize_,set_)  \
+    do { \
+        size_t __nn = 0; \
+        size_t __nn_max = (setsize_)/sizeof(__CPU_BITTYPE); \
+        for (; __nn < __nn_max; __nn++) \
+            (set_)->__bits[__nn] = 0; \
+    } while (0)
+
+#define CPU_SET_S(cpu_,setsize_,set_) \
+    do { \
+        size_t __cpu = (cpu_); \
+        if (__cpu < 8*(setsize_)) \
+            (set_)->__bits[__CPU_ELT(__cpu)] |= __CPU_MASK(__cpu); \
+    } while (0)
+
+#define CPU_CLR_S(cpu_,setsize_,set_) \
+    do { \
+        size_t __cpu = (cpu_); \
+        if (__cpu < 8*(setsize_)) \
+            (set_)->__bits[__CPU_ELT(__cpu)] &= ~__CPU_MASK(__cpu); \
+    } while (0)
+
+#define CPU_ISSET_S(cpu_, setsize_, set_) \
+    (__extension__ ({ \
+        size_t __cpu = (cpu_); \
+        (__cpu < 8*(setsize_)) \
+          ? ((set_)->__bits[__CPU_ELT(__cpu)] & __CPU_MASK(__cpu)) != 0 \
+          : 0; \
+    }))
+
+#define CPU_EQUAL_S(setsize_, set1_, set2_) \
+    (__extension__ ({ \
+        __const __CPU_BITTYPE* __src1 = (set1_)->__bits; \
+        __const __CPU_BITTYPE* __src2 = (set2_)->__bits; \
+        size_t __nn = 0, __nn_max = (setsize_)/sizeof(__CPU_BITTYPE); \
+        for (; __nn < __nn_max; __nn++) { \
+            if (__src1[__nn] != __src2[__nn]) \
+                break; \
+        } \
+        __nn == __nn_max; \
+    }))
+
+#define __CPU_OP_S(setsize_, dstset_, srcset1_, srcset2_, op) \
+    do { \
+        cpu_set_t* __dst = (dstset); \
+        const __CPU_BITTYPE* __src1 = (srcset1)->__bits; \
+        const __CPU_BITTYPE* __src2 = (srcset2)->__bits; \
+        size_t __nn = 0, __nn_max = (setsize_)/sizeof(__CPU_BITTYPE); \
+        for (; __nn < __nn_max; __nn++) \
+            (__dst)->__bits[__nn] = __src1[__nn] op __src2[__nn]; \
+    } while (0)
+
+#define CPU_COUNT_S(setsize_, set_) \
+    __sched_cpucount((setsize_), (set_))
+
+extern int __sched_cpucount(size_t setsize, cpu_set_t* set);
+
+#endif /* _GNU_SOURCE */
+
 __END_DECLS
 
 #endif /* _SCHED_H_ */
diff --git a/libc/include/signal.h b/libc/include/signal.h
index 4401164..91c3b00 100644
--- a/libc/include/signal.h
+++ b/libc/include/signal.h
@@ -42,12 +42,15 @@
 
 typedef int sig_atomic_t;
 
-/* crepy NIG / _NSIG handling, just to be safe */
-#ifndef NSIG
-#  define NSIG  _NSIG
-#endif
+/* _NSIG is used by the SIGRTMAX definition under <asm/signal.h>, however
+ * its definition is part of a #if __KERNEL__ .. #endif block in the original
+ * kernel headers and is thus not part of our cleaned-up versions.
+ *
+ * Looking at the current kernel sources, it is defined as 64 for all
+ * architectures except for the 'mips' one which set it to 128.
+ */
 #ifndef _NSIG
-#  define _NSIG  NSIG
+#  define _NSIG  64
 #endif
 
 extern const char * const sys_siglist[];
diff --git a/libc/include/stdint.h b/libc/include/stdint.h
index 237baa2..e791475 100644
--- a/libc/include/stdint.h
+++ b/libc/include/stdint.h
@@ -41,11 +41,6 @@
 #  define  __STDINT_MACROS
 #endif
 
-/* the definitions of STDINT_LIMITS depend on those of STDINT_MACROS */
-#if defined __STDINT_LIMITS && !defined __STDINT_MACROS
-#  define  __STDINT_MACROS
-#endif
-
 #if !defined __STRICT_ANSI__ || __STDC_VERSION__ >= 199901L
 #  define __STDC_INT64__
 #endif
@@ -185,13 +180,14 @@
 #  define UINT_FAST64_MAX UINT64_MAX
 #endif
 
+#define __INT64_C(c)     c ## LL
+#define __UINT64_C(c)     c ## ULL
+
 #ifdef __STDINT_MACROS
-#  define __INT64_C(c)     c ## LL
 #  define INT64_C(c)       __INT64_C(c)
 #  define INT_LEAST64_C(c) INT64_C(c)
 #  define INT_FAST64_C(c)  INT64_C(c)
 
-#  define __UINT64_C(c)     c ## ULL
 #  define UINT64_C(c)       __UINT64_C(c)
 #  define UINT_LEAST64_C(c) UINT64_C(c)
 #  define UINT_FAST64_C(c)  UINT64_C(c)
@@ -211,14 +207,20 @@
 typedef int           intptr_t;
 typedef unsigned int  uintptr_t;
 
+#ifdef __STDINT_LIMITS
 #  define INTPTR_MIN    INT32_MIN
 #  define INTPTR_MAX    INT32_MAX
 #  define UINTPTR_MAX   UINT32_MAX
+#  define PTRDIFF_MIN   INT32_MIN
+#  define PTRDIFF_MAX   INT32_MAX
+#endif
+
+#ifdef __STDINT_MACROS
 #  define INTPTR_C(c)   INT32_C(c)
 #  define UINTPTR_C(c)  UINT32_C(c)
 #  define PTRDIFF_C(c)  INT32_C(c)
-#  define PTRDIFF_MIN   INT32_MIN
-#  define PTRDIFF_MAX   INT32_MAX
+#endif
+
 
 
 /*
@@ -230,24 +232,32 @@
 typedef uint64_t uintmax_t;
 typedef int64_t  intmax_t;
 
-#define INTMAX_MIN	INT64_MIN
-#define INTMAX_MAX	INT64_MAX
-#define UINTMAX_MAX	UINT64_MAX
+#ifdef __STDINT_LIMITS
+#  define INTMAX_MIN	INT64_MIN
+#  define INTMAX_MAX	INT64_MAX
+#  define UINTMAX_MAX	UINT64_MAX
+#endif
 
-#define INTMAX_C(c)	INT64_C(c)
-#define UINTMAX_C(c)	UINT64_C(c)
+#ifdef __STDINT_MACROS
+#  define INTMAX_C(c)	INT64_C(c)
+#  define UINTMAX_C(c)	UINT64_C(c)
+#endif
 
 #else /* !__STDC_INT64__ */
 
 typedef uint32_t  uintmax_t;
 typedef int32_t   intmax_t;
 
-#define  INTMAX_MIN    INT32_MIN
-#define  INTMAX_MAX    INT32_MAX
-#define  UINTMAX_MAX   UINT32_MAX
+#ifdef __STDINT_LIMITS
+#  define  INTMAX_MIN    INT32_MIN
+#  define  INTMAX_MAX    INT32_MAX
+#  define  UINTMAX_MAX   UINT32_MAX
+#endif
 
-#define INTMAX_C(c)	INT32_C(c)
-#define UINTMAX_C(c)	UINT32_C(c)
+#ifdef __STDINT_MACROS
+#  define INTMAX_C(c)	INT32_C(c)
+#  define UINTMAX_C(c)	UINT32_C(c)
+#endif
 
 #endif /* !__STDC_INT64__ */
 
diff --git a/libc/include/stdlib.h b/libc/include/stdlib.h
index 97d8e46..5dc8a87 100644
--- a/libc/include/stdlib.h
+++ b/libc/include/stdlib.h
@@ -57,6 +57,7 @@
 extern int unsetenv(const char *);
 extern int clearenv(void);
 
+extern char *mkdtemp(char *);
 extern char *mktemp (char *);
 extern int mkstemp (char *);
 
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 849e2b8..92035d4 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -79,7 +79,7 @@
 #define	___STRING(x)	__STRING(x)
 #define	___CONCAT(x,y)	__CONCAT(x,y)
 
-#if __STDC__ || defined(__cplusplus)
+#if defined(__STDC__) || defined(__cplusplus)
 #define	__P(protos)	protos		/* full-blown ANSI C */
 #define	__CONCAT(x,y)	x ## y
 #define	__STRING(x)	#x
@@ -213,7 +213,7 @@
  * C99 defines the restrict type qualifier keyword, which was made available
  * in GCC 2.92.
  */
-#if __STDC_VERSION__ >= 199901L
+#if defined(__STDC__VERSION__) && __STDC_VERSION__ >= 199901L
 #define	__restrict	restrict
 #else
 #if !__GNUC_PREREQ__(2, 92)
@@ -225,7 +225,7 @@
  * C99 defines __func__ predefined identifier, which was made available
  * in GCC 2.95.
  */
-#if !(__STDC_VERSION__ >= 199901L)
+#if !defined(__STDC_VERSION__) || !(__STDC_VERSION__ >= 199901L)
 #if __GNUC_PREREQ__(2, 6)
 #define	__func__	__PRETTY_FUNCTION__
 #elif __GNUC_PREREQ__(2, 4)
@@ -497,5 +497,6 @@
 #endif
 
 #define  __BIONIC__   1
+#include <android/api-level.h>
 
 #endif /* !_SYS_CDEFS_H_ */
diff --git a/libc/include/sys/cdefs_elf.h b/libc/include/sys/cdefs_elf.h
index e051b1d..1e57470 100644
--- a/libc/include/sys/cdefs_elf.h
+++ b/libc/include/sys/cdefs_elf.h
@@ -95,6 +95,10 @@
 	__asm__(".section _sec\n\t.asciz _str\n\t.previous")
 #endif
 
+/* GCC visibility helper macro */
+#define __LIBC_HIDDEN__							\
+	__attribute__ ((visibility ("hidden")))
+
 #define	__IDSTRING(_n,_s)		__SECTIONSTRING(.ident,_s)
 
 #define	__RCSID(_s)			__IDSTRING(rcsid,_s)
diff --git a/libc/include/sys/linux-syscalls.h b/libc/include/sys/linux-syscalls.h
index 9702a7a..cb4d5e5 100644
--- a/libc/include/sys/linux-syscalls.h
+++ b/libc/include/sys/linux-syscalls.h
@@ -71,6 +71,7 @@
 #define __NR_dup2                         (__NR_SYSCALL_BASE + 63)
 #define __NR__newselect                   (__NR_SYSCALL_BASE + 142)
 #define __NR_ftruncate                    (__NR_SYSCALL_BASE + 93)
+#define __NR_ftruncate64                  (__NR_SYSCALL_BASE + 194)
 #define __NR_fsync                        (__NR_SYSCALL_BASE + 118)
 #define __NR_fdatasync                    (__NR_SYSCALL_BASE + 148)
 #define __NR_fchown32                     (__NR_SYSCALL_BASE + 207)
@@ -120,6 +121,8 @@
 #define __NR_sched_get_priority_max       (__NR_SYSCALL_BASE + 159)
 #define __NR_sched_get_priority_min       (__NR_SYSCALL_BASE + 160)
 #define __NR_sched_rr_get_interval        (__NR_SYSCALL_BASE + 161)
+#define __NR_sched_setaffinity            (__NR_SYSCALL_BASE + 241)
+#define __NR_sched_getaffinity            (__NR_SYSCALL_BASE + 242)
 #define __NR_uname                        (__NR_SYSCALL_BASE + 122)
 #define __NR_wait4                        (__NR_SYSCALL_BASE + 114)
 #define __NR_umask                        (__NR_SYSCALL_BASE + 60)
@@ -174,6 +177,7 @@
 #define __NR_getsockopt                   (__NR_SYSCALL_BASE + 295)
 #define __NR_sendmsg                      (__NR_SYSCALL_BASE + 296)
 #define __NR_recvmsg                      (__NR_SYSCALL_BASE + 297)
+#define __NR_getcpu                       (__NR_SYSCALL_BASE + 345)
 #define __NR_ioprio_set                   (__NR_SYSCALL_BASE + 314)
 #define __NR_ioprio_get                   (__NR_SYSCALL_BASE + 315)
 #define __NR_epoll_create                 (__NR_SYSCALL_BASE + 250)
@@ -218,6 +222,7 @@
 #define __NR_timer_delete                 (__NR_SYSCALL_BASE + 263)
 #define __NR_utimes                       (__NR_SYSCALL_BASE + 271)
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
+#define __NR_getcpu                       (__NR_SYSCALL_BASE + 318)
 #define __NR_ioprio_set                   (__NR_SYSCALL_BASE + 289)
 #define __NR_ioprio_get                   (__NR_SYSCALL_BASE + 290)
 #define __NR_epoll_create                 (__NR_SYSCALL_BASE + 254)
@@ -276,6 +281,7 @@
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
 #define __NR_socketcall                   (__NR_SYSCALL_BASE + 102)
 #define __NR___socketcall                 (__NR_SYSCALL_BASE + 102)
+#define __NR_getcpu                       (__NR_SYSCALL_BASE + 318)
 #define __NR_ioprio_set                   (__NR_SYSCALL_BASE + 288)
 #define __NR_ioprio_get                   (__NR_SYSCALL_BASE + 289)
 #define __NR_epoll_create                 (__NR_SYSCALL_BASE + 254)
diff --git a/libc/include/sys/linux-unistd.h b/libc/include/sys/linux-unistd.h
index 23853da..f706d00 100644
--- a/libc/include/sys/linux-unistd.h
+++ b/libc/include/sys/linux-unistd.h
@@ -52,8 +52,8 @@
 int              acct (const char*  filepath);
 ssize_t          read (int, void*, size_t);
 ssize_t          write (int, const void*, size_t);
-ssize_t          __pread64 (int, void *, size_t, off_t, off_t);
-ssize_t          __pwrite64 (int, void *, size_t, off_t, off_t);
+ssize_t          pread64 (int, void *, size_t, off64_t);
+ssize_t          pwrite64 (int, void *, size_t, off64_t);
 int              __open (const char*, int, mode_t);
 int              __openat (int, const char*, int, mode_t);
 int              close (int);
@@ -83,6 +83,7 @@
 int              dup2 (int, int);
 int              select (int, struct fd_set *, struct fd_set *, struct fd_set *, struct timeval *);
 int              ftruncate (int, off_t);
+int              ftruncate64 (int, off64_t);
 int              getdents (unsigned int, struct dirent *, unsigned int);
 int              fsync (int);
 int              fdatasync (int);
@@ -183,6 +184,9 @@
 int              sched_get_priority_max (int policy);
 int              sched_get_priority_min (int policy);
 int              sched_rr_get_interval (pid_t pid, struct timespec *interval);
+int              sched_setaffinity (pid_t pid, size_t setsize, const cpu_set_t* set);
+int              __sched_getaffinity (pid_t pid, size_t setsize, cpu_set_t* set);
+int              __getcpu (unsigned *cpu, unsigned *node, void *unused);
 int              ioprio_set (int which, int who, int ioprio);
 int              ioprio_get (int which, int who);
 int              uname (struct utsname *);
diff --git a/libc/include/sys/prctl.h b/libc/include/sys/prctl.h
index ce85bf7..359d684 100644
--- a/libc/include/sys/prctl.h
+++ b/libc/include/sys/prctl.h
@@ -32,8 +32,13 @@
 
 __BEGIN_DECLS
 
-extern int prctl(int option, unsigned long arg2, unsigned long arg3 , unsigned
-               long arg4, unsigned long arg5);
+/* IMPORTANT NOTE: This function is declared as taking a variable number
+ *                 of arguments to match the GLibc definition. However
+ *                 its declaration inside SYSCALLS.TXT *must* make it
+ *                 take 6 arguments to ensure consistency with the kernel
+ *                 implementation.
+ */
+extern int prctl(int option, ...);
 
 __END_DECLS
 
diff --git a/libc/include/time.h b/libc/include/time.h
index 5d1a0e2..4ad4f7b 100644
--- a/libc/include/time.h
+++ b/libc/include/time.h
@@ -128,6 +128,11 @@
 extern int  timer_gettime(timer_t timerid, struct itimerspec *value);
 extern int  timer_getoverrun(timer_t  timerid);
 
+extern time_t timelocal(struct tm *tm);
+extern time_t timegm(struct tm* tm);
+extern time_t time2posix(time_t ti);
+extern time_t posix2time(time_t ti);
+
 __END_DECLS
 
 #endif /* _TIME_H_ */
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 29154a2..d92549f 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -70,8 +70,9 @@
 extern int execle(const char *, const char *, ...);
 extern int capget(cap_user_header_t hdrp, cap_user_data_t datap);
 extern int capset(cap_user_header_t hdrp, const cap_user_data_t datap);
-extern int prctl(int  option,  unsigned long arg2, unsigned long arg3,
-                 unsigned long arg4, unsigned long arg5);
+
+/* IMPORTANT: See comment under <sys/prctl.h> about this declaration */
+extern int prctl(int  option, ...);
 
 extern int nice(int);
 
@@ -128,12 +129,14 @@
 
 extern int close(int);
 extern off_t lseek(int, off_t, int);
-extern loff_t lseek64(int, loff_t, int);
+extern off64_t lseek64(int, off64_t, int);
 
 extern ssize_t read(int, void *, size_t);
 extern ssize_t write(int, const void *, size_t);
 extern ssize_t pread(int, void *, size_t, off_t);
-extern ssize_t pwrite(int, void *, size_t, off_t);
+extern ssize_t pread64(int, void *, size_t, off64_t);
+extern ssize_t pwrite(int, const void *, size_t, off_t);
+extern ssize_t pwrite64(int, const void *, size_t, off64_t);
 
 extern int dup(int);
 extern int dup2(int, int);
@@ -143,6 +146,7 @@
 extern int fsync(int);
 extern int fdatasync(int);
 extern int ftruncate(int, off_t);
+extern int ftruncate64(int, off64_t);
 
 extern int pause(void);
 extern unsigned int alarm(unsigned int);
diff --git a/libc/include/wchar.h b/libc/include/wchar.h
index 9b744a5..1361ff5 100644
--- a/libc/include/wchar.h
+++ b/libc/include/wchar.h
@@ -112,6 +112,7 @@
 extern int               vwprintf(const wchar_t *, va_list);
 extern int               vswprintf(wchar_t *, size_t, const wchar_t *, va_list);
 extern size_t            wcrtomb(char *, wchar_t, mbstate_t *);
+extern int               wcscasecmp(const wchar_t *, const wchar_t *);
 extern wchar_t          *wcscat(wchar_t *, const wchar_t *);
 extern wchar_t          *wcschr(const wchar_t *, wchar_t);
 extern int               wcscmp(const wchar_t *, const wchar_t *);
@@ -120,6 +121,7 @@
 extern size_t            wcscspn(const wchar_t *, const wchar_t *);
 extern size_t            wcsftime(wchar_t *, size_t, const wchar_t *, const struct tm *);
 extern size_t            wcslen(const wchar_t *);
+extern int               wcsncasecmp(const wchar_t *, const wchar_t *, size_t);
 extern wchar_t          *wcsncat(wchar_t *, const wchar_t *, size_t);
 extern int               wcsncmp(const wchar_t *, const wchar_t *, size_t);
 extern wchar_t          *wcsncpy(wchar_t *, const wchar_t *, size_t);
diff --git a/libc/inet/ether_aton.c b/libc/inet/ether_aton.c
new file mode 100644
index 0000000..6540c07
--- /dev/null
+++ b/libc/inet/ether_aton.c
@@ -0,0 +1,89 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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 <stdlib.h>
+#include <sys/types.h>
+#include <net/if_ether.h>
+#include <ctype.h>
+
+static inline int
+xdigit (char c) {
+    unsigned d;
+    d = (unsigned)(c-'0');
+    if (d < 10) return (int)d;
+    d = (unsigned)(c-'a');
+    if (d < 6) return (int)(10+d);
+    d = (unsigned)(c-'A');
+    if (d < 6) return (int)(10+d);
+    return -1;
+}
+
+/*
+ * Convert Ethernet address in the standard hex-digits-and-colons to binary
+ * representation.
+ * Re-entrant version (GNU extensions)
+ */
+struct ether_addr *
+ether_aton_r (const char *asc, struct ether_addr * addr)
+{
+    int i, val0, val1;
+    for (i = 0; i < ETHER_ADDR_LEN; ++i) {
+        val0 = xdigit(*asc);
+        asc++;
+        if (val0 < 0)
+            return NULL;
+
+        val1 = xdigit(*asc);
+        asc++;
+        if (val1 < 0)
+            return NULL;
+
+        addr->ether_addr_octet[i] = (u_int8_t)((val0 << 4) + val1);
+
+        if (i < ETHER_ADDR_LEN - 1) {
+            if (*asc != ':')
+                return NULL;
+            asc++;
+        }
+    }
+    if (*asc != '\0')
+        return NULL;
+    return addr;
+}
+
+/*
+ * Convert Ethernet address in the standard hex-digits-and-colons to binary
+ * representation.
+ */
+struct ether_addr *
+ether_aton (const char *asc)
+{
+    static struct ether_addr addr;
+    return ether_aton_r(asc, &addr);
+}
diff --git a/libc/inet/ether_ntoa.c b/libc/inet/ether_ntoa.c
new file mode 100644
index 0000000..f56e48b
--- /dev/null
+++ b/libc/inet/ether_ntoa.c
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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 <sys/types.h>
+#include <net/if_ether.h>
+
+/*
+ * Convert Ethernet address to standard hex-digits-and-colons printable form.
+ * Re-entrant version (GNU extensions).
+ */
+char *
+ether_ntoa_r (const struct ether_addr *addr, char * buf)
+{
+    snprintf(buf, 18, "%02x:%02x:%02x:%02x:%02x:%02x",
+            addr->ether_addr_octet[0], addr->ether_addr_octet[1],
+            addr->ether_addr_octet[2], addr->ether_addr_octet[3],
+            addr->ether_addr_octet[4], addr->ether_addr_octet[5]);
+    return buf;
+}
+
+/*
+ * Convert Ethernet address to standard hex-digits-and-colons printable form.
+ */
+char *
+ether_ntoa (const struct ether_addr *addr)
+{
+    static char buf[18];
+    return ether_ntoa_r(addr, buf);
+}
diff --git a/libc/kernel/arch-arm/asm/byteorder.h b/libc/kernel/arch-arm/asm/byteorder.h
index 4da37bf..b869695 100644
--- a/libc/kernel/arch-arm/asm/byteorder.h
+++ b/libc/kernel/arch-arm/asm/byteorder.h
@@ -22,7 +22,7 @@
 #ifndef __thumb__
  if (!__builtin_constant_p(x)) {
 
- asm ("eor\t%0, %1, %1, ror #16" : "=r" (t) : "r" (x));
+ __asm__ ("eor\t%0, %1, %1, ror #16" : "=r" (t) : "r" (x));
  } else
 #endif
  t = x ^ ((x << 16) | (x >> 16));
diff --git a/libc/kernel/arch-arm/asm/ptrace.h b/libc/kernel/arch-arm/asm/ptrace.h
index b6be08c..3faf738 100644
--- a/libc/kernel/arch-arm/asm/ptrace.h
+++ b/libc/kernel/arch-arm/asm/ptrace.h
@@ -30,6 +30,7 @@
 #define PTRACE_SETCRUNCHREGS 26
 
 #define PTRACE_GETVFPREGS 27
+#define PTRACE_SETVFPREGS 28
 
 #define USR26_MODE 0x00000000
 #define FIQ26_MODE 0x00000001
diff --git a/libc/kernel/common/linux/akm8975.h b/libc/kernel/common/linux/akm8975.h
new file mode 100644
index 0000000..1815f75
--- /dev/null
+++ b/libc/kernel/common/linux/akm8975.h
@@ -0,0 +1,72 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef AKM8975_H
+#define AKM8975_H
+
+#include <linux/ioctl.h>
+
+#define AK8975_MODE_SNG_MEASURE 0x01
+#define AK8975_MODE_SELF_TEST 0x08
+#define AK8975_MODE_FUSE_ACCESS 0x0F
+#define AK8975_MODE_POWER_DOWN 0x00
+
+#define RBUFF_SIZE 8  
+
+#define AK8975_REG_WIA 0x00
+#define AK8975_REG_INFO 0x01
+#define AK8975_REG_ST1 0x02
+#define AK8975_REG_HXL 0x03
+#define AK8975_REG_HXH 0x04
+#define AK8975_REG_HYL 0x05
+#define AK8975_REG_HYH 0x06
+#define AK8975_REG_HZL 0x07
+#define AK8975_REG_HZH 0x08
+#define AK8975_REG_ST2 0x09
+#define AK8975_REG_CNTL 0x0A
+#define AK8975_REG_RSV 0x0B
+#define AK8975_REG_ASTC 0x0C
+#define AK8975_REG_TS1 0x0D
+#define AK8975_REG_TS2 0x0E
+#define AK8975_REG_I2CDIS 0x0F
+
+#define AK8975_FUSE_ASAX 0x10
+#define AK8975_FUSE_ASAY 0x11
+#define AK8975_FUSE_ASAZ 0x12
+
+#define AKMIO 0xA1
+
+#define ECS_IOCTL_WRITE _IOW(AKMIO, 0x02, char[5])
+#define ECS_IOCTL_READ _IOWR(AKMIO, 0x03, char[5])
+#define ECS_IOCTL_GETDATA _IOR(AKMIO, 0x08, char[RBUFF_SIZE])
+#define ECS_IOCTL_SET_YPR _IOW(AKMIO, 0x0C, short[12])
+#define ECS_IOCTL_GET_OPEN_STATUS _IOR(AKMIO, 0x0D, int)
+#define ECS_IOCTL_GET_CLOSE_STATUS _IOR(AKMIO, 0x0E, int)
+#define ECS_IOCTL_GET_DELAY _IOR(AKMIO, 0x30, short)
+
+#define ECS_IOCTL_APP_SET_MFLAG _IOW(AKMIO, 0x11, short)
+#define ECS_IOCTL_APP_GET_MFLAG _IOW(AKMIO, 0x12, short)
+#define ECS_IOCTL_APP_SET_AFLAG _IOW(AKMIO, 0x13, short)
+#define ECS_IOCTL_APP_GET_AFLAG _IOR(AKMIO, 0x14, short)
+#define ECS_IOCTL_APP_SET_DELAY _IOW(AKMIO, 0x18, short)
+#define ECS_IOCTL_APP_GET_DELAY ECS_IOCTL_GET_DELAY
+#define ECS_IOCTL_APP_SET_MVFLAG _IOW(AKMIO, 0x19, short)  
+#define ECS_IOCTL_APP_GET_MVFLAG _IOR(AKMIO, 0x1A, short)  
+#define ECS_IOCTL_APP_SET_TFLAG _IOR(AKMIO, 0x15, short)
+
+#define ECS_INTR 140
+
+struct akm8975_platform_data {
+ int intr;
+};
+
+#endif
+
diff --git a/libc/kernel/common/linux/bmp085.h b/libc/kernel/common/linux/bmp085.h
new file mode 100644
index 0000000..650cb88
--- /dev/null
+++ b/libc/kernel/common/linux/bmp085.h
@@ -0,0 +1,29 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __BMP085_H__
+#define __BMP085_H__
+
+#include <linux/ioctl.h>  
+
+#define BMP085_NAME "bmp085"
+
+#define BMP085_IOCTL_BASE 78
+
+#define BMP085_IOCTL_SET_DELAY _IOW(BMP085_IOCTL_BASE, 0, int)
+#define BMP085_IOCTL_GET_DELAY _IOR(BMP085_IOCTL_BASE, 1, int)
+#define BMP085_IOCTL_SET_ENABLE _IOW(BMP085_IOCTL_BASE, 2, int)
+#define BMP085_IOCTL_GET_ENABLE _IOR(BMP085_IOCTL_BASE, 3, int)
+#define BMP085_IOCTL_ACCURACY _IOW(BMP085_IOCTL_BASE, 4, int)
+
+#endif
+
+
diff --git a/libc/kernel/common/linux/cpcap_audio.h b/libc/kernel/common/linux/cpcap_audio.h
new file mode 100644
index 0000000..a59550f
--- /dev/null
+++ b/libc/kernel/common/linux/cpcap_audio.h
@@ -0,0 +1,65 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _CPCAP_AUDIO_H
+#define _CPCAP_AUDIO_H
+
+#include <linux/ioctl.h>
+
+#define CPCAP_AUDIO_MAGIC 'c'
+
+#define CPCAP_AUDIO_OUT_SPEAKER 0
+#define CPCAP_AUDIO_OUT_HEADSET 1
+#define CPCAP_AUDIO_OUT_HEADSET_AND_SPEAKER 2
+#define CPCAP_AUDIO_OUT_STANDBY 3
+#define CPCAP_AUDIO_OUT_ANLG_DOCK_HEADSET 4
+#define CPCAP_AUDIO_OUT_MAX 4
+
+struct cpcap_audio_stream {
+ unsigned id;
+ int on;
+};
+
+#define CPCAP_AUDIO_OUT_SET_OUTPUT _IOW(CPCAP_AUDIO_MAGIC, 0,   const struct cpcap_audio_stream *)
+
+#define CPCAP_AUDIO_OUT_VOL_MIN 0
+#define CPCAP_AUDIO_OUT_VOL_MAX 15
+
+#define CPCAP_AUDIO_OUT_SET_VOLUME _IOW(CPCAP_AUDIO_MAGIC, 1, unsigned int)
+
+#define CPCAP_AUDIO_OUT_GET_OUTPUT   _IOR(CPCAP_AUDIO_MAGIC, 2, struct cpcap_audio_stream *)
+#define CPCAP_AUDIO_OUT_GET_VOLUME   _IOR(CPCAP_AUDIO_MAGIC, 3, unsigned int *)
+
+#define CPCAP_AUDIO_IN_MIC1 0
+#define CPCAP_AUDIO_IN_MIC2 1
+#define CPCAP_AUDIO_IN_STANDBY 2
+#define CPCAP_AUDIO_IN_MAX 2
+
+#define CPCAP_AUDIO_IN_SET_INPUT _IOW(CPCAP_AUDIO_MAGIC, 4,   const struct cpcap_audio_stream *)
+
+#define CPCAP_AUDIO_IN_GET_INPUT _IOR(CPCAP_AUDIO_MAGIC, 5,   struct cpcap_audio_stream *)
+
+#define CPCAP_AUDIO_IN_VOL_MIN 0
+#define CPCAP_AUDIO_IN_VOL_MAX 31
+
+#define CPCAP_AUDIO_IN_SET_VOLUME _IOW(CPCAP_AUDIO_MAGIC, 6, unsigned int)
+
+#define CPCAP_AUDIO_IN_GET_VOLUME _IOR(CPCAP_AUDIO_MAGIC, 7, unsigned int *)
+
+#define CPCAP_AUDIO_OUT_GET_RATE _IOR(CPCAP_AUDIO_MAGIC, 8, unsigned int *)
+#define CPCAP_AUDIO_OUT_SET_RATE _IOW(CPCAP_AUDIO_MAGIC, 9, unsigned int)
+#define CPCAP_AUDIO_IN_GET_RATE _IOR(CPCAP_AUDIO_MAGIC, 10, unsigned int *)
+#define CPCAP_AUDIO_IN_SET_RATE _IOW(CPCAP_AUDIO_MAGIC, 11, unsigned int)
+
+#define CPCAP_AUDIO_SET_BLUETOOTH_BYPASS _IOW(CPCAP_AUDIO_MAGIC, 12, unsigned int)
+
+#endif
+
diff --git a/libc/kernel/common/linux/genetlink.h b/libc/kernel/common/linux/genetlink.h
new file mode 100644
index 0000000..bc6042c
--- /dev/null
+++ b/libc/kernel/common/linux/genetlink.h
@@ -0,0 +1,94 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __LINUX_GENERIC_NETLINK_H
+#define __LINUX_GENERIC_NETLINK_H
+#include <linux/types.h>
+#include <linux/netlink.h>
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define GENL_NAMSIZ 16  
+#define GENL_MIN_ID NLMSG_MIN_TYPE
+#define GENL_MAX_ID 1023
+struct genlmsghdr {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u8 cmd;
+ __u8 version;
+ __u16 reserved;
+};
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define GENL_HDRLEN NLMSG_ALIGN(sizeof(struct genlmsghdr))
+#define GENL_ADMIN_PERM 0x01
+#define GENL_CMD_CAP_DO 0x02
+#define GENL_CMD_CAP_DUMP 0x04
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define GENL_CMD_CAP_HASPOL 0x08
+#define GENL_ID_GENERATE 0
+#define GENL_ID_CTRL NLMSG_MIN_TYPE
+enum {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ CTRL_CMD_UNSPEC,
+ CTRL_CMD_NEWFAMILY,
+ CTRL_CMD_DELFAMILY,
+ CTRL_CMD_GETFAMILY,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ CTRL_CMD_NEWOPS,
+ CTRL_CMD_DELOPS,
+ CTRL_CMD_GETOPS,
+ CTRL_CMD_NEWMCAST_GRP,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ CTRL_CMD_DELMCAST_GRP,
+ CTRL_CMD_GETMCAST_GRP,
+ __CTRL_CMD_MAX,
+};
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define CTRL_CMD_MAX (__CTRL_CMD_MAX - 1)
+enum {
+ CTRL_ATTR_UNSPEC,
+ CTRL_ATTR_FAMILY_ID,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ CTRL_ATTR_FAMILY_NAME,
+ CTRL_ATTR_VERSION,
+ CTRL_ATTR_HDRSIZE,
+ CTRL_ATTR_MAXATTR,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ CTRL_ATTR_OPS,
+ CTRL_ATTR_MCAST_GROUPS,
+ __CTRL_ATTR_MAX,
+};
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define CTRL_ATTR_MAX (__CTRL_ATTR_MAX - 1)
+enum {
+ CTRL_ATTR_OP_UNSPEC,
+ CTRL_ATTR_OP_ID,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ CTRL_ATTR_OP_FLAGS,
+ __CTRL_ATTR_OP_MAX,
+};
+#define CTRL_ATTR_OP_MAX (__CTRL_ATTR_OP_MAX - 1)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+enum {
+ CTRL_ATTR_MCAST_GRP_UNSPEC,
+ CTRL_ATTR_MCAST_GRP_NAME,
+ CTRL_ATTR_MCAST_GRP_ID,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __CTRL_ATTR_MCAST_GRP_MAX,
+};
+#define CTRL_ATTR_MCAST_GRP_MAX (__CTRL_ATTR_MCAST_GRP_MAX - 1)
+#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+
diff --git a/libc/kernel/common/linux/hid.h b/libc/kernel/common/linux/hid.h
new file mode 100644
index 0000000..450db19
--- /dev/null
+++ b/libc/kernel/common/linux/hid.h
@@ -0,0 +1,36 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __HID_H
+#define __HID_H
+
+#define USB_INTERFACE_CLASS_HID 3
+
+#define USB_INTERFACE_SUBCLASS_BOOT 1
+#define USB_INTERFACE_PROTOCOL_KEYBOARD 1
+#define USB_INTERFACE_PROTOCOL_MOUSE 2
+
+#define HID_REQ_GET_REPORT 0x01
+#define HID_REQ_GET_IDLE 0x02
+#define HID_REQ_GET_PROTOCOL 0x03
+#define HID_REQ_SET_REPORT 0x09
+#define HID_REQ_SET_IDLE 0x0A
+#define HID_REQ_SET_PROTOCOL 0x0B
+
+#define HID_DT_HID (USB_TYPE_CLASS | 0x01)
+#define HID_DT_REPORT (USB_TYPE_CLASS | 0x02)
+#define HID_DT_PHYSICAL (USB_TYPE_CLASS | 0x03)
+
+#define HID_MAX_DESCRIPTOR_SIZE 4096
+
+#endif
+
+
diff --git a/libc/kernel/common/linux/hidraw.h b/libc/kernel/common/linux/hidraw.h
new file mode 100644
index 0000000..0681ece
--- /dev/null
+++ b/libc/kernel/common/linux/hidraw.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _HIDRAW_H
+#define _HIDRAW_H
+
+#include <linux/hid.h>
+#include <linux/types.h>
+
+struct hidraw_report_descriptor {
+ __u32 size;
+ __u8 value[HID_MAX_DESCRIPTOR_SIZE];
+};
+
+struct hidraw_devinfo {
+ __u32 bustype;
+ __s16 vendor;
+ __s16 product;
+};
+
+#define HIDIOCGRDESCSIZE _IOR('H', 0x01, int)
+#define HIDIOCGRDESC _IOR('H', 0x02, struct hidraw_report_descriptor)
+#define HIDIOCGRAWINFO _IOR('H', 0x03, struct hidraw_devinfo)
+#define HIDIOCGRAWNAME(len) _IOC(_IOC_READ, 'H', 0x04, len)
+#define HIDIOCGRAWPHYS(len) _IOC(_IOC_READ, 'H', 0x05, len)
+
+#define HIDRAW_FIRST_MINOR 0
+#define HIDRAW_MAX_DEVICES 64
+
+#define HIDRAW_BUFFER_SIZE 64
+
+#endif
+
diff --git a/libc/kernel/common/linux/if.h b/libc/kernel/common/linux/if.h
index 47c29d9..7db4888 100644
--- a/libc/kernel/common/linux/if.h
+++ b/libc/kernel/common/linux/if.h
@@ -17,6 +17,7 @@
 #include <linux/compiler.h>  
 
 #define IFNAMSIZ 16
+#define IFALIASZ 256
 #include <linux/hdlc/ioctl.h>
 
 #define IFF_UP 0x1  
@@ -42,13 +43,24 @@
 #define IFF_LOWER_UP 0x10000  
 #define IFF_DORMANT 0x20000  
 
-#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|  IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT)
+#define IFF_ECHO 0x40000  
+
+#define IFF_VOLATILE (IFF_LOOPBACK|IFF_POINTOPOINT|IFF_BROADCAST|IFF_ECHO|  IFF_MASTER|IFF_SLAVE|IFF_RUNNING|IFF_LOWER_UP|IFF_DORMANT)
 
 #define IFF_802_1Q_VLAN 0x1  
 #define IFF_EBRIDGE 0x2  
 #define IFF_SLAVE_INACTIVE 0x4  
 #define IFF_MASTER_8023AD 0x8  
 #define IFF_MASTER_ALB 0x10  
+#define IFF_BONDING 0x20  
+#define IFF_SLAVE_NEEDARP 0x40  
+#define IFF_ISATAP 0x80  
+#define IFF_MASTER_ARPMON 0x100  
+#define IFF_WAN_HDLC 0x200  
+#define IFF_XMIT_DST_RELEASE 0x400  
+#define IFF_DONT_BRIDGE 0x800  
+#define IFF_IN_NETPOLL 0x1000  
+#define IFF_DISABLE_NETPOLL 0x2000  
 
 #define IF_GET_IFACE 0x0001  
 #define IF_GET_PROTO 0x0002
@@ -90,8 +102,7 @@
  IF_LINK_MODE_DORMANT,
 };
 
-struct ifmap
-{
+struct ifmap {
  unsigned long mem_start;
  unsigned long mem_end;
  unsigned short base_addr;
@@ -101,8 +112,7 @@
 
 };
 
-struct if_settings
-{
+struct if_settings {
  unsigned int type;
  unsigned int size;
  union {
@@ -118,8 +128,7 @@
  } ifs_ifsu;
 };
 
-struct ifreq
-{
+struct ifreq {
 #define IFHWADDRLEN 6
  union
  {
@@ -161,11 +170,9 @@
 #define ifr_newname ifr_ifru.ifru_newname  
 #define ifr_settings ifr_ifru.ifru_settings  
 
-struct ifconf
-{
+struct ifconf {
  int ifc_len;
- union
- {
+ union {
  char __user *ifcu_buf;
  struct ifreq __user *ifcu_req;
  } ifc_ifcu;
@@ -174,3 +181,4 @@
 #define ifc_req ifc_ifcu.ifcu_req  
 
 #endif
+
diff --git a/libc/kernel/common/linux/if_arp.h b/libc/kernel/common/linux/if_arp.h
index a3df6c8..d8a4001 100644
--- a/libc/kernel/common/linux/if_arp.h
+++ b/libc/kernel/common/linux/if_arp.h
@@ -77,6 +77,7 @@
 
 #define ARPHRD_PHONET 820  
 #define ARPHRD_PHONET_PIPE 821  
+#define ARPHRD_CAIF 822  
 
 #define ARPHRD_VOID 0xFFFF  
 #define ARPHRD_NONE 0xFFFE  
@@ -111,8 +112,7 @@
 #define ATF_NETMASK 0x20  
 #define ATF_DONTPUB 0x40  
 
-struct arphdr
-{
+struct arphdr {
  __be16 ar_hrd;
  __be16 ar_pro;
  unsigned char ar_hln;
@@ -122,3 +122,4 @@
 };
 
 #endif
+
diff --git a/libc/kernel/common/linux/if_link.h b/libc/kernel/common/linux/if_link.h
index e9d77d4..4b83760 100644
--- a/libc/kernel/common/linux/if_link.h
+++ b/libc/kernel/common/linux/if_link.h
@@ -15,8 +15,7 @@
 #include <linux/types.h>
 #include <linux/netlink.h>
 
-struct rtnl_link_stats
-{
+struct rtnl_link_stats {
  __u32 rx_packets;
  __u32 tx_packets;
  __u32 rx_bytes;
@@ -45,8 +44,36 @@
  __u32 tx_compressed;
 };
 
-struct rtnl_link_ifmap
-{
+struct rtnl_link_stats64 {
+ __u64 rx_packets;
+ __u64 tx_packets;
+ __u64 rx_bytes;
+ __u64 tx_bytes;
+ __u64 rx_errors;
+ __u64 tx_errors;
+ __u64 rx_dropped;
+ __u64 tx_dropped;
+ __u64 multicast;
+ __u64 collisions;
+
+ __u64 rx_length_errors;
+ __u64 rx_over_errors;
+ __u64 rx_crc_errors;
+ __u64 rx_frame_errors;
+ __u64 rx_fifo_errors;
+ __u64 rx_missed_errors;
+
+ __u64 tx_aborted_errors;
+ __u64 tx_carrier_errors;
+ __u64 tx_fifo_errors;
+ __u64 tx_heartbeat_errors;
+ __u64 tx_window_errors;
+
+ __u64 rx_compressed;
+ __u64 tx_compressed;
+};
+
+struct rtnl_link_ifmap {
  __u64 mem_start;
  __u64 mem_end;
  __u64 base_addr;
@@ -55,8 +82,7 @@
  __u8 port;
 };
 
-enum
-{
+enum {
  IFLA_UNSPEC,
  IFLA_ADDRESS,
  IFLA_BROADCAST,
@@ -87,6 +113,11 @@
 #define IFLA_LINKINFO IFLA_LINKINFO
  IFLA_NET_NS_PID,
  IFLA_IFALIAS,
+ IFLA_NUM_VF,
+ IFLA_VFINFO_LIST,
+ IFLA_STATS64,
+ IFLA_VF_PORTS,
+ IFLA_PORT_SELF,
  __IFLA_MAX
 };
 
@@ -95,8 +126,7 @@
 #define IFLA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct ifinfomsg))))
 #define IFLA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct ifinfomsg))
 
-enum
-{
+enum {
  IFLA_INET6_UNSPEC,
  IFLA_INET6_FLAGS,
  IFLA_INET6_CONF,
@@ -109,16 +139,14 @@
 
 #define IFLA_INET6_MAX (__IFLA_INET6_MAX - 1)
 
-struct ifla_cacheinfo
-{
+struct ifla_cacheinfo {
  __u32 max_reasm_len;
  __u32 tstamp;
  __u32 reachable_time;
  __u32 retrans_time;
 };
 
-enum
-{
+enum {
  IFLA_INFO_UNSPEC,
  IFLA_INFO_KIND,
  IFLA_INFO_DATA,
@@ -128,8 +156,7 @@
 
 #define IFLA_INFO_MAX (__IFLA_INFO_MAX - 1)
 
-enum
-{
+enum {
  IFLA_VLAN_UNSPEC,
  IFLA_VLAN_ID,
  IFLA_VLAN_FLAGS,
@@ -145,8 +172,7 @@
  __u32 mask;
 };
 
-enum
-{
+enum {
  IFLA_VLAN_QOS_UNSPEC,
  IFLA_VLAN_QOS_MAPPING,
  __IFLA_VLAN_QOS_MAX
@@ -154,10 +180,123 @@
 
 #define IFLA_VLAN_QOS_MAX (__IFLA_VLAN_QOS_MAX - 1)
 
-struct ifla_vlan_qos_mapping
-{
+struct ifla_vlan_qos_mapping {
  __u32 from;
  __u32 to;
 };
 
+enum {
+ IFLA_MACVLAN_UNSPEC,
+ IFLA_MACVLAN_MODE,
+ __IFLA_MACVLAN_MAX,
+};
+
+#define IFLA_MACVLAN_MAX (__IFLA_MACVLAN_MAX - 1)
+
+enum macvlan_mode {
+ MACVLAN_MODE_PRIVATE = 1,
+ MACVLAN_MODE_VEPA = 2,
+ MACVLAN_MODE_BRIDGE = 4,
+};
+
+enum {
+ IFLA_VF_INFO_UNSPEC,
+ IFLA_VF_INFO,
+ __IFLA_VF_INFO_MAX,
+};
+
+#define IFLA_VF_INFO_MAX (__IFLA_VF_INFO_MAX - 1)
+
+enum {
+ IFLA_VF_UNSPEC,
+ IFLA_VF_MAC,
+ IFLA_VF_VLAN,
+ IFLA_VF_TX_RATE,
+ __IFLA_VF_MAX,
+};
+
+#define IFLA_VF_MAX (__IFLA_VF_MAX - 1)
+
+struct ifla_vf_mac {
+ __u32 vf;
+ __u8 mac[32];
+};
+
+struct ifla_vf_vlan {
+ __u32 vf;
+ __u32 vlan;
+ __u32 qos;
+};
+
+struct ifla_vf_tx_rate {
+ __u32 vf;
+ __u32 rate;
+};
+
+struct ifla_vf_info {
+ __u32 vf;
+ __u8 mac[32];
+ __u32 vlan;
+ __u32 qos;
+ __u32 tx_rate;
+};
+
+enum {
+ IFLA_VF_PORT_UNSPEC,
+ IFLA_VF_PORT,
+ __IFLA_VF_PORT_MAX,
+};
+
+#define IFLA_VF_PORT_MAX (__IFLA_VF_PORT_MAX - 1)
+
+enum {
+ IFLA_PORT_UNSPEC,
+ IFLA_PORT_VF,
+ IFLA_PORT_PROFILE,
+ IFLA_PORT_VSI_TYPE,
+ IFLA_PORT_INSTANCE_UUID,
+ IFLA_PORT_HOST_UUID,
+ IFLA_PORT_REQUEST,
+ IFLA_PORT_RESPONSE,
+ __IFLA_PORT_MAX,
+};
+
+#define IFLA_PORT_MAX (__IFLA_PORT_MAX - 1)
+
+#define PORT_PROFILE_MAX 40
+#define PORT_UUID_MAX 16
+#define PORT_SELF_VF -1
+
+enum {
+ PORT_REQUEST_PREASSOCIATE = 0,
+ PORT_REQUEST_PREASSOCIATE_RR,
+ PORT_REQUEST_ASSOCIATE,
+ PORT_REQUEST_DISASSOCIATE,
+};
+
+enum {
+ PORT_VDP_RESPONSE_SUCCESS = 0,
+ PORT_VDP_RESPONSE_INVALID_FORMAT,
+ PORT_VDP_RESPONSE_INSUFFICIENT_RESOURCES,
+ PORT_VDP_RESPONSE_UNUSED_VTID,
+ PORT_VDP_RESPONSE_VTID_VIOLATION,
+ PORT_VDP_RESPONSE_VTID_VERSION_VIOALTION,
+ PORT_VDP_RESPONSE_OUT_OF_SYNC,
+
+ PORT_PROFILE_RESPONSE_SUCCESS = 0x100,
+ PORT_PROFILE_RESPONSE_INPROGRESS,
+ PORT_PROFILE_RESPONSE_INVALID,
+ PORT_PROFILE_RESPONSE_BADSTATE,
+ PORT_PROFILE_RESPONSE_INSUFFICIENT_RESOURCES,
+ PORT_PROFILE_RESPONSE_ERROR,
+};
+
+struct ifla_port_vsi {
+ __u8 vsi_mgr_id;
+ __u8 vsi_type_id[3];
+ __u8 vsi_type_version;
+ __u8 pad[3];
+};
+
 #endif
+
diff --git a/libc/kernel/common/linux/if_tun.h b/libc/kernel/common/linux/if_tun.h
index c5db4e0..9ed49f1 100644
--- a/libc/kernel/common/linux/if_tun.h
+++ b/libc/kernel/common/linux/if_tun.h
@@ -12,6 +12,10 @@
 #ifndef __IF_TUN_H
 #define __IF_TUN_H
 
+#include <linux/types.h>
+#include <linux/if_ether.h>
+#include <linux/filter.h>
+
 #define TUN_READQ_SIZE 500
 
 #define TUN_TUN_DEV 0x0001 
@@ -23,6 +27,7 @@
 #define TUN_NO_PI 0x0040
 #define TUN_ONE_QUEUE 0x0080
 #define TUN_PERSIST 0x0100 
+#define TUN_VNET_HDR 0x0200
 
 #define TUNSETNOCSUM _IOW('T', 200, int) 
 #define TUNSETDEBUG _IOW('T', 201, int) 
@@ -30,16 +35,43 @@
 #define TUNSETPERSIST _IOW('T', 203, int) 
 #define TUNSETOWNER _IOW('T', 204, int)
 #define TUNSETLINK _IOW('T', 205, int)
+#define TUNSETGROUP _IOW('T', 206, int)
+#define TUNGETFEATURES _IOR('T', 207, unsigned int)
+#define TUNSETOFFLOAD _IOW('T', 208, unsigned int)
+#define TUNSETTXFILTER _IOW('T', 209, unsigned int)
+#define TUNGETIFF _IOR('T', 210, unsigned int)
+#define TUNGETSNDBUF _IOR('T', 211, int)
+#define TUNSETSNDBUF _IOW('T', 212, int)
+#define TUNATTACHFILTER _IOW('T', 213, struct sock_fprog)
+#define TUNDETACHFILTER _IOW('T', 214, struct sock_fprog)
+#define TUNGETVNETHDRSZ _IOR('T', 215, int)
+#define TUNSETVNETHDRSZ _IOW('T', 216, int)
 
 #define IFF_TUN 0x0001
 #define IFF_TAP 0x0002
 #define IFF_NO_PI 0x1000
 #define IFF_ONE_QUEUE 0x2000
+#define IFF_VNET_HDR 0x4000
+#define IFF_TUN_EXCL 0x8000
 
-struct tun_pi {
- unsigned short flags;
- unsigned short proto;
-};
+#define TUN_F_CSUM 0x01  
+#define TUN_F_TSO4 0x02  
+#define TUN_F_TSO6 0x04  
+#define TUN_F_TSO_ECN 0x08  
+#define TUN_F_UFO 0x10  
+
 #define TUN_PKT_STRIP 0x0001
+struct tun_pi {
+ __u16 flags;
+ __be16 proto;
+};
+
+#define TUN_FLT_ALLMULTI 0x0001  
+struct tun_filter {
+ __u16 flags;
+ __u16 count;
+ __u8 addr[0][ETH_ALEN];
+};
 
 #endif
+
diff --git a/libc/kernel/common/linux/if_vlan.h b/libc/kernel/common/linux/if_vlan.h
index d3d2df2..ab3b174 100644
--- a/libc/kernel/common/linux/if_vlan.h
+++ b/libc/kernel/common/linux/if_vlan.h
@@ -25,6 +25,12 @@
  GET_VLAN_VID_CMD
 };
 
+enum vlan_flags {
+ VLAN_FLAG_REORDER_HDR = 0x1,
+ VLAN_FLAG_GVRP = 0x2,
+ VLAN_FLAG_LOOSE_BINDING = 0x4,
+};
+
 enum vlan_name_types {
  VLAN_NAME_TYPE_PLUS_VID,
  VLAN_NAME_TYPE_RAW_PLUS_VID,
@@ -50,3 +56,4 @@
 };
 
 #endif
+
diff --git a/libc/kernel/common/linux/in_route.h b/libc/kernel/common/linux/in_route.h
new file mode 100644
index 0000000..34e14d6
--- /dev/null
+++ b/libc/kernel/common/linux/in_route.h
@@ -0,0 +1,41 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _LINUX_IN_ROUTE_H
+#define _LINUX_IN_ROUTE_H
+
+#define RTCF_DEAD RTNH_F_DEAD
+#define RTCF_ONLINK RTNH_F_ONLINK
+
+#define RTCF_NOPMTUDISC RTM_F_NOPMTUDISC
+
+#define RTCF_NOTIFY 0x00010000
+#define RTCF_DIRECTDST 0x00020000  
+#define RTCF_REDIRECTED 0x00040000
+#define RTCF_TPROXY 0x00080000  
+
+#define RTCF_FAST 0x00200000  
+#define RTCF_MASQ 0x00400000  
+#define RTCF_SNAT 0x00800000  
+#define RTCF_DOREDIRECT 0x01000000
+#define RTCF_DIRECTSRC 0x04000000
+#define RTCF_DNAT 0x08000000
+#define RTCF_BROADCAST 0x10000000
+#define RTCF_MULTICAST 0x20000000
+#define RTCF_REJECT 0x40000000  
+#define RTCF_LOCAL 0x80000000
+
+#define RTCF_NAT (RTCF_DNAT|RTCF_SNAT)
+
+#define RT_TOS(tos) ((tos)&IPTOS_TOS_MASK)
+
+#endif
+
diff --git a/libc/kernel/common/linux/ipv6_route.h b/libc/kernel/common/linux/ipv6_route.h
new file mode 100644
index 0000000..3791e87
--- /dev/null
+++ b/libc/kernel/common/linux/ipv6_route.h
@@ -0,0 +1,55 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _LINUX_IPV6_ROUTE_H
+#define _LINUX_IPV6_ROUTE_H
+
+#include <linux/types.h>
+
+#define RTF_DEFAULT 0x00010000  
+#define RTF_ALLONLINK 0x00020000  
+#define RTF_ADDRCONF 0x00040000  
+#define RTF_PREFIX_RT 0x00080000  
+#define RTF_ANYCAST 0x00100000  
+
+#define RTF_NONEXTHOP 0x00200000  
+#define RTF_EXPIRES 0x00400000
+
+#define RTF_ROUTEINFO 0x00800000  
+
+#define RTF_CACHE 0x01000000  
+#define RTF_FLOW 0x02000000  
+#define RTF_POLICY 0x04000000  
+
+#define RTF_PREF(pref) ((pref) << 27)
+#define RTF_PREF_MASK 0x18000000
+
+#define RTF_LOCAL 0x80000000
+
+struct in6_rtmsg {
+ struct in6_addr rtmsg_dst;
+ struct in6_addr rtmsg_src;
+ struct in6_addr rtmsg_gateway;
+ __u32 rtmsg_type;
+ __u16 rtmsg_dst_len;
+ __u16 rtmsg_src_len;
+ __u32 rtmsg_metric;
+ unsigned long rtmsg_info;
+ __u32 rtmsg_flags;
+ int rtmsg_ifindex;
+};
+
+#define RTMSG_NEWDEVICE 0x11
+#define RTMSG_DELDEVICE 0x12
+#define RTMSG_NEWROUTE 0x21
+#define RTMSG_DELROUTE 0x22
+
+#endif
diff --git a/libc/kernel/common/linux/kxtf9.h b/libc/kernel/common/linux/kxtf9.h
new file mode 100644
index 0000000..9141364
--- /dev/null
+++ b/libc/kernel/common/linux/kxtf9.h
@@ -0,0 +1,70 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __KXTF9_H__
+#define __KXTF9_H__
+
+#include <linux/ioctl.h>  
+
+#define KXTF9_IOCTL_BASE 77
+
+#define KXTF9_IOCTL_SET_DELAY _IOW(KXTF9_IOCTL_BASE, 0, int)
+#define KXTF9_IOCTL_GET_DELAY _IOR(KXTF9_IOCTL_BASE, 1, int)
+#define KXTF9_IOCTL_SET_ENABLE _IOW(KXTF9_IOCTL_BASE, 2, int)
+#define KXTF9_IOCTL_GET_ENABLE _IOR(KXTF9_IOCTL_BASE, 3, int)
+#define KXTF9_IOCTL_SET_G_RANGE _IOW(KXTF9_IOCTL_BASE, 4, int)
+
+#define KXTF9_IOCTL_SET_TILT_ENABLE _IOW(KXTF9_IOCTL_BASE, 5, int)
+#define KXTF9_IOCTL_SET_TAP_ENABLE _IOW(KXTF9_IOCTL_BASE, 6, int)
+#define KXTF9_IOCTL_SET_WAKE_ENABLE _IOW(KXTF9_IOCTL_BASE, 7, int)
+#define KXTF9_IOCTL_SET_PM_MODE _IOW(KXTF9_IOCTL_BASE, 8, int)
+#define KXTF9_IOCTL_SELF_TEST _IOW(KXTF9_IOCTL_BASE, 9, int)
+#define KXTF9_IOCTL_SET_SENSITIVITY _IOW(KXTF9_IOCTL_BASE, 10, int)
+
+#define RES_12BIT 0x40
+#define KXTF9_G_2G 0x00
+#define KXTF9_G_4G 0x08
+#define KXTF9_G_8G 0x10
+#define TPE 0x01  
+#define WUFE 0x02  
+#define TDTE 0x04  
+
+#define OTP1_6 0x00  
+#define OTP6_3 0x20
+#define OTP12_5 0x40
+#define OTP50 0x60
+#define OWUF25 0x00  
+#define OWUF50 0x01
+#define OWUF100 0x02
+#define OWUF200 0x03
+#define OTDT50 0x00  
+#define OTDT100 0x04
+#define OTDT200 0x08
+#define OTDT400 0x0C
+
+#define IEN 0x20  
+#define IEA 0x10  
+#define IEL 0x08  
+#define IEU 0x04  
+
+#define ODR800 0x06  
+#define ODR400 0x05
+#define ODR200 0x04
+#define ODR100 0x03
+#define ODR50 0x02
+#define ODR25 0x01
+#define ODR12_5 0x00
+
+#define SENSITIVITY_REGS 0x07
+
+#endif
+
+
diff --git a/libc/kernel/common/linux/l3g4200d.h b/libc/kernel/common/linux/l3g4200d.h
new file mode 100644
index 0000000..0a0f8cd
--- /dev/null
+++ b/libc/kernel/common/linux/l3g4200d.h
@@ -0,0 +1,27 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __L3G4200D_H__
+#define __L3G4200D_H__
+
+#include <linux/ioctl.h>  
+
+#define L3G4200D_NAME "l3g4200d"
+
+#define L3G4200D_IOCTL_BASE 77
+
+#define L3G4200D_IOCTL_SET_DELAY _IOW(L3G4200D_IOCTL_BASE, 0, int)
+#define L3G4200D_IOCTL_GET_DELAY _IOR(L3G4200D_IOCTL_BASE, 1, int)
+#define L3G4200D_IOCTL_SET_ENABLE _IOW(L3G4200D_IOCTL_BASE, 2, int)
+#define L3G4200D_IOCTL_GET_ENABLE _IOR(L3G4200D_IOCTL_BASE, 3, int)
+
+#endif
+
diff --git a/libc/kernel/common/linux/max9635.h b/libc/kernel/common/linux/max9635.h
new file mode 100644
index 0000000..e696fa9
--- /dev/null
+++ b/libc/kernel/common/linux/max9635.h
@@ -0,0 +1,23 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _LINUX_MAX9635_H__
+#define _LINUX_MAX9635_H__
+
+#define MAX9635_NAME "MAX9635_als"
+#define FOPS_MAX9635_NAME "MAX9635"
+
+#define MAX9635_IO 0xA3
+
+#define MAX9635_IOCTL_GET_ENABLE _IOR(MAX9635_IO, 0x00, char)
+#define MAX9635_IOCTL_SET_ENABLE _IOW(MAX9635_IO, 0x01, char)
+
+#endif
diff --git a/libc/kernel/common/linux/netfilter.h b/libc/kernel/common/linux/netfilter.h
index 0488344..ce8d394 100644
--- a/libc/kernel/common/linux/netfilter.h
+++ b/libc/kernel/common/linux/netfilter.h
@@ -7,30 +7,66 @@
  ***   structures, and macros generated from the original header, and thus,
  ***   contains no copyrightable information.
  ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
  ****************************************************************************
  ****************************************************************************/
 #ifndef __LINUX_NETFILTER_H
 #define __LINUX_NETFILTER_H
-
+#include <linux/types.h>
 #include <linux/compiler.h>
-
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define NF_DROP 0
 #define NF_ACCEPT 1
 #define NF_STOLEN 2
 #define NF_QUEUE 3
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define NF_REPEAT 4
 #define NF_STOP 5
 #define NF_MAX_VERDICT NF_STOP
-
 #define NF_VERDICT_MASK 0x0000ffff
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define NF_VERDICT_BITS 16
-
 #define NF_VERDICT_QMASK 0xffff0000
 #define NF_VERDICT_QBITS 16
-
-#define NF_QUEUE_NR(x) (((x << NF_VERDICT_QBITS) & NF_VERDICT_QMASK) | NF_QUEUE)
-
+#define NF_QUEUE_NR(x) ((((x) << NF_VERDICT_BITS) & NF_VERDICT_QMASK) | NF_QUEUE)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define NFC_UNKNOWN 0x4000
 #define NFC_ALTERED 0x8000
-
+enum nf_inet_hooks {
+ NF_INET_PRE_ROUTING,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ NF_INET_LOCAL_IN,
+ NF_INET_FORWARD,
+ NF_INET_LOCAL_OUT,
+ NF_INET_POST_ROUTING,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ NF_INET_NUMHOOKS
+};
+enum {
+ NFPROTO_UNSPEC = 0,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ NFPROTO_IPV4 = 2,
+ NFPROTO_ARP = 3,
+ NFPROTO_BRIDGE = 7,
+ NFPROTO_IPV6 = 10,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ NFPROTO_DECNET = 12,
+ NFPROTO_NUMPROTO,
+};
+union nf_inet_addr {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ __u32 all[4];
+ __be32 ip;
+ __be32 ip6[4];
+ struct in_addr in;
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ struct in6_addr in6;
+};
 #endif
+
diff --git a/libc/kernel/common/linux/netfilter/nfnetlink_conntrack.h b/libc/kernel/common/linux/netfilter/nfnetlink_conntrack.h
index 105dd09..0b1b356 100644
--- a/libc/kernel/common/linux/netfilter/nfnetlink_conntrack.h
+++ b/libc/kernel/common/linux/netfilter/nfnetlink_conntrack.h
@@ -7,140 +7,206 @@
  ***   structures, and macros generated from the original header, and thus,
  ***   contains no copyrightable information.
  ***
+ ***   To edit the content of this header, modify the corresponding
+ ***   source file (e.g. under external/kernel-headers/original/) then
+ ***   run bionic/libc/kernel/tools/update_all.py
+ ***
+ ***   Any manual change here will be lost the next time this script will
+ ***   be run. You've been warned!
+ ***
  ****************************************************************************
  ****************************************************************************/
 #ifndef _IPCONNTRACK_NETLINK_H
 #define _IPCONNTRACK_NETLINK_H
 #include <linux/netfilter/nfnetlink.h>
-
 enum cntl_msg_types {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  IPCTNL_MSG_CT_NEW,
  IPCTNL_MSG_CT_GET,
  IPCTNL_MSG_CT_DELETE,
  IPCTNL_MSG_CT_GET_CTRZERO,
-
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  IPCTNL_MSG_MAX
 };
-
 enum ctnl_exp_msg_types {
  IPCTNL_MSG_EXP_NEW,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  IPCTNL_MSG_EXP_GET,
  IPCTNL_MSG_EXP_DELETE,
-
  IPCTNL_MSG_EXP_MAX
 };
-
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 enum ctattr_type {
  CTA_UNSPEC,
  CTA_TUPLE_ORIG,
  CTA_TUPLE_REPLY,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  CTA_STATUS,
  CTA_PROTOINFO,
  CTA_HELP,
  CTA_NAT_SRC,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define CTA_NAT CTA_NAT_SRC  
  CTA_TIMEOUT,
  CTA_MARK,
  CTA_COUNTERS_ORIG,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  CTA_COUNTERS_REPLY,
  CTA_USE,
  CTA_ID,
  CTA_NAT_DST,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ CTA_TUPLE_MASTER,
+ CTA_NAT_SEQ_ADJ_ORIG,
+ CTA_NAT_SEQ_ADJ_REPLY,
+ CTA_SECMARK,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ CTA_ZONE,
  __CTA_MAX
 };
 #define CTA_MAX (__CTA_MAX - 1)
-
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 enum ctattr_tuple {
  CTA_TUPLE_UNSPEC,
  CTA_TUPLE_IP,
  CTA_TUPLE_PROTO,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  __CTA_TUPLE_MAX
 };
 #define CTA_TUPLE_MAX (__CTA_TUPLE_MAX - 1)
-
 enum ctattr_ip {
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  CTA_IP_UNSPEC,
  CTA_IP_V4_SRC,
  CTA_IP_V4_DST,
  CTA_IP_V6_SRC,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  CTA_IP_V6_DST,
  __CTA_IP_MAX
 };
 #define CTA_IP_MAX (__CTA_IP_MAX - 1)
-
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 enum ctattr_l4proto {
  CTA_PROTO_UNSPEC,
  CTA_PROTO_NUM,
  CTA_PROTO_SRC_PORT,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  CTA_PROTO_DST_PORT,
  CTA_PROTO_ICMP_ID,
  CTA_PROTO_ICMP_TYPE,
  CTA_PROTO_ICMP_CODE,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  CTA_PROTO_ICMPV6_ID,
  CTA_PROTO_ICMPV6_TYPE,
  CTA_PROTO_ICMPV6_CODE,
  __CTA_PROTO_MAX
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 };
 #define CTA_PROTO_MAX (__CTA_PROTO_MAX - 1)
-
 enum ctattr_protoinfo {
  CTA_PROTOINFO_UNSPEC,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  CTA_PROTOINFO_TCP,
+ CTA_PROTOINFO_DCCP,
+ CTA_PROTOINFO_SCTP,
  __CTA_PROTOINFO_MAX
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 };
 #define CTA_PROTOINFO_MAX (__CTA_PROTOINFO_MAX - 1)
-
 enum ctattr_protoinfo_tcp {
  CTA_PROTOINFO_TCP_UNSPEC,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  CTA_PROTOINFO_TCP_STATE,
+ CTA_PROTOINFO_TCP_WSCALE_ORIGINAL,
+ CTA_PROTOINFO_TCP_WSCALE_REPLY,
+ CTA_PROTOINFO_TCP_FLAGS_ORIGINAL,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ CTA_PROTOINFO_TCP_FLAGS_REPLY,
  __CTA_PROTOINFO_TCP_MAX
 };
 #define CTA_PROTOINFO_TCP_MAX (__CTA_PROTOINFO_TCP_MAX - 1)
-
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+enum ctattr_protoinfo_dccp {
+ CTA_PROTOINFO_DCCP_UNSPEC,
+ CTA_PROTOINFO_DCCP_STATE,
+ CTA_PROTOINFO_DCCP_ROLE,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ CTA_PROTOINFO_DCCP_HANDSHAKE_SEQ,
+ __CTA_PROTOINFO_DCCP_MAX,
+};
+#define CTA_PROTOINFO_DCCP_MAX (__CTA_PROTOINFO_DCCP_MAX - 1)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+enum ctattr_protoinfo_sctp {
+ CTA_PROTOINFO_SCTP_UNSPEC,
+ CTA_PROTOINFO_SCTP_STATE,
+ CTA_PROTOINFO_SCTP_VTAG_ORIGINAL,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ CTA_PROTOINFO_SCTP_VTAG_REPLY,
+ __CTA_PROTOINFO_SCTP_MAX
+};
+#define CTA_PROTOINFO_SCTP_MAX (__CTA_PROTOINFO_SCTP_MAX - 1)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 enum ctattr_counters {
  CTA_COUNTERS_UNSPEC,
  CTA_COUNTERS_PACKETS,
  CTA_COUNTERS_BYTES,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  CTA_COUNTERS32_PACKETS,
  CTA_COUNTERS32_BYTES,
  __CTA_COUNTERS_MAX
 };
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define CTA_COUNTERS_MAX (__CTA_COUNTERS_MAX - 1)
-
 enum ctattr_nat {
  CTA_NAT_UNSPEC,
  CTA_NAT_MINIP,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  CTA_NAT_MAXIP,
  CTA_NAT_PROTO,
  __CTA_NAT_MAX
 };
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 #define CTA_NAT_MAX (__CTA_NAT_MAX - 1)
-
 enum ctattr_protonat {
  CTA_PROTONAT_UNSPEC,
  CTA_PROTONAT_PORT_MIN,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  CTA_PROTONAT_PORT_MAX,
  __CTA_PROTONAT_MAX
 };
 #define CTA_PROTONAT_MAX (__CTA_PROTONAT_MAX - 1)
-
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+enum ctattr_natseq {
+ CTA_NAT_SEQ_UNSPEC,
+ CTA_NAT_SEQ_CORRECTION_POS,
+ CTA_NAT_SEQ_OFFSET_BEFORE,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ CTA_NAT_SEQ_OFFSET_AFTER,
+ __CTA_NAT_SEQ_MAX
+};
+#define CTA_NAT_SEQ_MAX (__CTA_NAT_SEQ_MAX - 1)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 enum ctattr_expect {
  CTA_EXPECT_UNSPEC,
  CTA_EXPECT_MASTER,
  CTA_EXPECT_TUPLE,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
  CTA_EXPECT_MASK,
  CTA_EXPECT_TIMEOUT,
  CTA_EXPECT_ID,
  CTA_EXPECT_HELP_NAME,
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+ CTA_EXPECT_ZONE,
  __CTA_EXPECT_MAX
 };
 #define CTA_EXPECT_MAX (__CTA_EXPECT_MAX - 1)
-
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 enum ctattr_help {
  CTA_HELP_UNSPEC,
  CTA_HELP_NAME,
  __CTA_HELP_MAX
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
 };
 #define CTA_HELP_MAX (__CTA_HELP_MAX - 1)
-
 #endif
+
diff --git a/libc/kernel/common/linux/netfilter_ipv6/ip6_tables.h b/libc/kernel/common/linux/netfilter_ipv6/ip6_tables.h
index 1687e4f..d76a529 100644
--- a/libc/kernel/common/linux/netfilter_ipv6/ip6_tables.h
+++ b/libc/kernel/common/linux/netfilter_ipv6/ip6_tables.h
@@ -173,6 +173,15 @@
 
 #define IP6T_ERROR_TARGET XT_ERROR_TARGET
 
+static __inline__ struct ip6t_entry_target *
+ip6t_get_target(struct ip6t_entry *e)
+{
+ return (void *)e + e->target_offset;
+}
+
 #define IP6T_MATCH_ITERATE(e, fn, args...)  ({   unsigned int __i;   int __ret = 0;   struct ip6t_entry_match *__m;     for (__i = sizeof(struct ip6t_entry);   __i < (e)->target_offset;   __i += __m->u.match_size) {   __m = (void *)(e) + __i;     __ret = fn(__m , ## args);   if (__ret != 0)   break;   }   __ret;  })
+
 #define IP6T_ENTRY_ITERATE(entries, size, fn, args...)  ({   unsigned int __i;   int __ret = 0;   struct ip6t_entry *__e;     for (__i = 0; __i < (size); __i += __e->next_offset) {   __e = (void *)(entries) + __i;     __ret = fn(__e , ## args);   if (__ret != 0)   break;   }   __ret;  })
+
 #endif
+
diff --git a/libc/kernel/common/linux/perf_event.h b/libc/kernel/common/linux/perf_event.h
new file mode 100644
index 0000000..9d3cd14
--- /dev/null
+++ b/libc/kernel/common/linux/perf_event.h
@@ -0,0 +1,240 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _LINUX_PERF_EVENT_H
+#define _LINUX_PERF_EVENT_H
+
+#include <linux/types.h>
+#include <linux/ioctl.h>
+#include <asm/byteorder.h>
+
+enum perf_type_id {
+ PERF_TYPE_HARDWARE = 0,
+ PERF_TYPE_SOFTWARE = 1,
+ PERF_TYPE_TRACEPOINT = 2,
+ PERF_TYPE_HW_CACHE = 3,
+ PERF_TYPE_RAW = 4,
+ PERF_TYPE_BREAKPOINT = 5,
+
+ PERF_TYPE_MAX,
+};
+
+enum perf_hw_id {
+
+ PERF_COUNT_HW_CPU_CYCLES = 0,
+ PERF_COUNT_HW_INSTRUCTIONS = 1,
+ PERF_COUNT_HW_CACHE_REFERENCES = 2,
+ PERF_COUNT_HW_CACHE_MISSES = 3,
+ PERF_COUNT_HW_BRANCH_INSTRUCTIONS = 4,
+ PERF_COUNT_HW_BRANCH_MISSES = 5,
+ PERF_COUNT_HW_BUS_CYCLES = 6,
+
+ PERF_COUNT_HW_MAX,
+};
+
+enum perf_hw_cache_id {
+ PERF_COUNT_HW_CACHE_L1D = 0,
+ PERF_COUNT_HW_CACHE_L1I = 1,
+ PERF_COUNT_HW_CACHE_LL = 2,
+ PERF_COUNT_HW_CACHE_DTLB = 3,
+ PERF_COUNT_HW_CACHE_ITLB = 4,
+ PERF_COUNT_HW_CACHE_BPU = 5,
+
+ PERF_COUNT_HW_CACHE_MAX,
+};
+
+enum perf_hw_cache_op_id {
+ PERF_COUNT_HW_CACHE_OP_READ = 0,
+ PERF_COUNT_HW_CACHE_OP_WRITE = 1,
+ PERF_COUNT_HW_CACHE_OP_PREFETCH = 2,
+
+ PERF_COUNT_HW_CACHE_OP_MAX,
+};
+
+enum perf_hw_cache_op_result_id {
+ PERF_COUNT_HW_CACHE_RESULT_ACCESS = 0,
+ PERF_COUNT_HW_CACHE_RESULT_MISS = 1,
+
+ PERF_COUNT_HW_CACHE_RESULT_MAX,
+};
+
+enum perf_sw_ids {
+ PERF_COUNT_SW_CPU_CLOCK = 0,
+ PERF_COUNT_SW_TASK_CLOCK = 1,
+ PERF_COUNT_SW_PAGE_FAULTS = 2,
+ PERF_COUNT_SW_CONTEXT_SWITCHES = 3,
+ PERF_COUNT_SW_CPU_MIGRATIONS = 4,
+ PERF_COUNT_SW_PAGE_FAULTS_MIN = 5,
+ PERF_COUNT_SW_PAGE_FAULTS_MAJ = 6,
+ PERF_COUNT_SW_ALIGNMENT_FAULTS = 7,
+ PERF_COUNT_SW_EMULATION_FAULTS = 8,
+
+ PERF_COUNT_SW_MAX,
+};
+
+enum perf_event_sample_format {
+ PERF_SAMPLE_IP = 1U << 0,
+ PERF_SAMPLE_TID = 1U << 1,
+ PERF_SAMPLE_TIME = 1U << 2,
+ PERF_SAMPLE_ADDR = 1U << 3,
+ PERF_SAMPLE_READ = 1U << 4,
+ PERF_SAMPLE_CALLCHAIN = 1U << 5,
+ PERF_SAMPLE_ID = 1U << 6,
+ PERF_SAMPLE_CPU = 1U << 7,
+ PERF_SAMPLE_PERIOD = 1U << 8,
+ PERF_SAMPLE_STREAM_ID = 1U << 9,
+ PERF_SAMPLE_RAW = 1U << 10,
+
+ PERF_SAMPLE_MAX = 1U << 11,
+};
+
+enum perf_event_read_format {
+ PERF_FORMAT_TOTAL_TIME_ENABLED = 1U << 0,
+ PERF_FORMAT_TOTAL_TIME_RUNNING = 1U << 1,
+ PERF_FORMAT_ID = 1U << 2,
+ PERF_FORMAT_GROUP = 1U << 3,
+
+ PERF_FORMAT_MAX = 1U << 4,
+};
+
+#define PERF_ATTR_SIZE_VER0 64  
+
+struct perf_event_attr {
+
+ __u32 type;
+
+ __u32 size;
+
+ __u64 config;
+
+ union {
+ __u64 sample_period;
+ __u64 sample_freq;
+ };
+
+ __u64 sample_type;
+ __u64 read_format;
+
+ __u64 disabled : 1,
+ inherit : 1,
+ pinned : 1,
+ exclusive : 1,
+ exclude_user : 1,
+ exclude_kernel : 1,
+ exclude_hv : 1,
+ exclude_idle : 1,
+ mmap : 1,
+ comm : 1,
+ freq : 1,
+ inherit_stat : 1,
+ enable_on_exec : 1,
+ task : 1,
+ watermark : 1,
+
+ precise_ip : 2,
+
+ __reserved_1 : 47;
+
+ union {
+ __u32 wakeup_events;
+ __u32 wakeup_watermark;
+ };
+
+ __u32 bp_type;
+ __u64 bp_addr;
+ __u64 bp_len;
+};
+
+#define PERF_EVENT_IOC_ENABLE _IO ('$', 0)
+#define PERF_EVENT_IOC_DISABLE _IO ('$', 1)
+#define PERF_EVENT_IOC_REFRESH _IO ('$', 2)
+#define PERF_EVENT_IOC_RESET _IO ('$', 3)
+#define PERF_EVENT_IOC_PERIOD _IOW('$', 4, __u64)
+#define PERF_EVENT_IOC_SET_OUTPUT _IO ('$', 5)
+#define PERF_EVENT_IOC_SET_FILTER _IOW('$', 6, char *)
+
+enum perf_event_ioc_flags {
+ PERF_IOC_FLAG_GROUP = 1U << 0,
+};
+
+struct perf_event_mmap_page {
+ __u32 version;
+ __u32 compat_version;
+
+ __u32 lock;
+ __u32 index;
+ __s64 offset;
+ __u64 time_enabled;
+ __u64 time_running;
+
+ __u64 __reserved[123];
+
+ __u64 data_head;
+ __u64 data_tail;
+};
+
+#define PERF_RECORD_MISC_CPUMODE_MASK (7 << 0)
+#define PERF_RECORD_MISC_CPUMODE_UNKNOWN (0 << 0)
+#define PERF_RECORD_MISC_KERNEL (1 << 0)
+#define PERF_RECORD_MISC_USER (2 << 0)
+#define PERF_RECORD_MISC_HYPERVISOR (3 << 0)
+#define PERF_RECORD_MISC_GUEST_KERNEL (4 << 0)
+#define PERF_RECORD_MISC_GUEST_USER (5 << 0)
+
+#define PERF_RECORD_MISC_EXACT_IP (1 << 14)
+
+#define PERF_RECORD_MISC_EXT_RESERVED (1 << 15)
+
+struct perf_event_header {
+ __u32 type;
+ __u16 misc;
+ __u16 size;
+};
+
+enum perf_event_type {
+
+ PERF_RECORD_MMAP = 1,
+
+ PERF_RECORD_LOST = 2,
+
+ PERF_RECORD_COMM = 3,
+
+ PERF_RECORD_EXIT = 4,
+
+ PERF_RECORD_THROTTLE = 5,
+ PERF_RECORD_UNTHROTTLE = 6,
+
+ PERF_RECORD_FORK = 7,
+
+ PERF_RECORD_READ = 8,
+
+ PERF_RECORD_SAMPLE = 9,
+
+ PERF_RECORD_MAX,
+};
+
+enum perf_callchain_context {
+ PERF_CONTEXT_HV = (__u64)-32,
+ PERF_CONTEXT_KERNEL = (__u64)-128,
+ PERF_CONTEXT_USER = (__u64)-512,
+
+ PERF_CONTEXT_GUEST = (__u64)-2048,
+ PERF_CONTEXT_GUEST_KERNEL = (__u64)-2176,
+ PERF_CONTEXT_GUEST_USER = (__u64)-2560,
+
+ PERF_CONTEXT_MAX = (__u64)-4095,
+};
+
+#define PERF_FLAG_FD_NO_GROUP (1U << 0)
+#define PERF_FLAG_FD_OUTPUT (1U << 1)
+
+#endif
+
diff --git a/libc/kernel/common/linux/rtnetlink.h b/libc/kernel/common/linux/rtnetlink.h
index e305505..bbd991a 100644
--- a/libc/kernel/common/linux/rtnetlink.h
+++ b/libc/kernel/common/linux/rtnetlink.h
@@ -18,6 +18,10 @@
 #include <linux/if_addr.h>
 #include <linux/neighbour.h>
 
+#define RTNL_FAMILY_IPMR 128
+#define RTNL_FAMILY_IP6MR 129
+#define RTNL_FAMILY_MAX 129
+
 enum {
  RTM_BASE = 16,
 #define RTM_BASE RTM_BASE
@@ -126,8 +130,7 @@
 #define RTM_NR_FAMILIES (RTM_NR_MSGTYPES >> 2)
 #define RTM_FAM(cmd) (((cmd) - RTM_BASE) >> 2)
 
-struct rtattr
-{
+struct rtattr {
  unsigned short rta_len;
  unsigned short rta_type;
 };
@@ -141,8 +144,7 @@
 #define RTA_DATA(rta) ((void*)(((char*)(rta)) + RTA_LENGTH(0)))
 #define RTA_PAYLOAD(rta) ((int)((rta)->rta_len) - RTA_LENGTH(0))
 
-struct rtmsg
-{
+struct rtmsg {
  unsigned char rtm_family;
  unsigned char rtm_dst_len;
  unsigned char rtm_src_len;
@@ -156,8 +158,7 @@
  unsigned rtm_flags;
 };
 
-enum
-{
+enum {
  RTN_UNSPEC,
  RTN_UNICAST,
  RTN_LOCAL,
@@ -191,8 +192,7 @@
 #define RTPROT_NTK 15  
 #define RTPROT_DHCP 16  
 
-enum rt_scope_t
-{
+enum rt_scope_t {
  RT_SCOPE_UNIVERSE=0,
 
  RT_SCOPE_SITE=200,
@@ -206,8 +206,7 @@
 #define RTM_F_EQUALIZE 0x400  
 #define RTM_F_PREFIX 0x800  
 
-enum rt_class_t
-{
+enum rt_class_t {
  RT_TABLE_UNSPEC=0,
 
  RT_TABLE_COMPAT=252,
@@ -217,8 +216,7 @@
  RT_TABLE_MAX=0xFFFFFFFF
 };
 
-enum rtattr_type_t
-{
+enum rtattr_type_t {
  RTA_UNSPEC,
  RTA_DST,
  RTA_SRC,
@@ -235,6 +233,7 @@
  RTA_SESSION,
  RTA_MP_ALGO,
  RTA_TABLE,
+ RTA_MARK,
  __RTA_MAX
 };
 
@@ -243,8 +242,7 @@
 #define RTM_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct rtmsg))))
 #define RTM_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct rtmsg))
 
-struct rtnexthop
-{
+struct rtnexthop {
  unsigned short rtnh_len;
  unsigned char rtnh_flags;
  unsigned char rtnh_hops;
@@ -263,8 +261,7 @@
 #define RTNH_SPACE(len) RTNH_ALIGN(RTNH_LENGTH(len))
 #define RTNH_DATA(rtnh) ((struct rtattr*)(((char*)(rtnh)) + RTNH_LENGTH(0)))
 
-struct rta_cacheinfo
-{
+struct rta_cacheinfo {
  __u32 rta_clntref;
  __u32 rta_lastuse;
  __s32 rta_expires;
@@ -277,8 +274,7 @@
  __u32 rta_tsage;
 };
 
-enum
-{
+enum {
  RTAX_UNSPEC,
 #define RTAX_UNSPEC RTAX_UNSPEC
  RTAX_LOCK,
@@ -307,6 +303,8 @@
 #define RTAX_FEATURES RTAX_FEATURES
  RTAX_RTO_MIN,
 #define RTAX_RTO_MIN RTAX_RTO_MIN
+ RTAX_INITRWND,
+#define RTAX_INITRWND RTAX_INITRWND
  __RTAX_MAX
 };
 
@@ -317,8 +315,7 @@
 #define RTAX_FEATURE_TIMESTAMP 0x00000004
 #define RTAX_FEATURE_ALLFRAG 0x00000008
 
-struct rta_session
-{
+struct rta_session {
  __u8 proto;
  __u8 pad1;
  __u16 pad2;
@@ -339,13 +336,11 @@
  } u;
 };
 
-struct rtgenmsg
-{
+struct rtgenmsg {
  unsigned char rtgen_family;
 };
 
-struct ifinfomsg
-{
+struct ifinfomsg {
  unsigned char ifi_family;
  unsigned char __ifi_pad;
  unsigned short ifi_type;
@@ -354,8 +349,7 @@
  unsigned ifi_change;
 };
 
-struct prefixmsg
-{
+struct prefixmsg {
  unsigned char prefix_family;
  unsigned char prefix_pad1;
  unsigned short prefix_pad2;
@@ -376,14 +370,12 @@
 
 #define PREFIX_MAX (__PREFIX_MAX - 1)
 
-struct prefix_cacheinfo
-{
+struct prefix_cacheinfo {
  __u32 preferred_time;
  __u32 valid_time;
 };
 
-struct tcmsg
-{
+struct tcmsg {
  unsigned char tcm_family;
  unsigned char tcm__pad1;
  unsigned short tcm__pad2;
@@ -393,8 +385,7 @@
  __u32 tcm_info;
 };
 
-enum
-{
+enum {
  TCA_UNSPEC,
  TCA_KIND,
  TCA_OPTIONS,
@@ -412,8 +403,7 @@
 #define TCA_RTA(r) ((struct rtattr*)(((char*)(r)) + NLMSG_ALIGN(sizeof(struct tcmsg))))
 #define TCA_PAYLOAD(n) NLMSG_PAYLOAD(n,sizeof(struct tcmsg))
 
-struct nduseroptmsg
-{
+struct nduseroptmsg {
  unsigned char nduseropt_family;
  unsigned char nduseropt_pad1;
  unsigned short nduseropt_opts_len;
@@ -425,8 +415,7 @@
 
 };
 
-enum
-{
+enum {
  NDUSEROPT_UNSPEC,
  NDUSEROPT_SRCADDR,
  __NDUSEROPT_MAX
@@ -503,8 +492,7 @@
 };
 #define RTNLGRP_MAX (__RTNLGRP_MAX - 1)
 
-struct tcamsg
-{
+struct tcamsg {
  unsigned char tca_family;
  unsigned char tca__pad1;
  unsigned short tca__pad2;
@@ -515,3 +503,4 @@
 #define TCAA_MAX 1
 
 #endif
+
diff --git a/libc/kernel/common/linux/spi/cpcap.h b/libc/kernel/common/linux/spi/cpcap.h
new file mode 100644
index 0000000..24bc918
--- /dev/null
+++ b/libc/kernel/common/linux/spi/cpcap.h
@@ -0,0 +1,587 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _LINUX_SPI_CPCAP_H
+#define _LINUX_SPI_CPCAP_H
+
+#include <linux/ioctl.h>
+
+#define CPCAP_DEV_NAME "cpcap"
+#define CPCAP_NUM_REG_CPCAP (CPCAP_REG_END - CPCAP_REG_START + 1)
+
+#define CPCAP_IRQ_INT1_INDEX 0
+#define CPCAP_IRQ_INT2_INDEX 16
+#define CPCAP_IRQ_INT3_INDEX 32
+#define CPCAP_IRQ_INT4_INDEX 48
+#define CPCAP_IRQ_INT5_INDEX 64
+
+#define CPCAP_HWCFG_NUM 2  
+
+#define CPCAP_HWCFG0_SEC_STBY_SW1 0x0001
+#define CPCAP_HWCFG0_SEC_STBY_SW2 0x0002
+#define CPCAP_HWCFG0_SEC_STBY_SW3 0x0004
+#define CPCAP_HWCFG0_SEC_STBY_SW4 0x0008
+#define CPCAP_HWCFG0_SEC_STBY_SW5 0x0010
+#define CPCAP_HWCFG0_SEC_STBY_VAUDIO 0x0020
+#define CPCAP_HWCFG0_SEC_STBY_VCAM 0x0040
+#define CPCAP_HWCFG0_SEC_STBY_VCSI 0x0080
+#define CPCAP_HWCFG0_SEC_STBY_VDAC 0x0100
+#define CPCAP_HWCFG0_SEC_STBY_VDIG 0x0200
+#define CPCAP_HWCFG0_SEC_STBY_VHVIO 0x0400
+#define CPCAP_HWCFG0_SEC_STBY_VPLL 0x0800
+#define CPCAP_HWCFG0_SEC_STBY_VRF1 0x1000
+#define CPCAP_HWCFG0_SEC_STBY_VRF2 0x2000
+#define CPCAP_HWCFG0_SEC_STBY_VRFREF 0x4000
+#define CPCAP_HWCFG0_SEC_STBY_VSDIO 0x8000
+
+#define CPCAP_HWCFG1_SEC_STBY_VWLAN1 0x0001
+#define CPCAP_HWCFG1_SEC_STBY_VWLAN2 0x0002
+#define CPCAP_HWCFG1_SEC_STBY_VSIM 0x0004
+#define CPCAP_HWCFG1_SEC_STBY_VSIMCARD 0x0008
+
+#define CPCAP_WHISPER_MODE_PU 0x00000001
+#define CPCAP_WHISPER_ENABLE_UART 0x00000002
+#define CPCAP_WHISPER_ACCY_MASK 0xF8000000
+#define CPCAP_WHISPER_ACCY_SHFT 27
+#define CPCAP_WHISPER_ID_SIZE 16
+#define CPCAP_WHISPER_PROP_SIZE 7
+
+enum cpcap_regulator_id {
+ CPCAP_SW2,
+ CPCAP_SW4,
+ CPCAP_SW5,
+ CPCAP_VCAM,
+ CPCAP_VCSI,
+ CPCAP_VDAC,
+ CPCAP_VDIG,
+ CPCAP_VFUSE,
+ CPCAP_VHVIO,
+ CPCAP_VSDIO,
+ CPCAP_VPLL,
+ CPCAP_VRF1,
+ CPCAP_VRF2,
+ CPCAP_VRFREF,
+ CPCAP_VWLAN1,
+ CPCAP_VWLAN2,
+ CPCAP_VSIM,
+ CPCAP_VSIMCARD,
+ CPCAP_VVIB,
+ CPCAP_VUSB,
+ CPCAP_VAUDIO,
+ CPCAP_NUM_REGULATORS
+};
+
+enum cpcap_reg {
+ CPCAP_REG_START,
+
+ CPCAP_REG_INT1 = CPCAP_REG_START,
+ CPCAP_REG_INT2,
+ CPCAP_REG_INT3,
+ CPCAP_REG_INT4,
+ CPCAP_REG_INTM1,
+ CPCAP_REG_INTM2,
+ CPCAP_REG_INTM3,
+ CPCAP_REG_INTM4,
+ CPCAP_REG_INTS1,
+ CPCAP_REG_INTS2,
+ CPCAP_REG_INTS3,
+ CPCAP_REG_INTS4,
+ CPCAP_REG_ASSIGN1,
+ CPCAP_REG_ASSIGN2,
+ CPCAP_REG_ASSIGN3,
+ CPCAP_REG_ASSIGN4,
+ CPCAP_REG_ASSIGN5,
+ CPCAP_REG_ASSIGN6,
+ CPCAP_REG_VERSC1,
+ CPCAP_REG_VERSC2,
+
+ CPCAP_REG_MI1,
+ CPCAP_REG_MIM1,
+ CPCAP_REG_MI2,
+ CPCAP_REG_MIM2,
+ CPCAP_REG_UCC1,
+ CPCAP_REG_UCC2,
+ CPCAP_REG_PC1,
+ CPCAP_REG_PC2,
+ CPCAP_REG_BPEOL,
+ CPCAP_REG_PGC,
+ CPCAP_REG_MT1,
+ CPCAP_REG_MT2,
+ CPCAP_REG_MT3,
+ CPCAP_REG_PF,
+
+ CPCAP_REG_SCC,
+ CPCAP_REG_SW1,
+ CPCAP_REG_SW2,
+ CPCAP_REG_UCTM,
+ CPCAP_REG_TOD1,
+ CPCAP_REG_TOD2,
+ CPCAP_REG_TODA1,
+ CPCAP_REG_TODA2,
+ CPCAP_REG_DAY,
+ CPCAP_REG_DAYA,
+ CPCAP_REG_VAL1,
+ CPCAP_REG_VAL2,
+
+ CPCAP_REG_SDVSPLL,
+ CPCAP_REG_SI2CC1,
+ CPCAP_REG_Si2CC2,
+ CPCAP_REG_S1C1,
+ CPCAP_REG_S1C2,
+ CPCAP_REG_S2C1,
+ CPCAP_REG_S2C2,
+ CPCAP_REG_S3C,
+ CPCAP_REG_S4C1,
+ CPCAP_REG_S4C2,
+ CPCAP_REG_S5C,
+ CPCAP_REG_S6C,
+ CPCAP_REG_VCAMC,
+ CPCAP_REG_VCSIC,
+ CPCAP_REG_VDACC,
+ CPCAP_REG_VDIGC,
+ CPCAP_REG_VFUSEC,
+ CPCAP_REG_VHVIOC,
+ CPCAP_REG_VSDIOC,
+ CPCAP_REG_VPLLC,
+ CPCAP_REG_VRF1C,
+ CPCAP_REG_VRF2C,
+ CPCAP_REG_VRFREFC,
+ CPCAP_REG_VWLAN1C,
+ CPCAP_REG_VWLAN2C,
+ CPCAP_REG_VSIMC,
+ CPCAP_REG_VVIBC,
+ CPCAP_REG_VUSBC,
+ CPCAP_REG_VUSBINT1C,
+ CPCAP_REG_VUSBINT2C,
+ CPCAP_REG_URT,
+ CPCAP_REG_URM1,
+ CPCAP_REG_URM2,
+
+ CPCAP_REG_VAUDIOC,
+ CPCAP_REG_CC,
+ CPCAP_REG_CDI,
+ CPCAP_REG_SDAC,
+ CPCAP_REG_SDACDI,
+ CPCAP_REG_TXI,
+ CPCAP_REG_TXMP,
+ CPCAP_REG_RXOA,
+ CPCAP_REG_RXVC,
+ CPCAP_REG_RXCOA,
+ CPCAP_REG_RXSDOA,
+ CPCAP_REG_RXEPOA,
+ CPCAP_REG_RXLL,
+ CPCAP_REG_A2LA,
+ CPCAP_REG_MIPIS1,
+ CPCAP_REG_MIPIS2,
+ CPCAP_REG_MIPIS3,
+ CPCAP_REG_LVAB,
+
+ CPCAP_REG_CCC1,
+ CPCAP_REG_CRM,
+ CPCAP_REG_CCCC2,
+ CPCAP_REG_CCS1,
+ CPCAP_REG_CCS2,
+ CPCAP_REG_CCA1,
+ CPCAP_REG_CCA2,
+ CPCAP_REG_CCM,
+ CPCAP_REG_CCO,
+ CPCAP_REG_CCI,
+
+ CPCAP_REG_ADCC1,
+ CPCAP_REG_ADCC2,
+ CPCAP_REG_ADCD0,
+ CPCAP_REG_ADCD1,
+ CPCAP_REG_ADCD2,
+ CPCAP_REG_ADCD3,
+ CPCAP_REG_ADCD4,
+ CPCAP_REG_ADCD5,
+ CPCAP_REG_ADCD6,
+ CPCAP_REG_ADCD7,
+ CPCAP_REG_ADCAL1,
+ CPCAP_REG_ADCAL2,
+
+ CPCAP_REG_USBC1,
+ CPCAP_REG_USBC2,
+ CPCAP_REG_USBC3,
+ CPCAP_REG_UVIDL,
+ CPCAP_REG_UVIDH,
+ CPCAP_REG_UPIDL,
+ CPCAP_REG_UPIDH,
+ CPCAP_REG_UFC1,
+ CPCAP_REG_UFC2,
+ CPCAP_REG_UFC3,
+ CPCAP_REG_UIC1,
+ CPCAP_REG_UIC2,
+ CPCAP_REG_UIC3,
+ CPCAP_REG_USBOTG1,
+ CPCAP_REG_USBOTG2,
+ CPCAP_REG_USBOTG3,
+ CPCAP_REG_UIER1,
+ CPCAP_REG_UIER2,
+ CPCAP_REG_UIER3,
+ CPCAP_REG_UIEF1,
+ CPCAP_REG_UIEF2,
+ CPCAP_REG_UIEF3,
+ CPCAP_REG_UIS,
+ CPCAP_REG_UIL,
+ CPCAP_REG_USBD,
+ CPCAP_REG_SCR1,
+ CPCAP_REG_SCR2,
+ CPCAP_REG_SCR3,
+ CPCAP_REG_VMC,
+ CPCAP_REG_OWDC,
+ CPCAP_REG_GPIO0,
+ CPCAP_REG_GPIO1,
+ CPCAP_REG_GPIO2,
+ CPCAP_REG_GPIO3,
+ CPCAP_REG_GPIO4,
+ CPCAP_REG_GPIO5,
+ CPCAP_REG_GPIO6,
+
+ CPCAP_REG_MDLC,
+ CPCAP_REG_KLC,
+ CPCAP_REG_ADLC,
+ CPCAP_REG_REDC,
+ CPCAP_REG_GREENC,
+ CPCAP_REG_BLUEC,
+ CPCAP_REG_CFC,
+ CPCAP_REG_ABC,
+ CPCAP_REG_BLEDC,
+ CPCAP_REG_CLEDC,
+
+ CPCAP_REG_OW1C,
+ CPCAP_REG_OW1D,
+ CPCAP_REG_OW1I,
+ CPCAP_REG_OW1IE,
+ CPCAP_REG_OW1,
+ CPCAP_REG_OW2C,
+ CPCAP_REG_OW2D,
+ CPCAP_REG_OW2I,
+ CPCAP_REG_OW2IE,
+ CPCAP_REG_OW2,
+ CPCAP_REG_OW3C,
+ CPCAP_REG_OW3D,
+ CPCAP_REG_OW3I,
+ CPCAP_REG_OW3IE,
+ CPCAP_REG_OW3,
+ CPCAP_REG_GCAIC,
+ CPCAP_REG_GCAIM,
+ CPCAP_REG_LGDIR,
+ CPCAP_REG_LGPU,
+ CPCAP_REG_LGPIN,
+ CPCAP_REG_LGMASK,
+ CPCAP_REG_LDEB,
+ CPCAP_REG_LGDET,
+ CPCAP_REG_LMISC,
+ CPCAP_REG_LMACE,
+
+ CPCAP_REG_END = CPCAP_REG_LMACE,
+
+ CPCAP_REG_MAX
+ = CPCAP_REG_END,
+
+ CPCAP_REG_SIZE = CPCAP_REG_MAX + 1,
+ CPCAP_REG_UNUSED = CPCAP_REG_MAX + 2,
+};
+
+enum {
+ CPCAP_IOCTL_NUM_TEST__START,
+ CPCAP_IOCTL_NUM_TEST_READ_REG,
+ CPCAP_IOCTL_NUM_TEST_WRITE_REG,
+ CPCAP_IOCTL_NUM_TEST__END,
+
+ CPCAP_IOCTL_NUM_ADC__START,
+ CPCAP_IOCTL_NUM_ADC_PHASE,
+ CPCAP_IOCTL_NUM_ADC__END,
+
+ CPCAP_IOCTL_NUM_BATT__START,
+ CPCAP_IOCTL_NUM_BATT_DISPLAY_UPDATE,
+ CPCAP_IOCTL_NUM_BATT_ATOD_ASYNC,
+ CPCAP_IOCTL_NUM_BATT_ATOD_SYNC,
+ CPCAP_IOCTL_NUM_BATT_ATOD_READ,
+ CPCAP_IOCTL_NUM_BATT__END,
+
+ CPCAP_IOCTL_NUM_UC__START,
+ CPCAP_IOCTL_NUM_UC_MACRO_START,
+ CPCAP_IOCTL_NUM_UC_MACRO_STOP,
+ CPCAP_IOCTL_NUM_UC_GET_VENDOR,
+ CPCAP_IOCTL_NUM_UC_SET_TURBO_MODE,
+ CPCAP_IOCTL_NUM_UC__END,
+
+ CPCAP_IOCTL_NUM_ACCY__START,
+ CPCAP_IOCTL_NUM_ACCY_WHISPER,
+ CPCAP_IOCTL_NUM_ACCY__END,
+};
+
+enum cpcap_irqs {
+ CPCAP_IRQ__START,
+ CPCAP_IRQ_HSCLK = CPCAP_IRQ_INT1_INDEX,
+ CPCAP_IRQ_PRIMAC,
+ CPCAP_IRQ_SECMAC,
+ CPCAP_IRQ_LOWBPL,
+ CPCAP_IRQ_SEC2PRI,
+ CPCAP_IRQ_LOWBPH,
+ CPCAP_IRQ_EOL,
+ CPCAP_IRQ_TS,
+ CPCAP_IRQ_ADCDONE,
+ CPCAP_IRQ_HS,
+ CPCAP_IRQ_MB2,
+ CPCAP_IRQ_VBUSOV,
+ CPCAP_IRQ_RVRS_CHRG,
+ CPCAP_IRQ_CHRG_DET,
+ CPCAP_IRQ_IDFLOAT,
+ CPCAP_IRQ_IDGND,
+
+ CPCAP_IRQ_SE1 = CPCAP_IRQ_INT2_INDEX,
+ CPCAP_IRQ_SESSEND,
+ CPCAP_IRQ_SESSVLD,
+ CPCAP_IRQ_VBUSVLD,
+ CPCAP_IRQ_CHRG_CURR1,
+ CPCAP_IRQ_CHRG_CURR2,
+ CPCAP_IRQ_RVRS_MODE,
+ CPCAP_IRQ_ON,
+ CPCAP_IRQ_ON2,
+ CPCAP_IRQ_CLK,
+ CPCAP_IRQ_1HZ,
+ CPCAP_IRQ_PTT,
+ CPCAP_IRQ_SE0CONN,
+ CPCAP_IRQ_CHRG_SE1B,
+ CPCAP_IRQ_UART_ECHO_OVERRUN,
+ CPCAP_IRQ_EXTMEMHD,
+
+ CPCAP_IRQ_WARM = CPCAP_IRQ_INT3_INDEX,
+ CPCAP_IRQ_SYSRSTR,
+ CPCAP_IRQ_SOFTRST,
+ CPCAP_IRQ_DIEPWRDWN,
+ CPCAP_IRQ_DIETEMPH,
+ CPCAP_IRQ_PC,
+ CPCAP_IRQ_OFLOWSW,
+ CPCAP_IRQ_TODA,
+ CPCAP_IRQ_OPT_SEL_DTCH,
+ CPCAP_IRQ_OPT_SEL_STATE,
+ CPCAP_IRQ_ONEWIRE1,
+ CPCAP_IRQ_ONEWIRE2,
+ CPCAP_IRQ_ONEWIRE3,
+ CPCAP_IRQ_UCRESET,
+ CPCAP_IRQ_PWRGOOD,
+ CPCAP_IRQ_USBDPLLCLK,
+
+ CPCAP_IRQ_DPI = CPCAP_IRQ_INT4_INDEX,
+ CPCAP_IRQ_DMI,
+ CPCAP_IRQ_UCBUSY,
+ CPCAP_IRQ_GCAI_CURR1,
+ CPCAP_IRQ_GCAI_CURR2,
+ CPCAP_IRQ_SB_MAX_RETRANSMIT_ERR,
+ CPCAP_IRQ_BATTDETB,
+ CPCAP_IRQ_PRIHALT,
+ CPCAP_IRQ_SECHALT,
+ CPCAP_IRQ_CC_CAL,
+
+ CPCAP_IRQ_UC_PRIROMR = CPCAP_IRQ_INT5_INDEX,
+ CPCAP_IRQ_UC_PRIRAMW,
+ CPCAP_IRQ_UC_PRIRAMR,
+ CPCAP_IRQ_UC_USEROFF,
+ CPCAP_IRQ_UC_PRIMACRO_4,
+ CPCAP_IRQ_UC_PRIMACRO_5,
+ CPCAP_IRQ_UC_PRIMACRO_6,
+ CPCAP_IRQ_UC_PRIMACRO_7,
+ CPCAP_IRQ_UC_PRIMACRO_8,
+ CPCAP_IRQ_UC_PRIMACRO_9,
+ CPCAP_IRQ_UC_PRIMACRO_10,
+ CPCAP_IRQ_UC_PRIMACRO_11,
+ CPCAP_IRQ_UC_PRIMACRO_12,
+ CPCAP_IRQ_UC_PRIMACRO_13,
+ CPCAP_IRQ_UC_PRIMACRO_14,
+ CPCAP_IRQ_UC_PRIMACRO_15,
+ CPCAP_IRQ__NUM
+};
+
+enum cpcap_adc_bank0 {
+ CPCAP_ADC_AD0_BATTDETB,
+ CPCAP_ADC_BATTP,
+ CPCAP_ADC_VBUS,
+ CPCAP_ADC_AD3,
+ CPCAP_ADC_BPLUS_AD4,
+ CPCAP_ADC_CHG_ISENSE,
+ CPCAP_ADC_BATTI_ADC,
+ CPCAP_ADC_USB_ID,
+
+ CPCAP_ADC_BANK0_NUM,
+};
+
+enum cpcap_adc_bank1 {
+ CPCAP_ADC_AD8,
+ CPCAP_ADC_AD9,
+ CPCAP_ADC_LICELL,
+ CPCAP_ADC_HV_BATTP,
+ CPCAP_ADC_TSX1_AD12,
+ CPCAP_ADC_TSX2_AD13,
+ CPCAP_ADC_TSY1_AD14,
+ CPCAP_ADC_TSY2_AD15,
+
+ CPCAP_ADC_BANK1_NUM,
+};
+
+enum cpcap_adc_format {
+ CPCAP_ADC_FORMAT_RAW,
+ CPCAP_ADC_FORMAT_PHASED,
+ CPCAP_ADC_FORMAT_CONVERTED,
+};
+
+enum cpcap_adc_timing {
+ CPCAP_ADC_TIMING_IMM,
+ CPCAP_ADC_TIMING_IN,
+ CPCAP_ADC_TIMING_OUT,
+};
+
+enum cpcap_adc_type {
+ CPCAP_ADC_TYPE_BANK_0,
+ CPCAP_ADC_TYPE_BANK_1,
+ CPCAP_ADC_TYPE_BATT_PI,
+};
+
+enum cpcap_macro {
+ CPCAP_MACRO_ROMR,
+ CPCAP_MACRO_RAMW,
+ CPCAP_MACRO_RAMR,
+ CPCAP_MACRO_USEROFF,
+ CPCAP_MACRO_4,
+ CPCAP_MACRO_5,
+ CPCAP_MACRO_6,
+ CPCAP_MACRO_7,
+ CPCAP_MACRO_8,
+ CPCAP_MACRO_9,
+ CPCAP_MACRO_10,
+ CPCAP_MACRO_11,
+ CPCAP_MACRO_12,
+ CPCAP_MACRO_13,
+ CPCAP_MACRO_14,
+ CPCAP_MACRO_15,
+
+ CPCAP_MACRO__END,
+};
+
+enum cpcap_vendor {
+ CPCAP_VENDOR_ST,
+ CPCAP_VENDOR_TI,
+};
+
+enum cpcap_revision {
+ CPCAP_REVISION_1_0 = 0x08,
+ CPCAP_REVISION_1_1 = 0x09,
+ CPCAP_REVISION_2_0 = 0x10,
+ CPCAP_REVISION_2_1 = 0x11,
+};
+
+enum cpcap_batt_usb_model {
+ CPCAP_BATT_USB_MODEL_NONE,
+ CPCAP_BATT_USB_MODEL_USB,
+ CPCAP_BATT_USB_MODEL_FACTORY,
+};
+
+struct cpcap_spi_init_data {
+ enum cpcap_reg reg;
+ unsigned short data;
+};
+
+struct cpcap_adc_ato {
+ unsigned short ato_in;
+ unsigned short atox_in;
+ unsigned short adc_ps_factor_in;
+ unsigned short atox_ps_factor_in;
+ unsigned short ato_out;
+ unsigned short atox_out;
+ unsigned short adc_ps_factor_out;
+ unsigned short atox_ps_factor_out;
+};
+
+struct cpcap_batt_data {
+ int status;
+ int health;
+ int present;
+ int capacity;
+ int batt_volt;
+ int batt_temp;
+};
+
+struct cpcap_batt_ac_data {
+ int online;
+};
+
+struct cpcap_batt_usb_data {
+ int online;
+ int current_now;
+ enum cpcap_batt_usb_model model;
+};
+
+struct cpcap_device;
+
+struct cpcap_adc_us_request {
+ enum cpcap_adc_format format;
+ enum cpcap_adc_timing timing;
+ enum cpcap_adc_type type;
+ int status;
+ int result[CPCAP_ADC_BANK0_NUM];
+};
+
+struct cpcap_adc_phase {
+ signed char offset_batti;
+ unsigned char slope_batti;
+ signed char offset_chrgi;
+ unsigned char slope_chrgi;
+ signed char offset_battp;
+ unsigned char slope_battp;
+ signed char offset_bp;
+ unsigned char slope_bp;
+ signed char offset_battt;
+ unsigned char slope_battt;
+ signed char offset_chrgv;
+ unsigned char slope_chrgv;
+};
+
+struct cpcap_regacc {
+ unsigned short reg;
+ unsigned short value;
+ unsigned short mask;
+};
+
+struct cpcap_whisper_request {
+ unsigned int cmd;
+ char dock_id[CPCAP_WHISPER_ID_SIZE];
+ char dock_prop[CPCAP_WHISPER_PROP_SIZE];
+};
+
+#define CPCAP_IOCTL_TEST_READ_REG   _IOWR(0, CPCAP_IOCTL_NUM_TEST_READ_REG, struct cpcap_regacc*)
+
+#define CPCAP_IOCTL_TEST_WRITE_REG   _IOWR(0, CPCAP_IOCTL_NUM_TEST_WRITE_REG, struct cpcap_regacc*)
+
+#define CPCAP_IOCTL_ADC_PHASE   _IOWR(0, CPCAP_IOCTL_NUM_ADC_PHASE, struct cpcap_adc_phase*)
+
+#define CPCAP_IOCTL_BATT_DISPLAY_UPDATE   _IOW(0, CPCAP_IOCTL_NUM_BATT_DISPLAY_UPDATE, struct cpcap_batt_data*)
+
+#define CPCAP_IOCTL_BATT_ATOD_ASYNC   _IOW(0, CPCAP_IOCTL_NUM_BATT_ATOD_ASYNC, struct cpcap_adc_us_request*)
+
+#define CPCAP_IOCTL_BATT_ATOD_SYNC   _IOWR(0, CPCAP_IOCTL_NUM_BATT_ATOD_SYNC, struct cpcap_adc_us_request*)
+
+#define CPCAP_IOCTL_BATT_ATOD_READ   _IOWR(0, CPCAP_IOCTL_NUM_BATT_ATOD_READ, struct cpcap_adc_us_request*)
+
+#define CPCAP_IOCTL_UC_MACRO_START   _IOWR(0, CPCAP_IOCTL_NUM_UC_MACRO_START, enum cpcap_macro)
+
+#define CPCAP_IOCTL_UC_MACRO_STOP   _IOWR(0, CPCAP_IOCTL_NUM_UC_MACRO_STOP, enum cpcap_macro)
+
+#define CPCAP_IOCTL_UC_GET_VENDOR   _IOWR(0, CPCAP_IOCTL_NUM_UC_GET_VENDOR, enum cpcap_vendor)
+
+#define CPCAP_IOCTL_UC_SET_TURBO_MODE   _IOW(0, CPCAP_IOCTL_NUM_UC_SET_TURBO_MODE, unsigned short)
+
+#define CPCAP_IOCTL_ACCY_WHISPER   _IOW(0, CPCAP_IOCTL_NUM_ACCY_WHISPER, struct cpcap_whisper_request*)
+
+#endif
+
diff --git a/libc/kernel/common/linux/tegra_audio.h b/libc/kernel/common/linux/tegra_audio.h
new file mode 100644
index 0000000..e18ce11
--- /dev/null
+++ b/libc/kernel/common/linux/tegra_audio.h
@@ -0,0 +1,43 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _TEGRA_AUDIO_H
+#define _TEGRA_AUDIO_H
+
+#include <linux/ioctl.h>
+
+#define TEGRA_AUDIO_MAGIC 't'
+
+#define TEGRA_AUDIO_IN_START _IO(TEGRA_AUDIO_MAGIC, 0)
+#define TEGRA_AUDIO_IN_STOP _IO(TEGRA_AUDIO_MAGIC, 1)
+
+struct tegra_audio_in_config {
+ int rate;
+ int stereo;
+};
+
+#define TEGRA_AUDIO_IN_SET_CONFIG _IOW(TEGRA_AUDIO_MAGIC, 2,   const struct tegra_audio_in_config *)
+#define TEGRA_AUDIO_IN_GET_CONFIG _IOR(TEGRA_AUDIO_MAGIC, 3,   struct tegra_audio_in_config *)
+
+#define TEGRA_AUDIO_IN_SET_NUM_BUFS _IOW(TEGRA_AUDIO_MAGIC, 4,   const unsigned int *)
+#define TEGRA_AUDIO_IN_GET_NUM_BUFS _IOW(TEGRA_AUDIO_MAGIC, 5,   unsigned int *)
+#define TEGRA_AUDIO_OUT_SET_NUM_BUFS _IOW(TEGRA_AUDIO_MAGIC, 6,   const unsigned int *)
+#define TEGRA_AUDIO_OUT_GET_NUM_BUFS _IOW(TEGRA_AUDIO_MAGIC, 7,   unsigned int *)
+
+#define TEGRA_AUDIO_OUT_FLUSH _IO(TEGRA_AUDIO_MAGIC, 10)
+
+#define TEGRA_AUDIO_BIT_FORMAT_DEFAULT 0
+#define TEGRA_AUDIO_BIT_FORMAT_DSP 1
+#define TEGRA_AUDIO_SET_BIT_FORMAT _IOW(TEGRA_AUDIO_MAGIC, 11,   const unsigned int *)
+#define TEGRA_AUDIO_GET_BIT_FORMAT _IOR(TEGRA_AUDIO_MAGIC, 12,   unsigned int *)
+
+#endif
+
diff --git a/libc/kernel/common/linux/tegra_avp.h b/libc/kernel/common/linux/tegra_avp.h
new file mode 100644
index 0000000..c4a0cbd
--- /dev/null
+++ b/libc/kernel/common/linux/tegra_avp.h
@@ -0,0 +1,38 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __LINUX_TEGRA_AVP_H
+#define __LINUX_TEGRA_AVP_H
+
+#include <linux/ioctl.h>
+#include <linux/types.h>
+
+#define TEGRA_AVP_LIB_MAX_NAME 32
+#define TEGRA_AVP_LIB_MAX_ARGS 220  
+
+struct tegra_avp_lib {
+ char name[TEGRA_AVP_LIB_MAX_NAME];
+ void __user *args;
+ size_t args_len;
+ int greedy;
+ unsigned long handle;
+};
+
+#define TEGRA_AVP_IOCTL_MAGIC 'r'
+
+#define TEGRA_AVP_IOCTL_LOAD_LIB _IOWR(TEGRA_AVP_IOCTL_MAGIC, 0x40, struct tegra_avp_lib)
+#define TEGRA_AVP_IOCTL_UNLOAD_LIB _IOW(TEGRA_AVP_IOCTL_MAGIC, 0x41, unsigned long)
+
+#define TEGRA_AVP_IOCTL_MIN_NR _IOC_NR(TEGRA_AVP_IOCTL_LOAD_LIB)
+#define TEGRA_AVP_IOCTL_MAX_NR _IOC_NR(TEGRA_AVP_IOCTL_UNLOAD_LIB)
+
+#endif
+
diff --git a/libc/kernel/common/linux/tegra_rpc.h b/libc/kernel/common/linux/tegra_rpc.h
new file mode 100644
index 0000000..e3c8bf2
--- /dev/null
+++ b/libc/kernel/common/linux/tegra_rpc.h
@@ -0,0 +1,35 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __LINUX_TEGRA_RPC_H
+#define __LINUX_TEGRA_RPC_H
+
+#define TEGRA_RPC_MAX_MSG_LEN 256
+
+#define TEGRA_RPC_MAX_NAME_LEN 17
+
+struct tegra_rpc_port_desc {
+ char name[TEGRA_RPC_MAX_NAME_LEN];
+ int notify_fd;
+};
+
+#define TEGRA_RPC_IOCTL_MAGIC 'r'
+
+#define TEGRA_RPC_IOCTL_PORT_CREATE _IOW(TEGRA_RPC_IOCTL_MAGIC, 0x20, struct tegra_rpc_port_desc)
+#define TEGRA_RPC_IOCTL_PORT_GET_NAME _IOR(TEGRA_RPC_IOCTL_MAGIC, 0x21, char *)
+#define TEGRA_RPC_IOCTL_PORT_CONNECT _IOR(TEGRA_RPC_IOCTL_MAGIC, 0x22, long)
+#define TEGRA_RPC_IOCTL_PORT_LISTEN _IOR(TEGRA_RPC_IOCTL_MAGIC, 0x23, long)
+
+#define TEGRA_RPC_IOCTL_MIN_NR _IOC_NR(TEGRA_RPC_IOCTL_PORT_CREATE)
+#define TEGRA_RPC_IOCTL_MAX_NR _IOC_NR(TEGRA_RPC_IOCTL_PORT_LISTEN)
+
+#endif
+
diff --git a/libc/kernel/common/linux/tegra_sema.h b/libc/kernel/common/linux/tegra_sema.h
new file mode 100644
index 0000000..bb11298
--- /dev/null
+++ b/libc/kernel/common/linux/tegra_sema.h
@@ -0,0 +1,24 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __LINUX_TEGRA_SEMA_H
+#define __LINUX_TEGRA_SEMA_H
+
+#define TEGRA_SEMA_IOCTL_MAGIC 'r'
+
+#define TEGRA_SEMA_IOCTL_WAIT _IOW(TEGRA_SEMA_IOCTL_MAGIC, 0x30, long *)
+#define TEGRA_SEMA_IOCTL_SIGNAL _IO(TEGRA_SEMA_IOCTL_MAGIC, 0x31)
+
+#define TEGRA_SEMA_IOCTL_MIN_NR _IOC_NR(TEGRA_SEMA_IOCTL_WAIT)
+#define TEGRA_SEMA_IOCTL_MAX_NR _IOC_NR(TEGRA_SEMA_IOCTL_SIGNAL)
+
+#endif
+
diff --git a/libc/kernel/common/linux/tegrafb.h b/libc/kernel/common/linux/tegrafb.h
new file mode 100644
index 0000000..b8e79ae
--- /dev/null
+++ b/libc/kernel/common/linux/tegrafb.h
@@ -0,0 +1,87 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _LINUX_TEGRAFB_H_
+#define _LINUX_TEGRAFB_H_
+
+#include <linux/fb.h>
+#include <linux/types.h>
+#include <asm/ioctl.h>
+
+#define TEGRA_FB_WIN_FMT_P1 0
+#define TEGRA_FB_WIN_FMT_P2 1
+#define TEGRA_FB_WIN_FMT_P4 2
+#define TEGRA_FB_WIN_FMT_P8 3
+#define TEGRA_FB_WIN_FMT_B4G4R4A4 4
+#define TEGRA_FB_WIN_FMT_B5G5R5A 5
+#define TEGRA_FB_WIN_FMT_B5G6R5 6
+#define TEGRA_FB_WIN_FMT_AB5G5R5 7
+#define TEGRA_FB_WIN_FMT_B8G8R8A8 12
+#define TEGRA_FB_WIN_FMT_R8G8B8A8 13
+#define TEGRA_FB_WIN_FMT_B6x2G6x2R6x2A8 14
+#define TEGRA_FB_WIN_FMT_R6x2G6x2B6x2A8 15
+#define TEGRA_FB_WIN_FMT_YCbCr422 16
+#define TEGRA_FB_WIN_FMT_YUV422 17
+#define TEGRA_FB_WIN_FMT_YCbCr420P 18
+#define TEGRA_FB_WIN_FMT_YUV420P 19
+#define TEGRA_FB_WIN_FMT_YCbCr422P 20
+#define TEGRA_FB_WIN_FMT_YUV422P 21
+#define TEGRA_FB_WIN_FMT_YCbCr422R 22
+#define TEGRA_FB_WIN_FMT_YUV422R 23
+#define TEGRA_FB_WIN_FMT_YCbCr422RA 24
+#define TEGRA_FB_WIN_FMT_YUV422RA 25
+
+#define TEGRA_FB_WIN_BLEND_NONE 0
+#define TEGRA_FB_WIN_BLEND_PREMULT 1
+#define TEGRA_FB_WIN_BLEND_COVERAGE 2
+
+struct tegra_fb_windowattr {
+ __s32 index;
+ __u32 buff_id;
+ __u32 blend;
+ __u32 offset;
+ __u32 offset_u;
+ __u32 offset_v;
+ __u32 stride;
+ __u32 stride_uv;
+ __u32 pixformat;
+ __u32 x;
+ __u32 y;
+ __u32 w;
+ __u32 h;
+ __u32 out_x;
+ __u32 out_y;
+ __u32 out_w;
+ __u32 out_h;
+ __u32 z;
+ __u32 pre_syncpt_id;
+ __u32 pre_syncpt_val;
+};
+
+#define TEGRA_FB_FLIP_N_WINDOWS 3
+
+struct tegra_fb_flip_args {
+ struct tegra_fb_windowattr win[TEGRA_FB_FLIP_N_WINDOWS];
+ __u32 post_syncpt_id;
+ __u32 post_syncpt_val;
+};
+
+struct tegra_fb_modedb {
+ struct fb_var_screeninfo *modedb;
+ __u32 modedb_len;
+};
+
+#define FBIO_TEGRA_SET_NVMAP_FD _IOW('F', 0x40, __u32)
+#define FBIO_TEGRA_FLIP _IOW('F', 0x41, struct tegra_fb_flip_args)
+#define FBIO_TEGRA_GET_MODEDB _IOWR('F', 0x42, struct tegra_fb_modedb)
+
+#endif
+
diff --git a/libc/kernel/common/linux/ublock.h b/libc/kernel/common/linux/ublock.h
new file mode 100644
index 0000000..aa19a81
--- /dev/null
+++ b/libc/kernel/common/linux/ublock.h
@@ -0,0 +1,81 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __UBLOCK_H_
+#define __UBLOCK_H_
+
+#include <linux/types.h>
+
+#define UBLOCK_VERSION 0
+
+enum {
+ UBLOCK_INIT_IN = 0,
+ UBLOCK_INIT_OUT = 1,
+ UBLOCK_READY_IN = 2,
+ UBLOCK_READY_OUT = 3,
+ UBLOCK_READ_IN = 4,
+ UBLOCK_READ_OUT = 5,
+ UBLOCK_WRITE_IN = 6,
+ UBLOCK_WRITE_OUT = 7,
+};
+
+struct ublock_in_header {
+ __u32 seq;
+ __u32 opcode;
+};
+
+struct ublock_out_header {
+ __u32 seq;
+ __u32 opcode;
+};
+
+struct ublock_init_in {
+ __u32 version;
+ __u32 max_buf;
+ __u32 index;
+};
+
+struct ublock_init_out {
+ __u32 version;
+ __u32 max_buf;
+ __u64 size;
+};
+
+struct ublock_ready_in {
+ __u32 _unused;
+};
+
+struct ublock_ready_out {
+ __u32 _unused;
+};
+
+struct ublock_read_in {
+ __u64 offset;
+ __u64 length;
+};
+
+struct ublock_read_out {
+ __s32 status;
+ __u8 data[];
+};
+
+struct ublock_write_in {
+ __u64 offset;
+ __u64 length;
+ __u8 data[];
+};
+
+struct ublock_write_out {
+ __s32 status;
+};
+
+#endif
+
diff --git a/libc/kernel/common/linux/usb/f_mtp.h b/libc/kernel/common/linux/usb/f_mtp.h
new file mode 100644
index 0000000..a9e37c2
--- /dev/null
+++ b/libc/kernel/common/linux/usb/f_mtp.h
@@ -0,0 +1,42 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __LINUX_USB_F_MTP_H
+#define __LINUX_USB_F_MTP_H
+
+#define MTP_INTERFACE_MODE_MTP 0
+#define MTP_INTERFACE_MODE_PTP 1
+
+struct mtp_file_range {
+
+ int fd;
+
+ loff_t offset;
+
+ int64_t length;
+};
+
+struct mtp_event {
+
+ size_t length;
+
+ void *data;
+};
+
+#define MTP_SEND_FILE _IOW('M', 0, struct mtp_file_range)
+
+#define MTP_RECEIVE_FILE _IOW('M', 1, struct mtp_file_range)
+
+#define MTP_SET_INTERFACE_MODE _IOW('M', 2, int)
+
+#define MTP_SEND_EVENT _IOW('M', 3, struct mtp_event)
+
+#endif
diff --git a/libc/kernel/common/media/ov5650.h b/libc/kernel/common/media/ov5650.h
new file mode 100644
index 0000000..3603dc2
--- /dev/null
+++ b/libc/kernel/common/media/ov5650.h
@@ -0,0 +1,63 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __OV5650_H__
+#define __OV5650_H__
+
+#include <linux/ioctl.h>  
+
+#define OV5650_IOCTL_SET_MODE _IOW('o', 1, struct ov5650_mode)
+#define OV5650_IOCTL_SET_FRAME_LENGTH _IOW('o', 2, __u32)
+#define OV5650_IOCTL_SET_COARSE_TIME _IOW('o', 3, __u32)
+#define OV5650_IOCTL_SET_GAIN _IOW('o', 4, __u16)
+#define OV5650_IOCTL_GET_STATUS _IOR('o', 5, __u8)
+#define OV5650_IOCTL_GET_OTP _IOR('o', 6, struct ov5650_otp_data)
+#define OV5650_IOCTL_TEST_PATTERN _IOW('o', 7, enum ov5650_test_pattern)
+
+enum ov5650_test_pattern {
+ TEST_PATTERN_NONE,
+ TEST_PATTERN_COLORBARS,
+ TEST_PATTERN_CHECKERBOARD
+};
+
+struct ov5650_otp_data {
+
+ __u8 sensor_serial_num[6];
+ __u8 part_num[8];
+ __u8 lens_id[1];
+ __u8 manufacture_id[2];
+ __u8 factory_id[2];
+ __u8 manufacture_date[9];
+ __u8 manufacture_line[2];
+
+ __u32 module_serial_num;
+ __u8 focuser_liftoff[2];
+ __u8 focuser_macro[2];
+ __u8 reserved1[12];
+ __u8 shutter_cal[16];
+ __u8 reserved2[183];
+
+ __u16 crc;
+ __u8 reserved3[3];
+ __u8 auto_load[2];
+} __attribute__ ((packed));
+
+struct ov5650_mode {
+ int xres;
+ int yres;
+ __u32 frame_length;
+ __u32 coarse_time;
+ __u16 gain;
+};
+
+#endif
+
+
diff --git a/libc/kernel/common/media/soc2030.h b/libc/kernel/common/media/soc2030.h
new file mode 100644
index 0000000..ad0ddfc
--- /dev/null
+++ b/libc/kernel/common/media/soc2030.h
@@ -0,0 +1,86 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef __SOC2030_H__
+#define __SOC2030_H__
+
+#include <linux/ioctl.h>  
+
+#define SOC2030_IOCTL_SET_MODE _IOWR('o', 1, struct soc2030_mode)
+#define SOC2030_IOCTL_GET_STATUS _IOC(_IOC_READ, 'o', 2, 10)
+#define SOC2030_IOCTL_SET_PRIVATE _IOWR('o', 3, struct soc2030_regs)
+#define SOC2030_IOCTL_GET_MODES _IO('o', 4)
+#define SOC2030_IOCTL_GET_NUM_MODES _IOR('o', 5, unsigned int)
+#define SOC2030_IOCTL_SET_EFFECT _IOWR('o', 6, unsigned int)
+#define SOC2030_IOCTL_SET_WHITEBALANCE _IOWR('o', 7, unsigned int)
+#define SOC2030_IOCTL_SET_EXP_COMP _IOWR('o', 8, int)
+
+#define SOC2030_POLL_WAITMS 50
+#define SOC2030_MAX_RETRIES 3
+#define SOC2030_POLL_RETRIES 5
+
+#define SOC2030_MAX_PRIVATE_SIZE 1024
+#define SOC2030_MAX_NUM_MODES 6
+
+#define SOC_EV_MAX 2
+#define SOC_EV_MIN -2
+#define EXP_TARGET 0x32
+
+enum {
+ REG_TABLE_END,
+ WRITE_REG_DATA,
+ WRITE_REG_BIT_H,
+ WRITE_REG_BIT_L,
+ POLL_REG_DATA,
+ POLL_REG_BIT_H,
+ POLL_REG_BIT_L,
+ WRITE_VAR_DATA,
+ POLL_VAR_DATA,
+ DELAY_MS,
+};
+
+enum {
+ EFFECT_NONE,
+ EFFECT_BW,
+ EFFECT_NEGATIVE,
+ EFFECT_POSTERIZE,
+ EFFECT_SEPIA,
+ EFFECT_SOLARIZE,
+ EFFECT_AQUA,
+ EFFECT_MAX,
+};
+
+enum {
+ WB_AUTO,
+ WB_INCANDESCENT,
+ WB_FLUORESCENT,
+ WB_DAYLIGHT,
+ WB_CLOUDYDAYLIGHT,
+ WB_NIGHT,
+ WB_MAX,
+};
+
+struct soc2030_regs {
+ __u8 op;
+ __u16 addr;
+ __u16 val;
+};
+
+struct soc2030_mode {
+ int xres;
+ int yres;
+ int fps;
+ struct soc2030_regs *regset;
+};
+
+#endif
+
+
diff --git a/libc/kernel/common/media/tegra_camera.h b/libc/kernel/common/media/tegra_camera.h
new file mode 100644
index 0000000..0f63035
--- /dev/null
+++ b/libc/kernel/common/media/tegra_camera.h
@@ -0,0 +1,33 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ ***   This header was automatically generated from a Linux kernel header
+ ***   of the same name, to make information necessary for userspace to
+ ***   call into the kernel available to libc.  It contains only constants,
+ ***   structures, and macros generated from the original header, and thus,
+ ***   contains no copyrightable information.
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+enum {
+ TEGRA_CAMERA_MODULE_ISP = 0,
+ TEGRA_CAMERA_MODULE_VI,
+ TEGRA_CAMERA_MODULE_CSI,
+};
+
+enum {
+ TEGRA_CAMERA_VI_CLK,
+ TEGRA_CAMERA_VI_SENSOR_CLK,
+};
+
+struct tegra_camera_clk_info {
+ uint id;
+ uint clk_id;
+ unsigned long rate;
+};
+
+#define TEGRA_CAMERA_IOCTL_ENABLE _IOWR('i', 1, uint)
+#define TEGRA_CAMERA_IOCTL_DISABLE _IOWR('i', 2, uint)
+#define TEGRA_CAMERA_IOCTL_CLK_SET_RATE   _IOWR('i', 3, struct tegra_camera_clk_info)
+#define TEGRA_CAMERA_IOCTL_RESET _IOWR('i', 4, uint)
+
diff --git a/libc/kernel/tools/clean_header.py b/libc/kernel/tools/clean_header.py
index 28cb05e..dad9120 100755
--- a/libc/kernel/tools/clean_header.py
+++ b/libc/kernel/tools/clean_header.py
@@ -71,6 +71,7 @@
     list.removeEmptyLines()
     list.removeMacroDefines( kernel_ignored_macros )
     list.insertDisclaimer( kernel.kernel_disclaimer )
+    list.replaceTokens( kernel_token_replacements )
 
     out = StringOutput()
     list.write(out)
diff --git a/libc/kernel/tools/cpp.py b/libc/kernel/tools/cpp.py
index 4b4bd38..8828a5d 100644
--- a/libc/kernel/tools/cpp.py
+++ b/libc/kernel/tools/cpp.py
@@ -1863,6 +1863,16 @@
         tokens = tokens[:-1]  # remove trailing tokLN
         self.blocks = [ Block(tokens) ] + self.blocks
 
+    def replaceTokens(self,replacements=dict()):
+        """replace tokens according to the given dict
+           """
+        for b in self.blocks:
+            if not b.isDirective():
+                for tok in b.tokens:
+                    if tok.id == tokIDENT:
+                        if tok.value in replacements:
+                            tok.value = replacements[tok.value]
+
 class BlockParser:
     """a class used to convert an input source file into a BlockList object"""
 
diff --git a/libc/kernel/tools/defaults.py b/libc/kernel/tools/defaults.py
index 4227de7..ca7e6bb 100644
--- a/libc/kernel/tools/defaults.py
+++ b/libc/kernel/tools/defaults.py
@@ -43,6 +43,11 @@
     "x86": {"__i386__": "1"},
     }
 
+# Replace tokens in the output according to this mapping
+kernel_token_replacements = {
+    {"asm": "__asm__"},
+    }
+
 # this is the set of known static inline functions that we want to keep
 # in the final ARM headers. this is only used to keep optimized byteswapping
 # static functions and stuff like that.
@@ -71,6 +76,7 @@
           "__cmsg_nxthdr",                    # linux/socket.h
           "cmsg_nxthdr",                      # linux/socket.h
           "ipt_get_target",
+          "ip6t_get_target",
         ]
     )
 
diff --git a/libc/netbsd/gethnamaddr.c b/libc/netbsd/gethnamaddr.c
index 1c219b2..fb18869 100644
--- a/libc/netbsd/gethnamaddr.c
+++ b/libc/netbsd/gethnamaddr.c
@@ -104,9 +104,9 @@
 static void map_v4v6_hostent(struct hostent *, char **, char *);
 static void addrsort(char **, int, res_state);
 
-void _sethtent(int);
-void _endhtent(void);
-struct hostent *_gethtent(void);
+static void _sethtent(int);
+static void _endhtent(void);
+static struct hostent *_gethtent(void);
 void ht_sethostent(int);
 void ht_endhostent(void);
 struct hostent *ht_gethostbyname(char *);
@@ -114,11 +114,11 @@
 void dns_service(void);
 #undef dn_skipname
 int dn_skipname(const u_char *, const u_char *);
-int _gethtbyaddr(void *, void *, va_list);
-int _gethtbyname(void *, void *, va_list);
-struct hostent *_gethtbyname2(const char *, int);
-int _dns_gethtbyaddr(void *, void *, va_list);
-int _dns_gethtbyname(void *, void *, va_list);
+static int _gethtbyaddr(void *, void *, va_list);
+static int _gethtbyname(void *, void *, va_list);
+static struct hostent *_gethtbyname2(const char *, int);
+static int _dns_gethtbyaddr(void *, void *, va_list);
+static int _dns_gethtbyname(void *, void *, va_list);
 
 static struct hostent *gethostbyname_internal(const char *, int, res_state);
 
@@ -637,7 +637,7 @@
 }
 
 struct hostent *
-gethostbyaddr(const char *addr,	/* XXX should have been def'd as u_char! */
+gethostbyaddr(const void *addr,
     socklen_t len, int af)
 {
 	const u_char *uaddr = (const u_char *)addr;
@@ -692,7 +692,7 @@
 	return hp;
 }
 
-void
+static void
 _sethtent(int f)
 {
     res_static  rs = __res_get_static();
@@ -704,7 +704,7 @@
 	rs->stayopen = f;
 }
 
-void
+static void
 _endhtent(void)
 {
     res_static  rs = __res_get_static();
@@ -716,7 +716,7 @@
 	}
 }
 
-struct hostent *
+static struct hostent *
 _gethtent(void)
 {
 	char *p;
@@ -829,7 +829,7 @@
 	return NS_SUCCESS;
 }
 
-struct hostent *
+static struct hostent *
 _gethtbyname2(const char *name, int af)
 {
 	struct hostent *p;
@@ -920,7 +920,7 @@
 }
 
 /*ARGSUSED*/
-int
+static int
 _gethtbyaddr(void *rv, void *cb_data, va_list ap)
 {
 	struct hostent *p;
@@ -1053,7 +1053,7 @@
 }
 
 /*ARGSUSED*/
-int
+static int
 _dns_gethtbyname(void *rv, void *cb_data, va_list ap)
 {
 	querybuf *buf;
@@ -1113,7 +1113,7 @@
 }
 
 /*ARGSUSED*/
-int
+static int
 _dns_gethtbyaddr(void *rv, void	*cb_data, va_list ap)
 {
 	char qbuf[MAXDNAME + 1], *qp, *ep;
diff --git a/libc/netbsd/net/getaddrinfo.c b/libc/netbsd/net/getaddrinfo.c
index e4d8c56..edb4f70 100644
--- a/libc/netbsd/net/getaddrinfo.c
+++ b/libc/netbsd/net/getaddrinfo.c
@@ -77,10 +77,13 @@
  *	  friends.
  */
 
+#include <fcntl.h>
 #include <sys/cdefs.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <sys/param.h>
 #include <sys/socket.h>
+#include <sys/un.h>
 #include <net/if.h>
 #include <netinet/in.h>
 #include <arpa/inet.h>
@@ -100,6 +103,10 @@
 #include <stdarg.h>
 #include "nsswitch.h"
 
+#ifdef ANDROID_CHANGES
+#include <sys/system_properties.h>
+#endif /* ANDROID_CHANGES */
+
 typedef union sockaddr_union {
     struct sockaddr     generic;
     struct sockaddr_in  in;
@@ -391,6 +398,191 @@
         return _test_connect(PF_INET, &addr.generic, sizeof(addr.in));
 }
 
+// Returns 0 on success, else returns non-zero on error (in which case
+// getaddrinfo should continue as normal)
+static int
+android_getaddrinfo_proxy(
+    const char *hostname, const char *servname,
+    const struct addrinfo *hints, struct addrinfo **res)
+{
+	int sock;
+	const int one = 1;
+	struct sockaddr_un proxy_addr;
+	const char* cache_mode = getenv("ANDROID_DNS_MODE");
+	FILE* proxy = NULL;
+	int success = 0;
+
+	// Clear this at start, as we use its non-NULLness later (in the
+	// error path) to decide if we have to free up any memory we
+	// allocated in the process (before failing).
+	*res = NULL;
+
+	if (cache_mode != NULL && strcmp(cache_mode, "local") == 0) {
+		// Don't use the proxy in local mode.  This is used by the
+		// proxy itself.
+		return -1;
+	}
+
+	// Temporary cautious hack to disable the DNS proxy for processes
+	// requesting special treatment.  Ideally the DNS proxy should
+	// accomodate these apps, though.
+	char propname[PROP_NAME_MAX];
+	char propvalue[PROP_VALUE_MAX];
+	snprintf(propname, sizeof(propname), "net.dns1.%d", getpid());
+	if (__system_property_get(propname, propvalue) > 0) {
+		return -1;
+	}
+
+	// Bogus things we can't serialize.  Don't use the proxy.
+	if ((hostname != NULL &&
+	     strcspn(hostname, " \n\r\t^'\"") != strlen(hostname)) ||
+	    (servname != NULL &&
+	     strcspn(servname, " \n\r\t^'\"") != strlen(servname))) {
+		return -1;
+	}
+
+	sock = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (sock < 0) {
+		return -1;
+	}
+
+	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+	memset(&proxy_addr, 0, sizeof(proxy_addr));
+	proxy_addr.sun_family = AF_UNIX;
+	strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd",
+		sizeof(proxy_addr.sun_path));
+	if (TEMP_FAILURE_RETRY(connect(sock,
+				       (const struct sockaddr*) &proxy_addr,
+				       sizeof(proxy_addr))) != 0) {
+		close(sock);
+		return -1;
+	}
+
+	// Send the request.
+	proxy = fdopen(sock, "r+");
+	if (fprintf(proxy, "getaddrinfo %s %s %d %d %d %d",
+		    hostname == NULL ? "^" : hostname,
+		    servname == NULL ? "^" : servname,
+		    hints == NULL ? -1 : hints->ai_flags,
+		    hints == NULL ? -1 : hints->ai_family,
+		    hints == NULL ? -1 : hints->ai_socktype,
+		    hints == NULL ? -1 : hints->ai_protocol) < 0) {
+		goto exit;
+	}
+	// literal NULL byte at end, required by FrameworkListener
+	if (fputc(0, proxy) == EOF ||
+	    fflush(proxy) != 0) {
+		goto exit;
+	}
+
+	int remote_rv;
+	if (fread(&remote_rv, sizeof(int), 1, proxy) != 1) {
+		goto exit;
+	}
+
+	if (remote_rv != 0) {
+		goto exit;
+	}
+
+	struct addrinfo* ai = NULL;
+	struct addrinfo** nextres = res;
+	while (1) {
+		uint32_t addrinfo_len;
+		if (fread(&addrinfo_len, sizeof(addrinfo_len),
+			  1, proxy) != 1) {
+			break;
+		}
+		addrinfo_len = ntohl(addrinfo_len);
+		if (addrinfo_len == 0) {
+			success = 1;
+			break;
+		}
+
+		if (addrinfo_len < sizeof(struct addrinfo)) {
+			break;
+		}
+		struct addrinfo* ai = calloc(1, addrinfo_len +
+					     sizeof(struct sockaddr_storage));
+		if (ai == NULL) {
+			break;
+		}
+
+		if (fread(ai, addrinfo_len, 1, proxy) != 1) {
+			// Error; fall through.
+			break;
+		}
+
+		// Zero out the pointer fields we copied which aren't
+		// valid in this address space.
+		ai->ai_addr = NULL;
+		ai->ai_canonname = NULL;
+		ai->ai_next = NULL;
+
+		// struct sockaddr
+		uint32_t addr_len;
+		if (fread(&addr_len, sizeof(addr_len), 1, proxy) != 1) {
+			break;
+		}
+		addr_len = ntohl(addr_len);
+		if (addr_len != 0) {
+			if (addr_len > sizeof(struct sockaddr_storage)) {
+				// Bogus; too big.
+				break;
+			}
+			struct sockaddr* addr = (struct sockaddr*)(ai + 1);
+			if (fread(addr, addr_len, 1, proxy) != 1) {
+				break;
+			}
+			ai->ai_addr = addr;
+		}
+
+		// cannonname
+		uint32_t name_len;
+		if (fread(&name_len, sizeof(name_len), 1, proxy) != 1) {
+			break;
+		}
+		name_len = ntohl(name_len);
+		if (name_len != 0) {
+			ai->ai_canonname = (char*) malloc(name_len);
+			if (fread(ai->ai_canonname, name_len, 1, proxy) != 1) {
+				break;
+			}
+			if (ai->ai_canonname[name_len - 1] != '\0') {
+				// The proxy should be returning this
+				// NULL-terminated.
+				break;
+			}
+		}
+
+		*nextres = ai;
+		nextres = &ai->ai_next;
+		ai = NULL;
+	}
+
+	if (ai != NULL) {
+		// Clean up partially-built addrinfo that we never ended up
+		// attaching to the response.
+		freeaddrinfo(ai);
+	}
+exit:
+	if (proxy != NULL) {
+		fclose(proxy);
+	}
+
+	if (success) {
+		return 0;
+	}
+
+	// Proxy failed; fall through to local
+	// resolver case.  But first clean up any
+	// memory we might've allocated.
+	if (*res) {
+		freeaddrinfo(*res);
+		*res = NULL;
+	}
+	return -1;
+}
+
 int
 getaddrinfo(const char *hostname, const char *servname,
     const struct addrinfo *hints, struct addrinfo **res)
@@ -537,6 +729,13 @@
 	if (pai->ai_flags & AI_NUMERICHOST)
 		ERR(EAI_NONAME);
 
+        /*
+         * BEGIN ANDROID CHANGES; proxying to the cache
+         */
+        if (android_getaddrinfo_proxy(hostname, servname, hints, res) == 0) {
+            return 0;
+        }
+
 	/*
 	 * hostname as alphabetical name.
 	 * we would like to prefer AF_INET6 than AF_INET, so we'll make a
diff --git a/libc/netbsd/net/getnameinfo.c b/libc/netbsd/net/getnameinfo.c
index 3666443..d3d0011 100644
--- a/libc/netbsd/net/getnameinfo.c
+++ b/libc/netbsd/net/getnameinfo.c
@@ -64,6 +64,11 @@
 #include <netdb.h>
 #ifdef ANDROID_CHANGES
 #include "resolv_private.h"
+#include <sys/system_properties.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <sys/un.h>
+#include <errno.h>
 #else
 #include <resolv.h>
 #endif
@@ -124,7 +129,98 @@
 	}
 }
 
+#ifdef ANDROID_CHANGES
+/* On success length of the host name is returned. A return
+ * value of 0 means there's no host name associated with
+ * the address. On failure -1 is returned in which case
+ * normal execution flow shall continue. */
+static int
+android_gethostbyaddr_proxy(struct hostent* hp, const void *addr, socklen_t addrLen, int addrFamily) {
 
+	int sock;
+	const int one = 1;
+	struct sockaddr_un proxy_addr;
+	const char* cache_mode = getenv("ANDROID_DNS_MODE");
+	FILE* proxy = NULL;
+	int result = -1;
+
+	if (cache_mode != NULL && strcmp(cache_mode, "local") == 0) {
+		// Don't use the proxy in local mode.  This is used by the
+		// proxy itself.
+		return -1;
+	}
+
+	// Temporary cautious hack to disable the DNS proxy for processes
+	// requesting special treatment.  Ideally the DNS proxy should
+	// accomodate these apps, though.
+	char propname[PROP_NAME_MAX];
+	char propvalue[PROP_VALUE_MAX];
+	snprintf(propname, sizeof(propname), "net.dns1.%d", getpid());
+	if (__system_property_get(propname, propvalue) > 0) {
+		return -1;
+	}
+	// create socket
+	sock = socket(AF_UNIX, SOCK_STREAM, 0);
+	if (sock < 0) {
+		return -1;
+	}
+
+	setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
+	memset(&proxy_addr, 0, sizeof(proxy_addr));
+	proxy_addr.sun_family = AF_UNIX;
+	strlcpy(proxy_addr.sun_path, "/dev/socket/dnsproxyd",
+			sizeof(proxy_addr.sun_path));
+	if (TEMP_FAILURE_RETRY(connect(sock, (const struct sockaddr*) (void*) &proxy_addr,
+							sizeof(proxy_addr))) != 0) {
+		close(sock);
+		return -1;
+	}
+
+	// send request to DnsProxyListener
+	proxy = fdopen(sock,"r+");
+	if (proxy == NULL) {
+		goto exit;
+	}
+
+	char buf[INET6_ADDRSTRLEN]; // big enough for IPv4 and IPv6
+	const char* addrStr = inet_ntop(addrFamily, addr, &buf, sizeof(buf));
+	if (addrStr == NULL) {
+		goto exit;
+	}
+	if (fprintf(proxy, "gethostbyaddr %s %d %d", addrStr, addrLen, addrFamily) < 0) {
+		goto exit;
+	}
+
+	// literal NULL byte at end, required by FrameworkListener
+	if (fputc(0, proxy) == EOF || fflush(proxy) != 0) {
+		goto exit;
+	}
+
+	result = 0;
+	uint32_t name_len;
+	if (fread(&name_len, sizeof(name_len), 1, proxy) != 1) {
+		goto exit;
+	}
+
+	name_len = ntohl(name_len);
+	if (name_len <= 0) {
+		goto exit;
+	}
+
+	if (fread(hp->h_name, name_len, 1, proxy) != 1) {
+		goto exit;
+	}
+
+	result = name_len;
+
+ exit:
+	if (proxy != NULL) {
+		fclose(proxy);
+	}
+
+	return result;
+}
+#endif
 /*
  * getnameinfo_inet():
  * Format an IPv4 or IPv6 sockaddr into a printable string.
@@ -277,7 +373,21 @@
 			break;
 		}
 	} else {
+#ifdef ANDROID_CHANGES
+		struct hostent android_proxy_hostent;
+		char android_proxy_buf[MAXDNAME];
+		android_proxy_hostent.h_name = android_proxy_buf;
+
+		int hostnamelen = android_gethostbyaddr_proxy(&android_proxy_hostent,
+				addr, afd->a_addrlen, afd->a_af);
+		if (hostnamelen >= 0) {
+			hp = (hostnamelen > 0) ? &android_proxy_hostent : NULL;
+		} else {
+			hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+		}
+#else
 		hp = gethostbyaddr(addr, afd->a_addrlen, afd->a_af);
+#endif
 
 		if (hp) {
 #if 0
diff --git a/libc/netbsd/resolv/res_cache.c b/libc/netbsd/resolv/res_cache.c
index 2621a7b..efce7dc 100644
--- a/libc/netbsd/resolv/res_cache.c
+++ b/libc/netbsd/resolv/res_cache.c
@@ -27,17 +27,28 @@
  */
 
 #include "resolv_cache.h"
+#include <resolv.h>
 #include <stdlib.h>
 #include <string.h>
 #include <time.h>
 #include "pthread.h"
 
+#include <errno.h>
+#include "arpa_nameser.h"
+#include <sys/system_properties.h>
+#include <net/if.h>
+#include <netdb.h>
+#include <linux/if.h>
+
+#include <arpa/inet.h>
+#include "resolv_private.h"
+
 /* This code implements a small and *simple* DNS resolver cache.
  *
- * It is only used to cache DNS answers for a maximum of CONFIG_SECONDS seconds
- * in order to reduce DNS traffic. It is not supposed to be a full DNS cache,
- * since we plan to implement that in the future in a dedicated process running
- * on the system.
+ * It is only used to cache DNS answers for a time defined by the smallest TTL
+ * among the answer records in order to reduce DNS traffic. It is not supposed
+ * to be a full DNS cache, since we plan to implement that in the future in a
+ * dedicated process running on the system.
  *
  * Note that its design is kept simple very intentionally, i.e.:
  *
@@ -47,9 +58,8 @@
  *    (this means that two similar queries that encode the DNS name
  *     differently will be treated distinctly).
  *
- *  - the TTLs of answer RRs are ignored. our DNS resolver library does not use
- *    them anyway, but it means that records with a TTL smaller than
- *    CONFIG_SECONDS will be kept in the cache anyway.
+ *    the smallest TTL value among the answer records are used as the time
+ *    to keep an answer in the cache.
  *
  *    this is bad, but we absolutely want to avoid parsing the answer packets
  *    (and should be solved by the later full DNS cache process).
@@ -104,7 +114,7 @@
  */
 #define  CONFIG_SECONDS    (60*10)    /* 10 minutes */
 
-/* maximum number of entries kept in the cache. This value has been
+/* default number of entries kept in the cache. This value has been
  * determined by browsing through various sites and counting the number
  * of corresponding requests. Keep in mind that our framework is currently
  * performing two requests per name lookup (one for IPv4, the other for IPv6)
@@ -123,10 +133,16 @@
  * most high-level websites use lots of media/ad servers with different names
  * but these are generally reused when browsing through the site.
  *
- * As such, a valud of 64 should be relatively conformtable at the moment.
+ * As such, a value of 64 should be relatively comfortable at the moment.
+ *
+ * The system property ro.net.dns_cache_size can be used to override the default
+ * value with a custom value
  */
 #define  CONFIG_MAX_ENTRIES    64
 
+/* name of the system property that can be used to set the cache size */
+#define  DNS_CACHE_SIZE_PROP_NAME   "ro.net.dns_cache_size"
+
 /****************************************************************************/
 /****************************************************************************/
 /*****                                                                  *****/
@@ -141,6 +157,7 @@
 /* set to 1 to debug query data */
 #define  DEBUG_DATA  0
 
+#undef XLOG
 #if DEBUG
 #  include <logd.h>
 #  define  XLOG(...)   \
@@ -987,10 +1004,50 @@
     int              querylen;
     const uint8_t*   answer;
     int              answerlen;
-    time_t           when;   /* time_t when entry was added to table */
-    int              id;     /* for debugging purpose */
+    time_t           expires;   /* time_t when the entry isn't valid any more */
+    int              id;        /* for debugging purpose */
 } Entry;
 
+/**
+ * Parse the answer records and find the smallest
+ * TTL among the answer records.
+ *
+ * The returned TTL is the number of seconds to
+ * keep the answer in the cache.
+ *
+ * In case of parse error zero (0) is returned which
+ * indicates that the answer shall not be cached.
+ */
+static u_long
+answer_getTTL(const void* answer, int answerlen)
+{
+    ns_msg handle;
+    int ancount, n;
+    u_long result, ttl;
+    ns_rr rr;
+
+    result = 0;
+    if (ns_initparse(answer, answerlen, &handle) >= 0) {
+        // get number of answer records
+        ancount = ns_msg_count(handle, ns_s_an);
+        for (n = 0; n < ancount; n++) {
+            if (ns_parserr(&handle, ns_s_an, n, &rr) == 0) {
+                ttl = ns_rr_ttl(rr);
+                if (n == 0 || ttl < result) {
+                    result = ttl;
+                }
+            } else {
+                XLOG("ns_parserr failed ancount no = %d. errno = %s\n", n, strerror(errno));
+            }
+        }
+    } else {
+        XLOG("ns_parserr failed. %s\n", strerror(errno));
+    }
+
+    XLOG("TTL = %d\n", result);
+
+    return result;
+}
 
 static void
 entry_free( Entry*  e )
@@ -1072,8 +1129,6 @@
 
     memcpy( (char*)e->answer, answer, e->answerlen );
 
-    e->when  = _time_now();
-
     return e;
 }
 
@@ -1103,17 +1158,25 @@
  * for simplicity, the hash-table fields 'hash' and 'hlink' are
  * inlined in the Entry structure.
  */
-#define  MAX_HASH_ENTRIES   (2*CONFIG_MAX_ENTRIES)
 
 typedef struct resolv_cache {
+    int              max_entries;
     int              num_entries;
     Entry            mru_list;
     pthread_mutex_t  lock;
     unsigned         generation;
     int              last_id;
-    Entry*           entries[ MAX_HASH_ENTRIES ];
+    Entry*           entries;
 } Cache;
 
+typedef struct resolv_cache_info {
+    char                        ifname[IF_NAMESIZE + 1];
+    struct in_addr              ifaddr;
+    Cache*                      cache;
+    struct resolv_cache_info*   next;
+    char*                       nameservers[MAXNS +1];
+    struct addrinfo*            nsaddrinfo[MAXNS + 1];
+} CacheInfo;
 
 #define  HTABLE_VALID(x)  ((x) != NULL && (x) != HTABLE_DELETED)
 
@@ -1123,9 +1186,9 @@
     int     nn;
     time_t  now = _time_now();
 
-    for (nn = 0; nn < MAX_HASH_ENTRIES; nn++) 
+    for (nn = 0; nn < cache->max_entries; nn++)
     {
-        Entry**  pnode = &cache->entries[nn];
+        Entry**  pnode = (Entry**) &cache->entries[nn];
 
         while (*pnode != NULL) {
             Entry*  node = *pnode;
@@ -1143,17 +1206,48 @@
          "*************************");
 }
 
-struct resolv_cache*
+/* Return max number of entries allowed in the cache,
+ * i.e. cache size. The cache size is either defined
+ * by system property ro.net.dns_cache_size or by
+ * CONFIG_MAX_ENTRIES if system property not set
+ * or set to invalid value. */
+static int
+_res_cache_get_max_entries( void )
+{
+    int result = -1;
+    char cache_size[PROP_VALUE_MAX];
+
+    if (__system_property_get(DNS_CACHE_SIZE_PROP_NAME, cache_size) > 0) {
+        result = atoi(cache_size);
+    }
+
+    // ro.net.dns_cache_size not set or set to negative value
+    if (result <= 0) {
+        result = CONFIG_MAX_ENTRIES;
+    }
+
+    XLOG("cache size: %d", result);
+    return result;
+}
+
+static struct resolv_cache*
 _resolv_cache_create( void )
 {
     struct resolv_cache*  cache;
 
     cache = calloc(sizeof(*cache), 1);
     if (cache) {
-        cache->generation = ~0U;
-        pthread_mutex_init( &cache->lock, NULL );
-        cache->mru_list.mru_prev = cache->mru_list.mru_next = &cache->mru_list;
-        XLOG("%s: cache created\n", __FUNCTION__);
+        cache->max_entries = _res_cache_get_max_entries();
+        cache->entries = calloc(sizeof(*cache->entries), cache->max_entries);
+        if (cache->entries) {
+            cache->generation = ~0U;
+            pthread_mutex_init( &cache->lock, NULL );
+            cache->mru_list.mru_prev = cache->mru_list.mru_next = &cache->mru_list;
+            XLOG("%s: cache created\n", __FUNCTION__);
+        } else {
+            free(cache);
+            cache = NULL;
+        }
     }
     return cache;
 }
@@ -1183,12 +1277,47 @@
 
     XLOG("%s", temp);
 }
+
+static void
+_dump_answer(const void* answer, int answerlen)
+{
+    res_state statep;
+    FILE* fp;
+    char* buf;
+    int fileLen;
+
+    fp = fopen("/data/reslog.txt", "w+");
+    if (fp != NULL) {
+        statep = __res_get_state();
+
+        res_pquery(statep, answer, answerlen, fp);
+
+        //Get file length
+        fseek(fp, 0, SEEK_END);
+        fileLen=ftell(fp);
+        fseek(fp, 0, SEEK_SET);
+        buf = (char *)malloc(fileLen+1);
+        if (buf != NULL) {
+            //Read file contents into buffer
+            fread(buf, fileLen, 1, fp);
+            XLOG("%s\n", buf);
+            free(buf);
+        }
+        fclose(fp);
+        remove("/data/reslog.txt");
+    }
+    else {
+        XLOG("_dump_answer: can't open file\n");
+    }
+}
 #endif
 
 #if DEBUG
 #  define  XLOG_QUERY(q,len)   _dump_query((q), (len))
+#  define  XLOG_ANSWER(a, len) _dump_answer((a), (len))
 #else
 #  define  XLOG_QUERY(q,len)   ((void)0)
+#  define  XLOG_ANSWER(a,len)  ((void)0)
 #endif
 
 /* This function tries to find a key within the hash table
@@ -1209,8 +1338,8 @@
 _cache_lookup_p( Cache*   cache,
                  Entry*   key )
 {
-    int      index = key->hash % MAX_HASH_ENTRIES;
-    Entry**  pnode = &cache->entries[ key->hash % MAX_HASH_ENTRIES ];
+    int      index = key->hash % cache->max_entries;
+    Entry**  pnode = (Entry**) &cache->entries[ index ];
 
     while (*pnode != NULL) {
         Entry*  node = *pnode;
@@ -1322,7 +1451,7 @@
     now = _time_now();
 
     /* remove stale entries here */
-    if ( (unsigned)(now - e->when) >= CONFIG_SECONDS ) {
+    if (now >= e->expires) {
         XLOG( " NOT IN CACHE (STALE ENTRY %p DISCARDED)", *lookup );
         _cache_remove_p(cache, lookup);
         goto Exit;
@@ -1363,6 +1492,7 @@
     Entry    key[1];
     Entry*   e;
     Entry**  lookup;
+    u_long   ttl;
 
     /* don't assume that the query has already been cached
      */
@@ -1375,6 +1505,7 @@
 
     XLOG( "%s: query:", __FUNCTION__ );
     XLOG_QUERY(query,querylen);
+    XLOG_ANSWER(answer, answerlen);
 #if DEBUG_DATA
     XLOG( "answer:");
     XLOG_BYTES(answer,answerlen);
@@ -1389,7 +1520,7 @@
         goto Exit;
     }
 
-    if (cache->num_entries >= CONFIG_MAX_ENTRIES) {
+    if (cache->num_entries >= cache->max_entries) {
         _cache_remove_oldest(cache);
         /* need to lookup again */
         lookup = _cache_lookup_p(cache, key);
@@ -1401,9 +1532,13 @@
         }
     }
 
-    e = entry_alloc( key, answer, answerlen );
-    if (e != NULL) {
-        _cache_add_p(cache, lookup, e);
+    ttl = answer_getTTL(answer, answerlen);
+    if (ttl > 0) {
+        e = entry_alloc(key, answer, answerlen);
+        if (e != NULL) {
+            e->expires = ttl + _time_now();
+            _cache_add_p(cache, lookup, e);
+        }
     }
 #if DEBUG
     _cache_dump_mru(cache);
@@ -1420,11 +1555,47 @@
 /****************************************************************************/
 /****************************************************************************/
 
-static struct resolv_cache*  _res_cache;
 static pthread_once_t        _res_cache_once;
 
+// Head of the list of caches.  Protected by _res_cache_list_lock.
+static struct resolv_cache_info _res_cache_list;
+
+// name of the current default inteface
+static char            _res_default_ifname[IF_NAMESIZE + 1];
+
+// lock protecting everything in the _resolve_cache_info structs (next ptr, etc)
+static pthread_mutex_t _res_cache_list_lock;
+
+
+/* lookup the default interface name */
+static char *_get_default_iface_locked();
+/* insert resolv_cache_info into the list of resolv_cache_infos */
+static void _insert_cache_info_locked(struct resolv_cache_info* cache_info);
+/* creates a resolv_cache_info */
+static struct resolv_cache_info* _create_cache_info( void );
+/* gets cache associated with an interface name, or NULL if none exists */
+static struct resolv_cache* _find_named_cache_locked(const char* ifname);
+/* gets a resolv_cache_info associated with an interface name, or NULL if not found */
+static struct resolv_cache_info* _find_cache_info_locked(const char* ifname);
+/* free dns name server list of a resolv_cache_info structure */
+static void _free_nameservers(struct resolv_cache_info* cache_info);
+/* look up the named cache, and creates one if needed */
+static struct resolv_cache* _get_res_cache_for_iface_locked(const char* ifname);
+/* empty the named cache */
+static void _flush_cache_for_iface_locked(const char* ifname);
+/* empty the nameservers set for the named cache */
+static void _free_nameservers_locked(struct resolv_cache_info* cache_info);
+/* lookup the namserver for the name interface */
+static int _get_nameserver_locked(const char* ifname, int n, char* addr, int addrLen);
+/* lookup the addr of the nameserver for the named interface */
+static struct addrinfo* _get_nameserver_addr_locked(const char* ifname, int n);
+/* lookup the inteface's address */
+static struct in_addr* _get_addr_locked(const char * ifname);
+
+
+
 static void
-_res_cache_init( void )
+_res_cache_init(void)
 {
     const char*  env = getenv(CONFIG_ENV);
 
@@ -1433,29 +1604,392 @@
         return;
     }
 
-    _res_cache = _resolv_cache_create();
+    memset(&_res_default_ifname, 0, sizeof(_res_default_ifname));
+    memset(&_res_cache_list, 0, sizeof(_res_cache_list));
+    pthread_mutex_init(&_res_cache_list_lock, NULL);
 }
 
-
 struct resolv_cache*
-__get_res_cache( void )
+__get_res_cache(void)
 {
-    pthread_once( &_res_cache_once, _res_cache_init );
-    return _res_cache;
+    struct resolv_cache *cache;
+
+    pthread_once(&_res_cache_once, _res_cache_init);
+
+    pthread_mutex_lock(&_res_cache_list_lock);
+
+    char* ifname = _get_default_iface_locked();
+
+    // if default interface not set then use the first cache
+    // associated with an interface as the default one.
+    if (ifname[0] == '\0') {
+        struct resolv_cache_info* cache_info = _res_cache_list.next;
+        while (cache_info) {
+            if (cache_info->ifname[0] != '\0') {
+                ifname = cache_info->ifname;
+            }
+
+            cache_info = cache_info->next;
+        }
+    }
+    cache = _get_res_cache_for_iface_locked(ifname);
+
+    pthread_mutex_unlock(&_res_cache_list_lock);
+    XLOG("_get_res_cache. default_ifname = %s\n", ifname);
+    return cache;
+}
+
+static struct resolv_cache*
+_get_res_cache_for_iface_locked(const char* ifname)
+{
+    if (ifname == NULL)
+        return NULL;
+
+    struct resolv_cache* cache = _find_named_cache_locked(ifname);
+    if (!cache) {
+        struct resolv_cache_info* cache_info = _create_cache_info();
+        if (cache_info) {
+            cache = _resolv_cache_create();
+            if (cache) {
+                int len = sizeof(cache_info->ifname);
+                cache_info->cache = cache;
+                strncpy(cache_info->ifname, ifname, len - 1);
+                cache_info->ifname[len - 1] = '\0';
+
+                _insert_cache_info_locked(cache_info);
+            } else {
+                free(cache_info);
+            }
+        }
+    }
+    return cache;
 }
 
 void
-_resolv_cache_reset( unsigned  generation )
+_resolv_cache_reset(unsigned  generation)
 {
     XLOG("%s: generation=%d", __FUNCTION__, generation);
 
-    if (_res_cache == NULL)
-        return;
+    pthread_once(&_res_cache_once, _res_cache_init);
+    pthread_mutex_lock(&_res_cache_list_lock);
 
-    pthread_mutex_lock( &_res_cache->lock );
-    if (_res_cache->generation != generation) {
-        _cache_flush_locked(_res_cache);
-        _res_cache->generation = generation;
+    char* ifname = _get_default_iface_locked();
+    // if default interface not set then use the first cache
+    // associated with an interface as the default one.
+    // Note: Copied the code from __get_res_cache since this
+    // method will be deleted/obsolete when cache per interface
+    // implemented all over
+    if (ifname[0] == '\0') {
+        struct resolv_cache_info* cache_info = _res_cache_list.next;
+        while (cache_info) {
+            if (cache_info->ifname[0] != '\0') {
+                ifname = cache_info->ifname;
+            }
+
+            cache_info = cache_info->next;
+        }
     }
-    pthread_mutex_unlock( &_res_cache->lock );
+    struct resolv_cache* cache = _get_res_cache_for_iface_locked(ifname);
+
+    if (cache == NULL) {
+        pthread_mutex_unlock(&_res_cache_list_lock);
+        return;
+    }
+
+    pthread_mutex_lock( &cache->lock );
+    if (cache->generation != generation) {
+        _cache_flush_locked(cache);
+        cache->generation = generation;
+    }
+    pthread_mutex_unlock( &cache->lock );
+
+    pthread_mutex_unlock(&_res_cache_list_lock);
+}
+
+void
+_resolv_flush_cache_for_default_iface(void)
+{
+    char* ifname;
+
+    pthread_once(&_res_cache_once, _res_cache_init);
+    pthread_mutex_lock(&_res_cache_list_lock);
+
+    ifname = _get_default_iface_locked();
+    _flush_cache_for_iface_locked(ifname);
+
+    pthread_mutex_unlock(&_res_cache_list_lock);
+}
+
+void
+_resolv_flush_cache_for_iface(const char* ifname)
+{
+    pthread_once(&_res_cache_once, _res_cache_init);
+    pthread_mutex_lock(&_res_cache_list_lock);
+
+    _flush_cache_for_iface_locked(ifname);
+
+    pthread_mutex_unlock(&_res_cache_list_lock);
+}
+
+static void
+_flush_cache_for_iface_locked(const char* ifname)
+{
+    struct resolv_cache* cache = _find_named_cache_locked(ifname);
+    if (cache) {
+        pthread_mutex_lock(&cache->lock);
+        _cache_flush_locked(cache);
+        pthread_mutex_unlock(&cache->lock);
+    }
+}
+
+static struct resolv_cache_info*
+_create_cache_info(void)
+{
+    struct resolv_cache_info*  cache_info;
+
+    cache_info = calloc(sizeof(*cache_info), 1);
+    return cache_info;
+}
+
+static void
+_insert_cache_info_locked(struct resolv_cache_info* cache_info)
+{
+    struct resolv_cache_info* last;
+
+    for (last = &_res_cache_list; last->next; last = last->next);
+
+    last->next = cache_info;
+
+}
+
+static struct resolv_cache*
+_find_named_cache_locked(const char* ifname) {
+
+    struct resolv_cache_info* info = _find_cache_info_locked(ifname);
+
+    if (info != NULL) return info->cache;
+
+    return NULL;
+}
+
+static struct resolv_cache_info*
+_find_cache_info_locked(const char* ifname)
+{
+    if (ifname == NULL)
+        return NULL;
+
+    struct resolv_cache_info* cache_info = _res_cache_list.next;
+
+    while (cache_info) {
+        if (strcmp(cache_info->ifname, ifname) == 0) {
+            break;
+        }
+
+        cache_info = cache_info->next;
+    }
+    return cache_info;
+}
+
+static char*
+_get_default_iface_locked(void)
+{
+    char* iface = _res_default_ifname;
+
+    return iface;
+}
+
+void
+_resolv_set_default_iface(const char* ifname)
+{
+    XLOG("_resolv_set_default_if ifname %s\n",ifname);
+
+    pthread_once(&_res_cache_once, _res_cache_init);
+    pthread_mutex_lock(&_res_cache_list_lock);
+
+    int size = sizeof(_res_default_ifname);
+    memset(_res_default_ifname, 0, size);
+    strncpy(_res_default_ifname, ifname, size - 1);
+    _res_default_ifname[size - 1] = '\0';
+
+    pthread_mutex_unlock(&_res_cache_list_lock);
+}
+
+void
+_resolv_set_nameservers_for_iface(const char* ifname, char** servers, int numservers)
+{
+    int i, rt, index;
+    struct addrinfo hints;
+    char sbuf[NI_MAXSERV];
+
+    pthread_once(&_res_cache_once, _res_cache_init);
+
+    pthread_mutex_lock(&_res_cache_list_lock);
+    // creates the cache if not created
+    _get_res_cache_for_iface_locked(ifname);
+
+    struct resolv_cache_info* cache_info = _find_cache_info_locked(ifname);
+
+    if (cache_info != NULL) {
+        // free current before adding new
+        _free_nameservers_locked(cache_info);
+
+        memset(&hints, 0, sizeof(hints));
+        hints.ai_family = PF_UNSPEC;
+        hints.ai_socktype = SOCK_DGRAM; /*dummy*/
+        hints.ai_flags = AI_NUMERICHOST;
+        sprintf(sbuf, "%u", NAMESERVER_PORT);
+
+        index = 0;
+        for (i = 0; i < numservers && i < MAXNS; i++) {
+            rt = getaddrinfo(servers[i], sbuf, &hints, &cache_info->nsaddrinfo[index]);
+            if (rt == 0) {
+                cache_info->nameservers[index] = strdup(servers[i]);
+                index++;
+            } else {
+                cache_info->nsaddrinfo[index] = NULL;
+            }
+        }
+    }
+    pthread_mutex_unlock(&_res_cache_list_lock);
+}
+
+static void
+_free_nameservers_locked(struct resolv_cache_info* cache_info)
+{
+    int i;
+    for (i = 0; i <= MAXNS; i++) {
+        free(cache_info->nameservers[i]);
+        cache_info->nameservers[i] = NULL;
+        freeaddrinfo(cache_info->nsaddrinfo[i]);
+        cache_info->nsaddrinfo[i] = NULL;
+    }
+}
+
+int
+_resolv_cache_get_nameserver(int n, char* addr, int addrLen)
+{
+    char *ifname;
+    int result = 0;
+
+    pthread_once(&_res_cache_once, _res_cache_init);
+    pthread_mutex_lock(&_res_cache_list_lock);
+
+    ifname = _get_default_iface_locked();
+    result = _get_nameserver_locked(ifname, n, addr, addrLen);
+
+    pthread_mutex_unlock(&_res_cache_list_lock);
+    return result;
+}
+
+static int
+_get_nameserver_locked(const char* ifname, int n, char* addr, int addrLen)
+{
+    int len = 0;
+    char* ns;
+    struct resolv_cache_info* cache_info;
+
+    if (n < 1 || n > MAXNS || !addr)
+        return 0;
+
+    cache_info = _find_cache_info_locked(ifname);
+    if (cache_info) {
+        ns = cache_info->nameservers[n - 1];
+        if (ns) {
+            len = strlen(ns);
+            if (len < addrLen) {
+                strncpy(addr, ns, len);
+                addr[len] = '\0';
+            } else {
+                len = 0;
+            }
+        }
+    }
+
+    return len;
+}
+
+struct addrinfo*
+_cache_get_nameserver_addr(int n)
+{
+    struct addrinfo *result;
+    char* ifname;
+
+    pthread_once(&_res_cache_once, _res_cache_init);
+    pthread_mutex_lock(&_res_cache_list_lock);
+
+    ifname = _get_default_iface_locked();
+
+    result = _get_nameserver_addr_locked(ifname, n);
+    pthread_mutex_unlock(&_res_cache_list_lock);
+    return result;
+}
+
+static struct addrinfo*
+_get_nameserver_addr_locked(const char* ifname, int n)
+{
+    struct addrinfo* ai = NULL;
+    struct resolv_cache_info* cache_info;
+
+    if (n < 1 || n > MAXNS)
+        return NULL;
+
+    cache_info = _find_cache_info_locked(ifname);
+    if (cache_info) {
+        ai = cache_info->nsaddrinfo[n - 1];
+    }
+    return ai;
+}
+
+void
+_resolv_set_addr_of_iface(const char* ifname, struct in_addr* addr)
+{
+    pthread_once(&_res_cache_once, _res_cache_init);
+    pthread_mutex_lock(&_res_cache_list_lock);
+    struct resolv_cache_info* cache_info = _find_cache_info_locked(ifname);
+    if (cache_info) {
+        memcpy(&cache_info->ifaddr, addr, sizeof(*addr));
+
+        if (DEBUG) {
+            char* addr_s = inet_ntoa(cache_info->ifaddr);
+            XLOG("address of interface %s is %s\n", ifname, addr_s);
+        }
+    }
+    pthread_mutex_unlock(&_res_cache_list_lock);
+}
+
+struct in_addr*
+_resolv_get_addr_of_default_iface(void)
+{
+    struct in_addr* ai = NULL;
+    char* ifname;
+
+    pthread_once(&_res_cache_once, _res_cache_init);
+    pthread_mutex_lock(&_res_cache_list_lock);
+    ifname = _get_default_iface_locked();
+    ai = _get_addr_locked(ifname);
+    pthread_mutex_unlock(&_res_cache_list_lock);
+
+    return ai;
+}
+
+struct in_addr*
+_resolv_get_addr_of_iface(const char* ifname)
+{
+    struct in_addr* ai = NULL;
+
+    pthread_once(&_res_cache_once, _res_cache_init);
+    pthread_mutex_lock(&_res_cache_list_lock);
+    ai =_get_addr_locked(ifname);
+    pthread_mutex_unlock(&_res_cache_list_lock);
+    return ai;
+}
+
+static struct in_addr*
+_get_addr_locked(const char * ifname)
+{
+    struct resolv_cache_info* cache_info = _find_cache_info_locked(ifname);
+    if (cache_info) {
+        return &cache_info->ifaddr;
+    }
+    return NULL;
 }
diff --git a/libc/netbsd/resolv/res_data.c b/libc/netbsd/resolv/res_data.c
index e60ecfd..014c99b 100644
--- a/libc/netbsd/resolv/res_data.c
+++ b/libc/netbsd/resolv/res_data.c
@@ -46,6 +46,7 @@
 #include <unistd.h>
 
 
+__LIBC_HIDDEN__
 const char * const _res_opcodes[] = {
 	"QUERY",
 	"IQUERY",
@@ -82,7 +83,7 @@
 int  res_ourserver_p(const res_state, const struct sockaddr *);
 
 #ifdef ANDROID_CHANGES
-int res_need_init() {
+static int res_need_init() {
 	return ((_nres.options & RES_INIT) == 0U) || res_get_dns_changed();
 }
 #else
diff --git a/libc/netbsd/resolv/res_debug.c b/libc/netbsd/resolv/res_debug.c
index 84c6afc..721e015 100644
--- a/libc/netbsd/resolv/res_debug.c
+++ b/libc/netbsd/resolv/res_debug.c
@@ -385,7 +385,7 @@
 /*
  * Names of message sections.
  */
-const struct res_sym __p_default_section_syms[] = {
+static const struct res_sym __p_default_section_syms[] = {
 	{ns_s_qd,	"QUERY",	(char *)0},
 	{ns_s_an,	"ANSWER",	(char *)0},
 	{ns_s_ns,	"AUTHORITY",	(char *)0},
@@ -393,7 +393,7 @@
 	{0,             (char *)0,	(char *)0}
 };
 
-const struct res_sym __p_update_section_syms[] = {
+static const struct res_sym __p_update_section_syms[] = {
 	{S_ZONE,	"ZONE",		(char *)0},
 	{S_PREREQ,	"PREREQUISITE",	(char *)0},
 	{S_UPDATE,	"UPDATE",	(char *)0},
diff --git a/libc/netbsd/resolv/res_init.c b/libc/netbsd/resolv/res_init.c
index 81e570f..ffd4054 100644
--- a/libc/netbsd/resolv/res_init.c
+++ b/libc/netbsd/resolv/res_init.c
@@ -113,8 +113,8 @@
 #define DNS_PROP_NAME_PREFIX "net.dns"
 #define DNS_CHANGE_PROP_NAME "net.dnschange"
 #define DNS_SEARCH_PROP_NAME "net.dns.search"
-const prop_info *dns_change_prop;
-int dns_last_change_counter;
+static const prop_info *dns_change_prop;
+static int dns_last_change_counter;
 static int _get_dns_change_count();
 #else
 #include <resolv.h>
@@ -170,7 +170,7 @@
 }
 
 #ifdef ANDROID_CHANGES
-int load_domain_search_list(res_state statp) {
+static int load_domain_search_list(res_state statp) {
 	char propvalue[PROP_VALUE_MAX];
 	register char *cp, **pp;
 
@@ -225,6 +225,9 @@
 	char dnsProperty[PROP_VALUE_MAX];
 #endif
 
+        if ((statp->options & RES_INIT) != 0U)
+                res_ndestroy(statp);
+
 	if (!preinit) {
 		statp->retrans = RES_TIMEOUT;
 		statp->retry = RES_DFLRETRY;
@@ -232,9 +235,6 @@
 		statp->id = res_randomid();
 	}
 
-	if ((statp->options & RES_INIT) != 0U)
-		res_ndestroy(statp);
-
 	memset(u, 0, sizeof(u));
 #ifdef USELOOPBACK
 	u[nserv].sin.sin_addr = inet_makeaddr(IN_LOOPBACKNET, 1);
diff --git a/libc/netbsd/resolv/res_send.c b/libc/netbsd/resolv/res_send.c
index 696f8cf..b118956 100644
--- a/libc/netbsd/resolv/res_send.c
+++ b/libc/netbsd/resolv/res_send.c
@@ -222,7 +222,7 @@
  * author:
  *	paul vixie, 29may94
  */
-int
+__LIBC_HIDDEN__ int
 res_ourserver_p(const res_state statp, const struct sockaddr *sa) {
 	const struct sockaddr_in *inp, *srv;
 	const struct sockaddr_in6 *in6p, *srv6;
diff --git a/libc/netbsd/resolv/res_state.c b/libc/netbsd/resolv/res_state.c
index 3a2301d..322ace9 100644
--- a/libc/netbsd/resolv/res_state.c
+++ b/libc/netbsd/resolv/res_state.c
@@ -38,21 +38,32 @@
 #define _REALLY_INCLUDE_SYS__SYSTEM_PROPERTIES_H_
 #include <sys/_system_properties.h>
 
+/* Set to 1 to enable debug traces */
+#define DEBUG 0
+
+#if DEBUG
+#  include <logd.h>
+#  include <unistd.h>  /* for gettid() */
+#  define D(...)  __libc_android_log_print(ANDROID_LOG_DEBUG,"libc", __VA_ARGS__)
+#else
+#  define D(...)  do{}while(0)
+#endif
+
 static pthread_key_t   _res_key;
 static pthread_once_t  _res_once;
 
 typedef struct {
-    int                    _h_errno;
-    struct __res_state     _nres[1];
-    unsigned               _serial;
-    struct prop_info*      _pi;
-    struct res_static      _rstatic[1];
+    int                  _h_errno;
+    struct __res_state  _nres[1];
+    unsigned             _serial;
+    struct prop_info*   _pi;
+    struct res_static   _rstatic[1];
 } _res_thread;
 
 static _res_thread*
 _res_thread_alloc(void)
 {
-    _res_thread*  rt = malloc(sizeof(*rt));
+    _res_thread*  rt = calloc(1, sizeof(*rt));
 
     if (rt) {
         rt->_h_errno = 0;
@@ -62,12 +73,7 @@
         if (rt->_pi) {
             rt->_serial = rt->_pi->serial;
         }
-        if ( res_ninit( rt->_nres ) < 0 ) {
-            free(rt);
-            rt = NULL;
-        } else {
-            memset(rt->_rstatic, 0, sizeof rt->_rstatic);
-        }
+        memset(rt->_rstatic, 0, sizeof rt->_rstatic);
     }
     return rt;
 }
@@ -91,6 +97,8 @@
 {
     _res_thread*  rt = _rt;
 
+    D("%s: rt=%p for thread=%d", __FUNCTION__, rt, gettid());
+
     _res_static_done(rt->_rstatic);
     res_ndestroy(rt->_nres);
     free(rt);
@@ -108,32 +116,65 @@
     _res_thread*  rt;
     pthread_once( &_res_once, _res_init_key );
     rt = pthread_getspecific( _res_key );
-    if (rt == NULL) {
-        if ((rt = _res_thread_alloc()) == NULL) {
-            return NULL;
+
+    if (rt != NULL) {
+        /* We already have one thread-specific DNS state object.
+         * Check the serial value for any changes to net.* properties */
+        D("%s: Called for tid=%d rt=%p rt->pi=%p rt->serial=%d",
+           __FUNCTION__, gettid(), rt, rt->_pi, rt->_serial);
+        if (rt->_pi == NULL) {
+            /* The property wasn't created when _res_thread_get() was
+             * called the last time. This should only happen very
+             * early during the boot sequence. First, let's try to see if it
+             * is here now. */
+            rt->_pi = (struct prop_info*) __system_property_find("net.change");
+            if (rt->_pi == NULL) {
+                /* Still nothing, return current state */
+                D("%s: exiting for tid=%d rt=%d since system property not found",
+                  __FUNCTION__, gettid(), rt);
+                return rt;
+            }
         }
-        rt->_h_errno = 0;
-        rt->_serial = 0;
-        pthread_setspecific( _res_key, rt );
+        if (rt->_serial == rt->_pi->serial) {
+            /* Nothing changed, so return the current state */
+            D("%s: tid=%d rt=%p nothing changed, returning",
+              __FUNCTION__, gettid(), rt);
+            return rt;
+        }
+        /* Update the recorded serial number, and go reset the state */
+        rt->_serial = rt->_pi->serial;
+        goto RESET_STATE;
     }
-    /* Check the serial value for any chanes to net.* properties. */
-    if (rt->_pi == NULL) {
-        rt->_pi = (struct prop_info*) __system_property_find("net.change");
+
+    /* It is the first time this function is called in this thread,
+     * we need to create a new thread-specific DNS resolver state. */
+    rt = _res_thread_alloc();
+    if (rt == NULL) {
+        return NULL;
     }
-    if (rt->_pi == NULL || rt->_serial == rt->_pi->serial) {
-        return rt;
-    }
-    rt->_serial = rt->_pi->serial;
-    /* Reload from system properties. */
+    pthread_setspecific( _res_key, rt );
+    D("%s: tid=%d Created new DNS state rt=%p",
+      __FUNCTION__, gettid(), rt);
+
+RESET_STATE:
+    /* Reset the state, note that res_ninit() can now properly reset
+     * an existing state without leaking memory.
+     */
+    D("%s: tid=%d, rt=%p, resetting DNS state (options RES_INIT=%d)",
+      __FUNCTION__, gettid(), rt, (rt->_nres->options & RES_INIT) != 0);
     if ( res_ninit( rt->_nres ) < 0 ) {
-        free(rt);
-        rt = NULL;
-        pthread_setspecific( _res_key, rt );
+        /* This should not happen */
+        D("%s: tid=%d rt=%p, woot, res_ninit() returned < 0",
+          __FUNCTION__, gettid(), rt);
+        _res_thread_free(rt);
+        pthread_setspecific( _res_key, NULL );
+        return NULL;
     }
     _resolv_cache_reset(rt->_serial);
     return rt;
 }
 
+__LIBC_HIDDEN__
 struct __res_state _nres;
 
 #if 0
diff --git a/libc/private/logd.h b/libc/private/logd.h
index 43fa742..4a9b62e 100644
--- a/libc/private/logd.h
+++ b/libc/private/logd.h
@@ -44,6 +44,7 @@
     ANDROID_LOG_SILENT,     /* only for SetMinPriority(); must be last */
 };
 
+int __libc_android_log_write(int prio, const char* tag, const char* buffer);
 int __libc_android_log_print(int prio, const char *tag, const char *fmt, ...);
 int __libc_android_log_vprint(int prio, const char *tag, const char *fmt, va_list ap);
 
diff --git a/libc/private/resolv_cache.h b/libc/private/resolv_cache.h
index cd876fb..2a54453 100644
--- a/libc/private/resolv_cache.h
+++ b/libc/private/resolv_cache.h
@@ -30,13 +30,45 @@
 
 struct resolv_cache;  /* forward */
 
-/* get cache instance, can be NULL if cache is disabled
- * (e.g. through an environment variable) */
+/* gets the cache for the default interface. Might be NULL*/
 extern struct resolv_cache*  __get_res_cache(void);
 
+/* get the cache for a specified interface. Can be NULL*/
+extern struct resolv_cache* __get_res_cache_for_iface(const char* ifname);
+
 /* this gets called everytime we detect some changes in the DNS configuration
  * and will flush the cache */
-extern void   _resolv_cache_reset( unsigned  generation );
+extern void  _resolv_cache_reset( unsigned  generation );
+
+/* Gets the address of the n:th name server for the default interface
+ * Return length of address on success else 0.
+ * Note: The first name server is at n = 1 */
+extern int _resolv_cache_get_nameserver(int n, char* addr, int addrLen);
+
+/* Gets the address of the n:th name server for a certain interface
+ * Return length of address on success else 0.
+ * Note: The first name server is at n = 1 */
+extern int _resolv_cache_get_nameserver_for_iface(const char* ifname, int n,
+        char* addr, int addrLen);
+
+/* Gets addrinfo of the n:th name server associated with an interface.
+ * NULL is returned if no address if found.
+ * Note: The first name server is at n = 1. */
+extern struct addrinfo* _resolv_cache_get_nameserver_addr_for_iface(const char* ifname, int n);
+
+/* Gets addrinfo of the n:th name server associated with the default interface
+ * NULL is returned if no address if found.
+ * Note: The first name server is at n = 1. */
+extern struct addrinfo* _resolv_cache_get_nameserver_addr(int n);
+
+/* gets the address associated with the default interface */
+extern struct in_addr* _resolv_get_addr_of_default_iface();
+
+/* gets the address associated with the specified interface */
+extern struct in_addr* _resolv_get_addr_of_iface(const char* ifname);
+
+/* Get name of default interface */
+extern char* _resolv_get_default_iface();
 
 typedef enum {
     RESOLV_CACHE_UNSUPPORTED,  /* the cache can't handle that kind of queries */
diff --git a/libc/stdio/fgetln.c b/libc/stdio/fgetln.c
index 946e1b7..95a5b31 100644
--- a/libc/stdio/fgetln.c
+++ b/libc/stdio/fgetln.c
@@ -43,7 +43,7 @@
  * so we add 1 here.
 #endif
  */
-int
+static int
 __slbexpand(FILE *fp, size_t newsize)
 {
 	void *p;
diff --git a/libc/stdio/findfp.c b/libc/stdio/findfp.c
index 039293f..1d0f9c5 100644
--- a/libc/stdio/findfp.c
+++ b/libc/stdio/findfp.c
@@ -55,7 +55,7 @@
 static struct __sfileext usualext[FOPEN_MAX - 3];
 static struct glue uglue = { 0, FOPEN_MAX - 3, usual };
 
-struct __sfileext __sFext[3];
+static struct __sfileext __sFext[3];
 FILE __sF[3] = {
 	std(__SRD, STDIN_FILENO),		/* stdin */
 	std(__SWR, STDOUT_FILENO),		/* stdout */
diff --git a/libc/stdio/flockfile.c b/libc/stdio/flockfile.c
index bfb081c..e8c74c5 100644
--- a/libc/stdio/flockfile.c
+++ b/libc/stdio/flockfile.c
@@ -191,7 +191,7 @@
 
 
 /* called from fclose() to remove the file lock */
-void
+__LIBC_HIDDEN__ void
 __fremovelock(FILE*  fp)
 {
     LockTable*  t = lock_table_lock();
diff --git a/libc/stdio/fvwrite.c b/libc/stdio/fvwrite.c
index ee39400..57a57e6 100644
--- a/libc/stdio/fvwrite.c
+++ b/libc/stdio/fvwrite.c
@@ -44,7 +44,7 @@
  * This routine is large and unsightly, but most of the ugliness due
  * to the three different kinds of output buffering is handled here.
  */
-int
+__LIBC_HIDDEN__ int
 __sfvwrite(FILE *fp, struct __suio *uio)
 {
 	size_t len;
diff --git a/libc/stdio/mktemp.c b/libc/stdio/mktemp.c
index 951f803..aaa5640 100644
--- a/libc/stdio/mktemp.c
+++ b/libc/stdio/mktemp.c
@@ -65,7 +65,7 @@
 
 char *_mktemp(char *);
 
-char *
+__LIBC_HIDDEN__ char *
 _mktemp(char *path)
 {
 	return(_gettemp(path, (int *)NULL, 0, 0) ? path : (char *)NULL);
diff --git a/libc/stdio/vfscanf.c b/libc/stdio/vfscanf.c
index dbd0a8b..c48dd36 100644
--- a/libc/stdio/vfscanf.c
+++ b/libc/stdio/vfscanf.c
@@ -159,7 +159,13 @@
 			flags |= MAXINT;
 			goto again;
 		case 'L':
-			flags |= LONGDBL;
+			flags |=
+				(*fmt == 'd') ? LLONG :
+				(*fmt == 'i') ? LLONG :
+				(*fmt == 'o') ? LLONG :
+				(*fmt == 'u') ? LLONG :
+				(*fmt == 'x') ? LLONG :
+				LONGDBL;
 			goto again;
 		case 'h':
 			if (*fmt == 'h') {
diff --git a/libc/stdlib/sha1hash.c b/libc/stdlib/sha1hash.c
deleted file mode 100644
index 1c7aaf3..0000000
--- a/libc/stdlib/sha1hash.c
+++ /dev/null
@@ -1,316 +0,0 @@
-/*
-SHA-1 in C
-By Steve Reid <sreid@sea-to-sky.net>
-100% Public Domain
-
------------------
-Modified 7/98
-By James H. Brown <jbrown@burgoyne.com>
-Still 100% Public Domain
-
-Corrected a problem which generated improper hash values on 16 bit machines
-Routine SHA1Update changed from
-	void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
-len)
-to
-	void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
-long len)
-
-The 'len' parameter was declared an int which works fine on 32 bit machines.
-However, on 16 bit machines an int is too small for the shifts being done
-against
-it.  This caused the hash function to generate incorrect values if len was
-greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
-
-Since the file IO in main() reads 16K at a time, any file 8K or larger would
-be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
-"a"s).
-
-I also changed the declaration of variables i & j in SHA1Update to
-unsigned long from unsigned int for the same reason.
-
-These changes should make no difference to any 32 bit implementations since
-an
-int and a long are the same size in those environments.
-
---
-I also corrected a few compiler warnings generated by Borland C.
-1. Added #include <process.h> for exit() prototype
-2. Removed unused variable 'j' in SHA1Final
-3. Changed exit(0) to return(0) at end of main.
-
-ALL changes I made can be located by searching for comments containing 'JHB'
------------------
-Modified 8/98
-By Steve Reid <sreid@sea-to-sky.net>
-Still 100% public domain
-
-1- Removed #include <process.h> and used return() instead of exit()
-2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
-3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
-
------------------
-Modified 4/01
-By Saul Kravitz <Saul.Kravitz@celera.com>
-Still 100% PD
-Modified to run on Compaq Alpha hardware.
-
------------------
-Modified 2/03
-By H. Peter Anvin <hpa@zytor.com>
-Still 100% PD
-Modified to run on any hardware with <inttypes.h> and <netinet/in.h>
-Changed the driver program
-
-*/
-
-/*
-Test Vectors (from FIPS PUB 180-1)
-"abc"
-  A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
-"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
-  84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
-A million repetitions of "a"
-  34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
-*/
-
-/* #define SHA1HANDSOFF  */
-
-#include <stdio.h>
-#include <string.h>
-#include <inttypes.h>
-#include <netinet/in.h>		/* For htonl/ntohl/htons/ntohs */
-
-/* #include <process.h> */	/* prototype for exit() - JHB */
-/* Using return() instead of exit() - SWR */
-
-typedef struct {
-    uint32_t state[5];
-    uint32_t count[2];
-    unsigned char buffer[64];
-} SHA1_CTX;
-
-void SHA1Transform(uint32_t state[5], unsigned char buffer[64]);
-void SHA1Init(SHA1_CTX* context);
-void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len);	/*
-JHB */
-void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
-
-#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
-
-/* blk0() and blk() perform the initial expand. */
-/* I got the idea of expanding during the round function from SSLeay */
-#define blk0(i) (block->l[i] = ntohl(block->l[i]))
-#define blk(i) (block->l[i&15] = rol(block->l[(i+13)&15]^block->l[(i+8)&15] \
-    ^block->l[(i+2)&15]^block->l[i&15],1))
-
-/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
-#define R0(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk0(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R1(v,w,x,y,z,i) z+=((w&(x^y))^y)+blk(i)+0x5A827999+rol(v,5);w=rol(w,30);
-#define R2(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0x6ED9EBA1+rol(v,5);w=rol(w,30);
-#define R3(v,w,x,y,z,i) z+=(((w|x)&y)|(w&x))+blk(i)+0x8F1BBCDC+rol(v,5);w=rol(w,30);
-#define R4(v,w,x,y,z,i) z+=(w^x^y)+blk(i)+0xCA62C1D6+rol(v,5);w=rol(w,30);
-
-
-#ifdef VERBOSE  /* SAK */
-void SHAPrintContext(SHA1_CTX *context, char *msg){
-  printf("%s (%d,%d) %x %x %x %x %x\n",
-	 msg,
-	 context->count[0], context->count[1],
-	 context->state[0],
-	 context->state[1],
-	 context->state[2],
-	 context->state[3],
-	 context->state[4]);
-}
-#endif
-
-/* Hash a single 512-bit block. This is the core of the algorithm. */
-
-void SHA1Transform(uint32_t state[5], unsigned char buffer[64])
-{
-uint32_t a, b, c, d, e;
-typedef union {
-    unsigned char c[64];
-    uint32_t l[16];
-} CHAR64LONG16;
-CHAR64LONG16* block;
-#ifdef SHA1HANDSOFF
-static unsigned char workspace[64];
-    block = (CHAR64LONG16*)workspace;
-    memcpy(block, buffer, 64);
-#else
-    block = (CHAR64LONG16*)buffer;
-#endif
-    /* Copy context->state[] to working vars */
-    a = state[0];
-    b = state[1];
-    c = state[2];
-    d = state[3];
-    e = state[4];
-    /* 4 rounds of 20 operations each. Loop unrolled. */
-    R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
-    R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
-    R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
-    R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
-    R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
-    R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
-    R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
-    R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
-    R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
-    R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
-    R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
-    R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
-    R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
-    R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
-    R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
-    R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
-    R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
-    R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
-    R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
-    R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
-    /* Add the working vars back into context.state[] */
-    state[0] += a;
-    state[1] += b;
-    state[2] += c;
-    state[3] += d;
-    state[4] += e;
-    /* Wipe variables */
-    a = b = c = d = e = 0;
-}
-
-
-/* SHA1Init - Initialize new context */
-
-void SHA1Init(SHA1_CTX* context)
-{
-    /* SHA1 initialization constants */
-    context->state[0] = 0x67452301;
-    context->state[1] = 0xEFCDAB89;
-    context->state[2] = 0x98BADCFE;
-    context->state[3] = 0x10325476;
-    context->state[4] = 0xC3D2E1F0;
-    context->count[0] = context->count[1] = 0;
-}
-
-
-/* Run your data through this. */
-
-void SHA1Update(SHA1_CTX* context, unsigned char* data, uint32_t len)	/*
-JHB */
-{
-uint32_t i, j;	/* JHB */
-
-#ifdef VERBOSE
-    SHAPrintContext(context, "before");
-#endif
-    j = (context->count[0] >> 3) & 63;
-    if ((context->count[0] += len << 3) < (len << 3)) context->count[1]++;
-    context->count[1] += (len >> 29);
-    if ((j + len) > 63) {
-        memcpy(&context->buffer[j], data, (i = 64-j));
-        SHA1Transform(context->state, context->buffer);
-        for ( ; i + 63 < len; i += 64) {
-            SHA1Transform(context->state, &data[i]);
-        }
-        j = 0;
-    }
-    else i = 0;
-    memcpy(&context->buffer[j], &data[i], len - i);
-#ifdef VERBOSE
-    SHAPrintContext(context, "after ");
-#endif
-}
-
-
-/* Add padding and return the message digest. */
-
-void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
-{
-uint32_t i;	/* JHB */
-unsigned char finalcount[8];
-
-    for (i = 0; i < 8; i++) {
-        finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
-         >> ((3-(i & 3)) * 8) ) & 255);  /* Endian independent */
-    }
-    SHA1Update(context, (unsigned char *)"\200", 1);
-    while ((context->count[0] & 504) != 448) {
-        SHA1Update(context, (unsigned char *)"\0", 1);
-    }
-    SHA1Update(context, finalcount, 8);  /* Should cause a SHA1Transform() */
-    for (i = 0; i < 20; i++) {
-        digest[i] = (unsigned char)
-         ((context->state[i>>2] >> ((3-(i & 3)) * 8) ) & 255);
-    }
-    /* Wipe variables */
-    i = 0;	/* JHB */
-    memset(context->buffer, 0, 64);
-    memset(context->state, 0, 20);
-    memset(context->count, 0, 8);
-    memset(finalcount, 0, 8);	/* SWR */
-#ifdef SHA1HANDSOFF  /* make SHA1Transform overwrite it's own static vars */
-    SHA1Transform(context->state, context->buffer);
-#endif
-}
-
-/*************************************************************/
-
-/* This is not quite the MIME base64 algorithm: it uses _ instead of /,
-   and instead of padding the output with = characters we just make the
-   output shorter. */
-char *mybase64(uint8_t digest[20])
-{
-  static const char charz[] =
-    "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
-  uint8_t input[21];
-  static char output[28];
-  int i, j;
-  uint8_t *p;
-  char *q;
-  uint32_t bv;
-
-  memcpy(input, digest, 20);
-  input[20] = 0;		/* Pad to multiple of 3 bytes */
-
-  p = input;  q = output;
-  for ( i = 0 ; i < 7 ; i++ ) {
-    bv = (p[0] << 16) | (p[1] << 8) | p[2];
-    p += 3;
-    for ( j = 0 ; j < 4 ; j++ ) {
-      *q++ = charz[(bv >> 18) & 0x3f];
-      bv <<= 6;
-    }
-  }
-  *--q = '\0';			/* The last character is not significant */
-  return output;
-}
-
-int main(int argc, char** argv)
-{
-  int i;
-  SHA1_CTX context;
-  uint8_t digest[20], buffer[16384];
-  FILE* file;
-
-  if (argc < 2) {
-    file = stdin;
-  }
-  else {
-    if (!(file = fopen(argv[1], "rb"))) {
-      fputs("Unable to open file.", stderr);
-      return(-1);
-    }
-  }
-  SHA1Init(&context);
-  while (!feof(file)) {  /* note: what if ferror(file) */
-    i = fread(buffer, 1, 16384, file);
-    SHA1Update(&context, buffer, i);
-  }
-  SHA1Final(digest, &context);
-  fclose(file);
-
-  puts(mybase64(digest));
-
-  return 0;
-}
diff --git a/libc/stdlib/strtod.c b/libc/stdlib/strtod.c
index 9d599b0..2851506 100644
--- a/libc/stdlib/strtod.c
+++ b/libc/stdlib/strtod.c
@@ -2062,7 +2062,7 @@
  *	   calculation.
  */
 
- char *
+__LIBC_HIDDEN__  char *
 __dtoa
 #ifdef KR_headers
 	(_d, mode, ndigits, decpt, sign, rve)
diff --git a/libc/stdlib/wchar.c b/libc/stdlib/wchar.c
index 1480212..d83613a 100644
--- a/libc/stdlib/wchar.c
+++ b/libc/stdlib/wchar.c
@@ -302,12 +302,6 @@
     return (wchar_t*) strstr( (const char*)ws1, (const char*)ws2 );
 }
 
-size_t wcsxfrm(wchar_t *ws1, const wchar_t *ws2, size_t n)
-{
-    memcpy( (char*)ws1, (const char*)ws2, n );
-    return n;
-}
-
 int wctob(wint_t c)
 {
     return c;
diff --git a/libc/string/memmove.c b/libc/string/memmove.c
index 98ecfc9..072104b 100644
--- a/libc/string/memmove.c
+++ b/libc/string/memmove.c
@@ -26,6 +26,7 @@
  * SUCH DAMAGE.
  */
 #include <string.h>
+#include <strings.h>
 
 void *memmove(void *dst, const void *src, size_t n)
 {
@@ -37,39 +38,7 @@
   if (__builtin_expect((q < p) || ((size_t)(q - p) >= n), 1)) {
     return memcpy(dst, src, n);
   } else {
-#define PRELOAD_DISTANCE 64
-      /* a semi-optimized memmove(). we're preloading the src and dst buffers
-       * as we go */
-    size_t c0, c1, i;
-    p += n;
-    q += n;
-    /* note: we preload the destination as well, because the 1-byte at a time
-     * copy below doesn't take advantage of the write-buffer, we need
-     * to use the cache instead as a poor man's write-combiner */
-    __builtin_prefetch(p-1);
-    __builtin_prefetch(q-1);
-    if (PRELOAD_DISTANCE > 32) {
-        __builtin_prefetch(p-(32+1));
-        __builtin_prefetch(q-(32+1));
-    }
-    /* do the prefetech as soon as possible, prevent the compiler to
-     * reorder the instructions above the prefetch */
-    asm volatile("":::"memory");
-    c0 = n & 0x1F; /* cache-line is 32 bytes */
-    c1 = n >> 5;
-    while ( c1-- ) {
-        /* ARMv6 can have up to 3 memory access outstanding */
-      __builtin_prefetch(p - (PRELOAD_DISTANCE+1));
-      __builtin_prefetch(q - (PRELOAD_DISTANCE+1));
-      asm volatile("":::"memory");
-      for (i=0 ; i<32 ; i++) {
-        *--q = *--p;
-      }
-    }
-    while ( c0-- ) {
-      *--q = *--p;
-    }
+    bcopy(src, dst, n);
+    return dst;
   }
-
-  return dst;
 }
diff --git a/libc/tools/gensyscalls.py b/libc/tools/gensyscalls.py
index 41c9500..0535e56 100755
--- a/libc/tools/gensyscalls.py
+++ b/libc/tools/gensyscalls.py
@@ -245,6 +245,59 @@
 """
 
 
+def param_uses_64bits(param):
+    """Returns True iff a syscall parameter description corresponds
+       to a 64-bit type."""
+    param = param.strip()
+    # First, check that the param type begins with one of the known
+    # 64-bit types.
+    if not ( \
+       param.startswith("int64_t") or param.startswith("uint64_t") or \
+       param.startswith("loff_t") or param.startswith("off64_t") or \
+       param.startswith("long long") or param.startswith("unsigned long long") or
+       param.startswith("signed long long") ):
+           return False
+
+    # Second, check that there is no pointer type here
+    if param.find("*") >= 0:
+            return False
+
+    # Ok
+    return True
+
+def count_arm_param_registers(params):
+    """This function is used to count the number of register used
+       to pass parameters when invoking a thumb or ARM system call.
+       This is because the ARM EABI mandates that 64-bit quantities
+       must be passed in an even+odd register pair. So, for example,
+       something like:
+
+             foo(int fd, off64_t pos)
+
+       would actually need 4 registers:
+             r0 -> int
+             r1 -> unused
+             r2-r3 -> pos
+   """
+    count = 0
+    for param in params:
+        if param_uses_64bits(param):
+            if (count & 1) != 0:
+                count += 1
+            count += 2
+        else:
+            count += 1
+    return count
+
+def count_generic_param_registers(params):
+    count = 0
+    for param in params:
+        if param_uses_64bits(param):
+            count += 2
+        else:
+            count += 1
+    return count
+
 class State:
     def __init__(self):
         self.old_stubs = []
@@ -370,25 +423,28 @@
             syscall_name   = t["name"]
 
             if t["id"] >= 0:
+                num_regs = count_arm_param_registers(syscall_params)
                 if gen_thumb_stubs:
-                    t["asm-thumb"] = self.thumb_genstub(syscall_func,len(syscall_params),"__NR_"+syscall_name)
+                    t["asm-thumb"] = self.thumb_genstub(syscall_func,num_regs,"__NR_"+syscall_name)
                 else:
                     if gen_eabi_stubs:
-                        t["asm-arm"]   = self.arm_eabi_genstub(syscall_func,len(syscall_params),"__NR_"+syscall_name)
+                        t["asm-arm"]   = self.arm_eabi_genstub(syscall_func,num_regs,"__NR_"+syscall_name)
                     else:
-                        t["asm-arm"]   = self.arm_genstub(syscall_func,len(syscall_params),"__NR_"+syscall_name)
+                        t["asm-arm"]   = self.arm_genstub(syscall_func,num_regs,"__NR_"+syscall_name)
 
             if t["id2"] >= 0:
+                num_regs = count_generic_param_registers(syscall_params)
                 if t["cid"] >= 0:
-                    t["asm-x86"] = self.x86_genstub_cid(syscall_func, len(syscall_params), "__NR_"+syscall_name, t["cid"])
+                    t["asm-x86"] = self.x86_genstub_cid(syscall_func, num_regs, "__NR_"+syscall_name, t["cid"])
                 else:
-                    t["asm-x86"] = self.x86_genstub(syscall_func,len(syscall_params),"__NR_"+syscall_name)
+                    t["asm-x86"] = self.x86_genstub(syscall_func, num_regs, "__NR_"+syscall_name)
             elif t["cid"] >= 0:
                 E("cid for dispatch syscalls is only supported for x86 in "
                   "'%s'" % syscall_name)
                 return
             if t["id3"] >= 0:
-                t["asm-sh"] = self.superh_genstub(syscall_func,len(syscall_params),"__NR_"+syscall_name)
+                num_regs = count_generic_param_registers(syscall_params)
+                t["asm-sh"] = self.superh_genstub(syscall_func,num_regs,"__NR_"+syscall_name)
 
 
 
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 85a913e..e442a03 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -60,6 +60,14 @@
 #  define  XLOG(x)   do{}while (0)
 #endif
 
+/* Add the following function implementations:
+ *  timelocal()
+ *  timegm()
+ *  time2posix()
+ *  posix2time()
+ */
+#define STD_INSPIRED 1
+
 /* THREAD-SAFETY SUPPORT GOES HERE */
 static pthread_mutex_t  _tzMutex = PTHREAD_MUTEX_INITIALIZER;
 
@@ -1509,7 +1517,7 @@
 }
 
 #ifdef STD_INSPIRED
-
+#if 0 /* disabled because there is no good documentation for this function */
 struct tm *
 offtime(timep, offset)
 const time_t * const    timep;
@@ -1517,7 +1525,7 @@
 {
     return gmtsub(timep, offset, &tmGlobal);
 }
-
+#endif /* 0 */
 #endif /* defined STD_INSPIRED */
 
 /*
@@ -2106,6 +2114,7 @@
     return result;
 }
 
+#if 0 /* disable due to lack of clear documentation on this function */
 time_t
 timeoff(tmp, offset)
 struct tm * const   tmp;
@@ -2120,6 +2129,7 @@
 
     return result;
 }
+#endif /* 0 */
 
 #endif /* defined STD_INSPIRED */
 
diff --git a/libc/tzcode/strftime.c b/libc/tzcode/strftime.c
index ab713fb..a2cc3b3 100644
--- a/libc/tzcode/strftime.c
+++ b/libc/tzcode/strftime.c
@@ -407,9 +407,9 @@
                     tm = *t;
                     mkt = mktime64(&tm);
                     if (TYPE_SIGNED(time64_t))
-                        (void) sprintf(buf, "%lld",
+                        (void) snprintf(buf, sizeof(buf), "%lld",
                             (long long) mkt);
-                    else    (void) sprintf(buf, "%llu",
+                    else    (void) snprintf(buf, sizeof(buf), "%llu",
                             (unsigned long long) mkt);
                     pt = _add(buf, pt, ptlim, modifier);
                 }
diff --git a/libc/unistd/abort.c b/libc/unistd/abort.c
index 3e3aab0..8b8659b 100644
--- a/libc/unistd/abort.c
+++ b/libc/unistd/abort.c
@@ -40,7 +40,7 @@
     __libc_android_log_print(ANDROID_LOG_DEBUG, "libc-abort", (format), ##__VA_ARGS__ )
 
 #ifdef __arm__
-void
+__LIBC_HIDDEN__ void
 __libc_android_abort(void)
 #else
 void
diff --git a/libc/unistd/lseek64.c b/libc/unistd/lseek64.c
index 017b331..db0c413 100644
--- a/libc/unistd/lseek64.c
+++ b/libc/unistd/lseek64.c
@@ -29,7 +29,7 @@
 
 extern int __llseek(int fd, unsigned long  offset_hi, unsigned long  offset_lo, loff_t*  result, int  whence);
 
-loff_t lseek64(int fd, loff_t off, int whence)
+off64_t lseek64(int fd, off64_t off, int whence)
 {
     loff_t  result;
 
diff --git a/libc/unistd/pread.c b/libc/unistd/pread.c
index b55623e..42fc3bc 100644
--- a/libc/unistd/pread.c
+++ b/libc/unistd/pread.c
@@ -11,24 +11,25 @@
  *    notice, this list of conditions and the following disclaimer in
  *    the documentation and/or other materials provided with the
  *    distribution.
- * modification, are permitted provided that the following conditions are met:
- *     * Redistributions of source code must retain the above copyright
- *       notice, this list of conditions and the following disclaimer.
- *     * 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.
- *     * Neither the name of Google Inc. 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 COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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 <sys/types.h>
 #include <unistd.h>
 
-extern int __pread64(int fd, void *buf, size_t nbytes, loff_t offset);
-
 ssize_t pread(int fd, void *buf, size_t nbytes, off_t offset)
 {
-    return __pread64(fd, buf, nbytes, offset);
+    return pread64(fd, buf, nbytes, (off64_t)offset);
 }
 
diff --git a/libc/unistd/pwrite.c b/libc/unistd/pwrite.c
index ea080d2..f106cb3 100644
--- a/libc/unistd/pwrite.c
+++ b/libc/unistd/pwrite.c
@@ -28,10 +28,8 @@
 #include <sys/types.h>
 #include <unistd.h>
 
-extern int __pwrite64(int fd, void *buf, size_t nbytes, loff_t offset);
-
-ssize_t pwrite(int fd, void *buf, size_t nbytes, off_t offset)
+ssize_t pwrite(int fd, const void *buf, size_t nbytes, off_t offset)
 {
-    return __pwrite64(fd, buf, nbytes, offset);
+    return pwrite64(fd, buf, nbytes, (off64_t)offset);
 }
 
diff --git a/libc/unistd/raise.c b/libc/unistd/raise.c
index de099da..7b03a7a 100644
--- a/libc/unistd/raise.c
+++ b/libc/unistd/raise.c
@@ -30,5 +30,5 @@
 
 int raise(int signum)
 {
-    return kill(getpid(), signum);
+    return kill(gettid(), signum);
 }
diff --git a/libc/unistd/sigblock.c b/libc/unistd/sigblock.c
index 863d7da..176bc13 100644
--- a/libc/unistd/sigblock.c
+++ b/libc/unistd/sigblock.c
@@ -37,6 +37,7 @@
         sigset_t  the_sigset;
     } in, out;
 
+    sigemptyset(&in.the_sigset);
     in.the_mask = mask;
 
     n = sigprocmask(SIG_BLOCK, &in.the_sigset, &out.the_sigset);
diff --git a/libc/unistd/sigsetmask.c b/libc/unistd/sigsetmask.c
index 4f46458..7842bf1 100644
--- a/libc/unistd/sigsetmask.c
+++ b/libc/unistd/sigsetmask.c
@@ -38,6 +38,7 @@
         sigset_t  the_sigset;
     } in, out;
 
+    sigemptyset(&in.the_sigset);
     in.the_mask = mask;
 
     n = sigprocmask(SIG_SETMASK, &in.the_sigset, &out.the_sigset);
diff --git a/libc/unistd/time.c b/libc/unistd/time.c
index 13d7366..7b450c7 100644
--- a/libc/unistd/time.c
+++ b/libc/unistd/time.c
@@ -34,12 +34,15 @@
 time(time_t *t)
 {
 	struct timeval tt;
+	time_t ret;
 
 	if (gettimeofday(&tt, (struct timezone *)0) < 0)
-		return (-1);
-	if (t)
-		*t = (time_t)tt.tv_sec;
-	return (tt.tv_sec);
+		ret = -1;
+	else
+		ret = tt.tv_sec;
+	if (t != NULL)
+		*t = ret;
+	return ret;
 }
 
 
diff --git a/libc/zoneinfo/MODULE_LICENSE_PUBLIC_DOMAIN b/libc/zoneinfo/MODULE_LICENSE_PUBLIC_DOMAIN
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/libc/zoneinfo/MODULE_LICENSE_PUBLIC_DOMAIN
diff --git a/libc/zoneinfo/zoneinfo.dat b/libc/zoneinfo/zoneinfo.dat
index 27ca5d0..bac23f0 100644
--- a/libc/zoneinfo/zoneinfo.dat
+++ b/libc/zoneinfo/zoneinfo.dat
Binary files differ
diff --git a/libc/zoneinfo/zoneinfo.idx b/libc/zoneinfo/zoneinfo.idx
index 09bd15f..7750e4d 100644
--- a/libc/zoneinfo/zoneinfo.idx
+++ b/libc/zoneinfo/zoneinfo.idx
Binary files differ
diff --git a/libc/zoneinfo/zoneinfo.version b/libc/zoneinfo/zoneinfo.version
index 76dcafb..4abe0cc 100644
--- a/libc/zoneinfo/zoneinfo.version
+++ b/libc/zoneinfo/zoneinfo.version
@@ -1 +1 @@
-2010k
+2011h
diff --git a/libm/Android.mk b/libm/Android.mk
index 28e8f33..29c75a2 100644
--- a/libm/Android.mk
+++ b/libm/Android.mk
@@ -117,6 +117,7 @@
 	src/s_lroundf.c \
 	src/s_lroundl.c \
 	src/s_modff.c \
+	src/s_nan.c \
 	src/s_nearbyint.c \
 	src/s_nextafter.c \
 	src/s_nextafterf.c \
@@ -138,6 +139,7 @@
 	src/s_tanf.c \
 	src/s_tanh.c \
 	src/s_tanhf.c \
+	src/s_tgammaf.c \
 	src/s_trunc.c \
 	src/s_truncf.c \
 	src/s_truncl.c \
diff --git a/libm/include/i387/fenv.h b/libm/include/i387/fenv.h
index 4281f10..5fe64e2 100644
--- a/libm/include/i387/fenv.h
+++ b/libm/include/i387/fenv.h
@@ -131,7 +131,8 @@
 static __inline int
 fegetexceptflag(fexcept_t *__flagp, int __excepts)
 {
-	int __mxcsr, __status;
+	int __mxcsr;
+	short __status;
 
 	__fnstsw(&__status);
 	if (__HAS_SSE())
diff --git a/libm/include/math.h b/libm/include/math.h
index 3b5660f..a86a16f 100644
--- a/libm/include/math.h
+++ b/libm/include/math.h
@@ -251,6 +251,7 @@
 double	logb(double);
 long	lrint(double);
 long	lround(double);
+double	nan(const char *) __pure2;
 double	nextafter(double, double);
 double	remainder(double, double);
 double	remquo(double, double, int *);
@@ -343,6 +344,7 @@
 float	erfcf(float);
 float	hypotf(float, float);
 float	lgammaf(float);
+float	tgammaf(float);
 
 float	acoshf(float);
 float	asinhf(float);
@@ -354,6 +356,7 @@
 long long llroundf(float);
 long	lrintf(float);
 long	lroundf(float);
+float	nanf(const char *) __pure2;
 float	nearbyintf(float);
 float	nextafterf(float, float);
 float	remainderf(float, float);
diff --git a/libm/src/s_nan.c b/libm/src/s_nan.c
new file mode 100644
index 0000000..e366e6b
--- /dev/null
+++ b/libm/src/s_nan.c
@@ -0,0 +1,131 @@
+/*-
+ * Copyright (c) 2007 David Schultz
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#include <sys/endian.h>
+#include <ctype.h>
+#include <float.h>
+#include <math.h>
+#include <stdint.h>
+#include <strings.h>
+
+#include "math_private.h"
+
+/* digittoint is in the FreeBSD C library, but not Bionic at this point */
+static int
+digittoint(char ch)
+{
+    int d;
+
+    d = ch - '0';
+    if ((unsigned)d < 10) {
+        return d;
+    }
+    d = ch - 'a';
+    if ((unsigned)d < 6) {
+        return d + 10;
+    }
+    d = ch - 'A';
+    if ((unsigned)d < 6) {
+        return d + 10;
+    }
+    return -1;
+}
+
+/*
+ * Scan a string of hexadecimal digits (the format nan(3) expects) and
+ * make a bit array (using the local endianness). We stop when we
+ * encounter an invalid character, NUL, etc.  If we overflow, we do
+ * the same as gcc's __builtin_nan(), namely, discard the high order bits.
+ *
+ * The format this routine accepts needs to be compatible with what is used
+ * in contrib/gdtoa/hexnan.c (for strtod/scanf) and what is used in
+ * __builtin_nan(). In fact, we're only 100% compatible for strings we
+ * consider valid, so we might be violating the C standard. But it's
+ * impossible to use nan(3) portably anyway, so this seems good enough.
+ */
+void
+_scan_nan(uint32_t *words, int num_words, const char *s)
+{
+	int si;		/* index into s */
+	int bitpos;	/* index into words (in bits) */
+
+	bzero(words, num_words * sizeof(uint32_t));
+
+	/* Allow a leading '0x'. (It's expected, but redundant.) */
+	if (s[0] == '0' && (s[1] == 'x' || s[1] == 'X'))
+		s += 2;
+
+	/* Scan forwards in the string, looking for the end of the sequence. */
+	for (si = 0; isxdigit(s[si]); si++)
+		;
+
+	/* Scan backwards, filling in the bits in words[] as we go. */
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+	for (bitpos = 0; bitpos < 32 * num_words; bitpos += 4) {
+#else
+	for (bitpos = 32 * num_words - 4; bitpos >= 0; bitpos -= 4) {
+#endif
+		if (--si < 0)
+			break;
+		words[bitpos / 32] |= digittoint(s[si]) << (bitpos % 32);
+	}
+}
+
+double
+nan(const char *s)
+{
+	union {
+		double d;
+		uint32_t bits[2];
+	} u;
+
+	_scan_nan(u.bits, 2, s);
+#if _BYTE_ORDER == _LITTLE_ENDIAN
+	u.bits[1] |= 0x7ff80000;
+#else
+	u.bits[0] |= 0x7ff80000;
+#endif
+	return (u.d);
+}
+
+float
+nanf(const char *s)
+{
+	union {
+		float f;
+		uint32_t bits[1];
+	} u;
+
+	_scan_nan(u.bits, 1, s);
+	u.bits[0] |= 0x7fc00000;
+	return (u.f);
+}
+
+#if (LDBL_MANT_DIG == 53)
+__weak_alias(nanl, nan);
+#endif
diff --git a/libm/src/s_tgammaf.c b/libm/src/s_tgammaf.c
new file mode 100644
index 0000000..9993d91
--- /dev/null
+++ b/libm/src/s_tgammaf.c
@@ -0,0 +1,43 @@
+/*-
+ * Copyright (c) 2008 David Schultz <das@FreeBSD.ORG>
+ * All rights reserved.
+ *
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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 <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <math.h>
+
+/*
+ * We simply call tgamma() rather than bloating the math library with
+ * a float-optimized version of it. The reason is that tgammaf() is
+ * essentially useless, since the function is superexponential and
+ * floats have very limited range.
+ */
+float
+tgammaf(float x)
+{
+
+	return (tgamma(x));
+}
diff --git a/libstdc++/src/new.cpp b/libstdc++/src/new.cpp
index a9c92d4..ddd3dba 100644
--- a/libstdc++/src/new.cpp
+++ b/libstdc++/src/new.cpp
@@ -7,7 +7,7 @@
 {
     void* p = malloc(size);
     if (p == NULL) {
-        // abort();
+        abort();
     }
     return p;
 }
@@ -16,7 +16,7 @@
 {
     void* p = malloc(size);
     if (p == NULL) {
-        // abort();
+        abort();
     }
     return p;
 }
diff --git a/libthread_db/Android.mk b/libthread_db/Android.mk
index 1e6ac15..af506ed 100644
--- a/libthread_db/Android.mk
+++ b/libthread_db/Android.mk
@@ -21,7 +21,7 @@
 
 LOCAL_WHOLE_STATIC_LIBRARIES := libthread_db
 LOCAL_MODULE:=libthread_db
-LOCAL_SHARED_LIBRARIES := libdl
+LOCAL_SHARED_LIBRARIES := libdl libc
 LOCAL_ALLOW_UNDEFINED_SYMBOLS := false
 LOCAL_SYSTEM_SHARED_LIBRARIES :=
 
diff --git a/linker/Android.mk b/linker/Android.mk
index 52f7ce3..e613397 100644
--- a/linker/Android.mk
+++ b/linker/Android.mk
@@ -4,6 +4,7 @@
 LOCAL_SRC_FILES:= \
 	arch/$(TARGET_ARCH)/begin.S \
 	linker.c \
+	linker_environ.c \
 	linker_format.c \
 	rt.c \
 	dlfcn.c \
@@ -94,6 +95,6 @@
 # just for this module
 $(LOCAL_BUILT_MODULE): TARGET_CRTBEGIN_STATIC_O :=
 # This line is not strictly necessary because the dynamic linker is built
-# as a static executable, but it won't hurt if in the future we start 
+# as a static executable, but it won't hurt if in the future we start
 # building the linker as a dynamic one.
 $(LOCAL_BUILT_MODULE): TARGET_CRTBEGIN_DYNAMIC_O :=
diff --git a/linker/linker.c b/linker/linker.c
index 42a5205..00f36c0 100644
--- a/linker/linker.c
+++ b/linker/linker.c
@@ -48,6 +48,7 @@
 
 #include "linker.h"
 #include "linker_debug.h"
+#include "linker_environ.h"
 #include "linker_format.h"
 
 #include "ba.h"
@@ -123,6 +124,9 @@
 int debug_verbosity;
 static int pid;
 
+/* This boolean is set if the program being loaded is setuid */
+static int program_is_setuid;
+
 #if STATS
 struct _link_stats linker_stats;
 #endif
@@ -286,7 +290,7 @@
 
     /* Make sure we get a clean block of soinfo */
     memset(si, 0, sizeof(soinfo));
-    strcpy((char*) si->name, name);
+    strlcpy((char*) si->name, name, sizeof(si->name));
     sonext->next = si;
     si->ba_index = -1; /* by default, prelinked */
     si->next = NULL;
@@ -314,7 +318,7 @@
         return;
     }
 
-    /* prev will never be NULL, because the first entry in solist is 
+    /* prev will never be NULL, because the first entry in solist is
        always the static libdl_info.
     */
     prev->next = si->next;
@@ -818,7 +822,7 @@
 static int reserve_mem_region(soinfo *si)
 {
     void *base = mmap((void *)si->base, si->size, PROT_READ | PROT_EXEC,
-                      MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+                      MAP_FIXED | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
     if (base == MAP_FAILED) {
         DL_ERR("%5d can NOT map (%sprelinked) library '%s' at 0x%08x "
               "as requested, will try general pool: %d (%s)",
@@ -1232,8 +1236,8 @@
     return init_library(si);
 }
 
-/* TODO: 
- *   notify gdb of unload 
+/* TODO:
+ *   notify gdb of unload
  *   for non-prelinked libraries, find a way to decrement libbase
  */
 static void call_destructors(soinfo *si);
@@ -1765,14 +1769,14 @@
             }
 #endif
             if (phdr->p_type == PT_LOAD) {
-                /* For the executable, we use the si->size field only in 
-                   dl_unwind_find_exidx(), so the meaning of si->size 
-                   is not the size of the executable; it is the last 
+                /* For the executable, we use the si->size field only in
+                   dl_unwind_find_exidx(), so the meaning of si->size
+                   is not the size of the executable; it is the last
                    virtual address of the loadable part of the executable;
                    since si->base == 0 for an executable, we use the
-                   range [0, si->size) to determine whether a PC value 
+                   range [0, si->size) to determine whether a PC value
                    falls within the executable section.  Of course, if
-                   a value is below phdr->p_vaddr, it's not in the 
+                   a value is below phdr->p_vaddr, it's not in the
                    executable section, but a) we shouldn't be asking for
                    such a value anyway, and b) if we have to provide
                    an EXIDX for such a value, then the executable's
@@ -1927,7 +1931,7 @@
         }
     }
 
-    DEBUG("%5d si->base = 0x%08x, si->strtab = %p, si->symtab = %p\n", 
+    DEBUG("%5d si->base = 0x%08x, si->strtab = %p, si->symtab = %p\n",
            pid, si->base, si->strtab, si->symtab);
 
     if((si->strtab == 0) || (si->symtab == 0)) {
@@ -2033,7 +2037,7 @@
     ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-02:23.stdio.asc
 
      */
-    if (getuid() != geteuid() || getgid() != getegid())
+    if (program_is_setuid)
         nullify_closed_stdio ();
     call_constructors(si);
     notify_gdb_of_load(si);
@@ -2045,7 +2049,7 @@
     return -1;
 }
 
-static void parse_library_path(char *path, char *delim)
+static void parse_library_path(const char *path, char *delim)
 {
     size_t len;
     char *ldpaths_bufp = ldpaths_buf;
@@ -2068,7 +2072,7 @@
     }
 }
 
-static void parse_preloads(char *path, char *delim)
+static void parse_preloads(const char *path, char *delim)
 {
     size_t len;
     char *ldpreloads_bufp = ldpreloads_buf;
@@ -2110,8 +2114,8 @@
     unsigned *vecs = (unsigned*) (argv + argc + 1);
     soinfo *si;
     struct link_map * map;
-    char *ldpath_env = NULL;
-    char *ldpreload_env = NULL;
+    const char *ldpath_env = NULL;
+    const char *ldpreload_env = NULL;
 
     /* Setup a temporary TLS area that is used to get a working
      * errno for system calls.
@@ -2135,20 +2139,32 @@
      */
     __tls_area[TLS_SLOT_BIONIC_PREINIT] = elfdata;
 
+    /* Are we setuid? */
+    program_is_setuid = (getuid() != geteuid()) || (getgid() != getegid());
+
+    /* Initialize environment functions, and get to the ELF aux vectors table */
+    vecs = linker_env_init(vecs);
+
+    /* Sanitize environment if we're loading a setuid program */
+    if (program_is_setuid)
+        linker_env_secure();
+
     debugger_init();
 
-        /* skip past the environment */
-    while(vecs[0] != 0) {
-        if(!strncmp((char*) vecs[0], "DEBUG=", 6)) {
-            debug_verbosity = atoi(((char*) vecs[0]) + 6);
-        } else if(!strncmp((char*) vecs[0], "LD_LIBRARY_PATH=", 16)) {
-            ldpath_env = (char*) vecs[0] + 16;
-        } else if(!strncmp((char*) vecs[0], "LD_PRELOAD=", 11)) {
-            ldpreload_env = (char*) vecs[0] + 11;
+    /* Get a few environment variables */
+    {
+        const char* env;
+        env = linker_env_get("DEBUG"); /* XXX: TODO: Change to LD_DEBUG */
+        if (env)
+            debug_verbosity = atoi(env);
+
+        /* Normally, these are cleaned by linker_env_secure, but the test
+         * against program_is_setuid doesn't cost us anything */
+        if (!program_is_setuid) {
+            ldpath_env = linker_env_get("LD_LIBRARY_PATH");
+            ldpreload_env = linker_env_get("LD_PRELOAD");
         }
-        vecs++;
     }
-    vecs++;
 
     INFO("[ android linker & debugger ]\n");
     DEBUG("%5d elfdata @ 0x%08x\n", pid, (unsigned)elfdata);
@@ -2176,7 +2192,7 @@
          * is.  Don't use alloc_info(), because the linker shouldn't
          * be on the soinfo list.
          */
-    strcpy((char*) linker_soinfo.name, "/system/bin/linker");
+    strlcpy((char*) linker_soinfo.name, "/system/bin/linker", sizeof linker_soinfo.name);
     linker_soinfo.flags = 0;
     linker_soinfo.base = 0;     // This is the important part; must be zero.
     insert_soinfo_into_debug_map(&linker_soinfo);
@@ -2206,10 +2222,10 @@
     si->refcount = 1;
 
         /* Use LD_LIBRARY_PATH if we aren't setuid/setgid */
-    if (ldpath_env && getuid() == geteuid() && getgid() == getegid())
+    if (ldpath_env)
         parse_library_path(ldpath_env, ":");
 
-    if (ldpreload_env && getuid() == geteuid() && getgid() == getegid()) {
+    if (ldpreload_env) {
         parse_preloads(ldpreload_env, " :");
     }
 
diff --git a/linker/linker_environ.c b/linker/linker_environ.c
new file mode 100644
index 0000000..b71dd80
--- /dev/null
+++ b/linker/linker_environ.c
@@ -0,0 +1,204 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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 "linker_environ.h"
+#include <stddef.h>
+
+static char** _envp;
+
+/* Returns 1 if 'str' points to a valid environment variable definition.
+ * For now, we check that:
+ *  - It is smaller than MAX_ENV_LEN (to detect non-zero terminated strings)
+ *  - It contains at least one equal sign that is not the first character
+ */
+static int
+_is_valid_definition(const char*  str)
+{
+    int   pos = 0;
+    int   first_equal_pos = -1;
+
+    /* According to its sources, the kernel uses 32*PAGE_SIZE by default
+     * as the maximum size for an env. variable definition.
+     */
+    const int MAX_ENV_LEN = 32*4096;
+
+    if (str == NULL)
+        return 0;
+
+    /* Parse the string, looking for the first '=' there, and its size */
+    do {
+        if (str[pos] == '\0')
+            break;
+        if (str[pos] == '=' && first_equal_pos < 0)
+            first_equal_pos = pos;
+        pos++;
+    } while (pos < MAX_ENV_LEN);
+
+    if (pos >= MAX_ENV_LEN)  /* Too large */
+        return 0;
+
+    if (first_equal_pos < 1)  /* No equal sign, or it is the first character */
+        return 0;
+
+    return 1;
+}
+
+unsigned*
+linker_env_init(unsigned* vecs)
+{
+    /* Store environment pointer - can't be NULL */
+    _envp = (char**) vecs;
+
+    /* Skip over all definitions */
+    while (vecs[0] != 0)
+        vecs++;
+    /* The end of the environment block is marked by two NULL pointers */
+    vecs++;
+
+    /* As a sanity check, we're going to remove all invalid variable
+     * definitions from the environment array.
+     */
+    {
+        char** readp  = _envp;
+        char** writep = _envp;
+        for ( ; readp[0] != NULL; readp++ ) {
+            if (!_is_valid_definition(readp[0]))
+                continue;
+            writep[0] = readp[0];
+            writep++;
+        }
+        writep[0] = NULL;
+    }
+
+    /* Return the address of the aux vectors table */
+    return vecs;
+}
+
+/* Check if the environment variable definition at 'envstr'
+ * starts with '<name>=', and if so return the address of the
+ * first character after the equal sign. Otherwise return NULL.
+ */
+static char*
+env_match(char* envstr, const char* name)
+{
+    size_t  cnt = 0;
+
+    while (envstr[cnt] == name[cnt] && name[cnt] != '\0')
+        cnt++;
+
+    if (name[cnt] == '\0' && envstr[cnt] == '=')
+        return envstr + cnt + 1;
+
+    return NULL;
+}
+
+#define MAX_ENV_LEN  (16*4096)
+
+const char*
+linker_env_get(const char* name)
+{
+    char** readp = _envp;
+
+    if (name == NULL || name[0] == '\0')
+        return NULL;
+
+    for ( ; readp[0] != NULL; readp++ ) {
+        char* val = env_match(readp[0], name);
+        if (val != NULL) {
+            /* Return NULL for empty strings, or if it is too large */
+            if (val[0] == '\0')
+                val = NULL;
+            return val;
+        }
+    }
+    return NULL;
+}
+
+
+void
+linker_env_unset(const char* name)
+{
+    char**  readp = _envp;
+    char**  writep = readp;
+
+    if (name == NULL || name[0] == '\0')
+        return;
+
+    for ( ; readp[0] != NULL; readp++ ) {
+        if (env_match(readp[0], name))
+            continue;
+        writep[0] = readp[0];
+        writep++;
+    }
+    /* end list with a NULL */
+    writep[0] = NULL;
+}
+
+
+
+/* Remove unsafe environment variables. This should be used when
+ * running setuid programs. */
+void
+linker_env_secure(void)
+{
+    /* The same list than GLibc at this point */
+    static const char* const unsec_vars[] = {
+        "GCONV_PATH",
+        "GETCONF_DIR",
+        "HOSTALIASES",
+        "LD_AUDIT",
+        "LD_DEBUG",
+        "LD_DEBUG_OUTPUT",
+        "LD_DYNAMIC_WEAK",
+        "LD_LIBRARY_PATH",
+        "LD_ORIGIN_PATH",
+        "LD_PRELOAD",
+        "LD_PROFILE",
+        "LD_SHOW_AUXV",
+        "LD_USE_LOAD_BIAS",
+        "LOCALDOMAIN",
+        "LOCPATH",
+        "MALLOC_TRACE",
+        "MALLOC_CHECK_",
+        "NIS_PATH",
+        "NLSPATH",
+        "RESOLV_HOST_CONF",
+        "RES_OPTIONS",
+        "TMPDIR",
+        "TZDIR",
+        "LD_AOUT_LIBRARY_PATH",
+        "LD_AOUT_PRELOAD",
+    };
+
+    const char* const* cp   = unsec_vars;
+    const char* const* endp = cp + sizeof(unsec_vars)/sizeof(unsec_vars[0]);
+
+    while (cp < endp) {
+        linker_env_unset(*cp);
+        cp++;
+    }
+}
diff --git a/linker/linker_environ.h b/linker/linker_environ.h
new file mode 100644
index 0000000..98ad1de
--- /dev/null
+++ b/linker/linker_environ.h
@@ -0,0 +1,54 @@
+/*
+ * Copyright (C) 2010 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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
+ * COPYRIGHT OWNER 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.
+ */
+#ifndef LINKER_ENVIRON_H
+#define LINKER_ENVIRON_H
+
+/* Call this function before anything else. 'vecs' must be the pointer
+ * to the environment block in the ELF data block. The function returns
+ * the start of the aux vectors after the env block.
+ */
+extern unsigned*   linker_env_init(unsigned* vecs);
+
+/* Unset a given environment variable. In case the variable is defined
+ * multiple times, unset all instances. This modifies the environment
+ * block, so any pointer returned by linker_env_get() after this call
+ * might become invalid */
+extern void        linker_env_unset(const char* name);
+
+
+/* Returns the value of environment variable 'name' if defined and not
+ * empty, or NULL otherwise. Note that the returned pointer may become
+ * invalid if linker_env_unset() or linker_env_secure() are called
+ * after this function. */
+extern const char* linker_env_get(const char* name);
+
+/* Remove unsecure environment variables. This should be used when
+ * running setuid programs. */
+extern void        linker_env_secure(void);
+
+#endif /* LINKER_ENVIRON_H */