Merge "Parameterize use of clang in libc_ndk."
diff --git a/libc/arch-mips/bionic/setjmp.S b/libc/arch-mips/bionic/setjmp.S
index 05d0e25..1c26553 100644
--- a/libc/arch-mips/bionic/setjmp.S
+++ b/libc/arch-mips/bionic/setjmp.S
@@ -1,4 +1,31 @@
 /*
+ * Copyright (C) 2014-2015 The Android Open Source Project
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *  * Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *  * Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
+ * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
+ * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
+ * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+/*
  * Copyright (c) 2001-2002 Opsycon AB  (www.opsycon.se / www.opsycon.com)
  *
  * Redistribution and use in source and binary forms, with or without
@@ -94,23 +121,31 @@
 #include <private/bionic_asm.h>
 #include <machine/setjmp.h>
 
-/* On Mips32, jmpbuf begins with optional 4-byte filler so that
- *  all saved FP regs are aligned on 8-byte boundary, despite this whole
- *  struct being mis-declared to users as an array of (4-byte) longs.
- *  All the following offsets are then from the rounded-up base addr
+/* jmpbuf is declared to users as an array of longs, which is only
+ * 4-byte aligned in 32-bit builds.  The Mips jmpbuf begins with a
+ * dynamically-sized 0- or 4-byte unused filler so that double-prec FP regs
+ * are saved to 8-byte-aligned mem cells.
+ * All the following jmpbuf offsets are from the rounded-DOWN base addr.
  */
 
 /* Fields of same size on all MIPS abis: */
-#define	SC_MAGIC        (0*4)		/* 4 bytes, identify jmpbuf */
-#define	SC_MASK		(1*4)		/* 4 bytes, saved signal mask */
-#define	SC_FPSR		(2*4)		/* 4 bytes, floating point control/status reg */
-/*     	filler2		(3*4)		   4 bytes, pad to 8-byte boundary */
+/*     	field:		byte offset:	size:						*/
+/*     	dynam filler	(0*4)		   0-4 bytes of rounddown filler, DON'T TOUCH!!
+						often overlays user storage!!		*/
+#define	SC_MAGIC_OFFSET	(1*4)		/* 4 bytes, identify jmpbuf, first actual field */
+#define	SC_FLAG_OFFSET	(2*4)		/* 4 bytes, savesigs flag */
+#define	SC_FPSR_OFFSET	(3*4)		/* 4 bytes, floating point control/status reg */
+/* following fields are 8-byte aligned */
+#define	SC_MASK_OFFSET	(4*4)		/* 16 bytes, mips32/mips64 version of sigset_t */
+#define	SC_SPARE_OFFSET	(8*4)		/* 8 bytes, reserved for future uses */
 
 /* Registers that are 4-byte on mips32 o32, and 8-byte on mips64 n64 abi */
-#define	SC_REGS_SAVED	12		/* ra,gp,sp,s0-s8 */
-#define	SC_REGS		(4*4)		/* SC_REGS_SAVED*REGSZ bytes */
+#define	SC_REGS_OFFSET	(10*4)		/* SC_REGS_BYTES */
+#define	SC_REGS_SAVED	12 /*regs*/	/* ra,s0-s8,gp,sp */
+#define	SC_REGS_BYTES   (SC_REGS_SAVED*REGSZ)
+#define	SC_REGS		SC_REGS_OFFSET
 
-/* Floating pt registers are 8-bytes on all abis,
+/* Double floating pt registers are 8-bytes on all abis,
  * but the number of saved fp regs varies for o32/n32 versus n64 abis:
  */
 
@@ -120,22 +155,20 @@
 #define	SC_FPREGS_SAVED	6  /* even fp regs f20,f22,f24,f26,f28,f30 */
 #endif
 
-#define	SC_FPREGS	(SC_REGS + SC_REGS_SAVED*REGSZ)  /* SC_FPREGS_SAVED*REGSZ_FP bytes */
+#define	SC_FPREGS_OFFSET (SC_REGS_OFFSET + SC_REGS_BYTES)  /* SC_FPREGS_BYTES */
+#define	SC_FPREGS_BYTES (SC_FPREGS_SAVED*REGSZ_FP)
+#define	SC_FPREGS	SC_FPREGS_OFFSET
 
