From 6e6d071ff9b3904dda3977803e9d5b67d8a4c96c Mon Sep 17 00:00:00 2001 From: Enrique Saurez Date: Thu, 28 May 2026 11:52:58 -0700 Subject: [PATCH] [posix] E: Add libposix pathconf/fpathconf stubs POSIX defines `pathconf(2)` / `fpathconf(2)` as queryable per-path configurable system limits. libstdc++'s `std::filesystem` code (`cow-fs_ops.cc`, `fs_ops.cc`) emits strong undefined references to `pathconf` -- specifically, `std::filesystem::current_path()` calls it to size the buffer for `getcwd()`. When the consumer of libstdc++ (e.g. CPython linking against `libstdc++.a`) tries to link, those references go unresolved and the link fails with "undefined reference to `pathconf'". This patch adds minimal `extern "C"` stubs for both functions to `src/libs/posix/src/dummy.rs`, matching the convention used by the other "not implemented" stubs in that module: - `pathconf(path, name) -> c_long` always returns `-1` with `errno = ENOSYS` (via `ErrorCode::InvalidSysCall`). - `fpathconf(fd, name) -> c_long` always returns `-1` with `errno = ENOSYS` (via `ErrorCode::InvalidSysCall`). This is sufficient to satisfy the libstdc++ link. libstdc++'s filesystem code checks `pathconf(...) == -1` and falls back to a compile-time `PATH_MAX` default, so observable behaviour is unchanged from "limit not advertised". A future implementation should return real, selector-aware values (`_PC_PATH_MAX = 4096`, `_PC_NAME_MAX = 255`, `_PC_LINK_MAX = 1`, etc.) and only set `errno = EINVAL` for genuinely unrecognised selectors, following the musl `src/conf/pathconf.c` pattern. Validated end-to-end: CPython 3.12 + numpy 1.26.4 link cleanly against a libstdc++.a that previously failed on `pathconf`, run `hello.py`, and produce `NUMPY_TEST_OK` on the Nanvix microvm. Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/libs/posix/src/dummy.rs | 79 +++++++++++++++++++++++++++++++++++++ 1 file changed, 79 insertions(+) diff --git a/src/libs/posix/src/dummy.rs b/src/libs/posix/src/dummy.rs index b70f8e87d4..d7230881c1 100644 --- a/src/libs/posix/src/dummy.rs +++ b/src/libs/posix/src/dummy.rs @@ -10,6 +10,7 @@ use ::sys::error::ErrorCode; use ::sysapi::ffi::{ c_char, c_int, + c_long, c_void, }; use ::syslog::trace_libcall; @@ -237,6 +238,84 @@ pub unsafe extern "C" fn realpath(path: *const c_char, resolved_path: *mut c_cha core::ptr::null_mut() } +/// +/// # Description +/// +/// Retrieves the value of a configurable system limit or option associated with the +/// pathname `path`, as identified by `name` (one of the `_PC_*` selectors defined in +/// ``). +/// +/// # Parameters +/// +/// - `path`: Null-terminated pathname of the file or directory being queried. +/// - `name`: A `_PC_*` selector specifying which configurable value to retrieve. +/// +/// # Returns +/// +/// On success a non-negative limit value, or `-1` (with `errno` unchanged) when the +/// queried option has no determinate limit. On failure returns `-1` and sets `errno`. +/// +/// # Notes +/// +/// This is a dummy implementation that always returns `-1` with `errno = ENOSYS`, +/// matching the convention used by the other "not implemented" stubs in this module. +/// Callers (notably libstdc++'s `std::filesystem`) treat `-1` as "no limit known" and +/// fall back to compile-time defaults such as `PATH_MAX`, so this stub is sufficient +/// to satisfy the libstdc++ link without changing behaviour. A future implementation +/// should return real limits for the selectors it knows about (e.g. `_PC_PATH_MAX`, +/// `_PC_NAME_MAX`, `_PC_LINK_MAX`), and only set `errno = EINVAL` for genuinely +/// unrecognised selectors per the POSIX contract. +/// +/// # Safety +/// +/// This function is unsafe because it accepts a raw pointer supplied by foreign callers. +/// It is safe to call this function if `path` (when non-null) points to a valid +/// null-terminated C string. +/// +#[unsafe(no_mangle)] +#[trace_libcall] +pub unsafe extern "C" fn pathconf(_path: *const c_char, _name: c_int) -> c_long { + ::syslog::debug!("pathconf(): not implemented"); + *__errno_location() = ErrorCode::InvalidSysCall.get(); + -1 +} + +/// +/// # Description +/// +/// Retrieves the value of a configurable system limit or option associated with the +/// open file descriptor `fd`, as identified by `name` (one of the `_PC_*` selectors +/// defined in ``). +/// +/// # Parameters +/// +/// - `fd`: An open file descriptor to query. +/// - `name`: A `_PC_*` selector specifying which configurable value to retrieve. +/// +/// # Returns +/// +/// On success a non-negative limit value, or `-1` (with `errno` unchanged) when the +/// queried option has no determinate limit. On failure returns `-1` and sets `errno`. +/// +/// # Notes +/// +/// This is a dummy implementation that always returns `-1` with `errno = ENOSYS`. +/// See `pathconf()` for the rationale on why this stub is acceptable for the current +/// libstdc++ link requirements. +/// +/// # Safety +/// +/// This function is safe to call with any integer; passing a descriptor that is not +/// currently open does not change the (stub) behaviour. +/// +#[unsafe(no_mangle)] +#[trace_libcall] +pub unsafe extern "C" fn fpathconf(_fd: c_int, _name: c_int) -> c_long { + ::syslog::debug!("fpathconf(): not implemented"); + *__errno_location() = ErrorCode::InvalidSysCall.get(); + -1 +} + /// /// # Description ///