libc: better errno, better pidfd
This commit is contained in:
parent
6017e1044a
commit
cd22da9098
@ -297,7 +297,7 @@ impl<'a, A: BlockAllocator> BVec<'a, A> {
|
||||
let l2 = &self.l2[l2_outer];
|
||||
debug_assert!(!l2.is_null());
|
||||
|
||||
return &l2[l2_inner];
|
||||
&l2[l2_inner]
|
||||
} else {
|
||||
panic!("Block index too large");
|
||||
}
|
||||
@ -325,7 +325,7 @@ impl<'a, A: BlockAllocator> BVec<'a, A> {
|
||||
let l2 = &mut self.l2[l2_outer];
|
||||
debug_assert!(!l2.is_null());
|
||||
|
||||
return &mut l2[l2_inner];
|
||||
&mut l2[l2_inner]
|
||||
} else {
|
||||
panic!("Block index too large");
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ pub struct MemoryFilesystem<A: BlockAllocator> {
|
||||
|
||||
impl<A: BlockAllocator> MemoryFilesystem<A> {
|
||||
fn make_path(
|
||||
self: &Rc<Self>,
|
||||
// self: &Rc<Self>,
|
||||
at: &NodeRef,
|
||||
path: &Path,
|
||||
create: bool,
|
||||
@ -106,7 +106,7 @@ impl<A: BlockAllocator> MemoryFilesystem<A> {
|
||||
Ok(node)
|
||||
} else {
|
||||
assert!(node.is_directory());
|
||||
self.make_path(&node, rest, create)
|
||||
Self::make_path(&node, rest, create)
|
||||
}
|
||||
}
|
||||
|
||||
@ -144,7 +144,7 @@ impl<A: BlockAllocator> MemoryFilesystem<A> {
|
||||
log::debug!("Make path {:?}", path);
|
||||
|
||||
let (dirname, filename) = path.split_right();
|
||||
let parent = self.make_path(&root, dirname, true)?;
|
||||
let parent = Self::make_path(&root, dirname, true)?;
|
||||
let node = self.create_node_initial(hdr)?;
|
||||
|
||||
parent.add_child(filename, node)?;
|
||||
@ -157,7 +157,7 @@ impl<A: BlockAllocator> MemoryFilesystem<A> {
|
||||
};
|
||||
|
||||
let path = Path::from_str(hdr.name.as_str()?.trim_matches('/'));
|
||||
let node = self.make_path(&root, path, false)?;
|
||||
let node = Self::make_path(&root, path, false)?;
|
||||
assert_eq!(node.ty(), hdr.node_kind());
|
||||
|
||||
let uid = unsafe { UserId::from_raw(usize::from(&hdr.uid) as u32) };
|
||||
|
@ -129,34 +129,36 @@ impl BoolEvent {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn poll_reset(&self, cx: &mut Context<'_>) -> Poll<()> {
|
||||
self.notify.register(cx.waker());
|
||||
if self
|
||||
.state
|
||||
.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed)
|
||||
.is_ok()
|
||||
{
|
||||
// Event set and immediately reset
|
||||
self.notify.remove(cx.waker());
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
pub fn poll(&self, cx: &mut Context<'_>) -> Poll<()> {
|
||||
self.notify.register(cx.waker());
|
||||
if self.is_signalled() {
|
||||
self.notify.remove(cx.waker());
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn wait_reset(&self) {
|
||||
poll_fn(|cx| {
|
||||
self.notify.register(cx.waker());
|
||||
if self
|
||||
.state
|
||||
.compare_exchange(true, false, Ordering::Acquire, Ordering::Relaxed)
|
||||
.is_ok()
|
||||
{
|
||||
// Event set and immediately reset
|
||||
self.notify.remove(cx.waker());
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await
|
||||
poll_fn(|cx| self.poll_reset(cx)).await
|
||||
}
|
||||
|
||||
pub async fn wait(&self) {
|
||||
poll_fn(|cx| {
|
||||
self.notify.register(cx.waker());
|
||||
if self.is_signalled() {
|
||||
self.notify.remove(cx.waker());
|
||||
Poll::Ready(())
|
||||
} else {
|
||||
Poll::Pending
|
||||
}
|
||||
})
|
||||
.await
|
||||
poll_fn(|cx| self.poll(cx)).await
|
||||
}
|
||||
}
|
||||
|
@ -294,6 +294,10 @@ impl Process {
|
||||
self.map_image(|image| image.load_base)
|
||||
}
|
||||
|
||||
pub fn strong_child(&self, id: ProcessId) -> Option<Arc<Self>> {
|
||||
self.inner.read().strong_child(id)
|
||||
}
|
||||
|
||||
pub fn as_single_thread(&self) -> Option<Arc<Thread>> {
|
||||
let inner = self.inner.read();
|
||||
if inner.threads.len() != 1 {
|
||||
|
@ -20,6 +20,7 @@ use yggdrasil_abi::{
|
||||
DeviceRequest, DirectoryEntry, OpenOptions, PipeOptions, RawFd, SeekFrom, TerminalOptions,
|
||||
TerminalSize, TimerOptions,
|
||||
},
|
||||
process::{ProcessWait, WaitFlags},
|
||||
};
|
||||
|
||||
use crate::{
|
||||
@ -165,8 +166,14 @@ impl File {
|
||||
}
|
||||
|
||||
/// Creates a new [PidFile]-backed file
|
||||
pub fn new_pid(process: &Arc<Process>) -> FileRef {
|
||||
Arc::new(Self::Pid(PidFile::new(process)))
|
||||
pub fn new_pid(
|
||||
parent: Arc<Process>,
|
||||
wait: &ProcessWait,
|
||||
flags: WaitFlags,
|
||||
) -> Result<FileRef, Error> {
|
||||
PidFile::new(parent, wait, flags)
|
||||
.map(Self::Pid)
|
||||
.map(Arc::new)
|
||||
}
|
||||
|
||||
/// Constructs a [File] from a [PacketSocket], [ConnectionSocket] or a [ListenerSocket].
|
||||
|
@ -1,58 +1,129 @@
|
||||
use alloc::sync::{Arc, Weak};
|
||||
use alloc::sync::Arc;
|
||||
use core::{
|
||||
fmt,
|
||||
task::{Context, Poll},
|
||||
};
|
||||
|
||||
use libk_util::io::Read;
|
||||
use yggdrasil_abi::{error::Error, process::ExitCode};
|
||||
use yggdrasil_abi::{
|
||||
error::Error,
|
||||
process::{ExitCode, ProcessId, ProcessWait, WaitFlags},
|
||||
};
|
||||
|
||||
use crate::task::process::Process;
|
||||
|
||||
use super::FileReadiness;
|
||||
|
||||
#[derive(Clone)]
|
||||
pub struct PidFile {
|
||||
process: Weak<Process>,
|
||||
pub struct PidFileProcess {
|
||||
parent: Arc<Process>,
|
||||
child: Arc<Process>,
|
||||
non_blocking: bool,
|
||||
}
|
||||
|
||||
#[allow(unused)]
|
||||
#[derive(Clone)]
|
||||
pub struct PidFileAnyChild {
|
||||
parent: Arc<Process>,
|
||||
non_blocking: bool,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub enum PidFile {
|
||||
Process(PidFileProcess),
|
||||
AnyChild(PidFileAnyChild),
|
||||
}
|
||||
|
||||
impl PidFileProcess {
|
||||
pub fn new(parent: Arc<Process>, child: ProcessId, flags: WaitFlags) -> Result<Self, Error> {
|
||||
let child = parent.strong_child(child).ok_or(Error::ProcessNotFound)?;
|
||||
Ok(Self {
|
||||
parent,
|
||||
child,
|
||||
non_blocking: flags.contains(WaitFlags::NON_BLOCKING),
|
||||
})
|
||||
}
|
||||
|
||||
pub fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
if let Some(status) = self.status() {
|
||||
return Ok(PidFile::write_completion(buf, self.child.id, status));
|
||||
}
|
||||
|
||||
if self.non_blocking {
|
||||
return Err(Error::WouldBlock);
|
||||
}
|
||||
|
||||
block! {
|
||||
loop {
|
||||
if let Some(status) = self.status() {
|
||||
break PidFile::write_completion(buf, self.child.id, status);
|
||||
}
|
||||
|
||||
self.parent.child_exit_notify.wait_reset().await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn poll_read(&self, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
|
||||
self.parent.child_exit_notify.poll_reset(cx).map(Ok)
|
||||
}
|
||||
|
||||
fn status(&self) -> Option<ExitCode> {
|
||||
self.child.get_exit_status()
|
||||
}
|
||||
}
|
||||
|
||||
impl PidFile {
|
||||
pub fn new(process: &Arc<Process>) -> Self {
|
||||
Self {
|
||||
process: Arc::downgrade(process),
|
||||
pub fn new(parent: Arc<Process>, wait: &ProcessWait, flags: WaitFlags) -> Result<Self, Error> {
|
||||
match wait {
|
||||
&ProcessWait::Process(id) => PidFileProcess::new(parent, id, flags).map(Self::Process),
|
||||
&ProcessWait::Group(_id) => todo!(),
|
||||
ProcessWait::AnyChild => todo!(),
|
||||
}
|
||||
}
|
||||
|
||||
fn write_completion(buf: &mut [u8], pid: ProcessId, status: ExitCode) -> usize {
|
||||
debug_assert!(buf.len() >= size_of::<u32>() + size_of::<i32>());
|
||||
buf[..size_of::<u32>()].copy_from_slice(&pid.bits().to_ne_bytes());
|
||||
match status {
|
||||
ExitCode::Exited(code) => buf[size_of::<u32>()..size_of::<u32>() + size_of::<i32>()]
|
||||
.copy_from_slice(&code.to_ne_bytes()),
|
||||
_ => todo!(),
|
||||
}
|
||||
size_of::<u32>() + size_of::<i32>()
|
||||
}
|
||||
}
|
||||
|
||||
impl Read for PidFile {
|
||||
fn read(&self, buf: &mut [u8]) -> Result<usize, Error> {
|
||||
if buf.len() < size_of::<i32>() {
|
||||
if buf.len() < size_of::<u32>() + size_of::<i32>() {
|
||||
return Err(Error::BufferTooSmall);
|
||||
}
|
||||
let process = self.process.upgrade().ok_or(Error::DoesNotExist)?;
|
||||
let exit = block!(process.wait_for_exit().await)?;
|
||||
match exit {
|
||||
ExitCode::Exited(code) => buf[..size_of::<i32>()].copy_from_slice(&code.to_le_bytes()),
|
||||
_ => todo!(),
|
||||
match self {
|
||||
Self::Process(pid) => pid.read(buf),
|
||||
Self::AnyChild(_) => todo!(),
|
||||
}
|
||||
Ok(size_of::<i32>())
|
||||
}
|
||||
}
|
||||
|
||||
impl FileReadiness for PidFile {
|
||||
fn poll_read(&self, cx: &mut Context<'_>) -> Poll<Result<(), Error>> {
|
||||
match self.process.upgrade() {
|
||||
Some(process) => process.poll_read(cx),
|
||||
None => Poll::Ready(Err(Error::DoesNotExist)),
|
||||
match self {
|
||||
Self::Process(pid) => pid.poll_read(cx),
|
||||
Self::AnyChild(_) => todo!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for PidFile {
|
||||
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
||||
match self.process.upgrade() {
|
||||
Some(process) => f.debug_struct("PidFile").field("pid", &process.id).finish(),
|
||||
None => f.debug_struct("PidFile").field("pid", &"<none>").finish(),
|
||||
}
|
||||
let mut s = f.debug_struct("PidFile");
|
||||
match self {
|
||||
Self::Process(pid) => s
|
||||
.field("child", &pid.child.id)
|
||||
.field("non_blocking", &pid.non_blocking),
|
||||
Self::AnyChild(pid) => s.field("non_blocking", &pid.non_blocking),
|
||||
};
|
||||
s.finish()
|
||||
}
|
||||
}
|
||||
|
@ -7,12 +7,12 @@ use abi::{
|
||||
MessageDestination, OpenOptions, PipeOptions, PollControl, RawFd, ReceivedMessageMetadata,
|
||||
SeekFrom, SentMessage, TerminalOptions, TerminalSize, TimerOptions,
|
||||
},
|
||||
process::ProcessId,
|
||||
process::{ProcessWait, WaitFlags},
|
||||
};
|
||||
use alloc::boxed::Box;
|
||||
use libk::{
|
||||
block,
|
||||
task::{process::Process, thread::Thread},
|
||||
task::thread::Thread,
|
||||
vfs::{self, File, MessagePayload, Read, Seek, Write},
|
||||
};
|
||||
|
||||
@ -243,13 +243,12 @@ pub(crate) fn create_timer(options: TimerOptions) -> Result<RawFd, Error> {
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn create_pid(pid: ProcessId) -> Result<RawFd, Error> {
|
||||
pub(crate) fn create_pid(wait: &ProcessWait, flags: WaitFlags) -> Result<RawFd, Error> {
|
||||
let thread = Thread::current();
|
||||
let process = thread.process();
|
||||
|
||||
run_with_io(&process, |mut io| {
|
||||
let process = Process::get(pid).ok_or(Error::DoesNotExist)?;
|
||||
let file = File::new_pid(&process);
|
||||
let file = File::new_pid(process.clone(), wait, flags)?;
|
||||
let fd = io.files.place_file(file, true)?;
|
||||
Ok(fd)
|
||||
})
|
||||
|
@ -321,9 +321,7 @@ pub(crate) fn wait_thread(id: u32) -> Result<(), Error> {
|
||||
let this_thread = Thread::current();
|
||||
let process = this_thread.process();
|
||||
|
||||
let result = block!(process.wait_for_thread(tid).await)?;
|
||||
|
||||
result
|
||||
block!(process.wait_for_thread(tid).await)?
|
||||
}
|
||||
|
||||
pub(crate) fn get_thread_option(option: &mut ThreadOption) -> Result<(), Error> {
|
||||
|
@ -28,4 +28,5 @@ enum Error(u32) {
|
||||
UndefinedSyscall = 25,
|
||||
DirectoryNotEmpty = 26,
|
||||
NotConnected = 27,
|
||||
ProcessNotFound = 28,
|
||||
}
|
||||
|
@ -122,7 +122,7 @@ syscall device_request(fd: RawFd, req: &mut DeviceRequest) -> Result<()>;
|
||||
// Misc I/O
|
||||
syscall open_channel(name: &str, subscribe: bool) -> Result<RawFd>;
|
||||
syscall create_timer(options: TimerOptions) -> Result<RawFd>;
|
||||
syscall create_pid(pid: ProcessId) -> Result<RawFd>;
|
||||
syscall create_pid(target: &ProcessWait, flags: WaitFlags) -> Result<RawFd>;
|
||||
syscall create_pty(opts: &TerminalOptions, size: &TerminalSize, fds: &mut [MaybeUninit<RawFd>; 2]) -> Result<()>;
|
||||
syscall create_shared_memory(size: usize) -> Result<RawFd>;
|
||||
syscall create_poll_channel() -> Result<RawFd>;
|
||||
|
@ -9,15 +9,17 @@
|
||||
)]
|
||||
#![no_std]
|
||||
#![deny(missing_docs)]
|
||||
#![allow(nonstandard_style)]
|
||||
#![allow(unused)]
|
||||
#![allow(nonstandard_style, clippy::new_without_default)]
|
||||
|
||||
// #[cfg(not(feature = "rustc-dep-of-std"))]
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate compiler_builtins;
|
||||
extern crate yggdrasil_abi as abi;
|
||||
|
||||
#[allow(unused_extern_crates)]
|
||||
extern crate alloc;
|
||||
|
||||
extern crate yggdrasil_abi as abi;
|
||||
|
||||
pub use abi::error::Error;
|
||||
pub use abi::path;
|
||||
pub mod debug;
|
||||
|
@ -7,6 +7,7 @@ use abi::{error::Error, io::RawFd};
|
||||
|
||||
use crate::sys;
|
||||
|
||||
#[allow(unused_macros)]
|
||||
macro socket_option_variant {
|
||||
($opt:ident: bool) => { $crate::net::SocketOption::$opt(false) },
|
||||
($opt:ident: Option) => { $crate::net::SocketOption::$opt(None) },
|
||||
|
@ -6,7 +6,6 @@ use abi::{
|
||||
mem::{MappingFlags, MappingSource},
|
||||
process::{ExitCode, ProcessOption, Signal, SignalEntryData, ThreadOption},
|
||||
};
|
||||
use alloc::boxed::Box;
|
||||
|
||||
/// Describes how a signal should be handled
|
||||
#[derive(Debug, Clone, Copy)]
|
||||
@ -25,6 +24,8 @@ pub enum SignalHandler {
|
||||
const MAX_SIGNALS: usize = 16;
|
||||
static mut TABLE: [SignalHandler; MAX_SIGNALS] = [const { SignalHandler::Terminate }; MAX_SIGNALS];
|
||||
|
||||
// TODO remove unused for i686
|
||||
#[allow(unused)]
|
||||
unsafe extern "C" fn common_signal_entry(data: &SignalEntryData) -> ! {
|
||||
let index = data.signal.into_raw() as usize;
|
||||
|
||||
@ -160,6 +161,7 @@ pub fn setup_signal_full(size: usize) -> Result<(), Error> {
|
||||
|
||||
// implementation details
|
||||
|
||||
// TODO
|
||||
#[cfg(any(target_arch = "x86", rust_analyzer))]
|
||||
mod imp {
|
||||
// i686 is a bit tricky: cdecl ABI requires the arguments to be passed on the stack, while
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
use core::{
|
||||
ptr,
|
||||
sync::atomic::{AtomicU32, AtomicUsize, Ordering},
|
||||
sync::atomic::{AtomicU32, Ordering},
|
||||
};
|
||||
|
||||
use abi::{
|
||||
@ -27,6 +27,7 @@ pub struct Thread<R> {
|
||||
/// Describes a "handle" to some runtime thread. This is what gets returned to the caller
|
||||
/// when a thread is spawned and can be used to, e.g., join the created thread later.
|
||||
pub struct ThreadHandle<R> {
|
||||
#[allow(unused)]
|
||||
stack: Option<OwnedStack>,
|
||||
thread: Arc<Thread<R>>,
|
||||
}
|
||||
@ -157,7 +158,7 @@ impl<R> Thread<R> {
|
||||
let mut argument = unsafe { Box::from_raw(raw) };
|
||||
|
||||
// Setup TLS as soon as possible
|
||||
if let Err(err) = unsafe { thread_local::init_tls(argument.tls_image, true) } {
|
||||
if let Err(err) = thread_local::init_tls(argument.tls_image, true) {
|
||||
crate::debug_trace!("thread_entry failed: TLS init error: {err:?}");
|
||||
// TODO result is uninit
|
||||
unsafe { crate::sys::exit_thread() };
|
||||
@ -196,7 +197,7 @@ impl<R> Thread<R> {
|
||||
None => unreachable!(),
|
||||
};
|
||||
|
||||
argument.thread_self.result.write().insert(result);
|
||||
argument.thread_self.result.write().replace(result);
|
||||
}
|
||||
|
||||
unsafe { crate::sys::exit_thread() };
|
||||
@ -224,7 +225,7 @@ impl<R> ThreadHandle<R> {
|
||||
pub fn join_uninterruptible(self) -> Option<R> {
|
||||
loop {
|
||||
match unsafe { crate::sys::wait_thread(self.thread.id.load(Ordering::Acquire)) } {
|
||||
Ok(result) => (),
|
||||
Ok(_) => (),
|
||||
Err(Error::Interrupted) => continue,
|
||||
Err(error) => panic!("wait_thread syscall returned error: {error:?}"),
|
||||
}
|
||||
|
@ -8,7 +8,7 @@ use alloc::{boxed::Box, vec::Vec};
|
||||
|
||||
use abi::{
|
||||
error::Error,
|
||||
process::{auxv, AuxValue, ThreadOption},
|
||||
process::{auxv, AuxValue},
|
||||
};
|
||||
|
||||
#[cfg(any(target_arch = "aarch64", rust_analyzer))]
|
||||
@ -56,11 +56,10 @@ pub struct Dtv {
|
||||
entries: Vec<*mut c_void>,
|
||||
// Entries for pthread_setspecific()-like behavior
|
||||
specific: Vec<*mut c_void>,
|
||||
// Self-reference for the thread
|
||||
thread_self: *mut c_void,
|
||||
}
|
||||
|
||||
struct TcbHeader {
|
||||
#[allow(unused)]
|
||||
self_pointer: usize,
|
||||
dtv_pointer: *mut Dtv,
|
||||
}
|
||||
@ -128,7 +127,6 @@ impl Dtv {
|
||||
Self {
|
||||
entries: Vec::new(),
|
||||
specific: Vec::new(),
|
||||
thread_self: null_mut(),
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -26,8 +26,6 @@ pub fn clone_tls(image: &TlsImage) -> Result<(usize, usize), Error> {
|
||||
panic!("TODO: TLS alignment larger than a page size is not supported");
|
||||
}
|
||||
|
||||
let align = image.align;
|
||||
|
||||
// TCB size, padded to align. Also the start of the first module
|
||||
let tcb_aligned_size = (TCB_SIZE + image.align - 1) & !(image.align - 1);
|
||||
let full_size = tcb_aligned_size + image.full_size;
|
||||
|
@ -23,8 +23,8 @@ mod generated {
|
||||
mem::{MappingFlags, MappingSource},
|
||||
net::SocketType,
|
||||
process::{
|
||||
ExecveOptions, ProcessGroupId, ProcessId, ProcessOption, Signal, SignalEntryData,
|
||||
SpawnOptions, ThreadSpawnOptions, WaitFlags,
|
||||
ExecveOptions, ProcessGroupId, ProcessId, Signal, SignalEntryData, SpawnOptions,
|
||||
ThreadSpawnOptions, WaitFlags,
|
||||
},
|
||||
SyscallFunction,
|
||||
};
|
||||
|
@ -1,14 +1,19 @@
|
||||
use std::{io, os::{fd::{AsRawFd, RawFd}, yggdrasil::io::pid::{PidFd as YggPidFd, ProcessId}}};
|
||||
use std::{
|
||||
io,
|
||||
os::{
|
||||
fd::{AsRawFd, RawFd},
|
||||
yggdrasil::io::pid::{PidFd as YggPidFd, ProcessId},
|
||||
},
|
||||
};
|
||||
|
||||
use crate::sys::PidFd;
|
||||
|
||||
|
||||
pub struct PidFdImpl(YggPidFd);
|
||||
|
||||
impl PidFd for PidFdImpl {
|
||||
fn new(pid: u32) -> io::Result<Self> {
|
||||
let pid = unsafe { ProcessId::from_raw(pid) };
|
||||
YggPidFd::new(pid).map(Self)
|
||||
YggPidFd::child(pid, false).map(Self)
|
||||
}
|
||||
|
||||
fn exit_status(&self) -> io::Result<i32> {
|
||||
|
@ -12,8 +12,7 @@ use yggdrasil_rt::{
|
||||
use crate::{
|
||||
error::{EResult, OptionExt},
|
||||
headers::{
|
||||
errno,
|
||||
string::mem::{memcpy, memset},
|
||||
errno::Errno, string::mem::{memcpy, memset}
|
||||
},
|
||||
};
|
||||
|
||||
@ -80,7 +79,7 @@ pub fn c_alloc(size: usize, align: usize, zero: bool) -> EResult<NonNull<c_void>
|
||||
};
|
||||
let size = size + 16;
|
||||
let layout = Layout::from_size_align(size, align).expect("Couldn't setup malloc() layout");
|
||||
let ptr = YALLOC.lock().allocate(layout).e_ok_or(errno::ENOMEM)?;
|
||||
let ptr = YALLOC.lock().allocate(layout).e_ok_or(Errno::ENOMEM)?;
|
||||
|
||||
if zero {
|
||||
unsafe {
|
||||
|
@ -13,8 +13,7 @@ use crate::{
|
||||
allocator::{c_alloc, c_free},
|
||||
error::EResult,
|
||||
headers::{
|
||||
errno,
|
||||
string::{mem::memcpy, str::strlen},
|
||||
errno::Errno, string::{mem::memcpy, str::strlen}
|
||||
},
|
||||
thread,
|
||||
util::PointerExt,
|
||||
@ -63,7 +62,7 @@ unsafe fn push_env(str: NonNull<c_char>) -> EResult<()> {
|
||||
reclaim_env()?;
|
||||
|
||||
if shadow.try_reserve(1).is_err() {
|
||||
return EResult::Err(errno::ENOMEM);
|
||||
return EResult::Err(Errno::ENOMEM);
|
||||
}
|
||||
|
||||
let entry = shadow.last_mut().unwrap();
|
||||
@ -81,7 +80,7 @@ unsafe fn push_env(str: NonNull<c_char>) -> EResult<()> {
|
||||
|
||||
pub unsafe fn get_env(name: &[u8]) -> EResult<Option<NonNull<c_char>>> {
|
||||
if name.is_empty() || name.contains(&b'=') {
|
||||
return EResult::Err(errno::EINVAL);
|
||||
return EResult::Err(Errno::EINVAL);
|
||||
}
|
||||
|
||||
let Some(mut iter) = NonNull::new(environ) else {
|
||||
@ -106,7 +105,7 @@ pub unsafe fn get_env(name: &[u8]) -> EResult<Option<NonNull<c_char>>> {
|
||||
|
||||
pub unsafe fn set_env(name: &[u8], value: NonNull<c_char>, overwrite: bool) -> EResult<()> {
|
||||
if name.is_empty() || name.contains(&b'=') {
|
||||
return EResult::Err(errno::EINVAL);
|
||||
return EResult::Err(Errno::EINVAL);
|
||||
}
|
||||
|
||||
let value = CStr::from_ptr(value.as_ptr()).to_bytes();
|
||||
@ -153,7 +152,7 @@ pub unsafe fn set_env(name: &[u8], value: NonNull<c_char>, overwrite: bool) -> E
|
||||
|
||||
pub unsafe fn remove_env(name: &[u8]) -> EResult<bool> {
|
||||
if name.is_empty() || name.contains(&b'=') {
|
||||
return EResult::Err(errno::EINVAL);
|
||||
return EResult::Err(Errno::EINVAL);
|
||||
}
|
||||
|
||||
reclaim_env()?;
|
||||
@ -180,7 +179,7 @@ pub unsafe fn remove_env(name: &[u8]) -> EResult<bool> {
|
||||
pub unsafe fn put_env(str: NonNull<c_char>) -> EResult<()> {
|
||||
let bytes = CStr::from_ptr(str.as_ptr()).to_bytes();
|
||||
if bytes.is_empty() || !bytes.contains(&b'=') {
|
||||
return EResult::Err(errno::EINVAL);
|
||||
return EResult::Err(Errno::EINVAL);
|
||||
}
|
||||
let name = get_key(str).unwrap();
|
||||
|
||||
|
@ -26,7 +26,7 @@ macro impl_from_residual($($ty:ty),+) {
|
||||
#[thread_local]
|
||||
#[no_mangle]
|
||||
#[allow(non_upper_case_globals)]
|
||||
pub static mut errno: Errno = Errno(0);
|
||||
pub static mut errno: Errno = Errno::ESUCCESS;
|
||||
|
||||
pub trait ResultExt<T, E> {
|
||||
fn e_map_err<F: FnOnce(E) -> Errno>(self, map: F) -> EResult<T>;
|
||||
|
@ -13,7 +13,7 @@ use crate::{
|
||||
util::{PointerExt, PointerStrExt},
|
||||
};
|
||||
|
||||
use super::{errno::ESUCCESS, sys_types::ino_t};
|
||||
use super::{errno::Errno, sys_types::ino_t};
|
||||
|
||||
#[derive(Debug)]
|
||||
#[repr(C)]
|
||||
@ -46,7 +46,7 @@ impl DIR {
|
||||
self.buffer.write(dirent::from(entry));
|
||||
EResult::Ok(unsafe { NonNull::new_unchecked(self.buffer.as_mut_ptr()) })
|
||||
}
|
||||
EResult::Ok(None) => EResult::Err(ESUCCESS),
|
||||
EResult::Ok(None) => EResult::Err(Errno::ESUCCESS),
|
||||
EResult::Err(err) => EResult::Err(err),
|
||||
}
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ pub struct Dl_info {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn dlclose(dl: *mut c_void) -> c_int {
|
||||
unsafe extern "C" fn dlclose(_dl: *mut c_void) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
||||
@ -25,26 +25,26 @@ unsafe extern "C" fn dlerror() -> *mut c_char {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn dlopen(path: *const c_char, flags: c_int) -> *mut c_void {
|
||||
unsafe extern "C" fn dlopen(_path: *const c_char, _flags: c_int) -> *mut c_void {
|
||||
todo!()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn dlsym(dl: *mut c_void, name: *const c_char) -> *mut c_void {
|
||||
unsafe extern "C" fn dlsym(_dl: *mut c_void, _name: *const c_char) -> *mut c_void {
|
||||
todo!()
|
||||
}
|
||||
|
||||
// Non-POSIX
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn dladdr(addr: *mut c_void, info: *mut Dl_info) -> c_int {
|
||||
unsafe extern "C" fn dladdr(_addr: *mut c_void, _info: *mut Dl_info) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn dladdr1(
|
||||
addr: *mut c_void,
|
||||
info: *mut Dl_info,
|
||||
extra_info: *mut *mut c_void,
|
||||
flags: c_int,
|
||||
_addr: *mut c_void,
|
||||
_info: *mut Dl_info,
|
||||
_extra_info: *mut *mut c_void,
|
||||
_flags: c_int,
|
||||
) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
@ -7,4 +7,8 @@ no_includes = true
|
||||
include_guard = "_ERRNO_H"
|
||||
trailer = "#include <bits/errno.h>"
|
||||
|
||||
[enum]
|
||||
enum_style = "define"
|
||||
|
||||
[export]
|
||||
include = ["Errno"]
|
||||
|
@ -1,187 +1,200 @@
|
||||
use core::ffi::{c_int, CStr};
|
||||
use core::ffi::CStr;
|
||||
|
||||
macro_rules! static_cstr {
|
||||
($string:expr) => {
|
||||
unsafe {
|
||||
::core::ffi::CStr::from_bytes_with_nul_unchecked(concat!($string, "\0").as_bytes())
|
||||
}
|
||||
};
|
||||
macro static_cstr($string:literal) {
|
||||
unsafe { ::core::ffi::CStr::from_bytes_with_nul_unchecked(concat!($string, "\0").as_bytes()) }
|
||||
}
|
||||
|
||||
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Debug)]
|
||||
#[repr(transparent)]
|
||||
pub struct Errno(pub c_int);
|
||||
#[non_exhaustive]
|
||||
#[repr(C)]
|
||||
pub enum Errno {
|
||||
ESUCCESS = 0,
|
||||
EPERM = 1,
|
||||
ENOENT = 2,
|
||||
ESRCH = 3,
|
||||
EINTR = 4,
|
||||
EIO = 5,
|
||||
ENXIO = 6,
|
||||
E2BIG = 7,
|
||||
ENOEXEC = 8,
|
||||
EBADF = 9,
|
||||
ECHILD = 10,
|
||||
EAGAIN = 11,
|
||||
ENOMEM = 12,
|
||||
EACCES = 13,
|
||||
EFAULT = 14,
|
||||
ENOTBLK = 15,
|
||||
EBUSY = 16,
|
||||
EEXIST = 17,
|
||||
EXDEV = 18,
|
||||
ENODEV = 19,
|
||||
ENOTDIR = 20,
|
||||
EISDIR = 21,
|
||||
EINVAL = 22,
|
||||
ENFILE = 23,
|
||||
EMFILE = 24,
|
||||
ENOTTY = 25,
|
||||
ETXTBSY = 26,
|
||||
EFBIG = 27,
|
||||
ENOSPC = 28,
|
||||
ESPIPE = 29,
|
||||
EROFS = 30,
|
||||
EMLINK = 31,
|
||||
EPIPE = 32,
|
||||
EDOM = 33,
|
||||
ERANGE = 34,
|
||||
|
||||
pub const ESUCCESS: Errno = Errno(0);
|
||||
pub const EPERM: Errno = Errno(1);
|
||||
pub const ENOENT: Errno = Errno(2);
|
||||
pub const ESRCH: Errno = Errno(3);
|
||||
pub const EINTR: Errno = Errno(4);
|
||||
pub const EIO: Errno = Errno(5);
|
||||
pub const ENXIO: Errno = Errno(6);
|
||||
pub const E2BIG: Errno = Errno(7);
|
||||
pub const ENOEXEC: Errno = Errno(8);
|
||||
pub const EBADF: Errno = Errno(9);
|
||||
pub const ECHILD: Errno = Errno(10);
|
||||
pub const EAGAIN: Errno = Errno(11);
|
||||
pub const ENOMEM: Errno = Errno(12);
|
||||
pub const EACCES: Errno = Errno(13);
|
||||
pub const EFAULT: Errno = Errno(14);
|
||||
pub const ENOTBLK: Errno = Errno(15);
|
||||
pub const EBUSY: Errno = Errno(16);
|
||||
pub const EEXIST: Errno = Errno(17);
|
||||
pub const EXDEV: Errno = Errno(18);
|
||||
pub const ENODEV: Errno = Errno(19);
|
||||
pub const ENOTDIR: Errno = Errno(20);
|
||||
pub const EISDIR: Errno = Errno(21);
|
||||
pub const EINVAL: Errno = Errno(22);
|
||||
pub const ENFILE: Errno = Errno(23);
|
||||
pub const EMFILE: Errno = Errno(24);
|
||||
pub const ENOTTY: Errno = Errno(25);
|
||||
pub const ETXTBSY: Errno = Errno(26);
|
||||
pub const EFBIG: Errno = Errno(27);
|
||||
pub const ENOSPC: Errno = Errno(28);
|
||||
pub const ESPIPE: Errno = Errno(29);
|
||||
pub const EROFS: Errno = Errno(30);
|
||||
pub const EMLINK: Errno = Errno(31);
|
||||
pub const EPIPE: Errno = Errno(32);
|
||||
pub const EDOM: Errno = Errno(33);
|
||||
pub const ERANGE: Errno = Errno(34);
|
||||
EDEADLK = 35,
|
||||
ENAMETOOLONG = 36,
|
||||
ENOLCK = 37,
|
||||
|
||||
pub const EDEADLK: Errno = Errno(35);
|
||||
pub const ENAMETOOLONG: Errno = Errno(36);
|
||||
ENOSYS = 38,
|
||||
ENOTEMPTY = 39,
|
||||
ELOOP = 40,
|
||||
|
||||
pub const ENOLCK: Errno = Errno(37);
|
||||
pub const ENOSYS: Errno = Errno(38);
|
||||
pub const ENOTEMPTY: Errno = Errno(39);
|
||||
pub const ELOOP: Errno = Errno(40);
|
||||
pub const EWOULDBLOCK: Errno = EAGAIN;
|
||||
pub const ENOMSG: Errno = Errno(42);
|
||||
ENOTSOCK = 41,
|
||||
EDESTADDRREQ = 42,
|
||||
EMSGSIZE = 43,
|
||||
EPROTOTYPE = 44,
|
||||
ENOPROTOOPT = 45,
|
||||
EPROTONOSUPPORT = 46,
|
||||
ESOCKTNOSUPPORT = 47,
|
||||
EOPNOTSUPP = 48,
|
||||
EPFNOSUPPORT = 49,
|
||||
EAFNOSUPPORT = 50,
|
||||
EADDRINUSE = 51,
|
||||
EADDRNOTAVAIL = 52,
|
||||
ENETDOWN = 53,
|
||||
ENETUNREACH = 54,
|
||||
ENETRESET = 55,
|
||||
ECONNABORTED = 56,
|
||||
ECONNRESET = 57,
|
||||
ENOBUFS = 58,
|
||||
EISCONN = 59,
|
||||
ENOTCONN = 60,
|
||||
ESHUTDOWN = 61,
|
||||
ETIMEDOUT = 62,
|
||||
ECONNREFUSED = 63,
|
||||
EHOSTDOWN = 64,
|
||||
EHOSTUNREACH = 65,
|
||||
// Custom errnos
|
||||
ENOTSUPP = 66,
|
||||
ETIMEOUT = 67,
|
||||
}
|
||||
|
||||
pub const MAX_ERROR: Errno = ERANGE;
|
||||
|
||||
static SUCCESS: &CStr = static_cstr!("Success");
|
||||
pub static UNKNOWN_ERROR: &CStr = static_cstr!("Unknown error");
|
||||
static UNKNOWN_ERROR: &CStr = static_cstr!("Unknown error");
|
||||
static ERRNO_STRINGS: &[&CStr] = &[
|
||||
// 0
|
||||
SUCCESS,
|
||||
// EPERM 1
|
||||
static_cstr!("No error"),
|
||||
static_cstr!("Operation not permitted"),
|
||||
// ENOENT 2
|
||||
static_cstr!("No such file or directory"),
|
||||
// ESRCH 3
|
||||
static_cstr!("No such process"),
|
||||
// EINTR 4
|
||||
static_cstr!("Interrupted system call"),
|
||||
// EIO 5
|
||||
static_cstr!("Input/output error"),
|
||||
// ENXIO 6
|
||||
static_cstr!("I/O error"),
|
||||
static_cstr!("No such device or address"),
|
||||
// E2BIG 7
|
||||
static_cstr!("Argument list too long"),
|
||||
// ENOEXEC 8
|
||||
static_cstr!("Exec format error"),
|
||||
// EBADF 9
|
||||
static_cstr!("Bad file descriptor"),
|
||||
// ECHILD 10
|
||||
static_cstr!("No child processses"),
|
||||
// EAGAIN 11
|
||||
static_cstr!("Resource temporarily unavailable"),
|
||||
// ENOMEM 12
|
||||
static_cstr!("Cannot allocate memory"),
|
||||
// EACCES 13
|
||||
static_cstr!("Bad file number"),
|
||||
static_cstr!("No child process"),
|
||||
static_cstr!("Try again"),
|
||||
static_cstr!("Out of memory"),
|
||||
static_cstr!("Permission denied"),
|
||||
// EFAULT 14
|
||||
static_cstr!("Bad address"),
|
||||
// ENOTBLK 15
|
||||
static_cstr!("Block device required"),
|
||||
// EBUSY 16
|
||||
static_cstr!("Device or resource busy"),
|
||||
// EEXIST 17
|
||||
static_cstr!("File exists"),
|
||||
// EXDEV 18
|
||||
static_cstr!("Invalid cross-device link"),
|
||||
// ENODEV 19
|
||||
static_cstr!("Cross-device link"),
|
||||
static_cstr!("No such device"),
|
||||
// ENOTDIR 20
|
||||
static_cstr!("Not a directory"),
|
||||
// EISDIR 21
|
||||
static_cstr!("Is a directory"),
|
||||
// EINVAL 22
|
||||
static_cstr!("Invalid argument"),
|
||||
// ENFILE 23
|
||||
static_cstr!("Too many open files in system"),
|
||||
// EMFILE 24
|
||||
static_cstr!("File table overflow"),
|
||||
static_cstr!("Too many open files"),
|
||||
// ENOTTY 25
|
||||
static_cstr!("Inappropriate ioctl for device"),
|
||||
// ETXTBSY 26
|
||||
static_cstr!("Not a typewriter"),
|
||||
static_cstr!("Text file busy"),
|
||||
// EFBIG 27
|
||||
static_cstr!("File too large"),
|
||||
// ENOSPC 28
|
||||
static_cstr!("No space left on device"),
|
||||
// ESPIPE 29
|
||||
static_cstr!("Illegal seek"),
|
||||
// EROFS 30
|
||||
static_cstr!("Read-only file system"),
|
||||
// EMLINK 31
|
||||
static_cstr!("Too many links"),
|
||||
// EPIPE 32
|
||||
static_cstr!("Broken pipe"),
|
||||
// EDOM 33
|
||||
static_cstr!("Numerical argument out of domain"),
|
||||
// ERANGE 34
|
||||
static_cstr!("Numerical result out of range"),
|
||||
static_cstr!("Math argument out of domain of func"),
|
||||
static_cstr!("Math result not representable"),
|
||||
static_cstr!("Resource deadlock would occur"),
|
||||
static_cstr!("File name too long"),
|
||||
static_cstr!("No record locks available"),
|
||||
static_cstr!("Invalid system call number"),
|
||||
static_cstr!("Directory not empty"),
|
||||
static_cstr!("Too many symbolic links encountered"),
|
||||
static_cstr!("Socket operation on non-socket"),
|
||||
static_cstr!("Destination address required"),
|
||||
static_cstr!("Message too long"),
|
||||
static_cstr!("Protocol wrong type for socket"),
|
||||
static_cstr!("Protocol not available"),
|
||||
static_cstr!("Protocol not supported"),
|
||||
static_cstr!("Socket type not supported"),
|
||||
static_cstr!("Operation not supported on transport endpoint"),
|
||||
static_cstr!("Protocol family not supported"),
|
||||
static_cstr!("Address family not supported by protocol"),
|
||||
static_cstr!("Address already in use"),
|
||||
static_cstr!("Cannot assign requested address"),
|
||||
static_cstr!("Network is down"),
|
||||
static_cstr!("Network is unreachable"),
|
||||
static_cstr!("Network dropped connection because of reset"),
|
||||
static_cstr!("Software caused connection abort"),
|
||||
static_cstr!("Connection reset by peer"),
|
||||
static_cstr!("No buffer space available"),
|
||||
static_cstr!("Transport endpoint is already connected"),
|
||||
static_cstr!("Transport endpoint is not connected"),
|
||||
static_cstr!("Cannot send after transport endpoint shutdown"),
|
||||
static_cstr!("Connection timed out"),
|
||||
static_cstr!("Connection refused"),
|
||||
static_cstr!("Host is down"),
|
||||
static_cstr!("No route to host"),
|
||||
// Custom errnos
|
||||
static_cstr!("Operation not supported"),
|
||||
static_cstr!("Operation timed out"),
|
||||
];
|
||||
|
||||
impl Errno {
|
||||
pub fn to_c_str(&self) -> &CStr {
|
||||
ERRNO_STRINGS
|
||||
.get(self.0 as usize)
|
||||
.copied()
|
||||
.unwrap_or(SUCCESS)
|
||||
}
|
||||
|
||||
pub fn from_c_int(v: c_int) -> Option<Self> {
|
||||
if !(0..=MAX_ERROR.0).contains(&v) {
|
||||
None
|
||||
} else {
|
||||
Some(Self(v))
|
||||
}
|
||||
pub fn to_c_str(self) -> &'static CStr {
|
||||
let index = self as usize;
|
||||
ERRNO_STRINGS.get(index).copied().unwrap_or(UNKNOWN_ERROR)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<yggdrasil_rt::Error> for Errno {
|
||||
fn from(value: yggdrasil_rt::Error) -> Self {
|
||||
use yggdrasil_rt::Error as E;
|
||||
use yggdrasil_rt::Error;
|
||||
|
||||
match value {
|
||||
E::TimedOut => todo!(),
|
||||
E::MissingData => todo!(),
|
||||
// TODO ???
|
||||
E::InvalidMemoryOperation => EPERM,
|
||||
// TODO ???
|
||||
E::NotImplemented => EPERM,
|
||||
// TODO ???
|
||||
E::DirectoryNotEmpty => EISDIR,
|
||||
// TODO ???
|
||||
E::WouldBlock => EAGAIN,
|
||||
// TODO ???
|
||||
E::InvalidOperation => EPERM,
|
||||
E::DoesNotExist => ENOENT,
|
||||
E::AlreadyExists => EEXIST,
|
||||
E::InvalidArgument => EINVAL,
|
||||
E::NotADirectory => ENOTDIR,
|
||||
E::PermissionDenied => EACCES,
|
||||
E::UnrecognizedExecutable => ENOEXEC,
|
||||
E::ReadOnly => EROFS,
|
||||
E::OutOfMemory => ENOMEM,
|
||||
E::InvalidFile => EBADF,
|
||||
E::Interrupted => EINTR,
|
||||
E::IsADirectory => EISDIR,
|
||||
|
||||
_ => todo!()
|
||||
Error::OutOfMemory => Errno::ENOMEM,
|
||||
Error::AlreadyExists => Errno::EEXIST,
|
||||
Error::NotImplemented => Errno::ENOTSUPP,
|
||||
Error::DoesNotExist => Errno::ENOENT,
|
||||
Error::InvalidFile => Errno::EBADF,
|
||||
Error::InvalidArgument => Errno::EINVAL,
|
||||
Error::Interrupted => Errno::EINTR,
|
||||
Error::WouldBlock => Errno::EAGAIN,
|
||||
Error::UnrecognizedExecutable => Errno::ENOEXEC,
|
||||
Error::InvalidOperation => Errno::EPERM,
|
||||
Error::InvalidMemoryOperation => Errno::EPERM,
|
||||
Error::NotADirectory => Errno::ENOTDIR,
|
||||
Error::IsADirectory => Errno::EISDIR,
|
||||
Error::ReadOnly => Errno::EROFS,
|
||||
Error::PermissionDenied => Errno::EACCES,
|
||||
Error::AddrInUse => Errno::EADDRINUSE,
|
||||
Error::QueueFull => Errno::ENOBUFS,
|
||||
Error::BufferTooSmall => Errno::ENOMEM,
|
||||
Error::ConnectionReset => Errno::ECONNRESET,
|
||||
Error::MissingData => Errno::EINVAL,
|
||||
Error::NetworkUnreachable => Errno::ENETUNREACH,
|
||||
Error::TimedOut => Errno::ETIMEOUT,
|
||||
Error::ConnectionRefused => Errno::ECONNREFUSED,
|
||||
Error::HostUnreachable => Errno::EHOSTUNREACH,
|
||||
Error::UndefinedSyscall => Errno::ENOSYS,
|
||||
Error::DirectoryNotEmpty => Errno::ENOTEMPTY,
|
||||
Error::NotConnected => Errno::ENOTCONN,
|
||||
Error::ProcessNotFound => Errno::ESRCH,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -9,7 +9,7 @@ use crate::{
|
||||
};
|
||||
|
||||
use super::{
|
||||
errno,
|
||||
errno::Errno,
|
||||
sys_types::{mode_t, off_t, pid_t},
|
||||
};
|
||||
|
||||
@ -107,7 +107,7 @@ fn open_opts(opts: c_int, ap: &mut VaList) -> EResult<OpenMode> {
|
||||
O_EXEC => todo!(),
|
||||
O_SEARCH => todo!(),
|
||||
_ => {
|
||||
return EResult::Err(errno::EINVAL);
|
||||
return EResult::Err(Errno::EINVAL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -182,10 +182,10 @@ unsafe extern "C" fn openat(
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn faccessat(
|
||||
atfd: c_int,
|
||||
path: *const c_char,
|
||||
mode: c_int,
|
||||
flags: c_int,
|
||||
_atfd: c_int,
|
||||
_path: *const c_char,
|
||||
_mode: c_int,
|
||||
_flags: c_int,
|
||||
) -> c_int {
|
||||
todo!()
|
||||
}
|
||||
|
@ -6,11 +6,7 @@ use core::{
|
||||
use crate::{
|
||||
error::{self, CIntZeroResult, CResult, OptionExt},
|
||||
headers::{
|
||||
errno,
|
||||
pthread::{PTHREAD_CREATE_JOINABLE, PTHREAD_INHERIT_SCHED, PTHREAD_SCOPE_PROCESS},
|
||||
sched::{__ygg_sched_param_t, SCHED_RR},
|
||||
sys_time::timespec,
|
||||
sys_types::pthread_attr_t,
|
||||
errno::Errno, pthread::{PTHREAD_CREATE_JOINABLE, PTHREAD_INHERIT_SCHED, PTHREAD_SCOPE_PROCESS}, sched::{__ygg_sched_param_t, SCHED_RR}, sys_time::timespec, sys_types::pthread_attr_t
|
||||
},
|
||||
thread,
|
||||
util::PointerExt,
|
||||
@ -192,13 +188,13 @@ unsafe extern "C" fn pthread_attr_setstack(
|
||||
size: usize,
|
||||
) -> CIntZeroResult {
|
||||
let attr = attr.ensure_mut();
|
||||
let stack = NonNull::new(stack).e_ok_or(errno::EINVAL)?;
|
||||
let stack = NonNull::new(stack).e_ok_or(Errno::EINVAL)?;
|
||||
if size >= thread::MIN_STACK_SIZE {
|
||||
attr.stack = Some(stack);
|
||||
attr.stack_size = size;
|
||||
CIntZeroResult::SUCCESS
|
||||
} else {
|
||||
error::errno = errno::EINVAL;
|
||||
error::errno = Errno::EINVAL;
|
||||
CIntZeroResult::ERROR
|
||||
}
|
||||
}
|
||||
@ -213,7 +209,7 @@ unsafe extern "C" fn pthread_attr_setstacksize(
|
||||
attr.stack_size = size;
|
||||
CIntZeroResult::SUCCESS
|
||||
} else {
|
||||
error::errno = errno::EINVAL;
|
||||
error::errno = Errno::EINVAL;
|
||||
CIntZeroResult::ERROR
|
||||
}
|
||||
}
|
||||
|
@ -11,7 +11,7 @@ use yggdrasil_rt::process::MutexOperation;
|
||||
use crate::{
|
||||
error::{self, CIntZeroResult, CResult},
|
||||
headers::{
|
||||
errno,
|
||||
errno::Errno,
|
||||
sys_types::{pthread_barrier_t, pthread_barrierattr_t},
|
||||
},
|
||||
util::PointerExt,
|
||||
@ -113,7 +113,7 @@ unsafe extern "C" fn pthread_barrierattr_setpshared(
|
||||
CIntZeroResult::SUCCESS
|
||||
} else {
|
||||
yggdrasil_rt::debug_trace!("TODO: pthread_barrierattr_setpshared()");
|
||||
error::errno = errno::EINVAL;
|
||||
error::errno = Errno::EINVAL;
|
||||
CIntZeroResult::ERROR
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,7 @@ use yggdrasil_rt::process::MutexOperation;
|
||||
use crate::{
|
||||
error::{self, CIntZeroResult, CResult, EResult},
|
||||
headers::{
|
||||
errno,
|
||||
errno::Errno,
|
||||
sys_time::__ygg_timespec_t,
|
||||
sys_types::{clockid_t, pthread_cond_t, pthread_condattr_t, pthread_mutex_t},
|
||||
time::CLOCK_MONOTONIC,
|
||||
@ -151,7 +151,7 @@ unsafe extern "C" fn pthread_condattr_setclock(
|
||||
CIntZeroResult::SUCCESS
|
||||
} else {
|
||||
yggdrasil_rt::debug_trace!("TODO: pthread_condattr_setclock()");
|
||||
error::errno = errno::EINVAL;
|
||||
error::errno = Errno::EINVAL;
|
||||
CIntZeroResult::ERROR
|
||||
}
|
||||
}
|
||||
@ -165,7 +165,7 @@ unsafe extern "C" fn pthread_condattr_setpshared(
|
||||
CIntZeroResult::SUCCESS
|
||||
} else {
|
||||
yggdrasil_rt::debug_trace!("TODO: pthread_condattr_setpshared()");
|
||||
error::errno = errno::EINVAL;
|
||||
error::errno = Errno::EINVAL;
|
||||
CIntZeroResult::ERROR
|
||||
}
|
||||
}
|
||||
|
@ -1,15 +1,11 @@
|
||||
use core::{
|
||||
ffi::c_int,
|
||||
ptr::NonNull,
|
||||
sync::atomic::{AtomicU32, Ordering},
|
||||
};
|
||||
use core::{ffi::c_int, ptr::NonNull, sync::atomic::Ordering};
|
||||
|
||||
use yggdrasil_rt::process::MutexOperation;
|
||||
|
||||
use crate::{
|
||||
error::{self, CIntZeroResult, CResult, EResult},
|
||||
headers::{
|
||||
errno,
|
||||
errno::Errno,
|
||||
pthread::{
|
||||
PTHREAD_MUTEX_NORMAL, PTHREAD_MUTEX_STALLED, PTHREAD_PRIO_NONE, PTHREAD_PROCESS_PRIVATE,
|
||||
},
|
||||
@ -25,22 +21,6 @@ use super::{PTHREAD_MUTEX_DEFAULT, PTHREAD_MUTEX_RECURSIVE};
|
||||
impl pthread_mutex_t {
|
||||
const LOCKED: u32 = 1;
|
||||
|
||||
// fn new() -> EResult<Self> {
|
||||
// Self::new_with(&pthread_mutexattr_t::default())
|
||||
// }
|
||||
|
||||
// fn new_with(attr: &pthread_mutexattr_t) -> EResult<Self> {
|
||||
// match attr.__mode {
|
||||
// PTHREAD_MUTEX_NORMAL | PTHREAD_MUTEX_RECURSIVE => (),
|
||||
// _ => return EResult::Err(errno::EINVAL)
|
||||
// }
|
||||
// EResult::Ok(Self {
|
||||
// __mode: attr.__mode,
|
||||
// __state: AtomicU32::new(0),
|
||||
// __recursion: AtomicU32::new(0)
|
||||
// })
|
||||
// }
|
||||
|
||||
fn try_lock(&self) -> EResult<bool> {
|
||||
match self.__mode {
|
||||
PTHREAD_MUTEX_NORMAL => EResult::Ok(
|
||||
@ -54,23 +34,26 @@ impl pthread_mutex_t {
|
||||
thread_id = u32::MAX;
|
||||
}
|
||||
|
||||
match self.__state.compare_exchange(0, thread_id, Ordering::Acquire, Ordering::Relaxed) {
|
||||
match self.__state.compare_exchange(
|
||||
0,
|
||||
thread_id,
|
||||
Ordering::Acquire,
|
||||
Ordering::Relaxed,
|
||||
) {
|
||||
// 0 -> thread_id
|
||||
Ok(_) => {
|
||||
self.__recursion.fetch_add(1, Ordering::Relaxed);
|
||||
EResult::Ok(true)
|
||||
},
|
||||
}
|
||||
Err(t) if t == thread_id => {
|
||||
self.__recursion.fetch_add(1, Ordering::Relaxed);
|
||||
EResult::Ok(true)
|
||||
}
|
||||
// Other thread owns the lock
|
||||
Err(_) => {
|
||||
EResult::Ok(false)
|
||||
}
|
||||
Err(_) => EResult::Ok(false),
|
||||
}
|
||||
}
|
||||
_ => EResult::Err(errno::EINVAL),
|
||||
_ => EResult::Err(Errno::EINVAL),
|
||||
}
|
||||
}
|
||||
|
||||
@ -78,7 +61,7 @@ impl pthread_mutex_t {
|
||||
if self.try_lock()? {
|
||||
EResult::Ok(())
|
||||
} else {
|
||||
EResult::Err(errno::EBUSY)
|
||||
EResult::Err(Errno::EBUSY)
|
||||
}
|
||||
}
|
||||
|
||||
@ -114,8 +97,8 @@ impl pthread_mutex_t {
|
||||
yggdrasil_rt::sys::mutex(&self.__state, &MutexOperation::Wake(1)).ok();
|
||||
}
|
||||
EResult::Ok(())
|
||||
},
|
||||
_ => EResult::Err(errno::EINVAL),
|
||||
}
|
||||
_ => EResult::Err(Errno::EINVAL),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -123,7 +106,7 @@ impl pthread_mutex_t {
|
||||
impl Default for pthread_mutexattr_t {
|
||||
fn default() -> Self {
|
||||
Self {
|
||||
__mode: PTHREAD_MUTEX_DEFAULT
|
||||
__mode: PTHREAD_MUTEX_DEFAULT,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -303,7 +286,7 @@ unsafe extern "C" fn pthread_mutexattr_setprotocol(
|
||||
CIntZeroResult::SUCCESS
|
||||
} else {
|
||||
yggdrasil_rt::debug_trace!("TODO: pthread_mutexattr_setprotocol()");
|
||||
error::errno = errno::EINVAL;
|
||||
error::errno = Errno::EINVAL;
|
||||
CIntZeroResult::ERROR
|
||||
}
|
||||
}
|
||||
@ -317,7 +300,7 @@ unsafe extern "C" fn pthread_mutexattr_setpshared(
|
||||
CIntZeroResult::SUCCESS
|
||||
} else {
|
||||
yggdrasil_rt::debug_trace!("TODO: pthread_mutexattr_setpshared()");
|
||||
error::errno = errno::EINVAL;
|
||||
error::errno = Errno::EINVAL;
|
||||
CIntZeroResult::ERROR
|
||||
}
|
||||
}
|
||||
@ -331,7 +314,7 @@ unsafe extern "C" fn pthread_mutexattr_setrobust(
|
||||
CIntZeroResult::SUCCESS
|
||||
} else {
|
||||
yggdrasil_rt::debug_trace!("TODO: pthread_mutexattr_setrobust()");
|
||||
error::errno = errno::EINVAL;
|
||||
error::errno = Errno::EINVAL;
|
||||
CIntZeroResult::ERROR
|
||||
}
|
||||
}
|
||||
@ -348,7 +331,7 @@ unsafe extern "C" fn pthread_mutexattr_settype(
|
||||
CIntZeroResult::SUCCESS
|
||||
}
|
||||
_ => {
|
||||
error::errno = errno::EINVAL;
|
||||
error::errno = Errno::EINVAL;
|
||||
CIntZeroResult::ERROR
|
||||
}
|
||||
}
|
||||
|
@ -4,7 +4,7 @@ use yggdrasil_rt::process::thread_local;
|
||||
|
||||
use crate::{
|
||||
error::{self, CIntZeroResult, ResultExt},
|
||||
headers::{errno, sys_types::pthread_key_t},
|
||||
headers::{errno::Errno, sys_types::pthread_key_t},
|
||||
util::PointerExt,
|
||||
};
|
||||
|
||||
@ -29,13 +29,13 @@ unsafe extern "C" fn pthread_key_delete(_key: pthread_key_t) -> CIntZeroResult {
|
||||
unsafe extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void {
|
||||
let dtv = thread_local::get_dtv();
|
||||
if key == 0 {
|
||||
error::errno = errno::EINVAL;
|
||||
error::errno = Errno::EINVAL;
|
||||
return null_mut();
|
||||
}
|
||||
match dtv.get_specific(key) {
|
||||
Some(value) => value,
|
||||
None => {
|
||||
error::errno = errno::EINVAL;
|
||||
error::errno = Errno::EINVAL;
|
||||
null_mut()
|
||||
}
|
||||
}
|
||||
@ -45,6 +45,6 @@ unsafe extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void {
|
||||
unsafe extern "C" fn pthread_setspecific(key: pthread_key_t, value: *mut c_void) -> CIntZeroResult {
|
||||
let dtv = thread_local::get_dtv();
|
||||
dtv.try_set_specific(key, value, false)
|
||||
.e_map_err(|_| errno::EINVAL)?;
|
||||
.e_map_err(|_| Errno::EINVAL)?;
|
||||
CIntZeroResult::SUCCESS
|
||||
}
|
||||
|
@ -1,11 +1,20 @@
|
||||
use core::{ffi::{c_char, c_int, c_long, c_void}, ptr::NonNull};
|
||||
use core::{
|
||||
ffi::{c_char, c_int, c_long, c_void},
|
||||
ptr::NonNull,
|
||||
};
|
||||
|
||||
use yggdrasil_rt::process::{Signal, signal as rt};
|
||||
use yggdrasil_rt::process::{signal as rt, Signal};
|
||||
|
||||
use crate::{error::{self, CIntZeroResult, CResult, EResult, TryFromExt}, signal, util::PointerExt};
|
||||
use crate::{
|
||||
error::{self, CIntZeroResult, CResult, EResult, TryFromExt},
|
||||
headers::errno::Errno,
|
||||
signal,
|
||||
util::PointerExt,
|
||||
};
|
||||
|
||||
use super::{
|
||||
errno, sys_time::__ygg_timespec_t, sys_types::{pid_t, uid_t}
|
||||
sys_time::__ygg_timespec_t,
|
||||
sys_types::{pid_t, uid_t},
|
||||
};
|
||||
|
||||
pub type sig_handler_t = unsafe extern "C" fn(SigNumber);
|
||||
@ -134,7 +143,7 @@ impl TryFromExt<SigNumber> for Signal {
|
||||
SigNumber::SIGILL => EResult::Ok(Signal::InvalidInstruction),
|
||||
SigNumber::SIGKILL => EResult::Ok(Signal::Killed),
|
||||
SigNumber::SIGTERM => EResult::Ok(Signal::Terminated),
|
||||
_ => EResult::Err(errno::EINVAL)
|
||||
_ => EResult::Err(Errno::EINVAL),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -149,7 +158,7 @@ impl From<Signal> for SigNumber {
|
||||
Signal::Killed => Self::SIGKILL,
|
||||
Signal::Terminated => Self::SIGTERM,
|
||||
// Never issued/handled
|
||||
Signal::Debug => unreachable!()
|
||||
Signal::Debug => unreachable!(),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -213,12 +222,16 @@ unsafe extern "C" fn sigaddset(_mask: *mut sigset_t, _signum: c_int) -> c_int {
|
||||
unsafe extern "C" fn sigaltstack(new: *const stack_t, old: *mut stack_t) -> CIntZeroResult {
|
||||
if let Some(old) = NonNull::new(old) {
|
||||
let (base, size) = rt::get_signal_stack();
|
||||
old.write(stack_t { ss_sp: base as _, ss_flags: 0, ss_size: size });
|
||||
old.write(stack_t {
|
||||
ss_sp: base as _,
|
||||
ss_flags: 0,
|
||||
ss_size: size,
|
||||
});
|
||||
}
|
||||
if let Some(new) = new.as_ref() {
|
||||
// TODO what do with SS_DISABLE?
|
||||
if new.ss_size < MINSIGSTKSZ {
|
||||
error::errno = errno::ENOMEM;
|
||||
error::errno = Errno::ENOMEM;
|
||||
return CIntZeroResult::ERROR;
|
||||
}
|
||||
rt::set_signal_stack(new.ss_sp.addr(), new.ss_size);
|
||||
@ -270,7 +283,7 @@ unsafe extern "C" fn signal(handler: sig_handler_t, signum: SigNumber) -> sig_ha
|
||||
// NULL or SIG_ERR
|
||||
if address == 0 || address == 1 {
|
||||
yggdrasil_rt::debug_trace!("libc: signal() was passed an invalid handler");
|
||||
error::errno = errno::EINVAL;
|
||||
error::errno = Errno::EINVAL;
|
||||
// SIG_ERR
|
||||
return core::mem::transmute(1usize);
|
||||
}
|
||||
|
@ -15,7 +15,7 @@ use crate::{
|
||||
CEofResult, CFdResult, CIntZeroResult, COffsetResult, CPtrResult, CResult, EResult,
|
||||
ResultExt, TryFromExt,
|
||||
},
|
||||
headers::{errno, sys_types::off_t},
|
||||
headers::{errno::Errno, sys_types::off_t},
|
||||
io::{
|
||||
self,
|
||||
managed::{FileOpenSource, FILE},
|
||||
@ -148,7 +148,7 @@ unsafe extern "C" fn fopen(path: *const c_char, mode: *const c_char) -> CPtrResu
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn fseek(fp: *mut FILE, offset: c_long, whence: c_int) -> CIntZeroResult {
|
||||
let offset: off_t = offset.try_into().e_map_err(|_| errno::EINVAL)?;
|
||||
let offset: off_t = offset.try_into().e_map_err(|_| Errno::EINVAL)?;
|
||||
fseeko(fp, offset, whence)
|
||||
}
|
||||
|
||||
|
@ -8,7 +8,7 @@ use core::{
|
||||
use crate::{
|
||||
allocator,
|
||||
error::{CEofResult, CIsizeResult, CPtrResult, CResult, EResult},
|
||||
headers::errno,
|
||||
headers::errno::Errno,
|
||||
io::{
|
||||
managed::{stdin, stdout, FILE},
|
||||
Read, Write,
|
||||
@ -154,8 +154,8 @@ unsafe extern "C" fn puts(str: *const c_char) -> CEofResult {
|
||||
yggdrasil_rt::sys::write(RawFd::STDOUT, b"\n").ok();
|
||||
}
|
||||
|
||||
return CEofResult::success(0)
|
||||
},
|
||||
return CEofResult::success(0);
|
||||
}
|
||||
};
|
||||
out.write_all(str.to_bytes())?;
|
||||
out.write_all(b"\n")?;
|
||||
@ -241,7 +241,7 @@ fn getdelim_inner(
|
||||
|
||||
if writer.position == 0 {
|
||||
// EOF reached before anything could be read
|
||||
return (writer, EResult::Err(errno::ESUCCESS));
|
||||
return (writer, EResult::Err(Errno::ESUCCESS));
|
||||
}
|
||||
|
||||
match writer.putc(0) {
|
||||
|
@ -2,7 +2,7 @@ use core::{ffi::c_double, fmt, num::FpCategory};
|
||||
|
||||
use alloc::{format, string::String};
|
||||
|
||||
use crate::{error::EResult, headers::errno, io::Write};
|
||||
use crate::{error::EResult, headers::errno::Errno, io::Write};
|
||||
|
||||
use super::format::FmtOpts;
|
||||
|
||||
@ -49,7 +49,7 @@ fn fmt_float_exp<W: Write + fmt::Write>(
|
||||
match write!(output, "{}{:+03}", exp_fmt as char, exp) {
|
||||
Ok(()) => (),
|
||||
// TODO proper error code
|
||||
Err(_) => return EResult::Err(errno::EINVAL),
|
||||
Err(_) => return EResult::Err(Errno::EINVAL),
|
||||
};
|
||||
|
||||
EResult::Ok(f_len + 2 + 2.max(exp_len))
|
||||
|
@ -6,8 +6,9 @@ use reader::{GetChar, ScanReader};
|
||||
|
||||
use crate::{
|
||||
error::{CEofResult, EResult},
|
||||
headers::errno::{self, Errno},
|
||||
io::managed::{stdin, FILE}, util::{PointerExt, PointerStrExt},
|
||||
headers::errno::Errno,
|
||||
io::managed::{stdin, FILE},
|
||||
util::{PointerExt, PointerStrExt},
|
||||
};
|
||||
|
||||
mod char_set;
|
||||
@ -121,7 +122,7 @@ fn scanf_inner<G: GetChar>(
|
||||
b'[' => {
|
||||
let (new_it, set) = match ScanCharSet::from_format_iter(it) {
|
||||
Ok(v) => v,
|
||||
Err(FormatError) => return EResult::Err(errno::ESUCCESS),
|
||||
Err(FormatError) => return EResult::Err(Errno::ESUCCESS),
|
||||
};
|
||||
it = new_it;
|
||||
ScanSpec::Chars(set)
|
||||
@ -132,11 +133,11 @@ fn scanf_inner<G: GetChar>(
|
||||
b'%' => ScanSpec::Percent,
|
||||
b'f' | b'e' | b'g' | b'E' | b'a' => todo!(),
|
||||
// Unrecognized specifier
|
||||
_ => return EResult::Err(errno::ESUCCESS),
|
||||
_ => return EResult::Err(Errno::ESUCCESS),
|
||||
}
|
||||
} else {
|
||||
// No specifier after %
|
||||
return EResult::Err(errno::ESUCCESS);
|
||||
return EResult::Err(Errno::ESUCCESS);
|
||||
};
|
||||
|
||||
matched += match opts.scan(stream, spec, &mut ap) {
|
||||
@ -157,11 +158,7 @@ unsafe extern "C" fn scanf(format: *const c_char, mut args: ...) -> CEofResult {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn fscanf(
|
||||
fp: *mut FILE,
|
||||
format: *const c_char,
|
||||
mut args: ...
|
||||
) -> CEofResult {
|
||||
unsafe extern "C" fn fscanf(fp: *mut FILE, format: *const c_char, mut args: ...) -> CEofResult {
|
||||
vfscanf(fp, format, args.as_va_list())
|
||||
}
|
||||
|
||||
@ -171,11 +168,7 @@ unsafe extern "C" fn vscanf(format: *const c_char, args: VaList) -> CEofResult {
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn vfscanf(
|
||||
fp: *mut FILE,
|
||||
format: *const c_char,
|
||||
args: VaList,
|
||||
) -> CEofResult {
|
||||
unsafe extern "C" fn vfscanf(fp: *mut FILE, format: *const c_char, args: VaList) -> CEofResult {
|
||||
let fp = fp.ensure_mut();
|
||||
let format = format.ensure_cstr();
|
||||
let mut reader = ScanReader::new(fp);
|
||||
|
@ -6,12 +6,12 @@ use core::{
|
||||
use crate::{
|
||||
allocator,
|
||||
error::{CPtrResult, OptionExt},
|
||||
headers::errno,
|
||||
headers::errno::Errno,
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn calloc(size: usize, nmemb: usize) -> CPtrResult<c_void> {
|
||||
let size = size.checked_mul(nmemb).e_ok_or(errno::ENOMEM)?;
|
||||
let size = size.checked_mul(nmemb).e_ok_or(Errno::ENOMEM)?;
|
||||
let ptr = allocator::c_alloc(size, 16, true)?;
|
||||
CPtrResult::success(ptr)
|
||||
}
|
||||
|
@ -4,11 +4,7 @@ use core::{
|
||||
};
|
||||
|
||||
use crate::{
|
||||
env,
|
||||
error::{CIntZeroResult, CPtrResult, CResult, OptionExt},
|
||||
headers::errno,
|
||||
process,
|
||||
util::PointerStrExt,
|
||||
env, error::{CIntZeroResult, CPtrResult, CResult, OptionExt}, headers::errno::Errno, process, util::PointerStrExt
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
@ -45,7 +41,7 @@ unsafe extern "C" fn getenv(name: *const c_char) -> CPtrResult<c_char> {
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn putenv(value: *mut c_char) -> CIntZeroResult {
|
||||
let value = NonNull::new(value).e_ok_or(errno::EINVAL)?;
|
||||
let value = NonNull::new(value).e_ok_or(Errno::EINVAL)?;
|
||||
env::put_env(value)?;
|
||||
CIntZeroResult::SUCCESS
|
||||
}
|
||||
@ -57,7 +53,7 @@ unsafe extern "C" fn setenv(
|
||||
overwrite: c_int,
|
||||
) -> CIntZeroResult {
|
||||
let name = name.ensure_cstr().to_bytes();
|
||||
let value = NonNull::new(value.cast_mut()).e_ok_or(errno::EINVAL)?;
|
||||
let value = NonNull::new(value.cast_mut()).e_ok_or(Errno::EINVAL)?;
|
||||
let overwrite = overwrite != 0;
|
||||
env::set_env(name, value, overwrite)?;
|
||||
CIntZeroResult::SUCCESS
|
||||
|
@ -1,7 +1,7 @@
|
||||
language = "C"
|
||||
style = "Type"
|
||||
|
||||
sys_includes = ["stddef.h", "locale.h", "strings.h"]
|
||||
sys_includes = ["stddef.h", "locale.h", "strings.h", "errno.h"]
|
||||
no_includes = true
|
||||
|
||||
include_guard = "_STRING_H"
|
||||
|
@ -7,10 +7,7 @@ use core::{
|
||||
use crate::{
|
||||
allocator,
|
||||
error::CPtrResult,
|
||||
headers::{
|
||||
errno::{self, Errno},
|
||||
locale::locale_t,
|
||||
},
|
||||
headers::{errno::Errno, locale::locale_t},
|
||||
};
|
||||
|
||||
use super::mem::{memcpy, mempcpy, memset};
|
||||
@ -99,23 +96,19 @@ unsafe extern "C" fn strdup(s: *const c_char) -> CPtrResult<c_char> {
|
||||
CPtrResult::success(data.cast())
|
||||
}
|
||||
|
||||
unsafe fn strerror_inner(e: c_int) -> *const c_char {
|
||||
if let Some(errno) = Errno::from_c_int(e) {
|
||||
errno.to_c_str().as_ptr()
|
||||
} else {
|
||||
errno::UNKNOWN_ERROR.as_ptr()
|
||||
}
|
||||
unsafe fn strerror_inner(e: Errno) -> *const c_char {
|
||||
e.to_c_str().as_ptr()
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strerror(e: c_int) -> *mut c_char {
|
||||
unsafe extern "C" fn strerror(e: Errno) -> *mut c_char {
|
||||
static mut BUF: [c_char; 128] = [0; 128];
|
||||
#[allow(static_mut_refs)]
|
||||
strerror_r(e, BUF.as_mut_ptr(), BUF.len())
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn strerror_r(e: c_int, buf: *mut c_char, n: usize) -> *mut c_char {
|
||||
unsafe extern "C" fn strerror_r(e: Errno, buf: *mut c_char, n: usize) -> *mut c_char {
|
||||
let source = strerror_inner(e);
|
||||
strncpy(buf, source, n)
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
use core::{ffi::{c_char, c_int, c_void}, ptr::null_mut};
|
||||
use core::ffi::{c_char, c_int, c_void};
|
||||
|
||||
use crate::error::CPtrResult;
|
||||
|
||||
|
@ -2,8 +2,9 @@ use core::{ffi::c_double, time::Duration};
|
||||
|
||||
use crate::{
|
||||
error::{self, CIntZeroResult, CResult},
|
||||
headers::{errno, sys_time::__ygg_timespec_t, sys_types::time_t},
|
||||
process, util::PointerExt,
|
||||
headers::{errno::Errno, sys_time::__ygg_timespec_t, sys_types::time_t},
|
||||
process,
|
||||
util::PointerExt,
|
||||
};
|
||||
|
||||
#[no_mangle]
|
||||
@ -15,14 +16,12 @@ unsafe extern "C" fn nanosleep(
|
||||
let amount = Duration::from(*rqtp);
|
||||
|
||||
match process::sleep(amount) {
|
||||
Ok(()) => {
|
||||
CIntZeroResult::SUCCESS
|
||||
}
|
||||
Ok(()) => CIntZeroResult::SUCCESS,
|
||||
Err(remaining) => {
|
||||
if let Some(rmtp) = rmtp.as_mut() {
|
||||
*rmtp = remaining.into();
|
||||
}
|
||||
error::errno = errno::EINTR;
|
||||
error::errno = Errno::EINTR;
|
||||
CIntZeroResult::ERROR
|
||||
}
|
||||
}
|
||||
|
@ -7,7 +7,10 @@ use yggdrasil_rt::debug_trace;
|
||||
|
||||
use crate::{
|
||||
error::{self, CIntCountResult, CIntZeroResult, ResultExt},
|
||||
headers::{errno, sys_types::{gid_t, pid_t, uid_t}},
|
||||
headers::{
|
||||
errno::Errno,
|
||||
sys_types::{gid_t, pid_t, uid_t},
|
||||
},
|
||||
process,
|
||||
};
|
||||
|
||||
@ -132,7 +135,7 @@ unsafe extern "C" fn sleep(seconds: c_uint) -> c_uint {
|
||||
match process::sleep(duration) {
|
||||
Ok(()) => 0,
|
||||
Err(remaining) => {
|
||||
error::errno = errno::EINTR;
|
||||
error::errno = Errno::EINTR;
|
||||
remaining.as_secs() as c_uint + (remaining.subsec_nanos() != 0) as c_uint
|
||||
}
|
||||
}
|
||||
@ -141,6 +144,6 @@ unsafe extern "C" fn sleep(seconds: c_uint) -> c_uint {
|
||||
#[no_mangle]
|
||||
unsafe extern "C" fn usleep(millis: c_uint) -> CIntZeroResult {
|
||||
let duration = Duration::from_millis(millis.try_into().unwrap());
|
||||
process::sleep(duration).e_map_err(|_| errno::EINTR)?;
|
||||
process::sleep(duration).e_map_err(|_| Errno::EINTR)?;
|
||||
CIntZeroResult::SUCCESS
|
||||
}
|
||||
|
@ -1,6 +1,6 @@
|
||||
use core::{ffi::c_char, ptr::NonNull, slice, str};
|
||||
|
||||
use crate::{error::EResult, headers::errno, types::wchar_t};
|
||||
use crate::{error::EResult, headers::errno::Errno, types::wchar_t};
|
||||
|
||||
use super::mbstate_t;
|
||||
|
||||
@ -40,11 +40,11 @@ pub unsafe fn mbrtowc(
|
||||
let size = utf8_char_width(src.cast::<u8>().read());
|
||||
// TODO EILSEQ
|
||||
if size > n || size == 0 {
|
||||
return EResult::Err(errno::EINVAL);
|
||||
return EResult::Err(Errno::EINVAL);
|
||||
}
|
||||
let slice = slice::from_raw_parts(src.cast::<u8>().as_ptr(), size);
|
||||
let Ok(decoded) = str::from_utf8(slice) else {
|
||||
return EResult::Err(errno::EINVAL);
|
||||
return EResult::Err(Errno::EINVAL);
|
||||
};
|
||||
|
||||
let result = decoded.chars().next().unwrap() as wchar_t;
|
||||
|
@ -7,7 +7,7 @@ use yggdrasil_rt::{
|
||||
sys as syscall,
|
||||
};
|
||||
|
||||
use crate::{error::EResult, headers::errno};
|
||||
use crate::{error::EResult, headers::errno::Errno};
|
||||
|
||||
use super::{AsRawFd, FromRawFd};
|
||||
|
||||
@ -34,7 +34,7 @@ impl DirReader {
|
||||
unsafe { syscall::close(fd) }?;
|
||||
EResult::Ok(())
|
||||
} else {
|
||||
EResult::Err(errno::EBADF)
|
||||
EResult::Err(Errno::EBADF)
|
||||
}
|
||||
}
|
||||
|
||||
@ -44,7 +44,7 @@ impl DirReader {
|
||||
|
||||
fn fill_buf(&mut self) -> EResult<&[DirectoryEntry]> {
|
||||
let Some(fd) = self.fd else {
|
||||
return EResult::Err(errno::EBADF);
|
||||
return EResult::Err(Errno::EBADF);
|
||||
};
|
||||
|
||||
if self.position == self.len {
|
||||
|
@ -18,8 +18,7 @@ use yggdrasil_rt::{
|
||||
use crate::{
|
||||
error::{EResult, TryFromExt},
|
||||
headers::{
|
||||
errno,
|
||||
stdio::{BUFSIZ, UNGETC_MAX, _IOFBF, _IOLBF, _IONBF},
|
||||
errno::Errno, stdio::{BUFSIZ, UNGETC_MAX, _IOFBF, _IOLBF, _IONBF}
|
||||
},
|
||||
};
|
||||
|
||||
@ -315,7 +314,7 @@ impl FILE {
|
||||
pub unsafe fn read_unlocked(&mut self, data: &mut [u8]) -> EResult<usize> {
|
||||
if !self.flags.contains(FileFlags::READ) {
|
||||
self.flags |= FileFlags::ERROR;
|
||||
return EResult::Err(errno::EBADF);
|
||||
return EResult::Err(Errno::EBADF);
|
||||
}
|
||||
|
||||
self.set_direction(Direction::Read)?;
|
||||
@ -351,7 +350,7 @@ impl FILE {
|
||||
pub unsafe fn write_unlocked(&mut self, data: &[u8]) -> EResult<usize> {
|
||||
if !self.flags.contains(FileFlags::WRITE) {
|
||||
self.flags |= FileFlags::ERROR;
|
||||
return EResult::Err(errno::EBADF);
|
||||
return EResult::Err(Errno::EBADF);
|
||||
}
|
||||
|
||||
self.set_direction(Direction::Write)?;
|
||||
@ -397,7 +396,7 @@ impl FILE {
|
||||
// ungetc() for write doesn't make any sense
|
||||
self.set_direction(Direction::Read)?;
|
||||
if self.ungetc.len() == UNGETC_MAX {
|
||||
return EResult::Err(errno::ENOMEM);
|
||||
return EResult::Err(Errno::ENOMEM);
|
||||
}
|
||||
self.ungetc.push(ch);
|
||||
EResult::Ok(())
|
||||
@ -413,7 +412,7 @@ impl FILE {
|
||||
|
||||
if self.last_operation.is_some() {
|
||||
self.flags |= FileFlags::ERROR;
|
||||
return EResult::Err(errno::EINVAL);
|
||||
return EResult::Err(Errno::EINVAL);
|
||||
}
|
||||
|
||||
self.ungetc.clear();
|
||||
@ -468,7 +467,7 @@ impl FILE {
|
||||
match self.last_operation.replace(direction) {
|
||||
Some(dir) if dir != direction => {
|
||||
self.flags |= FileFlags::ERROR;
|
||||
EResult::Err(errno::EINVAL)
|
||||
EResult::Err(Errno::EINVAL)
|
||||
}
|
||||
_ => EResult::Ok(()),
|
||||
}
|
||||
@ -561,7 +560,7 @@ impl TryFromExt<c_int> for BufferingMode {
|
||||
_IOFBF => EResult::Ok(Self::Full),
|
||||
_IOLBF => EResult::Ok(Self::Line),
|
||||
_IONBF => EResult::Ok(Self::None),
|
||||
_ => EResult::Err(errno::EINVAL),
|
||||
_ => EResult::Err(Errno::EINVAL),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -8,9 +8,7 @@ use yggdrasil_rt::{
|
||||
use crate::{
|
||||
error::{EResult, TryFromExt},
|
||||
headers::{
|
||||
errno,
|
||||
stdio::{SEEK_CUR, SEEK_END, SEEK_SET},
|
||||
sys_types::off_t,
|
||||
errno::Errno, stdio::{SEEK_CUR, SEEK_END, SEEK_SET}, sys_types::off_t
|
||||
},
|
||||
};
|
||||
|
||||
@ -31,7 +29,7 @@ pub trait Write {
|
||||
match self.write(data) {
|
||||
EResult::Ok(0) => todo!(),
|
||||
EResult::Ok(n) => pos += n,
|
||||
EResult::Err(err) if err == errno::EINTR => todo!(),
|
||||
EResult::Err(Errno::EINTR) => todo!(),
|
||||
EResult::Err(err) => return (pos, EResult::Err(err)),
|
||||
}
|
||||
}
|
||||
@ -89,7 +87,7 @@ impl TryFromExt<c_int> for RawFd {
|
||||
fn e_try_from(value: c_int) -> EResult<Self> {
|
||||
match value {
|
||||
0.. => EResult::Ok(unsafe { Self::from_raw(value as _) }),
|
||||
_ => EResult::Err(errno::EBADF),
|
||||
_ => EResult::Err(Errno::EBADF),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -100,13 +98,13 @@ impl TryFromExt<(off_t, c_int)> for SeekFrom {
|
||||
match whence {
|
||||
SEEK_SET => {
|
||||
if offset < 0 {
|
||||
return EResult::Err(errno::EINVAL);
|
||||
return EResult::Err(Errno::EINVAL);
|
||||
}
|
||||
EResult::Ok(Self::Start(offset as _))
|
||||
}
|
||||
SEEK_CUR => EResult::Ok(Self::Current(offset)),
|
||||
SEEK_END => EResult::Ok(Self::End(offset)),
|
||||
_ => EResult::Err(errno::EINVAL),
|
||||
_ => EResult::Err(Errno::EINVAL),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -12,8 +12,7 @@ use yggdrasil_rt::{
|
||||
use crate::{
|
||||
error::{EResult, OptionExt},
|
||||
headers::{
|
||||
errno,
|
||||
sys_types::{pthread_attr_t, pthread_t},
|
||||
errno::Errno, sys_types::{pthread_attr_t, pthread_t}
|
||||
},
|
||||
};
|
||||
|
||||
@ -49,6 +48,7 @@ impl Thread {
|
||||
let info = ThreadCreateInfo {
|
||||
signal_stack: rt::ThreadSignalStack::Allocate(DEFAULT_SIGNAL_STACK_SIZE),
|
||||
stack,
|
||||
#[allow(clippy::redundant_closure)]
|
||||
entry: rt::ThreadFunction::Closure(Box::new(move |arg| entry(arg))),
|
||||
tls_image: tls::TLS_IMAGE.get().as_ref(),
|
||||
};
|
||||
@ -59,7 +59,7 @@ impl Thread {
|
||||
}
|
||||
|
||||
pub fn join(id: pthread_t) -> EResult<*mut c_void> {
|
||||
let thread = THREADS.lock().remove(&id).e_ok_or(errno::EINVAL)?;
|
||||
let thread = THREADS.lock().remove(&id).e_ok_or(Errno::EINVAL)?;
|
||||
// TODO handle EINTR during join
|
||||
let result = thread.handle.join_uninterruptible().unwrap_or(null_mut());
|
||||
EResult::Ok(result)
|
||||
|
@ -1,12 +1,15 @@
|
||||
use core::{
|
||||
ffi::{c_char, c_int, CStr}, fmt, panic::Location, ptr::NonNull
|
||||
ffi::{c_char, c_int, CStr},
|
||||
fmt,
|
||||
panic::Location,
|
||||
ptr::NonNull,
|
||||
};
|
||||
|
||||
use yggdrasil_rt::io::RawFd;
|
||||
|
||||
use crate::{
|
||||
error::{EResult, TryFromExt},
|
||||
headers::{errno, fcntl::AT_FDCWD},
|
||||
headers::{errno::Errno, fcntl::AT_FDCWD},
|
||||
};
|
||||
|
||||
pub trait PointerExt {
|
||||
@ -124,7 +127,7 @@ pub fn at_fd(fd: c_int) -> EResult<Option<RawFd>> {
|
||||
match fd {
|
||||
AT_FDCWD => EResult::Ok(None),
|
||||
0.. => RawFd::e_try_from(fd).map(Some),
|
||||
_ => EResult::Err(errno::EBADF),
|
||||
_ => EResult::Err(Errno::EBADF),
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,7 +146,5 @@ pub unsafe fn cstr_prefix<F: Fn(u8, u8) -> bool>(a: NonNull<u8>, b: &[u8], cmp:
|
||||
// }
|
||||
|
||||
pub unsafe fn cstr_matches_insensitive(a: NonNull<u8>, b: &[u8]) -> bool {
|
||||
cstr_prefix(a, b, |a, b| {
|
||||
u8::eq_ignore_ascii_case(&a, &b)
|
||||
})
|
||||
cstr_prefix(a, b, |a, b| u8::eq_ignore_ascii_case(&a, &b))
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user