libc: fix missing bits

This commit is contained in:
2025-03-09 21:45:32 +02:00
parent c5994dd390
commit 4798240473
26 changed files with 102 additions and 56 deletions
+4 -1
View File
@@ -5,7 +5,10 @@
extern "C" {
#endif
extern _Thread_local int errno;
extern _Thread_local int __errno;
#undef errno
#define errno __errno
extern char *program_invocation_short_name;
extern char *program_invocation_name;
@@ -7,9 +7,11 @@ extern "C" {
int setjmp(jmp_buf buf);
int _setjmp(jmp_buf buf);
int sigsetjmp(sigjmp_buf buf, int savesigs);
[[noreturn]] void longjmp(jmp_buf buf, int val);
[[noreturn]] void _longjmp(jmp_buf buf, int val);
[[noreturn]] void siglongjmp(sigjmp_buf buf, int val);
#if defined(__cplusplus)
}
@@ -0,0 +1,4 @@
#ifndef _SYS_PARAM_H
#define _SYS_PARAM_H 1
#endif
+12 -10
View File
@@ -14,9 +14,7 @@ macro impl_from_residual($($ty:ty),+) {
impl FromResidual<EResult<Infallible>> for $ty {
fn from_residual(residual: EResult<Infallible>) -> Self {
let err = residual.unwrap_err();
unsafe {
errno = err;
}
crate::error::set_errno(err);
Self::ERROR
}
}
@@ -26,7 +24,7 @@ macro impl_from_residual($($ty:ty),+) {
#[thread_local]
#[no_mangle]
#[allow(non_upper_case_globals)]
pub static mut errno: Errno = Errno::ESUCCESS;
static mut __errno: Errno = Errno::ESUCCESS;
pub trait ResultExt<T, E> {
fn e_map_err<F: FnOnce(E) -> Errno>(self, map: F) -> EResult<T>;
@@ -136,9 +134,7 @@ impl<T> EResult<T> {
Self::Ok(value) => Ok(value),
Self::Err(err) => {
if set_errno {
unsafe {
errno = err;
}
self::set_errno(err);
}
Err(map_err(err))
}
@@ -219,9 +215,7 @@ impl<T> CResult for CPtrResult<T> {
impl<T> FromResidual<EResult<Infallible>> for CPtrResult<T> {
fn from_residual(residual: EResult<Infallible>) -> Self {
let err = residual.unwrap_err();
unsafe {
errno = err;
}
set_errno(err);
Self::ERROR
}
}
@@ -338,3 +332,11 @@ impl_from_residual!(
COffsetResult,
CUsizeResult
);
pub fn set_errno(value: Errno) {
unsafe { __errno = value };
}
pub fn get_errno() -> Errno {
unsafe { __errno }
}
@@ -198,7 +198,7 @@ unsafe extern "C" fn pthread_attr_setstack(
attr.stack_size = size;
CIntZeroResult::SUCCESS
} else {
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
CIntZeroResult::ERROR
}
}
@@ -213,7 +213,7 @@ unsafe extern "C" fn pthread_attr_setstacksize(
attr.stack_size = size;
CIntZeroResult::SUCCESS
} else {
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
CIntZeroResult::ERROR
}
}
@@ -113,7 +113,7 @@ unsafe extern "C" fn pthread_barrierattr_setpshared(
CIntZeroResult::SUCCESS
} else {
log::error!("TODO: pthread_barrierattr_setpshared()");
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
CIntZeroResult::ERROR
}
}
@@ -151,7 +151,7 @@ unsafe extern "C" fn pthread_condattr_setclock(
CIntZeroResult::SUCCESS
} else {
log::error!("TODO: pthread_condattr_setclock()");
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
CIntZeroResult::ERROR
}
}
@@ -165,7 +165,7 @@ unsafe extern "C" fn pthread_condattr_setpshared(
CIntZeroResult::SUCCESS
} else {
log::error!("TODO: pthread_condattr_setpshared()");
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
CIntZeroResult::ERROR
}
}
@@ -286,7 +286,7 @@ unsafe extern "C" fn pthread_mutexattr_setprotocol(
CIntZeroResult::SUCCESS
} else {
log::error!("TODO: pthread_mutexattr_setprotocol()");
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
CIntZeroResult::ERROR
}
}
@@ -300,7 +300,7 @@ unsafe extern "C" fn pthread_mutexattr_setpshared(
CIntZeroResult::SUCCESS
} else {
log::error!("TODO: pthread_mutexattr_setpshared()");
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
CIntZeroResult::ERROR
}
}
@@ -314,7 +314,7 @@ unsafe extern "C" fn pthread_mutexattr_setrobust(
CIntZeroResult::SUCCESS
} else {
log::error!("TODO: pthread_mutexattr_setrobust()");
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
CIntZeroResult::ERROR
}
}
@@ -331,7 +331,7 @@ unsafe extern "C" fn pthread_mutexattr_settype(
CIntZeroResult::SUCCESS
}
_ => {
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
CIntZeroResult::ERROR
}
}
@@ -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::set_errno(Errno::EINVAL);
return null_mut();
}
match dtv.get_specific(key) {
Some(value) => value,
None => {
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
null_mut()
}
}
@@ -11,10 +11,12 @@ usize_type = "size_t"
isize_type = "ssize_t"
[export]
include = ["jmp_buf"]
include = ["jmp_buf", "sigjmp_buf"]
exclude = [
"setjmp",
"sigsetjmp",
"longjmp",
"siglongjmp",
"_setjmp",
"_longjmp",
]
@@ -1,21 +1,22 @@
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
pub mod x86_64;
#[cfg(any(target_arch = "x86_64", rust_analyzer))]
pub use x86_64::__jmp_buf;
pub use x86_64::{__jmp_buf, __sigjmp_buf};
#[cfg(any(target_arch = "x86", rust_analyzer))]
pub mod i686;
#[cfg(any(target_arch = "x86", rust_analyzer))]
pub use i686::__jmp_buf;
pub use i686::{__jmp_buf, __sigjmp_buf};
#[cfg(any(target_arch = "aarch64", rust_analyzer))]
pub mod aarch64;
#[cfg(any(target_arch = "aarch64", rust_analyzer))]
pub use aarch64::__jmp_buf;
pub use aarch64::{__jmp_buf, __sigjmp_buf};
#[cfg(any(target_arch = "riscv64", rust_analyzer))]
pub mod riscv64;
#[cfg(any(target_arch = "riscv64", rust_analyzer))]
pub use riscv64::__jmp_buf;
pub use riscv64::{__jmp_buf, __sigjmp_buf};
pub type jmp_buf = __jmp_buf;
pub type sigjmp_buf = __sigjmp_buf;
@@ -1,6 +1,14 @@
use core::ffi::c_int;
pub type __jmp_buf = [usize; 8];
pub type __sigjmp_buf = [usize; 8];
#[no_mangle]
#[naked]
unsafe extern "C" fn sigsetjmp(buf: *mut __sigjmp_buf, savesigs: c_int) -> c_int {
// TODO: I don't yet have signal masking
core::arch::naked_asm!("jmp setjmp")
}
#[no_mangle]
#[naked]
@@ -36,7 +44,7 @@ unsafe extern "C" fn _setjmp(buf: *mut __jmp_buf) -> c_int {
#[no_mangle]
#[naked]
unsafe extern "C" fn longjmp(buf: *mut __jmp_buf, val: c_int) -> c_int {
unsafe extern "C" fn longjmp(buf: *mut __jmp_buf, val: c_int) -> ! {
// %rdi -- jmp_buf pointer
// %rsi -- return value
core::arch::naked_asm!(
@@ -61,6 +69,12 @@ unsafe extern "C" fn longjmp(buf: *mut __jmp_buf, val: c_int) -> c_int {
)
}
#[no_mangle]
#[naked]
unsafe extern "C" fn siglongjmp(buf: *mut __sigjmp_buf, val: c_int) -> ! {
core::arch::naked_asm!("jmp longjmp")
}
#[no_mangle]
#[naked]
unsafe extern "C" fn _longjmp(buf: *mut __jmp_buf, val: c_int) -> c_int {
@@ -248,7 +248,7 @@ unsafe extern "C" fn sigaction(
#[no_mangle]
unsafe extern "C" fn sigaddset(mask: *mut sigset_t, signum: c_int) -> CIntZeroResult {
if signum > 63 || signum <= 0 {
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
return CIntZeroResult::ERROR;
}
*mask |= 1 << signum;
@@ -268,7 +268,7 @@ unsafe extern "C" fn sigaltstack(new: *const stack_t, old: *mut stack_t) -> CInt
if let Some(new) = new.as_ref() {
// TODO what do with SS_DISABLE?
if new.ss_size < MINSIGSTKSZ {
error::errno = Errno::ENOMEM;
error::set_errno(Errno::ENOMEM);
return CIntZeroResult::ERROR;
}
rt::set_signal_stack(new.ss_sp.addr(), new.ss_size);
@@ -311,7 +311,7 @@ unsafe extern "C" fn siginterrupt(_signum: c_int, _b: c_int) -> c_int {
#[no_mangle]
unsafe extern "C" fn sigismember(mask: *const sigset_t, signum: c_int) -> c_int {
if signum > 63 || signum <= 0 {
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
return -1;
}
let mask = *mask.ensure();
@@ -329,7 +329,7 @@ unsafe extern "C" fn signal(signum: c_int, handler: sig_handler_t) -> sig_handle
// NULL or SIG_ERR
if address == 0 || address == 1 {
log::error!("libc: signal() was passed an invalid handler");
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
// SIG_ERR
return core::mem::transmute(1usize);
}
@@ -337,7 +337,7 @@ unsafe extern "C" fn signal(signum: c_int, handler: sig_handler_t) -> sig_handle
match signal::set(signum, handler) {
EResult::Ok(handler) => handler,
EResult::Err(err) => {
error::errno = err;
error::set_errno(err);
// SIG_ERR
core::mem::transmute(1usize)
}
@@ -135,7 +135,7 @@ impl fmt::Write for AllocatedStringWriter {
match self.write_all(s.as_bytes()) {
EResult::Ok(()) => Ok(()),
EResult::Err(e) => {
unsafe { error::errno = e };
error::set_errno(e);
Err(fmt::Error)
}
}
@@ -24,7 +24,8 @@ unsafe extern "C" fn perror(message: *const c_char) {
}
#[allow(static_mut_refs)]
out.write_unlocked(error::errno.to_c_str().to_bytes()).ok();
out.write_unlocked(error::get_errno().to_c_str().to_bytes())
.ok();
out.write_unlocked(b"\n").ok();
out.unlock();
@@ -27,6 +27,11 @@ unsafe extern "C" fn mkstemp(_template: *mut c_char) -> c_int {
todo!()
}
#[no_mangle]
unsafe extern "C" fn mktemp(_template: *mut c_char) -> *mut c_char {
todo!()
}
#[no_mangle]
unsafe extern "C" fn posix_openpt(_fd: c_int) -> c_int {
todo!()
@@ -43,7 +48,7 @@ unsafe extern "C" fn realpath(
resolved_ptr: *mut c_char,
) -> CPtrResult<c_char> {
if path.is_null() {
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
return CPtrResult::ERROR;
}
let path = path.ensure_str();
@@ -1,9 +1,9 @@
use core::{
cmp::Ordering,
ffi::{c_char, c_int},
ffi::{c_char, c_int, c_void},
};
use super::locale::locale_t;
use super::{locale::locale_t, string::mem::memmove};
#[no_mangle]
unsafe extern "C" fn ffs(_f: c_int) -> c_int {
@@ -63,3 +63,9 @@ unsafe extern "C" fn strncasecmp_l(
) -> c_int {
todo!()
}
#[deprecated]
#[no_mangle]
unsafe extern "C" fn bcopy(src: *const c_void, dst: *mut c_void, n: usize) {
memmove(dst, src, n);
}
@@ -135,7 +135,7 @@ unsafe extern "C" fn mmap(
match mmap_inner(hint, len, prot, flags, fd, offset) {
EResult::Ok(ptr) => ptr.as_ptr(),
EResult::Err(errno) => {
error::errno = errno;
error::set_errno(errno);
// MAP_FAILED
usize::MAX as *mut c_void
}
@@ -146,7 +146,7 @@ unsafe extern "C" fn mmap(
unsafe extern "C" fn munmap(ptr: *mut c_void, len: usize) -> CIntZeroResult {
let address = ptr.addr();
if address == 0 || address == usize::MAX || len == 0 {
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
return CIntZeroResult::ERROR;
}
syscall::unmap_memory(address, len).e_map_err(Errno::from)?;
@@ -14,7 +14,7 @@ unsafe extern "C" fn getsockopt(
) -> CIntZeroResult {
todo!()
// if value.is_null() || size.is_null() {
// error::errno = Errno::EINVAL;
// error::set_errno(Errno::EINVAL);
// return CIntZeroResult::ERROR;
// }
@@ -57,7 +57,7 @@ unsafe extern "C" fn getsockopt(
// }
// _ => {
// yggdrasil_rt::debug_trace!("Unhandled getsockopt({level}, {name}, {space})");
// error::errno = Errno::EINVAL;
// error::set_errno(Errno::EINVAL);
// return CIntZeroResult::ERROR;
// }
// };
@@ -75,7 +75,7 @@ unsafe extern "C" fn setsockopt(
) -> CIntZeroResult {
todo!()
// if value.is_null() {
// error::errno = Errno::EINVAL;
// error::set_errno(Errno::EINVAL);
// return CIntZeroResult::ERROR;
// }
@@ -102,7 +102,7 @@ unsafe extern "C" fn setsockopt(
// }
// _ => {
// yggdrasil_rt::debug_trace!("Unhandled setsockopt({level}, {name}, {size})");
// error::errno = Errno::EINVAL;
// error::set_errno(Errno::EINVAL);
// return CIntZeroResult::ERROR;
// }
// }
@@ -118,7 +118,7 @@ unsafe extern "C" fn getpeername(
) -> CIntZeroResult {
todo!()
// if remote.is_null() || len.is_null() {
// error::errno = Errno::EINVAL;
// error::set_errno(Errno::EINVAL);
// return CIntZeroResult::ERROR;
// }
@@ -138,7 +138,7 @@ unsafe extern "C" fn getsockname(
) -> CIntZeroResult {
todo!()
// if local.is_null() || len.is_null() {
// error::errno = Errno::EINVAL;
// error::set_errno(Errno::EINVAL);
// return CIntZeroResult::ERROR;
// }
@@ -73,7 +73,7 @@ unsafe extern "C" fn shutdown(fd: c_int, how: c_int) -> CIntZeroResult {
SHUT_WR => rt::SocketShutdown::WRITE,
SHUT_RDWR => rt::SocketShutdown::READ | rt::SocketShutdown::WRITE,
_ => {
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
return CIntZeroResult::ERROR;
}
};
@@ -86,7 +86,7 @@ unsafe extern "C" fn shutdown(fd: c_int, how: c_int) -> CIntZeroResult {
// TODO out-of-band data in sockets
#[no_mangle]
unsafe extern "C" fn sockatmark(_fd: c_int) -> CIntCountResult {
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
CIntCountResult::ERROR
}
@@ -97,7 +97,7 @@ unsafe extern "C" fn socket(domain: c_int, ty: c_int, proto: c_int) -> CFdResult
(AF_INET, SOCK_DGRAM, 0) => rt::SocketType::UdpPacket,
(_, _, _) => {
log::error!("Unsupported socket({domain}, {ty}, {proto})");
error::errno = Errno::ENOTSUPP;
error::set_errno(Errno::ENOTSUPP);
return CFdResult::ERROR;
}
};
@@ -30,6 +30,8 @@ include = [
"time_t",
"timer_t",
"uid_t",
"u_int",
"u_long",
"pthread_attr_t",
"pthread_barrier_t",
@@ -1,5 +1,5 @@
use core::{
ffi::{c_int, c_ulong, c_void},
ffi::{c_int, c_uint, c_ulong, c_void},
ptr::NonNull,
sync::atomic::{AtomicBool, AtomicU32},
};
@@ -36,6 +36,9 @@ pub type ino_t = u64;
pub type clock_t = u64;
pub type u_int = c_uint;
pub type u_long = c_ulong;
#[derive(Clone, Copy, PartialEq, Eq, Debug, Default)]
#[repr(transparent)]
pub struct time_t(pub i64);
@@ -80,7 +80,7 @@ unsafe extern "C" fn wait(status: *mut c_int) -> pid_t {
res.pid.bits() as pid_t
}
EResult::Err(error) => {
error::errno = error;
error::set_errno(error);
-1 as pid_t
}
}
@@ -113,7 +113,7 @@ unsafe extern "C" fn wait4(
let result = match wait_inner(pid, options & WNOHANG != 0) {
EResult::Ok(result) => result,
EResult::Err(err) => {
error::errno = err;
error::set_errno(err);
return -1;
}
};
@@ -21,7 +21,7 @@ unsafe extern "C" fn nanosleep(
if let Some(rmtp) = rmtp.as_mut() {
*rmtp = remaining.into();
}
error::errno = Errno::EINTR;
error::set_errno(Errno::EINTR);
CIntZeroResult::ERROR
}
}
@@ -133,7 +133,7 @@ unsafe extern "C" fn sleep(seconds: c_uint) -> c_uint {
match process::sleep(duration) {
Ok(()) => 0,
Err(remaining) => {
error::errno = Errno::EINTR;
error::set_errno(Errno::EINTR);
remaining.as_secs() as c_uint + (remaining.subsec_nanos() != 0) as c_uint
}
}
@@ -17,6 +17,7 @@ pub enum Sysconf {
_SC_HOST_NAME_MAX,
_SC_LINE_MAX,
_SC_ARG_MAX,
_SC_NPROCESSORS_ONLN,
}
pub const _CS_PATH: c_int = 1;
@@ -33,7 +34,7 @@ unsafe extern "C" fn confstr(name: c_int, buf: *mut c_char, size: usize) -> usiz
let path = match get_env("PATH".as_bytes()) {
EResult::Ok(value) => value,
EResult::Err(err) => {
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
return 0;
}
};
@@ -51,7 +52,7 @@ unsafe extern "C" fn confstr(name: c_int, buf: *mut c_char, size: usize) -> usiz
cstr.to_bytes().len()
}
_ => {
error::errno = Errno::EINVAL;
error::set_errno(Errno::EINVAL);
0
}
}