-#define	SC_BYTES	(SC_FPREGS + SC_FPREGS_SAVED*REGSZ_FP)
-#define	SC_LONGS	(SC_BYTES/REGSZ)
+#define	SC_TOTAL_BYTES	(SC_FPREGS_OFFSET + SC_FPREGS_BYTES)
+#define	SC_TOTAL_LONGS	(SC_TOTAL_BYTES/REGSZ)
 
-#ifdef __LP64__
-/* SC_LONGS is 22, so _JBLEN should be 22 or larger */
-#else
-/* SC_LONGS is 28, but must also allocate dynamic-roundup filler.
-   so _JBLEN should be 29 or larger */
+#if SC_TOTAL_LONGS > _JBLEN
+#error _JBLEN is too small
 #endif
 
 /*
- * _setjmp, _longjmp (restoring signal state)
  *
- *  GPOFF and FRAMESIZE must be the same for both _setjmp and _longjmp!
+ *  GPOFF and FRAMESIZE must be the same for all setjmp/longjmp routines
  *
  */
 
@@ -145,30 +178,33 @@
 GPOFF= FRAMESZ-2*REGSZ
 RAOFF= FRAMESZ-1*REGSZ
 
-NON_LEAF(setjmp, FRAMESZ, ra)
+NON_LEAF(sigsetjmp, FRAMESZ, ra)
 	.mask	0x80000000, RAOFF
 	PTR_SUBU sp, FRAMESZ			# allocate stack frame
-	SETUP_GP64(GPOFF, setjmp)
+	SETUP_GP64(GPOFF, sigsetjmp)
 	SAVE_GP(GPOFF)
 	.set	reorder
 
+setjmp_common:
 #ifndef __LP64__
-	addiu   a0, 7				# roundup jmpbuf addr to 8-byte boundary
-	li      t0, ~7
-	and     a0, t0
+	li	t0, ~7
+	and	a0, t0				# round jmpbuf addr DOWN to 8-byte boundary
 #endif
+	sw	a1, SC_FLAG_OFFSET(a0)		# save savesigs flag
+	beqz	a1, 1f				# do saving of signal mask?
 
-	REG_S	ra, RAOFF(sp)			# save state
+	REG_S	ra, RAOFF(sp)			# spill state
 	REG_S	a0, A0OFF(sp)
-	move	a0, zero			# get current signal mask
-	jal	sigblock
+	# call sigprocmask(int how ignored, sigset_t* null, sigset_t* SC_MASK(a0)):
+	LA	a2, SC_MASK_OFFSET(a0)		# gets current signal mask
+	li	a0, 0				# how; ignored when new mask is null
+	li	a1, 0				# null new mask
+	jal	sigprocmask			# get current signal mask
 	REG_L	a0, A0OFF(sp)
 	REG_L	ra, RAOFF(sp)
-
-	REG_S	v0, SC_MASK(a0)			# save sc_mask = sigblock(0)
-
+1:
 	li	v0, 0xACEDBADE			# sigcontext magic number
-	sw	v0, SC_MAGIC(a0)
+	sw	v0, SC_MAGIC_OFFSET(a0)
 	# callee-saved long-sized regs:
 	REG_S	ra, SC_REGS+0*REGSZ(a0)
 	REG_S	s0, SC_REGS+1*REGSZ(a0)
@@ -181,9 +217,9 @@
 	REG_S	s7, SC_REGS+8*REGSZ(a0)
 	REG_S	s8, SC_REGS+9*REGSZ(a0)
 	REG_L	v0, GPOFF(sp)
-	REG_S	v0, SC_REGS+10*REGSZ(a0)
+	REG_S	v0, SC_REGS+10*REGSZ(a0)	# save gp
 	PTR_ADDU v0, sp, FRAMESZ
-	REG_S	v0, SC_REGS+11*REGSZ(a0)
+	REG_S	v0, SC_REGS+11*REGSZ(a0)	# save orig sp
 
 	cfc1	v0, $31
 
@@ -199,7 +235,7 @@
 	s.d	$f31, SC_FPREGS+7*REGSZ_FP(a0)
 #else
 	# callee-saved fp regs on mips o32 ABI are
