From 58ba8129c4a46b7e61ec61cd61c32d2082fefcd8 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 19 Apr 2019 09:14:25 -0700 Subject: [PATCH 01/14] Add more WASI libc bindings. --- src/wasi.rs | 502 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 502 insertions(+) diff --git a/src/wasi.rs b/src/wasi.rs index 77c48f50a6010..84e70619eff9a 100644 --- a/src/wasi.rs +++ b/src/wasi.rs @@ -26,6 +26,17 @@ pub type clock_t = c_longlong; pub type time_t = c_longlong; pub type c_double = f64; pub type c_float = f32; +pub type ino_t = u64; +pub type sigset_t = c_uchar; +pub type suseconds_t = c_longlong; +pub type mode_t = u32; +pub type dev_t = u64; +pub type uid_t = u32; +pub type gid_t = u32; +pub type nlink_t = u64; +pub type blksize_t = c_long; +pub type blkcnt_t = i64; +pub type nfds_t = c_ulong; pub type __wasi_advice_t = u8; pub type __wasi_clockid_t = u32; @@ -65,6 +76,22 @@ impl ::Clone for FILE { *self } } +#[cfg_attr(feature = "extra_traits", derive(Debug))] +pub enum DIR {} +impl ::Copy for DIR {} +impl ::Clone for DIR { + fn clone(&self) -> DIR { + *self + } +} +#[cfg_attr(feature = "extra_traits", derive(Debug))] +pub enum locale_t {} +impl ::Copy for locale_t {} +impl ::Clone for locale_t { + fn clone(&self) -> locale_t { + *self + } +} s! { #[repr(align(8))] @@ -87,16 +114,108 @@ s! { pub __tm_nsec: c_int, } + pub struct timeval { + pub tv_sec: time_t, + pub tv_usec: suseconds_t, + } + pub struct timespec { pub tv_sec: time_t, pub tv_nsec: c_long, } + pub struct tms { + pub tms_utime: clock_t, + pub tms_stime: clock_t, + pub tms_cutime: clock_t, + pub tms_cstime: clock_t, + } + pub struct itimerspec { pub it_interval: timespec, pub it_value: timespec, } + pub struct iovec { + pub iov_base: *mut c_void, + pub iov_len: size_t, + } + + pub struct utsname { + pub sysname: [c_char; 65], + pub nodename: [c_char; 65], + pub release: [c_char; 65], + pub version: [c_char; 65], + pub machine: [c_char; 65], + pub domainname: [c_char; 65] + } + + pub struct fd_set { + fds_bits: [c_ulong; FD_SETSIZE / ULONG_SIZE], + } + + pub struct dirent { + pub d_ino: ino_t, + pub d_type: c_uchar, + pub d_name: [c_char; 1024], + } + + pub struct lconv { + pub decimal_point: *mut c_char, + pub thousands_sep: *mut c_char, + pub grouping: *mut c_char, + pub int_curr_symbol: *mut c_char, + pub currency_symbol: *mut c_char, + pub mon_decimal_point: *mut c_char, + pub mon_thousands_sep: *mut c_char, + pub mon_grouping: *mut c_char, + pub positive_sign: *mut c_char, + pub negative_sign: *mut c_char, + pub int_frac_digits: c_char, + pub frac_digits: c_char, + pub p_cs_precedes: c_char, + pub p_sep_by_space: c_char, + pub n_cs_precedes: c_char, + pub n_sep_by_space: c_char, + pub p_sign_posn: c_char, + pub n_sign_posn: c_char, + pub int_p_cs_precedes: c_char, + pub int_p_sep_by_space: c_char, + pub int_n_cs_precedes: c_char, + pub int_n_sep_by_space: c_char, + pub int_p_sign_posn: c_char, + pub int_n_sign_posn: c_char, + } + + pub struct pollfd { + pub fd: c_int, + pub events: c_short, + pub revents: c_short, + } + + pub struct rusage { + pub ru_utime: timeval, + pub ru_stime: timeval, + } + + pub struct stat { + pub st_dev: dev_t, + pub st_ino: ino_t, + pub st_nlink: nlink_t, + pub st_mode: mode_t, + pub st_uid: uid_t, + pub st_gid: gid_t, + __pad0: c_uint, + pub st_rdev: dev_t, + pub st_size: off_t, + pub st_blksize: blksize_t, + pub st_blocks: blkcnt_t, + pub st_atim: timespec, + pub st_mtim: timespec, + pub st_ctim: timespec, + __reserved: [c_longlong; 3], + } + pub struct __wasi_dirent_t { pub d_next: __wasi_dircookie_t, pub d_ino: __wasi_inode_t, @@ -197,12 +316,55 @@ s_no_extra_traits! { } +// intentionally not public, only used for fd_set +cfg_if! { + if #[cfg(target_pointer_width = "32")] { + const ULONG_SIZE: usize = 32; + } else if #[cfg(target_pointer_width = "64")] { + const ULONG_SIZE: usize = 64; + } else { + // Unknown target_pointer_width + } +} + +pub const EXIT_SUCCESS: c_int = 0; +pub const EXIT_FAILURE: c_int = 1; pub const STDIN_FILENO: c_int = 0; pub const STDOUT_FILENO: c_int = 1; pub const STDERR_FILENO: c_int = 2; pub const SEEK_SET: c_int = 2; pub const SEEK_CUR: c_int = 0; pub const SEEK_END: c_int = 1; +pub const _IOFBF: c_int = 0; +pub const _IONBF: c_int = 2; +pub const _IOLBF: c_int = 1; +pub const FD_SETSIZE: size_t = 1024; +pub const O_APPEND: c_int = __WASI_FDFLAG_APPEND as c_int; +pub const O_DSYNC: c_int = __WASI_FDFLAG_DSYNC as c_int; +pub const O_NONBLOCK: c_int = __WASI_FDFLAG_NONBLOCK as c_int; +pub const O_RSYNC: c_int = __WASI_FDFLAG_RSYNC as c_int; +pub const O_SYNC: c_int = __WASI_FDFLAG_SYNC as c_int; +pub const O_CREAT: c_int = (__WASI_O_CREAT as c_int) << 12; +pub const O_DIRECTORY: c_int = (__WASI_O_DIRECTORY as c_int) << 12; +pub const O_EXCL: c_int = (__WASI_O_EXCL as c_int) << 12; +pub const O_TRUNC: c_int = (__WASI_O_TRUNC as c_int) << 12; +pub const O_NOFOLLOW: c_int = 0x01000000; +pub const O_EXEC: c_int = 0x02000000; +pub const O_RDONLY: c_int = 0x04000000; +pub const O_SEARCH: c_int = 0x08000000; +pub const O_WRONLY: c_int = 0x10000000; +pub const O_RDWR: c_int = O_WRONLY | O_RDONLY; +pub const O_ACCMODE: c_int = O_EXEC | O_RDWR | O_SEARCH; +pub const POSIX_FADV_DONTNEED: c_int = __WASI_ADVICE_DONTNEED as c_int; +pub const POSIX_FADV_NOREUSE: c_int = __WASI_ADVICE_NOREUSE as c_int; +pub const POSIX_FADV_NORMAL: c_int = __WASI_ADVICE_NORMAL as c_int; +pub const POSIX_FADV_RANDOM: c_int = __WASI_ADVICE_RANDOM as c_int; +pub const POSIX_FADV_SEQUENTIAL: c_int = __WASI_ADVICE_SEQUENTIAL as c_int; +pub const POSIX_FADV_WILLNEED: c_int = __WASI_ADVICE_WILLNEED as c_int; +pub const AT_EACCESS: c_int = 0x0; +pub const AT_SYMLINK_NOFOLLOW: c_int = 0x1; +pub const AT_SYMLINK_FOLLOW: c_int = 0x2; +pub const AT_REMOVEDIR: c_int = 0x4; pub const __WASI_ADVICE_NORMAL: u8 = 0; pub const __WASI_ADVICE_SEQUENTIAL: u8 = 1; @@ -489,6 +651,346 @@ extern { // c: *mut timespec, // ) -> c_int; + pub fn isalnum(c: c_int) -> c_int; + pub fn isalpha(c: c_int) -> c_int; + pub fn iscntrl(c: c_int) -> c_int; + pub fn isdigit(c: c_int) -> c_int; + pub fn isgraph(c: c_int) -> c_int; + pub fn islower(c: c_int) -> c_int; + pub fn isprint(c: c_int) -> c_int; + pub fn ispunct(c: c_int) -> c_int; + pub fn isspace(c: c_int) -> c_int; + pub fn isupper(c: c_int) -> c_int; + pub fn isxdigit(c: c_int) -> c_int; + pub fn tolower(c: c_int) -> c_int; + pub fn toupper(c: c_int) -> c_int; + pub fn setvbuf( + stream: *mut FILE, + buffer: *mut c_char, + mode: c_int, + size: size_t, + ) -> c_int; + pub fn setbuf(stream: *mut FILE, buf: *mut c_char); + pub fn fgets(buf: *mut c_char, n: c_int, stream: *mut FILE) + -> *mut c_char; + pub fn atoi(s: *const c_char) -> c_int; + pub fn strtod(s: *const c_char, endp: *mut *mut c_char) -> c_double; + pub fn strtol( + s: *const c_char, + endp: *mut *mut c_char, + base: c_int, + ) -> c_long; + pub fn strtoul( + s: *const c_char, + endp: *mut *mut c_char, + base: c_int, + ) -> c_ulong; + + pub fn strcpy(dst: *mut c_char, src: *const c_char) -> *mut c_char; + pub fn strncpy( + dst: *mut c_char, + src: *const c_char, + n: size_t, + ) -> *mut c_char; + pub fn strcat(s: *mut c_char, ct: *const c_char) -> *mut c_char; + pub fn strncat( + s: *mut c_char, + ct: *const c_char, + n: size_t, + ) -> *mut c_char; + pub fn strcmp(cs: *const c_char, ct: *const c_char) -> c_int; + pub fn strncmp(cs: *const c_char, ct: *const c_char, n: size_t) -> c_int; + pub fn strcoll(cs: *const c_char, ct: *const c_char) -> c_int; + pub fn strchr(cs: *const c_char, c: c_int) -> *mut c_char; + pub fn strrchr(cs: *const c_char, c: c_int) -> *mut c_char; + pub fn strspn(cs: *const c_char, ct: *const c_char) -> size_t; + pub fn strcspn(cs: *const c_char, ct: *const c_char) -> size_t; + pub fn strdup(cs: *const c_char) -> *mut c_char; + pub fn strpbrk(cs: *const c_char, ct: *const c_char) -> *mut c_char; + pub fn strstr(cs: *const c_char, ct: *const c_char) -> *mut c_char; + pub fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_int; + pub fn strncasecmp( + s1: *const c_char, + s2: *const c_char, + n: size_t, + ) -> c_int; + pub fn strlen(cs: *const c_char) -> size_t; + pub fn strnlen(cs: *const c_char, maxlen: size_t) -> size_t; + pub fn strerror(n: c_int) -> *mut c_char; + pub fn strtok(s: *mut c_char, t: *const c_char) -> *mut c_char; + pub fn strxfrm(s: *mut c_char, ct: *const c_char, n: size_t) -> size_t; + + pub fn memchr(cx: *const c_void, c: c_int, n: size_t) -> *mut c_void; + pub fn memcmp(cx: *const c_void, ct: *const c_void, n: size_t) -> c_int; + pub fn memcpy( + dest: *mut c_void, + src: *const c_void, + n: size_t, + ) -> *mut c_void; + pub fn memmove( + dest: *mut c_void, + src: *const c_void, + n: size_t, + ) -> *mut c_void; + pub fn memset(dest: *mut c_void, c: c_int, n: size_t) -> *mut c_void; + + pub fn fprintf( + stream: *mut ::FILE, + format: *const ::c_char, + ... + ) -> ::c_int; + pub fn printf(format: *const ::c_char, ...) -> ::c_int; + pub fn snprintf( + s: *mut ::c_char, + n: ::size_t, + format: *const ::c_char, + ... + ) -> ::c_int; + pub fn sprintf(s: *mut ::c_char, format: *const ::c_char, ...) -> ::c_int; + pub fn fscanf( + stream: *mut ::FILE, + format: *const ::c_char, + ... + ) -> ::c_int; + pub fn scanf(format: *const ::c_char, ...) -> ::c_int; + pub fn sscanf(s: *const ::c_char, format: *const ::c_char, ...) + -> ::c_int; + pub fn getchar_unlocked() -> ::c_int; + pub fn putchar_unlocked(c: ::c_int) -> ::c_int; + + pub fn shutdown(socket: ::c_int, how: ::c_int) -> ::c_int; + pub fn fstat(fildes: ::c_int, buf: *mut stat) -> ::c_int; + pub fn mkdir(path: *const c_char, mode: mode_t) -> ::c_int; + pub fn stat(path: *const c_char, buf: *mut stat) -> ::c_int; + pub fn fdopen(fd: ::c_int, mode: *const c_char) -> *mut ::FILE; + pub fn fileno(stream: *mut ::FILE) -> ::c_int; + pub fn open(path: *const c_char, oflag: ::c_int, ...) -> ::c_int; + pub fn creat(path: *const c_char, mode: mode_t) -> ::c_int; + pub fn fcntl(fd: ::c_int, cmd: ::c_int, ...) -> ::c_int; + pub fn opendir(dirname: *const c_char) -> *mut ::DIR; + pub fn fdopendir(fd: ::c_int) -> *mut ::DIR; + pub fn readdir(dirp: *mut ::DIR) -> *mut ::dirent; + pub fn closedir(dirp: *mut ::DIR) -> ::c_int; + pub fn rewinddir(dirp: *mut ::DIR); + + pub fn openat( + dirfd: ::c_int, + pathname: *const ::c_char, + flags: ::c_int, + ... + ) -> ::c_int; + pub fn fstatat( + dirfd: ::c_int, + pathname: *const ::c_char, + buf: *mut stat, + flags: ::c_int, + ) -> ::c_int; + pub fn linkat( + olddirfd: ::c_int, + oldpath: *const ::c_char, + newdirfd: ::c_int, + newpath: *const ::c_char, + flags: ::c_int, + ) -> ::c_int; + pub fn mkdirat( + dirfd: ::c_int, + pathname: *const ::c_char, + mode: ::mode_t, + ) -> ::c_int; + pub fn readlinkat( + dirfd: ::c_int, + pathname: *const ::c_char, + buf: *mut ::c_char, + bufsiz: ::size_t, + ) -> ::ssize_t; + pub fn renameat( + olddirfd: ::c_int, + oldpath: *const ::c_char, + newdirfd: ::c_int, + newpath: *const ::c_char, + ) -> ::c_int; + pub fn symlinkat( + target: *const ::c_char, + newdirfd: ::c_int, + linkpath: *const ::c_char, + ) -> ::c_int; + pub fn unlinkat( + dirfd: ::c_int, + pathname: *const ::c_char, + flags: ::c_int, + ) -> ::c_int; + + pub fn access(path: *const c_char, amode: ::c_int) -> ::c_int; + pub fn close(fd: ::c_int) -> ::c_int; + pub fn fpathconf(filedes: ::c_int, name: ::c_int) -> c_long; + pub fn getopt( + argc: ::c_int, + argv: *const *mut c_char, + optstr: *const c_char, + ) -> ::c_int; + pub fn isatty(fd: ::c_int) -> ::c_int; + pub fn link(src: *const c_char, dst: *const c_char) -> ::c_int; + pub fn lseek(fd: ::c_int, offset: off_t, whence: ::c_int) -> off_t; + pub fn pathconf(path: *const c_char, name: ::c_int) -> c_long; + pub fn pause() -> ::c_int; + pub fn rmdir(path: *const c_char) -> ::c_int; + pub fn sleep(secs: ::c_uint) -> ::c_uint; + pub fn unlink(c: *const c_char) -> ::c_int; + pub fn pread( + fd: ::c_int, + buf: *mut ::c_void, + count: ::size_t, + offset: off_t, + ) -> ::ssize_t; + pub fn pwrite( + fd: ::c_int, + buf: *const ::c_void, + count: ::size_t, + offset: off_t, + ) -> ::ssize_t; + + pub fn lstat(path: *const c_char, buf: *mut stat) -> ::c_int; + + pub fn fsync(fd: ::c_int) -> ::c_int; + + pub fn symlink(path1: *const c_char, path2: *const c_char) -> ::c_int; + + pub fn ftruncate(fd: ::c_int, length: off_t) -> ::c_int; + + pub fn getrusage(resource: ::c_int, usage: *mut rusage) -> ::c_int; + + pub fn gettimeofday(tp: *mut ::timeval, tz: *mut ::c_void) -> ::c_int; + pub fn times(buf: *mut ::tms) -> ::clock_t; + + pub fn strerror_r( + errnum: ::c_int, + buf: *mut c_char, + buflen: ::size_t, + ) -> ::c_int; + + pub fn usleep(secs: ::c_uint) -> ::c_int; + pub fn send( + socket: ::c_int, + buf: *const ::c_void, + len: ::size_t, + flags: ::c_int, + ) -> ::ssize_t; + pub fn recv( + socket: ::c_int, + buf: *mut ::c_void, + len: ::size_t, + flags: ::c_int, + ) -> ::ssize_t; + pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: ::c_int) -> ::c_int; + pub fn select( + nfds: ::c_int, + readfs: *mut fd_set, + writefds: *mut fd_set, + errorfds: *mut fd_set, + timeout: *mut timeval, + ) -> ::c_int; + pub fn setlocale( + category: ::c_int, + locale: *const ::c_char, + ) -> *mut ::c_char; + pub fn localeconv() -> *mut lconv; + + pub fn readlink( + path: *const c_char, + buf: *mut c_char, + bufsz: ::size_t, + ) -> ::ssize_t; + + pub fn timegm(tm: *mut ::tm) -> time_t; + + pub fn sysconf(name: ::c_int) -> ::c_long; + + pub fn pselect( + nfds: ::c_int, + readfs: *mut fd_set, + writefds: *mut fd_set, + errorfds: *mut fd_set, + timeout: *const timespec, + sigmask: *const sigset_t, + ) -> ::c_int; + pub fn fseeko( + stream: *mut ::FILE, + offset: ::off_t, + whence: ::c_int, + ) -> ::c_int; + pub fn ftello(stream: *mut ::FILE) -> ::off_t; + + pub fn strcasestr(cs: *const c_char, ct: *const c_char) -> *mut c_char; + pub fn getline( + lineptr: *mut *mut c_char, + n: *mut size_t, + stream: *mut FILE, + ) -> ssize_t; + + pub fn faccessat( + dirfd: ::c_int, + pathname: *const ::c_char, + mode: ::c_int, + flags: ::c_int, + ) -> ::c_int; + pub fn writev( + fd: ::c_int, + iov: *const ::iovec, + iovcnt: ::c_int, + ) -> ::ssize_t; + pub fn readv( + fd: ::c_int, + iov: *const ::iovec, + iovcnt: ::c_int, + ) -> ::ssize_t; + pub fn pwritev( + fd: ::c_int, + iov: *const ::iovec, + iovcnt: ::c_int, + offset: ::off_t, + ) -> ::ssize_t; + pub fn preadv( + fd: ::c_int, + iov: *const ::iovec, + iovcnt: ::c_int, + offset: ::off_t, + ) -> ::ssize_t; + pub fn uname(buf: *mut ::utsname) -> ::c_int; + pub fn posix_fadvise( + fd: ::c_int, + offset: ::off_t, + len: ::off_t, + advise: ::c_int, + ) -> ::c_int; + pub fn futimens(fd: ::c_int, times: *const ::timespec) -> ::c_int; + pub fn utimensat( + dirfd: ::c_int, + path: *const ::c_char, + times: *const ::timespec, + flag: ::c_int, + ) -> ::c_int; + pub fn getentropy(buf: *mut ::c_void, buflen: ::size_t) -> ::c_int; + pub fn memrchr( + cx: *const ::c_void, + c: ::c_int, + n: ::size_t, + ) -> *mut ::c_void; + pub fn abs(i: c_int) -> c_int; + pub fn labs(i: c_long) -> c_long; + pub fn duplocale(base: ::locale_t) -> ::locale_t; + pub fn freelocale(loc: ::locale_t); + pub fn newlocale( + mask: ::c_int, + locale: *const ::c_char, + base: ::locale_t, + ) -> ::locale_t; + pub fn uselocale(loc: ::locale_t) -> ::locale_t; + + pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> (); + pub fn FD_ISSET(fd: ::c_int, set: *mut fd_set) -> bool; + pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> (); + pub fn FD_ZERO(set: *mut fd_set) -> (); + pub fn __wasilibc_register_preopened_fd( fd: c_int, path: *const c_char, From 1168782b3f0dd209534c9efd3b9f73bb3cfbcc4b Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 19 Apr 2019 10:18:41 -0700 Subject: [PATCH 02/14] Define WASI libc errno constants. --- src/wasi.rs | 79 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/src/wasi.rs b/src/wasi.rs index 84e70619eff9a..1309ff5026078 100644 --- a/src/wasi.rs +++ b/src/wasi.rs @@ -366,6 +366,85 @@ pub const AT_SYMLINK_NOFOLLOW: c_int = 0x1; pub const AT_SYMLINK_FOLLOW: c_int = 0x2; pub const AT_REMOVEDIR: c_int = 0x4; +pub const E2BIG: c_int = __WASI_E2BIG as c_int; +pub const EACCES: c_int = __WASI_EACCES as c_int; +pub const EADDRINUSE: c_int = __WASI_EADDRINUSE as c_int; +pub const EADDRNOTAVAIL: c_int = __WASI_EADDRNOTAVAIL as c_int; +pub const EAFNOSUPPORT: c_int = __WASI_EAFNOSUPPORT as c_int; +pub const EAGAIN: c_int = __WASI_EAGAIN as c_int; +pub const EALREADY: c_int = __WASI_EALREADY as c_int; +pub const EBADF: c_int = __WASI_EBADF as c_int; +pub const EBADMSG: c_int = __WASI_EBADMSG as c_int; +pub const EBUSY: c_int = __WASI_EBUSY as c_int; +pub const ECANCELED: c_int = __WASI_ECANCELED as c_int; +pub const ECHILD: c_int = __WASI_ECHILD as c_int; +pub const ECONNABORTED: c_int = __WASI_ECONNABORTED as c_int; +pub const ECONNREFUSED: c_int = __WASI_ECONNREFUSED as c_int; +pub const ECONNRESET: c_int = __WASI_ECONNRESET as c_int; +pub const EDEADLK: c_int = __WASI_EDEADLK as c_int; +pub const EDESTADDRREQ: c_int = __WASI_EDESTADDRREQ as c_int; +pub const EDOM: c_int = __WASI_EDOM as c_int; +pub const EDQUOT: c_int = __WASI_EDQUOT as c_int; +pub const EEXIST: c_int = __WASI_EEXIST as c_int; +pub const EFAULT: c_int = __WASI_EFAULT as c_int; +pub const EFBIG: c_int = __WASI_EFBIG as c_int; +pub const EHOSTUNREACH: c_int = __WASI_EHOSTUNREACH as c_int; +pub const EIDRM: c_int = __WASI_EIDRM as c_int; +pub const EILSEQ: c_int = __WASI_EILSEQ as c_int; +pub const EINPROGRESS: c_int = __WASI_EINPROGRESS as c_int; +pub const EINTR: c_int = __WASI_EINTR as c_int; +pub const EINVAL: c_int = __WASI_EINVAL as c_int; +pub const EIO: c_int = __WASI_EIO as c_int; +pub const EISCONN: c_int = __WASI_EISCONN as c_int; +pub const EISDIR: c_int = __WASI_EISDIR as c_int; +pub const ELOOP: c_int = __WASI_ELOOP as c_int; +pub const EMFILE: c_int = __WASI_EMFILE as c_int; +pub const EMLINK: c_int = __WASI_EMLINK as c_int; +pub const EMSGSIZE: c_int = __WASI_EMSGSIZE as c_int; +pub const EMULTIHOP: c_int = __WASI_EMULTIHOP as c_int; +pub const ENAMETOOLONG: c_int = __WASI_ENAMETOOLONG as c_int; +pub const ENETDOWN: c_int = __WASI_ENETDOWN as c_int; +pub const ENETRESET: c_int = __WASI_ENETRESET as c_int; +pub const ENETUNREACH: c_int = __WASI_ENETUNREACH as c_int; +pub const ENFILE: c_int = __WASI_ENFILE as c_int; +pub const ENOBUFS: c_int = __WASI_ENOBUFS as c_int; +pub const ENODEV: c_int = __WASI_ENODEV as c_int; +pub const ENOENT: c_int = __WASI_ENOENT as c_int; +pub const ENOEXEC: c_int = __WASI_ENOEXEC as c_int; +pub const ENOLCK: c_int = __WASI_ENOLCK as c_int; +pub const ENOLINK: c_int = __WASI_ENOLINK as c_int; +pub const ENOMEM: c_int = __WASI_ENOMEM as c_int; +pub const ENOMSG: c_int = __WASI_ENOMSG as c_int; +pub const ENOPROTOOPT: c_int = __WASI_ENOPROTOOPT as c_int; +pub const ENOSPC: c_int = __WASI_ENOSPC as c_int; +pub const ENOSYS: c_int = __WASI_ENOSYS as c_int; +pub const ENOTCONN: c_int = __WASI_ENOTCONN as c_int; +pub const ENOTDIR: c_int = __WASI_ENOTDIR as c_int; +pub const ENOTEMPTY: c_int = __WASI_ENOTEMPTY as c_int; +pub const ENOTRECOVERABLE: c_int = __WASI_ENOTRECOVERABLE as c_int; +pub const ENOTSOCK: c_int = __WASI_ENOTSOCK as c_int; +pub const ENOTSUP: c_int = __WASI_ENOTSUP as c_int; +pub const ENOTTY: c_int = __WASI_ENOTTY as c_int; +pub const ENXIO: c_int = __WASI_ENXIO as c_int; +pub const EOVERFLOW: c_int = __WASI_EOVERFLOW as c_int; +pub const EOWNERDEAD: c_int = __WASI_EOWNERDEAD as c_int; +pub const EPERM: c_int = __WASI_EPERM as c_int; +pub const EPIPE: c_int = __WASI_EPIPE as c_int; +pub const EPROTO: c_int = __WASI_EPROTO as c_int; +pub const EPROTONOSUPPORT: c_int = __WASI_EPROTONOSUPPORT as c_int; +pub const EPROTOTYPE: c_int = __WASI_EPROTOTYPE as c_int; +pub const ERANGE: c_int = __WASI_ERANGE as c_int; +pub const EROFS: c_int = __WASI_EROFS as c_int; +pub const ESPIPE: c_int = __WASI_ESPIPE as c_int; +pub const ESRCH: c_int = __WASI_ESRCH as c_int; +pub const ESTALE: c_int = __WASI_ESTALE as c_int; +pub const ETIMEDOUT: c_int = __WASI_ETIMEDOUT as c_int; +pub const ETXTBSY: c_int = __WASI_ETXTBSY as c_int; +pub const EXDEV: c_int = __WASI_EXDEV as c_int; +pub const ENOTCAPABLE: c_int = __WASI_ENOTCAPABLE as c_int; +pub const EOPNOTSUPP: c_int = ENOTSUP; +pub const EWOULDBLOCK: c_int = EAGAIN; + pub const __WASI_ADVICE_NORMAL: u8 = 0; pub const __WASI_ADVICE_SEQUENTIAL: u8 = 1; pub const __WASI_ADVICE_RANDOM: u8 = 2; From 3aa0188f1d51c5c4fb46826071d5e546af0385f6 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 19 Apr 2019 13:24:16 -0700 Subject: [PATCH 03/14] Add headers for WASI to libc-test/build.rs --- libc-test/build.rs | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/libc-test/build.rs b/libc-test/build.rs index 72ebbb3ca7e1b..d0e177e0b8406 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -1875,17 +1875,28 @@ fn test_wasi(target: &str) { cfg.define("_GNU_SOURCE", None); headers! { cfg: + "ctype.h", + "dirent.h", "errno.h", "fcntl.h", "limits.h", "locale.h", "malloc.h", + "poll.h", + "stdbool.h", "stddef.h", "stdint.h", "stdio.h", "stdlib.h", + "string.h", + "sys/resource.h", + "sys/select.h", + "sys/socket.h", "sys/stat.h", + "sys/times.h", "sys/types.h", + "sys/uio.h", + "sys/utsname.h", "time.h", "unistd.h", "wasi/core.h", From 30ed9835edeba247377a5783e59ad2175df79484 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 19 Apr 2019 13:25:37 -0700 Subject: [PATCH 04/14] Recognize WASI as either a target_env or a target_os. Rustc is changing it to be target_os; for now, recognize both. --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 2571f81a6cfbd..426b684962489 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -112,7 +112,7 @@ cfg_if! { } else if #[cfg(all(target_env = "sgx", target_vendor = "fortanix"))] { mod sgx; pub use sgx::*; - } else if #[cfg(target_env = "wasi")] { + } else if #[cfg(any(target_env = "wasi", target_os = "wasi"))] { mod wasi; pub use wasi::*; } else { From 49c0dc98d0a5f9dad89675c51132de4204ef28e2 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 19 Apr 2019 12:28:35 -0700 Subject: [PATCH 05/14] Don't add "struct" to "DIR" or "fd_set". --- libc-test/build.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libc-test/build.rs b/libc-test/build.rs index d0e177e0b8406..0c1b976c8e11b 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -1906,7 +1906,7 @@ fn test_wasi(target: &str) { } cfg.type_name(move |ty, is_struct, is_union| match ty { - "FILE" => ty.to_string(), + "FILE" | "fd_set" | "DIR" => ty.to_string(), t if is_union => format!("union {}", t), t if t.starts_with("__wasi") && t.ends_with("_u") => { format!("union {}", t) From 6b524b36c8661163171e2ad8b41901e4e9e545da Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 19 Apr 2019 12:29:59 -0700 Subject: [PATCH 06/14] Don't make opaque types like FILE and DIR copyable. Also, locale_t is a typedef for a pointer to an opaque struct, so represent it that way explicitly. --- src/wasi.rs | 25 ++++++------------------- 1 file changed, 6 insertions(+), 19 deletions(-) diff --git a/src/wasi.rs b/src/wasi.rs index 1309ff5026078..3412e435345bc 100644 --- a/src/wasi.rs +++ b/src/wasi.rs @@ -68,30 +68,17 @@ pub type __wasi_userdata_t = u64; pub type __wasi_whence_t = u8; pub type __wasi_preopentype_t = u8; +#[allow(missing_copy_implementations)] #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum FILE {} -impl ::Copy for FILE {} -impl ::Clone for FILE { - fn clone(&self) -> FILE { - *self - } -} +#[allow(missing_copy_implementations)] #[cfg_attr(feature = "extra_traits", derive(Debug))] pub enum DIR {} -impl ::Copy for DIR {} -impl ::Clone for DIR { - fn clone(&self) -> DIR { - *self - } -} +#[allow(missing_copy_implementations)] #[cfg_attr(feature = "extra_traits", derive(Debug))] -pub enum locale_t {} -impl ::Copy for locale_t {} -impl ::Clone for locale_t { - fn clone(&self) -> locale_t { - *self - } -} +pub enum __locale_struct {} + +pub type locale_t = *mut __locale_struct; s! { #[repr(align(8))] From a625c6954452ed2d35b2c3ddd50a0e062f62b069 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 19 Apr 2019 13:04:27 -0700 Subject: [PATCH 07/14] Make FD_ISSET's argument a pointer to const, to match the libc declaration. --- src/wasi.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/wasi.rs b/src/wasi.rs index 3412e435345bc..ee368adf376be 100644 --- a/src/wasi.rs +++ b/src/wasi.rs @@ -1053,7 +1053,7 @@ extern { pub fn uselocale(loc: ::locale_t) -> ::locale_t; pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> (); - pub fn FD_ISSET(fd: ::c_int, set: *mut fd_set) -> bool; + pub fn FD_ISSET(fd: ::c_int, set: *const fd_set) -> bool; pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> (); pub fn FD_ZERO(set: *mut fd_set) -> (); From ef7ae73239e504df2e38e74819dad1a508238c95 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Fri, 19 Apr 2019 02:03:42 -0700 Subject: [PATCH 08/14] Fix dirent to match WASI libc's definition. dirent contains a flexible array member, so don't test its sizeof, don't allow it to be copied, and don't represent it with an artificial size. --- libc-test/build.rs | 4 ++++ src/wasi.rs | 20 ++++++++++++++------ 2 files changed, 18 insertions(+), 6 deletions(-) diff --git a/libc-test/build.rs b/libc-test/build.rs index 0c1b976c8e11b..aba2a3056852c 100644 --- a/libc-test/build.rs +++ b/libc-test/build.rs @@ -1931,5 +1931,9 @@ fn test_wasi(target: &str) { // import the same thing but have different function pointers cfg.skip_fn_ptrcheck(|f| f.starts_with("__wasi")); + // d_name is declared as a flexible array in WASI libc, so it + // doesn't support sizeof. + cfg.skip_field(|s, field| s == "dirent" && field == "d_name"); + cfg.generate("../src/lib.rs", "main.rs"); } diff --git a/src/wasi.rs b/src/wasi.rs index ee368adf376be..42cb33f4924ae 100644 --- a/src/wasi.rs +++ b/src/wasi.rs @@ -141,12 +141,6 @@ s! { fds_bits: [c_ulong; FD_SETSIZE / ULONG_SIZE], } - pub struct dirent { - pub d_ino: ino_t, - pub d_type: c_uchar, - pub d_name: [c_char; 1024], - } - pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, @@ -303,6 +297,20 @@ s_no_extra_traits! { } +// Declare dirent outside of s! so that it doesn't implement Copy, Eq, Hash, +// etc., since it contains a flexible array member with a dynamic size. +#[repr(C)] +#[allow(missing_copy_implementations)] +#[cfg_attr(feature = "extra_traits", derive(Debug))] +pub struct dirent { + pub d_ino: ino_t, + pub d_type: c_uchar, + /// d_name is declared in WASI libc as a flexible array member, which + /// can't be directly expressed in Rust. As an imperfect workaround, + /// declare it as a zero-length array instead. + pub d_name: [c_char; 0], +} + // intentionally not public, only used for fd_set cfg_if! { if #[cfg(target_pointer_width = "32")] { From 8a5b230c14cd395d8c26c69f702b9e9927cc3dad Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 23 Apr 2019 21:01:39 -0700 Subject: [PATCH 09/14] Update to the latest wasi-sysroot. This contains several fixes, including the FD_ISSET signature change that the previous patch in this PR needs. --- ci/docker/wasm32-unknown-wasi/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/docker/wasm32-unknown-wasi/Dockerfile b/ci/docker/wasm32-unknown-wasi/Dockerfile index 6f46440457d3c..deac87a69305e 100644 --- a/ci/docker/wasm32-unknown-wasi/Dockerfile +++ b/ci/docker/wasm32-unknown-wasi/Dockerfile @@ -28,7 +28,7 @@ RUN mv /clang+llvm-8.0.0-x86_64-linux-gnu-ubuntu-18.04 /wasmcc # those breaking changes on `libc`'s own CI RUN git clone https://github.com/CraneStation/wasi-sysroot && \ cd wasi-sysroot && \ - git reset --hard e5f14be38362f1ab83302895a6e74b2ffd0e2302 + git reset --hard 2201343c17b7149a75f543f523bea0c3243c6091 RUN make -C wasi-sysroot install -j $(nproc) WASM_CC=/wasmcc/bin/clang INSTALL_DIR=/wasi-sysroot # This is a small wrapper script which executes the actual clang binary in From edd541e67f6fb8ff09b0092777dc7a75fd2cb254 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Tue, 23 Apr 2019 23:10:38 -0700 Subject: [PATCH 10/14] Remove FD_SET and related functions for now. --- src/wasi.rs | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/wasi.rs b/src/wasi.rs index 42cb33f4924ae..429bc53f5778c 100644 --- a/src/wasi.rs +++ b/src/wasi.rs @@ -1060,11 +1060,6 @@ extern { ) -> ::locale_t; pub fn uselocale(loc: ::locale_t) -> ::locale_t; - pub fn FD_CLR(fd: ::c_int, set: *mut fd_set) -> (); - pub fn FD_ISSET(fd: ::c_int, set: *const fd_set) -> bool; - pub fn FD_SET(fd: ::c_int, set: *mut fd_set) -> (); - pub fn FD_ZERO(set: *mut fd_set) -> (); - pub fn __wasilibc_register_preopened_fd( fd: c_int, path: *const c_char, From 4d0e84b8beefc01724111ffcf8ae12ca2b1b6937 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 24 Apr 2019 05:40:34 -0700 Subject: [PATCH 11/14] Use the WASI layout for fd_set. --- src/wasi.rs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/wasi.rs b/src/wasi.rs index 429bc53f5778c..bd2cbfa1d8535 100644 --- a/src/wasi.rs +++ b/src/wasi.rs @@ -138,7 +138,8 @@ s! { } pub struct fd_set { - fds_bits: [c_ulong; FD_SETSIZE / ULONG_SIZE], + pub __nfds: size_t, + pub __fds: [c_int; FD_SETSIZE], } pub struct lconv { From 7ba5e347544aad24a471e8d65088131098fd6245 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 24 Apr 2019 06:16:28 -0700 Subject: [PATCH 12/14] Remove the definition of ULONG_SIZE which is no longer needed. --- src/wasi.rs | 11 ----------- 1 file changed, 11 deletions(-) diff --git a/src/wasi.rs b/src/wasi.rs index bd2cbfa1d8535..45c809519a390 100644 --- a/src/wasi.rs +++ b/src/wasi.rs @@ -312,17 +312,6 @@ pub struct dirent { pub d_name: [c_char; 0], } -// intentionally not public, only used for fd_set -cfg_if! { - if #[cfg(target_pointer_width = "32")] { - const ULONG_SIZE: usize = 32; - } else if #[cfg(target_pointer_width = "64")] { - const ULONG_SIZE: usize = 64; - } else { - // Unknown target_pointer_width - } -} - pub const EXIT_SUCCESS: c_int = 0; pub const EXIT_FAILURE: c_int = 1; pub const STDIN_FILENO: c_int = 0; From 599c0f76ddfadc02343772f28d9623b938b82f97 Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 24 Apr 2019 08:09:15 -0700 Subject: [PATCH 13/14] Remove fd_set, select, and pselect entirely for now. fd_set isn't automatically copyable. While it will be possible to fix that, for now just remove these so that they don't block other changes. --- src/wasi.rs | 20 -------------------- 1 file changed, 20 deletions(-) diff --git a/src/wasi.rs b/src/wasi.rs index 45c809519a390..f4d92ed9e3341 100644 --- a/src/wasi.rs +++ b/src/wasi.rs @@ -137,11 +137,6 @@ s! { pub domainname: [c_char; 65] } - pub struct fd_set { - pub __nfds: size_t, - pub __fds: [c_int; FD_SETSIZE], - } - pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, @@ -946,13 +941,6 @@ extern { flags: ::c_int, ) -> ::ssize_t; pub fn poll(fds: *mut pollfd, nfds: nfds_t, timeout: ::c_int) -> ::c_int; - pub fn select( - nfds: ::c_int, - readfs: *mut fd_set, - writefds: *mut fd_set, - errorfds: *mut fd_set, - timeout: *mut timeval, - ) -> ::c_int; pub fn setlocale( category: ::c_int, locale: *const ::c_char, @@ -969,14 +957,6 @@ extern { pub fn sysconf(name: ::c_int) -> ::c_long; - pub fn pselect( - nfds: ::c_int, - readfs: *mut fd_set, - writefds: *mut fd_set, - errorfds: *mut fd_set, - timeout: *const timespec, - sigmask: *const sigset_t, - ) -> ::c_int; pub fn fseeko( stream: *mut ::FILE, offset: ::off_t, From 13ddc16e06e8cfaf192af81dd0eb6eff38f62a9f Mon Sep 17 00:00:00 2001 From: Dan Gohman Date: Wed, 24 Apr 2019 11:28:45 -0700 Subject: [PATCH 14/14] Remove utsname and uname for now too. --- src/wasi.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/src/wasi.rs b/src/wasi.rs index f4d92ed9e3341..a014e4c0fa330 100644 --- a/src/wasi.rs +++ b/src/wasi.rs @@ -128,15 +128,6 @@ s! { pub iov_len: size_t, } - pub struct utsname { - pub sysname: [c_char; 65], - pub nodename: [c_char; 65], - pub release: [c_char; 65], - pub version: [c_char; 65], - pub machine: [c_char; 65], - pub domainname: [c_char; 65] - } - pub struct lconv { pub decimal_point: *mut c_char, pub thousands_sep: *mut c_char, @@ -999,7 +990,6 @@ extern { iovcnt: ::c_int, offset: ::off_t, ) -> ::ssize_t; - pub fn uname(buf: *mut ::utsname) -> ::c_int; pub fn posix_fadvise( fd: ::c_int, offset: ::off_t,