Add posix_spawn_file_actions_t and posix_spawnattr_t and tests
This commit is contained in:
@@ -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"
|
||||
@@ -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
|
||||
}
|
||||
@@ -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!()
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
Reference in New Issue
Block a user