use crate::error::{VZError, VZResult};
use crate::shim_ffi;
use std::ffi::c_void;
use std::os::unix::io::RawFd;
pub struct SerialPortConfiguration {
inner: *mut c_void,
fds: Option<(RawFd, RawFd)>,
}
unsafe impl Send for SerialPortConfiguration {}
impl SerialPortConfiguration {
pub fn virtio_console() -> VZResult<Self> {
let mut input_pipe: [libc::c_int; 2] = [0, 0];
let mut output_pipe: [libc::c_int; 2] = [0, 0];
unsafe {
if libc::pipe(input_pipe.as_mut_ptr()) != 0 {
return Err(VZError::OperationFailed(
"Failed to create input pipe".to_string(),
));
}
if libc::pipe(output_pipe.as_mut_ptr()) != 0 {
libc::close(input_pipe[0]);
libc::close(input_pipe[1]);
return Err(VZError::OperationFailed(
"Failed to create output pipe".to_string(),
));
}
}
let obj = unsafe { shim_ffi::abx_serial_console_new(input_pipe[0], output_pipe[1]) };
Ok(Self {
inner: obj,
fds: Some((output_pipe[0], input_pipe[1])),
})
}
#[must_use]
pub fn read_fd(&self) -> Option<RawFd> {
self.fds.map(|(r, _)| r)
}
#[must_use]
pub fn write_fd(&self) -> Option<RawFd> {
self.fds.map(|(_, w)| w)
}
#[must_use]
pub(crate) fn into_ptr(self) -> *mut c_void {
let ptr = self.inner;
std::mem::forget(self);
ptr
}
}
impl Drop for SerialPortConfiguration {
fn drop(&mut self) {
if !self.inner.is_null() {
unsafe { shim_ffi::abx_object_release(self.inner.cast()) };
}
}
}