wasi-common error cleanup: part 1, yanix (#1226)
* Reuse std::io::Error for raw *nix errno This commit removes custom `yanix::Errno` and instead (as was previously suggested) reuses `std::io::Error` to generate and wrap raw *nix errno value. * Update wasi-common to use new Yanix error type This commit updates `wasi-common` to use new way of handling raw OS error in `yanix`; i.e., via re-use of `std::io::Error` instead of a custom `Errno` enum. * Fix formatting * Unwrap if io::Error created from raw OS error This commit calls `unwrap` on `err` if that one was created via `io::Error::last_os_error()`. It also refactors error matching in several syscalls on the BSD platform (mainly).
This commit is contained in:
@@ -101,9 +101,6 @@ pub enum Error {
|
||||
Wasi(#[from] WasiError),
|
||||
#[error("IO error: {0}")]
|
||||
Io(#[from] std::io::Error),
|
||||
#[cfg(unix)]
|
||||
#[error("Yanix error: {0}")]
|
||||
Yanix(#[from] yanix::YanixError),
|
||||
}
|
||||
|
||||
impl From<TryFromIntError> for Error {
|
||||
@@ -150,16 +147,6 @@ impl Error {
|
||||
};
|
||||
err.as_wasi_error()
|
||||
}
|
||||
#[cfg(unix)]
|
||||
Self::Yanix(err) => {
|
||||
use yanix::YanixError::*;
|
||||
let err: Self = match err {
|
||||
Errno(errno) => (*errno).into(),
|
||||
NulError(err) => err.into(),
|
||||
TryFromIntError(err) => (*err).into(),
|
||||
};
|
||||
err.as_wasi_error()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,142 +1,139 @@
|
||||
use crate::old::snapshot_0::hostcalls_impl::PathGet;
|
||||
use crate::old::snapshot_0::{Error, Result};
|
||||
use std::os::unix::prelude::AsRawFd;
|
||||
use std::{io, os::unix::prelude::AsRawFd};
|
||||
|
||||
pub(crate) fn path_unlink_file(resolved: PathGet) -> Result<()> {
|
||||
use yanix::{
|
||||
file::{unlinkat, AtFlag},
|
||||
Errno, YanixError,
|
||||
};
|
||||
unsafe {
|
||||
use yanix::file::{unlinkat, AtFlag};
|
||||
match unsafe {
|
||||
unlinkat(
|
||||
resolved.dirfd().as_raw_fd(),
|
||||
resolved.path(),
|
||||
AtFlag::empty(),
|
||||
)
|
||||
}
|
||||
.map_err(|err| {
|
||||
if let YanixError::Errno(mut errno) = err {
|
||||
// Non-Linux implementations may return EPERM when attempting to remove a
|
||||
// directory without REMOVEDIR. While that's what POSIX specifies, it's
|
||||
// less useful. Adjust this to EISDIR. It doesn't matter that this is not
|
||||
// atomic with the unlinkat, because if the file is removed and a directory
|
||||
// is created before fstatat sees it, we're racing with that change anyway
|
||||
// and unlinkat could have legitimately seen the directory if the race had
|
||||
// turned out differently.
|
||||
use yanix::file::{fstatat, FileType};
|
||||
} {
|
||||
Err(err) => {
|
||||
if let yanix::Error::Io(ref errno) = err {
|
||||
let raw_errno = errno.raw_os_error().unwrap();
|
||||
// Non-Linux implementations may return EPERM when attempting to remove a
|
||||
// directory without REMOVEDIR. While that's what POSIX specifies, it's
|
||||
// less useful. Adjust this to EISDIR. It doesn't matter that this is not
|
||||
// atomic with the unlinkat, because if the file is removed and a directory
|
||||
// is created before fstatat sees it, we're racing with that change anyway
|
||||
// and unlinkat could have legitimately seen the directory if the race had
|
||||
// turned out differently.
|
||||
use yanix::file::{fstatat, FileType};
|
||||
|
||||
if errno == Errno::EPERM {
|
||||
if let Ok(stat) = unsafe {
|
||||
fstatat(
|
||||
resolved.dirfd().as_raw_fd(),
|
||||
resolved.path(),
|
||||
AtFlag::SYMLINK_NOFOLLOW,
|
||||
)
|
||||
} {
|
||||
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Directory {
|
||||
errno = Errno::EISDIR;
|
||||
if raw_errno == libc::EPERM {
|
||||
match unsafe {
|
||||
fstatat(
|
||||
resolved.dirfd().as_raw_fd(),
|
||||
resolved.path(),
|
||||
AtFlag::SYMLINK_NOFOLLOW,
|
||||
)
|
||||
} {
|
||||
Ok(stat) => {
|
||||
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Directory {
|
||||
return Err(io::Error::from_raw_os_error(libc::EISDIR).into());
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::debug!("path_unlink_file fstatat error: {:?}", err);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
errno = Errno::last();
|
||||
}
|
||||
}
|
||||
errno.into()
|
||||
} else {
|
||||
err
|
||||
|
||||
Err(err.into())
|
||||
}
|
||||
})
|
||||
.map_err(Into::into)
|
||||
Ok(()) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn path_symlink(old_path: &str, resolved: PathGet) -> Result<()> {
|
||||
use yanix::{
|
||||
file::{fstatat, symlinkat, AtFlag},
|
||||
Errno, YanixError,
|
||||
};
|
||||
use yanix::file::{fstatat, symlinkat, AtFlag};
|
||||
|
||||
log::debug!("path_symlink old_path = {:?}", old_path);
|
||||
log::debug!("path_symlink resolved = {:?}", resolved);
|
||||
|
||||
unsafe { symlinkat(old_path, resolved.dirfd().as_raw_fd(), resolved.path()) }.or_else(|err| {
|
||||
if let YanixError::Errno(errno) = err {
|
||||
match errno {
|
||||
Errno::ENOTDIR => {
|
||||
match unsafe { symlinkat(old_path, resolved.dirfd().as_raw_fd(), resolved.path()) } {
|
||||
Err(err) => {
|
||||
if let yanix::Error::Io(ref errno) = err {
|
||||
if errno.raw_os_error().unwrap() == libc::ENOTDIR {
|
||||
// On BSD, symlinkat returns ENOTDIR when it should in fact
|
||||
// return a EEXIST. It seems that it gets confused with by
|
||||
// the trailing slash in the target path. Thus, we strip
|
||||
// the trailing slash and check if the path exists, and
|
||||
// adjust the error code appropriately.
|
||||
let new_path = resolved.path().trim_end_matches('/');
|
||||
if let Ok(_) = unsafe {
|
||||
match unsafe {
|
||||
fstatat(
|
||||
resolved.dirfd().as_raw_fd(),
|
||||
new_path,
|
||||
AtFlag::SYMLINK_NOFOLLOW,
|
||||
)
|
||||
} {
|
||||
Err(Error::EEXIST)
|
||||
} else {
|
||||
Err(Error::ENOTDIR)
|
||||
Ok(_) => return Err(Error::EEXIST),
|
||||
Err(err) => {
|
||||
log::debug!("path_symlink fstatat error: {:?}", err);
|
||||
}
|
||||
}
|
||||
}
|
||||
x => Err(x.into()),
|
||||
}
|
||||
} else {
|
||||
Err(err.into())
|
||||
}
|
||||
})
|
||||
Ok(()) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn path_rename(resolved_old: PathGet, resolved_new: PathGet) -> Result<()> {
|
||||
use yanix::{
|
||||
file::{fstatat, renameat, AtFlag},
|
||||
Errno, YanixError,
|
||||
};
|
||||
unsafe {
|
||||
use yanix::file::{fstatat, renameat, AtFlag};
|
||||
match unsafe {
|
||||
renameat(
|
||||
resolved_old.dirfd().as_raw_fd(),
|
||||
resolved_old.path(),
|
||||
resolved_new.dirfd().as_raw_fd(),
|
||||
resolved_new.path(),
|
||||
)
|
||||
}
|
||||
.or_else(|err| {
|
||||
// Currently, this is verified to be correct on macOS, where
|
||||
// ENOENT can be returned in case when we try to rename a file
|
||||
// into a name with a trailing slash. On macOS, if the latter does
|
||||
// not exist, an ENOENT is thrown, whereas on Linux we observe the
|
||||
// correct behaviour of throwing an ENOTDIR since the destination is
|
||||
// indeed not a directory.
|
||||
//
|
||||
// TODO
|
||||
// Verify on other BSD-based OSes.
|
||||
if let YanixError::Errno(errno) = err {
|
||||
match errno {
|
||||
Errno::ENOENT => {
|
||||
} {
|
||||
Err(err) => {
|
||||
// Currently, this is verified to be correct on macOS, where
|
||||
// ENOENT can be returned in case when we try to rename a file
|
||||
// into a name with a trailing slash. On macOS, if the latter does
|
||||
// not exist, an ENOENT is thrown, whereas on Linux we observe the
|
||||
// correct behaviour of throwing an ENOTDIR since the destination is
|
||||
// indeed not a directory.
|
||||
//
|
||||
// TODO
|
||||
// Verify on other BSD-based OSes.
|
||||
if let yanix::Error::Io(ref errno) = err {
|
||||
if errno.raw_os_error().unwrap() == libc::ENOENT {
|
||||
// check if the source path exists
|
||||
if let Ok(_) = unsafe {
|
||||
match unsafe {
|
||||
fstatat(
|
||||
resolved_old.dirfd().as_raw_fd(),
|
||||
resolved_old.path(),
|
||||
AtFlag::SYMLINK_NOFOLLOW,
|
||||
)
|
||||
} {
|
||||
// check if destination contains a trailing slash
|
||||
if resolved_new.path().contains('/') {
|
||||
Err(Error::ENOTDIR)
|
||||
} else {
|
||||
Err(Error::ENOENT)
|
||||
Ok(_) => {
|
||||
// check if destination contains a trailing slash
|
||||
if resolved_new.path().contains('/') {
|
||||
return Err(Error::ENOTDIR);
|
||||
} else {
|
||||
return Err(Error::ENOENT);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::debug!("path_rename fstatat error: {:?}", err);
|
||||
}
|
||||
} else {
|
||||
Err(Error::ENOENT)
|
||||
}
|
||||
}
|
||||
x => Err(x.into()),
|
||||
}
|
||||
} else {
|
||||
|
||||
Err(err.into())
|
||||
}
|
||||
})
|
||||
Ok(()) => Ok(()),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) mod fd_readdir_impl {
|
||||
|
||||
@@ -8,93 +8,102 @@ use crate::old::snapshot_0::{
|
||||
};
|
||||
use std::ffi::OsStr;
|
||||
use std::os::unix::prelude::OsStrExt;
|
||||
use yanix::{file::OFlag, Errno};
|
||||
use yanix::file::OFlag;
|
||||
|
||||
pub(crate) use sys_impl::host_impl::*;
|
||||
|
||||
impl FromRawOsError for Error {
|
||||
fn from_raw_os_error(code: i32) -> Self {
|
||||
Self::from(Errno::from_i32(code))
|
||||
impl From<yanix::Error> for Error {
|
||||
fn from(err: yanix::Error) -> Self {
|
||||
use yanix::Error::*;
|
||||
match err {
|
||||
Io(err) => err.into(),
|
||||
Nul(err) => err.into(),
|
||||
IntConversion(err) => err.into(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Errno> for Error {
|
||||
fn from(errno: Errno) -> Self {
|
||||
match errno {
|
||||
Errno::EPERM => Self::EPERM,
|
||||
Errno::ENOENT => Self::ENOENT,
|
||||
Errno::ESRCH => Self::ESRCH,
|
||||
Errno::EINTR => Self::EINTR,
|
||||
Errno::EIO => Self::EIO,
|
||||
Errno::ENXIO => Self::ENXIO,
|
||||
Errno::E2BIG => Self::E2BIG,
|
||||
Errno::ENOEXEC => Self::ENOEXEC,
|
||||
Errno::EBADF => Self::EBADF,
|
||||
Errno::ECHILD => Self::ECHILD,
|
||||
Errno::EAGAIN => Self::EAGAIN,
|
||||
Errno::ENOMEM => Self::ENOMEM,
|
||||
Errno::EACCES => Self::EACCES,
|
||||
Errno::EFAULT => Self::EFAULT,
|
||||
Errno::EBUSY => Self::EBUSY,
|
||||
Errno::EEXIST => Self::EEXIST,
|
||||
Errno::EXDEV => Self::EXDEV,
|
||||
Errno::ENODEV => Self::ENODEV,
|
||||
Errno::ENOTDIR => Self::ENOTDIR,
|
||||
Errno::EISDIR => Self::EISDIR,
|
||||
Errno::EINVAL => Self::EINVAL,
|
||||
Errno::ENFILE => Self::ENFILE,
|
||||
Errno::EMFILE => Self::EMFILE,
|
||||
Errno::ENOTTY => Self::ENOTTY,
|
||||
Errno::ETXTBSY => Self::ETXTBSY,
|
||||
Errno::EFBIG => Self::EFBIG,
|
||||
Errno::ENOSPC => Self::ENOSPC,
|
||||
Errno::ESPIPE => Self::ESPIPE,
|
||||
Errno::EROFS => Self::EROFS,
|
||||
Errno::EMLINK => Self::EMLINK,
|
||||
Errno::EPIPE => Self::EPIPE,
|
||||
Errno::EDOM => Self::EDOM,
|
||||
Errno::ERANGE => Self::ERANGE,
|
||||
Errno::EDEADLK => Self::EDEADLK,
|
||||
Errno::ENAMETOOLONG => Self::ENAMETOOLONG,
|
||||
Errno::ENOLCK => Self::ENOLCK,
|
||||
Errno::ENOSYS => Self::ENOSYS,
|
||||
Errno::ENOTEMPTY => Self::ENOTEMPTY,
|
||||
Errno::ELOOP => Self::ELOOP,
|
||||
Errno::ENOMSG => Self::ENOMSG,
|
||||
Errno::EIDRM => Self::EIDRM,
|
||||
Errno::ENOLINK => Self::ENOLINK,
|
||||
Errno::EPROTO => Self::EPROTO,
|
||||
Errno::EMULTIHOP => Self::EMULTIHOP,
|
||||
Errno::EBADMSG => Self::EBADMSG,
|
||||
Errno::EOVERFLOW => Self::EOVERFLOW,
|
||||
Errno::EILSEQ => Self::EILSEQ,
|
||||
Errno::ENOTSOCK => Self::ENOTSOCK,
|
||||
Errno::EDESTADDRREQ => Self::EDESTADDRREQ,
|
||||
Errno::EMSGSIZE => Self::EMSGSIZE,
|
||||
Errno::EPROTOTYPE => Self::EPROTOTYPE,
|
||||
Errno::ENOPROTOOPT => Self::ENOPROTOOPT,
|
||||
Errno::EPROTONOSUPPORT => Self::EPROTONOSUPPORT,
|
||||
Errno::EAFNOSUPPORT => Self::EAFNOSUPPORT,
|
||||
Errno::EADDRINUSE => Self::EADDRINUSE,
|
||||
Errno::EADDRNOTAVAIL => Self::EADDRNOTAVAIL,
|
||||
Errno::ENETDOWN => Self::ENETDOWN,
|
||||
Errno::ENETUNREACH => Self::ENETUNREACH,
|
||||
Errno::ENETRESET => Self::ENETRESET,
|
||||
Errno::ECONNABORTED => Self::ECONNABORTED,
|
||||
Errno::ECONNRESET => Self::ECONNRESET,
|
||||
Errno::ENOBUFS => Self::ENOBUFS,
|
||||
Errno::EISCONN => Self::EISCONN,
|
||||
Errno::ENOTCONN => Self::ENOTCONN,
|
||||
Errno::ETIMEDOUT => Self::ETIMEDOUT,
|
||||
Errno::ECONNREFUSED => Self::ECONNREFUSED,
|
||||
Errno::EHOSTUNREACH => Self::EHOSTUNREACH,
|
||||
Errno::EALREADY => Self::EALREADY,
|
||||
Errno::EINPROGRESS => Self::EINPROGRESS,
|
||||
Errno::ESTALE => Self::ESTALE,
|
||||
Errno::EDQUOT => Self::EDQUOT,
|
||||
Errno::ECANCELED => Self::ECANCELED,
|
||||
Errno::EOWNERDEAD => Self::EOWNERDEAD,
|
||||
Errno::ENOTRECOVERABLE => Self::ENOTRECOVERABLE,
|
||||
impl FromRawOsError for Error {
|
||||
fn from_raw_os_error(code: i32) -> Self {
|
||||
match code {
|
||||
libc::EPERM => Self::EPERM,
|
||||
libc::ENOENT => Self::ENOENT,
|
||||
libc::ESRCH => Self::ESRCH,
|
||||
libc::EINTR => Self::EINTR,
|
||||
libc::EIO => Self::EIO,
|
||||
libc::ENXIO => Self::ENXIO,
|
||||
libc::E2BIG => Self::E2BIG,
|
||||
libc::ENOEXEC => Self::ENOEXEC,
|
||||
libc::EBADF => Self::EBADF,
|
||||
libc::ECHILD => Self::ECHILD,
|
||||
libc::EAGAIN => Self::EAGAIN,
|
||||
libc::ENOMEM => Self::ENOMEM,
|
||||
libc::EACCES => Self::EACCES,
|
||||
libc::EFAULT => Self::EFAULT,
|
||||
libc::EBUSY => Self::EBUSY,
|
||||
libc::EEXIST => Self::EEXIST,
|
||||
libc::EXDEV => Self::EXDEV,
|
||||
libc::ENODEV => Self::ENODEV,
|
||||
libc::ENOTDIR => Self::ENOTDIR,
|
||||
libc::EISDIR => Self::EISDIR,
|
||||
libc::EINVAL => Self::EINVAL,
|
||||
libc::ENFILE => Self::ENFILE,
|
||||
libc::EMFILE => Self::EMFILE,
|
||||
libc::ENOTTY => Self::ENOTTY,
|
||||
libc::ETXTBSY => Self::ETXTBSY,
|
||||
libc::EFBIG => Self::EFBIG,
|
||||
libc::ENOSPC => Self::ENOSPC,
|
||||
libc::ESPIPE => Self::ESPIPE,
|
||||
libc::EROFS => Self::EROFS,
|
||||
libc::EMLINK => Self::EMLINK,
|
||||
libc::EPIPE => Self::EPIPE,
|
||||
libc::EDOM => Self::EDOM,
|
||||
libc::ERANGE => Self::ERANGE,
|
||||
libc::EDEADLK => Self::EDEADLK,
|
||||
libc::ENAMETOOLONG => Self::ENAMETOOLONG,
|
||||
libc::ENOLCK => Self::ENOLCK,
|
||||
libc::ENOSYS => Self::ENOSYS,
|
||||
libc::ENOTEMPTY => Self::ENOTEMPTY,
|
||||
libc::ELOOP => Self::ELOOP,
|
||||
libc::ENOMSG => Self::ENOMSG,
|
||||
libc::EIDRM => Self::EIDRM,
|
||||
libc::ENOLINK => Self::ENOLINK,
|
||||
libc::EPROTO => Self::EPROTO,
|
||||
libc::EMULTIHOP => Self::EMULTIHOP,
|
||||
libc::EBADMSG => Self::EBADMSG,
|
||||
libc::EOVERFLOW => Self::EOVERFLOW,
|
||||
libc::EILSEQ => Self::EILSEQ,
|
||||
libc::ENOTSOCK => Self::ENOTSOCK,
|
||||
libc::EDESTADDRREQ => Self::EDESTADDRREQ,
|
||||
libc::EMSGSIZE => Self::EMSGSIZE,
|
||||
libc::EPROTOTYPE => Self::EPROTOTYPE,
|
||||
libc::ENOPROTOOPT => Self::ENOPROTOOPT,
|
||||
libc::EPROTONOSUPPORT => Self::EPROTONOSUPPORT,
|
||||
libc::EAFNOSUPPORT => Self::EAFNOSUPPORT,
|
||||
libc::EADDRINUSE => Self::EADDRINUSE,
|
||||
libc::EADDRNOTAVAIL => Self::EADDRNOTAVAIL,
|
||||
libc::ENETDOWN => Self::ENETDOWN,
|
||||
libc::ENETUNREACH => Self::ENETUNREACH,
|
||||
libc::ENETRESET => Self::ENETRESET,
|
||||
libc::ECONNABORTED => Self::ECONNABORTED,
|
||||
libc::ECONNRESET => Self::ECONNRESET,
|
||||
libc::ENOBUFS => Self::ENOBUFS,
|
||||
libc::EISCONN => Self::EISCONN,
|
||||
libc::ENOTCONN => Self::ENOTCONN,
|
||||
libc::ETIMEDOUT => Self::ETIMEDOUT,
|
||||
libc::ECONNREFUSED => Self::ECONNREFUSED,
|
||||
libc::EHOSTUNREACH => Self::EHOSTUNREACH,
|
||||
libc::EALREADY => Self::EALREADY,
|
||||
libc::EINPROGRESS => Self::EINPROGRESS,
|
||||
libc::ESTALE => Self::ESTALE,
|
||||
libc::EDQUOT => Self::EDQUOT,
|
||||
libc::ECANCELED => Self::ECANCELED,
|
||||
libc::EOWNERDEAD => Self::EOWNERDEAD,
|
||||
libc::ENOTRECOVERABLE => Self::ENOTRECOVERABLE,
|
||||
x => {
|
||||
log::debug!("Unknown errno value: {}", x);
|
||||
Self::EIO
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -88,10 +88,7 @@ pub(crate) fn path_open(
|
||||
oflags: wasi::__wasi_oflags_t,
|
||||
fs_flags: wasi::__wasi_fdflags_t,
|
||||
) -> Result<File> {
|
||||
use yanix::{
|
||||
file::{fstatat, openat, AtFlag, FileType, Mode, OFlag},
|
||||
Errno,
|
||||
};
|
||||
use yanix::file::{fstatat, openat, AtFlag, FileType, Mode, OFlag};
|
||||
|
||||
let mut nix_all_oflags = if read && write {
|
||||
OFlag::RDWR
|
||||
@@ -127,54 +124,59 @@ pub(crate) fn path_open(
|
||||
} {
|
||||
Ok(fd) => fd,
|
||||
Err(e) => {
|
||||
if let yanix::YanixError::Errno(errno) = e {
|
||||
match errno {
|
||||
if let yanix::Error::Io(ref err) = e {
|
||||
match err.raw_os_error().unwrap() {
|
||||
// Linux returns ENXIO instead of EOPNOTSUPP when opening a socket
|
||||
Errno::ENXIO => {
|
||||
if let Ok(stat) = unsafe {
|
||||
libc::ENXIO => {
|
||||
match unsafe {
|
||||
fstatat(
|
||||
resolved.dirfd().as_raw_fd(),
|
||||
resolved.path(),
|
||||
AtFlag::SYMLINK_NOFOLLOW,
|
||||
)
|
||||
} {
|
||||
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Socket {
|
||||
return Err(Error::ENOTSUP);
|
||||
} else {
|
||||
return Err(Error::ENXIO);
|
||||
Ok(stat) => {
|
||||
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Socket {
|
||||
return Err(Error::ENOTSUP);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::debug!("path_open fstatat error: {:?}", err);
|
||||
}
|
||||
} else {
|
||||
return Err(Error::ENXIO);
|
||||
}
|
||||
}
|
||||
// Linux returns ENOTDIR instead of ELOOP when using O_NOFOLLOW|O_DIRECTORY
|
||||
// on a symlink.
|
||||
Errno::ENOTDIR
|
||||
libc::ENOTDIR
|
||||
if !(nix_all_oflags & (OFlag::NOFOLLOW | OFlag::DIRECTORY)).is_empty() =>
|
||||
{
|
||||
if let Ok(stat) = unsafe {
|
||||
match unsafe {
|
||||
fstatat(
|
||||
resolved.dirfd().as_raw_fd(),
|
||||
resolved.path(),
|
||||
AtFlag::SYMLINK_NOFOLLOW,
|
||||
)
|
||||
} {
|
||||
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Symlink {
|
||||
return Err(Error::ELOOP);
|
||||
Ok(stat) => {
|
||||
if FileType::from_stat_st_mode(stat.st_mode) == FileType::Symlink {
|
||||
return Err(Error::ELOOP);
|
||||
}
|
||||
}
|
||||
Err(err) => {
|
||||
log::debug!("path_open fstatat error: {:?}", err);
|
||||
}
|
||||
}
|
||||
return Err(Error::ENOTDIR);
|
||||
}
|
||||
// FreeBSD returns EMLINK instead of ELOOP when using O_NOFOLLOW on
|
||||
// a symlink.
|
||||
Errno::EMLINK if !(nix_all_oflags & OFlag::NOFOLLOW).is_empty() => {
|
||||
libc::EMLINK if !(nix_all_oflags & OFlag::NOFOLLOW).is_empty() => {
|
||||
return Err(Error::ELOOP);
|
||||
}
|
||||
errno => return Err(errno.into()),
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
return Err(e.into());
|
||||
}
|
||||
|
||||
return Err(e.into());
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#![allow(unused_unsafe)]
|
||||
use crate::old::snapshot_0::hostcalls_impl::{ClockEventData, FdEventData};
|
||||
use crate::old::snapshot_0::{wasi, Error, Result};
|
||||
use std::io;
|
||||
use yanix::clock::{clock_getres, clock_gettime, ClockId};
|
||||
|
||||
fn wasi_clock_id_to_unix(clock_id: wasi::__wasi_clockid_t) -> Result<ClockId> {
|
||||
@@ -54,10 +55,7 @@ pub(crate) fn poll_oneoff(
|
||||
events: &mut Vec<wasi::__wasi_event_t>,
|
||||
) -> Result<()> {
|
||||
use std::{convert::TryInto, os::unix::prelude::AsRawFd};
|
||||
use yanix::{
|
||||
poll::{poll, PollFd, PollFlags},
|
||||
Errno,
|
||||
};
|
||||
use yanix::poll::{poll, PollFd, PollFlags};
|
||||
|
||||
if fd_events.is_empty() && timeout.is_none() {
|
||||
return Ok(());
|
||||
@@ -88,10 +86,11 @@ pub(crate) fn poll_oneoff(
|
||||
let ready = loop {
|
||||
match poll(&mut poll_fds, poll_timeout) {
|
||||
Err(_) => {
|
||||
if Errno::last() == Errno::EINTR {
|
||||
let last_err = io::Error::last_os_error();
|
||||
if last_err.raw_os_error().unwrap() == libc::EINTR {
|
||||
continue;
|
||||
}
|
||||
return Err(Errno::last().into());
|
||||
return Err(last_err.into());
|
||||
}
|
||||
Ok(ready) => break ready,
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user