use wasi crate

This commit is contained in:
newpavlov 2019-08-19 09:47:58 +03:00
parent bd1da18b04
commit 6896ed383d
11 changed files with 247 additions and 374 deletions

View file

@ -27,14 +27,24 @@ pub fn args() -> Args {
})
}
fn cvt_wasi(r: u16) -> crate::io::Result<()> {
if r != 0 {
Err(Error::from_raw_os_error(r as i32))
} else {
Ok(())
}
}
fn maybe_args() -> io::Result<Args> {
// FIXME: replace with safe functions
use wasi::wasi_unstable::raw::{__wasi_args_sizes_get, __wasi_args_get};
unsafe {
let (mut argc, mut argv_buf_size) = (0, 0);
cvt_wasi(libc::__wasi_args_sizes_get(&mut argc, &mut argv_buf_size))?;
cvt_wasi(__wasi_args_sizes_get(&mut argc, &mut argv_buf_size))?;
let mut argc = vec![core::ptr::null_mut::<libc::c_char>(); argc];
let mut argc = vec![core::ptr::null_mut::<u8>(); 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()))?;
cvt_wasi(__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())

View file

@ -336,16 +336,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
}
}

View file

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

View file

@ -3,348 +3,240 @@
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 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: &mut [IoSliceMut<'_>]) -> &[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: &[IoSlice<'_>]) -> &[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) })
wasi::fd_datasync(self.fd).map_err(From::from)
}
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)
wasi::fd_pread(self.fd, iovec(bufs), offset).map_err(From::from)
}
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)
wasi::fd_pwrite(self.fd, ciovec(bufs), offset).map_err(From::from)
}
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)
wasi::fd_read(self.fd, iovec(bufs)).map_err(From::from)
}
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)
wasi::fd_write(self.fd, ciovec(bufs)).map_err(From::from)
}
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)
wasi::fd_seek(self.fd, offset, whence).map_err(From::from)
}
pub fn tell(&self) -> io::Result<u64> {
let mut pos = 0;
cvt_wasi(unsafe { libc::__wasi_fd_tell(self.fd, &mut pos) })?;
Ok(pos)
wasi::fd_tell(self.fd).map_err(From::from)
}
// 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<()> {
wasi::fd_fdstat_set_flags(self.fd, flags).map_err(From::from)
}
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<()> {
wasi::fd_fdstat_set_rights(self.fd, base, inheriting).map_err(From::from)
}
pub fn sync(&self) -> io::Result<()> {
cvt_wasi(unsafe { libc::__wasi_fd_sync(self.fd) })
wasi::fd_sync(self.fd).map_err(From::from)
}
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<()> {
wasi::fd_advise(self.fd, offset, len, advice).map_err(From::from)
}
pub fn allocate(&self, offset: u64, len: u64) -> io::Result<()> {
cvt_wasi(unsafe { libc::__wasi_fd_allocate(self.fd, offset, len) })
wasi::fd_allocate(self.fd, offset, len).map_err(From::from)
}
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())
})
wasi::path_create_directory(self.fd, path).map_err(From::from)
}
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(),
)
})
wasi::path_link(self.fd, old_flags, old_path, new_fd.fd, new_path)
.map_err(From::from)
}
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(
self.fd,
dirflags,
path.as_ptr() as *const c_char,
path.len(),
oflags,
fs_rights_base,
fs_rights_inheriting,
fs_flags,
&mut fd,
))?;
Ok(WasiFd::from_raw(fd))
}
let fd = wasi_path_open(
self.fd,
dirflags,
path,
oflags,
fs_rights_base,
fs_rights_inheriting,
fs_flags,
)?;
Ok(WasiFd::from_raw(fd))
}
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> {
wasi::fd_readdir(self.fd, buf, cookie).map_err(From::from)
}
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)
wasi::path_readlink(self.fd, path, buf).map_err(From::from)
}
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(),
)
})
wasi::path_rename(self.fd, old_path, new_fd.fd, new_path)
.map_err(From::from)
}
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> {
wasi::fd_filestat_get(self.fd, buf).map_err(From::from)
}
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) })
wasi::fd_filestat_set_times(self.fd, atim, mtim, fstflags)
.map_err(From::from)
}
pub fn filestat_set_size(&self, size: u64) -> io::Result<()> {
cvt_wasi(unsafe { libc::__wasi_fd_filestat_set_size(self.fd, size) })
wasi::fd_filestat_set_size(self.fd, size).map_err(From::from)
}
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> {
wasi::path_filestat_get(self.fd, flags, path).map_err(From::from)
}
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(
self.fd,
flags,
path.as_ptr() as *const c_char,
path.len(),
atim,
mtim,
fstflags,
)
})
wasi::path_filestat_set_times(
self.fd,
flags,
path,
atim,
mtim,
fstflags,
).map_err(From::from)
}
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(),
)
})
wasi::path_symlink(old_path, self.fd, new_path).map_err(From::from)
}
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())
})
wasi::path_unlink_file(self.fd, path).map_err(From::from)
}
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())
})
wasi::path_remove_directory(self.fd, path).map_err(From::from)
}
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)> {
wasi::sock_recv(self.fd, iovec(ri_data), ri_flags).map_err(From::from)
}
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> {
wasi::sock_send(self.fd, ciovec(si_data), si_flags).map_err(From::from)
}
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(())
wasi::sock_shutdown(self.fd, how).map_err(From::from)
}
}
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 _ = wasi::fd_close(self.fd);
}
}

