Preserve relibc overlay carriers
Ultraworked with [Sisyphus](https://github.com/code-yeongyu/oh-my-openagent) Co-authored-by: Sisyphus <clio-agent@sisyphuslabs.ai>
This commit is contained in:
@@ -1,19 +1,23 @@
|
||||
diff --git a/src/header/mod.rs b/src/header/mod.rs
|
||||
--- a/src/header/mod.rs
|
||||
+++ b/src/header/mod.rs
|
||||
@@ -88,6 +88,7 @@
|
||||
diff -ruN a/src/header/mod.rs b/src/header/mod.rs
|
||||
--- a/src/header/mod.rs 2026-04-15 09:40:30.417847129 +0100
|
||||
+++ b/src/header/mod.rs 2026-04-15 09:46:42.009254774 +0100
|
||||
@@ -89,6 +89,7 @@
|
||||
// TODO: stropts.h (deprecated)
|
||||
pub mod sys_auxv;
|
||||
pub mod sys_epoll;
|
||||
+pub mod sys_eventfd;
|
||||
pub mod sys_file;
|
||||
pub mod sys_ioctl;
|
||||
diff --git a/src/header/sys_eventfd/cbindgen.toml b/src/header/sys_eventfd/cbindgen.toml
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/src/header/sys_eventfd/cbindgen.toml
|
||||
@@ -0,0 +1,9 @@
|
||||
// TODO: sys/ipc.h
|
||||
diff -ruN a/src/header/sys_eventfd/cbindgen.toml b/src/header/sys_eventfd/cbindgen.toml
|
||||
--- a/src/header/sys_eventfd/cbindgen.toml 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/src/header/sys_eventfd/cbindgen.toml 2026-04-15 09:46:42.009280833 +0100
|
||||
@@ -0,0 +1,12 @@
|
||||
+sys_includes = ["stdint.h"]
|
||||
+include_guard = "_SYS_EVENTFD_H"
|
||||
+trailer = """
|
||||
+typedef uint64_t eventfd_t;
|
||||
+"""
|
||||
+language = "C"
|
||||
+style = "Tag"
|
||||
+no_includes = true
|
||||
@@ -21,11 +25,10 @@ new file mode 100644
|
||||
+
|
||||
+[enum]
|
||||
+prefix_with_name = true
|
||||
diff --git a/src/header/sys_eventfd/mod.rs b/src/header/sys_eventfd/mod.rs
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/src/header/sys_eventfd/mod.rs
|
||||
@@ -0,0 +1,89 @@
|
||||
diff -ruN a/src/header/sys_eventfd/mod.rs b/src/header/sys_eventfd/mod.rs
|
||||
--- a/src/header/sys_eventfd/mod.rs 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/src/header/sys_eventfd/mod.rs 2026-04-15 09:46:42.009305629 +0100
|
||||
@@ -0,0 +1,90 @@
|
||||
+//! `sys/eventfd.h` implementation.
|
||||
+//!
|
||||
+//! Non-POSIX, see <https://man7.org/linux/man-pages/man2/eventfd.2.html>.
|
||||
@@ -47,6 +50,7 @@ new file mode 100644
|
||||
+pub const EFD_CLOEXEC: c_int = 0x80000;
|
||||
+pub const EFD_NONBLOCK: c_int = 0x800;
|
||||
+pub const EFD_SEMAPHORE: c_int = 0x1;
|
||||
+pub type eventfd_t = u64;
|
||||
+
|
||||
+fn read_exact(fd: c_int, buf: &mut [u8]) -> Result<(), Errno> {
|
||||
+ match Sys::read(fd, buf)? {
|
||||
@@ -101,17 +105,17 @@ new file mode 100644
|
||||
+}
|
||||
+
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub unsafe extern "C" fn eventfd_read(fd: c_int, value: *mut u64) -> c_int {
|
||||
+pub unsafe extern "C" fn eventfd_read(fd: c_int, value: *mut eventfd_t) -> c_int {
|
||||
+ if value.is_null() {
|
||||
+ ERRNO.set(EFAULT);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ let buf = unsafe { slice::from_raw_parts_mut(value.cast::<u8>(), mem::size_of::<u64>()) };
|
||||
+ let buf = unsafe { slice::from_raw_parts_mut(value.cast::<u8>(), mem::size_of::<eventfd_t>()) };
|
||||
+ read_exact(fd, buf).map(|()| 0).or_minus_one_errno()
|
||||
+}
|
||||
+
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub unsafe extern "C" fn eventfd_write(fd: c_int, value: u64) -> c_int {
|
||||
+ let buf = unsafe { slice::from_raw_parts((&raw const value).cast::<u8>(), mem::size_of::<u64>()) };
|
||||
+pub unsafe extern "C" fn eventfd_write(fd: c_int, value: eventfd_t) -> c_int {
|
||||
+ let buf = unsafe { slice::from_raw_parts((&raw const value).cast::<u8>(), mem::size_of::<eventfd_t>()) };
|
||||
+ write_exact(fd, buf).map(|()| 0).or_minus_one_errno()
|
||||
+}
|
||||
|
||||
@@ -0,0 +1,92 @@
|
||||
diff --git a/tests/semaphore/sem_open.c b/tests/semaphore/sem_open.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/tests/semaphore/sem_open.c
|
||||
@@ -0,0 +1,15 @@
|
||||
+#include <assert.h>
|
||||
+#include <fcntl.h>
|
||||
+#include <semaphore.h>
|
||||
+#include <stdio.h>
|
||||
+
|
||||
+int main(void) {
|
||||
+ sem_t *sem = sem_open("/relibc-test-sem", O_CREAT | O_EXCL, 0600, 1);
|
||||
+ assert(sem != SEM_FAILED);
|
||||
+ assert(sem_wait(sem) == 0);
|
||||
+ assert(sem_post(sem) == 0);
|
||||
+ assert(sem_close(sem) == 0);
|
||||
+ assert(sem_unlink("/relibc-test-sem") == 0);
|
||||
+ puts("sem_open ok");
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/tests/sys_shm/shmget.c b/tests/sys_shm/shmget.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/tests/sys_shm/shmget.c
|
||||
@@ -0,0 +1,15 @@
|
||||
+#include <assert.h>
|
||||
+#include <stdio.h>
|
||||
+#include <sys/ipc.h>
|
||||
+#include <sys/shm.h>
|
||||
+
|
||||
+int main(void) {
|
||||
+ int id = shmget(IPC_PRIVATE, 4096, IPC_CREAT | 0600);
|
||||
+ assert(id >= 0);
|
||||
+ void *ptr = shmat(id, 0, 0);
|
||||
+ assert(ptr != (void *)-1);
|
||||
+ assert(shmdt(ptr) == 0);
|
||||
+ assert(shmctl(id, IPC_RMID, 0) == 0);
|
||||
+ puts("shmget ok");
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/tests/sys_timerfd/timerfd.c b/tests/sys_timerfd/timerfd.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/tests/sys_timerfd/timerfd.c
|
||||
@@ -0,0 +1,18 @@
|
||||
+#include <assert.h>
|
||||
+#include <stdio.h>
|
||||
+#include <string.h>
|
||||
+#include <sys/timerfd.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+int main(void) {
|
||||
+ int fd = timerfd_create(CLOCK_REALTIME, 0);
|
||||
+ if (fd < 0) {
|
||||
+ puts("timerfd unavailable");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ struct itimerspec spec;
|
||||
+ memset(&spec, 0, sizeof(spec));
|
||||
+ spec.it_value.tv_nsec = 1;
|
||||
+ assert(timerfd_settime(fd, TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET, &spec, NULL) == 0);
|
||||
+ assert(close(fd) == 0);
|
||||
+ puts("timerfd ok");
|
||||
+ return 0;
|
||||
+}
|
||||
diff --git a/tests/sys_signalfd/signalfd.c b/tests/sys_signalfd/signalfd.c
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/tests/sys_signalfd/signalfd.c
|
||||
@@ -0,0 +1,20 @@
|
||||
+#include <assert.h>
|
||||
+#include <signal.h>
|
||||
+#include <stdio.h>
|
||||
+#include <sys/signalfd.h>
|
||||
+#include <unistd.h>
|
||||
+
|
||||
+int main(void) {
|
||||
+ sigset_t mask;
|
||||
+ assert(sigemptyset(&mask) == 0);
|
||||
+ assert(sigaddset(&mask, SIGUSR1) == 0);
|
||||
+ int fd = signalfd(-1, &mask, sizeof(mask));
|
||||
+ if (fd < 0) {
|
||||
+ puts("signalfd unavailable");
|
||||
+ return 0;
|
||||
+ }
|
||||
+ assert(kill(getpid(), SIGUSR1) == 0);
|
||||
+ struct signalfd_siginfo info;
|
||||
+ assert(read(fd, &info, sizeof(info)) == (ssize_t)sizeof(info));
|
||||
+ assert(info.ssi_signo == SIGUSR1);
|
||||
+ puts("signalfd ok");
|
||||
+ return 0;
|
||||
+}
|
||||
@@ -0,0 +1,37 @@
|
||||
diff -ruN a/src/header/mod.rs b/src/header/mod.rs
|
||||
--- a/src/header/mod.rs 2026-04-15 09:40:30.417847129 +0100
|
||||
+++ b/src/header/mod.rs 2026-04-15 09:48:02.257729647 +0100
|
||||
@@ -103,6 +103,7 @@
|
||||
pub mod sys_stat;
|
||||
pub mod sys_statvfs;
|
||||
pub mod sys_time;
|
||||
+pub mod sys_signalfd;
|
||||
#[deprecated]
|
||||
pub mod sys_timeb;
|
||||
//pub mod sys_times;
|
||||
diff -ruN a/src/header/sys_signalfd/cbindgen.toml b/src/header/sys_signalfd/cbindgen.toml
|
||||
--- a/src/header/sys_signalfd/cbindgen.toml 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/src/header/sys_signalfd/cbindgen.toml 2026-04-15 09:48:02.257754724 +0100
|
||||
@@ -0,0 +1,12 @@
|
||||
+sys_includes = ["signal.h", "stdint.h"]
|
||||
+include_guard = "_SYS_SIGNALFD_H"
|
||||
+language = "C"
|
||||
+style = "Tag"
|
||||
+no_includes = true
|
||||
+cpp_compat = true
|
||||
+
|
||||
+[enum]
|
||||
+prefix_with_name = true
|
||||
+
|
||||
+[export.rename]
|
||||
+"signalfd_siginfo" = "struct signalfd_siginfo"
|
||||
diff -ruN a/src/header/sys_signalfd/mod.rs b/src/header/sys_signalfd/mod.rs
|
||||
--- a/src/header/sys_signalfd/mod.rs 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/src/header/sys_signalfd/mod.rs 2026-04-15 09:48:02.257778048 +0100
|
||||
@@ -0,0 +1,6 @@
|
||||
+//! `sys/signalfd.h` implementation.
|
||||
+
|
||||
+pub use crate::header::signal::{SFD_CLOEXEC, SFD_NONBLOCK, signalfd, signalfd4, signalfd_siginfo};
|
||||
+
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub extern "C" fn _cbindgen_export_sys_signalfd_siginfo(siginfo: signalfd_siginfo) {}
|
||||
@@ -1,7 +1,8 @@
|
||||
diff --git a/src/header/signal/mod.rs b/src/header/signal/mod.rs
|
||||
--- a/src/header/signal/mod.rs
|
||||
+++ b/src/header/signal/mod.rs
|
||||
@@ -33,6 +33,10 @@
|
||||
diff -ruN a/src/header/signal/mod.rs b/src/header/signal/mod.rs
|
||||
--- a/src/header/signal/mod.rs 2026-04-15 09:40:30.420306210 +0100
|
||||
+++ b/src/header/signal/mod.rs 2026-04-15 09:46:42.011891206 +0100
|
||||
@@ -32,6 +32,9 @@
|
||||
#[path = "redox.rs"]
|
||||
pub mod sys;
|
||||
|
||||
+mod signalfd;
|
||||
@@ -10,10 +11,9 @@ diff --git a/src/header/signal/mod.rs b/src/header/signal/mod.rs
|
||||
type SigSet = BitSet<[u64; 1]>;
|
||||
|
||||
pub(crate) const SIG_DFL: usize = 0;
|
||||
diff --git a/src/header/signal/signalfd.rs b/src/header/signal/signalfd.rs
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/src/header/signal/signalfd.rs
|
||||
diff -ruN a/src/header/signal/signalfd.rs b/src/header/signal/signalfd.rs
|
||||
--- a/src/header/signal/signalfd.rs 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/src/header/signal/signalfd.rs 2026-04-15 09:46:42.011930569 +0100
|
||||
@@ -0,0 +1,103 @@
|
||||
+use core::{mem, ptr};
|
||||
+
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
diff -ruN a/src/header/mod.rs b/src/header/mod.rs
|
||||
--- a/src/header/mod.rs 2026-04-15 09:55:11.441949342 +0100
|
||||
+++ b/src/header/mod.rs 2026-04-15 09:57:28.904091552 +0100
|
||||
@@ -92,14 +92,14 @@
|
||||
pub mod sys_eventfd;
|
||||
pub mod sys_file;
|
||||
pub mod sys_ioctl;
|
||||
-// TODO: sys/ipc.h
|
||||
+pub mod sys_ipc;
|
||||
pub mod sys_mman;
|
||||
// TODO: sys/msg.h
|
||||
pub mod sys_ptrace;
|
||||
pub mod sys_resource;
|
||||
pub mod sys_select;
|
||||
-// TODO: sys/sem.h
|
||||
-// TODO: sys/shm.h
|
||||
+pub mod sys_sem;
|
||||
+pub mod sys_shm;
|
||||
pub mod sys_socket;
|
||||
pub mod sys_stat;
|
||||
pub mod sys_statvfs;
|
||||
diff -ruN a/src/header/sys_ipc/cbindgen.toml b/src/header/sys_ipc/cbindgen.toml
|
||||
--- a/src/header/sys_ipc/cbindgen.toml 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/src/header/sys_ipc/cbindgen.toml 2026-04-15 09:57:28.904120977 +0100
|
||||
@@ -0,0 +1,9 @@
|
||||
+sys_includes = ["sys/types.h"]
|
||||
+include_guard = "_SYS_IPC_H"
|
||||
+language = "C"
|
||||
+style = "Tag"
|
||||
+no_includes = true
|
||||
+cpp_compat = true
|
||||
+
|
||||
+[enum]
|
||||
+prefix_with_name = true
|
||||
diff -ruN a/src/header/sys_ipc/mod.rs b/src/header/sys_ipc/mod.rs
|
||||
--- a/src/header/sys_ipc/mod.rs 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/src/header/sys_ipc/mod.rs 2026-04-15 09:57:28.904159138 +0100
|
||||
@@ -0,0 +1,31 @@
|
||||
+//! `sys/ipc.h` implementation.
|
||||
+
|
||||
+use crate::platform::types::{c_int, c_ushort};
|
||||
+
|
||||
+pub type key_t = c_int;
|
||||
+
|
||||
+pub const IPC_PRIVATE: key_t = 0;
|
||||
+pub const IPC_CREAT: c_int = 0o1000;
|
||||
+pub const IPC_EXCL: c_int = 0o2000;
|
||||
+pub const IPC_NOWAIT: c_int = 0o4000;
|
||||
+
|
||||
+pub const IPC_RMID: c_int = 0;
|
||||
+pub const IPC_SET: c_int = 1;
|
||||
+pub const IPC_STAT: c_int = 2;
|
||||
+
|
||||
+#[repr(C)]
|
||||
+#[derive(Clone, Copy, Default)]
|
||||
+pub struct ipc_perm {
|
||||
+ pub __key: key_t,
|
||||
+ pub uid: c_ushort,
|
||||
+ pub gid: c_ushort,
|
||||
+ pub cuid: c_ushort,
|
||||
+ pub cgid: c_ushort,
|
||||
+ pub mode: c_ushort,
|
||||
+ pub __seq: c_ushort,
|
||||
+}
|
||||
+
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub extern "C" fn _cbindgen_export_ipc_perm(value: ipc_perm) {
|
||||
+ let _ = value;
|
||||
+}
|
||||
diff -ruN a/src/header/sys_sem/cbindgen.toml b/src/header/sys_sem/cbindgen.toml
|
||||
--- a/src/header/sys_sem/cbindgen.toml 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/src/header/sys_sem/cbindgen.toml 2026-04-15 09:57:28.904183804 +0100
|
||||
@@ -0,0 +1,9 @@
|
||||
+sys_includes = ["sys/types.h", "sys/ipc.h", "stdint.h"]
|
||||
+include_guard = "_SYS_SEM_H"
|
||||
+language = "C"
|
||||
+style = "Tag"
|
||||
+no_includes = true
|
||||
+cpp_compat = true
|
||||
+
|
||||
+[enum]
|
||||
+prefix_with_name = true
|
||||
diff -ruN a/src/header/sys_shm/cbindgen.toml b/src/header/sys_shm/cbindgen.toml
|
||||
--- a/src/header/sys_shm/cbindgen.toml 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/src/header/sys_shm/cbindgen.toml 2026-04-15 09:57:28.904207067 +0100
|
||||
@@ -0,0 +1,9 @@
|
||||
+sys_includes = ["sys/types.h", "sys/ipc.h", "sys/mman.h", "stdint.h"]
|
||||
+include_guard = "_SYS_SHM_H"
|
||||
+language = "C"
|
||||
+style = "Tag"
|
||||
+no_includes = true
|
||||
+cpp_compat = true
|
||||
+
|
||||
+[enum]
|
||||
+prefix_with_name = true
|
||||
@@ -0,0 +1,180 @@
|
||||
diff -ruN a/src/header/sys_sem/mod.rs b/src/header/sys_sem/mod.rs
|
||||
--- a/src/header/sys_sem/mod.rs 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/src/header/sys_sem/mod.rs 2026-04-15 09:52:34.039784454 +0100
|
||||
@@ -0,0 +1,176 @@
|
||||
+//! `sys/sem.h` implementation.
|
||||
+
|
||||
+use alloc::{collections::BTreeMap, ffi::CString, format};
|
||||
+use core::{mem, ptr, sync::atomic::{AtomicI32, Ordering}};
|
||||
+
|
||||
+use crate::{
|
||||
+ header::{
|
||||
+ errno::{EFAULT, EINVAL, ENOENT},
|
||||
+ fcntl::{O_CREAT, O_EXCL, O_RDWR},
|
||||
+ sys_ipc::{IPC_CREAT, IPC_EXCL, IPC_NOWAIT, IPC_PRIVATE, IPC_RMID, ipc_perm, key_t},
|
||||
+ sys_mman::{MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE, mmap, munmap, shm_open, shm_unlink},
|
||||
+ unistd::close,
|
||||
+ },
|
||||
+ out::Out,
|
||||
+ platform::{ERRNO, Pal, Sys, types::{c_int, c_short, c_ushort, c_void}},
|
||||
+ sync::{Mutex, Semaphore},
|
||||
+};
|
||||
+
|
||||
+pub const GETVAL: c_int = 12;
|
||||
+pub const SETVAL: c_int = 16;
|
||||
+pub const SEM_UNDO: c_short = 0x1000;
|
||||
+
|
||||
+#[repr(C)]
|
||||
+#[derive(Clone, Copy, Default)]
|
||||
+pub struct sembuf {
|
||||
+ pub sem_num: c_ushort,
|
||||
+ pub sem_op: c_short,
|
||||
+ pub sem_flg: c_short,
|
||||
+}
|
||||
+
|
||||
+#[repr(C)]
|
||||
+#[derive(Clone, Copy, Default)]
|
||||
+pub struct semid_ds {
|
||||
+ pub sem_perm: ipc_perm,
|
||||
+ pub sem_nsems: c_ushort,
|
||||
+}
|
||||
+
|
||||
+#[repr(C)]
|
||||
+pub union semun {
|
||||
+ pub val: c_int,
|
||||
+ pub buf: *mut semid_ds,
|
||||
+}
|
||||
+
|
||||
+#[repr(C)]
|
||||
+struct SharedSemSet {
|
||||
+ sem: Semaphore,
|
||||
+}
|
||||
+
|
||||
+#[derive(Clone)]
|
||||
+struct SemMeta {
|
||||
+ path: CString,
|
||||
+ nsems: c_ushort,
|
||||
+}
|
||||
+
|
||||
+static NEXT_SEMID: AtomicI32 = AtomicI32::new(1);
|
||||
+static SEM_REGISTRY: Mutex<BTreeMap<c_int, SemMeta>> = Mutex::new(BTreeMap::new());
|
||||
+static SEM_ATTACHMENTS: Mutex<BTreeMap<c_int, (usize, c_int)>> = Mutex::new(BTreeMap::new());
|
||||
+
|
||||
+fn key_path(key: key_t) -> CString { CString::new(format!("/relibc-sysv-sem-{key:x}")).unwrap() }
|
||||
+fn id_path(id: c_int) -> CString { CString::new(format!("/relibc-sysv-sem-id-{id:x}")).unwrap() }
|
||||
+
|
||||
+fn open_flags_from_ipc(semflg: c_int) -> c_int {
|
||||
+ let mut flags = O_RDWR;
|
||||
+ if semflg & IPC_CREAT == IPC_CREAT { flags |= O_CREAT; }
|
||||
+ if semflg & IPC_EXCL == IPC_EXCL { flags |= O_EXCL; }
|
||||
+ flags
|
||||
+}
|
||||
+
|
||||
+unsafe fn map_sem(path: &CString, create: bool, initial: c_int) -> Result<*mut SharedSemSet, c_int> {
|
||||
+ let fd = unsafe { shm_open(path.as_ptr(), if create { O_CREAT | O_RDWR } else { O_RDWR }, 0o600) };
|
||||
+ if fd < 0 { return Err(ERRNO.get()); }
|
||||
+ let mut st = crate::header::sys_stat::stat::default();
|
||||
+ if Sys::fstat(fd, Out::from_mut(&mut st)).is_err() { let _ = close(fd); return Err(ERRNO.get()); }
|
||||
+ if st.st_size == 0 {
|
||||
+ if Sys::ftruncate(fd, mem::size_of::<SharedSemSet>() as i64).is_err() { let _ = close(fd); return Err(ERRNO.get()); }
|
||||
+ }
|
||||
+ let ptr = unsafe { mmap(ptr::null_mut(), mem::size_of::<SharedSemSet>(), PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0) };
|
||||
+ let _ = close(fd);
|
||||
+ if ptr == MAP_FAILED { return Err(ERRNO.get()); }
|
||||
+ let set = ptr.cast::<SharedSemSet>();
|
||||
+ if create && st.st_size == 0 { unsafe { set.write(SharedSemSet { sem: Semaphore::new(initial as u32) }) }; }
|
||||
+ Ok(set)
|
||||
+}
|
||||
+
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub unsafe extern "C" fn semget(key: key_t, nsems: c_int, semflg: c_int) -> c_int {
|
||||
+ if nsems != 1 { ERRNO.set(EINVAL); return -1; }
|
||||
+ let semid = NEXT_SEMID.fetch_add(1, Ordering::SeqCst);
|
||||
+ let path = if key == IPC_PRIVATE { id_path(semid) } else { key_path(key) };
|
||||
+ let fd = unsafe { shm_open(path.as_ptr(), open_flags_from_ipc(semflg), (semflg & 0o777) as c_int) };
|
||||
+ if fd < 0 { return -1; }
|
||||
+ let _ = close(fd);
|
||||
+ SEM_REGISTRY.lock().insert(semid, SemMeta { path, nsems: 1 });
|
||||
+ semid
|
||||
+}
|
||||
+
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub unsafe extern "C" fn semop(semid: c_int, sops: *mut sembuf, nsops: usize) -> c_int {
|
||||
+ if sops.is_null() { ERRNO.set(EFAULT); return -1; }
|
||||
+ if nsops == 0 { return 0; }
|
||||
+ let meta = { let registry = SEM_REGISTRY.lock(); registry.get(&semid).cloned() };
|
||||
+ let Some(meta) = meta else { ERRNO.set(ENOENT); return -1; };
|
||||
+ let set = {
|
||||
+ let mut attachments = SEM_ATTACHMENTS.lock();
|
||||
+ if let Some((ptr, _)) = attachments.get(&semid) { *ptr as *mut SharedSemSet } else {
|
||||
+ let ptr = match unsafe { map_sem(&meta.path, false, 0) } { Ok(ptr) => ptr, Err(_) => return -1 };
|
||||
+ attachments.insert(semid, (ptr as usize, 1));
|
||||
+ ptr
|
||||
+ }
|
||||
+ };
|
||||
+ let ops = unsafe { core::slice::from_raw_parts(sops, nsops) };
|
||||
+ for op in ops {
|
||||
+ if op.sem_num != 0 { ERRNO.set(EINVAL); return -1; }
|
||||
+ if op.sem_op > 0 { unsafe { (*set).sem.post(op.sem_op as u32) }; continue; }
|
||||
+ if op.sem_op == 0 {
|
||||
+ if op.sem_flg & IPC_NOWAIT as c_short == IPC_NOWAIT as c_short {
|
||||
+ if unsafe { (*set).sem.value() } != 0 { ERRNO.set(crate::header::errno::EAGAIN); return -1; }
|
||||
+ } else if unsafe { (*set).sem.value() } != 0 {
|
||||
+ ERRNO.set(crate::header::errno::EAGAIN);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ continue;
|
||||
+ }
|
||||
+ for _ in 0..(-op.sem_op) {
|
||||
+ if op.sem_flg & IPC_NOWAIT as c_short == IPC_NOWAIT as c_short {
|
||||
+ if unsafe { (*set).sem.try_wait() } == 0 { ERRNO.set(crate::header::errno::EAGAIN); return -1; }
|
||||
+ } else if unsafe { (*set).sem.wait(None, crate::header::time::CLOCK_MONOTONIC) }.is_err() {
|
||||
+ ERRNO.set(crate::header::errno::EINTR);
|
||||
+ return -1;
|
||||
+ }
|
||||
+ }
|
||||
+ }
|
||||
+ 0
|
||||
+}
|
||||
+
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub unsafe extern "C" fn semctl(semid: c_int, semnum: c_int, cmd: c_int, mut args: ...) -> c_int {
|
||||
+ if semnum != 0 { ERRNO.set(EINVAL); return -1; }
|
||||
+ let meta = { let registry = SEM_REGISTRY.lock(); registry.get(&semid).cloned() };
|
||||
+ let Some(meta) = meta else { ERRNO.set(ENOENT); return -1; };
|
||||
+ match cmd {
|
||||
+ IPC_RMID => {
|
||||
+ let _ = unsafe { shm_unlink(meta.path.as_ptr()) };
|
||||
+ SEM_REGISTRY.lock().remove(&semid);
|
||||
+ if let Some((ptr, _)) = SEM_ATTACHMENTS.lock().remove(&semid) {
|
||||
+ let _ = unsafe { munmap((ptr as *mut SharedSemSet).cast::<c_void>(), mem::size_of::<SharedSemSet>()) };
|
||||
+ }
|
||||
+ 0
|
||||
+ }
|
||||
+ GETVAL => {
|
||||
+ let set = match unsafe { map_sem(&meta.path, false, 0) } { Ok(set) => set, Err(errno) => { ERRNO.set(errno); return -1; } };
|
||||
+ let value = unsafe { (*set).sem.value() as c_int };
|
||||
+ let _ = unsafe { munmap(set.cast::<c_void>(), mem::size_of::<SharedSemSet>()) };
|
||||
+ value
|
||||
+ }
|
||||
+ SETVAL => {
|
||||
+ let val = unsafe { args.arg::<c_int>() };
|
||||
+ let set = match unsafe { map_sem(&meta.path, false, 0) } { Ok(set) => set, Err(errno) => { ERRNO.set(errno); return -1; } };
|
||||
+ let current = unsafe { (*set).sem.value() as c_int };
|
||||
+ if val > current { unsafe { (*set).sem.post((val - current) as u32) }; } else {
|
||||
+ for _ in 0..(current - val) {
|
||||
+ if unsafe { (*set).sem.try_wait() } == 0 { break; }
|
||||
+ }
|
||||
+ }
|
||||
+ let _ = unsafe { munmap(set.cast::<c_void>(), mem::size_of::<SharedSemSet>()) };
|
||||
+ 0
|
||||
+ }
|
||||
+ crate::header::sys_ipc::IPC_STAT => {
|
||||
+ let buf = unsafe { args.arg::<*mut semid_ds>() };
|
||||
+ if buf.is_null() { ERRNO.set(EFAULT); return -1; }
|
||||
+ unsafe { *buf = semid_ds { sem_perm: ipc_perm::default(), sem_nsems: meta.nsems }; }
|
||||
+ 0
|
||||
+ }
|
||||
+ _ => { ERRNO.set(EINVAL); -1 }
|
||||
+ }
|
||||
+}
|
||||
@@ -0,0 +1,131 @@
|
||||
diff -ruN a/src/header/sys_shm/mod.rs b/src/header/sys_shm/mod.rs
|
||||
--- a/src/header/sys_shm/mod.rs 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/src/header/sys_shm/mod.rs 2026-04-15 09:52:34.038301738 +0100
|
||||
@@ -0,0 +1,127 @@
|
||||
+//! `sys/shm.h` implementation.
|
||||
+
|
||||
+use alloc::{collections::BTreeMap, ffi::CString, format};
|
||||
+use core::{ptr, sync::atomic::{AtomicI32, Ordering}};
|
||||
+
|
||||
+use crate::{
|
||||
+ header::{
|
||||
+ errno::{EACCES, EFAULT, EINVAL, ENOENT, ENOSYS},
|
||||
+ fcntl::{O_CREAT, O_EXCL, O_RDWR},
|
||||
+ sys_ipc::{IPC_CREAT, IPC_EXCL, IPC_PRIVATE, IPC_RMID, ipc_perm, key_t},
|
||||
+ sys_mman::{MAP_FAILED, MAP_SHARED, PROT_READ, PROT_WRITE, mmap, munmap, shm_open, shm_unlink},
|
||||
+ sys_stat::stat,
|
||||
+ unistd::close,
|
||||
+ },
|
||||
+ out::Out,
|
||||
+ platform::{ERRNO, Pal, Sys, types::{c_int, c_ushort, c_void, size_t, time_t}},
|
||||
+ sync::Mutex,
|
||||
+};
|
||||
+
|
||||
+pub const SHM_RDONLY: c_int = 0o10000;
|
||||
+pub const SHM_RND: c_int = 0o20000;
|
||||
+
|
||||
+#[repr(C)]
|
||||
+#[derive(Clone, Copy)]
|
||||
+pub struct shmid_ds {
|
||||
+ pub shm_perm: ipc_perm,
|
||||
+ pub shm_segsz: size_t,
|
||||
+ pub shm_atime: time_t,
|
||||
+ pub shm_dtime: time_t,
|
||||
+ pub shm_ctime: time_t,
|
||||
+ pub shm_cpid: c_int,
|
||||
+ pub shm_lpid: c_int,
|
||||
+ pub shm_nattch: c_ushort,
|
||||
+}
|
||||
+
|
||||
+impl Default for shmid_ds {
|
||||
+ fn default() -> Self {
|
||||
+ Self { shm_perm: ipc_perm::default(), shm_segsz: 0, shm_atime: 0, shm_dtime: 0, shm_ctime: 0, shm_cpid: 0, shm_lpid: 0, shm_nattch: 0 }
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#[derive(Clone)]
|
||||
+struct SegmentMeta {
|
||||
+ path: CString,
|
||||
+ size: size_t,
|
||||
+ removed: bool,
|
||||
+}
|
||||
+
|
||||
+static NEXT_SHMID: AtomicI32 = AtomicI32::new(1);
|
||||
+static SHM_REGISTRY: Mutex<BTreeMap<c_int, SegmentMeta>> = Mutex::new(BTreeMap::new());
|
||||
+static SHM_ATTACHMENTS: Mutex<BTreeMap<usize, (c_int, size_t)>> = Mutex::new(BTreeMap::new());
|
||||
+
|
||||
+fn key_path(key: key_t) -> CString { CString::new(format!("/relibc-sysv-shm-{key:x}")).unwrap() }
|
||||
+fn id_path(id: c_int) -> CString { CString::new(format!("/relibc-sysv-shm-id-{id:x}")).unwrap() }
|
||||
+
|
||||
+fn open_flags_from_ipc(shmflg: c_int) -> c_int {
|
||||
+ let mut flags = O_RDWR;
|
||||
+ if shmflg & IPC_CREAT == IPC_CREAT { flags |= O_CREAT; }
|
||||
+ if shmflg & IPC_EXCL == IPC_EXCL { flags |= O_EXCL; }
|
||||
+ flags
|
||||
+}
|
||||
+
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub unsafe extern "C" fn shmget(key: key_t, size: size_t, shmflg: c_int) -> c_int {
|
||||
+ let shmid = NEXT_SHMID.fetch_add(1, Ordering::SeqCst);
|
||||
+ let path = if key == IPC_PRIVATE { id_path(shmid) } else { key_path(key) };
|
||||
+ let fd = unsafe { shm_open(path.as_ptr(), open_flags_from_ipc(shmflg), (shmflg & 0o777) as c_int) };
|
||||
+ if fd < 0 { return -1; }
|
||||
+
|
||||
+ let mut st = stat::default();
|
||||
+ if Sys::fstat(fd, Out::from_mut(&mut st)).is_err() { let _ = close(fd); return -1; }
|
||||
+ if st.st_size == 0 && size > 0 {
|
||||
+ if Sys::ftruncate(fd, size as i64).is_err() { let _ = close(fd); return -1; }
|
||||
+ }
|
||||
+ let _ = close(fd);
|
||||
+ SHM_REGISTRY.lock().insert(shmid, SegmentMeta { path, size, removed: false });
|
||||
+ shmid
|
||||
+}
|
||||
+
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub unsafe extern "C" fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void {
|
||||
+ let meta = { let registry = SHM_REGISTRY.lock(); registry.get(&shmid).cloned() };
|
||||
+ let Some(meta) = meta else { ERRNO.set(ENOENT); return MAP_FAILED; };
|
||||
+ if !shmaddr.is_null() { ERRNO.set(ENOSYS); return MAP_FAILED; }
|
||||
+ let mut prot = PROT_READ;
|
||||
+ if shmflg & SHM_RDONLY == 0 { prot |= PROT_WRITE; }
|
||||
+ let fd = unsafe { shm_open(meta.path.as_ptr(), O_RDWR, 0) };
|
||||
+ if fd < 0 { return MAP_FAILED; }
|
||||
+ let ptr = unsafe { mmap(ptr::null_mut(), meta.size, prot, MAP_SHARED, fd, 0) };
|
||||
+ let _ = close(fd);
|
||||
+ if ptr == MAP_FAILED { return MAP_FAILED; }
|
||||
+ SHM_ATTACHMENTS.lock().insert(ptr as usize, (shmid, meta.size));
|
||||
+ ptr
|
||||
+}
|
||||
+
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub unsafe extern "C" fn shmdt(shmaddr: *const c_void) -> c_int {
|
||||
+ if shmaddr.is_null() { ERRNO.set(EFAULT); return -1; }
|
||||
+ let Some((_, size)) = SHM_ATTACHMENTS.lock().remove(&(shmaddr as usize)) else { ERRNO.set(EINVAL); return -1; };
|
||||
+ unsafe { munmap(shmaddr.cast_mut(), size) }
|
||||
+}
|
||||
+
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub unsafe extern "C" fn shmctl(shmid: c_int, cmd: c_int, buf: *mut shmid_ds) -> c_int {
|
||||
+ let mut registry = SHM_REGISTRY.lock();
|
||||
+ let Some(meta) = registry.get_mut(&shmid) else { ERRNO.set(ENOENT); return -1; };
|
||||
+ match cmd {
|
||||
+ IPC_RMID => { meta.removed = true; unsafe { shm_unlink(meta.path.as_ptr()) } }
|
||||
+ crate::header::sys_ipc::IPC_STAT => {
|
||||
+ if buf.is_null() { ERRNO.set(EFAULT); return -1; }
|
||||
+ unsafe {
|
||||
+ *buf = shmid_ds {
|
||||
+ shm_perm: ipc_perm::default(),
|
||||
+ shm_segsz: meta.size,
|
||||
+ shm_atime: 0,
|
||||
+ shm_dtime: 0,
|
||||
+ shm_ctime: 0,
|
||||
+ shm_cpid: 0,
|
||||
+ shm_lpid: 0,
|
||||
+ shm_nattch: SHM_ATTACHMENTS.lock().values().filter(|(id, _)| *id == shmid).count() as c_ushort,
|
||||
+ };
|
||||
+ }
|
||||
+ 0
|
||||
+ }
|
||||
+ _ => { ERRNO.set(EACCES); -1 }
|
||||
+ }
|
||||
+}
|
||||
@@ -1,18 +1,18 @@
|
||||
diff --git a/src/header/mod.rs b/src/header/mod.rs
|
||||
--- a/src/header/mod.rs
|
||||
+++ b/src/header/mod.rs
|
||||
@@ -100,5 +100,6 @@ pub mod sys_socket;
|
||||
diff -ruN a/src/header/mod.rs b/src/header/mod.rs
|
||||
--- a/src/header/mod.rs 2026-04-15 09:58:03.811510680 +0100
|
||||
+++ b/src/header/mod.rs 2026-04-15 09:59:40.902089070 +0100
|
||||
@@ -103,6 +103,7 @@
|
||||
pub mod sys_stat;
|
||||
pub mod sys_statvfs;
|
||||
pub mod sys_time;
|
||||
+pub mod sys_timerfd;
|
||||
#[deprecated]
|
||||
pub mod sys_timeb;
|
||||
diff --git a/src/header/sys_timerfd/cbindgen.toml b/src/header/sys_timerfd/cbindgen.toml
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/src/header/sys_timerfd/cbindgen.toml
|
||||
@@ -0,0 +1,9 @@
|
||||
//pub mod sys_times;
|
||||
diff -ruN a/src/header/sys_timerfd/cbindgen.toml b/src/header/sys_timerfd/cbindgen.toml
|
||||
--- a/src/header/sys_timerfd/cbindgen.toml 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/src/header/sys_timerfd/cbindgen.toml 2026-04-15 09:59:40.902120449 +0100
|
||||
@@ -0,0 +1,12 @@
|
||||
+sys_includes = ["time.h"]
|
||||
+include_guard = "_SYS_TIMERFD_H"
|
||||
+language = "C"
|
||||
@@ -22,11 +22,13 @@ new file mode 100644
|
||||
+
|
||||
+[enum]
|
||||
+prefix_with_name = true
|
||||
diff --git a/src/header/sys_timerfd/mod.rs b/src/header/sys_timerfd/mod.rs
|
||||
new file mode 100644
|
||||
--- /dev/null
|
||||
+++ b/src/header/sys_timerfd/mod.rs
|
||||
@@ -0,0 +1,89 @@
|
||||
+
|
||||
+[export.rename]
|
||||
+"itimerspec" = "struct itimerspec"
|
||||
diff -ruN a/src/header/sys_timerfd/mod.rs b/src/header/sys_timerfd/mod.rs
|
||||
--- a/src/header/sys_timerfd/mod.rs 1970-01-01 00:00:00.000000000 +0000
|
||||
+++ b/src/header/sys_timerfd/mod.rs 2026-04-15 09:59:40.902160103 +0100
|
||||
@@ -0,0 +1,94 @@
|
||||
+//! `sys/timerfd.h` implementation.
|
||||
+//!
|
||||
+//! Non-POSIX, see <https://man7.org/linux/man-pages/man2/timerfd_create.2.html>.
|
||||
@@ -53,6 +55,7 @@ new file mode 100644
|
||||
+pub const TFD_CLOEXEC: c_int = 0x80000;
|
||||
+pub const TFD_NONBLOCK: c_int = 0x800;
|
||||
+pub const TFD_TIMER_ABSTIME: c_int = 0x1;
|
||||
+pub const TFD_TIMER_CANCEL_ON_SET: c_int = 0x2;
|
||||
+
|
||||
+fn read_exact(fd: c_int, buf: &mut [u8]) -> Result<(), Errno> {
|
||||
+ match Sys::read(fd, buf)? {
|
||||
@@ -92,7 +95,11 @@ new file mode 100644
|
||||
+
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub unsafe extern "C" fn timerfd_settime(fd: c_int, flags: c_int, new: *const itimerspec, old: *mut itimerspec) -> c_int {
|
||||
+ if flags & !TFD_TIMER_ABSTIME != 0 {
|
||||
+ let supported = TFD_TIMER_ABSTIME | TFD_TIMER_CANCEL_ON_SET;
|
||||
+ if flags & !supported != 0 {
|
||||
+ return Err::<c_int, _>(Errno(EINVAL)).or_minus_one_errno();
|
||||
+ }
|
||||
+ if flags & TFD_TIMER_CANCEL_ON_SET != 0 && flags & TFD_TIMER_ABSTIME == 0 {
|
||||
+ return Err::<c_int, _>(Errno(EINVAL)).or_minus_one_errno();
|
||||
+ }
|
||||
+ if new.is_null() {
|
||||
|
||||
@@ -0,0 +1,19 @@
|
||||
diff --git a/src/header/sys_wait/cbindgen.toml b/src/header/sys_wait/cbindgen.toml
|
||||
index 807d8fb3..047dc3e9 100644
|
||||
--- a/src/header/sys_wait/cbindgen.toml
|
||||
+++ b/src/header/sys_wait/cbindgen.toml
|
||||
@@ -1,4 +1,4 @@
|
||||
-sys_includes = ["sys/types.h", "sys/resource.h"]
|
||||
+sys_includes = ["sys/types.h", "sys/resource.h", "signal.h"]
|
||||
include_guard = "_SYS_WAIT_H"
|
||||
trailer = """
|
||||
#define WEXITSTATUS(s) (((s) >> 8) & 0xff)
|
||||
@@ -7,7 +7,7 @@ trailer = """
|
||||
#define WCOREDUMP(s) (((s) & 0x80) != 0)
|
||||
#define WIFEXITED(s) (((s) & 0x7f) == 0)
|
||||
#define WIFSTOPPED(s) (((s) & 0xff) == 0x7f)
|
||||
-#define WIFSIGNALED(s) (((((s) & 0x7f) + 1U) & 0x7f) >= 2) // Ends with 1111111 or 10000000
|
||||
+#define WIFSIGNALED(s) (((((s) & 0x7f) + 1U) & 0x7f) >= 2)
|
||||
#define WIFCONTINUED(s) ((s) == 0xffff)
|
||||
"""
|
||||
language = "C"
|
||||
@@ -0,0 +1,130 @@
|
||||
diff --git a/src/header/sys_wait/mod.rs b/src/header/sys_wait/mod.rs
|
||||
index 11f4bf2c..91a58c5b 100644
|
||||
--- a/src/header/sys_wait/mod.rs
|
||||
+++ b/src/header/sys_wait/mod.rs
|
||||
@@ -4,13 +4,17 @@
|
||||
|
||||
use crate::{
|
||||
error::ResultExt,
|
||||
+ header::signal::siginfo_t,
|
||||
out::Out,
|
||||
platform::{
|
||||
- Pal, Sys,
|
||||
- types::{c_int, pid_t},
|
||||
+ ERRNO, Pal, Sys,
|
||||
+ types::{c_int, c_uint, pid_t},
|
||||
},
|
||||
};
|
||||
|
||||
+pub type idtype_t = c_int;
|
||||
+pub type id_t = c_uint;
|
||||
+
|
||||
pub const WNOHANG: c_int = 1;
|
||||
pub const WUNTRACED: c_int = 2;
|
||||
|
||||
@@ -24,27 +28,89 @@ pub const __WALL: c_int = 0x4000_0000;
|
||||
#[allow(overflowing_literals)]
|
||||
pub const __WCLONE: c_int = 0x8000_0000;
|
||||
|
||||
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/wait.html>.
|
||||
+pub const P_ALL: idtype_t = 0;
|
||||
+pub const P_PID: idtype_t = 1;
|
||||
+pub const P_PGID: idtype_t = 2;
|
||||
+
|
||||
+pub const CLD_EXITED: c_int = 1;
|
||||
+pub const CLD_KILLED: c_int = 2;
|
||||
+pub const CLD_DUMPED: c_int = 3;
|
||||
+pub const CLD_TRAPPED: c_int = 4;
|
||||
+pub const CLD_STOPPED: c_int = 5;
|
||||
+pub const CLD_CONTINUED: c_int = 6;
|
||||
+
|
||||
+fn wexitstatus(status: c_int) -> c_int { (status >> 8) & 0xff }
|
||||
+fn wtermsig(status: c_int) -> c_int { status & 0x7f }
|
||||
+fn wstopsig(status: c_int) -> c_int { wexitstatus(status) }
|
||||
+fn wcoredump(status: c_int) -> bool { (status & 0x80) != 0 }
|
||||
+fn wifexited(status: c_int) -> bool { (status & 0x7f) == 0 }
|
||||
+fn wifstopped(status: c_int) -> bool { (status & 0xff) == 0x7f }
|
||||
+fn wifcontinued(status: c_int) -> bool { status == 0xffff }
|
||||
+
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn wait(stat_loc: *mut c_int) -> pid_t {
|
||||
unsafe { waitpid(!0, stat_loc, 0) }
|
||||
}
|
||||
|
||||
-/*
|
||||
- * TODO: implement idtype_t, id_t, and siginfo_t
|
||||
- *
|
||||
- * #[unsafe(no_mangle)]
|
||||
- * pub unsafe extern "C" fn waitid(
|
||||
- * idtype: idtype_t,
|
||||
- * id: id_t,
|
||||
- * infop: siginfo_t,
|
||||
- * options: c_int
|
||||
- * ) -> c_int {
|
||||
- * unimplemented!();
|
||||
- * }
|
||||
- */
|
||||
-
|
||||
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/waitpid.html>.
|
||||
+fn map_waitid_target(idtype: idtype_t, id: id_t) -> Option<pid_t> {
|
||||
+ match idtype {
|
||||
+ P_ALL => Some(-1),
|
||||
+ P_PID => Some(id as pid_t),
|
||||
+ P_PGID => Some(if id == 0 { 0 } else { -(id as pid_t) }),
|
||||
+ _ => None,
|
||||
+ }
|
||||
+}
|
||||
+
|
||||
+#[unsafe(no_mangle)]
|
||||
+pub unsafe extern "C" fn waitid(
|
||||
+ idtype: idtype_t,
|
||||
+ id: id_t,
|
||||
+ infop: *mut siginfo_t,
|
||||
+ options: c_int,
|
||||
+) -> c_int {
|
||||
+ if infop.is_null() {
|
||||
+ ERRNO.set(crate::header::errno::EFAULT);
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ let Some(pid_target) = map_waitid_target(idtype, id) else {
|
||||
+ ERRNO.set(crate::header::errno::EINVAL);
|
||||
+ return -1;
|
||||
+ };
|
||||
+
|
||||
+ let mut status = 0;
|
||||
+ let pid = Sys::waitpid(pid_target, Some(Out::from_mut(&mut status)), options).or_minus_one_errno();
|
||||
+ if pid < 0 {
|
||||
+ return -1;
|
||||
+ }
|
||||
+
|
||||
+ unsafe { *infop = core::mem::zeroed() };
|
||||
+ if pid == 0 {
|
||||
+ return 0;
|
||||
+ }
|
||||
+
|
||||
+ unsafe {
|
||||
+ (*infop).si_pid = pid;
|
||||
+ (*infop).si_signo = crate::header::signal::SIGCHLD as c_int;
|
||||
+ (*infop).si_errno = 0;
|
||||
+ if wifexited(status) {
|
||||
+ (*infop).si_code = CLD_EXITED;
|
||||
+ (*infop).si_status = wexitstatus(status);
|
||||
+ } else if wifstopped(status) {
|
||||
+ (*infop).si_code = CLD_STOPPED;
|
||||
+ (*infop).si_status = wstopsig(status);
|
||||
+ } else if wifcontinued(status) {
|
||||
+ (*infop).si_code = CLD_CONTINUED;
|
||||
+ (*infop).si_status = crate::header::signal::SIGCONT as c_int;
|
||||
+ } else {
|
||||
+ (*infop).si_status = wtermsig(status);
|
||||
+ (*infop).si_code = if wcoredump(status) { CLD_DUMPED } else { CLD_KILLED };
|
||||
+ }
|
||||
+ }
|
||||
+
|
||||
+ 0
|
||||
+}
|
||||
+
|
||||
#[unsafe(no_mangle)]
|
||||
pub unsafe extern "C" fn waitpid(pid: pid_t, stat_loc: *mut c_int, options: c_int) -> pid_t {
|
||||
Sys::waitpid(pid, unsafe { Out::nullable(stat_loc) }, options).or_minus_one_errno()
|
||||
Reference in New Issue
Block a user