Commit 07cc32b004

Alex Rønne Petersen <alex@alexrp.com>
2025-08-17 11:56:11
wasi-libc: update to c89896107d7b57aef69dcadede47409ee4f702ee
1 parent d748cc9
Changed files (124)
lib
libc
include
wasi
fts
libc-bottom-half
libc-top-half
thread-stub
std
src
lib/libc/include/wasm-wasi-musl/arpa/nameser.h
@@ -1,455 +0,0 @@
-#ifndef _ARPA_NAMESER_H
-#define _ARPA_NAMESER_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stddef.h>
-#include <stdint.h>
-
-#define __NAMESER	19991006
-#define NS_PACKETSZ	512
-#define NS_MAXDNAME	1025
-#define NS_MAXMSG	65535
-#define NS_MAXCDNAME	255
-#define NS_MAXLABEL	63
-#define NS_HFIXEDSZ	12
-#define NS_QFIXEDSZ	4
-#define NS_RRFIXEDSZ	10
-#define NS_INT32SZ	4
-#define NS_INT16SZ	2
-#define NS_INT8SZ	1
-#define NS_INADDRSZ	4
-#define NS_IN6ADDRSZ	16
-#define NS_CMPRSFLGS	0xc0
-#define NS_DEFAULTPORT	53
-
-typedef enum __ns_sect {
-	ns_s_qd = 0,
-	ns_s_zn = 0,
-	ns_s_an = 1,
-	ns_s_pr = 1,
-	ns_s_ns = 2,
-	ns_s_ud = 2,
-	ns_s_ar = 3,
-	ns_s_max = 4
-} ns_sect;
-
-typedef struct __ns_msg {
-	const unsigned char *_msg, *_eom;
-	uint16_t _id, _flags, _counts[ns_s_max];
-	const unsigned char *_sections[ns_s_max];
-	ns_sect _sect;
-	int _rrnum;
-	const unsigned char *_msg_ptr;
-} ns_msg;
-
-struct _ns_flagdata {  int mask, shift;  };
-extern const struct _ns_flagdata _ns_flagdata[];
-
-#define ns_msg_id(handle) ((handle)._id + 0)
-#define ns_msg_base(handle) ((handle)._msg + 0)
-#define ns_msg_end(handle) ((handle)._eom + 0)
-#define ns_msg_size(handle) ((handle)._eom - (handle)._msg)
-#define ns_msg_count(handle, section) ((handle)._counts[section] + 0)
-#define ns_msg_getflag(handle, flag) \
-	(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift)
-
-typedef	struct __ns_rr {
-	char		name[NS_MAXDNAME];
-	uint16_t	type;
-	uint16_t	rr_class;
-	uint32_t	ttl;
-	uint16_t	rdlength;
-	const unsigned char *rdata;
-} ns_rr;
-
-#define ns_rr_name(rr)	(((rr).name[0] != '\0') ? (rr).name : ".")
-#define ns_rr_type(rr)	((ns_type)((rr).type + 0))
-#define ns_rr_class(rr)	((ns_class)((rr).rr_class + 0))
-#define ns_rr_ttl(rr)	((rr).ttl + 0)
-#define ns_rr_rdlen(rr)	((rr).rdlength + 0)
-#define ns_rr_rdata(rr)	((rr).rdata + 0)
-
-typedef enum __ns_flag {
-	ns_f_qr,
-	ns_f_opcode,
-	ns_f_aa,
-	ns_f_tc,
-	ns_f_rd,
-	ns_f_ra,
-	ns_f_z,
-	ns_f_ad,
-	ns_f_cd,
-	ns_f_rcode,
-	ns_f_max
-} ns_flag;
-
-typedef enum __ns_opcode {
-	ns_o_query = 0,
-	ns_o_iquery = 1,
-	ns_o_status = 2,
-	ns_o_notify = 4,
-	ns_o_update = 5,
-	ns_o_max = 6
-} ns_opcode;
-
-typedef	enum __ns_rcode {
-	ns_r_noerror = 0,
-	ns_r_formerr = 1,
-	ns_r_servfail = 2,
-	ns_r_nxdomain = 3,
-	ns_r_notimpl = 4,
-	ns_r_refused = 5,
-	ns_r_yxdomain = 6,
-	ns_r_yxrrset = 7,
-	ns_r_nxrrset = 8,
-	ns_r_notauth = 9,
-	ns_r_notzone = 10,
-	ns_r_max = 11,
-	ns_r_badvers = 16,
-	ns_r_badsig = 16,
-	ns_r_badkey = 17,
-	ns_r_badtime = 18
-} ns_rcode;
-
-typedef enum __ns_update_operation {
-	ns_uop_delete = 0,
-	ns_uop_add = 1,
-	ns_uop_max = 2
-} ns_update_operation;
-
-struct ns_tsig_key {
-        char name[NS_MAXDNAME], alg[NS_MAXDNAME];
-        unsigned char *data;
-        int len;
-};
-typedef struct ns_tsig_key ns_tsig_key;
-
-struct ns_tcp_tsig_state {
-	int counter;
-	struct dst_key *key;
-	void *ctx;
-	unsigned char sig[NS_PACKETSZ];
-	int siglen;
-};
-typedef struct ns_tcp_tsig_state ns_tcp_tsig_state;
-
-#define NS_TSIG_FUDGE 300
-#define NS_TSIG_TCP_COUNT 100
-#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT"
-
-#define NS_TSIG_ERROR_NO_TSIG -10
-#define NS_TSIG_ERROR_NO_SPACE -11
-#define NS_TSIG_ERROR_FORMERR -12
-
-typedef enum __ns_type {
-	ns_t_invalid = 0,
-	ns_t_a = 1,
-	ns_t_ns = 2,
-	ns_t_md = 3,
-	ns_t_mf = 4,
-	ns_t_cname = 5,
-	ns_t_soa = 6,
-	ns_t_mb = 7,
-	ns_t_mg = 8,
-	ns_t_mr = 9,
-	ns_t_null = 10,
-	ns_t_wks = 11,
-	ns_t_ptr = 12,
-	ns_t_hinfo = 13,
-	ns_t_minfo = 14,
-	ns_t_mx = 15,
-	ns_t_txt = 16,
-	ns_t_rp = 17,
-	ns_t_afsdb = 18,
-	ns_t_x25 = 19,
-	ns_t_isdn = 20,
-	ns_t_rt = 21,
-	ns_t_nsap = 22,
-	ns_t_nsap_ptr = 23,
-	ns_t_sig = 24,
-	ns_t_key = 25,
-	ns_t_px = 26,
-	ns_t_gpos = 27,
-	ns_t_aaaa = 28,
-	ns_t_loc = 29,
-	ns_t_nxt = 30,
-	ns_t_eid = 31,
-	ns_t_nimloc = 32,
-	ns_t_srv = 33,
-	ns_t_atma = 34,
-	ns_t_naptr = 35,
-	ns_t_kx = 36,
-	ns_t_cert = 37,
-	ns_t_a6 = 38,
-	ns_t_dname = 39,
-	ns_t_sink = 40,
-	ns_t_opt = 41,
-	ns_t_apl = 42,
-	ns_t_tkey = 249,
-	ns_t_tsig = 250,
-	ns_t_ixfr = 251,
-	ns_t_axfr = 252,
-	ns_t_mailb = 253,
-	ns_t_maila = 254,
-	ns_t_any = 255,
-	ns_t_zxfr = 256,
-	ns_t_max = 65536
-} ns_type;
-
-#define	ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \
-		      (t) == ns_t_mailb || (t) == ns_t_maila)
-#define	ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt)
-#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t))
-#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr)
-#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \
-		       (t) == ns_t_zxfr)
-
-typedef enum __ns_class {
-	ns_c_invalid = 0,
-	ns_c_in = 1,
-	ns_c_2 = 2,
-	ns_c_chaos = 3,
-	ns_c_hs = 4,
-	ns_c_none = 254,
-	ns_c_any = 255,
-	ns_c_max = 65536
-} ns_class;
-
-typedef enum __ns_key_types {
-	ns_kt_rsa = 1,
-	ns_kt_dh  = 2,
-	ns_kt_dsa = 3,
-	ns_kt_private = 254
-} ns_key_types;
-
-typedef enum __ns_cert_types {
-	cert_t_pkix = 1,
-	cert_t_spki = 2,
-	cert_t_pgp  = 3,
-	cert_t_url  = 253,
-	cert_t_oid  = 254
-} ns_cert_types;
-
-#define	NS_KEY_TYPEMASK		0xC000
-#define	NS_KEY_TYPE_AUTH_CONF	0x0000
-#define	NS_KEY_TYPE_CONF_ONLY	0x8000
-#define	NS_KEY_TYPE_AUTH_ONLY	0x4000
-#define	NS_KEY_TYPE_NO_KEY	0xC000
-#define	NS_KEY_NO_AUTH		0x8000
-#define	NS_KEY_NO_CONF		0x4000
-#define	NS_KEY_RESERVED2	0x2000
-#define	NS_KEY_EXTENDED_FLAGS	0x1000
-#define	NS_KEY_RESERVED4	0x0800
-#define	NS_KEY_RESERVED5	0x0400
-#define	NS_KEY_NAME_TYPE	0x0300
-#define	NS_KEY_NAME_USER	0x0000
-#define	NS_KEY_NAME_ENTITY	0x0200
-#define	NS_KEY_NAME_ZONE	0x0100
-#define	NS_KEY_NAME_RESERVED	0x0300
-#define	NS_KEY_RESERVED8	0x0080
-#define	NS_KEY_RESERVED9	0x0040
-#define	NS_KEY_RESERVED10	0x0020
-#define	NS_KEY_RESERVED11	0x0010
-#define	NS_KEY_SIGNATORYMASK	0x000F
-#define	NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \
-				  NS_KEY_RESERVED4 | \
-				  NS_KEY_RESERVED5 | \
-				  NS_KEY_RESERVED8 | \
-				  NS_KEY_RESERVED9 | \
-				  NS_KEY_RESERVED10 | \
-				  NS_KEY_RESERVED11 )
-#define NS_KEY_RESERVED_BITMASK2 0xFFFF
-#define	NS_ALG_MD5RSA		1
-#define	NS_ALG_DH               2
-#define	NS_ALG_DSA              3
-#define	NS_ALG_DSS              NS_ALG_DSA
-#define	NS_ALG_EXPIRE_ONLY	253
-#define	NS_ALG_PRIVATE_OID	254
-
-#define NS_KEY_PROT_TLS         1
-#define NS_KEY_PROT_EMAIL       2
-#define NS_KEY_PROT_DNSSEC      3
-#define NS_KEY_PROT_IPSEC       4
-#define NS_KEY_PROT_ANY		255
-
-#define	NS_MD5RSA_MIN_BITS	 512
-#define	NS_MD5RSA_MAX_BITS	4096
-#define	NS_MD5RSA_MAX_BYTES	((NS_MD5RSA_MAX_BITS+7/8)*2+3)
-#define	NS_MD5RSA_MAX_BASE64	(((NS_MD5RSA_MAX_BYTES+2)/3)*4)
-#define NS_MD5RSA_MIN_SIZE	((NS_MD5RSA_MIN_BITS+7)/8)
-#define NS_MD5RSA_MAX_SIZE	((NS_MD5RSA_MAX_BITS+7)/8)
-
-#define NS_DSA_SIG_SIZE         41
-#define NS_DSA_MIN_SIZE         213
-#define NS_DSA_MAX_BYTES        405
-
-#define	NS_SIG_TYPE	0
-#define	NS_SIG_ALG	2
-#define	NS_SIG_LABELS	3
-#define	NS_SIG_OTTL	4
-#define	NS_SIG_EXPIR	8
-#define	NS_SIG_SIGNED	12
-#define	NS_SIG_FOOT	16
-#define	NS_SIG_SIGNER	18
-#define	NS_NXT_BITS 8
-#define	NS_NXT_BIT_SET(  n,p) (p[(n)/NS_NXT_BITS] |=  (0x80>>((n)%NS_NXT_BITS)))
-#define	NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS)))
-#define	NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] &   (0x80>>((n)%NS_NXT_BITS)))
-#define NS_NXT_MAX 127
-
-#define NS_OPT_DNSSEC_OK        0x8000U
-#define NS_OPT_NSID		3
-
-#define NS_GET16(s, cp) (void)((s) = ns_get16(((cp)+=2)-2))
-#define NS_GET32(l, cp) (void)((l) = ns_get32(((cp)+=4)-4))
-#define NS_PUT16(s, cp) ns_put16((s), ((cp)+=2)-2)
-#define NS_PUT32(l, cp) ns_put32((l), ((cp)+=4)-4)
-
-unsigned ns_get16(const unsigned char *);
-unsigned long ns_get32(const unsigned char *);
-void ns_put16(unsigned, unsigned char *);
-void ns_put32(unsigned long, unsigned char *);
-
-int ns_initparse(const unsigned char *, int, ns_msg *);
-int ns_parserr(ns_msg *, ns_sect, int, ns_rr *);
-int ns_skiprr(const unsigned char *, const unsigned char *, ns_sect, int);
-int ns_name_uncompress(const unsigned char *, const unsigned char *, const unsigned char *, char *, size_t);
-
-
-#define	__BIND		19950621
-
-typedef struct {
-	unsigned	id :16;
-#if __BYTE_ORDER == __BIG_ENDIAN
-	unsigned	qr: 1;
-	unsigned	opcode: 4;
-	unsigned	aa: 1;
-	unsigned	tc: 1;
-	unsigned	rd: 1;
-	unsigned	ra: 1;
-	unsigned	unused :1;
-	unsigned	ad: 1;
-	unsigned	cd: 1;
-	unsigned	rcode :4;
-#else
-	unsigned	rd :1;
-	unsigned	tc :1;
-	unsigned	aa :1;
-	unsigned	opcode :4;
-	unsigned	qr :1;
-	unsigned	rcode :4;
-	unsigned	cd: 1;
-	unsigned	ad: 1;
-	unsigned	unused :1;
-	unsigned	ra :1;
-#endif
-	unsigned	qdcount :16;
-	unsigned	ancount :16;
-	unsigned	nscount :16;
-	unsigned	arcount :16;
-} HEADER;
-
-#define PACKETSZ	NS_PACKETSZ
-#define MAXDNAME	NS_MAXDNAME
-#define MAXCDNAME	NS_MAXCDNAME
-#define MAXLABEL	NS_MAXLABEL
-#define	HFIXEDSZ	NS_HFIXEDSZ
-#define QFIXEDSZ	NS_QFIXEDSZ
-#define RRFIXEDSZ	NS_RRFIXEDSZ
-#define	INT32SZ		NS_INT32SZ
-#define	INT16SZ		NS_INT16SZ
-#define INT8SZ		NS_INT8SZ
-#define	INADDRSZ	NS_INADDRSZ
-#define	IN6ADDRSZ	NS_IN6ADDRSZ
-#define	INDIR_MASK	NS_CMPRSFLGS
-#define NAMESERVER_PORT	NS_DEFAULTPORT
-
-#define S_ZONE		ns_s_zn
-#define S_PREREQ	ns_s_pr
-#define S_UPDATE	ns_s_ud
-#define S_ADDT		ns_s_ar
-
-#define QUERY		ns_o_query
-#define IQUERY		ns_o_iquery
-#define STATUS		ns_o_status
-#define	NS_NOTIFY_OP	ns_o_notify
-#define	NS_UPDATE_OP	ns_o_update
-
-#define NOERROR		ns_r_noerror
-#define FORMERR		ns_r_formerr
-#define SERVFAIL	ns_r_servfail
-#define NXDOMAIN	ns_r_nxdomain
-#define NOTIMP		ns_r_notimpl
-#define REFUSED		ns_r_refused
-#define YXDOMAIN	ns_r_yxdomain
-#define YXRRSET		ns_r_yxrrset
-#define NXRRSET		ns_r_nxrrset
-#define NOTAUTH		ns_r_notauth
-#define NOTZONE		ns_r_notzone
-
-#define DELETE		ns_uop_delete
-#define ADD		ns_uop_add
-
-#define T_A		ns_t_a
-#define T_NS		ns_t_ns
-#define T_MD		ns_t_md
-#define T_MF		ns_t_mf
-#define T_CNAME		ns_t_cname
-#define T_SOA		ns_t_soa
-#define T_MB		ns_t_mb
-#define T_MG		ns_t_mg
-#define T_MR		ns_t_mr
-#define T_NULL		ns_t_null
-#define T_WKS		ns_t_wks
-#define T_PTR		ns_t_ptr
-#define T_HINFO		ns_t_hinfo
-#define T_MINFO		ns_t_minfo
-#define T_MX		ns_t_mx
-#define T_TXT		ns_t_txt
-#define	T_RP		ns_t_rp
-#define T_AFSDB		ns_t_afsdb
-#define T_X25		ns_t_x25
-#define T_ISDN		ns_t_isdn
-#define T_RT		ns_t_rt
-#define T_NSAP		ns_t_nsap
-#define T_NSAP_PTR	ns_t_nsap_ptr
-#define	T_SIG		ns_t_sig
-#define	T_KEY		ns_t_key
-#define	T_PX		ns_t_px
-#define	T_GPOS		ns_t_gpos
-#define	T_AAAA		ns_t_aaaa
-#define	T_LOC		ns_t_loc
-#define	T_NXT		ns_t_nxt
-#define	T_EID		ns_t_eid
-#define	T_NIMLOC	ns_t_nimloc
-#define	T_SRV		ns_t_srv
-#define T_ATMA		ns_t_atma
-#define T_NAPTR		ns_t_naptr
-#define T_A6		ns_t_a6
-#define T_DNAME		ns_t_dname
-#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 C_IN		ns_c_in
-#define C_CHAOS		ns_c_chaos
-#define C_HS		ns_c_hs
-#define C_NONE		ns_c_none
-#define C_ANY		ns_c_any
-
-#define	GETSHORT		NS_GET16
-#define	GETLONG			NS_GET32
-#define	PUTSHORT		NS_PUT16
-#define	PUTLONG			NS_PUT32
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
lib/libc/include/wasm-wasi-musl/sys/stat.h
@@ -18,6 +18,13 @@ extern "C" {
 #define __NEED_blkcnt_t
 #define __NEED_struct_timespec
 
+#ifdef _GNU_SOURCE
+#define __NEED_int64_t
+#define __NEED_uint64_t
+#define __NEED_uint32_t
+#define __NEED_uint16_t
+#endif
+
 #include <bits/alltypes.h>
 
 #include <bits/stat.h>
@@ -112,6 +119,56 @@ int lchmod(const char *, mode_t);
 #define S_IEXEC S_IXUSR
 #endif
 
+#ifdef __wasilibc_unmodified_upstream /* WASI has no statx */
+#if defined(_GNU_SOURCE)
+#define STATX_TYPE 1U
+#define STATX_MODE 2U
+#define STATX_NLINK 4U
+#define STATX_UID 8U
+#define STATX_GID 0x10U
+#define STATX_ATIME 0x20U
+#define STATX_MTIME 0x40U
+#define STATX_CTIME 0x80U
+#define STATX_INO 0x100U
+#define STATX_SIZE 0x200U
+#define STATX_BLOCKS 0x400U
+#define STATX_BASIC_STATS 0x7ffU
+#define STATX_BTIME 0x800U
+#define STATX_ALL 0xfffU
+
+struct statx_timestamp {
+	int64_t tv_sec;
+	uint32_t tv_nsec, __pad;
+};
+
+struct statx {
+	uint32_t stx_mask;
+	uint32_t stx_blksize;
+	uint64_t stx_attributes;
+	uint32_t stx_nlink;
+	uint32_t stx_uid;
+	uint32_t stx_gid;
+	uint16_t stx_mode;
+	uint16_t __pad0[1];
+	uint64_t stx_ino;
+	uint64_t stx_size;
+	uint64_t stx_blocks;
+	uint64_t stx_attributes_mask;
+	struct statx_timestamp stx_atime;
+	struct statx_timestamp stx_btime;
+	struct statx_timestamp stx_ctime;
+	struct statx_timestamp stx_mtime;
+	uint32_t stx_rdev_major;
+	uint32_t stx_rdev_minor;
+	uint32_t stx_dev_major;
+	uint32_t stx_dev_minor;
+	uint64_t __pad1[14];
+};
+
+int statx(int, const char *__restrict, int, unsigned, struct statx *__restrict);
+#endif
+#endif
+
 #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
 #define stat64 stat
 #define fstat64 fstat
lib/libc/include/wasm-wasi-musl/sys/statvfs.h
@@ -23,7 +23,8 @@ struct statvfs {
 	unsigned long f_fsid;
 #endif
 	unsigned long f_flag, f_namemax;
-	int __reserved[6];
+	unsigned int f_type;
+	int __reserved[5];
 };
 
 int statvfs (const char *__restrict, struct statvfs *__restrict);
lib/libc/include/wasm-wasi-musl/sys/uio.h
@@ -36,9 +36,18 @@ ssize_t pwritev (int, const struct iovec *, int, off_t);
 #endif
 #endif
 
+#ifdef __wasilibc_unmodified_upstream // Wasm doesn't have these Linux-specific functions
 #ifdef _GNU_SOURCE
 ssize_t process_vm_writev(pid_t, const struct iovec *, unsigned long, const struct iovec *, unsigned long, unsigned long);
 ssize_t process_vm_readv(pid_t, const struct iovec *, unsigned long, const struct iovec *, unsigned long, unsigned long);
+ssize_t preadv2 (int, const struct iovec *, int, off_t, int);
+ssize_t pwritev2 (int, const struct iovec *, int, off_t, int);
+#define RWF_HIPRI 0x00000001
+#define RWF_DSYNC 0x00000002
+#define RWF_SYNC 0x00000004
+#define RWF_NOWAIT 0x00000008
+#define RWF_APPEND 0x00000010
+#endif
 #endif
 
 #ifdef __cplusplus
lib/libc/include/wasm-wasi-musl/wasi/libc-busywait.h
@@ -0,0 +1,15 @@
+#ifndef __wasi_libc_busywait_h
+#define __wasi_libc_busywait_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Enable busywait in futex on current thread.
+void __wasilibc_enable_futex_busywait_on_current_thread(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif 
lib/libc/include/wasm-wasi-musl/wasi/libc.h
@@ -3,6 +3,7 @@
 
 #include <__typedef_off_t.h>
 #include <__struct_timespec.h>
+#include <unistd.h>
 
 #ifdef __cplusplus
 extern "C" {
@@ -17,10 +18,6 @@ struct timespec;
 /// afterward, you should call this before doing so.
 void __wasilibc_populate_preopens(void);
 
-/// Reset the preopens table to an uninitialized state, forcing it to be
-/// reinitialized next time it is needed.
-void __wasilibc_reset_preopens(void);
-
 /// Register the given pre-opened file descriptor under the given path.
 ///
 /// This function does not take ownership of `prefix` (it makes its own copy).
@@ -68,6 +65,13 @@ int __wasilibc_rename_oldat(int olddirfd, const char *oldpath, const char *newpa
 int __wasilibc_rename_newat(const char *oldpath, int newdirfd, const char *newpath)
     __attribute__((__warn_unused_result__));
 
+/// Enable busywait in futex on current thread.
+void __wasilibc_enable_futex_busywait_on_current_thread(void);
+
+/// Fill a buffer with random bytes
+int __wasilibc_random(void* buffer, size_t len)
+   __attribute__((__warn_unused_result__));
+
 #ifdef __cplusplus
 }
 #endif
lib/libc/include/wasm-wasi-musl/__macro_PAGESIZE.h
@@ -2,15 +2,23 @@
 #define __wasilibc___macro_PAGESIZE_h
 
 /*
- * The page size in WebAssembly is fixed at 64 KiB. If this ever changes,
- * it's expected that applications will need to opt in, so we can change
- * this.
+ * Without custom-page-sizes proposal, the page size in WebAssembly
+ * is fixed at 64 KiB.
+ *
+ * The LLVM versions with a support of custom-page-sizes proposal
+ * provides __wasm_first_page_end global to allow page-size-agnostic
+ * objects.
  *
  * If this ever needs to be a value outside the range of an `int`, the
  * `getpagesize` function which returns this value will need special
  * consideration. POSIX has deprecated `getpagesize` in favor of
  * `sysconf(_SC_PAGESIZE)` which does not have this problem.
  */
+#if __clang_major__ >= 22
+extern char __wasm_first_page_end;
+#define PAGESIZE ((unsigned long)&__wasm_first_page_end)
+#else
 #define PAGESIZE (0x10000)
+#endif
 
 #endif
lib/libc/include/wasm-wasi-musl/__wasi_snapshot.h
@@ -0,0 +1,5 @@
+/* This file is (practically) empty by default.  The Makefile will replace it
+   with a non-empty version that defines `__wasilibc_use_wasip2` if targeting
+   `wasm32-wasip2`.
+ */
+
lib/libc/include/wasm-wasi-musl/fcntl.h
@@ -203,7 +203,6 @@ struct f_owner_ex {
 #endif
 #ifdef __wasilibc_unmodified_upstream /* WASI has no fallocate */
 int fallocate(int, int, off_t, off_t);
-#define fallocate64 fallocate
 #endif
 #ifdef __wasilibc_unmodified_upstream /* WASI has no name_to_handle_at */
 int name_to_handle_at(int, const char *, struct file_handle *, int *, int);
@@ -237,6 +236,11 @@ ssize_t tee(int, int, size_t, unsigned);
 #define posix_fadvise64 posix_fadvise
 #define posix_fallocate64 posix_fallocate
 #define off64_t off_t
+#ifdef __wasilibc_unmodified_upstream /* WASI has no fallocate */
+#if defined(_GNU_SOURCE)
+#define fallocate64 fallocate
+#endif
+#endif
 #endif
 
 #ifdef __cplusplus
lib/libc/include/wasm-wasi-musl/fts.h
@@ -0,0 +1,155 @@
+/*	$NetBSD: fts.h,v 1.19 2009/08/16 19:33:38 christos Exp $	*/
+
+/*
+ * Copyright (c) 1989, 1993
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ *	@(#)fts.h	8.3 (Berkeley) 8/14/94
+ */
+
+#ifndef	_FTS_H_
+#define	_FTS_H_
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifndef	__fts_stat_t
+#define	__fts_stat_t	struct stat
+#endif
+#ifndef	__fts_nlink_t
+#define	__fts_nlink_t	nlink_t
+#endif
+#ifndef	__fts_ino_t
+#define	__fts_ino_t	ino_t
+#endif
+#ifndef	__fts_length_t
+#define	__fts_length_t	unsigned int
+#endif
+#ifndef	__fts_number_t
+#define	__fts_number_t	int64_t
+#endif
+#ifndef	__fts_dev_t
+#define	__fts_dev_t	dev_t
+#endif
+#ifndef	__fts_level_t
+#define	__fts_level_t	int
+#endif
+
+typedef struct {
+	struct _ftsent *fts_cur;	/* current node */
+	struct _ftsent *fts_child;	/* linked list of children */
+	struct _ftsent **fts_array;	/* sort array */
+	dev_t fts_dev;			/* starting device # */
+	char *fts_path;			/* path for this descent */
+	int fts_rfd;			/* fd for root */
+	unsigned int fts_pathlen;	/* sizeof(path) */
+	unsigned int fts_nitems;	/* elements in the sort array */
+	int (*fts_compar)		/* compare function */
+		(const struct _ftsent **, const struct _ftsent **);
+
+#define	FTS_COMFOLLOW	0x001		/* follow command line symlinks */
+#define	FTS_LOGICAL	0x002		/* logical walk */
+#define	FTS_NOCHDIR	0x004		/* don't change directories */
+#define	FTS_NOSTAT	0x008		/* don't get stat info */
+#define	FTS_PHYSICAL	0x010		/* physical walk */
+#define	FTS_SEEDOT	0x020		/* return dot and dot-dot */
+#define	FTS_XDEV	0x040		/* don't cross devices */
+#define	FTS_WHITEOUT	0x080		/* return whiteout information */
+#define	FTS_OPTIONMASK	0x0ff		/* valid user option mask */
+
+#define	FTS_NAMEONLY	0x100		/* (private) child names only */
+#define	FTS_STOP	0x200		/* (private) unrecoverable error */
+	int fts_options;		/* fts_open options, global flags */
+} FTS;
+
+typedef struct _ftsent {
+	struct _ftsent *fts_cycle;	/* cycle node */
+	struct _ftsent *fts_parent;	/* parent directory */
+	struct _ftsent *fts_link;	/* next file in directory */
+	__fts_number_t fts_number;      /* local numeric value */
+	void *fts_pointer;	        /* local address value */
+	char *fts_accpath;		/* access path */
+	char *fts_path;			/* root path */
+	int fts_errno;			/* errno for this node */
+	int fts_symfd;			/* fd for symlink */
+	__fts_length_t fts_pathlen;	/* strlen(fts_path) */
+	__fts_length_t fts_namelen;	/* strlen(fts_name) */
+
+	__fts_ino_t fts_ino;		/* inode */
+	__fts_dev_t fts_dev;		/* device */
+	__fts_nlink_t fts_nlink;	/* link count */
+
+#define	FTS_ROOTPARENTLEVEL	-1
+#define	FTS_ROOTLEVEL		 0
+	__fts_level_t fts_level;		/* depth (-1 to N) */
+
+#define	FTS_D		 1		/* preorder directory */
+#define	FTS_DC		 2		/* directory that causes cycles */
+#define	FTS_DEFAULT	 3		/* none of the above */
+#define	FTS_DNR		 4		/* unreadable directory */
+#define	FTS_DOT		 5		/* dot or dot-dot */
+#define	FTS_DP		 6		/* postorder directory */
+#define	FTS_ERR		 7		/* error; errno is set */
+#define	FTS_F		 8		/* regular file */
+#define	FTS_INIT	 9		/* initialized only */
+#define	FTS_NS		10		/* stat(2) failed */
+#define	FTS_NSOK	11		/* no stat(2) requested */
+#define	FTS_SL		12		/* symbolic link */
+#define	FTS_SLNONE	13		/* symbolic link without target */
+#define	FTS_W		14		/* whiteout object */
+	unsigned short fts_info;	/* user flags for FTSENT structure */
+
+#define	FTS_DONTCHDIR	 0x01		/* don't chdir .. to the parent */
+#define	FTS_SYMFOLLOW	 0x02		/* followed a symlink to get here */
+#define	FTS_ISW		 0x04		/* this is a whiteout object */
+	unsigned short fts_flags;	/* private flags for FTSENT structure */
+
+#define	FTS_AGAIN	 1		/* read node again */
+#define	FTS_FOLLOW	 2		/* follow symbolic link */
+#define	FTS_NOINSTR	 3		/* no instructions */
+#define	FTS_SKIP	 4		/* discard node */
+	unsigned short fts_instr;	/* fts_set() instructions */
+
+	__fts_stat_t *fts_statp;	/* stat(2) information */
+	char fts_name[1];		/* file name */
+} FTSENT;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+FTSENT	*fts_children(FTS *, int);
+int	 fts_close(FTS *);
+FTS	*fts_open(char * const *, int,
+    int (*)(const FTSENT **, const FTSENT **));
+FTSENT	*fts_read(FTS *);
+int	 fts_set(FTS *, FTSENT *, int);
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif /* !_FTS_H_ */
lib/libc/include/wasm-wasi-musl/limits.h
@@ -65,11 +65,9 @@
 
 /* Implementation choices... */
 
-#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
 #define PTHREAD_KEYS_MAX 128
 #define PTHREAD_STACK_MIN 2048
 #define PTHREAD_DESTRUCTOR_ITERATIONS 4
-#endif
 #if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
 #define SEM_VALUE_MAX 0x7fffffff
 #define SEM_NSEMS_MAX 256
lib/libc/include/wasm-wasi-musl/poll.h
@@ -48,7 +48,7 @@ struct pollfd {
 
 int poll (struct pollfd *, nfds_t, int);
 
-#ifdef _GNU_SOURCE
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
 #define __NEED_time_t
 #define __NEED_struct_timespec
 #define __NEED_sigset_t
@@ -57,7 +57,7 @@ int ppoll(struct pollfd *, nfds_t, const struct timespec *, const sigset_t *);
 #endif
 
 #if _REDIR_TIME64
-#ifdef _GNU_SOURCE
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
 __REDIR(ppoll, __ppoll_time64);
 #endif
 #endif
lib/libc/include/wasm-wasi-musl/pthread.h
@@ -0,0 +1,267 @@
+#ifndef _PTHREAD_H
+#define _PTHREAD_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <features.h>
+
+#define __NEED_time_t
+#define __NEED_clockid_t
+#define __NEED_struct_timespec
+#define __NEED_sigset_t
+#define __NEED_pthread_t
+#define __NEED_pthread_attr_t
+#define __NEED_pthread_mutexattr_t
+#define __NEED_pthread_condattr_t
+#define __NEED_pthread_rwlockattr_t
+#define __NEED_pthread_barrierattr_t
+#define __NEED_pthread_mutex_t
+#define __NEED_pthread_cond_t
+#define __NEED_pthread_rwlock_t
+#define __NEED_pthread_barrier_t
+#define __NEED_pthread_spinlock_t
+#define __NEED_pthread_key_t
+#define __NEED_pthread_once_t
+#define __NEED_size_t
+
+#include <bits/alltypes.h>
+
+#include <sched.h>
+#include <time.h>
+
+#define PTHREAD_CREATE_JOINABLE 0
+#define PTHREAD_CREATE_DETACHED 1
+
+#define PTHREAD_MUTEX_NORMAL 0
+#define PTHREAD_MUTEX_DEFAULT 0
+#define PTHREAD_MUTEX_RECURSIVE 1
+#define PTHREAD_MUTEX_ERRORCHECK 2
+
+#define PTHREAD_MUTEX_STALLED 0
+#define PTHREAD_MUTEX_ROBUST 1
+
+#define PTHREAD_PRIO_NONE 0
+#define PTHREAD_PRIO_INHERIT 1
+#define PTHREAD_PRIO_PROTECT 2
+
+#define PTHREAD_INHERIT_SCHED 0
+#define PTHREAD_EXPLICIT_SCHED 1
+
+#define PTHREAD_SCOPE_SYSTEM 0
+#define PTHREAD_SCOPE_PROCESS 1
+
+#define PTHREAD_PROCESS_PRIVATE 0
+#define PTHREAD_PROCESS_SHARED 1
+
+
+#define PTHREAD_MUTEX_INITIALIZER {{{0}}}
+#define PTHREAD_RWLOCK_INITIALIZER {{{0}}}
+#define PTHREAD_COND_INITIALIZER {{{0}}}
+#define PTHREAD_ONCE_INIT 0
+
+
+#define PTHREAD_CANCEL_ENABLE 0
+#define PTHREAD_CANCEL_DISABLE 1
+#define PTHREAD_CANCEL_MASKED 2
+
+#define PTHREAD_CANCEL_DEFERRED 0
+#define PTHREAD_CANCEL_ASYNCHRONOUS 1
+
+#define PTHREAD_CANCELED ((void *)-1)
+
+
+#define PTHREAD_BARRIER_SERIAL_THREAD (-1)
+
+
+#define PTHREAD_NULL ((pthread_t)0)
+
+
+#ifdef __wasilibc_unmodified_upstream
+int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict);
+int pthread_detach(pthread_t);
+_Noreturn void pthread_exit(void *);
+int pthread_join(pthread_t, void **);
+#else
+#if defined(_REENTRANT) || !defined(_WASI_STRICT_PTHREAD)
+int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict);
+int pthread_detach(pthread_t);
+int pthread_join(pthread_t, void **);
+#else
+#define pthread_create(...) ({ _Static_assert(0, "This function is not available on a single-threaded target; switch to a multi-threaded target with -pthread or enable a stub implementation by undefining _WASI_STRICT_PTHREAD"); 0;})
+#define pthread_detach(...) ({ _Static_assert(0, "This function is not available on a single-threaded target; switch to a multi-threaded target with -pthread or enable a stub implementation by undefining _WASI_STRICT_PTHREAD"); 0;})
+#define pthread_join(...) ({ _Static_assert(0, "This function is not available on a single-threaded target; switch to a multi-threaded target with -pthread or enable a stub implementation by undefining _WASI_STRICT_PTHREAD"); 0;})
+#endif
+#endif
+
+#ifdef __GNUC__
+__attribute__((const))
+#endif
+pthread_t pthread_self(void);
+
+int pthread_equal(pthread_t, pthread_t);
+#ifndef __cplusplus
+#define pthread_equal(x,y) ((x)==(y))
+#endif
+
+int pthread_setcancelstate(int, int *);
+int pthread_setcanceltype(int, int *);
+void pthread_testcancel(void);
+#ifdef __wasilibc_unmodified_upstream /* WASI has no cancellation support. */
+int pthread_cancel(pthread_t);
+#endif
+
+#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */
+int pthread_getschedparam(pthread_t, int *__restrict, struct sched_param *__restrict);
+int pthread_setschedparam(pthread_t, int, const struct sched_param *);
+#endif
+int pthread_setschedprio(pthread_t, int);
+
+int pthread_once(pthread_once_t *, void (*)(void));
+
+int pthread_mutex_init(pthread_mutex_t *__restrict, const pthread_mutexattr_t *__restrict);
+int pthread_mutex_lock(pthread_mutex_t *);
+int pthread_mutex_unlock(pthread_mutex_t *);
+int pthread_mutex_trylock(pthread_mutex_t *);
+int pthread_mutex_timedlock(pthread_mutex_t *__restrict, const struct timespec *__restrict);
+int pthread_mutex_destroy(pthread_mutex_t *);
+int pthread_mutex_consistent(pthread_mutex_t *);
+
+int pthread_mutex_getprioceiling(const pthread_mutex_t *__restrict, int *__restrict);
+int pthread_mutex_setprioceiling(pthread_mutex_t *__restrict, int, int *__restrict);
+
+int pthread_cond_init(pthread_cond_t *__restrict, const pthread_condattr_t *__restrict);
+int pthread_cond_destroy(pthread_cond_t *);
+int pthread_cond_wait(pthread_cond_t *__restrict, pthread_mutex_t *__restrict);
+int pthread_cond_timedwait(pthread_cond_t *__restrict, pthread_mutex_t *__restrict, const struct timespec *__restrict);
+int pthread_cond_broadcast(pthread_cond_t *);
+int pthread_cond_signal(pthread_cond_t *);
+
+int pthread_rwlock_init(pthread_rwlock_t *__restrict, const pthread_rwlockattr_t *__restrict);
+int pthread_rwlock_destroy(pthread_rwlock_t *);
+int pthread_rwlock_rdlock(pthread_rwlock_t *);
+int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
+int pthread_rwlock_timedrdlock(pthread_rwlock_t *__restrict, const struct timespec *__restrict);
+int pthread_rwlock_wrlock(pthread_rwlock_t *);
+int pthread_rwlock_trywrlock(pthread_rwlock_t *);
+int pthread_rwlock_timedwrlock(pthread_rwlock_t *__restrict, const struct timespec *__restrict);
+int pthread_rwlock_unlock(pthread_rwlock_t *);
+
+int pthread_spin_init(pthread_spinlock_t *, int);
+int pthread_spin_destroy(pthread_spinlock_t *);
+int pthread_spin_lock(pthread_spinlock_t *);
+int pthread_spin_trylock(pthread_spinlock_t *);
+int pthread_spin_unlock(pthread_spinlock_t *);
+
+int pthread_barrier_init(pthread_barrier_t *__restrict, const pthread_barrierattr_t *__restrict, unsigned);
+int pthread_barrier_destroy(pthread_barrier_t *);
+int pthread_barrier_wait(pthread_barrier_t *);
+
+int pthread_key_create(pthread_key_t *, void (*)(void *));
+int pthread_key_delete(pthread_key_t);
+void *pthread_getspecific(pthread_key_t);
+int pthread_setspecific(pthread_key_t, const void *);
+
+int pthread_attr_init(pthread_attr_t *);
+int pthread_attr_destroy(pthread_attr_t *);
+
+int pthread_attr_getguardsize(const pthread_attr_t *__restrict, size_t *__restrict);
+int pthread_attr_setguardsize(pthread_attr_t *, size_t);
+int pthread_attr_getstacksize(const pthread_attr_t *__restrict, size_t *__restrict);
+int pthread_attr_setstacksize(pthread_attr_t *, size_t);
+int pthread_attr_getdetachstate(const pthread_attr_t *, int *);
+int pthread_attr_setdetachstate(pthread_attr_t *, int);
+int pthread_attr_getstack(const pthread_attr_t *__restrict, void **__restrict, size_t *__restrict);
+int pthread_attr_setstack(pthread_attr_t *, void *, size_t);
+int pthread_attr_getscope(const pthread_attr_t *__restrict, int *__restrict);
+int pthread_attr_setscope(pthread_attr_t *, int);
+int pthread_attr_getschedpolicy(const pthread_attr_t *__restrict, int *__restrict);
+int pthread_attr_setschedpolicy(pthread_attr_t *, int);
+#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */
+int pthread_attr_getschedparam(const pthread_attr_t *__restrict, struct sched_param *__restrict);
+int pthread_attr_setschedparam(pthread_attr_t *__restrict, const struct sched_param *__restrict);
+#endif
+int pthread_attr_getinheritsched(const pthread_attr_t *__restrict, int *__restrict);
+int pthread_attr_setinheritsched(pthread_attr_t *, int);
+
+int pthread_mutexattr_destroy(pthread_mutexattr_t *);
+int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *__restrict, int *__restrict);
+int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *__restrict, int *__restrict);
+int pthread_mutexattr_getpshared(const pthread_mutexattr_t *__restrict, int *__restrict);
+int pthread_mutexattr_getrobust(const pthread_mutexattr_t *__restrict, int *__restrict);
+int pthread_mutexattr_gettype(const pthread_mutexattr_t *__restrict, int *__restrict);
+int pthread_mutexattr_init(pthread_mutexattr_t *);
+int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int);
+int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int);
+int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
+int pthread_mutexattr_setrobust(pthread_mutexattr_t *, int);
+int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
+
+int pthread_condattr_init(pthread_condattr_t *);
+int pthread_condattr_destroy(pthread_condattr_t *);
+int pthread_condattr_setclock(pthread_condattr_t *, clockid_t);
+int pthread_condattr_setpshared(pthread_condattr_t *, int);
+int pthread_condattr_getclock(const pthread_condattr_t *__restrict, clockid_t *__restrict);
+int pthread_condattr_getpshared(const pthread_condattr_t *__restrict, int *__restrict);
+
+int pthread_rwlockattr_init(pthread_rwlockattr_t *);
+int pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
+int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
+int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *__restrict, int *__restrict);
+
+int pthread_barrierattr_destroy(pthread_barrierattr_t *);
+int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict, int *__restrict);
+int pthread_barrierattr_init(pthread_barrierattr_t *);
+int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int);
+
+int pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
+
+int pthread_getconcurrency(void);
+int pthread_setconcurrency(int);
+
+int pthread_getcpuclockid(pthread_t, clockid_t *);
+
+struct __ptcb {
+	void (*__f)(void *);
+	void *__x;
+	struct __ptcb *__next;
+};
+
+void _pthread_cleanup_push(struct __ptcb *, void (*)(void *), void *);
+void _pthread_cleanup_pop(struct __ptcb *, int);
+
+#define pthread_cleanup_push(f, x) do { struct __ptcb __cb; _pthread_cleanup_push(&__cb, f, x);
+#define pthread_cleanup_pop(r) _pthread_cleanup_pop(&__cb, (r)); } while(0)
+
+#ifdef _GNU_SOURCE
+struct cpu_set_t;
+int pthread_getaffinity_np(pthread_t, size_t, struct cpu_set_t *);
+int pthread_setaffinity_np(pthread_t, size_t, const struct cpu_set_t *);
+int pthread_getattr_np(pthread_t, pthread_attr_t *);
+int pthread_setname_np(pthread_t, const char *);
+int pthread_getname_np(pthread_t, char *, size_t);
+int pthread_getattr_default_np(pthread_attr_t *);
+int pthread_setattr_default_np(const pthread_attr_t *);
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) || !defined(_WASI_STRICT_PTHREAD)
+int pthread_tryjoin_np(pthread_t, void **);
+int pthread_timedjoin_np(pthread_t, void **, const struct timespec *);
+#else
+#define pthread_tryjoin_np(...) ({ _Static_assert(0, "This function is not available on a single-threaded target; switch to a multi-threaded target with -pthread or enable a stub implementation by undefining _WASI_STRICT_PTHREAD"); 0;})
+#define pthread_timedjoin_np(...) ({ _Static_assert(0, "This function is not available on a single-threaded target; switch to a multi-threaded target with -pthread or enable a stub implementation by undefining _WASI_STRICT_PTHREAD"); 0;})
+#endif
+#endif
+
+#if _REDIR_TIME64
+__REDIR(pthread_mutex_timedlock, __pthread_mutex_timedlock_time64);
+__REDIR(pthread_cond_timedwait, __pthread_cond_timedwait_time64);
+__REDIR(pthread_rwlock_timedrdlock, __pthread_rwlock_timedrdlock_time64);
+__REDIR(pthread_rwlock_timedwrlock, __pthread_rwlock_timedwrlock_time64);
+#ifdef _GNU_SOURCE
+__REDIR(pthread_timedjoin_np, __pthread_timedjoin_np_time64);
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
lib/libc/include/wasm-wasi-musl/sched.h
@@ -16,7 +16,6 @@ extern "C" {
 
 #include <bits/alltypes.h>
 
-#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */
 struct sched_param {
 	int sched_priority;
 	int __reserved1;
@@ -31,6 +30,7 @@ struct sched_param {
 	int __reserved3;
 };
 
+#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */
 int    sched_get_priority_max(int);
 int    sched_get_priority_min(int);
 int    sched_getparam(pid_t, struct sched_param *);
@@ -127,7 +127,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/include/wasm-wasi-musl/stdc-predef.h
@@ -1,13 +0,0 @@
-#ifndef _STDC_PREDEF_H
-#define _STDC_PREDEF_H
-
-#define __STDC_ISO_10646__ 201206L
-
-#if !defined(__GCC_IEC_559) || __GCC_IEC_559 > 0
-#define __STDC_IEC_559__ 1
-#endif
-
-#define __STDC_UTF_16__ 1
-#define __STDC_UTF_32__ 1
-
-#endif
lib/libc/include/wasm-wasi-musl/stdlib.h
@@ -108,7 +108,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)
 #endif
 
@@ -190,7 +190,7 @@ long double strtold_l(const char *__restrict, char **__restrict, struct __locale
 #endif
 
 #ifdef __wasilibc_unmodified_upstream /* WASI has no temp directories */
-#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/include/wasm-wasi-musl/string.h
@@ -92,6 +92,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) \
@@ -111,14 +112,8 @@ 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);
-#ifdef __wasilibc_unmodified_upstream /* avoid unprototyped decls; use <libgen.h> */
-#ifndef __cplusplus
-char *basename();
-#endif
-#endif
 #endif
 
 #ifdef __cplusplus
