Rollup merge of #66750 - alexcrichton:update-wasi, r=sfackler

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.
This commit is contained in:
Mazdak Farrokhzad 2019-12-03 19:41:46 +01:00 committed by GitHub
commit 1b83dcf2ee
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
12 changed files with 304 additions and 364 deletions

View File

@ -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",

View File

@ -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"]

View File

@ -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)
}
}

View File

@ -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 @@ fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
}
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 @@ fn metadata_at<P: AsRef<Path>>(&self, lookup_flags: u32, path: P) -> io::Result<
}
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 @@ fn remove_directory<P: AsRef<Path>>(&self, path: P) -> io::Result<()> {
///
/// [`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 @@ fn open_at<P: AsRef<Path>>(&self, file: &File, path: P) -> io::Result<File> {
///
/// [`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 @@ fn is_socket_stream(&self) -> bool {
///
/// [`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 @@ fn ino(&self) -> u64 {
/// 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())?)
}

View File

@ -8,8 +8,6 @@
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 @@ fn into_raw_fd(self) -> RawFd {
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()
}
}

View File

@ -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 @@ pub fn tell(&self) -> io::Result<u64> {
// 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 @@ pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
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 @@ pub fn open(
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 @@ pub fn filestat_set_times(
&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 @@ pub fn filestat_set_size(&self, size: u64) -> io::Result<()> {
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) }
}

View File

@ -15,20 +15,18 @@
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 @@ pub fn perm(&self) -> FilePermissions {
}
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 @@ pub fn is_symlink(&self) -> bool {
self.bits == wasi::FILETYPE_SYMBOLIC_LINK
}
pub fn bits(&self) -> wasi::FileType {
pub fn bits(&self) -> wasi::Filetype {
self.bits
}
}
@ -177,8 +173,7 @@ fn next(&mut self) -> Option<io::Result<DirEntry>> {
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 @@ pub fn file_name(&self) -> OsString {
}
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 @@ pub fn ino(&self) -> wasi::Inode {
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 @@ pub fn write(&mut self, write: bool) {
}
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 @@ fn oflag(&mut self, bit: wasi::OFlags, set: bool) {
}
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 @@ fn rights_base(&self) -> wasi::Rights {
// 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 @@ fn rights_inheriting(&self) -> wasi::Rights {
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 @@ pub fn file_attr(&self) -> io::Result<FileAttr> {
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 @@ pub fn read_link(&self, file: &Path) -> io::Result<PathBuf> {
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 @@ pub fn new() -> 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"))
}

View File

@ -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 @@ pub fn as_slice(&self) -> &[u8] {
#[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,

View File

@ -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())
}

View File

@ -2,8 +2,6 @@
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 @@ pub fn read(&self, data: &mut [u8]) -> io::Result<usize> {
}
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 @@ pub fn write(&self, data: &[u8]) -> io::Result<usize> {
}
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 @@ pub fn write(&self, data: &[u8]) -> io::Result<usize> {
}
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 @@ fn flush(&mut self) -> io::Result<()> {
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> {

View File

@ -4,22 +4,18 @@
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 @@ pub fn sleep(dur: Duration) {
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 @@ pub fn join(self) {
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
}
}

View File

@ -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 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 @@ pub fn checked_sub_duration(&self, other: &Duration) -> Option<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)
}