Commit a5d8c310ee

Andrew Kelley <andrew@ziglang.org>
2023-06-19 23:22:17
musl: update src files to v1.2.4
1 parent cdcfd15
Changed files (173)
lib
libc
musl
arch
compat
include
src
aio
conf
dirent
fcntl
include
sys
internal
ipc
ldso
legacy
linux
malloc
mallocng
math
misc
mman
mq
network
process
regex
search
select
setjmp
powerpc
signal
stat
stdio
stdlib
string
temp
thread
time
unistd
src
lib/libc/musl/arch/arm/syscall_arch.h
@@ -101,3 +101,10 @@ static inline long __syscall6(long n, long a, long b, long c, long d, long e, lo
 #define SYSCALL_FADVISE_6_ARG
 
 #define SYSCALL_IPC_BROKEN_MODE
+
+#define VDSO_USEFUL
+#define VDSO_CGT32_SYM "__vdso_clock_gettime"
+#define VDSO_CGT32_VER "LINUX_2.6"
+#define VDSO_CGT_SYM "__vdso_clock_gettime64"
+#define VDSO_CGT_VER "LINUX_2.6"
+#define VDSO_CGT_WORKAROUND 1
lib/libc/musl/arch/i386/arch.mak
@@ -1,1 +0,0 @@
-COMPAT_SRC_DIRS = compat/time32
lib/libc/musl/arch/m68k/arch.mak
@@ -1,1 +0,0 @@
-COMPAT_SRC_DIRS = compat/time32
lib/libc/musl/arch/mips/bits/signal.h
@@ -66,7 +66,6 @@ typedef struct __ucontext {
 #define SA_RESTART    0x10000000
 #define SA_NODEFER    0x40000000
 #define SA_RESETHAND  0x80000000
-#define SA_RESTORER   0x04000000
 
 #undef SIG_BLOCK
 #undef SIG_UNBLOCK
lib/libc/musl/arch/mips/arch.mak
@@ -1,1 +0,0 @@
-COMPAT_SRC_DIRS = compat/time32
lib/libc/musl/arch/mips/ksigaction.h
@@ -4,10 +4,7 @@ struct k_sigaction {
 	unsigned flags;
 	void (*handler)(int);
 	unsigned long mask[4];
-	/* The following field is past the end of the structure the
-	 * kernel will read or write, and exists only to avoid having
-	 * mips-specific preprocessor conditionals in sigaction.c. */
-	void (*restorer)();
+	void *unused;
 };
 
 hidden void __restore(), __restore_rt();
lib/libc/musl/arch/mips/reloc.h
@@ -29,6 +29,7 @@
 
 #define NEED_MIPS_GOT_RELOCS 1
 #define DT_DEBUG_INDIRECT DT_MIPS_RLD_MAP
+#define DT_DEBUG_INDIRECT_REL DT_MIPS_RLD_MAP_REL
 #define ARCH_SYM_REJECT_UND(s) (!((s)->st_other & STO_MIPS_PLT))
 
 #define CRTJMP(pc,sp) __asm__ __volatile__( \
lib/libc/musl/arch/mips64/bits/signal.h
@@ -85,7 +85,6 @@ typedef struct __ucontext {
 #define SA_RESTART    0x10000000
 #define SA_NODEFER    0x40000000
 #define SA_RESETHAND  0x80000000
-#define SA_RESTORER   0x04000000
 
 #undef SIG_BLOCK
 #undef SIG_UNBLOCK
lib/libc/musl/arch/mips64/ksigaction.h
@@ -4,7 +4,7 @@ struct k_sigaction {
 	unsigned flags;
 	void (*handler)(int);
 	unsigned long mask[2];
-	void (*restorer)();
+	void *unused;
 };
 
 hidden void __restore(), __restore_rt();
lib/libc/musl/arch/mips64/reloc.h
@@ -38,6 +38,7 @@
 
 #define NEED_MIPS_GOT_RELOCS 1
 #define DT_DEBUG_INDIRECT DT_MIPS_RLD_MAP
+#define DT_DEBUG_INDIRECT_REL DT_MIPS_RLD_MAP_REL
 #define ARCH_SYM_REJECT_UND(s) (!((s)->st_other & STO_MIPS_PLT))
 
 #define CRTJMP(pc,sp) __asm__ __volatile__( \
lib/libc/musl/arch/powerpc/arch.mak
@@ -1,1 +0,0 @@
-COMPAT_SRC_DIRS = compat/time32
lib/libc/musl/arch/riscv64/bits/signal.h
@@ -76,7 +76,6 @@ typedef struct __ucontext
 #define SA_RESTART   0x10000000
 #define SA_NODEFER   0x40000000
 #define SA_RESETHAND 0x80000000
-#define SA_RESTORER  0x04000000
 
 #endif
 
lib/libc/musl/compat/time32/__xstat.c
@@ -3,22 +3,22 @@
 
 struct stat32;
 
-int __fxstat64(int ver, int fd, struct stat32 *buf)
+int __fxstat(int ver, int fd, struct stat32 *buf)
 {
 	return __fstat_time32(fd, buf);
 }
 
-int __fxstatat64(int ver, int fd, const char *path, struct stat32 *buf, int flag)
+int __fxstatat(int ver, int fd, const char *path, struct stat32 *buf, int flag)
 {
 	return __fstatat_time32(fd, path, buf, flag);
 }
 
-int __lxstat64(int ver, const char *path, struct stat32 *buf)
+int __lxstat(int ver, const char *path, struct stat32 *buf)
 {
 	return __lstat_time32(path, buf);
 }
 
-int __xstat64(int ver, const char *path, struct stat32 *buf)
+int __xstat(int ver, const char *path, struct stat32 *buf)
 {
 	return __stat_time32(path, buf);
 }
lib/libc/musl/compat/time32/aio_suspend_time32.c
@@ -7,5 +7,3 @@ int __aio_suspend_time32(const struct aiocb *const cbs[], int cnt, const struct
 	return aio_suspend(cbs, cnt, ts32 ? (&(struct timespec){
 		.tv_sec = ts32->tv_sec, .tv_nsec = ts32->tv_nsec}) : 0);
 }
-
-weak_alias(aio_suspend, aio_suspend64);
lib/libc/musl/compat/time32/fstat_time32.c
@@ -13,5 +13,3 @@ int __fstat_time32(int fd, struct stat32 *restrict st32)
 	if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
 	return r;
 }
-
-weak_alias(fstat, fstat64);
lib/libc/musl/compat/time32/fstatat_time32.c
@@ -13,5 +13,3 @@ int __fstatat_time32(int fd, const char *restrict path, struct stat32 *restrict
 	if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
 	return r;
 }
-
-weak_alias(fstatat, fstatat64);
lib/libc/musl/compat/time32/lstat_time32.c
@@ -13,5 +13,3 @@ int __lstat_time32(const char *restrict path, struct stat32 *restrict st32)
 	if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
 	return r;
 }
-
-weak_alias(lstat, lstat64);
lib/libc/musl/compat/time32/stat_time32.c
@@ -13,5 +13,3 @@ int __stat_time32(const char *restrict path, struct stat32 *restrict st32)
 	if (!r) memcpy(st32, &st, offsetof(struct stat, st_atim));
 	return r;
 }
