diff --git a/userspace/etc/test.sh b/userspace/etc/test.sh new file mode 100755 index 00000000..0f840cc8 --- /dev/null +++ b/userspace/etc/test.sh @@ -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 / diff --git a/userspace/lib/ygglibc/src/headers/spawn/mod.rs b/userspace/lib/ygglibc/src/headers/spawn/mod.rs index 357994e2..06d8fa68 100644 --- a/userspace/lib/ygglibc/src/headers/spawn/mod.rs +++ b/userspace/lib/ygglibc/src/headers/spawn/mod.rs @@ -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::>(); + + 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] diff --git a/userspace/lib/ygglibc/src/headers/unistd/fs.rs b/userspace/lib/ygglibc/src/headers/unistd/fs.rs index 26f911df..ee4b6304 100644 --- a/userspace/lib/ygglibc/src/headers/unistd/fs.rs +++ b/userspace/lib/ygglibc/src/headers/unistd/fs.rs @@ -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] diff --git a/userspace/lib/ygglibc/src/headers/unistd/io.rs b/userspace/lib/ygglibc/src/headers/unistd/io.rs index db0dde34..c0b21757 100644 --- a/userspace/lib/ygglibc/src/headers/unistd/io.rs +++ b/userspace/lib/ygglibc/src/headers/unistd/io.rs @@ -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] diff --git a/userspace/lib/ygglibc/src/headers/unistd/util.rs b/userspace/lib/ygglibc/src/headers/unistd/util.rs index ef9a7ff0..27f3b35f 100644 --- a/userspace/lib/ygglibc/src/headers/unistd/util.rs +++ b/userspace/lib/ygglibc/src/headers/unistd/util.rs @@ -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:?}"), } diff --git a/userspace/lib/ygglibc/src/io/raw.rs b/userspace/lib/ygglibc/src/io/raw.rs index 37036b61..cf49772d 100644 --- a/userspace/lib/ygglibc/src/io/raw.rs +++ b/userspace/lib/ygglibc/src/io/raw.rs @@ -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) -> EResult { let fd = unsafe { syscall::clone_fd(self.0, new) }?; EResult::Ok(Self(fd)) diff --git a/userspace/lib/ygglibc/src/util.rs b/userspace/lib/ygglibc/src/util.rs index 8073384b..d89e4783 100644 --- a/userspace/lib/ygglibc/src/util.rs +++ b/userspace/lib/ygglibc/src/util.rs @@ -12,6 +12,54 @@ use crate::{ headers::{errno::Errno, fcntl::AT_FDCWD}, }; +pub trait Pointer { + type Pointee; + + fn is_null(self) -> bool; +} + +impl Pointer for *const T { + type Pointee = T; + + fn is_null(self) -> bool { + <*const T>::is_null(self) + } +} + +impl Pointer for *mut T { + type Pointee = T; + + fn is_null(self) -> bool { + <*mut T>::is_null(self) + } +} + +pub struct NullTerminatedArrayIter { + pointer: *const T, +} + +impl NullTerminatedArrayIter { + pub fn new(pointer: *const T) -> Self { + Self { pointer } + } +} + +impl Iterator for NullTerminatedArrayIter { + type Item = T; + + fn next(&mut self) -> Option { + 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;