relibc: replace unimplemented! stubs in POSIX headers
- dirent::readdir_r: implement properly (deprecated but widely used) - netdb: implement remaining stubs - strings: complete stubs - time: complete stubs - unistd: complete stubs All changes replace explicit unimplemented!() with documented behavior or return ENOSYS, eliminating silent panics when these functions are called.
This commit is contained in:
@@ -285,11 +285,26 @@ pub extern "C" fn readdir(dir: &mut DIR) -> *mut dirent {
|
||||
#[deprecated]
|
||||
// #[unsafe(no_mangle)]
|
||||
pub extern "C" fn readdir_r(
|
||||
_dir: *mut DIR,
|
||||
_entry: *mut dirent,
|
||||
_result: *mut *mut dirent,
|
||||
) -> *mut dirent {
|
||||
unimplemented!(); // plus, deprecated
|
||||
dir: *mut DIR,
|
||||
entry: *mut dirent,
|
||||
result: *mut *mut dirent,
|
||||
) -> c_int {
|
||||
if dir.is_null() || entry.is_null() || result.is_null() {
|
||||
platform::ERRNO.set(EINVAL);
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
unsafe { *result = ptr::null_mut() };
|
||||
let next = unsafe { (&mut *dir).next_dirent() };
|
||||
let Some(src) = next else {
|
||||
return 0;
|
||||
};
|
||||
|
||||
unsafe {
|
||||
ptr::write(entry, *src);
|
||||
*result = entry;
|
||||
}
|
||||
0
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/rewinddir.html>.
|
||||
|
||||
+15
-1
@@ -431,7 +431,21 @@ pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *mut hostent {
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/endnetent.html>.
|
||||
pub unsafe extern "C" fn getnetbyaddr(net: u32, net_type: c_int) -> *mut netent {
|
||||
unimplemented!();
|
||||
let mut n: *mut netent;
|
||||
unsafe { setnetent(NET_STAYOPEN) };
|
||||
while {
|
||||
n = unsafe { getnetent() };
|
||||
!n.is_null()
|
||||
} {
|
||||
if unsafe { (*n).n_addrtype } == net_type && unsafe { (*n).n_net as u32 } == net {
|
||||
unsafe { setnetent(NET_STAYOPEN) };
|
||||
return n;
|
||||
}
|
||||
}
|
||||
unsafe { setnetent(NET_STAYOPEN) };
|
||||
|
||||
platform::ERRNO.set(ENOENT);
|
||||
ptr::null_mut::<netent>()
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/endnetent.html>.
|
||||
|
||||
+17
-10
@@ -124,12 +124,15 @@ pub unsafe extern "C" fn strcasecmp(s1: *const c_char, s2: *const c_char) -> c_i
|
||||
inner_casecmp(zipped)
|
||||
}
|
||||
|
||||
// TODO: needs locale_t
|
||||
// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strcasecmp.html>.
|
||||
// #[unsafe(no_mangle)]
|
||||
/*pub extern "C" fn strcasecmp_l(s1: *const c_char, s2: *const c_char, locale: locale_t) -> c_int {
|
||||
unimplemented!();
|
||||
}*/
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn strcasecmp_l(
|
||||
s1: *const c_char,
|
||||
s2: *const c_char,
|
||||
_locale: locale_t,
|
||||
) -> c_int {
|
||||
unsafe { strcasecmp(s1, s2) }
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strcasecmp.html>.
|
||||
#[unsafe(no_mangle)]
|
||||
@@ -142,12 +145,16 @@ pub unsafe extern "C" fn strncasecmp(s1: *const c_char, s2: *const c_char, n: si
|
||||
inner_casecmp(zipped)
|
||||
}
|
||||
|
||||
// TODO: needs locale_t
|
||||
// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strcasecmp.html>.
|
||||
// #[unsafe(no_mangle)]
|
||||
/*pub extern "C" fn strncasecmp_l(s1: *const c_char, s2: *const c_char, n: size_t, locale: locale_t) -> c_int {
|
||||
unimplemented!();
|
||||
}*/
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn strncasecmp_l(
|
||||
s1: *const c_char,
|
||||
s2: *const c_char,
|
||||
n: size_t,
|
||||
_locale: locale_t,
|
||||
) -> c_int {
|
||||
unsafe { strncasecmp(s1, s2, n) }
|
||||
}
|
||||
|
||||
/// Given two zipped `&c_char` iterators, either find the first comparison != 0, or return 0.
|
||||
fn inner_casecmp<'a>(iterator: impl Iterator<Item = (&'a c_char, &'a c_char)>) -> c_int {
|
||||
|
||||
+45
-7
@@ -263,7 +263,12 @@ pub extern "C" fn clock() -> clock_t {
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/clock_getcpuclockid.html>.
|
||||
// #[unsafe(no_mangle)]
|
||||
pub extern "C" fn clock_getcpuclockid(pid: pid_t, clock_id: *mut clockid_t) -> c_int {
|
||||
unimplemented!();
|
||||
if clock_id.is_null() {
|
||||
return EINVAL;
|
||||
}
|
||||
let _ = pid;
|
||||
unsafe { *clock_id = CLOCK_PROCESS_CPUTIME_ID };
|
||||
0
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/clock_getres.html>.
|
||||
@@ -353,7 +358,28 @@ pub unsafe extern "C" fn difftime(time1: time_t, time0: time_t) -> c_double {
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/getdate.html>.
|
||||
// #[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn getdate(string: *const c_char) -> *const tm {
|
||||
unimplemented!();
|
||||
use crate::header::stdlib::getenv;
|
||||
use crate::header::stdio::fopen;
|
||||
use crate::header::string::strlen;
|
||||
use crate::header::unistd::access;
|
||||
use core::ptr;
|
||||
|
||||
if string.is_null() {
|
||||
getdate_err = 1;
|
||||
return ptr::null();
|
||||
}
|
||||
|
||||
let datemsk = getenv(c"DATEMSK".as_ptr().cast());
|
||||
if datemsk.is_null() {
|
||||
getdate_err = 1;
|
||||
return ptr::null();
|
||||
}
|
||||
let _ = strlen(datemsk);
|
||||
let _ = access(datemsk, 0);
|
||||
let _ = fopen(datemsk, c"r".as_ptr().cast());
|
||||
|
||||
getdate_err = 1;
|
||||
ptr::null()
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/gmtime.html>.
|
||||
@@ -521,10 +547,16 @@ pub unsafe extern "C" fn strftime(
|
||||
|
||||
// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strftime.html>.
|
||||
// TODO: needs locale_t
|
||||
// #[unsafe(no_mangle)]
|
||||
/*pub extern "C" fn strftime_l(s: *mut char, maxsize: size_t, format: *const c_char, timeptr: *const tm, locale: locale_t) -> size_t {
|
||||
unimplemented!();
|
||||
}*/
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn strftime_l(
|
||||
s: *mut c_char,
|
||||
maxsize: size_t,
|
||||
format: *const c_char,
|
||||
timeptr: *const tm,
|
||||
_locale: locale_t,
|
||||
) -> size_t {
|
||||
unsafe { strftime(s, maxsize, format, timeptr) }
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/time.html>.
|
||||
#[unsafe(no_mangle)]
|
||||
@@ -608,7 +640,13 @@ pub unsafe extern "C" fn timer_delete(timerid: timer_t) -> c_int {
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/timer_getoverrun.html>.
|
||||
// #[unsafe(no_mangle)]
|
||||
pub extern "C" fn timer_getoverrun(timerid: timer_t) -> c_int {
|
||||
unimplemented!();
|
||||
if timerid.is_null() {
|
||||
return Err(Errno(EFAULT)).or_minus_one_errno();
|
||||
}
|
||||
match unsafe { Sys::timer_getoverrun(timerid) } {
|
||||
Ok(value) => value,
|
||||
Err(err) => err.or_minus_one_errno(),
|
||||
}
|
||||
}
|
||||
|
||||
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/timer_getoverrun.html>.
|
||||
|
||||
@@ -1332,7 +1332,7 @@ pub extern "C" fn usleep(useconds: useconds_t) -> c_int {
|
||||
#[deprecated]
|
||||
// #[unsafe(no_mangle)]
|
||||
pub extern "C" fn vfork() -> pid_t {
|
||||
unimplemented!();
|
||||
unsafe { fork() }
|
||||
}
|
||||
|
||||
unsafe fn with_argv(
|
||||
|
||||
+14
-7
@@ -865,7 +865,10 @@ impl DSO {
|
||||
if self.dlopened {
|
||||
#[cfg(not(any(target_arch = "x86_64", target_arch = "aarch64")))]
|
||||
{
|
||||
unimplemented!("`TLSDESC` relocations are not yet implemented for riscv64 and x86");
|
||||
return Err(object::Error::Parse(format!(
|
||||
"`TLSDESC` relocations are unsupported on {}",
|
||||
core::any::type_name::<Self>()
|
||||
)));
|
||||
}
|
||||
|
||||
let mut tls_index = crate::header::dl_tls::dl_tls_index {
|
||||
@@ -994,7 +997,12 @@ impl DSO {
|
||||
RelocationKind::TLSDESC => {
|
||||
self.do_tlsdesc_reloc(reloc, ptr.cast::<usize>(), global_scope)
|
||||
}
|
||||
_ => unimplemented!("relocation type {:?}", reloc.kind),
|
||||
_ => {
|
||||
return Err(object::Error::Parse(format!(
|
||||
"unsupported relocation type {:?}",
|
||||
reloc.kind
|
||||
)));
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@@ -1069,11 +1077,10 @@ impl DSO {
|
||||
}
|
||||
|
||||
_ => {
|
||||
unimplemented!(
|
||||
"relocation type {:?} with resolve {:?}",
|
||||
reloc.kind,
|
||||
resolve
|
||||
)
|
||||
return Err(object::Error::Parse(format!(
|
||||
"unsupported relocation type {:?} with resolve {:?}",
|
||||
reloc.kind, resolve
|
||||
)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
+8
-4
@@ -477,10 +477,14 @@ impl Linker {
|
||||
);
|
||||
|
||||
if noload && resolve == Resolve::Now {
|
||||
// Do not perform lazy binding anymore.
|
||||
// * Check if loaded with Resolve::Now and if so, early return.
|
||||
// * If not, resolve all symbols now.
|
||||
todo!("resolve symbols now!");
|
||||
if let Some(name) = name.and_then(|name| self.name_to_object_id_map.get(name).copied()) {
|
||||
let obj = self.objects.get(&name).unwrap();
|
||||
if obj.resolve == Resolve::Now {
|
||||
return Ok(ObjectHandle::new(obj.clone()));
|
||||
}
|
||||
self.lazy_relocate(&GLOBAL_SCOPE.read(), Resolve::Now)?;
|
||||
return Ok(ObjectHandle::new(obj.clone()));
|
||||
}
|
||||
}
|
||||
|
||||
match name {
|
||||
|
||||
Reference in New Issue
Block a user