-
-weak_alias(stat, stat64);
lib/libc/musl/include/arpa/nameser.h
@@ -188,6 +188,36 @@ typedef enum __ns_type {
 	ns_t_sink = 40,
 	ns_t_opt = 41,
 	ns_t_apl = 42,
+	ns_t_ds = 43,
+	ns_t_sshfp = 44,
+	ns_t_ipseckey = 45,
+	ns_t_rrsig = 46,
+	ns_t_nsec = 47,
+	ns_t_dnskey = 48,
+	ns_t_dhcid = 49,
+	ns_t_nsec3 = 50,
+	ns_t_nsec3param = 51,
+	ns_t_tlsa = 52,
+	ns_t_smimea = 53,
+	ns_t_hip = 55,
+	ns_t_ninfo = 56,
+	ns_t_rkey = 57,
+	ns_t_talink = 58,
+	ns_t_cds = 59,
+	ns_t_cdnskey = 60,
+	ns_t_openpgpkey = 61,
+	ns_t_csync = 62,
+	ns_t_spf = 99,
+	ns_t_uinfo = 100,
+	ns_t_uid = 101,
+	ns_t_gid = 102,
+	ns_t_unspec = 103,
+	ns_t_nid = 104,
+	ns_t_l32 = 105,
+	ns_t_l64 = 106,
+	ns_t_lp = 107,
+	ns_t_eui48 = 108,
+	ns_t_eui64 = 109,
 	ns_t_tkey = 249,
 	ns_t_tsig = 250,
 	ns_t_ixfr = 251,
@@ -196,6 +226,11 @@ typedef enum __ns_type {
 	ns_t_maila = 254,
 	ns_t_any = 255,
 	ns_t_zxfr = 256,
+	ns_t_uri = 256,
+	ns_t_caa = 257,
+	ns_t_avc = 258,
+	ns_t_ta = 32768,
+	ns_t_dlv = 32769,
 	ns_t_max = 65536
 } ns_type;
 
@@ -430,12 +465,48 @@ typedef struct {
 #define T_NAPTR		ns_t_naptr
 #define T_A6		ns_t_a6
 #define T_DNAME		ns_t_dname
+#define T_DS		ns_t_ds
+#define T_SSHFP		ns_t_sshfp
+#define T_IPSECKEY	ns_t_ipseckey
+#define T_RRSIG		ns_t_rrsig
+#define T_NSEC		ns_t_nsec
+#define T_DNSKEY	ns_t_dnskey
+#define T_DHCID		ns_t_dhcid
+#define T_NSEC3		ns_t_nsec3
+#define T_NSEC3PARAM	ns_t_nsec3param
+#define T_TLSA		ns_t_tlsa
+#define T_SMIMEA	ns_t_smimea
+#define T_HIP		ns_t_hip
+#define T_NINFO		ns_t_ninfo
+#define T_RKEY		ns_t_rkey
+#define T_TALINK	ns_t_talink
+#define T_CDS		ns_t_cds
+#define T_CDNSKEY	ns_t_cdnskey
+#define T_OPENPGPKEY	ns_t_openpgpkey
+#define T_CSYNC		ns_t_csync
+#define T_SPF		ns_t_spf
+#define T_UINFO		ns_t_uinfo
+#define T_UID		ns_t_uid
+#define T_GID		ns_t_gid
+#define T_UNSPEC	ns_t_unspec
+#define T_NID		ns_t_nid
+#define T_L32		ns_t_l32
+#define T_L64		ns_t_l64
+#define T_LP		ns_t_lp
+#define T_EUI48		ns_t_eui48
+#define T_EUI64		ns_t_eui64
+#define T_TKEY		ns_t_tkey
 #define	T_TSIG		ns_t_tsig
 #define	T_IXFR		ns_t_ixfr
 #define T_AXFR		ns_t_axfr
 #define T_MAILB		ns_t_mailb
 #define T_MAILA		ns_t_maila
 #define T_ANY		ns_t_any
+#define T_URI		ns_t_uri
+#define T_CAA		ns_t_caa
+#define T_AVC		ns_t_avc
+#define T_TA		ns_t_ta
+#define T_DLV		ns_t_dlv
 
 #define C_IN		ns_c_in
 #define C_CHAOS		ns_c_chaos
lib/libc/musl/include/sys/mman.h
@@ -141,7 +141,7 @@ int mincore (void *, size_t, unsigned char *);
 int shm_open (const char *, int, mode_t);
 int shm_unlink (const char *);
 
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define mmap64 mmap
 #define off64_t off_t
 #endif
lib/libc/musl/include/sys/resource.h
@@ -95,7 +95,7 @@ int prlimit(pid_t, int, const struct rlimit *, struct rlimit *);
 
 #define RLIM_NLIMITS RLIMIT_NLIMITS
 
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define RLIM64_INFINITY RLIM_INFINITY
 #define RLIM64_SAVED_CUR RLIM_SAVED_CUR
 #define RLIM64_SAVED_MAX RLIM_SAVED_MAX
lib/libc/musl/include/sys/sendfile.h
@@ -10,7 +10,7 @@ extern "C" {
 
 ssize_t sendfile(int, int, off_t *, size_t);
 
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define sendfile64 sendfile
 #define off64_t off_t
 #endif
lib/libc/musl/include/sys/stat.h
@@ -98,7 +98,7 @@ int lchmod(const char *, mode_t);
 #define S_IEXEC S_IXUSR
 #endif
 
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define stat64 stat
 #define fstat64 fstat
 #define lstat64 lstat
lib/libc/musl/include/sys/statfs.h
@@ -18,7 +18,7 @@ typedef struct __fsid_t {
 int statfs (const char *, struct statfs *);
 int fstatfs (int, struct statfs *);
 
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define statfs64 statfs
 #define fstatfs64 fstatfs
 #define fsblkcnt64_t fsblkcnt_t
lib/libc/musl/include/sys/statvfs.h
@@ -42,7 +42,7 @@ int fstatvfs (int, struct statvfs *);
 #define ST_NODIRATIME  2048
 #define ST_RELATIME    4096
 
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define statvfs64 statvfs
 #define fstatvfs64 fstatvfs
 #define fsblkcnt64_t fsblkcnt_t
lib/libc/musl/include/sys/types.h
@@ -71,7 +71,7 @@ typedef unsigned long long u_quad_t;
 #include <sys/select.h>
 #endif
 
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define blkcnt64_t blkcnt_t
 #define fsblkcnt64_t fsblkcnt_t
 #define fsfilcnt64_t fsfilcnt_t
lib/libc/musl/include/sys/uio.h
@@ -29,7 +29,7 @@ ssize_t writev (int, const struct iovec *, int);
 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
 ssize_t preadv (int, const struct iovec *, int, off_t);
 ssize_t pwritev (int, const struct iovec *, int, off_t);
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define preadv64 preadv
 #define pwritev64 pwritev
 #define off64_t off_t
lib/libc/musl/include/sys/wait.h
@@ -50,7 +50,7 @@ pid_t wait4 (pid_t, int *, int, struct rusage *);
 #define WSTOPSIG(s) WEXITSTATUS(s)
 #define WCOREDUMP(s) ((s) & 0x80)
 #define WIFEXITED(s) (!WTERMSIG(s))
-#define WIFSTOPPED(s) ((short)((((s)&0xffff)*0x10001)>>8) > 0x7f00)
+#define WIFSTOPPED(s) ((short)((((s)&0xffff)*0x10001U)>>8) > 0x7f00)
 #define WIFSIGNALED(s) (((s)&0xffff)-1U < 0xffu)
 #define WIFCONTINUED(s) ((s) == 0xffff)
 
lib/libc/musl/include/aio.h
@@ -49,7 +49,7 @@ int aio_fsync(int, struct aiocb *);
 
 int lio_listio(int, struct aiocb *__restrict const *__restrict, int, struct sigevent *__restrict);
 
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define aiocb64 aiocb
 #define aio_read64 aio_read
 #define aio_write64 aio_write
lib/libc/musl/include/dirent.h
@@ -56,7 +56,7 @@ int getdents(int, struct dirent *, size_t);
 int versionsort(const struct dirent **, const struct dirent **);
 #endif
 
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define dirent64 dirent
 #define readdir64 readdir
 #define readdir64_r readdir_r
lib/libc/musl/include/elf.h
@@ -385,7 +385,8 @@ typedef struct {
 #define SHT_PREINIT_ARRAY 16
 #define SHT_GROUP	  17
 #define SHT_SYMTAB_SHNDX  18
-#define	SHT_NUM		  19
+#define SHT_RELR	  19
+#define	SHT_NUM		  20
 #define SHT_LOOS	  0x60000000
 #define SHT_GNU_ATTRIBUTES 0x6ffffff5
 #define SHT_GNU_HASH	  0x6ffffff6
@@ -436,6 +437,7 @@ typedef struct {
 } Elf64_Chdr;
 
 #define ELFCOMPRESS_ZLIB	1
+#define ELFCOMPRESS_ZSTD	2
 #define ELFCOMPRESS_LOOS	0x60000000
 #define ELFCOMPRESS_HIOS	0x6fffffff
 #define ELFCOMPRESS_LOPROC	0x70000000
@@ -754,7 +756,10 @@ typedef struct {
 #define DT_PREINIT_ARRAY 32
 #define DT_PREINIT_ARRAYSZ 33
 #define DT_SYMTAB_SHNDX	34
-#define	DT_NUM		35
+#define DT_RELRSZ	35
+#define DT_RELR		36
+#define DT_RELRENT	37
+#define	DT_NUM		38
 #define DT_LOOS		0x6000000d
 #define DT_HIOS		0x6ffff000
 #define DT_LOPROC	0x70000000
lib/libc/musl/include/fcntl.h
@@ -195,7 +195,7 @@ ssize_t tee(int, int, size_t, unsigned);
 #define loff_t off_t
 #endif
 
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define F_GETLK64 F_GETLK
 #define F_SETLK64 F_SETLK
 #define F_SETLKW64 F_SETLKW
lib/libc/musl/include/ftw.h
@@ -29,7 +29,7 @@ struct FTW {
 int ftw(const char *, int (*)(const char *, const struct stat *, int), int);
 int nftw(const char *, int (*)(const char *, const struct stat *, int, struct FTW *), int, int);
 
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define ftw64 ftw
 #define nftw64 nftw
 #endif
lib/libc/musl/include/glob.h
@@ -39,7 +39,7 @@ void globfree(glob_t *);
 #define GLOB_NOMATCH 3
 #define GLOB_NOSYS   4
 
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define glob64 glob
 #define globfree64 globfree
 #define glob64_t glob_t
lib/libc/musl/include/netdb.h
@@ -44,6 +44,7 @@ struct addrinfo {
 #define EAI_NONAME     -2
 #define EAI_AGAIN      -3
 #define EAI_FAIL       -4
+#define EAI_NODATA     -5
 #define EAI_FAMILY     -6
 #define EAI_SOCKTYPE   -7
 #define EAI_SERVICE    -8
lib/libc/musl/include/sched.h
@@ -124,7 +124,7 @@ __CPU_op_func_S(XOR, ^)
 #define CPU_ALLOC(n) ((cpu_set_t *)calloc(1,CPU_ALLOC_SIZE(n)))
 #define CPU_FREE(set) free(set)
 
-#define CPU_SETSIZE 128
+#define CPU_SETSIZE 1024
 
 #define CPU_SET(i, set) CPU_SET_S(i,sizeof(cpu_set_t),set)
 #define CPU_CLR(i, set) CPU_CLR_S(i,sizeof(cpu_set_t),set)
lib/libc/musl/include/stdio.h
@@ -205,7 +205,7 @@ typedef struct _IO_cookie_io_functions_t {
 FILE *fopencookie(void *, const char *, cookie_io_functions_t);
 #endif
 
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define tmpfile64 tmpfile
 #define fopen64 fopen
 #define freopen64 freopen
lib/libc/musl/include/stdlib.h
@@ -95,7 +95,7 @@ size_t __ctype_get_mb_cur_max(void);
 #define WTERMSIG(s) ((s) & 0x7f)
 #define WSTOPSIG(s) WEXITSTATUS(s)
 #define WIFEXITED(s) (!WTERMSIG(s))
-#define WIFSTOPPED(s) ((short)((((s)&0xffff)*0x10001)>>8) > 0x7f00)
+#define WIFSTOPPED(s) ((short)((((s)&0xffff)*0x10001U)>>8) > 0x7f00)
 #define WIFSIGNALED(s) (((s)&0xffff)-1U < 0xffu)
 
 int posix_memalign (void **, size_t, size_t);
@@ -163,7 +163,7 @@ double strtod_l(const char *__restrict, char **__restrict, struct __locale_struc
 long double strtold_l(const char *__restrict, char **__restrict, struct __locale_struct *);
 #endif
 
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define mkstemp64 mkstemp
 #define mkostemp64 mkostemp
 #if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
lib/libc/musl/include/string.h
@@ -73,6 +73,7 @@ char *strsignal(int);
 char *strerror_l (int, locale_t);
 int strcoll_l (const char *, const char *, locale_t);
 size_t strxfrm_l (char *__restrict, const char *__restrict, size_t, locale_t);
+void *memmem(const void *, size_t, const void *, size_t);
 #endif
 
 #if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE) \
@@ -92,7 +93,6 @@ void explicit_bzero (void *, size_t);
 int strverscmp (const char *, const char *);
 char *strchrnul(const char *, int);
 char *strcasestr(const char *, const char *);
-void *memmem(const void *, size_t, const void *, size_t);
 void *memrchr(const void *, int, size_t);
 void *mempcpy(void *, const void *, size_t);
 #ifndef __cplusplus
lib/libc/musl/include/strings.h
@@ -5,6 +5,7 @@
 extern "C" {
 #endif
 
+#include <features.h>
 
 #define __NEED_size_t
 #define __NEED_locale_t
lib/libc/musl/include/unistd.h
@@ -198,7 +198,7 @@ ssize_t copy_file_range(int, off_t *, int, off_t *, size_t, unsigned);
 pid_t gettid(void);
 #endif
 
-#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#if defined(_LARGEFILE64_SOURCE)
 #define lseek64 lseek
 #define pread64 pread
 #define pwrite64 pwrite
@@ -425,6 +425,8 @@ pid_t gettid(void);
 #define _SC_XOPEN_STREAMS	246
 #define _SC_THREAD_ROBUST_PRIO_INHERIT	247
 #define _SC_THREAD_ROBUST_PRIO_PROTECT	248
+#define _SC_MINSIGSTKSZ	249
+#define _SC_SIGSTKSZ	250
 
 #define _CS_PATH	0
 #define _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS	1
@@ -467,6 +469,8 @@ pid_t gettid(void);
 #define _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS	1147
 #define _CS_V6_ENV	1148
 #define _CS_V7_ENV	1149
+#define _CS_POSIX_V7_THREADS_CFLAGS	1150
+#define _CS_POSIX_V7_THREADS_LDFLAGS	1151
 
 #ifdef __cplusplus
 }
lib/libc/musl/src/aio/aio.c
@@ -82,6 +82,8 @@ static size_t io_thread_stack_size;
 
 static struct aio_queue *__aio_get_queue(int fd, int need)
 {
+	sigset_t allmask, origmask;
+	int masked = 0;
 	if (fd < 0) {
 		errno = EBADF;
 		return 0;
@@ -93,6 +95,9 @@ static struct aio_queue *__aio_get_queue(int fd, int need)
 	if ((!map || !map[a] || !map[a][b] || !map[a][b][c] || !(q=map[a][b][c][d])) && need) {
 		pthread_rwlock_unlock(&maplock);
 		if (fcntl(fd, F_GETFD) < 0) return 0;
+		sigfillset(&allmask);
+		masked = 1;
+		pthread_sigmask(SIG_BLOCK, &allmask, &origmask);
 		pthread_rwlock_wrlock(&maplock);
 		if (!io_thread_stack_size) {
 			unsigned long val = __getauxval(AT_MINSIGSTKSZ);
@@ -119,6 +124,7 @@ static struct aio_queue *__aio_get_queue(int fd, int need)
 	if (q) pthread_mutex_lock(&q->lock);
 out:
 	pthread_rwlock_unlock(&maplock);
+	if (masked) pthread_sigmask(SIG_SETMASK, &origmask, 0);
 	return q;
 }
 
@@ -401,18 +407,26 @@ void __aio_atfork(int who)
 	if (who<0) {
 		pthread_rwlock_rdlock(&maplock);
 		return;
+	} else if (!who) {
+		pthread_rwlock_unlock(&maplock);
+		return;
 	}
-	if (who>0 && map) for (int a=0; a<(-1U/2+1)>>24; a++)
+	aio_fd_cnt = 0;
+	if (pthread_rwlock_tryrdlock(&maplock)) {
+		/* Obtaining lock may fail if _Fork was called nor via
+		 * fork. In this case, no further aio is possible from
+		 * child and we can just null out map so __aio_close
+		 * does not attempt to do anything. */
+		map = 0;
+		return;
+	}
+	if (map) for (int a=0; a<(-1U/2+1)>>24; a++)
 		if (map[a]) for (int b=0; b<256; b++)
 			if (map[a][b]) for (int c=0; c<256; c++)
 				if (map[a][b][c]) for (int d=0; d<256; d++)
 					map[a][b][c][d] = 0;
-	pthread_rwlock_unlock(&maplock);
+	/* Re-initialize the rwlock rather than unlocking since there
+	 * may have been more than one reference on it in the parent.
+	 * We are not a lock holder anyway; the thread in the parent was. */
+	pthread_rwlock_init(&maplock, 0);
 }
-
-weak_alias(aio_cancel, aio_cancel64);
-weak_alias(aio_error, aio_error64);
-weak_alias(aio_fsync, aio_fsync64);
-weak_alias(aio_read, aio_read64);
-weak_alias(aio_write, aio_write64);
-weak_alias(aio_return, aio_return64);
lib/libc/musl/src/aio/aio_suspend.c
@@ -9,7 +9,7 @@ int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec
 {
 	int i, tid = 0, ret, expect = 0;
 	struct timespec at;
-	volatile int dummy_fut, *pfut;
+	volatile int dummy_fut = 0, *pfut;
 	int nzcnt = 0;
 	const struct aiocb *cb = 0;
 
@@ -73,7 +73,3 @@ int aio_suspend(const struct aiocb *const cbs[], int cnt, const struct timespec
 		}
 	}
 }
-
-#if !_REDIR_TIME64
-weak_alias(aio_suspend, aio_suspend64);
-#endif
lib/libc/musl/src/aio/lio_listio.c
@@ -139,5 +139,3 @@ int lio_listio(int mode, struct aiocb *restrict const *restrict cbs, int cnt, st
 
 	return 0;
 }
-
-weak_alias(lio_listio, lio_listio64);
lib/libc/musl/src/conf/confstr.c
@@ -7,7 +7,7 @@ size_t confstr(int name, char *buf, size_t len)
 	const char *s = "";
 	if (!name) {
 		s = "/bin:/usr/bin";
-	} else if ((name&~4U)!=1 && name-_CS_POSIX_V6_ILP32_OFF32_CFLAGS>33U) {
+	} else if ((name&~4U)!=1 && name-_CS_POSIX_V6_ILP32_OFF32_CFLAGS>35U) {
 		errno = EINVAL;
 		return 0;
 	}
lib/libc/musl/src/conf/sysconf.c
@@ -4,6 +4,7 @@
 #include <sys/resource.h>
 #include <signal.h>
 #include <sys/sysinfo.h>
+#include <sys/auxv.h>
 #include "syscall.h"
 #include "libc.h"
 
@@ -19,6 +20,8 @@
 #define JT_AVPHYS_PAGES JT(9)
 #define JT_ZERO JT(10)
 #define JT_DELAYTIMER_MAX JT(11)
+#define JT_MINSIGSTKSZ JT(12)
+#define JT_SIGSTKSZ JT(13)
 
 #define RLIM(x) (-32768|(RLIMIT_ ## x))
 
@@ -165,6 +168,9 @@ long sysconf(int name)
 		[_SC_XOPEN_STREAMS] = JT_ZERO,
 		[_SC_THREAD_ROBUST_PRIO_INHERIT] = -1,
 		[_SC_THREAD_ROBUST_PRIO_PROTECT] = -1,
+
+		[_SC_MINSIGSTKSZ] = JT_MINSIGSTKSZ,
+		[_SC_SIGSTKSZ] = JT_SIGSTKSZ,
 	};
 
 	if (name >= sizeof(values)/sizeof(values[0]) || !values[name]) {
@@ -212,6 +218,13 @@ long sysconf(int name)
 		mem *= si.mem_unit;
 		mem /= PAGE_SIZE;
 		return (mem > LONG_MAX) ? LONG_MAX : mem;
+	case JT_MINSIGSTKSZ & 255:
+	case JT_SIGSTKSZ & 255: ;
+		long val = __getauxval(AT_MINSIGSTKSZ);
+		if (val < MINSIGSTKSZ) val = MINSIGSTKSZ;
+		if (values[name] == JT_SIGSTKSZ)
+			val += SIGSTKSZ - MINSIGSTKSZ;
+		return val;
 	case JT_ZERO & 255:
 		return 0;
 	}
lib/libc/musl/src/dirent/alphasort.c
@@ -5,5 +5,3 @@ int alphasort(const struct dirent **a, const struct dirent **b)
 {
 	return strcoll((*a)->d_name, (*b)->d_name);
 }
-
-weak_alias(alphasort, alphasort64);
lib/libc/musl/src/dirent/readdir.c
@@ -25,5 +25,3 @@ struct dirent *readdir(DIR *dir)
 	dir->tell = de->d_off;
 	return de;
 }
-
-weak_alias(readdir, readdir64);
lib/libc/musl/src/dirent/readdir_r.c
@@ -25,5 +25,3 @@ int readdir_r(DIR *restrict dir, struct dirent *restrict buf, struct dirent **re
 	*result = buf;
 	return 0;
 }
-
-weak_alias(readdir_r, readdir64_r);
lib/libc/musl/src/dirent/scandir.c
@@ -43,5 +43,3 @@ int scandir(const char *path, struct dirent ***res,
 	*res = names;
 	return cnt;
 }
-
-weak_alias(scandir, scandir64);
lib/libc/musl/src/dirent/versionsort.c
@@ -6,6 +6,3 @@ int versionsort(const struct dirent **a, const struct dirent **b)
 {
 	return strverscmp((*a)->d_name, (*b)->d_name);
 }
-
-#undef versionsort64
-weak_alias(versionsort, versionsort64);
lib/libc/musl/src/fcntl/creat.c
@@ -4,5 +4,3 @@ int creat(const char *filename, mode_t mode)
 {
 	return open(filename, O_CREAT|O_WRONLY|O_TRUNC, mode);
 }
-
-weak_alias(creat, creat64);
lib/libc/musl/src/fcntl/open.c
@@ -19,5 +19,3 @@ int open(const char *filename, int flags, ...)
 
 	return __syscall_ret(fd);
 }
-
-weak_alias(open, open64);
lib/libc/musl/src/fcntl/openat.c
@@ -15,5 +15,3 @@ int openat(int fd, const char *filename, int flags, ...)
 
 	return syscall_cp(SYS_openat, fd, filename, flags|O_LARGEFILE, mode);
 }
-
-weak_alias(openat, openat64);
lib/libc/musl/src/fcntl/posix_fadvise.c
@@ -14,5 +14,3 @@ int posix_fadvise(int fd, off_t base, off_t len, int advice)
 		__SYSCALL_LL_E(len), advice);
 #endif
 }
-
-weak_alias(posix_fadvise, posix_fadvise64);
lib/libc/musl/src/fcntl/posix_fallocate.c
@@ -6,5 +6,3 @@ int posix_fallocate(int fd, off_t base, off_t len)
 	return -__syscall(SYS_fallocate, fd, 0, __SYSCALL_LL_E(base),
 		__SYSCALL_LL_E(len));
 }
-
-weak_alias(posix_fallocate, posix_fallocate64);
lib/libc/musl/src/include/sys/stat.h
@@ -0,0 +1,9 @@
+#ifndef SYS_STAT_H
+#define SYS_STAT_H
+
+#include "../../../include/sys/stat.h"
+
+hidden int __fstat(int, struct stat *);
+hidden int __fstatat(int, const char *restrict, struct stat *restrict, int);
+
+#endif
lib/libc/musl/src/internal/dynlink.h
@@ -92,8 +92,12 @@ struct fdpic_dummy_loadmap {
 #define DT_DEBUG_INDIRECT 0
 #endif
 
+#ifndef DT_DEBUG_INDIRECT_REL
+#define DT_DEBUG_INDIRECT_REL 0
+#endif
+
 #define AUX_CNT 32
-#define DYN_CNT 32
+#define DYN_CNT 37
 
 typedef void (*stage2_func)(unsigned char *, size_t *);
 
lib/libc/musl/src/internal/fork_impl.h
@@ -2,7 +2,6 @@
 
 extern hidden volatile int *const __at_quick_exit_lockptr;
 extern hidden volatile int *const __atexit_lockptr;
-extern hidden volatile int *const __dlerror_lockptr;
 extern hidden volatile int *const __gettext_lockptr;
 extern hidden volatile int *const __locale_lockptr;
 extern hidden volatile int *const __random_lockptr;
@@ -17,3 +16,4 @@ extern hidden volatile int *const __vmlock_lockptr;
 
 hidden void __malloc_atfork(int);
 hidden void __ldso_atfork(int);
+hidden void __pthread_key_atfork(int);
lib/libc/musl/src/internal/ksigaction.h
@@ -6,8 +6,13 @@
 struct k_sigaction {
 	void (*handler)(int);
 	unsigned long flags;
+#ifdef SA_RESTORER
 	void (*restorer)(void);
+#endif
 	unsigned mask[2];
+#ifndef SA_RESTORER
+	void *unused;
+#endif
 };
 
 hidden void __restore(), __restore_rt();
lib/libc/musl/src/internal/syscall.h
@@ -58,7 +58,7 @@ hidden long __syscall_ret(unsigned long),
 #define __syscall_cp(...) __SYSCALL_DISP(__syscall_cp,__VA_ARGS__)
 #define syscall_cp(...) __syscall_ret(__syscall_cp(__VA_ARGS__))
 
-static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, long c, long d, long e, long f)
+static inline long __alt_socketcall(int sys, int sock, int cp, syscall_arg_t a, syscall_arg_t b, syscall_arg_t c, syscall_arg_t d, syscall_arg_t e, syscall_arg_t f)
 {
 	long r;
 	if (cp) r = __syscall_cp(sys, a, b, c, d, e, f);
@@ -71,9 +71,9 @@ static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, l
 	return r;
 }
 #define __socketcall(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 0, \
-	(long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f))
+	__scc(a), __scc(b), __scc(c), __scc(d), __scc(e), __scc(f))
 #define __socketcall_cp(nm, a, b, c, d, e, f) __alt_socketcall(SYS_##nm, __SC_##nm, 1, \
-	(long)(a), (long)(b), (long)(c), (long)(d), (long)(e), (long)(f))
+	__scc(a), __scc(b), __scc(c), __scc(d), __scc(e), __scc(f))
 
 /* fixup legacy 16-bit junk */
 