-	#   the even-numbered fp regs $f20,$f22,...$f30
+	#   the even-numbered double fp regs $f20,$f22,...$f30
 	s.d	$f20, SC_FPREGS+0*REGSZ_FP(a0)
 	s.d	$f22, SC_FPREGS+1*REGSZ_FP(a0)
 	s.d	$f24, SC_FPREGS+2*REGSZ_FP(a0)
@@ -207,37 +243,68 @@
 	s.d	$f28, SC_FPREGS+4*REGSZ_FP(a0)
 	s.d	$f30, SC_FPREGS+5*REGSZ_FP(a0)
 #endif
-	sw	v0, SC_FPSR(a0)
+	sw	v0, SC_FPSR_OFFSET(a0)
 	move	v0, zero
 	RESTORE_GP64
 	PTR_ADDU sp, FRAMESZ
 	j	ra
-END(setjmp)
+END(sigsetjmp)
 
-NON_LEAF(longjmp, FRAMESZ, ra)
+
+# Alternate entry points:
+
+NON_LEAF(setjmp, FRAMESZ, ra)
 	.mask	0x80000000, RAOFF
 	PTR_SUBU sp, FRAMESZ
-	SETUP_GP64(GPOFF, longjmp)
+	SETUP_GP64(GPOFF, setjmp)		# can't share sigsetjmp's gp code
+	SAVE_GP(GPOFF)
+	.set	reorder
+
+	li	a1, 1				# save/restore signals state
+	b	setjmp_common			# tail call
+END(setjmp)
+
+
+NON_LEAF(_setjmp, FRAMESZ, ra)
+	.mask	0x80000000, RAOFF
+	PTR_SUBU sp, FRAMESZ
+	SETUP_GP64(GPOFF, _setjmp)		# can't share sigsetjmp's gp code
+	SAVE_GP(GPOFF)
+	.set	reorder
+
+	li	a1, 0				# don't save/restore signals
+	b	setjmp_common			# tail call
+END(_setjmp)
+
+
+NON_LEAF(siglongjmp, FRAMESZ, ra)
+	.mask	0x80000000, RAOFF
+	PTR_SUBU sp, FRAMESZ
+	SETUP_GP64(GPOFF, siglongjmp)
 	SAVE_GP(GPOFF)
 	.set	reorder
 
 #ifndef __LP64__
-	addiu	a0, 7				# roundup jmpbuf addr to 8-byte boundary
-	li      t0, ~7
-	and	a0, t0
+	li	t0, ~7
+	and	a0, t0				# round jmpbuf addr DOWN to 8-byte boundary
 #endif
+	lw	v0, SC_MAGIC_OFFSET(a0)
+	li	t0, 0xACEDBADE
+	bne	v0, t0, longjmp_botch		# jump if error
 
-	REG_S	a1, A1OFF(sp)
+	lw	t0, SC_FLAG_OFFSET(a0)		# get savesigs flag
+	beqz	t0, 1f				# restore signal mask?
+
+	REG_S	a1, A1OFF(sp)			# temp spill
 	REG_S	a0, A0OFF(sp)
-	lw	a0, SC_MASK(a0)
-	jal	sigsetmask
+        # call sigprocmask(int how SIG_SETMASK, sigset_t* SC_MASK(a0), sigset_t* null):
+	LA	a1, SC_MASK_OFFSET(a0)		# signals being restored
+	li	a0, 3				# mips SIG_SETMASK
+	li	a2, 0				# null
+	jal	sigprocmask			# restore signal mask
 	REG_L	a0, A0OFF(sp)
 	REG_L	a1, A1OFF(sp)
-
-	lw	v0, SC_MAGIC(a0)
-	li	t0, 0xACEDBADE
-	bne	v0, t0, longjmp_botch			# jump if error
-
+1:
 	# callee-saved long-sized regs:
 	REG_L	ra, SC_REGS+0*REGSZ(a0)
 	REG_L	s0, SC_REGS+1*REGSZ(a0)
@@ -252,8 +319,8 @@
 	REG_L	gp, SC_REGS+10*REGSZ(a0)
 	REG_L	sp, SC_REGS+11*REGSZ(a0)
 
-	lw	v0, SC_FPSR(a0)
-	ctc1	v0, $31
+	lw	v0, SC_FPSR_OFFSET(a0)
+	ctc1	v0, $31			# restore old fr mode before fp values
 #ifdef __LP64__
 	# callee-saved fp regs on mips n64 ABI are $f24..$f31
 	l.d	$f24, SC_FPREGS+0*REGSZ_FP(a0)
