Rollup merge of #63676 - newpavlov:wasi, r=alexcrichton
Use wasi crate for Core API Blocked by: CraneStation/rust-wasi#5 Blocks: rust-lang/libc#1461 cc @sunfishcode @alexcrichton
This commit is contained in:
commit
5b995397db
14 changed files with 339 additions and 433 deletions
12
Cargo.lock
12
Cargo.lock
|
@ -3870,6 +3870,7 @@ dependencies = [
|
||||||
"rustc_msan",
|
"rustc_msan",
|
||||||
"rustc_tsan",
|
"rustc_tsan",
|
||||||
"unwind",
|
"unwind",
|
||||||
|
"wasi",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
@ -4686,6 +4687,17 @@ dependencies = [
|
||||||
"try-lock",
|
"try-lock",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "wasi"
|
||||||
|
version = "0.7.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b89c3ce4ce14bdc6fb6beaf9ec7928ca331de5df7e5ea278375642a2f478570d"
|
||||||
|
dependencies = [
|
||||||
|
"compiler_builtins",
|
||||||
|
"rustc-std-workspace-alloc",
|
||||||
|
"rustc-std-workspace-core",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "winapi"
|
name = "winapi"
|
||||||
version = "0.2.8"
|
version = "0.2.8"
|
||||||
|
|
|
@ -56,6 +56,9 @@ dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] }
|
||||||
[target.x86_64-fortanix-unknown-sgx.dependencies]
|
[target.x86_64-fortanix-unknown-sgx.dependencies]
|
||||||
fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }
|
fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }
|
||||||
|
|
||||||
|
[target.wasm32-wasi.dependencies]
|
||||||
|
wasi = { version = "0.7.0", features = ['rustc-dep-of-std', 'alloc'] }
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
cc = "1.0"
|
cc = "1.0"
|
||||||
|
|
||||||
|
|
|
@ -1,11 +1,10 @@
|
||||||
use crate::ffi::CStr;
|
|
||||||
use crate::io;
|
|
||||||
use crate::sys::cvt_wasi;
|
|
||||||
use crate::ffi::OsString;
|
use crate::ffi::OsString;
|
||||||
use crate::marker::PhantomData;
|
use crate::marker::PhantomData;
|
||||||
use crate::os::wasi::ffi::OsStringExt;
|
use crate::os::wasi::ffi::OsStringExt;
|
||||||
use crate::vec;
|
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) {
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -19,32 +18,18 @@ pub struct Args {
|
||||||
|
|
||||||
/// Returns the command line arguments
|
/// Returns the command line arguments
|
||||||
pub fn args() -> Args {
|
pub fn args() -> Args {
|
||||||
maybe_args().unwrap_or_else(|_| {
|
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 {
|
Args {
|
||||||
iter: Vec::new().into_iter(),
|
iter: buf.into_iter(),
|
||||||
_dont_send_or_sync_me: PhantomData
|
_dont_send_or_sync_me: PhantomData
|
||||||
}
|
}
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
fn maybe_args() -> io::Result<Args> {
|
|
||||||
unsafe {
|
|
||||||
let (mut argc, mut argv_buf_size) = (0, 0);
|
|
||||||
cvt_wasi(libc::__wasi_args_sizes_get(&mut argc, &mut argv_buf_size))?;
|
|
||||||
|
|
||||||
let mut argc = vec![core::ptr::null_mut::<libc::c_char>(); argc];
|
|
||||||
let mut argv_buf = vec![0; argv_buf_size];
|
|
||||||
cvt_wasi(libc::__wasi_args_get(argc.as_mut_ptr(), argv_buf.as_mut_ptr()))?;
|
|
||||||
|
|
||||||
let args = argc.into_iter()
|
|
||||||
.map(|ptr| CStr::from_ptr(ptr).to_bytes().to_vec())
|
|
||||||
.map(|bytes| OsString::from_vec(bytes))
|
|
||||||
.collect::<Vec<_>>();
|
|
||||||
Ok(Args {
|
|
||||||
iter: args.into_iter(),
|
|
||||||
_dont_send_or_sync_me: PhantomData,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Args {
|
impl Args {
|
||||||
|
|
|
@ -8,6 +8,8 @@ use crate::os::wasi::ffi::OsStrExt;
|
||||||
use crate::path::{Path, PathBuf};
|
use crate::path::{Path, PathBuf};
|
||||||
use crate::sys_common::{AsInner, AsInnerMut, FromInner};
|
use crate::sys_common::{AsInner, AsInnerMut, FromInner};
|
||||||
|
|
||||||
|
use ::wasi::wasi_unstable as wasi;
|
||||||
|
|
||||||
/// WASI-specific extensions to [`File`].
|
/// WASI-specific extensions to [`File`].
|
||||||
///
|
///
|
||||||
/// [`File`]: ../../../../std/fs/struct.File.html
|
/// [`File`]: ../../../../std/fs/struct.File.html
|
||||||
|
@ -336,16 +338,16 @@ pub trait FileTypeExt {
|
||||||
|
|
||||||
impl FileTypeExt for fs::FileType {
|
impl FileTypeExt for fs::FileType {
|
||||||
fn is_block_device(&self) -> bool {
|
fn is_block_device(&self) -> bool {
|
||||||
self.as_inner().bits() == libc::__WASI_FILETYPE_BLOCK_DEVICE
|
self.as_inner().bits() == wasi::FILETYPE_BLOCK_DEVICE
|
||||||
}
|
}
|
||||||
fn is_character_device(&self) -> bool {
|
fn is_character_device(&self) -> bool {
|
||||||
self.as_inner().bits() == libc::__WASI_FILETYPE_CHARACTER_DEVICE
|
self.as_inner().bits() == wasi::FILETYPE_CHARACTER_DEVICE
|
||||||
}
|
}
|
||||||
fn is_socket_dgram(&self) -> bool {
|
fn is_socket_dgram(&self) -> bool {
|
||||||
self.as_inner().bits() == libc::__WASI_FILETYPE_SOCKET_DGRAM
|
self.as_inner().bits() == wasi::FILETYPE_SOCKET_DGRAM
|
||||||
}
|
}
|
||||||
fn is_socket_stream(&self) -> bool {
|
fn is_socket_stream(&self) -> bool {
|
||||||
self.as_inner().bits() == libc::__WASI_FILETYPE_SOCKET_STREAM
|
self.as_inner().bits() == wasi::FILETYPE_SOCKET_STREAM
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,6 +8,8 @@ use crate::sys;
|
||||||
use crate::net;
|
use crate::net;
|
||||||
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
use crate::sys_common::{AsInner, FromInner, IntoInner};
|
||||||
|
|
||||||
|
use ::wasi::wasi_unstable as wasi;
|
||||||
|
|
||||||
/// Raw file descriptors.
|
/// Raw file descriptors.
|
||||||
pub type RawFd = u32;
|
pub type RawFd = u32;
|
||||||
|
|
||||||
|
@ -125,18 +127,18 @@ impl IntoRawFd for fs::File {
|
||||||
|
|
||||||
impl AsRawFd for io::Stdin {
|
impl AsRawFd for io::Stdin {
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
libc::STDIN_FILENO as u32
|
wasi::STDIN_FD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRawFd for io::Stdout {
|
impl AsRawFd for io::Stdout {
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
libc::STDOUT_FILENO as u32
|
wasi::STDOUT_FD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl AsRawFd for io::Stderr {
|
impl AsRawFd for io::Stderr {
|
||||||
fn as_raw_fd(&self) -> RawFd {
|
fn as_raw_fd(&self) -> RawFd {
|
||||||
libc::STDERR_FILENO as u32
|
wasi::STDERR_FD
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,348 +3,248 @@
|
||||||
use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
|
use crate::io::{self, IoSlice, IoSliceMut, SeekFrom};
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::net::Shutdown;
|
use crate::net::Shutdown;
|
||||||
use crate::sys::cvt_wasi;
|
use super::err2io;
|
||||||
use libc::{self, c_char, c_void};
|
use ::wasi::wasi_unstable as wasi;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct WasiFd {
|
pub struct WasiFd {
|
||||||
fd: libc::__wasi_fd_t,
|
fd: wasi::Fd,
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: these should probably all be fancier structs, builders, enums, etc
|
fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::IoVec] {
|
||||||
pub type LookupFlags = u32;
|
|
||||||
pub type FdFlags = u16;
|
|
||||||
pub type Advice = u8;
|
|
||||||
pub type Rights = u64;
|
|
||||||
pub type Oflags = u16;
|
|
||||||
pub type DirCookie = u64;
|
|
||||||
pub type Timestamp = u64;
|
|
||||||
pub type FstFlags = u16;
|
|
||||||
pub type RiFlags = u16;
|
|
||||||
pub type RoFlags = u16;
|
|
||||||
pub type SiFlags = u16;
|
|
||||||
|
|
||||||
fn iovec(a: &mut [IoSliceMut<'_>]) -> (*const libc::__wasi_iovec_t, usize) {
|
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
mem::size_of::<IoSliceMut<'_>>(),
|
mem::size_of::<IoSliceMut<'_>>(),
|
||||||
mem::size_of::<libc::__wasi_iovec_t>()
|
mem::size_of::<wasi::IoVec>()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
mem::align_of::<IoSliceMut<'_>>(),
|
mem::align_of::<IoSliceMut<'_>>(),
|
||||||
mem::align_of::<libc::__wasi_iovec_t>()
|
mem::align_of::<wasi::IoVec>()
|
||||||
);
|
);
|
||||||
(a.as_ptr() as *const libc::__wasi_iovec_t, a.len())
|
/// SAFETY: `IoSliceMut` and `IoVec` have exactly the same memory layout
|
||||||
|
unsafe { mem::transmute(a) }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn ciovec(a: &[IoSlice<'_>]) -> (*const libc::__wasi_ciovec_t, usize) {
|
fn ciovec<'a>(a: &'a [IoSlice<'_>]) -> &'a [wasi::CIoVec] {
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
mem::size_of::<IoSlice<'_>>(),
|
mem::size_of::<IoSlice<'_>>(),
|
||||||
mem::size_of::<libc::__wasi_ciovec_t>()
|
mem::size_of::<wasi::CIoVec>()
|
||||||
);
|
);
|
||||||
assert_eq!(
|
assert_eq!(
|
||||||
mem::align_of::<IoSlice<'_>>(),
|
mem::align_of::<IoSlice<'_>>(),
|
||||||
mem::align_of::<libc::__wasi_ciovec_t>()
|
mem::align_of::<wasi::CIoVec>()
|
||||||
);
|
);
|
||||||
(a.as_ptr() as *const libc::__wasi_ciovec_t, a.len())
|
/// SAFETY: `IoSlice` and `CIoVec` have exactly the same memory layout
|
||||||
|
unsafe { mem::transmute(a) }
|
||||||
}
|
}
|
||||||
|
|
||||||
impl WasiFd {
|
impl WasiFd {
|
||||||
pub unsafe fn from_raw(fd: libc::__wasi_fd_t) -> WasiFd {
|
pub unsafe fn from_raw(fd: wasi::Fd) -> WasiFd {
|
||||||
WasiFd { fd }
|
WasiFd { fd }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn into_raw(self) -> libc::__wasi_fd_t {
|
pub fn into_raw(self) -> wasi::Fd {
|
||||||
let ret = self.fd;
|
let ret = self.fd;
|
||||||
mem::forget(self);
|
mem::forget(self);
|
||||||
ret
|
ret
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_raw(&self) -> libc::__wasi_fd_t {
|
pub fn as_raw(&self) -> wasi::Fd {
|
||||||
self.fd
|
self.fd
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn datasync(&self) -> io::Result<()> {
|
pub fn datasync(&self) -> io::Result<()> {
|
||||||
cvt_wasi(unsafe { libc::__wasi_fd_datasync(self.fd) })
|
unsafe { wasi::fd_datasync(self.fd).map_err(err2io) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
|
pub fn pread(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
|
||||||
let mut read = 0;
|
unsafe { wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(err2io) }
|
||||||
let (ptr, len) = iovec(bufs);
|
|
||||||
cvt_wasi(unsafe { libc::__wasi_fd_pread(self.fd, ptr, len, offset, &mut read) })?;
|
|
||||||
Ok(read)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
|
pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
|
||||||
let mut read = 0;
|
unsafe { wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(err2io) }
|
||||||
let (ptr, len) = ciovec(bufs);
|
|
||||||
cvt_wasi(unsafe { libc::__wasi_fd_pwrite(self.fd, ptr, len, offset, &mut read) })?;
|
|
||||||
Ok(read)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||||
let mut read = 0;
|
unsafe { wasi::fd_read(self.fd, iovec(bufs)).map_err(err2io) }
|
||||||
let (ptr, len) = iovec(bufs);
|
|
||||||
cvt_wasi(unsafe { libc::__wasi_fd_read(self.fd, ptr, len, &mut read) })?;
|
|
||||||
Ok(read)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||||
let mut read = 0;
|
unsafe { wasi::fd_write(self.fd, ciovec(bufs)).map_err(err2io) }
|
||||||
let (ptr, len) = ciovec(bufs);
|
|
||||||
cvt_wasi(unsafe { libc::__wasi_fd_write(self.fd, ptr, len, &mut read) })?;
|
|
||||||
Ok(read)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
|
pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
|
||||||
let (whence, offset) = match pos {
|
let (whence, offset) = match pos {
|
||||||
SeekFrom::Start(pos) => (libc::__WASI_WHENCE_SET, pos as i64),
|
SeekFrom::Start(pos) => (wasi::WHENCE_SET, pos as i64),
|
||||||
SeekFrom::End(pos) => (libc::__WASI_WHENCE_END, pos),
|
SeekFrom::End(pos) => (wasi::WHENCE_END, pos),
|
||||||
SeekFrom::Current(pos) => (libc::__WASI_WHENCE_CUR, pos),
|
SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos),
|
||||||
};
|
};
|
||||||
let mut pos = 0;
|
unsafe { wasi::fd_seek(self.fd, offset, whence).map_err(err2io) }
|
||||||
cvt_wasi(unsafe { libc::__wasi_fd_seek(self.fd, offset, whence, &mut pos) })?;
|
|
||||||
Ok(pos)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn tell(&self) -> io::Result<u64> {
|
pub fn tell(&self) -> io::Result<u64> {
|
||||||
let mut pos = 0;
|
unsafe { wasi::fd_tell(self.fd).map_err(err2io) }
|
||||||
cvt_wasi(unsafe { libc::__wasi_fd_tell(self.fd, &mut pos) })?;
|
|
||||||
Ok(pos)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: __wasi_fd_fdstat_get
|
// FIXME: __wasi_fd_fdstat_get
|
||||||
|
|
||||||
pub fn set_flags(&self, flags: FdFlags) -> io::Result<()> {
|
pub fn set_flags(&self, flags: wasi::FdFlags) -> io::Result<()> {
|
||||||
cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_flags(self.fd, flags) })
|
unsafe { wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_rights(&self, base: Rights, inheriting: Rights) -> io::Result<()> {
|
pub fn set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()> {
|
||||||
cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_rights(self.fd, base, inheriting) })
|
unsafe { wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(err2io) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sync(&self) -> io::Result<()> {
|
pub fn sync(&self) -> io::Result<()> {
|
||||||
cvt_wasi(unsafe { libc::__wasi_fd_sync(self.fd) })
|
unsafe { wasi::fd_sync(self.fd).map_err(err2io) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn advise(&self, offset: u64, len: u64, advice: Advice) -> io::Result<()> {
|
pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> {
|
||||||
cvt_wasi(unsafe { libc::__wasi_fd_advise(self.fd, offset, len, advice as u8) })
|
unsafe { wasi::fd_advise(self.fd, offset, len, advice).map_err(err2io) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
|
pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
|
||||||
cvt_wasi(unsafe { libc::__wasi_fd_allocate(self.fd, offset, len) })
|
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: &[u8]) -> io::Result<()> {
|
||||||
cvt_wasi(unsafe {
|
unsafe { wasi::path_create_directory(self.fd, path).map_err(err2io) }
|
||||||
libc::__wasi_path_create_directory(self.fd, path.as_ptr() as *const c_char, path.len())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn link(
|
pub fn link(
|
||||||
&self,
|
&self,
|
||||||
old_flags: LookupFlags,
|
old_flags: wasi::LookupFlags,
|
||||||
old_path: &[u8],
|
old_path: &[u8],
|
||||||
new_fd: &WasiFd,
|
new_fd: &WasiFd,
|
||||||
new_path: &[u8],
|
new_path: &[u8],
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
cvt_wasi(unsafe {
|
unsafe {
|
||||||
libc::__wasi_path_link(
|
wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path)
|
||||||
self.fd,
|
.map_err(err2io)
|
||||||
old_flags,
|
}
|
||||||
old_path.as_ptr() as *const c_char,
|
|
||||||
old_path.len(),
|
|
||||||
new_fd.fd,
|
|
||||||
new_path.as_ptr() as *const c_char,
|
|
||||||
new_path.len(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn open(
|
pub fn open(
|
||||||
&self,
|
&self,
|
||||||
dirflags: LookupFlags,
|
dirflags: wasi::LookupFlags,
|
||||||
path: &[u8],
|
path: &[u8],
|
||||||
oflags: Oflags,
|
oflags: wasi::OFlags,
|
||||||
fs_rights_base: Rights,
|
fs_rights_base: wasi::Rights,
|
||||||
fs_rights_inheriting: Rights,
|
fs_rights_inheriting: wasi::Rights,
|
||||||
fs_flags: FdFlags,
|
fs_flags: wasi::FdFlags,
|
||||||
) -> io::Result<WasiFd> {
|
) -> io::Result<WasiFd> {
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut fd = 0;
|
wasi::path_open(
|
||||||
cvt_wasi(libc::__wasi_path_open(
|
|
||||||
self.fd,
|
self.fd,
|
||||||
dirflags,
|
dirflags,
|
||||||
path.as_ptr() as *const c_char,
|
path,
|
||||||
path.len(),
|
|
||||||
oflags,
|
oflags,
|
||||||
fs_rights_base,
|
fs_rights_base,
|
||||||
fs_rights_inheriting,
|
fs_rights_inheriting,
|
||||||
fs_flags,
|
fs_flags,
|
||||||
&mut fd,
|
).map(|fd| WasiFd::from_raw(fd)).map_err(err2io)
|
||||||
))?;
|
|
||||||
Ok(WasiFd::from_raw(fd))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readdir(&self, buf: &mut [u8], cookie: DirCookie) -> io::Result<usize> {
|
pub fn readdir(&self, buf: &mut [u8], cookie: wasi::DirCookie) -> io::Result<usize> {
|
||||||
let mut used = 0;
|
unsafe { wasi::fd_readdir(self.fd, buf, cookie).map_err(err2io) }
|
||||||
cvt_wasi(unsafe {
|
|
||||||
libc::__wasi_fd_readdir(
|
|
||||||
self.fd,
|
|
||||||
buf.as_mut_ptr() as *mut c_void,
|
|
||||||
buf.len(),
|
|
||||||
cookie,
|
|
||||||
&mut used,
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
Ok(used)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readlink(&self, path: &[u8], buf: &mut [u8]) -> io::Result<usize> {
|
pub fn readlink(&self, path: &[u8], buf: &mut [u8]) -> io::Result<usize> {
|
||||||
let mut used = 0;
|
unsafe { wasi::path_readlink(self.fd, path, buf).map_err(err2io) }
|
||||||
cvt_wasi(unsafe {
|
|
||||||
libc::__wasi_path_readlink(
|
|
||||||
self.fd,
|
|
||||||
path.as_ptr() as *const c_char,
|
|
||||||
path.len(),
|
|
||||||
buf.as_mut_ptr() as *mut c_char,
|
|
||||||
buf.len(),
|
|
||||||
&mut used,
|
|
||||||
)
|
|
||||||
})?;
|
|
||||||
Ok(used)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rename(&self, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8]) -> io::Result<()> {
|
pub fn rename(&self, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8]) -> io::Result<()> {
|
||||||
cvt_wasi(unsafe {
|
unsafe {
|
||||||
libc::__wasi_path_rename(
|
wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io)
|
||||||
self.fd,
|
}
|
||||||
old_path.as_ptr() as *const c_char,
|
|
||||||
old_path.len(),
|
|
||||||
new_fd.fd,
|
|
||||||
new_path.as_ptr() as *const c_char,
|
|
||||||
new_path.len(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filestat_get(&self, buf: *mut libc::__wasi_filestat_t) -> io::Result<()> {
|
pub fn filestat_get(&self) -> io::Result<wasi::FileStat> {
|
||||||
cvt_wasi(unsafe { libc::__wasi_fd_filestat_get(self.fd, buf) })
|
unsafe { wasi::fd_filestat_get(self.fd).map_err(err2io) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filestat_set_times(
|
pub fn filestat_set_times(
|
||||||
&self,
|
&self,
|
||||||
atim: Timestamp,
|
atim: wasi::Timestamp,
|
||||||
mtim: Timestamp,
|
mtim: wasi::Timestamp,
|
||||||
fstflags: FstFlags,
|
fstflags: wasi::FstFlags,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_times(self.fd, atim, mtim, fstflags) })
|
unsafe {
|
||||||
|
wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags).map_err(err2io)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn filestat_set_size(&self, size: u64) -> io::Result<()> {
|
pub fn filestat_set_size(&self, size: u64) -> io::Result<()> {
|
||||||
cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_size(self.fd, size) })
|
unsafe { wasi::fd_filestat_set_size(self.fd, size).map_err(err2io) }
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn path_filestat_get(
|
pub fn path_filestat_get(
|
||||||
&self,
|
&self,
|
||||||
flags: LookupFlags,
|
flags: wasi::LookupFlags,
|
||||||
path: &[u8],
|
path: &[u8],
|
||||||
buf: *mut libc::__wasi_filestat_t,
|
) -> io::Result<wasi::FileStat> {
|
||||||
) -> io::Result<()> {
|
unsafe { wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) }
|
||||||
cvt_wasi(unsafe {
|
|
||||||
libc::__wasi_path_filestat_get(
|
|
||||||
self.fd,
|
|
||||||
flags,
|
|
||||||
path.as_ptr() as *const c_char,
|
|
||||||
path.len(),
|
|
||||||
buf,
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn path_filestat_set_times(
|
pub fn path_filestat_set_times(
|
||||||
&self,
|
&self,
|
||||||
flags: LookupFlags,
|
flags: wasi::LookupFlags,
|
||||||
path: &[u8],
|
path: &[u8],
|
||||||
atim: Timestamp,
|
atim: wasi::Timestamp,
|
||||||
mtim: Timestamp,
|
mtim: wasi::Timestamp,
|
||||||
fstflags: FstFlags,
|
fstflags: wasi::FstFlags,
|
||||||
) -> io::Result<()> {
|
) -> io::Result<()> {
|
||||||
cvt_wasi(unsafe {
|
unsafe {
|
||||||
libc::__wasi_path_filestat_set_times(
|
wasi::path_filestat_set_times(
|
||||||
self.fd,
|
self.fd,
|
||||||
flags,
|
flags,
|
||||||
path.as_ptr() as *const c_char,
|
path,
|
||||||
path.len(),
|
|
||||||
atim,
|
atim,
|
||||||
mtim,
|
mtim,
|
||||||
fstflags,
|
fstflags,
|
||||||
)
|
).map_err(err2io)
|
||||||
})
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn symlink(&self, old_path: &[u8], new_path: &[u8]) -> io::Result<()> {
|
pub fn symlink(&self, old_path: &[u8], new_path: &[u8]) -> io::Result<()> {
|
||||||
cvt_wasi(unsafe {
|
unsafe { wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) }
|
||||||
libc::__wasi_path_symlink(
|
|
||||||
old_path.as_ptr() as *const c_char,
|
|
||||||
old_path.len(),
|
|
||||||
self.fd,
|
|
||||||
new_path.as_ptr() as *const c_char,
|
|
||||||
new_path.len(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unlink_file(&self, path: &[u8]) -> io::Result<()> {
|
pub fn unlink_file(&self, path: &[u8]) -> io::Result<()> {
|
||||||
cvt_wasi(unsafe {
|
unsafe { wasi::path_unlink_file(self.fd, path).map_err(err2io) }
|
||||||
libc::__wasi_path_unlink_file(self.fd, path.as_ptr() as *const c_char, path.len())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn remove_directory(&self, path: &[u8]) -> io::Result<()> {
|
pub fn remove_directory(&self, path: &[u8]) -> io::Result<()> {
|
||||||
cvt_wasi(unsafe {
|
unsafe { wasi::path_remove_directory(self.fd, path).map_err(err2io) }
|
||||||
libc::__wasi_path_remove_directory(self.fd, path.as_ptr() as *const c_char, path.len())
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sock_recv(
|
pub fn sock_recv(
|
||||||
&self,
|
&self,
|
||||||
ri_data: &mut [IoSliceMut<'_>],
|
ri_data: &mut [IoSliceMut<'_>],
|
||||||
ri_flags: RiFlags,
|
ri_flags: wasi::RiFlags,
|
||||||
) -> io::Result<(usize, RoFlags)> {
|
) -> io::Result<(usize, wasi::RoFlags)> {
|
||||||
let mut ro_datalen = 0;
|
unsafe { wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(err2io) }
|
||||||
let mut ro_flags = 0;
|
|
||||||
let (ptr, len) = iovec(ri_data);
|
|
||||||
cvt_wasi(unsafe {
|
|
||||||
libc::__wasi_sock_recv(self.fd, ptr, len, ri_flags, &mut ro_datalen, &mut ro_flags)
|
|
||||||
})?;
|
|
||||||
Ok((ro_datalen, ro_flags))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: SiFlags) -> io::Result<usize> {
|
pub fn sock_send(&self, si_data: &[IoSlice<'_>], si_flags: wasi::SiFlags) -> io::Result<usize> {
|
||||||
let mut so_datalen = 0;
|
unsafe { wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(err2io) }
|
||||||
let (ptr, len) = ciovec(si_data);
|
|
||||||
cvt_wasi(unsafe { libc::__wasi_sock_send(self.fd, ptr, len, si_flags, &mut so_datalen) })?;
|
|
||||||
Ok(so_datalen)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> {
|
pub fn sock_shutdown(&self, how: Shutdown) -> io::Result<()> {
|
||||||
let how = match how {
|
let how = match how {
|
||||||
Shutdown::Read => libc::__WASI_SHUT_RD,
|
Shutdown::Read => wasi::SHUT_RD,
|
||||||
Shutdown::Write => libc::__WASI_SHUT_WR,
|
Shutdown::Write => wasi::SHUT_WR,
|
||||||
Shutdown::Both => libc::__WASI_SHUT_WR | libc::__WASI_SHUT_RD,
|
Shutdown::Both => wasi::SHUT_WR | wasi::SHUT_RD,
|
||||||
};
|
};
|
||||||
cvt_wasi(unsafe { libc::__wasi_sock_shutdown(self.fd, how) })?;
|
unsafe { wasi::sock_shutdown(self.fd, how).map_err(err2io) }
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for WasiFd {
|
impl Drop for WasiFd {
|
||||||
fn drop(&mut self) {
|
fn drop(&mut self) {
|
||||||
unsafe {
|
|
||||||
// FIXME: can we handle the return code here even though we can't on
|
// FIXME: can we handle the return code here even though we can't on
|
||||||
// unix?
|
// unix?
|
||||||
libc::__wasi_fd_close(self.fd);
|
let _ = unsafe { wasi::fd_close(self.fd) };
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,7 @@ use crate::os::wasi::ffi::{OsStrExt, OsStringExt};
|
||||||
use crate::path::{Path, PathBuf};
|
use crate::path::{Path, PathBuf};
|
||||||
use crate::ptr;
|
use crate::ptr;
|
||||||
use crate::sync::Arc;
|
use crate::sync::Arc;
|
||||||
use crate::sys::fd::{DirCookie, WasiFd};
|
use crate::sys::fd::WasiFd;
|
||||||
use crate::sys::time::SystemTime;
|
use crate::sys::time::SystemTime;
|
||||||
use crate::sys::unsupported;
|
use crate::sys::unsupported;
|
||||||
use crate::sys_common::FromInner;
|
use crate::sys_common::FromInner;
|
||||||
|
@ -15,18 +15,20 @@ use crate::sys_common::FromInner;
|
||||||
pub use crate::sys_common::fs::copy;
|
pub use crate::sys_common::fs::copy;
|
||||||
pub use crate::sys_common::fs::remove_dir_all;
|
pub use crate::sys_common::fs::remove_dir_all;
|
||||||
|
|
||||||
|
use ::wasi::wasi_unstable as wasi;
|
||||||
|
|
||||||
pub struct File {
|
pub struct File {
|
||||||
fd: WasiFd,
|
fd: WasiFd,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub struct FileAttr {
|
pub struct FileAttr {
|
||||||
meta: libc::__wasi_filestat_t,
|
meta: wasi::FileStat,
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct ReadDir {
|
pub struct ReadDir {
|
||||||
inner: Arc<ReadDirInner>,
|
inner: Arc<ReadDirInner>,
|
||||||
cookie: Option<DirCookie>,
|
cookie: Option<wasi::DirCookie>,
|
||||||
buf: Vec<u8>,
|
buf: Vec<u8>,
|
||||||
offset: usize,
|
offset: usize,
|
||||||
cap: usize,
|
cap: usize,
|
||||||
|
@ -38,7 +40,7 @@ struct ReadDirInner {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct DirEntry {
|
pub struct DirEntry {
|
||||||
meta: libc::__wasi_dirent_t,
|
meta: wasi::Dirent,
|
||||||
name: Vec<u8>,
|
name: Vec<u8>,
|
||||||
inner: Arc<ReadDirInner>,
|
inner: Arc<ReadDirInner>,
|
||||||
}
|
}
|
||||||
|
@ -47,11 +49,11 @@ pub struct DirEntry {
|
||||||
pub struct OpenOptions {
|
pub struct OpenOptions {
|
||||||
read: bool,
|
read: bool,
|
||||||
write: bool,
|
write: bool,
|
||||||
dirflags: libc::__wasi_lookupflags_t,
|
dirflags: wasi::LookupFlags,
|
||||||
fdflags: libc::__wasi_fdflags_t,
|
fdflags: wasi::FdFlags,
|
||||||
oflags: libc::__wasi_oflags_t,
|
oflags: wasi::OFlags,
|
||||||
rights_base: Option<libc::__wasi_rights_t>,
|
rights_base: Option<wasi::Rights>,
|
||||||
rights_inheriting: Option<libc::__wasi_rights_t>,
|
rights_inheriting: Option<wasi::Rights>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||||
|
@ -61,19 +63,13 @@ pub struct FilePermissions {
|
||||||
|
|
||||||
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
|
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
|
||||||
pub struct FileType {
|
pub struct FileType {
|
||||||
bits: libc::__wasi_filetype_t,
|
bits: wasi::FileType,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct DirBuilder {}
|
pub struct DirBuilder {}
|
||||||
|
|
||||||
impl FileAttr {
|
impl FileAttr {
|
||||||
fn zero() -> FileAttr {
|
|
||||||
FileAttr {
|
|
||||||
meta: unsafe { mem::zeroed() },
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn size(&self) -> u64 {
|
pub fn size(&self) -> u64 {
|
||||||
self.meta.st_size
|
self.meta.st_size
|
||||||
}
|
}
|
||||||
|
@ -101,7 +97,7 @@ impl FileAttr {
|
||||||
Ok(SystemTime::from_wasi_timestamp(self.meta.st_ctim))
|
Ok(SystemTime::from_wasi_timestamp(self.meta.st_ctim))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn as_wasi(&self) -> &libc::__wasi_filestat_t {
|
pub fn as_wasi(&self) -> &wasi::FileStat {
|
||||||
&self.meta
|
&self.meta
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -118,18 +114,18 @@ impl FilePermissions {
|
||||||
|
|
||||||
impl FileType {
|
impl FileType {
|
||||||
pub fn is_dir(&self) -> bool {
|
pub fn is_dir(&self) -> bool {
|
||||||
self.bits == libc::__WASI_FILETYPE_DIRECTORY
|
self.bits == wasi::FILETYPE_DIRECTORY
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_file(&self) -> bool {
|
pub fn is_file(&self) -> bool {
|
||||||
self.bits == libc::__WASI_FILETYPE_REGULAR_FILE
|
self.bits == wasi::FILETYPE_REGULAR_FILE
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_symlink(&self) -> bool {
|
pub fn is_symlink(&self) -> bool {
|
||||||
self.bits == libc::__WASI_FILETYPE_SYMBOLIC_LINK
|
self.bits == wasi::FILETYPE_SYMBOLIC_LINK
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn bits(&self) -> libc::__wasi_filetype_t {
|
pub fn bits(&self) -> wasi::FileType {
|
||||||
self.bits
|
self.bits
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -173,7 +169,7 @@ impl Iterator for ReadDir {
|
||||||
// must have been truncated at the end of the buffer, so reset our
|
// must have been truncated at the end of the buffer, so reset our
|
||||||
// offset so we can go back and reread into the buffer, picking up
|
// offset so we can go back and reread into the buffer, picking up
|
||||||
// where we last left off.
|
// where we last left off.
|
||||||
let dirent_size = mem::size_of::<libc::__wasi_dirent_t>();
|
let dirent_size = mem::size_of::<wasi::Dirent>();
|
||||||
if data.len() < dirent_size {
|
if data.len() < dirent_size {
|
||||||
assert!(self.cookie.is_some());
|
assert!(self.cookie.is_some());
|
||||||
assert!(self.buf.len() >= dirent_size);
|
assert!(self.buf.len() >= dirent_size);
|
||||||
|
@ -182,7 +178,7 @@ impl Iterator for ReadDir {
|
||||||
}
|
}
|
||||||
let (dirent, data) = data.split_at(dirent_size);
|
let (dirent, data) = data.split_at(dirent_size);
|
||||||
let dirent =
|
let dirent =
|
||||||
unsafe { ptr::read_unaligned(dirent.as_ptr() as *const libc::__wasi_dirent_t) };
|
unsafe { ptr::read_unaligned(dirent.as_ptr() as *const wasi::Dirent) };
|
||||||
|
|
||||||
// If the file name was truncated, then we need to reinvoke
|
// If the file name was truncated, then we need to reinvoke
|
||||||
// `readdir` so we truncate our buffer to start over and reread this
|
// `readdir` so we truncate our buffer to start over and reread this
|
||||||
|
@ -241,7 +237,7 @@ impl DirEntry {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn ino(&self) -> libc::__wasi_inode_t {
|
pub fn ino(&self) -> wasi::Inode {
|
||||||
self.meta.d_ino
|
self.meta.d_ino
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -249,7 +245,7 @@ impl DirEntry {
|
||||||
impl OpenOptions {
|
impl OpenOptions {
|
||||||
pub fn new() -> OpenOptions {
|
pub fn new() -> OpenOptions {
|
||||||
let mut base = OpenOptions::default();
|
let mut base = OpenOptions::default();
|
||||||
base.dirflags = libc::__WASI_LOOKUP_SYMLINK_FOLLOW;
|
base.dirflags = wasi::LOOKUP_SYMLINK_FOLLOW;
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -262,23 +258,23 @@ impl OpenOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn truncate(&mut self, truncate: bool) {
|
pub fn truncate(&mut self, truncate: bool) {
|
||||||
self.oflag(libc::__WASI_O_TRUNC, truncate);
|
self.oflag(wasi::O_TRUNC, truncate);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create(&mut self, create: bool) {
|
pub fn create(&mut self, create: bool) {
|
||||||
self.oflag(libc::__WASI_O_CREAT, create);
|
self.oflag(wasi::O_CREAT, create);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn create_new(&mut self, create_new: bool) {
|
pub fn create_new(&mut self, create_new: bool) {
|
||||||
self.oflag(libc::__WASI_O_EXCL, create_new);
|
self.oflag(wasi::O_EXCL, create_new);
|
||||||
self.oflag(libc::__WASI_O_CREAT, create_new);
|
self.oflag(wasi::O_CREAT, create_new);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn directory(&mut self, directory: bool) {
|
pub fn directory(&mut self, directory: bool) {
|
||||||
self.oflag(libc::__WASI_O_DIRECTORY, directory);
|
self.oflag(wasi::O_DIRECTORY, directory);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn oflag(&mut self, bit: libc::__wasi_oflags_t, set: bool) {
|
fn oflag(&mut self, bit: wasi::OFlags, set: bool) {
|
||||||
if set {
|
if set {
|
||||||
self.oflags |= bit;
|
self.oflags |= bit;
|
||||||
} else {
|
} else {
|
||||||
|
@ -287,26 +283,26 @@ impl OpenOptions {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn append(&mut self, set: bool) {
|
pub fn append(&mut self, set: bool) {
|
||||||
self.fdflag(libc::__WASI_FDFLAG_APPEND, set);
|
self.fdflag(wasi::FDFLAG_APPEND, set);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn dsync(&mut self, set: bool) {
|
pub fn dsync(&mut self, set: bool) {
|
||||||
self.fdflag(libc::__WASI_FDFLAG_DSYNC, set);
|
self.fdflag(wasi::FDFLAG_DSYNC, set);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nonblock(&mut self, set: bool) {
|
pub fn nonblock(&mut self, set: bool) {
|
||||||
self.fdflag(libc::__WASI_FDFLAG_NONBLOCK, set);
|
self.fdflag(wasi::FDFLAG_NONBLOCK, set);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rsync(&mut self, set: bool) {
|
pub fn rsync(&mut self, set: bool) {
|
||||||
self.fdflag(libc::__WASI_FDFLAG_RSYNC, set);
|
self.fdflag(wasi::FDFLAG_RSYNC, set);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sync(&mut self, set: bool) {
|
pub fn sync(&mut self, set: bool) {
|
||||||
self.fdflag(libc::__WASI_FDFLAG_SYNC, set);
|
self.fdflag(wasi::FDFLAG_SYNC, set);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn fdflag(&mut self, bit: libc::__wasi_fdflags_t, set: bool) {
|
fn fdflag(&mut self, bit: wasi::FdFlags, set: bool) {
|
||||||
if set {
|
if set {
|
||||||
self.fdflags |= bit;
|
self.fdflags |= bit;
|
||||||
} else {
|
} else {
|
||||||
|
@ -314,15 +310,15 @@ impl OpenOptions {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fs_rights_base(&mut self, rights: libc::__wasi_rights_t) {
|
pub fn fs_rights_base(&mut self, rights: wasi::Rights) {
|
||||||
self.rights_base = Some(rights);
|
self.rights_base = Some(rights);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn fs_rights_inheriting(&mut self, rights: libc::__wasi_rights_t) {
|
pub fn fs_rights_inheriting(&mut self, rights: wasi::Rights) {
|
||||||
self.rights_inheriting = Some(rights);
|
self.rights_inheriting = Some(rights);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rights_base(&self) -> libc::__wasi_rights_t {
|
fn rights_base(&self) -> wasi::Rights {
|
||||||
if let Some(rights) = self.rights_base {
|
if let Some(rights) = self.rights_base {
|
||||||
return rights;
|
return rights;
|
||||||
}
|
}
|
||||||
|
@ -334,52 +330,52 @@ impl OpenOptions {
|
||||||
// based on that.
|
// based on that.
|
||||||
let mut base = 0;
|
let mut base = 0;
|
||||||
if self.read {
|
if self.read {
|
||||||
base |= libc::__WASI_RIGHT_FD_READ;
|
base |= wasi::RIGHT_FD_READ;
|
||||||
base |= libc::__WASI_RIGHT_FD_READDIR;
|
base |= wasi::RIGHT_FD_READDIR;
|
||||||
}
|
}
|
||||||
if self.write {
|
if self.write {
|
||||||
base |= libc::__WASI_RIGHT_FD_WRITE;
|
base |= wasi::RIGHT_FD_WRITE;
|
||||||
base |= libc::__WASI_RIGHT_FD_DATASYNC;
|
base |= wasi::RIGHT_FD_DATASYNC;
|
||||||
base |= libc::__WASI_RIGHT_FD_ALLOCATE;
|
base |= wasi::RIGHT_FD_ALLOCATE;
|
||||||
base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_SIZE;
|
base |= wasi::RIGHT_FD_FILESTAT_SET_SIZE;
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: some of these should probably be read-only or write-only...
|
// FIXME: some of these should probably be read-only or write-only...
|
||||||
base |= libc::__WASI_RIGHT_FD_ADVISE;
|
base |= wasi::RIGHT_FD_ADVISE;
|
||||||
base |= libc::__WASI_RIGHT_FD_FDSTAT_SET_FLAGS;
|
base |= wasi::RIGHT_FD_FDSTAT_SET_FLAGS;
|
||||||
base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_TIMES;
|
base |= wasi::RIGHT_FD_FILESTAT_SET_TIMES;
|
||||||
base |= libc::__WASI_RIGHT_FD_SEEK;
|
base |= wasi::RIGHT_FD_SEEK;
|
||||||
base |= libc::__WASI_RIGHT_FD_SYNC;
|
base |= wasi::RIGHT_FD_SYNC;
|
||||||
base |= libc::__WASI_RIGHT_FD_TELL;
|
base |= wasi::RIGHT_FD_TELL;
|
||||||
base |= libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY;
|
base |= wasi::RIGHT_PATH_CREATE_DIRECTORY;
|
||||||
base |= libc::__WASI_RIGHT_PATH_CREATE_FILE;
|
base |= wasi::RIGHT_PATH_CREATE_FILE;
|
||||||
base |= libc::__WASI_RIGHT_PATH_FILESTAT_GET;
|
base |= wasi::RIGHT_PATH_FILESTAT_GET;
|
||||||
base |= libc::__WASI_RIGHT_PATH_LINK_SOURCE;
|
base |= wasi::RIGHT_PATH_LINK_SOURCE;
|
||||||
base |= libc::__WASI_RIGHT_PATH_LINK_TARGET;
|
base |= wasi::RIGHT_PATH_LINK_TARGET;
|
||||||
base |= libc::__WASI_RIGHT_PATH_OPEN;
|
base |= wasi::RIGHT_PATH_OPEN;
|
||||||
base |= libc::__WASI_RIGHT_PATH_READLINK;
|
base |= wasi::RIGHT_PATH_READLINK;
|
||||||
base |= libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY;
|
base |= wasi::RIGHT_PATH_REMOVE_DIRECTORY;
|
||||||
base |= libc::__WASI_RIGHT_PATH_RENAME_SOURCE;
|
base |= wasi::RIGHT_PATH_RENAME_SOURCE;
|
||||||
base |= libc::__WASI_RIGHT_PATH_RENAME_TARGET;
|
base |= wasi::RIGHT_PATH_RENAME_TARGET;
|
||||||
base |= libc::__WASI_RIGHT_PATH_SYMLINK;
|
base |= wasi::RIGHT_PATH_SYMLINK;
|
||||||
base |= libc::__WASI_RIGHT_PATH_UNLINK_FILE;
|
base |= wasi::RIGHT_PATH_UNLINK_FILE;
|
||||||
base |= libc::__WASI_RIGHT_POLL_FD_READWRITE;
|
base |= wasi::RIGHT_POLL_FD_READWRITE;
|
||||||
|
|
||||||
return base;
|
return base;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rights_inheriting(&self) -> libc::__wasi_rights_t {
|
fn rights_inheriting(&self) -> wasi::Rights {
|
||||||
self.rights_inheriting.unwrap_or_else(|| self.rights_base())
|
self.rights_inheriting.unwrap_or_else(|| self.rights_base())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lookup_flags(&mut self, flags: libc::__wasi_lookupflags_t) {
|
pub fn lookup_flags(&mut self, flags: wasi::LookupFlags) {
|
||||||
self.dirflags = flags;
|
self.dirflags = flags;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl File {
|
impl File {
|
||||||
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
|
pub fn open(path: &Path, opts: &OpenOptions) -> io::Result<File> {
|
||||||
let (dir, file) = open_parent(path, libc::__WASI_RIGHT_PATH_OPEN)?;
|
let (dir, file) = open_parent(path, wasi::RIGHT_PATH_OPEN)?;
|
||||||
open_at(&dir, &file, opts)
|
open_at(&dir, &file, opts)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -388,14 +384,12 @@ impl File {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
||||||
let mut ret = FileAttr::zero();
|
self.fd.filestat_get().map(|meta| FileAttr { meta })
|
||||||
self.fd.filestat_get(&mut ret.meta)?;
|
|
||||||
Ok(ret)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn metadata_at(
|
pub fn metadata_at(
|
||||||
&self,
|
&self,
|
||||||
flags: libc::__wasi_lookupflags_t,
|
flags: wasi::LookupFlags,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
) -> io::Result<FileAttr> {
|
) -> io::Result<FileAttr> {
|
||||||
metadata_at(&self.fd, flags, path)
|
metadata_at(&self.fd, flags, path)
|
||||||
|
@ -477,7 +471,7 @@ impl DirBuilder {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn mkdir(&self, p: &Path) -> io::Result<()> {
|
pub fn mkdir(&self, p: &Path) -> io::Result<()> {
|
||||||
let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY)?;
|
let (dir, file) = open_parent(p, wasi::RIGHT_PATH_CREATE_DIRECTORY)?;
|
||||||
dir.create_directory(file.as_os_str().as_bytes())
|
dir.create_directory(file.as_os_str().as_bytes())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -508,13 +502,13 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unlink(p: &Path) -> io::Result<()> {
|
pub fn unlink(p: &Path) -> io::Result<()> {
|
||||||
let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_UNLINK_FILE)?;
|
let (dir, file) = open_parent(p, wasi::RIGHT_PATH_UNLINK_FILE)?;
|
||||||
dir.unlink_file(file.as_os_str().as_bytes())
|
dir.unlink_file(file.as_os_str().as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
|
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
|
||||||
let (old, old_file) = open_parent(old, libc::__WASI_RIGHT_PATH_RENAME_SOURCE)?;
|
let (old, old_file) = open_parent(old, wasi::RIGHT_PATH_RENAME_SOURCE)?;
|
||||||
let (new, new_file) = open_parent(new, libc::__WASI_RIGHT_PATH_RENAME_TARGET)?;
|
let (new, new_file) = open_parent(new, wasi::RIGHT_PATH_RENAME_TARGET)?;
|
||||||
old.rename(
|
old.rename(
|
||||||
old_file.as_os_str().as_bytes(),
|
old_file.as_os_str().as_bytes(),
|
||||||
&new,
|
&new,
|
||||||
|
@ -529,12 +523,12 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn rmdir(p: &Path) -> io::Result<()> {
|
pub fn rmdir(p: &Path) -> io::Result<()> {
|
||||||
let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY)?;
|
let (dir, file) = open_parent(p, wasi::RIGHT_PATH_REMOVE_DIRECTORY)?;
|
||||||
dir.remove_directory(file.as_os_str().as_bytes())
|
dir.remove_directory(file.as_os_str().as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn readlink(p: &Path) -> io::Result<PathBuf> {
|
pub fn readlink(p: &Path) -> io::Result<PathBuf> {
|
||||||
let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_READLINK)?;
|
let (dir, file) = open_parent(p, wasi::RIGHT_PATH_READLINK)?;
|
||||||
read_link(&dir, &file)
|
read_link(&dir, &file)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -570,15 +564,15 @@ fn read_link(fd: &WasiFd, file: &Path) -> io::Result<PathBuf> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
|
pub fn symlink(src: &Path, dst: &Path) -> io::Result<()> {
|
||||||
let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_SYMLINK)?;
|
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())
|
dst.symlink(src.as_os_str().as_bytes(), dst_file.as_os_str().as_bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
|
pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
|
||||||
let (src, src_file) = open_parent(src, libc::__WASI_RIGHT_PATH_LINK_SOURCE)?;
|
let (src, src_file) = open_parent(src, wasi::RIGHT_PATH_LINK_SOURCE)?;
|
||||||
let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_LINK_TARGET)?;
|
let (dst, dst_file) = open_parent(dst, wasi::RIGHT_PATH_LINK_TARGET)?;
|
||||||
src.link(
|
src.link(
|
||||||
libc::__WASI_LOOKUP_SYMLINK_FOLLOW,
|
wasi::LOOKUP_SYMLINK_FOLLOW,
|
||||||
src_file.as_os_str().as_bytes(),
|
src_file.as_os_str().as_bytes(),
|
||||||
&dst,
|
&dst,
|
||||||
dst_file.as_os_str().as_bytes(),
|
dst_file.as_os_str().as_bytes(),
|
||||||
|
@ -586,23 +580,22 @@ pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn stat(p: &Path) -> io::Result<FileAttr> {
|
pub fn stat(p: &Path) -> io::Result<FileAttr> {
|
||||||
let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?;
|
let (dir, file) = open_parent(p, wasi::RIGHT_PATH_FILESTAT_GET)?;
|
||||||
metadata_at(&dir, libc::__WASI_LOOKUP_SYMLINK_FOLLOW, &file)
|
metadata_at(&dir, wasi::LOOKUP_SYMLINK_FOLLOW, &file)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn lstat(p: &Path) -> io::Result<FileAttr> {
|
pub fn lstat(p: &Path) -> io::Result<FileAttr> {
|
||||||
let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?;
|
let (dir, file) = open_parent(p, wasi::RIGHT_PATH_FILESTAT_GET)?;
|
||||||
metadata_at(&dir, 0, &file)
|
metadata_at(&dir, 0, &file)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn metadata_at(
|
fn metadata_at(
|
||||||
fd: &WasiFd,
|
fd: &WasiFd,
|
||||||
flags: libc::__wasi_lookupflags_t,
|
flags: wasi::LookupFlags,
|
||||||
path: &Path,
|
path: &Path,
|
||||||
) -> io::Result<FileAttr> {
|
) -> io::Result<FileAttr> {
|
||||||
let mut ret = FileAttr::zero();
|
fd.path_filestat_get(flags, path.as_os_str().as_bytes())
|
||||||
fd.path_filestat_get(flags, path.as_os_str().as_bytes(), &mut ret.meta)?;
|
.map(|meta| FileAttr { meta })
|
||||||
Ok(ret)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
|
pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
|
||||||
|
@ -652,12 +645,12 @@ fn open_at(fd: &WasiFd, path: &Path, opts: &OpenOptions) -> io::Result<File> {
|
||||||
/// to any preopened file descriptor.
|
/// to any preopened file descriptor.
|
||||||
fn open_parent(
|
fn open_parent(
|
||||||
p: &Path,
|
p: &Path,
|
||||||
rights: libc::__wasi_rights_t,
|
rights: wasi::Rights,
|
||||||
) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
|
) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
|
||||||
let p = CString::new(p.as_os_str().as_bytes())?;
|
let p = CString::new(p.as_os_str().as_bytes())?;
|
||||||
unsafe {
|
unsafe {
|
||||||
let mut ret = ptr::null();
|
let mut ret = ptr::null();
|
||||||
let fd = __wasilibc_find_relpath(p.as_ptr(), rights, 0, &mut ret);
|
let fd = libc::__wasilibc_find_relpath(p.as_ptr(), rights, 0, &mut ret);
|
||||||
if fd == -1 {
|
if fd == -1 {
|
||||||
let msg = format!(
|
let msg = format!(
|
||||||
"failed to find a preopened file descriptor \
|
"failed to find a preopened file descriptor \
|
||||||
|
@ -677,15 +670,4 @@ fn open_parent(
|
||||||
|
|
||||||
return Ok((ManuallyDrop::new(WasiFd::from_raw(fd as u32)), path));
|
return Ok((ManuallyDrop::new(WasiFd::from_raw(fd as u32)), path));
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME(rust-lang/libc#1314) use the `libc` crate for this when the API
|
|
||||||
// there is published
|
|
||||||
extern "C" {
|
|
||||||
pub fn __wasilibc_find_relpath(
|
|
||||||
path: *const libc::c_char,
|
|
||||||
rights_base: libc::__wasi_rights_t,
|
|
||||||
rights_inheriting: libc::__wasi_rights_t,
|
|
||||||
relative_path: *mut *const libc::c_char,
|
|
||||||
) -> libc::c_int;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,11 +1,12 @@
|
||||||
use crate::marker::PhantomData;
|
use crate::marker::PhantomData;
|
||||||
use crate::slice;
|
use crate::slice;
|
||||||
|
|
||||||
use libc::{__wasi_ciovec_t, __wasi_iovec_t, c_void};
|
use ::wasi::wasi_unstable as wasi;
|
||||||
|
use core::ffi::c_void;
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct IoSlice<'a> {
|
pub struct IoSlice<'a> {
|
||||||
vec: __wasi_ciovec_t,
|
vec: wasi::CIoVec,
|
||||||
_p: PhantomData<&'a [u8]>,
|
_p: PhantomData<&'a [u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -13,7 +14,7 @@ impl<'a> IoSlice<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
|
pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
|
||||||
IoSlice {
|
IoSlice {
|
||||||
vec: __wasi_ciovec_t {
|
vec: wasi::CIoVec {
|
||||||
buf: buf.as_ptr() as *const c_void,
|
buf: buf.as_ptr() as *const c_void,
|
||||||
buf_len: buf.len(),
|
buf_len: buf.len(),
|
||||||
},
|
},
|
||||||
|
@ -43,7 +44,7 @@ impl<'a> IoSlice<'a> {
|
||||||
|
|
||||||
#[repr(transparent)]
|
#[repr(transparent)]
|
||||||
pub struct IoSliceMut<'a> {
|
pub struct IoSliceMut<'a> {
|
||||||
vec: __wasi_iovec_t,
|
vec: wasi::IoVec,
|
||||||
_p: PhantomData<&'a mut [u8]>,
|
_p: PhantomData<&'a mut [u8]>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ impl<'a> IoSliceMut<'a> {
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
|
pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
|
||||||
IoSliceMut {
|
IoSliceMut {
|
||||||
vec: __wasi_iovec_t {
|
vec: wasi::IoVec {
|
||||||
buf: buf.as_mut_ptr() as *mut c_void,
|
buf: buf.as_mut_ptr() as *mut c_void,
|
||||||
buf_len: buf.len()
|
buf_len: buf.len()
|
||||||
},
|
},
|
||||||
|
|
|
@ -14,10 +14,10 @@
|
||||||
//! compiling for wasm. That way it's a compile time error for something that's
|
//! compiling for wasm. That way it's a compile time error for something that's
|
||||||
//! guaranteed to be a runtime error!
|
//! guaranteed to be a runtime error!
|
||||||
|
|
||||||
use libc;
|
use crate::io as std_io;
|
||||||
use crate::io::{Error, ErrorKind};
|
|
||||||
use crate::mem;
|
use crate::mem;
|
||||||
use crate::os::raw::c_char;
|
use crate::os::raw::c_char;
|
||||||
|
use ::wasi::wasi_unstable as wasi;
|
||||||
|
|
||||||
pub mod alloc;
|
pub mod alloc;
|
||||||
pub mod args;
|
pub mod args;
|
||||||
|
@ -56,31 +56,42 @@ pub mod ext;
|
||||||
pub fn init() {
|
pub fn init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unsupported<T>() -> crate::io::Result<T> {
|
pub fn unsupported<T>() -> std_io::Result<T> {
|
||||||
Err(unsupported_err())
|
Err(unsupported_err())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn unsupported_err() -> Error {
|
pub fn unsupported_err() -> std_io::Error {
|
||||||
Error::new(ErrorKind::Other, "operation not supported on wasm yet")
|
std_io::Error::new(
|
||||||
|
std_io::ErrorKind::Other,
|
||||||
|
"operation not supported on wasm yet",
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn decode_error_kind(errno: i32) -> ErrorKind {
|
pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
|
||||||
match errno as libc::c_int {
|
use std_io::ErrorKind::*;
|
||||||
libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
|
if errno > u16::max_value() as i32 || errno < 0 {
|
||||||
libc::ECONNRESET => ErrorKind::ConnectionReset,
|
return Other;
|
||||||
libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied,
|
}
|
||||||
libc::EPIPE => ErrorKind::BrokenPipe,
|
let code = match wasi::Error::new(errno as u16) {
|
||||||
libc::ENOTCONN => ErrorKind::NotConnected,
|
Some(code) => code,
|
||||||
libc::ECONNABORTED => ErrorKind::ConnectionAborted,
|
None => return Other,
|
||||||
libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
|
};
|
||||||
libc::EADDRINUSE => ErrorKind::AddrInUse,
|
match code {
|
||||||
libc::ENOENT => ErrorKind::NotFound,
|
wasi::ECONNREFUSED => ConnectionRefused,
|
||||||
libc::EINTR => ErrorKind::Interrupted,
|
wasi::ECONNRESET => ConnectionReset,
|
||||||
libc::EINVAL => ErrorKind::InvalidInput,
|
wasi::EPERM | wasi::EACCES => PermissionDenied,
|
||||||
libc::ETIMEDOUT => ErrorKind::TimedOut,
|
wasi::EPIPE => BrokenPipe,
|
||||||
libc::EEXIST => ErrorKind::AlreadyExists,
|
wasi::ENOTCONN => NotConnected,
|
||||||
libc::EAGAIN => ErrorKind::WouldBlock,
|
wasi::ECONNABORTED => ConnectionAborted,
|
||||||
_ => ErrorKind::Other,
|
wasi::EADDRNOTAVAIL => AddrNotAvailable,
|
||||||
|
wasi::EADDRINUSE => AddrInUse,
|
||||||
|
wasi::ENOENT => NotFound,
|
||||||
|
wasi::EINTR => Interrupted,
|
||||||
|
wasi::EINVAL => InvalidInput,
|
||||||
|
wasi::ETIMEDOUT => TimedOut,
|
||||||
|
wasi::EEXIST => AlreadyExists,
|
||||||
|
wasi::EAGAIN => WouldBlock,
|
||||||
|
_ => Other,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -105,40 +116,16 @@ pub unsafe fn abort_internal() -> ! {
|
||||||
pub fn hashmap_random_keys() -> (u64, u64) {
|
pub fn hashmap_random_keys() -> (u64, u64) {
|
||||||
let mut ret = (0u64, 0u64);
|
let mut ret = (0u64, 0u64);
|
||||||
unsafe {
|
unsafe {
|
||||||
let base = &mut ret as *mut (u64, u64) as *mut libc::c_void;
|
let base = &mut ret as *mut (u64, u64) as *mut core::ffi::c_void;
|
||||||
let len = mem::size_of_val(&ret);
|
let len = mem::size_of_val(&ret);
|
||||||
cvt_wasi(libc::__wasi_random_get(base, len)).unwrap();
|
let ret = wasi::raw::__wasi_random_get(base, len);
|
||||||
|
if ret != 0 {
|
||||||
|
panic!("__wasi_random_get failure")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return ret
|
return ret
|
||||||
}
|
}
|
||||||
|
|
||||||
#[doc(hidden)]
|
fn err2io(err: wasi::Error) -> std_io::Error {
|
||||||
pub trait IsMinusOne {
|
std_io::Error::from_raw_os_error(err.get() as i32)
|
||||||
fn is_minus_one(&self) -> bool;
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! impl_is_minus_one {
|
|
||||||
($($t:ident)*) => ($(impl IsMinusOne for $t {
|
|
||||||
fn is_minus_one(&self) -> bool {
|
|
||||||
*self == -1
|
|
||||||
}
|
|
||||||
})*)
|
|
||||||
}
|
|
||||||
|
|
||||||
impl_is_minus_one! { i8 i16 i32 i64 isize }
|
|
||||||
|
|
||||||
pub fn cvt<T: IsMinusOne>(t: T) -> crate::io::Result<T> {
|
|
||||||
if t.is_minus_one() {
|
|
||||||
Err(Error::last_os_error())
|
|
||||||
} else {
|
|
||||||
Ok(t)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn cvt_wasi(r: u16) -> crate::io::Result<()> {
|
|
||||||
if r != libc::__WASI_ESUCCESS {
|
|
||||||
Err(Error::from_raw_os_error(r as i32))
|
|
||||||
} else {
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,7 +9,7 @@ use crate::path::{self, PathBuf};
|
||||||
use crate::ptr;
|
use crate::ptr;
|
||||||
use crate::str;
|
use crate::str;
|
||||||
use crate::sys::memchr;
|
use crate::sys::memchr;
|
||||||
use crate::sys::{cvt, unsupported, Void};
|
use crate::sys::{unsupported, Void};
|
||||||
use crate::vec;
|
use crate::vec;
|
||||||
|
|
||||||
#[cfg(not(target_feature = "atomics"))]
|
#[cfg(not(target_feature = "atomics"))]
|
||||||
|
@ -28,16 +28,11 @@ pub fn errno() -> i32 {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn error_string(errno: i32) -> String {
|
pub fn error_string(errno: i32) -> String {
|
||||||
extern {
|
|
||||||
fn strerror_r(errnum: libc::c_int, buf: *mut libc::c_char,
|
|
||||||
buflen: libc::size_t) -> libc::c_int;
|
|
||||||
}
|
|
||||||
|
|
||||||
let mut buf = [0 as libc::c_char; 1024];
|
let mut buf = [0 as libc::c_char; 1024];
|
||||||
|
|
||||||
let p = buf.as_mut_ptr();
|
let p = buf.as_mut_ptr();
|
||||||
unsafe {
|
unsafe {
|
||||||
if strerror_r(errno as libc::c_int, p, buf.len()) < 0 {
|
if libc::strerror_r(errno as libc::c_int, p, buf.len()) < 0 {
|
||||||
panic!("strerror_r failure");
|
panic!("strerror_r failure");
|
||||||
}
|
}
|
||||||
str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
|
str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
|
||||||
|
@ -89,7 +84,6 @@ impl StdError for JoinPathsError {
|
||||||
pub fn current_exe() -> io::Result<PathBuf> {
|
pub fn current_exe() -> io::Result<PathBuf> {
|
||||||
unsupported()
|
unsupported()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub struct Env {
|
pub struct Env {
|
||||||
iter: vec::IntoIter<(OsString, OsString)>,
|
iter: vec::IntoIter<(OsString, OsString)>,
|
||||||
_dont_send_or_sync_me: PhantomData<*mut ()>,
|
_dont_send_or_sync_me: PhantomData<*mut ()>,
|
||||||
|
@ -182,3 +176,26 @@ pub fn exit(code: i32) -> ! {
|
||||||
pub fn getpid() -> u32 {
|
pub fn getpid() -> u32 {
|
||||||
panic!("unsupported");
|
panic!("unsupported");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[doc(hidden)]
|
||||||
|
pub trait IsMinusOne {
|
||||||
|
fn is_minus_one(&self) -> bool;
|
||||||
|
}
|
||||||
|
|
||||||
|
macro_rules! impl_is_minus_one {
|
||||||
|
($($t:ident)*) => ($(impl IsMinusOne for $t {
|
||||||
|
fn is_minus_one(&self) -> bool {
|
||||||
|
*self == -1
|
||||||
|
}
|
||||||
|
})*)
|
||||||
|
}
|
||||||
|
|
||||||
|
impl_is_minus_one! { i8 i16 i32 i64 isize }
|
||||||
|
|
||||||
|
fn cvt<T: IsMinusOne>(t: T) -> io::Result<T> {
|
||||||
|
if t.is_minus_one() {
|
||||||
|
Err(io::Error::last_os_error())
|
||||||
|
} else {
|
||||||
|
Ok(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,8 +1,9 @@
|
||||||
use crate::io::{self, IoSlice, IoSliceMut};
|
use crate::io::{self, IoSlice, IoSliceMut};
|
||||||
use crate::libc;
|
|
||||||
use crate::mem::ManuallyDrop;
|
use crate::mem::ManuallyDrop;
|
||||||
use crate::sys::fd::WasiFd;
|
use crate::sys::fd::WasiFd;
|
||||||
|
|
||||||
|
use ::wasi::wasi_unstable as wasi;
|
||||||
|
|
||||||
pub struct Stdin;
|
pub struct Stdin;
|
||||||
pub struct Stdout;
|
pub struct Stdout;
|
||||||
pub struct Stderr;
|
pub struct Stderr;
|
||||||
|
@ -17,7 +18,7 @@ impl Stdin {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn read_vectored(&self, data: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
pub fn read_vectored(&self, data: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||||
ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDIN_FILENO as u32) })
|
ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDIN_FD) })
|
||||||
.read(data)
|
.read(data)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -32,7 +33,7 @@ impl Stdout {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||||
ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDOUT_FILENO as u32) })
|
ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDOUT_FD) })
|
||||||
.write(data)
|
.write(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -51,7 +52,7 @@ impl Stderr {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
pub fn write_vectored(&self, data: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||||
ManuallyDrop::new(unsafe { WasiFd::from_raw(libc::STDERR_FILENO as u32) })
|
ManuallyDrop::new(unsafe { WasiFd::from_raw(wasi::STDERR_FD) })
|
||||||
.write(data)
|
.write(data)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -73,7 +74,7 @@ impl io::Write for Stderr {
|
||||||
pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
|
pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
|
||||||
|
|
||||||
pub fn is_ebadf(err: &io::Error) -> bool {
|
pub fn is_ebadf(err: &io::Error) -> bool {
|
||||||
err.raw_os_error() == Some(libc::__WASI_EBADF as i32)
|
err.raw_os_error() == Some(wasi::EBADF.get() as i32)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn panic_output() -> Option<impl io::Write> {
|
pub fn panic_output() -> Option<impl io::Write> {
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
use crate::cmp;
|
|
||||||
use crate::ffi::CStr;
|
use crate::ffi::CStr;
|
||||||
use crate::io;
|
use crate::io;
|
||||||
use crate::sys::cvt;
|
use crate::mem;
|
||||||
use crate::sys::{unsupported, Void};
|
use crate::sys::{unsupported, Void};
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
use libc;
|
|
||||||
|
use ::wasi::wasi_unstable as wasi;
|
||||||
|
|
||||||
pub struct Thread(Void);
|
pub struct Thread(Void);
|
||||||
|
|
||||||
|
@ -19,8 +19,8 @@ impl Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn yield_now() {
|
pub fn yield_now() {
|
||||||
let ret = unsafe { libc::__wasi_sched_yield() };
|
let ret = wasi::sched_yield();
|
||||||
debug_assert_eq!(ret, 0);
|
debug_assert_eq!(ret, Ok(()));
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_name(_name: &CStr) {
|
pub fn set_name(_name: &CStr) {
|
||||||
|
@ -28,19 +28,37 @@ impl Thread {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn sleep(dur: Duration) {
|
pub fn sleep(dur: Duration) {
|
||||||
let mut secs = dur.as_secs();
|
let nanos = dur.as_nanos();
|
||||||
let mut nsecs = dur.subsec_nanos() as i32;
|
assert!(nanos <= u64::max_value() as u128);
|
||||||
|
|
||||||
unsafe {
|
const CLOCK_ID: wasi::Userdata = 0x0123_45678;
|
||||||
while secs > 0 || nsecs > 0 {
|
|
||||||
let mut ts = libc::timespec {
|
let clock = wasi::raw::__wasi_subscription_u_clock_t {
|
||||||
tv_sec: cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t,
|
identifier: CLOCK_ID,
|
||||||
tv_nsec: nsecs,
|
clock_id: wasi::CLOCK_MONOTONIC,
|
||||||
|
timeout: nanos as u64,
|
||||||
|
precision: 0,
|
||||||
|
flags: 0,
|
||||||
};
|
};
|
||||||
secs -= ts.tv_sec as u64;
|
|
||||||
cvt(libc::nanosleep(&ts, &mut ts)).unwrap();
|
let in_ = [wasi::Subscription {
|
||||||
nsecs = 0;
|
userdata: 0,
|
||||||
}
|
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])
|
||||||
|
};
|
||||||
|
match (res, event) {
|
||||||
|
(Ok(1), wasi::Event {
|
||||||
|
userdata: CLOCK_ID,
|
||||||
|
error: 0,
|
||||||
|
type_: wasi::EVENTTYPE_CLOCK,
|
||||||
|
..
|
||||||
|
}) => {}
|
||||||
|
_ => panic!("thread::sleep(): unexpected result of poll_oneoff"),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
use crate::time::Duration;
|
use crate::time::Duration;
|
||||||
use crate::mem;
|
use ::wasi::wasi_unstable as wasi;
|
||||||
use crate::sys::cvt_wasi;
|
|
||||||
use libc;
|
|
||||||
|
|
||||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||||
pub struct Instant(Duration);
|
pub struct Instant(Duration);
|
||||||
|
@ -12,23 +10,19 @@ pub struct SystemTime(Duration);
|
||||||
pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
|
pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
|
||||||
|
|
||||||
fn current_time(clock: u32) -> Duration {
|
fn current_time(clock: u32) -> Duration {
|
||||||
unsafe {
|
let ts = wasi::clock_time_get(
|
||||||
let mut ts = mem::zeroed();
|
|
||||||
cvt_wasi(libc::__wasi_clock_time_get(
|
|
||||||
clock,
|
clock,
|
||||||
1, // precision... seems ignored though?
|
1, // precision... seems ignored though?
|
||||||
&mut ts,
|
).unwrap();
|
||||||
)).unwrap();
|
|
||||||
Duration::new(
|
Duration::new(
|
||||||
(ts / 1_000_000_000) as u64,
|
(ts / 1_000_000_000) as u64,
|
||||||
(ts % 1_000_000_000) as u32,
|
(ts % 1_000_000_000) as u32,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
impl Instant {
|
impl Instant {
|
||||||
pub fn now() -> Instant {
|
pub fn now() -> Instant {
|
||||||
Instant(current_time(libc::__WASI_CLOCK_MONOTONIC))
|
Instant(current_time(wasi::CLOCK_MONOTONIC))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub const fn zero() -> Instant {
|
pub const fn zero() -> Instant {
|
||||||
|
@ -54,10 +48,10 @@ impl Instant {
|
||||||
|
|
||||||
impl SystemTime {
|
impl SystemTime {
|
||||||
pub fn now() -> SystemTime {
|
pub fn now() -> SystemTime {
|
||||||
SystemTime(current_time(libc::__WASI_CLOCK_REALTIME))
|
SystemTime(current_time(wasi::CLOCK_REALTIME))
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_wasi_timestamp(ts: libc::__wasi_timestamp_t) -> SystemTime {
|
pub fn from_wasi_timestamp(ts: wasi::Timestamp) -> SystemTime {
|
||||||
SystemTime(Duration::from_nanos(ts))
|
SystemTime(Duration::from_nanos(ts))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -15,6 +15,7 @@ const LICENSES: &[&str] = &[
|
||||||
"Apache-2.0 / MIT",
|
"Apache-2.0 / MIT",
|
||||||
"MIT OR Apache-2.0",
|
"MIT OR Apache-2.0",
|
||||||
"Apache-2.0 OR MIT",
|
"Apache-2.0 OR MIT",
|
||||||
|
"Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT", // wasi license
|
||||||
"MIT",
|
"MIT",
|
||||||
"Unlicense/MIT",
|
"Unlicense/MIT",
|
||||||
"Unlicense OR MIT",
|
"Unlicense OR MIT",
|
||||||
|
@ -172,6 +173,7 @@ const WHITELIST: &[Crate<'_>] = &[
|
||||||
Crate("vcpkg"),
|
Crate("vcpkg"),
|
||||||
Crate("version_check"),
|
Crate("version_check"),
|
||||||
Crate("void"),
|
Crate("void"),
|
||||||
|
Crate("wasi"),
|
||||||
Crate("winapi"),
|
Crate("winapi"),
|
||||||
Crate("winapi-build"),
|
Crate("winapi-build"),
|
||||||
Crate("winapi-i686-pc-windows-gnu"),
|
Crate("winapi-i686-pc-windows-gnu"),
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue