libc: implement posix_spawn()/truncate()

This commit is contained in:
Mark Poliakov 2025-02-24 11:05:23 +02:00
parent 5d5379ac8a
commit 6abea7ef22
7 changed files with 109 additions and 10 deletions

4
userspace/etc/test.sh Executable file
View File

@ -0,0 +1,4 @@
#!/bin/sh
/mnt/bin/clang -cc1as -filetype obj -main-file-name test.S -target-cpu x86-64 -mrelocation-model pic -triple x86_64-unknown-yggdrasil -o /test.o /etc/test.S
/bin/ls -lh /

View File

@ -1,10 +1,17 @@
use core::ffi::{c_char, c_int, c_short, c_void};
use alloc::vec::Vec;
use yggdrasil_rt::{io::RawFd, process::{SpawnFlags, SpawnOption, SpawnOptions}, sys as syscall};
use super::{
sched::__ygg_sched_param_t,
sys_types::{mode_t, pid_t},
};
use crate::util::PointerStrExt;
use crate::{
error::{CIntCountResult, CIntZeroResult, ResultExt},
headers::errno::Errno,
util::{NullTerminatedArrayIter, PointerStrExt},
};
#[repr(C)]
pub struct posix_spawnattr_t {}
@ -21,15 +28,39 @@ pub const POSIX_SPAWN_SETSIGMASK: c_int = 1 << 6;
#[no_mangle]
unsafe extern "C" fn posix_spawn(
_pid: *mut pid_t,
pid: *mut pid_t,
path: *const c_char,
_file_actions: *const posix_spawn_file_actions_t,
_attrp: *const posix_spawnattr_t,
_argv: *const *mut c_char,
argv: *const *mut c_char,
_envp: *const *mut c_char,
) -> c_int {
) -> CIntZeroResult {
let path = path.ensure_str();
todo!("TODO: posix_spawn({path:?})")
let argv = NullTerminatedArrayIter::new(argv);
let args = argv
.map(|arg| arg.cast_const().ensure_str())
.collect::<Vec<_>>();
log::info!("posix_spawn({path:?}, {args:?})");
let options = SpawnOptions {
program: path,
arguments: &args,
environment: &[],
directory: None,
optional: &[
SpawnOption::CopyFile { source: RawFd::STDIN, child: RawFd::STDIN },
SpawnOption::CopyFile { source: RawFd::STDOUT, child: RawFd::STDOUT },
SpawnOption::CopyFile { source: RawFd::STDERR, child: RawFd::STDERR },
],
flags: SpawnFlags::empty(),
};
let id = syscall::spawn_process(&options).e_map_err(Errno::from)?;
if let Some(pid) = pid.as_mut() {
*pid = id.bits() as i32;
}
CIntZeroResult::SUCCESS
}
#[no_mangle]

View File

@ -1,6 +1,14 @@
use core::ffi::{c_char, c_int, c_long};
use crate::{error::CIntZeroResult, headers::{fcntl::{faccessat, AT_FDCWD}, sys_types::{gid_t, off_t, uid_t}}, util::PointerExt};
use crate::{
error::{CIntZeroResult, TryFromExt},
headers::{
fcntl::{faccessat, AT_FDCWD},
sys_types::{gid_t, off_t, uid_t},
},
io::{raw::RawFile, FromRawFd},
util::PointerExt,
};
pub const _PC_PATH_MAX: c_int = 0;
@ -40,8 +48,11 @@ unsafe extern "C" fn fpathconf(fd: c_int, name: c_int) -> c_long {
}
#[no_mangle]
unsafe extern "C" fn ftruncate(fd: c_int, size: off_t) -> c_int {
todo!()
unsafe extern "C" fn ftruncate(fd: c_int, size: off_t) -> CIntZeroResult {
let mut file = RawFile::e_try_from(fd)?;
let size: u64 = size.try_into().unwrap();
file.truncate(size)?;
CIntZeroResult::SUCCESS
}
#[no_mangle]

View File

@ -45,7 +45,7 @@ unsafe extern "C" fn fsync(fd: c_int) -> CIntZeroResult {
#[no_mangle]
unsafe extern "C" fn isatty(fd: c_int) -> c_int {
log::error!("TODO: isatty()");
1
0
}
#[no_mangle]

View File

@ -46,7 +46,7 @@ unsafe extern "C" fn swab(from: *const c_void, to: *mut c_void, n: isize) {
#[no_mangle]
unsafe extern "C" fn sysconf(name: Sysconf) -> c_long {
match name {
Sysconf::_SC_ARG_MAX => 256,
Sysconf::_SC_ARG_MAX => 4096,
Sysconf::_SC_PAGE_SIZE => 0x1000,
_ => todo!("{name:?}"),
}

View File

@ -29,6 +29,11 @@ impl RawFile {
EResult::Ok(())
}
pub fn truncate(&mut self, size: u64) -> EResult<()> {
unsafe { syscall::truncate(self.0, size) }?;
EResult::Ok(())
}
pub fn duplicate(&self, new: Option<RawFd>) -> EResult<Self> {
let fd = unsafe { syscall::clone_fd(self.0, new) }?;
EResult::Ok(Self(fd))

View File

@ -12,6 +12,54 @@ use crate::{
headers::{errno::Errno, fcntl::AT_FDCWD},
};
pub trait Pointer {
type Pointee;
fn is_null(self) -> bool;
}
impl<T> Pointer for *const T {
type Pointee = T;
fn is_null(self) -> bool {
<*const T>::is_null(self)
}
}
impl<T> Pointer for *mut T {
type Pointee = T;
fn is_null(self) -> bool {
<*mut T>::is_null(self)
}
}
pub struct NullTerminatedArrayIter<T: Pointer> {
pointer: *const T,
}
impl<T: Pointer + Copy> NullTerminatedArrayIter<T> {
pub fn new(pointer: *const T) -> Self {
Self { pointer }
}
}
impl<T: Pointer + Copy> Iterator for NullTerminatedArrayIter<T> {
type Item = T;
fn next(&mut self) -> Option<Self::Item> {
if self.pointer.is_null() {
return None;
}
let current = unsafe { *self.pointer };
if current.is_null() {
return None;
}
self.pointer = unsafe { self.pointer.add(1) };
Some(current)
}
}
pub trait PointerExt {
unsafe fn ensure(self: *const Self) -> &'static Self;
unsafe fn ensure_mut(self: *mut Self) -> &'static mut Self;