--- /dev/null
+commit f3fb1c5e95b9fef29df00f0924a27790b03c524b
+Author: Alex Crichton <alex@alexcrichton.com>
+Date: Mon Nov 25 09:27:25 2019 -0800
+
+ Update the `wasi` crate for `wasm32-wasi`
+
+ This commit updates the `wasi` crate used by the standard library which
+ is used to implement most of the functionality of libstd on the
+ `wasm32-wasi` target. This update comes with a brand new crate structure
+ in the `wasi` crate which caused quite a few changes for the wasi target
+ here, but it also comes with a significant change to where the
+ functionality is coming from.
+
+ The WASI specification is organized into "snapshots" and a new snapshot
+ happened recently, so the WASI APIs themselves have changed since the
+ previous revision. This had only minor impact on the public facing
+ surface area of libstd, only changing on `u32` to a `u64` in an unstable
+ API. The actual source for all of these types and such, however, is now
+ coming from the `wasi_preview_snapshot1` module instead of the
+ `wasi_unstable` module like before. This means that any implementors
+ generating binaries will need to ensure that their embedding environment
+ handles the `wasi_preview_snapshot1` module.
+
+diff --git a/Cargo.lock b/Cargo.lock
+index 8fd0285a7e6..5a56bf03f4d 100644
+--- a/Cargo.lock
++++ b/Cargo.lock
+@@ -1294,7 +1294,7 @@ checksum = "473a1265acc8ff1e808cd0a1af8cee3c2ee5200916058a2ca113c29f2d903571"
+ dependencies = [
+ "cfg-if",
+ "libc",
+- "wasi",
++ "wasi 0.7.0",
+ ]
+
+ [[package]]
+@@ -4301,7 +4301,7 @@ dependencies = [
+ "rustc_msan",
+ "rustc_tsan",
+ "unwind",
+- "wasi",
++ "wasi 0.9.0+wasi-snapshot-preview1",
+ ]
+
+ [[package]]
+@@ -5172,6 +5172,12 @@ name = "wasi"
+ version = "0.7.0"
+ source = "registry+https://github.com/rust-lang/crates.io-index"
+ checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d"
++
++[[package]]
++name = "wasi"
++version = "0.9.0+wasi-snapshot-preview1"
++source = "registry+https://github.com/rust-lang/crates.io-index"
++checksum = "cccddf32554fecc6acb585f82a32a72e28b48f8c4c1883ddfeeeaa96f7d8e519"
+ dependencies = [
+ "compiler_builtins",
+ "rustc-std-workspace-alloc",
+diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
+index c55911a33f5..a22e162bbff 100644
+--- a/src/libstd/Cargo.toml
++++ b/src/libstd/Cargo.toml
+@@ -54,7 +54,7 @@ fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }
+ hermit-abi = { version = "0.1", features = ['rustc-dep-of-std'] }
+
+ [target.wasm32-wasi.dependencies]
+-wasi = { version = "0.7.0", features = ['rustc-dep-of-std', 'alloc'] }
++wasi = { version = "0.9.0", features = ['rustc-dep-of-std'], default-features = false }
+
+ [features]
+ default = ["std_detect_file_io", "std_detect_dlsym_getauxval"]
+diff --git a/src/libstd/sys/wasi/args.rs b/src/libstd/sys/wasi/args.rs
+index 3280c4990dc..3db36f5e132 100644
+--- a/src/libstd/sys/wasi/args.rs
++++ b/src/libstd/sys/wasi/args.rs
+@@ -1,15 +1,11 @@
+-use crate::ffi::OsString;
++use crate::ffi::{CStr, OsStr, OsString};
+ use crate::marker::PhantomData;
+-use crate::os::wasi::ffi::OsStringExt;
++use crate::os::wasi::ffi::OsStrExt;
+ use crate::vec;
+
+-use ::wasi::wasi_unstable as wasi;
++pub unsafe fn init(_argc: isize, _argv: *const *const u8) {}
+
+-pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
+-}
+-
+-pub unsafe fn cleanup() {
+-}
++pub unsafe fn cleanup() {}
+
+ pub struct Args {
+ iter: vec::IntoIter<OsString>,
+@@ -18,17 +14,24 @@ pub struct Args {
+
+ /// Returns the command line arguments
+ pub fn args() -> Args {
+- let buf = wasi::args_sizes_get().and_then(|args_sizes| {
+- let mut buf = Vec::with_capacity(args_sizes.get_count());
+- wasi::args_get(args_sizes, |arg| {
+- let arg = OsString::from_vec(arg.to_vec());
+- buf.push(arg);
+- })?;
+- Ok(buf)
+- }).unwrap_or(vec![]);
+ Args {
+- iter: buf.into_iter(),
+- _dont_send_or_sync_me: PhantomData
++ iter: maybe_args().unwrap_or(Vec::new()).into_iter(),
++ _dont_send_or_sync_me: PhantomData,
++ }
++}
++
++fn maybe_args() -> Option<Vec<OsString>> {
++ unsafe {
++ let (argc, buf_size) = wasi::args_sizes_get().ok()?;
++ let mut argv = Vec::with_capacity(argc);
++ let mut buf = Vec::with_capacity(buf_size);
++ wasi::args_get(argv.as_mut_ptr(), buf.as_mut_ptr()).ok()?;
++ let mut ret = Vec::with_capacity(argc);
++ for ptr in argv {
++ let s = CStr::from_ptr(ptr.cast());
++ ret.push(OsStr::from_bytes(s.to_bytes()).to_owned());
++ }
++ Some(ret)
+ }
+ }
+
+diff --git a/src/libstd/sys/wasi/ext/fs.rs b/src/libstd/sys/wasi/ext/fs.rs
+index 9fa4abfd171..92d0e60c07e 100644
+--- a/src/libstd/sys/wasi/ext/fs.rs
++++ b/src/libstd/sys/wasi/ext/fs.rs
+@@ -4,12 +4,10 @@
+
+ use crate::fs::{self, File, Metadata, OpenOptions};
+ use crate::io::{self, IoSlice, IoSliceMut};
+-use crate::os::wasi::ffi::OsStrExt;
+ use crate::path::{Path, PathBuf};
++use crate::sys::fs::osstr2str;
+ use crate::sys_common::{AsInner, AsInnerMut, FromInner};
+
+-use ::wasi::wasi_unstable as wasi;
+-
+ /// WASI-specific extensions to [`File`].
+ ///
+ /// [`File`]: ../../../../std/fs/struct.File.html
+@@ -49,62 +47,62 @@ pub trait FileExt {
+
+ /// Returns the current position within the file.
+ ///
+- /// This corresponds to the `__wasi_fd_tell` syscall and is similar to
++ /// This corresponds to the `fd_tell` syscall and is similar to
+ /// `seek` where you offset 0 bytes from the current position.
+ fn tell(&self) -> io::Result<u64>;
+
+ /// Adjust the flags associated with this file.
+ ///
+- /// This corresponds to the `__wasi_fd_fdstat_set_flags` syscall.
++ /// This corresponds to the `fd_fdstat_set_flags` syscall.
+ fn fdstat_set_flags(&self, flags: u16) -> io::Result<()>;
+
+ /// Adjust the rights associated with this file.
+ ///
+- /// This corresponds to the `__wasi_fd_fdstat_set_rights` syscall.
++ /// This corresponds to the `fd_fdstat_set_rights` syscall.
+ fn fdstat_set_rights(&self, rights: u64, inheriting: u64) -> io::Result<()>;
+
+ /// Provide file advisory information on a file descriptor.
+ ///
+- /// This corresponds to the `__wasi_fd_advise` syscall.
++ /// This corresponds to the `fd_advise` syscall.
+ fn advise(&self, offset: u64, len: u64, advice: u8) -> io::Result<()>;
+
+ /// Force the allocation of space in a file.
+ ///
+- /// This corresponds to the `__wasi_fd_allocate` syscall.
++ /// This corresponds to the `fd_allocate` syscall.
+ fn allocate(&self, offset: u64, len: u64) -> io::Result<()>;
+
+ /// Create a directory.
+ ///
+- /// This corresponds to the `__wasi_path_create_directory` syscall.
++ /// This corresponds to the `path_create_directory` syscall.
+ fn create_directory<P: AsRef<Path>>(&self, dir: P) -> io::Result<()>;
+
+ /// Read the contents of a symbolic link.
+ ///
+- /// This corresponds to the `__wasi_path_readlink` syscall.
++ /// This corresponds to the `path_readlink` syscall.
+ fn read_link<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf>;
+
+ /// Return the attributes of a file or directory.
+ ///
+- /// This corresponds to the `__wasi_path_filestat_get` syscall.
++ /// This corresponds to the `path_filestat_get` syscall.
+ fn metadata_at<P: AsRef<Path>>(&self, lookup_flags: u32, path: P) -> io::Result<Metadata>;
+
+ /// Unlink a file.
+ ///
+- /// This corresponds to the `__wasi_path_unlink_file` syscall.
++ /// This corresponds to the `path_unlink_file` syscall.
+ fn remove_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()>;
+
+ /// Remove a directory.
+ ///
+- /// This corresponds to the `__wasi_path_remove_directory` syscall.
++ /// This corresponds to the `path_remove_directory` syscall.
+ fn remove_directory<P: AsRef<Path>>(&self, path: P) -> io::Result<()>;
+ }
+
+-// FIXME: bind __wasi_fd_fdstat_get - need to define a custom return type
+-// FIXME: bind __wasi_fd_readdir - can't return `ReadDir` since we only have entry name
+-// FIXME: bind __wasi_fd_filestat_set_times maybe? - on crates.io for unix
+-// FIXME: bind __wasi_path_filestat_set_times maybe? - on crates.io for unix
+-// FIXME: bind __wasi_poll_oneoff maybe? - probably should wait for I/O to settle
+-// FIXME: bind __wasi_random_get maybe? - on crates.io for unix
++// FIXME: bind fd_fdstat_get - need to define a custom return type
++// FIXME: bind fd_readdir - can't return `ReadDir` since we only have entry name
++// FIXME: bind fd_filestat_set_times maybe? - on crates.io for unix
++// FIXME: bind path_filestat_set_times maybe? - on crates.io for unix
++// FIXME: bind poll_oneoff maybe? - probably should wait for I/O to settle
++// FIXME: bind random_get maybe? - on crates.io for unix
+
+ impl FileExt for fs::File {
+ fn read_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
+@@ -136,9 +134,7 @@ impl FileExt for fs::File {
+ }
+
+ fn create_directory<P: AsRef<Path>>(&self, dir: P) -> io::Result<()> {
+- self.as_inner()
+- .fd()
+- .create_directory(dir.as_ref().as_os_str().as_bytes())
++ self.as_inner().fd().create_directory(osstr2str(dir.as_ref().as_ref())?)
+ }
+
+ fn read_link<P: AsRef<Path>>(&self, path: P) -> io::Result<PathBuf> {
+@@ -151,15 +147,11 @@ impl FileExt for fs::File {
+ }
+
+ fn remove_file<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
+- self.as_inner()
+- .fd()
+- .unlink_file(path.as_ref().as_os_str().as_bytes())
++ self.as_inner().fd().unlink_file(osstr2str(path.as_ref().as_ref())?)
+ }
+
+ fn remove_directory<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
+- self.as_inner()
+- .fd()
+- .remove_directory(path.as_ref().as_os_str().as_bytes())
++ self.as_inner().fd().remove_directory(osstr2str(path.as_ref().as_ref())?)
+ }
+ }
+
+@@ -167,10 +159,10 @@ impl FileExt for fs::File {
+ ///
+ /// [`fs::OpenOptions`]: ../../../../std/fs/struct.OpenOptions.html
+ pub trait OpenOptionsExt {
+- /// Pass custom `dirflags` argument to `__wasi_path_open`.
++ /// Pass custom `dirflags` argument to `path_open`.
+ ///
+ /// This option configures the `dirflags` argument to the
+- /// `__wasi_path_open` syscall which `OpenOptions` will eventually call. The
++ /// `path_open` syscall which `OpenOptions` will eventually call. The
+ /// `dirflags` argument configures how the file is looked up, currently
+ /// primarily affecting whether symlinks are followed or not.
+ ///
+@@ -188,31 +180,31 @@ pub trait OpenOptionsExt {
+ fn directory(&mut self, dir: bool) -> &mut Self;
+
+ /// Indicates whether `__WASI_FDFLAG_DSYNC` is passed in the `fs_flags`
+- /// field of `__wasi_path_open`.
++ /// field of `path_open`.
+ ///
+ /// This option is by default `false`
+ fn dsync(&mut self, dsync: bool) -> &mut Self;
+
+ /// Indicates whether `__WASI_FDFLAG_NONBLOCK` is passed in the `fs_flags`
+- /// field of `__wasi_path_open`.
++ /// field of `path_open`.
+ ///
+ /// This option is by default `false`
+ fn nonblock(&mut self, nonblock: bool) -> &mut Self;
+
+ /// Indicates whether `__WASI_FDFLAG_RSYNC` is passed in the `fs_flags`
+- /// field of `__wasi_path_open`.
++ /// field of `path_open`.
+ ///
+ /// This option is by default `false`
+ fn rsync(&mut self, rsync: bool) -> &mut Self;
+
+ /// Indicates whether `__WASI_FDFLAG_SYNC` is passed in the `fs_flags`
+- /// field of `__wasi_path_open`.
++ /// field of `path_open`.
+ ///
+ /// This option is by default `false`
+ fn sync(&mut self, sync: bool) -> &mut Self;
+
+ /// Indicates the value that should be passed in for the `fs_rights_base`
+- /// parameter of `__wasi_path_open`.
++ /// parameter of `path_open`.
+ ///
+ /// This option defaults based on the `read` and `write` configuration of
+ /// this `OpenOptions` builder. If this method is called, however, the
+@@ -220,7 +212,7 @@ pub trait OpenOptionsExt {
+ fn fs_rights_base(&mut self, rights: u64) -> &mut Self;
+
+ /// Indicates the value that should be passed in for the
+- /// `fs_rights_inheriting` parameter of `__wasi_path_open`.
++ /// `fs_rights_inheriting` parameter of `path_open`.
+ ///
+ /// The default for this option is the same value as what will be passed
+ /// for the `fs_rights_base` parameter but if this method is called then
+@@ -229,7 +221,7 @@ pub trait OpenOptionsExt {
+
+ /// Open a file or directory.
+ ///
+- /// This corresponds to the `__wasi_path_open` syscall.
++ /// This corresponds to the `path_open` syscall.
+ fn open_at<P: AsRef<Path>>(&self, file: &File, path: P) -> io::Result<File>;
+ }
+
+@@ -284,38 +276,38 @@ impl OpenOptionsExt for OpenOptions {
+ ///
+ /// [`fs::Metadata`]: ../../../../std/fs/struct.Metadata.html
+ pub trait MetadataExt {
+- /// Returns the `st_dev` field of the internal `__wasi_filestat_t`
++ /// Returns the `st_dev` field of the internal `filestat_t`
+ fn dev(&self) -> u64;
+- /// Returns the `st_ino` field of the internal `__wasi_filestat_t`
++ /// Returns the `st_ino` field of the internal `filestat_t`
+ fn ino(&self) -> u64;
+- /// Returns the `st_nlink` field of the internal `__wasi_filestat_t`
+- fn nlink(&self) -> u32;
+- /// Returns the `st_atim` field of the internal `__wasi_filestat_t`
++ /// Returns the `st_nlink` field of the internal `filestat_t`
++ fn nlink(&self) -> u64;
++ /// Returns the `st_atim` field of the internal `filestat_t`
+ fn atim(&self) -> u64;
+- /// Returns the `st_mtim` field of the internal `__wasi_filestat_t`
++ /// Returns the `st_mtim` field of the internal `filestat_t`
+ fn mtim(&self) -> u64;
+- /// Returns the `st_ctim` field of the internal `__wasi_filestat_t`
++ /// Returns the `st_ctim` field of the internal `filestat_t`
+ fn ctim(&self) -> u64;
+ }
+
+ impl MetadataExt for fs::Metadata {
+ fn dev(&self) -> u64 {
+- self.as_inner().as_wasi().st_dev
++ self.as_inner().as_wasi().dev
+ }
+ fn ino(&self) -> u64 {
+- self.as_inner().as_wasi().st_ino
++ self.as_inner().as_wasi().ino
+ }
+- fn nlink(&self) -> u32 {
+- self.as_inner().as_wasi().st_nlink
++ fn nlink(&self) -> u64 {
++ self.as_inner().as_wasi().nlink
+ }
+ fn atim(&self) -> u64 {
+- self.as_inner().as_wasi().st_atim
++ self.as_inner().as_wasi().atim
+ }
+ fn mtim(&self) -> u64 {
+- self.as_inner().as_wasi().st_mtim
++ self.as_inner().as_wasi().mtim
+ }
+ fn ctim(&self) -> u64 {
+- self.as_inner().as_wasi().st_ctim
++ self.as_inner().as_wasi().ctim
+ }
+ }
+
+@@ -355,7 +347,7 @@ impl FileTypeExt for fs::FileType {
+ ///
+ /// [`fs::DirEntry`]: ../../../../std/fs/struct.DirEntry.html
+ pub trait DirEntryExt {
+- /// Returns the underlying `d_ino` field of the `__wasi_dirent_t`
++ /// Returns the underlying `d_ino` field of the `dirent_t`
+ fn ino(&self) -> u64;
+ }
+
+@@ -367,7 +359,7 @@ impl DirEntryExt for fs::DirEntry {
+
+ /// Create a hard link.
+ ///
+-/// This corresponds to the `__wasi_path_link` syscall.
++/// This corresponds to the `path_link` syscall.
+ pub fn link<P: AsRef<Path>, U: AsRef<Path>>(
+ old_fd: &File,
+ old_flags: u32,
+@@ -377,15 +369,15 @@ pub fn link<P: AsRef<Path>, U: AsRef<Path>>(
+ ) -> io::Result<()> {
+ old_fd.as_inner().fd().link(
+ old_flags,
+- old_path.as_ref().as_os_str().as_bytes(),
++ osstr2str(old_path.as_ref().as_ref())?,
+ new_fd.as_inner().fd(),
+- new_path.as_ref().as_os_str().as_bytes(),
++ osstr2str(new_path.as_ref().as_ref())?,
+ )
+ }
+
+ /// Rename a file or directory.
+ ///
+-/// This corresponds to the `__wasi_path_rename` syscall.
++/// This corresponds to the `path_rename` syscall.
+ pub fn rename<P: AsRef<Path>, U: AsRef<Path>>(
+ old_fd: &File,
+ old_path: P,
+@@ -393,22 +385,21 @@ pub fn rename<P: AsRef<Path>, U: AsRef<Path>>(
+ new_path: U,
+ ) -> io::Result<()> {
+ old_fd.as_inner().fd().rename(
+- old_path.as_ref().as_os_str().as_bytes(),
++ osstr2str(old_path.as_ref().as_ref())?,
+ new_fd.as_inner().fd(),
+- new_path.as_ref().as_os_str().as_bytes(),
++ osstr2str(new_path.as_ref().as_ref())?,
+ )
+ }
+
+ /// Create a symbolic link.
+ ///
+-/// This corresponds to the `__wasi_path_symlink` syscall.
++/// This corresponds to the `path_symlink` syscall.
+ pub fn symlink<P: AsRef<Path>, U: AsRef<Path>>(
+ old_path: P,
+ fd: &File,
+ new_path: U,
+ ) -> io::Result<()> {
+- fd.as_inner().fd().symlink(
+- old_path.as_ref().as_os_str().as_bytes(),
+- new_path.as_ref().as_os_str().as_bytes(),
+- )
++ fd.as_inner()
++ .fd()
++ .symlink(osstr2str(old_path.as_ref().as_ref())?, osstr2str(new_path.as_ref().as_ref())?)
+ }
+diff --git a/src/libstd/sys/wasi/ext/io.rs b/src/libstd/sys/wasi/ext/io.rs
+index f1839df3801..f678b71a2b9 100644
+--- a/src/libstd/sys/wasi/ext/io.rs
++++ b/src/libstd/sys/wasi/ext/io.rs
+@@ -8,8 +8,6 @@ use crate::sys;
+ use crate::net;
+ use crate::sys_common::{AsInner, FromInner, IntoInner};
+
+-use ::wasi::wasi_unstable as wasi;
+-
+ /// Raw file descriptors.
+ pub type RawFd = u32;
+
+@@ -127,18 +125,18 @@ impl IntoRawFd for fs::File {
+
+ impl AsRawFd for io::Stdin {
+ fn as_raw_fd(&self) -> RawFd {
+- wasi::STDIN_FD
++ sys::stdio::Stdin.as_raw_fd()
+ }
+ }
+
+ impl AsRawFd for io::Stdout {
+ fn as_raw_fd(&self) -> RawFd {
+- wasi::STDOUT_FD
++ sys::stdio::Stdout.as_raw_fd()
+ }
+ }
+
+ impl AsRawFd for io::Stderr {
+ fn as_raw_fd(&self) -> RawFd {
+- wasi::STDERR_FD
++ sys::stdio::Stderr.as_raw_fd()
+ }
+ }
+diff --git a/src/libstd/sys/wasi/fd.rs b/src/libstd/sys/wasi/fd.rs
+index 5b7a8678b66..00327c1743c 100644
+--- a/src/libstd/sys/wasi/fd.rs
++++ b/src/libstd/sys/wasi/fd.rs
+@@ -1,40 +1,31 @@
+ #![allow(dead_code)]
+
++use super::err2io;
+ use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
+ use crate::mem;
+ use crate::net::Shutdown;
+-use super::err2io;
+-use ::wasi::wasi_unstable as wasi;
+
+ #[derive(Debug)]
+ pub struct WasiFd {
+ fd: wasi::Fd,
+ }
+
+-fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::IoVec] {
+- assert_eq!(
+- mem::size_of::<IoSliceMut<'_>>(),
+- mem::size_of::<wasi::IoVec>()
+- );
+- assert_eq!(
+- mem::align_of::<IoSliceMut<'_>>(),
+- mem::align_of::<wasi::IoVec>()
+- );
++fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::Iovec] {
++ assert_eq!(mem::size_of::<IoSliceMut<'_>>(), mem::size_of::<wasi::Iovec>());
++ assert_eq!(mem::align_of::<IoSliceMut<'_>>(), mem::align_of::<wasi::Iovec>());
+ /// SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout
+- unsafe { mem::transmute(a) }
++ unsafe {
++ mem::transmute(a)
++ }
+ }
+
+-fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::CIoVec] {
+- assert_eq!(
+- mem::size_of::<IoSlice<'_>>(),
+- mem::size_of::<wasi::CIoVec>()
+- );
+- assert_eq!(
+- mem::align_of::<IoSlice<'_>>(),
+- mem::align_of::<wasi::CIoVec>()
+- );
++fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::Ciovec] {
++ assert_eq!(mem::size_of::<IoSlice<'_>>(), mem::size_of::<wasi::Ciovec>());
++ assert_eq!(mem::align_of::<IoSlice<'_>>(), mem::align_of::<wasi::Ciovec>());
+ /// SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout
+- unsafe { mem::transmute(a) }
++ unsafe {
++ mem::transmute(a)
++ }
+ }
+
+ impl WasiFd {
+@@ -87,7 +78,7 @@ impl WasiFd {
+
+ // FIXME: __wasi_fd_fdstat_get
+
+- pub fn set_flags(&self, flags: wasi::FdFlags) -> io::Result<()> {
++ pub fn set_flags(&self, flags: wasi::Fdflags) -> io::Result<()> {
+ unsafe { wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) }
+ }
+
+@@ -107,31 +98,30 @@ impl WasiFd {
+ unsafe { wasi::fd_allocate(self.fd, offset, len).map_err(err2io) }
+ }
+
+- pub fn create_directory(&self, path: &[u8]) -> io::Result<()> {
++ pub fn create_directory(&self, path: &str) -> io::Result<()> {
+ unsafe { wasi::path_create_directory(self.fd, path).map_err(err2io) }
+ }
+
+ pub fn link(
+ &self,
+- old_flags: wasi::LookupFlags,
+- old_path: &[u8],
++ old_flags: wasi::Lookupflags,
++ old_path: &str,
+ new_fd: &WasiFd,
+- new_path: &[u8],
++ new_path: &str,
+ ) -> io::Result<()> {
+ unsafe {
+- wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path)
+- .map_err(err2io)
++ wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path).map_err(err2io)
+ }
+ }
+
+ pub fn open(
+ &self,
+- dirflags: wasi::LookupFlags,
+- path: &[u8],
+- oflags: wasi::OFlags,
++ dirflags: wasi::Lookupflags,
++ path: &str,
++ oflags: wasi::Oflags,
+ fs_rights_base: wasi::Rights,
+ fs_rights_inheriting: wasi::Rights,
+- fs_flags: wasi::FdFlags,
++ fs_flags: wasi::Fdflags,
+ ) -> io::Result<WasiFd> {
+ unsafe {
+ wasi::path_open(
+@@ -142,25 +132,25 @@ impl WasiFd {
+ fs_rights_base,
+ fs_rights_inheriting,
+ fs_flags,
+- ).map(|fd| WasiFd::from_raw(fd)).map_err(err2io)
++ )
++ .map(|fd| WasiFd::from_raw(fd))
++ .map_err(err2io)
+ }
+ }
+
+- pub fn readdir(&self, buf: &mut [u8], cookie: wasi::DirCookie) -> io::Result<usize> {
+- unsafe { wasi::fd_readdir(self.fd, buf, cookie).map_err(err2io) }
++ pub fn readdir(&self, buf: &mut [u8], cookie: wasi::Dircookie) -> io::Result<usize> {
++ unsafe { wasi::fd_readdir(self.fd, buf.as_mut_ptr(), buf.len(), cookie).map_err(err2io) }
+ }
+
+- pub fn readlink(&self, path: &[u8], buf: &mut [u8]) -> io::Result<usize> {
+- unsafe { wasi::path_readlink(self.fd, path, buf).map_err(err2io) }
++ pub fn readlink(&self, path: &str, buf: &mut [u8]) -> io::Result<usize> {
++ unsafe { wasi::path_readlink(self.fd, path, buf.as_mut_ptr(), buf.len()).map_err(err2io) }
+ }
+
+- pub fn rename(&self, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8]) -> io::Result<()> {
+- unsafe {
+- wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io)
+- }
++ pub fn rename(&self, old_path: &str, new_fd: &WasiFd, new_path: &str) -> io::Result<()> {
++ unsafe { wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io) }
+ }
+
+- pub fn filestat_get(&self) -> io::Result<wasi::FileStat> {
++ pub fn filestat_get(&self) -> io::Result<wasi::Filestat> {
+ unsafe { wasi::fd_filestat_get(self.fd).map_err(err2io) }
+ }
+
+@@ -168,11 +158,9 @@ impl WasiFd {
+ &self,
+ atim: wasi::Timestamp,
+ mtim: wasi::Timestamp,
+- fstflags: wasi::FstFlags,
++ fstflags: wasi::Fstflags,
+ ) -> io::Result<()> {
+- unsafe {
+- wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags).map_err(err2io)
+- }
++ unsafe { wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags).map_err(err2io) }
+ }
+
+ pub fn filestat_set_size(&self, size: u64) -> io::Result<()> {
+@@ -181,61 +169,55 @@ impl WasiFd {
+
+ pub fn path_filestat_get(
+ &self,
+- flags: wasi::LookupFlags,
+- path: &[u8],
+- ) -> io::Result<wasi::FileStat> {
++ flags: wasi::Lookupflags,
++ path: &str,
++ ) -> io::Result<wasi::Filestat> {
+ unsafe { wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) }
+ }
+
+ pub fn path_filestat_set_times(
+ &self,
+- flags: wasi::LookupFlags,
+- path: &[u8],
++ flags: wasi::Lookupflags,
++ path: &str,
+ atim: wasi::Timestamp,
+ mtim: wasi::Timestamp,
+- fstflags: wasi::FstFlags,
++ fstflags: wasi::Fstflags,
+ ) -> io::Result<()> {
+ unsafe {
+- wasi::path_filestat_set_times(
+- self.fd,
+- flags,
+- path,
+- atim,
+- mtim,
+- fstflags,
+- ).map_err(err2io)
++ wasi::path_filestat_set_times(self.fd, flags, path, atim, mtim, fstflags)
++ .map_err(err2io)
+ }
+ }
+
+- pub fn symlink(&self, old_path: &[u8], new_path: &[u8]) -> io::Result<()> {
++ pub fn symlink(&self, old_path: &str, new_path: &str) -> io::Result<()> {
+ unsafe { wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) }
+ }
+
+- pub fn unlink_file(&self, path: &[u8]) -> io::Result<()> {
++ pub fn unlink_file(&self, path: &str) -> io::Result<()> {
+ unsafe { wasi::path_unlink_file(self.fd, path).map_err(err2io) }
+ }
+
+- pub fn remove_directory(&self, path: &[u8]) -> io::Result<()> {
++ pub fn remove_directory(&self, path: &str) -> io::Result<()> {
+ unsafe { wasi::path_remove_directory(self.fd, path).map_err(err2io) }
+ }
+
+ pub fn sock_recv(
+ &self,
+ ri_data: &mut [IoSliceMut<'_>],
+- ri_flags: wasi::RiFlags,
+- ) -> io::Result<(usize, wasi::RoFlags)> {
++ ri_flags: wasi::Riflags,
++ ) -> io::Result<(usize, wasi::Roflags)> {
+ unsafe { wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(err2io) }
+ }
+
+- pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::SiFlags) -> io::Result<usize> {
++ pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::Siflags) -> io::Result<usize> {
+ unsafe { wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(err2io) }
+ }
+
+ pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> {
+ let how = match how {
+- Shutdown::Read => wasi::SHUT_RD,
+- Shutdown::Write => wasi::SHUT_WR,
+- Shutdown::Both => wasi::SHUT_WR | wasi::SHUT_RD,
++ Shutdown::Read => wasi::SDFLAGS_RD,
++ Shutdown::Write => wasi::SDFLAGS_WR,
++ Shutdown::Both => wasi::SDFLAGS_WR | wasi::SDFLAGS_RD,
+ };
+ unsafe { wasi::sock_shutdown(self.fd, how).map_err(err2io) }
+ }
+diff --git a/src/libstd/sys/wasi/fs.rs b/src/libstd/sys/wasi/fs.rs
+index 4113f6a2e09..fad092e35c3 100644
+--- a/src/libstd/sys/wasi/fs.rs
++++ b/src/libstd/sys/wasi/fs.rs
+@@ -15,20 +15,18 @@ use crate::sys_common::FromInner;
+ pub use crate::sys_common::fs::copy;
+ pub use crate::sys_common::fs::remove_dir_all;
+
+-use ::wasi::wasi_unstable as wasi;
+-
+ pub struct File {
+ fd: WasiFd,
+ }
+
+ #[derive(Clone)]
+ pub struct FileAttr {
+- meta: wasi::FileStat,
++ meta: wasi::Filestat,
+ }
+
+ pub struct ReadDir {
+ inner: Arc<ReadDirInner>,
+- cookie: Option<wasi::DirCookie>,
++ cookie: Option<wasi::Dircookie>,
+ buf: Vec<u8>,
+ offset: usize,
+ cap: usize,
+@@ -49,9 +47,9 @@ pub struct DirEntry {
+ pub struct OpenOptions {
+ read: bool,
+ write: bool,
+- dirflags: wasi::LookupFlags,
+- fdflags: wasi::FdFlags,
+- oflags: wasi::OFlags,
++ dirflags: wasi::Lookupflags,
++ fdflags: wasi::Fdflags,
++ oflags: wasi::Oflags,
+ rights_base: Option<wasi::Rights>,
+ rights_inheriting: Option<wasi::Rights>,
+ }
+@@ -63,7 +61,7 @@ pub struct FilePermissions {
+
+ #[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
+ pub struct FileType {
+- bits: wasi::FileType,
++ bits: wasi::Filetype,
+ }
+
+ #[derive(Debug)]
+@@ -71,7 +69,7 @@ pub struct DirBuilder {}
+
+ impl FileAttr {
+ pub fn size(&self) -> u64 {
+- self.meta.st_size
++ self.meta.size
+ }
+
+ pub fn perm(&self) -> FilePermissions {
+@@ -80,24 +78,22 @@ impl FileAttr {
+ }
+
+ pub fn file_type(&self) -> FileType {
+- FileType {
+- bits: self.meta.st_filetype,
+- }
++ FileType { bits: self.meta.filetype }
+ }
+
+ pub fn modified(&self) -> io::Result<SystemTime> {
+- Ok(SystemTime::from_wasi_timestamp(self.meta.st_mtim))
++ Ok(SystemTime::from_wasi_timestamp(self.meta.mtim))
+ }
+
+ pub fn accessed(&self) -> io::Result<SystemTime> {
+- Ok(SystemTime::from_wasi_timestamp(self.meta.st_atim))
++ Ok(SystemTime::from_wasi_timestamp(self.meta.atim))
+ }
+
+ pub fn created(&self) -> io::Result<SystemTime> {
+- Ok(SystemTime::from_wasi_timestamp(self.meta.st_ctim))
++ Ok(SystemTime::from_wasi_timestamp(self.meta.ctim))
+ }
+
+- pub fn as_wasi(&self) -> &wasi::FileStat {
++ pub fn as_wasi(&self) -> &wasi::Filestat {
+ &self.meta
+ }
+ }
+@@ -125,7 +121,7 @@ impl FileType {
+ self.bits == wasi::FILETYPE_SYMBOLIC_LINK
+ }
+
+- pub fn bits(&self) -> wasi::FileType {
++ pub fn bits(&self) -> wasi::Filetype {
+ self.bits
+ }
+ }
+@@ -177,8 +173,7 @@ impl Iterator for ReadDir {
+ continue;
+ }
+ let (dirent, data) = data.split_at(dirent_size);
+- let dirent =
+- unsafe { ptr::read_unaligned(dirent.as_ptr() as *const wasi::Dirent) };
++ let dirent = unsafe { ptr::read_unaligned(dirent.as_ptr() as *const wasi::Dirent) };
+
+ // If the file name was truncated, then we need to reinvoke
+ // `readdir` so we truncate our buffer to start over and reread this
+@@ -224,17 +219,11 @@ impl DirEntry {
+ }
+
+ pub fn metadata(&self) -> io::Result<FileAttr> {
+- metadata_at(
+- &self.inner.dir.fd,
+- 0,
+- OsStr::from_bytes(&self.name).as_ref(),
+- )
++ metadata_at(&self.inner.dir.fd, 0, OsStr::from_bytes(&self.name).as_ref())
+ }
+
+ pub fn file_type(&self) -> io::Result<FileType> {
+- Ok(FileType {
+- bits: self.meta.d_type,
+- })
++ Ok(FileType { bits: self.meta.d_type })
+ }
+
+ pub fn ino(&self) -> wasi::Inode {
+@@ -245,7 +234,7 @@ impl DirEntry {
+ impl OpenOptions {
+ pub fn new() -> OpenOptions {
+ let mut base = OpenOptions::default();
+- base.dirflags = wasi::LOOKUP_SYMLINK_FOLLOW;
++ base.dirflags = wasi::LOOKUPFLAGS_SYMLINK_FOLLOW;
+ return base;
+ }
+
+@@ -258,23 +247,23 @@ impl OpenOptions {
+ }
+
+ pub fn truncate(&mut self, truncate: bool) {
+- self.oflag(wasi::O_TRUNC, truncate);
++ self.oflag(wasi::OFLAGS_TRUNC, truncate);
+ }
+
+ pub fn create(&mut self, create: bool) {
+- self.oflag(wasi::O_CREAT, create);
++ self.oflag(wasi::OFLAGS_CREAT, create);
+ }
+
+ pub fn create_new(&mut self, create_new: bool) {
+- self.oflag(wasi::O_EXCL, create_new);
+- self.oflag(wasi::O_CREAT, create_new);
++ self.oflag(wasi::OFLAGS_EXCL, create_new);
++ self.oflag(wasi::OFLAGS_CREAT, create_new);
+ }
+
+ pub fn directory(&mut self, directory: bool) {
+- self.oflag(wasi::O_DIRECTORY, directory);
++ self.oflag(wasi::OFLAGS_DIRECTORY, directory);
+ }
+
+- fn oflag(&mut self, bit: wasi::OFlags, set: bool) {
++ fn oflag(&mut self, bit: wasi::Oflags, set: bool) {
+ if set {
+ self.oflags |= bit;
+ } else {
+@@ -283,26 +272,26 @@ impl OpenOptions {
+ }
+
+ pub fn append(&mut self, set: bool) {
+- self.fdflag(wasi::FDFLAG_APPEND, set);
++ self.fdflag(wasi::FDFLAGS_APPEND, set);
+ }
+
+ pub fn dsync(&mut self, set: bool) {
+- self.fdflag(wasi::FDFLAG_DSYNC, set);
++ self.fdflag(wasi::FDFLAGS_DSYNC, set);
+ }
+
+ pub fn nonblock(&mut self, set: bool) {
+- self.fdflag(wasi::FDFLAG_NONBLOCK, set);
++ self.fdflag(wasi::FDFLAGS_NONBLOCK, set);
+ }
+
+ pub fn rsync(&mut self, set: bool) {
+- self.fdflag(wasi::FDFLAG_RSYNC, set);
++ self.fdflag(wasi::FDFLAGS_RSYNC, set);
+ }
+
+ pub fn sync(&mut self, set: bool) {
+- self.fdflag(wasi::FDFLAG_SYNC, set);
++ self.fdflag(wasi::FDFLAGS_SYNC, set);
+ }
+
+- fn fdflag(&mut self, bit: wasi::FdFlags, set: bool) {
++ fn fdflag(&mut self, bit: wasi::Fdflags, set: bool) {
+ if set {
+ self.fdflags |= bit;
+ } else {
+@@ -330,36 +319,36 @@ impl OpenOptions {
+ // based on that.
+ let mut base = 0;
+ if self.read {
+- base |= wasi::RIGHT_FD_READ;
+- base |= wasi::RIGHT_FD_READDIR;
++ base |= wasi::RIGHTS_FD_READ;
++ base |= wasi::RIGHTS_FD_READDIR;
+ }
+ if self.write {
+- base |= wasi::RIGHT_FD_WRITE;
+- base |= wasi::RIGHT_FD_DATASYNC;
+- base |= wasi::RIGHT_FD_ALLOCATE;
+- base |= wasi::RIGHT_FD_FILESTAT_SET_SIZE;
++ base |= wasi::RIGHTS_FD_WRITE;
++ base |= wasi::RIGHTS_FD_DATASYNC;
++ base |= wasi::RIGHTS_FD_ALLOCATE;
++ base |= wasi::RIGHTS_FD_FILESTAT_SET_SIZE;
+ }
+
+ // FIXME: some of these should probably be read-only or write-only...
+- base |= wasi::RIGHT_FD_ADVISE;
+- base |= wasi::RIGHT_FD_FDSTAT_SET_FLAGS;
+- base |= wasi::RIGHT_FD_FILESTAT_SET_TIMES;
+- base |= wasi::RIGHT_FD_SEEK;
+- base |= wasi::RIGHT_FD_SYNC;
+- base |= wasi::RIGHT_FD_TELL;
+- base |= wasi::RIGHT_PATH_CREATE_DIRECTORY;
+- base |= wasi::RIGHT_PATH_CREATE_FILE;
+- base |= wasi::RIGHT_PATH_FILESTAT_GET;
+- base |= wasi::RIGHT_PATH_LINK_SOURCE;
+- base |= wasi::RIGHT_PATH_LINK_TARGET;
+- base |= wasi::RIGHT_PATH_OPEN;
+- base |= wasi::RIGHT_PATH_READLINK;
+- base |= wasi::RIGHT_PATH_REMOVE_DIRECTORY;
+- base |= wasi::RIGHT_PATH_RENAME_SOURCE;
+- base |= wasi::RIGHT_PATH_RENAME_TARGET;
+- base |= wasi::RIGHT_PATH_SYMLINK;
+- base |= wasi::RIGHT_PATH_UNLINK_FILE;
+- base |= wasi::RIGHT_POLL_FD_READWRITE;
++ base |= wasi::RIGHTS_FD_ADVISE;
++ base |= wasi::RIGHTS_FD_FDSTAT_SET_FLAGS;
++ base |= wasi::RIGHTS_FD_FILESTAT_SET_TIMES;
++ base |= wasi::RIGHTS_FD_SEEK;
++ base |= wasi::RIGHTS_FD_SYNC;
++ base |= wasi::RIGHTS_FD_TELL;
++ base |= wasi::RIGHTS_PATH_CREATE_DIRECTORY;
++ base |= wasi::RIGHTS_PATH_CREATE_FILE;
++ base |= wasi::RIGHTS_PATH_FILESTAT_GET;
++ base |= wasi::RIGHTS_PATH_LINK_SOURCE;
++ base |= wasi::RIGHTS_PATH_LINK_TARGET;
++ base |= wasi::RIGHTS_PATH_OPEN;
++ base |= wasi::RIGHTS_PATH_READLINK;
++ base |= wasi::RIGHTS_PATH_REMOVE_DIRECTORY;
++ base |= wasi::RIGHTS_PATH_RENAME_SOURCE;
++ base |= wasi::RIGHTS_PATH_RENAME_TARGET;
++ base |= wasi::RIGHTS_PATH_SYMLINK;
++ base |= wasi::RIGHTS_PATH_UNLINK_FILE;
++ base |= wasi::RIGHTS_POLL_FD_READWRITE;
+
+ return base;
+ }
+@@ -368,14 +357,14 @@ impl OpenOptions {
+ self.rights_inheriting.unwrap_or_else(|| self.rights_base())
+ }
+
+- pub fn lookup_flags(&mut self, flags: wasi::LookupFlags) {
++ pub fn lookup_flags(&mut self, flags: wasi::Lookupflags) {
+ self.dirflags = flags;
+ }
+ }
+
+ impl File {
+ pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
+- let (dir, file) = open_parent(path, wasi::RIGHT_PATH_OPEN)?;
++ let (dir, file) = open_parent(path, wasi::RIGHTS_PATH_OPEN)?;
+ open_at(&dir, &file, opts)
+ }
+
+@@ -387,11 +376,7 @@ impl File {
+ self.fd.filestat_get().map(|meta| FileAttr { meta })
+ }
+
+- pub fn metadata_at(
+- &self,
+- flags: wasi::LookupFlags,
+- path: &Path,
+- ) -> io::Result<FileAttr> {
++ pub fn metadata_at(&self, flags: wasi::Lookupflags, path: &Path) -> io::Result<FileAttr> {
+ metadata_at(&self.fd, flags, path)
+ }
+
+@@ -457,11 +442,7 @@ impl File {
+
+ impl FromInner<u32> for File {
+ fn from_inner(fd: u32) -> File {
+- unsafe {
+- File {
+- fd: WasiFd::from_raw(fd),
+- }
+- }
++ unsafe { File { fd: WasiFd::from_raw(fd) } }
+ }
+ }
+
+@@ -471,16 +452,14 @@ impl DirBuilder {
+ }
+
+ pub fn mkdir(&self, p: &Path) -> io::Result<()> {
+- let (dir, file) = open_parent(p, wasi::RIGHT_PATH_CREATE_DIRECTORY)?;
+- dir.create_directory(file.as_os_str().as_bytes())
++ let (dir, file) = open_parent(p, wasi::RIGHTS_PATH_CREATE_DIRECTORY)?;
++ dir.create_directory(osstr2str(file.as_ref())?)
+ }
+ }
+
+ impl fmt::Debug for File {
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+- f.debug_struct("File")
+- .field("fd", &self.fd.as_raw())
+- .finish()
++ f.debug_struct("File").field("fd", &self.fd.as_raw()).finish()
+ }
+ }
+
+@@ -494,26 +473,19 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
+ buf: vec![0; 128],
+ offset: 0,
+ cap: 0,
+- inner: Arc::new(ReadDirInner {
+- dir,
+- root: p.to_path_buf(),
+- }),
++ inner: Arc::new(ReadDirInner { dir, root: p.to_path_buf() }),
+ })
+ }
+
+ pub fn unlink(p: &Path) -> io::Result<()> {
+- let (dir, file) = open_parent(p, wasi::RIGHT_PATH_UNLINK_FILE)?;
+- dir.unlink_file(file.as_os_str().as_bytes())
++ let (dir, file) = open_parent(p, wasi::RIGHTS_PATH_UNLINK_FILE)?;
++ dir.unlink_file(osstr2str(file.as_ref())?)
+ }
+
+ pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
+- let (old, old_file) = open_parent(old, wasi::RIGHT_PATH_RENAME_SOURCE)?;
+- let (new, new_file) = open_parent(new, wasi::RIGHT_PATH_RENAME_TARGET)?;
+- old.rename(
+- old_file.as_os_str().as_bytes(),
+- &new,
+- new_file.as_os_str().as_bytes(),
+- )
++ let (old, old_file) = open_parent(old, wasi::RIGHTS_PATH_RENAME_SOURCE)?;
++ let (new, new_file) = open_parent(new, wasi::RIGHTS_PATH_RENAME_TARGET)?;
++ old.rename(osstr2str(old_file.as_ref())?, &new, osstr2str(new_file.as_ref())?)
+ }
+
+ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> {
+@@ -523,12 +495,12 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> {
+ }
+
+ pub fn rmdir(p: &Path) -> io::Result<()> {
+- let (dir, file) = open_parent(p, wasi::RIGHT_PATH_REMOVE_DIRECTORY)?;
+- dir.remove_directory(file.as_os_str().as_bytes())
++ let (dir, file) = open_parent(p, wasi::RIGHTS_PATH_REMOVE_DIRECTORY)?;
++ dir.remove_directory(osstr2str(file.as_ref())?)
+ }
+
+ pub fn readlink(p: &Path) -> io::Result<PathBuf> {
+- let (dir, file) = open_parent(p, wasi::RIGHT_PATH_READLINK)?;
++ let (dir, file) = open_parent(p, wasi::RIGHTS_PATH_READLINK)?;
+ read_link(&dir, &file)
+ }
+
+@@ -549,7 +521,7 @@ fn read_link(fd: &WasiFd, file: &Path) -> io::Result<PathBuf> {
+ // Now that we have an initial guess of how big to make our buffer, call
+ // `readlink` in a loop until it fails or reports it filled fewer bytes than
+ // we asked for, indicating we got everything.
+- let file = file.as_os_str().as_bytes();
++ let file = osstr2str(file.as_ref())?;
+ let mut destination = vec![0u8; initial_size];
+ loop {
+ let len = fd.readlink(file, &mut destination)?;
+@@ -564,38 +536,34 @@ fn read_link(fd: &WasiFd, file: &Path) -> io::Result<PathBuf> {
+ }
+
+ pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
+- let (dst, dst_file) = open_parent(dst, wasi::RIGHT_PATH_SYMLINK)?;
+- dst.symlink(src.as_os_str().as_bytes(), dst_file.as_os_str().as_bytes())
++ let (dst, dst_file) = open_parent(dst, wasi::RIGHTS_PATH_SYMLINK)?;
++ dst.symlink(osstr2str(src.as_ref())?, osstr2str(dst_file.as_ref())?)
+ }
+
+ pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
+- let (src, src_file) = open_parent(src, wasi::RIGHT_PATH_LINK_SOURCE)?;
+- let (dst, dst_file) = open_parent(dst, wasi::RIGHT_PATH_LINK_TARGET)?;
++ let (src, src_file) = open_parent(src, wasi::RIGHTS_PATH_LINK_SOURCE)?;
++ let (dst, dst_file) = open_parent(dst, wasi::RIGHTS_PATH_LINK_TARGET)?;
+ src.link(
+- wasi::LOOKUP_SYMLINK_FOLLOW,
+- src_file.as_os_str().as_bytes(),
++ wasi::LOOKUPFLAGS_SYMLINK_FOLLOW,
++ osstr2str(src_file.as_ref())?,
+ &dst,
+- dst_file.as_os_str().as_bytes(),
++ osstr2str(dst_file.as_ref())?,
+ )
+ }
+
+ pub fn stat(p: &Path) -> io::Result<FileAttr> {
+- let (dir, file) = open_parent(p, wasi::RIGHT_PATH_FILESTAT_GET)?;
+- metadata_at(&dir, wasi::LOOKUP_SYMLINK_FOLLOW, &file)
++ let (dir, file) = open_parent(p, wasi::RIGHTS_PATH_FILESTAT_GET)?;
++ metadata_at(&dir, wasi::LOOKUPFLAGS_SYMLINK_FOLLOW, &file)
+ }
+
+ pub fn lstat(p: &Path) -> io::Result<FileAttr> {
+- let (dir, file) = open_parent(p, wasi::RIGHT_PATH_FILESTAT_GET)?;
++ let (dir, file) = open_parent(p, wasi::RIGHTS_PATH_FILESTAT_GET)?;
+ metadata_at(&dir, 0, &file)
+ }
+
+-fn metadata_at(
+- fd: &WasiFd,
+- flags: wasi::LookupFlags,
+- path: &Path,
+-) -> io::Result<FileAttr> {
+- fd.path_filestat_get(flags, path.as_os_str().as_bytes())
+- .map(|meta| FileAttr { meta })
++fn metadata_at(fd: &WasiFd, flags: wasi::Lookupflags, path: &Path) -> io::Result<FileAttr> {
++ let meta = fd.path_filestat_get(flags, osstr2str(path.as_ref())?)?;
++ Ok(FileAttr { meta })
+ }
+
+ pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
+@@ -607,7 +575,7 @@ pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
+ fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result<File> {
+ let fd = fd.open(
+ opts.dirflags,
+- path.as_os_str().as_bytes(),
++ osstr2str(path.as_ref())?,
+ opts.oflags,
+ opts.rights_base(),
+ opts.rights_inheriting(),
+@@ -643,10 +611,7 @@ fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result<File> {
+ ///
+ /// Note that this can fail if `p` doesn't look like it can be opened relative
+ /// to any preopened file descriptor.
+-fn open_parent(
+- p: &Path,
+- rights: wasi::Rights,
+-) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
++fn open_parent(p: &Path, rights: wasi::Rights) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
+ let p = CString::new(p.as_os_str().as_bytes())?;
+ unsafe {
+ let mut ret = ptr::null();
+@@ -671,3 +636,7 @@ fn open_parent(
+ return Ok((ManuallyDrop::new(WasiFd::from_raw(fd as u32)), path));
+ }
+ }
++
++pub fn osstr2str(f: &OsStr) -> io::Result<&str> {
++ f.to_str().ok_or_else(|| io::Error::new(io::ErrorKind::Other, "input must be utf-8"))
++}
+diff --git a/src/libstd/sys/wasi/io.rs b/src/libstd/sys/wasi/io.rs
+index 4be92faed30..41a6e9783c0 100644
+--- a/src/libstd/sys/wasi/io.rs
++++ b/src/libstd/sys/wasi/io.rs
+@@ -1,12 +1,9 @@
+ use crate::marker::PhantomData;
+ use crate::slice;
+
+-use ::wasi::wasi_unstable as wasi;
+-use core::ffi::c_void;
+-
+ #[repr(transparent)]
+ pub struct IoSlice<'a> {
+- vec: wasi::CIoVec,
++ vec: wasi::Ciovec,
+ _p: PhantomData<&'a [u8]>,
+ }
+
+@@ -14,8 +11,8 @@ impl<'a> IoSlice<'a> {
+ #[inline]
+ pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
+ IoSlice {
+- vec: wasi::CIoVec {
+- buf: buf.as_ptr() as *const c_void,
++ vec: wasi::Ciovec {
++ buf: buf.as_ptr(),
+ buf_len: buf.len(),
+ },
+ _p: PhantomData,
+@@ -44,7 +41,7 @@ impl<'a> IoSlice<'a> {
+
+ #[repr(transparent)]
+ pub struct IoSliceMut<'a> {
+- vec: wasi::IoVec,
++ vec: wasi::Iovec,
+ _p: PhantomData<&'a mut [u8]>,
+ }
+
+@@ -52,8 +49,8 @@ impl<'a> IoSliceMut<'a> {
+ #[inline]
+ pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
+ IoSliceMut {
+- vec: wasi::IoVec {
+- buf: buf.as_mut_ptr() as *mut c_void,
++ vec: wasi::Iovec {
++ buf: buf.as_mut_ptr(),
+ buf_len: buf.len()
+ },
+ _p: PhantomData,
+diff --git a/src/libstd/sys/wasi/mod.rs b/src/libstd/sys/wasi/mod.rs
+index 517e3be9cb5..83f98a19f47 100644
+--- a/src/libstd/sys/wasi/mod.rs
++++ b/src/libstd/sys/wasi/mod.rs
+@@ -17,7 +17,6 @@
+ use crate::io as std_io;
+ use crate::mem;
+ use crate::os::raw::c_char;
+-use ::wasi::wasi_unstable as wasi;
+
+ pub mod alloc;
+ pub mod args;
+@@ -72,25 +71,21 @@ pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
+ if errno > u16::max_value() as i32 || errno < 0 {
+ return Other;
+ }
+- let code = match wasi::Error::new(errno as u16) {
+- Some(code) => code,
+- None => return Other,
+- };
+- match code {
+- wasi::ECONNREFUSED => ConnectionRefused,
+- wasi::ECONNRESET => ConnectionReset,
+- wasi::EPERM | wasi::EACCES => PermissionDenied,
+- wasi::EPIPE => BrokenPipe,
+- wasi::ENOTCONN => NotConnected,
+- wasi::ECONNABORTED => ConnectionAborted,
+- wasi::EADDRNOTAVAIL => AddrNotAvailable,
+- wasi::EADDRINUSE => AddrInUse,
+- wasi::ENOENT => NotFound,
+- wasi::EINTR => Interrupted,
+- wasi::EINVAL => InvalidInput,
+- wasi::ETIMEDOUT => TimedOut,
+- wasi::EEXIST => AlreadyExists,
+- wasi::EAGAIN => WouldBlock,
++ match errno as u16 {
++ wasi::ERRNO_CONNREFUSED => ConnectionRefused,
++ wasi::ERRNO_CONNRESET => ConnectionReset,
++ wasi::ERRNO_PERM | wasi::ERRNO_ACCES => PermissionDenied,
++ wasi::ERRNO_PIPE => BrokenPipe,
++ wasi::ERRNO_NOTCONN => NotConnected,
++ wasi::ERRNO_CONNABORTED => ConnectionAborted,
++ wasi::ERRNO_ADDRNOTAVAIL => AddrNotAvailable,
++ wasi::ERRNO_ADDRINUSE => AddrInUse,
++ wasi::ERRNO_NOENT => NotFound,
++ wasi::ERRNO_INTR => Interrupted,
++ wasi::ERRNO_INVAL => InvalidInput,
++ wasi::ERRNO_TIMEDOUT => TimedOut,
++ wasi::ERRNO_EXIST => AlreadyExists,
++ wasi::ERRNO_AGAIN => WouldBlock,
+ _ => Other,
+ }
+ }
+@@ -116,16 +111,13 @@ pub unsafe fn abort_internal() -> ! {
+ pub fn hashmap_random_keys() -> (u64, u64) {
+ let mut ret = (0u64, 0u64);
+ unsafe {
+- let base = &mut ret as *mut (u64, u64) as *mut core::ffi::c_void;
++ let base = &mut ret as *mut (u64, u64) as *mut u8;
+ let len = mem::size_of_val(&ret);
+- let ret = wasi::raw::__wasi_random_get(base, len);
+- if ret != 0 {
+- panic!("__wasi_random_get failure")
+- }
++ wasi::random_get(base, len).expect("random_get failure");
+ }
+ return ret
+ }
+
+ fn err2io(err: wasi::Error) -> std_io::Error {
+- std_io::Error::from_raw_os_error(err.get() as i32)
++ std_io::Error::from_raw_os_error(err.raw_error().into())
+ }
+diff --git a/src/libstd/sys/wasi/stdio.rs b/src/libstd/sys/wasi/stdio.rs
+index 1d57b9922e5..1d53884f2d6 100644
+--- a/src/libstd/sys/wasi/stdio.rs
++++ b/src/libstd/sys/wasi/stdio.rs
+@@ -2,8 +2,6 @@ use crate::io::{self, IoSlice, IoSliceMut};
+ use crate::mem::ManuallyDrop;
+ use crate::sys::fd::WasiFd;
+
+-use ::wasi::wasi_unstable as wasi;
+-
+ pub struct Stdin;
+ pub struct Stdout;
+ pub struct Stderr;
+@@ -18,8 +16,11 @@ impl Stdin {
+ }
+
+ pub fn read_vectored(&self, data: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+- ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDIN_FD) })
+- .read(data)
++ ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).read(data)
++ }
++
++ pub fn as_raw_fd(&self) -> u32 {
++ 0
+ }
+ }
+
+@@ -33,13 +34,16 @@ impl Stdout {
+ }
+
+ pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
+- ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDOUT_FD) })
+- .write(data)
++ ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data)
+ }
+
+ pub fn flush(&self) -> io::Result<()> {
+ Ok(())
+ }
++
++ pub fn as_raw_fd(&self) -> u32 {
++ 1
++ }
+ }
+
+ impl Stderr {
+@@ -52,13 +56,16 @@ impl Stderr {
+ }
+
+ pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
+- ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDERR_FD) })
+- .write(data)
++ ManuallyDrop::new(unsafe { WasiFd::from_raw(self.as_raw_fd()) }).write(data)
+ }
+
+ pub fn flush(&self) -> io::Result<()> {
+ Ok(())
+ }
++
++ pub fn as_raw_fd(&self) -> u32 {
++ 2
++ }
+ }
+
+ impl io::Write for Stderr {
+@@ -74,7 +81,7 @@ impl io::Write for Stderr {
+ pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
+
+ pub fn is_ebadf(err: &io::Error) -> bool {
+- err.raw_os_error() == Some(wasi::EBADF.get() as i32)
++ err.raw_os_error() == Some(wasi::ERRNO_BADF.into())
+ }
+
+ pub fn panic_output() -> Option<impl io::Write> {
+diff --git a/src/libstd/sys/wasi/thread.rs b/src/libstd/sys/wasi/thread.rs
+index 6ce41420284..0986759b89b 100644
+--- a/src/libstd/sys/wasi/thread.rs
++++ b/src/libstd/sys/wasi/thread.rs
+@@ -4,22 +4,18 @@ use crate::mem;
+ use crate::sys::{unsupported, Void};
+ use crate::time::Duration;
+
+-use ::wasi::wasi_unstable as wasi;
+-
+ pub struct Thread(Void);
+
+ pub const DEFAULT_MIN_STACK_SIZE: usize = 4096;
+
+ impl Thread {
+ // unsafe: see thread::Builder::spawn_unchecked for safety requirements
+- pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>)
+- -> io::Result<Thread>
+- {
++ pub unsafe fn new(_stack: usize, _p: Box<dyn FnOnce()>) -> io::Result<Thread> {
+ unsupported()
+ }
+
+ pub fn yield_now() {
+- let ret = wasi::sched_yield();
++ let ret = unsafe { wasi::sched_yield() };
+ debug_assert_eq!(ret, Ok(()));
+ }
+
+@@ -33,32 +29,30 @@ impl Thread {
+
+ const USERDATA: wasi::Userdata = 0x0123_45678;
+
+- let clock = wasi::raw::__wasi_subscription_u_clock_t {
+- identifier: 0,
+- clock_id: wasi::CLOCK_MONOTONIC,
++ let clock = wasi::SubscriptionClock {
++ id: wasi::CLOCKID_MONOTONIC,
+ timeout: nanos as u64,
+ precision: 0,
+ flags: 0,
+ };
+
+- let in_ = [wasi::Subscription {
++ let in_ = wasi::Subscription {
+ userdata: USERDATA,
+- type_: wasi::EVENTTYPE_CLOCK,
+- u: wasi::raw::__wasi_subscription_u { clock: clock },
+- }];
+- let (res, event) = unsafe {
+- let mut out: [wasi::Event; 1] = mem::zeroed();
+- let res = wasi::poll_oneoff(&in_, &mut out);
+- (res, out[0])
++ r#type: wasi::EVENTTYPE_CLOCK,
++ u: wasi::SubscriptionU { clock },
+ };
+- match (res, event) {
+- (Ok(1), wasi::Event {
+- userdata: USERDATA,
+- error: 0,
+- type_: wasi::EVENTTYPE_CLOCK,
+- ..
+- }) => {}
+- _ => panic!("thread::sleep(): unexpected result of poll_oneoff"),
++ unsafe {
++ let mut event: wasi::Event = mem::zeroed();
++ let res = wasi::poll_oneoff(&in_, &mut event, 1);
++ match (res, event) {
++ (
++ Ok(1),
++ wasi::Event {
++ userdata: USERDATA, error: 0, r#type: wasi::EVENTTYPE_CLOCK, ..
++ },
++ ) => {}
++ _ => panic!("thread::sleep(): unexpected result of poll_oneoff"),
++ }
+ }
+ }
+
+@@ -69,6 +63,10 @@ impl Thread {
+
+ pub mod guard {
+ pub type Guard = !;
+- pub unsafe fn current() -> Option<Guard> { None }
+- pub unsafe fn init() -> Option<Guard> { None }
++ pub unsafe fn current() -> Option<Guard> {
++ None
++ }
++ pub unsafe fn init() -> Option<Guard> {
++ None
++ }
+ }
+diff --git a/src/libstd/sys/wasi/time.rs b/src/libstd/sys/wasi/time.rs
+index 4394a22f9c2..80ec317b5a2 100644
+--- a/src/libstd/sys/wasi/time.rs
++++ b/src/libstd/sys/wasi/time.rs
+@@ -1,5 +1,4 @@
+ use crate::time::Duration;
+-use ::wasi::wasi_unstable as wasi;
+
+ #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
+ pub struct Instant(Duration);
+@@ -10,19 +9,18 @@ pub struct SystemTime(Duration);
+ pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
+
+ fn current_time(clock: u32) -> Duration {
+- let ts = wasi::clock_time_get(
+- clock,
+- 1, // precision... seems ignored though?
+- ).unwrap();
+- Duration::new(
+- (ts / 1_000_000_000) as u64,
+- (ts % 1_000_000_000) as u32,
+- )
++ let ts = unsafe {
++ wasi::clock_time_get(
++ clock, 1, // precision... seems ignored though?
++ )
++ .unwrap()
++ };
++ Duration::new((ts / 1_000_000_000) as u64, (ts % 1_000_000_000) as u32)
+ }
+
+ impl Instant {
+ pub fn now() -> Instant {
+- Instant(current_time(wasi::CLOCK_MONOTONIC))
++ Instant(current_time(wasi::CLOCKID_MONOTONIC))
+ }
+
+ pub const fn zero() -> Instant {
+@@ -48,15 +46,14 @@ impl Instant {
+
+ impl SystemTime {
+ pub fn now() -> SystemTime {
+- SystemTime(current_time(wasi::CLOCK_REALTIME))
++ SystemTime(current_time(wasi::CLOCKID_REALTIME))
+ }
+
+ pub fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime {
+ SystemTime(Duration::from_nanos(ts))
+ }
+
+- pub fn sub_time(&self, other: &SystemTime)
+- -> Result<Duration, Duration> {
++ pub fn sub_time(&self, other: &SystemTime) -> Result<Duration, Duration> {
+ self.0.checked_sub(other.0).ok_or_else(|| other.0 - self.0)
+ }
+