sys: import types from handle or sched, not wasi. drop types:: prefix.

This commit is contained in:
Pat Hickey
2020-09-14 16:32:35 -07:00
parent e5129b39cb
commit 4763678be2
23 changed files with 328 additions and 362 deletions

View File

@@ -1,4 +1,4 @@
use crate::wasi::types::{Subclockflags, SubscriptionClock}; use crate::sched::{Subclockflags, SubscriptionClock};
use crate::{Error, Result}; use crate::{Error, Result};
use std::time::SystemTime; use std::time::SystemTime;

View File

@@ -1,4 +1,4 @@
use crate::wasi::types; use crate::handle::{Fstflags, Timestamp};
use crate::{Error, Result}; use crate::{Error, Result};
use filetime::{set_file_handle_times, FileTime}; use filetime::{set_file_handle_times, FileTime};
use std::fs::File; use std::fs::File;
@@ -8,14 +8,14 @@ pub(crate) use super::sys_impl::fd::*;
pub(crate) fn filestat_set_times( pub(crate) fn filestat_set_times(
file: &File, file: &File,
st_atim: types::Timestamp, st_atim: Timestamp,
st_mtim: types::Timestamp, st_mtim: Timestamp,
fst_flags: types::Fstflags, fst_flags: Fstflags,
) -> Result<()> { ) -> Result<()> {
let set_atim = fst_flags.contains(&types::Fstflags::ATIM); let set_atim = fst_flags.contains(&Fstflags::ATIM);
let set_atim_now = fst_flags.contains(&types::Fstflags::ATIM_NOW); let set_atim_now = fst_flags.contains(&Fstflags::ATIM_NOW);
let set_mtim = fst_flags.contains(&types::Fstflags::MTIM); let set_mtim = fst_flags.contains(&Fstflags::MTIM);
let set_mtim_now = fst_flags.contains(&types::Fstflags::MTIM_NOW); let set_mtim_now = fst_flags.contains(&Fstflags::MTIM_NOW);
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) { if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
return Err(Error::Inval); return Err(Error::Inval);

View File

@@ -24,8 +24,7 @@ cfg_if! {
pub(crate) use sys_impl::path; pub(crate) use sys_impl::path;
pub(crate) use sys_impl::poll; pub(crate) use sys_impl::poll;
use super::handle::Handle; use super::handle::{Filetype, Handle};
use crate::wasi::types;
use osdir::OsDir; use osdir::OsDir;
use osfile::OsFile; use osfile::OsFile;
use osother::OsOther; use osother::OsOther;
@@ -67,7 +66,7 @@ impl TryFrom<File> for Box<dyn Handle> {
fn try_from(file: File) -> io::Result<Self> { fn try_from(file: File) -> io::Result<Self> {
let file_type = get_file_type(&file)?; let file_type = get_file_type(&file)?;
match file_type { match file_type {
types::Filetype::RegularFile => { Filetype::RegularFile => {
let handle = OsFile::try_from(file)?; let handle = OsFile::try_from(file)?;
tracing::debug!( tracing::debug!(
handle = tracing::field::debug(&handle), handle = tracing::field::debug(&handle),
@@ -75,7 +74,7 @@ impl TryFrom<File> for Box<dyn Handle> {
); );
Ok(Box::new(handle)) Ok(Box::new(handle))
} }
types::Filetype::Directory => { Filetype::Directory => {
let handle = OsDir::try_from(file)?; let handle = OsDir::try_from(file)?;
tracing::debug!( tracing::debug!(
handle = tracing::field::debug(&handle), handle = tracing::field::debug(&handle),

View File

@@ -1,7 +1,9 @@
use super::sys_impl::oshandle::RawOsHandle; use super::sys_impl::oshandle::RawOsHandle;
use super::{fd, path, AsFile}; use super::{fd, path, AsFile};
use crate::handle::{Handle, HandleRights}; use crate::handle::{
use crate::wasi::types; Dircookie, Dirent, Fdflags, Filestat, Filetype, Fstflags, Handle, HandleRights, Oflags,
};
use crate::sched::Timestamp;
use crate::{Error, Result}; use crate::{Error, Result};
use std::any::Any; use std::any::Any;
use std::io; use std::io;
@@ -30,8 +32,8 @@ impl Handle for OsDir {
let new = Self::new(self.rights.get(), handle)?; let new = Self::new(self.rights.get(), handle)?;
Ok(Box::new(new)) Ok(Box::new(new))
} }
fn get_file_type(&self) -> types::Filetype { fn get_file_type(&self) -> Filetype {
types::Filetype::Directory Filetype::Directory
} }
fn get_rights(&self) -> HandleRights { fn get_rights(&self) -> HandleRights {
self.rights.get() self.rights.get()
@@ -40,45 +42,45 @@ impl Handle for OsDir {
self.rights.set(rights) self.rights.set(rights)
} }
// FdOps // FdOps
fn fdstat_get(&self) -> Result<types::Fdflags> { fn fdstat_get(&self) -> Result<Fdflags> {
fd::fdstat_get(&*self.as_file()?) fd::fdstat_get(&*self.as_file()?)
} }
fn fdstat_set_flags(&self, fdflags: types::Fdflags) -> Result<()> { fn fdstat_set_flags(&self, fdflags: Fdflags) -> Result<()> {
if let Some(new_file) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? { if let Some(new_file) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? {
self.handle.update_from(new_file); self.handle.update_from(new_file);
} }
Ok(()) Ok(())
} }
fn filestat_get(&self) -> Result<types::Filestat> { fn filestat_get(&self) -> Result<Filestat> {
fd::filestat_get(&*self.as_file()?) fd::filestat_get(&*self.as_file()?)
} }
fn filestat_set_times( fn filestat_set_times(
&self, &self,
atim: types::Timestamp, atim: Timestamp,
mtim: types::Timestamp, mtim: Timestamp,
fst_flags: types::Fstflags, fst_flags: Fstflags,
) -> Result<()> { ) -> Result<()> {
fd::filestat_set_times(&*self.as_file()?, atim, mtim, fst_flags) fd::filestat_set_times(&*self.as_file()?, atim, mtim, fst_flags)
} }
fn readdir<'a>( fn readdir<'a>(
&'a self, &'a self,
cookie: types::Dircookie, cookie: Dircookie,
) -> Result<Box<dyn Iterator<Item = Result<(types::Dirent, String)>> + 'a>> { ) -> Result<Box<dyn Iterator<Item = Result<(Dirent, String)>> + 'a>> {
fd::readdir(self, cookie) fd::readdir(self, cookie)
} }
// PathOps // PathOps
fn create_directory(&self, path: &str) -> Result<()> { fn create_directory(&self, path: &str) -> Result<()> {
path::create_directory(self, path) path::create_directory(self, path)
} }
fn filestat_get_at(&self, path: &str, follow: bool) -> Result<types::Filestat> { fn filestat_get_at(&self, path: &str, follow: bool) -> Result<Filestat> {
path::filestat_get_at(self, path, follow) path::filestat_get_at(self, path, follow)
} }
fn filestat_set_times_at( fn filestat_set_times_at(
&self, &self,
path: &str, path: &str,
atim: types::Timestamp, atim: Timestamp,
mtim: types::Timestamp, mtim: Timestamp,
fst_flags: types::Fstflags, fst_flags: Fstflags,
follow: bool, follow: bool,
) -> Result<()> { ) -> Result<()> {
path::filestat_set_times_at(self, path, atim, mtim, fst_flags, follow) path::filestat_set_times_at(self, path, atim, mtim, fst_flags, follow)
@@ -88,8 +90,8 @@ impl Handle for OsDir {
path: &str, path: &str,
read: bool, read: bool,
write: bool, write: bool,
oflags: types::Oflags, oflags: Oflags,
fd_flags: types::Fdflags, fd_flags: Fdflags,
) -> Result<Box<dyn Handle>> { ) -> Result<Box<dyn Handle>> {
path::open(self, path, read, write, oflags, fd_flags) path::open(self, path, read, write, oflags, fd_flags)
} }

View File

@@ -1,7 +1,9 @@
use super::sys_impl::oshandle::RawOsHandle; use super::sys_impl::oshandle::RawOsHandle;
use super::{fd, AsFile}; use super::{fd, AsFile};
use crate::handle::{Handle, HandleRights}; use crate::handle::{
use crate::wasi::types; Advice, Fdflags, Filesize, Filestat, Filetype, Fstflags, Handle, HandleRights,
};
use crate::sched::Timestamp;
use crate::{Error, Result}; use crate::{Error, Result};
use std::any::Any; use std::any::Any;
use std::cell::Cell; use std::cell::Cell;
@@ -56,8 +58,8 @@ impl Handle for OsFile {
let rights = self.rights.clone(); let rights = self.rights.clone();
Ok(Box::new(Self { rights, handle })) Ok(Box::new(Self { rights, handle }))
} }
fn get_file_type(&self) -> types::Filetype { fn get_file_type(&self) -> Filetype {
types::Filetype::RegularFile Filetype::RegularFile
} }
fn get_rights(&self) -> HandleRights { fn get_rights(&self) -> HandleRights {
self.rights.get() self.rights.get()
@@ -66,15 +68,10 @@ impl Handle for OsFile {
self.rights.set(rights) self.rights.set(rights)
} }
// FdOps // FdOps
fn advise( fn advise(&self, advice: Advice, offset: Filesize, len: Filesize) -> Result<()> {
&self,
advice: types::Advice,
offset: types::Filesize,
len: types::Filesize,
) -> Result<()> {
fd::advise(self, advice, offset, len) fd::advise(self, advice, offset, len)
} }
fn allocate(&self, offset: types::Filesize, len: types::Filesize) -> Result<()> { fn allocate(&self, offset: Filesize, len: Filesize) -> Result<()> {
let fd = self.as_file()?; let fd = self.as_file()?;
let metadata = fd.metadata()?; let metadata = fd.metadata()?;
let current_size = metadata.len(); let current_size = metadata.len();
@@ -92,27 +89,27 @@ impl Handle for OsFile {
self.as_file()?.sync_data()?; self.as_file()?.sync_data()?;
Ok(()) Ok(())
} }
fn fdstat_get(&self) -> Result<types::Fdflags> { fn fdstat_get(&self) -> Result<Fdflags> {
fd::fdstat_get(&*self.as_file()?) fd::fdstat_get(&*self.as_file()?)
} }
fn fdstat_set_flags(&self, fdflags: types::Fdflags) -> Result<()> { fn fdstat_set_flags(&self, fdflags: Fdflags) -> Result<()> {
if let Some(new_handle) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? { if let Some(new_handle) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? {
self.handle.update_from(new_handle); self.handle.update_from(new_handle);
} }
Ok(()) Ok(())
} }
fn filestat_get(&self) -> Result<types::Filestat> { fn filestat_get(&self) -> Result<Filestat> {
fd::filestat_get(&*self.as_file()?) fd::filestat_get(&*self.as_file()?)
} }
fn filestat_set_size(&self, size: types::Filesize) -> Result<()> { fn filestat_set_size(&self, size: Filesize) -> Result<()> {
self.as_file()?.set_len(size)?; self.as_file()?.set_len(size)?;
Ok(()) Ok(())
} }
fn filestat_set_times( fn filestat_set_times(
&self, &self,
atim: types::Timestamp, atim: Timestamp,
mtim: types::Timestamp, mtim: Timestamp,
fst_flags: types::Fstflags, fst_flags: Fstflags,
) -> Result<()> { ) -> Result<()> {
fd::filestat_set_times(&*self.as_file()?, atim, mtim, fst_flags) fd::filestat_set_times(&*self.as_file()?, atim, mtim, fst_flags)
} }

View File

@@ -1,8 +1,7 @@
use super::sys_impl::oshandle::RawOsHandle; use super::sys_impl::oshandle::RawOsHandle;
use super::{fd, AsFile}; use super::{fd, AsFile};
use crate::handle::{Handle, HandleRights}; use crate::handle::{Fdflags, Filetype, Handle, HandleRights};
use crate::sandboxed_tty_writer::SandboxedTTYWriter; use crate::sandboxed_tty_writer::SandboxedTTYWriter;
use crate::wasi::types::{self, Filetype};
use crate::Result; use crate::Result;
use std::any::Any; use std::any::Any;
use std::cell::Cell; use std::cell::Cell;
@@ -79,10 +78,10 @@ impl Handle for OsOther {
self.rights.set(new_rights) self.rights.set(new_rights)
} }
// FdOps // FdOps
fn fdstat_get(&self) -> Result<types::Fdflags> { fn fdstat_get(&self) -> Result<Fdflags> {
fd::fdstat_get(&*self.as_file()?) fd::fdstat_get(&*self.as_file()?)
} }
fn fdstat_set_flags(&self, fdflags: types::Fdflags) -> Result<()> { fn fdstat_set_flags(&self, fdflags: Fdflags) -> Result<()> {
if let Some(handle) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? { if let Some(handle) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? {
self.handle.update_from(handle); self.handle.update_from(handle);
} }

View File

@@ -17,10 +17,8 @@
// TODO it might worth re-investigating the suitability of this type on Windows. // TODO it might worth re-investigating the suitability of this type on Windows.
use super::{fd, AsFile}; use super::{fd, AsFile};
use crate::handle::{Handle, HandleRights}; use crate::handle::{Fdflags, Filetype, Handle, HandleRights, Rights, RightsExt, Size};
use crate::sandboxed_tty_writer::SandboxedTTYWriter; use crate::sandboxed_tty_writer::SandboxedTTYWriter;
use crate::wasi::types::{self, Filetype};
use crate::wasi::RightsExt;
use crate::{Error, Result}; use crate::{Error, Result};
use std::any::Any; use std::any::Any;
use std::cell::Cell; use std::cell::Cell;
@@ -55,10 +53,10 @@ impl Handle for Stdin {
self.rights.set(new_rights) self.rights.set(new_rights)
} }
// FdOps // FdOps
fn fdstat_get(&self) -> Result<types::Fdflags> { fn fdstat_get(&self) -> Result<Fdflags> {
fd::fdstat_get(&*self.as_file()?) fd::fdstat_get(&*self.as_file()?)
} }
fn fdstat_set_flags(&self, fdflags: types::Fdflags) -> Result<()> { fn fdstat_set_flags(&self, fdflags: Fdflags) -> Result<()> {
if let Some(_) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? { if let Some(_) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? {
// OK, this means we should somehow update the underlying os handle, // OK, this means we should somehow update the underlying os handle,
// and we can't do that with `std::io::std{in, out, err}`, so we'll // and we can't do that with `std::io::std{in, out, err}`, so we'll
@@ -101,10 +99,10 @@ impl Handle for Stdout {
self.rights.set(new_rights) self.rights.set(new_rights)
} }
// FdOps // FdOps
fn fdstat_get(&self) -> Result<types::Fdflags> { fn fdstat_get(&self) -> Result<Fdflags> {
fd::fdstat_get(&*self.as_file()?) fd::fdstat_get(&*self.as_file()?)
} }
fn fdstat_set_flags(&self, fdflags: types::Fdflags) -> Result<()> { fn fdstat_set_flags(&self, fdflags: Fdflags) -> Result<()> {
if let Some(_) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? { if let Some(_) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? {
// OK, this means we should somehow update the underlying os handle, // OK, this means we should somehow update the underlying os handle,
// and we can't do that with `std::io::std{in, out, err}`, so we'll // and we can't do that with `std::io::std{in, out, err}`, so we'll
@@ -155,10 +153,10 @@ impl Handle for Stderr {
self.rights.set(new_rights) self.rights.set(new_rights)
} }
// FdOps // FdOps
fn fdstat_get(&self) -> Result<types::Fdflags> { fn fdstat_get(&self) -> Result<Fdflags> {
fd::fdstat_get(&*self.as_file()?) fd::fdstat_get(&*self.as_file()?)
} }
fn fdstat_set_flags(&self, fdflags: types::Fdflags) -> Result<()> { fn fdstat_set_flags(&self, fdflags: Fdflags) -> Result<()> {
if let Some(_) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? { if let Some(_) = fd::fdstat_set_flags(&*self.as_file()?, fdflags)? {
// OK, this means we should somehow update the underlying os handle, // OK, this means we should somehow update the underlying os handle,
// and we can't do that with `std::io::std{in, out, err}`, so we'll // and we can't do that with `std::io::std{in, out, err}`, so we'll
@@ -180,17 +178,17 @@ impl Handle for Stderr {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub(crate) struct NullDevice { pub(crate) struct NullDevice {
pub(crate) rights: Cell<HandleRights>, pub(crate) rights: Cell<HandleRights>,
pub(crate) fd_flags: Cell<types::Fdflags>, pub(crate) fd_flags: Cell<Fdflags>,
} }
impl NullDevice { impl NullDevice {
pub(crate) fn new() -> Self { pub(crate) fn new() -> Self {
let rights = HandleRights::new( let rights = HandleRights::new(
types::Rights::character_device_base(), Rights::character_device_base(),
types::Rights::character_device_inheriting(), Rights::character_device_inheriting(),
); );
let rights = Cell::new(rights); let rights = Cell::new(rights);
let fd_flags = types::Fdflags::empty(); let fd_flags = Fdflags::empty();
let fd_flags = Cell::new(fd_flags); let fd_flags = Cell::new(fd_flags);
Self { rights, fd_flags } Self { rights, fd_flags }
} }
@@ -203,8 +201,8 @@ impl Handle for NullDevice {
fn try_clone(&self) -> io::Result<Box<dyn Handle>> { fn try_clone(&self) -> io::Result<Box<dyn Handle>> {
Ok(Box::new(self.clone())) Ok(Box::new(self.clone()))
} }
fn get_file_type(&self) -> types::Filetype { fn get_file_type(&self) -> Filetype {
types::Filetype::CharacterDevice Filetype::CharacterDevice
} }
fn get_rights(&self) -> HandleRights { fn get_rights(&self) -> HandleRights {
self.rights.get() self.rights.get()
@@ -213,10 +211,10 @@ impl Handle for NullDevice {
self.rights.set(rights) self.rights.set(rights)
} }
// FdOps // FdOps
fn fdstat_get(&self) -> Result<types::Fdflags> { fn fdstat_get(&self) -> Result<Fdflags> {
Ok(self.fd_flags.get()) Ok(self.fd_flags.get())
} }
fn fdstat_set_flags(&self, fdflags: types::Fdflags) -> Result<()> { fn fdstat_set_flags(&self, fdflags: Fdflags) -> Result<()> {
self.fd_flags.set(fdflags); self.fd_flags.set(fdflags);
Ok(()) Ok(())
} }
@@ -226,7 +224,7 @@ impl Handle for NullDevice {
fn write_vectored(&self, iovs: &[io::IoSlice]) -> Result<usize> { fn write_vectored(&self, iovs: &[io::IoSlice]) -> Result<usize> {
let mut total_len = 0u32; let mut total_len = 0u32;
for iov in iovs { for iov in iovs {
let len: types::Size = iov.len().try_into()?; let len: Size = iov.len().try_into()?;
total_len = total_len.checked_add(len).ok_or(Error::Overflow)?; total_len = total_len.checked_add(len).ok_or(Error::Overflow)?;
} }
Ok(total_len as usize) Ok(total_len as usize)

View File

@@ -1,17 +1,17 @@
use crate::wasi::types; use crate::sched::{Clockid, Timestamp};
use crate::{Error, Result}; use crate::{Error, Result};
use yanix::clock::{clock_getres, clock_gettime, ClockId}; use yanix::clock::{clock_getres, clock_gettime, ClockId};
pub(crate) fn res_get(clock_id: types::Clockid) -> Result<types::Timestamp> { pub(crate) fn res_get(clock_id: Clockid) -> Result<Timestamp> {
let clock_id: ClockId = clock_id.into(); let clock_id: ClockId = clock_id.into();
let timespec = clock_getres(clock_id)?; let timespec = clock_getres(clock_id)?;
// convert to nanoseconds, returning EOVERFLOW in case of overflow; // convert to nanoseconds, returning EOVERFLOW in case of overflow;
// this is freelancing a bit from the spec but seems like it'll // this is freelancing a bit from the spec but seems like it'll
// be an unusual situation to hit // be an unusual situation to hit
(timespec.tv_sec as types::Timestamp) (timespec.tv_sec as Timestamp)
.checked_mul(1_000_000_000) .checked_mul(1_000_000_000)
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as types::Timestamp)) .and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as Timestamp))
.map_or(Err(Error::Overflow), |resolution| { .map_or(Err(Error::Overflow), |resolution| {
// a supported clock can never return zero; this case will probably never get hit, but // a supported clock can never return zero; this case will probably never get hit, but
// make sure we follow the spec // make sure we follow the spec
@@ -23,14 +23,14 @@ pub(crate) fn res_get(clock_id: types::Clockid) -> Result<types::Timestamp> {
}) })
} }
pub(crate) fn time_get(clock_id: types::Clockid) -> Result<types::Timestamp> { pub(crate) fn time_get(clock_id: Clockid) -> Result<Timestamp> {
let clock_id: ClockId = clock_id.into(); let clock_id: ClockId = clock_id.into();
let timespec = clock_gettime(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
(timespec.tv_sec as types::Timestamp) (timespec.tv_sec as Timestamp)
.checked_mul(1_000_000_000) .checked_mul(1_000_000_000)
.and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as types::Timestamp)) .and_then(|sec_ns| sec_ns.checked_add(timespec.tv_nsec as Timestamp))
.map_or(Err(Error::Overflow), Ok) .map_or(Err(Error::Overflow), Ok)
} }

View File

@@ -1,18 +1,18 @@
use super::oshandle::RawOsHandle; use super::oshandle::RawOsHandle;
use crate::handle::{Advice, Dircookie, Dirent, Fdflags, Filesize, Filestat, DIRCOOKIE_START};
use crate::sys::osdir::OsDir; use crate::sys::osdir::OsDir;
use crate::sys::osfile::OsFile; use crate::sys::osfile::OsFile;
use crate::wasi::{self, types};
use crate::Result; use crate::Result;
use std::convert::TryInto; use std::convert::TryInto;
use std::fs::File; use std::fs::File;
use std::os::unix::prelude::AsRawFd; use std::os::unix::prelude::AsRawFd;
pub(crate) fn fdstat_get(fd: &File) -> Result<types::Fdflags> { pub(crate) fn fdstat_get(fd: &File) -> Result<Fdflags> {
let fdflags = unsafe { yanix::fcntl::get_status_flags(fd.as_raw_fd())? }; let fdflags = unsafe { yanix::fcntl::get_status_flags(fd.as_raw_fd())? };
Ok(fdflags.into()) Ok(fdflags.into())
} }
pub(crate) fn fdstat_set_flags(fd: &File, fdflags: types::Fdflags) -> Result<Option<RawOsHandle>> { pub(crate) fn fdstat_set_flags(fd: &File, fdflags: Fdflags) -> Result<Option<RawOsHandle>> {
unsafe { yanix::fcntl::set_status_flags(fd.as_raw_fd(), fdflags.into())? }; unsafe { yanix::fcntl::set_status_flags(fd.as_raw_fd(), fdflags.into())? };
// We return None here to signal that the operation succeeded on the original // We return None here to signal that the operation succeeded on the original
// file descriptor and mutating the original WASI Descriptor is thus unnecessary. // file descriptor and mutating the original WASI Descriptor is thus unnecessary.
@@ -20,28 +20,23 @@ pub(crate) fn fdstat_set_flags(fd: &File, fdflags: types::Fdflags) -> Result<Opt
Ok(None) Ok(None)
} }
pub(crate) fn advise( pub(crate) fn advise(file: &OsFile, advice: Advice, offset: Filesize, len: Filesize) -> Result<()> {
file: &OsFile,
advice: types::Advice,
offset: types::Filesize,
len: types::Filesize,
) -> Result<()> {
use yanix::fadvise::{posix_fadvise, PosixFadviseAdvice}; use yanix::fadvise::{posix_fadvise, PosixFadviseAdvice};
let offset = offset.try_into()?; let offset = offset.try_into()?;
let len = len.try_into()?; let len = len.try_into()?;
let host_advice = match advice { let host_advice = match advice {
types::Advice::Dontneed => PosixFadviseAdvice::DontNeed, Advice::Dontneed => PosixFadviseAdvice::DontNeed,
types::Advice::Sequential => PosixFadviseAdvice::Sequential, Advice::Sequential => PosixFadviseAdvice::Sequential,
types::Advice::Willneed => PosixFadviseAdvice::WillNeed, Advice::Willneed => PosixFadviseAdvice::WillNeed,
types::Advice::Noreuse => PosixFadviseAdvice::NoReuse, Advice::Noreuse => PosixFadviseAdvice::NoReuse,
types::Advice::Random => PosixFadviseAdvice::Random, Advice::Random => PosixFadviseAdvice::Random,
types::Advice::Normal => PosixFadviseAdvice::Normal, Advice::Normal => PosixFadviseAdvice::Normal,
}; };
unsafe { posix_fadvise(file.as_raw_fd(), offset, len, host_advice)? }; unsafe { posix_fadvise(file.as_raw_fd(), offset, len, host_advice)? };
Ok(()) Ok(())
} }
pub(crate) fn filestat_get(file: &File) -> Result<types::Filestat> { pub(crate) fn filestat_get(file: &File) -> Result<Filestat> {
use yanix::file::fstat; use yanix::file::fstat;
let stat = unsafe { fstat(file.as_raw_fd())? }; let stat = unsafe { fstat(file.as_raw_fd())? };
Ok(stat.try_into()?) Ok(stat.try_into()?)
@@ -49,8 +44,8 @@ pub(crate) fn filestat_get(file: &File) -> Result<types::Filestat> {
pub(crate) fn readdir<'a>( pub(crate) fn readdir<'a>(
dirfd: &'a OsDir, dirfd: &'a OsDir,
cookie: types::Dircookie, cookie: Dircookie,
) -> Result<Box<dyn Iterator<Item = Result<(types::Dirent, String)>> + 'a>> { ) -> Result<Box<dyn Iterator<Item = Result<(Dirent, String)>> + 'a>> {
use yanix::dir::{DirIter, Entry, EntryExt, SeekLoc}; use yanix::dir::{DirIter, Entry, EntryExt, SeekLoc};
// Get an instance of `Dir`; this is host-specific due to intricasies // Get an instance of `Dir`; this is host-specific due to intricasies
@@ -59,7 +54,7 @@ pub(crate) fn readdir<'a>(
// Seek if needed. Unless cookie is wasi::__WASI_DIRCOOKIE_START, // Seek if needed. Unless cookie is wasi::__WASI_DIRCOOKIE_START,
// new items may not be returned to the caller. // new items may not be returned to the caller.
if cookie == wasi::DIRCOOKIE_START { if cookie == DIRCOOKIE_START {
tracing::trace!("fd_readdir: doing rewinddir"); tracing::trace!("fd_readdir: doing rewinddir");
dir.rewind(); dir.rewind();
} else { } else {
@@ -71,7 +66,7 @@ pub(crate) fn readdir<'a>(
Ok(Box::new(DirIter::new(dir).map(|entry| { Ok(Box::new(DirIter::new(dir).map(|entry| {
let entry: Entry = entry?; let entry: Entry = entry?;
let name = entry.file_name().to_str()?.to_owned(); let name = entry.file_name().to_str()?.to_owned();
let dirent = types::Dirent { let dirent = Dirent {
d_next: entry.seek_loc()?.to_raw().try_into()?, d_next: entry.seek_loc()?.to_raw().try_into()?,
d_ino: entry.ino(), d_ino: entry.ino(),
d_namlen: name.len().try_into()?, d_namlen: name.len().try_into()?,

View File

@@ -26,9 +26,11 @@ cfg_if::cfg_if! {
} }
} }
use crate::handle::HandleRights; use crate::handle::{
Fdflags, Filesize, Filestat, Filetype, HandleRights, Lookupflags, Oflags, Rights, RightsExt,
};
use crate::sched::{Clockid, Timestamp};
use crate::sys::AsFile; use crate::sys::AsFile;
use crate::wasi::{types, RightsExt};
use crate::{Error, Result}; use crate::{Error, Result};
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use std::fs::File; use std::fs::File;
@@ -48,34 +50,34 @@ impl<T: AsRawFd> AsFile for T {
} }
} }
pub(super) fn get_file_type(file: &File) -> io::Result<types::Filetype> { pub(super) fn get_file_type(file: &File) -> io::Result<Filetype> {
let ft = file.metadata()?.file_type(); let ft = file.metadata()?.file_type();
let file_type = if ft.is_block_device() { let file_type = if ft.is_block_device() {
tracing::debug!( tracing::debug!(
host_fd = tracing::field::display(file.as_raw_fd()), host_fd = tracing::field::display(file.as_raw_fd()),
"Host fd is a block device" "Host fd is a block device"
); );
types::Filetype::BlockDevice Filetype::BlockDevice
} else if ft.is_char_device() { } else if ft.is_char_device() {
tracing::debug!("Host fd {:?} is a char device", file.as_raw_fd()); tracing::debug!("Host fd {:?} is a char device", file.as_raw_fd());
types::Filetype::CharacterDevice Filetype::CharacterDevice
} else if ft.is_dir() { } else if ft.is_dir() {
tracing::debug!("Host fd {:?} is a directory", file.as_raw_fd()); tracing::debug!("Host fd {:?} is a directory", file.as_raw_fd());
types::Filetype::Directory Filetype::Directory
} else if ft.is_file() { } else if ft.is_file() {
tracing::debug!("Host fd {:?} is a file", file.as_raw_fd()); tracing::debug!("Host fd {:?} is a file", file.as_raw_fd());
types::Filetype::RegularFile Filetype::RegularFile
} else if ft.is_socket() { } else if ft.is_socket() {
tracing::debug!("Host fd {:?} is a socket", file.as_raw_fd()); tracing::debug!("Host fd {:?} is a socket", file.as_raw_fd());
use yanix::socket::{get_socket_type, SockType}; use yanix::socket::{get_socket_type, SockType};
match unsafe { get_socket_type(file.as_raw_fd())? } { match unsafe { get_socket_type(file.as_raw_fd())? } {
SockType::Datagram => types::Filetype::SocketDgram, SockType::Datagram => Filetype::SocketDgram,
SockType::Stream => types::Filetype::SocketStream, SockType::Stream => Filetype::SocketStream,
_ => return Err(io::Error::from_raw_os_error(libc::EINVAL)), _ => return Err(io::Error::from_raw_os_error(libc::EINVAL)),
} }
} else if ft.is_fifo() { } else if ft.is_fifo() {
tracing::debug!("Host fd {:?} is a fifo", file.as_raw_fd()); tracing::debug!("Host fd {:?} is a fifo", file.as_raw_fd());
types::Filetype::Unknown Filetype::Unknown
} else { } else {
tracing::debug!("Host fd {:?} is unknown", file.as_raw_fd()); tracing::debug!("Host fd {:?} is unknown", file.as_raw_fd());
return Err(io::Error::from_raw_os_error(libc::EINVAL)); return Err(io::Error::from_raw_os_error(libc::EINVAL));
@@ -83,48 +85,44 @@ pub(super) fn get_file_type(file: &File) -> io::Result<types::Filetype> {
Ok(file_type) Ok(file_type)
} }
pub(super) fn get_rights(file: &File, file_type: &types::Filetype) -> io::Result<HandleRights> { pub(super) fn get_rights(file: &File, file_type: &Filetype) -> io::Result<HandleRights> {
use yanix::{fcntl, file::OFlags}; use yanix::{fcntl, file::OFlags};
let (base, inheriting) = match file_type { let (base, inheriting) = match file_type {
types::Filetype::BlockDevice => ( Filetype::BlockDevice => (
types::Rights::block_device_base(), Rights::block_device_base(),
types::Rights::block_device_inheriting(), Rights::block_device_inheriting(),
), ),
types::Filetype::CharacterDevice => { Filetype::CharacterDevice => {
use yanix::file::isatty; use yanix::file::isatty;
if unsafe { isatty(file.as_raw_fd())? } { if unsafe { isatty(file.as_raw_fd())? } {
(types::Rights::tty_base(), types::Rights::tty_base()) (Rights::tty_base(), Rights::tty_base())
} else { } else {
( (
types::Rights::character_device_base(), Rights::character_device_base(),
types::Rights::character_device_inheriting(), Rights::character_device_inheriting(),
) )
} }
} }
types::Filetype::SocketDgram | types::Filetype::SocketStream => ( Filetype::SocketDgram | Filetype::SocketStream => {
types::Rights::socket_base(), (Rights::socket_base(), Rights::socket_inheriting())
types::Rights::socket_inheriting(), }
Filetype::SymbolicLink | Filetype::Unknown => (
Rights::regular_file_base(),
Rights::regular_file_inheriting(),
), ),
types::Filetype::SymbolicLink | types::Filetype::Unknown => ( Filetype::Directory => (Rights::directory_base(), Rights::directory_inheriting()),
types::Rights::regular_file_base(), Filetype::RegularFile => (
types::Rights::regular_file_inheriting(), Rights::regular_file_base(),
), Rights::regular_file_inheriting(),
types::Filetype::Directory => (
types::Rights::directory_base(),
types::Rights::directory_inheriting(),
),
types::Filetype::RegularFile => (
types::Rights::regular_file_base(),
types::Rights::regular_file_inheriting(),
), ),
}; };
let mut rights = HandleRights::new(base, inheriting); let mut rights = HandleRights::new(base, inheriting);
let flags = unsafe { fcntl::get_status_flags(file.as_raw_fd())? }; let flags = unsafe { fcntl::get_status_flags(file.as_raw_fd())? };
let accmode = flags & OFlags::ACCMODE; let accmode = flags & OFlags::ACCMODE;
if accmode == OFlags::RDONLY { if accmode == OFlags::RDONLY {
rights.base &= !types::Rights::FD_WRITE; rights.base &= !Rights::FD_WRITE;
} else if accmode == OFlags::WRONLY { } else if accmode == OFlags::WRONLY {
rights.base &= !types::Rights::FD_READ; rights.base &= !Rights::FD_READ;
} }
Ok(rights) Ok(rights)
} }
@@ -133,9 +131,9 @@ pub fn preopen_dir<P: AsRef<Path>>(path: P) -> io::Result<File> {
File::open(path) File::open(path)
} }
impl From<types::Clockid> for ClockId { impl From<Clockid> for ClockId {
fn from(clock_id: types::Clockid) -> Self { fn from(clock_id: Clockid) -> Self {
use types::Clockid::*; use Clockid::*;
match clock_id { match clock_id {
Realtime => Self::Realtime, Realtime => Self::Realtime,
Monotonic => Self::Monotonic, Monotonic => Self::Monotonic,
@@ -145,29 +143,29 @@ impl From<types::Clockid> for ClockId {
} }
} }
impl From<types::Fdflags> for OFlags { impl From<Fdflags> for OFlags {
fn from(fdflags: types::Fdflags) -> Self { fn from(fdflags: Fdflags) -> Self {
let mut nix_flags = Self::empty(); let mut nix_flags = Self::empty();
if fdflags.contains(&types::Fdflags::APPEND) { if fdflags.contains(&Fdflags::APPEND) {
nix_flags.insert(Self::APPEND); nix_flags.insert(Self::APPEND);
} }
if fdflags.contains(&types::Fdflags::DSYNC) { if fdflags.contains(&Fdflags::DSYNC) {
nix_flags.insert(Self::DSYNC); nix_flags.insert(Self::DSYNC);
} }
if fdflags.contains(&types::Fdflags::NONBLOCK) { if fdflags.contains(&Fdflags::NONBLOCK) {
nix_flags.insert(Self::NONBLOCK); nix_flags.insert(Self::NONBLOCK);
} }
if fdflags.contains(&types::Fdflags::RSYNC) { if fdflags.contains(&Fdflags::RSYNC) {
nix_flags.insert(O_RSYNC); nix_flags.insert(O_RSYNC);
} }
if fdflags.contains(&types::Fdflags::SYNC) { if fdflags.contains(&Fdflags::SYNC) {
nix_flags.insert(Self::SYNC); nix_flags.insert(Self::SYNC);
} }
nix_flags nix_flags
} }
} }
impl From<OFlags> for types::Fdflags { impl From<OFlags> for Fdflags {
fn from(oflags: OFlags) -> Self { fn from(oflags: OFlags) -> Self {
let mut fdflags = Self::empty(); let mut fdflags = Self::empty();
if oflags.contains(OFlags::APPEND) { if oflags.contains(OFlags::APPEND) {
@@ -189,30 +187,30 @@ impl From<OFlags> for types::Fdflags {
} }
} }
impl From<types::Oflags> for OFlags { impl From<Oflags> for OFlags {
fn from(oflags: types::Oflags) -> Self { fn from(oflags: Oflags) -> Self {
let mut nix_flags = Self::empty(); let mut nix_flags = Self::empty();
if oflags.contains(&types::Oflags::CREAT) { if oflags.contains(&Oflags::CREAT) {
nix_flags.insert(Self::CREAT); nix_flags.insert(Self::CREAT);
} }
if oflags.contains(&types::Oflags::DIRECTORY) { if oflags.contains(&Oflags::DIRECTORY) {
nix_flags.insert(Self::DIRECTORY); nix_flags.insert(Self::DIRECTORY);
} }
if oflags.contains(&types::Oflags::EXCL) { if oflags.contains(&Oflags::EXCL) {
nix_flags.insert(Self::EXCL); nix_flags.insert(Self::EXCL);
} }
if oflags.contains(&types::Oflags::TRUNC) { if oflags.contains(&Oflags::TRUNC) {
nix_flags.insert(Self::TRUNC); nix_flags.insert(Self::TRUNC);
} }
nix_flags nix_flags
} }
} }
impl TryFrom<libc::stat> for types::Filestat { impl TryFrom<libc::stat> for Filestat {
type Error = Error; type Error = Error;
fn try_from(filestat: libc::stat) -> Result<Self> { fn try_from(filestat: libc::stat) -> Result<Self> {
fn filestat_to_timestamp(secs: u64, nsecs: u64) -> Result<types::Timestamp> { fn filestat_to_timestamp(secs: u64, nsecs: u64) -> Result<Timestamp> {
secs.checked_mul(1_000_000_000) secs.checked_mul(1_000_000_000)
.and_then(|sec_nsec| sec_nsec.checked_add(nsecs)) .and_then(|sec_nsec| sec_nsec.checked_add(nsecs))
.ok_or(Error::Overflow) .ok_or(Error::Overflow)
@@ -238,7 +236,7 @@ impl TryFrom<libc::stat> for types::Filestat {
dev, dev,
ino, ino,
nlink: filestat.st_nlink.into(), nlink: filestat.st_nlink.into(),
size: filestat.st_size as types::Filesize, size: filestat.st_size as Filesize,
atim, atim,
ctim, ctim,
mtim, mtim,
@@ -247,7 +245,7 @@ impl TryFrom<libc::stat> for types::Filestat {
} }
} }
impl From<yanix::file::FileType> for types::Filetype { impl From<yanix::file::FileType> for Filetype {
fn from(ft: yanix::file::FileType) -> Self { fn from(ft: yanix::file::FileType) -> Self {
use yanix::file::FileType::*; use yanix::file::FileType::*;
match ft { match ft {
@@ -267,10 +265,10 @@ impl From<yanix::file::FileType> for types::Filetype {
} }
} }
impl From<types::Lookupflags> for AtFlags { impl From<Lookupflags> for AtFlags {
fn from(flags: types::Lookupflags) -> Self { fn from(flags: Lookupflags) -> Self {
match flags { match flags {
types::Lookupflags::SYMLINK_FOLLOW => Self::empty(), Lookupflags::SYMLINK_FOLLOW => Self::empty(),
_ => Self::SYMLINK_NOFOLLOW, _ => Self::SYMLINK_NOFOLLOW,
} }
} }

View File

@@ -1,6 +1,5 @@
use super::oshandle::RawOsHandle; use super::oshandle::RawOsHandle;
use crate::handle::HandleRights; use crate::handle::{HandleRights, Rights, RightsExt};
use crate::wasi::{types, RightsExt};
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fs::File; use std::fs::File;
use std::io; use std::io;
@@ -24,16 +23,13 @@ impl TryFrom<File> for OsDir {
fn get_rights(file: &File) -> io::Result<HandleRights> { fn get_rights(file: &File) -> io::Result<HandleRights> {
use yanix::{fcntl, file::OFlags}; use yanix::{fcntl, file::OFlags};
let mut rights = HandleRights::new( let mut rights = HandleRights::new(Rights::directory_base(), Rights::directory_inheriting());
types::Rights::directory_base(),
types::Rights::directory_inheriting(),
);
let flags = unsafe { fcntl::get_status_flags(file.as_raw_fd())? }; let flags = unsafe { fcntl::get_status_flags(file.as_raw_fd())? };
let accmode = flags & OFlags::ACCMODE; let accmode = flags & OFlags::ACCMODE;
if accmode == OFlags::RDONLY { if accmode == OFlags::RDONLY {
rights.base &= !types::Rights::FD_WRITE; rights.base &= !Rights::FD_WRITE;
} else if accmode == OFlags::WRONLY { } else if accmode == OFlags::WRONLY {
rights.base &= !types::Rights::FD_READ; rights.base &= !Rights::FD_READ;
} }
Ok(rights) Ok(rights)
} }

View File

@@ -1,7 +1,6 @@
use super::oshandle::RawOsHandle; use super::oshandle::RawOsHandle;
use crate::handle::HandleRights; use crate::handle::{HandleRights, Rights, RightsExt};
use crate::sys::osfile::OsFile; use crate::sys::osfile::OsFile;
use crate::wasi::{types, RightsExt};
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fs::File; use std::fs::File;
use std::io; use std::io;
@@ -24,15 +23,15 @@ impl TryFrom<File> for OsFile {
fn get_rights(file: &File) -> io::Result<HandleRights> { fn get_rights(file: &File) -> io::Result<HandleRights> {
use yanix::{fcntl, file::OFlags}; use yanix::{fcntl, file::OFlags};
let mut rights = HandleRights::new( let mut rights = HandleRights::new(
types::Rights::regular_file_base(), Rights::regular_file_base(),
types::Rights::regular_file_inheriting(), Rights::regular_file_inheriting(),
); );
let flags = unsafe { fcntl::get_status_flags(file.as_raw_fd())? }; let flags = unsafe { fcntl::get_status_flags(file.as_raw_fd())? };
let accmode = flags & OFlags::ACCMODE; let accmode = flags & OFlags::ACCMODE;
if accmode == OFlags::RDONLY { if accmode == OFlags::RDONLY {
rights.base &= !types::Rights::FD_WRITE; rights.base &= !Rights::FD_WRITE;
} else if accmode == OFlags::WRONLY { } else if accmode == OFlags::WRONLY {
rights.base &= !types::Rights::FD_READ; rights.base &= !Rights::FD_READ;
} }
Ok(rights) Ok(rights)
} }

View File

@@ -1,7 +1,7 @@
use super::oshandle::RawOsHandle; use super::oshandle::RawOsHandle;
use super::{get_file_type, get_rights}; use super::{get_file_type, get_rights};
use crate::handle::Filetype;
use crate::sys::osother::OsOther; use crate::sys::osother::OsOther;
use crate::wasi::types;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fs::File; use std::fs::File;
use std::io; use std::io;
@@ -12,7 +12,7 @@ impl TryFrom<File> for OsOther {
fn try_from(file: File) -> io::Result<Self> { fn try_from(file: File) -> io::Result<Self> {
let file_type = get_file_type(&file)?; let file_type = get_file_type(&file)?;
if file_type == types::Filetype::RegularFile || file_type == types::Filetype::Directory { if file_type == Filetype::RegularFile || file_type == Filetype::Directory {
return Err(io::Error::from_raw_os_error(libc::EINVAL)); return Err(io::Error::from_raw_os_error(libc::EINVAL));
} }
let rights = get_rights(&file, &file_type)?; let rights = get_rights(&file, &file_type)?;

View File

@@ -1,7 +1,7 @@
use crate::handle::{Handle, HandleRights}; use crate::handle::{Fdflags, Filestat, Fstflags, Handle, HandleRights, Oflags, Rights};
use crate::sched::Timestamp;
use crate::sys::osdir::OsDir; use crate::sys::osdir::OsDir;
use crate::sys::AsFile; use crate::sys::AsFile;
use crate::wasi::types;
use crate::{Error, Result}; use crate::{Error, Result};
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use std::ffi::OsStr; use std::ffi::OsStr;
@@ -23,29 +23,29 @@ pub(crate) fn from_host<S: AsRef<OsStr>>(s: S) -> Result<String> {
pub(crate) fn open_rights( pub(crate) fn open_rights(
input_rights: &HandleRights, input_rights: &HandleRights,
oflags: types::Oflags, oflags: Oflags,
fs_flags: types::Fdflags, fs_flags: Fdflags,
) -> HandleRights { ) -> HandleRights {
// which rights are needed on the dirfd? // which rights are needed on the dirfd?
let mut needed_base = types::Rights::PATH_OPEN; let mut needed_base = Rights::PATH_OPEN;
let mut needed_inheriting = input_rights.base | input_rights.inheriting; let mut needed_inheriting = input_rights.base | input_rights.inheriting;
// convert open flags // convert open flags
let oflags: OFlags = oflags.into(); let oflags: OFlags = oflags.into();
if oflags.contains(OFlags::CREAT) { if oflags.contains(OFlags::CREAT) {
needed_base |= types::Rights::PATH_CREATE_FILE; needed_base |= Rights::PATH_CREATE_FILE;
} }
if oflags.contains(OFlags::TRUNC) { if oflags.contains(OFlags::TRUNC) {
needed_base |= types::Rights::PATH_FILESTAT_SET_SIZE; needed_base |= Rights::PATH_FILESTAT_SET_SIZE;
} }
// convert file descriptor flags // convert file descriptor flags
let fdflags: OFlags = fs_flags.into(); let fdflags: OFlags = fs_flags.into();
if fdflags.contains(OFlags::DSYNC) { if fdflags.contains(OFlags::DSYNC) {
needed_inheriting |= types::Rights::FD_DATASYNC; needed_inheriting |= Rights::FD_DATASYNC;
} }
if fdflags.intersects(super::O_RSYNC | OFlags::SYNC) { if fdflags.intersects(super::O_RSYNC | OFlags::SYNC) {
needed_inheriting |= types::Rights::FD_SYNC; needed_inheriting |= Rights::FD_SYNC;
} }
HandleRights::new(needed_base, needed_inheriting) HandleRights::new(needed_base, needed_inheriting)
@@ -98,8 +98,8 @@ pub(crate) fn open(
path: &str, path: &str,
read: bool, read: bool,
write: bool, write: bool,
oflags: types::Oflags, oflags: Oflags,
fs_flags: types::Fdflags, fs_flags: Fdflags,
) -> Result<Box<dyn Handle>> { ) -> Result<Box<dyn Handle>> {
use yanix::file::{fstatat, openat, AtFlags, FileType, Mode, OFlags}; use yanix::file::{fstatat, openat, AtFlags, FileType, Mode, OFlags};
@@ -216,7 +216,7 @@ pub(crate) fn remove_directory(dirfd: &OsDir, path: &str) -> Result<()> {
Ok(()) Ok(())
} }
pub(crate) fn filestat_get_at(dirfd: &OsDir, path: &str, follow: bool) -> Result<types::Filestat> { pub(crate) fn filestat_get_at(dirfd: &OsDir, path: &str, follow: bool) -> Result<Filestat> {
use yanix::file::{fstatat, AtFlags}; use yanix::file::{fstatat, AtFlags};
let flags = if follow { let flags = if follow {
AtFlags::empty() AtFlags::empty()
@@ -231,18 +231,18 @@ pub(crate) fn filestat_get_at(dirfd: &OsDir, path: &str, follow: bool) -> Result
pub(crate) fn filestat_set_times_at( pub(crate) fn filestat_set_times_at(
dirfd: &OsDir, dirfd: &OsDir,
path: &str, path: &str,
atim: types::Timestamp, atim: Timestamp,
mtim: types::Timestamp, mtim: Timestamp,
fst_flags: types::Fstflags, fst_flags: Fstflags,
follow: bool, follow: bool,
) -> Result<()> { ) -> Result<()> {
use std::time::{Duration, UNIX_EPOCH}; use std::time::{Duration, UNIX_EPOCH};
use yanix::filetime::*; use yanix::filetime::*;
let set_atim = fst_flags.contains(&types::Fstflags::ATIM); let set_atim = fst_flags.contains(&Fstflags::ATIM);
let set_atim_now = fst_flags.contains(&types::Fstflags::ATIM_NOW); let set_atim_now = fst_flags.contains(&Fstflags::ATIM_NOW);
let set_mtim = fst_flags.contains(&types::Fstflags::MTIM); let set_mtim = fst_flags.contains(&Fstflags::MTIM);
let set_mtim_now = fst_flags.contains(&types::Fstflags::MTIM_NOW); let set_mtim_now = fst_flags.contains(&Fstflags::MTIM_NOW);
if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) { if (set_atim && set_atim_now) || (set_mtim && set_mtim_now) {
return Err(Error::Inval); return Err(Error::Inval);

View File

@@ -1,7 +1,9 @@
use crate::entry::EntryHandle; use crate::entry::EntryHandle;
use crate::poll::{ClockEventData, FdEventData}; use crate::handle::Filetype;
use crate::sched::{
ClockEventData, Errno, Event, EventFdReadwrite, Eventrwflags, Eventtype, FdEventData,
};
use crate::sys::AsFile; use crate::sys::AsFile;
use crate::wasi::types;
use crate::{Error, Result}; use crate::{Error, Result};
use std::io; use std::io;
use std::{convert::TryInto, os::unix::prelude::AsRawFd}; use std::{convert::TryInto, os::unix::prelude::AsRawFd};
@@ -11,7 +13,7 @@ use yanix::poll::{poll, PollFd, PollFlags};
pub(crate) fn oneoff( pub(crate) fn oneoff(
timeout: Option<ClockEventData>, timeout: Option<ClockEventData>,
fd_events: Vec<FdEventData>, fd_events: Vec<FdEventData>,
events: &mut Vec<types::Event>, events: &mut Vec<Event>,
) -> Result<()> { ) -> Result<()> {
if fd_events.is_empty() && timeout.is_none() { if fd_events.is_empty() && timeout.is_none() {
return Ok(()); return Ok(());
@@ -22,8 +24,8 @@ pub(crate) fn oneoff(
.map(|event| { .map(|event| {
let mut flags = PollFlags::empty(); let mut flags = PollFlags::empty();
match event.r#type { match event.r#type {
types::Eventtype::FdRead => flags.insert(PollFlags::POLLIN), Eventtype::FdRead => flags.insert(PollFlags::POLLIN),
types::Eventtype::FdWrite => flags.insert(PollFlags::POLLOUT), Eventtype::FdWrite => flags.insert(PollFlags::POLLOUT),
// An event on a file descriptor can currently only be of type FD_READ or FD_WRITE // An event on a file descriptor can currently only be of type FD_READ or FD_WRITE
// Nothing else has been defined in the specification, and these are also the only two // Nothing else has been defined in the specification, and these are also the only two
// events we filtered before. If we get something else here, the code has a serious bug. // events we filtered before. If we get something else here, the code has a serious bug.
@@ -65,13 +67,13 @@ pub(crate) fn oneoff(
}) })
} }
fn handle_timeout_event(timeout: ClockEventData, events: &mut Vec<types::Event>) { fn handle_timeout_event(timeout: ClockEventData, events: &mut Vec<Event>) {
events.push(types::Event { events.push(Event {
userdata: timeout.userdata, userdata: timeout.userdata,
error: types::Errno::Success, error: Errno::Success,
type_: types::Eventtype::Clock, type_: Eventtype::Clock,
fd_readwrite: types::EventFdReadwrite { fd_readwrite: EventFdReadwrite {
flags: types::Eventrwflags::empty(), flags: Eventrwflags::empty(),
nbytes: 0, nbytes: 0,
}, },
}); });
@@ -79,11 +81,11 @@ fn handle_timeout_event(timeout: ClockEventData, events: &mut Vec<types::Event>)
fn handle_fd_event( fn handle_fd_event(
ready_events: impl Iterator<Item = (FdEventData, yanix::poll::PollFd)>, ready_events: impl Iterator<Item = (FdEventData, yanix::poll::PollFd)>,
events: &mut Vec<types::Event>, events: &mut Vec<Event>,
) -> Result<()> { ) -> Result<()> {
fn query_nbytes(handle: EntryHandle) -> Result<u64> { fn query_nbytes(handle: EntryHandle) -> Result<u64> {
let file = handle.as_file()?; let file = handle.as_file()?;
if handle.get_file_type() == types::Filetype::RegularFile { if handle.get_file_type() == Filetype::RegularFile {
// fionread may overflow for large files, so use another way for regular files. // fionread may overflow for large files, so use another way for regular files.
use yanix::file::tell; use yanix::file::tell;
let meta = file.metadata()?; let meta = file.metadata()?;
@@ -106,50 +108,50 @@ fn handle_fd_event(
None => continue, None => continue,
}; };
let nbytes = if fd_event.r#type == types::Eventtype::FdRead { let nbytes = if fd_event.r#type == Eventtype::FdRead {
query_nbytes(fd_event.handle)? query_nbytes(fd_event.handle)?
} else { } else {
0 0
}; };
let output_event = if revents.contains(PollFlags::POLLNVAL) { let output_event = if revents.contains(PollFlags::POLLNVAL) {
types::Event { Event {
userdata: fd_event.userdata, userdata: fd_event.userdata,
error: Error::Badf.into(), error: Error::Badf.into(),
type_: fd_event.r#type, type_: fd_event.r#type,
fd_readwrite: types::EventFdReadwrite { fd_readwrite: EventFdReadwrite {
nbytes: 0, nbytes: 0,
flags: types::Eventrwflags::FD_READWRITE_HANGUP, flags: Eventrwflags::FD_READWRITE_HANGUP,
}, },
} }
} else if revents.contains(PollFlags::POLLERR) { } else if revents.contains(PollFlags::POLLERR) {
types::Event { Event {
userdata: fd_event.userdata, userdata: fd_event.userdata,
error: Error::Io.into(), error: Error::Io.into(),
type_: fd_event.r#type, type_: fd_event.r#type,
fd_readwrite: types::EventFdReadwrite { fd_readwrite: EventFdReadwrite {
nbytes: 0, nbytes: 0,
flags: types::Eventrwflags::FD_READWRITE_HANGUP, flags: Eventrwflags::FD_READWRITE_HANGUP,
}, },
} }
} else if revents.contains(PollFlags::POLLHUP) { } else if revents.contains(PollFlags::POLLHUP) {
types::Event { Event {
userdata: fd_event.userdata, userdata: fd_event.userdata,
error: types::Errno::Success, error: Errno::Success,
type_: fd_event.r#type, type_: fd_event.r#type,
fd_readwrite: types::EventFdReadwrite { fd_readwrite: EventFdReadwrite {
nbytes: 0, nbytes: 0,
flags: types::Eventrwflags::FD_READWRITE_HANGUP, flags: Eventrwflags::FD_READWRITE_HANGUP,
}, },
} }
} else if revents.contains(PollFlags::POLLIN) | revents.contains(PollFlags::POLLOUT) { } else if revents.contains(PollFlags::POLLIN) | revents.contains(PollFlags::POLLOUT) {
types::Event { Event {
userdata: fd_event.userdata, userdata: fd_event.userdata,
error: types::Errno::Success, error: Errno::Success,
type_: fd_event.r#type, type_: fd_event.r#type,
fd_readwrite: types::EventFdReadwrite { fd_readwrite: EventFdReadwrite {
nbytes: nbytes.try_into()?, nbytes: nbytes.try_into()?,
flags: types::Eventrwflags::empty(), flags: Eventrwflags::empty(),
}, },
} }
} else { } else {

View File

@@ -1,4 +1,4 @@
use crate::wasi::types; use crate::sched::{Clockid, Timestamp};
use crate::{Error, Result}; use crate::{Error, Result};
use cpu_time::{ProcessTime, ThreadTime}; use cpu_time::{ProcessTime, ThreadTime};
use lazy_static::lazy_static; use lazy_static::lazy_static;
@@ -12,7 +12,7 @@ lazy_static! {
// Timer resolution on Windows is really hard. We may consider exposing the resolution of the respective // Timer resolution on Windows is really hard. We may consider exposing the resolution of the respective
// timers as an associated function in the future. // timers as an associated function in the future.
pub(crate) fn res_get(clock_id: types::Clockid) -> Result<types::Timestamp> { pub(crate) fn res_get(clock_id: Clockid) -> Result<Timestamp> {
let ts = match clock_id { let ts = match clock_id {
// This is the best that we can do with std::time::SystemTime. // This is the best that we can do with std::time::SystemTime.
// Rust uses GetSystemTimeAsFileTime, which is said to have the resolution of // Rust uses GetSystemTimeAsFileTime, which is said to have the resolution of
@@ -47,25 +47,25 @@ pub(crate) fn res_get(clock_id: types::Clockid) -> Result<types::Timestamp> {
// [4] https://www.codeproject.com/Tips/1011902/High-Resolution-Time-For-Windows // [4] https://www.codeproject.com/Tips/1011902/High-Resolution-Time-For-Windows
// [5] https://stackoverflow.com/questions/7685762/windows-7-timing-functions-how-to-use-getsystemtimeadjustment-correctly // [5] https://stackoverflow.com/questions/7685762/windows-7-timing-functions-how-to-use-getsystemtimeadjustment-correctly
// [6] https://bugs.python.org/issue19007 // [6] https://bugs.python.org/issue19007
types::Clockid::Realtime => 55_000_000, Clockid::Realtime => 55_000_000,
// std::time::Instant uses QueryPerformanceCounter & QueryPerformanceFrequency internally // std::time::Instant uses QueryPerformanceCounter & QueryPerformanceFrequency internally
types::Clockid::Monotonic => *PERF_COUNTER_RES, Clockid::Monotonic => *PERF_COUNTER_RES,
// The best we can do is to hardcode the value from the docs. // The best we can do is to hardcode the value from the docs.
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getprocesstimes // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getprocesstimes
types::Clockid::ProcessCputimeId => 100, Clockid::ProcessCputimeId => 100,
// The best we can do is to hardcode the value from the docs. // The best we can do is to hardcode the value from the docs.
// https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadtimes // https://docs.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-getthreadtimes
types::Clockid::ThreadCputimeId => 100, Clockid::ThreadCputimeId => 100,
}; };
Ok(ts) Ok(ts)
} }
pub(crate) fn time_get(clock_id: types::Clockid) -> Result<types::Timestamp> { pub(crate) fn time_get(clock_id: Clockid) -> Result<Timestamp> {
let duration = match clock_id { let duration = match clock_id {
types::Clockid::Realtime => get_monotonic_time(), Clockid::Realtime => get_monotonic_time(),
types::Clockid::Monotonic => get_realtime_time()?, Clockid::Monotonic => get_realtime_time()?,
types::Clockid::ProcessCputimeId => get_proc_cputime()?, Clockid::ProcessCputimeId => get_proc_cputime()?,
types::Clockid::ThreadCputimeId => get_thread_cputime()?, Clockid::ThreadCputimeId => get_thread_cputime()?,
}; };
let duration = duration.as_nanos().try_into()?; let duration = duration.as_nanos().try_into()?;
Ok(duration) Ok(duration)

View File

@@ -1,10 +1,10 @@
use super::file_serial_no; use super::file_serial_no;
use super::oshandle::RawOsHandle; use super::oshandle::RawOsHandle;
use crate::handle::{Advice, Dircookie, Dirent, Fdflags, Filesize, Filestat};
use crate::path; use crate::path;
use crate::sys::osdir::OsDir; use crate::sys::osdir::OsDir;
use crate::sys::osfile::OsFile; use crate::sys::osfile::OsFile;
use crate::sys::AsFile; use crate::sys::AsFile;
use crate::wasi::types;
use crate::Result; use crate::Result;
use std::convert::TryInto; use std::convert::TryInto;
use std::fs::{File, OpenOptions}; use std::fs::{File, OpenOptions};
@@ -14,8 +14,8 @@ use std::path::Path;
use tracing::trace; use tracing::trace;
use winx::file::{AccessMode, FileModeInformation, Flags}; use winx::file::{AccessMode, FileModeInformation, Flags};
pub(crate) fn fdstat_get(file: &File) -> Result<types::Fdflags> { pub(crate) fn fdstat_get(file: &File) -> Result<Fdflags> {
let mut fdflags = types::Fdflags::empty(); let mut fdflags = Fdflags::empty();
let handle = file.as_raw_handle(); let handle = file.as_raw_handle();
let access_mode = winx::file::query_access_information(handle)?; let access_mode = winx::file::query_access_information(handle)?;
let mode = winx::file::query_mode_information(handle)?; let mode = winx::file::query_mode_information(handle)?;
@@ -24,13 +24,13 @@ pub(crate) fn fdstat_get(file: &File) -> Result<types::Fdflags> {
if access_mode.contains(AccessMode::FILE_APPEND_DATA) if access_mode.contains(AccessMode::FILE_APPEND_DATA)
&& !access_mode.contains(AccessMode::FILE_WRITE_DATA) && !access_mode.contains(AccessMode::FILE_WRITE_DATA)
{ {
fdflags |= types::Fdflags::APPEND; fdflags |= Fdflags::APPEND;
} }
if mode.contains(FileModeInformation::FILE_WRITE_THROUGH) { if mode.contains(FileModeInformation::FILE_WRITE_THROUGH) {
// Only report __WASI_FDFLAGS_SYNC // Only report __WASI_FDFLAGS_SYNC
// This is technically the only one of the O_?SYNC flags Windows supports. // This is technically the only one of the O_?SYNC flags Windows supports.
fdflags |= types::Fdflags::SYNC; fdflags |= Fdflags::SYNC;
} }
// Files do not support the `__WASI_FDFLAGS_NONBLOCK` flag // Files do not support the `__WASI_FDFLAGS_NONBLOCK` flag
@@ -42,10 +42,7 @@ pub(crate) fn fdstat_get(file: &File) -> Result<types::Fdflags> {
// handle came from `CreateFile`, but the Rust's libstd will use `GetStdHandle` // handle came from `CreateFile`, but the Rust's libstd will use `GetStdHandle`
// rather than `CreateFile`. Relevant discussion can be found in: // rather than `CreateFile`. Relevant discussion can be found in:
// https://github.com/rust-lang/rust/issues/40490 // https://github.com/rust-lang/rust/issues/40490
pub(crate) fn fdstat_set_flags( pub(crate) fn fdstat_set_flags(file: &File, fdflags: Fdflags) -> Result<Option<RawOsHandle>> {
file: &File,
fdflags: types::Fdflags,
) -> Result<Option<RawOsHandle>> {
let handle = file.as_raw_handle(); let handle = file.as_raw_handle();
let access_mode = winx::file::query_access_information(handle)?; let access_mode = winx::file::query_access_information(handle)?;
let new_access_mode = file_access_mode_from_fdflags( let new_access_mode = file_access_mode_from_fdflags(
@@ -65,14 +62,14 @@ pub(crate) fn fdstat_set_flags(
pub(crate) fn advise( pub(crate) fn advise(
_file: &OsFile, _file: &OsFile,
_advice: types::Advice, _advice: Advice,
_offset: types::Filesize, _offset: Filesize,
_len: types::Filesize, _len: Filesize,
) -> Result<()> { ) -> Result<()> {
Ok(()) Ok(())
} }
fn file_access_mode_from_fdflags(fdflags: types::Fdflags, read: bool, write: bool) -> AccessMode { fn file_access_mode_from_fdflags(fdflags: Fdflags, read: bool, write: bool) -> AccessMode {
let mut access_mode = AccessMode::READ_CONTROL; let mut access_mode = AccessMode::READ_CONTROL;
// Note that `GENERIC_READ` and `GENERIC_WRITE` cannot be used to properly support append-only mode // Note that `GENERIC_READ` and `GENERIC_WRITE` cannot be used to properly support append-only mode
@@ -89,7 +86,7 @@ fn file_access_mode_from_fdflags(fdflags: types::Fdflags, read: bool, write: boo
// For append, grant the handle FILE_APPEND_DATA access but *not* FILE_WRITE_DATA. // For append, grant the handle FILE_APPEND_DATA access but *not* FILE_WRITE_DATA.
// This makes the handle "append only". // This makes the handle "append only".
// Changes to the file pointer will be ignored (like POSIX's O_APPEND behavior). // Changes to the file pointer will be ignored (like POSIX's O_APPEND behavior).
if fdflags.contains(&types::Fdflags::APPEND) { if fdflags.contains(&Fdflags::APPEND) {
access_mode.insert(AccessMode::FILE_APPEND_DATA); access_mode.insert(AccessMode::FILE_APPEND_DATA);
access_mode.remove(AccessMode::FILE_WRITE_DATA); access_mode.remove(AccessMode::FILE_WRITE_DATA);
} }
@@ -127,8 +124,8 @@ fn file_access_mode_from_fdflags(fdflags: types::Fdflags, read: bool, write: boo
// other entries, in order they were returned by FindNextFileW get subsequent integers as their cookies // other entries, in order they were returned by FindNextFileW get subsequent integers as their cookies
pub(crate) fn readdir( pub(crate) fn readdir(
dirfd: &OsDir, dirfd: &OsDir,
cookie: types::Dircookie, cookie: Dircookie,
) -> Result<Box<dyn Iterator<Item = Result<(types::Dirent, String)>>>> { ) -> Result<Box<dyn Iterator<Item = Result<(Dirent, String)>>>> {
use winx::file::get_file_path; use winx::file::get_file_path;
let cookie = cookie.try_into()?; let cookie = cookie.try_into()?;
@@ -146,7 +143,7 @@ pub(crate) fn readdir(
let ftype = dir.file_type()?; let ftype = dir.file_type()?;
let name = path::from_host(dir.file_name())?; let name = path::from_host(dir.file_name())?;
let d_ino = File::open(dir.path()).and_then(|f| file_serial_no(&f))?; let d_ino = File::open(dir.path()).and_then(|f| file_serial_no(&f))?;
let dirent = types::Dirent { let dirent = Dirent {
d_namlen: name.len().try_into()?, d_namlen: name.len().try_into()?,
d_type: ftype.into(), d_type: ftype.into(),
d_ino, d_ino,
@@ -171,8 +168,8 @@ pub(crate) fn readdir(
fn dirent_from_path<P: AsRef<Path>>( fn dirent_from_path<P: AsRef<Path>>(
path: P, path: P,
name: &str, name: &str,
cookie: types::Dircookie, cookie: Dircookie,
) -> Result<(types::Dirent, String)> { ) -> Result<(Dirent, String)> {
let path = path.as_ref(); let path = path.as_ref();
trace!("dirent_from_path: opening {}", path.to_string_lossy()); trace!("dirent_from_path: opening {}", path.to_string_lossy());
@@ -183,7 +180,7 @@ fn dirent_from_path<P: AsRef<Path>>(
.open(path)?; .open(path)?;
let ty = file.metadata()?.file_type(); let ty = file.metadata()?.file_type();
let name = name.to_owned(); let name = name.to_owned();
let dirent = types::Dirent { let dirent = Dirent {
d_namlen: name.len().try_into()?, d_namlen: name.len().try_into()?,
d_next: cookie, d_next: cookie,
d_type: ty.into(), d_type: ty.into(),
@@ -192,7 +189,7 @@ fn dirent_from_path<P: AsRef<Path>>(
Ok((dirent, name)) Ok((dirent, name))
} }
pub(crate) fn filestat_get(file: &File) -> Result<types::Filestat> { pub(crate) fn filestat_get(file: &File) -> Result<Filestat> {
let filestat = file.try_into()?; let filestat = file.try_into()?;
Ok(filestat) Ok(filestat)
} }

View File

@@ -8,9 +8,8 @@ pub(crate) mod path;
pub(crate) mod poll; pub(crate) mod poll;
pub(crate) mod stdio; pub(crate) mod stdio;
use crate::handle::HandleRights; use crate::handle::{Fdflags, Filestat, Filetype, HandleRights, Oflags, Rights, RightsExt};
use crate::sys::AsFile; use crate::sys::AsFile;
use crate::wasi::{types, RightsExt};
use crate::{Error, Result}; use crate::{Error, Result};
use std::convert::{TryFrom, TryInto}; use std::convert::{TryFrom, TryInto};
use std::fs::File; use std::fs::File;
@@ -28,54 +27,50 @@ impl<T: AsRawHandle> AsFile for T {
} }
} }
pub(super) fn get_file_type(file: &File) -> io::Result<types::Filetype> { pub(super) fn get_file_type(file: &File) -> io::Result<Filetype> {
let file_type = unsafe { winx::file::get_file_type(file.as_raw_handle())? }; let file_type = unsafe { winx::file::get_file_type(file.as_raw_handle())? };
let file_type = if file_type.is_char() { let file_type = if file_type.is_char() {
// character file: LPT device or console // character file: LPT device or console
// TODO: rule out LPT device // TODO: rule out LPT device
types::Filetype::CharacterDevice Filetype::CharacterDevice
} else if file_type.is_disk() { } else if file_type.is_disk() {
// disk file: file, dir or disk device // disk file: file, dir or disk device
let meta = file.metadata()?; let meta = file.metadata()?;
if meta.is_dir() { if meta.is_dir() {
types::Filetype::Directory Filetype::Directory
} else if meta.is_file() { } else if meta.is_file() {
types::Filetype::RegularFile Filetype::RegularFile
} else { } else {
return Err(io::Error::from_raw_os_error(libc::EINVAL)); return Err(io::Error::from_raw_os_error(libc::EINVAL));
} }
} else if file_type.is_pipe() { } else if file_type.is_pipe() {
// pipe object: socket, named pipe or anonymous pipe // pipe object: socket, named pipe or anonymous pipe
// TODO: what about pipes, etc? // TODO: what about pipes, etc?
types::Filetype::SocketStream Filetype::SocketStream
} else { } else {
return Err(io::Error::from_raw_os_error(libc::EINVAL)); return Err(io::Error::from_raw_os_error(libc::EINVAL));
}; };
Ok(file_type) Ok(file_type)
} }
pub(super) fn get_rights(file_type: &types::Filetype) -> io::Result<HandleRights> { pub(super) fn get_rights(file_type: &Filetype) -> io::Result<HandleRights> {
let (base, inheriting) = match file_type { let (base, inheriting) = match file_type {
types::Filetype::BlockDevice => ( Filetype::BlockDevice => (
types::Rights::block_device_base(), Rights::block_device_base(),
types::Rights::block_device_inheriting(), Rights::block_device_inheriting(),
), ),
types::Filetype::CharacterDevice => (types::Rights::tty_base(), types::Rights::tty_base()), Filetype::CharacterDevice => (Rights::tty_base(), Rights::tty_base()),
types::Filetype::SocketDgram | types::Filetype::SocketStream => ( Filetype::SocketDgram | Filetype::SocketStream => {
types::Rights::socket_base(), (Rights::socket_base(), Rights::socket_inheriting())
types::Rights::socket_inheriting(), }
Filetype::SymbolicLink | Filetype::Unknown => (
Rights::regular_file_base(),
Rights::regular_file_inheriting(),
), ),
types::Filetype::SymbolicLink | types::Filetype::Unknown => ( Filetype::Directory => (Rights::directory_base(), Rights::directory_inheriting()),
types::Rights::regular_file_base(), Filetype::RegularFile => (
types::Rights::regular_file_inheriting(), Rights::regular_file_base(),
), Rights::regular_file_inheriting(),
types::Filetype::Directory => (
types::Rights::directory_base(),
types::Rights::directory_inheriting(),
),
types::Filetype::RegularFile => (
types::Rights::regular_file_base(),
types::Rights::regular_file_inheriting(),
), ),
}; };
let rights = HandleRights::new(base, inheriting); let rights = HandleRights::new(base, inheriting);
@@ -132,12 +127,12 @@ fn systemtime_to_timestamp(st: SystemTime) -> Result<u64> {
.map_err(Into::into) // u128 doesn't fit into u64 .map_err(Into::into) // u128 doesn't fit into u64
} }
impl TryFrom<&File> for types::Filestat { impl TryFrom<&File> for Filestat {
type Error = Error; type Error = Error;
fn try_from(file: &File) -> Result<Self> { fn try_from(file: &File) -> Result<Self> {
let metadata = file.metadata()?; let metadata = file.metadata()?;
Ok(types::Filestat { Ok(Filestat {
dev: device_id(file)?, dev: device_id(file)?,
ino: file_serial_no(file)?, ino: file_serial_no(file)?,
nlink: num_hardlinks(file)?.try_into()?, // u64 doesn't fit into u32 nlink: num_hardlinks(file)?.try_into()?, // u64 doesn't fit into u32
@@ -150,15 +145,15 @@ impl TryFrom<&File> for types::Filestat {
} }
} }
impl From<types::Oflags> for CreationDisposition { impl From<Oflags> for CreationDisposition {
fn from(oflags: types::Oflags) -> Self { fn from(oflags: Oflags) -> Self {
if oflags.contains(&types::Oflags::CREAT) { if oflags.contains(&Oflags::CREAT) {
if oflags.contains(&types::Oflags::EXCL) { if oflags.contains(&Oflags::EXCL) {
CreationDisposition::CREATE_NEW CreationDisposition::CREATE_NEW
} else { } else {
CreationDisposition::CREATE_ALWAYS CreationDisposition::CREATE_ALWAYS
} }
} else if oflags.contains(&types::Oflags::TRUNC) { } else if oflags.contains(&Oflags::TRUNC) {
CreationDisposition::TRUNCATE_EXISTING CreationDisposition::TRUNCATE_EXISTING
} else { } else {
CreationDisposition::OPEN_EXISTING CreationDisposition::OPEN_EXISTING
@@ -166,8 +161,8 @@ impl From<types::Oflags> for CreationDisposition {
} }
} }
impl From<types::Fdflags> for Flags { impl From<Fdflags> for Flags {
fn from(fdflags: types::Fdflags) -> Self { fn from(fdflags: Fdflags) -> Self {
// Enable backup semantics so directories can be opened as files // Enable backup semantics so directories can be opened as files
let mut flags = Flags::FILE_FLAG_BACKUP_SEMANTICS; let mut flags = Flags::FILE_FLAG_BACKUP_SEMANTICS;
@@ -176,9 +171,9 @@ impl From<types::Fdflags> for Flags {
// treat I/O operations on files as synchronous. WASI might have an async-io API in the future. // treat I/O operations on files as synchronous. WASI might have an async-io API in the future.
// Technically, Windows only supports __WASI_FDFLAGS_SYNC, but treat all the flags as the same. // Technically, Windows only supports __WASI_FDFLAGS_SYNC, but treat all the flags as the same.
if fdflags.contains(&types::Fdflags::DSYNC) if fdflags.contains(&Fdflags::DSYNC)
|| fdflags.contains(&types::Fdflags::RSYNC) || fdflags.contains(&Fdflags::RSYNC)
|| fdflags.contains(&types::Fdflags::SYNC) || fdflags.contains(&Fdflags::SYNC)
{ {
flags.insert(Flags::FILE_FLAG_WRITE_THROUGH); flags.insert(Flags::FILE_FLAG_WRITE_THROUGH);
} }

View File

@@ -1,6 +1,5 @@
use super::oshandle::RawOsHandle; use super::oshandle::RawOsHandle;
use crate::handle::HandleRights; use crate::handle::{HandleRights, Rights, RightsExt};
use crate::wasi::{types, RightsExt};
use std::cell::Cell; use std::cell::Cell;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fs::File; use std::fs::File;
@@ -55,16 +54,13 @@ impl TryFrom<File> for OsDir {
fn get_rights(file: &File) -> io::Result<HandleRights> { fn get_rights(file: &File) -> io::Result<HandleRights> {
use winx::file::{query_access_information, AccessMode}; use winx::file::{query_access_information, AccessMode};
let mut rights = HandleRights::new( let mut rights = HandleRights::new(Rights::directory_base(), Rights::directory_inheriting());
types::Rights::directory_base(),
types::Rights::directory_inheriting(),
);
let mode = query_access_information(file.as_raw_handle())?; let mode = query_access_information(file.as_raw_handle())?;
if mode.contains(AccessMode::FILE_GENERIC_READ) { if mode.contains(AccessMode::FILE_GENERIC_READ) {
rights.base |= types::Rights::FD_READ; rights.base |= Rights::FD_READ;
} }
if mode.contains(AccessMode::FILE_GENERIC_WRITE) { if mode.contains(AccessMode::FILE_GENERIC_WRITE) {
rights.base |= types::Rights::FD_WRITE; rights.base |= Rights::FD_WRITE;
} }
Ok(rights) Ok(rights)
} }

View File

@@ -1,7 +1,6 @@
use super::oshandle::RawOsHandle; use super::oshandle::RawOsHandle;
use crate::handle::HandleRights; use crate::handle::{HandleRights, Rights, RightsExt};
use crate::sys::osfile::OsFile; use crate::sys::osfile::OsFile;
use crate::wasi::{types, RightsExt};
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fs::File; use std::fs::File;
use std::io; use std::io;
@@ -24,15 +23,15 @@ impl TryFrom<File> for OsFile {
fn get_rights(file: &File) -> io::Result<HandleRights> { fn get_rights(file: &File) -> io::Result<HandleRights> {
use winx::file::{query_access_information, AccessMode}; use winx::file::{query_access_information, AccessMode};
let mut rights = HandleRights::new( let mut rights = HandleRights::new(
types::Rights::regular_file_base(), Rights::regular_file_base(),
types::Rights::regular_file_inheriting(), Rights::regular_file_inheriting(),
); );
let mode = query_access_information(file.as_raw_handle())?; let mode = query_access_information(file.as_raw_handle())?;
if mode.contains(AccessMode::FILE_GENERIC_READ) { if mode.contains(AccessMode::FILE_GENERIC_READ) {
rights.base |= types::Rights::FD_READ; rights.base |= Rights::FD_READ;
} }
if mode.contains(AccessMode::FILE_GENERIC_WRITE) { if mode.contains(AccessMode::FILE_GENERIC_WRITE) {
rights.base |= types::Rights::FD_WRITE; rights.base |= Rights::FD_WRITE;
} }
Ok(rights) Ok(rights)
} }

View File

@@ -1,7 +1,7 @@
use super::oshandle::RawOsHandle; use super::oshandle::RawOsHandle;
use super::{get_file_type, get_rights}; use super::{get_file_type, get_rights};
use crate::handle::Filetype;
use crate::sys::osother::OsOther; use crate::sys::osother::OsOther;
use crate::wasi::types;
use std::convert::TryFrom; use std::convert::TryFrom;
use std::fs::File; use std::fs::File;
use std::io; use std::io;
@@ -12,7 +12,7 @@ impl TryFrom<File> for OsOther {
fn try_from(file: File) -> io::Result<Self> { fn try_from(file: File) -> io::Result<Self> {
let file_type = get_file_type(&file)?; let file_type = get_file_type(&file)?;
if file_type == types::Filetype::RegularFile || file_type == types::Filetype::Directory { if file_type == Filetype::RegularFile || file_type == Filetype::Directory {
return Err(io::Error::from_raw_os_error(libc::EINVAL)); return Err(io::Error::from_raw_os_error(libc::EINVAL));
} }
let rights = get_rights(&file_type)?; let rights = get_rights(&file_type)?;

View File

@@ -1,7 +1,7 @@
use crate::handle::{Handle, HandleRights}; use crate::handle::{Fdflags, Filestat, Fstflags, Handle, HandleRights, Oflags, Rights};
use crate::sched::Timestamp;
use crate::sys::osdir::OsDir; use crate::sys::osdir::OsDir;
use crate::sys::{fd, AsFile}; use crate::sys::{fd, AsFile};
use crate::wasi::types;
use crate::{Error, Result}; use crate::{Error, Result};
use std::convert::TryFrom; use std::convert::TryFrom;
use std::ffi::{OsStr, OsString}; use std::ffi::{OsStr, OsString};
@@ -52,7 +52,7 @@ fn concatenate<P: AsRef<Path>>(file: &OsDir, path: P) -> Result<PathBuf> {
Ok(out_path) Ok(out_path)
} }
fn file_access_mode_from_fdflags(fdflags: types::Fdflags, read: bool, write: bool) -> AccessMode { fn file_access_mode_from_fdflags(fdflags: Fdflags, read: bool, write: bool) -> AccessMode {
let mut access_mode = AccessMode::READ_CONTROL; let mut access_mode = AccessMode::READ_CONTROL;
// We always need `FILE_WRITE_ATTRIBUTES` so that we can set attributes such as filetimes, etc. // We always need `FILE_WRITE_ATTRIBUTES` so that we can set attributes such as filetimes, etc.
@@ -72,7 +72,7 @@ fn file_access_mode_from_fdflags(fdflags: types::Fdflags, read: bool, write: boo
// For append, grant the handle FILE_APPEND_DATA access but *not* FILE_WRITE_DATA. // For append, grant the handle FILE_APPEND_DATA access but *not* FILE_WRITE_DATA.
// This makes the handle "append only". // This makes the handle "append only".
// Changes to the file pointer will be ignored (like POSIX's O_APPEND behavior). // Changes to the file pointer will be ignored (like POSIX's O_APPEND behavior).
if fdflags.contains(&types::Fdflags::APPEND) { if fdflags.contains(&Fdflags::APPEND) {
access_mode.insert(AccessMode::FILE_APPEND_DATA); access_mode.insert(AccessMode::FILE_APPEND_DATA);
access_mode.remove(AccessMode::FILE_WRITE_DATA); access_mode.remove(AccessMode::FILE_WRITE_DATA);
} }
@@ -92,27 +92,27 @@ pub(crate) fn from_host<S: AsRef<OsStr>>(s: S) -> Result<String> {
pub(crate) fn open_rights( pub(crate) fn open_rights(
input_rights: &HandleRights, input_rights: &HandleRights,
oflags: types::Oflags, oflags: Oflags,
fdflags: types::Fdflags, fdflags: Fdflags,
) -> HandleRights { ) -> HandleRights {
// which rights are needed on the dirfd? // which rights are needed on the dirfd?
let mut needed_base = types::Rights::PATH_OPEN; let mut needed_base = Rights::PATH_OPEN;
let mut needed_inheriting = input_rights.base | input_rights.inheriting; let mut needed_inheriting = input_rights.base | input_rights.inheriting;
// convert open flags // convert open flags
if oflags.contains(&types::Oflags::CREAT) { if oflags.contains(&Oflags::CREAT) {
needed_base |= types::Rights::PATH_CREATE_FILE; needed_base |= Rights::PATH_CREATE_FILE;
} else if oflags.contains(&types::Oflags::TRUNC) { } else if oflags.contains(&Oflags::TRUNC) {
needed_base |= types::Rights::PATH_FILESTAT_SET_SIZE; needed_base |= Rights::PATH_FILESTAT_SET_SIZE;
} }
// convert file descriptor flags // convert file descriptor flags
if fdflags.contains(&types::Fdflags::DSYNC) if fdflags.contains(&Fdflags::DSYNC)
|| fdflags.contains(&types::Fdflags::RSYNC) || fdflags.contains(&Fdflags::RSYNC)
|| fdflags.contains(&types::Fdflags::SYNC) || fdflags.contains(&Fdflags::SYNC)
{ {
needed_inheriting |= types::Rights::FD_DATASYNC; needed_inheriting |= Rights::FD_DATASYNC;
needed_inheriting |= types::Rights::FD_SYNC; needed_inheriting |= Rights::FD_SYNC;
} }
HandleRights::new(needed_base, needed_inheriting) HandleRights::new(needed_base, needed_inheriting)
@@ -206,18 +206,18 @@ pub(crate) fn open(
path: &str, path: &str,
read: bool, read: bool,
write: bool, write: bool,
oflags: types::Oflags, oflags: Oflags,
fdflags: types::Fdflags, fdflags: Fdflags,
) -> Result<Box<dyn Handle>> { ) -> Result<Box<dyn Handle>> {
use winx::file::{AccessMode, CreationDisposition, Flags}; use winx::file::{AccessMode, CreationDisposition, Flags};
let is_trunc = oflags.contains(&types::Oflags::TRUNC); let is_trunc = oflags.contains(&Oflags::TRUNC);
if is_trunc { if is_trunc {
// Windows does not support append mode when opening for truncation // Windows does not support append mode when opening for truncation
// This is because truncation requires `GENERIC_WRITE` access, which will override the removal // This is because truncation requires `GENERIC_WRITE` access, which will override the removal
// of the `FILE_WRITE_DATA` permission. // of the `FILE_WRITE_DATA` permission.
if fdflags.contains(&types::Fdflags::APPEND) { if fdflags.contains(&Fdflags::APPEND) {
return Err(Error::Notsup); return Err(Error::Notsup);
} }
} }
@@ -246,7 +246,7 @@ pub(crate) fn open(
return Err(Error::Loop); return Err(Error::Loop);
} }
// check if we are trying to open a file as a dir // check if we are trying to open a file as a dir
if file_type.is_file() && oflags.contains(&types::Oflags::DIRECTORY) { if file_type.is_file() && oflags.contains(&Oflags::DIRECTORY) {
return Err(Error::Notdir); return Err(Error::Notdir);
} }
} }
@@ -499,7 +499,7 @@ pub(crate) fn remove_directory(dirfd: &OsDir, path: &str) -> Result<()> {
std::fs::remove_dir(&path).map_err(Into::into) std::fs::remove_dir(&path).map_err(Into::into)
} }
pub(crate) fn filestat_get_at(dirfd: &OsDir, path: &str, follow: bool) -> Result<types::Filestat> { pub(crate) fn filestat_get_at(dirfd: &OsDir, path: &str, follow: bool) -> Result<Filestat> {
use winx::file::Flags; use winx::file::Flags;
let path = concatenate(dirfd, path)?; let path = concatenate(dirfd, path)?;
let mut opts = OpenOptions::new(); let mut opts = OpenOptions::new();
@@ -517,9 +517,9 @@ pub(crate) fn filestat_get_at(dirfd: &OsDir, path: &str, follow: bool) -> Result
pub(crate) fn filestat_set_times_at( pub(crate) fn filestat_set_times_at(
dirfd: &OsDir, dirfd: &OsDir,
path: &str, path: &str,
atim: types::Timestamp, atim: Timestamp,
mtim: types::Timestamp, mtim: Timestamp,
fst_flags: types::Fstflags, fst_flags: Fstflags,
follow: bool, follow: bool,
) -> Result<()> { ) -> Result<()> {
use winx::file::{AccessMode, Flags}; use winx::file::{AccessMode, Flags};

View File

@@ -1,11 +1,12 @@
use crate::handle::Handle; use crate::handle::{Filetype, Handle};
use crate::poll::{ClockEventData, FdEventData}; use crate::sched::{
ClockEventData, Errno, Event, EventFdReadwrite, Eventrwflags, Eventtype, FdEventData,
};
use crate::sys::osdir::OsDir; use crate::sys::osdir::OsDir;
use crate::sys::osfile::OsFile; use crate::sys::osfile::OsFile;
use crate::sys::osother::OsOther; use crate::sys::osother::OsOther;
use crate::sys::stdio::{Stderr, Stdin, Stdout}; use crate::sys::stdio::{Stderr, Stdin, Stdout};
use crate::sys::AsFile; use crate::sys::AsFile;
use crate::wasi::types;
use crate::{Error, Result}; use crate::{Error, Result};
use lazy_static::lazy_static; use lazy_static::lazy_static;
use std::convert::TryInto; use std::convert::TryInto;
@@ -24,7 +25,7 @@ enum PollState {
Ready, Ready,
NotReady, // it's not ready, but we didn't wait NotReady, // it's not ready, but we didn't wait
TimedOut, // it's not ready and a timeout has occurred TimedOut, // it's not ready and a timeout has occurred
Error(types::Errno), Error(Errno),
} }
enum WaitMode { enum WaitMode {
@@ -80,7 +81,7 @@ impl StdinPoll {
// Linux returns `POLLIN` in both cases, and we imitate this behavior. // Linux returns `POLLIN` in both cases, and we imitate this behavior.
let resp = match std::io::stdin().lock().fill_buf() { let resp = match std::io::stdin().lock().fill_buf() {
Ok(_) => PollState::Ready, Ok(_) => PollState::Ready,
Err(e) => PollState::Error(types::Errno::from(Error::from(e))), Err(e) => PollState::Error(Errno::from(Error::from(e))),
}; };
// Notify the requestor about data in stdin. They may have already timed out, // Notify the requestor about data in stdin. They may have already timed out,
@@ -102,52 +103,45 @@ lazy_static! {
}; };
} }
fn make_rw_event( fn make_rw_event(event: &FdEventData, nbytes: std::result::Result<u64, Errno>) -> Event {
event: &FdEventData,
nbytes: std::result::Result<u64, types::Errno>,
) -> types::Event {
let (nbytes, error) = match nbytes { let (nbytes, error) = match nbytes {
Ok(nbytes) => (nbytes, types::Errno::Success), Ok(nbytes) => (nbytes, Errno::Success),
Err(e) => (u64::default(), e), Err(e) => (u64::default(), e),
}; };
types::Event { Event {
userdata: event.userdata, userdata: event.userdata,
type_: event.r#type, type_: event.r#type,
error, error,
fd_readwrite: types::EventFdReadwrite { fd_readwrite: EventFdReadwrite {
nbytes, nbytes,
flags: types::Eventrwflags::empty(), flags: Eventrwflags::empty(),
}, },
} }
} }
fn make_timeout_event(timeout: &ClockEventData) -> types::Event { fn make_timeout_event(timeout: &ClockEventData) -> Event {
types::Event { Event {
userdata: timeout.userdata, userdata: timeout.userdata,
type_: types::Eventtype::Clock, type_: Eventtype::Clock,
error: types::Errno::Success, error: Errno::Success,
fd_readwrite: types::EventFdReadwrite { fd_readwrite: EventFdReadwrite {
nbytes: 0, nbytes: 0,
flags: types::Eventrwflags::empty(), flags: Eventrwflags::empty(),
}, },
} }
} }
fn handle_timeout( fn handle_timeout(timeout_event: ClockEventData, timeout: Duration, events: &mut Vec<Event>) {
timeout_event: ClockEventData,
timeout: Duration,
events: &mut Vec<types::Event>,
) {
thread::sleep(timeout); thread::sleep(timeout);
handle_timeout_event(timeout_event, events); handle_timeout_event(timeout_event, events);
} }
fn handle_timeout_event(timeout_event: ClockEventData, events: &mut Vec<types::Event>) { fn handle_timeout_event(timeout_event: ClockEventData, events: &mut Vec<Event>) {
let new_event = make_timeout_event(&timeout_event); let new_event = make_timeout_event(&timeout_event);
events.push(new_event); events.push(new_event);
} }
fn handle_rw_event(event: FdEventData, out_events: &mut Vec<types::Event>) { fn handle_rw_event(event: FdEventData, out_events: &mut Vec<Event>) {
let handle = &event.handle; let handle = &event.handle;
let size = if let Some(_) = handle.as_any().downcast_ref::<Stdin>() { let size = if let Some(_) = handle.as_any().downcast_ref::<Stdin>() {
// We return the only universally correct lower bound, see the comment later in the function. // We return the only universally correct lower bound, see the comment later in the function.
@@ -159,12 +153,12 @@ fn handle_rw_event(event: FdEventData, out_events: &mut Vec<types::Event>) {
// On Unix, ioctl(FIONREAD) will return 0 for stdout/stderr. Emulate the same behavior on Windows. // On Unix, ioctl(FIONREAD) will return 0 for stdout/stderr. Emulate the same behavior on Windows.
Ok(0) Ok(0)
} else { } else {
if event.r#type == types::Eventtype::FdRead { if event.r#type == Eventtype::FdRead {
handle handle
.as_file() .as_file()
.and_then(|f| f.metadata()) .and_then(|f| f.metadata())
.map(|m| m.len()) .map(|m| m.len())
.map_err(|ioerror| types::Errno::from(Error::from(ioerror))) .map_err(|ioerror| Errno::from(Error::from(ioerror)))
} else { } else {
// The spec is unclear what nbytes should actually be for __WASI_EVENTTYPE_FD_WRITE and // The spec is unclear what nbytes should actually be for __WASI_EVENTTYPE_FD_WRITE and
// the implementation on Unix just returns 0 here, so it's probably fine // the implementation on Unix just returns 0 here, so it's probably fine
@@ -177,7 +171,7 @@ fn handle_rw_event(event: FdEventData, out_events: &mut Vec<types::Event>) {
out_events.push(new_event); out_events.push(new_event);
} }
fn handle_error_event(event: FdEventData, error: types::Errno, out_events: &mut Vec<types::Event>) { fn handle_error_event(event: FdEventData, error: Errno, out_events: &mut Vec<Event>) {
let new_event = make_rw_event(&event, Err(error)); let new_event = make_rw_event(&event, Err(error));
out_events.push(new_event); out_events.push(new_event);
} }
@@ -185,7 +179,7 @@ fn handle_error_event(event: FdEventData, error: types::Errno, out_events: &mut
pub(crate) fn oneoff( pub(crate) fn oneoff(
timeout: Option<ClockEventData>, timeout: Option<ClockEventData>,
fd_events: Vec<FdEventData>, fd_events: Vec<FdEventData>,
events: &mut Vec<types::Event>, events: &mut Vec<Event>,
) -> Result<()> { ) -> Result<()> {
let timeout = timeout let timeout = timeout
.map(|event| { .map(|event| {
@@ -234,7 +228,7 @@ pub(crate) fn oneoff(
// considered immediately ready, following the behavior on Linux. // considered immediately ready, following the behavior on Linux.
immediate_events.push(event); immediate_events.push(event);
} else if let Some(other) = handle.as_any().downcast_ref::<OsOther>() { } else if let Some(other) = handle.as_any().downcast_ref::<OsOther>() {
if other.get_file_type() == types::Filetype::SocketStream { if other.get_file_type() == Filetype::SocketStream {
// We map pipe to SocketStream // We map pipe to SocketStream
pipe_events.push(event); pipe_events.push(event);
} else { } else {
@@ -242,7 +236,7 @@ pub(crate) fn oneoff(
"poll_oneoff: unsupported file type: {}", "poll_oneoff: unsupported file type: {}",
other.get_file_type() other.get_file_type()
); );
handle_error_event(event, types::Errno::Notsup, events); handle_error_event(event, Errno::Notsup, events);
} }
} else { } else {
tracing::error!("can poll FdEvent for OS resources only"); tracing::error!("can poll FdEvent for OS resources only");