Merge "Renamed the misleading libc/netbsd directory to libc/dns."
authorCalin Juravle <calin@google.com>
Tue, 4 Mar 2014 14:25:30 +0000 (14:25 +0000)
committerGerrit Code Review <noreply-gerritcodereview@google.com>
Tue, 4 Mar 2014 14:25:30 +0000 (14:25 +0000)
30 files changed:
libc/Android.mk
libc/SYSCALLS.TXT
libc/arch-arm/syscalls/recvmmsg.S [new file with mode: 0644]
libc/arch-arm/syscalls/sendmmsg.S [new file with mode: 0644]
libc/arch-arm64/syscalls/recvmmsg.S [new file with mode: 0644]
libc/arch-arm64/syscalls/sendmmsg.S [new file with mode: 0644]
libc/arch-mips/syscalls/recvmmsg.S [new file with mode: 0644]
libc/arch-mips/syscalls/sendmmsg.S [new file with mode: 0644]
libc/arch-mips64/syscalls/recvmmsg.S [new file with mode: 0644]
libc/arch-mips64/syscalls/sendmmsg.S [new file with mode: 0644]
libc/arch-x86/syscalls/recvmmsg.S [new file with mode: 0644]
libc/arch-x86/syscalls/sendmmsg.S [new file with mode: 0644]
libc/arch-x86_64/syscalls/recvmmsg.S [new file with mode: 0644]
libc/arch-x86_64/syscalls/sendmmsg.S [new file with mode: 0644]
libc/bionic/mmap.cpp
libc/bionic/pthread_cond.cpp
libc/include/pthread.h
libc/include/stdlib.h
libc/include/sys/klog.h
libc/include/sys/socket.h
libc/tzcode/localtime.c
libc/tzcode/private.h
libc/tzcode/tzfile.h
libc/upstream-openbsd/lib/libc/gen/alarm.c [moved from libc/unistd/alarm.c with 78% similarity]
libc/upstream-openbsd/lib/libc/gen/getprogname.c [new file with mode: 0644]
libc/upstream-openbsd/lib/libc/gen/setprogname.c [new file with mode: 0644]
tests/Android.mk
tests/pthread_test.cpp
tests/sys_socket_test.cpp [new file with mode: 0644]
tests/unistd_test.cpp

index f3a2ce8b883793747b71d018baa0bd83e95d135f..25de501f549e1b9d6cfd147ed502bbef30830c8e 100644 (file)
@@ -104,7 +104,6 @@ libc_common_src_files := \
     stdlib/putenv.c \
     stdlib/setenv.c \
     stdlib/strtod.c \
-    unistd/alarm.c \
     unistd/syslog.c \
     unistd/time.c \
 
@@ -316,11 +315,14 @@ libc_upstream_netbsd_src_files := \
     upstream-netbsd/lib/libc/unistd/killpg.c \
 
 libc_upstream_openbsd_src_files := \
+    upstream-openbsd/lib/libc/gen/alarm.c \
     upstream-openbsd/lib/libc/gen/exec.c \
-    upstream-openbsd/lib/libc/gen/ftok.c \
     upstream-openbsd/lib/libc/gen/fnmatch.c \
-    upstream-openbsd/lib/libc/gen/toupper_.c \
+    upstream-openbsd/lib/libc/gen/ftok.c \
+    upstream-openbsd/lib/libc/gen/getprogname.c \
+    upstream-openbsd/lib/libc/gen/setprogname.c \
     upstream-openbsd/lib/libc/gen/tolower_.c \
+    upstream-openbsd/lib/libc/gen/toupper_.c \
     upstream-openbsd/lib/libc/string/strstr.c \
     upstream-openbsd/lib/libc/string/strsep.c \
     upstream-openbsd/lib/libc/string/wcslcpy.c \
@@ -465,9 +467,6 @@ include $(CLEAR_VARS)
 
 LOCAL_SRC_FILES := bionic/__stack_chk_fail.cpp
 LOCAL_CFLAGS := $(libc_common_cflags) -fno-stack-protector -Werror
-ifeq ($(TARGET_USES_LOGD),yes)
-LOCAL_CFLAGS += -DTARGET_USES_LOGD
-endif
 LOCAL_CONLYFLAGS := $(libc_common_conlyflags)
 LOCAL_CPPFLAGS := $(libc_common_cppflags)
 LOCAL_C_INCLUDES := $(libc_common_c_includes)
@@ -624,6 +623,10 @@ LOCAL_SYSTEM_SHARED_LIBRARIES :=
 # Since this code is experimental it is disabled by default.
 LOCAL_CFLAGS += -DPTHREAD_DEBUG_ENABLED=false
 
+ifeq ($(TARGET_USES_LOGD),true)
+LOCAL_CFLAGS += -DTARGET_USES_LOGD
+endif
+
 $(eval $(call patch-up-arch-specific-flags,LOCAL_CFLAGS,libc_common_cflags))
 $(eval $(call patch-up-arch-specific-flags,LOCAL_SRC_FILES,libc_bionic_src_files))
 include $(BUILD_STATIC_LIBRARY)
index ee3a05b198aae6a7e0d68cad8607af4c162481de..192816816a2d937d6dce02000ae46058f4c8fe54 100644 (file)
@@ -247,6 +247,8 @@ int           setsockopt(int, int, int, const void*, socklen_t)  arm,arm64,mips,
 int           getsockopt(int, int, int, void*, socklen_t*)    arm,arm64,mips,mips64,x86_64
 int           sendmsg(int, const struct msghdr*, unsigned int)  arm,arm64,mips,mips64,x86_64
 int           recvmsg(int, struct msghdr*, unsigned int)   arm,arm64,mips,mips64,x86_64
+int           recvmmsg(int, struct mmsghdr*, unsigned int, int, const struct timespec*)   arm,arm64,mips,mips64,x86_64
+int           sendmmsg(int, struct mmsghdr*, unsigned int, int)   arm,arm64,mips,mips64,x86_64
 
 # sockets for x86. These are done as an "indexed" call to socketcall syscall.
 int           socket:socketcall:1(int, int, int) x86
@@ -264,6 +266,8 @@ int           setsockopt:socketcall:14(int, int, int, const void*, socklen_t)  x
 int           getsockopt:socketcall:15(int, int, int, void*, socklen_t*)    x86
 int           sendmsg:socketcall:16(int, const struct msghdr*, unsigned int)  x86
 int           recvmsg:socketcall:17(int, struct msghdr*, unsigned int)   x86
+int           recvmmsg:socketcall:19(int, struct mmsghdr*, unsigned int, int, const struct timespec*)   x86
+int           sendmmsg:socketcall:20(int, struct mmsghdr*, unsigned int, int)   x86
 
 # scheduler & real-time
 int sched_setscheduler(pid_t pid, int policy, const struct sched_param* param)  all
