diff --git a/src/header/dirent/mod.rs b/src/header/dirent/mod.rs index 17eccf0b4e..df556c6378 100644 --- a/src/header/dirent/mod.rs +++ b/src/header/dirent/mod.rs @@ -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 . diff --git a/src/header/netdb/mod.rs b/src/header/netdb/mod.rs index e39a82f50b..df1935d5fe 100644 --- a/src/header/netdb/mod.rs +++ b/src/header/netdb/mod.rs @@ -431,7 +431,21 @@ pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *mut hostent { /// See . 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::() } /// See . diff --git a/src/header/strings/mod.rs b/src/header/strings/mod.rs index 9f33d65f54..69ece3cec1 100644 --- a/src/header/strings/mod.rs +++ b/src/header/strings/mod.rs @@ -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 . -// #[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 . #[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 . -// #[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) -> c_int { diff --git a/src/header/time/mod.rs b/src/header/time/mod.rs index b2d8417522..29f6783d01 100644 --- a/src/header/time/mod.rs +++ b/src/header/time/mod.rs @@ -263,7 +263,12 @@ pub extern "C" fn clock() -> clock_t { /// See . // #[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 . @@ -353,7 +358,28 @@ pub unsafe extern "C" fn difftime(time1: time_t, time0: time_t) -> c_double { /// See . // #[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 . @@ -521,10 +547,16 @@ pub unsafe extern "C" fn strftime( // See . // 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 . #[unsafe(no_mangle)] @@ -608,7 +640,13 @@ pub unsafe extern "C" fn timer_delete(timerid: timer_t) -> c_int { /// See . // #[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 . diff --git a/src/header/unistd/mod.rs b/src/header/unistd/mod.rs index 8efddf891e..ca44cca40e 100644 --- a/src/header/unistd/mod.rs +++ b/src/header/unistd/mod.rs @@ -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( diff --git a/src/ld_so/dso.rs b/src/ld_so/dso.rs index afb4c7c1e6..7647840a64 100644 --- a/src/ld_so/dso.rs +++ b/src/ld_so/dso.rs @@ -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::() + ))); } 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::(), 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 + ))); } } } diff --git a/src/ld_so/linker.rs b/src/ld_so/linker.rs index 4a01b0d9b1..e953d07faa 100644 --- a/src/ld_so/linker.rs +++ b/src/ld_so/linker.rs @@ -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 {