Merge upstream/master into submodule/relibc

Sync the relibc fork with 50 upstream commits (socket layer rework,
exec/signal/ptrace/path/timer updates, pthread cleanup, ld_so lifecycle
work bringing mark_ready/run_fini into the tree, dynamically-linked
init support, start.rs allocator-model rewrite, test harness updates).
Satisfies the verify-fork-functions gate (2 previously-missing ld_so
functions now present).

Conflicts resolved (4 files; 46 auto-merged):

- src/start.rs: took upstream's version wholesale. Upstream moved
  allocator/linker initialization into ld_so's new lifecycle (the
  mark_ready/run_fini work this merge brings in), superseding the RB
  alloc_init cluster; the old model's function was already merged out
  and its lone call would not compile.

- redox-rt/src/sys.rs: kept the RB refresh flow with the non-fatal
  lseek fallback (upstream adopted the refresh as a fatal '?' —
  RB's conservative fallback protects spawn for uid-dropped /
  namespace-restricted exec where the kernel cannot refresh).

- src/platform/redox/exec.rs: kept the RB root exec-permission bypass
  (ruid/euid != 0 gate, Linux-matching behavior).

- Cargo.lock: syn 2.0.118 -> 2.0.119 (upstream).

Verified: repo cook relibc --force-rebuild successful;
verify-fork-functions.sh --no-fetch relibc passes;
all 9 forks now pass the gate.
This commit is contained in:
Red Bear OS
2026-07-19 07:12:56 +09:00
54 changed files with 745 additions and 2333 deletions
+6 -20
View File
@@ -3,8 +3,7 @@ use core::{
cell::SyncUnsafeCell,
cmp,
mem::align_of,
ptr::{self, copy_nonoverlapping, write_bytes},
sync::atomic::{AtomicPtr, Ordering},
ptr::{copy_nonoverlapping, write_bytes},
};
mod sys;
@@ -17,31 +16,18 @@ pub type Dlmalloc = DlmallocCApi<sys::System>;
#[allow(clippy::declare_interior_mutable_const)]
pub const NEWALLOCATOR: Allocator = Allocator::new();
pub struct Allocator {
inner: SyncUnsafeCell<Mutex<Dlmalloc>>,
pub ptr: AtomicPtr<Mutex<Dlmalloc>>,
}
pub struct Allocator(SyncUnsafeCell<Mutex<Dlmalloc>>);
impl Allocator {
#[allow(clippy::new_without_default)]
pub const fn new() -> Self {
Allocator {
inner: SyncUnsafeCell::new(Mutex::new(Dlmalloc::new(sys::System::new()))),
ptr: AtomicPtr::new(ptr::null_mut()),
}
Self(SyncUnsafeCell::new(Mutex::new(Dlmalloc::new(
sys::System::new(),
))))
}
pub fn get(&self) -> *const Mutex<Dlmalloc> {
let ptr = self.ptr.load(Ordering::Acquire);
if !ptr.is_null() {
return ptr;
}
self.inner.get()
}
pub fn set(&self, mspace: *const Mutex<Dlmalloc>) {
self.ptr.store(mspace.cast_mut(), Ordering::Release);
self.0.get()
}
}
+15 -16
View File
@@ -1,36 +1,33 @@
use core::{fmt, str::FromStr};
use core::fmt;
use crate::{c_str::CStr, io::prelude::*, sync::Mutex};
use alloc::string::{String, ToString};
use log::{Metadata, Record};
use log::{LevelFilter, Metadata, Record, SetLoggerError};
const DEFAULT_LOG_LEVEL: log::LevelFilter = log::LevelFilter::Info;
pub unsafe fn init() {
pub const RELIBC_LOG_ENV_VAR: &core::ffi::CStr = c"RELIBC_LOG_LEVEL";
pub unsafe fn init(level: LevelFilter) -> Result<(), SetLoggerError> {
let mut logger = RedoxLogger::new();
let log_env = c"RELIBC_LOG_LEVEL".as_ptr();
#[cfg(feature = "no_trace")]
let mut trace_warn = false;
unsafe {
if let Some(env) = CStr::from_nullable_ptr(crate::header::stdlib::getenv(log_env))
&& let Ok(level) = log::LevelFilter::from_str(env.to_str().unwrap_or(""))
{
#[cfg(feature = "no_trace")]
if level == log::LevelFilter::Trace {
trace_warn = true;
}
logger = logger.with_output(OutputBuilder::stderr().with_filter(level).build());
#[cfg(feature = "no_trace")]
if level == log::LevelFilter::Trace {
trace_warn = true;
}
logger = logger.with_output(OutputBuilder::stderr().with_filter(level).build());
if let Some(name) = CStr::from_nullable_ptr(crate::platform::program_invocation_short_name)
{
logger = logger.with_process_name(name.to_str().unwrap_or("").to_string());
}
}
if logger.enable().is_err() {
log::error!("Logger already initialized");
}
logger.enable()?;
#[cfg(feature = "no_trace")]
if trace_warn {
@@ -38,6 +35,8 @@ pub unsafe fn init() {
"The 'no_trace' feature is enabled but RELIBC_LOG_LEVEL=TRACE, there will be no trace logs"
);
}
Ok(())
}
/// Copied from redox_log crate with some modifications, in future we might use it instead?
+4 -5
View File
@@ -102,13 +102,12 @@ impl PalEpoll for Sys {
};
let callback = || {
let res = syscall::read(epfd as usize, unsafe {
syscall::read(epfd as usize, unsafe {
slice::from_raw_parts_mut(
events as *mut u8,
events.cast::<u8>(),
maxevents as usize * mem::size_of::<syscall::Event>(),
)
});
res
})
};
let bytes_read = if sigset.is_null() {
@@ -126,7 +125,7 @@ impl PalEpoll for Sys {
unsafe {
let event_ptr = events.add(i);
let target_ptr = events.add(count);
let event = *(event_ptr as *mut Event);
let event = *event_ptr.cast::<Event>();
*target_ptr = epoll_event {
events: event_flags_to_epoll(event.flags),
data: epoll_data {
+4 -4
View File
@@ -31,7 +31,7 @@ fn fexec_impl(
interp_override: new_interp_override,
} = redox_rt::proc::fexec_impl(
exec_file,
&RtTcb::current().thread_fd(),
RtTcb::current().thread_fd(),
redox_rt::current_proc_fd(),
path,
args,
@@ -49,11 +49,11 @@ fn fexec_impl(
// null-terminated. Violating this should therefore give the "format error" ENOEXEC.
let path_cstr = CStr::from_bytes_with_nul(&path).map_err(|_| Error::new(ENOEXEC))?;
return execve(
execve(
Executable::AtPath(path_cstr),
ArgEnv::Parsed { args, envs },
Some(new_interp_override),
);
)
}
pub enum ArgEnv<'a> {
@@ -166,7 +166,7 @@ pub fn execve(
let mut args: Vec<&[u8]> = Vec::with_capacity(len);
if let Some(interpreter) = &interpreter_path {
image_file = File::open(CStr::borrow(&interpreter), O_RDONLY as c_int)
image_file = File::open(CStr::borrow(interpreter), O_RDONLY as c_int)
.map_err(|_| Error::new(ENOENT))?;
// Push interpreter to arguments
+1 -1
View File
@@ -9,7 +9,7 @@ use syscall::{F_SETFD, F_SETFL, O_CLOEXEC, O_RDONLY, O_WRONLY};
#[unsafe(no_mangle)]
pub unsafe extern "C" fn redox_fpath(fd: c_int, buf: *mut c_void, count: size_t) -> ssize_t {
syscall::fpath(fd as usize, unsafe {
slice::from_raw_parts_mut(buf as *mut u8, count)
slice::from_raw_parts_mut(buf.cast::<u8>(), count)
})
.map_err(Errno::from)
.map(|l| l as ssize_t)
+4 -5
View File
@@ -1,8 +1,7 @@
use crate::{c_str::CStr, header::stdlib::getenv, platform::types::*};
use core::ptr;
use crate::{c_str::CStr, header::stdlib::getenv, platform::types::c_char};
use syscall::{EIO, ENOENT, Error, Result, flag::*};
pub const LIBC_SCHEME: &'static str = "libc:";
pub const LIBC_SCHEME: &str = "libc:";
const ENV_MAX_LEN: i32 = i32::MAX;
@@ -10,8 +9,8 @@ macro_rules! env_str {
($lit:expr) => {
#[allow(unused_unsafe)]
{
let val_bytes = unsafe { getenv(concat!($lit, "\0").as_ptr() as *const c_char) };
if val_bytes != ptr::null_mut() {
let val_bytes = unsafe { getenv(concat!($lit, "\0").as_ptr().cast::<c_char>()) };
if !val_bytes.is_null() {
if let Ok(val_str) = unsafe { CStr::from_ptr(val_bytes) }.to_str() {
Some(val_str)
} else {
+17 -11
View File
@@ -31,7 +31,7 @@ pub fn openat(dirfd: c_int, path: RedoxStr<'_>, oflag: c_int, mode: mode_t) -> R
((oflag as usize) & 0xFFFF_0000) | ((mode as usize) & 0xFFFF),
)?;
if let Err(_) = c_int::try_from(usize_fd) {
if c_int::try_from(usize_fd).is_err() {
let _ = redox_rt::sys::close(usize_fd);
return Err(Error::new(EMFILE));
}
@@ -42,7 +42,7 @@ pub fn fchmod(fd: usize, new_mode: u16) -> Result<()> {
std_fs_call_wo(
fd,
&[],
&StdFsCallMeta::new(StdFsCallKind::Fchmod, new_mode as u64, 0),
&StdFsCallMeta::new(StdFsCallKind::Fchmod, u64::from(new_mode), 0),
)?;
Ok(())
}
@@ -77,7 +77,7 @@ pub fn getdents(fd: usize, buf: &mut [u8], opaque: u64) -> Result<usize> {
}) => (),
other => {
//println!("REAL GETDENTS {:?}", other);
return Ok(other?);
return other;
}
}
@@ -87,7 +87,7 @@ pub fn getdents(fd: usize, buf: &mut [u8], opaque: u64) -> Result<usize> {
let (header, name) = buf.split_at_mut(mem::size_of::<DirentHeader>());
let bytes_read = Sys::pread(fd as c_int, name, opaque as i64)? as usize;
let bytes_read = Sys::pread(fd as c_int, name, opaque as i64)?;
if bytes_read == 0 {
return Ok(0);
}
@@ -122,14 +122,21 @@ pub unsafe fn fstat(fd: usize, buf: *mut crate::header::sys_stat::stat) -> Resul
if let Some(buf) = unsafe { buf.as_mut() } {
buf.st_dev = redox_buf.st_dev as dev_t;
buf.st_ino = redox_buf.st_ino as ino_t;
buf.st_nlink = redox_buf.st_nlink as nlink_t;
buf.st_nlink = nlink_t::from(redox_buf.st_nlink);
buf.st_mode = redox_buf.st_mode as mode_t;
buf.st_uid = redox_buf.st_uid as uid_t;
buf.st_gid = redox_buf.st_gid as gid_t;
// TODO st_rdev
buf.st_rdev = 0;
buf.st_size = redox_buf.st_size as off_t;
buf.st_blksize = redox_buf.st_blksize as blksize_t;
#[cfg(target_pointer_width = "32")]
{
buf.st_blksize = redox_buf.st_blksize as blksize_t;
}
#[cfg(target_pointer_width = "64")]
{
buf.st_blksize = blksize_t::from(redox_buf.st_blksize);
}
buf.st_blocks = redox_buf.st_blocks as blkcnt_t;
buf.st_atim = timespec {
tv_sec: redox_buf.st_atime as time_t,
@@ -202,7 +209,7 @@ pub unsafe fn futimens(fd: usize, times: *const timespec) -> Result<()> {
};
let redox_buf = unsafe {
slice::from_raw_parts(
times.as_ptr() as *const u8,
times.as_ptr().cast::<u8>(),
times.len() * mem::size_of::<syscall::TimeSpec>(),
)
};
@@ -215,7 +222,7 @@ pub unsafe fn futimens(fd: usize, times: *const timespec) -> Result<()> {
}
pub fn clock_gettime(clock: usize, mut tp: Out<timespec>) -> Result<()> {
let mut redox_tp = syscall::TimeSpec::default();
syscall::clock_gettime(clock as usize, &mut redox_tp)?;
syscall::clock_gettime(clock, &mut redox_tp)?;
tp.write((&redox_tp).into());
Ok(())
}
@@ -228,9 +235,8 @@ pub unsafe extern "C" fn redox_open_v1(
mode: u16,
) -> RawResult {
let path = unsafe { str::from_utf8_unchecked(slice::from_raw_parts(path_base, path_len)) };
let path = match RedoxStr::new(path) {
Some(path) => path,
None => return Error::mux(Err(Error::new(EINVAL))),
let Some(path) = RedoxStr::new(path) else {
return Error::mux(Err(Error::new(EINVAL)));
};
Error::mux(openat(AT_FDCWD, path, flags as c_int, mode as mode_t))
}
+49 -40
View File
@@ -171,7 +171,7 @@ impl Pal for Sys {
let perms = (if stat.st_uid == uid {
stat.st_mode >> (3 * 2)
} else if stat.st_gid == gid {
stat.st_mode >> (3 * 1)
stat.st_mode >> 3
} else {
stat.st_mode
}) & 0o7;
@@ -204,7 +204,7 @@ impl Pal for Sys {
unsafe {
BRK_CUR = allocated;
BRK_END = (allocated as *mut u8).add(BRK_MAX_SIZE) as *mut c_void
BRK_END = allocated.cast::<u8>().add(BRK_MAX_SIZE).cast::<c_void>()
};
}
@@ -222,7 +222,7 @@ impl Pal for Sys {
}
fn chdir(path: CStr) -> Result<()> {
let path = RedoxStr::new_c(path.to_cstr()).ok_or_else(|| Errno(EINVAL))?;
let path = RedoxStr::new_c(path.to_cstr()).ok_or(Errno(EINVAL))?;
path::chdir(path)?;
Ok(())
}
@@ -243,11 +243,11 @@ impl Pal for Sys {
CLOCK_MONOTONIC => "/scheme/time/4/getres",
_ => return Err(Errno(EINVAL)),
};
let timerfd = FdGuard::open(&path, syscall::O_RDONLY)?;
let timerfd = FdGuard::open(path, syscall::O_RDONLY)?;
let mut redox_res = timespec::default();
let buffer = unsafe {
slice::from_raw_parts_mut(
&mut redox_res as *mut _ as *mut u8,
(&raw mut redox_res).cast::<u8>(),
mem::size_of::<timespec>(),
)
};
@@ -285,8 +285,7 @@ impl Pal for Sys {
}
fn exit(status: c_int) -> ! {
let _ = redox_rt::sys::posix_exit(status);
loop {}
redox_rt::sys::posix_exit(status)
}
unsafe fn execve(path: CStr, argv: *const *mut c_char, envp: *const *mut c_char) -> Result<()> {
@@ -382,7 +381,7 @@ impl Pal for Sys {
let start = start as u64 | if is_ofd { 1 << 63 } else { 0 };
let len = len as u64;
match flock.l_type as i32 {
match i32::from(flock.l_type) {
F_UNLCK => {
let meta = StdFsCallMeta::new(StdFsCallKind::Unlock, start, len);
syscall::std_fs_call(fd as usize, &mut [], &meta)?;
@@ -393,7 +392,7 @@ impl Pal for Sys {
let meta = StdFsCallMeta::new(
StdFsCallKind::Lock,
start,
len | if flock.l_type as i32 == F_WRLCK {
len | if i32::from(flock.l_type) == F_WRLCK {
1 << 63
} else {
0
@@ -429,7 +428,7 @@ impl Pal for Sys {
}
let mut len = len as u64;
if flock.l_type as i32 == F_WRLCK {
if i32::from(flock.l_type) == F_WRLCK {
len |= 1 << 63;
}
@@ -562,7 +561,7 @@ impl Pal for Sys {
#[inline]
unsafe fn futex_wait(addr: *mut u32, val: u32, deadline: Option<&timespec>) -> Result<()> {
let deadline = deadline.map(|d| syscall::TimeSpec::from(d));
let deadline = deadline.map(syscall::TimeSpec::from);
(unsafe { redox_rt::sys::sys_futex_wait(addr, val, deadline.as_ref()) })?;
Ok(())
}
@@ -611,7 +610,7 @@ impl Pal for Sys {
// NOTE: fn is unsafe, but this just means we can assume more things. impl is safe
unsafe fn dent_reclen_offset(this_dent: &[u8], offset: usize) -> Option<(u16, u64)> {
let mut header = DirentHeader::default();
header.copy_from_slice(&this_dent.get(..size_of::<DirentHeader>())?);
header.copy_from_slice(this_dent.get(..size_of::<DirentHeader>())?);
// If scheme does not send a NUL byte, this shouldn't be able to cause UB for the caller.
if this_dent.get(usize::from(header.record_len) - 1) != Some(&b'\0') {
@@ -665,7 +664,7 @@ impl Pal for Sys {
}
if found {
if !list.is_empty() && (count as usize) < list.len() {
if !list.is_empty() && count < list.len() {
list.index(count).write(grp.gr_gid);
}
count += 1;
@@ -674,7 +673,7 @@ impl Pal for Sys {
grp::endgrent();
}
if !list.is_empty() && (count as usize) > list.len() {
if !list.is_empty() && count > list.len() {
return Err(Errno(EINVAL));
}
@@ -698,9 +697,9 @@ impl Pal for Sys {
}
fn getpriority(which: c_int, who: id_t) -> Result<c_int> {
match redox_rt::sys::posix_getpriority(which, who as u32) {
match redox_rt::sys::posix_getpriority(which, who) {
Ok(kernel_prio) => {
let posix_prio = (kernel_prio as i32 * -1) + 40 as i32;
let posix_prio = -(kernel_prio as i32) + 40_i32;
Ok(posix_prio)
}
Err(e) => Err(Errno(e.errno)),
@@ -851,7 +850,7 @@ impl Pal for Sys {
if (flags & !(AT_SYMLINK_FOLLOW)) != 0 {
return Err(Errno(EINVAL));
}
let newpath = RedoxStr::new_c(newpath.to_cstr()).ok_or_else(|| Errno(EINVAL))?;
let newpath = RedoxStr::new_c(newpath.to_cstr()).ok_or(Errno(EINVAL))?;
// By default, we don't follow the symlink if there is one.
// We only follow it if AT_SYMLINK_FOLLOW is passed in flags.
@@ -992,7 +991,7 @@ impl Pal for Sys {
redox_rmtp = unsafe { (&*rmtp).into() };
}
match redox_rt::sys::posix_nanosleep(&redox_rqtp, &mut redox_rmtp) {
Ok(_) => Ok(()),
Ok(()) => Ok(()),
Err(Error { errno: EINTR }) => {
unsafe {
if !rmtp.is_null() {
@@ -1040,7 +1039,7 @@ impl Pal for Sys {
let total_offset = offset.checked_add(length).ok_or(Errno(EFBIG))?;
let mut stat: stat = unsafe { mem::zeroed() };
unsafe { libredox::fstat(fd as usize, &mut stat)? };
unsafe { libredox::fstat(fd as usize, &raw mut stat)? };
let st_size = stat.st_size as u64;
// The difference between total_offset and the file size is the number of bytes to
// allocate. So, if it's negative then the file is already large enough and we don't
@@ -1129,7 +1128,7 @@ impl Pal for Sys {
let redox_path = str::from_utf8(&buf[..count])
.ok()
.and_then(|x| redox_path::RedoxPath::from_absolute(x))
.and_then(redox_path::RedoxPath::from_absolute)
.ok_or(Errno(EINVAL))?;
let (scheme, reference) = redox_path.as_parts().ok_or(Errno(EINVAL))?;
@@ -1216,8 +1215,8 @@ impl Pal for Sys {
let clamped_prio = prio.clamp(-20, 19);
let kernel_prio = (20 + clamped_prio) as u32;
match redox_rt::sys::posix_setpriority(which, who as u32, kernel_prio) {
Ok(_) => Ok(()),
match redox_rt::sys::posix_setpriority(which, who, kernel_prio) {
Ok(()) => Ok(()),
Err(e) => Err(Errno(e.errno)),
}
}
@@ -1290,7 +1289,7 @@ impl Pal for Sys {
}
}
args[0] = &program.to_bytes();
args[0] = program.to_bytes();
let new_file_table = child.thr_fd.dup_into_upper(b"filetable-binary")?;
@@ -1606,7 +1605,7 @@ impl Pal for Sys {
CLOCK_MONOTONIC => "/scheme/time/4",
_ => return Err(Errno(EINVAL)),
};
let timerfd = FdGuard::open_into_upper(&path, syscall::O_RDWR)?;
let timerfd = FdGuard::open_into_upper(path, syscall::O_RDWR)?;
let eventfd = FdGuard::new(Error::demux(unsafe {
event::redox_event_queue_create_v1(0)
})?)
@@ -1627,7 +1626,7 @@ impl Pal for Sys {
let mut memory_pointer: *mut timer_internal_t = ptr::null_mut();
unsafe {
let result = posix_memalign(
(&mut memory_pointer as *mut *mut timer_internal_t).cast(),
(&raw mut memory_pointer).cast(),
align_of::<timer_internal_t>(),
size_of::<timer_internal_t>(),
);
@@ -1653,36 +1652,44 @@ impl Pal for Sys {
Ok(())
}
#[expect(clippy::not_unsafe_ptr_arg_deref)]
fn timer_delete(timerid: timer_t) -> Result<()> {
let timers = &mut TIMERS.lock().0;
let removed = timers.remove(&timerid);
if !removed {
return Err(Errno(EINVAL));
}
// SAFETY: `timerid` should have already been created via `timer_create()`
// before calling `timer_delete()` so should not be NULL
let timer_st = unsafe { timer_internal_t::from_raw(timerid) };
let _ = redox_rt::sys::close(timer_st.timerfd);
let _ = redox_rt::sys::close(timer_st.eventfd);
if !timer_st.thread.is_null() {
let _ = unsafe { pthread_cancel(timer_st.thread) };
}
// SAFETY: `timerid` should have already been created via `timer_create()`
// before calling `timer_delete()` so should not be NULL
unsafe { free(timerid) };
Ok(())
}
#[expect(clippy::not_unsafe_ptr_arg_deref)]
fn timer_gettime(timerid: timer_t, mut value: Out<itimerspec>) -> Result<()> {
let timers = &mut TIMERS.lock().0;
if !timers.contains(&timerid) {
return Err(Errno(EINVAL));
}
// SAFETY: `timerid` should have already been created via `timer_create()`
// before calling `timer_delete()` so should not be NULL
let timer_st = unsafe { timer_internal_t::from_raw(timerid) };
let mut now = timespec::default();
Self::clock_gettime(timer_st.clockid, Out::from_mut(&mut now))?;
if timer_st.evp.sigev_notify == SIGEV_NONE {
if timespec::subtract(&timer_st.next_wake_time.it_value, &now).is_none() {
// error here means the timer is disarmed
let _ = timer_update_wake_time(timer_st);
}
if timer_st.evp.sigev_notify == SIGEV_NONE
&& timespec::subtract(&timer_st.next_wake_time.it_value, &now).is_none()
{
// error here means the timer is disarmed
let _ = timer_update_wake_time(timer_st);
}
let remaining = &timer_st.next_wake_time.it_value;
value.write(if remaining.is_zero() {
@@ -1698,6 +1705,7 @@ impl Pal for Sys {
Ok(())
}
#[expect(clippy::not_unsafe_ptr_arg_deref)]
fn timer_settime(
timerid: timer_t,
flags: c_int,
@@ -1712,6 +1720,8 @@ impl Pal for Sys {
if !timers.contains(&timerid) {
return Err(Errno(EINVAL));
}
// SAFETY: `timerid` should have already been created via `timer_create()`
// before calling `timer_delete()` so should not be NULL
let timer_st = unsafe { timer_internal_t::from_raw(timerid) };
if value.it_value.is_zero() {
@@ -1747,10 +1757,10 @@ impl Pal for Sys {
let mut tid = pthread_t::default();
let result = unsafe {
pthread_create(
&mut tid as *mut _,
&raw mut tid,
ptr::null(),
timer_routine,
timerid as *mut c_void,
timerid.cast::<c_void>(),
)
};
if result != 0 {
@@ -1804,21 +1814,19 @@ impl Pal for Sys {
}
match gethostname(nodename.as_slice_mut().cast_slice_to::<u8>()) {
Ok(_) => (),
Ok(()) => (),
Err(_) => return Err(Errno(EIO)),
}
let file_path = c"/scheme/sys/uname".into();
let mut file = match File::open(file_path, fcntl::O_RDONLY | fcntl::O_CLOEXEC) {
Ok(ok) => ok,
Err(_) => return Err(Errno(EIO)),
let Ok(mut file) = File::open(file_path, fcntl::O_RDONLY | fcntl::O_CLOEXEC) else {
return Err(Errno(EIO));
};
let mut lines = BufReader::new(&mut file).lines();
let mut read_line = |mut dst: Out<[u8]>| {
let mut line = match lines.next() {
Some(Ok(l)) => l,
None | Some(Err(_)) => return Err(Errno(EIO)),
let Some(Ok(mut line)) = lines.next() else {
return Err(Errno(EIO));
};
line.push('\0');
let line_slice: &[u8] = line.as_bytes();
@@ -1864,6 +1872,7 @@ impl Pal for Sys {
Ok(())
}
#[expect(clippy::unnecessary_literal_unwrap, reason = "res needs refactoring")]
fn waitpid(pid: pid_t, stat_loc: Option<Out<'_, c_int>>, options: c_int) -> Result<pid_t> {
let res = None;
let mut status = 0;
@@ -1962,7 +1971,7 @@ impl Sys {
len: off_t,
) -> Result<(off_t, off_t)> {
// let file_off = Self::lseek(fd, 0, SEEK_SET)?;
match whence as i32 {
match i32::from(whence) {
SEEK_SET => {
let (start, len) = if len < 0 {
(start + len, -len)
+23 -14
View File
@@ -29,7 +29,7 @@ pub fn chdir(path: RedoxStr<'_>) -> Result<()> {
let (redox, fd) = match path {
RedoxStr::Absolute(path) => {
let path = path.to_standard_canon();
let fd = FdGuard::open_into_upper(&path.as_reference(), O_STAT);
let fd = FdGuard::open_into_upper(path.as_reference(), O_STAT);
(path.into_owned(), fd)
}
RedoxStr::Relative(redox_reference) => {
@@ -112,7 +112,7 @@ pub struct Cwd<'a> {
static CWD: RwLock<Option<Cwd<'_>>> = RwLock::new(None);
pub fn to_cwd_path(path: &str) -> Result<CwdPath> {
ArrayString::from_str(&path).or(Err(Error::new(ENAMETOOLONG)))
ArrayString::from_str(path).or(Err(Error::new(ENAMETOOLONG)))
}
pub fn set_cwd_manual(path: CwdPath, fd: FdGuardUpper) -> Result<()> {
@@ -126,7 +126,7 @@ pub fn set_cwd_manual(path: CwdPath, fd: FdGuardUpper) -> Result<()> {
pub fn clone_cwd() -> Option<CwdPath> {
let _siglock = tmp_disable_signals();
CWD.read().as_ref().map(|cwd| cwd.path.clone())
CWD.read().as_ref().map(|cwd| cwd.path)
}
fn open_absolute(path: &str, flags: usize) -> Result<usize> {
@@ -138,9 +138,9 @@ fn open_absolute(path: &str, flags: usize) -> Result<usize> {
}
// Read symlink content
fn read_link_content<'a, 'b>(
fn read_link_content<'b>(
dirfd: Option<&FdGuard>,
path: &'a str,
path: &str,
is_relative: bool,
) -> Result<RedoxStr<'b>> {
let resolve_flags = O_CLOEXEC | O_SYMLINK | O_RDONLY;
@@ -156,7 +156,7 @@ fn read_link_content<'a, 'b>(
log::trace!(
"read_link_content ({:?} {:?} {}): {:?}",
dirfd,
&path,
path,
is_relative,
fd
);
@@ -180,7 +180,7 @@ fn resolve_sym_links<'a>(mut current_path_string: RedoxPath<'a>, flags: usize) -
let dirname = current_path_string.dirname();
let cow: Cow<'_, str> = current_path_string.into();
let initial_res = open_absolute(&cow, flags);
log::trace!("resolve_sym_links({:?}): {:?}", &cow, initial_res);
log::trace!("resolve_sym_links({:?}): {:?}", cow, initial_res);
match initial_res {
Ok(fd) => return Ok(fd),
Err(e) if e == Error::new(EXDEV) => {
@@ -309,12 +309,21 @@ pub struct FileLock(c_int);
impl FileLock {
pub fn lock(fd: c_int, op: c_int) -> Result<Self> {
if op & sys_file::LOCK_SH | sys_file::LOCK_EX == 0 {
return Err(Error::new(EINVAL));
const LOCK_SH_NB: c_int = sys_file::LOCK_SH | sys_file::LOCK_NB;
const LOCK_EX_NB: c_int = sys_file::LOCK_EX | sys_file::LOCK_NB;
const LOCK_UN_NB: c_int = sys_file::LOCK_UN | sys_file::LOCK_NB;
match op {
sys_file::LOCK_SH
| sys_file::LOCK_EX
| sys_file::LOCK_UN
| LOCK_SH_NB
| LOCK_EX_NB
| LOCK_UN_NB => {
Sys::flock(fd, op)?;
Ok(Self(fd))
}
_ => Err(Error::new(EINVAL)),
}
Sys::flock(fd, op)?;
Ok(Self(fd))
}
pub fn unlock(self) -> Result<()> {
@@ -384,14 +393,14 @@ fn at_flags_to_open_flags(at_flags: c_int) -> c_int {
/// # Arguments
/// * `dirfd` is a directory descriptor to which `path` is resolved.
/// * `path` is a relative or absolute path. Relative paths are resolved in relation to `dirfd`
/// while absolute paths skip `dirfd`.
/// while absolute paths skip `dirfd`.
/// * `at_flags` constrains how `path` is resolved.
/// * `oflags` are flags that are passed to open.
///
/// # Constants
/// `at_flags`:
/// * AT_EMPTY_PATH returns the path at `dirfd` itself if `path` is empty. If `path` is not
/// empty, it's resolved w.r.t `dirfd` like normal.
/// empty, it's resolved w.r.t `dirfd` like normal.
///
/// `dirfd`:
/// `AT_FDCWD` is a special constant for `dirfd` that resolves `path` under the current working
+3 -3
View File
@@ -60,7 +60,7 @@ pub fn init_state() -> &'static State {
if STATE.unsafe_ref().is_none() {
STATE.unsafe_set(Some(State::new()));
}
let state_ptr = STATE.unsafe_ref().as_ref().unwrap() as *const State;
let state_ptr = core::ptr::from_ref::<State>(STATE.unsafe_ref().as_ref().unwrap());
&*state_ptr
}
}
@@ -193,7 +193,7 @@ unsafe fn inner_ptrace(
Ok(0)
}
sys_ptrace::PTRACE_GETREGS => {
let c_regs = unsafe { &mut *(data as *mut user_regs_struct) };
let c_regs = unsafe { &mut *data.cast::<user_regs_struct>() };
let mut redox_regs = syscall::IntRegisters::default();
(&mut &session.regs).read(&mut redox_regs)?;
*c_regs = user_regs_struct {
@@ -228,7 +228,7 @@ unsafe fn inner_ptrace(
Ok(0)
}
sys_ptrace::PTRACE_SETREGS => {
let c_regs = unsafe { &*(data as *mut user_regs_struct) };
let c_regs = unsafe { &*data.cast::<user_regs_struct>() };
let redox_regs = syscall::IntRegisters {
r15: c_regs.r15 as _,
r14: c_regs.r14 as _,
+24 -4
View File
@@ -115,7 +115,14 @@ impl PalSignal for Sys {
SigactionKind::Handled {
handler: if c_act.sa_flags & crate::header::signal::SA_SIGINFO as c_int != 0 {
SignalHandler {
sigaction: unsafe { core::mem::transmute(c_act.sa_handler) },
sigaction: unsafe {
core::mem::transmute::<
core::option::Option<extern "C" fn(i32)>,
core::option::Option<
unsafe extern "C" fn(i32, *const (), *mut ()),
>,
>(c_act.sa_handler)
},
}
} else {
SignalHandler {
@@ -138,20 +145,33 @@ impl PalSignal for Sys {
if let (Some(c_oact), Some(old_action)) = (c_oact, old_action) {
*c_oact = match old_action.kind {
SigactionKind::Ignore => sigaction {
sa_handler: unsafe { core::mem::transmute(SIG_IGN) },
sa_handler: unsafe {
core::mem::transmute::<usize, core::option::Option<extern "C" fn(i32)>>(
SIG_IGN,
)
},
sa_flags: 0,
sa_restorer: None,
sa_mask: 0,
},
SigactionKind::Default => sigaction {
sa_handler: unsafe { core::mem::transmute(SIG_DFL) },
sa_handler: unsafe {
core::mem::transmute::<usize, core::option::Option<extern "C" fn(i32)>>(
SIG_DFL,
)
},
sa_flags: 0,
sa_restorer: None,
sa_mask: 0,
},
SigactionKind::Handled { handler } => sigaction {
sa_handler: if old_action.flags.contains(SigactionFlags::SIGINFO) {
unsafe { core::mem::transmute(handler.sigaction) }
unsafe {
core::mem::transmute::<
core::option::Option<unsafe extern "C" fn(i32, *const (), *mut ())>,
core::option::Option<extern "C" fn(i32)>,
>(handler.sigaction)
}
} else {
unsafe { handler.handler }
},
+78 -72
View File
@@ -1,4 +1,4 @@
use alloc::{borrow::Cow, vec::Vec};
use alloc::{borrow::Cow, string::ToString, vec::Vec};
use core::{cmp, mem, ptr, slice, str};
use redox_path::RedoxStr;
use redox_protocols::protocol::{FsCall, O_CLOEXEC, SocketCall};
@@ -42,16 +42,16 @@ unsafe fn bind_or_connect(
return Err(Errno(EINVAL));
}
let path = match unsafe { (*address).sa_family } as c_int {
let path = match c_int::from(unsafe { (*address).sa_family }) {
AF_INET => {
if (address_len as usize) != mem::size_of::<sockaddr_in>() {
return Err(Errno(EINVAL));
}
let data = unsafe { &*(address as *const sockaddr_in) };
let data = unsafe { &*address.cast::<sockaddr_in>() };
let addr = unsafe {
slice::from_raw_parts(
&data.sin_addr.s_addr as *const _ as *const u8,
(&raw const data.sin_addr.s_addr).cast::<u8>(),
mem::size_of_val(&data.sin_addr.s_addr),
)
};
@@ -78,7 +78,7 @@ unsafe fn bind_or_connect(
}
SocketCall::Connect => {
// When a connect is made using AF_UNSPEC TCP and UDP need to disconnect from the default peer
format!("disconnect")
"disconnect".to_string()
}
_ => unreachable!(),
},
@@ -101,12 +101,12 @@ pub unsafe fn bind_or_connect_into(
}
unsafe fn inner_af_unix(buf: &[u8], address: *mut sockaddr, address_len: *mut socklen_t) {
let data = unsafe { &mut *(address as *mut sockaddr_un) };
let data = unsafe { &mut *address.cast::<sockaddr_un>() };
data.sun_family = AF_UNIX as c_ushort;
let path = unsafe {
slice::from_raw_parts_mut(&mut data.sun_path as *mut _ as *mut u8, data.sun_path.len())
slice::from_raw_parts_mut((&raw mut data.sun_path).cast::<u8>(), data.sun_path.len())
};
let len = cmp::min(path.len(), buf.len());
@@ -142,11 +142,11 @@ unsafe fn inner_af_inet(
// Make address be followed by a NUL-byte
colon[0] = b'\0';
log::trace!("address: {:?}, port: {:?}", str::from_utf8(&raw_addr), port);
log::trace!("address: {:?}, port: {:?}", str::from_utf8(raw_addr), port);
let mut addr = in_addr::default();
assert_eq!(
unsafe { inet_aton(raw_addr.as_ptr() as *mut c_char, &mut addr) },
unsafe { inet_aton(raw_addr.as_ptr() as *mut c_char, &raw mut addr) },
1,
"inet_aton might be broken, failed to parse netstack address"
);
@@ -161,7 +161,7 @@ unsafe fn inner_af_inet(
let len = cmp::min(unsafe { *address_len } as usize, mem::size_of_val(&ret));
unsafe {
ptr::copy_nonoverlapping(&ret as *const _ as *const u8, address as *mut u8, len);
ptr::copy_nonoverlapping((&raw const ret).cast::<u8>(), address.cast::<u8>(), len);
*address_len = len as socklen_t;
}
}
@@ -282,11 +282,11 @@ unsafe fn serialize_ancillary_data_to_stream(
let fds_usize: Vec<usize> = c_fds.iter().map(|&fd| fd as usize).collect();
let fds_slice = unsafe {
slice::from_raw_parts(
fds_usize.as_ptr() as *const u8,
fds_usize.as_ptr().cast::<u8>(),
fds_usize.len() * mem::size_of::<usize>(),
)
};
redox_rt::sys::sys_call_wo(socket as usize, &fds_slice, CallFlags::FD, &[])?;
redox_rt::sys::sys_call_wo(socket as usize, fds_slice, CallFlags::FD, &[])?;
}
// Serialize to ancillary_data_stream.
@@ -300,7 +300,7 @@ unsafe fn serialize_ancillary_data_to_stream(
(SOL_SOCKET, SCM_CREDENTIALS) => {
// Our intermediate format: data_len is 0, no data payload
let data_for_stream_len = 0usize;
msg_stream.extend_from_slice(&(data_for_stream_len as usize).to_le_bytes());
msg_stream.extend_from_slice(&data_for_stream_len.to_le_bytes());
}
_ => {
return Err(Errno(EOPNOTSUPP));
@@ -330,8 +330,8 @@ unsafe fn deserialize_name_from_stream(
(unsafe {
inner_get_name_inner(
false,
mhdr.msg_name as *mut sockaddr,
&mut mhdr.msg_namelen,
mhdr.msg_name.cast::<sockaddr>(),
&raw mut mhdr.msg_namelen,
name_buffer,
)
})?;
@@ -380,7 +380,7 @@ unsafe fn deserialize_payload_from_stream(
let bytes_to_write = cmp::min(iov.iov_len, source_bytes_remaining);
if bytes_to_write > 0 {
let dest_slice: &mut [u8] =
unsafe { slice::from_raw_parts_mut(iov.iov_base as *mut u8, iov.iov_len) };
unsafe { slice::from_raw_parts_mut(iov.iov_base.cast::<u8>(), iov.iov_len) };
let source_sub_slice = &payload_data_from_stream
[source_bytes_consumed..source_bytes_consumed + bytes_to_write];
@@ -448,13 +448,13 @@ unsafe fn deserialize_ancillary_data_from_stream(
if cmsg_data_len_in_stream != mem::size_of::<usize>() {
return Err(Errno(EINVAL));
}
let fd_count = read_num::<usize>(&cmsg_data_from_stream)?;
let fd_count = read_num::<usize>(cmsg_data_from_stream)?;
let mut fds_usize = vec![0usize; fd_count];
let fds_bytes = unsafe {
slice::from_raw_parts_mut(
fds_usize.as_mut_ptr() as *mut u8,
fds_usize.as_mut_ptr().cast::<u8>(),
fds_usize.len() * mem::size_of::<usize>(),
)
};
@@ -478,7 +478,7 @@ unsafe fn deserialize_ancillary_data_from_stream(
return Err(Errno(EINVAL));
}
let pid = read_num::<pid_t>(&cmsg_data_from_stream)?;
let pid = read_num::<pid_t>(cmsg_data_from_stream)?;
let uid_offset = mem::size_of::<pid_t>();
let uid = read_num::<uid_t>(&cmsg_data_from_stream[uid_offset..])?;
let gid_offset = uid_offset + mem::size_of::<uid_t>();
@@ -486,10 +486,7 @@ unsafe fn deserialize_ancillary_data_from_stream(
let cred = ucred { pid, uid, gid };
temp_posix_cmsg_data_buf.extend_from_slice(unsafe {
slice::from_raw_parts(
&cred as *const ucred as *const u8,
mem::size_of::<ucred>(),
)
slice::from_raw_parts((&raw const cred).cast::<u8>(), mem::size_of::<ucred>())
});
temp_posix_cmsg_data_buf.len()
}
@@ -513,7 +510,7 @@ unsafe fn deserialize_ancillary_data_from_stream(
unsafe {
ptr::copy_nonoverlapping(
temp_posix_cmsg_data_buf.as_ptr(),
data_ptr_in_user_cmsg as *mut u8,
data_ptr_in_user_cmsg.cast::<u8>(),
actual_posix_cmsg_data_len,
)
};
@@ -539,22 +536,23 @@ impl PalSocket for Sys {
address_len: *mut socklen_t,
) -> Result<c_int> {
let stream = redox_rt::sys::dup(socket as usize, b"listen")?;
if address != ptr::null_mut() && address_len != ptr::null_mut() {
if let Err(err) = unsafe { Self::getpeername(stream as c_int, address, address_len) } {
let _ = redox_rt::sys::close(stream);
return Err(err);
}
if !address.is_null()
&& !address_len.is_null()
&& let Err(err) = unsafe { Self::getpeername(stream as c_int, address, address_len) }
{
let _ = redox_rt::sys::close(stream);
return Err(err);
}
Ok(stream as c_int)
}
unsafe fn bind(socket: c_int, address: *const sockaddr, address_len: socklen_t) -> Result<()> {
match unsafe { (*address).sa_family } as c_int {
match c_int::from(unsafe { (*address).sa_family }) {
AF_INET => {
(unsafe { bind_or_connect_into(SocketCall::Bind, socket, address, address_len) })?;
}
AF_UNIX => {
let data = unsafe { &*(address as *const sockaddr_un) };
let data = unsafe { &*address.cast::<sockaddr_un>() };
// NOTE: It's UB to access data in given address that exceeds
// the given address length.
@@ -569,11 +567,15 @@ impl PalSocket for Sys {
// The maximum length of the address
maxlen,
// The first NUL byte, if any
unsafe { strnlen(&data.sun_path as *const _, maxlen as size_t) },
// FIXME applying clippy suggestion fails to compile
#[expect(clippy::borrow_as_ptr)]
unsafe {
strnlen(&data.sun_path as *const _, maxlen as size_t)
},
);
let addr =
unsafe { slice::from_raw_parts(&data.sun_path as *const _ as *const u8, len) };
unsafe { slice::from_raw_parts((&raw const data.sun_path).cast::<u8>(), len) };
let path = str::from_utf8(addr).map_err(|_| Errno(EINVAL))?;
log::trace!("bind(): path: {:?}", path);
@@ -635,12 +637,12 @@ impl PalSocket for Sys {
address: *const sockaddr,
address_len: socklen_t,
) -> Result<c_int> {
match unsafe { (*address).sa_family } as c_int {
match c_int::from(unsafe { (*address).sa_family }) {
AF_INET => unsafe {
bind_or_connect_into(SocketCall::Connect, socket, address, address_len)
},
AF_UNIX => {
let data = unsafe { &*(address as *const sockaddr_un) };
let data = unsafe { &*address.cast::<sockaddr_un>() };
// NOTE: It's UB to access data in given address that exceeds
// the given address length.
@@ -655,11 +657,15 @@ impl PalSocket for Sys {
// The maximum length of the address
maxlen,
// The first NUL byte, if any
unsafe { strnlen(&data.sun_path as *const _, maxlen as size_t) },
// FIXME applying clippy suggestion fails to compile
#[expect(clippy::borrow_as_ptr)]
unsafe {
strnlen(&data.sun_path as *const _, maxlen as size_t)
},
);
let addr =
unsafe { slice::from_raw_parts(&data.sun_path as *const _ as *const u8, len) };
unsafe { slice::from_raw_parts((&raw const data.sun_path).cast::<u8>(), len) };
let path = str::from_utf8(addr).map_err(|_| Errno(EINVAL))?;
log::trace!("bind(): path: {:?}", path);
@@ -743,11 +749,12 @@ impl PalSocket for Sys {
return Err(Errno(EINVAL));
}
Ok(unsafe { &mut *(option_value as *mut c_int) })
Ok(unsafe { &mut *option_value.cast::<c_int>() })
};
match level {
SOL_SOCKET => match option_name {
// TODO convert back to match when we support more levels
if level == SOL_SOCKET {
match option_name {
SO_DOMAIN => {
let option = option_c_int()?;
*option = socket_domain_type(socket)?.0;
@@ -770,7 +777,7 @@ impl PalSocket for Sys {
_ => {
let metadata = [SocketCall::GetSockOpt as u64, option_name as u64];
let payload =
unsafe { slice::from_raw_parts_mut(option_value as *mut u8, option_len) };
unsafe { slice::from_raw_parts_mut(option_value.cast::<u8>(), option_len) };
let call_flags = CallFlags::empty();
unsafe {
*option_len_ptr = redox_rt::sys::sys_call_ro(
@@ -782,8 +789,7 @@ impl PalSocket for Sys {
}
return Ok(());
}
},
_ => (),
}
}
todo_skip!(
@@ -813,7 +819,7 @@ impl PalSocket for Sys {
) -> Result<usize> {
if address.is_null() && flags == 0 {
Self::read(socket, unsafe {
slice::from_raw_parts_mut(buf as *mut u8, len)
slice::from_raw_parts_mut(buf.cast::<u8>(), len)
})
} else {
// Convert to recvmsg
@@ -822,23 +828,23 @@ impl PalSocket for Sys {
iov_len: len,
};
let mut msg = msghdr {
msg_name: address as *mut c_void,
msg_name: address.cast::<c_void>(),
msg_namelen: if !address_len.is_null() {
unsafe { *address_len }
} else {
0
},
msg_iov: &mut iov,
msg_iov: &raw mut iov,
msg_iovlen: 1,
msg_control: ptr::null_mut(),
msg_controllen: 0,
msg_flags: 0,
};
let count = unsafe { Self::recvmsg(socket, &mut msg, flags) }?;
let count = unsafe { Self::recvmsg(socket, &raw mut msg, flags) }?;
if !address_len.is_null() {
unsafe { *address_len = msg.msg_namelen };
}
return Ok(count);
Ok(count)
}
}
@@ -846,11 +852,11 @@ impl PalSocket for Sys {
if msg.is_null() {
return Err(Errno(EINVAL));
}
let mut mhdr = unsafe { &mut *msg };
let mhdr = unsafe { &mut *msg };
let iovs_slice: &[iovec] = if mhdr.msg_iov.is_null() || mhdr.msg_iovlen == 0 {
&[]
} else {
unsafe { slice::from_raw_parts(mhdr.msg_iov, mhdr.msg_iovlen as usize) }
unsafe { slice::from_raw_parts(mhdr.msg_iov, mhdr.msg_iovlen) }
};
let whole_iov_size: usize = iovs_slice.iter().map(|iov| iov.iov_len).sum();
@@ -867,7 +873,7 @@ impl PalSocket for Sys {
+ mem::size_of::<usize>() // payload_len
+ whole_iov_size // payload_data_buffer
+ mem::size_of::<usize>() // control_len
+ mhdr.msg_controllen as usize // ancillary_stream_buffer
+ mhdr.msg_controllen // ancillary_stream_buffer
};
msg_stream
.try_reserve_exact(expected_stream_size)
@@ -883,7 +889,7 @@ impl PalSocket for Sys {
.copy_from_slice(&(whole_iov_size).to_le_bytes());
cursor += mem::size_of::<usize>();
msg_stream[cursor..cursor + mem::size_of::<usize>()]
.copy_from_slice(&(mhdr.msg_controllen as usize).to_le_bytes());
.copy_from_slice(&mhdr.msg_controllen.to_le_bytes());
// Read the message stream.
let metadata = [SocketCall::RecvMsg as u64, flags as u64];
@@ -897,12 +903,12 @@ impl PalSocket for Sys {
mhdr.msg_flags = 0;
// Read sender name.
(unsafe { deserialize_name_from_stream(&mut mhdr, &msg_stream, &mut cursor) })?;
(unsafe { deserialize_name_from_stream(mhdr, &msg_stream, &mut cursor) })?;
// Read payload data.
let actual_payload_bytes_written_to_iov = unsafe {
deserialize_payload_from_stream(
&mut mhdr,
mhdr,
&msg_stream,
iovs_slice,
whole_iov_size,
@@ -921,7 +927,7 @@ impl PalSocket for Sys {
socket,
&msg_stream,
&mut cursor,
cmsg_space_provided_by_user as usize,
cmsg_space_provided_by_user,
flags,
)
})?;
@@ -943,7 +949,7 @@ impl PalSocket for Sys {
let iovs_slice: &[iovec] = if mhdr.msg_iov.is_null() || mhdr.msg_iovlen == 0 {
&[]
} else {
unsafe { slice::from_raw_parts(mhdr.msg_iov, mhdr.msg_iovlen as usize) }
unsafe { slice::from_raw_parts(mhdr.msg_iov, mhdr.msg_iovlen) }
};
let mut msg_stream: Vec<u8> = Vec::new();
@@ -952,7 +958,7 @@ impl PalSocket for Sys {
.try_reserve_exact(
mem::size_of::<usize>() // payload_len
+ whole_iov_size // payload_data_buffer
+ mhdr.msg_controllen as usize, // ancillary_stream_buffer
+ mhdr.msg_controllen, // ancillary_stream_buffer
)
.map_err(|_| Errno(ENOMEM))?;
@@ -960,7 +966,7 @@ impl PalSocket for Sys {
let mut actual_payload_bytes_serialized = 0;
if !mhdr.msg_iov.is_null() && mhdr.msg_iovlen > 0 {
actual_payload_bytes_serialized = unsafe {
serialize_payload_to_stream(&mut msg_stream, &iovs_slice, whole_iov_size)
serialize_payload_to_stream(&mut msg_stream, iovs_slice, whole_iov_size)
}?;
}
// Process Control Messages from msghdr and serialize them.
@@ -995,30 +1001,30 @@ impl PalSocket for Sys {
if flags != 0 {
// Convert to sendmsg
let mut iov = iovec {
iov_base: buf as *mut c_void,
iov_base: buf.cast_mut(),
iov_len: len,
};
let msg = msghdr {
msg_name: dest_addr as *mut c_void,
msg_namelen: dest_len,
msg_iov: &mut iov,
msg_iov: &raw mut iov,
msg_iovlen: 1,
msg_control: ptr::null_mut(),
msg_controllen: 0,
msg_flags: 0,
};
return unsafe { Self::sendmsg(socket, &msg, flags) };
return unsafe { Self::sendmsg(socket, &raw const msg, flags) };
}
if dest_addr == ptr::null() || dest_len == 0 {
if dest_addr.is_null() || dest_len == 0 {
Self::write(socket, unsafe {
slice::from_raw_parts(buf as *const u8, len)
slice::from_raw_parts(buf.cast::<u8>(), len)
})
} else {
let fd = FdGuard::new(unsafe {
bind_or_connect(SocketCall::Connect, socket, dest_addr, dest_len)
}?);
Self::write(fd.as_c_fd().unwrap(), unsafe {
slice::from_raw_parts(buf as *const u8, len)
slice::from_raw_parts(buf.cast::<u8>(), len)
})
}
}
@@ -1039,7 +1045,7 @@ impl PalSocket for Sys {
return Err(Errno(EINVAL));
}
let timeval = unsafe { &*(option_value as *const timeval) };
let timeval = unsafe { &*option_value.cast::<timeval>() };
let fd = FdGuard::new(redox_rt::sys::dup(socket as usize, timeout_name)?);
@@ -1048,7 +1054,7 @@ impl PalSocket for Sys {
};
let timespec = syscall::TimeSpec {
tv_sec: timeval.tv_sec as i64,
tv_sec: timeval.tv_sec,
tv_nsec,
};
@@ -1056,8 +1062,9 @@ impl PalSocket for Sys {
Ok(())
};
match level {
SOL_SOCKET => match option_name {
// TODO convert back to match when we support more levels
if level == SOL_SOCKET {
match option_name {
SO_RCVTIMEO => return set_timeout(b"read_timeout"),
SO_SNDTIMEO => return set_timeout(b"write_timeout"),
_ => {
@@ -1074,8 +1081,7 @@ impl PalSocket for Sys {
)?;
return Ok(());
}
},
_ => (),
}
}
todo_skip!(
@@ -1183,7 +1189,7 @@ impl NumFromBytes for i32 {
buffer
.get(..mem::size_of::<i32>())
.and_then(|slice| slice.try_into().ok())
.ok_or_else(|| Errno(EFAULT))?,
.ok_or(Errno(EFAULT))?,
))
}
}
@@ -1193,7 +1199,7 @@ impl NumFromBytes for usize {
buffer
.get(..mem::size_of::<usize>())
.and_then(|slice| slice.try_into().ok())
.ok_or_else(|| Errno(EFAULT))?,
.ok_or(Errno(EFAULT))?,
))
}
}
+5 -6
View File
@@ -70,16 +70,15 @@ pub extern "C" fn timer_routine(arg: *mut c_void) -> *mut c_void {
if let Some(fun) = timer_st.evp.sigev_notify_function {
fun(timer_st.evp.sigev_value);
}
} else if timer_st.evp.sigev_notify == SIGEV_SIGNAL {
if Sys::sigqueue(
} else if timer_st.evp.sigev_notify == SIGEV_SIGNAL
&& Sys::sigqueue(
timer_st.process_pid,
timer_st.evp.sigev_signo as _,
timer_st.evp.sigev_value,
)
.is_err()
{
break;
}
{
break;
}
}
@@ -107,7 +106,7 @@ fn timer_next_event(timer_st: &mut timer_internal_t) -> Result<()> {
syscall::TimeSpec::from(&timer_st.next_wake_time.it_value)
};
let bytes_written = redox_rt::sys::posix_write(timer_st.timerfd, &*buf_to_write)?;
let bytes_written = redox_rt::sys::posix_write(timer_st.timerfd, &buf_to_write)?;
if bytes_written < size_of::<timespec>() {
return Err(Errno(EIO));
}