1#![cfg_attr(not(test), no_std)]
2#![feature(c_variadic)]
3#![feature(linkage)]
4#![cfg_attr(target_arch = "aarch64", feature(f128))]
5#![cfg_attr(target_arch = "riscv64", feature(f128))]
6#![allow(dead_code, non_camel_case_types)]
7#![allow(static_mut_refs)]
11#![allow(improper_ctypes_definitions)]
14
15use core::ffi::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ulonglong, c_void, VaList};
16use core::ptr::null_mut;
17use core::sync::atomic::{AtomicI32, AtomicUsize, Ordering};
18
19macro_rules! ERRNO {
20 () => { *errno_ptr() };
21}
22
23include!("encoding_tables.rs");
24include!("math_helpers.rs");
25include!("math_bitmanip.rs");
26include!("math_sqrtfmod.rs");
27include!("math_trig.rs");
28include!("math_exp.rs");
29include!("math_erf.rs");
30include!("math_lgamma.rs");
31include!("math_tgamma.rs");
32include!("math_bessel.rs");
33include!("alloc.rs");
34include!("math_log.rs");
35include!("math_pow.rs");
36include!("math_hypot.rs");
37include!("math_hyperbolic.rs");
38include!("math_invtrig.rs");
39include!("math_lrint.rs");
40include!("math_long_double.rs");
41include!("string_fast.rs");
42include!("vdso.rs");
43
44const EILSEQ: c_int = 84;
49const EINVAL: c_int = 22;
50const EFAULT: c_int = 14;
51const E2BIG: c_int = 7;
52
53const LC_CTYPE: c_int = 0;
54const LC_NUMERIC: c_int = 1;
55const LC_TIME: c_int = 2;
56const LC_COLLATE: c_int = 3;
57const LC_MONETARY: c_int = 4;
58const LC_MESSAGES: c_int = 5;
59const LC_ALL: c_int = 6;
60const ENOMEM: c_int = 12;
61const EINTR: c_int = 4;
62const EPERM: c_int = 1;
63const EAGAIN: c_int = 11;
64const EBUSY: c_int = 16;
65const EDEADLK: c_int = 35;
66const ETIMEDOUT: c_int = 110;
67const ECANCELED: c_int = 125;
68const EOVERFLOW: c_int = 75;
69const EOWNERDEAD: c_int = 130;
70const ENOTRECOVERABLE: c_int = 131;
71
72static mut ERRNO_FALLBACK: c_int = 0;
78static ERRNO_TLS_ACTIVE: AtomicUsize = AtomicUsize::new(0);
79const ERRNO_TCB_OFFSET: usize = 0x30;
80
81#[inline]
82unsafe fn errno_ptr() -> *mut c_int {
83 if ERRNO_TLS_ACTIVE.load(Ordering::Relaxed) == 0 {
84 return core::ptr::addr_of_mut!(ERRNO_FALLBACK);
85 }
86 #[cfg(target_arch = "x86_64")]
87 let tp: usize = {
88 let tp: usize;
89 core::arch::asm!("mov {}, fs:[0]", out(reg) tp, options(nostack, preserves_flags));
90 tp
91 };
92 #[cfg(target_arch = "aarch64")]
93 let tp: usize = {
94 let tp: usize;
95 core::arch::asm!("mrs {}, tpidr_el0", out(reg) tp, options(nostack, preserves_flags));
96 tp
97 };
98 #[cfg(target_arch = "riscv64")]
99 let tp: usize = {
100 let tp: usize;
101 core::arch::asm!("mv {}, tp", out(reg) tp, options(nostack, preserves_flags));
102 tp
103 };
104 #[cfg(target_arch = "x86_64")]
105 let tcb = tp;
106 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
107 let tcb = tp - 256;
108 (tcb + ERRNO_TCB_OFFSET) as *mut c_int
109}
110
111unsafe fn errno_init() {
114 let tp = arch_get_tp();
115 #[cfg(target_arch = "x86_64")]
116 let tcb = tp;
117 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
118 let tcb = tp.wrapping_sub(256);
119 if tp != 0 && core::ptr::read(tcb as *const usize) == tcb {
120 ERRNO_TLS_ACTIVE.store(1, Ordering::Relaxed);
121 }
122}
123
124#[cfg(target_arch = "x86_64")]
125unsafe fn arch_get_tp() -> usize {
126 let mut tp: usize = 0;
127 let _ = <Arch as Syscalls>::syscall2(158 , 0x1003 , &mut tp as *mut usize as i64);
128 tp
129}
130
131#[cfg(target_arch = "aarch64")]
132unsafe fn arch_get_tp() -> usize {
133 let tp: usize;
134 core::arch::asm!("mrs {}, tpidr_el0", out(reg) tp, options(nostack, preserves_flags));
135 tp
136}
137
138#[cfg(target_arch = "riscv64")]
139unsafe fn arch_get_tp() -> usize {
140 let tp: usize;
141 core::arch::asm!("mv {}, tp", out(reg) tp, options(nostack, preserves_flags));
142 tp
143}
144
145#[inline]
148unsafe fn syscall_ret(r: i64) -> i64 {
149 if r < 0 {
150 *errno_ptr() = (-r) as c_int;
151 -1
152 } else {
153 r
154 }
155}
156
157#[no_mangle]
158pub unsafe extern "C" fn __errno_location() -> *mut c_int {
159 errno_ptr()
160}
161
162#[cfg(not(test))]
163#[panic_handler]
164fn panic(_: &core::panic::PanicInfo) -> ! {
165 loop {}
166}
167
168#[cfg(not(test))]
170#[no_mangle]
171pub extern "C" fn rust_eh_personality() {}
172
173const PROT_READ: i32 = 1;
178const PROT_WRITE: i32 = 2;
179const MAP_SHARED: i32 = 0x01;
180const MAP_PRIVATE: i32 = 0x02;
181const MAP_ANONYMOUS: i32 = 0x20;
182
183trait Syscalls {
188 unsafe fn syscall0(n: i64) -> i64;
189 unsafe fn syscall1(n: i64, a1: i64) -> i64;
190 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64;
191 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64;
192 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64;
193 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64;
194 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64;
195 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> !;
196}
197
198struct X86_64;
199struct Aarch64;
200struct Riscv64;
201
202#[cfg(target_arch = "x86_64")]
203impl Syscalls for X86_64 {
204 #[inline(always)]
205 unsafe fn syscall0(n: i64) -> i64 {
206 let result: i64;
207 core::arch::asm!(
208 "syscall",
209 inlateout("rax") n => result,
210 lateout("rcx") _,
211 lateout("r11") _,
212 );
213 result
214 }
215 #[inline(always)]
216 unsafe fn syscall1(n: i64, a1: i64) -> i64 {
217 let result: i64;
218 core::arch::asm!(
219 "syscall",
220 inlateout("rax") n => result,
221 in("rdi") a1,
222 lateout("rcx") _,
223 lateout("r11") _,
224 );
225 result
226 }
227 #[inline(always)]
228 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
229 let result: i64;
230 core::arch::asm!(
231 "syscall",
232 inlateout("rax") n => result,
233 in("rdi") a1,
234 in("rsi") a2,
235 lateout("rcx") _,
236 lateout("r11") _,
237 );
238 result
239 }
240 #[inline(always)]
241 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
242 let result: i64;
243 core::arch::asm!(
244 "syscall",
245 inlateout("rax") n => result,
246 in("rdi") a1,
247 in("rsi") a2,
248 in("rdx") a3,
249 lateout("rcx") _,
250 lateout("r11") _,
251 );
252 result
253 }
254 #[inline(always)]
255 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
256 let result: i64;
257 core::arch::asm!(
258 "syscall",
259 inlateout("rax") n => result,
260 in("rdi") a1,
261 in("rsi") a2,
262 in("rdx") a3,
263 in("r10") a4,
264 lateout("rcx") _,
265 lateout("r11") _,
266 );
267 result
268 }
269 #[inline(always)]
270 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
271 let result: i64;
272 core::arch::asm!(
273 "syscall",
274 inlateout("rax") n => result,
275 in("rdi") a1,
276 in("rsi") a2,
277 in("rdx") a3,
278 in("r10") a4,
279 in("r8") a5,
280 lateout("rcx") _,
281 lateout("r11") _,
282 );
283 result
284 }
285 #[inline(always)]
286 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
287 let result: i64;
288 core::arch::asm!(
289 "syscall",
290 inlateout("rax") n => result,
291 in("rdi") a1,
292 in("rsi") a2,
293 in("rdx") a3,
294 in("r10") a4,
295 in("r8") a5,
296 in("r9") a6,
297 lateout("rcx") _,
298 lateout("r11") _,
299 );
300 result
301 }
302 #[inline(always)]
303 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
304 core::arch::asm!(
305 "syscall",
306 in("rax") n,
307 in("rdi") a1,
308 options(noreturn)
309 );
310 }
311}
312
313#[cfg(target_arch = "aarch64")]
314impl Syscalls for Aarch64 {
315 #[inline(always)]
316 unsafe fn syscall0(n: i64) -> i64 {
317 let result: i64;
318 core::arch::asm!(
319 "svc #0",
320 inlateout("x8") n => _,
321 lateout("x0") result,
322 options(nostack),
323 );
324 result
325 }
326 #[inline(always)]
327 unsafe fn syscall1(n: i64, a1: i64) -> i64 {
328 let result: i64;
329 core::arch::asm!(
330 "svc #0",
331 inlateout("x8") n => _,
332 inlateout("x0") a1 => result,
333 options(nostack),
334 );
335 result
336 }
337 #[inline(always)]
338 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
339 let result: i64;
340 core::arch::asm!(
341 "svc #0",
342 inlateout("x8") n => _,
343 inlateout("x0") a1 => result,
344 inlateout("x1") a2 => _,
345 options(nostack),
346 );
347 result
348 }
349 #[inline(always)]
350 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
351 let result: i64;
352 core::arch::asm!(
353 "svc #0",
354 inlateout("x8") n => _,
355 inlateout("x0") a1 => result,
356 inlateout("x1") a2 => _,
357 inlateout("x2") a3 => _,
358 options(nostack),
359 );
360 result
361 }
362 #[inline(always)]
363 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
364 let result: i64;
365 core::arch::asm!(
366 "svc #0",
367 inlateout("x8") n => _,
368 inlateout("x0") a1 => result,
369 inlateout("x1") a2 => _,
370 inlateout("x2") a3 => _,
371 inlateout("x3") a4 => _,
372 options(nostack),
373 );
374 result
375 }
376 #[inline(always)]
377 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
378 let result: i64;
379 core::arch::asm!(
380 "svc #0",
381 inlateout("x8") n => _,
382 inlateout("x0") a1 => result,
383 inlateout("x1") a2 => _,
384 inlateout("x2") a3 => _,
385 inlateout("x3") a4 => _,
386 inlateout("x4") a5 => _,
387 options(nostack),
388 );
389 result
390 }
391 #[inline(always)]
392 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
393 let result: i64;
394 core::arch::asm!(
395 "svc #0",
396 inlateout("x8") n => _,
397 inlateout("x0") a1 => result,
398 inlateout("x1") a2 => _,
399 inlateout("x2") a3 => _,
400 inlateout("x3") a4 => _,
401 inlateout("x4") a5 => _,
402 inlateout("x5") a6 => _,
403 options(nostack),
404 );
405 result
406 }
407 #[inline(always)]
408 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
409 core::arch::asm!(
410 "svc #0",
411 in("x8") n,
412 in("x0") a1,
413 options(noreturn, nostack),
414 );
415 }
416}
417
418#[cfg(target_arch = "riscv64")]
419impl Syscalls for Riscv64 {
420 #[inline(always)]
421 unsafe fn syscall0(n: i64) -> i64 {
422 let result: i64;
423 core::arch::asm!(
424 "ecall",
425 inlateout("a7") n => _,
426 lateout("a0") result,
427 options(nostack),
428 );
429 result
430 }
431 #[inline(always)]
432 unsafe fn syscall1(n: i64, a1: i64) -> i64 {
433 let result: i64;
434 core::arch::asm!(
435 "ecall",
436 inlateout("a7") n => _,
437 inlateout("a0") a1 => result,
438 options(nostack),
439 );
440 result
441 }
442 #[inline(always)]
443 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
444 let result: i64;
445 core::arch::asm!(
446 "ecall",
447 inlateout("a7") n => _,
448 inlateout("a0") a1 => result,
449 inlateout("a1") a2 => _,
450 options(nostack),
451 );
452 result
453 }
454 #[inline(always)]
455 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
456 let result: i64;
457 core::arch::asm!(
458 "ecall",
459 inlateout("a7") n => _,
460 inlateout("a0") a1 => result,
461 inlateout("a1") a2 => _,
462 inlateout("a2") a3 => _,
463 options(nostack),
464 );
465 result
466 }
467 #[inline(always)]
468 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
469 let result: i64;
470 core::arch::asm!(
471 "ecall",
472 inlateout("a7") n => _,
473 inlateout("a0") a1 => result,
474 inlateout("a1") a2 => _,
475 inlateout("a2") a3 => _,
476 inlateout("a3") a4 => _,
477 options(nostack),
478 );
479 result
480 }
481 #[inline(always)]
482 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
483 let result: i64;
484 core::arch::asm!(
485 "ecall",
486 inlateout("a7") n => _,
487 inlateout("a0") a1 => result,
488 inlateout("a1") a2 => _,
489 inlateout("a2") a3 => _,
490 inlateout("a3") a4 => _,
491 inlateout("a4") a5 => _,
492 options(nostack),
493 );
494 result
495 }
496 #[inline(always)]
497 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
498 let result: i64;
499 core::arch::asm!(
500 "ecall",
501 inlateout("a7") n => _,
502 inlateout("a0") a1 => result,
503 inlateout("a1") a2 => _,
504 inlateout("a2") a3 => _,
505 inlateout("a3") a4 => _,
506 inlateout("a4") a5 => _,
507 inlateout("a5") a6 => _,
508 options(nostack),
509 );
510 result
511 }
512 #[inline(always)]
513 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
514 core::arch::asm!(
515 "ecall",
516 in("a7") n,
517 in("a0") a1,
518 options(noreturn, nostack),
519 );
520 }
521}
522
523#[cfg(target_arch = "x86_64")]
524type Arch = X86_64;
525#[cfg(target_arch = "aarch64")]
526type Arch = Aarch64;
527#[cfg(target_arch = "riscv64")]
528type Arch = Riscv64;
529
530
531
532#[cfg(target_arch = "x86_64")]
534mod sysnr {
535 pub const SYS_READ: i64 = 0;
536 pub const SYS_WRITE: i64 = 1;
537 pub const SYS_OPEN: i64 = 2;
538 pub const SYS_CLOSE: i64 = 3;
539 pub const SYS_STAT: i64 = 4;
540 pub const SYS_FSTAT: i64 = 5;
541 pub const SYS_LSEEK: i64 = 8;
542 pub const SYS_MMAP: i64 = 9;
543 pub const SYS_MUNMAP: i64 = 11;
544 pub const SYS_MPROTECT: i64 = 10;
545 pub const SYS_RT_SIGACTION: i64 = 13;
546 pub const SYS_RT_SIGPROCMASK: i64 = 14;
547 pub const SYS_IOCTL: i64 = 16;
548 pub const SYS_ACCESS: i64 = 21;
549 pub const SYS_SHMGET: i64 = 29;
550 pub const SYS_SHMAT: i64 = 30;
551 pub const SYS_SHMCTL: i64 = 31;
552 pub const SYS_DUP: i64 = 32;
553 pub const SYS_NANOSLEEP: i64 = 35;
554 pub const SYS_SETITIMER: i64 = 38;
555 pub const SYS_ALARM: i64 = 37;
556 pub const SYS_SOCKET: i64 = 41;
557 pub const SYS_CONNECT: i64 = 42;
558 pub const SYS_ACCEPT: i64 = 43;
559 pub const SYS_ACCEPT4: i64 = 288;
560 pub const SYS_SENDTO: i64 = 44;
561 pub const SYS_RECVFROM: i64 = 45;
562 pub const SYS_SENDMSG: i64 = 46;
563 pub const SYS_RECVMSG: i64 = 47;
564 pub const SYS_SHUTDOWN: i64 = 48;
565 pub const SYS_BIND: i64 = 49;
566 pub const SYS_LISTEN: i64 = 50;
567 pub const SYS_GETSOCKNAME: i64 = 51;
568 pub const SYS_SOCKETPAIR: i64 = 53;
569 pub const SYS_SETSOCKOPT: i64 = 54;
570 pub const SYS_EXECVE: i64 = 59;
571 pub const SYS_WAIT4: i64 = 61;
572 pub const SYS_KILL: i64 = 62;
573 pub const SYS_UNAME: i64 = 63;
574 pub const SYS_SEMGET: i64 = 64;
575 pub const SYS_SEMOP: i64 = 65;
576 pub const SYS_SEMCTL: i64 = 66;
577 pub const SYS_SHMDT: i64 = 67;
578 pub const SYS_MSGGET: i64 = 68;
579 pub const SYS_MSGSND: i64 = 69;
580 pub const SYS_MSGRCV: i64 = 70;
581 pub const SYS_MSGCTL: i64 = 71;
582 pub const SYS_FCNTL: i64 = 72;
583 pub const SYS_FSYNC: i64 = 74;
584 pub const SYS_TRUNCATE: i64 = 76;
585 pub const SYS_FTRUNCATE: i64 = 77;
586 pub const SYS_GETCWD: i64 = 79;
587 pub const SYS_CHDIR: i64 = 80;
588 pub const SYS_SYMLINK: i64 = 88;
589 pub const SYS_FCHMOD: i64 = 91;
590 pub const SYS_UMASK: i64 = 95;
591 pub const SYS_GETRLIMIT: i64 = 97;
592 pub const SYS_SETUID: i64 = 105;
593 pub const SYS_SETGID: i64 = 106;
594 pub const SYS_SETPGID: i64 = 109;
595 pub const SYS_GETGROUPS: i64 = 115;
596 pub const SYS_GETPGID: i64 = 121;
597 pub const SYS_GETSID: i64 = 124;
598 pub const SYS_RT_SIGPENDING: i64 = 127;
599 pub const SYS_RT_SIGTIMEDWAIT: i64 = 128;
600 pub const SYS_RT_SIGSUSPEND: i64 = 130;
601 pub const SYS_SIGALTSTACK: i64 = 131;
602 pub const SYS_SETRLIMIT: i64 = 160;
603 pub const SYS_SETHOSTNAME: i64 = 170;
604 pub const SYS_FUTEX: i64 = 202;
605 pub const SYS_CLOCK_GETTIME: i64 = 228;
606 pub const SYS_CLOCK_GETRES: i64 = 229;
607 pub const SYS_CLOCK_NANOSLEEP: i64 = 230;
608 pub const SYS_EXIT_GROUP: i64 = 231;
609 pub const SYS_TGKILL: i64 = 234;
610 pub const SYS_MKDIRAT: i64 = 258;
611 pub const SYS_NEWFSTATAT: i64 = 262;
612 pub const SYS_UNLINKAT: i64 = 263;
613 pub const SYS_LINKAT: i64 = 265;
614 pub const SYS_SYMLINKAT: i64 = 266;
615 pub const SYS_READLINKAT: i64 = 267;
616 pub const SYS_FCHMODAT: i64 = 268;
617 pub const SYS_SET_ROBUST_LIST: i64 = 273;
618 pub const SYS_UTIMENSAT: i64 = 280;
619 pub const SYS_OPENAT: i64 = 257;
620 pub const SYS_FACCESSAT: i64 = 269;
621 pub const SYS_DUP3: i64 = 292;
622 pub const SYS_PIPE2: i64 = 293;
623 pub const SYS_SYNCFS: i64 = 306;
624 pub const SYS_RENAMEAT2: i64 = 316;
625 pub const SYS_STATFS: i64 = 137;
626 pub const SYS_FSTATFS: i64 = 138;
627 pub const SYS_FDATASYNC: i64 = 75;
628 pub const SYS_PAUSE: i64 = 34;
629 pub const SYS_POLL: i64 = 7;
630 pub const SYS_PPOLL: i64 = 271;
631 pub const SYS_PSELECT6: i64 = 270;
632 pub const SYS_GETPID: i64 = 39;
633 pub const SYS_FORK: i64 = 57;
634 pub const SYS_EXIT: i64 = 60;
635 pub const SYS_GETPPID: i64 = 110;
636 pub const SYS_SETSID: i64 = 112;
637 pub const SYS_SYNC: i64 = 162;
638 pub const SYS_GETUID: i64 = 102;
639 pub const SYS_GETGID: i64 = 104;
640 pub const SYS_GETEUID: i64 = 107;
641 pub const SYS_GETEGID: i64 = 108;
642 pub const SYS_GETTID: i64 = 186;
643 pub const SYS_CLOCK_SETTIME: i64 = 227;
644 pub const SYS_CLONE: i64 = 56;
645 pub const SYS_PREAD64: i64 = 17;
646 pub const SYS_MREMAP: i64 = 25;
647 pub const SYS_SYSINFO: i64 = 99;
648 pub const SYS_MEMBARRIER: i64 = 324;
649 pub const SYS_VHANGUP: i64 = 153;
650 pub const SYS_VMSPLICE: i64 = 278;
651 pub const SYS_GETDENTS64: i64 = 217;
652 pub const SYS_EPOLL_CREATE: i64 = 213;
653 pub const SYS_EPOLL_CREATE1: i64 = 291;
654 pub const SYS_EPOLL_CTL: i64 = 233;
655 pub const SYS_EPOLL_WAIT: i64 = 232;
656 pub const SYS_EPOLL_PWAIT: i64 = 281;
657 pub const SYS_EVENTFD2: i64 = 290;
658 pub const SYS_SIGNALFD4: i64 = 289;
659 pub const SYS_TIMERFD_CREATE: i64 = 283;
660 pub const SYS_TIMERFD_SETTIME: i64 = 286;
661 pub const SYS_TIMERFD_GETTIME: i64 = 287;
662 pub const SYS_PRCTL: i64 = 157;
663 pub const SYS_FALLOCATE: i64 = 285;
664 pub const SYS_FLOCK: i64 = 73;
665 pub const SYS_SETGROUPS: i64 = 116;
666 pub const SYS_SETRESUID: i64 = 117;
667 pub const SYS_SETRESGID: i64 = 119;
668 pub const SYS_GETRESUID: i64 = 118;
669 pub const SYS_GETRESGID: i64 = 120;
670 pub const SYS_MKNOD: i64 = 133;
671 pub const SYS_FCHDIR: i64 = 81;
672 pub const SYS_FCHOWN: i64 = 93;
673 pub const SYS_ACCT: i64 = 163;
674 pub const SYS_ADJTIMEX: i64 = 159;
675 pub const SYS_CAPGET: i64 = 125;
676 pub const SYS_CAPSET: i64 = 126;
677 pub const SYS_CHROOT: i64 = 161;
678 pub const SYS_COPY_FILE_RANGE: i64 = 326;
679 pub const SYS_DELETE_MODULE: i64 = 176;
680 pub const SYS_INIT_MODULE: i64 = 175;
681 pub const SYS_FCHOWNAT: i64 = 260;
682 pub const SYS_MKNODAT: i64 = 259;
683 pub const SYS_SETNS: i64 = 308;
684 pub const SYS_UNSHARE: i64 = 272;
685 pub const SYS_REBOOT: i64 = 169;
686 pub const SYS_NICE: i64 = 34;
687 pub const SYS_SETPRIORITY: i64 = 141;
688 pub const SYS_GETPRIORITY: i64 = 140;
689 pub const SYS_IOPERM: i64 = 173;
690 pub const SYS_IOPL: i64 = 172;
691 pub const SYS_SWAPON: i64 = 167;
692 pub const SYS_SWAPOFF: i64 = 168;
693 pub const SYS_MOUNT: i64 = 165;
694 pub const SYS_UMOUNT2: i64 = 166;
695 pub const SYS_PIVOT_ROOT: i64 = 155;
696 pub const SYS_SETTIMEOFDAY: i64 = 164;
697 pub const SYS_GETTIMEOFDAY: i64 = 96;
698}
699#[cfg(target_arch = "aarch64")]
700mod sysnr {
701 pub const SYS_READ: i64 = 63;
702 pub const SYS_WRITE: i64 = 64;
703 pub const SYS_CLOSE: i64 = 57;
705 pub const SYS_FSTAT: i64 = 80;
707 pub const SYS_LSEEK: i64 = 62;
708 pub const SYS_MMAP: i64 = 222;
709 pub const SYS_MUNMAP: i64 = 215;
710 pub const SYS_RT_SIGACTION: i64 = 134;
711 pub const SYS_RT_SIGPROCMASK: i64 = 135;
712 pub const SYS_IOCTL: i64 = 29;
713 pub const SYS_SHMGET: i64 = 194;
715 pub const SYS_SHMAT: i64 = 196;
716 pub const SYS_SHMCTL: i64 = 195;
717 pub const SYS_DUP: i64 = 23;
718 pub const SYS_NANOSLEEP: i64 = 101;
719 pub const SYS_SETITIMER: i64 = 103;
720 pub const SYS_SOCKET: i64 = 198;
722 pub const SYS_CONNECT: i64 = 203;
723 pub const SYS_ACCEPT: i64 = 202;
724 pub const SYS_SENDTO: i64 = 206;
725 pub const SYS_RECVFROM: i64 = 207;
726 pub const SYS_SHUTDOWN: i64 = 210;
727 pub const SYS_BIND: i64 = 200;
728 pub const SYS_LISTEN: i64 = 201;
729 pub const SYS_GETSOCKNAME: i64 = 204;
730 pub const SYS_SOCKETPAIR: i64 = 199;
731 pub const SYS_SETSOCKOPT: i64 = 208;
732 pub const SYS_EXECVE: i64 = 221;
733 pub const SYS_WAIT4: i64 = 260;
734 pub const SYS_KILL: i64 = 129;
735 pub const SYS_UNAME: i64 = 160;
736 pub const SYS_SEMGET: i64 = 190;
737 pub const SYS_SEMOP: i64 = 193;
738 pub const SYS_SEMCTL: i64 = 191;
739 pub const SYS_SHMDT: i64 = 197;
740 pub const SYS_MSGGET: i64 = 186;
741 pub const SYS_MSGSND: i64 = 189;
742 pub const SYS_MSGRCV: i64 = 188;
743 pub const SYS_MSGCTL: i64 = 187;
744 pub const SYS_FCNTL: i64 = 25;
745 pub const SYS_FSYNC: i64 = 82;
746 pub const SYS_TRUNCATE: i64 = 45;
747 pub const SYS_FTRUNCATE: i64 = 46;
748 pub const SYS_GETCWD: i64 = 17;
749 pub const SYS_CHDIR: i64 = 49;
750 pub const SYS_FCHMOD: i64 = 52;
752 pub const SYS_UMASK: i64 = 166;
753 pub const SYS_GETRLIMIT: i64 = 163;
754 pub const SYS_SETUID: i64 = 146;
755 pub const SYS_SETGID: i64 = 144;
756 pub const SYS_SETPGID: i64 = 154;
757 pub const SYS_GETGROUPS: i64 = 158;
758 pub const SYS_GETPGID: i64 = 155;
759 pub const SYS_GETSID: i64 = 156;
760 pub const SYS_RT_SIGPENDING: i64 = 136;
761 pub const SYS_RT_SIGTIMEDWAIT: i64 = 137;
762 pub const SYS_RT_SIGSUSPEND: i64 = 133;
763 pub const SYS_SIGALTSTACK: i64 = 132;
764 pub const SYS_SETRLIMIT: i64 = 164;
765 pub const SYS_SETHOSTNAME: i64 = 161;
766 pub const SYS_FUTEX: i64 = 98;
767 pub const SYS_CLOCK_GETTIME: i64 = 113;
768 pub const SYS_CLOCK_GETRES: i64 = 114;
769 pub const SYS_CLOCK_NANOSLEEP: i64 = 115;
770 pub const SYS_EXIT_GROUP: i64 = 94;
771 pub const SYS_TGKILL: i64 = 131;
772 pub const SYS_MKDIRAT: i64 = 34;
773 pub const SYS_NEWFSTATAT: i64 = 79;
774 pub const SYS_UNLINKAT: i64 = 35;
775 pub const SYS_LINKAT: i64 = 37;
776 pub const SYS_SYMLINKAT: i64 = 36;
777 pub const SYS_READLINKAT: i64 = 78;
778 pub const SYS_FCHMODAT: i64 = 53;
779 pub const SYS_SET_ROBUST_LIST: i64 = 99;
780 pub const SYS_UTIMENSAT: i64 = 88;
781 pub const SYS_OPENAT: i64 = 56;
782 pub const SYS_FACCESSAT: i64 = 48;
783 pub const SYS_DUP3: i64 = 24;
784 pub const SYS_PIPE2: i64 = 59;
785 pub const SYS_SYNCFS: i64 = 267;
786 pub const SYS_RENAMEAT2: i64 = 276;
787 pub const SYS_STATFS: i64 = 43;
788 pub const SYS_FSTATFS: i64 = 44;
789 pub const SYS_FDATASYNC: i64 = 83;
790 pub const SYS_GETPID: i64 = 172;
791 pub const SYS_EXIT: i64 = 93;
792 pub const SYS_GETPPID: i64 = 173;
793 pub const SYS_SETSID: i64 = 157;
794 pub const SYS_SYNC: i64 = 81;
795 pub const SYS_GETUID: i64 = 174;
796 pub const SYS_GETGID: i64 = 176;
797 pub const SYS_GETEUID: i64 = 175;
798 pub const SYS_GETEGID: i64 = 177;
799 pub const SYS_GETTID: i64 = 178;
800 pub const SYS_CLOCK_SETTIME: i64 = 112;
801 pub const SYS_CLONE: i64 = 220;
802 pub const SYS_PPOLL: i64 = 73;
803 pub const SYS_PREAD64: i64 = 67;
804 pub const SYS_MREMAP: i64 = 216;
805 pub const SYS_SYSINFO: i64 = 179;
806 pub const SYS_MEMBARRIER: i64 = 283;
807 pub const SYS_VHANGUP: i64 = 58;
808 pub const SYS_VMSPLICE: i64 = 75;
809 pub const SYS_GETTIMEOFDAY: i64 = 169;
810 pub const SYS_SETTIMEOFDAY: i64 = 170;
811 pub const SYS_ADJTIMEX: i64 = 171;
812 pub const SYS_EPOLL_CREATE1: i64 = 20;
813 pub const SYS_EPOLL_CTL: i64 = 21;
814 pub const SYS_EPOLL_WAIT: i64 = 22;
815 pub const SYS_EPOLL_PWAIT: i64 = 22;
816 pub const SYS_EVENTFD2: i64 = 19;
817 pub const SYS_SIGNALFD4: i64 = 74;
818 pub const SYS_TIMERFD_CREATE: i64 = 85;
819 pub const SYS_TIMERFD_SETTIME: i64 = 86;
820 pub const SYS_TIMERFD_GETTIME: i64 = 87;
821 pub const SYS_ACCEPT4: i64 = 242;
822 pub const SYS_ACCT: i64 = 89;
823 pub const SYS_CAPGET: i64 = 90;
824 pub const SYS_CAPSET: i64 = 91;
825 pub const SYS_CHROOT: i64 = 51;
826 pub const SYS_COPY_FILE_RANGE: i64 = 285;
827 pub const SYS_DELETE_MODULE: i64 = 106;
828 pub const SYS_FALLOCATE: i64 = 47;
829 pub const SYS_FCHDIR: i64 = 50;
830 pub const SYS_FCHOWN: i64 = 55;
831 pub const SYS_FCHOWNAT: i64 = 54;
832 pub const SYS_FLOCK: i64 = 32;
833 pub const SYS_GETDENTS64: i64 = 61;
834 pub const SYS_GETPRIORITY: i64 = 141;
835 pub const SYS_GETRESGID: i64 = 150;
836 pub const SYS_GETRESUID: i64 = 148;
837 pub const SYS_INIT_MODULE: i64 = 105;
838 pub const SYS_MKNODAT: i64 = 33;
839 pub const SYS_MOUNT: i64 = 40;
840 pub const SYS_MPROTECT: i64 = 226;
841 pub const SYS_PIVOT_ROOT: i64 = 41;
842 pub const SYS_PRCTL: i64 = 167;
843 pub const SYS_PSELECT6: i64 = 72;
844 pub const SYS_REBOOT: i64 = 142;
845 pub const SYS_RECVMSG: i64 = 212;
846 pub const SYS_SENDMSG: i64 = 211;
847 pub const SYS_SETGROUPS: i64 = 159;
848 pub const SYS_SETNS: i64 = 268;
849 pub const SYS_SETPRIORITY: i64 = 140;
850 pub const SYS_SETRESGID: i64 = 149;
851 pub const SYS_SETRESUID: i64 = 147;
852 pub const SYS_SWAPOFF: i64 = 225;
853 pub const SYS_SWAPON: i64 = 224;
854 pub const SYS_UMOUNT2: i64 = 39;
855 pub const SYS_UNSHARE: i64 = 97;
856}
857#[cfg(target_arch = "riscv64")]
859mod sysnr {
860 pub const SYS_READ: i64 = 63;
861 pub const SYS_WRITE: i64 = 64;
862 pub const SYS_CLOSE: i64 = 57;
863 pub const SYS_FSTAT: i64 = 80;
864 pub const SYS_LSEEK: i64 = 62;
865 pub const SYS_MMAP: i64 = 222;
866 pub const SYS_MUNMAP: i64 = 215;
867 pub const SYS_RT_SIGACTION: i64 = 134;
868 pub const SYS_RT_SIGPROCMASK: i64 = 135;
869 pub const SYS_IOCTL: i64 = 29;
870 pub const SYS_SHMGET: i64 = 194;
871 pub const SYS_SHMAT: i64 = 196;
872 pub const SYS_SHMCTL: i64 = 195;
873 pub const SYS_DUP: i64 = 23;
874 pub const SYS_NANOSLEEP: i64 = 101;
875 pub const SYS_SETITIMER: i64 = 103;
876 pub const SYS_SOCKET: i64 = 198;
877 pub const SYS_CONNECT: i64 = 203;
878 pub const SYS_ACCEPT: i64 = 202;
879 pub const SYS_SENDTO: i64 = 206;
880 pub const SYS_RECVFROM: i64 = 207;
881 pub const SYS_SHUTDOWN: i64 = 210;
882 pub const SYS_BIND: i64 = 200;
883 pub const SYS_LISTEN: i64 = 201;
884 pub const SYS_GETSOCKNAME: i64 = 204;
885 pub const SYS_SOCKETPAIR: i64 = 199;
886 pub const SYS_SETSOCKOPT: i64 = 208;
887 pub const SYS_EXECVE: i64 = 221;
888 pub const SYS_WAIT4: i64 = 260;
889 pub const SYS_KILL: i64 = 129;
890 pub const SYS_UNAME: i64 = 160;
891 pub const SYS_SEMGET: i64 = 190;
892 pub const SYS_SEMOP: i64 = 193;
893 pub const SYS_SEMCTL: i64 = 191;
894 pub const SYS_SHMDT: i64 = 197;
895 pub const SYS_MSGGET: i64 = 186;
896 pub const SYS_MSGSND: i64 = 189;
897 pub const SYS_MSGRCV: i64 = 188;
898 pub const SYS_MSGCTL: i64 = 187;
899 pub const SYS_FCNTL: i64 = 25;
900 pub const SYS_FSYNC: i64 = 82;
901 pub const SYS_TRUNCATE: i64 = 45;
902 pub const SYS_FTRUNCATE: i64 = 46;
903 pub const SYS_GETCWD: i64 = 17;
904 pub const SYS_CHDIR: i64 = 49;
905 pub const SYS_FCHMOD: i64 = 52;
906 pub const SYS_UMASK: i64 = 166;
907 pub const SYS_GETRLIMIT: i64 = 163;
908 pub const SYS_SETUID: i64 = 146;
909 pub const SYS_SETGID: i64 = 144;
910 pub const SYS_SETPGID: i64 = 154;
911 pub const SYS_GETGROUPS: i64 = 158;
912 pub const SYS_GETPGID: i64 = 155;
913 pub const SYS_GETSID: i64 = 156;
914 pub const SYS_RT_SIGPENDING: i64 = 136;
915 pub const SYS_RT_SIGTIMEDWAIT: i64 = 137;
916 pub const SYS_RT_SIGSUSPEND: i64 = 133;
917 pub const SYS_SIGALTSTACK: i64 = 132;
918 pub const SYS_SETRLIMIT: i64 = 164;
919 pub const SYS_SETHOSTNAME: i64 = 161;
920 pub const SYS_FUTEX: i64 = 98;
921 pub const SYS_CLOCK_GETTIME: i64 = 113;
922 pub const SYS_CLOCK_GETRES: i64 = 114;
923 pub const SYS_CLOCK_NANOSLEEP: i64 = 115;
924 pub const SYS_EXIT_GROUP: i64 = 94;
925 pub const SYS_TGKILL: i64 = 131;
926 pub const SYS_MKDIRAT: i64 = 34;
927 pub const SYS_NEWFSTATAT: i64 = 79;
928 pub const SYS_UNLINKAT: i64 = 35;
929 pub const SYS_LINKAT: i64 = 37;
930 pub const SYS_SYMLINKAT: i64 = 36;
931 pub const SYS_READLINKAT: i64 = 78;
932 pub const SYS_FCHMODAT: i64 = 53;
933 pub const SYS_SET_ROBUST_LIST: i64 = 99;
934 pub const SYS_UTIMENSAT: i64 = 88;
935 pub const SYS_OPENAT: i64 = 56;
936 pub const SYS_FACCESSAT: i64 = 48;
937 pub const SYS_DUP3: i64 = 24;
938 pub const SYS_PIPE2: i64 = 59;
939 pub const SYS_SYNCFS: i64 = 267;
940 pub const SYS_RENAMEAT2: i64 = 276;
941 pub const SYS_STATFS: i64 = 43;
942 pub const SYS_FSTATFS: i64 = 44;
943 pub const SYS_FDATASYNC: i64 = 83;
944 pub const SYS_GETPID: i64 = 172;
945 pub const SYS_EXIT: i64 = 93;
946 pub const SYS_GETPPID: i64 = 173;
947 pub const SYS_SETSID: i64 = 157;
948 pub const SYS_SYNC: i64 = 81;
949 pub const SYS_GETUID: i64 = 174;
950 pub const SYS_GETGID: i64 = 176;
951 pub const SYS_GETEUID: i64 = 175;
952 pub const SYS_GETEGID: i64 = 177;
953 pub const SYS_GETTID: i64 = 178;
954 pub const SYS_CLOCK_SETTIME: i64 = 112;
955 pub const SYS_CLONE: i64 = 220;
956 pub const SYS_PPOLL: i64 = 73;
957 pub const SYS_PREAD64: i64 = 67;
958 pub const SYS_MREMAP: i64 = 216;
959 pub const SYS_SYSINFO: i64 = 179;
960 pub const SYS_MEMBARRIER: i64 = 283;
961 pub const SYS_VHANGUP: i64 = 58;
962 pub const SYS_VMSPLICE: i64 = 75;
963 pub const SYS_GETTIMEOFDAY: i64 = 169;
964 pub const SYS_SETTIMEOFDAY: i64 = 170;
965 pub const SYS_ADJTIMEX: i64 = 171;
966 pub const SYS_EPOLL_CREATE1: i64 = 20;
967 pub const SYS_EPOLL_CTL: i64 = 21;
968 pub const SYS_EPOLL_WAIT: i64 = 22;
969 pub const SYS_EPOLL_PWAIT: i64 = 22;
970 pub const SYS_EVENTFD2: i64 = 19;
971 pub const SYS_SIGNALFD4: i64 = 74;
972 pub const SYS_TIMERFD_CREATE: i64 = 85;
973 pub const SYS_TIMERFD_SETTIME: i64 = 86;
974 pub const SYS_TIMERFD_GETTIME: i64 = 87;
975 pub const SYS_ACCEPT4: i64 = 242;
976 pub const SYS_ACCT: i64 = 89;
977 pub const SYS_CAPGET: i64 = 90;
978 pub const SYS_CAPSET: i64 = 91;
979 pub const SYS_CHROOT: i64 = 51;
980 pub const SYS_COPY_FILE_RANGE: i64 = 285;
981 pub const SYS_DELETE_MODULE: i64 = 106;
982 pub const SYS_FALLOCATE: i64 = 47;
983 pub const SYS_FCHDIR: i64 = 50;
984 pub const SYS_FCHOWN: i64 = 55;
985 pub const SYS_FCHOWNAT: i64 = 54;
986 pub const SYS_FLOCK: i64 = 32;
987 pub const SYS_GETDENTS64: i64 = 61;
988 pub const SYS_GETPRIORITY: i64 = 141;
989 pub const SYS_GETRESGID: i64 = 150;
990 pub const SYS_GETRESUID: i64 = 148;
991 pub const SYS_INIT_MODULE: i64 = 105;
992 pub const SYS_MKNODAT: i64 = 33;
993 pub const SYS_MOUNT: i64 = 40;
994 pub const SYS_MPROTECT: i64 = 226;
995 pub const SYS_PIVOT_ROOT: i64 = 41;
996 pub const SYS_PRCTL: i64 = 167;
997 pub const SYS_PSELECT6: i64 = 72;
998 pub const SYS_REBOOT: i64 = 142;
999 pub const SYS_RECVMSG: i64 = 212;
1000 pub const SYS_SENDMSG: i64 = 211;
1001 pub const SYS_SETGROUPS: i64 = 159;
1002 pub const SYS_SETNS: i64 = 268;
1003 pub const SYS_SETPRIORITY: i64 = 140;
1004 pub const SYS_SETRESGID: i64 = 149;
1005 pub const SYS_SETRESUID: i64 = 147;
1006 pub const SYS_SWAPOFF: i64 = 225;
1007 pub const SYS_SWAPON: i64 = 224;
1008 pub const SYS_UMOUNT2: i64 = 39;
1009 pub const SYS_UNSHARE: i64 = 97;
1010}
1011pub use sysnr::*;
1012
1013#[inline]
1018unsafe fn sys_write(fd: i64, buf: *const u8, count: usize) -> i64 {
1019 <Arch as Syscalls>::syscall3(SYS_WRITE, fd as i64, buf as i64, count as i64)
1020}
1021
1022#[inline]
1023unsafe fn sys_read(fd: i64, buf: *mut u8, count: usize) -> i64 {
1024 <Arch as Syscalls>::syscall3(SYS_READ, fd as i64, buf as i64, count as i64)
1025}
1026
1027#[inline]
1028unsafe fn sys_open(path: *const u8, flags: i64, mode: i64) -> i64 {
1029 <Arch as Syscalls>::syscall4(SYS_OPENAT, AT_FDCWD as i64, path as i64, flags as i64, mode as i64)
1030}
1031
1032#[inline]
1033unsafe fn sys_close(fd: i64) -> i64 {
1034 <Arch as Syscalls>::syscall1(SYS_CLOSE, fd as i64)
1035}
1036
1037#[inline]
1038unsafe fn sys_lseek(fd: i64, offset: i64, whence: i64) -> i64 {
1039 <Arch as Syscalls>::syscall3(SYS_LSEEK, fd as i64, offset as i64, whence as i64)
1040}
1041
1042unsafe fn sys_mmap(
1043 addr: *mut u8,
1044 length: usize,
1045 prot: i32,
1046 flags: i32,
1047 fd: i32,
1048 offset: i64,
1049) -> *mut u8 {
1050 let result = <Arch as Syscalls>::syscall6(SYS_MMAP, addr as i64, length as i64, prot as i64, flags as i64, fd as i64, offset);
1051 if result < 0 && result > -4096 {
1052 ERRNO!() = (-result) as c_int;
1053 return MMAP_FAILED;
1054 }
1055 result as *mut u8
1056}
1057
1058unsafe fn sys_munmap(addr: *mut u8, length: usize) -> i64 {
1059 <Arch as Syscalls>::syscall2(SYS_MUNMAP, addr as i64, length as i64)
1060}
1061
1062#[no_mangle]
1069pub unsafe extern "C" fn bcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int {
1070 memcmp(s1, s2, n)
1071}
1072
1073#[no_mangle]
1076pub unsafe extern "C" fn strncmp(s1: *const u8, s2: *const u8, n: usize) -> c_int {
1077 let mut i = 0;
1078 while i < n {
1079 let a = *s1.add(i);
1080 let b = *s2.add(i);
1081 if a != b {
1082 return a as c_int - b as c_int;
1083 }
1084 if a == 0 {
1085 return 0;
1086 }
1087 i += 1;
1088 }
1089 0
1090}
1091
1092#[no_mangle]
1093pub unsafe extern "C" fn strcpy(dst: *mut u8, src: *const u8) -> *mut u8 {
1094 let mut i = 0;
1095 loop {
1096 let c = *src.add(i);
1097 *dst.add(i) = c;
1098 if c == 0 {
1099 break;
1100 }
1101 i += 1;
1102 }
1103 dst
1104}
1105
1106#[no_mangle]
1107pub unsafe extern "C" fn strncpy(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 {
1108 let mut i = 0;
1109 while i < n && *src.add(i) != 0 {
1110 *dst.add(i) = *src.add(i);
1111 i += 1;
1112 }
1113 while i < n {
1114 *dst.add(i) = 0;
1115 i += 1;
1116 }
1117 dst
1118}
1119
1120#[no_mangle]
1121pub unsafe extern "C" fn strcat(dst: *mut u8, src: *const u8) -> *mut u8 {
1122 let mut i = 0;
1123 while *dst.add(i) != 0 {
1124 i += 1;
1125 }
1126 let mut j = 0;
1127 loop {
1128 let c = *src.add(j);
1129 *dst.add(i + j) = c;
1130 if c == 0 {
1131 break;
1132 }
1133 j += 1;
1134 }
1135 dst
1136}
1137
1138#[no_mangle]
1139pub unsafe extern "C" fn strncat(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 {
1140 let mut i = 0;
1141 while *dst.add(i) != 0 {
1142 i += 1;
1143 }
1144 let mut j = 0;
1145 while j < n && *src.add(j) != 0 {
1146 *dst.add(i + j) = *src.add(j);
1147 j += 1;
1148 }
1149 *dst.add(i + j) = 0;
1150 dst
1151}
1152
1153#[no_mangle]
1154pub unsafe extern "C" fn strlcpy(dst: *mut u8, src: *const u8, n: usize) -> usize {
1155 let l = strlen(src as *const c_char);
1156 if n > 0 {
1157 let c = if l < n { l } else { n - 1 };
1158 core::ptr::copy_nonoverlapping(src, dst, c);
1159 *dst.add(c) = 0;
1160 }
1161 l
1162}
1163
1164#[no_mangle]
1165pub unsafe extern "C" fn strlcat(dst: *mut u8, src: *const u8, n: usize) -> usize {
1166 let dl = strlen(dst as *const c_char);
1167 let sl = strlen(src as *const c_char);
1168 if dl >= n { return n + sl; }
1169 let c = if sl < n - dl { sl } else { n - dl - 1 };
1170 core::ptr::copy_nonoverlapping(src, dst.add(dl), c);
1171 *dst.add(dl + c) = 0;
1172 dl + sl
1173}
1174
1175#[no_mangle]
1176pub unsafe extern "C" fn bcopy(src: *const c_void, dst: *mut c_void, n: usize) {
1177 core::ptr::copy(src as *const u8, dst as *mut u8, n);
1178}
1179
1180#[no_mangle]
1181pub unsafe extern "C" fn bzero(s: *mut c_void, n: usize) {
1182 core::ptr::write_bytes(s as *mut u8, 0, n);
1183}
1184
1185#[no_mangle]
1186pub unsafe extern "C" fn strndup(s: *const c_char, n: usize) -> *mut c_char {
1187 let mut len = 0;
1188 while len < n && *s.add(len) != 0 {
1189 len += 1;
1190 }
1191 let p = malloc(len + 1) as *mut c_char;
1192 if p.is_null() {
1193 return core::ptr::null_mut();
1194 }
1195 core::ptr::copy_nonoverlapping(s, p, len);
1196 *p.add(len) = 0;
1197 p
1198}
1199
1200#[no_mangle]
1201pub unsafe extern "C" fn strchr(s: *const u8, c: c_int) -> *mut u8 {
1202 let target = c as u8;
1203 let mut i = 0;
1204 loop {
1205 let ch = *s.add(i);
1206 if ch == target {
1207 return s.add(i) as *mut u8;
1208 }
1209 if ch == 0 {
1210 return null_mut();
1211 }
1212 i += 1;
1213 }
1214}
1215
1216#[no_mangle]
1217pub unsafe extern "C" fn strrchr(s: *const u8, c: c_int) -> *mut u8 {
1218 let target = c as u8;
1219 let mut i = 0;
1220 let mut last: *mut u8 = null_mut();
1221 loop {
1222 let ch = *s.add(i);
1223 if ch == target {
1224 last = s.add(i) as *mut u8;
1225 }
1226 if ch == 0 {
1227 return last;
1228 }
1229 i += 1;
1230 }
1231}
1232
1233#[no_mangle]
1234pub unsafe extern "C" fn strnlen(s: *const u8, maxlen: usize) -> usize {
1235 let mut i = 0;
1236 while i < maxlen && *s.add(i) != 0 {
1237 i += 1;
1238 }
1239 i
1240}
1241
1242#[no_mangle]
1243pub unsafe extern "C" fn strcspn(s: *const u8, reject: *const u8) -> usize {
1244 let mut i = 0;
1245 loop {
1246 let c = *s.add(i);
1247 if c == 0 {
1248 return i;
1249 }
1250 let mut j = 0;
1251 loop {
1252 let r = *reject.add(j);
1253 if r == 0 {
1254 break;
1255 }
1256 if c == r {
1257 return i;
1258 }
1259 j += 1;
1260 }
1261 i += 1;
1262 }
1263}
1264
1265#[no_mangle]
1266pub unsafe extern "C" fn strspn(s: *const u8, accept: *const u8) -> usize {
1267 let mut i = 0;
1268 loop {
1269 let c = *s.add(i);
1270 if c == 0 {
1271 return i;
1272 }
1273 let mut found = false;
1274 let mut j = 0;
1275 loop {
1276 let a = *accept.add(j);
1277 if a == 0 {
1278 break;
1279 }
1280 if c == a {
1281 found = true;
1282 break;
1283 }
1284 j += 1;
1285 }
1286 if !found {
1287 return i;
1288 }
1289 i += 1;
1290 }
1291}
1292
1293#[no_mangle]
1294pub unsafe extern "C" fn strpbrk(s: *const u8, accept: *const u8) -> *mut u8 {
1295 let mut i = 0;
1296 loop {
1297 let c = *s.add(i);
1298 if c == 0 {
1299 return null_mut();
1300 }
1301 let mut j = 0;
1302 loop {
1303 let a = *accept.add(j);
1304 if a == 0 {
1305 break;
1306 }
1307 if c == a {
1308 return s.add(i) as *mut u8;
1309 }
1310 j += 1;
1311 }
1312 i += 1;
1313 }
1314}
1315
1316#[no_mangle]
1317pub unsafe extern "C" fn strstr(haystack: *const u8, needle: *const u8) -> *mut u8 {
1318 if *needle == 0 {
1319 return haystack as *mut u8;
1320 }
1321 let mut i = 0;
1322 loop {
1323 let h = *haystack.add(i);
1324 if h == 0 {
1325 return null_mut();
1326 }
1327 if h == *needle {
1328 let mut j = 0;
1329 loop {
1330 let n = *needle.add(j);
1331 if n == 0 {
1332 return haystack.add(i) as *mut u8;
1333 }
1334 if *haystack.add(i + j) != n {
1335 break;
1336 }
1337 j += 1;
1338 }
1339 }
1340 i += 1;
1341 }
1342}
1343
1344#[no_mangle]
1345pub unsafe extern "C" fn memchr(s: *const u8, c: c_int, n: usize) -> *mut u8 {
1346 let target = c as u8;
1347 let mut i = 0;
1348 while i < n {
1349 if *s.add(i) == target {
1350 return s.add(i) as *mut u8;
1351 }
1352 i += 1;
1353 }
1354 null_mut()
1355}
1356
1357#[no_mangle]
1358pub unsafe extern "C" fn memrchr(s: *const u8, c: c_int, n: usize) -> *mut u8 {
1359 let target = c as u8;
1360 let mut i = n;
1361 while i > 0 {
1362 i -= 1;
1363 if *s.add(i) == target {
1364 return s.add(i) as *mut u8;
1365 }
1366 }
1367 null_mut()
1368}
1369
1370#[no_mangle]
1371pub unsafe extern "C" fn memmem(
1372 haystack: *const c_void, haystacklen: usize,
1373 needle: *const c_void, needlelen: usize,
1374) -> *mut c_void {
1375 if needlelen == 0 { return haystack as *mut c_void; }
1376 if haystacklen < needlelen { return null_mut(); }
1377 let h = haystack as *const u8;
1378 let n = needle as *const u8;
1379 let last = haystacklen - needlelen;
1380 for i in 0..=last {
1381 if *h.add(i) == *n && memcmp(h.add(i) as *const c_void, n as *const c_void, needlelen) == 0 {
1382 return h.add(i) as *mut c_void;
1383 }
1384 }
1385 null_mut()
1386}
1387
1388#[no_mangle]
1389pub unsafe extern "C" fn strtok(s: *mut u8, delim: *const u8) -> *mut u8 {
1390 static mut STATE: *mut u8 = core::ptr::null_mut();
1391 let mut p = if s.is_null() { STATE } else { s };
1392 if p.is_null() {
1393 return core::ptr::null_mut();
1394 }
1395 loop {
1396 let c = *p;
1397 if c == 0 {
1398 STATE = core::ptr::null_mut();
1399 return core::ptr::null_mut();
1400 }
1401 let mut is_delim = false;
1402 let mut i = 0;
1403 loop {
1404 let d = *delim.add(i);
1405 if d == 0 {
1406 break;
1407 }
1408 if c == d {
1409 is_delim = true;
1410 break;
1411 }
1412 i += 1;
1413 }
1414 if !is_delim {
1415 break;
1416 }
1417 p = p.add(1);
1418 }
1419 let start = p;
1420 loop {
1421 let c = *p;
1422 if c == 0 {
1423 STATE = core::ptr::null_mut();
1424 return start;
1425 }
1426 let mut is_delim = false;
1427 let mut i = 0;
1428 loop {
1429 let d = *delim.add(i);
1430 if d == 0 {
1431 break;
1432 }
1433 if c == d {
1434 is_delim = true;
1435 break;
1436 }
1437 i += 1;
1438 }
1439 if is_delim {
1440 *p = 0;
1441 STATE = p.add(1);
1442 return start;
1443 }
1444 p = p.add(1);
1445 }
1446}
1447
1448type SizeT = usize;
1453type SSizeT = isize;
1454type mode_t = c_uint;
1455type TimeT = c_long;
1456type ClockT = c_long;
1457type wchar_t = c_int;
1458type wint_t = c_uint;
1459type wctype_t = *const c_int;
1460type wctrans_t = *const c_int;
1461
1462const WEOF: wint_t = 0xffffffff;
1463
1464#[repr(C)]
1465pub struct tm {
1466 pub tm_sec: c_int,
1467 pub tm_min: c_int,
1468 pub tm_hour: c_int,
1469 pub tm_mday: c_int,
1470 pub tm_mon: c_int,
1471 pub tm_year: c_int,
1472 pub tm_wday: c_int,
1473 pub tm_yday: c_int,
1474 pub tm_isdst: c_int,
1475 pub tm_gmtoff: c_long,
1476 pub tm_zone: *const c_char,
1477}
1478
1479#[repr(C)]
1480pub struct timeval {
1481 pub tv_sec: TimeT,
1482 pub tv_usec: c_long,
1483}
1484
1485#[repr(C)]
1486pub struct Timeb {
1487 pub time: TimeT,
1488 pub millitm: u16,
1489 pub timezone: i16,
1490 pub dstflag: u16,
1491}
1492
1493const CT_UPPER: u8 = 1 << 0;
1498const CT_LOWER: u8 = 1 << 1;
1499const CT_DIGIT: u8 = 1 << 2;
1500const CT_SPACE: u8 = 1 << 3;
1501const CT_PUNCT: u8 = 1 << 4;
1502const CT_CNTRL: u8 = 1 << 5;
1503const CT_BLANK: u8 = 1 << 6;
1504const CT_XDIGIT: u8 = 1 << 7;
1505
1506const CT_TABLE: [u8; 128] = {
1507 let mut t = [0u8; 128];
1508 let mut i = 0;
1509 while i < 128 {
1510 let c = i as u8;
1511 let mut flags = 0u8;
1512 if c >= b'A' && c <= b'Z' {
1513 flags |= CT_UPPER;
1514 }
1515 if c >= b'a' && c <= b'z' {
1516 flags |= CT_LOWER;
1517 }
1518 if c >= b'0' && c <= b'9' {
1519 flags |= CT_DIGIT;
1520 }
1521 if c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == b'\x0c' || c == b'\x0b' {
1522 flags |= CT_SPACE;
1523 }
1524 if (c >= b'!' && c <= b'/')
1525 || (c >= b':' && c <= b'@')
1526 || (c >= b'[' && c <= b'`')
1527 || (c >= b'{' && c <= b'~')
1528 {
1529 flags |= CT_PUNCT;
1530 }
1531 if c < 0x20 || c == 0x7f {
1532 flags |= CT_CNTRL;
1533 }
1534 if c == b' ' || c == b'\t' {
1535 flags |= CT_BLANK;
1536 }
1537 if (c >= b'0' && c <= b'9') || (c >= b'A' && c <= b'F') || (c >= b'a' && c <= b'f') {
1538 flags |= CT_XDIGIT;
1539 }
1540 t[i] = flags;
1541 i += 1;
1542 }
1543 t
1544};
1545
1546#[inline]
1547fn ct_flags(c: c_int) -> u8 {
1548 if c < 0 || c > 127 {
1549 0
1550 } else {
1551 CT_TABLE[c as usize]
1552 }
1553}
1554
1555#[no_mangle]
1556pub extern "C" fn isalnum(c: c_int) -> c_int {
1557 (ct_flags(c) & (CT_UPPER | CT_LOWER | CT_DIGIT) != 0) as c_int
1558}
1559
1560#[no_mangle]
1561pub extern "C" fn isalpha(c: c_int) -> c_int {
1562 (ct_flags(c) & (CT_UPPER | CT_LOWER) != 0) as c_int
1563}
1564
1565#[no_mangle]
1566pub extern "C" fn isascii(c: c_int) -> c_int {
1567 ((c as u32) <= 127) as c_int
1568}
1569
1570#[no_mangle]
1571pub extern "C" fn isblank(c: c_int) -> c_int {
1572 (ct_flags(c) & CT_BLANK != 0) as c_int
1573}
1574
1575#[no_mangle]
1576pub extern "C" fn iscntrl(c: c_int) -> c_int {
1577 (ct_flags(c) & CT_CNTRL != 0) as c_int
1578}
1579
1580#[no_mangle]
1581pub extern "C" fn isdigit(c: c_int) -> c_int {
1582 (ct_flags(c) & CT_DIGIT != 0) as c_int
1583}
1584
1585#[no_mangle]
1586pub extern "C" fn isgraph(c: c_int) -> c_int {
1587 (ct_flags(c) & (CT_UPPER | CT_LOWER | CT_DIGIT | CT_PUNCT) != 0) as c_int
1588}
1589
1590#[no_mangle]
1591pub extern "C" fn islower(c: c_int) -> c_int {
1592 (ct_flags(c) & CT_LOWER != 0) as c_int
1593}
1594
1595#[no_mangle]
1596pub extern "C" fn isprint(c: c_int) -> c_int {
1597 let flags = ct_flags(c);
1598 (flags & (CT_UPPER | CT_LOWER | CT_DIGIT | CT_PUNCT | CT_BLANK) != 0) as c_int
1599}
1600
1601#[no_mangle]
1602pub extern "C" fn ispunct(c: c_int) -> c_int {
1603 (ct_flags(c) & CT_PUNCT != 0) as c_int
1604}
1605
1606#[no_mangle]
1607pub extern "C" fn isspace(c: c_int) -> c_int {
1608 (ct_flags(c) & CT_SPACE != 0) as c_int
1609}
1610
1611#[no_mangle]
1612pub extern "C" fn isupper(c: c_int) -> c_int {
1613 (ct_flags(c) & CT_UPPER != 0) as c_int
1614}
1615
1616#[no_mangle]
1617pub extern "C" fn isxdigit(c: c_int) -> c_int {
1618 (ct_flags(c) & CT_XDIGIT != 0) as c_int
1619}
1620
1621#[no_mangle]
1622pub extern "C" fn tolower(c: c_int) -> c_int {
1623 if (ct_flags(c) & CT_UPPER) != 0 {
1624 c + (b'a' as c_int - b'A' as c_int)
1625 } else {
1626 c
1627 }
1628}
1629
1630#[no_mangle]
1631pub extern "C" fn toupper(c: c_int) -> c_int {
1632 if (ct_flags(c) & CT_LOWER) != 0 {
1633 c - (b'a' as c_int - b'A' as c_int)
1634 } else {
1635 c
1636 }
1637}
1638
1639unsafe fn parse_digit(c: u8, base: c_int) -> Option<u8> {
1644 if c == 0 { return None; }
1645 let d = if c >= b'0' && c <= b'9' {
1646 c - b'0'
1647 } else if c >= b'a' && c <= b'z' {
1648 c - b'a' + 10
1649 } else if c >= b'A' && c <= b'Z' {
1650 c - b'A' + 10
1651 } else {
1652 return None;
1653 };
1654 if (d as c_int) < base {
1655 Some(d)
1656 } else {
1657 None
1658 }
1659}
1660
1661unsafe fn parse_prefix(s: *const u8, base: *mut c_int) -> *const u8 {
1662 let mut p = s;
1663 if *base == 0 {
1664 if *p == b'0' {
1665 if (*p.add(1) == b'x' || *p.add(1) == b'X') && parse_digit(*p.add(2), 16).is_some() {
1666 *base = 16;
1667 p = p.add(2);
1668 } else {
1669 *base = 8;
1670 }
1671 } else {
1672 *base = 10;
1673 }
1674 } else if *base == 16 {
1675 if *p == b'0' && (*p.add(1) == b'x' || *p.add(1) == b'X') && parse_digit(*p.add(2), 16).is_some() {
1676 p = p.add(2);
1677 }
1678 }
1679 p
1680}
1681
1682unsafe fn strtox(
1683 s: *const c_char,
1684 endptr: *mut *mut c_char,
1685 mut base: c_int,
1686 pos_limit: u64,
1687 neg_limit: u64,
1688) -> (u64, bool, bool) {
1689 let s0 = s as *const u8;
1690 let mut p = s0;
1691 while isspace(*p as c_int) != 0 {
1692 p = p.add(1);
1693 }
1694
1695 if base < 0 || base == 1 || base > 36 {
1696 if !endptr.is_null() {
1697 *endptr = s as *mut c_char;
1698 }
1699 ERRNO!() = EINVAL;
1700 return (0, false, false);
1701 }
1702
1703 let mut neg = false;
1704 match *p {
1705 b'-' => { neg = true; p = p.add(1); }
1706 b'+' => p = p.add(1),
1707 _ => {}
1708 }
1709
1710 p = parse_prefix(p, &mut base);
1711
1712 let limit = if neg { neg_limit } else { pos_limit };
1713 let mut val: u64 = 0;
1714 let mut any = false;
1715 while let Some(d) = parse_digit(*p, base) {
1716 any = true;
1717 if val > (limit - d as u64) / base as u64 {
1718 while parse_digit(*p, base).is_some() { p = p.add(1); }
1719 if !endptr.is_null() { *endptr = p as *mut c_char; }
1720 ERRNO!() = ERANGE_VAL;
1721 return (limit, true, neg);
1722 }
1723 val = val * base as u64 + d as u64;
1724 p = p.add(1);
1725 }
1726
1727 if !endptr.is_null() {
1728 *endptr = if any { p as *mut c_char } else { s as *mut c_char };
1729 }
1730 (val, false, neg)
1731}
1732
1733#[no_mangle]
1734pub unsafe extern "C" fn strtol(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_long {
1735 let pos_limit = c_long::MAX as u64;
1736 let neg_limit = pos_limit.wrapping_add(1);
1737 let (val, overflow, neg) = strtox(s, endptr, base, pos_limit, neg_limit);
1738 if overflow {
1739 return if neg { c_long::MIN } else { c_long::MAX };
1740 }
1741 if neg { val.wrapping_neg() as c_long } else { val as c_long }
1742}
1743
1744#[no_mangle]
1745pub unsafe extern "C" fn strtoul(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_ulong {
1746 let limit = c_ulong::MAX as u64;
1747 let (val, overflow, neg) = strtox(s, endptr, base, limit, limit);
1748 if overflow {
1749 return c_ulong::MAX;
1750 }
1751 if neg { val.wrapping_neg() as c_ulong } else { val as c_ulong }
1752}
1753
1754#[no_mangle]
1755pub unsafe extern "C" fn strtoll(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_longlong {
1756 let pos_limit = c_longlong::MAX as u64;
1757 let neg_limit = pos_limit.wrapping_add(1);
1758 let (val, overflow, neg) = strtox(s, endptr, base, pos_limit, neg_limit);
1759 if overflow {
1760 return if neg { c_longlong::MIN } else { c_longlong::MAX };
1761 }
1762 if neg { val.wrapping_neg() as c_longlong } else { val as c_longlong }
1763}
1764
1765#[no_mangle]
1766pub unsafe extern "C" fn strtoull(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_ulonglong {
1767 let limit = c_ulonglong::MAX as u64;
1768 let (val, overflow, neg) = strtox(s, endptr, base, limit, limit);
1769 if overflow {
1770 return c_ulonglong::MAX;
1771 }
1772 if neg { val.wrapping_neg() as c_ulonglong } else { val as c_ulonglong }
1773}
1774
1775#[no_mangle]
1776pub unsafe extern "C" fn atoi(s: *const c_char) -> c_int {
1777 strtol(s, core::ptr::null_mut(), 10) as c_int
1778}
1779
1780#[no_mangle]
1781pub unsafe extern "C" fn atol(s: *const c_char) -> c_long {
1782 strtol(s, core::ptr::null_mut(), 10)
1783}
1784
1785#[no_mangle]
1786pub unsafe extern "C" fn atoll(s: *const c_char) -> c_longlong {
1787 strtoll(s, core::ptr::null_mut(), 10)
1788}
1789
1790#[no_mangle]
1791pub extern "C" fn abs(n: c_int) -> c_int {
1792 if n < 0 {
1793 -n
1794 } else {
1795 n
1796 }
1797}
1798
1799#[no_mangle]
1800pub extern "C" fn labs(n: c_long) -> c_long {
1801 if n < 0 {
1802 -n
1803 } else {
1804 n
1805 }
1806}
1807
1808#[no_mangle]
1809pub extern "C" fn llabs(n: c_longlong) -> c_longlong {
1810 if n < 0 {
1811 -n
1812 } else {
1813 n
1814 }
1815}
1816
1817static mut RAND_STATE: c_uint = 1;
1818
1819#[no_mangle]
1820pub extern "C" fn srand(seed: c_uint) {
1821 unsafe {
1822 RAND_STATE = seed;
1823 }
1824}
1825
1826#[no_mangle]
1827pub extern "C" fn rand() -> c_int {
1828 unsafe {
1829 RAND_STATE = RAND_STATE.wrapping_mul(1103515245).wrapping_add(12345);
1830 ((RAND_STATE >> 16) & 0x7fff) as c_int
1831 }
1832}
1833
1834#[repr(C)]
1839pub struct div_t { pub quot: c_int, pub rem: c_int }
1840#[repr(C)]
1841pub struct ldiv_t { pub quot: c_long, pub rem: c_long }
1842#[repr(C)]
1843pub struct lldiv_t { pub quot: c_longlong, pub rem: c_longlong }
1844
1845#[no_mangle]
1846pub extern "C" fn div(num: c_int, den: c_int) -> div_t {
1847 div_t { quot: num / den, rem: num % den }
1848}
1849
1850#[no_mangle]
1851pub extern "C" fn ldiv(num: c_long, den: c_long) -> ldiv_t {
1852 ldiv_t { quot: num / den, rem: num % den }
1853}
1854
1855#[no_mangle]
1856pub extern "C" fn lldiv(num: c_longlong, den: c_longlong) -> lldiv_t {
1857 lldiv_t { quot: num / den, rem: num % den }
1858}
1859
1860type CmpFn = unsafe extern "C" fn(*const c_void, *const c_void) -> c_int;
1865
1866#[no_mangle]
1867pub unsafe extern "C" fn bsearch(
1868 key: *const c_void,
1869 base: *const c_void,
1870 nel: usize,
1871 width: usize,
1872 cmp: CmpFn,
1873) -> *mut c_void {
1874 let mut base = base as *const u8;
1875 let mut nel = nel;
1876 while nel > 0 {
1877 let trial = base.add(width * (nel / 2));
1878 let sign = cmp(key, trial as *const c_void);
1879 if sign < 0 {
1880 nel /= 2;
1881 } else if sign > 0 {
1882 base = trial.add(width);
1883 nel -= nel / 2 + 1;
1884 } else {
1885 return trial as *mut c_void;
1886 }
1887 }
1888 null_mut()
1889}
1890
1891pub const SA_RESTORER: c_ulong = 0x04000000;
1896
1897pub const SIG_DFL: usize = 0;
1898pub const SIG_IGN: usize = 1;
1899pub const SIG_ERR: usize = !0usize;
1900
1901pub const SIGHUP: c_int = 1;
1902pub const SIGINT: c_int = 2;
1903pub const SIGQUIT: c_int = 3;
1904pub const SIGILL: c_int = 4;
1905pub const SIGTRAP: c_int = 5;
1906pub const SIGABRT: c_int = 6;
1907pub const SIGIOT: c_int = 6;
1908pub const SIGBUS: c_int = 7;
1909pub const SIGFPE: c_int = 8;
1910pub const SIGKILL: c_int = 9;
1911pub const SIGUSR1: c_int = 10;
1912pub const SIGSEGV: c_int = 11;
1913pub const SIGUSR2: c_int = 12;
1914pub const SIGPIPE: c_int = 13;
1915pub const SIGALRM: c_int = 14;
1916pub const SIGTERM: c_int = 15;
1917pub const SIGSTKFLT: c_int = 16;
1918pub const SIGCHLD: c_int = 17;
1919pub const SIGCONT: c_int = 18;
1920pub const SIGSTOP: c_int = 19;
1921pub const SIGTSTP: c_int = 20;
1922pub const SIGTTIN: c_int = 21;
1923pub const SIGTTOU: c_int = 22;
1924pub const SIGURG: c_int = 23;
1925pub const SIGXCPU: c_int = 24;
1926pub const SIGXFSZ: c_int = 25;
1927pub const SIGVTALRM: c_int = 26;
1928pub const SIGPROF: c_int = 27;
1929pub const SIGWINCH: c_int = 28;
1930pub const SIGIO: c_int = 29;
1931pub const SIGPOLL: c_int = 29;
1932pub const SIGPWR: c_int = 30;
1933pub const SIGSYS: c_int = 31;
1934pub const SIGUNUSED: c_int = 31;
1935pub const _NSIG: c_int = 65;
1936
1937pub const SIG_BLOCK: c_int = 0;
1938pub const SIG_UNBLOCK: c_int = 1;
1939pub const SIG_SETMASK: c_int = 2;
1940
1941pub const SA_NOCLDSTOP: c_ulong = 1;
1942pub const SA_NOCLDWAIT: c_ulong = 2;
1943pub const SA_SIGINFO: c_ulong = 4;
1944pub const SA_ONSTACK: c_ulong = 0x08000000;
1945pub const SA_RESTART: c_ulong = 0x10000000;
1946pub const SA_NODEFER: c_ulong = 0x40000000;
1947pub const SA_RESETHAND: c_ulong = 0x80000000;
1948
1949pub const SS_ONSTACK: c_int = 1;
1950pub const SS_DISABLE: c_int = 2;
1951pub const MINSIGSTKSZ: usize = 2048;
1952pub const SIGSTKSZ: usize = 8192;
1953
1954pub const SI_USER: c_int = 0;
1955pub const SI_TKILL: c_int = -6;
1956
1957#[repr(C)]
1958pub struct timespec {
1959 pub tv_sec: c_long,
1960 pub tv_nsec: c_long,
1961}
1962
1963#[repr(C)]
1964pub struct siginfo_t {
1965 pub si_signo: c_int,
1966 pub si_errno: c_int,
1967 pub si_code: c_int,
1968 _pad: [u8; 128 - 3 * core::mem::size_of::<c_int>()],
1970}
1971
1972#[repr(C)]
1973pub struct stack_t {
1974 pub ss_sp: *mut c_void,
1975 pub ss_flags: c_int,
1976 pub ss_size: usize,
1977}
1978
1979#[repr(C)]
1982pub struct KSigAction {
1983 pub sa_handler: usize,
1984 pub sa_flags: c_ulong,
1985 pub sa_restorer: usize,
1986 pub sa_mask: [c_ulong; 1],
1987}
1988
1989#[repr(C)]
1991pub struct sigaction {
1992 pub sa_handler: usize,
1993 pub sa_mask: [u64; 16],
1994 pub sa_flags: c_int,
1995 pub sa_restorer: usize,
1996}
1997
1998pub type SigSetT = c_ulong;
1999
2000#[cfg(target_arch = "x86_64")]
2001core::arch::global_asm!(
2002 ".global sig_restorer",
2003 ".type sig_restorer, @function",
2004 "sig_restorer:",
2005 "mov eax, 15",
2006 "syscall",
2007);
2008
2009#[cfg(target_arch = "aarch64")]
2010core::arch::global_asm!(
2011 ".global sig_restorer",
2012 ".type sig_restorer, @function",
2013 "sig_restorer:",
2014 "mov x8, #139",
2015 "svc #0",
2016);
2017
2018#[cfg(target_arch = "riscv64")]
2019core::arch::global_asm!(
2020 ".global sig_restorer",
2021 ".type sig_restorer, @function",
2022 "sig_restorer:",
2023 "li a7, 139",
2024 "ecall",
2025);
2026
2027extern "C" {
2028 fn sig_restorer();
2029}
2030
2031#[inline]
2032unsafe fn sys_rt_sigaction(sig: c_int,
2033 act: *const KSigAction,
2034 oldact: *mut KSigAction,
2035 sigsetsize: usize,) -> i64 {
2036 <Arch as Syscalls>::syscall4(SYS_RT_SIGACTION, sig as i64, act as i64, oldact as i64, sigsetsize as i64)
2037}
2038
2039#[inline]
2040unsafe fn sys_rt_sigprocmask(how: c_int,
2041 set: *const SigSetT,
2042 oldset: *mut SigSetT,
2043 sigsetsize: usize,) -> i64 {
2044 <Arch as Syscalls>::syscall4(SYS_RT_SIGPROCMASK, how as i64, set as i64, oldset as i64, sigsetsize as i64)
2045}
2046
2047#[inline]
2048unsafe fn sys_rt_sigpending(set: *mut SigSetT, sigsetsize: usize) -> i64 {
2049 <Arch as Syscalls>::syscall2(SYS_RT_SIGPENDING, set as i64, sigsetsize as i64)
2050}
2051
2052#[inline]
2053unsafe fn sys_rt_sigsuspend(mask: *const SigSetT, sigsetsize: usize) -> i64 {
2054 <Arch as Syscalls>::syscall2(SYS_RT_SIGSUSPEND, mask as i64, sigsetsize as i64)
2055}
2056
2057#[inline]
2058unsafe fn sys_rt_sigtimedwait(set: *const SigSetT,
2059 info: *mut siginfo_t,
2060 timeout: *const timespec,
2061 sigsetsize: usize,) -> i64 {
2062 <Arch as Syscalls>::syscall4(SYS_RT_SIGTIMEDWAIT, set as i64, info as i64, timeout as i64, sigsetsize as i64)
2063}
2064
2065#[inline]
2066unsafe fn sys_sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> i64 {
2067 <Arch as Syscalls>::syscall2(SYS_SIGALTSTACK, ss as i64, old_ss as i64)
2068}
2069
2070#[inline]
2071unsafe fn sys_tgkill(tgid: c_int, tid: c_int, sig: c_int) -> i64 {
2072 <Arch as Syscalls>::syscall3(SYS_TGKILL, tgid as i64, tid as i64, sig as i64)
2073}
2074
2075const CLOCK_REALTIME: c_int = 0;
2076const CLOCK_MONOTONIC: c_int = 1;
2077
2078#[inline]
2079unsafe fn sys_clock_gettime(clockid: c_int, ts: *mut timespec) -> i64 {
2080 <Arch as Syscalls>::syscall2(SYS_CLOCK_GETTIME, clockid as i64, ts as i64)
2081}
2082
2083#[no_mangle]
2087pub unsafe extern "C" fn sigprocmask(
2088 how: c_int,
2089 set: *const SigSetT,
2090 oldset: *mut SigSetT,
2091) -> c_int {
2092 let internal_mask: SigSetT = (1u64 << 31) | (1u64 << 32);
2094 let filtered: SigSetT;
2095 let set_ptr: *const SigSetT = if set.is_null() {
2096 set
2097 } else {
2098 filtered = *set & !internal_mask;
2099 &filtered
2100 };
2101 let r = sys_rt_sigprocmask(how, set_ptr, oldset, core::mem::size_of::<SigSetT>());
2102 if !oldset.is_null() {
2103 *oldset &= !internal_mask;
2104 }
2105 if r < 0 { -1 } else { 0 }
2106}
2107
2108#[inline]
2109unsafe fn sys_kill(pid: c_int, sig: c_int) -> i64 {
2110 <Arch as Syscalls>::syscall2(SYS_KILL, pid as i64, sig as i64)
2111}
2112
2113#[inline]
2114unsafe fn sys_getpid() -> i64 {
2115 <Arch as Syscalls>::syscall0(SYS_GETPID)
2116}
2117
2118#[no_mangle]
2119pub unsafe extern "C" fn sigaction(
2120 signum: c_int,
2121 act: *const sigaction,
2122 oldact: *mut sigaction,
2123) -> c_int {
2124 let mut kact: KSigAction = core::mem::zeroed();
2125 let act_ptr = if act.is_null() {
2126 core::ptr::null()
2127 } else {
2128 kact.sa_handler = (*act).sa_handler;
2129 kact.sa_flags = ((*act).sa_flags as c_ulong) | SA_RESTORER;
2130 kact.sa_restorer = if (*act).sa_flags as c_ulong & SA_RESTORER != 0
2131 && (*act).sa_restorer != 0
2132 {
2133 (*act).sa_restorer
2134 } else {
2135 sig_restorer as *const () as usize
2136 };
2137 kact.sa_mask[0] = (*act).sa_mask[0];
2138 &kact
2139 };
2140 let mut kold: KSigAction = core::mem::zeroed();
2141 let old_ptr = if oldact.is_null() { core::ptr::null_mut() } else { &mut kold };
2142 let r = sys_rt_sigaction(signum, act_ptr, old_ptr, 8);
2143 if r < 0 {
2144 ERRNO!() = (-r) as c_int;
2145 return -1;
2146 }
2147 if !oldact.is_null() {
2148 (*oldact).sa_handler = kold.sa_handler;
2149 (*oldact).sa_flags = kold.sa_flags as c_int;
2150 (*oldact).sa_restorer = kold.sa_restorer;
2151 (*oldact).sa_mask = [0; 16];
2152 (*oldact).sa_mask[0] = kold.sa_mask[0];
2153 }
2154 0
2155}
2156
2157#[no_mangle]
2158pub unsafe extern "C" fn signal(signum: c_int, handler: usize) -> usize {
2159 let act = sigaction {
2162 sa_handler: handler,
2163 sa_mask: [0; 16],
2164 sa_flags: SA_RESTART as c_int,
2165 sa_restorer: 0,
2166 };
2167 let mut old: sigaction = core::mem::zeroed();
2168 if sigaction(signum, &act, &mut old) == -1 {
2169 SIG_ERR
2170 } else {
2171 old.sa_handler
2172 }
2173}
2174
2175#[no_mangle]
2176pub unsafe extern "C" fn kill(pid: c_int, sig: c_int) -> c_int {
2177 let r = sys_kill(pid, sig);
2178 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2179 0
2180}
2181
2182#[no_mangle]
2183pub unsafe extern "C" fn tgkill(tgid: c_int, tid: c_int, sig: c_int) -> c_int {
2184 let r = sys_tgkill(tgid, tid, sig);
2185 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2186 0
2187}
2188
2189#[no_mangle]
2190pub unsafe extern "C" fn getpid() -> c_int {
2191 sys_getpid() as c_int
2192}
2193
2194#[no_mangle]
2195pub unsafe extern "C" fn raise(sig: c_int) -> c_int {
2196 let r = sys_tgkill(sys_getpid() as c_int, sys_gettid() as c_int, sig);
2197 if r < 0 {
2198 ERRNO!() = (-r) as c_int;
2199 -1
2200 } else {
2201 0
2202 }
2203}
2204
2205#[no_mangle]
2206pub unsafe extern "C" fn sigemptyset(set: *mut SigSetT) -> c_int {
2207 *set = 0;
2208 0
2209}
2210
2211#[no_mangle]
2212pub unsafe extern "C" fn sigfillset(set: *mut SigSetT) -> c_int {
2213 *set = 0xFFFF_FFFC_7FFF_FFFFu64;
2215 0
2216}
2217
2218#[no_mangle]
2219pub unsafe extern "C" fn sigaddset(set: *mut SigSetT, signum: c_int) -> c_int {
2220 let s = (signum as c_uint).wrapping_sub(1);
2221 if s as usize >= 64 {
2222 ERRNO!() = EINVAL;
2223 return -1;
2224 }
2225 if signum >= 32 && signum < __libc_current_sigrtmin() {
2227 return 0;
2228 }
2229 *set |= 1u64 << s;
2230 0
2231}
2232
2233#[no_mangle]
2234pub unsafe extern "C" fn sigdelset(set: *mut SigSetT, signum: c_int) -> c_int {
2235 let s = (signum as c_uint).wrapping_sub(1);
2236 if s as usize >= 64 {
2237 ERRNO!() = EINVAL;
2238 return -1;
2239 }
2240 if signum >= 32 && signum < __libc_current_sigrtmin() {
2242 return 0;
2243 }
2244 *set &= !(1u64 << s);
2245 0
2246}
2247
2248#[no_mangle]
2249pub unsafe extern "C" fn sigismember(set: *const SigSetT, signum: c_int) -> c_int {
2250 let s = (signum as c_uint).wrapping_sub(1);
2251 if s as usize >= 64 { return 0; }
2252 if signum >= 32 && signum < __libc_current_sigrtmin() {
2254 return 0;
2255 }
2256 ((*set & (1u64 << s)) != 0) as c_int
2257}
2258
2259#[no_mangle]
2260pub unsafe extern "C" fn sigpending(set: *mut SigSetT) -> c_int {
2261 let r = sys_rt_sigpending(set, core::mem::size_of::<SigSetT>());
2262 if r < 0 {
2263 ERRNO!() = (-r) as c_int;
2264 return -1;
2265 }
2266 0
2267}
2268
2269#[no_mangle]
2270pub unsafe extern "C" fn sigsuspend(mask: *const SigSetT) -> c_int {
2271 let r = sys_rt_sigsuspend(mask, core::mem::size_of::<SigSetT>());
2272 if r < 0 {
2273 ERRNO!() = (-r) as c_int;
2274 }
2275 -1
2276}
2277
2278#[no_mangle]
2279pub unsafe extern "C" fn sigtimedwait(
2280 mask: *const SigSetT,
2281 info: *mut siginfo_t,
2282 timeout: *const timespec,
2283) -> c_int {
2284 loop {
2285 let r = sys_rt_sigtimedwait(mask, info, timeout, core::mem::size_of::<SigSetT>());
2286 if r >= 0 {
2287 return r as c_int;
2288 }
2289 let e = (-r) as c_int;
2290 if e != EINTR {
2291 ERRNO!() = e;
2292 return -1;
2293 }
2294 }
2295}
2296
2297#[no_mangle]
2298pub unsafe extern "C" fn sigwaitinfo(
2299 mask: *const SigSetT,
2300 info: *mut siginfo_t,
2301) -> c_int {
2302 sigtimedwait(mask, info, core::ptr::null())
2303}
2304
2305#[no_mangle]
2306pub unsafe extern "C" fn sigwait(
2307 mask: *const SigSetT,
2308 sig: *mut c_int,
2309) -> c_int {
2310 let mut info: siginfo_t = core::mem::zeroed();
2311 if sigtimedwait(mask, &mut info, core::ptr::null()) < 0 {
2312 return ERRNO!();
2313 }
2314 *sig = info.si_signo;
2315 0
2316}
2317
2318#[no_mangle]
2319pub unsafe extern "C" fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> c_int {
2320 if !ss.is_null() {
2321 if (*ss).ss_flags & SS_ONSTACK != 0 {
2322 ERRNO!() = EINVAL;
2323 return -1;
2324 }
2325 if (*ss).ss_flags & SS_DISABLE == 0 && (*ss).ss_size < MINSIGSTKSZ {
2326 ERRNO!() = ENOMEM;
2327 return -1;
2328 }
2329 }
2330 let r = sys_sigaltstack(ss, old_ss);
2331 if r < 0 {
2332 ERRNO!() = (-r) as c_int;
2333 return -1;
2334 }
2335 0
2336}
2337
2338#[no_mangle]
2344#[inline(never)]
2345#[cfg(target_arch = "x86_64")]
2346pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2347 core::arch::asm!(
2348 "mov rax, [rsp]",
2349 "lea rcx, [rsp + 8]",
2350 "mov [r8], rbx",
2351 "mov [r8 + 8], rbp",
2352 "mov [r8 + 16], r12",
2353 "mov [r8 + 24], r13",
2354 "mov [r8 + 32], r14",
2355 "mov [r8 + 40], r15",
2356 "mov [r8 + 48], rcx",
2357 "mov [r8 + 56], rax",
2358 in("r8") env,
2359 lateout("rax") _,
2360 lateout("rcx") _,
2361 options(nostack),
2362 );
2363 0
2364}
2365
2366#[no_mangle]
2367#[inline(never)]
2368#[cfg(target_arch = "x86_64")]
2369pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2370 let ret = if val == 0 { 1 } else { val } as u32;
2371 core::arch::asm!(
2372 "mov rbx, [r8]",
2373 "mov rbp, [r8 + 8]",
2374 "mov r12, [r8 + 16]",
2375 "mov r13, [r8 + 24]",
2376 "mov r14, [r8 + 32]",
2377 "mov r15, [r8 + 40]",
2378 "mov rsp, [r8 + 48]",
2379 "mov eax, edx",
2380 "jmp [r8 + 56]",
2381 in("r8") env,
2382 in("edx") ret,
2383 options(noreturn),
2384 );
2385}
2386
2387#[no_mangle]
2388#[unsafe(naked)]
2389#[cfg(target_arch = "aarch64")]
2390pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2391 core::arch::naked_asm!(
2392 "stp x19, x20, [x0, #0]",
2393 "stp x21, x22, [x0, #16]",
2394 "stp x23, x24, [x0, #32]",
2395 "stp x25, x26, [x0, #48]",
2396 "stp x27, x28, [x0, #64]",
2397 "stp x29, x30, [x0, #80]",
2398 "mov x2, sp",
2399 "str x2, [x0, #104]",
2400 "stp d8, d9, [x0, #112]",
2401 "stp d10, d11, [x0, #128]",
2402 "stp d12, d13, [x0, #144]",
2403 "stp d14, d15, [x0, #160]",
2404 "mov x0, #0",
2405 "ret",
2406 );
2407}
2408
2409#[no_mangle]
2410#[inline(never)]
2411#[cfg(target_arch = "aarch64")]
2412pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2413 let ret = if val == 0 { 1 } else { val } as u64;
2414 core::arch::asm!(
2415 "ldp x19, x20, [x0]",
2416 "ldp x21, x22, [x0, #16]",
2417 "ldp x23, x24, [x0, #32]",
2418 "ldp x25, x26, [x0, #48]",
2419 "ldp x27, x28, [x0, #64]",
2420 "ldp x29, x30, [x0, #80]",
2421 "ldr x2, [x0, #104]",
2422 "mov sp, x2",
2423 "ldp d8, d9, [x0, #112]",
2424 "ldp d10, d11, [x0, #128]",
2425 "ldp d12, d13, [x0, #144]",
2426 "ldp d14, d15, [x0, #160]",
2427 "mov x0, x1",
2428 "br x30",
2429 in("x0") env,
2430 in("x1") ret,
2431 options(noreturn),
2432 );
2433}
2434
2435#[no_mangle]
2436#[unsafe(naked)]
2437#[cfg(target_arch = "riscv64")]
2438pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2439 core::arch::naked_asm!(
2440 "sd s0, 0(a0)",
2441 "sd s1, 8(a0)",
2442 "sd s2, 16(a0)",
2443 "sd s3, 24(a0)",
2444 "sd s4, 32(a0)",
2445 "sd s5, 40(a0)",
2446 "sd s6, 48(a0)",
2447 "sd s7, 56(a0)",
2448 "sd s8, 64(a0)",
2449 "sd s9, 72(a0)",
2450 "sd s10, 80(a0)",
2451 "sd s11, 88(a0)",
2452 "sd sp, 96(a0)",
2453 "sd ra, 104(a0)",
2454 "li a0, 0",
2455 "ret",
2456 );
2457}
2458
2459#[no_mangle]
2460#[inline(never)]
2461#[cfg(target_arch = "riscv64")]
2462pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2463 let ret = if val == 0 { 1 } else { val } as u64;
2464 core::arch::asm!(
2465 "ld s0, 0(a0)",
2466 "ld s1, 8(a0)",
2467 "ld s2, 16(a0)",
2468 "ld s3, 24(a0)",
2469 "ld s4, 32(a0)",
2470 "ld s5, 40(a0)",
2471 "ld s6, 48(a0)",
2472 "ld s7, 56(a0)",
2473 "ld s8, 64(a0)",
2474 "ld s9, 72(a0)",
2475 "ld s10, 80(a0)",
2476 "ld s11, 88(a0)",
2477 "ld sp, 96(a0)",
2478 "ld ra, 104(a0)",
2479 "mv a0, a1",
2480 "ret",
2481 in("a0") env,
2482 in("a1") ret,
2483 options(noreturn),
2484 );
2485}
2486
2487#[no_mangle]
2495#[unsafe(naked)]
2496#[cfg(target_arch = "x86_64")]
2497pub unsafe extern "C" fn sigsetjmp(_env: *mut c_ulong, _savemask: c_int) -> c_int {
2498 core::arch::naked_asm!("jmp sigsetjmp_real");
2499}
2500
2501#[no_mangle]
2502#[unsafe(naked)]
2503#[cfg(target_arch = "x86_64")]
2504pub unsafe extern "C" fn __sigsetjmp(_env: *mut c_ulong, _savemask: c_int) -> c_int {
2505 core::arch::naked_asm!("jmp sigsetjmp_real");
2506}
2507
2508#[cfg(target_arch = "x86_64")]
2509core::arch::global_asm!(
2510 ".type sigsetjmp_real, @function",
2511 "sigsetjmp_real:",
2512 " test esi, esi",
2513 " jz 1f",
2514 " pop qword ptr [rdi + 64]",
2515 " mov qword ptr [rdi + 80], rbx",
2516 " mov rbx, rdi",
2520 " call setjmp",
2521 " push qword ptr [rbx + 64]",
2522 " mov rdi, rbx",
2523 " mov esi, eax",
2524 " mov rbx, qword ptr [rbx + 80]",
2525 " lea rdx, [rdi + 72]",
2526 " test esi, esi",
2527 " jz 2f",
2528 " mov rsi, rdx",
2529 " xor rdx, rdx",
2530 " mov edi, 2",
2531 " jmp 3f",
2532 "2:",
2533 " xor rsi, rsi",
2534 " mov edi, 2",
2535 "3:",
2536 " mov eax, 14",
2537 " mov r10d, 8",
2538 " syscall",
2539 " test esi, esi",
2540 " jnz 4f",
2541 " mov rax, 0xfffffffe7fffffff",
2542 " and qword ptr [rdx], rax",
2543 "4:",
2544 " mov eax, esi",
2545 " ret",
2546 "1:",
2547 " jmp setjmp",
2548);
2549
2550#[no_mangle]
2551#[inline(never)]
2552#[cfg(target_arch = "x86_64")]
2553pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2554 longjmp(env, val);
2555}
2556
2557#[no_mangle]
2558#[cfg(target_arch = "aarch64")]
2559pub unsafe extern "C" fn __sigsetjmp_tail(env: *mut c_ulong, ret: c_int) -> c_int {
2560 const SIG_SETMASK: c_int = 2;
2561 let ss = env.add(23) as *mut SigSetT;
2562 let set = if ret != 0 { ss as *const SigSetT } else { core::ptr::null() };
2563 let old = if ret != 0 { core::ptr::null_mut() } else { ss };
2564 let _ = sys_rt_sigprocmask(SIG_SETMASK, set, old, core::mem::size_of::<SigSetT>());
2565 ret
2566}
2567
2568#[no_mangle]
2569#[unsafe(naked)]
2570#[cfg(target_arch = "aarch64")]
2571pub unsafe extern "C" fn sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2572 core::arch::naked_asm!(
2573 "cbz w1, setjmp",
2574 "str x30, [x0, #176]",
2575 "str x19, [x0, #192]",
2576 "mov x19, x0",
2577 "bl setjmp",
2578 "mov w1, w0",
2579 "mov x0, x19",
2580 "ldr x30, [x0, #176]",
2581 "ldr x19, [x0, #192]",
2582 "b __sigsetjmp_tail",
2583 );
2584}
2585
2586#[no_mangle]
2587#[unsafe(naked)]
2588#[cfg(target_arch = "aarch64")]
2589pub unsafe extern "C" fn __sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2590 core::arch::naked_asm!(
2591 "cbz w1, setjmp",
2592 "str x30, [x0, #176]",
2593 "str x19, [x0, #192]",
2594 "mov x19, x0",
2595 "bl setjmp",
2596 "mov w1, w0",
2597 "mov x0, x19",
2598 "ldr x30, [x0, #176]",
2599 "ldr x19, [x0, #192]",
2600 "b __sigsetjmp_tail",
2601 );
2602}
2603
2604#[no_mangle]
2605#[inline(never)]
2606#[cfg(target_arch = "aarch64")]
2607pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2608 longjmp(env, val);
2609}
2610
2611#[no_mangle]
2612#[cfg(target_arch = "riscv64")]
2613pub unsafe extern "C" fn __sigsetjmp_tail(env: *mut c_ulong, ret: c_int) -> c_int {
2614 const SIG_SETMASK: c_int = 2;
2615 let ss = env.add(27) as *mut SigSetT;
2616 let set = if ret != 0 { ss as *const SigSetT } else { core::ptr::null() };
2617 let old = if ret != 0 { core::ptr::null_mut() } else { ss };
2618 let _ = sys_rt_sigprocmask(SIG_SETMASK, set, old, core::mem::size_of::<SigSetT>());
2619 ret
2620}
2621
2622#[no_mangle]
2623#[unsafe(naked)]
2624#[cfg(target_arch = "riscv64")]
2625pub unsafe extern "C" fn sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2626 core::arch::naked_asm!(
2627 "bnez a1, 1f",
2628 "tail setjmp",
2629 "1:",
2630 "sd ra, 208(a0)",
2631 "sd s0, 224(a0)",
2632 "mv s0, a0",
2633 "call setjmp",
2634 "mv a1, a0",
2635 "mv a0, s0",
2636 "ld s0, 224(a0)",
2637 "ld ra, 208(a0)",
2638 "tail __sigsetjmp_tail",
2639 );
2640}
2641
2642#[no_mangle]
2643#[unsafe(naked)]
2644#[cfg(target_arch = "riscv64")]
2645pub unsafe extern "C" fn __sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2646 core::arch::naked_asm!(
2647 "bnez a1, 1f",
2648 "tail setjmp",
2649 "1:",
2650 "sd ra, 208(a0)",
2651 "sd s0, 224(a0)",
2652 "mv s0, a0",
2653 "call setjmp",
2654 "mv a1, a0",
2655 "mv a0, s0",
2656 "ld s0, 224(a0)",
2657 "ld ra, 208(a0)",
2658 "tail __sigsetjmp_tail",
2659 );
2660}
2661
2662#[no_mangle]
2663#[inline(never)]
2664#[cfg(target_arch = "riscv64")]
2665pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2666 longjmp(env, val);
2667}
2668
2669#[inline]
2674unsafe fn sys_newfstatat(dirfd: i32, path: *const c_char, buf: *mut u8, flags: i32) -> i64 {
2675 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, dirfd as i64, path as i64, buf as i64, flags as i64)
2676}
2677
2678#[inline]
2679unsafe fn sys_fstat(fd: i32, buf: *mut u8) -> i64 {
2680 <Arch as Syscalls>::syscall2(SYS_FSTAT, fd as i64, buf as i64)
2681}
2682
2683#[inline]
2684unsafe fn sys_getrlimit(resource: i32, rlim: *mut u8) -> i64 {
2685 <Arch as Syscalls>::syscall2(SYS_GETRLIMIT, resource as i64, rlim as i64)
2686}
2687
2688#[inline]
2689unsafe fn sys_setrlimit(resource: i32, rlim: *const u8) -> i64 {
2690 <Arch as Syscalls>::syscall2(SYS_SETRLIMIT, resource as i64, rlim as i64)
2691}
2692
2693#[inline]
2694unsafe fn sys_utimensat(dirfd: i32, path: *const c_char, times: *const u8, flags: i32) -> i64 {
2695 <Arch as Syscalls>::syscall4(SYS_UTIMENSAT, dirfd as i64, path as i64, times as i64, flags as i64)
2696}
2697
2698#[inline]
2703unsafe fn sys_fork() -> i64 {
2704 #[cfg(target_arch = "x86_64")]
2705 { <Arch as Syscalls>::syscall0(SYS_FORK) }
2706 #[cfg(target_arch = "aarch64")]
2707 { <Arch as Syscalls>::syscall2(SYS_CLONE, 17, 0) }
2708 #[cfg(target_arch = "riscv64")]
2709 { <Arch as Syscalls>::syscall2(SYS_CLONE, 17, 0) }
2710}
2711
2712#[inline]
2713unsafe fn sys_execve(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> i64 {
2714 <Arch as Syscalls>::syscall3(SYS_EXECVE, path as i64, argv as i64, envp as i64)
2715}
2716
2717#[inline]
2718unsafe fn sys_wait4(pid: c_int, status: *mut c_int, options: c_int, rusage: *mut c_void) -> i64 {
2719 <Arch as Syscalls>::syscall4(SYS_WAIT4, pid as i64, status as i64, options as i64, rusage as i64)
2720}
2721
2722#[inline]
2723unsafe fn sys_getppid() -> i64 {
2724 <Arch as Syscalls>::syscall0(SYS_GETPPID)
2725}
2726
2727#[inline]
2728unsafe fn sys_getuid() -> i64 {
2729 <Arch as Syscalls>::syscall0(SYS_GETUID)
2730}
2731
2732#[inline]
2733unsafe fn sys_getgid() -> i64 {
2734 <Arch as Syscalls>::syscall0(SYS_GETGID)
2735}
2736
2737#[inline]
2738unsafe fn sys_geteuid() -> i64 {
2739 <Arch as Syscalls>::syscall0(SYS_GETEUID)
2740}
2741
2742#[inline]
2743unsafe fn sys_getegid() -> i64 {
2744 <Arch as Syscalls>::syscall0(SYS_GETEGID)
2745}
2746
2747#[no_mangle]
2748pub unsafe extern "C" fn fork() -> c_int {
2749 __fork_handler(-1);
2750 let ret = sys_fork();
2751 if ret < 0 {
2756 let err = (-ret) as c_int;
2757 __fork_handler(0);
2758 ERRNO!() = err;
2759 return -1;
2760 }
2761 if ret == 0 {
2762 allocator_after_fork();
2763 __fork_handler(1);
2764 } else {
2765 __fork_handler(0);
2766 }
2767 ret as c_int
2768}
2769
2770#[no_mangle]
2771pub unsafe extern "C" fn execve(
2772 path: *const c_char,
2773 argv: *const *const c_char,
2774 envp: *const *const c_char,
2775) -> c_int {
2776 let r = sys_execve(path, argv, envp);
2777 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2778 r as c_int
2779}
2780
2781#[no_mangle]
2782pub unsafe extern "C" fn wait(status: *mut c_int) -> c_int {
2783 let r = sys_wait4(-1, status, 0, core::ptr::null_mut());
2784 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2785 r as c_int
2786}
2787
2788#[no_mangle]
2789pub unsafe extern "C" fn waitpid(pid: c_int, status: *mut c_int, options: c_int) -> c_int {
2790 let r = sys_wait4(pid, status, options, core::ptr::null_mut());
2791 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2792 r as c_int
2793}
2794
2795#[no_mangle]
2796pub unsafe extern "C" fn getppid() -> c_int {
2797 sys_getppid() as c_int
2798}
2799
2800#[no_mangle]
2801pub unsafe extern "C" fn getuid() -> c_uint {
2802 sys_getuid() as c_uint
2803}
2804
2805#[no_mangle]
2806pub unsafe extern "C" fn getgid() -> c_uint {
2807 sys_getgid() as c_uint
2808}
2809
2810#[no_mangle]
2811pub unsafe extern "C" fn geteuid() -> c_uint {
2812 sys_geteuid() as c_uint
2813}
2814
2815#[no_mangle]
2816pub unsafe extern "C" fn getegid() -> c_uint {
2817 sys_getegid() as c_uint
2818}
2819
2820#[no_mangle]
2822pub unsafe extern "C" fn vfork() -> c_int {
2823 let r = sys_fork();
2824 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2825 r as c_int
2826}
2827
2828#[no_mangle]
2829pub unsafe extern "C" fn execl(path: *const c_char, arg: *const c_char, mut args: ...) -> c_int {
2830 let mut argv: [*const c_char; 256] = [core::ptr::null(); 256];
2831 argv[0] = arg;
2832 let mut n: usize = 1;
2833 loop {
2834 let a: *const c_char = args.next_arg();
2835 if a.is_null() { break; }
2836 if n >= 255 { return -1; }
2837 argv[n] = a;
2838 n += 1;
2839 }
2840 argv[n] = core::ptr::null();
2841 sys_execve(path, argv.as_ptr(), __environ as *const *const c_char) as c_int
2842}
2843
2844unsafe fn spawn_execvp(file: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> ! {
2853 let flen = strlen(file as *const c_char);
2854 let f = file as *const u8;
2855 let mut has_slash = false;
2856 for i in 0..flen {
2857 if *f.add(i) == b'/' { has_slash = true; break; }
2858 }
2859 if has_slash {
2860 sys_execve(file, argv, envp);
2861 _exit(127);
2862 }
2863 let path = getenv(b"PATH\0".as_ptr() as *const c_char);
2864 let default_path = b"/usr/local/bin:/usr/bin:/bin\0";
2865 let p = if path.is_null() { default_path.as_ptr() } else { path as *const u8 };
2866 let plen = strlen(p as *const c_char);
2867 let mut buf: [u8; 4096] = [0; 4096];
2868 let mut i: usize = 0;
2869 while i <= plen {
2870 let start = i;
2871 while i < plen && *p.add(i) != b':' { i += 1; }
2872 let dlen = i - start;
2873 if dlen > 0 && dlen + 1 + flen < 4096 {
2874 core::ptr::copy_nonoverlapping(p.add(start), buf.as_mut_ptr(), dlen);
2875 *buf.as_mut_ptr().add(dlen) = b'/';
2876 core::ptr::copy_nonoverlapping(f, buf.as_mut_ptr().add(dlen + 1), flen + 1);
2877 sys_execve(buf.as_ptr() as *const c_char, argv, envp);
2878 }
2880 i += 1; }
2882 _exit(127);
2883}
2884
2885#[no_mangle]
2886pub unsafe extern "C" fn posix_spawnp(
2887 pid: *mut c_int,
2888 file: *const c_char,
2889 fa: *const posix_spawn_file_actions_t,
2890 attrp: *const posix_spawnattr_t,
2891 argv: *const *const c_char,
2892 envp: *const *const c_char,
2893) -> c_int {
2894 let child = sys_fork();
2895 if child < 0 {
2896 ERRNO!() = EAGAIN;
2897 return -1;
2898 }
2899 if child == 0 {
2900 spawn_apply_attr(attrp);
2902 spawn_apply_actions(fa);
2903 let actual_envp = if envp.is_null() { __environ as *const *const c_char } else { envp };
2904 spawn_execvp(file, argv, actual_envp);
2905 }
2907 *pid = child as c_int;
2908 0
2909}
2910
2911#[no_mangle]
2912pub unsafe extern "C" fn posix_spawn(
2913 pid: *mut c_int,
2914 path: *const c_char,
2915 fa: *const posix_spawn_file_actions_t,
2916 attrp: *const posix_spawnattr_t,
2917 argv: *const *const c_char,
2918 envp: *const *const c_char,
2919) -> c_int {
2920 posix_spawnp(pid, path, fa, attrp, argv, envp)
2923}
2924
2925#[cfg(target_arch = "x86_64")]
2930#[repr(C)]
2931pub struct Stat {
2932 pub st_dev: u64,
2933 pub st_ino: u64,
2934 pub st_nlink: u64,
2935 pub st_mode: u32,
2936 pub st_uid: u32,
2937 pub st_gid: u32,
2938 _pad0: u32,
2939 pub st_rdev: u64,
2940 pub st_size: i64,
2941 pub st_blksize: i64,
2942 pub st_blocks: i64,
2943 pub st_atim: timespec,
2944 pub st_mtim: timespec,
2945 pub st_ctim: timespec,
2946 _unused: [i64; 3],
2947}
2948
2949#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
2950#[repr(C)]
2951pub struct Stat {
2952 pub st_dev: u64,
2953 pub st_ino: u64,
2954 pub st_mode: u32,
2955 pub st_nlink: u32,
2956 pub st_uid: u32,
2957 pub st_gid: u32,
2958 pub st_rdev: u64,
2959 __pad1: u64,
2960 pub st_size: i64,
2961 pub st_blksize: i32,
2962 __pad2: i32,
2963 pub st_blocks: i64,
2964 pub st_atim: timespec,
2965 pub st_mtim: timespec,
2966 pub st_ctim: timespec,
2967 __unused4: u32,
2968 __unused5: u32,
2969}
2970
2971pub const S_IFMT: u32 = 0o170000;
2972pub const S_IFDIR: u32 = 0o040000;
2973pub const S_IFCHR: u32 = 0o020000;
2974pub const S_IFBLK: u32 = 0o060000;
2975pub const S_IFREG: u32 = 0o100000;
2976pub const S_IFLNK: u32 = 0o120000;
2977pub const S_IFIFO: u32 = 0o010000;
2978pub const S_IFSOCK: u32 = 0o140000;
2979
2980pub const AT_FDCWD: i32 = -100;
2981
2982#[no_mangle]
2983pub unsafe extern "C" fn stat(path: *const c_char, buf: *mut Stat) -> c_int {
2984 let r = sys_newfstatat(AT_FDCWD, path, buf as *mut u8, 0);
2985 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2986 if *path == b'/' as c_char && strcmp(path as *const u8, b"/dev/null\0".as_ptr()) == 0 {
2987 (*buf).st_mode = ((*buf).st_mode & !0o170000) | 0o020000;
2988 }
2989 0
2990}
2991
2992#[no_mangle]
2993pub unsafe extern "C" fn fstat(fd: c_int, buf: *mut Stat) -> c_int {
2994 let r = sys_fstat(fd, buf as *mut u8);
2995 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
2996}
2997
2998#[repr(C)]
3003pub struct Rlimit {
3004 pub rlim_cur: u64,
3005 pub rlim_max: u64,
3006}
3007
3008pub const RLIMIT_NOFILE: c_int = 7;
3009pub const RLIMIT_STACK: c_int = 3;
3010pub const RLIMIT_DATA: c_int = 2;
3011pub const RLIMIT_AS: c_int = 9;
3012pub const RLIMIT_CPU: c_int = 0;
3013pub const RLIMIT_FSIZE: c_int = 1;
3014pub const RLIMIT_CORE: c_int = 4;
3015pub const RLIMIT_RSS: c_int = 5;
3016pub const RLIMIT_NPROC: c_int = 6;
3017pub const RLIMIT_MEMLOCK: c_int = 8;
3018pub const RLIMIT_LOCKS: c_int = 10;
3019pub const RLIMIT_SIGPENDING: c_int = 11;
3020pub const RLIMIT_MSGQUEUE: c_int = 12;
3021pub const RLIMIT_NICE: c_int = 13;
3022pub const RLIMIT_RTPRIO: c_int = 14;
3023pub const RLIMIT_RTTIME: c_int = 15;
3024pub const RLIM_INFINITY: u64 = !0u64;
3025
3026#[no_mangle]
3027pub unsafe extern "C" fn getrlimit(resource: c_int, rlim: *mut Rlimit) -> c_int {
3028 let r = sys_getrlimit(resource, rlim as *mut u8);
3029 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
3030}
3031
3032#[no_mangle]
3033pub unsafe extern "C" fn setrlimit(resource: c_int, rlim: *const Rlimit) -> c_int {
3034 let r = sys_setrlimit(resource, rlim as *const u8);
3035 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
3036}
3037
3038#[no_mangle]
3043pub unsafe extern "C" fn utimensat(dirfd: c_int, path: *const c_char, times: *const timespec, flags: c_int) -> c_int {
3044 let r = sys_utimensat(dirfd, path, times as *const u8, flags);
3045 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
3046}
3047
3048#[no_mangle]
3049pub unsafe extern "C" fn futimens(fd: c_int, times: *const timespec) -> c_int {
3050 let r = sys_utimensat(fd, core::ptr::null(), times as *const u8, 0);
3051 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
3052}
3053
3054pub const AF_UNIX: c_int = 1;
3059pub const AF_INET: c_int = 2;
3060pub const AF_INET6: c_int = 10;
3061
3062pub const SOCK_STREAM: c_int = 1;
3063pub const SOCK_DGRAM: c_int = 2;
3064
3065pub const SHUT_RD: c_int = 0;
3066pub const SHUT_WR: c_int = 1;
3067pub const SHUT_RDWR: c_int = 2;
3068
3069pub const SOL_SOCKET: c_int = 1;
3070pub const SO_REUSEADDR: c_int = 2;
3071
3072#[repr(C)]
3073pub struct sockaddr {
3074 pub sa_family: u16,
3075 pub sa_data: [u8; 14],
3076}
3077
3078#[inline]
3079unsafe fn sys_socket(domain: c_int, ty: c_int, protocol: c_int) -> i64 {
3080 <Arch as Syscalls>::syscall3(SYS_SOCKET, domain as i64, ty as i64, protocol as i64)
3081}
3082
3083#[inline]
3084unsafe fn sys_socketpair(domain: c_int, ty: c_int, protocol: c_int, sv: *mut c_int) -> i64 {
3085 <Arch as Syscalls>::syscall4(SYS_SOCKETPAIR, domain as i64, ty as i64, protocol as i64, sv as i64)
3086}
3087
3088#[inline]
3089unsafe fn sys_bind(fd: c_int, addr: *const sockaddr, len: c_uint) -> i64 {
3090 <Arch as Syscalls>::syscall3(SYS_BIND, fd as i64, addr as i64, len as i64)
3091}
3092
3093#[inline]
3094unsafe fn sys_listen(fd: c_int, backlog: c_int) -> i64 {
3095 <Arch as Syscalls>::syscall2(SYS_LISTEN, fd as i64, backlog as i64)
3096}
3097
3098#[inline]
3099unsafe fn sys_accept(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> i64 {
3100 <Arch as Syscalls>::syscall3(SYS_ACCEPT, fd as i64, addr as i64, len as i64)
3101}
3102
3103#[inline]
3104unsafe fn sys_connect(fd: c_int, addr: *const sockaddr, len: c_uint) -> i64 {
3105 <Arch as Syscalls>::syscall3(SYS_CONNECT, fd as i64, addr as i64, len as i64)
3106}
3107
3108#[inline]
3109unsafe fn sys_sendto(fd: c_int,
3110 buf: *const c_void,
3111 len: usize,
3112 flags: c_int,
3113 addr: *const sockaddr,
3114 addrlen: c_uint,) -> i64 {
3115 <Arch as Syscalls>::syscall6(SYS_SENDTO, fd as i64, buf as i64, len as i64, flags as i64, addr as i64, addrlen as i64)
3116}
3117
3118#[inline]
3119unsafe fn sys_recvfrom(fd: c_int,
3120 buf: *mut c_void,
3121 len: usize,
3122 flags: c_int,
3123 addr: *mut sockaddr,
3124 addrlen: *mut c_uint,) -> i64 {
3125 <Arch as Syscalls>::syscall6(SYS_RECVFROM, fd as i64, buf as i64, len as i64, flags as i64, addr as i64, addrlen as i64)
3126}
3127
3128#[inline]
3129unsafe fn sys_shutdown(fd: c_int, how: c_int) -> i64 {
3130 <Arch as Syscalls>::syscall2(SYS_SHUTDOWN, fd as i64, how as i64)
3131}
3132
3133#[inline]
3134unsafe fn sys_setsockopt(fd: c_int,
3135 level: c_int,
3136 optname: c_int,
3137 optval: *const c_void,
3138 optlen: c_uint,) -> i64 {
3139 <Arch as Syscalls>::syscall5(SYS_SETSOCKOPT, fd as i64, level as i64, optname as i64, optval as i64, optlen as i64)
3140}
3141
3142#[inline]
3143unsafe fn sys_getsockname(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> i64 {
3144 <Arch as Syscalls>::syscall3(SYS_GETSOCKNAME, fd as i64, addr as i64, len as i64)
3145}
3146
3147#[no_mangle]
3148pub unsafe extern "C" fn socket(domain: c_int, ty: c_int, protocol: c_int) -> c_int {
3149 let r = sys_socket(domain, ty, protocol);
3150 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3151 r as c_int
3152}
3153
3154#[no_mangle]
3155pub unsafe extern "C" fn socketpair(domain: c_int, ty: c_int, protocol: c_int, sv: *mut c_int) -> c_int {
3156 let r = sys_socketpair(domain, ty, protocol, sv);
3157 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3158 0
3159}
3160
3161#[no_mangle]
3162pub unsafe extern "C" fn bind(fd: c_int, addr: *const sockaddr, len: c_uint) -> c_int {
3163 let r = sys_bind(fd, addr, len);
3164 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3165 0
3166}
3167
3168#[no_mangle]
3169pub unsafe extern "C" fn listen(fd: c_int, backlog: c_int) -> c_int {
3170 let r = sys_listen(fd, backlog);
3171 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3172 0
3173}
3174
3175#[no_mangle]
3176pub unsafe extern "C" fn accept(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> c_int {
3177 let r = sys_accept(fd, addr, len);
3178 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3179 r as c_int
3180}
3181
3182#[no_mangle]
3183pub unsafe extern "C" fn connect(fd: c_int, addr: *const sockaddr, len: c_uint) -> c_int {
3184 let r = sys_connect(fd, addr, len);
3185 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3186 0
3187}
3188
3189#[no_mangle]
3190pub unsafe extern "C" fn send(fd: c_int, buf: *const c_void, len: usize, flags: c_int) -> isize {
3191 let r = sys_sendto(fd, buf, len, flags, core::ptr::null(), 0);
3192 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3193 r as isize
3194}
3195
3196#[no_mangle]
3197pub unsafe extern "C" fn recv(fd: c_int, buf: *mut c_void, len: usize, flags: c_int) -> isize {
3198 let r = sys_recvfrom(fd, buf, len, flags, core::ptr::null_mut(), core::ptr::null_mut());
3199 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3200 r as isize
3201}
3202
3203#[no_mangle]
3204pub unsafe extern "C" fn sendto(
3205 fd: c_int,
3206 buf: *const c_void,
3207 len: usize,
3208 flags: c_int,
3209 addr: *const sockaddr,
3210 addrlen: c_uint,
3211) -> isize {
3212 let r = sys_sendto(fd, buf, len, flags, addr, addrlen);
3213 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3214 r as isize
3215}
3216
3217#[no_mangle]
3218pub unsafe extern "C" fn recvfrom(
3219 fd: c_int,
3220 buf: *mut c_void,
3221 len: usize,
3222 flags: c_int,
3223 addr: *mut sockaddr,
3224 addrlen: *mut c_uint,
3225) -> isize {
3226 let r = sys_recvfrom(fd, buf, len, flags, addr, addrlen);
3227 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3228 r as isize
3229}
3230
3231#[no_mangle]
3232pub unsafe extern "C" fn shutdown(fd: c_int, how: c_int) -> c_int {
3233 let r = sys_shutdown(fd, how);
3234 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3235 0
3236}
3237
3238#[no_mangle]
3239pub unsafe extern "C" fn setsockopt(
3240 fd: c_int,
3241 level: c_int,
3242 optname: c_int,
3243 optval: *const c_void,
3244 optlen: c_uint,
3245) -> c_int {
3246 let r = sys_setsockopt(fd, level, optname, optval, optlen);
3247 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3248 0
3249}
3250
3251#[no_mangle]
3252pub unsafe extern "C" fn getsockname(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> c_int {
3253 let r = sys_getsockname(fd, addr, len);
3254 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3255 0
3256}
3257
3258#[no_mangle]
3259pub extern "C" fn htonl(hostlong: c_uint) -> c_uint {
3260 hostlong.to_be()
3261}
3262
3263#[no_mangle]
3264pub extern "C" fn ntohl(netlong: c_uint) -> c_uint {
3265 c_uint::from_be(netlong)
3266}
3267
3268#[no_mangle]
3269pub extern "C" fn htons(hostshort: u16) -> u16 {
3270 hostshort.to_be()
3271}
3272
3273#[no_mangle]
3274pub extern "C" fn ntohs(netshort: u16) -> u16 {
3275 u16::from_be(netshort)
3276}
3277
3278pub type PthreadT = c_ulong;
3279
3280#[repr(C)]
3282pub struct pthread_attr_t {
3283 __i: [c_int; 14],
3284}
3285
3286#[repr(C)]
3289pub struct pthread_mutex_t {
3290 __i: [c_int; 10],
3291}
3292
3293#[repr(C)]
3294pub struct pthread_mutexattr_t {
3295 __attr: c_uint,
3296}
3297
3298#[repr(C)]
3301pub struct pthread_cond_t {
3302 __i: [c_int; 12],
3303}
3304
3305#[repr(C)]
3306pub struct pthread_condattr_t {
3307 __attr: c_uint,
3308}
3309
3310#[repr(C)]
3313pub struct pthread_rwlock_t {
3314 __i: [c_int; 14],
3315}
3316
3317#[repr(C)]
3318pub struct pthread_rwlockattr_t {
3319 __attr: [c_uint; 2],
3320}
3321
3322#[repr(C)]
3324pub struct pthread_barrier_t {
3325 __i: [c_int; 8],
3326}
3327
3328#[repr(C)]
3329pub struct pthread_barrierattr_t {
3330 __attr: c_uint,
3331}
3332
3333pub type pthread_spinlock_t = c_int;
3334pub type pthread_once_t = c_int;
3335pub type pthread_key_t = c_uint;
3336
3337#[repr(C)]
3339pub struct sem_t {
3340 __val: [c_int; 8],
3341}
3342
3343#[repr(C)]
3344pub struct sched_param {
3345 pub sched_priority: c_int,
3346}
3347
3348const CLONE_VM: c_ulong = 0x00000100;
3349const CLONE_FS: c_ulong = 0x00000200;
3350const CLONE_FILES: c_ulong = 0x00000400;
3351const CLONE_SIGHAND: c_ulong = 0x00000800;
3352const CLONE_THREAD: c_ulong = 0x00010000;
3353const CLONE_SYSVSEM: c_ulong = 0x00040000;
3354const CLONE_SETTLS: c_ulong = 0x00080000;
3355const CLONE_PARENT_SETTID: c_ulong = 0x00100000;
3356const CLONE_CHILD_CLEARTID: c_ulong = 0x00200000;
3357
3358const FUTEX_WAIT: c_int = 0;
3359const FUTEX_WAKE: c_int = 1;
3360const FUTEX_LOCK_PI: c_int = 6;
3361const FUTEX_UNLOCK_PI: c_int = 7;
3362const FUTEX_TRYLOCK_PI: c_int = 8;
3363
3364const SIGCANCEL: c_int = 32;
3366
3367const PTHREAD_MUTEX_NORMAL: c_int = 0;
3368const PTHREAD_MUTEX_DEFAULT: c_int = 0;
3369const PTHREAD_MUTEX_RECURSIVE: c_int = 1;
3370const PTHREAD_MUTEX_ERRORCHECK: c_int = 2;
3371
3372const PTHREAD_CREATE_JOINABLE: c_int = 0;
3373const PTHREAD_CREATE_DETACHED: c_int = 1;
3374
3375const PTHREAD_CANCEL_ENABLE: c_int = 0;
3376const PTHREAD_CANCEL_DISABLE: c_int = 1;
3377const PTHREAD_CANCEL_DEFERRED: c_int = 0;
3378const PTHREAD_CANCEL_ASYNCHRONOUS: c_int = 1;
3379
3380const PTHREAD_SCOPE_SYSTEM: c_int = 0;
3381const PTHREAD_PROCESS_PRIVATE: c_int = 0;
3382const PTHREAD_PROCESS_SHARED: c_int = 1;
3383const PTHREAD_INHERIT_SCHED: c_int = 0;
3384const PTHREAD_EXPLICIT_SCHED: c_int = 1;
3385
3386const PTHREAD_BARRIER_SERIAL_THREAD: c_int = -1;
3387
3388const PTHREAD_KEYS_MAX: usize = 128;
3389const PTHREAD_DESTRUCTOR_ITERATIONS: usize = 4;
3390const SEM_VALUE_MAX: c_int = 0x7fffffff;
3391
3392const DT_EXITED: c_int = 0;
3393const DT_EXITING: c_int = 1;
3394const DT_JOINABLE: c_int = 2;
3395const DT_DETACHED: c_int = 3;
3396
3397#[repr(C)]
3399#[derive(Copy, Clone)]
3400pub struct __ptcb {
3401 __f: Option<unsafe extern "C" fn(*mut c_void)>,
3402 __x: *mut c_void,
3403 __next: *mut __ptcb,
3404}
3405
3406#[repr(C)]
3408#[derive(Copy, Clone)]
3409struct robust_list {
3410 next: *mut robust_list,
3411}
3412
3413#[repr(C)]
3414#[derive(Copy, Clone)]
3415struct robust_list_head {
3416 list: robust_list,
3417 futex_offset: c_long,
3418 pending: *mut robust_list,
3419}
3420
3421#[cfg(all(target_arch = "x86_64", not(test)))]
3423core::arch::global_asm!(
3424 ".global __rc_clone",
3425 ".type __rc_clone, @function",
3426 "__rc_clone:",
3427 "mov rax, rdi",
3428 "mov rdi, rdx",
3429 "mov rdx, r8",
3430 "mov r10, [rsp + 8]",
3431 "mov r8, r9",
3432 "mov r9, rax",
3433 "and rsi, -16",
3434 "sub rsi, 8",
3435 "mov [rsi], rcx",
3436 "mov eax, 56",
3437 "syscall",
3438 "test rax, rax",
3439 "jnz 1f",
3440 "pop rdi",
3441 "call r9",
3442 "mov edi, eax",
3445 "mov eax, 60",
3446 "syscall",
3447 "hlt",
3448 "1:",
3449 "ret",
3450);
3451
3452#[no_mangle]
3454#[unsafe(naked)]
3455#[cfg(target_arch = "aarch64")]
3456pub unsafe extern "C" fn __rc_clone(
3457 fn_: usize,
3458 stack: *mut u8,
3459 flags: c_ulong,
3460 arg: *mut c_void,
3461 ptid: *mut c_int,
3462 tls: c_ulong,
3463 ctid: *mut c_int,
3464) -> i64 {
3465 core::arch::naked_asm!(
3466 "and x1, x1, #-16",
3467 "stp x0, x3, [x1, #-16]!",
3468 "uxtw x0, w2",
3469 "mov x2, x4",
3470 "mov x3, x5",
3471 "mov x4, x6",
3472 "mov x8, #220",
3473 "svc #0",
3474 "cbz x0, 1f",
3475 "ret",
3476 "1:",
3477 "mov x29, #0",
3478 "ldp x1, x0, [sp], #16",
3479 "blr x1",
3480 "mov x8, #93",
3481 "svc #0",
3482 );
3483}
3484
3485#[no_mangle]
3486#[unsafe(naked)]
3487#[cfg(target_arch = "riscv64")]
3488pub unsafe extern "C" fn __rc_clone(
3489 fn_: usize,
3490 stack: *mut u8,
3491 flags: c_ulong,
3492 arg: *mut c_void,
3493 ptid: *mut c_int,
3494 tls: c_ulong,
3495 ctid: *mut c_int,
3496) -> i64 {
3497 core::arch::naked_asm!(
3498 "andi a1, a1, -16",
3499 "addi a1, a1, -16",
3500 "sd a0, 0(a1)",
3501 "sd a3, 8(a1)",
3502 "mv a0, a2",
3503 "mv a2, a4",
3504 "mv a3, a5",
3505 "mv a4, a6",
3506 "li a7, 220",
3507 "ecall",
3508 "beqz a0, 1f",
3509 "ret",
3510 "1:",
3511 "ld a1, 0(sp)",
3512 "ld a0, 8(sp)",
3513 "jalr a1",
3514 "li a7, 93",
3515 "ecall",
3516 );
3517}
3518
3519#[cfg(all(target_arch = "x86_64", test))]
3520#[inline(never)]
3521unsafe fn __rc_clone(
3522 _fn_: usize,
3523 _stack: *mut u8,
3524 _flags: c_ulong,
3525 _arg: *mut c_void,
3526 _ptid: *mut c_int,
3527 _tls: c_ulong,
3528 _ctid: *mut c_int,
3529) -> i64 {
3530 -1
3531}
3532
3533#[cfg(all(target_arch = "x86_64", not(test)))]
3534extern "C" {
3535 fn __rc_clone(
3536 fn_: usize,
3537 stack: *mut u8,
3538 flags: c_ulong,
3539 arg: *mut c_void,
3540 ptid: *mut c_int,
3541 tls: c_ulong,
3542 ctid: *mut c_int,
3543 ) -> i64;
3544}
3545
3546#[inline(never)]
3547#[linkage = "weak"]
3548#[no_mangle]
3549pub extern "C" fn __rc_create_thread_tls() -> *mut u8 {
3550 core::ptr::null_mut()
3551}
3552
3553#[inline(never)]
3554#[linkage = "weak"]
3555#[no_mangle]
3556pub unsafe extern "C" fn __rc_init_thread_tls_at(_block: *mut u8) -> *mut u8 {
3557 core::ptr::null_mut()
3558}
3559
3560#[inline(never)]
3561#[linkage = "weak"]
3562#[no_mangle]
3563pub extern "C" fn __rc_tls_block_size() -> usize {
3564 0
3565}
3566
3567#[inline(never)]
3568#[linkage = "weak"]
3569#[no_mangle]
3570pub extern "C" fn __rc_tls_base_offset() -> usize {
3571 0
3572}
3573
3574#[inline]
3575unsafe fn sys_gettid() -> i64 {
3576 <Arch as Syscalls>::syscall0(SYS_GETTID)
3577}
3578
3579#[inline]
3580unsafe fn sys_futex(uaddr: *mut c_int,
3581 futex_op: c_int,
3582 val: c_int,
3583 timeout: *mut c_void,
3584 uaddr2: *mut c_int,
3585 val3: c_int,) -> i64 {
3586 <Arch as Syscalls>::syscall6(SYS_FUTEX, uaddr as i64, futex_op as i64, val as i64, timeout as i64, uaddr2 as i64, val3 as i64)
3587}
3588
3589const MAX_THREADS: usize = 1024;
3590const STACK_SIZE: usize = 1024 * 1024;
3591
3592#[repr(C)]
3593#[derive(Copy, Clone)]
3594struct Thread {
3595 tid: c_int,
3596 detach_state: c_int,
3597 result: *mut c_void,
3598 cancel: c_int,
3599 cancel_state: c_int,
3600 cancel_type: c_int,
3601 user_fn: usize,
3602 user_arg: *mut c_void,
3603 stack: *mut u8,
3604 stack_size: usize,
3605 stack_owned: bool,
3606 fs_base: *mut u8,
3607 tls_base: *mut u8,
3612 tls_size: usize,
3613 tsd: [*mut c_void; PTHREAD_KEYS_MAX],
3614 cancelbuf: *mut __ptcb,
3615 robust_list: robust_list_head,
3616}
3617
3618static mut THREADS: [Thread; MAX_THREADS] = [Thread {
3619 tid: -1,
3620 detach_state: DT_JOINABLE,
3621 result: core::ptr::null_mut(),
3622 cancel: 0,
3623 cancel_state: PTHREAD_CANCEL_ENABLE,
3624 cancel_type: PTHREAD_CANCEL_DEFERRED,
3625 user_fn: 0,
3626 user_arg: core::ptr::null_mut(),
3627 stack: core::ptr::null_mut(),
3628 stack_size: 0,
3629 stack_owned: false,
3630 fs_base: core::ptr::null_mut(),
3631 tls_base: core::ptr::null_mut(),
3632 tls_size: 0,
3633 tsd: [core::ptr::null_mut(); PTHREAD_KEYS_MAX],
3634 cancelbuf: core::ptr::null_mut(),
3635 robust_list: robust_list_head {
3636 list: robust_list { next: core::ptr::null_mut() },
3637 futex_offset: 0,
3638 pending: core::ptr::null_mut(),
3639 },
3640}; MAX_THREADS];
3641const SLOT_WORDS: usize = (MAX_THREADS + usize::BITS as usize - 1) / usize::BITS as usize;
3642static SLOT_USED: [AtomicUsize; SLOT_WORDS] = [const { AtomicUsize::new(0) }; SLOT_WORDS];
3643static mut KEY_DTORS: [Option<unsafe extern "C" fn(*mut c_void)>; PTHREAD_KEYS_MAX] = [None; PTHREAD_KEYS_MAX];
3644static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
3645
3646unsafe fn futex_wait(addr: *mut c_int, expected: c_int) -> c_int {
3648 let r = sys_futex(addr, FUTEX_WAIT, expected, null_mut(), null_mut(), 0);
3649 if r < 0 { let e = (-r) as c_int; if e == EAGAIN { 0 } else { e } } else { 0 }
3650}
3651
3652unsafe fn futex_wake(addr: *mut c_int, count: c_int) {
3653 let c = if count < 0 { c_int::MAX } else { count };
3654 sys_futex(addr, FUTEX_WAKE, c, null_mut(), null_mut(), 0);
3655}
3656
3657unsafe fn futex_lock_pi(addr: *mut c_int, abs_timeout: *const timespec) -> c_int {
3658 let timeout_ptr = if abs_timeout.is_null() { null_mut() } else { abs_timeout as *mut c_void };
3659 let r = sys_futex(addr, FUTEX_LOCK_PI, 0, timeout_ptr, null_mut(), 0);
3660 if r < 0 { (-r) as c_int } else { 0 }
3661}
3662
3663unsafe fn futex_unlock_pi(addr: *mut c_int) -> c_int {
3664 let r = sys_futex(addr, FUTEX_UNLOCK_PI, 0, null_mut(), null_mut(), 0);
3665 if r < 0 { (-r) as c_int } else { 0 }
3666}
3667
3668#[inline]
3669unsafe fn sys_set_robust_list(head: *mut robust_list_head, len: usize) -> i64 {
3670 <Arch as Syscalls>::syscall2(SYS_SET_ROBUST_LIST, head as i64, len as i64)
3671}
3672
3673unsafe fn futex_timedwait(addr: *mut c_int, expected: c_int, abs_timeout: *const timespec) -> c_int {
3674 if abs_timeout.is_null() { return futex_wait(addr, expected); }
3675 let mut now: timespec = core::mem::zeroed();
3676 if sys_clock_gettime(CLOCK_REALTIME, &mut now) < 0 { return EINVAL; }
3677 let mut rel: timespec = core::mem::zeroed();
3678 rel.tv_sec = (*abs_timeout).tv_sec - now.tv_sec;
3679 rel.tv_nsec = (*abs_timeout).tv_nsec - now.tv_nsec;
3680 if rel.tv_nsec < 0 { rel.tv_sec -= 1; rel.tv_nsec += 1_000_000_000; }
3681 if rel.tv_sec < 0 { return ETIMEDOUT; }
3682 let r = sys_futex(addr, FUTEX_WAIT, expected, &mut rel as *mut timespec as *mut c_void, null_mut(), 0);
3683 if r < 0 { let e = (-r) as c_int; if e == EAGAIN { 0 } else { e } } else { 0 }
3684}
3685
3686unsafe fn a_cas(addr: *mut c_int, expected: c_int, desired: c_int) -> c_int {
3688 let a = &*(addr as *const AtomicI32);
3689 match a.compare_exchange(expected, desired, Ordering::AcqRel, Ordering::Acquire) {
3690 Ok(v) | Err(v) => v,
3691 }
3692}
3693
3694unsafe fn a_store(addr: *mut c_int, val: c_int) {
3695 (*(addr as *const AtomicI32)).store(val, Ordering::Release);
3696}
3697
3698unsafe fn a_load(addr: *const c_int) -> c_int {
3699 (*(addr as *const AtomicI32)).load(Ordering::Acquire)
3700}
3701
3702unsafe fn a_swap(addr: *mut c_int, val: c_int) -> c_int {
3703 (*(addr as *const AtomicI32)).swap(val, Ordering::AcqRel)
3704}
3705
3706unsafe fn a_fetch_add(addr: *mut c_int, val: c_int) -> c_int {
3707 (*(addr as *const AtomicI32)).fetch_add(val, Ordering::AcqRel)
3708}
3709
3710unsafe fn a_fetch_sub(addr: *mut c_int, val: c_int) -> c_int {
3711 (*(addr as *const AtomicI32)).fetch_sub(val, Ordering::AcqRel)
3712}
3713
3714unsafe fn spinlock_lock(lock: *mut c_int, waiters: *mut c_int) {
3715 while a_swap(lock, 1) != 0 {
3716 let mut spins = 100;
3717 while spins > 0 && a_load(lock) != 0 { core::hint::spin_loop(); spins -= 1; }
3718 if a_load(lock) == 0 { continue; }
3719 a_fetch_add(waiters, 1);
3720 futex_wait(lock, 1);
3721 a_fetch_sub(waiters, 1);
3722 }
3723}
3724
3725unsafe fn spinlock_unlock(lock: *mut c_int, waiters: *mut c_int) {
3726 a_store(lock, 0);
3727 if a_load(waiters) > 0 { futex_wake(lock, 1); }
3728}
3729
3730unsafe fn slot_index(slot: *const Thread) -> usize {
3731 let base = core::ptr::addr_of!(THREADS[0]) as usize;
3732 (slot as usize - base) / core::mem::size_of::<Thread>()
3733}
3734
3735unsafe fn release_thread_slot(slot: *const Thread) {
3736 let idx = slot_index(slot);
3737 if idx < MAX_THREADS {
3738 let word = idx / usize::BITS as usize;
3739 let bit = idx % usize::BITS as usize;
3740 SLOT_USED[word].fetch_and(!(1usize << bit), Ordering::AcqRel);
3741 }
3742}
3743
3744unsafe fn alloc_thread_slot() -> Option<&'static mut Thread> {
3745 for word in 0..SLOT_WORDS {
3746 let mut used = SLOT_USED[word].load(Ordering::Acquire);
3747 loop {
3748 let free = !used;
3749 if free == 0 {
3750 break;
3751 }
3752 let bit = free.trailing_zeros() as usize;
3753 let idx = word * usize::BITS as usize + bit;
3754 if idx >= MAX_THREADS {
3755 break;
3756 }
3757 match SLOT_USED[word].compare_exchange_weak(
3758 used,
3759 used | (1usize << bit),
3760 Ordering::AcqRel,
3761 Ordering::Acquire,
3762 ) {
3763 Ok(_) => return Some(&mut THREADS[idx]),
3764 Err(v) => used = v,
3765 }
3766 }
3767 }
3768 None
3769}
3770
3771unsafe fn run_key_dtors(slot: &mut Thread) {
3772 for _ in 0..PTHREAD_DESTRUCTOR_ITERATIONS {
3773 let mut any = false;
3774 for i in 0..PTHREAD_KEYS_MAX {
3775 let val = slot.tsd[i];
3776 if !val.is_null() {
3777 if let Some(dtor) = KEY_DTORS[i] {
3778 slot.tsd[i] = core::ptr::null_mut();
3779 any = true;
3780 dtor(val);
3781 }
3782 }
3783 }
3784 if !any { break; }
3785 }
3786}
3787
3788unsafe extern "C" fn thread_entry(slot: *mut c_void) -> *mut c_void {
3789 let slot = &mut *(slot as *mut Thread);
3790 slot.robust_list.list.next = core::ptr::null_mut();
3793 slot.robust_list.futex_offset = 0;
3794 slot.robust_list.pending = core::ptr::null_mut();
3795 ensure_robust_list(slot);
3796 let mut set: SigSetT = 0;
3797 sigemptyset(&mut set);
3798 sigaddset(&mut set, SIGCANCEL);
3799 pthread_sigmask(SIG_UNBLOCK, &set, core::ptr::null_mut());
3800 let user_fn: unsafe extern "C" fn(*mut c_void) -> *mut c_void =
3801 core::mem::transmute::<usize, _>(slot.user_fn);
3802 let ret = user_fn(slot.user_arg);
3803 run_key_dtors(slot);
3804 slot.result = ret;
3805 a_store(&raw mut slot.detach_state, DT_EXITED);
3806 futex_wake(&raw mut slot.detach_state, 1);
3807 sys_exit_thread(0)
3808}
3809
3810unsafe fn find_thread() -> Option<&'static mut Thread> {
3811 let me = sys_gettid() as c_int;
3812 let base = core::ptr::addr_of_mut!(THREADS[0]);
3813 for i in 0..MAX_THREADS {
3814 let slot = base.add(i);
3815 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3816 return Some(&mut *slot);
3817 }
3818 }
3819 pthread_self();
3821 for i in 0..MAX_THREADS {
3822 let slot = base.add(i);
3823 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3824 return Some(&mut *slot);
3825 }
3826 }
3827 None
3828}
3829
3830#[no_mangle]
3831pub unsafe extern "C" fn pthread_self() -> PthreadT {
3832 let me = sys_gettid() as c_int;
3833 let base = core::ptr::addr_of_mut!(THREADS[0]);
3834 for i in 0..MAX_THREADS {
3835 let slot = base.add(i);
3836 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3837 return slot as PthreadT;
3838 }
3839 }
3840 if let Some(slot) = alloc_thread_slot() {
3842 let slot = slot as *mut Thread;
3843 (*slot).tid = me;
3844 (*slot).detach_state = DT_JOINABLE;
3845 return slot as PthreadT;
3846 }
3847 0
3848}
3849
3850#[no_mangle]
3851pub unsafe extern "C" fn pthread_equal(t1: PthreadT, t2: PthreadT) -> c_int {
3852 (t1 == t2) as c_int
3853}
3854
3855#[no_mangle]
3856pub unsafe extern "C" fn pthread_create(
3857 thread: *mut PthreadT,
3858 attr: *const pthread_attr_t,
3859 start_routine: usize,
3860 arg: *mut c_void,
3861) -> c_int {
3862 if start_routine == 0 || thread.is_null() { return EINVAL; }
3863 let Some(slot_ref) = alloc_thread_slot() else { return EAGAIN; };
3864 let slot = slot_ref as *mut Thread;
3865 let stack_size = if !attr.is_null() {
3866 let s = *((*attr).__i.as_ptr() as *const usize);
3867 if s > 0 { s } else { STACK_SIZE }
3868 } else { STACK_SIZE };
3869 let user_top = if !attr.is_null() {
3871 *((*attr).__i.as_ptr().add(4) as *const *mut c_void)
3872 } else {
3873 core::ptr::null_mut()
3874 };
3875 let stack_owned = user_top.is_null();
3876 let stack = if stack_owned {
3877 sys_mmap(null_mut(), stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
3878 } else {
3879 (user_top as *mut u8).sub(stack_size)
3880 };
3881 if stack == MMAP_FAILED { release_thread_slot(slot); return EAGAIN; }
3882 let tls_total = __rc_tls_block_size();
3883 let mut stack_top = stack.add(stack_size);
3884 let mut tls_owned = true;
3885 let fs_base = if !stack_owned && tls_total > 0 && stack_size > tls_total + 4096 {
3886 let block = ((user_top as usize - tls_total) & !63usize) as *mut u8;
3890 let fs = __rc_init_thread_tls_at(block);
3891 if fs.is_null() {
3892 __rc_create_thread_tls()
3893 } else {
3894 stack_top = block;
3895 tls_owned = false;
3896 fs
3897 }
3898 } else {
3899 __rc_create_thread_tls()
3900 };
3901 if fs_base.is_null() {
3902 if stack_owned { sys_munmap(stack, stack_size); }
3903 release_thread_slot(slot);
3904 return EAGAIN;
3905 }
3906 let tls_base = fs_base.sub(__rc_tls_base_offset());
3907 let tls_size = if tls_owned { tls_total } else { 0 };
3908 (*slot).detach_state = DT_JOINABLE;
3909 (*slot).result = core::ptr::null_mut();
3910 (*slot).cancel = 0;
3911 (*slot).cancel_state = PTHREAD_CANCEL_ENABLE;
3912 (*slot).cancel_type = PTHREAD_CANCEL_DEFERRED;
3913 core::ptr::write_bytes((*slot).tsd.as_mut_ptr(), 0, PTHREAD_KEYS_MAX);
3914 (*slot).tid = 1;
3915 (*slot).user_fn = start_routine;
3916 (*slot).user_arg = arg;
3917 (*slot).stack = stack;
3918 (*slot).stack_size = stack_size;
3919 (*slot).stack_owned = stack_owned;
3920 (*slot).fs_base = fs_base;
3921 (*slot).tls_base = tls_base;
3922 (*slot).tls_size = tls_size;
3923 let tid_ptr = &raw mut (*slot).tid;
3924 let flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD
3925 | CLONE_SYSVSEM | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_SETTLS;
3926 let tid = __rc_clone(thread_entry as *const () as usize, stack_top, flags, slot as *mut c_void, tid_ptr, fs_base as c_ulong, tid_ptr);
3927 if tid < 0 {
3928 (*slot).tid = -1;
3929 if stack_owned { sys_munmap(stack, stack_size); }
3930 if tls_size > 0 { sys_munmap(tls_base, tls_size); }
3931 release_thread_slot(slot);
3932 return EAGAIN;
3933 }
3934 if !attr.is_null() && (*attr).__i[6] == PTHREAD_CREATE_DETACHED {
3935 (*slot).detach_state = DT_DETACHED;
3936 }
3937 *thread = slot as PthreadT;
3938 0
3939}
3940
3941#[no_mangle]
3942pub unsafe extern "C" fn pthread_join(thread: PthreadT, retval: *mut *mut c_void) -> c_int {
3943 let slot = thread as *mut Thread;
3944 if slot.is_null() { return EINVAL; }
3945 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
3946 let tid_ptr = &raw mut (*slot).tid;
3947 loop {
3948 pthread_testcancel();
3949 let tid = core::ptr::read_volatile(tid_ptr);
3950 if tid == 0 { break; }
3951 if tid < 0 { return EINVAL; }
3952 sys_futex(tid_ptr, FUTEX_WAIT, tid, null_mut(), null_mut(), 0);
3953 pthread_testcancel();
3954 }
3955 if !retval.is_null() { *retval = (*slot).result; }
3956 let stack = (*slot).stack;
3957 let stack_size = (*slot).stack_size;
3958 let stack_owned = (*slot).stack_owned;
3959 let tls_base = (*slot).tls_base;
3960 let tls_size = (*slot).tls_size;
3961 (*slot).tid = -1;
3962 (*slot).detach_state = DT_JOINABLE;
3963 (*slot).result = core::ptr::null_mut();
3964 (*slot).stack = core::ptr::null_mut();
3965 (*slot).stack_size = 0;
3966 (*slot).stack_owned = false;
3967 (*slot).fs_base = core::ptr::null_mut();
3968 (*slot).tls_base = core::ptr::null_mut();
3969 (*slot).tls_size = 0;
3970 if stack_owned && !stack.is_null() && stack_size > 0 { sys_munmap(stack, stack_size); }
3971 let _ = (tls_base, tls_size);
3981 release_thread_slot(slot);
3982 0
3983}
3984
3985#[no_mangle]
3986pub unsafe extern "C" fn pthread_detach(thread: PthreadT) -> c_int {
3987 let slot = thread as *mut Thread;
3988 if slot.is_null() { return EINVAL; }
3989 let old = a_cas(&raw mut (*slot).detach_state, DT_JOINABLE, DT_DETACHED);
3990 if old == DT_EXITED {
3991 let stack = (*slot).stack;
3992 let stack_size = (*slot).stack_size;
3993 let stack_owned = (*slot).stack_owned;
3994 let tls_base = (*slot).tls_base;
3995 let tls_size = (*slot).tls_size;
3996 (*slot).tid = -1;
3997 (*slot).stack = core::ptr::null_mut();
3998 (*slot).stack_size = 0;
3999 (*slot).stack_owned = false;
4000 (*slot).fs_base = core::ptr::null_mut();
4001 (*slot).tls_base = core::ptr::null_mut();
4002 (*slot).tls_size = 0;
4003 if stack_owned && !stack.is_null() && stack_size > 0 { sys_munmap(stack, stack_size); }
4004 let _ = (tls_base, tls_size);
4006 release_thread_slot(slot);
4007 }
4008 0
4009}
4010
4011#[no_mangle]
4012pub unsafe extern "C" fn pthread_exit(retval: *mut c_void) -> ! {
4013 if let Some(slot) = find_thread() {
4014 run_cleanup_handlers(slot);
4015 run_key_dtors(slot);
4016 slot.result = retval;
4017 slot.detach_state = DT_EXITED;
4018 futex_wake(&slot.detach_state as *const c_int as *mut c_int, 1);
4019
4020 let mut active = 0usize;
4022 for i in 0..MAX_THREADS {
4023 if THREADS[i].tid > 0 {
4024 active += 1;
4025 }
4026 }
4027 if active == 1 {
4028 exit(0);
4029 }
4030 }
4031 sys_exit_thread(0);
4032}
4033
4034#[no_mangle]
4036pub unsafe extern "C" fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int {
4037 core::ptr::write_bytes(attr, 0, 1);
4038 *((*attr).__i.as_mut_ptr() as *mut usize) = STACK_SIZE;
4039 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = 4096;
4040 (*attr).__i[6] = PTHREAD_CREATE_JOINABLE;
4041 (*attr).__i[7] = PTHREAD_INHERIT_SCHED;
4042 0
4043}
4044#[no_mangle]
4045pub unsafe extern "C" fn pthread_attr_destroy(_attr: *mut pthread_attr_t) -> c_int { 0 }
4046#[no_mangle]
4047pub unsafe extern "C" fn pthread_attr_setdetachstate(attr: *mut pthread_attr_t, s: c_int) -> c_int {
4048 if s != PTHREAD_CREATE_JOINABLE && s != PTHREAD_CREATE_DETACHED { return EINVAL; }
4049 (*attr).__i[6] = s; 0
4050}
4051#[no_mangle]
4052pub unsafe extern "C" fn pthread_attr_getdetachstate(attr: *const pthread_attr_t, s: *mut c_int) -> c_int {
4053 *s = (*attr).__i[6]; 0
4054}
4055#[no_mangle]
4056pub unsafe extern "C" fn pthread_attr_setstacksize(attr: *mut pthread_attr_t, sz: usize) -> c_int {
4057 if sz < 2048 { return EINVAL; }
4058 *((*attr).__i.as_mut_ptr() as *mut usize) = sz;
4059 *((*attr).__i.as_mut_ptr().add(4) as *mut *mut c_void) = core::ptr::null_mut();
4060 0
4061}
4062#[no_mangle]
4063pub unsafe extern "C" fn pthread_attr_getstacksize(attr: *const pthread_attr_t, sz: *mut usize) -> c_int {
4064 *sz = *((*attr).__i.as_ptr() as *const usize); 0
4065}
4066#[no_mangle]
4067pub unsafe extern "C" fn pthread_attr_setstack(attr: *mut pthread_attr_t, addr: *mut c_void, sz: usize) -> c_int {
4068 if sz < 2048 { return EINVAL; }
4069 *((*attr).__i.as_mut_ptr() as *mut usize) = sz;
4070 *((*attr).__i.as_mut_ptr().add(4) as *mut *mut c_void) = (addr as *mut u8).add(sz) as *mut c_void;
4072 0
4073}
4074#[no_mangle]
4075pub unsafe extern "C" fn pthread_attr_getstack(attr: *const pthread_attr_t, addr: *mut *mut c_void, sz: *mut usize) -> c_int {
4076 let size = *((*attr).__i.as_ptr() as *const usize);
4077 *sz = size;
4078 let top = *((*attr).__i.as_ptr().add(4) as *const *mut c_void);
4079 *addr = if top.is_null() {
4080 core::ptr::null_mut()
4081 } else {
4082 (top as *mut u8).sub(size) as *mut c_void
4083 };
4084 0
4085}
4086#[no_mangle]
4087pub unsafe extern "C" fn pthread_attr_setguardsize(attr: *mut pthread_attr_t, sz: usize) -> c_int {
4088 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = sz; 0
4089}
4090#[no_mangle]
4091pub unsafe extern "C" fn pthread_attr_getguardsize(attr: *const pthread_attr_t, sz: *mut usize) -> c_int {
4092 *sz = *((*attr).__i.as_ptr().add(2) as *const usize); 0
4093}
4094#[no_mangle]
4095pub unsafe extern "C" fn pthread_attr_setscope(_attr: *mut pthread_attr_t, scope: c_int) -> c_int {
4096 if scope != PTHREAD_SCOPE_SYSTEM { return EINVAL; }
4097 0
4098}
4099#[no_mangle]
4100pub unsafe extern "C" fn pthread_attr_getscope(_attr: *const pthread_attr_t, scope: *mut c_int) -> c_int {
4101 *scope = PTHREAD_SCOPE_SYSTEM; 0
4102}
4103#[no_mangle]
4104pub unsafe extern "C" fn pthread_attr_setinheritsched(attr: *mut pthread_attr_t, inh: c_int) -> c_int {
4105 if inh != PTHREAD_INHERIT_SCHED && inh != PTHREAD_EXPLICIT_SCHED { return EINVAL; }
4106 (*attr).__i[7] = inh; 0
4107}
4108#[no_mangle]
4109pub unsafe extern "C" fn pthread_attr_getinheritsched(attr: *const pthread_attr_t, inh: *mut c_int) -> c_int {
4110 *inh = (*attr).__i[7]; 0
4111}
4112#[no_mangle]
4113pub unsafe extern "C" fn pthread_attr_setschedpolicy(attr: *mut pthread_attr_t, p: c_int) -> c_int {
4114 (*attr).__i[8] = p; 0
4115}
4116#[no_mangle]
4117pub unsafe extern "C" fn pthread_attr_getschedpolicy(attr: *const pthread_attr_t, p: *mut c_int) -> c_int {
4118 *p = (*attr).__i[8]; 0
4119}
4120#[no_mangle]
4121pub unsafe extern "C" fn pthread_attr_setschedparam(attr: *mut pthread_attr_t, param: *const sched_param) -> c_int {
4122 (*attr).__i[9] = (*param).sched_priority; 0
4123}
4124#[no_mangle]
4125pub unsafe extern "C" fn pthread_attr_getschedparam(attr: *const pthread_attr_t, param: *mut sched_param) -> c_int {
4126 (*param).sched_priority = (*attr).__i[9]; 0
4127}
4128
4129#[no_mangle]
4131pub unsafe extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int {
4132 (*attr).__attr = 0; 0
4133}
4134#[no_mangle]
4135pub unsafe extern "C" fn pthread_mutexattr_destroy(_attr: *mut pthread_mutexattr_t) -> c_int { 0 }
4136#[no_mangle]
4137pub unsafe extern "C" fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, t: c_int) -> c_int {
4138 if (t as c_uint) > 2 { return EINVAL; }
4139 (*attr).__attr = ((*attr).__attr & !3) | t as c_uint; 0
4140}
4141#[no_mangle]
4142pub unsafe extern "C" fn pthread_mutexattr_gettype(attr: *const pthread_mutexattr_t, t: *mut c_int) -> c_int {
4143 *t = ((*attr).__attr & 3) as c_int; 0
4144}
4145#[no_mangle]
4146pub unsafe extern "C" fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, p: c_int) -> c_int {
4147 if (p as c_uint) > 1 { return EINVAL; }
4148 (*attr).__attr = ((*attr).__attr & !128) | ((p as c_uint) << 7); 0
4149}
4150#[no_mangle]
4151pub unsafe extern "C" fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, p: *mut c_int) -> c_int {
4152 *p = (((*attr).__attr >> 7) & 1) as c_int; 0
4153}
4154
4155#[no_mangle]
4156pub unsafe extern "C" fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int {
4157 match protocol {
4158 0 => { (*attr).__attr &= !(MUTEX_PI as c_uint); 0 }
4159 1 => {
4160 let mut lk: c_int = 0;
4161 let r = sys_futex(&raw mut lk, FUTEX_LOCK_PI, 0, null_mut(), null_mut(), 0);
4162 if r < 0 { return (-r) as c_int; }
4163 sys_futex(&raw mut lk, FUTEX_UNLOCK_PI, 0, null_mut(), null_mut(), 0);
4164 (*attr).__attr |= MUTEX_PI as c_uint;
4165 0
4166 }
4167 2 => ENOTSUP,
4168 _ => EINVAL,
4169 }
4170}
4171#[no_mangle]
4172pub unsafe extern "C" fn pthread_mutexattr_getprotocol(attr: *const pthread_mutexattr_t, protocol: *mut c_int) -> c_int {
4173 *protocol = (((*attr).__attr >> 3) & 3) as c_int; 0
4174}
4175
4176const ENOTSUP: c_int = 95;
4177
4178#[no_mangle]
4179pub unsafe extern "C" fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robust: c_int) -> c_int {
4180 if (robust as c_uint) > 1 { return EINVAL; }
4181 if robust != 0 {
4182 (*attr).__attr |= MUTEX_ROBUST as c_uint;
4183 } else {
4184 (*attr).__attr &= !(MUTEX_ROBUST as c_uint);
4185 }
4186 0
4187}
4188#[no_mangle]
4189pub unsafe extern "C" fn pthread_mutexattr_getrobust(attr: *const pthread_mutexattr_t, robust: *mut c_int) -> c_int {
4190 *robust = (((*attr).__attr >> 2) & 1) as c_int; 0
4191}
4192
4193#[no_mangle]
4194pub unsafe extern "C" fn pthread_mutex_consistent(m: *mut pthread_mutex_t) -> c_int {
4195 let old = a_load(&raw const (*m).__i[1]);
4196 let own = old & 0x3fffffff;
4197 if ((*m).__i[0] & MUTEX_ROBUST) == 0 || own == 0 || (old & 0x40000000) == 0 {
4198 return EINVAL;
4199 }
4200 let self_tid = sys_gettid() as c_int;
4201 if own != self_tid { return EPERM; }
4202 a_and(&raw mut (*m).__i[1], !(0x40000000i32));
4203 0
4204}
4205
4206unsafe fn a_and(addr: *mut c_int, val: c_int) {
4207 let a = &*(addr as *const AtomicI32);
4208 a.fetch_and(val, Ordering::AcqRel);
4209}
4210
4211const MUTEX_TYPE_MASK: c_int = 3;
4213const MUTEX_ROBUST: c_int = 4;
4214const MUTEX_PI: c_int = 8;
4215const MUTEX_PSHARED: c_int = 128;
4216
4217unsafe fn ensure_robust_list(slot: &mut Thread) {
4218 if slot.robust_list.futex_offset == 0 {
4219 slot.robust_list.futex_offset = -28;
4220 slot.robust_list.pending = core::ptr::null_mut();
4221 sys_set_robust_list(&mut slot.robust_list, 24);
4222 }
4223}
4224
4225unsafe fn mutex_trylock(m: *mut pthread_mutex_t) -> c_int {
4226 let type_ = (*m).__i[0];
4227 if (type_ & 0x8f) == PTHREAD_MUTEX_NORMAL {
4232 let old = a_cas(&raw mut (*m).__i[1], 0, EBUSY);
4233 return if old == 0 { 0 } else { EBUSY };
4234 }
4235 let base_type = type_ & MUTEX_TYPE_MASK;
4236 let self_tid = sys_gettid() as c_int;
4237 let old = a_load(&raw const (*m).__i[1]);
4238 let own = old & 0x3fffffff;
4239 if own == self_tid {
4240 if (type_ & MUTEX_PI) != 0 && (*m).__i[5] < 0 {
4241 (*m).__i[5] = 0;
4242 return 0;
4243 }
4244 if base_type == PTHREAD_MUTEX_RECURSIVE {
4245 if (*m).__i[5] >= c_int::MAX { return EAGAIN; }
4246 (*m).__i[5] += 1;
4247 return 0;
4248 }
4249 if base_type == PTHREAD_MUTEX_ERRORCHECK { return EDEADLK; }
4250 return EBUSY;
4251 }
4252 if own == 0x3fffffff { return ENOTRECOVERABLE; }
4253 if own != 0 || (old != 0 && (type_ & MUTEX_ROBUST) == 0) { return EBUSY; }
4254 let mut newtid = self_tid;
4255 if (type_ & MUTEX_ROBUST) != 0 {
4256 if (*m).__i[2] != 0 { newtid |= 1i32 << 31; }
4257 newtid |= old & 0x40000000;
4258 }
4259 if a_cas(&raw mut (*m).__i[1], old, newtid) == old {
4260 (*m).__i[5] = 0;
4261 if (type_ & MUTEX_ROBUST) != 0 {
4262 if let Some(slot) = find_thread() {
4263 ensure_robust_list(slot);
4264 let m_next = &raw mut (*m).__i[8] as *mut robust_list;
4265 let head = &mut slot.robust_list.list;
4266 (*m_next).next = head.next;
4267 head.next = m_next;
4268 }
4269 }
4270 if old != 0 { return EOWNERDEAD; }
4271 0
4272 } else { EBUSY }
4273}
4274
4275unsafe fn mutex_lock_internal(m: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4276 let type_ = (*m).__i[0];
4277 if (type_ & 0x8f) == PTHREAD_MUTEX_NORMAL && a_cas(&raw mut (*m).__i[1], 0, EBUSY) == 0 {
4278 return 0;
4279 }
4280 let r = mutex_trylock(m);
4281 if r != EBUSY { return r; }
4282 if (type_ & MUTEX_PI) != 0 {
4283 let timeout_ptr = if abs_timeout.is_null() { core::ptr::null() } else { abs_timeout };
4284 loop {
4285 let e = futex_lock_pi(&raw mut (*m).__i[1], timeout_ptr);
4286 match e {
4287 0 => {
4288 if (type_ & MUTEX_ROBUST) != 0 && (((*m).__i[1] & 0x40000000) != 0 || (*m).__i[2] != 0) {
4289 (*m).__i[5] = -1;
4290 let _ = mutex_trylock(m);
4291 return EOWNERDEAD;
4292 }
4293 if (type_ & MUTEX_ROBUST) == 0 && (((*m).__i[1] & 0x40000000) != 0 || (*m).__i[2] != 0) {
4294 (*m).__i[2] = -1;
4295 futex_unlock_pi(&raw mut (*m).__i[1]);
4296 return EBUSY;
4297 }
4298 (*m).__i[5] = -1;
4299 let r2 = mutex_trylock(m);
4300 if r2 == 0 { return 0; }
4301 return r2;
4302 }
4303 EINTR => continue,
4304 EDEADLK => {
4305 if (type_ & MUTEX_TYPE_MASK) == PTHREAD_MUTEX_ERRORCHECK { return e; }
4306 loop { pause(); }
4307 }
4308 EOWNERDEAD => {
4309 (*m).__i[5] = -1;
4310 let _ = mutex_trylock(m);
4311 return EOWNERDEAD;
4312 }
4313 _ => return e,
4314 }
4315 }
4316 }
4317 let mut spins = 100;
4318 while spins > 0 {
4319 let r = mutex_trylock(m);
4320 if r != EBUSY { return r; }
4321 core::hint::spin_loop();
4322 spins -= 1;
4323 }
4324 loop {
4325 let r = mutex_trylock(m);
4326 if r != EBUSY { return r; }
4327 if (type_ & MUTEX_TYPE_MASK) == PTHREAD_MUTEX_ERRORCHECK {
4328 let self_tid = sys_gettid() as c_int;
4329 if (a_load(&raw const (*m).__i[1]) & 0x3fffffff) == self_tid { return EDEADLK; }
4330 }
4331 a_fetch_add(&raw mut (*m).__i[2], 1);
4332 let val = a_load(&raw const (*m).__i[1]);
4333 if val == 0 {
4337 a_fetch_sub(&raw mut (*m).__i[2], 1);
4338 continue;
4339 }
4340 a_cas(&raw mut (*m).__i[1], val, val | (1i32 << 31));
4341 let e = futex_timedwait(&raw mut (*m).__i[1], val | (1i32 << 31), abs_timeout);
4342 a_fetch_sub(&raw mut (*m).__i[2], 1);
4343 if e != 0 && e != EINTR { return e; }
4344 }
4345}
4346
4347#[no_mangle]
4348pub unsafe extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t) -> c_int {
4349 core::ptr::write_bytes(mutex, 0, 1);
4350 if !attr.is_null() { (*mutex).__i[0] = (*attr).__attr as c_int; }
4351 0
4352}
4353#[no_mangle]
4354pub unsafe extern "C" fn pthread_mutex_destroy(_mutex: *mut pthread_mutex_t) -> c_int { 0 }
4355#[no_mangle]
4356pub unsafe extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int {
4357 mutex_lock_internal(mutex, core::ptr::null())
4358}
4359#[no_mangle]
4360pub unsafe extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int {
4361 mutex_trylock(mutex)
4362}
4363#[no_mangle]
4364pub unsafe extern "C" fn pthread_mutex_timedlock(mutex: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4365 mutex_lock_internal(mutex, abs_timeout)
4366}
4367#[no_mangle]
4368pub unsafe extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int {
4369 let type_ = (*mutex).__i[0];
4370 let base_type = type_ & MUTEX_TYPE_MASK;
4371 let old = a_load(&raw const (*mutex).__i[1]);
4372 if base_type != PTHREAD_MUTEX_NORMAL {
4373 let self_tid = sys_gettid() as c_int;
4374 if (old & 0x3fffffff) != self_tid { return EPERM; }
4375 if base_type == PTHREAD_MUTEX_RECURSIVE && (*mutex).__i[5] > 0 {
4376 (*mutex).__i[5] -= 1;
4377 return 0;
4378 }
4379 }
4380 let mut new = 0;
4381 if (type_ & MUTEX_ROBUST) != 0 && (old & 0x40000000) != 0 {
4382 new = 0x7fffffff;
4383 }
4384 if (type_ & MUTEX_PI) != 0 {
4385 if old < 0 || a_cas(&raw mut (*mutex).__i[1], old, new) != old {
4386 if new != 0 { a_store(&raw mut (*mutex).__i[2], -1); }
4387 return futex_unlock_pi(&raw mut (*mutex).__i[1]);
4388 }
4389 return 0;
4390 }
4391 a_store(&raw mut (*mutex).__i[1], new);
4392 if new == 0 && (a_load(&raw const (*mutex).__i[2]) > 0 || old < 0) {
4393 futex_wake(&raw mut (*mutex).__i[1], 1);
4394 }
4395 0
4396}
4397
4398#[no_mangle]
4400pub unsafe extern "C" fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> c_int {
4401 (*attr).__attr = 0; 0
4402}
4403#[no_mangle]
4404pub unsafe extern "C" fn pthread_condattr_destroy(_attr: *mut pthread_condattr_t) -> c_int { 0 }
4405#[no_mangle]
4406pub unsafe extern "C" fn pthread_condattr_setclock(attr: *mut pthread_condattr_t, clk: c_int) -> c_int {
4407 if clk != CLOCK_REALTIME && clk != CLOCK_MONOTONIC { return EINVAL; }
4408 (*attr).__attr = ((*attr).__attr & 0x80000000) | clk as c_uint; 0
4409}
4410#[no_mangle]
4411pub unsafe extern "C" fn pthread_condattr_getclock(attr: *const pthread_condattr_t, clk: *mut c_int) -> c_int {
4412 *clk = ((*attr).__attr & 0x7fffffff) as c_int; 0
4413}
4414#[no_mangle]
4415pub unsafe extern "C" fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, p: c_int) -> c_int {
4416 if (p as c_uint) > 1 { return EINVAL; }
4417 (*attr).__attr = ((*attr).__attr & 0x7fffffff) | ((p as c_uint) << 31); 0
4418}
4419#[no_mangle]
4420pub unsafe extern "C" fn pthread_condattr_getpshared(attr: *const pthread_condattr_t, p: *mut c_int) -> c_int {
4421 *p = ((*attr).__attr >> 31) as c_int; 0
4422}
4423
4424#[no_mangle]
4426pub unsafe extern "C" fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> c_int {
4427 core::ptr::write_bytes(cond, 0, 1);
4428 if !attr.is_null() {
4429 (*cond).__i[4] = ((*attr).__attr & 0x7fffffff) as c_int;
4430 }
4431 0
4432}
4433#[no_mangle]
4434pub unsafe extern "C" fn pthread_cond_destroy(_cond: *mut pthread_cond_t) -> c_int { 0 }
4435#[no_mangle]
4436pub unsafe extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *mut pthread_mutex_t) -> c_int {
4437 pthread_cond_timedwait(cond, mutex, core::ptr::null())
4438}
4439
4440
4441#[no_mangle]
4442pub unsafe extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4443 pthread_testcancel();
4444 let seq_ptr = &raw mut (*cond).__i[2];
4445 let waiters_ptr = &raw mut (*cond).__i[3];
4446 let seq = a_load(seq_ptr);
4447 a_fetch_add(waiters_ptr, 1);
4448 pthread_mutex_unlock(mutex);
4449 let e = futex_timedwait(seq_ptr, seq, abs_timeout);
4450 a_fetch_sub(waiters_ptr, 1);
4451 let r = pthread_mutex_lock(mutex);
4452 if r != 0 { return r; }
4453 if e == EINTR {
4454 pthread_testcancel();
4455 }
4456 if e != 0 && e != EINTR { return e; }
4457 0
4458}
4459#[no_mangle]
4460pub unsafe extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int {
4461 if a_load(&raw const (*cond).__i[3]) == 0 { return 0; }
4462 a_fetch_add(&raw mut (*cond).__i[2], 1);
4463 futex_wake(&raw mut (*cond).__i[2], 1);
4464 0
4465}
4466#[no_mangle]
4467pub unsafe extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int {
4468 if a_load(&raw const (*cond).__i[3]) == 0 { return 0; }
4469 a_fetch_add(&raw mut (*cond).__i[2], 1);
4470 futex_wake(&raw mut (*cond).__i[2], -1);
4471 0
4472}
4473
4474#[no_mangle]
4476pub unsafe extern "C" fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> c_int {
4477 (*attr).__attr = [0; 2]; 0
4478}
4479#[no_mangle]
4480pub unsafe extern "C" fn pthread_rwlockattr_destroy(_attr: *mut pthread_rwlockattr_t) -> c_int { 0 }
4481#[no_mangle]
4482pub unsafe extern "C" fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, p: c_int) -> c_int {
4483 if (p as c_uint) > 1 { return EINVAL; }
4484 (*attr).__attr[0] = ((*attr).__attr[0] & !128) | ((p as c_uint) << 7); 0
4485}
4486#[no_mangle]
4487pub unsafe extern "C" fn pthread_rwlockattr_getpshared(attr: *const pthread_rwlockattr_t, p: *mut c_int) -> c_int {
4488 *p = (((*attr).__attr[0] >> 7) & 1) as c_int; 0
4489}
4490
4491unsafe fn rwlock_tryrdlock(rw: *mut pthread_rwlock_t) -> c_int {
4493 loop {
4494 let val = a_load(&raw const (*rw).__i[0]);
4495 let cnt = val & 0x7fffffff;
4496 if cnt == 0x7fffffff { return EBUSY; }
4497 if cnt == 0x7ffffffe { return EAGAIN; }
4498 if a_cas(&raw mut (*rw).__i[0], val, val + 1) == val { return 0; }
4499 }
4500}
4501unsafe fn rwlock_trywrlock(rw: *mut pthread_rwlock_t) -> c_int {
4502 if a_cas(&raw mut (*rw).__i[0], 0, 0x7fffffff) == 0 { 0 } else { EBUSY }
4503}
4504unsafe fn rwlock_timedrdlock(rw: *mut pthread_rwlock_t, abs_timeout: *const timespec) -> c_int {
4505 let r = rwlock_tryrdlock(rw);
4506 if r != EBUSY { return r; }
4507 let mut spins = 100;
4508 while spins > 0 { let r = rwlock_tryrdlock(rw); if r != EBUSY { return r; } core::hint::spin_loop(); spins -= 1; }
4509 loop {
4510 let r = rwlock_tryrdlock(rw);
4511 if r != EBUSY { return r; }
4512 let val = a_load(&raw const (*rw).__i[0]);
4513 if val & 0x7fffffff != 0x7fffffff { continue; }
4514 a_fetch_add(&raw mut (*rw).__i[1], 1);
4515 a_cas(&raw mut (*rw).__i[0], val, val | (1i32 << 31));
4516 let e = futex_timedwait(&raw mut (*rw).__i[0], val | (1i32 << 31), abs_timeout);
4517 a_fetch_sub(&raw mut (*rw).__i[1], 1);
4518 if e != 0 && e != EINTR { return e; }
4519 }
4520}
4521unsafe fn rwlock_timedwrlock(rw: *mut pthread_rwlock_t, abs_timeout: *const timespec) -> c_int {
4522 let r = rwlock_trywrlock(rw);
4523 if r != EBUSY { return r; }
4524 let mut spins = 100;
4525 while spins > 0 { let r = rwlock_trywrlock(rw); if r != EBUSY { return r; } core::hint::spin_loop(); spins -= 1; }
4526 loop {
4527 let r = rwlock_trywrlock(rw);
4528 if r != EBUSY { return r; }
4529 let val = a_load(&raw const (*rw).__i[0]);
4530 if val == 0 { continue; }
4531 a_fetch_add(&raw mut (*rw).__i[1], 1);
4532 a_cas(&raw mut (*rw).__i[0], val, val | (1i32 << 31));
4533 let e = futex_timedwait(&raw mut (*rw).__i[0], val | (1i32 << 31), abs_timeout);
4534 a_fetch_sub(&raw mut (*rw).__i[1], 1);
4535 if e != 0 && e != EINTR { return e; }
4536 }
4537}
4538
4539#[no_mangle]
4540pub unsafe extern "C" fn pthread_rwlock_init(rw: *mut pthread_rwlock_t, attr: *const pthread_rwlockattr_t) -> c_int {
4541 core::ptr::write_bytes(rw, 0, 1);
4542 if !attr.is_null() { (*rw).__i[2] = (*attr).__attr[0] as c_int & 128; }
4543 0
4544}
4545#[no_mangle]
4546pub unsafe extern "C" fn pthread_rwlock_destroy(_rw: *mut pthread_rwlock_t) -> c_int { 0 }
4547#[no_mangle]
4548pub unsafe extern "C" fn pthread_rwlock_rdlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_timedrdlock(rw, core::ptr::null()) }
4549#[no_mangle]
4550pub unsafe extern "C" fn pthread_rwlock_tryrdlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_tryrdlock(rw) }
4551#[no_mangle]
4552pub unsafe extern "C" fn pthread_rwlock_timedrdlock(rw: *mut pthread_rwlock_t, t: *const timespec) -> c_int { rwlock_timedrdlock(rw, t) }
4553#[no_mangle]
4554pub unsafe extern "C" fn pthread_rwlock_wrlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_timedwrlock(rw, core::ptr::null()) }
4555#[no_mangle]
4556pub unsafe extern "C" fn pthread_rwlock_trywrlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_trywrlock(rw) }
4557#[no_mangle]
4558pub unsafe extern "C" fn pthread_rwlock_timedwrlock(rw: *mut pthread_rwlock_t, t: *const timespec) -> c_int { rwlock_timedwrlock(rw, t) }
4559#[no_mangle]
4560pub unsafe extern "C" fn pthread_rwlock_unlock(rw: *mut pthread_rwlock_t) -> c_int {
4561 loop {
4562 let val = a_load(&raw const (*rw).__i[0]);
4563 let cnt = val & 0x7fffffff;
4564 let new_val = if cnt == 0x7fffffff || cnt == 1 { 0 } else { val - 1 };
4565 if a_cas(&raw mut (*rw).__i[0], val, new_val) == val {
4566 if new_val == 0 && (a_load(&raw const (*rw).__i[1]) > 0 || val < 0) {
4567 futex_wake(&raw mut (*rw).__i[0], cnt);
4568 }
4569 return 0;
4570 }
4571 }
4572}
4573
4574#[no_mangle]
4576pub unsafe extern "C" fn pthread_barrierattr_init(attr: *mut pthread_barrierattr_t) -> c_int { (*attr).__attr = 0; 0 }
4577#[no_mangle]
4578pub unsafe extern "C" fn pthread_barrierattr_destroy(_attr: *mut pthread_barrierattr_t) -> c_int { 0 }
4579#[no_mangle]
4580pub unsafe extern "C" fn pthread_barrierattr_setpshared(attr: *mut pthread_barrierattr_t, p: c_int) -> c_int {
4581 if (p as c_uint) > 1 { return EINVAL; }
4582 (*attr).__attr = p as c_uint; 0
4583}
4584#[no_mangle]
4585pub unsafe extern "C" fn pthread_barrierattr_getpshared(attr: *const pthread_barrierattr_t, p: *mut c_int) -> c_int {
4586 *p = (*attr).__attr as c_int; 0
4587}
4588
4589#[no_mangle]
4591pub unsafe extern "C" fn pthread_barrier_init(b: *mut pthread_barrier_t, _attr: *const pthread_barrierattr_t, count: c_uint) -> c_int {
4592 if count == 0 { return EINVAL; }
4593 core::ptr::write_bytes(b, 0, 1);
4594 (*b).__i[2] = count as c_int - 1;
4595 0
4596}
4597#[no_mangle]
4598pub unsafe extern "C" fn pthread_barrier_destroy(_b: *mut pthread_barrier_t) -> c_int { 0 }
4599#[no_mangle]
4600pub unsafe extern "C" fn pthread_barrier_wait(b: *mut pthread_barrier_t) -> c_int {
4601 let limit = (*b).__i[2];
4602 if limit == 0 { return PTHREAD_BARRIER_SERIAL_THREAD; }
4603 spinlock_lock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4604 let arrived = a_load(&raw const (*b).__i[3]) + 1;
4605 a_store(&raw mut (*b).__i[3], arrived);
4606 if arrived > limit {
4607 a_store(&raw mut (*b).__i[3], 0);
4608 let gen = a_load(&raw const (*b).__i[4]);
4609 a_store(&raw mut (*b).__i[4], gen + 1);
4610 spinlock_unlock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4611 futex_wake(&raw mut (*b).__i[4], -1);
4612 return PTHREAD_BARRIER_SERIAL_THREAD;
4613 }
4614 let gen = a_load(&raw const (*b).__i[4]);
4615 spinlock_unlock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4616 while a_load(&raw const (*b).__i[4]) == gen {
4617 futex_wait(&raw mut (*b).__i[4], gen);
4618 }
4619 0
4620}
4621
4622#[no_mangle]
4624pub unsafe extern "C" fn pthread_spin_init(s: *mut pthread_spinlock_t, _pshared: c_int) -> c_int { a_store(s, 0); 0 }
4625#[no_mangle]
4626pub unsafe extern "C" fn pthread_spin_destroy(_s: *mut pthread_spinlock_t) -> c_int { 0 }
4627#[no_mangle]
4628pub unsafe extern "C" fn pthread_spin_lock(s: *mut pthread_spinlock_t) -> c_int {
4629 while a_load(s) != 0 || a_cas(s, 0, EBUSY) != 0 { core::hint::spin_loop(); }
4630 0
4631}
4632#[no_mangle]
4633pub unsafe extern "C" fn pthread_spin_trylock(s: *mut pthread_spinlock_t) -> c_int { a_cas(s, 0, EBUSY) }
4634#[no_mangle]
4635pub unsafe extern "C" fn pthread_spin_unlock(s: *mut pthread_spinlock_t) -> c_int { a_store(s, 0); 0 }
4636
4637#[no_mangle]
4639pub unsafe extern "C" fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int {
4640 if value > SEM_VALUE_MAX as c_uint { return EINVAL; }
4641 (*sem).__val[0] = value as c_int;
4642 (*sem).__val[1] = 0;
4643 (*sem).__val[2] = if pshared != 0 { 0 } else { 128 };
4644 0
4645}
4646#[no_mangle]
4647pub unsafe extern "C" fn sem_destroy(_sem: *mut sem_t) -> c_int { 0 }
4648
4649unsafe fn sem_trywait_internal(sem: *mut sem_t) -> c_int {
4650 loop {
4651 let val = a_load(&raw const (*sem).__val[0]);
4652 if val & SEM_VALUE_MAX == 0 { return EAGAIN; }
4653 if a_cas(&raw mut (*sem).__val[0], val, val - 1) == val { return 0; }
4654 }
4655}
4656
4657#[no_mangle]
4658pub unsafe extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int {
4659 if sem_trywait_internal(sem) == 0 { 0 } else { ERRNO!() = EAGAIN; -1 }
4660}
4661#[no_mangle]
4662pub unsafe extern "C" fn sem_wait(sem: *mut sem_t) -> c_int {
4663 pthread_testcancel();
4664 if sem_trywait_internal(sem) == 0 { return 0; }
4665 let mut spins = 100;
4666 while spins > 0 { if sem_trywait_internal(sem) == 0 { return 0; } core::hint::spin_loop(); spins -= 1; }
4667 loop {
4668 pthread_testcancel();
4669 if sem_trywait_internal(sem) == 0 { return 0; }
4670 let val = a_load(&raw const (*sem).__val[0]);
4671 if val & SEM_VALUE_MAX != 0 { continue; }
4672 a_cas(&raw mut (*sem).__val[0], val, val | (1i32 << 31));
4673 a_fetch_add(&raw mut (*sem).__val[1], 1);
4674 futex_wait(&raw mut (*sem).__val[0], 1i32 << 31);
4675 a_fetch_sub(&raw mut (*sem).__val[1], 1);
4676 }
4677}
4678#[no_mangle]
4679pub unsafe extern "C" fn sem_timedwait(sem: *mut sem_t, abs_timeout: *const timespec) -> c_int {
4680 pthread_testcancel();
4681 if sem_trywait_internal(sem) == 0 { return 0; }
4682 let mut spins = 100;
4683 while spins > 0 { if sem_trywait_internal(sem) == 0 { return 0; } core::hint::spin_loop(); spins -= 1; }
4684 loop {
4685 pthread_testcancel();
4686 if sem_trywait_internal(sem) == 0 { return 0; }
4687 let val = a_load(&raw const (*sem).__val[0]);
4688 if val & SEM_VALUE_MAX != 0 { continue; }
4689 a_cas(&raw mut (*sem).__val[0], val, val | (1i32 << 31));
4690 a_fetch_add(&raw mut (*sem).__val[1], 1);
4691 let e = futex_timedwait(&raw mut (*sem).__val[0], 1i32 << 31, abs_timeout);
4692 a_fetch_sub(&raw mut (*sem).__val[1], 1);
4693 if e != 0 && e != EINTR { ERRNO!() = e; return -1; }
4694 }
4695}
4696#[no_mangle]
4697pub unsafe extern "C" fn sem_post(sem: *mut sem_t) -> c_int {
4698 loop {
4699 let val = a_load(&raw const (*sem).__val[0]);
4700 if (val & SEM_VALUE_MAX) == SEM_VALUE_MAX { ERRNO!() = EOVERFLOW; return -1; }
4701 let mut new = val + 1;
4702 let waiters = a_load(&raw const (*sem).__val[1]);
4703 if waiters <= 1 { new &= !(1i32 << 31); }
4704 if a_cas(&raw mut (*sem).__val[0], val, new) == val {
4705 if val < 0 || waiters > 0 {
4706 futex_wake(&raw mut (*sem).__val[0], if waiters > 1 { 1 } else { -1 });
4707 }
4708 return 0;
4709 }
4710 }
4711}
4712#[no_mangle]
4713pub unsafe extern "C" fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int {
4714 *sval = a_load(&raw const (*sem).__val[0]) & SEM_VALUE_MAX;
4715 0
4716}
4717
4718const NAME_MAX: usize = 255;
4723const SEM_NSEMS_MAX: usize = 256;
4724
4725static SEMTAB_LOCK: AtomicI32 = AtomicI32::new(0);
4727
4728struct SemEntry {
4729 ino: u64,
4730 sem: *mut sem_t,
4731 refcnt: u32,
4732}
4733
4734static mut SEMTAB: [SemEntry; SEM_NSEMS_MAX] = {
4736 const ZERO: SemEntry = SemEntry { ino: 0, sem: core::ptr::null_mut(), refcnt: 0 };
4737 [ZERO; SEM_NSEMS_MAX]
4738};
4739
4740unsafe fn semtab_lock() {
4741 while SEMTAB_LOCK.compare_exchange_weak(0, 1, Ordering::Acquire, Ordering::Relaxed).is_err() {
4742 core::hint::spin_loop();
4743 }
4744}
4745
4746unsafe fn semtab_unlock() {
4747 SEMTAB_LOCK.store(0, Ordering::Release);
4748}
4749
4750unsafe fn shm_mapname(name: *const c_char, buf: *mut u8) -> c_int {
4753 let mut p = name;
4754 while *p == b'/' as c_char { p = p.add(1); }
4756 let start = p;
4757 while *p != 0 && *p != b'/' as c_char { p = p.add(1); }
4759 let len = p.offset_from(start) as usize;
4760 if len == 0 || *p != 0 {
4762 ERRNO!() = EINVAL;
4763 return -1;
4764 }
4765 if len == 1 && *start == b'.' as c_char {
4766 ERRNO!() = EINVAL;
4767 return -1;
4768 }
4769 if len == 2 && *start == b'.' as c_char && *start.add(1) == b'.' as c_char {
4770 ERRNO!() = EINVAL;
4771 return -1;
4772 }
4773 if len > NAME_MAX {
4774 ERRNO!() = ENAMETOOLONG;
4775 return -1;
4776 }
4777 let prefix = b"/dev/shm/\0";
4779 let mut i = 0;
4780 while prefix[i] != 0 {
4781 *buf.add(i) = prefix[i];
4782 i += 1;
4783 }
4784 let mut j = 0;
4785 while j < len {
4786 *buf.add(i + j) = *start.add(j) as u8;
4787 j += 1;
4788 }
4789 *buf.add(i + j) = 0;
4790 (i + j) as c_int
4791}
4792
4793#[no_mangle]
4794pub unsafe extern "C" fn shm_open(name: *const c_char, flags: c_int, mode: mode_t) -> c_int {
4795 let mut buf = [0u8; 16 + NAME_MAX + 1];
4796 if shm_mapname(name, buf.as_mut_ptr()) < 0 { return -1; }
4797 let fd = sys_open(buf.as_ptr(), (flags | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, mode as i64);
4798 if fd < 0 { ERRNO!() = (-fd) as c_int; return -1; }
4799 fd as c_int
4800}
4801
4802#[no_mangle]
4803pub unsafe extern "C" fn shm_unlink(name: *const c_char) -> c_int {
4804 let mut buf = [0u8; 16 + NAME_MAX + 1];
4805 if shm_mapname(name, buf.as_mut_ptr()) < 0 { return -1; }
4806 let r = sys_unlink(buf.as_ptr());
4807 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
4808 0
4809}
4810
4811#[no_mangle]
4812pub unsafe extern "C" fn sem_open(name: *const c_char, flags: c_int, mut args: ...) -> *mut sem_t {
4813 let mut buf = [0u8; 16 + NAME_MAX + 1];
4814 if shm_mapname(name, buf.as_mut_ptr()).is_negative() {
4815 return core::ptr::null_mut(); }
4817
4818 let oflags = flags & (O_CREAT | O_EXCL);
4819
4820 semtab_lock();
4821
4822 let mut slot: c_int = -1;
4824 for i in 0..SEMTAB_LEN {
4825 if SEMTAB[i].sem.is_null() && slot < 0 { slot = i as c_int; }
4826 }
4827 if slot < 0 {
4828 ERRNO!() = EMFILE;
4829 semtab_unlock();
4830 return core::ptr::null_mut();
4831 }
4832 SEMTAB[slot as usize].sem = !0usize as *mut sem_t; semtab_unlock();
4835
4836 let mut mode: mode_t = 0;
4838 let mut value: c_uint = 0;
4839 if oflags & O_CREAT != 0 {
4840 mode = args.next_arg::<mode_t>() & 0o666;
4841 value = args.next_arg::<c_uint>();
4842 if value > SEM_VALUE_MAX as c_uint {
4843 ERRNO!() = EINVAL;
4844 semtab_lock();
4845 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4846 semtab_unlock();
4847 return core::ptr::null_mut();
4848 }
4849 }
4850
4851 if oflags != O_CREAT | O_EXCL {
4853 let fd = sys_open(buf.as_ptr(), (O_RDWR | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, 0);
4854 if fd >= 0 {
4855 let map = sys_mmap(
4856 core::ptr::null_mut(),
4857 core::mem::size_of::<sem_t>(),
4858 PROT_READ | PROT_WRITE,
4859 MAP_SHARED,
4860 fd as i32,
4861 0,
4862 );
4863 sys_close(fd);
4864 if map != MMAP_FAILED {
4865 let st_ino = get_ino(fd as c_int, buf.as_ptr());
4866 return sem_register(map as *mut sem_t, st_ino, slot);
4867 }
4868 }
4869 if oflags == 0 {
4870 semtab_lock();
4872 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4873 semtab_unlock();
4874 return core::ptr::null_mut();
4875 }
4876 }
4877
4878 let mut tmp = [0u8; 32];
4880 let tmpname = b"/dev/shm/tmp-XXXXXX\0";
4881 tmp[..tmpname.len()].copy_from_slice(tmpname);
4882 let mut ts: timespec = core::mem::zeroed();
4884 sys_clock_gettime(0, &mut ts);
4885 let mut n = ts.tv_nsec;
4887 let mut pos = tmpname.len() - 1;
4888 tmp[pos] = 0;
4889 pos -= 1;
4890 loop {
4891 tmp[pos] = b'0' + (n % 10) as u8;
4892 n /= 10;
4893 if n == 0 || pos == 0 { break; }
4894 pos -= 1;
4895 }
4896 let tmp_path = tmp.as_ptr();
4898
4899 let mut newsem: sem_t = core::mem::zeroed();
4900 newsem.__val[0] = value as c_int;
4901 newsem.__val[1] = 0;
4902 newsem.__val[2] = 128; loop {
4905 let fd = sys_open(tmp_path as *const u8, (O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC | O_NONBLOCK) as i64, mode as i64);
4906 if fd < 0 {
4907 if (-fd) as c_int == EEXIST { continue; }
4908 semtab_lock();
4909 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4910 semtab_unlock();
4911 return core::ptr::null_mut();
4912 }
4913 let written = sys_write(fd, &newsem as *const sem_t as *const u8, core::mem::size_of::<sem_t>());
4914 if written != core::mem::size_of::<sem_t>() as i64 {
4915 sys_close(fd);
4916 sys_unlink(tmp_path);
4917 semtab_lock();
4918 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4919 semtab_unlock();
4920 return core::ptr::null_mut();
4921 }
4922 let map = sys_mmap(
4923 core::ptr::null_mut(),
4924 core::mem::size_of::<sem_t>(),
4925 PROT_READ | PROT_WRITE,
4926 MAP_SHARED,
4927 fd as i32,
4928 0,
4929 );
4930 sys_close(fd);
4931 if map == MMAP_FAILED {
4932 sys_unlink(tmp_path);
4933 semtab_lock();
4934 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4935 semtab_unlock();
4936 return core::ptr::null_mut();
4937 }
4938 let r = sys_linkat(AT_FDCWD, tmp_path, AT_FDCWD, buf.as_ptr(), 0);
4940 let e = if r < 0 { (-r) as c_int } else { 0 };
4941 sys_unlink(tmp_path);
4942 if e == 0 {
4943 let st_ino = get_ino(-1, buf.as_ptr());
4944 return sem_register(map as *mut sem_t, st_ino, slot);
4945 }
4946 sys_munmap(map, core::mem::size_of::<sem_t>());
4947 if e != EEXIST || oflags == O_CREAT | O_EXCL {
4948 ERRNO!() = e;
4949 semtab_lock();
4950 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4951 semtab_unlock();
4952 return core::ptr::null_mut();
4953 }
4954 break;
4956 }
4957
4958 let fd = sys_open(buf.as_ptr(), (O_RDWR | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, 0);
4960 if fd < 0 {
4961 semtab_lock();
4962 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4963 semtab_unlock();
4964 return core::ptr::null_mut();
4965 }
4966 let map = sys_mmap(
4967 core::ptr::null_mut(),
4968 core::mem::size_of::<sem_t>(),
4969 PROT_READ | PROT_WRITE,
4970 MAP_SHARED,
4971 fd as i32,
4972 0,
4973 );
4974 sys_close(fd);
4975 if map == MMAP_FAILED {
4976 semtab_lock();
4977 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4978 semtab_unlock();
4979 return core::ptr::null_mut();
4980 }
4981 let st_ino = get_ino(-1, buf.as_ptr());
4982 sem_register(map as *mut sem_t, st_ino, slot)
4983}
4984
4985unsafe fn get_ino(_fd_hint: c_int, path: *const u8) -> u64 {
4986 let mut st: Stat = core::mem::zeroed();
4987 if sys_newfstatat(AT_FDCWD, path as *const c_char, &mut st as *mut Stat as *mut u8, 0) == 0 {
4988 st.st_ino
4989 } else {
4990 0
4991 }
4992}
4993
4994unsafe fn sem_register(map: *mut sem_t, ino: u64, slot_hint: c_int) -> *mut sem_t {
4995 semtab_lock();
4996 for i in 0..SEMTAB_LEN {
4998 if SEMTAB[i].ino == ino && !SEMTAB[i].sem.is_null() && SEMTAB[i].sem != !0usize as *mut sem_t {
4999 sys_munmap(map as *mut u8, core::mem::size_of::<sem_t>());
5001 SEMTAB[slot_hint as usize].sem = core::ptr::null_mut();
5002 SEMTAB[i].refcnt += 1;
5003 let ret = SEMTAB[i].sem;
5004 semtab_unlock();
5005 return ret;
5006 }
5007 }
5008 SEMTAB[slot_hint as usize].sem = map;
5010 SEMTAB[slot_hint as usize].ino = ino;
5011 SEMTAB[slot_hint as usize].refcnt = 1;
5012 semtab_unlock();
5013 map
5014}
5015
5016const SEMTAB_LEN: usize = SEM_NSEMS_MAX;
5017
5018#[no_mangle]
5019pub unsafe extern "C" fn sem_close(sem: *mut sem_t) -> c_int {
5020 semtab_lock();
5021 for i in 0..SEMTAB_LEN {
5022 if SEMTAB[i].sem == sem {
5023 SEMTAB[i].refcnt -= 1;
5024 if SEMTAB[i].refcnt == 0 {
5025 SEMTAB[i].sem = core::ptr::null_mut();
5026 SEMTAB[i].ino = 0;
5027 semtab_unlock();
5028 sys_munmap(sem as *mut u8, core::mem::size_of::<sem_t>());
5029 return 0;
5030 }
5031 semtab_unlock();
5032 return 0;
5033 }
5034 }
5035 semtab_unlock();
5036 0
5037}
5038
5039#[no_mangle]
5040pub unsafe extern "C" fn sem_unlink(name: *const c_char) -> c_int {
5041 shm_unlink(name)
5042}
5043
5044#[no_mangle]
5046pub unsafe extern "C" fn pthread_once(control: *mut pthread_once_t, init_routine: Option<unsafe extern "C" fn()>) -> c_int {
5047 if a_load(control) == 2 { return 0; }
5048 loop {
5049 match a_cas(control, 0, 1) {
5050 0 => {
5051 if let Some(f) = init_routine { f(); }
5052 if a_swap(control, 2) == 3 { futex_wake(control, -1); }
5053 return 0;
5054 }
5055 1 => { a_cas(control, 1, 3); }
5056 3 => { futex_wait(control, 3); }
5057 _ => { return 0; }
5058 }
5059 }
5060}
5061
5062#[no_mangle]
5064pub unsafe extern "C" fn pthread_key_create(key: *mut pthread_key_t, dtor: Option<unsafe extern "C" fn(*mut c_void)>) -> c_int {
5065 let start = NEXT_KEY.load(Ordering::Relaxed);
5066 let mut j = start;
5067 loop {
5068 if KEY_DTORS[j].is_none() {
5069 KEY_DTORS[j] = dtor;
5070 NEXT_KEY.store((j + 1) % PTHREAD_KEYS_MAX, Ordering::Relaxed);
5071 *key = j as pthread_key_t;
5072 return 0;
5073 }
5074 j = (j + 1) % PTHREAD_KEYS_MAX;
5075 if j == start { return EAGAIN; }
5076 }
5077}
5078#[no_mangle]
5079pub unsafe extern "C" fn pthread_key_delete(key: pthread_key_t) -> c_int {
5080 KEY_DTORS[key as usize] = None;
5081 for i in 0..MAX_THREADS {
5082 if THREADS[i].tid > 0 { THREADS[i].tsd[key as usize] = core::ptr::null_mut(); }
5083 }
5084 0
5085}
5086#[no_mangle]
5087pub unsafe extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void {
5088 if let Some(slot) = find_thread() { slot.tsd[key as usize] } else { core::ptr::null_mut() }
5089}
5090#[no_mangle]
5091pub unsafe extern "C" fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int {
5092 if let Some(slot) = find_thread() {
5093 slot.tsd[key as usize] = value as *mut c_void;
5094 0
5095 } else { EINVAL }
5096}
5097
5098unsafe fn run_cleanup_handlers(slot: &mut Thread) {
5100 let mut cb = slot.cancelbuf;
5101 while !cb.is_null() {
5102 let cur = &*cb;
5103 let f = cur.__f;
5104 let x = cur.__x;
5105 cb = cur.__next;
5106 if let Some(func) = f {
5107 func(x);
5108 }
5109 }
5110 slot.cancelbuf = core::ptr::null_mut();
5111}
5112
5113unsafe fn do_cancel() -> ! {
5114 if let Some(slot) = find_thread() {
5115 run_cleanup_handlers(slot);
5116 slot.result = !0usize as *mut c_void; slot.detach_state = DT_EXITED;
5118 futex_wake(&raw mut slot.detach_state, 1);
5119 }
5120 sys_exit_thread(0);
5121}
5122
5123extern "C" fn cancel_handler(_sig: c_int) {
5124 unsafe {
5125 if let Some(slot) = find_thread() {
5126 if slot.cancel != 0
5130 && slot.cancel_state == PTHREAD_CANCEL_ENABLE
5131 && slot.cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS
5132 {
5133 do_cancel();
5134 }
5135 }
5136 }
5137}
5138
5139static CANCEL_INIT: AtomicI32 = AtomicI32::new(0);
5140
5141unsafe fn ensure_cancel_handler() {
5142 if CANCEL_INIT.swap(1, Ordering::AcqRel) == 0 {
5143 let act = KSigAction {
5144 sa_handler: cancel_handler as *const () as usize,
5145 sa_flags: SA_RESTORER,
5146 sa_restorer: sig_restorer as *const () as usize,
5147 sa_mask: [!0u64],
5148 };
5149 sys_rt_sigaction(SIGCANCEL, &act as *const KSigAction, core::ptr::null_mut(), 8);
5150 }
5151}
5152
5153#[no_mangle]
5154pub unsafe extern "C" fn pthread_cancel(thread: PthreadT) -> c_int {
5155 let slot = thread as *mut Thread;
5156 if slot.is_null() { return EINVAL; }
5157 ensure_cancel_handler();
5158 a_store(&raw mut (*slot).cancel, 1);
5159 let tid = (*slot).tid;
5160 if tid > 0 {
5161 sys_tgkill(sys_getpid() as c_int, tid, SIGCANCEL);
5162 }
5163 0
5164}
5165#[no_mangle]
5166pub unsafe extern "C" fn pthread_setcancelstate(state: c_int, oldstate: *mut c_int) -> c_int {
5167 if state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE { return EINVAL; }
5168 if let Some(slot) = find_thread() {
5169 if !oldstate.is_null() { *oldstate = slot.cancel_state; }
5170 slot.cancel_state = state;
5171 0
5172 } else { EINVAL }
5173}
5174#[no_mangle]
5175pub unsafe extern "C" fn pthread_setcanceltype(type_: c_int, oldtype: *mut c_int) -> c_int {
5176 if type_ != PTHREAD_CANCEL_DEFERRED && type_ != PTHREAD_CANCEL_ASYNCHRONOUS { return EINVAL; }
5177 if let Some(slot) = find_thread() {
5178 if !oldtype.is_null() { *oldtype = slot.cancel_type; }
5179 slot.cancel_type = type_;
5180 0
5181 } else { EINVAL }
5182}
5183#[no_mangle]
5184pub unsafe extern "C" fn pthread_testcancel() {
5185 if let Some(slot) = find_thread() {
5186 if slot.cancel != 0 && slot.cancel_state == PTHREAD_CANCEL_ENABLE {
5187 do_cancel();
5188 }
5189 }
5190}
5191
5192#[no_mangle]
5193pub unsafe extern "C" fn _pthread_cleanup_push(cb: *mut __ptcb, f: Option<unsafe extern "C" fn(*mut c_void)>, x: *mut c_void) {
5194 (*cb).__f = f;
5195 (*cb).__x = x;
5196 if let Some(slot) = find_thread() {
5197 (*cb).__next = slot.cancelbuf;
5198 slot.cancelbuf = cb;
5199 } else {
5200 (*cb).__next = core::ptr::null_mut();
5201 }
5202}
5203
5204#[no_mangle]
5205pub unsafe extern "C" fn _pthread_cleanup_pop(cb: *mut __ptcb, run: c_int) {
5206 if let Some(slot) = find_thread() {
5207 slot.cancelbuf = (*cb).__next;
5208 }
5209 if run != 0 {
5210 if let Some(f) = (*cb).__f {
5211 f((*cb).__x);
5212 }
5213 }
5214}
5215
5216#[no_mangle]
5217pub unsafe extern "C" fn pthread_kill(thread: PthreadT, sig: c_int) -> c_int {
5218 let slot = thread as *mut Thread;
5219 if slot.is_null() { return EINVAL; }
5220 let tid = (*slot).tid;
5221 if tid <= 0 { return EINVAL; }
5222 if sys_tgkill(sys_getpid() as c_int, tid, sig) < 0 { -1 } else { 0 }
5223}
5224
5225#[no_mangle]
5226pub unsafe extern "C" fn pthread_sigmask(how: c_int, set: *const SigSetT, oldset: *mut SigSetT) -> c_int {
5227 sigprocmask(how, set, oldset)
5228}
5229
5230
5231#[repr(C)]
5232pub struct lconv {
5233 pub decimal_point: *mut c_char,
5234 pub thousands_sep: *mut c_char,
5235 pub grouping: *mut c_char,
5236 pub int_curr_symbol: *mut c_char,
5237 pub currency_symbol: *mut c_char,
5238 pub mon_decimal_point: *mut c_char,
5239 pub mon_thousands_sep: *mut c_char,
5240 pub mon_grouping: *mut c_char,
5241 pub positive_sign: *mut c_char,
5242 pub negative_sign: *mut c_char,
5243 pub int_frac_digits: c_char,
5244 pub frac_digits: c_char,
5245 pub p_cs_precedes: c_char,
5246 pub p_sep_by_space: c_char,
5247 pub n_cs_precedes: c_char,
5248 pub n_sep_by_space: c_char,
5249 pub p_sign_posn: c_char,
5250 pub n_sign_posn: c_char,
5251 pub int_p_cs_precedes: c_char,
5252 pub int_p_sep_by_space: c_char,
5253 pub int_n_cs_precedes: c_char,
5254 pub int_n_sep_by_space: c_char,
5255 pub int_p_sign_posn: c_char,
5256 pub int_n_sign_posn: c_char,
5257}
5258
5259static UTF8_NAME: [u8; 6] = [b'U', b'T', b'F', b'-', b'8', 0];
5260static C_NAME: [u8; 2] = [b'C', 0];
5261static mut LOCALE_NAME: *const c_char = C_NAME.as_ptr() as *const c_char;
5262static mut LOCALE_CTYPE_UTF8: bool = true;
5263static mut EMPTY_STR: [c_char; 1] = [0];
5264static mut DECIMAL_POINT: [c_char; 2] = [b'.' as c_char, 0];
5265static mut LCONV: lconv = lconv {
5266 decimal_point: core::ptr::null_mut(),
5267 thousands_sep: core::ptr::null_mut(),
5268 grouping: core::ptr::null_mut(),
5269 int_curr_symbol: core::ptr::null_mut(),
5270 currency_symbol: core::ptr::null_mut(),
5271 mon_decimal_point: core::ptr::null_mut(),
5272 mon_thousands_sep: core::ptr::null_mut(),
5273 mon_grouping: core::ptr::null_mut(),
5274 positive_sign: core::ptr::null_mut(),
5275 negative_sign: core::ptr::null_mut(),
5276 int_frac_digits: (-1i32) as c_char,
5277 frac_digits: (-1i32) as c_char,
5278 p_cs_precedes: (-1i32) as c_char,
5279 p_sep_by_space: (-1i32) as c_char,
5280 n_cs_precedes: (-1i32) as c_char,
5281 n_sep_by_space: (-1i32) as c_char,
5282 p_sign_posn: (-1i32) as c_char,
5283 n_sign_posn: (-1i32) as c_char,
5284 int_p_cs_precedes: (-1i32) as c_char,
5285 int_p_sep_by_space: (-1i32) as c_char,
5286 int_n_cs_precedes: (-1i32) as c_char,
5287 int_n_sep_by_space: (-1i32) as c_char,
5288 int_p_sign_posn: (-1i32) as c_char,
5289 int_n_sign_posn: (-1i32) as c_char,
5290};
5291
5292unsafe fn cstr_contains_ci(s: *const u8, needle: &[u8]) -> bool {
5293 let len = strlen(s as *const c_char) as usize;
5294 let s_slice = core::slice::from_raw_parts(s, len);
5295 if needle.len() > len { return false; }
5296 for i in 0..=len - needle.len() {
5297 if s_slice[i..i + needle.len()].eq_ignore_ascii_case(needle) {
5298 return true;
5299 }
5300 }
5301 false
5302}
5303
5304#[no_mangle]
5305pub unsafe extern "C" fn setlocale(_category: c_int, locale: *const c_char) -> *mut c_char {
5306 if locale.is_null() || *locale == 0 {
5307 return LOCALE_NAME as *mut c_char;
5308 }
5309 let name = locale as *const u8;
5310 if strcmp(name, b"C\0".as_ptr()) == 0 || strcmp(name, b"POSIX\0".as_ptr()) == 0 {
5311 LOCALE_CTYPE_UTF8 = false;
5312 return LOCALE_NAME as *mut c_char;
5313 }
5314 if cstr_contains_ci(name, b"UTF-8") || cstr_contains_ci(name, b"UTF8") {
5315 LOCALE_CTYPE_UTF8 = true;
5316 return LOCALE_NAME as *mut c_char;
5317 }
5318 core::ptr::null_mut()
5319}
5320
5321#[no_mangle]
5322pub unsafe extern "C" fn localeconv() -> *mut lconv {
5323 let empty = core::ptr::addr_of_mut!(EMPTY_STR) as *mut c_char;
5324 let lconv = core::ptr::addr_of_mut!(LCONV);
5325 (*lconv).decimal_point = core::ptr::addr_of_mut!(DECIMAL_POINT) as *mut c_char;
5326 (*lconv).thousands_sep = empty;
5327 (*lconv).grouping = empty;
5328 (*lconv).int_curr_symbol = empty;
5329 (*lconv).currency_symbol = empty;
5330 (*lconv).mon_decimal_point = empty;
5331 (*lconv).mon_thousands_sep = empty;
5332 (*lconv).mon_grouping = empty;
5333 (*lconv).positive_sign = empty;
5334 (*lconv).negative_sign = empty;
5335 lconv
5336}
5337
5338pub type locale_t = *mut c_void;
5339static mut CURRENT_LOCALE: locale_t = LC_GLOBAL_LOCALE;
5340
5341static mut C_LOCALE_STORAGE: c_int = 0;
5342const C_LOCALE: locale_t = core::ptr::addr_of_mut!(C_LOCALE_STORAGE) as locale_t;
5343const LC_GLOBAL_LOCALE: locale_t = usize::MAX as locale_t;
5344
5345#[no_mangle]
5346pub unsafe extern "C" fn newlocale(_mask: c_int, name: *const c_char, base: locale_t) -> locale_t {
5347 if !name.is_null() && *name != 0 {
5348 let n = name as *const u8;
5349 if strcmp(n, b"C\0".as_ptr()) != 0
5350 && strcmp(n, b"POSIX\0".as_ptr()) != 0
5351 {
5352 return core::ptr::null_mut();
5353 }
5354 }
5355 if base.is_null() || base == C_LOCALE || base == LC_GLOBAL_LOCALE {
5356 C_LOCALE
5357 } else {
5358 core::ptr::null_mut()
5359 }
5360}
5361
5362#[no_mangle]
5363pub unsafe extern "C" fn freelocale(_loc: locale_t) {}
5364
5365#[no_mangle]
5366pub unsafe extern "C" fn uselocale(loc: locale_t) -> locale_t {
5367 let old = CURRENT_LOCALE;
5368 if !loc.is_null() {
5369 CURRENT_LOCALE = loc;
5370 }
5371 old
5372}
5373
5374#[no_mangle]
5375pub unsafe extern "C" fn duplocale(loc: locale_t) -> locale_t {
5376 if loc.is_null() {
5377 return core::ptr::null_mut();
5378 }
5379 C_LOCALE
5380}
5381
5382const NL_ITEM_CODESET: c_int = 14;
5383const NL_ITEM_RADIXCHAR: c_int = 0x10000;
5384const NL_ITEM_THOUSEP: c_int = 0x10001;
5385const NL_ITEM_YESEXPR: c_int = 0x50000;
5386const NL_ITEM_NOEXPR: c_int = 0x50001;
5387
5388const C_TIME_STRINGS: &[u8] = b"Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat\0\
5389Sunday\0Monday\0Tuesday\0Wednesday\0Thursday\0Friday\0Saturday\0\
5390Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec\0\
5391January\0February\0March\0April\0May\0June\0July\0August\0\
5392September\0October\0November\0December\0\
5393AM\0PM\0\
5394%a %b %e %T %Y\0%m/%d/%y\0%H:%M:%S\0%I:%M:%S %p\0\
5395\0\0%m/%d/%y\00123456789\0%a %b %e %T %Y\0%H:%M:%S\0";
5396
5397const C_NUMERIC_STRINGS: &[u8] = b".\0\0";
5398const C_MESSAGES_STRINGS: &[u8] = b"^[yY]\0^[nN]\0";
5399
5400unsafe fn langinfo_str(table: *const u8, mut idx: c_int) -> *mut c_char {
5401 let mut p = table;
5402 while idx > 0 {
5403 while *p != 0 { p = p.add(1); }
5404 p = p.add(1);
5405 idx -= 1;
5406 }
5407 p as *mut c_char
5408}
5409
5410#[no_mangle]
5411pub unsafe extern "C" fn nl_langinfo(item: c_int) -> *mut c_char {
5412 if item == NL_ITEM_CODESET {
5413 return if LOCALE_CTYPE_UTF8 {
5414 b"UTF-8\0".as_ptr() as *mut c_char
5415 } else {
5416 b"US-ASCII\0".as_ptr() as *mut c_char
5417 };
5418 }
5419 let cat = item >> 16;
5420 let idx = item & 0xFFFF;
5421 match cat {
5422 1 => {
5423 if idx > 1 { return b"\0".as_ptr() as *mut c_char; }
5424 langinfo_str(C_NUMERIC_STRINGS.as_ptr(), idx)
5425 }
5426 2 => {
5427 if idx > 49 { return b"\0".as_ptr() as *mut c_char; }
5428 langinfo_str(C_TIME_STRINGS.as_ptr(), idx)
5429 }
5430 5 => {
5431 if idx > 1 { return b"\0".as_ptr() as *mut c_char; }
5432 langinfo_str(C_MESSAGES_STRINGS.as_ptr(), idx)
5433 }
5434 _ => b"\0".as_ptr() as *mut c_char,
5435 }
5436}
5437
5438pub type nl_catd = *mut c_void;
5439
5440#[no_mangle]
5441pub unsafe extern "C" fn catopen(_name: *const c_char, _oflag: c_int) -> nl_catd {
5442 !0usize as nl_catd
5443}
5444
5445#[no_mangle]
5446pub unsafe extern "C" fn catclose(_catd: nl_catd) -> c_int { 0 }
5447
5448#[no_mangle]
5449pub unsafe extern "C" fn catgets(catd: nl_catd, _set_id: c_int, _msg_id: c_int, s: *const c_char) -> *mut c_char {
5450 if catd == !0usize as nl_catd { return s as *mut c_char; }
5451 s as *mut c_char
5452}
5453
5454pub type IconvT = *mut c_void;
5455
5456const ENC_UTF8: i32 = 1;
5457const ENC_UTF16LE: i32 = 2;
5458const ENC_UTF16BE: i32 = 3;
5459const ENC_UTF32LE: i32 = 4;
5460const ENC_UTF32BE: i32 = 5;
5461const ENC_WCHAR_T: i32 = 6;
5462const ENC_ASCII: i32 = 7;
5463const ENC_LATIN1: i32 = 8;
5464const ENC_WIN1252: i32 = 9;
5465const ENC_WIN1251: i32 = 10;
5466const ENC_KOI8R: i32 = 11;
5467const ENC_GBK: i32 = 12;
5468const ENC_GB2312: i32 = 13;
5469const ENC_BIG5: i32 = 14;
5470const ENC_EUCJP: i32 = 15;
5471const ENC_SHIFTJIS: i32 = 16;
5472const ENC_ISO8859_2: i32 = 17;
5473const ENC_ISO8859_3: i32 = 18;
5474const ENC_ISO8859_4: i32 = 19;
5475const ENC_ISO8859_5: i32 = 20;
5476const ENC_ISO8859_6: i32 = 21;
5477const ENC_ISO8859_7: i32 = 22;
5478const ENC_ISO8859_8: i32 = 23;
5479const ENC_ISO8859_9: i32 = 24;
5480const ENC_ISO8859_10: i32 = 25;
5481const ENC_ISO8859_11: i32 = 26;
5482const ENC_ISO8859_13: i32 = 27;
5483const ENC_ISO8859_14: i32 = 28;
5484const ENC_ISO8859_15: i32 = 29;
5485const ENC_ISO8859_16: i32 = 30;
5486
5487include!("iconv_iso8859.rs");
5488
5489fn make_cd(from: i32, to: i32) -> IconvT {
5490 ((from as usize) << 16 | (to as usize) << 1 | 1) as IconvT
5491}
5492fn extract_from(cd: IconvT) -> i32 {
5493 ((cd as usize) >> 16) as i32
5494}
5495fn extract_to(cd: IconvT) -> i32 {
5496 (((cd as usize) >> 1) & 0x7fff) as i32
5497}
5498
5499unsafe fn match_name(input: *const u8, target: &[u8]) -> bool {
5500 let mut i = input;
5501 let mut j = 0;
5502 while *i != 0 && j < target.len() {
5503 let mut c = *i;
5504 if !c.is_ascii_alphanumeric() { i = i.add(1); continue; }
5505 c = c.to_ascii_lowercase();
5506 if c != target[j] { return false; }
5507 i = i.add(1);
5508 j += 1;
5509 }
5510 while *i != 0 && !(*i).is_ascii_alphanumeric() { i = i.add(1); }
5511 *i == 0 && j == target.len()
5512}
5513
5514unsafe fn find_encoding(name: *const u8) -> i32 {
5515 if name.is_null() { return -1; }
5516 if match_name(name, b"utf8") || match_name(name, b"utf-8") || match_name(name, b"char") { return ENC_UTF8; }
5517 if match_name(name, b"utf16le") || match_name(name, b"utf-16le") { return ENC_UTF16LE; }
5518 if match_name(name, b"utf16be") || match_name(name, b"utf-16be") { return ENC_UTF16BE; }
5519 if match_name(name, b"utf32le") || match_name(name, b"utf-32le") || match_name(name, b"ucs4le") { return ENC_UTF32LE; }
5520 if match_name(name, b"utf32be") || match_name(name, b"utf-32be") || match_name(name, b"ucs4be") { return ENC_UTF32BE; }
5521 if match_name(name, b"wchart") || match_name(name, b"wchar-t") { return ENC_WCHAR_T; }
5522 if match_name(name, b"ascii") || match_name(name, b"usascii") || match_name(name, b"iso646") { return ENC_ASCII; }
5523 if match_name(name, b"iso88591") || match_name(name, b"iso-8859-1") || match_name(name, b"latin1") { return ENC_LATIN1; }
5524 if match_name(name, b"iso88592") || match_name(name, b"iso-8859-2") { return ENC_ISO8859_2; }
5525 if match_name(name, b"iso88593") || match_name(name, b"iso-8859-3") { return ENC_ISO8859_3; }
5526 if match_name(name, b"iso88594") || match_name(name, b"iso-8859-4") { return ENC_ISO8859_4; }
5527 if match_name(name, b"iso88595") || match_name(name, b"iso-8859-5") { return ENC_ISO8859_5; }
5528 if match_name(name, b"iso88596") || match_name(name, b"iso-8859-6") { return ENC_ISO8859_6; }
5529 if match_name(name, b"iso88597") || match_name(name, b"iso-8859-7") { return ENC_ISO8859_7; }
5530 if match_name(name, b"iso88598") || match_name(name, b"iso-8859-8") { return ENC_ISO8859_8; }
5531 if match_name(name, b"iso88599") || match_name(name, b"iso-8859-9") { return ENC_ISO8859_9; }
5532 if match_name(name, b"iso885910") || match_name(name, b"iso-8859-10") { return ENC_ISO8859_10; }
5533 if match_name(name, b"iso885911") || match_name(name, b"iso-8859-11") || match_name(name, b"tis620") { return ENC_ISO8859_11; }
5534 if match_name(name, b"iso885913") || match_name(name, b"iso-8859-13") { return ENC_ISO8859_13; }
5535 if match_name(name, b"iso885914") || match_name(name, b"iso-8859-14") { return ENC_ISO8859_14; }
5536 if match_name(name, b"iso885915") || match_name(name, b"iso-8859-15") { return ENC_ISO8859_15; }
5537 if match_name(name, b"iso885916") || match_name(name, b"iso-8859-16") { return ENC_ISO8859_16; }
5538 if match_name(name, b"cp1252") || match_name(name, b"windows1252") || match_name(name, b"windows-1252") { return ENC_WIN1252; }
5539 if match_name(name, b"cp1251") || match_name(name, b"windows1251") || match_name(name, b"windows-1251") { return ENC_WIN1251; }
5540 if match_name(name, b"koi8r") || match_name(name, b"koi8-r") { return ENC_KOI8R; }
5541 if match_name(name, b"gbk") || match_name(name, b"cp936") { return ENC_GBK; }
5542 if match_name(name, b"gb2312") { return ENC_GB2312; }
5543 if match_name(name, b"big5") || match_name(name, b"bigfive") || match_name(name, b"cp950") { return ENC_BIG5; }
5544 if match_name(name, b"eucjp") || match_name(name, b"euc-jp") { return ENC_EUCJP; }
5545 if match_name(name, b"shiftjis") || match_name(name, b"sjis") || match_name(name, b"cp932") { return ENC_SHIFTJIS; }
5546 -1
5547}
5548
5549fn uni_to_jis(c: u32) -> u16 {
5550 let mut b = 0usize;
5551 let mut nel = REV_JIS.len();
5552 loop {
5553 let i = nel / 2;
5554 let j = REV_JIS[b + i] as usize;
5555 let row = j / 256;
5556 let col = j % 256;
5557 let d = JIS0208[row * 94 + col] as u32;
5558 if d == c { return (j as u16) + 0x2121; }
5559 if nel == 1 { return 0; }
5560 if c < d { nel /= 2; }
5561 else { b += i; nel -= nel / 2; }
5562 }
5563}
5564
5565unsafe fn iconv_decode(enc: i32, src: *const u8, src_left: usize) -> (u32, usize, c_int) {
5566 if src_left == 0 { return (0, 0, EINVAL); }
5567 match enc {
5568 ENC_UTF8 => {
5569 let c = *src;
5570 if c < 128 { return (c as u32, 1, 0); }
5571 if c < 0xC2 { return (0, 0, EILSEQ); }
5572 if c < 0xE0 {
5573 if src_left < 2 || (*src.add(1) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5574 return (((c as u32 & 0x1F) << 6) | (*src.add(1) as u32 & 0x3F), 2, 0);
5575 }
5576 if c < 0xF0 {
5577 if src_left < 3 || (*src.add(1) & 0xC0) != 0x80 || (*src.add(2) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5578 let cp = ((c as u32 & 0x0F) << 12) | ((*src.add(1) as u32 & 0x3F) << 6) | (*src.add(2) as u32 & 0x3F);
5579 if cp < 0x800 { return (0, 0, EILSEQ); }
5580 return (cp, 3, 0);
5581 }
5582 if c < 0xF8 {
5583 if src_left < 4 || (*src.add(1) & 0xC0) != 0x80 || (*src.add(2) & 0xC0) != 0x80 || (*src.add(3) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5584 let cp = ((c as u32 & 0x07) << 18) | ((*src.add(1) as u32 & 0x3F) << 12) | ((*src.add(2) as u32 & 0x3F) << 6) | (*src.add(3) as u32 & 0x3F);
5585 if cp < 0x10000 || cp >= 0x110000 { return (0, 0, EILSEQ); }
5586 return (cp, 4, 0);
5587 }
5588 (0, 0, EILSEQ)
5589 }
5590 ENC_UTF16LE => {
5591 if src_left < 2 { return (0, 0, EINVAL); }
5592 let c = (*src as u32) | ((*src.add(1) as u32) << 8);
5593 if c >= 0xD800 && c <= 0xDBFF {
5594 if src_left < 4 { return (0, 0, EINVAL); }
5595 let d = (*src.add(2) as u32) | ((*src.add(3) as u32) << 8);
5596 if d < 0xDC00 || d > 0xDFFF { return (0, 0, EILSEQ); }
5597 return (((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000, 4, 0);
5598 }
5599 if c >= 0xDC00 && c <= 0xDFFF { return (0, 0, EILSEQ); }
5600 (c, 2, 0)
5601 }
5602 ENC_UTF16BE => {
5603 if src_left < 2 { return (0, 0, EINVAL); }
5604 let c = ((*src as u32) << 8) | (*src.add(1) as u32);
5605 if c >= 0xD800 && c <= 0xDBFF {
5606 if src_left < 4 { return (0, 0, EINVAL); }
5607 let d = ((*src.add(2) as u32) << 8) | (*src.add(3) as u32);
5608 if d < 0xDC00 || d > 0xDFFF { return (0, 0, EILSEQ); }
5609 return (((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000, 4, 0);
5610 }
5611 if c >= 0xDC00 && c <= 0xDFFF { return (0, 0, EILSEQ); }
5612 (c, 2, 0)
5613 }
5614 ENC_UTF32LE => {
5615 if src_left < 4 { return (0, 0, EINVAL); }
5616 let c = (*src as u32) | ((*src.add(1) as u32) << 8) | ((*src.add(2) as u32) << 16) | ((*src.add(3) as u32) << 24);
5617 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5618 if c >= 0x110000 { return (0, 0, EILSEQ); }
5619 (c, 4, 0)
5620 }
5621 ENC_UTF32BE => {
5622 if src_left < 4 { return (0, 0, EINVAL); }
5623 let c = ((*src as u32) << 24) | ((*src.add(1) as u32) << 16) | ((*src.add(2) as u32) << 8) | (*src.add(3) as u32);
5624 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5625 if c >= 0x110000 { return (0, 0, EILSEQ); }
5626 (c, 4, 0)
5627 }
5628 ENC_WCHAR_T => {
5629 if src_left < 4 { return (0, 0, EINVAL); }
5630 let c = *(src as *const u32);
5631 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5632 if c >= 0x110000 { return (0, 0, EILSEQ); }
5633 (c, 4, 0)
5634 }
5635 ENC_ASCII => {
5636 let c = *src as u32;
5637 if c >= 128 { return (0, 0, EILSEQ); }
5638 (c, 1, 0)
5639 }
5640 ENC_LATIN1 => (*src as u32, 1, 0),
5641 ENC_ISO8859_2 => (iso8859_to_u(&ISO8859_2_TO_U, *src), 1, 0),
5642 ENC_ISO8859_3 => (iso8859_to_u(&ISO8859_3_TO_U, *src), 1, 0),
5643 ENC_ISO8859_4 => (iso8859_to_u(&ISO8859_4_TO_U, *src), 1, 0),
5644 ENC_ISO8859_5 => (iso8859_to_u(&ISO8859_5_TO_U, *src), 1, 0),
5645 ENC_ISO8859_6 => (iso8859_to_u(&ISO8859_6_TO_U, *src), 1, 0),
5646 ENC_ISO8859_7 => (iso8859_to_u(&ISO8859_7_TO_U, *src), 1, 0),
5647 ENC_ISO8859_8 => (iso8859_to_u(&ISO8859_8_TO_U, *src), 1, 0),
5648 ENC_ISO8859_9 => (iso8859_to_u(&ISO8859_9_TO_U, *src), 1, 0),
5649 ENC_ISO8859_10 => (iso8859_to_u(&ISO8859_10_TO_U, *src), 1, 0),
5650 ENC_ISO8859_11 => (iso8859_to_u(&ISO8859_11_TO_U, *src), 1, 0),
5651 ENC_ISO8859_13 => (iso8859_to_u(&ISO8859_13_TO_U, *src), 1, 0),
5652 ENC_ISO8859_14 => (iso8859_to_u(&ISO8859_14_TO_U, *src), 1, 0),
5653 ENC_ISO8859_15 => (iso8859_to_u(&ISO8859_15_TO_U, *src), 1, 0),
5654 ENC_ISO8859_16 => (iso8859_to_u(&ISO8859_16_TO_U, *src), 1, 0),
5655 ENC_WIN1252 => {
5656 let b = *src;
5657 if b < 128 { return (b as u32, 1, 0); }
5658 (WIN1252_TO_U[b as usize - 128], 1, 0)
5659 }
5660 ENC_WIN1251 => {
5661 let b = *src;
5662 if b < 128 { return (b as u32, 1, 0); }
5663 (WIN1251_TO_U[b as usize - 128], 1, 0)
5664 }
5665 ENC_KOI8R => {
5666 let b = *src;
5667 if b < 128 { return (b as u32, 1, 0); }
5668 (KOI8R_TO_U[b as usize - 128], 1, 0)
5669 }
5670 ENC_GBK | ENC_GB2312 => {
5671 let c = *src;
5672 if c < 128 { return (c as u32, 1, 0); }
5673 if c == 128 { return (0x20AC, 1, 0); }
5674 if src_left < 2 { return (0, 0, EINVAL); }
5675 let d = *src.add(1);
5676 if d < 0x40 || d == 0x7F || d > 0xFE { return (0, 0, EILSEQ); }
5677 let row = (c as usize).wrapping_sub(0x81);
5678 if row >= 126 { return (0, 0, EILSEQ); }
5679 let mut col = (d as usize) - 0x40;
5680 if col > 63 { col -= 1; }
5681 let cp = GB18030_TABLE[row * 190 + col] as u32;
5682 if cp == 0 { return (0, 0, EILSEQ); }
5683 (cp, 2, 0)
5684 }
5685 ENC_BIG5 => {
5686 let c = *src;
5687 if c < 128 { return (c as u32, 1, 0); }
5688 if src_left < 2 { return (0, 0, EINVAL); }
5689 let d = *src.add(1);
5690 if d < 0x40 || d == 0x7F || d > 0xFE { return (0, 0, EILSEQ); }
5691 let mut col = (d as usize) - 0x40;
5692 if col > 0x3E { col -= 0x22; }
5693 if c >= 0xA1 && c < 0xFA {
5694 let row = (c as usize) - 0xA1;
5695 if row >= 89 { return (0, 0, EILSEQ); }
5696 let cp = BIG5_TABLE[row * 157 + col] as u32;
5697 if cp == 0 { return (0, 0, EILSEQ); }
5698 return (cp, 2, 0);
5699 }
5700 (0, 0, EILSEQ)
5701 }
5702 ENC_EUCJP => {
5703 let c = *src;
5704 if c < 128 { return (c as u32, 1, 0); }
5705 if c == 0x8E {
5706 if src_left < 2 { return (0, 0, EINVAL); }
5707 let d = *src.add(1);
5708 if d < 0xA1 || d > 0xDF { return (0, 0, EILSEQ); }
5709 return ((d as u32) + 0xFF61 - 0xA1, 2, 0);
5710 }
5711 if c < 0xA1 { return (0, 0, EILSEQ); }
5712 if src_left < 2 { return (0, 0, EINVAL); }
5713 let d = *src.add(1);
5714 if d < 0xA1 || d > 0xFE { return (0, 0, EILSEQ); }
5715 let row = (c as usize) - 0xA1;
5716 let col = (d as usize) - 0xA1;
5717 if row >= 84 || col >= 94 { return (0, 0, EILSEQ); }
5718 let cp = JIS0208[row * 94 + col] as u32;
5719 if cp == 0 { return (0, 0, EILSEQ); }
5720 (cp, 2, 0)
5721 }
5722 ENC_SHIFTJIS => {
5723 let c = *src;
5724 if c < 128 { return (c as u32, 1, 0); }
5725 if c >= 0xA1 && c <= 0xDF { return ((c as u32) + 0xFF61 - 0xA1, 1, 0); }
5726 if src_left < 2 { return (0, 0, EINVAL); }
5727 let d = *src.add(1);
5728 if d < 0x40 || d == 0x7F || d > 0xFC { return (0, 0, EILSEQ); }
5729 let row = if c >= 129 && c <= 159 { (c as usize) - 129 }
5730 else if c >= 224 && c <= 239 { (c as usize) - 193 }
5731 else { return (0, 0, EILSEQ); };
5732 let (col, row_adj) = if d >= 64 && d <= 158 && d != 127 {
5733 let mut dd = d as usize;
5734 if dd > 127 { dd -= 1; }
5735 (dd - 64, row * 2)
5736 } else if d >= 159 && d <= 252 {
5737 ((d as usize) - 159, row * 2 + 1)
5738 } else {
5739 return (0, 0, EILSEQ);
5740 };
5741 if row_adj >= 84 { return (0, 0, EILSEQ); }
5742 let cp = JIS0208[row_adj * 94 + col] as u32;
5743 if cp == 0 { return (0, 0, EILSEQ); }
5744 (cp, 2, 0)
5745 }
5746 _ => (0, 0, EILSEQ),
5747 }
5748}
5749
5750unsafe fn iconv_encode(enc: i32, c: u32, dst: *mut u8, dst_left: usize) -> (usize, c_int) {
5751 match enc {
5752 ENC_UTF8 => {
5753 if c < 0x80 {
5754 if dst_left < 1 { return (0, E2BIG); }
5755 *dst = c as u8; return (1, 0);
5756 }
5757 if c < 0x800 {
5758 if dst_left < 2 { return (0, E2BIG); }
5759 *dst = (0xC0 | (c >> 6)) as u8;
5760 *dst.add(1) = (0x80 | (c & 0x3F)) as u8;
5761 return (2, 0);
5762 }
5763 if c < 0x10000 {
5764 if dst_left < 3 { return (0, E2BIG); }
5765 *dst = (0xE0 | (c >> 12)) as u8;
5766 *dst.add(1) = (0x80 | ((c >> 6) & 0x3F)) as u8;
5767 *dst.add(2) = (0x80 | (c & 0x3F)) as u8;
5768 return (3, 0);
5769 }
5770 if dst_left < 4 { return (0, E2BIG); }
5771 *dst = (0xF0 | (c >> 18)) as u8;
5772 *dst.add(1) = (0x80 | ((c >> 12) & 0x3F)) as u8;
5773 *dst.add(2) = (0x80 | ((c >> 6) & 0x3F)) as u8;
5774 *dst.add(3) = (0x80 | (c & 0x3F)) as u8;
5775 (4, 0)
5776 }
5777 ENC_UTF16LE => {
5778 if c < 0x10000 {
5779 if dst_left < 2 { return (0, E2BIG); }
5780 *dst = (c & 0xFF) as u8;
5781 *dst.add(1) = (c >> 8) as u8;
5782 return (2, 0);
5783 }
5784 if dst_left < 4 { return (0, E2BIG); }
5785 let c = c - 0x10000;
5786 let hi = ((c >> 10) + 0xD800) as u16;
5787 let lo = ((c & 0x3FF) + 0xDC00) as u16;
5788 *dst = (hi & 0xFF) as u8; *dst.add(1) = (hi >> 8) as u8;
5789 *dst.add(2) = (lo & 0xFF) as u8; *dst.add(3) = (lo >> 8) as u8;
5790 (4, 0)
5791 }
5792 ENC_UTF16BE => {
5793 if c < 0x10000 {
5794 if dst_left < 2 { return (0, E2BIG); }
5795 *dst = (c >> 8) as u8;
5796 *dst.add(1) = (c & 0xFF) as u8;
5797 return (2, 0);
5798 }
5799 if dst_left < 4 { return (0, E2BIG); }
5800 let c = c - 0x10000;
5801 let hi = ((c >> 10) + 0xD800) as u16;
5802 let lo = ((c & 0x3FF) + 0xDC00) as u16;
5803 *dst = (hi >> 8) as u8; *dst.add(1) = (hi & 0xFF) as u8;
5804 *dst.add(2) = (lo >> 8) as u8; *dst.add(3) = (lo & 0xFF) as u8;
5805 (4, 0)
5806 }
5807 ENC_UTF32LE => {
5808 if dst_left < 4 { return (0, E2BIG); }
5809 *dst = (c & 0xFF) as u8; *dst.add(1) = ((c >> 8) & 0xFF) as u8;
5810 *dst.add(2) = ((c >> 16) & 0xFF) as u8; *dst.add(3) = (c >> 24) as u8;
5811 (4, 0)
5812 }
5813 ENC_UTF32BE => {
5814 if dst_left < 4 { return (0, E2BIG); }
5815 *dst = (c >> 24) as u8; *dst.add(1) = ((c >> 16) & 0xFF) as u8;
5816 *dst.add(2) = ((c >> 8) & 0xFF) as u8; *dst.add(3) = (c & 0xFF) as u8;
5817 (4, 0)
5818 }
5819 ENC_WCHAR_T => {
5820 if dst_left < 4 { return (0, E2BIG); }
5821 *(dst as *mut u32) = c;
5822 (4, 0)
5823 }
5824 ENC_ASCII => {
5825 if c < 128 {
5826 if dst_left < 1 { return (0, E2BIG); }
5827 *dst = c as u8; return (1, 0);
5828 }
5829 (0, EILSEQ)
5830 }
5831 ENC_LATIN1 => {
5832 if c < 256 {
5833 if dst_left < 1 { return (0, E2BIG); }
5834 *dst = c as u8; return (1, 0);
5835 }
5836 (0, EILSEQ)
5837 }
5838 ENC_ISO8859_2 => {
5839 if let Some(b) = u_to_iso8859(&ISO8859_2_TO_U, c) {
5840 if dst_left < 1 { return (0, E2BIG); }
5841 *dst = b; return (1, 0);
5842 }
5843 (0, EILSEQ)
5844 }
5845 ENC_ISO8859_3 => {
5846 if let Some(b) = u_to_iso8859(&ISO8859_3_TO_U, c) {
5847 if dst_left < 1 { return (0, E2BIG); }
5848 *dst = b; return (1, 0);
5849 }
5850 (0, EILSEQ)
5851 }
5852 ENC_ISO8859_4 => {
5853 if let Some(b) = u_to_iso8859(&ISO8859_4_TO_U, c) {
5854 if dst_left < 1 { return (0, E2BIG); }
5855 *dst = b; return (1, 0);
5856 }
5857 (0, EILSEQ)
5858 }
5859 ENC_ISO8859_5 => {
5860 if let Some(b) = u_to_iso8859(&ISO8859_5_TO_U, c) {
5861 if dst_left < 1 { return (0, E2BIG); }
5862 *dst = b; return (1, 0);
5863 }
5864 (0, EILSEQ)
5865 }
5866 ENC_ISO8859_6 => {
5867 if let Some(b) = u_to_iso8859(&ISO8859_6_TO_U, c) {
5868 if dst_left < 1 { return (0, E2BIG); }
5869 *dst = b; return (1, 0);
5870 }
5871 (0, EILSEQ)
5872 }
5873 ENC_ISO8859_7 => {
5874 if let Some(b) = u_to_iso8859(&ISO8859_7_TO_U, c) {
5875 if dst_left < 1 { return (0, E2BIG); }
5876 *dst = b; return (1, 0);
5877 }
5878 (0, EILSEQ)
5879 }
5880 ENC_ISO8859_8 => {
5881 if let Some(b) = u_to_iso8859(&ISO8859_8_TO_U, c) {
5882 if dst_left < 1 { return (0, E2BIG); }
5883 *dst = b; return (1, 0);
5884 }
5885 (0, EILSEQ)
5886 }
5887 ENC_ISO8859_9 => {
5888 if let Some(b) = u_to_iso8859(&ISO8859_9_TO_U, c) {
5889 if dst_left < 1 { return (0, E2BIG); }
5890 *dst = b; return (1, 0);
5891 }
5892 (0, EILSEQ)
5893 }
5894 ENC_ISO8859_10 => {
5895 if let Some(b) = u_to_iso8859(&ISO8859_10_TO_U, c) {
5896 if dst_left < 1 { return (0, E2BIG); }
5897 *dst = b; return (1, 0);
5898 }
5899 (0, EILSEQ)
5900 }
5901 ENC_ISO8859_11 => {
5902 if let Some(b) = u_to_iso8859(&ISO8859_11_TO_U, c) {
5903 if dst_left < 1 { return (0, E2BIG); }
5904 *dst = b; return (1, 0);
5905 }
5906 (0, EILSEQ)
5907 }
5908 ENC_ISO8859_13 => {
5909 if let Some(b) = u_to_iso8859(&ISO8859_13_TO_U, c) {
5910 if dst_left < 1 { return (0, E2BIG); }
5911 *dst = b; return (1, 0);
5912 }
5913 (0, EILSEQ)
5914 }
5915 ENC_ISO8859_14 => {
5916 if let Some(b) = u_to_iso8859(&ISO8859_14_TO_U, c) {
5917 if dst_left < 1 { return (0, E2BIG); }
5918 *dst = b; return (1, 0);
5919 }
5920 (0, EILSEQ)
5921 }
5922 ENC_ISO8859_15 => {
5923 if let Some(b) = u_to_iso8859(&ISO8859_15_TO_U, c) {
5924 if dst_left < 1 { return (0, E2BIG); }
5925 *dst = b; return (1, 0);
5926 }
5927 (0, EILSEQ)
5928 }
5929 ENC_ISO8859_16 => {
5930 if let Some(b) = u_to_iso8859(&ISO8859_16_TO_U, c) {
5931 if dst_left < 1 { return (0, E2BIG); }
5932 *dst = b; return (1, 0);
5933 }
5934 (0, EILSEQ)
5935 }
5936 ENC_WIN1252 => {
5937 if c < 128 {
5938 if dst_left < 1 { return (0, E2BIG); }
5939 *dst = c as u8; return (1, 0);
5940 }
5941 if c >= 0xA0 && c <= 0xFF && WIN1252_TO_U[c as usize - 128] == c {
5942 if dst_left < 1 { return (0, E2BIG); }
5943 *dst = c as u8; return (1, 0);
5944 }
5945 for i in 0..128usize {
5946 if WIN1252_TO_U[i] == c {
5947 if dst_left < 1 { return (0, E2BIG); }
5948 *dst = (i + 128) as u8; return (1, 0);
5949 }
5950 }
5951 (0, EILSEQ)
5952 }
5953 ENC_WIN1251 => {
5954 if c < 128 {
5955 if dst_left < 1 { return (0, E2BIG); }
5956 *dst = c as u8; return (1, 0);
5957 }
5958 for i in 0..128usize {
5959 if WIN1251_TO_U[i] == c {
5960 if dst_left < 1 { return (0, E2BIG); }
5961 *dst = (i + 128) as u8; return (1, 0);
5962 }
5963 }
5964 (0, EILSEQ)
5965 }
5966 ENC_KOI8R => {
5967 if c < 128 {
5968 if dst_left < 1 { return (0, E2BIG); }
5969 *dst = c as u8; return (1, 0);
5970 }
5971 for i in 0..128usize {
5972 if KOI8R_TO_U[i] == c {
5973 if dst_left < 1 { return (0, E2BIG); }
5974 *dst = (i + 128) as u8; return (1, 0);
5975 }
5976 }
5977 (0, EILSEQ)
5978 }
5979 ENC_GBK | ENC_GB2312 => {
5980 if c < 128 {
5981 if dst_left < 1 { return (0, E2BIG); }
5982 *dst = c as u8; return (1, 0);
5983 }
5984 if c == 0x20AC {
5985 if dst_left < 1 { return (0, E2BIG); }
5986 *dst = 128; return (1, 0);
5987 }
5988 for row in 0..126usize {
5989 for col in 0..190usize {
5990 if GB18030_TABLE[row * 190 + col] as u32 == c {
5991 if dst_left < 2 { return (0, E2BIG); }
5992 *dst = (row + 0x81) as u8;
5993 *dst.add(1) = if col <= 62 { (col + 0x40) as u8 } else { (col + 0x41) as u8 };
5994 return (2, 0);
5995 }
5996 }
5997 }
5998 (0, EILSEQ)
5999 }
6000 ENC_BIG5 => {
6001 if c < 128 {
6002 if dst_left < 1 { return (0, E2BIG); }
6003 *dst = c as u8; return (1, 0);
6004 }
6005 for row in 0..89usize {
6006 for col in 0..157usize {
6007 if BIG5_TABLE[row * 157 + col] as u32 == c {
6008 if dst_left < 2 { return (0, E2BIG); }
6009 *dst = (row + 0xA1) as u8;
6010 *dst.add(1) = if col <= 0x3E { (col + 0x40) as u8 } else { (col + 0x62) as u8 };
6011 return (2, 0);
6012 }
6013 }
6014 }
6015 (0, EILSEQ)
6016 }
6017 ENC_EUCJP => {
6018 if c < 128 {
6019 if dst_left < 1 { return (0, E2BIG); }
6020 *dst = c as u8; return (1, 0);
6021 }
6022 if c >= 0xFF61 && c <= 0xFF9F {
6023 if dst_left < 2 { return (0, E2BIG); }
6024 *dst = 0x8E;
6025 *dst.add(1) = (c - 0xFF61 + 0xA1) as u8;
6026 return (2, 0);
6027 }
6028 let jis = uni_to_jis(c);
6029 if jis == 0 { return (0, EILSEQ); }
6030 if dst_left < 2 { return (0, E2BIG); }
6031 *dst = ((jis >> 8) as u8).wrapping_add(0x80);
6032 *dst.add(1) = ((jis & 0xFF) as u8).wrapping_add(0x80);
6033 (2, 0)
6034 }
6035 ENC_SHIFTJIS => {
6036 if c < 128 {
6037 if dst_left < 1 { return (0, E2BIG); }
6038 *dst = c as u8; return (1, 0);
6039 }
6040 if c >= 0xFF61 && c <= 0xFF9F {
6041 if dst_left < 1 { return (0, E2BIG); }
6042 *dst = (c - 0xFF61 + 0xA1) as u8;
6043 return (1, 0);
6044 }
6045 let jis = uni_to_jis(c);
6046 if jis == 0 { return (0, EILSEQ); }
6047 if dst_left < 2 { return (0, E2BIG); }
6048 let r = (jis >> 8) as usize;
6049 let d = (jis & 0xFF) as usize;
6050 *dst = ((r + 1) / 2 + if r < 95 { 112 } else { 176 }) as u8;
6051 *dst.add(1) = if r % 2 == 1 { (d + 31 + d / 96) as u8 } else { (d + 126) as u8 };
6052 (2, 0)
6053 }
6054 _ => (0, EILSEQ),
6055 }
6056}
6057
6058#[no_mangle]
6059pub unsafe extern "C" fn iconv_open(tocode: *const c_char, fromcode: *const c_char) -> IconvT {
6060 let to = find_encoding(tocode as *const u8);
6061 let from = find_encoding(fromcode as *const u8);
6062 if to < 0 || from < 0 {
6063 ERRNO!() = EINVAL;
6064 return !0usize as IconvT;
6065 }
6066 make_cd(from, to)
6067}
6068
6069#[no_mangle]
6070pub unsafe extern "C" fn iconv(
6071 cd: IconvT,
6072 inbuf: *mut *mut c_char,
6073 inbytesleft: *mut SizeT,
6074 outbuf: *mut *mut c_char,
6075 outbytesleft: *mut SizeT,
6076) -> SizeT {
6077 if cd == !0usize as IconvT {
6078 ERRNO!() = EINVAL;
6079 return !0usize;
6080 }
6081 if inbuf.is_null() || outbuf.is_null() { return 0; }
6082 let from = extract_from(cd);
6083 let to = extract_to(cd);
6084 let mut src = *inbuf as *const u8;
6085 let mut dst = *outbuf as *mut u8;
6086 let mut src_left = *inbytesleft;
6087 let mut dst_left = *outbytesleft;
6088 let mut subst = 0usize;
6089 while src_left > 0 {
6090 let (cp, consumed, err) = iconv_decode(from, src, src_left);
6091 if err != 0 {
6092 if err == EINVAL { break; }
6093 ERRNO!() = err;
6094 return !0usize;
6095 }
6096 let (written, err) = iconv_encode(to, cp, dst, dst_left);
6097 if err != 0 {
6098 if err == E2BIG {
6099 ERRNO!() = E2BIG;
6100 return !0usize;
6101 }
6102 if dst_left < 1 {
6103 ERRNO!() = E2BIG;
6104 return !0usize;
6105 }
6106 *dst = b'*';
6107 dst = dst.add(1);
6108 dst_left -= 1;
6109 subst += 1;
6110 } else {
6111 dst = dst.add(written);
6112 dst_left -= written;
6113 }
6114 src = src.add(consumed);
6115 src_left -= consumed;
6116 }
6117 *inbuf = src as *mut c_char;
6118 *outbuf = dst as *mut c_char;
6119 *inbytesleft = src_left;
6120 *outbytesleft = dst_left;
6121 subst
6122}
6123
6124#[no_mangle]
6125pub unsafe extern "C" fn iconv_close(_cd: IconvT) -> c_int { 0 }
6126
6127#[no_mangle]
6132pub unsafe extern "C" fn write(fd: c_int, buf: *const c_void, count: SizeT) -> SSizeT {
6133 syscall_ret(sys_write(fd as i64, buf as *const u8, count)) as SSizeT
6134}
6135
6136#[no_mangle]
6137pub unsafe extern "C" fn read(fd: c_int, buf: *mut c_void, count: SizeT) -> SSizeT {
6138 syscall_ret(sys_read(fd as i64, buf as *mut u8, count)) as SSizeT
6139}
6140
6141#[no_mangle]
6142pub unsafe extern "C" fn open(path: *const c_char, flags: c_int, mode: c_int) -> c_int {
6143 syscall_ret(sys_open(path as *const u8, flags as i64, mode as i64)) as c_int
6144}
6145
6146#[no_mangle]
6147pub unsafe extern "C" fn close(fd: c_int) -> c_int {
6148 syscall_ret(sys_close(fd as i64)) as c_int
6149}
6150
6151#[no_mangle]
6152pub unsafe extern "C" fn lseek(fd: c_int, offset: i64, whence: c_int) -> i64 {
6153 syscall_ret(sys_lseek(fd as i64, offset, whence as i64))
6154}
6155
6156const O_RDONLY: i32 = 0;
6161const O_WRONLY: i32 = 1;
6162const O_RDWR: i32 = 2;
6163const O_CREAT: i32 = 64;
6164const O_TRUNC: i32 = 512;
6165const O_APPEND: i32 = 1024;
6166const O_EXCL: i32 = 128;
6167const O_NONBLOCK: i32 = 2048;
6168const O_NOFOLLOW: i32 = if cfg!(target_arch = "aarch64") { 0o100000 } else { 0o400000 };
6169const O_DIRECTORY: i32 = if cfg!(target_arch = "aarch64") { 0o40000 } else { 0o200000 };
6170const O_CLOEXEC: i32 = 0x80000;
6171
6172const F_GETFD: i32 = 1;
6173const F_SETFD: i32 = 2;
6174const F_GETFL: i32 = 3;
6175const F_SETFL: i32 = 4;
6176const F_GETLK: i32 = 5;
6177const F_SETLK: i32 = 6;
6178const F_SETLKW: i32 = 7;
6179const F_DUPFD: i32 = 0;
6180const F_DUPFD_CLOEXEC: i32 = 1030;
6181const FD_CLOEXEC: i32 = 1;
6182
6183const TIOCGWINSZ: u32 = 0x5413;
6184
6185#[repr(C)]
6186struct winsize {
6187 ws_row: u16,
6188 ws_col: u16,
6189 ws_xpixel: u16,
6190 ws_ypixel: u16,
6191}
6192
6193#[inline]
6194unsafe fn sys_pipe2(fds: *mut c_int, flags: i32) -> i64 {
6195 <Arch as Syscalls>::syscall2(SYS_PIPE2, fds as i64, flags as i64)
6196}
6197
6198#[inline]
6199unsafe fn sys_dup3(oldfd: i32, newfd: i32, flags: i32) -> i64 {
6200 <Arch as Syscalls>::syscall3(SYS_DUP3, oldfd as i64, newfd as i64, flags as i64)
6201}
6202
6203#[inline]
6204unsafe fn sys_fcntl(fd: i32, cmd: i32, arg: i64) -> i64 {
6205 <Arch as Syscalls>::syscall3(SYS_FCNTL, fd as i64, cmd as i64, arg as i64)
6206}
6207
6208#[inline]
6209unsafe fn sys_ioctl(fd: c_int, request: u32, arg: *mut u8) -> i64 {
6210 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, request as i64, arg as i64)
6211}
6212
6213#[inline]
6214unsafe fn sys_unlinkat(dirfd: i32, path: *const u8, flags: i32) -> i64 {
6215 <Arch as Syscalls>::syscall3(SYS_UNLINKAT, dirfd as i64, path as i64, flags as i64)
6216}
6217
6218#[inline]
6219unsafe fn sys_renameat2(olddirfd: i32, oldpath: *const u8, newdirfd: i32, newpath: *const u8, flags: u32) -> i64 {
6220 <Arch as Syscalls>::syscall5(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)
6221}
6222
6223const UNGET: usize = 8;
6228const F_PERM: u32 = 1;
6229const F_NORD: u32 = 4;
6230const F_NOWR: u32 = 8;
6231const F_EOF: u32 = 16;
6232const F_ERR: u32 = 32;
6233const F_SVB: u32 = 64;
6234const F_APP: u32 = 128;
6235
6236const BUFSIZ: usize = 1024;
6237
6238const _IOFBF: c_int = 0;
6239const _IOLBF: c_int = 1;
6240const _IONBF: c_int = 2;
6241
6242const SEEK_SET: c_int = 0;
6243const SEEK_CUR: c_int = 1;
6244const SEEK_END: c_int = 2;
6245
6246#[repr(C)]
6248pub struct FILE {
6249 flags: c_uint,
6250 rpos: *mut u8,
6251 rend: *mut u8,
6252 close: Option<unsafe extern "C" fn(*mut FILE) -> c_int>,
6253 wend: *mut u8,
6254 wpos: *mut u8,
6255 mustbezero_1: *mut u8,
6256 wbase: *mut u8,
6257 read_fn: Option<unsafe extern "C" fn(*mut FILE, *mut u8, usize) -> usize>,
6258 write_fn: Option<unsafe extern "C" fn(*mut FILE, *const u8, usize) -> usize>,
6259 seek_fn: Option<unsafe extern "C" fn(*mut FILE, i64, c_int) -> i64>,
6260 buf: *mut u8,
6261 buf_size: usize,
6262 prev: *mut FILE,
6263 next: *mut FILE,
6264 fd: c_int,
6265 pipe_pid: c_int,
6266 lockcount: c_long,
6267 mode: c_int,
6268 lock: c_int,
6269 lbf: c_int,
6270 cookie: *mut c_void,
6271 off: i64,
6272 getln_buf: *mut c_char,
6273 mustbezero_2: *mut c_void,
6274 shend: *mut u8,
6275 shlim: i64,
6276 shcnt: i64,
6277 ungotten: [c_int; UNGET],
6278 ungotten_count: c_int,
6279 _eof: c_int,
6280 _err: c_int,
6281}
6282
6283static mut STDIN_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
6284static mut STDOUT_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
6285static mut STDERR_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
6286
6287static mut STDIN_FILE: FILE = FILE {
6288 flags: 0, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
6289 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
6290 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
6291 read_fn: None, write_fn: None, seek_fn: None,
6292 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
6293 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
6294 fd: 0, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
6295 cookie: core::ptr::null_mut(), off: 0,
6296 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
6297 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
6298 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
6299};
6300static mut STDOUT_FILE: FILE = FILE {
6301 flags: F_NOWR as u32 + F_SVB as u32, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
6302 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
6303 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
6304 read_fn: None, write_fn: None, seek_fn: None,
6305 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
6306 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
6307 fd: 1, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
6308 cookie: core::ptr::null_mut(), off: 0,
6309 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
6310 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
6311 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
6312};
6313static mut STDERR_FILE: FILE = FILE {
6314 flags: F_NOWR as u32, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
6315 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
6316 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
6317 read_fn: None, write_fn: None, seek_fn: None,
6318 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
6319 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
6320 fd: 2, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
6321 cookie: core::ptr::null_mut(), off: 0,
6322 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
6323 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
6324 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
6325};
6326
6327#[no_mangle]
6328pub static mut stdin: *mut FILE = &raw mut STDIN_FILE as *mut FILE;
6329#[no_mangle]
6330pub static mut stdout: *mut FILE = &raw mut STDOUT_FILE as *mut FILE;
6331#[no_mangle]
6332pub static mut stderr: *mut FILE = &raw mut STDERR_FILE as *mut FILE;
6333
6334unsafe fn __stdio_init() {
6339 STDIN_FILE.buf = core::ptr::addr_of_mut!(STDIN_BUF) as *mut u8;
6340 STDIN_FILE.buf_size = BUFSIZ;
6341 STDIN_FILE.read_fn = Some(__stdio_read);
6342 STDIN_FILE.write_fn = Some(__stdio_write);
6343 STDIN_FILE.seek_fn = Some(__stdio_seek);
6344 STDOUT_FILE.buf = core::ptr::addr_of_mut!(STDOUT_BUF) as *mut u8;
6345 STDOUT_FILE.buf_size = BUFSIZ;
6346 STDOUT_FILE.lbf = b'\n' as c_int;
6347 STDOUT_FILE.read_fn = Some(__stdio_read);
6348 STDOUT_FILE.write_fn = Some(__stdio_write);
6349 STDOUT_FILE.seek_fn = Some(__stdio_seek);
6350 STDERR_FILE.buf = core::ptr::addr_of_mut!(STDERR_BUF) as *mut u8;
6351 STDERR_FILE.buf_size = BUFSIZ;
6352 STDERR_FILE.read_fn = Some(__stdio_read);
6353 STDERR_FILE.write_fn = Some(__stdio_write);
6354 STDERR_FILE.seek_fn = Some(__stdio_seek);
6355}
6356
6357unsafe fn buf_ptr(f: *mut FILE) -> *mut u8 {
6358 (f as *mut u8).add(core::mem::size_of::<FILE>())
6359}
6360
6361unsafe extern "C" fn __stdio_read(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
6362 let n = sys_read((*f).fd as i64, buf, len);
6363 if n <= 0 {
6364 if n == 0 { (*f).flags |= F_EOF; } else { (*f).flags |= F_ERR; (*f)._err = 1; }
6365 return 0;
6366 }
6367 n as usize
6368}
6369
6370unsafe extern "C" fn __stdio_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
6371 let l = (*f).wpos as usize - (*f).wbase as usize;
6372 let mut iov = [
6373 ((*f).wbase as *const u8, l),
6374 (buf, len),
6375 ];
6376 if iov[0].1 == 0 { iov = [iov[1], (core::ptr::null(), 0)]; }
6377 if (*f).flags & F_APP != 0 {
6378 let _ = sys_lseek((*f).fd as i64, 0, SEEK_END as i64);
6379 }
6380 let mut rem = iov[0].1 + iov[1].1;
6381 let mut idx = 0usize;
6382 while rem > 0 {
6383 let ptr = iov[idx].0;
6384 let cnt = iov[idx].1;
6385 if cnt == 0 { idx += 1; continue; }
6386 let n = sys_write((*f).fd as i64, ptr, cnt);
6387 if n <= 0 {
6388 (*f).wpos = core::ptr::null_mut();
6389 (*f).wbase = core::ptr::null_mut();
6390 (*f).wend = core::ptr::null_mut();
6391 (*f).flags |= F_ERR;
6392 return if iov[idx].0 == buf { 0 } else { len };
6393 }
6394 rem -= n as usize;
6395 iov[idx].0 = iov[idx].0.add(n as usize);
6396 iov[idx].1 -= n as usize;
6397 if iov[idx].1 == 0 { idx += 1; }
6398 }
6399 (*f).wend = (*f).buf.add((*f).buf_size);
6400 (*f).wbase = (*f).buf;
6401 (*f).wpos = (*f).buf;
6402 len
6403}
6404
6405unsafe extern "C" fn __stdio_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
6406 sys_lseek((*f).fd as i64, off, whence as i64)
6407}
6408
6409unsafe fn init_file(
6410 f: *mut FILE,
6411 fd: c_int,
6412 mode: *const c_char,
6413 close_fn: Option<unsafe extern "C" fn(*mut FILE) -> c_int>,
6414 buf_area: *mut u8,
6415 buf_sz: usize,
6416) {
6417 core::ptr::write_bytes(f as *mut u8, 0, core::mem::size_of::<FILE>());
6418 (*f).fd = fd;
6419 (*f).close = close_fn;
6420 (*f).lock = 0;
6421 (*f).lbf = -1;
6422 (*f).buf = buf_area;
6423 (*f).buf_size = buf_sz;
6424 (*f).read_fn = Some(__stdio_read);
6425 (*f).write_fn = Some(__stdio_write);
6426 (*f).seek_fn = Some(__stdio_seek);
6427 let m = *mode;
6428 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
6429 if m == b'r' as c_char && !has_plus {
6430 (*f).flags = F_NORD;
6431 } else if !has_plus {
6432 (*f).flags = F_NOWR;
6433 }
6434}
6435
6436unsafe extern "C" fn __stdio_close(f: *mut FILE) -> c_int {
6437 sys_close((*f).fd as i64);
6438 0
6439}
6440
6441unsafe fn fmodeflags(mode: *const c_char) -> c_int {
6442 let mut flags: c_int;
6443 let m = *mode;
6444 if !strchr(mode as *const u8, b'+' as c_int).is_null() {
6445 flags = O_RDWR;
6446 } else if m == b'r' as c_char {
6447 flags = O_RDONLY;
6448 } else {
6449 flags = O_WRONLY;
6450 }
6451 if !strchr(mode as *const u8, b'x' as c_int).is_null() { flags |= O_EXCL; }
6452 if !strchr(mode as *const u8, b'e' as c_int).is_null() { flags |= O_CLOEXEC; }
6453 if m != b'r' as c_char { flags |= O_CREAT; }
6454 if m == b'w' as c_char { flags |= O_TRUNC; }
6455 if m == b'a' as c_char { flags |= O_APPEND; }
6456 flags
6457}
6458
6459const O_ACCMODE: c_int = O_RDONLY | O_WRONLY | O_RDWR;
6460
6461unsafe fn flush_buf(f: *mut FILE) -> c_int {
6462 if (*f).wpos == (*f).wbase {
6463 if !(*f).wpos.is_null() {
6464 (*f).wend = (*f).buf.add((*f).buf_size);
6465 (*f).wpos = (*f).wbase;
6466 }
6467 return 0;
6468 }
6469 if let Some(wfunc) = (*f).write_fn {
6470 let ret = wfunc(f, core::ptr::null(), 0);
6471 if ret == 0 && (*f).wpos.is_null() { return -1; }
6472 return 0;
6473 }
6474 (*f).flags |= F_ERR;
6475 -1
6476}
6477
6478#[no_mangle]
6483pub unsafe extern "C" fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE {
6484 if filename.is_null() || mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
6485 let m = *mode;
6486 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
6487 ERRNO!() = EINVAL; return core::ptr::null_mut();
6488 }
6489 let flags = fmodeflags(mode);
6490 let fd = sys_open(filename as *const u8, flags as i64, 0o666);
6491 if fd < 0 { ERRNO!() = (-fd) as c_int; return core::ptr::null_mut(); }
6492 fdopen(fd as c_int, mode)
6493}
6494
6495#[no_mangle]
6496pub unsafe extern "C" fn fdopen(fd: c_int, mode: *const c_char) -> *mut FILE {
6497 if fd < 0 || mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
6498 let m = *mode;
6499 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
6500 ERRNO!() = EINVAL; return core::ptr::null_mut();
6501 }
6502 let f = calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
6503 if f.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
6504 let buf = buf_ptr(f);
6505 init_file(f, fd, mode, Some(__stdio_close), buf, BUFSIZ);
6506 if !strchr(mode as *const u8, b'a' as c_int).is_null() { (*f).flags |= F_APP; }
6507 if !strchr(mode as *const u8, b'e' as c_int).is_null() { sys_fcntl(fd, F_SETFD, FD_CLOEXEC as i64); }
6508 if (*f).flags & F_NOWR == 0 {
6509 let mut ws: winsize = core::mem::zeroed();
6510 if sys_ioctl(fd, TIOCGWINSZ, &mut ws as *mut winsize as *mut u8) == 0 {
6511 (*f).lbf = b'\n' as c_int;
6512 }
6513 }
6514 f
6515}
6516
6517#[no_mangle]
6518pub unsafe extern "C" fn freopen(
6519 filename: *const c_char, mode: *const c_char, f: *mut FILE,
6520) -> *mut FILE {
6521 fflush(f);
6522 if (*f).pipe_pid > 0 { let _ = __stdio_close(f); }
6523 if filename.is_null() {
6524 let flags = fmodeflags(mode);
6525 if flags == 0 { return core::ptr::null_mut(); }
6526 let mut fl = flags & !(O_CREAT | O_EXCL | O_CLOEXEC);
6527 if (*f).flags & F_APP != 0 { fl = (fl & !O_ACCMODE) | O_WRONLY | O_APPEND; }
6528 if sys_fcntl((*f).fd, F_SETFL, fl as i64) < 0 { return core::ptr::null_mut(); }
6529 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
6530 if has_plus {
6531 (*f).flags &= !(F_NORD | F_NOWR);
6532 } else if *mode == b'r' as c_char {
6533 (*f).flags = ((*f).flags & !F_NOWR) | F_NORD;
6534 } else {
6535 (*f).flags = ((*f).flags & !F_NORD) | F_NOWR;
6536 }
6537 return f;
6538 }
6539 let new_f = fopen(filename, mode);
6540 if new_f.is_null() { let _ = __stdio_close(f); return core::ptr::null_mut(); }
6541 if (*new_f).fd == (*f).fd {
6542 (*new_f).fd = -1;
6543 } else {
6544 sys_dup3((*new_f).fd, (*f).fd, 0);
6545 let _ = __stdio_close(new_f);
6546 }
6547 (*f).flags = (*new_f).flags;
6548 (*f).rpos = core::ptr::null_mut();
6549 (*f).rend = core::ptr::null_mut();
6550 (*f).wpos = core::ptr::null_mut();
6551 (*f).wbase = core::ptr::null_mut();
6552 (*f).wend = core::ptr::null_mut();
6553 (*f).lbf = (*new_f).lbf;
6554 (*f).pipe_pid = 0;
6555 free(new_f as *mut c_void);
6556 f
6557}
6558
6559#[no_mangle]
6560pub unsafe extern "C" fn fclose(f: *mut FILE) -> c_int {
6561 if f.is_null() { return -1; }
6562 let r = fflush(f);
6563 if let Some(close_fn) = (*f).close { let _ = close_fn(f); }
6564 if r != 0 { -1 } else { 0 }
6565}
6566
6567#[no_mangle]
6572pub unsafe extern "C" fn setvbuf(f: *mut FILE, buf: *mut c_char, mode: c_int, size: usize) -> c_int {
6573 if mode != _IOFBF && mode != _IOLBF && mode != _IONBF { return -1; }
6574 fflush(f);
6575 (*f).rpos = core::ptr::null_mut();
6576 (*f).rend = core::ptr::null_mut();
6577 (*f).wpos = core::ptr::null_mut();
6578 (*f).wbase = core::ptr::null_mut();
6579 (*f).wend = core::ptr::null_mut();
6580 if mode == _IONBF {
6581 (*f).buf_size = 0;
6582 } else if !buf.is_null() && size > 0 {
6583 (*f).buf = buf as *mut u8;
6584 (*f).buf_size = size;
6585 }
6586 (*f).lbf = if mode == _IOLBF { b'\n' as c_int } else { -1 };
6587 0
6588}
6589
6590#[no_mangle]
6591pub unsafe extern "C" fn setbuf(f: *mut FILE, buf: *mut c_char) {
6592 if buf.is_null() { setvbuf(f, core::ptr::null_mut(), _IONBF, 0); }
6593 else { setvbuf(f, buf, _IOFBF, BUFSIZ); }
6594}
6595
6596#[no_mangle]
6597pub unsafe extern "C" fn setbuffer(f: *mut FILE, buf: *mut c_char, size: usize) {
6598 if buf.is_null() { setvbuf(f, core::ptr::null_mut(), _IONBF, 0); }
6599 else { setvbuf(f, buf, _IOFBF, size); }
6600}
6601
6602#[no_mangle]
6603pub unsafe extern "C" fn fflush(f: *mut FILE) -> c_int {
6604 if f.is_null() {
6605 let mut r = 0;
6606 if !stdout.is_null() && !(*stdout).wpos.is_null() && (*stdout).wpos != (*stdout).wbase {
6607 if flush_buf(stdout) != 0 { r = -1; }
6608 }
6609 if !stderr.is_null() && !(*stderr).wpos.is_null() && (*stderr).wpos != (*stderr).wbase {
6610 if flush_buf(stderr) != 0 { r = -1; }
6611 }
6612 return r;
6613 }
6614 if !(*f).wpos.is_null() && (*f).wpos != (*f).wbase {
6615 return flush_buf(f);
6616 }
6617 0
6618}
6619
6620#[no_mangle]
6625pub unsafe extern "C" fn fwide(_f: *mut FILE, mode: c_int) -> c_int { mode }
6626
6627#[no_mangle]
6628pub unsafe extern "C" fn feof(f: *mut FILE) -> c_int { if (*f)._eof != 0 { 1 } else { 0 } }
6629
6630#[no_mangle]
6631pub unsafe extern "C" fn ferror(f: *mut FILE) -> c_int { if (*f)._err != 0 { 1 } else { 0 } }
6632
6633#[no_mangle]
6634pub unsafe extern "C" fn clearerr(f: *mut FILE) { (*f)._eof = 0; (*f)._err = 0; }
6635
6636#[no_mangle]
6637pub unsafe extern "C" fn fileno(f: *mut FILE) -> c_int { (*f).fd }
6638
6639#[no_mangle]
6644pub unsafe extern "C" fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int {
6645 fseeko(stream, offset as i64, whence)
6646}
6647
6648#[no_mangle]
6649pub unsafe extern "C" fn ftell(stream: *mut FILE) -> c_long {
6650 ftello(stream) as c_long
6651}
6652
6653#[no_mangle]
6654pub unsafe extern "C" fn rewind(stream: *mut FILE) {
6655 fseek(stream, 0, SEEK_SET);
6656 (*stream)._eof = 0;
6657 (*stream)._err = 0;
6658}
6659
6660#[no_mangle]
6661pub unsafe extern "C" fn fseeko(stream: *mut FILE, offset: i64, whence: c_int) -> c_int {
6662 if whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END {
6663 ERRNO!() = EINVAL;
6664 return -1;
6665 }
6666 let f = &mut *stream;
6667 let mut adj_offset = offset;
6668 if whence == SEEK_CUR {
6669 if !f.rpos.is_null() {
6670 adj_offset -= f.rend as i64 - f.rpos as i64;
6671 }
6672 adj_offset -= f.ungotten_count as i64;
6673 }
6674 if !f.wpos.is_null() && f.wpos != f.wbase {
6675 if flush_buf(stream) != 0 { return -1; }
6676 }
6677 f.wpos = core::ptr::null_mut();
6678 f.wbase = core::ptr::null_mut();
6679 f.wend = core::ptr::null_mut();
6680 if let Some(sfunc) = f.seek_fn {
6681 let r = sfunc(stream, adj_offset, whence);
6682 if r < 0 { return -1; }
6683 } else {
6684 ERRNO!() = EINVAL;
6685 return -1;
6686 }
6687 f.rpos = core::ptr::null_mut();
6688 f.rend = core::ptr::null_mut();
6689 f._eof = 0;
6690 f.ungotten_count = 0;
6691 0
6692}
6693
6694#[no_mangle]
6695pub unsafe extern "C" fn ftello(stream: *mut FILE) -> i64 {
6696 let f = &mut *stream;
6697 if f.flags & F_APP != 0 && !f.wpos.is_null() && f.wpos != f.wbase {
6698 if fflush(stream) != 0 { return -1; }
6699 }
6700 let sfunc = match f.seek_fn { Some(s) => s, None => return -1 };
6701 let pos = sfunc(stream, 0,
6702 if (f.flags & F_APP) != 0 && !f.wpos.is_null() && f.wpos != f.wbase { SEEK_END } else { SEEK_CUR });
6703 if pos < 0 { return -1; }
6704 let mut pos = pos;
6705 if !f.rpos.is_null() {
6706 pos += f.rpos as i64 - f.rend as i64;
6707 } else if !f.wbase.is_null() {
6708 pos += f.wpos as i64 - f.wbase as i64;
6709 }
6710 pos - f.ungotten_count as i64
6711}
6712
6713#[no_mangle]
6714pub unsafe extern "C" fn fgetpos(stream: *mut FILE, pos: *mut i64) -> c_int {
6715 let off = ftello(stream);
6716 if off < 0 { return -1; }
6717 *pos = off;
6718 0
6719}
6720
6721#[no_mangle]
6722pub unsafe extern "C" fn fsetpos(stream: *mut FILE, pos: *const i64) -> c_int {
6723 fseeko(stream, *pos, SEEK_SET)
6724}
6725
6726#[no_mangle]
6731pub unsafe extern "C" fn fgetc(stream: *mut FILE) -> c_int {
6732 let f = &mut *stream;
6733 if f.ungotten_count > 0 {
6734 f.ungotten_count -= 1;
6735 return f.ungotten[f.ungotten_count as usize];
6736 }
6737 if !f.rpos.is_null() && f.rpos < f.rend {
6738 let c = *f.rpos;
6739 f.rpos = f.rpos.add(1);
6740 return c as c_int;
6741 }
6742 if f._eof != 0 { return -1; }
6743 if let Some(rfunc) = f.read_fn {
6744 if !f.buf.is_null() && f.buf_size > 1 {
6748 let n = rfunc(stream, f.buf, f.buf_size);
6749 if n == 0 {
6750 if f.flags & F_ERR != 0 { f._err = 1; } else { f._eof = 1; }
6751 return -1;
6752 }
6753 f.rpos = f.buf;
6754 f.rend = f.buf.add(n);
6755 let c = *f.rpos;
6756 f.rpos = f.rpos.add(1);
6757 return c as c_int;
6758 }
6759 let mut buf = [0u8; 1];
6760 let n = rfunc(stream, buf.as_mut_ptr(), 1);
6761 if n == 0 {
6762 if f.flags & F_ERR != 0 { f._err = 1; } else { f._eof = 1; }
6763 return -1;
6764 }
6765 buf[0] as c_int
6766 } else {
6767 f._eof = 1;
6768 -1
6769 }
6770}
6771
6772#[no_mangle]
6773pub unsafe extern "C" fn getc(stream: *mut FILE) -> c_int { fgetc(stream) }
6774
6775#[no_mangle]
6776pub unsafe extern "C" fn getchar() -> c_int { fgetc(stdin) }
6777
6778#[no_mangle]
6779pub unsafe extern "C" fn ungetc(c: c_int, stream: *mut FILE) -> c_int {
6780 if c == -1 { return -1; }
6781 let f = &mut *stream;
6782 if f.ungotten_count >= UNGET as c_int { return -1; }
6783 f.ungotten[f.ungotten_count as usize] = c;
6784 f.ungotten_count += 1;
6785 f._eof = 0;
6786 c
6787}
6788
6789#[no_mangle]
6794pub unsafe extern "C" fn fgets(s: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char {
6795 if n <= 0 { return null_mut(); }
6796 let max = (n - 1) as usize;
6797 let mut i = 0usize;
6798 while i < max {
6799 let c = fgetc(stream);
6800 if c == -1 { if i == 0 { return null_mut(); } break; }
6801 *s.add(i) = c as c_char;
6802 i += 1;
6803 if c == b'\n' as c_int { break; }
6804 }
6805 *s.add(i) = 0;
6806 s
6807}
6808
6809#[no_mangle]
6811pub unsafe extern "C" fn gets(s: *mut c_char) -> *mut c_char {
6812 let mut i = 0usize;
6813 loop {
6814 let c = fgetc(stdin);
6815 if c == -1 { if i == 0 { return null_mut(); } break; }
6816 if c == b'\n' as c_int { break; }
6817 *s.add(i) = c as c_char;
6818 i += 1;
6819 }
6820 *s.add(i) = 0;
6821 s
6822}
6823
6824#[no_mangle]
6825pub unsafe extern "C" fn fopen64(filename: *const c_char, mode: *const c_char) -> *mut FILE {
6826 fopen(filename, mode)
6827}
6828
6829const PERROR_BUF_SIZE: usize = 64;
6831static mut PERROR_BUF: [u8; PERROR_BUF_SIZE] = [0; PERROR_BUF_SIZE];
6832
6833#[no_mangle]
6834pub unsafe extern "C" fn perror(msg: *const c_char) {
6835 let fd = (*stderr).fd;
6836 if !msg.is_null() && *msg != 0 {
6837 let len = strlen(msg as *const c_char);
6838 write_str(fd, msg as *const u8, len);
6839 write_str(fd, b": ".as_ptr(), 2);
6840 }
6841 let e = ERRNO!();
6842 let text = strerror(e) as *const u8;
6843 write_str(fd, text, strlen(text as *const c_char));
6844 write_str(fd, b"\n".as_ptr(), 1);
6845}
6846
6847#[no_mangle]
6848pub unsafe extern "C" fn fread(
6849 ptr: *mut c_void, size: SizeT, nmemb: SizeT, stream: *mut FILE,
6850) -> SizeT {
6851 if size == 0 || nmemb == 0 { return 0; }
6852 let total = size * nmemb;
6853 let mut rd = 0usize;
6854 while rd < total {
6855 let c = fgetc(stream);
6856 if c == -1 { break; }
6857 *(ptr as *mut u8).add(rd) = c as u8;
6858 rd += 1;
6859 }
6860 rd / size
6861}
6862
6863unsafe fn write_str(fd: c_int, s: *const u8, len: usize) {
6868 let mut written = 0usize;
6869 while written < len {
6870 let n = sys_write(fd as i64, s.add(written), len - written);
6871 if n <= 0 { break; }
6872 written += n as usize;
6873 }
6874}
6875
6876#[no_mangle]
6877unsafe fn __overflow(f: *mut FILE, c: c_int) -> c_int {
6878 if (*f).wpos.is_null() {
6879 (*f).wbase = (*f).buf;
6880 (*f).wpos = (*f).buf;
6881 (*f).wend = (*f).buf.add((*f).buf_size);
6882 }
6883 if flush_buf(f) == -1 { return -1; }
6884 if (*f).wpos >= (*f).wend {
6885 if let Some(wfunc) = (*f).write_fn {
6886 let byte = c as u8;
6887 let ret = wfunc(f, &byte as *const u8, 1);
6888 if ret == 0 { return -1; }
6889 }
6890 return c;
6891 }
6892 *(*f).wpos = c as u8;
6893 (*f).wpos = (*f).wpos.add(1);
6894 if c == (*f).lbf || (*f).wpos >= (*f).wend { let _ = flush_buf(f); }
6895 c
6896}
6897
6898#[no_mangle]
6899pub unsafe extern "C" fn puts(s: *const c_char) -> c_int {
6900 let len = strlen(s as *const c_char);
6901 let _ = fwrite(s as *const c_void, 1, len, stdout);
6902 let _ = fwrite(b"\n".as_ptr() as *const c_void, 1, 1, stdout);
6903 let f = &mut *stdout;
6904 if f.lbf >= 0 { let _ = flush_buf(stdout); }
6905 (len + 1) as c_int
6906}
6907
6908#[no_mangle]
6909pub unsafe extern "C" fn fputs(s: *const c_char, stream: *mut FILE) -> c_int {
6910 let len = strlen(s as *const c_char);
6911 fwrite(s as *const c_void, 1, len, stream) as c_int
6912}
6913
6914#[no_mangle]
6915pub unsafe extern "C" fn fputc(c: c_int, stream: *mut FILE) -> c_int {
6916 let f = &mut *stream;
6917 if f.wpos.is_null() || f.wpos >= f.wend {
6918 if __overflow(f, c) == -1 { return -1; }
6919 return c;
6920 }
6921 *f.wpos = c as u8;
6922 f.wpos = f.wpos.add(1);
6923 if c == f.lbf || f.wpos >= f.wend { let _ = flush_buf(f); }
6924 c
6925}
6926
6927#[no_mangle]
6928pub unsafe extern "C" fn putc(c: c_int, stream: *mut FILE) -> c_int { fputc(c, stream) }
6929
6930#[no_mangle]
6931pub unsafe extern "C" fn putchar(c: c_int) -> c_int { fputc(c, stdout) }
6932
6933#[no_mangle]
6934pub unsafe extern "C" fn fwrite(
6935 ptr: *const c_void, size: SizeT, nmemb: SizeT, stream: *mut FILE,
6936) -> SizeT {
6937 if size == 0 || nmemb == 0 { return 0; }
6938 let total = size * nmemb;
6939 let f = &mut *stream;
6940 if f.buf_size == 0 {
6941 if let Some(wfunc) = f.write_fn {
6942 let ret = wfunc(stream, ptr as *const u8, total);
6943 return ret / size;
6944 }
6945 return 0;
6946 }
6947 if f.wpos.is_null() {
6948 f.wbase = f.buf;
6949 f.wpos = f.buf;
6950 f.wend = f.buf.add(f.buf_size);
6951 }
6952 let mut remaining = total;
6953 let mut src = ptr as *const u8;
6954 while remaining > 0 {
6955 let space = f.wend as usize - f.wpos as usize;
6956 if space == 0 {
6957 if flush_buf(f as *mut FILE) == -1 { break; }
6958 continue;
6959 }
6960 let n = if remaining < space { remaining } else { space };
6961 core::ptr::copy_nonoverlapping(src, f.wpos, n);
6962 f.wpos = f.wpos.add(n);
6963 src = src.add(n);
6964 remaining -= n;
6965 if f.wpos >= f.wend { let _ = flush_buf(f as *mut FILE); }
6966 }
6967 if f.lbf >= 0 { let _ = flush_buf(f as *mut FILE); }
6968 (total - remaining) / size
6969}
6970
6971unsafe fn wide_to_mb(dst: *mut u8, cap: usize, src: *const wchar_t) -> usize {
6976 let mut o = 0usize;
6977 let mut i = 0usize;
6978 let mut st: c_uint = 0;
6979 while *src.add(i) != 0 {
6980 let mut tmp = [0u8; 8];
6981 let n = wcrtomb(tmp.as_mut_ptr() as *mut c_char, *src.add(i), &mut st);
6982 if n == !0usize || n == 0 { break; }
6983 if o + n > cap { break; }
6984 core::ptr::copy_nonoverlapping(tmp.as_ptr(), dst.add(o), n);
6985 o += n;
6986 i += 1;
6987 }
6988 o
6989}
6990
6991macro_rules! impl_format {
6992 ($fmt:expr, $args:expr, $write_char:expr, $write_str:expr) => {{
6993 let fmt = $fmt;
6994 let args = &mut $args;
6995 let mut count: usize = 0;
6996 let mut i = 0usize;
6997 loop {
6998 let c = *fmt.add(i) as u8;
6999 if c == 0 { break; }
7000 if c != b'%' {
7001 ($write_char)(c);
7002 count += 1; i += 1; continue;
7003 }
7004 i += 1;
7005 let mut flags: u8 = 0;
7007 loop {
7008 let fc = *fmt.add(i) as u8;
7009 match fc {
7010 b'-' => { flags |= FLAG_MINUS; i += 1; }
7011 b'+' => { flags |= FLAG_PLUS; i += 1; }
7012 b' ' => { flags |= FLAG_SPACE; i += 1; }
7013 b'0' => { flags |= FLAG_ZERO; i += 1; }
7014 b'#' => { flags |= FLAG_HASH; i += 1; }
7015 _ => break,
7016 }
7017 }
7018 let mut width: usize = 0;
7020 if *fmt.add(i) as u8 == b'*' {
7021 width = args.next_arg::<c_int>() as usize; i += 1;
7022 } else {
7023 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
7024 width = width * 10 + ((*fmt.add(i) as u8) - b'0') as usize; i += 1;
7025 }
7026 }
7027 let mut precision: i32 = -1;
7029 if *fmt.add(i) as u8 == b'.' {
7030 i += 1;
7031 if *fmt.add(i) as u8 == b'*' {
7032 precision = args.next_arg::<c_int>(); i += 1;
7033 } else {
7034 precision = 0;
7035 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
7036 precision = precision * 10 + ((*fmt.add(i) as u8) - b'0') as i32; i += 1;
7037 }
7038 }
7039 }
7040 let len_mod = *fmt.add(i) as u8;
7042 let spec: u8;
7043 if len_mod == b'h' || len_mod == b'l' || len_mod == b'j' || len_mod == b'z' || len_mod == b't' || len_mod == b'L' {
7044 i += 1;
7045 let len_mod2 = *fmt.add(i) as u8;
7046 if (len_mod == b'h' && len_mod2 == b'h') || (len_mod == b'l' && len_mod2 == b'l') {
7047 i += 1;
7048 spec = *fmt.add(i) as u8;
7049 match (len_mod, len_mod2, spec) {
7051 (b'h', b'h', b'n') => {
7052 let p = args.next_arg::<*mut c_void>();
7053 if !p.is_null() { *(p as *mut u8) = count as u8; }
7054 }
7055 (b'l', b'l', b'n') => {
7056 let p = args.next_arg::<*mut c_void>();
7057 if !p.is_null() { *(p as *mut c_longlong) = count as c_longlong; }
7058 }
7059 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
7060 let val = args.next_arg::<c_longlong>();
7061 let neg = val < 0;
7062 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
7063 let b = format_u64(abs);
7064 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7065 let mut fbuf = [0u8; 32];
7066 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7067 ($write_str)(fbuf.as_ptr(), len); count += len;
7068 }
7069 (b'l', b'l', b'u') => {
7070 let val = args.next_arg::<c_ulonglong>();
7071 let b = format_u64(val as u64);
7072 let mut fbuf = [0u8; 32];
7073 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7074 ($write_str)(fbuf.as_ptr(), len); count += len;
7075 }
7076 (b'l', b'l', b'o') => {
7077 let val = args.next_arg::<c_ulonglong>();
7078 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
7079 let mut fbuf = [0u8; 32];
7080 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7081 ($write_str)(fbuf.as_ptr(), len); count += len;
7082 }
7083 (b'l', b'l', b'x') => {
7084 let val = args.next_arg::<c_ulonglong>();
7085 let b = format_hex(val as u64, false);
7086 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
7087 let mut fbuf = [0u8; 32];
7088 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7089 ($write_str)(fbuf.as_ptr(), len); count += len;
7090 }
7091 (b'l', b'l', b'X') => {
7092 let val = args.next_arg::<c_ulonglong>();
7093 let b = format_hex(val as u64, true);
7094 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
7095 let mut fbuf = [0u8; 32];
7096 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7097 ($write_str)(fbuf.as_ptr(), len); count += len;
7098 }
7099 _ => { ($write_char)(b'%'); ($write_char)(len_mod); ($write_char)(len_mod2); ($write_char)(spec); count += 4; }
7100 }
7101 } else {
7102 spec = len_mod2;
7103 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
7106 match (lm, spec) {
7107 (b'h', b'n') => {
7108 let p = args.next_arg::<*mut c_void>();
7109 if !p.is_null() { *(p as *mut u16) = count as u16; }
7110 }
7111 (b'l', b'n') => {
7112 let p = args.next_arg::<*mut c_void>();
7113 if !p.is_null() { *(p as *mut c_long) = count as c_long; }
7114 }
7115 (b'z', b'n') | (b't', b'n') => {
7116 let p = args.next_arg::<*mut c_void>();
7117 if !p.is_null() { *(p as *mut usize) = count; }
7118 }
7119 (b'j', b'n') => {
7120 let p = args.next_arg::<*mut c_void>();
7121 if !p.is_null() { *(p as *mut c_ulonglong) = count as c_ulonglong; }
7122 }
7123 (b'l', b'd') | (b'l', b'i') => {
7124 let val = args.next_arg::<c_long>();
7125 let neg = val < 0;
7126 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
7127 let b = format_u64(abs);
7128 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7129 let mut fbuf = [0u8; 32];
7130 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7131 ($write_str)(fbuf.as_ptr(), len); count += len;
7132 }
7133 (b'l', b'u') => {
7134 let val = args.next_arg::<c_ulong>();
7135 let b = format_u64(val as u64);
7136 let mut fbuf = [0u8; 32];
7137 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7138 ($write_str)(fbuf.as_ptr(), len); count += len;
7139 }
7140 (b'l', b's') => {
7141 let p = args.next_arg::<*const wchar_t>();
7142 if p.is_null() {
7143 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
7144 let pad = width.saturating_sub(slen);
7145 if flags & FLAG_MINUS != 0 { ($write_str)(b"(null)".as_ptr(), slen); for _ in 0..pad { ($write_char)(b' '); } }
7146 else { for _ in 0..pad { ($write_char)(b' '); } ($write_str)(b"(null)".as_ptr(), slen); }
7147 count += slen + pad;
7148 } else {
7149 let mut mb = [0u8; 4096];
7150 let mut n = wide_to_mb(mb.as_mut_ptr(), mb.len(), p);
7151 if precision >= 0 && (precision as usize) < n { n = precision as usize; }
7152 let pad = width.saturating_sub(n);
7153 if flags & FLAG_MINUS != 0 { ($write_str)(mb.as_ptr(), n); for _ in 0..pad { ($write_char)(b' '); } }
7154 else { for _ in 0..pad { ($write_char)(b' '); } ($write_str)(mb.as_ptr(), n); }
7155 count += n + pad;
7156 }
7157 }
7158 (b'l', b'c') => {
7159 let ch = args.next_arg::<c_int>();
7160 let mut mb = [0u8; 8];
7161 let mut st: c_uint = 0;
7162 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, ch, &mut st);
7163 if n != !0usize { ($write_str)(mb.as_ptr(), n); count += n; }
7164 }
7165 (b'l', b'x') => {
7166 let val = args.next_arg::<c_ulong>();
7167 let b = format_hex(val as u64, false);
7168 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
7169 let mut fbuf = [0u8; 32];
7170 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7171 ($write_str)(fbuf.as_ptr(), len); count += len;
7172 }
7173 (b'l', b'X') => {
7174 let val = args.next_arg::<c_ulong>();
7175 let b = format_hex(val as u64, true);
7176 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
7177 let mut fbuf = [0u8; 32];
7178 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7179 ($write_str)(fbuf.as_ptr(), len); count += len;
7180 }
7181 (b'l', b'o') => {
7182 let val = args.next_arg::<c_ulong>();
7183 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
7184 let mut fbuf = [0u8; 32];
7185 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7186 ($write_str)(fbuf.as_ptr(), len); count += len;
7187 }
7188 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
7189 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
7190 let val = args.next_arg::<f64>();
7191 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7192 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7193 let mut fbuf = [0u8; 4224];
7194 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7195 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
7196 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
7197 ($write_str)(fbuf.as_ptr(), total); count += total;
7198 }
7199 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
7200 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
7201 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
7202 let val = {
7203 let lo: u64 = args.next_arg::<u64>();
7204 let hi: u64 = args.next_arg::<u64>();
7205 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
7206 f128::from_bits(combined) as f64
7207 };
7208 #[cfg(target_arch = "x86_64")]
7209 let val = args.next_arg::<f64>();
7210 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7211 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7212 let mut fbuf = [0u8; 4224];
7213 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7214 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
7215 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
7216 ($write_str)(fbuf.as_ptr(), total); count += total;
7217 }
7218 _ => { ($write_char)(b'%'); ($write_char)(len_mod); ($write_char)(spec); count += 3; }
7219 }
7220 }
7221 } else {
7222 spec = *fmt.add(i) as u8;
7223 match spec {
7224 b's' => {
7225 let s = args.next_arg::<*const c_char>();
7226 if s.is_null() {
7227 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
7228 let padded_len = if width > slen { width } else { slen };
7229 let pad = padded_len - slen;
7230 if flags & FLAG_MINUS != 0 {
7231 ($write_str)(b"(null)".as_ptr(), slen);
7232 for _ in 0..pad { ($write_char)(b' '); }
7233 } else {
7234 for _ in 0..pad { ($write_char)(b' '); }
7235 ($write_str)(b"(null)".as_ptr(), slen);
7236 }
7237 count += padded_len;
7238 } else {
7239 let full_len = strlen(s as *const c_char);
7240 let slen = if precision >= 0 { (precision as usize).min(full_len) } else { full_len };
7241 let padded_len = if width > slen { width } else { slen };
7242 let pad = padded_len - slen;
7243 if flags & FLAG_MINUS != 0 {
7244 ($write_str)(s as *const u8, slen);
7245 for _ in 0..pad { ($write_char)(b' '); }
7246 } else {
7247 for _ in 0..pad { ($write_char)(b' '); }
7248 ($write_str)(s as *const u8, slen);
7249 }
7250 count += padded_len;
7251 }
7252 }
7253 b'd' | b'i' => {
7254 let d = args.next_arg::<c_int>();
7255 let neg = d < 0;
7256 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
7257 let b = format_u64(abs);
7258 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7259 let mut fbuf = [0u8; 32];
7260 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7261 ($write_str)(fbuf.as_ptr(), len); count += len;
7262 }
7263 b'u' => {
7264 let u = args.next_arg::<c_uint>();
7265 let b = format_u64(u as u64);
7266 let mut fbuf = [0u8; 32];
7267 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7268 ($write_str)(fbuf.as_ptr(), len); count += len;
7269 }
7270 b'x' => {
7271 let x = args.next_arg::<c_uint>();
7272 let b = format_hex(x as u64, false);
7273 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
7274 let mut fbuf = [0u8; 32];
7275 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7276 ($write_str)(fbuf.as_ptr(), len); count += len;
7277 }
7278 b'X' => {
7279 let x = args.next_arg::<c_uint>();
7280 let b = format_hex(x as u64, true);
7281 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
7282 let mut fbuf = [0u8; 32];
7283 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7284 ($write_str)(fbuf.as_ptr(), len); count += len;
7285 }
7286 b'o' => {
7287 let o = args.next_arg::<c_uint>();
7288 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
7289 let mut fbuf = [0u8; 32];
7290 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7291 ($write_str)(fbuf.as_ptr(), len); count += len;
7292 }
7293 b'c' => {
7294 let ch = args.next_arg::<c_int>();
7295 if width > 1 {
7296 let pad = width - 1;
7297 if flags & FLAG_MINUS != 0 {
7298 ($write_char)(ch as u8); count += 1;
7299 for _ in 0..pad { ($write_char)(b' '); count += 1; }
7300 } else {
7301 for _ in 0..pad { ($write_char)(b' '); count += 1; }
7302 ($write_char)(ch as u8); count += 1;
7303 }
7304 } else {
7305 ($write_char)(ch as u8); count += 1;
7306 }
7307 }
7308 b'p' => {
7309 let p = args.next_arg::<*const c_void>();
7310 let mut fbuf = [0u8; 20];
7311 fbuf[0] = b'0'; fbuf[1] = b'x';
7312 let b = format_hex(p as u64, false);
7313 core::ptr::copy_nonoverlapping(b.0.as_ptr(), fbuf.as_mut_ptr().add(2), b.1);
7314 ($write_str)(fbuf.as_ptr(), b.1 + 2); count += b.1 + 2;
7315 }
7316 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
7317 let val = args.next_arg::<f64>();
7318 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7319 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7320 let mut fbuf = [0u8; 4224];
7321 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7322 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
7323 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
7324 ($write_str)(fbuf.as_ptr(), total); count += total;
7325 }
7326 b'%' => { ($write_char)(b'%'); count += 1; }
7327 b'n' => {
7328 let p = args.next_arg::<*mut c_void>();
7329 if !p.is_null() { *(p as *mut c_int) = count as c_int; }
7330 }
7331 _ => { ($write_char)(b'%'); ($write_char)(spec); count += 2; }
7332 }
7333 }
7334 i += 1;
7335 }
7336 count as c_int
7337 }};
7338}
7339
7340unsafe fn format_u64(mut val: u64) -> ([u8; 20], usize) {
7341 let mut buf = [0u8; 20];
7342 if val == 0 { buf[0] = b'0'; return (buf, 1); }
7343 let mut tmp = [0u8; 20];
7344 let mut pos = 20;
7345 while val > 0 { pos -= 1; tmp[pos] = b'0' + (val % 10) as u8; val /= 10; }
7346 let len = 20 - pos;
7347 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
7348 (buf, len)
7349}
7350
7351unsafe fn format_i64(val: i64) -> ([u8; 21], usize) {
7352 let mut buf = [0u8; 21];
7353 if val < 0 {
7354 buf[0] = b'-';
7355 let (inner, len) = format_u64((-(val as i128)) as u64);
7356 core::ptr::copy_nonoverlapping(inner.as_ptr(), buf.as_mut_ptr().add(1), len);
7357 (buf, len + 1)
7358 } else {
7359 let (inner, len) = format_u64(val as u64);
7360 core::ptr::copy_nonoverlapping(inner.as_ptr(), buf.as_mut_ptr(), len);
7361 (buf, len)
7362 }
7363}
7364
7365unsafe fn format_hex(mut val: u64, uppercase: bool) -> ([u8; 16], usize) {
7366 let digits = if uppercase { b"0123456789ABCDEF" } else { b"0123456789abcdef" };
7367 let mut buf = [0u8; 16];
7368 if val == 0 { buf[0] = b'0'; return (buf, 1); }
7369 let mut tmp = [0u8; 16];
7370 let mut pos = 16;
7371 while val > 0 { pos -= 1; tmp[pos] = digits[(val & 0xf) as usize]; val >>= 4; }
7372 let len = 16 - pos;
7373 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
7374 (buf, len)
7375}
7376
7377unsafe fn format_octal(mut val: u64, alt: bool) -> ([u8; 24], usize) {
7378 let mut buf = [0u8; 24];
7379 if val == 0 {
7380 buf[0] = b'0';
7381 return (buf, 1);
7382 }
7383 let mut tmp = [0u8; 24];
7384 let mut pos = 24;
7385 while val > 0 {
7386 pos -= 1;
7387 tmp[pos] = b'0' + (val & 7) as u8;
7388 val >>= 3;
7389 }
7390 let len = 24 - pos;
7391 if alt {
7392 tmp[pos - 1] = b'0';
7393 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos - 1), buf.as_mut_ptr(), len + 1);
7394 (buf, len + 1)
7395 } else {
7396 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
7397 (buf, len)
7398 }
7399}
7400
7401unsafe fn format_int(
7402 dst: *mut u8,
7403 digits: *const u8,
7404 digits_len: usize,
7405 sign: Option<u8>,
7406 prefix: Option<u8>,
7407 precision: i32,
7408 width: usize,
7409 flags: u8,
7410 octal_alt: bool,
7411) -> usize {
7412 let num_digits = if precision == 0 && digits_len == 1 && *digits == b'0' && !octal_alt {
7413 0
7414 } else {
7415 digits_len
7416 };
7417 let prec = precision as usize;
7418 let zero_pad = if precision >= 0 && prec > num_digits { prec - num_digits } else { 0 };
7419
7420 let sign_len = sign.map_or(0, |_| 1);
7421 let prefix_len = prefix.map_or(0, |_| 2);
7422 let content_len = sign_len + prefix_len + zero_pad + num_digits;
7423
7424 let mut buf = [0u8; 32];
7425 let mut pos = 0usize;
7426 if let Some(c) = sign { buf[pos] = c; pos += 1; }
7427 if let Some(c) = prefix { buf[pos] = b'0'; pos += 1; buf[pos] = c; pos += 1; }
7428 for _ in 0..zero_pad { buf[pos] = b'0'; pos += 1; }
7429 if num_digits > 0 {
7430 core::ptr::copy_nonoverlapping(digits, buf.as_mut_ptr().add(pos), num_digits);
7431 }
7432
7433 if content_len >= width {
7434 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, content_len);
7435 return content_len;
7436 }
7437 let pad = width - content_len;
7438 if flags & FLAG_MINUS != 0 {
7439 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, content_len);
7440 for i in 0..pad { *dst.add(content_len + i) = b' '; }
7441 } else if flags & FLAG_ZERO != 0 && precision < 0 {
7442 let fixed = sign_len + prefix_len;
7443 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, fixed);
7444 for i in fixed..width - num_digits { *dst.add(i) = b'0'; }
7445 if num_digits > 0 {
7446 core::ptr::copy_nonoverlapping(digits, dst.add(width - num_digits), num_digits);
7447 }
7448 } else {
7449 for i in 0..pad { *dst.add(i) = b' '; }
7450 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst.add(pad), content_len);
7451 }
7452 width
7453}
7454
7455unsafe fn format_f64(val: f64) -> ([u8; 64], usize) {
7456 let mut buf = [0u8; 64];
7457 let mut pos = 0usize;
7458 let mut v = val;
7459 if v.is_nan() {
7460 let nan = b"nan";
7461 core::ptr::copy_nonoverlapping(nan.as_ptr(), buf.as_mut_ptr(), 3);
7462 return (buf, 3);
7463 }
7464 if v < 0.0 { buf[pos] = b'-'; pos += 1; v = -v; }
7465 if v.is_infinite() {
7466 let inf = b"inf";
7467 core::ptr::copy_nonoverlapping(inf.as_ptr(), buf.as_mut_ptr().add(pos), 3);
7468 return (buf, pos + 3);
7469 }
7470 let int_part = v as u64;
7471 let frac = v - int_part as f64;
7472 let (ibuf, ilen) = format_u64(int_part);
7473 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), buf.as_mut_ptr().add(pos), ilen);
7474 pos += ilen;
7475 buf[pos] = b'.';
7476 pos += 1;
7477 let mut f = frac;
7478 for _ in 0..6 { f *= 10.0; let digit = f as u8; buf[pos] = b'0' + digit; pos += 1; f -= digit as f64; }
7479 (buf, pos)
7480}
7481
7482const FMT_F: u8 = 0;
7484const FMT_E: u8 = 1;
7485const FMT_G: u8 = 2;
7486const FMT_A: u8 = 3;
7487
7488const FLAG_HASH: u8 = 1;
7489const FLAG_PLUS: u8 = 2;
7490const FLAG_SPACE: u8 = 4;
7491const FLAG_ZERO: u8 = 8;
7492const FLAG_MINUS: u8 = 16;
7493
7494unsafe fn bigint_to_decimal(buf: *mut u8, mant: u64, shift: u32) -> usize {
7499 let nlimbs = (2 + (shift + 31) / 32) as usize;
7501 let mut limbs = [0u32; 36];
7502 limbs[0] = mant as u32;
7503 limbs[1] = (mant >> 32) as u32;
7504
7505 let ws = (shift / 32) as usize;
7506 let bs = shift % 32;
7507
7508 if ws > 0 {
7510 let mut i = 1usize;
7511 loop {
7512 limbs[i + ws] = limbs[i];
7513 if i == 0 { break; }
7514 i -= 1;
7515 }
7516 for j in 0..ws { limbs[j] = 0; }
7517 }
7518 if bs > 0 {
7520 let mut carry = 0u32;
7521 let end = nlimbs.min(ws + 3);
7522 for i in ws..end {
7523 let new_val = (limbs[i] << bs) | carry;
7524 carry = limbs[i] >> (32 - bs);
7525 limbs[i] = new_val;
7526 }
7527 }
7528
7529 let mut used = nlimbs;
7531 while used > 0 && limbs[used - 1] == 0 { used -= 1; }
7532 if used == 0 { *buf = b'0'; return 1; }
7533
7534 let mut digits = [0u8; 400];
7536 let mut nd = 0usize;
7537 loop {
7538 let mut all_zero = true;
7539 for i in 0..used { if limbs[i] != 0 { all_zero = false; break; } }
7540 if all_zero { break; }
7541 let mut rem = 0u64;
7542 for i in (0..used).rev() {
7543 let val = (rem << 32) | limbs[i] as u64;
7544 limbs[i] = (val / 10) as u32;
7545 rem = val % 10;
7546 }
7547 digits[nd] = rem as u8;
7548 nd += 1;
7549 }
7550 for i in 0..nd { *buf.add(i) = b'0' + digits[nd - 1 - i]; }
7552 nd
7553}
7554
7555unsafe fn frac_digits_u128(buf: *mut u8, frac_bits: u64, shift: u32, count: usize) -> bool {
7558 let mask: u128 = (1u128 << shift) - 1;
7559 let mut rem = frac_bits as u128;
7560 for i in 0..count {
7561 rem *= 10;
7562 let digit = (rem >> shift) as u8;
7563 rem &= mask;
7564 *buf.add(i) = digit;
7565 }
7566 rem != 0
7567}
7568
7569unsafe fn frac_digits_bigint(buf: *mut u8, frac_bits: u64, shift: u32, count: usize) -> bool {
7572 let nlimbs = ((shift + 31) / 32) as usize;
7573 let mut rem = [0u32; 36]; rem[0] = frac_bits as u32;
7575 if nlimbs > 1 { rem[1] = (frac_bits >> 32) as u32; }
7576 let hi_word = (shift / 32) as usize;
7578 let hi_bit = shift % 32;
7579 if hi_bit > 0 && hi_word < nlimbs {
7580 rem[hi_word] &= (1u32 << hi_bit) - 1;
7581 }
7582 let clear_from = if hi_bit > 0 { hi_word + 1 } else { hi_word };
7584 for j in clear_from..nlimbs { rem[j] = 0; }
7585
7586 for i in 0..count {
7587 let mut carry = 0u64;
7589 for j in 0..nlimbs {
7590 let val = rem[j] as u64 * 10 + carry;
7591 rem[j] = val as u32;
7592 carry = val >> 32;
7593 }
7594 let digit: u32;
7596 if hi_bit == 0 {
7597 digit = if hi_word < nlimbs { rem[hi_word] } else { carry as u32 };
7598 } else {
7599 let mut d = if hi_word < nlimbs { rem[hi_word] >> hi_bit } else { 0 };
7600 if hi_word + 1 < nlimbs {
7601 d |= rem[hi_word + 1] << (32 - hi_bit);
7602 } else if carry > 0 {
7603 d |= (carry as u32) << (32 - hi_bit);
7604 }
7605 digit = d;
7606 }
7607 *buf.add(i) = digit.min(9) as u8;
7608 if hi_bit == 0 {
7610 if hi_word < nlimbs { rem[hi_word] = 0; }
7611 } else {
7612 if hi_word < nlimbs {
7613 rem[hi_word] &= (1u32 << hi_bit) - 1;
7614 }
7615 for j in (hi_word + 1)..nlimbs { rem[j] = 0; }
7616 }
7617 }
7618 for i in 0..nlimbs { if rem[i] != 0 { return true; } }
7620 false
7621}
7622
7623unsafe fn increment_decimal(buf: *mut u8, len: &mut usize) {
7625 let mut j = *len;
7626 loop {
7627 if j == 0 {
7628 let l = *len;
7630 for i in (0..l).rev() { *buf.add(i + 1) = *buf.add(i); }
7631 *buf = b'1';
7632 *len = l + 1;
7633 return;
7634 }
7635 j -= 1;
7636 let d = *buf.add(j);
7637 if d < b'9' { *buf.add(j) = d + 1; return; }
7638 *buf.add(j) = b'0';
7639 }
7640}
7641
7642unsafe fn format_f64_full(
7644 dst: *mut u8, val: f64, fmt_type: u8, precision: i32, flags: u8, uppercase: bool,
7645) -> usize {
7646 let mut pos = 0usize;
7647
7648 if val.is_nan() {
7650 let nan_s: &[u8] = if uppercase { b"NAN" } else { b"nan" };
7651 core::ptr::copy_nonoverlapping(nan_s.as_ptr(), dst, 3);
7652 return 3;
7653 }
7654 let neg = val.is_sign_negative();
7655 let v = if neg { -val } else { val };
7656
7657 if v.is_infinite() {
7659 if neg { *dst.add(pos) = b'-'; pos += 1; }
7660 else if flags & FLAG_PLUS != 0 { *dst.add(pos) = b'+'; pos += 1; }
7661 else if flags & FLAG_SPACE != 0 { *dst.add(pos) = b' '; pos += 1; }
7662 let inf_s: &[u8] = if uppercase { b"INF" } else { b"inf" };
7663 core::ptr::copy_nonoverlapping(inf_s.as_ptr(), dst.add(pos), 3);
7664 return pos + 3;
7665 }
7666
7667 if neg { *dst.add(pos) = b'-'; pos += 1; }
7669 else if flags & FLAG_PLUS != 0 { *dst.add(pos) = b'+'; pos += 1; }
7670 else if flags & FLAG_SPACE != 0 { *dst.add(pos) = b' '; pos += 1; }
7671
7672 if fmt_type == FMT_A {
7674 return pos + fmt_hex_float(dst.add(pos), val, precision, flags, uppercase);
7675 }
7676
7677 let p: usize;
7679 let mut exp: i32;
7680 let use_f: bool;
7681
7682 match fmt_type {
7683 FMT_G => {
7684 let gp = if precision < 0 { 6usize } else if precision == 0 { 1usize } else { precision as usize };
7685 exp = if v > 0.0 { compute_exp10(v) } else { 0 };
7686 use_f = exp >= -4 && exp < gp as i32;
7687 if use_f {
7688 p = if exp < 0 { gp + ((-exp) as usize - 1) }
7689 else if (exp as usize) < gp { gp - exp as usize - 1 }
7690 else { 0 };
7691 } else {
7692 p = gp - 1;
7693 }
7694 }
7695 FMT_E => {
7696 p = if precision < 0 { 6usize } else { precision as usize };
7697 exp = if v > 0.0 { compute_exp10(v) } else { 0 };
7698 use_f = false;
7699 }
7700 _ => {
7701 p = if precision < 0 { 6usize } else { precision as usize };
7702 exp = 0;
7703 use_f = true;
7704 }
7705 }
7706
7707 if v == 0.0 {
7708 *dst.add(pos) = b'0'; pos += 1;
7709 if !(fmt_type == FMT_G && flags & FLAG_HASH == 0) {
7710 if p > 0 || flags & FLAG_HASH != 0 {
7711 *dst.add(pos) = b'.'; pos += 1;
7712 for _ in 0..p { *dst.add(pos) = b'0'; pos += 1; }
7713 }
7714 }
7715 if !use_f {
7716 let ec = if uppercase { b'E' } else { b'e' };
7717 *dst.add(pos) = ec; pos += 1;
7718 *dst.add(pos) = b'+'; pos += 1;
7719 *dst.add(pos) = b'0'; pos += 1;
7720 *dst.add(pos) = b'0'; pos += 1;
7721 }
7722 return pos;
7723 }
7724
7725 if use_f {
7727 let bits = v.to_bits();
7728 let raw_mant = bits & 0x000FFFFFFFFFFFFF;
7729 let raw_exp_bits = ((bits >> 52) & 0x7FF) as i32;
7730 let (mant_b, bin_exp) = if raw_exp_bits == 0 {
7731 (raw_mant, -1022i32)
7732 } else {
7733 (raw_mant | (1u64 << 52), raw_exp_bits - 1023)
7734 };
7735
7736 let mut ibuf = [0u8; 400];
7738 let mut ilen: usize;
7739 if bin_exp < 0 {
7740 ibuf[0] = b'0'; ilen = 1;
7741 } else if bin_exp <= 63 {
7742 let int_val = if bin_exp <= 52 { mant_b >> (52 - bin_exp) }
7743 else { mant_b << (bin_exp - 52) };
7744 let (buf2, len2) = format_u64(int_val);
7745 ibuf[..len2].copy_from_slice(&buf2[..len2]);
7746 ilen = len2;
7747 } else {
7748 ilen = bigint_to_decimal(ibuf.as_mut_ptr(), mant_b, (bin_exp - 52) as u32);
7749 }
7750
7751 let mut fbuf = [0u8; 1100];
7753 let mut has_rest = false;
7754 if p > 0 && bin_exp < 52 {
7755 let shift = (52 - bin_exp) as u32;
7756 let frac_bits = if bin_exp >= 0 { mant_b & ((1u64 << shift) - 1) } else { mant_b };
7757 if shift <= 124 {
7758 has_rest = frac_digits_u128(fbuf.as_mut_ptr(), frac_bits, shift, p + 1);
7759 } else {
7760 has_rest = frac_digits_bigint(fbuf.as_mut_ptr(), frac_bits, shift, p + 1);
7761 }
7762 }
7763
7764 if p > 0 && bin_exp < 52 {
7766 let next_d = fbuf[p];
7767 let last_d = fbuf[p - 1];
7768 if next_d > 5 || (next_d == 5 && (has_rest || last_d & 1 != 0)) {
7769 let mut carry = true;
7770 for j in (0..p).rev() {
7771 if !carry { break; }
7772 fbuf[j] += 1;
7773 if fbuf[j] < 10 { carry = false; break; }
7774 fbuf[j] = 0;
7775 }
7776 if carry { increment_decimal(ibuf.as_mut_ptr(), &mut ilen); }
7777 }
7778 } else if p == 0 {
7779 if bin_exp >= 0 && bin_exp < 52 {
7781 let shift = (52 - bin_exp) as u32;
7782 let frac_bits = mant_b & ((1u64 << shift) - 1);
7783 let half = 1u64 << (shift - 1);
7784 let last_d = ibuf[ilen - 1] - b'0';
7785 if frac_bits > half || (frac_bits == half && last_d & 1 != 0) {
7786 increment_decimal(ibuf.as_mut_ptr(), &mut ilen);
7787 }
7788 }
7789 }
7790
7791 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), dst.add(pos), ilen);
7793 pos += ilen;
7794 if p > 0 || flags & FLAG_HASH != 0 {
7795 *dst.add(pos) = b'.'; pos += 1;
7796 for i in 0..p { *dst.add(pos) = b'0' + fbuf[i]; pos += 1; }
7797 }
7798 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7799 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7800 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7801 }
7802 return pos;
7803 }
7804
7805 let mut fbuf = [0u8; 20];
7808 let mut int_part: u64;
7809 {
7810 let bits_v = v.to_bits();
7811 let raw_mant_v = bits_v & 0x000FFFFFFFFFFFFF;
7812 let raw_exp_v = ((bits_v >> 52) & 0x7FF) as i32;
7813 let (mant_b_v, bin_exp_v) = if raw_exp_v == 0 {
7814 (raw_mant_v, -1022i32)
7815 } else {
7816 (raw_mant_v | (1u64 << 52), raw_exp_v - 1023)
7817 };
7818
7819 let s: i32 = (p as i32) + 1 - exp;
7820 let bs: i32 = bin_exp_v - 52 + s;
7821
7822 let mut limbs = [0u32; 40];
7823 limbs[0] = mant_b_v as u32;
7824 limbs[1] = (mant_b_v >> 32) as u32;
7825 let mut nlimbs: usize = if limbs[1] != 0 { 2 } else { 1 };
7826
7827 if s > 0 {
7828 for _ in 0..(s as usize) {
7829 let mut carry = 0u64;
7830 for j in 0..nlimbs {
7831 let val = limbs[j] as u64 * 5 + carry;
7832 limbs[j] = val as u32;
7833 carry = val >> 32;
7834 }
7835 if carry > 0 { limbs[nlimbs] = carry as u32; nlimbs += 1; }
7836 }
7837 }
7838
7839 if bs > 0 {
7840 let ws = (bs as u32 / 32) as usize;
7841 let bit = bs as u32 % 32;
7842 if ws > 0 {
7843 let mut i = nlimbs;
7844 while i > 0 { i -= 1; if i + ws < 40 { limbs[i + ws] = limbs[i]; } limbs[i] = 0; }
7845 nlimbs += ws;
7846 }
7847 if bit > 0 {
7848 let mut carry = 0u32;
7849 for i in ws..nlimbs {
7850 let new_val = (limbs[i] << bit) | carry;
7851 carry = limbs[i] >> (32 - bit);
7852 limbs[i] = new_val;
7853 }
7854 if carry > 0 && nlimbs < 40 { limbs[nlimbs] = carry; nlimbs += 1; }
7855 }
7856 }
7857
7858 let mut has_rest = false;
7859 if s < 0 {
7860 for _ in 0..(-s as usize) {
7861 let mut rem = 0u64;
7862 for i in (0..nlimbs).rev() {
7863 let val = (rem << 32) | limbs[i] as u64;
7864 limbs[i] = (val / 5) as u32;
7865 rem = val % 5;
7866 }
7867 if rem != 0 { has_rest = true; }
7868 }
7869 }
7870
7871 if bs < 0 {
7872 let rshift = (-bs) as u32;
7873 let ws = (rshift / 32) as usize;
7874 let bit = rshift % 32;
7875 if ws > 0 {
7876 for j in 0..ws.min(nlimbs) { if limbs[j] != 0 { has_rest = true; } }
7877 for i in ws..nlimbs { limbs[i - ws] = limbs[i]; }
7878 nlimbs = nlimbs.saturating_sub(ws);
7879 }
7880 if bit > 0 && nlimbs > 0 {
7881 let mask = (1u32 << bit) - 1;
7882 if limbs[0] & mask != 0 { has_rest = true; }
7883 for i in 0..nlimbs - 1 {
7884 limbs[i] = (limbs[i] >> bit) | (limbs[i + 1] << (32 - bit));
7885 }
7886 limbs[nlimbs - 1] >>= bit;
7887 }
7888 }
7889
7890 while nlimbs > 0 && limbs[nlimbs - 1] == 0 { nlimbs -= 1; }
7891
7892 let ndigits = p + 2;
7893 let mut all_digits = [0u8; 25];
7894 let mut nd = 0usize;
7895 if nlimbs > 0 {
7896 loop {
7897 let mut all_zero = true;
7898 for i in 0..nlimbs { if limbs[i] != 0 { all_zero = false; break; } }
7899 if all_zero { break; }
7900 let mut rem64 = 0u64;
7901 for i in (0..nlimbs).rev() {
7902 let val = (rem64 << 32) | limbs[i] as u64;
7903 limbs[i] = (val / 10) as u32;
7904 rem64 = val % 10;
7905 }
7906 if nd < 25 { all_digits[nd] = rem64 as u8; }
7907 nd += 1;
7908 }
7909 }
7910
7911 if nd >= ndigits {
7912 for i in 0..ndigits { fbuf[ndigits - 1 - i] = all_digits[i]; }
7913 } else {
7914 for i in 0..nd { fbuf[ndigits - 1 - i] = all_digits[i]; }
7915 for i in nd..ndigits { fbuf[ndigits - 1 - i] = 0; }
7916 }
7917
7918 int_part = fbuf[0] as u64;
7919
7920 if p > 0 {
7922 let next_d = fbuf[p + 1];
7923 let last_d = fbuf[p];
7924 if next_d > 5 || (next_d == 5 && (has_rest || last_d & 1 != 0)) {
7925 let mut carry = true;
7926 for j in (1..=p).rev() {
7927 if !carry { break; }
7928 let d = fbuf[j] + 1;
7929 if d < 10 { fbuf[j] = d; carry = false; break; }
7930 fbuf[j] = 0;
7931 }
7932 if carry { int_part += 1; }
7933 }
7934 } else {
7935 let next_d = fbuf[1];
7936 if next_d > 5 || (next_d == 5 && (has_rest || int_part & 1 != 0)) {
7937 int_part += 1;
7938 }
7939 }
7940
7941 for i in 0..p { fbuf[i] = fbuf[i + 1]; }
7944 }
7945
7946 if !use_f && int_part >= 10 {
7947 exp += 1;
7948 int_part = 1;
7949 }
7950
7951 if use_f {
7953 let (ibuf, ilen) = format_u64(int_part);
7955 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), dst.add(pos), ilen);
7956 pos += ilen;
7957 if p > 0 || flags & FLAG_HASH != 0 {
7958 *dst.add(pos) = b'.'; pos += 1;
7959 for idx in 0..p { *dst.add(pos) = b'0' + fbuf[idx]; pos += 1; }
7960 }
7961 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7962 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7963 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7964 }
7965 } else {
7966 *dst.add(pos) = b'0' + int_part as u8; pos += 1;
7968 if p > 0 || flags & FLAG_HASH != 0 {
7969 *dst.add(pos) = b'.'; pos += 1;
7970 for idx in 0..p { *dst.add(pos) = b'0' + fbuf[idx]; pos += 1; }
7971 }
7972 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7973 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7974 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7975 }
7976 let ec = if uppercase { b'E' } else { b'e' };
7977 *dst.add(pos) = ec; pos += 1;
7978 *dst.add(pos) = if exp < 0 { b'-' } else { b'+' }; pos += 1;
7979 let eabs = if exp < 0 { (-exp) as u32 } else { exp as u32 };
7980 if eabs < 10 { *dst.add(pos) = b'0'; pos += 1; }
7981 let (ebuf, elen) = format_u64(eabs as u64);
7982 core::ptr::copy_nonoverlapping(ebuf.as_ptr(), dst.add(pos), elen);
7983 pos += elen;
7984 }
7985
7986 pos
7987}
7988
7989unsafe fn compute_exp10(v: f64) -> i32 {
7991 let e = libm::floor(libm::log10(v)) as i32;
7992 let probe = v / libm::pow(10.0, e as f64);
7993 if probe >= 10.0 { e + 1 }
7994 else if probe < 1.0 { e - 1 }
7995 else { e }
7996}
7997
7998unsafe fn fmt_hex_float(dst: *mut u8, val: f64, precision: i32, _flags: u8, uppercase: bool) -> usize {
8000 if val.to_bits() & 0x7FFFFFFFFFFFFFFF == 0 {
8002 let lc = !uppercase;
8003 let pfx: &[u8] = if lc { b"0x" } else { b"0X" };
8004 let p = if precision < 0 { 0usize } else { precision as usize };
8005 let mut pos = 0usize;
8006 core::ptr::copy_nonoverlapping(pfx.as_ptr(), dst.add(pos), 2); pos += 2;
8007 *dst.add(pos) = b'0'; pos += 1;
8008 if p > 0 {
8009 *dst.add(pos) = b'.'; pos += 1;
8010 for _ in 0..p { *dst.add(pos) = b'0'; pos += 1; }
8011 }
8012 let pc = if lc { b'p' } else { b'P' };
8013 *dst.add(pos) = pc; pos += 1;
8014 *dst.add(pos) = b'+'; pos += 1;
8015 *dst.add(pos) = b'0'; pos += 1;
8016 return pos;
8017 }
8018 let bits = val.to_bits();
8019 let exp_bits = ((bits >> 52) & 0x7FF) as i32;
8020 let mant_bits = bits & 0x000FFFFFFFFFFFFF;
8021 let (mut e, mut m) = if exp_bits == 0 { (1 - 1023, mant_bits) } else { (exp_bits - 1023, mant_bits | (1u64 << 52)) };
8022 if exp_bits == 0 && m != 0 {
8025 let shift = m.leading_zeros() as i32 - 11;
8026 m <<= shift;
8027 e -= shift;
8028 }
8029 let explicit = precision >= 0;
8030 let p = if explicit { precision as usize } else { 13usize };
8031 let mut pos = 0usize;
8032 let lc = !uppercase;
8033 let pfx: &[u8] = if lc { b"0x" } else { b"0X" };
8034 core::ptr::copy_nonoverlapping(pfx.as_ptr(), dst.add(pos), 2); pos += 2;
8035
8036 let lead_pos = pos;
8038 let mut lead = ((m >> 52) & 0xF) as u8;
8039 *dst.add(pos) = hex_digit_char(lead, lc); pos += 1;
8040 let mut frac_start = pos;
8041 if p > 0 {
8042 *dst.add(pos) = b'.'; pos += 1;
8043 frac_start = pos;
8044 }
8045
8046 let mut rm = m;
8048 for _ in 0..p {
8049 let nib = ((rm >> 48) & 0xF) as u8;
8050 *dst.add(pos) = hex_digit_char(nib, lc); pos += 1;
8051 rm <<= 4;
8052 }
8053
8054 let round_nib = ((rm >> 48) & 0xF) as u8;
8056 let rest = rm & 0x0000FFFFFFFFFFFF;
8057 let last_nib = if p > 0 {
8058 hex_char_val(*dst.add(pos - 1))
8059 } else {
8060 lead
8061 };
8062 let should_round = round_nib > 8 || (round_nib == 8 && (rest != 0 || (last_nib & 1) != 0));
8063 if should_round {
8064 let mut j = pos;
8065 loop {
8066 if j == frac_start {
8067 lead += 1;
8069 *dst.add(lead_pos) = hex_digit_char(lead, lc);
8070 break;
8071 }
8072 j -= 1;
8073 let v = hex_char_val(*dst.add(j));
8074 if v < 15 {
8075 *dst.add(j) = hex_digit_char(v + 1, lc);
8076 break;
8077 }
8078 *dst.add(j) = b'0';
8079 }
8080 }
8081
8082 if !explicit {
8085 while pos > frac_start && *dst.add(pos - 1) == b'0' {
8086 pos -= 1;
8087 }
8088 if pos == frac_start {
8089 pos = frac_start - 1;
8090 }
8091 }
8092
8093 let pc = if lc { b'p' } else { b'P' };
8095 *dst.add(pos) = pc; pos += 1;
8096 *dst.add(pos) = if e < 0 { b'-' } else { b'+' }; pos += 1;
8097 let eabs = if e < 0 { (-e) as u32 } else { e as u32 };
8098 let (ebuf, elen) = format_u64(eabs as u64);
8099 core::ptr::copy_nonoverlapping(ebuf.as_ptr(), dst.add(pos), elen);
8100 pos += elen;
8101 pos
8102}
8103
8104#[inline]
8105fn hex_digit_char(v: u8, lowercase: bool) -> u8 {
8106 if v < 10 { b'0' + v }
8107 else if lowercase { b'a' + v - 10 }
8108 else { b'A' + v - 10 }
8109}
8110
8111#[inline]
8112fn hex_char_val(c: u8) -> u8 {
8113 if c >= b'0' && c <= b'9' { c - b'0' }
8114 else if c >= b'a' && c <= b'f' { c - b'a' + 10 }
8115 else if c >= b'A' && c <= b'F' { c - b'A' + 10 }
8116 else { 0 }
8117}
8118
8119unsafe fn apply_width_flags(
8122 dst: *mut u8, buf: *const u8, len: usize, width: usize, flags: u8,
8123) -> usize {
8124 if len >= width {
8125 core::ptr::copy_nonoverlapping(buf, dst, len);
8126 return len;
8127 }
8128 let pad = width - len;
8129 let pad_char = if flags & FLAG_ZERO != 0 && flags & FLAG_MINUS == 0 { b'0' } else { b' ' };
8130 if flags & FLAG_MINUS != 0 {
8131 core::ptr::copy_nonoverlapping(buf, dst, len);
8133 for i in 0..pad { *dst.add(len + i) = pad_char; }
8134 } else {
8135 if flags & FLAG_ZERO != 0 && len > 0 {
8138 let first = *buf;
8139 if first == b'-' || first == b'+' || first == b' ' {
8140 *dst = first;
8141 for i in 0..pad { *dst.add(1 + i) = pad_char; }
8142 core::ptr::copy_nonoverlapping(buf.add(1), dst.add(1 + pad), len - 1);
8143 return width;
8144 }
8145 }
8146 for i in 0..pad { *dst.add(i) = pad_char; }
8147 core::ptr::copy_nonoverlapping(buf, dst.add(pad), len);
8148 }
8149 width
8150}
8151
8152#[no_mangle]
8153pub unsafe extern "C" fn vprintf(fmt: *const c_char, mut args: VaList) -> c_int {
8154 impl_format!(fmt, args,
8155 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stdout); },
8156 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stdout); }
8157 )
8158}
8159
8160#[no_mangle]
8161pub unsafe extern "C" fn vfprintf(stream: *mut FILE, fmt: *const c_char, mut args: VaList) -> c_int {
8162 impl_format!(fmt, args,
8163 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stream); },
8164 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stream); }
8165 )
8166}
8167
8168#[no_mangle]
8169pub unsafe extern "C" fn printf(fmt: *const c_char, mut args: ...) -> c_int {
8170 impl_format!(fmt, args,
8171 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stdout); },
8172 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stdout); }
8173 )
8174}
8175
8176#[no_mangle]
8177pub unsafe extern "C" fn fprintf(stream: *mut FILE, fmt: *const c_char, mut args: ...) -> c_int {
8178 impl_format!(fmt, args,
8179 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stream); },
8180 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stream); }
8181 )
8182}
8183
8184#[no_mangle]
8185unsafe fn format_write_fd(fd: c_int, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
8186 let mut stack = [0u8; 4096];
8189 let mut a1 = args.clone();
8190 let n = format_to_buf(stack.as_mut_ptr(), stack.len(), fmt, &mut a1);
8191 if n < 0 { return -1; }
8192 if (n as usize) < stack.len() {
8193 let w = crate::write(fd, stack.as_ptr() as *const c_void, n as usize);
8194 if w < 0 { return -1; }
8195 return n;
8196 }
8197 let heap = crate::malloc(n as usize + 1) as *mut u8;
8198 if heap.is_null() { return -1; }
8199 let mut a2 = args.clone();
8200 let n2 = format_to_buf(heap, n as usize + 1, fmt, &mut a2);
8201 if n2 < 0 { crate::free(heap as *mut c_void); return -1; }
8202 let w = crate::write(fd, heap as *const c_void, n2 as usize);
8203 crate::free(heap as *mut c_void);
8204 if w < 0 { return -1; }
8205 n2
8206}
8207
8208#[no_mangle]
8209pub unsafe extern "C" fn dprintf(fd: c_int, fmt: *const c_char, mut args: ...) -> c_int {
8210 format_write_fd(fd, fmt, &mut args)
8211}
8212
8213#[no_mangle]
8214pub unsafe extern "C" fn vdprintf(fd: c_int, fmt: *const c_char, mut args: VaList) -> c_int {
8215 format_write_fd(fd, fmt, &mut args)
8216}
8217
8218unsafe fn format_to_buf(buf: *mut u8, cap: usize, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
8223 let mut pos = 0usize;
8224 let mut i = 0usize;
8225 let mut count = 0usize;
8226 macro_rules! wc {
8227 ($c:expr) => { if pos < cap { *buf.add(pos) = $c; } pos += 1; count += 1; }
8228 }
8229 macro_rules! ws {
8230 ($s:expr, $len:expr) => {{
8231 let __len = $len;
8232 for k in 0..__len { if pos + k < cap { *buf.add(pos + k) = *$s.add(k); } }
8233 pos += __len; count += __len;
8234 }}
8235 }
8236 macro_rules! ws_buf {
8238 ($src:expr, $len:expr) => {{
8239 let __len = $len;
8240 for k in 0..__len { if pos + k < cap { *buf.add(pos + k) = *$src.add(k); } }
8241 pos += __len; count += __len;
8242 }}
8243 }
8244 loop {
8245 let c = *fmt.add(i) as u8;
8246 if c == 0 { break; }
8247 if c != b'%' { wc!(c); i += 1; continue; }
8248 i += 1;
8249 let mut flags: u8 = 0;
8251 loop {
8252 let fc = *fmt.add(i) as u8;
8253 match fc {
8254 b'-' => { flags |= FLAG_MINUS; i += 1; }
8255 b'+' => { flags |= FLAG_PLUS; i += 1; }
8256 b' ' => { flags |= FLAG_SPACE; i += 1; }
8257 b'0' => { flags |= FLAG_ZERO; i += 1; }
8258 b'#' => { flags |= FLAG_HASH; i += 1; }
8259 _ => break,
8260 }
8261 }
8262 let mut width: usize = 0;
8264 if *fmt.add(i) as u8 == b'*' {
8265 width = args.next_arg::<c_int>() as usize; i += 1;
8266 } else {
8267 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
8268 width = width * 10 + ((*fmt.add(i) as u8) - b'0') as usize; i += 1;
8269 }
8270 }
8271 let mut precision: i32 = -1;
8273 if *fmt.add(i) as u8 == b'.' {
8274 i += 1;
8275 if *fmt.add(i) as u8 == b'*' {
8276 precision = args.next_arg::<c_int>(); i += 1;
8277 } else {
8278 precision = 0;
8279 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
8280 precision = precision * 10 + ((*fmt.add(i) as u8) - b'0') as i32; i += 1;
8281 }
8282 }
8283 }
8284 let len_mod = *fmt.add(i) as u8;
8286 let spec: u8;
8287 if len_mod == b'h' || len_mod == b'l' || len_mod == b'j' || len_mod == b'z' || len_mod == b't' || len_mod == b'L' {
8288 i += 1;
8289 let len_mod2 = *fmt.add(i) as u8;
8290 if (len_mod == b'h' && len_mod2 == b'h') || (len_mod == b'l' && len_mod2 == b'l') {
8291 i += 1;
8292 spec = *fmt.add(i) as u8;
8293 match (len_mod, len_mod2, spec) {
8294 (b'h', b'h', b'n') => {
8295 let p = args.next_arg::<*mut c_void>();
8296 if !p.is_null() { *(p as *mut u8) = count as u8; }
8297 }
8298 (b'l', b'l', b'n') => {
8299 let p = args.next_arg::<*mut c_void>();
8300 if !p.is_null() { *(p as *mut c_longlong) = count as c_longlong; }
8301 }
8302 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
8303 let val = args.next_arg::<c_longlong>();
8304 let neg = val < 0;
8305 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
8306 let b = format_u64(abs);
8307 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
8308 let mut fbuf = [0u8; 32];
8309 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
8310 ws_buf!(fbuf.as_ptr(), len);
8311 }
8312 (b'l', b'l', b'u') => {
8313 let val = args.next_arg::<c_ulonglong>();
8314 let b = format_u64(val as u64);
8315 let mut fbuf = [0u8; 32];
8316 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8317 ws_buf!(fbuf.as_ptr(), len);
8318 }
8319 (b'l', b'l', b'o') => {
8320 let val = args.next_arg::<c_ulonglong>();
8321 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
8322 let mut fbuf = [0u8; 32];
8323 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8324 ws_buf!(fbuf.as_ptr(), len);
8325 }
8326 (b'l', b'l', b'x') | (b'l', b'l', b'X') => {
8327 let val = args.next_arg::<c_ulonglong>();
8328 let b = format_hex(val as u64, spec == b'X');
8329 let pc = if spec == b'X' { b'X' } else { b'x' };
8330 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(pc) } else { None };
8331 let mut fbuf = [0u8; 32];
8332 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8333 ws_buf!(fbuf.as_ptr(), len);
8334 }
8335 _ => { wc!(b'%'); wc!(len_mod); wc!(len_mod2); wc!(spec); }
8336 }
8337 } else {
8338 spec = len_mod2;
8339 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
8340 match (lm, spec) {
8341 (b'h', b'n') => {
8342 let p = args.next_arg::<*mut c_void>();
8343 if !p.is_null() { *(p as *mut u16) = count as u16; }
8344 }
8345 (b'l', b'n') => {
8346 let p = args.next_arg::<*mut c_void>();
8347 if !p.is_null() { *(p as *mut c_long) = count as c_long; }
8348 }
8349 (b'z', b'n') | (b't', b'n') => {
8350 let p = args.next_arg::<*mut c_void>();
8351 if !p.is_null() { *(p as *mut usize) = count; }
8352 }
8353 (b'j', b'n') => {
8354 let p = args.next_arg::<*mut c_void>();
8355 if !p.is_null() { *(p as *mut c_ulonglong) = count as c_ulonglong; }
8356 }
8357 (b'l', b'd') | (b'l', b'i') => {
8358 let val = args.next_arg::<c_long>();
8359 let neg = val < 0;
8360 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
8361 let b = format_u64(abs);
8362 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
8363 let mut fbuf = [0u8; 32];
8364 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
8365 ws_buf!(fbuf.as_ptr(), len);
8366 }
8367 (b'l', b'u') => {
8368 let val = args.next_arg::<c_ulong>();
8369 let b = format_u64(val as u64);
8370 let mut fbuf = [0u8; 32];
8371 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8372 ws_buf!(fbuf.as_ptr(), len);
8373 }
8374 (b'l', b's') => {
8375 let p = args.next_arg::<*const wchar_t>();
8376 if p.is_null() {
8377 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
8378 let pad = width.saturating_sub(slen);
8379 if flags & FLAG_MINUS != 0 { ws!(b"(null)".as_ptr(), slen); for _ in 0..pad { wc!(b' '); } }
8380 else { for _ in 0..pad { wc!(b' '); } ws!(b"(null)".as_ptr(), slen); }
8381 } else {
8382 let mut mb = [0u8; 4096];
8383 let mut n = wide_to_mb(mb.as_mut_ptr(), mb.len(), p);
8384 if precision >= 0 && (precision as usize) < n { n = precision as usize; }
8385 let pad = width.saturating_sub(n);
8386 if flags & FLAG_MINUS != 0 { ws!(mb.as_ptr(), n); for _ in 0..pad { wc!(b' '); } }
8387 else { for _ in 0..pad { wc!(b' '); } ws!(mb.as_ptr(), n); }
8388 }
8389 }
8390 (b'l', b'c') => {
8391 let ch = args.next_arg::<c_int>();
8392 let mut mb = [0u8; 8];
8393 let mut st: c_uint = 0;
8394 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, ch, &mut st);
8395 if n != !0usize { ws!(mb.as_ptr(), n); }
8396 }
8397 (b'l', b'x') => {
8398 let val = args.next_arg::<c_ulong>();
8399 let b = format_hex(val as u64, false);
8400 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
8401 let mut fbuf = [0u8; 32];
8402 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8403 ws_buf!(fbuf.as_ptr(), len);
8404 }
8405 (b'l', b'X') => {
8406 let val = args.next_arg::<c_ulong>();
8407 let b = format_hex(val as u64, true);
8408 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
8409 let mut fbuf = [0u8; 32];
8410 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8411 ws_buf!(fbuf.as_ptr(), len);
8412 }
8413 (b'l', b'o') => {
8414 let val = args.next_arg::<c_ulong>();
8415 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
8416 let mut fbuf = [0u8; 32];
8417 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8418 ws_buf!(fbuf.as_ptr(), len);
8419 }
8420 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
8421 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
8422 let val = args.next_arg::<f64>();
8423 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8424 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8425 let mut fbuf = [0u8; 4224];
8426 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8427 let mut wbuf = [0u8; 4224];
8428 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8429 ws_buf!(wbuf.as_ptr(), wlen);
8430 }
8431 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
8432 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
8433 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
8434 let val = {
8435 let lo: u64 = args.next_arg::<u64>();
8436 let hi: u64 = args.next_arg::<u64>();
8437 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
8438 f128::from_bits(combined) as f64
8439 };
8440 #[cfg(target_arch = "x86_64")]
8441 let val = args.next_arg::<f64>();
8442 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8443 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8444 let mut fbuf = [0u8; 4224];
8445 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8446 let mut wbuf = [0u8; 4224];
8447 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8448 ws_buf!(wbuf.as_ptr(), wlen);
8449 }
8450 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); }
8451 }
8452 }
8453 } else {
8454 spec = *fmt.add(i) as u8;
8455 match spec {
8456 b's' => {
8457 let s = args.next_arg::<*const c_char>();
8458 if s.is_null() {
8459 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
8460 let padded_len = if width > slen { width } else { slen };
8461 let pad = padded_len - slen;
8462 if flags & FLAG_MINUS != 0 {
8463 ws!(b"(null)".as_ptr(), slen);
8464 for _ in 0..pad { wc!(b' '); }
8465 } else {
8466 for _ in 0..pad { wc!(b' '); }
8467 ws!(b"(null)".as_ptr(), slen);
8468 }
8469 } else {
8470 let full_len = strlen(s as *const c_char);
8471 let slen = if precision >= 0 { (precision as usize).min(full_len) } else { full_len };
8472 let padded_len = if width > slen { width } else { slen };
8473 let pad = padded_len - slen;
8474 if flags & FLAG_MINUS != 0 {
8475 ws!(s as *const u8, slen);
8476 for _ in 0..pad { wc!(b' '); }
8477 } else {
8478 for _ in 0..pad { wc!(b' '); }
8479 ws!(s as *const u8, slen);
8480 }
8481 }
8482 }
8483 b'd' | b'i' => {
8484 let d = args.next_arg::<c_int>();
8485 let neg = d < 0;
8486 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
8487 let b = format_u64(abs);
8488 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
8489 let mut fbuf = [0u8; 32];
8490 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
8491 ws_buf!(fbuf.as_ptr(), len);
8492 }
8493 b'u' => {
8494 let u = args.next_arg::<c_uint>();
8495 let b = format_u64(u as u64);
8496 let mut fbuf = [0u8; 32];
8497 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8498 ws_buf!(fbuf.as_ptr(), len);
8499 }
8500 b'x' => {
8501 let x = args.next_arg::<c_uint>();
8502 let b = format_hex(x as u64, false);
8503 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
8504 let mut fbuf = [0u8; 32];
8505 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8506 ws_buf!(fbuf.as_ptr(), len);
8507 }
8508 b'X' => {
8509 let x = args.next_arg::<c_uint>();
8510 let b = format_hex(x as u64, true);
8511 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
8512 let mut fbuf = [0u8; 32];
8513 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8514 ws_buf!(fbuf.as_ptr(), len);
8515 }
8516 b'o' => {
8517 let o = args.next_arg::<c_uint>();
8518 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
8519 let mut fbuf = [0u8; 32];
8520 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8521 ws_buf!(fbuf.as_ptr(), len);
8522 }
8523 b'c' => {
8524 let ch = args.next_arg::<c_int>();
8525 if width > 1 {
8526 let pad = width - 1;
8527 if flags & FLAG_MINUS != 0 {
8528 wc!(ch as u8);
8529 for _ in 0..pad { wc!(b' '); }
8530 } else {
8531 for _ in 0..pad { wc!(b' '); }
8532 wc!(ch as u8);
8533 }
8534 } else {
8535 wc!(ch as u8);
8536 }
8537 }
8538 b'p' => {
8539 wc!(b'0'); wc!(b'x');
8540 let p = args.next_arg::<*const c_void>();
8541 let b = format_hex(p as u64, false);
8542 ws!(b.0.as_ptr(), b.1);
8543 }
8544 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
8545 let val = args.next_arg::<f64>();
8546 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8547 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8548 let mut fbuf = [0u8; 4224];
8549 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8550 let mut wbuf = [0u8; 4224];
8551 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8552 ws_buf!(wbuf.as_ptr(), wlen);
8553 }
8554 b'%' => { wc!(b'%'); }
8555 b'n' => {
8556 let p = args.next_arg::<*mut c_void>();
8557 if !p.is_null() { *(p as *mut c_int) = count as c_int; }
8558 }
8559 _ => { wc!(b'%'); wc!(spec); }
8560 }
8561 }
8562 i += 1;
8563 }
8564 if cap > 0 { let null_pos = if pos < cap { pos } else { cap - 1 }; *buf.add(null_pos) = 0; }
8565 count as c_int
8566}
8567
8568#[no_mangle]
8569pub unsafe extern "C" fn vsprintf(buf: *mut c_char, fmt: *const c_char, mut args: VaList) -> c_int {
8570 format_to_buf(buf as *mut u8, usize::MAX, fmt, &mut args)
8571}
8572
8573#[no_mangle]
8574pub unsafe extern "C" fn vsnprintf(buf: *mut c_char, size: usize, fmt: *const c_char, mut args: VaList) -> c_int {
8575 format_to_buf(buf as *mut u8, size, fmt, &mut args)
8576}
8577
8578#[no_mangle]
8579pub unsafe extern "C" fn sprintf(buf: *mut c_char, fmt: *const c_char, mut args: ...) -> c_int {
8580 format_to_buf(buf as *mut u8, usize::MAX, fmt, &mut args)
8581}
8582
8583#[no_mangle]
8584pub unsafe extern "C" fn snprintf(buf: *mut c_char, size: usize, fmt: *const c_char, mut args: ...) -> c_int {
8585 format_to_buf(buf as *mut u8, size, fmt, &mut args)
8586}
8587
8588#[no_mangle]
8589pub unsafe extern "C" fn vasprintf(strp: *mut *mut c_char, fmt: *const c_char, ap: VaList) -> c_int {
8590 let len = vsnprintf(core::ptr::null_mut(), 0, fmt, ap.clone());
8591 if len < 0 {
8592 *strp = core::ptr::null_mut();
8593 return -1;
8594 }
8595 let p = malloc((len as usize) + 1) as *mut c_char;
8596 if p.is_null() {
8597 *strp = core::ptr::null_mut();
8598 return -1;
8599 }
8600 let ret = vsnprintf(p, (len as usize) + 1, fmt, ap.clone());
8601 if ret < 0 {
8602 free(p as *mut c_void);
8603 *strp = core::ptr::null_mut();
8604 return -1;
8605 }
8606 *strp = p;
8607 ret
8608}
8609
8610#[no_mangle]
8611pub unsafe extern "C" fn asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int {
8612 vasprintf(strp, fmt, args)
8613}
8614
8615unsafe fn skip_ws(p: *const u8) -> *const u8 {
8620 let mut q = p;
8621 while *q == b' ' || *q == b'\t' || *q == b'\n' || *q == b'\r' { q = q.add(1); }
8622 q
8623}
8624
8625#[inline]
8626fn is_ws_byte(c: u8) -> bool {
8627 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == 0x0b || c == 0x0c
8628}
8629
8630unsafe fn scan_int_val(
8633 buf: *const u8, pos: &mut usize, buf_len: usize, base: u32, width: usize,
8634) -> (u64, bool, bool) {
8635 let start = *pos;
8636 let max = if width > 0 { (start + width).min(buf_len) } else { buf_len };
8637 let neg = if *pos < max && *buf.add(*pos) == b'-' { *pos += 1; true }
8638 else if *pos < max && *buf.add(*pos) == b'+' { *pos += 1; false }
8639 else { false };
8640 if *pos >= max { *pos = start; return (0, false, false); }
8641 let mut base = base;
8642 let mut val: u64 = 0;
8643 if (base == 0 || base == 16) && *pos < max && *buf.add(*pos) == b'0' {
8645 *pos += 1;
8646 if *pos < max && (*buf.add(*pos) == b'x' || *buf.add(*pos) == b'X') {
8647 *pos += 1;
8648 if *pos < max {
8649 if let Some(d) = hex_val(*buf.add(*pos)) {
8650 val = d as u64; *pos += 1;
8651 while *pos < max { if let Some(d) = hex_val(*buf.add(*pos)) { val = val.wrapping_mul(16).wrapping_add(d as u64); *pos += 1; } else { break; } }
8652 return (val, neg, true);
8653 }
8654 }
8655 return (0, neg, false);
8656 } else if base == 0 {
8657 while *pos < max { let c = *buf.add(*pos); if c >= b'0' && c <= b'7' { val = val.wrapping_mul(8).wrapping_add((c - b'0') as u64); *pos += 1; } else { break; } }
8658 return (val, neg, true);
8659 } else {
8660 while *pos < max {
8663 if let Some(d) = hex_val(*buf.add(*pos)) {
8664 val = val.wrapping_mul(16).wrapping_add(d as u64);
8665 *pos += 1;
8666 } else {
8667 break;
8668 }
8669 }
8670 return (val, neg, true);
8671 }
8672 }
8673 if base == 0 { base = 10; }
8674 let mut found = false;
8675 while *pos < max {
8676 let c = *buf.add(*pos);
8677 let d: Option<u64> = match base {
8678 8 => if c >= b'0' && c <= b'7' { Some((c - b'0') as u64) } else { None },
8679 10 => if c >= b'0' && c <= b'9' { Some((c - b'0') as u64) } else { None },
8680 16 => hex_val(c).map(|v| v as u64),
8681 _ => None,
8682 };
8683 match d { Some(digit) => { val = val.wrapping_mul(base as u64).wrapping_add(digit); *pos += 1; found = true; } None => break }
8684 }
8685 if !found { *pos = start; return (0, false, false); }
8686 (val, neg, true)
8687}
8688
8689unsafe fn scan_float_val(
8691 buf: *const u8, pos: &mut usize, buf_len: usize, width: usize,
8692) -> (f64, bool) {
8693 let start = *pos;
8694 let max = if width > 0 { (start + width).min(buf_len) } else { buf_len };
8695 let neg = if *pos < max && *buf.add(*pos) == b'-' { *pos += 1; true }
8696 else if *pos < max && *buf.add(*pos) == b'+' { *pos += 1; false }
8697 else { false };
8698 if *pos + 2 < max {
8700 let (c0,c1,c2) = (*buf.add(*pos), *buf.add(*pos+1), *buf.add(*pos+2));
8701 if (c0==b'i'||c0==b'I')&&(c1==b'n'||c1==b'N')&&(c2==b'f'||c2==b'F') { *pos+=3; return (if neg{f64::NEG_INFINITY}else{f64::INFINITY}, true); }
8702 if (c0==b'n'||c0==b'N')&&(c1==b'a'||c1==b'A')&&(c2==b'n'||c2==b'N') { *pos+=3; return (if neg{-f64::NAN}else{f64::NAN}, true); }
8703 }
8704 if *pos+1 < max && *buf.add(*pos)==b'0' && (*buf.add(*pos+1)==b'x'||*buf.add(*pos+1)==b'X') {
8706 *pos += 2;
8707 let mut val: f64 = 0.0; let mut found = false; let mut frac_scale = 1.0f64; let mut in_frac = false;
8708 while *pos < max {
8709 if let Some(d) = hex_val(*buf.add(*pos)) {
8710 if in_frac { frac_scale /= 16.0; val += d as f64 * frac_scale; } else { val = val * 16.0 + d as f64; }
8711 *pos += 1; found = true;
8712 } else if *buf.add(*pos)==b'.' && !in_frac { in_frac = true; *pos += 1; } else { break; }
8713 }
8714 if !found { *pos = start; return (0.0, false); }
8715 if *pos < max && (*buf.add(*pos)==b'p'||*buf.add(*pos)==b'P') {
8717 *pos += 1;
8718 let mut eneg = false;
8719 if *pos<max && *buf.add(*pos)==b'-' { eneg=true; *pos+=1; }
8720 else if *pos<max && *buf.add(*pos)==b'+' { *pos+=1; }
8721 let mut ev: i32 = 0; let mut ef = false;
8722 while *pos<max && *buf.add(*pos)>=b'0' && *buf.add(*pos)<=b'9' { ev = ev*10+(*buf.add(*pos)-b'0') as i32; *pos+=1; ef=true; }
8723 if !ef { return (0.0, false); }
8724 if eneg { ev = -ev; }
8725 val *= libm::pow(2.0, ev as f64);
8726 }
8727 return (if neg{-val}else{val}, true);
8728 }
8729 let token_start = start;
8730 let mut i = start;
8731 let mut saw_digit = false;
8732 let mut saw_dot = false;
8733 let mut saw_exp = false;
8734 let mut first = true;
8735 while i < max {
8736 let c = *buf.add(i);
8737 if (c == b'+' || c == b'-') && first {
8738 i += 1; first = false; continue;
8739 }
8740 if c >= b'0' && c <= b'9' {
8741 saw_digit = true; i += 1; first = false; continue;
8742 }
8743 if c == b'.' && !saw_dot && !saw_exp {
8744 saw_dot = true; i += 1; first = false; continue;
8745 }
8746 if (c == b'e' || c == b'E') && !saw_exp && saw_digit {
8747 saw_exp = true; i += 1; first = true; continue;
8748 }
8749 break;
8750 }
8751 if !saw_digit { return (0.0, false); }
8752 let s = core::str::from_utf8_unchecked(core::slice::from_raw_parts(buf.add(token_start), i - token_start));
8753 match <f64 as core::str::FromStr>::from_str(s) {
8754 Ok(v) => { *pos = i; return (v, true); }
8755 Err(_) => { return (0.0, false); }
8756 }
8757}
8758
8759unsafe fn store_scan_int(dest: *mut c_void, len_mod: u8, val: u64, neg: bool) {
8764 let sv: i64 = if neg { (val as i64).wrapping_neg() } else { val as i64 };
8765 match len_mod {
8766 2 => *(dest as *mut i8) = sv as i8,
8767 1 => *(dest as *mut i16) = sv as i16,
8768 3 | 4 => *(dest as *mut i64) = sv,
8769 _ => *(dest as *mut i32) = sv as i32,
8770 }
8771}
8772
8773unsafe fn do_vsscanf(
8774 buf: *const u8, buf_len: usize, fmt: *const c_char, args: &mut VaList<'_>, consumed: *mut usize,
8775) -> c_int {
8776 let mut p = 0usize;
8777 let mut fi = 0usize;
8778 let mut assigned = 0i32;
8779 let mut input_eof = false;
8780 loop {
8781 let fc = *fmt.add(fi) as u8;
8782 if fc == 0 { break; }
8783 if is_ws_byte(fc) {
8784 while is_ws_byte(*fmt.add(fi) as u8) { fi += 1; }
8785 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8786 continue;
8787 }
8788 if fc != b'%' {
8789 if p >= buf_len { input_eof = true; break; }
8790 if *buf.add(p) != fc { break; }
8791 p += 1; fi += 1; continue;
8792 }
8793 fi += 1;
8794 if *fmt.add(fi) as u8 == b'%' {
8796 if p >= buf_len { input_eof = true; break; }
8797 if *buf.add(p) != b'%' { break; }
8798 p += 1; fi += 1; continue;
8799 }
8800 let suppress = if *fmt.add(fi) as u8 == b'*' { fi += 1; true } else { false };
8801 let mut width: usize = 0;
8802 while (*fmt.add(fi) as u8) >= b'0' && (*fmt.add(fi) as u8) <= b'9' {
8803 width = width * 10 + ((*fmt.add(fi) as u8) - b'0') as usize; fi += 1;
8804 }
8805 if *fmt.add(fi) as u8 == b'm' { fi += 1; }
8806 let mut len_mod = 0u8;
8807 match *fmt.add(fi) as u8 {
8808 b'h' => { fi += 1; if *fmt.add(fi) as u8 == b'h' { fi += 1; len_mod = 2; } else { len_mod = 1; } }
8809 b'l' => { fi += 1; if *fmt.add(fi) as u8 == b'l' { fi += 1; len_mod = 4; } else { len_mod = 3; } }
8810 b'j' => { fi += 1; len_mod = 4; }
8811 b'z' | b't' => { fi += 1; len_mod = 3; }
8812 b'L' => { fi += 1; len_mod = 5; }
8813 _ => {}
8814 }
8815 let spec = *fmt.add(fi) as u8;
8816 let (real_spec, _real_len) = if spec==b'C' {(b'c',3u8)} else if spec==b'S' {(b's',3u8)} else {(spec,len_mod)};
8817 match real_spec {
8818 b'n' => {
8819 if !suppress {
8820 let out = args.next_arg::<*mut c_void>();
8821 if !out.is_null() {
8822 match len_mod {
8823 1 => *(out as *mut i16) = p as i16,
8824 2 => *(out as *mut i8) = p as i8,
8825 3 | 4 => *(out as *mut i64) = p as i64,
8826 _ => *(out as *mut c_int) = p as c_int,
8827 }
8828 }
8829 }
8830 }
8831 b'd' | b'u' => {
8832 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8833 if p >= buf_len { input_eof = true; break; }
8834 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8835 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 10, width);
8836 if !ok { break; }
8837 if let Some(out) = dest { if !out.is_null() {
8838 store_scan_int(out, len_mod, val, neg);
8839 }}
8840 if !suppress { assigned += 1; }
8841 }
8842 b'i' => {
8843 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8844 if p >= buf_len { input_eof = true; break; }
8845 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8846 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 0, width);
8847 if !ok { break; }
8848 if let Some(out) = dest { if !out.is_null() { store_scan_int(out, len_mod, val, neg); } }
8849 if !suppress { assigned += 1; }
8850 }
8851 b'o' => {
8852 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8853 if p >= buf_len { input_eof = true; break; }
8854 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8855 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 8, width);
8856 if !ok { break; }
8857 if let Some(out) = dest { if !out.is_null() { store_scan_int(out, len_mod, val, neg); } }
8858 if !suppress { assigned += 1; }
8859 }
8860 b'x' | b'X' => {
8861 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8862 if p >= buf_len { input_eof = true; break; }
8863 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8864 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 16, width);
8865 if !ok { break; }
8866 if let Some(out) = dest { if !out.is_null() { store_scan_int(out, len_mod, val, neg); } }
8867 if !suppress { assigned += 1; }
8868 }
8869 b'p' => {
8870 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8871 if p >= buf_len { input_eof = true; break; }
8872 let dest = if !suppress { Some(args.next_arg::<*mut *mut c_void>()) } else { None };
8873 let (val, _, ok) = scan_int_val(buf, &mut p, buf_len, 16, width);
8874 if !ok { break; }
8875 if let Some(out) = dest { if !out.is_null() { *out = val as usize as *mut c_void; } }
8876 if !suppress { assigned += 1; }
8877 }
8878 b'a' | b'e' | b'f' | b'g' | b'A' | b'E' | b'F' | b'G' => {
8879 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8880 if p >= buf_len { input_eof = true; break; }
8881 let (val, ok) = scan_float_val(buf, &mut p, buf_len, width);
8882 if !ok { break; }
8883 if !suppress {
8884 if _real_len == 3 {
8885 let out = args.next_arg::<*mut f64>(); if !out.is_null() { *out = val; }
8886 } else if _real_len == 5 {
8887 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
8888 { let out = args.next_arg::<*mut f128>(); if !out.is_null() { *out = val as f128; } }
8889 #[cfg(target_arch = "x86_64")]
8890 { let out = args.next_arg::<*mut f64>(); if !out.is_null() { *out = val; } }
8891 } else {
8892 let out = args.next_arg::<*mut f32>(); if !out.is_null() { *out = val as f32; }
8893 }
8894 }
8895 if !suppress { assigned += 1; }
8896 }
8897 b'c' => {
8898 let w = if width > 0 { width } else { 1 };
8899 if p >= buf_len { input_eof = true; break; }
8900 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8901 let start_p = p;
8902 let mut j = 0usize;
8903 while j < w && p < buf_len {
8904 if !dest_ptr.is_null() { *dest_ptr.add(j) = *buf.add(p) as c_char; }
8905 p += 1; j += 1;
8906 }
8907 if j != w { p = start_p; input_eof = true; break; }
8908 if !suppress { assigned += 1; }
8909 }
8910 b's' => {
8911 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8912 if p >= buf_len { input_eof = true; break; }
8913 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8914 let w = if width > 0 { width } else { usize::MAX };
8915 let mut j = 0usize;
8916 while p < buf_len && *buf.add(p) != 0 && !is_ws_byte(*buf.add(p)) && j < w {
8917 if !dest_ptr.is_null() { *dest_ptr.add(j) = *buf.add(p) as c_char; }
8918 p += 1; j += 1;
8919 }
8920 if j == 0 { break; }
8921 if !dest_ptr.is_null() { *dest_ptr.add(j) = 0; }
8922 if !suppress { assigned += 1; }
8923 }
8924 b'[' => {
8925 fi += 1;
8926 let negate = if *fmt.add(fi) as u8 == b'^' { fi += 1; true } else { false };
8927 let mut charset = [0u8; 256];
8928 let mut prev: Option<u8> = None;
8929 if *fmt.add(fi) as u8 == b']' {
8930 charset[b']' as usize] = 1;
8931 prev = Some(b']');
8932 fi += 1;
8933 }
8934 loop {
8935 let c = *fmt.add(fi) as u8;
8936 if c == b']' || c == 0 { break; }
8937 if c == b'-' && prev.is_some() {
8940 let hi = *fmt.add(fi + 1) as u8;
8941 if hi != b']' && hi != 0 {
8942 let lo = prev.unwrap();
8943 let mut k = lo;
8944 while k <= hi {
8945 charset[k as usize] = 1;
8946 if k == 255 { break; }
8947 k += 1;
8948 }
8949 prev = None;
8950 fi += 2;
8951 continue;
8952 }
8953 }
8954 charset[c as usize] = 1;
8955 prev = Some(c);
8956 fi += 1;
8957 }
8958 if *fmt.add(fi) as u8 == b']' { fi += 1; }
8959 fi -= 1; if p >= buf_len { input_eof = true; break; }
8961 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8962 let w = if width > 0 { width } else { usize::MAX };
8963 let mut j = 0usize;
8964 while p < buf_len && *buf.add(p) != 0 && j < w {
8965 let c = *buf.add(p);
8966 let in_set = charset[c as usize] != 0;
8967 if negate { if in_set { break; } } else { if !in_set { break; } }
8968 if !dest_ptr.is_null() { *dest_ptr.add(j) = c as c_char; }
8969 p += 1; j += 1;
8970 }
8971 if j == 0 { break; }
8972 if !dest_ptr.is_null() { *dest_ptr.add(j) = 0; }
8973 if !suppress { assigned += 1; }
8974 }
8975 _ => break,
8976 }
8977 fi += 1;
8978 }
8979 if !consumed.is_null() { *consumed = p; }
8980 if assigned == 0 && input_eof { -1 } else { assigned }
8981}
8982
8983unsafe fn vsscanf_inner(buf: *const u8, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
8984 let len = strlen(buf as *const c_char);
8985 do_vsscanf(buf, len, fmt, args, core::ptr::null_mut())
8986}
8987
8988#[no_mangle]
8989pub unsafe extern "C" fn vsscanf(buf: *const c_char, fmt: *const c_char, mut args: VaList) -> c_int {
8990 vsscanf_inner(buf as *const u8, fmt, &mut args)
8991}
8992
8993#[no_mangle]
8994pub unsafe extern "C" fn vfscanf(stream: *mut FILE, fmt: *const c_char, mut args: VaList) -> c_int {
8995 let f = &mut *stream;
8996 let start_ungotten_count = f.ungotten_count as usize;
8997 let ungotten_saved = f.ungotten;
8998 let sfunc = f.seek_fn;
8999 let start_pos = if sfunc.is_some() { ftello(stream) } else { -1 };
9001
9002 let mut line = [0u8; 4096];
9003 let mut pos = 0usize;
9004
9005 if start_pos >= 0 {
9006 while pos < line.len() - 1 {
9008 let c = fgetc(stream);
9009 if c == -1 { break; }
9010 line[pos] = c as u8;
9011 pos += 1;
9012 if c == b'\n' as c_int { break; }
9013 }
9014 } else {
9015 while f.ungotten_count > 0 && pos < line.len() - 1 {
9020 f.ungotten_count -= 1;
9021 line[pos] = f.ungotten[f.ungotten_count as usize] as u8;
9022 pos += 1;
9023 }
9024 while !f.rpos.is_null() && f.rpos < f.rend && pos < line.len() - 1 {
9026 line[pos] = *f.rpos;
9027 f.rpos = f.rpos.add(1);
9028 pos += 1;
9029 }
9030 let fd = f.fd;
9034 if pos == 0 {
9035 let n = sys_read(fd as i64, line.as_mut_ptr(), 1);
9036 if n == 1 { pos = 1; }
9037 }
9038 let old_flags = sys_fcntl(fd, F_GETFL, 0);
9039 if old_flags >= 0 {
9040 let _ = sys_fcntl(fd, F_SETFL, old_flags | O_NONBLOCK as i64);
9041 }
9042 while pos < line.len() - 1 {
9043 let n = sys_read(fd as i64, line.as_mut_ptr().add(pos), line.len() - 1 - pos);
9044 if n <= 0 { break; }
9045 pos += n as usize;
9046 }
9047 if old_flags >= 0 {
9048 let _ = sys_fcntl(fd, F_SETFL, old_flags);
9049 }
9050 f._eof = 0;
9052 f._err = 0;
9053 f.flags &= !(F_EOF | F_ERR);
9054 }
9055
9056 line[pos] = 0;
9057 if pos == 0 { return 0; }
9058
9059 let mut consumed = 0usize;
9060 let assigned = do_vsscanf(line.as_ptr(), pos, fmt, &mut args, &mut consumed);
9061
9062 if start_pos >= 0 {
9063 let remaining = start_ungotten_count.saturating_sub(consumed);
9066 let target = start_pos + consumed as i64 + remaining as i64;
9069 if let Some(sfunc) = sfunc {
9070 sfunc(stream, target, SEEK_SET);
9071 }
9072 f.rpos = core::ptr::null_mut();
9073 f.rend = core::ptr::null_mut();
9074 if consumed < pos { f._eof = 0; }
9075 f.ungotten_count = 0;
9076 for i in 0..remaining {
9077 f.ungotten[f.ungotten_count as usize] = ungotten_saved[i];
9078 f.ungotten_count += 1;
9079 }
9080 } else {
9081 let unconsumed = pos.saturating_sub(consumed);
9083 if unconsumed > 0 && !f.buf.is_null() {
9084 let copy_count = core::cmp::min(unconsumed, f.buf_size);
9085 core::ptr::copy(
9086 line.as_ptr().add(consumed),
9087 f.buf,
9088 copy_count,
9089 );
9090 f.rpos = f.buf;
9091 f.rend = f.buf.add(copy_count);
9092 }
9093 f.ungotten_count = 0;
9094 f._eof = 0;
9095 f.flags &= !F_EOF;
9096 }
9097 assigned
9098}
9099
9100#[no_mangle]
9101pub unsafe extern "C" fn vscanf(fmt: *const c_char, args: VaList) -> c_int {
9102 vfscanf(stdin, fmt, args)
9103}
9104
9105#[no_mangle]
9106pub unsafe extern "C" fn sscanf(buf: *const c_char, fmt: *const c_char, mut args: ...) -> c_int {
9107 vsscanf_inner(buf as *const u8, fmt, &mut args)
9108}
9109
9110#[no_mangle]
9111pub unsafe extern "C" fn fscanf(stream: *mut FILE, fmt: *const c_char, args: ...) -> c_int {
9112 vfscanf(stream, fmt, args)
9113}
9114
9115#[no_mangle]
9116pub unsafe extern "C" fn scanf(fmt: *const c_char, args: ...) -> c_int {
9117 vfscanf(stdin, fmt, args)
9118}
9119
9120#[no_mangle]
9125pub unsafe extern "C" fn getdelim(
9126 lineptr: *mut *mut c_char, n: *mut usize, delim: c_int, stream: *mut FILE,
9127) -> isize {
9128 if lineptr.is_null() || n.is_null() { return -1; }
9129 let mut cap = *n;
9130 let mut buf = *lineptr;
9131 if buf.is_null() || cap == 0 {
9132 cap = 128;
9133 buf = realloc(buf as *mut c_void, cap) as *mut c_char;
9134 if buf.is_null() { return -1; }
9135 *lineptr = buf;
9136 *n = cap;
9137 }
9138 let mut len = 0usize;
9139 loop {
9140 let c = fgetc(stream);
9141 if c == -1 { if len == 0 { return -1; } break; }
9142 if len + 1 >= cap {
9143 let new_cap = cap.wrapping_mul(2);
9144 let new_buf = realloc(buf as *mut c_void, new_cap) as *mut c_char;
9145 if new_buf.is_null() { return -1; }
9146 buf = new_buf; cap = new_cap;
9147 *lineptr = buf; *n = cap;
9148 }
9149 *buf.add(len) = c as c_char;
9150 len += 1;
9151 if c == delim { break; }
9152 }
9153 *buf.add(len) = 0;
9154 len as isize
9155}
9156
9157#[no_mangle]
9158pub unsafe extern "C" fn getline(lineptr: *mut *mut c_char, n: *mut usize, stream: *mut FILE) -> isize {
9159 getdelim(lineptr, n, b'\n' as c_int, stream)
9160}
9161
9162#[no_mangle]
9167pub unsafe extern "C" fn popen(cmd: *const c_char, mode: *const c_char) -> *mut FILE {
9168 if cmd.is_null() || mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
9169 let m = *mode;
9170 if m != b'r' as c_char && m != b'w' as c_char { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
9171 let mut p: [c_int; 2] = [0; 2];
9172 if sys_pipe2(p.as_mut_ptr(), O_CLOEXEC) < 0 { return core::ptr::null_mut(); }
9173 let op = if m == b'r' as c_char { 0 } else { 1 };
9174 let child_fd = p[1 - op];
9175 let f = fdopen(p[op], mode);
9176 if f.is_null() { sys_close(p[0] as i64); sys_close(p[1] as i64); return core::ptr::null_mut(); }
9177 let pid = sys_fork();
9178 if pid < 0 { fclose(f); sys_close(child_fd as i64); return core::ptr::null_mut(); }
9179 if pid == 0 {
9180 sys_close(p[op] as i64);
9181 if child_fd != (1 - op) as c_int { sys_dup3(child_fd, (1 - op) as c_int, 0); sys_close(child_fd as i64); }
9182 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
9183 let argv = [b"sh\0".as_ptr() as *const c_char, b"-c\0".as_ptr() as *const c_char, cmd, core::ptr::null()];
9184 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
9185 _exit(127);
9186 }
9187 sys_close(child_fd as i64);
9188 (*f).pipe_pid = pid as c_int;
9189 f
9190}
9191
9192#[no_mangle]
9193pub unsafe extern "C" fn pclose(f: *mut FILE) -> c_int {
9194 let pid = (*f).pipe_pid;
9195 let r = fclose(f);
9196 if pid <= 0 { return -1; }
9197 let mut status: c_int = 0;
9198 let mut w: c_int;
9199 loop {
9200 w = waitpid(pid, &mut status, 0);
9201 if w >= 0 || ERRNO!() != EINTR_VAL { break; }
9202 }
9203 if w < 0 || r != 0 { return -1; }
9204 status
9205}
9206
9207const L_TMPNAM: usize = 20;
9212static mut TMPNAM_COUNTER: c_uint = 0;
9213
9214unsafe fn fill_tmpname(out: *mut c_char, seed: c_uint) {
9215 let prefix = b"/tmp/tmp\0";
9216 let mut k = 0;
9217 while k < prefix.len() - 1 { *out.add(k) = prefix[k] as c_char; k += 1; }
9218 let (buf, len) = format_hex(seed as u64, false);
9219 for j in 0..len.min(L_TMPNAM - k - 1) { *out.add(k + j) = buf[j] as c_char; k += 1; }
9220 *out.add(k) = 0;
9221}
9222
9223#[no_mangle]
9224pub unsafe extern "C" fn tmpfile() -> *mut FILE {
9225 let mut name = [0u8; L_TMPNAM];
9226 let mut ctr: c_uint = 0;
9227 loop {
9228 ctr = ctr.wrapping_add(1);
9229 let mut ts: timespec = core::mem::zeroed();
9230 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
9231 let seed = (ts.tv_nsec as c_uint).wrapping_add(ctr);
9232 fill_tmpname(name.as_mut_ptr() as *mut c_char, seed);
9233 let fd = sys_open(name.as_ptr(), (O_RDWR | O_CREAT | O_EXCL) as i64, 0o600);
9234 if fd >= 0 {
9235 sys_unlinkat(AT_FDCWD, name.as_ptr(), 0);
9236 let f = fdopen(fd as c_int, b"w+\0".as_ptr() as *const c_char);
9237 if f.is_null() { sys_close(fd); }
9238 return f;
9239 }
9240 if ctr > 100 { return core::ptr::null_mut(); }
9241 }
9242}
9243
9244#[no_mangle]
9245pub unsafe extern "C" fn tmpnam(s: *mut c_char) -> *mut c_char {
9246 static mut BUF: [c_char; L_TMPNAM] = [0; L_TMPNAM];
9247 let out = if s.is_null() { core::ptr::addr_of_mut!(BUF) as *mut c_char } else { s };
9248 TMPNAM_COUNTER = TMPNAM_COUNTER.wrapping_add(1);
9249 let mut ts: timespec = core::mem::zeroed();
9250 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
9251 let seed = (ts.tv_nsec as c_uint).wrapping_add(TMPNAM_COUNTER);
9252 fill_tmpname(out, seed);
9253 out
9254}
9255
9256#[no_mangle]
9257pub unsafe extern "C" fn remove(path: *const c_char) -> c_int {
9258 if path.is_null() { ERRNO!() = EINVAL; return -1; }
9259 let r = sys_unlinkat(AT_FDCWD, path as *const u8, 0);
9260 if r == 0 {
9261 return 0;
9262 }
9263 if (-r) as c_int == 21 {
9266 return rmdir(path);
9267 }
9268 ERRNO!() = (-r) as c_int;
9269 -1
9270}
9271
9272#[no_mangle]
9273pub unsafe extern "C" fn rename(old: *const c_char, new_: *const c_char) -> c_int {
9274 if old.is_null() || new_.is_null() { ERRNO!() = EINVAL; return -1; }
9275 let r = sys_renameat2(AT_FDCWD, old as *const u8, AT_FDCWD, new_ as *const u8, 0);
9276 if r == 0 { 0 } else { ERRNO!() = (-r) as c_int; -1 }
9277}
9278
9279const MMAP_FAILED: *mut u8 = !0usize as *mut u8;
9284const PAGE: usize = 4096;
9285
9286#[no_mangle]
9291pub unsafe extern "C" fn _exit(code: c_int) -> ! {
9292 sys_exit_group(code)
9293}
9294
9295#[inline]
9296unsafe fn sys_exit_group(code: c_int) -> ! {
9297 <Arch as Syscalls>::syscall_noreturn1(SYS_EXIT_GROUP, code as i64)
9298}
9299
9300#[inline]
9301unsafe fn sys_exit_thread(code: c_int) -> ! {
9302 <Arch as Syscalls>::syscall_noreturn1(SYS_EXIT, code as i64)
9303}
9304
9305#[no_mangle]
9306pub unsafe extern "C" fn _Exit(code: c_int) -> ! {
9307 _exit(code);
9308}
9309
9310#[no_mangle]
9311pub unsafe extern "C" fn exit(code: c_int) -> ! {
9312 fflush(core::ptr::null_mut());
9313 __funcs_on_exit();
9314 _exit(code);
9315}
9316
9317#[no_mangle]
9318pub unsafe extern "C" fn abort() -> ! {
9319 raise(6); _exit(128 + 6);
9321}
9322
9323#[no_mangle]
9326pub static mut __stack_chk_guard: usize = 0;
9327
9328#[no_mangle]
9329pub unsafe extern "C" fn __stack_chk_fail() -> ! {
9330 const MSG: &[u8] = b"*** stack smashing detected ***: terminated\n";
9331 let _ = sys_write(2, MSG.as_ptr(), MSG.len());
9332 abort();
9333}
9334
9335type CmpRfn = unsafe extern "C" fn(*const c_void, *const c_void, *mut c_void) -> c_int;
9340
9341const AR_LEN: usize = 16 * core::mem::size_of::<usize>();
9342const AR_MASK: usize = AR_LEN - 1;
9343
9344unsafe fn qsort_pntz(p: &[usize; 2]) -> i32 {
9345 if p[0] != 1 {
9346 p[0].wrapping_sub(1).trailing_zeros() as i32
9347 } else if p[1] != 0 {
9348 (8 * core::mem::size_of::<usize>()) as i32 + p[1].trailing_zeros() as i32
9349 } else {
9350 0
9351 }
9352}
9353
9354unsafe fn qsort_cycle(width: usize, ar: &mut [*mut u8; AR_LEN], n: usize) {
9355 if n < 2 { return; }
9356 let mut tmp = [0u8; 256];
9357 ar[n] = tmp.as_mut_ptr();
9358 let mut w = width;
9359 while w > 0 {
9360 let l = if 256 < w { 256 } else { w };
9361 core::ptr::copy_nonoverlapping(ar[0], ar[n], l);
9362 for i in 0..n {
9363 core::ptr::copy_nonoverlapping(ar[i + 1], ar[i], l);
9364 ar[i] = ar[i].add(l);
9365 }
9366 w -= l;
9367 }
9368}
9369
9370unsafe fn qsort_shl(p: &mut [usize; 2], n: i32) {
9371 let bits = (8 * core::mem::size_of::<usize>()) as i32;
9372 if n >= bits {
9373 p[1] = p[0];
9374 p[0] = 0;
9375 let n = n - bits;
9376 if n == 0 { return; }
9377 }
9378 p[1] = (p[1] << n) | (p[0] >> (bits - n));
9379 p[0] <<= n;
9380}
9381
9382unsafe fn qsort_shr(p: &mut [usize; 2], n: i32) {
9383 let bits = (8 * core::mem::size_of::<usize>()) as i32;
9384 if n >= bits {
9385 p[0] = p[1];
9386 p[1] = 0;
9387 let n = n - bits;
9388 if n == 0 { return; }
9389 }
9390 p[0] = (p[0] >> n) | (p[1] << (bits - n));
9391 p[1] >>= n;
9392}
9393
9394unsafe fn qsort_sift(
9395 head: *mut u8, width: usize,
9396 cmp: CmpRfn, arg: *mut c_void,
9397 pshift: i32, lp: &[usize],
9398) {
9399 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
9400 ar[0] = head;
9401 let mut i = 1usize;
9402 let mut h = head;
9403 let mut ps = pshift;
9404
9405 while ps > 1 {
9406 let rt = h.sub(width);
9407 let lf = h.sub(width + lp[(ps - 2) as usize]);
9408
9409 if cmp(ar[0] as *const c_void, lf as *const c_void, arg) >= 0
9410 && cmp(ar[0] as *const c_void, rt as *const c_void, arg) >= 0
9411 {
9412 break;
9413 }
9414 if cmp(lf as *const c_void, rt as *const c_void, arg) >= 0 {
9415 ar[i & AR_MASK] = lf;
9416 i += 1;
9417 h = lf;
9418 ps -= 1;
9419 } else {
9420 ar[i & AR_MASK] = rt;
9421 i += 1;
9422 h = rt;
9423 ps -= 2;
9424 }
9425 }
9426 qsort_cycle(width, &mut ar, i & AR_MASK);
9427}
9428
9429unsafe fn qsort_trinkle(
9430 head: *mut u8, width: usize,
9431 cmp: CmpRfn, arg: *mut c_void,
9432 pp: &[usize; 2], pshift: i32, trusty: i32,
9433 lp: &[usize],
9434) {
9435 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
9436 let mut p = *pp;
9437 ar[0] = head;
9438 let mut i = 1usize;
9439 let mut h = head;
9440 let mut ps = pshift;
9441 let mut t = trusty;
9442
9443 while p[0] != 1 || p[1] != 0 {
9444 let stepson = h.sub(lp[ps as usize]);
9445 if cmp(stepson as *const c_void, ar[0] as *const c_void, arg) <= 0 {
9446 break;
9447 }
9448 if t == 0 && ps > 1 {
9449 let rt = h.sub(width);
9450 let lf = h.sub(width + lp[(ps - 2) as usize]);
9451 if cmp(rt as *const c_void, stepson as *const c_void, arg) >= 0
9452 || cmp(lf as *const c_void, stepson as *const c_void, arg) >= 0
9453 {
9454 break;
9455 }
9456 }
9457
9458 ar[i & AR_MASK] = stepson;
9459 i += 1;
9460 h = stepson;
9461 let trail = qsort_pntz(&p);
9462 qsort_shr(&mut p, trail);
9463 ps += trail;
9464 t = 0;
9465 }
9466 if t == 0 {
9467 qsort_cycle(width, &mut ar, i & AR_MASK);
9468 qsort_sift(h, width, cmp, arg, ps, lp);
9469 }
9470}
9471
9472#[no_mangle]
9473pub unsafe extern "C" fn __qsort_r(
9474 base: *mut c_void,
9475 nel: usize,
9476 width: usize,
9477 cmp: CmpRfn,
9478 arg: *mut c_void,
9479) {
9480 let size = width * nel;
9481 if size == 0 { return; }
9482
9483 let mut lp = [0usize; 96];
9484 lp[0] = width;
9485 lp[1] = width;
9486 let mut li = 2;
9487 while {
9488 lp[li] = lp[li - 2] + lp[li - 1] + width;
9489 lp[li] < size
9490 } {
9491 li += 1;
9492 }
9493
9494 let mut head = base as *mut u8;
9495 let high = head.add(size - width);
9496 let mut p: [usize; 2] = [1, 0];
9497 let mut pshift: i32 = 1;
9498
9499 while head < high {
9500 if (p[0] & 3) == 3 {
9501 qsort_sift(head, width, cmp, arg, pshift, &lp);
9502 qsort_shr(&mut p, 2);
9503 pshift += 2;
9504 } else {
9505 if lp[(pshift - 1) as usize] >= (high as usize) - (head as usize) {
9506 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
9507 } else {
9508 qsort_sift(head, width, cmp, arg, pshift, &lp);
9509 }
9510
9511 if pshift == 1 {
9512 qsort_shl(&mut p, 1);
9513 pshift = 0;
9514 } else {
9515 qsort_shl(&mut p, pshift - 1);
9516 pshift = 1;
9517 }
9518 }
9519
9520 p[0] |= 1;
9521 head = head.add(width);
9522 }
9523
9524 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
9525
9526 while pshift != 1 || p[0] != 1 || p[1] != 0 {
9527 if pshift <= 1 {
9528 let trail = qsort_pntz(&p);
9529 qsort_shr(&mut p, trail);
9530 pshift += trail;
9531 } else {
9532 qsort_shl(&mut p, 2);
9533 pshift -= 2;
9534 p[0] ^= 7;
9535 qsort_shr(&mut p, 1);
9536 qsort_trinkle(
9537 head.sub(lp[pshift as usize] + width),
9538 width, cmp, arg, &p, pshift + 1, 1, &lp,
9539 );
9540 qsort_shl(&mut p, 1);
9541 p[0] |= 1;
9542 qsort_trinkle(head.sub(width), width, cmp, arg, &p, pshift, 1, &lp);
9543 }
9544 head = head.sub(width);
9545 }
9546}
9547
9548#[no_mangle]
9549pub unsafe extern "C" fn qsort_r(
9550 base: *mut c_void,
9551 nel: usize,
9552 width: usize,
9553 cmp: CmpRfn,
9554 arg: *mut c_void,
9555) {
9556 __qsort_r(base, nel, width, cmp, arg);
9557}
9558
9559unsafe extern "C" fn qsort_wrap_cmp(
9560 a: *const c_void,
9561 b: *const c_void,
9562 cmp_ctx: *mut c_void,
9563) -> c_int {
9564 let cmp: CmpFn = core::mem::transmute(cmp_ctx);
9565 cmp(a, b)
9566}
9567
9568#[no_mangle]
9569pub unsafe extern "C" fn qsort(
9570 base: *mut c_void,
9571 nel: usize,
9572 width: usize,
9573 cmp: CmpFn,
9574) {
9575 __qsort_r(base, nel, width, qsort_wrap_cmp, cmp as *mut c_void);
9576}
9577
9578const ATEXIT_COUNT: usize = 32;
9583
9584#[repr(C)]
9585struct AtExitBlock {
9586 next: *mut AtExitBlock,
9587 f: [Option<unsafe extern "C" fn(*mut c_void)>; ATEXIT_COUNT],
9588 a: [*mut c_void; ATEXIT_COUNT],
9589}
9590
9591static mut ATEXIT_BUILTIN: AtExitBlock = AtExitBlock {
9592 next: core::ptr::null_mut(),
9593 f: [None; ATEXIT_COUNT],
9594 a: [core::ptr::null_mut(); ATEXIT_COUNT],
9595};
9596static mut ATEXIT_HEAD: *mut AtExitBlock = core::ptr::null_mut();
9597static mut ATEXIT_SLOT: usize = 0;
9598static mut ATEXIT_FINISHED: bool = false;
9599
9600#[no_mangle]
9601pub unsafe extern "C" fn __funcs_on_exit() {
9602 while !ATEXIT_HEAD.is_null() {
9603 let head = ATEXIT_HEAD;
9604 while ATEXIT_SLOT > 0 {
9605 ATEXIT_SLOT -= 1;
9606 if let Some(f) = (*head).f[ATEXIT_SLOT] {
9607 let a = (*head).a[ATEXIT_SLOT];
9608 f(a);
9609 }
9610 }
9611 ATEXIT_HEAD = (*head).next;
9612 ATEXIT_SLOT = ATEXIT_COUNT;
9613 }
9614 ATEXIT_FINISHED = true;
9615}
9616
9617#[no_mangle]
9618pub unsafe extern "C" fn __cxa_atexit(
9619 func: unsafe extern "C" fn(*mut c_void),
9620 arg: *mut c_void,
9621 _dso: *mut c_void,
9622) -> c_int {
9623 if ATEXIT_FINISHED {
9624 return -1;
9625 }
9626 if ATEXIT_HEAD.is_null() {
9627 ATEXIT_HEAD = core::ptr::addr_of_mut!(ATEXIT_BUILTIN);
9628 }
9629 if ATEXIT_SLOT == ATEXIT_COUNT {
9630 let new = calloc(1, core::mem::size_of::<AtExitBlock>()) as *mut AtExitBlock;
9631 if new.is_null() {
9632 return -1;
9633 }
9634 (*new).next = ATEXIT_HEAD;
9635 ATEXIT_HEAD = new;
9636 ATEXIT_SLOT = 0;
9637 }
9638 (*ATEXIT_HEAD).f[ATEXIT_SLOT] = Some(func);
9639 (*ATEXIT_HEAD).a[ATEXIT_SLOT] = arg;
9640 ATEXIT_SLOT += 1;
9641 0
9642}
9643
9644unsafe extern "C" fn atexit_caller(arg: *mut c_void) {
9645 let func: unsafe extern "C" fn() = core::mem::transmute(arg);
9646 func();
9647}
9648
9649#[no_mangle]
9650pub unsafe extern "C" fn atexit(func: unsafe extern "C" fn()) -> c_int {
9651 __cxa_atexit(atexit_caller, func as *mut c_void, core::ptr::null_mut())
9652}
9653
9654#[no_mangle]
9655pub unsafe extern "C" fn __cxa_finalize(_dso: *mut c_void) {}
9656
9657#[no_mangle]
9662pub static mut __environ: *mut *mut c_char = core::ptr::null_mut();
9663
9664const ENV_MAX_ALLOCED: usize = 256;
9666static mut ENV_ALLOCED: [*mut c_char; ENV_MAX_ALLOCED] = [core::ptr::null_mut(); ENV_MAX_ALLOCED];
9667static mut ENV_ALLOCED_N: usize = 0;
9668
9669unsafe fn env_rm_add(old: *mut c_char, mut new: *mut c_char) {
9670 for i in 0..ENV_ALLOCED_N {
9671 if ENV_ALLOCED[i] == old {
9672 ENV_ALLOCED[i] = new;
9673 if !old.is_null() {
9674 free(old as *mut c_void);
9675 }
9676 return;
9677 } else if ENV_ALLOCED[i].is_null() && !new.is_null() {
9678 ENV_ALLOCED[i] = new;
9679 new = core::ptr::null_mut();
9680 }
9681 }
9682 if !new.is_null() && ENV_ALLOCED_N < ENV_MAX_ALLOCED {
9683 ENV_ALLOCED[ENV_ALLOCED_N] = new;
9684 ENV_ALLOCED_N += 1;
9685 }
9686}
9687
9688unsafe fn strchrnul_u8(s: *const u8, c: u8) -> *const u8 {
9689 let mut p = s;
9690 while *p != 0 && *p != c {
9691 p = p.add(1);
9692 }
9693 p
9694}
9695
9696#[no_mangle]
9697pub unsafe extern "C" fn getenv(name: *const c_char) -> *mut c_char {
9698 if __environ.is_null() || name.is_null() {
9699 return core::ptr::null_mut();
9700 }
9701 let name = name as *const u8;
9702 let l = strchrnul_u8(name, b'=') as usize - name as usize;
9703 if l == 0 || *name.add(l) != 0 {
9704 return core::ptr::null_mut();
9705 }
9706 let mut e = __environ;
9707 while !(*e).is_null() {
9708 let entry = *e as *const u8;
9709 if strncmp(entry, name, l) == 0 && *entry.add(l) == b'=' {
9710 return entry.add(l + 1) as *mut c_char;
9711 }
9712 e = e.add(1);
9713 }
9714 core::ptr::null_mut()
9715}
9716
9717#[no_mangle]
9718pub unsafe extern "C" fn setenv(
9719 var: *const c_char,
9720 value: *const c_char,
9721 overwrite: c_int,
9722) -> c_int {
9723 if var.is_null() || value.is_null() {
9724 ERRNO!() = EINVAL;
9725 return -1;
9726 }
9727 let var = var as *const u8;
9728 let l1 = strchrnul_u8(var, b'=') as usize - var as usize;
9729 if l1 == 0 || *var.add(l1) != 0 {
9730 ERRNO!() = EINVAL;
9731 return -1;
9732 }
9733 if overwrite == 0 && !getenv(var as *const c_char).is_null() {
9734 return 0;
9735 }
9736 let l2 = strlen(value as *const c_char);
9737 let s = malloc(l1 + l2 + 2) as *mut u8;
9738 if s.is_null() {
9739 return -1;
9740 }
9741 core::ptr::copy_nonoverlapping(var, s, l1);
9742 *s.add(l1) = b'=';
9743 core::ptr::copy_nonoverlapping(value as *const u8, s.add(l1 + 1), l2 + 1);
9744 putenv_internal(s as *mut c_char, l1, s as *mut c_char)
9745}
9746
9747unsafe fn putenv_internal(s: *mut c_char, l: usize, r: *mut c_char) -> c_int {
9748 let mut i = 0;
9749 if !__environ.is_null() {
9750 let mut e = __environ;
9751 while !(*e).is_null() {
9752 if strncmp(s as *const u8, *e as *const u8, l + 1) == 0 {
9753 let tmp = *e;
9754 *e = s;
9755 env_rm_add(tmp, r);
9756 return 0;
9757 }
9758 e = e.add(1);
9759 i += 1;
9760 }
9761 }
9762 let newenv = malloc(core::mem::size_of::<*mut c_char>() * (i + 2)) as *mut *mut c_char;
9763 if newenv.is_null() {
9764 if !r.is_null() { free(r as *mut c_void); }
9765 return -1;
9766 }
9767 if i > 0 && !__environ.is_null() {
9768 core::ptr::copy_nonoverlapping(__environ, newenv, i);
9769 }
9770 *newenv.add(i) = s;
9771 *newenv.add(i + 1) = core::ptr::null_mut();
9772 __environ = newenv;
9774 environ = __environ;
9775 if !r.is_null() {
9776 env_rm_add(core::ptr::null_mut(), r);
9777 }
9778 0
9779}
9780
9781#[no_mangle]
9782pub unsafe extern "C" fn putenv(s: *mut c_char) -> c_int {
9783 if s.is_null() { return -1; }
9784 let l = strchrnul_u8(s as *const u8, b'=') as usize - s as *const u8 as usize;
9785 if l == 0 || *s.add(l) as u8 == 0 {
9786 return unsetenv(s);
9787 }
9788 putenv_internal(s, l, core::ptr::null_mut())
9789}
9790
9791#[no_mangle]
9792pub unsafe extern "C" fn unsetenv(name: *const c_char) -> c_int {
9793 if name.is_null() {
9794 ERRNO!() = EINVAL;
9795 return -1;
9796 }
9797 let name = name as *const u8;
9798 let l = strchrnul_u8(name, b'=') as usize - name as usize;
9799 if l == 0 || *name.add(l) != 0 {
9800 ERRNO!() = EINVAL;
9801 return -1;
9802 }
9803 if __environ.is_null() {
9804 return 0;
9805 }
9806 let mut e = __environ;
9807 let mut eo = e;
9808 while !(*e).is_null() {
9809 if strncmp(name, *e as *const u8, l) == 0 && *(*e as *const u8).add(l) == b'=' {
9810 env_rm_add(*e, core::ptr::null_mut());
9811 } else {
9812 if eo != e {
9813 *eo = *e;
9814 }
9815 eo = eo.add(1);
9816 }
9817 e = e.add(1);
9818 }
9819 if eo != e {
9820 *eo = core::ptr::null_mut();
9821 }
9822 environ = __environ;
9823 0
9824}
9825
9826#[no_mangle]
9827pub unsafe extern "C" fn clearenv() -> c_int {
9828 let e = __environ;
9829 __environ = core::ptr::null_mut();
9830 environ = core::ptr::null_mut();
9831 if !e.is_null() {
9832 let mut p = e;
9833 while !(*p).is_null() {
9834 env_rm_add(*p, core::ptr::null_mut());
9835 p = p.add(1);
9836 }
9837 }
9838 0
9839}
9840
9841static mut RANDOM_INIT: [u32; 32] = [
9847 0x00000000,0x5851f42d,0xc0b18ccf,0xcbb5f646,
9848 0xc7033129,0x30705b04,0x20fd5db4,0x9a8b7f78,
9849 0x502959d8,0xab894868,0x6c0356a7,0x88cdb7ff,
9850 0xb477d43f,0x70a3a52b,0xa8e4baf1,0xfd8341fc,
9851 0x8ae16fd9,0x742d2f7a,0x0d1f0796,0x76035e09,
9852 0x40f7702c,0x6fa72ca5,0xaaa84157,0x58a0df74,
9853 0xc74a0364,0xae533cc4,0x04185faf,0x6de3b115,
9854 0x0cab8628,0xf043bfa4,0x398150e9,0x37521657,
9855];
9856
9857static mut RANDOM_N: i32 = 31;
9858static mut RANDOM_I: i32 = 3;
9859static mut RANDOM_J: i32 = 0;
9860static mut RANDOM_X: *mut u32 = unsafe { core::ptr::addr_of_mut!(RANDOM_INIT).cast::<u32>().add(1) };
9861
9862unsafe fn random_lcg31(x: u32) -> u32 {
9863 (1103515245u32.wrapping_mul(x).wrapping_add(12345)) & 0x7fffffff
9864}
9865
9866unsafe fn random_lcg64(x: u64) -> u64 {
9867 6364136223846793005u64.wrapping_mul(x).wrapping_add(1)
9868}
9869
9870unsafe fn random_savestate() -> *mut u8 {
9871 (*RANDOM_X.offset(-1)) = ((RANDOM_N as u32) << 16) | ((RANDOM_I as u32) << 8) | (RANDOM_J as u32);
9872 RANDOM_X.offset(-1) as *mut u8
9873}
9874
9875unsafe fn random_loadstate(state: *mut u32) {
9876 RANDOM_X = state.add(1);
9877 RANDOM_N = ((*RANDOM_X.offset(-1)) >> 16) as i32;
9878 RANDOM_I = (((*RANDOM_X.offset(-1)) >> 8) & 0xff) as i32;
9879 RANDOM_J = ((*RANDOM_X.offset(-1)) & 0xff) as i32;
9880}
9881
9882unsafe fn random_srandom_inner(seed: u32) {
9883 let mut s = seed as u64;
9884 if RANDOM_N == 0 {
9885 *RANDOM_X = s as u32;
9886 return;
9887 }
9888 RANDOM_I = if RANDOM_N == 31 || RANDOM_N == 7 { 3 } else { 1 };
9889 RANDOM_J = 0;
9890 for k in 0..RANDOM_N as usize {
9891 s = random_lcg64(s);
9892 *RANDOM_X.add(k) = (s >> 32) as u32;
9893 }
9894 *RANDOM_X |= 1;
9895}
9896
9897#[no_mangle]
9898pub unsafe extern "C" fn srandom(seed: c_uint) {
9899 random_srandom_inner(seed);
9900}
9901
9902#[no_mangle]
9903pub unsafe extern "C" fn initstate(seed: c_uint, state: *mut c_char, size: usize) -> *mut c_char {
9904 if size < 8 { return core::ptr::null_mut(); }
9905 let old = random_savestate();
9906 RANDOM_N = if size < 32 { 0 }
9907 else if size < 64 { 7 }
9908 else if size < 128 { 15 }
9909 else if size < 256 { 31 }
9910 else { 63 };
9911 RANDOM_X = (state as *mut u32).add(1);
9912 random_srandom_inner(seed);
9913 random_savestate();
9914 old as *mut c_char
9915}
9916
9917#[no_mangle]
9918pub unsafe extern "C" fn setstate(state: *mut c_char) -> *mut c_char {
9919 let old = random_savestate();
9920 random_loadstate(state as *mut u32);
9921 old as *mut c_char
9922}
9923
9924#[no_mangle]
9925pub unsafe extern "C" fn random() -> c_long {
9926 let k: c_long;
9927 if RANDOM_N == 0 {
9928 *RANDOM_X = random_lcg31(*RANDOM_X);
9929 k = *RANDOM_X as c_long;
9930 } else {
9931 *RANDOM_X.add(RANDOM_I as usize) = (*RANDOM_X.add(RANDOM_I as usize)).wrapping_add(*RANDOM_X.add(RANDOM_J as usize));
9932 k = (*RANDOM_X.add(RANDOM_I as usize) >> 1) as c_long;
9933 RANDOM_I += 1;
9934 if RANDOM_I == RANDOM_N { RANDOM_I = 0; }
9935 RANDOM_J += 1;
9936 if RANDOM_J == RANDOM_N { RANDOM_J = 0; }
9937 }
9938 k
9939}
9940
9941const SA: u8 = 0xC2;
9946const SB: u8 = 0xF4;
9947
9948const BITTAB: [u32; 51] = [
9949 0xC000_0002, 0xC000_0003, 0xC000_0004, 0xC000_0005, 0xC000_0006, 0xC000_0007,
9950 0xC000_0008, 0xC000_0009, 0xC000_000A, 0xC000_000B, 0xC000_000C, 0xC000_000D,
9951 0xC000_000E, 0xC000_000F, 0xC000_0010, 0xC000_0011, 0xC000_0012, 0xC000_0013,
9952 0xC000_0014, 0xC000_0015, 0xC000_0016, 0xC000_0017, 0xC000_0018, 0xC000_0019,
9953 0xC000_001A, 0xC000_001B, 0xC000_001C, 0xC000_001D, 0xC000_001E, 0xC000_001F,
9954 0xB300_0000, 0xC300_0001, 0xC300_0002, 0xC300_0003, 0xC300_0004, 0xC300_0005,
9955 0xC300_0006, 0xC300_0007, 0xC300_0008, 0xC300_0009, 0xC300_000A, 0xC300_000B,
9956 0xC300_000C, 0xD300_000D, 0xC300_000E, 0xC300_000F, 0xBB0C_0000, 0xC30C_0001,
9957 0xC30C_0002, 0xC30C_0003, 0xDB0C_0004,
9958];
9959
9960#[inline]
9961fn mb_oob(c: u32, b: u8) -> u32 {
9962 let b3 = (b >> 3) as u32;
9963 ((b3.wrapping_sub(0x10)) | (b3.wrapping_add((c as i32 >> 26) as u32))) & !7
9964}
9965
9966static mut MB_STATE: c_uint = 0;
9967
9968const MB_CUR_MAX_VAL_UTF8: usize = 4;
9969const MB_CUR_MAX_VAL_C: usize = 1;
9970
9971#[no_mangle]
9972pub extern "C" fn __ctype_get_mb_cur_max() -> usize {
9973 unsafe { if LOCALE_CTYPE_UTF8 { MB_CUR_MAX_VAL_UTF8 } else { MB_CUR_MAX_VAL_C } }
9974}
9975
9976#[no_mangle]
9977pub unsafe extern "C" fn mbrtowc(
9978 wc: *mut c_int,
9979 src: *const c_char,
9980 n: usize,
9981 st: *mut c_uint,
9982) -> usize {
9983 let s = src as *const u8;
9984 let n0 = n;
9985 let mut dummy: c_int = 0;
9986 let wc = if wc.is_null() { &mut dummy } else { &mut *wc };
9987 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
9988
9989 let mut c: u32 = *st;
9990 let mut s = s;
9991 let mut n = n;
9992
9993 if s.is_null() {
9994 if c != 0 { *st = 0; ERRNO!() = EILSEQ; return !0usize; }
9995 return 0;
9996 }
9997
9998 if n == 0 { return !1usize; }
9999
10000 if unsafe { !LOCALE_CTYPE_UTF8 } {
10001 let b = *s;
10002 *wc = b as c_int;
10003 return if b == 0 { 0 } else { 1 };
10004 }
10005
10006 if c == 0 {
10007 if *s < 0x80 {
10008 let r = if *s == 0 { 0 } else { 1 };
10009 *wc = *s as c_int;
10010 return r;
10011 }
10012 if (*s).wrapping_sub(SA) as u32 > (SB - SA) as u32 {
10013 *st = 0; ERRNO!() = EILSEQ; return !0usize;
10014 }
10015 c = BITTAB[*s as usize - SA as usize];
10016 s = s.add(1);
10017 n -= 1;
10018 }
10019
10020 if n > 0 {
10021 if mb_oob(c, *s) != 0 {
10022 *st = 0; ERRNO!() = EILSEQ; return !0usize;
10023 }
10024 loop {
10025 c = (c << 6) | (*s as u32).wrapping_sub(0x80);
10026 s = s.add(1);
10027 n -= 1;
10028 if c & (1u32 << 31) == 0 {
10029 *st = 0;
10030 *wc = c as c_int;
10031 return n0 - n;
10032 }
10033 if n == 0 { break; }
10034 if (*s).wrapping_sub(0x80) >= 0x40 {
10035 *st = 0; ERRNO!() = EILSEQ; return !0usize;
10036 }
10037 }
10038 }
10039
10040 *st = c;
10041 !1usize
10042}
10043
10044#[no_mangle]
10045pub unsafe extern "C" fn wcrtomb(
10046 s: *mut c_char,
10047 wc: c_int,
10048 _st: *mut c_uint,
10049) -> usize {
10050 if s.is_null() { return 1; }
10051 let wc_u = wc as u32;
10052 if unsafe { !LOCALE_CTYPE_UTF8 } {
10053 if wc_u > 0xFF {
10054 ERRNO!() = EILSEQ;
10055 return !0usize;
10056 }
10057 *s = wc as c_char;
10058 return 1;
10059 }
10060 if wc_u < 0x80 {
10061 *s = wc as c_char;
10062 return 1;
10063 }
10064 if wc_u < 0x800 {
10065 *s = (0xC0 | (wc_u >> 6)) as c_char;
10066 *s.add(1) = (0x80 | (wc_u & 0x3F)) as c_char;
10067 return 2;
10068 }
10069 if wc_u < 0xD800 || wc_u.wrapping_sub(0xE000) < 0x2000 {
10070 *s = (0xE0 | (wc_u >> 12)) as c_char;
10071 *s.add(1) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
10072 *s.add(2) = (0x80 | (wc_u & 0x3F)) as c_char;
10073 return 3;
10074 }
10075 if wc_u.wrapping_sub(0x10000) < 0x100000 {
10076 *s = (0xF0 | (wc_u >> 18)) as c_char;
10077 *s.add(1) = (0x80 | ((wc_u >> 12) & 0x3F)) as c_char;
10078 *s.add(2) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
10079 *s.add(3) = (0x80 | (wc_u & 0x3F)) as c_char;
10080 return 4;
10081 }
10082 ERRNO!() = EILSEQ;
10083 !0usize
10084}
10085
10086#[no_mangle]
10087pub unsafe extern "C" fn mblen(s: *const c_char, n: usize) -> c_int {
10088 if s.is_null() { return 0; }
10089 mbtowc(core::ptr::null_mut(), s, n)
10090}
10091
10092#[no_mangle]
10093pub unsafe extern "C" fn mbtowc(
10094 wc: *mut c_int,
10095 src: *const c_char,
10096 n: usize,
10097) -> c_int {
10098 if src.is_null() { return 0; }
10099 if n == 0 { ERRNO!() = EILSEQ; return -1; }
10100 let mut state: c_uint = 0;
10101 let mut w: c_int = 0;
10102 let r = mbrtowc(&mut w, src, n, &mut state);
10103 if r == !0usize { return -1; }
10104 if !wc.is_null() { *wc = w; }
10105 r as c_int
10106}
10107
10108#[no_mangle]
10109pub unsafe extern "C" fn wctomb(s: *mut c_char, wc: c_int) -> c_int {
10110 if s.is_null() { return 0; }
10111 wcrtomb(s, wc, core::ptr::null_mut()) as c_int
10112}
10113
10114#[no_mangle]
10115pub unsafe extern "C" fn mbsrtowcs(
10116 ws: *mut c_int,
10117 src: *mut *const c_char,
10118 wn: usize,
10119 st: *mut c_uint,
10120) -> usize {
10121 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
10122 let mut s = *src as *const u8;
10123 let wn0 = wn;
10124 let mut wn = wn;
10125
10126 if ws.is_null() {
10127 while *s != 0 {
10128 if *s < 0x80 {
10129 s = s.add(1);
10130 wn = wn.wrapping_sub(1);
10131 continue;
10132 }
10133 let mut wc: c_int = 0;
10134 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
10135 if r == !0usize { return !0usize; }
10136 if r == !1usize { return wn0 - wn; }
10137 s = s.add(r);
10138 wn = wn.wrapping_sub(1);
10139 }
10140 wn0 - wn
10141 } else {
10142 let mut w = ws;
10143 while wn > 0 {
10144 if *s < 0x80 {
10145 let c = *s as c_int;
10146 *w = c;
10147 if c == 0 {
10148 *src = core::ptr::null();
10149 return wn0 - wn;
10150 }
10151 w = w.add(1);
10152 s = s.add(1);
10153 wn -= 1;
10154 continue;
10155 }
10156 let mut wc: c_int = 0;
10157 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
10158 if r == !0usize {
10159 *src = s as *const c_char;
10160 return !0usize;
10161 }
10162 if r == !1usize {
10163 *src = s as *const c_char;
10164 return wn0 - wn;
10165 }
10166 *w = wc;
10167 w = w.add(1);
10168 s = s.add(r);
10169 wn -= 1;
10170 }
10171 *src = s as *const c_char;
10172 wn0 - wn
10173 }
10174}
10175
10176#[no_mangle]
10177pub unsafe extern "C" fn wcsrtombs(
10178 s: *mut c_char,
10179 ws: *mut *const c_int,
10180 n: usize,
10181 _st: *mut c_uint,
10182) -> usize {
10183 let mut w = *ws;
10184 let n0 = n;
10185 let mut n = n;
10186
10187 if s.is_null() {
10188 let mut count = 0usize;
10189 while *w != 0 {
10190 if (*w as u32) < 0x80 {
10191 count += 1;
10192 } else {
10193 let mut buf = [0u8; 4];
10194 let r = wcrtomb(buf.as_mut_ptr() as *mut c_char, *w, core::ptr::null_mut());
10195 if r == !0usize { return !0usize; }
10196 count += r;
10197 }
10198 w = w.add(1);
10199 }
10200 return count;
10201 }
10202
10203 let mut dst = s;
10204 while n > 0 {
10205 if (*w as u32) < 0x80 {
10206 *dst = *w as c_char;
10207 if *w == 0 {
10208 *ws = core::ptr::null();
10209 return n0 - n;
10210 }
10211 dst = dst.add(1);
10212 n -= 1;
10213 } else {
10214 let r = wcrtomb(dst, *w, core::ptr::null_mut());
10215 if r == !0usize {
10216 *ws = w;
10217 return !0usize;
10218 }
10219 if r > n {
10220 *ws = w;
10221 return n0 - n;
10222 }
10223 dst = dst.add(r);
10224 n -= r;
10225 }
10226 w = w.add(1);
10227 }
10228 *ws = w;
10229 n0
10230}
10231
10232#[no_mangle]
10233pub unsafe extern "C" fn mbstowcs(
10234 ws: *mut c_int,
10235 src: *const c_char,
10236 wn: usize,
10237) -> usize {
10238 let mut src_ptr = src;
10239 mbsrtowcs(ws, &mut src_ptr, wn, core::ptr::null_mut())
10240}
10241
10242#[no_mangle]
10243pub unsafe extern "C" fn wcstombs(
10244 s: *mut c_char,
10245 ws: *const c_int,
10246 n: usize,
10247) -> usize {
10248 let mut ws_ptr = ws;
10249 wcsrtombs(s, &mut ws_ptr, n, core::ptr::null_mut())
10250}
10251
10252#[no_mangle]
10257pub extern "C" fn btowc(c: c_int) -> wint_t {
10258 if c == -1 { return WEOF; }
10259 unsafe {
10260 if LOCALE_CTYPE_UTF8 {
10261 if (c as u32) < 128 { c as wint_t } else { WEOF }
10262 } else {
10263 (c as u8) as wint_t
10264 }
10265 }
10266}
10267
10268#[no_mangle]
10269pub extern "C" fn wctob(c: wint_t) -> c_int {
10270 unsafe {
10271 if LOCALE_CTYPE_UTF8 {
10272 if c < 128 { c as c_int } else { -1 }
10273 } else {
10274 if c <= 0xFF { c as c_int } else { -1 }
10275 }
10276 }
10277}
10278
10279#[no_mangle]
10280pub unsafe extern "C" fn mbsinit(s: *const c_uint) -> c_int {
10281 if s.is_null() || *s == 0 { 1 } else { 0 }
10282}
10283
10284#[no_mangle]
10285pub unsafe extern "C" fn mbrlen(s: *const c_char, n: usize, ps: *mut c_uint) -> usize {
10286 mbrtowc(core::ptr::null_mut(), s, n, ps)
10287}
10288
10289#[no_mangle]
10294pub unsafe extern "C" fn wcslen(s: *const wchar_t) -> usize {
10295 let mut len = 0;
10296 while *s.add(len) != 0 { len += 1; }
10297 len
10298}
10299
10300#[no_mangle]
10301pub unsafe extern "C" fn wcschr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
10302 let mut i = 0;
10303 loop {
10304 let ch = *s.add(i);
10305 if ch == c { return s.add(i) as *mut wchar_t; }
10306 if ch == 0 { return null_mut(); }
10307 i += 1;
10308 }
10309}
10310
10311#[no_mangle]
10312pub unsafe extern "C" fn wcsrchr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
10313 let mut i = 0;
10314 let mut last: *mut wchar_t = null_mut();
10315 loop {
10316 let ch = *s.add(i);
10317 if ch == c { last = s.add(i) as *mut wchar_t; }
10318 if ch == 0 { return last; }
10319 i += 1;
10320 }
10321}
10322
10323#[no_mangle]
10324pub unsafe extern "C" fn wcsstr(haystack: *const wchar_t, needle: *const wchar_t) -> *mut wchar_t {
10325 if *needle == 0 { return haystack as *mut wchar_t; }
10326 let mut i = 0;
10327 loop {
10328 let h = *haystack.add(i);
10329 if h == 0 { return null_mut(); }
10330 if h == *needle {
10331 let mut j = 0;
10332 loop {
10333 let n = *needle.add(j);
10334 if n == 0 { return haystack.add(i) as *mut wchar_t; }
10335 if *haystack.add(i + j) != n { break; }
10336 j += 1;
10337 }
10338 }
10339 i += 1;
10340 }
10341}
10342
10343#[no_mangle]
10344pub unsafe extern "C" fn wcscmp(s1: *const wchar_t, s2: *const wchar_t) -> c_int {
10345 let mut i = 0;
10346 loop {
10347 let a = *s1.add(i);
10348 let b = *s2.add(i);
10349 if a != b { return a - b; }
10350 if a == 0 { return 0; }
10351 i += 1;
10352 }
10353}
10354
10355#[no_mangle]
10356pub unsafe extern "C" fn wcsncmp(s1: *const wchar_t, s2: *const wchar_t, n: usize) -> c_int {
10357 let mut i = 0;
10358 while i < n {
10359 let a = *s1.add(i);
10360 let b = *s2.add(i);
10361 if a != b { return a - b; }
10362 if a == 0 { return 0; }
10363 i += 1;
10364 }
10365 0
10366}
10367
10368#[no_mangle]
10369pub unsafe extern "C" fn wcscpy(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
10370 let mut i = 0;
10371 loop {
10372 let c = *src.add(i);
10373 *dst.add(i) = c;
10374 if c == 0 { break; }
10375 i += 1;
10376 }
10377 dst
10378}
10379
10380#[no_mangle]
10381pub unsafe extern "C" fn wcsncpy(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
10382 let mut i = 0;
10383 while i < n && *src.add(i) != 0 { *dst.add(i) = *src.add(i); i += 1; }
10384 while i < n { *dst.add(i) = 0; i += 1; }
10385 dst
10386}
10387
10388#[no_mangle]
10389pub unsafe extern "C" fn wcscat(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
10390 let mut i = 0;
10391 while *dst.add(i) != 0 { i += 1; }
10392 let mut j = 0;
10393 loop {
10394 let c = *src.add(j);
10395 *dst.add(i + j) = c;
10396 if c == 0 { break; }
10397 j += 1;
10398 }
10399 dst
10400}
10401
10402#[no_mangle]
10403pub unsafe extern "C" fn wcsncat(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
10404 let mut i = 0;
10405 while *dst.add(i) != 0 { i += 1; }
10406 let mut j = 0;
10407 while j < n && *src.add(j) != 0 { *dst.add(i + j) = *src.add(j); j += 1; }
10408 *dst.add(i + j) = 0;
10409 dst
10410}
10411
10412#[no_mangle]
10413pub unsafe extern "C" fn wcsdup(s: *const wchar_t) -> *mut wchar_t {
10414 let len = wcslen(s);
10415 let p = malloc((len + 1) * core::mem::size_of::<wchar_t>()) as *mut wchar_t;
10416 if p.is_null() { return null_mut(); }
10417 core::ptr::copy_nonoverlapping(s, p, len + 1);
10418 p
10419}
10420
10421#[no_mangle]
10422pub unsafe extern "C" fn wcsnlen(s: *const wchar_t, maxlen: usize) -> usize {
10423 let mut i = 0;
10424 while i < maxlen && *s.add(i) != 0 { i += 1; }
10425 i
10426}
10427
10428#[no_mangle]
10429pub unsafe extern "C" fn wcsspn(s: *const wchar_t, accept: *const wchar_t) -> usize {
10430 let mut i = 0;
10431 loop {
10432 let c = *s.add(i);
10433 if c == 0 { return i; }
10434 let mut found = false;
10435 let mut j = 0;
10436 loop {
10437 let a = *accept.add(j);
10438 if a == 0 { break; }
10439 if c == a { found = true; break; }
10440 j += 1;
10441 }
10442 if !found { return i; }
10443 i += 1;
10444 }
10445}
10446
10447#[no_mangle]
10448pub unsafe extern "C" fn wcscspn(s: *const wchar_t, reject: *const wchar_t) -> usize {
10449 let mut i = 0;
10450 loop {
10451 let c = *s.add(i);
10452 if c == 0 { return i; }
10453 let mut j = 0;
10454 loop {
10455 let r = *reject.add(j);
10456 if r == 0 { break; }
10457 if c == r { return i; }
10458 j += 1;
10459 }
10460 i += 1;
10461 }
10462}
10463
10464#[no_mangle]
10465pub unsafe extern "C" fn wcspbrk(s: *const wchar_t, accept: *const wchar_t) -> *mut wchar_t {
10466 let mut i = 0;
10467 loop {
10468 let c = *s.add(i);
10469 if c == 0 { return null_mut(); }
10470 let mut j = 0;
10471 loop {
10472 let a = *accept.add(j);
10473 if a == 0 { break; }
10474 if c == a { return s.add(i) as *mut wchar_t; }
10475 j += 1;
10476 }
10477 i += 1;
10478 }
10479}
10480
10481#[no_mangle]
10482pub unsafe extern "C" fn wcsxfrm(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> usize {
10483 let len = wcslen(src);
10484 if !dst.is_null() {
10485 let copy = if len < n { len } else { if n > 0 { n - 1 } else { 0 } };
10486 for i in 0..copy { *dst.add(i) = *src.add(i); }
10487 if n > 0 { *dst.add(copy) = 0; }
10488 }
10489 len
10490}
10491
10492unsafe fn wcs_to_bytes(ws: *const wchar_t, buf: *mut u8, bufsz: usize) -> usize {
10497 let mut i = 0;
10498 while i < bufsz - 1 {
10499 let c = *ws.add(i);
10500 if c == 0 { break; }
10501 if (c as u32) > 127 { break; }
10502 *buf.add(i) = c as u8;
10503 i += 1;
10504 }
10505 *buf.add(i) = 0;
10506 i
10507}
10508
10509#[no_mangle]
10510pub unsafe extern "C" fn wcstol(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_long {
10511 let mut buf = [0u8; 256];
10512 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10513 let mut end: *mut c_char = core::ptr::null_mut();
10514 let r = strtol(buf.as_ptr() as *const c_char, &mut end, base);
10515 if !endptr.is_null() {
10516 let offset = end as usize - buf.as_ptr() as usize;
10517 *endptr = s.add(offset) as *mut wchar_t;
10518 }
10519 r
10520}
10521
10522#[no_mangle]
10523pub unsafe extern "C" fn wcstoul(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulong {
10524 let mut buf = [0u8; 256];
10525 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10526 let mut end: *mut c_char = core::ptr::null_mut();
10527 let r = strtoul(buf.as_ptr() as *const c_char, &mut end, base);
10528 if !endptr.is_null() {
10529 let offset = end as usize - buf.as_ptr() as usize;
10530 *endptr = s.add(offset) as *mut wchar_t;
10531 }
10532 r
10533}
10534
10535#[no_mangle]
10536pub unsafe extern "C" fn wcstoll(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong {
10537 let mut buf = [0u8; 256];
10538 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10539 let mut end: *mut c_char = core::ptr::null_mut();
10540 let r = strtoll(buf.as_ptr() as *const c_char, &mut end, base);
10541 if !endptr.is_null() {
10542 let offset = end as usize - buf.as_ptr() as usize;
10543 *endptr = s.add(offset) as *mut wchar_t;
10544 }
10545 r
10546}
10547
10548#[no_mangle]
10549pub unsafe extern "C" fn wcstoull(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong {
10550 let mut buf = [0u8; 256];
10551 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10552 let mut end: *mut c_char = core::ptr::null_mut();
10553 let r = strtoull(buf.as_ptr() as *const c_char, &mut end, base);
10554 if !endptr.is_null() {
10555 let offset = end as usize - buf.as_ptr() as usize;
10556 *endptr = s.add(offset) as *mut wchar_t;
10557 }
10558 r
10559}
10560
10561#[no_mangle]
10562pub unsafe extern "C" fn wcstod(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 {
10563 let mut buf = [0u8; 256];
10564 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10565 let mut end: *mut c_char = core::ptr::null_mut();
10566 let r = strtod(buf.as_ptr() as *const c_char, &mut end);
10567 if !endptr.is_null() {
10568 let offset = end as usize - buf.as_ptr() as usize;
10569 *endptr = s.add(offset) as *mut wchar_t;
10570 }
10571 r
10572}
10573
10574#[no_mangle]
10575pub unsafe extern "C" fn wcstof(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f32 { wcstod(s, endptr) as f32 }
10576
10577#[no_mangle]
10578#[cfg(target_arch = "x86_64")]
10579pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 { wcstod(s, endptr) }
10580
10581#[no_mangle]
10582#[cfg(target_arch = "aarch64")]
10583pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
10584
10585#[no_mangle]
10586#[cfg(target_arch = "riscv64")]
10587pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
10588
10589#[no_mangle]
10590pub unsafe extern "C" fn wcstoimax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong { wcstoll(s, endptr, base) }
10591
10592#[no_mangle]
10593pub unsafe extern "C" fn wcstoumax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong { wcstoull(s, endptr, base) }
10594
10595const WC_ALPHA: c_int = 1;
10600const WC_DIGIT: c_int = 2;
10601const WC_SPACE: c_int = 4;
10602const WC_UPPER: c_int = 8;
10603const WC_LOWER: c_int = 16;
10604const WC_ALNUM: c_int = WC_ALPHA | WC_DIGIT;
10605const WC_BLANK: c_int = 32;
10606const WC_CNTRL: c_int = 64;
10607const WC_PUNCT: c_int = 128;
10608const WC_GRAPH: c_int = WC_ALNUM | WC_PUNCT;
10609const WC_PRINT: c_int = WC_GRAPH | WC_BLANK;
10610const WC_XDIGIT: c_int = 256;
10611
10612fn wc_flags(c: wint_t) -> c_int {
10613 if c < 128 {
10614 let f = CT_TABLE[c as usize];
10615 let mut r = 0;
10616 if f & (CT_UPPER | CT_LOWER) != 0 { r |= WC_ALPHA; }
10617 if f & CT_DIGIT != 0 { r |= WC_DIGIT; }
10618 if f & CT_SPACE != 0 { r |= WC_SPACE; }
10619 if f & CT_UPPER != 0 { r |= WC_UPPER; }
10620 if f & CT_LOWER != 0 { r |= WC_LOWER; }
10621 if f & CT_BLANK != 0 { r |= WC_BLANK; }
10622 if f & CT_CNTRL != 0 { r |= WC_CNTRL; }
10623 if f & CT_PUNCT != 0 { r |= WC_PUNCT; }
10624 if f & CT_XDIGIT != 0 { r |= WC_XDIGIT; }
10625 r
10626 } else {
10627 if c < 0x100 { 0 }
10628 else { WC_PRINT | WC_ALPHA }
10629 }
10630}
10631
10632#[no_mangle]
10633pub extern "C" fn iswalnum(c: wint_t) -> c_int { (wc_flags(c) & WC_ALNUM != 0) as c_int }
10634#[no_mangle]
10635pub extern "C" fn iswalpha(c: wint_t) -> c_int { (wc_flags(c) & WC_ALPHA != 0) as c_int }
10636#[no_mangle]
10637pub extern "C" fn iswblank(c: wint_t) -> c_int { (wc_flags(c) & WC_BLANK != 0) as c_int }
10638#[no_mangle]
10639pub extern "C" fn iswcntrl(c: wint_t) -> c_int { (wc_flags(c) & WC_CNTRL != 0) as c_int }
10640#[no_mangle]
10641pub extern "C" fn iswdigit(c: wint_t) -> c_int { ((c >= b'0' as wint_t) && (c <= b'9' as wint_t)) as c_int }
10642#[no_mangle]
10643pub extern "C" fn iswgraph(c: wint_t) -> c_int { (wc_flags(c) & WC_GRAPH != 0) as c_int }
10644#[no_mangle]
10645pub extern "C" fn iswlower(c: wint_t) -> c_int { (wc_flags(c) & WC_LOWER != 0) as c_int }
10646#[no_mangle]
10647pub extern "C" fn iswprint(c: wint_t) -> c_int {
10648 if c < 128 { (wc_flags(c) & WC_PRINT != 0) as c_int }
10649 else if c >= 0x100 && c < 0x110000 { 1 }
10650 else { 0 }
10651}
10652#[no_mangle]
10653pub extern "C" fn iswpunct(c: wint_t) -> c_int { (wc_flags(c) & WC_PUNCT != 0) as c_int }
10654#[no_mangle]
10655pub extern "C" fn iswspace(c: wint_t) -> c_int {
10656 if c < 128 { (wc_flags(c) & WC_SPACE != 0) as c_int }
10657 else {
10658 match c {
10659 0x1680 | 0x2000..=0x200A | 0x2028 | 0x2029 | 0x202F | 0x205F | 0x3000 => 1,
10660 _ => 0,
10661 }
10662 }
10663}
10664#[no_mangle]
10665pub extern "C" fn iswupper(c: wint_t) -> c_int { (wc_flags(c) & WC_UPPER != 0) as c_int }
10666#[no_mangle]
10667pub extern "C" fn iswxdigit(c: wint_t) -> c_int { (wc_flags(c) & WC_XDIGIT != 0) as c_int }
10668
10669static WCTYPE_ALNUM: c_int = WC_ALNUM;
10670static WCTYPE_ALPHA: c_int = WC_ALPHA;
10671static WCTYPE_BLANK: c_int = WC_BLANK;
10672static WCTYPE_CNTRL: c_int = WC_CNTRL;
10673static WCTYPE_DIGIT: c_int = WC_DIGIT;
10674static WCTYPE_GRAPH: c_int = WC_GRAPH;
10675static WCTYPE_LOWER: c_int = WC_LOWER;
10676static WCTYPE_PRINT: c_int = WC_PRINT;
10677static WCTYPE_PUNCT: c_int = WC_PUNCT;
10678static WCTYPE_SPACE: c_int = WC_SPACE;
10679static WCTYPE_UPPER: c_int = WC_UPPER;
10680static WCTYPE_XDIGIT: c_int = WC_XDIGIT;
10681
10682#[no_mangle]
10683pub unsafe extern "C" fn wctype(name: *const c_char) -> wctype_t {
10684 if name.is_null() { return core::ptr::null(); }
10685 let n = name as *const u8;
10686 if strcmp(n, b"alnum\0".as_ptr()) == 0 { return &WCTYPE_ALNUM; }
10687 if strcmp(n, b"alpha\0".as_ptr()) == 0 { return &WCTYPE_ALPHA; }
10688 if strcmp(n, b"blank\0".as_ptr()) == 0 { return &WCTYPE_BLANK; }
10689 if strcmp(n, b"cntrl\0".as_ptr()) == 0 { return &WCTYPE_CNTRL; }
10690 if strcmp(n, b"digit\0".as_ptr()) == 0 { return &WCTYPE_DIGIT; }
10691 if strcmp(n, b"graph\0".as_ptr()) == 0 { return &WCTYPE_GRAPH; }
10692 if strcmp(n, b"lower\0".as_ptr()) == 0 { return &WCTYPE_LOWER; }
10693 if strcmp(n, b"print\0".as_ptr()) == 0 { return &WCTYPE_PRINT; }
10694 if strcmp(n, b"punct\0".as_ptr()) == 0 { return &WCTYPE_PUNCT; }
10695 if strcmp(n, b"space\0".as_ptr()) == 0 { return &WCTYPE_SPACE; }
10696 if strcmp(n, b"upper\0".as_ptr()) == 0 { return &WCTYPE_UPPER; }
10697 if strcmp(n, b"xdigit\0".as_ptr()) == 0 { return &WCTYPE_XDIGIT; }
10698 core::ptr::null()
10699}
10700
10701#[no_mangle]
10702pub unsafe extern "C" fn iswctype(c: wint_t, desc: wctype_t) -> c_int {
10703 if desc.is_null() { return 0; }
10704 (wc_flags(c) & *desc != 0) as c_int
10705}
10706
10707static WCTRANS_LOWER: c_int = 1;
10708static WCTRANS_UPPER: c_int = 2;
10709
10710#[no_mangle]
10711pub unsafe extern "C" fn towlower(c: wint_t) -> wint_t {
10712 if c < 128 { tolower(c as c_int) as wint_t } else { c }
10713}
10714
10715#[no_mangle]
10716pub unsafe extern "C" fn towupper(c: wint_t) -> wint_t {
10717 if c < 128 { toupper(c as c_int) as wint_t } else { c }
10718}
10719
10720#[no_mangle]
10721pub unsafe extern "C" fn wctrans(name: *const c_char) -> wctrans_t {
10722 if name.is_null() { return core::ptr::null(); }
10723 let n = name as *const u8;
10724 if strcmp(n, b"tolower\0".as_ptr()) == 0 { return &WCTRANS_LOWER; }
10725 if strcmp(n, b"toupper\0".as_ptr()) == 0 { return &WCTRANS_UPPER; }
10726 core::ptr::null()
10727}
10728
10729#[no_mangle]
10730pub unsafe extern "C" fn towctrans(c: wint_t, desc: wctrans_t) -> wint_t {
10731 if desc.is_null() { return c; }
10732 match *desc {
10733 1 => towlower(c),
10734 2 => towupper(c),
10735 _ => c,
10736 }
10737}
10738
10739#[no_mangle]
10744pub unsafe extern "C" fn fgetwc(f: *mut FILE) -> wint_t {
10745 let mut state: c_uint = 0;
10746 let mut wc: wchar_t = 0;
10747 let mut buf = [0u8; 4];
10748 let c = fgetc(f);
10749 if c == -1 { return WEOF; }
10750 buf[0] = c as u8;
10751 if buf[0] < 0x80 { return buf[0] as wint_t; }
10752 let len = if buf[0] < 0xE0 { 2 } else if buf[0] < 0xF0 { 3 } else { 4 };
10753 let mut n = 1usize;
10754 while n < len {
10755 let c2 = fgetc(f);
10756 if c2 == -1 { return WEOF; }
10757 buf[n] = c2 as u8;
10758 n += 1;
10759 }
10760 let r = mbrtowc(&mut wc, buf.as_ptr() as *const c_char, n, &mut state);
10761 if r == !0usize || r == !1usize { WEOF } else { wc as wint_t }
10762}
10763
10764#[no_mangle]
10765pub unsafe extern "C" fn fputwc(c: wchar_t, f: *mut FILE) -> wint_t {
10766 let mut buf = [0u8; 4];
10767 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c, core::ptr::null_mut());
10768 if n == !0usize || n == 0 { return WEOF; }
10769 if fwrite(buf.as_ptr() as *const c_void, 1, n, f) != n { return WEOF; }
10770 c as wint_t
10771}
10772
10773#[no_mangle]
10774pub unsafe extern "C" fn fputws(s: *const wchar_t, f: *mut FILE) -> c_int {
10775 let mut i = 0;
10776 while *s.add(i) != 0 {
10777 if fputwc(*s.add(i), f) == WEOF { return -1; }
10778 i += 1;
10779 }
10780 0
10781}
10782
10783#[no_mangle]
10784pub unsafe extern "C" fn ungetwc(c: wint_t, f: *mut FILE) -> wint_t {
10785 if c == WEOF { return WEOF; }
10786 let mut buf = [0u8; 4];
10787 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c as wchar_t, core::ptr::null_mut());
10788 if n == !0usize || n == 0 { return WEOF; }
10789 let mut i = n;
10790 while i > 0 {
10791 i -= 1;
10792 if ungetc(buf[i] as c_int, f) == -1 { return WEOF; }
10793 }
10794 c
10795}
10796
10797#[no_mangle]
10798pub unsafe extern "C" fn getwchar() -> wint_t { fgetwc(stdin) }
10799
10800#[no_mangle]
10801pub unsafe extern "C" fn putwchar(c: wchar_t) -> wint_t { fputwc(c, stdout) }
10802
10803unsafe fn wfmt_write_str(dst: *mut wchar_t, pos: usize, cap: usize, s: *const u8, len: usize) -> usize {
10808 let mut i = 0;
10809 while i < len {
10810 if pos + i < cap { *dst.add(pos + i) = *s.add(i) as wchar_t; }
10811 i += 1;
10812 }
10813 pos + len
10814}
10815
10816#[no_mangle]
10817pub unsafe extern "C" fn vswprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, mut args: VaList) -> c_int {
10818 if n == 0 { return -1; }
10819 let cap = n - 1;
10820 let mut pos = 0usize;
10821 let mut fmt_narrow = [0u8; 256];
10823 let mut flen = 0usize;
10824 loop {
10825 let ch = *fmt.add(flen) as u32;
10826 if ch == 0 || flen >= 255 { break; }
10827 fmt_narrow[flen] = if ch < 128 { ch as u8 } else { b'?' };
10828 flen += 1;
10829 }
10830 fmt_narrow[flen] = 0;
10831 let mut fi = 0usize;
10832 macro_rules! wc {
10833 ($c:expr) => { if pos < cap { *s.add(pos) = $c as wchar_t; } pos += 1; }
10834 }
10835 loop {
10836 let c = fmt_narrow[fi];
10837 if c == 0 { break; }
10838 if c != b'%' { wc!(c); fi += 1; continue; }
10839 fi += 1;
10840 let mut flags: u8 = 0;
10841 loop {
10842 match fmt_narrow[fi] {
10843 b'-' => { flags |= FLAG_MINUS; fi += 1; }
10844 b'+' => { flags |= FLAG_PLUS; fi += 1; }
10845 b' ' => { flags |= FLAG_SPACE; fi += 1; }
10846 b'0' => { flags |= FLAG_ZERO; fi += 1; }
10847 b'#' => { flags |= FLAG_HASH; fi += 1; }
10848 _ => break,
10849 }
10850 }
10851 let mut width: usize = 0;
10852 if fmt_narrow[fi] == b'*' {
10853 let w = args.next_arg::<c_int>();
10854 if w < 0 { flags |= FLAG_MINUS; width = (-w) as usize; } else { width = w as usize; }
10855 fi += 1;
10856 } else {
10857 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10858 width = width * 10 + (fmt_narrow[fi] - b'0') as usize; fi += 1;
10859 }
10860 }
10861 let mut precision: i32 = -1;
10862 if fmt_narrow[fi] == b'.' {
10863 fi += 1;
10864 if fmt_narrow[fi] == b'*' {
10865 let p = args.next_arg::<c_int>();
10866 precision = if p < 0 { -1 } else { p }; fi += 1;
10867 } else {
10868 precision = 0;
10869 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10870 precision = precision * 10 + (fmt_narrow[fi] - b'0') as i32; fi += 1;
10871 }
10872 }
10873 }
10874 let len_mod = fmt_narrow[fi];
10875 if len_mod == b'h' || len_mod == b'l' || len_mod == b'j' || len_mod == b'z' || len_mod == b't' || len_mod == b'L' {
10876 fi += 1;
10877 let spec = fmt_narrow[fi];
10878 if (len_mod == b'h' && spec == b'h') || (len_mod == b'l' && spec == b'l') {
10879 fi += 1;
10880 let spec2 = fmt_narrow[fi];
10881 match (len_mod, spec, spec2) {
10882 (b'h', b'h', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut u8) = pos as u8; } }
10883 (b'l', b'l', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut c_longlong) = pos as c_longlong; } }
10884 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
10885 let val = args.next_arg::<c_longlong>();
10886 let neg = val < 0;
10887 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10888 let b = format_u64(abs);
10889 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10890 let mut fbuf = [0u8; 32];
10891 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10892 for k in 0..len { wc!(fbuf[k]); }
10893 }
10894 (b'l', b'l', b'u') => {
10895 let val = args.next_arg::<c_ulonglong>();
10896 let b = format_u64(val as u64);
10897 let mut fbuf = [0u8; 32];
10898 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10899 for k in 0..len { wc!(fbuf[k]); }
10900 }
10901 (b'l', b'l', b'x') => {
10902 let val = args.next_arg::<c_ulonglong>();
10903 let b = format_hex(val as u64, false);
10904 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10905 let mut fbuf = [0u8; 32];
10906 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10907 for k in 0..len { wc!(fbuf[k]); }
10908 }
10909 (b'l', b'l', b'X') => {
10910 let val = args.next_arg::<c_ulonglong>();
10911 let b = format_hex(val as u64, true);
10912 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10913 let mut fbuf = [0u8; 32];
10914 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10915 for k in 0..len { wc!(fbuf[k]); }
10916 }
10917 (b'l', b'l', b'o') => {
10918 let val = args.next_arg::<c_ulonglong>();
10919 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
10920 let mut fbuf = [0u8; 32];
10921 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10922 for k in 0..len { wc!(fbuf[k]); }
10923 }
10924 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); wc!(spec2); }
10925 }
10926 } else {
10927 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
10928 match (lm, spec) {
10929 (b'h', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut u16) = pos as u16; } }
10930 (b'l', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut c_long) = pos as c_long; } }
10931 (b'z', b'n') | (b't', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut usize) = pos; } }
10932 (b'j', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut c_ulonglong) = pos as c_ulonglong; } }
10933 (b'l', b'd') | (b'l', b'i') => {
10934 let val = args.next_arg::<c_long>();
10935 let neg = val < 0;
10936 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10937 let b = format_u64(abs);
10938 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10939 let mut fbuf = [0u8; 32];
10940 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10941 for k in 0..len { wc!(fbuf[k]); }
10942 }
10943 (b'l', b'u') => {
10944 let val = args.next_arg::<c_ulong>();
10945 let b = format_u64(val as u64);
10946 let mut fbuf = [0u8; 32];
10947 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10948 for k in 0..len { wc!(fbuf[k]); }
10949 }
10950 (b'l', b'x') => {
10951 let val = args.next_arg::<c_ulong>();
10952 let b = format_hex(val as u64, false);
10953 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10954 let mut fbuf = [0u8; 32];
10955 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10956 for k in 0..len { wc!(fbuf[k]); }
10957 }
10958 (b'l', b'X') => {
10959 let val = args.next_arg::<c_ulong>();
10960 let b = format_hex(val as u64, true);
10961 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10962 let mut fbuf = [0u8; 32];
10963 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10964 for k in 0..len { wc!(fbuf[k]); }
10965 }
10966 (b'l', b'o') => {
10967 let val = args.next_arg::<c_ulong>();
10968 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
10969 let mut fbuf = [0u8; 32];
10970 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10971 for k in 0..len { wc!(fbuf[k]); }
10972 }
10973 (b'l', b'c') => {
10974 let ch = args.next_arg::<wint_t>();
10975 wc!(ch);
10976 }
10977 (b'l', b's') => {
10978 let ws_arg = args.next_arg::<*const wchar_t>();
10979 if ws_arg.is_null() {
10980 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
10981 if flags & FLAG_MINUS != 0 {
10982 for k in 0..slen { wc!(b"(null)"[k]); }
10983 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10984 } else {
10985 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10986 for k in 0..slen { wc!(b"(null)"[k]); }
10987 }
10988 } else {
10989 let mut wlen = 0usize;
10990 loop {
10991 let ch = *ws_arg.add(wlen);
10992 if ch == 0 { break; }
10993 if precision >= 0 && wlen >= precision as usize { break; }
10994 wlen += 1;
10995 }
10996 if flags & FLAG_MINUS != 0 {
10997 for k in 0..wlen { wc!(*ws_arg.add(k)); }
10998 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
10999 } else {
11000 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
11001 for k in 0..wlen { wc!(*ws_arg.add(k)); }
11002 }
11003 }
11004 }
11005 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
11006 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
11007 let val = args.next_arg::<f64>();
11008 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
11009 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
11010 let mut fbuf = [0u8; 4224];
11011 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
11012 let mut wbuf = [0u8; 4224];
11013 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
11014 for k in 0..wlen { wc!(wbuf[k]); }
11015 }
11016 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
11017 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
11018 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
11019 let val = {
11020 let lo: u64 = args.next_arg::<u64>();
11021 let hi: u64 = args.next_arg::<u64>();
11022 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
11023 f128::from_bits(combined) as f64
11024 };
11025 #[cfg(target_arch = "x86_64")]
11026 let val = args.next_arg::<f64>();
11027 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
11028 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
11029 let mut fbuf = [0u8; 4224];
11030 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
11031 let mut wbuf = [0u8; 4224];
11032 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
11033 for k in 0..wlen { wc!(wbuf[k]); }
11034 }
11035 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); }
11036 }
11037 }
11038 } else {
11039 let spec = fmt_narrow[fi];
11040 match spec {
11041 b'd' | b'i' => {
11042 let d = args.next_arg::<c_int>();
11043 let neg = d < 0;
11044 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
11045 let b = format_u64(abs);
11046 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
11047 let mut fbuf = [0u8; 32];
11048 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
11049 for k in 0..len { wc!(fbuf[k]); }
11050 }
11051 b'u' => {
11052 let u = args.next_arg::<c_uint>();
11053 let b = format_u64(u as u64);
11054 let mut fbuf = [0u8; 32];
11055 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
11056 for k in 0..len { wc!(fbuf[k]); }
11057 }
11058 b'x' => {
11059 let x = args.next_arg::<c_uint>();
11060 let b = format_hex(x as u64, false);
11061 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
11062 let mut fbuf = [0u8; 32];
11063 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
11064 for k in 0..len { wc!(fbuf[k]); }
11065 }
11066 b'X' => {
11067 let x = args.next_arg::<c_uint>();
11068 let b = format_hex(x as u64, true);
11069 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
11070 let mut fbuf = [0u8; 32];
11071 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
11072 for k in 0..len { wc!(fbuf[k]); }
11073 }
11074 b'o' => {
11075 let o = args.next_arg::<c_uint>();
11076 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
11077 let mut fbuf = [0u8; 32];
11078 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
11079 for k in 0..len { wc!(fbuf[k]); }
11080 }
11081 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
11082 let val = args.next_arg::<f64>();
11083 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
11084 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
11085 let mut fbuf = [0u8; 4224];
11086 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
11087 let mut wbuf = [0u8; 4224];
11088 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
11089 for k in 0..wlen { wc!(wbuf[k]); }
11090 }
11091 b'c' => {
11092 let ch = args.next_arg::<c_int>();
11093 wc!(ch as u8);
11094 }
11095 b's' => {
11096 let p = args.next_arg::<*const c_char>();
11097 if p.is_null() {
11098 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
11099 if flags & FLAG_MINUS != 0 {
11100 for k in 0..slen { wc!(b"(null)"[k]); }
11101 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
11102 } else {
11103 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
11104 for k in 0..slen { wc!(b"(null)"[k]); }
11105 }
11106 } else {
11107 let mut wbuf_local = [0i32; 256];
11108 let mut wcount = 0usize;
11109 let mut byte_pos = 0usize;
11110 let pbytes = p as *const u8;
11111 loop {
11112 if precision >= 0 && wcount >= precision as usize { break; }
11113 if wcount >= 256 { break; }
11114 let mut wc_val: c_int = 0;
11115 let consumed = mbrtowc(&mut wc_val as *mut c_int, p.add(byte_pos) as *const c_char, 256, core::ptr::null_mut());
11116 if consumed == !0usize || consumed == !1usize {
11117 wbuf_local[wcount] = *pbytes.add(byte_pos) as c_int;
11118 byte_pos += 1;
11119 wcount += 1;
11120 } else if consumed == 0 {
11121 break;
11122 } else {
11123 wbuf_local[wcount] = wc_val;
11124 byte_pos += consumed;
11125 wcount += 1;
11126 }
11127 }
11128 if flags & FLAG_MINUS != 0 {
11129 for k in 0..wcount { wc!(wbuf_local[k]); }
11130 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
11131 } else {
11132 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
11133 for k in 0..wcount { wc!(wbuf_local[k]); }
11134 }
11135 }
11136 }
11137 b'p' => {
11138 wc!(b'0'); wc!(b'x');
11139 let p = args.next_arg::<*const c_void>();
11140 let b = format_hex(p as u64, false);
11141 for k in 0..b.1 { wc!(b.0[k]); }
11142 }
11143 b'n' => {
11144 let p = args.next_arg::<*mut c_void>();
11145 if !p.is_null() { *(p as *mut c_int) = pos as c_int; }
11146 }
11147 b'%' => { wc!(b'%'); }
11148 _ => { wc!(b'%'); wc!(spec); }
11149 }
11150 }
11151 fi += 1;
11152 }
11153 let null_pos = if pos < cap { pos } else { cap };
11154 *s.add(null_pos) = 0;
11155 if pos > cap { -1 } else { pos as c_int }
11156}
11157
11158#[no_mangle]
11159pub unsafe extern "C" fn swprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, args: ...) -> c_int {
11160 vswprintf(s, n, fmt, args)
11161}
11162
11163#[no_mangle]
11164pub unsafe extern "C" fn vfwprintf(f: *mut FILE, fmt: *const wchar_t, args: VaList) -> c_int {
11165 let mut buf = [0i32; 4096];
11166 let r = vswprintf(buf.as_mut_ptr(), 4096, fmt, args);
11167 if r < 0 { return r; }
11168 let mut i = 0;
11169 while i < r as usize {
11170 let mut mb = [0u8; 4];
11171 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, buf[i], core::ptr::null_mut());
11172 if n == !0usize { return -1; }
11173 if fwrite(mb.as_ptr() as *const c_void, 1, n, f) != n { return -1; }
11174 i += 1;
11175 }
11176 r
11177}
11178
11179#[no_mangle]
11180pub unsafe extern "C" fn fwprintf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
11181 vfwprintf(f, fmt, args)
11182}
11183
11184unsafe fn wcsfmt_to_mbs(dst: *mut u8, dst_len: usize, src: *const wchar_t) {
11190 let mut i = 0usize;
11191 loop {
11192 let ch = *src.add(i) as u32;
11193 if ch == 0 || i >= dst_len - 1 { break; }
11194 *dst.add(i) = if ch < 128 { ch as u8 } else { b'?' };
11195 i += 1;
11196 }
11197 *dst.add(i) = 0;
11198}
11199
11200#[no_mangle]
11201pub unsafe extern "C" fn vswscanf(s: *const wchar_t, fmt: *const wchar_t, mut args: VaList) -> c_int {
11202 let mut mbs_buf = [0u8; 4096];
11203 let mut i = 0usize;
11204 let mut mb_pos = 0usize;
11205 loop {
11206 let wc = *s.add(i) as c_int;
11207 if wc == 0 { break; }
11208 let mut mb = [0u8; 4];
11209 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, wc, core::ptr::null_mut());
11210 if n == !0usize || n == 0 { break; }
11211 if mb_pos + n >= mbs_buf.len() { break; }
11212 let mut k = 0usize;
11213 while k < n { mbs_buf[mb_pos + k] = mb[k]; k += 1; }
11214 mb_pos += n;
11215 i += 1;
11216 }
11217 mbs_buf[mb_pos] = 0;
11218 let mut mbs_fmt = [0u8; 4096];
11219 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
11220 do_vsscanf(mbs_buf.as_ptr(), mb_pos, mbs_fmt.as_ptr() as *const c_char, &mut args, core::ptr::null_mut())
11221}
11222
11223#[no_mangle]
11224pub unsafe extern "C" fn swscanf(s: *const wchar_t, fmt: *const wchar_t, args: ...) -> c_int {
11225 vswscanf(s, fmt, args)
11226}
11227
11228#[no_mangle]
11229pub unsafe extern "C" fn vfwscanf(f: *mut FILE, fmt: *const wchar_t, mut args: VaList) -> c_int {
11230 let start_pos = ftello(f);
11231 if start_pos < 0 { return -1; }
11232 let mut buf = [0u8; 4096];
11233 let mut n = 0usize;
11234 loop {
11235 if n >= buf.len() - 1 { break; }
11236 let c = fgetc(f);
11237 if c == -1 { break; }
11238 buf[n] = c as u8;
11239 n += 1;
11240 }
11241 buf[n] = 0;
11242 let mut mbs_fmt = [0u8; 4096];
11243 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
11244 let mut consumed = 0usize;
11245 let hit_eof = (*f)._eof != 0;
11246 let result = do_vsscanf(buf.as_ptr(), n, mbs_fmt.as_ptr() as *const c_char, &mut args, &mut consumed);
11247 let _ = fseeko(f, start_pos + consumed as i64, SEEK_SET);
11248 if hit_eof && consumed == n {
11249 (*f)._eof = 1;
11250 }
11251 result
11252}
11253
11254#[no_mangle]
11255pub unsafe extern "C" fn fwscanf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
11256 vfwscanf(f, fmt, args)
11257}
11258
11259#[no_mangle]
11260pub unsafe extern "C" fn vwscanf(fmt: *const wchar_t, args: VaList) -> c_int {
11261 vfwscanf(stdin, fmt, args)
11262}
11263
11264#[no_mangle]
11265pub unsafe extern "C" fn wscanf(fmt: *const wchar_t, args: ...) -> c_int {
11266 vfwscanf(stdin, fmt, args)
11267}
11268
11269const LEAPOCH: i64 = 946684800 + 86400 * (31 + 29);
11274const DAYS_PER_400Y: i64 = 365 * 400 + 97;
11275const DAYS_PER_100Y: i64 = 365 * 100 + 24;
11276const DAYS_PER_4Y: i64 = 365 * 4 + 1;
11277
11278const SECS_THROUGH_MONTH: [i32; 12] = [
11279 0, 31*86400, 59*86400, 90*86400, 120*86400, 151*86400,
11280 181*86400, 212*86400, 243*86400, 273*86400, 304*86400, 334*86400,
11281];
11282
11283const DAYS_IN_MONTH: [i32; 12] = [31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29];
11284
11285unsafe fn year_to_secs(year: i64, is_leap: &mut bool) -> i64 {
11286 if year - 2 <= 136 {
11287 let y = year as i32;
11288 let mut leaps = (y - 68) >> 2;
11289 if (y - 68) & 3 == 0 { leaps -= 1; *is_leap = true; } else { *is_leap = false; }
11290 return 31536000 * (y as i64 - 70) + 86400 * leaps as i64;
11291 }
11292 let mut cycles = ((year - 100) / 400) as i32;
11293 let mut rem = ((year - 100) % 400) as i32;
11294 if rem < 0 { cycles -= 1; rem += 400; }
11295 let (centuries, leaps);
11296 if rem == 0 { *is_leap = true; centuries = 0; leaps = 0; }
11297 else {
11298 let c;
11299 if rem >= 200 { if rem >= 300 { c = 3; rem -= 300; } else { c = 2; rem -= 200; } }
11300 else { if rem >= 100 { c = 1; rem -= 100; } else { c = 0; } }
11301 centuries = c;
11302 if rem == 0 { *is_leap = false; leaps = 0; }
11303 else { leaps = rem / 4; rem %= 4; *is_leap = rem == 0; }
11304 }
11305 let total_leaps = leaps + 97 * cycles + 24 * centuries - (*is_leap as i32);
11306 (year - 100) * 31536000 + total_leaps as i64 * 86400 + 946684800 + 86400
11307}
11308
11309fn month_to_secs(month: i32, is_leap: bool) -> i32 {
11310 let mut t = SECS_THROUGH_MONTH[month as usize];
11311 if is_leap && month >= 2 { t += 86400; }
11312 t
11313}
11314
11315unsafe fn secs_to_tm(t: i64, tm: &mut tm) -> bool {
11316 if t < (i32::MIN as i64) * 31622400 || t > (i32::MAX as i64) * 31622400 { return false; }
11317 let secs = t - LEAPOCH;
11318 let mut days = secs / 86400;
11319 let mut remsecs = (secs % 86400) as i32;
11320 if remsecs < 0 { remsecs += 86400; days -= 1; }
11321 let mut wday = ((3 + days) % 7) as i32;
11322 if wday < 0 { wday += 7; }
11323 let mut qc_cycles = (days / DAYS_PER_400Y) as i32;
11324 let mut remdays = (days % DAYS_PER_400Y) as i32;
11325 if remdays < 0 { remdays += DAYS_PER_400Y as i32; qc_cycles -= 1; }
11326 let mut c_cycles = remdays / DAYS_PER_100Y as i32;
11327 if c_cycles == 4 { c_cycles -= 1; }
11328 remdays -= c_cycles * DAYS_PER_100Y as i32;
11329 let mut q_cycles = remdays / DAYS_PER_4Y as i32;
11330 if q_cycles == 25 { q_cycles -= 1; }
11331 remdays -= q_cycles * DAYS_PER_4Y as i32;
11332 let mut remyears = remdays / 365;
11333 if remyears == 4 { remyears -= 1; }
11334 remdays -= remyears * 365;
11335 let leap = remyears == 0 && (q_cycles != 0 || c_cycles == 0);
11336 let mut yday = remdays + 31 + 28 + leap as i32;
11337 if yday >= 365 + leap as i32 { yday -= 365 + leap as i32; }
11338 let years = remyears as i64 + 4 * q_cycles as i64 + 100 * c_cycles as i64 + 400 * qc_cycles as i64;
11339 let mut months = 0i32;
11340 let mut rd = remdays;
11341 for m in 0..12 {
11342 if DAYS_IN_MONTH[m] <= rd { rd -= DAYS_IN_MONTH[m]; } else { months = m as i32; break; }
11343 }
11344 let mut adj_years = years;
11345 if months >= 10 { months -= 12; adj_years += 1; }
11346 if adj_years + 100 > i32::MAX as i64 || adj_years + 100 < i32::MIN as i64 { return false; }
11347 tm.tm_year = (adj_years + 100) as c_int;
11348 tm.tm_mon = months + 2;
11349 tm.tm_mday = rd + 1;
11350 tm.tm_wday = wday;
11351 tm.tm_yday = yday;
11352 tm.tm_hour = remsecs / 3600;
11353 tm.tm_min = remsecs / 60 % 60;
11354 tm.tm_sec = remsecs % 60;
11355 true
11356}
11357
11358unsafe fn tm_to_secs(tm: *const tm) -> i64 {
11359 let mut year = (*tm).tm_year as i64;
11360 let mut month = (*tm).tm_mon;
11361 if month >= 12 || month < 0 {
11362 let adj = month / 12;
11363 month %= 12;
11364 if month < 0 { month += 12; }
11365 year += adj as i64;
11366 }
11367 let mut is_leap = false;
11368 let mut t = year_to_secs(year, &mut is_leap);
11369 t += month_to_secs(month, is_leap) as i64;
11370 t += 86400 * ((*tm).tm_mday - 1) as i64;
11371 t += 3600 * (*tm).tm_hour as i64;
11372 t += 60 * (*tm).tm_min as i64;
11373 t += (*tm).tm_sec as i64;
11374 t
11375}
11376
11377static mut TM_BUF: tm = tm {
11378 tm_sec: 0, tm_min: 0, tm_hour: 0, tm_mday: 0, tm_mon: 0,
11379 tm_year: 0, tm_wday: 0, tm_yday: 0, tm_isdst: 0,
11380 tm_gmtoff: 0, tm_zone: core::ptr::null(),
11381};
11382
11383static mut UTC_STR: [c_char; 4] = [b'U' as c_char, b'T' as c_char, b'C' as c_char, 0];
11384
11385const CLOCK_PROCESS_CPUTIME_ID: c_int = 2;
11386
11387#[no_mangle]
11392pub unsafe extern "C" fn time(t: *mut TimeT) -> TimeT {
11393 let mut ts: timespec = core::mem::zeroed();
11394 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
11395 if !t.is_null() { *t = ts.tv_sec; }
11396 ts.tv_sec
11397}
11398
11399#[no_mangle]
11400pub unsafe extern "C" fn difftime(t1: TimeT, t0: TimeT) -> f64 {
11401 (t1 as i64 - t0 as i64) as f64
11402}
11403
11404#[no_mangle]
11405pub unsafe extern "C" fn clock() -> ClockT {
11406 let mut ts: timespec = core::mem::zeroed();
11407 let _ = sys_clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &mut ts);
11408 ts.tv_sec * 1000000 + ts.tv_nsec / 1000
11409}
11410
11411#[no_mangle]
11412pub unsafe extern "C" fn gmtime(t: *const TimeT) -> *mut tm {
11413 gmtime_r(t, &raw mut TM_BUF)
11414}
11415
11416#[no_mangle]
11417pub unsafe extern "C" fn gmtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm {
11418 if !secs_to_tm(*t as i64, &mut *tm) { ERRNO!() = EOVERFLOW; return core::ptr::null_mut(); }
11419 (*tm).tm_isdst = 0;
11420 (*tm).tm_gmtoff = 0;
11421 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11422 tm
11423}
11424
11425#[no_mangle]
11426pub unsafe extern "C" fn localtime(t: *const TimeT) -> *mut tm { gmtime(t) }
11427
11428#[no_mangle]
11429pub unsafe extern "C" fn localtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm { gmtime_r(t, tm) }
11430
11431#[no_mangle]
11432pub unsafe extern "C" fn mktime(tm: *mut tm) -> TimeT {
11433 let t = tm_to_secs(tm as *const tm);
11434 if !secs_to_tm(t, &mut *tm) { ERRNO!() = EOVERFLOW; return -1; }
11435 (*tm).tm_isdst = 0;
11436 (*tm).tm_gmtoff = 0;
11437 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11438 t as TimeT
11439}
11440
11441#[no_mangle]
11442pub unsafe extern "C" fn timegm(tm: *mut tm) -> TimeT {
11443 let t = tm_to_secs(tm as *const tm);
11444 if !secs_to_tm(t, &mut *tm) { ERRNO!() = EOVERFLOW; return -1; }
11445 (*tm).tm_isdst = 0;
11446 (*tm).tm_gmtoff = 0;
11447 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11448 t as TimeT
11449}
11450
11451static mut ASCTIME_BUF: [c_char; 26] = [0; 26];
11452
11453const DAY_NAMES: [&[u8]; 7] = [b"Sun\0", b"Mon\0", b"Tue\0", b"Wed\0", b"Thu\0", b"Fri\0", b"Sat\0"];
11454const MON_NAMES: [&[u8]; 12] = [b"Jan\0", b"Feb\0", b"Mar\0", b"Apr\0", b"May\0", b"Jun\0", b"Jul\0", b"Aug\0", b"Sep\0", b"Oct\0", b"Nov\0", b"Dec\0"];
11455
11456#[no_mangle]
11457pub unsafe extern "C" fn asctime(tm: *const tm) -> *mut c_char {
11458 asctime_r(tm, core::ptr::addr_of_mut!(ASCTIME_BUF).cast::<c_char>())
11459}
11460
11461#[no_mangle]
11462pub unsafe extern "C" fn asctime_r(tm: *const tm, buf: *mut c_char) -> *mut c_char {
11463 let wday = if (*tm).tm_wday >= 0 && (*tm).tm_wday < 7 { (*tm).tm_wday as usize } else { 0 };
11464 let mon = if (*tm).tm_mon >= 0 && (*tm).tm_mon < 12 { (*tm).tm_mon as usize } else { 0 };
11465 let dn = DAY_NAMES[wday];
11466 let mn = MON_NAMES[mon];
11467 let mut p = 0;
11468 for k in 0..3 { *buf.add(p) = *dn.as_ptr().add(k) as c_char; p += 1; }
11469 *buf.add(p) = b' ' as c_char; p += 1;
11470 for k in 0..3 { *buf.add(p) = *mn.as_ptr().add(k) as c_char; p += 1; }
11471 *buf.add(p) = b' ' as c_char; p += 1;
11472 let v = (*tm).tm_mday;
11473 *buf.add(p) = (b'0' + (v / 10) as u8) as c_char; p += 1;
11474 *buf.add(p) = (b'0' + (v % 10) as u8) as c_char; p += 1;
11475 *buf.add(p) = b' ' as c_char; p += 1;
11476 let hh = (*tm).tm_hour;
11477 *buf.add(p) = (b'0' + (hh / 10) as u8) as c_char; p += 1;
11478 *buf.add(p) = (b'0' + (hh % 10) as u8) as c_char; p += 1;
11479 *buf.add(p) = b':' as c_char; p += 1;
11480 let mm = (*tm).tm_min;
11481 *buf.add(p) = (b'0' + (mm / 10) as u8) as c_char; p += 1;
11482 *buf.add(p) = (b'0' + (mm % 10) as u8) as c_char; p += 1;
11483 *buf.add(p) = b':' as c_char; p += 1;
11484 let ss = (*tm).tm_sec;
11485 *buf.add(p) = (b'0' + (ss / 10) as u8) as c_char; p += 1;
11486 *buf.add(p) = (b'0' + (ss % 10) as u8) as c_char; p += 1;
11487 *buf.add(p) = b' ' as c_char; p += 1;
11488 let yr = (*tm).tm_year + 1900;
11489 let mut tmp = [0u8; 4];
11490 let mut v2 = yr;
11491 for k in (0..4).rev() { tmp[k] = b'0' + (v2 % 10) as u8; v2 /= 10; }
11492 for k in 0..4 { *buf.add(p) = tmp[k] as c_char; p += 1; }
11493 *buf.add(p) = b'\n' as c_char; p += 1;
11494 *buf.add(p) = 0;
11495 buf
11496}
11497
11498#[no_mangle]
11499pub unsafe extern "C" fn ctime(t: *const TimeT) -> *mut c_char { asctime(gmtime(t)) }
11500
11501#[no_mangle]
11502pub unsafe extern "C" fn ctime_r(t: *const TimeT, buf: *mut c_char) -> *mut c_char {
11503 let mut tmp: tm = core::mem::zeroed();
11504 gmtime_r(t, &mut tmp);
11505 asctime_r(&tmp, buf)
11506}
11507
11508unsafe fn sys_clock_getres(clockid: c_int, ts: *mut timespec) -> i64 {
11513 <Arch as Syscalls>::syscall2(SYS_CLOCK_GETRES, clockid as i64, ts as i64)
11514}
11515
11516unsafe fn sys_clock_settime(clockid: c_int, ts: *const timespec) -> i64 {
11517 <Arch as Syscalls>::syscall2(SYS_CLOCK_SETTIME, clockid as i64, ts as i64)
11518}
11519
11520unsafe fn sys_clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> i64 {
11521 <Arch as Syscalls>::syscall4(SYS_CLOCK_NANOSLEEP, clockid as i64, flags as i64, req as i64, rem as i64)
11522}
11523
11524#[no_mangle]
11525pub unsafe extern "C" fn clock_getres(clockid: c_int, ts: *mut timespec) -> c_int {
11526 let r = sys_clock_getres(clockid, ts);
11527 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
11528}
11529
11530#[no_mangle]
11531pub unsafe extern "C" fn clock_settime(clockid: c_int, ts: *const timespec) -> c_int {
11532 let r = sys_clock_settime(clockid, ts);
11533 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
11534}
11535
11536#[no_mangle]
11537pub unsafe extern "C" fn clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> c_int {
11538 let r = sys_clock_nanosleep(clockid, flags, req, rem);
11539 if r < 0 {
11540 let e = (-r) as c_int;
11541 if clockid == 3 && e == 95 { return 22; }
11544 e
11545 } else {
11546 0
11547 }
11548}
11549
11550#[no_mangle]
11551pub unsafe extern "C" fn gettimeofday(tv: *mut timeval, _tz: *mut c_void) -> c_int {
11552 if tv.is_null() { return 0; }
11553 let mut ts: timespec = core::mem::zeroed();
11554 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
11555 (*tv).tv_sec = ts.tv_sec;
11556 (*tv).tv_usec = ts.tv_nsec / 1000;
11557 0
11558}
11559
11560fn is_leap_year(y: i32) -> bool {
11565 let yr = if y > i32::MAX - 1900 { y - 2000 } else { y + 1900 };
11566 yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0)
11567}
11568
11569fn week_num(tm: &tm) -> i32 {
11570 let mut val = (tm.tm_yday + 7 - ((tm.tm_wday + 6) % 7)) / 7;
11571 if (tm.tm_wday + 371 - tm.tm_yday - 2).rem_euclid(7) <= 2 { val += 1; }
11572 if val == 0 {
11573 val = 52;
11574 let dec31 = (tm.tm_wday + 7 - tm.tm_yday - 1).rem_euclid(7);
11575 if dec31 == 4 || (dec31 == 5 && is_leap_year(tm.tm_year % 400 - 1)) { val += 1; }
11576 } else if val == 53 {
11577 let jan1 = (tm.tm_wday + 371 - tm.tm_yday).rem_euclid(7);
11578 if jan1 != 4 && (jan1 != 3 || !is_leap_year(tm.tm_year)) { val = 1; }
11579 }
11580 val
11581}
11582
11583const ABDAY_1: c_int = 0x20000;
11585const DAY_1: c_int = 0x20007;
11586const ABMON_1: c_int = 0x2000E;
11587const MON_1: c_int = 0x2001A;
11588const AM_STR_LI: c_int = 0x20026;
11589const PM_STR_LI: c_int = 0x20027;
11590const D_T_FMT: c_int = 0x20028;
11591const D_FMT: c_int = 0x20029;
11592const T_FMT: c_int = 0x2002A;
11593const T_FMT_AMPM: c_int = 0x2002B;
11594
11595unsafe fn num_fmt(buf: &mut [u8; 100], val: i64, pad: u8, width: usize) -> (*const u8, usize) {
11598 let negative = val < 0;
11599 let mut v = if negative { -val as u64 } else { val as u64 };
11600 let mut tmp = [0u8; 24];
11601 let mut pos = 24usize;
11602 if v == 0 { pos -= 1; tmp[pos] = b'0'; }
11603 while v > 0 { pos -= 1; tmp[pos] = b'0' + (v % 10) as u8; v /= 10; }
11604 let digits = 24 - pos;
11605 let sign_chars = if negative { 1 } else { 0 };
11606 let needed = sign_chars + digits;
11607 let fill = if width > needed { width - needed } else { 0 };
11608 let total = fill + needed;
11609 let mut p = 0usize;
11610 match pad {
11611 b'-' => { }
11612 b'_' => {
11613 for _ in 0..fill { buf[p] = b' '; p += 1; }
11614 if negative { buf[p] = b'-'; p += 1; }
11615 }
11616 _ => {
11617 if negative { buf[p] = b'-'; p += 1; }
11618 for _ in 0..fill { buf[p] = b'0'; p += 1; }
11619 }
11620 }
11621 for i in 0..digits { buf[p] = tmp[pos + i]; p += 1; }
11622 (buf.as_ptr(), total)
11623}
11624
11625unsafe fn str_to_buf(buf: &mut [u8; 100], s: *const c_char) -> (*const u8, usize) {
11627 let mut k = 0usize;
11628 while *s.add(k) != 0 {
11629 buf[k] = *s.add(k) as u8;
11630 k += 1;
11631 }
11632 (buf.as_ptr(), k)
11633}
11634
11635unsafe fn __strftime_fmt_1(buf: &mut [u8; 100], f: u8, tm: *const tm, pad: u8) -> (*const u8, usize) {
11638 let mut val: i64;
11639 let mut width: usize = 2;
11640 let mut def_pad: u8 = b'0';
11641 let fmt: *const c_char;
11642
11643 match f {
11644 b'a' => {
11645 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
11646 let p = nl_langinfo(ABDAY_1 + (*tm).tm_wday);
11647 return str_to_buf(buf, p);
11648 }
11649 b'A' => {
11650 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
11651 let p = nl_langinfo(DAY_1 + (*tm).tm_wday);
11652 return str_to_buf(buf, p);
11653 }
11654 b'h' | b'b' => {
11655 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
11656 let p = nl_langinfo(ABMON_1 + (*tm).tm_mon);
11657 return str_to_buf(buf, p);
11658 }
11659 b'B' => {
11660 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
11661 let p = nl_langinfo(MON_1 + (*tm).tm_mon);
11662 return str_to_buf(buf, p);
11663 }
11664 b'c' => {
11665 let p = nl_langinfo(D_T_FMT);
11666 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11667 return (buf.as_ptr(), l);
11668 }
11669 b'C' => {
11670 val = (1900i64 + (*tm).tm_year as i64) / 100;
11671 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11672 }
11673 b'e' => { def_pad = b'_'; }
11674 b'd' => {
11675 val = (*tm).tm_mday as i64;
11676 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11677 }
11678 b'D' => {
11679 fmt = b"%m/%d/%y\0".as_ptr() as *const c_char;
11680 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11681 return (buf.as_ptr(), l);
11682 }
11683 b'F' => {
11684 fmt = b"%Y-%m-%d\0".as_ptr() as *const c_char;
11685 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11686 return (buf.as_ptr(), l);
11687 }
11688 b'g' | b'G' => {
11689 val = (*tm).tm_year as i64 + 1900;
11690 if (*tm).tm_yday < 3 && week_num(&*tm) != 1 { val -= 1; }
11691 else if (*tm).tm_yday > 360 && week_num(&*tm) == 1 { val += 1; }
11692 if f == b'g' { val %= 100; }
11693 else { width = 4; }
11694 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11695 }
11696 b'H' => {
11697 val = (*tm).tm_hour as i64;
11698 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11699 }
11700 b'I' => {
11701 val = (*tm).tm_hour as i64;
11702 if val == 0 { val = 12; }
11703 else if val > 12 { val -= 12; }
11704 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11705 }
11706 b'j' => {
11707 val = (*tm).tm_yday as i64 + 1;
11708 width = 3;
11709 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11710 }
11711 b'm' => {
11712 val = (*tm).tm_mon as i64 + 1;
11713 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11714 }
11715 b'M' => {
11716 val = (*tm).tm_min as i64;
11717 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11718 }
11719 b'n' => { buf[0] = b'\n'; return (buf.as_ptr(), 1); }
11720 b'p' => {
11721 let p = if (*tm).tm_hour >= 12 { nl_langinfo(PM_STR_LI) } else { nl_langinfo(AM_STR_LI) };
11722 return str_to_buf(buf, p);
11723 }
11724 b'r' => {
11725 let p = nl_langinfo(T_FMT_AMPM);
11726 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11727 return (buf.as_ptr(), l);
11728 }
11729 b'R' => {
11730 fmt = b"%H:%M\0".as_ptr() as *const c_char;
11731 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11732 return (buf.as_ptr(), l);
11733 }
11734 b's' => {
11735 val = tm_to_secs(tm) - (*tm).tm_gmtoff as i64;
11736 width = 1;
11737 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11738 }
11739 b'S' => {
11740 val = (*tm).tm_sec as i64;
11741 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11742 }
11743 b't' => { buf[0] = b'\t'; return (buf.as_ptr(), 1); }
11744 b'T' => {
11745 fmt = b"%H:%M:%S\0".as_ptr() as *const c_char;
11746 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11747 return (buf.as_ptr(), l);
11748 }
11749 b'u' => {
11750 val = if (*tm).tm_wday != 0 { (*tm).tm_wday as i64 } else { 7 };
11751 width = 1;
11752 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11753 }
11754 b'U' => {
11755 val = ((*tm).tm_yday as u64 + 7 - (*tm).tm_wday as u64) as i64 / 7;
11756 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11757 }
11758 b'W' => {
11759 val = ((*tm).tm_yday as u64 + 7 - ((*tm).tm_wday as u64 + 6) % 7) as i64 / 7;
11760 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11761 }
11762 b'V' => {
11763 val = week_num(&*tm) as i64;
11764 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11765 }
11766 b'w' => {
11767 val = (*tm).tm_wday as i64;
11768 width = 1;
11769 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11770 }
11771 b'x' => {
11772 let p = nl_langinfo(D_FMT);
11773 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11774 return (buf.as_ptr(), l);
11775 }
11776 b'X' => {
11777 let p = nl_langinfo(T_FMT);
11778 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11779 return (buf.as_ptr(), l);
11780 }
11781 b'y' => {
11782 val = (1900i64 + (*tm).tm_year as i64) % 100;
11783 if val < 0 { val = -val; }
11784 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11785 }
11786 b'Y' => {
11787 val = (*tm).tm_year as i64 + 1900;
11788 if val >= 10000 {
11789 let mut tmp = [0u8; 100];
11790 let (_, k) = num_fmt(&mut tmp, val, b'-', 1);
11791 buf[0] = b'+';
11792 for i in 0..k { buf[1 + i] = tmp[i]; }
11793 return (buf.as_ptr(), 1 + k);
11794 }
11795 width = 4;
11796 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11797 }
11798 b'z' => {
11799 if (*tm).tm_isdst < 0 { return (b"\0".as_ptr(), 0); }
11800 let gmtoff = (*tm).tm_gmtoff as i64;
11801 let sign = if gmtoff >= 0 { b'+' } else { b'-' };
11802 let off = if gmtoff < 0 { -gmtoff } else { gmtoff };
11803 let hh = (off / 3600) as i32;
11804 let mm = ((off % 3600) / 60) as i32;
11805 buf[0] = sign;
11806 buf[1] = b'0' + (hh / 10) as u8;
11807 buf[2] = b'0' + (hh % 10) as u8;
11808 buf[3] = b'0' + (mm / 10) as u8;
11809 buf[4] = b'0' + (mm % 10) as u8;
11810 return (buf.as_ptr(), 5);
11811 }
11812 b'Z' => {
11813 if (*tm).tm_isdst < 0 || (*tm).tm_zone.is_null() { return (b"\0".as_ptr(), 0); }
11814 return str_to_buf(buf, (*tm).tm_zone);
11815 }
11816 b'%' => { buf[0] = b'%'; return (buf.as_ptr(), 1); }
11817 _ => { return (core::ptr::null(), 0); }
11818 }
11819 val = (*tm).tm_mday as i64;
11821 num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width)
11822}
11823
11824unsafe fn __strftime_l(s: *mut c_char, n: usize, f: *const c_char, tm: *const tm) -> usize {
11825 let mut l: usize = 0;
11826 let mut fi: usize = 0;
11827 while l < n {
11828 let ch = *f.add(fi) as u8;
11829 if ch == 0 {
11830 *s.add(l) = 0;
11831 return l;
11832 }
11833 if ch != b'%' {
11834 *s.add(l) = ch as c_char;
11835 l += 1;
11836 fi += 1;
11837 continue;
11838 }
11839 fi += 1;
11840 let mut pad: u8 = 0;
11842 let fc = *f.add(fi) as u8;
11843 if fc == b'-' || fc == b'_' || fc == b'0' { pad = fc; fi += 1; }
11844 let plus = *f.add(fi) as u8 == b'+';
11845 if plus { fi += 1; }
11846 let mut width: usize = 0;
11848 let mut p_idx = fi;
11849 {
11850 let fc2 = *f.add(fi) as u8;
11851 if fc2 >= b'0' && fc2 <= b'9' {
11852 let mut w: usize = 0;
11853 while { let c = *f.add(p_idx) as u8; c >= b'0' && c <= b'9' } {
11854 w = w * 10 + (*f.add(p_idx) as usize - b'0' as usize);
11855 p_idx += 1;
11856 }
11857 width = w;
11858 }
11859 }
11860 let spec_ch = *f.add(p_idx) as u8;
11861 if spec_ch == b'C' || spec_ch == b'F' || spec_ch == b'G' || spec_ch == b'Y' {
11862 if width == 0 && p_idx != fi { width = 1; }
11863 } else {
11864 width = 0;
11865 }
11866 fi = p_idx;
11867 let fc3 = *f.add(fi) as u8;
11869 if fc3 == b'E' || fc3 == b'O' { fi += 1; }
11870 let fch = *f.add(fi) as u8;
11871 let mut buf = [0u8; 100];
11873 let (t, k) = __strftime_fmt_1(&mut buf, fch, tm, pad);
11874 if t.is_null() { break; }
11875 let mut k = k;
11876 let mut t = t;
11877 if width != 0 {
11878 if *t == b'+' || *t == b'-' { t = t.add(1); k -= 1; }
11880 while k > 0 && *t == b'0' && k > 1 && *t.add(1) >= b'0' && *t.add(1) <= b'9' {
11881 t = t.add(1); k -= 1;
11882 }
11883 if width < k { width = k; }
11884 let mut d: usize = 0;
11885 while d < k && *t.add(d) >= b'0' && *t.add(d) <= b'9' { d += 1; }
11886 if (*tm).tm_year < -1900 {
11887 if l < n { *s.add(l) = b'-' as c_char; }
11888 l += 1;
11889 width -= 1;
11890 } else if plus && d + (width - k) >= (if spec_ch == b'C' { 3 } else { 5 }) {
11891 if l < n { *s.add(l) = b'+' as c_char; }
11892 l += 1;
11893 width -= 1;
11894 }
11895 while width > k && l < n {
11896 *s.add(l) = b'0' as c_char;
11897 l += 1;
11898 width -= 1;
11899 }
11900 }
11901 let copy = if k > n - l { n - l } else { k };
11902 core::ptr::copy_nonoverlapping(t, s.add(l) as *mut u8, copy);
11903 l += copy;
11904 fi += 1;
11905 }
11906 if n > 0 {
11907 if l == n { l = n - 1; }
11908 *s.add(l) = 0;
11909 }
11910 0
11911}
11912
11913#[no_mangle]
11914pub unsafe extern "C" fn strftime(s: *mut c_char, maxsize: usize, fmt: *const c_char, tm: *const tm) -> usize {
11915 __strftime_l(s, maxsize, fmt, tm)
11916}
11917
11918unsafe fn match_prefix(s: *const u8, prefix: &[u8]) -> bool {
11923 for i in 0..prefix.len() {
11924 if *s.add(i) == 0 || *s.add(i) != prefix[i] { return false; }
11925 }
11926 true
11927}
11928
11929unsafe fn match_ci_prefix(s: *const u8, prefix: &[u8]) -> bool {
11930 for i in 0..prefix.len() {
11931 let c = *s.add(i);
11932 if c == 0 { return false; }
11933 if c.to_ascii_lowercase() != prefix[i].to_ascii_lowercase() { return false; }
11934 }
11935 true
11936}
11937
11938unsafe fn parse_int(p: *const u8, max_digits: usize) -> (i32, *const u8) {
11939 let mut val = 0i32;
11940 let mut np = p;
11941 let mut count = 0;
11942 while *np >= b'0' && *np <= b'9' && count < max_digits {
11943 val = val * 10 + (*np - b'0') as i32;
11944 np = np.add(1);
11945 count += 1;
11946 }
11947 if count == 0 { (0, p) } else { (val, np) }
11948}
11949
11950unsafe fn parse_range(p: *const u8, min: i32, max: i32) -> (i32, *const u8) {
11951 let (val, np) = parse_int(p, 4);
11952 if np == p || val < min || val > max { (0, p) } else { (val, np) }
11953}
11954
11955fn is_ascii_space(c: u8) -> bool {
11956 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == 0x0c || c == 0x0b
11957}
11958
11959#[no_mangle]
11960pub unsafe extern "C" fn strptime(s: *const c_char, fmt: *const c_char, tm: *mut tm) -> *mut c_char {
11961 let mut p = s as *const u8;
11962 let mut f = fmt as *const u8;
11963 let mut want_century = 0i32;
11964 let mut century = 0i32;
11965 let mut relyear = 0i32;
11966 while *f != 0 {
11967 if *f != b'%' {
11968 if is_ascii_space(*f) {
11969 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
11970 } else {
11971 if *p != *f { return core::ptr::null_mut(); }
11972 p = p.add(1);
11973 }
11974 f = f.add(1);
11975 continue;
11976 }
11977 f = f.add(1);
11978 if *f == b'+' { f = f.add(1); }
11979 while *f >= b'0' && *f <= b'9' { f = f.add(1); }
11980 if *f == b'E' || *f == b'O' { f = f.add(1); }
11981 match *f {
11982 b'a' | b'A' => {
11983 let mut found = false;
11984 for i in 0..7 {
11985 let names: [&[u8]; 7] = [b"Sunday", b"Monday", b"Tuesday", b"Wednesday", b"Thursday", b"Friday", b"Saturday"];
11986 let snames: [&[u8]; 7] = [b"Sun", b"Mon", b"Tue", b"Wed", b"Thu", b"Fri", b"Sat"];
11987 if match_prefix(p, names[i]) { (*tm).tm_wday = i as c_int; p = p.add(names[i].len()); found = true; break; }
11988 if match_prefix(p, snames[i]) { (*tm).tm_wday = i as c_int; p = p.add(snames[i].len()); found = true; break; }
11989 }
11990 if !found { return core::ptr::null_mut(); }
11991 }
11992 b'b' | b'B' | b'h' => {
11993 let mut found = false;
11994 for i in 0..12 {
11995 let names: [&[u8]; 12] = [b"January", b"February", b"March", b"April", b"May", b"June", b"July", b"August", b"September", b"October", b"November", b"December"];
11996 let snames: [&[u8]; 12] = [b"Jan", b"Feb", b"Mar", b"Apr", b"May", b"Jun", b"Jul", b"Aug", b"Sep", b"Oct", b"Nov", b"Dec"];
11997 if match_prefix(p, names[i]) { (*tm).tm_mon = i as c_int; p = p.add(names[i].len()); found = true; break; }
11998 if match_prefix(p, snames[i]) { (*tm).tm_mon = i as c_int; p = p.add(snames[i].len()); found = true; break; }
11999 }
12000 if !found { return core::ptr::null_mut(); }
12001 }
12002 b'C' => {
12003 let (v, np) = parse_int(p, 2);
12004 if np == p { return core::ptr::null_mut(); }
12005 century = v;
12006 want_century |= 2;
12007 p = np;
12008 }
12009 b'd' | b'e' => {
12010 let (v, np) = parse_range(p, 1, 31);
12011 if np == p { return core::ptr::null_mut(); }
12012 (*tm).tm_mday = v;
12013 p = np;
12014 }
12015 b'D' => {
12016 let r = strptime(p as *const c_char, b"%m/%d/%y\0".as_ptr() as *const c_char, tm);
12017 if r.is_null() { return core::ptr::null_mut(); }
12018 p = r as *const u8;
12019 }
12020 b'F' => {
12021 let (yv, ynp) = parse_int(p, 4);
12022 if ynp == p { return core::ptr::null_mut(); }
12023 (*tm).tm_year = yv - 1900;
12024 p = ynp;
12025 if *p != b'-' { return core::ptr::null_mut(); }
12026 p = p.add(1);
12027 let (mv, mnp) = parse_range(p, 1, 12);
12028 if mnp == p { return core::ptr::null_mut(); }
12029 (*tm).tm_mon = mv - 1;
12030 p = mnp;
12031 if *p != b'-' { return core::ptr::null_mut(); }
12032 p = p.add(1);
12033 let (dv, dnp) = parse_range(p, 1, 31);
12034 if dnp == p { return core::ptr::null_mut(); }
12035 (*tm).tm_mday = dv;
12036 p = dnp;
12037 }
12038 b'H' | b'I' => {
12039 let (v, np) = parse_range(p, 0, 23);
12040 if np == p { return core::ptr::null_mut(); }
12041 (*tm).tm_hour = v;
12042 p = np;
12043 }
12044 b'j' => {
12045 let (v, np) = parse_range(p, 1, 366);
12046 if np == p { return core::ptr::null_mut(); }
12047 (*tm).tm_yday = v - 1;
12048 p = np;
12049 }
12050 b'm' => {
12051 let (v, np) = parse_range(p, 1, 12);
12052 if np == p { return core::ptr::null_mut(); }
12053 (*tm).tm_mon = v - 1;
12054 p = np;
12055 }
12056 b'M' => {
12057 let (v, np) = parse_range(p, 0, 59);
12058 if np == p { return core::ptr::null_mut(); }
12059 (*tm).tm_min = v;
12060 p = np;
12061 }
12062 b'n' | b't' => {
12063 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
12064 }
12065 b'p' => {
12066 if match_ci_prefix(p, b"AM") {
12067 if (*tm).tm_hour == 12 { (*tm).tm_hour = 0; }
12068 p = p.add(2);
12069 } else if match_ci_prefix(p, b"PM") {
12070 if (*tm).tm_hour < 12 { (*tm).tm_hour += 12; }
12071 p = p.add(2);
12072 } else { return core::ptr::null_mut(); }
12073 }
12074 b'r' => {
12075 let r = strptime(p as *const c_char, b"%I:%M:%S %p\0".as_ptr() as *const c_char, tm);
12076 if r.is_null() { return core::ptr::null_mut(); }
12077 p = r as *const u8;
12078 }
12079 b'R' => {
12080 let r = strptime(p as *const c_char, b"%H:%M\0".as_ptr() as *const c_char, tm);
12081 if r.is_null() { return core::ptr::null_mut(); }
12082 p = r as *const u8;
12083 }
12084 b's' => {
12085 let neg = if *p == b'-' { p = p.add(1); true } else { false };
12086 if *p < b'0' || *p > b'9' { return core::ptr::null_mut(); }
12087 let mut val = 0i64;
12088 while *p >= b'0' && *p <= b'9' {
12089 val = val * 10 + (*p - b'0') as i64;
12090 p = p.add(1);
12091 }
12092 if neg { val = -val; }
12093 secs_to_tm(val, &mut *tm);
12094 }
12095 b'S' => {
12096 let (v, np) = parse_range(p, 0, 60);
12097 if np == p { return core::ptr::null_mut(); }
12098 (*tm).tm_sec = v;
12099 p = np;
12100 }
12101 b'T' => {
12102 let r = strptime(p as *const c_char, b"%H:%M:%S\0".as_ptr() as *const c_char, tm);
12103 if r.is_null() { return core::ptr::null_mut(); }
12104 p = r as *const u8;
12105 }
12106 b'U' | b'W' => {
12107 let (_, np) = parse_range(p, 0, 53);
12108 if np == p { return core::ptr::null_mut(); }
12109 p = np;
12110 }
12111 b'V' => {
12112 let (_, np) = parse_range(p, 1, 53);
12113 if np == p { return core::ptr::null_mut(); }
12114 p = np;
12115 }
12116 b'w' => {
12117 let (v, np) = parse_range(p, 0, 6);
12118 if np == p { return core::ptr::null_mut(); }
12119 (*tm).tm_wday = v;
12120 p = np;
12121 }
12122 b'y' => {
12123 let (v, np) = parse_int(p, 2);
12124 if np == p { return core::ptr::null_mut(); }
12125 relyear = v;
12126 want_century |= 1;
12127 p = np;
12128 }
12129 b'Y' => {
12130 let neg = if *p == b'-' { p = p.add(1); true } else { false };
12131 let (v, np) = parse_int(p, 4);
12132 if np == p { return core::ptr::null_mut(); }
12133 (*tm).tm_year = if neg { -(v + 1900) } else { v - 1900 };
12134 want_century = 0;
12135 p = np;
12136 }
12137 b'z' => {
12138 if *p != b'+' && *p != b'-' { return core::ptr::null_mut(); }
12139 let neg = *p == b'-';
12140 p = p.add(1);
12141 let mut off = 0i64;
12142 let mut digits = 0;
12143 while digits < 4 && *p >= b'0' && *p <= b'9' {
12144 off = off * 10 + (*p - b'0') as i64;
12145 p = p.add(1);
12146 digits += 1;
12147 }
12148 if digits == 0 { return core::ptr::null_mut(); }
12149 let (hh, mm) = if digits <= 2 { (off, 0i64) } else { (off / 100, off % 100) };
12150 (*tm).tm_gmtoff = (hh * 3600 + mm * 60) * if neg { -1 } else { 1 };
12151 }
12152 b'%' => {
12153 if *p != b'%' { return core::ptr::null_mut(); }
12154 p = p.add(1);
12155 }
12156 _ => { return core::ptr::null_mut(); }
12157 }
12158 f = f.add(1);
12159 }
12160 if want_century != 0 {
12161 (*tm).tm_year = relyear;
12162 if want_century & 2 != 0 { (*tm).tm_year += century * 100 - 1900; }
12163 else if (*tm).tm_year <= 68 { (*tm).tm_year += 100; }
12164 }
12165 p as *mut c_char
12166}
12167
12168#[no_mangle]
12173pub static mut daylight: c_int = 0;
12174#[no_mangle]
12175pub static mut timezone: c_long = 0;
12176#[no_mangle]
12177pub static mut tzname: [*mut c_char; 2] = [b"UTC\0".as_ptr() as *mut c_char, b"UTC\0".as_ptr() as *mut c_char];
12178
12179#[no_mangle]
12180pub unsafe extern "C" fn tzset() {
12181 daylight = 0;
12182 timezone = 0;
12183}
12184
12185#[no_mangle]
12190pub unsafe extern "C" fn system(cmd: *const c_char) -> c_int {
12191 if cmd.is_null() {
12192 let pid = sys_fork();
12194 if pid == 0 {
12195 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
12196 let dash_c = b"-c\0".as_ptr() as *const c_char;
12197 let exit0 = b"exit 0\0".as_ptr() as *const c_char;
12198 let argv = [b"sh\0".as_ptr() as *const c_char, dash_c, exit0, core::ptr::null()];
12199 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
12200 _exit(127);
12201 }
12202 if pid < 0 { return -1; }
12203 let mut status: c_int = 0;
12204 loop {
12205 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
12206 if r >= 0 { return status; }
12207 if r != -4 { return -1; } }
12209 }
12210
12211 let sa_ignore = KSigAction {
12212 sa_handler: SIG_IGN,
12213 sa_flags: SA_RESTORER,
12214 sa_restorer: sig_restorer as *const () as usize,
12215 sa_mask: [0],
12216 };
12217 let mut oldint: KSigAction = core::mem::zeroed();
12218 let mut oldquit: KSigAction = core::mem::zeroed();
12219
12220 sys_rt_sigaction(SIGINT, &sa_ignore, &mut oldint, 8);
12221 sys_rt_sigaction(SIGQUIT, &sa_ignore, &mut oldquit, 8);
12222
12223 let mut block_set: SigSetT = 0;
12224 block_set |= 1u64 << (SIGCHLD - 1);
12225 let mut oldmask: SigSetT = 0;
12226 sys_rt_sigprocmask(SIG_BLOCK, &block_set, &mut oldmask, 8);
12227
12228 let pid = sys_fork();
12229
12230 if pid == 0 {
12231 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
12232 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
12233 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
12234
12235 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
12236 let argv = [
12237 b"sh\0".as_ptr() as *const c_char,
12238 b"-c\0".as_ptr() as *const c_char,
12239 cmd,
12240 core::ptr::null(),
12241 ];
12242 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
12243 _exit(127);
12244 }
12245
12246 let mut status: c_int = -1;
12247 if pid > 0 {
12248 loop {
12249 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
12250 if r >= 0 { break; }
12251 if r != -4 { break; } }
12253 }
12254
12255 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
12256 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
12257 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
12258
12259 status
12260}
12261
12262const EPERM_VAL: c_int = 1;
12267const ENOENT_VAL: c_int = 2;
12268const ESRCH_VAL: c_int = 3;
12269const EINTR_VAL: c_int = 4;
12270const EIO_VAL: c_int = 5;
12271const ENXIO_VAL: c_int = 6;
12272const E2BIG_VAL: c_int = 7;
12273const ENOEXEC_VAL: c_int = 8;
12274const EBADF_VAL: c_int = 9;
12275const ECHILD_VAL: c_int = 10;
12276const EAGAIN_VAL: c_int = 11;
12277const ENOMEM_VAL: c_int = 12;
12278const EACCES_VAL: c_int = 13;
12279const EFAULT_VAL: c_int = 14;
12280const ENOTBLK_VAL: c_int = 15;
12281const EBUSY_VAL: c_int = 16;
12282const EEXIST_VAL: c_int = 17;
12283const EXDEV_VAL: c_int = 18;
12284const ENODEV_VAL: c_int = 19;
12285const ENOTDIR_VAL: c_int = 20;
12286const EISDIR_VAL: c_int = 21;
12287const EINVAL_VAL: c_int = 22;
12288const ENFILE_VAL: c_int = 23;
12289const EMFILE_VAL: c_int = 24;
12290const ENOTTY_VAL: c_int = 25;
12291const ETXTBSY_VAL: c_int = 26;
12292const EFBIG_VAL: c_int = 27;
12293const ENOSPC_VAL: c_int = 28;
12294const ESPIPE_VAL: c_int = 29;
12295const EROFS_VAL: c_int = 30;
12296const EMLINK_VAL: c_int = 31;
12297const EPIPE_VAL: c_int = 32;
12298const EDOM_VAL: c_int = 33;
12299const ERANGE_VAL: c_int = 34;
12300const EDEADLK_VAL: c_int = 35;
12301const ENAMETOOLONG_VAL: c_int = 36;
12302const ENOLCK_VAL: c_int = 37;
12303const ENOSYS_VAL: c_int = 38;
12304const ENOTEMPTY_VAL: c_int = 39;
12305const ELOOP_VAL: c_int = 40;
12306const EWOULDBLOCK_VAL: c_int = 11;
12307const ENOMSG_VAL: c_int = 42;
12308const EIDRM_VAL: c_int = 43;
12309const ECHRNG_VAL: c_int = 44;
12310const EL2NSYNC_VAL: c_int = 45;
12311const EL3HLT_VAL: c_int = 46;
12312const EL3RST_VAL: c_int = 47;
12313const ELNRNG_VAL: c_int = 48;
12314const EUNATCH_VAL: c_int = 49;
12315const ENOCSI_VAL: c_int = 50;
12316const EL2HLT_VAL: c_int = 51;
12317const EBADE_VAL: c_int = 52;
12318const EBADR_VAL: c_int = 53;
12319const EXFULL_VAL: c_int = 54;
12320const ENOANO_VAL: c_int = 55;
12321const EBADRQC_VAL: c_int = 56;
12322const EBADSLT_VAL: c_int = 57;
12323const EBFONT_VAL: c_int = 59;
12324const ENOSTR_VAL: c_int = 60;
12325const ENODATA_VAL: c_int = 61;
12326const ETIME_VAL: c_int = 62;
12327const ENOSR_VAL: c_int = 63;
12328const ENONET_VAL: c_int = 64;
12329const ENOPKG_VAL: c_int = 65;
12330const EREMOTE_VAL: c_int = 66;
12331const ENOLINK_VAL: c_int = 67;
12332const EADV_VAL: c_int = 68;
12333const ESRMNT_VAL: c_int = 69;
12334const ECOMM_VAL: c_int = 70;
12335const EPROTO_VAL: c_int = 71;
12336const EMULTIHOP_VAL: c_int = 72;
12337const EDOTDOT_VAL: c_int = 73;
12338const EBADMSG_VAL: c_int = 74;
12339const EOVERFLOW_VAL: c_int = 75;
12340const ENOTUNIQ_VAL: c_int = 76;
12341const EBADFD_VAL: c_int = 77;
12342const EREMCHG_VAL: c_int = 78;
12343const ELIBACC_VAL: c_int = 79;
12344const ELIBBAD_VAL: c_int = 80;
12345const ELIBSCN_VAL: c_int = 81;
12346const ELIBMAX_VAL: c_int = 82;
12347const ELIBEXEC_VAL: c_int = 83;
12348const EILSEQ_VAL: c_int = 84;
12349const ERESTART_VAL: c_int = 85;
12350const ESTRPIPE_VAL: c_int = 86;
12351const EUSERS_VAL: c_int = 87;
12352const ENOTSOCK_VAL: c_int = 88;
12353const EDESTADDRREQ_VAL: c_int = 89;
12354const EMSGSIZE_VAL: c_int = 90;
12355const EPROTOTYPE_VAL: c_int = 91;
12356const ENOPROTOOPT_VAL: c_int = 92;
12357const EPROTONOSUPPORT_VAL: c_int = 93;
12358const ESOCKTNOSUPPORT_VAL: c_int = 94;
12359const EOPNOTSUPP_VAL: c_int = 95;
12360const ENOTSUP_VAL: c_int = 95;
12361const EPFNOSUPPORT_VAL: c_int = 96;
12362const EAFNOSUPPORT_VAL: c_int = 97;
12363const EADDRINUSE_VAL: c_int = 98;
12364const EADDRNOTAVAIL_VAL: c_int = 99;
12365const ENETDOWN_VAL: c_int = 100;
12366const ENETUNREACH_VAL: c_int = 101;
12367const ENETRESET_VAL: c_int = 102;
12368const ECONNABORTED_VAL: c_int = 103;
12369const ECONNRESET_VAL: c_int = 104;
12370const ENOBUFS_VAL: c_int = 105;
12371const EISCONN_VAL: c_int = 106;
12372const ENOTCONN_VAL: c_int = 107;
12373const ESHUTDOWN_VAL: c_int = 108;
12374const ETOOMANYREFS_VAL: c_int = 109;
12375const ETIMEDOUT_VAL: c_int = 110;
12376const ECONNREFUSED_VAL: c_int = 111;
12377const EHOSTDOWN_VAL: c_int = 112;
12378const EHOSTUNREACH_VAL: c_int = 113;
12379const EALREADY_VAL: c_int = 114;
12380const EINPROGRESS_VAL: c_int = 115;
12381const ESTALE_VAL: c_int = 116;
12382const EUCLEAN_VAL: c_int = 117;
12383const ENOTNAM_VAL: c_int = 118;
12384const ENAVAIL_VAL: c_int = 119;
12385const EISNAM_VAL: c_int = 120;
12386const EREMOTEIO_VAL: c_int = 121;
12387const EDQUOT_VAL: c_int = 122;
12388const ENOMEDIUM_VAL: c_int = 123;
12389const EMEDIUMTYPE_VAL: c_int = 124;
12390const ECANCELED_VAL: c_int = 125;
12391const ENOKEY_VAL: c_int = 126;
12392const EKEYEXPIRED_VAL: c_int = 127;
12393const EKEYREVOKED_VAL: c_int = 128;
12394const EKEYREJECTED_VAL: c_int = 129;
12395const EOWNERDEAD_VAL: c_int = 130;
12396const ENOTRECOVERABLE_VAL: c_int = 131;
12397const ERFKILL_VAL: c_int = 132;
12398const EHWPOISON_VAL: c_int = 133;
12399
12400static ERR_STRS: [&[u8]; 134] = [
12402 b"Success\0", b"Operation not permitted\0", b"No such file or directory\0", b"No such process\0", b"Interrupted system call\0", b"Input/output error\0", b"No such device or address\0", b"Argument list too long\0", b"Exec format error\0", b"Bad file descriptor\0", b"No child processes\0", b"Resource temporarily unavailable\0", b"Cannot allocate memory\0", b"Permission denied\0", b"Bad address\0", b"Block device required\0", b"Device or resource busy\0", b"File exists\0", b"Invalid cross-device link\0", b"No such device\0", b"Not a directory\0", b"Is a directory\0", b"Invalid argument\0", b"Too many open files in system\0", b"Too many open files\0", b"Inappropriate ioctl for device\0", b"Text file busy\0", b"File too large\0", b"No space left on device\0", b"Illegal seek\0", b"Read-only file system\0", b"Too many links\0", b"Broken pipe\0", b"Numerical argument out of domain\0", b"Numerical result out of range\0", b"Resource deadlock avoided\0", b"File name too long\0", b"No locks available\0", b"Function not implemented\0", b"Directory not empty\0", b"Too many levels of symbolic links\0", b"Unknown error 41\0", b"No message of desired type\0", b"Identifier removed\0", b"Channel number out of range\0", b"Level 2 not synchronized\0", b"Level 3 halted\0", b"Level 3 reset\0", b"Link number out of range\0", b"Protocol driver not attached\0", b"No CSI structure available\0", b"Level 2 halted\0", b"Invalid exchange\0", b"Invalid request descriptor\0", b"Exchange full\0", b"No anode\0", b"Invalid request code\0", b"Invalid slot\0", b"Unknown error 58\0", b"Bad font file format\0", b"Device not a stream\0", b"No data available\0", b"Timer expired\0", b"Out of streams resources\0", b"Machine is not on the network\0", b"Package not installed\0", b"Object is remote\0", b"Link has been severed\0", b"Advertise error\0", b"Srmount error\0", b"Communication error on send\0", b"Protocol error\0", b"Multihop attempted\0", b"RFS specific error\0", b"Bad message\0", b"Value too large for defined data type\0", b"Name not unique on network\0", b"File descriptor in bad state\0", b"Remote address changed\0", b"Can not access a needed shared library\0", b"Accessing a corrupted shared library\0", b".lib section in a.out corrupted\0", b"Attempting to link in too many shared libraries\0", b"Cannot exec a shared library directly\0", b"Invalid or incomplete multibyte or wide character\0", b"Interrupted system call should be restarted\0", b"Streams pipe error\0", b"Too many users\0", b"Socket operation on non-socket\0", b"Destination address required\0", b"Message too long\0", b"Protocol wrong type for socket\0", b"Protocol not available\0", b"Protocol not supported\0", b"Socket type not supported\0", b"Operation not supported\0", b"Protocol family not supported\0", b"Address family not supported by protocol\0", b"Address already in use\0", b"Cannot assign requested address\0", b"Network is down\0", b"Network is unreachable\0", b"Network dropped connection on reset\0", b"Software caused connection abort\0", b"Connection reset by peer\0", b"No buffer space available\0", b"Transport endpoint is already connected\0", b"Transport endpoint is not connected\0", b"Cannot send after transport endpoint shutdown\0", b"Too many references: cannot splice\0", b"Connection timed out\0", b"Connection refused\0", b"Host is down\0", b"No route to host\0", b"Operation already in progress\0", b"Operation now in progress\0", b"Stale file handle\0", b"Structure needs cleaning\0", b"Not a XENIX named type file\0", b"No XENIX semaphores available\0", b"Is a named type file\0", b"Remote I/O error\0", b"Quota exceeded\0", b"No medium found\0", b"Wrong medium type\0", b"Operation canceled\0", b"Required key not available\0", b"Key has expired\0", b"Key has been revoked\0", b"Key was rejected by service\0", b"Owner died\0", b"State not recoverable\0", b"Operation not possible due to RF-kill\0", b"Memory page has hardware error\0", ];
12537
12538#[no_mangle]
12539pub unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char {
12540 if errnum < 0 || errnum as usize >= ERR_STRS.len() {
12541 static mut UNKNOWN_BUF: [c_char; 32] = [0; 32];
12543 let prefix = b"Unknown error \0";
12544 let mut i = 0;
12545 while prefix[i] != 0 {
12546 UNKNOWN_BUF[i] = prefix[i] as c_char;
12547 i += 1;
12548 }
12549 let (buf, len) = format_u64(errnum as u64);
12550 for j in 0..len {
12551 UNKNOWN_BUF[i] = buf[20 - len + j] as c_char;
12552 i += 1;
12553 }
12554 UNKNOWN_BUF[i] = 0;
12555 return core::ptr::addr_of_mut!(UNKNOWN_BUF).cast::<c_char>();
12556 }
12557 ERR_STRS[errnum as usize].as_ptr() as *mut c_char
12558}
12559
12560#[no_mangle]
12561pub unsafe extern "C" fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: usize) -> c_int {
12562 let s = strerror(errnum);
12563 let slen = strlen(s as *const c_char);
12564 if slen >= buflen {
12565 if buflen > 0 {
12566 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, buflen - 1);
12567 *buf.add(buflen - 1) = 0;
12568 }
12569 return 34; }
12571 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, slen + 1);
12572 0
12573}
12574
12575#[no_mangle]
12577pub static mut environ: *mut *mut c_char = core::ptr::null_mut();
12578
12579unsafe fn sync_environ() {
12581 environ = __environ;
12582}
12583
12584#[inline]
12589unsafe fn sys_dup(oldfd: i32) -> i64 {
12590 <Arch as Syscalls>::syscall1(SYS_DUP, oldfd as i64)
12591}
12592
12593#[inline]unsafe fn sys_dup2(oldfd: i32, newfd: i32) -> i64 {
12594 sys_dup3(oldfd, newfd, 0)
12596}
12597
12598#[inline]
12599unsafe fn sys_access(path: *const u8, mode: i32) -> i64 {
12600 <Arch as Syscalls>::syscall4(SYS_FACCESSAT, AT_FDCWD as i64, path as i64, mode as i64, 0)
12601}
12602
12603#[inline]unsafe fn sys_unlink(path: *const u8) -> i64 {
12604 sys_unlinkat(AT_FDCWD, path, 0)
12605}
12606
12607#[inline]unsafe fn sys_rmdir(path: *const u8) -> i64 {
12608 sys_unlinkat(AT_FDCWD, path, 512) }
12610
12611#[inline]
12612unsafe fn sys_chdir(path: *const u8) -> i64 {
12613 <Arch as Syscalls>::syscall1(SYS_CHDIR, path as i64)
12614}
12615
12616#[inline]
12617unsafe fn sys_getcwd(buf: *mut u8, size: usize) -> i64 {
12618 <Arch as Syscalls>::syscall2(SYS_GETCWD, buf as i64, size as i64)
12619}
12620
12621#[inline]
12622unsafe fn sys_sethostname(name: *const u8, len: usize) -> i64 {
12623 <Arch as Syscalls>::syscall2(SYS_SETHOSTNAME, name as i64, len as i64)
12624}
12625
12626#[inline]
12627unsafe fn sys_gethostname(buf: *mut u8, len: usize) -> i64 {
12628 #[repr(C)]
12629 struct UtsName {
12630 sysname: [u8; 65],
12631 nodename: [u8; 65],
12632 release: [u8; 65],
12633 version: [u8; 65],
12634 machine: [u8; 65],
12635 domainname: [u8; 65],
12636 }
12637 let mut uts: UtsName = core::mem::zeroed();
12638 let result = <Arch as Syscalls>::syscall1(SYS_UNAME, &mut uts as *mut UtsName as i64);
12639 if result < 0 {
12640 return result;
12641 }
12642 let nlen = strlen(uts.nodename.as_ptr() as *const c_char);
12643 let copylen = if nlen < len { nlen } else { if len > 0 { len - 1 } else { 0 } };
12644 core::ptr::copy_nonoverlapping(uts.nodename.as_ptr(), buf, copylen);
12645 if len > 0 { *buf.add(copylen) = 0; }
12646 0
12647}
12648
12649unsafe fn sys_truncate(path: *const u8, length: i64) -> i64 {
12650 <Arch as Syscalls>::syscall2(SYS_TRUNCATE, path as i64, length as i64)
12651}
12652
12653unsafe fn sys_ftruncate(fd: i32, length: i64) -> i64 {
12654 <Arch as Syscalls>::syscall2(SYS_FTRUNCATE, fd as i64, length as i64)
12655}
12656
12657unsafe fn sys_nanosleep(req: *const timespec, rem: *mut timespec) -> i64 {
12658 <Arch as Syscalls>::syscall2(SYS_NANOSLEEP, req as i64, rem as i64)
12659}
12660
12661const ITIMER_REAL: i32 = 0;
12662
12663#[repr(C)]
12664struct itimerval {
12665 it_interval: timeval,
12666 it_value: timeval,
12667}
12668
12669unsafe fn sys_alarm(seconds: c_uint) -> i64 {
12670 let mut new: itimerval = core::mem::zeroed();
12671 new.it_value.tv_sec = seconds as c_long;
12672 let mut old: itimerval = core::mem::zeroed();
12673 let r = <Arch as Syscalls>::syscall3(
12674 SYS_SETITIMER,
12675 ITIMER_REAL as i64,
12676 &new as *const _ as i64,
12677 &mut old as *mut _ as i64,
12678 );
12679 if r < 0 {
12680 return r;
12681 }
12682 old.it_value.tv_sec as i64 + (old.it_value.tv_usec != 0) as i64
12683}
12684
12685unsafe fn sys_pause() -> i64 {
12686 #[cfg(target_arch = "x86_64")]
12687 { <Arch as Syscalls>::syscall0(SYS_PAUSE) }
12688 #[cfg(target_arch = "aarch64")]
12689 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12690 #[cfg(target_arch = "riscv64")]
12691 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12692}
12693
12694unsafe fn sys_fsync(fd: i32) -> i64 {
12695 <Arch as Syscalls>::syscall1(SYS_FSYNC, fd as i64)
12696}
12697
12698unsafe fn sys_fdatasync(fd: i32) -> i64 {
12699 <Arch as Syscalls>::syscall1(SYS_FDATASYNC, fd as i64)
12700}
12701
12702unsafe fn sys_sync() {
12703 let _ = <Arch as Syscalls>::syscall0(SYS_SYNC);
12704}
12705
12706unsafe fn sys_symlink(target: *const u8, linkpath: *const u8) -> i64 {
12707 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, AT_FDCWD as i64, linkpath as i64)
12708}
12709
12710unsafe fn sys_symlinkat(target: *const u8, newdirfd: i32, linkpath: *const u8) -> i64 {
12711 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, newdirfd as i64, linkpath as i64)
12712}
12713
12714unsafe fn sys_readlinkat(dirfd: i32, path: *const u8, buf: *mut u8, bufsiz: usize) -> i64 {
12715 <Arch as Syscalls>::syscall4(SYS_READLINKAT, dirfd as i64, path as i64, buf as i64, bufsiz as i64)
12716}
12717
12718unsafe fn sys_linkat(olddirfd: i32, oldpath: *const u8, newdirfd: i32, newpath: *const u8, flags: i32) -> i64 {
12719 <Arch as Syscalls>::syscall5(SYS_LINKAT, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)
12720}
12721
12722unsafe fn sys_fchmod(fd: i32, mode: u32) -> i64 {
12723 <Arch as Syscalls>::syscall2(SYS_FCHMOD, fd as i64, mode as i64)
12724}
12725
12726unsafe fn sys_fchmodat(dirfd: i32, path: *const u8, mode: u32, flags: i32) -> i64 {
12727 <Arch as Syscalls>::syscall4(SYS_FCHMODAT, dirfd as i64, path as i64, mode as i64, flags as i64)
12728}
12729
12730unsafe fn sys_umask(mask: u32) -> u32 {
12731 <Arch as Syscalls>::syscall1(SYS_UMASK, mask as i64) as u32
12732}
12733
12734unsafe fn sys_getgroups(size: i32, list: *mut c_uint) -> i64 {
12735 <Arch as Syscalls>::syscall2(SYS_GETGROUPS, size as i64, list as i64)
12736}
12737
12738unsafe fn sys_setuid(uid: c_uint) -> i64 {
12739 <Arch as Syscalls>::syscall1(SYS_SETUID, uid as i64)
12740}
12741
12742unsafe fn sys_setgid(gid: c_uint) -> i64 {
12743 <Arch as Syscalls>::syscall1(SYS_SETGID, gid as i64)
12744}
12745
12746unsafe fn sys_setsid() -> i64 {
12747 <Arch as Syscalls>::syscall0(SYS_SETSID)
12748}
12749
12750unsafe fn sys_setpgid(pid: c_int, pgid: c_int) -> i64 {
12751 <Arch as Syscalls>::syscall2(SYS_SETPGID, pid as i64, pgid as i64)
12752}
12753
12754unsafe fn sys_getpgid(pid: c_int) -> i64 {
12755 <Arch as Syscalls>::syscall1(SYS_GETPGID, pid as i64)
12756}
12757
12758unsafe fn sys_getsid(pid: c_int) -> i64 {
12759 <Arch as Syscalls>::syscall1(SYS_GETSID, pid as i64)
12760}
12761
12762unsafe fn sys_mkdirat(dirfd: i32, path: *const u8, mode: u32) -> i64 {
12763 <Arch as Syscalls>::syscall3(SYS_MKDIRAT, dirfd as i64, path as i64, mode as i64)
12764}
12765
12766#[no_mangle]
12769pub unsafe extern "C" fn pipe(fds: *mut c_int) -> c_int {
12770 let r = sys_pipe2(fds, 0);
12771 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12772 0
12773}
12774
12775#[no_mangle]
12776pub unsafe extern "C" fn pipe2(fds: *mut c_int, flags: c_int) -> c_int {
12777 let r = sys_pipe2(fds, flags);
12778 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12779 0
12780}
12781
12782#[no_mangle]
12783pub unsafe extern "C" fn dup(oldfd: c_int) -> c_int {
12784 let r = sys_dup(oldfd);
12785 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12786 r as c_int
12787}
12788
12789#[no_mangle]
12790pub unsafe extern "C" fn dup2(oldfd: c_int, newfd: c_int) -> c_int {
12791 if oldfd == newfd {
12792 let r = sys_fcntl(oldfd, 1 , 0);
12795 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12796 return newfd;
12797 }
12798 let r = sys_dup2(oldfd, newfd);
12799 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12800 r as c_int
12801}
12802
12803#[no_mangle]
12804pub unsafe extern "C" fn dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int {
12805 let r = sys_dup3(oldfd, newfd, flags);
12806 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12807 r as c_int
12808}
12809
12810#[no_mangle]
12811pub unsafe extern "C" fn fcntl(fd: c_int, cmd: c_int, mut args: ...) -> c_int {
12812 let no_arg = matches!(cmd, 1 | 3 | 9 | 11 | 1025 | 1032 | 1034 );
12817 let r = if no_arg {
12818 sys_fcntl(fd, cmd, 0)
12819 } else {
12820 let arg = args.next_arg::<c_long>();
12821 sys_fcntl(fd, cmd, arg)
12822 };
12823 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12824 r as c_int
12825}
12826
12827#[no_mangle]
12828pub unsafe extern "C" fn access(path: *const c_char, mode: c_int) -> c_int {
12829 let r = sys_access(path as *const u8, mode);
12830 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12831 0
12832}
12833
12834#[no_mangle]
12835pub unsafe extern "C" fn unlink(path: *const c_char) -> c_int {
12836 let r = sys_unlink(path as *const u8);
12837 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12838 0
12839}
12840
12841#[no_mangle]
12842pub unsafe extern "C" fn rmdir(path: *const c_char) -> c_int {
12843 let r = sys_rmdir(path as *const u8);
12844 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12845 0
12846}
12847
12848#[no_mangle]
12849pub unsafe extern "C" fn chdir(path: *const c_char) -> c_int {
12850 let r = sys_chdir(path as *const u8);
12851 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12852 0
12853}
12854
12855#[no_mangle]
12856pub unsafe extern "C" fn getcwd(buf: *mut c_char, size: usize) -> *mut c_char {
12857 if buf.is_null() {
12858 let alloc_size = if size == 0 { 256 } else { size };
12860 let p = malloc(alloc_size) as *mut c_char;
12861 if p.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
12862 let r = sys_getcwd(p as *mut u8, alloc_size);
12863 if r < 0 { free(p as *mut c_void); ERRNO!() = (-r) as c_int; return core::ptr::null_mut(); }
12864 if *p as u8 != b'/' {
12867 free(p as *mut c_void);
12868 ERRNO!() = 2;
12869 return core::ptr::null_mut();
12870 }
12871 return p;
12872 }
12873 if size == 0 { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
12874 let r = sys_getcwd(buf as *mut u8, size);
12875 if r < 0 { ERRNO!() = (-r) as c_int; return core::ptr::null_mut(); }
12876 if *buf as u8 != b'/' {
12877 ERRNO!() = 2;
12878 return core::ptr::null_mut();
12879 }
12880 buf
12881}
12882
12883#[no_mangle]
12884pub unsafe extern "C" fn gethostname(name: *mut c_char, len: usize) -> c_int {
12885 let r = sys_gethostname(name as *mut u8, len);
12886 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12887 0
12888}
12889
12890#[no_mangle]
12892pub extern "C" fn getpagesize() -> c_int {
12893 4096
12894}
12895
12896#[no_mangle]
12897pub unsafe extern "C" fn truncate(path: *const c_char, length: i64) -> c_int {
12898 let r = sys_truncate(path as *const u8, length);
12899 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12900 0
12901}
12902
12903#[no_mangle]
12904pub unsafe extern "C" fn ftruncate(fd: c_int, length: i64) -> c_int {
12905 let r = sys_ftruncate(fd, length);
12906 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12907 0
12908}
12909
12910#[no_mangle]
12911pub unsafe extern "C" fn nanosleep(req: *const timespec, rem: *mut timespec) -> c_int {
12912 pthread_testcancel();
12913 let r = sys_nanosleep(req, rem);
12914 pthread_testcancel();
12915 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12916 0
12917}
12918
12919#[no_mangle]
12920pub unsafe extern "C" fn sleep(seconds: c_uint) -> c_uint {
12921 let req = timespec { tv_sec: seconds as c_long, tv_nsec: 0 };
12922 let mut rem: timespec = core::mem::zeroed();
12923 pthread_testcancel();
12924 let r = sys_nanosleep(&req, &mut rem);
12925 pthread_testcancel();
12926 if r < 0 {
12927 let e = (-r) as c_int;
12928 if e == EINTR { return rem.tv_sec as c_uint; }
12929 }
12930 0
12931}
12932
12933#[no_mangle]
12934pub unsafe extern "C" fn usleep(usec: c_uint) -> c_int {
12935 let req = timespec { tv_sec: (usec / 1000000) as c_long, tv_nsec: ((usec % 1000000) * 1000) as c_long };
12936 pthread_testcancel();
12937 let r = sys_nanosleep(&req, core::ptr::null_mut());
12938 pthread_testcancel();
12939 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12940 0
12941}
12942
12943#[no_mangle]
12944pub unsafe extern "C" fn alarm(seconds: c_uint) -> c_uint {
12945 let r = sys_alarm(seconds);
12948 if r < 0 { 0 } else { r as c_uint }
12949}
12950
12951#[no_mangle]
12952pub unsafe extern "C" fn pause() -> c_int {
12953 pthread_testcancel();
12954 sys_pause();
12955 pthread_testcancel();
12956 ERRNO!() = EINTR;
12957 -1
12958}
12959
12960#[no_mangle]
12961pub unsafe extern "C" fn fsync(fd: c_int) -> c_int {
12962 let r = sys_fsync(fd);
12963 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12964 0
12965}
12966
12967#[no_mangle]
12968pub unsafe extern "C" fn fdatasync(fd: c_int) -> c_int {
12969 let r = sys_fdatasync(fd);
12970 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12971 0
12972}
12973
12974#[no_mangle]
12975pub unsafe extern "C" fn sync() {
12976 sys_sync();
12977}
12978
12979#[no_mangle]
12980pub unsafe extern "C" fn symlink(target: *const c_char, linkpath: *const c_char) -> c_int {
12981 let r = sys_symlinkat(target as *const u8, AT_FDCWD, linkpath as *const u8);
12982 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12983 0
12984}
12985
12986#[no_mangle]
12987pub unsafe extern "C" fn readlink(path: *const c_char, buf: *mut c_char, bufsiz: usize) -> isize {
12988 let r = sys_readlinkat(AT_FDCWD, path as *const u8, buf as *mut u8, bufsiz);
12989 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12990 r as isize
12991}
12992
12993#[no_mangle]
12994pub unsafe extern "C" fn link(oldpath: *const c_char, newpath: *const c_char) -> c_int {
12995 let r = sys_linkat(AT_FDCWD, oldpath as *const u8, AT_FDCWD, newpath as *const u8, 0);
12996 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12997 0
12998}
12999
13000#[no_mangle]
13001pub unsafe extern "C" fn chmod(path: *const c_char, mode: c_uint) -> c_int {
13002 let r = sys_fchmodat(AT_FDCWD, path as *const u8, mode, 0);
13003 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13004 0
13005}
13006
13007#[no_mangle]
13008pub unsafe extern "C" fn fchmod(fd: c_int, mode: c_uint) -> c_int {
13009 let r = sys_fchmod(fd, mode);
13010 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13011 0
13012}
13013
13014#[no_mangle]
13015pub unsafe extern "C" fn umask(mask: c_uint) -> c_uint {
13016 sys_umask(mask) as c_uint
13017}
13018
13019#[no_mangle]
13020pub unsafe extern "C" fn isatty(fd: c_int) -> c_int {
13021 let mut ws: winsize = core::mem::zeroed();
13022 if sys_ioctl(fd, TIOCGWINSZ, &mut ws as *mut winsize as *mut u8) == 0 { 1 } else { 0 }
13023}
13024
13025#[no_mangle]
13026pub unsafe extern "C" fn getlogin() -> *mut c_char {
13027 static mut LOGIN_BUF: [c_char; 32] = [0; 32];
13028 let pw = getpwuid(crate::getuid());
13029 if pw.is_null() { return core::ptr::null_mut(); }
13030 let n = crate::strlen((*pw).pw_name);
13031 if n + 1 > LOGIN_BUF.len() { return core::ptr::null_mut(); }
13032 core::ptr::copy_nonoverlapping((*pw).pw_name, LOGIN_BUF.as_mut_ptr(), n + 1);
13033 LOGIN_BUF.as_mut_ptr()
13034}
13035
13036#[no_mangle]
13037pub unsafe extern "C" fn getgroups(size: c_int, list: *mut c_uint) -> c_int {
13038 let r = sys_getgroups(size, list);
13039 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13040 r as c_int
13041}
13042
13043#[no_mangle]
13044pub unsafe extern "C" fn setuid(uid: c_uint) -> c_int {
13045 let r = sys_setuid(uid);
13046 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13047 0
13048}
13049
13050#[no_mangle]
13051pub unsafe extern "C" fn setgid(gid: c_uint) -> c_int {
13052 let r = sys_setgid(gid);
13053 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13054 0
13055}
13056
13057#[no_mangle]
13058pub unsafe extern "C" fn seteuid(euid: c_uint) -> c_int {
13059 setresuid(u32::MAX, euid, u32::MAX)
13063}
13064
13065#[no_mangle]
13066pub unsafe extern "C" fn setegid(egid: c_uint) -> c_int {
13067 setresgid(u32::MAX, egid, u32::MAX)
13068}
13069
13070#[no_mangle]
13071pub unsafe extern "C" fn setreuid(ruid: c_uint, euid: c_uint) -> c_int {
13072 let r = <Arch as Syscalls>::syscall2(sysno(113, 145), ruid as i64, euid as i64);
13073 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
13074}
13075
13076
13077
13078#[no_mangle]
13079pub unsafe extern "C" fn setsid() -> c_int {
13080 let r = sys_setsid();
13081 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13082 r as c_int
13083}
13084
13085#[no_mangle]
13086pub unsafe extern "C" fn setpgid(pid: c_int, pgid: c_int) -> c_int {
13087 let r = sys_setpgid(pid, pgid);
13088 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13089 0
13090}
13091
13092#[no_mangle]
13093pub unsafe extern "C" fn getpgid(pid: c_int) -> c_int {
13094 let r = sys_getpgid(pid);
13095 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13096 r as c_int
13097}
13098
13099#[no_mangle]
13100pub unsafe extern "C" fn getsid(pid: c_int) -> c_int {
13101 let r = sys_getsid(pid);
13102 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13103 r as c_int
13104}
13105
13106#[no_mangle]
13107pub unsafe extern "C" fn getpgrp() -> c_int {
13108 sys_getpgid(0) as c_int
13109}
13110
13111#[no_mangle]
13112pub unsafe extern "C" fn setpgrp() -> c_int {
13113 setpgid(0, 0)
13114}
13115
13116#[no_mangle]
13117pub unsafe extern "C" fn mkstemp(template: *mut c_char) -> c_int {
13118 if template.is_null() { ERRNO!() = EINVAL; return -1; }
13119 let len = strlen(template as *const c_char);
13120 if len < 6 { ERRNO!() = EINVAL; return -1; }
13121 let x_start = len - 6;
13122 for i in x_start..len {
13124 if *template.add(i) != b'X' as c_char { ERRNO!() = EINVAL; return -1; }
13125 }
13126 let mut ts: timespec = core::mem::zeroed();
13127 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
13128 let mut ctr: u32 = ts.tv_nsec as u32;
13129 for _ in 0..100 {
13130 ctr = ctr.wrapping_mul(1103515245).wrapping_add(12345);
13131 let seed = ctr;
13132 let hex = b"0123456789abcdef";
13134 let mut s = seed;
13135 for i in x_start..len {
13136 *template.add(i) = hex[(s & 0xf) as usize] as c_char;
13137 s >>= 4;
13138 }
13139 let fd = sys_open(template as *const u8, (O_RDWR | O_CREAT | O_EXCL) as i64, 0o600);
13140 if fd >= 0 { return fd as c_int; }
13141 let e = (-fd) as c_int;
13142 if e != EEXIST_VAL { ERRNO!() = e; return -1; }
13143 }
13144 ERRNO!() = EEXIST_VAL;
13145 -1
13146}
13147
13148#[no_mangle]
13149pub unsafe extern "C" fn mkdir(path: *const c_char, mode: c_uint) -> c_int {
13150 let r = sys_mkdirat(AT_FDCWD, path as *const u8, mode);
13151 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13152 0
13153}
13154
13155#[no_mangle]
13160pub unsafe extern "C" fn dirname(s: *mut c_char) -> *mut c_char {
13161 if s.is_null() || *s == 0 {
13162 return b".\0".as_ptr() as *mut c_char;
13163 }
13164 let mut i = strlen(s as *const c_char);
13165 i = i.wrapping_sub(1);
13166 while i > 0 && *s.add(i) == b'/' as c_char {
13168 i = i.wrapping_sub(1);
13169 }
13170 if i == 0 && *s.add(0) == b'/' as c_char {
13171 return b"/\0".as_ptr() as *mut c_char;
13172 }
13173 while i > 0 && *s.add(i) != b'/' as c_char {
13175 i = i.wrapping_sub(1);
13176 }
13177 if i == 0 {
13178 if *s.add(0) == b'/' as c_char {
13179 return b"/\0".as_ptr() as *mut c_char;
13180 }
13181 return b".\0".as_ptr() as *mut c_char;
13182 }
13183 while i > 0 && *s.add(i - 1) == b'/' as c_char {
13185 i = i.wrapping_sub(1);
13186 }
13187 if i == 0 {
13188 return b"/\0".as_ptr() as *mut c_char;
13189 }
13190 *s.add(i) = 0;
13191 s
13192}
13193
13194#[no_mangle]
13195pub unsafe extern "C" fn basename(s: *mut c_char) -> *mut c_char {
13196 if s.is_null() || *s == 0 {
13197 return b".\0".as_ptr() as *mut c_char;
13198 }
13199 let mut i = strlen(s as *const c_char);
13200 i = i.wrapping_sub(1);
13201 while i > 0 && *s.add(i) == b'/' as c_char {
13203 *s.add(i) = 0;
13204 i = i.wrapping_sub(1);
13205 }
13206 while i > 0 && *s.add(i - 1) != b'/' as c_char {
13208 i = i.wrapping_sub(1);
13209 }
13210 s.add(i)
13211}
13212
13213const AF_INET_VAL: c_int = 2;
13218const AF_INET6_VAL: c_int = 10;
13219const EAFNOSUPPORT: c_int = 97;
13220const ENOSPC_VAL2: c_int = 28;
13221
13222unsafe fn inet_pton_v4(s: *const u8, a: *mut u8) -> c_int {
13223 let mut p = s;
13224 let mut i = 0;
13225 while i < 4 {
13226 let oct_start = p;
13227 let mut v: u32 = 0;
13228 let mut j: u32 = 0;
13229 while j < 3 && *p >= b'0' && *p <= b'9' {
13230 v = v * 10 + (*p - b'0') as u32;
13231 p = p.add(1);
13232 j += 1;
13233 }
13234 if j == 0 || (j > 1 && *oct_start == b'0') || v > 255 { return 0; }
13235 *a.add(i) = v as u8;
13236 if *p == 0 && i == 3 { return 1; }
13237 if *p != b'.' { return 0; }
13238 p = p.add(1);
13239 i += 1;
13240 }
13241 0
13242}
13243
13244unsafe fn inet_pton_v6(s: *const u8, a: *mut u8) -> c_int {
13245 let mut ip = [0u16; 8];
13246 let mut p = s;
13247 let mut i: usize = 0;
13248 let mut brk: isize = -1;
13249 let mut need_v4 = false;
13250 let mut v4_start: *const u8 = core::ptr::null();
13251
13252 if *p == b':' {
13253 p = p.add(1);
13254 if *p != b':' { return 0; }
13255 }
13256
13257 loop {
13258 if *p == b':' && brk < 0 {
13259 brk = i as isize;
13260 ip[i & 7] = 0;
13261 p = p.add(1);
13262 if *p == 0 { break; }
13263 if i == 7 { return 0; }
13264 i += 1;
13265 continue;
13266 }
13267 v4_start = p;
13268 let mut v: u16 = 0;
13269 let mut j = 0;
13270 while j < 4 {
13271 let d = hex_digit(*p);
13272 if d < 0 { break; }
13273 v = v * 16 + d as u16;
13274 p = p.add(1);
13275 j += 1;
13276 }
13277 if j == 0 { return 0; }
13278 ip[i & 7] = v;
13279 if *p == 0 && (brk >= 0 || i == 7) { break; }
13280 if i == 7 { return 0; }
13281 if *p != b':' {
13282 if *p != b'.' || (i < 6 && brk < 0) { return 0; }
13283 need_v4 = true;
13284 i += 1;
13285 ip[i & 7] = 0;
13286 break;
13287 }
13288 p = p.add(1);
13289 i += 1;
13290 }
13291
13292 if brk >= 0 {
13293 let trail_count = i + 1 - brk as usize;
13295 let dest_start = brk as usize + 7 - i;
13296 for j in (0..trail_count).rev() {
13298 ip[dest_start + j] = ip[brk as usize + j];
13299 }
13300 for j in 0..(7 - i) {
13301 ip[brk as usize + j] = 0;
13302 }
13303 }
13304
13305 for k in 0..8 {
13306 *a.add(k * 2) = (ip[k] >> 8) as u8;
13307 *a.add(k * 2 + 1) = (ip[k] & 0xff) as u8;
13308 }
13309
13310 if need_v4 {
13311 if inet_pton_v4(v4_start, a.add(12)) <= 0 { return 0; }
13312 }
13313 1
13314}
13315
13316unsafe fn hex_digit(c: u8) -> i32 {
13317 if c >= b'0' && c <= b'9' { (c - b'0') as i32 }
13318 else if c >= b'a' && c <= b'f' { (c - b'a' + 10) as i32 }
13319 else if c >= b'A' && c <= b'F' { (c - b'A' + 10) as i32 }
13320 else { -1 }
13321}
13322
13323#[no_mangle]
13324pub unsafe extern "C" fn inet_pton(af: c_int, s: *const c_char, a: *mut c_void) -> c_int {
13325 if af == AF_INET_VAL {
13326 inet_pton_v4(s as *const u8, a as *mut u8)
13327 } else if af == AF_INET6_VAL {
13328 inet_pton_v6(s as *const u8, a as *mut u8)
13329 } else {
13330 ERRNO!() = EAFNOSUPPORT;
13331 -1
13332 }
13333}
13334
13335#[no_mangle]
13336pub unsafe extern "C" fn inet_ntop(af: c_int, a: *const c_void, s: *mut c_char, size: u32) -> *mut c_char {
13337 if af == AF_INET_VAL {
13338 let b = a as *const u8;
13339 let needed = 16; if size < needed as u32 { ERRNO!() = ENOSPC_VAL2; return core::ptr::null_mut(); }
13341 let mut pos = 0;
13342 for i in 0..4 {
13343 if i > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
13344 let (buf, len) = format_u64(*b.add(i) as u64);
13345 for j in 0..len { *s.add(pos) = buf[j] as c_char; pos += 1; }
13346 }
13347 *s.add(pos) = 0;
13348 s
13349 } else if af == AF_INET6_VAL {
13350 let b = a as *const u8;
13351 let needed = 46; if size < needed as u32 { ERRNO!() = ENOSPC_VAL2; return core::ptr::null_mut(); }
13353 let mut words = [0u16; 8];
13354 for i in 0..8 {
13355 words[i] = ((*b.add(i * 2) as u16) << 8) | (*b.add(i * 2 + 1) as u16);
13356 }
13357 let mut pos = 0usize;
13359 if words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0
13360 && words[4] == 0 && words[5] == 0xffff
13361 {
13362 let prefix = b"::ffff:";
13363 for k in 0..prefix.len() { *s.add(pos) = prefix[k] as c_char; pos += 1; }
13364 for idx in 0..4 {
13365 if idx > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
13366 let octet = *b.add(12 + idx);
13367 if octet >= 100 {
13368 *s.add(pos) = (b'0' + octet / 100) as c_char; pos += 1;
13369 *s.add(pos) = (b'0' + (octet / 10) % 10) as c_char; pos += 1;
13370 } else if octet >= 10 {
13371 *s.add(pos) = (b'0' + octet / 10) as c_char; pos += 1;
13372 }
13373 *s.add(pos) = (b'0' + octet % 10) as c_char; pos += 1;
13374 }
13375 *s.add(pos) = 0;
13376 return s;
13377 }
13378 let mut best_start: isize = -1;
13380 let mut best_len: usize = 0;
13381 let mut j: usize = 0;
13382 while j < 8 {
13383 if words[j] == 0 {
13384 let mut k = j;
13385 while k < 8 && words[k] == 0 { k += 1; }
13386 let run = k - j;
13387 if run > best_len { best_start = j as isize; best_len = run; }
13388 j = k;
13389 } else {
13390 j += 1;
13391 }
13392 }
13393 let mut i: usize = 0;
13394 let mut prev_in_run = false;
13395 while i < 8 {
13396 let in_run = best_len >= 2 && i >= best_start as usize && i < best_start as usize + best_len;
13397 if in_run {
13398 if i == best_start as usize {
13399 *s.add(pos) = b':' as c_char; pos += 1;
13400 *s.add(pos) = b':' as c_char; pos += 1;
13401 }
13402 i += 1;
13403 prev_in_run = true;
13404 continue;
13405 }
13406 if i > 0 && !prev_in_run {
13407 *s.add(pos) = b':' as c_char; pos += 1;
13408 }
13409 let (buf, len) = format_hex(words[i] as u64, false);
13410 for k in 0..len { *s.add(pos) = buf[k] as c_char; pos += 1; }
13411 i += 1;
13412 prev_in_run = false;
13413 }
13414 *s.add(pos) = 0;
13415 s
13416 } else {
13417 ERRNO!() = EAFNOSUPPORT;
13418 core::ptr::null_mut()
13419 }
13420}
13421
13422#[no_mangle]
13423pub unsafe extern "C" fn inet_aton(s: *const c_char, dest: *mut c_void) -> c_int {
13424 let a = dest as *mut u8;
13425 let mut p = s as *const u8;
13426 let mut vals = [0u64; 4];
13427 let mut i = 0usize;
13428 while i < 4 {
13429 if *p < b'0' || *p > b'9' { return 0; }
13430 let mut base = 10u32;
13431 if *p == b'0' {
13432 let c = *p.add(1);
13433 if c == b'x' || c == b'X' {
13434 base = 16;
13435 p = p.add(2);
13436 if !((*p >= b'0' && *p <= b'9')
13437 || (*p >= b'a' && *p <= b'f')
13438 || (*p >= b'A' && *p <= b'F')) {
13439 return 0;
13440 }
13441 } else {
13442 base = 8;
13443 }
13444 }
13445 let mut v: u64 = 0;
13446 let start = p;
13447 loop {
13448 let c = *p;
13449 let d = if c >= b'0' && c <= b'9' {
13450 (c - b'0') as u64
13451 } else if base == 16 && c >= b'a' && c <= b'f' {
13452 (c - b'a' + 10) as u64
13453 } else if base == 16 && c >= b'A' && c <= b'F' {
13454 (c - b'A' + 10) as u64
13455 } else {
13456 break;
13457 };
13458 v = v * (base as u64) + d;
13459 p = p.add(1);
13460 }
13461 if p == start { return 0; }
13462 vals[i] = v;
13463 if *p == 0 {
13464 break;
13465 }
13466 if *p != b'.' || i == 3 { return 0; }
13467 p = p.add(1);
13468 i += 1;
13469 }
13470 if i == 4 { return 0; }
13471 if i < 1 { vals[1] = vals[0] & 0xffffff; vals[0] >>= 24; }
13472 if i < 2 { vals[2] = vals[1] & 0xffff; vals[1] >>= 16; }
13473 if i < 3 { vals[3] = vals[2] & 0xff; vals[2] >>= 8; }
13474 for j in 0..4 {
13475 if vals[j] > 255 { return 0; }
13476 *a.add(j) = vals[j] as u8;
13477 }
13478 1
13479}
13480
13481#[no_mangle]
13482pub unsafe extern "C" fn inet_addr(s: *const c_char) -> u32 {
13483 let mut a = [0u8; 4];
13484 if inet_aton(s, a.as_mut_ptr() as *mut c_void) == 1 {
13485 u32::from_ne_bytes(a)
13486 } else {
13487 !0u32 }
13489}
13490
13491#[no_mangle]
13492pub unsafe extern "C" fn inet_ntoa(addr: u32) -> *mut c_char {
13493 static mut NTOA_BUF: [c_char; 16] = [0; 16];
13494 let b = addr.to_ne_bytes();
13495 let mut pos = 0;
13496 for i in 0..4 {
13497 if i > 0 { NTOA_BUF[pos] = b'.' as c_char; pos += 1; }
13498 let (buf, len) = format_u64(b[i] as u64);
13499 for j in 0..len { NTOA_BUF[pos] = buf[j] as c_char; pos += 1; }
13500 }
13501 NTOA_BUF[pos] = 0;
13502 core::ptr::addr_of_mut!(NTOA_BUF).cast::<c_char>()
13503}
13504
13505#[no_mangle]
13507pub unsafe extern "C" fn inet_network(s: *const c_char) -> u32 {
13508 inet_addr(s).to_be()
13509}
13510
13511#[no_mangle]
13512pub extern "C" fn inet_makeaddr(net: c_int, host: c_int) -> u32 {
13513 let addr: u32;
13514 if (net as u32) < 128 {
13515 addr = (net as u32) << 24;
13516 } else if (net as u32) < 0x10000 {
13517 addr = (net as u32) << 16;
13518 } else if (net as u32) < 0x1000000 {
13519 addr = (net as u32) << 8;
13520 } else {
13521 addr = net as u32;
13522 }
13523 addr | (host as u32 & 0xffffffff)
13524}
13525
13526#[no_mangle]
13527pub extern "C" fn inet_lnaof(addr: u32) -> c_int {
13528 let h = u32::from_be(addr);
13529 if h < 0x80000000 { (h & 0x00ffffff) as c_int }
13530 else if h < 0xc0000000 { (h & 0x0000ffff) as c_int }
13531 else { (h & 0x000000ff) as c_int }
13532}
13533
13534#[no_mangle]
13535pub extern "C" fn inet_netof(addr: u32) -> c_int {
13536 let h = u32::from_be(addr);
13537 if h < 0x80000000 { (h >> 24) as c_int }
13538 else if h < 0xc0000000 { (h >> 16) as c_int }
13539 else { (h >> 8) as c_int }
13540}
13541
13542unsafe fn parse_float(s: *const u8, endptr: *mut *mut u8, is_f32: bool) -> f64 {
13551 let mut p = s;
13552 while *p == b' ' || *p == b'\t' || *p == b'\n' || *p == b'\r' { p = p.add(1); }
13554 let mut neg = false;
13555 if *p == b'-' { neg = true; p = p.add(1); }
13556 else if *p == b'+' { p = p.add(1); }
13557
13558 if (*p | 0x20) == b'i'
13560 && (*p.add(1) | 0x20) == b'n'
13561 && (*p.add(2) | 0x20) == b'f'
13562 {
13563 p = p.add(3);
13564 if (*p | 0x20) == b'i'
13566 && (*p.add(1) | 0x20) == b't'
13567 && (*p.add(2) | 0x20) == b'y'
13568 {
13569 p = p.add(3);
13570 }
13571 if !endptr.is_null() { *endptr = p as *mut u8; }
13572 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13573 }
13574 if (*p | 0x20) == b'n'
13576 && (*p.add(1) | 0x20) == b'a'
13577 && (*p.add(2) | 0x20) == b'n'
13578 {
13579 p = p.add(3);
13580 if *p == b'(' {
13582 p = p.add(1);
13583 while *p != 0 && *p != b')' { p = p.add(1); }
13584 if *p == b')' { p = p.add(1); }
13585 }
13586 if !endptr.is_null() { *endptr = p as *mut u8; }
13587 return if neg { -f64::NAN } else { f64::NAN };
13588 }
13589
13590 if *p == b'0' && (*p.add(1) == b'x' || *p.add(1) == b'X') {
13592 p = p.add(2);
13593 let mut mant: u128 = 0;
13594 let mut frac_hex: u32 = 0;
13595 let mut found = false;
13596 let mut in_frac = false;
13597
13598 loop {
13599 if let Some(d) = hex_val(*p) {
13600 if mant <= u128::MAX / 16 {
13601 mant = mant * 16 + d as u128;
13602 }
13603 if in_frac { frac_hex += 1; }
13604 p = p.add(1);
13605 found = true;
13606 } else if *p == b'.' && !in_frac {
13607 in_frac = true;
13608 p = p.add(1);
13609 } else {
13610 break;
13611 }
13612 }
13613
13614 if !found {
13615 if !endptr.is_null() { *endptr = s as *mut u8; }
13616 return 0.0;
13617 }
13618
13619 let mut bin_exp: i32 = 0;
13621 if *p == b'p' || *p == b'P' {
13622 p = p.add(1);
13623 let mut exp_neg = false;
13624 if *p == b'-' { exp_neg = true; p = p.add(1); }
13625 else if *p == b'+' { p = p.add(1); }
13626 while *p >= b'0' && *p <= b'9' {
13627 if bin_exp < 100000 {
13628 bin_exp = bin_exp * 10 + (*p - b'0') as i32;
13629 }
13630 p = p.add(1);
13631 }
13632 if exp_neg { bin_exp = -bin_exp; }
13633 }
13634
13635 if !endptr.is_null() { *endptr = p as *mut u8; }
13636 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
13637
13638 let total_exp = bin_exp as i64 - 4 * frac_hex as i64;
13639 return hex_mant_to_f64(mant, total_exp, neg);
13640 }
13641
13642 let mut buf = [0u8; 65536];
13644 let mut n = 0usize;
13645 let mut found_digit = false;
13646
13647 while *p >= b'0' && *p <= b'9' {
13648 if n < 65535 { buf[n] = *p; n += 1; }
13649 p = p.add(1);
13650 found_digit = true;
13651 }
13652 if *p == b'.' {
13653 if n < 65535 { buf[n] = b'.'; n += 1; }
13654 p = p.add(1);
13655 while *p >= b'0' && *p <= b'9' {
13656 if n < 65535 { buf[n] = *p; n += 1; }
13657 p = p.add(1);
13658 found_digit = true;
13659 }
13660 }
13661 if !found_digit {
13662 if !endptr.is_null() { *endptr = s as *mut u8; }
13663 return 0.0;
13664 }
13665 if *p == b'e' || *p == b'E' {
13666 if n < 65535 { buf[n] = b'e'; n += 1; }
13667 p = p.add(1);
13668 if *p == b'-' || *p == b'+' {
13669 if n < 65535 { buf[n] = *p; n += 1; }
13670 p = p.add(1);
13671 }
13672 while *p >= b'0' && *p <= b'9' {
13673 if n < 65535 { buf[n] = *p; n += 1; }
13674 p = p.add(1);
13675 }
13676 }
13677
13678 if !endptr.is_null() { *endptr = p as *mut u8; }
13679 let s_str = core::str::from_utf8_unchecked(
13680 core::slice::from_raw_parts(buf.as_ptr(), n),
13681 );
13682 if is_f32 {
13683 match <f32 as core::str::FromStr>::from_str(s_str) {
13684 Ok(v) => { let r = v as f64; if neg { -r } else { r } }
13685 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13686 }
13687 } else {
13688 match <f64 as core::str::FromStr>::from_str(s_str) {
13689 Ok(v) => if neg { -v } else { v },
13690 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13691 }
13692 }
13693}
13694
13695fn hex_mant_to_f64(mant: u128, total_exp: i64, neg: bool) -> f64 {
13699 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
13700
13701 let msb = (127 - mant.leading_zeros()) as i64;
13702 let unbiased_exp = msb + total_exp;
13703 let biased_exp = unbiased_exp + 1023;
13704
13705 if biased_exp >= 2047 {
13707 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13708 }
13709
13710 if biased_exp <= 0 {
13712 let shift = total_exp + 1074;
13715 if shift < 0 {
13716 return if neg { -0.0 } else { 0.0 };
13717 }
13718 if shift > 128 {
13719 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13720 }
13721 let shifted = mant << (shift as u32);
13722 let mantissa52 = (shifted as u64) & 0x000FFFFFFFFFFFFF;
13723 let guard = ((shifted >> 52) & 1) != 0;
13724 let sticky = (shifted >> 53) != 0;
13725 let mut result = mantissa52;
13726 if guard && (sticky || (result & 1) != 0) {
13727 result += 1;
13728 if result > 0x000FFFFFFFFFFFFF {
13729 return if neg { -f64::from_bits(1u64 << 52) } else { f64::from_bits(1u64 << 52) };
13731 }
13732 }
13733 return if neg { -f64::from_bits(result) } else { f64::from_bits(result) };
13734 }
13735
13736 let shift = msb - 52;
13738
13739 if shift <= 0 {
13740 let mantissa = ((mant as u64) & ((1u64 << msb as u32) - 1)) << ((-shift) as u32);
13742 let bits = ((biased_exp as u64) << 52) | mantissa;
13743 return if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) };
13744 }
13745
13746 let mantissa = ((mant >> shift as u32) as u64) & 0x000FFFFFFFFFFFFF;
13748 let guard = ((mant >> (shift as u32 - 1)) & 1) != 0;
13749 let sticky = if shift > 1 {
13750 (mant & ((1u128 << (shift as u32 - 1)) - 1)) != 0
13751 } else { false };
13752
13753 let mut result_mant = mantissa;
13754 let mut result_exp = biased_exp;
13755 if guard && (sticky || (result_mant & 1) != 0) {
13756 result_mant += 1;
13757 if result_mant > 0x000FFFFFFFFFFFFF {
13758 result_mant = 0;
13759 result_exp += 1;
13760 if result_exp >= 2047 {
13761 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13762 }
13763 }
13764 }
13765
13766 let bits = ((result_exp as u64) << 52) | result_mant;
13767 if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) }
13768}
13769
13770unsafe fn hex_val(c: u8) -> Option<u8> {
13771 if c >= b'0' && c <= b'9' { Some(c - b'0') }
13772 else if c >= b'a' && c <= b'f' { Some(c - b'a' + 10) }
13773 else if c >= b'A' && c <= b'F' { Some(c - b'A' + 10) }
13774 else { None }
13775}
13776
13777#[no_mangle]
13778pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13779 let mut end: *mut u8 = s as *mut u8;
13780 let r = parse_float(s as *const u8, &mut end, false);
13781 if !endptr.is_null() { *endptr = end as *mut c_char; }
13782 r
13783}
13784
13785#[no_mangle]
13786pub unsafe extern "C" fn strtof(s: *const c_char, endptr: *mut *mut c_char) -> f32 {
13787 let mut end: *mut u8 = s as *mut u8;
13788 let r = parse_float(s as *const u8, &mut end, true);
13789 if !endptr.is_null() { *endptr = end as *mut c_char; }
13790 r as f32
13791}
13792
13793#[no_mangle]
13794#[cfg(target_arch = "x86_64")]
13795pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13796 strtod(s, endptr)
13797}
13798
13799#[no_mangle]
13800#[cfg(target_arch = "aarch64")]
13801pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13802 strtod(s, endptr) as f128
13803}
13804
13805#[no_mangle]
13806#[cfg(target_arch = "riscv64")]
13807pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13808 strtod(s, endptr) as f128
13809}
13810
13811#[no_mangle]
13812pub unsafe extern "C" fn atof(s: *const c_char) -> f64 {
13813 strtod(s, core::ptr::null_mut())
13814}
13815
13816#[repr(C)]
13821struct MsCookie {
13822 bufp: *mut *mut c_char,
13823 sizep: *mut usize,
13824 pos: usize,
13825 len: usize,
13826 buf: *mut u8,
13827 space: usize,
13828}
13829
13830#[repr(C)]
13831struct MfCookie {
13832 pos: usize,
13833 len: usize,
13834 size: usize,
13835 buf: *mut u8,
13836 mode: c_char,
13837}
13838
13839unsafe extern "C" fn ms_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13840 let c = (*f).cookie as *mut MsCookie;
13841 if whence < 0 || whence > 2 { ERRNO!() = EINVAL; return -1; }
13842 let base: i64 = match whence {
13843 0 => 0,
13844 1 => (*c).pos as i64,
13845 2 => (*c).len as i64,
13846 _ => { ERRNO!() = EINVAL; return -1; }
13847 };
13848 if off < -base || off > isize::MAX as i64 - base { ERRNO!() = EINVAL; return -1; }
13849 (*c).pos = (base + off) as usize;
13850 (*c).pos as i64
13851}
13852
13853unsafe extern "C" fn ms_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13854 let c = (*f).cookie as *mut MsCookie;
13855 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13856 if buffered > 0 {
13857 (*f).wpos = (*f).wbase;
13858 if ms_write(f, (*f).wbase, buffered) < buffered { return 0; }
13859 }
13860 if len == 0 { return 0; }
13861 if (*c).pos + len >= (*c).space {
13862 let new_space = 2 * (*c).space + 1 | (*c).pos + len + 1;
13863 let newbuf = realloc((*c).buf as *mut c_void, new_space) as *mut u8;
13864 if newbuf.is_null() { return 0; }
13865 *(*c).bufp = newbuf as *mut c_char;
13866 core::ptr::write_bytes(newbuf.add((*c).space), 0, new_space - (*c).space);
13867 (*c).buf = newbuf;
13868 (*c).space = new_space;
13869 }
13870 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), len);
13871 (*c).pos += len;
13872 if (*c).pos >= (*c).len { (*c).len = (*c).pos; }
13873 *(*c).sizep = (*c).pos;
13874 len
13875}
13876
13877unsafe extern "C" fn ms_close(_f: *mut FILE) -> c_int {
13878 0
13879}
13880
13881#[no_mangle]
13882pub unsafe extern "C" fn open_memstream(bufp: *mut *mut c_char, sizep: *mut usize) -> *mut FILE {
13883 if bufp.is_null() || sizep.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
13884 let f = calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
13885 if f.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13886 let buf_area = buf_ptr(f);
13887 init_file(f, -1, b"w\0".as_ptr() as *const c_char, Some(ms_close), buf_area, BUFSIZ);
13888 (*f).flags = F_NORD | F_SVB;
13889 (*f).lbf = -1;
13890 let c = calloc(1, core::mem::size_of::<MsCookie>()) as *mut MsCookie;
13891 if c.is_null() { free(f as *mut c_void); ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13892 (*c).bufp = bufp;
13893 (*c).sizep = sizep;
13894 (*c).pos = 0;
13895 (*c).len = 0;
13896 (*c).buf = core::ptr::null_mut();
13897 (*c).space = 0;
13898 (*f).cookie = c as *mut c_void;
13899 (*f).write_fn = Some(ms_write);
13900 (*f).seek_fn = Some(ms_seek);
13901 *bufp = core::ptr::null_mut();
13902 *sizep = 0;
13903 f
13904}
13905
13906unsafe extern "C" fn mseek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13907 let c = (*f).cookie as *mut MfCookie;
13908 if whence < 0 || whence > 2 { ERRNO!() = EINVAL; return -1; }
13909 let base: i64 = match whence {
13910 0 => 0,
13911 1 => (*c).pos as i64,
13912 2 => (*c).len as i64,
13913 _ => { ERRNO!() = EINVAL; return -1; }
13914 };
13915 if off < -base || off > (*c).size as i64 - base { ERRNO!() = EINVAL; return -1; }
13916 (*c).pos = (base + off) as usize;
13917 (*c).pos as i64
13918}
13919
13920unsafe extern "C" fn mread(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
13921 let c = (*f).cookie as *mut MfCookie;
13922 let mut rem = if (*c).pos <= (*c).len { (*c).len - (*c).pos } else { 0 };
13923 let mut l = len;
13924 if l > rem {
13925 l = rem;
13926 (*f).flags |= F_EOF;
13927 }
13928 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), buf, l);
13929 (*c).pos += l;
13930 rem -= l;
13931 if rem > (*f).buf_size { rem = (*f).buf_size; }
13932 (*f).rpos = (*f).buf;
13933 (*f).rend = (*f).buf.add(rem);
13934 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), (*f).rpos, rem);
13935 (*c).pos += rem;
13936 l
13937}
13938
13939unsafe extern "C" fn mwrite(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13940 let c = (*f).cookie as *mut MfCookie;
13941 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13942 if buffered > 0 {
13943 (*f).wpos = (*f).wbase;
13944 if mwrite(f, (*f).wbase, buffered) < buffered { return 0; }
13945 }
13946 if len == 0 { return 0; }
13947 if (*c).mode == b'a' as c_char { (*c).pos = (*c).len; }
13948 let rem = (*c).size - (*c).pos;
13949 let mut l = len;
13950 if l > rem { l = rem; }
13951 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), l);
13952 (*c).pos += l;
13953 if (*c).pos > (*c).len {
13954 (*c).len = (*c).pos;
13955 if (*c).len < (*c).size {
13956 *(*c).buf.add((*c).len) = 0;
13957 } else if ((*f).flags & F_NORD) != 0 && (*c).size > 0 {
13958 *(*c).buf.add((*c).size - 1) = 0;
13959 }
13960 }
13961 l
13962}
13963
13964unsafe extern "C" fn mclose(_f: *mut FILE) -> c_int {
13965 0
13966}
13967
13968#[no_mangle]
13969pub unsafe extern "C" fn fmemopen(buf: *mut c_void, size: usize, mode: *const c_char) -> *mut FILE {
13970 if mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
13971 let m = *mode;
13972 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
13973 ERRNO!() = EINVAL; return core::ptr::null_mut();
13974 }
13975 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
13976 let need_alloc = buf.is_null();
13977 let alloc_size = core::mem::size_of::<FILE>() + UNGET + BUFSIZ + if need_alloc { size } else { 0 };
13978 let f = calloc(1, alloc_size) as *mut FILE;
13979 if f.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13980 let buf_area = buf_ptr(f);
13981 init_file(f, -1, mode, Some(mclose), buf_area, BUFSIZ);
13982 (*f).flags |= F_SVB;
13983 let actual_buf: *mut u8 = if need_alloc {
13984 (f as *mut u8).add(alloc_size - size)
13985 } else {
13986 buf as *mut u8
13987 };
13988 if need_alloc { core::ptr::write_bytes(actual_buf, 0, size); }
13989 let c = calloc(1, core::mem::size_of::<MfCookie>()) as *mut MfCookie;
13990 if c.is_null() { free(f as *mut c_void); ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13991 (*c).buf = actual_buf;
13992 (*c).size = size;
13993 (*c).mode = m;
13994 (*f).cookie = c as *mut c_void;
13995 (*f).read_fn = Some(mread);
13996 (*f).write_fn = Some(mwrite);
13997 (*f).seek_fn = Some(mseek);
13998 if !has_plus { (*f).flags = if m == b'r' as c_char { F_NOWR } else { F_NORD }; }
13999 if m == b'r' as c_char {
14000 (*c).len = size;
14001 } else if m == b'a' as c_char {
14002 (*c).len = strnlen(actual_buf, size);
14003 (*c).pos = (*c).len;
14004 } else if has_plus {
14005 *actual_buf = 0;
14006 }
14007 f
14008}
14009
14010#[repr(C)]
14015struct kernel_stat64 {
14016 st_dev: u64,
14017 st_ino: u64,
14018 st_nlink: u64,
14019 st_mode: u32,
14020 st_uid: u32,
14021 st_gid: u32,
14022 __pad0: c_int,
14023 st_rdev: u64,
14024 st_size: i64,
14025 st_blksize: i64,
14026 st_blocks: i64,
14027 st_atime: i64,
14028 st_atime_nsec: i64,
14029 st_mtime: i64,
14030 st_mtime_nsec: i64,
14031 st_ctime: i64,
14032 st_ctime_nsec: i64,
14033 __unused: [i64; 3],
14034}
14035
14036#[inline]
14038unsafe fn sys_stat(path: *const u8, statbuf: *mut kernel_stat64) -> i64 {
14039 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, AT_FDCWD as i64, path as i64, statbuf as i64, 0)
14040}
14041
14042const HSEARCH_MINSIZE: usize = 8;
14047
14048#[repr(C)]
14049#[derive(Copy, Clone)]
14050pub struct HSearchEntry {
14051 key: *mut c_char,
14052 data: *mut c_void,
14053}
14054
14055#[repr(C)]
14056struct HTab {
14057 entries: *mut HSearchEntry,
14058 mask: usize,
14059 used: usize,
14060}
14061
14062#[repr(C)]
14063pub struct HSearchData {
14064 tab: *mut HTab,
14065 __unused1: c_uint,
14066 __unused2: c_uint,
14067}
14068
14069static mut HTAB_DATA: HSearchData = HSearchData {
14071 tab: core::ptr::null_mut(),
14072 __unused1: 0,
14073 __unused2: 0,
14074};
14075
14076unsafe fn keyhash(k: *const c_char) -> usize {
14077 let mut h: usize = 0;
14078 let mut p = k;
14079 while *p != 0 {
14080 h = h.wrapping_mul(31).wrapping_add(*p as usize);
14081 p = p.add(1);
14082 }
14083 h
14084}
14085
14086unsafe fn htab_lookup(key: *const c_char, hash: usize, htab: *mut HSearchData) -> *mut HSearchEntry {
14087 let tab = (*htab).tab;
14088 let mask = (*tab).mask;
14089 let entries = (*tab).entries;
14090 let mut i = hash;
14091 let mut j: usize = 1;
14092 loop {
14093 let e = entries.add(i & mask);
14094 if (*e).key.is_null() || strcmp((*e).key as *const u8, key as *const u8) == 0 {
14095 return e;
14096 }
14097 i = i.wrapping_add(j);
14098 j += 1;
14099 }
14100}
14101
14102unsafe fn htab_resize(nel: usize, htab: *mut HSearchData) -> c_int {
14103 let tab = (*htab).tab;
14104 let old_entries = (*tab).entries;
14105 let old_size = (*tab).mask + 1;
14106
14107 let mut newsize: usize = HSEARCH_MINSIZE;
14108 while newsize < nel {
14109 let Some(next) = newsize.checked_mul(2) else {
14110 ERRNO!() = ENOMEM;
14111 return 0;
14112 };
14113 newsize = next;
14114 }
14115
14116 let new_entries = calloc(newsize, core::mem::size_of::<HSearchEntry>()) as *mut HSearchEntry;
14117 if new_entries.is_null() {
14118 ERRNO!() = ENOMEM;
14119 return 0;
14120 }
14121 (*tab).entries = new_entries;
14122 (*tab).mask = newsize - 1;
14123
14124 if !old_entries.is_null() {
14125 for idx in 0..old_size {
14126 let old_e = old_entries.add(idx);
14127 if !(*old_e).key.is_null() {
14128 let h = keyhash((*old_e).key);
14129 let mut i = h;
14130 let mut j: usize = 1;
14131 loop {
14132 let e = new_entries.add(i & (*tab).mask);
14133 if (*e).key.is_null() {
14134 *e = *old_e;
14135 break;
14136 }
14137 i = i.wrapping_add(j);
14138 j += 1;
14139 }
14140 }
14141 }
14142 free(old_entries as *mut c_void);
14143 }
14144 1
14145}
14146
14147unsafe fn hcreate_r_impl(nel: usize, htab: *mut HSearchData) -> c_int {
14148 if nel == 0 || nel > (1usize << 30) {
14149 ERRNO!() = ENOMEM;
14150 return 0;
14151 }
14152 (*htab).tab = calloc(1, core::mem::size_of::<HTab>()) as *mut HTab;
14153 if (*htab).tab.is_null() {
14154 ERRNO!() = ENOMEM;
14155 return 0;
14156 }
14157 if htab_resize(nel, htab) == 0 {
14158 free((*htab).tab as *mut c_void);
14159 (*htab).tab = core::ptr::null_mut();
14160 return 0;
14161 }
14162 1
14163}
14164
14165unsafe fn hdestroy_r_impl(htab: *mut HSearchData) {
14166 if !(*htab).tab.is_null() {
14167 if !(*(*htab).tab).entries.is_null() {
14168 free((*(*htab).tab).entries as *mut c_void);
14169 }
14170 free((*htab).tab as *mut c_void);
14171 (*htab).tab = core::ptr::null_mut();
14172 }
14173}
14174
14175unsafe fn hsearch_r_impl(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
14176 let hash = keyhash(item.key);
14177 let e = htab_lookup(item.key, hash, htab);
14178
14179 if !(*e).key.is_null() {
14180 *retval = e;
14181 return 1;
14182 }
14183 if action == 0 { *retval = core::ptr::null_mut();
14185 return 0;
14186 }
14187 let item_key = item.key;
14189 *e = item;
14190 (*(*htab).tab).used += 1;
14191 if (*(*htab).tab).used > (*(*htab).tab).mask - (*(*htab).tab).mask / 4 {
14192 if htab_resize(2 * (*(*htab).tab).used, htab) == 0 {
14193 (*(*htab).tab).used -= 1;
14194 (*e).key = core::ptr::null_mut();
14195 *retval = core::ptr::null_mut();
14196 return 0;
14197 }
14198 let e2 = htab_lookup(item_key, hash, htab);
14199 *retval = e2;
14200 return 1;
14201 }
14202 *retval = e;
14203 1
14204}
14205
14206#[no_mangle]
14207pub unsafe extern "C" fn hcreate(nel: usize) -> c_int {
14208 hcreate_r_impl(nel, core::ptr::addr_of_mut!(HTAB_DATA))
14209}
14210
14211#[no_mangle]
14212pub unsafe extern "C" fn hdestroy() {
14213 hdestroy_r_impl(core::ptr::addr_of_mut!(HTAB_DATA));
14214}
14215
14216#[no_mangle]
14217pub unsafe extern "C" fn hsearch(item: HSearchEntry, action: c_int) -> *mut HSearchEntry {
14218 let mut e: *mut HSearchEntry = core::ptr::null_mut();
14219 hsearch_r_impl(item, action, &mut e, core::ptr::addr_of_mut!(HTAB_DATA));
14220 e
14221}
14222
14223#[no_mangle]
14224pub unsafe extern "C" fn hcreate_r(nel: usize, htab: *mut HSearchData) -> c_int {
14225 hcreate_r_impl(nel, htab)
14226}
14227
14228#[no_mangle]
14229pub unsafe extern "C" fn hdestroy_r(htab: *mut HSearchData) {
14230 hdestroy_r_impl(htab);
14231}
14232
14233#[no_mangle]
14234pub unsafe extern "C" fn hsearch_r(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
14235 hsearch_r_impl(item, action, retval, htab)
14236}
14237
14238#[repr(C)]
14243struct QueNode {
14244 next: *mut QueNode,
14245 prev: *mut QueNode,
14246}
14247
14248#[no_mangle]
14249pub unsafe extern "C" fn insque(element: *mut c_void, pred: *mut c_void) {
14250 let e = element as *mut QueNode;
14251 let p = pred as *mut QueNode;
14252 if p.is_null() {
14253 (*e).next = core::ptr::null_mut();
14254 (*e).prev = core::ptr::null_mut();
14255 return;
14256 }
14257 (*e).next = (*p).next;
14258 (*e).prev = p;
14259 (*p).next = e;
14260 if !(*e).next.is_null() {
14261 (*(*e).next).prev = e;
14262 }
14263}
14264
14265#[no_mangle]
14266pub unsafe extern "C" fn remque(element: *mut c_void) {
14267 let e = element as *mut QueNode;
14268 if !(*e).next.is_null() {
14269 (*(*e).next).prev = (*e).prev;
14270 }
14271 if !(*e).prev.is_null() {
14272 (*(*e).prev).next = (*e).next;
14273 }
14274}
14275
14276#[no_mangle]
14281pub unsafe extern "C" fn lsearch(
14282 key: *const c_void,
14283 base: *mut c_void,
14284 nelp: *mut usize,
14285 width: usize,
14286 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
14287) -> *mut c_void {
14288 let n = *nelp;
14289 let p = base as *mut u8;
14290 for i in 0..n {
14291 let elem = p.add(i * width);
14292 if compar.unwrap()(key, elem as *const c_void) == 0 {
14293 return elem as *mut c_void;
14294 }
14295 }
14296 let dest = p.add(n * width);
14297 memcpy(dest as *mut c_void, key as *const c_void, width);
14298 *nelp = n + 1;
14299 dest as *mut c_void
14300}
14301
14302#[no_mangle]
14303pub unsafe extern "C" fn lfind(
14304 key: *const c_void,
14305 base: *const c_void,
14306 nelp: *mut usize,
14307 width: usize,
14308 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
14309) -> *mut c_void {
14310 let n = *nelp;
14311 let p = base as *const u8;
14312 for i in 0..n {
14313 let elem = p.add(i * width);
14314 if compar.unwrap()(key, elem as *const c_void) == 0 {
14315 return elem as *mut c_void;
14316 }
14317 }
14318 core::ptr::null_mut()
14319}
14320
14321#[repr(C)]
14327pub struct TreeNode {
14328 key: *const c_void,
14329 left: *mut TreeNode,
14330 right: *mut TreeNode,
14331}
14332
14333type ComparFn = Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>;
14334
14335unsafe fn bst_new(key: *const c_void) -> *mut TreeNode {
14336 let n = calloc(1, core::mem::size_of::<TreeNode>()) as *mut TreeNode;
14337 if !n.is_null() {
14338 (*n).key = key;
14339 (*n).left = core::ptr::null_mut();
14340 (*n).right = core::ptr::null_mut();
14341 }
14342 n
14343}
14344
14345#[no_mangle]
14346pub unsafe extern "C" fn tsearch(
14347 key: *const c_void,
14348 rootp: *mut *mut TreeNode,
14349 compar: ComparFn,
14350) -> *mut c_void {
14351 if rootp.is_null() {
14352 return core::ptr::null_mut();
14353 }
14354 let mut pp = rootp;
14355 loop {
14356 let n = *pp;
14357 if n.is_null() {
14358 let r = bst_new(key);
14359 if r.is_null() {
14360 return core::ptr::null_mut();
14361 }
14362 *pp = r;
14363 return r as *mut c_void;
14364 }
14365 let c = compar.unwrap()(key, (*n).key);
14366 if c == 0 {
14367 return n as *mut c_void;
14368 }
14369 if c < 0 {
14370 pp = &mut (*n).left;
14371 } else {
14372 pp = &mut (*n).right;
14373 }
14374 }
14375}
14376
14377#[no_mangle]
14378pub unsafe extern "C" fn tfind(
14379 key: *const c_void,
14380 rootp: *const *mut TreeNode,
14381 compar: ComparFn,
14382) -> *mut c_void {
14383 if rootp.is_null() {
14384 return core::ptr::null_mut();
14385 }
14386 let mut n = *rootp;
14387 loop {
14388 if n.is_null() {
14389 return core::ptr::null_mut();
14390 }
14391 let c = compar.unwrap()(key, (*n).key);
14392 if c == 0 {
14393 return n as *mut c_void;
14394 }
14395 if c < 0 {
14396 n = (*n).left;
14397 } else {
14398 n = (*n).right;
14399 }
14400 }
14401}
14402
14403#[no_mangle]
14404pub unsafe extern "C" fn tdelete(
14405 key: *const c_void,
14406 rootp: *mut *mut TreeNode,
14407 compar: ComparFn,
14408) -> *mut c_void {
14409 if rootp.is_null() {
14410 return core::ptr::null_mut();
14411 }
14412 let mut pp = rootp;
14413 loop {
14414 let n = *pp;
14415 if n.is_null() {
14416 return core::ptr::null_mut();
14417 }
14418 let c = compar.unwrap()(key, (*n).key);
14419 if c == 0 {
14420 break;
14421 }
14422 if c < 0 {
14423 pp = &mut (*n).left;
14424 } else {
14425 pp = &mut (*n).right;
14426 }
14427 }
14428 let n = *pp;
14429 let parent = *rootp;
14431 if !(*n).left.is_null() {
14432 let mut q = &mut (*n).left;
14434 while !(*(*q)).right.is_null() {
14435 q = &mut (*(*q)).right;
14436 }
14437 let pred = *q;
14438 (*n).key = (*pred).key;
14440 *q = (*pred).left;
14442 free(pred as *mut c_void);
14443 } else {
14444 *pp = (*n).right;
14446 free(n as *mut c_void);
14447 }
14448 parent as *mut c_void
14449}
14450
14451#[no_mangle]
14452pub unsafe extern "C" fn twalk(
14453 root: *const TreeNode,
14454 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
14455) {
14456 unsafe fn walk(
14457 node: *const TreeNode,
14458 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
14459 depth: c_int,
14460 ) {
14461 if node.is_null() {
14462 return;
14463 }
14464 let is_leaf = (*node).left.is_null() && (*node).right.is_null();
14465 if is_leaf {
14466 action.unwrap()(node as *const c_void, 3, depth); } else {
14468 action.unwrap()(node as *const c_void, 0, depth); walk((*node).left, action, depth + 1);
14470 action.unwrap()(node as *const c_void, 1, depth); walk((*node).right, action, depth + 1);
14472 action.unwrap()(node as *const c_void, 2, depth); }
14474 }
14475 walk(root, action, 0);
14476}
14477
14478#[no_mangle]
14479pub unsafe extern "C" fn tdestroy(root: *mut TreeNode, freekey: Option<unsafe extern "C" fn(*mut c_void)>) {
14480 if root.is_null() {
14481 return;
14482 }
14483 tdestroy((*root).left, freekey);
14484 tdestroy((*root).right, freekey);
14485 if let Some(f) = freekey {
14486 f((*root).key as *mut c_void);
14487 }
14488 free(root as *mut c_void);
14489}
14490
14491const FNM_PATHNAME: c_int = 0x1;
14496const FNM_NOESCAPE: c_int = 0x2;
14497const FNM_PERIOD: c_int = 0x4;
14498const FNM_LEADING_DIR: c_int = 0x8;
14499const FNM_CASEFOLD: c_int = 0x10;
14500const FNM_NOMATCH: c_int = 1;
14501
14502const FNM_END: c_int = 0;
14503const FNM_STAR: c_int = -5;
14504const FNM_QUESTION: c_int = -4;
14505const FNM_BRACKET: c_int = -3;
14506const FNM_UNMATCHABLE: c_int = -2;
14507
14508fn ascii_tolower(c: u8) -> u8 {
14509 if c >= b'A' && c <= b'Z' { c + 32 } else { c }
14510}
14511
14512fn ascii_toupper(c: u8) -> u8 {
14513 if c >= b'a' && c <= b'z' { c - 32 } else { c }
14514}
14515
14516fn ascii_casefold(k: u8) -> u8 {
14517 let upper = ascii_toupper(k);
14518 if upper != k { upper } else { ascii_tolower(k) }
14519}
14520
14521unsafe fn pat_next(pat: *const u8, m: usize, flags: c_int) -> (c_int, usize) {
14524 if m == 0 || *pat == 0 {
14525 return (FNM_END, 0);
14526 }
14527 let mut p = pat;
14528 let mut step = 1usize;
14529 let mut esc = false;
14530 if *p == b'\\' && !(flags & FNM_NOESCAPE != 0) && *p.add(1) != 0 {
14531 p = p.add(1);
14532 step = 2;
14533 esc = true;
14534 }
14535 if *p == b'[' && !esc {
14536 let mut k = 1usize;
14538 if k < m && (*pat.add(k) == b'^' || *pat.add(k) == b'!') { k += 1; }
14539 if k < m && *pat.add(k) == b']' { k += 1; }
14540 while k < m && *pat.add(k) != 0 && *pat.add(k) != b']' {
14541 if k + 1 < m && *pat.add(k) == b'[' &&
14542 (*pat.add(k+1) == b':' || *pat.add(k+1) == b'.' || *pat.add(k+1) == b'=') {
14543 let z = *pat.add(k+1);
14544 k += 2;
14545 if k < m { k += 1; }
14546 while k < m && *pat.add(k) != 0 && (*pat.add(k-1) != z || *pat.add(k) != b']') { k += 1; }
14547 if k == m || *pat.add(k) == 0 { break; }
14548 }
14549 k += 1;
14550 }
14551 if k == m || *pat.add(k) == 0 {
14552 return (b'[' as c_int, 1);
14554 }
14555 return (FNM_BRACKET, k + 1);
14556 }
14557 if *p == b'*' && !esc {
14558 return (FNM_STAR, 1);
14559 }
14560 if *p == b'?' && !esc {
14561 return (FNM_QUESTION, 1);
14562 }
14563 (*p as c_int, step)
14564}
14565
14566unsafe fn match_class(name: &[u8], k: u8, kfold: u8) -> bool {
14567 let eq = |c: u8| k == c || kfold == c;
14568 let in_range = |lo: u8, hi: u8| (k >= lo && k <= hi) || (kfold >= lo && kfold <= hi);
14569 match name {
14570 b"alnum" => in_range(b'0', b'9') || in_range(b'A', b'Z') || in_range(b'a', b'z'),
14571 b"alpha" => in_range(b'A', b'Z') || in_range(b'a', b'z'),
14572 b"blank" => eq(b' ') || eq(b'\t'),
14573 b"cntrl" => k < 0x20 || k == 0x7f,
14574 b"digit" => in_range(b'0', b'9'),
14575 b"graph" => k >= 0x21 && k <= 0x7e,
14576 b"lower" => in_range(b'a', b'z'),
14577 b"print" => k >= 0x20 && k <= 0x7e,
14578 b"punct" =>
14579 (k >= 0x21 && k <= 0x2f) ||
14580 (k >= 0x3a && k <= 0x40) ||
14581 (k >= 0x5b && k <= 0x60) ||
14582 (k >= 0x7b && k <= 0x7e),
14583 b"space" => eq(b' ') || eq(b'\t') || eq(b'\n') || eq(b'\r') || eq(0x0c) || eq(0x0b),
14584 b"upper" => in_range(b'A', b'Z'),
14585 b"xdigit" => in_range(b'0', b'9') || in_range(b'A', b'F') || in_range(b'a', b'f'),
14586 _ => false,
14587 }
14588}
14589
14590unsafe fn match_bracket(mut p: *const u8, k: u8, kfold: u8) -> bool {
14592 let mut inv = false;
14593 p = p.add(1); if *p == b'^' || *p == b'!' {
14595 inv = true;
14596 p = p.add(1);
14597 }
14598 if *p == b']' {
14600 if k == b']' { return !inv; }
14601 p = p.add(1);
14602 } else if *p == b'-' {
14603 if k == b'-' { return !inv; }
14604 p = p.add(1);
14605 }
14606 while *p != b']' && *p != 0 {
14607 if *p == b'-' && *p.add(1) != b']' && *p.add(1) != 0 {
14608 let lo = *p.sub(1);
14610 let hi = *p.add(1);
14611 if lo <= hi && (k >= lo && k <= hi || kfold >= lo && kfold <= hi) {
14612 return !inv;
14613 }
14614 p = p.add(2);
14615 } else if *p == b'[' && (*p.add(1) == b':' || *p.add(1) == b'.' || *p.add(1) == b'=') {
14616 let z = *p.add(1);
14617 let start = p.add(2);
14618 let mut q = start;
14619 while *q != 0 && (*q != z || *q.add(1) != b']') { q = q.add(1); }
14620 if *q != 0 {
14621 let len = (q as usize) - (start as usize);
14622 if len > 0 {
14623 let inner = core::slice::from_raw_parts(start, len);
14624 let matched =
14625 if z == b':' { match_class(inner, k, kfold) }
14626 else { len == 1 && (inner[0] == k || inner[0] == kfold) };
14627 if matched { return !inv; }
14628 }
14629 p = q.add(2);
14630 continue;
14631 }
14632 } else {
14633 if *p == k || *p == kfold {
14634 return !inv;
14635 }
14636 p = p.add(1);
14637 }
14638 }
14639 inv
14640}
14641
14642unsafe fn fnmatch_internal(pat: *const u8, str: *const u8, flags: c_int) -> c_int {
14644 if flags & FNM_PERIOD != 0 && *str == b'.' && *pat != b'.' {
14646 return FNM_NOMATCH;
14647 }
14648
14649 let mut p = pat;
14650 let mut s = str;
14651
14652 loop {
14654 let (tok, step) = pat_next(p, usize::MAX, flags);
14655 match tok {
14656 FNM_END => {
14657 return if *s == 0 { 0 } else { FNM_NOMATCH };
14658 }
14659 FNM_STAR => {
14660 p = p.add(1);
14661 break;
14662 }
14663 FNM_QUESTION => {
14664 if *s == 0 { return FNM_NOMATCH; }
14665 s = s.add(1);
14666 p = p.add(step);
14667 }
14668 FNM_BRACKET => {
14669 if *s == 0 { return FNM_NOMATCH; }
14670 let k = *s;
14671 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14672 if !match_bracket(p, k, kfold) { return FNM_NOMATCH; }
14673 p = p.add(step);
14674 s = s.add(1);
14675 }
14676 c => {
14677 if *s == 0 { return FNM_NOMATCH; }
14678 let k = *s;
14679 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14680 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14681 p = p.add(step);
14682 s = s.add(1);
14683 }
14684 }
14685 }
14686
14687 let mut ptail = p;
14690 let mut tailcnt: usize = 0;
14691 let mut pp = p;
14692 loop {
14693 let (tok, step) = pat_next(pp, usize::MAX, flags);
14694 if tok == FNM_END { break; }
14695 if tok == FNM_STAR {
14696 tailcnt = 0;
14697 ptail = pp.add(1);
14698 } else {
14699 tailcnt += 1;
14700 }
14701 pp = pp.add(step);
14702 }
14703
14704 let slen = strlen(s as *const c_char);
14706 if slen < tailcnt { return FNM_NOMATCH; }
14707
14708 let stail = s.add(slen - tailcnt);
14710 let mut tp = ptail;
14711 let mut ts = stail;
14712 loop {
14713 let (tok, step) = pat_next(tp, usize::MAX, flags);
14714 tp = tp.add(step);
14715 if tok == FNM_END {
14716 break;
14717 }
14718 let k = *ts;
14719 if k == 0 { return FNM_NOMATCH; }
14720 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14721 match tok {
14722 FNM_QUESTION => { ts = ts.add(1); }
14723 FNM_BRACKET => {
14724 if !match_bracket(tp.sub(step), k, kfold) { return FNM_NOMATCH; }
14725 ts = ts.add(1);
14726 }
14727 c => {
14728 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14729 ts = ts.add(1);
14730 }
14731 }
14732 }
14733
14734 let endstr = stail;
14735 let endpat = ptail;
14736
14737 let mut cp = p;
14738 let mut cs = s;
14739 while cp < endpat {
14740 let (tok, step) = pat_next(cp, usize::MAX, flags);
14741 if tok == FNM_STAR {
14742 cp = cp.add(step);
14743 cs = s;
14744 continue;
14745 }
14746 let comp_start = cp;
14747 let mut ok = false;
14748 let mut try_s = cs;
14749 while try_s < endstr {
14750 let mut tmp_p = comp_start;
14751 let mut tmp_s = try_s;
14752 let mut matched = true;
14753 loop {
14754 let (t, st) = pat_next(tmp_p, usize::MAX, flags);
14755 if t == FNM_STAR || t == FNM_END {
14756 cp = tmp_p;
14757 cs = tmp_s;
14758 ok = true;
14759 break;
14760 }
14761 if *tmp_s == 0 {
14762 matched = false;
14763 break;
14764 }
14765 let k = *tmp_s;
14766 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14767 match t {
14768 FNM_QUESTION => {
14769 tmp_s = tmp_s.add(1);
14770 }
14771 FNM_BRACKET => {
14772 if !match_bracket(tmp_p, k, kfold) {
14773 matched = false;
14774 break;
14775 }
14776 tmp_s = tmp_s.add(1);
14777 }
14778 c => {
14779 if k as c_int != c && kfold as c_int != c {
14780 matched = false;
14781 break;
14782 }
14783 tmp_s = tmp_s.add(1);
14784 }
14785 }
14786 tmp_p = tmp_p.add(st);
14787 }
14788 if ok { break; }
14789 if !matched {
14790 try_s = try_s.add(1);
14791 }
14792 }
14793 if !ok {
14794 return FNM_NOMATCH;
14795 }
14796 }
14797 0
14798}
14799
14800#[no_mangle]
14801pub unsafe extern "C" fn fnmatch(pat: *const c_char, str: *const c_char, flags: c_int) -> c_int {
14802 let pat = pat as *const u8;
14803 let str = str as *const u8;
14804
14805 if flags & FNM_PATHNAME != 0 {
14806 let mut s = str;
14808 let mut p = pat;
14809 loop {
14810 let mut send = s;
14812 while *send != 0 && *send != b'/' { send = send.add(1); }
14813 let mut pend = p;
14815 loop {
14816 let (tok, step) = pat_next(pend, usize::MAX, flags);
14817 if tok == FNM_END || (tok >= 0 && tok as u8 == b'/') {
14818 break;
14819 }
14820 pend = pend.add(step);
14821 }
14822 let (ptok, pstep) = pat_next(pend, usize::MAX, flags);
14823 let pat_is_slash = ptok >= 0 && ptok as u8 == b'/';
14824 let str_is_slash = *send == b'/';
14825 if pat_is_slash != str_is_slash && (*send != 0 || !(flags & FNM_LEADING_DIR != 0)) {
14826 return FNM_NOMATCH;
14827 }
14828 let plen = (pend as usize) - (p as usize);
14831 let slen = (send as usize) - (s as usize);
14832 if plen > 1024 || slen > 1024 { return FNM_NOMATCH; }
14835 let mut pbuf = [0u8; 1025];
14836 let mut sbuf = [0u8; 1025];
14837 core::ptr::copy_nonoverlapping(p, pbuf.as_mut_ptr(), plen);
14838 pbuf[plen] = 0;
14839 core::ptr::copy_nonoverlapping(s, sbuf.as_mut_ptr(), slen);
14840 sbuf[slen] = 0;
14841 if fnmatch_internal(pbuf.as_ptr(), sbuf.as_ptr(), flags & !FNM_LEADING_DIR) != 0 {
14842 return FNM_NOMATCH;
14843 }
14844 if !pat_is_slash {
14845 return 0;
14846 }
14847 s = send.add(1);
14848 p = pend.add(pstep);
14849 }
14850 }
14851
14852 if flags & FNM_LEADING_DIR != 0 {
14853 let mut s = str;
14855 while *s != 0 {
14856 if *s == b'/' {
14857 let len = (s as usize) - (str as usize);
14860 if len < 4096 {
14862 let mut buf = [0u8; 4096];
14863 core::ptr::copy_nonoverlapping(str, buf.as_mut_ptr(), len);
14864 buf[len] = 0;
14865 if fnmatch_internal(pat, buf.as_ptr(), flags) == 0 {
14866 return 0;
14867 }
14868 }
14869 }
14870 s = s.add(1);
14871 }
14872 }
14873
14874 fnmatch_internal(pat, str, flags)
14875}
14876
14877#[no_mangle]
14882pub unsafe extern "C" fn setmntent(name: *const c_char, mode: *const c_char) -> *mut FILE {
14883 fopen(name, mode)
14884}
14885
14886#[no_mangle]
14887pub unsafe extern "C" fn endmntent(f: *mut FILE) -> c_int {
14888 if !f.is_null() {
14889 fclose(f);
14890 }
14891 1
14892}
14893
14894static mut MNTENT_MNT: MntEnt = MntEnt {
14896 mnt_fsname: core::ptr::null_mut(),
14897 mnt_dir: core::ptr::null_mut(),
14898 mnt_type: core::ptr::null_mut(),
14899 mnt_opts: core::ptr::null_mut(),
14900 mnt_freq: 0,
14901 mnt_passno: 0,
14902};
14903
14904#[repr(C)]
14905pub struct MntEnt {
14906 mnt_fsname: *mut c_char,
14907 mnt_dir: *mut c_char,
14908 mnt_type: *mut c_char,
14909 mnt_opts: *mut c_char,
14910 mnt_freq: c_int,
14911 mnt_passno: c_int,
14912}
14913
14914unsafe fn unescape_ent(beg: *mut c_char) -> *mut c_char {
14915 let mut dest = beg;
14916 let mut src = beg;
14917 while *src != 0 {
14918 if *src != b'\\' as c_char {
14919 *dest = *src;
14920 dest = dest.add(1);
14921 src = src.add(1);
14922 continue;
14923 }
14924 if *src.add(1) == b'\\' as c_char {
14926 src = src.add(1);
14927 *dest = *src;
14928 dest = dest.add(1);
14929 src = src.add(1);
14930 continue;
14931 }
14932 let mut val: u8 = 0;
14934 let mut cnt = 0;
14935 let mut sp = src.add(1);
14936 while cnt < 3 && *sp >= b'0' as c_char && *sp <= b'7' as c_char {
14937 val = val * 8 + (*sp as u8 - b'0');
14938 sp = sp.add(1);
14939 cnt += 1;
14940 }
14941 if cnt > 0 {
14942 *dest = val as c_char;
14943 dest = dest.add(1);
14944 src = sp;
14945 } else {
14946 *dest = *src;
14947 dest = dest.add(1);
14948 src = src.add(1);
14949 }
14950 }
14951 *dest = 0;
14952 beg
14953}
14954
14955unsafe fn parse_mntent_line(
14956 linebuf: *mut c_char,
14957 mnt: *mut MntEnt,
14958) -> *mut MntEnt {
14959 let _len = strlen(linebuf as *const c_char);
14960 let mut p = linebuf;
14963 while *p == b' ' as c_char || *p == b'\t' as c_char || *p == b'\n' as c_char || *p == b'\r' as c_char {
14965 p = p.add(1);
14966 }
14967 if *p == 0 || *p == b'#' as c_char {
14968 return core::ptr::null_mut();
14969 }
14970
14971 (*mnt).mnt_fsname = p;
14973 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14974 p = p.add(1);
14975 }
14976 if *p == 0 { return core::ptr::null_mut(); }
14977 *p = 0;
14978 p = p.add(1);
14979 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14980
14981 (*mnt).mnt_dir = p;
14983 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14984 p = p.add(1);
14985 }
14986 if *p == 0 { return core::ptr::null_mut(); }
14987 *p = 0;
14988 p = p.add(1);
14989 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14990
14991 (*mnt).mnt_type = p;
14993 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14994 p = p.add(1);
14995 }
14996 if *p == 0 { return core::ptr::null_mut(); }
14997 *p = 0;
14998 p = p.add(1);
14999 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
15000
15001 (*mnt).mnt_opts = p;
15003 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
15004 p = p.add(1);
15005 }
15006 if *p != 0 {
15007 *p = 0;
15008 p = p.add(1);
15009 }
15010 if *(*mnt).mnt_opts == 0 {
15011 (*mnt).mnt_opts = b"defaults\0".as_ptr() as *mut c_char;
15012 }
15013
15014 (*mnt).mnt_freq = 0;
15016 (*mnt).mnt_passno = 0;
15017 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
15019 if *p >= b'0' as c_char && *p <= b'9' as c_char {
15020 (*mnt).mnt_freq = (*p - b'0' as c_char) as c_int;
15021 p = p.add(1);
15022 while *p >= b'0' as c_char && *p <= b'9' as c_char {
15023 (*mnt).mnt_freq = (*mnt).mnt_freq * 10 + (*p - b'0' as c_char) as c_int;
15024 p = p.add(1);
15025 }
15026 }
15027 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
15028 if *p >= b'0' as c_char && *p <= b'9' as c_char {
15029 (*mnt).mnt_passno = (*p - b'0' as c_char) as c_int;
15030 p = p.add(1);
15031 while *p >= b'0' as c_char && *p <= b'9' as c_char {
15032 (*mnt).mnt_passno = (*mnt).mnt_passno * 10 + (*p - b'0' as c_char) as c_int;
15033 p = p.add(1);
15034 }
15035 }
15036
15037 unescape_ent((*mnt).mnt_fsname);
15039 unescape_ent((*mnt).mnt_dir);
15040 unescape_ent((*mnt).mnt_type);
15041 unescape_ent((*mnt).mnt_opts);
15042
15043 mnt
15044}
15045
15046static SENTINEL_PTR: usize = 1;
15049
15050unsafe fn mntent_fgetc(f: *mut FILE) -> c_int {
15052 fgetc(f)
15053}
15054
15055unsafe fn mntent_fgets(buf: *mut c_char, n: usize, f: *mut FILE) -> *mut c_char {
15056 if n == 0 { return core::ptr::null_mut(); }
15057 let max = n - 1;
15058 let mut i = 0usize;
15059 while i < max {
15060 let c = mntent_fgetc(f);
15061 if c == -1 { if i == 0 { return core::ptr::null_mut(); } break; }
15062 *buf.add(i) = c as c_char;
15063 i += 1;
15064 if c == b'\n' as c_int { break; }
15065 }
15066 *buf.add(i) = 0;
15067 buf
15068}
15069
15070#[no_mangle]
15071pub unsafe extern "C" fn getmntent_r(
15072 f: *mut FILE,
15073 mnt: *mut MntEnt,
15074 mut linebuf: *mut c_char,
15075 _buflen: c_int,
15076) -> *mut MntEnt {
15077 let use_internal = linebuf as usize == SENTINEL_PTR;
15078
15079 (*mnt).mnt_freq = 0;
15080 (*mnt).mnt_passno = 0;
15081
15082 static mut INTERNAL_BUF: [c_char; 4096] = [0; 4096];
15084
15085 loop {
15086 if use_internal {
15087 linebuf = core::ptr::addr_of_mut!(INTERNAL_BUF).cast::<c_char>();
15088 }
15089 let res = mntent_fgets(linebuf, 4096, f);
15090 if res.is_null() {
15091 return core::ptr::null_mut();
15092 }
15093 let mut has_newline = false;
15094 let mut p = linebuf;
15095 while *p != 0 { if *p == b'\n' as c_char { has_newline = true; break; } p = p.add(1); }
15096 if !has_newline {
15097 ERRNO!() = 34;
15098 return core::ptr::null_mut();
15099 }
15100 let result = parse_mntent_line(linebuf, mnt);
15101 if !result.is_null() {
15102 return result;
15103 }
15104 }
15105}
15106
15107#[no_mangle]
15108pub unsafe extern "C" fn getmntent(f: *mut FILE) -> *mut MntEnt {
15109 getmntent_r(f, core::ptr::addr_of_mut!(MNTENT_MNT), SENTINEL_PTR as *mut c_char, 0)
15110}
15111
15112#[no_mangle]
15113pub unsafe extern "C" fn addmntent(f: *mut FILE, mnt: *const MntEnt) -> c_int {
15114 fseek(f, 0, 2); let written = fprintf(
15116 f,
15117 b"%s\t%s\t%s\t%s\t%d\t%d\n\0".as_ptr() as *const c_char,
15118 (*mnt).mnt_fsname,
15119 (*mnt).mnt_dir,
15120 (*mnt).mnt_type,
15121 (*mnt).mnt_opts,
15122 (*mnt).mnt_freq,
15123 (*mnt).mnt_passno,
15124 );
15125 if written < 0 { 1 } else { 0 }
15126}
15127
15128#[no_mangle]
15129pub unsafe extern "C" fn hasmntopt(mnt: *const MntEnt, opt: *const c_char) -> *mut c_char {
15130 let l = strlen(opt as *const c_char);
15131 let mut p = (*mnt).mnt_opts;
15132 loop {
15133 if strncmp(p as *const u8, opt as *const u8, l) == 0 {
15134 let after = *p.add(l);
15135 if after == 0 || after == b',' as c_char || after == b'=' as c_char {
15136 return p;
15137 }
15138 }
15139 let comma = strchr(p as *const u8, b',' as c_int);
15140 if comma.is_null() {
15141 return core::ptr::null_mut();
15142 }
15143 p = comma.add(1) as *mut c_char;
15144 }
15145}
15146
15147const EEXIST: c_int = 17;
15155const ENAMETOOLONG: c_int = 36;
15156const EMFILE: c_int = 24;
15157const EIDRM: c_int = 43;
15158
15159#[inline]
15160unsafe fn sys_msgget(key: c_int, msgflg: c_int) -> i64 {
15161 <Arch as Syscalls>::syscall2(SYS_MSGGET, key as i64, msgflg as i64)
15162}
15163
15164#[inline]
15165unsafe fn sys_msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> i64 {
15166 <Arch as Syscalls>::syscall4(SYS_MSGSND, msqid as i64, msgp as i64, msgsz as i64, msgflg as i64)
15167}
15168
15169#[inline]
15170unsafe fn sys_msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> i64 {
15171 <Arch as Syscalls>::syscall5(SYS_MSGRCV, msqid as i64, msgp as i64, msgsz as i64, msgtyp as i64, msgflg as i64)
15172}
15173
15174#[inline]
15175unsafe fn sys_msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
15176 <Arch as Syscalls>::syscall3(SYS_MSGCTL, msqid as i64, cmd as i64, buf as i64)
15177}
15178
15179#[inline]
15180unsafe fn sys_semget(key: c_int, nsems: c_int, semflg: c_int) -> i64 {
15181 <Arch as Syscalls>::syscall3(SYS_SEMGET, key as i64, nsems as i64, semflg as i64)
15182}
15183
15184#[inline]
15185unsafe fn sys_semop(semid: c_int, sops: *const c_void, nsops: usize) -> i64 {
15186 <Arch as Syscalls>::syscall3(SYS_SEMOP, semid as i64, sops as i64, nsops as i64)
15187}
15188
15189#[inline]
15190unsafe fn sys_semctl(semid: c_int, semnum: c_int, cmd: c_int, arg: *mut c_void) -> i64 {
15191 <Arch as Syscalls>::syscall4(SYS_SEMCTL, semid as i64, semnum as i64, cmd as i64, arg as i64)
15192}
15193
15194#[inline]
15195unsafe fn sys_shmget(key: c_int, size: usize, shmflg: c_int) -> i64 {
15196 <Arch as Syscalls>::syscall3(SYS_SHMGET, key as i64, size as i64, shmflg as i64)
15197}
15198
15199#[inline]
15200unsafe fn sys_shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> i64 {
15201 <Arch as Syscalls>::syscall3(SYS_SHMAT, shmid as i64, shmaddr as i64, shmflg as i64)
15202}
15203
15204#[inline]
15205unsafe fn sys_shmdt(shmaddr: *const c_void) -> i64 {
15206 <Arch as Syscalls>::syscall1(SYS_SHMDT, shmaddr as i64)
15207}
15208
15209#[inline]
15210unsafe fn sys_shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
15211 <Arch as Syscalls>::syscall3(SYS_SHMCTL, shmid as i64, cmd as i64, buf as i64)
15212}
15213
15214#[no_mangle]
15216pub unsafe extern "C" fn ftok(path: *const c_char, id: c_int) -> c_int {
15217 let mut st: kernel_stat64 = core::mem::zeroed();
15218 let r = sys_stat(path as *const u8, &mut st);
15219 if r < 0 {
15220 ERRNO!() = (-r) as c_int;
15221 return -1;
15222 }
15223 ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16) | (((id as u32 & 0xff) << 24)) as u64) as c_int
15224}
15225
15226#[no_mangle]
15228pub unsafe extern "C" fn msgget(key: c_int, msgflg: c_int) -> c_int {
15229 let r = sys_msgget(key, msgflg);
15230 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15231}
15232
15233#[no_mangle]
15235pub unsafe extern "C" fn msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> c_int {
15236 let r = sys_msgsnd(msqid, msgp, msgsz, msgflg);
15237 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15238}
15239
15240#[no_mangle]
15242pub unsafe extern "C" fn msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> isize {
15243 let r = sys_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
15244 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
15245}
15246
15247#[no_mangle]
15249pub unsafe extern "C" fn msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
15250 let r = sys_msgctl(msqid, cmd, buf);
15251 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15252}
15253
15254#[no_mangle]
15256pub unsafe extern "C" fn semget(key: c_int, nsems: c_int, semflg: c_int) -> c_int {
15257 if nsems > 65535 { ERRNO!() = 22; return -1; }
15258 let r = sys_semget(key, nsems, semflg);
15259 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15260}
15261
15262#[no_mangle]
15264pub unsafe extern "C" fn semop(semid: c_int, sops: *const c_void, nsops: usize) -> c_int {
15265 let r = sys_semop(semid, sops, nsops);
15266 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15267}
15268
15269#[no_mangle]
15271pub unsafe extern "C" fn semctl(semid: c_int, semnum: c_int, cmd: c_int, mut args: ...) -> c_int {
15272 let mut arg: *mut c_void = core::ptr::null_mut();
15273 match cmd {
15275 16 | 13 | 17 | 1 | 2 | 3 | 18 | 19 | 20 | 0x102 | 0x104 | 0x106 => {
15279 arg = args.next_arg::<*mut c_void>();
15280 }
15281 _ => {}
15282 }
15283 let r = sys_semctl(semid, semnum, cmd, arg);
15284 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15285}
15286
15287#[no_mangle]
15289pub unsafe extern "C" fn shmget(key: c_int, size: usize, shmflg: c_int) -> c_int {
15290 let r = sys_shmget(key, size, shmflg);
15291 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15292}
15293
15294#[no_mangle]
15296pub unsafe extern "C" fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void {
15297 let r = sys_shmat(shmid, shmaddr, shmflg);
15298 if (r as usize) > (-(4096isize as isize)) as usize {
15299 ERRNO!() = (-r) as c_int;
15300 return -1isize as *mut c_void;
15301 }
15302 r as *mut c_void
15303}
15304
15305#[no_mangle]
15307pub unsafe extern "C" fn shmdt(shmaddr: *const c_void) -> c_int {
15308 let r = sys_shmdt(shmaddr);
15309 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15310}
15311
15312#[no_mangle]
15314pub unsafe extern "C" fn shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
15315 let r = sys_shmctl(shmid, cmd, buf);
15316 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15317}
15318
15319#[no_mangle]
15329pub static mut __auxv: *const usize = core::ptr::null();
15330
15331#[no_mangle]
15332pub static mut __progname: *mut c_char = core::ptr::null_mut();
15333#[no_mangle]
15334pub static mut __progname_full: *mut c_char = core::ptr::null_mut();
15335#[no_mangle]
15336pub static mut program_invocation_name: *mut c_char = core::ptr::null_mut();
15337#[no_mangle]
15338pub static mut program_invocation_short_name: *mut c_char = core::ptr::null_mut();
15339
15340#[no_mangle]
15341pub static in6addr_any: [u8; 16] = [0; 16];
15342#[no_mangle]
15343pub static in6addr_loopback: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
15344
15345#[no_mangle]
15346pub static mut __daylight: c_int = 0;
15347#[no_mangle]
15348pub static mut __timezone: c_long = 0;
15349#[no_mangle]
15350pub static mut __tzname: [*mut c_char; 2] = [core::ptr::null_mut(); 2];
15351
15352#[no_mangle]
15353pub unsafe extern "C" fn getauxval(type_: c_ulong) -> c_ulong {
15354 let mut p = __auxv;
15355 if p.is_null() {
15356 return 0;
15357 }
15358 loop {
15359 let tag = *p;
15360 if tag == 0 {
15361 return 0;
15362 }
15363 if tag == type_ as usize {
15364 return *p.add(1) as c_ulong;
15365 }
15366 p = p.add(2);
15367 }
15368}
15369
15370type MainFn = unsafe extern "C" fn(c_int, *const *const c_char, *const *const c_char) -> c_int;
15371type InitFn = unsafe extern "C" fn();
15372
15373#[no_mangle]
15374pub unsafe extern "C" fn __libc_start_main(
15375 main: MainFn,
15376 argc: c_int,
15377 argv: *const *const c_char,
15378 _init: *const c_void,
15379 _fini: *const c_void,
15380 _rtld_fini: *const c_void,
15381 _stack_end: *const c_void,
15382) -> ! {
15383 errno_init();
15384
15385 let envp = argv.add((argc + 1) as usize);
15386 __environ = envp as *mut *mut c_char;
15387 environ = __environ; ___environ = __environ;
15389 _environ = __environ;
15390
15391 if !argv.is_null() && argc > 0 {
15393 let argv0 = *argv;
15394 __progname_full = argv0 as *mut c_char;
15395 program_invocation_name = argv0 as *mut c_char;
15396 let mut base = argv0;
15397 let mut p = argv0;
15398 while *p != 0 {
15399 if *p == b'/' as c_char { base = p.add(1); }
15400 p = p.add(1);
15401 }
15402 __progname = base as *mut c_char;
15403 program_invocation_short_name = base as *mut c_char;
15404 }
15405
15406 __stdio_init();
15407
15408 let mut set: SigSetT = 0;
15409 sigemptyset(&mut set);
15410 sigaddset(&mut set, SIGCANCEL);
15411 sigprocmask(SIG_UNBLOCK, &set, core::ptr::null_mut());
15412
15413 if !_init.is_null() {
15414 let init_fn: InitFn = core::mem::transmute(_init);
15415 init_fn();
15416 }
15417
15418 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
15422 {
15423 let random_ptr = getauxval(25) as *const u8; if !random_ptr.is_null() {
15425 let a = core::ptr::read_unaligned(random_ptr as *const u64);
15426 let b = core::ptr::read_unaligned(random_ptr.add(8) as *const u64);
15427 __stack_chk_guard = (a ^ b) as usize;
15428 } else {
15429 __stack_chk_guard = 0xdefaced_cafebeef;
15431 }
15432 }
15433
15434 let result = main(argc, argv, envp);
15435
15436 if !_fini.is_null() {
15437 let fini_fn: InitFn = core::mem::transmute(_fini);
15438 fini_fn();
15439 }
15440
15441 exit(result);
15442}
15443
15444type LdsoDlopenFn = unsafe extern "C" fn(*const c_char, c_int) -> *mut c_void;
15445type LdsoDlsymFn = unsafe extern "C" fn(*mut c_void, *const c_char) -> *mut c_void;
15446type LdsoDlcloseFn = unsafe extern "C" fn(*mut c_void) -> c_int;
15447type LdsoDlerrorFn = unsafe extern "C" fn() -> *const c_char;
15448
15449static mut LDSO_DLOPEN: Option<LdsoDlopenFn> = None;
15450static mut LDSO_DLSYM: Option<LdsoDlsymFn> = None;
15451static mut LDSO_DLCLOSE: Option<LdsoDlcloseFn> = None;
15452static mut LDSO_DLERROR: Option<LdsoDlerrorFn> = None;
15453
15454#[no_mangle]
15455pub unsafe extern "C" fn __ldso_register_dlopen(f: LdsoDlopenFn) {
15456 LDSO_DLOPEN = Some(f);
15457}
15458
15459#[no_mangle]
15460pub unsafe extern "C" fn __ldso_register_dlsym(f: LdsoDlsymFn) {
15461 LDSO_DLSYM = Some(f);
15462}
15463
15464#[no_mangle]
15465pub unsafe extern "C" fn __ldso_register_dlclose(f: LdsoDlcloseFn) {
15466 LDSO_DLCLOSE = Some(f);
15467}
15468
15469#[no_mangle]
15470pub unsafe extern "C" fn __ldso_register_dlerror(f: LdsoDlerrorFn) {
15471 LDSO_DLERROR = Some(f);
15472}
15473
15474#[no_mangle]
15475pub unsafe extern "C" fn dlopen(filename: *const c_char, flags: c_int) -> *mut c_void {
15476 if let Some(f) = LDSO_DLOPEN {
15477 f(filename, flags)
15478 } else {
15479 null_mut()
15480 }
15481}
15482
15483#[no_mangle]
15484pub unsafe extern "C" fn dlsym(handle: *mut c_void, symbol: *const c_char) -> *mut c_void {
15485 if let Some(f) = LDSO_DLSYM {
15486 f(handle, symbol)
15487 } else {
15488 null_mut()
15489 }
15490}
15491
15492#[no_mangle]
15493pub unsafe extern "C" fn dlclose(handle: *mut c_void) -> c_int {
15494 if let Some(f) = LDSO_DLCLOSE {
15495 f(handle)
15496 } else {
15497 0
15498 }
15499}
15500
15501#[no_mangle]
15502pub unsafe extern "C" fn dlerror() -> *const c_char {
15503 if let Some(f) = LDSO_DLERROR {
15504 f()
15505 } else {
15506 core::ptr::null()
15507 }
15508}
15509
15510include!("crypt_impl.rs");
15511include!("statvfs.rs");
15512include!("daemon.rs");
15513include!("dn_expand.rs");
15514include!("lrand48.rs");
15515include!("strverscmp.rs");
15516include!("syscall.rs");
15517include!("pthread_atfork.rs");
15518include!("fenv.rs");
15519include!("locale_ctype.rs");
15520include!("regression_stubs.rs");
15521include!("netdb_extra.rs");
15522include!("compat_extra.rs");
15523include!("stdio_extra.rs");
15524include!("ns_parse.rs");
15525include!("fts.rs");
15526include!("ifaddrs.rs");
15527include!("dl_extra.rs");
15528include!("des.rs");
15529include!("path_extra.rs");
15530include!("wordexp.rs");
15531include!("getopt_impl.rs");
15532
15533type regoff_t = c_int;
15538
15539#[repr(C)]
15540pub struct regex_t {
15541 pub re_nsub: usize,
15542 pub __opaque: *mut c_void,
15543 pub __padding: [*mut c_void; 4],
15544 pub __nsub2: usize,
15545 pub __padding2: c_char,
15546}
15547
15548#[repr(C)]
15549pub struct regmatch_t {
15550 pub rm_so: regoff_t,
15551 pub rm_eo: regoff_t,
15552}
15553
15554include!("regex.rs");
15555
15556#[cfg(test)]
15557mod libc_unit_stub {
15558 #[test]
15559 fn stub() {
15560 assert!(true);
15561 }
15562}
15563
15564#[inline]
15569pub(crate) fn fmax_impl(x: f64, y: f64) -> f64 {
15570 if x.is_nan() { return y; }
15571 if y.is_nan() { return x; }
15572 if x == 0.0 && y == 0.0 {
15573 return if x.is_sign_negative() && y.is_sign_negative() { -0.0 } else { 0.0 };
15574 }
15575 if x > y { x } else { y }
15576}
15577
15578#[inline]
15579pub(crate) fn fmin_impl(x: f64, y: f64) -> f64 {
15580 if x.is_nan() { return y; }
15581 if y.is_nan() { return x; }
15582 if x == 0.0 && y == 0.0 {
15583 return if x.is_sign_negative() || y.is_sign_negative() { -0.0 } else { 0.0 };
15584 }
15585 if x < y { x } else { y }
15586}
15587
15588#[inline]
15589pub(crate) fn fmaxf_impl(x: f32, y: f32) -> f32 {
15590 if x.is_nan() { return y; }
15591 if y.is_nan() { return x; }
15592 if x == 0.0 && y == 0.0 {
15593 return if x.is_sign_negative() && y.is_sign_negative() { -0.0 } else { 0.0 };
15594 }
15595 if x > y { x } else { y }
15596}
15597
15598#[inline]
15599pub(crate) fn fminf_impl(x: f32, y: f32) -> f32 {
15600 if x.is_nan() { return y; }
15601 if y.is_nan() { return x; }
15602 if x == 0.0 && y == 0.0 {
15603 return if x.is_sign_negative() || y.is_sign_negative() { -0.0 } else { 0.0 };
15604 }
15605 if x < y { x } else { y }
15606}
15607
15608#[inline(never)]
15609#[no_mangle]
15610pub unsafe extern "C" fn fmax(x: f64, y: f64) -> f64 {
15611 fmax_impl(x, y)
15612}
15613
15614#[inline(never)]
15615#[no_mangle]
15616pub unsafe extern "C" fn fmin(x: f64, y: f64) -> f64 {
15617 fmin_impl(x, y)
15618}
15619
15620#[no_mangle]
15621pub unsafe extern "C" fn fminf(x: f32, y: f32) -> f32 {
15622 fminf_impl(x, y)
15623}
15624
15625#[no_mangle]
15626pub unsafe extern "C" fn fdim(x: f64, y: f64) -> f64 {
15627 if x.is_nan() || y.is_nan() {
15628 return f64::NAN;
15629 }
15630 if x > y { x - y } else { 0.0 }
15631}
15632
15633#[no_mangle]
15634pub unsafe extern "C" fn fma(x: f64, y: f64, z: f64) -> f64 {
15635 if (x.is_infinite() && y == 0.0) || (y.is_infinite() && x == 0.0) {
15636 feraiseexcept(FE_INVALID);
15637 return f64::NAN;
15638 }
15639 if x.is_nan() || y.is_nan() || z.is_nan() {
15640 return f64::NAN;
15641 }
15642 let r = libm::fma(x, y, z);
15643 if r.is_nan() {
15645 feraiseexcept(FE_INVALID);
15646 }
15647 r
15648}
15649
15650#[no_mangle]
15651pub unsafe extern "C" fn ilogb(x: f64) -> i32 {
15652 if x.is_nan() {
15653 feraiseexcept(FE_INVALID);
15654 return -0x7fffffff - 1; }
15656 if x == 0.0 || x.is_infinite() {
15657 feraiseexcept(FE_INVALID);
15658 return if x == 0.0 { -0x7fffffff - 1 } else { 0x7fffffff };
15659 }
15660 let bits = x.to_bits();
15661 let exp = ((bits >> 52) & 0x7ff) as i32;
15662 if exp == 0 {
15663 let mut v = bits & 0xfffffffffffff;
15665 let mut e = -1022;
15666 while v < (1u64 << 52) { v <<= 1; e -= 1; }
15667 e
15668 } else {
15669 exp - 1023
15670 }
15671}
15672
15673#[no_mangle]
15674pub unsafe extern "C" fn logb(x: f64) -> f64 {
15675 if x.is_nan() { return x; }
15676 if x == 0.0 { return __math_divzero(1); }
15677 let bits = x.to_bits();
15678 let exp = ((bits >> 52) & 0x7ff) as i32;
15679 if exp == 0 {
15680 let mut v = bits & 0xfffffffffffff;
15682 let mut e = -1022i32;
15683 while v < (1u64 << 52) { v <<= 1; e -= 1; }
15684 e as f64
15685 } else if exp == 0x7ff {
15686 x * x } else {
15688 (exp - 1023) as f64
15689 }
15690}
15691
15692#[no_mangle]
15693pub unsafe extern "C" fn nearbyint(x: f64) -> f64 {
15694 let had_inexact = fetestexcept(FE_INEXACT) & FE_INEXACT != 0;
15695 let r = libm::rint(x);
15696 if !had_inexact {
15697 feclearexcept(FE_INEXACT);
15698 }
15699 r
15700}
15701
15702#[no_mangle]
15703pub unsafe extern "C" fn nextafter(x: f64, y: f64) -> f64 {
15704 if x.is_nan() || y.is_nan() { return x + y; }
15705 if x == 0.0 && y == 0.0 { return y; }
15706 if x == y { return x; }
15707 let r = libm::nextafter(x, y);
15708 if r.is_infinite() && x.is_finite() {
15709 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
15710 } else if r != x {
15711 let bits = r.to_bits();
15712 let is_subnormal = (bits & 0x7ff0000000000000) == 0 && (bits & 0xfffffffffffff) != 0;
15713 if r == 0.0 || is_subnormal {
15714 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
15715 }
15716 }
15717 r
15718}
15719
15720#[no_mangle]
15721pub unsafe extern "C" fn nexttoward(x: f64, y: f64) -> f64 {
15722 if x == 0.0 && y == 0.0 {
15724 return if y.is_sign_negative() { -0.0 } else { 0.0 };
15725 }
15726 nextafter(x, y)
15727}
15728
15729#[no_mangle]
15730pub unsafe extern "C" fn remainder(x: f64, y: f64) -> f64 {
15731 if x.is_nan() || y.is_nan() { return x + y; }
15732 if y == 0.0 || x.is_infinite() { return __math_invalid(x); }
15733 libm::remainder(x, y)
15734}
15735
15736#[no_mangle]
15737pub unsafe extern "C" fn remquo(x: f64, y: f64, quo: *mut i32) -> f64 {
15738 if x.is_nan() || y.is_nan() {
15739 if !quo.is_null() { *quo = 0; }
15740 return x + y;
15741 }
15742 if y == 0.0 || x.is_infinite() {
15743 if !quo.is_null() { *quo = 0; }
15744 return __math_invalid(x);
15745 }
15746 let (r, q) = libm::remquo(x, y);
15747 if !quo.is_null() { *quo = q; }
15748 r
15749}
15750
15751#[no_mangle]
15752pub unsafe extern "C" fn exp2(x: f64) -> f64 {
15753 exp2_impl(x)
15754}
15755
15756#[no_mangle]
15757pub unsafe extern "C" fn expm1(x: f64) -> f64 {
15758 let r = libm::expm1(x);
15759 if r != 0.0 && x != 0.0 && libm::fabs(x) < 1e-307 {
15761 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
15762 }
15763 r
15764}
15765
15766#[no_mangle]
15767pub unsafe extern "C" fn log1p(x: f64) -> f64 {
15768 if x == -1.0 {
15769 feraiseexcept(FE_DIVBYZERO);
15770 return f64::NEG_INFINITY;
15771 }
15772 libm::log1p(x)
15773}
15774
15775#[no_mangle]
15776pub unsafe extern "C" fn acosh(x: f64) -> f64 {
15777 if x < 1.0 {
15778 feraiseexcept(FE_INVALID);
15779 return f64::NAN;
15780 }
15781 libm::acosh(x)
15782}
15783
15784#[no_mangle]
15785pub unsafe extern "C" fn asinh(x: f64) -> f64 {
15786 if x == 0.0 { return x; }
15787 libm::asinh(x)
15788}
15789
15790#[no_mangle]
15791pub unsafe extern "C" fn atanh(x: f64) -> f64 {
15792 if x == 0.0 { return x; }
15793 let e = ((x.to_bits() >> 52) & 0x7ff) as i32;
15794 if e < 0x3ff - 32 {
15795 feraiseexcept(FE_INEXACT);
15796 if e == 0 { feraiseexcept(FE_UNDERFLOW); }
15797 return x;
15798 }
15799 if x == 1.0 {
15800 feraiseexcept(FE_DIVBYZERO);
15801 return f64::INFINITY;
15802 }
15803 if x == -1.0 {
15804 feraiseexcept(FE_DIVBYZERO);
15805 return f64::NEG_INFINITY;
15806 }
15807 if x.is_nan() { return x; }
15808 let ax = libm::fabs(x);
15809 if ax > 1.0 {
15810 feraiseexcept(FE_INVALID);
15811 return f64::NAN;
15812 }
15813 if ax < 0.5 {
15814 let r = libm::log1p(2.0 * (ax + ax * ax / (1.0 - ax))) / 2.0;
15816 if x < 0.0 { -r } else { r }
15817 } else {
15818 let r = 0.5 * libm::log((1.0 + ax) / (1.0 - ax));
15820 if x < 0.0 { -r } else { r }
15821 }
15822}
15823
15824#[no_mangle]
15825pub unsafe extern "C" fn cbrt(x: f64) -> f64 {
15826 libm::cbrt(x)
15827}
15828
15829#[no_mangle]
15830pub unsafe extern "C" fn erf(x: f64) -> f64 {
15831 erf_impl(x)
15832}
15833
15834#[no_mangle]
15835pub unsafe extern "C" fn erfc(x: f64) -> f64 {
15836 erfc_impl(x)
15837}
15838
15839#[no_mangle]
15840pub unsafe extern "C" fn lgamma(x: f64) -> f64 {
15841 lgamma_impl(x)
15842}
15843
15844#[no_mangle]
15845pub unsafe extern "C" fn tgamma(x: f64) -> f64 {
15846 tgamma_impl(x)
15847}
15848
15849#[no_mangle]
15850pub unsafe extern "C" fn lround(x: f64) -> core::ffi::c_long {
15851 libm::round(x) as core::ffi::c_long
15852}
15853
15854#[no_mangle]
15855pub unsafe extern "C" fn llround(x: f64) -> i64 {
15856 libm::round(x) as i64
15857}
15858
15859#[no_mangle]
15866pub unsafe extern "C" fn cabs(z: (f64, f64)) -> f64 {
15867 libm::sqrt(z.0 * z.0 + z.1 * z.1)
15868}
15869
15870#[no_mangle]
15871pub unsafe extern "C" fn cabsf(z: (f32, f32)) -> f32 {
15872 libm::sqrtf(z.0 * z.0 + z.1 * z.1)
15873}
15874
15875#[no_mangle]
15876pub unsafe extern "C" fn cabsl(z: (f64, f64)) -> f64 {
15877 cabs(z)
15878}
15879
15880#[no_mangle]
15881pub unsafe extern "C" fn carg(z: (f64, f64)) -> f64 {
15882 libm::atan2(z.1, z.0)
15883}
15884
15885#[no_mangle]
15886pub unsafe extern "C" fn cargf(z: (f32, f32)) -> f32 {
15887 libm::atan2f(z.1, z.0)
15888}
15889
15890#[no_mangle]
15891pub unsafe extern "C" fn cargl(z: (f64, f64)) -> f64 {
15892 carg(z)
15893}
15894
15895#[no_mangle]
15896pub unsafe extern "C" fn cimag(z: (f64, f64)) -> f64 {
15897 z.1
15898}
15899
15900#[no_mangle]
15901pub unsafe extern "C" fn cimagf(z: (f32, f32)) -> f32 {
15902 z.1
15903}
15904
15905#[no_mangle]
15906pub unsafe extern "C" fn cimagl(z: (f64, f64)) -> f64 {
15907 z.1
15908}
15909
15910#[no_mangle]
15911pub unsafe extern "C" fn creal(z: (f64, f64)) -> f64 {
15912 z.0
15913}
15914
15915#[no_mangle]
15916pub unsafe extern "C" fn crealf(z: (f32, f32)) -> f32 {
15917 z.0
15918}
15919
15920#[no_mangle]
15921pub unsafe extern "C" fn creall(z: (f64, f64)) -> f64 {
15922 z.0
15923}
15924
15925#[no_mangle]
15926pub unsafe extern "C" fn conj(z: (f64, f64)) -> (f64, f64) {
15927 (z.0, -z.1)
15928}
15929
15930#[no_mangle]
15931pub unsafe extern "C" fn conjf(z: (f32, f32)) -> (f32, f32) {
15932 (z.0, -z.1)
15933}
15934
15935#[no_mangle]
15936pub unsafe extern "C" fn conjl(z: (f64, f64)) -> (f64, f64) {
15937 conj(z)
15938}
15939
15940#[no_mangle]
15941pub unsafe extern "C" fn cproj(z: (f64, f64)) -> (f64, f64) {
15942 if z.0.is_infinite() || z.1.is_infinite() {
15943 (f64::INFINITY, if z.1.is_sign_positive() { 0.0 } else { -0.0 })
15944 } else {
15945 z
15946 }
15947}
15948
15949#[no_mangle]
15950pub unsafe extern "C" fn cprojf(z: (f32, f32)) -> (f32, f32) {
15951 if z.0.is_infinite() || z.1.is_infinite() {
15952 (f32::INFINITY, if z.1.is_sign_positive() { 0.0 } else { -0.0 })
15953 } else {
15954 z
15955 }
15956}
15957
15958#[no_mangle]
15959pub unsafe extern "C" fn cprojl(z: (f64, f64)) -> (f64, f64) {
15960 cproj(z)
15961}
15962
15963#[no_mangle]
15965pub unsafe extern "C" fn cexp(z: (f64, f64)) -> (f64, f64) {
15966 let r = libm::exp(z.0);
15967 (r * libm::cos(z.1), r * libm::sin(z.1))
15968}
15969
15970#[no_mangle]
15971pub unsafe extern "C" fn cexpf(z: (f32, f32)) -> (f32, f32) {
15972 let r = libm::expf(z.0);
15973 (r * libm::cosf(z.1), r * libm::sinf(z.1))
15974}
15975
15976#[no_mangle]
15977pub unsafe extern "C" fn cexpl(z: (f64, f64)) -> (f64, f64) {
15978 cexp(z)
15979}
15980
15981#[no_mangle]
15983pub unsafe extern "C" fn clog(z: (f64, f64)) -> (f64, f64) {
15984 (libm::log(cabs(z)), carg(z))
15985}
15986
15987#[no_mangle]
15988pub unsafe extern "C" fn clogf(z: (f32, f32)) -> (f32, f32) {
15989 (libm::logf(cabsf(z)), cargf(z))
15990}
15991
15992#[no_mangle]
15993pub unsafe extern "C" fn clogl(z: (f64, f64)) -> (f64, f64) {
15994 clog(z)
15995}
15996
15997#[no_mangle]
15999pub unsafe extern "C" fn csqrt(z: (f64, f64)) -> (f64, f64) {
16000 let r = cabs(z);
16001 let sign = if z.1 < 0.0 { -1.0 } else { 1.0 };
16002 (libm::sqrt((r + z.0) / 2.0), sign * libm::sqrt((r - z.0) / 2.0))
16003}
16004
16005#[no_mangle]
16006pub unsafe extern "C" fn csqrtf(z: (f32, f32)) -> (f32, f32) {
16007 let r = cabsf(z);
16008 let sign = if z.1 < 0.0 { -1.0f32 } else { 1.0f32 };
16009 (libm::sqrtf((r + z.0) / 2.0), sign * libm::sqrtf((r - z.0) / 2.0))
16010}
16011
16012#[no_mangle]
16013pub unsafe extern "C" fn csqrtl(z: (f64, f64)) -> (f64, f64) {
16014 csqrt(z)
16015}
16016
16017#[no_mangle]
16019pub unsafe extern "C" fn cpow(z: (f64, f64), w: (f64, f64)) -> (f64, f64) {
16020 let log_z = clog(z);
16021 let exp_arg = (w.0 * log_z.0 - w.1 * log_z.1, w.0 * log_z.1 + w.1 * log_z.0);
16022 cexp(exp_arg)
16023}
16024
16025#[no_mangle]
16026pub unsafe extern "C" fn cpowf(z: (f32, f32), w: (f32, f32)) -> (f32, f32) {
16027 let log_z = clogf(z);
16028 let exp_arg = (w.0 * log_z.0 - w.1 * log_z.1, w.0 * log_z.1 + w.1 * log_z.0);
16029 cexpf(exp_arg)
16030}
16031
16032#[no_mangle]
16033pub unsafe extern "C" fn cpowl(z: (f64, f64), w: (f64, f64)) -> (f64, f64) {
16034 cpow(z, w)
16035}
16036
16037#[no_mangle]
16039pub unsafe extern "C" fn ccos(z: (f64, f64)) -> (f64, f64) {
16040 (libm::cos(z.0) * libm::cosh(z.1), -libm::sin(z.0) * libm::sinh(z.1))
16041}
16042
16043#[no_mangle]
16044pub unsafe extern "C" fn ccosf(z: (f32, f32)) -> (f32, f32) {
16045 (libm::cosf(z.0) * libm::coshf(z.1), -libm::sinf(z.0) * libm::sinhf(z.1))
16046}
16047
16048#[no_mangle]
16049pub unsafe extern "C" fn ccosl(z: (f64, f64)) -> (f64, f64) {
16050 ccos(z)
16051}
16052
16053#[no_mangle]
16055pub unsafe extern "C" fn csin(z: (f64, f64)) -> (f64, f64) {
16056 (libm::sin(z.0) * libm::cosh(z.1), libm::cos(z.0) * libm::sinh(z.1))
16057}
16058
16059#[no_mangle]
16060pub unsafe extern "C" fn csinf(z: (f32, f32)) -> (f32, f32) {
16061 (libm::sinf(z.0) * libm::coshf(z.1), libm::cosf(z.0) * libm::sinhf(z.1))
16062}
16063
16064#[no_mangle]
16065pub unsafe extern "C" fn csinl(z: (f64, f64)) -> (f64, f64) {
16066 csin(z)
16067}
16068
16069#[no_mangle]
16071pub unsafe extern "C" fn ctan(z: (f64, f64)) -> (f64, f64) {
16072 let d = libm::cos(2.0 * z.0) + libm::cosh(2.0 * z.1);
16073 (libm::sin(2.0 * z.0) / d, libm::sinh(2.0 * z.1) / d)
16074}
16075
16076#[no_mangle]
16077pub unsafe extern "C" fn ctanf(z: (f32, f32)) -> (f32, f32) {
16078 let d = libm::cosf(2.0 * z.0) + libm::coshf(2.0 * z.1);
16079 (libm::sinf(2.0 * z.0) / d, libm::sinhf(2.0 * z.1) / d)
16080}
16081
16082#[no_mangle]
16083pub unsafe extern "C" fn ctanl(z: (f64, f64)) -> (f64, f64) {
16084 ctan(z)
16085}
16086
16087#[no_mangle]
16089pub unsafe extern "C" fn ccosh(z: (f64, f64)) -> (f64, f64) {
16090 (libm::cosh(z.0) * libm::cos(z.1), libm::sinh(z.0) * libm::sin(z.1))
16091}
16092
16093#[no_mangle]
16094pub unsafe extern "C" fn ccoshf(z: (f32, f32)) -> (f32, f32) {
16095 (libm::coshf(z.0) * libm::cosf(z.1), libm::sinhf(z.0) * libm::sinf(z.1))
16096}
16097
16098#[no_mangle]
16099pub unsafe extern "C" fn ccoshl(z: (f64, f64)) -> (f64, f64) {
16100 ccosh(z)
16101}
16102
16103#[no_mangle]
16105pub unsafe extern "C" fn csinh(z: (f64, f64)) -> (f64, f64) {
16106 (libm::sinh(z.0) * libm::cos(z.1), libm::cosh(z.0) * libm::sin(z.1))
16107}
16108
16109#[no_mangle]
16110pub unsafe extern "C" fn csinhf(z: (f32, f32)) -> (f32, f32) {
16111 (libm::sinhf(z.0) * libm::cosf(z.1), libm::coshf(z.0) * libm::sinf(z.1))
16112}
16113
16114#[no_mangle]
16115pub unsafe extern "C" fn csinhl(z: (f64, f64)) -> (f64, f64) {
16116 csinh(z)
16117}
16118
16119#[no_mangle]
16121pub unsafe extern "C" fn ctanh(z: (f64, f64)) -> (f64, f64) {
16122 let d = libm::cosh(2.0 * z.0) + libm::cos(2.0 * z.1);
16123 (libm::sinh(2.0 * z.0) / d, libm::sin(2.0 * z.1) / d)
16124}
16125
16126#[no_mangle]
16127pub unsafe extern "C" fn ctanhf(z: (f32, f32)) -> (f32, f32) {
16128 let d = libm::coshf(2.0 * z.0) + libm::cosf(2.0 * z.1);
16129 (libm::sinhf(2.0 * z.0) / d, libm::sinf(2.0 * z.1) / d)
16130}
16131
16132#[no_mangle]
16133pub unsafe extern "C" fn ctanhl(z: (f64, f64)) -> (f64, f64) {
16134 ctanh(z)
16135}
16136
16137#[no_mangle]
16140pub unsafe extern "C" fn cacos(z: (f64, f64)) -> (f64, f64) {
16141 let asin_z = casin(z);
16142 (3.14159265358979323846264338327950288419716939937510582097494459230781640 / 2.0 - asin_z.0, -asin_z.1)
16143}
16144
16145#[no_mangle]
16146pub unsafe extern "C" fn cacosf(z: (f32, f32)) -> (f32, f32) {
16147 let asin_z = casinf(z);
16148 (3.14159265358979323846264338327950288419716939937510582097494459230781640f32 / 2.0 - asin_z.0, -asin_z.1)
16149}
16150
16151#[no_mangle]
16152pub unsafe extern "C" fn cacosl(z: (f64, f64)) -> (f64, f64) {
16153 cacos(z)
16154}
16155
16156#[no_mangle]
16158pub unsafe extern "C" fn casin(z: (f64, f64)) -> (f64, f64) {
16159 let iz = (-z.1, z.0);
16161 let one_minus_z2 = (1.0 - z.0 * z.0 + z.1 * z.1, -2.0 * z.0 * z.1);
16163 let sqrt_val = csqrt(one_minus_z2);
16164 let arg = clog((iz.0 + sqrt_val.0, iz.1 + sqrt_val.1));
16165 (arg.1, -arg.0)
16167}
16168
16169#[no_mangle]
16170pub unsafe extern "C" fn casinf(z: (f32, f32)) -> (f32, f32) {
16171 let iz = (-z.1, z.0);
16172 let one_minus_z2 = (1.0 - z.0 * z.0 + z.1 * z.1, -2.0 * z.0 * z.1);
16173 let sqrt_val = csqrtf(one_minus_z2);
16174 let arg = clogf((iz.0 + sqrt_val.0, iz.1 + sqrt_val.1));
16175 (arg.1, -arg.0)
16176}
16177
16178#[no_mangle]
16179pub unsafe extern "C" fn casinl(z: (f64, f64)) -> (f64, f64) {
16180 casin(z)
16181}
16182
16183#[no_mangle]
16185pub unsafe extern "C" fn catan(z: (f64, f64)) -> (f64, f64) {
16186 let num = (1.0 + z.1, -z.0);
16190 let den = (1.0 - z.1, z.0);
16191 let ratio = cdiv(num, den);
16192 let log_ratio = clog(ratio);
16193 (-log_ratio.1 / 2.0, log_ratio.0 / 2.0)
16195}
16196
16197#[no_mangle]
16198pub unsafe extern "C" fn catanf(z: (f32, f32)) -> (f32, f32) {
16199 let num = (1.0 + z.1, -z.0);
16200 let den = (1.0 - z.1, z.0);
16201 let ratio = cdivf(num, den);
16202 let log_ratio = clogf(ratio);
16203 (-log_ratio.1 / 2.0, log_ratio.0 / 2.0)
16204}
16205
16206#[no_mangle]
16207pub unsafe extern "C" fn catanl(z: (f64, f64)) -> (f64, f64) {
16208 catan(z)
16209}
16210
16211fn cdiv(a: (f64, f64), b: (f64, f64)) -> (f64, f64) {
16213 let d = b.0 * b.0 + b.1 * b.1;
16214 ((a.0 * b.0 + a.1 * b.1) / d, (a.1 * b.0 - a.0 * b.1) / d)
16215}
16216
16217fn cdivf(a: (f32, f32), b: (f32, f32)) -> (f32, f32) {
16218 let d = b.0 * b.0 + b.1 * b.1;
16219 ((a.0 * b.0 + a.1 * b.1) / d, (a.1 * b.0 - a.0 * b.1) / d)
16220}
16221
16222#[no_mangle]
16224pub unsafe extern "C" fn cacosh(z: (f64, f64)) -> (f64, f64) {
16225 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16226 let z2_minus_1 = (z2.0 - 1.0, z2.1);
16227 let sqrt_val = csqrt(z2_minus_1);
16228 clog((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16229}
16230
16231#[no_mangle]
16232pub unsafe extern "C" fn cacoshf(z: (f32, f32)) -> (f32, f32) {
16233 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16234 let z2_minus_1 = (z2.0 - 1.0, z2.1);
16235 let sqrt_val = csqrtf(z2_minus_1);
16236 clogf((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16237}
16238
16239#[no_mangle]
16240pub unsafe extern "C" fn cacoshl(z: (f64, f64)) -> (f64, f64) {
16241 cacosh(z)
16242}
16243
16244#[no_mangle]
16246pub unsafe extern "C" fn casinh(z: (f64, f64)) -> (f64, f64) {
16247 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16248 let z2_plus_1 = (z2.0 + 1.0, z2.1);
16249 let sqrt_val = csqrt(z2_plus_1);
16250 clog((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16251}
16252
16253#[no_mangle]
16254pub unsafe extern "C" fn casinhf(z: (f32, f32)) -> (f32, f32) {
16255 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16256 let z2_plus_1 = (z2.0 + 1.0, z2.1);
16257 let sqrt_val = csqrtf(z2_plus_1);
16258 clogf((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16259}
16260
16261#[no_mangle]
16262pub unsafe extern "C" fn casinhl(z: (f64, f64)) -> (f64, f64) {
16263 casinh(z)
16264}
16265
16266#[no_mangle]
16268pub unsafe extern "C" fn catanh(z: (f64, f64)) -> (f64, f64) {
16269 let num = (1.0 + z.0, z.1);
16270 let den = (1.0 - z.0, -z.1);
16271 let ratio = cdiv(num, den);
16272 let log_ratio = clog(ratio);
16273 (log_ratio.0 / 2.0, log_ratio.1 / 2.0)
16274}
16275
16276#[no_mangle]
16277pub unsafe extern "C" fn catanhf(z: (f32, f32)) -> (f32, f32) {
16278 let num = (1.0 + z.0, z.1);
16279 let den = (1.0 - z.0, -z.1);
16280 let ratio = cdivf(num, den);
16281 let log_ratio = clogf(ratio);
16282 (log_ratio.0 / 2.0, log_ratio.1 / 2.0)
16283}
16284
16285#[no_mangle]
16286pub unsafe extern "C" fn catanhl(z: (f64, f64)) -> (f64, f64) {
16287 catanh(z)
16288}
16289
16290#[inline(never)]
16295#[no_mangle]
16296pub unsafe extern "C" fn fmaxf(x: f32, y: f32) -> f32 {
16297 fmaxf_impl(x, y)
16298}
16299
16300#[no_mangle]
16301pub unsafe extern "C" fn fdimf(x: f32, y: f32) -> f32 {
16302 if x.is_nan() || y.is_nan() {
16303 return f32::NAN;
16304 }
16305 if x > y { x - y } else { 0.0 }
16306}
16307
16308#[no_mangle]
16309pub unsafe extern "C" fn fmaf(x: f32, y: f32, z: f32) -> f32 {
16310 if (x.is_infinite() && y == 0.0) || (y.is_infinite() && x == 0.0) {
16311 feraiseexcept(FE_INVALID);
16312 return f32::NAN;
16313 }
16314 if x.is_nan() || y.is_nan() || z.is_nan() {
16315 return f32::NAN;
16316 }
16317 let r = libm::fmaf(x, y, z);
16318 if r.is_nan() {
16319 feraiseexcept(FE_INVALID);
16320 }
16321 r
16322}
16323
16324#[no_mangle]
16325pub unsafe extern "C" fn ilogbf(x: f32) -> i32 {
16326 if x.is_nan() {
16327 feraiseexcept(FE_INVALID);
16328 return -0x7fffffff - 1;
16329 }
16330 if x == 0.0 || x.is_infinite() {
16331 feraiseexcept(FE_INVALID);
16332 return if x == 0.0 { -0x7fffffff - 1 } else { 0x7fffffff };
16333 }
16334 let bits = x.to_bits();
16335 let exp = ((bits >> 23) & 0xff) as i32;
16336 if exp == 0 {
16337 let mut v = bits & 0x7fffff;
16338 let mut e = -126;
16339 while v < (1u32 << 23) { v <<= 1; e -= 1; }
16340 e
16341 } else {
16342 exp - 127
16343 }
16344}
16345
16346#[no_mangle]
16347pub unsafe extern "C" fn logbf(x: f32) -> f32 {
16348 if x.is_nan() { return x; }
16349 if x == 0.0 { return __math_divzerof(1); }
16350 let bits = x.to_bits();
16351 let exp = ((bits >> 23) & 0xff) as i32;
16352 if exp == 0 {
16353 let mut v = bits & 0x7fffff;
16354 let mut e = -126i32;
16355 while v < (1u32 << 23) { v <<= 1; e -= 1; }
16356 e as f32
16357 } else if exp == 0xff {
16358 x * x
16359 } else {
16360 (exp - 127) as f32
16361 }
16362}
16363
16364#[no_mangle]
16365pub unsafe extern "C" fn nearbyintf(x: f32) -> f32 {
16366 let had_inexact = fetestexcept(FE_INEXACT) & FE_INEXACT != 0;
16367 let r = libm::rintf(x);
16368 if !had_inexact {
16369 feclearexcept(FE_INEXACT);
16370 }
16371 r
16372}
16373
16374#[no_mangle]
16375pub unsafe extern "C" fn nextafterf(x: f32, y: f32) -> f32 {
16376 if x.is_nan() || y.is_nan() { return x + y; }
16377 if x == 0.0 && y == 0.0 { return y; }
16378 if x == y { return x; }
16379 let r = libm::nextafterf(x, y);
16380 if r.is_infinite() && x.is_finite() {
16381 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
16382 } else if r != x {
16383 let bits = r.to_bits();
16384 let is_subnormal = (bits & 0x7f800000) == 0 && (bits & 0x7fffff) != 0;
16385 if r == 0.0 || is_subnormal {
16386 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16387 }
16388 }
16389 r
16390}
16391
16392#[no_mangle]
16393#[cfg(target_arch = "x86_64")]
16394pub unsafe extern "C" fn nexttowardf(x: f32, y: f64) -> f32 {
16395 if y.is_nan() { return (x as f64 + y) as f32; }
16396 if x == 0.0 && y == 0.0 {
16397 return if y.is_sign_negative() { -0.0 } else { 0.0 };
16398 }
16399 if (x as f64) == y { return x; }
16400 nextafterf(x, if y > x as f64 { f32::INFINITY } else { f32::NEG_INFINITY })
16401}
16402
16403#[no_mangle]
16404#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
16405pub unsafe extern "C" fn nexttowardf(x: f32, y: f128) -> f32 {
16406 if y.is_nan() { return (x as f128 + y) as f32; }
16407 if (x as f128) == y { return x; }
16408 nextafterf(x, if y > x as f128 { f32::INFINITY } else { f32::NEG_INFINITY })
16409}
16410
16411#[no_mangle]
16412pub unsafe extern "C" fn remainderf(x: f32, y: f32) -> f32 {
16413 if x.is_nan() || y.is_nan() { return x + y; }
16414 if y == 0.0 || x.is_infinite() { return __math_invalidf(x); }
16415 libm::remainderf(x, y)
16416}
16417
16418#[no_mangle]
16419pub unsafe extern "C" fn remquof(x: f32, y: f32, quo: *mut i32) -> f32 {
16420 if x.is_nan() || y.is_nan() {
16421 if !quo.is_null() { *quo = 0; }
16422 return x + y;
16423 }
16424 if y == 0.0 || x.is_infinite() {
16425 if !quo.is_null() { *quo = 0; }
16426 return __math_invalidf(x);
16427 }
16428 let (r, q) = libm::remquof(x, y);
16429 if !quo.is_null() { *quo = q; }
16430 r
16431}
16432
16433#[no_mangle]
16434pub unsafe extern "C" fn exp2f(x: f32) -> f32 {
16435 if x == f32::INFINITY { return f32::INFINITY; }
16436 if x == f32::NEG_INFINITY { return 0.0; }
16437 if x.is_nan() { return f32::NAN; }
16438 let r = libm::exp2f(x);
16439 if r.is_infinite() && x.is_finite() {
16440 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
16441 } else if r == 0.0 && x < -149.0 {
16442 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16443 } else if r != 0.0 && x != libm::truncf(x) {
16444 let bits = r.to_bits();
16445 if (bits & 0x7f800000) == 0 {
16446 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16447 }
16448 }
16449 r
16450}
16451
16452#[no_mangle]
16453pub unsafe extern "C" fn expm1f(x: f32) -> f32 {
16454 libm::expm1f(x)
16455}
16456
16457#[no_mangle]
16458pub unsafe extern "C" fn log1pf(x: f32) -> f32 {
16459 if x == -1.0 {
16460 feraiseexcept(FE_DIVBYZERO);
16461 return f32::NEG_INFINITY;
16462 }
16463 libm::log1pf(x)
16464}
16465
16466#[no_mangle]
16467pub unsafe extern "C" fn acoshf(x: f32) -> f32 {
16468 if x < 1.0 {
16469 feraiseexcept(FE_INVALID);
16470 return f32::NAN;
16471 }
16472 libm::acoshf(x)
16473}
16474
16475#[no_mangle]
16476pub unsafe extern "C" fn asinhf(x: f32) -> f32 {
16477 if x == 0.0 { return x; }
16478 libm::asinhf(x)
16479}
16480
16481#[no_mangle]
16482pub unsafe extern "C" fn atanhf(x: f32) -> f32 {
16483 if x == 0.0 { return x; }
16484 let e = ((x.to_bits() >> 23) & 0xff) as i32;
16485 if e < 0x7f - 32 {
16486 feraiseexcept(FE_INEXACT);
16487 if e == 0 { feraiseexcept(FE_UNDERFLOW); }
16488 return x;
16489 }
16490 if x == 1.0 {
16491 feraiseexcept(FE_DIVBYZERO);
16492 return f32::INFINITY;
16493 }
16494 if x == -1.0 {
16495 feraiseexcept(FE_DIVBYZERO);
16496 return f32::NEG_INFINITY;
16497 }
16498 if x.is_nan() { return x; }
16499 let ax = libm::fabsf(x);
16500 if ax > 1.0 {
16501 feraiseexcept(FE_INVALID);
16502 return f32::NAN;
16503 }
16504 if ax < 0.5 {
16505 let r = libm::log1pf(2.0 * (ax + ax * ax / (1.0 - ax))) / 2.0;
16506 if x < 0.0 { -r } else { r }
16507 } else {
16508 let r = 0.5 * libm::logf((1.0 + ax) / (1.0 - ax));
16509 if x < 0.0 { -r } else { r }
16510 }
16511}
16512
16513#[no_mangle]
16514pub unsafe extern "C" fn cbrtf(x: f32) -> f32 {
16515 libm::cbrtf(x)
16516}
16517
16518#[no_mangle]
16519pub unsafe extern "C" fn erff(x: f32) -> f32 {
16520 libm::erff(x)
16521}
16522
16523#[no_mangle]
16524pub unsafe extern "C" fn erfcf(x: f32) -> f32 {
16525 libm::erfcf(x)
16526}
16527
16528#[no_mangle]
16529pub unsafe extern "C" fn lgammaf(x: f32) -> f32 {
16530 if x.is_nan() {
16531 crate::signgam = 1;
16532 return x;
16533 }
16534 if x == 0.0 {
16535 crate::signgam = if x.is_sign_negative() { -1 } else { 1 };
16536 feraiseexcept(FE_DIVBYZERO);
16537 return f32::INFINITY;
16538 }
16539 let (r, sign) = libm::lgammaf_r(x);
16540 crate::signgam = sign;
16541 r
16542}
16543
16544#[no_mangle]
16545pub unsafe extern "C" fn tgammaf(x: f32) -> f32 {
16546 if x.is_nan() { return x; }
16547 if x == 0.0 {
16548 feraiseexcept(FE_DIVBYZERO);
16549 return if x.is_sign_negative() { f32::NEG_INFINITY } else { f32::INFINITY };
16550 }
16551 if x.is_infinite() {
16552 return if x.is_sign_negative() { __math_invalidf(x) } else { f32::INFINITY };
16553 }
16554 if x < 0.0 && x == libm::floorf(x) {
16555 feraiseexcept(FE_INVALID);
16556 return f32::NAN;
16557 }
16558 libm::tgammaf(x)
16559}
16560
16561#[no_mangle]
16562pub unsafe extern "C" fn lroundf(x: f32) -> core::ffi::c_long {
16563 libm::roundf(x) as core::ffi::c_long
16564}
16565
16566#[no_mangle]
16567pub unsafe extern "C" fn llroundf(x: f32) -> i64 {
16568 libm::roundf(x) as i64
16569}
16570
16571#[no_mangle]
16576pub unsafe extern "C" fn wcscasecmp(s1: *const u32, s2: *const u32) -> i32 {
16577 let mut i = 0;
16578 loop {
16579 let c1 = *s1.add(i);
16580 let c2 = *s2.add(i);
16581 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16582 let l1 = if c1 >= 'A' as u32 && c1 <= 'Z' as u32 { c1 + 32 } else { c1 };
16583 let l2 = if c2 >= 'A' as u32 && c2 <= 'Z' as u32 { c2 + 32 } else { c2 };
16584 if l1 != l2 { return (l1 as i32) - (l2 as i32); }
16585 i += 1;
16586 }
16587}
16588
16589#[no_mangle]
16590pub unsafe extern "C" fn wcscasecmp_l(s1: *const u32, s2: *const u32, _loc: *mut core::ffi::c_void) -> i32 {
16591 wcscasecmp(s1, s2)
16592}
16593
16594#[no_mangle]
16595pub unsafe extern "C" fn wcsncasecmp(s1: *const u32, s2: *const u32, n: usize) -> i32 {
16596 let mut i = 0;
16597 while i < n {
16598 let c1 = *s1.add(i);
16599 let c2 = *s2.add(i);
16600 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16601 let l1 = if c1 >= 'A' as u32 && c1 <= 'Z' as u32 { c1 + 32 } else { c1 };
16602 let l2 = if c2 >= 'A' as u32 && c2 <= 'Z' as u32 { c2 + 32 } else { c2 };
16603 if l1 != l2 { return (l1 as i32) - (l2 as i32); }
16604 i += 1;
16605 }
16606 0
16607}
16608
16609#[no_mangle]
16610pub unsafe extern "C" fn wcsncasecmp_l(s1: *const u32, s2: *const u32, n: usize, _loc: *mut core::ffi::c_void) -> i32 {
16611 wcsncasecmp(s1, s2, n)
16612}
16613
16614#[no_mangle]
16615pub unsafe extern "C" fn wcscoll(s1: *const u32, s2: *const u32) -> i32 {
16616 let mut i = 0;
16618 loop {
16619 let c1 = *s1.add(i);
16620 let c2 = *s2.add(i);
16621 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16622 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
16623 i += 1;
16624 }
16625}
16626
16627#[no_mangle]
16628pub unsafe extern "C" fn wcstok(s: *mut u32, sep: *const u32, p: *mut *mut u32) -> *mut u32 {
16629 let mut src = if s.is_null() { *p } else { s };
16630 while *src != 0 && *sep.add(0) == *src { src = src.add(1); }
16632 if *src == 0 { return core::ptr::null_mut(); }
16633 let start = src;
16634 while *src != 0 && *sep.add(0) != *src { src = src.add(1); }
16636 if *src != 0 {
16637 *src = 0;
16638 *p = src.add(1);
16639 } else {
16640 *p = src;
16641 }
16642 start
16643}
16644
16645#[no_mangle]
16646pub unsafe extern "C" fn wcswcs(haystack: *const u32, needle: *const u32) -> *mut u32 {
16647 if *needle == 0 { return haystack as *mut u32; }
16648 let mut i = 0;
16649 while *haystack.add(i) != 0 {
16650 let mut j = 0;
16651 while *needle.add(j) != 0 && *haystack.add(i + j) == *needle.add(j) {
16652 j += 1;
16653 }
16654 if *needle.add(j) == 0 { return haystack.add(i) as *mut u32; }
16655 i += 1;
16656 }
16657 core::ptr::null_mut()
16658}
16659
16660#[no_mangle]
16661pub unsafe extern "C" fn wcswidth(s: *const u32, n: usize) -> i32 {
16662 let mut width = 0i32;
16663 let mut i = 0;
16664 while i < n {
16665 let c = *s.add(i);
16666 if c == 0 { break; }
16667 width += 1;
16669 i += 1;
16670 }
16671 width
16672}
16673
16674#[no_mangle]
16675pub unsafe extern "C" fn wcsftime(s: *mut u32, maxsize: usize, fmt: *const u32, tm: *const c_void) -> usize {
16676 if s.is_null() || fmt.is_null() || maxsize == 0 { return 0; }
16677 let mut cfmt = [0u8; 1024];
16680 let mut o = 0usize;
16681 let mut i = 0usize;
16682 let mut st: c_uint = 0;
16683 while *fmt.add(i) != 0 && o + 8 < cfmt.len() {
16684 let n = wcrtomb(
16685 cfmt.as_mut_ptr().add(o) as *mut c_char,
16686 *fmt.add(i) as c_int,
16687 &mut st as *mut c_uint,
16688 );
16689 if n == !0usize { return 0; }
16690 o += n;
16691 i += 1;
16692 }
16693 cfmt[o] = 0;
16694 let mut out = [0u8; 4096];
16695 let mut lim = maxsize.saturating_mul(4);
16696 if lim > out.len() { lim = out.len(); }
16697 let n = strftime(out.as_mut_ptr() as *mut c_char, lim, cfmt.as_ptr() as *const c_char, tm as *const tm);
16698 if n == 0 { return 0; }
16699 let mut ws = 0usize;
16700 let mut p = 0usize;
16701 while p < n && ws + 1 < maxsize {
16702 let mut wc: c_int = 0;
16703 let mut st2: c_uint = 0;
16704 let r = mbrtowc(&mut wc, out.as_ptr().add(p) as *const c_char, n - p, &mut st2);
16705 if r == !0usize { return 0; }
16706 if r == 0 || r == !1usize { break; }
16707 *s.add(ws) = wc as u32;
16708 ws += 1;
16709 p += r;
16710 }
16711 *s.add(ws) = 0;
16712 ws
16713}
16714
16715#[no_mangle]
16716pub unsafe extern "C" fn mbsnrtowcs(
16717 dst: *mut u32,
16718 src: *mut *const u8,
16719 nms: usize,
16720 len: usize,
16721 st: *mut core::ffi::c_void,
16722) -> usize {
16723 if src.is_null() { return 0; }
16724 let mut s = *src;
16725 if s.is_null() { return 0; }
16726 let state = st as *mut c_uint;
16727 let limit = if dst.is_null() { usize::MAX } else { len };
16728 let mut count = 0usize;
16729 let mut n = nms;
16730 while count < limit && n > 0 {
16731 let c = *s;
16732 if c == 0 {
16733 if !dst.is_null() {
16734 if count < len { *dst.add(count) = 0; }
16735 *src = core::ptr::null();
16736 }
16737 return count;
16738 }
16739 let mut wc: c_int = 0;
16740 let r = mbrtowc(&mut wc, s as *const c_char, n, state);
16741 if r == !0usize {
16742 *src = s;
16743 return !0usize;
16744 }
16745 if r == !1usize { break; }
16746 if !dst.is_null() { *dst.add(count) = wc as u32; }
16747 count += 1;
16748 s = s.add(r);
16749 n -= r;
16750 }
16751 *src = s;
16752 count
16753}
16754
16755#[no_mangle]
16756pub unsafe extern "C" fn wcsnrtombs(dst: *mut u8, src: *mut *const u32, nwc: usize, len: usize, _st: *mut core::ffi::c_void) -> usize {
16757 let mut count = 0;
16758 let mut s = *src;
16759 let mut d = dst;
16760 while count < len && count < nwc {
16761 let c = *s;
16762 if c == 0 { break; }
16763 if !d.is_null() {
16764 if c < 0x80 {
16765 *d = c as u8;
16766 d = d.add(1);
16767 count += 1;
16768 } else if c < 0x800 {
16769 if count + 2 > len { break; }
16770 *d = 0xc0 | (c >> 6) as u8;
16771 *d.add(1) = 0x80 | (c & 0x3f) as u8;
16772 d = d.add(2);
16773 count += 2;
16774 } else if c < 0x10000 {
16775 if count + 3 > len { break; }
16776 *d = 0xe0 | (c >> 12) as u8;
16777 *d.add(1) = 0x80 | ((c >> 6) & 0x3f) as u8;
16778 *d.add(2) = 0x80 | (c & 0x3f) as u8;
16779 d = d.add(3);
16780 count += 3;
16781 } else {
16782 if count + 4 > len { break; }
16783 *d = 0xf0 | (c >> 18) as u8;
16784 *d.add(1) = 0x80 | ((c >> 12) & 0x3f) as u8;
16785 *d.add(2) = 0x80 | ((c >> 6) & 0x3f) as u8;
16786 *d.add(3) = 0x80 | (c & 0x3f) as u8;
16787 d = d.add(4);
16788 count += 4;
16789 }
16790 }
16791 s = s.add(1);
16792 }
16793 if !dst.is_null() { *src = s; }
16794 count
16795}
16796
16797pub type thrd_start_t = Option<unsafe extern "C" fn(arg: *mut core::ffi::c_void) -> i32>;
16804
16805#[no_mangle]
16807pub unsafe extern "C" fn thrd_create(thr: *mut usize, func: thrd_start_t, arg: *mut core::ffi::c_void) -> i32 {
16808 let mut thread: u64 = 0;
16809 let r = pthread_create(&mut thread, core::ptr::null(), core::mem::transmute(func), arg);
16810 if r == 0 {
16811 *thr = thread as usize;
16812 0 } else {
16814 -1 }
16816}
16817
16818#[no_mangle]
16819pub unsafe extern "C" fn thrd_join(thr: usize, res: *mut i32) -> i32 {
16820 let mut retval: *mut core::ffi::c_void = core::ptr::null_mut();
16821 let r = pthread_join(thr as u64, &mut retval);
16822 if r == 0 {
16823 if !res.is_null() { *res = retval as i32; }
16824 0
16825 } else {
16826 -1
16827 }
16828}
16829
16830#[no_mangle]
16831pub unsafe extern "C" fn thrd_exit(res: i32) {
16832 pthread_exit(res as *mut core::ffi::c_void);
16833}
16834
16835#[no_mangle]
16836pub unsafe extern "C" fn thrd_detach(thr: usize) -> i32 {
16837 let r = pthread_detach(thr as u64);
16838 if r == 0 { 0 } else { -1 }
16839}
16840
16841#[no_mangle]
16842pub unsafe extern "C" fn thrd_current() -> usize {
16843 pthread_self() as usize
16844}
16845
16846#[no_mangle]
16847pub unsafe extern "C" fn thrd_equal(thr1: usize, thr2: usize) -> i32 {
16848 (thr1 == thr2) as i32
16849}
16850
16851#[no_mangle]
16852pub unsafe extern "C" fn thrd_sleep(duration: *const core::ffi::c_void, remaining: *mut core::ffi::c_void) -> i32 {
16853 nanosleep(duration as *const timespec, remaining as *mut timespec)
16854}
16855
16856#[no_mangle]
16857pub unsafe extern "C" fn thrd_yield() {
16858 sched_yield();
16859}
16860
16861#[no_mangle]
16863pub unsafe extern "C" fn mtx_init(mtx: *mut usize, _mtx_type: i32) -> i32 {
16864 let r = pthread_mutex_init(mtx as *mut pthread_mutex_t, core::ptr::null());
16865 if r == 0 { 0 } else { -1 }
16866}
16867
16868#[no_mangle]
16869pub unsafe extern "C" fn mtx_lock(mtx: *mut usize) -> i32 {
16870 let r = pthread_mutex_lock(mtx as *mut pthread_mutex_t);
16871 if r == 0 { 0 } else { -1 }
16872}
16873
16874#[no_mangle]
16875pub unsafe extern "C" fn mtx_trylock(mtx: *mut usize) -> i32 {
16876 let r = pthread_mutex_trylock(mtx as *mut pthread_mutex_t);
16877 if r == 0 { 0 } else { -1 }
16878}
16879
16880#[no_mangle]
16881pub unsafe extern "C" fn mtx_unlock(mtx: *mut usize) -> i32 {
16882 let r = pthread_mutex_unlock(mtx as *mut pthread_mutex_t);
16883 if r == 0 { 0 } else { -1 }
16884}
16885
16886#[no_mangle]
16887pub unsafe extern "C" fn mtx_destroy(mtx: *mut usize) {
16888 pthread_mutex_destroy(mtx as *mut pthread_mutex_t);
16889}
16890
16891#[no_mangle]
16892pub unsafe extern "C" fn mtx_timedlock(mtx: *mut usize, ts: *const core::ffi::c_void) -> i32 {
16893 let r = pthread_mutex_timedlock(mtx as *mut pthread_mutex_t, ts as *const timespec);
16894 if r == 0 { 0 } else { -1 }
16895}
16896
16897#[no_mangle]
16899pub unsafe extern "C" fn cnd_init(cnd: *mut usize) -> i32 {
16900 let r = pthread_cond_init(cnd as *mut pthread_cond_t, core::ptr::null());
16901 if r == 0 { 0 } else { -1 }
16902}
16903
16904#[no_mangle]
16905pub unsafe extern "C" fn cnd_signal(cnd: *mut usize) -> i32 {
16906 let r = pthread_cond_signal(cnd as *mut pthread_cond_t);
16907 if r == 0 { 0 } else { -1 }
16908}
16909
16910#[no_mangle]
16911pub unsafe extern "C" fn cnd_broadcast(cnd: *mut usize) -> i32 {
16912 let r = pthread_cond_broadcast(cnd as *mut pthread_cond_t);
16913 if r == 0 { 0 } else { -1 }
16914}
16915
16916#[no_mangle]
16917pub unsafe extern "C" fn cnd_wait(cnd: *mut usize, mtx: *mut usize) -> i32 {
16918 let r = pthread_cond_wait(cnd as *mut pthread_cond_t, mtx as *mut pthread_mutex_t);
16919 if r == 0 { 0 } else { -1 }
16920}
16921
16922#[no_mangle]
16923pub unsafe extern "C" fn cnd_timedwait(cnd: *mut usize, mtx: *mut usize, ts: *const core::ffi::c_void) -> i32 {
16924 let r = pthread_cond_timedwait(cnd as *mut pthread_cond_t, mtx as *mut pthread_mutex_t, ts as *const timespec);
16925 if r == 0 { 0 } else { -1 }
16926}
16927
16928#[no_mangle]
16929pub unsafe extern "C" fn cnd_destroy(cnd: *mut usize) {
16930 pthread_cond_destroy(cnd as *mut pthread_cond_t);
16931}
16932
16933#[no_mangle]
16935pub unsafe extern "C" fn tss_create(key: *mut u32, dtor: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>) -> i32 {
16936 let r = pthread_key_create(key, dtor);
16937 if r == 0 { 0 } else { -1 }
16938}
16939
16940#[no_mangle]
16941pub unsafe extern "C" fn tss_delete(key: u32) {
16942 pthread_key_delete(key);
16943}
16944
16945#[no_mangle]
16946pub unsafe extern "C" fn tss_set(key: u32, val: *mut core::ffi::c_void) -> i32 {
16947 let r = pthread_setspecific(key, val);
16948 if r == 0 { 0 } else { -1 }
16949}
16950
16951#[no_mangle]
16952pub unsafe extern "C" fn tss_get(key: u32) -> *mut core::ffi::c_void {
16953 pthread_getspecific(key)
16954}
16955
16956#[no_mangle]
16958pub unsafe extern "C" fn call_once(flag: *mut u32, func: Option<unsafe extern "C" fn()>) {
16959 if *flag == 0 {
16960 if let Some(f) = func { f(); }
16961 *flag = 1;
16962 }
16963}
16964
16965#[no_mangle]
16971pub unsafe extern "C" fn accept4(fd: i32, addr: *mut core::ffi::c_void, addrlen: *mut u32, flags: i32) -> i32 {
16972 syscall_ret(<Arch as Syscalls>::syscall4(SYS_ACCEPT4, fd as i64, addr as i64, addrlen as i64, flags as i64)) as i32
16973}
16974
16975#[no_mangle]
16981pub unsafe extern "C" fn epoll_create(size: i32) -> i32 {
16982 #[cfg(target_arch = "x86_64")]
16983 { syscall_ret(<Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE, size as i64)) as i32 }
16984 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
16985 {
16986 if size < 1 {
16987 ERRNO!() = EINVAL;
16988 return -1;
16989 }
16990 syscall_ret(<Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE1, 0)) as i32
16991 }
16992}
16993
16994#[no_mangle]
16995pub unsafe extern "C" fn epoll_create1(flags: i32) -> i32 {
16996 syscall_ret(<Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE1, flags as i64)) as i32
16997}
16998
16999#[no_mangle]
17000pub unsafe extern "C" fn epoll_ctl(epfd: i32, op: i32, fd: i32, event: *mut core::ffi::c_void) -> i32 {
17001 syscall_ret(<Arch as Syscalls>::syscall4(SYS_EPOLL_CTL, epfd as i64, op as i64, fd as i64, event as i64)) as i32
17002}
17003
17004#[no_mangle]
17005pub unsafe extern "C" fn epoll_wait(epfd: i32, events: *mut core::ffi::c_void, maxevents: i32, timeout: i32) -> i32 {
17006 #[cfg(target_arch = "x86_64")]
17007 {
17008 syscall_ret(<Arch as Syscalls>::syscall4(
17009 SYS_EPOLL_WAIT,
17010 epfd as i64,
17011 events as i64,
17012 maxevents as i64,
17013 timeout as i64,
17014 )) as i32
17015 }
17016 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
17017 {
17018 epoll_pwait(epfd, events, maxevents, timeout, core::ptr::null())
17019 }
17020}
17021
17022#[no_mangle]
17023pub unsafe extern "C" fn epoll_pwait(
17024 epfd: i32,
17025 events: *mut core::ffi::c_void,
17026 maxevents: i32,
17027 timeout: i32,
17028 sigmask: *const u64,
17029) -> i32 {
17030 syscall_ret(<Arch as Syscalls>::syscall6(
17031 SYS_EPOLL_PWAIT,
17032 epfd as i64,
17033 events as i64,
17034 maxevents as i64,
17035 timeout as i64,
17036 sigmask as i64,
17037 8,
17038 )) as i32
17039}
17040
17041#[no_mangle]
17042pub unsafe extern "C" fn eventfd(initval: u32, flags: i32) -> i32 {
17043 syscall_ret(<Arch as Syscalls>::syscall2(SYS_EVENTFD2, initval as i64, flags as i64)) as i32
17044}
17045
17046#[no_mangle]
17047pub unsafe extern "C" fn eventfd_read(fd: i32, value: *mut u64) -> i32 {
17048 let n = crate::read(fd, value as *mut core::ffi::c_void, 8);
17049 if n == 8 { 0 } else { -1 }
17050}
17051
17052#[no_mangle]
17053pub unsafe extern "C" fn eventfd_write(fd: i32, value: u64) -> i32 {
17054 let n = crate::write(fd, &value as *const u64 as *const core::ffi::c_void, 8);
17055 if n == 8 { 0 } else { -1 }
17056}
17057
17058#[no_mangle]
17059pub unsafe extern "C" fn signalfd(fd: i32, mask: *const u64, flags: i32) -> i32 {
17060 syscall_ret(<Arch as Syscalls>::syscall4(SYS_SIGNALFD4, fd as i64, mask as i64, 8, flags as i64)) as i32
17061}
17062
17063#[no_mangle]
17064pub unsafe extern "C" fn timerfd_create(clockid: i32, flags: i32) -> i32 {
17065 syscall_ret(<Arch as Syscalls>::syscall2(SYS_TIMERFD_CREATE, clockid as i64, flags as i64)) as i32
17066}
17067
17068#[no_mangle]
17069pub unsafe extern "C" fn timerfd_settime(fd: i32, flags: i32, new_value: *const core::ffi::c_void, old_value: *mut core::ffi::c_void) -> i32 {
17070 syscall_ret(<Arch as Syscalls>::syscall4(SYS_TIMERFD_SETTIME, fd as i64, flags as i64, new_value as i64, old_value as i64)) as i32
17071}
17072
17073#[no_mangle]
17074pub unsafe extern "C" fn timerfd_gettime(fd: i32, curr_value: *mut core::ffi::c_void) -> i32 {
17075 syscall_ret(<Arch as Syscalls>::syscall2(SYS_TIMERFD_GETTIME, fd as i64, curr_value as i64)) as i32
17076}
17077
17078#[no_mangle]
17083pub unsafe extern "C" fn prctl(option: i32, mut args: ...) -> i32 {
17084 let a1 = args.next_arg::<i64>();
17085 let a2 = args.next_arg::<i64>();
17086 let a3 = args.next_arg::<i64>();
17087 let a4 = args.next_arg::<i64>();
17088 syscall_ret(<Arch as Syscalls>::syscall5(SYS_PRCTL, option as i64, a1, a2, a3, a4)) as i32
17089}
17090
17091#[no_mangle]
17092pub unsafe extern "C" fn quotactl(cmd: i32, special: *const core::ffi::c_char, id: i32, addr: *mut core::ffi::c_char) -> i32 {
17093 syscall_ret(<Arch as Syscalls>::syscall4(sysno(179, 60), cmd as i64, special as i64, id as i64, addr as i64)) as i32
17094}
17095
17096#[no_mangle]
17097pub unsafe extern "C" fn klogctl(type_: i32, bufp: *mut core::ffi::c_char, len: i32) -> i32 {
17098 syscall_ret(<Arch as Syscalls>::syscall3(sysno(103, 116), type_ as i64, bufp as i64, len as i64)) as i32
17099}
17100
17101static mut SYSLOG_IDENT: [core::ffi::c_char; 64] = [0; 64];
17102static mut SYSLOG_OPTIONS: i32 = 0;
17103static mut SYSLOG_FACILITY: i32 = 1;
17104
17105#[no_mangle]
17106pub unsafe extern "C" fn openlog(ident: *const core::ffi::c_char, option: i32, facility: i32) {
17107 SYSLOG_OPTIONS = option;
17108 SYSLOG_FACILITY = facility & 0x3f8;
17109 SYSLOG_IDENT[0] = 0;
17110 if !ident.is_null() {
17111 let mut i = 0;
17112 while i < 63 && *ident.add(i) != 0 {
17113 SYSLOG_IDENT[i] = *ident.add(i);
17114 i += 1;
17115 }
17116 SYSLOG_IDENT[i] = 0;
17117 }
17118}
17119
17120#[repr(C)]
17121struct SockAddrUn {
17122 sun_family: u16,
17123 sun_path: [core::ffi::c_char; 108],
17124}
17125
17126unsafe fn syslog_emit(priority: i32, msg: *const core::ffi::c_char, len: usize) {
17127 let mut out = [0u8; 1200];
17128 let mut o = 0usize;
17129 let pri = (SYSLOG_FACILITY | (priority & 7)) as u32;
17130 out[o] = b'<'; o += 1;
17131 if pri >= 100 { out[o] = b'0' + (pri / 100) as u8; o += 1; }
17132 if pri >= 10 { out[o] = b'0' + ((pri / 10) % 10) as u8; o += 1; }
17133 out[o] = b'0' + (pri % 10) as u8; o += 1;
17134 out[o] = b'>'; o += 1;
17135 let mut i = 0;
17136 while i < 63 && SYSLOG_IDENT[i] != 0 && o + 1 < out.len() {
17137 out[o] = SYSLOG_IDENT[i] as u8; o += 1; i += 1;
17138 }
17139 if SYSLOG_OPTIONS & 1 != 0 {
17140 out[o] = b'['; o += 1;
17141 let mut pid = crate::getpid() as u32;
17142 let mut digits = [0u8; 10];
17143 let mut d = 0;
17144 if pid == 0 { digits[0] = b'0'; d = 1; }
17145 while pid > 0 { digits[d] = b'0' + (pid % 10) as u8; pid /= 10; d += 1; }
17146 while d > 0 { d -= 1; out[o] = digits[d]; o += 1; }
17147 out[o] = b']'; o += 1;
17148 }
17149 out[o] = b':'; o += 1; out[o] = b' '; o += 1;
17150 let copy = core::cmp::min(len, out.len() - o - 1);
17151 core::ptr::copy_nonoverlapping(msg as *const u8, out.as_mut_ptr().add(o), copy);
17152 o += copy;
17153 let fd = crate::socket(AF_UNIX, SOCK_DGRAM, 0);
17154 if fd >= 0 {
17155 let mut sa: SockAddrUn = core::mem::zeroed();
17156 sa.sun_family = AF_UNIX as u16;
17157 let path = b"/dev/log";
17158 for i in 0..path.len() { sa.sun_path[i] = path[i] as core::ffi::c_char; }
17159 let r = crate::sendto(fd, out.as_ptr() as *const core::ffi::c_void, o, 0, &sa as *const SockAddrUn as *const crate::sockaddr, core::mem::size_of::<SockAddrUn>() as u32);
17160 crate::close(fd);
17161 if r >= 0 { return; }
17162 }
17163 crate::write(2, out.as_ptr() as *const core::ffi::c_void, o);
17164 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
17165}
17166
17167#[no_mangle]
17168pub unsafe extern "C" fn vsyslog(priority: c_int, fmt: *const c_char, ap: VaList) {
17169 let mut msg = [0 as c_char; 1024];
17170 let n = vsnprintf(msg.as_mut_ptr(), msg.len(), fmt, ap);
17171 if n > 0 { syslog_emit(priority, msg.as_ptr(), core::cmp::min(n as usize, msg.len() - 1)); }
17172}
17173
17174#[no_mangle]
17175pub unsafe extern "C" fn syslog(priority: c_int, fmt: *const c_char, args: ...) {
17176 vsyslog(priority, fmt, args);
17177}
17178
17179#[no_mangle]
17180pub unsafe extern "C" fn closelog() {
17181 }
17183
17184#[no_mangle]
17185pub unsafe extern "C" fn setlogmask(mask: i32) -> i32 {
17186 static mut LOG_MASK: i32 = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80;
17187 let old = LOG_MASK;
17188 if mask != 0 { LOG_MASK = mask; }
17189 old
17190}
17191
17192#[no_mangle]
17193pub unsafe extern "C" fn acct(filename: *const core::ffi::c_char) -> i32 {
17194 syscall_ret(<Arch as Syscalls>::syscall1(SYS_ACCT, filename as i64)) as i32
17195}
17196
17197#[no_mangle]
17198pub unsafe extern "C" fn swapon(path: *const core::ffi::c_char, flags: i32) -> i32 {
17199 syscall_ret(<Arch as Syscalls>::syscall2(SYS_SWAPON, path as i64, flags as i64)) as i32
17200}
17201
17202#[no_mangle]
17203pub unsafe extern "C" fn swapoff(path: *const core::ffi::c_char) -> i32 {
17204 syscall_ret(<Arch as Syscalls>::syscall1(SYS_SWAPOFF, path as i64)) as i32
17205}
17206
17207#[no_mangle]
17208pub unsafe extern "C" fn syncfs(fd: i32) -> i32 {
17209 syscall_ret(<Arch as Syscalls>::syscall1(SYS_SYNCFS, fd as i64)) as i32
17210}
17211
17212#[no_mangle]
17213pub unsafe extern "C" fn sync_file_range(fd: i32, offset: i64, nbytes: u64, flags: u32) -> i32 {
17214 syscall_ret(<Arch as Syscalls>::syscall4(sysno(277, 84), fd as i64, offset, nbytes as i64, flags as i64)) as i32
17215}
17216
17217#[no_mangle]
17218pub unsafe extern "C" fn posix_fadvise(fd: i32, offset: i64, len: u64, advice: i32) -> i32 {
17219 let r = <Arch as Syscalls>::syscall4(sysno(221, 223), fd as i64, offset, len as i64, advice as i64);
17221 if r < 0 { (-r) as i32 } else { 0 }
17222}
17223
17224#[no_mangle]
17225pub unsafe extern "C" fn posix_fallocate(fd: i32, offset: i64, len: u64) -> i32 {
17226 let r = <Arch as Syscalls>::syscall3(SYS_FALLOCATE, fd as i64, offset, len as i64);
17227 if r < 0 { (-r) as i32 } else { 0 }
17228}
17229
17230#[no_mangle]
17231pub unsafe extern "C" fn readahead(fd: i32, offset: i64, count: usize) -> isize {
17232 syscall_ret(<Arch as Syscalls>::syscall3(sysno(187, 213), fd as i64, offset, count as i64)) as isize
17235}
17236
17237#[no_mangle]
17238pub unsafe extern "C" fn fallocate(fd: i32, mode: i32, offset: i64, len: u64) -> i32 {
17239 syscall_ret(<Arch as Syscalls>::syscall4(SYS_FALLOCATE, fd as i64, mode as i64, offset, len as i64)) as i32
17240}
17241
17242#[no_mangle]
17247pub unsafe extern "C" fn tcgetattr(fd: i32, termios_p: *mut core::ffi::c_void) -> i32 {
17248 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5401, termios_p as i64)) as i32
17249}
17250
17251#[no_mangle]
17252pub unsafe extern "C" fn tcsetattr(fd: i32, optional_actions: i32, termios_p: *const core::ffi::c_void) -> i32 {
17253 let cmd = match optional_actions {
17254 0 => 0x5402,
17255 1 => 0x5403,
17256 2 => 0x5404,
17257 _ => 0x5402,
17258 };
17259 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, cmd, termios_p as i64)) as i32
17260}
17261
17262#[no_mangle]
17263pub unsafe extern "C" fn tcdrain(fd: i32) -> i32 {
17264 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5409, 1)) as i32
17265}
17266
17267#[no_mangle]
17268pub unsafe extern "C" fn tcflush(fd: i32, queue_selector: i32) -> i32 {
17269 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540B, queue_selector as i64)) as i32
17270}
17271
17272#[no_mangle]
17273pub unsafe extern "C" fn tcflow(fd: i32, action: i32) -> i32 {
17274 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540A, action as i64)) as i32
17275}
17276
17277#[no_mangle]
17278pub unsafe extern "C" fn tcsendbreak(fd: i32, duration: i32) -> i32 {
17279 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5425, duration as i64)) as i32
17280}
17281
17282#[no_mangle]
17283pub unsafe extern "C" fn tcgetsid(fd: i32) -> i32 {
17284 let mut sid: i32 = 0;
17285 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5429, &mut sid as *mut i32 as i64);
17286 if r < 0 { -1 } else { sid }
17287}
17288
17289#[no_mangle]
17290pub unsafe extern "C" fn tcgetpgrp(fd: i32) -> i32 {
17291 let mut pgrp: i32 = 0;
17292 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540F, &mut pgrp as *mut i32 as i64);
17293 if r < 0 { -1 } else { pgrp }
17294}
17295
17296#[no_mangle]
17297pub unsafe extern "C" fn tcsetpgrp(fd: i32, pgrp: i32) -> i32 {
17298 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5410, &pgrp as *const i32 as i64)) as i32
17299}
17300
17301#[no_mangle]
17312pub unsafe extern "C" fn mq_open(name: *const core::ffi::c_char, oflag: i32, mut args: ...) -> i32 {
17313 if name.is_null() { ERRNO!() = EINVAL; return -1; }
17314 let mut p = name as *const u8;
17315 if *p == b'/' { p = p.add(1); }
17316 let mut mode: u32 = 0;
17317 let mut attr: *const core::ffi::c_void = core::ptr::null();
17318 if oflag & 0o100 != 0 {
17319 mode = args.next_arg::<u32>();
17320 attr = args.next_arg::<*const core::ffi::c_void>();
17321 }
17322 syscall_ret(<Arch as Syscalls>::syscall4(
17323 sysno(240, 180),
17324 p as i64,
17325 oflag as i64,
17326 mode as i64,
17327 attr as i64,
17328 )) as i32
17329}
17330
17331#[no_mangle]
17332pub unsafe extern "C" fn mq_close(mqdes: i32) -> i32 {
17333 crate::close(mqdes as i32)
17334}
17335
17336#[no_mangle]
17337pub unsafe extern "C" fn mq_unlink(name: *const core::ffi::c_char) -> i32 {
17338 if name.is_null() { ERRNO!() = EINVAL; return -1; }
17339 let mut p = name as *const u8;
17340 if *p == b'/' { p = p.add(1); }
17341 let r = <Arch as Syscalls>::syscall1(sysno(241, 181), p as i64);
17342 if r < 0 {
17343 let e = if (-r) as c_int == 1 { 13 } else { (-r) as c_int };
17345 ERRNO!() = e;
17346 -1
17347 } else {
17348 0
17349 }
17350}
17351
17352#[no_mangle]
17353pub unsafe extern "C" fn mq_send(mqdes: i32, msg_ptr: *const core::ffi::c_char, msg_len: usize, msg_prio: u32) -> i32 {
17354 mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, core::ptr::null())
17355}
17356
17357#[no_mangle]
17358pub unsafe extern "C" fn mq_receive(mqdes: i32, msg_ptr: *mut core::ffi::c_char, msg_len: usize, msg_prio: *mut u32) -> isize {
17359 mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, core::ptr::null())
17360}
17361
17362#[no_mangle]
17363pub unsafe extern "C" fn mq_timedsend(
17364 mqdes: i32,
17365 msg_ptr: *const core::ffi::c_char,
17366 msg_len: usize,
17367 msg_prio: u32,
17368 abs_timeout: *const core::ffi::c_void,
17369) -> i32 {
17370 syscall_ret(<Arch as Syscalls>::syscall5(
17371 sysno(242, 182),
17372 mqdes as i64,
17373 msg_ptr as i64,
17374 msg_len as i64,
17375 msg_prio as i64,
17376 abs_timeout as i64,
17377 )) as i32
17378}
17379
17380#[no_mangle]
17381pub unsafe extern "C" fn mq_timedreceive(
17382 mqdes: i32,
17383 msg_ptr: *mut core::ffi::c_char,
17384 msg_len: usize,
17385 msg_prio: *mut u32,
17386 abs_timeout: *const core::ffi::c_void,
17387) -> isize {
17388 syscall_ret(<Arch as Syscalls>::syscall5(
17389 sysno(243, 183),
17390 mqdes as i64,
17391 msg_ptr as i64,
17392 msg_len as i64,
17393 msg_prio as i64,
17394 abs_timeout as i64,
17395 )) as isize
17396}
17397
17398#[repr(C)]
17399pub struct SigEventFull {
17400 sigev_value: usize,
17401 sigev_signo: i32,
17402 sigev_notify: i32,
17403 sigev_function: usize,
17404 sigev_attributes: usize,
17405 sigev_pad: [u8; 32],
17406}
17407
17408struct MqNotifyArgs {
17409 sem: sem_t,
17410 sock: i32,
17411 mqd: i32,
17412 err: i32,
17413 func: usize,
17414 value: usize,
17415}
17416
17417unsafe extern "C" fn mq_notify_thread(arg: *mut c_void) -> *mut c_void {
17418 let a = &mut *(arg as *mut MqNotifyArgs);
17419 let sock = a.sock;
17420 let mqd = a.mqd;
17421 let func = a.func;
17422 let value = a.value;
17423 let zeros = [0u8; 32];
17424 let sev2 = SigEventFull {
17425 sigev_value: zeros.as_ptr() as usize,
17426 sigev_signo: sock,
17427 sigev_notify: 2, sigev_function: 0,
17429 sigev_attributes: 0,
17430 sigev_pad: [0; 32],
17431 };
17432 let r = <Arch as Syscalls>::syscall2(sysno(244, 184), mqd as i64, &sev2 as *const SigEventFull as i64);
17433 a.err = if r < 0 { (-r) as i32 } else { 0 };
17434 sem_post(&mut a.sem);
17435 if a.err != 0 { return core::ptr::null_mut(); }
17436 pthread_detach(pthread_self());
17437 let mut buf = [0u8; 32];
17438 let n = recv(sock, buf.as_mut_ptr() as *mut c_void, buf.len(), 0x4000 | 0x100);
17439 crate::close(sock);
17440 if n as usize == buf.len() && buf[buf.len() - 1] == 1 && func != 0 {
17441 let f: extern "C" fn(usize) = core::mem::transmute(func);
17442 f(value);
17443 }
17444 core::ptr::null_mut()
17445}
17446
17447#[no_mangle]
17448pub unsafe extern "C" fn mq_notify(mqdes: i32, sev: *const core::ffi::c_void) -> i32 {
17449 if sev.is_null() {
17450 return syscall_ret(<Arch as Syscalls>::syscall2(sysno(244, 184), mqdes as i64, 0)) as i32;
17451 }
17452 let ev = &*(sev as *const SigEventFull);
17453 if ev.sigev_notify != 2 {
17454 return syscall_ret(<Arch as Syscalls>::syscall2(sysno(244, 184), mqdes as i64, sev as i64)) as i32;
17455 }
17456
17457 let sock = socket(16 , 3 | 0x80000 , 0);
17460 if sock < 0 { return -1; }
17461 let mut a = MqNotifyArgs {
17462 sem: core::mem::zeroed(),
17463 sock,
17464 mqd: mqdes,
17465 err: 0,
17466 func: ev.sigev_function,
17467 value: ev.sigev_value,
17468 };
17469 sem_init(&mut a.sem, 0, 0);
17470
17471 let mut attr: pthread_attr_t = core::mem::zeroed();
17472 if ev.sigev_attributes != 0 {
17473 attr = core::ptr::read(ev.sigev_attributes as *const pthread_attr_t);
17474 } else {
17475 pthread_attr_init(&mut attr);
17476 }
17477 pthread_attr_setdetachstate(&mut attr, PTHREAD_CREATE_JOINABLE);
17478
17479 let mut all: SigSetT = 0;
17480 sigfillset(&mut all);
17481 let mut orig: SigSetT = 0;
17482 pthread_sigmask(0 , &all, &mut orig);
17483
17484 let mut td: PthreadT = 0;
17485 let r = pthread_create(&mut td, &attr, mq_notify_thread as *const () as usize, &mut a as *mut MqNotifyArgs as *mut c_void);
17486 pthread_sigmask(2 , &orig, core::ptr::null_mut());
17487 if r != 0 {
17488 crate::close(sock);
17489 ERRNO!() = 11;
17490 return -1;
17491 }
17492 sem_wait(&mut a.sem);
17493 sem_destroy(&mut a.sem);
17494 if a.err != 0 {
17495 crate::close(sock);
17496 pthread_join(td, core::ptr::null_mut());
17497 ERRNO!() = a.err;
17498 return -1;
17499 }
17500 0
17501}
17502
17503#[no_mangle]
17504pub unsafe extern "C" fn mq_getattr(mqdes: i32, attr: *mut core::ffi::c_void) -> i32 {
17505 mq_setattr(mqdes, core::ptr::null(), attr)
17506}
17507
17508#[no_mangle]
17509pub unsafe extern "C" fn mq_setattr(
17510 mqdes: i32,
17511 new: *const core::ffi::c_void,
17512 old: *mut core::ffi::c_void,
17513) -> i32 {
17514 syscall_ret(<Arch as Syscalls>::syscall3(
17515 sysno(245, 185),
17516 mqdes as i64,
17517 new as i64,
17518 old as i64,
17519 )) as i32
17520}
17521
17522#[no_mangle]
17527pub unsafe extern "C" fn pthread_getaffinity_np(thread: usize, cpusetsize: usize, cpuset: *mut u8) -> i32 {
17528 sched_getaffinity(thread as i32, cpusetsize, cpuset)
17529}
17530
17531#[no_mangle]
17532pub unsafe extern "C" fn pthread_setaffinity_np(thread: usize, cpusetsize: usize, cpuset: *const u8) -> i32 {
17533 sched_setaffinity(thread as i32, cpusetsize, cpuset)
17534}
17535
17536#[no_mangle]
17541pub unsafe extern "C" fn sched_yield() -> i32 {
17542 syscall_ret(<Arch as Syscalls>::syscall0(sysno(24, 124))) as i32
17543}
17544
17545#[no_mangle]
17546pub unsafe extern "C" fn sched_get_priority_max(policy: i32) -> i32 {
17547 syscall_ret(<Arch as Syscalls>::syscall1(sysno(146, 125), policy as i64)) as i32
17548}
17549
17550#[no_mangle]
17551pub unsafe extern "C" fn sched_get_priority_min(policy: i32) -> i32 {
17552 syscall_ret(<Arch as Syscalls>::syscall1(sysno(147, 126), policy as i64)) as i32
17553}
17554
17555#[no_mangle]
17556pub unsafe extern "C" fn sched_getparam(pid: i32, param: *mut core::ffi::c_void) -> i32 {
17557 syscall_ret(<Arch as Syscalls>::syscall2(sysno(143, 121), pid as i64, param as i64)) as i32
17558}
17559
17560#[no_mangle]
17561pub unsafe extern "C" fn sched_setparam(pid: i32, param: *const core::ffi::c_void) -> i32 {
17562 syscall_ret(<Arch as Syscalls>::syscall2(sysno(142, 118), pid as i64, param as i64)) as i32
17563}
17564
17565#[no_mangle]
17566pub unsafe extern "C" fn sched_getscheduler(pid: i32) -> i32 {
17567 syscall_ret(<Arch as Syscalls>::syscall1(sysno(145, 120), pid as i64)) as i32
17568}
17569
17570#[no_mangle]
17571pub unsafe extern "C" fn sched_setscheduler(pid: i32, policy: i32, param: *const core::ffi::c_void) -> i32 {
17572 syscall_ret(<Arch as Syscalls>::syscall3(sysno(144, 119), pid as i64, policy as i64, param as i64)) as i32
17573}
17574
17575#[no_mangle]
17576pub unsafe extern "C" fn sched_setaffinity(pid: i32, cpusetsize: usize, cpuset: *const u8) -> i32 {
17577 syscall_ret(<Arch as Syscalls>::syscall3(sysno(203, 122), pid as i64, cpusetsize as i64, cpuset as i64)) as i32
17578}
17579
17580#[no_mangle]
17581pub unsafe extern "C" fn sched_getaffinity(pid: i32, cpusetsize: usize, cpuset: *mut u8) -> i32 {
17582 let r = <Arch as Syscalls>::syscall3(sysno(204, 123), pid as i64, cpusetsize as i64, cpuset as i64);
17583 if r < 0 {
17584 ERRNO!() = (-r) as c_int;
17585 return -1;
17586 }
17587 0
17589}
17590
17591#[no_mangle]
17592pub unsafe extern "C" fn sched_getcpu() -> i32 {
17593 let mut cpu: i32 = 0;
17594 <Arch as Syscalls>::syscall3(sysno(309, 168), &mut cpu as *mut i32 as i64, 0, 0);
17595 cpu
17596}
17597
17598#[no_mangle]
17599pub unsafe extern "C" fn sched_rr_get_interval(pid: i32, tp: *mut core::ffi::c_void) -> i32 {
17600 syscall_ret(<Arch as Syscalls>::syscall2(sysno(148, 127), pid as i64, tp as i64)) as i32
17601}
17602
17603#[no_mangle]
17608pub unsafe extern "C" fn timer_create(clockid: i32, sevp: *mut core::ffi::c_void, timerid: *mut i32) -> i32 {
17609 syscall_ret(<Arch as Syscalls>::syscall3(sysno(222, 107), clockid as i64, sevp as i64, timerid as i64)) as i32
17610}
17611
17612#[no_mangle]
17613pub unsafe extern "C" fn timer_delete(timerid: i32) -> i32 {
17614 syscall_ret(<Arch as Syscalls>::syscall1(sysno(226, 111), timerid as i64)) as i32
17615}
17616
17617#[no_mangle]
17618pub unsafe extern "C" fn timer_settime(timerid: i32, flags: i32, new_value: *const core::ffi::c_void, old_value: *mut core::ffi::c_void) -> i32 {
17619 syscall_ret(<Arch as Syscalls>::syscall4(sysno(223, 110), timerid as i64, flags as i64, new_value as i64, old_value as i64)) as i32
17620}
17621
17622#[no_mangle]
17623pub unsafe extern "C" fn timer_gettime(timerid: i32, curr_value: *mut core::ffi::c_void) -> i32 {
17624 syscall_ret(<Arch as Syscalls>::syscall2(sysno(224, 108), timerid as i64, curr_value as i64)) as i32
17625}
17626
17627#[no_mangle]
17628pub unsafe extern "C" fn timer_getoverrun(timerid: i32) -> i32 {
17629 syscall_ret(<Arch as Syscalls>::syscall1(sysno(225, 109), timerid as i64)) as i32
17630}
17631
17632#[no_mangle]
17633pub unsafe extern "C" fn clock_adjtime(_clockid: i32, buf: *mut core::ffi::c_void) -> i32 {
17634 syscall_ret(<Arch as Syscalls>::syscall2(SYS_ADJTIMEX, buf as i64, 0)) as i32
17635}
17636
17637#[no_mangle]
17638pub unsafe extern "C" fn clock_getcpuclockid(pid: i32, clockid: *mut i32) -> i32 {
17639 if clockid.is_null() { return EINVAL; }
17640 let id: i32 = ((-(pid as i64) - 1) * 8 + 2) as i32;
17641 let mut ts: timespec = core::mem::zeroed();
17642 let r = <Arch as Syscalls>::syscall2(SYS_CLOCK_GETRES, id as i64, &mut ts as *mut timespec as i64);
17643 if r < 0 {
17644 let e = (-r) as c_int;
17645 return if e == EINVAL { 3 } else { e };
17646 }
17647 *clockid = id;
17648 0
17649}
17650
17651#[no_mangle]
17656pub unsafe extern "C" fn strcoll(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char) -> i32 {
17657 let mut i = 0;
17659 loop {
17660 let c1 = *s1.add(i) as u8;
17661 let c2 = *s2.add(i) as u8;
17662 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
17663 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
17664 i += 1;
17665 }
17666}
17667
17668#[no_mangle]
17669pub unsafe extern "C" fn strxfrm(dest: *mut core::ffi::c_char, src: *const core::ffi::c_char, n: usize) -> usize {
17670 let mut i = 0;
17671 while i < n {
17672 let c = *src.add(i);
17673 *dest.add(i) = c;
17674 if c == 0 { break; }
17675 i += 1;
17676 }
17677 i
17678}
17679
17680#[no_mangle]
17685pub unsafe extern "C" fn scandir(dirp: *const core::ffi::c_char, _namelist: *mut *mut *mut core::ffi::c_void, _filter: Option<unsafe extern "C" fn(*const core::ffi::c_void) -> i32>, _compar: Option<unsafe extern "C" fn(*const core::ffi::c_void, *const core::ffi::c_void) -> i32>) -> i32 {
17686 let dir = opendir(dirp);
17687 if dir.is_null() { return -1; }
17688 let mut count = 0;
17689 loop {
17690 let ent = readdir(dir);
17691 if ent.is_null() { break; }
17692 count += 1;
17693 }
17694 closedir(dir);
17695 count
17696}
17697
17698#[no_mangle]
17699pub unsafe extern "C" fn alphasort(a: *const *const core::ffi::c_void, b: *const *const core::ffi::c_void) -> i32 {
17700 let s1 = *a as *const core::ffi::c_char;
17701 let s2 = *b as *const core::ffi::c_char;
17702 crate::strcmp(s1 as *const u8, s2 as *const u8)
17703}
17704
17705#[no_mangle]
17706pub unsafe extern "C" fn versionsort(a: *const *const core::ffi::c_void, b: *const *const core::ffi::c_void) -> i32 {
17707 let s1 = *a as *const core::ffi::c_char;
17708 let s2 = *b as *const core::ffi::c_char;
17709 crate::strcmp(s1 as *const u8, s2 as *const u8)
17710}
17711
17712unsafe fn vwarn_impl(fmt: *const c_char, ap: VaList, with_errno: bool) {
17720 let mut buf = [0 as c_char; 1024];
17721 let n = vsnprintf(buf.as_mut_ptr(), buf.len(), fmt, ap);
17722 if n > 0 {
17723 let l = core::cmp::min(n as usize, buf.len() - 1);
17724 crate::write(2, buf.as_ptr() as *const c_void, l);
17725 }
17726 if with_errno {
17727 let e = ERRNO!();
17728 crate::write(2, b": ".as_ptr() as *const c_void, 2);
17729 let msg = strerror(e);
17730 crate::write(2, msg as *const c_void, crate::strlen(msg));
17731 }
17732 crate::write(2, b"\n".as_ptr() as *const c_void, 1);
17733}
17734
17735#[no_mangle]
17736pub unsafe extern "C" fn verr(eval: c_int, fmt: *const c_char, ap: VaList) {
17737 vwarn_impl(fmt, ap, true);
17738 crate::exit(eval);
17739}
17740
17741#[no_mangle]
17742pub unsafe extern "C" fn verrx(eval: c_int, fmt: *const c_char, ap: VaList) {
17743 vwarn_impl(fmt, ap, false);
17744 crate::exit(eval);
17745}
17746
17747#[no_mangle]
17748pub unsafe extern "C" fn vwarn(fmt: *const c_char, ap: VaList) {
17749 vwarn_impl(fmt, ap, true);
17750}
17751
17752#[no_mangle]
17753pub unsafe extern "C" fn vwarnx(fmt: *const c_char, ap: VaList) {
17754 vwarn_impl(fmt, ap, false);
17755}
17756
17757#[no_mangle]
17758pub unsafe extern "C" fn err(eval: c_int, fmt: *const c_char, args: ...) {
17759 verr(eval, fmt, args);
17760}
17761
17762#[no_mangle]
17763pub unsafe extern "C" fn errx(eval: c_int, fmt: *const c_char, args: ...) {
17764 verrx(eval, fmt, args);
17765}
17766
17767#[no_mangle]
17768pub unsafe extern "C" fn warn(fmt: *const c_char, args: ...) {
17769 vwarn(fmt, args);
17770}
17771
17772#[no_mangle]
17773pub unsafe extern "C" fn warnx(fmt: *const c_char, args: ...) {
17774 vwarnx(fmt, args);
17775}
17776
17777#[no_mangle]
17782pub unsafe extern "C" fn ecvt(value: f64, ndigit: i32, decpt: *mut i32, sign: *mut i32) -> *mut core::ffi::c_char {
17783 static mut BUF: [core::ffi::c_char; 80] = [0; 80];
17784 if value < 0.0 { *sign = 1; } else { *sign = 0; }
17785 let v = if value < 0.0 { -value } else { value };
17786 if v == 0.0 { *decpt = 0; BUF[0] = 0; return BUF.as_mut_ptr(); }
17787 let mut d = 0i32;
17788 let mut tmp = v;
17789 while tmp >= 10.0 { tmp /= 10.0; d += 1; }
17790 while tmp < 1.0 { tmp *= 10.0; d -= 1; }
17791 *decpt = d + 1;
17792 let mut i = 0;
17793 let mut val = tmp;
17794 while i < ndigit as usize && i < 79 {
17795 let digit = val as i32;
17796 BUF[i] = (b'0' + digit as u8) as c_char;
17797 val = (val - digit as f64) * 10.0;
17798 i += 1;
17799 }
17800 BUF[i] = 0;
17801 BUF.as_mut_ptr()
17802}
17803
17804#[no_mangle]
17805pub unsafe extern "C" fn fcvt(value: f64, ndigit: i32, decpt: *mut i32, sign: *mut i32) -> *mut core::ffi::c_char {
17806 static mut BUF: [core::ffi::c_char; 80] = [0; 80];
17807 if value < 0.0 { *sign = 1; } else { *sign = 0; }
17808 let v = if value < 0.0 { -value } else { value };
17809 if v == 0.0 { *decpt = 0; BUF[0] = 0; return BUF.as_mut_ptr(); }
17810 let mut d = 0i32;
17811 let mut tmp = v;
17812 while tmp >= 10.0 { tmp /= 10.0; d += 1; }
17813 while tmp < 1.0 { tmp *= 10.0; d -= 1; }
17814 *decpt = d + 1;
17815 let mut val = tmp;
17816 let mut i = 0;
17817 while i < (*decpt) as usize && i < 79 {
17818 let digit = val as i32;
17819 BUF[i] = (b'0' + digit as u8) as c_char;
17820 val = (val - digit as f64) * 10.0;
17821 i += 1;
17822 }
17823 if ndigit > 0 && i < 79 {
17824 BUF[i] = '.' as c_char;
17825 i += 1;
17826 let mut frac = val;
17827 let mut j = 0;
17828 while j < ndigit as usize && i < 79 {
17829 let digit = frac as i32;
17830 BUF[i] = (b'0' + digit as u8) as c_char;
17831 frac = (frac - digit as f64) * 10.0;
17832 i += 1;
17833 j += 1;
17834 }
17835 }
17836 BUF[i] = 0;
17837 BUF.as_mut_ptr()
17838}
17839
17840#[no_mangle]
17841pub unsafe extern "C" fn gcvt(value: f64, _ndigit: i32, buf: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
17842 if value == 0.0 {
17844 *buf = '0' as c_char;
17845 *buf.add(1) = 0;
17846 return buf;
17847 }
17848 let mut i = 0;
17849 let v = if value < 0.0 { *buf = '-' as c_char; i = 1; -value } else { value };
17850 let mut int_part = v as i64;
17852 let mut digits = [0u8; 32];
17853 let mut di = 0;
17854 if int_part == 0 {
17855 digits[0] = 0;
17856 di = 1;
17857 } else {
17858 while int_part > 0 && di < 32 {
17859 digits[di] = (int_part % 10) as u8;
17860 int_part /= 10;
17861 di += 1;
17862 }
17863 }
17864 while di > 0 && i < 79 {
17865 di -= 1;
17866 *buf.add(i) = (b'0' + digits[di]) as c_char;
17867 i += 1;
17868 }
17869 *buf.add(i) = 0;
17870 buf
17871}
17872
17873static mut SHELLS: [*const core::ffi::c_char; 3] = [
17878 b"/bin/sh\0".as_ptr() as *const core::ffi::c_char,
17879 b"/bin/bash\0".as_ptr() as *const core::ffi::c_char,
17880 core::ptr::null(),
17881];
17882static mut SHELL_IDX: usize = 0;
17883
17884#[no_mangle]
17885pub unsafe extern "C" fn getusershell() -> *mut core::ffi::c_char {
17886 let s = SHELLS[SHELL_IDX];
17887 if s.is_null() {
17888 SHELL_IDX = 0;
17889 return core::ptr::null_mut();
17890 }
17891 SHELL_IDX += 1;
17892 s as *mut core::ffi::c_char
17893}
17894
17895#[no_mangle]
17896pub unsafe extern "C" fn setusershell() {
17897 SHELL_IDX = 0;
17898}
17899
17900#[no_mangle]
17901pub unsafe extern "C" fn endusershell() {
17902 SHELL_IDX = 0;
17903}
17904
17905#[no_mangle]
17910pub unsafe extern "C" fn ether_aton(s: *const core::ffi::c_char) -> *mut u8 {
17911 static mut EA: [u8; 6] = [0; 6];
17912 if ether_aton_r(s, EA.as_mut_ptr()).is_null() { core::ptr::null_mut() } else { EA.as_mut_ptr() }
17913}
17914
17915#[no_mangle]
17916pub unsafe extern "C" fn ether_aton_r(s: *const core::ffi::c_char, ea: *mut u8) -> *mut u8 {
17917 if ea.is_null() { return core::ptr::null_mut(); }
17918 let mut i = 0;
17919 let mut j = 0;
17920 let mut val: u32 = 0;
17921 let mut digits = 0;
17922 while *s.add(i) != 0 && j < 6 {
17923 let c = *s.add(i);
17924 if c == ':' as c_char {
17925 if digits == 0 { return core::ptr::null_mut(); }
17926 *ea.add(j) = val as u8;
17927 j += 1;
17928 val = 0;
17929 digits = 0;
17930 } else if (c >= '0' as c_char && c <= '9' as c_char) || (c >= 'a' as c_char && c <= 'f' as c_char) || (c >= 'A' as c_char && c <= 'F' as c_char) {
17931 let d = if c >= '0' as c_char && c <= '9' as c_char { (c - '0' as c_char) as u32 }
17932 else if c >= 'a' as c_char { (c - 'a' as c_char + 10) as u32 }
17933 else { (c - 'A' as c_char + 10) as u32 };
17934 val = val * 16 + d;
17935 if val > 255 { return core::ptr::null_mut(); }
17936 digits += 1;
17937 if digits > 2 { return core::ptr::null_mut(); }
17938 } else {
17939 return core::ptr::null_mut();
17940 }
17941 i += 1;
17942 }
17943 if digits == 0 || j != 5 { return core::ptr::null_mut(); }
17944 *ea.add(j) = val as u8;
17945 ea
17946}
17947
17948#[no_mangle]
17949pub unsafe extern "C" fn ether_ntoa(ea: *const u8) -> *mut core::ffi::c_char {
17950 static mut BUF: [core::ffi::c_char; 18] = [0; 18];
17951 ether_ntoa_r(ea, BUF.as_mut_ptr());
17952 BUF.as_mut_ptr()
17953}
17954
17955#[no_mangle]
17956pub unsafe extern "C" fn ether_ntoa_r(ea: *const u8, buf: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
17957 let a = *ea.add(0); let b = *ea.add(1); let c = *ea.add(2);
17958 let d = *ea.add(3); let e = *ea.add(4); let f = *ea.add(5);
17959 let hex = b"0123456789abcdef\0".as_ptr() as *const u8;
17960 let mut i = 0;
17961 *buf.add(i) = *hex.add((a >> 4) as usize) as c_char; i += 1;
17962 *buf.add(i) = *hex.add((a & 0xf) as usize) as c_char; i += 1;
17963 *buf.add(i) = ':' as c_char; i += 1;
17964 *buf.add(i) = *hex.add((b >> 4) as usize) as c_char; i += 1;
17965 *buf.add(i) = *hex.add((b & 0xf) as usize) as c_char; i += 1;
17966 *buf.add(i) = ':' as c_char; i += 1;
17967 *buf.add(i) = *hex.add((c >> 4) as usize) as c_char; i += 1;
17968 *buf.add(i) = *hex.add((c & 0xf) as usize) as c_char; i += 1;
17969 *buf.add(i) = ':' as c_char; i += 1;
17970 *buf.add(i) = *hex.add((d >> 4) as usize) as c_char; i += 1;
17971 *buf.add(i) = *hex.add((d & 0xf) as usize) as c_char; i += 1;
17972 *buf.add(i) = ':' as c_char; i += 1;
17973 *buf.add(i) = *hex.add((e >> 4) as usize) as c_char; i += 1;
17974 *buf.add(i) = *hex.add((e & 0xf) as usize) as c_char; i += 1;
17975 *buf.add(i) = ':' as c_char; i += 1;
17976 *buf.add(i) = *hex.add((f >> 4) as usize) as c_char; i += 1;
17977 *buf.add(i) = *hex.add((f & 0xf) as usize) as c_char; i += 1;
17978 *buf.add(i) = 0;
17979 buf
17980}
17981
17982#[no_mangle]
17987pub unsafe extern "C" fn getutxent() -> *mut core::ffi::c_void {
17988 getutent()
17989}
17990
17991#[no_mangle]
17992pub unsafe extern "C" fn getutxid(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
17993 getutid(ut)
17994}
17995
17996#[no_mangle]
17997pub unsafe extern "C" fn getutxline(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
17998 getutline(ut)
17999}
18000
18001#[no_mangle]
18002pub unsafe extern "C" fn pututxline(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
18003 pututline(ut)
18004}
18005
18006#[no_mangle]
18007pub unsafe extern "C" fn setutxent() {
18008 setutent()
18009}
18010
18011#[no_mangle]
18012pub unsafe extern "C" fn endutxent() {
18013 endutent()
18014}
18015
18016#[no_mangle]
18021pub unsafe extern "C" fn execv(path: *const core::ffi::c_char, argv: *const *const core::ffi::c_char) -> i32 {
18022 crate::execve(path, argv, __environ as *const *const core::ffi::c_char)
18023}
18024
18025#[no_mangle]
18026pub unsafe extern "C" fn execlp(file: *const core::ffi::c_char, _args: ...) -> i32 {
18027 let mut argv: [*const core::ffi::c_char; 64] = [core::ptr::null(); 64];
18029 let mut i = 0;
18030 let mut args = _args;
18031 loop {
18032 let arg = args.next_arg::<*const core::ffi::c_char>();
18033 if arg.is_null() { break; }
18034 argv[i] = arg;
18035 i += 1;
18036 if i >= 63 { break; }
18037 }
18038 argv[i] = core::ptr::null();
18039 execvp(file, argv.as_ptr())
18040}
18041
18042#[no_mangle]
18043pub unsafe extern "C" fn execvp(file: *const core::ffi::c_char, argv: *const *const core::ffi::c_char) -> i32 {
18044 execvpe(file, argv, __environ as *const *const core::ffi::c_char)
18045}
18046
18047#[no_mangle]
18048pub unsafe extern "C" fn fexecve(fd: i32, argv: *const *const core::ffi::c_char, envp: *const *const core::ffi::c_char) -> i32 {
18049 let mut path: [core::ffi::c_char; 64] = [0; 64];
18051 let mut i = 0;
18052 let src = b"/proc/self/fd/\0".as_ptr() as *const core::ffi::c_char;
18053 while i < 63 && *src.add(i) != 0 { path[i] = *src.add(i); i += 1; }
18054 let mut n = fd as usize;
18055 if n == 0 { path[i] = '0' as c_char; i += 1; }
18056 while n > 0 && i < 63 {
18057 path[i] = (b'0' + (n % 10) as u8) as c_char;
18058 n /= 10;
18059 i += 1;
18060 }
18061 path[i] = 0;
18062 crate::execve(path.as_ptr(), argv, envp)
18063}
18064
18065#[no_mangle]
18070pub unsafe extern "C" fn confstr(name: i32, buf: *mut core::ffi::c_char, len: usize) -> usize {
18071 let value: &[u8] = if name == 0 {
18074 b"/bin:/usr/bin"
18075 } else if (1..=37).contains(&name) {
18076 b""
18077 } else {
18078 ERRNO!() = EINVAL;
18079 return 0;
18080 };
18081 let need = value.len() + 1;
18082 if !buf.is_null() && len > 0 {
18083 let n = core::cmp::min(value.len(), len - 1);
18084 core::ptr::copy_nonoverlapping(value.as_ptr(), buf as *mut u8, n);
18085 *buf.add(n) = 0;
18086 }
18087 need
18088}
18089
18090#[no_mangle]
18091pub unsafe extern "C" fn pathconf(_path: *const core::ffi::c_char, name: i32) -> i64 {
18092 match name {
18094 0 => 4096, 1 => 255, 2 => 255, 3 => 255, 4 => 4096, 5 => 4096, 6 => 1, 7 => 0, 8 => 0, _ => -1,
18104 }
18105}
18106
18107#[no_mangle]
18108pub unsafe extern "C" fn fpathconf(_fd: i32, name: i32) -> i64 {
18109 match name {
18111 0 => 4096, 1 => 255, 2 => 255, 3 => 255, 4 => 4096, 5 => 4096, 6 => 1, 7 => 0, 8 => 0, _ => -1,
18121 }
18122}
18123
18124#[no_mangle]
18129pub unsafe extern "C" fn exp10(x: f64) -> f64 {
18130 libm::pow(10.0, x)
18131}
18132
18133#[no_mangle]
18134pub unsafe extern "C" fn exp10f(x: f32) -> f32 {
18135 libm::powf(10.0, x)
18136}
18137
18138#[no_mangle]
18143pub unsafe extern "C" fn explicit_bzero(s: *mut u8, n: usize) {
18144 core::ptr::write_bytes(s, 0, n);
18145 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
18146}
18147
18148#[no_mangle]
18149pub unsafe extern "C" fn memccpy(dest: *mut u8, src: *const u8, c: i32, n: usize) -> *mut u8 {
18150 let mut i = 0;
18151 while i < n {
18152 let byte = *src.add(i);
18153 *dest.add(i) = byte;
18154 if byte == c as u8 {
18155 return dest.add(i + 1);
18156 }
18157 i += 1;
18158 }
18159 core::ptr::null_mut()
18160}
18161
18162#[no_mangle]
18167pub unsafe extern "C" fn faccessat(dirfd: i32, pathname: *const core::ffi::c_char, mode: i32, flags: i32) -> i32 {
18168 syscall_ret(<Arch as Syscalls>::syscall4(SYS_FACCESSAT, dirfd as i64, pathname as i64, mode as i64, flags as i64)) as i32
18169}
18170
18171#[no_mangle]
18172pub unsafe extern "C" fn fchmodat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32, flags: i32) -> i32 {
18173 if flags == 0 {
18174 return syscall_ret(<Arch as Syscalls>::syscall4(SYS_FCHMODAT, dirfd as i64, pathname as i64, mode as i64, 0)) as i32;
18175 }
18176 if flags != 0x100 {
18177 ERRNO!() = EINVAL;
18179 return -1;
18180 }
18181 syscall_ret(<Arch as Syscalls>::syscall4(sysno(452, 452), dirfd as i64, pathname as i64, mode as i64, flags as i64)) as i32
18182}
18183
18184#[no_mangle]
18185pub unsafe extern "C" fn fchownat(dirfd: i32, pathname: *const core::ffi::c_char, uid: u32, gid: u32, flags: i32) -> i32 {
18186 syscall_ret(<Arch as Syscalls>::syscall5(sysno(260, 54), dirfd as i64, pathname as i64, uid as i64, gid as i64, flags as i64)) as i32
18187}
18188
18189#[no_mangle]
18190pub unsafe extern "C" fn linkat(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char, flags: i32) -> i32 {
18191 syscall_ret(<Arch as Syscalls>::syscall5(SYS_LINKAT, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)) as i32
18192}
18193
18194#[no_mangle]
18195pub unsafe extern "C" fn mkdirat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18196 syscall_ret(<Arch as Syscalls>::syscall3(SYS_MKDIRAT, dirfd as i64, pathname as i64, mode as i64)) as i32
18197}
18198
18199#[no_mangle]
18200pub unsafe extern "C" fn mkfifoat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18201 mknodat(dirfd, pathname, mode | 0o010000, 0)
18202}
18203
18204#[no_mangle]
18205pub unsafe extern "C" fn mknodat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32, dev: u64) -> i32 {
18206 syscall_ret(<Arch as Syscalls>::syscall4(sysno(259, 33), dirfd as i64, pathname as i64, mode as i64, dev as i64)) as i32
18207}
18208
18209#[no_mangle]
18210pub unsafe extern "C" fn readlinkat(dirfd: i32, pathname: *const core::ffi::c_char, buf: *mut core::ffi::c_char, bufsiz: usize) -> isize {
18211 syscall_ret(<Arch as Syscalls>::syscall4(SYS_READLINKAT, dirfd as i64, pathname as i64, buf as i64, bufsiz as i64)) as isize
18212}
18213
18214#[no_mangle]
18215pub unsafe extern "C" fn renameat(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char) -> i32 {
18216 syscall_ret(<Arch as Syscalls>::syscall5(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, 0)) as i32
18217}
18218
18219#[no_mangle]
18220pub unsafe extern "C" fn renameat2(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char, flags: u32) -> i32 {
18221 syscall_ret(<Arch as Syscalls>::syscall5(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)) as i32
18222}
18223
18224#[no_mangle]
18225pub unsafe extern "C" fn symlinkat(target: *const core::ffi::c_char, newdirfd: i32, linkpath: *const core::ffi::c_char) -> i32 {
18226 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, newdirfd as i64, linkpath as i64)) as i32
18227}
18228
18229#[no_mangle]
18230pub unsafe extern "C" fn unlinkat(dirfd: i32, pathname: *const core::ffi::c_char, flags: i32) -> i32 {
18231 syscall_ret(<Arch as Syscalls>::syscall3(SYS_UNLINKAT, dirfd as i64, pathname as i64, flags as i64)) as i32
18232}
18233
18234#[no_mangle]
18235pub unsafe extern "C" fn utimes(filename: *const core::ffi::c_char, times: *const core::ffi::c_void) -> i32 {
18236 utimensat(AT_FDCWD, filename, times as *const timespec, 0)
18237}
18238
18239#[no_mangle]
18240pub unsafe extern "C" fn futimes(fd: i32, times: *const core::ffi::c_void) -> i32 {
18241 utimensat(fd, core::ptr::null(), times as *const timespec, 0)
18242}
18243
18244#[no_mangle]
18249pub unsafe extern "C" fn inotify_init() -> i32 {
18250 syscall_ret(<Arch as Syscalls>::syscall1(sysno(253, 26), 0)) as i32
18251}
18252
18253#[no_mangle]
18254pub unsafe extern "C" fn inotify_init1(flags: i32) -> i32 {
18255 syscall_ret(<Arch as Syscalls>::syscall1(sysno(294, 26), flags as i64)) as i32
18256}
18257
18258#[no_mangle]
18259pub unsafe extern "C" fn inotify_add_watch(fd: i32, pathname: *const core::ffi::c_char, mask: u32) -> i32 {
18260 syscall_ret(<Arch as Syscalls>::syscall3(sysno(254, 27), fd as i64, pathname as i64, mask as i64)) as i32
18261}
18262
18263#[no_mangle]
18264pub unsafe extern "C" fn inotify_rm_watch(fd: i32, wd: i32) -> i32 {
18265 syscall_ret(<Arch as Syscalls>::syscall2(sysno(255, 28), fd as i64, wd as i64)) as i32
18266}
18267
18268#[no_mangle]
18269pub unsafe extern "C" fn fanotify_init(flags: i32, event_f_flags: i32) -> i32 {
18270 syscall_ret(<Arch as Syscalls>::syscall2(sysno(300, 262), flags as i64, event_f_flags as i64)) as i32
18271}
18272
18273#[no_mangle]
18274pub unsafe extern "C" fn fanotify_mark(fd: i32, flags: i32, mask: u64, dirfd: i32, pathname: *const core::ffi::c_char) -> i32 {
18275 syscall_ret(<Arch as Syscalls>::syscall5(sysno(301, 263), fd as i64, flags as i64, mask as i64, dirfd as i64, pathname as i64)) as i32
18276}
18277
18278#[no_mangle]
18283pub unsafe extern "C" fn ffs(x: i32) -> i32 {
18284 if x == 0 { return 0; }
18285 x.trailing_zeros() as i32 + 1
18286}
18287
18288#[no_mangle]
18289pub unsafe extern "C" fn ffsl(x: i64) -> i32 {
18290 if x == 0 { return 0; }
18291 x.trailing_zeros() as i32 + 1
18292}
18293
18294#[no_mangle]
18295pub unsafe extern "C" fn ffsll(x: i64) -> i32 {
18296 if x == 0 { return 0; }
18297 x.trailing_zeros() as i32 + 1
18298}
18299
18300#[no_mangle]
18305pub unsafe extern "C" fn fchdir(fd: i32) -> i32 {
18306 syscall_ret(<Arch as Syscalls>::syscall1(SYS_FCHDIR, fd as i64)) as i32
18307}
18308
18309#[no_mangle]
18310pub unsafe extern "C" fn fchown(fd: i32, uid: u32, gid: u32) -> i32 {
18311 syscall_ret(<Arch as Syscalls>::syscall3(SYS_FCHOWN, fd as i64, uid as i64, gid as i64)) as i32
18312}
18313
18314#[no_mangle]
18315pub unsafe extern "C" fn fdopendir(fd: i32) -> *mut core::ffi::c_void {
18316 if fd < 0 { ERRNO!() = 9; return core::ptr::null_mut(); }
18317 dir_stream_new(fd)
18318}
18319
18320#[no_mangle]
18321pub unsafe extern "C" fn getdtablesize() -> i32 {
18322 let mut rlim: Rlimit = core::mem::zeroed();
18323 if getrlimit(RLIMIT_NOFILE, &mut rlim) == 0 {
18324 rlim.rlim_cur as i32
18325 } else {
18326 1024
18327 }
18328}
18329
18330#[no_mangle]
18331pub unsafe extern "C" fn getentropy(buf: *mut u8, buflen: usize) -> i32 {
18332 if buflen > 256 {
18333 ERRNO!() = EIO_VAL;
18334 return -1;
18335 }
18336 let mut pos = buf;
18337 let mut left = buflen;
18338 while left > 0 {
18339 let r = getrandom(pos, left, 0);
18340 if r < 0 {
18341 if ERRNO!() == EINTR_VAL {
18342 continue;
18343 }
18344 return -1;
18345 }
18346 pos = pos.add(r as usize);
18347 left -= r as usize;
18348 }
18349 0
18350}
18351
18352#[no_mangle]
18353pub unsafe extern "C" fn getrandom(buf: *mut u8, buflen: usize, flags: u32) -> isize {
18354 let r = <Arch as Syscalls>::syscall3(sysno(318, 278), buf as i64, buflen as i64, flags as i64);
18355 if r < 0 {
18356 ERRNO!() = (-r) as c_int;
18357 -1
18358 } else {
18359 r as isize
18360 }
18361}
18362
18363#[no_mangle]
18364pub unsafe extern "C" fn killpg(pgrp: i32, sig: i32) -> i32 {
18365 syscall_ret(<Arch as Syscalls>::syscall2(SYS_KILL, -pgrp as i64, sig as i64)) as i32
18366}
18367
18368#[no_mangle]
18369pub unsafe extern "C" fn mkfifo(pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18370 mknod(pathname, 0o010000 | mode, 0)
18371}
18372
18373#[no_mangle]
18378pub unsafe extern "C" fn aligned_alloc(alignment: usize, size: usize) -> *mut core::ffi::c_void {
18379 alloc_aligned_impl(alignment, size) as *mut core::ffi::c_void
18380}
18381
18382#[no_mangle]
18383pub unsafe extern "C" fn memalign(alignment: usize, size: usize) -> *mut core::ffi::c_void {
18384 alloc_aligned_impl(alignment, size) as *mut core::ffi::c_void
18385}
18386
18387#[no_mangle]
18388pub unsafe extern "C" fn posix_memalign(memptr: *mut *mut core::ffi::c_void, alignment: usize, size: usize) -> i32 {
18389 if memptr.is_null() { return EINVAL; }
18390 if alignment < core::mem::size_of::<*mut core::ffi::c_void>() || !alignment.is_power_of_two() {
18391 return EINVAL;
18392 }
18393 let p = alloc_aligned_impl(alignment, size);
18394 if p.is_null() { return ENOMEM; }
18395 *memptr = p as *mut core::ffi::c_void;
18396 0
18397}
18398
18399#[no_mangle]
18400pub unsafe extern "C" fn valloc(size: usize) -> *mut core::ffi::c_void {
18401 alloc_aligned_impl(PAGE, size) as *mut core::ffi::c_void
18402}
18403
18404#[no_mangle]
18417pub unsafe extern "C" fn gettext(msgid: *const core::ffi::c_char) -> *const core::ffi::c_char {
18418 msgid
18419}
18420
18421#[no_mangle]
18422pub unsafe extern "C" fn dgettext(_domainname: *const core::ffi::c_char, msgid: *const core::ffi::c_char) -> *const core::ffi::c_char {
18423 msgid
18424}
18425
18426#[no_mangle]
18427pub unsafe extern "C" fn dcgettext(_domainname: *const core::ffi::c_char, msgid: *const core::ffi::c_char, _category: i32) -> *const core::ffi::c_char {
18428 msgid
18429}
18430
18431#[no_mangle]
18432pub unsafe extern "C" fn ngettext(msgid1: *const core::ffi::c_char, msgid2: *const core::ffi::c_char, n: u64) -> *const core::ffi::c_char {
18433 if n == 1 { msgid1 } else { msgid2 }
18434}
18435
18436#[no_mangle]
18437pub unsafe extern "C" fn dngettext(_domainname: *const core::ffi::c_char, msgid1: *const core::ffi::c_char, msgid2: *const core::ffi::c_char, n: u64) -> *const core::ffi::c_char {
18438 if n == 1 { msgid1 } else { msgid2 }
18439}
18440
18441#[no_mangle]
18442pub unsafe extern "C" fn dcngettext(_domainname: *const core::ffi::c_char, msgid1: *const core::ffi::c_char, msgid2: *const core::ffi::c_char, n: u64, _category: i32) -> *const core::ffi::c_char {
18443 if n == 1 { msgid1 } else { msgid2 }
18444}
18445
18446#[no_mangle]
18447pub unsafe extern "C" fn textdomain(domainname: *const core::ffi::c_char) -> *mut core::ffi::c_char {
18448 static mut DOMAIN: [core::ffi::c_char; 256] = [0; 256];
18449 if domainname.is_null() { return DOMAIN.as_mut_ptr(); }
18450 let mut i = 0;
18451 while i < 255 && *domainname.add(i) != 0 {
18452 DOMAIN[i] = *domainname.add(i);
18453 i += 1;
18454 }
18455 DOMAIN[i] = 0;
18456 DOMAIN.as_mut_ptr()
18457}
18458
18459#[no_mangle]
18460pub unsafe extern "C" fn bindtextdomain(_domainname: *const core::ffi::c_char, dirname: *const core::ffi::c_char) -> *mut core::ffi::c_char {
18461 dirname as *mut core::ffi::c_char
18462}
18463
18464#[no_mangle]
18465pub unsafe extern "C" fn bind_textdomain_codeset(_domainname: *const core::ffi::c_char, codeset: *const core::ffi::c_char) -> *mut core::ffi::c_char {
18466 codeset as *mut core::ffi::c_char
18467}
18468
18469#[no_mangle]
18474pub unsafe extern "C" fn wmemcpy(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18475 let mut i = 0;
18476 while i < n {
18477 *dest.add(i) = *src.add(i);
18478 i += 1;
18479 }
18480 dest
18481}
18482
18483#[no_mangle]
18484pub unsafe extern "C" fn wmemmove(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18485 if dest as usize <= src as usize {
18486 let mut i = 0;
18487 while i < n {
18488 *dest.add(i) = *src.add(i);
18489 i += 1;
18490 }
18491 } else {
18492 let mut i = n;
18493 while i > 0 {
18494 i -= 1;
18495 *dest.add(i) = *src.add(i);
18496 }
18497 }
18498 dest
18499}
18500
18501#[no_mangle]
18502pub unsafe extern "C" fn wmemset(dest: *mut u32, c: u32, n: usize) -> *mut u32 {
18503 let mut i = 0;
18504 while i < n {
18505 *dest.add(i) = c;
18506 i += 1;
18507 }
18508 dest
18509}
18510
18511#[no_mangle]
18512pub unsafe extern "C" fn wmemcmp(s1: *const u32, s2: *const u32, n: usize) -> i32 {
18513 let mut i = 0;
18514 while i < n {
18515 let c1 = *s1.add(i);
18516 let c2 = *s2.add(i);
18517 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
18518 i += 1;
18519 }
18520 0
18521}
18522
18523#[no_mangle]
18524pub unsafe extern "C" fn wmemchr(s: *const u32, c: u32, n: usize) -> *mut u32 {
18525 let mut i = 0;
18526 while i < n {
18527 if *s.add(i) == c { return s.add(i) as *mut u32; }
18528 i += 1;
18529 }
18530 core::ptr::null_mut()
18531}
18532
18533#[no_mangle]
18534pub unsafe extern "C" fn wcpcpy(dest: *mut u32, src: *const u32) -> *mut u32 {
18535 let mut i = 0;
18536 loop {
18537 let c = *src.add(i);
18538 *dest.add(i) = c;
18539 if c == 0 { return dest.add(i); }
18540 i += 1;
18541 }
18542}
18543
18544#[no_mangle]
18545pub unsafe extern "C" fn wcpncpy(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18546 let mut i = 0;
18547 while i < n {
18548 let c = *src.add(i);
18549 *dest.add(i) = c;
18550 if c == 0 { return dest.add(i); }
18551 i += 1;
18552 }
18553 dest.add(n)
18554}
18555
18556#[no_mangle]
18557pub unsafe extern "C" fn wprintf(fmt: *const wchar_t, args: ...) -> c_int {
18558 vfwprintf(stdout, fmt, args)
18559}
18560
18561#[no_mangle]
18562pub unsafe extern "C" fn vwprintf(fmt: *const wchar_t, ap: core::ffi::VaList) -> c_int {
18563 vfwprintf(stdout, fmt, ap)
18564}
18565
18566#[no_mangle]
18571pub unsafe extern "C" fn c16rtomb(s: *mut u8, c16: u16, ps: *mut core::ffi::c_void) -> usize {
18572 let state = ps as *mut u32;
18574 let saved: u32 = if state.is_null() { 0 } else { *state };
18575 if s.is_null() {
18576 if !state.is_null() { *state = 0; }
18577 return 1;
18578 }
18579 let cp: u32;
18580 if saved != 0 {
18581 if c16 < 0xdc00 || c16 > 0xdfff {
18582 if !state.is_null() { *state = 0; }
18583 ERRNO!() = EILSEQ;
18584 return !0usize;
18585 }
18586 cp = 0x10000 + (((saved - 0xd800) << 10) | ((c16 as u32) - 0xdc00));
18587 if !state.is_null() { *state = 0; }
18588 } else if c16 >= 0xd800 && c16 <= 0xdbff {
18589 if !state.is_null() { *state = c16 as u32; }
18590 return 0;
18591 } else if c16 >= 0xdc00 && c16 <= 0xdfff {
18592 ERRNO!() = EILSEQ;
18593 return !0usize;
18594 } else {
18595 cp = c16 as u32;
18596 }
18597 if cp < 0x80 {
18598 *s = cp as u8;
18599 1
18600 } else if cp < 0x800 {
18601 *s = (0xc0 | (cp >> 6)) as u8;
18602 *s.add(1) = (0x80 | (cp & 0x3f)) as u8;
18603 2
18604 } else if cp < 0x10000 {
18605 *s = (0xe0 | (cp >> 12)) as u8;
18606 *s.add(1) = (0x80 | ((cp >> 6) & 0x3f)) as u8;
18607 *s.add(2) = (0x80 | (cp & 0x3f)) as u8;
18608 3
18609 } else {
18610 *s = (0xf0 | (cp >> 18)) as u8;
18611 *s.add(1) = (0x80 | ((cp >> 12) & 0x3f)) as u8;
18612 *s.add(2) = (0x80 | ((cp >> 6) & 0x3f)) as u8;
18613 *s.add(3) = (0x80 | (cp & 0x3f)) as u8;
18614 4
18615 }
18616}
18617
18618#[no_mangle]
18619pub unsafe extern "C" fn c32rtomb(s: *mut u8, c32: u32, _ps: *mut core::ffi::c_void) -> usize {
18620 if s.is_null() { return 1; }
18621 if c32 > 0x10ffff || (c32 >= 0xd800 && c32 <= 0xdfff) {
18622 ERRNO!() = EILSEQ;
18623 return !0usize;
18624 }
18625 if c32 < 0x80 {
18626 *s = c32 as u8;
18627 1
18628 } else if c32 < 0x800 {
18629 *s = (0xc0 | (c32 >> 6)) as u8;
18630 *s.add(1) = (0x80 | (c32 & 0x3f)) as u8;
18631 2
18632 } else if c32 < 0x10000 {
18633 *s = (0xe0 | (c32 >> 12)) as u8;
18634 *s.add(1) = (0x80 | ((c32 >> 6) & 0x3f)) as u8;
18635 *s.add(2) = (0x80 | (c32 & 0x3f)) as u8;
18636 3
18637 } else {
18638 *s = (0xf0 | (c32 >> 18)) as u8;
18639 *s.add(1) = (0x80 | ((c32 >> 12) & 0x3f)) as u8;
18640 *s.add(2) = (0x80 | ((c32 >> 6) & 0x3f)) as u8;
18641 *s.add(3) = (0x80 | (c32 & 0x3f)) as u8;
18642 4
18643 }
18644}
18645
18646#[no_mangle]
18647pub unsafe extern "C" fn mbrtoc16(pc16: *mut u16, s: *const u8, n: usize, _ps: *mut core::ffi::c_void) -> usize {
18648 if s.is_null() { return 0; }
18649 if n == 0 { return 1; }
18650 let c = *s;
18651 if c == 0 { return 0; }
18652 if c < 0x80 {
18653 if !pc16.is_null() { *pc16 = c as u16; }
18654 return 1;
18655 }
18656 if c < 0xC2 { return 1; } if c < 0xE0 {
18658 if n < 2 { return 1; }
18659 let c2 = *s.add(1);
18660 if (c2 & 0xC0) != 0x80 { return 1; }
18661 if !pc16.is_null() { *pc16 = ((((c & 0x1F) as u32) << 6) | ((c2 & 0x3F) as u32)) as u16; }
18662 return 2;
18663 }
18664 if c < 0xF0 {
18665 if n < 3 { return 1; }
18666 let c2 = *s.add(1);
18667 let c3 = *s.add(2);
18668 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 { return 1; }
18669 if !pc16.is_null() { *pc16 = ((((c & 0x0F) as u32) << 12) | (((c2 & 0x3F) as u32) << 6) | ((c3 & 0x3F) as u32)) as u16; }
18670 return 3;
18671 }
18672 1
18673}
18674
18675#[no_mangle]
18676pub unsafe extern "C" fn mbrtoc32(pc32: *mut u32, s: *const u8, n: usize, _ps: *mut core::ffi::c_void) -> usize {
18677 if s.is_null() { return 0; }
18678 if n == 0 { return 1; }
18679 let c = *s;
18680 if c == 0 { return 0; }
18681 if c < 0x80 {
18682 if !pc32.is_null() { *pc32 = c as u32; }
18683 return 1;
18684 }
18685 if c < 0xC2 { return 1; } if c < 0xE0 {
18687 if n < 2 { return 1; }
18688 let c2 = *s.add(1);
18689 if (c2 & 0xC0) != 0x80 { return 1; }
18690 if !pc32.is_null() { *pc32 = (((c & 0x1F) as u32) << 6) | ((c2 & 0x3F) as u32); }
18691 return 2;
18692 }
18693 if c < 0xF0 {
18694 if n < 3 { return 1; }
18695 let c2 = *s.add(1);
18696 let c3 = *s.add(2);
18697 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 { return 1; }
18698 if !pc32.is_null() { *pc32 = (((c & 0x0F) as u32) << 12) | (((c2 & 0x3F) as u32) << 6) | ((c3 & 0x3F) as u32); }
18699 return 3;
18700 }
18701 if c < 0xF5 {
18702 if n < 4 { return 1; }
18703 let c2 = *s.add(1);
18704 let c3 = *s.add(2);
18705 let c4 = *s.add(3);
18706 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80 { return 1; }
18707 if !pc32.is_null() { *pc32 = (((c & 0x07) as u32) << 18) | (((c2 & 0x3F) as u32) << 12) | (((c3 & 0x3F) as u32) << 6) | ((c4 & 0x3F) as u32); }
18708 return 4;
18709 }
18710 1
18711}
18712
18713#[no_mangle]
18725pub unsafe extern "C" fn chown(path: *const core::ffi::c_char, uid: u32, gid: u32) -> i32 {
18726 syscall_ret(<Arch as Syscalls>::syscall5(
18727 SYS_FCHOWNAT,
18728 AT_FDCWD as i64,
18729 path as i64,
18730 uid as i64,
18731 gid as i64,
18732 0,
18733 )) as i32
18734}
18735
18736#[no_mangle]
18737pub unsafe extern "C" fn lchown(path: *const core::ffi::c_char, uid: u32, gid: u32) -> i32 {
18738 syscall_ret(<Arch as Syscalls>::syscall5(
18739 SYS_FCHOWNAT,
18740 AT_FDCWD as i64,
18741 path as i64,
18742 uid as i64,
18743 gid as i64,
18744 0x100, )) as i32
18746}
18747
18748#[no_mangle]
18753pub unsafe extern "C" fn chroot(path: *const core::ffi::c_char) -> i32 {
18754 syscall_ret(<Arch as Syscalls>::syscall1(SYS_CHROOT, path as i64)) as i32
18755}
18756
18757#[no_mangle]
18758pub unsafe extern "C" fn get_current_dir_name() -> *mut core::ffi::c_char {
18759 static mut BUF: [core::ffi::c_char; 4096] = [0; 4096];
18760 let r = getcwd(BUF.as_mut_ptr(), 4096);
18761 if r.is_null() { core::ptr::null_mut() } else { BUF.as_mut_ptr() }
18762}
18763
18764#[no_mangle]
18769pub unsafe extern "C" fn creat(pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18770 open(pathname, 1 | 0o100 | 0o1000, mode as i32)
18772}
18773
18774#[no_mangle]
18775pub unsafe extern "C" fn openat(dirfd: i32, pathname: *const core::ffi::c_char, flags: i32, mode: u32) -> i32 {
18776 syscall_ret(<Arch as Syscalls>::syscall4(SYS_OPENAT, dirfd as i64, pathname as i64, flags as i64, mode as i64)) as i32
18777}
18778
18779#[no_mangle]
18780pub unsafe extern "C" fn pwrite(fd: i32, buf: *const u8, count: usize, offset: i64) -> isize {
18781 syscall_ret(<Arch as Syscalls>::syscall4(sysno(18, 68), fd as i64, buf as i64, count as i64, offset)) as isize
18782}
18783
18784#[no_mangle]
18785pub unsafe extern "C" fn readv(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32) -> isize {
18786 syscall_ret(<Arch as Syscalls>::syscall3(sysno(19, 65), fd as i64, iov as i64, iovcnt as i64)) as isize
18787}
18788
18789#[no_mangle]
18790pub unsafe extern "C" fn writev(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32) -> isize {
18791 syscall_ret(<Arch as Syscalls>::syscall3(sysno(20, 66), fd as i64, iov as i64, iovcnt as i64)) as isize
18792}
18793
18794#[no_mangle]
18799pub unsafe extern "C" fn flock(fd: i32, operation: i32) -> i32 {
18800 syscall_ret(<Arch as Syscalls>::syscall2(SYS_FLOCK, fd as i64, operation as i64)) as i32
18801}
18802
18803#[no_mangle]
18804pub unsafe extern "C" fn lockf(fd: i32, cmd: i32, len: i64) -> i32 {
18805 let r = <Arch as Syscalls>::syscall3(SYS_FCNTL, fd as i64, if cmd == 0 { 7 } else if cmd == 1 { 6 } else { 5 } , len);
18806 if r < 0 { return -1; }
18807 0
18808}
18809
18810#[no_mangle]
18815pub unsafe extern "C" fn getdomainname(name: *mut core::ffi::c_char, len: usize) -> i32 {
18816 if name.is_null() || len == 0 {
18817 ERRNO!() = EINVAL;
18818 return -1;
18819 }
18820 let mut uts: UtsName = core::mem::zeroed();
18821 let r = <Arch as Syscalls>::syscall1(SYS_UNAME, &mut uts as *mut UtsName as i64);
18822 if r < 0 {
18823 ERRNO!() = (-r) as c_int;
18824 return -1;
18825 }
18826 let mut n = 0usize;
18827 while n < uts.domainname.len() && uts.domainname[n] != 0 { n += 1; }
18828 if n >= len {
18829 ERRNO!() = EINVAL;
18830 return -1;
18831 }
18832 core::ptr::copy_nonoverlapping(uts.domainname.as_ptr(), name as *mut u8, n);
18833 *name.add(n) = 0;
18834 0
18835}
18836
18837#[no_mangle]
18838pub unsafe extern "C" fn setdomainname(name: *const core::ffi::c_char, len: usize) -> i32 {
18839 syscall_ret(<Arch as Syscalls>::syscall2(sysno(171, 162), name as i64, len as i64)) as i32
18840}
18841
18842#[no_mangle]
18843pub unsafe extern "C" fn sethostname(name: *const core::ffi::c_char, len: usize) -> i32 {
18844 syscall_ret(<Arch as Syscalls>::syscall2(SYS_SETHOSTNAME, name as i64, len as i64)) as i32
18845}
18846
18847#[no_mangle]
18848pub unsafe extern "C" fn getlogin_r(name: *mut core::ffi::c_char, bufsize: usize) -> i32 {
18849 let user = crate::getenv(b"USER\0".as_ptr() as *const core::ffi::c_char);
18851 if user.is_null() { return 2; }
18852 let mut i = 0;
18853 while i < bufsize - 1 && *user.add(i) != 0 {
18854 *name.add(i) = *user.add(i);
18855 i += 1;
18856 }
18857 *name.add(i) = 0;
18858 0
18859}
18860
18861#[no_mangle]
18862pub unsafe extern "C" fn cuserid(s: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
18863 let user = crate::getenv(b"USER\0".as_ptr() as *const core::ffi::c_char);
18864 if user.is_null() { return core::ptr::null_mut(); }
18865 if s.is_null() {
18866 static mut BUF: [core::ffi::c_char; 32] = [0; 32];
18867 let mut i = 0;
18868 while i < 31 && *user.add(i) != 0 { BUF[i] = *user.add(i); i += 1; }
18869 BUF[i] = 0;
18870 BUF.as_mut_ptr()
18871 } else {
18872 let mut i = 0;
18873 while i < 31 && *user.add(i) != 0 { *s.add(i) = *user.add(i); i += 1; }
18874 *s.add(i) = 0;
18875 s
18876 }
18877}
18878
18879#[repr(C)]
18884#[derive(Copy, Clone)]
18885pub struct Passwd {
18886 pub pw_name: *mut c_char,
18887 pub pw_passwd: *mut c_char,
18888 pub pw_uid: u32,
18889 pub pw_gid: u32,
18890 pub pw_gecos: *mut c_char,
18891 pub pw_dir: *mut c_char,
18892 pub pw_shell: *mut c_char,
18893}
18894
18895#[repr(C)]
18896#[derive(Copy, Clone)]
18897pub struct Group {
18898 pub gr_name: *mut c_char,
18899 pub gr_passwd: *mut c_char,
18900 pub gr_gid: u32,
18901 pub gr_mem: *mut *mut c_char,
18902}
18903
18904static mut PWD_ENT: Passwd = Passwd {
18905 pw_name: core::ptr::null_mut(), pw_passwd: core::ptr::null_mut(),
18906 pw_uid: 0, pw_gid: 0, pw_gecos: core::ptr::null_mut(),
18907 pw_dir: core::ptr::null_mut(), pw_shell: core::ptr::null_mut(),
18908};
18909static mut PWD_BUF: [c_char; 1024] = [0; 1024];
18910static mut PWD_FILE: *mut FILE = core::ptr::null_mut();
18911
18912static mut GRP_ENT: Group = Group {
18913 gr_name: core::ptr::null_mut(), gr_passwd: core::ptr::null_mut(),
18914 gr_gid: 0, gr_mem: core::ptr::null_mut(),
18915};
18916static mut GRP_BUF: [c_char; 2048] = [0; 2048];
18917static mut GRP_MEM: [*mut c_char; 32] = [core::ptr::null_mut(); 32];
18918static mut GRP_FILE: *mut FILE = core::ptr::null_mut();
18919
18920unsafe fn parse_passwd(line: *const c_char, ent: *mut Passwd, buf: *mut c_char, buflen: usize) -> bool {
18921 let mut src = line;
18922 let mut o = 0usize;
18923 let mut fields: [*mut c_char; 7] = [core::ptr::null_mut(); 7];
18924 let mut n = 0usize;
18925 while n < 7 {
18926 let start = o;
18927 while *src != 0 && *src != b':' as c_char {
18928 if o + 1 >= buflen { return false; }
18929 *buf.add(o) = *src;
18930 o += 1;
18931 src = src.add(1);
18932 }
18933 *buf.add(o) = 0;
18934 o += 1;
18935 fields[n] = buf.add(start);
18936 n += 1;
18937 if *src == 0 { break; }
18938 src = src.add(1);
18939 }
18940 if n < 7 { return false; }
18941 (*ent).pw_name = fields[0];
18942 (*ent).pw_passwd = fields[1];
18943 (*ent).pw_uid = crate::strtol(fields[2], core::ptr::null_mut(), 10) as u32;
18944 (*ent).pw_gid = crate::strtol(fields[3], core::ptr::null_mut(), 10) as u32;
18945 (*ent).pw_gecos = fields[4];
18946 (*ent).pw_dir = fields[5];
18947 (*ent).pw_shell = fields[6];
18948 true
18949}
18950
18951unsafe fn parse_group(line: *const c_char, ent: *mut Group, buf: *mut c_char, buflen: usize) -> bool {
18952 let mut src = line;
18953 let mut o = 0usize;
18954 let mut fields: [*mut c_char; 4] = [core::ptr::null_mut(); 4];
18955 let mut n = 0usize;
18956 while n < 4 {
18957 let start = o;
18958 while *src != 0 && *src != b':' as c_char {
18959 if o + 1 >= buflen { return false; }
18960 *buf.add(o) = *src;
18961 o += 1;
18962 src = src.add(1);
18963 }
18964 *buf.add(o) = 0;
18965 o += 1;
18966 fields[n] = buf.add(start);
18967 n += 1;
18968 if *src == 0 { break; }
18969 src = src.add(1);
18970 }
18971 if n < 4 { return false; }
18972 (*ent).gr_name = fields[0];
18973 (*ent).gr_passwd = fields[1];
18974 (*ent).gr_gid = crate::strtol(fields[2], core::ptr::null_mut(), 10) as u32;
18975 let mut mi = 0usize;
18976 let mut m = fields[3];
18977 if *m != 0 {
18978 loop {
18979 if mi + 1 >= GRP_MEM.len() { break; }
18980 GRP_MEM[mi] = m;
18981 mi += 1;
18982 while *m != 0 && *m != b',' as c_char { m = m.add(1); }
18983 if *m == 0 { break; }
18984 *m = 0;
18985 m = m.add(1);
18986 }
18987 }
18988 GRP_MEM[mi] = core::ptr::null_mut();
18989 (*ent).gr_mem = GRP_MEM.as_mut_ptr();
18990 true
18991}
18992
18993#[no_mangle]
18994pub unsafe extern "C" fn getpwnam(name: *const c_char) -> *mut Passwd {
18995 if name.is_null() { return core::ptr::null_mut(); }
18996 setpwent();
18997 loop {
18998 let p = getpwent();
18999 if p.is_null() { break; }
19000 if crate::strcmp((*p).pw_name as *const u8, name as *const u8) == 0 { endpwent(); return p; }
19001 }
19002 endpwent();
19003 core::ptr::null_mut()
19004}
19005
19006#[no_mangle]
19007pub unsafe extern "C" fn getpwuid(uid: u32) -> *mut Passwd {
19008 setpwent();
19009 loop {
19010 let p = getpwent();
19011 if p.is_null() { break; }
19012 if (*p).pw_uid == uid { endpwent(); return p; }
19013 }
19014 endpwent();
19015 core::ptr::null_mut()
19016}
19017
19018#[no_mangle]
19019pub unsafe extern "C" fn setpwent() {
19020 endpwent();
19021 PWD_FILE = crate::fopen(b"/etc/passwd\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
19022}
19023
19024#[no_mangle]
19025pub unsafe extern "C" fn getpwent() -> *mut Passwd {
19026 if PWD_FILE.is_null() { setpwent(); if PWD_FILE.is_null() { return core::ptr::null_mut(); } }
19027 let mut line = [0 as c_char; 1024];
19028 loop {
19029 if crate::fgets(line.as_mut_ptr(), 1024, PWD_FILE).is_null() { return core::ptr::null_mut(); }
19030 if parse_passwd(line.as_ptr(), &raw mut PWD_ENT, PWD_BUF.as_mut_ptr(), PWD_BUF.len()) {
19031 return &raw mut PWD_ENT;
19032 }
19033 }
19034}
19035
19036#[no_mangle]
19037pub unsafe extern "C" fn endpwent() {
19038 if !PWD_FILE.is_null() { crate::fclose(PWD_FILE); PWD_FILE = core::ptr::null_mut(); }
19039}
19040
19041#[no_mangle]
19042pub unsafe extern "C" fn getpwnam_r(name: *const c_char, pwd: *mut Passwd, _buf: *mut c_char, _buflen: usize, result: *mut *mut Passwd) -> c_int {
19043 if result.is_null() { return EINVAL; }
19044 let p = getpwnam(name);
19045 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *pwd = *p; *result = pwd; 0 }
19046}
19047
19048#[no_mangle]
19049pub unsafe extern "C" fn getpwuid_r(uid: u32, pwd: *mut Passwd, _buf: *mut c_char, _buflen: usize, result: *mut *mut Passwd) -> c_int {
19050 if result.is_null() { return EINVAL; }
19051 let p = getpwuid(uid);
19052 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *pwd = *p; *result = pwd; 0 }
19053}
19054
19055#[no_mangle]
19056pub unsafe extern "C" fn fgetpwent(f: *mut FILE) -> *mut Passwd {
19057 if f.is_null() { return core::ptr::null_mut(); }
19058 let mut line = [0 as c_char; 1024];
19059 loop {
19060 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
19061 if parse_passwd(line.as_ptr(), &raw mut PWD_ENT, PWD_BUF.as_mut_ptr(), PWD_BUF.len()) {
19062 return &raw mut PWD_ENT;
19063 }
19064 }
19065}
19066
19067#[no_mangle]
19068pub unsafe extern "C" fn putpwent(f: *mut FILE, p: *const Passwd) -> c_int {
19069 if f.is_null() || p.is_null() { return -1; }
19070 crate::fprintf(f, b"%s:%s:%u:%u:%s:%s:%s\n\0".as_ptr() as *const c_char,
19071 (*p).pw_name, (*p).pw_passwd, (*p).pw_uid, (*p).pw_gid,
19072 (*p).pw_gecos, (*p).pw_dir, (*p).pw_shell)
19073}
19074
19075#[no_mangle]
19076pub unsafe extern "C" fn getgrnam(name: *const c_char) -> *mut Group {
19077 if name.is_null() { return core::ptr::null_mut(); }
19078 setgrent();
19079 loop {
19080 let g = getgrent();
19081 if g.is_null() { break; }
19082 if crate::strcmp((*g).gr_name as *const u8, name as *const u8) == 0 { endgrent(); return g; }
19083 }
19084 endgrent();
19085 core::ptr::null_mut()
19086}
19087
19088#[no_mangle]
19089pub unsafe extern "C" fn getgrgid(gid: u32) -> *mut Group {
19090 setgrent();
19091 loop {
19092 let g = getgrent();
19093 if g.is_null() { break; }
19094 if (*g).gr_gid == gid { endgrent(); return g; }
19095 }
19096 endgrent();
19097 core::ptr::null_mut()
19098}
19099
19100#[no_mangle]
19101pub unsafe extern "C" fn setgrent() {
19102 endgrent();
19103 GRP_FILE = crate::fopen(b"/etc/group\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
19104}
19105
19106#[no_mangle]
19107pub unsafe extern "C" fn getgrent() -> *mut Group {
19108 if GRP_FILE.is_null() { setgrent(); if GRP_FILE.is_null() { return core::ptr::null_mut(); } }
19109 let mut line = [0 as c_char; 1024];
19110 loop {
19111 if crate::fgets(line.as_mut_ptr(), 1024, GRP_FILE).is_null() { return core::ptr::null_mut(); }
19112 if parse_group(line.as_ptr(), &raw mut GRP_ENT, GRP_BUF.as_mut_ptr(), GRP_BUF.len()) {
19113 return &raw mut GRP_ENT;
19114 }
19115 }
19116}
19117
19118#[no_mangle]
19119pub unsafe extern "C" fn endgrent() {
19120 if !GRP_FILE.is_null() { crate::fclose(GRP_FILE); GRP_FILE = core::ptr::null_mut(); }
19121}
19122
19123#[no_mangle]
19124pub unsafe extern "C" fn getgrnam_r(name: *const c_char, grp: *mut Group, _buf: *mut c_char, _buflen: usize, result: *mut *mut Group) -> c_int {
19125 if result.is_null() { return EINVAL; }
19126 let g = getgrnam(name);
19127 if g.is_null() { *result = core::ptr::null_mut(); 0 } else { *grp = *g; *result = grp; 0 }
19128}
19129
19130#[no_mangle]
19131pub unsafe extern "C" fn getgrgid_r(gid: u32, grp: *mut Group, _buf: *mut c_char, _buflen: usize, result: *mut *mut Group) -> c_int {
19132 if result.is_null() { return EINVAL; }
19133 let g = getgrgid(gid);
19134 if g.is_null() { *result = core::ptr::null_mut(); 0 } else { *grp = *g; *result = grp; 0 }
19135}
19136
19137#[no_mangle]
19138pub unsafe extern "C" fn fgetgrent(f: *mut FILE) -> *mut Group {
19139 if f.is_null() { return core::ptr::null_mut(); }
19140 let mut line = [0 as c_char; 1024];
19141 loop {
19142 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
19143 if parse_group(line.as_ptr(), &raw mut GRP_ENT, GRP_BUF.as_mut_ptr(), GRP_BUF.len()) {
19144 return &raw mut GRP_ENT;
19145 }
19146 }
19147}
19148
19149#[no_mangle]
19150pub unsafe extern "C" fn putgrent(f: *mut FILE, g: *const Group) -> c_int {
19151 if f.is_null() || g.is_null() { return -1; }
19152 crate::fprintf(f, b"%s:%s:%u:\0".as_ptr() as *const c_char, (*g).gr_name, (*g).gr_passwd, (*g).gr_gid);
19153 if !(*g).gr_mem.is_null() {
19154 let mut i = 0;
19155 while !(*(*g).gr_mem.add(i)).is_null() {
19156 if i > 0 { crate::fputc(b',' as c_int, f); }
19157 crate::fputs(*(*g).gr_mem.add(i), f);
19158 i += 1;
19159 }
19160 }
19161 crate::fputc(b'\n' as c_int, f);
19162 0
19163}
19164
19165#[no_mangle]
19170pub unsafe extern "C" fn setgroups(ngroups: usize, gidset: *const u32) -> i32 {
19171 syscall_ret(<Arch as Syscalls>::syscall2(SYS_SETGROUPS, ngroups as i64, gidset as i64)) as i32
19172}
19173
19174#[no_mangle]
19175pub unsafe extern "C" fn setresuid(ruid: u32, euid: u32, suid: u32) -> i32 {
19176 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SETRESUID, ruid as i64, euid as i64, suid as i64)) as i32
19177}
19178
19179#[no_mangle]
19180pub unsafe extern "C" fn setresgid(rgid: u32, egid: u32, sgid: u32) -> i32 {
19181 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SETRESGID, rgid as i64, egid as i64, sgid as i64)) as i32
19182}
19183
19184#[no_mangle]
19185pub unsafe extern "C" fn getresuid(ruid: *mut u32, euid: *mut u32, suid: *mut u32) -> i32 {
19186 syscall_ret(<Arch as Syscalls>::syscall3(SYS_GETRESUID, ruid as i64, euid as i64, suid as i64)) as i32
19187}
19188
19189#[no_mangle]
19190pub unsafe extern "C" fn getresgid(rgid: *mut u32, egid: *mut u32, sgid: *mut u32) -> i32 {
19191 syscall_ret(<Arch as Syscalls>::syscall3(SYS_GETRESGID, rgid as i64, egid as i64, sgid as i64)) as i32
19192}
19193
19194#[repr(C)]
19202struct KernelMsgHdr {
19203 msg_name: *mut c_void,
19204 msg_namelen: u32,
19205 __pad0: u32,
19206 msg_iov: *mut c_void,
19207 msg_iovlen: u64,
19208 msg_control: *mut c_void,
19209 msg_controllen: u64,
19210 msg_flags: u32,
19211 __pad1: u32,
19212}
19213
19214#[repr(C)]
19215struct UserMsgHdr {
19216 msg_name: *mut c_void,
19217 msg_namelen: u32,
19218 msg_iov: *mut c_void,
19219 msg_iovlen: i32,
19220 __pad1: i32,
19221 msg_control: *mut c_void,
19222 msg_controllen: u32,
19223 __pad2: i32,
19224 msg_flags: i32,
19225}
19226
19227unsafe fn msg_to_kernel(msg: *const UserMsgHdr, out: &mut KernelMsgHdr) {
19228 *out = KernelMsgHdr {
19229 msg_name: (*msg).msg_name,
19230 msg_namelen: (*msg).msg_namelen,
19231 __pad0: 0,
19232 msg_iov: (*msg).msg_iov,
19233 msg_iovlen: (*msg).msg_iovlen as u32 as u64,
19234 msg_control: (*msg).msg_control,
19235 msg_controllen: (*msg).msg_controllen as u64,
19236 msg_flags: (*msg).msg_flags as u32,
19237 __pad1: 0,
19238 };
19239}
19240
19241#[no_mangle]
19242pub unsafe extern "C" fn sendmsg(fd: i32, msg: *const core::ffi::c_void, flags: i32) -> isize {
19243 if msg.is_null() {
19244 ERRNO!() = EINVAL;
19245 return -1;
19246 }
19247 let mut k: KernelMsgHdr = core::mem::zeroed();
19248 msg_to_kernel(msg as *const UserMsgHdr, &mut k);
19249 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SENDMSG, fd as i64, &k as *const KernelMsgHdr as i64, flags as i64)) as isize
19250}
19251
19252#[no_mangle]
19253pub unsafe extern "C" fn recvmsg(fd: i32, msg: *mut core::ffi::c_void, flags: i32) -> isize {
19254 if msg.is_null() {
19255 ERRNO!() = EINVAL;
19256 return -1;
19257 }
19258 let user = msg as *mut UserMsgHdr;
19259 let mut k: KernelMsgHdr = core::mem::zeroed();
19260 msg_to_kernel(user, &mut k);
19261 let r = syscall_ret(<Arch as Syscalls>::syscall3(SYS_RECVMSG, fd as i64, &mut k as *mut KernelMsgHdr as i64, flags as i64));
19262 (*user).msg_flags = k.msg_flags as i32;
19263 (*user).msg_controllen = k.msg_controllen as u32;
19264 r as isize
19265}
19266
19267#[no_mangle]
19268pub unsafe extern "C" fn sendmmsg(fd: i32, msgvec: *mut core::ffi::c_void, vlen: u32, flags: i32) -> i32 {
19269 syscall_ret(<Arch as Syscalls>::syscall4(sysno(307, 269), fd as i64, msgvec as i64, vlen as i64, flags as i64)) as i32
19270}
19271
19272#[no_mangle]
19273pub unsafe extern "C" fn recvmmsg(fd: i32, msgvec: *mut core::ffi::c_void, vlen: u32, flags: i32, timeout: *mut core::ffi::c_void) -> i32 {
19274 syscall_ret(<Arch as Syscalls>::syscall5(sysno(299, 243), fd as i64, msgvec as i64, vlen as i64, flags as i64, timeout as i64)) as i32
19275}
19276
19277#[no_mangle]
19278pub unsafe extern "C" fn getpeername(fd: i32, addr: *mut core::ffi::c_void, addrlen: *mut u32) -> i32 {
19279 syscall_ret(<Arch as Syscalls>::syscall3(sysno(52, 205), fd as i64, addr as i64, addrlen as i64)) as i32
19280}
19281
19282#[no_mangle]
19283pub unsafe extern "C" fn getsockopt(fd: i32, level: i32, optname: i32, optval: *mut core::ffi::c_void, optlen: *mut u32) -> i32 {
19284 syscall_ret(<Arch as Syscalls>::syscall5(sysno(55, 209), fd as i64, level as i64, optname as i64, optval as i64, optlen as i64)) as i32
19285}
19286
19287#[no_mangle]
19292pub unsafe extern "C" fn ftrylockfile(file: *mut FILE) -> i32 {
19293 if file.is_null() { return EINVAL; }
19294 if (*file).lock < 0 { return 0; }
19295 let tid = sys_gettid() as c_int;
19296 let v = a_load(&raw const (*file).lock);
19297 if v == tid {
19298 (*file).lockcount += 1;
19299 return 0;
19300 }
19301 if v == 0 && a_cas(&raw mut (*file).lock, 0, tid) == 0 {
19302 (*file).lockcount = 1;
19303 return 0;
19304 }
19305 EBUSY
19306}
19307
19308#[no_mangle]
19309pub unsafe extern "C" fn getc_unlocked(file: *mut core::ffi::c_char) -> i32 {
19310 getc(file as *mut FILE)
19311}
19312
19313#[no_mangle]
19314pub unsafe extern "C" fn getchar_unlocked() -> i32 {
19315 getchar()
19316}
19317
19318#[no_mangle]
19319pub unsafe extern "C" fn putc_unlocked(c: i32, file: *mut core::ffi::c_char) -> i32 {
19320 putc(c, file as *mut FILE)
19321}
19322
19323#[no_mangle]
19324pub unsafe extern "C" fn putchar_unlocked(c: i32) -> i32 {
19325 putchar(c)
19326}
19327
19328#[no_mangle] pub static mut optarg: *mut core::ffi::c_char = core::ptr::null_mut();
19333#[no_mangle] pub static mut optind: i32 = 1;
19334#[no_mangle] pub static mut opterr: i32 = 1;
19335#[no_mangle] pub static mut optopt: i32 = '?' as i32;
19336#[no_mangle] pub static mut optreset: i32 = 0;
19337
19338#[no_mangle]
19343pub unsafe extern "C" fn getitimer(which: i32, curr_value: *mut core::ffi::c_void) -> i32 {
19344 syscall_ret(<Arch as Syscalls>::syscall2(sysno(36, 102), which as i64, curr_value as i64)) as i32
19345}
19346
19347#[no_mangle]
19348pub unsafe extern "C" fn setitimer(which: i32, new_value: *const core::ffi::c_void, old_value: *mut core::ffi::c_void) -> i32 {
19349 syscall_ret(<Arch as Syscalls>::syscall3(sysno(38, 103), which as i64, new_value as i64, old_value as i64)) as i32
19350}
19351
19352#[no_mangle]
19357pub unsafe extern "C" fn getloadavg(loadavg: *mut f64, nelem: i32) -> i32 {
19358 let fd = crate::open(b"/proc/loadavg\0".as_ptr() as *const core::ffi::c_char, 0, 0);
19359 if fd < 0 { return -1; }
19360 let mut buf: [u8; 64] = [0; 64];
19361 let n = crate::read(fd, buf.as_mut_ptr() as *mut core::ffi::c_void, 63);
19362 crate::close(fd);
19363 if n <= 0 { return -1; }
19364 buf[n as usize] = 0;
19365 let mut i = 0;
19366 while i < nelem as usize && i < 3 {
19367 let val = crate::strtod((buf.as_ptr() as *const core::ffi::c_char).add(i * 5), core::ptr::null_mut());
19368 *loadavg.add(i) = val;
19369 i += 1;
19370 }
19371 i as i32
19372}
19373
19374#[no_mangle]
19375pub unsafe extern "C" fn get_nprocs() -> i32 {
19376 sysconf(84) as i32 }
19378
19379#[no_mangle]
19380pub unsafe extern "C" fn get_nprocs_conf() -> i32 {
19381 sysconf(83) as i32 }
19383
19384#[no_mangle]
19385pub unsafe extern "C" fn get_avphys_pages() -> i64 {
19386 sysconf(86) }
19388
19389#[no_mangle]
19390pub unsafe extern "C" fn get_phys_pages() -> i64 {
19391 sysconf(85) }
19393
19394#[no_mangle]
19399pub unsafe extern "C" fn capget(header: *mut core::ffi::c_void, data: *mut core::ffi::c_void) -> i32 {
19400 syscall_ret(<Arch as Syscalls>::syscall2(SYS_CAPGET, header as i64, data as i64)) as i32
19401}
19402
19403#[no_mangle]
19404pub unsafe extern "C" fn capset(header: *const core::ffi::c_void, data: *const core::ffi::c_void) -> i32 {
19405 syscall_ret(<Arch as Syscalls>::syscall2(SYS_CAPSET, header as i64, data as i64)) as i32
19406}
19407
19408#[no_mangle]
19409pub unsafe extern "C" fn arch_prctl(code: i32, addr: u64) -> i32 {
19410 if cfg!(target_arch = "x86_64") { syscall_ret(<Arch as Syscalls>::syscall2(158, code as i64, addr as i64)) as i32 } else { ERRNO!() = 38; -1 }
19411}
19412
19413#[no_mangle]
19418pub unsafe extern "C" fn cfgetospeed(termios_p: *const core::ffi::c_void) -> u32 {
19419 unsafe { *(termios_p as *const u32).add(1) }
19420}
19421
19422#[no_mangle]
19423pub unsafe extern "C" fn cfgetispeed(termios_p: *const core::ffi::c_void) -> u32 {
19424 unsafe { *(termios_p as *const u32).add(2) }
19425}
19426
19427#[no_mangle]
19428pub unsafe extern "C" fn cfsetospeed(termios_p: *mut core::ffi::c_void, speed: u32) -> i32 {
19429 unsafe { *(termios_p as *mut u32).add(1) = speed; }
19430 0
19431}
19432
19433#[no_mangle]
19434pub unsafe extern "C" fn cfsetispeed(termios_p: *mut core::ffi::c_void, speed: u32) -> i32 {
19435 unsafe { *(termios_p as *mut u32).add(2) = speed; }
19436 0
19437}
19438
19439#[no_mangle]
19440pub unsafe extern "C" fn cfmakeraw(termios_p: *mut core::ffi::c_void) {
19441 unsafe {
19442 let p = termios_p as *mut u32;
19443 *p.add(0) &= !0o37;
19444 *p.add(0) &= !(0o4000 | 0o2000 | 0o10000 | 0o20);
19445 *p.add(0) |= 0o60;
19446 *p.add(3) &= !0o17;
19447 *p.add(3) &= !(0o1000 | 0o40000000);
19448 *p.add(1) = 1;
19449 *p.add(2) = 0;
19450 }
19451}
19452
19453#[no_mangle]
19458pub unsafe extern "C" fn getrusage(who: i32, usage: *mut core::ffi::c_void) -> i32 {
19459 syscall_ret(<Arch as Syscalls>::syscall2(sysno(98, 165), who as i64, usage as i64)) as i32
19460}
19461
19462#[no_mangle]
19463pub unsafe extern "C" fn getpriority(which: i32, who: u32) -> i32 {
19464 let r = <Arch as Syscalls>::syscall2(SYS_GETPRIORITY, which as i64, who as i64);
19466 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
19467 20 - r as i32
19468}
19469
19470#[no_mangle]
19471pub unsafe extern "C" fn setpriority(which: i32, who: u32, prio: i32) -> i32 {
19472 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SETPRIORITY, which as i64, who as i64, prio as i64)) as i32
19473}
19474
19475#[no_mangle]
19476pub unsafe extern "C" fn prlimit(pid: u32, resource: i32, new_limit: *const core::ffi::c_void, old_limit: *mut core::ffi::c_void) -> i32 {
19477 syscall_ret(<Arch as Syscalls>::syscall4(sysno(302, 261), pid as i64, resource as i64, new_limit as i64, old_limit as i64)) as i32
19478}
19479
19480#[no_mangle]
19485pub unsafe extern "C" fn clone(
19486 func: usize,
19487 stack: *mut u8,
19488 flags: c_int,
19489 arg: *mut c_void,
19490 mut args: ...
19491) -> c_int {
19492 const CLONE_PIDFD_C: c_int = 0x00001000;
19494 const CLONE_VM_C: c_int = 0x00000100;
19495 const CLONE_THREAD_C: c_int = 0x00010000;
19496 const CLONE_SETTLS_C: c_int = 0x00080000;
19497 const CLONE_PARENT_SETTID_C: c_int = 0x00100000;
19498 const CLONE_CHILD_SETTID_C: c_int = 0x01000000;
19499 const CLONE_CHILD_CLEARTID_C: c_int = 0x00200000;
19500 let _ = CLONE_VM_C;
19501 if flags & (CLONE_THREAD_C | CLONE_SETTLS_C | CLONE_CHILD_CLEARTID_C) != 0
19502 || stack.is_null()
19503 {
19504 ERRNO!() = EINVAL;
19505 return -1;
19506 }
19507 let mut ptid: *mut c_int = core::ptr::null_mut();
19508 let mut tls: c_ulong = 0;
19509 let mut ctid: *mut c_int = core::ptr::null_mut();
19510 if flags & (CLONE_PIDFD_C | CLONE_PARENT_SETTID_C | CLONE_CHILD_SETTID_C) != 0 {
19511 ptid = args.next_arg::<*mut c_int>();
19512 }
19513 if flags & CLONE_CHILD_SETTID_C != 0 {
19514 tls = args.next_arg::<c_ulong>();
19515 ctid = args.next_arg::<*mut c_int>();
19516 }
19517 let r = __rc_clone(func, stack, flags as c_ulong, arg, ptid, tls, ctid);
19518 if r < 0 {
19519 ERRNO!() = (-r) as c_int;
19520 -1
19521 } else {
19522 r as c_int
19523 }
19524}
19525
19526#[no_mangle]
19527pub unsafe extern "C" fn _Fork() -> i32 {
19528 crate::fork()
19529}
19530
19531#[no_mangle]
19532pub unsafe extern "C" fn forkpty(amaster: *mut i32, name: *mut core::ffi::c_char, termp: *const core::ffi::c_void, winp: *const core::ffi::c_void) -> i32 {
19533 let mut master: i32 = 0;
19534 let mut slave: i32 = 0;
19535 if openpty(&mut master, &mut slave, name, termp, winp) < 0 { return -1; }
19536 let pid = crate::fork();
19537 if pid < 0 { crate::close(master); crate::close(slave); return -1; }
19538 if pid == 0 {
19539 crate::close(master);
19540 crate::setsid();
19541 crate::dup2(slave, 0);
19542 crate::dup2(slave, 1);
19543 crate::dup2(slave, 2);
19544 } else {
19545 crate::close(slave);
19546 if !amaster.is_null() { *amaster = master; }
19547 }
19548 pid
19549}
19550
19551#[no_mangle]
19552pub unsafe extern "C" fn openpty(amaster: *mut i32, aslave: *mut i32, name: *mut core::ffi::c_char, _termp: *const core::ffi::c_void, _winp: *const core::ffi::c_void) -> i32 {
19553 let master = crate::open(b"/dev/ptmx\0".as_ptr() as *const core::ffi::c_char, 0o2000, 0);
19554 if master < 0 { return -1; }
19555 grantpt(master);
19556 unlockpt(master);
19557 let slave_name = ptsname(master);
19558 if slave_name.is_null() { crate::close(master); return -1; }
19559 let slave = crate::open(slave_name, 0o2000, 0);
19560 if slave < 0 { crate::close(master); return -1; }
19561 if !amaster.is_null() { *amaster = master; }
19562 if !aslave.is_null() { *aslave = slave; }
19563 if !name.is_null() { crate::strcpy(name as *mut u8, slave_name as *const u8); }
19564 0
19565}
19566
19567#[no_mangle]
19568pub unsafe extern "C" fn login_tty(fd: i32) -> i32 {
19569 crate::setsid();
19570 crate::dup2(fd, 0);
19571 crate::dup2(fd, 1);
19572 crate::dup2(fd, 2);
19573 0
19574}
19575
19576#[no_mangle]
19581pub unsafe extern "C" fn __dls2b() {}
19582#[no_mangle]
19583pub unsafe extern "C" fn __dls3() {}
19584#[no_mangle]
19585pub unsafe extern "C" fn _dlstart() {}
19586
19587#[no_mangle]
19592pub unsafe extern "C" fn index(s: *const core::ffi::c_char, c: i32) -> *mut core::ffi::c_char {
19593 let mut i = 0;
19594 loop {
19595 let ch = *s.add(i);
19596 if ch == c as core::ffi::c_char { return s.add(i) as *mut core::ffi::c_char; }
19597 if ch == 0 { return core::ptr::null_mut(); }
19598 i += 1;
19599 }
19600}
19601
19602#[no_mangle]
19603pub unsafe extern "C" fn rindex(s: *const core::ffi::c_char, c: i32) -> *mut core::ffi::c_char {
19604 let mut last = core::ptr::null_mut();
19605 let mut i = 0;
19606 loop {
19607 let ch = *s.add(i);
19608 if ch == 0 { return last; }
19609 if ch == c as core::ffi::c_char { last = s.add(i) as *mut core::ffi::c_char; }
19610 i += 1;
19611 }
19612}
19613
19614#[no_mangle]
19619pub unsafe extern "C" fn imaxabs(j: i64) -> i64 {
19620 j.abs()
19621}
19622
19623#[no_mangle]
19624pub unsafe extern "C" fn imaxdiv(numer: i64, denom: i64) -> (i64, i64) {
19625 (numer / denom, numer % denom)
19626}
19627
19628#[no_mangle]
19633pub static mut h_errno: i32 = 0;
19634
19635#[no_mangle]
19636pub unsafe extern "C" fn __h_errno_location() -> *mut i32 {
19637 &mut h_errno
19638}
19639
19640#[no_mangle]
19641pub unsafe extern "C" fn herror(s: *const core::ffi::c_char) {
19642 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
19643 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
19644 crate::write(2, hstrerror(*__h_errno_location()) as *const core::ffi::c_void, crate::strlen(hstrerror(*__h_errno_location())));
19645 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
19646}
19647
19648#[no_mangle]
19649pub unsafe extern "C" fn hstrerror(_err: i32) -> *const core::ffi::c_char {
19650 b"Unknown error\0".as_ptr() as *const core::ffi::c_char
19651}
19652
19653#[no_mangle]
19658pub unsafe extern "C" fn gettid() -> i32 {
19659 syscall_ret(<Arch as Syscalls>::syscall0(SYS_GETTID)) as i32
19660}
19661
19662#[no_mangle]
19667pub unsafe extern "C" fn ioctl(fd: i32, request: u32, mut args: ...) -> i32 {
19668 let arg = args.next_arg::<i64>();
19669 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, request as i64, arg)) as i32
19670}
19671
19672#[no_mangle]
19673pub unsafe extern "C" fn ioperm(from: u64, num: u64, turn_on: i32) -> i32 {
19674 #[cfg(target_arch = "x86_64")]
19675 { syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOPERM, from as i64, num as i64, turn_on as i64)) as i32 }
19676 #[cfg(not(target_arch = "x86_64"))]
19677 {
19678 let _ = (from, num, turn_on);
19679 ERRNO!() = ENOSYS_VAL;
19680 -1
19681 }
19682}
19683
19684#[no_mangle]
19685pub unsafe extern "C" fn iopl(level: i32) -> i32 {
19686 #[cfg(target_arch = "x86_64")]
19687 { syscall_ret(<Arch as Syscalls>::syscall1(SYS_IOPL, level as i64)) as i32 }
19688 #[cfg(not(target_arch = "x86_64"))]
19689 {
19690 let _ = level;
19691 ERRNO!() = ENOSYS_VAL;
19692 -1
19693 }
19694}
19695
19696#[no_mangle]
19701pub unsafe extern "C" fn getxattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19702 syscall_ret(<Arch as Syscalls>::syscall4(sysno(191, 8), path as i64, name as i64, value as i64, size as i64)) as isize
19703}
19704
19705#[no_mangle]
19706pub unsafe extern "C" fn lgetxattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19707 syscall_ret(<Arch as Syscalls>::syscall4(sysno(192, 9), path as i64, name as i64, value as i64, size as i64)) as isize
19708}
19709
19710#[no_mangle]
19711pub unsafe extern "C" fn fgetxattr(fd: i32, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19712 syscall_ret(<Arch as Syscalls>::syscall4(sysno(193, 10), fd as i64, name as i64, value as i64, size as i64)) as isize
19713}
19714
19715#[no_mangle]
19716pub unsafe extern "C" fn listxattr(path: *const core::ffi::c_char, list: *mut u8, size: usize) -> isize {
19717 syscall_ret(<Arch as Syscalls>::syscall3(sysno(194, 11), path as i64, list as i64, size as i64)) as isize
19718}
19719
19720#[no_mangle]
19721pub unsafe extern "C" fn llistxattr(path: *const core::ffi::c_char, list: *mut u8, size: usize) -> isize {
19722 syscall_ret(<Arch as Syscalls>::syscall3(sysno(195, 12), path as i64, list as i64, size as i64)) as isize
19723}
19724
19725#[no_mangle]
19726pub unsafe extern "C" fn flistxattr(fd: i32, list: *mut u8, size: usize) -> isize {
19727 syscall_ret(<Arch as Syscalls>::syscall3(sysno(196, 13), fd as i64, list as i64, size as i64)) as isize
19728}
19729
19730#[no_mangle]
19731pub unsafe extern "C" fn setxattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char, value: *const u8, size: usize, flags: i32) -> i32 {
19732 syscall_ret(<Arch as Syscalls>::syscall5(sysno(188, 5), path as i64, name as i64, value as i64, size as i64, flags as i64)) as i32
19733}
19734
19735#[no_mangle]
19736pub unsafe extern "C" fn lsetxattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char, value: *const u8, size: usize, flags: i32) -> i32 {
19737 syscall_ret(<Arch as Syscalls>::syscall5(sysno(189, 6), path as i64, name as i64, value as i64, size as i64, flags as i64)) as i32
19738}
19739
19740#[no_mangle]
19741pub unsafe extern "C" fn fsetxattr(fd: i32, name: *const core::ffi::c_char, value: *const u8, size: usize, flags: i32) -> i32 {
19742 syscall_ret(<Arch as Syscalls>::syscall5(sysno(190, 7), fd as i64, name as i64, value as i64, size as i64, flags as i64)) as i32
19743}
19744
19745#[no_mangle]
19746pub unsafe extern "C" fn removexattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char) -> i32 {
19747 syscall_ret(<Arch as Syscalls>::syscall2(sysno(197, 14), path as i64, name as i64)) as i32
19748}
19749
19750#[no_mangle]
19751pub unsafe extern "C" fn lremovexattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char) -> i32 {
19752 syscall_ret(<Arch as Syscalls>::syscall2(sysno(198, 15), path as i64, name as i64)) as i32
19753}
19754
19755#[no_mangle]
19756pub unsafe extern "C" fn fremovexattr(fd: i32, name: *const core::ffi::c_char) -> i32 {
19757 syscall_ret(<Arch as Syscalls>::syscall2(sysno(199, 16), fd as i64, name as i64)) as i32
19758}
19759
19760#[no_mangle]
19765pub unsafe extern "C" fn adjtime(_delta: *const core::ffi::c_void, olddelta: *mut core::ffi::c_void) -> i32 {
19766 syscall_ret(<Arch as Syscalls>::syscall1(SYS_ADJTIMEX, olddelta as i64)) as i32
19767}
19768
19769#[no_mangle]
19770pub unsafe extern "C" fn adjtimex(buf: *mut core::ffi::c_void) -> i32 {
19771 syscall_ret(<Arch as Syscalls>::syscall1(SYS_ADJTIMEX, buf as i64)) as i32
19772}
19773
19774const TIOCGPTN: i64 = 0x80045430;
19783const TIOCSPTLCK: i64 = 0x40045431;
19784
19785#[no_mangle]
19786pub unsafe extern "C" fn grantpt(_fd: i32) -> i32 {
19787 0
19789}
19790
19791#[no_mangle]
19792pub unsafe extern "C" fn unlockpt(fd: i32) -> i32 {
19793 let mut unlock: i32 = 0;
19794 let r = <Arch as Syscalls>::syscall3(
19795 SYS_IOCTL,
19796 fd as i64,
19797 TIOCSPTLCK,
19798 &mut unlock as *mut i32 as i64,
19799 );
19800 if r < 0 { -1 } else { 0 }
19801}
19802
19803#[no_mangle]
19804pub unsafe extern "C" fn ptsname(fd: i32) -> *mut core::ffi::c_char {
19805 static mut BUF: [core::ffi::c_char; 32] = [0; 32];
19806 let mut pty_nr: i32 = 0;
19807 if <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, TIOCGPTN, &mut pty_nr as *mut i32 as i64) < 0 {
19808 return core::ptr::null_mut();
19809 }
19810 BUF[0] = '/' as c_char; BUF[1] = 'd' as c_char; BUF[2] = 'e' as c_char; BUF[3] = 'v' as c_char;
19812 BUF[4] = '/' as c_char; BUF[5] = 'p' as c_char; BUF[6] = 't' as c_char; BUF[7] = 's' as c_char;
19813 BUF[8] = '/' as c_char;
19814 let mut n = pty_nr as usize;
19815 let mut i = 9;
19816 if n == 0 { BUF[i] = '0' as c_char; i += 1; }
19817 while n > 0 && i < 31 {
19818 BUF[i] = (b'0' + (n % 10) as u8) as c_char;
19819 n /= 10;
19820 i += 1;
19821 }
19822 BUF[i] = 0;
19823 BUF.as_mut_ptr()
19824}
19825
19826#[no_mangle]
19831pub unsafe extern "C" fn finite(x: f64) -> i32 {
19832 (!x.is_nan() && !x.is_infinite()) as i32
19833}
19834
19835#[no_mangle]
19836pub unsafe extern "C" fn finitef(x: f32) -> i32 {
19837 (!x.is_nan() && !x.is_infinite()) as i32
19838}
19839
19840#[no_mangle]
19841pub unsafe extern "C" fn __fpclassifyl(x: f64) -> i32 {
19842 __fpclassify(x)
19843}
19844
19845#[no_mangle]
19846pub unsafe extern "C" fn __signbitl(x: f64) -> i32 {
19847 __signbit(x)
19848}
19849
19850#[no_mangle]
19859pub unsafe extern "C" fn j0(x: f64) -> f64 {
19860 j0_impl(x)
19861}
19862
19863#[no_mangle]
19864pub unsafe extern "C" fn j0f(x: f32) -> f32 {
19865 libm::j0f(x)
19866}
19867
19868#[no_mangle]
19869pub unsafe extern "C" fn j1(x: f64) -> f64 {
19870 libm::j1(x)
19871}
19872
19873#[no_mangle]
19874pub unsafe extern "C" fn j1f(x: f32) -> f32 {
19875 libm::j1f(x)
19876}
19877
19878#[no_mangle]
19879pub unsafe extern "C" fn jn(n: i32, x: f64) -> f64 {
19880 libm::jn(n, x)
19881}
19882
19883#[no_mangle]
19884pub unsafe extern "C" fn jnf(n: i32, x: f32) -> f32 {
19885 libm::jnf(n, x)
19886}
19887
19888#[no_mangle]
19889pub unsafe extern "C" fn y0(x: f64) -> f64 {
19890 y0_impl(x)
19891}
19892
19893#[no_mangle]
19894pub unsafe extern "C" fn y0f(x: f32) -> f32 {
19895 if x.is_nan() { return x; }
19896 if x < 0.0 { return __math_invalidf(x); }
19897 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f32::NEG_INFINITY; }
19898 libm::y0f(x)
19899}
19900
19901#[no_mangle]
19902pub unsafe extern "C" fn y1(x: f64) -> f64 {
19903 if x.is_nan() { return x; }
19904 if x < 0.0 { return __math_invalid(x); }
19905 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f64::NEG_INFINITY; }
19906 libm::y1(x)
19907}
19908
19909#[no_mangle]
19910pub unsafe extern "C" fn y1f(x: f32) -> f32 {
19911 if x.is_nan() { return x; }
19912 if x < 0.0 { return __math_invalidf(x); }
19913 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f32::NEG_INFINITY; }
19914 libm::y1f(x)
19915}
19916
19917#[no_mangle]
19918pub unsafe extern "C" fn yn(n: i32, x: f64) -> f64 {
19919 if x.is_nan() { return x; }
19920 if x < 0.0 { return __math_invalid(x); }
19921 if x == 0.0 {
19922 feraiseexcept(FE_DIVBYZERO);
19923 if n >= 0 { return f64::NEG_INFINITY; }
19924 }
19925 libm::yn(n, x)
19926}
19927
19928#[no_mangle]
19929pub unsafe extern "C" fn ynf(n: i32, x: f32) -> f32 {
19930 if x.is_nan() { return x; }
19931 if x < 0.0 { return __math_invalidf(x); }
19932 if x == 0.0 {
19933 feraiseexcept(FE_DIVBYZERO);
19934 if n >= 0 { return f32::NEG_INFINITY; }
19935 }
19936 libm::ynf(n, x)
19937}
19938
19939#[no_mangle]
19944pub unsafe extern "C" fn __ctype_b_loc() -> *mut *const u16 {
19945 static mut TABLE: *const u16 = core::ptr::null();
19946 &mut TABLE
19947}
19948
19949#[no_mangle]
19950pub unsafe extern "C" fn __ctype_tolower_loc() -> *mut *const i32 {
19951 static mut TABLE: *const i32 = core::ptr::null();
19952 &mut TABLE
19953}
19954
19955#[no_mangle]
19956pub unsafe extern "C" fn __ctype_toupper_loc() -> *mut *const i32 {
19957 static mut TABLE: *const i32 = core::ptr::null();
19958 &mut TABLE
19959}
19960
19961#[no_mangle]
19962pub unsafe extern "C" fn __isalnum_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19963 (c >= '0' as i32 && c <= '9' as i32 || c >= 'A' as i32 && c <= 'Z' as i32 || c >= 'a' as i32 && c <= 'z' as i32) as i32
19964}
19965
19966#[no_mangle]
19967pub unsafe extern "C" fn __isalpha_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19968 (c >= 'A' as i32 && c <= 'Z' as i32 || c >= 'a' as i32 && c <= 'z' as i32) as i32
19969}
19970
19971#[no_mangle]
19972pub unsafe extern "C" fn __isblank_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19973 (c == ' ' as i32 || c == '\t' as i32) as i32
19974}
19975
19976#[no_mangle]
19977pub unsafe extern "C" fn __iscntrl_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19978 (c < 0x20 || c == 0x7f) as i32
19979}
19980
19981#[no_mangle]
19982pub unsafe extern "C" fn __isdigit_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19983 (c >= '0' as i32 && c <= '9' as i32) as i32
19984}
19985
19986#[no_mangle]
19987pub unsafe extern "C" fn __isgraph_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19988 (c > 0x20 && c < 0x7f) as i32
19989}
19990
19991#[no_mangle]
19992pub unsafe extern "C" fn __islower_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19993 (c >= 'a' as i32 && c <= 'z' as i32) as i32
19994}
19995
19996#[no_mangle]
19997pub unsafe extern "C" fn __isprint_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19998 (c >= 0x20 && c < 0x7f) as i32
19999}
20000
20001#[no_mangle]
20002pub unsafe extern "C" fn __ispunct_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20003 (c >= 0x21 && c <= 0x2f || c >= 0x3a && c <= 0x40 || c >= 0x5b && c <= 0x60 || c >= 0x7b && c <= 0x7e) as i32
20004}
20005
20006#[no_mangle]
20007pub unsafe extern "C" fn __isspace_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20008 (c == ' ' as i32 || c >= 0x09 && c <= 0x0d) as i32
20009}
20010
20011#[no_mangle]
20012pub unsafe extern "C" fn __isupper_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20013 (c >= 'A' as i32 && c <= 'Z' as i32) as i32
20014}
20015
20016#[no_mangle]
20017pub unsafe extern "C" fn __isxdigit_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20018 (c >= '0' as i32 && c <= '9' as i32 || c >= 'A' as i32 && c <= 'F' as i32 || c >= 'a' as i32 && c <= 'f' as i32) as i32
20019}
20020
20021#[no_mangle]
20026pub unsafe extern "C" fn __iswalnum_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20027 (c >= '0' as u32 && c <= '9' as u32 || c >= 'A' as u32 && c <= 'Z' as u32 || c >= 'a' as u32 && c <= 'z' as u32) as i32
20028}
20029
20030#[no_mangle]
20031pub unsafe extern "C" fn __iswalpha_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20032 (c >= 'A' as u32 && c <= 'Z' as u32 || c >= 'a' as u32 && c <= 'z' as u32) as i32
20033}
20034
20035#[no_mangle]
20036pub unsafe extern "C" fn __iswblank_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20037 (c == ' ' as u32 || c == '\t' as u32) as i32
20038}
20039
20040#[no_mangle]
20041pub unsafe extern "C" fn __iswcntrl_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20042 (c < 0x20 || c == 0x7f) as i32
20043}
20044
20045#[no_mangle]
20046pub unsafe extern "C" fn __iswdigit_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20047 (c >= '0' as u32 && c <= '9' as u32) as i32
20048}
20049
20050#[no_mangle]
20051pub unsafe extern "C" fn __iswgraph_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20052 (c > 0x20 && c < 0x7f) as i32
20053}
20054
20055#[no_mangle]
20056pub unsafe extern "C" fn __iswlower_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20057 (c >= 'a' as u32 && c <= 'z' as u32) as i32
20058}
20059
20060#[no_mangle]
20061pub unsafe extern "C" fn __iswprint_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20062 (c >= 0x20 && c < 0x7f) as i32
20063}
20064
20065#[no_mangle]
20066pub unsafe extern "C" fn __iswpunct_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20067 (c >= 0x21 && c <= 0x2f || c >= 0x3a && c <= 0x40 || c >= 0x5b && c <= 0x60 || c >= 0x7b && c <= 0x7e) as i32
20068}
20069
20070#[no_mangle]
20071pub unsafe extern "C" fn __iswspace_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20072 (c == ' ' as u32 || c >= 0x09 && c <= 0x0d) as i32
20073}
20074
20075#[no_mangle]
20076pub unsafe extern "C" fn __iswupper_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20077 (c >= 'A' as u32 && c <= 'Z' as u32) as i32
20078}
20079
20080#[no_mangle]
20081pub unsafe extern "C" fn __iswxdigit_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20082 (c >= '0' as u32 && c <= '9' as u32 || c >= 'A' as u32 && c <= 'F' as u32 || c >= 'a' as u32 && c <= 'f' as u32) as i32
20083}
20084
20085#[no_mangle]
20086pub unsafe extern "C" fn __iswctype_l(c: u32, ctype: u32, _loc: *mut core::ffi::c_void) -> i32 {
20087 crate::iswctype(c as wint_t, ctype as wctype_t)
20088}
20089
20090#[no_mangle]
20091pub unsafe extern "C" fn __towlower_l(c: u32, _loc: *mut core::ffi::c_void) -> u32 {
20092 crate::towlower(c)
20093}
20094
20095#[no_mangle]
20096pub unsafe extern "C" fn __towupper_l(c: u32, _loc: *mut core::ffi::c_void) -> u32 {
20097 crate::towupper(c)
20098}
20099
20100#[no_mangle]
20101pub unsafe extern "C" fn __towctrans_l(c: u32, _trans: u32, _loc: *mut core::ffi::c_void) -> u32 {
20102 c
20103}
20104
20105#[no_mangle]
20118pub unsafe extern "C" fn __assert_fail(expr: *const core::ffi::c_char, file: *const core::ffi::c_char, line: u32, func: *const core::ffi::c_char) {
20119 crate::write(2, b"Assertion failed: ".as_ptr() as *const core::ffi::c_void, 18);
20120 if !expr.is_null() { crate::write(2, expr as *const core::ffi::c_void, crate::strlen(expr)); }
20121 crate::write(2, b" (".as_ptr() as *const core::ffi::c_void, 2);
20122 if !file.is_null() { crate::write(2, file as *const core::ffi::c_void, crate::strlen(file)); }
20123 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
20124 let mut n = line as usize;
20125 let mut digits: [u8; 32] = [0; 32];
20126 let mut di = 0;
20127 if n == 0 { digits[0] = 0; di = 1; }
20128 while n > 0 && di < 32 { digits[di] = (n % 10) as u8; n /= 10; di += 1; }
20129 while di > 0 { di -= 1; let c = (b'0' + digits[di]) as c_char; crate::write(2, &c as *const c_char as *const core::ffi::c_void, 1); }
20130 crate::write(2, b")".as_ptr() as *const core::ffi::c_void, 1);
20131 if !func.is_null() { crate::write(2, func as *const core::ffi::c_void, crate::strlen(func)); }
20132 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20133 crate::abort()
20134}
20135
20136#[no_mangle]
20137pub unsafe extern "C" fn at_quick_exit(_func: Option<unsafe extern "C" fn()>) -> i32 {
20138 0
20140}
20141
20142#[no_mangle]
20143pub unsafe extern "C" fn brk(addr: *mut u8) -> i32 {
20144 syscall_ret(<Arch as Syscalls>::syscall1(sysno(12, 214), addr as i64)) as i32
20145}
20146
20147#[no_mangle]
20148pub unsafe extern "C" fn copy_file_range(fd_in: i32, off_in: *mut i64, fd_out: i32, off_out: *mut i64, len: usize, flags: u32) -> isize {
20149 syscall_ret(<Arch as Syscalls>::syscall6(SYS_COPY_FILE_RANGE, fd_in as i64, off_in as i64, fd_out as i64, off_out as i64, len as i64, flags as i64)) as isize
20150}
20151
20152#[no_mangle]
20153pub unsafe extern "C" fn ctermid(s: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
20154 static mut BUF: [core::ffi::c_char; 20] = [0; 20];
20155 let dst = if s.is_null() { BUF.as_mut_ptr() } else { s };
20156 let src = b"/dev/tty\0".as_ptr() as *const core::ffi::c_char;
20157 let mut i = 0;
20158 while i < 9 { *dst.add(i) = *src.add(i); i += 1; }
20159 dst
20160}
20161
20162#[no_mangle]
20163pub unsafe extern "C" fn delete_module(name: *const core::ffi::c_char, flags: u32) -> i32 {
20164 syscall_ret(<Arch as Syscalls>::syscall2(SYS_DELETE_MODULE, name as i64, flags as i64)) as i32
20165}
20166
20167
20168
20169
20170
20171#[no_mangle]
20172pub unsafe extern "C" fn __duplocale(loc: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
20173 loc
20174}
20175
20176#[no_mangle]
20177pub unsafe extern "C" fn euidaccess(pathname: *const core::ffi::c_char, mode: i32) -> i32 {
20178 faccessat(AT_FDCWD, pathname, mode, 0x200)
20179}
20180
20181#[no_mangle]
20182pub unsafe extern "C" fn fgetln(f: *mut core::ffi::c_void, lenp: *mut usize) -> *mut core::ffi::c_char {
20183 static mut BUF: [core::ffi::c_char; 4096] = [0; 4096];
20184 let mut i = 0;
20185 while i < 4095 {
20186 let c = getc(f as *mut FILE);
20187 if c < 0 { break; }
20188 BUF[i] = c as c_char;
20189 i += 1;
20190 if c == '\n' as i32 { break; }
20191 }
20192 BUF[i] = 0;
20193 if !lenp.is_null() { *lenp = i; }
20194 if i == 0 { core::ptr::null_mut() } else { BUF.as_mut_ptr() }
20195}
20196
20197#[no_mangle]
20198pub unsafe extern "C" fn fgetws(ws: *mut u32, n: i32, f: *mut core::ffi::c_void) -> *mut u32 {
20199 let mut i = 0;
20200 while i < n - 1 {
20201 let c = getwc(f as *mut core::ffi::c_void);
20202 if c == 0 { break; }
20203 *ws.add(i as usize) = c;
20204 i += 1;
20205 if c == '\n' as u32 { break; }
20206 }
20207 *ws.add(i as usize) = 0;
20208 if i == 0 { core::ptr::null_mut() } else { ws }
20209}
20210
20211#[no_mangle]
20212pub unsafe extern "C" fn fmtmsg(_classification: i64, label: *const core::ffi::c_char, _severity: i32, text: *const core::ffi::c_char, _action: *const core::ffi::c_char, _tag: *const core::ffi::c_char) -> i32 {
20213 if !label.is_null() { crate::write(2, label as *const core::ffi::c_void, crate::strlen(label)); }
20214 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
20215 if !text.is_null() { crate::write(2, text as *const core::ffi::c_void, crate::strlen(text)); }
20216 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20217 0
20218}
20219
20220#[no_mangle]
20221pub unsafe extern "C" fn ftime(tp: *mut core::ffi::c_void) -> i32 {
20222 let mut tv: timeval = core::mem::zeroed();
20223 if gettimeofday(&mut tv, core::ptr::null_mut()) == 0 {
20224 let tb = tp as *mut Timeb;
20225 (*tb).time = tv.tv_sec;
20226 (*tb).millitm = (tv.tv_usec / 1000) as u16;
20227 (*tb).timezone = 0;
20228 (*tb).dstflag = 0;
20229 0
20230 } else {
20231 -1
20232 }
20233}
20234
20235#[no_mangle]
20236pub unsafe extern "C" fn getdents(fd: i32, dirp: *mut u8, count: usize) -> isize {
20237 syscall_ret(<Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, dirp as i64, count as i64)) as isize
20238}
20239
20240#[no_mangle]
20241pub unsafe extern "C" fn gethostid() -> i64 {
20242 let fd = crate::open(b"/proc/sys/kernel/random/boot_id\0".as_ptr() as *const core::ffi::c_char, 0, 0);
20244 if fd < 0 { return 0; }
20245 let mut buf: [u8; 64] = [0; 64];
20246 let n = crate::read(fd, buf.as_mut_ptr() as *mut core::ffi::c_void, 63);
20247 crate::close(fd);
20248 if n <= 0 { return 0; }
20249 buf[n as usize] = 0;
20250 crate::strtol(buf.as_ptr() as *const core::ffi::c_char, core::ptr::null_mut(), 16)
20251}
20252
20253#[no_mangle]
20254pub unsafe extern "C" fn getpass(prompt: *const core::ffi::c_char) -> *mut core::ffi::c_char {
20255 static mut BUF: [core::ffi::c_char; 128] = [0; 128];
20256 crate::write(2, prompt as *const core::ffi::c_void, crate::strlen(prompt));
20258 let n = crate::read(0, BUF.as_mut_ptr() as *mut core::ffi::c_void, 127);
20260 if n > 0 {
20261 let end = if BUF[(n - 1) as usize] == '\n' as c_char { n - 1 } else { n };
20262 BUF[end as usize] = 0;
20263 } else {
20264 BUF[0] = 0;
20265 }
20266 BUF.as_mut_ptr()
20267}
20268
20269#[no_mangle]
20270pub unsafe extern "C" fn getsubopt(optionp: *mut *mut core::ffi::c_char, tokens: *const *const core::ffi::c_char, valuep: *mut *mut core::ffi::c_char) -> i32 {
20271 let s = *optionp;
20272 if s.is_null() { return -1; }
20273 let mut end = s;
20275 while *end != 0 && *end != ',' as c_char && *end != '=' as c_char { end = end.add(1); }
20276 let eq = *end == '=' as c_char;
20277 if eq { *end = 0; *valuep = end.add(1); }
20278 let mut i = 0;
20280 loop {
20281 let tok = *tokens.add(i);
20282 if tok.is_null() { break; }
20283 if crate::strcmp(s as *const u8, tok as *const u8) == 0 {
20284 while *end != 0 && *end != ',' as c_char { end = end.add(1); }
20286 if *end == ',' as c_char { end = end.add(1); }
20287 *optionp = end;
20288 return i as i32;
20289 }
20290 i += 1;
20291 }
20292 -1
20293}
20294
20295#[no_mangle]
20296pub unsafe extern "C" fn getw(f: *mut core::ffi::c_void) -> i32 {
20297 let c0 = getc(f as *mut FILE);
20298 if c0 < 0 { return -1; }
20299 let c1 = getc(f as *mut FILE);
20300 if c1 < 0 { return -1; }
20301 let c2 = getc(f as *mut FILE);
20302 if c2 < 0 { return -1; }
20303 let c3 = getc(f as *mut FILE);
20304 if c3 < 0 { return -1; }
20305 (c0 | (c1 << 8) | (c2 << 16) | (c3 << 24)) as i32
20306}
20307
20308#[no_mangle]
20309pub unsafe extern "C" fn getwc(f: *mut core::ffi::c_void) -> u32 {
20310 getc(f as *mut FILE) as u32
20311}
20312
20313#[no_mangle]
20314pub unsafe extern "C" fn init_module(module_image: *mut u8, len: usize, param_values: *const core::ffi::c_char) -> i32 {
20315 syscall_ret(<Arch as Syscalls>::syscall3(SYS_INIT_MODULE, module_image as i64, len as i64, param_values as i64)) as i32
20316}
20317
20318
20319
20320#[no_mangle]
20321pub unsafe extern "C" fn issetugid() -> i32 {
20322 let ruid = crate::getuid();
20323 let euid = crate::geteuid();
20324 let rgid = crate::getgid();
20325 let egid = crate::getegid();
20326 (ruid != euid || rgid != egid) as i32
20327}
20328
20329#[no_mangle]
20334pub unsafe extern "C" fn poll(fds: *mut core::ffi::c_void, nfds: u32, timeout: i32) -> i32 {
20335 #[cfg(target_arch = "x86_64")]
20336 { syscall_ret(<Arch as Syscalls>::syscall3(SYS_POLL, fds as i64, nfds as i64, timeout as i64)) as i32 }
20337 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
20338 {
20339 syscall_ret(<Arch as Syscalls>::syscall5(SYS_PPOLL, fds as i64, nfds as i64, timeout as i64, 0, 0)) as i32
20340 }
20341}
20342
20343#[no_mangle]
20344pub unsafe extern "C" fn ppoll(fds: *mut core::ffi::c_void, nfds: u32, timeout: *const core::ffi::c_void, sigmask: *const u64) -> i32 {
20345 syscall_ret(<Arch as Syscalls>::syscall5(SYS_PPOLL, fds as i64, nfds as i64, timeout as i64, sigmask as i64, 8)) as i32
20346}
20347
20348#[no_mangle]
20349pub unsafe extern "C" fn pselect(nfds: i32, readfds: *mut u8, writefds: *mut u8, exceptfds: *mut u8, timeout: *const core::ffi::c_void, sigmask: *const u64) -> i32 {
20350 syscall_ret(<Arch as Syscalls>::syscall6(SYS_PSELECT6, nfds as i64, readfds as i64, writefds as i64, exceptfds as i64, timeout as i64, sigmask as i64)) as i32
20351}
20352
20353#[no_mangle]
20362pub unsafe extern "C" fn quick_exit(status: i32) -> ! {
20363 crate::_exit(status)
20364}
20365
20366#[no_mangle]
20371pub unsafe extern "C" fn lstat(path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
20372 let r = <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, AT_FDCWD as i64, path as i64, buf as i64, 0x100);
20373 if r < 0 {
20374 ERRNO!() = (-r) as c_int;
20375 -1
20376 } else {
20377 0
20378 }
20379}
20380
20381#[no_mangle]
20382pub unsafe extern "C" fn __xstat(_ver: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
20383 crate::stat(path, buf as *mut Stat)
20384}
20385
20386#[no_mangle]
20387pub unsafe extern "C" fn __lxstat(_ver: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
20388 crate::lstat(path, buf)
20389}
20390
20391#[no_mangle]
20392pub unsafe extern "C" fn __fxstat(_ver: i32, fd: i32, buf: *mut core::ffi::c_void) -> i32 {
20393 crate::fstat(fd, buf as *mut Stat)
20394}
20395
20396#[no_mangle]
20397pub unsafe extern "C" fn __fxstatat(_ver: i32, _dirfd: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void, _flags: i32) -> i32 {
20398 crate::stat(path, buf as *mut Stat)
20399}
20400
20401#[no_mangle]
20406pub unsafe extern "C" fn mempcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
20407 core::ptr::copy_nonoverlapping(src, dest, n);
20408 dest.add(n)
20409}
20410
20411#[no_mangle]
20416pub unsafe extern "C" fn mkostemp(template: *mut core::ffi::c_char, _flags: i32) -> i32 {
20417 mkstemp(template)
20418}
20419
20420#[no_mangle]
20421pub unsafe extern "C" fn mkstemps(template: *mut core::ffi::c_char, _suffixlen: i32) -> i32 {
20422 mkstemp(template)
20423}
20424
20425#[no_mangle]
20430pub unsafe extern "C" fn ptrace(request: i32, mut args: ...) -> i64 {
20431 let pid = args.next_arg::<c_long>();
20432 let addr = args.next_arg::<c_long>();
20433 let data = args.next_arg::<c_long>();
20434 if (1..=3).contains(&request) {
20437 let mut result: c_long = 0;
20438 let r = <Arch as Syscalls>::syscall4(
20439 sysno(101, 117),
20440 request as i64,
20441 pid,
20442 addr,
20443 &mut result as *mut c_long as i64,
20444 );
20445 if r < 0 {
20446 ERRNO!() = (-r) as c_int;
20447 return -1;
20448 }
20449 return result;
20450 }
20451 syscall_ret(<Arch as Syscalls>::syscall4(sysno(101, 117), request as i64, pid, addr, data))
20452}
20453
20454#[no_mangle]
20455pub unsafe extern "C" fn personality(persona: u64) -> i64 {
20456 <Arch as Syscalls>::syscall1(sysno(135, 92), persona as i64)
20457}
20458
20459#[no_mangle]
20460pub unsafe extern "C" fn reboot(cmd: c_int) -> i32 {
20461 syscall_ret(<Arch as Syscalls>::syscall3(
20463 SYS_REBOOT,
20464 0xfee1dead,
20465 672274793,
20466 cmd as i64,
20467 )) as i32
20468}
20469
20470#[no_mangle]
20471pub unsafe extern "C" fn pivot_root(new_root: *const core::ffi::c_char, put_old: *const core::ffi::c_char) -> i32 {
20472 syscall_ret(<Arch as Syscalls>::syscall2(SYS_PIVOT_ROOT, new_root as i64, put_old as i64)) as i32
20473}
20474
20475#[no_mangle]
20476pub unsafe extern "C" fn mount(source: *const core::ffi::c_char, target: *const core::ffi::c_char, filesystemtype: *const core::ffi::c_char, mountflags: u64, data: *const core::ffi::c_void) -> i32 {
20477 syscall_ret(<Arch as Syscalls>::syscall5(SYS_MOUNT, source as i64, target as i64, filesystemtype as i64, mountflags as i64, data as i64)) as i32
20478}
20479
20480#[no_mangle]
20481pub unsafe extern "C" fn umount(target: *const core::ffi::c_char) -> i32 {
20482 syscall_ret(<Arch as Syscalls>::syscall2(SYS_UMOUNT2, target as i64, 0)) as i32
20483}
20484
20485#[no_mangle]
20486pub unsafe extern "C" fn umount2(target: *const core::ffi::c_char, flags: i32) -> i32 {
20487 syscall_ret(<Arch as Syscalls>::syscall2(SYS_UMOUNT2, target as i64, flags as i64)) as i32
20488}
20489
20490#[no_mangle]
20500pub unsafe extern "C" fn psiginfo(_pinfo: *const core::ffi::c_void, s: *const core::ffi::c_char) {
20501 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
20502 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20503}
20504
20505#[no_mangle]
20506pub unsafe extern "C" fn psignal(sig: i32, s: *const core::ffi::c_char) {
20507 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
20508 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
20509 crate::write(2, strsignal(sig) as *const core::ffi::c_void, crate::strlen(strsignal(sig)));
20510 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20511}
20512
20513#[no_mangle]
20514pub unsafe extern "C" fn strsignal(sig: c_int) -> *const c_char {
20515 static NAMES: [&[u8]; 32] = [
20516 b"Unknown signal\0",
20517 b"Hangup\0",
20518 b"Interrupt\0",
20519 b"Quit\0",
20520 b"Illegal instruction\0",
20521 b"Trace/breakpoint trap\0",
20522 b"Aborted\0",
20523 b"Bus error\0",
20524 b"Floating point exception\0",
20525 b"Killed\0",
20526 b"User defined signal 1\0",
20527 b"Segmentation fault\0",
20528 b"User defined signal 2\0",
20529 b"Broken pipe\0",
20530 b"Alarm clock\0",
20531 b"Terminated\0",
20532 b"Stack fault\0",
20533 b"Child process status\0",
20534 b"Continued\0",
20535 b"Stopped (signal)\0",
20536 b"Stopped\0",
20537 b"Stopped (tty input)\0",
20538 b"Stopped (tty output)\0",
20539 b"Urgent I/O condition\0",
20540 b"CPU time limit exceeded\0",
20541 b"File size limit exceeded\0",
20542 b"Virtual timer expired\0",
20543 b"Profiling timer expired\0",
20544 b"Window changed\0",
20545 b"I/O possible\0",
20546 b"Power failure\0",
20547 b"Bad system call\0",
20548 ];
20549 static mut RT_BUF: [c_char; 32] = [0; 32];
20550 if sig > 0 && sig < 32 {
20551 return NAMES[sig as usize].as_ptr() as *const c_char;
20552 }
20553 if sig >= 32 && sig < 65 {
20554 let mut o = 0usize;
20555 for &c in b"Real-time signal \0" {
20556 if c == 0 { break; }
20557 RT_BUF[o] = c as c_char;
20558 o += 1;
20559 }
20560 let mut v = (sig - 32) as u32;
20561 let mut digits = [0u8; 10];
20562 let mut d = 0usize;
20563 if v == 0 { digits[0] = b'0'; d = 1; }
20564 while v > 0 { digits[d] = b'0' + (v % 10) as u8; v /= 10; d += 1; }
20565 while d > 0 { d -= 1; RT_BUF[o] = digits[d] as c_char; o += 1; }
20566 RT_BUF[o] = 0;
20567 return RT_BUF.as_ptr();
20568 }
20569 b"Unknown signal\0".as_ptr() as *const c_char
20570}
20571
20572#[no_mangle]
20573pub unsafe extern "C" fn __strerror_l(errnum: i32, _loc: *mut core::ffi::c_void) -> *const core::ffi::c_char {
20574 crate::strerror(errnum)
20575}
20576
20577#[no_mangle]
20582pub unsafe extern "C" fn preadv(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64) -> isize {
20583 syscall_ret(<Arch as Syscalls>::syscall5(
20586 sysno(295, 69),
20587 fd as i64,
20588 iov as i64,
20589 iovcnt as i64,
20590 offset,
20591 offset >> 32,
20592 )) as isize
20593}
20594
20595#[no_mangle]
20596pub unsafe extern "C" fn pwritev(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64) -> isize {
20597 syscall_ret(<Arch as Syscalls>::syscall5(
20598 sysno(296, 70),
20599 fd as i64,
20600 iov as i64,
20601 iovcnt as i64,
20602 offset,
20603 offset >> 32,
20604 )) as isize
20605}
20606
20607#[no_mangle]
20608pub unsafe extern "C" fn preadv2(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64, flags: u32) -> isize {
20609 syscall_ret(<Arch as Syscalls>::syscall6(
20612 sysno(327, 286),
20613 fd as i64,
20614 iov as i64,
20615 iovcnt as i64,
20616 offset,
20617 offset >> 32,
20618 flags as i64,
20619 )) as isize
20620}
20621
20622#[no_mangle]
20623pub unsafe extern "C" fn pwritev2(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64, flags: u32) -> isize {
20624 syscall_ret(<Arch as Syscalls>::syscall6(
20625 sysno(328, 287),
20626 fd as i64,
20627 iov as i64,
20628 iovcnt as i64,
20629 offset,
20630 offset >> 32,
20631 flags as i64,
20632 )) as isize
20633}
20634
20635#[no_mangle]
20640pub unsafe extern "C" fn nice(inc: i32) -> i32 {
20641 let mut prio = inc;
20642 if inc > -40 && inc < 40 {
20643 prio += getpriority(0, 0);
20644 }
20645 if prio > 19 { prio = 19; }
20646 if prio < -20 { prio = -20; }
20647 if setpriority(0, 0, prio) != 0 {
20648 if ERRNO!() == 13 { ERRNO!() = 1; } return -1;
20650 }
20651 prio
20652}
20653
20654#[no_mangle]
20659pub unsafe extern "C" fn l64a(value: i64) -> *mut core::ffi::c_char {
20660 static mut BUF: [core::ffi::c_char; 7] = [0; 7];
20661 let mut v = value as u64;
20662 let mut i = 0;
20663 while v > 0 && i < 6 {
20664 let c = (v & 0x3f) as u8;
20665 BUF[i] = if c < 26 { c + b'A' } else if c < 52 { c - 26 + b'a' } else if c < 62 { c - 52 + b'0' } else if c == 62 { b'.' } else { b'/' } as core::ffi::c_char;
20666 v >>= 6;
20667 i += 1;
20668 }
20669 BUF[i] = 0;
20670 BUF.as_mut_ptr()
20671}
20672
20673#[no_mangle]
20674pub unsafe extern "C" fn lchmod(path: *const core::ffi::c_char, mode: u32) -> i32 {
20675 syscall_ret(<Arch as Syscalls>::syscall4(SYS_FCHMODAT, AT_FDCWD as i64, path as i64, mode as i64, 0x100)) as i32
20676}
20677
20678#[no_mangle]
20679pub unsafe extern "C" fn lutimes(filename: *const core::ffi::c_char, times: *const core::ffi::c_void) -> i32 {
20680 utimensat(AT_FDCWD, filename, times as *const timespec, 0x100)
20681}
20682
20683#[no_mangle]
20684pub unsafe extern "C" fn mknod(pathname: *const core::ffi::c_char, mode: u32, dev: u64) -> i32 {
20685 #[cfg(target_arch = "x86_64")]
20686 { syscall_ret(<Arch as Syscalls>::syscall3(SYS_MKNOD, pathname as i64, mode as i64, dev as i64)) as i32 }
20687 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
20688 {
20689 syscall_ret(<Arch as Syscalls>::syscall4(SYS_MKNODAT, AT_FDCWD as i64, pathname as i64, mode as i64, dev as i64)) as i32
20690 }
20691}
20692
20693#[no_mangle]
20694pub unsafe extern "C" fn memfd_create(name: *const core::ffi::c_char, flags: u32) -> i32 {
20695 syscall_ret(<Arch as Syscalls>::syscall2(sysno(319, 279), name as i64, flags as i64)) as i32
20696}
20697
20698#[no_mangle]
20699pub unsafe extern "C" fn mlock2(addr: *const core::ffi::c_void, len: usize, flags: u32) -> i32 {
20700 syscall_ret(<Arch as Syscalls>::syscall3(sysno(325, 284), addr as i64, len as i64, flags as i64)) as i32
20701}
20702
20703
20704
20705#[no_mangle]
20706pub unsafe extern "C" fn remap_file_pages(addr: *mut core::ffi::c_void, size: usize, prot: i32, pgoff: usize, flags: u32) -> i32 {
20707 syscall_ret(<Arch as Syscalls>::syscall5(sysno(216, 234), addr as i64, size as i64, prot as i64, pgoff as i64, flags as i64)) as i32
20708}
20709
20710#[no_mangle]
20715pub unsafe extern "C" fn nan(_tagp: *const core::ffi::c_char) -> f64 {
20716 f64::NAN
20717}
20718
20719#[no_mangle]
20720pub unsafe extern "C" fn nanf(_tagp: *const core::ffi::c_char) -> f32 {
20721 f32::NAN
20722}
20723
20724#[no_mangle]
20729pub unsafe extern "C" fn __lgammal_r(x: f64, signgamp: *mut i32) -> f64 {
20730 *signgamp = 1;
20731 lgamma(x)
20732}
20733
20734#[no_mangle]
20735pub unsafe extern "C" fn __libc_current_sigrtmax() -> i32 {
20736 64
20737}
20738
20739#[no_mangle]
20740pub unsafe extern "C" fn _longjmp(env: *mut core::ffi::c_void, val: i32) {
20741 crate::longjmp(env as *mut u64, val)
20742}
20743
20744#[no_mangle]
20745pub unsafe extern "C" fn __newlocale(_mask: i32, _name: *const core::ffi::c_char, base: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
20746 base
20747}
20748
20749#[no_mangle]
20750pub unsafe extern "C" fn __nl_langinfo(_item: i32) -> *mut core::ffi::c_char {
20751 b"\0".as_ptr() as *mut core::ffi::c_char
20752}
20753
20754#[no_mangle]
20755pub unsafe extern "C" fn __nl_langinfo_l(_item: i32, _loc: *mut core::ffi::c_void) -> *mut core::ffi::c_char {
20756 b"\0".as_ptr() as *mut core::ffi::c_char
20757}
20758
20759#[no_mangle]
20760pub unsafe extern "C" fn ns_get16(cp: *const u8) -> u16 {
20761 ((*cp.add(0) as u16) << 8) | *cp.add(1) as u16
20762}
20763
20764#[no_mangle]
20765pub unsafe extern "C" fn ns_get32(cp: *const u8) -> u32 {
20766 ((*cp.add(0) as u32) << 24) | ((*cp.add(1) as u32) << 16) | ((*cp.add(2) as u32) << 8) | *cp.add(3) as u32
20767}
20768
20769#[no_mangle]
20770pub unsafe extern "C" fn ns_put16(s: u16, dst: *mut u8) {
20771 *dst.add(0) = (s >> 8) as u8;
20772 *dst.add(1) = (s & 0xff) as u8;
20773}
20774
20775#[no_mangle]
20776pub unsafe extern "C" fn ns_put32(l: u32, dst: *mut u8) {
20777 *dst.add(0) = (l >> 24) as u8;
20778 *dst.add(1) = ((l >> 16) & 0xff) as u8;
20779 *dst.add(2) = ((l >> 8) & 0xff) as u8;
20780 *dst.add(3) = (l & 0xff) as u8;
20781}
20782
20783#[no_mangle]
20784pub unsafe extern "C" fn posix_close(fd: i32) -> i32 {
20785 crate::close(fd)
20786}
20787
20788#[no_mangle]
20789pub unsafe extern "C" fn posix_openpt(flags: i32) -> i32 {
20790 crate::open(b"/dev/ptmx\0".as_ptr() as *const core::ffi::c_char, flags, 0)
20791}
20792
20793#[no_mangle]
20794pub unsafe extern "C" fn putw(w: i32, f: *mut core::ffi::c_void) {
20795 putc((w & 0xff) as i32, f as *mut FILE);
20796 putc(((w >> 8) & 0xff) as i32, f as *mut FILE);
20797 putc(((w >> 16) & 0xff) as i32, f as *mut FILE);
20798 putc(((w >> 24) & 0xff) as i32, f as *mut FILE);
20799}
20800
20801
20802
20803#[no_mangle]
20804pub unsafe extern "C" fn rand_r(seedp: *mut u32) -> i32 {
20805 let seed = (*seedp).wrapping_mul(1103515245).wrapping_add(12345);
20806 *seedp = seed;
20807 ((seed >> 16) & 0x7fff) as i32
20808}
20809
20810#[no_mangle]
20811pub unsafe extern "C" fn reallocarray(ptr: *mut core::ffi::c_void, nmemb: usize, size: usize) -> *mut core::ffi::c_void {
20812 let total = match nmemb.checked_mul(size) {
20813 Some(v) => v,
20814 None => { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
20815 };
20816 crate::realloc(ptr, total)
20817}
20818
20819#[no_mangle]
20820pub unsafe extern "C" fn __res_state() -> *mut core::ffi::c_void {
20821 static mut STATE: [u8; 512] = [0; 512];
20822 STATE.as_mut_ptr() as *mut core::ffi::c_void
20823}
20824
20825#[no_mangle]
20826pub unsafe extern "C" fn sbrk(increment: isize) -> *mut u8 {
20827 if increment != 0 {
20830 ERRNO!() = ENOMEM;
20831 return -1isize as usize as *mut u8;
20832 }
20833 <Arch as Syscalls>::syscall1(sysno(12, 214), 0) as *mut u8
20834}
20835
20836#[no_mangle]
20837pub unsafe extern "C" fn scalb(x: f64, exp: f64) -> f64 {
20838 if x.is_nan() || exp.is_nan() { return x * exp; }
20839 if !exp.is_finite() {
20840 let r = if exp > 0.0 { x * exp } else { x / (-exp) };
20841 if r.is_nan() && !x.is_nan() {
20842 feraiseexcept(FE_INVALID);
20843 }
20844 return r;
20845 }
20846 if libm::rint(exp) != exp {
20847 return __math_invalid(exp);
20848 }
20849 if exp > 65000.0 { return libm::scalbn(x, 65000); }
20850 if -exp > 65000.0 { return libm::scalbn(x, -65000); }
20851 libm::scalbn(x, exp as i32)
20852}
20853
20854#[no_mangle]
20855pub unsafe extern "C" fn scalbf(x: f32, exp: f32) -> f32 {
20856 if x.is_nan() || exp.is_nan() { return x * exp; }
20857 if !exp.is_finite() {
20858 let r = if exp > 0.0 { x * exp } else { x / (-exp) };
20859 if r.is_nan() && !x.is_nan() {
20860 feraiseexcept(FE_INVALID);
20861 }
20862 return r;
20863 }
20864 if libm::rintf(exp) != exp {
20865 return __math_invalidf(exp);
20866 }
20867 if exp > 65000.0 { return libm::scalbnf(x, 65000); }
20868 if -exp > 65000.0 { return libm::scalbnf(x, -65000); }
20869 libm::scalbnf(x, exp as i32)
20870}
20871
20872#[no_mangle]
20873pub unsafe extern "C" fn __sched_cpucount(setsize: usize, setp: *const u8) -> i32 {
20874 let mut count = 0;
20875 let mut i = 0;
20876 while i < setsize * 8 {
20877 if (*setp.add(i / 8) >> (i % 8)) & 1 != 0 { count += 1; }
20878 i += 1;
20879 }
20880 count
20881}
20882
20883
20884
20885#[no_mangle]
20886pub unsafe extern "C" fn select(nfds: i32, readfds: *mut u8, writefds: *mut u8, exceptfds: *mut u8, timeout: *mut core::ffi::c_void) -> i32 {
20887 syscall_ret(<Arch as Syscalls>::syscall6(sysno(23, 72), nfds as i64, readfds as i64, writefds as i64, exceptfds as i64, timeout as i64, 0)) as i32
20888}
20889
20890
20891
20892#[no_mangle]
20893pub unsafe extern "C" fn sendfile(out_fd: i32, in_fd: i32, offset: *mut i64, count: usize) -> isize {
20894 syscall_ret(<Arch as Syscalls>::syscall4(sysno(40, 71), out_fd as i64, in_fd as i64, offset as i64, count as i64)) as isize
20895}
20896
20897
20898
20899
20900
20901#[no_mangle]
20902pub unsafe extern "C" fn __setjmp(env: *mut core::ffi::c_void) -> i32 {
20903 crate::setjmp(env as *mut u64)
20904}
20905
20906#[no_mangle]
20907pub unsafe extern "C" fn _setjmp(env: *mut core::ffi::c_void) -> i32 {
20908 crate::setjmp(env as *mut u64)
20909}
20910
20911#[no_mangle]
20912pub unsafe extern "C" fn setlinebuf(stream: *mut core::ffi::c_void) {
20913 setvbuf(stream as *mut FILE, core::ptr::null_mut(), 1, 0);
20914}
20915
20916
20917
20918
20919
20920
20921
20922
20923
20924
20925
20926
20927
20928
20929
20930#[no_mangle]
20931pub unsafe extern "C" fn significand(x: f64) -> f64 {
20932 let bits = x.to_bits();
20933 let exp = ((bits >> 52) & 0x7ff) as i32;
20934 if exp == 0 || exp == 0x7ff { return x; }
20935 f64::from_bits((bits & 0x000fffffffffffff) | (1023u64 << 52))
20936}
20937
20938#[no_mangle]
20939pub unsafe extern "C" fn significandf(x: f32) -> f32 {
20940 let bits = x.to_bits();
20941 let exp = ((bits >> 23) & 0xff) as i32;
20942 if exp == 0 || exp == 0xff { return x; }
20943 f32::from_bits((bits & 0x007fffff) | (127u32 << 23))
20944}
20945
20946
20947
20948
20949
20950#[no_mangle]
20951pub unsafe extern "C" fn sigset(sig: i32, handler: usize) -> usize {
20952 signal(sig, handler)
20954}
20955
20956#[no_mangle]
20957pub unsafe extern "C" fn sincos(x: f64, sin: *mut f64, cos: *mut f64) {
20958 *sin = libm::sin(x);
20959 *cos = libm::cos(x);
20960}
20961
20962#[no_mangle]
20963pub unsafe extern "C" fn sincosf(x: f32, sin: *mut f32, cos: *mut f32) {
20964 *sin = libm::sinf(x);
20965 *cos = libm::cosf(x);
20966}
20967
20968
20969
20970
20971
20972
20973
20974
20975
20976unsafe fn nd_ascii_lower(c: c_char) -> c_int {
20977 let b = c as u8;
20978 if b >= b'A' && b <= b'Z' { (b + 32) as c_int } else { b as c_int }
20979}
20980
20981unsafe fn nd_strncasecmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int {
20982 let mut i = 0usize;
20983 while i < n {
20984 let c1 = nd_ascii_lower(*s1.add(i));
20985 let c2 = nd_ascii_lower(*s2.add(i));
20986 if c1 != c2 || c1 == 0 { return c1 - c2; }
20987 i += 1;
20988 }
20989 0
20990}
20991
20992#[no_mangle]
20993pub unsafe extern "C" fn strcasecmp(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char) -> i32 {
20994 nd_strncasecmp(s1, s2, usize::MAX)
20995}
20996
20997#[no_mangle]
20998pub unsafe extern "C" fn __strcasecmp_l(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char, _loc: *mut core::ffi::c_void) -> i32 {
20999 nd_strncasecmp(s1, s2, usize::MAX)
21000}
21001
21002#[no_mangle]
21003pub unsafe extern "C" fn strcasestr(haystack: *const core::ffi::c_char, needle: *const core::ffi::c_char) -> *mut core::ffi::c_char {
21004 let nlen = crate::strlen(needle);
21005 if nlen == 0 { return haystack as *mut core::ffi::c_char; }
21006 let mut i = 0;
21007 loop {
21008 let h = haystack.add(i);
21009 if *h == 0 { return core::ptr::null_mut(); }
21010 if crate::strncasecmp(h, needle, nlen) == 0 { return h as *mut core::ffi::c_char; }
21011 i += 1;
21012 }
21013}
21014
21015#[no_mangle]
21016pub unsafe extern "C" fn __strcoll_l(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char, _loc: *mut core::ffi::c_void) -> i32 {
21017 crate::strcmp(s1 as *const u8, s2 as *const u8)
21018}
21019
21020#[no_mangle]
21021pub unsafe extern "C" fn strncasecmp(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char, n: usize) -> i32 {
21022 nd_strncasecmp(s1, s2, n)
21023}
21024
21025#[no_mangle]
21026pub unsafe extern "C" fn __strncasecmp_l(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char, n: usize, _loc: *mut core::ffi::c_void) -> i32 {
21027 nd_strncasecmp(s1, s2, n)
21028}
21029
21030#[no_mangle]
21031pub unsafe extern "C" fn strsep(stringp: *mut *mut core::ffi::c_char, delim: *const core::ffi::c_char) -> *mut core::ffi::c_char {
21032 let s = *stringp;
21033 if s.is_null() { return core::ptr::null_mut(); }
21034 let mut p = s;
21035 while *p != 0 {
21036 let mut d = delim;
21037 while *d != 0 {
21038 if *p == *d { *p = 0; *stringp = p.add(1); return s; }
21039 d = d.add(1);
21040 }
21041 p = p.add(1);
21042 }
21043 *stringp = core::ptr::null_mut();
21044 s
21045}
21046
21047#[no_mangle]
21048pub unsafe extern "C" fn strtoimax(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, base: i32) -> i64 {
21049 crate::strtol(nptr, endptr, base)
21050}
21051
21052#[no_mangle]
21053pub unsafe extern "C" fn strtok_r(s: *mut core::ffi::c_char, delim: *const core::ffi::c_char, saveptr: *mut *mut core::ffi::c_char) -> *mut core::ffi::c_char {
21054 let mut s = if s.is_null() { *saveptr } else { s };
21055 if s.is_null() { return core::ptr::null_mut(); }
21056 while *s != 0 {
21058 let mut d = delim;
21059 let mut found = false;
21060 while *d != 0 {
21061 if *s == *d { found = true; break; }
21062 d = d.add(1);
21063 }
21064 if !found { break; }
21065 s = s.add(1);
21066 }
21067 if *s == 0 { *saveptr = s; return core::ptr::null_mut(); }
21068 let start = s;
21069 while *s != 0 {
21071 let mut d = delim;
21072 while *d != 0 {
21073 if *s == *d { *s = 0; *saveptr = s.add(1); return start; }
21074 d = d.add(1);
21075 }
21076 s = s.add(1);
21077 }
21078 *saveptr = s;
21079 start
21080}
21081
21082#[no_mangle]
21083pub unsafe extern "C" fn strtoumax(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, base: i32) -> u64 {
21084 crate::strtoul(nptr, endptr, base) as u64
21085}
21086
21087#[no_mangle]
21088pub unsafe extern "C" fn __strxfrm_l(dest: *mut core::ffi::c_char, src: *const core::ffi::c_char, n: usize, _loc: *mut core::ffi::c_void) -> usize {
21089 crate::strlcpy(dest as *mut u8, src as *const u8, n)
21090}
21091
21092#[no_mangle]
21093pub unsafe extern "C" fn swab(src: *const u8, dest: *mut u8, nbytes: isize) {
21094 let mut i = 0;
21095 while i + 1 < nbytes {
21096 let a = *src.add(i as usize);
21097 let b = *src.add(i as usize + 1);
21098 *dest.add(i as usize) = b;
21099 *dest.add(i as usize + 1) = a;
21100 i += 2;
21101 }
21102}
21103
21104
21105
21106
21107
21108
21109
21110
21111
21112
21113
21114#[no_mangle]
21115pub unsafe extern "C" fn __tolower_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
21116 if c >= 'A' as i32 && c <= 'Z' as i32 { c + 32 } else { c }
21117}
21118
21119#[no_mangle]
21120pub unsafe extern "C" fn __toupper_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
21121 if c >= 'a' as i32 && c <= 'z' as i32 { c - 32 } else { c }
21122}
21123
21124#[no_mangle]
21125pub unsafe extern "C" fn ulimit(cmd: c_int, mut args: ...) -> c_long {
21126 let mut rl: Rlimit = core::mem::zeroed();
21127 if getrlimit(RLIMIT_FSIZE, &mut rl) != 0 { return -1; }
21128 if cmd == 2 {
21129 let val = args.next_arg::<c_long>();
21130 rl.rlim_cur = 512u64.wrapping_mul(val as u64);
21131 if setrlimit(RLIMIT_FSIZE, &rl) != 0 { return -1; }
21132 }
21133 (rl.rlim_cur / 512) as c_long
21134}
21135
21136#[repr(C)]
21137struct UtsName {
21138 sysname: [u8; 65],
21139 nodename: [u8; 65],
21140 release: [u8; 65],
21141 version: [u8; 65],
21142 machine: [u8; 65],
21143 domainname: [u8; 65],
21144}
21145
21146#[no_mangle]
21147pub unsafe extern "C" fn uname(buf: *mut c_void) -> c_int {
21148 let r = <Arch as Syscalls>::syscall1(SYS_UNAME, buf as i64);
21151 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
21152 0
21153}
21154
21155#[no_mangle]
21156pub unsafe extern "C" fn unshare(flags: i32) -> i32 {
21157 let r = <Arch as Syscalls>::syscall1(SYS_UNSHARE, flags as i64);
21158 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21159}
21160
21161#[no_mangle]
21162pub unsafe extern "C" fn updwtmpx(wtmpx_file: *const core::ffi::c_char, utx: *const core::ffi::c_void) {
21163 updwtmp(wtmpx_file, utx)
21164}
21165
21166#[no_mangle]
21167pub unsafe extern "C" fn __uselocale(loc: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
21168 loc
21169}
21170
21171#[repr(C)]
21172pub struct Utimbuf { actime: i64, modtime: i64 }
21173
21174#[no_mangle]
21175pub unsafe extern "C" fn utime(filename: *const c_char, times: *const Utimbuf) -> c_int {
21176 if times.is_null() {
21177 return utimensat(AT_FDCWD, filename, core::ptr::null(), 0);
21178 }
21179 let ts = [
21180 timespec { tv_sec: (*times).actime, tv_nsec: 0 },
21181 timespec { tv_sec: (*times).modtime, tv_nsec: 0 },
21182 ];
21183 utimensat(AT_FDCWD, filename, ts.as_ptr(), 0)
21184}
21185
21186#[no_mangle]
21187pub unsafe extern "C" fn vhangup() -> c_int {
21188 let r = <Arch as Syscalls>::syscall0(SYS_VHANGUP);
21189 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21190}
21191
21192#[no_mangle]
21193pub unsafe extern "C" fn vmsplice(fd: i32, iov: *const c_void, nr_segs: usize, flags: u32) -> isize {
21194 let r = <Arch as Syscalls>::syscall4(SYS_VMSPLICE, fd as i64, iov as i64, nr_segs as i64, flags as i64);
21195 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
21196}
21197
21198
21199
21200#[no_mangle]
21201pub unsafe extern "C" fn wait4(pid: i32, wstatus: *mut i32, options: i32, rusage: *mut core::ffi::c_void) -> i32 {
21202 syscall_ret(<Arch as Syscalls>::syscall4(SYS_WAIT4, pid as i64, wstatus as i64, options as i64, rusage as i64)) as i32
21203}
21204
21205#[no_mangle]
21206pub unsafe extern "C" fn waitid(idtype: i32, id: u32, infop: *mut core::ffi::c_void, options: i32) -> i32 {
21207 syscall_ret(<Arch as Syscalls>::syscall5(
21210 sysno(247, 95),
21211 idtype as i64,
21212 id as i64,
21213 infop as i64,
21214 options as i64,
21215 0,
21216 )) as i32
21217}
21218
21219#[no_mangle]
21220pub unsafe extern "C" fn __wcscoll_l(s1: *const u32, s2: *const u32, _loc: *mut core::ffi::c_void) -> i32 {
21221 crate::wcscmp(s1 as *const i32, s2 as *const i32)
21222}
21223
21224#[no_mangle]
21225pub unsafe extern "C" fn __wcsxfrm_l(dest: *mut u32, src: *const u32, n: usize, _loc: *mut core::ffi::c_void) -> usize {
21226 crate::wcscpy(dest as *mut i32, src as *const i32);
21227 n
21228}
21229
21230#[no_mangle]
21231pub unsafe extern "C" fn wcwidth(c: u32) -> i32 {
21232 if c == 0 { return 0; }
21233 if c < 32 || (c >= 0x7f && c < 0xa0) { return -1; }
21234 1
21235}
21236
21237
21238
21239
21240
21241#[no_mangle]
21248pub unsafe extern "C" fn strtod_l(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, _loc: *mut core::ffi::c_void) -> f64 {
21249 crate::strtod(nptr, endptr)
21250}
21251
21252#[no_mangle]
21253pub unsafe extern "C" fn strtof_l(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, _loc: *mut core::ffi::c_void) -> f32 {
21254 crate::strtof(nptr, endptr)
21255}
21256
21257#[no_mangle]
21258pub unsafe extern "C" fn strtold_l(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, _loc: *mut core::ffi::c_void) -> f64 {
21259 crate::strtod(nptr, endptr)
21260}
21261
21262#[repr(C)]
21267struct linux_dirent64 {
21268 d_ino: u64,
21269 d_off: i64,
21270 d_reclen: u16,
21271 d_type: u8,
21272 d_name: [u8; 0], }
21274
21275const DIR_BUF_SIZE: usize = 4096;
21279
21280#[repr(C)]
21281struct DirStream {
21282 fd: i32,
21283 pos: usize,
21284 len: usize,
21285 last_off: i64,
21286 buf: [u8; DIR_BUF_SIZE],
21287}
21288
21289unsafe fn dir_stream_new(fd: i32) -> *mut core::ffi::c_void {
21290 let ds = malloc(core::mem::size_of::<DirStream>()) as *mut DirStream;
21291 if ds.is_null() {
21292 crate::close(fd);
21293 ERRNO!() = ENOMEM;
21294 return core::ptr::null_mut();
21295 }
21296 core::ptr::write_bytes(ds, 0, 1);
21297 (*ds).fd = fd;
21298 ds as *mut core::ffi::c_void
21299}
21300
21301#[no_mangle]
21302pub unsafe extern "C" fn opendir(dirname: *const core::ffi::c_char) -> *mut core::ffi::c_void {
21303 let fd = openat(AT_FDCWD, dirname, O_DIRECTORY, 0); if fd < 0 { return core::ptr::null_mut(); }
21305 dir_stream_new(fd)
21306}
21307
21308#[no_mangle]
21309pub unsafe extern "C" fn closedir(dirp: *mut core::ffi::c_void) -> i32 {
21310 if dirp.is_null() { ERRNO!() = 22; return -1; }
21311 let ds = dirp as *mut DirStream;
21312 let r = crate::close((*ds).fd);
21313 free(dirp);
21314 r
21315}
21316
21317#[no_mangle]
21318pub unsafe extern "C" fn readdir(dirp: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
21319 if dirp.is_null() { ERRNO!() = 22; return core::ptr::null_mut(); }
21320 let ds = &mut *(dirp as *mut DirStream);
21321
21322 loop {
21323 if ds.pos >= ds.len {
21324 let nread = syscall_ret(<Arch as Syscalls>::syscall3(
21325 SYS_GETDENTS64,
21326 ds.fd as i64,
21327 ds.buf.as_mut_ptr() as i64,
21328 DIR_BUF_SIZE as i64,
21329 )) as isize;
21330 if nread <= 0 { return core::ptr::null_mut(); }
21331 ds.len = nread as usize;
21332 ds.pos = 0;
21333 }
21334
21335 let ent = ds.buf.as_ptr().add(ds.pos) as *const linux_dirent64;
21336 let ent_ref = &*ent;
21337 if ent_ref.d_reclen as usize == 0 {
21338 ds.len = 0;
21339 return core::ptr::null_mut();
21340 }
21341 ds.pos += ent_ref.d_reclen as usize;
21342 ds.last_off = ent_ref.d_off;
21343
21344 return ent as *mut core::ffi::c_void;
21346 }
21347}
21348
21349#[no_mangle]
21350pub unsafe extern "C" fn readdir_r(dirp: *mut core::ffi::c_void, _entry: *mut core::ffi::c_void, result: *mut *mut core::ffi::c_void) -> i32 {
21351 let ent = readdir(dirp);
21352 if ent.is_null() {
21353 *result = core::ptr::null_mut();
21354 } else {
21355 *result = ent;
21356 }
21357 0
21358}
21359
21360#[no_mangle]
21361pub unsafe extern "C" fn seekdir(dirp: *mut core::ffi::c_void, loc: i64) {
21362 if dirp.is_null() { return; }
21363 let ds = &mut *(dirp as *mut DirStream);
21364 <Arch as Syscalls>::syscall3(SYS_LSEEK, ds.fd as i64, loc, 0);
21365 ds.pos = 0;
21366 ds.len = 0;
21367}
21368
21369#[no_mangle]
21370pub unsafe extern "C" fn telldir(dirp: *mut core::ffi::c_void) -> i64 {
21371 if dirp.is_null() { return -1; }
21372 (*(dirp as *mut DirStream)).last_off
21373}
21374
21375#[no_mangle]
21376pub unsafe extern "C" fn rewinddir(dirp: *mut core::ffi::c_void) {
21377 if dirp.is_null() { return; }
21378 let ds = &mut *(dirp as *mut DirStream);
21379 <Arch as Syscalls>::syscall3(SYS_LSEEK, ds.fd as i64, 0, 0);
21380 ds.pos = 0;
21381 ds.len = 0;
21382 ds.last_off = 0;
21383}
21384
21385#[no_mangle]
21386pub unsafe extern "C" fn dirfd(dirp: *mut core::ffi::c_void) -> i32 {
21387 if dirp.is_null() { ERRNO!() = 22; return -1; }
21388 (*(dirp as *mut DirStream)).fd
21389}
21390
21391#[no_mangle]
21396pub unsafe extern "C" fn mprotect(addr: *mut u8, len: usize, prot: i32) -> i32 {
21397 syscall_ret(<Arch as Syscalls>::syscall3(SYS_MPROTECT, addr as i64, len as i64, prot as i64)) as i32
21398}
21399
21400#[no_mangle]
21401pub unsafe extern "C" fn msync(addr: *mut u8, len: usize, flags: i32) -> i32 {
21402 syscall_ret(<Arch as Syscalls>::syscall3(sysno(26, 227), addr as i64, len as i64, flags as i64)) as i32
21403}
21404
21405#[no_mangle]
21406pub unsafe extern "C" fn mlock(addr: *const u8, len: usize) -> i32 {
21407 syscall_ret(<Arch as Syscalls>::syscall2(sysno(149, 228), addr as i64, len as i64)) as i32
21408}
21409
21410#[no_mangle]
21411pub unsafe extern "C" fn munlock(addr: *const u8, len: usize) -> i32 {
21412 syscall_ret(<Arch as Syscalls>::syscall2(sysno(150, 229), addr as i64, len as i64)) as i32
21413}
21414
21415#[no_mangle]
21416pub unsafe extern "C" fn mlockall(flags: i32) -> i32 {
21417 syscall_ret(<Arch as Syscalls>::syscall1(sysno(151, 230), flags as i64)) as i32
21418}
21419
21420#[no_mangle]
21421pub unsafe extern "C" fn munlockall() -> i32 {
21422 syscall_ret(<Arch as Syscalls>::syscall0(sysno(152, 231))) as i32
21423}
21424
21425#[no_mangle]
21426pub unsafe extern "C" fn madvise(addr: *mut u8, len: usize, advice: i32) -> i32 {
21427 syscall_ret(<Arch as Syscalls>::syscall3(sysno(28, 233), addr as i64, len as i64, advice as i64)) as i32
21428}
21429
21430#[no_mangle]
21431pub unsafe extern "C" fn mincore(addr: *mut u8, len: usize, vec: *mut u8) -> i32 {
21432 syscall_ret(<Arch as Syscalls>::syscall3(sysno(27, 232), addr as i64, len as i64, vec as i64)) as i32
21433}
21434
21435#[no_mangle]
21442pub unsafe extern "C" fn drem(x: f64, y: f64) -> f64 {
21443 remainder(x, y)
21444}
21445
21446#[no_mangle]
21447pub unsafe extern "C" fn dremf(x: f32, y: f32) -> f32 {
21448 remainderf(x, y)
21449}
21450
21451#[no_mangle]
21452pub unsafe extern "C" fn pow10(x: f64) -> f64 {
21453 libm::pow(10.0, x)
21454}
21455
21456#[no_mangle]
21457pub unsafe extern "C" fn pow10f(x: f32) -> f32 {
21458 libm::powf(10.0, x)
21459}
21460
21461#[no_mangle]
21462pub unsafe extern "C" fn pow10l(x: f64) -> f64 {
21463 libm::pow(10.0, x)
21464}
21465
21466#[no_mangle]
21467pub unsafe extern "C" fn isless(x: f64, y: f64) -> i32 {
21468 if x.is_nan() || y.is_nan() { 0 } else { (x < y) as i32 }
21469}
21470
21471#[no_mangle]
21472pub unsafe extern "C" fn islessf(x: f32, y: f32) -> i32 {
21473 if x.is_nan() || y.is_nan() { 0 } else { (x < y) as i32 }
21474}
21475
21476#[no_mangle]
21477pub unsafe extern "C" fn lgamma_r(x: f64, signgamp: *mut i32) -> f64 {
21478 lgamma_r_impl(x, signgamp)
21479}
21480
21481#[no_mangle]
21482pub unsafe extern "C" fn lgammaf_r(x: f32, signgamp: *mut i32) -> f32 {
21483 if x.is_nan() {
21484 if !signgamp.is_null() { *signgamp = 1; }
21485 return x;
21486 }
21487 if x == 0.0 {
21488 if !signgamp.is_null() { *signgamp = if x.is_sign_negative() { -1 } else { 1 }; }
21489 feraiseexcept(FE_DIVBYZERO);
21490 return f32::INFINITY;
21491 }
21492 let (r, sign) = libm::lgammaf_r(x);
21493 if !signgamp.is_null() { *signgamp = sign; }
21494 r
21495}
21496
21497#[no_mangle]
21498pub unsafe extern "C" fn lgammal_r(x: f64, signgamp: *mut i32) -> f64 {
21499 lgamma_r(x, signgamp)
21500}
21501
21502#[no_mangle]
21507pub unsafe extern "C" fn islessequal(x: f64, y: f64) -> i32 {
21508 if x.is_nan() || y.is_nan() { 0 } else { (x <= y) as i32 }
21509}
21510
21511#[no_mangle]
21512pub unsafe extern "C" fn islessequalf(x: f32, y: f32) -> i32 {
21513 if x.is_nan() || y.is_nan() { 0 } else { (x <= y) as i32 }
21514}
21515
21516#[no_mangle]
21517pub unsafe extern "C" fn islessgreater(x: f64, y: f64) -> i32 {
21518 if x.is_nan() || y.is_nan() { 0 } else { (x < y || x > y) as i32 }
21519}
21520
21521#[no_mangle]
21522pub unsafe extern "C" fn islessgreaterf(x: f32, y: f32) -> i32 {
21523 if x.is_nan() || y.is_nan() { 0 } else { (x < y || x > y) as i32 }
21524}
21525
21526#[no_mangle]
21527pub unsafe extern "C" fn isgreater(x: f64, y: f64) -> i32 {
21528 if x.is_nan() || y.is_nan() { 0 } else { (x > y) as i32 }
21529}
21530
21531#[no_mangle]
21532pub unsafe extern "C" fn isgreaterf(x: f32, y: f32) -> i32 {
21533 if x.is_nan() || y.is_nan() { 0 } else { (x > y) as i32 }
21534}
21535
21536#[no_mangle]
21537pub unsafe extern "C" fn isgreaterequal(x: f64, y: f64) -> i32 {
21538 if x.is_nan() || y.is_nan() { 0 } else { (x >= y) as i32 }
21539}
21540
21541#[no_mangle]
21542pub unsafe extern "C" fn isgreaterequalf(x: f32, y: f32) -> i32 {
21543 if x.is_nan() || y.is_nan() { 0 } else { (x >= y) as i32 }
21544}
21545
21546#[no_mangle]
21551pub unsafe extern "C" fn stpcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char {
21552 let mut d = dest;
21553 let mut s = src;
21554 while *s != 0 {
21555 *d = *s;
21556 d = d.add(1);
21557 s = s.add(1);
21558 }
21559 *d = 0;
21560 d
21561}
21562
21563#[no_mangle]
21564pub unsafe extern "C" fn stpncpy(dest: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
21565 let mut i = 0;
21566 while i < n && *src.add(i) != 0 {
21567 *dest.add(i) = *src.add(i);
21568 i += 1;
21569 }
21570 let end = dest.add(i);
21571 while i < n {
21572 *dest.add(i) = 0;
21573 i += 1;
21574 }
21575 end
21576}
21577
21578#[no_mangle]
21579pub unsafe extern "C" fn strchrnul(s: *const c_char, c: c_int) -> *mut c_char {
21580 let mut p = s;
21581 while *p != 0 && *p as c_int != c {
21582 p = p.add(1);
21583 }
21584 p as *mut c_char
21585}
21586
21587#[no_mangle]
21588pub unsafe extern "C" fn fstatat(dirfd: c_int, path: *const c_char, buf: *mut Stat, flags: c_int) -> c_int {
21589 let r = sys_newfstatat(dirfd, path, buf as *mut u8, flags);
21590 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21591}
21592
21593#[no_mangle]
21594pub unsafe extern "C" fn execvpe(
21595 file: *const c_char,
21596 argv: *const *const c_char,
21597 envp: *const *const c_char,
21598) -> c_int {
21599 ERRNO!() = ENOENT_VAL;
21600 if file.is_null() || *file == 0 {
21601 return -1;
21602 }
21603 let mut p = file;
21604 while *p != 0 {
21605 if *p == b'/' as c_char {
21606 return execve(file, argv, envp);
21607 }
21608 p = p.add(1);
21609 }
21610 let file_len = crate::strlen(file);
21611 let path = crate::getenv(b"PATH\0".as_ptr() as *const c_char);
21612 let default_path = b"/usr/local/bin:/bin:/usr/bin\0";
21613 let path = if path.is_null() { default_path.as_ptr() as *const c_char } else { path };
21614
21615 let mut seen_eacces = false;
21616 let mut buf = [0 as c_char; 4096];
21617 let mut dir = path;
21618 loop {
21619 let mut end = dir;
21620 while *end != 0 && *end != b':' as c_char { end = end.add(1); }
21621 let dlen = end.offset_from(dir) as usize;
21622 let need_slash = dlen > 0;
21624 let total = dlen + need_slash as usize + file_len;
21625 if total < buf.len() {
21626 let mut i = 0;
21627 while i < dlen { buf[i] = *dir.add(i); i += 1; }
21628 if need_slash { buf[i] = b'/' as c_char; i += 1; }
21629 let mut j = 0;
21630 while j < file_len { buf[i + j] = *file.add(j); j += 1; }
21631 buf[i + j] = 0;
21632 execve(buf.as_ptr(), argv, envp);
21633 match ERRNO!() {
21634 13 => seen_eacces = true, 2 | 20 => {} _ => return -1,
21637 }
21638 }
21639 if *end == 0 { break; }
21640 dir = end.add(1);
21641 }
21642 ERRNO!() = if seen_eacces { 13 } else { 2 };
21643 -1
21644}
21645
21646#[no_mangle]
21649pub unsafe extern "C" fn strcoll_l(s1: *const c_char, s2: *const c_char, _loc: locale_t) -> c_int {
21650 strcoll(s1, s2)
21651}
21652
21653#[no_mangle]
21654pub unsafe extern "C" fn strxfrm_l(dest: *mut c_char, src: *const c_char, n: usize, _loc: locale_t) -> usize {
21655 strxfrm(dest, src, n)
21656}
21657
21658#[no_mangle]
21659pub unsafe extern "C" fn strerror_l(errnum: c_int, _loc: locale_t) -> *mut c_char {
21660 strerror(errnum)
21661}
21662
21663#[no_mangle]
21664pub unsafe extern "C" fn strcasecmp_l(s1: *const c_char, s2: *const c_char, _loc: locale_t) -> c_int {
21665 strcasecmp(s1, s2)
21666}
21667
21668#[no_mangle]
21669pub unsafe extern "C" fn strncasecmp_l(s1: *const c_char, s2: *const c_char, n: usize, _loc: locale_t) -> c_int {
21670 strncasecmp(s1, s2, n)
21671}
21672
21673#[no_mangle]
21674pub unsafe extern "C" fn strftime_l(s: *mut c_char, max: usize, fmt: *const c_char, tm: *const tm, _loc: locale_t) -> usize {
21675 strftime(s, max, fmt, tm)
21676}
21677
21678#[no_mangle]
21679pub unsafe extern "C" fn nl_langinfo_l(item: c_int, _loc: locale_t) -> *mut c_char {
21680 nl_langinfo(item)
21681}
21682
21683#[no_mangle]
21684pub unsafe extern "C" fn wcscoll_l(s1: *const u32, s2: *const u32, _loc: locale_t) -> c_int {
21685 wcscoll(s1, s2)
21686}
21687
21688#[no_mangle]
21689pub unsafe extern "C" fn wcsxfrm_l(dst: *mut wchar_t, src: *const wchar_t, n: usize, _loc: locale_t) -> usize {
21690 wcsxfrm(dst, src, n)
21691}
21692
21693#[no_mangle]
21694pub unsafe extern "C" fn wcsftime_l(s: *mut u32, max: usize, fmt: *const u32, tm: *const c_void, _loc: locale_t) -> usize {
21695 wcsftime(s, max, fmt, tm)
21696}
21697
21698#[no_mangle]
21699pub unsafe extern "C" fn wctype_l(name: *const c_char, _loc: locale_t) -> wctype_t {
21700 wctype(name)
21701}
21702
21703#[no_mangle]
21704pub unsafe extern "C" fn wctrans_l(name: *const c_char, _loc: locale_t) -> wctrans_t {
21705 wctrans(name)
21706}
21707
21708#[no_mangle]
21709pub unsafe extern "C" fn towlower_l(c: wint_t, _loc: locale_t) -> wint_t {
21710 towlower(c)
21711}
21712
21713#[no_mangle]
21714pub unsafe extern "C" fn towupper_l(c: wint_t, _loc: locale_t) -> wint_t {
21715 towupper(c)
21716}
21717
21718#[no_mangle]
21719pub unsafe extern "C" fn towctrans_l(c: wint_t, desc: wctrans_t, _loc: locale_t) -> wint_t {
21720 towctrans(c, desc)
21721}
21722
21723#[no_mangle] pub unsafe extern "C" fn iswalnum_l(c: wint_t, _l: locale_t) -> c_int { iswalnum(c) }
21724#[no_mangle] pub unsafe extern "C" fn iswalpha_l(c: wint_t, _l: locale_t) -> c_int { iswalpha(c) }
21725#[no_mangle] pub unsafe extern "C" fn iswblank_l(c: wint_t, _l: locale_t) -> c_int { iswblank(c) }
21726#[no_mangle] pub unsafe extern "C" fn iswcntrl_l(c: wint_t, _l: locale_t) -> c_int { iswcntrl(c) }
21727#[no_mangle] pub unsafe extern "C" fn iswdigit_l(c: wint_t, _l: locale_t) -> c_int { iswdigit(c) }
21728#[no_mangle] pub unsafe extern "C" fn iswgraph_l(c: wint_t, _l: locale_t) -> c_int { iswgraph(c) }
21729#[no_mangle] pub unsafe extern "C" fn iswlower_l(c: wint_t, _l: locale_t) -> c_int { iswlower(c) }
21730#[no_mangle] pub unsafe extern "C" fn iswprint_l(c: wint_t, _l: locale_t) -> c_int { iswprint(c) }
21731#[no_mangle] pub unsafe extern "C" fn iswpunct_l(c: wint_t, _l: locale_t) -> c_int { iswpunct(c) }
21732#[no_mangle] pub unsafe extern "C" fn iswspace_l(c: wint_t, _l: locale_t) -> c_int { iswspace(c) }
21733#[no_mangle] pub unsafe extern "C" fn iswupper_l(c: wint_t, _l: locale_t) -> c_int { iswupper(c) }
21734#[no_mangle] pub unsafe extern "C" fn iswxdigit_l(c: wint_t, _l: locale_t) -> c_int { iswxdigit(c) }
21735#[no_mangle] pub unsafe extern "C" fn iswctype_l(c: wint_t, desc: wctype_t, _l: locale_t) -> c_int { iswctype(c, desc) }
21736
21737#[no_mangle] pub unsafe extern "C" fn __isoc99_scanf(fmt: *const c_char, args: ...) -> c_int { vfscanf(stdin, fmt, args) }
21739#[no_mangle] pub unsafe extern "C" fn __isoc99_fscanf(f: *mut FILE, fmt: *const c_char, args: ...) -> c_int { vfscanf(f, fmt, args) }
21740#[no_mangle] pub unsafe extern "C" fn __isoc99_sscanf(s: *const c_char, fmt: *const c_char, args: ...) -> c_int { vsscanf(s, fmt, args) }
21741#[no_mangle] pub unsafe extern "C" fn __isoc99_vscanf(fmt: *const c_char, args: VaList) -> c_int { vfscanf(stdin, fmt, args) }
21742#[no_mangle] pub unsafe extern "C" fn __isoc99_vfscanf(f: *mut FILE, fmt: *const c_char, args: VaList) -> c_int { vfscanf(f, fmt, args) }
21743#[no_mangle] pub unsafe extern "C" fn __isoc99_vsscanf(s: *const c_char, fmt: *const c_char, args: VaList) -> c_int { vsscanf(s, fmt, args) }
21744#[no_mangle] pub unsafe extern "C" fn __isoc99_wscanf(fmt: *const wchar_t, args: ...) -> c_int { vfwscanf(stdin, fmt, args) }
21745#[no_mangle] pub unsafe extern "C" fn __isoc99_fwscanf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int { vfwscanf(f, fmt, args) }
21746#[no_mangle] pub unsafe extern "C" fn __isoc99_swscanf(s: *const wchar_t, fmt: *const wchar_t, args: ...) -> c_int { vswscanf(s, fmt, args) }
21747#[no_mangle] pub unsafe extern "C" fn __isoc99_vwscanf(fmt: *const wchar_t, args: VaList) -> c_int { vfwscanf(stdin, fmt, args) }
21748#[no_mangle] pub unsafe extern "C" fn __isoc99_vfwscanf(f: *mut FILE, fmt: *const wchar_t, args: VaList) -> c_int { vfwscanf(f, fmt, args) }
21749#[no_mangle] pub unsafe extern "C" fn __isoc99_vswscanf(s: *const wchar_t, fmt: *const wchar_t, args: VaList) -> c_int { vswscanf(s, fmt, args) }
21750
21751#[no_mangle] pub unsafe extern "C" fn clearerr_unlocked(f: *mut FILE) { clearerr(f) }
21754#[no_mangle] pub unsafe extern "C" fn feof_unlocked(f: *mut FILE) -> c_int { feof(f) }
21755#[no_mangle] pub unsafe extern "C" fn ferror_unlocked(f: *mut FILE) -> c_int { ferror(f) }
21756#[no_mangle] pub unsafe extern "C" fn fileno_unlocked(f: *mut FILE) -> c_int { fileno(f) }
21757#[no_mangle] pub unsafe extern "C" fn fflush_unlocked(f: *mut FILE) -> c_int { fflush(f) }
21758#[no_mangle] pub unsafe extern "C" fn fgetc_unlocked(f: *mut FILE) -> c_int { fgetc(f) }
21759#[no_mangle] pub unsafe extern "C" fn fgets_unlocked(s: *mut c_char, n: c_int, f: *mut FILE) -> *mut c_char { fgets(s, n, f) }
21760#[no_mangle] pub unsafe extern "C" fn fputc_unlocked(c: c_int, f: *mut FILE) -> c_int { fputc(c, f) }
21761#[no_mangle] pub unsafe extern "C" fn fputs_unlocked(s: *const c_char, f: *mut FILE) -> c_int { fputs(s, f) }
21762#[no_mangle] pub unsafe extern "C" fn fread_unlocked(p: *mut c_void, size: usize, n: usize, f: *mut FILE) -> usize { fread(p, size, n, f) }
21763#[no_mangle] pub unsafe extern "C" fn fwrite_unlocked(p: *const c_void, size: usize, n: usize, f: *mut FILE) -> usize { fwrite(p, size, n, f) }
21764#[no_mangle] pub unsafe extern "C" fn fgetwc_unlocked(f: *mut FILE) -> wint_t { fgetwc(f) }
21765#[no_mangle] pub unsafe extern "C" fn fgetws_unlocked(s: *mut u32, n: c_int, f: *mut c_void) -> *mut u32 { fgetws(s, n, f) }
21766#[no_mangle] pub unsafe extern "C" fn fputwc_unlocked(c: wchar_t, f: *mut FILE) -> wint_t { fputwc(c, f) }
21767#[no_mangle] pub unsafe extern "C" fn fputws_unlocked(s: *const wchar_t, f: *mut FILE) -> c_int { fputws(s, f) }
21768#[no_mangle] pub unsafe extern "C" fn getwc_unlocked(f: *mut c_void) -> wint_t { getwc(f) }
21769#[no_mangle] pub unsafe extern "C" fn putwc_unlocked(c: u32, f: *mut c_void) -> wint_t { putwc(c, f) }
21770#[no_mangle] pub unsafe extern "C" fn getwchar_unlocked() -> wint_t { getwchar() }
21771#[no_mangle] pub unsafe extern "C" fn putwchar_unlocked(c: wchar_t) -> wint_t { putwchar(c) }
21772#[no_mangle] pub unsafe extern "C" fn fpurge(f: *mut FILE) { clearerr(f) }
21773#[no_mangle] pub unsafe extern "C" fn _IO_getc(f: *mut FILE) -> c_int { getc(f) }
21774#[no_mangle] pub unsafe extern "C" fn _IO_putc(c: c_int, f: *mut FILE) -> c_int { putc(c, f) }
21775#[no_mangle] pub unsafe extern "C" fn _IO_getc_unlocked(f: *mut FILE) -> c_int { getc(f) }
21776#[no_mangle] pub unsafe extern "C" fn _IO_putc_unlocked(c: c_int, f: *mut FILE) -> c_int { putc(c, f) }
21777#[no_mangle] pub unsafe extern "C" fn _IO_feof_unlocked(f: *mut FILE) -> c_int { feof(f) }
21778#[no_mangle] pub unsafe extern "C" fn _IO_ferror_unlocked(f: *mut FILE) -> c_int { ferror(f) }
21779
21780#[no_mangle] pub unsafe extern "C" fn __getauxval(t: c_ulong) -> c_ulong { getauxval(t) }
21782#[no_mangle] pub unsafe extern "C" fn __longjmp(env: *const c_ulong, val: c_int) -> ! { longjmp(env, val) }
21783#[no_mangle] pub unsafe extern "C" fn bsd_signal(sig: c_int, handler: usize) -> usize { signal(sig, handler) }
21784#[no_mangle] pub unsafe extern "C" fn __sysv_signal(sig: c_int, handler: usize) -> usize { signal(sig, handler) }
21785#[no_mangle] pub unsafe extern "C" fn eaccess(path: *const c_char, mode: c_int) -> c_int { access(path, mode) }
21786#[no_mangle] pub unsafe extern "C" fn __xpg_basename(path: *mut c_char) -> *mut c_char { basename(path) }
21787#[no_mangle] pub unsafe extern "C" fn __xpg_strerror_r(errnum: c_int, buf: *mut c_char, len: usize) -> c_int { strerror_r(errnum, buf, len) }
21788#[no_mangle] pub unsafe extern "C" fn __posix_getopt(argc: c_int, argv: *const *const c_char, optstring: *const c_char) -> c_int { getopt(argc, argv, optstring) }
21789
21790#[no_mangle]
21795pub unsafe extern "C" fn cfsetspeed(termios_p: *mut c_void, speed: u32) -> c_int {
21796 let r = cfsetispeed(termios_p, speed);
21797 if r != 0 { return r; }
21798 cfsetospeed(termios_p, speed)
21799}
21800
21801#[no_mangle]
21802pub unsafe extern "C" fn futimesat(dirfd: c_int, path: *const c_char, times: *const timeval) -> c_int {
21803 if times.is_null() {
21804 return utimensat(dirfd, path, core::ptr::null(), 0);
21805 }
21806 let tv = times as *const [timeval; 2];
21807 let mut ts: [timespec; 2] = [
21808 timespec { tv_sec: (*tv)[0].tv_sec, tv_nsec: (*tv)[0].tv_usec * 1000 },
21809 timespec { tv_sec: (*tv)[1].tv_sec, tv_nsec: (*tv)[1].tv_usec * 1000 },
21810 ];
21811 for t in &mut ts {
21812 if t.tv_nsec < 0 || t.tv_nsec >= 1_000_000_000 {
21813 ERRNO!() = EINVAL;
21814 return -1;
21815 }
21816 }
21817 utimensat(dirfd, path, ts.as_ptr(), 0)
21818}
21819
21820#[no_mangle]
21821pub unsafe extern "C" fn membarrier(cmd: c_int, flags: c_int, cpu_id: c_int) -> c_int {
21822 <Arch as Syscalls>::syscall3(SYS_MEMBARRIER, cmd as i64, flags as i64, cpu_id as i64) as c_int
21823}
21824
21825#[no_mangle]
21826pub unsafe extern "C" fn mremap(
21827 old_address: *mut c_void,
21828 old_size: usize,
21829 new_size: usize,
21830 flags: c_int,
21831 mut args: ...
21832) -> *mut c_void {
21833 let new_address = if flags & 2 != 0 { args.next_arg::<*mut c_void>() } else { core::ptr::null_mut() };
21834 let r = <Arch as Syscalls>::syscall5(
21835 SYS_MREMAP,
21836 old_address as i64,
21837 old_size as i64,
21838 new_size as i64,
21839 flags as i64,
21840 new_address as i64,
21841 );
21842 if r < 0 {
21843 ERRNO!() = (-r) as c_int;
21844 return (-1isize) as *mut c_void;
21845 }
21846 r as *mut c_void
21847}
21848
21849#[no_mangle]
21850pub unsafe extern "C" fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: usize) -> c_int {
21851 let name = ptsname(fd);
21852 if name.is_null() { return -1; }
21853 let n = crate::strlen(name);
21854 if n + 1 > buflen {
21855 ERRNO!() = ERANGE_VAL;
21856 return ERANGE_VAL;
21857 }
21858 core::ptr::copy_nonoverlapping(name, buf, n + 1);
21859 0
21860}
21861
21862#[no_mangle]
21863pub unsafe extern "C" fn posix_getdents(fd: c_int, buf: *mut c_void, len: usize, flags: c_int) -> isize {
21864 if flags != 0 {
21865 ERRNO!() = EINVAL;
21866 return -1;
21867 }
21868 let r = <Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, buf as i64, len as i64);
21869 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
21870}
21871
21872#[no_mangle]
21873pub unsafe extern "C" fn riscv_flush_icache(start: *mut c_void, end: *mut c_void, flags: c_ulong) -> c_int {
21874 #[cfg(target_arch = "riscv64")]
21875 {
21876 let r = <Arch as Syscalls>::syscall3(259, start as i64, end as i64, flags as i64);
21877 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21878 }
21879 #[cfg(not(target_arch = "riscv64"))]
21880 {
21881 let _ = (start, end, flags);
21882 0
21883 }
21884}
21885
21886#[no_mangle]
21887pub unsafe extern "C" fn __riscv_flush_icache(start: *mut c_void, end: *mut c_void, flags: c_ulong) -> c_int {
21888 riscv_flush_icache(start, end, flags)
21889}
21890
21891#[no_mangle]
21892pub unsafe extern "C" fn mkostemps(template: *mut c_char, suffixlen: c_int, flags: c_int) -> c_int {
21893 let fd = mkstemps(template, suffixlen);
21894 if fd >= 0 && flags & O_CLOEXEC != 0 {
21895 sys_fcntl(fd, F_SETFD, FD_CLOEXEC as i64);
21896 }
21897 fd
21898}
21899
21900#[no_mangle]
21901pub unsafe extern "C" fn statfs(path: *const c_char, buf: *mut c_void) -> c_int {
21902 let r = <Arch as Syscalls>::syscall2(SYS_STATFS, path as i64, buf as i64);
21903 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21904}
21905
21906#[no_mangle]
21907pub unsafe extern "C" fn fstatfs(fd: c_int, buf: *mut c_void) -> c_int {
21908 let r = <Arch as Syscalls>::syscall2(SYS_FSTATFS, fd as i64, buf as i64);
21909 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21910}
21911
21912#[no_mangle]
21913pub unsafe extern "C" fn sysinfo(info: *mut c_void) -> c_int {
21914 let r = <Arch as Syscalls>::syscall1(SYS_SYSINFO, info as i64);
21915 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21916}
21917
21918#[no_mangle]
21919pub unsafe extern "C" fn pthread_tryjoin_np(thread: PthreadT, retval: *mut *mut c_void) -> c_int {
21920 let slot = thread as *mut Thread;
21921 if slot.is_null() { return EINVAL; }
21922 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
21923 let tid = core::ptr::read_volatile(&raw const (*slot).tid);
21924 if tid > 0 { return EBUSY; }
21925 if tid < 0 { return EINVAL; }
21926 pthread_join(thread, retval)
21927}
21928
21929#[no_mangle]
21930pub unsafe extern "C" fn pthread_timedjoin_np(thread: PthreadT, retval: *mut *mut c_void, abstime: *const timespec) -> c_int {
21931 let slot = thread as *mut Thread;
21932 if slot.is_null() { return EINVAL; }
21933 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
21934 loop {
21935 let r = pthread_tryjoin_np(thread, retval);
21936 if r != EBUSY { return r; }
21937 let tid = core::ptr::read_volatile(&raw const (*slot).tid);
21938 if tid <= 0 { continue; }
21939 let e = futex_timedwait(&raw mut (*slot).tid, tid, abstime);
21940 if e == ETIMEDOUT { return ETIMEDOUT; }
21941 }
21942}
21943
21944
21945#[repr(C)]
21948pub struct UtmpExit {
21949 pub e_termination: i16,
21950 pub e_exit: i16,
21951}
21952
21953#[repr(C)]
21954pub struct Utmpx {
21955 pub ut_type: i16,
21956 pub __ut_pad1: i16,
21957 pub ut_pid: i32,
21958 pub ut_line: [c_char; 32],
21959 pub ut_id: [c_char; 4],
21960 pub ut_user: [c_char; 32],
21961 pub ut_host: [c_char; 256],
21962 pub ut_exit: UtmpExit,
21963 pub ut_session: i32,
21964 pub __ut_pad2: i32,
21965 pub ut_tv: timeval,
21966 pub ut_addr_v6: [u32; 4],
21967 pub __unused: [u8; 20],
21968}
21969
21970const UTMP_SIZE: usize = 400;
21971const _: [(); UTMP_SIZE] = [(); core::mem::size_of::<Utmpx>()];
21972
21973static mut UTMP_FD: c_int = -1;
21974static mut UTMP_PATH: [u8; 256] = [0; 256];
21975static mut UTMP_PATH_SET: bool = false;
21976#[repr(align(8))]
21977struct UtmpBuf([u8; UTMP_SIZE]);
21978static mut UTMP_BUF: UtmpBuf = UtmpBuf([0; UTMP_SIZE]);
21979
21980unsafe fn utmp_path_ptr() -> *const c_char {
21981 if !UTMP_PATH_SET {
21982 let default = b"/var/run/utmp\0";
21983 let mut i = 0;
21984 while i < default.len() && i < UTMP_PATH.len() {
21985 UTMP_PATH[i] = default[i];
21986 i += 1;
21987 }
21988 UTMP_PATH_SET = true;
21989 }
21990 UTMP_PATH.as_ptr() as *const c_char
21991}
21992
21993unsafe fn utmp_open_read() -> c_int {
21994 if UTMP_FD >= 0 {
21995 crate::close(UTMP_FD);
21996 }
21997 UTMP_FD = crate::open(utmp_path_ptr(), 0, 0);
21998 UTMP_FD
21999}
22000
22001unsafe fn utmp_open_append() -> c_int {
22002 crate::open(utmp_path_ptr(), 1 | 64 | 1024, 0o644)
22003}
22004
22005#[no_mangle]
22006pub unsafe extern "C" fn setutent() {
22007 let _ = utmp_open_read();
22008}
22009
22010#[no_mangle]
22011pub unsafe extern "C" fn endutent() {
22012 if UTMP_FD >= 0 {
22013 crate::close(UTMP_FD);
22014 UTMP_FD = -1;
22015 }
22016}
22017
22018#[no_mangle]
22019pub unsafe extern "C" fn getutent() -> *mut c_void {
22020 if UTMP_FD < 0 && utmp_open_read() < 0 {
22021 return core::ptr::null_mut();
22022 }
22023 let n = crate::read(UTMP_FD, UTMP_BUF.0.as_mut_ptr() as *mut c_void, UTMP_SIZE);
22024 if n == UTMP_SIZE as isize {
22025 UTMP_BUF.0.as_mut_ptr() as *mut c_void
22026 } else {
22027 core::ptr::null_mut()
22028 }
22029}
22030
22031unsafe fn utmp_id_eq(a: &[c_char; 4], b: &[c_char; 4]) -> bool {
22032 a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]
22033}
22034
22035unsafe fn utmp_line_eq(a: &[c_char; 32], b: &[c_char; 32]) -> bool {
22036 let mut i = 0;
22037 while i < 32 {
22038 if a[i] != b[i] { return false; }
22039 if a[i] == 0 { return true; }
22040 i += 1;
22041 }
22042 true
22043}
22044
22045#[no_mangle]
22046pub unsafe extern "C" fn getutid(ut: *const c_void) -> *mut c_void {
22047 if ut.is_null() { return core::ptr::null_mut(); }
22048 let want = &*(ut as *const Utmpx);
22049 loop {
22050 let p = getutent();
22051 if p.is_null() { return p; }
22052 let cur = &*(p as *const Utmpx);
22053 let matched = match want.ut_type {
22054 1 | 2 | 3 | 4 => cur.ut_type == want.ut_type,
22055 _ => utmp_id_eq(&cur.ut_id, &want.ut_id)
22056 && (want.ut_type == 0 || cur.ut_type == want.ut_type),
22057 };
22058 if matched { return p; }
22059 }
22060}
22061
22062#[no_mangle]
22063pub unsafe extern "C" fn getutline(ut: *const c_void) -> *mut c_void {
22064 if ut.is_null() { return core::ptr::null_mut(); }
22065 let want = &*(ut as *const Utmpx);
22066 loop {
22067 let p = getutent();
22068 if p.is_null() { return p; }
22069 if utmp_line_eq(&(*(p as *const Utmpx)).ut_line, &want.ut_line) {
22070 return p;
22071 }
22072 }
22073}
22074
22075#[no_mangle]
22076pub unsafe extern "C" fn pututline(ut: *const c_void) -> *mut c_void {
22077 if ut.is_null() { return core::ptr::null_mut(); }
22078 let fd = utmp_open_append();
22079 if fd < 0 { return core::ptr::null_mut(); }
22080 let n = crate::write(fd, ut, UTMP_SIZE);
22081 crate::close(fd);
22082 if n == UTMP_SIZE as isize { ut as *mut c_void } else { core::ptr::null_mut() }
22083}
22084
22085#[no_mangle]
22086pub unsafe extern "C" fn updwtmp(file: *const c_char, ut: *const c_void) {
22087 if file.is_null() || ut.is_null() { return; }
22088 let fd = crate::open(file, 1 | 64 | 1024, 0o644);
22089 if fd >= 0 {
22090 let _ = crate::write(fd, ut, UTMP_SIZE);
22091 crate::close(fd);
22092 }
22093}
22094
22095unsafe fn utmp_set_name(file: *const c_char) -> c_int {
22096 if file.is_null() { return -1; }
22097 let len = crate::strlen(file);
22098 if len + 1 > UTMP_PATH.len() { return -1; }
22099 if UTMP_FD >= 0 {
22100 crate::close(UTMP_FD);
22101 UTMP_FD = -1;
22102 }
22103 core::ptr::copy_nonoverlapping(file, UTMP_PATH.as_mut_ptr() as *mut c_char, len + 1);
22104 UTMP_PATH_SET = true;
22105 0
22106}
22107
22108#[no_mangle]
22109pub unsafe extern "C" fn utmpname(file: *const c_char) -> c_int { utmp_set_name(file) }
22110
22111#[no_mangle]
22112pub unsafe extern "C" fn utmpxname(file: *const c_char) -> c_int { utmp_set_name(file) }
22113
22114
22115#[no_mangle] pub static mut ___environ: *mut *mut c_char = core::ptr::null_mut();
22117#[no_mangle] pub static mut _environ: *mut *mut c_char = core::ptr::null_mut();
22118#[no_mangle] pub unsafe extern "C" fn __freelocale(loc: locale_t) { freelocale(loc) }
22119#[no_mangle] pub unsafe extern "C" fn __getdelim(lineptr: *mut *mut c_char, n: *mut usize, delim: c_int, stream: *mut FILE) -> isize { getdelim(lineptr, n, delim, stream) }
22120#[no_mangle] pub unsafe extern "C" fn __strtod_l(s: *const c_char, end: *mut *mut c_char, loc: locale_t) -> f64 { strtod_l(s, end, loc) }
22121#[no_mangle] pub unsafe extern "C" fn __strtof_l(s: *const c_char, end: *mut *mut c_char, loc: locale_t) -> f32 { strtof_l(s, end, loc) }
22122#[no_mangle] pub unsafe extern "C" fn __strtold_l(s: *const c_char, end: *mut *mut c_char, loc: locale_t) -> f64 { strtold_l(s, end, loc) }
22123
22124#[no_mangle] pub unsafe extern "C" fn __strtol_internal(s: *const c_char, end: *mut *mut c_char, base: c_int) -> c_long { strtol(s, end, base) }
22125#[no_mangle] pub unsafe extern "C" fn __strtoul_internal(s: *const c_char, end: *mut *mut c_char, base: c_int) -> c_ulong { strtoul(s, end, base) }
22126#[no_mangle] pub unsafe extern "C" fn __strtoll_internal(s: *const c_char, end: *mut *mut c_char, base: c_int) -> c_longlong { strtoll(s, end, base) }
22127#[no_mangle] pub unsafe extern "C" fn __strtoull_internal(s: *const c_char, end: *mut *mut c_char, base: c_int) -> c_ulonglong { strtoull(s, end, base) }
22128#[no_mangle] pub unsafe extern "C" fn __strtoimax_internal(s: *const c_char, end: *mut *mut c_char, base: c_int) -> i64 { strtoimax(s, end, base) }
22129#[no_mangle] pub unsafe extern "C" fn __strtoumax_internal(s: *const c_char, end: *mut *mut c_char, base: c_int) -> u64 { strtoumax(s, end, base) }
22130
22131const MAX_NS: usize = 3;
22136const MAX_SEARCH: usize = 6;
22137const HOST_NOT_FOUND: c_int = 1;
22138const TRY_AGAIN: c_int = 2;
22139const NO_RECOVERY: c_int = 3;
22140const NO_DATA: c_int = 4;
22141
22142static mut NS_COUNT: usize = 0;
22143static mut NS_ADDRS: [u32; MAX_NS] = [0; MAX_NS];
22144static mut SEARCH_COUNT: usize = 0;
22145static mut SEARCH_DOMAINS: [[u8; 256]; MAX_SEARCH] = [[0; 256]; MAX_SEARCH];
22146static mut RESOLV_INITIALIZED: bool = false;
22147
22148#[repr(C)]
22149struct SockAddrIn {
22150 sin_family: u16,
22151 sin_port: u16,
22152 sin_addr: u32,
22153 sin_zero: [u8; 8],
22154}
22155
22156#[repr(C)]
22157struct PollFd {
22158 fd: c_int,
22159 events: i16,
22160 revents: i16,
22161}
22162
22163unsafe fn resolv_skip_ws(line: &[u8], mut i: usize) -> usize {
22164 while i < line.len() && (line[i] == b' ' || line[i] == b'\t') { i += 1; }
22165 i
22166}
22167
22168unsafe fn resolv_token<'a>(line: &'a [u8], mut i: usize) -> (&'a [u8], usize) {
22169 let start = i;
22170 while i < line.len() && line[i] != b' ' && line[i] != b'\t' && line[i] != b'#' { i += 1; }
22171 (&line[start..i], i)
22172}
22173
22174unsafe fn resolv_parse_config() -> c_int {
22175 RESOLV_INITIALIZED = true;
22176 NS_COUNT = 0;
22177 SEARCH_COUNT = 0;
22178 let path = b"/etc/resolv.conf\0";
22179 let fd = crate::open(path.as_ptr() as *const c_char, 0, 0);
22180 if fd < 0 { return -1; }
22181 let mut buf = [0u8; 4096];
22182 let n = crate::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len());
22183 crate::close(fd);
22184 if n <= 0 { return -1; }
22185 let len = n as usize;
22186 let mut i = 0;
22187 while i < len {
22188 let start = i;
22189 while i < len && buf[i] != b'\n' { i += 1; }
22190 let line = &buf[start..i];
22191 i += 1;
22192 let mut j = resolv_skip_ws(line, 0);
22193 if j >= line.len() || line[j] == b'#' { continue; }
22194 let (key, next) = resolv_token(line, j);
22195 j = next;
22196 if key == b"nameserver" {
22197 j = resolv_skip_ws(line, j);
22198 let (tok, _) = resolv_token(line, j);
22199 if !tok.is_empty() && NS_COUNT < MAX_NS {
22200 let mut name = [0u8; 64];
22201 let l = core::cmp::min(tok.len(), 63);
22202 name[..l].copy_from_slice(&tok[..l]);
22203 let addr = crate::inet_addr(name.as_ptr() as *const c_char);
22204 if addr != u32::MAX {
22205 NS_ADDRS[NS_COUNT] = addr;
22206 NS_COUNT += 1;
22207 }
22208 }
22209 } else if key == b"search" || key == b"domain" {
22210 loop {
22211 j = resolv_skip_ws(line, j);
22212 if j >= line.len() || line[j] == b'#' { break; }
22213 let (tok, next) = resolv_token(line, j);
22214 j = next;
22215 if tok.is_empty() { break; }
22216 if SEARCH_COUNT < MAX_SEARCH {
22217 let l = core::cmp::min(tok.len(), 255);
22218 SEARCH_DOMAINS[SEARCH_COUNT][..l].copy_from_slice(&tok[..l]);
22219 SEARCH_DOMAINS[SEARCH_COUNT][l] = 0;
22220 SEARCH_COUNT += 1;
22221 }
22222 if key == b"domain" { break; }
22223 }
22224 }
22225 }
22226 0
22227}
22228
22229#[no_mangle]
22230pub unsafe extern "C" fn res_init() -> c_int {
22231 let _ = resolv_parse_config();
22232 0
22233}
22234
22235#[no_mangle]
22236pub unsafe extern "C" fn res_mkquery(
22237 op: c_int,
22238 dname: *const c_char,
22239 class: c_int,
22240 type_: c_int,
22241 _data: *const u8,
22242 _datalen: c_int,
22243 _newrr: *const u8,
22244 buf: *mut u8,
22245 buflen: c_int,
22246) -> c_int {
22247 if dname.is_null() || buf.is_null() { return -1; }
22248 let mut l = crate::strnlen(dname as *const u8, 255);
22249 if l > 0 && *dname.add(l - 1) == b'.' as c_char { l -= 1; }
22250 if l > 0 && *dname.add(l - 1) == b'.' as c_char { return -1; }
22251 let n = 17 + l + if l != 0 { 1 } else { 0 };
22252 if l > 253 || buflen < n as c_int || op < 0 || op > 15 || class < 0 || class > 255 || type_ < 0 || type_ > 255 {
22253 return -1;
22254 }
22255 let mut q = [0u8; 280];
22256 crate::memset(q.as_mut_ptr() as *mut c_void, 0, n);
22257 q[2] = (op * 8 + 1) as u8;
22258 q[3] = 32;
22259 q[5] = 1;
22260 core::ptr::copy_nonoverlapping(dname as *const u8, q.as_mut_ptr().add(13), l);
22261 let mut i = 13;
22262 while q[i] != 0 {
22263 let mut j = i;
22264 while q[j] != 0 && q[j] != b'.' { j += 1; }
22265 if j - i - 1 > 62 { return -1; }
22266 q[i - 1] = (j - i) as u8;
22267 i = j + 1;
22268 }
22269 q[i + 1] = type_ as u8;
22270 q[i + 3] = class as u8;
22271 let mut ts = timespec { tv_sec: 0, tv_nsec: 0 };
22272 let _ = clock_gettime(CLOCK_REALTIME, &mut ts);
22273 let id = (((ts.tv_nsec as u64) + (ts.tv_nsec as u64) / 65536) & 0xffff) as u16;
22274 q[0] = (id >> 8) as u8;
22275 q[1] = id as u8;
22276 core::ptr::copy_nonoverlapping(q.as_ptr(), buf, n);
22277 n as c_int
22278}
22279
22280unsafe fn res_send_inner(msg: *const u8, msglen: c_int, answer: *mut u8, anslen: c_int) -> c_int {
22281 if msg.is_null() || answer.is_null() || msglen < 12 || anslen < 12 { return -1; }
22282 if !RESOLV_INITIALIZED { let _ = resolv_parse_config(); }
22283 if NS_COUNT == 0 {
22284 h_errno = TRY_AGAIN;
22285 return -1;
22286 }
22287 for n in 0..NS_COUNT {
22288 let fd = crate::socket(AF_INET, SOCK_DGRAM, 0);
22289 if fd < 0 { continue; }
22290 let sa = SockAddrIn {
22291 sin_family: AF_INET as u16,
22292 sin_port: 53u16.to_be(),
22293 sin_addr: NS_ADDRS[n],
22294 sin_zero: [0; 8],
22295 };
22296 let sent = crate::sendto(fd, msg as *const c_void, msglen as usize, 0, &sa as *const SockAddrIn as *const crate::sockaddr, 16);
22297 if sent != msglen as isize {
22298 crate::close(fd);
22299 continue;
22300 }
22301 let mut pfd = PollFd { fd, events: 1, revents: 0 };
22302 let pr = crate::poll(&mut pfd as *mut PollFd as *mut c_void, 1, 5000);
22303 if pr <= 0 {
22304 crate::close(fd);
22305 continue;
22306 }
22307 let r = crate::recvfrom(fd, answer as *mut c_void, anslen as usize, 0, core::ptr::null_mut(), core::ptr::null_mut());
22308 crate::close(fd);
22309 if r >= 12 {
22310 let id_ok = *answer == *msg && *answer.add(1) == *msg.add(1);
22311 let qr = (*answer.add(2) & 0x80) != 0;
22312 if id_ok && qr {
22313 return r as c_int;
22314 }
22315 }
22316 }
22317 h_errno = TRY_AGAIN;
22318 -1
22319}
22320
22321#[no_mangle]
22322pub unsafe extern "C" fn res_send(msg: *const u8, msglen: c_int, answer: *mut u8, anslen: c_int) -> c_int {
22323 if anslen < 512 {
22324 let mut buf = [0u8; 512];
22325 let r = res_send_inner(msg, msglen, buf.as_mut_ptr(), 512);
22326 if r >= 0 {
22327 let copy = core::cmp::min(r, anslen) as usize;
22328 if copy > 0 { core::ptr::copy_nonoverlapping(buf.as_ptr(), answer, copy); }
22329 }
22330 return r;
22331 }
22332 res_send_inner(msg, msglen, answer, anslen)
22333}
22334
22335#[no_mangle]
22336pub unsafe extern "C" fn res_query(
22337 dname: *const c_char,
22338 class: c_int,
22339 type_: c_int,
22340 answer: *mut u8,
22341 anslen: c_int,
22342) -> c_int {
22343 let mut q = [0u8; 280];
22344 let ql = res_mkquery(0, dname, class, type_, core::ptr::null(), 0, core::ptr::null(), q.as_mut_ptr(), q.len() as c_int);
22345 if ql < 0 { return ql; }
22346 let r = res_send(q.as_ptr(), ql, answer, anslen);
22347 if r < 12 {
22348 h_errno = TRY_AGAIN;
22349 return -1;
22350 }
22351 let rcode = answer.add(3).read() & 0x0f;
22352 if rcode == 3 {
22353 h_errno = HOST_NOT_FOUND;
22354 return -1;
22355 }
22356 if rcode == 0 && *answer.add(6) == 0 && *answer.add(7) == 0 {
22357 h_errno = NO_DATA;
22358 return -1;
22359 }
22360 if rcode != 0 {
22361 h_errno = NO_RECOVERY;
22362 return -1;
22363 }
22364 r
22365}
22366
22367#[no_mangle]
22368pub unsafe extern "C" fn res_querydomain(
22369 name: *const c_char,
22370 domain: *const c_char,
22371 class: c_int,
22372 type_: c_int,
22373 answer: *mut u8,
22374 anslen: c_int,
22375) -> c_int {
22376 if domain.is_null() || *domain == 0 { return res_query(name, class, type_, answer, anslen); }
22377 let mut buf = [0u8; 512];
22378 let nl = crate::strlen(name);
22379 let dl = crate::strlen(domain);
22380 if nl + 1 + dl >= buf.len() { return -1; }
22381 core::ptr::copy_nonoverlapping(name, buf.as_mut_ptr() as *mut c_char, nl);
22382 buf[nl] = b'.';
22383 core::ptr::copy_nonoverlapping(domain, buf.as_mut_ptr().add(nl + 1) as *mut c_char, dl);
22384 buf[nl + 1 + dl] = 0;
22385 res_query(buf.as_ptr() as *const c_char, class, type_, answer, anslen)
22386}
22387
22388#[no_mangle]
22389pub unsafe extern "C" fn res_search(
22390 name: *const c_char,
22391 class: c_int,
22392 type_: c_int,
22393 answer: *mut u8,
22394 anslen: c_int,
22395) -> c_int {
22396 if name.is_null() { return -1; }
22397 if !RESOLV_INITIALIZED { let _ = resolv_parse_config(); }
22398 let len = crate::strlen(name);
22399 let mut dots = 0;
22400 for i in 0..len {
22401 if *name.add(i) == b'.' as c_char { dots += 1; }
22402 }
22403 let trailing_dot = len > 0 && *name.add(len - 1) == b'.' as c_char;
22404 if trailing_dot || dots >= 1 {
22405 let r = res_query(name, class, type_, answer, anslen);
22406 if r >= 0 { return r; }
22407 if trailing_dot { return -1; }
22408 }
22409 for i in 0..SEARCH_COUNT {
22410 let dom = SEARCH_DOMAINS[i].as_ptr() as *const c_char;
22411 let r = res_querydomain(name, dom, class, type_, answer, anslen);
22412 if r >= 0 { return r; }
22413 if h_errno != HOST_NOT_FOUND && h_errno != NO_DATA { return -1; }
22414 }
22415 if dots == 0 {
22416 return res_query(name, class, type_, answer, anslen);
22417 }
22418 -1
22419}
22420
22421#[repr(C)]
22426pub struct HostEnt {
22427 pub h_name: *mut c_char,
22428 pub h_aliases: *mut *mut c_char,
22429 pub h_addrtype: c_int,
22430 pub h_length: c_int,
22431 pub h_addr_list: *mut *mut c_char,
22432}
22433
22434#[repr(C)]
22435pub struct AddrInfo {
22436 pub ai_flags: c_int,
22437 pub ai_family: c_int,
22438 pub ai_socktype: c_int,
22439 pub ai_protocol: c_int,
22440 pub ai_addrlen: u32,
22441 pub ai_addr: *mut c_void,
22442 pub ai_canonname: *mut c_char,
22443 pub ai_next: *mut AddrInfo,
22444}
22445
22446static mut HOST_ENT: HostEnt = HostEnt {
22447 h_name: core::ptr::null_mut(),
22448 h_aliases: core::ptr::null_mut(),
22449 h_addrtype: 0,
22450 h_length: 0,
22451 h_addr_list: core::ptr::null_mut(),
22452};
22453static mut HOST_NAME: [c_char; 256] = [0; 256];
22454static mut HOST_ALIASES: [*mut c_char; 1] = [core::ptr::null_mut()];
22455static mut HOST_ADDR: [u8; 16] = [0; 16];
22456static mut HOST_ADDR_PTRS: [*mut c_char; 2] = [core::ptr::null_mut(); 2];
22457
22458unsafe fn dns_skip_name(p: *const u8, end: *const u8) -> *const u8 {
22459 let mut q = p;
22460 while q < end {
22461 let c = *q;
22462 if c == 0 { return q.add(1); }
22463 if c & 0xc0 == 0xc0 { return q.add(2); }
22464 q = q.add(1 + c as usize);
22465 }
22466 end
22467}
22468
22469unsafe fn dns_read_u16(p: *const u8) -> u16 {
22470 ((*p as u16) << 8) | *p.add(1) as u16
22471}
22472
22473unsafe fn dns_expand_name(p: *const u8, msg: *const u8, out: *mut c_char, outlen: usize) -> bool {
22474 let mut q = p;
22475 let mut o = 0usize;
22476 let mut jumps = 0;
22477 loop {
22478 let c = *q;
22479 if c == 0 {
22480 if o < outlen { *out.add(o) = 0; }
22481 return true;
22482 }
22483 if c & 0xc0 == 0xc0 {
22484 let off = (((c & 0x3f) as usize) << 8) | *q.add(1) as usize;
22485 q = msg.add(off);
22486 jumps += 1;
22487 if jumps > 16 { return false; }
22488 continue;
22489 }
22490 let l = c as usize;
22491 if l > 63 { return false; }
22492 if o + l + 1 >= outlen { return false; }
22493 core::ptr::copy_nonoverlapping(q.add(1), out.add(o) as *mut u8, l);
22494 o += l;
22495 *out.add(o) = b'.' as c_char;
22496 o += 1;
22497 q = q.add(1 + l);
22498 }
22499}
22500
22501unsafe fn host_from_answer(answer: *const u8, len: c_int, af: c_int) -> *mut HostEnt {
22502 if len < 12 { return core::ptr::null_mut(); }
22503 let end = answer.add(len as usize);
22504 let qd = dns_read_u16(answer.add(4)) as usize;
22505 let an = dns_read_u16(answer.add(6)) as usize;
22506 let mut p = answer.add(12);
22507 for _ in 0..qd {
22508 p = dns_skip_name(p, end);
22509 p = p.add(4);
22510 }
22511 let want_type: u16 = if af == AF_INET6 { 28 } else { 1 };
22512 let want_len = if af == AF_INET6 { 16 } else { 4 };
22513 for _ in 0..an {
22514 p = dns_skip_name(p, end);
22515 if p.add(10) > end { break; }
22516 let typ = dns_read_u16(p);
22517 let class = dns_read_u16(p.add(2));
22518 let rdlen = dns_read_u16(p.add(8)) as usize;
22519 let rdata = p.add(10);
22520 if rdata.add(rdlen) > end { break; }
22521 if typ == want_type && class == 1 && rdlen == want_len {
22522 core::ptr::copy_nonoverlapping(rdata, HOST_ADDR.as_mut_ptr(), want_len);
22523 HOST_ENT.h_addrtype = af;
22524 HOST_ENT.h_length = want_len as c_int;
22525 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
22526 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
22527 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
22528 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
22529 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
22530 h_errno = 0;
22531 return &raw mut HOST_ENT;
22532 }
22533 p = rdata.add(rdlen);
22534 }
22535 core::ptr::null_mut()
22536}
22537
22538#[no_mangle]
22539pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *mut HostEnt {
22540 gethostbyname2(name, AF_INET)
22541}
22542
22543#[no_mangle]
22544pub unsafe extern "C" fn gethostbyname2(name: *const c_char, af: c_int) -> *mut HostEnt {
22545 if name.is_null() { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
22546 let mut addr = [0u8; 16];
22547 let addrlen = if af == AF_INET6 { 16 } else { 4 };
22548 if inet_pton(af, name, addr.as_mut_ptr() as *mut c_void) == 1 {
22549 core::ptr::copy_nonoverlapping(addr.as_ptr(), HOST_ADDR.as_mut_ptr(), addrlen);
22550 let n = crate::strlen(name);
22551 let l = core::cmp::min(n, 255);
22552 core::ptr::copy_nonoverlapping(name, HOST_NAME.as_mut_ptr(), l);
22553 HOST_NAME[l] = 0;
22554 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
22555 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
22556 HOST_ENT.h_addrtype = af;
22557 HOST_ENT.h_length = addrlen as c_int;
22558 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
22559 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
22560 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
22561 h_errno = 0;
22562 return &raw mut HOST_ENT;
22563 }
22564 let mut answer = [0u8; 512];
22565 let qtype = if af == AF_INET6 { 28 } else { 1 };
22566 let r = res_query(name, 1, qtype, answer.as_mut_ptr(), answer.len() as c_int);
22567 if r < 0 {
22568 if h_errno == 0 { h_errno = TRY_AGAIN; }
22569 return core::ptr::null_mut();
22570 }
22571 let ent = host_from_answer(answer.as_ptr(), r, af);
22572 if !ent.is_null() {
22573 let n = crate::strlen(name);
22574 let l = core::cmp::min(n, 255);
22575 core::ptr::copy_nonoverlapping(name, HOST_NAME.as_mut_ptr(), l);
22576 HOST_NAME[l] = 0;
22577 } else {
22578 h_errno = HOST_NOT_FOUND;
22579 }
22580 ent
22581}
22582
22583#[no_mangle]
22584pub unsafe extern "C" fn gethostbyaddr(addr: *const c_void, len: u32, type_: c_int) -> *mut HostEnt {
22585 if addr.is_null() || type_ != AF_INET || len != 4 { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
22586 let a = addr as *const u8;
22587 let mut name = [0u8; 128];
22588 let mut pos = 0;
22589 for i in 0..4 {
22590 let v = *a.add(3 - i) as u32;
22591 if v >= 100 { name[pos] = b'0' + (v / 100) as u8; pos += 1; }
22592 if v >= 10 { name[pos] = b'0' + ((v / 10) % 10) as u8; pos += 1; }
22593 name[pos] = b'0' + (v % 10) as u8; pos += 1;
22594 name[pos] = b'.'; pos += 1;
22595 }
22596 let suffix = b"in-addr.arpa";
22597 for &c in suffix { name[pos] = c; pos += 1; }
22598 name[pos] = 0;
22599 let mut answer = [0u8; 512];
22600 let r = res_query(name.as_ptr() as *const c_char, 1, 12, answer.as_mut_ptr(), answer.len() as c_int);
22601 if r < 12 { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
22602 let end = answer.as_ptr().add(r as usize);
22603 let qd = dns_read_u16(answer.as_ptr().add(4)) as usize;
22604 let an = dns_read_u16(answer.as_ptr().add(6)) as usize;
22605 let mut p = answer.as_ptr().add(12);
22606 for _ in 0..qd { p = dns_skip_name(p, end); p = p.add(4); }
22607 for _ in 0..an {
22608 p = dns_skip_name(p, end);
22609 if p.add(10) > end { break; }
22610 let typ = dns_read_u16(p);
22611 let rdlen = dns_read_u16(p.add(8)) as usize;
22612 let rdata = p.add(10);
22613 if typ == 12 && dns_expand_name(rdata, answer.as_ptr(), HOST_NAME.as_mut_ptr(), HOST_NAME.len()) {
22614 let mut o = crate::strlen(HOST_NAME.as_ptr());
22615 if o > 0 && HOST_NAME[o - 1] == b'.' as c_char { o -= 1; }
22616 HOST_NAME[o] = 0;
22617 core::ptr::copy_nonoverlapping(a, HOST_ADDR.as_mut_ptr(), 4);
22618 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
22619 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
22620 HOST_ENT.h_addrtype = AF_INET;
22621 HOST_ENT.h_length = 4;
22622 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
22623 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
22624 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
22625 h_errno = 0;
22626 return &raw mut HOST_ENT;
22627 }
22628 p = rdata.add(rdlen);
22629 }
22630 h_errno = HOST_NOT_FOUND;
22631 core::ptr::null_mut()
22632}
22633
22634#[inline]
22639fn sysno(x86_64: i64, generic: i64) -> i64 {
22640 if cfg!(target_arch = "x86_64") { x86_64 } else { generic }
22641}
22642
22643#[no_mangle]
22644pub unsafe extern "C" fn settimeofday(tv: *const c_void, tz: *const c_void) -> c_int {
22645 let r = <Arch as Syscalls>::syscall2(sysno(164, 170), tv as i64, tz as i64);
22646 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22647}
22648
22649#[no_mangle]
22650pub unsafe extern "C" fn stime(t: *const i64) -> c_int {
22651 if t.is_null() { ERRNO!() = EINVAL; return -1; }
22652 let tv = timeval { tv_sec: *t, tv_usec: 0 };
22653 settimeofday(&tv as *const timeval as *const c_void, core::ptr::null())
22654}
22655
22656#[no_mangle]
22657pub unsafe extern "C" fn times(buf: *mut c_void) -> c_long {
22658 let r = <Arch as Syscalls>::syscall1(sysno(100, 153), buf as i64);
22659 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_long }
22660}
22661
22662#[no_mangle]
22663pub unsafe extern "C" fn splice(fd_in: c_int, off_in: *mut i64, fd_out: c_int, off_out: *mut i64, len: usize, flags: u32) -> isize {
22664 let r = <Arch as Syscalls>::syscall6(sysno(275, 76), fd_in as i64, off_in as i64, fd_out as i64, off_out as i64, len as i64, flags as i64);
22665 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22666}
22667
22668#[no_mangle]
22669pub unsafe extern "C" fn tee(fd_in: c_int, fd_out: c_int, len: usize, flags: u32) -> isize {
22670 let r = <Arch as Syscalls>::syscall4(sysno(276, 77), fd_in as i64, fd_out as i64, len as i64, flags as i64);
22671 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22672}
22673
22674#[no_mangle]
22675pub unsafe extern "C" fn statx(dirfd: c_int, path: *const c_char, flags: c_int, mask: u32, buf: *mut c_void) -> c_int {
22676 let r = <Arch as Syscalls>::syscall5(sysno(332, 291), dirfd as i64, path as i64, flags as i64, mask as i64, buf as i64);
22677 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22678}
22679
22680#[no_mangle]
22681pub unsafe extern "C" fn setns(fd: c_int, nstype: c_int) -> c_int {
22682 let r = <Arch as Syscalls>::syscall2(SYS_SETNS, fd as i64, nstype as i64);
22683 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22684}
22685
22686#[no_mangle]
22687pub unsafe extern "C" fn setfsuid(uid: u32) -> c_int {
22688 <Arch as Syscalls>::syscall1(sysno(122, 151), uid as i64) as c_int
22689}
22690
22691#[no_mangle]
22692pub unsafe extern "C" fn setfsgid(gid: u32) -> c_int {
22693 <Arch as Syscalls>::syscall1(sysno(123, 152), gid as i64) as c_int
22694}
22695
22696#[no_mangle]
22697pub unsafe extern "C" fn setregid(rgid: u32, egid: u32) -> c_int {
22698 let r = <Arch as Syscalls>::syscall2(sysno(114, 143), rgid as i64, egid as i64);
22699 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22700}
22701
22702#[no_mangle]
22703pub unsafe extern "C" fn process_vm_readv(pid: c_int, local: *const c_void, liovcnt: usize, remote: *const c_void, riovcnt: usize, flags: u64) -> isize {
22704 let r = <Arch as Syscalls>::syscall6(sysno(310, 270), pid as i64, local as i64, liovcnt as i64, remote as i64, riovcnt as i64, flags as i64);
22705 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22706}
22707
22708#[no_mangle]
22709pub unsafe extern "C" fn process_vm_writev(pid: c_int, local: *const c_void, liovcnt: usize, remote: *const c_void, riovcnt: usize, flags: u64) -> isize {
22710 let r = <Arch as Syscalls>::syscall6(sysno(311, 271), pid as i64, local as i64, liovcnt as i64, remote as i64, riovcnt as i64, flags as i64);
22711 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22712}
22713
22714#[no_mangle]
22715pub unsafe extern "C" fn tcgetwinsize(fd: c_int, ws: *mut c_void) -> c_int {
22716 if fd < 0 || ws.is_null() { ERRNO!() = EINVAL; return -1; }
22717 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5413, ws as i64);
22718 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22719}
22720
22721#[no_mangle]
22722pub unsafe extern "C" fn tcsetwinsize(fd: c_int, ws: *const c_void) -> c_int {
22723 if fd < 0 || ws.is_null() { ERRNO!() = EINVAL; return -1; }
22724 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5414, ws as i64);
22725 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22726}
22727
22728#[no_mangle]
22729pub unsafe extern "C" fn sockatmark(fd: c_int) -> c_int {
22730 let mut at: c_int = 0;
22731 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x8905, &mut at as *mut c_int as i64);
22732 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { at }
22733}
22734
22735#[no_mangle]
22736pub unsafe extern "C" fn isastream(fd: c_int) -> c_int {
22737 let mut buf = [0u8; 64];
22738 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5401, buf.as_mut_ptr() as i64);
22739 if r < 0 { ERRNO!() = (-r) as c_int; 0 } else { 1 }
22740}
22741
22742#[no_mangle]
22743pub unsafe extern "C" fn posix_madvise(addr: *mut c_void, len: usize, advice: c_int) -> c_int {
22744 madvise(addr as *mut u8, len, advice)
22745}
22746
22747#[no_mangle]
22748pub unsafe extern "C" fn secure_getenv(name: *const c_char) -> *mut c_char {
22749 if getauxval(23) != 0 { return core::ptr::null_mut(); }
22750 getenv(name)
22751}
22752
22753#[no_mangle]
22754pub unsafe extern "C" fn sigandset(dest: *mut c_ulong, left: *const c_ulong, right: *const c_ulong) -> c_int {
22755 if dest.is_null() || left.is_null() || right.is_null() { return -1; }
22756 *dest = *left & *right;
22757 0
22758}
22759
22760#[no_mangle]
22761pub unsafe extern "C" fn sigorset(dest: *mut c_ulong, left: *const c_ulong, right: *const c_ulong) -> c_int {
22762 if dest.is_null() || left.is_null() || right.is_null() { return -1; }
22763 *dest = *left | *right;
22764 0
22765}
22766
22767#[no_mangle]
22768pub unsafe extern "C" fn sigisemptyset(set: *const c_ulong) -> c_int {
22769 if set.is_null() { return 1; }
22770 (*set == 0) as c_int
22771}
22772
22773#[no_mangle]
22774pub unsafe extern "C" fn sighold(sig: c_int) -> c_int {
22775 let set: c_ulong = 1u64 << (sig - 1) as u32;
22776 sigprocmask(0, &set, core::ptr::null_mut());
22777 0
22778}
22779
22780#[no_mangle]
22781pub unsafe extern "C" fn sigignore(sig: c_int) -> c_int {
22782 let _ = signal(sig, 1);
22783 0
22784}
22785
22786#[no_mangle]
22787pub unsafe extern "C" fn sigrelse(sig: c_int) -> c_int {
22788 let set: c_ulong = 1u64 << (sig - 1) as u32;
22789 sigprocmask(1, &set, core::ptr::null_mut());
22790 0
22791}
22792
22793#[no_mangle]
22794pub unsafe extern "C" fn siginterrupt(sig: c_int, flag: c_int) -> c_int {
22795 let mut sa: sigaction = core::mem::zeroed();
22796 if sigaction(sig, core::ptr::null(), &mut sa) != 0 { return -1; }
22797 if flag != 0 { sa.sa_flags &= !(SA_RESTART as c_int); } else { sa.sa_flags |= SA_RESTART as c_int; }
22798 sigaction(sig, &sa, core::ptr::null_mut())
22799}
22800
22801#[no_mangle]
22802pub unsafe extern "C" fn sigpause(sig: c_int) -> c_int {
22803 let set: c_ulong = 1u64 << (sig - 1) as u32;
22804 sigsuspend(&set)
22805}
22806
22807#[no_mangle]
22808pub unsafe extern "C" fn semtimedop(semid: c_int, sops: *mut c_void, nsops: usize, timeout: *const timespec) -> c_int {
22809 let r = <Arch as Syscalls>::syscall4(sysno(220, 192), semid as i64, sops as i64, nsops as i64, timeout as i64);
22810 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
22811}
22812
22813#[no_mangle]
22814pub unsafe extern "C" fn wait3(status: *mut c_int, options: c_int, rusage: *mut c_void) -> i32 {
22815 wait4(-1, status, options, rusage) as i32
22816}
22817
22818#[no_mangle]
22819pub unsafe extern "C" fn tempnam(dir: *const c_char, pfx: *const c_char) -> *mut c_char {
22820 let mut path = [0 as c_char; 256];
22821 let mut i = 0;
22822 if !dir.is_null() {
22823 while *dir.add(i) != 0 && i < 200 { path[i] = *dir.add(i); i += 1; }
22824 if i > 0 && path[i-1] != b'/' as c_char { path[i] = b'/' as c_char; i += 1; }
22825 } else {
22826 for &c in b"/tmp/" { path[i] = c as c_char; i += 1; }
22827 }
22828 if !pfx.is_null() {
22829 let mut j = 0;
22830 while *pfx.add(j) != 0 && i < 220 { path[i] = *pfx.add(j); i += 1; j += 1; }
22831 }
22832 for &c in b"XXXXXX" { path[i] = c as c_char; i += 1; }
22833 path[i] = 0;
22834 let fd = mkstemp(path.as_mut_ptr());
22835 if fd < 0 { return core::ptr::null_mut(); }
22836 close(fd);
22837 unlink(path.as_ptr());
22838 let n = strlen(path.as_ptr());
22839 let out = malloc(n + 1) as *mut c_char;
22840 if out.is_null() { return core::ptr::null_mut(); }
22841 core::ptr::copy_nonoverlapping(path.as_ptr(), out, n + 1);
22842 out
22843}
22844
22845#[no_mangle]
22846pub unsafe extern "C" fn putwc(c: u32, f: *mut c_void) -> u32 {
22847 fputwc(c as c_int, f as *mut FILE) as u32
22848}
22849
22850#[no_mangle]
22851pub unsafe extern "C" fn __uflow(f: *mut c_void) -> c_int {
22852 fgetc(f as *mut FILE)
22853}
22854
22855#[no_mangle]
22856pub unsafe extern "C" fn __xmknod(_ver: c_int, path: *const c_char, mode: c_uint, dev: u64) -> c_int {
22857 mknod(path, mode, dev)
22858}
22859
22860#[no_mangle]
22861pub unsafe extern "C" fn __xmknodat(_ver: c_int, dirfd: c_int, path: *const c_char, mode: c_uint, dev: u64) -> c_int {
22862 mknodat(dirfd, path, mode, dev)
22863}
22864
22865#[no_mangle]
22866pub unsafe extern "C" fn name_to_handle_at(dirfd: c_int, path: *const c_char, handle: *mut c_void, mount_id: *mut c_int, flags: c_int) -> c_int {
22867 let r = <Arch as Syscalls>::syscall5(sysno(303, 264), dirfd as i64, path as i64, handle as i64, mount_id as i64, flags as i64);
22868 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22869}
22870
22871#[no_mangle]
22872pub unsafe extern "C" fn open_by_handle_at(mount_fd: c_int, handle: *mut c_void, flags: c_int) -> c_int {
22873 let r = <Arch as Syscalls>::syscall3(sysno(304, 265), mount_fd as i64, handle as i64, flags as i64);
22874 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
22875}
22876
22877#[no_mangle]
22878pub unsafe extern "C" fn dn_skipname(comp: *const u8, eom: *const u8) -> c_int {
22879 let p = dns_skip_name(comp, eom);
22880 if p <= eom { (p as isize - comp as isize) as c_int } else { -1 }
22881}
22882
22883#[no_mangle]
22884pub unsafe extern "C" fn dn_comp(exp: *const c_char, dst: *mut u8, dstsiz: c_int, _dnptrs: *mut *mut u8, _lastdnptr: *mut *mut u8) -> c_int {
22885 if exp.is_null() || dst.is_null() || dstsiz <= 0 { return -1; }
22886 let mut o = 0usize;
22887 let mut p = exp;
22888 loop {
22889 let start = p;
22890 while *p != 0 && *p != b'.' as c_char { p = p.add(1); }
22891 let l = p as usize - start as usize;
22892 if l > 63 || o + l + 2 > dstsiz as usize { return -1; }
22893 *dst.add(o) = l as u8; o += 1;
22894 core::ptr::copy_nonoverlapping(start as *const u8, dst.add(o), l);
22895 o += l;
22896 if *p == 0 { break; }
22897 p = p.add(1);
22898 }
22899 if o + 1 > dstsiz as usize { return -1; }
22900 *dst.add(o) = 0;
22901 (o + 1) as c_int
22902}
22903
22904#[repr(C)]
22909#[derive(Copy, Clone)]
22910pub struct Spwd {
22911 pub sp_namp: *mut c_char,
22912 pub sp_pwdp: *mut c_char,
22913 pub sp_lstchg: c_long,
22914 pub sp_min: c_long,
22915 pub sp_max: c_long,
22916 pub sp_warn: c_long,
22917 pub sp_inact: c_long,
22918 pub sp_expire: c_long,
22919 pub sp_flag: c_ulong,
22920}
22921
22922static mut SPWD_ENT: Spwd = Spwd {
22923 sp_namp: core::ptr::null_mut(), sp_pwdp: core::ptr::null_mut(),
22924 sp_lstchg: 0, sp_min: 0, sp_max: 0, sp_warn: 0, sp_inact: 0,
22925 sp_expire: 0, sp_flag: 0,
22926};
22927static mut SPWD_BUF: [c_char; 1024] = [0; 1024];
22928static mut SPWD_FILE: *mut FILE = core::ptr::null_mut();
22929
22930unsafe fn parse_spwd(line: *const c_char, ent: *mut Spwd, buf: *mut c_char, buflen: usize) -> bool {
22931 let mut src = line;
22932 let mut o = 0usize;
22933 let mut fields: [*mut c_char; 9] = [core::ptr::null_mut(); 9];
22934 let mut n = 0usize;
22935 while n < 9 {
22936 let start = o;
22937 while *src != 0 && *src != b':' as c_char {
22938 if o + 1 >= buflen { return false; }
22939 *buf.add(o) = *src;
22940 o += 1;
22941 src = src.add(1);
22942 }
22943 *buf.add(o) = 0;
22944 o += 1;
22945 fields[n] = buf.add(start);
22946 n += 1;
22947 if *src == 0 { break; }
22948 src = src.add(1);
22949 }
22950 if n < 9 { return false; }
22951 (*ent).sp_namp = fields[0];
22952 (*ent).sp_pwdp = fields[1];
22953 (*ent).sp_lstchg = crate::strtol(fields[2], core::ptr::null_mut(), 10) as c_long;
22954 (*ent).sp_min = crate::strtol(fields[3], core::ptr::null_mut(), 10) as c_long;
22955 (*ent).sp_max = crate::strtol(fields[4], core::ptr::null_mut(), 10) as c_long;
22956 (*ent).sp_warn = crate::strtol(fields[5], core::ptr::null_mut(), 10) as c_long;
22957 (*ent).sp_inact = crate::strtol(fields[6], core::ptr::null_mut(), 10) as c_long;
22958 (*ent).sp_expire = crate::strtol(fields[7], core::ptr::null_mut(), 10) as c_long;
22959 (*ent).sp_flag = crate::strtoul(fields[8], core::ptr::null_mut(), 10) as c_ulong;
22960 true
22961}
22962
22963#[no_mangle]
22964pub unsafe extern "C" fn setspent() {
22965 endspent();
22966 SPWD_FILE = crate::fopen(b"/etc/shadow\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
22967}
22968
22969#[no_mangle]
22970pub unsafe extern "C" fn endspent() {
22971 if !SPWD_FILE.is_null() { crate::fclose(SPWD_FILE); SPWD_FILE = core::ptr::null_mut(); }
22972}
22973
22974#[no_mangle]
22975pub unsafe extern "C" fn getspent() -> *mut Spwd {
22976 if SPWD_FILE.is_null() { setspent(); if SPWD_FILE.is_null() { return core::ptr::null_mut(); } }
22977 let mut line = [0 as c_char; 1024];
22978 loop {
22979 if crate::fgets(line.as_mut_ptr(), 1024, SPWD_FILE).is_null() { return core::ptr::null_mut(); }
22980 if parse_spwd(line.as_ptr(), &raw mut SPWD_ENT, SPWD_BUF.as_mut_ptr(), SPWD_BUF.len()) {
22981 return &raw mut SPWD_ENT;
22982 }
22983 }
22984}
22985
22986#[no_mangle]
22987pub unsafe extern "C" fn fgetspent(f: *mut FILE) -> *mut Spwd {
22988 if f.is_null() { return core::ptr::null_mut(); }
22989 let mut line = [0 as c_char; 1024];
22990 loop {
22991 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
22992 if parse_spwd(line.as_ptr(), &raw mut SPWD_ENT, SPWD_BUF.as_mut_ptr(), SPWD_BUF.len()) {
22993 return &raw mut SPWD_ENT;
22994 }
22995 }
22996}
22997
22998#[no_mangle]
22999pub unsafe extern "C" fn getspnam(name: *const c_char) -> *mut Spwd {
23000 if name.is_null() { return core::ptr::null_mut(); }
23001 setspent();
23002 loop {
23003 let sp = getspent();
23004 if sp.is_null() { break; }
23005 if crate::strcmp((*sp).sp_namp as *const u8, name as *const u8) == 0 { endspent(); return sp; }
23006 }
23007 endspent();
23008 core::ptr::null_mut()
23009}
23010
23011#[no_mangle]
23012pub unsafe extern "C" fn getspnam_r(name: *const c_char, sp: *mut Spwd, _buf: *mut c_char, _buflen: usize, result: *mut *mut Spwd) -> c_int {
23013 if result.is_null() { return EINVAL; }
23014 let p = getspnam(name);
23015 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *sp = *p; *result = sp; 0 }
23016}
23017
23018#[no_mangle]
23019pub unsafe extern "C" fn putspent(sp: *const Spwd, f: *mut FILE) -> c_int {
23020 if sp.is_null() || f.is_null() { return -1; }
23021 crate::fprintf(f, b"%s:%s:%ld:%ld:%ld:%ld:%ld:%ld:%lu\\n\0".as_ptr() as *const c_char,
23022 (*sp).sp_namp, (*sp).sp_pwdp, (*sp).sp_lstchg, (*sp).sp_min, (*sp).sp_max,
23023 (*sp).sp_warn, (*sp).sp_inact, (*sp).sp_expire, (*sp).sp_flag)
23024}
23025
23026#[no_mangle]
23027pub unsafe extern "C" fn getgrouplist(user: *const c_char, group: u32, groups: *mut u32, ngroups: *mut i32) -> c_int {
23028 if user.is_null() || groups.is_null() || ngroups.is_null() { return -1; }
23029 let max = *ngroups as usize;
23030 let mut n = 0usize;
23031 if n < max { *groups.add(n) = group; }
23032 n += 1;
23033 setgrent();
23034 loop {
23035 let g = getgrent();
23036 if g.is_null() { break; }
23037 if (*g).gr_gid == group { continue; }
23038 let mut found = false;
23039 let mut i = 0;
23040 while !(*(*g).gr_mem.add(i)).is_null() {
23041 if crate::strcmp(*(*g).gr_mem.add(i) as *const u8, user as *const u8) == 0 {
23042 found = true;
23043 break;
23044 }
23045 i += 1;
23046 }
23047 if found {
23048 if n < max { *groups.add(n) = (*g).gr_gid; }
23049 n += 1;
23050 }
23051 }
23052 endgrent();
23053 if n > max { *ngroups = n as i32; return -1; }
23054 *ngroups = n as i32;
23055 n as c_int
23056}