Files
yggdrasil/lib/runtime/src/io/mod.rs
T

122 lines
3.4 KiB
Rust

#![allow(missing_docs)]
pub mod poll {
pub use abi::io::PollControl;
}
pub use abi::io::{
options, AccessMode, DirectoryEntry, FileAttr, FileMetadataUpdate, FileMetadataUpdateMode,
FileMode, FileSync, FileTimesUpdate, FileType, OpenOptions, RawFd, RemoveFlags, Rename,
SeekFrom, TimerOptions,
};
pub use abi::option::OptionSizeHint;
pub mod device;
pub mod filesystem;
pub mod input;
pub mod paths;
pub mod terminal;
pub use paths::*;
use core::mem::MaybeUninit;
use abi::{error::Error, option::OptionValue, process::ProcessId};
pub fn read_pid_fd(fd: RawFd) -> Result<(ProcessId, i32), Error> {
let mut buffer = [0; size_of::<u32>() + size_of::<i32>()];
let len = unsafe { crate::sys::read(fd, &mut buffer) }?;
assert_eq!(len, buffer.len());
let mut word = [0; size_of::<u32>()];
word.copy_from_slice(&buffer[0..4]);
let pid = unsafe { ProcessId::from_raw(u32::from_ne_bytes(word)) };
word.copy_from_slice(&buffer[4..8]);
let status = i32::from_ne_bytes(word);
Ok((pid, status))
}
pub fn remove_file(at: Option<RawFd>, path: &str) -> Result<(), Error> {
unsafe { crate::sys::remove(at, path, RemoveFlags::empty()) }
}
pub fn remove_directory(at: Option<RawFd>, path: &str) -> Result<(), Error> {
unsafe { crate::sys::remove(at, path, RemoveFlags::DIRECTORY_ONLY) }
}
pub fn remove_directory_recursive(_at: Option<RawFd>, _path: &str) -> Result<(), Error> {
todo!()
}
fn configure_pipe(
read: RawFd,
write: RawFd,
read_nonblocking: bool,
write_nonblocking: bool,
) -> Result<(), Error> {
if read_nonblocking {
set_file_option::<options::NonBlocking>(read, &true)?;
}
if write_nonblocking {
set_file_option::<options::NonBlocking>(write, &true)?;
}
Ok(())
}
pub fn create_pipe_pair(
read_nonblocking: bool,
write_nonblocking: bool,
) -> Result<(RawFd, RawFd), Error> {
let mut fds = [MaybeUninit::uninit(); 2];
unsafe { crate::sys::create_pipe(&mut fds) }?;
let fds = unsafe { MaybeUninit::array_assume_init(fds) };
let read = fds[0];
let write = fds[1];
match configure_pipe(read, write, read_nonblocking, write_nonblocking) {
Ok(()) => Ok((read, write)),
Err(error) => {
unsafe {
crate::sys::close(read).ok();
crate::sys::close(write).ok();
}
Err(error)
}
}
}
pub macro get_file_option($fd:expr, $variant_ty:ty) {{
let mut buffer = [0; <$variant_ty as $crate::io::OptionSizeHint>::SIZE_HINT];
$crate::io::get_file_option::<$variant_ty>($fd, &mut buffer)
}}
pub fn get_file_option<'de, T: OptionValue<'de>>(
fd: RawFd,
buffer: &'de mut [u8],
) -> Result<T::Value, Error> {
let len = unsafe { crate::sys::get_file_option(fd, T::VARIANT.into(), buffer) }?;
T::load(&buffer[..len])
}
pub fn set_file_option<'de, T: OptionValue<'de> + OptionSizeHint>(
fd: RawFd,
value: &T::Value,
) -> Result<(), Error>
where
[u8; T::SIZE_HINT]: Sized,
{
let mut buffer = [0; T::SIZE_HINT];
set_file_option_with::<T>(fd, &mut buffer, value)
}
pub fn set_file_option_with<'de, T: OptionValue<'de>>(
fd: RawFd,
buffer: &mut [u8],
value: &T::Value,
) -> Result<(), Error> {
let len = T::store(value, buffer)?;
unsafe { crate::sys::set_file_option(fd, T::VARIANT.into(), &buffer[..len]) }
}
pub fn set_nonblocking(fd: RawFd, nonblocking: bool) -> Result<(), Error> {
set_file_option::<options::NonBlocking>(fd, &nonblocking)
}