@@ -266,7 +333,7 @@
 	l.d	$f31, SC_FPREGS+7*REGSZ_FP(a0)
 #else
 	# callee-saved fp regs on mips o32 ABI are
-	#   the even-numbered fp regs $f20,$f22,...$f30
+	#   the even-numbered double fp regs $f20,$f22,...$f30
 	l.d	$f20, SC_FPREGS+0*REGSZ_FP(a0)
 	l.d	$f22, SC_FPREGS+1*REGSZ_FP(a0)
 	l.d	$f24, SC_FPREGS+2*REGSZ_FP(a0)
@@ -278,192 +345,19 @@
 	li	a1, 1			# never return 0!
 1:
 	move	v0, a1
-	j	ra
+	j	ra			# return to setjmp call site
 
 longjmp_botch:
 	jal	longjmperror
 	jal	abort
-	RESTORE_GP64
-	PTR_ADDU sp, FRAMESZ
-END(longjmp)
-
-
-/*
- * _setjmp, _longjmp (not restoring signal state)
- *
- *  GPOFF and FRAMESIZE must be the same for both _setjmp and _longjmp!
- *
- */
-
-FRAMESZ= MKFSIZ(0,4)
-GPOFF= FRAMESZ-2*REGSZ
-
-LEAF(_setjmp, FRAMESZ)
-	PTR_SUBU sp, FRAMESZ
-	SETUP_GP64(GPOFF, _setjmp)
-	SAVE_GP(GPOFF)
-	.set	reorder
-
-#ifndef __LP64__
-	addiu   a0, 7				# roundup jmpbuf addr to 8-byte boundary
-	li      t0, ~7
-	and     a0, t0
-#endif
-
-	# SC_MASK is unused here
-
-	li	v0, 0xACEDBADE			# sigcontext magic number
-	sw	v0, SC_MAGIC(a0)
-	# callee-saved long-sized regs:
-	REG_S	ra, SC_REGS+0*REGSZ(a0)
-	REG_S	s0, SC_REGS+1*REGSZ(a0)
-	REG_S	s1, SC_REGS+2*REGSZ(a0)
-	REG_S	s2, SC_REGS+3*REGSZ(a0)
-	REG_S	s3, SC_REGS+4*REGSZ(a0)
-	REG_S	s4, SC_REGS+5*REGSZ(a0)
-	REG_S	s5, SC_REGS+6*REGSZ(a0)
-	REG_S	s6, SC_REGS+7*REGSZ(a0)
-	REG_S	s7, SC_REGS+8*REGSZ(a0)
-	REG_S	s8, SC_REGS+9*REGSZ(a0)
-	REG_L	v0, GPOFF(sp)
-	REG_S	v0, SC_REGS+10*REGSZ(a0)
-	PTR_ADDU v0, sp, FRAMESZ
-	REG_S	v0, SC_REGS+11*REGSZ(a0)
-
-	cfc1	v0, $31
-
-#ifdef __LP64__
-	# callee-saved fp regs on mips n64 ABI are $f24..$f31
-	s.d	$f24, SC_FPREGS+0*REGSZ_FP(a0)
-	s.d	$f25, SC_FPREGS+1*REGSZ_FP(a0)
-	s.d	$f26, SC_FPREGS+2*REGSZ_FP(a0)
-	s.d	$f27, SC_FPREGS+3*REGSZ_FP(a0)
-	s.d	$f28, SC_FPREGS+4*REGSZ_FP(a0)
-	s.d	$f29, SC_FPREGS+5*REGSZ_FP(a0)
-	s.d	$f30, SC_FPREGS+6*REGSZ_FP(a0)
-	s.d	$f31, SC_FPREGS+7*REGSZ_FP(a0)
-#else
-	# callee-saved fp regs on mips o32 ABI are
-	#   the even-numbered fp regs $f20,$f22,...$f30
-	s.d	$f20, SC_FPREGS+0*REGSZ_FP(a0)
-	s.d	$f22, SC_FPREGS+1*REGSZ_FP(a0)
-	s.d	$f24, SC_FPREGS+2*REGSZ_FP(a0)
-	s.d	$f26, SC_FPREGS+3*REGSZ_FP(a0)
-	s.d	$f28, SC_FPREGS+4*REGSZ_FP(a0)
-	s.d	$f30, SC_FPREGS+5*REGSZ_FP(a0)
-#endif
-	sw	v0, SC_FPSR(a0)
-	move	v0, zero
-	RESTORE_GP64
-	PTR_ADDU sp, FRAMESZ
-	j	ra
-END(_setjmp)
-
-
-LEAF(_longjmp, FRAMESZ)
-	PTR_SUBU sp, FRAMESZ
-	SETUP_GP64(GPOFF, _longjmp)
-	SAVE_GP(GPOFF)
-	.set	reorder
-
-#ifndef __LP64__
-	addiu	a0, 7				# roundup jmpbuf addr to 8-byte boundary
-	li      t0, ~7
-	and	a0, t0
-#endif
-
-	# SC_MASK is unused here
-
-	lw	v0, SC_MAGIC(a0)
-	li	t0, 0xACEDBADE
-	bne	v0, t0, _longjmp_botch			# jump if error
-
-	# callee-saved long-sized regs:
-	REG_L	ra, SC_REGS+0*REGSZ(a0)
-	REG_L	s0, SC_REGS+1*REGSZ(a0)
-	REG_L	s1, SC_REGS+2*REGSZ(a0)
-	REG_L	s2, SC_REGS+3*REGSZ(a0)
-	REG_L	s3, SC_REGS+4*REGSZ(a0)
-	REG_L	s4, SC_REGS+5*REGSZ(a0)
-	REG_L	s5, SC_REGS+6*REGSZ(a0)
-	REG_L	s6, SC_REGS+7*REGSZ(a0)
-	REG_L	s7, SC_REGS+8*REGSZ(a0)
-	REG_L	s8, SC_REGS+9*REGSZ(a0)
-	REG_L	gp, SC_REGS+10*REGSZ(a0)
-	REG_L	sp, SC_REGS+11*REGSZ(a0)
-
-	lw	v0, SC_FPSR(a0)
-	ctc1	v0, $31
-#ifdef __LP64__
-	# callee-saved fp regs on mips n64 ABI are $f24..$f31
-	l.d	$f24, SC_FPREGS+0*REGSZ_FP(a0)
-	l.d	$f25, SC_FPREGS+1*REGSZ_FP(a0)
-	l.d	$f26, SC_FPREGS+2*REGSZ_FP(a0)
-	l.d	$f27, SC_FPREGS+3*REGSZ_FP(a0)
-	l.d	$f28, SC_FPREGS+4*REGSZ_FP(a0)
-	l.d	$f29, SC_FPREGS+5*REGSZ_FP(a0)
-	l.d	$f30, SC_FPREGS+6*REGSZ_FP(a0)
-	l.d	$f31, SC_FPREGS+7*REGSZ_FP(a0)
-#else
-	# callee-saved fp regs on mips o32 ABI are
-	#   the even-numbered fp regs $f20,$f22,...$f30
-	l.d	$f20, SC_FPREGS+0*REGSZ_FP(a0)
-	l.d	$f22, SC_FPREGS+1*REGSZ_FP(a0)
-	l.d	$f24, SC_FPREGS+2*REGSZ_FP(a0)
-	l.d	$f26, SC_FPREGS+3*REGSZ_FP(a0)
-	l.d	$f28, SC_FPREGS+4*REGSZ_FP(a0)
-	l.d	$f30, SC_FPREGS+5*REGSZ_FP(a0)
-#endif
-	bne	a1, zero, 1f
-	li	a1, 1			# never return 0!
-1:
-	move	v0, a1
-	j	ra
-
-_longjmp_botch:
-	jal	longjmperror
-	jal	abort
-	RESTORE_GP64
-	PTR_ADDU sp, FRAMESZ
-END(_longjmp)
-
-/*
- * trampolines for sigsetjmp and  siglongjmp save and restore mask.
- *
- */
-FRAMESZ= MKFSIZ(1,1)
-GPOFF= FRAMESZ-2*REGSZ
-
-LEAF(sigsetjmp, FRAMESZ)
-	PTR_SUBU sp, FRAMESZ
-	SETUP_GP64(GPOFF, sigsetjmp)
-	.set	reorder
-	sw	a1, _JBLEN*REGSZ(a0)		# save "savemask"
-	bne	a1, 0x0, 1f			# do saving of signal mask?
-	LA	t9, _setjmp
-	RESTORE_GP64
-	PTR_ADDU sp, FRAMESZ
-	jr t9
-
-1:	LA	t9, setjmp
-	RESTORE_GP64
-	PTR_ADDU sp, FRAMESZ
-	jr t9
-END(sigsetjmp)
-
-LEAF(siglongjmp, FRAMESZ)
-	PTR_SUBU sp, FRAMESZ
-	SETUP_GP64(GPOFF, siglongjmp)
-	.set	reorder
-	lw	t0, _JBLEN*REGSZ(a0)		# get "savemask"
-	bne	t0, 0x0, 1f			# restore signal mask?
-	LA	t9, _longjmp
-	RESTORE_GP64
-	PTR_ADDU sp, FRAMESZ
-	jr	t9
-1:
-	LA	t9, longjmp
-	RESTORE_GP64
-	PTR_ADDU sp, FRAMESZ
-	jr	t9
 END(siglongjmp)