@@ -201,43 +201,43 @@ static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, l
 #define SYS_sendfile SYS_sendfile64
 #endif
 
-#ifndef SYS_timer_settime
+#ifdef SYS_timer_settime32
 #define SYS_timer_settime SYS_timer_settime32
 #endif
 
-#ifndef SYS_timer_gettime
+#ifdef SYS_timer_gettime32
 #define SYS_timer_gettime SYS_timer_gettime32
 #endif
 
-#ifndef SYS_timerfd_settime
+#ifdef SYS_timerfd_settime32
 #define SYS_timerfd_settime SYS_timerfd_settime32
 #endif
 
-#ifndef SYS_timerfd_gettime
+#ifdef SYS_timerfd_gettime32
 #define SYS_timerfd_gettime SYS_timerfd_gettime32
 #endif
 
-#ifndef SYS_clock_settime
+#ifdef SYS_clock_settime32
 #define SYS_clock_settime SYS_clock_settime32
 #endif
 
-#ifndef SYS_clock_gettime
+#ifdef SYS_clock_gettime32
 #define SYS_clock_gettime SYS_clock_gettime32
 #endif
 
-#ifndef SYS_clock_getres
+#ifdef SYS_clock_getres_time32
 #define SYS_clock_getres SYS_clock_getres_time32
 #endif
 
-#ifndef SYS_clock_nanosleep
+#ifdef SYS_clock_nanosleep_time32
 #define SYS_clock_nanosleep SYS_clock_nanosleep_time32
 #endif
 
-#ifndef SYS_gettimeofday
+#ifdef SYS_gettimeofday_time32
 #define SYS_gettimeofday SYS_gettimeofday_time32
 #endif
 
-#ifndef SYS_settimeofday
+#ifdef SYS_settimeofday_time32
 #define SYS_settimeofday SYS_settimeofday_time32
 #endif
 
lib/libc/musl/src/internal/version.h
@@ -1,1 +1,1 @@
-#define VERSION "1.2.3"
+#define VERSION "1.2.4"
lib/libc/musl/src/ipc/semtimedop.c
@@ -7,7 +7,8 @@
 #define IS32BIT(x) !((x)+0x80000000ULL>>32)
 #define CLAMP(x) (int)(IS32BIT(x) ? (x) : 0x7fffffffU+((0ULL+(x))>>63))
 
-#if !defined(SYS_semtimedop) && !defined(SYS_ipc)
+#if !defined(SYS_semtimedop) && !defined(SYS_ipc) || \
+	SYS_semtimedop == SYS_semtimedop_time64
 #define NO_TIME32 1
 #else
 #define NO_TIME32 0
lib/libc/musl/src/ldso/dlerror.c
@@ -3,8 +3,7 @@
 #include <stdarg.h>
 #include "pthread_impl.h"
 #include "dynlink.h"
-#include "lock.h"
-#include "fork_impl.h"
+#include "atomic.h"
 
 #define malloc __libc_malloc
 #define calloc __libc_calloc
@@ -23,28 +22,31 @@ char *dlerror()
 		return s;
 }
 
-static volatile int freebuf_queue_lock[1];
-static void **freebuf_queue;
-volatile int *const __dlerror_lockptr = freebuf_queue_lock;
+/* Atomic singly-linked list, used to store list of thread-local dlerror
+ * buffers for deferred free. They cannot be freed at thread exit time
+ * because, by the time it's known they can be freed, the exiting thread
+ * is in a highly restrictive context where it cannot call (even the
+ * libc-internal) free. It also can't take locks; thus the atomic list. */
+
+static void *volatile freebuf_queue;
 
 void __dl_thread_cleanup(void)
 {
 	pthread_t self = __pthread_self();
-	if (self->dlerror_buf && self->dlerror_buf != (void *)-1) {
-		LOCK(freebuf_queue_lock);
-		void **p = (void **)self->dlerror_buf;
-		*p = freebuf_queue;
-		freebuf_queue = p;
-		UNLOCK(freebuf_queue_lock);
-	}
+	if (!self->dlerror_buf || self->dlerror_buf == (void *)-1)
+		return;
+	void *h;
+	do {
+		h = freebuf_queue;
+		*(void **)self->dlerror_buf = h;
+	} while (a_cas_p(&freebuf_queue, h, self->dlerror_buf) != h);
 }
 
 hidden void __dl_vseterr(const char *fmt, va_list ap)
 {
-	LOCK(freebuf_queue_lock);
-	void **q = freebuf_queue;
-	freebuf_queue = 0;
-	UNLOCK(freebuf_queue_lock);
+	void **q;
+	do q = freebuf_queue;
+	while (q && a_cas_p(&freebuf_queue, q, 0) != q);
 
 	while (q) {
 		void **p = *q;
lib/libc/musl/src/legacy/ftw.c
@@ -7,5 +7,3 @@ int ftw(const char *path, int (*fn)(const char *, const struct stat *, int), int
 	 * actually undefined, but works on all real-world machines. */
 	return nftw(path, (int (*)())fn, fd_limit, FTW_PHYS);
 }
-
-weak_alias(ftw, ftw64);
lib/libc/musl/src/linux/epoll.c
@@ -5,6 +5,7 @@
 
 int epoll_create(int size)
 {
+	if (size<=0) return __syscall_ret(-EINVAL);
 	return epoll_create1(0);
 }
 
lib/libc/musl/src/linux/fallocate.c
@@ -7,6 +7,3 @@ int fallocate(int fd, int mode, off_t base, off_t len)
 	return syscall(SYS_fallocate, fd, mode, __SYSCALL_LL_E(base),
 		__SYSCALL_LL_E(len));
 }
-
-#undef fallocate64
-weak_alias(fallocate, fallocate64);
lib/libc/musl/src/linux/getdents.c
@@ -8,5 +8,3 @@ int getdents(int fd, struct dirent *buf, size_t len)
 	if (len>INT_MAX) len = INT_MAX;
 	return syscall(SYS_getdents, fd, buf, len);
 }
-
-weak_alias(getdents, getdents64);
lib/libc/musl/src/linux/membarrier.c
@@ -35,7 +35,7 @@ int __membarrier(int cmd, int flags)
 		__tl_lock();
 		sem_init(&barrier_sem, 0, 0);
 		struct sigaction sa = {
-			.sa_flags = SA_RESTART,
+			.sa_flags = SA_RESTART | SA_ONSTACK,
 			.sa_handler = bcast_barrier
 		};
 		memset(&sa.sa_mask, -1, sizeof sa.sa_mask);
lib/libc/musl/src/linux/prlimit.c
@@ -21,6 +21,3 @@ int prlimit(pid_t pid, int resource, const struct rlimit *new_limit, struct rlim
 	}
 	return r;
 }
-
-#undef prlimit64
-weak_alias(prlimit, prlimit64);
lib/libc/musl/src/linux/sendfile.c
@@ -5,5 +5,3 @@ ssize_t sendfile(int out_fd, int in_fd, off_t *ofs, size_t count)
 {
 	return syscall(SYS_sendfile, out_fd, in_fd, ofs, count);
 }
