Reconcile with jb-mr2-release - do not merge
Change-Id: I0839dac295b83f3c5d53d0bb81925b44e3ec17cc
diff --git a/libc/Android.mk b/libc/Android.mk
index 22ed2d8..411d780 100644
--- a/libc/Android.mk
+++ b/libc/Android.mk
@@ -15,58 +15,29 @@
unistd/system.c \
unistd/time.c \
stdio/asprintf.c \
- stdio/clrerr.c \
- stdio/fclose.c \
- stdio/fdopen.c \
- stdio/feof.c \
- stdio/ferror.c \
stdio/fflush.c \
stdio/fgetc.c \
- stdio/fgetln.c \
- stdio/fgetpos.c \
- stdio/fgets.c \
- stdio/fileno.c \
stdio/findfp.c \
- stdio/flags.c \
- stdio/fopen.c \
stdio/fprintf.c \
- stdio/fpurge.c \
stdio/fputc.c \
- stdio/fputs.c \
stdio/fread.c \
stdio/freopen.c \
stdio/fscanf.c \
stdio/fseek.c \
- stdio/fsetpos.c \
stdio/ftell.c \
- stdio/funopen.c \
stdio/fvwrite.c \
- stdio/fwalk.c \
- stdio/fwrite.c \
- stdio/getc.c \
- stdio/getchar.c \
stdio/gets.c \
stdio/makebuf.c \
stdio/mktemp.c \
stdio/printf.c \
- stdio/putc.c \
- stdio/putchar.c \
- stdio/puts.c \
- stdio/putw.c \
stdio/refill.c \
- stdio/remove.c \
stdio/rewind.c \
- stdio/rget.c \
stdio/scanf.c \
- stdio/setbuf.c \
- stdio/setbuffer.c \
stdio/setvbuf.c \
stdio/snprintf.c\
stdio/sprintf.c \
stdio/sscanf.c \
stdio/stdio.c \
- stdio/tempnam.c \
- stdio/tmpnam.c \
stdio/ungetc.c \
stdio/vasprintf.c \
stdio/vfprintf.c \
@@ -77,13 +48,11 @@
stdio/vscanf.c \
stdio/vsscanf.c \
stdio/wbuf.c \
- stdio/wsetup.c \
stdlib/atexit.c \
stdlib/ctype_.c \
stdlib/exit.c \
stdlib/getenv.c \
stdlib/putenv.c \
- stdlib/qsort.c \
stdlib/setenv.c \
stdlib/strtod.c \
stdlib/strtoimax.c \
@@ -97,7 +66,6 @@
string/index.c \
string/strcasecmp.c \
string/strcat.c \
- string/strchr.c \
string/strcspn.c \
string/strdup.c \
string/strlcat.c \
@@ -170,7 +138,6 @@
bionic/recv.c \
bionic/sched_cpualloc.c \
bionic/sched_cpucount.c \
- bionic/sched_getaffinity.c \
bionic/sched_getcpu.c \
bionic/semaphore.c \
bionic/send.c \
@@ -264,11 +231,13 @@
bionic/raise.cpp \
bionic/sbrk.cpp \
bionic/scandir.cpp \
+ bionic/sched_getaffinity.cpp \
bionic/__set_errno.cpp \
bionic/setlocale.cpp \
bionic/signalfd.cpp \
bionic/sigwait.cpp \
bionic/__strcat_chk.cpp \
+ bionic/strchr.cpp \
bionic/__strcpy_chk.cpp \
bionic/strerror.cpp \
bionic/strerror_r.cpp \
@@ -289,6 +258,37 @@
bionic/wchar.cpp \
libc_upstream_freebsd_src_files := \
+ upstream-freebsd/lib/libc/stdio/clrerr.c \
+ upstream-freebsd/lib/libc/stdio/fclose.c \
+ upstream-freebsd/lib/libc/stdio/fdopen.c \
+ upstream-freebsd/lib/libc/stdio/feof.c \
+ upstream-freebsd/lib/libc/stdio/ferror.c \
+ upstream-freebsd/lib/libc/stdio/fgetln.c \
+ upstream-freebsd/lib/libc/stdio/fgetpos.c \
+ upstream-freebsd/lib/libc/stdio/fgets.c \
+ upstream-freebsd/lib/libc/stdio/fileno.c \
+ upstream-freebsd/lib/libc/stdio/flags.c \
+ upstream-freebsd/lib/libc/stdio/fopen.c \
+ upstream-freebsd/lib/libc/stdio/fpurge.c \
+ upstream-freebsd/lib/libc/stdio/fputs.c \
+ upstream-freebsd/lib/libc/stdio/fsetpos.c \
+ upstream-freebsd/lib/libc/stdio/funopen.c \
+ upstream-freebsd/lib/libc/stdio/fwalk.c \
+ upstream-freebsd/lib/libc/stdio/fwrite.c \
+ upstream-freebsd/lib/libc/stdio/getc.c \
+ upstream-freebsd/lib/libc/stdio/getchar.c \
+ upstream-freebsd/lib/libc/stdio/putc.c \
+ upstream-freebsd/lib/libc/stdio/putchar.c \
+ upstream-freebsd/lib/libc/stdio/puts.c \
+ upstream-freebsd/lib/libc/stdio/putw.c \
+ upstream-freebsd/lib/libc/stdio/remove.c \
+ upstream-freebsd/lib/libc/stdio/rget.c \
+ upstream-freebsd/lib/libc/stdio/setbuf.c \
+ upstream-freebsd/lib/libc/stdio/setbuffer.c \
+ upstream-freebsd/lib/libc/stdio/tempnam.c \
+ upstream-freebsd/lib/libc/stdio/tmpnam.c \
+ upstream-freebsd/lib/libc/stdio/wsetup.c \
+ upstream-freebsd/lib/libc/stdlib/qsort.c \
upstream-freebsd/lib/libc/stdlib/realpath.c \
upstream-freebsd/lib/libc/string/wcpcpy.c \
upstream-freebsd/lib/libc/string/wcpncpy.c \
diff --git a/libc/NOTICE b/libc/NOTICE
index 730fa46..be59d38 100644
--- a/libc/NOTICE
+++ b/libc/NOTICE
@@ -2056,6 +2056,35 @@
Copyright (c) 1992, 1993
The Regents of the University of California. All rights reserved.
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+4. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+-------------------------------------------------------------------
+
+Copyright (c) 1992, 1993
+ The Regents of the University of California. All rights reserved.
+
This code is derived from software contributed to Berkeley by
Ralph Campbell.
diff --git a/libc/SYSCALLS.TXT b/libc/SYSCALLS.TXT
index 96cc9e6..ac04e51 100644
--- a/libc/SYSCALLS.TXT
+++ b/libc/SYSCALLS.TXT
@@ -221,6 +221,9 @@
int __timer_delete:timer_delete(timer_t) 1
int utimes(const char*, const struct timeval tvp[2]) 1
int utimensat(int, const char *, const struct timespec times[2], int) 1
+int timerfd_create(clockid_t, int) 1
+int timerfd_settime(int, int, const struct itimerspec *, struct itimerspec *) 1
+int timerfd_gettime(int, struct itimerspec *) 1
# signals
int sigaction(int, const struct sigaction *, struct sigaction *) 1
diff --git a/libc/arch-arm/bionic/strlen.c b/libc/arch-arm/bionic/strlen.c
index 01632e3..ca0669d 100644
--- a/libc/arch-arm/bionic/strlen.c
+++ b/libc/arch-arm/bionic/strlen.c
@@ -60,52 +60,52 @@
// We need to process 32 bytes per loop to schedule PLD properly
// and achieve the maximum bus speed.
asm(
- "ldr %[v], [ %[s] ], #4 \n"
+ "ldr %[v], [%[s]], #4 \n"
"sub %[l], %[l], %[s] \n"
"0: \n"
#if __ARM_HAVE_PLD
- "pld [ %[s], #64 ] \n"
+ "pld [%[s], #64] \n"
#endif
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
- "ldreq %[v], [ %[s] ], #4 \n"
+ "ldreq %[v], [%[s]], #4 \n"
#if !defined(__OPTIMIZE_SIZE__)
"bne 1f \n"
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
- "ldreq %[v], [ %[s] ], #4 \n"
+ "ldreq %[v], [%[s]], #4 \n"
"bne 1f \n"
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
- "ldreq %[v], [ %[s] ], #4 \n"
+ "ldreq %[v], [%[s]], #4 \n"
"bne 1f \n"
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
- "ldreq %[v], [ %[s] ], #4 \n"
+ "ldreq %[v], [%[s]], #4 \n"
"bne 1f \n"
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
- "ldreq %[v], [ %[s] ], #4 \n"
+ "ldreq %[v], [%[s]], #4 \n"
"bne 1f \n"
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
- "ldreq %[v], [ %[s] ], #4 \n"
+ "ldreq %[v], [%[s]], #4 \n"
"bne 1f \n"
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
- "ldreq %[v], [ %[s] ], #4 \n"
+ "ldreq %[v], [%[s]], #4 \n"
"bne 1f \n"
"sub %[t], %[v], %[mask], lsr #7\n"
"and %[t], %[t], %[mask] \n"
"bics %[t], %[t], %[v] \n"
- "ldreq %[v], [ %[s] ], #4 \n"
+ "ldreq %[v], [%[s]], #4 \n"
#endif
"beq 0b \n"
"1: \n"
diff --git a/libc/arch-arm/cortex-a15/bionic/memcpy.S b/libc/arch-arm/cortex-a15/bionic/memcpy.S
index 16187b5..d297064 100644
--- a/libc/arch-arm/cortex-a15/bionic/memcpy.S
+++ b/libc/arch-arm/cortex-a15/bionic/memcpy.S
@@ -25,80 +25,109 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+/*
+ * Copyright (c) 2013 ARM Ltd
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the company may not be used to endorse or promote
+ * products derived from this software without specific prior written
+ * permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY ARM LTD ``AS IS'' AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL ARM LTD BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED
+ * TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
+ * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
+ * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
-/* Assumes neon instructions and a cache line size of 64 bytes. */
+ /* Prototype: void *memcpy (void *dst, const void *src, size_t count). */
+
+ // This version is tuned for the Cortex-A15 processor.
#include <machine/cpu-features.h>
#include <machine/asm.h>
-/*
- * This code assumes it is running on a processor that supports all arm v7
- * instructions, that supports neon instructions, and that has a 64 byte
- * cache line.
- */
-
.text
+ .syntax unified
.fpu neon
-#define CACHE_LINE_SIZE 64
+#define CACHE_LINE_SIZE 64
ENTRY(memcpy)
- .save {r0, lr}
- /* start preloading as early as possible */
- pld [r1, #(CACHE_LINE_SIZE*0)]
- stmfd sp!, {r0, lr}
- pld [r1, #(CACHE_LINE_SIZE*1)]
+ // Assumes that n >= 0, and dst, src are valid pointers.
+ // For any sizes less than 832 use the neon code that doesn't
+ // care about the src alignment. This avoids any checks
+ // for src alignment, and offers the best improvement since
+ // smaller sized copies are dominated by the overhead of
+ // the pre and post main loop.
+ // For larger copies, if src and dst cannot both be aligned to
+ // word boundaries, use the neon code.
+ // For all other copies, align dst to a double word boundary
+ // and copy using LDRD/STRD instructions.
- /* do we have at least 16-bytes to copy (needed for alignment below) */
- cmp r2, #16
- blo 5f
+ // Save registers (r0 holds the return value):
+ // optimized push {r0, lr}.
+ .save {r0, lr}
+ pld [r1, #(CACHE_LINE_SIZE*16)]
+ push {r0, lr}
- /* align destination to cache-line for the write-buffer */
+ cmp r2, #16
+ blo copy_less_than_16_unknown_align
+
+ cmp r2, #832
+ bge check_alignment
+
+copy_unknown_alignment:
+ // Unknown alignment of src and dst.
+ // Assumes that the first few bytes have already been prefetched.
+
+ // Align destination to 128 bits. The mainloop store instructions
+ // require this alignment or they will throw an exception.
rsb r3, r0, #0
ands r3, r3, #0xF
- beq 0f
+ beq 2f
- /* copy up to 15-bytes (count in r3) */
+ // Copy up to 15 bytes (count in r3).
sub r2, r2, r3
movs ip, r3, lsl #31
- ldrmib lr, [r1], #1
- strmib lr, [r0], #1
- ldrcsb ip, [r1], #1
- ldrcsb lr, [r1], #1
- strcsb ip, [r0], #1
- strcsb lr, [r0], #1
+
+ itt mi
+ ldrbmi lr, [r1], #1
+ strbmi lr, [r0], #1
+ itttt cs
+ ldrbcs ip, [r1], #1
+ ldrbcs lr, [r1], #1
+ strbcs ip, [r0], #1
+ strbcs lr, [r0], #1
+
movs ip, r3, lsl #29
bge 1f
- // copies 4 bytes, destination 32-bits aligned
+ // Copies 4 bytes, dst 32 bits aligned before, at least 64 bits after.
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0, :32]!
1: bcc 2f
- // copies 8 bytes, destination 64-bits aligned
+ // Copies 8 bytes, dst 64 bits aligned before, at least 128 bits after.
vld1.8 {d0}, [r1]!
vst1.8 {d0}, [r0, :64]!
-2:
-0: /* preload immediately the next cache line, which we may need */
- pld [r1, #(CACHE_LINE_SIZE*0)]
- pld [r1, #(CACHE_LINE_SIZE*1)]
-
- /* make sure we have at least 64 bytes to copy */
+2: // Make sure we have at least 64 bytes to copy.
subs r2, r2, #64
blo 2f
- /* Preload all the cache lines we need.
- * NOTE: The number of pld below depends on CACHE_LINE_SIZE,
- * ideally we would increase the distance in the main loop to
- * avoid the goofy code below. In practice this doesn't seem to make
- * a big difference.
- * NOTE: The value CACHE_LINE_SIZE * 4 was chosen through
- * experimentation.
- */
- pld [r1, #(CACHE_LINE_SIZE*2)]
- pld [r1, #(CACHE_LINE_SIZE*3)]
- pld [r1, #(CACHE_LINE_SIZE*4)]
-
-1: /* The main loop copies 64 bytes at a time */
+1: // The main loop copies 64 bytes at a time.
vld1.8 {d0 - d3}, [r1]!
vld1.8 {d4 - d7}, [r1]!
pld [r1, #(CACHE_LINE_SIZE*4)]
@@ -107,25 +136,24 @@
vst1.8 {d4 - d7}, [r0, :128]!
bhs 1b
-2: /* fix-up the remaining count and make sure we have >= 32 bytes left */
- add r2, r2, #64
- subs r2, r2, #32
- blo 4f
+2: // Fix-up the remaining count and make sure we have >= 32 bytes left.
+ adds r2, r2, #32
+ blo 3f
-3: /* 32 bytes at a time. These cache lines were already preloaded */
+ // 32 bytes. These cache lines were already preloaded.
vld1.8 {d0 - d3}, [r1]!
- subs r2, r2, #32
+ sub r2, r2, #32
vst1.8 {d0 - d3}, [r0, :128]!
- bhs 3b
-4: /* less than 32 left */
+3: // Less than 32 left.
add r2, r2, #32
tst r2, #0x10
- beq 5f
- // copies 16 bytes, 128-bits aligned
+ beq copy_less_than_16_unknown_align
+ // Copies 16 bytes, destination 128 bits aligned.
vld1.8 {d0, d1}, [r1]!
vst1.8 {d0, d1}, [r0, :128]!
-5: /* copy up to 15-bytes (count in r2) */
+copy_less_than_16_unknown_align:
+ // Copy up to 15 bytes (count in r2).
movs ip, r2, lsl #29
bcc 1f
vld1.8 {d0}, [r1]!
@@ -133,14 +161,164 @@
1: bge 2f
vld4.8 {d0[0], d1[0], d2[0], d3[0]}, [r1]!
vst4.8 {d0[0], d1[0], d2[0], d3[0]}, [r0]!
-2: movs ip, r2, lsl #31
- ldrmib r3, [r1], #1
- ldrcsb ip, [r1], #1
- ldrcsb lr, [r1], #1
- strmib r3, [r0], #1
- strcsb ip, [r0], #1
- strcsb lr, [r0], #1
- ldmfd sp!, {r0, lr}
- bx lr
+2: // Copy 0 to 4 bytes.
+ lsls r2, r2, #31
+ itt ne
+ ldrbne lr, [r1], #1
+ strbne lr, [r0], #1
+ itttt cs
+ ldrbcs ip, [r1], #1
+ ldrbcs lr, [r1]
+ strbcs ip, [r0], #1
+ strbcs lr, [r0]
+
+ pop {r0, pc}
+
+check_alignment:
+ // If src and dst cannot both be aligned to a word boundary,
+ // use the unaligned copy version.
+ eor r3, r0, r1
+ ands r3, r3, #0x3
+ bne copy_unknown_alignment
+
+ // To try and improve performance, stack layout changed,
+ // i.e., not keeping the stack looking like users expect
+ // (highest numbered register at highest address).
+ // TODO: Add debug frame directives.
+ // We don't need exception unwind directives, because the code below
+ // does not throw any exceptions and does not call any other functions.
+ // Generally, newlib functions like this lack debug information for
+ // assembler source.
+ .save {r4, r5}
+ strd r4, r5, [sp, #-8]!
+ .save {r6, r7}
+ strd r6, r7, [sp, #-8]!
+ .save {r8, r9}
+ strd r8, r9, [sp, #-8]!
+
+ // Optimized for already aligned dst code.
+ ands ip, r0, #3
+ bne dst_not_word_aligned
+
+word_aligned:
+ // Align the destination buffer to 8 bytes, to make sure double
+ // loads and stores don't cross a cache line boundary,
+ // as they are then more expensive even if the data is in the cache
+ // (require two load/store issue cycles instead of one).
+ // If only one of the buffers is not 8 bytes aligned,
+ // then it's more important to align dst than src,
+ // because there is more penalty for stores
+ // than loads that cross a cacheline boundary.
+ // This check and realignment are only done if there is >= 832
+ // bytes to copy.
+
+ // Dst is word aligned, but check if it is already double word aligned.
+ ands r3, r0, #4
+ beq 1f
+ ldr r3, [r1], #4
+ str r3, [r0], #4
+ sub r2, #4
+
+1: // Can only get here if > 64 bytes to copy, so don't do check r2.
+ sub r2, #64
+
+2: // Every loop iteration copies 64 bytes.
+ .irp offset, #0, #8, #16, #24, #32
+ ldrd r4, r5, [r1, \offset]
+ strd r4, r5, [r0, \offset]
+ .endr
+
+ ldrd r4, r5, [r1, #40]
+ ldrd r6, r7, [r1, #48]
+ ldrd r8, r9, [r1, #56]
+
+ // Keep the pld as far from the next load as possible.
+ // The amount to prefetch was determined experimentally using
+ // large sizes, and verifying the prefetch size does not affect
+ // the smaller copies too much.
+ // WARNING: If the ldrd and strd instructions get too far away
+ // from each other, performance suffers. Three loads
+ // in a row is the best tradeoff.
+ pld [r1, #(CACHE_LINE_SIZE*16)]
+ strd r4, r5, [r0, #40]
+ strd r6, r7, [r0, #48]
+ strd r8, r9, [r0, #56]
+
+ add r0, r0, #64
+ add r1, r1, #64
+ subs r2, r2, #64
+ bge 2b
+
+ // Fix-up the remaining count and make sure we have >= 32 bytes left.
+ adds r2, r2, #32
+ blo 4f
+
+ // Copy 32 bytes. These cache lines were already preloaded.
+ .irp offset, #0, #8, #16, #24
+ ldrd r4, r5, [r1, \offset]
+ strd r4, r5, [r0, \offset]
+ .endr
+ add r1, r1, #32
+ add r0, r0, #32
+ sub r2, r2, #32
+4: // Less than 32 left.
+ add r2, r2, #32
+ tst r2, #0x10
+ beq 5f
+ // Copy 16 bytes.
+ .irp offset, #0, #8
+ ldrd r4, r5, [r1, \offset]
+ strd r4, r5, [r0, \offset]
+ .endr
+ add r1, r1, #16
+ add r0, r0, #16
+
+5: // Copy up to 15 bytes (count in r2).
+ movs ip, r2, lsl #29
+ bcc 1f
+ // Copy 8 bytes.
+ ldrd r4, r5, [r1], #8
+ strd r4, r5, [r0], #8
+1: bge 2f
+ // Copy 4 bytes.
+ ldr r4, [r1], #4
+ str r4, [r0], #4
+2: // Copy 0 to 4 bytes.
+ lsls r2, r2, #31
+ itt ne
+ ldrbne lr, [r1], #1
+ strbne lr, [r0], #1
+ itttt cs
+ ldrbcs ip, [r1], #1
+ ldrbcs lr, [r1]
+ strbcs ip, [r0], #1
+ strbcs lr, [r0]
+
+ // Restore registers: optimized pop {r0, pc}
+ ldrd r8, r9, [sp], #8
+ ldrd r6, r7, [sp], #8
+ ldrd r4, r5, [sp], #8
+ pop {r0, pc}
+
+dst_not_word_aligned:
+ // Align dst to word.
+ rsb ip, ip, #4
+ cmp ip, #2
+
+ itt gt
+ ldrbgt lr, [r1], #1
+ strbgt lr, [r0], #1
+
+ itt ge
+ ldrbge lr, [r1], #1
+ strbge lr, [r0], #1
+
+ ldrb lr, [r1], #1
+ strb lr, [r0], #1
+
+ sub r2, r2, ip
+
+ // Src is guaranteed to be at least word aligned by this point.
+ b word_aligned
END(memcpy)
diff --git a/libc/arch-arm/cortex-a15/bionic/memset.S b/libc/arch-arm/cortex-a15/bionic/memset.S
index 7bb3297..2e1ad54 100644
--- a/libc/arch-arm/cortex-a15/bionic/memset.S
+++ b/libc/arch-arm/cortex-a15/bionic/memset.S
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2008 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -35,11 +35,12 @@
* memset() returns its first argument.
*/
- .fpu neon
+ .fpu neon
+ .syntax unified
ENTRY(bzero)
- mov r2, r1
- mov r1, #0
+ mov r2, r1
+ mov r1, #0
// Fall through to memset...
END(bzero)
@@ -47,60 +48,117 @@
.save {r0}
stmfd sp!, {r0}
- vdup.8 q0, r1
-
- /* do we have at least 16-bytes to write (needed for alignment below) */
+ // The new algorithm is slower for copies < 16 so use the old
+ // neon code in that case.
cmp r2, #16
- blo 3f
+ blo set_less_than_16_unknown_align
- /* align destination to 16 bytes for the write-buffer */
- rsb r3, r0, #0
- ands r3, r3, #0xF
- beq 2f
+ // Use strd which requires an even and odd register so move the
+ // values so that:
+ // r0 and r1 contain the memset value
+ // r2 is the number of bytes to set
+ // r3 is the destination pointer
+ mov r3, r0
- /* write up to 15-bytes (count in r3) */
- sub r2, r2, r3
- movs ip, r3, lsl #31
- strmib r1, [r0], #1
- strcsb r1, [r0], #1
- strcsb r1, [r0], #1
- movs ip, r3, lsl #29
- bge 1f
+ // Copy the byte value in every byte of r1.
+ mov r1, r1, lsl #24
+ orr r1, r1, r1, lsr #8
+ orr r1, r1, r1, lsr #16
- // writes 4 bytes, 32-bits aligned
- vst1.32 {d0[0]}, [r0, :32]!
-1: bcc 2f
+check_alignment:
+ // Align destination to a double word to avoid the strd crossing
+ // a cache line boundary.
+ ands ip, r3, #7
+ bne do_double_word_align
- // writes 8 bytes, 64-bits aligned
- vst1.8 {d0}, [r0, :64]!
-2:
- /* make sure we have at least 32 bytes to write */
- subs r2, r2, #32
- blo 2f
- vmov q1, q0
+double_word_aligned:
+ mov r0, r1
-1: /* The main loop writes 32 bytes at a time */
- subs r2, r2, #32
- vst1.8 {d0 - d3}, [r0, :128]!
- bhs 1b
+ subs r2, #64
+ blo set_less_than_64
-2: /* less than 32 left */
- add r2, r2, #32
- tst r2, #0x10
- beq 3f
+1: // Main loop sets 64 bytes at a time.
+ .irp offset, #0, #8, #16, #24, #32, #40, #48, #56
+ strd r0, r1, [r3, \offset]
+ .endr
- // writes 16 bytes, 128-bits aligned
- vst1.8 {d0, d1}, [r0, :128]!
-3: /* write up to 15-bytes (count in r2) */
+ add r3, #64
+ subs r2, #64
+ bge 1b
+
+set_less_than_64:
+ // Restore r2 to the count of bytes left to set.
+ add r2, #64
+ lsls ip, r2, #27
+ bcc set_less_than_32
+ // Set 32 bytes.
+ .irp offset, #0, #8, #16, #24
+ strd r0, r1, [r3, \offset]
+ .endr
+ add r3, #32
+
+set_less_than_32:
+ bpl set_less_than_16
+ // Set 16 bytes.
+ .irp offset, #0, #8
+ strd r0, r1, [r3, \offset]
+ .endr
+ add r3, #16
+
+set_less_than_16:
+ // Less than 16 bytes to set.
+ lsls ip, r2, #29
+ bcc set_less_than_8
+
+ // Set 8 bytes.
+ strd r0, r1, [r3], #8
+
+set_less_than_8:
+ bpl set_less_than_4
+ // Set 4 bytes
+ str r1, [r3], #4
+
+set_less_than_4:
+ lsls ip, r2, #31
+ it ne
+ strbne r1, [r3], #1
+ itt cs
+ strbcs r1, [r3], #1
+ strbcs r1, [r3]
+
+ ldmfd sp!, {r0}
+ bx lr
+
+do_double_word_align:
+ rsb ip, ip, #8
+ sub r2, r2, ip
+ movs r0, ip, lsl #31
+ it mi
+ strbmi r1, [r3], #1
+ itt cs
+ strbcs r1, [r3], #1
+ strbcs r1, [r3], #1
+
+ // Dst is at least word aligned by this point.
+ cmp ip, #4
+ blo double_word_aligned
+ str r1, [r3], #4
+ b double_word_aligned
+
+set_less_than_16_unknown_align:
+ // Set up to 15 bytes.
+ vdup.8 d0, r1
movs ip, r2, lsl #29
bcc 1f
vst1.8 {d0}, [r0]!
1: bge 2f
vst1.32 {d0[0]}, [r0]!
2: movs ip, r2, lsl #31
- strmib r1, [r0], #1
- strcsb r1, [r0], #1
- strcsb r1, [r0], #1
+ it mi
+ strbmi r1, [r0], #1
+ itt cs
+ strbcs r1, [r0], #1
+ strbcs r1, [r0], #1
ldmfd sp!, {r0}
bx lr
END(memset)
diff --git a/libc/arch-arm/syscalls.mk b/libc/arch-arm/syscalls.mk
index 9eb5136..3c8f204 100644
--- a/libc/arch-arm/syscalls.mk
+++ b/libc/arch-arm/syscalls.mk
@@ -144,6 +144,9 @@
syscall_src += arch-arm/syscalls/__timer_delete.S
syscall_src += arch-arm/syscalls/utimes.S
syscall_src += arch-arm/syscalls/utimensat.S
+syscall_src += arch-arm/syscalls/timerfd_create.S
+syscall_src += arch-arm/syscalls/timerfd_settime.S
+syscall_src += arch-arm/syscalls/timerfd_gettime.S
syscall_src += arch-arm/syscalls/sigaction.S
syscall_src += arch-arm/syscalls/sigprocmask.S
syscall_src += arch-arm/syscalls/__sigsuspend.S
diff --git a/libc/arch-arm/syscalls/timerfd_create.S b/libc/arch-arm/syscalls/timerfd_create.S
new file mode 100644
index 0000000..7e3f16f
--- /dev/null
+++ b/libc/arch-arm/syscalls/timerfd_create.S
@@ -0,0 +1,15 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+#include <linux/err.h>
+#include <machine/asm.h>
+
+ENTRY(timerfd_create)
+ mov ip, r7
+ ldr r7, =__NR_timerfd_create
+ swi #0
+ mov r7, ip
+ cmn r0, #(MAX_ERRNO + 1)
+ bxls lr
+ neg r0, r0
+ b __set_errno
+END(timerfd_create)
diff --git a/libc/arch-arm/syscalls/timerfd_gettime.S b/libc/arch-arm/syscalls/timerfd_gettime.S
new file mode 100644
index 0000000..2c3e2cf
--- /dev/null
+++ b/libc/arch-arm/syscalls/timerfd_gettime.S
@@ -0,0 +1,15 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+#include <linux/err.h>
+#include <machine/asm.h>
+
+ENTRY(timerfd_gettime)
+ mov ip, r7
+ ldr r7, =__NR_timerfd_gettime
+ swi #0
+ mov r7, ip
+ cmn r0, #(MAX_ERRNO + 1)
+ bxls lr
+ neg r0, r0
+ b __set_errno
+END(timerfd_gettime)
diff --git a/libc/arch-arm/syscalls/timerfd_settime.S b/libc/arch-arm/syscalls/timerfd_settime.S
new file mode 100644
index 0000000..f7f0cf0
--- /dev/null
+++ b/libc/arch-arm/syscalls/timerfd_settime.S
@@ -0,0 +1,15 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+#include <linux/err.h>
+#include <machine/asm.h>
+
+ENTRY(timerfd_settime)
+ mov ip, r7
+ ldr r7, =__NR_timerfd_settime
+ swi #0
+ mov r7, ip
+ cmn r0, #(MAX_ERRNO + 1)
+ bxls lr
+ neg r0, r0
+ b __set_errno
+END(timerfd_settime)
diff --git a/libc/arch-mips/syscalls.mk b/libc/arch-mips/syscalls.mk
index 0b8eccd..d3096bc 100644
--- a/libc/arch-mips/syscalls.mk
+++ b/libc/arch-mips/syscalls.mk
@@ -147,6 +147,9 @@
syscall_src += arch-mips/syscalls/__timer_delete.S
syscall_src += arch-mips/syscalls/utimes.S
syscall_src += arch-mips/syscalls/utimensat.S
+syscall_src += arch-mips/syscalls/timerfd_create.S
+syscall_src += arch-mips/syscalls/timerfd_settime.S
+syscall_src += arch-mips/syscalls/timerfd_gettime.S
syscall_src += arch-mips/syscalls/sigaction.S
syscall_src += arch-mips/syscalls/sigprocmask.S
syscall_src += arch-mips/syscalls/__sigsuspend.S
diff --git a/libc/arch-mips/syscalls/timerfd_create.S b/libc/arch-mips/syscalls/timerfd_create.S
new file mode 100644
index 0000000..b5ac003
--- /dev/null
+++ b/libc/arch-mips/syscalls/timerfd_create.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+ .text
+ .globl timerfd_create
+ .align 4
+ .ent timerfd_create
+
+timerfd_create:
+ .set noreorder
+ .cpload $t9
+ li $v0, __NR_timerfd_create
+ syscall
+ bnez $a3, 1f
+ move $a0, $v0
+ j $ra
+ nop
+1:
+ la $t9,__set_errno
+ j $t9
+ nop
+ .set reorder
+ .end timerfd_create
diff --git a/libc/arch-mips/syscalls/timerfd_gettime.S b/libc/arch-mips/syscalls/timerfd_gettime.S
new file mode 100644
index 0000000..b1c21ff
--- /dev/null
+++ b/libc/arch-mips/syscalls/timerfd_gettime.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+ .text
+ .globl timerfd_gettime
+ .align 4
+ .ent timerfd_gettime
+
+timerfd_gettime:
+ .set noreorder
+ .cpload $t9
+ li $v0, __NR_timerfd_gettime
+ syscall
+ bnez $a3, 1f
+ move $a0, $v0
+ j $ra
+ nop
+1:
+ la $t9,__set_errno
+ j $t9
+ nop
+ .set reorder
+ .end timerfd_gettime
diff --git a/libc/arch-mips/syscalls/timerfd_settime.S b/libc/arch-mips/syscalls/timerfd_settime.S
new file mode 100644
index 0000000..f68819d
--- /dev/null
+++ b/libc/arch-mips/syscalls/timerfd_settime.S
@@ -0,0 +1,22 @@
+/* autogenerated by gensyscalls.py */
+#include <asm/unistd.h>
+ .text
+ .globl timerfd_settime
+ .align 4
+ .ent timerfd_settime
+
+timerfd_settime:
+ .set noreorder
+ .cpload $t9
+ li $v0, __NR_timerfd_settime
+ syscall
+ bnez $a3, 1f
+ move $a0, $v0
+ j $ra
+ nop
+1:
+ la $t9,__set_errno
+ j $t9
+ nop
+ .set reorder
+ .end timerfd_settime
diff --git a/libc/arch-x86/syscalls.mk b/libc/arch-x86/syscalls.mk
index b4ad564..31eb930 100644
--- a/libc/arch-x86/syscalls.mk
+++ b/libc/arch-x86/syscalls.mk
@@ -148,6 +148,9 @@
syscall_src += arch-x86/syscalls/__timer_delete.S
syscall_src += arch-x86/syscalls/utimes.S
syscall_src += arch-x86/syscalls/utimensat.S
+syscall_src += arch-x86/syscalls/timerfd_create.S
+syscall_src += arch-x86/syscalls/timerfd_settime.S
+syscall_src += arch-x86/syscalls/timerfd_gettime.S
syscall_src += arch-x86/syscalls/sigaction.S
syscall_src += arch-x86/syscalls/sigprocmask.S
syscall_src += arch-x86/syscalls/__sigsuspend.S
diff --git a/libc/arch-x86/syscalls/timerfd_create.S b/libc/arch-x86/syscalls/timerfd_create.S
new file mode 100644
index 0000000..801f8a7
--- /dev/null
+++ b/libc/arch-x86/syscalls/timerfd_create.S
@@ -0,0 +1,24 @@
+/* autogenerated by gensyscalls.py */
+#include <linux/err.h>
+#include <machine/asm.h>
+#include <asm/unistd.h>
+
+ENTRY(timerfd_create)
+ pushl %ebx
+ pushl %ecx
+ mov 12(%esp), %ebx
+ mov 16(%esp), %ecx
+ movl $__NR_timerfd_create, %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(timerfd_create)
diff --git a/libc/arch-x86/syscalls/timerfd_gettime.S b/libc/arch-x86/syscalls/timerfd_gettime.S
new file mode 100644
index 0000000..fde17be
--- /dev/null
+++ b/libc/arch-x86/syscalls/timerfd_gettime.S
@@ -0,0 +1,24 @@
+/* autogenerated by gensyscalls.py */
+#include <linux/err.h>
+#include <machine/asm.h>
+#include <asm/unistd.h>
+
+ENTRY(timerfd_gettime)
+ pushl %ebx
+ pushl %ecx
+ mov 12(%esp), %ebx
+ mov 16(%esp), %ecx
+ movl $__NR_timerfd_gettime, %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(timerfd_gettime)
diff --git a/libc/arch-x86/syscalls/timerfd_settime.S b/libc/arch-x86/syscalls/timerfd_settime.S
new file mode 100644
index 0000000..5a5f3e4
--- /dev/null
+++ b/libc/arch-x86/syscalls/timerfd_settime.S
@@ -0,0 +1,30 @@
+/* autogenerated by gensyscalls.py */
+#include <linux/err.h>
+#include <machine/asm.h>
+#include <asm/unistd.h>
+
+ENTRY(timerfd_settime)
+ pushl %ebx
+ pushl %ecx
+ pushl %edx
+ pushl %esi
+ mov 20(%esp), %ebx
+ mov 24(%esp), %ecx
+ mov 28(%esp), %edx
+ mov 32(%esp), %esi
+ movl $__NR_timerfd_settime, %eax
+ int $0x80
+ cmpl $-MAX_ERRNO, %eax
+ jb 1f
+ negl %eax
+ pushl %eax
+ call __set_errno
+ addl $4, %esp
+ orl $-1, %eax
+1:
+ popl %esi
+ popl %edx
+ popl %ecx
+ popl %ebx
+ ret
+END(timerfd_settime)
diff --git a/libc/bionic/__memcpy_chk.cpp b/libc/bionic/__memcpy_chk.cpp
index b36cfdd..a3d744c 100644
--- a/libc/bionic/__memcpy_chk.cpp
+++ b/libc/bionic/__memcpy_chk.cpp
@@ -45,7 +45,7 @@
extern "C" void *__memcpy_chk(void *dest, const void *src,
size_t copy_amount, size_t dest_len)
{
- if (__builtin_expect(copy_amount > dest_len, 0)) {
+ if (__predict_false(copy_amount > dest_len)) {
__fortify_chk_fail("memcpy buffer overflow",
BIONIC_EVENT_MEMCPY_BUFFER_OVERFLOW);
}
diff --git a/libc/bionic/__memmove_chk.cpp b/libc/bionic/__memmove_chk.cpp
index ff770b5..49a0597 100644
--- a/libc/bionic/__memmove_chk.cpp
+++ b/libc/bionic/__memmove_chk.cpp
@@ -44,7 +44,7 @@
extern "C" void *__memmove_chk (void *dest, const void *src,
size_t len, size_t dest_len)
{
- if (len > dest_len) {
+ if (__predict_false(len > dest_len)) {
__fortify_chk_fail("memmove buffer overflow",
BIONIC_EVENT_MEMMOVE_BUFFER_OVERFLOW);
}
diff --git a/libc/bionic/__memset_chk.cpp b/libc/bionic/__memset_chk.cpp
index b201ed2..f7a5f24 100644
--- a/libc/bionic/__memset_chk.cpp
+++ b/libc/bionic/__memset_chk.cpp
@@ -42,7 +42,7 @@
* greater than 0.
*/
extern "C" void *__memset_chk (void *dest, int c, size_t n, size_t dest_len) {
- if (n > dest_len) {
+ if (__predict_false(n > dest_len)) {
__fortify_chk_fail("memset buffer overflow",
BIONIC_EVENT_MEMSET_BUFFER_OVERFLOW);
}
diff --git a/libc/bionic/__strcpy_chk.cpp b/libc/bionic/__strcpy_chk.cpp
index bfb6642..5aa0e93 100644
--- a/libc/bionic/__strcpy_chk.cpp
+++ b/libc/bionic/__strcpy_chk.cpp
@@ -44,7 +44,7 @@
extern "C" char *__strcpy_chk (char *dest, const char *src, size_t dest_len) {
// TODO: optimize so we don't scan src twice.
size_t src_len = strlen(src) + 1;
- if (src_len > dest_len) {
+ if (__predict_false(src_len > dest_len)) {
__fortify_chk_fail("strcpy buffer overflow",
BIONIC_EVENT_STRCPY_BUFFER_OVERFLOW);
}
diff --git a/libc/bionic/__strlcat_chk.cpp b/libc/bionic/__strlcat_chk.cpp
index 96f62f9..25c67ad 100644
--- a/libc/bionic/__strlcat_chk.cpp
+++ b/libc/bionic/__strlcat_chk.cpp
@@ -45,7 +45,7 @@
extern "C" size_t __strlcat_chk(char *dest, const char *src,
size_t supplied_size, size_t dest_len_from_compiler)
{
- if (supplied_size > dest_len_from_compiler) {
+ if (__predict_false(supplied_size > dest_len_from_compiler)) {
__fortify_chk_fail("strlcat buffer overflow", 0);
}
diff --git a/libc/bionic/__strlcpy_chk.cpp b/libc/bionic/__strlcpy_chk.cpp
index 636966b..f6b11fc 100644
--- a/libc/bionic/__strlcpy_chk.cpp
+++ b/libc/bionic/__strlcpy_chk.cpp
@@ -45,7 +45,7 @@
extern "C" size_t __strlcpy_chk(char *dest, const char *src,
size_t supplied_size, size_t dest_len_from_compiler)
{
- if (supplied_size > dest_len_from_compiler) {
+ if (__predict_false(supplied_size > dest_len_from_compiler)) {
__fortify_chk_fail("strlcpy buffer overflow", 0);
}
diff --git a/libc/bionic/__strlen_chk.cpp b/libc/bionic/__strlen_chk.cpp
index 6ebf09c..151a497 100644
--- a/libc/bionic/__strlen_chk.cpp
+++ b/libc/bionic/__strlen_chk.cpp
@@ -56,7 +56,7 @@
extern "C" size_t __strlen_chk(const char *s, size_t s_len) {
size_t ret = strlen(s);
- if (__builtin_expect(ret >= s_len, 0)) {
+ if (__predict_false(ret >= s_len)) {
__fortify_chk_fail("strlen read overflow", 0);
}
diff --git a/libc/bionic/__strncpy_chk.cpp b/libc/bionic/__strncpy_chk.cpp
index 0f1797e..b01879c 100644
--- a/libc/bionic/__strncpy_chk.cpp
+++ b/libc/bionic/__strncpy_chk.cpp
@@ -44,7 +44,7 @@
extern "C" char *__strncpy_chk (char *dest, const char *src,
size_t len, size_t dest_len)
{
- if (len > dest_len) {
+ if (__predict_false(len > dest_len)) {
__fortify_chk_fail("strncpy buffer overflow",
BIONIC_EVENT_STRNCPY_BUFFER_OVERFLOW);
}
diff --git a/libc/bionic/__umask_chk.cpp b/libc/bionic/__umask_chk.cpp
index ff67ed6..8fe95a2 100644
--- a/libc/bionic/__umask_chk.cpp
+++ b/libc/bionic/__umask_chk.cpp
@@ -42,7 +42,7 @@
* greater than 0.
*/
extern "C" mode_t __umask_chk(mode_t mode) {
- if ((mode & 0777) != mode) {
+ if (__predict_false((mode & 0777) != mode)) {
__fortify_chk_fail("umask called with invalid mask", 0);
}
diff --git a/libc/bionic/__vsnprintf_chk.cpp b/libc/bionic/__vsnprintf_chk.cpp
index 0fdda3e..2d3a81e 100644
--- a/libc/bionic/__vsnprintf_chk.cpp
+++ b/libc/bionic/__vsnprintf_chk.cpp
@@ -50,7 +50,7 @@
const char *format,
va_list va)
{
- if (supplied_size > dest_len_from_compiler) {
+ if (__predict_false(supplied_size > dest_len_from_compiler)) {
__fortify_chk_fail("vsnprintf buffer overflow", 0);
}
diff --git a/libc/bionic/malloc_debug_common.cpp b/libc/bionic/malloc_debug_common.cpp
index 2148d20..f6fa83c 100644
--- a/libc/bionic/malloc_debug_common.cpp
+++ b/libc/bionic/malloc_debug_common.cpp
@@ -524,7 +524,7 @@
* This routine is called from __libc_init routines implemented
* in libc_init_static.c and libc_init_dynamic.c files.
*/
-extern "C" void malloc_debug_init() {
+extern "C" __LIBC_HIDDEN__ void malloc_debug_init() {
/* We need to initialize malloc iff we implement here custom
* malloc routines (i.e. USE_DL_PREFIX is defined) for libc.so */
#if defined(USE_DL_PREFIX) && !defined(LIBC_STATIC)
@@ -534,7 +534,7 @@
#endif // USE_DL_PREFIX && !LIBC_STATIC
}
-extern "C" void malloc_debug_fini() {
+extern "C" __LIBC_HIDDEN__ void malloc_debug_fini() {
/* We need to finalize malloc iff we implement here custom
* malloc routines (i.e. USE_DL_PREFIX is defined) for libc.so */
#if defined(USE_DL_PREFIX) && !defined(LIBC_STATIC)
diff --git a/libc/bionic/open.c b/libc/bionic/open.c
index e3573a3..424573f 100644
--- a/libc/bionic/open.c
+++ b/libc/bionic/open.c
@@ -52,7 +52,7 @@
}
int __open_2(const char *pathname, int flags) {
- if (flags & O_CREAT) {
+ if (__predict_false(flags & O_CREAT)) {
__fortify_chk_fail("open(O_CREAT) called without specifying a mode", 0);
}
diff --git a/libc/bionic/sched_getaffinity.c b/libc/bionic/sched_getaffinity.cpp
similarity index 76%
rename from libc/bionic/sched_getaffinity.c
rename to libc/bionic/sched_getaffinity.cpp
index 7313822..26f22b1 100644
--- a/libc/bionic/sched_getaffinity.c
+++ b/libc/bionic/sched_getaffinity.cpp
@@ -25,17 +25,21 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
+
#define _GNU_SOURCE 1
#include <sched.h>
+#include <string.h>
-int sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set)
-{
- int ret = __sched_getaffinity(pid, setsize, set);
- if (ret >= 0) {
- if ((size_t)ret < setsize) {
- memset((char*)set + ret, '\0', setsize - (size_t)ret);
- }
- ret = 0;
- }
- return ret;
+extern "C" int __sched_getaffinity(pid_t, size_t, cpu_set_t*);
+
+int sched_getaffinity(pid_t pid, size_t set_size, cpu_set_t* set) {
+ int rc = __sched_getaffinity(pid, set_size, set);
+ if (rc == -1) {
+ return -1;
+ }
+
+ // Clear any bytes the kernel didn't touch.
+ // (The kernel returns the number of bytes written on success.)
+ memset(reinterpret_cast<char*>(set) + rc, 0, set_size - rc);
+ return 0;
}
diff --git a/libc/string/strchr.c b/libc/bionic/strchr.cpp
similarity index 77%
rename from libc/string/strchr.c
rename to libc/bionic/strchr.cpp
index 29acca5..972029e 100644
--- a/libc/string/strchr.c
+++ b/libc/bionic/strchr.cpp
@@ -1,4 +1,3 @@
-/* $OpenBSD: index.c,v 1.5 2005/08/08 08:05:37 espie Exp $ */
/*-
* Copyright (c) 1990 The Regents of the University of California.
* All rights reserved.
@@ -31,21 +30,21 @@
#include <string.h>
#include "libc_logging.h"
-char *
-__strchr_chk(const char *p, int ch, size_t s_len)
-{
- for (;; ++p, s_len--) {
- if (s_len == 0)
- __fortify_chk_fail("strchr read beyond buffer", 0);
- if (*p == (char) ch)
- return((char *)p);
- if (!*p)
- return((char *)NULL);
- }
- /* NOTREACHED */
+extern "C" char* __strchr_chk(const char* p, int ch, size_t s_len) {
+ for (;; ++p, s_len--) {
+ if (__predict_false(s_len == 0)) {
+ __fortify_chk_fail("read beyond buffer", 0);
+ }
+ if (*p == static_cast<char>(ch)) {
+ return const_cast<char*>(p);
+ }
+ if (*p == '\0') {
+ return NULL;
+ }
+ }
+ /* NOTREACHED */
}
-char *
-strchr(const char *p, int ch) {
- return __strchr_chk(p, ch, __BIONIC_FORTIFY_UNKNOWN_SIZE);
+extern "C" char* strchr(const char* p, int ch) {
+ return __strchr_chk(p, ch, __BIONIC_FORTIFY_UNKNOWN_SIZE);
}
diff --git a/libc/bionic/sysconf.cpp b/libc/bionic/sysconf.cpp
index 5e39e61..9ab2007 100644
--- a/libc/bionic/sysconf.cpp
+++ b/libc/bionic/sysconf.cpp
@@ -298,8 +298,8 @@
case _SC_TIMERS: return _POSIX_TIMERS;
#endif
- // GETGR_R_SIZE_MAX ?
- // GETPW_R_SIZE_MAX ?
+ case _SC_GETGR_R_SIZE_MAX: return 1024;
+ case _SC_GETPW_R_SIZE_MAX: return 1024;
case _SC_LOGIN_NAME_MAX: return SYSTEM_LOGIN_NAME_MAX;
diff --git a/libc/include/err.h b/libc/include/err.h
index 1636efe..f24da61 100644
--- a/libc/include/err.h
+++ b/libc/include/err.h
@@ -48,42 +48,42 @@
__BEGIN_DECLS
__noreturn void err(int, const char *, ...)
- __attribute__((__format__ (printf, 2, 3)));
+ __printflike(2, 3);
__noreturn void verr(int, const char *, __va_list)
- __attribute__((__format__ (printf, 2, 0)));
+ __printflike(2, 0);
__noreturn void errx(int, const char *, ...)
- __attribute__((__format__ (printf, 2, 3)));
+ __printflike(2, 3);
__noreturn void verrx(int, const char *, __va_list)
- __attribute__((__format__ (printf, 2, 0)));
+ __printflike(2, 0);
void warn(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
+ __printflike(1, 2);
void vwarn(const char *, __va_list)
- __attribute__((__format__ (printf, 1, 0)));
+ __printflike(1, 0);
void warnx(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
+ __printflike(1, 2);
void vwarnx(const char *, __va_list)
- __attribute__((__format__ (printf, 1, 0)));
+ __printflike(1, 0);
/*
* The _* versions are for use in library functions so user-defined
* versions of err*,warn* do not get used.
*/
__noreturn void _err(int, const char *, ...)
- __attribute__((__format__ (printf, 2, 3)));
+ __printflike(2, 3);
__noreturn void _verr(int, const char *, __va_list)
- __attribute__((__format__ (printf, 2, 0)));
+ __printflike(2, 0);
__noreturn void _errx(int, const char *, ...)
- __attribute__((__format__ (printf, 2, 3)));
+ __printflike(2, 3);
__noreturn void _verrx(int, const char *, __va_list)
- __attribute__((__format__ (printf, 2, 0)));
+ __printflike(2, 0);
void _warn(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
+ __printflike(1, 2);
void _vwarn(const char *, __va_list)
- __attribute__((__format__ (printf, 1, 0)));
+ __printflike(1, 0);
void _warnx(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)));
+ __printflike(1, 2);
void _vwarnx(const char *, __va_list)
- __attribute__((__format__ (printf, 1, 0)));
+ __printflike(1, 0);
__END_DECLS
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index fdf747d..aca6d9f 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -139,8 +139,8 @@
#define __SMBF 0x0080 /* _buf is from malloc */
#define __SAPP 0x0100 /* fdopen()ed in append mode */
#define __SSTR 0x0200 /* this is an sprintf/snprintf string */
-#define __SOPT 0x0400 /* do fseek() optimisation */
-#define __SNPT 0x0800 /* do not do fseek() optimisation */
+#define __SOPT 0x0400 /* do fseek() optimization */
+#define __SNPT 0x0800 /* do not do fseek() optimization */
#define __SOFF 0x1000 /* set iff _offset is in fact correct */
#define __SMOD 0x2000 /* true => fgetln modified _p text */
#define __SALC 0x4000 /* allocate string space dynamically */
@@ -160,14 +160,14 @@
#define _IONBF 2 /* setvbuf should set unbuffered */
#define BUFSIZ 1024 /* size of buffer used by setbuf */
-
#define EOF (-1)
/*
- * FOPEN_MAX is a minimum maximum, and should be the number of descriptors
- * that the kernel can provide without allocation of a resource that can
- * fail without the process sleeping. Do not use this for anything.
+ * FOPEN_MAX is a minimum maximum, and is the number of streams that
+ * stdio can provide without attempting to allocate further resources
+ * (which could fail). Do not use this for anything.
*/
+
#define FOPEN_MAX 20 /* must be <= OPEN_MAX <sys/syslimits.h> */
#define FILENAME_MAX 1024 /* must be <= PATH_MAX <sys/syslimits.h> */
@@ -178,6 +178,7 @@
#define L_tmpnam 1024 /* XXX must be == PATH_MAX */
#define TMP_MAX 308915776
+/* Always ensure that these are consistent with <fcntl.h> and <unistd.h>! */
#ifndef SEEK_SET
#define SEEK_SET 0 /* set file offset to offset */
#endif
@@ -202,25 +203,20 @@
int ferror(FILE *);
int fflush(FILE *);
int fgetc(FILE *);
-int fgetpos(FILE *, fpos_t *);
-char *fgets(char *, int, FILE *);
-FILE *fopen(const char *, const char *);
-int fprintf(FILE *, const char *, ...)
- __attribute__((__format__ (printf, 2, 3)))
- __attribute__((__nonnull__ (2)));
+char *fgets(char * __restrict, int, FILE * __restrict);
+FILE *fopen(const char * __restrict , const char * __restrict);
+int fprintf(FILE * __restrict , const char * __restrict, ...)
+ __printflike(2, 3);
int fputc(int, FILE *);
-int fputs(const char *, FILE *);
-size_t fread(void *, size_t, size_t, FILE *);
-FILE *freopen(const char *, const char *, FILE *);
-int fscanf(FILE *, const char *, ...)
- __attribute__ ((__format__ (scanf, 2, 3)))
- __attribute__ ((__nonnull__ (2)));
+int fputs(const char * __restrict, FILE * __restrict);
+size_t fread(void * __restrict, size_t, size_t, FILE * __restrict);
+FILE *freopen(const char * __restrict, const char * __restrict,
+ FILE * __restrict);
+int fscanf(FILE * __restrict, const char * __restrict, ...)
+ __scanflike(2, 3);
int fseek(FILE *, long, int);
-int fseeko(FILE *, off_t, int);
-int fsetpos(FILE *, const fpos_t *);
long ftell(FILE *);
-off_t ftello(FILE *);
-size_t fwrite(const void *, size_t, size_t, FILE *);
+size_t fwrite(const void * __restrict, size_t, size_t, FILE * __restrict);
int getc(FILE *);
int getchar(void);
ssize_t getdelim(char ** __restrict, size_t * __restrict, int,
@@ -234,55 +230,55 @@
extern char *sys_errlist[];
#endif
void perror(const char *);
-int printf(const char *, ...)
- __attribute__((__format__ (printf, 1, 2)))
- __attribute__((__nonnull__ (1)));
+int printf(const char * __restrict, ...)
+ __printflike(1, 2);
int putc(int, FILE *);
int putchar(int);
int puts(const char *);
int remove(const char *);
-int rename(const char *, const char *);
void rewind(FILE *);
-int scanf(const char *, ...)
- __attribute__ ((__format__ (scanf, 1, 2)))
- __attribute__ ((__nonnull__ (1)));
-void setbuf(FILE *, char *);
-int setvbuf(FILE *, char *, int, size_t);
-int sprintf(char *, const char *, ...)
- __attribute__((__format__ (printf, 2, 3)))
- __attribute__((__nonnull__ (2)));
-int sscanf(const char *, const char *, ...)
- __attribute__ ((__format__ (scanf, 2, 3)))
- __attribute__ ((__nonnull__ (2)));
+int scanf(const char * __restrict, ...)
+ __scanflike(1, 2);
+void setbuf(FILE * __restrict, char * __restrict);
+int setvbuf(FILE * __restrict, char * __restrict, int, size_t);
+int sscanf(const char * __restrict, const char * __restrict, ...)
+ __scanflike(2, 3);
FILE *tmpfile(void);
-char *tmpnam(char *);
int ungetc(int, FILE *);
-int vfprintf(FILE *, const char *, __va_list)
- __attribute__((__format__ (printf, 2, 0)))
- __attribute__((__nonnull__ (2)));
-int vprintf(const char *, __va_list)
- __attribute__((__format__ (printf, 1, 0)))
- __attribute__((__nonnull__ (1)));
-int vsprintf(char *, const char *, __va_list)
- __attribute__((__format__ (printf, 2, 0)))
- __attribute__((__nonnull__ (2)));
+int vfprintf(FILE * __restrict, const char * __restrict, __va_list)
+ __printflike(2, 0);
+int vprintf(const char * __restrict, __va_list)
+ __printflike(1, 0);
+
+#ifndef __AUDIT__
+char *gets(char *);
+int sprintf(char * __restrict, const char * __restrict, ...)
+ __printflike(2, 3);
+char *tmpnam(char *);
+int vsprintf(char * __restrict, const char * __restrict,
+ __va_list)
+ __printflike(2, 0);
+#endif
+
+int rename (const char *, const char *);
+
+int fgetpos(FILE * __restrict, fpos_t * __restrict);
+int fsetpos(FILE *, const fpos_t *);
+
+int fseeko(FILE *, off_t, int);
+off_t ftello(FILE *);
#if __ISO_C_VISIBLE >= 1999 || __BSD_VISIBLE
-int snprintf(char *, size_t, const char *, ...)
- __attribute__((__format__ (printf, 3, 4)))
- __attribute__((__nonnull__ (3)));
-int vfscanf(FILE *, const char *, __va_list)
- __attribute__((__format__ (scanf, 2, 0)))
- __attribute__((__nonnull__ (2)));
+int snprintf(char * __restrict, size_t, const char * __restrict, ...)
+ __printflike(3, 4);
+int vfscanf(FILE * __restrict, const char * __restrict, __va_list)
+ __scanflike(2, 0);
int vscanf(const char *, __va_list)
- __attribute__((__format__ (scanf, 1, 0)))
- __attribute__((__nonnull__ (1)));
-int vsnprintf(char *, size_t, const char *, __va_list)
- __attribute__((__format__ (printf, 3, 0)))
- __attribute__((__nonnull__ (3)));
-int vsscanf(const char *, const char *, __va_list)
- __attribute__((__format__ (scanf, 2, 0)))
- __attribute__((__nonnull__ (2)));
+ __scanflike(1, 0);
+int vsnprintf(char * __restrict, size_t, const char * __restrict, __va_list)
+ __printflike(3, 0);
+int vsscanf(const char * __restrict, const char * __restrict, __va_list)
+ __scanflike(2, 0);
#endif /* __ISO_C_VISIBLE >= 1999 || __BSD_VISIBLE */
__END_DECLS
@@ -335,18 +331,17 @@
*/
#if __BSD_VISIBLE
__BEGIN_DECLS
-int asprintf(char **, const char *, ...)
- __attribute__((__format__ (printf, 2, 3)))
- __attribute__((__nonnull__ (2)));
-char *fgetln(FILE *, size_t *);
+int asprintf(char ** __restrict, const char * __restrict, ...)
+ __printflike(2, 3);
+char *fgetln(FILE * __restrict, size_t * __restrict);
int fpurge(FILE *);
int getw(FILE *);
int putw(int, FILE *);
void setbuffer(FILE *, char *, int);
int setlinebuf(FILE *);
-int vasprintf(char **, const char *, __va_list)
- __attribute__((__format__ (printf, 2, 0)))
- __attribute__((__nonnull__ (2)));
+int vasprintf(char ** __restrict, const char * __restrict,
+ __va_list)
+ __printflike(2, 0);
__END_DECLS
/*
@@ -449,11 +444,9 @@
*/
__BEGIN_DECLS
int fdprintf(int, const char*, ...)
- __attribute__((__format__ (printf, 2, 3)))
- __attribute__((__nonnull__ (2)));
+ __printflike(2, 3);
int vfdprintf(int, const char*, __va_list)
- __attribute__((__format__ (printf, 2, 0)))
- __attribute__((__nonnull__ (2)));
+ __printflike(2, 0);
__END_DECLS
#endif /* _GNU_SOURCE */
@@ -462,39 +455,33 @@
__BEGIN_DECLS
__BIONIC_FORTIFY_INLINE
-__attribute__((__format__ (printf, 3, 0)))
-__attribute__((__nonnull__ (3)))
+__printflike(3, 0)
int vsnprintf(char *dest, size_t size, const char *format, __va_list ap)
{
- return __builtin___vsnprintf_chk(dest, size, 0,
- __builtin_object_size(dest, 0), format, ap);
+ return __builtin___vsnprintf_chk(dest, size, 0, __bos(dest), format, ap);
}
__BIONIC_FORTIFY_INLINE
-__attribute__((__format__ (printf, 2, 0)))
-__attribute__((__nonnull__ (2)))
+__printflike(2, 0)
int vsprintf(char *dest, const char *format, __va_list ap)
{
- return __builtin___vsprintf_chk(dest, 0,
- __builtin_object_size(dest, 0), format, ap);
+ return __builtin___vsprintf_chk(dest, 0, __bos(dest), format, ap);
}
__BIONIC_FORTIFY_INLINE
-__attribute__((__format__ (printf, 3, 4)))
-__attribute__((__nonnull__ (3)))
+__printflike(3, 4)
int snprintf(char *str, size_t size, const char *format, ...)
{
return __builtin___snprintf_chk(str, size, 0,
- __builtin_object_size(str, 0), format, __builtin_va_arg_pack());
+ __bos(str), format, __builtin_va_arg_pack());
}
__BIONIC_FORTIFY_INLINE
-__attribute__((__format__ (printf, 2, 3)))
-__attribute__((__nonnull__ (2)))
+__printflike(2, 3)
int sprintf(char *dest, const char *format, ...)
{
return __builtin___sprintf_chk(dest, 0,
- __builtin_object_size(dest, 0), format, __builtin_va_arg_pack());
+ __bos(dest), format, __builtin_va_arg_pack());
}
extern char *__fgets_real(char *, int, FILE *)
@@ -508,7 +495,7 @@
__BIONIC_FORTIFY_INLINE
char *fgets(char *dest, int size, FILE *stream)
{
- size_t bos = __builtin_object_size(dest, 0);
+ size_t bos = __bos(dest);
// Compiler can prove, at compile time, that the passed in size
// is always negative. Force a compiler error.
diff --git a/libc/include/string.h b/libc/include/string.h
index 56d89a4..f8c573c 100644
--- a/libc/include/string.h
+++ b/libc/include/string.h
@@ -34,11 +34,11 @@
__BEGIN_DECLS
-extern void* memccpy(void *, const void *, int, size_t);
+extern void* memccpy(void* __restrict, const void* __restrict, int, size_t);
extern void* memchr(const void *, int, size_t) __purefunc;
extern void* memrchr(const void *, int, size_t) __purefunc;
extern int memcmp(const void *, const void *, size_t) __purefunc;
-extern void* memcpy(void *, const void *, size_t);
+extern void* memcpy(void* __restrict, const void* __restrict, size_t);
extern void* memmove(void *, const void *, size_t);
extern void* memset(void *, int, size_t);
extern void* memmem(const void *, size_t, const void *, size_t) __purefunc;
@@ -50,8 +50,8 @@
extern size_t strlen(const char *) __purefunc;
extern int strcmp(const char *, const char *) __purefunc;
-extern char* strcpy(char *, const char *);
-extern char* strcat(char *, const char *);
+extern char* strcpy(char* __restrict, const char* __restrict);
+extern char* strcat(char* __restrict, const char* __restrict);
extern int strcasecmp(const char *, const char *) __purefunc;
extern int strncasecmp(const char *, const char *, size_t) __purefunc;
@@ -59,30 +59,30 @@
extern char* strstr(const char *, const char *) __purefunc;
extern char* strcasestr(const char *haystack, const char *needle) __purefunc;
-extern char* strtok(char *, const char *);
-extern char* strtok_r(char *, const char *, char**);
+extern char* strtok(char* __restrict, const char* __restrict);
+extern char* strtok_r(char* __restrict, const char* __restrict, char** __restrict);
extern char* strerror(int);
extern int strerror_r(int errnum, char *buf, size_t n);
extern size_t strnlen(const char *, size_t) __purefunc;
-extern char* strncat(char *, const char *, size_t);
+extern char* strncat(char* __restrict, const char* __restrict, size_t);
extern char* strndup(const char *, size_t);
extern int strncmp(const char *, const char *, size_t) __purefunc;
-extern char* strncpy(char *, const char *, size_t);
+extern char* strncpy(char* __restrict, const char* __restrict, size_t);
-extern size_t strlcat(char *, const char *, size_t);
-extern size_t strlcpy(char *, const char *, size_t);
+extern size_t strlcat(char* __restrict, const char* __restrict, size_t);
+extern size_t strlcpy(char* __restrict, const char* __restrict, size_t);
extern size_t strcspn(const char *, const char *) __purefunc;
extern char* strpbrk(const char *, const char *) __purefunc;
-extern char* strsep(char **, const char *);
+extern char* strsep(char** __restrict, const char* __restrict);
extern size_t strspn(const char *, const char *);
extern char* strsignal(int sig);
extern int strcoll(const char *, const char *) __purefunc;
-extern size_t strxfrm(char *, const char *, size_t);
+extern size_t strxfrm(char* __restrict, const char* __restrict, size_t);
#if defined(__BIONIC_FORTIFY)
@@ -92,7 +92,7 @@
__attribute__((__error__("memcpy called with size bigger than source")));
__BIONIC_FORTIFY_INLINE
-void *memcpy (void *dest, const void *src, size_t copy_amount) {
+void *memcpy (void* __restrict dest, const void* __restrict src, size_t copy_amount) {
char *d = (char *) dest;
const char *s = (const char *) src;
size_t s_len = __builtin_object_size(s, 0);
@@ -115,23 +115,30 @@
}
__BIONIC_FORTIFY_INLINE
-char *strcpy(char *dest, const char *src) {
- return __builtin___strcpy_chk(dest, src, __builtin_object_size (dest, 0));
+char *strcpy(char* __restrict dest, const char* __restrict src) {
+ return __builtin___strcpy_chk(dest, src, __bos(dest));
+}
+
+extern void __strncpy_error()
+ __attribute__((__error__("strncpy called with size bigger than buffer")));
+
+__BIONIC_FORTIFY_INLINE
+char *strncpy(char* __restrict dest, const char* __restrict src, size_t n) {
+ size_t bos = __bos(dest);
+ if (__builtin_constant_p(n) && (n > bos)) {
+ __strncpy_error();
+ }
+ return __builtin___strncpy_chk(dest, src, n, bos);
}
__BIONIC_FORTIFY_INLINE
-char *strncpy(char *dest, const char *src, size_t n) {
- return __builtin___strncpy_chk(dest, src, n, __builtin_object_size (dest, 0));
+char *strcat(char* __restrict dest, const char* __restrict src) {
+ return __builtin___strcat_chk(dest, src, __bos(dest));
}
__BIONIC_FORTIFY_INLINE
-char *strcat(char *dest, const char *src) {
- return __builtin___strcat_chk(dest, src, __builtin_object_size (dest, 0));
-}
-
-__BIONIC_FORTIFY_INLINE
-char *strncat(char *dest, const char *src, size_t n) {
- return __builtin___strncat_chk(dest, src, n, __builtin_object_size (dest, 0));
+char *strncat(char* __restrict dest, const char* __restrict src, size_t n) {
+ return __builtin___strncat_chk(dest, src, n, __bos(dest));
}
__BIONIC_FORTIFY_INLINE
@@ -139,15 +146,15 @@
return __builtin___memset_chk(s, c, n, __builtin_object_size (s, 0));
}
-extern size_t __strlcpy_real(char *, const char *, size_t)
+extern size_t __strlcpy_real(char* __restrict, const char* __restrict, size_t)
__asm__(__USER_LABEL_PREFIX__ "strlcpy");
extern void __strlcpy_error()
__attribute__((__error__("strlcpy called with size bigger than buffer")));
extern size_t __strlcpy_chk(char *, const char *, size_t, size_t);
__BIONIC_FORTIFY_INLINE
-size_t strlcpy(char *dest, const char *src, size_t size) {
- size_t bos = __builtin_object_size(dest, 0);
+size_t strlcpy(char* __restrict dest, const char* __restrict src, size_t size) {
+ size_t bos = __bos(dest);
// Compiler doesn't know destination size. Don't call __strlcpy_chk
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
@@ -169,16 +176,16 @@
return __strlcpy_chk(dest, src, size, bos);
}
-extern size_t __strlcat_real(char *, const char *, size_t)
+extern size_t __strlcat_real(char* __restrict, const char* __restrict, size_t)
__asm__(__USER_LABEL_PREFIX__ "strlcat");
extern void __strlcat_error()
__attribute__((__error__("strlcat called with size bigger than buffer")));
-extern size_t __strlcat_chk(char *, const char *, size_t, size_t);
+extern size_t __strlcat_chk(char* __restrict, const char* __restrict, size_t, size_t);
__BIONIC_FORTIFY_INLINE
-size_t strlcat(char *dest, const char *src, size_t size) {
- size_t bos = __builtin_object_size(dest, 0);
+size_t strlcat(char* __restrict dest, const char* __restrict src, size_t size) {
+ size_t bos = __bos(dest);
// Compiler doesn't know destination size. Don't call __strlcat_chk
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
@@ -204,7 +211,7 @@
__BIONIC_FORTIFY_INLINE
size_t strlen(const char *s) {
- size_t bos = __builtin_object_size(s, 0);
+ size_t bos = __bos(s);
// Compiler doesn't know destination size. Don't call __strlen_chk
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
@@ -223,7 +230,7 @@
__BIONIC_FORTIFY_INLINE
char* strchr(const char *s, int c) {
- size_t bos = __builtin_object_size(s, 0);
+ size_t bos = __bos(s);
// Compiler doesn't know destination size. Don't call __strchr_chk
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
@@ -242,7 +249,7 @@
__BIONIC_FORTIFY_INLINE
char* strrchr(const char *s, int c) {
- size_t bos = __builtin_object_size(s, 0);
+ size_t bos = __bos(s);
// Compiler doesn't know destination size. Don't call __strrchr_chk
if (bos == __BIONIC_FORTIFY_UNKNOWN_SIZE) {
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 1976d6a..c710356 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -211,6 +211,9 @@
#define __statement(x) (x)
#endif
+#define __printflike(x, y) __attribute__((__format__(printf, x, y))) __attribute__((__nonnull__(x)))
+#define __scanflike(x, y) __attribute__((__format__(scanf, x, y))) __attribute__((__nonnull__(x)))
+
/*
* C99 defines the restrict type qualifier keyword, which was made available
* in GCC 2.92.
@@ -517,6 +520,12 @@
#if defined(_FORTIFY_SOURCE) && _FORTIFY_SOURCE > 0 && defined(__OPTIMIZE__) && __OPTIMIZE__ > 0 && !defined(__clang__)
#define __BIONIC_FORTIFY 1
+#if _FORTIFY_SOURCE == 2
+#define __bos(s) __builtin_object_size((s), 1)
+#else
+#define __bos(s) __builtin_object_size((s), 0)
+#endif
+
#define __BIONIC_FORTIFY_INLINE \
extern inline \
__attribute__ ((always_inline)) \
diff --git a/libc/include/sys/epoll.h b/libc/include/sys/epoll.h
index decdb46..38739aa 100644
--- a/libc/include/sys/epoll.h
+++ b/libc/include/sys/epoll.h
@@ -42,6 +42,9 @@
#define EPOLLWRNORM 0x00000100
#define EPOLLWRBAND 0x00000200
#define EPOLLMSG 0x00000400
+#define EPOLLRDHUP 0x00002000
+#define EPOLLWAKEUP 0x20000000
+#define EPOLLONESHOT 0x40000000
#define EPOLLET 0x80000000
#define EPOLL_CTL_ADD 1
diff --git a/libc/bionic/sched_getaffinity.c b/libc/include/sys/timerfd.h
similarity index 74%
copy from libc/bionic/sched_getaffinity.c
copy to libc/include/sys/timerfd.h
index 7313822..0651f1c 100644
--- a/libc/bionic/sched_getaffinity.c
+++ b/libc/include/sys/timerfd.h
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 The Android Open Source Project
+ * Copyright (C) 2013 The Android Open Source Project
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@@ -25,17 +25,21 @@
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*/
-#define _GNU_SOURCE 1
-#include <sched.h>
-int sched_getaffinity(pid_t pid, size_t setsize, cpu_set_t* set)
-{
- int ret = __sched_getaffinity(pid, setsize, set);
- if (ret >= 0) {
- if ((size_t)ret < setsize) {
- memset((char*)set + ret, '\0', setsize - (size_t)ret);
- }
- ret = 0;
- }
- return ret;
-}
+#ifndef _SYS_TIMERFD_H_
+#define _SYS_TIMERFD_H_
+
+#include <time.h>
+#include <sys/types.h>
+#include <linux/timerfd.h>
+
+__BEGIN_DECLS
+
+extern int timerfd_create(clockid_t, int);
+extern int timerfd_settime(int, int, const struct itimerspec*,
+ struct itimerspec*);
+extern int timerfd_gettime(int, struct itimerspec*);
+
+__END_DECLS
+
+#endif /* _SYS_TIMERFD_H */
diff --git a/libc/include/time.h b/libc/include/time.h
index e280e0a..8995585 100644
--- a/libc/include/time.h
+++ b/libc/include/time.h
@@ -101,9 +101,12 @@
#define CLOCK_MONOTONIC 1
#define CLOCK_PROCESS_CPUTIME_ID 2
#define CLOCK_THREAD_CPUTIME_ID 3
-#define CLOCK_REALTIME_HR 4
-#define CLOCK_MONOTONIC_HR 5
+#define CLOCK_MONOTONIC_RAW 4
+#define CLOCK_REALTIME_COARSE 5
+#define CLOCK_MONOTONIC_COARSE 6
#define CLOCK_BOOTTIME 7
+#define CLOCK_REALTIME_ALARM 8
+#define CLOCK_BOOTTIME_ALARM 9
extern int timer_create(int, struct sigevent*, timer_t*);
extern int timer_delete(timer_t);
diff --git a/libc/kernel/common/linux/netfilter_ipv4/ip_tables.h b/libc/kernel/common/linux/netfilter_ipv4/ip_tables.h
index e5e9d66..6f75416 100644
--- a/libc/kernel/common/linux/netfilter_ipv4/ip_tables.h
+++ b/libc/kernel/common/linux/netfilter_ipv4/ip_tables.h
@@ -23,7 +23,7 @@
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#include <linux/netfilter/x_tables.h>
#define IPT_FUNCTION_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
-#define IPT_TABLE_MAXNAMELEN XT_FUNCTION_MAXNAMELEN
+#define IPT_TABLE_MAXNAMELEN XT_TABLE_MAXNAMELEN
#define ipt_match xt_match
/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
#define ipt_target xt_target
diff --git a/libc/kernel/common/linux/timerfd.h b/libc/kernel/common/linux/timerfd.h
new file mode 100644
index 0000000..0165ebb
--- /dev/null
+++ b/libc/kernel/common/linux/timerfd.h
@@ -0,0 +1,31 @@
+/****************************************************************************
+ ****************************************************************************
+ ***
+ *** This header was automatically generated from a Linux kernel header
+ *** of the same name, to make information necessary for userspace to
+ *** call into the kernel available to libc. It contains only constants,
+ *** structures, and macros generated from the original header, and thus,
+ *** contains no copyrightable information.
+ ***
+ *** To edit the content of this header, modify the corresponding
+ *** source file (e.g. under external/kernel-headers/original/) then
+ *** run bionic/libc/kernel/tools/update_all.py
+ ***
+ *** Any manual change here will be lost the next time this script will
+ *** be run. You've been warned!
+ ***
+ ****************************************************************************
+ ****************************************************************************/
+#ifndef _LINUX_TIMERFD_H
+#define _LINUX_TIMERFD_H
+#include <linux/fcntl.h>
+#define TFD_TIMER_ABSTIME (1 << 0)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define TFD_TIMER_CANCEL_ON_SET (1 << 1)
+#define TFD_CLOEXEC O_CLOEXEC
+#define TFD_NONBLOCK O_NONBLOCK
+#define TFD_SHARED_FCNTL_FLAGS (TFD_CLOEXEC | TFD_NONBLOCK)
+/* WARNING: DO NOT EDIT, AUTO-GENERATED CODE - SEE TOP FOR INSTRUCTIONS */
+#define TFD_CREATE_FLAGS TFD_SHARED_FCNTL_FLAGS
+#define TFD_SETTIME_FLAGS (TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET)
+#endif
diff --git a/libc/netbsd/resolv/res_send.c b/libc/netbsd/resolv/res_send.c
index d407ac8..0bb5b6b 100644
--- a/libc/netbsd/resolv/res_send.c
+++ b/libc/netbsd/resolv/res_send.c
@@ -581,8 +581,8 @@
if (n == 0)
goto next_ns;
if (DBG) {
- __libc_format_log(ANDROID_LOG_DEBUG, "libc",
- "time=%d, %d\n",time(NULL), time(NULL)%2);
+ __libc_format_log(ANDROID_LOG_DEBUG, "libc", "time=%ld\n",
+ time(NULL));
}
if (v_circuit)
goto same_ns;
@@ -961,7 +961,7 @@
fcntl(sock, F_SETFL, origflags);
if (DBG) {
__libc_format_log(ANDROID_LOG_DEBUG, "libc",
- " %d connect_with_timeout returning %s\n", sock, res);
+ " %d connect_with_timeout returning %d\n", sock, res);
}
return res;
}
@@ -1025,7 +1025,7 @@
}
if (DBG) {
__libc_format_log(ANDROID_LOG_DEBUG, "libc",
- " %d retrying_select returning %d for %d\n",sock, n);
+ " %d retrying_select returning %d\n",sock, n);
}
return n;
diff --git a/libc/private/libc_logging.h b/libc/private/libc_logging.h
index 281bad3..c6e1765 100644
--- a/libc/private/libc_logging.h
+++ b/libc/private/libc_logging.h
@@ -79,7 +79,7 @@
//
__LIBC_HIDDEN__ __noreturn void __libc_fatal(const char* format, ...)
- __attribute__((__format__(printf, 1, 2)));
+ __printflike(1, 2);
//
// Formatting routines for the C library's internal debugging.
@@ -87,13 +87,13 @@
//
__LIBC_HIDDEN__ int __libc_format_buffer(char* buffer, size_t buffer_size, const char* format, ...)
- __attribute__((__format__(printf, 3, 4)));
+ __printflike(3, 4);
__LIBC_HIDDEN__ int __libc_format_fd(int fd, const char* format, ...)
- __attribute__((__format__(printf, 2, 3)));
+ __printflike(2, 3);
__LIBC_HIDDEN__ int __libc_format_log(int priority, const char* tag, const char* format, ...)
- __attribute__((__format__(printf, 3, 4)));
+ __printflike(3, 4);
__LIBC_HIDDEN__ int __libc_format_log_va_list(int priority, const char* tag, const char* format,
va_list ap);
diff --git a/libc/stdio/fgetpos.c b/libc/stdio/fgetpos.c
deleted file mode 100644
index e6188e5..0000000
--- a/libc/stdio/fgetpos.c
+++ /dev/null
@@ -1,43 +0,0 @@
-/* $OpenBSD: fgetpos.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
-/*-
- * Copyright (c) 1990, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * This code is derived from software contributed to Berkeley by
- * Chris Torek.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <stdio.h>
-
-/*
- * fgetpos: like ftello.
- */
-int
-fgetpos(FILE *fp, fpos_t *pos)
-{
- return((*pos = ftello(fp)) == (fpos_t)-1);
-}
diff --git a/libc/stdlib/qsort.c b/libc/stdlib/qsort.c
deleted file mode 100644
index f6fc8e1..0000000
--- a/libc/stdlib/qsort.c
+++ /dev/null
@@ -1,161 +0,0 @@
-/* $OpenBSD: qsort.c,v 1.10 2005/08/08 08:05:37 espie Exp $ */
-/*-
- * Copyright (c) 1992, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <sys/types.h>
-#include <stdlib.h>
-
-static __inline char *med3(char *, char *, char *, int (*)(const void *, const void *));
-static __inline void swapfunc(char *, char *, int, int);
-
-#define min(a, b) (a) < (b) ? a : b
-
-/*
- * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
- */
-#define swapcode(TYPE, parmi, parmj, n) { \
- long i = (n) / sizeof (TYPE); \
- TYPE *pi = (TYPE *) (parmi); \
- TYPE *pj = (TYPE *) (parmj); \
- do { \
- TYPE t = *pi; \
- *pi++ = *pj; \
- *pj++ = t; \
- } while (--i > 0); \
-}
-
-#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
- es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
-
-static __inline void
-swapfunc(char *a, char *b, int n, int swaptype)
-{
- if (swaptype <= 1)
- swapcode(long, a, b, n)
- else
- swapcode(char, a, b, n)
-}
-
-#define swap(a, b) \
- if (swaptype == 0) { \
- long t = *(long *)(a); \
- *(long *)(a) = *(long *)(b); \
- *(long *)(b) = t; \
- } else \
- swapfunc(a, b, es, swaptype)
-
-#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
-
-static __inline char *
-med3(char *a, char *b, char *c, int (*cmp)(const void *, const void *))
-{
- return cmp(a, b) < 0 ?
- (cmp(b, c) < 0 ? b : (cmp(a, c) < 0 ? c : a ))
- :(cmp(b, c) > 0 ? b : (cmp(a, c) < 0 ? a : c ));
-}
-
-void
-qsort(void *aa, size_t n, size_t es, int (*cmp)(const void *, const void *))
-{
- char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
- int d, r, swaptype, swap_cnt;
- char *a = aa;
-
-loop: SWAPINIT(a, es);
- swap_cnt = 0;
- if (n < 7) {
- for (pm = (char *)a + es; pm < (char *) a + n * es; pm += es)
- for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
- pl -= es)
- swap(pl, pl - es);
- return;
- }
- pm = (char *)a + (n / 2) * es;
- if (n > 7) {
- pl = (char *)a;
- pn = (char *)a + (n - 1) * es;
- if (n > 40) {
- d = (n / 8) * es;
- pl = med3(pl, pl + d, pl + 2 * d, cmp);
- pm = med3(pm - d, pm, pm + d, cmp);
- pn = med3(pn - 2 * d, pn - d, pn, cmp);
- }
- pm = med3(pl, pm, pn, cmp);
- }
- swap(a, pm);
- pa = pb = (char *)a + es;
-
- pc = pd = (char *)a + (n - 1) * es;
- for (;;) {
- while (pb <= pc && (r = cmp(pb, a)) <= 0) {
- if (r == 0) {
- swap_cnt = 1;
- swap(pa, pb);
- pa += es;
- }
- pb += es;
- }
- while (pb <= pc && (r = cmp(pc, a)) >= 0) {
- if (r == 0) {
- swap_cnt = 1;
- swap(pc, pd);
- pd -= es;
- }
- pc -= es;
- }
- if (pb > pc)
- break;
- swap(pb, pc);
- swap_cnt = 1;
- pb += es;
- pc -= es;
- }
- if (swap_cnt == 0) { /* Switch to insertion sort */
- for (pm = (char *) a + es; pm < (char *) a + n * es; pm += es)
- for (pl = pm; pl > (char *) a && cmp(pl - es, pl) > 0;
- pl -= es)
- swap(pl, pl - es);
- return;
- }
-
- pn = (char *)a + n * es;
- r = min(pa - (char *)a, pb - pa);
- vecswap(a, pb - r, r);
- r = min(pd - pc, pn - pd - (int)es);
- vecswap(pb, pn - r, r);
- if ((r = pb - pa) > (int)es)
- qsort(a, r / es, es, cmp);
- if ((r = pd - pc) > (int)es) {
- /* Iterate rather than recurse to save stack space */
- a = pn - r;
- n = r / es;
- goto loop;
- }
- /* qsort(pn - r, r / es, es, cmp); */
-}
diff --git a/libc/tools/zoneinfo/generate b/libc/tools/zoneinfo/update-tzdata.py
similarity index 68%
rename from libc/tools/zoneinfo/generate
rename to libc/tools/zoneinfo/update-tzdata.py
index 334ba3c..8956136 100755
--- a/libc/tools/zoneinfo/generate
+++ b/libc/tools/zoneinfo/update-tzdata.py
@@ -3,6 +3,7 @@
"""Updates the tzdata file."""
import ftplib
+import httplib
import os
import re
import subprocess
@@ -58,27 +59,57 @@
setup.close()
-def Retrieve(ftp, filename):
- ftp.retrbinary('RETR %s' % filename, open(filename, 'wb').write)
-
-
-def UpgradeTo(ftp, data_filename):
- """Downloads and repackages the given data from the given FTP server."""
-
- new_version = re.search('(tzdata.+)\\.tar\\.gz', data_filename).group(1)
-
- # Switch to a temporary directory.
+def SwitchToNewTemporaryDirectory():
tmp_dir = tempfile.mkdtemp('-tzdata')
os.chdir(tmp_dir)
print 'Created temporary directory "%s"...' % tmp_dir
+
+def FtpRetrieve(ftp, filename):
+ ftp.retrbinary('RETR %s' % filename, open(filename, 'wb').write)
+
+
+def FtpUpgrade(ftp, data_filename):
+ """Downloads and repackages the given data from the given FTP server."""
+ SwitchToNewTemporaryDirectory()
+
print 'Downloading data...'
- Retrieve(ftp, data_filename)
+ FtpRetrieve(ftp, data_filename)
print 'Downloading signature...'
signature_filename = '%s.asc' % data_filename
- Retrieve(ftp, signature_filename)
+ FtpRetrieve(ftp, signature_filename)
+ ExtractAndCompile(data_filename)
+
+
+def HttpRetrieve(http, path, output_filename):
+ http.request("GET", path)
+ f = open(output_filename, 'wb')
+ f.write(http.getresponse().read())
+ f.close()
+
+
+def HttpUpgrade(http, data_filename):
+ """Downloads and repackages the given data from the given HTTP server."""
+ SwitchToNewTemporaryDirectory()
+
+ path = "/time-zones/repository/releases/%s" % data_filename
+
+ print 'Downloading data...'
+ HttpRetrieve(http, path, data_filename)
+
+ print 'Downloading signature...'
+ signature_filename = '%s.asc' % data_filename
+ HttpRetrieve(http, "%s.asc" % path, signature_filename)
+
+ ExtractAndCompile(data_filename)
+
+
+def ExtractAndCompile(data_filename):
+ new_version = re.search('(tzdata.+)\\.tar\\.gz', data_filename).group(1)
+
+ signature_filename = '%s.asc' % data_filename
print 'Verifying signature...'
# If this fails for you, you probably need to import Paul Eggert's public key:
# gpg --recv-keys ED97E90E62AA7E34
@@ -113,14 +144,29 @@
# See http://www.iana.org/time-zones/ for more about the source of this data.
def main():
print 'Looking for new tzdata...'
- ftp = ftplib.FTP('ftp.iana.org')
- ftp.login()
- ftp.cwd('tz/releases')
+
tzdata_filenames = []
- for filename in ftp.nlst():
- if filename.startswith('tzdata20') and filename.endswith('.tar.gz'):
- tzdata_filenames.append(filename)
- tzdata_filenames.sort()
+
+ # The FTP server lets you download intermediate releases, and also lets you
+ # download the signatures for verification, so it's your best choice.
+ use_ftp = True
+
+ if use_ftp:
+ ftp = ftplib.FTP('ftp.iana.org')
+ ftp.login()
+ ftp.cwd('tz/releases')
+ for filename in ftp.nlst():
+ if filename.startswith('tzdata20') and filename.endswith('.tar.gz'):
+ tzdata_filenames.append(filename)
+ tzdata_filenames.sort()
+ else:
+ http = httplib.HTTPConnection('www.iana.org')
+ http.request("GET", "/time-zones")
+ index_lines = http.getresponse().read().split('\n')
+ for line in index_lines:
+ m = re.compile('.*href="/time-zones/repository/releases/(tzdata20\d\d\c\.tar\.gz)".*').match(line)
+ if m:
+ tzdata_filenames.append(m.group(1))
# If you're several releases behind, we'll walk you through the upgrades
# one by one.
@@ -129,7 +175,10 @@
for filename in tzdata_filenames:
if filename > current_filename:
print 'Found new tzdata: %s' % filename
- UpgradeTo(ftp, filename)
+ if use_ftp:
+ FtpUpgrade(ftp, filename)
+ else:
+ HttpUpgrade(http, filename)
sys.exit(0)
print 'You already have the latest tzdata (%s)!' % current_version
diff --git a/libc/tzcode/localtime.c b/libc/tzcode/localtime.c
index 8a54e81..0c4d268 100644
--- a/libc/tzcode/localtime.c
+++ b/libc/tzcode/localtime.c
@@ -2276,14 +2276,18 @@
int32_t data_offset;
int32_t zonetab_offset;
} header;
- if (TEMP_FAILURE_RETRY(read(fd, &header, sizeof(header))) != sizeof(header)) {
- fprintf(stderr, "%s: could not read header: %s\n", __FUNCTION__, strerror(errno));
+ memset(&header, 0, sizeof(header));
+ ssize_t bytes_read = TEMP_FAILURE_RETRY(read(fd, &header, sizeof(header)));
+ if (bytes_read != sizeof(header)) {
+ fprintf(stderr, "%s: could not read header of \"%s\": %s\n",
+ __FUNCTION__, path, (bytes_read == -1) ? strerror(errno) : "short read");
close(fd);
return -1;
}
if (strncmp(header.tzdata_version, "tzdata", 6) != 0 || header.tzdata_version[11] != 0) {
- fprintf(stderr, "%s: bad magic: %s\n", __FUNCTION__, header.tzdata_version);
+ fprintf(stderr, "%s: bad magic in \"%s\": \"%.6s\"\n",
+ __FUNCTION__, path, header.tzdata_version);
close(fd);
return -1;
}
@@ -2296,7 +2300,8 @@
#endif
if (TEMP_FAILURE_RETRY(lseek(fd, ntohl(header.index_offset), SEEK_SET)) == -1) {
- fprintf(stderr, "%s: couldn't seek to index: %s\n", __FUNCTION__, strerror(errno));
+ fprintf(stderr, "%s: couldn't seek to index in \"%s\": %s\n",
+ __FUNCTION__, path, strerror(errno));
close(fd);
return -1;
}
@@ -2330,11 +2335,14 @@
}
if (TEMP_FAILURE_RETRY(lseek(fd, specific_zone_offset, SEEK_SET)) == -1) {
- fprintf(stderr, "%s: could not seek to %ld: %s\n", __FUNCTION__, specific_zone_offset, strerror(errno));
+ fprintf(stderr, "%s: could not seek to %ld in \"%s\": %s\n",
+ __FUNCTION__, specific_zone_offset, path, strerror(errno));
close(fd);
return -1;
}
+ // TODO: check that there's TZ_MAGIC at this offset, so we can fall back to the other file if not.
+
return fd;
}
diff --git a/libc/upstream-freebsd/freebsd-compat.h b/libc/upstream-freebsd/freebsd-compat.h
index 08dec15..697ddcb 100644
--- a/libc/upstream-freebsd/freebsd-compat.h
+++ b/libc/upstream-freebsd/freebsd-compat.h
@@ -17,4 +17,12 @@
#ifndef _BIONIC_FREEBSD_COMPAT_H_included
#define _BIONIC_FREEBSD_COMPAT_H_included
+#define __USE_BSD
+
+#define _close close
+#define _fcntl fcntl
+#define _open open
+
+#define _sseek __sseek /* Needed as long as we have a mix of OpenBSD and FreeBSD stdio. */
+
#endif
diff --git a/libc/stdio/clrerr.c b/libc/upstream-freebsd/lib/libc/stdio/clrerr.c
similarity index 82%
rename from libc/stdio/clrerr.c
rename to libc/upstream-freebsd/lib/libc/stdio/clrerr.c
index cb6c4df..f161a6e 100644
--- a/libc/stdio/clrerr.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/clrerr.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: clrerr.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,9 +30,19 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)clrerr.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
#include <stdio.h>
-#include "local.h"
-#undef clearerr
+#include "un-namespace.h"
+#include "libc_private.h"
+
+#undef clearerr
+#undef clearerr_unlocked
void
clearerr(FILE *fp)
@@ -42,3 +51,10 @@
__sclearerr(fp);
FUNLOCKFILE(fp);
}
+
+void
+clearerr_unlocked(FILE *fp)
+{
+
+ __sclearerr(fp);
+}
diff --git a/libc/stdio/fclose.c b/libc/upstream-freebsd/lib/libc/stdio/fclose.c
similarity index 75%
rename from libc/stdio/fclose.c
rename to libc/upstream-freebsd/lib/libc/stdio/fclose.c
index 8c3bac4..5ed8b2c 100644
--- a/libc/stdio/fclose.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/fclose.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: fclose.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,9 +30,19 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fclose.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
+#include "un-namespace.h"
+#include <spinlock.h>
+#include "libc_private.h"
#include "local.h"
int
@@ -46,7 +55,6 @@
return (EOF);
}
FLOCKFILE(fp);
- WCIO_FREE(fp);
r = fp->_flags & __SWR ? __sflush(fp) : 0;
if (fp->_close != NULL && (*fp->_close)(fp->_cookie) < 0)
r = EOF;
@@ -56,8 +64,22 @@
FREEUB(fp);
if (HASLB(fp))
FREELB(fp);
+ fp->_file = -1;
fp->_r = fp->_w = 0; /* Mess up if reaccessed. */
+
+ /*
+ * Lock the spinlock used to protect __sglue list walk in
+ * __sfp(). The __sfp() uses fp->_flags == 0 test as an
+ * indication of the unused FILE.
+ *
+ * Taking the lock prevents possible compiler or processor
+ * reordering of the writes performed before the final _flags
+ * cleanup, making sure that we are done with the FILE before
+ * it is considered available.
+ */
+ STDIO_THREAD_LOCK();
fp->_flags = 0; /* Release this FILE for reuse. */
+ STDIO_THREAD_UNLOCK();
FUNLOCKFILE(fp);
return (r);
}
diff --git a/libc/stdio/fdopen.c b/libc/upstream-freebsd/lib/libc/stdio/fdopen.c
similarity index 74%
rename from libc/stdio/fdopen.c
rename to libc/upstream-freebsd/lib/libc/stdio/fdopen.c
index 1df609c..2e19b9f 100644
--- a/libc/stdio/fdopen.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/fdopen.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: fdopen.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,11 +30,20 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fdopen.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
#include <sys/types.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
+#include <limits.h>
+#include "un-namespace.h"
#include "local.h"
FILE *
@@ -44,11 +52,23 @@
FILE *fp;
int flags, oflags, fdflags, tmp;
+ /*
+ * File descriptors are a full int, but _file is only a short.
+ * If we get a valid file descriptor that is greater than
+ * SHRT_MAX, then the fd will get sign-extended into an
+ * invalid file descriptor. Handle this case by failing the
+ * open.
+ */
+ if (fd > SHRT_MAX) {
+ errno = EMFILE;
+ return (NULL);
+ }
+
if ((flags = __sflags(mode, &oflags)) == 0)
return (NULL);
/* Make sure the mode the user wants is a subset of the actual mode. */
- if ((fdflags = fcntl(fd, F_GETFL, 0)) < 0)
+ if ((fdflags = _fcntl(fd, F_GETFL, 0)) < 0)
return (NULL);
tmp = fdflags & O_ACCMODE;
if (tmp != O_RDWR && (tmp != (oflags & O_ACCMODE))) {
@@ -58,11 +78,17 @@
if ((fp = __sfp()) == NULL)
return (NULL);
+
+ if ((oflags & O_CLOEXEC) && _fcntl(fd, F_SETFD, FD_CLOEXEC) == -1) {
+ fp->_flags = 0;
+ return (NULL);
+ }
+
fp->_flags = flags;
/*
* If opened for appending, but underlying descriptor does not have
- * O_APPEND bit set, assert __SAPP so that __swrite() will lseek to
- * end before each write.
+ * O_APPEND bit set, assert __SAPP so that __swrite() caller
+ * will _sseek() to the end before write.
*/
if ((oflags & O_APPEND) && !(fdflags & O_APPEND))
fp->_flags |= __SAPP;
diff --git a/libc/stdio/feof.c b/libc/upstream-freebsd/lib/libc/stdio/feof.c
similarity index 82%
rename from libc/stdio/feof.c
rename to libc/upstream-freebsd/lib/libc/stdio/feof.c
index 0fa65b0..b970248 100644
--- a/libc/stdio/feof.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/feof.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: feof.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,21 +30,34 @@
* SUCH DAMAGE.
*/
-#include <stdio.h>
-#include "local.h"
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)feof.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
-/*
- * A subroutine version of the macro feof.
- */
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
#undef feof
+#undef feof_unlocked
int
feof(FILE *fp)
{
- int ret;
+ int ret;
FLOCKFILE(fp);
- ret = __sfeof(fp);
+ ret= __sfeof(fp);
FUNLOCKFILE(fp);
return (ret);
}
+
+int
+feof_unlocked(FILE *fp)
+{
+
+ return (__sfeof(fp));
+}
diff --git a/libc/stdio/ferror.c b/libc/upstream-freebsd/lib/libc/stdio/ferror.c
similarity index 81%
rename from libc/stdio/ferror.c
rename to libc/upstream-freebsd/lib/libc/stdio/ferror.c
index 0d2cf01..7e0f8f9 100644
--- a/libc/stdio/ferror.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/ferror.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: ferror.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,15 +30,34 @@
* SUCH DAMAGE.
*/
-#include <stdio.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)ferror.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
-/*
- * A subroutine version of the macro ferror.
- */
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
#undef ferror
+#undef ferror_unlocked
int
ferror(FILE *fp)
{
+ int ret;
+
+ FLOCKFILE(fp);
+ ret = __sferror(fp);
+ FUNLOCKFILE(fp);
+ return (ret);
+}
+
+int
+ferror_unlocked(FILE *fp)
+{
+
return (__sferror(fp));
}
diff --git a/libc/stdio/fgetln.c b/libc/upstream-freebsd/lib/libc/stdio/fgetln.c
similarity index 85%
rename from libc/stdio/fgetln.c
rename to libc/upstream-freebsd/lib/libc/stdio/fgetln.c
index 0947dd8..1779de2 100644
--- a/libc/stdio/fgetln.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/fgetln.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: fgetln.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,9 +30,18 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fgetln.c 8.2 (Berkeley) 1/2/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include "un-namespace.h"
+#include "libc_private.h"
#include "local.h"
/*
@@ -43,7 +51,7 @@
* so we add 1 here.
#endif
*/
-static int
+int
__slbexpand(FILE *fp, size_t newsize)
{
void *p;
@@ -51,7 +59,7 @@
#ifdef notdef
++newsize;
#endif
- if ((size_t)fp->_lb._size >= newsize)
+ if (fp->_lb._size >= newsize)
return (0);
if ((p = realloc(fp->_lb._base, newsize)) == NULL)
return (-1);
@@ -62,7 +70,7 @@
/*
* Get an input line. The returned pointer often (but not always)
- * points into a stdio buffer. Fgetline does not alter the text of
+ * points into a stdio buffer. Fgetln does not alter the text of
* the returned line (which is thus not a C string because it will
* not necessarily end with '\0'), but does allow callers to modify
* it if they wish. Thus, we set __SMOD in case the caller does.
@@ -71,18 +79,22 @@
fgetln(FILE *fp, size_t *lenp)
{
unsigned char *p;
- char *ret;
size_t len;
size_t off;
FLOCKFILE(fp);
-
+ ORIENT(fp, -1);
/* make sure there is input */
- if (fp->_r <= 0 && __srefill(fp))
- goto error;
+ if (fp->_r <= 0 && __srefill(fp)) {
+ *lenp = 0;
+ FUNLOCKFILE(fp);
+ return (NULL);
+ }
/* look for a newline in the input */
- if ((p = memchr((void *)fp->_p, '\n', fp->_r)) != NULL) {
+ if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) != NULL) {
+ char *ret;
+
/*
* Found one. Flag buffer as modified to keep fseek from
* `optimising' a backward seek, in case the user stomps on
@@ -123,7 +135,7 @@
off = len;
if (__srefill(fp))
break; /* EOF or error: return partial line */
- if ((p = memchr((void *)fp->_p, '\n', fp->_r)) == NULL)
+ if ((p = memchr((void *)fp->_p, '\n', (size_t)fp->_r)) == NULL)
continue;
/* got it: finish up the line (like code above) */
@@ -139,12 +151,11 @@
break;
}
*lenp = len;
- ret = (char *)fp->_lb._base;
#ifdef notdef
- ret[len] = '\0';
+ fp->_lb._base[len] = 0;
#endif
FUNLOCKFILE(fp);
- return (ret);
+ return ((char *)fp->_lb._base);
error:
*lenp = 0; /* ??? */
diff --git a/libc/stdio/remove.c b/libc/upstream-freebsd/lib/libc/stdio/fgetpos.c
similarity index 82%
copy from libc/stdio/remove.c
copy to libc/upstream-freebsd/lib/libc/stdio/fgetpos.c
index d09d76f..f161f43 100644
--- a/libc/stdio/remove.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/fgetpos.c
@@ -1,5 +1,3 @@
-/* $OpenBSD: remove.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
-
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -32,18 +30,22 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fgetpos.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <stdio.h>
-#include <unistd.h>
-#include <sys/stat.h>
int
-remove(const char *file)
+fgetpos(FILE * __restrict fp, fpos_t * __restrict pos)
{
- struct stat st;
-
- if (lstat(file, &st) < 0)
+ /*
+ * ftello is thread-safe; no need to lock fp.
+ */
+ if ((*pos = ftello(fp)) == (fpos_t)-1)
return (-1);
- if (S_ISDIR(st.st_mode))
- return (rmdir(file));
- return (unlink(file));
+ else
+ return (0);
}
diff --git a/libc/stdio/fgets.c b/libc/upstream-freebsd/lib/libc/stdio/fgets.c
similarity index 86%
rename from libc/stdio/fgets.c
rename to libc/upstream-freebsd/lib/libc/stdio/fgets.c
index 311b7b2..9abf559 100644
--- a/libc/stdio/fgets.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/fgets.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: fgets.c,v 1.10 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,18 +30,26 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fgets.c 8.2 (Berkeley) 12/22/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
#include <stdio.h>
#include <string.h>
+#include "un-namespace.h"
#include "local.h"
+#include "libc_private.h"
/*
* Read at most n-1 characters from the given file.
* Stop when a newline has been read, or the count runs out.
* Return first argument, or NULL if no characters were read.
- * Do not return NULL if n == 1.
*/
char *
-fgets(char *buf, int n, FILE *fp)
+fgets(char * __restrict buf, int n, FILE * __restrict fp)
{
size_t len;
char *s;
@@ -52,24 +59,24 @@
return (NULL);
FLOCKFILE(fp);
- _SET_ORIENTATION(fp, -1);
+ ORIENT(fp, -1);
s = buf;
n--; /* leave space for NUL */
while (n != 0) {
/*
* If the buffer is empty, refill it.
*/
- if (fp->_r <= 0) {
+ if ((len = fp->_r) <= 0) {
if (__srefill(fp)) {
/* EOF/error: stop with partial or no line */
if (s == buf) {
FUNLOCKFILE(fp);
return (NULL);
- }
+ }
break;
}
+ len = fp->_r;
}
- len = fp->_r;
p = fp->_p;
/*
@@ -78,7 +85,7 @@
* newline, and stop. Otherwise, copy entire chunk
* and loop.
*/
- if ((int)len > n)
+ if (len > n)
len = n;
t = memchr((void *)p, '\n', len);
if (t != NULL) {
@@ -86,7 +93,7 @@
fp->_r -= len;
fp->_p = t;
(void)memcpy((void *)s, (void *)p, len);
- s[len] = '\0';
+ s[len] = 0;
FUNLOCKFILE(fp);
return (buf);
}
@@ -96,7 +103,7 @@
s += len;
n -= len;
}
- *s = '\0';
+ *s = 0;
FUNLOCKFILE(fp);
return (buf);
}
diff --git a/libc/stdio/fileno.c b/libc/upstream-freebsd/lib/libc/stdio/fileno.c
similarity index 81%
rename from libc/stdio/fileno.c
rename to libc/upstream-freebsd/lib/libc/stdio/fileno.c
index cbefdeb..3ac1830 100644
--- a/libc/stdio/fileno.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/fileno.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: fileno.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,21 +30,35 @@
* SUCH DAMAGE.
*/
-#include <stdio.h>
-#include "local.h"
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fileno.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
-/*
- * A subroutine version of the macro fileno.
- */
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "libc_private.h"
+
#undef fileno
+#undef fileno_unlocked
int
fileno(FILE *fp)
{
- int ret;
+ int fd;
FLOCKFILE(fp);
- ret = __sfileno(fp);
+ fd = __sfileno(fp);
FUNLOCKFILE(fp);
- return (ret);
+
+ return (fd);
+}
+
+int
+fileno_unlocked(FILE *fp)
+{
+
+ return (__sfileno(fp));
}
diff --git a/libc/stdio/flags.c b/libc/upstream-freebsd/lib/libc/stdio/flags.c
similarity index 76%
rename from libc/stdio/flags.c
rename to libc/upstream-freebsd/lib/libc/stdio/flags.c
index dde0447..1878c2f 100644
--- a/libc/stdio/flags.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/flags.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: flags.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,15 +30,22 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)flags.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/types.h>
#include <sys/file.h>
#include <stdio.h>
#include <errno.h>
-#include <fcntl.h>
+
+#include "local.h"
/*
* Return the (stdio) flags for a given mode. Store the flags
- * to be passed to an open() syscall through *optr.
+ * to be passed to an _open() syscall through *optr.
* Return 0 on error.
*/
int
@@ -72,11 +78,35 @@
return (0);
}
- /* [rwa]\+ or [rwa]b\+ means read and write */
- if (*mode == '+' || (*mode == 'b' && mode[1] == '+')) {
+ /* 'b' (binary) is ignored */
+ if (*mode == 'b')
+ mode++;
+
+ /* [rwa][b]\+ means read and write */
+ if (*mode == '+') {
+ mode++;
ret = __SRW;
m = O_RDWR;
}
+
+ /* 'b' (binary) can appear here, too -- and is ignored again */
+ if (*mode == 'b')
+ mode++;
+
+ /* 'x' means exclusive (fail if the file exists) */
+ if (*mode == 'x') {
+ mode++;
+ if (m == O_RDONLY) {
+ errno = EINVAL;
+ return (0);
+ }
+ o |= O_EXCL;
+ }
+
+ /* set close-on-exec */
+ if (*mode == 'e')
+ o |= O_CLOEXEC;
+
*optr = m | o;
return (ret);
}
diff --git a/libc/stdio/fopen.c b/libc/upstream-freebsd/lib/libc/stdio/fopen.c
similarity index 75%
rename from libc/stdio/fopen.c
rename to libc/upstream-freebsd/lib/libc/stdio/fopen.c
index 6d2d882..b08e336 100644
--- a/libc/stdio/fopen.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/fopen.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: fopen.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,18 +30,26 @@
* SUCH DAMAGE.
*/
-#define __USE_BSD
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fopen.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+#include "namespace.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
+#include <unistd.h>
#include <stdio.h>
#include <errno.h>
+#include <limits.h>
+#include "un-namespace.h"
+
#include "local.h"
-#include <linux/stat.h>
FILE *
-fopen(const char *file, const char *mode)
+fopen(const char * __restrict file, const char * __restrict mode)
{
FILE *fp;
int f;
@@ -52,10 +59,23 @@
return (NULL);
if ((fp = __sfp()) == NULL)
return (NULL);
- if ((f = open(file, oflags, DEFFILEMODE)) < 0) {
+ if ((f = _open(file, oflags, DEFFILEMODE)) < 0) {
fp->_flags = 0; /* release */
return (NULL);
}
+ /*
+ * File descriptors are a full int, but _file is only a short.
+ * If we get a valid file descriptor that is greater than
+ * SHRT_MAX, then the fd will get sign-extended into an
+ * invalid file descriptor. Handle this case by failing the
+ * open.
+ */
+ if (f > SHRT_MAX) {
+ fp->_flags = 0; /* release */
+ _close(f);
+ errno = EMFILE;
+ return (NULL);
+ }
fp->_file = f;
fp->_flags = flags;
fp->_cookie = fp;
@@ -63,7 +83,6 @@
fp->_write = __swrite;
fp->_seek = __sseek;
fp->_close = __sclose;
-
/*
* When opening in append mode, even though we use O_APPEND,
* we need to seek to the end so that ftell() gets the right
@@ -73,6 +92,6 @@
* fseek and ftell.)
*/
if (oflags & O_APPEND)
- (void) __sseek((void *)fp, (fpos_t)0, SEEK_END);
+ (void)_sseek(fp, (fpos_t)0, SEEK_END);
return (fp);
}
diff --git a/libc/stdio/fpurge.c b/libc/upstream-freebsd/lib/libc/stdio/fpurge.c
similarity index 80%
rename from libc/stdio/fpurge.c
rename to libc/upstream-freebsd/lib/libc/stdio/fpurge.c
index e04c4fe..f205bdf 100644
--- a/libc/stdio/fpurge.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/fpurge.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: fpurge.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,10 +30,19 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fpurge.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
+#include "un-namespace.h"
#include "local.h"
+#include "libc_private.h"
/*
* fpurge: like fflush, but without writing anything: leave the
@@ -43,19 +51,19 @@
int
fpurge(FILE *fp)
{
+ int retval;
FLOCKFILE(fp);
if (!fp->_flags) {
- FUNLOCKFILE(fp);
errno = EBADF;
- return(EOF);
+ retval = EOF;
+ } else {
+ if (HASUB(fp))
+ FREEUB(fp);
+ fp->_p = fp->_bf._base;
+ fp->_r = 0;
+ fp->_w = fp->_flags & (__SLBF|__SNBF|__SRD) ? 0 : fp->_bf._size;
+ retval = 0;
}
-
- if (HASUB(fp))
- FREEUB(fp);
- WCIO_FREE(fp);
- fp->_p = fp->_bf._base;
- fp->_r = 0;
- fp->_w = fp->_flags & (__SLBF|__SNBF) ? 0 : fp->_bf._size;
FUNLOCKFILE(fp);
- return (0);
+ return (retval);
}
diff --git a/libc/stdio/fputs.c b/libc/upstream-freebsd/lib/libc/stdio/fputs.c
similarity index 83%
rename from libc/stdio/fputs.c
rename to libc/upstream-freebsd/lib/libc/stdio/fputs.c
index c2462ba..3b8f2c9 100644
--- a/libc/stdio/fputs.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/fputs.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: fputs.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,28 +30,37 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fputs.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
#include <stdio.h>
#include <string.h>
-#include "local.h"
+#include "un-namespace.h"
#include "fvwrite.h"
+#include "libc_private.h"
+#include "local.h"
/*
* Write the given string to the given file.
*/
int
-fputs(const char *s, FILE *fp)
+fputs(const char * __restrict s, FILE * __restrict fp)
{
+ int retval;
struct __suio uio;
struct __siov iov;
- int ret;
iov.iov_base = (void *)s;
iov.iov_len = uio.uio_resid = strlen(s);
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
FLOCKFILE(fp);
- _SET_ORIENTATION(fp, -1);
- ret = __sfvwrite(fp, &uio);
+ ORIENT(fp, -1);
+ retval = __sfvwrite(fp, &uio);
FUNLOCKFILE(fp);
- return (ret);
+ return (retval);
}
diff --git a/libc/stdio/fsetpos.c b/libc/upstream-freebsd/lib/libc/stdio/fsetpos.c
similarity index 88%
rename from libc/stdio/fsetpos.c
rename to libc/upstream-freebsd/lib/libc/stdio/fsetpos.c
index 9624fe5..c6b8b78 100644
--- a/libc/stdio/fsetpos.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/fsetpos.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: fsetpos.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,10 +30,17 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fsetpos.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
#include <stdio.h>
/*
- * fsetpos: like fseeko.
+ * fsetpos: like fseek.
*/
int
fsetpos(FILE *iop, const fpos_t *pos)
diff --git a/libc/stdio/funopen.c b/libc/upstream-freebsd/lib/libc/stdio/funopen.c
similarity index 86%
rename from libc/stdio/funopen.c
rename to libc/upstream-freebsd/lib/libc/stdio/funopen.c
index b85ee96..983fe50 100644
--- a/libc/stdio/funopen.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/funopen.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: funopen.c,v 1.8 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,14 +30,23 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)funopen.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <stdio.h>
#include <errno.h>
+
#include "local.h"
FILE *
-funopen(const void *cookie, int (*readfn)(void *, char *, int),
+funopen(const void *cookie,
+ int (*readfn)(void *, char *, int),
int (*writefn)(void *, const char *, int),
- fpos_t (*seekfn)(void *, fpos_t, int), int (*closefn)(void *))
+ fpos_t (*seekfn)(void *, fpos_t, int),
+ int (*closefn)(void *))
{
FILE *fp;
int flags;
@@ -59,7 +67,7 @@
return (NULL);
fp->_flags = flags;
fp->_file = -1;
- fp->_cookie = (void *)cookie; /* SAFE: cookie not modified */
+ fp->_cookie = (void *)cookie;
fp->_read = readfn;
fp->_write = writefn;
fp->_seek = seekfn;
diff --git a/libc/stdio/fwalk.c b/libc/upstream-freebsd/lib/libc/stdio/fwalk.c
similarity index 78%
rename from libc/stdio/fwalk.c
rename to libc/upstream-freebsd/lib/libc/stdio/fwalk.c
index b1df891..151837b 100644
--- a/libc/stdio/fwalk.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/fwalk.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: fwalk.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,7 +30,13 @@
* SUCH DAMAGE.
*/
-#include <errno.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fwalk.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
#include <stdio.h>
#include "local.h"
#include "glue.h"
@@ -44,10 +49,17 @@
struct glue *g;
ret = 0;
+ /*
+ * It should be safe to walk the list without locking it;
+ * new nodes are only added to the end and none are ever
+ * removed.
+ *
+ * Avoid locking this list while walking it or else you will
+ * introduce a potential deadlock in [at least] refill.c.
+ */
for (g = &__sglue; g != NULL; g = g->next)
- for (fp = g->iobs, n = g->niobs; --n >= 0; fp++) {
+ for (fp = g->iobs, n = g->niobs; --n >= 0; fp++)
if ((fp->_flags != 0) && ((fp->_flags & __SIGN) == 0))
ret |= (*function)(fp);
- }
return (ret);
}
diff --git a/libc/stdio/fwrite.c b/libc/upstream-freebsd/lib/libc/stdio/fwrite.c
similarity index 67%
rename from libc/stdio/fwrite.c
rename to libc/upstream-freebsd/lib/libc/stdio/fwrite.c
index a97313e..707d362 100644
--- a/libc/stdio/fwrite.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/fwrite.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: fwrite.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,36 +30,67 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)fwrite.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
+#include <errno.h>
+#include <stdint.h>
#include <stdio.h>
+#include "un-namespace.h"
#include "local.h"
#include "fvwrite.h"
+#include "libc_private.h"
/*
* Write `count' objects (each size `size') from memory to the given file.
* Return the number of whole objects written.
*/
size_t
-fwrite(const void *buf, size_t size, size_t count, FILE *fp)
+fwrite(const void * __restrict buf, size_t size, size_t count, FILE * __restrict fp)
{
size_t n;
struct __suio uio;
struct __siov iov;
- int ret;
+
+ /*
+ * ANSI and SUSv2 require a return value of 0 if size or count are 0.
+ */
+ if ((count == 0) || (size == 0))
+ return (0);
+
+ /*
+ * Check for integer overflow. As an optimization, first check that
+ * at least one of {count, size} is at least 2^16, since if both
+ * values are less than that, their product can't possible overflow
+ * (size_t is always at least 32 bits on FreeBSD).
+ */
+ if (((count | size) > 0xFFFF) &&
+ (count > SIZE_MAX / size)) {
+ errno = EINVAL;
+ fp->_flags |= __SERR;
+ return (0);
+ }
+
+ n = count * size;
iov.iov_base = (void *)buf;
- uio.uio_resid = iov.iov_len = n = count * size;
+ uio.uio_resid = iov.iov_len = n;
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
+ FLOCKFILE(fp);
+ ORIENT(fp, -1);
/*
* The usual case is success (__sfvwrite returns 0);
* skip the divide if this happens, since divides are
* generally slow and since this occurs whenever size==0.
*/
- FLOCKFILE(fp);
- ret = __sfvwrite(fp, &uio);
+ if (__sfvwrite(fp, &uio) != 0)
+ count = (n - uio.uio_resid) / size;
FUNLOCKFILE(fp);
- if (ret == 0)
- return (count);
- return ((n - uio.uio_resid) / size);
+ return (count);
}
diff --git a/libc/stdio/getc.c b/libc/upstream-freebsd/lib/libc/stdio/getc.c
similarity index 82%
rename from libc/stdio/getc.c
rename to libc/upstream-freebsd/lib/libc/stdio/getc.c
index 16a5b1d..4963c8c 100644
--- a/libc/stdio/getc.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/getc.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: getc.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,32 +30,36 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getc.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
#include <stdio.h>
+#include "un-namespace.h"
+#include "libc_private.h"
#include "local.h"
-/*
- * A subroutine version of the macro getc_unlocked.
- */
-#undef getc_unlocked
-
-int
-getc_unlocked(FILE *fp)
-{
- return (__sgetc(fp));
-}
-
-/*
- * A subroutine version of the macro getc.
- */
#undef getc
+#undef getc_unlocked
int
getc(FILE *fp)
{
- int c;
-
+ int retval;
FLOCKFILE(fp);
- c = __sgetc(fp);
+ /* Orientation set by __sgetc() when buffer is empty. */
+ /* ORIENT(fp, -1); */
+ retval = __sgetc(fp);
FUNLOCKFILE(fp);
- return (c);
+ return (retval);
+}
+
+int
+getc_unlocked(FILE *fp)
+{
+
+ return (__sgetc(fp));
}
diff --git a/libc/stdio/getchar.c b/libc/upstream-freebsd/lib/libc/stdio/getchar.c
similarity index 78%
rename from libc/stdio/getchar.c
rename to libc/upstream-freebsd/lib/libc/stdio/getchar.c
index 550817d..21040bc 100644
--- a/libc/stdio/getchar.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/getchar.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: getchar.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,28 +30,39 @@
* SUCH DAMAGE.
*/
-#include <stdio.h>
-
-/*
- * A subroutine version of the macro getchar_unlocked.
- */
-#undef getchar_unlocked
-
-int
-getchar_unlocked(void)
-{
- return (getc_unlocked(stdin));
-}
-
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)getchar.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
/*
* A subroutine version of the macro getchar.
*/
+#include "namespace.h"
+#include <stdio.h>
+#include "un-namespace.h"
+#include "local.h"
+#include "libc_private.h"
#undef getchar
+#undef getchar_unlocked
int
-getchar(void)
+getchar()
{
- return (getc(stdin));
+ int retval;
+ FLOCKFILE(stdin);
+ /* Orientation set by __sgetc() when buffer is empty. */
+ /* ORIENT(stdin, -1); */
+ retval = __sgetc(stdin);
+ FUNLOCKFILE(stdin);
+ return (retval);
+}
+
+int
+getchar_unlocked(void)
+{
+
+ return (__sgetc(stdin));
}
diff --git a/libc/stdio/putc.c b/libc/upstream-freebsd/lib/libc/stdio/putc.c
similarity index 79%
rename from libc/stdio/putc.c
rename to libc/upstream-freebsd/lib/libc/stdio/putc.c
index 2b05504..aaffece 100644
--- a/libc/stdio/putc.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/putc.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: putc.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,37 +30,36 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)putc.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
#include <stdio.h>
-#include <errno.h>
+#include "un-namespace.h"
#include "local.h"
+#include "libc_private.h"
-/*
- * A subroutine version of the macro putc_unlocked.
- */
-#undef putc_unlocked
-
-int
-putc_unlocked(int c, FILE *fp)
-{
- if (cantwrite(fp)) {
- errno = EBADF;
- return (EOF);
- }
- return (__sputc(c, fp));
-}
-
-/*
- * A subroutine version of the macro putc.
- */
#undef putc
+#undef putc_unlocked
int
putc(int c, FILE *fp)
{
- int ret;
-
+ int retval;
FLOCKFILE(fp);
- ret = putc_unlocked(c, fp);
+ /* Orientation set by __sputc() when buffer is full. */
+ /* ORIENT(fp, -1); */
+ retval = __sputc(c, fp);
FUNLOCKFILE(fp);
- return (ret);
+ return (retval);
+}
+
+int
+putc_unlocked(int ch, FILE *fp)
+{
+
+ return (__sputc(ch, fp));
}
diff --git a/libc/stdio/putchar.c b/libc/upstream-freebsd/lib/libc/stdio/putchar.c
similarity index 78%
rename from libc/stdio/putchar.c
rename to libc/upstream-freebsd/lib/libc/stdio/putchar.c
index eeed0a2..7561559 100644
--- a/libc/stdio/putchar.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/putchar.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: putchar.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,21 +30,20 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)putchar.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
#include <stdio.h>
-
-#undef putchar_unlocked
-/*
- * A subrouting version of the macro putchar_unlocked
- */
-int
-putchar_unlocked(int c)
-{
- FILE *so = stdout;
-
- return (putc_unlocked(c, so));
-}
+#include "un-namespace.h"
+#include "local.h"
+#include "libc_private.h"
#undef putchar
+#undef putchar_unlocked
/*
* A subroutine version of the macro putchar
@@ -53,7 +51,20 @@
int
putchar(int c)
{
+ int retval;
FILE *so = stdout;
- return (putc(c, so));
+ FLOCKFILE(so);
+ /* Orientation set by __sputc() when buffer is full. */
+ /* ORIENT(so, -1); */
+ retval = __sputc(c, so);
+ FUNLOCKFILE(so);
+ return (retval);
+}
+
+int
+putchar_unlocked(int ch)
+{
+
+ return (__sputc(ch, stdout));
}
diff --git a/libc/stdio/puts.c b/libc/upstream-freebsd/lib/libc/stdio/puts.c
similarity index 84%
rename from libc/stdio/puts.c
rename to libc/upstream-freebsd/lib/libc/stdio/puts.c
index 4603a3d..5ee7fc1 100644
--- a/libc/stdio/puts.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/puts.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: puts.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,21 +30,30 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)puts.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
#include <stdio.h>
#include <string.h>
-#include "local.h"
+#include "un-namespace.h"
#include "fvwrite.h"
+#include "libc_private.h"
+#include "local.h"
/*
* Write the given string to stdout, appending a newline.
*/
int
-puts(const char *s)
+puts(char const *s)
{
+ int retval;
size_t c = strlen(s);
struct __suio uio;
struct __siov iov[2];
- int ret;
iov[0].iov_base = (void *)s;
iov[0].iov_len = c;
@@ -55,7 +63,8 @@
uio.uio_iov = &iov[0];
uio.uio_iovcnt = 2;
FLOCKFILE(stdout);
- ret = __sfvwrite(stdout, &uio);
+ ORIENT(stdout, -1);
+ retval = __sfvwrite(stdout, &uio) ? EOF : '\n';
FUNLOCKFILE(stdout);
- return (ret ? EOF : '\n');
+ return (retval);
}
diff --git a/libc/stdio/putw.c b/libc/upstream-freebsd/lib/libc/stdio/putw.c
similarity index 83%
rename from libc/stdio/putw.c
rename to libc/upstream-freebsd/lib/libc/stdio/putw.c
index 12955fe..0360caf 100644
--- a/libc/stdio/putw.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/putw.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: putw.c,v 1.6 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,12 +30,22 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)putw.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include "namespace.h"
#include <stdio.h>
+#include "un-namespace.h"
#include "fvwrite.h"
+#include "libc_private.h"
int
putw(int w, FILE *fp)
{
+ int retval;
struct __suio uio;
struct __siov iov;
@@ -44,5 +53,8 @@
iov.iov_len = uio.uio_resid = sizeof(w);
uio.uio_iov = &iov;
uio.uio_iovcnt = 1;
- return (__sfvwrite(fp, &uio));
+ FLOCKFILE(fp);
+ retval = __sfvwrite(fp, &uio);
+ FUNLOCKFILE(fp);
+ return (retval);
}
diff --git a/libc/stdio/remove.c b/libc/upstream-freebsd/lib/libc/stdio/remove.c
similarity index 86%
rename from libc/stdio/remove.c
rename to libc/upstream-freebsd/lib/libc/stdio/remove.c
index d09d76f..2e984ba 100644
--- a/libc/stdio/remove.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/remove.c
@@ -1,5 +1,3 @@
-/* $OpenBSD: remove.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
-
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -32,18 +30,25 @@
* SUCH DAMAGE.
*/
-#include <stdio.h>
-#include <unistd.h>
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)remove.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
#include <sys/stat.h>
+#include <unistd.h>
+#include <stdio.h>
int
remove(const char *file)
{
- struct stat st;
+ struct stat sb;
- if (lstat(file, &st) < 0)
+ if (lstat(file, &sb) < 0)
return (-1);
- if (S_ISDIR(st.st_mode))
+ if (S_ISDIR(sb.st_mode))
return (rmdir(file));
return (unlink(file));
}
diff --git a/libc/stdio/rget.c b/libc/upstream-freebsd/lib/libc/stdio/rget.c
similarity index 91%
rename from libc/stdio/rget.c
rename to libc/upstream-freebsd/lib/libc/stdio/rget.c
index 4cd97cb..bdc0311 100644
--- a/libc/stdio/rget.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/rget.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: rget.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,6 +30,12 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)rget.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <stdio.h>
#include "local.h"
@@ -42,7 +47,6 @@
int
__srget(FILE *fp)
{
- _SET_ORIENTATION(fp, -1);
if (__srefill(fp) == 0) {
fp->_r--;
return (*fp->_p++);
diff --git a/libc/stdio/setbuf.c b/libc/upstream-freebsd/lib/libc/stdio/setbuf.c
similarity index 87%
rename from libc/stdio/setbuf.c
rename to libc/upstream-freebsd/lib/libc/stdio/setbuf.c
index 883b895..5c65f97 100644
--- a/libc/stdio/setbuf.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/setbuf.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: setbuf.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,11 +30,17 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setbuf.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <stdio.h>
#include "local.h"
void
-setbuf(FILE *fp, char *buf)
+setbuf(FILE * __restrict fp, char * __restrict buf)
{
(void) setvbuf(fp, buf, buf ? _IOFBF : _IONBF, BUFSIZ);
}
diff --git a/libc/stdio/setbuffer.c b/libc/upstream-freebsd/lib/libc/stdio/setbuffer.c
similarity index 87%
rename from libc/stdio/setbuffer.c
rename to libc/upstream-freebsd/lib/libc/stdio/setbuffer.c
index 8725ff7..af5eb3c 100644
--- a/libc/stdio/setbuffer.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/setbuffer.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: setbuffer.c,v 1.5 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,13 +30,19 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)setbuffer.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <stdio.h>
void
setbuffer(FILE *fp, char *buf, int size)
{
- (void)setvbuf(fp, buf, buf ? _IOFBF : _IONBF, size);
+ (void)setvbuf(fp, buf, buf ? _IOFBF : _IONBF, (size_t)size);
}
/*
diff --git a/libc/stdio/tempnam.c b/libc/upstream-freebsd/lib/libc/stdio/tempnam.c
similarity index 85%
rename from libc/stdio/tempnam.c
rename to libc/upstream-freebsd/lib/libc/stdio/tempnam.c
index 3b7ec75..e15746f 100644
--- a/libc/stdio/tempnam.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/tempnam.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: tempnam.c,v 1.14 2005/08/08 08:05:36 espie Exp $ */
/*
* Copyright (c) 1988, 1993
* The Regents of the University of California. All rights reserved.
@@ -28,6 +27,12 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tempnam.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/param.h>
#include <errno.h>
#include <stdio.h>
@@ -54,26 +59,26 @@
pfx = "tmp.";
if (issetugid() == 0 && (f = getenv("TMPDIR"))) {
- (void)snprintf(name, MAXPATHLEN, "%s%s%sXXXXXXXXXX", f,
+ (void)snprintf(name, MAXPATHLEN, "%s%s%sXXXXXX", f,
*(f + strlen(f) - 1) == '/'? "": "/", pfx);
if ((f = _mktemp(name)))
return(f);
}
if ((f = (char *)dir)) {
- (void)snprintf(name, MAXPATHLEN, "%s%s%sXXXXXXXXXX", f,
+ (void)snprintf(name, MAXPATHLEN, "%s%s%sXXXXXX", f,
*(f + strlen(f) - 1) == '/'? "": "/", pfx);
if ((f = _mktemp(name)))
return(f);
}
f = P_tmpdir;
- (void)snprintf(name, MAXPATHLEN, "%s%sXXXXXXXXX", f, pfx);
+ (void)snprintf(name, MAXPATHLEN, "%s%sXXXXXX", f, pfx);
if ((f = _mktemp(name)))
return(f);
f = _PATH_TMP;
- (void)snprintf(name, MAXPATHLEN, "%s%sXXXXXXXXX", f, pfx);
+ (void)snprintf(name, MAXPATHLEN, "%s%sXXXXXX", f, pfx);
if ((f = _mktemp(name)))
return(f);
diff --git a/libc/stdio/tmpnam.c b/libc/upstream-freebsd/lib/libc/stdio/tmpnam.c
similarity index 88%
rename from libc/stdio/tmpnam.c
rename to libc/upstream-freebsd/lib/libc/stdio/tmpnam.c
index 32e0a22..ce32dcc 100644
--- a/libc/stdio/tmpnam.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/tmpnam.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: tmpnam.c,v 1.10 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993, 1994
* The Regents of the University of California. All rights reserved.
@@ -31,6 +30,12 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)tmpnam.c 8.3 (Berkeley) 3/28/94";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
#include <sys/types.h>
#include <stdio.h>
@@ -49,7 +54,7 @@
if (s == NULL)
s = buf;
- (void)snprintf(s, L_tmpnam, "%stmp.%lu.XXXXXXXXX", P_tmpdir, tmpcount);
+ (void)snprintf(s, L_tmpnam, "%stmp.%lu.XXXXXX", P_tmpdir, tmpcount);
++tmpcount;
return (_mktemp(s));
}
diff --git a/libc/stdio/wsetup.c b/libc/upstream-freebsd/lib/libc/stdio/wsetup.c
similarity index 86%
rename from libc/stdio/wsetup.c
rename to libc/upstream-freebsd/lib/libc/stdio/wsetup.c
index 0834223..70f8247 100644
--- a/libc/stdio/wsetup.c
+++ b/libc/upstream-freebsd/lib/libc/stdio/wsetup.c
@@ -1,4 +1,3 @@
-/* $OpenBSD: wsetup.c,v 1.7 2005/08/08 08:05:36 espie Exp $ */
/*-
* Copyright (c) 1990, 1993
* The Regents of the University of California. All rights reserved.
@@ -31,6 +30,13 @@
* SUCH DAMAGE.
*/
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)wsetup.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include "local.h"
@@ -38,7 +44,7 @@
/*
* Various output routines call wsetup to be sure it is safe to write,
* because either _flags does not include __SWR, or _buf is NULL.
- * _wsetup returns 0 if OK to write, nonzero otherwise.
+ * _wsetup returns 0 if OK to write; otherwise, it returns EOF and sets errno.
*/
int
__swsetup(FILE *fp)
@@ -51,8 +57,11 @@
* If we are not writing, we had better be reading and writing.
*/
if ((fp->_flags & __SWR) == 0) {
- if ((fp->_flags & __SRW) == 0)
+ if ((fp->_flags & __SRW) == 0) {
+ errno = EBADF;
+ fp->_flags |= __SERR;
return (EOF);
+ }
if (fp->_flags & __SRD) {
/* clobber any ungetc data */
if (HASUB(fp))
@@ -67,11 +76,8 @@
/*
* Make a buffer if necessary, then set _w.
*/
- if (fp->_bf._base == NULL) {
- if ((fp->_flags & (__SSTR | __SALC)) == __SSTR)
- return (EOF);
+ if (fp->_bf._base == NULL)
__smakebuf(fp);
- }
if (fp->_flags & __SLBF) {
/*
* It is line buffered, so make _lbfsize be -_bufsize
diff --git a/libc/upstream-freebsd/lib/libc/stdlib/qsort.c b/libc/upstream-freebsd/lib/libc/stdlib/qsort.c
new file mode 100644
index 0000000..3687b05
--- /dev/null
+++ b/libc/upstream-freebsd/lib/libc/stdlib/qsort.c
@@ -0,0 +1,195 @@
+/*-
+ * Copyright (c) 1992, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char sccsid[] = "@(#)qsort.c 8.1 (Berkeley) 6/4/93";
+#endif /* LIBC_SCCS and not lint */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <stdlib.h>
+
+#ifdef I_AM_QSORT_R
+typedef int cmp_t(void *, const void *, const void *);
+#else
+typedef int cmp_t(const void *, const void *);
+#endif
+static inline char *med3(char *, char *, char *, cmp_t *, void *);
+static inline void swapfunc(char *, char *, int, int);
+
+#define min(a, b) (a) < (b) ? a : b
+
+/*
+ * Qsort routine from Bentley & McIlroy's "Engineering a Sort Function".
+ */
+#define swapcode(TYPE, parmi, parmj, n) { \
+ long i = (n) / sizeof (TYPE); \
+ TYPE *pi = (TYPE *) (parmi); \
+ TYPE *pj = (TYPE *) (parmj); \
+ do { \
+ TYPE t = *pi; \
+ *pi++ = *pj; \
+ *pj++ = t; \
+ } while (--i > 0); \
+}
+
+#define SWAPINIT(a, es) swaptype = ((char *)a - (char *)0) % sizeof(long) || \
+ es % sizeof(long) ? 2 : es == sizeof(long)? 0 : 1;
+
+static inline void
+swapfunc(a, b, n, swaptype)
+ char *a, *b;
+ int n, swaptype;
+{
+ if(swaptype <= 1)
+ swapcode(long, a, b, n)
+ else
+ swapcode(char, a, b, n)
+}
+
+#define swap(a, b) \
+ if (swaptype == 0) { \
+ long t = *(long *)(a); \
+ *(long *)(a) = *(long *)(b); \
+ *(long *)(b) = t; \
+ } else \
+ swapfunc(a, b, es, swaptype)
+
+#define vecswap(a, b, n) if ((n) > 0) swapfunc(a, b, n, swaptype)
+
+#ifdef I_AM_QSORT_R
+#define CMP(t, x, y) (cmp((t), (x), (y)))
+#else
+#define CMP(t, x, y) (cmp((x), (y)))
+#endif
+
+static inline char *
+med3(char *a, char *b, char *c, cmp_t *cmp, void *thunk
+#ifndef I_AM_QSORT_R
+__unused
+#endif
+)
+{
+ return CMP(thunk, a, b) < 0 ?
+ (CMP(thunk, b, c) < 0 ? b : (CMP(thunk, a, c) < 0 ? c : a ))
+ :(CMP(thunk, b, c) > 0 ? b : (CMP(thunk, a, c) < 0 ? a : c ));
+}
+
+#ifdef I_AM_QSORT_R
+void
+qsort_r(void *a, size_t n, size_t es, void *thunk, cmp_t *cmp)
+#else
+#define thunk NULL
+void
+qsort(void *a, size_t n, size_t es, cmp_t *cmp)
+#endif
+{
+ char *pa, *pb, *pc, *pd, *pl, *pm, *pn;
+ size_t d, r;
+ int cmp_result;
+ int swaptype, swap_cnt;
+
+loop: SWAPINIT(a, es);
+ swap_cnt = 0;
+ if (n < 7) {
+ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+ for (pl = pm;
+ pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+ pm = (char *)a + (n / 2) * es;
+ if (n > 7) {
+ pl = a;
+ pn = (char *)a + (n - 1) * es;
+ if (n > 40) {
+ d = (n / 8) * es;
+ pl = med3(pl, pl + d, pl + 2 * d, cmp, thunk);
+ pm = med3(pm - d, pm, pm + d, cmp, thunk);
+ pn = med3(pn - 2 * d, pn - d, pn, cmp, thunk);
+ }
+ pm = med3(pl, pm, pn, cmp, thunk);
+ }
+ swap(a, pm);
+ pa = pb = (char *)a + es;
+
+ pc = pd = (char *)a + (n - 1) * es;
+ for (;;) {
+ while (pb <= pc && (cmp_result = CMP(thunk, pb, a)) <= 0) {
+ if (cmp_result == 0) {
+ swap_cnt = 1;
+ swap(pa, pb);
+ pa += es;
+ }
+ pb += es;
+ }
+ while (pb <= pc && (cmp_result = CMP(thunk, pc, a)) >= 0) {
+ if (cmp_result == 0) {
+ swap_cnt = 1;
+ swap(pc, pd);
+ pd -= es;
+ }
+ pc -= es;
+ }
+ if (pb > pc)
+ break;
+ swap(pb, pc);
+ swap_cnt = 1;
+ pb += es;
+ pc -= es;
+ }
+ if (swap_cnt == 0) { /* Switch to insertion sort */
+ for (pm = (char *)a + es; pm < (char *)a + n * es; pm += es)
+ for (pl = pm;
+ pl > (char *)a && CMP(thunk, pl - es, pl) > 0;
+ pl -= es)
+ swap(pl, pl - es);
+ return;
+ }
+
+ pn = (char *)a + n * es;
+ r = min(pa - (char *)a, pb - pa);
+ vecswap(a, pb - r, r);
+ r = min(pd - pc, pn - pd - es);
+ vecswap(pb, pn - r, r);
+ if ((r = pb - pa) > es)
+#ifdef I_AM_QSORT_R
+ qsort_r(a, r / es, es, thunk, cmp);
+#else
+ qsort(a, r / es, es, cmp);
+#endif
+ if ((r = pd - pc) > es) {
+ /* Iterate rather than recurse to save stack space */
+ a = pn - r;
+ n = r / es;
+ goto loop;
+ }
+/* qsort(pn - r, r / es, es, cmp);*/
+}
diff --git a/libc/upstream-freebsd/libc_private.h b/libc/upstream-freebsd/libc_private.h
new file mode 100644
index 0000000..ecdbb7e
--- /dev/null
+++ b/libc/upstream-freebsd/libc_private.h
@@ -0,0 +1,28 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef _BIONIC_FREEBSD_LIBC_PRIVATE_H_included
+#define _BIONIC_FREEBSD_LIBC_PRIVATE_H_included
+
+#define FLOCKFILE(fp) do { if (__isthreaded) flockfile(fp); } while (0)
+#define FUNLOCKFILE(fp) do { if (__isthreaded) funlockfile(fp); } while (0)
+
+#define STDIO_THREAD_LOCK() /* TODO: until we have the FreeBSD findfp.c, this is useless. */
+#define STDIO_THREAD_UNLOCK() /* TODO: until we have the FreeBSD findfp.c, this is useless. */
+
+#define ORIENT(fp, o) /* Only needed for wide-character stream support. */
+
+#endif
diff --git a/libc/upstream-freebsd/spinlock.h b/libc/upstream-freebsd/spinlock.h
new file mode 100644
index 0000000..f5c3785
--- /dev/null
+++ b/libc/upstream-freebsd/spinlock.h
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#ifndef _BIONIC_FREEBSD_SPINLOCK_H_included
+#define _BIONIC_FREEBSD_SPINLOCK_H_included
+
+/* TODO: until we have the FreeBSD findfp.c, this is useless. */
+
+#endif
diff --git a/libc/upstream-netbsd/port_before.h b/libc/upstream-netbsd/port_before.h
index 70eed26..9f77f79 100644
--- a/libc/upstream-netbsd/port_before.h
+++ b/libc/upstream-netbsd/port_before.h
@@ -21,7 +21,7 @@
#include <sys/cdefs.h>
#include <arpa_nameser.h>
-#define ISC_FORMAT_PRINTF(a,b) __attribute__((__format__(__printf__,a,b)))
+#define ISC_FORMAT_PRINTF(a,b) __printflike(a,b)
#define ISC_SOCKLEN_T socklen_t
#endif
diff --git a/linker/linker.cpp b/linker/linker.cpp
index 7c5165b..c97b712 100644
--- a/linker/linker.cpp
+++ b/linker/linker.cpp
@@ -1581,11 +1581,6 @@
return false;
}
- // If this is a setuid/setgid program, close the security hole described in
- // ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-02:23.stdio.asc
- if (get_AT_SECURE()) {
- nullify_closed_stdio();
- }
notify_gdb_of_load(si);
return true;
}
@@ -1614,6 +1609,12 @@
// Initialize environment functions, and get to the ELF aux vectors table.
linker_env_init(args);
+ // If this is a setuid/setgid program, close the security hole described in
+ // ftp://ftp.freebsd.org/pub/FreeBSD/CERT/advisories/FreeBSD-SA-02:23.stdio.asc
+ if (get_AT_SECURE()) {
+ nullify_closed_stdio();
+ }
+
debuggerd_init();
// Get a few environment variables.
diff --git a/tests/Android.mk b/tests/Android.mk
index dee5e33..45cb462 100644
--- a/tests/Android.mk
+++ b/tests/Android.mk
@@ -60,6 +60,8 @@
dirent_test.cpp \
eventfd_test.cpp \
fenv_test.cpp \
+ fortify1_test.cpp \
+ fortify2_test.cpp \
getauxval_test.cpp \
getcwd_test.cpp \
libc_logging_test.cpp \
diff --git a/tests/fortify1_test.cpp b/tests/fortify1_test.cpp
new file mode 100644
index 0000000..e237193
--- /dev/null
+++ b/tests/fortify1_test.cpp
@@ -0,0 +1,62 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#undef _FORTIFY_SOURCE
+#define _FORTIFY_SOURCE 1
+
+#include <gtest/gtest.h>
+#include <string.h>
+
+#if __BIONIC__
+// We have to say "DeathTest" here so gtest knows to run this test (which exits)
+// in its own process.
+TEST(Fortify1_DeathTest, strcpy_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ char *orig = strdup("0123456789");
+ ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGSEGV), "");
+ free(orig);
+}
+
+TEST(Fortify1_DeathTest, strlen_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ memcpy(buf, "0123456789", sizeof(buf));
+ ASSERT_EXIT(printf("%d", strlen(buf)), testing::KilledBySignal(SIGSEGV), "");
+}
+
+TEST(Fortify1_DeathTest, strchr_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ memcpy(buf, "0123456789", sizeof(buf));
+ ASSERT_EXIT(printf("%s", strchr(buf, 'a')), testing::KilledBySignal(SIGSEGV), "");
+}
+
+TEST(Fortify1_DeathTest, strrchr_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ memcpy(buf, "0123456789", sizeof(buf));
+ ASSERT_EXIT(printf("%s", strrchr(buf, 'a')), testing::KilledBySignal(SIGSEGV), "");
+}
+#endif
+
+TEST(Fortify1_DeathTest, sprintf_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ char source_buf[15];
+ memcpy(source_buf, "12345678901234", 15);
+ ASSERT_EXIT(sprintf(buf, "%s", source_buf), testing::KilledBySignal(SIGSEGV), "");
+}
diff --git a/tests/fortify2_test.cpp b/tests/fortify2_test.cpp
new file mode 100644
index 0000000..ea890fe
--- /dev/null
+++ b/tests/fortify2_test.cpp
@@ -0,0 +1,108 @@
+/*
+ * Copyright (C) 2013 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.
+ */
+
+#undef _FORTIFY_SOURCE
+#define _FORTIFY_SOURCE 2
+
+#include <gtest/gtest.h>
+#include <string.h>
+
+struct foo {
+ char a[10];
+ char b[10];
+};
+
+// We have to say "DeathTest" here so gtest knows to run this test (which exits)
+// in its own process.
+TEST(Fortify2_DeathTest, strncpy_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ int copy_amt = atoi("11");
+ ASSERT_EXIT(strncpy(myfoo.a, "01234567890", copy_amt),
+ testing::KilledBySignal(SIGSEGV), "");
+}
+
+TEST(Fortify2_DeathTest, sprintf_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ char source_buf[15];
+ memcpy(source_buf, "12345678901234", 15);
+ ASSERT_EXIT(sprintf(myfoo.a, "%s", source_buf),
+ testing::KilledBySignal(SIGSEGV), "");
+}
+
+#if __BIONIC__
+TEST(Fortify2_DeathTest, strchr_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ memcpy(myfoo.a, "0123456789", sizeof(myfoo.a));
+ myfoo.b[0] = '\0';
+ ASSERT_EXIT(printf("%s", strchr(myfoo.a, 'a')),
+ testing::KilledBySignal(SIGSEGV), "");
+}
+
+TEST(Fortify2_DeathTest, strrchr_fortified2) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ foo myfoo;
+ memcpy(myfoo.a, "0123456789", 10);
+ memcpy(myfoo.b, "01234", 6);
+ ASSERT_EXIT(printf("%s", strrchr(myfoo.a, 'a')),
+ testing::KilledBySignal(SIGSEGV), "");
+}
+#endif
+
+/***********************************************************/
+/* TESTS BELOW HERE DUPLICATE TESTS FROM fortify1_test.cpp */
+/***********************************************************/
+
+#if __BIONIC__
+TEST(Fortify2_DeathTest, strcpy_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ char *orig = strdup("0123456789");
+ ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGSEGV), "");
+ free(orig);
+}
+
+TEST(Fortify2_DeathTest, strlen_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ memcpy(buf, "0123456789", sizeof(buf));
+ ASSERT_EXIT(printf("%d", strlen(buf)), testing::KilledBySignal(SIGSEGV), "");
+}
+
+TEST(Fortify2_DeathTest, strchr_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ memcpy(buf, "0123456789", sizeof(buf));
+ ASSERT_EXIT(printf("%s", strchr(buf, 'a')), testing::KilledBySignal(SIGSEGV), "");
+}
+
+TEST(Fortify2_DeathTest, strrchr_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ memcpy(buf, "0123456789", sizeof(buf));
+ ASSERT_EXIT(printf("%s", strrchr(buf, 'a')), testing::KilledBySignal(SIGSEGV), "");
+}
+#endif
+
+TEST(Fortify2_DeathTest, sprintf_fortified) {
+ ::testing::FLAGS_gtest_death_test_style = "threadsafe";
+ char buf[10];
+ char source_buf[15];
+ memcpy(source_buf, "12345678901234", 15);
+ ASSERT_EXIT(sprintf(buf, "%s", source_buf), testing::KilledBySignal(SIGSEGV), "");
+}
diff --git a/tests/stdio_test.cpp b/tests/stdio_test.cpp
index 4b5a1f9..2e779d8 100644
--- a/tests/stdio_test.cpp
+++ b/tests/stdio_test.cpp
@@ -193,3 +193,21 @@
ASSERT_EQ(0, pclose(fp));
}
+
+TEST(stdio, getc) {
+ FILE* fp = fopen("/proc/version", "r");
+ ASSERT_TRUE(fp != NULL);
+ ASSERT_EQ('L', getc(fp));
+ ASSERT_EQ('i', getc(fp));
+ ASSERT_EQ('n', getc(fp));
+ ASSERT_EQ('u', getc(fp));
+ ASSERT_EQ('x', getc(fp));
+ fclose(fp);
+}
+
+TEST(stdio, putc) {
+ FILE* fp = fopen("/proc/version", "r");
+ ASSERT_TRUE(fp != NULL);
+ ASSERT_EQ(EOF, putc('x', fp));
+ fclose(fp);
+}
diff --git a/tests/stdlib_test.cpp b/tests/stdlib_test.cpp
index fed39f8..e5d7812 100644
--- a/tests/stdlib_test.cpp
+++ b/tests/stdlib_test.cpp
@@ -109,3 +109,26 @@
ASSERT_STREQ(executable_path, p);
free(p);
}
+
+TEST(stdlib, qsort) {
+ struct s {
+ char name[16];
+ static int comparator(const void* lhs, const void* rhs) {
+ return strcmp(reinterpret_cast<const s*>(lhs)->name, reinterpret_cast<const s*>(rhs)->name);
+ }
+ };
+ s entries[3];
+ strcpy(entries[0].name, "charlie");
+ strcpy(entries[1].name, "bravo");
+ strcpy(entries[2].name, "alpha");
+
+ qsort(entries, 3, sizeof(s), s::comparator);
+ ASSERT_STREQ("alpha", entries[0].name);
+ ASSERT_STREQ("bravo", entries[1].name);
+ ASSERT_STREQ("charlie", entries[2].name);
+
+ qsort(entries, 3, sizeof(s), s::comparator);
+ ASSERT_STREQ("alpha", entries[0].name);
+ ASSERT_STREQ("bravo", entries[1].name);
+ ASSERT_STREQ("charlie", entries[2].name);
+}
diff --git a/tests/string_test.cpp b/tests/string_test.cpp
index 1720058..63bfadb 100644
--- a/tests/string_test.cpp
+++ b/tests/string_test.cpp
@@ -209,6 +209,13 @@
}
}
+TEST(string, strchr_with_0) {
+ char buf[10];
+ const char* s = "01234";
+ memcpy(buf, s, strlen(s) + 1);
+ EXPECT_TRUE(strchr(buf, '\0') == (buf + strlen(s)));
+}
+
TEST(string, strchr) {
int seek_char = random() & 255;
@@ -307,39 +314,6 @@
#if __BIONIC__
-// We have to say "DeathTest" here so gtest knows to run this test (which exits)
-// in its own process.
-TEST(string_DeathTest, strcpy_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- char *orig = strdup("0123456789");
- ASSERT_EXIT(strcpy(buf, orig), testing::KilledBySignal(SIGSEGV), "");
- free(orig);
-}
-
-TEST(string_DeathTest, strlen_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- memcpy(buf, "0123456789", sizeof(buf));
- ASSERT_EXIT(printf("%d", strlen(buf)), testing::KilledBySignal(SIGSEGV), "");
-}
-
-TEST(string_DeathTest, strchr_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- memcpy(buf, "0123456789", sizeof(buf));
- ASSERT_EXIT(printf("%s", strchr(buf, 'a')), testing::KilledBySignal(SIGSEGV), "");
-}
-
-TEST(string_DeathTest, strrchr_fortified) {
- ::testing::FLAGS_gtest_death_test_style = "threadsafe";
- char buf[10];
- memcpy(buf, "0123456789", sizeof(buf));
- ASSERT_EXIT(printf("%s", strrchr(buf, 'a')), testing::KilledBySignal(SIGSEGV), "");
-}
-#endif
-
-#if __BIONIC__
TEST(string, strlcat) {
StringTestState state(SMALL);
for (size_t i = 0; i < state.n; i++) {