Skip to content

Commit

Permalink
add support of HermitOS
Browse files Browse the repository at this point in the history
HermitOS is a library operating system. It it is partly compatible
to Unix. Consequently, the system interface to unix is revised
to support HermitOS.
  • Loading branch information
stlankes committed Feb 14, 2024
1 parent 08ee541 commit 98cd0d9
Show file tree
Hide file tree
Showing 16 changed files with 107 additions and 26 deletions.
4 changes: 4 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,9 @@ log = { version = "0.4.8", optional = true }
[target.'cfg(unix)'.dependencies]
libc = "0.2.149"

[target.'cfg(target_os = "hermit")'.dependencies]
hermit-abi = { version = "0.3.6" }

[target.'cfg(windows)'.dependencies.windows-sys]
version = "0.52"
features = [
Expand Down Expand Up @@ -87,6 +90,7 @@ targets = [
"x86_64-unknown-linux-gnu",
"x86_64-unknown-netbsd",
"x86_64-unknown-openbsd",
"x86_64-unknown-hermit",
]

[package.metadata.playground]
Expand Down
4 changes: 3 additions & 1 deletion src/io_source.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use std::ops::{Deref, DerefMut};
#[cfg(target_os = "hermit")]
use std::os::hermit::io::AsRawFd;
#[cfg(unix)]
use std::os::unix::io::AsRawFd;
#[cfg(target_os = "wasi")]
Expand Down Expand Up @@ -102,7 +104,7 @@ impl<T> DerefMut for IoSource<T> {
}
}

#[cfg(unix)]
#[cfg(any(unix, target_os = "hermit"))]
impl<T> event::Source for IoSource<T>
where
T: AsRawFd,
Expand Down
3 changes: 3 additions & 0 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,9 @@
//!
//! The available features are described in the [`features`] module.

#[cfg(target_os = "hermit")]
extern crate hermit_abi as libc;

// macros used internally
#[macro_use]
mod macros;
Expand Down
4 changes: 2 additions & 2 deletions src/macros.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,8 +51,8 @@ macro_rules! cfg_net {
macro_rules! cfg_io_source {
($($item:item)*) => {
$(
#[cfg(any(feature = "net", all(unix, feature = "os-ext")))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "net", all(unix, feature = "os-ext")))))]
#[cfg(any(feature = "net", all(any(unix, target_os = "hermit"), feature = "os-ext")))]
#[cfg_attr(docsrs, doc(cfg(any(feature = "net", all(any(unix, target_os = "hermit"), feature = "os-ext")))))]
$item
)*
}
Expand Down
12 changes: 7 additions & 5 deletions src/net/tcp/listener.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
use std::net::{self, SocketAddr};
#[cfg(target_os = "hermit")]
use std::os::hermit::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(target_os = "wasi")]
Expand All @@ -9,7 +11,7 @@ use std::{fmt, io};

use crate::io_source::IoSource;
use crate::net::TcpStream;
#[cfg(unix)]
#[cfg(any(unix, target_os = "hermit"))]
use crate::sys::tcp::set_reuseaddr;
#[cfg(not(target_os = "wasi"))]
use crate::sys::tcp::{bind, listen, new_for_addr};
Expand Down Expand Up @@ -58,7 +60,7 @@ impl TcpListener {
#[cfg(not(target_os = "wasi"))]
pub fn bind(addr: SocketAddr) -> io::Result<TcpListener> {
let socket = new_for_addr(addr)?;
#[cfg(unix)]
#[cfg(any(unix, target_os = "hermit"))]
let listener = unsafe { TcpListener::from_raw_fd(socket) };
#[cfg(windows)]
let listener = unsafe { TcpListener::from_raw_socket(socket as _) };
Expand Down Expand Up @@ -166,21 +168,21 @@ impl fmt::Debug for TcpListener {
}
}

#[cfg(unix)]
#[cfg(any(unix, target_os = "hermit"))]
impl IntoRawFd for TcpListener {
fn into_raw_fd(self) -> RawFd {
self.inner.into_inner().into_raw_fd()
}
}

#[cfg(unix)]
#[cfg(any(unix, target_os = "hermit"))]
impl AsRawFd for TcpListener {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}

#[cfg(unix)]
#[cfg(any(unix, target_os = "hermit"))]
impl FromRawFd for TcpListener {
/// Converts a `RawFd` to a `TcpListener`.
///
Expand Down
10 changes: 7 additions & 3 deletions src/net/tcp/stream.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::fmt;
use std::io::{self, IoSlice, IoSliceMut, Read, Write};
use std::net::{self, Shutdown, SocketAddr};
#[cfg(target_os = "hermit")]
use std::os::hermit::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(target_os = "wasi")]
Expand Down Expand Up @@ -88,6 +90,8 @@ impl TcpStream {
let socket = new_for_addr(addr)?;
#[cfg(unix)]
let stream = unsafe { TcpStream::from_raw_fd(socket) };
#[cfg(target_os = "hermit")]
let stream = unsafe { TcpStream::from_raw_fd(socket) };
#[cfg(windows)]
let stream = unsafe { TcpStream::from_raw_socket(socket as _) };
connect(&stream.inner, addr)?;
Expand Down Expand Up @@ -348,21 +352,21 @@ impl fmt::Debug for TcpStream {
}
}

#[cfg(unix)]
#[cfg(any(unix, target_os = "hermit"))]
impl IntoRawFd for TcpStream {
fn into_raw_fd(self) -> RawFd {
self.inner.into_inner().into_raw_fd()
}
}

#[cfg(unix)]
#[cfg(any(unix, target_os = "hermit"))]
impl AsRawFd for TcpStream {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}

#[cfg(unix)]
#[cfg(any(unix, target_os = "hermit"))]
impl FromRawFd for TcpStream {
/// Converts a `RawFd` to a `TcpStream`.
///
Expand Down
8 changes: 5 additions & 3 deletions src/net/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ use std::fmt;
use std::io;
use std::net;
use std::net::{Ipv4Addr, Ipv6Addr, SocketAddr};
#[cfg(target_os = "hermit")]
use std::os::hermit::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(unix)]
use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd, RawFd};
#[cfg(windows)]
Expand Down Expand Up @@ -642,21 +644,21 @@ impl fmt::Debug for UdpSocket {
}
}

