fix: consolidate relibc patch chain

Remove absorbed prerequisite patches and fd-event test patch. Add
statvfs constants patch. Update recipe.toml wiring.
This commit is contained in:
2026-05-11 10:08:30 +01:00
parent 7dfb749b3d
commit cfddfe4ebe
12 changed files with 58 additions and 409 deletions
@@ -1,106 +0,0 @@
diff --git a/include/features.h b/include/features.h
index 6d0a0d6..d14516f 100644
--- a/include/features.h
+++ b/include/features.h
@@ -14,6 +14,11 @@
#define __RELIBC__MAJOR 0
#define __RELIBC__MINOR 2
+#ifndef __RELIBC_C_LONGDOUBLE_DEFINED
+#define __RELIBC_C_LONGDOUBLE_DEFINED 1
+typedef long double c_longdouble;
+#endif
+
/*
* Sources:
* https://en.cppreference.com/w/c/language/attributes
diff --git a/include/stddef.h b/include/stddef.h
index 334267f..bb58d55 100644
--- a/include/stddef.h
+++ b/include/stddef.h
@@ -11,6 +11,11 @@ typedef __PTRDIFF_TYPE__ ptrdiff_t;
typedef long unsigned int size_t;
+#ifndef __RELIBC_C_LONGDOUBLE_DEFINED
+#define __RELIBC_C_LONGDOUBLE_DEFINED 1
+typedef long double c_longdouble;
+#endif
+
typedef struct { long long __ll; long double __ld; } max_align_t;
#define offsetof(type, member) __builtin_offsetof(type, member)
diff --git a/src/c/stdlib.c b/src/c/stdlib.c
index 62e9810..4040655 100644
--- a/src/c/stdlib.c
+++ b/src/c/stdlib.c
@@ -1,9 +1,5 @@
double strtod(const char *nptr, char **endptr);
-long double strtold(const char *nptr, char **endptr) {
- return (long double)strtod(nptr, endptr);
-}
-
double relibc_ldtod(const long double* val) {
return (double)(*val);
}
diff --git a/src/header/stdlib/cbindgen.toml b/src/header/stdlib/cbindgen.toml
index c105da5..d5bcb23 100644
--- a/src/header/stdlib/cbindgen.toml
+++ b/src/header/stdlib/cbindgen.toml
@@ -1,21 +1,5 @@
sys_includes = ["stddef.h", "alloca.h", "wchar.h", "features.h"]
include_guard = "_RELIBC_STDLIB_H"
-trailer = """
-#ifndef _RELIBC_STDLIB_EXTRA_H
-#define _RELIBC_STDLIB_EXTRA_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-long double strtold(const char *nptr, char **endptr);
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif
-"""
language = "C"
style = "Type"
no_includes = true
diff --git a/src/header/stdlib/mod.rs b/src/header/stdlib/mod.rs
index 423ee95..43bc912 100644
--- a/src/header/stdlib/mod.rs
+++ b/src/header/stdlib/mod.rs
@@ -31,7 +31,7 @@ use crate::{
platform::{
self, Pal, Sys,
types::{
- c_char, c_double, c_float, c_int, c_long, c_longlong, c_uint, c_ulong, c_ulonglong,
+ c_char, c_double, c_float, c_int, c_long, c_longdouble, c_longlong, c_uint, c_ulong, c_ulonglong,
c_ushort, c_void, size_t, ssize_t, uintptr_t, wchar_t,
},
},
@@ -1490,12 +1494,19 @@ pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> c
strto_float_impl!(c_double, s, endptr)
}
-/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strtod.html>.
+/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strtof.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strtof(s: *const c_char, endptr: *mut *mut c_char) -> c_float {
strto_float_impl!(c_float, s, endptr)
}
+/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strtod.html>.
+#[unsafe(no_mangle)]
+pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> c_longdouble {
+ let result = unsafe { strtod(s, core::ptr::null_mut()) };
+ result as c_longdouble
+}
+
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/strtol.html>.
#[unsafe(no_mangle)]
pub unsafe extern "C" fn strtol(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_long {
@@ -1,15 +0,0 @@
diff --git a/tests/Makefile.tests.mk b/tests/Makefile.tests.mk
--- a/tests/Makefile.tests.mk
+++ b/tests/Makefile.tests.mk
@@ -314,0 +314,4 @@ VARIED_NAMES=\
grp/gr_iter \
semaphore/named \
semaphore/unnamed \
+ sys_eventfd/eventfd \
+ sys_signalfd/header_only \
+ sys_signalfd/signalfd \
+ sys_timerfd/timerfd \
waitid \
waitpid \
waitpid_multiple \
$(FAILING_TESTS)
+4 -6
View File
@@ -1,6 +1,5 @@
diff --git a/tests/semaphore/sem_open.c b/tests/semaphore/sem_open.c
new file mode 100644
--- /dev/null
diff -ruN a/tests/semaphore/sem_open.c b/tests/semaphore/sem_open.c
--- a/tests/semaphore/sem_open.c
+++ b/tests/semaphore/sem_open.c
@@ -0,0 +1,15 @@
+#include <assert.h>
@@ -18,9 +17,8 @@ new file mode 100644
+ 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
diff -ruN a/tests/sys_shm/shmget.c b/tests/sys_shm/shmget.c
--- a/tests/sys_shm/shmget.c
+++ b/tests/sys_shm/shmget.c
@@ -0,0 +1,15 @@
+#include <assert.h>
@@ -1,181 +0,0 @@
diff --git a/src/header/stdio/mod.rs b/src/header/stdio/mod.rs
--- a/src/header/stdio/mod.rs
+++ b/src/header/stdio/mod.rs
@@ -46,4 +46,7 @@
pub use self::getdelim::*;
mod getdelim;
+pub use self::open_memstream::*;
+mod open_memstream;
+
mod ext;
diff --git a/src/header/stdio/open_memstream.rs b/src/header/stdio/open_memstream.rs
new file mode 100644
--- /dev/null
+++ b/src/header/stdio/open_memstream.rs
@@ -0,0 +1,124 @@
+use alloc::{boxed::Box, vec, vec::Vec};
+use core::ptr;
+
+use super::{
+ Buffer, FILE,
+ constants::{BUFSIZ, F_NORD},
+};
+use crate::{
+ error::{Errno, ResultExtPtrMut},
+ fs::File,
+ header::{
+ errno::{EFAULT, ENOMEM},
+ fcntl, pthread, stdlib, unistd,
+ },
+ io::{self, BufWriter, Write},
+ platform::{
+ ERRNO,
+ types::{c_char, size_t},
+ },
+};
+
+struct MemstreamWriter {
+ bufp: *mut *mut c_char,
+ sizep: *mut size_t,
+ current: *mut c_char,
+ buffer: Vec<u8>,
+}
+
+unsafe impl Send for MemstreamWriter {}
+
+impl MemstreamWriter {
+ fn new(bufp: *mut *mut c_char, sizep: *mut size_t) -> Self {
+ Self {
+ bufp,
+ sizep,
+ current: ptr::null_mut(),
+ buffer: Vec::new(),
+ }
+ }
+
+ fn sync_output(&mut self) -> io::Result<()> {
+ let size = self.buffer.len();
+ let alloc_size = size
+ .checked_add(1)
+ .ok_or_else(|| io::Error::from_raw_os_error(ENOMEM))?;
+
+ let raw = if self.current.is_null() {
+ unsafe { stdlib::malloc(alloc_size) }
+ } else {
+ unsafe { stdlib::realloc(self.current.cast(), alloc_size) }
+ };
+ if raw.is_null() {
+ return Err(io::Error::from_raw_os_error(ENOMEM));
+ }
+
+ let raw = raw.cast::<c_char>();
+ if size != 0 {
+ unsafe { ptr::copy_nonoverlapping(self.buffer.as_ptr(), raw.cast::<u8>(), size) };
+ }
+ unsafe {
+ *raw.add(size) = 0;
+ *self.bufp = raw;
+ *self.sizep = size;
+ }
+ self.current = raw;
+ Ok(())
+ }
+}
+
+impl Write for MemstreamWriter {
+ fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+ self.buffer
+ .try_reserve(buf.len())
+ .map_err(|_| io::Error::from_raw_os_error(ENOMEM))?;
+ self.buffer.extend_from_slice(buf);
+ Ok(buf.len())
+ }
+
+ fn flush(&mut self) -> io::Result<()> {
+ self.sync_output()
+ }
+}
+
+fn create_memstream(bufp: *mut *mut c_char, sizep: *mut size_t) -> Result<Box<FILE>, Errno> {
+ if bufp.is_null() || sizep.is_null() {
+ return Err(Errno(EFAULT));
+ }
+
+ unsafe {
+ *bufp = ptr::null_mut();
+ *sizep = 0;
+ }
+
+ let mut fds = [0; 2];
+ if unsafe { unistd::pipe2(fds.as_mut_ptr(), fcntl::O_CLOEXEC) } != 0 {
+ return Err(Errno(ERRNO.get()));
+ }
+ let _ = unistd::close(fds[0]);
+
+ let file = File::new(fds[1]);
+ let writer = Box::new(BufWriter::new(MemstreamWriter::new(bufp, sizep)));
+ let mutex_attr = pthread::RlctMutexAttr {
+ ty: pthread::PTHREAD_MUTEX_RECURSIVE,
+ ..Default::default()
+ };
+
+ Ok(Box::new(FILE {
+ lock: pthread::RlctMutex::new(&mutex_attr).unwrap(),
+ file,
+ flags: F_NORD,
+ read_buf: Buffer::Owned(vec![0; BUFSIZ as usize]),
+ read_pos: 0,
+ read_size: 0,
+ unget: Vec::new(),
+ writer,
+ pid: None,
+ orientation: 0,
+ }))
+}
+
+#[unsafe(no_mangle)]
+pub unsafe extern "C" fn open_memstream(bufp: *mut *mut c_char, sizep: *mut size_t) -> *mut FILE {
+ create_memstream(bufp, sizep).or_errno_null_mut()
+}
diff --git a/tests/Makefile.tests.mk b/tests/Makefile.tests.mk
--- a/tests/Makefile.tests.mk
+++ b/tests/Makefile.tests.mk
@@ -85,1 +85,2 @@ VARIED_NAMES=\
stdio/fseek \
stdio/fwrite \
stdio/getc_unget \
- stdio/getline \
+ stdio/getline \
+ stdio/open_memstream \
stdio/mutex \
stdio/popen \
diff --git a/tests/stdio/open_memstream.c b/tests/stdio/open_memstream.c
new file mode 100644
--- /dev/null
+++ b/tests/stdio/open_memstream.c
@@ -0,0 +1,24 @@
+#include <assert.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+int main(void) {
+ char *buf = NULL;
+ size_t size = 0;
+
+ FILE *stream = open_memstream(&buf, &size);
+ assert(stream != NULL);
+ assert(fputs("hello", stream) >= 0);
+ assert(fflush(stream) == 0);
+ assert(size == 5);
+ assert(strcmp(buf, "hello") == 0);
+ assert(fputc('!', stream) != EOF);
+ assert(fclose(stream) == 0);
+ assert(size == 6);
+ assert(strcmp(buf, "hello!") == 0);
+
+ free(buf);
+ puts("open_memstream ok");
+ return 0;
+}
@@ -0,0 +1,15 @@
diff --git a/src/header/sys_statvfs/mod.rs b/src/header/sys_statvfs/mod.rs
index 866768b..5ac15de 100644
--- a/src/header/sys_statvfs/mod.rs
+++ b/src/header/sys_statvfs/mod.rs
@@ -13,8 +13,8 @@ use crate::{
},
};
-//pub const ST_RDONLY
-//pub const ST_NOSUID
+pub const ST_RDONLY: c_ulong = 1;
+pub const ST_NOSUID: c_ulong = 2;
#[repr(C)]
#[derive(Default)]
@@ -1,34 +0,0 @@
diff --git a/src/header/stdlib/cbindgen.toml b/src/header/stdlib/cbindgen.toml
index e0c73c31..5504b0d5 100644
--- a/src/header/stdlib/cbindgen.toml
+++ b/src/header/stdlib/cbindgen.toml
@@ -1,4 +1,4 @@
-sys_includes = ["stddef.h", "alloca.h", "wchar.h", "features.h"]
+sys_includes = ["stddef.h", "stdint.h", "alloca.h", "wchar.h", "features.h"]
include_guard = "_RELIBC_STDLIB_H"
trailer = """
#ifndef _RELIBC_STDLIB_EXTRA_H
diff --git a/src/header/inttypes/cbindgen.toml b/src/header/inttypes/cbindgen.toml
index 73018c8e..8bec0e0f 100644
--- a/src/header/inttypes/cbindgen.toml
+++ b/src/header/inttypes/cbindgen.toml
@@ -4,8 +4,7 @@
# - "The <inttypes.h> header shall include the <stdint.h> header."
# - "wchar_t As described in <stddef.h>."
#
-# wchar.h brings in both stdint.h and stddef.h
-sys_includes = ["wchar.h"]
+sys_includes = ["stdint.h", "wchar.h"]
include_guard = "_RELIBC_INTTYPES_H"
trailer = """
#ifndef _RELIBC_BITS_INTTYPES_H
diff --git a/src/header/wctype/cbindgen.toml b/src/header/wctype/cbindgen.toml
index 37cd9dc9..83b421c0 100644
--- a/src/header/wctype/cbindgen.toml
+++ b/src/header/wctype/cbindgen.toml
@@ -1,4 +1,4 @@
-sys_includes = ["wchar.h" ]
+sys_includes = ["stdint.h", "wchar.h"]
include_guard = "_RELIBC_WCTYPE_H"
language = "C"
style = "Type"
+14 -14
View File
@@ -1,7 +1,7 @@
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,15 +92,15 @@
--- a/src/header/mod.rs
+++ b/src/header/mod.rs
@@ -95,14 +95,14 @@
pub mod sys_eventfd;
pub mod sys_file;
pub mod sys_ioctl;
@@ -20,9 +20,9 @@ diff -ruN a/src/header/mod.rs b/src/header/mod.rs
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,1 +1,13 @@
--- a/src/header/sys_ipc/cbindgen.toml
+++ b/src/header/sys_ipc/cbindgen.toml
@@ -0,0 +1,12 @@
+sys_includes = ["sys/types.h"]
+include_guard = "_SYS_IPC_H"
+trailer = """
@@ -36,9 +36,9 @@ diff -ruN a/src/header/sys_ipc/cbindgen.toml b/src/header/sys_ipc/cbindgen.toml
+[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,1 +1,32 @@
--- a/src/header/sys_ipc/mod.rs
+++ b/src/header/sys_ipc/mod.rs
@@ -0,0 +1,31 @@
+//! `sys/ipc.h` implementation.
+
+use crate::platform::types::{c_int, c_ushort};
@@ -71,9 +71,9 @@ diff -ruN a/src/header/sys_ipc/mod.rs b/src/header/sys_ipc/mod.rs
+ 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,1 +1,10 @@
--- a/src/header/sys_sem/cbindgen.toml
+++ b/src/header/sys_sem/cbindgen.toml
@@ -0,0 +1,9 @@
+sys_includes = ["sys/types.h", "sys/ipc.h", "stdint.h"]
+include_guard = "_SYS_SEM_H"
+language = "C"
@@ -84,8 +84,8 @@ diff -ruN a/src/header/sys_sem/cbindgen.toml b/src/header/sys_sem/cbindgen.toml
+[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
--- a/src/header/sys_shm/cbindgen.toml
+++ b/src/header/sys_shm/cbindgen.toml
@@ -0,0 +1,9 @@
+sys_includes = ["sys/types.h", "sys/ipc.h", "sys/mman.h", "stdint.h"]
+include_guard = "_SYS_SHM_H"
+2 -2
View File
@@ -1,6 +1,6 @@
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
--- a/src/header/sys_sem/mod.rs
+++ b/src/header/sys_sem/mod.rs
@@ -0,0 +1,176 @@
+//! `sys/sem.h` implementation.
+
+2 -2
View File
@@ -1,6 +1,6 @@
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
--- a/src/header/sys_shm/mod.rs
+++ b/src/header/sys_shm/mod.rs
@@ -0,0 +1,127 @@
+//! `sys/shm.h` implementation.
+
@@ -1,49 +0,0 @@
diff --git a/src/header/wchar/cbindgen.toml b/src/header/wchar/cbindgen.toml
index a31881ba..9e206fd1 100644
--- a/src/header/wchar/cbindgen.toml
+++ b/src/header/wchar/cbindgen.toml
@@ -1,17 +1,13 @@
sys_includes = [
- "stdio.h",
- "time.h",
+ "stdarg.h",
"features.h",
]
after_includes = """
-// int32_t, uint32_t, WCHAR_MIN, WCHAR_MAX
-#include <stdint.h>
-
#ifndef _WCHAR_T
#define _WCHAR_T
#ifndef __cplusplus
#ifndef __WCHAR_TYPE__
- #define __WCHAR_TYPE__ int32_t
+ #define __WCHAR_TYPE__ int
#endif
typedef __WCHAR_TYPE__ wchar_t;
#endif // __cplusplus
@@ -20,7 +16,7 @@ after_includes = """
#ifndef _WINT_T
#define _WINT_T
#ifndef __WINT_TYPE__
- #define __WINT_TYPE__ uint32_t
+ #define __WINT_TYPE__ unsigned int
#endif
typedef __WINT_TYPE__ wint_t;
#endif // _WINT_T
@@ -31,6 +27,15 @@ after_includes = """
#include <stddef.h>
#define WEOF (0xffffffffu)
+
+// FILE. Avoid including stdio.h from wchar.h: gnulib wrappers can reach wchar.h
+// recursively through stdio.h -> stdint.h -> inttypes.h before wchar prerequisite
+// types are visible. wchar.h only needs FILE as an opaque pointer type.
+typedef struct FILE FILE;
+
+// Avoid including time.h from wchar.h for the same wrapper-recursion reason.
+// wcsftime only needs struct tm as an opaque pointer type.
+struct tm;
"""
include_guard = "_RELIBC_WCHAR_H"
language = "C"
+21
View File
@@ -62,6 +62,27 @@ patches = [
"P3-stddef-reorder.patch",
# ld.so: parse DT_RPATH in addition to DT_RUNPATH (RUNPATH takes precedence per gABI)
"P3-ldso-rpath-support.patch",
# signal.h cbindgen: expose stdint types to downstream consumers
"P3-signal-stdint-include.patch",
# spawn.h implementation (new header module)
"P3-spawn.patch",
# C11 threads.h compatibility header
"P3-threads.patch",
# stdio_ext: __freadahead, __fpending, __fseterr helpers
"P3-stdio-fseterr.patch",
# locale: getlocalename_l function
"P3-locale-getlocalename-l.patch",
# SysV IPC foundation (key_t, ipc_perm, IPC_* constants, sys/ipc.h header)
"P3-sysv-ipc.patch",
# SysV semaphore implementation (semget/semop/semctl)
"P3-sysv-sem-impl.patch",
# SysV shared memory implementation (shmget/shmat/shmdt/shmctl)
"P3-sysv-shm-impl.patch",
# IPC tests (semaphore/shm)
"P3-ipc-tests.patch",
# ST_RDONLY/ST_NOSUID constants for statvfs (POSIX)
"P3-statvfs-constants.patch",
]
[build]