Commit 07cc32b004
Changed files (124)
lib
libc
include
wasi
libc-bottom-half
clocks
cloudlibc
src
libc
stdlib
headers
private
wasi
mman
libc-top-half
musl
include
src
math
misc
regex
setjmp
wasm32
stdlib
thread
time
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",