lib/libc/include/wasm-wasi-musl/strings.h
@@ -1,39 +0,0 @@
-#ifndef	_STRINGS_H
-#define	_STRINGS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define __NEED_size_t
-#define __NEED_locale_t
-#include <bits/alltypes.h>
-
-#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_POSIX_SOURCE) \
- || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE+0 < 200809L) \
- || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700)
-int bcmp (const void *, const void *, size_t);
-void bcopy (const void *, void *, size_t);
-void bzero (void *, size_t);
-char *index (const char *, int);
-char *rindex (const char *, int);
-#endif
-
-#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE)  || defined(_BSD_SOURCE)
-int ffs (int);
-int ffsl (long);
-int ffsll (long long);
-#endif
-
-int strcasecmp (const char *, const char *);
-int strncasecmp (const char *, const char *, size_t);
-
-int strcasecmp_l (const char *, const char *, locale_t);
-int strncasecmp_l (const char *, const char *, size_t, locale_t);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
lib/libc/include/wasm-wasi-musl/unistd.h
@@ -336,15 +336,21 @@ pid_t gettid(void);
 #endif
 #define _POSIX_VDISABLE         0
 
-#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) || !defined(_WASI_STRICT_PTHREAD)
 #define _POSIX_THREADS          _POSIX_VERSION
-#endif
 #define _POSIX_THREAD_PROCESS_SHARED _POSIX_VERSION
 #define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION
+#endif
+#if defined(__wasilibc_unmodified_upstream) /* wasi-libc doesn't provide pthread_attr_{get,set}stackaddr */
 #define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION
+#endif
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) || !defined(_WASI_STRICT_PTHREAD)
 #define _POSIX_THREAD_ATTR_STACKSIZE _POSIX_VERSION
+#endif
+#if defined(__wasilibc_unmodified_upstream) /* WASI has no scheduling control, and wasi-libc doesn't provide pthread_getcpuclockid */
 #define _POSIX_THREAD_PRIORITY_SCHEDULING _POSIX_VERSION
 #define _POSIX_THREAD_CPUTIME   _POSIX_VERSION
+#endif
 #define _POSIX_TIMERS           _POSIX_VERSION
 #define _POSIX_TIMEOUTS         _POSIX_VERSION
 #define _POSIX_MONOTONIC_CLOCK  _POSIX_VERSION