#[cfg(unix)]
#[cfg(any(unix, target_os = "hermit"))]
impl IntoRawFd for UdpSocket {
fn into_raw_fd(self) -> RawFd {
self.inner.into_inner().into_raw_fd()
}
}

#[cfg(unix)]
#[cfg(any(unix, target_os = "hermit"))]
impl AsRawFd for UdpSocket {
fn as_raw_fd(&self) -> RawFd {
self.inner.as_raw_fd()
}
}

#[cfg(unix)]
#[cfg(any(unix, target_os = "hermit"))]
impl FromRawFd for UdpSocket {
/// Converts a `RawFd` to a `UdpSocket`.
///
Expand Down
6 changes: 6 additions & 0 deletions src/sys/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,12 @@ cfg_os_poll! {
pub(crate) use self::wasi::*;
}

#[cfg(target_os = "hermit")]
cfg_os_poll! {
mod unix;
pub(crate) use self::unix::*;
}

cfg_not_os_poll! {
mod shell;
pub(crate) use self::shell::*;
Expand Down
33 changes: 30 additions & 3 deletions src/sys/unix/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,31 @@
macro_rules! syscall {
($fn: ident ( $($arg: expr),* $(,)* ) ) => {{
let res = unsafe { libc::$fn($($arg, )*) };
#[cfg(target_os = "hermit")]
if res < 0 {
let e = match -res {
libc::errno::EACCES => std::io::ErrorKind::PermissionDenied,
libc::errno::EADDRINUSE => std::io::ErrorKind::AddrInUse,
libc::errno::EADDRNOTAVAIL => std::io::ErrorKind::AddrNotAvailable,
libc::errno::EAGAIN => std::io::ErrorKind::WouldBlock,
libc::errno::ECONNABORTED => std::io::ErrorKind::ConnectionAborted,
libc::errno::ECONNREFUSED => std::io::ErrorKind::ConnectionRefused,
libc::errno::ECONNRESET => std::io::ErrorKind::ConnectionReset,
libc::errno::EEXIST => std::io::ErrorKind::AlreadyExists,
libc::errno::EINTR => std::io::ErrorKind::Interrupted,
libc::errno::EINVAL => std::io::ErrorKind::InvalidInput,
libc::errno::ENOENT => std::io::ErrorKind::NotFound,
libc::errno::ENOTCONN => std::io::ErrorKind::NotConnected,
libc::errno::EPERM => std::io::ErrorKind::PermissionDenied,
libc::errno::EPIPE => std::io::ErrorKind::BrokenPipe,
libc::errno::ETIMEDOUT => std::io::ErrorKind::TimedOut,
_ => panic!("Unknown error {}", res),
};
Err(std::io::Error::from(e))
} else {
Ok(res)
}
#[cfg(unix)]
if res == -1 {
Err(std::io::Error::last_os_error())
} else {
Expand All @@ -29,13 +54,15 @@ cfg_os_poll! {

pub(crate) mod tcp;
pub(crate) mod udp;
#[cfg(not(target_os = "hermit"))]
pub(crate) mod uds;
#[cfg(not(target_os = "hermit"))]
pub use self::uds::SocketAddr;
}

cfg_io_source! {
// Both `kqueue` and `epoll` don't need to hold any user space state.
#[cfg(not(any(mio_unsupported_force_poll_poll, target_os = "solaris", target_os = "vita")))]
#[cfg(not(any(mio_unsupported_force_poll_poll, target_os = "hermit", target_os = "solaris", target_os = "vita")))]
mod stateless_io_source {
use std::io;
use std::os::unix::io::RawFd;
Expand Down Expand Up @@ -88,10 +115,10 @@ cfg_os_poll! {
}
}

#[cfg(not(any(mio_unsupported_force_poll_poll, target_os = "solaris",target_os = "vita")))]
#[cfg(not(any(mio_unsupported_force_poll_poll, target_os = "hermit", target_os = "solaris",target_os = "vita")))]
pub(crate) use self::stateless_io_source::IoSourceState;

#[cfg(any(mio_unsupported_force_poll_poll, target_os = "solaris", target_os = "vita"))]
#[cfg(any(mio_unsupported_force_poll_poll, target_os = "hermit", target_os = "solaris", target_os = "vita"))]
pub(crate) use self::selector::IoSourceState;
}

Expand Down
2 changes: 2 additions & 0 deletions src/sys/unix/net.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ pub(crate) fn new_socket(domain: libc::c_int, socket_type: libc::c_int) -> io::R
target_os = "netbsd",
target_os = "openbsd",
target_os = "solaris",
target_os = "hermit",
))]
let socket_type = socket_type | libc::SOCK_NONBLOCK | libc::SOCK_CLOEXEC;

Expand Down Expand Up @@ -115,6 +116,7 @@ pub(crate) fn socket_addr(addr: &SocketAddr) -> (SocketAddrCRepr, libc::socklen_
target_os = "watchos",
target_os = "espidf",
target_os = "vita",
target_os = "hermit",
))]
sin_len: 0,
#[cfg(target_os = "vita")]
Expand Down
8 changes: 5 additions & 3 deletions src/sys/unix/selector/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,19 +23,21 @@ pub(crate) use self::epoll::{event, Event, Events, Selector};
#[cfg(any(
mio_unsupported_force_poll_poll,
target_os = "solaris",
target_os = "vita"
target_os = "vita",
target_os = "hermit"
))]
mod poll;

