Skip to main content

c/
regression_stubs.rs

1// Stubs and minimal implementations for symbols required by libc-test
2// regression cases that currently fail to link.
3
4const _SC_ARG_MAX: c_int = 0;
5const _SC_CHILD_MAX: c_int = 1;
6const _SC_CLK_TCK: c_int = 2;
7const _SC_NGROUPS_MAX: c_int = 3;
8const _SC_OPEN_MAX: c_int = 4;
9const _SC_STREAM_MAX: c_int = 5;
10const _SC_TZNAME_MAX: c_int = 6;
11const _SC_PAGE_SIZE: c_int = 30;
12const _SC_NPROCESSORS_CONF: c_int = 83;
13const _SC_NPROCESSORS_ONLN: c_int = 84;
14const _SC_PHYS_PAGES: c_int = 85;
15const _SC_AVPHYS_PAGES: c_int = 86;
16const _SC_IOV_MAX: c_int = 60;
17const _SC_SEM_NSEMS_MAX: c_int = 32;
18const _SC_SEM_VALUE_MAX: c_int = 33;
19const _SC_MQ_OPEN_MAX: c_int = 27;
20const _SC_MQ_PRIO_MAX: c_int = 28;
21const _SC_DELAYTIMER_MAX: c_int = 26;
22const _SC_THREAD_DESTRUCTOR_ITERATIONS: c_int = 73;
23const _SC_THREAD_KEYS_MAX: c_int = 74;
24const _SC_THREAD_STACK_MIN: c_int = 75;
25const _SC_LOGIN_NAME_MAX: c_int = 71;
26const _SC_TTY_NAME_MAX: c_int = 72;
27const _SC_SYMLOOP_MAX: c_int = 173;
28const _SC_HOST_NAME_MAX: c_int = 180;
29const _SC_NZERO: c_int = 109;
30const _SC_VERSION: c_int = 29;
31const _SC_2_VERSION: c_int = 46;
32const _SC_XOPEN_VERSION: c_int = 89;
33
34#[no_mangle]
35pub unsafe extern "C" fn mmap(
36    addr: *mut c_void,
37    len: usize,
38    prot: c_int,
39    flags: c_int,
40    fd: c_int,
41    off: i64,
42) -> *mut c_void {
43    let r = crate::syscall(
44        SYS_MMAP,
45        addr as c_long,
46        len as c_long,
47        prot as c_long,
48        flags as c_long,
49        fd as c_long,
50        off as c_long,
51    );
52    if r == -1 {
53        return -1isize as *mut c_void;
54    }
55    r as *mut c_void
56}
57
58#[no_mangle]
59pub unsafe extern "C" fn munmap(addr: *mut c_void, len: usize) -> c_int {
60    crate::syscall(SYS_MUNMAP, addr as c_long, len as c_long, 0, 0, 0, 0) as c_int
61}
62
63#[no_mangle]
64pub unsafe extern "C" fn pread(fd: c_int, buf: *mut c_void, count: usize, offset: i64) -> isize {
65    crate::syscall(
66        SYS_PREAD64,
67        fd as c_long,
68        buf as c_long,
69        count as c_long,
70        offset as c_long,
71        0,
72        0,
73    ) as isize
74}
75
76unsafe fn rlimit_sc(resource: c_int) -> c_long {
77    let mut lim: crate::Rlimit = core::mem::zeroed();
78    if crate::getrlimit(resource, &mut lim) != 0 {
79        return -1;
80    }
81    if lim.rlim_cur == !0u64 {
82        return -1;
83    }
84    if lim.rlim_cur > c_long::MAX as u64 {
85        return c_long::MAX;
86    }
87    lim.rlim_cur as c_long
88}
89
90unsafe fn online_cpus() -> c_long {
91    let mut set = [0u8; 128];
92    let r = crate::sched_getaffinity(0, set.len(), set.as_mut_ptr());
93    if r != 0 {
94        return 1;
95    }
96    let mut count = 0u32;
97    for b in set.iter() {
98        count += b.count_ones();
99    }
100    if count == 0 { 1 } else { count as c_long }
101}
102
103unsafe fn memory_pages(free: bool) -> c_long {
104    // struct sysinfo: totalram/freeram/bufferram/mem_unit at fixed offsets.
105    let mut info = [0u64; 16];
106    if crate::sysinfo(info.as_mut_ptr() as *mut core::ffi::c_void) != 0 {
107        return -1;
108    }
109    let total = if free {
110        info[5].saturating_add(info[7])
111    } else {
112        info[4]
113    };
114    let unit = (info[13] & 0xffff_ffff) as u64;
115    let bytes = total.saturating_mul(if unit == 0 { 1 } else { unit });
116    (bytes / 4096) as c_long
117}
118
119#[no_mangle]
120pub unsafe extern "C" fn sysconf(name: c_int) -> c_long {
121    const POSIX_VERSION: c_long = 200809;
122    match name {
123        _SC_ARG_MAX => 131072,
124        _SC_CHILD_MAX => rlimit_sc(crate::RLIMIT_NPROC),
125        _SC_CLK_TCK => 100,
126        _SC_NGROUPS_MAX => 32,
127        _SC_OPEN_MAX => rlimit_sc(crate::RLIMIT_NOFILE),
128        _SC_STREAM_MAX => -1,
129        _SC_TZNAME_MAX => 6,
130        7 | 8 => 1,                    // JOB_CONTROL, SAVED_IDS
131        9 | 11 | 12 => POSIX_VERSION,  // REALTIME_SIGNALS, TIMERS, ASYNC_IO
132        10 | 13 | 14 => -1,            // PRIORITY_SCHEDULING, PRIORITIZED_IO, SYNC_IO
133        15..=22 => POSIX_VERSION,      // FSYNC .. SHARED_MEMORY_OBJECTS
134        23 | 24 => -1,                 // AIO_LISTIO_MAX, AIO_MAX
135        25 => 0,                       // AIO_PRIO_DELTA_MAX
136        _SC_DELAYTIMER_MAX => 0x7fffffff,
137        _SC_MQ_OPEN_MAX => -1,
138        _SC_MQ_PRIO_MAX => 32768,
139        _SC_VERSION => POSIX_VERSION,
140        _SC_PAGE_SIZE => 4096,
141        31 => 30,                      // _SC_RTSIG_MAX
142        _SC_SEM_NSEMS_MAX => 256,
143        _SC_SEM_VALUE_MAX => 0x7fffffff,
144        34 | 35 => -1,                 // SIGQUEUE_MAX, TIMER_MAX
145        36 => 99, 37 => 2048, 38 => 99, 39 => 1000, // POSIX2 bc limits
146        40 => 2,                       // COLL_WEIGHTS_MAX
147        42 | 43 => -1,                 // EXPR_NEST_MAX, LINE_MAX
148        44 => 255,                     // RE_DUP_MAX
149        _SC_2_VERSION => POSIX_VERSION,
150        47 => POSIX_VERSION,           // _SC_2_C_BIND
151        48..=52 => -1,                 // 2_C_DEV .. 2_LOCALEDEF
152        _SC_IOV_MAX => 1024,
153        67 | 68 => POSIX_VERSION,      // THREADS, THREAD_SAFE_FUNCTIONS
154        69 | 70 => -1,                 // GETGR/PW_R_SIZE_MAX
155        _SC_LOGIN_NAME_MAX => 256,
156        _SC_TTY_NAME_MAX => 32,
157        _SC_THREAD_DESTRUCTOR_ITERATIONS => 4,
158        _SC_THREAD_KEYS_MAX => 128,
159        _SC_THREAD_STACK_MIN => 2048,
160        76 => -1,                      // THREAD_THREADS_MAX
161        77 | 78 | 79 => POSIX_VERSION, // ATTR_STACKADDR/SIZE, PRIO_SCHED
162        80 | 81 => -1,                 // PRIO_INHERIT/PROTECT
163        82 => POSIX_VERSION,           // PROCESS_SHARED
164        _SC_NPROCESSORS_CONF | _SC_NPROCESSORS_ONLN => online_cpus(),
165        _SC_PHYS_PAGES => memory_pages(false),
166        _SC_AVPHYS_PAGES => memory_pages(true),
167        87 | 88 => -1,                 // ATEXIT_MAX, PASS_MAX
168        _SC_XOPEN_VERSION => 700,
169        90 => 700,                     // XOPEN_XCU_VERSION
170        91 => 1,                       // XOPEN_UNIX
171        92 => -1,                      // XOPEN_CRYPT
172        93 | 94 => 1,                  // XOPEN_ENH_I18N, XOPEN_SHM
173        95 => -1,                      // 2_CHAR_TERM
174        97 => -1,                      // 2_UPE
175        98..=100 => -1,                // XOPEN_XPG2..4
176        _SC_NZERO => 20,
177        125 | 126 | 128 => -1,         // XBS5 ILP32/LPBIG
178        127 => 1,                      // XBS5 LP64_OFF64
179        129..=131 => -1,               // XOPEN legacy/realtime
180        132 | 133 => POSIX_VERSION,    // ADVISORY_INFO, BARRIERS
181        137 | 138 | 139 => POSIX_VERSION,
182        149 => POSIX_VERSION,          // MONOTONIC_CLOCK
183        153 | 154 | 155 | 157 | 159 => POSIX_VERSION,
184        160 | 161 => -1,
185        164 => POSIX_VERSION,          // TIMEOUTS
186        165 => -1,                     // TYPED_MEMORY_OBJECTS
187        168..=172 => -1,               // 2_PBS
188        _SC_SYMLOOP_MAX => 40,
189        174 => 0,                      // STREAMS
190        175 => -1,
191        176 | 177 | 179 => -1,         // V6 ILP32/LPBIG
192        178 => 1,                      // V6_LP64_OFF64
193        _SC_HOST_NAME_MAX => 255,
194        181..=184 => -1,               // TRACE
195        235 | 236 => POSIX_VERSION,    // IPV6, RAW_SOCKETS
196        237 | 238 | 240 => -1,         // V7 variants
197        239 => 1,                      // V7_LP64_OFF64
198        241..=245 => -1,               // SS_REPL_MAX, TRACE_*
199        _ => {
200            crate::__errno_location().write(EINVAL);
201            -1
202        }
203    }
204}
205
206#[no_mangle]
207pub unsafe extern "C" fn execle(path: *const c_char, arg: *const c_char, mut args: ...) -> c_int {
208    let mut argv: [*const c_char; 128] = [core::ptr::null(); 128];
209    argv[0] = arg;
210    let mut n = 1usize;
211    loop {
212        let a: *const c_char = args.next_arg();
213        if a.is_null() {
214            break;
215        }
216        if n >= argv.len() - 1 {
217            crate::__errno_location().write(E2BIG);
218            return -1;
219        }
220        argv[n] = a;
221        n += 1;
222    }
223    argv[n] = core::ptr::null();
224    let envp: *const *const c_char = args.next_arg();
225    crate::execve(path, argv.as_ptr(), envp)
226}
227
228#[no_mangle]
229pub unsafe extern "C" fn flockfile(f: *mut crate::FILE) {
230    if (*f).lock < 0 { return; }
231    let tid = crate::sys_gettid() as i32;
232    loop {
233        let v = crate::a_load(&raw const (*f).lock);
234        if v == tid {
235            (*f).lockcount += 1;
236            return;
237        }
238        if v == 0 && crate::a_cas(&raw mut (*f).lock, 0, tid) == 0 {
239            (*f).lockcount = 1;
240            return;
241        }
242        if v != 0 {
243            crate::futex_wait(&raw mut (*f).lock, v);
244        }
245    }
246}
247
248#[no_mangle]
249pub unsafe extern "C" fn funlockfile(f: *mut crate::FILE) {
250    if (*f).lock < 0 { return; }
251    if (*f).lockcount > 1 {
252        (*f).lockcount -= 1;
253        return;
254    }
255    (*f).lockcount = 0;
256    crate::a_store(&raw mut (*f).lock, 0);
257    crate::futex_wake(&raw mut (*f).lock, 1);
258}
259
260#[no_mangle]
261pub unsafe extern "C" fn __libc_current_sigrtmin() -> c_int {
262    34
263}
264
265#[no_mangle]
266pub unsafe extern "C" fn strdup(s: *const c_char) -> *mut c_char {
267    if s.is_null() {
268        return core::ptr::null_mut();
269    }
270    let len = crate::strlen(s);
271    let p = crate::malloc(len + 1) as *mut c_char;
272    if p.is_null() {
273        return core::ptr::null_mut();
274    }
275    crate::memcpy(p as *mut c_void, s as *const c_void, len + 1);
276    p
277}
278
279static mut MKTEMP_COUNTER: c_uint = 0;
280
281unsafe fn mktemp_internal(
282    template: *mut c_char,
283    mkdir_fn: Option<unsafe extern "C" fn(*const c_char, c_uint) -> c_int>,
284) -> *mut c_char {
285    if template.is_null() {
286        crate::__errno_location().write(EINVAL);
287        return core::ptr::null_mut();
288    }
289    let len = crate::strlen(template);
290    if len < 6 {
291        crate::__errno_location().write(EINVAL);
292        return core::ptr::null_mut();
293    }
294    let mut xcount = 0usize;
295    while xcount < 6 {
296        let ch = *template.add(len - 1 - xcount) as u8;
297        if ch != b'X' {
298            break;
299        }
300        xcount += 1;
301    }
302    if xcount != 6 {
303        crate::__errno_location().write(EINVAL);
304        return core::ptr::null_mut();
305    }
306    let _pid = crate::getpid();
307    let mut c = MKTEMP_COUNTER;
308    for _ in 0..1000 {
309        let mut n = c;
310        for i in 0..6 {
311            let digit = (n % 36) as u8;
312            let ch = if digit < 10 { b'0' + digit } else { b'a' + digit - 10 };
313            *template.add(len - 6 + i) = ch as c_char;
314            n /= 36;
315        }
316        c = c.wrapping_add(1);
317        if mkdir_fn.is_some() {
318            if crate::mkdir(template, 0o700) == 0 {
319                MKTEMP_COUNTER = c;
320                return template;
321            }
322            let e = crate::__errno_location().read();
323            if e != EEXIST && e != EINTR {
324                break;
325            }
326        } else {
327            MKTEMP_COUNTER = c;
328            return template;
329        }
330    }
331    MKTEMP_COUNTER = c;
332    template
333}
334
335#[no_mangle]
336pub unsafe extern "C" fn mkdtemp(template: *mut c_char) -> *mut c_char {
337    mktemp_internal(template, Some(crate::mkdir))
338}
339
340#[no_mangle]
341pub unsafe extern "C" fn mktemp(template: *mut c_char) -> *mut c_char {
342    mktemp_internal(template, None)
343}