@@ -529,6 +535,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
@@ -571,6 +579,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/wasi/fts/musl-fts/COPYING
@@ -0,0 +1,26 @@
+Copyright (c) 1989, 1993
+   The Regents of the University of California.  All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+   notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+   notice, this list of conditions and the following disclaimer in the
+   documentation and/or other materials provided with the distribution.
+3. Neither the name of the University nor the names of its contributors
+   may be used to endorse or promote products derived from this software
+   without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
lib/libc/wasi/fts/musl-fts/fts.c
@@ -0,0 +1,1279 @@
+/*	$NetBSD: fts.c,v 1.48 2015/01/29 15:55:21 manu Exp $	*/
+
+/*-
+ * Copyright (c) 1990, 1993, 1994
+ *	The Regents of the University of California.  All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in the
+ *    documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ *    may be used to endorse or promote products derived from this software
+ *    without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+#if 0
+static char sccsid[] = "@(#)fts.c	8.6 (Berkeley) 8/14/94";
+#else
+__RCSID("$NetBSD: fts.c,v 1.48 2015/01/29 15:55:21 manu Exp $");
+#endif
+#endif /* LIBC_SCCS and not lint */
+
+#include "config.h"
+
+#include <sys/param.h>
+#include <sys/stat.h>
+
+#include <assert.h>
+#define _DIAGASSERT(e)
+#include <dirent.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <fts.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#if !defined(HAVE_DECL_MAX) || (HAVE_DECL_MAX==0)
+#define MAX(a,b) ((a)>(b)?(a):(b))
+#endif
+
+#if !defined(UINT_MAX) && (HAVE_DECL_UINTMAX_MAX==1)
+#define UINT_MAX UINTMAX_MAX
+#endif
+
+#if !defined(HAVE_DIRFD)
+#if defined(HAVE_DIR_DD_FD)
+#define dirfd(dirp)     ((dirp)->dd_fd)
+#endif
+#if defined(HAVE_DIR_D_FD)
+#define dirfd(dirp)     ((dirp)->d_fd)
+#endif
+#endif
+
+static FTSENT	*fts_alloc(FTS *, const char *, size_t);
+static FTSENT	*fts_build(FTS *, int);
+static void	 fts_free(FTSENT *);
+static void	 fts_lfree(FTSENT *);
+static void	 fts_load(FTS *, FTSENT *);
+static size_t	 fts_maxarglen(char * const *);
+static size_t	 fts_pow2(size_t);
+static int	 fts_palloc(FTS *, size_t);
+static void	 fts_padjust(FTS *, FTSENT *);
+static FTSENT	*fts_sort(FTS *, FTSENT *, size_t);
+static unsigned short fts_stat(FTS *, FTSENT *, int);
+static int	 fts_safe_changedir(const FTS *, const FTSENT *, int,
+    const char *);
+
+#if defined(ALIGNBYTES) && defined(ALIGN)
+#define	FTS_ALLOC_ALIGNED	1
+#else
+#undef	FTS_ALLOC_ALIGNED
+#endif
+
+#ifndef ftsent_namelen_truncate
+#define ftsent_namelen_truncate(a)	\
+    ((a) > UINT_MAX ? UINT_MAX : (unsigned int)(a))
+#endif
+#ifndef ftsent_pathlen_truncate
+#define ftsent_pathlen_truncate(a) \
+    ((a) > UINT_MAX ? UINT_MAX : (unsigned int)(a))
+#endif
+#ifndef fts_pathlen_truncate
+#define fts_pathlen_truncate(a)	\
+    ((a) > UINT_MAX ? UINT_MAX : (unsigned int)(a))
+#endif
+#ifndef fts_nitems_truncate
+#define fts_nitems_truncate(a) \
+    ((a) > UINT_MAX ? UINT_MAX : (unsigned int)(a))
+#endif
+
+#define	ISDOT(a)	(a[0] == '.' && (!a[1] || (a[1] == '.' && !a[2])))
+
+#define	CLR(opt)	(sp->fts_options &= ~(opt))
+#define	ISSET(opt)	(sp->fts_options & (opt))
+#define	SET(opt)	(sp->fts_options |= (opt))
+
+#if HAVE_FCHDIR
+#define	CHDIR(sp, path)	(!ISSET(FTS_NOCHDIR) && chdir(path))
+#define	FCHDIR(sp, fd)	(!ISSET(FTS_NOCHDIR) && fchdir(fd))
+#else
+/* If we don't have fchdir, pretend that !ISSET(FTS_NOCHDIR) is always false in
+ * the above macros, and do not reference chdir or fchdir. */
+#define	CHDIR(sp, path)	0
+#define	FCHDIR(sp, fd)	0
+#endif
+
+/* fts_build flags */
+#define	BCHILD		1		/* fts_children */
+#define	BNAMES		2		/* fts_children, names only */
+#define	BREAD		3		/* fts_read */
+
+#ifndef DTF_HIDEW
+#undef FTS_WHITEOUT
+#endif
+
+FTS *
+fts_open(char * const *argv, int options,
+    int (*compar)(const FTSENT **, const FTSENT **))
+{
+	FTS *sp;
+	FTSENT *p, *root;
+	size_t nitems;
+	FTSENT *parent, *tmp = NULL;	/* pacify gcc */
+	size_t len;
+
+	_DIAGASSERT(argv != NULL);
+
+#if !HAVE_FCHDIR
+        /* If we don't have fchdir, pretend that FTS_NOCHDIR is always set. */
+        options |= FTS_NOCHDIR;
+#endif
+
+	/* Options check. */
+	if (options & ~FTS_OPTIONMASK) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	/* Allocate/initialize the stream */
+	if ((sp = malloc(sizeof(FTS))) == NULL)
+		return (NULL);
+	memset(sp, 0, sizeof(FTS));
+	sp->fts_compar = compar;
+	sp->fts_options = options;
+
+	/* Logical walks turn on NOCHDIR; symbolic links are too hard. */
+	if (ISSET(FTS_LOGICAL))
+		SET(FTS_NOCHDIR);
+
+	/*
+	 * Start out with 1K of path space, and enough, in any case,
+	 * to hold the user's paths.
+	 */
+	if (fts_palloc(sp, MAX(fts_maxarglen(argv), MAXPATHLEN)))
+		goto mem1;
+
+	/* Allocate/initialize root's parent. */
+	if ((parent = fts_alloc(sp, "", 0)) == NULL)
+		goto mem2;
+	parent->fts_level = FTS_ROOTPARENTLEVEL;
+
+	/* Allocate/initialize root(s). */
+	for (root = NULL, nitems = 0; *argv; ++argv, ++nitems) {
+		/* Don't allow zero-length paths. */
+		if ((len = strlen(*argv)) == 0) {
+			errno = ENOENT;
+			goto mem3;
+		}
+
+		if ((p = fts_alloc(sp, *argv, len)) == NULL)
+			goto mem3;
+		p->fts_level = FTS_ROOTLEVEL;
+		p->fts_parent = parent;
+		p->fts_accpath = p->fts_name;
+		p->fts_info = fts_stat(sp, p, ISSET(FTS_COMFOLLOW));
+
+		/* Command-line "." and ".." are real directories. */
+		if (p->fts_info == FTS_DOT)
+			p->fts_info = FTS_D;
+
+		/*
+		 * If comparison routine supplied, traverse in sorted
+		 * order; otherwise traverse in the order specified.
+		 */
+		if (compar) {
+			p->fts_link = root;
+			root = p;
+		} else {
+			p->fts_link = NULL;
+			if (root == NULL)
+				tmp = root = p;
+			else {
+				tmp->fts_link = p;
+				tmp = p;
+			}
+		}
+	}
+	if (compar && nitems > 1)
+		root = fts_sort(sp, root, nitems);
+
+	/*
+	 * Allocate a dummy pointer and make fts_read think that we've just
+	 * finished the node before the root(s); set p->fts_info to FTS_INIT
+	 * so that everything about the "current" node is ignored.
+	 */
+	if ((sp->fts_cur = fts_alloc(sp, "", 0)) == NULL)
+		goto mem3;
+	sp->fts_cur->fts_link = root;
+	sp->fts_cur->fts_info = FTS_INIT;
+
+	/*
+	 * If using chdir(2), grab a file descriptor pointing to dot to ensure
+	 * that we can get back here; this could be avoided for some paths,
+	 * but almost certainly not worth the effort.  Slashes, symbolic links,
+	 * and ".." are all fairly nasty problems.  Note, if we can't get the
+	 * descriptor we run anyway, just more slowly.
+	 */
+#ifndef O_CLOEXEC
+#define O_CLOEXEC 0
+#endif
+	if (!ISSET(FTS_NOCHDIR)) {
+		if ((sp->fts_rfd = open(".", O_RDONLY | O_CLOEXEC, 0)) == -1)
+			SET(FTS_NOCHDIR);
+	}
+
+	if (nitems == 0)
+		fts_free(parent);
+
+	return (sp);
+
+mem3:	fts_lfree(root);
+	fts_free(parent);
+mem2:	free(sp->fts_path);
+mem1:	free(sp);
+	return (NULL);
+}
+
+static void
+fts_load(FTS *sp, FTSENT *p)
+{
+	size_t len;
+	char *cp;
+
+	_DIAGASSERT(sp != NULL);
+	_DIAGASSERT(p != NULL);
+
+	/*
+	 * Load the stream structure for the next traversal.  Since we don't
+	 * actually enter the directory until after the preorder visit, set
+	 * the fts_accpath field specially so the chdir gets done to the right
+	 * place and the user can access the first node.  From fts_open it's
+	 * known that the path will fit.
+	 */
+	len = p->fts_pathlen = p->fts_namelen;
+	memmove(sp->fts_path, p->fts_name, len + 1);
+	if ((cp = strrchr(p->fts_name, '/')) && (cp != p->fts_name || cp[1])) {
+		len = strlen(++cp);
+		memmove(p->fts_name, cp, len + 1);
+		p->fts_namelen = ftsent_namelen_truncate(len);
+	}
+	p->fts_accpath = p->fts_path = sp->fts_path;
+	sp->fts_dev = p->fts_dev;
+}
+
+int
+fts_close(FTS *sp)
+{
+	FTSENT *freep, *p;
+	int saved_errno = 0;
+
+	_DIAGASSERT(sp != NULL);
+
+	/*
+	 * This still works if we haven't read anything -- the dummy structure
+	 * points to the root list, so we step through to the end of the root
+	 * list which has a valid parent pointer.
+	 */
+	if (sp->fts_cur) {
+		if (sp->fts_cur->fts_flags & FTS_SYMFOLLOW)
+			(void)close(sp->fts_cur->fts_symfd);
+		for (p = sp->fts_cur; p->fts_level >= FTS_ROOTLEVEL;) {
+			freep = p;
+			p = p->fts_link ? p->fts_link : p->fts_parent;
+			fts_free(freep);
+		}
+		fts_free(p);
+	}
+
+	/* Free up child linked list, sort array, path buffer. */
+	if (sp->fts_child)
+		fts_lfree(sp->fts_child);
+	if (sp->fts_array)
+		free(sp->fts_array);
+	free(sp->fts_path);
+
+	#if HAVE_FCHDIR
+	/* Return to original directory, save errno if necessary. */
+	if (!ISSET(FTS_NOCHDIR)) {
+		if (fchdir(sp->fts_rfd) == -1)
+			saved_errno = errno;
+		(void)close(sp->fts_rfd);
+	}
+	#endif
+
+	/* Free up the stream pointer. */
+	free(sp);
+	if (saved_errno) {
+		errno = saved_errno;
+		return -1;
+	}
+
+	return 0;
+}
+
+#if !defined(__FTS_COMPAT_TAILINGSLASH)
+
+/*
+ * Special case of "/" at the end of the path so that slashes aren't
+ * appended which would cause paths to be written as "....//foo".
+ */
+#define	NAPPEND(p)							\
+	(p->fts_path[p->fts_pathlen - 1] == '/'				\
+	    ? p->fts_pathlen - 1 : p->fts_pathlen)
+
+#else /* !defined(__FTS_COMPAT_TAILINGSLASH) */
+
+/*
+ * compatibility with the old behaviour.
+ *
+ * Special case a root of "/" so that slashes aren't appended which would
+ * cause paths to be written as "//foo".
+ */
+
+#define	NAPPEND(p)							\
+	(p->fts_level == FTS_ROOTLEVEL && p->fts_pathlen == 1 &&	\
+	    p->fts_path[0] == '/' ? 0 : p->fts_pathlen)
+
+#endif /* !defined(__FTS_COMPAT_TAILINGSLASH) */
+
+FTSENT *
+fts_read(FTS *sp)
+{
+	FTSENT *p, *tmp;
+	int instr;
+	char *t;
+	int saved_errno;
+
+	_DIAGASSERT(sp != NULL);
+
+	/* If finished or unrecoverable error, return NULL. */
+	if (sp->fts_cur == NULL || ISSET(FTS_STOP))
+		return (NULL);
+
+	/* Set current node pointer. */
+	p = sp->fts_cur;
+
+	/* Save and zero out user instructions. */
+	instr = p->fts_instr;
+	p->fts_instr = FTS_NOINSTR;
+
+	/* Any type of file may be re-visited; re-stat and re-turn. */
+	if (instr == FTS_AGAIN) {
+		p->fts_info = fts_stat(sp, p, 0);
+		return (p);
+	}
+
+	/*
+	 * Following a symlink -- SLNONE test allows application to see
+	 * SLNONE and recover.  If indirecting through a symlink, have
+	 * keep a pointer to current location.  If unable to get that
+	 * pointer, follow fails.
+	 */
+	if (instr == FTS_FOLLOW &&
+	    (p->fts_info == FTS_SL || p->fts_info == FTS_SLNONE)) {
+		p->fts_info = fts_stat(sp, p, 1);
+		if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+			if ((p->fts_symfd = open(".", O_RDONLY | O_CLOEXEC, 0))
+			    == -1) {
+				p->fts_errno = errno;
+				p->fts_info = FTS_ERR;
+			} else
+				p->fts_flags |= FTS_SYMFOLLOW;
+		}
+		return (p);
+	}
+
+	/* Directory in pre-order. */
+	if (p->fts_info == FTS_D) {
+		/* If skipped or crossed mount point, do post-order visit. */
+		if (instr == FTS_SKIP ||
+		    (ISSET(FTS_XDEV) && p->fts_dev != sp->fts_dev)) {
+			if (p->fts_flags & FTS_SYMFOLLOW)
+				(void)close(p->fts_symfd);
+			if (sp->fts_child) {
+				fts_lfree(sp->fts_child);
+				sp->fts_child = NULL;
+			}
+			p->fts_info = FTS_DP;
+			return (p);
+		}
+
+		/* Rebuild if only read the names and now traversing. */
+		if (sp->fts_child && ISSET(FTS_NAMEONLY)) {
+			CLR(FTS_NAMEONLY);
+			fts_lfree(sp->fts_child);
+			sp->fts_child = NULL;
+		}
+
+		/*
+		 * Cd to the subdirectory.
+		 *
+		 * If have already read and now fail to chdir, whack the list
+		 * to make the names come out right, and set the parent errno
+		 * so the application will eventually get an error condition.
+		 * Set the FTS_DONTCHDIR flag so that when we logically change
+		 * directories back to the parent we don't do a chdir.
+		 *
+		 * If haven't read do so.  If the read fails, fts_build sets
+		 * FTS_STOP or the fts_info field of the node.
+		 */
+		if (sp->fts_child) {
+			if (fts_safe_changedir(sp, p, -1, p->fts_accpath)) {
+				p->fts_errno = errno;
+				p->fts_flags |= FTS_DONTCHDIR;
+				for (p = sp->fts_child; p; p = p->fts_link)
+					p->fts_accpath =
+					    p->fts_parent->fts_accpath;
+			}
+		} else if ((sp->fts_child = fts_build(sp, BREAD)) == NULL) {
+			if (ISSET(FTS_STOP))
+				return (NULL);
+			return (p);
+		}
+		p = sp->fts_child;
+		sp->fts_child = NULL;
+		goto name;
+	}
+
+next:	
+	/* Move to the next node on this level. */
+	tmp = p;
+
+	/* 
+	 * We are going to free sp->fts_cur, set it to NULL so 
+	 * that fts_close() does not attempt to free it again 
+	 * if we exit without setting it to a new value because
+	 * FCHDIR() failed below.
+	 */
+	assert(tmp == sp->fts_cur);
+	sp->fts_cur = NULL;
+	
+	if ((p = p->fts_link) != NULL) {
+		fts_free(tmp);
+
+		/*
+		 * If reached the top, return to the original directory, and
+		 * load the paths for the next root.
+		 */
+		if (p->fts_level == FTS_ROOTLEVEL) {
+			if (FCHDIR(sp, sp->fts_rfd)) {
+				SET(FTS_STOP);
+				return (NULL);
+			}
+			fts_load(sp, p);
+			return (sp->fts_cur = p);
+		}
+
+		/*
+		 * User may have called fts_set on the node.  If skipped,
+		 * ignore.  If followed, get a file descriptor so we can
+		 * get back if necessary.
+		 */
+		if (p->fts_instr == FTS_SKIP)
+			goto next;
+		if (p->fts_instr == FTS_FOLLOW) {
+			p->fts_info = fts_stat(sp, p, 1);
+			if (p->fts_info == FTS_D && !ISSET(FTS_NOCHDIR)) {
+				if ((p->fts_symfd =
+				    open(".", O_RDONLY | O_CLOEXEC, 0)) == -1) {
+					p->fts_errno = errno;
+					p->fts_info = FTS_ERR;
+				} else
+					p->fts_flags |= FTS_SYMFOLLOW;
+			}
+			p->fts_instr = FTS_NOINSTR;
+		}
+
+name:		t = sp->fts_path + NAPPEND(p->fts_parent);
+		*t++ = '/';
+		memmove(t, p->fts_name, (size_t)(p->fts_namelen + 1));
+		return (sp->fts_cur = p);
+	}
+
+	/* Move up to the parent node. */
+	p = tmp->fts_parent;
+	fts_free(tmp);
+
+	if (p->fts_level == FTS_ROOTPARENTLEVEL) {
+		/*
+		 * Done; free everything up and set errno to 0 so the user
+		 * can distinguish between error and EOF.
+		 */
+		fts_free(p);
+		errno = 0;
+		return (sp->fts_cur = NULL);
+	}
+
+	/* NUL terminate the pathname. */
+	sp->fts_path[p->fts_pathlen] = '\0';
+
+	/*
+	 * Return to the parent directory.  If at a root node or came through
+	 * a symlink, go back through the file descriptor.  Otherwise, cd up
+	 * one directory.
+	 */
+	if (p->fts_level == FTS_ROOTLEVEL) {
+		if (FCHDIR(sp, sp->fts_rfd)) {
+			SET(FTS_STOP);
+			return (NULL);
+		}
+	} else if (p->fts_flags & FTS_SYMFOLLOW) {
+		if (FCHDIR(sp, p->fts_symfd)) {
+			saved_errno = errno;
+			(void)close(p->fts_symfd);
+			errno = saved_errno;
+			SET(FTS_STOP);
+			return (NULL);
+		}
+		(void)close(p->fts_symfd);
+	} else if (!(p->fts_flags & FTS_DONTCHDIR) &&
+	    fts_safe_changedir(sp, p->fts_parent, -1, "..")) {
+		SET(FTS_STOP);
+		return (NULL);
+	}
+	p->fts_info = p->fts_errno ? FTS_ERR : FTS_DP;
+	return (sp->fts_cur = p);
+}
+
+/*
+ * Fts_set takes the stream as an argument although it's not used in this
+ * implementation; it would be necessary if anyone wanted to add global
+ * semantics to fts using fts_set.  An error return is allowed for similar
+ * reasons.
+ */
+/* ARGSUSED */
+int
+fts_set(FTS *sp, FTSENT *p, int instr)
+{
+
+	_DIAGASSERT(sp != NULL);
+	_DIAGASSERT(p != NULL);
+
+	if (instr && instr != FTS_AGAIN && instr != FTS_FOLLOW &&
+	    instr != FTS_NOINSTR && instr != FTS_SKIP) {
+		errno = EINVAL;
+		return (1);
+	}
+	p->fts_instr = instr;
+	return (0);
+}
+
+FTSENT *
+fts_children(FTS *sp, int instr)
+{
+	FTSENT *p;
+	int fd;
+
+	_DIAGASSERT(sp != NULL);
+
+	if (instr && instr != FTS_NAMEONLY) {
+		errno = EINVAL;
+		return (NULL);
+	}
+
+	/* Set current node pointer. */
+	p = sp->fts_cur;
+
+	/*
+	 * Errno set to 0 so user can distinguish empty directory from
+	 * an error.
+	 */
+	errno = 0;
+
+	/* Fatal errors stop here. */
+	if (ISSET(FTS_STOP))
+		return (NULL);
+
+	/* Return logical hierarchy of user's arguments. */
+	if (p->fts_info == FTS_INIT)
+		return (p->fts_link);
+
+	/*
+	 * If not a directory being visited in pre-order, stop here.  Could
+	 * allow FTS_DNR, assuming the user has fixed the problem, but the
+	 * same effect is available with FTS_AGAIN.
+	 */
+	if (p->fts_info != FTS_D /* && p->fts_info != FTS_DNR */)
+		return (NULL);
+
+	/* Free up any previous child list. */
+	if (sp->fts_child)
+		fts_lfree(sp->fts_child);
+
+	if (instr == FTS_NAMEONLY) {
+		SET(FTS_NAMEONLY);
+		instr = BNAMES;
+	} else
+		instr = BCHILD;
+
+	#if HAVE_FCHDIR
+	/*
+	 * If using chdir on a relative path and called BEFORE fts_read does
+	 * its chdir to the root of a traversal, we can lose -- we need to
+	 * chdir into the subdirectory, and we don't know where the current
+	 * directory is, so we can't get back so that the upcoming chdir by
+	 * fts_read will work.
+	 */
+	if (p->fts_level != FTS_ROOTLEVEL || p->fts_accpath[0] == '/' ||
+	    ISSET(FTS_NOCHDIR))
+		return (sp->fts_child = fts_build(sp, instr));
+
+	if ((fd = open(".", O_RDONLY | O_CLOEXEC, 0)) == -1)
+		return (sp->fts_child = NULL);
+	sp->fts_child = fts_build(sp, instr);
+	if (fchdir(fd)) {
+		(void)close(fd);
+		return (NULL);
+	}
+	(void)close(fd);
+	return (sp->fts_child);
+	#else
+	/* If not using chdir, just build the list. */
+	return (sp->fts_child = fts_build(sp, instr));
+	#endif
+}
+
+/*
+ * This is the tricky part -- do not casually change *anything* in here.  The
+ * idea is to build the linked list of entries that are used by fts_children
+ * and fts_read.  There are lots of special cases.
+ *
+ * The real slowdown in walking the tree is the stat calls.  If FTS_NOSTAT is
+ * set and it's a physical walk (so that symbolic links can't be directories),
+ * we can do things quickly.  First, if it's a 4.4BSD file system, the type
+ * of the file is in the directory entry.  Otherwise, we assume that the number
+ * of subdirectories in a node is equal to the number of links to the parent.
+ * The former skips all stat calls.  The latter skips stat calls in any leaf
+ * directories and for any files after the subdirectories in the directory have
+ * been found, cutting the stat calls by about 2/3.
+ */
+static FTSENT *
+fts_build(FTS *sp, int type)
+{
+	struct dirent *dp;
+	FTSENT *p, *head;
+	size_t nitems;
+	FTSENT *cur, *tail;
+	DIR *dirp;
+	void *oldaddr;
+	size_t dnamlen;
+	int cderrno, descend, level, nlinks, saved_errno, nostat, doadjust;
+	size_t len, maxlen;
+#ifdef FTS_WHITEOUT
+	int oflag;
+#endif
+	char *cp = NULL;	/* pacify gcc */
+
+	_DIAGASSERT(sp != NULL);
+
+	/* Set current node pointer. */
+	cur = sp->fts_cur;
+
+	/*
+	 * Open the directory for reading.  If this fails, we're done.
+	 * If being called from fts_read, set the fts_info field.
+	 */
+#ifdef FTS_WHITEOUT
+	if (ISSET(FTS_WHITEOUT))
+		oflag = DTF_NODUP|DTF_REWIND;
+	else
+		oflag = DTF_HIDEW|DTF_NODUP|DTF_REWIND;
+#else
+#define	__opendir2(path, flag) opendir(path)
+#endif
+	if ((dirp = __opendir2(cur->fts_accpath, oflag)) == NULL) {
+		if (type == BREAD) {
+			cur->fts_info = FTS_DNR;
+			cur->fts_errno = errno;
+		}
+		return (NULL);
+	}
+
+	/*
+	 * Nlinks is the number of possible entries of type directory in the
+	 * directory if we're cheating on stat calls, 0 if we're not doing
+	 * any stat calls at all, -1 if we're doing stats on everything.
+	 */
+	if (type == BNAMES) {
+		nlinks = 0;
+		nostat = 1;
+	} else if (ISSET(FTS_NOSTAT) && ISSET(FTS_PHYSICAL)) {
+		nlinks = cur->fts_nlink - (ISSET(FTS_SEEDOT) ? 0 : 2);
+		nostat = 1;
+	} else {
+		nlinks = -1;
+		nostat = 0;
+	}
+
+#ifdef notdef
+	(void)printf("nlinks == %d (cur: %d)\n", nlinks, cur->fts_nlink);
+	(void)printf("NOSTAT %d PHYSICAL %d SEEDOT %d\n",
+	    ISSET(FTS_NOSTAT), ISSET(FTS_PHYSICAL), ISSET(FTS_SEEDOT));
+#endif
+	/*
+	 * If we're going to need to stat anything or we want to descend
+	 * and stay in the directory, chdir.  If this fails we keep going,
+	 * but set a flag so we don't chdir after the post-order visit.
+	 * We won't be able to stat anything, but we can still return the
+	 * names themselves.  Note, that since fts_read won't be able to
+	 * chdir into the directory, it will have to return different path
+	 * names than before, i.e. "a/b" instead of "b".  Since the node
+	 * has already been visited in pre-order, have to wait until the
+	 * post-order visit to return the error.  There is a special case
+	 * here, if there was nothing to stat then it's not an error to
+	 * not be able to stat.  This is all fairly nasty.  If a program
+	 * needed sorted entries or stat information, they had better be
+	 * checking FTS_NS on the returned nodes.
+	 */
+	cderrno = 0;
+	if (nlinks || type == BREAD) {
+		if (fts_safe_changedir(sp, cur, dirfd(dirp), NULL)) {
+			if (nlinks && type == BREAD)
+				cur->fts_errno = errno;
+			cur->fts_flags |= FTS_DONTCHDIR;
+			descend = 0;
+			cderrno = errno;
+		} else
+			descend = 1;
+	} else
+		descend = 0;
+
+	/*
+	 * Figure out the max file name length that can be stored in the
+	 * current path -- the inner loop allocates more path as necessary.
+	 * We really wouldn't have to do the maxlen calculations here, we
+	 * could do them in fts_read before returning the path, but it's a
+	 * lot easier here since the length is part of the dirent structure.
+	 *
+	 * If not changing directories set a pointer so that can just append
+	 * each new name into the path.
+	 */
+	len = NAPPEND(cur);
+	if (ISSET(FTS_NOCHDIR)) {
+		cp = sp->fts_path + len;
+		*cp++ = '/';
+	}
+	len++;
+	maxlen = sp->fts_pathlen - len;
+
+#if defined(__FTS_COMPAT_LEVEL)
+	if (cur->fts_level == SHRT_MAX) {
+		(void)closedir(dirp);
+		cur->fts_info = FTS_ERR;
+		SET(FTS_STOP);
+		errno = ENAMETOOLONG;
+		return (NULL);
+	}
+#endif
+
+	level = cur->fts_level + 1;
+
+	/* Read the directory, attaching each entry to the `link' pointer. */
+	doadjust = 0;
+	for (head = tail = NULL, nitems = 0; (dp = readdir(dirp)) != NULL;) {
+
+		if (!ISSET(FTS_SEEDOT) && ISDOT(dp->d_name))
+			continue;
+
+#if defined(HAVE_STRUCT_DIRENT_D_NAMLEN)
+		dnamlen = dp->d_namlen;
+#else
+		dnamlen = strlen(dp->d_name);
+#endif
+		if ((p = fts_alloc(sp, dp->d_name, dnamlen)) == NULL)
+			goto mem1;
+		if (dnamlen >= maxlen) {	/* include space for NUL */
+			oldaddr = sp->fts_path;
+			if (fts_palloc(sp, dnamlen + len + 1)) {
+				/*
+				 * No more memory for path or structures.  Save
+				 * errno, free up the current structure and the
+				 * structures already allocated.
+				 */
+mem1:				saved_errno = errno;
+				if (p)
+					fts_free(p);
+				fts_lfree(head);
+				(void)closedir(dirp);
+				errno = saved_errno;
+				cur->fts_info = FTS_ERR;
+				SET(FTS_STOP);
+				return (NULL);
+			}
+			/* Did realloc() change the pointer? */
+			if (oldaddr != sp->fts_path) {
+				doadjust = 1;
+				if (ISSET(FTS_NOCHDIR))
+					cp = sp->fts_path + len;
+			}
+			maxlen = sp->fts_pathlen - len;
+		}
+
+#if defined(__FTS_COMPAT_LENGTH)
+		if (len + dnamlen >= USHRT_MAX) {
+			/*
+			 * In an FTSENT, fts_pathlen is an unsigned short
+			 * so it is possible to wraparound here.
+			 * If we do, free up the current structure and the
+			 * structures already allocated, then error out
+			 * with ENAMETOOLONG.
+			 */
+			fts_free(p);
+			fts_lfree(head);
+			(void)closedir(dirp);
+			cur->fts_info = FTS_ERR;
+			SET(FTS_STOP);
+			errno = ENAMETOOLONG;
+			return (NULL);
+		}
+#endif
+		p->fts_level = level;
+		p->fts_pathlen = ftsent_pathlen_truncate(len + dnamlen);
+		p->fts_parent = sp->fts_cur;
+
+#ifdef FTS_WHITEOUT
+		if (dp->d_type == DT_WHT)
+			p->fts_flags |= FTS_ISW;
+#endif
+
+		if (cderrno) {
+			if (nlinks) {
+				p->fts_info = FTS_NS;
+				p->fts_errno = cderrno;
+			} else
+				p->fts_info = FTS_NSOK;
+			p->fts_accpath = cur->fts_accpath;
+		} else if (nlinks == 0
+#ifdef DT_DIR
+		    || (nostat &&
+		    dp->d_type != DT_DIR && dp->d_type != DT_UNKNOWN)
+#endif
+		    ) {
+			p->fts_accpath =
+			    ISSET(FTS_NOCHDIR) ? p->fts_path : p->fts_name;
+			p->fts_info = FTS_NSOK;
+		} else {
+			/* Build a file name for fts_stat to stat. */
+			if (ISSET(FTS_NOCHDIR)) {
+				p->fts_accpath = p->fts_path;
+				memmove(cp, p->fts_name,
+				        (size_t)(p->fts_namelen + 1));
+			} else
+				p->fts_accpath = p->fts_name;
+			/* Stat it. */
+			p->fts_info = fts_stat(sp, p, 0);
+
+			/* Decrement link count if applicable. */
+			if (nlinks > 0 && (p->fts_info == FTS_D ||
+			    p->fts_info == FTS_DC || p->fts_info == FTS_DOT))
+				--nlinks;
+		}
+
+		/* We walk in directory order so "ls -f" doesn't get upset. */
+		p->fts_link = NULL;
+		if (head == NULL)
+			head = tail = p;
+		else {
+			tail->fts_link = p;
+			tail = p;
+		}
+		++nitems;
+	}
+	(void)closedir(dirp);
+
+	/*
+	 * If had to realloc the path, adjust the addresses for the rest
+	 * of the tree.
+	 */
+	if (doadjust)
+		fts_padjust(sp, head);
+
+	/*
+	 * If not changing directories, reset the path back to original
+	 * state.
+	 */
+	if (ISSET(FTS_NOCHDIR)) {
+		if (len == sp->fts_pathlen || nitems == 0)
+			--cp;
+		*cp = '\0';
+	}
+
+	/*
+	 * If descended after called from fts_children or after called from
+	 * fts_read and nothing found, get back.  At the root level we use
+	 * the saved fd; if one of fts_open()'s arguments is a relative path
+	 * to an empty directory, we wind up here with no other way back.  If
+	 * can't get back, we're done.
+	 */
+	if (descend && (type == BCHILD || !nitems) &&
+	    (cur->fts_level == FTS_ROOTLEVEL ?
+	    FCHDIR(sp, sp->fts_rfd) :
+	    fts_safe_changedir(sp, cur->fts_parent, -1, ".."))) {
+		cur->fts_info = FTS_ERR;
+		SET(FTS_STOP);
+		return (NULL);
+	}
+
+	/* If didn't find anything, return NULL. */
+	if (!nitems) {
+		if (type == BREAD)
+			cur->fts_info = FTS_DP;
+		return (NULL);
+	}
+
+	/* Sort the entries. */
+	if (sp->fts_compar && nitems > 1)
+		head = fts_sort(sp, head, nitems);
+	return (head);
+}
+
+static unsigned short
+fts_stat(FTS *sp, FTSENT *p, int follow)
+{
+	FTSENT *t;
+	dev_t dev;
+	__fts_ino_t ino;
+	__fts_stat_t *sbp, sb;
+	int saved_errno;
+
+	_DIAGASSERT(sp != NULL);
+	_DIAGASSERT(p != NULL);
+
+	/* If user needs stat info, stat buffer already allocated. */
+	sbp = ISSET(FTS_NOSTAT) ? &sb : p->fts_statp;
+
+#ifdef FTS_WHITEOUT
+	/* check for whiteout */
+	if (p->fts_flags & FTS_ISW) {
+		if (sbp != &sb) {
+			memset(sbp, '\0', sizeof (*sbp));
+			sbp->st_mode = S_IFWHT;
+		}
+		return (FTS_W);
+	}
+#endif
+
+	/*
+	 * If doing a logical walk, or application requested FTS_FOLLOW, do
+	 * a stat(2).  If that fails, check for a non-existent symlink.  If
+	 * fail, set the errno from the stat call.
+	 */
+	if (ISSET(FTS_LOGICAL) || follow) {
+		if (stat(p->fts_accpath, sbp)) {
+			saved_errno = errno;
+			if (!lstat(p->fts_accpath, sbp)) {
+				errno = 0;
+				return (FTS_SLNONE);
+			}
+			p->fts_errno = saved_errno;
+			goto err;
+		}
+	} else if (lstat(p->fts_accpath, sbp)) {
+		p->fts_errno = errno;
+err:		memset(sbp, 0, sizeof(*sbp));
+		return (FTS_NS);
+	}
+
+	if (S_ISDIR(sbp->st_mode)) {
+		/*
+		 * Set the device/inode.  Used to find cycles and check for
+		 * crossing mount points.  Also remember the link count, used
+		 * in fts_build to limit the number of stat calls.  It is
+		 * understood that these fields are only referenced if fts_info
+		 * is set to FTS_D.
+		 */
+		dev = p->fts_dev = sbp->st_dev;
+		ino = p->fts_ino = sbp->st_ino;
+		p->fts_nlink = sbp->st_nlink;
+
+		if (ISDOT(p->fts_name))
+			return (FTS_DOT);
+
+		/*
+		 * Cycle detection is done by brute force when the directory
+		 * is first encountered.  If the tree gets deep enough or the
+		 * number of symbolic links to directories is high enough,
+		 * something faster might be worthwhile.
+		 */
+		for (t = p->fts_parent;
+		    t->fts_level >= FTS_ROOTLEVEL; t = t->fts_parent)
+			if (ino == t->fts_ino && dev == t->fts_dev) {
+				p->fts_cycle = t;
+				return (FTS_DC);
+			}
+		return (FTS_D);
+	}
+	if (S_ISLNK(sbp->st_mode))
+		return (FTS_SL);
+	if (S_ISREG(sbp->st_mode))
+		return (FTS_F);
+	return (FTS_DEFAULT);
+}
+
+static FTSENT *
+fts_sort(FTS *sp, FTSENT *head, size_t nitems)
+{
+	FTSENT **ap, *p;
+
+	_DIAGASSERT(sp != NULL);
+	_DIAGASSERT(head != NULL);
+
+	/*
+	 * Construct an array of pointers to the structures and call qsort(3).
+	 * Reassemble the array in the order returned by qsort.  If unable to
+	 * sort for memory reasons, return the directory entries in their
+	 * current order.  Allocate enough space for the current needs plus
+	 * 40 so don't realloc one entry at a time.
+	 */
+	if (nitems > sp->fts_nitems) {
+		FTSENT **new;
+
+		new = realloc(sp->fts_array, sizeof(FTSENT *) * (nitems + 40));
+		if (new == 0)
+			return (head);
+		sp->fts_array = new;
+		sp->fts_nitems = fts_nitems_truncate(nitems + 40);
+	}
+	for (ap = sp->fts_array, p = head; p; p = p->fts_link)
+		*ap++ = p;
+	qsort((void *)sp->fts_array, nitems, sizeof(FTSENT *),
+		(int (*)(const void *, const void *))sp->fts_compar);
+	for (head = *(ap = sp->fts_array); --nitems; ++ap)
+		ap[0]->fts_link = ap[1];
+	ap[0]->fts_link = NULL;
+	return (head);
+}
+
+static FTSENT *
+fts_alloc(FTS *sp, const char *name, size_t namelen)
+{
+	FTSENT *p;
+#if defined(FTS_ALLOC_ALIGNED)
+	size_t len;
+#endif
+
+	_DIAGASSERT(sp != NULL);
+	_DIAGASSERT(name != NULL);
+
+#if defined(FTS_ALLOC_ALIGNED)
+	/*
+	 * The file name is a variable length array and no stat structure is
+	 * necessary if the user has set the nostat bit.  Allocate the FTSENT
+	 * structure, the file name and the stat structure in one chunk, but
+	 * be careful that the stat structure is reasonably aligned.  Since the
+	 * fts_name field is declared to be of size 1, the fts_name pointer is
+	 * namelen + 2 before the first possible address of the stat structure.
+	 */
+	len = sizeof(FTSENT) + namelen;
+	if (!ISSET(FTS_NOSTAT))
+		len += sizeof(*(p->fts_statp)) + ALIGNBYTES;
+	if ((p = malloc(len)) == NULL)
+		return (NULL);
+
+	if (!ISSET(FTS_NOSTAT))
+		p->fts_statp = (__fts_stat_t *)ALIGN(
+		    (unsigned long)(p->fts_name + namelen + 2));
+#else
+	if ((p = malloc(sizeof(FTSENT) + namelen)) == NULL)
+		return (NULL);
+
+	if (!ISSET(FTS_NOSTAT))
+		if ((p->fts_statp = malloc(sizeof(*(p->fts_statp)))) == NULL) {
+			free(p);
+			return (NULL);
+		}
+#endif
+
+        if (ISSET(FTS_NOSTAT))
+                p->fts_statp = NULL;
+
+	/* Copy the name plus the trailing NULL. */
+	memmove(p->fts_name, name, namelen + 1);
+
+	p->fts_namelen = ftsent_namelen_truncate(namelen);
+	p->fts_path = sp->fts_path;
+	p->fts_errno = 0;
+	p->fts_flags = 0;
+	p->fts_instr = FTS_NOINSTR;
+	p->fts_number = 0;
+	p->fts_pointer = NULL;
+	return (p);
+}
+
+static void
+fts_free(FTSENT *p)
+{
+#if !defined(FTS_ALLOC_ALIGNED)
+	if (p->fts_statp)
+		free(p->fts_statp);
+#endif
+	free(p);
+}
+
+static void
+fts_lfree(FTSENT *head)
+{
+	FTSENT *p;
+
+	/* XXX: head may be NULL ? */
+
+	/* Free a linked list of structures. */
+	while ((p = head) != NULL) {
+		head = head->fts_link;
+		fts_free(p);
+	}
+}
+
+static size_t
+fts_pow2(size_t x)
+{
+
+	x--;
+	x |= x>>1;
+	x |= x>>2;
+	x |= x>>4;
+	x |= x>>8;
+	x |= x>>16;
+#if LONG_BIT > 32
+	x |= x>>32;
+#endif
+#if LONG_BIT > 64
+	x |= x>>64;
+#endif
+	x++;
+	return (x);
+}
+
+/*
+ * Allow essentially unlimited paths; find, rm, ls should all work on any tree.
+ * Most systems will allow creation of paths much longer than MAXPATHLEN, even
+ * though the kernel won't resolve them.  Round up the new size to a power of 2,
+ * so we don't realloc the path 2 bytes at a time.
+ */
+static int
+fts_palloc(FTS *sp, size_t size)
+{
+	char *new;
+
+	_DIAGASSERT(sp != NULL);
+
+#ifdef __FTS_COMPAT_LENGTH
+	/* Protect against fts_pathlen overflow. */
+	if (size > USHRT_MAX + 1) {
+		errno = ENAMETOOLONG;
+		return (1);
+	}
+#endif
+	size = fts_pow2(size);
+	new = realloc(sp->fts_path, size);
+	if (new == 0)
+		return (1);
+	sp->fts_path = new;
+	sp->fts_pathlen = fts_pathlen_truncate(size);
+	return (0);
+}
+
+/*
+ * When the path is realloc'd, have to fix all of the pointers in structures
+ * already returned.
+ */
+static void
+fts_padjust(FTS *sp, FTSENT *head)
+{
+	FTSENT *p;
+	char *addr;
+
+	_DIAGASSERT(sp != NULL);
+
+#define	ADJUST(p) do {							\
+	if ((p)->fts_accpath != (p)->fts_name)				\
+		(p)->fts_accpath =					\
+		    addr + ((p)->fts_accpath - (p)->fts_path);		\
+	(p)->fts_path = addr;						\
+} while (/*CONSTCOND*/0)
+
+	addr = sp->fts_path;
+
+	/* Adjust the current set of children. */
+	for (p = sp->fts_child; p; p = p->fts_link)
+		ADJUST(p);
+
+	/* Adjust the rest of the tree, including the current level. */
+	for (p = head; p->fts_level >= FTS_ROOTLEVEL;) {
+		ADJUST(p);
+		p = p->fts_link ? p->fts_link : p->fts_parent;
+	}
+}
+
+static size_t
+fts_maxarglen(char * const *argv)
+{
+	size_t len, max;
+
+	_DIAGASSERT(argv != NULL);
+
+	for (max = 0; *argv; ++argv)
+		if ((len = strlen(*argv)) > max)
+			max = len;
+	return (max + 1);
+}
+
+/*
+ * Change to dir specified by fd or p->fts_accpath without getting
+ * tricked by someone changing the world out from underneath us.
+ * Assumes p->fts_dev and p->fts_ino are filled in.
+ */
+static int
+fts_safe_changedir(const FTS *sp, const FTSENT *p, int fd, const char *path)
+{
+#if HAVE_FCHDIR
+	int oldfd = fd, ret = -1;
+	__fts_stat_t sb;
+
+	if (ISSET(FTS_NOCHDIR))
+		return 0;
+
+	if (oldfd < 0 && (fd = open(path, O_RDONLY | O_CLOEXEC)) == -1)
+		return -1;
+
+	if (fstat(fd, &sb) == -1)
+		goto bail;
+
+	if (sb.st_ino != p->fts_ino || sb.st_dev != p->fts_dev) {
+		errno = ENOENT;
+		goto bail;
+	}
+
+	ret = fchdir(fd);
+
+bail:
+	if (oldfd < 0) {
+		int save_errno = errno;
+		(void)close(fd);
+		errno = save_errno;
+	}
+	return ret;
+#else
+	/* If we can't do fchdir, pretend as if ISSET(FTS_NOCHDIR) is set. */
+	return 0;
+#endif
+}
lib/libc/wasi/fts/config.h
@@ -0,0 +1,7 @@
+#define HAVE_DECL_MAX 1
+
+#define HAVE_DECL_UINTMAX_MAX 0
+
+#define HAVE_DIRFD 1
+
+#define HAVE_FCHDIR 0
lib/libc/wasi/libc-bottom-half/clocks/times.c
@@ -17,7 +17,8 @@ clock_t times(struct tms *buffer) {
     __wasi_timestamp_t user = __clock();
     *buffer = (struct tms){
         .tms_utime = user,
-        .tms_cutime = user
+        // WASI doesn't provide a way to spawn a new process, so always 0.
+        .tms_cutime = 0
     };
 
     __wasi_timestamp_t realtime = 0;
lib/libc/wasi/libc-bottom-half/cloudlibc/src/libc/stdlib/_Exit.c
@@ -2,13 +2,22 @@
 //
 // SPDX-License-Identifier: BSD-2-Clause
 
+#ifdef __wasilibc_use_wasip2
+#include <wasi/wasip2.h>
+#else
 #include <wasi/api.h>
+#endif
 #include <_/cdefs.h>
 #include <stdnoreturn.h>
 #include <unistd.h>
 
 noreturn void _Exit(int status) {
+#ifdef __wasilibc_use_wasip2
+  exit_result_void_void_t exit_status = { .is_err = status != 0 };
+  exit_exit(&exit_status);
+#else
   __wasi_proc_exit(status);
+#endif
 }
 
 __strong_reference(_Exit, _exit);
lib/libc/wasi/libc-bottom-half/crt/crt1-command.c
@@ -2,7 +2,11 @@
 #include <stdatomic.h>
 extern void __wasi_init_tp(void);
 #endif
+#ifdef __wasilibc_use_wasip2
+#include <wasi/wasip2.h>
+#else
 #include <wasi/api.h>
+#endif
 extern void __wasm_call_ctors(void);
 extern int __main_void(void);
 extern void __wasm_call_dtors(void);
@@ -47,7 +51,14 @@ void _start(void) {
 
     // If main exited successfully, just return, otherwise call
     // `__wasi_proc_exit`.
+#ifdef __wasilibc_use_wasip2
+    if (r != 0) {
+        exit_result_void_void_t status = { .is_err = true };
+        exit_exit(&status);
+    }
+#else
     if (r != 0) {
         __wasi_proc_exit(r);
     }
+#endif
 }
lib/libc/wasi/libc-bottom-half/headers/private/wasi/sockets_utils.h
@@ -26,6 +26,17 @@ typedef struct {
 	};
 } output_sockaddr_t;
 
