Implement confstr (unistd.h)

The implementation for confstr is straightforward. Most of the constants
return 1 on both musl and glibc. The only constant that doesn't is
required for Fish.

I also switched an #[unsafe(no_mangle)] from my last patch back
to a #[no_mangle] because we need to bump cbindgen. #[unsafe(no_mangle)]
is required for Rust 2024.
This commit is contained in:
Josh Megnauth
2025-08-21 02:47:45 -04:00
parent 4758685217
commit 9d2f5d95dc
8 changed files with 98 additions and 4 deletions
+62 -3
View File
@@ -34,7 +34,10 @@ pub use crate::header::stdio::{ctermid, cuserid};
// TODO: implement and reexport fcntl functions:
//pub use crate::header::fcntl::{faccessat, fchownat, fexecve, linkat, readlinkat, symlinkat, unlinkat};
use super::errno::{E2BIG, ENOMEM};
use super::{
errno::{E2BIG, ENOMEM},
stdio::snprintf,
};
mod brk;
mod getopt;
@@ -62,6 +65,45 @@ pub const STDERR_FILENO: c_int = 2;
pub const L_cuserid: usize = 9;
// confstr constants
// These are copied from Rust's libc and match musl as well.
pub const _CS_PATH: c_int = 0;
pub const _CS_POSIX_V6_WIDTH_RESTRICTED_ENVS: c_int = 1;
pub const _CS_POSIX_V5_WIDTH_RESTRICTED_ENVS: c_int = 4;
pub const _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS: c_int = 5;
pub const _CS_POSIX_V6_ILP32_OFF32_CFLAGS: c_int = 1116;
pub const _CS_POSIX_V6_ILP32_OFF32_LDFLAGS: c_int = 1117;
pub const _CS_POSIX_V6_ILP32_OFF32_LIBS: c_int = 1118;
pub const _CS_POSIX_V6_ILP32_OFF32_LINTFLAGS: c_int = 1119;
pub const _CS_POSIX_V6_ILP32_OFFBIG_CFLAGS: c_int = 1120;
pub const _CS_POSIX_V6_ILP32_OFFBIG_LDFLAGS: c_int = 1121;
pub const _CS_POSIX_V6_ILP32_OFFBIG_LIBS: c_int = 1122;
pub const _CS_POSIX_V6_ILP32_OFFBIG_LINTFLAGS: c_int = 1123;
pub const _CS_POSIX_V6_LP64_OFF64_CFLAGS: c_int = 1124;
pub const _CS_POSIX_V6_LP64_OFF64_LDFLAGS: c_int = 1125;
pub const _CS_POSIX_V6_LP64_OFF64_LIBS: c_int = 1126;
pub const _CS_POSIX_V6_LP64_OFF64_LINTFLAGS: c_int = 1127;
pub const _CS_POSIX_V6_LPBIG_OFFBIG_CFLAGS: c_int = 1128;
pub const _CS_POSIX_V6_LPBIG_OFFBIG_LDFLAGS: c_int = 1129;
pub const _CS_POSIX_V6_LPBIG_OFFBIG_LIBS: c_int = 1130;
pub const _CS_POSIX_V6_LPBIG_OFFBIG_LINTFLAGS: c_int = 1131;
pub const _CS_POSIX_V7_ILP32_OFF32_CFLAGS: c_int = 1132;
pub const _CS_POSIX_V7_ILP32_OFF32_LDFLAGS: c_int = 1133;
pub const _CS_POSIX_V7_ILP32_OFF32_LIBS: c_int = 1134;
pub const _CS_POSIX_V7_ILP32_OFF32_LINTFLAGS: c_int = 1135;
pub const _CS_POSIX_V7_ILP32_OFFBIG_CFLAGS: c_int = 1136;
pub const _CS_POSIX_V7_ILP32_OFFBIG_LDFLAGS: c_int = 1137;
pub const _CS_POSIX_V7_ILP32_OFFBIG_LIBS: c_int = 1138;
pub const _CS_POSIX_V7_ILP32_OFFBIG_LINTFLAGS: c_int = 1139;
pub const _CS_POSIX_V7_LP64_OFF64_CFLAGS: c_int = 1140;
pub const _CS_POSIX_V7_LP64_OFF64_LDFLAGS: c_int = 1141;
pub const _CS_POSIX_V7_LP64_OFF64_LIBS: c_int = 1142;
pub const _CS_POSIX_V7_LP64_OFF64_LINTFLAGS: c_int = 1143;
pub const _CS_POSIX_V7_LPBIG_OFFBIG_CFLAGS: c_int = 1144;
pub const _CS_POSIX_V7_LPBIG_OFFBIG_LDFLAGS: c_int = 1145;
pub const _CS_POSIX_V7_LPBIG_OFFBIG_LIBS: c_int = 1146;
pub const _CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS: c_int = 1147;
#[thread_local]
pub static mut fork_hooks_static: Option<[LinkedList<extern "C" fn()>; 3]> = None;
@@ -154,9 +196,26 @@ pub extern "C" fn close(fildes: c_int) -> c_int {
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/confstr.html>.
// #[no_mangle]
#[no_mangle]
pub extern "C" fn confstr(name: c_int, buf: *mut c_char, len: size_t) -> size_t {
unimplemented!();
// confstr returns the number of bytes required to hold the string INCLUDING the NUL
// terminator. This is different from other C functions hence the + 1.
match name {
_CS_PATH => {
let posix2_path = c"/usr/bin";
unsafe { snprintf(buf, len, c"%s".as_ptr(), posix2_path.as_ptr()) + 1 }
.try_into()
.unwrap_or_default()
}
_CS_POSIX_V6_WIDTH_RESTRICTED_ENVS
| _CS_POSIX_V5_WIDTH_RESTRICTED_ENVS
| _CS_POSIX_V7_WIDTH_RESTRICTED_ENVS
| _CS_POSIX_V6_LP64_OFF64_LIBS..=_CS_POSIX_V7_LPBIG_OFFBIG_LINTFLAGS => 1,
_ => {
platform::ERRNO.set(errno::EINVAL);
0
}
}
}
/// See <https://pubs.opengroup.org/onlinepubs/9799919799/functions/crypt.html>.
+1 -1
View File
@@ -12,7 +12,7 @@ pub use sys::*;
use core::ffi::{c_int, c_long};
#[unsafe(no_mangle)]
#[no_mangle]
pub unsafe extern "C" fn sysconf(name: c_int) -> c_long {
sysconf_impl(name)
}
+1
View File
@@ -124,6 +124,7 @@ EXPECT_NAMES=\
unistd/access \
unistd/brk \
unistd/constants \
unistd/confstr \
unistd/dup \
unistd/exec \
unistd/fchdir \
+34
View File
@@ -0,0 +1,34 @@
#include <assert.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define CSPATHSZ 9
#define BADSIZ 4
int main(void) {
char actual[CSPATHSZ] = {0};
assert(confstr(_CS_PATH, actual, CSPATHSZ) == CSPATHSZ);
const char expected[] = "/usr/bin";
assert(strncmp(expected, actual, CSPATHSZ) == 0);
// The constants other than _CS_PATH just return an empty str (no support).
char empty[] = "";
assert(
confstr(
_CS_POSIX_V6_LP64_OFF64_LIBS,
empty,
0
) == 1
);
// Buffers that are too small should return the expected size.
char small[BADSIZ] = {0};
assert(confstr(_CS_PATH, small, BADSIZ) == CSPATHSZ);
// Null buffer and zero length should return the expected size
// for the constant.
assert(confstr(_CS_PATH, NULL, 0) == CSPATHSZ);
return EXIT_SUCCESS;
}