+
+
+	.globl	longjmp
+	.type	longjmp, @function
+	.equ	longjmp, siglongjmp	# alias for siglongjmp
+
+
+	.globl	_longjmp
+	.type	_longjmp, @function
+	.equ	_longjmp, siglongjmp	# alias for siglongjmp
diff --git a/libc/arch-mips/include/machine/setjmp.h b/libc/arch-mips/include/machine/setjmp.h
index a9707dc..4067d51 100644
--- a/libc/arch-mips/include/machine/setjmp.h
+++ b/libc/arch-mips/include/machine/setjmp.h
@@ -6,9 +6,10 @@
 #define _MIPS_SETJMP_H_
 
 #ifdef __LP64__
-#define	_JBLEN	22		/* size, in 8-byte longs, of a mips64 jmp_buf */
+#define	_JBLEN	25	/* size, in 8-byte longs, of a mips64 jmp_buf/sigjmp_buf */
 #else
-#define	_JBLEN	29		/* size, in 4-byte longs, of a mips32 jmp_buf */
+#define	_JBLEN	157	/* historical size, in 4-byte longs, of a mips32 jmp_buf */
+			/* actual used size is 34 */
 #endif
 
 #endif /* !_MIPS_SETJMP_H_ */
diff --git a/libc/include/fcntl.h b/libc/include/fcntl.h
index 4c4cfbd..0f016d7 100644
--- a/libc/include/fcntl.h
+++ b/libc/include/fcntl.h
@@ -59,22 +59,29 @@
 
 extern int creat(const char*, mode_t);
 extern int creat64(const char*, mode_t);