+typedef struct {
+	char *s_name;
+	uint16_t port;
+	uint16_t protocol;
+} service_entry_t;
+
+typedef enum {
+	SERVICE_PROTOCOL_TCP = 1,
+	SERVICE_PROTOCOL_UDP = 2
+} service_protocol_e;
+
 network_borrow_network_t __wasi_sockets_utils__borrow_network();
 int __wasi_sockets_utils__map_error(network_error_code_t wasi_error);
 bool __wasi_sockets_utils__parse_address(
@@ -49,5 +60,8 @@ bool __wasi_sockets_utils__stream(udp_socket_t *socket,
 				  udp_socket_streams_t *result,
 				  network_error_code_t *error);
 void __wasi_sockets_utils__drop_streams(udp_socket_streams_t streams);
+int __wasi_sockets_utils__parse_port(const char *port);
+const service_entry_t *__wasi_sockets_utils__get_service_entry_by_name(const char *name);
+const service_entry_t *__wasi_sockets_utils__get_service_entry_by_port(const uint16_t port);
 
 #endif
lib/libc/wasi/libc-bottom-half/mman/mman.c
@@ -9,6 +9,7 @@
 #include <errno.h>
 #include <unistd.h>
 #include <string.h>
+#include <limits.h>
 #include <sys/mman.h>
 #include <sys/types.h>
 
@@ -122,3 +123,35 @@ int munmap(void *addr, size_t length) {
     // Success!
     return 0;
 }
+
+int mprotect(void *addr, size_t length, int prot) {
+    // Address must be page-aligned.
+    size_t begin = (size_t)addr;
+    if ((begin & (PAGESIZE - 1)) != 0) {
+        errno = EINVAL;
+        return -1;
+    }
+
+    // Length must not be big enough to wrap around.
+    size_t end;
+    if (__builtin_add_overflow(begin, length, &end)) {
+        errno = ENOMEM;
+        return -1;
+    }
+
+    // Range must be in bounds of linear memory.
+    size_t memory_size = __builtin_wasm_memory_size(0) * PAGESIZE;
+    if (end > memory_size) {
+        errno = ENOMEM;
+        return -1;
+    }
+
+    // Can only protect memory as read/write (which is a no-op).
+    if (prot != (PROT_READ | PROT_WRITE)) {
+        errno = ENOTSUP;
+        return -1;
+    }
+
+    // Success!
+    return 0;
+}
lib/libc/wasi/libc-bottom-half/sources/__main_void.c
@@ -1,19 +1,19 @@
+#ifdef __wasilibc_use_wasip2
+#include <wasi/wasip2.h>
+#else
 #include <wasi/api.h>
+#endif
 #include <stdlib.h>
 #include <sysexits.h>
 
-int __wasilibc_main(int argc, char *argv[]) asm("main");
-
 // The user's `main` function, expecting arguments.
 //
 // Note that we make this a weak symbol so that it will have a
 // `WASM_SYM_BINDING_WEAK` flag in libc.so, which tells the dynamic linker that
 // it need not be defined (e.g. in reactor-style apps with no main function).
 // See also the TODO comment on `__main_void` below.
-__attribute__((__weak__, nodebug))
-int __main_argc_argv(int argc, char *argv[]) {
-    return __wasilibc_main(argc, argv);
-}
+__attribute__((__weak__))
+int __main_argc_argv(int argc, char *argv[]);
 
 // If the user's `main` function expects arguments, the compiler will rename
 // it to `__main_argc_argv`, and this version will get linked in, which
@@ -25,6 +25,46 @@ int __main_argc_argv(int argc, char *argv[]) {
 // (e.g. crt0.o or crtend.o) and teach Clang to use it when needed.
 __attribute__((__weak__, nodebug))
 int __main_void(void) {
+#ifdef __wasilibc_use_wasip2
+    wasip2_list_string_t argument_list;
+
+    environment_get_arguments(&argument_list);
+
+    // Add 1 for the NULL pointer to mark the end, and check for overflow.
+    size_t argc = argument_list.len;
+    size_t num_ptrs = argc + 1;
+    if (num_ptrs == 0) {
+        wasip2_list_string_free(&argument_list);
+        _Exit(EX_SOFTWARE);
+    }
+
+    // Allocate memory for the array of pointers. This uses `calloc` both to
+    // handle overflow and to initialize the NULL pointer at the end.
+    char **argv = calloc(num_ptrs, sizeof(char *));
+    if (argv == NULL) {
+        wasip2_list_string_free(&argument_list);
+        _Exit(EX_SOFTWARE);
+    }
+
+    // Copy the arguments
+    for (size_t i = 0; i < argc; i++) {
+        wasip2_string_t wasi_string = argument_list.ptr[i];
+        size_t len = wasi_string.len;
+        argv[i] = malloc(len + 1);
+        if (!argv[i]) {
+            wasip2_list_string_free(&argument_list);
+            _Exit(EX_SOFTWARE);
+        }
+        memcpy(argv[i], wasi_string.ptr, len);
+        argv[i][len] = '\0';
+    }
+
+    // Free the WASI argument list
+    wasip2_list_string_free(&argument_list);
+
+    // Call `__main_argc_argv` with the arguments!
+    return __main_argc_argv(argc, argv);
+#else
     __wasi_errno_t err;
 
     // Get the sizes of the arrays we'll have to create to copy in the args.
@@ -66,4 +106,5 @@ int __main_void(void) {
 
     // Call `__main_argc_argv` with the arguments!
     return __main_argc_argv(argc, argv);
+#endif
 }
lib/libc/wasi/libc-bottom-half/sources/__wasilibc_initialize_environ.c
@@ -1,7 +1,11 @@
 #include <unistd.h>
 #include <stdlib.h>
 #include <sysexits.h>
+#ifdef __wasilibc_use_wasip2
+#include <wasi/wasip2.h>
+#else
 #include <wasi/api.h>
+#endif
 #include <wasi/libc.h>
 #include <wasi/libc-environ.h>
 
@@ -26,6 +30,55 @@ static char *empty_environ[1] = { NULL };
 
 // See the comments in libc-environ.h.
 void __wasilibc_initialize_environ(void) {
+#ifdef __wasilibc_use_wasip2
+    // Get the environment
+    wasip2_list_tuple2_string_string_t wasi_environment;
+    environment_get_environment(&wasi_environment);
+
+    size_t environ_count = wasi_environment.len;
+    if (environ_count == 0) {
+        __wasilibc_environ = empty_environ;
+        return;
+    }
+
+    // Add 1 for the NULL pointer to mark the end, and check for overflow.
+    size_t num_ptrs = environ_count + 1;
+    if (num_ptrs == 0) {
+        goto software;
+    }
+
+    // Allocate memory for the array of pointers. This uses `calloc` both to
+    // handle overflow and to initialize the NULL pointer at the end.
+    char **environ_ptrs = calloc(num_ptrs, sizeof(char *));
+
+    // Copy the environment variables
+    for (size_t i = 0; i < environ_count; i++) {
+        wasip2_tuple2_string_string_t pair = wasi_environment.ptr[i];
+        // 1 extra character for the null terminator, 1 for the '=' character
+        environ_ptrs[i] = malloc(pair.f0.len + pair.f1.len + 2);
+        if (!environ_ptrs[i]) {
+            for (size_t j = 0; j < i; j++)
+                free(environ_ptrs[j]);
+            free(environ_ptrs);
+            goto software;
+        }
+        memcpy(environ_ptrs[i], pair.f0.ptr, pair.f0.len);
+        environ_ptrs[i][pair.f0.len] = '=';
+        memcpy(environ_ptrs[i] + pair.f0.len + 1, pair.f1.ptr, pair.f1.len);
+        environ_ptrs[i][pair.f0.len + pair.f1.len + 1] = '\0';
+    }
+
+    // Free the WASI environment list
+    wasip2_list_tuple2_string_string_free(&wasi_environment);
+
+    // Initialize the environment from the created array
+    __wasilibc_environ = environ_ptrs;
+    return;
+software:
+    wasip2_list_tuple2_string_string_free(&wasi_environment);
+    _Exit(EX_SOFTWARE);
+
+#else
     // Get the sizes of the arrays we'll have to create to copy in the environment.
     size_t environ_count;
     size_t environ_buf_size;
@@ -74,6 +127,7 @@ oserr:
     _Exit(EX_OSERR);
 software:
     _Exit(EX_SOFTWARE);
+#endif
 }
 
 // See the comments in libc-environ.h.
lib/libc/wasi/libc-bottom-half/sources/__wasilibc_random.c
@@ -0,0 +1,29 @@
+#include <errno.h>
+#include <unistd.h>
+#ifdef __wasilibc_use_wasip2
+#include <wasi/wasip2.h>
+#include <sysexits.h>
+
+int __wasilibc_random(void *buffer, size_t len) {
+
+        // Set up a WASI byte list to receive the results
+        wasip2_list_u8_t wasi_list;
+
+        // Get random bytes
+        random_get_random_bytes(len, &wasi_list);
+
+        // The spec for get-random-bytes specifies that wasi_list.len
+        // will be equal to len.
+        if (wasi_list.len != len)
+            _Exit(EX_OSERR);
+        else {
+            // Copy the result
+            memcpy(buffer, wasi_list.ptr, len);
+        }
+
+        // Free the WASI byte list
+        wasip2_list_u8_free(&wasi_list);
+
+        return 0;
+}
+#endif
lib/libc/wasi/libc-bottom-half/sources/getentropy.c
@@ -1,6 +1,10 @@
 #include <errno.h>
 #include <unistd.h>
+#ifdef __wasilibc_use_wasip2
+#include <wasi/libc.h>
+#else
 #include <wasi/api.h>
+#endif
 
 int __getentropy(void *buffer, size_t len) {
     if (len > 256) {
@@ -8,13 +12,15 @@ int __getentropy(void *buffer, size_t len) {
         return -1;
     }
 
+#ifdef __wasilibc_use_wasip2
+    int r = __wasilibc_random(buffer, len);
+#else
     int r = __wasi_random_get(buffer, len);
-
+#endif
     if (r != 0) {
         errno = r;
         return -1;
     }
-
     return 0;
 }
 weak_alias(__getentropy, getentropy);
lib/libc/wasi/libc-bottom-half/sources/preopens.c
@@ -59,7 +59,6 @@ static void assert_invariants(void) {
 
 /// Allocate space for more preopens. Returns 0 on success and -1 on failure.
 static int resize(void) {
-    LOCK(lock);
     size_t start_capacity = 4;
     size_t old_capacity = preopen_capacity;
     size_t new_capacity = old_capacity == 0 ? start_capacity : old_capacity * 2;
@@ -67,7 +66,6 @@ static int resize(void) {
     preopen *old_preopens = preopens;
     preopen *new_preopens = calloc(sizeof(preopen), new_capacity);
     if (new_preopens == NULL) {
-        UNLOCK(lock);
         return -1;
     }
 
@@ -77,7 +75,6 @@ static int resize(void) {
     free(old_preopens);
 
     assert_invariants();
-    UNLOCK(lock);
     return 0;
 }
 
@@ -101,8 +98,7 @@ static const char *strip_prefixes(const char *path) {
     return path;
 }
 
-/// Similar to `internal_register_preopened_fd_unlocked` but does not
-/// take a lock.
+/// Similar to `internal_register_preopened_fd` but does not take a lock.
 static int internal_register_preopened_fd_unlocked(__wasi_fd_t fd, const char *relprefix) {
     // Check preconditions.
     assert_invariants();
@@ -184,7 +180,7 @@ int __wasilibc_find_abspath(const char *path,
                             const char **relative_path) {
     __wasilibc_populate_preopens();
 
-    // Strip leading `/` characters, the prefixes we're mataching won't have
+    // Strip leading `/` characters, the prefixes we're matching won't have
     // them.
     while (*path == '/')
         path++;
@@ -231,6 +227,7 @@ int __wasilibc_find_abspath(const char *path,
     return fd;
 }
 
+/* zig patch: initialize preopens early so zig code doesn't have to call __wasilibc_populate_preopens */
 __attribute__((constructor(51)))
 void __wasilibc_populate_preopens(void) {
     // Fast path: If the preopens are already initialized, do nothing.
lib/libc/wasi/libc-top-half/musl/include/arpa/nameser.h
@@ -1,455 +0,0 @@
-#ifndef _ARPA_NAMESER_H
-#define _ARPA_NAMESER_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-#include <stddef.h>
-#include <stdint.h>
-
-#define __NAMESER	19991006
-#define NS_PACKETSZ	512
-#define NS_MAXDNAME	1025
-#define NS_MAXMSG	65535
-#define NS_MAXCDNAME	255
-#define NS_MAXLABEL	63
-#define NS_HFIXEDSZ	12
-#define NS_QFIXEDSZ	4
-#define NS_RRFIXEDSZ	10
-#define NS_INT32SZ	4
-#define NS_INT16SZ	2
-#define NS_INT8SZ	1
-#define NS_INADDRSZ	4
-#define NS_IN6ADDRSZ	16
-#define NS_CMPRSFLGS	0xc0
-#define NS_DEFAULTPORT	53
-
-typedef enum __ns_sect {
-	ns_s_qd = 0,
-	ns_s_zn = 0,
-	ns_s_an = 1,
-	ns_s_pr = 1,
-	ns_s_ns = 2,
-	ns_s_ud = 2,
-	ns_s_ar = 3,
-	ns_s_max = 4
-} ns_sect;
-
-typedef struct __ns_msg {
-	const unsigned char *_msg, *_eom;
-	uint16_t _id, _flags, _counts[ns_s_max];
-	const unsigned char *_sections[ns_s_max];
-	ns_sect _sect;
-	int _rrnum;
-	const unsigned char *_msg_ptr;
-} ns_msg;
-
-struct _ns_flagdata {  int mask, shift;  };
-extern const struct _ns_flagdata _ns_flagdata[];
-
-#define ns_msg_id(handle) ((handle)._id + 0)
-#define ns_msg_base(handle) ((handle)._msg + 0)
-#define ns_msg_end(handle) ((handle)._eom + 0)
-#define ns_msg_size(handle) ((handle)._eom - (handle)._msg)
-#define ns_msg_count(handle, section) ((handle)._counts[section] + 0)
-#define ns_msg_getflag(handle, flag) \
-	(((handle)._flags & _ns_flagdata[flag].mask) >> _ns_flagdata[flag].shift)
-
-typedef	struct __ns_rr {
-	char		name[NS_MAXDNAME];
-	uint16_t	type;
-	uint16_t	rr_class;
-	uint32_t	ttl;
-	uint16_t	rdlength;
-	const unsigned char *rdata;
-} ns_rr;
-
-#define ns_rr_name(rr)	(((rr).name[0] != '\0') ? (rr).name : ".")
-#define ns_rr_type(rr)	((ns_type)((rr).type + 0))
-#define ns_rr_class(rr)	((ns_class)((rr).rr_class + 0))
-#define ns_rr_ttl(rr)	((rr).ttl + 0)
-#define ns_rr_rdlen(rr)	((rr).rdlength + 0)
-#define ns_rr_rdata(rr)	((rr).rdata + 0)
-
-typedef enum __ns_flag {
-	ns_f_qr,
-	ns_f_opcode,
-	ns_f_aa,
-	ns_f_tc,
-	ns_f_rd,
-	ns_f_ra,
-	ns_f_z,
-	ns_f_ad,
-	ns_f_cd,
-	ns_f_rcode,
-	ns_f_max
-} ns_flag;
-
-typedef enum __ns_opcode {
-	ns_o_query = 0,
-	ns_o_iquery = 1,
-	ns_o_status = 2,
-	ns_o_notify = 4,
-	ns_o_update = 5,
-	ns_o_max = 6
-} ns_opcode;
-
-typedef	enum __ns_rcode {
-	ns_r_noerror = 0,
-	ns_r_formerr = 1,
-	ns_r_servfail = 2,
-	ns_r_nxdomain = 3,
-	ns_r_notimpl = 4,
-	ns_r_refused = 5,
-	ns_r_yxdomain = 6,
-	ns_r_yxrrset = 7,
-	ns_r_nxrrset = 8,
-	ns_r_notauth = 9,
-	ns_r_notzone = 10,
-	ns_r_max = 11,
-	ns_r_badvers = 16,
-	ns_r_badsig = 16,
-	ns_r_badkey = 17,
-	ns_r_badtime = 18
-} ns_rcode;
-
-typedef enum __ns_update_operation {
-	ns_uop_delete = 0,
-	ns_uop_add = 1,
-	ns_uop_max = 2
-} ns_update_operation;
-
-struct ns_tsig_key {
-        char name[NS_MAXDNAME], alg[NS_MAXDNAME];
-        unsigned char *data;
-        int len;
-};
-typedef struct ns_tsig_key ns_tsig_key;
-
-struct ns_tcp_tsig_state {
-	int counter;
-	struct dst_key *key;
-	void *ctx;
-	unsigned char sig[NS_PACKETSZ];
-	int siglen;
-};
-typedef struct ns_tcp_tsig_state ns_tcp_tsig_state;
-
-#define NS_TSIG_FUDGE 300
-#define NS_TSIG_TCP_COUNT 100
-#define NS_TSIG_ALG_HMAC_MD5 "HMAC-MD5.SIG-ALG.REG.INT"
-
-#define NS_TSIG_ERROR_NO_TSIG -10
-#define NS_TSIG_ERROR_NO_SPACE -11
-#define NS_TSIG_ERROR_FORMERR -12
-
-typedef enum __ns_type {
-	ns_t_invalid = 0,
-	ns_t_a = 1,
-	ns_t_ns = 2,
-	ns_t_md = 3,
-	ns_t_mf = 4,
-	ns_t_cname = 5,
-	ns_t_soa = 6,
-	ns_t_mb = 7,
-	ns_t_mg = 8,
-	ns_t_mr = 9,
-	ns_t_null = 10,
-	ns_t_wks = 11,
-	ns_t_ptr = 12,
-	ns_t_hinfo = 13,
-	ns_t_minfo = 14,
-	ns_t_mx = 15,
-	ns_t_txt = 16,
-	ns_t_rp = 17,
-	ns_t_afsdb = 18,
-	ns_t_x25 = 19,
-	ns_t_isdn = 20,
-	ns_t_rt = 21,
-	ns_t_nsap = 22,
-	ns_t_nsap_ptr = 23,
-	ns_t_sig = 24,
-	ns_t_key = 25,
-	ns_t_px = 26,
-	ns_t_gpos = 27,
-	ns_t_aaaa = 28,
-	ns_t_loc = 29,
-	ns_t_nxt = 30,
-	ns_t_eid = 31,
-	ns_t_nimloc = 32,
-	ns_t_srv = 33,
-	ns_t_atma = 34,
-	ns_t_naptr = 35,
-	ns_t_kx = 36,
-	ns_t_cert = 37,
-	ns_t_a6 = 38,
-	ns_t_dname = 39,
-	ns_t_sink = 40,
-	ns_t_opt = 41,
-	ns_t_apl = 42,
-	ns_t_tkey = 249,
-	ns_t_tsig = 250,
-	ns_t_ixfr = 251,
-	ns_t_axfr = 252,
-	ns_t_mailb = 253,
-	ns_t_maila = 254,
-	ns_t_any = 255,
-	ns_t_zxfr = 256,
-	ns_t_max = 65536
-} ns_type;
-
-#define	ns_t_qt_p(t) (ns_t_xfr_p(t) || (t) == ns_t_any || \
-		      (t) == ns_t_mailb || (t) == ns_t_maila)
-#define	ns_t_mrr_p(t) ((t) == ns_t_tsig || (t) == ns_t_opt)
-#define ns_t_rr_p(t) (!ns_t_qt_p(t) && !ns_t_mrr_p(t))
-#define ns_t_udp_p(t) ((t) != ns_t_axfr && (t) != ns_t_zxfr)
-#define ns_t_xfr_p(t) ((t) == ns_t_axfr || (t) == ns_t_ixfr || \
-		       (t) == ns_t_zxfr)
-
-typedef enum __ns_class {
-	ns_c_invalid = 0,
-	ns_c_in = 1,
-	ns_c_2 = 2,
-	ns_c_chaos = 3,
-	ns_c_hs = 4,
-	ns_c_none = 254,
-	ns_c_any = 255,
-	ns_c_max = 65536
-} ns_class;
-
-typedef enum __ns_key_types {
-	ns_kt_rsa = 1,
-	ns_kt_dh  = 2,
-	ns_kt_dsa = 3,
-	ns_kt_private = 254
-} ns_key_types;
-
-typedef enum __ns_cert_types {
-	cert_t_pkix = 1,
-	cert_t_spki = 2,
-	cert_t_pgp  = 3,
-	cert_t_url  = 253,
-	cert_t_oid  = 254
-} ns_cert_types;
-
-#define	NS_KEY_TYPEMASK		0xC000
-#define	NS_KEY_TYPE_AUTH_CONF	0x0000
-#define	NS_KEY_TYPE_CONF_ONLY	0x8000
-#define	NS_KEY_TYPE_AUTH_ONLY	0x4000
-#define	NS_KEY_TYPE_NO_KEY	0xC000
-#define	NS_KEY_NO_AUTH		0x8000
-#define	NS_KEY_NO_CONF		0x4000
-#define	NS_KEY_RESERVED2	0x2000
-#define	NS_KEY_EXTENDED_FLAGS	0x1000
-#define	NS_KEY_RESERVED4	0x0800
-#define	NS_KEY_RESERVED5	0x0400
-#define	NS_KEY_NAME_TYPE	0x0300
-#define	NS_KEY_NAME_USER	0x0000
-#define	NS_KEY_NAME_ENTITY	0x0200
-#define	NS_KEY_NAME_ZONE	0x0100
-#define	NS_KEY_NAME_RESERVED	0x0300
-#define	NS_KEY_RESERVED8	0x0080
-#define	NS_KEY_RESERVED9	0x0040
-#define	NS_KEY_RESERVED10	0x0020
-#define	NS_KEY_RESERVED11	0x0010
-#define	NS_KEY_SIGNATORYMASK	0x000F
-#define	NS_KEY_RESERVED_BITMASK ( NS_KEY_RESERVED2 | \
-				  NS_KEY_RESERVED4 | \
-				  NS_KEY_RESERVED5 | \
-				  NS_KEY_RESERVED8 | \
-				  NS_KEY_RESERVED9 | \
-				  NS_KEY_RESERVED10 | \
-				  NS_KEY_RESERVED11 )
-#define NS_KEY_RESERVED_BITMASK2 0xFFFF
-#define	NS_ALG_MD5RSA		1
-#define	NS_ALG_DH               2
-#define	NS_ALG_DSA              3
-#define	NS_ALG_DSS              NS_ALG_DSA
-#define	NS_ALG_EXPIRE_ONLY	253
-#define	NS_ALG_PRIVATE_OID	254
-
-#define NS_KEY_PROT_TLS         1
-#define NS_KEY_PROT_EMAIL       2
-#define NS_KEY_PROT_DNSSEC      3
-#define NS_KEY_PROT_IPSEC       4
-#define NS_KEY_PROT_ANY		255
-
-#define	NS_MD5RSA_MIN_BITS	 512
-#define	NS_MD5RSA_MAX_BITS	4096
-#define	NS_MD5RSA_MAX_BYTES	((NS_MD5RSA_MAX_BITS+7/8)*2+3)
-#define	NS_MD5RSA_MAX_BASE64	(((NS_MD5RSA_MAX_BYTES+2)/3)*4)
-#define NS_MD5RSA_MIN_SIZE	((NS_MD5RSA_MIN_BITS+7)/8)
-#define NS_MD5RSA_MAX_SIZE	((NS_MD5RSA_MAX_BITS+7)/8)
-
-#define NS_DSA_SIG_SIZE         41
-#define NS_DSA_MIN_SIZE         213
-#define NS_DSA_MAX_BYTES        405
-
-#define	NS_SIG_TYPE	0
-#define	NS_SIG_ALG	2
-#define	NS_SIG_LABELS	3
-#define	NS_SIG_OTTL	4
-#define	NS_SIG_EXPIR	8
-#define	NS_SIG_SIGNED	12
-#define	NS_SIG_FOOT	16
-#define	NS_SIG_SIGNER	18
-#define	NS_NXT_BITS 8
-#define	NS_NXT_BIT_SET(  n,p) (p[(n)/NS_NXT_BITS] |=  (0x80>>((n)%NS_NXT_BITS)))
-#define	NS_NXT_BIT_CLEAR(n,p) (p[(n)/NS_NXT_BITS] &= ~(0x80>>((n)%NS_NXT_BITS)))
-#define	NS_NXT_BIT_ISSET(n,p) (p[(n)/NS_NXT_BITS] &   (0x80>>((n)%NS_NXT_BITS)))
-#define NS_NXT_MAX 127
-
-#define NS_OPT_DNSSEC_OK        0x8000U
-#define NS_OPT_NSID		3
-
-#define NS_GET16(s, cp) (void)((s) = ns_get16(((cp)+=2)-2))
-#define NS_GET32(l, cp) (void)((l) = ns_get32(((cp)+=4)-4))
-#define NS_PUT16(s, cp) ns_put16((s), ((cp)+=2)-2)
-#define NS_PUT32(l, cp) ns_put32((l), ((cp)+=4)-4)
-
-unsigned ns_get16(const unsigned char *);
-unsigned long ns_get32(const unsigned char *);
-void ns_put16(unsigned, unsigned char *);
-void ns_put32(unsigned long, unsigned char *);
-
-int ns_initparse(const unsigned char *, int, ns_msg *);
-int ns_parserr(ns_msg *, ns_sect, int, ns_rr *);
-int ns_skiprr(const unsigned char *, const unsigned char *, ns_sect, int);
-int ns_name_uncompress(const unsigned char *, const unsigned char *, const unsigned char *, char *, size_t);
-
-
-#define	__BIND		19950621
-
-typedef struct {
-	unsigned	id :16;
-#if __BYTE_ORDER == __BIG_ENDIAN
-	unsigned	qr: 1;
-	unsigned	opcode: 4;
-	unsigned	aa: 1;
-	unsigned	tc: 1;
-	unsigned	rd: 1;
-	unsigned	ra: 1;
-	unsigned	unused :1;
-	unsigned	ad: 1;
-	unsigned	cd: 1;
-	unsigned	rcode :4;
-#else
-	unsigned	rd :1;
-	unsigned	tc :1;
-	unsigned	aa :1;
-	unsigned	opcode :4;
-	unsigned	qr :1;
-	unsigned	rcode :4;
-	unsigned	cd: 1;
-	unsigned	ad: 1;
-	unsigned	unused :1;
-	unsigned	ra :1;
-#endif
-	unsigned	qdcount :16;
-	unsigned	ancount :16;
-	unsigned	nscount :16;
-	unsigned	arcount :16;
-} HEADER;
-
-#define PACKETSZ	NS_PACKETSZ
-#define MAXDNAME	NS_MAXDNAME
-#define MAXCDNAME	NS_MAXCDNAME
-#define MAXLABEL	NS_MAXLABEL
-#define	HFIXEDSZ	NS_HFIXEDSZ
-#define QFIXEDSZ	NS_QFIXEDSZ
-#define RRFIXEDSZ	NS_RRFIXEDSZ
-#define	INT32SZ		NS_INT32SZ
-#define	INT16SZ		NS_INT16SZ
-#define INT8SZ		NS_INT8SZ
-#define	INADDRSZ	NS_INADDRSZ
-#define	IN6ADDRSZ	NS_IN6ADDRSZ
-#define	INDIR_MASK	NS_CMPRSFLGS
-#define NAMESERVER_PORT	NS_DEFAULTPORT
-
-#define S_ZONE		ns_s_zn
-#define S_PREREQ	ns_s_pr
-#define S_UPDATE	ns_s_ud
-#define S_ADDT		ns_s_ar
-
-#define QUERY		ns_o_query
-#define IQUERY		ns_o_iquery
-#define STATUS		ns_o_status
-#define	NS_NOTIFY_OP	ns_o_notify
-#define	NS_UPDATE_OP	ns_o_update
-
-#define NOERROR		ns_r_noerror
-#define FORMERR		ns_r_formerr
-#define SERVFAIL	ns_r_servfail
-#define NXDOMAIN	ns_r_nxdomain
-#define NOTIMP		ns_r_notimpl
-#define REFUSED		ns_r_refused
-#define YXDOMAIN	ns_r_yxdomain
-#define YXRRSET		ns_r_yxrrset
-#define NXRRSET		ns_r_nxrrset
-#define NOTAUTH		ns_r_notauth
-#define NOTZONE		ns_r_notzone
-
-#define DELETE		ns_uop_delete
-#define ADD		ns_uop_add
-
-#define T_A		ns_t_a
-#define T_NS		ns_t_ns
-#define T_MD		ns_t_md
-#define T_MF		ns_t_mf
-#define T_CNAME		ns_t_cname
-#define T_SOA		ns_t_soa
-#define T_MB		ns_t_mb
-#define T_MG		ns_t_mg
-#define T_MR		ns_t_mr
-#define T_NULL		ns_t_null
-#define T_WKS		ns_t_wks
-#define T_PTR		ns_t_ptr
-#define T_HINFO		ns_t_hinfo
-#define T_MINFO		ns_t_minfo
-#define T_MX		ns_t_mx
-#define T_TXT		ns_t_txt
-#define	T_RP		ns_t_rp
-#define T_AFSDB		ns_t_afsdb
-#define T_X25		ns_t_x25
-#define T_ISDN		ns_t_isdn
-#define T_RT		ns_t_rt
-#define T_NSAP		ns_t_nsap
-#define T_NSAP_PTR	ns_t_nsap_ptr
-#define	T_SIG		ns_t_sig
-#define	T_KEY		ns_t_key
-#define	T_PX		ns_t_px
-#define	T_GPOS		ns_t_gpos
-#define	T_AAAA		ns_t_aaaa
-#define	T_LOC		ns_t_loc
-#define	T_NXT		ns_t_nxt
-#define	T_EID		ns_t_eid
-#define	T_NIMLOC	ns_t_nimloc
-#define	T_SRV		ns_t_srv
-#define T_ATMA		ns_t_atma
-#define T_NAPTR		ns_t_naptr
-#define T_A6		ns_t_a6
-#define T_DNAME		ns_t_dname
-#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 C_IN		ns_c_in
-#define C_CHAOS		ns_c_chaos
-#define C_HS		ns_c_hs
-#define C_NONE		ns_c_none
-#define C_ANY		ns_c_any
-
-#define	GETSHORT		NS_GET16
-#define	GETLONG			NS_GET32
-#define	PUTSHORT		NS_PUT16
-#define	PUTLONG			NS_PUT32
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
lib/libc/wasi/libc-top-half/musl/include/sys/sendfile.h
@@ -0,0 +1,22 @@
+#ifndef _SYS_SENDFILE_H
+#define _SYS_SENDFILE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <features.h>
+#include <unistd.h>
+
+ssize_t sendfile(int, int, off_t *, size_t);
+
+#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#define sendfile64 sendfile
+#define off64_t off_t
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
lib/libc/wasi/libc-top-half/musl/include/sys/stat.h
@@ -18,6 +18,13 @@ extern "C" {
 #define __NEED_blkcnt_t
 #define __NEED_struct_timespec
 
+#ifdef _GNU_SOURCE
+#define __NEED_int64_t
+#define __NEED_uint64_t
+#define __NEED_uint32_t
+#define __NEED_uint16_t
+#endif
+
 #include <bits/alltypes.h>
 
 #include <bits/stat.h>
@@ -112,6 +119,56 @@ int lchmod(const char *, mode_t);
 #define S_IEXEC S_IXUSR
 #endif
 
+#ifdef __wasilibc_unmodified_upstream /* WASI has no statx */
+#if defined(_GNU_SOURCE)
+#define STATX_TYPE 1U
+#define STATX_MODE 2U
+#define STATX_NLINK 4U
+#define STATX_UID 8U
+#define STATX_GID 0x10U
+#define STATX_ATIME 0x20U
+#define STATX_MTIME 0x40U
+#define STATX_CTIME 0x80U
+#define STATX_INO 0x100U
+#define STATX_SIZE 0x200U
+#define STATX_BLOCKS 0x400U
+#define STATX_BASIC_STATS 0x7ffU
+#define STATX_BTIME 0x800U
+#define STATX_ALL 0xfffU
+
+struct statx_timestamp {
+	int64_t tv_sec;
+	uint32_t tv_nsec, __pad;
+};
+
+struct statx {
+	uint32_t stx_mask;
+	uint32_t stx_blksize;
+	uint64_t stx_attributes;
+	uint32_t stx_nlink;
+	uint32_t stx_uid;
+	uint32_t stx_gid;
+	uint16_t stx_mode;
+	uint16_t __pad0[1];
+	uint64_t stx_ino;
+	uint64_t stx_size;
+	uint64_t stx_blocks;
+	uint64_t stx_attributes_mask;
+	struct statx_timestamp stx_atime;
+	struct statx_timestamp stx_btime;
+	struct statx_timestamp stx_ctime;
+	struct statx_timestamp stx_mtime;
+	uint32_t stx_rdev_major;
+	uint32_t stx_rdev_minor;
+	uint32_t stx_dev_major;
+	uint32_t stx_dev_minor;
+	uint64_t __pad1[14];
+};
+
+int statx(int, const char *__restrict, int, unsigned, struct statx *__restrict);
+#endif
+#endif
+
 #if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
 #define stat64 stat
 #define fstat64 fstat
lib/libc/wasi/libc-top-half/musl/include/sys/statfs.h
@@ -0,0 +1,32 @@
+#ifndef	_SYS_STATFS_H
+#define	_SYS_STATFS_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <features.h>
+
+#include <sys/statvfs.h>
+
+typedef struct __fsid_t {
+	int __val[2];
+} fsid_t;
+
+#include <bits/statfs.h>
+
+int statfs (const char *, struct statfs *);
+int fstatfs (int, struct statfs *);
+
+#if defined(_LARGEFILE64_SOURCE) || defined(_GNU_SOURCE)
+#define statfs64 statfs
+#define fstatfs64 fstatfs
+#define fsblkcnt64_t fsblkcnt_t
+#define fsfilcnt64_t fsfilcnt_t
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
lib/libc/wasi/libc-top-half/musl/include/sys/statvfs.h
@@ -23,7 +23,8 @@ struct statvfs {
 	unsigned long f_fsid;
 #endif
 	unsigned long f_flag, f_namemax;
-	int __reserved[6];
+	unsigned int f_type;
+	int __reserved[5];
 };
 
 int statvfs (const char *__restrict, struct statvfs *__restrict);
lib/libc/wasi/libc-top-half/musl/include/sys/uio.h
@@ -36,9 +36,18 @@ ssize_t pwritev (int, const struct iovec *, int, off_t);
 #endif
 #endif
 
+#ifdef __wasilibc_unmodified_upstream // Wasm doesn't have these Linux-specific functions
 #ifdef _GNU_SOURCE
 ssize_t process_vm_writev(pid_t, const struct iovec *, unsigned long, const struct iovec *, unsigned long, unsigned long);
 ssize_t process_vm_readv(pid_t, const struct iovec *, unsigned long, const struct iovec *, unsigned long, unsigned long);
+ssize_t preadv2 (int, const struct iovec *, int, off_t, int);
+ssize_t pwritev2 (int, const struct iovec *, int, off_t, int);
+#define RWF_HIPRI 0x00000001
+#define RWF_DSYNC 0x00000002
+#define RWF_SYNC 0x00000004
+#define RWF_NOWAIT 0x00000008
+#define RWF_APPEND 0x00000010
+#endif
 #endif
 
 #ifdef __cplusplus
lib/libc/wasi/libc-top-half/musl/include/wasi/libc-busywait.h
@@ -0,0 +1,15 @@
+#ifndef __wasi_libc_busywait_h
+#define __wasi_libc_busywait_h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/// Enable busywait in futex on current thread.
+void __wasilibc_enable_futex_busywait_on_current_thread(void);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif 
lib/libc/wasi/libc-top-half/musl/include/aio.h
@@ -0,0 +1,73 @@
+#ifndef _AIO_H
+#define _AIO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <features.h>
+#include <signal.h>
+#include <time.h>
+
+#define __NEED_ssize_t
+#define __NEED_off_t
+
+#include <bits/alltypes.h>
+
+struct aiocb {
+	int aio_fildes, aio_lio_opcode, aio_reqprio;
+	volatile void *aio_buf;
+	size_t aio_nbytes;
+	struct sigevent aio_sigevent;
+	void *__td;
+	int __lock[2];
+	volatile int __err;
+	ssize_t __ret;
+	off_t aio_offset;
+	void *__next, *__prev;
+	char __dummy4[32-2*sizeof(void *)];
+};
+
+#define AIO_CANCELED 0
+#define AIO_NOTCANCELED 1
+#define AIO_ALLDONE 2
+
+#define LIO_READ 0
+#define LIO_WRITE 1
+#define LIO_NOP 2
+
+#define LIO_WAIT 0
+#define LIO_NOWAIT 1
+
+int aio_read(struct aiocb *);
+int aio_write(struct aiocb *);
+int aio_error(const struct aiocb *);
+ssize_t aio_return(struct aiocb *);
+int aio_cancel(int, struct aiocb *);
+int aio_suspend(const struct aiocb *const [], int, const struct timespec *);
+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)
+#define aiocb64 aiocb
+#define aio_read64 aio_read
+#define aio_write64 aio_write
+#define aio_error64 aio_error
+#define aio_return64 aio_return
+#define aio_cancel64 aio_cancel
+#define aio_suspend64 aio_suspend
+#define aio_fsync64 aio_fsync
+#define lio_listio64 lio_listio
+#define off64_t off_t
+#endif
+
+#if _REDIR_TIME64
+__REDIR(aio_suspend, __aio_suspend_time64);
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
lib/libc/wasi/libc-top-half/musl/include/fcntl.h
@@ -203,7 +203,6 @@ struct f_owner_ex {
 #endif
 #ifdef __wasilibc_unmodified_upstream /* WASI has no fallocate */
 int fallocate(int, int, off_t, off_t);
-#define fallocate64 fallocate
 #endif
 #ifdef __wasilibc_unmodified_upstream /* WASI has no name_to_handle_at */
 int name_to_handle_at(int, const char *, struct file_handle *, int *, int);
@@ -237,6 +236,11 @@ ssize_t tee(int, int, size_t, unsigned);
 #define posix_fadvise64 posix_fadvise
 #define posix_fallocate64 posix_fallocate
 #define off64_t off_t
+#ifdef __wasilibc_unmodified_upstream /* WASI has no fallocate */
+#if defined(_GNU_SOURCE)
+#define fallocate64 fallocate
+#endif
+#endif
 #endif
 
 #ifdef __cplusplus
lib/libc/wasi/libc-top-half/musl/include/limits.h
@@ -65,11 +65,9 @@
 
 /* Implementation choices... */
 
-#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
 #define PTHREAD_KEYS_MAX 128
 #define PTHREAD_STACK_MIN 2048
 #define PTHREAD_DESTRUCTOR_ITERATIONS 4
-#endif
 #if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
 #define SEM_VALUE_MAX 0x7fffffff
 #define SEM_NSEMS_MAX 256
lib/libc/wasi/libc-top-half/musl/include/netdb.h
@@ -0,0 +1,162 @@
+#ifndef	_NETDB_H
+#define	_NETDB_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <features.h>
+#include <netinet/in.h>
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+#define __NEED_size_t
+#include <bits/alltypes.h>
+#endif
+
+struct addrinfo {
+	int ai_flags;
+	int ai_family;
+	int ai_socktype;
+	int ai_protocol;
+	socklen_t ai_addrlen;
+	struct sockaddr *ai_addr;
+	char *ai_canonname;
+	struct addrinfo *ai_next;
+};
+
+#define AI_PASSIVE      0x01
+#define AI_CANONNAME    0x02
+#define AI_NUMERICHOST  0x04
+#define AI_V4MAPPED     0x08
+#define AI_ALL          0x10
+#define AI_ADDRCONFIG   0x20
+#define AI_NUMERICSERV  0x400
+
+
+#define NI_NUMERICHOST  0x01
+#define NI_NUMERICSERV  0x02
+#define NI_NOFQDN       0x04
+#define NI_NAMEREQD     0x08
+#define NI_DGRAM        0x10
+#define NI_NUMERICSCOPE 0x100
+
+#define EAI_BADFLAGS   -1
+#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
+#define EAI_MEMORY     -10
+#define EAI_SYSTEM     -11
+#define EAI_OVERFLOW   -12
+
+int getaddrinfo (const char *__restrict, const char *__restrict, const struct addrinfo *__restrict, struct addrinfo **__restrict);
+void freeaddrinfo (struct addrinfo *);
+int getnameinfo (const struct sockaddr *__restrict, socklen_t, char *__restrict, socklen_t, char *__restrict, socklen_t, int);
+const char *gai_strerror(int);
+
+
+/* Legacy functions follow (marked OBsolete in SUS) */
+
+struct netent {
+	char *n_name;
+	char **n_aliases;
+	int n_addrtype;
+	uint32_t n_net;
+};
+
+struct hostent {
+	char *h_name;
+	char **h_aliases;
+	int h_addrtype;
+	int h_length;
+	char **h_addr_list;
+};
+#define h_addr h_addr_list[0]
+
+struct servent {
+	char *s_name;
+	char **s_aliases;
+	int s_port;
+	char *s_proto;
+};
+
+struct protoent {
+	char *p_name;
+	char **p_aliases;
+	int p_proto;
+};
+
+void sethostent (int);
+void endhostent (void);
+struct hostent *gethostent (void);
+
+void setnetent (int);
+void endnetent (void);
+struct netent *getnetent (void);
+struct netent *getnetbyaddr (uint32_t, int);
+struct netent *getnetbyname (const char *);
+
+void setservent (int);
+void endservent (void);
+struct servent *getservent (void);
+struct servent *getservbyname (const char *, const char *);
+struct servent *getservbyport (int, const char *);
+
+void setprotoent (int);
+void endprotoent (void);
+struct protoent *getprotoent (void);
+struct protoent *getprotobyname (const char *);
+struct protoent *getprotobynumber (int);
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_POSIX_SOURCE) \
+ || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE+0 < 200809L) \
+ || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700)
+struct hostent *gethostbyname (const char *);
+struct hostent *gethostbyaddr (const void *, socklen_t, int);
+#ifdef __GNUC__
+__attribute__((const))
+#endif
+#ifdef __wasilibc_unmodified_upstream
+int *__h_errno_location(void);
+#define h_errno (*__h_errno_location())
+#elif (defined __wasilibc_use_wasip2)
+extern _Thread_local int h_errno;
+#define h_errno h_errno
+#endif
+#define HOST_NOT_FOUND 1
+#define TRY_AGAIN      2
+#define NO_RECOVERY    3
+#define NO_DATA        4
+#define NO_ADDRESS     NO_DATA
+#endif
+
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
+void herror(const char *);
+const char *hstrerror(int);
+int gethostbyname_r(const char *, struct hostent *, char *, size_t, struct hostent **, int *);
+int gethostbyname2_r(const char *, int, struct hostent *, char *, size_t, struct hostent **, int *);
+struct hostent *gethostbyname2(const char *, int);
+int gethostbyaddr_r(const void *, socklen_t, int, struct hostent *, char *, size_t, struct hostent **, int *);
+int getservbyport_r(int, const char *, struct servent *, char *, size_t, struct servent **);
+int getservbyname_r(const char *, const char *, struct servent *, char *, size_t, struct servent **);
+#define EAI_NODATA     -5
+#define EAI_ADDRFAMILY -9
+#define EAI_INPROGRESS -100
+#define EAI_CANCELED   -101
+#define EAI_NOTCANCELED -102
+#define EAI_ALLDONE    -103
+#define EAI_INTR       -104
+#define EAI_IDN_ENCODE -105
+#define NI_MAXHOST 255
+#define NI_MAXSERV 32
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
lib/libc/wasi/libc-top-half/musl/include/poll.h
@@ -48,7 +48,7 @@ struct pollfd {
 
 int poll (struct pollfd *, nfds_t, int);
 
-#ifdef _GNU_SOURCE
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
 #define __NEED_time_t
 #define __NEED_struct_timespec
 #define __NEED_sigset_t
@@ -57,7 +57,7 @@ int ppoll(struct pollfd *, nfds_t, const struct timespec *, const sigset_t *);
 #endif
 
 #if _REDIR_TIME64
-#ifdef _GNU_SOURCE
+#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE)
 __REDIR(ppoll, __ppoll_time64);
 #endif
 #endif
lib/libc/wasi/libc-top-half/musl/include/pthread.h
@@ -0,0 +1,267 @@
+#ifndef _PTHREAD_H
+#define _PTHREAD_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <features.h>
+
+#define __NEED_time_t
+#define __NEED_clockid_t
+#define __NEED_struct_timespec
+#define __NEED_sigset_t
+#define __NEED_pthread_t
+#define __NEED_pthread_attr_t
+#define __NEED_pthread_mutexattr_t
+#define __NEED_pthread_condattr_t
+#define __NEED_pthread_rwlockattr_t
+#define __NEED_pthread_barrierattr_t
+#define __NEED_pthread_mutex_t
+#define __NEED_pthread_cond_t
+#define __NEED_pthread_rwlock_t
+#define __NEED_pthread_barrier_t
+#define __NEED_pthread_spinlock_t
+#define __NEED_pthread_key_t
+#define __NEED_pthread_once_t
+#define __NEED_size_t
+
+#include <bits/alltypes.h>
+
+#include <sched.h>
+#include <time.h>
+
+#define PTHREAD_CREATE_JOINABLE 0
+#define PTHREAD_CREATE_DETACHED 1
+
+#define PTHREAD_MUTEX_NORMAL 0
+#define PTHREAD_MUTEX_DEFAULT 0
+#define PTHREAD_MUTEX_RECURSIVE 1
+#define PTHREAD_MUTEX_ERRORCHECK 2
+
+#define PTHREAD_MUTEX_STALLED 0
+#define PTHREAD_MUTEX_ROBUST 1
+
+#define PTHREAD_PRIO_NONE 0
+#define PTHREAD_PRIO_INHERIT 1
+#define PTHREAD_PRIO_PROTECT 2
+
+#define PTHREAD_INHERIT_SCHED 0
+#define PTHREAD_EXPLICIT_SCHED 1
+
+#define PTHREAD_SCOPE_SYSTEM 0
+#define PTHREAD_SCOPE_PROCESS 1
+
+#define PTHREAD_PROCESS_PRIVATE 0
+#define PTHREAD_PROCESS_SHARED 1
+
+
+#define PTHREAD_MUTEX_INITIALIZER {{{0}}}
+#define PTHREAD_RWLOCK_INITIALIZER {{{0}}}
+#define PTHREAD_COND_INITIALIZER {{{0}}}
+#define PTHREAD_ONCE_INIT 0
+
+
+#define PTHREAD_CANCEL_ENABLE 0
+#define PTHREAD_CANCEL_DISABLE 1
+#define PTHREAD_CANCEL_MASKED 2
+
+#define PTHREAD_CANCEL_DEFERRED 0
+#define PTHREAD_CANCEL_ASYNCHRONOUS 1
+
+#define PTHREAD_CANCELED ((void *)-1)
+
+
+#define PTHREAD_BARRIER_SERIAL_THREAD (-1)
+
+
+#define PTHREAD_NULL ((pthread_t)0)
+
+
+#ifdef __wasilibc_unmodified_upstream
+int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict);
+int pthread_detach(pthread_t);
+_Noreturn void pthread_exit(void *);
+int pthread_join(pthread_t, void **);
+#else
+#if defined(_REENTRANT) || !defined(_WASI_STRICT_PTHREAD)
+int pthread_create(pthread_t *__restrict, const pthread_attr_t *__restrict, void *(*)(void *), void *__restrict);
+int pthread_detach(pthread_t);
+int pthread_join(pthread_t, void **);
+#else
+#define pthread_create(...) ({ _Static_assert(0, "This function is not available on a single-threaded target; switch to a multi-threaded target with -pthread or enable a stub implementation by undefining _WASI_STRICT_PTHREAD"); 0;})
+#define pthread_detach(...) ({ _Static_assert(0, "This function is not available on a single-threaded target; switch to a multi-threaded target with -pthread or enable a stub implementation by undefining _WASI_STRICT_PTHREAD"); 0;})
+#define pthread_join(...) ({ _Static_assert(0, "This function is not available on a single-threaded target; switch to a multi-threaded target with -pthread or enable a stub implementation by undefining _WASI_STRICT_PTHREAD"); 0;})
+#endif
+#endif
+
+#ifdef __GNUC__
+__attribute__((const))
+#endif
+pthread_t pthread_self(void);
+
+int pthread_equal(pthread_t, pthread_t);
+#ifndef __cplusplus
+#define pthread_equal(x,y) ((x)==(y))
+#endif
+
+int pthread_setcancelstate(int, int *);
+int pthread_setcanceltype(int, int *);
+void pthread_testcancel(void);
+#ifdef __wasilibc_unmodified_upstream /* WASI has no cancellation support. */
+int pthread_cancel(pthread_t);
+#endif
+
+#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */
+int pthread_getschedparam(pthread_t, int *__restrict, struct sched_param *__restrict);
+int pthread_setschedparam(pthread_t, int, const struct sched_param *);
+#endif
+int pthread_setschedprio(pthread_t, int);
+
+int pthread_once(pthread_once_t *, void (*)(void));
+
+int pthread_mutex_init(pthread_mutex_t *__restrict, const pthread_mutexattr_t *__restrict);
+int pthread_mutex_lock(pthread_mutex_t *);
+int pthread_mutex_unlock(pthread_mutex_t *);
+int pthread_mutex_trylock(pthread_mutex_t *);
+int pthread_mutex_timedlock(pthread_mutex_t *__restrict, const struct timespec *__restrict);
+int pthread_mutex_destroy(pthread_mutex_t *);
+int pthread_mutex_consistent(pthread_mutex_t *);
+
+int pthread_mutex_getprioceiling(const pthread_mutex_t *__restrict, int *__restrict);
+int pthread_mutex_setprioceiling(pthread_mutex_t *__restrict, int, int *__restrict);
+
+int pthread_cond_init(pthread_cond_t *__restrict, const pthread_condattr_t *__restrict);
+int pthread_cond_destroy(pthread_cond_t *);
+int pthread_cond_wait(pthread_cond_t *__restrict, pthread_mutex_t *__restrict);
+int pthread_cond_timedwait(pthread_cond_t *__restrict, pthread_mutex_t *__restrict, const struct timespec *__restrict);
+int pthread_cond_broadcast(pthread_cond_t *);
+int pthread_cond_signal(pthread_cond_t *);
+
+int pthread_rwlock_init(pthread_rwlock_t *__restrict, const pthread_rwlockattr_t *__restrict);
+int pthread_rwlock_destroy(pthread_rwlock_t *);
+int pthread_rwlock_rdlock(pthread_rwlock_t *);
+int pthread_rwlock_tryrdlock(pthread_rwlock_t *);
+int pthread_rwlock_timedrdlock(pthread_rwlock_t *__restrict, const struct timespec *__restrict);
+int pthread_rwlock_wrlock(pthread_rwlock_t *);
+int pthread_rwlock_trywrlock(pthread_rwlock_t *);
+int pthread_rwlock_timedwrlock(pthread_rwlock_t *__restrict, const struct timespec *__restrict);
+int pthread_rwlock_unlock(pthread_rwlock_t *);
+
+int pthread_spin_init(pthread_spinlock_t *, int);
+int pthread_spin_destroy(pthread_spinlock_t *);
+int pthread_spin_lock(pthread_spinlock_t *);
+int pthread_spin_trylock(pthread_spinlock_t *);
+int pthread_spin_unlock(pthread_spinlock_t *);
+
+int pthread_barrier_init(pthread_barrier_t *__restrict, const pthread_barrierattr_t *__restrict, unsigned);
+int pthread_barrier_destroy(pthread_barrier_t *);
+int pthread_barrier_wait(pthread_barrier_t *);
+
+int pthread_key_create(pthread_key_t *, void (*)(void *));
+int pthread_key_delete(pthread_key_t);
+void *pthread_getspecific(pthread_key_t);
+int pthread_setspecific(pthread_key_t, const void *);
+
+int pthread_attr_init(pthread_attr_t *);
+int pthread_attr_destroy(pthread_attr_t *);
+
+int pthread_attr_getguardsize(const pthread_attr_t *__restrict, size_t *__restrict);
+int pthread_attr_setguardsize(pthread_attr_t *, size_t);
+int pthread_attr_getstacksize(const pthread_attr_t *__restrict, size_t *__restrict);
+int pthread_attr_setstacksize(pthread_attr_t *, size_t);
+int pthread_attr_getdetachstate(const pthread_attr_t *, int *);
+int pthread_attr_setdetachstate(pthread_attr_t *, int);
+int pthread_attr_getstack(const pthread_attr_t *__restrict, void **__restrict, size_t *__restrict);
+int pthread_attr_setstack(pthread_attr_t *, void *, size_t);
+int pthread_attr_getscope(const pthread_attr_t *__restrict, int *__restrict);
+int pthread_attr_setscope(pthread_attr_t *, int);
+int pthread_attr_getschedpolicy(const pthread_attr_t *__restrict, int *__restrict);
+int pthread_attr_setschedpolicy(pthread_attr_t *, int);
+#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */
+int pthread_attr_getschedparam(const pthread_attr_t *__restrict, struct sched_param *__restrict);
+int pthread_attr_setschedparam(pthread_attr_t *__restrict, const struct sched_param *__restrict);
+#endif
+int pthread_attr_getinheritsched(const pthread_attr_t *__restrict, int *__restrict);
+int pthread_attr_setinheritsched(pthread_attr_t *, int);
+
+int pthread_mutexattr_destroy(pthread_mutexattr_t *);
+int pthread_mutexattr_getprioceiling(const pthread_mutexattr_t *__restrict, int *__restrict);
+int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *__restrict, int *__restrict);
+int pthread_mutexattr_getpshared(const pthread_mutexattr_t *__restrict, int *__restrict);
+int pthread_mutexattr_getrobust(const pthread_mutexattr_t *__restrict, int *__restrict);
+int pthread_mutexattr_gettype(const pthread_mutexattr_t *__restrict, int *__restrict);
+int pthread_mutexattr_init(pthread_mutexattr_t *);
+int pthread_mutexattr_setprioceiling(pthread_mutexattr_t *, int);
+int pthread_mutexattr_setprotocol(pthread_mutexattr_t *, int);
+int pthread_mutexattr_setpshared(pthread_mutexattr_t *, int);
+int pthread_mutexattr_setrobust(pthread_mutexattr_t *, int);
+int pthread_mutexattr_settype(pthread_mutexattr_t *, int);
+
+int pthread_condattr_init(pthread_condattr_t *);
+int pthread_condattr_destroy(pthread_condattr_t *);
+int pthread_condattr_setclock(pthread_condattr_t *, clockid_t);
+int pthread_condattr_setpshared(pthread_condattr_t *, int);
+int pthread_condattr_getclock(const pthread_condattr_t *__restrict, clockid_t *__restrict);
+int pthread_condattr_getpshared(const pthread_condattr_t *__restrict, int *__restrict);
+
+int pthread_rwlockattr_init(pthread_rwlockattr_t *);
+int pthread_rwlockattr_destroy(pthread_rwlockattr_t *);
+int pthread_rwlockattr_setpshared(pthread_rwlockattr_t *, int);
+int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *__restrict, int *__restrict);
+
+int pthread_barrierattr_destroy(pthread_barrierattr_t *);
+int pthread_barrierattr_getpshared(const pthread_barrierattr_t *__restrict, int *__restrict);
+int pthread_barrierattr_init(pthread_barrierattr_t *);
+int pthread_barrierattr_setpshared(pthread_barrierattr_t *, int);
+
+int pthread_atfork(void (*)(void), void (*)(void), void (*)(void));
+
+int pthread_getconcurrency(void);
+int pthread_setconcurrency(int);
+
+int pthread_getcpuclockid(pthread_t, clockid_t *);
+
+struct __ptcb {
+	void (*__f)(void *);
+	void *__x;
+	struct __ptcb *__next;
+};
+
+void _pthread_cleanup_push(struct __ptcb *, void (*)(void *), void *);
+void _pthread_cleanup_pop(struct __ptcb *, int);
+
+#define pthread_cleanup_push(f, x) do { struct __ptcb __cb; _pthread_cleanup_push(&__cb, f, x);
+#define pthread_cleanup_pop(r) _pthread_cleanup_pop(&__cb, (r)); } while(0)
+
+#ifdef _GNU_SOURCE
+struct cpu_set_t;
+int pthread_getaffinity_np(pthread_t, size_t, struct cpu_set_t *);
+int pthread_setaffinity_np(pthread_t, size_t, const struct cpu_set_t *);
+int pthread_getattr_np(pthread_t, pthread_attr_t *);
+int pthread_setname_np(pthread_t, const char *);
+int pthread_getname_np(pthread_t, char *, size_t);
+int pthread_getattr_default_np(pthread_attr_t *);
+int pthread_setattr_default_np(const pthread_attr_t *);
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) || !defined(_WASI_STRICT_PTHREAD)
+int pthread_tryjoin_np(pthread_t, void **);
+int pthread_timedjoin_np(pthread_t, void **, const struct timespec *);
+#else
+#define pthread_tryjoin_np(...) ({ _Static_assert(0, "This function is not available on a single-threaded target; switch to a multi-threaded target with -pthread or enable a stub implementation by undefining _WASI_STRICT_PTHREAD"); 0;})
+#define pthread_timedjoin_np(...) ({ _Static_assert(0, "This function is not available on a single-threaded target; switch to a multi-threaded target with -pthread or enable a stub implementation by undefining _WASI_STRICT_PTHREAD"); 0;})
+#endif
+#endif
+
+#if _REDIR_TIME64
+__REDIR(pthread_mutex_timedlock, __pthread_mutex_timedlock_time64);
+__REDIR(pthread_cond_timedwait, __pthread_cond_timedwait_time64);
+__REDIR(pthread_rwlock_timedrdlock, __pthread_rwlock_timedrdlock_time64);
+__REDIR(pthread_rwlock_timedwrlock, __pthread_rwlock_timedwrlock_time64);
+#ifdef _GNU_SOURCE
+__REDIR(pthread_timedjoin_np, __pthread_timedjoin_np_time64);
+#endif
+#endif
+
+#ifdef __cplusplus
+}
+#endif
+#endif
lib/libc/wasi/libc-top-half/musl/include/sched.h
@@ -16,7 +16,6 @@ extern "C" {
 
 #include <bits/alltypes.h>
 
-#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */
 struct sched_param {
 	int sched_priority;
 	int __reserved1;
@@ -31,6 +30,7 @@ struct sched_param {
 	int __reserved3;
 };
 
+#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */
 int    sched_get_priority_max(int);
 int    sched_get_priority_min(int);
 int    sched_getparam(pid_t, struct sched_param *);
@@ -127,7 +127,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/wasi/libc-top-half/musl/include/stdc-predef.h
@@ -1,13 +0,0 @@
-#ifndef _STDC_PREDEF_H
-#define _STDC_PREDEF_H
-
-#define __STDC_ISO_10646__ 201206L
-
-#if !defined(__GCC_IEC_559) || __GCC_IEC_559 > 0
-#define __STDC_IEC_559__ 1
-#endif
-
-#define __STDC_UTF_16__ 1
-#define __STDC_UTF_32__ 1
-
-#endif
lib/libc/wasi/libc-top-half/musl/include/stdlib.h
@@ -108,7 +108,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)
 #endif
 
@@ -190,7 +190,7 @@ long double strtold_l(const char *__restrict, char **__restrict, struct __locale
 #endif
 
 #ifdef __wasilibc_unmodified_upstream /* WASI has no temp directories */
-#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/wasi/libc-top-half/musl/include/string.h
@@ -92,6 +92,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) \
@@ -111,14 +112,8 @@ 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);
-#ifdef __wasilibc_unmodified_upstream /* avoid unprototyped decls; use <libgen.h> */
-#ifndef __cplusplus
-char *basename();
-#endif
-#endif
 #endif
 
 #ifdef __cplusplus
lib/libc/wasi/libc-top-half/musl/include/strings.h
@@ -1,39 +0,0 @@
-#ifndef	_STRINGS_H
-#define	_STRINGS_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#define __NEED_size_t
-#define __NEED_locale_t
-#include <bits/alltypes.h>
-
-#if defined(_GNU_SOURCE) || defined(_BSD_SOURCE) || defined(_POSIX_SOURCE) \
- || (defined(_POSIX_C_SOURCE) && _POSIX_C_SOURCE+0 < 200809L) \
- || (defined(_XOPEN_SOURCE) && _XOPEN_SOURCE+0 < 700)
-int bcmp (const void *, const void *, size_t);
-void bcopy (const void *, void *, size_t);
-void bzero (void *, size_t);
-char *index (const char *, int);
-char *rindex (const char *, int);
-#endif
-
-#if defined(_XOPEN_SOURCE) || defined(_GNU_SOURCE)  || defined(_BSD_SOURCE)
-int ffs (int);
-int ffsl (long);
-int ffsll (long long);
-#endif
-
-int strcasecmp (const char *, const char *);
-int strncasecmp (const char *, const char *, size_t);
-
-int strcasecmp_l (const char *, const char *, locale_t);
-int strncasecmp_l (const char *, const char *, size_t, locale_t);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
lib/libc/wasi/libc-top-half/musl/include/unistd.h
@@ -336,15 +336,21 @@ pid_t gettid(void);
 #endif
 #define _POSIX_VDISABLE         0
 
-#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT)
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) || !defined(_WASI_STRICT_PTHREAD)
 #define _POSIX_THREADS          _POSIX_VERSION