#[cfg(any(
mio_unsupported_force_poll_poll,
target_os = "solaris",
target_os = "vita"
target_os = "vita",
target_os = "hermit"
))]
pub(crate) use self::poll::{event, Event, Events, Selector};

cfg_io_source! {
#[cfg(any(mio_unsupported_force_poll_poll, target_os = "solaris", target_os = "vita"))]
#[cfg(any(mio_unsupported_force_poll_poll, target_os = "hermit", target_os = "solaris", target_os = "vita"))]
pub(crate) use self::poll::IoSourceState;
}

Expand Down
3 changes: 3 additions & 0 deletions src/sys/unix/selector/poll.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@ use crate::sys::unix::waker::WakerInternal;
use crate::{Interest, Token};
use std::collections::HashMap;
use std::fmt::{Debug, Formatter};
#[cfg(target_os = "hermit")]
use std::os::hermit::io::{AsRawFd, RawFd};
#[cfg(not(target_os = "hermit"))]
use std::os::unix::io::{AsRawFd, RawFd};
use std::sync::atomic::AtomicBool;
use std::sync::atomic::{AtomicUsize, Ordering};
Expand Down
3 changes: 3 additions & 0 deletions src/sys/unix/sourcefd.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
use crate::{event, Interest, Registry, Token};

use std::io;
#[cfg(target_os = "hermit")]
use std::os::hermit::io::RawFd;
#[cfg(not(target_os = "hermit"))]
use std::os::unix::io::RawFd;

/// Adapter for [`RawFd`] providing an [`event::Source`] implementation.
Expand Down
5 changes: 5 additions & 0 deletions src/sys/unix/tcp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ use std::convert::TryInto;
use std::io;
use std::mem::{size_of, MaybeUninit};
use std::net::{self, SocketAddr};
#[cfg(target_os = "hermit")]
use std::os::hermit::io::{AsRawFd, FromRawFd};
#[cfg(not(target_os = "hermit"))]
use std::os::unix::io::{AsRawFd, FromRawFd};

use crate::sys::unix::net::{new_socket, socket_addr, to_socket_addr};
Expand Down Expand Up @@ -91,6 +94,7 @@ pub(crate) fn accept(listener: &net::TcpListener) -> io::Result<(net::TcpStream,
target_os = "watchos",
target_os = "espidf",
target_os = "vita",
target_os = "hermit",
all(target_arch = "x86", target_os = "android"),
))]
let stream = {
Expand All @@ -109,6 +113,7 @@ pub(crate) fn accept(listener: &net::TcpListener) -> io::Result<(net::TcpStream,
all(target_arch = "x86", target_os = "android"),
target_os = "espidf",
target_os = "vita",
target_os = "hermit",
))]
syscall!(fcntl(s.as_raw_fd(), libc::F_SETFL, libc::O_NONBLOCK))?;

Expand Down
3 changes: 3 additions & 0 deletions src/sys/unix/udp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ use crate::sys::unix::net::{new_ip_socket, socket_addr};
use std::io;
use std::mem;
use std::net::{self, SocketAddr};
#[cfg(target_os = "hermit")]
use std::os::hermit::io::{AsRawFd, FromRawFd};
#[cfg(not(target_os = "hermit"))]
use std::os::unix::io::{AsRawFd, FromRawFd};

pub fn bind(addr: SocketAddr) -> io::Result<net::UdpSocket> {
Expand Down
Loading

0 comments on commit 98cd0d9

Please sign in to comment.