diff --git a/libc/arch-arm/syscalls/recvmmsg.S b/libc/arch-arm/syscalls/recvmmsg.S
new file mode 100644 (file)
index 0000000..dd8cd8c
--- /dev/null
@@ -0,0 +1,22 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(recvmmsg)
+    mov     ip, sp
+    stmfd   sp!, {r4, r5, r6, r7}
+    .cfi_def_cfa_offset 16
+    .cfi_rel_offset r4, 0
+    .cfi_rel_offset r5, 4
+    .cfi_rel_offset r6, 8
+    .cfi_rel_offset r7, 12
+    ldmfd   ip, {r4, r5, r6}
+    ldr     r7, =__NR_recvmmsg
+    swi     #0
+    ldmfd   sp!, {r4, r5, r6, r7}
+    .cfi_def_cfa_offset 0
+    cmn     r0, #(MAX_ERRNO + 1)
+    bxls    lr
+    neg     r0, r0
+    b       __set_errno
+END(recvmmsg)
diff --git a/libc/arch-arm/syscalls/sendmmsg.S b/libc/arch-arm/syscalls/sendmmsg.S
new file mode 100644 (file)
index 0000000..04c3fe3
--- /dev/null
@@ -0,0 +1,14 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(sendmmsg)
+    mov     ip, r7
+    ldr     r7, =__NR_sendmmsg
+    swi     #0
+    mov     r7, ip
+    cmn     r0, #(MAX_ERRNO + 1)
+    bxls    lr
+    neg     r0, r0
+    b       __set_errno
+END(sendmmsg)
diff --git a/libc/arch-arm64/syscalls/recvmmsg.S b/libc/arch-arm64/syscalls/recvmmsg.S
new file mode 100644 (file)
index 0000000..44875cc
--- /dev/null
@@ -0,0 +1,21 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(recvmmsg)
+    stp     x29, x30, [sp, #-16]!
+    mov     x29,  sp
+    str     x8,       [sp, #-16]!
+
+    mov     x8, __NR_recvmmsg
+    svc     #0
+
+    ldr     x8,       [sp], #16
+    ldp     x29, x30, [sp], #16
+
+    cmn     x0, #(MAX_ERRNO + 1)
+    cneg    x0, x0, hi
+    b.hi    __set_errno
+
+    ret
+END(recvmmsg)
diff --git a/libc/arch-arm64/syscalls/sendmmsg.S b/libc/arch-arm64/syscalls/sendmmsg.S
new file mode 100644 (file)
index 0000000..43b2fbf
--- /dev/null
@@ -0,0 +1,21 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(sendmmsg)
+    stp     x29, x30, [sp, #-16]!
+    mov     x29,  sp
+    str     x8,       [sp, #-16]!
+
+    mov     x8, __NR_sendmmsg
+    svc     #0
+
+    ldr     x8,       [sp], #16
+    ldp     x29, x30, [sp], #16
+
+    cmn     x0, #(MAX_ERRNO + 1)
+    cneg    x0, x0, hi
+    b.hi    __set_errno
+
+    ret
+END(sendmmsg)
diff --git a/libc/arch-mips/syscalls/recvmmsg.S b/libc/arch-mips/syscalls/recvmmsg.S
new file mode 100644 (file)
index 0000000..23e511b
--- /dev/null
@@ -0,0 +1,19 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(recvmmsg)
+    .set noreorder
+    .cpload t9
+    li v0, __NR_recvmmsg
+    syscall
+    bnez a3, 1f
+    move a0, v0
+    j ra
+    nop
+1:
+    la t9,__set_errno
+    j t9
+    nop
+    .set reorder
+END(recvmmsg)
diff --git a/libc/arch-mips/syscalls/sendmmsg.S b/libc/arch-mips/syscalls/sendmmsg.S
new file mode 100644 (file)
index 0000000..d99ba93
--- /dev/null
@@ -0,0 +1,19 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(sendmmsg)
+    .set noreorder
+    .cpload t9
+    li v0, __NR_sendmmsg
+    syscall
+    bnez a3, 1f
+    move a0, v0
+    j ra
+    nop
+1:
+    la t9,__set_errno
+    j t9
+    nop
+    .set reorder
+END(sendmmsg)
diff --git a/libc/arch-mips64/syscalls/recvmmsg.S b/libc/arch-mips64/syscalls/recvmmsg.S
new file mode 100644 (file)
index 0000000..fa9fbb2
--- /dev/null
@@ -0,0 +1,25 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(recvmmsg)
+    .set push
+    .set noreorder
+    li v0, __NR_recvmmsg
+    syscall
+    bnez a3, 1f
+    move a0, v0
+    j ra
+    nop
+1:
+    move t0, ra
+    bal     2f
+    nop
+2:
+    .cpsetup ra, t1, 2b
+    LA t9,__set_errno
+    .cpreturn
+    j t9
+    move ra, t0
+    .set pop
+END(recvmmsg)
diff --git a/libc/arch-mips64/syscalls/sendmmsg.S b/libc/arch-mips64/syscalls/sendmmsg.S
new file mode 100644 (file)
index 0000000..e4d8019
--- /dev/null
@@ -0,0 +1,25 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(sendmmsg)
+    .set push
+    .set noreorder
+    li v0, __NR_sendmmsg
+    syscall
+    bnez a3, 1f
+    move a0, v0
+    j ra
+    nop
+1:
+    move t0, ra
+    bal     2f
+    nop
+2:
+    .cpsetup ra, t1, 2b
+    LA t9,__set_errno
+    .cpreturn
+    j t9
+    move ra, t0
+    .set pop
+END(sendmmsg)
diff --git a/libc/arch-x86/syscalls/recvmmsg.S b/libc/arch-x86/syscalls/recvmmsg.S
new file mode 100644 (file)
index 0000000..a7adac8
--- /dev/null
@@ -0,0 +1,27 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(recvmmsg)
+    pushl   %ebx
+    pushl   %ecx
+    .cfi_def_cfa_offset 8
+    .cfi_rel_offset ebx, 0
+    .cfi_rel_offset ecx, 4
+    mov     $19, %ebx
+    mov     %esp, %ecx
+    addl    $12, %ecx
+    movl    $__NR_socketcall, %eax
+    int     $0x80
+    cmpl    $-MAX_ERRNO, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %ecx
+    popl    %ebx
+    ret
+END(recvmmsg)
diff --git a/libc/arch-x86/syscalls/sendmmsg.S b/libc/arch-x86/syscalls/sendmmsg.S
new file mode 100644 (file)
index 0000000..46dd6cd
--- /dev/null
@@ -0,0 +1,27 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(sendmmsg)
+    pushl   %ebx
+    pushl   %ecx
+    .cfi_def_cfa_offset 8
+    .cfi_rel_offset ebx, 0
+    .cfi_rel_offset ecx, 4
+    mov     $20, %ebx
+    mov     %esp, %ecx
+    addl    $12, %ecx
+    movl    $__NR_socketcall, %eax
+    int     $0x80
+    cmpl    $-MAX_ERRNO, %eax
+    jb      1f
+    negl    %eax
+    pushl   %eax
+    call    __set_errno
+    addl    $4, %esp
+    orl     $-1, %eax
+1:
+    popl    %ecx
+    popl    %ebx
+    ret
+END(sendmmsg)
diff --git a/libc/arch-x86_64/syscalls/recvmmsg.S b/libc/arch-x86_64/syscalls/recvmmsg.S
new file mode 100644 (file)
index 0000000..9da70e2
--- /dev/null
@@ -0,0 +1,17 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(recvmmsg)
+    movq    %rcx, %r10
+    movl    $__NR_recvmmsg, %eax
+    syscall
+    cmpq    $-MAX_ERRNO, %rax
+    jb      1f
+    negl    %eax
+    movl    %eax, %edi
+    call    __set_errno
+    orq     $-1, %rax
+1:
+    ret
+END(recvmmsg)
diff --git a/libc/arch-x86_64/syscalls/sendmmsg.S b/libc/arch-x86_64/syscalls/sendmmsg.S
new file mode 100644 (file)
index 0000000..7407c12
--- /dev/null
@@ -0,0 +1,17 @@
+/* Generated by gensyscalls.py. Do not edit. */
+
+#include <private/bionic_asm.h>
+
+ENTRY(sendmmsg)
+    movq    %rcx, %r10
+    movl    $__NR_sendmmsg, %eax
+    syscall
+    cmpq    $-MAX_ERRNO, %rax
+    jb      1f
+    negl    %eax
+    movl    %eax, %edi
+    call    __set_errno
+    orq     $-1, %rax
+1:
+    ret
+END(sendmmsg)
index 28a47cc9d2c1fa17fd5ca4af5b3d4ec6be9a5eff..8f25a89410ce7fb99d23503916e2306138e2cea2 100644 (file)
@@ -37,16 +37,23 @@ extern "C" void*  __mmap2(void*, size_t, int, int, int, size_t);
 
 #define MMAP2_SHIFT 12 // 2**12 == 4096
 
+static bool kernel_has_MADV_MERGEABLE = true;
+
 void* mmap64(void* addr, size_t size, int prot, int flags, int fd, off64_t offset) {
   if (offset < 0 || (offset & ((1UL << MMAP2_SHIFT)-1)) != 0) {
     errno = EINVAL;
     return MAP_FAILED;
   }
 
+  bool is_private_anonymous = (flags & (MAP_PRIVATE | MAP_ANONYMOUS)) != 0;
   void* result = __mmap2(addr, size, prot, flags, fd, offset >> MMAP2_SHIFT);
-  if (result != MAP_FAILED && (flags & (MAP_PRIVATE | MAP_ANONYMOUS)) != 0) {
+
+  if (result != MAP_FAILED && kernel_has_MADV_MERGEABLE && is_private_anonymous) {
     ErrnoRestorer errno_restorer;
-    madvise(result, size, MADV_MERGEABLE);
+    int rc = madvise(result, size, MADV_MERGEABLE);
+    if (rc == -1 && errno == EINVAL) {
+      kernel_has_MADV_MERGEABLE = false;
+    }
   }
 
   return result;
index 4583cef9d99f2e6dd771e2d4f65498324f524a15..e67afbafb01430f9f0909560d8a3cad8da26410a 100644 (file)
@@ -32,6 +32,7 @@
 #include <limits.h>
 #include <sys/atomics.h>
 #include <sys/mman.h>
+#include <time.h>
 #include <unistd.h>
 
 #include "pthread_internal.h"
 #include "private/bionic_tls.h"
 #include "private/thread_private.h"
 
+// We use one bit in pthread_condattr_t (long) values as the 'shared' flag
+// and one bit for the clock type (CLOCK_REALTIME is ((clockid_t) 1), and
+// CLOCK_MONOTONIC is ((clockid_t) 0).). The rest of the bits are a counter.
+//
+// The 'value' field pthread_cond_t has the same layout.
+
+#define COND_SHARED_MASK 0x0001
+#define COND_CLOCK_MASK 0x0002
+#define COND_COUNTER_STEP 0x0004
+#define COND_FLAGS_MASK (COND_SHARED_MASK | COND_CLOCK_MASK)
+#define COND_COUNTER_MASK (~COND_FLAGS_MASK)
+
+#define COND_IS_SHARED(c) (((c) & COND_SHARED_MASK) != 0)
+#define COND_GET_CLOCK(c) (((c) & COND_CLOCK_MASK) >> 1)
+#define COND_SET_CLOCK(attr, c) ((attr) | (c << 1))
+
+
 int pthread_condattr_init(pthread_condattr_t* attr) {
-  if (attr == NULL) {
-    return EINVAL;
-  }
-  *attr = PTHREAD_PROCESS_PRIVATE;
+  *attr = 0;
+  *attr |= PTHREAD_PROCESS_PRIVATE;
+  *attr |= (CLOCK_REALTIME << 1);
   return 0;
 }
 
 int pthread_condattr_getpshared(const pthread_condattr_t* attr, int* pshared) {
-  if (attr == NULL || pshared == NULL) {
-    return EINVAL;
-  }
-  *pshared = *attr;
+  *pshared = static_cast<int>(COND_IS_SHARED(*attr));
   return 0;
 }
 
 int pthread_condattr_setpshared(pthread_condattr_t* attr, int pshared) {
-  if (attr == NULL) {
+  if (pshared != PTHREAD_PROCESS_SHARED && pshared != PTHREAD_PROCESS_PRIVATE) {
     return EINVAL;
   }
-  if (pshared != PTHREAD_PROCESS_SHARED && pshared != PTHREAD_PROCESS_PRIVATE) {
+
+  *attr |= pshared;
+  return 0;
+}
+
+int pthread_condattr_getclock(const pthread_condattr_t* attr, clockid_t* clock) {
+  *clock = COND_GET_CLOCK(*attr);
+  return 0;
+}
+
+int pthread_condattr_setclock(pthread_condattr_t* attr, clockid_t clock) {
+  if (clock != CLOCK_MONOTONIC && clock != CLOCK_REALTIME) {
     return EINVAL;
   }
-  *attr = pshared;
+
+  *attr = COND_SET_CLOCK(*attr, clock);
   return 0;
 }
 
@@ -77,13 +103,6 @@ int pthread_condattr_destroy(pthread_condattr_t* attr) {
   return 0;
 }
 
-// We use one bit in condition variable values as the 'shared' flag
-// The rest is a counter.
-#define COND_SHARED_MASK        0x0001
-#define COND_COUNTER_INCREMENT  0x0002
-#define COND_COUNTER_MASK       (~COND_SHARED_MASK)
-
-#define COND_IS_SHARED(c)  (((c)->value & COND_SHARED_MASK) != 0)
 
 // XXX *technically* there is a race condition that could allow
 // XXX a signal to be missed.  If thread A is preempted in _wait()
@@ -97,10 +116,10 @@ int pthread_cond_init(pthread_cond_t* cond, const pthread_condattr_t* attr) {
     return EINVAL;
   }
 
-  cond->value = 0;
-
-  if (attr != NULL && *attr == PTHREAD_PROCESS_SHARED) {
-    cond->value |= COND_SHARED_MASK;
+  if (attr != NULL) {
+    cond->value = (*attr & COND_FLAGS_MASK);
+  } else {
+    cond->value = 0;
   }
 
   return 0;
@@ -123,10 +142,10 @@ static int __pthread_cond_pulse(pthread_cond_t* cond, int counter) {
     return EINVAL;
   }
 
-  long flags = (cond->value & ~COND_COUNTER_MASK);
+  int flags = (cond->value & COND_FLAGS_MASK);
   while (true) {
-    long old_value = cond->value;
-    long new_value = ((old_value - COND_COUNTER_INCREMENT) & COND_COUNTER_MASK) | flags;
+    int old_value = cond->value;
+    int new_value = ((old_value - COND_COUNTER_STEP) & COND_COUNTER_MASK) | flags;
     if (__bionic_cmpxchg(old_value, new_value, &cond->value) == 0) {
       break;
     }
@@ -142,7 +161,7 @@ static int __pthread_cond_pulse(pthread_cond_t* cond, int counter) {
   // hold the mutex, they're subject to race conditions anyway.
   ANDROID_MEMBAR_FULL();
 
-  __futex_wake_ex(&cond->value, COND_IS_SHARED(cond), counter);
+  __futex_wake_ex(&cond->value, COND_IS_SHARED(cond->value), counter);
   return 0;
 }
 
@@ -151,7 +170,7 @@ int __pthread_cond_timedwait_relative(pthread_cond_t* cond, pthread_mutex_t* mut
   int old_value = cond->value;
 
   pthread_mutex_unlock(mutex);
-  int status = __futex_wait_ex(&cond->value, COND_IS_SHARED(cond), old_value, reltime);
+  int status = __futex_wait_ex(&cond->value, COND_IS_SHARED(cond->value), old_value, reltime);
   pthread_mutex_lock(mutex);
 
   if (status == -ETIMEDOUT) {
@@ -186,21 +205,23 @@ int pthread_cond_signal(pthread_cond_t* cond) {
 }
 
 int pthread_cond_wait(pthread_cond_t* cond, pthread_mutex_t* mutex) {
-  return __pthread_cond_timedwait(cond, mutex, NULL, CLOCK_REALTIME);
+  return __pthread_cond_timedwait(cond, mutex, NULL, COND_GET_CLOCK(cond->value));
 }
 
 int pthread_cond_timedwait(pthread_cond_t *cond, pthread_mutex_t * mutex, const timespec *abstime) {
-  return __pthread_cond_timedwait(cond, mutex, abstime, CLOCK_REALTIME);
+  return __pthread_cond_timedwait(cond, mutex, abstime, COND_GET_CLOCK(cond->value));
 }
 
-// TODO: this exists only for backward binary compatibility.
-int pthread_cond_timedwait_monotonic(pthread_cond_t* cond, pthread_mutex_t* mutex, const timespec* abstime) {
+#if !defined(__LP64__)
+// TODO: this exists only for backward binary compatibility on 32 bit platforms.
+extern "C" int pthread_cond_timedwait_monotonic(pthread_cond_t* cond, pthread_mutex_t* mutex, const timespec* abstime) {
   return __pthread_cond_timedwait(cond, mutex, abstime, CLOCK_MONOTONIC);
 }
 
-int pthread_cond_timedwait_monotonic_np(pthread_cond_t* cond, pthread_mutex_t* mutex, const timespec* abstime) {
+extern "C" int pthread_cond_timedwait_monotonic_np(pthread_cond_t* cond, pthread_mutex_t* mutex, const timespec* abstime) {
   return __pthread_cond_timedwait(cond, mutex, abstime, CLOCK_MONOTONIC);
 }
+#endif // !defined(__LP64__)
 
 int pthread_cond_timedwait_relative_np(pthread_cond_t* cond, pthread_mutex_t* mutex, const timespec* reltime) {
   return __pthread_cond_timedwait_relative(cond, mutex, reltime);
index c5380be9d8ee5b891876d83295d55c0896436fd9..6330a6f9d5791723a26601e8bbf398dd057629ae 100644 (file)
@@ -127,11 +127,13 @@ int pthread_attr_setschedparam(pthread_attr_t*, const struct sched_param*) __non
 int pthread_attr_setschedpolicy(pthread_attr_t*, int) __nonnull((1));
 int pthread_attr_setscope(pthread_attr_t*, int) __nonnull((1));
 int pthread_attr_setstack(pthread_attr_t*, void*, size_t) __nonnull((1));
-int pthread_attr_setstacksize(pthread_attr_t * attr, size_t stack_size) __nonnull((1));
+int pthread_attr_setstacksize(pthread_attr_t*, size_t stack_size) __nonnull((1));
 
 int pthread_condattr_destroy(pthread_condattr_t*) __nonnull((1));
+int pthread_condattr_getclock(const pthread_condattr_t*, clockid_t*) __nonnull((1, 2));
 int pthread_condattr_getpshared(const pthread_condattr_t*, int*) __nonnull((1, 2));
 int pthread_condattr_init(pthread_condattr_t*) __nonnull((1));
+int pthread_condattr_setclock(pthread_condattr_t*, clockid_t) __nonnull((1));
 int pthread_condattr_setpshared(pthread_condattr_t*, int) __nonnull((1));
 
 int pthread_cond_broadcast(pthread_cond_t*) __nonnull((1));
@@ -236,7 +238,9 @@ extern void __pthread_cleanup_pop(__pthread_cleanup_t*, int);
 int pthread_attr_getstackaddr(const pthread_attr_t*, void**) __nonnull((1, 2)); /* deprecated */
 int pthread_attr_setstackaddr(pthread_attr_t*, void*) __nonnull((1)); /* deprecated */
 
-/* Bionic additions that are deprecated even in the 32-bit ABI. */
+// Bionic additions that are deprecated even in the 32-bit ABI.
+//
+// TODO: Remove them once chromium_org / NFC have switched over.
 int pthread_cond_timedwait_monotonic_np(pthread_cond_t*, pthread_mutex_t*, const struct timespec*);
 int pthread_cond_timedwait_monotonic(pthread_cond_t*, pthread_mutex_t*, const struct timespec*);
 #define HAVE_PTHREAD_COND_TIMEDWAIT_MONOTONIC 1
index 9c04059b32c8ec0127a566134976fc985f6d1e45..9595170a30d63752973758ae436a8e8eca21bc3f 100644 (file)
@@ -153,6 +153,10 @@ typedef struct {
 
 extern lldiv_t   lldiv(long long, long long);
 
+/* BSD compatibility. */
+extern const char* getprogname(void);
+extern void setprogname(const char*);
+
 #if 1 /* MISSING FROM BIONIC - ENABLED FOR STLPort and libstdc++-v3 */
 /* make STLPort happy */
 extern int      mblen(const char *, size_t);
index 02851d290972af2f5de5e6a675cc6b258d4b9d74..acfaa206982e6d9642ff6882491b02f4c2cbf8ad 100644 (file)
@@ -25,6 +25,7 @@
  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
  * SUCH DAMAGE.
  */
+
 #ifndef _SYS_KLOG_H_
 #define _SYS_KLOG_H_
 
@@ -45,13 +46,6 @@ __BEGIN_DECLS
 #define KLOG_SIZE_UNREAD   9
 #define KLOG_SIZE_BUFFER   10
 
-/* These are deprecated names that were used in earlier bionic releases. Do not use. */
-#define KLOG_DISABLE 6
-#define KLOG_ENABLE 7
-#define KLOG_SETLEVEL 8
-#define KLOG_UNREADSIZE 9
-#define KLOG_WRITE 10
-
 extern int klogctl(int, char *, int);
 
 __END_DECLS
index 5eb7e3d90be2774da0fcde20c3e939ccfdddc5d3..db6902a9ff0300c73f76a3b4863403a9a503357b 100644 (file)
@@ -45,6 +45,8 @@ __BEGIN_DECLS
 #define sockaddr_storage __kernel_sockaddr_storage
 typedef unsigned short sa_family_t;
 
+struct timespec;
+
 #ifdef __mips__
 #define SOCK_DGRAM      1
 #define SOCK_STREAM     2
@@ -75,40 +77,45 @@ enum {
 };
 
 struct sockaddr {
- sa_family_t sa_family;
- char sa_data[14];
 sa_family_t sa_family;
 char sa_data[14];
 };
 
 struct linger {
- int l_onoff;
- int l_linger;
 int l_onoff;
 int l_linger;
 };
 
 struct msghdr {
- void * msg_name;
- int msg_namelen;
- struct iovec * msg_iov;
- __kernel_size_t msg_iovlen;
- void * msg_control;
- __kernel_size_t msg_controllen;
- unsigned msg_flags;
+  void* msg_name;
+  socklen_t msg_namelen;
+  struct iovec* msg_iov;
+  size_t msg_iovlen;
+  void* msg_control;
+  size_t msg_controllen;
+  int msg_flags;
+};
+
+struct mmsghdr {
+  struct msghdr msg_hdr;
+  unsigned int msg_len;
 };
 
 struct cmsghdr {
__kernel_size_t cmsg_len;
- int cmsg_level;
- int cmsg_type;
 size_t cmsg_len;
 int cmsg_level;
 int cmsg_type;
 };
 
 #define __CMSG_NXTHDR(ctl, len, cmsg) __cmsg_nxthdr((ctl),(len),(cmsg))
 #define CMSG_NXTHDR(mhdr, cmsg) cmsg_nxthdr((mhdr), (cmsg))
 #define CMSG_ALIGN(len) ( ((len)+sizeof(long)-1) & ~(sizeof(long)-1) )
-#define CMSG_DATA(cmsg) ((void *)((char *)(cmsg) + CMSG_ALIGN(sizeof(struct cmsghdr))))
+#define CMSG_DATA(cmsg) ((void*)((char*)(cmsg) + CMSG_ALIGN(sizeof(struct cmsghdr))))
 #define CMSG_SPACE(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + CMSG_ALIGN(len))
 #define CMSG_LEN(len) (CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
-#define __CMSG_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr) ?   (struct cmsghdr *)(ctl) :   (struct cmsghdr *)NULL)
+#define __CMSG_FIRSTHDR(ctl,len) ((len) >= sizeof(struct cmsghdr) ?   (struct cmsghdr*)(ctl) :   (struct cmsghdr*)NULL)
 #define CMSG_FIRSTHDR(msg) __CMSG_FIRSTHDR((msg)->msg_control, (msg)->msg_controllen)
-#define CMSG_OK(mhdr, cmsg) ((cmsg)->cmsg_len >= sizeof(struct cmsghdr) &&   (cmsg)->cmsg_len <= (unsigned long)   ((mhdr)->msg_controllen -   ((char *)(cmsg) - (char *)(mhdr)->msg_control)))
+#define CMSG_OK(mhdr, cmsg) ((cmsg)->cmsg_len >= sizeof(struct cmsghdr) &&   (cmsg)->cmsg_len <= (unsigned long)   ((mhdr)->msg_controllen -   ((char*)(cmsg) - (char*)(mhdr)->msg_control)))
 
 #ifdef __GNUC__
 #define __KINLINE static __inline__
@@ -118,16 +125,17 @@ struct cmsghdr {
 #define __KINLINE static
 #endif
 
-__KINLINE struct cmsghdr * __cmsg_nxthdr(void *__ctl, __kernel_size_t __size, struct cmsghdr *__cmsg) {
- struct cmsghdr * __ptr;
- __ptr = (struct cmsghdr*)(((unsigned char *) __cmsg) + CMSG_ALIGN(__cmsg->cmsg_len));
- if ((unsigned long)((char*)(__ptr+1) - (char *) __ctl) > __size)
- return (struct cmsghdr *)0;
- return __ptr;
+__KINLINE struct cmsghdr* __cmsg_nxthdr(void* __ctl, size_t __size, struct cmsghdr* __cmsg) {
+  struct cmsghdr* __ptr;
+  __ptr = (struct cmsghdr*)(((unsigned char*) __cmsg) + CMSG_ALIGN(__cmsg->cmsg_len));
+  if ((unsigned long)((char*)(__ptr+1) - (char*) __ctl) > __size) {
+    return NULL;
+  }
+  return __ptr;
 }
 
-__KINLINE struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr *__cmsg) {
- return __cmsg_nxthdr(__msg->msg_control, __msg->msg_controllen, __cmsg);
+__KINLINE struct cmsghdr* cmsg_nxthdr (struct msghdr* __msg, struct cmsghdr* __cmsg) {
 return __cmsg_nxthdr(__msg->msg_control, __msg->msg_controllen, __cmsg);
 }
 
 #define SCM_RIGHTS 0x01
@@ -135,9 +143,9 @@ __KINLINE struct cmsghdr * cmsg_nxthdr (struct msghdr *__msg, struct cmsghdr *__
 #define SCM_SECURITY 0x03
 
 struct ucred {
__u32 pid;
__u32 uid;
__u32 gid;
 pid_t pid;
 uid_t uid;
 gid_t gid;
 };
 
 #define AF_UNSPEC 0
@@ -241,6 +249,9 @@ struct ucred {
 #define MSG_ERRQUEUE 0x2000
 #define MSG_NOSIGNAL 0x4000
 #define MSG_MORE 0x8000
+#define MSG_WAITFORONE 0x10000
+#define MSG_FASTOPEN 0x20000000
+#define MSG_CMSG_CLOEXEC 0x40000000
 #define MSG_EOF MSG_FIN
 #define MSG_CMSG_COMPAT 0
 
@@ -276,30 +287,32 @@ struct ucred {
 # define __socketcall extern
 #endif
 
-__socketcall int socket(int, int, int);
-__socketcall int bind(int, const struct sockaddr *, int);
-__socketcall int connect(int, const struct sockaddr *, socklen_t);
+__socketcall int accept(int, struct sockaddr*, socklen_t*);
+__socketcall int bind(int, const struct sockaddr*, int);
+__socketcall int connect(int, const struct sockaddr*, socklen_t);
+__socketcall int getpeername(int, struct sockaddr*, socklen_t*);
+__socketcall int getsockname(int, struct sockaddr*, socklen_t*);
+__socketcall int getsockopt(int, int, int, void*, socklen_t*);
 __socketcall int listen(int, int);
-__socketcall int accept(int, struct sockaddr *, socklen_t *);
-__socketcall int getsockname(int, struct sockaddr *, socklen_t *);
-__socketcall int getpeername(int, struct sockaddr *, socklen_t *);
-__socketcall int socketpair(int, int, int, int *);
+__socketcall int recvmmsg(int, struct mmsghdr*, unsigned int, int, const struct timespec*);
+__socketcall int recvmsg(int, struct msghdr*, unsigned int);
+__socketcall int sendmmsg(int, const struct mmsghdr*, unsigned int, int);
+__socketcall int sendmsg(int, const struct msghdr*, unsigned int);
+__socketcall int setsockopt(int, int, int, const void*, socklen_t);
 __socketcall int shutdown(int, int);
-__socketcall int setsockopt(int, int, int, const void *, socklen_t);
-__socketcall int getsockopt(int, int, int, void *, socklen_t *);
-__socketcall int sendmsg(int, const struct msghdr *, unsigned int);
-__socketcall int recvmsg(int, struct msghdr *, unsigned int);
+__socketcall int socket(int, int, int);
+__socketcall int socketpair(int, int, int, int*);
 
-extern  ssize_t  send(int, const void *, size_t, unsigned int);
-extern  ssize_t  recv(int, void *, size_t, unsigned int);
+extern ssize_t send(int, const void*, size_t, unsigned int);
+extern ssize_t recv(int, void*, size_t, unsigned int);
 
-__socketcall ssize_t sendto(int, const void *, size_t, int, const struct sockaddr *, socklen_t);
-__socketcall ssize_t recvfrom(int, void *, size_t, unsigned int, const struct sockaddr *, socklen_t *);
+__socketcall ssize_t sendto(int, const void*, size_t, int, const struct sockaddr*, socklen_t);
+__socketcall ssize_t recvfrom(int, void*, size_t, unsigned int, const struct sockaddr*, socklen_t*);
 
 #if defined(__BIONIC_FORTIFY)
 __errordecl(__recvfrom_error, "recvfrom called with size bigger than buffer");
-extern ssize_t __recvfrom_chk(int, void*, size_t, size_t, unsigned int, const struct sockaddr*, socklen_t *);
-extern ssize_t __recvfrom_real(int, void *, size_t, unsigned int, const struct sockaddr*, socklen_t*)
+extern ssize_t __recvfrom_chk(int, void*, size_t, size_t, unsigned int, const struct sockaddr*, socklen_t*);
+extern ssize_t __recvfrom_real(int, void*, size_t, unsigned int, const struct sockaddr*, socklen_t*)
     __asm__(__USER_LABEL_PREFIX__ "recvfrom");
 
 __BIONIC_FORTIFY_INLINE
@@ -324,7 +337,7 @@ ssize_t recvfrom(int fd, void* buf, size_t len, unsigned int flags, const struct
 }
 
 __BIONIC_FORTIFY_INLINE
-ssize_t recv(int socket, void *buf, size_t buflen, unsigned int flags) {
+ssize_t recv(int socket, voidbuf, size_t buflen, unsigned int flags) {
   return recvfrom(socket, buf, buflen, flags, NULL, 0);
 }
 
index 202f031afcb79cd29d38dc9f24d391b622c5b315..6e7eaa9ea89ae3687071755120f40cad75e58a99 100644 (file)
@@ -74,9 +74,9 @@ static inline void _tzUnlock(void) { pthread_mutex_unlock(&_tzMutex); }
 #define WILDABBR    "   "
 #endif /* !defined WILDABBR */
 
-static char     wildabbr[] = WILDABBR;
+static char       wildabbr[] = WILDABBR;
 
-static const char   gmt[] = "GMT";
+static const char gmt[] = "GMT";
 
 /*
 ** The DST rules to use if TZ has no rules and we can't load TZDEFRULES.
@@ -89,7 +89,7 @@ static const char   gmt[] = "GMT";
 #define TZDEFRULESTRING ",M4.1.0,M10.5.0"
 #endif /* !defined TZDEFDST */
 
-struct ttinfo {             /* time type information */
+struct ttinfo {              /* time type information */
     int_fast32_t tt_gmtoff;  /* UT offset in seconds */
     int          tt_isdst;   /* used to set tm_isdst */
     int          tt_abbrind; /* abbreviation list index */
@@ -97,7 +97,7 @@ struct ttinfo {             /* time type information */
     int          tt_ttisgmt; /* TRUE if transition is UT */
 };
 
-struct lsinfo {             /* leap second information */
+struct lsinfo {              /* leap second information */
     time_t       ls_trans;   /* transition time */
     int_fast64_t ls_corr;    /* correction to apply */
 };
@@ -112,32 +112,32 @@ struct lsinfo {             /* leap second information */
 #endif /* !defined TZNAME_MAX */
 
 struct state {
-    int     leapcnt;
-    int     timecnt;
-    int     typecnt;
-    int     charcnt;
-    int     goback;
-    int     goahead;
-    time_t      ats[TZ_MAX_TIMES];
-    unsigned char   types[TZ_MAX_TIMES];
-    struct ttinfo   ttis[TZ_MAX_TYPES];
-    char        chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
-                (2 * (MY_TZNAME_MAX + 1)))];
-    struct lsinfo   lsis[TZ_MAX_LEAPS];
-    int defaulttype; /* for early times or if no transitions */
+    int           leapcnt;
+    int           timecnt;
+    int           typecnt;
+    int           charcnt;
+    int           goback;
+    int           goahead;
+    time_t        ats[TZ_MAX_TIMES];
+    unsigned char types[TZ_MAX_TIMES];
+    struct ttinfo ttis[TZ_MAX_TYPES];
+    char          chars[BIGGEST(BIGGEST(TZ_MAX_CHARS + 1, sizeof gmt),
+                  (2 * (MY_TZNAME_MAX + 1)))];
+    struct lsinfo lsis[TZ_MAX_LEAPS];
+    int           defaulttype; /* for early times or if no transitions */
 };
 
 struct rule {
-    int          r_type;     /* type of rule--see below */
-    int          r_day;      /* day number of rule */
-    int          r_week;     /* week number of rule */
-    int          r_mon;      /* month number of rule */
-    int_fast32_t r_time;     /* transition time of rule */
+    int          r_type; /* type of rule--see below */
+    int          r_day;  /* day number of rule */
+    int          r_week; /* week number of rule */
+    int          r_mon;  /* month number of rule */
+    int_fast32_t r_time; /* transition time of rule */
 };
 
-#define JULIAN_DAY      0   /* Jn - Julian day */
-#define DAY_OF_YEAR     1   /* n - day of year */
-#define MONTH_NTH_DAY_OF_WEEK   2   /* Mm.n.d - month, week, day of week */
+#define JULIAN_DAY            0 /* Jn - Julian day */
+#define DAY_OF_YEAR           1 /* n - day of year */
+#define MONTH_NTH_DAY_OF_WEEK 2 /* Mm.n.d - month, week, day of week */
 
 /*
 ** Prototypes for static functions.
@@ -147,7 +147,7 @@ struct rule {
 
 static int __bionic_open_tzdata(const char*, int*);
 static int_fast32_t detzcode(const char * codep);
-static time_t   detzcode64(const char * codep);
+static int_fast64_t detzcode64(const char * codep);
 static int      differ_by_repeat(time_t t1, time_t t0);
 static const char * getzname(const char * strp) ATTRIBUTE_PURE;
 static const char * getqzname(const char * strp, const int delim)
@@ -165,6 +165,7 @@ static struct tm *  localsub(const time_t * timep, int_fast32_t offset,
 static int      increment_overflow(int * number, int delta);
 static int      leaps_thru_end_of(int y) ATTRIBUTE_PURE;
 static int      increment_overflow32(int_fast32_t * number, int delta);
+static int      increment_overflow_time(time_t *t, int_fast32_t delta);
 static int      normalize_overflow32(int_fast32_t * tensptr,
                 int * unitsptr, int base);
 static int      normalize_overflow(int * tensptr, int * unitsptr,
@@ -186,18 +187,18 @@ static struct tm *  timesub(const time_t * timep, int_fast32_t offset,
                 const struct state * sp, struct tm * tmp);
 static int      tmcomp(const struct tm * atmp,
                 const struct tm * btmp);
-static time_t transtime(time_t janfirst, int year,
-                        const struct rule * rulep, int_fast32_t offset)
+static int_fast32_t transtime(int year, const struct rule * rulep,
+                int_fast32_t offset)
         ATTRIBUTE_PURE;
-static int             typesequiv(const struct state * sp, int a, int b);
+static int      typesequiv(const struct state * sp, int a, int b);
 static int      tzload(const char * name, struct state * sp,
                 int doextend);
 static int      tzparse(const char * name, struct state * sp,
                 int lastditch);
 
 #ifdef ALL_STATE
-static struct state *   lclptr;
-static struct state *   gmtptr;
+static struct state * lclptr;
+static struct state * gmtptr;
 #endif /* defined ALL_STATE */
 
 #ifndef ALL_STATE
@@ -211,11 +212,11 @@ static struct state gmtmem;
 #define TZ_STRLEN_MAX 255
 #endif /* !defined TZ_STRLEN_MAX */
 
-static char     lcl_TZname[TZ_STRLEN_MAX + 1];
-static int      lcl_is_set;
-static int      gmt_is_set;
+static char lcl_TZname[TZ_STRLEN_MAX + 1];
+static int  lcl_is_set;
+static int  gmt_is_set;
 
-char *          tzname[2] = {
+char * tzname[2] = {
     wildabbr,
     wildabbr
 };
@@ -231,43 +232,43 @@ char *          tzname[2] = {
 static struct tm    tmGlobal;
 
 #ifdef USG_COMPAT
-long                   timezone = 0;
-int                    daylight = 0;
+long                timezone = 0;
+int                 daylight = 0;
 #endif /* defined USG_COMPAT */
 
 #ifdef ALTZONE
-long                   altzone = 0;
+long                altzone = 0;
 #endif /* defined ALTZONE */
 
 static int_fast32_t
 detzcode(const char *const codep)
 {
-       register int_fast32_t   result;
-       register int            i;
+    register int_fast32_t result;
+    register int          i;
 
-       result = (codep[0] & 0x80) ? -1 : 0;
-       for (i = 0; i < 4; ++i)
-               result = (result << 8) | (codep[i] & 0xff);
-       return result;
+    result = (codep[0] & 0x80) ? -1 : 0;
+    for (i = 0; i < 4; ++i)
+        result = (result << 8) | (codep[i] & 0xff);
+    return result;
 }
 
-static time_t
+static int_fast64_t
 detzcode64(const char *const codep)
 {
-       register time_t result;
-       register int    i;
+    register int_fast64_t result;
+    register int          i;
 
-       result = (codep[0] & 0x80) ?  (~(int_fast64_t) 0) : 0;
-       for (i = 0; i < 8; ++i)
-               result = result * 256 + (codep[i] & 0xff);
-       return result;
+    result = (codep[0] & 0x80) ? -1 : 0;
+    for (i = 0; i < 8; ++i)
+        result = (result << 8) | (codep[i] & 0xff);
+    return result;
 }
 
 static void
 settzname(void)
 {
-    register struct state * const   sp = lclptr;
-    register int            i;
+    register struct state * const sp = lclptr;
+    register int                  i;
 
     tzname[0] = wildabbr;
     tzname[1] = wildabbr;
@@ -333,10 +334,10 @@ settzname(void)
 static int
 differ_by_repeat(const time_t t1, const time_t t0)
 {
-       if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
-                       return 0;
+    if (TYPE_BIT(time_t) - TYPE_SIGNED(time_t) < SECSPERREPEAT_BITS)
+        return 0;
 #if __LP64__ // 32-bit Android only has a signed 32-bit time_t; 64-bit Android is fixed.
-       return t1 - t0 == SECSPERREPEAT;
+    return t1 - t0 == SECSPERREPEAT;
 #endif
 }
 
@@ -344,26 +345,26 @@ static int
 tzload(register const char* name, register struct state* const sp,
        register const int doextend)
 {
-    register const char *       p;
-    register int            i;
-    register int            fid;
-    register int            stored;
-    register int            nread;
+    register const char * p;
+    register int          i;
+    register int          fid;
+    register int          stored;
+    register int          nread;
     typedef union {
-        struct tzhead   tzhead;
-        char        buf[2 * sizeof(struct tzhead) +
-                    2 * sizeof *sp +
-                    4 * TZ_MAX_TIMES];
+        struct tzhead tzhead;
+        char          buf[2 * sizeof(struct tzhead) +
+                      2 * sizeof *sp +
+                      4 * TZ_MAX_TIMES];
     } u_t;
 #ifdef ALL_STATE
-    register u_t *                     up;
+    register u_t *        up;
 
     up = (u_t *) calloc(1, sizeof *up);
     if (up == NULL)
         return -1;
 #else /* !defined ALL_STATE */
-    u_t                                u;
-    register u_t * const               up = &u;
+    u_t                   u;
+    register u_t * const  up = &u;
 #endif /* !defined ALL_STATE */
 
     sp->goback = sp->goahead = FALSE;
@@ -377,8 +378,9 @@ tzload(register const char* name, register struct state* const sp,
     if (close(fid) < 0 || nread <= 0)
         goto oops;
     for (stored = 4; stored <= 8; stored *= 2) {
-        int     ttisstdcnt;
-        int     ttisgmtcnt;
+        int ttisstdcnt;
+        int ttisgmtcnt;
+        int timecnt;
 
         ttisstdcnt = (int) detzcode(up->tzhead.tzh_ttisstdcnt);
         ttisgmtcnt = (int) detzcode(up->tzhead.tzh_ttisgmtcnt);
@@ -395,24 +397,45 @@ tzload(register const char* name, register struct state* const sp,
             (ttisgmtcnt != sp->typecnt && ttisgmtcnt != 0))
                 goto oops;
         if (nread - (p - up->buf) <
-            sp->timecnt * stored +      /* ats */
-            sp->timecnt +           /* types */
-            sp->typecnt * 6 +       /* ttinfos */
-            sp->charcnt +           /* chars */
-            sp->leapcnt * (stored + 4) +    /* lsinfos */
-            ttisstdcnt +            /* ttisstds */
-            ttisgmtcnt)         /* ttisgmts */
+            sp->timecnt * stored +       /* ats */
+            sp->timecnt +                /* types */
+            sp->typecnt * 6 +            /* ttinfos */
+            sp->charcnt +                /* chars */
+            sp->leapcnt * (stored + 4) + /* lsinfos */
+            ttisstdcnt +                 /* ttisstds */
+            ttisgmtcnt)                  /* ttisgmts */
                 goto oops;
+        timecnt = 0;
         for (i = 0; i < sp->timecnt; ++i) {
-            sp->ats[i] = (stored == 4) ?
-                detzcode(p) : detzcode64(p);
+            int_fast64_t at
+              = stored == 4 ? detzcode(p) : detzcode64(p);
+            sp->types[i] = ((TYPE_SIGNED(time_t)
+                     ? time_t_min <= at
+                     : 0 <= at)
+                    && at <= time_t_max);
+            if (sp->types[i]) {
+                if (i && !timecnt && at != time_t_min) {
+                    /*
+                    ** Keep the earlier record, but tweak
+                    ** it so that it starts with the
+                    ** minimum time_t value.
+                    */
+                    sp->types[i - 1] = 1;
+                    sp->ats[timecnt++] = time_t_min;
+                }
+                sp->ats[timecnt++] = at;
+            }
             p += stored;
         }
+        timecnt = 0;
         for (i = 0; i < sp->timecnt; ++i) {
-            sp->types[i] = (unsigned char) *p++;
-            if (sp->types[i] >= sp->typecnt)
+            unsigned char typ = *p++;
+            if (sp->typecnt <= typ)
                 goto oops;
+            if (sp->types[i])
+                sp->types[timecnt++] = typ;
         }
+        sp->timecnt = timecnt;
         for (i = 0; i < sp->typecnt; ++i) {
             register struct ttinfo *    ttisp;
 
@@ -467,44 +490,6 @@ tzload(register const char* name, register struct state* const sp,
             }
         }
         /*
-        ** Out-of-sort ats should mean we're running on a
-        ** signed time_t system but using a data file with
-        ** unsigned values (or vice versa).
-        */
-        for (i = 0; i < sp->timecnt; ++i)
-            if ((i < sp->timecnt - 1 &&
-                sp->ats[i] > sp->ats[i + 1]) ||
-                (i == sp->timecnt - 1 && !TYPE_SIGNED(time_t) &&
-                sp->ats[i] >
-                ((stored == 4) ? INT32_MAX : INT64_MAX))) {
-                    if (TYPE_SIGNED(time_t)) {
-                        /*
-                        ** Ignore the end (easy).
-                        */
-                        sp->timecnt = i + 1;
-                    } else {
-                        /*
-                        ** Ignore the beginning (harder).
-                        */
-                        register int    j;
-
-                        /*
-                        ** Keep the record right before the
-                        ** epoch boundary,
-                        ** but tweak it so that it starts
-                        ** right with the epoch
-                        ** (thanks to Doug Bailey).
-                        */
-                        sp->ats[i] = 0;
-                        for (j = 0; j + i < sp->timecnt; ++j) {
-                            sp->ats[j] = sp->ats[j + i];
-                            sp->types[j] = sp->types[j + i];
-                        }
-                        sp->timecnt = j;
-                    }
-                    break;
-            }
-        /*
         ** If this is an old file, we're done.
         */
         if (up->tzhead.tzh_version[0] == '\0')
@@ -513,16 +498,16 @@ tzload(register const char* name, register struct state* const sp,
         for (i = 0; i < nread; ++i)
             up->buf[i] = p[i];
         /*
-        ** If this is a narrow time_t system, we're done.
+        ** If this is a signed narrow time_t system, we're done.
         */
-        if (stored >= (int) sizeof(time_t))
+        if (TYPE_SIGNED(time_t) && stored >= (int) sizeof(time_t))
             break;
     }
     if (doextend && nread > 2 &&
         up->buf[0] == '\n' && up->buf[nread - 1] == '\n' &&
         sp->typecnt + 2 <= TZ_MAX_TYPES) {
-            struct state    ts;
-            register int    result;
+            struct state ts;
+            register int result;
 
             up->buf[nread - 1] = '\0';
             result = tzparse(&up->buf[1], &ts, FALSE);
@@ -617,31 +602,31 @@ oops:
 static int
 typesequiv(const struct state *const sp, const int a, const int b)
 {
-       register int    result;
-
-       if (sp == NULL ||
-               a < 0 || a >= sp->typecnt ||
-               b < 0 || b >= sp->typecnt)
-                       result = FALSE;
-       else {
-               register const struct ttinfo *  ap = &sp->ttis[a];
-               register const struct ttinfo *  bp = &sp->ttis[b];
-               result = ap->tt_gmtoff == bp->tt_gmtoff &&
-                       ap->tt_isdst == bp->tt_isdst &&
-                       ap->tt_ttisstd == bp->tt_ttisstd &&
-                       ap->tt_ttisgmt == bp->tt_ttisgmt &&
-                       strcmp(&sp->chars[ap->tt_abbrind],
-                       &sp->chars[bp->tt_abbrind]) == 0;
-       }
-       return result;
+    register int result;
+
+    if (sp == NULL ||
+        a < 0 || a >= sp->typecnt ||
+        b < 0 || b >= sp->typecnt)
+            result = FALSE;
+    else {
+        register const struct ttinfo *  ap = &sp->ttis[a];
+        register const struct ttinfo *  bp = &sp->ttis[b];
+        result = ap->tt_gmtoff == bp->tt_gmtoff &&
+            ap->tt_isdst == bp->tt_isdst &&
+            ap->tt_ttisstd == bp->tt_ttisstd &&
+            ap->tt_ttisgmt == bp->tt_ttisgmt &&
+            strcmp(&sp->chars[ap->tt_abbrind],
+            &sp->chars[bp->tt_abbrind]) == 0;
+    }
+    return result;
 }
 
-static const int    mon_lengths[2][MONSPERYEAR] = {
+static const int mon_lengths[2][MONSPERYEAR] = {
     { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 },
     { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }
 };
 
-static const int    year_lengths[2] = {
+static const int year_lengths[2] = {
     DAYSPERNYEAR, DAYSPERLYEAR
 };
 
@@ -674,7 +659,7 @@ getzname(register const char * strp)
 static const char *
 getqzname(register const char *strp, const int delim)
 {
-    register int    c;
+    register int c;
 
     while ((c = *strp) != '\0' && c != delim)
         ++strp;
@@ -691,8 +676,8 @@ getqzname(register const char *strp, const int delim)
 static const char *
 getnum(register const char * strp, int * const nump, const int min, const int max)
 {
-    register char   c;
-    register int    num;
+    register char c;
+    register int  num;
 
     if (strp == NULL || !is_digit(c = *strp))
         return NULL;
@@ -760,7 +745,7 @@ getsecs(register const char *strp, int_fast32_t *const secsp)
 static const char *
 getoffset(register const char *strp, int_fast32_t *const offsetp)
 {
-    register int    neg = 0;
+    register int neg = 0;
 
     if (*strp == '-') {
         neg = 1;
@@ -829,19 +814,18 @@ getrule(const char * strp, register struct rule * const rulep)
 }
 
 /*
-** Given the Epoch-relative time of January 1, 00:00:00 UTC, in a year, the
-** year, a rule, and the offset from UT at the time that rule takes effect,
-** calculate the Epoch-relative time that rule takes effect.
+** Given a year, a rule, and the offset from UT at the time that rule takes
+** effect, calculate the year-relative time that rule takes effect.
 */
 
-static time_t
-transtime(const time_t janfirst, const int year,
-          register const struct rule *const rulep, const int_fast32_t offset)
+static int_fast32_t
+transtime(const int year, register const struct rule *const rulep,
+          const int_fast32_t offset)
 {
-    register int    leapyear;
-    register time_t value;
-    register int    i;
-    int     d, m1, yy0, yy1, yy2, dow;
+    register int          leapyear;
+    register int_fast32_t value;
+    register int          i;
+    int d, m1, yy0, yy1, yy2, dow;
 
     INITIALIZE(value);
     leapyear = isleap(year);
@@ -855,7 +839,7 @@ transtime(const time_t janfirst, const int year,
         ** add SECSPERDAY times the day number-1 to the time of
         ** January 1, midnight, to get the day.
         */
-        value = janfirst + (rulep->r_day - 1) * SECSPERDAY;
+        value = (rulep->r_day - 1) * SECSPERDAY;
         if (leapyear && rulep->r_day >= 60)
             value += SECSPERDAY;
         break;
@@ -866,16 +850,13 @@ transtime(const time_t janfirst, const int year,
         ** Just add SECSPERDAY times the day number to the time of
         ** January 1, midnight, to get the day.
         */
-        value = janfirst + rulep->r_day * SECSPERDAY;
+        value = rulep->r_day * SECSPERDAY;
         break;
 
     case MONTH_NTH_DAY_OF_WEEK:
         /*
         ** Mm.n.d - nth "dth day" of month m.
         */
-        value = janfirst;
-        for (i = 0; i < rulep->r_mon - 1; ++i)
-            value += mon_lengths[leapyear][i] * SECSPERDAY;
 
         /*
         ** Use Zeller's Congruence to get day-of-week of first day of
@@ -908,13 +889,15 @@ transtime(const time_t janfirst, const int year,
         /*
         ** "d" is the day-of-month (zero-origin) of the day we want.
         */
-        value += d * SECSPERDAY;
+        value = d * SECSPERDAY;
+        for (i = 0; i < rulep->r_mon - 1; ++i)
+            value += mon_lengths[leapyear][i] * SECSPERDAY;
         break;
     }
 
     /*
-    ** "value" is the Epoch-relative time of 00:00:00 UT on the day in
-    ** question. To get the Epoch-relative time of the specified local
+    ** "value" is the year-relative time of 00:00:00 UT on the day in
+    ** question. To get the year-relative time of the specified local
     ** time on that day, add the transition time and the current offset
     ** from UT.
     */
@@ -930,17 +913,15 @@ static int
 tzparse(const char * name, register struct state * const sp,
         const int lastditch)
 {
-    const char *            stdname;
-    const char *            dstname;
-    size_t              stdlen;
-    size_t              dstlen;
-    int_fast32_t                stdoffset;
-    int_fast32_t                dstoffset;
-    register time_t *           atp;
-    register unsigned char *    typep;
-    register char *         cp;
-    register int            load_result;
-    static struct ttinfo    zttinfo;
+    const char *         stdname;
+    const char *         dstname;
+    size_t               stdlen;
+    size_t               dstlen;
+    int_fast32_t         stdoffset;
+    int_fast32_t         dstoffset;
+    register char *      cp;
+    register int         load_result;
+    static struct ttinfo zttinfo;
 
     INITIALIZE(dstname);
     stdname = name;
@@ -993,13 +974,12 @@ tzparse(const char * name, register struct state * const sp,
         if (*name == '\0' && load_result != 0)
             name = TZDEFRULESTRING;
         if (*name == ',' || *name == ';') {
-            struct rule start;
-            struct rule end;
-            register int    year;
-            register int    yearlim;
-            register time_t janfirst;
-            time_t      starttime;
-            time_t      endtime;
+            struct rule  start;
+            struct rule  end;
+            register int year;
+            register int yearlim;
+            register int timecnt;
+            time_t       janfirst;
 
             ++name;
             if ((name = getrule(name, &start)) == NULL)
@@ -1021,46 +1001,47 @@ tzparse(const char * name, register struct state * const sp,
             sp->ttis[1].tt_gmtoff = -stdoffset;
             sp->ttis[1].tt_isdst = 0;
             sp->ttis[1].tt_abbrind = 0;
-            atp = sp->ats;
-            typep = sp->types;
+            timecnt = 0;
             janfirst = 0;
             yearlim = EPOCH_YEAR + YEARSPERREPEAT;
             for (year = EPOCH_YEAR; year < yearlim; year++) {
-                int_fast32_t yearsecs;
-
-                starttime = transtime(janfirst, year, &start,
-                    stdoffset);
-                endtime = transtime(janfirst, year, &end,
-                    dstoffset);
+                int_fast32_t
+                  starttime = transtime(year, &start, stdoffset),
+                  endtime = transtime(year, &end, dstoffset);
+                int_fast32_t
                 yearsecs = (year_lengths[isleap(year)]
                             * SECSPERDAY);
-                if (starttime > endtime
+                int reversed = endtime < starttime;
+                if (reversed) {
+                    int_fast32_t swap = starttime;
+                    starttime = endtime;
+                    endtime = swap;
+                }
+                if (reversed
                     || (starttime < endtime
                         && (endtime - starttime
                             < (yearsecs
                                + (stdoffset - dstoffset))))) {
-                    if (&sp->ats[TZ_MAX_TIMES - 2] < atp)
+                    if (TZ_MAX_TIMES - 2 < timecnt)
                         break;
                     yearlim = year + YEARSPERREPEAT + 1;
-                    if (starttime > endtime) {
-                        *atp++ = endtime;
-                        *typep++ = 1;   /* DST ends */
-                        *atp++ = starttime;
-                        *typep++ = 0;   /* DST begins */
-                    } else {
-                        *atp++ = starttime;
-                        *typep++ = 0;   /* DST begins */
-                         *atp++ = endtime;
-                        *typep++ = 1;   /* DST ends */
+                    sp->ats[timecnt] = janfirst;
+                    if (increment_overflow_time
+                        (&sp->ats[timecnt], starttime))
+                        break;
+                    sp->types[timecnt++] = reversed;
+                    sp->ats[timecnt] = janfirst;
+                    if (increment_overflow_time
+                        (&sp->ats[timecnt], endtime))
+                        break;
+                    sp->types[timecnt++] = !reversed;
                     }
-                }
-                if (time_t_max - janfirst < yearsecs)
+                if (increment_overflow_time(&janfirst, yearsecs))
                     break;
-                janfirst += yearsecs;
             }
-            sp->timecnt = atp - sp->ats;
-            if (!sp->timecnt)
-                sp->typecnt = 1;       /* Perpetual DST.  */
+            sp->timecnt = timecnt;
+            if (!timecnt)
+                sp->typecnt = 1;    /* Perpetual DST.  */
         } else {
             register int_fast32_t   theirstdoffset;
             register int_fast32_t   theirdstoffset;
@@ -1211,7 +1192,7 @@ tzsetwall(void)
 static void
 tzset_locked(void)
 {
-    register const char *   name = NULL;
+    register const char * name = NULL;
 
     name = getenv("TZ");
 
@@ -1280,10 +1261,10 @@ static struct tm *
 localsub(const time_t * const timep, const int_fast32_t offset,
          struct tm * const tmp, const struct state * sp) // android-changed: added sp.
 {
-    register const struct ttinfo *  ttisp;
-    register int            i;
-    register struct tm *        result;
-    const time_t            t = *timep;
+    register const struct ttinfo * ttisp;
+    register int         i;
+    register struct tm * result;
+    const time_t         t = *timep;
 
     // BEGIN android-changed: support user-supplied sp.
     if (sp == NULL) {
@@ -1297,8 +1278,8 @@ localsub(const time_t * const timep, const int_fast32_t offset,
     if ((sp->goback && t < sp->ats[0]) ||
         (sp->goahead && t > sp->ats[sp->timecnt - 1])) {
             time_t          newt = t;
-            register time_t     seconds;
-            register time_t     years;
+            register time_t seconds;
+            register time_t years;
 
             if (t < sp->ats[0])
                 seconds = sp->ats[0] - t;
@@ -1329,8 +1310,8 @@ localsub(const time_t * const timep, const int_fast32_t offset,
     if (sp->timecnt == 0 || t < sp->ats[0]) {
         i = sp->defaulttype;
     } else {
-        register int    lo = 1;
-        register int    hi = sp->timecnt;
+        register int lo = 1;
+        register int hi = sp->timecnt;
 
         while (lo < hi) {
             register int    mid = (lo + hi) >> 1;
@@ -1370,7 +1351,7 @@ localtime(const time_t * const timep)
 struct tm *
 localtime_r(const time_t * const timep, struct tm * tmp)
 {
-    struct tm*  result;
+    struct tm* result;
 
     _tzLock();
     tzset_locked();
@@ -1388,7 +1369,7 @@ static struct tm *
 gmtsub(const time_t * const timep, const int_fast32_t offset,
        struct tm *const tmp, const struct state * sp) // android-changed: added sp.
 {
-    register struct tm *    result;
+    register struct tm * result;
 
     (void) sp; // android-added: unused.
 
@@ -1436,7 +1417,7 @@ gmtime(const time_t * const timep)
 struct tm *
 gmtime_r(const time_t * const timep, struct tm * tmp)
 {
-    struct tm*  result;
+    struct tm* result;
 
     _tzLock();
     result = gmtsub(timep, 0L, tmp, NULL); // android-changed: extra parameter.
@@ -1462,15 +1443,15 @@ timesub(const time_t *const timep, const int_fast32_t offset,
         register const struct state *const sp,
         register struct tm *const tmp)
 {
-    register const struct lsinfo *  lp;
-    register time_t         tdays;
-    register int            idays;  /* unsigned would be so 2003 */
-    register int_fast64_t           rem;
-    int             y;
-    register const int *        ip;
-    register int_fast64_t           corr;
-    register int            hit;
-    register int            i;
+    register const struct lsinfo * lp;
+    register time_t       tdays;
+    register int          idays;  /* unsigned would be so 2003 */
+    register int_fast64_t rem;
+    int                   y;
+    register const int *  ip;
+    register int_fast64_t corr;
+    register int          hit;
+    register int          i;
 
     corr = 0;
     hit = 0;
@@ -1630,61 +1611,77 @@ ctime_r(const time_t * const timep, char * buf)
 static int
 increment_overflow(int *const ip, int j)
 {
-       register int const      i = *ip;
-
-       /*
-       ** If i >= 0 there can only be overflow if i + j > INT_MAX
-       ** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
-       ** If i < 0 there can only be overflow if i + j < INT_MIN
-       ** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
-       */
-       if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
-               return TRUE;
-       *ip += j;
-       return FALSE;
+    register int const i = *ip;
+
+    /*
+    ** If i >= 0 there can only be overflow if i + j > INT_MAX
+    ** or if j > INT_MAX - i; given i >= 0, INT_MAX - i cannot overflow.
+    ** If i < 0 there can only be overflow if i + j < INT_MIN
+    ** or if j < INT_MIN - i; given i < 0, INT_MIN - i cannot overflow.
+    */
+    if ((i >= 0) ? (j > INT_MAX - i) : (j < INT_MIN - i))
+        return TRUE;
+    *ip += j;
+    return FALSE;
 }
 
 static int
 increment_overflow32(int_fast32_t *const lp, int const m)
 {
-       register int_fast32_t const     l = *lp;
+    register int_fast32_t const l = *lp;
 
-       if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
-               return TRUE;
-       *lp += m;
-       return FALSE;
+    if ((l >= 0) ? (m > INT_FAST32_MAX - l) : (m < INT_FAST32_MIN - l))
+        return TRUE;
+    *lp += m;
+    return FALSE;
+}
+
+static int
+increment_overflow_time(time_t *tp, int_fast32_t j)
+{
+    /*
+    ** This is like
+    ** 'if (! (time_t_min <= *tp + j && *tp + j <= time_t_max)) ...',
+    ** except that it does the right thing even if *tp + j would overflow.
+    */
+    if (! (j < 0
+           ? (TYPE_SIGNED(time_t) ? time_t_min - j <= *tp : -1 - j < *tp)
+           : *tp <= time_t_max - j))
+        return TRUE;
+    *tp += j;
+    return FALSE;
 }
 
 static int
 normalize_overflow(int *const tensptr, int *const unitsptr, const int base)
 {
-       register int    tensdelta;
+    register int tensdelta;
 
-       tensdelta = (*unitsptr >= 0) ?
-               (*unitsptr / base) :
-               (-1 - (-1 - *unitsptr) / base);
-       *unitsptr -= tensdelta * base;
-       return increment_overflow(tensptr, tensdelta);
+    tensdelta = (*unitsptr >= 0) ?
+        (*unitsptr / base) :
+        (-1 - (-1 - *unitsptr) / base);
+    *unitsptr -= tensdelta * base;
+    return increment_overflow(tensptr, tensdelta);
 }
 
 static int
 normalize_overflow32(int_fast32_t *const tensptr, int *const unitsptr,
-                    const int base)
+             const int base)
 {
-       register int    tensdelta;
+    register int tensdelta;
 
-       tensdelta = (*unitsptr >= 0) ?
-               (*unitsptr / base) :
-               (-1 - (-1 - *unitsptr) / base);
-       *unitsptr -= tensdelta * base;
-       return increment_overflow32(tensptr, tensdelta);
+    tensdelta = (*unitsptr >= 0) ?
+        (*unitsptr / base) :
+        (-1 - (-1 - *unitsptr) / base);
+    *unitsptr -= tensdelta * base;
+    return increment_overflow32(tensptr, tensdelta);
 }
 
 static int
 tmcomp(register const struct tm * const atmp,
        register const struct tm * const btmp)
 {
-    register int    result;
+    register int result;
 
     if (atmp->tm_year != btmp->tm_year)
         return atmp->tm_year < btmp->tm_year ? -1 : 1;
@@ -1703,16 +1700,16 @@ time2sub(struct tm * const tmp,
          int * const okayp,
          const int do_norm_secs, const struct state * sp) // android-changed: added sp
 {
-    register int            dir;
-    register int            i, j;
-    register int            saved_seconds;
-    register int_fast32_t           li;
-    register time_t         lo;
-    register time_t         hi;
-    int_fast32_t                y;
-    time_t              newt;
-    time_t              t;
-    struct tm           yourtm, mytm;
+    register int          dir;
+    register int          i, j;
+    register int          saved_seconds;
+    register int_fast32_t li;
+    register time_t       lo;
+    register time_t       hi;
+    int_fast32_t          y;
+    time_t                newt;
+    time_t                t;
+    struct tm             yourtm, mytm;
 
     *okayp = FALSE;
     yourtm = *tmp;
@@ -1883,7 +1880,7 @@ time2(struct tm * const tmp,
       const int_fast32_t offset,
       int *const okayp, const struct state* sp) // android-changed: added sp.
 {
-    time_t  t;
+    time_t t;
 
     /*
     ** First try without normalization of seconds
@@ -1899,11 +1896,11 @@ time1(struct tm * const tmp,
       struct tm * (* const funcp) (const time_t *, int_fast32_t, struct tm *, const struct state *), // android-changed: added sp.
       const int_fast32_t offset, const struct state * sp) // android-changed: added sp.
 {
-    register time_t         t;
-    register int            samei, otheri;
-    register int            sameind, otherind;
-    register int            i;
-    register int            nseen;
+    register time_t t;
+    register int    samei, otheri;
+    register int    sameind, otherind;
+    register int    i;
+    register int    nseen;
     int             seen[TZ_MAX_TYPES];
     int             types[TZ_MAX_TYPES];
     int             okay;
@@ -1996,7 +1993,7 @@ timelocal(struct tm * const tmp)
 time_t
 timegm(struct tm * const tmp)
 {
-    time_t  result;
+    time_t result;
 
     if (tmp != NULL)
         tmp->tm_isdst = 0;
@@ -2019,7 +2016,7 @@ timegm(struct tm * const tmp)
 long
 gtime(struct tm * const tmp)
 {
-    const time_t    t = mktime(tmp);
+    const time_t t = mktime(tmp);
 
     if (t == WRONG)
         return -1;
@@ -2045,9 +2042,9 @@ gtime(struct tm * const tmp)
 static int_fast64_t
 leapcorr(time_t * timep)
 {
-    register struct state *     sp;
-    register struct lsinfo *    lp;
-    register int            i;
+    register struct state *  sp;
+    register struct lsinfo * lp;
+    register int             i;
 
     sp = lclptr;
     i = sp->leapcnt;
@@ -2069,8 +2066,8 @@ time2posix(time_t t)
 time_t
 posix2time(time_t t)
 {
-    time_t  x;
-    time_t  y;
+    time_t x;
+    time_t y;
 
     tzset();
     /*
@@ -2167,26 +2164,40 @@ static int __bionic_open_tzdata_path(const char* path_prefix_variable, const cha
   }
 
   off_t specific_zone_offset = -1;
+  ssize_t index_size = ntohl(header.data_offset) - ntohl(header.index_offset);
+  char* index = malloc(index_size);
+  if (TEMP_FAILURE_RETRY(read(fd, index, index_size)) != index_size) {
+    fprintf(stderr, "%s: could not read index of \"%s\": %s\n",
+            __FUNCTION__, path, (bytes_read == -1) ? strerror(errno) : "short read");
+    free(index);
+    close(fd);
+    return -1;
+  }
 
   static const size_t NAME_LENGTH = 40;
-  unsigned char buf[NAME_LENGTH + 3 * sizeof(int32_t)];
-
-  size_t id_count = (ntohl(header.data_offset) - ntohl(header.index_offset)) / sizeof(buf);
+  struct index_entry_t {
+    char buf[NAME_LENGTH];
+    int32_t start;
+    int32_t length;
+    int32_t raw_gmt_offset;
+  };
+
+  size_t id_count = (ntohl(header.data_offset) - ntohl(header.index_offset)) / sizeof(struct index_entry_t);
+  struct index_entry_t* entry = (struct index_entry_t*) index;
   for (size_t i = 0; i < id_count; ++i) {
-    if (TEMP_FAILURE_RETRY(read(fd, buf, sizeof(buf))) != (ssize_t) sizeof(buf)) {
-      break;
-    }
-
     char this_id[NAME_LENGTH + 1];
-    memcpy(this_id, buf, NAME_LENGTH);
+    memcpy(this_id, entry->buf, NAME_LENGTH);
     this_id[NAME_LENGTH] = '\0';
 
     if (strcmp(this_id, olson_id) == 0) {
-      specific_zone_offset = to_int(buf + NAME_LENGTH) + ntohl(header.data_offset);
-      *data_size = to_int(buf + NAME_LENGTH + sizeof(int32_t));
+      specific_zone_offset = ntohl(entry->start) + ntohl(header.data_offset);
+      *data_size = ntohl(entry->length);
       break;
     }
+
+    ++entry;
   }
+  free(index);
 
   if (specific_zone_offset == -1) {
     XLOG(("%s: couldn't find zone \"%s\"\n", __FUNCTION__, olson_id));
index 3a1930571db5e178ab27833cb549d2fd83ec567c..4eb0ab62215bf39b52119fc6934466388ffe6471 100644 (file)
 #define HAVE_INCOMPATIBLE_CTIME_R      0
 #endif /* !defined INCOMPATIBLE_CTIME_R */
 
+#ifndef HAVE_LINK
+#define HAVE_LINK              1
+#endif /* !defined HAVE_LINK */
+
 #ifndef HAVE_SETTIMEOFDAY
 #define HAVE_SETTIMEOFDAY      3
 #endif /* !defined HAVE_SETTIMEOFDAY */
index a2955dd1479965cef256f84877524db1cdc03819..529650dd8a044b7a141dd41fbff76134c36dcb01 100644 (file)
@@ -101,16 +101,8 @@ struct tzhead {
 #endif /* !defined TZ_MAX_TIMES */
 
 #ifndef TZ_MAX_TYPES
-#ifndef NOSOLAR
+/* This must be at least 17 for Europe/Samara and Europe/Vilnius.  */
 #define TZ_MAX_TYPES   256 /* Limited by what (unsigned char)'s can hold */
-#endif /* !defined NOSOLAR */
-#ifdef NOSOLAR
-/*
-** Must be at least 14 for Europe/Riga as of Jan 12 1995,
-** as noted by Earl Chew.
-*/
-#define TZ_MAX_TYPES   20      /* Maximum number of local time types */
-#endif /* !defined NOSOLAR */
 #endif /* !defined TZ_MAX_TYPES */
 
 #ifndef TZ_MAX_CHARS
similarity index 78%
rename from libc/unistd/alarm.c
rename to libc/upstream-openbsd/lib/libc/gen/alarm.c
index 53edea949854e082ea454fd1eebc53a360a21676..2af847a46a39c2706693ae11b1701c8fadb460b0 100644 (file)
@@ -1,3 +1,4 @@
+/*     $OpenBSD: alarm.c,v 1.7 2005/08/08 08:05:33 espie Exp $ */
 /*
  * Copyright (c) 1983, 1993
  *     The Regents of the University of California.  All rights reserved.
@@ -10,7 +11,7 @@
  * 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.
- * 4. Neither the name of the University nor the names of its contributors
+ * 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.
  *
  * SUCH DAMAGE.
  */
 
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)alarm.c    8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-#include <sys/cdefs.h>
-//__FBSDID("$FreeBSD: /repoman/r/ncvs/src/lib/libc/gen/alarm.c,v 1.3 2007/01/09 00:27:53 imp Exp $");
-
 /*
  * Backwards compatible alarm.
  */
@@ -40,22 +35,16 @@ static char sccsid[] = "@(#)alarm.c 8.1 (Berkeley) 6/4/93";
 #include <unistd.h>
 
 unsigned int
-alarm(secs)
-       unsigned int secs;
+alarm(unsigned int secs)
 {
        struct itimerval it, oitv;
        struct itimerval *itp = &it;
 
-    itp->it_interval.tv_usec = 0;
-    itp->it_interval.tv_sec = 0;
+       timerclear(&itp->it_interval);
        itp->it_value.tv_sec = secs;
        itp->it_value.tv_usec = 0;
        if (setitimer(ITIMER_REAL, itp, &oitv) < 0)
-#if 1 /* BIONIC: Same behaviour than GLibc for errors */
-               return 0;
-#else
-               return (-1);
-#endif
+               return ((unsigned int) -1);
        if (oitv.it_value.tv_usec)
                oitv.it_value.tv_sec++;
        return (oitv.it_value.tv_sec);
diff --git a/libc/upstream-openbsd/lib/libc/gen/getprogname.c b/libc/upstream-openbsd/lib/libc/gen/getprogname.c
new file mode 100644 (file)
index 0000000..1cf498c
--- /dev/null
@@ -0,0 +1,24 @@
+/* $OpenBSD: getprogname.c,v 1.2 2013/05/31 21:19:01 tedu Exp $ */
+/*
+ * Copyright (c) 2013 Antoine Jacoutot <ajacoutot@openbsd.org>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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.
+ */
+
+extern const char *__progname;
+
+const char *
+getprogname(void)
+{
+       return (__progname);
+}
diff --git a/libc/upstream-openbsd/lib/libc/gen/setprogname.c b/libc/upstream-openbsd/lib/libc/gen/setprogname.c
new file mode 100644 (file)
index 0000000..18b2ce0
--- /dev/null
@@ -0,0 +1,32 @@
+/* $OpenBSD: setprogname.c,v 1.3 2013/06/01 01:43:43 tedu Exp $ */
+/*
+ * Copyright (c) 2013 Antoine Jacoutot <ajacoutot@openbsd.org>
+ *
+ * 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 THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR 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 <string.h>
+
+extern const char *__progname;
+
+void
+setprogname(const char *progname)
+{
+       const char *tmpn;
+
+       tmpn = strrchr(progname, '/');
+       if (tmpn == NULL)
+               __progname = progname;
+       else
+               __progname = tmpn + 1;
+}
index 5fafba6b06d17e4ab84405b8d28cfc3eea4afe3e..451b3a99dfc28de764cfa69001a234483ad6a5cb 100644 (file)
@@ -71,6 +71,7 @@ libBionicStandardTests_src_files := \
     sys_resource_test.cpp \
     sys_select_test.cpp \
     sys_sendfile_test.cpp \
+    sys_socket_test.cpp \
     sys_stat_test.cpp \
     sys_statvfs_test.cpp \
     sys_syscall_test.cpp \
index d2341188beff50668c19e8ad6e0e935d0dbb283c..d481a1d86fe18bd5881df54ca521dd00dc1d1f90 100644 (file)
@@ -22,6 +22,7 @@
 #include <pthread.h>
 #include <signal.h>
 #include <sys/mman.h>
+#include <time.h>
 #include <unistd.h>
 
 TEST(pthread, pthread_key_create) {
@@ -597,3 +598,58 @@ TEST(pthread, pthread_attr_getscope) {
   ASSERT_EQ(0, pthread_attr_getscope(&attr, &scope));
   ASSERT_EQ(PTHREAD_SCOPE_SYSTEM, scope);
 }
+
+TEST(pthread, pthread_condattr_init) {
+  pthread_condattr_t attr;
+  pthread_condattr_init(&attr);
+
+  clockid_t clock;
+  ASSERT_EQ(0, pthread_condattr_getclock(&attr, &clock));
+  ASSERT_EQ(CLOCK_REALTIME, clock);
+
+  int pshared;
+  ASSERT_EQ(0, pthread_condattr_getpshared(&attr, &pshared));
+  ASSERT_EQ(PTHREAD_PROCESS_PRIVATE, pshared);
+}
+
+TEST(pthread, pthread_condattr_setclock) {
+  pthread_condattr_t attr;
+  pthread_condattr_init(&attr);
+
+  ASSERT_EQ(0, pthread_condattr_setclock(&attr, CLOCK_REALTIME));
+  clockid_t clock;
+  ASSERT_EQ(0, pthread_condattr_getclock(&attr, &clock));
+  ASSERT_EQ(CLOCK_REALTIME, clock);
+
+  ASSERT_EQ(0, pthread_condattr_setclock(&attr, CLOCK_MONOTONIC));
+  ASSERT_EQ(0, pthread_condattr_getclock(&attr, &clock));
+  ASSERT_EQ(CLOCK_MONOTONIC, clock);
+
+  ASSERT_EQ(EINVAL, pthread_condattr_setclock(&attr, CLOCK_PROCESS_CPUTIME_ID));
+}
+
+TEST(pthread, pthread_cond_broadcast__preserves_condattr_flags) {
+#if defined(__BIONIC__) // This tests a bionic implementation detail.
+  pthread_condattr_t attr;
+  pthread_condattr_init(&attr);
+
+  ASSERT_EQ(0, pthread_condattr_setclock(&attr, CLOCK_MONOTONIC));
+  ASSERT_EQ(0, pthread_condattr_setpshared(&attr, PTHREAD_PROCESS_SHARED));
+
+  pthread_cond_t cond_var;
+  ASSERT_EQ(0, pthread_cond_init(&cond_var, &attr));
+
+  ASSERT_EQ(0, pthread_cond_signal(&cond_var));
+  ASSERT_EQ(0, pthread_cond_broadcast(&cond_var));
+
+  attr = static_cast<pthread_condattr_t>(cond_var.value);
+  clockid_t clock;
+  ASSERT_EQ(0, pthread_condattr_getclock(&attr, &clock));
+  ASSERT_EQ(CLOCK_MONOTONIC, clock);
+  int pshared;
+  ASSERT_EQ(0, pthread_condattr_getpshared(&attr, &pshared));
+  ASSERT_EQ(PTHREAD_PROCESS_SHARED, pshared);
+#else // __BIONIC__
+  GTEST_LOG_(INFO) << "This test does nothing.\n";
+#endif // __BIONIC__
+}
diff --git a/tests/sys_socket_test.cpp b/tests/sys_socket_test.cpp
new file mode 100644 (file)
index 0000000..901ac17
--- /dev/null
@@ -0,0 +1,34 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <gtest/gtest.h>
+
+#include <errno.h>
+#include <sys/socket.h>
+
+TEST(sys_socket, recvmmsg) {
+#if !defined(__GLIBC__) // TODO: Android's prebuilt gcc is too old for recvmmsg/sendmmsg.
+  ASSERT_EQ(-1, recvmmsg(-1, NULL, 0, 0, NULL));
+  ASSERT_EQ(EBADF, errno);
+#endif
+}
+
+TEST(sys_socket, sendmmsg) {
+#if !defined(__GLIBC__) // TODO: Android's prebuilt gcc is too old for recvmmsg/sendmmsg.
+  ASSERT_EQ(-1, sendmmsg(-1, NULL, 0, 0));
+  ASSERT_EQ(EBADF, errno);
+#endif
+}
index 9969d49bcdf9cf018628ff62665f297d1987cbb8..f50c102f6b187d922a4a2cbfa63ea6bee3eeee0b 100644 (file)
@@ -112,3 +112,7 @@ TEST(unistd, read_EBADF) {
   ASSERT_EQ(-1, read(-1, buf, sizeof(buf)));
   ASSERT_EQ(EBADF, errno);
 }
+
+TEST(unistd, alarm) {
+  ASSERT_EQ(0U, alarm(0));
+}