-#endif
 #define _POSIX_THREAD_PROCESS_SHARED _POSIX_VERSION
 #define _POSIX_THREAD_SAFE_FUNCTIONS _POSIX_VERSION
+#endif
+#if defined(__wasilibc_unmodified_upstream) /* wasi-libc doesn't provide pthread_attr_{get,set}stackaddr */
 #define _POSIX_THREAD_ATTR_STACKADDR _POSIX_VERSION
+#endif
+#if defined(__wasilibc_unmodified_upstream) || defined(_REENTRANT) || !defined(_WASI_STRICT_PTHREAD)
 #define _POSIX_THREAD_ATTR_STACKSIZE _POSIX_VERSION
+#endif
+#if defined(__wasilibc_unmodified_upstream) /* WASI has no scheduling control, and wasi-libc doesn't provide pthread_getcpuclockid */
 #define _POSIX_THREAD_PRIORITY_SCHEDULING _POSIX_VERSION
 #define _POSIX_THREAD_CPUTIME   _POSIX_VERSION
+#endif
 #define _POSIX_TIMERS           _POSIX_VERSION
 #define _POSIX_TIMEOUTS         _POSIX_VERSION
 #define _POSIX_MONOTONIC_CLOCK  _POSIX_VERSION
@@ -529,6 +535,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
@@ -571,6 +579,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/wasi/libc-top-half/musl/src/conf/confstr.c
@@ -1,17 +0,0 @@
-#include <unistd.h>
-#include <stdio.h>
-#include <errno.h>
-
-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) {
-		errno = EINVAL;
-		return 0;
-	}
-	// snprintf is overkill but avoid wasting code size to implement
-	// this completely useless function and its truncation semantics
-	return snprintf(buf, len, "%s", s) + 1;
-}
lib/libc/wasi/libc-top-half/musl/src/conf/sysconf.c
@@ -9,6 +9,7 @@
 #endif
 #include <sys/sysinfo.h>
 #ifdef __wasilibc_unmodified_upstream
