use alloc::string::String;
use alloc::vec;
use core::sync::atomic::{AtomicU64, Ordering};
use hyperlight_common::flatbuffer_wrappers::function_types::{ParameterValue, ReturnType};
use crate::host_comm::call_host_function;
use crate::libc::{
CLOCK_MONOTONIC, CLOCK_REALTIME, EBADF, EINVAL, EIO, ENOSYS, c_int, c_long, c_void, clockid_t,
errno, timespec,
};
fn set_errno(val: u32) {
unsafe { errno = val as _ };
}
static CURRENT_TIME: AtomicU64 = AtomicU64::new(0);
fn current_time() -> (u64, u64) {
let call_count = CURRENT_TIME.fetch_add(1, Ordering::Relaxed) + 1;
(call_count, 0)
}
#[unsafe(no_mangle)]
extern "C" fn read(fd: c_int, buf: *mut c_void, count: usize) -> isize {
if buf.is_null() && count > 0 {
set_errno(EINVAL);
return -1;
}
if fd != 0 {
set_errno(EBADF);
return -1;
}
0
}
#[unsafe(no_mangle)]
extern "C" fn write(fd: c_int, buf: *const c_void, count: usize) -> isize {
if buf.is_null() && count > 0 {
set_errno(EINVAL);
return -1;
}
if fd != 1 && fd != 2 {
set_errno(EBADF);
return -1;
}
let slice = unsafe { core::slice::from_raw_parts(buf as *const u8, count) };
let s = String::from_utf8_lossy(slice);
match call_host_function::<i32>(
"HostPrint",
Some(vec![ParameterValue::String(s.into_owned())]),
ReturnType::Int,
) {
Ok(_) => count as isize,
Err(_) => {
set_errno(EIO);
-1
}
}
}
#[unsafe(no_mangle)]
extern "C" fn clock_gettime(clk_id: clockid_t, tp: *mut timespec) -> c_int {
const CLOCK_ID_REALTIME: clockid_t = CLOCK_REALTIME as _;
const CLOCK_ID_MONOTONIC: clockid_t = CLOCK_MONOTONIC as _;
if tp.is_null() {
set_errno(EINVAL);
return -1;
}
match clk_id {
CLOCK_ID_REALTIME | CLOCK_ID_MONOTONIC => {
let (secs, nanos) = current_time();
unsafe {
(*tp).tv_sec = secs as c_long;
(*tp).tv_nsec = nanos as c_long;
}
0
}
_ => {
set_errno(EINVAL);
-1
}
}
}
#[unsafe(no_mangle)]
extern "C" fn _exit(ec: c_int) -> ! {
hyperlight_guest::exit::abort_with_code(&[ec as u8]);
}
#[unsafe(no_mangle)]
extern "C" fn lseek(_fd: c_int, _offset: c_long, _whence: c_int) -> c_long {
set_errno(ENOSYS);
-1
}
#[unsafe(no_mangle)]
extern "C" fn close(_fd: c_int) -> c_int {
0
}