Merge "Add cleaned headers for ion to bionic"
diff --git a/libc/Android.mk b/libc/Android.mk
index d8a4b1c..ef0ee47 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -523,6 +523,10 @@
#
libc_crt_target_cflags += -I$(LOCAL_PATH)/private
+ifeq ($(TARGET_ARCH),arm)
+libc_crt_target_cflags += -DCRT_LEGACY_WORKAROUND
+endif
+
# Define some common includes
# ========================================================
libc_common_c_includes := \
@@ -551,18 +555,24 @@
# that will call __cxa_finalize(&__dso_handle) in order to ensure that
# static C++ destructors are properly called on dlclose().
#
+
+libc_crt_target_so_cflags := $(libc_crt_target_cflags)
+ifeq ($(TARGET_ARCH),x86)
+ # This flag must be added for x86 targets, but not for ARM
+ libc_crt_target_so_cflags += -fPIC
+endif
GEN := $(TARGET_OUT_STATIC_LIBRARIES)/crtbegin_so.o
$(GEN): $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtbegin_so.S
@mkdir -p $(dir $@)
- $(TARGET_CC) $(libc_crt_target_cflags) -o $@ -c $<
+ $(TARGET_CC) $(libc_crt_target_so_cflags) -o $@ -c $<
ALL_GENERATED_SOURCES += $(GEN)
GEN := $(TARGET_OUT_STATIC_LIBRARIES)/crtend_so.o
$(GEN): $(LOCAL_PATH)/arch-$(TARGET_ARCH)/bionic/crtend_so.S
@mkdir -p $(dir $@)
- $(TARGET_CC) $(libc_crt_target_cflags) -o $@ -c $<
+ $(TARGET_CC) $(libc_crt_target_so_cflags) -o $@ -c $<
ALL_GENERATED_SOURCES += $(GEN)
-endif # TARGET_ARCH == x86
+endif # TARGET_ARCH == x86 || TARGET_ARCH == arm
GEN := $(TARGET_OUT_STATIC_LIBRARIES)/crtbegin_static.o
@@ -598,6 +608,9 @@
LOCAL_SRC_FILES := $(libc_common_src_files)
LOCAL_CFLAGS := $(libc_common_cflags)
+ifeq ($(TARGET_ARCH),arm)
+LOCAL_CFLAGS += -DCRT_LEGACY_WORKAROUND
+endif
LOCAL_C_INCLUDES := $(libc_common_c_includes)
LOCAL_MODULE := libc_common
LOCAL_SYSTEM_SHARED_LIBRARIES :=
diff --git a/libc/arch-arm/bionic/atexit.S b/libc/arch-arm/bionic/atexit.S
new file mode 100644
index 0000000..aa1e18d
--- /dev/null
+++ b/libc/arch-arm/bionic/atexit.S
@@ -0,0 +1,69 @@
+/*
+ * Copyright (C) 2011 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 CRT_LEGACY_WORKAROUND
+ .arch armv5te
+ .fpu softvfp
+ .eabi_attribute 20, 1
+ .eabi_attribute 21, 1
+ .eabi_attribute 23, 3
+ .eabi_attribute 24, 1
+ .eabi_attribute 25, 1
+ .eabi_attribute 26, 2
+ .eabi_attribute 30, 4
+ .eabi_attribute 18, 4
+ .code 16
+ .section .text.atexit,"ax",%progbits
+ .align 2
+ .global atexit
+ .hidden atexit
+ .code 16
+ .thumb_func
+ .type atexit, %function
+atexit:
+ .fnstart
+.LFB0:
+ .save {r4, lr}
+ push {r4, lr}
+.LCFI0:
+ ldr r3, .L3
+ mov r1, #0
+ @ sp needed for prologue
+.LPIC0:
+ add r3, pc
+ ldr r2, [r3]
+ bl __cxa_atexit
+ pop {r4, pc}
+.L4:
+ .align 2
+.L3:
+ .word __dso_handle-(.LPIC0+4)
+.LFE0:
+ .fnend
+ .size atexit, .-atexit
+#endif
diff --git a/libc/arch-arm/bionic/crtbegin_dynamic.S b/libc/arch-arm/bionic/crtbegin_dynamic.S
index d18e715..0999084 100644
--- a/libc/arch-arm/bionic/crtbegin_dynamic.S
+++ b/libc/arch-arm/bionic/crtbegin_dynamic.S
@@ -85,3 +85,4 @@
.long -1
#include "__dso_handle.S"
+#include "atexit.S"
diff --git a/libc/arch-arm/bionic/crtbegin_so.S b/libc/arch-arm/bionic/crtbegin_so.S
index bb6b3e2..9275b1e 100644
--- a/libc/arch-arm/bionic/crtbegin_so.S
+++ b/libc/arch-arm/bionic/crtbegin_so.S
@@ -52,4 +52,10 @@
.long -1
.long __on_dlclose
+#ifdef CRT_LEGACY_WORKAROUND
#include "__dso_handle.S"
+#else
+#include "__dso_handle_so.S"
+#endif
+
+#include "atexit.S"
diff --git a/libc/arch-arm/bionic/crtbegin_static.S b/libc/arch-arm/bionic/crtbegin_static.S
index 6f9cf25..13b05b2 100644
--- a/libc/arch-arm/bionic/crtbegin_static.S
+++ b/libc/arch-arm/bionic/crtbegin_static.S
@@ -86,3 +86,4 @@
#include "__dso_handle.S"
+#include "atexit.S"
diff --git a/libc/arch-x86/bionic/__stack_chk_fail_local.S b/libc/arch-x86/bionic/__stack_chk_fail_local.S
new file mode 100644
index 0000000..59fe86e
--- /dev/null
+++ b/libc/arch-x86/bionic/__stack_chk_fail_local.S
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2011 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.
+ */
+/*
+ * Contributed by: Intel Corporation
+ */
+
+ .text
+ .p2align 4,,15
+ .globl __stack_chk_fail_local
+ .hidden __stack_chk_fail_local
+ .type __stack_chk_fail_local, @function
+
+__stack_chk_fail_local:
+#ifdef __PIC__
+ pushl %ebx
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ call __stack_chk_fail@PLT
+#else /* PIC */
+ jmp __stack_chk_fail
+#endif /* not PIC */
+
+ .size __stack_chk_fail_local, .-__stack_chk_fail_local
diff --git a/libc/arch-x86/bionic/atexit.S b/libc/arch-x86/bionic/atexit.S
new file mode 100644
index 0000000..b28f40b
--- /dev/null
+++ b/libc/arch-x86/bionic/atexit.S
@@ -0,0 +1,66 @@
+/*
+ * 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.
+ */
+ .text
+ .p2align 4,,15
+ .globl atexit
+ .hidden atexit
+ .type atexit, @function
+atexit:
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %ebx
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ subl $20, %esp
+ movl $0, 4(%esp)
+ movl __dso_handle@GOTOFF(%ebx), %eax
+ movl %eax, 8(%esp)
+ movl 8(%ebp), %eax
+ movl %eax, (%esp)
+ call __cxa_atexit@PLT
+ addl $20, %esp
+ popl %ebx
+ popl %ebp
+ ret
+ .size atexit, .-atexit
+
+ .section .text.__x86.get_pc_thunk.bx,"axG",@progbits,__x86.get_pc_thunk.bx,comdat
+ .globl __x86.get_pc_thunk.bx
+ .hidden __x86.get_pc_thunk.bx
+ .type __x86.get_pc_thunk.bx, @function
+__x86.get_pc_thunk.bx:
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ nop
+ movl (%esp), %ebx
+ ret
diff --git a/libc/arch-x86/bionic/crtbegin_dynamic.S b/libc/arch-x86/bionic/crtbegin_dynamic.S
index 0a7bc62..9ba0d2f 100644
--- a/libc/arch-x86/bionic/crtbegin_dynamic.S
+++ b/libc/arch-x86/bionic/crtbegin_dynamic.S
@@ -76,10 +76,62 @@
.globl __INIT_ARRAY__
__INIT_ARRAY__:
.long -1
+ .long frame_dummy
.section .fini_array, "aw"
.globl __FINI_ARRAY__
__FINI_ARRAY__:
.long -1
+ .long __do_global_dtors_aux
+
+ .section .eh_frame,"a",@progbits
+ .align 4
+ .type __EH_FRAME_BEGIN__, @object
+__EH_FRAME_BEGIN__:
+ .text
+ .p2align 4,,15
+ .type __do_global_dtors_aux, @function
+__do_global_dtors_aux:
+ pushl %ebp
+ movl %esp, %ebp
+ subl $24, %esp
+ cmpb $0, completed.4454
+ jne .L4
+ movl $__deregister_frame_info_bases, %eax
+ testl %eax, %eax
+ je .L3
+ movl $__EH_FRAME_BEGIN__, (%esp)
+ call __deregister_frame_info_bases
+.L3:
+ movb $1, completed.4454
+.L4:
+ leave
+ ret
+ .text
+ .p2align 4,,15
+ .type frame_dummy, @function
+frame_dummy:
+ pushl %ebp
+ movl $__register_frame_info_bases, %eax
+ movl %esp, %ebp
+ subl $24, %esp
+ testl %eax, %eax
+ je .L7
+ movl %ebx, 12(%esp)
+ movl $0, 8(%esp)
+ movl $object.4466, 4(%esp)
+ movl $__EH_FRAME_BEGIN__, (%esp)
+ call __register_frame_info_bases
+.L7:
+ leave
+ ret
+ .local completed.4454
+ .comm completed.4454,1,1
+ .local object.4466
+ .comm object.4466,24,4
+ .weak __register_frame_info_bases
+ .weak __deregister_frame_info_bases
#include "__dso_handle.S"
+#include "atexit.S"
+#include "__stack_chk_fail_local.S"
diff --git a/libc/arch-x86/bionic/crtbegin_so.S b/libc/arch-x86/bionic/crtbegin_so.S
index b3a01b5..99662fe 100644
--- a/libc/arch-x86/bionic/crtbegin_so.S
+++ b/libc/arch-x86/bionic/crtbegin_so.S
@@ -1,9 +1,30 @@
-# This function is to be called when the shared library
-# is unloaded through dlclose()
-_on_dlclose:
- lea __dso_handle, %eax
- call __cxa_finalize
- ret
+/*
+ * 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.
+ */
.section .init_array, "aw"
.align 4
@@ -11,6 +32,7 @@
.globl __INIT_ARRAY__
__INIT_ARRAY__:
.long -1
+ .long frame_dummy
.section .fini_array, "aw"
.align 4
@@ -18,6 +40,72 @@
.globl __FINI_ARRAY__
__FINI_ARRAY__:
.long -1
- .long _on_dlclose
+ .long __do_global_dtors_aux
-#include "__dso_handle.S"
+ .section .eh_frame,"a",@progbits
+ .align 4
+ .type __EH_FRAME_BEGIN__, @object
+__EH_FRAME_BEGIN__:
+ .text
+ .p2align 4,,15
+ .type __do_global_dtors_aux, @function
+__do_global_dtors_aux:
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %ebx
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ subl $20, %esp
+ cmpb $0, completed.4454@GOTOFF(%ebx)
+ jne .L5
+ movl __dso_handle@GOTOFF(%ebx), %eax
+ movl %eax, (%esp)
+ call __cxa_finalize@PLT
+ movl __deregister_frame_info_bases@GOT(%ebx), %eax
+ testl %eax, %eax
+ je .L4
+ leal __EH_FRAME_BEGIN__@GOTOFF(%ebx), %eax
+ movl %eax, (%esp)
+ call __deregister_frame_info_bases@PLT
+.L4:
+ movb $1, completed.4454@GOTOFF(%ebx)
+.L5:
+ addl $20, %esp
+ popl %ebx
+ popl %ebp
+ ret
+ .text
+ .p2align 4,,15
+ .type frame_dummy, @function
+frame_dummy:
+ pushl %ebp
+ movl %esp, %ebp
+ pushl %ebx
+ call __x86.get_pc_thunk.bx
+ addl $_GLOBAL_OFFSET_TABLE_, %ebx
+ subl $20, %esp
+ movl __register_frame_info_bases@GOT(%ebx), %eax
+ testl %eax, %eax
+ je .L8
+ leal object.4469@GOTOFF(%ebx), %eax
+ movl %eax, 4(%esp)
+ leal __EH_FRAME_BEGIN__@GOTOFF(%ebx), %eax
+ movl %ebx, 12(%esp)
+ movl $0, 8(%esp)
+ movl %eax, (%esp)
+ call __register_frame_info_bases@PLT
+.L8:
+ addl $20, %esp
+ popl %ebx
+ popl %ebp
+ ret
+ .local completed.4454
+ .comm completed.4454,1,1
+ .local object.4469
+ .comm object.4469,24,4
+ .weak __register_frame_info_bases
+ .weak __deregister_frame_info_bases
+
+#include "__dso_handle_so.S"
+#include "atexit.S"
+#include "__stack_chk_fail_local.S"
diff --git a/libc/arch-x86/bionic/crtbegin_static.S b/libc/arch-x86/bionic/crtbegin_static.S
index d5c2430..8e70330 100644
--- a/libc/arch-x86/bionic/crtbegin_static.S
+++ b/libc/arch-x86/bionic/crtbegin_static.S
@@ -75,10 +75,62 @@
.globl __INIT_ARRAY__
__INIT_ARRAY__:
.long -1
+ .long frame_dummy
.section .fini_array, "aw"
.globl __FINI_ARRAY__
__FINI_ARRAY__:
.long -1
+ .long __do_global_dtors_aux
+
+ .section .eh_frame,"a",@progbits
+ .align 4
+ .type __EH_FRAME_BEGIN__, @object
+__EH_FRAME_BEGIN__:
+ .text
+ .p2align 4,,15
+ .type __do_global_dtors_aux, @function
+__do_global_dtors_aux:
+ pushl %ebp
+ movl %esp, %ebp
+ subl $24, %esp
+ cmpb $0, completed.4454
+ jne .L4
+ movl $__deregister_frame_info_bases, %eax
+ testl %eax, %eax
+ je .L3
+ movl $__EH_FRAME_BEGIN__, (%esp)
+ call __deregister_frame_info_bases
+.L3:
+ movb $1, completed.4454
+.L4:
+ leave
+ ret
+ .text
+ .p2align 4,,15
+ .type frame_dummy, @function
+frame_dummy:
+ pushl %ebp
+ movl $__register_frame_info_bases, %eax
+ movl %esp, %ebp
+ subl $24, %esp
+ testl %eax, %eax
+ je .L7
+ movl %ebx, 12(%esp)
+ movl $0, 8(%esp)
+ movl $object.4466, 4(%esp)
+ movl $__EH_FRAME_BEGIN__, (%esp)
+ call __register_frame_info_bases
+.L7:
+ leave
+ ret
+ .local completed.4454
+ .comm completed.4454,1,1
+ .local object.4466
+ .comm object.4466,24,4
+ .weak __register_frame_info_bases
+ .weak __deregister_frame_info_bases
#include "__dso_handle.S"
+#include "atexit.S"
+#include "__stack_chk_fail_local.S"
diff --git a/libc/arch-x86/bionic/crtend.S b/libc/arch-x86/bionic/crtend.S
index 884ba8b..68447e7 100644
--- a/libc/arch-x86/bionic/crtend.S
+++ b/libc/arch-x86/bionic/crtend.S
@@ -6,3 +6,10 @@
.section .fini_array, "aw"
.long 0
+
+ .section .eh_frame,"a",@progbits
+ .align 4
+ .type __FRAME_END__, @object
+ .size __FRAME_END__, 4
+__FRAME_END__:
+ .zero 4
diff --git a/libc/arch-x86/bionic/crtend_so.S b/libc/arch-x86/bionic/crtend_so.S
index 8c9d419..63e58b9 100644
--- a/libc/arch-x86/bionic/crtend_so.S
+++ b/libc/arch-x86/bionic/crtend_so.S
@@ -1,6 +1,12 @@
-
.section .init_array, "aw"
.long 0
.section .fini_array, "aw"
.long 0
+
+ .section .eh_frame,"a",@progbits
+ .align 4
+ .type __FRAME_END__, @object
+ .size __FRAME_END__, 4
+__FRAME_END__:
+ .zero 4
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/sys/_errdefs.h b/libc/include/sys/_errdefs.h
index e27ab7a..51d921b 100644
--- a/libc/include/sys/_errdefs.h
+++ b/libc/include/sys/_errdefs.h
@@ -36,6 +36,7 @@
#ifndef __BIONIC_ERRDEF
#error "__BIONIC_ERRDEF must be defined before including this file"
#endif
+__BIONIC_ERRDEF( 0 , 0, "Success" )
__BIONIC_ERRDEF( EPERM , 1, "Operation not permitted" )
__BIONIC_ERRDEF( ENOENT , 2, "No such file or directory" )
__BIONIC_ERRDEF( ESRCH , 3, "No such process" )
diff --git a/libc/inet/inet_pton.c b/libc/inet/inet_pton.c
index 4caf981..6e74e6a 100644
--- a/libc/inet/inet_pton.c
+++ b/libc/inet/inet_pton.c
@@ -1,36 +1,64 @@
-/* $OpenBSD: inet_pton.c,v 1.7 2006/12/30 23:37:37 itojun Exp $ */
+/* $NetBSD: inet_pton.c,v 1.6.10.1 2011/01/10 00:42:17 riz Exp $ */
-/* Copyright (c) 1996 by Internet Software Consortium.
+/*
+ * Copyright (c) 2004 by Internet Systems Consortium, Inc. ("ISC")
+ * Copyright (c) 1996,1999 by Internet Software Consortium.
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
* copyright notice and this permission notice appear in all copies.
*
- * THE SOFTWARE IS PROVIDED "AS IS" AND INTERNET SOFTWARE CONSORTIUM DISCLAIMS
- * ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES
- * OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL INTERNET SOFTWARE
- * CONSORTIUM BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL
- * DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR
- * PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS
- * ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
- * SOFTWARE.
+ * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+ * OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include <sys/cdefs.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static const char rcsid[] = "Id: inet_pton.c,v 1.5 2005/07/28 06:51:47 marka Exp";
+#else
+__RCSID("$NetBSD: inet_pton.c,v 1.6.10.1 2011/01/10 00:42:17 riz Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+// BEGIN android-added
+#define _DIAGASSERT(exp) assert(exp)
+#include "../private/arpa_nameser.h"
+// END android-added
+
+// android-removed: #include "port_before.h"
+
+// android-removed: #include "namespace.h"
#include <sys/param.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
-#include "arpa_nameser.h"
+#include <arpa/nameser.h>
#include <string.h>
+#include <assert.h>
+#include <ctype.h>
#include <errno.h>
-/*
+// android-removed: #include "port_after.h"
+
+// BEGIN android-removed
+// #ifdef __weak_alias
+// __weak_alias(inet_pton,_inet_pton)
+// #endif
+// END android-removed
+
+/*%
* WARNING: Don't even consider trying to compile this on a system where
* sizeof(int) < 4. sizeof(int) > 4 is fine; all the world's not a VAX.
*/
-static int inet_pton4(const char *src, u_char *dst);
+static int inet_pton4(const char *src, u_char *dst, int pton);
static int inet_pton6(const char *src, u_char *dst);
/* int
@@ -47,9 +75,13 @@
int
inet_pton(int af, const char *src, void *dst)
{
+
+ _DIAGASSERT(src != NULL);
+ _DIAGASSERT(dst != NULL);
+
switch (af) {
case AF_INET:
- return (inet_pton4(src, dst));
+ return (inet_pton4(src, dst, 1));
case AF_INET6:
return (inet_pton6(src, dst));
default:
@@ -60,51 +92,123 @@
}
/* int
- * inet_pton4(src, dst)
- * like inet_aton() but without all the hexadecimal and shorthand.
+ * inet_pton4(src, dst, pton)
+ * when last arg is 0: inet_aton(). with hexadecimal, octal and shorthand.
+ * when last arg is 1: inet_pton(). decimal dotted-quad only.
* return:
- * 1 if `src' is a valid dotted quad, else 0.
+ * 1 if `src' is a valid input, else 0.
* notice:
* does not touch `dst' unless it's returning 1.
* author:
* Paul Vixie, 1996.
*/
static int
-inet_pton4(const char *src, u_char *dst)
+inet_pton4(const char *src, u_char *dst, int pton)
{
- static const char digits[] = "0123456789";
- int saw_digit, octets, ch;
- u_char tmp[INADDRSZ], *tp;
+ u_int32_t val;
+ u_int digit, base;
+ int n;
+ unsigned char c;
+ u_int parts[4];
+ register u_int *pp = parts;
- saw_digit = 0;
- octets = 0;
- *(tp = tmp) = 0;
- while ((ch = *src++) != '\0') {
- const char *pch;
+ _DIAGASSERT(src != NULL);
+ _DIAGASSERT(dst != NULL);
- if ((pch = strchr(digits, ch)) != NULL) {
- u_int new = *tp * 10 + (pch - digits);
-
- if (new > 255)
- return (0);
- if (! saw_digit) {
- if (++octets > 4)
- return (0);
- saw_digit = 1;
- }
- *tp = new;
- } else if (ch == '.' && saw_digit) {
- if (octets == 4)
- return (0);
- *++tp = 0;
- saw_digit = 0;
- } else
+ c = *src;
+ for (;;) {
+ /*
+ * Collect number up to ``.''.
+ * Values are specified as for C:
+ * 0x=hex, 0=octal, isdigit=decimal.
+ */
+ if (!isdigit(c))
return (0);
+ val = 0; base = 10;
+ if (c == '0') {
+ c = *++src;
+ if (c == 'x' || c == 'X')
+ base = 16, c = *++src;
+ else if (isdigit(c) && c != '9')
+ base = 8;
+ }
+ /* inet_pton() takes decimal only */
+ if (pton && base != 10)
+ return (0);
+ for (;;) {
+ if (isdigit(c)) {
+ digit = c - '0';
+ if (digit >= base)
+ break;
+ val = (val * base) + digit;
+ c = *++src;
+ } else if (base == 16 && isxdigit(c)) {
+ digit = c + 10 - (islower(c) ? 'a' : 'A');
+ if (digit >= 16)
+ break;
+ val = (val << 4) | digit;
+ c = *++src;
+ } else
+ break;
+ }
+ if (c == '.') {
+ /*
+ * Internet format:
+ * a.b.c.d
+ * a.b.c (with c treated as 16 bits)
+ * a.b (with b treated as 24 bits)
+ * a (with a treated as 32 bits)
+ */
+ if (pp >= parts + 3)
+ return (0);
+ *pp++ = val;
+ c = *++src;
+ } else
+ break;
}
- if (octets < 4)
+ /*
+ * Check for trailing characters.
+ */
+ if (c != '\0' && !isspace(c))
return (0);
+ /*
+ * Concoct the address according to
+ * the number of parts specified.
+ */
+ n = pp - parts + 1;
+ /* inet_pton() takes dotted-quad only. it does not take shorthand. */
+ if (pton && n != 4)
+ return (0);
+ switch (n) {
- memcpy(dst, tmp, INADDRSZ);
+ case 0:
+ return (0); /* initial nondigit */
+
+ case 1: /* a -- 32 bits */
+ break;
+
+ case 2: /* a.b -- 8.24 bits */
+ if (parts[0] > 0xff || val > 0xffffff)
+ return (0);
+ val |= parts[0] << 24;
+ break;
+
+ case 3: /* a.b.c -- 8.8.16 bits */
+ if ((parts[0] | parts[1]) > 0xff || val > 0xffff)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16);
+ break;
+
+ case 4: /* a.b.c.d -- 8.8.8.8 bits */
+ if ((parts[0] | parts[1] | parts[2] | val) > 0xff)
+ return (0);
+ val |= (parts[0] << 24) | (parts[1] << 16) | (parts[2] << 8);
+ break;
+ }
+ if (dst) {
+ val = htonl(val);
+ memcpy(dst, &val, NS_INADDRSZ);
+ }
return (1);
}
@@ -126,20 +230,23 @@
{
static const char xdigits_l[] = "0123456789abcdef",
xdigits_u[] = "0123456789ABCDEF";
- u_char tmp[IN6ADDRSZ], *tp, *endp, *colonp;
+ u_char tmp[NS_IN6ADDRSZ], *tp, *endp, *colonp;
const char *xdigits, *curtok;
- int ch, saw_xdigit, count_xdigit;
+ int ch, seen_xdigits;
u_int val;
- memset((tp = tmp), '\0', IN6ADDRSZ);
- endp = tp + IN6ADDRSZ;
+ _DIAGASSERT(src != NULL);
+ _DIAGASSERT(dst != NULL);
+
+ memset((tp = tmp), '\0', NS_IN6ADDRSZ);
+ endp = tp + NS_IN6ADDRSZ;
colonp = NULL;
/* Leading :: requires some special handling. */
if (*src == ':')
if (*++src != ':')
return (0);
curtok = src;
- saw_xdigit = count_xdigit = 0;
+ seen_xdigits = 0;
val = 0;
while ((ch = *src++) != '\0') {
const char *pch;
@@ -147,46 +254,39 @@
if ((pch = strchr((xdigits = xdigits_l), ch)) == NULL)
pch = strchr((xdigits = xdigits_u), ch);
if (pch != NULL) {
- if (count_xdigit >= 4)
- return (0);
val <<= 4;
val |= (pch - xdigits);
- if (val > 0xffff)
+ if (++seen_xdigits > 4)
return (0);
- saw_xdigit = 1;
- count_xdigit++;
continue;
}
if (ch == ':') {
curtok = src;
- if (!saw_xdigit) {
+ if (!seen_xdigits) {
if (colonp)
return (0);
colonp = tp;
continue;
- } else if (*src == '\0') {
+ } else if (*src == '\0')
return (0);
- }
- if (tp + INT16SZ > endp)
+ if (tp + NS_INT16SZ > endp)
return (0);
*tp++ = (u_char) (val >> 8) & 0xff;
*tp++ = (u_char) val & 0xff;
- saw_xdigit = 0;
- count_xdigit = 0;
+ seen_xdigits = 0;
val = 0;
continue;
}
- if (ch == '.' && ((tp + INADDRSZ) <= endp) &&
- inet_pton4(curtok, tp) > 0) {
- tp += INADDRSZ;
- saw_xdigit = 0;
- count_xdigit = 0;
- break; /* '\0' was seen by inet_pton4(). */
+ if (ch == '.' && ((tp + NS_INADDRSZ) <= endp) &&
+ inet_pton4(curtok, tp, 1) > 0) {
+ tp += NS_INADDRSZ;
+ seen_xdigits = 0;
+ break; /*%< '\\0' was seen by inet_pton4(). */
}
return (0);
}
- if (saw_xdigit) {
- if (tp + INT16SZ > endp)
+ if (seen_xdigits) {
+ if (tp + NS_INT16SZ > endp)
return (0);
*tp++ = (u_char) (val >> 8) & 0xff;
*tp++ = (u_char) val & 0xff;
@@ -199,6 +299,8 @@
const int n = tp - colonp;
int i;
+ if (tp == endp)
+ return (0);
for (i = 1; i <= n; i++) {
endp[- i] = colonp[n - i];
colonp[n - i] = 0;
@@ -207,6 +309,8 @@
}
if (tp != endp)
return (0);
- memcpy(dst, tmp, IN6ADDRSZ);
+ memcpy(dst, tmp, NS_IN6ADDRSZ);
return (1);
}
+
+/*! \file */
diff --git a/libc/kernel/common/asm-generic/resource.h b/libc/kernel/common/asm-generic/resource.h
index a7f7dec..c49b476 100644
--- a/libc/kernel/common/asm-generic/resource.h
+++ b/libc/kernel/common/asm-generic/resource.h
@@ -7,51 +7,57 @@
*** 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 _ASM_GENERIC_RESOURCE_H
#define _ASM_GENERIC_RESOURCE_H
-
#define RLIMIT_CPU 0
#define RLIMIT_FSIZE 1
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define RLIMIT_DATA 2
#define RLIMIT_STACK 3
#define RLIMIT_CORE 4
-
#ifndef RLIMIT_RSS
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define RLIMIT_RSS 5
#endif
-
#ifndef RLIMIT_NPROC
#define RLIMIT_NPROC 6
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#endif
-
#ifndef RLIMIT_NOFILE
#define RLIMIT_NOFILE 7
#endif
-
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#ifndef RLIMIT_MEMLOCK
#define RLIMIT_MEMLOCK 8
#endif
-
#ifndef RLIMIT_AS
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define RLIMIT_AS 9
#endif
-
#define RLIMIT_LOCKS 10
#define RLIMIT_SIGPENDING 11
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define RLIMIT_MSGQUEUE 12
#define RLIMIT_NICE 13
#define RLIMIT_RTPRIO 14
-
-#define RLIM_NLIMITS 15
-
+#define RLIMIT_RTTIME 15
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define RLIM_NLIMITS 16
#ifndef RLIM_INFINITY
#define RLIM_INFINITY (~0UL)
#endif
-
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#ifndef _STK_LIM_MAX
#define _STK_LIM_MAX RLIM_INFINITY
#endif
-
#endif
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
diff --git a/libc/netbsd/resolv/res_cache.c b/libc/netbsd/resolv/res_cache.c
index e6302ed..efce7dc 100644
--- a/libc/netbsd/resolv/res_cache.c
+++ b/libc/netbsd/resolv/res_cache.c
@@ -27,6 +27,7 @@
*/
#include "resolv_cache.h"
+#include <resolv.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
@@ -35,6 +36,12 @@
#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.
*
@@ -159,9 +166,6 @@
#include <stdio.h>
#include <stdarg.h>
-#include <arpa/inet.h>
-#include "resolv_private.h"
-
/** BOUNDED BUFFER FORMATTING
**/
@@ -1165,6 +1169,14 @@
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)
@@ -1543,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);
@@ -1556,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/private/__dso_handle.S b/libc/private/__dso_handle.S
index fcebab6..3e80128 100644
--- a/libc/private/__dso_handle.S
+++ b/libc/private/__dso_handle.S
@@ -32,6 +32,11 @@
#
.section .bss
.align 4
+
+#ifndef CRT_LEGACY_WORKAROUND
+ .hidden __dso_handle
+#endif
+
.globl __dso_handle
__dso_handle:
.long 0
diff --git a/libc/private/__dso_handle_so.S b/libc/private/__dso_handle_so.S
new file mode 100644
index 0000000..77a5d7f
--- /dev/null
+++ b/libc/private/__dso_handle_so.S
@@ -0,0 +1,38 @@
+/*
+ * 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.
+ */
+
+# The __dso_handle global variable is used by static
+# C++ constructors and destructors in the binary.
+# See http://www.codesourcery.com/public/cxx-abi/abi.html#dso-dtor
+#
+ .data
+ .align 4
+ .hidden __dso_handle
+ .globl __dso_handle
+__dso_handle:
+ .long __dso_handle
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/stdlib/atexit.c b/libc/stdlib/atexit.c
index 4ba2177..f4bcab9 100644
--- a/libc/stdlib/atexit.c
+++ b/libc/stdlib/atexit.c
@@ -104,6 +104,7 @@
return (ret);
}
+#ifdef CRT_LEGACY_WORKAROUND
/*
* Register a function to be performed at exit.
*/
@@ -112,6 +113,7 @@
{
return (__cxa_atexit((void (*)(void *))func, NULL, NULL));
}
+#endif
/*
* Call all handlers registered with __cxa_atexit() for the shared
diff --git a/libc/string/strerror_r.c b/libc/string/strerror_r.c
index f43d417..2f26f17 100644
--- a/libc/string/strerror_r.c
+++ b/libc/string/strerror_r.c
@@ -21,7 +21,7 @@
for (;;)
{
- if (strings[nn].code == 0)
+ if (strings[nn].msg == NULL)
break;
if (strings[nn].code == code)
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/time.c b/libc/unistd/time.c
index 4b51675..18aa62c 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;
}
// return monotonically increasing CPU time in ticks relative to unspecified epoch
diff --git a/libc/zoneinfo/zoneinfo.dat b/libc/zoneinfo/zoneinfo.dat
index 7b1bd49..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 984aa00..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 2a4dffc..4abe0cc 100644
--- a/libc/zoneinfo/zoneinfo.version
+++ b/libc/zoneinfo/zoneinfo.version
@@ -1 +1 @@
-2011g
+2011h