+#include <sys/auxv.h>
 #include "syscall.h"
 #endif
 #include "libc.h"
@@ -29,6 +30,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))
 
@@ -211,6 +214,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]) {
@@ -278,5 +284,14 @@ long sysconf(int name)
 	case JT_ZERO & 255:
 		return 0;
 	}
+#ifdef __wasilibc_unmodified_upstream // WASI has no auxv
+	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;
+#endif
 	return values[name];
 }
lib/libc/wasi/libc-top-half/musl/src/env/__stack_chk_fail.c
@@ -38,12 +38,22 @@ hidden void __stack_chk_fail_local(void);
 weak_alias(__stack_chk_fail, __stack_chk_fail_local);
 
 #ifndef __wasilibc_unmodified_upstream
+#ifdef __wasilibc_use_wasip2
+# include <wasi/libc.h>
+#else
 # include <wasi/api.h>
+#endif
 
 __attribute__((constructor(60)))
 static void __wasilibc_init_ssp(void) {
 	uintptr_t entropy;
+#ifdef __wasilibc_use_wasip2
+        int len = sizeof(uintptr_t);
+
+        int r = __wasilibc_random(&entropy, len);
+#else
 	int r = __wasi_random_get((uint8_t *)&entropy, sizeof(uintptr_t));
+#endif
 	__init_ssp(r ? NULL : &entropy);
 }
 #endif
lib/libc/wasi/libc-top-half/musl/src/include/pthread.h
@@ -0,0 +1,31 @@
+#ifndef PTHREAD_H
+#define PTHREAD_H
+
+#include "../../include/pthread.h"
+
+hidden int __pthread_once(pthread_once_t *, void (*)(void));
+hidden void __pthread_testcancel(void);
+hidden int __pthread_setcancelstate(int, int *);
+hidden int __pthread_create(pthread_t *restrict, const pthread_attr_t *restrict, void *(*)(void *), void *restrict);
+#ifdef __wasilibc_unmodified_upstream
+hidden _Noreturn void __pthread_exit(void *);
+#endif
+hidden int __pthread_join(pthread_t, void **);
+hidden int __pthread_mutex_lock(pthread_mutex_t *);
+hidden int __pthread_mutex_trylock(pthread_mutex_t *);
+hidden int __pthread_mutex_trylock_owner(pthread_mutex_t *);
+hidden int __pthread_mutex_timedlock(pthread_mutex_t *restrict, const struct timespec *restrict);
+hidden int __pthread_mutex_unlock(pthread_mutex_t *);
+hidden int __private_cond_signal(pthread_cond_t *, int);
+hidden int __pthread_cond_timedwait(pthread_cond_t *restrict, pthread_mutex_t *restrict, const struct timespec *restrict);
+hidden int __pthread_key_create(pthread_key_t *, void (*)(void *));
+hidden int __pthread_key_delete(pthread_key_t);
+hidden int __pthread_rwlock_rdlock(pthread_rwlock_t *);
+hidden int __pthread_rwlock_tryrdlock(pthread_rwlock_t *);
+hidden int __pthread_rwlock_timedrdlock(pthread_rwlock_t *__restrict, const struct timespec *__restrict);
+hidden int __pthread_rwlock_wrlock(pthread_rwlock_t *);
+hidden int __pthread_rwlock_trywrlock(pthread_rwlock_t *);
+hidden int __pthread_rwlock_timedwrlock(pthread_rwlock_t *__restrict, const struct timespec *__restrict);
+hidden int __pthread_rwlock_unlock(pthread_rwlock_t *);
+
+#endif
lib/libc/wasi/libc-top-half/musl/src/include/time.h
@@ -0,0 +1,15 @@
+#ifndef TIME_H
+#define TIME_H
+
+#include "../../include/time.h"
+
+hidden int __clock_gettime(clockid_t, struct timespec *);
+hidden int __clock_nanosleep(clockid_t, int, const struct timespec *, struct timespec *);
+
+hidden char *__asctime_r(const struct tm *, char *);
+hidden struct tm *__gmtime_r(const time_t *restrict, struct tm *restrict);
+hidden struct tm *__localtime_r(const time_t *restrict, struct tm *restrict);
+
+hidden size_t __strftime_l(char *restrict, size_t, const char *restrict, const struct tm *restrict, locale_t);
+
+#endif
lib/libc/wasi/libc-top-half/musl/src/internal/fork_impl.h
@@ -3,7 +3,6 @@
 #ifdef __wasilibc_unmodified_upstream
 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;
@@ -18,4 +17,7 @@ extern hidden volatile int *const __vmlock_lockptr;
 
 hidden void __malloc_atfork(int);
 hidden void __ldso_atfork(int);
+hidden void __pthread_key_atfork(int);
+
+hidden void __post_Fork(int);
 #endif
lib/libc/wasi/libc-top-half/musl/src/internal/ksigaction.h
@@ -1,13 +0,0 @@
-#include <features.h>
-
-/* This is the structure used for the rt_sigaction syscall on most archs,
- * but it can be overridden by a file with the same name in the top-level
- * arch dir for a given arch, if necessary. */
-struct k_sigaction {
-	void (*handler)(int);
-	unsigned long flags;
-	void (*restorer)(void);
-	unsigned mask[2];
-};
-
-hidden void __restore(), __restore_rt();
lib/libc/wasi/libc-top-half/musl/src/internal/locale_impl.h
@@ -64,7 +64,7 @@ hidden char *__gettextdomain(void);
         &libc.current_locale; \
     }))
 
-#define CURRENT_UTF8 (!!libc.global_locale.cat[LC_CTYPE])
+#define CURRENT_UTF8 (!!CURRENT_LOCALE->cat[LC_CTYPE])
 #endif
 
 #undef MB_CUR_MAX
lib/libc/wasi/libc-top-half/musl/src/internal/pthread_impl.h
@@ -186,8 +186,10 @@ static inline void __wake(volatile void *addr, int cnt, int priv)
 	__syscall(SYS_futex, addr, FUTEX_WAKE|priv, cnt) != -ENOSYS ||
 	__syscall(SYS_futex, addr, FUTEX_WAKE, cnt);
 #else
+#ifdef _REENTRANT
 	__builtin_wasm_memory_atomic_notify((int*)addr, cnt);
 #endif
+#endif
 }
 static inline void __futexwait(volatile void *addr, int val, int priv)
 {
lib/libc/wasi/libc-top-half/musl/src/internal/syscall.h
@@ -59,7 +59,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);
@@ -72,9 +72,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 */
 
@@ -202,43 +202,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
 
@@ -392,6 +392,18 @@ static inline long __alt_socketcall(int sys, int sock, int cp, long a, long b, l
 #define __sys_open_cp(...) __SYSCALL_DISP(__sys_open_cp,,__VA_ARGS__)
 #define sys_open_cp(...) __syscall_ret(__sys_open_cp(__VA_ARGS__))
 
+#ifdef SYS_wait4
+#define __sys_wait4(a,b,c,d) __syscall(SYS_wait4,a,b,c,d)
+#define __sys_wait4_cp(a,b,c,d) __syscall_cp(SYS_wait4,a,b,c,d)
+#else
+hidden long __emulate_wait4(int, int *, int, void *, int);
+#define __sys_wait4(a,b,c,d) __emulate_wait4(a,b,c,d,0)
+#define __sys_wait4_cp(a,b,c,d) __emulate_wait4(a,b,c,d,1)
+#endif
+
+#define sys_wait4(a,b,c,d) __syscall_ret(__sys_wait4(a,b,c,d))
+#define sys_wait4_cp(a,b,c,d) __syscall_ret(__sys_wait4_cp(a,b,c,d))
+
 hidden void __procfdname(char __buf[static 15+3*sizeof(int)], unsigned);
 
 hidden void *__vdsosym(const char *, const char *);
lib/libc/wasi/libc-top-half/musl/src/math/powl.c
@@ -216,25 +216,33 @@ long double powl(long double x, long double y)
 	}
 	if (x == 1.0)
 		return 1.0; /* 1**y = 1, even if y is nan */
-	if (x == -1.0 && !isfinite(y))
-		return 1.0; /* -1**inf = 1 */
 	if (y == 0.0)
 		return 1.0; /* x**0 = 1, even if x is nan */
 	if (y == 1.0)
 		return x;
