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_tsan",
|
||||
"unwind",
|
||||
"wasi",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
@ -4686,6 +4687,17 @@ dependencies = [
|
|||
"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]]
|
||||
name = "winapi"
|
||||
version = "0.2.8"
|
||||
|
|
|
@ -56,6 +56,9 @@ dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] }
|
|||
[target.x86_64-fortanix-unknown-sgx.dependencies]
|
||||
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]
|
||||
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::marker::PhantomData;
|
||||
use crate::os::wasi::ffi::OsStringExt;
|
||||
use crate::vec;
|
||||
|
||||
use ::wasi::wasi_unstable as wasi;
|
||||
|
||||
pub unsafe fn init(_argc: isize, _argv: *const *const u8) {
|
||||
}
|
||||
|
||||
|
@ -19,31 +18,17 @@ pub struct Args {
|
|||
|
||||
/// Returns the command line arguments
|
||||
pub fn args() -> Args {
|
||||
maybe_args().unwrap_or_else(|_| {
|
||||
Args {
|
||||
iter: Vec::new().into_iter(),
|
||||
_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,
|
||||
})
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -8,6 +8,8 @@ use crate::os::wasi::ffi::OsStrExt;
|
|||
use crate::path::{Path, PathBuf};
|
||||
use crate::sys_common::{AsInner, AsInnerMut, FromInner};
|
||||
|
||||
use ::wasi::wasi_unstable as wasi;
|
||||
|
||||
/// WASI-specific extensions to [`File`].
|
||||
///
|
||||
/// [`File`]: ../../../../std/fs/struct.File.html
|
||||
|
@ -336,16 +338,16 @@ pub trait FileTypeExt {
|
|||
|
||||
impl FileTypeExt for fs::FileType {
|
||||
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 {
|
||||
self.as_inner().bits() == libc::__WASI_FILETYPE_CHARACTER_DEVICE
|
||||
self.as_inner().bits() == wasi::FILETYPE_CHARACTER_DEVICE
|
||||
}
|
||||
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 {
|
||||
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::sys_common::{AsInner, FromInner, IntoInner};
|
||||
|
||||
use ::wasi::wasi_unstable as wasi;
|
||||
|
||||
/// Raw file descriptors.
|
||||
pub type RawFd = u32;
|
||||
|
||||
|
@ -125,18 +127,18 @@ impl IntoRawFd for fs::File {
|
|||
|
||||
impl AsRawFd for io::Stdin {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
libc::STDIN_FILENO as u32
|
||||
wasi::STDIN_FD
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for io::Stdout {
|
||||
fn as_raw_fd(&self) -> RawFd {
|
||||
libc::STDOUT_FILENO as u32
|
||||
wasi::STDOUT_FD
|
||||
}
|
||||
}
|
||||
|
||||
impl AsRawFd for io::Stderr {
|
||||
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::mem;
|
||||
use crate::net::Shutdown;
|
||||
use crate::sys::cvt_wasi;
|
||||
use libc::{self, c_char, c_void};
|
||||
use super::err2io;
|
||||
use ::wasi::wasi_unstable as wasi;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct WasiFd {
|
||||
fd: libc::__wasi_fd_t,
|
||||
fd: wasi::Fd,
|
||||
}
|
||||
|
||||
// FIXME: these should probably all be fancier structs, builders, enums, etc
|
||||
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) {
|
||||
fn iovec<'a>(a: &'a mut [IoSliceMut<'_>]) -> &'a [wasi::IoVec] {
|
||||
assert_eq!(
|
||||
mem::size_of::<IoSliceMut<'_>>(),
|
||||
mem::size_of::<libc::__wasi_iovec_t>()
|
||||
mem::size_of::<wasi::IoVec>()
|
||||
);
|
||||
assert_eq!(
|
||||
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!(
|
||||
mem::size_of::<IoSlice<'_>>(),
|
||||
mem::size_of::<libc::__wasi_ciovec_t>()
|
||||
mem::size_of::<wasi::CIoVec>()
|
||||
);
|
||||
assert_eq!(
|
||||
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 {
|
||||
pub unsafe fn from_raw(fd: libc::__wasi_fd_t) -> WasiFd {
|
||||
pub unsafe fn from_raw(fd: wasi::Fd) -> WasiFd {
|
||||
WasiFd { fd }
|
||||
}
|
||||
|
||||
pub fn into_raw(self) -> libc::__wasi_fd_t {
|
||||
pub fn into_raw(self) -> wasi::Fd {
|
||||
let ret = self.fd;
|
||||
mem::forget(self);
|
||||
ret
|
||||
}
|
||||
|
||||
pub fn as_raw(&self) -> libc::__wasi_fd_t {
|
||||
pub fn as_raw(&self) -> wasi::Fd {
|
||||
self.fd
|
||||
}
|
||||
|
||||
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> {
|
||||
let mut read = 0;
|
||||
let (ptr, len) = iovec(bufs);
|
||||
cvt_wasi(unsafe { libc::__wasi_fd_pread(self.fd, ptr, len, offset, &mut read) })?;
|
||||
Ok(read)
|
||||
unsafe { wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn pwrite(&self, bufs: &[IoSlice<'_>], offset: u64) -> io::Result<usize> {
|
||||
let mut read = 0;
|
||||
let (ptr, len) = ciovec(bufs);
|
||||
cvt_wasi(unsafe { libc::__wasi_fd_pwrite(self.fd, ptr, len, offset, &mut read) })?;
|
||||
Ok(read)
|
||||
unsafe { wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn read(&self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
|
||||
let mut read = 0;
|
||||
let (ptr, len) = iovec(bufs);
|
||||
cvt_wasi(unsafe { libc::__wasi_fd_read(self.fd, ptr, len, &mut read) })?;
|
||||
Ok(read)
|
||||
unsafe { wasi::fd_read(self.fd, iovec(bufs)).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn write(&self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
|
||||
let mut read = 0;
|
||||
let (ptr, len) = ciovec(bufs);
|
||||
cvt_wasi(unsafe { libc::__wasi_fd_write(self.fd, ptr, len, &mut read) })?;
|
||||
Ok(read)
|
||||
unsafe { wasi::fd_write(self.fd, ciovec(bufs)).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
|
||||
let (whence, offset) = match pos {
|
||||
SeekFrom::Start(pos) => (libc::__WASI_WHENCE_SET, pos as i64),
|
||||
SeekFrom::End(pos) => (libc::__WASI_WHENCE_END, pos),
|
||||
SeekFrom::Current(pos) => (libc::__WASI_WHENCE_CUR, pos),
|
||||
SeekFrom::Start(pos) => (wasi::WHENCE_SET, pos as i64),
|
||||
SeekFrom::End(pos) => (wasi::WHENCE_END, pos),
|
||||
SeekFrom::Current(pos) => (wasi::WHENCE_CUR, pos),
|
||||
};
|
||||
let mut pos = 0;
|
||||
cvt_wasi(unsafe { libc::__wasi_fd_seek(self.fd, offset, whence, &mut pos) })?;
|
||||
Ok(pos)
|
||||
unsafe { wasi::fd_seek(self.fd, offset, whence).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn tell(&self) -> io::Result<u64> {
|
||||
let mut pos = 0;
|
||||
cvt_wasi(unsafe { libc::__wasi_fd_tell(self.fd, &mut pos) })?;
|
||||
Ok(pos)
|
||||
unsafe { wasi::fd_tell(self.fd).map_err(err2io) }
|
||||
}
|
||||
|
||||
// FIXME: __wasi_fd_fdstat_get
|
||||
|
||||
pub fn set_flags(&self, flags: FdFlags) -> io::Result<()> {
|
||||
cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_flags(self.fd, flags) })
|
||||
pub fn set_flags(&self, flags: wasi::FdFlags) -> io::Result<()> {
|
||||
unsafe { wasi::fd_fdstat_set_flags(self.fd, flags).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn set_rights(&self, base: Rights, inheriting: Rights) -> io::Result<()> {
|
||||
cvt_wasi(unsafe { libc::__wasi_fd_fdstat_set_rights(self.fd, base, inheriting) })
|
||||
pub fn set_rights(&self, base: wasi::Rights, inheriting: wasi::Rights) -> io::Result<()> {
|
||||
unsafe { wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(err2io) }
|
||||
}
|
||||
|
||||
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<()> {
|
||||
cvt_wasi(unsafe { libc::__wasi_fd_advise(self.fd, offset, len, advice as u8) })
|
||||
pub fn advise(&self, offset: u64, len: u64, advice: wasi::Advice) -> io::Result<()> {
|
||||
unsafe { wasi::fd_advise(self.fd, offset, len, advice).map_err(err2io) }
|
||||
}
|
||||
|
||||
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<()> {
|
||||
cvt_wasi(unsafe {
|
||||
libc::__wasi_path_create_directory(self.fd, path.as_ptr() as *const c_char, path.len())
|
||||
})
|
||||
unsafe { wasi::path_create_directory(self.fd, path).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn link(
|
||||
&self,
|
||||
old_flags: LookupFlags,
|
||||
old_flags: wasi::LookupFlags,
|
||||
old_path: &[u8],
|
||||
new_fd: &WasiFd,
|
||||
new_path: &[u8],
|
||||
) -> io::Result<()> {
|
||||
cvt_wasi(unsafe {
|
||||
libc::__wasi_path_link(
|
||||
self.fd,
|
||||
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(),
|
||||
)
|
||||
})
|
||||
unsafe {
|
||||
wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path)
|
||||
.map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn open(
|
||||
&self,
|
||||
dirflags: LookupFlags,
|
||||
dirflags: wasi::LookupFlags,
|
||||
path: &[u8],
|
||||
oflags: Oflags,
|
||||
fs_rights_base: Rights,
|
||||
fs_rights_inheriting: Rights,
|
||||
fs_flags: FdFlags,
|
||||
oflags: wasi::OFlags,
|
||||
fs_rights_base: wasi::Rights,
|
||||
fs_rights_inheriting: wasi::Rights,
|
||||
fs_flags: wasi::FdFlags,
|
||||
) -> io::Result<WasiFd> {
|
||||
unsafe {
|
||||
let mut fd = 0;
|
||||
cvt_wasi(libc::__wasi_path_open(
|
||||
wasi::path_open(
|
||||
self.fd,
|
||||
dirflags,
|
||||
path.as_ptr() as *const c_char,
|
||||
path.len(),
|
||||
path,
|
||||
oflags,
|
||||
fs_rights_base,
|
||||
fs_rights_inheriting,
|
||||
fs_flags,
|
||||
&mut fd,
|
||||
))?;
|
||||
Ok(WasiFd::from_raw(fd))
|
||||
).map(|fd| WasiFd::from_raw(fd)).map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn readdir(&self, buf: &mut [u8], cookie: DirCookie) -> io::Result<usize> {
|
||||
let mut used = 0;
|
||||
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 readdir(&self, buf: &mut [u8], cookie: wasi::DirCookie) -> io::Result<usize> {
|
||||
unsafe { wasi::fd_readdir(self.fd, buf, cookie).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn readlink(&self, path: &[u8], buf: &mut [u8]) -> io::Result<usize> {
|
||||
let mut used = 0;
|
||||
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)
|
||||
unsafe { wasi::path_readlink(self.fd, path, buf).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn rename(&self, old_path: &[u8], new_fd: &WasiFd, new_path: &[u8]) -> io::Result<()> {
|
||||
cvt_wasi(unsafe {
|
||||
libc::__wasi_path_rename(
|
||||
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(),
|
||||
)
|
||||
})
|
||||
unsafe {
|
||||
wasi::path_rename(self.fd, old_path, new_fd.fd, new_path).map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn filestat_get(&self, buf: *mut libc::__wasi_filestat_t) -> io::Result<()> {
|
||||
cvt_wasi(unsafe { libc::__wasi_fd_filestat_get(self.fd, buf) })
|
||||
pub fn filestat_get(&self) -> io::Result<wasi::FileStat> {
|
||||
unsafe { wasi::fd_filestat_get(self.fd).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn filestat_set_times(
|
||||
&self,
|
||||
atim: Timestamp,
|
||||
mtim: Timestamp,
|
||||
fstflags: FstFlags,
|
||||
atim: wasi::Timestamp,
|
||||
mtim: wasi::Timestamp,
|
||||
fstflags: wasi::FstFlags,
|
||||
) -> 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<()> {
|
||||
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(
|
||||
&self,
|
||||
flags: LookupFlags,
|
||||
flags: wasi::LookupFlags,
|
||||
path: &[u8],
|
||||
buf: *mut libc::__wasi_filestat_t,
|
||||
) -> io::Result<()> {
|
||||
cvt_wasi(unsafe {
|
||||
libc::__wasi_path_filestat_get(
|
||||
self.fd,
|
||||
flags,
|
||||
path.as_ptr() as *const c_char,
|
||||
path.len(),
|
||||
buf,
|
||||
)
|
||||
})
|
||||
) -> io::Result<wasi::FileStat> {
|
||||
unsafe { wasi::path_filestat_get(self.fd, flags, path).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn path_filestat_set_times(
|
||||
&self,
|
||||
flags: LookupFlags,
|
||||
flags: wasi::LookupFlags,
|
||||
path: &[u8],
|
||||
atim: Timestamp,
|
||||
mtim: Timestamp,
|
||||
fstflags: FstFlags,
|
||||
atim: wasi::Timestamp,
|
||||
mtim: wasi::Timestamp,
|
||||
fstflags: wasi::FstFlags,
|
||||
) -> io::Result<()> {
|
||||
cvt_wasi(unsafe {
|
||||
libc::__wasi_path_filestat_set_times(
|
||||
unsafe {
|
||||
wasi::path_filestat_set_times(
|
||||
self.fd,
|
||||
flags,
|
||||
path.as_ptr() as *const c_char,
|
||||
path.len(),
|
||||
path,
|
||||
atim,
|
||||
mtim,
|
||||
fstflags,
|
||||
)
|
||||
})
|
||||
).map_err(err2io)
|
||||
}
|
||||
}
|
||||
|
||||
pub fn symlink(&self, old_path: &[u8], new_path: &[u8]) -> io::Result<()> {
|
||||
cvt_wasi(unsafe {
|
||||
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(),
|
||||
)
|
||||
})
|
||||
unsafe { wasi::path_symlink(old_path, self.fd, new_path).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn unlink_file(&self, path: &[u8]) -> io::Result<()> {
|
||||
cvt_wasi(unsafe {
|
||||
libc::__wasi_path_unlink_file(self.fd, path.as_ptr() as *const c_char, path.len())
|
||||
})
|
||||
unsafe { wasi::path_unlink_file(self.fd, path).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn remove_directory(&self, path: &[u8]) -> io::Result<()> {
|
||||
cvt_wasi(unsafe {
|
||||
libc::__wasi_path_remove_directory(self.fd, path.as_ptr() as *const c_char, path.len())
|
||||
})
|
||||
unsafe { wasi::path_remove_directory(self.fd, path).map_err(err2io) }
|
||||
}
|
||||
|
||||
pub fn sock_recv(
|
||||
&self,
|
||||
ri_data: &mut [IoSliceMut<'_>],
|
||||
ri_flags: RiFlags,
|
||||
) -> io::Result<(usize, RoFlags)> {
|
||||
let mut ro_datalen = 0;
|
||||
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))
|
||||
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: SiFlags) -> io::Result<usize> {
|
||||
let mut so_datalen = 0;
|
||||
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_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 => libc::__WASI_SHUT_RD,
|
||||
Shutdown::Write => libc::__WASI_SHUT_WR,
|
||||
Shutdown::Both => libc::__WASI_SHUT_WR | libc::__WASI_SHUT_RD,
|
||||
Shutdown::Read => wasi::SHUT_RD,
|
||||
Shutdown::Write => wasi::SHUT_WR,
|
||||
Shutdown::Both => wasi::SHUT_WR | wasi::SHUT_RD,
|
||||
};
|
||||
cvt_wasi(unsafe { libc::__wasi_sock_shutdown(self.fd, how) })?;
|
||||
Ok(())
|
||||
unsafe { wasi::sock_shutdown(self.fd, how).map_err(err2io) }
|
||||
}
|
||||
}
|
||||
|
||||
impl Drop for WasiFd {
|
||||
fn drop(&mut self) {
|
||||
unsafe {
|
||||
// FIXME: can we handle the return code here even though we can't on
|
||||
// unix?
|
||||
libc::__wasi_fd_close(self.fd);
|
||||
}
|
||||
// FIXME: can we handle the return code here even though we can't on
|
||||
// unix?
|
||||
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::ptr;
|
||||
use crate::sync::Arc;
|
||||
use crate::sys::fd::{DirCookie, WasiFd};
|
||||
use crate::sys::fd::WasiFd;
|
||||
use crate::sys::time::SystemTime;
|
||||
use crate::sys::unsupported;
|
||||
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::remove_dir_all;
|
||||
|
||||
use ::wasi::wasi_unstable as wasi;
|
||||
|
||||
pub struct File {
|
||||
fd: WasiFd,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct FileAttr {
|
||||
meta: libc::__wasi_filestat_t,
|
||||
meta: wasi::FileStat,
|
||||
}
|
||||
|
||||
pub struct ReadDir {
|
||||
inner: Arc<ReadDirInner>,
|
||||
cookie: Option<DirCookie>,
|
||||
cookie: Option<wasi::DirCookie>,
|
||||
buf: Vec<u8>,
|
||||
offset: usize,
|
||||
cap: usize,
|
||||
|
@ -38,7 +40,7 @@ struct ReadDirInner {
|
|||
}
|
||||
|
||||
pub struct DirEntry {
|
||||
meta: libc::__wasi_dirent_t,
|
||||
meta: wasi::Dirent,
|
||||
name: Vec<u8>,
|
||||
inner: Arc<ReadDirInner>,
|
||||
}
|
||||
|
@ -47,11 +49,11 @@ pub struct DirEntry {
|
|||
pub struct OpenOptions {
|
||||
read: bool,
|
||||
write: bool,
|
||||
dirflags: libc::__wasi_lookupflags_t,
|
||||
fdflags: libc::__wasi_fdflags_t,
|
||||
oflags: libc::__wasi_oflags_t,
|
||||
rights_base: Option<libc::__wasi_rights_t>,
|
||||
rights_inheriting: Option<libc::__wasi_rights_t>,
|
||||
dirflags: wasi::LookupFlags,
|
||||
fdflags: wasi::FdFlags,
|
||||
oflags: wasi::OFlags,
|
||||
rights_base: Option<wasi::Rights>,
|
||||
rights_inheriting: Option<wasi::Rights>,
|
||||
}
|
||||
|
||||
#[derive(Clone, PartialEq, Eq, Debug)]
|
||||
|
@ -61,19 +63,13 @@ pub struct FilePermissions {
|
|||
|
||||
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
|
||||
pub struct FileType {
|
||||
bits: libc::__wasi_filetype_t,
|
||||
bits: wasi::FileType,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct DirBuilder {}
|
||||
|
||||
impl FileAttr {
|
||||
fn zero() -> FileAttr {
|
||||
FileAttr {
|
||||
meta: unsafe { mem::zeroed() },
|
||||
}
|
||||
}
|
||||
|
||||
pub fn size(&self) -> u64 {
|
||||
self.meta.st_size
|
||||
}
|
||||
|
@ -101,7 +97,7 @@ impl FileAttr {
|
|||
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
|
||||
}
|
||||
}
|
||||
|
@ -118,18 +114,18 @@ impl FilePermissions {
|
|||
|
||||
impl FileType {
|
||||
pub fn is_dir(&self) -> bool {
|
||||
self.bits == libc::__WASI_FILETYPE_DIRECTORY
|
||||
self.bits == wasi::FILETYPE_DIRECTORY
|
||||
}
|
||||
|
||||
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 {
|
||||
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
|
||||
}
|
||||
}
|
||||
|
@ -173,7 +169,7 @@ impl Iterator for ReadDir {
|
|||
// 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
|
||||
// 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 {
|
||||
assert!(self.cookie.is_some());
|
||||
assert!(self.buf.len() >= dirent_size);
|
||||
|
@ -182,7 +178,7 @@ impl Iterator for ReadDir {
|
|||
}
|
||||
let (dirent, data) = data.split_at(dirent_size);
|
||||
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
|
||||
// `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
|
||||
}
|
||||
}
|
||||
|
@ -249,7 +245,7 @@ impl DirEntry {
|
|||
impl OpenOptions {
|
||||
pub fn new() -> OpenOptions {
|
||||
let mut base = OpenOptions::default();
|
||||
base.dirflags = libc::__WASI_LOOKUP_SYMLINK_FOLLOW;
|
||||
base.dirflags = wasi::LOOKUP_SYMLINK_FOLLOW;
|
||||
return base;
|
||||
}
|
||||
|
||||
|
@ -262,23 +258,23 @@ impl OpenOptions {
|
|||
}
|
||||
|
||||
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) {
|
||||
self.oflag(libc::__WASI_O_CREAT, create);
|
||||
self.oflag(wasi::O_CREAT, create);
|
||||
}
|
||||
|
||||
pub fn create_new(&mut self, create_new: bool) {
|
||||
self.oflag(libc::__WASI_O_EXCL, create_new);
|
||||
self.oflag(libc::__WASI_O_CREAT, create_new);
|
||||
self.oflag(wasi::O_EXCL, create_new);
|
||||
self.oflag(wasi::O_CREAT, create_new);
|
||||
}
|
||||
|
||||
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 {
|
||||
self.oflags |= bit;
|
||||
} else {
|
||||
|
@ -287,26 +283,26 @@ impl OpenOptions {
|
|||
}
|
||||
|
||||
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) {
|
||||
self.fdflag(libc::__WASI_FDFLAG_DSYNC, set);
|
||||
self.fdflag(wasi::FDFLAG_DSYNC, set);
|
||||
}
|
||||
|
||||
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) {
|
||||
self.fdflag(libc::__WASI_FDFLAG_RSYNC, set);
|
||||
self.fdflag(wasi::FDFLAG_RSYNC, set);
|
||||
}
|
||||
|
||||
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 {
|
||||
self.fdflags |= bit;
|
||||
} 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);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
fn rights_base(&self) -> libc::__wasi_rights_t {
|
||||
fn rights_base(&self) -> wasi::Rights {
|
||||
if let Some(rights) = self.rights_base {
|
||||
return rights;
|
||||
}
|
||||
|
@ -334,52 +330,52 @@ impl OpenOptions {
|
|||
// based on that.
|
||||
let mut base = 0;
|
||||
if self.read {
|
||||
base |= libc::__WASI_RIGHT_FD_READ;
|
||||
base |= libc::__WASI_RIGHT_FD_READDIR;
|
||||
base |= wasi::RIGHT_FD_READ;
|
||||
base |= wasi::RIGHT_FD_READDIR;
|
||||
}
|
||||
if self.write {
|
||||
base |= libc::__WASI_RIGHT_FD_WRITE;
|
||||
base |= libc::__WASI_RIGHT_FD_DATASYNC;
|
||||
base |= libc::__WASI_RIGHT_FD_ALLOCATE;
|
||||
base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_SIZE;
|
||||
base |= wasi::RIGHT_FD_WRITE;
|
||||
base |= wasi::RIGHT_FD_DATASYNC;
|
||||
base |= wasi::RIGHT_FD_ALLOCATE;
|
||||
base |= wasi::RIGHT_FD_FILESTAT_SET_SIZE;
|
||||
}
|
||||
|
||||
// FIXME: some of these should probably be read-only or write-only...
|
||||
base |= libc::__WASI_RIGHT_FD_ADVISE;
|
||||
base |= libc::__WASI_RIGHT_FD_FDSTAT_SET_FLAGS;
|
||||
base |= libc::__WASI_RIGHT_FD_FILESTAT_SET_TIMES;
|
||||
base |= libc::__WASI_RIGHT_FD_SEEK;
|
||||
base |= libc::__WASI_RIGHT_FD_SYNC;
|
||||
base |= libc::__WASI_RIGHT_FD_TELL;
|
||||
base |= libc::__WASI_RIGHT_PATH_CREATE_DIRECTORY;
|
||||
base |= libc::__WASI_RIGHT_PATH_CREATE_FILE;
|
||||
base |= libc::__WASI_RIGHT_PATH_FILESTAT_GET;
|
||||
base |= libc::__WASI_RIGHT_PATH_LINK_SOURCE;
|
||||
base |= libc::__WASI_RIGHT_PATH_LINK_TARGET;
|
||||
base |= libc::__WASI_RIGHT_PATH_OPEN;
|
||||
base |= libc::__WASI_RIGHT_PATH_READLINK;
|
||||
base |= libc::__WASI_RIGHT_PATH_REMOVE_DIRECTORY;
|
||||
base |= libc::__WASI_RIGHT_PATH_RENAME_SOURCE;
|
||||
base |= libc::__WASI_RIGHT_PATH_RENAME_TARGET;
|
||||
base |= libc::__WASI_RIGHT_PATH_SYMLINK;
|
||||
base |= libc::__WASI_RIGHT_PATH_UNLINK_FILE;
|
||||
base |= libc::__WASI_RIGHT_POLL_FD_READWRITE;
|
||||
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;
|
||||
|
||||
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())
|
||||
}
|
||||
|
||||
pub fn lookup_flags(&mut self, flags: libc::__wasi_lookupflags_t) {
|
||||
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, libc::__WASI_RIGHT_PATH_OPEN)?;
|
||||
let (dir, file) = open_parent(path, wasi::RIGHT_PATH_OPEN)?;
|
||||
open_at(&dir, &file, opts)
|
||||
}
|
||||
|
||||
|
@ -388,14 +384,12 @@ impl File {
|
|||
}
|
||||
|
||||
pub fn file_attr(&self) -> io::Result<FileAttr> {
|
||||
let mut ret = FileAttr::zero();
|
||||
self.fd.filestat_get(&mut ret.meta)?;
|
||||
Ok(ret)
|
||||
self.fd.filestat_get().map(|meta| FileAttr { meta })
|
||||
}
|
||||
|
||||
pub fn metadata_at(
|
||||
&self,
|
||||
flags: libc::__wasi_lookupflags_t,
|
||||
flags: wasi::LookupFlags,
|
||||
path: &Path,
|
||||
) -> io::Result<FileAttr> {
|
||||
metadata_at(&self.fd, flags, path)
|
||||
|
@ -477,7 +471,7 @@ impl DirBuilder {
|
|||
}
|
||||
|
||||
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())
|
||||
}
|
||||
}
|
||||
|
@ -508,13 +502,13 @@ pub fn readdir(p: &Path) -> io::Result<ReadDir> {
|
|||
}
|
||||
|
||||
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())
|
||||
}
|
||||
|
||||
pub fn rename(old: &Path, new: &Path) -> io::Result<()> {
|
||||
let (old, old_file) = open_parent(old, libc::__WASI_RIGHT_PATH_RENAME_SOURCE)?;
|
||||
let (new, new_file) = open_parent(new, libc::__WASI_RIGHT_PATH_RENAME_TARGET)?;
|
||||
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,
|
||||
|
@ -529,12 +523,12 @@ pub fn set_perm(_p: &Path, _perm: FilePermissions) -> 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())
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -570,15 +564,15 @@ 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, 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())
|
||||
}
|
||||
|
||||
pub fn link(src: &Path, dst: &Path) -> io::Result<()> {
|
||||
let (src, src_file) = open_parent(src, libc::__WASI_RIGHT_PATH_LINK_SOURCE)?;
|
||||
let (dst, dst_file) = open_parent(dst, libc::__WASI_RIGHT_PATH_LINK_TARGET)?;
|
||||
let (src, src_file) = open_parent(src, wasi::RIGHT_PATH_LINK_SOURCE)?;
|
||||
let (dst, dst_file) = open_parent(dst, wasi::RIGHT_PATH_LINK_TARGET)?;
|
||||
src.link(
|
||||
libc::__WASI_LOOKUP_SYMLINK_FOLLOW,
|
||||
wasi::LOOKUP_SYMLINK_FOLLOW,
|
||||
src_file.as_os_str().as_bytes(),
|
||||
&dst,
|
||||
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> {
|
||||
let (dir, file) = open_parent(p, libc::__WASI_RIGHT_PATH_FILESTAT_GET)?;
|
||||
metadata_at(&dir, libc::__WASI_LOOKUP_SYMLINK_FOLLOW, &file)
|
||||
let (dir, file) = open_parent(p, wasi::RIGHT_PATH_FILESTAT_GET)?;
|
||||
metadata_at(&dir, wasi::LOOKUP_SYMLINK_FOLLOW, &file)
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
fn metadata_at(
|
||||
fd: &WasiFd,
|
||||
flags: libc::__wasi_lookupflags_t,
|
||||
flags: wasi::LookupFlags,
|
||||
path: &Path,
|
||||
) -> io::Result<FileAttr> {
|
||||
let mut ret = FileAttr::zero();
|
||||
fd.path_filestat_get(flags, path.as_os_str().as_bytes(), &mut ret.meta)?;
|
||||
Ok(ret)
|
||||
fd.path_filestat_get(flags, path.as_os_str().as_bytes())
|
||||
.map(|meta| FileAttr { meta })
|
||||
}
|
||||
|
||||
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.
|
||||
fn open_parent(
|
||||
p: &Path,
|
||||
rights: libc::__wasi_rights_t,
|
||||
rights: wasi::Rights,
|
||||
) -> io::Result<(ManuallyDrop<WasiFd>, PathBuf)> {
|
||||
let p = CString::new(p.as_os_str().as_bytes())?;
|
||||
unsafe {
|
||||
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 {
|
||||
let msg = format!(
|
||||
"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));
|
||||
}
|
||||
|
||||
// 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::slice;
|
||||
|
||||
use libc::{__wasi_ciovec_t, __wasi_iovec_t, c_void};
|
||||
use ::wasi::wasi_unstable as wasi;
|
||||
use core::ffi::c_void;
|
||||
|
||||
#[repr(transparent)]
|
||||
pub struct IoSlice<'a> {
|
||||
vec: __wasi_ciovec_t,
|
||||
vec: wasi::CIoVec,
|
||||
_p: PhantomData<&'a [u8]>,
|
||||
}
|
||||
|
||||
|
@ -13,7 +14,7 @@ impl<'a> IoSlice<'a> {
|
|||
#[inline]
|
||||
pub fn new(buf: &'a [u8]) -> IoSlice<'a> {
|
||||
IoSlice {
|
||||
vec: __wasi_ciovec_t {
|
||||
vec: wasi::CIoVec {
|
||||
buf: buf.as_ptr() as *const c_void,
|
||||
buf_len: buf.len(),
|
||||
},
|
||||
|
@ -43,7 +44,7 @@ impl<'a> IoSlice<'a> {
|
|||
|
||||
#[repr(transparent)]
|
||||
pub struct IoSliceMut<'a> {
|
||||
vec: __wasi_iovec_t,
|
||||
vec: wasi::IoVec,
|
||||
_p: PhantomData<&'a mut [u8]>,
|
||||
}
|
||||
|
||||
|
@ -51,7 +52,7 @@ impl<'a> IoSliceMut<'a> {
|
|||
#[inline]
|
||||
pub fn new(buf: &'a mut [u8]) -> IoSliceMut<'a> {
|
||||
IoSliceMut {
|
||||
vec: __wasi_iovec_t {
|
||||
vec: wasi::IoVec {
|
||||
buf: buf.as_mut_ptr() as *mut c_void,
|
||||
buf_len: buf.len()
|
||||
},
|
||||
|
|
|
@ -14,10 +14,10 @@
|
|||
//! compiling for wasm. That way it's a compile time error for something that's
|
||||
//! guaranteed to be a runtime error!
|
||||
|
||||
use libc;
|
||||
use crate::io::{Error, ErrorKind};
|
||||
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;
|
||||
|
@ -56,31 +56,42 @@ pub mod ext;
|
|||
pub fn init() {
|
||||
}
|
||||
|
||||
pub fn unsupported<T>() -> crate::io::Result<T> {
|
||||
pub fn unsupported<T>() -> std_io::Result<T> {
|
||||
Err(unsupported_err())
|
||||
}
|
||||
|
||||
pub fn unsupported_err() -> Error {
|
||||
Error::new(ErrorKind::Other, "operation not supported on wasm yet")
|
||||
pub fn unsupported_err() -> std_io::Error {
|
||||
std_io::Error::new(
|
||||
std_io::ErrorKind::Other,
|
||||
"operation not supported on wasm yet",
|
||||
)
|
||||
}
|
||||
|
||||
pub fn decode_error_kind(errno: i32) -> ErrorKind {
|
||||
match errno as libc::c_int {
|
||||
libc::ECONNREFUSED => ErrorKind::ConnectionRefused,
|
||||
libc::ECONNRESET => ErrorKind::ConnectionReset,
|
||||
libc::EPERM | libc::EACCES => ErrorKind::PermissionDenied,
|
||||
libc::EPIPE => ErrorKind::BrokenPipe,
|
||||
libc::ENOTCONN => ErrorKind::NotConnected,
|
||||
libc::ECONNABORTED => ErrorKind::ConnectionAborted,
|
||||
libc::EADDRNOTAVAIL => ErrorKind::AddrNotAvailable,
|
||||
libc::EADDRINUSE => ErrorKind::AddrInUse,
|
||||
libc::ENOENT => ErrorKind::NotFound,
|
||||
libc::EINTR => ErrorKind::Interrupted,
|
||||
libc::EINVAL => ErrorKind::InvalidInput,
|
||||
libc::ETIMEDOUT => ErrorKind::TimedOut,
|
||||
libc::EEXIST => ErrorKind::AlreadyExists,
|
||||
libc::EAGAIN => ErrorKind::WouldBlock,
|
||||
_ => ErrorKind::Other,
|
||||
pub fn decode_error_kind(errno: i32) -> std_io::ErrorKind {
|
||||
use 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,
|
||||
_ => Other,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -105,40 +116,16 @@ 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 libc::c_void;
|
||||
let base = &mut ret as *mut (u64, u64) as *mut core::ffi::c_void;
|
||||
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
|
||||
}
|
||||
|
||||
#[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 }
|
||||
|
||||
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(())
|
||||
}
|
||||
fn err2io(err: wasi::Error) -> std_io::Error {
|
||||
std_io::Error::from_raw_os_error(err.get() as i32)
|
||||
}
|
||||
|
|
|
@ -9,7 +9,7 @@ use crate::path::{self, PathBuf};
|
|||
use crate::ptr;
|
||||
use crate::str;
|
||||
use crate::sys::memchr;
|
||||
use crate::sys::{cvt, unsupported, Void};
|
||||
use crate::sys::{unsupported, Void};
|
||||
use crate::vec;
|
||||
|
||||
#[cfg(not(target_feature = "atomics"))]
|
||||
|
@ -28,16 +28,11 @@ pub fn errno() -> i32 {
|
|||
}
|
||||
|
||||
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 p = buf.as_mut_ptr();
|
||||
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");
|
||||
}
|
||||
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> {
|
||||
unsupported()
|
||||
}
|
||||
|
||||
pub struct Env {
|
||||
iter: vec::IntoIter<(OsString, OsString)>,
|
||||
_dont_send_or_sync_me: PhantomData<*mut ()>,
|
||||
|
@ -182,3 +176,26 @@ pub fn exit(code: i32) -> ! {
|
|||
pub fn getpid() -> u32 {
|
||||
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::libc;
|
||||
use crate::mem::ManuallyDrop;
|
||||
use crate::sys::fd::WasiFd;
|
||||
|
||||
use ::wasi::wasi_unstable as wasi;
|
||||
|
||||
pub struct Stdin;
|
||||
pub struct Stdout;
|
||||
pub struct Stderr;
|
||||
|
@ -17,7 +18,7 @@ impl Stdin {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
}
|
||||
|
@ -32,7 +33,7 @@ impl Stdout {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -51,7 +52,7 @@ impl Stderr {
|
|||
}
|
||||
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -73,7 +74,7 @@ impl io::Write for Stderr {
|
|||
pub const STDIN_BUF_SIZE: usize = crate::sys_common::io::DEFAULT_BUF_SIZE;
|
||||
|
||||
pub fn is_ebadf(err: &io::Error) -> bool {
|
||||
err.raw_os_error() == Some(libc::__WASI_EBADF as i32)
|
||||
err.raw_os_error() == Some(wasi::EBADF.get() as i32)
|
||||
}
|
||||
|
||||
pub fn panic_output() -> Option<impl io::Write> {
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
use crate::cmp;
|
||||
use crate::ffi::CStr;
|
||||
use crate::io;
|
||||
use crate::sys::cvt;
|
||||
use crate::mem;
|
||||
use crate::sys::{unsupported, Void};
|
||||
use crate::time::Duration;
|
||||
use libc;
|
||||
|
||||
use ::wasi::wasi_unstable as wasi;
|
||||
|
||||
pub struct Thread(Void);
|
||||
|
||||
|
@ -19,8 +19,8 @@ impl Thread {
|
|||
}
|
||||
|
||||
pub fn yield_now() {
|
||||
let ret = unsafe { libc::__wasi_sched_yield() };
|
||||
debug_assert_eq!(ret, 0);
|
||||
let ret = wasi::sched_yield();
|
||||
debug_assert_eq!(ret, Ok(()));
|
||||
}
|
||||
|
||||
pub fn set_name(_name: &CStr) {
|
||||
|
@ -28,19 +28,37 @@ impl Thread {
|
|||
}
|
||||
|
||||
pub fn sleep(dur: Duration) {
|
||||
let mut secs = dur.as_secs();
|
||||
let mut nsecs = dur.subsec_nanos() as i32;
|
||||
let nanos = dur.as_nanos();
|
||||
assert!(nanos <= u64::max_value() as u128);
|
||||
|
||||
unsafe {
|
||||
while secs > 0 || nsecs > 0 {
|
||||
let mut ts = libc::timespec {
|
||||
tv_sec: cmp::min(libc::time_t::max_value() as u64, secs) as libc::time_t,
|
||||
tv_nsec: nsecs,
|
||||
};
|
||||
secs -= ts.tv_sec as u64;
|
||||
cvt(libc::nanosleep(&ts, &mut ts)).unwrap();
|
||||
nsecs = 0;
|
||||
}
|
||||
const CLOCK_ID: wasi::Userdata = 0x0123_45678;
|
||||
|
||||
let clock = wasi::raw::__wasi_subscription_u_clock_t {
|
||||
identifier: CLOCK_ID,
|
||||
clock_id: wasi::CLOCK_MONOTONIC,
|
||||
timeout: nanos as u64,
|
||||
precision: 0,
|
||||
flags: 0,
|
||||
};
|
||||
|
||||
let in_ = [wasi::Subscription {
|
||||
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::mem;
|
||||
use crate::sys::cvt_wasi;
|
||||
use libc;
|
||||
use ::wasi::wasi_unstable as wasi;
|
||||
|
||||
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Hash)]
|
||||
pub struct Instant(Duration);
|
||||
|
@ -12,23 +10,19 @@ pub struct SystemTime(Duration);
|
|||
pub const UNIX_EPOCH: SystemTime = SystemTime(Duration::from_secs(0));
|
||||
|
||||
fn current_time(clock: u32) -> Duration {
|
||||
unsafe {
|
||||
let mut ts = mem::zeroed();
|
||||
cvt_wasi(libc::__wasi_clock_time_get(
|
||||
clock,
|
||||
1, // precision... seems ignored though?
|
||||
&mut ts,
|
||||
)).unwrap();
|
||||
Duration::new(
|
||||
(ts / 1_000_000_000) as u64,
|
||||
(ts % 1_000_000_000) as u32,
|
||||
)
|
||||
}
|
||||
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,
|
||||
)
|
||||
}
|
||||
|
||||
impl Instant {
|
||||
pub fn now() -> Instant {
|
||||
Instant(current_time(libc::__WASI_CLOCK_MONOTONIC))
|
||||
Instant(current_time(wasi::CLOCK_MONOTONIC))
|
||||
}
|
||||
|
||||
pub const fn zero() -> Instant {
|
||||
|
@ -54,10 +48,10 @@ impl Instant {
|
|||
|
||||
impl 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))
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ const LICENSES: &[&str] = &[
|
|||
"Apache-2.0 / MIT",
|
||||
"MIT OR Apache-2.0",
|
||||
"Apache-2.0 OR MIT",
|
||||
"Apache-2.0 WITH LLVM-exception OR Apache-2.0 OR MIT", // wasi license
|
||||
"MIT",
|
||||
"Unlicense/MIT",
|
||||
"Unlicense OR MIT",
|
||||
|
@ -172,6 +173,7 @@ const WHITELIST: &[Crate<'_>] = &[
|
|||
Crate("vcpkg"),
|
||||
Crate("version_check"),
|
||||
Crate("void"),
|
||||
Crate("wasi"),
|
||||
Crate("winapi"),
|
||||
Crate("winapi-build"),
|
||||
Crate("winapi-i686-pc-windows-gnu"),
|
||||
|
|
Loading…
Add table
Reference in a new issue