Add posix_spawn_file_actions_t and posix_spawnattr_t and tests

This commit is contained in:
R Aadarsh
2026-05-12 21:03:10 +05:30
parent 0dd5cf597a
commit df78820f01
7 changed files with 583 additions and 1 deletions
+10
View File
@@ -0,0 +1,10 @@
sys_includes = ["sched.h", "bits/sigset-t.h"]
include_guard = "_RELIBC_SPAWN_H"
language = "C"
cpp_compat = true
[enum]
prefix_with_name = true
[export.rename]
"sched_param" = "struct sched_param"
+200
View File
@@ -0,0 +1,200 @@
use core::{
ffi::{c_char, c_int},
ptr::null,
};
use crate::{
error::{Errno, Result},
header::{
errno::{EBADF, EINVAL, ENOMEM},
stdlib::{free, malloc},
string::memcpy,
},
platform::types::{c_void, mode_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;
#[repr(C)]
enum Operation {
Open {
fd: c_int,
path: *const c_char,
flag: c_int,
mode: mode_t,
},
Close(c_int),
Chdir(*const c_char),
FChdir(c_int),
Dup2(c_int, c_int),
}
#[repr(C)]
pub struct posix_spawn_file_actions_t {
size: usize,
operation: *const Operation,
}
fn copy_op(file_actions: *mut posix_spawn_file_actions_t, op: Operation) -> Result<()> {
if file_actions.is_null() {
return Err(Errno(EINVAL));
}
let new = unsafe { malloc((*file_actions).size + size_of::<Operation>()) };
if new == -1isize as *mut c_void {
return Err(Errno(ENOMEM));
}
unsafe {
if (*file_actions).size >= size_of::<Operation>() {
memcpy(
new,
(*file_actions).operation as *const c_void,
(*file_actions).size / size_of::<Operation>(),
);
free((*file_actions).operation as *mut c_void);
}
(*file_actions).operation = new as *const Operation;
let new = new as *mut Operation;
(*new.add((*file_actions).size)) = op;
(*file_actions).size += size_of::<Operation>()
}
Ok(())
}
#[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() {
return EINVAL;
}
unsafe {
(*file_actions).operation = null();
(*file_actions).size = 0;
}
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() {
return EINVAL;
}
unsafe {
free((*file_actions).operation as *mut c_void);
(*file_actions).operation = null();
(*file_actions).size = 0;
}
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 {
if fd < 0 {
return EBADF;
}
let open_op = Operation::Open {
fd,
path,
flag: oflag,
mode,
};
if let Err(e) = copy_op(file_actions, open_op) {
return e.0;
}
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 {
if fd < 0 {
return EBADF;
}
let close_op = Operation::Close(fd);
if let Err(e) = copy_op(file_actions, close_op) {
return e.0;
}
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 chdir_op = Operation::Chdir(path);
if let Err(e) = copy_op(file_actions, chdir_op) {
return e.0;
}
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 {
if fd < 0 {
return EBADF;
}
let fchdir_op = Operation::FChdir(fd);
if let Err(e) = copy_op(file_actions, fchdir_op) {
return e.0;
}
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 {
if fd < 0 || new < 0 {
return EBADF;
}
let dup2_op = Operation::Dup2(fd, new);
if let Err(e) = copy_op(file_actions, dup2_op) {
return e.0;
}
0
}
+25
View File
@@ -0,0 +1,25 @@
//! `spawn.h` implementation
//!
//! See <https://pubs.opengroup.org/onlinepubs/9799919799/basedefs/spawn.h.html>.
mod file_actions;
mod spawn_attr;
use core::ffi::c_char;
use crate::{
header::spawn::{file_actions::posix_spawn_file_actions_t, spawn_attr::posix_spawnattr_t},
platform::types::{c_int, pid_t},
};
#[unsafe(no_mangle)]
pub fn posix_spawn(
pid: *const pid_t,
path: *const c_char,
file_actions: *const posix_spawn_file_actions_t,
spawn_attr: *const posix_spawnattr_t,
argv: *const *const c_char,
envp: *const *const c_char,
) -> c_int {
todo!()
}
+254
View File
@@ -0,0 +1,254 @@
use core::{
ffi::{c_int, c_short},
mem::zeroed,
};
use bitflags;
use crate::header::{
bits_sigset_t::sigset_t,
errno::EINVAL,
sched::{SCHED_FIFO, SCHED_OTHER, SCHED_RR, sched_param},
sys_types_internal::pid_t,
};
bitflags::bitflags! {
struct Flags: c_short
{
const POSIX_SPAWN_RESETIDS = 1;
const POSIX_SPAWN_SETPGROUP = 2;
const POSIX_SPAWN_SETSIGDEF = 3;
const POSIX_SPAWN_SETSIGMASK = 4;
const POSIX_SPAWN_SETSCHEDPARAM = 5;
const POSIX_SPAWN_SETSCHEDULER = 6;
}
}
pub const POSIX_SPAWN_RESETIDS: c_short = 1;
pub const POSIX_SPAWN_SETPGROUP: c_short = 2;
pub const POSIX_SPAWN_SETSIGDEF: c_short = 3;
pub const POSIX_SPAWN_SETSIGMASK: c_short = 4;
pub const POSIX_SPAWN_SETSCHEDPARAM: c_short = 5;
pub const POSIX_SPAWN_SETSCHEDULER: c_short = 6;
#[repr(C)]
pub struct posix_spawnattr_t {
pub(crate) param: sched_param,
flags: c_short,
pgroup: c_int,
policy: c_int,
sigdefault: sigset_t,
sigmask: sigset_t,
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn posix_spawnattr_init(attr: *mut posix_spawnattr_t) -> c_int {
if attr.is_null() {
return EINVAL;
}
unsafe {
*attr = zeroed();
}
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn posix_spawnattr_destroy(attr: *mut posix_spawnattr_t) -> c_int {
if attr.is_null() {
return EINVAL;
}
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn posix_spawnattr_setschedparam(
attr: *mut posix_spawnattr_t,
schedparam: *const sched_param,
) -> c_int {
if attr.is_null() || schedparam.is_null() {
return EINVAL;
}
unsafe {
(*attr).param = *schedparam;
}
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn posix_spawnattr_getschedparam(
attr: *const posix_spawnattr_t,
schedparam: *mut sched_param,
) -> c_int {
if attr.is_null() || schedparam.is_null() {
return EINVAL;
}
unsafe {
*schedparam = (*attr).param;
}
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn posix_spawnattr_setschedpolicy(
attr: *mut posix_spawnattr_t,
schedpolicy: c_int,
) -> c_int {
if attr.is_null() {
return EINVAL;
}
match schedpolicy {
SCHED_FIFO | SCHED_RR | SCHED_OTHER => unsafe {
(*attr).policy = schedpolicy;
},
_ => return EINVAL,
}
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn posix_spawnattr_getschedpolicy(
attr: *const posix_spawnattr_t,
schedpolicy: *mut c_int,
) -> c_int {
if attr.is_null() || schedpolicy.is_null() {
return EINVAL;
}
unsafe {
*schedpolicy = (*attr).policy;
}
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn posix_spawnattr_setsigdefault(
attr: *mut posix_spawnattr_t,
sigdefault: *const sigset_t,
) -> c_int {
if attr.is_null() || sigdefault.is_null() {
return EINVAL;
}
unsafe {
(*attr).sigdefault = *sigdefault;
}
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn posix_spawnattr_getsigdefault(
attr: *const posix_spawnattr_t,
sigdefault: *mut sigset_t,
) -> c_int {
if attr.is_null() || sigdefault.is_null() {
return EINVAL;
}
unsafe {
*sigdefault = (*attr).sigdefault;
}
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn posix_spawnattr_setsigmask(
attr: *mut posix_spawnattr_t,
sigmask: *const sigset_t,
) -> c_int {
if attr.is_null() || sigmask.is_null() {
return EINVAL;
}
unsafe {
(*attr).sigmask = *sigmask;
}
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn posix_spawnattr_getsigmask(
attr: *const posix_spawnattr_t,
sigmask: *mut sigset_t,
) -> c_int {
if attr.is_null() || sigmask.is_null() {
return EINVAL;
}
unsafe {
*sigmask = (*attr).sigmask;
}
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn posix_spawnattr_setflags(
attr: *mut posix_spawnattr_t,
flags: c_short,
) -> c_int {
if attr.is_null() {
return EINVAL;
}
unsafe {
match Flags::from_bits(flags) {
Some(v) => (*attr).flags = v.bits(),
None => {
return EINVAL;
}
}
}
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn posix_spawnattr_getflags(
attr: *const posix_spawnattr_t,
flags: *mut c_short,
) -> c_int {
if attr.is_null() || flags.is_null() {
return EINVAL;
}
unsafe {
*flags = (*attr).flags;
}
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn posix_spawnattr_setpgroup(
attr: *mut posix_spawnattr_t,
pgroup: pid_t,
) -> c_int {
if attr.is_null() {
return EINVAL;
}
unsafe {
(*attr).pgroup = pgroup;
}
0
}
#[unsafe(no_mangle)]
pub unsafe extern "C" fn posix_spawnattr_getpgroup(
attr: *const posix_spawnattr_t,
pgroup: *mut pid_t,
) -> c_int {
if attr.is_null() || pgroup.is_null() {
return EINVAL;
}
unsafe {
*pgroup = (*attr).pgroup;
}
0
}