-	if (y >= LDBL_MAX) {
-		if (x > 1.0 || x < -1.0)
-			return INFINITY;
-		if (x != 0.0)
-			return 0.0;
-	}
-	if (y <= -LDBL_MAX) {
-		if (x > 1.0 || x < -1.0)
+	/* if y*log2(x) < log2(LDBL_TRUE_MIN)-1 then x^y uflows to 0
+	   if y*log2(x) > -log2(LDBL_TRUE_MIN)+1 > LDBL_MAX_EXP then x^y oflows
+	   if |x|!=1 then |log2(x)| > |log(x)| > LDBL_EPSILON/2 so
+	   x^y oflows/uflows if |y|*LDBL_EPSILON/2 > -log2(LDBL_TRUE_MIN)+1 */
+	if (fabsl(y) > 2*(-LDBL_MIN_EXP+LDBL_MANT_DIG+1)/LDBL_EPSILON) {
+		/* y is not an odd int */
+		if (x == -1.0)
+			return 1.0;
+		if (y == INFINITY) {
+			if (x > 1.0 || x < -1.0)
+				return INFINITY;
 			return 0.0;
-		if (x != 0.0 || y == -INFINITY)
+		}
+		if (y == -INFINITY) {
+			if (x > 1.0 || x < -1.0)
+				return 0.0;
 			return INFINITY;
+		}
+		if ((x > 1.0 || x < -1.0) == (y > 0))
+			return huge * huge;
+		return twom10000 * twom10000;
 	}
-	if (x >= LDBL_MAX) {
+	if (x == INFINITY) {
 		if (y > 0.0)
 			return INFINITY;
 		return 0.0;
@@ -257,7 +265,7 @@ long double powl(long double x, long double y)
 			yoddint = 1;
 	}
 
-	if (x <= -LDBL_MAX) {
+	if (x == -INFINITY) {
 		if (y > 0.0) {
 			if (yoddint)
 				return -INFINITY;
lib/libc/wasi/libc-top-half/musl/src/misc/nftw.c
@@ -33,6 +33,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;
@@ -48,7 +50,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;
lib/libc/wasi/libc-top-half/musl/src/regex/glob.c
@@ -271,7 +271,7 @@ int glob(const char *restrict pat, int flags, int (*errfunc)(const char *path, i
 			if (append(&tail, pat, strlen(pat), 0))
 				return GLOB_NOSPACE;
 			cnt++;
-		} else
+		} else if (!error)
 			return GLOB_NOMATCH;
 	}
 
lib/libc/wasi/libc-top-half/musl/src/setjmp/wasm32/rt.c
@@ -0,0 +1,83 @@
+/*
+ * a runtime implementation for
+ * https://github.com/llvm/llvm-project/pull/84137
+ * https://docs.google.com/document/d/1ZvTPT36K5jjiedF8MCXbEmYjULJjI723aOAks1IdLLg/edit
+ */
+
+#include <stddef.h>
+#include <stdint.h>
+
+/*
+ * function prototypes
+ */
+void __wasm_setjmp(void *env, uint32_t label, void *func_invocation_id);
+uint32_t __wasm_setjmp_test(void *env, void *func_invocation_id);
+void __wasm_longjmp(void *env, int val);
+
+/*
+ * jmp_buf should have large enough size and alignment to contain
+ * this structure.
+ */
+struct jmp_buf_impl {
+        void *func_invocation_id;
+        uint32_t label;
+
+        /*
+         * this is a temorary storage used by the communication between
+         * __wasm_sjlj_longjmp and WebAssemblyLowerEmscriptenEHSjL-generated
+         * logic.
+         * ideally, this can be replaced with multivalue.
+         */
+        struct arg {
+                void *env;
+                int val;
+        } arg;
+};
+
+void
+__wasm_setjmp(void *env, uint32_t label, void *func_invocation_id)
+{
+        struct jmp_buf_impl *jb = env;
+        if (label == 0) { /* ABI contract */
+                __builtin_trap();
+        }
+        if (func_invocation_id == NULL) { /* sanity check */
+                __builtin_trap();
+        }
+        jb->func_invocation_id = func_invocation_id;
+        jb->label = label;
+}
+
+uint32_t
+__wasm_setjmp_test(void *env, void *func_invocation_id)
+{
+        struct jmp_buf_impl *jb = env;
+        if (jb->label == 0) { /* ABI contract */
+                __builtin_trap();
+        }
+        if (func_invocation_id == NULL) { /* sanity check */
+                __builtin_trap();
+        }
+        if (jb->func_invocation_id == func_invocation_id) {
+                return jb->label;
+        }
+        return 0;
+}
+
+void
+__wasm_longjmp(void *env, int val)
+{
+        struct jmp_buf_impl *jb = env;
+        struct arg *arg = &jb->arg;
+        /*
+         * C standard says:
+         * The longjmp function cannot cause the setjmp macro to return
+         * the value 0; if val is 0, the setjmp macro returns the value 1.
+         */
+        if (val == 0) {
+                val = 1;
+        }
+        arg->env = env;
+        arg->val = val;
+        __builtin_wasm_throw(1, arg); /* 1 == C_LONGJMP */
+}
lib/libc/wasi/libc-top-half/musl/src/stdio/freopen.c
@@ -67,6 +67,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;
 
lib/libc/wasi/libc-top-half/musl/src/stdio/open_wmemstream.c
@@ -48,8 +48,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/wasi/libc-top-half/musl/src/stdio/ungetc.c
@@ -1,20 +0,0 @@
-#include "stdio_impl.h"
-
-int ungetc(int c, FILE *f)
-{
-	if (c == EOF) return c;
-
-	FLOCK(f);
-
-	if (!f->rpos) __toread(f);
-	if (!f->rpos || f->rpos <= f->buf - UNGET) {
-		FUNLOCK(f);
-		return EOF;
-	}
-
-	*--f->rpos = c;
-	f->flags &= ~F_EOF;
-
-	FUNLOCK(f);
-	return (unsigned char)c;
-}
lib/libc/wasi/libc-top-half/musl/src/stdio/vfprintf.c
@@ -56,7 +56,7 @@ static const unsigned char states[]['z'-'A'+1] = {
 		S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT,
 		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
 		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
-		S('c') = CHAR, S('C') = INT,
+		S('c') = INT, S('C') = UINT,
 		S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR,
 		S('m') = NOARG,
 		S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
@@ -66,7 +66,7 @@ static const unsigned char states[]['z'-'A'+1] = {
 		S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
 		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
 		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
-		S('c') = INT, S('s') = PTR, S('n') = PTR,
+		S('c') = UINT, S('s') = PTR, S('n') = PTR,
 		S('l') = LLPRE,
 	}, { /* 2: ll-prefixed */
 		S('d') = LLONG, S('i') = LLONG,
@@ -152,7 +152,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)
@@ -476,7 +476,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 	unsigned st, ps;
 	int cnt=0, l=0;
 	size_t i;
-	char buf[sizeof(uintmax_t)*3+3+LDBL_MANT_DIG/4];
+	char buf[sizeof(uintmax_t)*3];
 	const char *prefix;
 	int t, pl;
 	wchar_t wc[2], *ws;
@@ -517,8 +517,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;
@@ -530,8 +530,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;
@@ -560,13 +560,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;
@@ -622,6 +627,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 			}
 			p = MAX(p, z-a + !arg.i);
 			break;
+		narrow_c:
 		case 'c':
 			*(a=z-(p=1))=arg.i;
 			fl &= ~ZERO_PAD;
@@ -636,6 +642,7 @@ static int printf_core(FILE *f, const char *fmt, va_list *ap, union arg *nl_arg,
 			fl &= ~ZERO_PAD;
 			break;
 		case 'C':
+			if (!arg.i) goto narrow_c;
 			wc[0] = arg.i;
 			wc[1] = 0;
 			arg.p = wc;
@@ -713,7 +720,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;
@@ -729,7 +736,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/wasi/libc-top-half/musl/src/stdio/vfwprintf.c
@@ -49,7 +49,7 @@ static const unsigned char states[]['z'-'A'+1] = {
 		S('o') = UINT, S('u') = UINT, S('x') = UINT, S('X') = UINT,
 		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
 		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
-		S('c') = CHAR, S('C') = INT,
+		S('c') = INT, S('C') = UINT,
 		S('s') = PTR, S('S') = PTR, S('p') = UIPTR, S('n') = PTR,
 		S('m') = NOARG,
 		S('l') = LPRE, S('h') = HPRE, S('L') = BIGLPRE,
@@ -59,7 +59,7 @@ static const unsigned char states[]['z'-'A'+1] = {
 		S('o') = ULONG, S('u') = ULONG, S('x') = ULONG, S('X') = ULONG,
 		S('e') = DBL, S('f') = DBL, S('g') = DBL, S('a') = DBL,
 		S('E') = DBL, S('F') = DBL, S('G') = DBL, S('A') = DBL,
-		S('c') = INT, S('s') = PTR, S('n') = PTR,
+		S('c') = UINT, S('s') = PTR, S('n') = PTR,
 		S('l') = LLPRE,
 	}, { /* 2: ll-prefixed */
 		S('d') = LLONG, S('i') = LLONG,
@@ -144,7 +144,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) {
@@ -261,6 +267,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;
 
@@ -277,25 +287,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':
@@ -308,14 +315,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;
 		}
@@ -389,8 +396,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;
 
@@ -406,7 +413,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/wasi/libc-top-half/musl/src/stdio/vfwscanf.c
@@ -1,332 +0,0 @@
-#include <stdio.h>
-#include <stdlib.h>
-#include <stdarg.h>
-#include <ctype.h>
-#include <wchar.h>
-#include <wctype.h>
-#include <limits.h>
-#include <string.h>
-
-#include "stdio_impl.h"
-#include "shgetc.h"
-#include "intscan.h"
-#include "floatscan.h"
-
-#define SIZE_hh -2
-#define SIZE_h  -1
-#define SIZE_def 0
-#define SIZE_l   1
-#define SIZE_L   2
-#define SIZE_ll  3
-
-static void store_int(void *dest, int size, unsigned long long i)
-{
-	if (!dest) return;
-	switch (size) {
-	case SIZE_hh:
-		*(char *)dest = i;
-		break;
-	case SIZE_h:
-		*(short *)dest = i;
-		break;
-	case SIZE_def:
-		*(int *)dest = i;
-		break;
-	case SIZE_l:
-		*(long *)dest = i;
-		break;
-	case SIZE_ll:
-		*(long long *)dest = i;
-		break;
-	}
-}
-
-static void *arg_n(va_list ap, unsigned int n)
-{
-	void *p;
-	unsigned int i;
-	va_list ap2;
-	va_copy(ap2, ap);
-	for (i=n; i>1; i--) va_arg(ap2, void *);
-	p = va_arg(ap2, void *);
-	va_end(ap2);
-	return p;
-}
-
-static int in_set(const wchar_t *set, int c)
-{
-	int j;
-	const wchar_t *p = set;
-	if (*p == '-') {
-		if (c=='-') return 1;
-		p++;
-	} else if (*p == ']') {
-		if (c==']') return 1;
-		p++;
-	}
-	for (; *p && *p != ']'; p++) {
-		if (*p=='-' && p[1] && p[1] != ']')
-			for (j=p++[-1]; j<*p; j++)
-				if (c==j) return 1;
-		if (c==*p) return 1;
-	}
-	return 0;
-}
-
-#if 1
-#undef getwc
-#define getwc(f) \
-	((f)->rpos != (f)->rend && *(f)->rpos < 128 ? *(f)->rpos++ : (getwc)(f))
-
-#undef ungetwc
-#define ungetwc(c,f) \
-	((f)->rend && (c)<128U ? *--(f)->rpos : ungetwc((c),(f)))
-#endif
-
-int vfwscanf(FILE *restrict f, const wchar_t *restrict fmt, va_list ap)
-{
-	int width;
-	int size;
-	int alloc;
-	const wchar_t *p;
-	int c, t;
-	char *s;
-	wchar_t *wcs;
-	void *dest=NULL;
-	int invert;
-	int matches=0;
-	off_t pos = 0, cnt;
-	static const char size_pfx[][3] = { "hh", "h", "", "l", "L", "ll" };
-	char tmp[3*sizeof(int)+10];
-	const wchar_t *set;
-	size_t i, k;
-
-	FLOCK(f);
-
-	fwide(f, 1);
-
-	for (p=fmt; *p; p++) {
-
-		alloc = 0;
-
-		if (iswspace(*p)) {
-			while (iswspace(p[1])) p++;
-			while (iswspace((c=getwc(f)))) pos++;
-			ungetwc(c, f);
-			continue;
-		}
-		if (*p != '%' || p[1] == '%') {
-			if (*p == '%') {
-				p++;
-				while (iswspace((c=getwc(f)))) pos++;
-			} else {
-				c = getwc(f);
-			}
-			if (c!=*p) {
-				ungetwc(c, f);
-				if (c<0) goto input_fail;
-				goto match_fail;
-			}
-			pos++;
-			continue;
-		}
-
-		p++;
-		if (*p=='*') {
-			dest = 0; p++;
-		} else if (iswdigit(*p) && p[1]=='$') {
-			dest = arg_n(ap, *p-'0'); p+=2;
-		} else {
-			dest = va_arg(ap, void *);
-		}
-
-		for (width=0; iswdigit(*p); p++) {
-			width = 10*width + *p - '0';
-		}
-
-		if (*p=='m') {
-			wcs = 0;
-			s = 0;
-			alloc = !!dest;
-			p++;
-		} else {
-			alloc = 0;
-		}
-
-		size = SIZE_def;
-		switch (*p++) {
-		case 'h':
-			if (*p == 'h') p++, size = SIZE_hh;
-			else size = SIZE_h;
-			break;
-		case 'l':
-			if (*p == 'l') p++, size = SIZE_ll;
-			else size = SIZE_l;
-			break;
-		case 'j':
-			size = SIZE_ll;
-			break;
-		case 'z':
-		case 't':
-			size = SIZE_l;
-			break;
-		case 'L':
-			size = SIZE_L;
-			break;
-		case 'd': case 'i': case 'o': case 'u': case 'x':
-		case 'a': case 'e': case 'f': case 'g':
-		case 'A': case 'E': case 'F': case 'G': case 'X':
-		case 's': case 'c': case '[':
-		case 'S': case 'C':
-		case 'p': case 'n':
-			p--;
-			break;
-		default:
-			goto fmt_fail;
-		}
-
-		t = *p;
-
-		/* Transform S,C -> ls,lc */
-		if ((t&0x2f)==3) {
-			size = SIZE_l;
-			t |= 32;
-		}
-
-		if (t != 'n') {
-			if (t != '[' && (t|32) != 'c')
-				while (iswspace((c=getwc(f)))) pos++;
-			else
-				c=getwc(f);
-			if (c < 0) goto input_fail;
-			ungetwc(c, f);
-		}
-
-		switch (t) {
-		case 'n':
-			store_int(dest, size, pos);
-			/* do not increment match count, etc! */
-			continue;
-
-		case 's':
-		case 'c':
-		case '[':
-			if (t == 'c') {
-				if (width<1) width = 1;
-				invert = 1;
-				set = L"";
-			} else if (t == 's') {
-				invert = 1;
-				static const wchar_t spaces[] = {
-					' ', '\t', '\n', '\r', 11, 12,  0x0085,
-					0x2000, 0x2001, 0x2002, 0x2003, 0x2004, 0x2005,
-					0x2006, 0x2008, 0x2009, 0x200a,
-					0x2028, 0x2029, 0x205f, 0x3000, 0 };
-				set = spaces;
-			} else {
-				if (*++p == '^') p++, invert = 1;
-				else invert = 0;
-				set = p;
-				if (*p==']') p++;
-				while (*p!=']') {
-					if (!*p) goto fmt_fail;
-					p++;
-				}
-			}
-
-			s = (size == SIZE_def) ? dest : 0;
-			wcs = (size == SIZE_l) ? dest : 0;
-
-			int gotmatch = 0;
-
-			if (width < 1) width = -1;
-
-			i = 0;
-			if (alloc) {
-				k = t=='c' ? width+1U : 31;
-				if (size == SIZE_l) {
-					wcs = malloc(k*sizeof(wchar_t));
-					if (!wcs) goto alloc_fail;
-				} else {
-					s = malloc(k);
-					if (!s) goto alloc_fail;
-				}
-			}
-			while (width) {
-				if ((c=getwc(f))<0) break;
-				if (in_set(set, c) == invert)
-					break;
-				if (wcs) {
-					wcs[i++] = c;
-					if (alloc && i==k) {
-						k += k+1;
-						wchar_t *tmp = realloc(wcs, k*sizeof(wchar_t));
-						if (!tmp) goto alloc_fail;
-						wcs = tmp;
-					}
-				} else if (size != SIZE_l) {
-					int l = wctomb(s?s+i:tmp, c);
-					if (l<0) goto input_fail;
-					i += l;
-					if (alloc && i > k-4) {
-						k += k+1;
-						char *tmp = realloc(s, k);
-						if (!tmp) goto alloc_fail;
-						s = tmp;
-					}
-				}
-				pos++;
-				width-=(width>0);
-				gotmatch=1;
-			}
-			if (width) {
-				ungetwc(c, f);
-				if (t == 'c' || !gotmatch) goto match_fail;
-			}
-
-			if (alloc) {
-				if (size == SIZE_l) *(wchar_t **)dest = wcs;
-				else *(char **)dest = s;
-			}
-			if (t != 'c') {
-				if (wcs) wcs[i] = 0;
-				if (s) s[i] = 0;
-			}
-			break;
-
-		case 'd': case 'i': case 'o': case 'u': case 'x':
-		case 'a': case 'e': case 'f': case 'g':
-		case 'A': case 'E': case 'F': case 'G': case 'X':
-		case 'p':
-			if (width < 1) width = 0;
-			snprintf(tmp, sizeof tmp, "%.*s%.0d%s%c%%lln",
-				1+!dest, "%*", width, size_pfx[size+2], t);
-			cnt = 0;
-			if (fscanf(f, tmp, dest?dest:&cnt, &cnt) == -1)
-				goto input_fail;
-			else if (!cnt)
-				goto match_fail;
-			pos += cnt;
-			break;
-		default:
-			goto fmt_fail;
-		}
-
-		if (dest) matches++;
-	}
-	if (0) {
-fmt_fail:
-alloc_fail:
-input_fail:
-		if (!matches) matches--;
-match_fail:
-		if (alloc) {
-			free(s);
-			free(wcs);
-		}
-	}
-	FUNLOCK(f);
-	return matches;
-}
-
-weak_alias(vfwscanf,__isoc99_vfwscanf);
lib/libc/wasi/libc-top-half/musl/src/stdio/vsnprintf.c
@@ -47,11 +47,6 @@ int vsnprintf(char *restrict s, size_t n, const char *restrict fmt, va_list ap)
 		.cookie = &c,
 	};
 
-	if (n > INT_MAX) {
-		errno = EOVERFLOW;
-		return -1;
-	}
-
 	*c.s = 0;
 	return vfprintf(&f, fmt, ap);
 }
lib/libc/wasi/libc-top-half/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--;
@@ -52,9 +53,6 @@ int vswprintf(wchar_t *restrict s, size_t n, const wchar_t *restrict fmt, va_lis
 
 	if (!n) {
 		return -1;
-	} else if (n > INT_MAX) {
-		errno = EOVERFLOW;
-		return -1;
 	}
 	r = vfwprintf(&f, fmt, ap);
 	sw_write(&f, 0, 0);
lib/libc/wasi/libc-top-half/musl/src/stdlib/strtol.c
@@ -1,56 +0,0 @@
-#include "stdio_impl.h"
-#include "intscan.h"
-#include "shgetc.h"
-#include <inttypes.h>
-#include <limits.h>
-#include <ctype.h>
-
-static unsigned long long strtox(const char *s, char **p, int base, unsigned long long lim)
-{
-	FILE f;
-	sh_fromstring(&f, s);
-	shlim(&f, 0);
-	unsigned long long y = __intscan(&f, base, 1, lim);
-	if (p) {
-		size_t cnt = shcnt(&f);
-		*p = (char *)s + cnt;
-	}
-	return y;
-}
-
-unsigned long long strtoull(const char *restrict s, char **restrict p, int base)
-{
-	return strtox(s, p, base, ULLONG_MAX);
-}
-
-long long strtoll(const char *restrict s, char **restrict p, int base)
-{
-	return strtox(s, p, base, LLONG_MIN);
-}
-
-unsigned long strtoul(const char *restrict s, char **restrict p, int base)
-{
-	return strtox(s, p, base, ULONG_MAX);
-}
-
-long strtol(const char *restrict s, char **restrict p, int base)
-{
-	return strtox(s, p, base, 0UL+LONG_MIN);
-}
-
-intmax_t strtoimax(const char *restrict s, char **restrict p, int base)
-{
-	return strtoll(s, p, base);
-}
-
-uintmax_t strtoumax(const char *restrict s, char **restrict p, int base)
-{
-	return strtoull(s, p, base);
-}
-
-weak_alias(strtol, __strtol_internal);
-weak_alias(strtoul, __strtoul_internal);
-weak_alias(strtoll, __strtoll_internal);
-weak_alias(strtoull, __strtoull_internal);
-weak_alias(strtoimax, __strtoimax_internal);
-weak_alias(strtoumax, __strtoumax_internal);
lib/libc/wasi/libc-top-half/musl/src/string/memchr.c
@@ -0,0 +1,89 @@
+#include <string.h>
+#include <stdint.h>
+#include <limits.h>
+
+#ifdef __wasm_simd128__
+#include <wasm_simd128.h>
+#endif
+
+#define SS (sizeof(size_t))
+#define ALIGN (sizeof(size_t)-1)
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+void *memchr(const void *src, int c, size_t n)
+{
+#if defined(__wasm_simd128__) && defined(__wasilibc_simd_string)
+	// Skip Clang 19 and Clang 20 which have a bug (llvm/llvm-project#146574)
+	// which results in an ICE when inline assembly is used with a vector result.
+#if __clang_major__ != 19 && __clang_major__ != 20
+	// When n is zero, a function that locates a character finds no occurrence.
+	// Otherwise, decrement n to ensure sub_overflow overflows
+	// when n would go equal-to-or-below zero.
+	if (!n--) {
+		return NULL;
+	}
+
+	// Note that reading before/after the allocation of a pointer is UB in
+	// C, so inline assembly is used to generate the exact machine
+	// instruction we want with opaque semantics to the compiler to avoid
+	// the UB.
+	uintptr_t align = (uintptr_t)src % sizeof(v128_t);
+	uintptr_t addr = (uintptr_t)src - align;
+	v128_t vc = wasm_i8x16_splat(c);
+
+	for (;;) {
+		v128_t v;
+		__asm__ (
+			"local.get %1\n"
+			"v128.load 0\n"
+			"local.set %0\n"
+			: "=r"(v)
+			: "r"(addr)
+			: "memory");
+		v128_t cmp = wasm_i8x16_eq(v, vc);
+		// Bitmask is slow on AArch64, any_true is much faster.
+		if (wasm_v128_any_true(cmp)) {
+			// Clear the bits corresponding to align (little-endian)
+			// so we can count trailing zeros.
+			int mask = wasm_i8x16_bitmask(cmp) >> align << align;
+			// At least one bit will be set, unless align cleared them.
+			// Knowing this helps the compiler if it unrolls the loop.
+			__builtin_assume(mask || align);
+			// If the mask became zero because of align,
+			// it's as if we didn't find anything.
+			if (mask) {
+				// Find the offset of the first one bit (little-endian).
+				// That's a match, unless it is beyond the end of the object.
+				// Recall that we decremented n, so less-than-or-equal-to is correct.
+				size_t ctz = __builtin_ctz(mask);
+				return ctz - align <= n ? (char *)src + (addr + ctz - (uintptr_t)src)
+				                        : NULL;
+			}
+		}
+		// Decrement n; if it overflows we're done.
+		if (__builtin_sub_overflow(n, sizeof(v128_t) - align, &n)) {
+			return NULL;
+		}
+		align = 0;
+		addr += sizeof(v128_t);
+	}
+#endif
+#endif
+
+	const unsigned char *s = src;
+	c = (unsigned char)c;
+#ifdef __GNUC__
+	for (; ((uintptr_t)s & ALIGN) && n && *s != c; s++, n--);
+	if (n && *s != c) {
+		typedef size_t __attribute__((__may_alias__)) word;
+		const word *w;
+		size_t k = ONES * c;
+		for (w = (const void *)s; n>=SS && !HASZERO(*w^k); w++, n-=SS);
+		s = (const void *)w;
+	}
+#endif
+	for (; n && *s != c; s++, n--);
+	return n ? (void *)s : 0;
+}
lib/libc/wasi/libc-top-half/musl/src/string/memcmp.c
@@ -0,0 +1,43 @@
+#include <string.h>
+
+#ifdef __wasm_simd128__
+#include <wasm_simd128.h>
+#endif
+
+int memcmp(const void *vl, const void *vr, size_t n)
+{
+#if defined(__wasm_simd128__) && defined(__wasilibc_simd_string)
+	if (n >= sizeof(v128_t)) {
+		// memcmp is allowed to read up to n bytes from each object.
+		// Find the first different character in the objects.
+		// Unaligned loads handle the case where the objects
+		// have mismatching alignments.
+		const v128_t *v1 = (v128_t *)vl;
+		const v128_t *v2 = (v128_t *)vr;
+		while (n) {
+			const v128_t cmp = wasm_i8x16_eq(wasm_v128_load(v1), wasm_v128_load(v2));
+			// Bitmask is slow on AArch64, all_true is much faster.
+			if (!wasm_i8x16_all_true(cmp)) {
+				// Find the offset of the first zero bit (little-endian).
+				size_t ctz = __builtin_ctz(~wasm_i8x16_bitmask(cmp));
+				const unsigned char *u1 = (unsigned char *)v1 + ctz;
+				const unsigned char *u2 = (unsigned char *)v2 + ctz;
+				// This may help the compiler if the function is inlined.
+				__builtin_assume(*u1 - *u2 != 0);
+				return *u1 - *u2;
+			}
+			// This makes n a multiple of sizeof(v128_t)
+			// for every iteration except the first.
+			size_t align = (n - 1) % sizeof(v128_t) + 1;
+			v1 = (v128_t *)((char *)v1 + align);
+			v2 = (v128_t *)((char *)v2 + align);
+			n -= align;
+		}
+		return 0;
+	}
+#endif
+
+	const unsigned char *l=vl, *r=vr;
+	for (; n && *l == *r; n--, l++, r++);
+	return n ? *l-*r : 0;
+}
lib/libc/wasi/libc-top-half/musl/src/string/memrchr.c
@@ -0,0 +1,33 @@
+#include <string.h>
+
+#ifdef __wasm_simd128__
+#include <wasm_simd128.h>
+#endif
+
+void *__memrchr(const void *m, int c, size_t n)
+{
+#if defined(__wasm_simd128__) && defined(__wasilibc_simd_string)
+	// memrchr is allowed to read up to n bytes from the object.
+	// Search backward for the last matching character.
+	const v128_t *v = (v128_t *)((char *)m + n);
+	const v128_t vc = wasm_i8x16_splat(c);
+	for (; n >= sizeof(v128_t); n -= sizeof(v128_t)) {
+		const v128_t cmp = wasm_i8x16_eq(wasm_v128_load(--v), vc);
+		// Bitmask is slow on AArch64, any_true is much faster.
+		if (wasm_v128_any_true(cmp)) {
+			// Find the offset of the last one bit (little-endian).
+			// The leading 16 bits of the bitmask are always zero,
+			// and to be ignored.
+			size_t clz = __builtin_clz(wasm_i8x16_bitmask(cmp)) - 16;
+			return (char *)(v + 1) - (clz + 1);
+		}
+	}
+#endif
+
+	const unsigned char *s = m;
+	c = (unsigned char)c;
+	while (n--) if (s[n]==c) return (void *)(s+n);
+	return 0;
+}
+
+weak_alias(__memrchr, memrchr);
lib/libc/wasi/libc-top-half/musl/src/string/strchrnul.c
@@ -0,0 +1,75 @@
+#include <string.h>
+#include <stdint.h>
+#include <limits.h>
+
+#ifdef __wasm_simd128__
+#include <wasm_simd128.h>
+#endif
+
+#define ALIGN (sizeof(size_t))
+#define ONES ((size_t)-1/UCHAR_MAX)
+#define HIGHS (ONES * (UCHAR_MAX/2+1))
+#define HASZERO(x) ((x)-ONES & ~(x) & HIGHS)
+
+char *__strchrnul(const char *s, int c)
+{
+	c = (unsigned char)c;
+	if (!c) return (char *)s + strlen(s);
+
+#if defined(__wasm_simd128__) && defined(__wasilibc_simd_string)
+	// Skip Clang 19 and Clang 20 which have a bug (llvm/llvm-project#146574)
+	// which results in an ICE when inline assembly is used with a vector result.
+#if __clang_major__ != 19 && __clang_major__ != 20
+	// Note that reading before/after the allocation of a pointer is UB in
+	// C, so inline assembly is used to generate the exact machine
+	// instruction we want with opaque semantics to the compiler to avoid
+	// the UB.
+	uintptr_t align = (uintptr_t)s % sizeof(v128_t);
+	uintptr_t addr = (uintptr_t)s - align;
+	v128_t vc = wasm_i8x16_splat(c);
+
+	for (;;) {
+		v128_t v;
+		__asm__ (
+			"local.get %1\n"
+			"v128.load 0\n"
+			"local.set %0\n"
+			: "=r"(v)
+			: "r"(addr)
+			: "memory");
+		const v128_t cmp = wasm_i8x16_eq(v, (v128_t){}) | wasm_i8x16_eq(v, vc);
+		// Bitmask is slow on AArch64, any_true is much faster.
+		if (wasm_v128_any_true(cmp)) {
+			// Clear the bits corresponding to align (little-endian)
+			// so we can count trailing zeros.
+			int mask = wasm_i8x16_bitmask(cmp) >> align << align;
+			// At least one bit will be set, unless align cleared them.
+			// Knowing this helps the compiler if it unrolls the loop.
+			__builtin_assume(mask || align);
+			// If the mask became zero because of align,
+			// it's as if we didn't find anything.
+			if (mask) {
+				// Find the offset of the first one bit (little-endian).
+				return (char *)s + (addr - (uintptr_t)s + __builtin_ctz(mask));
+			}
+		}
+		align = 0;
+		addr += sizeof(v128_t);
+	}
+#endif
+#endif
+
+#ifdef __GNUC__
+	typedef size_t __attribute__((__may_alias__)) word;
+	const word *w;
+	for (; (uintptr_t)s % ALIGN; s++)
+		if (!*s || *(unsigned char *)s == c) return (char *)s;
+	size_t k = ONES * c;
+	for (w = (void *)s; !HASZERO(*w) && !HASZERO(*w^k); w++);
+	s = (void *)w;
+#endif
+	for (; *s && *(unsigned char *)s != c; s++);
+	return (char *)s;
+}
+
+weak_alias(__strchrnul, strchrnul);
lib/libc/wasi/libc-top-half/musl/src/thread/pthread_attr_get.c
@@ -0,0 +1,121 @@
+#include "pthread_impl.h"
+
+#ifndef __wasilibc_unmodified_upstream
+#include <common/clock.h>
+#endif
+
+int pthread_attr_getdetachstate(const pthread_attr_t *a, int *state)
+{
+	*state = a->_a_detach;
+	return 0;
+}
+int pthread_attr_getguardsize(const pthread_attr_t *restrict a, size_t *restrict size)
+{
+	*size = a->_a_guardsize;
+	return 0;
+}
+
+#ifdef __wasilibc_unmodified_upstream /* WASI has no CPU scheduling support. */
+int pthread_attr_getinheritsched(const pthread_attr_t *restrict a, int *restrict inherit)
+{
+	*inherit = a->_a_sched;
+	return 0;
+}
+
+int pthread_attr_getschedparam(const pthread_attr_t *restrict a, struct sched_param *restrict param)
+{
+	param->sched_priority = a->_a_prio;
+	return 0;
+}
+
+int pthread_attr_getschedpolicy(const pthread_attr_t *restrict a, int *restrict policy)
+{
+	*policy = a->_a_policy;
+	return 0;
+}
+
+int pthread_attr_getscope(const pthread_attr_t *restrict a, int *restrict scope)
+{
+	*scope = PTHREAD_SCOPE_SYSTEM;
+	return 0;
+}
+#else
+int pthread_attr_getschedparam(const pthread_attr_t *restrict a, struct sched_param *restrict param)
+{
+	param->sched_priority = 0;
+	return 0;
+}
+#endif
+
+int pthread_attr_getstack(const pthread_attr_t *restrict a, void **restrict addr, size_t *restrict size)
+{
+	if (!a->_a_stackaddr)
+		return EINVAL;
+	*size = a->_a_stacksize;
+	*addr = (void *)(a->_a_stackaddr - *size);
+	return 0;
+}
+
+int pthread_attr_getstacksize(const pthread_attr_t *restrict a, size_t *restrict size)
+{
+	*size = a->_a_stacksize;
+	return 0;
+}
+
+int pthread_barrierattr_getpshared(const pthread_barrierattr_t *restrict a, int *restrict pshared)
+{
+	*pshared = !!a->__attr;
+	return 0;
+}
+
+#ifdef __wasilibc_unmodified_upstream /* Forward declaration of WASI's `__clockid` type. */
+int pthread_condattr_getclock(const pthread_condattr_t *restrict a, clockid_t *restrict clk)
+{
+	*clk = a->__attr & 0x7fffffff;
+	return 0;
+}
+#else
+int pthread_condattr_getclock(const pthread_condattr_t *restrict a, clockid_t *restrict clk)
+{
+	if (a->__attr & 0x7fffffff == __WASI_CLOCKID_REALTIME)
+		*clk = CLOCK_REALTIME;
+	if (a->__attr & 0x7fffffff == __WASI_CLOCKID_MONOTONIC)
+		*clk = CLOCK_MONOTONIC;
+	return 0;
+}
+#endif
+
+int pthread_condattr_getpshared(const pthread_condattr_t *restrict a, int *restrict pshared)
+{
+	*pshared = a->__attr>>31;
+	return 0;
+}
+
+int pthread_mutexattr_getprotocol(const pthread_mutexattr_t *restrict a, int *restrict protocol)
+{
+	*protocol = a->__attr / 8U % 2;
+	return 0;
+}
+int pthread_mutexattr_getpshared(const pthread_mutexattr_t *restrict a, int *restrict pshared)
+{
+	*pshared = a->__attr / 128U % 2;
+	return 0;
+}
+
+int pthread_mutexattr_getrobust(const pthread_mutexattr_t *restrict a, int *restrict robust)
+{
+	*robust = a->__attr / 4U % 2;
+	return 0;
+}
+
+int pthread_mutexattr_gettype(const pthread_mutexattr_t *restrict a, int *restrict type)
+{
+	*type = a->__attr & 3;
+	return 0;
+}
+
+int pthread_rwlockattr_getpshared(const pthread_rwlockattr_t *restrict a, int *restrict pshared)
+{
+	*pshared = a->__attr[0];
+	return 0;
+}
lib/libc/wasi/libc-top-half/musl/src/thread/pthread_attr_setguardsize.c
@@ -0,0 +1,13 @@
+#include "pthread_impl.h"
+
+int pthread_attr_setguardsize(pthread_attr_t *a, size_t size)
+{
+#ifdef __wasilibc_unmodified_upstream
+	if (size > SIZE_MAX/8) return EINVAL;
+#else
+	/* WASI doesn't have memory protection required for stack guards. */
+	if (size > 0) return EINVAL;
+#endif
+	a->_a_guardsize = size;
+	return 0;
+}
lib/libc/wasi/libc-top-half/musl/src/thread/pthread_attr_setschedparam.c
@@ -0,0 +1,11 @@
+#include "pthread_impl.h"
+
+int pthread_attr_setschedparam(pthread_attr_t *restrict a, const struct sched_param *restrict param)
+{
+#ifdef __wasilibc_unmodified_upstream
+	a->_a_prio = param->sched_priority;
+#else
+	if (param->sched_priority != 0) return ENOTSUP;
+#endif
+	return 0;
+}
lib/libc/wasi/libc-top-half/musl/src/thread/pthread_cancel.c
@@ -0,0 +1,113 @@
+#define _GNU_SOURCE
+#include <string.h>
+#include "pthread_impl.h"
+#include "syscall.h"
+
+#ifdef __wasilibc_unmodified_upstream
+hidden long __cancel(), __syscall_cp_asm(), __syscall_cp_c();
+
+long __cancel()
+{
+	pthread_t self = __pthread_self();
+	if (self->canceldisable == PTHREAD_CANCEL_ENABLE || self->cancelasync)
+		pthread_exit(PTHREAD_CANCELED);
+	self->canceldisable = PTHREAD_CANCEL_DISABLE;
+	return -ECANCELED;
+}
+
+long __syscall_cp_asm(volatile void *, syscall_arg_t,
+                      syscall_arg_t, syscall_arg_t, syscall_arg_t,
+                      syscall_arg_t, syscall_arg_t, syscall_arg_t);
+
+long __syscall_cp_c(syscall_arg_t nr,
+                    syscall_arg_t u, syscall_arg_t v, syscall_arg_t w,
+                    syscall_arg_t x, syscall_arg_t y, syscall_arg_t z)
+{
+	pthread_t self;
+	long r;
+	int st;
+
+	if ((st=(self=__pthread_self())->canceldisable)
+	    && (st==PTHREAD_CANCEL_DISABLE || nr==SYS_close))
+		return __syscall(nr, u, v, w, x, y, z);
+
+	r = __syscall_cp_asm(&self->cancel, nr, u, v, w, x, y, z);
+	if (r==-EINTR && nr!=SYS_close && self->cancel &&
+	    self->canceldisable != PTHREAD_CANCEL_DISABLE)
+		r = __cancel();
+	return r;
+}
+
+static void _sigaddset(sigset_t *set, int sig)
+{
+	unsigned s = sig-1;
+	set->__bits[s/8/sizeof *set->__bits] |= 1UL<<(s&8*sizeof *set->__bits-1);
+}
+
+extern hidden const char __cp_begin[1], __cp_end[1], __cp_cancel[1];
+
+static void cancel_handler(int sig, siginfo_t *si, void *ctx)
+{
+	pthread_t self = __pthread_self();
+	ucontext_t *uc = ctx;
+	uintptr_t pc = uc->uc_mcontext.MC_PC;
+
+	a_barrier();
+	if (!self->cancel || self->canceldisable == PTHREAD_CANCEL_DISABLE) return;
+
+	_sigaddset(&uc->uc_sigmask, SIGCANCEL);
+
+	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;
+#endif
+		return;
+	}
+
+	__syscall(SYS_tkill, self->tid, SIGCANCEL);
+}
+
+void __testcancel()
+{
+	pthread_t self = __pthread_self();
+	if (self->cancel && !self->canceldisable)
+		__cancel();
+}
+
+static void init_cancellation()
+{
+	struct sigaction sa = {
+		.sa_flags = SA_SIGINFO | SA_RESTART | SA_ONSTACK,
+		.sa_sigaction = cancel_handler
+	};
+	memset(&sa.sa_mask, -1, _NSIG/8);
+	__libc_sigaction(SIGCANCEL, &sa, 0);
+}
+
+int pthread_cancel(pthread_t t)
+{
+	static int init;
+	if (!init) {
+		init_cancellation();
+		init = 1;
+	}
+	a_store(&t->cancel, 1);
+	if (t == pthread_self()) {
+		if (t->canceldisable == PTHREAD_CANCEL_ENABLE && t->cancelasync)
+			pthread_exit(PTHREAD_CANCELED);
+		return 0;
+	}
+	return pthread_kill(t, SIGCANCEL);
+}
+#else
+int pthread_cancel(pthread_t t)
+{
+	return ENOTSUP;
+}
+#endif
lib/libc/wasi/libc-top-half/musl/src/thread/pthread_condattr_setclock.c
@@ -0,0 +1,21 @@
+#include "pthread_impl.h"
+
+#ifndef __wasilibc_unmodified_upstream
+#include <common/clock.h>
+#endif
+
+int pthread_condattr_setclock(pthread_condattr_t *a, clockid_t clk)
+{
+#ifdef __wasilibc_unmodified_upstream
+	if (clk < 0 || clk-2U < 2) return EINVAL;
+#else
+	if (clk->id < 0 || clk->id-2U < 2) return EINVAL;
+#endif
+	a->__attr &= 0x80000000;
+#ifdef __wasilibc_unmodified_upstream
+	a->__attr |= clk;
+#else
+	a->__attr |= clk->id;
+#endif
+	return 0;
+}
lib/libc/wasi/libc-top-half/musl/src/thread/pthread_key_create.c
@@ -0,0 +1,105 @@
+#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 };
+
+static void (*keys[PTHREAD_KEYS_MAX])(void *);
+
+static pthread_rwlock_t key_lock = PTHREAD_RWLOCK_INITIALIZER;
+
+static pthread_key_t next_key;
+
+static void nodtor(void *dummy)
+{
+}
+
+static void dummy_0(void)
+{
+}
+
+weak_alias(dummy_0, __tl_lock);
+weak_alias(dummy_0, __tl_unlock);
+
+#ifdef __wasilibc_unmodified_upstream // WASI lacks fork
+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;
+}
+#endif
+
+int __pthread_key_create(pthread_key_t *k, void (*dtor)(void *))
+{
+	pthread_t self = __pthread_self();
+
+	/* This can only happen in the main thread before
+	 * pthread_create has been called. */
+	if (!self->tsd) self->tsd = __pthread_tsd_main;
+
+	/* Purely a sentinel value since null means slot is free. */
+	if (!dtor) dtor = nodtor;
+
+	__pthread_rwlock_wrlock(&key_lock);
+	pthread_key_t j = next_key;
+	do {
+		if (!keys[j]) {
+			keys[next_key = *k = j] = dtor;
+			__pthread_rwlock_unlock(&key_lock);
+			return 0;
+		}
+	} while ((j=(j+1)%PTHREAD_KEYS_MAX) != next_key);
+
+	__pthread_rwlock_unlock(&key_lock);
+	return EAGAIN;
+}
+
+int __pthread_key_delete(pthread_key_t k)
+{
+	sigset_t set;
+	pthread_t self = __pthread_self(), td=self;
+
+#ifdef __wasilibc_unmodified_upstream
+	__block_app_sigs(&set);
+#endif
+	__pthread_rwlock_wrlock(&key_lock);
+
+	__tl_lock();
+	do td->tsd[k] = 0;
+	while ((td=td->next)!=self);
+	__tl_unlock();
+
+	keys[k] = 0;
+
+	__pthread_rwlock_unlock(&key_lock);
+#ifdef __wasilibc_unmodified_upstream
+	__restore_sigs(&set);
+#endif
+
+	return 0;
+}
+
+void __pthread_tsd_run_dtors()
+{
+	pthread_t self = __pthread_self();
+	int i, j;
+	for (j=0; self->tsd_used && j<PTHREAD_DESTRUCTOR_ITERATIONS; j++) {
+		__pthread_rwlock_rdlock(&key_lock);
+		self->tsd_used = 0;
+		for (i=0; i<PTHREAD_KEYS_MAX; i++) {
+			void *val = self->tsd[i];
+			void (*dtor)(void *) = keys[i];
+			self->tsd[i] = 0;
+			if (val && dtor && dtor != nodtor) {
+				__pthread_rwlock_unlock(&key_lock);
+				dtor(val);
+				__pthread_rwlock_rdlock(&key_lock);
+			}
+		}
+		__pthread_rwlock_unlock(&key_lock);
+	}
+}
+
+weak_alias(__pthread_key_create, pthread_key_create);
+weak_alias(__pthread_key_delete, pthread_key_delete);
lib/libc/wasi/libc-top-half/musl/src/thread/pthread_mutex_destroy.c
@@ -0,0 +1,18 @@
+#include "pthread_impl.h"
+
+int pthread_mutex_destroy(pthread_mutex_t *mutex)
+{
+#ifdef __wasilibc_unmodified_upstream
+	/* If the mutex being destroyed is process-shared and has nontrivial
+	 * type (tracking ownership), it might be in the pending slot of a
+	 * robust_list; wait for quiescence. */
+	if (mutex->_m_type > 128) __vm_wait();
+#else
+	/* For now, wasi-libc chooses to avoid implementing robust mutex support
+	 * though this could be added later. The error code indicates that the
+	 * mutex was an invalid type, but it would be more accurate as 
+	 * "unimplemented". */
+	if (mutex->_m_type > 128) return EINVAL;
+#endif
+	return 0;
+}
lib/libc/wasi/libc-top-half/musl/src/thread/pthread_mutexattr_setprotocol.c
@@ -0,0 +1,32 @@
+#include "pthread_impl.h"
+#include "syscall.h"
+
+static volatile int check_pi_result = -1;
+
+int pthread_mutexattr_setprotocol(pthread_mutexattr_t *a, int protocol)
+{
+	int r;
+	switch (protocol) {
+	case PTHREAD_PRIO_NONE:
+		a->__attr &= ~8;
+		return 0;
+	case PTHREAD_PRIO_INHERIT:
+#ifdef __wasilibc_unmodified_upstream
+		r = check_pi_result;
+		if (r < 0) {
+			volatile int lk = 0;
+			r = -__syscall(SYS_futex, &lk, FUTEX_LOCK_PI, 0, 0);
+			a_store(&check_pi_result, r);
+		}
+		if (r) return r;
+		a->__attr |= 8;
+		return 0;
+#else
+		return ENOTSUP;
+#endif
+	case PTHREAD_PRIO_PROTECT:
+		return ENOTSUP;
+	default:
+		return EINVAL;
+	}
+}
lib/libc/wasi/libc-top-half/musl/src/thread/pthread_mutexattr_setrobust.c
@@ -0,0 +1,28 @@
+#include "pthread_impl.h"
+#include "syscall.h"
+
+static volatile int check_robust_result = -1;
+
+int pthread_mutexattr_setrobust(pthread_mutexattr_t *a, int robust)
+{
+#ifdef __wasilibc_unmodified_upstream
+	if (robust > 1U) return EINVAL;
+	if (robust) {
+		int r = check_robust_result;
+		if (r < 0) {
+			void *p;
+			size_t l;
+			r = -__syscall(SYS_get_robust_list, 0, &p, &l);
+			a_store(&check_robust_result, r);
+		}
+		if (r) return r;
+		a->__attr |= 4;
+		return 0;
+	}
+	a->__attr &= ~4;
+	return 0;
+#else
+	if (robust) return EINVAL;
+	return 0;
+#endif
+}
lib/libc/wasi/libc-top-half/musl/src/thread/pthread_self.c
@@ -0,0 +1,14 @@
+#include "pthread_impl.h"
+#include <threads.h>
+
+#if !defined(__wasilibc_unmodified_upstream) && defined(__wasm__)
+_Thread_local struct pthread __wasilibc_pthread_self;
+#endif
+
+static pthread_t __pthread_self_internal()
+{
+	return __pthread_self();
+}
+
+weak_alias(__pthread_self_internal, pthread_self);
+weak_alias(__pthread_self_internal, thrd_current);
lib/libc/wasi/libc-top-half/musl/src/time/__tz.c
@@ -434,10 +434,14 @@ weak_alias(__tzset, tzset);
 void __secs_to_zone(long long t, int local, int *isdst, int *offset, long *oppoff, const char **zonename)
 {
 	// Minimalist implementation for now.
-	*isdst = 0;
-	*offset = 0;
-	*oppoff = 0;
-	*zonename = __utc;
+	if (isdst)
+		*isdst = 0;
+	if (offset)
+		*offset = 0;
+	if (oppoff)
+		*oppoff = 0;
+	if (zonename)
+		*zonename = __utc;
 }
 #endif
 
lib/libc/wasi/libc-top-half/musl/src/time/strftime.c
@@ -3,6 +3,7 @@
 #include <string.h>
 #include <langinfo.h>
 #include <locale.h>
+#include <ctype.h>
 #include <time.h>
 #include <limits.h>
 #include "locale_impl.h"
@@ -237,7 +238,12 @@ size_t __strftime_l(char *restrict s, size_t n, const char *restrict f, const st
 		pad = 0;
 		if (*f == '-' || *f == '_' || *f == '0') pad = *f++;
 		if ((plus = (*f == '+'))) f++;
-		width = strtoul(f, &p, 10);
+		if (isdigit(*f)) {
+			width = strtoul(f, &p, 10);
+		} else {
+			width = 0;
+			p = (void *)f;
+		}
 		if (*p == 'C' || *p == 'F' || *p == 'G' || *p == 'Y') {
 			if (!width && p!=f) width = 1;
 		} else {
lib/libc/wasi/thread-stub/pthread_barrier_destroy.c
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_barrier_destroy(pthread_barrier_t *b)
+{
+	return 0;
+}
lib/libc/wasi/thread-stub/pthread_barrier_init.c
@@ -0,0 +1,8 @@
+#include "pthread_impl.h"
+
+int pthread_barrier_init(pthread_barrier_t *restrict b, const pthread_barrierattr_t *restrict a, unsigned count)
+{
+	if (count-1 > INT_MAX-1) return EINVAL;
+	*b = (pthread_barrier_t){ ._b_limit = count-1 };
+	return 0;
+}
lib/libc/wasi/thread-stub/pthread_barrier_wait.c
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+int pthread_barrier_wait(pthread_barrier_t *b)
+{
+	if (!b->_b_limit) return PTHREAD_BARRIER_SERIAL_THREAD;
+	__builtin_trap();
+}
lib/libc/wasi/thread-stub/pthread_cond_broadcast.c
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_cond_broadcast(pthread_cond_t *c)
+{
+	return 0;
+}
lib/libc/wasi/thread-stub/pthread_cond_destroy.c
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_cond_destroy(pthread_cond_t *c)
+{
+	return 0;
+}
lib/libc/wasi/thread-stub/pthread_cond_init.c
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_cond_init(pthread_cond_t *restrict c, const pthread_condattr_t *restrict a)
+{
+	return 0;
+}
lib/libc/wasi/thread-stub/pthread_cond_signal.c
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_cond_signal(pthread_cond_t *c)
+{
+	return 0;
+}
lib/libc/wasi/thread-stub/pthread_cond_timedwait.c
@@ -0,0 +1,13 @@
+#include "pthread_impl.h"
+
+int __pthread_cond_timedwait(pthread_cond_t *restrict c, pthread_mutex_t *restrict m, const struct timespec *restrict ts)
+{
+	/* Error check mutexes must detect if they're not locked (UB for others) */
+	if (!m->_m_count) return EPERM;
+	int ret = clock_nanosleep(CLOCK_REALTIME, TIMER_ABSTIME, ts, 0);
+	if (ret == 0) return ETIMEDOUT;
+	if (ret != EINTR) return ret;
+	return 0;
+}
+
+weak_alias(__pthread_cond_timedwait, pthread_cond_timedwait);
lib/libc/wasi/thread-stub/pthread_cond_wait.c
@@ -0,0 +1,9 @@
+#include "pthread_impl.h"
+
+int pthread_cond_wait(pthread_cond_t *restrict c, pthread_mutex_t *restrict m)
+{
+	/* Because there is no other thread that can signal us, this is a deadlock immediately.
+	The other possible choice is to return immediately (spurious wakeup), but that is likely to
+	just result in the program spinning forever on a condition that cannot become true. */
+	__builtin_trap();
+}
lib/libc/wasi/thread-stub/pthread_create.c
@@ -0,0 +1,19 @@
+#include "pthread_impl.h"
+
+static void dummy_0()
+{
+}
+weak_alias(dummy_0, __acquire_ptc);
+weak_alias(dummy_0, __release_ptc);
+
+int __pthread_create(pthread_t *restrict res, const pthread_attr_t *restrict attrp, void *(*entry)(void *), void *restrict arg)
+{
+	/*
+		"The system lacked the necessary resources to create another thread,
+		or the system-imposed limit on the total number of threads in a process
+		{PTHREAD_THREADS_MAX} would be exceeded."
+	*/
+	return EAGAIN;
+}
+
+weak_alias(__pthread_create, pthread_create);
lib/libc/wasi/thread-stub/pthread_detach.c
@@ -0,0 +1,13 @@
+#include "pthread_impl.h"
+
+static int __pthread_detach(pthread_t t)
+{
+	/*
+		If we are the only thread, when we exit the whole process exits.
+		So the storage will be reclaimed no matter what.
+	*/
+	return 0;
+}
+
+weak_alias(__pthread_detach, pthread_detach);
+weak_alias(__pthread_detach, thrd_detach);
lib/libc/wasi/thread-stub/pthread_getattr_np.c
@@ -0,0 +1,11 @@
+#include "pthread_impl.h"
+
+int pthread_getattr_np(pthread_t t, pthread_attr_t *a)
+{
+	*a = (pthread_attr_t){0};
+	/* Can't join main thread. */
+	a->_a_detach = PTHREAD_CREATE_DETACHED;
+	/* WASI doesn't have memory protection required for stack guards. */
+	a->_a_guardsize = 0;
+	return 0;
+}
lib/libc/wasi/thread-stub/pthread_join.c
@@ -0,0 +1,32 @@
+#include "pthread_impl.h"
+
+static int __pthread_tryjoin_np(pthread_t t, void **res)
+{
+	/*
+		"The behavior is undefined if the value specified by the thread argument
+		to pthread_join() refers to the calling thread."
+	*/
+	return 0;
+}
+
+static int __pthread_timedjoin_np(pthread_t t, void **res, const struct timespec *at)
+{
+	/*
+		"The behavior is undefined if the value specified by the thread argument
+		to pthread_join() refers to the calling thread."
+	*/
+	return 0;
+}
+
+int __pthread_join(pthread_t t, void **res)
+{
+	/*
+		"The behavior is undefined if the value specified by the thread argument
+		to pthread_join() refers to the calling thread."
+	*/
+	return 0;
+}
+
+weak_alias(__pthread_tryjoin_np, pthread_tryjoin_np);
+weak_alias(__pthread_timedjoin_np, pthread_timedjoin_np);
+weak_alias(__pthread_join, pthread_join);
lib/libc/wasi/thread-stub/pthread_mutex_consistent.c
@@ -0,0 +1,8 @@
+#include "pthread_impl.h"
+
+int pthread_mutex_consistent(pthread_mutex_t *m)
+{
+	/* cannot be a robust mutex, as they're entirely unsupported in WASI */
+	return EINVAL;
+
+}
lib/libc/wasi/thread-stub/pthread_mutex_getprioceiling.c
@@ -0,0 +1,6 @@
+#include "pthread_impl.h"
+
+int pthread_mutex_getprioceiling(const pthread_mutex_t *restrict m, int *restrict ceiling)
+{
+	return EINVAL;
+}
lib/libc/wasi/thread-stub/pthread_mutex_lock.c
@@ -0,0 +1,21 @@
+#include "pthread_impl.h"
+
+int __pthread_mutex_lock(pthread_mutex_t *m)
+{
+	/*
+		_m_type[1:0] 	- type
+		0 - normal
+		1 - recursive
+		2 - errorcheck
+	*/
+	if (m->_m_type&3 != PTHREAD_MUTEX_RECURSIVE) {
+		if (m->_m_count) return EDEADLK;
+		m->_m_count = 1;
+	} else {
+		if ((unsigned)m->_m_count >= INT_MAX) return EAGAIN;
+		m->_m_count++;
+	}
+	return 0;
+}
+
+weak_alias(__pthread_mutex_lock, pthread_mutex_lock);
lib/libc/wasi/thread-stub/pthread_mutex_timedlock.c
@@ -0,0 +1,10 @@
+#include "pthread_impl.h"
+
+int __pthread_mutex_timedlock(pthread_mutex_t *restrict m, const struct timespec *restrict at)
+{
+	/* "The pthread_mutex_timedlock() function may fail if: A deadlock condition was detected." */
+	/* This means that we don't have to wait and then return timeout, we can just detect deadlock. */
+	return pthread_mutex_lock(m);
+}
+
+weak_alias(__pthread_mutex_timedlock, pthread_mutex_timedlock);
lib/libc/wasi/thread-stub/pthread_mutex_trylock.c
@@ -0,0 +1,21 @@
+#include "pthread_impl.h"
+
+int __pthread_mutex_trylock(pthread_mutex_t *m)
+{
+	/*
+		_m_type[1:0] 	- type
+		0 - normal
+		1 - recursive
+		2 - errorcheck
+	*/
+	if (m->_m_type&3 != PTHREAD_MUTEX_RECURSIVE) {
+		if (m->_m_count) return EBUSY;
+		m->_m_count = 1;
+	} else {
+		if ((unsigned)m->_m_count >= INT_MAX) return EAGAIN;
+		m->_m_count++;
+	}
+	return 0;
+}
+
+weak_alias(__pthread_mutex_trylock, pthread_mutex_trylock);
lib/libc/wasi/thread-stub/pthread_mutex_unlock.c
@@ -0,0 +1,10 @@
+#include "pthread_impl.h"
+
+int __pthread_mutex_unlock(pthread_mutex_t *m)
+{
+	if (!m->_m_count) return EPERM;
+	m->_m_count--;
+	return 0;
+}
+
+weak_alias(__pthread_mutex_unlock, pthread_mutex_unlock);
lib/libc/wasi/thread-stub/pthread_once.c
@@ -0,0 +1,12 @@
+#include "pthread_impl.h"
+
+int __pthread_once(pthread_once_t *control, void (*init)(void))
+{
+       if (!*control) {
+               init();
+               *control = 1;
+       }
+       return 0;
+}
+
+weak_alias(__pthread_once, pthread_once);
lib/libc/wasi/thread-stub/pthread_rwlock_rdlock.c
@@ -0,0 +1,11 @@
+#include "pthread_impl.h"
+
+int __pthread_rwlock_rdlock(pthread_rwlock_t *rw)
+{
+	if (rw->_rw_lock == 0x7fffffff) return EDEADLK;
+	if (rw->_rw_lock == 0x7ffffffe) return EAGAIN;
+	rw->_rw_lock++;
+	return 0;
+}
+
+weak_alias(__pthread_rwlock_rdlock, pthread_rwlock_rdlock);
lib/libc/wasi/thread-stub/pthread_rwlock_timedrdlock.c
@@ -0,0 +1,8 @@
+#include "pthread_impl.h"
+
+int __pthread_rwlock_timedrdlock(pthread_rwlock_t *restrict rw, const struct timespec *restrict at)
+{
+	return pthread_rwlock_rdlock(rw);
+}
+
+weak_alias(__pthread_rwlock_timedrdlock, pthread_rwlock_timedrdlock);
lib/libc/wasi/thread-stub/pthread_rwlock_timedwrlock.c
@@ -0,0 +1,8 @@
+#include "pthread_impl.h"
+
+int __pthread_rwlock_timedwrlock(pthread_rwlock_t *restrict rw, const struct timespec *restrict at)
+{
+	return pthread_rwlock_wrlock(rw);
+}
+
+weak_alias(__pthread_rwlock_timedwrlock, pthread_rwlock_timedwrlock);
lib/libc/wasi/thread-stub/pthread_rwlock_tryrdlock.c
@@ -0,0 +1,11 @@
+#include "pthread_impl.h"
+
+int __pthread_rwlock_tryrdlock(pthread_rwlock_t *rw)
+{
+	if (rw->_rw_lock == 0x7fffffff) return EBUSY;
+	if (rw->_rw_lock == 0x7ffffffe) return EAGAIN;
+	rw->_rw_lock++;
+	return 0;
+}
+
+weak_alias(__pthread_rwlock_tryrdlock, pthread_rwlock_tryrdlock);
lib/libc/wasi/thread-stub/pthread_rwlock_trywrlock.c
@@ -0,0 +1,10 @@
+#include "pthread_impl.h"
+
+int __pthread_rwlock_trywrlock(pthread_rwlock_t *rw)
+{
+	if (rw->_rw_lock) return EBUSY;
+	rw->_rw_lock = 0x7fffffff;
+	return 0;
+}
+
+weak_alias(__pthread_rwlock_trywrlock, pthread_rwlock_trywrlock);
lib/libc/wasi/thread-stub/pthread_rwlock_unlock.c
@@ -0,0 +1,12 @@
+#include "pthread_impl.h"
+
+int __pthread_rwlock_unlock(pthread_rwlock_t *rw)
+{
+	if (rw->_rw_lock == 0x7fffffff)
+		rw->_rw_lock = 0;
+	else
+		rw->_rw_lock--;
+	return 0;
+}
+
+weak_alias(__pthread_rwlock_unlock, pthread_rwlock_unlock);
lib/libc/wasi/thread-stub/pthread_rwlock_wrlock.c
@@ -0,0 +1,10 @@
+#include "pthread_impl.h"
+
+int __pthread_rwlock_wrlock(pthread_rwlock_t *rw)
+{
+	if (rw->_rw_lock) return EDEADLK;
+	rw->_rw_lock = 0x7fffffff;
+	return 0;
+}
+
+weak_alias(__pthread_rwlock_wrlock, pthread_rwlock_wrlock);
lib/libc/wasi/thread-stub/pthread_spin_lock.c
@@ -0,0 +1,8 @@
+#include "pthread_impl.h"
+
+int pthread_spin_lock(pthread_spinlock_t *s)
+{
+	if (*s) return EDEADLK;
+	*s = 1;
+	return 0;
+}
lib/libc/wasi/thread-stub/pthread_spin_trylock.c
@@ -0,0 +1,8 @@
+#include "pthread_impl.h"
+
+int pthread_spin_trylock(pthread_spinlock_t *s)
+{
+	if (*s) return EBUSY;
+	*s = 1;
+	return 0;
+}
lib/libc/wasi/thread-stub/pthread_spin_unlock.c
@@ -0,0 +1,7 @@
+#include "pthread_impl.h"
+
+int pthread_spin_unlock(pthread_spinlock_t *s)
+{
+	*s = 0;
+	return 0;
+}
lib/std/zig/target.zig
@@ -361,6 +361,8 @@ pub fn isLibCLibName(target: *const std.Target, name: []const u8) bool {
             return true;
 
         if (target.os.tag == .wasi) {
+            if (eqlIgnoreCase(ignore_case, name, "setjmp"))
+                return true;
             if (eqlIgnoreCase(ignore_case, name, "wasi-emulated-getpid"))
                 return true;
             if (eqlIgnoreCase(ignore_case, name, "wasi-emulated-mman"))
lib/std/start.zig
@@ -57,7 +57,7 @@ comptime {
         } else if (builtin.output_mode == .Exe or @hasDecl(root, "main")) {
             if (builtin.link_libc and @hasDecl(root, "main")) {
                 if (native_arch.isWasm()) {
-                    @export(&mainWithoutEnv, .{ .name = "main" });
+                    @export(&mainWithoutEnv, .{ .name = "__main_argc_argv" });
                 } else if (!@typeInfo(@TypeOf(root.main)).@"fn".calling_convention.eql(.c)) {
                     @export(&main, .{ .name = "main" });
                 }
src/libs/wasi_libc.zig
@@ -44,6 +44,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
             var args = std.array_list.Managed([]const u8).init(arena);
             try addCCArgs(comp, arena, &args, .{});
             try addLibcBottomHalfIncludes(comp, arena, &args);
+
             var files = [_]Compilation.CSourceFile{
                 .{
                     .src_path = try comp.dirs.zig_lib.join(arena, &.{
@@ -53,12 +54,14 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
                     .owner = undefined,
                 },
             };
+
             return comp.build_crt_file("crt1-reactor", .Obj, .@"wasi crt1-reactor.o", prog_node, &files, .{});
         },
         .crt1_command_o => {
             var args = std.array_list.Managed([]const u8).init(arena);
             try addCCArgs(comp, arena, &args, .{});
             try addLibcBottomHalfIncludes(comp, arena, &args);
+
             var files = [_]Compilation.CSourceFile{
                 .{
                     .src_path = try comp.dirs.zig_lib.join(arena, &.{
@@ -68,6 +71,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
                     .owner = undefined,
                 },
             };
+
             return comp.build_crt_file("crt1-command", .Obj, .@"wasi crt1-command.o", prog_node, &files, .{});
         },
         .libc_a => {
@@ -77,6 +81,7 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
                 // Compile emmalloc.
                 var args = std.array_list.Managed([]const u8).init(arena);
                 try addCCArgs(comp, arena, &args, .{ .want_O3 = true, .no_strict_aliasing = true });
+
                 for (emmalloc_src_files) |file_path| {
                     try libc_sources.append(.{
                         .src_path = try comp.dirs.zig_lib.join(arena, &.{
@@ -122,11 +127,52 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
                 }
             }
 
+            {
+                // Compile musl-fts.
+                var args = std.array_list.Managed([]const u8).init(arena);
+                try addCCArgs(comp, arena, &args, .{ .want_O3 = true });
+                try args.appendSlice(&[_][]const u8{
+                    "-I",
+                    try comp.dirs.zig_lib.join(arena, &.{
+                        "libc",
+                        "wasi",
+                        "fts",
+                    }),
+                });
+
+                for (fts_src_files) |file_path| {
+                    try libc_sources.append(.{
+                        .src_path = try comp.dirs.zig_lib.join(arena, &.{
+                            "libc", try sanitize(arena, file_path),
+                        }),
+                        .extra_flags = args.items,
+                        .owner = undefined,
+                    });
+                }
+            }
+
+            if (comp.getTarget().cpu.has(.wasm, .exception_handling)) {
+                // Compile libsetjmp.
+                var args = std.array_list.Managed([]const u8).init(arena);
+                try addCCArgs(comp, arena, &args, .{ .want_O3 = true });
+                try addLibcTopHalfIncludes(comp, arena, &args);
+
+                for (setjmp_src_files) |file_path| {
+                    try libc_sources.append(.{
+                        .src_path = try comp.dirs.zig_lib.join(arena, &.{
+                            "libc", try sanitize(arena, file_path),
+                        }),
+                        .extra_flags = args.items,
+                        .owner = undefined,
+                    });
+                }
+            }
+
             {
                 // Compile libdl.
                 var args = std.array_list.Managed([]const u8).init(arena);
                 try addCCArgs(comp, arena, &args, .{ .want_O3 = true });
-                try addLibcBottomHalfIncludes(comp, arena, &args);
+                try addLibcTopHalfIncludes(comp, arena, &args);
 
                 for (emulated_dl_src_files) |file_path| {
                     try libc_sources.append(.{
@@ -143,16 +189,6 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
                 // Compile libwasi-emulated-process-clocks.
                 var args = std.array_list.Managed([]const u8).init(arena);
                 try addCCArgs(comp, arena, &args, .{ .want_O3 = true });
-                try args.appendSlice(&.{
-                    "-I",
-                    try comp.dirs.zig_lib.join(arena, &.{
-                        "libc",
-                        "wasi",
-                        "libc-bottom-half",
-                        "cloudlibc",
-                        "src",
-                    }),
-                });
 
                 for (emulated_process_clocks_src_files) |file_path| {
                     try libc_sources.append(.{
@@ -169,7 +205,6 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
                 // Compile libwasi-emulated-getpid.
                 var args = std.array_list.Managed([]const u8).init(arena);
                 try addCCArgs(comp, arena, &args, .{ .want_O3 = true });
-                try addLibcBottomHalfIncludes(comp, arena, &args);
 
                 for (emulated_getpid_src_files) |file_path| {
                     try libc_sources.append(.{
@@ -186,7 +221,6 @@ pub fn buildCrtFile(comp: *Compilation, crt_file: CrtFile, prog_node: std.Progre
                 // Compile libwasi-emulated-mman.
                 var args = std.array_list.Managed([]const u8).init(arena);
                 try addCCArgs(comp, arena, &args, .{ .want_O3 = true });
-                try addLibcBottomHalfIncludes(comp, arena, &args);
 
                 for (emulated_mman_src_files) |file_path| {
                     try libc_sources.append(.{
@@ -278,13 +312,18 @@ fn addCCArgs(
         "-mthread-model",
         "single",
 
-        "-isysroot",
-        "/",
+        "-I",
+        try comp.dirs.zig_lib.join(arena, &.{
+            "libc",
+            "wasi",
+            "libc-bottom-half",
+            "cloudlibc",
+            "src",
+        }),
 
-        "-iwithsysroot",
+        "-isystem",
         try comp.dirs.zig_lib.join(arena, &.{ "libc", "include", triple }),
-
-        "-iwithsysroot",
+        "-isystem",
         try comp.dirs.zig_lib.join(arena, &.{ "libc", "include", "generic-musl" }),
 
         "-DBULK_MEMORY_THRESHOLD=32",
@@ -338,7 +377,6 @@ fn addLibcBottomHalfIncludes(
             "src",
             "include",
         }),
-
         "-I",
         try comp.dirs.zig_lib.join(arena, &.{
             "libc",
@@ -346,8 +384,8 @@ fn addLibcBottomHalfIncludes(
             "src",
             "include",
         }),
-
         "-I",
+
         try comp.dirs.zig_lib.join(arena, &.{
             "libc",
             "wasi",
@@ -356,7 +394,6 @@ fn addLibcBottomHalfIncludes(
             "src",
             "internal",
         }),
-
         "-I",
         try comp.dirs.zig_lib.join(arena, &.{
             "libc",
@@ -382,7 +419,6 @@ fn addLibcTopHalfIncludes(
             "src",
             "include",
         }),
-
         "-I",
         try comp.dirs.zig_lib.join(arena, &.{
             "libc",
@@ -400,7 +436,6 @@ fn addLibcTopHalfIncludes(
             "src",
             "internal",
         }),
-
         "-I",
         try comp.dirs.zig_lib.join(arena, &.{
             "libc",
@@ -418,7 +453,6 @@ fn addLibcTopHalfIncludes(
             "arch",
             "wasm32",
         }),
-
         "-I",
         try comp.dirs.zig_lib.join(arena, &.{
             "libc",
@@ -469,8 +503,8 @@ const libc_bottom_half_src_files = [_][]const u8{
     "wasi/libc-bottom-half/cloudlibc/src/libc/sys/socket/recv.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/sys/socket/send.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/sys/socket/shutdown.c",
-    "wasi/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstat.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstatat.c",
+    "wasi/libc-bottom-half/cloudlibc/src/libc/sys/stat/fstat.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/sys/stat/futimens.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/sys/stat/mkdirat.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/sys/stat/utimensat.c",
@@ -479,11 +513,11 @@ const libc_bottom_half_src_files = [_][]const u8{
     "wasi/libc-bottom-half/cloudlibc/src/libc/sys/uio/pwritev.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/sys/uio/readv.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/sys/uio/writev.c",
-    "wasi/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_MONOTONIC.c",
-    "wasi/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_REALTIME.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/time/clock_getres.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/time/clock_gettime.c",
+    "wasi/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_MONOTONIC.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/time/clock_nanosleep.c",
+    "wasi/libc-bottom-half/cloudlibc/src/libc/time/CLOCK_REALTIME.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/time/nanosleep.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/time/time.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/unistd/faccessat.c",
@@ -501,25 +535,18 @@ const libc_bottom_half_src_files = [_][]const u8{
     "wasi/libc-bottom-half/cloudlibc/src/libc/unistd/unlinkat.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/unistd/usleep.c",
     "wasi/libc-bottom-half/cloudlibc/src/libc/unistd/write.c",
-    "wasi/libc-bottom-half/sources/__errno_location.c",
-    "wasi/libc-bottom-half/sources/__main_void.c",
-    "wasi/libc-bottom-half/sources/__wasilibc_dt.c",
-    "wasi/libc-bottom-half/sources/__wasilibc_environ.c",
-    "wasi/libc-bottom-half/sources/__wasilibc_fd_renumber.c",
-    "wasi/libc-bottom-half/sources/__wasilibc_initialize_environ.c",
-    "wasi/libc-bottom-half/sources/__wasilibc_real.c",
-    "wasi/libc-bottom-half/sources/__wasilibc_rmdirat.c",
-    "wasi/libc-bottom-half/sources/__wasilibc_tell.c",
-    "wasi/libc-bottom-half/sources/__wasilibc_unlinkat.c",
     "wasi/libc-bottom-half/sources/abort.c",
     "wasi/libc-bottom-half/sources/accept-wasip1.c",
     "wasi/libc-bottom-half/sources/at_fdcwd.c",
+    "wasi/libc-bottom-half/sources/chdir.c",
     "wasi/libc-bottom-half/sources/complex-builtins.c",
     "wasi/libc-bottom-half/sources/environ.c",
     "wasi/libc-bottom-half/sources/errno.c",
+    "wasi/libc-bottom-half/sources/__errno_location.c",
     "wasi/libc-bottom-half/sources/getcwd.c",
     "wasi/libc-bottom-half/sources/getentropy.c",
     "wasi/libc-bottom-half/sources/isatty.c",
+    "wasi/libc-bottom-half/sources/__main_void.c",
     "wasi/libc-bottom-half/sources/math/fmin-fmax.c",
     "wasi/libc-bottom-half/sources/math/math-builtins.c",
     "wasi/libc-bottom-half/sources/posix.c",
@@ -527,7 +554,15 @@ const libc_bottom_half_src_files = [_][]const u8{
     "wasi/libc-bottom-half/sources/reallocarray.c",
     "wasi/libc-bottom-half/sources/sbrk.c",
     "wasi/libc-bottom-half/sources/truncate.c",
-    "wasi/libc-bottom-half/sources/chdir.c",
+    "wasi/libc-bottom-half/sources/__wasilibc_dt.c",
+    "wasi/libc-bottom-half/sources/__wasilibc_environ.c",
+    "wasi/libc-bottom-half/sources/__wasilibc_fd_renumber.c",
+    "wasi/libc-bottom-half/sources/__wasilibc_initialize_environ.c",
+    "wasi/libc-bottom-half/sources/__wasilibc_random.c",
+    "wasi/libc-bottom-half/sources/__wasilibc_real.c",
+    "wasi/libc-bottom-half/sources/__wasilibc_rmdirat.c",
+    "wasi/libc-bottom-half/sources/__wasilibc_tell.c",
+    "wasi/libc-bottom-half/sources/__wasilibc_unlinkat.c",
 };
 
 const libc_top_half_src_files = [_][]const u8{
@@ -593,6 +628,7 @@ const libc_top_half_src_files = [_][]const u8{
     "musl/src/complex/ctanhf.c",
     "musl/src/complex/ctanhl.c",
     "musl/src/complex/ctanl.c",
+    "musl/src/conf/confstr.c",
     "musl/src/conf/legacy.c",
     "musl/src/conf/pathconf.c",
     "musl/src/crypt/crypt_blowfish.c",
@@ -971,8 +1007,10 @@ const libc_top_half_src_files = [_][]const u8{
     "musl/src/stdio/__toread.c",
     "musl/src/stdio/__towrite.c",
     "musl/src/stdio/__uflow.c",
+    "musl/src/stdio/ungetc.c",
     "musl/src/stdio/ungetwc.c",
     "musl/src/stdio/vasprintf.c",
+    "musl/src/stdio/vfwscanf.c",
     "musl/src/stdio/vprintf.c",
     "musl/src/stdio/vscanf.c",
     "musl/src/stdio/vsprintf.c",
@@ -994,23 +1032,20 @@ const libc_top_half_src_files = [_][]const u8{
     "musl/src/stdlib/lldiv.c",
     "musl/src/stdlib/qsort.c",
     "musl/src/stdlib/qsort_nr.c",
+    "musl/src/stdlib/strtol.c",
     "musl/src/string/bcmp.c",
     "musl/src/string/bcopy.c",
     "musl/src/string/explicit_bzero.c",
     "musl/src/string/index.c",
     "musl/src/string/memccpy.c",
-    "musl/src/string/memchr.c",
-    "musl/src/string/memcmp.c",
     "musl/src/string/memmem.c",
     "musl/src/string/mempcpy.c",
-    "musl/src/string/memrchr.c",
     "musl/src/string/rindex.c",
     "musl/src/string/stpcpy.c",
     "musl/src/string/stpncpy.c",
     "musl/src/string/strcasestr.c",
     "musl/src/string/strcat.c",
     "musl/src/string/strchr.c",
-    "musl/src/string/strchrnul.c",
     "musl/src/string/strcpy.c",
     "musl/src/string/strcspn.c",
     "musl/src/string/strdup.c",
@@ -1058,6 +1093,37 @@ const libc_top_half_src_files = [_][]const u8{
     "musl/src/string/wmemcpy.c",
     "musl/src/string/wmemmove.c",
     "musl/src/string/wmemset.c",
+    "musl/src/thread/default_attr.c",
+    "musl/src/thread/pthread_attr_destroy.c",
+    "musl/src/thread/pthread_attr_init.c",
+    "musl/src/thread/pthread_attr_setdetachstate.c",
+    "musl/src/thread/pthread_attr_setstack.c",
+    "musl/src/thread/pthread_attr_setstacksize.c",
+    "musl/src/thread/pthread_barrierattr_destroy.c",
+    "musl/src/thread/pthread_barrierattr_init.c",
+    "musl/src/thread/pthread_barrierattr_setpshared.c",
+    "musl/src/thread/pthread_cleanup_push.c",
+    "musl/src/thread/pthread_condattr_destroy.c",
+    "musl/src/thread/pthread_condattr_init.c",
+    "musl/src/thread/pthread_condattr_setpshared.c",
+    "musl/src/thread/pthread_equal.c",
+    "musl/src/thread/pthread_getspecific.c",
+    "musl/src/thread/pthread_mutexattr_destroy.c",
+    "musl/src/thread/pthread_mutexattr_init.c",
+    "musl/src/thread/pthread_mutexattr_setpshared.c",
+    "musl/src/thread/pthread_mutexattr_settype.c",
+    "musl/src/thread/pthread_mutex_init.c",
+    "musl/src/thread/pthread_rwlockattr_destroy.c",
+    "musl/src/thread/pthread_rwlockattr_init.c",
+    "musl/src/thread/pthread_rwlockattr_setpshared.c",
+    "musl/src/thread/pthread_rwlock_destroy.c",
+    "musl/src/thread/pthread_rwlock_init.c",
+    "musl/src/thread/pthread_setcancelstate.c",
+    "musl/src/thread/pthread_setcanceltype.c",
+    "musl/src/thread/pthread_setspecific.c",
+    "musl/src/thread/pthread_spin_destroy.c",
+    "musl/src/thread/pthread_spin_init.c",
+    "musl/src/thread/pthread_testcancel.c",
     "musl/src/thread/thrd_sleep.c",
     "musl/src/time/asctime.c",
     "musl/src/time/asctime_r.c",
@@ -1071,7 +1137,6 @@ const libc_top_half_src_files = [_][]const u8{
     "musl/src/time/__year_to_secs.c",
     "musl/src/unistd/posix_close.c",
 
-    "wasi/libc-top-half/musl/src/conf/confstr.c",
     "wasi/libc-top-half/musl/src/conf/fpathconf.c",
     "wasi/libc-top-half/musl/src/conf/sysconf.c",
     "wasi/libc-top-half/musl/src/dirent/alphasort.c",
@@ -1112,9 +1177,9 @@ const libc_top_half_src_files = [_][]const u8{
     "wasi/libc-top-half/musl/src/misc/nftw.c",
     "wasi/libc-top-half/musl/src/misc/uname.c",
     "wasi/libc-top-half/musl/src/prng/random.c",
+    "wasi/libc-top-half/musl/src/regex/glob.c",
     "wasi/libc-top-half/musl/src/regex/regcomp.c",
     "wasi/libc-top-half/musl/src/regex/regexec.c",
-    "wasi/libc-top-half/musl/src/regex/glob.c",
     "wasi/libc-top-half/musl/src/regex/tre-mem.c",
     "wasi/libc-top-half/musl/src/stat/futimesat.c",
     "wasi/libc-top-half/musl/src/stdio/__fdopen.c",
@@ -1144,21 +1209,32 @@ const libc_top_half_src_files = [_][]const u8{
     "wasi/libc-top-half/musl/src/stdio/__stdio_write.c",
     "wasi/libc-top-half/musl/src/stdio/stdout.c",
     "wasi/libc-top-half/musl/src/stdio/__stdout_write.c",
-    "wasi/libc-top-half/musl/src/stdio/ungetc.c",
     "wasi/libc-top-half/musl/src/stdio/vdprintf.c",
     "wasi/libc-top-half/musl/src/stdio/vfprintf.c",
     "wasi/libc-top-half/musl/src/stdio/vfscanf.c",
     "wasi/libc-top-half/musl/src/stdio/vfwprintf.c",
-    "wasi/libc-top-half/musl/src/stdio/vfwscanf.c",
     "wasi/libc-top-half/musl/src/stdio/vsnprintf.c",
     "wasi/libc-top-half/musl/src/stdio/vsscanf.c",
     "wasi/libc-top-half/musl/src/stdio/vswprintf.c",
     "wasi/libc-top-half/musl/src/stdio/vswscanf.c",
     "wasi/libc-top-half/musl/src/stdlib/strtod.c",
-    "wasi/libc-top-half/musl/src/stdlib/strtol.c",
     "wasi/libc-top-half/musl/src/stdlib/wcstod.c",
     "wasi/libc-top-half/musl/src/stdlib/wcstol.c",
+    "wasi/libc-top-half/musl/src/string/memchr.c",
+    "wasi/libc-top-half/musl/src/string/memcmp.c",
+    "wasi/libc-top-half/musl/src/string/memrchr.c",
     "wasi/libc-top-half/musl/src/string/memset.c",
+    "wasi/libc-top-half/musl/src/string/strchrnul.c",
+    "wasi/libc-top-half/musl/src/thread/pthread_attr_get.c",
+    "wasi/libc-top-half/musl/src/thread/pthread_attr_setguardsize.c",
+    "wasi/libc-top-half/musl/src/thread/pthread_attr_setschedparam.c",
+    "wasi/libc-top-half/musl/src/thread/pthread_cancel.c",
+    "wasi/libc-top-half/musl/src/thread/pthread_condattr_setclock.c",
+    "wasi/libc-top-half/musl/src/thread/pthread_key_create.c",
+    "wasi/libc-top-half/musl/src/thread/pthread_mutexattr_setprotocol.c",
+    "wasi/libc-top-half/musl/src/thread/pthread_mutexattr_setrobust.c",
+    "wasi/libc-top-half/musl/src/thread/pthread_mutex_destroy.c",
+    "wasi/libc-top-half/musl/src/thread/pthread_self.c",
     "wasi/libc-top-half/musl/src/time/getdate.c",
     "wasi/libc-top-half/musl/src/time/gmtime.c",
     "wasi/libc-top-half/musl/src/time/gmtime_r.c",
@@ -1173,11 +1249,50 @@ const libc_top_half_src_files = [_][]const u8{
     "wasi/libc-top-half/musl/src/time/wcsftime.c",
 
     "wasi/libc-top-half/sources/arc4random.c",
+
+    "wasi/thread-stub/pthread_barrier_destroy.c",
+    "wasi/thread-stub/pthread_barrier_init.c",
+    "wasi/thread-stub/pthread_barrier_wait.c",
+    "wasi/thread-stub/pthread_cond_broadcast.c",
+    "wasi/thread-stub/pthread_cond_destroy.c",
+    "wasi/thread-stub/pthread_cond_init.c",
+    "wasi/thread-stub/pthread_cond_signal.c",
+    "wasi/thread-stub/pthread_cond_timedwait.c",
+    "wasi/thread-stub/pthread_cond_wait.c",
+    "wasi/thread-stub/pthread_create.c",
+    "wasi/thread-stub/pthread_detach.c",
+    "wasi/thread-stub/pthread_getattr_np.c",
+    "wasi/thread-stub/pthread_join.c",
+    "wasi/thread-stub/pthread_mutex_consistent.c",
+    "wasi/thread-stub/pthread_mutex_getprioceiling.c",
+    "wasi/thread-stub/pthread_mutex_lock.c",
+    "wasi/thread-stub/pthread_mutex_timedlock.c",
+    "wasi/thread-stub/pthread_mutex_trylock.c",
+    "wasi/thread-stub/pthread_mutex_unlock.c",
+    "wasi/thread-stub/pthread_once.c",
+    "wasi/thread-stub/pthread_rwlock_rdlock.c",
+    "wasi/thread-stub/pthread_rwlock_timedrdlock.c",
+    "wasi/thread-stub/pthread_rwlock_timedwrlock.c",
+    "wasi/thread-stub/pthread_rwlock_tryrdlock.c",
+    "wasi/thread-stub/pthread_rwlock_trywrlock.c",
+    "wasi/thread-stub/pthread_rwlock_unlock.c",
+    "wasi/thread-stub/pthread_rwlock_wrlock.c",
+    "wasi/thread-stub/pthread_spin_lock.c",
+    "wasi/thread-stub/pthread_spin_trylock.c",
+    "wasi/thread-stub/pthread_spin_unlock.c",
 };
 
 const crt1_command_src_file = "wasi/libc-bottom-half/crt/crt1-command.c";
 const crt1_reactor_src_file = "wasi/libc-bottom-half/crt/crt1-reactor.c";
 
+const fts_src_files = &[_][]const u8{
+    "wasi/fts/musl-fts/fts.c",
+};
+
+const setjmp_src_files = &[_][]const u8{
+    "wasi/libc-top-half/musl/src/setjmp/wasm32/rt.c",
+};
+
 const emulated_dl_src_files = &[_][]const u8{
     "wasi/libc-top-half/musl/src/misc/dl.c",
 };
src/Compilation.zig
@@ -1426,11 +1426,6 @@ pub const MiscTask = enum {
     @"wasi crt1-reactor.o",
     @"wasi crt1-command.o",
     @"wasi libc.a",
-    @"wasi libdl.a",
-    @"libwasi-emulated-process-clocks.a",
-    @"libwasi-emulated-getpid.a",
-    @"libwasi-emulated-mman.a",
-    @"libwasi-emulated-signal.a",
 
     @"glibc Scrt1.o",
     @"glibc libc_nonshared.a",