You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

106 lines
2.3 KiB

//! `pipe()` related operations
use super::*;
use errno::Errno;
use std::{
fmt,
};
/// Represents an error on `pipe()` related operations
#[derive(Debug)]
pub enum Error {
Create,
Read,
Write,
Broken,
Unknown,
}
impl std::error::Error for Error{}
impl std::fmt::Display for Error
{
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result
{
match self {
Self::Create => write!(f, "failed to create pipe"),
Self::Read => write!(f, "failed to read from pipe"),
Self::Write => write!(f, "failed to write to pipe"),
Self::Broken => write!(f, "broken pipe"),
_ => write!(f, "unknown error"),
}
}
}
/// Create with `pipe()`
pub(super) fn unix_pipe() -> Result<(i32,i32), Errno<Error>>
{
use libc::{
pipe,
};
let mut pipe_fd: [libc::c_int; 2] = [0;2];
if unsafe{pipe(&mut pipe_fd[0] as *mut libc::c_int)} == 0{
Ok((pipe_fd[0], pipe_fd[1]))
} else {
Err(Error::Create.into())
}
}
/// Write to a pipe
pub(super) fn pipe_write(output: i32, buf: impl AsRef<[u8]>) -> Result<usize, Errno<Error>>
{
let buf = buf.as_ref();
let len = buf.len();
let read = unsafe{libc::write(output, &buf[0] as *const u8 as *const libc::c_void, len)};
if read < 0 {
Err(Error::Write.into())
} else {
Ok(read as usize)
}
}
pub(super) fn pipe_read(input: i32, mut buf: impl AsMut<[u8]>) -> Result<usize, Errno<Error>>
{
let buf = buf.as_mut();
let len = buf.len();
let read = unsafe{libc::read(input, &mut buf[0] as *mut u8 as *mut libc::c_void, len)};
if read < 0 {
Err(Error::Read.into())
} else {
Ok(read as usize)
}
}
pub(super) unsafe fn pipe_write_value<T: ?Sized>(fd: i32, value: &T) -> Result<(), Errno<Error>>
{
let sz = std::mem::size_of_val(value);
let write = pipe_write(fd, std::slice::from_raw_parts(value as *const T as *const u8, sz))?;
if write == sz {
Ok(())
} else {
Err(Error::Broken.into())
}
}
pub(super) unsafe fn pipe_read_value<T>(fd: i32) -> Result<T, Errno<Error>>
{
use malloc_array::heap;
let mut buf = heap![unsafe 0u8; std::mem::size_of::<T>()];
let read = pipe_read(fd, &mut buf)?;
if read == buf.len() {
let ptr = buf.reinterpret::<T>();
Ok(ptr.as_ptr().read())
} else {
Err(Error::Broken.into())
}
}