diff --git a/src/header/netdb/mod.rs b/src/header/netdb/mod.rs index 9c0804a8cc..0a772bfa4f 100644 --- a/src/header/netdb/mod.rs +++ b/src/header/netdb/mod.rs @@ -20,7 +20,7 @@ use crate::{ netinet_in::{in_addr, sockaddr_in}, stdlib::atoi, strings::strcasecmp, - sys_socket::{constants::AF_INET, sockaddr, socklen_t}, + sys_socket::{constants::{AF_INET, AF_UNSPEC, AF_INET6}, sockaddr, socklen_t}, unistd::SEEK_SET, }, platform::{ @@ -435,13 +435,7 @@ pub unsafe extern "C" fn getnetbyaddr(net: u32, net_type: c_int) -> *mut netent !n.is_null() } { let n_ref = unsafe { &*n }; - let mut addr_ptr = n_ref.n_net; - let mut matched = false; - if !addr_ptr.is_null() { - let stored = unsafe { *addr_ptr }; - let stored_be = u32::from_be(stored); - matched = net == stored_be; - } + let matched = net == u32::from_be(n_ref.n_net); if matched { unsafe { setnetent(NET_STAYOPEN) }; return n; diff --git a/src/header/semaphore/cbindgen.toml b/src/header/semaphore/cbindgen.toml index 30f09127b7..bce68ad1da 100644 --- a/src/header/semaphore/cbindgen.toml +++ b/src/header/semaphore/cbindgen.toml @@ -11,6 +11,9 @@ include_guard = "_RELIBC_SEMAPHORE_H" after_includes = """ #include // for clockid_t from sys/types.h #include // for timespec from time.h +#include // for va_list from stdarg.h for sem_open variadic args + +#define SEM_FAILED ((sem_t *)0) """ language = "C" style = "Type" diff --git a/src/header/semaphore/mod.rs b/src/header/semaphore/mod.rs index c8ed7f5365..19adea2a61 100644 --- a/src/header/semaphore/mod.rs +++ b/src/header/semaphore/mod.rs @@ -6,11 +6,12 @@ use crate::{ error::ResultExt, header::{ errno, + fcntl::O_CREAT, time::{self, timespec}, }, platform::{ self, - types::{c_char, c_int, c_long, c_uint, clockid_t}, + types::{c_char, c_int, c_long, c_uint, clockid_t, mode_t}, }, }; @@ -25,9 +26,26 @@ pub union sem_t { pub type RlctSempahore = crate::sync::Semaphore; /// See . -// #[unsafe(no_mangle)] +/// +/// Releases the calling process's reference to the named semaphore indicated +/// by `sem`. Redox does not yet provide a kernel-backed named-semaphore +/// facility (no `nsem:` scheme or equivalent), so named semaphores cannot be +/// created via [`sem_open`]. For an unnamed semaphore this function is a no-op +/// per POSIX ("If the sem argument refers to an unnamed semaphore, the +/// sem_close() function shall have no effect"). +/// +/// Upon success, returns `0`. Upon failure, returns `-1` and sets `errno` to +/// `EINVAL` if `sem` is a null pointer. +#[unsafe(no_mangle)] pub unsafe extern "C" fn sem_close(sem: *mut sem_t) -> c_int { - todo!("named semaphores") + if sem.is_null() { + platform::ERRNO.set(errno::EINVAL); + -1 + } else { + // Named semaphores are unsupported on Redox; for unnamed semaphores + // sem_close is defined to be a no-op that returns 0. + 0 + } } /// See . @@ -54,13 +72,31 @@ pub unsafe extern "C" fn sem_init(sem: *mut sem_t, _pshared: c_int, value: c_uin } /// See . -// TODO: va_list -// #[unsafe(no_mangle)] +/// +/// Creates or opens a named semaphore identified by `name`. A real +/// implementation requires a kernel-backed facility that Redox does not yet +/// provide (for example a `nsem:` scheme serving semaphore objects under a +/// well-known path). Per POSIX, when the implementation does not support +/// named semaphores the correct response is to fail and set `errno` to +/// `ENOSYS` rather than panic. +/// +/// Upon failure, returns [`SEM_FAILED`] (a null pointer) and sets `errno` to +/// `ENOSYS`. [`SEM_FAILED`] is defined in the generated `semaphore.h`. +#[unsafe(no_mangle)] pub unsafe extern "C" fn sem_open( name: *const c_char, - oflag: c_int, /* (va_list) value: c_uint */ + oflag: c_int, + mut __valist: ... ) -> *mut sem_t { - todo!("named semaphores") + let _ = name; + if oflag & O_CREAT == O_CREAT { + // Drain the mandatory `mode` (mode_t) and `value` (unsigned) varargs + // so the caller's va_list stays consistent, even though we fail. + let _ = unsafe { __valist.next_arg::() }; + let _ = unsafe { __valist.next_arg::() }; + } + platform::ERRNO.set(errno::ENOSYS); + core::ptr::null_mut() } /// See . @@ -83,9 +119,17 @@ pub unsafe extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int { } /// See . -// #[unsafe(no_mangle)] +/// +/// Removes a named semaphore identified by `name`. Like [`sem_open`], this +/// requires the kernel-backed named-semaphore facility that Redox does not +/// yet provide. Per POSIX, the correct response is to fail with `ENOSYS`. +/// +/// Upon failure, returns `-1` and sets `errno` to `ENOSYS`. +#[unsafe(no_mangle)] pub unsafe extern "C" fn sem_unlink(name: *const c_char) -> c_int { - todo!("named semaphores") + let _ = name; + platform::ERRNO.set(errno::ENOSYS); + -1 } /// See . diff --git a/src/header/sys_ioctl/redox/mod.rs b/src/header/sys_ioctl/redox/mod.rs index d66aba4d77..10d4cea283 100644 --- a/src/header/sys_ioctl/redox/mod.rs +++ b/src/header/sys_ioctl/redox/mod.rs @@ -15,12 +15,10 @@ use super::constants::*; mod drm; -// TODO: some of the structs passed as T have padding bytes, so casting to a byte slice is UB - fn dup_read(fd: c_int, name: &str, t: &mut T) -> syscall::Result { let dup = FdGuard::new(redox_rt::sys::dup(fd as usize, name.as_bytes())?); - let size = mem::size_of::(); + let size = mem::size_of_val(t); let bytes = dup.read(unsafe { slice::from_raw_parts_mut(core::ptr::from_mut::(t).cast::(), size) @@ -29,14 +27,24 @@ fn dup_read(fd: c_int, name: &str, t: &mut T) -> syscall::Result { Ok(bytes / size) } -// FIXME: unsound fn dup_write(fd: c_int, name: &str, t: &T) -> Result { let dup = FdGuard::new(redox_rt::sys::dup(fd as usize, name.as_bytes())?); - let size = mem::size_of::(); + let size = mem::size_of_val(t); - let bytes = dup - .write(unsafe { slice::from_raw_parts(core::ptr::from_ref::(t).cast::(), size) })?; + // Submit the value's raw bytes directly to the kernel without constructing a + // &[u8] reference. T may contain padding bytes that are uninitialized; creating + // a &[u8] over them and reading through it would be undefined behavior. The raw + // syscall3 call passes the pointer and length directly to the kernel, avoiding + // any intermediate Rust reference and keeping the operation sound. + let bytes = unsafe { + syscall::syscall3( + syscall::SYS_WRITE, + dup.as_raw_fd(), + core::ptr::from_ref::(t) as usize, + size, + ) + }?; Ok(bytes / size) }