Files
wasmtime/crates/wasi-common/src/host.rs
Dan Gohman c2ba419409 Misc yanix fixes (#715)
* Correctly handle possibly misaligned pointers in readdir

This reapplies #615, which was inadvertently reverted.

* Tidy up unneeded `self::` qualifiers.

* Make Dir's contents private.

Also remove the `unsafe` from `impl_iter`. With `Dir`'s field being
private, we can rely on the pointer being only what we've assigned to
it.

* Make `poll`'s timeout argument a `libc::c_int`.

This clarifies that there are no subsequent conversions before calling the
underlying libc API.

* Use clock_gettime instead of clock_getres to get the time.

* Mark FileType::from_raw as safe.

It handles unknown values, so it can be marked safe.
2019-12-16 13:34:22 -08:00

169 lines
5.1 KiB
Rust

//! WASI host types. These are types that contain raw pointers and `usize`
//! values, and so are platform-specific.
#![allow(non_camel_case_types)]
#![allow(non_snake_case)]
use crate::wasi::*;
use crate::{Error, Result};
use std::{convert::TryInto, io, mem, slice};
use wig::witx_host_types;
witx_host_types!("snapshot" "wasi_snapshot_preview1");
pub(crate) unsafe fn ciovec_to_host(ciovec: &__wasi_ciovec_t) -> io::IoSlice {
let slice = slice::from_raw_parts(ciovec.buf as *const u8, ciovec.buf_len);
io::IoSlice::new(slice)
}
pub(crate) unsafe fn iovec_to_host_mut(iovec: &mut __wasi_iovec_t) -> io::IoSliceMut {
let slice = slice::from_raw_parts_mut(iovec.buf as *mut u8, iovec.buf_len);
io::IoSliceMut::new(slice)
}
#[allow(dead_code)] // trouble with sockets
#[derive(Clone, Copy, Debug)]
#[repr(u8)]
pub(crate) enum FileType {
Unknown = __WASI_FILETYPE_UNKNOWN,
BlockDevice = __WASI_FILETYPE_BLOCK_DEVICE,
CharacterDevice = __WASI_FILETYPE_CHARACTER_DEVICE,
Directory = __WASI_FILETYPE_DIRECTORY,
RegularFile = __WASI_FILETYPE_REGULAR_FILE,
SocketDgram = __WASI_FILETYPE_SOCKET_DGRAM,
SocketStream = __WASI_FILETYPE_SOCKET_STREAM,
Symlink = __WASI_FILETYPE_SYMBOLIC_LINK,
}
impl FileType {
pub(crate) fn to_wasi(&self) -> __wasi_filetype_t {
*self as __wasi_filetype_t
}
}
#[derive(Debug, Clone)]
pub(crate) struct Dirent {
pub name: String,
pub ftype: FileType,
pub ino: u64,
pub cookie: __wasi_dircookie_t,
}
impl Dirent {
/// Serialize the directory entry to the format define by `__wasi_fd_readdir`,
/// so that the serialized entries can be concatenated by the implementation.
pub fn to_wasi_raw(&self) -> Result<Vec<u8>> {
let name = self.name.as_bytes();
let namlen = name.len();
let dirent_size = mem::size_of::<__wasi_dirent_t>();
let offset = dirent_size.checked_add(namlen).ok_or(Error::EOVERFLOW)?;
let mut raw = Vec::<u8>::with_capacity(offset);
raw.resize(offset, 0);
let sys_dirent = raw.as_mut_ptr() as *mut __wasi_dirent_t;
unsafe {
sys_dirent.write_unaligned(__wasi_dirent_t {
d_namlen: namlen.try_into()?,
d_ino: self.ino,
d_next: self.cookie,
d_type: self.ftype.to_wasi(),
});
}
let sys_name = unsafe { sys_dirent.offset(1) as *mut u8 };
let sys_name = unsafe { slice::from_raw_parts_mut(sys_name, namlen) };
sys_name.copy_from_slice(&name);
Ok(raw)
}
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn bindgen_test_layout___wasi_prestat_t() {
assert_eq!(
::std::mem::size_of::<__wasi_prestat_t>(),
16usize,
concat!("Size of: ", stringify!(__wasi_prestat_t))
);
assert_eq!(
::std::mem::align_of::<__wasi_prestat_t>(),
8usize,
concat!("Alignment of ", stringify!(__wasi_prestat_t))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<__wasi_prestat_t>())).pr_type as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(__wasi_prestat_t),
"::",
stringify!(pr_type)
)
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<__wasi_prestat_t>())).u as *const _ as usize },
8usize,
concat!(
"Offset of field: ",
stringify!(__wasi_prestat_t),
"::",
stringify!(u)
)
);
}
#[test]
fn bindgen_test_layout___wasi_prestat_t___wasi_prestat_u___wasi_prestat_u_dir_t() {
assert_eq!(
::std::mem::size_of::<__wasi_prestat_dir_t>(),
8usize,
concat!("Size of: ", stringify!(__wasi_prestat_dir_t))
);
assert_eq!(
::std::mem::align_of::<__wasi_prestat_dir_t>(),
8usize,
concat!("Alignment of ", stringify!(__wasi_prestat_dir_t))
);
assert_eq!(
unsafe {
&(*(::std::ptr::null::<__wasi_prestat_dir_t>())).pr_name_len as *const _ as usize
},
0usize,
concat!(
"Offset of field: ",
stringify!(__wasi_prestat_dir_t),
"::",
stringify!(pr_name_len)
)
);
}
#[test]
fn bindgen_test_layout___wasi_prestat_t___wasi_prestat_u() {
assert_eq!(
::std::mem::size_of::<__wasi_prestat_u_t>(),
8usize,
concat!("Size of: ", stringify!(__wasi_prestat_u))
);
assert_eq!(
::std::mem::align_of::<__wasi_prestat_u_t>(),
8usize,
concat!("Alignment of ", stringify!(__wasi_prestat_u))
);
assert_eq!(
unsafe { &(*(::std::ptr::null::<__wasi_prestat_u_t>())).dir as *const _ as usize },
0usize,
concat!(
"Offset of field: ",
stringify!(__wasi_prestat_u_t),
"::",
stringify!(dir)
)
);
}
}