View file

@ -15,13 +15,15 @@ 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 {
@ -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,7 +63,7 @@ pub struct FilePermissions {
#[derive(PartialEq, Eq, Hash, Debug, Copy, Clone)]
pub struct FileType {
bits: libc::__wasi_filetype_t,
bits: wasi::FileType,
}
#[derive(Debug)]
@ -101,7 +103,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 +120,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 +175,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 +184,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 +243,7 @@ impl DirEntry {
})
}
pub fn ino(&self) -> libc::__wasi_inode_t {
pub fn ino(&self) -> wasi::Inode {
self.meta.d_ino
}
}
@ -249,7 +251,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 +264,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 +289,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 +316,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 +336,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 +390,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_ok(|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 +477,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 +508,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 +529,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 +570,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 +586,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_ok(|meta| FileAttr { meta })
}
pub fn canonicalize(_p: &Path) -> io::Result<PathBuf> {
@ -652,12 +651,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 +676,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;
}
}

View file

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

View file

@ -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;
use crate::mem;
use crate::os::raw::c_char;
use wasi::wasi_unstable as wasi;
pub mod alloc;
pub mod args;
@ -60,12 +60,12 @@ pub fn unsupported<T>() -> crate::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() -> io::Error {
io::Error::new(io::ErrorKind::Other, "operation not supported on wasm yet")
}
pub fn decode_error_kind(_code: i32) -> ErrorKind {
ErrorKind::Other
pub fn decode_error_kind(_code: i32) -> io::ErrorKind {
io::ErrorKind::Other
}
// This enum is used as the storage for a bunch of types which can't actually
@ -83,15 +83,18 @@ pub unsafe fn strlen(mut s: *const c_char) -> usize {
}
pub unsafe fn abort_internal() -> ! {
libc::abort()
wasi::proc_exit(127)
}
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
}
@ -113,16 +116,14 @@ 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())
Err(io::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(())
impl From<wasi::Error> for io::Error {
fn from(err: wasi::Error) -> Self {
Self::from_raw_os_error(err as i32)
}
}

View file

@ -12,6 +12,8 @@ use crate::sys::memchr;
use crate::sys::{cvt, unsupported, Void};
use crate::vec;
use wasi::wasi_unstable as wasi;
#[cfg(not(target_feature = "atomics"))]
pub unsafe fn env_lock() -> impl Any {
// No need for a lock if we're single-threaded, but this function will need
@ -19,29 +21,11 @@ pub unsafe fn env_lock() -> impl Any {
}
pub fn errno() -> i32 {
extern {
#[thread_local]
static errno: libc::c_int;
}
unsafe { errno as i32 }
panic!("unsupported")
}
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 {
panic!("strerror_r failure");
}
str::from_utf8(CStr::from_ptr(p).to_bytes()).unwrap().to_owned()
}
wasi::error_string(errno).to_string()
}
pub fn getcwd() -> io::Result<PathBuf> {
@ -105,6 +89,7 @@ impl Iterator for Env {
pub fn env() -> Env {
unsafe {
let _guard = env_lock();
// FIXME: replace with wasi::environ_get
let mut environ = libc::environ;
let mut result = Vec::new();
while environ != ptr::null_mut() && *environ != ptr::null_mut() {
@ -174,9 +159,7 @@ pub fn home_dir() -> Option<PathBuf> {
}
pub fn exit(code: i32) -> ! {
unsafe {
libc::exit(code)
}
unsafe { wasi::proc_exit(code as u32) }
}
pub fn getpid() -> u32 {

View file

@ -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 as i32)
}
pub fn panic_output() -> Option<impl io::Write> {

View file

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

View file

@ -1,7 +1,6 @@
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 +11,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 +49,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))
}