-
-weak_alias(sendfile, sendfile64);
lib/libc/musl/src/linux/wait4.c
@@ -12,7 +12,7 @@ pid_t wait4(pid_t pid, int *status, int options, struct rusage *ru)
 	if (ru) {
 		long long kru64[18];
 		r = __syscall(SYS_wait4_time64, pid, status, options, kru64);
-		if (!r) {
+		if (r > 0) {
 			ru->ru_utime = (struct timeval)
 				{ .tv_sec = kru64[0], .tv_usec = kru64[1] };
 			ru->ru_stime = (struct timeval)
lib/libc/musl/src/malloc/mallocng/free.c
@@ -119,7 +119,7 @@ void free(void *p)
 	if (((uintptr_t)(start-1) ^ (uintptr_t)end) >= 2*PGSZ && g->last_idx) {
 		unsigned char *base = start + (-(uintptr_t)start & (PGSZ-1));
 		size_t len = (end-base) & -PGSZ;
-		if (len) {
+		if (len && USE_MADV_FREE) {
 			int e = errno;
 			madvise(base, len, MADV_FREE);
 			errno = e;
lib/libc/musl/src/malloc/mallocng/glue.h
@@ -24,6 +24,8 @@
 #define realloc __libc_realloc
 #define free __libc_free
 
+#define USE_MADV_FREE 0
+
 #if USE_REAL_ASSERT
 #include <assert.h>
 #else
lib/libc/musl/src/math/logf.c
@@ -53,7 +53,7 @@ float logf(float x)
 	tmp = ix - OFF;
 	i = (tmp >> (23 - LOGF_TABLE_BITS)) % N;
 	k = (int32_t)tmp >> 23; /* arithmetic shift */
-	iz = ix - (tmp & 0x1ff << 23);
+	iz = ix - (tmp & 0xff800000);
 	invc = T[i].invc;
 	logc = T[i].logc;
 	z = (double_t)asfloat(iz);
lib/libc/musl/src/misc/getopt.c
@@ -87,7 +87,8 @@ int getopt(int argc, char * const argv[], const char *optstring)
 	if (optstring[i] == ':') {
 		optarg = 0;
 		if (optstring[i+1] != ':' || optpos) {
-			optarg = argv[optind++] + optpos;
+			optarg = argv[optind++];
+			if (optpos) optarg += optpos;
 			optpos = 0;
 		}
 		if (optind > argc) {
lib/libc/musl/src/misc/getrlimit.c
@@ -6,12 +6,13 @@
 
 int getrlimit(int resource, struct rlimit *rlim)
 {
-	unsigned long k_rlim[2];
 	int ret = syscall(SYS_prlimit64, 0, resource, 0, rlim);
 	if (!ret) {
 		FIX(rlim->rlim_cur);
 		FIX(rlim->rlim_max);
 	}
+#ifdef SYS_getrlimit
+	unsigned long k_rlim[2];
 	if (!ret || errno != ENOSYS)
 		return ret;
 	if (syscall(SYS_getrlimit, resource, k_rlim) < 0)
@@ -21,6 +22,7 @@ int getrlimit(int resource, struct rlimit *rlim)
 	FIX(rlim->rlim_cur);
 	FIX(rlim->rlim_max);
 	return 0;
+#else
+	return ret;
+#endif
 }
-
-weak_alias(getrlimit, getrlimit64);
lib/libc/musl/src/misc/lockf.c
@@ -28,5 +28,3 @@ int lockf(int fd, int op, off_t size)
 	errno = EINVAL;
 	return -1;
 }
-
-weak_alias(lockf, lockf64);
lib/libc/musl/src/misc/mntent.c
@@ -2,6 +2,7 @@
 #include <string.h>
 #include <mntent.h>
 #include <errno.h>
+#include <limits.h>
 
 static char *internal_buf;
 static size_t internal_bufsize;
@@ -21,7 +22,8 @@ int endmntent(FILE *f)
 
 struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int buflen)
 {
-	int cnt, n[8], use_internal = (linebuf == SENTINEL);
+	int n[8], use_internal = (linebuf == SENTINEL);
+	size_t len, i;
 
 	mnt->mnt_freq = 0;
 	mnt->mnt_passno = 0;
@@ -39,10 +41,14 @@ struct mntent *getmntent_r(FILE *f, struct mntent *mnt, char *linebuf, int bufle
 			errno = ERANGE;
 			return 0;
 		}
-		cnt = sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d",
+
+		len = strlen(linebuf);
+		if (len > INT_MAX) continue;
+		for (i = 0; i < sizeof n / sizeof *n; i++) n[i] = len;
+		sscanf(linebuf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d",
 			n, n+1, n+2, n+3, n+4, n+5, n+6, n+7,
 			&mnt->mnt_freq, &mnt->mnt_passno);
-	} while (cnt < 2 || linebuf[n[0]] == '#');
+	} while (linebuf[n[0]] == '#' || n[1]==len);
 
 	linebuf[n[1]] = 0;
 	linebuf[n[3]] = 0;
lib/libc/musl/src/misc/nftw.c
@@ -31,6 +31,8 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int,
 	int err;
 	struct FTW lev;
 
+	st.st_dev = st.st_ino = 0;
+
 	if ((flags & FTW_PHYS) ? lstat(path, &st) : stat(path, &st) < 0) {
 		if (!(flags & FTW_PHYS) && errno==ENOENT && !lstat(path, &st))
 			type = FTW_SLN;
@@ -46,7 +48,7 @@ static int do_nftw(char *path, int (*fn)(const char *, const struct stat *, int,
 		type = FTW_F;
 	}
 
-	if ((flags & FTW_MOUNT) && h && st.st_dev != h->dev)
+	if ((flags & FTW_MOUNT) && h && type != FTW_NS && st.st_dev != h->dev)
 		return 0;
 	
 	new.chain = h;
@@ -138,5 +140,3 @@ int nftw(const char *path, int (*fn)(const char *, const struct stat *, int, str
 	pthread_setcancelstate(cs, 0);
 	return r;
 }
-
-weak_alias(nftw, nftw64);
lib/libc/musl/src/misc/setrlimit.c
@@ -12,12 +12,14 @@ struct ctx {
 	int err;
 };
 
+#ifdef SYS_setrlimit
 static void do_setrlimit(void *p)
 {
 	struct ctx *c = p;
 	if (c->err>0) return;
 	c->err = -__syscall(SYS_setrlimit, c->res, c->lim);
 }
+#endif
 
 int setrlimit(int resource, const struct rlimit *rlim)
 {
@@ -29,6 +31,7 @@ int setrlimit(int resource, const struct rlimit *rlim)
 		rlim = &tmp;
 	}
 	int ret = __syscall(SYS_prlimit64, 0, resource, rlim, 0);
+#ifdef SYS_setrlimit
 	if (ret != -ENOSYS) return __syscall_ret(ret);
 
 	struct ctx c = {
@@ -42,6 +45,7 @@ int setrlimit(int resource, const struct rlimit *rlim)
 		return -1;
 	}
 	return 0;
+#else
+	return __syscall_ret(ret);
+#endif
 }
-
-weak_alias(setrlimit, setrlimit64);
lib/libc/musl/src/mman/mmap.c
@@ -37,5 +37,3 @@ void *__mmap(void *start, size_t len, int prot, int flags, int fd, off_t off)
 }
 
 weak_alias(__mmap, mmap);
-
-weak_alias(mmap, mmap64);
lib/libc/musl/src/mq/mq_notify.c
@@ -4,11 +4,14 @@
 #include <sys/socket.h>
 #include <signal.h>
 #include <unistd.h>
+#include <semaphore.h>
 #include "syscall.h"
 
 struct args {
-	pthread_barrier_t barrier;
+	sem_t sem;
 	int sock;
+	mqd_t mqd;
+	int err;
 	const struct sigevent *sev;
 };
 
@@ -20,8 +23,19 @@ static void *start(void *p)
 	int s = args->sock;
 	void (*func)(union sigval) = args->sev->sigev_notify_function;
 	union sigval val = args->sev->sigev_value;
+	struct sigevent sev2;
+	static const char zeros[32];
+	int err;
+
+	sev2.sigev_notify = SIGEV_THREAD;
+	sev2.sigev_signo = s;
+	sev2.sigev_value.sival_ptr = (void *)&zeros;
+
+	args->err = err = -__syscall(SYS_mq_notify, args->mqd, &sev2);
+	sem_post(&args->sem);
+	if (err) return 0;
 
-	pthread_barrier_wait(&args->barrier);
+	pthread_detach(pthread_self());
 	n = recv(s, buf, sizeof(buf), MSG_NOSIGNAL|MSG_WAITALL);
 	close(s);
 	if (n==sizeof buf && buf[sizeof buf - 1] == 1)
@@ -35,8 +49,8 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev)
 	pthread_attr_t attr;
 	pthread_t td;
 	int s;
-	struct sigevent sev2;
-	static const char zeros[32];
+	int cs;
+	sigset_t allmask, origmask;
 
 	if (!sev || sev->sigev_notify != SIGEV_THREAD)
 		return syscall(SYS_mq_notify, mqd, sev);
@@ -44,30 +58,35 @@ int mq_notify(mqd_t mqd, const struct sigevent *sev)
 	s = socket(AF_NETLINK, SOCK_RAW|SOCK_CLOEXEC, 0);
 	if (s < 0) return -1;
 	args.sock = s;
+	args.mqd = mqd;
 
 	if (sev->sigev_notify_attributes) attr = *sev->sigev_notify_attributes;
 	else pthread_attr_init(&attr);
-	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
-	pthread_barrier_init(&args.barrier, 0, 2);
+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_JOINABLE);
+	sem_init(&args.sem, 0, 0);
 
+	sigfillset(&allmask);
+	pthread_sigmask(SIG_BLOCK, &allmask, &origmask);
 	if (pthread_create(&td, &attr, start, &args)) {
 		__syscall(SYS_close, s);
+		pthread_sigmask(SIG_SETMASK, &origmask, 0);
 		errno = EAGAIN;
 		return -1;
 	}
+	pthread_sigmask(SIG_SETMASK, &origmask, 0);
 
-	pthread_barrier_wait(&args.barrier);
-	pthread_barrier_destroy(&args.barrier);
-
-	sev2.sigev_notify = SIGEV_THREAD;
-	sev2.sigev_signo = s;
-	sev2.sigev_value.sival_ptr = (void *)&zeros;
+	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+	sem_wait(&args.sem);
+	sem_destroy(&args.sem);
 
-	if (syscall(SYS_mq_notify, mqd, &sev2) < 0) {
-		pthread_cancel(td);
+	if (args.err) {
 		__syscall(SYS_close, s);
+		pthread_join(td, 0);
+		pthread_setcancelstate(cs, 0);
+		errno = args.err;
 		return -1;
 	}
 
+	pthread_setcancelstate(cs, 0);
 	return 0;
 }
lib/libc/musl/src/network/accept4.c
@@ -9,6 +9,10 @@ int accept4(int fd, struct sockaddr *restrict addr, socklen_t *restrict len, int
 	if (!flg) return accept(fd, addr, len);
 	int ret = socketcall_cp(accept4, fd, addr, len, flg, 0, 0);
 	if (ret>=0 || (errno != ENOSYS && errno != EINVAL)) return ret;
+	if (flg & ~(SOCK_CLOEXEC|SOCK_NONBLOCK)) {
+		errno = EINVAL;
+		return -1;
+	}
 	ret = accept(fd, addr, len);
 	if (ret<0) return ret;
 	if (flg & SOCK_CLOEXEC)
lib/libc/musl/src/network/dns_parse.c
@@ -1,7 +1,7 @@
 #include <string.h>
 #include "lookup.h"
 
-int __dns_parse(const unsigned char *r, int rlen, int (*callback)(void *, int, const void *, int, const void *), void *ctx)
+int __dns_parse(const unsigned char *r, int rlen, int (*callback)(void *, int, const void *, int, const void *, int), void *ctx)
 {
 	int qdcount, ancount;
 	const unsigned char *p;
@@ -15,18 +15,18 @@ int __dns_parse(const unsigned char *r, int rlen, int (*callback)(void *, int, c
 	if (qdcount+ancount > 64) return -1;
 	while (qdcount--) {
 		while (p-r < rlen && *p-1U < 127) p++;
-		if (*p>193 || (*p==193 && p[1]>254) || p>r+rlen-6)
+		if (p>r+rlen-6 || *p>193 || (*p==193 && p[1]>254))
 			return -1;
 		p += 5 + !!*p;
 	}
 	while (ancount--) {
 		while (p-r < rlen && *p-1U < 127) p++;
-		if (*p>193 || (*p==193 && p[1]>254) || p>r+rlen-6)
+		if (p>r+rlen-12 || *p>193 || (*p==193 && p[1]>254))
 			return -1;
 		p += 1 + !!*p;
 		len = p[8]*256 + p[9];
-		if (p+len > r+rlen) return -1;
-		if (callback(ctx, p[1], p+10, len, r) < 0) return -1;
+		if (len+10 > r+rlen-p) return -1;
+		if (callback(ctx, p[1], p+10, len, r, rlen) < 0) return -1;
 		p += 10 + len;
 	}
 	return 0;
lib/libc/musl/src/network/gai_strerror.c
@@ -6,7 +6,7 @@ static const char msgs[] =
 	"Name does not resolve\0"
 	"Try again\0"
 	"Non-recoverable error\0"
-	"Unknown error\0"
+	"Name has no usable address\0"
 	"Unrecognized address family or invalid length\0"
 	"Unrecognized socket type\0"
 	"Unrecognized service\0"
lib/libc/musl/src/network/getaddrinfo.c
@@ -16,6 +16,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
 	char canon[256], *outcanon;
 	int nservs, naddrs, nais, canon_len, i, j, k;
 	int family = AF_UNSPEC, flags = 0, proto = 0, socktype = 0;
+	int no_family = 0;
 	struct aibuf *out;
 
 	if (!host && !serv) return EAI_NONAME;
@@ -66,9 +67,11 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
 				pthread_setcancelstate(
 					PTHREAD_CANCEL_DISABLE, &cs);
 				int r = connect(s, ta[i], tl[i]);
+				int saved_errno = errno;
 				pthread_setcancelstate(cs, 0);
 				close(s);
 				if (!r) continue;
+				errno = saved_errno;
 			}
 			switch (errno) {
 			case EADDRNOTAVAIL:
@@ -80,7 +83,7 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
 			default:
 				return EAI_SYSTEM;
 			}
-			if (family == tf[i]) return EAI_NONAME;
+			if (family == tf[i]) no_family = 1;
 			family = tf[1-i];
 		}
 	}
@@ -91,6 +94,8 @@ int getaddrinfo(const char *restrict host, const char *restrict serv, const stru
 	naddrs = __lookup_name(addrs, canon, host, family, flags);
 	if (naddrs < 0) return naddrs;
 
+	if (no_family) return EAI_NODATA;
+
 	nais = nservs * naddrs;
 	canon_len = strlen(canon);
 	out = calloc(1, nais * sizeof(*out) + canon_len + 1);
lib/libc/musl/src/network/gethostbyaddr.c
@@ -20,5 +20,5 @@ struct hostent *gethostbyaddr(const void *a, socklen_t l, int af)
 		err = gethostbyaddr_r(a, l, af, h,
 			(void *)(h+1), size-sizeof *h, &res, &h_errno);
 	} while (err == ERANGE);
-	return err ? 0 : h;
+	return res;
 }
lib/libc/musl/src/network/gethostbyaddr_r.c
@@ -54,9 +54,10 @@ int gethostbyaddr_r(const void *a, socklen_t l, int af,
 	case EAI_OVERFLOW:
 		return ERANGE;
 	default:
-	case EAI_MEMORY:
-	case EAI_SYSTEM:
 	case EAI_FAIL:
+		*err = NO_RECOVERY;
+		return EBADMSG;
+	case EAI_SYSTEM:
 		*err = NO_RECOVERY;
 		return errno;
 	case 0:
lib/libc/musl/src/network/gethostbyname2.c
@@ -21,5 +21,5 @@ struct hostent *gethostbyname2(const char *name, int af)
 		err = gethostbyname2_r(name, af, h,
 			(void *)(h+1), size-sizeof *h, &res, &h_errno);
 	} while (err == ERANGE);
-	return err ? 0 : h;
+	return res;
 }
lib/libc/musl/src/network/gethostbyname2_r.c
@@ -22,7 +22,10 @@ int gethostbyname2_r(const char *name, int af,
 	if (cnt<0) switch (cnt) {
 	case EAI_NONAME:
 		*err = HOST_NOT_FOUND;
-		return ENOENT;
+		return 0;
+	case EAI_NODATA:
+		*err = NO_DATA;
+		return 0;
 	case EAI_AGAIN:
 		*err = TRY_AGAIN;
 		return EAGAIN;
@@ -30,7 +33,6 @@ int gethostbyname2_r(const char *name, int af,
 	case EAI_FAIL:
 		*err = NO_RECOVERY;
 		return EBADMSG;
-	case EAI_MEMORY:
 	case EAI_SYSTEM:
 		*err = NO_RECOVERY;
 		return errno;
lib/libc/musl/src/network/getifaddrs.c
@@ -39,8 +39,8 @@ struct ifaddrs_storage {
 };
 
 struct ifaddrs_ctx {
-	struct ifaddrs_storage *first;
-	struct ifaddrs_storage *last;
+	struct ifaddrs *first;
+	struct ifaddrs *last;
 	struct ifaddrs_storage *hash[IFADDRS_HASH_SIZE];
 };
 
@@ -195,9 +195,9 @@ static int netlink_msg_to_ifaddr(void *pctx, struct nlmsghdr *h)
 	}
 
 	if (ifs->ifa.ifa_name) {
-		if (!ctx->first) ctx->first = ifs;
-		if (ctx->last) ctx->last->ifa.ifa_next = &ifs->ifa;
-		ctx->last = ifs;
+		if (!ctx->first) ctx->first = &ifs->ifa;
+		if (ctx->last) ctx->last->ifa_next = &ifs->ifa;
+		ctx->last = &ifs->ifa;
 	} else {
 		free(ifs);
 	}
@@ -210,7 +210,7 @@ int getifaddrs(struct ifaddrs **ifap)
 	int r;
 	memset(ctx, 0, sizeof *ctx);
 	r = __rtnetlink_enumerate(AF_UNSPEC, AF_UNSPEC, netlink_msg_to_ifaddr, ctx);
-	if (r == 0) *ifap = &ctx->first->ifa;
-	else freeifaddrs(&ctx->first->ifa);
+	if (r == 0) *ifap = ctx->first;
+	else freeifaddrs(ctx->first);
 	return r;
 }
lib/libc/musl/src/network/getnameinfo.c
@@ -58,6 +58,7 @@ static void reverse_hosts(char *buf, const unsigned char *a, unsigned scopeid, i
 		if ((p=strchr(line, '#'))) *p++='\n', *p=0;
 
 		for (p=line; *p && !isspace(*p); p++);
+		if (!*p) continue;
 		*p++ = 0;
 		if (__lookup_ipliteral(&iplit, line, AF_UNSPEC)<=0)
 			continue;
@@ -108,10 +109,10 @@ static void reverse_services(char *buf, int port, int dgram)
 	__fclose_ca(f);
 }
 
-static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet)
+static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet, int plen)
 {
 	if (rr != RR_PTR) return 0;
-	if (__dn_expand(packet, (const unsigned char *)packet + 512,
+	if (__dn_expand(packet, (const unsigned char *)packet + plen,
 	    data, c, 256) <= 0)
 		*(char *)c = 0;
 	return 0;
lib/libc/musl/src/network/getservbyport_r.c
@@ -26,7 +26,7 @@ int getservbyport_r(int port, const char *prots,
 	/* Align buffer */
 	i = (uintptr_t)buf & sizeof(char *)-1;
 	if (!i) i = sizeof(char *);
-	if (buflen < 3*sizeof(char *)-i)
+	if (buflen <= 3*sizeof(char *)-i)
 		return ERANGE;
 	buf += sizeof(char *)-i;
 	buflen -= sizeof(char *)-i;
@@ -46,6 +46,8 @@ int getservbyport_r(int port, const char *prots,
 	case EAI_MEMORY:
 	case EAI_SYSTEM:
 		return ENOMEM;
+	case EAI_OVERFLOW:
+		return ERANGE;
 	default:
 		return ENOENT;
 	case 0:
lib/libc/musl/src/network/inet_pton.c
@@ -54,6 +54,7 @@ int inet_pton(int af, const char *restrict s, void *restrict a0)
 			if (s[j]!='.' || (i<6 && brk<0)) return 0;
 			need_v4=1;
 			i++;
+			ip[i&7]=0;
 			break;
 		}
 		s += j+1;
lib/libc/musl/src/network/lookup.h
@@ -50,6 +50,6 @@ hidden int __lookup_ipliteral(struct address buf[static 1], const char *name, in
 hidden int __get_resolv_conf(struct resolvconf *, char *, size_t);
 hidden int __res_msend_rc(int, const unsigned char *const *, const int *, unsigned char *const *, int *, int, const struct resolvconf *);
 
-hidden int __dns_parse(const unsigned char *, int, int (*)(void *, int, const void *, int, const void *), void *);
+hidden int __dns_parse(const unsigned char *, int, int (*)(void *, int, const void *, int, const void *, int), void *);
 
 #endif
lib/libc/musl/src/network/lookup_ipliteral.c
@@ -15,7 +15,7 @@ int __lookup_ipliteral(struct address buf[static 1], const char *name, int famil
 	struct in6_addr a6;
 	if (__inet_aton(name, &a4) > 0) {
 		if (family == AF_INET6) /* wrong family */
-			return EAI_NONAME;
+			return EAI_NODATA;
 		memcpy(&buf[0].addr, &a4, sizeof a4);
 		buf[0].family = AF_INET;
 		buf[0].scopeid = 0;
@@ -34,7 +34,7 @@ int __lookup_ipliteral(struct address buf[static 1], const char *name, int famil
 	if (inet_pton(AF_INET6, name, &a6) <= 0)
 		return 0;
 	if (family == AF_INET) /* wrong family */
-		return EAI_NONAME;
+		return EAI_NODATA;
 
 	memcpy(&buf[0].addr, &a6, sizeof a6);
 	buf[0].family = AF_INET6;
lib/libc/musl/src/network/lookup_name.c
@@ -79,7 +79,7 @@ static int name_from_hosts(struct address buf[static MAXADDRS], char canon[stati
 		case 0:
 			continue;
 		default:
-			badfam = EAI_NONAME;
+			badfam = EAI_NODATA;
 			break;
 		}
 
@@ -102,45 +102,50 @@ struct dpc_ctx {
 	struct address *addrs;
 	char *canon;
 	int cnt;
+	int rrtype;
 };
 
 #define RR_A 1
 #define RR_CNAME 5
 #define RR_AAAA 28
 
-static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet)
+#define ABUF_SIZE 768
+
+static int dns_parse_callback(void *c, int rr, const void *data, int len, const void *packet, int plen)
 {
 	char tmp[256];
+	int family;
 	struct dpc_ctx *ctx = c;
-	if (ctx->cnt >= MAXADDRS) return -1;
+	if (rr == RR_CNAME) {
+		if (__dn_expand(packet, (const unsigned char *)packet + plen,
+		    data, tmp, sizeof tmp) > 0 && is_valid_hostname(tmp))
+			strcpy(ctx->canon, tmp);
+		return 0;
+	}
+	if (ctx->cnt >= MAXADDRS) return 0;
+	if (rr != ctx->rrtype) return 0;
 	switch (rr) {
 	case RR_A:
 		if (len != 4) return -1;
-		ctx->addrs[ctx->cnt].family = AF_INET;
-		ctx->addrs[ctx->cnt].scopeid = 0;
-		memcpy(ctx->addrs[ctx->cnt++].addr, data, 4);
+		family = AF_INET;
 		break;
 	case RR_AAAA:
 		if (len != 16) return -1;
-		ctx->addrs[ctx->cnt].family = AF_INET6;
-		ctx->addrs[ctx->cnt].scopeid = 0;
-		memcpy(ctx->addrs[ctx->cnt++].addr, data, 16);
-		break;
-	case RR_CNAME:
-		if (__dn_expand(packet, (const unsigned char *)packet + 512,
-		    data, tmp, sizeof tmp) > 0 && is_valid_hostname(tmp))
-			strcpy(ctx->canon, tmp);
+		family = AF_INET6;
 		break;
 	}
+	ctx->addrs[ctx->cnt].family = family;
+	ctx->addrs[ctx->cnt].scopeid = 0;
+	memcpy(ctx->addrs[ctx->cnt++].addr, data, len);
 	return 0;
 }
 
 static int name_from_dns(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family, const struct resolvconf *conf)
 {
-	unsigned char qbuf[2][280], abuf[2][512];
+	unsigned char qbuf[2][280], abuf[2][ABUF_SIZE];
 	const unsigned char *qp[2] = { qbuf[0], qbuf[1] };
 	unsigned char *ap[2] = { abuf[0], abuf[1] };
-	int qlens[2], alens[2];
+	int qlens[2], alens[2], qtypes[2];
 	int i, nq = 0;
 	struct dpc_ctx ctx = { .addrs = buf, .canon = canon };
 	static const struct { int af; int rr; } afrr[2] = {
@@ -153,8 +158,12 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static
 			qlens[nq] = __res_mkquery(0, name, 1, afrr[i].rr,
 				0, 0, 0, qbuf[nq], sizeof *qbuf);
 			if (qlens[nq] == -1)
-				return EAI_NONAME;
+				return 0;
+			qtypes[nq] = afrr[i].rr;
 			qbuf[nq][3] = 0; /* don't need AD flag */
+			/* Ensure query IDs are distinct. */
+			if (nq && qbuf[nq][0] == qbuf[0][0])
+				qbuf[nq][0]++;
 			nq++;
 		}
 	}
@@ -168,11 +177,14 @@ static int name_from_dns(struct address buf[static MAXADDRS], char canon[static
 		if ((abuf[i][3] & 15) != 0) return EAI_FAIL;
 	}
 
-	for (i=0; i<nq; i++)
+	for (i=nq-1; i>=0; i--) {
+		ctx.rrtype = qtypes[i];
+		if (alens[i] > sizeof(abuf[i])) alens[i] = sizeof abuf[i];
 		__dns_parse(abuf[i], alens[i], dns_parse_callback, &ctx);
+	}
 
 	if (ctx.cnt) return ctx.cnt;
-	return EAI_NONAME;
+	return EAI_NODATA;
 }
 
 static int name_from_dns_search(struct address buf[static MAXADDRS], char canon[static 256], const char *name, int family)
lib/libc/musl/src/network/netlink.h
@@ -86,7 +86,7 @@ struct ifaddrmsg {
 #define RTA_DATALEN(rta)	((rta)->rta_len-sizeof(struct rtattr))
 #define RTA_DATAEND(rta)	((char*)(rta)+(rta)->rta_len)
 #define RTA_NEXT(rta)		(struct rtattr*)((char*)(rta)+NETLINK_ALIGN((rta)->rta_len))
-#define RTA_OK(nlh,end)		((char*)(end)-(char*)(rta) >= sizeof(struct rtattr))
+#define RTA_OK(rta,end)		((char*)(end)-(char*)(rta) >= sizeof(struct rtattr))
 
 #define NLMSG_RTA(nlh,len)	((void*)((char*)(nlh)+sizeof(struct nlmsghdr)+NETLINK_ALIGN(len)))
 #define NLMSG_RTAOK(rta,nlh)	RTA_OK(rta,NLMSG_DATAEND(nlh))
lib/libc/musl/src/network/res_mkquery.c
@@ -13,6 +13,7 @@ int __res_mkquery(int op, const char *dname, int class, int type,
 	int n;
 
 	if (l && dname[l-1]=='.') l--;
+	if (l && dname[l-1]=='.') return -1;
 	n = 17+l+!!l;
 	if (l>253 || buflen<n || op>15u || class>255u || type>255u)
 		return -1;
lib/libc/musl/src/network/res_msend.c
@@ -1,5 +1,6 @@
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <netinet/tcp.h>
 #include <netdb.h>
 #include <arpa/inet.h>
 #include <stdint.h>
@@ -16,17 +17,65 @@
 
 static void cleanup(void *p)
 {
-	__syscall(SYS_close, (intptr_t)p);
+	struct pollfd *pfd = p;
+	for (int i=0; pfd[i].fd >= -1; i++)
+		if (pfd[i].fd >= 0) __syscall(SYS_close, pfd[i].fd);
 }
 
 static unsigned long mtime()
 {
 	struct timespec ts;
-	clock_gettime(CLOCK_REALTIME, &ts);
+	if (clock_gettime(CLOCK_MONOTONIC, &ts) < 0 && errno == ENOSYS)
+		clock_gettime(CLOCK_REALTIME, &ts);
 	return (unsigned long)ts.tv_sec * 1000
 		+ ts.tv_nsec / 1000000;
 }
 
+static int start_tcp(struct pollfd *pfd, int family, const void *sa, socklen_t sl, const unsigned char *q, int ql)
+{
+	struct msghdr mh = {
+		.msg_name = (void *)sa,
+		.msg_namelen = sl,
+		.msg_iovlen = 2,
+		.msg_iov = (struct iovec [2]){
+			{ .iov_base = (uint8_t[]){ ql>>8, ql }, .iov_len = 2 },
+			{ .iov_base = (void *)q, .iov_len = ql } }
+	};
+	int r;
+	int fd = socket(family, SOCK_STREAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
+	pfd->fd = fd;
+	pfd->events = POLLOUT;
+	if (!setsockopt(fd, IPPROTO_TCP, TCP_FASTOPEN_CONNECT,
+	    &(int){1}, sizeof(int))) {
+		r = sendmsg(fd, &mh, MSG_FASTOPEN|MSG_NOSIGNAL);
+		if (r == ql+2) pfd->events = POLLIN;
+		if (r >= 0) return r;
+		if (errno == EINPROGRESS) return 0;
+	}
+	r = connect(fd, sa, sl);
+	if (!r || errno == EINPROGRESS) return 0;
+	close(fd);
+	pfd->fd = -1;
+	return -1;
+}
+
+static void step_mh(struct msghdr *mh, size_t n)
+{
+	/* Adjust iovec in msghdr to skip first n bytes. */
+	while (mh->msg_iovlen && n >= mh->msg_iov->iov_len) {
+		n -= mh->msg_iov->iov_len;
+		mh->msg_iov++;
+		mh->msg_iovlen--;
+	}
+	if (!mh->msg_iovlen) return;
+	mh->msg_iov->iov_base = (char *)mh->msg_iov->iov_base + n;
+	mh->msg_iov->iov_len -= n;
+}
+
+/* Internal contract for __res_msend[_rc]: asize must be >=512, nqueries
+ * must be sufficiently small to be safe as VLA size. In practice it's
+ * either 1 or 2, anyway. */
+
 int __res_msend_rc(int nqueries, const unsigned char *const *queries,
 	const int *qlens, unsigned char *const *answers, int *alens, int asize,
 	const struct resolvconf *conf)
@@ -44,7 +93,10 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
 	int next;
 	int i, j;
 	int cs;
-	struct pollfd pfd;
+	struct pollfd pfd[nqueries+2];
+	int qpos[nqueries], apos[nqueries];
+	unsigned char alen_buf[nqueries][2];
+	int r;
 	unsigned long t0, t1, t2;
 
 	pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
@@ -68,29 +120,22 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
 	}
 
 	/* Get local address and open/bind a socket */
-	sa.sin.sin_family = family;
 	fd = socket(family, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
 
 	/* Handle case where system lacks IPv6 support */
 	if (fd < 0 && family == AF_INET6 && errno == EAFNOSUPPORT) {
+		for (i=0; i<nns && conf->ns[nns].family == AF_INET6; i++);
+		if (i==nns) {
+			pthread_setcancelstate(cs, 0);
+			return -1;
+		}
 		fd = socket(AF_INET, SOCK_DGRAM|SOCK_CLOEXEC|SOCK_NONBLOCK, 0);
 		family = AF_INET;
+		sl = sizeof sa.sin;
 	}
-	if (fd < 0 || bind(fd, (void *)&sa, sl) < 0) {
-		if (fd >= 0) close(fd);
-		pthread_setcancelstate(cs, 0);
-		return -1;
-	}
-
-	/* Past this point, there are no errors. Each individual query will
-	 * yield either no reply (indicated by zero length) or an answer
-	 * packet which is up to the caller to interpret. */
-
-	pthread_cleanup_push(cleanup, (void *)(intptr_t)fd);
-	pthread_setcancelstate(cs, 0);
 
 	/* Convert any IPv4 addresses in a mixed environment to v4-mapped */
-	if (family == AF_INET6) {
+	if (fd >= 0 && family == AF_INET6) {
 		setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &(int){0}, sizeof 0);
 		for (i=0; i<nns; i++) {
 			if (ns[i].sin.sin_family != AF_INET) continue;
@@ -104,16 +149,38 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
 		}
 	}
 
+	sa.sin.sin_family = family;
+	if (fd < 0 || bind(fd, (void *)&sa, sl) < 0) {
+		if (fd >= 0) close(fd);
+		pthread_setcancelstate(cs, 0);
+		return -1;
+	}
+
+	/* Past this point, there are no errors. Each individual query will
+	 * yield either no reply (indicated by zero length) or an answer
+	 * packet which is up to the caller to interpret. */
+
+	for (i=0; i<nqueries; i++) pfd[i].fd = -1;
+	pfd[nqueries].fd = fd;
+	pfd[nqueries].events = POLLIN;
+	pfd[nqueries+1].fd = -2;
+
+	pthread_cleanup_push(cleanup, pfd);
+	pthread_setcancelstate(cs, 0);
+
 	memset(alens, 0, sizeof *alens * nqueries);
 
-	pfd.fd = fd;
-	pfd.events = POLLIN;
 	retry_interval = timeout / attempts;
 	next = 0;
 	t0 = t2 = mtime();
 	t1 = t2 - retry_interval;
 
 	for (; t2-t0 < timeout; t2=mtime()) {
+		/* This is the loop exit condition: that all queries
+		 * have an accepted answer. */
+		for (i=0; i<nqueries && alens[i]>0; i++);
+		if (i==nqueries) break;
+
 		if (t2-t1 >= retry_interval) {
 			/* Query all configured namservers in parallel */
 			for (i=0; i<nqueries; i++)
@@ -127,10 +194,20 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
 		}
 
 		/* Wait for a response, or until time to retry */
-		if (poll(&pfd, 1, t1+retry_interval-t2) <= 0) continue;
+		if (poll(pfd, nqueries+1, t1+retry_interval-t2) <= 0) continue;
 
-		while ((rlen = recvfrom(fd, answers[next], asize, 0,
-		  (void *)&sa, (socklen_t[1]){sl})) >= 0) {
+		while (next < nqueries) {
+			struct msghdr mh = {
+				.msg_name = (void *)&sa,
+				.msg_namelen = sl,
+				.msg_iovlen = 1,
+				.msg_iov = (struct iovec []){
+					{ .iov_base = (void *)answers[next],
+					  .iov_len = asize }
+				}
+			};
+			rlen = recvmsg(fd, &mh, 0);
+			if (rlen < 0) break;
 
 			/* Ignore non-identifiable packets */
 			if (rlen < 4) continue;
@@ -170,12 +247,72 @@ int __res_msend_rc(int nqueries, const unsigned char *const *queries,
 			else
 				memcpy(answers[i], answers[next], rlen);
 
-			if (next == nqueries) goto out;
+			/* Ignore further UDP if all slots full or TCP-mode */
+			if (next == nqueries) pfd[nqueries].events = 0;
+
+			/* If answer is truncated (TC bit), fallback to TCP */
+			if ((answers[i][2] & 2) || (mh.msg_flags & MSG_TRUNC)) {
+				alens[i] = -1;
+				pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, 0);
+				r = start_tcp(pfd+i, family, ns+j, sl, queries[i], qlens[i]);
+				pthread_setcancelstate(cs, 0);
+				if (r >= 0) {
+					qpos[i] = r;
+					apos[i] = 0;
+				}
+				continue;
+			}
+		}
+
+		for (i=0; i<nqueries; i++) if (pfd[i].revents & POLLOUT) {
+			struct msghdr mh = {
+				.msg_iovlen = 2,
+				.msg_iov = (struct iovec [2]){
+					{ .iov_base = (uint8_t[]){ qlens[i]>>8, qlens[i] }, .iov_len = 2 },
+					{ .iov_base = (void *)queries[i], .iov_len = qlens[i] } }
+			};
+			step_mh(&mh, qpos[i]);
+			r = sendmsg(pfd[i].fd, &mh, MSG_NOSIGNAL);
+			if (r < 0) goto out;
+			qpos[i] += r;
+			if (qpos[i] == qlens[i]+2)
+				pfd[i].events = POLLIN;
+		}
+
+		for (i=0; i<nqueries; i++) if (pfd[i].revents & POLLIN) {
+			struct msghdr mh = {
+				.msg_iovlen = 2,
+				.msg_iov = (struct iovec [2]){
+					{ .iov_base = alen_buf[i], .iov_len = 2 },
+					{ .iov_base = answers[i], .iov_len = asize } }
+			};
+			step_mh(&mh, apos[i]);
+			r = recvmsg(pfd[i].fd, &mh, 0);
+			if (r <= 0) goto out;
+			apos[i] += r;
+			if (apos[i] < 2) continue;
+			int alen = alen_buf[i][0]*256 + alen_buf[i][1];
+			if (alen < 13) goto out;
+			if (apos[i] < alen+2 && apos[i] < asize+2)
+				continue;
+			int rcode = answers[i][3] & 15;
+			if (rcode != 0 && rcode != 3)
+				goto out;
+
+			/* Storing the length here commits the accepted answer.
+			 * Immediately close TCP socket so as not to consume
+			 * resources we no longer need. */
+			alens[i] = alen;
+			__syscall(SYS_close, pfd[i].fd);
+			pfd[i].fd = -1;
 		}
 	}
 out:
 	pthread_cleanup_pop(1);
 
+	/* Disregard any incomplete TCP results */
+	for (i=0; i<nqueries; i++) if (alens[i]<0) alens[i] = 0;
+
 	return 0;
 }
 
lib/libc/musl/src/network/res_send.c
@@ -1,8 +1,16 @@
 #include <resolv.h>
+#include <string.h>
 
 int __res_send(const unsigned char *msg, int msglen, unsigned char *answer, int anslen)
 {
-	int r = __res_msend(1, &msg, &msglen, &answer, &anslen, anslen);
+	int r;
+	if (anslen < 512) {
+		unsigned char buf[512];
+		r = __res_send(msg, msglen, buf, sizeof buf);
+		if (r >= 0) memcpy(answer, buf, r < anslen ? r : anslen);
+		return r;
+	}
+	r = __res_msend(1, &msg, &msglen, &answer, &anslen, anslen);
 	return r<0 || !anslen ? -1 : anslen;
 }
 
lib/libc/musl/src/network/sendmsg.c
@@ -8,13 +8,16 @@ ssize_t sendmsg(int fd, const struct msghdr *msg, int flags)
 {
 #if LONG_MAX > INT_MAX
 	struct msghdr h;
-	struct cmsghdr chbuf[1024/sizeof(struct cmsghdr)+1], *c;
+	/* Kernels before 2.6.38 set SCM_MAX_FD to 255, allocate enough
+	 * space to support an SCM_RIGHTS ancillary message with 255 fds.
+	 * Kernels since 2.6.38 set SCM_MAX_FD to 253. */
+	struct cmsghdr chbuf[CMSG_SPACE(255*sizeof(int))/sizeof(struct cmsghdr)+1], *c;
 	if (msg) {
 		h = *msg;
 		h.__pad1 = h.__pad2 = 0;
 		msg = &h;
 		if (h.msg_controllen) {
-			if (h.msg_controllen > 1024) {
+			if (h.msg_controllen > sizeof chbuf) {
 				errno = ENOMEM;
 				return -1;
 			}
lib/libc/musl/src/process/aarch64/vfork.s
@@ -0,0 +1,9 @@
+.global vfork
+.type vfork,%function
+vfork:
+	mov x8, 220    // SYS_clone
+	mov x0, 0x4111 // SIGCHLD | CLONE_VM | CLONE_VFORK
+	mov x1, 0
+	svc 0
+	.hidden __syscall_ret
+	b __syscall_ret
lib/libc/musl/src/process/riscv64/vfork.s
@@ -0,0 +1,12 @@
+.global vfork
+.type vfork,@function
+vfork:
+	/* riscv does not have SYS_vfork, so we must use clone instead */
+	/* note: riscv's clone = clone(flags, sp, ptidptr, tls, ctidptr) */
+	li a7, 220
+	li a0, 0x100 | 0x4000 | 17 /* flags = CLONE_VM | CLONE_VFORK | SIGCHLD */
+	mv a1, sp
+	/* the other arguments are ignoreable */
+	ecall
+	.hidden __syscall_ret
+	j __syscall_ret
lib/libc/musl/src/process/_Fork.c
@@ -14,7 +14,6 @@ pid_t _Fork(void)
 	pid_t ret;
 	sigset_t set;
 	__block_all_sigs(&set);
-	__aio_atfork(-1);
 	LOCK(__abort_lock);
 #ifdef SYS_fork
 	ret = __syscall(SYS_fork);
@@ -32,7 +31,7 @@ pid_t _Fork(void)
 		if (libc.need_locks) libc.need_locks = -1;
 	}
 	UNLOCK(__abort_lock);
-	__aio_atfork(!ret);
+	if (!ret) __aio_atfork(1);
 	__restore_sigs(&set);
 	return __syscall_ret(ret);
 }
lib/libc/musl/src/process/fork.c
@@ -9,7 +9,6 @@ static volatile int *const dummy_lockptr = 0;
 
 weak_alias(dummy_lockptr, __at_quick_exit_lockptr);
 weak_alias(dummy_lockptr, __atexit_lockptr);
-weak_alias(dummy_lockptr, __dlerror_lockptr);
 weak_alias(dummy_lockptr, __gettext_lockptr);
 weak_alias(dummy_lockptr, __locale_lockptr);
 weak_alias(dummy_lockptr, __random_lockptr);
@@ -24,7 +23,6 @@ weak_alias(dummy_lockptr, __vmlock_lockptr);
 static volatile int *const *const atfork_locks[] = {
 	&__at_quick_exit_lockptr,
 	&__atexit_lockptr,
-	&__dlerror_lockptr,
 	&__gettext_lockptr,
 	&__locale_lockptr,
 	&__random_lockptr,
@@ -38,6 +36,8 @@ static volatile int *const *const atfork_locks[] = {
 static void dummy(int x) { }
 weak_alias(dummy, __fork_handler);
 weak_alias(dummy, __malloc_atfork);
+weak_alias(dummy, __aio_atfork);
+weak_alias(dummy, __pthread_key_atfork);
 weak_alias(dummy, __ldso_atfork);
 
 static void dummy_0(void) { }
@@ -52,6 +52,8 @@ pid_t fork(void)
 	int need_locks = libc.need_locks > 0;
 	if (need_locks) {
 		__ldso_atfork(-1);
+		__pthread_key_atfork(-1);
+		__aio_atfork(-1);
 		__inhibit_ptc();
 		for (int i=0; i<sizeof atfork_locks/sizeof *atfork_locks; i++)
 			if (*atfork_locks[i]) LOCK(*atfork_locks[i]);
@@ -77,6 +79,8 @@ pid_t fork(void)
 				if (ret) UNLOCK(*atfork_locks[i]);
 				else **atfork_locks[i] = 0;
 		__release_ptc();
+		if (ret) __aio_atfork(0);
+		__pthread_key_atfork(!ret);
 		__ldso_atfork(!ret);
 	}
 	__restore_sigs(&set);
lib/libc/musl/src/regex/glob.c
@@ -306,6 +306,3 @@ void globfree(glob_t *g)
 	g->gl_pathc = 0;
 	g->gl_pathv = NULL;
 }
-
-weak_alias(glob, glob64);
-weak_alias(globfree, globfree64);
lib/libc/musl/src/search/hsearch.c
@@ -41,9 +41,9 @@ static int resize(size_t nel, struct hsearch_data *htab)
 {
 	size_t newsize;
 	size_t i, j;
+	size_t oldsize = htab->__tab->mask + 1;
 	ENTRY *e, *newe;
 	ENTRY *oldtab = htab->__tab->entries;
-	ENTRY *oldend = htab->__tab->entries + htab->__tab->mask + 1;
 
 	if (nel > MAXSIZE)
 		nel = MAXSIZE;
@@ -56,7 +56,7 @@ static int resize(size_t nel, struct hsearch_data *htab)
 	htab->__tab->mask = newsize - 1;
 	if (!oldtab)
 		return 1;
-	for (e = oldtab; e < oldend; e++)
+	for (e = oldtab; e < oldtab + oldsize; e++)
 		if (e->key) {
 			for (i=keyhash(e->key),j=1; ; i+=j++) {
 				newe = htab->__tab->entries + (i & htab->__tab->mask);
lib/libc/musl/src/select/poll.c
@@ -8,8 +8,13 @@ int poll(struct pollfd *fds, nfds_t n, int timeout)
 #ifdef SYS_poll
 	return syscall_cp(SYS_poll, fds, n, timeout);
 #else
+#if SYS_ppoll_time64 == SYS_ppoll
+	typedef long long ppoll_ts_t[2];
+#else
+	typedef long ppoll_ts_t[2];
+#endif
 	return syscall_cp(SYS_ppoll, fds, n, timeout>=0 ?
-		&((struct timespec){ .tv_sec = timeout/1000,
-		.tv_nsec = timeout%1000*1000000 }) : 0, 0, _NSIG/8);
+		((ppoll_ts_t){ timeout/1000, timeout%1000*1000000 }) : 0,
+		0, _NSIG/8);
 #endif
 }
lib/libc/musl/src/select/select.c
@@ -33,6 +33,7 @@ int select(int n, fd_set *restrict rfds, fd_set *restrict wfds, fd_set *restrict
 			((syscall_arg_t[]){ 0, _NSIG/8 }));
 	if (SYS_pselect6 == SYS_pselect6_time64 || r!=-ENOSYS)
 		return __syscall_ret(r);
+	s = CLAMP(s);
 #endif
 #ifdef SYS_select
 	return syscall_cp(SYS_select, n, rfds, wfds, efds,
lib/libc/musl/src/setjmp/powerpc/longjmp.S
@@ -42,10 +42,10 @@ longjmp:
 	bl 1f
 	.hidden __hwcap
 	.long __hwcap-.
-1:	mflr 4
-	lwz 5, 0(4)
-	lwzx 4, 4, 5
-	andis. 4, 4, 0x80
+1:	mflr 6
+	lwz 5, 0(6)
+	lwzx 6, 6, 5
+	andis. 6, 6, 0x80
 	beq 1f
 	.long 0x11c35b01 /* evldd 14,88(3) */
 	.long 0x11e36301 /* ... */
lib/libc/musl/src/signal/mips/restore.s
@@ -1,15 +0,0 @@
-.set noreorder
-
-.global __restore_rt
-.hidden __restore_rt
-.type   __restore_rt,@function
-__restore_rt:
-	li $2, 4193
-	syscall
-
-.global __restore
-.hidden __restore
-.type   __restore,@function
-__restore:
-	li $2, 4119
-	syscall
lib/libc/musl/src/signal/mips64/restore.s
@@ -1,11 +0,0 @@
-.set	noreorder
-.global	__restore_rt
-.global	__restore
-.hidden __restore_rt
-.hidden __restore
-.type	__restore_rt,@function
-.type	__restore,@function
-__restore_rt:
-__restore:
-	li	$2,5211
-	syscall
lib/libc/musl/src/signal/mipsn32/restore.s
@@ -1,11 +0,0 @@
-.set	noreorder
-.global	__restore_rt
-.global	__restore
-.hidden __restore_rt
-.hidden __restore
-.type	__restore_rt,@function
-.type	__restore,@function
-__restore_rt:
-__restore:
-	li	$2,6211
-	syscall
lib/libc/musl/src/signal/sigaction.c
@@ -44,8 +44,11 @@ int __libc_sigaction(int sig, const struct sigaction *restrict sa, struct sigact
 			}
 		}
 		ksa.handler = sa->sa_handler;
-		ksa.flags = sa->sa_flags | SA_RESTORER;
+		ksa.flags = sa->sa_flags;
+#ifdef SA_RESTORER
+		ksa.flags |= SA_RESTORER;
 		ksa.restorer = (sa->sa_flags & SA_SIGINFO) ? __restore_rt : __restore;
+#endif
 		memcpy(&ksa.mask, &sa->sa_mask, _NSIG/8);
 	}
 	int r = __syscall(SYS_rt_sigaction, sig, sa?&ksa:0, old?&ksa_old:0, _NSIG/8);
lib/libc/musl/src/stat/__xstat.c
@@ -22,11 +22,6 @@ int __xstat(int ver, const char *path, struct stat *buf)
 	return stat(path, buf);
 }
 
-weak_alias(__fxstat, __fxstat64);
-weak_alias(__fxstatat, __fxstatat64);
-weak_alias(__lxstat, __lxstat64);
-weak_alias(__xstat, __xstat64);
-
 #endif
 
 int __xmknod(int ver, const char *path, mode_t mode, dev_t *dev)
lib/libc/musl/src/stat/fchmodat.c
@@ -2,7 +2,6 @@
 #include <fcntl.h>
 #include <errno.h>
 #include "syscall.h"
-#include "kstat.h"
 
 int fchmodat(int fd, const char *path, mode_t mode, int flag)
 {
@@ -11,12 +10,12 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag)
 	if (flag != AT_SYMLINK_NOFOLLOW)
 		return __syscall_ret(-EINVAL);
 
-	struct kstat st;
+	struct stat st;
 	int ret, fd2;
 	char proc[15+3*sizeof(int)];
 
-	if ((ret = __syscall(SYS_fstatat, fd, path, &st, flag)))
-		return __syscall_ret(ret);
+	if (fstatat(fd, path, &st, flag))
+		return -1;
 	if (S_ISLNK(st.st_mode))
 		return __syscall_ret(-EOPNOTSUPP);
 
@@ -27,12 +26,12 @@ int fchmodat(int fd, const char *path, mode_t mode, int flag)
 	}
 
 	__procfdname(proc, fd2);
-	ret = __syscall(SYS_fstatat, AT_FDCWD, proc, &st, 0);
+	ret = stat(proc, &st);
 	if (!ret) {
-		if (S_ISLNK(st.st_mode)) ret = -EOPNOTSUPP;
-		else ret = __syscall(SYS_fchmodat, AT_FDCWD, proc, mode);
+		if (S_ISLNK(st.st_mode)) ret = __syscall_ret(-EOPNOTSUPP);
+		else ret = syscall(SYS_fchmodat, AT_FDCWD, proc, mode);
 	}
 
 	__syscall(SYS_close, fd2);
-	return __syscall_ret(ret);
+	return ret;
 }
lib/libc/musl/src/stat/fstat.c
@@ -4,12 +4,10 @@
 #include <fcntl.h>
 #include "syscall.h"
 
-int fstat(int fd, struct stat *st)
+int __fstat(int fd, struct stat *st)
 {
 	if (fd<0) return __syscall_ret(-EBADF);
-	return fstatat(fd, "", st, AT_EMPTY_PATH);
+	return __fstatat(fd, "", st, AT_EMPTY_PATH);
 }
 
-#if !_REDIR_TIME64
-weak_alias(fstat, fstat64);
-#endif
+weak_alias(__fstat, fstat);
lib/libc/musl/src/stat/fstatat.c
@@ -6,7 +6,6 @@
 #include <stdint.h>
 #include <sys/sysmacros.h>
 #include "syscall.h"
-#include "kstat.h"
 
 struct statx {
 	uint32_t stx_mask;
@@ -69,6 +68,10 @@ static int fstatat_statx(int fd, const char *restrict path, struct stat *restric
 	return 0;
 }
 
+#ifdef SYS_fstatat
+
+#include "kstat.h"
+
 static int fstatat_kstat(int fd, const char *restrict path, struct stat *restrict st, int flag)
 {
 	int ret;
@@ -130,18 +133,21 @@ static int fstatat_kstat(int fd, const char *restrict path, struct stat *restric
 
 	return 0;
 }
+#endif
 
-int fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag)
+int __fstatat(int fd, const char *restrict path, struct stat *restrict st, int flag)
 {
 	int ret;
+#ifdef SYS_fstatat
 	if (sizeof((struct kstat){0}.st_atime_sec) < sizeof(time_t)) {
 		ret = fstatat_statx(fd, path, st, flag);
 		if (ret!=-ENOSYS) return __syscall_ret(ret);
 	}
 	ret = fstatat_kstat(fd, path, st, flag);
+#else
+	ret = fstatat_statx(fd, path, st, flag);
+#endif
 	return __syscall_ret(ret);
 }
 
-#if !_REDIR_TIME64
-weak_alias(fstatat, fstatat64);
-#endif
+weak_alias(__fstatat, fstatat);
lib/libc/musl/src/stat/lstat.c
@@ -5,7 +5,3 @@ int lstat(const char *restrict path, struct stat *restrict buf)
 {
 	return fstatat(AT_FDCWD, path, buf, AT_SYMLINK_NOFOLLOW);
 }
-
-#if !_REDIR_TIME64
-weak_alias(lstat, lstat64);
-#endif
lib/libc/musl/src/stat/stat.c
@@ -5,7 +5,3 @@ int stat(const char *restrict path, struct stat *restrict buf)
 {
 	return fstatat(AT_FDCWD, path, buf, 0);
 }
-
-#if !_REDIR_TIME64
-weak_alias(stat, stat64);
-#endif
lib/libc/musl/src/stat/statvfs.c
@@ -56,8 +56,3 @@ int fstatvfs(int fd, struct statvfs *buf)
 	fixup(buf, &kbuf);
 	return 0;
 }
-
-weak_alias(statvfs, statvfs64);
-weak_alias(statfs, statfs64);
-weak_alias(fstatvfs, fstatvfs64);
-weak_alias(fstatfs, fstatfs64);
lib/libc/musl/src/stdio/fgetpos.c
@@ -7,5 +7,3 @@ int fgetpos(FILE *restrict f, fpos_t *restrict pos)
 	*(long long *)pos = off;
 	return 0;
 }
-
-weak_alias(fgetpos, fgetpos64);
lib/libc/musl/src/stdio/fgets.c
@@ -12,13 +12,14 @@ char *fgets(char *restrict s, int n, FILE *restrict f)
 
 	FLOCK(f);
 
-	if (n--<=1) {
+	if (n<=1) {
 		f->mode |= f->mode-1;
 		FUNLOCK(f);
-		if (n) return 0;
+		if (n<1) return 0;
 		*s = 0;
 		return s;
 	}
+	n--;
 
 	while (n) {
 		if (f->rpos != f->rend) {
lib/libc/musl/src/stdio/fopen.c
@@ -29,5 +29,3 @@ FILE *fopen(const char *restrict filename, const char *restrict mode)
 	__syscall(SYS_close, fd);
 	return 0;
 }
-
-weak_alias(fopen, fopen64);
lib/libc/musl/src/stdio/freopen.c
@@ -40,6 +40,8 @@ FILE *freopen(const char *restrict filename, const char *restrict mode, FILE *re
 		fclose(f2);
 	}
 
+	f->mode = 0;
+	f->locale = 0;
 	FUNLOCK(f);
 	return f;
 
@@ -49,5 +51,3 @@ fail:
 	fclose(f);
 	return NULL;
 }
-
-weak_alias(freopen, freopen64);
lib/libc/musl/src/stdio/fseek.c
@@ -46,5 +46,3 @@ int fseek(FILE *f, long off, int whence)
 }
 
 weak_alias(__fseeko, fseeko);
-
-weak_alias(fseeko, fseeko64);
lib/libc/musl/src/stdio/fsetpos.c
@@ -4,5 +4,3 @@ int fsetpos(FILE *f, const fpos_t *pos)
 {
 	return __fseeko(f, *(const long long *)pos, SEEK_SET);
 }
-
-weak_alias(fsetpos, fsetpos64);
lib/libc/musl/src/stdio/ftell.c
@@ -37,5 +37,3 @@ long ftell(FILE *f)
 }
 
 weak_alias(__ftello, ftello);
-
-weak_alias(ftello, ftello64);
lib/libc/musl/src/stdio/open_wmemstream.c
@@ -40,8 +40,12 @@ fail:
 static size_t wms_write(FILE *f, const unsigned char *buf, size_t len)
 {
 	struct cookie *c = f->cookie;
-	size_t len2;
+	size_t len2 = f->wpos - f->wbase;
 	wchar_t *newbuf;
+	if (len2) {
+		f->wpos = f->wbase;
+		if (wms_write(f, f->wbase, len2) < len2) return 0;
+	}
 	if (len + c->pos >= c->space) {
 		len2 = 2*c->space+1 | c->pos+len+1;
 		if (len2 > SSIZE_MAX/4) return 0;
lib/libc/musl/src/stdio/tempnam.c
@@ -6,7 +6,6 @@
 #include <string.h>
 #include <stdlib.h>
 #include "syscall.h"
-#include "kstat.h"
 
 #define MAXTRIES 100
 
@@ -37,11 +36,10 @@ char *tempnam(const char *dir, const char *pfx)
 
 	for (try=0; try<MAXTRIES; try++) {
 		__randname(s+l-6);
-#ifdef SYS_lstat
-		r = __syscall(SYS_lstat, s, &(struct kstat){0});
+#ifdef SYS_readlink
+		r = __syscall(SYS_readlink, s, (char[1]){0}, 1);
 #else
-		r = __syscall(SYS_fstatat, AT_FDCWD, s,
-			&(struct kstat){0}, AT_SYMLINK_NOFOLLOW);
+		r = __syscall(SYS_readlinkat, AT_FDCWD, s, (char[1]){0}, 1);
 #endif
 		if (r == -ENOENT) return strdup(s);
 	}
lib/libc/musl/src/stdio/tmpfile.c
@@ -27,5 +27,3 @@ FILE *tmpfile(void)
 	}
 	return 0;
 }
-
-weak_alias(tmpfile, tmpfile64);
lib/libc/musl/src/stdio/tmpnam.c
@@ -5,7 +5,6 @@
 #include <string.h>
 #include <stdlib.h>
 #include "syscall.h"
-#include "kstat.h"
 
 #define MAXTRIES 100
 
@@ -17,11 +16,10 @@ char *tmpnam(char *buf)
 	int r;
 	for (try=0; try<MAXTRIES; try++) {
 		__randname(s+12);
-#ifdef SYS_lstat
-		r = __syscall(SYS_lstat, s, &(struct kstat){0});
+#ifdef SYS_readlink
+		r = __syscall(SYS_readlink, s, (char[1]){0}, 1);
 #else
-		r = __syscall(SYS_fstatat, AT_FDCWD, s,
-			&(struct kstat){0}, AT_SYMLINK_NOFOLLOW);
+		r = __syscall(SYS_readlinkat, AT_FDCWD, s, (char[1]){0}, 1);
 #endif
 		if (r == -ENOENT) return strcpy(buf ? buf : internal, s);
 	}
lib/libc/musl/src/stdio/vfprintf.c
@@ -132,7 +132,7 @@ static void pop_arg(union arg *arg, int type, va_list *ap)
 
 static void out(FILE *f, const char *s, size_t l)
 {
-	if (!(f->flags & F_ERR)) __fwritex((void *)s, l, f);
+	if (!ferror(f)) __fwritex((void *)s, l, f);
 }
 
 static void pad(FILE *f, char c, int w, int l, int fl)
@@ -478,8 +478,8 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 		if (*s=='*') {
 			if (isdigit(s[1]) && s[2]=='$') {
 				l10n=1;
-				nl_type[s[1]-'0'] = INT;
-				w = nl_arg[s[1]-'0'].i;
+				if (!f) nl_type[s[1]-'0'] = INT, w = 0;
+				else w = nl_arg[s[1]-'0'].i;
 				s+=3;
 			} else if (!l10n) {
 				w = f ? va_arg(*ap, int) : 0;
@@ -491,8 +491,8 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 		/* Read precision */
 		if (*s=='.' && s[1]=='*') {
 			if (isdigit(s[2]) && s[3]=='$') {
-				nl_type[s[2]-'0'] = INT;
-				p = nl_arg[s[2]-'0'].i;
+				if (!f) nl_type[s[2]-'0'] = INT, p = 0;
+				else p = nl_arg[s[2]-'0'].i;
 				s+=4;
 			} else if (!l10n) {
 				p = f ? va_arg(*ap, int) : 0;
@@ -521,13 +521,18 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 		if (st==NOARG) {
 			if (argpos>=0) goto inval;
 		} else {
-			if (argpos>=0) nl_type[argpos]=st, arg=nl_arg[argpos];
-			else if (f) pop_arg(&arg, st, ap);
+			if (argpos>=0) {
+				if (!f) nl_type[argpos]=st;
+				else arg=nl_arg[argpos];
+			} else if (f) pop_arg(&arg, st, ap);
 			else return 0;
 		}
 
 		if (!f) continue;
 
+		/* Do not process any new directives once in error state. */
+		if (ferror(f)) return -1;
+
 		z = buf + sizeof(buf);
 		prefix = "-+   0X0x";
 		pl = 0;
@@ -672,7 +677,7 @@ int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap)
 
 	FLOCK(f);
 	olderr = f->flags & F_ERR;
-	if (f->mode < 1) f->flags &= ~F_ERR;
+	f->flags &= ~F_ERR;
 	if (!f->buf_size) {
 		saved_buf = f->buf;
 		f->buf = internal_buf;
@@ -688,7 +693,7 @@ int vfprintf(FILE *restrict f, const char *restrict fmt, va_list ap)
 		f->buf_size = 0;
 		f->wpos = f->wbase = f->wend = 0;
 	}
-	if (f->flags & F_ERR) ret = -1;
+	if (ferror(f)) ret = -1;
 	f->flags |= olderr;
 	FUNLOCK(f);
 	va_end(ap2);
lib/libc/musl/src/stdio/vfwprintf.c
@@ -125,7 +125,13 @@ static void pop_arg(union arg *arg, int type, va_list *ap)
 
 static void out(FILE *f, const wchar_t *s, size_t l)
 {
-	while (l-- && !(f->flags & F_ERR)) fputwc(*s++, f);
+	while (l-- && !ferror(f)) fputwc(*s++, f);
+}
+
+static void pad(FILE *f, int n, int fl)
+{
+	if ((fl & LEFT_ADJ) || !n || ferror(f)) return;
+	fprintf(f, "%*s", n, "");
 }
 
 static int getint(wchar_t **s) {
@@ -242,6 +248,10 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
 		}
 
 		if (!f) continue;
+
+		/* Do not process any new directives once in error state. */
+		if (ferror(f)) return -1;
+
 		t = s[-1];
 		if (ps && (t&15)==3) t&=~32;
 
@@ -258,25 +268,22 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
 			}
 			continue;
 		case 'c':
+		case 'C':
 			if (w<1) w=1;
-			if (w>1 && !(fl&LEFT_ADJ)) fprintf(f, "%*s", w-1, "");
-			fputwc(btowc(arg.i), f);
-			if (w>1 && (fl&LEFT_ADJ)) fprintf(f, "%*s", w-1, "");
+			pad(f, w-1, fl);
+			out(f, &(wchar_t){t=='C' ? arg.i : btowc(arg.i)}, 1);
+			pad(f, w-1, fl^LEFT_ADJ);
 			l = w;
 			continue;
-		case 'C':
-			fputwc(arg.i, f);
-			l = 1;
-			continue;
 		case 'S':
 			a = arg.p;
 			z = a + wcsnlen(a, p<0 ? INT_MAX : p);
 			if (p<0 && *z) goto overflow;
 			p = z-a;
 			if (w<p) w=p;
-			if (!(fl&LEFT_ADJ)) fprintf(f, "%*s", w-p, "");
+			pad(f, w-p, fl);
 			out(f, a, p);
-			if ((fl&LEFT_ADJ)) fprintf(f, "%*s", w-p, "");
+			pad(f, w-p, fl^LEFT_ADJ);
 			l=w;
 			continue;
 		case 'm':
@@ -289,14 +296,14 @@ static int wprintf_core(FILE *f, const wchar_t *fmt, va_list *ap, union arg *nl_
 			if (p<0 && *bs) goto overflow;
 			p=l;
 			if (w<p) w=p;
-			if (!(fl&LEFT_ADJ)) fprintf(f, "%*s", w-p, "");
+			pad(f, w-p, fl);
 			bs = arg.p;
 			while (l--) {
 				i=mbtowc(&wc, bs, MB_LEN_MAX);
 				bs+=i;
-				fputwc(wc, f);
+				out(f, &wc, 1);
 			}
-			if ((fl&LEFT_ADJ)) fprintf(f, "%*s", w-p, "");
+			pad(f, w-p, fl^LEFT_ADJ);
 			l=w;
 			continue;
 		}
@@ -340,8 +347,8 @@ overflow:
 int vfwprintf(FILE *restrict f, const wchar_t *restrict fmt, va_list ap)
 {
 	va_list ap2;
-	int nl_type[NL_ARGMAX] = {0};
-	union arg nl_arg[NL_ARGMAX];
+	int nl_type[NL_ARGMAX+1] = {0};
+	union arg nl_arg[NL_ARGMAX+1];
 	int olderr;
 	int ret;
 
@@ -357,7 +364,7 @@ int vfwprintf(FILE *restrict f, const wchar_t *restrict fmt, va_list ap)
 	olderr = f->flags & F_ERR;
 	f->flags &= ~F_ERR;
 	ret = wprintf_core(f, fmt, &ap2, nl_arg, nl_type);
-	if (f->flags & F_ERR) ret = -1;
+	if (ferror(f)) ret = -1;
 	f->flags |= olderr;
 	FUNLOCK(f);
 	va_end(ap2);
lib/libc/musl/src/stdio/vswprintf.c
@@ -18,6 +18,7 @@ static size_t sw_write(FILE *f, const unsigned char *s, size_t l)
 	if (s!=f->wbase && sw_write(f, f->wbase, f->wpos-f->wbase)==-1)
 		return -1;
 	while (c->l && l && (i=mbtowc(c->ws, (void *)s, l))>=0) {
+		if (!i) i=1;
 		s+=i;
 		l-=i;
 		c->l--;
lib/libc/musl/src/stdlib/qsort_nr.c
@@ -10,5 +10,5 @@ static int wrapper_cmp(const void *v1, const void *v2, void *cmp)
 
 void qsort(void *base, size_t nel, size_t width, cmpfun cmp)
 {
-	__qsort_r(base, nel, width, wrapper_cmp, cmp);
+	__qsort_r(base, nel, width, wrapper_cmp, (void *)cmp);
 }
lib/libc/musl/src/string/strverscmp.c
@@ -18,9 +18,9 @@ int strverscmp(const char *l0, const char *r0)
 		else if (c!='0') z=0;
 	}
 
-	if (l[dp]!='0' && r[dp]!='0') {
-		/* If we're not looking at a digit sequence that began
-		 * with a zero, longest digit string is greater. */
+	if (l[dp]-'1'<9U && r[dp]-'1'<9U) {
+		/* If we're looking at non-degenerate digit sequences starting
+		 * with nonzero digits, longest digit string is greater. */
 		for (j=i; isdigit(l[j]); j++)
 			if (!isdigit(r[j])) return 1;
 		if (isdigit(r[j])) return -1;
lib/libc/musl/src/string/wcscmp.c
@@ -3,5 +3,5 @@
 int wcscmp(const wchar_t *l, const wchar_t *r)
 {
 	for (; *l==*r && *l && *r; l++, r++);
-	return *l - *r;
+	return *l < *r ? -1 : *l > *r;
 }
lib/libc/musl/src/string/wcsncmp.c
@@ -3,5 +3,5 @@
 int wcsncmp(const wchar_t *l, const wchar_t *r, size_t n)
 {
 	for (; n && *l==*r && *l && *r; n--, l++, r++);
-	return n ? *l - *r : 0;
+	return n ? (*l < *r ? -1 : *l > *r) : 0;
 }
lib/libc/musl/src/string/wmemcmp.c
@@ -3,5 +3,5 @@
 int wmemcmp(const wchar_t *l, const wchar_t *r, size_t n)
 {
 	for (; n && *l==*r; n--, l++, r++);
-	return n ? *l-*r : 0;
+	return n ? (*l < *r ? -1 : *l > *r) : 0;
 }
lib/libc/musl/src/temp/__randname.c
@@ -1,5 +1,6 @@
 #include <time.h>
 #include <stdint.h>
+#include "pthread_impl.h"
 
 /* This assumes that a check for the
    template size has already been made */
@@ -10,7 +11,7 @@ char *__randname(char *template)
 	unsigned long r;
 
 	__clock_gettime(CLOCK_REALTIME, &ts);
-	r = ts.tv_nsec*65537 ^ (uintptr_t)&ts / 16 + (uintptr_t)template;
+	r = ts.tv_sec + ts.tv_nsec + __pthread_self()->tid * 65537UL;
 	for (i=0; i<6; i++, r>>=5)
 		template[i] = 'A'+(r&15)+(r&16)*2;
 
lib/libc/musl/src/temp/mkostemp.c
@@ -5,5 +5,3 @@ int mkostemp(char *template, int flags)
 {
 	return __mkostemps(template, 0, flags);
 }
-
-weak_alias(mkostemp, mkostemp64);
lib/libc/musl/src/temp/mkostemps.c
@@ -26,4 +26,3 @@ int __mkostemps(char *template, int len, int flags)
 }
 
 weak_alias(__mkostemps, mkostemps);
-weak_alias(__mkostemps, mkostemps64);
lib/libc/musl/src/temp/mkstemp.c
@@ -4,5 +4,3 @@ int mkstemp(char *template)
 {
 	return __mkostemps(template, 0, 0);
 }
-
-weak_alias(mkstemp, mkstemp64);
lib/libc/musl/src/temp/mkstemps.c
@@ -5,5 +5,3 @@ int mkstemps(char *template, int len)
 {
 	return __mkostemps(template, len, 0);
 }
-
-weak_alias(mkstemps, mkstemps64);
lib/libc/musl/src/thread/pthread_atfork.c
@@ -1,7 +1,13 @@
 #include <pthread.h>
+#include <errno.h>
 #include "libc.h"
 #include "lock.h"
 
+#define malloc __libc_malloc
+#define calloc undef
+#define realloc undef
+#define free undef
+
 static struct atfork_funcs {
 	void (*prepare)(void);
 	void (*parent)(void);
@@ -34,7 +40,7 @@ void __fork_handler(int who)
 int pthread_atfork(void (*prepare)(void), void (*parent)(void), void (*child)(void))
 {
 	struct atfork_funcs *new = malloc(sizeof *new);
-	if (!new) return -1;
+	if (!new) return ENOMEM;
 
 	LOCK(lock);
 	new->next = funcs;
lib/libc/musl/src/thread/pthread_cancel.c
@@ -56,7 +56,12 @@ static void cancel_handler(int sig, siginfo_t *si, void *ctx)
 
 	_sigaddset(&uc->uc_sigmask, SIGCANCEL);
 
-	if (self->cancelasync || pc >= (uintptr_t)__cp_begin && pc < (uintptr_t)__cp_end) {
+	if (self->cancelasync) {
+		pthread_sigmask(SIG_SETMASK, &uc->uc_sigmask, 0);
+		__cancel();
+	}
+
+	if (pc >= (uintptr_t)__cp_begin && pc < (uintptr_t)__cp_end) {
 		uc->uc_mcontext.MC_PC = (uintptr_t)__cp_cancel;
 #ifdef CANCEL_GOT
 		uc->uc_mcontext.MC_GOT = CANCEL_GOT;
@@ -77,7 +82,7 @@ void __testcancel()
 static void init_cancellation()
 {
 	struct sigaction sa = {
-		.sa_flags = SA_SIGINFO | SA_RESTART,
+		.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK,
 		.sa_sigaction = cancel_handler
 	};
 	memset(&sa.sa_mask, -1, _NSIG/8);
lib/libc/musl/src/thread/pthread_create.c
@@ -107,6 +107,16 @@ _Noreturn void __pthread_exit(void *result)
 
 	/* At this point we are committed to thread termination. */
 
+	/* After the kernel thread exits, its tid may be reused. Clear it
+	 * to prevent inadvertent use and inform functions that would use
+	 * it that it's no longer available. At this point the killlock
+	 * may be released, since functions that use it will consistently
+	 * see the thread as having exited. Release it now so that no
+	 * remaining locks (except thread list) are held if we end up
+	 * resetting need_locks below. */
+	self->tid = 0;
+	UNLOCK(self->killlock);
+
 	/* Process robust list in userspace to handle non-pshared mutexes
 	 * and the detached thread case where the robust list head will
 	 * be invalid when the kernel would process it. */
@@ -159,12 +169,6 @@ _Noreturn void __pthread_exit(void *result)
 	a_store(&self->detach_state, DT_EXITED);
 	__wake(&self->detach_state, 1, 1);
 
-	/* After the kernel thread exits, its tid may be reused. Clear it
-	 * to prevent inadvertent use and inform functions that would use
-	 * it that it's no longer available. */
-	self->tid = 0;
-	UNLOCK(self->killlock);
-
 	for (;;) __syscall(SYS_exit, 0);
 }
 
lib/libc/musl/src/thread/pthread_detach.c
@@ -5,8 +5,12 @@ static int __pthread_detach(pthread_t t)
 {
 	/* If the cas fails, detach state is either already-detached
 	 * or exiting/exited, and pthread_join will trap or cleanup. */
-	if (a_cas(&t->detach_state, DT_JOINABLE, DT_DETACHED) != DT_JOINABLE)
-		return __pthread_join(t, 0);
+	if (a_cas(&t->detach_state, DT_JOINABLE, DT_DETACHED) != DT_JOINABLE) {
+		int cs;
+		__pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &cs);
+		__pthread_join(t, 0);
+		__pthread_setcancelstate(cs, 0);
+	}
 	return 0;
 }
 
lib/libc/musl/src/thread/pthread_key_create.c
@@ -1,4 +1,5 @@
 #include "pthread_impl.h"
+#include "fork_impl.h"
 
 volatile size_t __pthread_tsd_size = sizeof(void *) * PTHREAD_KEYS_MAX;
 void *__pthread_tsd_main[PTHREAD_KEYS_MAX] = { 0 };
@@ -20,6 +21,13 @@ static void dummy_0(void)
 weak_alias(dummy_0, __tl_lock);
 weak_alias(dummy_0, __tl_unlock);
 
+void __pthread_key_atfork(int who)
+{
+	if (who<0) __pthread_rwlock_rdlock(&key_lock);
+	else if (!who) __pthread_rwlock_unlock(&key_lock);
+	else key_lock = (pthread_rwlock_t)PTHREAD_RWLOCK_INITIALIZER;
+}
+
 int __pthread_key_create(pthread_key_t *k, void (*dtor)(void *))
 {
 	pthread_t self = __pthread_self();
lib/libc/musl/src/thread/sem_getvalue.c
@@ -1,8 +1,9 @@
 #include <semaphore.h>
+#include <limits.h>
 
 int sem_getvalue(sem_t *restrict sem, int *restrict valp)
 {
 	int val = sem->__val[0];
-	*valp = val < 0 ? 0 : val;
+	*valp = val & SEM_VALUE_MAX;
 	return 0;
 }
lib/libc/musl/src/thread/sem_post.c
@@ -1,17 +1,21 @@
 #include <semaphore.h>
+#include <limits.h>
 #include "pthread_impl.h"
 
 int sem_post(sem_t *sem)
 {
-	int val, waiters, priv = sem->__val[2];
+	int val, new, waiters, priv = sem->__val[2];
 	do {
 		val = sem->__val[0];
 		waiters = sem->__val[1];
-		if (val == SEM_VALUE_MAX) {
+		if ((val & SEM_VALUE_MAX) == SEM_VALUE_MAX) {
 			errno = EOVERFLOW;
 			return -1;
 		}
-	} while (a_cas(sem->__val, val, val+1+(val<0)) != val);
-	if (val<0 || waiters) __wake(sem->__val, 1, priv);
+		new = val + 1;
+		if (waiters <= 1)
+			new &= ~0x80000000;
+	} while (a_cas(sem->__val, val, new) != val);
+	if (val<0) __wake(sem->__val, waiters>1 ? 1 : -1, priv);
 	return 0;
 }
lib/libc/musl/src/thread/sem_timedwait.c
@@ -1,4 +1,5 @@
 #include <semaphore.h>
+#include <limits.h>
 #include "pthread_impl.h"
 
 static void cleanup(void *p)
@@ -13,14 +14,15 @@ int sem_timedwait(sem_t *restrict sem, const struct timespec *restrict at)
 	if (!sem_trywait(sem)) return 0;
 
 	int spins = 100;
-	while (spins-- && sem->__val[0] <= 0 && !sem->__val[1]) a_spin();
+	while (spins-- && !(sem->__val[0] & SEM_VALUE_MAX) && !sem->__val[1])
+		a_spin();
 
 	while (sem_trywait(sem)) {
-		int r;
+		int r, priv = sem->__val[2];
 		a_inc(sem->__val+1);
-		a_cas(sem->__val, 0, -1);
+		a_cas(sem->__val, 0, 0x80000000);
 		pthread_cleanup_push(cleanup, (void *)(sem->__val+1));
-		r = __timedwait_cp(sem->__val, -1, CLOCK_REALTIME, at, sem->__val[2]);
+		r = __timedwait_cp(sem->__val, 0x80000000, CLOCK_REALTIME, at, priv);
 		pthread_cleanup_pop(1);
 		if (r) {
 			errno = r;
lib/libc/musl/src/thread/sem_trywait.c
@@ -1,12 +1,12 @@
 #include <semaphore.h>
+#include <limits.h>
 #include "pthread_impl.h"
 
 int sem_trywait(sem_t *sem)
 {
 	int val;
-	while ((val=sem->__val[0]) > 0) {
-		int new = val-1-(val==1 && sem->__val[1]);
-		if (a_cas(sem->__val, val, new)==val) return 0;
+	while ((val=sem->__val[0]) & SEM_VALUE_MAX) {
+		if (a_cas(sem->__val, val, val-1)==val) return 0;
 	}
 	errno = EAGAIN;
 	return -1;
lib/libc/musl/src/thread/synccall.c
@@ -45,7 +45,7 @@ void __synccall(void (*func)(void *), void *ctx)
 {
 	sigset_t oldmask;
 	int cs, i, r;
-	struct sigaction sa = { .sa_flags = SA_RESTART, .sa_handler = handler };
+	struct sigaction sa = { .sa_flags = SA_RESTART | SA_ONSTACK, .sa_handler = handler };
 	pthread_t self = __pthread_self(), td;
 	int count = 0;
 
lib/libc/musl/src/time/__map_file.c
@@ -2,15 +2,14 @@
 #include <fcntl.h>
 #include <sys/stat.h>
 #include "syscall.h"
-#include "kstat.h"
 
 const char unsigned *__map_file(const char *pathname, size_t *size)
 {
-	struct kstat st;
+	struct stat st;
 	const unsigned char *map = MAP_FAILED;
 	int fd = sys_open(pathname, O_RDONLY|O_CLOEXEC|O_NONBLOCK);
 	if (fd < 0) return 0;
-	if (!syscall(SYS_fstat, fd, &st)) {
+	if (!__fstat(fd, &st)) {
 		map = __mmap(0, st.st_size, PROT_READ, MAP_SHARED, fd, 0);
 		*size = st.st_size;
 	}
lib/libc/musl/src/time/clock_getcpuclockid.c
@@ -8,6 +8,7 @@ int clock_getcpuclockid(pid_t pid, clockid_t *clk)
 	struct timespec ts;
 	clockid_t id = (-pid-1)*8U + 2;
 	int ret = __syscall(SYS_clock_getres, id, &ts);
+	if (ret == -EINVAL) ret = -ESRCH;
 	if (ret) return -ret;
 	*clk = id;
 	return 0;
lib/libc/musl/src/time/clock_gettime.c
@@ -42,6 +42,9 @@ static int cgt_init(clockid_t clk, struct timespec *ts)
 			p = cgt_time32_wrap;
 		}
 	}
+#ifdef VDSO_CGT_WORKAROUND
+	if (!__vdsosym(VDSO_CGT32_VER, VDSO_CGT32_SYM)) p = 0;
+#endif
 #endif
 	int (*f)(clockid_t, struct timespec *) =
 		(int (*)(clockid_t, struct timespec *))p;
@@ -80,10 +83,12 @@ int __clock_gettime(clockid_t clk, struct timespec *ts)
 		return __syscall_ret(r);
 	long ts32[2];
 	r = __syscall(SYS_clock_gettime, clk, ts32);
+#ifdef SYS_gettimeofday
 	if (r==-ENOSYS && clk==CLOCK_REALTIME) {
 		r = __syscall(SYS_gettimeofday, ts32, 0);
 		ts32[1] *= 1000;
 	}
+#endif
 	if (!r) {
 		ts->tv_sec = ts32[0];
 		ts->tv_nsec = ts32[1];
@@ -92,6 +97,7 @@ int __clock_gettime(clockid_t clk, struct timespec *ts)
 	return __syscall_ret(r);
 #else
 	r = __syscall(SYS_clock_gettime, clk, ts);
+#ifdef SYS_gettimeofday
 	if (r == -ENOSYS) {
 		if (clk == CLOCK_REALTIME) {
 			__syscall(SYS_gettimeofday, ts, 0);
@@ -100,6 +106,7 @@ int __clock_gettime(clockid_t clk, struct timespec *ts)
 		}
 		r = -EINVAL;
 	}
+#endif
 	return __syscall_ret(r);
 #endif
 }
lib/libc/musl/src/time/timer_create.c
@@ -43,6 +43,8 @@ static void *start(void *arg)
 	union sigval val = args->sev->sigev_value;
 
 	pthread_barrier_wait(&args->b);
+	if (self->cancel)
+		return 0;
 	for (;;) {
 		siginfo_t si;
 		while (sigwaitinfo(SIGTIMER_SET, &si) < 0);
@@ -113,8 +115,10 @@ int timer_create(clockid_t clk, struct sigevent *restrict evp, timer_t *restrict
 		ksev.sigev_signo = SIGTIMER;
 		ksev.sigev_notify = SIGEV_THREAD_ID;
 		ksev.sigev_tid = td->tid;
-		if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0)
+		if (syscall(SYS_timer_create, clk, &ksev, &timerid) < 0) {
 			timerid = -1;
+			td->cancel = 1;
+		}
 		td->timer_id = timerid;
 		pthread_barrier_wait(&args.b);
 		if (timerid < 0) return -1;
lib/libc/musl/src/unistd/mipsn32/lseek.c
@@ -17,4 +17,3 @@ off_t __lseek(int fd, off_t offset, int whence)
 }
 
 weak_alias(__lseek, lseek);
-weak_alias(__lseek, lseek64);
lib/libc/musl/src/unistd/x32/lseek.c
@@ -12,4 +12,3 @@ off_t __lseek(int fd, off_t offset, int whence)
 }
 
 weak_alias(__lseek, lseek);
-weak_alias(__lseek, lseek64);
lib/libc/musl/src/unistd/dup3.c
@@ -9,12 +9,14 @@ int __dup3(int old, int new, int flags)
 	int r;
 #ifdef SYS_dup2
 	if (old==new) return __syscall_ret(-EINVAL);
-	if (flags & O_CLOEXEC) {
+	if (flags) {
 		while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY);
 		if (r!=-ENOSYS) return __syscall_ret(r);
+		if (flags & ~O_CLOEXEC) return __syscall_ret(-EINVAL);
 	}
 	while ((r=__syscall(SYS_dup2, old, new))==-EBUSY);
-	if (flags & O_CLOEXEC) __syscall(SYS_fcntl, new, F_SETFD, FD_CLOEXEC);
+	if (r >= 0 && (flags & O_CLOEXEC))
+		__syscall(SYS_fcntl, new, F_SETFD, FD_CLOEXEC);
 #else
 	while ((r=__syscall(SYS_dup3, old, new, flags))==-EBUSY);
 #endif
lib/libc/musl/src/unistd/ftruncate.c
@@ -5,5 +5,3 @@ int ftruncate(int fd, off_t length)
 {
 	return syscall(SYS_ftruncate, fd, __SYSCALL_LL_O(length));
 }
-
-weak_alias(ftruncate, ftruncate64);
lib/libc/musl/src/unistd/lseek.c
@@ -12,4 +12,3 @@ off_t __lseek(int fd, off_t offset, int whence)
 }
 
 weak_alias(__lseek, lseek);
-weak_alias(__lseek, lseek64);
lib/libc/musl/src/unistd/pipe2.c
@@ -8,6 +8,7 @@ int pipe2(int fd[2], int flag)
 	if (!flag) return pipe(fd);
 	int ret = __syscall(SYS_pipe2, fd, flag);
 	if (ret != -ENOSYS) return __syscall_ret(ret);
+	if (flag & ~(O_CLOEXEC|O_NONBLOCK)) return __syscall_ret(-EINVAL);
 	ret = pipe(fd);
 	if (ret) return ret;
 	if (flag & O_CLOEXEC) {
lib/libc/musl/src/unistd/pread.c
@@ -5,5 +5,3 @@ ssize_t pread(int fd, void *buf, size_t size, off_t ofs)
 {
 	return syscall_cp(SYS_pread, fd, buf, size, __SYSCALL_LL_PRW(ofs));
 }
-
-weak_alias(pread, pread64);
lib/libc/musl/src/unistd/preadv.c
@@ -8,5 +8,3 @@ ssize_t preadv(int fd, const struct iovec *iov, int count, off_t ofs)
 	return syscall_cp(SYS_preadv, fd, iov, count,
 		(long)(ofs), (long)(ofs>>32));
 }
-
-weak_alias(preadv, preadv64);
lib/libc/musl/src/unistd/pwrite.c
@@ -5,5 +5,3 @@ ssize_t pwrite(int fd, const void *buf, size_t size, off_t ofs)
 {
 	return syscall_cp(SYS_pwrite, fd, buf, size, __SYSCALL_LL_PRW(ofs));
 }
-
-weak_alias(pwrite, pwrite64);
lib/libc/musl/src/unistd/pwritev.c
@@ -8,5 +8,3 @@ ssize_t pwritev(int fd, const struct iovec *iov, int count, off_t ofs)
 	return syscall_cp(SYS_pwritev, fd, iov, count,
 		(long)(ofs), (long)(ofs>>32));
 }
-
-weak_alias(pwritev, pwritev64);
lib/libc/musl/src/unistd/truncate.c
@@ -5,5 +5,3 @@ int truncate(const char *path, off_t length)
 {
 	return syscall(SYS_truncate, path, __SYSCALL_LL_O(length));
 }
-
-weak_alias(truncate, truncate64);
src/musl.zig
@@ -1466,6 +1466,7 @@ const src_files = [_][]const u8{
     "musl/src/prng/seed48.c",
     "musl/src/prng/srand48.c",
     "musl/src/process/_Fork.c",
+    "musl/src/process/aarch64/vfork.s",
     "musl/src/process/arm/vfork.s",
     "musl/src/process/execl.c",
     "musl/src/process/execle.c",
@@ -1496,6 +1497,7 @@ const src_files = [_][]const u8{
     "musl/src/process/posix_spawnattr_setsigdefault.c",
     "musl/src/process/posix_spawnattr_setsigmask.c",
     "musl/src/process/posix_spawnp.c",
+    "musl/src/process/riscv64/vfork.s",
     "musl/src/process/s390x/vfork.s",
     "musl/src/process/sh/vfork.s",
     "musl/src/process/system.c",
@@ -1579,11 +1581,8 @@ const src_files = [_][]const u8{
     "musl/src/signal/m68k/sigsetjmp.s",
     "musl/src/signal/microblaze/restore.s",
     "musl/src/signal/microblaze/sigsetjmp.s",
-    "musl/src/signal/mips/restore.s",
     "musl/src/signal/mips/sigsetjmp.s",
-    "musl/src/signal/mips64/restore.s",
     "musl/src/signal/mips64/sigsetjmp.s",
-    "musl/src/signal/mipsn32/restore.s",
     "musl/src/signal/mipsn32/sigsetjmp.s",
     "musl/src/signal/or1k/sigsetjmp.s",
     "musl/src/signal/powerpc/restore.s",