195 lines
4.6 KiB
Rust
195 lines
4.6 KiB
Rust
use alloc::{ffi::CString, vec::Vec};
|
|
use core::ptr;
|
|
|
|
use crate::{
|
|
header::errno::EBADF,
|
|
platform::types::{c_char, c_int, mode_t, size_t},
|
|
};
|
|
|
|
const OPEN: c_char = 1;
|
|
const CLOSE: c_char = 2;
|
|
const CHDIR: c_char = 3;
|
|
const FCHDIR: c_char = 4;
|
|
const DUP2: c_char = 5;
|
|
|
|
#[derive(Debug, Clone)]
|
|
pub enum Action {
|
|
Open {
|
|
fd: c_int,
|
|
path: CString,
|
|
flag: c_int,
|
|
mode: mode_t,
|
|
},
|
|
Close(c_int),
|
|
Chdir(CString),
|
|
FChdir(c_int),
|
|
Dup2(c_int, c_int),
|
|
}
|
|
|
|
struct FileActions(Vec<Action>);
|
|
|
|
#[repr(C)]
|
|
#[derive(Debug, Clone, Copy)]
|
|
pub struct posix_spawn_file_actions_t {
|
|
__relibc_internal_size: [u8; 24],
|
|
__relibc_internal_align: size_t,
|
|
}
|
|
|
|
impl posix_spawn_file_actions_t {
|
|
pub fn add_action(&mut self, action: Action) {
|
|
let v = ptr::from_mut(self).cast::<FileActions>();
|
|
unsafe {
|
|
(*v).0.push(action);
|
|
}
|
|
}
|
|
}
|
|
|
|
pub struct FileActionsIter {
|
|
actions: posix_spawn_file_actions_t,
|
|
curr: usize,
|
|
}
|
|
|
|
impl Iterator for FileActionsIter {
|
|
type Item = Action;
|
|
|
|
fn next(&mut self) -> Option<Self::Item> {
|
|
let actions = unsafe {
|
|
ptr::from_mut(&mut self.actions)
|
|
.cast::<FileActions>()
|
|
.as_ref()
|
|
.unwrap()
|
|
};
|
|
let e = actions.0.get(self.curr)?;
|
|
self.curr += 1;
|
|
Some((*e).clone())
|
|
}
|
|
}
|
|
|
|
impl<'a> IntoIterator for &'a posix_spawn_file_actions_t {
|
|
type Item = Action;
|
|
|
|
type IntoIter = FileActionsIter;
|
|
|
|
fn into_iter(self) -> Self::IntoIter {
|
|
FileActionsIter {
|
|
actions: (*self).clone(),
|
|
curr: 0,
|
|
}
|
|
}
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn posix_spawn_file_actions_init(
|
|
file_actions: *mut posix_spawn_file_actions_t,
|
|
) -> c_int {
|
|
if file_actions.is_null() {
|
|
panic!("file_actions cannot be NULL");
|
|
}
|
|
let v = Vec::new();
|
|
let actions = FileActions(v);
|
|
unsafe {
|
|
ptr::write(file_actions.cast::<FileActions>(), actions);
|
|
}
|
|
0
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn posix_spawn_file_actions_destroy(
|
|
file_actions: *mut posix_spawn_file_actions_t,
|
|
) -> c_int {
|
|
if file_actions.is_null() {
|
|
panic!("file_actions cannot be NULL");
|
|
}
|
|
unsafe {
|
|
let _ = *(file_actions.cast::<FileActions>());
|
|
}
|
|
0
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn posix_spawn_file_actions_addopen(
|
|
file_actions: *mut posix_spawn_file_actions_t,
|
|
fd: c_int,
|
|
path: *const c_char,
|
|
oflag: c_int,
|
|
mode: mode_t,
|
|
) -> c_int {
|
|
let file_actions = unsafe { file_actions.as_mut().expect("file_actions cannot be NULL") };
|
|
if path.is_null() {
|
|
panic!("path cannot be NULL");
|
|
}
|
|
if fd < 0 {
|
|
return EBADF;
|
|
}
|
|
file_actions.add_action(Action::Open {
|
|
fd,
|
|
path: if path.is_null() {
|
|
CString::new("").unwrap()
|
|
} else {
|
|
unsafe { CString::from_raw(path as *mut c_char) }
|
|
},
|
|
flag: oflag,
|
|
mode,
|
|
});
|
|
0
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn posix_spawn_file_actions_addclose(
|
|
file_actions: *mut posix_spawn_file_actions_t,
|
|
fd: c_int,
|
|
) -> c_int {
|
|
let file_actions = unsafe { file_actions.as_mut().expect("file_actions cannot be NULL") };
|
|
if fd < 0 {
|
|
return EBADF;
|
|
}
|
|
file_actions.add_action(Action::Close(fd));
|
|
0
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn posix_spawn_file_actions_addchdir(
|
|
file_actions: *mut posix_spawn_file_actions_t,
|
|
path: *const c_char,
|
|
) -> c_int {
|
|
let file_actions = unsafe { file_actions.as_mut().expect("file_actions cannot be NULL") };
|
|
if path.is_null() {
|
|
panic!("path cannot be NULL");
|
|
}
|
|
file_actions.add_action(Action::Chdir(unsafe {
|
|
if path.is_null() {
|
|
CString::new("").unwrap()
|
|
} else {
|
|
CString::from_raw(path as *mut c_char)
|
|
}
|
|
}));
|
|
0
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn posix_spawn_file_actions_addfchdir(
|
|
file_actions: *mut posix_spawn_file_actions_t,
|
|
fd: c_int,
|
|
) -> c_int {
|
|
let file_actions = unsafe { file_actions.as_mut().expect("file_actions cannot be NULL") };
|
|
if fd < 0 {
|
|
return EBADF;
|
|
}
|
|
file_actions.add_action(Action::FChdir(fd));
|
|
0
|
|
}
|
|
|
|
#[unsafe(no_mangle)]
|
|
pub unsafe extern "C" fn posix_spawn_file_actions_adddup2(
|
|
file_actions: *mut posix_spawn_file_actions_t,
|
|
fd: c_int,
|
|
new: c_int,
|
|
) -> c_int {
|
|
let file_actions = unsafe { file_actions.as_mut().expect("file_actions cannot be NULL") };
|
|
if fd < 0 || new < 0 {
|
|
return EBADF;
|
|
}
|
|
file_actions.add_action(Action::Dup2(fd, new));
|
|
0
|
|
}
|