-extern int fallocate64(int, int, off64_t, off64_t);
-extern int fallocate(int, int, off_t, off_t);
 extern int fcntl(int, int, ...);
 extern int openat(int, const char*, int, ...);
 extern int openat64(int, const char*, int, ...);
 extern int open(const char*, int, ...);
 extern int open64(const char*, int, ...);
-extern int posix_fadvise64(int, off64_t, off64_t, int);
-extern int posix_fadvise(int, off_t, off_t, int);
-extern int posix_fallocate64(int, off64_t, off64_t);
-extern int posix_fallocate(int, off_t, off_t);
 extern ssize_t splice(int, off64_t*, int, off64_t*, size_t, unsigned int);
 extern ssize_t tee(int, int, size_t, unsigned int);
 extern int unlinkat(int, const char*, int);
 extern ssize_t vmsplice(int, const struct iovec*, size_t, unsigned int);
 
+#if defined(__USE_FILE_OFFSET64)
+extern int fallocate(int, int, off_t, off_t) __RENAME(fallocate64);
+extern int posix_fadvise(int, off_t, off_t, int) __RENAME(posix_fadvise64);
+extern int posix_fallocate(int, off_t, off_t) __RENAME(posix_fallocate);
+#else
+extern int fallocate(int, int, off_t, off_t);
+extern int posix_fadvise(int, off_t, off_t, int);
+extern int posix_fallocate(int, off_t, off_t);
+#endif
+extern int fallocate64(int, int, off64_t, off64_t);
+extern int posix_fadvise64(int, off64_t, off64_t, int);
+extern int posix_fallocate64(int, off64_t, off64_t);
+
 extern int __open_2(const char*, int);
 extern int __open_real(const char*, int, ...) __RENAME(open);
 extern int __openat_2(int, const char*, int);
