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.
This commit is contained in:
@@ -63,12 +63,12 @@ impl Dirent {
|
|||||||
|
|
||||||
let sys_dirent = raw.as_mut_ptr() as *mut __wasi_dirent_t;
|
let sys_dirent = raw.as_mut_ptr() as *mut __wasi_dirent_t;
|
||||||
unsafe {
|
unsafe {
|
||||||
*sys_dirent = __wasi_dirent_t {
|
sys_dirent.write_unaligned(__wasi_dirent_t {
|
||||||
d_namlen: namlen.try_into()?,
|
d_namlen: namlen.try_into()?,
|
||||||
d_ino: self.ino,
|
d_ino: self.ino,
|
||||||
d_next: self.cookie,
|
d_next: self.cookie,
|
||||||
d_type: self.ftype.to_wasi(),
|
d_type: self.ftype.to_wasi(),
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let sys_name = unsafe { sys_dirent.offset(1) as *mut u8 };
|
let sys_name = unsafe { sys_dirent.offset(1) as *mut u8 };
|
||||||
|
|||||||
@@ -63,12 +63,12 @@ impl Dirent {
|
|||||||
|
|
||||||
let sys_dirent = raw.as_mut_ptr() as *mut __wasi_dirent_t;
|
let sys_dirent = raw.as_mut_ptr() as *mut __wasi_dirent_t;
|
||||||
unsafe {
|
unsafe {
|
||||||
*sys_dirent = __wasi_dirent_t {
|
sys_dirent.write_unaligned(__wasi_dirent_t {
|
||||||
d_namlen: namlen.try_into()?,
|
d_namlen: namlen.try_into()?,
|
||||||
d_ino: self.ino,
|
d_ino: self.ino,
|
||||||
d_next: self.cookie,
|
d_next: self.cookie,
|
||||||
d_type: self.ftype.to_wasi(),
|
d_type: self.ftype.to_wasi(),
|
||||||
};
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let sys_name = unsafe { sys_dirent.offset(1) as *mut u8 };
|
let sys_name = unsafe { sys_dirent.offset(1) as *mut u8 };
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
use crate::old::snapshot_0::hostcalls_impl::{ClockEventData, FdEventData};
|
use crate::old::snapshot_0::hostcalls_impl::{ClockEventData, FdEventData};
|
||||||
use crate::old::snapshot_0::sys::host_impl;
|
use crate::old::snapshot_0::sys::host_impl;
|
||||||
use crate::old::snapshot_0::{wasi, Error, Result};
|
use crate::old::snapshot_0::{wasi, Error, Result};
|
||||||
use yanix::clock::{clock_getres, ClockId};
|
use yanix::clock::{clock_getres, clock_gettime, ClockId};
|
||||||
|
|
||||||
fn wasi_clock_id_to_unix(clock_id: wasi::__wasi_clockid_t) -> Result<ClockId> {
|
fn wasi_clock_id_to_unix(clock_id: wasi::__wasi_clockid_t) -> Result<ClockId> {
|
||||||
// convert the supported clocks to libc types, or return EINVAL
|
// convert the supported clocks to libc types, or return EINVAL
|
||||||
@@ -39,7 +39,7 @@ pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__
|
|||||||
|
|
||||||
pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__wasi_timestamp_t> {
|
pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__wasi_timestamp_t> {
|
||||||
let clock_id = wasi_clock_id_to_unix(clock_id)?;
|
let clock_id = wasi_clock_id_to_unix(clock_id)?;
|
||||||
let timespec = clock_getres(clock_id)?;
|
let timespec = clock_gettime(clock_id)?;
|
||||||
|
|
||||||
// convert to nanoseconds, returning EOVERFLOW in case of overflow; this is freelancing a bit
|
// convert to nanoseconds, returning EOVERFLOW in case of overflow; this is freelancing a bit
|
||||||
// from the spec but seems like it'll be an unusual situation to hit
|
// from the spec but seems like it'll be an unusual situation to hit
|
||||||
|
|||||||
@@ -4,16 +4,16 @@ use cfg_if::cfg_if;
|
|||||||
cfg_if! {
|
cfg_if! {
|
||||||
if #[cfg(unix)] {
|
if #[cfg(unix)] {
|
||||||
mod unix;
|
mod unix;
|
||||||
pub(crate) use self::unix::*;
|
pub(crate) use unix::*;
|
||||||
pub use self::unix::preopen_dir;
|
pub use unix::preopen_dir;
|
||||||
|
|
||||||
pub(crate) fn errno_from_host(err: i32) -> wasi::__wasi_errno_t {
|
pub(crate) fn errno_from_host(err: i32) -> wasi::__wasi_errno_t {
|
||||||
host_impl::errno_from_nix(yanix::Errno::from_i32(err)).as_wasi_errno()
|
host_impl::errno_from_nix(yanix::Errno::from_i32(err)).as_wasi_errno()
|
||||||
}
|
}
|
||||||
} else if #[cfg(windows)] {
|
} else if #[cfg(windows)] {
|
||||||
mod windows;
|
mod windows;
|
||||||
pub(crate) use self::windows::*;
|
pub(crate) use windows::*;
|
||||||
pub use self::windows::preopen_dir;
|
pub use windows::preopen_dir;
|
||||||
|
|
||||||
pub(crate) fn errno_from_host(err: i32) -> wasi::__wasi_errno_t {
|
pub(crate) fn errno_from_host(err: i32) -> wasi::__wasi_errno_t {
|
||||||
host_impl::errno_from_win(winx::winerror::WinError::from_u32(err as u32))
|
host_impl::errno_from_win(winx::winerror::WinError::from_u32(err as u32))
|
||||||
|
|||||||
@@ -3,7 +3,7 @@
|
|||||||
use crate::hostcalls_impl::{ClockEventData, FdEventData};
|
use crate::hostcalls_impl::{ClockEventData, FdEventData};
|
||||||
use crate::sys::host_impl;
|
use crate::sys::host_impl;
|
||||||
use crate::{wasi, Error, Result};
|
use crate::{wasi, Error, Result};
|
||||||
use yanix::clock::{clock_getres, ClockId};
|
use yanix::clock::{clock_getres, clock_gettime, ClockId};
|
||||||
|
|
||||||
fn wasi_clock_id_to_unix(clock_id: wasi::__wasi_clockid_t) -> Result<ClockId> {
|
fn wasi_clock_id_to_unix(clock_id: wasi::__wasi_clockid_t) -> Result<ClockId> {
|
||||||
// convert the supported clocks to libc types, or return EINVAL
|
// convert the supported clocks to libc types, or return EINVAL
|
||||||
@@ -39,7 +39,7 @@ pub(crate) fn clock_res_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__
|
|||||||
|
|
||||||
pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__wasi_timestamp_t> {
|
pub(crate) fn clock_time_get(clock_id: wasi::__wasi_clockid_t) -> Result<wasi::__wasi_timestamp_t> {
|
||||||
let clock_id = wasi_clock_id_to_unix(clock_id)?;
|
let clock_id = wasi_clock_id_to_unix(clock_id)?;
|
||||||
let timespec = clock_getres(clock_id)?;
|
let timespec = clock_gettime(clock_id)?;
|
||||||
|
|
||||||
// convert to nanoseconds, returning EOVERFLOW in case of overflow; this is freelancing a bit
|
// convert to nanoseconds, returning EOVERFLOW in case of overflow; this is freelancing a bit
|
||||||
// from the spec but seems like it'll be an unusual situation to hit
|
// from the spec but seems like it'll be an unusual situation to hit
|
||||||
|
|||||||
@@ -27,3 +27,11 @@ pub fn clock_getres(clock_id: ClockId) -> Result<libc::timespec> {
|
|||||||
})?;
|
})?;
|
||||||
Ok(unsafe { timespec.assume_init() })
|
Ok(unsafe { timespec.assume_init() })
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn clock_gettime(clock_id: ClockId) -> Result<libc::timespec> {
|
||||||
|
let mut timespec = MaybeUninit::<libc::timespec>::uninit();
|
||||||
|
Errno::from_success_code(unsafe {
|
||||||
|
libc::clock_gettime(clock_id.as_raw(), timespec.as_mut_ptr())
|
||||||
|
})?;
|
||||||
|
Ok(unsafe { timespec.assume_init() })
|
||||||
|
}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ use std::{ffi::CStr, ops::Deref, ptr};
|
|||||||
pub use crate::sys::EntryExt;
|
pub use crate::sys::EntryExt;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
|
||||||
pub struct Dir(pub(crate) ptr::NonNull<libc::DIR>);
|
pub struct Dir(ptr::NonNull<libc::DIR>);
|
||||||
|
|
||||||
impl Dir {
|
impl Dir {
|
||||||
/// Takes the ownership of the passed-in descriptor-based object,
|
/// Takes the ownership of the passed-in descriptor-based object,
|
||||||
@@ -51,6 +51,12 @@ impl Dir {
|
|||||||
let loc = unsafe { libc::telldir(self.0.as_ptr()) };
|
let loc = unsafe { libc::telldir(self.0.as_ptr()) };
|
||||||
SeekLoc(loc)
|
SeekLoc(loc)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// For use by platform-specific implementation code. Returns the raw
|
||||||
|
/// underlying state.
|
||||||
|
pub(crate) fn as_raw(&self) -> ptr::NonNull<libc::DIR> {
|
||||||
|
self.0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl Send for Dir {}
|
unsafe impl Send for Dir {}
|
||||||
@@ -78,7 +84,7 @@ impl Entry {
|
|||||||
|
|
||||||
/// Returns the type of this directory entry.
|
/// Returns the type of this directory entry.
|
||||||
pub fn file_type(&self) -> FileType {
|
pub fn file_type(&self) -> FileType {
|
||||||
unsafe { FileType::from_raw(self.0.d_type) }
|
FileType::from_raw(self.0.d_type)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +113,7 @@ pub enum FileType {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl FileType {
|
impl FileType {
|
||||||
pub unsafe fn from_raw(file_type: u8) -> Self {
|
pub fn from_raw(file_type: u8) -> Self {
|
||||||
match file_type {
|
match file_type {
|
||||||
libc::DT_CHR => Self::CharacterDevice,
|
libc::DT_CHR => Self::CharacterDevice,
|
||||||
libc::DT_DIR => Self::Directory,
|
libc::DT_DIR => Self::Directory,
|
||||||
@@ -153,6 +159,6 @@ where
|
|||||||
type Item = Result<Entry>;
|
type Item = Result<Entry>;
|
||||||
|
|
||||||
fn next(&mut self) -> Option<Self::Item> {
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
unsafe { iter_impl(&self.0).map(|x| x.map(Entry)) }
|
iter_impl(&self.0).map(|x| x.map(Entry))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ impl PollFd {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn poll(fds: &mut [PollFd], timeout: i32) -> Result<usize> {
|
pub fn poll(fds: &mut [PollFd], timeout: libc::c_int) -> Result<usize> {
|
||||||
Errno::from_result(unsafe {
|
Errno::from_result(unsafe {
|
||||||
libc::poll(
|
libc::poll(
|
||||||
fds.as_mut_ptr() as *mut libc::pollfd,
|
fds.as_mut_ptr() as *mut libc::pollfd,
|
||||||
|
|||||||
@@ -18,9 +18,9 @@ impl Deref for EntryImpl {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn iter_impl(dir: &Dir) -> Option<Result<EntryImpl>> {
|
pub(crate) fn iter_impl(dir: &Dir) -> Option<Result<EntryImpl>> {
|
||||||
let errno = Errno::last();
|
let errno = Errno::last();
|
||||||
let dirent = libc::readdir(dir.0.as_ptr());
|
let dirent = unsafe { libc::readdir(dir.as_raw().as_ptr()) };
|
||||||
if dirent.is_null() {
|
if dirent.is_null() {
|
||||||
if errno != Errno::last() {
|
if errno != Errno::last() {
|
||||||
// TODO This should be verified on different BSD-flavours.
|
// TODO This should be verified on different BSD-flavours.
|
||||||
@@ -35,7 +35,7 @@ pub(crate) unsafe fn iter_impl(dir: &Dir) -> Option<Result<EntryImpl>> {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Some(Ok(EntryImpl {
|
Some(Ok(EntryImpl {
|
||||||
dirent: *dirent,
|
dirent: unsafe { *dirent },
|
||||||
loc: dir.tell(),
|
loc: dir.tell(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -25,9 +25,9 @@ impl EntryExt for Entry {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub(crate) unsafe fn iter_impl(dir: &Dir) -> Option<Result<EntryImpl>> {
|
pub(crate) fn iter_impl(dir: &Dir) -> Option<Result<EntryImpl>> {
|
||||||
let errno = Errno::last();
|
let errno = Errno::last();
|
||||||
let dirent = libc::readdir64(dir.0.as_ptr());
|
let dirent = unsafe { libc::readdir64(dir.as_raw().as_ptr()) };
|
||||||
if dirent.is_null() {
|
if dirent.is_null() {
|
||||||
if errno != Errno::last() {
|
if errno != Errno::last() {
|
||||||
// TODO This should be verified on different BSD-flavours.
|
// TODO This should be verified on different BSD-flavours.
|
||||||
@@ -41,6 +41,6 @@ pub(crate) unsafe fn iter_impl(dir: &Dir) -> Option<Result<EntryImpl>> {
|
|||||||
None
|
None
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
Some(Ok(EntryImpl(*dirent)))
|
Some(Ok(EntryImpl(unsafe { *dirent })))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,10 +5,10 @@ cfg_if! {
|
|||||||
if #[cfg(any(target_os = "linux",
|
if #[cfg(any(target_os = "linux",
|
||||||
target_os = "android"))] {
|
target_os = "android"))] {
|
||||||
mod linux;
|
mod linux;
|
||||||
pub(crate) use self::linux::*;
|
pub(crate) use linux::*;
|
||||||
} else if #[cfg(target_os = "emscripten")] {
|
} else if #[cfg(target_os = "emscripten")] {
|
||||||
mod emscripten;
|
mod emscripten;
|
||||||
pub(crate) use self::emscripten::*;
|
pub(crate) use emscripten::*;
|
||||||
} else if #[cfg(any(target_os = "macos",
|
} else if #[cfg(any(target_os = "macos",
|
||||||
target_os = "ios",
|
target_os = "ios",
|
||||||
target_os = "freebsd",
|
target_os = "freebsd",
|
||||||
@@ -16,7 +16,7 @@ cfg_if! {
|
|||||||
target_os = "openbsd",
|
target_os = "openbsd",
|
||||||
target_os = "dragonfly"))] {
|
target_os = "dragonfly"))] {
|
||||||
mod bsd;
|
mod bsd;
|
||||||
pub(crate) use self::bsd::*;
|
pub(crate) use bsd::*;
|
||||||
} else {
|
} else {
|
||||||
compile_error!("yanix doesn't compile for this platform yet");
|
compile_error!("yanix doesn't compile for this platform yet");
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user