[wasi-common]: yanix now returns io::Error directly (#1242)

* Yanix now returns io::Error

This commit may seem somewhat controversial at first, but hear me
out first. Currently, Yanix would return a custom error that's a
wrapper around three other error types returned by various entities
inside Rust's `libstd`. In particular, Yanix's error type would wrap
`io::Error`, `num::TryFromIntError` and `ffi::NulError`. It turns
out that there is a natural conversion between the first and the last
and provided by the standard library, i.e., `From<ffi::NulError> for io::Error`
is provided. So at the surface it may seem that only the first two
wrapped error types are worth keeping.

Digging a little bit deeper into `libstd`, `num::TryFromIntError`
is essentially speaking only a marker that the integral conversion
went wrong. The struct implementing this error stores a unit type,
and nothing more. It therefore seems like a waste to wrap this
particular error when we could unify everything under `io::Error`.
And so, whenever we perform an int conversion, I suggest we simply
remap the error to `io::Error::from_raw_os_error(libc::EOVERFLOW)`
since this carries a comparable amount of information.

As a result of completely discarding `yanix::Error` custom error type,
we are invariably simplifying `yanix` itself, but also allowing
`wasi-common` to simplify in several places as well.

* Adapt wasi-common to changes in yanix

* Add Cargo.lock

* Unwrap try_into's where possible

* Remove unnecessary type annotation
This commit is contained in:
Jakub Konka
2020-03-06 23:20:54 +01:00
committed by GitHub
parent 55337abd3f
commit 42fae4e3b8
25 changed files with 368 additions and 398 deletions

View File

@@ -1,8 +1,8 @@
use crate::{
dir::{Dir, Entry, EntryExt, SeekLoc},
Result,
use crate::dir::{Dir, Entry, EntryExt, SeekLoc};
use std::{
io::{Error, Result},
ops::Deref,
};
use std::{io, ops::Deref};
#[derive(Copy, Clone, Debug)]
pub(crate) struct EntryImpl {
@@ -19,17 +19,17 @@ impl Deref for EntryImpl {
}
pub(crate) fn iter_impl(dir: &Dir) -> Option<Result<EntryImpl>> {
let errno = io::Error::last_os_error();
let errno = Error::last_os_error();
let dirent = unsafe { libc::readdir(dir.as_raw().as_ptr()) };
if dirent.is_null() {
let curr_errno = io::Error::last_os_error();
let curr_errno = Error::last_os_error();
if errno.raw_os_error() != curr_errno.raw_os_error() {
// TODO This should be verified on different BSD-flavours.
//
// According to 4.3BSD/POSIX.1-2001 man pages, there was an error
// if the errno value has changed at some point during the sequence
// of readdir calls.
Some(Err(curr_errno.into()))
Some(Err(curr_errno))
} else {
// Not an error. We've simply reached the end of the stream.
None

View File

@@ -1,5 +1,5 @@
use crate::{Error, Result};
use std::{convert::TryInto, os::unix::prelude::*};
use crate::from_success_code;
use std::{convert::TryInto, io::Result, os::unix::prelude::*};
#[cfg(not(any(target_os = "freebsd", target_os = "netbsd")))]
#[derive(Debug, Copy, Clone)]
@@ -44,11 +44,22 @@ pub unsafe fn posix_fadvise(
// off_t ra_offset; /* offset into the file */
// int ra_count; /* size of the read */
// };
let ra_count = match len.try_into() {
Ok(ra_count) => ra_count,
Err(_) => {
// This conversion can fail, because it's converting into int. But in that case, the user
// is providing a dubiously large hint. This is not confirmed (no helpful info in the man
// pages), but offhand, a 2+ GiB advisory read async seems unlikely to help with any kind
// of performance, so we log and exit early with a no-op.
log::warn!("`len` too big to fit in the host's command. Returning early with no-op!");
return Ok(());
}
};
let advisory = libc::radvisory {
ra_offset: offset,
ra_count: len.try_into()?,
ra_count,
};
Error::from_success_code(libc::fcntl(fd, libc::F_RDADVISE, &advisory))
from_success_code(libc::fcntl(fd, libc::F_RDADVISE, &advisory))
}
#[cfg(any(target_os = "freebsd", target_os = "netbsd"))]
@@ -58,7 +69,7 @@ pub unsafe fn posix_fadvise(
len: libc::off_t,
advice: PosixFadviseAdvice,
) -> Result<()> {
Error::from_success_code(libc::posix_fadvise(fd, offset, len, advice as libc::c_int))
from_success_code(libc::posix_fadvise(fd, offset, len, advice as libc::c_int))
}
// On BSDs without support we leave it as no-op

View File

@@ -1,5 +1,7 @@
use crate::Result;
use std::{io, os::unix::prelude::*};
use std::{
io::{Error, Result},
os::unix::prelude::*,
};
pub unsafe fn isatty(fd: RawFd) -> Result<bool> {
let res = libc::isatty(fd);
@@ -8,15 +10,11 @@ pub unsafe fn isatty(fd: RawFd) -> Result<bool> {
Ok(true)
} else {
// ... otherwise 0 is returned, and errno is set to indicate the error.
let errno = io::Error::last_os_error();
if let Some(raw_errno) = errno.raw_os_error() {
if raw_errno == libc::ENOTTY {
Ok(false)
} else {
Err(errno.into())
}
let errno = Error::last_os_error();
if errno.raw_os_error().unwrap() == libc::ENOTTY {
Ok(false)
} else {
Err(errno.into())
Err(errno)
}
}
}

View File

@@ -5,12 +5,20 @@ pub(crate) mod fadvise;
#[path = "../linux/file.rs"]
pub(crate) mod file;
use crate::{dir::SeekLoc, Result};
use crate::dir::SeekLoc;
use std::convert::TryInto;
use std::io::{Error, Result};
impl SeekLoc {
pub unsafe fn from_raw(loc: i64) -> Result<Self> {
let loc = loc.try_into()?;
// The cookie (or `loc`) is an opaque value, and applications aren't supposed to do
// arithmetic on them or pick their own values or have any awareness of the numeric
// range of the values. They're just supposed to pass back in the values that we
// give them. And any value we give them will be convertable back to `long`,
// because that's the type the OS gives them to us in. So return an `EINVAL`.
let loc = loc
.try_into()
.map_err(|_| Error::from_raw_os_error(libc::EINVAL))?;
Ok(Self(loc))
}
}

View File

@@ -1,8 +1,8 @@
use crate::{
dir::{Dir, Entry, EntryExt, SeekLoc},
Result,
use crate::dir::{Dir, Entry, EntryExt, SeekLoc};
use std::{
io::{Error, Result},
ops::Deref,
};
use std::{io, ops::Deref};
#[derive(Copy, Clone, Debug)]
pub(crate) struct EntryImpl(libc::dirent64);
@@ -26,17 +26,17 @@ impl EntryExt for Entry {
}
pub(crate) fn iter_impl(dir: &Dir) -> Option<Result<EntryImpl>> {
let errno = io::Error::last_os_error();
let errno = Error::last_os_error();
let dirent = unsafe { libc::readdir64(dir.as_raw().as_ptr()) };
if dirent.is_null() {
let curr_errno = io::Error::last_os_error();
let curr_errno = Error::last_os_error();
if errno.raw_os_error() != curr_errno.raw_os_error() {
// TODO This should be verified on different BSD-flavours.
//
// According to 4.3BSD/POSIX.1-2001 man pages, there was an error
// if the errno value has changed at some point during the sequence
// of readdir calls.
Some(Err(curr_errno.into()))
Some(Err(curr_errno))
} else {
// Not an error. We've simply reached the end of the stream.
None

View File

@@ -1,4 +1,5 @@
use crate::{Error, Result};
use crate::from_success_code;
use std::io::Result;
use std::os::unix::prelude::*;
#[derive(Debug, Copy, Clone)]
@@ -18,5 +19,5 @@ pub unsafe fn posix_fadvise(
len: libc::off_t,
advice: PosixFadviseAdvice,
) -> Result<()> {
Error::from_success_code(libc::posix_fadvise(fd, offset, len, advice as libc::c_int))
from_success_code(libc::posix_fadvise(fd, offset, len, advice as libc::c_int))
}

View File

@@ -1,5 +1,7 @@
use crate::Result;
use std::{io, os::unix::prelude::*};
use std::{
io::{Error, Result},
os::unix::prelude::*,
};
pub unsafe fn isatty(fd: RawFd) -> Result<bool> {
let res = libc::isatty(fd);
@@ -8,20 +10,17 @@ pub unsafe fn isatty(fd: RawFd) -> Result<bool> {
Ok(true)
} else {
// ... otherwise 0 is returned, and errno is set to indicate the error.
let errno = io::Error::last_os_error();
if let Some(raw_errno) = errno.raw_os_error() {
// While POSIX specifies ENOTTY if the passed
// fd is *not* a tty, on Linux, some implementations
// may return EINVAL instead.
//
// https://linux.die.net/man/3/isatty
if raw_errno == libc::ENOTTY || raw_errno == libc::EINVAL {
Ok(false)
} else {
Err(errno.into())
}
let errno = Error::last_os_error();
let raw_errno = errno.raw_os_error().unwrap();
// While POSIX specifies ENOTTY if the passed
// fd is *not* a tty, on Linux, some implementations
// may return EINVAL instead.
//
// https://linux.die.net/man/3/isatty
if raw_errno == libc::ENOTTY || raw_errno == libc::EINVAL {
Ok(false)
} else {
Err(errno.into())
Err(errno)
}
}
}

View File

@@ -2,7 +2,8 @@ pub(crate) mod dir;
pub(crate) mod fadvise;
pub(crate) mod file;
use crate::{dir::SeekLoc, Result};
use crate::dir::SeekLoc;
use std::io::Result;
impl SeekLoc {
pub unsafe fn from_raw(loc: i64) -> Result<Self> {

View File

@@ -1,5 +1,6 @@
use crate::{dir::SeekLoc, Result};
use crate::dir::SeekLoc;
use cfg_if::cfg_if;
use std::io::Result;
cfg_if! {
if #[cfg(any(target_os = "linux",