diff --git a/libc/include/stdio.h b/libc/include/stdio.h
index b04aa24..17ef096 100644
--- a/libc/include/stdio.h
+++ b/libc/include/stdio.h
@@ -57,8 +57,6 @@
 
 __BEGIN_DECLS
 
-#define	_FSTDIO			/* Define for new stdio with functions. */
-
 typedef off_t fpos_t;		/* stdio file position type */
 
 /*
@@ -266,7 +264,7 @@
 
 #ifndef __AUDIT__
 #if !defined(__STDC_VERSION__) || __STDC_VERSION__ < 201112L
-char* gets(char*) __warnattr("gets is very unsafe; consider using fgets");
+char* gets(char*) __attribute__((deprecated("gets is very unsafe; consider using fgets")));
 #endif
 int sprintf(char* __restrict, const char* __restrict, ...)
     __printflike(2, 3) __warnattr("sprintf is often misused; please use snprintf");
@@ -282,11 +280,22 @@
 extern int rename(const char*, const char*);
 extern int renameat(int, const char*, int, const char*);
 
+#if defined(__USE_FILE_OFFSET64)
+/* Not possible. */
+int	 fgetpos(FILE * __restrict, fpos_t * __restrict)
+	__attribute__((__error__("not available with _FILE_OFFSET_BITS=64")));
+int	 fsetpos(FILE *, const fpos_t *)
+	__attribute__((__error__("not available with _FILE_OFFSET_BITS=64")));
+int	 fseeko(FILE *, off_t, int)
+	__attribute__((__error__("not available with _FILE_OFFSET_BITS=64")));
+off_t	 ftello(FILE *)
+	__attribute__((__error__("not available with _FILE_OFFSET_BITS=64")));
+#else
 int	 fgetpos(FILE * __restrict, fpos_t * __restrict);
 int	 fsetpos(FILE *, const fpos_t *);
-
 int	 fseeko(FILE *, off_t, int);
 off_t	 ftello(FILE *);
+#endif
 
 #if __ISO_C_VISIBLE >= 1999 || __BSD_VISIBLE
 int	 snprintf(char * __restrict, size_t, const char * __restrict, ...)
diff --git a/libc/include/sys/cdefs.h b/libc/include/sys/cdefs.h
index 1d33895..04613f4 100644
--- a/libc/include/sys/cdefs.h
+++ b/libc/include/sys/cdefs.h
@@ -380,6 +380,15 @@
 # define __USE_BSD 1
 #endif
 
+/*
+ * _FILE_OFFSET_BITS 64 support.
+ */
+#if !defined(__LP64__) && defined(_FILE_OFFSET_BITS)
+#if _FILE_OFFSET_BITS == 64
+#define __USE_FILE_OFFSET64 1
+#endif
+#endif
+
 /*-
  * POSIX.1 requires that the macros we test be defined before any standard
  * header file is included.
diff --git a/libc/include/sys/mman.h b/libc/include/sys/mman.h
index 1663222..6857f60 100644
--- a/libc/include/sys/mman.h
+++ b/libc/include/sys/mman.h
@@ -49,8 +49,13 @@
 #define POSIX_MADV_WILLNEED   MADV_WILLNEED
 #define POSIX_MADV_DONTNEED   MADV_DONTNEED
 
+#if defined(__USE_FILE_OFFSET64)
+extern void* mmap(void*, size_t, int, int, int, off_t) __RENAME(mmap64);
+#else
 extern void* mmap(void*, size_t, int, int, int, off_t);
+#endif
 extern void* mmap64(void*, size_t, int, int, int, off64_t);
+
 extern int munmap(void*, size_t);
 extern int msync(const void*, size_t, int);
 extern int mprotect(const void*, size_t, int);
diff --git a/libc/include/sys/sendfile.h b/libc/include/sys/sendfile.h
index 81a3c44..c588e68 100644
--- a/libc/include/sys/sendfile.h
+++ b/libc/include/sys/sendfile.h
@@ -34,7 +34,11 @@
 
 __BEGIN_DECLS
 
+#if defined(__USE_FILE_OFFSET64)
+extern ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count) __RENAME(sendfile64);
+#else
 extern ssize_t sendfile(int out_fd, int in_fd, off_t* offset, size_t count);
+#endif
 extern ssize_t sendfile64(int out_fd, int in_fd, off64_t* offset, size_t count);
 
 __END_DECLS
diff --git a/libc/include/sys/types.h b/libc/include/sys/types.h
index a5fa692..a6b0fd8 100644
--- a/libc/include/sys/types.h
+++ b/libc/include/sys/types.h
@@ -90,16 +90,14 @@
 typedef __kernel_time_t __time_t;
 typedef __time_t time_t;
 
-/* This historical accident means that we had a 32-bit off_t on 32-bit architectures. */
-#if !defined(__LP64__)
-typedef __kernel_off_t off_t;
-typedef __kernel_loff_t loff_t;
+#if defined(__USE_FILE_OFFSET64) || defined(__LP64__)
+typedef int64_t off_t;
+typedef off_t loff_t;
 typedef loff_t off64_t;
 #else
-/* We could re-use the LP32 definitions, but that would mean that although off_t and loff_t/off64_t
- * would be the same size, they wouldn't actually be the same type, which can lead to warnings. */
+/* This historical accident means that we had a 32-bit off_t on 32-bit architectures. */
 typedef __kernel_off_t off_t;
-typedef off_t loff_t;
+typedef __kernel_loff_t loff_t;
 typedef loff_t off64_t;
 #endif
 
diff --git a/libc/include/unistd.h b/libc/include/unistd.h
index 16d413a..0b67004 100644
--- a/libc/include/unistd.h
+++ b/libc/include/unistd.h
@@ -146,22 +146,14 @@
 extern int fchown(int, uid_t, gid_t);
 extern int fchownat(int, const char*, uid_t, gid_t, int);
 extern int lchown(const char *, uid_t, gid_t);
-extern int truncate(const char *, off_t);
-extern int truncate64(const char *, off64_t);
 extern char *getcwd(char *, size_t);
 
 extern int sync(void);
 
 extern int close(int);
-extern off_t lseek(int, off_t, int);
-extern off64_t lseek64(int, off64_t, int);
 
 extern ssize_t read(int, void *, size_t);
 extern ssize_t write(int, const void *, size_t);
-extern ssize_t pread(int, void *, size_t, off_t);
-extern ssize_t pread64(int, void *, size_t, off64_t);
-extern ssize_t pwrite(int, const void *, size_t, off_t);
-extern ssize_t pwrite64(int, const void *, size_t, off64_t);
 
 extern int dup(int);
 extern int dup2(int, int);
@@ -170,7 +162,24 @@
 extern int ioctl(int, int, ...);
 extern int fsync(int);
 extern int fdatasync(int);
+
+#if defined(__USE_FILE_OFFSET64)
+extern int truncate(const char *, off_t) __RENAME(truncate64);
+extern off_t lseek(int, off_t, int) __RENAME(lseek64);
+extern ssize_t pread(int, void *, size_t, off_t) __RENAME(pread64);
+extern ssize_t pwrite(int, const void *, size_t, off_t) __RENAME(pwrite64);
+extern int ftruncate(int, off_t) __RENAME(ftruncate64);
+#else
+extern int truncate(const char *, off_t);
+extern off_t lseek(int, off_t, int);
+extern ssize_t pread(int, void *, size_t, off_t);
+extern ssize_t pwrite(int, const void *, size_t, off_t);
 extern int ftruncate(int, off_t);
+#endif
+extern int truncate64(const char *, off64_t);
+extern off64_t lseek64(int, off64_t, int);
+extern ssize_t pread64(int, void *, size_t, off64_t);
+extern ssize_t pwrite64(int, const void *, size_t, off64_t);
 extern int ftruncate64(int, off64_t);
 
 extern int pause(void);
diff --git a/libc/zoneinfo/tzdata b/libc/zoneinfo/tzdata
index fc6c5ba..b9a6621 100644
--- a/libc/zoneinfo/tzdata
+++ b/libc/zoneinfo/tzdata
Binary files differ