1#![cfg_attr(not(test), no_std)]
5#![feature(c_variadic)]
6#![feature(linkage)]
7#![cfg_attr(target_arch = "aarch64", feature(f128))]
8#![cfg_attr(target_arch = "riscv64", feature(f128))]
9#![allow(dead_code, non_camel_case_types)]
10#![allow(static_mut_refs)]
14#![allow(improper_ctypes_definitions)]
17
18use core::ffi::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ulonglong, c_void, VaList};
19use core::ptr::null_mut;
20use core::sync::atomic::{AtomicI32, AtomicPtr, AtomicUsize, Ordering};
21
22macro_rules! ERRNO {
23 () => { *errno_ptr() };
24}
25
26include!("encoding_tables.rs");
27include!("math_helpers.rs");
28include!("math_bitmanip.rs");
29include!("math_sqrtfmod.rs");
30include!("math_trig.rs");
31include!("math_exp.rs");
32include!("math_erf.rs");
33include!("math_lgamma.rs");
34include!("math_tgamma.rs");
35include!("math_bessel.rs");
36include!("alloc.rs");
37include!("math_log.rs");
38include!("math_pow.rs");
39include!("math_hypot.rs");
40include!("math_hyperbolic.rs");
41include!("math_invtrig.rs");
42include!("math_lrint.rs");
43include!("math_long_double.rs");
44include!("string_fast.rs");
45include!("vdso.rs");
46include!("arch.rs");
47
48const EILSEQ: c_int = 84;
53const EINVAL: c_int = 22;
54const EFAULT: c_int = 14;
55const E2BIG: c_int = 7;
56
57const LC_CTYPE: c_int = 0;
58const LC_NUMERIC: c_int = 1;
59const LC_TIME: c_int = 2;
60const LC_COLLATE: c_int = 3;
61const LC_MONETARY: c_int = 4;
62const LC_MESSAGES: c_int = 5;
63const LC_ALL: c_int = 6;
64const ENOMEM: c_int = 12;
65const EINTR: c_int = 4;
66const EPERM: c_int = 1;
67const EAGAIN: c_int = 11;
68const EBUSY: c_int = 16;
69const EDEADLK: c_int = 35;
70const ETIMEDOUT: c_int = 110;
71const ECANCELED: c_int = 125;
72const EOVERFLOW: c_int = 75;
73const EOWNERDEAD: c_int = 130;
74const ENOTRECOVERABLE: c_int = 131;
75
76static mut ERRNO_FALLBACK: c_int = 0;
82static ERRNO_TLS_ACTIVE: AtomicUsize = AtomicUsize::new(0);
83const ERRNO_TCB_OFFSET: usize = 0x30;
84
85#[inline]
86unsafe fn errno_ptr() -> *mut c_int {
87 if ERRNO_TLS_ACTIVE.load(Ordering::Relaxed) == 0 {
88 return core::ptr::addr_of_mut!(ERRNO_FALLBACK);
89 }
90 #[cfg(target_arch = "x86_64")]
91 let tp: usize = {
92 let tp: usize;
93 core::arch::asm!("mov {}, fs:[0]", out(reg) tp, options(nostack, preserves_flags));
94 tp
95 };
96 #[cfg(target_arch = "aarch64")]
97 let tp: usize = {
98 let tp: usize;
99 core::arch::asm!("mrs {}, tpidr_el0", out(reg) tp, options(nostack, preserves_flags));
100 tp
101 };
102 #[cfg(target_arch = "riscv64")]
103 let tp: usize = {
104 let tp: usize;
105 core::arch::asm!("mv {}, tp", out(reg) tp, options(nostack, preserves_flags));
106 tp
107 };
108 #[cfg(target_arch = "x86_64")]
109 let tcb = tp;
110 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
111 let tcb = tp - 256;
112 (tcb + ERRNO_TCB_OFFSET) as *mut c_int
113}
114
115unsafe fn errno_init() {
118 let tp = arch_get_tp();
119 #[cfg(target_arch = "x86_64")]
120 let tcb = tp;
121 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
122 let tcb = tp.wrapping_sub(256);
123 if tp != 0 && core::ptr::read(tcb as *const usize) == tcb {
124 ERRNO_TLS_ACTIVE.store(1, Ordering::Relaxed);
125 }
126}
127
128#[inline]
131unsafe fn syscall_ret(r: i64) -> i64 {
132 if r < 0 {
133 *errno_ptr() = (-r) as c_int;
134 -1
135 } else {
136 r
137 }
138}
139
140#[no_mangle]
141pub unsafe extern "C" fn __errno_location() -> *mut c_int {
142 errno_ptr()
143}
144
145#[cfg(not(test))]
146#[panic_handler]
147fn panic(_: &core::panic::PanicInfo) -> ! {
148 loop {}
149}
150
151#[cfg(not(test))]
153#[no_mangle]
154pub extern "C" fn rust_eh_personality() {}
155
156const PROT_READ: i32 = 1;
161const PROT_WRITE: i32 = 2;
162const MAP_SHARED: i32 = 0x01;
163const MAP_PRIVATE: i32 = 0x02;
164const MAP_ANONYMOUS: i32 = 0x20;
165
166#[inline]
171unsafe fn sys_write(fd: i64, buf: *const u8, count: usize) -> i64 {
172 <Arch as Syscalls>::syscall3(SYS_WRITE, fd as i64, buf as i64, count as i64)
173}
174
175#[inline]
176unsafe fn sys_read(fd: i64, buf: *mut u8, count: usize) -> i64 {
177 <Arch as Syscalls>::syscall3(SYS_READ, fd as i64, buf as i64, count as i64)
178}
179
180#[inline]
181unsafe fn sys_open(path: *const u8, flags: i64, mode: i64) -> i64 {
182 <Arch as Syscalls>::syscall4(SYS_OPENAT, AT_FDCWD as i64, path as i64, flags as i64, mode as i64)
183}
184
185#[inline]
186unsafe fn sys_close(fd: i64) -> i64 {
187 <Arch as Syscalls>::syscall1(SYS_CLOSE, fd as i64)
188}
189
190#[inline]
191unsafe fn sys_lseek(fd: i64, offset: i64, whence: i64) -> i64 {
192 <Arch as Syscalls>::syscall3(SYS_LSEEK, fd as i64, offset as i64, whence as i64)
193}
194
195unsafe fn sys_mmap(
196 addr: *mut u8,
197 length: usize,
198 prot: i32,
199 flags: i32,
200 fd: i32,
201 offset: i64,
202) -> *mut u8 {
203 let result = <Arch as Syscalls>::syscall6(SYS_MMAP, addr as i64, length as i64, prot as i64, flags as i64, fd as i64, offset);
204 if result < 0 && result > -4096 {
205 ERRNO!() = (-result) as c_int;
206 return MMAP_FAILED;
207 }
208 result as *mut u8
209}
210
211unsafe fn sys_munmap(addr: *mut u8, length: usize) -> i64 {
212 <Arch as Syscalls>::syscall2(SYS_MUNMAP, addr as i64, length as i64)
213}
214
215#[no_mangle]
222pub unsafe extern "C" fn bcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int {
223 memcmp(s1, s2, n)
224}
225
226#[no_mangle]
229pub unsafe extern "C" fn strncmp(s1: *const u8, s2: *const u8, n: usize) -> c_int {
230 let mut i = 0;
231 while i < n {
232 let a = *s1.add(i);
233 let b = *s2.add(i);
234 if a != b {
235 return a as c_int - b as c_int;
236 }
237 if a == 0 {
238 return 0;
239 }
240 i += 1;
241 }
242 0
243}
244
245#[no_mangle]
246pub unsafe extern "C" fn strcpy(dst: *mut u8, src: *const u8) -> *mut u8 {
247 let mut i = 0;
248 loop {
249 let c = *src.add(i);
250 *dst.add(i) = c;
251 if c == 0 {
252 break;
253 }
254 i += 1;
255 }
256 dst
257}
258
259#[no_mangle]
260pub unsafe extern "C" fn strncpy(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 {
261 let mut i = 0;
262 while i < n && *src.add(i) != 0 {
263 *dst.add(i) = *src.add(i);
264 i += 1;
265 }
266 while i < n {
267 *dst.add(i) = 0;
268 i += 1;
269 }
270 dst
271}
272
273#[no_mangle]
274pub unsafe extern "C" fn strcat(dst: *mut u8, src: *const u8) -> *mut u8 {
275 let mut i = 0;
276 while *dst.add(i) != 0 {
277 i += 1;
278 }
279 let mut j = 0;
280 loop {
281 let c = *src.add(j);
282 *dst.add(i + j) = c;
283 if c == 0 {
284 break;
285 }
286 j += 1;
287 }
288 dst
289}
290
291#[no_mangle]
292pub unsafe extern "C" fn strncat(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 {
293 let mut i = 0;
294 while *dst.add(i) != 0 {
295 i += 1;
296 }
297 let mut j = 0;
298 while j < n && *src.add(j) != 0 {
299 *dst.add(i + j) = *src.add(j);
300 j += 1;
301 }
302 *dst.add(i + j) = 0;
303 dst
304}
305
306#[no_mangle]
307pub unsafe extern "C" fn strlcpy(dst: *mut u8, src: *const u8, n: usize) -> usize {
308 let l = strlen(src as *const c_char);
309 if n > 0 {
310 let c = if l < n { l } else { n - 1 };
311 core::ptr::copy_nonoverlapping(src, dst, c);
312 *dst.add(c) = 0;
313 }
314 l
315}
316
317#[no_mangle]
318pub unsafe extern "C" fn strlcat(dst: *mut u8, src: *const u8, n: usize) -> usize {
319 let dl = strlen(dst as *const c_char);
320 let sl = strlen(src as *const c_char);
321 if dl >= n { return n + sl; }
322 let c = if sl < n - dl { sl } else { n - dl - 1 };
323 core::ptr::copy_nonoverlapping(src, dst.add(dl), c);
324 *dst.add(dl + c) = 0;
325 dl + sl
326}
327
328#[no_mangle]
329pub unsafe extern "C" fn bcopy(src: *const c_void, dst: *mut c_void, n: usize) {
330 core::ptr::copy(src as *const u8, dst as *mut u8, n);
331}
332
333#[no_mangle]
334pub unsafe extern "C" fn bzero(s: *mut c_void, n: usize) {
335 core::ptr::write_bytes(s as *mut u8, 0, n);
336}
337
338#[no_mangle]
339pub unsafe extern "C" fn strndup(s: *const c_char, n: usize) -> *mut c_char {
340 let mut len = 0;
341 while len < n && *s.add(len) != 0 {
342 len += 1;
343 }
344 let p = malloc(len + 1) as *mut c_char;
345 if p.is_null() {
346 return core::ptr::null_mut();
347 }
348 core::ptr::copy_nonoverlapping(s, p, len);
349 *p.add(len) = 0;
350 p
351}
352
353#[no_mangle]
354pub unsafe extern "C" fn strchr(s: *const u8, c: c_int) -> *mut u8 {
355 let target = c as u8;
356 let mut i = 0;
357 loop {
358 let ch = *s.add(i);
359 if ch == target {
360 return s.add(i) as *mut u8;
361 }
362 if ch == 0 {
363 return null_mut();
364 }
365 i += 1;
366 }
367}
368
369#[no_mangle]
370pub unsafe extern "C" fn strrchr(s: *const u8, c: c_int) -> *mut u8 {
371 let target = c as u8;
372 let mut i = 0;
373 let mut last: *mut u8 = null_mut();
374 loop {
375 let ch = *s.add(i);
376 if ch == target {
377 last = s.add(i) as *mut u8;
378 }
379 if ch == 0 {
380 return last;
381 }
382 i += 1;
383 }
384}
385
386#[no_mangle]
387pub unsafe extern "C" fn strnlen(s: *const u8, maxlen: usize) -> usize {
388 let mut i = 0;
389 while i < maxlen && *s.add(i) != 0 {
390 i += 1;
391 }
392 i
393}
394
395#[no_mangle]
396pub unsafe extern "C" fn strcspn(s: *const u8, reject: *const u8) -> usize {
397 let mut i = 0;
398 loop {
399 let c = *s.add(i);
400 if c == 0 {
401 return i;
402 }
403 let mut j = 0;
404 loop {
405 let r = *reject.add(j);
406 if r == 0 {
407 break;
408 }
409 if c == r {
410 return i;
411 }
412 j += 1;
413 }
414 i += 1;
415 }
416}
417
418#[no_mangle]
419pub unsafe extern "C" fn strspn(s: *const u8, accept: *const u8) -> usize {
420 let mut i = 0;
421 loop {
422 let c = *s.add(i);
423 if c == 0 {
424 return i;
425 }
426 let mut found = false;
427 let mut j = 0;
428 loop {
429 let a = *accept.add(j);
430 if a == 0 {
431 break;
432 }
433 if c == a {
434 found = true;
435 break;
436 }
437 j += 1;
438 }
439 if !found {
440 return i;
441 }
442 i += 1;
443 }
444}
445
446#[no_mangle]
447pub unsafe extern "C" fn strpbrk(s: *const u8, accept: *const u8) -> *mut u8 {
448 let mut i = 0;
449 loop {
450 let c = *s.add(i);
451 if c == 0 {
452 return null_mut();
453 }
454 let mut j = 0;
455 loop {
456 let a = *accept.add(j);
457 if a == 0 {
458 break;
459 }
460 if c == a {
461 return s.add(i) as *mut u8;
462 }
463 j += 1;
464 }
465 i += 1;
466 }
467}
468
469#[no_mangle]
470pub unsafe extern "C" fn strstr(haystack: *const u8, needle: *const u8) -> *mut u8 {
471 if *needle == 0 {
472 return haystack as *mut u8;
473 }
474 let mut i = 0;
475 loop {
476 let h = *haystack.add(i);
477 if h == 0 {
478 return null_mut();
479 }
480 if h == *needle {
481 let mut j = 0;
482 loop {
483 let n = *needle.add(j);
484 if n == 0 {
485 return haystack.add(i) as *mut u8;
486 }
487 if *haystack.add(i + j) != n {
488 break;
489 }
490 j += 1;
491 }
492 }
493 i += 1;
494 }
495}
496
497#[no_mangle]
498pub unsafe extern "C" fn memchr(s: *const u8, c: c_int, n: usize) -> *mut u8 {
499 let target = c as u8;
500 let mut i = 0;
501 while i < n {
502 if *s.add(i) == target {
503 return s.add(i) as *mut u8;
504 }
505 i += 1;
506 }
507 null_mut()
508}
509
510#[no_mangle]
511pub unsafe extern "C" fn memrchr(s: *const u8, c: c_int, n: usize) -> *mut u8 {
512 let target = c as u8;
513 let mut i = n;
514 while i > 0 {
515 i -= 1;
516 if *s.add(i) == target {
517 return s.add(i) as *mut u8;
518 }
519 }
520 null_mut()
521}
522
523#[no_mangle]
524pub unsafe extern "C" fn memmem(
525 haystack: *const c_void, haystacklen: usize,
526 needle: *const c_void, needlelen: usize,
527) -> *mut c_void {
528 if needlelen == 0 { return haystack as *mut c_void; }
529 if haystacklen < needlelen { return null_mut(); }
530 let h = haystack as *const u8;
531 let n = needle as *const u8;
532 let last = haystacklen - needlelen;
533 for i in 0..=last {
534 if *h.add(i) == *n && memcmp(h.add(i) as *const c_void, n as *const c_void, needlelen) == 0 {
535 return h.add(i) as *mut c_void;
536 }
537 }
538 null_mut()
539}
540
541#[no_mangle]
542pub unsafe extern "C" fn strtok(s: *mut u8, delim: *const u8) -> *mut u8 {
543 static mut STATE: *mut u8 = core::ptr::null_mut();
544 let mut p = if s.is_null() { STATE } else { s };
545 if p.is_null() {
546 return core::ptr::null_mut();
547 }
548 loop {
549 let c = *p;
550 if c == 0 {
551 STATE = core::ptr::null_mut();
552 return core::ptr::null_mut();
553 }
554 let mut is_delim = false;
555 let mut i = 0;
556 loop {
557 let d = *delim.add(i);
558 if d == 0 {
559 break;
560 }
561 if c == d {
562 is_delim = true;
563 break;
564 }
565 i += 1;
566 }
567 if !is_delim {
568 break;
569 }
570 p = p.add(1);
571 }
572 let start = p;
573 loop {
574 let c = *p;
575 if c == 0 {
576 STATE = core::ptr::null_mut();
577 return start;
578 }
579 let mut is_delim = false;
580 let mut i = 0;
581 loop {
582 let d = *delim.add(i);
583 if d == 0 {
584 break;
585 }
586 if c == d {
587 is_delim = true;
588 break;
589 }
590 i += 1;
591 }
592 if is_delim {
593 *p = 0;
594 STATE = p.add(1);
595 return start;
596 }
597 p = p.add(1);
598 }
599}
600
601type SizeT = usize;
606type SSizeT = isize;
607type mode_t = c_uint;
608type TimeT = c_long;
609type ClockT = c_long;
610type wchar_t = c_int;
611type wint_t = c_uint;
612type wctype_t = *const c_int;
613type wctrans_t = *const c_int;
614
615const WEOF: wint_t = 0xffffffff;
616
617#[repr(C)]
618pub struct tm {
619 pub tm_sec: c_int,
620 pub tm_min: c_int,
621 pub tm_hour: c_int,
622 pub tm_mday: c_int,
623 pub tm_mon: c_int,
624 pub tm_year: c_int,
625 pub tm_wday: c_int,
626 pub tm_yday: c_int,
627 pub tm_isdst: c_int,
628 pub tm_gmtoff: c_long,
629 pub tm_zone: *const c_char,
630}
631
632#[repr(C)]
633pub struct timeval {
634 pub tv_sec: TimeT,
635 pub tv_usec: c_long,
636}
637
638#[repr(C)]
639pub struct Timeb {
640 pub time: TimeT,
641 pub millitm: u16,
642 pub timezone: i16,
643 pub dstflag: u16,
644}
645
646const CT_UPPER: u8 = 1 << 0;
651const CT_LOWER: u8 = 1 << 1;
652const CT_DIGIT: u8 = 1 << 2;
653const CT_SPACE: u8 = 1 << 3;
654const CT_PUNCT: u8 = 1 << 4;
655const CT_CNTRL: u8 = 1 << 5;
656const CT_BLANK: u8 = 1 << 6;
657const CT_XDIGIT: u8 = 1 << 7;
658
659const CT_TABLE: [u8; 128] = {
660 let mut t = [0u8; 128];
661 let mut i = 0;
662 while i < 128 {
663 let c = i as u8;
664 let mut flags = 0u8;
665 if c >= b'A' && c <= b'Z' {
666 flags |= CT_UPPER;
667 }
668 if c >= b'a' && c <= b'z' {
669 flags |= CT_LOWER;
670 }
671 if c >= b'0' && c <= b'9' {
672 flags |= CT_DIGIT;
673 }
674 if c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == b'\x0c' || c == b'\x0b' {
675 flags |= CT_SPACE;
676 }
677 if (c >= b'!' && c <= b'/')
678 || (c >= b':' && c <= b'@')
679 || (c >= b'[' && c <= b'`')
680 || (c >= b'{' && c <= b'~')
681 {
682 flags |= CT_PUNCT;
683 }
684 if c < 0x20 || c == 0x7f {
685 flags |= CT_CNTRL;
686 }
687 if c == b' ' || c == b'\t' {
688 flags |= CT_BLANK;
689 }
690 if (c >= b'0' && c <= b'9') || (c >= b'A' && c <= b'F') || (c >= b'a' && c <= b'f') {
691 flags |= CT_XDIGIT;
692 }
693 t[i] = flags;
694 i += 1;
695 }
696 t
697};
698
699#[inline]
700fn ct_flags(c: c_int) -> u8 {
701 if c < 0 || c > 127 {
702 0
703 } else {
704 CT_TABLE[c as usize]
705 }
706}
707
708#[no_mangle]
709pub extern "C" fn isalnum(c: c_int) -> c_int {
710 (ct_flags(c) & (CT_UPPER | CT_LOWER | CT_DIGIT) != 0) as c_int
711}
712
713#[no_mangle]
714pub extern "C" fn isalpha(c: c_int) -> c_int {
715 (ct_flags(c) & (CT_UPPER | CT_LOWER) != 0) as c_int
716}
717
718#[no_mangle]
719pub extern "C" fn isascii(c: c_int) -> c_int {
720 ((c as u32) <= 127) as c_int
721}
722
723#[no_mangle]
724pub extern "C" fn isblank(c: c_int) -> c_int {
725 (ct_flags(c) & CT_BLANK != 0) as c_int
726}
727
728#[no_mangle]
729pub extern "C" fn iscntrl(c: c_int) -> c_int {
730 (ct_flags(c) & CT_CNTRL != 0) as c_int
731}
732
733#[no_mangle]
734pub extern "C" fn isdigit(c: c_int) -> c_int {
735 (ct_flags(c) & CT_DIGIT != 0) as c_int
736}
737
738#[no_mangle]
739pub extern "C" fn isgraph(c: c_int) -> c_int {
740 (ct_flags(c) & (CT_UPPER | CT_LOWER | CT_DIGIT | CT_PUNCT) != 0) as c_int
741}
742
743#[no_mangle]
744pub extern "C" fn islower(c: c_int) -> c_int {
745 (ct_flags(c) & CT_LOWER != 0) as c_int
746}
747
748#[no_mangle]
749pub extern "C" fn isprint(c: c_int) -> c_int {
750 let flags = ct_flags(c);
751 (flags & (CT_UPPER | CT_LOWER | CT_DIGIT | CT_PUNCT | CT_BLANK) != 0) as c_int
752}
753
754#[no_mangle]
755pub extern "C" fn ispunct(c: c_int) -> c_int {
756 (ct_flags(c) & CT_PUNCT != 0) as c_int
757}
758
759#[no_mangle]
760pub extern "C" fn isspace(c: c_int) -> c_int {
761 (ct_flags(c) & CT_SPACE != 0) as c_int
762}
763
764#[no_mangle]
765pub extern "C" fn isupper(c: c_int) -> c_int {
766 (ct_flags(c) & CT_UPPER != 0) as c_int
767}
768
769#[no_mangle]
770pub extern "C" fn isxdigit(c: c_int) -> c_int {
771 (ct_flags(c) & CT_XDIGIT != 0) as c_int
772}
773
774#[no_mangle]
775pub extern "C" fn tolower(c: c_int) -> c_int {
776 if (ct_flags(c) & CT_UPPER) != 0 {
777 c + (b'a' as c_int - b'A' as c_int)
778 } else {
779 c
780 }
781}
782
783#[no_mangle]
784pub extern "C" fn toupper(c: c_int) -> c_int {
785 if (ct_flags(c) & CT_LOWER) != 0 {
786 c - (b'a' as c_int - b'A' as c_int)
787 } else {
788 c
789 }
790}
791
792unsafe fn parse_digit(c: u8, base: c_int) -> Option<u8> {
797 if c == 0 { return None; }
798 let d = if c >= b'0' && c <= b'9' {
799 c - b'0'
800 } else if c >= b'a' && c <= b'z' {
801 c - b'a' + 10
802 } else if c >= b'A' && c <= b'Z' {
803 c - b'A' + 10
804 } else {
805 return None;
806 };
807 if (d as c_int) < base {
808 Some(d)
809 } else {
810 None
811 }
812}
813
814unsafe fn parse_prefix(s: *const u8, base: *mut c_int) -> *const u8 {
815 let mut p = s;
816 if *base == 0 {
817 if *p == b'0' {
818 if (*p.add(1) == b'x' || *p.add(1) == b'X') && parse_digit(*p.add(2), 16).is_some() {
819 *base = 16;
820 p = p.add(2);
821 } else {
822 *base = 8;
823 }
824 } else {
825 *base = 10;
826 }
827 } else if *base == 16 {
828 if *p == b'0' && (*p.add(1) == b'x' || *p.add(1) == b'X') && parse_digit(*p.add(2), 16).is_some() {
829 p = p.add(2);
830 }
831 }
832 p
833}
834
835unsafe fn strtox(
836 s: *const c_char,
837 endptr: *mut *mut c_char,
838 mut base: c_int,
839 pos_limit: u64,
840 neg_limit: u64,
841) -> (u64, bool, bool) {
842 let s0 = s as *const u8;
843 let mut p = s0;
844 while isspace(*p as c_int) != 0 {
845 p = p.add(1);
846 }
847
848 if base < 0 || base == 1 || base > 36 {
849 if !endptr.is_null() {
850 *endptr = s as *mut c_char;
851 }
852 ERRNO!() = EINVAL;
853 return (0, false, false);
854 }
855
856 let mut neg = false;
857 match *p {
858 b'-' => { neg = true; p = p.add(1); }
859 b'+' => p = p.add(1),
860 _ => {}
861 }
862
863 p = parse_prefix(p, &mut base);
864
865 let limit = if neg { neg_limit } else { pos_limit };
866 let mut val: u64 = 0;
867 let mut any = false;
868 while let Some(d) = parse_digit(*p, base) {
869 any = true;
870 if val > (limit - d as u64) / base as u64 {
871 while parse_digit(*p, base).is_some() { p = p.add(1); }
872 if !endptr.is_null() { *endptr = p as *mut c_char; }
873 ERRNO!() = ERANGE_VAL;
874 return (limit, true, neg);
875 }
876 val = val * base as u64 + d as u64;
877 p = p.add(1);
878 }
879
880 if !endptr.is_null() {
881 *endptr = if any { p as *mut c_char } else { s as *mut c_char };
882 }
883 (val, false, neg)
884}
885
886#[no_mangle]
887pub unsafe extern "C" fn strtol(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_long {
888 let pos_limit = c_long::MAX as u64;
889 let neg_limit = pos_limit.wrapping_add(1);
890 let (val, overflow, neg) = strtox(s, endptr, base, pos_limit, neg_limit);
891 if overflow {
892 return if neg { c_long::MIN } else { c_long::MAX };
893 }
894 if neg { val.wrapping_neg() as c_long } else { val as c_long }
895}
896
897#[no_mangle]
898pub unsafe extern "C" fn strtoul(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_ulong {
899 let limit = c_ulong::MAX as u64;
900 let (val, overflow, neg) = strtox(s, endptr, base, limit, limit);
901 if overflow {
902 return c_ulong::MAX;
903 }
904 if neg { val.wrapping_neg() as c_ulong } else { val as c_ulong }
905}
906
907#[no_mangle]
908pub unsafe extern "C" fn strtoll(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_longlong {
909 let pos_limit = c_longlong::MAX as u64;
910 let neg_limit = pos_limit.wrapping_add(1);
911 let (val, overflow, neg) = strtox(s, endptr, base, pos_limit, neg_limit);
912 if overflow {
913 return if neg { c_longlong::MIN } else { c_longlong::MAX };
914 }
915 if neg { val.wrapping_neg() as c_longlong } else { val as c_longlong }
916}
917
918#[no_mangle]
919pub unsafe extern "C" fn strtoull(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_ulonglong {
920 let limit = c_ulonglong::MAX as u64;
921 let (val, overflow, neg) = strtox(s, endptr, base, limit, limit);
922 if overflow {
923 return c_ulonglong::MAX;
924 }
925 if neg { val.wrapping_neg() as c_ulonglong } else { val as c_ulonglong }
926}
927
928#[no_mangle]
929pub unsafe extern "C" fn atoi(s: *const c_char) -> c_int {
930 strtol(s, core::ptr::null_mut(), 10) as c_int
931}
932
933#[no_mangle]
934pub unsafe extern "C" fn atol(s: *const c_char) -> c_long {
935 strtol(s, core::ptr::null_mut(), 10)
936}
937
938#[no_mangle]
939pub unsafe extern "C" fn atoll(s: *const c_char) -> c_longlong {
940 strtoll(s, core::ptr::null_mut(), 10)
941}
942
943#[no_mangle]
944pub extern "C" fn abs(n: c_int) -> c_int {
945 if n < 0 {
946 -n
947 } else {
948 n
949 }
950}
951
952#[no_mangle]
953pub extern "C" fn labs(n: c_long) -> c_long {
954 if n < 0 {
955 -n
956 } else {
957 n
958 }
959}
960
961#[no_mangle]
962pub extern "C" fn llabs(n: c_longlong) -> c_longlong {
963 if n < 0 {
964 -n
965 } else {
966 n
967 }
968}
969
970static mut RAND_STATE: c_uint = 1;
971
972#[no_mangle]
973pub extern "C" fn srand(seed: c_uint) {
974 unsafe {
975 RAND_STATE = seed;
976 }
977}
978
979#[no_mangle]
980pub extern "C" fn rand() -> c_int {
981 unsafe {
982 RAND_STATE = RAND_STATE.wrapping_mul(1103515245).wrapping_add(12345);
983 ((RAND_STATE >> 16) & 0x7fff) as c_int
984 }
985}
986
987#[repr(C)]
992pub struct div_t { pub quot: c_int, pub rem: c_int }
993#[repr(C)]
994pub struct ldiv_t { pub quot: c_long, pub rem: c_long }
995#[repr(C)]
996pub struct lldiv_t { pub quot: c_longlong, pub rem: c_longlong }
997
998#[no_mangle]
999pub extern "C" fn div(num: c_int, den: c_int) -> div_t {
1000 div_t { quot: num / den, rem: num % den }
1001}
1002
1003#[no_mangle]
1004pub extern "C" fn ldiv(num: c_long, den: c_long) -> ldiv_t {
1005 ldiv_t { quot: num / den, rem: num % den }
1006}
1007
1008#[no_mangle]
1009pub extern "C" fn lldiv(num: c_longlong, den: c_longlong) -> lldiv_t {
1010 lldiv_t { quot: num / den, rem: num % den }
1011}
1012
1013type CmpFn = unsafe extern "C" fn(*const c_void, *const c_void) -> c_int;
1018
1019#[no_mangle]
1020pub unsafe extern "C" fn bsearch(
1021 key: *const c_void,
1022 base: *const c_void,
1023 nel: usize,
1024 width: usize,
1025 cmp: CmpFn,
1026) -> *mut c_void {
1027 let mut base = base as *const u8;
1028 let mut nel = nel;
1029 while nel > 0 {
1030 let trial = base.add(width * (nel / 2));
1031 let sign = cmp(key, trial as *const c_void);
1032 if sign < 0 {
1033 nel /= 2;
1034 } else if sign > 0 {
1035 base = trial.add(width);
1036 nel -= nel / 2 + 1;
1037 } else {
1038 return trial as *mut c_void;
1039 }
1040 }
1041 null_mut()
1042}
1043
1044pub const SA_RESTORER: c_ulong = 0x04000000;
1049
1050pub const SIG_DFL: usize = 0;
1051pub const SIG_IGN: usize = 1;
1052pub const SIG_ERR: usize = !0usize;
1053
1054pub const SIGHUP: c_int = 1;
1055pub const SIGINT: c_int = 2;
1056pub const SIGQUIT: c_int = 3;
1057pub const SIGILL: c_int = 4;
1058pub const SIGTRAP: c_int = 5;
1059pub const SIGABRT: c_int = 6;
1060pub const SIGIOT: c_int = 6;
1061pub const SIGBUS: c_int = 7;
1062pub const SIGFPE: c_int = 8;
1063pub const SIGKILL: c_int = 9;
1064pub const SIGUSR1: c_int = 10;
1065pub const SIGSEGV: c_int = 11;
1066pub const SIGUSR2: c_int = 12;
1067pub const SIGPIPE: c_int = 13;
1068pub const SIGALRM: c_int = 14;
1069pub const SIGTERM: c_int = 15;
1070pub const SIGSTKFLT: c_int = 16;
1071pub const SIGCHLD: c_int = 17;
1072pub const SIGCONT: c_int = 18;
1073pub const SIGSTOP: c_int = 19;
1074pub const SIGTSTP: c_int = 20;
1075pub const SIGTTIN: c_int = 21;
1076pub const SIGTTOU: c_int = 22;
1077pub const SIGURG: c_int = 23;
1078pub const SIGXCPU: c_int = 24;
1079pub const SIGXFSZ: c_int = 25;
1080pub const SIGVTALRM: c_int = 26;
1081pub const SIGPROF: c_int = 27;
1082pub const SIGWINCH: c_int = 28;
1083pub const SIGIO: c_int = 29;
1084pub const SIGPOLL: c_int = 29;
1085pub const SIGPWR: c_int = 30;
1086pub const SIGSYS: c_int = 31;
1087pub const SIGUNUSED: c_int = 31;
1088pub const _NSIG: c_int = 65;
1089
1090pub const SIG_BLOCK: c_int = 0;
1091pub const SIG_UNBLOCK: c_int = 1;
1092pub const SIG_SETMASK: c_int = 2;
1093
1094pub const SA_NOCLDSTOP: c_ulong = 1;
1095pub const SA_NOCLDWAIT: c_ulong = 2;
1096pub const SA_SIGINFO: c_ulong = 4;
1097pub const SA_ONSTACK: c_ulong = 0x08000000;
1098pub const SA_RESTART: c_ulong = 0x10000000;
1099pub const SA_NODEFER: c_ulong = 0x40000000;
1100pub const SA_RESETHAND: c_ulong = 0x80000000;
1101
1102pub const SS_ONSTACK: c_int = 1;
1103pub const SS_DISABLE: c_int = 2;
1104#[cfg(target_arch = "aarch64")]
1105pub const MINSIGSTKSZ: usize = 6144;
1106#[cfg(target_arch = "aarch64")]
1107pub const SIGSTKSZ: usize = 12288;
1108#[cfg(not(target_arch = "aarch64"))]
1109pub const MINSIGSTKSZ: usize = 2048;
1110#[cfg(not(target_arch = "aarch64"))]
1111pub const SIGSTKSZ: usize = 8192;
1112
1113pub const SI_USER: c_int = 0;
1114pub const SI_TKILL: c_int = -6;
1115
1116#[repr(C)]
1117pub struct timespec {
1118 pub tv_sec: c_long,
1119 pub tv_nsec: c_long,
1120}
1121
1122#[repr(C)]
1123pub struct siginfo_t {
1124 pub si_signo: c_int,
1125 pub si_errno: c_int,
1126 pub si_code: c_int,
1127 _pad: [u8; 128 - 3 * core::mem::size_of::<c_int>()],
1129}
1130
1131#[repr(C)]
1132pub struct stack_t {
1133 pub ss_sp: *mut c_void,
1134 pub ss_flags: c_int,
1135 pub ss_size: usize,
1136}
1137
1138#[repr(C)]
1141pub struct KSigAction {
1142 pub sa_handler: usize,
1143 pub sa_flags: c_ulong,
1144 pub sa_restorer: usize,
1145 pub sa_mask: [c_ulong; 1],
1146}
1147
1148#[repr(C)]
1150pub struct sigaction {
1151 pub sa_handler: usize,
1152 pub sa_mask: [u64; 16],
1153 pub sa_flags: c_int,
1154 pub sa_restorer: usize,
1155}
1156
1157pub type SigSetT = c_ulong;
1158
1159#[cfg(target_arch = "x86_64")]
1160core::arch::global_asm!(
1161 ".global sig_restorer",
1162 ".type sig_restorer, @function",
1163 "sig_restorer:",
1164 "mov eax, 15",
1165 "syscall",
1166);
1167
1168#[cfg(target_arch = "aarch64")]
1169core::arch::global_asm!(
1170 ".global sig_restorer",
1171 ".type sig_restorer, @function",
1172 "sig_restorer:",
1173 "mov x8, #139",
1174 "svc #0",
1175);
1176
1177#[cfg(target_arch = "riscv64")]
1178core::arch::global_asm!(
1179 ".global sig_restorer",
1180 ".type sig_restorer, @function",
1181 "sig_restorer:",
1182 "li a7, 139",
1183 "ecall",
1184);
1185
1186extern "C" {
1187 fn sig_restorer();
1188}
1189
1190#[inline]
1191unsafe fn sys_rt_sigaction(sig: c_int,
1192 act: *const KSigAction,
1193 oldact: *mut KSigAction,
1194 sigsetsize: usize,) -> i64 {
1195 <Arch as Syscalls>::syscall4(SYS_RT_SIGACTION, sig as i64, act as i64, oldact as i64, sigsetsize as i64)
1196}
1197
1198#[inline]
1199unsafe fn sys_rt_sigprocmask(how: c_int,
1200 set: *const SigSetT,
1201 oldset: *mut SigSetT,
1202 sigsetsize: usize,) -> i64 {
1203 <Arch as Syscalls>::syscall4(SYS_RT_SIGPROCMASK, how as i64, set as i64, oldset as i64, sigsetsize as i64)
1204}
1205
1206#[inline]
1207unsafe fn sys_rt_sigpending(set: *mut SigSetT, sigsetsize: usize) -> i64 {
1208 <Arch as Syscalls>::syscall2(SYS_RT_SIGPENDING, set as i64, sigsetsize as i64)
1209}
1210
1211#[inline]
1212unsafe fn sys_rt_sigsuspend(mask: *const SigSetT, sigsetsize: usize) -> i64 {
1213 <Arch as Syscalls>::syscall2(SYS_RT_SIGSUSPEND, mask as i64, sigsetsize as i64)
1214}
1215
1216#[inline]
1217unsafe fn sys_rt_sigtimedwait(set: *const SigSetT,
1218 info: *mut siginfo_t,
1219 timeout: *const timespec,
1220 sigsetsize: usize,) -> i64 {
1221 <Arch as Syscalls>::syscall4(SYS_RT_SIGTIMEDWAIT, set as i64, info as i64, timeout as i64, sigsetsize as i64)
1222}
1223
1224#[inline]
1225unsafe fn sys_sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> i64 {
1226 <Arch as Syscalls>::syscall2(SYS_SIGALTSTACK, ss as i64, old_ss as i64)
1227}
1228
1229#[inline]
1230unsafe fn sys_tgkill(tgid: c_int, tid: c_int, sig: c_int) -> i64 {
1231 <Arch as Syscalls>::syscall3(SYS_TGKILL, tgid as i64, tid as i64, sig as i64)
1232}
1233
1234const CLOCK_REALTIME: c_int = 0;
1235const CLOCK_MONOTONIC: c_int = 1;
1236
1237#[inline]
1238unsafe fn sys_clock_gettime(clockid: c_int, ts: *mut timespec) -> i64 {
1239 <Arch as Syscalls>::syscall2(SYS_CLOCK_GETTIME, clockid as i64, ts as i64)
1240}
1241
1242#[no_mangle]
1246pub unsafe extern "C" fn sigprocmask(
1247 how: c_int,
1248 set: *const SigSetT,
1249 oldset: *mut SigSetT,
1250) -> c_int {
1251 let internal_mask: SigSetT = (1u64 << 31) | (1u64 << 32);
1253 let filtered: SigSetT;
1254 let set_ptr: *const SigSetT = if set.is_null() {
1255 set
1256 } else {
1257 filtered = *set & !internal_mask;
1258 &filtered
1259 };
1260 let r = sys_rt_sigprocmask(how, set_ptr, oldset, core::mem::size_of::<SigSetT>());
1261 if !oldset.is_null() {
1262 *oldset &= !internal_mask;
1263 }
1264 if r < 0 { -1 } else { 0 }
1265}
1266
1267#[inline]
1268unsafe fn sys_kill(pid: c_int, sig: c_int) -> i64 {
1269 <Arch as Syscalls>::syscall2(SYS_KILL, pid as i64, sig as i64)
1270}
1271
1272#[inline]
1273unsafe fn sys_getpid() -> i64 {
1274 <Arch as Syscalls>::syscall0(SYS_GETPID)
1275}
1276
1277#[no_mangle]
1278pub unsafe extern "C" fn sigaction(
1279 signum: c_int,
1280 act: *const sigaction,
1281 oldact: *mut sigaction,
1282) -> c_int {
1283 let mut kact: KSigAction = core::mem::zeroed();
1284 let act_ptr = if act.is_null() {
1285 core::ptr::null()
1286 } else {
1287 kact.sa_handler = (*act).sa_handler;
1288 kact.sa_flags = ((*act).sa_flags as c_ulong) | SA_RESTORER;
1289 kact.sa_restorer = if (*act).sa_flags as c_ulong & SA_RESTORER != 0
1290 && (*act).sa_restorer != 0
1291 {
1292 (*act).sa_restorer
1293 } else {
1294 sig_restorer as *const () as usize
1295 };
1296 kact.sa_mask[0] = (*act).sa_mask[0];
1297 &kact
1298 };
1299 let mut kold: KSigAction = core::mem::zeroed();
1300 let old_ptr = if oldact.is_null() { core::ptr::null_mut() } else { &mut kold };
1301 let r = sys_rt_sigaction(signum, act_ptr, old_ptr, 8);
1302 if r < 0 {
1303 ERRNO!() = (-r) as c_int;
1304 return -1;
1305 }
1306 if !oldact.is_null() {
1307 (*oldact).sa_handler = kold.sa_handler;
1308 (*oldact).sa_flags = kold.sa_flags as c_int;
1309 (*oldact).sa_restorer = kold.sa_restorer;
1310 (*oldact).sa_mask = [0; 16];
1311 (*oldact).sa_mask[0] = kold.sa_mask[0];
1312 }
1313 0
1314}
1315
1316#[no_mangle]
1317pub unsafe extern "C" fn signal(signum: c_int, handler: usize) -> usize {
1318 let act = sigaction {
1321 sa_handler: handler,
1322 sa_mask: [0; 16],
1323 sa_flags: SA_RESTART as c_int,
1324 sa_restorer: 0,
1325 };
1326 let mut old: sigaction = core::mem::zeroed();
1327 if sigaction(signum, &act, &mut old) == -1 {
1328 SIG_ERR
1329 } else {
1330 old.sa_handler
1331 }
1332}
1333
1334#[no_mangle]
1335pub unsafe extern "C" fn kill(pid: c_int, sig: c_int) -> c_int {
1336 let r = sys_kill(pid, sig);
1337 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
1338 0
1339}
1340
1341#[no_mangle]
1342pub unsafe extern "C" fn tgkill(tgid: c_int, tid: c_int, sig: c_int) -> c_int {
1343 let r = sys_tgkill(tgid, tid, sig);
1344 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
1345 0
1346}
1347
1348#[no_mangle]
1349pub unsafe extern "C" fn getpid() -> c_int {
1350 sys_getpid() as c_int
1351}
1352
1353#[no_mangle]
1354pub unsafe extern "C" fn raise(sig: c_int) -> c_int {
1355 let r = sys_tgkill(sys_getpid() as c_int, sys_gettid() as c_int, sig);
1356 if r < 0 {
1357 ERRNO!() = (-r) as c_int;
1358 -1
1359 } else {
1360 0
1361 }
1362}
1363
1364#[no_mangle]
1365pub unsafe extern "C" fn sigemptyset(set: *mut SigSetT) -> c_int {
1366 *set = 0;
1367 0
1368}
1369
1370#[no_mangle]
1371pub unsafe extern "C" fn sigfillset(set: *mut SigSetT) -> c_int {
1372 *set = 0xFFFF_FFFC_7FFF_FFFFu64;
1374 0
1375}
1376
1377#[no_mangle]
1378pub unsafe extern "C" fn sigaddset(set: *mut SigSetT, signum: c_int) -> c_int {
1379 let s = (signum as c_uint).wrapping_sub(1);
1380 if s as usize >= 64 {
1381 ERRNO!() = EINVAL;
1382 return -1;
1383 }
1384 if signum >= 32 && signum < __libc_current_sigrtmin() {
1386 return 0;
1387 }
1388 *set |= 1u64 << s;
1389 0
1390}
1391
1392#[no_mangle]
1393pub unsafe extern "C" fn sigdelset(set: *mut SigSetT, signum: c_int) -> c_int {
1394 let s = (signum as c_uint).wrapping_sub(1);
1395 if s as usize >= 64 {
1396 ERRNO!() = EINVAL;
1397 return -1;
1398 }
1399 if signum >= 32 && signum < __libc_current_sigrtmin() {
1401 return 0;
1402 }
1403 *set &= !(1u64 << s);
1404 0
1405}
1406
1407#[no_mangle]
1408pub unsafe extern "C" fn sigismember(set: *const SigSetT, signum: c_int) -> c_int {
1409 let s = (signum as c_uint).wrapping_sub(1);
1410 if s as usize >= 64 { return 0; }
1411 if signum >= 32 && signum < __libc_current_sigrtmin() {
1413 return 0;
1414 }
1415 ((*set & (1u64 << s)) != 0) as c_int
1416}
1417
1418#[no_mangle]
1419pub unsafe extern "C" fn sigpending(set: *mut SigSetT) -> c_int {
1420 let r = sys_rt_sigpending(set, core::mem::size_of::<SigSetT>());
1421 if r < 0 {
1422 ERRNO!() = (-r) as c_int;
1423 return -1;
1424 }
1425 0
1426}
1427
1428#[no_mangle]
1429pub unsafe extern "C" fn sigsuspend(mask: *const SigSetT) -> c_int {
1430 let r = sys_rt_sigsuspend(mask, core::mem::size_of::<SigSetT>());
1431 if r < 0 {
1432 ERRNO!() = (-r) as c_int;
1433 }
1434 -1
1435}
1436
1437#[no_mangle]
1438pub unsafe extern "C" fn sigtimedwait(
1439 mask: *const SigSetT,
1440 info: *mut siginfo_t,
1441 timeout: *const timespec,
1442) -> c_int {
1443 loop {
1444 let r = sys_rt_sigtimedwait(mask, info, timeout, core::mem::size_of::<SigSetT>());
1445 if r >= 0 {
1446 return r as c_int;
1447 }
1448 let e = (-r) as c_int;
1449 if e != EINTR {
1450 ERRNO!() = e;
1451 return -1;
1452 }
1453 }
1454}
1455
1456#[no_mangle]
1457pub unsafe extern "C" fn sigwaitinfo(
1458 mask: *const SigSetT,
1459 info: *mut siginfo_t,
1460) -> c_int {
1461 sigtimedwait(mask, info, core::ptr::null())
1462}
1463
1464#[no_mangle]
1465pub unsafe extern "C" fn sigwait(
1466 mask: *const SigSetT,
1467 sig: *mut c_int,
1468) -> c_int {
1469 let mut info: siginfo_t = core::mem::zeroed();
1470 if sigtimedwait(mask, &mut info, core::ptr::null()) < 0 {
1471 return ERRNO!();
1472 }
1473 *sig = info.si_signo;
1474 0
1475}
1476
1477#[no_mangle]
1478pub unsafe extern "C" fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> c_int {
1479 if !ss.is_null() {
1480 if (*ss).ss_flags & SS_ONSTACK != 0 {
1481 ERRNO!() = EINVAL;
1482 return -1;
1483 }
1484 if (*ss).ss_flags & SS_DISABLE == 0 && (*ss).ss_size < MINSIGSTKSZ {
1485 ERRNO!() = ENOMEM;
1486 return -1;
1487 }
1488 }
1489 let r = sys_sigaltstack(ss, old_ss);
1490 if r < 0 {
1491 ERRNO!() = (-r) as c_int;
1492 return -1;
1493 }
1494 0
1495}
1496
1497#[no_mangle]
1503#[inline(never)]
1504#[cfg(target_arch = "x86_64")]
1505pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
1506 core::arch::asm!(
1507 "mov rax, [rsp]",
1508 "lea rcx, [rsp + 8]",
1509 "mov [r8], rbx",
1510 "mov [r8 + 8], rbp",
1511 "mov [r8 + 16], r12",
1512 "mov [r8 + 24], r13",
1513 "mov [r8 + 32], r14",
1514 "mov [r8 + 40], r15",
1515 "mov [r8 + 48], rcx",
1516 "mov [r8 + 56], rax",
1517 in("r8") env,
1518 lateout("rax") _,
1519 lateout("rcx") _,
1520 options(nostack),
1521 );
1522 0
1523}
1524
1525#[no_mangle]
1526#[inline(never)]
1527#[cfg(target_arch = "x86_64")]
1528pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
1529 let ret = if val == 0 { 1 } else { val } as u32;
1530 core::arch::asm!(
1531 "mov rbx, [r8]",
1532 "mov rbp, [r8 + 8]",
1533 "mov r12, [r8 + 16]",
1534 "mov r13, [r8 + 24]",
1535 "mov r14, [r8 + 32]",
1536 "mov r15, [r8 + 40]",
1537 "mov rsp, [r8 + 48]",
1538 "mov eax, edx",
1539 "jmp [r8 + 56]",
1540 in("r8") env,
1541 in("edx") ret,
1542 options(noreturn),
1543 );
1544}
1545
1546#[no_mangle]
1547#[unsafe(naked)]
1548#[cfg(target_arch = "aarch64")]
1549pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
1550 core::arch::naked_asm!(
1551 "stp x19, x20, [x0, #0]",
1552 "stp x21, x22, [x0, #16]",
1553 "stp x23, x24, [x0, #32]",
1554 "stp x25, x26, [x0, #48]",
1555 "stp x27, x28, [x0, #64]",
1556 "stp x29, x30, [x0, #80]",
1557 "mov x2, sp",
1558 "str x2, [x0, #104]",
1559 "stp d8, d9, [x0, #112]",
1560 "stp d10, d11, [x0, #128]",
1561 "stp d12, d13, [x0, #144]",
1562 "stp d14, d15, [x0, #160]",
1563 "mov x0, #0",
1564 "ret",
1565 );
1566}
1567
1568#[no_mangle]
1569#[inline(never)]
1570#[cfg(target_arch = "aarch64")]
1571pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
1572 let ret = if val == 0 { 1 } else { val } as u64;
1573 core::arch::asm!(
1574 "ldp x19, x20, [x0]",
1575 "ldp x21, x22, [x0, #16]",
1576 "ldp x23, x24, [x0, #32]",
1577 "ldp x25, x26, [x0, #48]",
1578 "ldp x27, x28, [x0, #64]",
1579 "ldp x29, x30, [x0, #80]",
1580 "ldr x2, [x0, #104]",
1581 "mov sp, x2",
1582 "ldp d8, d9, [x0, #112]",
1583 "ldp d10, d11, [x0, #128]",
1584 "ldp d12, d13, [x0, #144]",
1585 "ldp d14, d15, [x0, #160]",
1586 "mov x0, x1",
1587 "br x30",
1588 in("x0") env,
1589 in("x1") ret,
1590 options(noreturn),
1591 );
1592}
1593
1594#[no_mangle]
1595#[unsafe(naked)]
1596#[cfg(target_arch = "riscv64")]
1597pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
1598 core::arch::naked_asm!(
1599 "sd s0, 0(a0)",
1600 "sd s1, 8(a0)",
1601 "sd s2, 16(a0)",
1602 "sd s3, 24(a0)",
1603 "sd s4, 32(a0)",
1604 "sd s5, 40(a0)",
1605 "sd s6, 48(a0)",
1606 "sd s7, 56(a0)",
1607 "sd s8, 64(a0)",
1608 "sd s9, 72(a0)",
1609 "sd s10, 80(a0)",
1610 "sd s11, 88(a0)",
1611 "sd sp, 96(a0)",
1612 "sd ra, 104(a0)",
1613 "li a0, 0",
1614 "ret",
1615 );
1616}
1617
1618#[no_mangle]
1619#[inline(never)]
1620#[cfg(target_arch = "riscv64")]
1621pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
1622 let ret = if val == 0 { 1 } else { val } as u64;
1623 core::arch::asm!(
1624 "ld s0, 0(a0)",
1625 "ld s1, 8(a0)",
1626 "ld s2, 16(a0)",
1627 "ld s3, 24(a0)",
1628 "ld s4, 32(a0)",
1629 "ld s5, 40(a0)",
1630 "ld s6, 48(a0)",
1631 "ld s7, 56(a0)",
1632 "ld s8, 64(a0)",
1633 "ld s9, 72(a0)",
1634 "ld s10, 80(a0)",
1635 "ld s11, 88(a0)",
1636 "ld sp, 96(a0)",
1637 "ld ra, 104(a0)",
1638 "mv a0, a1",
1639 "ret",
1640 in("a0") env,
1641 in("a1") ret,
1642 options(noreturn),
1643 );
1644}
1645
1646#[no_mangle]
1654#[unsafe(naked)]
1655#[cfg(target_arch = "x86_64")]
1656pub unsafe extern "C" fn sigsetjmp(_env: *mut c_ulong, _savemask: c_int) -> c_int {
1657 core::arch::naked_asm!("jmp sigsetjmp_real");
1658}
1659
1660#[no_mangle]
1661#[unsafe(naked)]
1662#[cfg(target_arch = "x86_64")]
1663pub unsafe extern "C" fn __sigsetjmp(_env: *mut c_ulong, _savemask: c_int) -> c_int {
1664 core::arch::naked_asm!("jmp sigsetjmp_real");
1665}
1666
1667#[cfg(target_arch = "x86_64")]
1668core::arch::global_asm!(
1669 ".type sigsetjmp_real, @function",
1670 "sigsetjmp_real:",
1671 " test esi, esi",
1672 " jz 1f",
1673 " pop qword ptr [rdi + 64]",
1674 " mov qword ptr [rdi + 80], rbx",
1675 " mov rbx, rdi",
1679 " call setjmp",
1680 " push qword ptr [rbx + 64]",
1681 " mov rdi, rbx",
1682 " mov esi, eax",
1683 " mov rbx, qword ptr [rbx + 80]",
1684 " lea rdx, [rdi + 72]",
1685 " test esi, esi",
1686 " jz 2f",
1687 " mov rsi, rdx",
1688 " xor rdx, rdx",
1689 " mov edi, 2",
1690 " jmp 3f",
1691 "2:",
1692 " xor rsi, rsi",
1693 " mov edi, 2",
1694 "3:",
1695 " mov eax, 14",
1696 " mov r10d, 8",
1697 " syscall",
1698 " test esi, esi",
1699 " jnz 4f",
1700 " mov rax, 0xfffffffe7fffffff",
1701 " and qword ptr [rdx], rax",
1702 "4:",
1703 " mov eax, esi",
1704 " ret",
1705 "1:",
1706 " jmp setjmp",
1707);
1708
1709#[no_mangle]
1710#[inline(never)]
1711#[cfg(target_arch = "x86_64")]
1712pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
1713 longjmp(env, val);
1714}
1715
1716#[no_mangle]
1717#[cfg(target_arch = "aarch64")]
1718pub unsafe extern "C" fn __sigsetjmp_tail(env: *mut c_ulong, ret: c_int) -> c_int {
1719 const SIG_SETMASK: c_int = 2;
1720 let ss = env.add(23) as *mut SigSetT;
1721 let set = if ret != 0 { ss as *const SigSetT } else { core::ptr::null() };
1722 let old = if ret != 0 { core::ptr::null_mut() } else { ss };
1723 let _ = sys_rt_sigprocmask(SIG_SETMASK, set, old, core::mem::size_of::<SigSetT>());
1724 ret
1725}
1726
1727#[no_mangle]
1728#[unsafe(naked)]
1729#[cfg(target_arch = "aarch64")]
1730pub unsafe extern "C" fn sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
1731 core::arch::naked_asm!(
1732 "cbz w1, setjmp",
1733 "str x30, [x0, #176]",
1734 "str x19, [x0, #192]",
1735 "mov x19, x0",
1736 "bl setjmp",
1737 "mov w1, w0",
1738 "mov x0, x19",
1739 "ldr x30, [x0, #176]",
1740 "ldr x19, [x0, #192]",
1741 "b __sigsetjmp_tail",
1742 );
1743}
1744
1745#[no_mangle]
1746#[unsafe(naked)]
1747#[cfg(target_arch = "aarch64")]
1748pub unsafe extern "C" fn __sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
1749 core::arch::naked_asm!(
1750 "cbz w1, setjmp",
1751 "str x30, [x0, #176]",
1752 "str x19, [x0, #192]",
1753 "mov x19, x0",
1754 "bl setjmp",
1755 "mov w1, w0",
1756 "mov x0, x19",
1757 "ldr x30, [x0, #176]",
1758 "ldr x19, [x0, #192]",
1759 "b __sigsetjmp_tail",
1760 );
1761}
1762
1763#[no_mangle]
1764#[inline(never)]
1765#[cfg(target_arch = "aarch64")]
1766pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
1767 longjmp(env, val);
1768}
1769
1770#[no_mangle]
1771#[cfg(target_arch = "riscv64")]
1772pub unsafe extern "C" fn __sigsetjmp_tail(env: *mut c_ulong, ret: c_int) -> c_int {
1773 const SIG_SETMASK: c_int = 2;
1774 let ss = env.add(27) as *mut SigSetT;
1775 let set = if ret != 0 { ss as *const SigSetT } else { core::ptr::null() };
1776 let old = if ret != 0 { core::ptr::null_mut() } else { ss };
1777 let _ = sys_rt_sigprocmask(SIG_SETMASK, set, old, core::mem::size_of::<SigSetT>());
1778 ret
1779}
1780
1781#[no_mangle]
1782#[unsafe(naked)]
1783#[cfg(target_arch = "riscv64")]
1784pub unsafe extern "C" fn sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
1785 core::arch::naked_asm!(
1786 "bnez a1, 1f",
1787 "tail setjmp",
1788 "1:",
1789 "sd ra, 208(a0)",
1790 "sd s0, 224(a0)",
1791 "mv s0, a0",
1792 "call setjmp",
1793 "mv a1, a0",
1794 "mv a0, s0",
1795 "ld s0, 224(a0)",
1796 "ld ra, 208(a0)",
1797 "tail __sigsetjmp_tail",
1798 );
1799}
1800
1801#[no_mangle]
1802#[unsafe(naked)]
1803#[cfg(target_arch = "riscv64")]
1804pub unsafe extern "C" fn __sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
1805 core::arch::naked_asm!(
1806 "bnez a1, 1f",
1807 "tail setjmp",
1808 "1:",
1809 "sd ra, 208(a0)",
1810 "sd s0, 224(a0)",
1811 "mv s0, a0",
1812 "call setjmp",
1813 "mv a1, a0",
1814 "mv a0, s0",
1815 "ld s0, 224(a0)",
1816 "ld ra, 208(a0)",
1817 "tail __sigsetjmp_tail",
1818 );
1819}
1820
1821#[no_mangle]
1822#[inline(never)]
1823#[cfg(target_arch = "riscv64")]
1824pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
1825 longjmp(env, val);
1826}
1827
1828#[inline]
1833unsafe fn sys_newfstatat(dirfd: i32, path: *const c_char, buf: *mut u8, flags: i32) -> i64 {
1834 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, dirfd as i64, path as i64, buf as i64, flags as i64)
1835}
1836
1837#[inline]
1838unsafe fn sys_fstat(fd: i32, buf: *mut u8) -> i64 {
1839 <Arch as Syscalls>::syscall2(SYS_FSTAT, fd as i64, buf as i64)
1840}
1841
1842#[inline]
1843unsafe fn sys_getrlimit(resource: i32, rlim: *mut u8) -> i64 {
1844 <Arch as Syscalls>::syscall2(SYS_GETRLIMIT, resource as i64, rlim as i64)
1845}
1846
1847#[inline]
1848unsafe fn sys_setrlimit(resource: i32, rlim: *const u8) -> i64 {
1849 <Arch as Syscalls>::syscall2(SYS_SETRLIMIT, resource as i64, rlim as i64)
1850}
1851
1852#[inline]
1853unsafe fn sys_utimensat(dirfd: i32, path: *const c_char, times: *const u8, flags: i32) -> i64 {
1854 <Arch as Syscalls>::syscall4(SYS_UTIMENSAT, dirfd as i64, path as i64, times as i64, flags as i64)
1855}
1856
1857#[inline]
1862unsafe fn sys_fork() -> i64 {
1863 #[cfg(target_arch = "x86_64")]
1864 { <Arch as Syscalls>::syscall0(SYS_FORK) }
1865 #[cfg(target_arch = "aarch64")]
1866 { <Arch as Syscalls>::syscall2(SYS_CLONE, 17, 0) }
1867 #[cfg(target_arch = "riscv64")]
1868 { <Arch as Syscalls>::syscall2(SYS_CLONE, 17, 0) }
1869}
1870
1871
1872#[inline]
1873unsafe fn sys_execve(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> i64 {
1874 <Arch as Syscalls>::syscall3(SYS_EXECVE, path as i64, argv as i64, envp as i64)
1875}
1876
1877#[inline]
1878unsafe fn sys_wait4(pid: c_int, status: *mut c_int, options: c_int, rusage: *mut c_void) -> i64 {
1879 <Arch as Syscalls>::syscall4(SYS_WAIT4, pid as i64, status as i64, options as i64, rusage as i64)
1880}
1881
1882#[inline]
1883unsafe fn sys_getppid() -> i64 {
1884 <Arch as Syscalls>::syscall0(SYS_GETPPID)
1885}
1886
1887#[inline]
1888unsafe fn sys_getuid() -> i64 {
1889 <Arch as Syscalls>::syscall0(SYS_GETUID)
1890}
1891
1892#[inline]
1893unsafe fn sys_getgid() -> i64 {
1894 <Arch as Syscalls>::syscall0(SYS_GETGID)
1895}
1896
1897#[inline]
1898unsafe fn sys_geteuid() -> i64 {
1899 <Arch as Syscalls>::syscall0(SYS_GETEUID)
1900}
1901
1902#[inline]
1903unsafe fn sys_getegid() -> i64 {
1904 <Arch as Syscalls>::syscall0(SYS_GETEGID)
1905}
1906
1907#[no_mangle]
1908pub unsafe extern "C" fn fork() -> c_int {
1909 __fork_handler(-1);
1910 let ret = sys_fork();
1911 if ret < 0 {
1916 let err = (-ret) as c_int;
1917 __fork_handler(0);
1918 ERRNO!() = err;
1919 return -1;
1920 }
1921 if ret == 0 {
1922 allocator_after_fork();
1923 thread_allocator_after_fork();
1924 __fork_handler(1);
1925 } else {
1926 __fork_handler(0);
1927 }
1928 ret as c_int
1929}
1930
1931#[no_mangle]
1932pub unsafe extern "C" fn execve(
1933 path: *const c_char,
1934 argv: *const *const c_char,
1935 envp: *const *const c_char,
1936) -> c_int {
1937 let r = sys_execve(path, argv, envp);
1938 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
1939 r as c_int
1940}
1941
1942#[no_mangle]
1943pub unsafe extern "C" fn wait(status: *mut c_int) -> c_int {
1944 let r = sys_wait4(-1, status, 0, core::ptr::null_mut());
1945 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
1946 r as c_int
1947}
1948
1949#[no_mangle]
1950pub unsafe extern "C" fn waitpid(pid: c_int, status: *mut c_int, options: c_int) -> c_int {
1951 let r = sys_wait4(pid, status, options, core::ptr::null_mut());
1952 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
1953 r as c_int
1954}
1955
1956#[no_mangle]
1957pub unsafe extern "C" fn getppid() -> c_int {
1958 sys_getppid() as c_int
1959}
1960
1961#[no_mangle]
1962pub unsafe extern "C" fn getuid() -> c_uint {
1963 sys_getuid() as c_uint
1964}
1965
1966#[no_mangle]
1967pub unsafe extern "C" fn getgid() -> c_uint {
1968 sys_getgid() as c_uint
1969}
1970
1971#[no_mangle]
1972pub unsafe extern "C" fn geteuid() -> c_uint {
1973 sys_geteuid() as c_uint
1974}
1975
1976#[no_mangle]
1977pub unsafe extern "C" fn getegid() -> c_uint {
1978 sys_getegid() as c_uint
1979}
1980
1981#[no_mangle]
1983pub unsafe extern "C" fn vfork() -> c_int {
1984 let r = sys_fork();
1989 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
1990 if r == 0 {
1991 allocator_after_fork();
1992 thread_allocator_after_fork();
1993 }
1994 r as c_int
1995}
1996
1997#[no_mangle]
1998pub unsafe extern "C" fn execl(path: *const c_char, arg: *const c_char, mut args: ...) -> c_int {
1999 let mut cap = 16usize;
2000 let mut argv = malloc(cap * core::mem::size_of::<*const c_char>()) as *mut *const c_char;
2001 if argv.is_null() { ERRNO!() = ENOMEM; return -1; }
2002 *argv.add(0) = arg;
2003 let mut n: usize = 1;
2004 loop {
2005 let a: *const c_char = args.next_arg();
2006 if a.is_null() { break; }
2007 if n + 1 >= cap {
2008 cap = match cap.checked_mul(2) { Some(v) => v, None => { free(argv as *mut c_void); ERRNO!() = ENOMEM; return -1; } };
2009 let grown = realloc(argv as *mut c_void, cap * core::mem::size_of::<*const c_char>()) as *mut *const c_char;
2010 if grown.is_null() { free(argv as *mut c_void); ERRNO!() = ENOMEM; return -1; }
2011 argv = grown;
2012 }
2013 *argv.add(n) = a;
2014 n += 1;
2015 }
2016 *argv.add(n) = core::ptr::null();
2017 let r = sys_execve(path, argv, __environ as *const *const c_char);
2018 free(argv as *mut c_void);
2019 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
2020}
2021
2022unsafe fn spawn_execvp(file: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> ! {
2031 let flen = strlen(file as *const c_char);
2032 let f = file as *const u8;
2033 let mut has_slash = false;
2034 for i in 0..flen {
2035 if *f.add(i) == b'/' { has_slash = true; break; }
2036 }
2037 if has_slash {
2038 sys_execve(file, argv, envp);
2039 _exit(127);
2040 }
2041 let path = getenv(b"PATH\0".as_ptr() as *const c_char);
2042 let default_path = b"/usr/local/bin:/usr/bin:/bin\0";
2043 let p = if path.is_null() { default_path.as_ptr() } else { path as *const u8 };
2044 let plen = strlen(p as *const c_char);
2045 let mut buf: [u8; 4096] = [0; 4096];
2046 let mut i: usize = 0;
2047 while i <= plen {
2048 let start = i;
2049 while i < plen && *p.add(i) != b':' { i += 1; }
2050 let dlen = i - start;
2051 if dlen > 0 && dlen + 1 + flen < 4096 {
2052 core::ptr::copy_nonoverlapping(p.add(start), buf.as_mut_ptr(), dlen);
2053 *buf.as_mut_ptr().add(dlen) = b'/';
2054 core::ptr::copy_nonoverlapping(f, buf.as_mut_ptr().add(dlen + 1), flen + 1);
2055 sys_execve(buf.as_ptr() as *const c_char, argv, envp);
2056 }
2058 i += 1; }
2060 _exit(127);
2061}
2062
2063#[no_mangle]
2064pub unsafe extern "C" fn posix_spawnp(
2065 pid: *mut c_int,
2066 file: *const c_char,
2067 fa: *const posix_spawn_file_actions_t,
2068 attrp: *const posix_spawnattr_t,
2069 argv: *const *const c_char,
2070 envp: *const *const c_char,
2071) -> c_int {
2072 let child = sys_fork();
2073 if child < 0 {
2074 ERRNO!() = EAGAIN;
2075 return -1;
2076 }
2077 if child == 0 {
2078 spawn_apply_attr(attrp);
2080 spawn_apply_actions(fa);
2081 let actual_envp = if envp.is_null() { __environ as *const *const c_char } else { envp };
2082 spawn_execvp(file, argv, actual_envp);
2083 }
2085 *pid = child as c_int;
2086 0
2087}
2088
2089#[no_mangle]
2090pub unsafe extern "C" fn posix_spawn(
2091 pid: *mut c_int,
2092 path: *const c_char,
2093 fa: *const posix_spawn_file_actions_t,
2094 attrp: *const posix_spawnattr_t,
2095 argv: *const *const c_char,
2096 envp: *const *const c_char,
2097) -> c_int {
2098 posix_spawnp(pid, path, fa, attrp, argv, envp)
2101}
2102
2103#[cfg(target_arch = "x86_64")]
2108#[repr(C)]
2109pub struct Stat {
2110 pub st_dev: u64,
2111 pub st_ino: u64,
2112 pub st_nlink: u64,
2113 pub st_mode: u32,
2114 pub st_uid: u32,
2115 pub st_gid: u32,
2116 _pad0: u32,
2117 pub st_rdev: u64,
2118 pub st_size: i64,
2119 pub st_blksize: i64,
2120 pub st_blocks: i64,
2121 pub st_atim: timespec,
2122 pub st_mtim: timespec,
2123 pub st_ctim: timespec,
2124 _unused: [i64; 3],
2125}
2126
2127#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
2128#[repr(C)]
2129pub struct Stat {
2130 pub st_dev: u64,
2131 pub st_ino: u64,
2132 pub st_mode: u32,
2133 pub st_nlink: u32,
2134 pub st_uid: u32,
2135 pub st_gid: u32,
2136 pub st_rdev: u64,
2137 __pad1: u64,
2138 pub st_size: i64,
2139 pub st_blksize: i32,
2140 __pad2: i32,
2141 pub st_blocks: i64,
2142 pub st_atim: timespec,
2143 pub st_mtim: timespec,
2144 pub st_ctim: timespec,
2145 __unused4: u32,
2146 __unused5: u32,
2147}
2148
2149pub const S_IFMT: u32 = 0o170000;
2150pub const S_IFDIR: u32 = 0o040000;
2151pub const S_IFCHR: u32 = 0o020000;
2152pub const S_IFBLK: u32 = 0o060000;
2153pub const S_IFREG: u32 = 0o100000;
2154pub const S_IFLNK: u32 = 0o120000;
2155pub const S_IFIFO: u32 = 0o010000;
2156pub const S_IFSOCK: u32 = 0o140000;
2157
2158pub const AT_FDCWD: i32 = -100;
2159
2160#[no_mangle]
2161pub unsafe extern "C" fn stat(path: *const c_char, buf: *mut Stat) -> c_int {
2162 let r = sys_newfstatat(AT_FDCWD, path, buf as *mut u8, 0);
2163 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2164 if *path == b'/' as c_char && strcmp(path as *const u8, b"/dev/null\0".as_ptr()) == 0 {
2165 (*buf).st_mode = ((*buf).st_mode & !0o170000) | 0o020000;
2166 }
2167 0
2168}
2169
2170#[no_mangle]
2171pub unsafe extern "C" fn fstat(fd: c_int, buf: *mut Stat) -> c_int {
2172 let r = sys_fstat(fd, buf as *mut u8);
2173 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
2174}
2175
2176#[repr(C)]
2181pub struct Rlimit {
2182 pub rlim_cur: u64,
2183 pub rlim_max: u64,
2184}
2185
2186pub const RLIMIT_NOFILE: c_int = 7;
2187pub const RLIMIT_STACK: c_int = 3;
2188pub const RLIMIT_DATA: c_int = 2;
2189pub const RLIMIT_AS: c_int = 9;
2190pub const RLIMIT_CPU: c_int = 0;
2191pub const RLIMIT_FSIZE: c_int = 1;
2192pub const RLIMIT_CORE: c_int = 4;
2193pub const RLIMIT_RSS: c_int = 5;
2194pub const RLIMIT_NPROC: c_int = 6;
2195pub const RLIMIT_MEMLOCK: c_int = 8;
2196pub const RLIMIT_LOCKS: c_int = 10;
2197pub const RLIMIT_SIGPENDING: c_int = 11;
2198pub const RLIMIT_MSGQUEUE: c_int = 12;
2199pub const RLIMIT_NICE: c_int = 13;
2200pub const RLIMIT_RTPRIO: c_int = 14;
2201pub const RLIMIT_RTTIME: c_int = 15;
2202pub const RLIM_INFINITY: u64 = !0u64;
2203
2204#[no_mangle]
2205pub unsafe extern "C" fn getrlimit(resource: c_int, rlim: *mut Rlimit) -> c_int {
2206 let r = sys_getrlimit(resource, rlim as *mut u8);
2207 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
2208}
2209
2210#[no_mangle]
2211pub unsafe extern "C" fn setrlimit(resource: c_int, rlim: *const Rlimit) -> c_int {
2212 let r = sys_setrlimit(resource, rlim as *const u8);
2213 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
2214}
2215
2216#[no_mangle]
2221pub unsafe extern "C" fn utimensat(dirfd: c_int, path: *const c_char, times: *const timespec, flags: c_int) -> c_int {
2222 let r = sys_utimensat(dirfd, path, times as *const u8, flags);
2223 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
2224}
2225
2226#[no_mangle]
2227pub unsafe extern "C" fn futimens(fd: c_int, times: *const timespec) -> c_int {
2228 let r = sys_utimensat(fd, core::ptr::null(), times as *const u8, 0);
2229 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
2230}
2231
2232pub const AF_UNIX: c_int = 1;
2237pub const AF_INET: c_int = 2;
2238pub const AF_INET6: c_int = 10;
2239
2240pub const SOCK_STREAM: c_int = 1;
2241pub const SOCK_DGRAM: c_int = 2;
2242
2243pub const SHUT_RD: c_int = 0;
2244pub const SHUT_WR: c_int = 1;
2245pub const SHUT_RDWR: c_int = 2;
2246
2247pub const SOL_SOCKET: c_int = 1;
2248pub const SO_REUSEADDR: c_int = 2;
2249
2250#[repr(C)]
2251pub struct sockaddr {
2252 pub sa_family: u16,
2253 pub sa_data: [u8; 14],
2254}
2255
2256#[inline]
2257unsafe fn sys_socket(domain: c_int, ty: c_int, protocol: c_int) -> i64 {
2258 <Arch as Syscalls>::syscall3(SYS_SOCKET, domain as i64, ty as i64, protocol as i64)
2259}
2260
2261#[inline]
2262unsafe fn sys_socketpair(domain: c_int, ty: c_int, protocol: c_int, sv: *mut c_int) -> i64 {
2263 <Arch as Syscalls>::syscall4(SYS_SOCKETPAIR, domain as i64, ty as i64, protocol as i64, sv as i64)
2264}
2265
2266#[inline]
2267unsafe fn sys_bind(fd: c_int, addr: *const sockaddr, len: c_uint) -> i64 {
2268 <Arch as Syscalls>::syscall3(SYS_BIND, fd as i64, addr as i64, len as i64)
2269}
2270
2271#[inline]
2272unsafe fn sys_listen(fd: c_int, backlog: c_int) -> i64 {
2273 <Arch as Syscalls>::syscall2(SYS_LISTEN, fd as i64, backlog as i64)
2274}
2275
2276#[inline]
2277unsafe fn sys_accept(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> i64 {
2278 <Arch as Syscalls>::syscall3(SYS_ACCEPT, fd as i64, addr as i64, len as i64)
2279}
2280
2281#[inline]
2282unsafe fn sys_connect(fd: c_int, addr: *const sockaddr, len: c_uint) -> i64 {
2283 <Arch as Syscalls>::syscall3(SYS_CONNECT, fd as i64, addr as i64, len as i64)
2284}
2285
2286#[inline]
2287unsafe fn sys_sendto(fd: c_int,
2288 buf: *const c_void,
2289 len: usize,
2290 flags: c_int,
2291 addr: *const sockaddr,
2292 addrlen: c_uint,) -> i64 {
2293 <Arch as Syscalls>::syscall6(SYS_SENDTO, fd as i64, buf as i64, len as i64, flags as i64, addr as i64, addrlen as i64)
2294}
2295
2296#[inline]
2297unsafe fn sys_recvfrom(fd: c_int,
2298 buf: *mut c_void,
2299 len: usize,
2300 flags: c_int,
2301 addr: *mut sockaddr,
2302 addrlen: *mut c_uint,) -> i64 {
2303 <Arch as Syscalls>::syscall6(SYS_RECVFROM, fd as i64, buf as i64, len as i64, flags as i64, addr as i64, addrlen as i64)
2304}
2305
2306#[inline]
2307unsafe fn sys_shutdown(fd: c_int, how: c_int) -> i64 {
2308 <Arch as Syscalls>::syscall2(SYS_SHUTDOWN, fd as i64, how as i64)
2309}
2310
2311#[inline]
2312unsafe fn sys_setsockopt(fd: c_int,
2313 level: c_int,
2314 optname: c_int,
2315 optval: *const c_void,
2316 optlen: c_uint,) -> i64 {
2317 <Arch as Syscalls>::syscall5(SYS_SETSOCKOPT, fd as i64, level as i64, optname as i64, optval as i64, optlen as i64)
2318}
2319
2320#[inline]
2321unsafe fn sys_getsockname(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> i64 {
2322 <Arch as Syscalls>::syscall3(SYS_GETSOCKNAME, fd as i64, addr as i64, len as i64)
2323}
2324
2325#[no_mangle]
2326pub unsafe extern "C" fn socket(domain: c_int, ty: c_int, protocol: c_int) -> c_int {
2327 let r = sys_socket(domain, ty, protocol);
2328 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2329 r as c_int
2330}
2331
2332#[no_mangle]
2333pub unsafe extern "C" fn socketpair(domain: c_int, ty: c_int, protocol: c_int, sv: *mut c_int) -> c_int {
2334 let r = sys_socketpair(domain, ty, protocol, sv);
2335 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2336 0
2337}
2338
2339#[no_mangle]
2340pub unsafe extern "C" fn bind(fd: c_int, addr: *const sockaddr, len: c_uint) -> c_int {
2341 let r = sys_bind(fd, addr, len);
2342 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2343 0
2344}
2345
2346#[no_mangle]
2347pub unsafe extern "C" fn listen(fd: c_int, backlog: c_int) -> c_int {
2348 let r = sys_listen(fd, backlog);
2349 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2350 0
2351}
2352
2353#[no_mangle]
2354pub unsafe extern "C" fn accept(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> c_int {
2355 let r = sys_accept(fd, addr, len);
2356 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2357 r as c_int
2358}
2359
2360#[no_mangle]
2361pub unsafe extern "C" fn connect(fd: c_int, addr: *const sockaddr, len: c_uint) -> c_int {
2362 let r = sys_connect(fd, addr, len);
2363 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2364 0
2365}
2366
2367#[no_mangle]
2368pub unsafe extern "C" fn send(fd: c_int, buf: *const c_void, len: usize, flags: c_int) -> isize {
2369 let r = sys_sendto(fd, buf, len, flags, core::ptr::null(), 0);
2370 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2371 r as isize
2372}
2373
2374#[no_mangle]
2375pub unsafe extern "C" fn recv(fd: c_int, buf: *mut c_void, len: usize, flags: c_int) -> isize {
2376 let r = sys_recvfrom(fd, buf, len, flags, core::ptr::null_mut(), core::ptr::null_mut());
2377 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2378 r as isize
2379}
2380
2381#[no_mangle]
2382pub unsafe extern "C" fn sendto(
2383 fd: c_int,
2384 buf: *const c_void,
2385 len: usize,
2386 flags: c_int,
2387 addr: *const sockaddr,
2388 addrlen: c_uint,
2389) -> isize {
2390 let r = sys_sendto(fd, buf, len, flags, addr, addrlen);
2391 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2392 r as isize
2393}
2394
2395#[no_mangle]
2396pub unsafe extern "C" fn recvfrom(
2397 fd: c_int,
2398 buf: *mut c_void,
2399 len: usize,
2400 flags: c_int,
2401 addr: *mut sockaddr,
2402 addrlen: *mut c_uint,
2403) -> isize {
2404 let r = sys_recvfrom(fd, buf, len, flags, addr, addrlen);
2405 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2406 r as isize
2407}
2408
2409#[no_mangle]
2410pub unsafe extern "C" fn shutdown(fd: c_int, how: c_int) -> c_int {
2411 let r = sys_shutdown(fd, how);
2412 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2413 0
2414}
2415
2416#[no_mangle]
2417pub unsafe extern "C" fn setsockopt(
2418 fd: c_int,
2419 level: c_int,
2420 optname: c_int,
2421 optval: *const c_void,
2422 optlen: c_uint,
2423) -> c_int {
2424 let r = sys_setsockopt(fd, level, optname, optval, optlen);
2425 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2426 0
2427}
2428
2429#[no_mangle]
2430pub unsafe extern "C" fn getsockname(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> c_int {
2431 let r = sys_getsockname(fd, addr, len);
2432 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2433 0
2434}
2435
2436#[no_mangle]
2437pub extern "C" fn htonl(hostlong: c_uint) -> c_uint {
2438 hostlong.to_be()
2439}
2440
2441#[no_mangle]
2442pub extern "C" fn ntohl(netlong: c_uint) -> c_uint {
2443 c_uint::from_be(netlong)
2444}
2445
2446#[no_mangle]
2447pub extern "C" fn htons(hostshort: u16) -> u16 {
2448 hostshort.to_be()
2449}
2450
2451#[no_mangle]
2452pub extern "C" fn ntohs(netshort: u16) -> u16 {
2453 u16::from_be(netshort)
2454}
2455
2456pub type PthreadT = c_ulong;
2457
2458#[repr(C)]
2460pub struct pthread_attr_t {
2461 __i: [c_int; 14],
2462}
2463
2464#[repr(C)]
2467pub struct pthread_mutex_t {
2468 __i: [c_int; 10],
2469}
2470
2471#[repr(C)]
2472pub struct pthread_mutexattr_t {
2473 __attr: c_uint,
2474}
2475
2476#[repr(C)]
2479pub struct pthread_cond_t {
2480 __i: [c_int; 12],
2481}
2482
2483#[repr(C)]
2484pub struct pthread_condattr_t {
2485 __attr: c_uint,
2486}
2487
2488#[repr(C)]
2491pub struct pthread_rwlock_t {
2492 __i: [c_int; 14],
2493}
2494
2495#[repr(C)]
2496pub struct pthread_rwlockattr_t {
2497 __attr: [c_uint; 2],
2498}
2499
2500#[repr(C)]
2502pub struct pthread_barrier_t {
2503 __i: [c_int; 8],
2504}
2505
2506#[repr(C)]
2507pub struct pthread_barrierattr_t {
2508 __attr: c_uint,
2509}
2510
2511pub type pthread_spinlock_t = c_int;
2512pub type pthread_once_t = c_int;
2513pub type pthread_key_t = c_uint;
2514
2515#[repr(C)]
2517pub struct sem_t {
2518 __val: [c_int; 8],
2519}
2520
2521#[repr(C)]
2522pub struct sched_param {
2523 pub sched_priority: c_int,
2524}
2525
2526const CLONE_VM: c_ulong = 0x00000100;
2527const CLONE_FS: c_ulong = 0x00000200;
2528const CLONE_FILES: c_ulong = 0x00000400;
2529const CLONE_SIGHAND: c_ulong = 0x00000800;
2530const CLONE_THREAD: c_ulong = 0x00010000;
2531const CLONE_SYSVSEM: c_ulong = 0x00040000;
2532const CLONE_SETTLS: c_ulong = 0x00080000;
2533const CLONE_PARENT_SETTID: c_ulong = 0x00100000;
2534const CLONE_CHILD_CLEARTID: c_ulong = 0x00200000;
2535
2536const FUTEX_WAIT: c_int = 0;
2537const FUTEX_WAKE: c_int = 1;
2538const FUTEX_LOCK_PI: c_int = 6;
2539const FUTEX_UNLOCK_PI: c_int = 7;
2540const FUTEX_TRYLOCK_PI: c_int = 8;
2541
2542const SIGCANCEL: c_int = 32;
2544
2545const PTHREAD_MUTEX_NORMAL: c_int = 0;
2546const PTHREAD_MUTEX_DEFAULT: c_int = 0;
2547const PTHREAD_MUTEX_RECURSIVE: c_int = 1;
2548const PTHREAD_MUTEX_ERRORCHECK: c_int = 2;
2549
2550const PTHREAD_CREATE_JOINABLE: c_int = 0;
2551const PTHREAD_CREATE_DETACHED: c_int = 1;
2552
2553const PTHREAD_CANCEL_ENABLE: c_int = 0;
2554const PTHREAD_CANCEL_DISABLE: c_int = 1;
2555const PTHREAD_CANCEL_DEFERRED: c_int = 0;
2556const PTHREAD_CANCEL_ASYNCHRONOUS: c_int = 1;
2557
2558const PTHREAD_SCOPE_SYSTEM: c_int = 0;
2559const PTHREAD_PROCESS_PRIVATE: c_int = 0;
2560const PTHREAD_PROCESS_SHARED: c_int = 1;
2561const PTHREAD_INHERIT_SCHED: c_int = 0;
2562const PTHREAD_EXPLICIT_SCHED: c_int = 1;
2563
2564const PTHREAD_BARRIER_SERIAL_THREAD: c_int = -1;
2565
2566const PTHREAD_KEYS_MAX: usize = 128;
2567const PTHREAD_DESTRUCTOR_ITERATIONS: usize = 4;
2568const SEM_VALUE_MAX: c_int = 0x7fffffff;
2569
2570const DT_EXITED: c_int = 0;
2571const DT_EXITING: c_int = 1;
2572const DT_JOINABLE: c_int = 2;
2573const DT_DETACHED: c_int = 3;
2574
2575#[repr(C)]
2577#[derive(Copy, Clone)]
2578pub struct __ptcb {
2579 __f: Option<unsafe extern "C" fn(*mut c_void)>,
2580 __x: *mut c_void,
2581 __next: *mut __ptcb,
2582}
2583
2584#[repr(C)]
2586#[derive(Copy, Clone)]
2587struct robust_list {
2588 next: *mut robust_list,
2589}
2590
2591#[repr(C)]
2592#[derive(Copy, Clone)]
2593struct robust_list_head {
2594 list: robust_list,
2595 futex_offset: c_long,
2596 pending: *mut robust_list,
2597}
2598
2599#[cfg(all(target_arch = "x86_64", not(test)))]
2601core::arch::global_asm!(
2602 ".global __rc_clone",
2603 ".type __rc_clone, @function",
2604 "__rc_clone:",
2605 "mov rax, rdi",
2606 "mov rdi, rdx",
2607 "mov rdx, r8",
2608 "mov r10, [rsp + 8]",
2609 "mov r8, r9",
2610 "mov r9, rax",
2611 "and rsi, -16",
2612 "sub rsi, 8",
2613 "mov [rsi], rcx",
2614 "mov eax, 56",
2615 "syscall",
2616 "test rax, rax",
2617 "jnz 1f",
2618 "pop rdi",
2619 "call r9",
2620 "mov edi, eax",
2623 "mov eax, 60",
2624 "syscall",
2625 "hlt",
2626 "1:",
2627 "ret",
2628);
2629
2630#[no_mangle]
2632#[unsafe(naked)]
2633#[cfg(target_arch = "aarch64")]
2634pub unsafe extern "C" fn __rc_clone(
2635 fn_: usize,
2636 stack: *mut u8,
2637 flags: c_ulong,
2638 arg: *mut c_void,
2639 ptid: *mut c_int,
2640 tls: c_ulong,
2641 ctid: *mut c_int,
2642) -> i64 {
2643 core::arch::naked_asm!(
2644 "and x1, x1, #-16",
2645 "stp x0, x3, [x1, #-16]!",
2646 "uxtw x0, w2",
2647 "mov x2, x4",
2648 "mov x3, x5",
2649 "mov x4, x6",
2650 "mov x8, #220",
2651 "svc #0",
2652 "cbz x0, 1f",
2653 "ret",
2654 "1:",
2655 "mov x29, #0",
2656 "ldp x1, x0, [sp], #16",
2657 "blr x1",
2658 "mov x8, #93",
2659 "svc #0",
2660 );
2661}
2662
2663#[no_mangle]
2664#[unsafe(naked)]
2665#[cfg(target_arch = "riscv64")]
2666pub unsafe extern "C" fn __rc_clone(
2667 fn_: usize,
2668 stack: *mut u8,
2669 flags: c_ulong,
2670 arg: *mut c_void,
2671 ptid: *mut c_int,
2672 tls: c_ulong,
2673 ctid: *mut c_int,
2674) -> i64 {
2675 core::arch::naked_asm!(
2676 "andi a1, a1, -16",
2677 "addi a1, a1, -16",
2678 "sd a0, 0(a1)",
2679 "sd a3, 8(a1)",
2680 "mv a0, a2",
2681 "mv a2, a4",
2682 "mv a3, a5",
2683 "mv a4, a6",
2684 "li a7, 220",
2685 "ecall",
2686 "beqz a0, 1f",
2687 "ret",
2688 "1:",
2689 "ld a1, 0(sp)",
2690 "ld a0, 8(sp)",
2691 "jalr a1",
2692 "li a7, 93",
2693 "ecall",
2694 );
2695}
2696
2697#[cfg(all(target_arch = "x86_64", test))]
2698#[inline(never)]
2699unsafe fn __rc_clone(
2700 _fn_: usize,
2701 _stack: *mut u8,
2702 _flags: c_ulong,
2703 _arg: *mut c_void,
2704 _ptid: *mut c_int,
2705 _tls: c_ulong,
2706 _ctid: *mut c_int,
2707) -> i64 {
2708 -1
2709}
2710
2711#[cfg(all(target_arch = "x86_64", not(test)))]
2712extern "C" {
2713 fn __rc_clone(
2714 fn_: usize,
2715 stack: *mut u8,
2716 flags: c_ulong,
2717 arg: *mut c_void,
2718 ptid: *mut c_int,
2719 tls: c_ulong,
2720 ctid: *mut c_int,
2721 ) -> i64;
2722}
2723
2724#[inline(never)]
2725#[linkage = "weak"]
2726#[no_mangle]
2727pub extern "C" fn __rc_create_thread_tls() -> *mut u8 {
2728 core::ptr::null_mut()
2729}
2730
2731#[inline(never)]
2732#[linkage = "weak"]
2733#[no_mangle]
2734pub unsafe extern "C" fn __rc_init_thread_tls_at(_block: *mut u8) -> *mut u8 {
2735 core::ptr::null_mut()
2736}
2737
2738#[inline(never)]
2739#[linkage = "weak"]
2740#[no_mangle]
2741pub extern "C" fn __rc_tls_block_size() -> usize {
2742 0
2743}
2744
2745#[inline(never)]
2746#[linkage = "weak"]
2747#[no_mangle]
2748pub extern "C" fn __rc_tls_base_offset() -> usize {
2749 0
2750}
2751
2752#[inline]
2753unsafe fn sys_gettid() -> i64 {
2754 <Arch as Syscalls>::syscall0(SYS_GETTID)
2755}
2756
2757#[inline]
2758unsafe fn sys_futex(uaddr: *mut c_int,
2759 futex_op: c_int,
2760 val: c_int,
2761 timeout: *mut c_void,
2762 uaddr2: *mut c_int,
2763 val3: c_int,) -> i64 {
2764 <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)
2765}
2766
2767const THREAD_CHUNK: usize = 1024;
2768const STACK_SIZE: usize = 1024 * 1024;
2769const THREAD_TCB_OFFSET: usize = 0x40;
2772
2773#[repr(C)]
2774#[derive(Copy, Clone)]
2775struct Thread {
2776 tid: c_int,
2777 detach_state: c_int,
2778 result: *mut c_void,
2779 cancel: c_int,
2780 cancel_state: c_int,
2781 cancel_type: c_int,
2782 user_fn: usize,
2783 user_arg: *mut c_void,
2784 stack: *mut u8,
2785 stack_size: usize,
2786 stack_owned: bool,
2787 fs_base: *mut u8,
2788 tls_base: *mut u8,
2793 tls_size: usize,
2794 tsd: [*mut c_void; PTHREAD_KEYS_MAX],
2795 cancelbuf: *mut __ptcb,
2796 robust_list: robust_list_head,
2797 free_next: *mut Thread,
2798}
2799
2800static mut THREADS: [Thread; THREAD_CHUNK] = [Thread {
2801 tid: -1,
2802 detach_state: DT_JOINABLE,
2803 result: core::ptr::null_mut(),
2804 cancel: 0,
2805 cancel_state: PTHREAD_CANCEL_ENABLE,
2806 cancel_type: PTHREAD_CANCEL_DEFERRED,
2807 user_fn: 0,
2808 user_arg: core::ptr::null_mut(),
2809 stack: core::ptr::null_mut(),
2810 stack_size: 0,
2811 stack_owned: false,
2812 fs_base: core::ptr::null_mut(),
2813 tls_base: core::ptr::null_mut(),
2814 tls_size: 0,
2815 tsd: [core::ptr::null_mut(); PTHREAD_KEYS_MAX],
2816 cancelbuf: core::ptr::null_mut(),
2817 robust_list: robust_list_head {
2818 list: robust_list { next: core::ptr::null_mut() },
2819 futex_offset: 0,
2820 pending: core::ptr::null_mut(),
2821 },
2822 free_next: core::ptr::null_mut(),
2823}; THREAD_CHUNK];
2824#[repr(C)]
2825struct ThreadChunk {
2826 next: *mut ThreadChunk,
2827 base: *mut Thread,
2828}
2829static THREAD_CHUNK_LIST: AtomicPtr<ThreadChunk> =
2830 AtomicPtr::new(core::ptr::null_mut());
2831static EXTRA_CHUNK_COUNT: AtomicUsize = AtomicUsize::new(0);
2832static mut FREE_THREADS: *mut Thread = core::ptr::null_mut();
2835static mut THREAD_TABLE_READY: bool = false;
2836static mut THREAD_LOCK: c_int = 0;
2837static mut THREAD_WAITERS: c_int = 0;
2838static ACTIVE_THREADS: AtomicUsize = AtomicUsize::new(0);
2839static mut KEY_DTORS: [Option<unsafe extern "C" fn(*mut c_void)>; PTHREAD_KEYS_MAX] = [None; PTHREAD_KEYS_MAX];
2840static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
2841
2842unsafe fn futex_wait(addr: *mut c_int, expected: c_int) -> c_int {
2844 let r = sys_futex(addr, FUTEX_WAIT, expected, null_mut(), null_mut(), 0);
2845 if r < 0 { let e = (-r) as c_int; if e == EAGAIN { 0 } else { e } } else { 0 }
2846}
2847
2848unsafe fn futex_wake(addr: *mut c_int, count: c_int) {
2849 let c = if count < 0 { c_int::MAX } else { count };
2850 sys_futex(addr, FUTEX_WAKE, c, null_mut(), null_mut(), 0);
2851}
2852
2853unsafe fn futex_lock_pi(addr: *mut c_int, abs_timeout: *const timespec) -> c_int {
2854 let timeout_ptr = if abs_timeout.is_null() { null_mut() } else { abs_timeout as *mut c_void };
2855 let r = sys_futex(addr, FUTEX_LOCK_PI, 0, timeout_ptr, null_mut(), 0);
2856 if r < 0 { (-r) as c_int } else { 0 }
2857}
2858
2859unsafe fn futex_unlock_pi(addr: *mut c_int) -> c_int {
2860 let r = sys_futex(addr, FUTEX_UNLOCK_PI, 0, null_mut(), null_mut(), 0);
2861 if r < 0 { (-r) as c_int } else { 0 }
2862}
2863
2864#[inline]
2865unsafe fn sys_set_robust_list(head: *mut robust_list_head, len: usize) -> i64 {
2866 <Arch as Syscalls>::syscall2(SYS_SET_ROBUST_LIST, head as i64, len as i64)
2867}
2868
2869unsafe fn futex_timedwait(addr: *mut c_int, expected: c_int, abs_timeout: *const timespec) -> c_int {
2870 if abs_timeout.is_null() { return futex_wait(addr, expected); }
2871 let mut now: timespec = core::mem::zeroed();
2872 if sys_clock_gettime(CLOCK_REALTIME, &mut now) < 0 { return EINVAL; }
2873 let mut rel: timespec = core::mem::zeroed();
2874 rel.tv_sec = (*abs_timeout).tv_sec - now.tv_sec;
2875 rel.tv_nsec = (*abs_timeout).tv_nsec - now.tv_nsec;
2876 if rel.tv_nsec < 0 { rel.tv_sec -= 1; rel.tv_nsec += 1_000_000_000; }
2877 if rel.tv_sec < 0 { return ETIMEDOUT; }
2878 let r = sys_futex(addr, FUTEX_WAIT, expected, &mut rel as *mut timespec as *mut c_void, null_mut(), 0);
2879 if r < 0 { let e = (-r) as c_int; if e == EAGAIN { 0 } else { e } } else { 0 }
2880}
2881
2882unsafe fn a_cas(addr: *mut c_int, expected: c_int, desired: c_int) -> c_int {
2884 let a = &*(addr as *const AtomicI32);
2885 match a.compare_exchange(expected, desired, Ordering::AcqRel, Ordering::Acquire) {
2886 Ok(v) | Err(v) => v,
2887 }
2888}
2889
2890unsafe fn a_store(addr: *mut c_int, val: c_int) {
2891 (*(addr as *const AtomicI32)).store(val, Ordering::Release);
2892}
2893
2894unsafe fn a_load(addr: *const c_int) -> c_int {
2895 (*(addr as *const AtomicI32)).load(Ordering::Acquire)
2896}
2897
2898unsafe fn a_swap(addr: *mut c_int, val: c_int) -> c_int {
2899 (*(addr as *const AtomicI32)).swap(val, Ordering::AcqRel)
2900}
2901
2902unsafe fn a_fetch_add(addr: *mut c_int, val: c_int) -> c_int {
2903 (*(addr as *const AtomicI32)).fetch_add(val, Ordering::AcqRel)
2904}
2905
2906unsafe fn a_fetch_sub(addr: *mut c_int, val: c_int) -> c_int {
2907 (*(addr as *const AtomicI32)).fetch_sub(val, Ordering::AcqRel)
2908}
2909
2910unsafe fn spinlock_lock(lock: *mut c_int, waiters: *mut c_int) {
2911 while a_swap(lock, 1) != 0 {
2912 let mut spins = 100;
2913 while spins > 0 && a_load(lock) != 0 { core::hint::spin_loop(); spins -= 1; }
2914 if a_load(lock) == 0 { continue; }
2915 a_fetch_add(waiters, 1);
2916 futex_wait(lock, 1);
2917 a_fetch_sub(waiters, 1);
2918 }
2919}
2920
2921unsafe fn spinlock_unlock(lock: *mut c_int, waiters: *mut c_int) {
2922 a_store(lock, 0);
2923 if a_load(waiters) > 0 { futex_wake(lock, 1); }
2924}
2925
2926unsafe fn thread_slot_count() -> usize {
2927 THREAD_CHUNK + EXTRA_CHUNK_COUNT.load(Ordering::Acquire) * THREAD_CHUNK
2928}
2929
2930unsafe fn thread_slot_at(index: usize) -> *mut Thread {
2931 if index < THREAD_CHUNK {
2932 core::ptr::addr_of_mut!(THREADS[index])
2933 } else {
2934 let extra = index - THREAD_CHUNK;
2935 let chunk_index = extra / THREAD_CHUNK;
2936 let offset = extra % THREAD_CHUNK;
2937 let mut chunk = THREAD_CHUNK_LIST.load(Ordering::Acquire);
2938 let mut i = 0usize;
2939 while i < chunk_index && !chunk.is_null() {
2940 chunk = (*chunk).next;
2941 i += 1;
2942 }
2943 if chunk.is_null() {
2944 return core::ptr::null_mut();
2945 }
2946 (*chunk).base.add(offset)
2947 }
2948}
2949
2950unsafe fn release_thread_slot(slot: *const Thread) {
2951 let slot = slot as *mut Thread;
2952 spinlock_lock(&raw mut THREAD_LOCK, &raw mut THREAD_WAITERS);
2953 (*slot).tid = -1;
2954 (*slot).free_next = FREE_THREADS;
2955 FREE_THREADS = slot;
2956 spinlock_unlock(&raw mut THREAD_LOCK, &raw mut THREAD_WAITERS);
2957}
2958
2959unsafe fn alloc_thread_slot() -> Option<&'static mut Thread> {
2960 spinlock_lock(&raw mut THREAD_LOCK, &raw mut THREAD_WAITERS);
2961 if !THREAD_TABLE_READY {
2962 let mut i = THREAD_CHUNK;
2963 while i > 0 {
2964 i -= 1;
2965 let slot = &mut THREADS[i];
2966 slot.free_next = FREE_THREADS;
2967 FREE_THREADS = slot;
2968 }
2969 THREAD_TABLE_READY = true;
2970 }
2971 let mut slot = FREE_THREADS;
2972 if slot.is_null() {
2973 let bytes = core::mem::size_of::<ThreadChunk>()
2974 + THREAD_CHUNK * core::mem::size_of::<Thread>();
2975 let raw = sys_mmap(
2976 core::ptr::null_mut(),
2977 bytes,
2978 PROT_READ | PROT_WRITE,
2979 MAP_PRIVATE | MAP_ANONYMOUS,
2980 -1,
2981 0,
2982 ) as *mut u8;
2983 if raw.is_null() || raw == MMAP_FAILED {
2984 spinlock_unlock(&raw mut THREAD_LOCK, &raw mut THREAD_WAITERS);
2985 return None;
2986 }
2987 let header = raw as *mut ThreadChunk;
2988 let base = raw.add(core::mem::size_of::<ThreadChunk>()) as *mut Thread;
2989 (*header).base = base;
2990 let mut i = THREAD_CHUNK;
2991 while i > 1 {
2992 i -= 1;
2993 let s = base.add(i);
2994 (*s).free_next = FREE_THREADS;
2995 FREE_THREADS = s;
2996 }
2997 (*header).next = THREAD_CHUNK_LIST.load(Ordering::Relaxed);
2998 THREAD_CHUNK_LIST.store(header, Ordering::Release);
2999 EXTRA_CHUNK_COUNT.fetch_add(1, Ordering::AcqRel);
3000 slot = base;
3001 } else {
3002 FREE_THREADS = (*slot).free_next;
3003 (*slot).free_next = core::ptr::null_mut();
3004 }
3005 spinlock_unlock(&raw mut THREAD_LOCK, &raw mut THREAD_WAITERS);
3006 Some(&mut *slot)
3007}
3008
3009unsafe fn thread_allocator_after_fork() {
3013 a_store(&raw mut THREAD_LOCK, 0);
3014 a_store(&raw mut THREAD_WAITERS, 0);
3015 if !THREAD_TABLE_READY {
3016 return;
3017 }
3018 let tp = tcb_slot(THREAD_TCB_OFFSET);
3019 let current = if tp.is_null() {
3020 core::ptr::null_mut()
3021 } else {
3022 core::ptr::read_unaligned(tp) as *mut Thread
3023 };
3024 let child_tid = sys_gettid() as c_int;
3025 let count = thread_slot_count();
3026 let mut free = core::ptr::null_mut();
3027 let mut active = 0usize;
3028 let mut i = 0usize;
3029 while i < count {
3030 let slot = thread_slot_at(i);
3031 if slot == current {
3032 (*slot).tid = child_tid;
3033 (*slot).free_next = core::ptr::null_mut();
3034 active += 1;
3035 } else {
3036 (*slot).tid = -1;
3037 (*slot).free_next = free;
3038 free = slot;
3039 }
3040 i += 1;
3041 }
3042 FREE_THREADS = free;
3043 ACTIVE_THREADS.store(active, Ordering::Release);
3044}
3045
3046unsafe fn run_key_dtors(slot: &mut Thread) {
3047 for _ in 0..PTHREAD_DESTRUCTOR_ITERATIONS {
3048 let mut any = false;
3049 for i in 0..PTHREAD_KEYS_MAX {
3050 let val = slot.tsd[i];
3051 if !val.is_null() {
3052 if let Some(dtor) = KEY_DTORS[i] {
3053 slot.tsd[i] = core::ptr::null_mut();
3054 any = true;
3055 dtor(val);
3056 }
3057 }
3058 }
3059 if !any { break; }
3060 }
3061}
3062
3063unsafe extern "C" fn thread_entry(slot: *mut c_void) -> *mut c_void {
3064 let slot = &mut *(slot as *mut Thread);
3065 let tp = tcb_slot(THREAD_TCB_OFFSET);
3066 if !tp.is_null() {
3067 core::ptr::write_unaligned(tp, slot as *mut Thread as usize);
3068 }
3069 slot.robust_list.list.next = core::ptr::null_mut();
3072 slot.robust_list.futex_offset = 0;
3073 slot.robust_list.pending = core::ptr::null_mut();
3074 ensure_robust_list(slot);
3075 let mut set: SigSetT = 0;
3076 sigemptyset(&mut set);
3077 sigaddset(&mut set, SIGCANCEL);
3078 pthread_sigmask(SIG_UNBLOCK, &set, core::ptr::null_mut());
3079 let user_fn: unsafe extern "C" fn(*mut c_void) -> *mut c_void =
3080 core::mem::transmute::<usize, _>(slot.user_fn);
3081 let ret = user_fn(slot.user_arg);
3082 run_key_dtors(slot);
3083 vdso_getrandom_thread_exit();
3084 slot.result = ret;
3085 a_store(&raw mut slot.detach_state, DT_EXITED);
3086 futex_wake(&raw mut slot.detach_state, 1);
3087 if ACTIVE_THREADS.fetch_sub(1, Ordering::AcqRel) <= 1 {
3088 exit(0);
3089 }
3090 sys_exit_thread(0)
3091}
3092
3093unsafe fn register_current_thread() -> Option<&'static mut Thread> {
3094 let me = sys_gettid() as c_int;
3095 let slot_ref = alloc_thread_slot()?;
3096 let slot = slot_ref as *mut Thread;
3097 (*slot).tid = me;
3098 (*slot).detach_state = DT_JOINABLE;
3099 (*slot).result = core::ptr::null_mut();
3100 (*slot).cancel = 0;
3101 (*slot).cancel_state = PTHREAD_CANCEL_ENABLE;
3102 (*slot).cancel_type = PTHREAD_CANCEL_DEFERRED;
3103 (*slot).cancelbuf = core::ptr::null_mut();
3104 core::ptr::write_bytes((*slot).tsd.as_mut_ptr(), 0, PTHREAD_KEYS_MAX);
3105 (*slot).robust_list.list.next = core::ptr::null_mut();
3106 (*slot).robust_list.futex_offset = 0;
3107 (*slot).robust_list.pending = core::ptr::null_mut();
3108 let tp = tcb_slot(THREAD_TCB_OFFSET);
3109 if !tp.is_null() {
3110 core::ptr::write_unaligned(tp, slot as usize);
3111 }
3112 ACTIVE_THREADS.fetch_add(1, Ordering::AcqRel);
3113 Some(&mut *slot)
3114}
3115
3116unsafe fn find_thread() -> Option<&'static mut Thread> {
3117 let me = sys_gettid() as c_int;
3118 let tp = tcb_slot(THREAD_TCB_OFFSET);
3119 if !tp.is_null() {
3120 let p = core::ptr::read_unaligned(tp) as *mut Thread;
3121 if !p.is_null() && (*p).tid == me {
3122 return Some(&mut *p);
3123 }
3124 }
3125 let count = thread_slot_count();
3126 let mut i = 0usize;
3127 while i < count {
3128 let slot = thread_slot_at(i);
3129 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3130 if !tp.is_null() {
3131 core::ptr::write_unaligned(tp, slot as usize);
3132 }
3133 return Some(&mut *slot);
3134 }
3135 i += 1;
3136 }
3137 register_current_thread()
3138}
3139
3140#[no_mangle]
3141pub unsafe extern "C" fn pthread_self() -> PthreadT {
3142 match find_thread() {
3143 Some(slot) => slot as *mut Thread as PthreadT,
3144 None => 0,
3145 }
3146}
3147
3148#[no_mangle]
3149pub unsafe extern "C" fn pthread_equal(t1: PthreadT, t2: PthreadT) -> c_int {
3150 (t1 == t2) as c_int
3151}
3152
3153#[no_mangle]
3154pub unsafe extern "C" fn pthread_create(
3155 thread: *mut PthreadT,
3156 attr: *const pthread_attr_t,
3157 start_routine: usize,
3158 arg: *mut c_void,
3159) -> c_int {
3160 if start_routine == 0 || thread.is_null() { return EINVAL; }
3161 let Some(slot_ref) = alloc_thread_slot() else { return EAGAIN; };
3162 let slot = slot_ref as *mut Thread;
3163 let stack_size = if !attr.is_null() {
3164 let s = *((*attr).__i.as_ptr() as *const usize);
3165 if s > 0 { s } else { STACK_SIZE }
3166 } else { STACK_SIZE };
3167 let user_top = if !attr.is_null() {
3169 *((*attr).__i.as_ptr().add(4) as *const *mut c_void)
3170 } else {
3171 core::ptr::null_mut()
3172 };
3173 let stack_owned = user_top.is_null();
3174 let stack = if stack_owned {
3175 sys_mmap(null_mut(), stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
3176 } else {
3177 (user_top as *mut u8).sub(stack_size)
3178 };
3179 if stack == MMAP_FAILED { release_thread_slot(slot); return EAGAIN; }
3180 let static_mode = RC_STATIC_EXEC;
3181 let tls_total = if static_mode {
3182 STATIC_TLS_BLOCK_SIZE
3183 } else {
3184 __rc_tls_block_size()
3185 };
3186 let mut stack_top = stack.add(stack_size);
3187 let mut tls_owned = true;
3188 let fs_base = if static_mode {
3189 if !stack_owned && tls_total > 0 && stack_size > tls_total + 4096 {
3190 let block = ((user_top as usize - tls_total) & !63usize) as *mut u8;
3191 let fs = static_tls_init_block(block);
3192 if fs.is_null() {
3193 static_tls_create_block()
3194 } else {
3195 stack_top = block;
3196 tls_owned = false;
3197 fs
3198 }
3199 } else {
3200 static_tls_create_block()
3201 }
3202 } else if !stack_owned && tls_total > 0 && stack_size > tls_total + 4096 {
3203 let block = ((user_top as usize - tls_total) & !63usize) as *mut u8;
3207 let fs = __rc_init_thread_tls_at(block);
3208 if fs.is_null() {
3209 __rc_create_thread_tls()
3210 } else {
3211 stack_top = block;
3212 tls_owned = false;
3213 fs
3214 }
3215 } else {
3216 __rc_create_thread_tls()
3217 };
3218 if fs_base.is_null() {
3219 if stack_owned { sys_munmap(stack, stack_size); }
3220 release_thread_slot(slot);
3221 return EAGAIN;
3222 }
3223 let tls_base = if static_mode {
3224 fs_base.sub(STATIC_TLS_TP_OFFSET)
3225 } else {
3226 fs_base.sub(__rc_tls_base_offset())
3227 };
3228 let tls_size = if tls_owned { tls_total } else { 0 };
3229 (*slot).detach_state = DT_JOINABLE;
3230 (*slot).result = core::ptr::null_mut();
3231 (*slot).cancel = 0;
3232 (*slot).cancel_state = PTHREAD_CANCEL_ENABLE;
3233 (*slot).cancel_type = PTHREAD_CANCEL_DEFERRED;
3234 core::ptr::write_bytes((*slot).tsd.as_mut_ptr(), 0, PTHREAD_KEYS_MAX);
3235 (*slot).tid = 1;
3236 (*slot).user_fn = start_routine;
3237 (*slot).user_arg = arg;
3238 (*slot).stack = stack;
3239 (*slot).stack_size = stack_size;
3240 (*slot).stack_owned = stack_owned;
3241 (*slot).fs_base = fs_base;
3242 (*slot).tls_base = tls_base;
3243 (*slot).tls_size = tls_size;
3244 let tid_ptr = &raw mut (*slot).tid;
3245 let flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD
3246 | CLONE_SYSVSEM | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_SETTLS;
3247 ACTIVE_THREADS.fetch_add(1, Ordering::AcqRel);
3248 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);
3249 if tid < 0 {
3250 ACTIVE_THREADS.fetch_sub(1, Ordering::AcqRel);
3251 (*slot).tid = -1;
3252 if stack_owned { sys_munmap(stack, stack_size); }
3253 if tls_size > 0 { sys_munmap(tls_base, tls_size); }
3254 release_thread_slot(slot);
3255 return EAGAIN;
3256 }
3257 if !attr.is_null() && (*attr).__i[6] == PTHREAD_CREATE_DETACHED {
3258 (*slot).detach_state = DT_DETACHED;
3259 }
3260 *thread = slot as PthreadT;
3261 0
3262}
3263
3264#[no_mangle]
3265pub unsafe extern "C" fn pthread_join(thread: PthreadT, retval: *mut *mut c_void) -> c_int {
3266 let slot = thread as *mut Thread;
3267 if slot.is_null() { return EINVAL; }
3268 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
3269 let tid_ptr = &raw mut (*slot).tid;
3270 loop {
3271 pthread_testcancel();
3272 let tid = core::ptr::read_volatile(tid_ptr);
3273 if tid == 0 { break; }
3274 if tid < 0 { return EINVAL; }
3275 sys_futex(tid_ptr, FUTEX_WAIT, tid, null_mut(), null_mut(), 0);
3276 pthread_testcancel();
3277 }
3278 if !retval.is_null() { *retval = (*slot).result; }
3279 let stack = (*slot).stack;
3280 let stack_size = (*slot).stack_size;
3281 let stack_owned = (*slot).stack_owned;
3282 let tls_base = (*slot).tls_base;
3283 let tls_size = (*slot).tls_size;
3284 (*slot).tid = -1;
3285 (*slot).detach_state = DT_JOINABLE;
3286 (*slot).result = core::ptr::null_mut();
3287 (*slot).stack = core::ptr::null_mut();
3288 (*slot).stack_size = 0;
3289 (*slot).stack_owned = false;
3290 (*slot).fs_base = core::ptr::null_mut();
3291 (*slot).tls_base = core::ptr::null_mut();
3292 (*slot).tls_size = 0;
3293 if stack_owned && !stack.is_null() && stack_size > 0 { sys_munmap(stack, stack_size); }
3294 let _ = (tls_base, tls_size);
3304 release_thread_slot(slot);
3305 0
3306}
3307
3308#[no_mangle]
3309pub unsafe extern "C" fn pthread_detach(thread: PthreadT) -> c_int {
3310 let slot = thread as *mut Thread;
3311 if slot.is_null() { return EINVAL; }
3312 let old = a_cas(&raw mut (*slot).detach_state, DT_JOINABLE, DT_DETACHED);
3313 if old == DT_EXITED {
3314 let stack = (*slot).stack;
3315 let stack_size = (*slot).stack_size;
3316 let stack_owned = (*slot).stack_owned;
3317 let tls_base = (*slot).tls_base;
3318 let tls_size = (*slot).tls_size;
3319 (*slot).tid = -1;
3320 (*slot).stack = core::ptr::null_mut();
3321 (*slot).stack_size = 0;
3322 (*slot).stack_owned = false;
3323 (*slot).fs_base = core::ptr::null_mut();
3324 (*slot).tls_base = core::ptr::null_mut();
3325 (*slot).tls_size = 0;
3326 if stack_owned && !stack.is_null() && stack_size > 0 { sys_munmap(stack, stack_size); }
3327 let _ = (tls_base, tls_size);
3329 release_thread_slot(slot);
3330 }
3331 0
3332}
3333
3334#[no_mangle]
3335pub unsafe extern "C" fn pthread_exit(retval: *mut c_void) -> ! {
3336 if let Some(slot) = find_thread() {
3337 run_cleanup_handlers(slot);
3338 run_key_dtors(slot);
3339 vdso_getrandom_thread_exit();
3340 slot.result = retval;
3341 slot.detach_state = DT_EXITED;
3342 futex_wake(&slot.detach_state as *const c_int as *mut c_int, 1);
3343
3344 if ACTIVE_THREADS.fetch_sub(1, Ordering::AcqRel) <= 1 {
3346 exit(0);
3347 }
3348 }
3349 sys_exit_thread(0);
3350}
3351
3352#[no_mangle]
3354pub unsafe extern "C" fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int {
3355 core::ptr::write_bytes(attr, 0, 1);
3356 *((*attr).__i.as_mut_ptr() as *mut usize) = STACK_SIZE;
3357 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = 4096;
3358 (*attr).__i[6] = PTHREAD_CREATE_JOINABLE;
3359 (*attr).__i[7] = PTHREAD_INHERIT_SCHED;
3360 0
3361}
3362#[no_mangle]
3363pub unsafe extern "C" fn pthread_attr_destroy(_attr: *mut pthread_attr_t) -> c_int { 0 }
3364#[no_mangle]
3365pub unsafe extern "C" fn pthread_attr_setdetachstate(attr: *mut pthread_attr_t, s: c_int) -> c_int {
3366 if s != PTHREAD_CREATE_JOINABLE && s != PTHREAD_CREATE_DETACHED { return EINVAL; }
3367 (*attr).__i[6] = s; 0
3368}
3369#[no_mangle]
3370pub unsafe extern "C" fn pthread_attr_getdetachstate(attr: *const pthread_attr_t, s: *mut c_int) -> c_int {
3371 *s = (*attr).__i[6]; 0
3372}
3373#[no_mangle]
3374pub unsafe extern "C" fn pthread_attr_setstacksize(attr: *mut pthread_attr_t, sz: usize) -> c_int {
3375 if sz < 2048 { return EINVAL; }
3376 *((*attr).__i.as_mut_ptr() as *mut usize) = sz;
3377 *((*attr).__i.as_mut_ptr().add(4) as *mut *mut c_void) = core::ptr::null_mut();
3378 0
3379}
3380#[no_mangle]
3381pub unsafe extern "C" fn pthread_attr_getstacksize(attr: *const pthread_attr_t, sz: *mut usize) -> c_int {
3382 *sz = *((*attr).__i.as_ptr() as *const usize); 0
3383}
3384#[no_mangle]
3385pub unsafe extern "C" fn pthread_attr_setstack(attr: *mut pthread_attr_t, addr: *mut c_void, sz: usize) -> c_int {
3386 if sz < 2048 { return EINVAL; }
3387 *((*attr).__i.as_mut_ptr() as *mut usize) = sz;
3388 *((*attr).__i.as_mut_ptr().add(4) as *mut *mut c_void) = (addr as *mut u8).add(sz) as *mut c_void;
3390 0
3391}
3392#[no_mangle]
3393pub unsafe extern "C" fn pthread_attr_getstack(attr: *const pthread_attr_t, addr: *mut *mut c_void, sz: *mut usize) -> c_int {
3394 let size = *((*attr).__i.as_ptr() as *const usize);
3395 *sz = size;
3396 let top = *((*attr).__i.as_ptr().add(4) as *const *mut c_void);
3397 *addr = if top.is_null() {
3398 core::ptr::null_mut()
3399 } else {
3400 (top as *mut u8).sub(size) as *mut c_void
3401 };
3402 0
3403}
3404#[no_mangle]
3405pub unsafe extern "C" fn pthread_attr_setguardsize(attr: *mut pthread_attr_t, sz: usize) -> c_int {
3406 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = sz; 0
3407}
3408#[no_mangle]
3409pub unsafe extern "C" fn pthread_attr_getguardsize(attr: *const pthread_attr_t, sz: *mut usize) -> c_int {
3410 *sz = *((*attr).__i.as_ptr().add(2) as *const usize); 0
3411}
3412#[no_mangle]
3413pub unsafe extern "C" fn pthread_attr_setscope(_attr: *mut pthread_attr_t, scope: c_int) -> c_int {
3414 if scope != PTHREAD_SCOPE_SYSTEM { return EINVAL; }
3415 0
3416}
3417#[no_mangle]
3418pub unsafe extern "C" fn pthread_attr_getscope(_attr: *const pthread_attr_t, scope: *mut c_int) -> c_int {
3419 *scope = PTHREAD_SCOPE_SYSTEM; 0
3420}
3421#[no_mangle]
3422pub unsafe extern "C" fn pthread_attr_setinheritsched(attr: *mut pthread_attr_t, inh: c_int) -> c_int {
3423 if inh != PTHREAD_INHERIT_SCHED && inh != PTHREAD_EXPLICIT_SCHED { return EINVAL; }
3424 (*attr).__i[7] = inh; 0
3425}
3426#[no_mangle]
3427pub unsafe extern "C" fn pthread_attr_getinheritsched(attr: *const pthread_attr_t, inh: *mut c_int) -> c_int {
3428 *inh = (*attr).__i[7]; 0
3429}
3430#[no_mangle]
3431pub unsafe extern "C" fn pthread_attr_setschedpolicy(attr: *mut pthread_attr_t, p: c_int) -> c_int {
3432 (*attr).__i[8] = p; 0
3433}
3434#[no_mangle]
3435pub unsafe extern "C" fn pthread_attr_getschedpolicy(attr: *const pthread_attr_t, p: *mut c_int) -> c_int {
3436 *p = (*attr).__i[8]; 0
3437}
3438#[no_mangle]
3439pub unsafe extern "C" fn pthread_attr_setschedparam(attr: *mut pthread_attr_t, param: *const sched_param) -> c_int {
3440 (*attr).__i[9] = (*param).sched_priority; 0
3441}
3442#[no_mangle]
3443pub unsafe extern "C" fn pthread_attr_getschedparam(attr: *const pthread_attr_t, param: *mut sched_param) -> c_int {
3444 (*param).sched_priority = (*attr).__i[9]; 0
3445}
3446
3447#[no_mangle]
3449pub unsafe extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int {
3450 (*attr).__attr = 0; 0
3451}
3452#[no_mangle]
3453pub unsafe extern "C" fn pthread_mutexattr_destroy(_attr: *mut pthread_mutexattr_t) -> c_int { 0 }
3454#[no_mangle]
3455pub unsafe extern "C" fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, t: c_int) -> c_int {
3456 if (t as c_uint) > 2 { return EINVAL; }
3457 (*attr).__attr = ((*attr).__attr & !3) | t as c_uint; 0
3458}
3459#[no_mangle]
3460pub unsafe extern "C" fn pthread_mutexattr_gettype(attr: *const pthread_mutexattr_t, t: *mut c_int) -> c_int {
3461 *t = ((*attr).__attr & 3) as c_int; 0
3462}
3463#[no_mangle]
3464pub unsafe extern "C" fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, p: c_int) -> c_int {
3465 if (p as c_uint) > 1 { return EINVAL; }
3466 (*attr).__attr = ((*attr).__attr & !128) | ((p as c_uint) << 7); 0
3467}
3468#[no_mangle]
3469pub unsafe extern "C" fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, p: *mut c_int) -> c_int {
3470 *p = (((*attr).__attr >> 7) & 1) as c_int; 0
3471}
3472
3473#[no_mangle]
3474pub unsafe extern "C" fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int {
3475 match protocol {
3476 0 => { (*attr).__attr &= !(MUTEX_PI as c_uint); 0 }
3477 1 => {
3478 let mut lk: c_int = 0;
3479 let r = sys_futex(&raw mut lk, FUTEX_LOCK_PI, 0, null_mut(), null_mut(), 0);
3480 if r < 0 { return (-r) as c_int; }
3481 sys_futex(&raw mut lk, FUTEX_UNLOCK_PI, 0, null_mut(), null_mut(), 0);
3482 (*attr).__attr |= MUTEX_PI as c_uint;
3483 0
3484 }
3485 2 => ENOTSUP,
3486 _ => EINVAL,
3487 }
3488}
3489#[no_mangle]
3490pub unsafe extern "C" fn pthread_mutexattr_getprotocol(attr: *const pthread_mutexattr_t, protocol: *mut c_int) -> c_int {
3491 *protocol = (((*attr).__attr >> 3) & 3) as c_int; 0
3492}
3493
3494const ENOTSUP: c_int = 95;
3495
3496#[no_mangle]
3497pub unsafe extern "C" fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robust: c_int) -> c_int {
3498 if (robust as c_uint) > 1 { return EINVAL; }
3499 if robust != 0 {
3500 (*attr).__attr |= MUTEX_ROBUST as c_uint;
3501 } else {
3502 (*attr).__attr &= !(MUTEX_ROBUST as c_uint);
3503 }
3504 0
3505}
3506#[no_mangle]
3507pub unsafe extern "C" fn pthread_mutexattr_getrobust(attr: *const pthread_mutexattr_t, robust: *mut c_int) -> c_int {
3508 *robust = (((*attr).__attr >> 2) & 1) as c_int; 0
3509}
3510
3511#[no_mangle]
3512pub unsafe extern "C" fn pthread_mutex_consistent(m: *mut pthread_mutex_t) -> c_int {
3513 let old = a_load(&raw const (*m).__i[1]);
3514 let own = old & 0x3fffffff;
3515 if ((*m).__i[0] & MUTEX_ROBUST) == 0 || own == 0 || (old & 0x40000000) == 0 {
3516 return EINVAL;
3517 }
3518 let self_tid = sys_gettid() as c_int;
3519 if own != self_tid { return EPERM; }
3520 a_and(&raw mut (*m).__i[1], !(0x40000000i32));
3521 0
3522}
3523
3524unsafe fn a_and(addr: *mut c_int, val: c_int) {
3525 let a = &*(addr as *const AtomicI32);
3526 a.fetch_and(val, Ordering::AcqRel);
3527}
3528
3529const MUTEX_TYPE_MASK: c_int = 3;
3531const MUTEX_ROBUST: c_int = 4;
3532const MUTEX_PI: c_int = 8;
3533const MUTEX_PSHARED: c_int = 128;
3534
3535unsafe fn ensure_robust_list(slot: &mut Thread) {
3536 if slot.robust_list.futex_offset == 0 {
3537 slot.robust_list.futex_offset = -28;
3538 slot.robust_list.pending = core::ptr::null_mut();
3539 sys_set_robust_list(&mut slot.robust_list, 24);
3540 }
3541}
3542
3543unsafe fn mutex_trylock(m: *mut pthread_mutex_t) -> c_int {
3544 let type_ = (*m).__i[0];
3545 if (type_ & 0x8f) == PTHREAD_MUTEX_NORMAL {
3550 let old = a_cas(&raw mut (*m).__i[1], 0, EBUSY);
3551 return if old == 0 { 0 } else { EBUSY };
3552 }
3553 let base_type = type_ & MUTEX_TYPE_MASK;
3554 let self_tid = sys_gettid() as c_int;
3555 let old = a_load(&raw const (*m).__i[1]);
3556 let own = old & 0x3fffffff;
3557 if own == self_tid {
3558 if (type_ & MUTEX_PI) != 0 && (*m).__i[5] < 0 {
3559 (*m).__i[5] = 0;
3560 return 0;
3561 }
3562 if base_type == PTHREAD_MUTEX_RECURSIVE {
3563 if (*m).__i[5] >= c_int::MAX { return EAGAIN; }
3564 (*m).__i[5] += 1;
3565 return 0;
3566 }
3567 if base_type == PTHREAD_MUTEX_ERRORCHECK { return EDEADLK; }
3568 return EBUSY;
3569 }
3570 if own == 0x3fffffff { return ENOTRECOVERABLE; }
3571 if own != 0 || (old != 0 && (type_ & MUTEX_ROBUST) == 0) { return EBUSY; }
3572 let mut newtid = self_tid;
3573 if (type_ & MUTEX_ROBUST) != 0 {
3574 if (*m).__i[2] != 0 { newtid |= 1i32 << 31; }
3575 newtid |= old & 0x40000000;
3576 }
3577 if a_cas(&raw mut (*m).__i[1], old, newtid) == old {
3578 (*m).__i[5] = 0;
3579 if (type_ & MUTEX_ROBUST) != 0 {
3580 if let Some(slot) = find_thread() {
3581 ensure_robust_list(slot);
3582 let m_next = &raw mut (*m).__i[8] as *mut robust_list;
3583 let head = &mut slot.robust_list.list;
3584 (*m_next).next = head.next;
3585 head.next = m_next;
3586 }
3587 }
3588 if old != 0 { return EOWNERDEAD; }
3589 0
3590 } else { EBUSY }
3591}
3592
3593unsafe fn mutex_lock_internal(m: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
3594 let type_ = (*m).__i[0];
3595 if (type_ & 0x8f) == PTHREAD_MUTEX_NORMAL && a_cas(&raw mut (*m).__i[1], 0, EBUSY) == 0 {
3596 return 0;
3597 }
3598 let r = mutex_trylock(m);
3599 if r != EBUSY { return r; }
3600 if (type_ & MUTEX_PI) != 0 {
3601 let timeout_ptr = if abs_timeout.is_null() { core::ptr::null() } else { abs_timeout };
3602 loop {
3603 let e = futex_lock_pi(&raw mut (*m).__i[1], timeout_ptr);
3604 match e {
3605 0 => {
3606 if (type_ & MUTEX_ROBUST) != 0 && (((*m).__i[1] & 0x40000000) != 0 || (*m).__i[2] != 0) {
3607 (*m).__i[5] = -1;
3608 let _ = mutex_trylock(m);
3609 return EOWNERDEAD;
3610 }
3611 if (type_ & MUTEX_ROBUST) == 0 && (((*m).__i[1] & 0x40000000) != 0 || (*m).__i[2] != 0) {
3612 (*m).__i[2] = -1;
3613 futex_unlock_pi(&raw mut (*m).__i[1]);
3614 return EBUSY;
3615 }
3616 (*m).__i[5] = -1;
3617 let r2 = mutex_trylock(m);
3618 if r2 == 0 { return 0; }
3619 return r2;
3620 }
3621 EINTR => continue,
3622 EDEADLK => {
3623 if (type_ & MUTEX_TYPE_MASK) == PTHREAD_MUTEX_ERRORCHECK { return e; }
3624 loop { pause(); }
3625 }
3626 EOWNERDEAD => {
3627 (*m).__i[5] = -1;
3628 let _ = mutex_trylock(m);
3629 return EOWNERDEAD;
3630 }
3631 _ => return e,
3632 }
3633 }
3634 }
3635 let mut spins = 100;
3636 while spins > 0 {
3637 let r = mutex_trylock(m);
3638 if r != EBUSY { return r; }
3639 core::hint::spin_loop();
3640 spins -= 1;
3641 }
3642 loop {
3643 let r = mutex_trylock(m);
3644 if r != EBUSY { return r; }
3645 if (type_ & MUTEX_TYPE_MASK) == PTHREAD_MUTEX_ERRORCHECK {
3646 let self_tid = sys_gettid() as c_int;
3647 if (a_load(&raw const (*m).__i[1]) & 0x3fffffff) == self_tid { return EDEADLK; }
3648 }
3649 a_fetch_add(&raw mut (*m).__i[2], 1);
3650 let val = a_load(&raw const (*m).__i[1]);
3651 if val == 0 {
3655 a_fetch_sub(&raw mut (*m).__i[2], 1);
3656 continue;
3657 }
3658 a_cas(&raw mut (*m).__i[1], val, val | (1i32 << 31));
3659 let e = futex_timedwait(&raw mut (*m).__i[1], val | (1i32 << 31), abs_timeout);
3660 a_fetch_sub(&raw mut (*m).__i[2], 1);
3661 if e != 0 && e != EINTR { return e; }
3662 }
3663}
3664
3665#[no_mangle]
3666pub unsafe extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t) -> c_int {
3667 core::ptr::write_bytes(mutex, 0, 1);
3668 if !attr.is_null() { (*mutex).__i[0] = (*attr).__attr as c_int; }
3669 0
3670}
3671#[no_mangle]
3672pub unsafe extern "C" fn pthread_mutex_destroy(_mutex: *mut pthread_mutex_t) -> c_int { 0 }
3673#[no_mangle]
3674pub unsafe extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int {
3675 mutex_lock_internal(mutex, core::ptr::null())
3676}
3677#[no_mangle]
3678pub unsafe extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int {
3679 mutex_trylock(mutex)
3680}
3681#[no_mangle]
3682pub unsafe extern "C" fn pthread_mutex_timedlock(mutex: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
3683 mutex_lock_internal(mutex, abs_timeout)
3684}
3685#[no_mangle]
3686pub unsafe extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int {
3687 let type_ = (*mutex).__i[0];
3688 let base_type = type_ & MUTEX_TYPE_MASK;
3689 let old = a_load(&raw const (*mutex).__i[1]);
3690 if base_type != PTHREAD_MUTEX_NORMAL {
3691 let self_tid = sys_gettid() as c_int;
3692 if (old & 0x3fffffff) != self_tid { return EPERM; }
3693 if base_type == PTHREAD_MUTEX_RECURSIVE && (*mutex).__i[5] > 0 {
3694 (*mutex).__i[5] -= 1;
3695 return 0;
3696 }
3697 }
3698 let mut new = 0;
3699 if (type_ & MUTEX_ROBUST) != 0 && (old & 0x40000000) != 0 {
3700 new = 0x7fffffff;
3701 }
3702 if (type_ & MUTEX_PI) != 0 {
3703 if old < 0 || a_cas(&raw mut (*mutex).__i[1], old, new) != old {
3704 if new != 0 { a_store(&raw mut (*mutex).__i[2], -1); }
3705 return futex_unlock_pi(&raw mut (*mutex).__i[1]);
3706 }
3707 return 0;
3708 }
3709 a_store(&raw mut (*mutex).__i[1], new);
3710 if new == 0 && (a_load(&raw const (*mutex).__i[2]) > 0 || old < 0) {
3711 futex_wake(&raw mut (*mutex).__i[1], 1);
3712 }
3713 0
3714}
3715
3716#[no_mangle]
3718pub unsafe extern "C" fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> c_int {
3719 (*attr).__attr = 0; 0
3720}
3721#[no_mangle]
3722pub unsafe extern "C" fn pthread_condattr_destroy(_attr: *mut pthread_condattr_t) -> c_int { 0 }
3723#[no_mangle]
3724pub unsafe extern "C" fn pthread_condattr_setclock(attr: *mut pthread_condattr_t, clk: c_int) -> c_int {
3725 if clk != CLOCK_REALTIME && clk != CLOCK_MONOTONIC { return EINVAL; }
3726 (*attr).__attr = ((*attr).__attr & 0x80000000) | clk as c_uint; 0
3727}
3728#[no_mangle]
3729pub unsafe extern "C" fn pthread_condattr_getclock(attr: *const pthread_condattr_t, clk: *mut c_int) -> c_int {
3730 *clk = ((*attr).__attr & 0x7fffffff) as c_int; 0
3731}
3732#[no_mangle]
3733pub unsafe extern "C" fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, p: c_int) -> c_int {
3734 if (p as c_uint) > 1 { return EINVAL; }
3735 (*attr).__attr = ((*attr).__attr & 0x7fffffff) | ((p as c_uint) << 31); 0
3736}
3737#[no_mangle]
3738pub unsafe extern "C" fn pthread_condattr_getpshared(attr: *const pthread_condattr_t, p: *mut c_int) -> c_int {
3739 *p = ((*attr).__attr >> 31) as c_int; 0
3740}
3741
3742#[no_mangle]
3744pub unsafe extern "C" fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> c_int {
3745 core::ptr::write_bytes(cond, 0, 1);
3746 if !attr.is_null() {
3747 (*cond).__i[4] = ((*attr).__attr & 0x7fffffff) as c_int;
3748 }
3749 0
3750}
3751#[no_mangle]
3752pub unsafe extern "C" fn pthread_cond_destroy(_cond: *mut pthread_cond_t) -> c_int { 0 }
3753#[no_mangle]
3754pub unsafe extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *mut pthread_mutex_t) -> c_int {
3755 pthread_cond_timedwait(cond, mutex, core::ptr::null())
3756}
3757
3758
3759#[no_mangle]
3760pub unsafe extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
3761 pthread_testcancel();
3762 let seq_ptr = &raw mut (*cond).__i[2];
3763 let waiters_ptr = &raw mut (*cond).__i[3];
3764 let seq = a_load(seq_ptr);
3765 a_fetch_add(waiters_ptr, 1);
3766 pthread_mutex_unlock(mutex);
3767 let e = futex_timedwait(seq_ptr, seq, abs_timeout);
3768 a_fetch_sub(waiters_ptr, 1);
3769 let r = pthread_mutex_lock(mutex);
3770 if r != 0 { return r; }
3771 if e == EINTR {
3772 pthread_testcancel();
3773 }
3774 if e != 0 && e != EINTR { return e; }
3775 0
3776}
3777#[no_mangle]
3778pub unsafe extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int {
3779 if a_load(&raw const (*cond).__i[3]) == 0 { return 0; }
3780 a_fetch_add(&raw mut (*cond).__i[2], 1);
3781 futex_wake(&raw mut (*cond).__i[2], 1);
3782 0
3783}
3784#[no_mangle]
3785pub unsafe extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int {
3786 if a_load(&raw const (*cond).__i[3]) == 0 { return 0; }
3787 a_fetch_add(&raw mut (*cond).__i[2], 1);
3788 futex_wake(&raw mut (*cond).__i[2], -1);
3789 0
3790}
3791
3792#[no_mangle]
3794pub unsafe extern "C" fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> c_int {
3795 (*attr).__attr = [0; 2]; 0
3796}
3797#[no_mangle]
3798pub unsafe extern "C" fn pthread_rwlockattr_destroy(_attr: *mut pthread_rwlockattr_t) -> c_int { 0 }
3799#[no_mangle]
3800pub unsafe extern "C" fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, p: c_int) -> c_int {
3801 if (p as c_uint) > 1 { return EINVAL; }
3802 (*attr).__attr[0] = ((*attr).__attr[0] & !128) | ((p as c_uint) << 7); 0
3803}
3804#[no_mangle]
3805pub unsafe extern "C" fn pthread_rwlockattr_getpshared(attr: *const pthread_rwlockattr_t, p: *mut c_int) -> c_int {
3806 *p = (((*attr).__attr[0] >> 7) & 1) as c_int; 0
3807}
3808
3809unsafe fn rwlock_tryrdlock(rw: *mut pthread_rwlock_t) -> c_int {
3811 loop {
3812 let val = a_load(&raw const (*rw).__i[0]);
3813 let cnt = val & 0x7fffffff;
3814 if cnt == 0x7fffffff { return EBUSY; }
3815 if cnt == 0x7ffffffe { return EAGAIN; }
3816 if a_cas(&raw mut (*rw).__i[0], val, val + 1) == val { return 0; }
3817 }
3818}
3819unsafe fn rwlock_trywrlock(rw: *mut pthread_rwlock_t) -> c_int {
3820 if a_cas(&raw mut (*rw).__i[0], 0, 0x7fffffff) == 0 { 0 } else { EBUSY }
3821}
3822unsafe fn rwlock_timedrdlock(rw: *mut pthread_rwlock_t, abs_timeout: *const timespec) -> c_int {
3823 let r = rwlock_tryrdlock(rw);
3824 if r != EBUSY { return r; }
3825 let mut spins = 100;
3826 while spins > 0 { let r = rwlock_tryrdlock(rw); if r != EBUSY { return r; } core::hint::spin_loop(); spins -= 1; }
3827 loop {
3828 let r = rwlock_tryrdlock(rw);
3829 if r != EBUSY { return r; }
3830 let val = a_load(&raw const (*rw).__i[0]);
3831 if val & 0x7fffffff != 0x7fffffff { continue; }
3832 a_fetch_add(&raw mut (*rw).__i[1], 1);
3833 a_cas(&raw mut (*rw).__i[0], val, val | (1i32 << 31));
3834 let e = futex_timedwait(&raw mut (*rw).__i[0], val | (1i32 << 31), abs_timeout);
3835 a_fetch_sub(&raw mut (*rw).__i[1], 1);
3836 if e != 0 && e != EINTR { return e; }
3837 }
3838}
3839unsafe fn rwlock_timedwrlock(rw: *mut pthread_rwlock_t, abs_timeout: *const timespec) -> c_int {
3840 let r = rwlock_trywrlock(rw);
3841 if r != EBUSY { return r; }
3842 let mut spins = 100;
3843 while spins > 0 { let r = rwlock_trywrlock(rw); if r != EBUSY { return r; } core::hint::spin_loop(); spins -= 1; }
3844 loop {
3845 let r = rwlock_trywrlock(rw);
3846 if r != EBUSY { return r; }
3847 let val = a_load(&raw const (*rw).__i[0]);
3848 if val == 0 { continue; }
3849 a_fetch_add(&raw mut (*rw).__i[1], 1);
3850 a_cas(&raw mut (*rw).__i[0], val, val | (1i32 << 31));
3851 let e = futex_timedwait(&raw mut (*rw).__i[0], val | (1i32 << 31), abs_timeout);
3852 a_fetch_sub(&raw mut (*rw).__i[1], 1);
3853 if e != 0 && e != EINTR { return e; }
3854 }
3855}
3856
3857#[no_mangle]
3858pub unsafe extern "C" fn pthread_rwlock_init(rw: *mut pthread_rwlock_t, attr: *const pthread_rwlockattr_t) -> c_int {
3859 core::ptr::write_bytes(rw, 0, 1);
3860 if !attr.is_null() { (*rw).__i[2] = (*attr).__attr[0] as c_int & 128; }
3861 0
3862}
3863#[no_mangle]
3864pub unsafe extern "C" fn pthread_rwlock_destroy(_rw: *mut pthread_rwlock_t) -> c_int { 0 }
3865#[no_mangle]
3866pub unsafe extern "C" fn pthread_rwlock_rdlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_timedrdlock(rw, core::ptr::null()) }
3867#[no_mangle]
3868pub unsafe extern "C" fn pthread_rwlock_tryrdlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_tryrdlock(rw) }
3869#[no_mangle]
3870pub unsafe extern "C" fn pthread_rwlock_timedrdlock(rw: *mut pthread_rwlock_t, t: *const timespec) -> c_int { rwlock_timedrdlock(rw, t) }
3871#[no_mangle]
3872pub unsafe extern "C" fn pthread_rwlock_wrlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_timedwrlock(rw, core::ptr::null()) }
3873#[no_mangle]
3874pub unsafe extern "C" fn pthread_rwlock_trywrlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_trywrlock(rw) }
3875#[no_mangle]
3876pub unsafe extern "C" fn pthread_rwlock_timedwrlock(rw: *mut pthread_rwlock_t, t: *const timespec) -> c_int { rwlock_timedwrlock(rw, t) }
3877#[no_mangle]
3878pub unsafe extern "C" fn pthread_rwlock_unlock(rw: *mut pthread_rwlock_t) -> c_int {
3879 loop {
3880 let val = a_load(&raw const (*rw).__i[0]);
3881 let cnt = val & 0x7fffffff;
3882 let new_val = if cnt == 0x7fffffff || cnt == 1 { 0 } else { val - 1 };
3883 if a_cas(&raw mut (*rw).__i[0], val, new_val) == val {
3884 if new_val == 0 && (a_load(&raw const (*rw).__i[1]) > 0 || val < 0) {
3885 futex_wake(&raw mut (*rw).__i[0], cnt);
3886 }
3887 return 0;
3888 }
3889 }
3890}
3891
3892#[no_mangle]
3894pub unsafe extern "C" fn pthread_barrierattr_init(attr: *mut pthread_barrierattr_t) -> c_int { (*attr).__attr = 0; 0 }
3895#[no_mangle]
3896pub unsafe extern "C" fn pthread_barrierattr_destroy(_attr: *mut pthread_barrierattr_t) -> c_int { 0 }
3897#[no_mangle]
3898pub unsafe extern "C" fn pthread_barrierattr_setpshared(attr: *mut pthread_barrierattr_t, p: c_int) -> c_int {
3899 if (p as c_uint) > 1 { return EINVAL; }
3900 (*attr).__attr = p as c_uint; 0
3901}
3902#[no_mangle]
3903pub unsafe extern "C" fn pthread_barrierattr_getpshared(attr: *const pthread_barrierattr_t, p: *mut c_int) -> c_int {
3904 *p = (*attr).__attr as c_int; 0
3905}
3906
3907#[no_mangle]
3909pub unsafe extern "C" fn pthread_barrier_init(b: *mut pthread_barrier_t, _attr: *const pthread_barrierattr_t, count: c_uint) -> c_int {
3910 if count == 0 { return EINVAL; }
3911 core::ptr::write_bytes(b, 0, 1);
3912 (*b).__i[2] = count as c_int - 1;
3913 0
3914}
3915#[no_mangle]
3916pub unsafe extern "C" fn pthread_barrier_destroy(_b: *mut pthread_barrier_t) -> c_int { 0 }
3917#[no_mangle]
3918pub unsafe extern "C" fn pthread_barrier_wait(b: *mut pthread_barrier_t) -> c_int {
3919 let limit = (*b).__i[2];
3920 if limit == 0 { return PTHREAD_BARRIER_SERIAL_THREAD; }
3921 spinlock_lock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
3922 let arrived = a_load(&raw const (*b).__i[3]) + 1;
3923 a_store(&raw mut (*b).__i[3], arrived);
3924 if arrived > limit {
3925 a_store(&raw mut (*b).__i[3], 0);
3926 let gen = a_load(&raw const (*b).__i[4]);
3927 a_store(&raw mut (*b).__i[4], gen + 1);
3928 spinlock_unlock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
3929 futex_wake(&raw mut (*b).__i[4], -1);
3930 return PTHREAD_BARRIER_SERIAL_THREAD;
3931 }
3932 let gen = a_load(&raw const (*b).__i[4]);
3933 spinlock_unlock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
3934 while a_load(&raw const (*b).__i[4]) == gen {
3935 futex_wait(&raw mut (*b).__i[4], gen);
3936 }
3937 0
3938}
3939
3940#[no_mangle]
3942pub unsafe extern "C" fn pthread_spin_init(s: *mut pthread_spinlock_t, _pshared: c_int) -> c_int { a_store(s, 0); 0 }
3943#[no_mangle]
3944pub unsafe extern "C" fn pthread_spin_destroy(_s: *mut pthread_spinlock_t) -> c_int { 0 }
3945#[no_mangle]
3946pub unsafe extern "C" fn pthread_spin_lock(s: *mut pthread_spinlock_t) -> c_int {
3947 while a_load(s) != 0 || a_cas(s, 0, EBUSY) != 0 { core::hint::spin_loop(); }
3948 0
3949}
3950#[no_mangle]
3951pub unsafe extern "C" fn pthread_spin_trylock(s: *mut pthread_spinlock_t) -> c_int { a_cas(s, 0, EBUSY) }
3952#[no_mangle]
3953pub unsafe extern "C" fn pthread_spin_unlock(s: *mut pthread_spinlock_t) -> c_int { a_store(s, 0); 0 }
3954
3955#[no_mangle]
3957pub unsafe extern "C" fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int {
3958 if value > SEM_VALUE_MAX as c_uint { return EINVAL; }
3959 (*sem).__val[0] = value as c_int;
3960 (*sem).__val[1] = 0;
3961 (*sem).__val[2] = if pshared != 0 { 0 } else { 128 };
3962 0
3963}
3964#[no_mangle]
3965pub unsafe extern "C" fn sem_destroy(_sem: *mut sem_t) -> c_int { 0 }
3966
3967unsafe fn sem_trywait_internal(sem: *mut sem_t) -> c_int {
3968 loop {
3969 let val = a_load(&raw const (*sem).__val[0]);
3970 if val & SEM_VALUE_MAX == 0 { return EAGAIN; }
3971 if a_cas(&raw mut (*sem).__val[0], val, val - 1) == val { return 0; }
3972 }
3973}
3974
3975#[no_mangle]
3976pub unsafe extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int {
3977 if sem_trywait_internal(sem) == 0 { 0 } else { ERRNO!() = EAGAIN; -1 }
3978}
3979#[no_mangle]
3980pub unsafe extern "C" fn sem_wait(sem: *mut sem_t) -> c_int {
3981 pthread_testcancel();
3982 if sem_trywait_internal(sem) == 0 { return 0; }
3983 let mut spins = 100;
3984 while spins > 0 { if sem_trywait_internal(sem) == 0 { return 0; } core::hint::spin_loop(); spins -= 1; }
3985 loop {
3986 pthread_testcancel();
3987 if sem_trywait_internal(sem) == 0 { return 0; }
3988 let val = a_load(&raw const (*sem).__val[0]);
3989 if val & SEM_VALUE_MAX != 0 { continue; }
3990 a_cas(&raw mut (*sem).__val[0], val, val | (1i32 << 31));
3991 a_fetch_add(&raw mut (*sem).__val[1], 1);
3992 futex_wait(&raw mut (*sem).__val[0], 1i32 << 31);
3993 a_fetch_sub(&raw mut (*sem).__val[1], 1);
3994 }
3995}
3996#[no_mangle]
3997pub unsafe extern "C" fn sem_timedwait(sem: *mut sem_t, abs_timeout: *const timespec) -> c_int {
3998 pthread_testcancel();
3999 if sem_trywait_internal(sem) == 0 { return 0; }
4000 let mut spins = 100;
4001 while spins > 0 { if sem_trywait_internal(sem) == 0 { return 0; } core::hint::spin_loop(); spins -= 1; }
4002 loop {
4003 pthread_testcancel();
4004 if sem_trywait_internal(sem) == 0 { return 0; }
4005 let val = a_load(&raw const (*sem).__val[0]);
4006 if val & SEM_VALUE_MAX != 0 { continue; }
4007 a_cas(&raw mut (*sem).__val[0], val, val | (1i32 << 31));
4008 a_fetch_add(&raw mut (*sem).__val[1], 1);
4009 let e = futex_timedwait(&raw mut (*sem).__val[0], 1i32 << 31, abs_timeout);
4010 a_fetch_sub(&raw mut (*sem).__val[1], 1);
4011 if e != 0 && e != EINTR { ERRNO!() = e; return -1; }
4012 }
4013}
4014#[no_mangle]
4015pub unsafe extern "C" fn sem_post(sem: *mut sem_t) -> c_int {
4016 loop {
4017 let val = a_load(&raw const (*sem).__val[0]);
4018 if (val & SEM_VALUE_MAX) == SEM_VALUE_MAX { ERRNO!() = EOVERFLOW; return -1; }
4019 let mut new = val + 1;
4020 let waiters = a_load(&raw const (*sem).__val[1]);
4021 if waiters <= 1 { new &= !(1i32 << 31); }
4022 if a_cas(&raw mut (*sem).__val[0], val, new) == val {
4023 if val < 0 || waiters > 0 {
4024 futex_wake(&raw mut (*sem).__val[0], if waiters > 1 { 1 } else { -1 });
4025 }
4026 return 0;
4027 }
4028 }
4029}
4030#[no_mangle]
4031pub unsafe extern "C" fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int {
4032 *sval = a_load(&raw const (*sem).__val[0]) & SEM_VALUE_MAX;
4033 0
4034}
4035
4036const NAME_MAX: usize = 255;
4041const SEM_NSEMS_MAX: usize = 256;
4042
4043static SEMTAB_LOCK: AtomicI32 = AtomicI32::new(0);
4045
4046struct SemEntry {
4047 ino: u64,
4048 sem: *mut sem_t,
4049 refcnt: u32,
4050}
4051
4052static mut SEMTAB: [SemEntry; SEM_NSEMS_MAX] = {
4054 const ZERO: SemEntry = SemEntry { ino: 0, sem: core::ptr::null_mut(), refcnt: 0 };
4055 [ZERO; SEM_NSEMS_MAX]
4056};
4057
4058unsafe fn semtab_lock() {
4059 while SEMTAB_LOCK.compare_exchange_weak(0, 1, Ordering::Acquire, Ordering::Relaxed).is_err() {
4060 core::hint::spin_loop();
4061 }
4062}
4063
4064unsafe fn semtab_unlock() {
4065 SEMTAB_LOCK.store(0, Ordering::Release);
4066}
4067
4068unsafe fn shm_mapname(name: *const c_char, buf: *mut u8) -> c_int {
4071 let mut p = name;
4072 while *p == b'/' as c_char { p = p.add(1); }
4074 let start = p;
4075 while *p != 0 && *p != b'/' as c_char { p = p.add(1); }
4077 let len = p.offset_from(start) as usize;
4078 if len == 0 || *p != 0 {
4080 ERRNO!() = EINVAL;
4081 return -1;
4082 }
4083 if len == 1 && *start == b'.' as c_char {
4084 ERRNO!() = EINVAL;
4085 return -1;
4086 }
4087 if len == 2 && *start == b'.' as c_char && *start.add(1) == b'.' as c_char {
4088 ERRNO!() = EINVAL;
4089 return -1;
4090 }
4091 if len > NAME_MAX {
4092 ERRNO!() = ENAMETOOLONG;
4093 return -1;
4094 }
4095 let prefix = b"/dev/shm/\0";
4097 let mut i = 0;
4098 while prefix[i] != 0 {
4099 *buf.add(i) = prefix[i];
4100 i += 1;
4101 }
4102 let mut j = 0;
4103 while j < len {
4104 *buf.add(i + j) = *start.add(j) as u8;
4105 j += 1;
4106 }
4107 *buf.add(i + j) = 0;
4108 (i + j) as c_int
4109}
4110
4111#[no_mangle]
4112pub unsafe extern "C" fn shm_open(name: *const c_char, flags: c_int, mode: mode_t) -> c_int {
4113 let mut buf = [0u8; 16 + NAME_MAX + 1];
4114 if shm_mapname(name, buf.as_mut_ptr()) < 0 { return -1; }
4115 let fd = sys_open(buf.as_ptr(), (flags | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, mode as i64);
4116 if fd < 0 { ERRNO!() = (-fd) as c_int; return -1; }
4117 fd as c_int
4118}
4119
4120#[no_mangle]
4121pub unsafe extern "C" fn shm_unlink(name: *const c_char) -> c_int {
4122 let mut buf = [0u8; 16 + NAME_MAX + 1];
4123 if shm_mapname(name, buf.as_mut_ptr()) < 0 { return -1; }
4124 let r = sys_unlink(buf.as_ptr());
4125 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
4126 0
4127}
4128
4129#[no_mangle]
4130pub unsafe extern "C" fn sem_open(name: *const c_char, flags: c_int, mut args: ...) -> *mut sem_t {
4131 let mut buf = [0u8; 16 + NAME_MAX + 1];
4132 if shm_mapname(name, buf.as_mut_ptr()).is_negative() {
4133 return core::ptr::null_mut(); }
4135
4136 let oflags = flags & (O_CREAT | O_EXCL);
4137
4138 semtab_lock();
4139
4140 let mut slot: c_int = -1;
4142 for i in 0..SEMTAB_LEN {
4143 if SEMTAB[i].sem.is_null() && slot < 0 { slot = i as c_int; }
4144 }
4145 if slot < 0 {
4146 ERRNO!() = EMFILE;
4147 semtab_unlock();
4148 return core::ptr::null_mut();
4149 }
4150 SEMTAB[slot as usize].sem = !0usize as *mut sem_t; semtab_unlock();
4153
4154 let mut mode: mode_t = 0;
4156 let mut value: c_uint = 0;
4157 if oflags & O_CREAT != 0 {
4158 mode = args.next_arg::<mode_t>() & 0o666;
4159 value = args.next_arg::<c_uint>();
4160 if value > SEM_VALUE_MAX as c_uint {
4161 ERRNO!() = EINVAL;
4162 semtab_lock();
4163 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4164 semtab_unlock();
4165 return core::ptr::null_mut();
4166 }
4167 }
4168
4169 if oflags != O_CREAT | O_EXCL {
4171 let fd = sys_open(buf.as_ptr(), (O_RDWR | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, 0);
4172 if fd >= 0 {
4173 let map = sys_mmap(
4174 core::ptr::null_mut(),
4175 core::mem::size_of::<sem_t>(),
4176 PROT_READ | PROT_WRITE,
4177 MAP_SHARED,
4178 fd as i32,
4179 0,
4180 );
4181 sys_close(fd);
4182 if map != MMAP_FAILED {
4183 let st_ino = get_ino(fd as c_int, buf.as_ptr());
4184 return sem_register(map as *mut sem_t, st_ino, slot);
4185 }
4186 }
4187 if oflags == 0 {
4188 semtab_lock();
4190 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4191 semtab_unlock();
4192 return core::ptr::null_mut();
4193 }
4194 }
4195
4196 let mut tmp = [0u8; 32];
4198 let tmpname = b"/dev/shm/tmp-XXXXXX\0";
4199 tmp[..tmpname.len()].copy_from_slice(tmpname);
4200 let mut ts: timespec = core::mem::zeroed();
4202 sys_clock_gettime(0, &mut ts);
4203 let mut n = ts.tv_nsec;
4205 let mut pos = tmpname.len() - 1;
4206 tmp[pos] = 0;
4207 pos -= 1;
4208 loop {
4209 tmp[pos] = b'0' + (n % 10) as u8;
4210 n /= 10;
4211 if n == 0 || pos == 0 { break; }
4212 pos -= 1;
4213 }
4214 let tmp_path = tmp.as_ptr();
4216
4217 let mut newsem: sem_t = core::mem::zeroed();
4218 newsem.__val[0] = value as c_int;
4219 newsem.__val[1] = 0;
4220 newsem.__val[2] = 128; loop {
4223 let fd = sys_open(tmp_path as *const u8, (O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC | O_NONBLOCK) as i64, mode as i64);
4224 if fd < 0 {
4225 if (-fd) as c_int == EEXIST { continue; }
4226 semtab_lock();
4227 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4228 semtab_unlock();
4229 return core::ptr::null_mut();
4230 }
4231 let written = sys_write(fd, &newsem as *const sem_t as *const u8, core::mem::size_of::<sem_t>());
4232 if written != core::mem::size_of::<sem_t>() as i64 {
4233 sys_close(fd);
4234 sys_unlink(tmp_path);
4235 semtab_lock();
4236 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4237 semtab_unlock();
4238 return core::ptr::null_mut();
4239 }
4240 let map = sys_mmap(
4241 core::ptr::null_mut(),
4242 core::mem::size_of::<sem_t>(),
4243 PROT_READ | PROT_WRITE,
4244 MAP_SHARED,
4245 fd as i32,
4246 0,
4247 );
4248 sys_close(fd);
4249 if map == MMAP_FAILED {
4250 sys_unlink(tmp_path);
4251 semtab_lock();
4252 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4253 semtab_unlock();
4254 return core::ptr::null_mut();
4255 }
4256 let r = sys_linkat(AT_FDCWD, tmp_path, AT_FDCWD, buf.as_ptr(), 0);
4258 let e = if r < 0 { (-r) as c_int } else { 0 };
4259 sys_unlink(tmp_path);
4260 if e == 0 {
4261 let st_ino = get_ino(-1, buf.as_ptr());
4262 return sem_register(map as *mut sem_t, st_ino, slot);
4263 }
4264 sys_munmap(map, core::mem::size_of::<sem_t>());
4265 if e != EEXIST || oflags == O_CREAT | O_EXCL {
4266 ERRNO!() = e;
4267 semtab_lock();
4268 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4269 semtab_unlock();
4270 return core::ptr::null_mut();
4271 }
4272 break;
4274 }
4275
4276 let fd = sys_open(buf.as_ptr(), (O_RDWR | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, 0);
4278 if fd < 0 {
4279 semtab_lock();
4280 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4281 semtab_unlock();
4282 return core::ptr::null_mut();
4283 }
4284 let map = sys_mmap(
4285 core::ptr::null_mut(),
4286 core::mem::size_of::<sem_t>(),
4287 PROT_READ | PROT_WRITE,
4288 MAP_SHARED,
4289 fd as i32,
4290 0,
4291 );
4292 sys_close(fd);
4293 if map == MMAP_FAILED {
4294 semtab_lock();
4295 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4296 semtab_unlock();
4297 return core::ptr::null_mut();
4298 }
4299 let st_ino = get_ino(-1, buf.as_ptr());
4300 sem_register(map as *mut sem_t, st_ino, slot)
4301}
4302
4303unsafe fn get_ino(_fd_hint: c_int, path: *const u8) -> u64 {
4304 let mut st: Stat = core::mem::zeroed();
4305 if sys_newfstatat(AT_FDCWD, path as *const c_char, &mut st as *mut Stat as *mut u8, 0) == 0 {
4306 st.st_ino
4307 } else {
4308 0
4309 }
4310}
4311
4312unsafe fn sem_register(map: *mut sem_t, ino: u64, slot_hint: c_int) -> *mut sem_t {
4313 semtab_lock();
4314 for i in 0..SEMTAB_LEN {
4316 if SEMTAB[i].ino == ino && !SEMTAB[i].sem.is_null() && SEMTAB[i].sem != !0usize as *mut sem_t {
4317 sys_munmap(map as *mut u8, core::mem::size_of::<sem_t>());
4319 SEMTAB[slot_hint as usize].sem = core::ptr::null_mut();
4320 SEMTAB[i].refcnt += 1;
4321 let ret = SEMTAB[i].sem;
4322 semtab_unlock();
4323 return ret;
4324 }
4325 }
4326 SEMTAB[slot_hint as usize].sem = map;
4328 SEMTAB[slot_hint as usize].ino = ino;
4329 SEMTAB[slot_hint as usize].refcnt = 1;
4330 semtab_unlock();
4331 map
4332}
4333
4334const SEMTAB_LEN: usize = SEM_NSEMS_MAX;
4335
4336#[no_mangle]
4337pub unsafe extern "C" fn sem_close(sem: *mut sem_t) -> c_int {
4338 semtab_lock();
4339 for i in 0..SEMTAB_LEN {
4340 if SEMTAB[i].sem == sem {
4341 SEMTAB[i].refcnt -= 1;
4342 if SEMTAB[i].refcnt == 0 {
4343 SEMTAB[i].sem = core::ptr::null_mut();
4344 SEMTAB[i].ino = 0;
4345 semtab_unlock();
4346 sys_munmap(sem as *mut u8, core::mem::size_of::<sem_t>());
4347 return 0;
4348 }
4349 semtab_unlock();
4350 return 0;
4351 }
4352 }
4353 semtab_unlock();
4354 0
4355}
4356
4357#[no_mangle]
4358pub unsafe extern "C" fn sem_unlink(name: *const c_char) -> c_int {
4359 shm_unlink(name)
4360}
4361
4362#[no_mangle]
4364pub unsafe extern "C" fn pthread_once(control: *mut pthread_once_t, init_routine: Option<unsafe extern "C" fn()>) -> c_int {
4365 if a_load(control) == 2 { return 0; }
4366 loop {
4367 match a_cas(control, 0, 1) {
4368 0 => {
4369 if let Some(f) = init_routine { f(); }
4370 if a_swap(control, 2) == 3 { futex_wake(control, -1); }
4371 return 0;
4372 }
4373 1 => { a_cas(control, 1, 3); }
4374 3 => { futex_wait(control, 3); }
4375 _ => { return 0; }
4376 }
4377 }
4378}
4379
4380#[no_mangle]
4382pub unsafe extern "C" fn pthread_key_create(key: *mut pthread_key_t, dtor: Option<unsafe extern "C" fn(*mut c_void)>) -> c_int {
4383 let start = NEXT_KEY.load(Ordering::Relaxed);
4384 let mut j = start;
4385 loop {
4386 if KEY_DTORS[j].is_none() {
4387 KEY_DTORS[j] = dtor;
4388 NEXT_KEY.store((j + 1) % PTHREAD_KEYS_MAX, Ordering::Relaxed);
4389 *key = j as pthread_key_t;
4390 return 0;
4391 }
4392 j = (j + 1) % PTHREAD_KEYS_MAX;
4393 if j == start { return EAGAIN; }
4394 }
4395}
4396#[no_mangle]
4397pub unsafe extern "C" fn pthread_key_delete(key: pthread_key_t) -> c_int {
4398 KEY_DTORS[key as usize] = None;
4399 let count = thread_slot_count();
4400 let mut i = 0usize;
4401 while i < count {
4402 let slot = thread_slot_at(i);
4403 if core::ptr::read_volatile(&raw const (*slot).tid) > 0 {
4404 (*slot).tsd[key as usize] = core::ptr::null_mut();
4405 }
4406 i += 1;
4407 }
4408 0
4409}
4410#[no_mangle]
4411pub unsafe extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void {
4412 if let Some(slot) = find_thread() { slot.tsd[key as usize] } else { core::ptr::null_mut() }
4413}
4414#[no_mangle]
4415pub unsafe extern "C" fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int {
4416 if let Some(slot) = find_thread() {
4417 slot.tsd[key as usize] = value as *mut c_void;
4418 0
4419 } else { EINVAL }
4420}
4421
4422unsafe fn run_cleanup_handlers(slot: &mut Thread) {
4424 let mut cb = slot.cancelbuf;
4425 while !cb.is_null() {
4426 let cur = &*cb;
4427 let f = cur.__f;
4428 let x = cur.__x;
4429 cb = cur.__next;
4430 if let Some(func) = f {
4431 func(x);
4432 }
4433 }
4434 slot.cancelbuf = core::ptr::null_mut();
4435}
4436
4437unsafe fn do_cancel() -> ! {
4438 if let Some(slot) = find_thread() {
4439 run_cleanup_handlers(slot);
4440 slot.result = !0usize as *mut c_void; slot.detach_state = DT_EXITED;
4442 futex_wake(&raw mut slot.detach_state, 1);
4443 }
4444 sys_exit_thread(0);
4445}
4446
4447extern "C" fn cancel_handler(_sig: c_int) {
4448 unsafe {
4449 if let Some(slot) = find_thread() {
4450 if slot.cancel != 0
4454 && slot.cancel_state == PTHREAD_CANCEL_ENABLE
4455 && slot.cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS
4456 {
4457 do_cancel();
4458 }
4459 }
4460 }
4461}
4462
4463static CANCEL_INIT: AtomicI32 = AtomicI32::new(0);
4464
4465unsafe fn ensure_cancel_handler() {
4466 if CANCEL_INIT.swap(1, Ordering::AcqRel) == 0 {
4467 let act = KSigAction {
4468 sa_handler: cancel_handler as *const () as usize,
4469 sa_flags: SA_RESTORER,
4470 sa_restorer: sig_restorer as *const () as usize,
4471 sa_mask: [!0u64],
4472 };
4473 sys_rt_sigaction(SIGCANCEL, &act as *const KSigAction, core::ptr::null_mut(), 8);
4474 }
4475}
4476
4477#[no_mangle]
4478pub unsafe extern "C" fn pthread_cancel(thread: PthreadT) -> c_int {
4479 let slot = thread as *mut Thread;
4480 if slot.is_null() { return EINVAL; }
4481 ensure_cancel_handler();
4482 a_store(&raw mut (*slot).cancel, 1);
4483 let tid = (*slot).tid;
4484 if tid > 0 {
4485 sys_tgkill(sys_getpid() as c_int, tid, SIGCANCEL);
4486 }
4487 0
4488}
4489#[no_mangle]
4490pub unsafe extern "C" fn pthread_setcancelstate(state: c_int, oldstate: *mut c_int) -> c_int {
4491 if state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE { return EINVAL; }
4492 if let Some(slot) = find_thread() {
4493 if !oldstate.is_null() { *oldstate = slot.cancel_state; }
4494 slot.cancel_state = state;
4495 0
4496 } else { EINVAL }
4497}
4498#[no_mangle]
4499pub unsafe extern "C" fn pthread_setcanceltype(type_: c_int, oldtype: *mut c_int) -> c_int {
4500 if type_ != PTHREAD_CANCEL_DEFERRED && type_ != PTHREAD_CANCEL_ASYNCHRONOUS { return EINVAL; }
4501 if let Some(slot) = find_thread() {
4502 if !oldtype.is_null() { *oldtype = slot.cancel_type; }
4503 slot.cancel_type = type_;
4504 0
4505 } else { EINVAL }
4506}
4507#[no_mangle]
4508pub unsafe extern "C" fn pthread_testcancel() {
4509 if let Some(slot) = find_thread() {
4510 if slot.cancel != 0 && slot.cancel_state == PTHREAD_CANCEL_ENABLE {
4511 do_cancel();
4512 }
4513 }
4514}
4515
4516#[no_mangle]
4517pub unsafe extern "C" fn _pthread_cleanup_push(cb: *mut __ptcb, f: Option<unsafe extern "C" fn(*mut c_void)>, x: *mut c_void) {
4518 (*cb).__f = f;
4519 (*cb).__x = x;
4520 if let Some(slot) = find_thread() {
4521 (*cb).__next = slot.cancelbuf;
4522 slot.cancelbuf = cb;
4523 } else {
4524 (*cb).__next = core::ptr::null_mut();
4525 }
4526}
4527
4528#[no_mangle]
4529pub unsafe extern "C" fn _pthread_cleanup_pop(cb: *mut __ptcb, run: c_int) {
4530 if let Some(slot) = find_thread() {
4531 slot.cancelbuf = (*cb).__next;
4532 }
4533 if run != 0 {
4534 if let Some(f) = (*cb).__f {
4535 f((*cb).__x);
4536 }
4537 }
4538}
4539
4540#[no_mangle]
4541pub unsafe extern "C" fn pthread_kill(thread: PthreadT, sig: c_int) -> c_int {
4542 let slot = thread as *mut Thread;
4543 if slot.is_null() { return EINVAL; }
4544 let tid = (*slot).tid;
4545 if tid <= 0 { return EINVAL; }
4546 if sys_tgkill(sys_getpid() as c_int, tid, sig) < 0 { -1 } else { 0 }
4547}
4548
4549#[no_mangle]
4550pub unsafe extern "C" fn pthread_sigmask(how: c_int, set: *const SigSetT, oldset: *mut SigSetT) -> c_int {
4551 sigprocmask(how, set, oldset)
4552}
4553
4554
4555#[repr(C)]
4556pub struct lconv {
4557 pub decimal_point: *mut c_char,
4558 pub thousands_sep: *mut c_char,
4559 pub grouping: *mut c_char,
4560 pub int_curr_symbol: *mut c_char,
4561 pub currency_symbol: *mut c_char,
4562 pub mon_decimal_point: *mut c_char,
4563 pub mon_thousands_sep: *mut c_char,
4564 pub mon_grouping: *mut c_char,
4565 pub positive_sign: *mut c_char,
4566 pub negative_sign: *mut c_char,
4567 pub int_frac_digits: c_char,
4568 pub frac_digits: c_char,
4569 pub p_cs_precedes: c_char,
4570 pub p_sep_by_space: c_char,
4571 pub n_cs_precedes: c_char,
4572 pub n_sep_by_space: c_char,
4573 pub p_sign_posn: c_char,
4574 pub n_sign_posn: c_char,
4575 pub int_p_cs_precedes: c_char,
4576 pub int_p_sep_by_space: c_char,
4577 pub int_n_cs_precedes: c_char,
4578 pub int_n_sep_by_space: c_char,
4579 pub int_p_sign_posn: c_char,
4580 pub int_n_sign_posn: c_char,
4581}
4582
4583static UTF8_NAME: [u8; 6] = [b'U', b'T', b'F', b'-', b'8', 0];
4584static C_NAME: [u8; 2] = [b'C', 0];
4585static mut LOCALE_NAME: *const c_char = C_NAME.as_ptr() as *const c_char;
4586static mut LOCALE_CTYPE_UTF8: bool = true;
4587static mut EMPTY_STR: [c_char; 1] = [0];
4588static mut DECIMAL_POINT: [c_char; 2] = [b'.' as c_char, 0];
4589static mut LCONV: lconv = lconv {
4590 decimal_point: core::ptr::null_mut(),
4591 thousands_sep: core::ptr::null_mut(),
4592 grouping: core::ptr::null_mut(),
4593 int_curr_symbol: core::ptr::null_mut(),
4594 currency_symbol: core::ptr::null_mut(),
4595 mon_decimal_point: core::ptr::null_mut(),
4596 mon_thousands_sep: core::ptr::null_mut(),
4597 mon_grouping: core::ptr::null_mut(),
4598 positive_sign: core::ptr::null_mut(),
4599 negative_sign: core::ptr::null_mut(),
4600 int_frac_digits: (-1i32) as c_char,
4601 frac_digits: (-1i32) as c_char,
4602 p_cs_precedes: (-1i32) as c_char,
4603 p_sep_by_space: (-1i32) as c_char,
4604 n_cs_precedes: (-1i32) as c_char,
4605 n_sep_by_space: (-1i32) as c_char,
4606 p_sign_posn: (-1i32) as c_char,
4607 n_sign_posn: (-1i32) as c_char,
4608 int_p_cs_precedes: (-1i32) as c_char,
4609 int_p_sep_by_space: (-1i32) as c_char,
4610 int_n_cs_precedes: (-1i32) as c_char,
4611 int_n_sep_by_space: (-1i32) as c_char,
4612 int_p_sign_posn: (-1i32) as c_char,
4613 int_n_sign_posn: (-1i32) as c_char,
4614};
4615
4616unsafe fn cstr_contains_ci(s: *const u8, needle: &[u8]) -> bool {
4617 let len = strlen(s as *const c_char) as usize;
4618 let s_slice = core::slice::from_raw_parts(s, len);
4619 if needle.len() > len { return false; }
4620 for i in 0..=len - needle.len() {
4621 if s_slice[i..i + needle.len()].eq_ignore_ascii_case(needle) {
4622 return true;
4623 }
4624 }
4625 false
4626}
4627
4628#[no_mangle]
4629pub unsafe extern "C" fn setlocale(_category: c_int, locale: *const c_char) -> *mut c_char {
4630 if locale.is_null() || *locale == 0 {
4631 return LOCALE_NAME as *mut c_char;
4632 }
4633 let name = locale as *const u8;
4634 if strcmp(name, b"C\0".as_ptr()) == 0 || strcmp(name, b"POSIX\0".as_ptr()) == 0 {
4635 LOCALE_CTYPE_UTF8 = false;
4636 return LOCALE_NAME as *mut c_char;
4637 }
4638 if cstr_contains_ci(name, b"UTF-8") || cstr_contains_ci(name, b"UTF8") {
4639 LOCALE_CTYPE_UTF8 = true;
4640 return LOCALE_NAME as *mut c_char;
4641 }
4642 core::ptr::null_mut()
4643}
4644
4645#[no_mangle]
4646pub unsafe extern "C" fn localeconv() -> *mut lconv {
4647 let empty = core::ptr::addr_of_mut!(EMPTY_STR) as *mut c_char;
4648 let lconv = core::ptr::addr_of_mut!(LCONV);
4649 (*lconv).decimal_point = core::ptr::addr_of_mut!(DECIMAL_POINT) as *mut c_char;
4650 (*lconv).thousands_sep = empty;
4651 (*lconv).grouping = empty;
4652 (*lconv).int_curr_symbol = empty;
4653 (*lconv).currency_symbol = empty;
4654 (*lconv).mon_decimal_point = empty;
4655 (*lconv).mon_thousands_sep = empty;
4656 (*lconv).mon_grouping = empty;
4657 (*lconv).positive_sign = empty;
4658 (*lconv).negative_sign = empty;
4659 lconv
4660}
4661
4662pub type locale_t = *mut c_void;
4663static mut CURRENT_LOCALE: locale_t = LC_GLOBAL_LOCALE;
4664
4665static mut C_LOCALE_STORAGE: c_int = 0;
4666const C_LOCALE: locale_t = core::ptr::addr_of_mut!(C_LOCALE_STORAGE) as locale_t;
4667const LC_GLOBAL_LOCALE: locale_t = usize::MAX as locale_t;
4668
4669#[no_mangle]
4670pub unsafe extern "C" fn newlocale(_mask: c_int, name: *const c_char, base: locale_t) -> locale_t {
4671 if !name.is_null() && *name != 0 {
4672 let n = name as *const u8;
4673 if strcmp(n, b"C\0".as_ptr()) != 0
4674 && strcmp(n, b"POSIX\0".as_ptr()) != 0
4675 {
4676 return core::ptr::null_mut();
4677 }
4678 }
4679 if base.is_null() || base == C_LOCALE || base == LC_GLOBAL_LOCALE {
4680 C_LOCALE
4681 } else {
4682 core::ptr::null_mut()
4683 }
4684}
4685
4686#[no_mangle]
4687pub unsafe extern "C" fn freelocale(_loc: locale_t) {}
4688
4689#[no_mangle]
4690pub unsafe extern "C" fn uselocale(loc: locale_t) -> locale_t {
4691 let old = CURRENT_LOCALE;
4692 if !loc.is_null() {
4693 CURRENT_LOCALE = loc;
4694 }
4695 old
4696}
4697
4698#[no_mangle]
4699pub unsafe extern "C" fn duplocale(loc: locale_t) -> locale_t {
4700 if loc.is_null() {
4701 return core::ptr::null_mut();
4702 }
4703 C_LOCALE
4704}
4705
4706const NL_ITEM_CODESET: c_int = 14;
4707const NL_ITEM_RADIXCHAR: c_int = 0x10000;
4708const NL_ITEM_THOUSEP: c_int = 0x10001;
4709const NL_ITEM_YESEXPR: c_int = 0x50000;
4710const NL_ITEM_NOEXPR: c_int = 0x50001;
4711
4712const C_TIME_STRINGS: &[u8] = b"Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat\0\
4713Sunday\0Monday\0Tuesday\0Wednesday\0Thursday\0Friday\0Saturday\0\
4714Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec\0\
4715January\0February\0March\0April\0May\0June\0July\0August\0\
4716September\0October\0November\0December\0\
4717AM\0PM\0\
4718%a %b %e %T %Y\0%m/%d/%y\0%H:%M:%S\0%I:%M:%S %p\0\
4719\0\0%m/%d/%y\00123456789\0%a %b %e %T %Y\0%H:%M:%S\0";
4720
4721const C_NUMERIC_STRINGS: &[u8] = b".\0\0";
4722const C_MESSAGES_STRINGS: &[u8] = b"^[yY]\0^[nN]\0";
4723
4724unsafe fn langinfo_str(table: *const u8, mut idx: c_int) -> *mut c_char {
4725 let mut p = table;
4726 while idx > 0 {
4727 while *p != 0 { p = p.add(1); }
4728 p = p.add(1);
4729 idx -= 1;
4730 }
4731 p as *mut c_char
4732}
4733
4734#[no_mangle]
4735pub unsafe extern "C" fn nl_langinfo(item: c_int) -> *mut c_char {
4736 if item == NL_ITEM_CODESET {
4737 return if LOCALE_CTYPE_UTF8 {
4738 b"UTF-8\0".as_ptr() as *mut c_char
4739 } else {
4740 b"US-ASCII\0".as_ptr() as *mut c_char
4741 };
4742 }
4743 let cat = item >> 16;
4744 let idx = item & 0xFFFF;
4745 match cat {
4746 1 => {
4747 if idx > 1 { return b"\0".as_ptr() as *mut c_char; }
4748 langinfo_str(C_NUMERIC_STRINGS.as_ptr(), idx)
4749 }
4750 2 => {
4751 if idx > 49 { return b"\0".as_ptr() as *mut c_char; }
4752 langinfo_str(C_TIME_STRINGS.as_ptr(), idx)
4753 }
4754 5 => {
4755 if idx > 1 { return b"\0".as_ptr() as *mut c_char; }
4756 langinfo_str(C_MESSAGES_STRINGS.as_ptr(), idx)
4757 }
4758 _ => b"\0".as_ptr() as *mut c_char,
4759 }
4760}
4761
4762pub type nl_catd = *mut c_void;
4763
4764#[no_mangle]
4765pub unsafe extern "C" fn catopen(_name: *const c_char, _oflag: c_int) -> nl_catd {
4766 !0usize as nl_catd
4767}
4768
4769#[no_mangle]
4770pub unsafe extern "C" fn catclose(_catd: nl_catd) -> c_int { 0 }
4771
4772#[no_mangle]
4773pub unsafe extern "C" fn catgets(catd: nl_catd, _set_id: c_int, _msg_id: c_int, s: *const c_char) -> *mut c_char {
4774 if catd == !0usize as nl_catd { return s as *mut c_char; }
4775 s as *mut c_char
4776}
4777
4778pub type IconvT = *mut c_void;
4779
4780const ENC_UTF8: i32 = 1;
4781const ENC_UTF16LE: i32 = 2;
4782const ENC_UTF16BE: i32 = 3;
4783const ENC_UTF32LE: i32 = 4;
4784const ENC_UTF32BE: i32 = 5;
4785const ENC_WCHAR_T: i32 = 6;
4786const ENC_ASCII: i32 = 7;
4787const ENC_LATIN1: i32 = 8;
4788const ENC_WIN1252: i32 = 9;
4789const ENC_WIN1251: i32 = 10;
4790const ENC_KOI8R: i32 = 11;
4791const ENC_GBK: i32 = 12;
4792const ENC_GB2312: i32 = 13;
4793const ENC_BIG5: i32 = 14;
4794const ENC_EUCJP: i32 = 15;
4795const ENC_SHIFTJIS: i32 = 16;
4796const ENC_ISO8859_2: i32 = 17;
4797const ENC_ISO8859_3: i32 = 18;
4798const ENC_ISO8859_4: i32 = 19;
4799const ENC_ISO8859_5: i32 = 20;
4800const ENC_ISO8859_6: i32 = 21;
4801const ENC_ISO8859_7: i32 = 22;
4802const ENC_ISO8859_8: i32 = 23;
4803const ENC_ISO8859_9: i32 = 24;
4804const ENC_ISO8859_10: i32 = 25;
4805const ENC_ISO8859_11: i32 = 26;
4806const ENC_ISO8859_13: i32 = 27;
4807const ENC_ISO8859_14: i32 = 28;
4808const ENC_ISO8859_15: i32 = 29;
4809const ENC_ISO8859_16: i32 = 30;
4810
4811include!("iconv_iso8859.rs");
4812
4813fn make_cd(from: i32, to: i32) -> IconvT {
4814 ((from as usize) << 16 | (to as usize) << 1 | 1) as IconvT
4815}
4816fn extract_from(cd: IconvT) -> i32 {
4817 ((cd as usize) >> 16) as i32
4818}
4819fn extract_to(cd: IconvT) -> i32 {
4820 (((cd as usize) >> 1) & 0x7fff) as i32
4821}
4822
4823unsafe fn match_name(input: *const u8, target: &[u8]) -> bool {
4824 let mut i = input;
4825 let mut j = 0;
4826 while *i != 0 && j < target.len() {
4827 let mut c = *i;
4828 if !c.is_ascii_alphanumeric() { i = i.add(1); continue; }
4829 c = c.to_ascii_lowercase();
4830 if c != target[j] { return false; }
4831 i = i.add(1);
4832 j += 1;
4833 }
4834 while *i != 0 && !(*i).is_ascii_alphanumeric() { i = i.add(1); }
4835 *i == 0 && j == target.len()
4836}
4837
4838unsafe fn find_encoding(name: *const u8) -> i32 {
4839 if name.is_null() { return -1; }
4840 if match_name(name, b"utf8") || match_name(name, b"utf-8") || match_name(name, b"char") { return ENC_UTF8; }
4841 if match_name(name, b"utf16le") || match_name(name, b"utf-16le") { return ENC_UTF16LE; }
4842 if match_name(name, b"utf16be") || match_name(name, b"utf-16be") { return ENC_UTF16BE; }
4843 if match_name(name, b"utf32le") || match_name(name, b"utf-32le") || match_name(name, b"ucs4le") { return ENC_UTF32LE; }
4844 if match_name(name, b"utf32be") || match_name(name, b"utf-32be") || match_name(name, b"ucs4be") { return ENC_UTF32BE; }
4845 if match_name(name, b"wchart") || match_name(name, b"wchar-t") { return ENC_WCHAR_T; }
4846 if match_name(name, b"ascii") || match_name(name, b"usascii") || match_name(name, b"iso646") { return ENC_ASCII; }
4847 if match_name(name, b"iso88591") || match_name(name, b"iso-8859-1") || match_name(name, b"latin1") { return ENC_LATIN1; }
4848 if match_name(name, b"iso88592") || match_name(name, b"iso-8859-2") { return ENC_ISO8859_2; }
4849 if match_name(name, b"iso88593") || match_name(name, b"iso-8859-3") { return ENC_ISO8859_3; }
4850 if match_name(name, b"iso88594") || match_name(name, b"iso-8859-4") { return ENC_ISO8859_4; }
4851 if match_name(name, b"iso88595") || match_name(name, b"iso-8859-5") { return ENC_ISO8859_5; }
4852 if match_name(name, b"iso88596") || match_name(name, b"iso-8859-6") { return ENC_ISO8859_6; }
4853 if match_name(name, b"iso88597") || match_name(name, b"iso-8859-7") { return ENC_ISO8859_7; }
4854 if match_name(name, b"iso88598") || match_name(name, b"iso-8859-8") { return ENC_ISO8859_8; }
4855 if match_name(name, b"iso88599") || match_name(name, b"iso-8859-9") { return ENC_ISO8859_9; }
4856 if match_name(name, b"iso885910") || match_name(name, b"iso-8859-10") { return ENC_ISO8859_10; }
4857 if match_name(name, b"iso885911") || match_name(name, b"iso-8859-11") || match_name(name, b"tis620") { return ENC_ISO8859_11; }
4858 if match_name(name, b"iso885913") || match_name(name, b"iso-8859-13") { return ENC_ISO8859_13; }
4859 if match_name(name, b"iso885914") || match_name(name, b"iso-8859-14") { return ENC_ISO8859_14; }
4860 if match_name(name, b"iso885915") || match_name(name, b"iso-8859-15") { return ENC_ISO8859_15; }
4861 if match_name(name, b"iso885916") || match_name(name, b"iso-8859-16") { return ENC_ISO8859_16; }
4862 if match_name(name, b"cp1252") || match_name(name, b"windows1252") || match_name(name, b"windows-1252") { return ENC_WIN1252; }
4863 if match_name(name, b"cp1251") || match_name(name, b"windows1251") || match_name(name, b"windows-1251") { return ENC_WIN1251; }
4864 if match_name(name, b"koi8r") || match_name(name, b"koi8-r") { return ENC_KOI8R; }
4865 if match_name(name, b"gbk") || match_name(name, b"cp936") { return ENC_GBK; }
4866 if match_name(name, b"gb2312") { return ENC_GB2312; }
4867 if match_name(name, b"big5") || match_name(name, b"bigfive") || match_name(name, b"cp950") { return ENC_BIG5; }
4868 if match_name(name, b"eucjp") || match_name(name, b"euc-jp") { return ENC_EUCJP; }
4869 if match_name(name, b"shiftjis") || match_name(name, b"sjis") || match_name(name, b"cp932") { return ENC_SHIFTJIS; }
4870 -1
4871}
4872
4873fn uni_to_jis(c: u32) -> u16 {
4874 let mut b = 0usize;
4875 let mut nel = REV_JIS.len();
4876 loop {
4877 let i = nel / 2;
4878 let j = REV_JIS[b + i] as usize;
4879 let row = j / 256;
4880 let col = j % 256;
4881 let d = JIS0208[row * 94 + col] as u32;
4882 if d == c { return (j as u16) + 0x2121; }
4883 if nel == 1 { return 0; }
4884 if c < d { nel /= 2; }
4885 else { b += i; nel -= nel / 2; }
4886 }
4887}
4888
4889unsafe fn iconv_decode(enc: i32, src: *const u8, src_left: usize) -> (u32, usize, c_int) {
4890 if src_left == 0 { return (0, 0, EINVAL); }
4891 match enc {
4892 ENC_UTF8 => {
4893 let c = *src;
4894 if c < 128 { return (c as u32, 1, 0); }
4895 if c < 0xC2 { return (0, 0, EILSEQ); }
4896 if c < 0xE0 {
4897 if src_left < 2 || (*src.add(1) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
4898 return (((c as u32 & 0x1F) << 6) | (*src.add(1) as u32 & 0x3F), 2, 0);
4899 }
4900 if c < 0xF0 {
4901 if src_left < 3 || (*src.add(1) & 0xC0) != 0x80 || (*src.add(2) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
4902 let cp = ((c as u32 & 0x0F) << 12) | ((*src.add(1) as u32 & 0x3F) << 6) | (*src.add(2) as u32 & 0x3F);
4903 if cp < 0x800 { return (0, 0, EILSEQ); }
4904 return (cp, 3, 0);
4905 }
4906 if c < 0xF8 {
4907 if src_left < 4 || (*src.add(1) & 0xC0) != 0x80 || (*src.add(2) & 0xC0) != 0x80 || (*src.add(3) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
4908 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);
4909 if cp < 0x10000 || cp >= 0x110000 { return (0, 0, EILSEQ); }
4910 return (cp, 4, 0);
4911 }
4912 (0, 0, EILSEQ)
4913 }
4914 ENC_UTF16LE => {
4915 if src_left < 2 { return (0, 0, EINVAL); }
4916 let c = (*src as u32) | ((*src.add(1) as u32) << 8);
4917 if c >= 0xD800 && c <= 0xDBFF {
4918 if src_left < 4 { return (0, 0, EINVAL); }
4919 let d = (*src.add(2) as u32) | ((*src.add(3) as u32) << 8);
4920 if d < 0xDC00 || d > 0xDFFF { return (0, 0, EILSEQ); }
4921 return (((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000, 4, 0);
4922 }
4923 if c >= 0xDC00 && c <= 0xDFFF { return (0, 0, EILSEQ); }
4924 (c, 2, 0)
4925 }
4926 ENC_UTF16BE => {
4927 if src_left < 2 { return (0, 0, EINVAL); }
4928 let c = ((*src as u32) << 8) | (*src.add(1) as u32);
4929 if c >= 0xD800 && c <= 0xDBFF {
4930 if src_left < 4 { return (0, 0, EINVAL); }
4931 let d = ((*src.add(2) as u32) << 8) | (*src.add(3) as u32);
4932 if d < 0xDC00 || d > 0xDFFF { return (0, 0, EILSEQ); }
4933 return (((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000, 4, 0);
4934 }
4935 if c >= 0xDC00 && c <= 0xDFFF { return (0, 0, EILSEQ); }
4936 (c, 2, 0)
4937 }
4938 ENC_UTF32LE => {
4939 if src_left < 4 { return (0, 0, EINVAL); }
4940 let c = (*src as u32) | ((*src.add(1) as u32) << 8) | ((*src.add(2) as u32) << 16) | ((*src.add(3) as u32) << 24);
4941 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
4942 if c >= 0x110000 { return (0, 0, EILSEQ); }
4943 (c, 4, 0)
4944 }
4945 ENC_UTF32BE => {
4946 if src_left < 4 { return (0, 0, EINVAL); }
4947 let c = ((*src as u32) << 24) | ((*src.add(1) as u32) << 16) | ((*src.add(2) as u32) << 8) | (*src.add(3) as u32);
4948 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
4949 if c >= 0x110000 { return (0, 0, EILSEQ); }
4950 (c, 4, 0)
4951 }
4952 ENC_WCHAR_T => {
4953 if src_left < 4 { return (0, 0, EINVAL); }
4954 let c = *(src as *const u32);
4955 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
4956 if c >= 0x110000 { return (0, 0, EILSEQ); }
4957 (c, 4, 0)
4958 }
4959 ENC_ASCII => {
4960 let c = *src as u32;
4961 if c >= 128 { return (0, 0, EILSEQ); }
4962 (c, 1, 0)
4963 }
4964 ENC_LATIN1 => (*src as u32, 1, 0),
4965 ENC_ISO8859_2 => (iso8859_to_u(&ISO8859_2_TO_U, *src), 1, 0),
4966 ENC_ISO8859_3 => (iso8859_to_u(&ISO8859_3_TO_U, *src), 1, 0),
4967 ENC_ISO8859_4 => (iso8859_to_u(&ISO8859_4_TO_U, *src), 1, 0),
4968 ENC_ISO8859_5 => (iso8859_to_u(&ISO8859_5_TO_U, *src), 1, 0),
4969 ENC_ISO8859_6 => (iso8859_to_u(&ISO8859_6_TO_U, *src), 1, 0),
4970 ENC_ISO8859_7 => (iso8859_to_u(&ISO8859_7_TO_U, *src), 1, 0),
4971 ENC_ISO8859_8 => (iso8859_to_u(&ISO8859_8_TO_U, *src), 1, 0),
4972 ENC_ISO8859_9 => (iso8859_to_u(&ISO8859_9_TO_U, *src), 1, 0),
4973 ENC_ISO8859_10 => (iso8859_to_u(&ISO8859_10_TO_U, *src), 1, 0),
4974 ENC_ISO8859_11 => (iso8859_to_u(&ISO8859_11_TO_U, *src), 1, 0),
4975 ENC_ISO8859_13 => (iso8859_to_u(&ISO8859_13_TO_U, *src), 1, 0),
4976 ENC_ISO8859_14 => (iso8859_to_u(&ISO8859_14_TO_U, *src), 1, 0),
4977 ENC_ISO8859_15 => (iso8859_to_u(&ISO8859_15_TO_U, *src), 1, 0),
4978 ENC_ISO8859_16 => (iso8859_to_u(&ISO8859_16_TO_U, *src), 1, 0),
4979 ENC_WIN1252 => {
4980 let b = *src;
4981 if b < 128 { return (b as u32, 1, 0); }
4982 (WIN1252_TO_U[b as usize - 128], 1, 0)
4983 }
4984 ENC_WIN1251 => {
4985 let b = *src;
4986 if b < 128 { return (b as u32, 1, 0); }
4987 (WIN1251_TO_U[b as usize - 128], 1, 0)
4988 }
4989 ENC_KOI8R => {
4990 let b = *src;
4991 if b < 128 { return (b as u32, 1, 0); }
4992 (KOI8R_TO_U[b as usize - 128], 1, 0)
4993 }
4994 ENC_GBK | ENC_GB2312 => {
4995 let c = *src;
4996 if c < 128 { return (c as u32, 1, 0); }
4997 if c == 128 { return (0x20AC, 1, 0); }
4998 if src_left < 2 { return (0, 0, EINVAL); }
4999 let d = *src.add(1);
5000 if d < 0x40 || d == 0x7F || d > 0xFE { return (0, 0, EILSEQ); }
5001 let row = (c as usize).wrapping_sub(0x81);
5002 if row >= 126 { return (0, 0, EILSEQ); }
5003 let mut col = (d as usize) - 0x40;
5004 if col > 63 { col -= 1; }
5005 let cp = GB18030_TABLE[row * 190 + col] as u32;
5006 if cp == 0 { return (0, 0, EILSEQ); }
5007 (cp, 2, 0)
5008 }
5009 ENC_BIG5 => {
5010 let c = *src;
5011 if c < 128 { return (c as u32, 1, 0); }
5012 if src_left < 2 { return (0, 0, EINVAL); }
5013 let d = *src.add(1);
5014 if d < 0x40 || d == 0x7F || d > 0xFE { return (0, 0, EILSEQ); }
5015 let mut col = (d as usize) - 0x40;
5016 if col > 0x3E { col -= 0x22; }
5017 if c >= 0xA1 && c < 0xFA {
5018 let row = (c as usize) - 0xA1;
5019 if row >= 89 { return (0, 0, EILSEQ); }
5020 let cp = BIG5_TABLE[row * 157 + col] as u32;
5021 if cp == 0 { return (0, 0, EILSEQ); }
5022 return (cp, 2, 0);
5023 }
5024 (0, 0, EILSEQ)
5025 }
5026 ENC_EUCJP => {
5027 let c = *src;
5028 if c < 128 { return (c as u32, 1, 0); }
5029 if c == 0x8E {
5030 if src_left < 2 { return (0, 0, EINVAL); }
5031 let d = *src.add(1);
5032 if d < 0xA1 || d > 0xDF { return (0, 0, EILSEQ); }
5033 return ((d as u32) + 0xFF61 - 0xA1, 2, 0);
5034 }
5035 if c < 0xA1 { return (0, 0, EILSEQ); }
5036 if src_left < 2 { return (0, 0, EINVAL); }
5037 let d = *src.add(1);
5038 if d < 0xA1 || d > 0xFE { return (0, 0, EILSEQ); }
5039 let row = (c as usize) - 0xA1;
5040 let col = (d as usize) - 0xA1;
5041 if row >= 84 || col >= 94 { return (0, 0, EILSEQ); }
5042 let cp = JIS0208[row * 94 + col] as u32;
5043 if cp == 0 { return (0, 0, EILSEQ); }
5044 (cp, 2, 0)
5045 }
5046 ENC_SHIFTJIS => {
5047 let c = *src;
5048 if c < 128 { return (c as u32, 1, 0); }
5049 if c >= 0xA1 && c <= 0xDF { return ((c as u32) + 0xFF61 - 0xA1, 1, 0); }
5050 if src_left < 2 { return (0, 0, EINVAL); }
5051 let d = *src.add(1);
5052 if d < 0x40 || d == 0x7F || d > 0xFC { return (0, 0, EILSEQ); }
5053 let row = if c >= 129 && c <= 159 { (c as usize) - 129 }
5054 else if c >= 224 && c <= 239 { (c as usize) - 193 }
5055 else { return (0, 0, EILSEQ); };
5056 let (col, row_adj) = if d >= 64 && d <= 158 && d != 127 {
5057 let mut dd = d as usize;
5058 if dd > 127 { dd -= 1; }
5059 (dd - 64, row * 2)
5060 } else if d >= 159 && d <= 252 {
5061 ((d as usize) - 159, row * 2 + 1)
5062 } else {
5063 return (0, 0, EILSEQ);
5064 };
5065 if row_adj >= 84 { return (0, 0, EILSEQ); }
5066 let cp = JIS0208[row_adj * 94 + col] as u32;
5067 if cp == 0 { return (0, 0, EILSEQ); }
5068 (cp, 2, 0)
5069 }
5070 _ => (0, 0, EILSEQ),
5071 }
5072}
5073
5074unsafe fn iconv_encode(enc: i32, c: u32, dst: *mut u8, dst_left: usize) -> (usize, c_int) {
5075 match enc {
5076 ENC_UTF8 => {
5077 if c < 0x80 {
5078 if dst_left < 1 { return (0, E2BIG); }
5079 *dst = c as u8; return (1, 0);
5080 }
5081 if c < 0x800 {
5082 if dst_left < 2 { return (0, E2BIG); }
5083 *dst = (0xC0 | (c >> 6)) as u8;
5084 *dst.add(1) = (0x80 | (c & 0x3F)) as u8;
5085 return (2, 0);
5086 }
5087 if c < 0x10000 {
5088 if dst_left < 3 { return (0, E2BIG); }
5089 *dst = (0xE0 | (c >> 12)) as u8;
5090 *dst.add(1) = (0x80 | ((c >> 6) & 0x3F)) as u8;
5091 *dst.add(2) = (0x80 | (c & 0x3F)) as u8;
5092 return (3, 0);
5093 }
5094 if dst_left < 4 { return (0, E2BIG); }
5095 *dst = (0xF0 | (c >> 18)) as u8;
5096 *dst.add(1) = (0x80 | ((c >> 12) & 0x3F)) as u8;
5097 *dst.add(2) = (0x80 | ((c >> 6) & 0x3F)) as u8;
5098 *dst.add(3) = (0x80 | (c & 0x3F)) as u8;
5099 (4, 0)
5100 }
5101 ENC_UTF16LE => {
5102 if c < 0x10000 {
5103 if dst_left < 2 { return (0, E2BIG); }
5104 *dst = (c & 0xFF) as u8;
5105 *dst.add(1) = (c >> 8) as u8;
5106 return (2, 0);
5107 }
5108 if dst_left < 4 { return (0, E2BIG); }
5109 let c = c - 0x10000;
5110 let hi = ((c >> 10) + 0xD800) as u16;
5111 let lo = ((c & 0x3FF) + 0xDC00) as u16;
5112 *dst = (hi & 0xFF) as u8; *dst.add(1) = (hi >> 8) as u8;
5113 *dst.add(2) = (lo & 0xFF) as u8; *dst.add(3) = (lo >> 8) as u8;
5114 (4, 0)
5115 }
5116 ENC_UTF16BE => {
5117 if c < 0x10000 {
5118 if dst_left < 2 { return (0, E2BIG); }
5119 *dst = (c >> 8) as u8;
5120 *dst.add(1) = (c & 0xFF) as u8;
5121 return (2, 0);
5122 }
5123 if dst_left < 4 { return (0, E2BIG); }
5124 let c = c - 0x10000;
5125 let hi = ((c >> 10) + 0xD800) as u16;
5126 let lo = ((c & 0x3FF) + 0xDC00) as u16;
5127 *dst = (hi >> 8) as u8; *dst.add(1) = (hi & 0xFF) as u8;
5128 *dst.add(2) = (lo >> 8) as u8; *dst.add(3) = (lo & 0xFF) as u8;
5129 (4, 0)
5130 }
5131 ENC_UTF32LE => {
5132 if dst_left < 4 { return (0, E2BIG); }
5133 *dst = (c & 0xFF) as u8; *dst.add(1) = ((c >> 8) & 0xFF) as u8;
5134 *dst.add(2) = ((c >> 16) & 0xFF) as u8; *dst.add(3) = (c >> 24) as u8;
5135 (4, 0)
5136 }
5137 ENC_UTF32BE => {
5138 if dst_left < 4 { return (0, E2BIG); }
5139 *dst = (c >> 24) as u8; *dst.add(1) = ((c >> 16) & 0xFF) as u8;
5140 *dst.add(2) = ((c >> 8) & 0xFF) as u8; *dst.add(3) = (c & 0xFF) as u8;
5141 (4, 0)
5142 }
5143 ENC_WCHAR_T => {
5144 if dst_left < 4 { return (0, E2BIG); }
5145 *(dst as *mut u32) = c;
5146 (4, 0)
5147 }
5148 ENC_ASCII => {
5149 if c < 128 {
5150 if dst_left < 1 { return (0, E2BIG); }
5151 *dst = c as u8; return (1, 0);
5152 }
5153 (0, EILSEQ)
5154 }
5155 ENC_LATIN1 => {
5156 if c < 256 {
5157 if dst_left < 1 { return (0, E2BIG); }
5158 *dst = c as u8; return (1, 0);
5159 }
5160 (0, EILSEQ)
5161 }
5162 ENC_ISO8859_2 => {
5163 if let Some(b) = u_to_iso8859(&ISO8859_2_TO_U, c) {
5164 if dst_left < 1 { return (0, E2BIG); }
5165 *dst = b; return (1, 0);
5166 }
5167 (0, EILSEQ)
5168 }
5169 ENC_ISO8859_3 => {
5170 if let Some(b) = u_to_iso8859(&ISO8859_3_TO_U, c) {
5171 if dst_left < 1 { return (0, E2BIG); }
5172 *dst = b; return (1, 0);
5173 }
5174 (0, EILSEQ)
5175 }
5176 ENC_ISO8859_4 => {
5177 if let Some(b) = u_to_iso8859(&ISO8859_4_TO_U, c) {
5178 if dst_left < 1 { return (0, E2BIG); }
5179 *dst = b; return (1, 0);
5180 }
5181 (0, EILSEQ)
5182 }
5183 ENC_ISO8859_5 => {
5184 if let Some(b) = u_to_iso8859(&ISO8859_5_TO_U, c) {
5185 if dst_left < 1 { return (0, E2BIG); }
5186 *dst = b; return (1, 0);
5187 }
5188 (0, EILSEQ)
5189 }
5190 ENC_ISO8859_6 => {
5191 if let Some(b) = u_to_iso8859(&ISO8859_6_TO_U, c) {
5192 if dst_left < 1 { return (0, E2BIG); }
5193 *dst = b; return (1, 0);
5194 }
5195 (0, EILSEQ)
5196 }
5197 ENC_ISO8859_7 => {
5198 if let Some(b) = u_to_iso8859(&ISO8859_7_TO_U, c) {
5199 if dst_left < 1 { return (0, E2BIG); }
5200 *dst = b; return (1, 0);
5201 }
5202 (0, EILSEQ)
5203 }
5204 ENC_ISO8859_8 => {
5205 if let Some(b) = u_to_iso8859(&ISO8859_8_TO_U, c) {
5206 if dst_left < 1 { return (0, E2BIG); }
5207 *dst = b; return (1, 0);
5208 }
5209 (0, EILSEQ)
5210 }
5211 ENC_ISO8859_9 => {
5212 if let Some(b) = u_to_iso8859(&ISO8859_9_TO_U, c) {
5213 if dst_left < 1 { return (0, E2BIG); }
5214 *dst = b; return (1, 0);
5215 }
5216 (0, EILSEQ)
5217 }
5218 ENC_ISO8859_10 => {
5219 if let Some(b) = u_to_iso8859(&ISO8859_10_TO_U, c) {
5220 if dst_left < 1 { return (0, E2BIG); }
5221 *dst = b; return (1, 0);
5222 }
5223 (0, EILSEQ)
5224 }
5225 ENC_ISO8859_11 => {
5226 if let Some(b) = u_to_iso8859(&ISO8859_11_TO_U, c) {
5227 if dst_left < 1 { return (0, E2BIG); }
5228 *dst = b; return (1, 0);
5229 }
5230 (0, EILSEQ)
5231 }
5232 ENC_ISO8859_13 => {
5233 if let Some(b) = u_to_iso8859(&ISO8859_13_TO_U, c) {
5234 if dst_left < 1 { return (0, E2BIG); }
5235 *dst = b; return (1, 0);
5236 }
5237 (0, EILSEQ)
5238 }
5239 ENC_ISO8859_14 => {
5240 if let Some(b) = u_to_iso8859(&ISO8859_14_TO_U, c) {
5241 if dst_left < 1 { return (0, E2BIG); }
5242 *dst = b; return (1, 0);
5243 }
5244 (0, EILSEQ)
5245 }
5246 ENC_ISO8859_15 => {
5247 if let Some(b) = u_to_iso8859(&ISO8859_15_TO_U, c) {
5248 if dst_left < 1 { return (0, E2BIG); }
5249 *dst = b; return (1, 0);
5250 }
5251 (0, EILSEQ)
5252 }
5253 ENC_ISO8859_16 => {
5254 if let Some(b) = u_to_iso8859(&ISO8859_16_TO_U, c) {
5255 if dst_left < 1 { return (0, E2BIG); }
5256 *dst = b; return (1, 0);
5257 }
5258 (0, EILSEQ)
5259 }
5260 ENC_WIN1252 => {
5261 if c < 128 {
5262 if dst_left < 1 { return (0, E2BIG); }
5263 *dst = c as u8; return (1, 0);
5264 }
5265 if c >= 0xA0 && c <= 0xFF && WIN1252_TO_U[c as usize - 128] == c {
5266 if dst_left < 1 { return (0, E2BIG); }
5267 *dst = c as u8; return (1, 0);
5268 }
5269 for i in 0..128usize {
5270 if WIN1252_TO_U[i] == c {
5271 if dst_left < 1 { return (0, E2BIG); }
5272 *dst = (i + 128) as u8; return (1, 0);
5273 }
5274 }
5275 (0, EILSEQ)
5276 }
5277 ENC_WIN1251 => {
5278 if c < 128 {
5279 if dst_left < 1 { return (0, E2BIG); }
5280 *dst = c as u8; return (1, 0);
5281 }
5282 for i in 0..128usize {
5283 if WIN1251_TO_U[i] == c {
5284 if dst_left < 1 { return (0, E2BIG); }
5285 *dst = (i + 128) as u8; return (1, 0);
5286 }
5287 }
5288 (0, EILSEQ)
5289 }
5290 ENC_KOI8R => {
5291 if c < 128 {
5292 if dst_left < 1 { return (0, E2BIG); }
5293 *dst = c as u8; return (1, 0);
5294 }
5295 for i in 0..128usize {
5296 if KOI8R_TO_U[i] == c {
5297 if dst_left < 1 { return (0, E2BIG); }
5298 *dst = (i + 128) as u8; return (1, 0);
5299 }
5300 }
5301 (0, EILSEQ)
5302 }
5303 ENC_GBK | ENC_GB2312 => {
5304 if c < 128 {
5305 if dst_left < 1 { return (0, E2BIG); }
5306 *dst = c as u8; return (1, 0);
5307 }
5308 if c == 0x20AC {
5309 if dst_left < 1 { return (0, E2BIG); }
5310 *dst = 128; return (1, 0);
5311 }
5312 for row in 0..126usize {
5313 for col in 0..190usize {
5314 if GB18030_TABLE[row * 190 + col] as u32 == c {
5315 if dst_left < 2 { return (0, E2BIG); }
5316 *dst = (row + 0x81) as u8;
5317 *dst.add(1) = if col <= 62 { (col + 0x40) as u8 } else { (col + 0x41) as u8 };
5318 return (2, 0);
5319 }
5320 }
5321 }
5322 (0, EILSEQ)
5323 }
5324 ENC_BIG5 => {
5325 if c < 128 {
5326 if dst_left < 1 { return (0, E2BIG); }
5327 *dst = c as u8; return (1, 0);
5328 }
5329 for row in 0..89usize {
5330 for col in 0..157usize {
5331 if BIG5_TABLE[row * 157 + col] as u32 == c {
5332 if dst_left < 2 { return (0, E2BIG); }
5333 *dst = (row + 0xA1) as u8;
5334 *dst.add(1) = if col <= 0x3E { (col + 0x40) as u8 } else { (col + 0x62) as u8 };
5335 return (2, 0);
5336 }
5337 }
5338 }
5339 (0, EILSEQ)
5340 }
5341 ENC_EUCJP => {
5342 if c < 128 {
5343 if dst_left < 1 { return (0, E2BIG); }
5344 *dst = c as u8; return (1, 0);
5345 }
5346 if c >= 0xFF61 && c <= 0xFF9F {
5347 if dst_left < 2 { return (0, E2BIG); }
5348 *dst = 0x8E;
5349 *dst.add(1) = (c - 0xFF61 + 0xA1) as u8;
5350 return (2, 0);
5351 }
5352 let jis = uni_to_jis(c);
5353 if jis == 0 { return (0, EILSEQ); }
5354 if dst_left < 2 { return (0, E2BIG); }
5355 *dst = ((jis >> 8) as u8).wrapping_add(0x80);
5356 *dst.add(1) = ((jis & 0xFF) as u8).wrapping_add(0x80);
5357 (2, 0)
5358 }
5359 ENC_SHIFTJIS => {
5360 if c < 128 {
5361 if dst_left < 1 { return (0, E2BIG); }
5362 *dst = c as u8; return (1, 0);
5363 }
5364 if c >= 0xFF61 && c <= 0xFF9F {
5365 if dst_left < 1 { return (0, E2BIG); }
5366 *dst = (c - 0xFF61 + 0xA1) as u8;
5367 return (1, 0);
5368 }
5369 let jis = uni_to_jis(c);
5370 if jis == 0 { return (0, EILSEQ); }
5371 if dst_left < 2 { return (0, E2BIG); }
5372 let r = (jis >> 8) as usize;
5373 let d = (jis & 0xFF) as usize;
5374 *dst = ((r + 1) / 2 + if r < 95 { 112 } else { 176 }) as u8;
5375 *dst.add(1) = if r % 2 == 1 { (d + 31 + d / 96) as u8 } else { (d + 126) as u8 };
5376 (2, 0)
5377 }
5378 _ => (0, EILSEQ),
5379 }
5380}
5381
5382#[no_mangle]
5383pub unsafe extern "C" fn iconv_open(tocode: *const c_char, fromcode: *const c_char) -> IconvT {
5384 let to = find_encoding(tocode as *const u8);
5385 let from = find_encoding(fromcode as *const u8);
5386 if to < 0 || from < 0 {
5387 ERRNO!() = EINVAL;
5388 return !0usize as IconvT;
5389 }
5390 make_cd(from, to)
5391}
5392
5393#[no_mangle]
5394pub unsafe extern "C" fn iconv(
5395 cd: IconvT,
5396 inbuf: *mut *mut c_char,
5397 inbytesleft: *mut SizeT,
5398 outbuf: *mut *mut c_char,
5399 outbytesleft: *mut SizeT,
5400) -> SizeT {
5401 if cd == !0usize as IconvT {
5402 ERRNO!() = EINVAL;
5403 return !0usize;
5404 }
5405 if inbuf.is_null() || outbuf.is_null() { return 0; }
5406 let from = extract_from(cd);
5407 let to = extract_to(cd);
5408 let mut src = *inbuf as *const u8;
5409 let mut dst = *outbuf as *mut u8;
5410 let mut src_left = *inbytesleft;
5411 let mut dst_left = *outbytesleft;
5412 let mut subst = 0usize;
5413 while src_left > 0 {
5414 let (cp, consumed, err) = iconv_decode(from, src, src_left);
5415 if err != 0 {
5416 if err == EINVAL { break; }
5417 ERRNO!() = err;
5418 return !0usize;
5419 }
5420 let (written, err) = iconv_encode(to, cp, dst, dst_left);
5421 if err != 0 {
5422 if err == E2BIG {
5423 ERRNO!() = E2BIG;
5424 return !0usize;
5425 }
5426 if dst_left < 1 {
5427 ERRNO!() = E2BIG;
5428 return !0usize;
5429 }
5430 *dst = b'*';
5431 dst = dst.add(1);
5432 dst_left -= 1;
5433 subst += 1;
5434 } else {
5435 dst = dst.add(written);
5436 dst_left -= written;
5437 }
5438 src = src.add(consumed);
5439 src_left -= consumed;
5440 }
5441 *inbuf = src as *mut c_char;
5442 *outbuf = dst as *mut c_char;
5443 *inbytesleft = src_left;
5444 *outbytesleft = dst_left;
5445 subst
5446}
5447
5448#[no_mangle]
5449pub unsafe extern "C" fn iconv_close(_cd: IconvT) -> c_int { 0 }
5450
5451#[no_mangle]
5456pub unsafe extern "C" fn write(fd: c_int, buf: *const c_void, count: SizeT) -> SSizeT {
5457 syscall_ret(sys_write(fd as i64, buf as *const u8, count)) as SSizeT
5458}
5459
5460#[no_mangle]
5461pub unsafe extern "C" fn read(fd: c_int, buf: *mut c_void, count: SizeT) -> SSizeT {
5462 syscall_ret(sys_read(fd as i64, buf as *mut u8, count)) as SSizeT
5463}
5464
5465#[no_mangle]
5466pub unsafe extern "C" fn open(path: *const c_char, flags: c_int, mode: c_int) -> c_int {
5467 syscall_ret(sys_open(path as *const u8, flags as i64, mode as i64)) as c_int
5468}
5469
5470#[no_mangle]
5471pub unsafe extern "C" fn close(fd: c_int) -> c_int {
5472 syscall_ret(sys_close(fd as i64)) as c_int
5473}
5474
5475#[no_mangle]
5476pub unsafe extern "C" fn lseek(fd: c_int, offset: i64, whence: c_int) -> i64 {
5477 syscall_ret(sys_lseek(fd as i64, offset, whence as i64))
5478}
5479
5480const O_RDONLY: i32 = 0;
5485const O_WRONLY: i32 = 1;
5486const O_RDWR: i32 = 2;
5487const O_CREAT: i32 = 64;
5488const O_TRUNC: i32 = 512;
5489const O_APPEND: i32 = 1024;
5490const O_EXCL: i32 = 128;
5491const O_NONBLOCK: i32 = 2048;
5492const O_NOFOLLOW: i32 = if cfg!(target_arch = "aarch64") { 0o100000 } else { 0o400000 };
5493const O_DIRECTORY: i32 = if cfg!(target_arch = "aarch64") { 0o40000 } else { 0o200000 };
5494const O_CLOEXEC: i32 = 0x80000;
5495
5496const F_GETFD: i32 = 1;
5497const F_SETFD: i32 = 2;
5498const F_GETFL: i32 = 3;
5499const F_SETFL: i32 = 4;
5500const F_GETLK: i32 = 5;
5501const F_SETLK: i32 = 6;
5502const F_SETLKW: i32 = 7;
5503const F_DUPFD: i32 = 0;
5504const F_DUPFD_CLOEXEC: i32 = 1030;
5505const FD_CLOEXEC: i32 = 1;
5506
5507const TIOCGWINSZ: u32 = 0x5413;
5508
5509#[repr(C)]
5510struct winsize {
5511 ws_row: u16,
5512 ws_col: u16,
5513 ws_xpixel: u16,
5514 ws_ypixel: u16,
5515}
5516
5517#[inline]
5518unsafe fn sys_pipe2(fds: *mut c_int, flags: i32) -> i64 {
5519 <Arch as Syscalls>::syscall2(SYS_PIPE2, fds as i64, flags as i64)
5520}
5521
5522#[inline]
5523unsafe fn sys_dup3(oldfd: i32, newfd: i32, flags: i32) -> i64 {
5524 <Arch as Syscalls>::syscall3(SYS_DUP3, oldfd as i64, newfd as i64, flags as i64)
5525}
5526
5527#[inline]
5528unsafe fn sys_fcntl(fd: i32, cmd: i32, arg: i64) -> i64 {
5529 <Arch as Syscalls>::syscall3(SYS_FCNTL, fd as i64, cmd as i64, arg as i64)
5530}
5531
5532#[inline]
5533unsafe fn sys_ioctl(fd: c_int, request: u32, arg: *mut u8) -> i64 {
5534 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, request as i64, arg as i64)
5535}
5536
5537#[inline]
5538unsafe fn sys_unlinkat(dirfd: i32, path: *const u8, flags: i32) -> i64 {
5539 <Arch as Syscalls>::syscall3(SYS_UNLINKAT, dirfd as i64, path as i64, flags as i64)
5540}
5541
5542#[inline]
5543unsafe fn sys_renameat2(olddirfd: i32, oldpath: *const u8, newdirfd: i32, newpath: *const u8, flags: u32) -> i64 {
5544 <Arch as Syscalls>::syscall5(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)
5545}
5546
5547const UNGET: usize = 8;
5552const F_PERM: u32 = 1;
5553const F_NORD: u32 = 4;
5554const F_NOWR: u32 = 8;
5555const F_EOF: u32 = 16;
5556const F_ERR: u32 = 32;
5557const F_SVB: u32 = 64;
5558const F_APP: u32 = 128;
5559
5560const BUFSIZ: usize = 1024;
5561
5562const _IOFBF: c_int = 0;
5563const _IOLBF: c_int = 1;
5564const _IONBF: c_int = 2;
5565
5566const SEEK_SET: c_int = 0;
5567const SEEK_CUR: c_int = 1;
5568const SEEK_END: c_int = 2;
5569
5570#[repr(C)]
5572pub struct FILE {
5573 flags: c_uint,
5574 rpos: *mut u8,
5575 rend: *mut u8,
5576 close: Option<unsafe extern "C" fn(*mut FILE) -> c_int>,
5577 wend: *mut u8,
5578 wpos: *mut u8,
5579 mustbezero_1: *mut u8,
5580 wbase: *mut u8,
5581 read_fn: Option<unsafe extern "C" fn(*mut FILE, *mut u8, usize) -> usize>,
5582 write_fn: Option<unsafe extern "C" fn(*mut FILE, *const u8, usize) -> usize>,
5583 seek_fn: Option<unsafe extern "C" fn(*mut FILE, i64, c_int) -> i64>,
5584 buf: *mut u8,
5585 buf_size: usize,
5586 prev: *mut FILE,
5587 next: *mut FILE,
5588 fd: c_int,
5589 pipe_pid: c_int,
5590 lockcount: c_long,
5591 mode: c_int,
5592 lock: c_int,
5593 lbf: c_int,
5594 cookie: *mut c_void,
5595 off: i64,
5596 getln_buf: *mut c_char,
5597 mustbezero_2: *mut c_void,
5598 shend: *mut u8,
5599 shlim: i64,
5600 shcnt: i64,
5601 ungotten: [c_int; UNGET],
5602 ungotten_count: c_int,
5603 _eof: c_int,
5604 _err: c_int,
5605}
5606
5607static mut STDIN_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
5608static mut STDOUT_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
5609static mut STDERR_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
5610
5611static mut STDIN_FILE: FILE = FILE {
5612 flags: 0, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
5613 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
5614 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
5615 read_fn: None, write_fn: None, seek_fn: None,
5616 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
5617 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
5618 fd: 0, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
5619 cookie: core::ptr::null_mut(), off: 0,
5620 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
5621 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
5622 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
5623};
5624static mut STDOUT_FILE: FILE = FILE {
5625 flags: F_NOWR as u32 + F_SVB as u32, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
5626 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
5627 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
5628 read_fn: None, write_fn: None, seek_fn: None,
5629 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
5630 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
5631 fd: 1, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
5632 cookie: core::ptr::null_mut(), off: 0,
5633 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
5634 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
5635 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
5636};
5637static mut STDERR_FILE: FILE = FILE {
5638 flags: F_NOWR as u32, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
5639 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
5640 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
5641 read_fn: None, write_fn: None, seek_fn: None,
5642 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
5643 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
5644 fd: 2, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
5645 cookie: core::ptr::null_mut(), off: 0,
5646 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
5647 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
5648 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
5649};
5650
5651#[no_mangle]
5652pub static mut stdin: *mut FILE = &raw mut STDIN_FILE as *mut FILE;
5653#[no_mangle]
5654pub static mut stdout: *mut FILE = &raw mut STDOUT_FILE as *mut FILE;
5655#[no_mangle]
5656pub static mut stderr: *mut FILE = &raw mut STDERR_FILE as *mut FILE;
5657
5658unsafe fn __stdio_init() {
5663 STDIN_FILE.buf = core::ptr::addr_of_mut!(STDIN_BUF) as *mut u8;
5664 STDIN_FILE.buf_size = BUFSIZ;
5665 STDIN_FILE.read_fn = Some(__stdio_read);
5666 STDIN_FILE.write_fn = Some(__stdio_write);
5667 STDIN_FILE.seek_fn = Some(__stdio_seek);
5668 STDOUT_FILE.buf = core::ptr::addr_of_mut!(STDOUT_BUF) as *mut u8;
5669 STDOUT_FILE.buf_size = BUFSIZ;
5670 STDOUT_FILE.lbf = b'\n' as c_int;
5671 STDOUT_FILE.read_fn = Some(__stdio_read);
5672 STDOUT_FILE.write_fn = Some(__stdio_write);
5673 STDOUT_FILE.seek_fn = Some(__stdio_seek);
5674 STDERR_FILE.buf = core::ptr::addr_of_mut!(STDERR_BUF) as *mut u8;
5675 STDERR_FILE.buf_size = BUFSIZ;
5676 STDERR_FILE.read_fn = Some(__stdio_read);
5677 STDERR_FILE.write_fn = Some(__stdio_write);
5678 STDERR_FILE.seek_fn = Some(__stdio_seek);
5679}
5680
5681unsafe fn buf_ptr(f: *mut FILE) -> *mut u8 {
5682 (f as *mut u8).add(core::mem::size_of::<FILE>())
5683}
5684
5685unsafe extern "C" fn __stdio_read(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
5686 let n = sys_read((*f).fd as i64, buf, len);
5687 if n <= 0 {
5688 if n == 0 { (*f).flags |= F_EOF; } else { (*f).flags |= F_ERR; (*f)._err = 1; }
5689 return 0;
5690 }
5691 n as usize
5692}
5693
5694unsafe extern "C" fn __stdio_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
5695 let l = (*f).wpos as usize - (*f).wbase as usize;
5696 let mut iov = [
5697 ((*f).wbase as *const u8, l),
5698 (buf, len),
5699 ];
5700 if iov[0].1 == 0 { iov = [iov[1], (core::ptr::null(), 0)]; }
5701 if (*f).flags & F_APP != 0 {
5702 let _ = sys_lseek((*f).fd as i64, 0, SEEK_END as i64);
5703 }
5704 let mut rem = iov[0].1 + iov[1].1;
5705 let mut idx = 0usize;
5706 while rem > 0 {
5707 let ptr = iov[idx].0;
5708 let cnt = iov[idx].1;
5709 if cnt == 0 { idx += 1; continue; }
5710 let n = sys_write((*f).fd as i64, ptr, cnt);
5711 if n <= 0 {
5712 (*f).wpos = core::ptr::null_mut();
5713 (*f).wbase = core::ptr::null_mut();
5714 (*f).wend = core::ptr::null_mut();
5715 (*f).flags |= F_ERR;
5716 return if iov[idx].0 == buf { 0 } else { len };
5717 }
5718 rem -= n as usize;
5719 iov[idx].0 = iov[idx].0.add(n as usize);
5720 iov[idx].1 -= n as usize;
5721 if iov[idx].1 == 0 { idx += 1; }
5722 }
5723 (*f).wend = (*f).buf.add((*f).buf_size);
5724 (*f).wbase = (*f).buf;
5725 (*f).wpos = (*f).buf;
5726 len
5727}
5728
5729unsafe extern "C" fn __stdio_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
5730 sys_lseek((*f).fd as i64, off, whence as i64)
5731}
5732
5733unsafe fn init_file(
5734 f: *mut FILE,
5735 fd: c_int,
5736 mode: *const c_char,
5737 close_fn: Option<unsafe extern "C" fn(*mut FILE) -> c_int>,
5738 buf_area: *mut u8,
5739 buf_sz: usize,
5740) {
5741 core::ptr::write_bytes(f as *mut u8, 0, core::mem::size_of::<FILE>());
5742 (*f).fd = fd;
5743 (*f).close = close_fn;
5744 (*f).lock = 0;
5745 (*f).lbf = -1;
5746 (*f).buf = buf_area;
5747 (*f).buf_size = buf_sz;
5748 (*f).read_fn = Some(__stdio_read);
5749 (*f).write_fn = Some(__stdio_write);
5750 (*f).seek_fn = Some(__stdio_seek);
5751 let m = *mode;
5752 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
5753 if m == b'r' as c_char && !has_plus {
5754 (*f).flags = F_NORD;
5755 } else if !has_plus {
5756 (*f).flags = F_NOWR;
5757 }
5758}
5759
5760unsafe extern "C" fn __stdio_close(f: *mut FILE) -> c_int {
5761 sys_close((*f).fd as i64);
5762 0
5763}
5764
5765unsafe fn fmodeflags(mode: *const c_char) -> c_int {
5766 let mut flags: c_int;
5767 let m = *mode;
5768 if !strchr(mode as *const u8, b'+' as c_int).is_null() {
5769 flags = O_RDWR;
5770 } else if m == b'r' as c_char {
5771 flags = O_RDONLY;
5772 } else {
5773 flags = O_WRONLY;
5774 }
5775 if !strchr(mode as *const u8, b'x' as c_int).is_null() { flags |= O_EXCL; }
5776 if !strchr(mode as *const u8, b'e' as c_int).is_null() { flags |= O_CLOEXEC; }
5777 if m != b'r' as c_char { flags |= O_CREAT; }
5778 if m == b'w' as c_char { flags |= O_TRUNC; }
5779 if m == b'a' as c_char { flags |= O_APPEND; }
5780 flags
5781}
5782
5783const O_ACCMODE: c_int = O_RDONLY | O_WRONLY | O_RDWR;
5784
5785unsafe fn flush_buf(f: *mut FILE) -> c_int {
5786 if (*f).wpos == (*f).wbase {
5787 if !(*f).wpos.is_null() {
5788 (*f).wend = (*f).buf.add((*f).buf_size);
5789 (*f).wpos = (*f).wbase;
5790 }
5791 return 0;
5792 }
5793 if let Some(wfunc) = (*f).write_fn {
5794 let ret = wfunc(f, core::ptr::null(), 0);
5795 if ret == 0 && (*f).wpos.is_null() { return -1; }
5796 return 0;
5797 }
5798 (*f).flags |= F_ERR;
5799 -1
5800}
5801
5802#[no_mangle]
5807pub unsafe extern "C" fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE {
5808 if filename.is_null() || mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
5809 let m = *mode;
5810 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
5811 ERRNO!() = EINVAL; return core::ptr::null_mut();
5812 }
5813 let flags = fmodeflags(mode);
5814 let fd = sys_open(filename as *const u8, flags as i64, 0o666);
5815 if fd < 0 { ERRNO!() = (-fd) as c_int; return core::ptr::null_mut(); }
5816 fdopen(fd as c_int, mode)
5817}
5818
5819#[no_mangle]
5820pub unsafe extern "C" fn fdopen(fd: c_int, mode: *const c_char) -> *mut FILE {
5821 if fd < 0 || mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
5822 let m = *mode;
5823 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
5824 ERRNO!() = EINVAL; return core::ptr::null_mut();
5825 }
5826 let f = calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
5827 if f.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
5828 let buf = buf_ptr(f);
5829 init_file(f, fd, mode, Some(__stdio_close), buf, BUFSIZ);
5830 if !strchr(mode as *const u8, b'a' as c_int).is_null() { (*f).flags |= F_APP; }
5831 if !strchr(mode as *const u8, b'e' as c_int).is_null() { sys_fcntl(fd, F_SETFD, FD_CLOEXEC as i64); }
5832 if (*f).flags & F_NOWR == 0 {
5833 let mut ws: winsize = core::mem::zeroed();
5834 if sys_ioctl(fd, TIOCGWINSZ, &mut ws as *mut winsize as *mut u8) == 0 {
5835 (*f).lbf = b'\n' as c_int;
5836 }
5837 }
5838 f
5839}
5840
5841#[no_mangle]
5842pub unsafe extern "C" fn freopen(
5843 filename: *const c_char, mode: *const c_char, f: *mut FILE,
5844) -> *mut FILE {
5845 fflush(f);
5846 if (*f).pipe_pid > 0 { let _ = __stdio_close(f); }
5847 if filename.is_null() {
5848 let flags = fmodeflags(mode);
5849 if flags == 0 { return core::ptr::null_mut(); }
5850 let mut fl = flags & !(O_CREAT | O_EXCL | O_CLOEXEC);
5851 if (*f).flags & F_APP != 0 { fl = (fl & !O_ACCMODE) | O_WRONLY | O_APPEND; }
5852 if sys_fcntl((*f).fd, F_SETFL, fl as i64) < 0 { return core::ptr::null_mut(); }
5853 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
5854 if has_plus {
5855 (*f).flags &= !(F_NORD | F_NOWR);
5856 } else if *mode == b'r' as c_char {
5857 (*f).flags = ((*f).flags & !F_NOWR) | F_NORD;
5858 } else {
5859 (*f).flags = ((*f).flags & !F_NORD) | F_NOWR;
5860 }
5861 return f;
5862 }
5863 let new_f = fopen(filename, mode);
5864 if new_f.is_null() { let _ = __stdio_close(f); return core::ptr::null_mut(); }
5865 if (*new_f).fd == (*f).fd {
5866 (*new_f).fd = -1;
5867 } else {
5868 sys_dup3((*new_f).fd, (*f).fd, 0);
5869 let _ = __stdio_close(new_f);
5870 }
5871 (*f).flags = (*new_f).flags;
5872 (*f).rpos = core::ptr::null_mut();
5873 (*f).rend = core::ptr::null_mut();
5874 (*f).wpos = core::ptr::null_mut();
5875 (*f).wbase = core::ptr::null_mut();
5876 (*f).wend = core::ptr::null_mut();
5877 (*f).lbf = (*new_f).lbf;
5878 (*f).pipe_pid = 0;
5879 free(new_f as *mut c_void);
5880 f
5881}
5882
5883#[no_mangle]
5884pub unsafe extern "C" fn fclose(f: *mut FILE) -> c_int {
5885 if f.is_null() { return -1; }
5886 let r = fflush(f);
5887 if let Some(close_fn) = (*f).close { let _ = close_fn(f); }
5888 if r != 0 { -1 } else { 0 }
5889}
5890
5891#[no_mangle]
5896pub unsafe extern "C" fn setvbuf(f: *mut FILE, buf: *mut c_char, mode: c_int, size: usize) -> c_int {
5897 if mode != _IOFBF && mode != _IOLBF && mode != _IONBF { return -1; }
5898 fflush(f);
5899 (*f).rpos = core::ptr::null_mut();
5900 (*f).rend = core::ptr::null_mut();
5901 (*f).wpos = core::ptr::null_mut();
5902 (*f).wbase = core::ptr::null_mut();
5903 (*f).wend = core::ptr::null_mut();
5904 if mode == _IONBF {
5905 (*f).buf_size = 0;
5906 } else if !buf.is_null() && size > 0 {
5907 (*f).buf = buf as *mut u8;
5908 (*f).buf_size = size;
5909 }
5910 (*f).lbf = if mode == _IOLBF { b'\n' as c_int } else { -1 };
5911 0
5912}
5913
5914#[no_mangle]
5915pub unsafe extern "C" fn setbuf(f: *mut FILE, buf: *mut c_char) {
5916 if buf.is_null() { setvbuf(f, core::ptr::null_mut(), _IONBF, 0); }
5917 else { setvbuf(f, buf, _IOFBF, BUFSIZ); }
5918}
5919
5920#[no_mangle]
5921pub unsafe extern "C" fn setbuffer(f: *mut FILE, buf: *mut c_char, size: usize) {
5922 if buf.is_null() { setvbuf(f, core::ptr::null_mut(), _IONBF, 0); }
5923 else { setvbuf(f, buf, _IOFBF, size); }
5924}
5925
5926#[no_mangle]
5927pub unsafe extern "C" fn fflush(f: *mut FILE) -> c_int {
5928 if f.is_null() {
5929 let mut r = 0;
5930 if !stdout.is_null() && !(*stdout).wpos.is_null() && (*stdout).wpos != (*stdout).wbase {
5931 if flush_buf(stdout) != 0 { r = -1; }
5932 }
5933 if !stderr.is_null() && !(*stderr).wpos.is_null() && (*stderr).wpos != (*stderr).wbase {
5934 if flush_buf(stderr) != 0 { r = -1; }
5935 }
5936 return r;
5937 }
5938 if !(*f).wpos.is_null() && (*f).wpos != (*f).wbase {
5939 return flush_buf(f);
5940 }
5941 0
5942}
5943
5944#[no_mangle]
5949pub unsafe extern "C" fn fwide(_f: *mut FILE, mode: c_int) -> c_int { mode }
5950
5951#[no_mangle]
5952pub unsafe extern "C" fn feof(f: *mut FILE) -> c_int { if (*f)._eof != 0 { 1 } else { 0 } }
5953
5954#[no_mangle]
5955pub unsafe extern "C" fn ferror(f: *mut FILE) -> c_int { if (*f)._err != 0 { 1 } else { 0 } }
5956
5957#[no_mangle]
5958pub unsafe extern "C" fn clearerr(f: *mut FILE) { (*f)._eof = 0; (*f)._err = 0; }
5959
5960#[no_mangle]
5961pub unsafe extern "C" fn fileno(f: *mut FILE) -> c_int { (*f).fd }
5962
5963#[no_mangle]
5968pub unsafe extern "C" fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int {
5969 fseeko(stream, offset as i64, whence)
5970}
5971
5972#[no_mangle]
5973pub unsafe extern "C" fn ftell(stream: *mut FILE) -> c_long {
5974 ftello(stream) as c_long
5975}
5976
5977#[no_mangle]
5978pub unsafe extern "C" fn rewind(stream: *mut FILE) {
5979 fseek(stream, 0, SEEK_SET);
5980 (*stream)._eof = 0;
5981 (*stream)._err = 0;
5982}
5983
5984#[no_mangle]
5985pub unsafe extern "C" fn fseeko(stream: *mut FILE, offset: i64, whence: c_int) -> c_int {
5986 if whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END {
5987 ERRNO!() = EINVAL;
5988 return -1;
5989 }
5990 let f = &mut *stream;
5991 let mut adj_offset = offset;
5992 if whence == SEEK_CUR {
5993 if !f.rpos.is_null() {
5994 adj_offset -= f.rend as i64 - f.rpos as i64;
5995 }
5996 adj_offset -= f.ungotten_count as i64;
5997 }
5998 if !f.wpos.is_null() && f.wpos != f.wbase {
5999 if flush_buf(stream) != 0 { return -1; }
6000 }
6001 f.wpos = core::ptr::null_mut();
6002 f.wbase = core::ptr::null_mut();
6003 f.wend = core::ptr::null_mut();
6004 if let Some(sfunc) = f.seek_fn {
6005 let r = sfunc(stream, adj_offset, whence);
6006 if r < 0 { return -1; }
6007 } else {
6008 ERRNO!() = EINVAL;
6009 return -1;
6010 }
6011 f.rpos = core::ptr::null_mut();
6012 f.rend = core::ptr::null_mut();
6013 f._eof = 0;
6014 f.ungotten_count = 0;
6015 0
6016}
6017
6018#[no_mangle]
6019pub unsafe extern "C" fn ftello(stream: *mut FILE) -> i64 {
6020 let f = &mut *stream;
6021 if f.flags & F_APP != 0 && !f.wpos.is_null() && f.wpos != f.wbase {
6022 if fflush(stream) != 0 { return -1; }
6023 }
6024 let sfunc = match f.seek_fn { Some(s) => s, None => return -1 };
6025 let pos = sfunc(stream, 0,
6026 if (f.flags & F_APP) != 0 && !f.wpos.is_null() && f.wpos != f.wbase { SEEK_END } else { SEEK_CUR });
6027 if pos < 0 { return -1; }
6028 let mut pos = pos;
6029 if !f.rpos.is_null() {
6030 pos += f.rpos as i64 - f.rend as i64;
6031 } else if !f.wbase.is_null() {
6032 pos += f.wpos as i64 - f.wbase as i64;
6033 }
6034 pos - f.ungotten_count as i64
6035}
6036
6037#[no_mangle]
6038pub unsafe extern "C" fn fgetpos(stream: *mut FILE, pos: *mut i64) -> c_int {
6039 let off = ftello(stream);
6040 if off < 0 { return -1; }
6041 *pos = off;
6042 0
6043}
6044
6045#[no_mangle]
6046pub unsafe extern "C" fn fsetpos(stream: *mut FILE, pos: *const i64) -> c_int {
6047 fseeko(stream, *pos, SEEK_SET)
6048}
6049
6050#[no_mangle]
6055pub unsafe extern "C" fn fgetc(stream: *mut FILE) -> c_int {
6056 let f = &mut *stream;
6057 if f.ungotten_count > 0 {
6058 f.ungotten_count -= 1;
6059 return f.ungotten[f.ungotten_count as usize];
6060 }
6061 if !f.rpos.is_null() && f.rpos < f.rend {
6062 let c = *f.rpos;
6063 f.rpos = f.rpos.add(1);
6064 return c as c_int;
6065 }
6066 if f._eof != 0 { return -1; }
6067 if let Some(rfunc) = f.read_fn {
6068 if !f.buf.is_null() && f.buf_size > 1 {
6072 let n = rfunc(stream, f.buf, f.buf_size);
6073 if n == 0 {
6074 if f.flags & F_ERR != 0 { f._err = 1; } else { f._eof = 1; }
6075 return -1;
6076 }
6077 f.rpos = f.buf;
6078 f.rend = f.buf.add(n);
6079 let c = *f.rpos;
6080 f.rpos = f.rpos.add(1);
6081 return c as c_int;
6082 }
6083 let mut buf = [0u8; 1];
6084 let n = rfunc(stream, buf.as_mut_ptr(), 1);
6085 if n == 0 {
6086 if f.flags & F_ERR != 0 { f._err = 1; } else { f._eof = 1; }
6087 return -1;
6088 }
6089 buf[0] as c_int
6090 } else {
6091 f._eof = 1;
6092 -1
6093 }
6094}
6095
6096#[no_mangle]
6097pub unsafe extern "C" fn getc(stream: *mut FILE) -> c_int { fgetc(stream) }
6098
6099#[no_mangle]
6100pub unsafe extern "C" fn getchar() -> c_int { fgetc(stdin) }
6101
6102#[no_mangle]
6103pub unsafe extern "C" fn ungetc(c: c_int, stream: *mut FILE) -> c_int {
6104 if c == -1 { return -1; }
6105 let f = &mut *stream;
6106 if f.ungotten_count >= UNGET as c_int { return -1; }
6107 f.ungotten[f.ungotten_count as usize] = c;
6108 f.ungotten_count += 1;
6109 f._eof = 0;
6110 c
6111}
6112
6113#[no_mangle]
6118pub unsafe extern "C" fn fgets(s: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char {
6119 if n <= 0 { return null_mut(); }
6120 let max = (n - 1) as usize;
6121 let mut i = 0usize;
6122 while i < max {
6123 let c = fgetc(stream);
6124 if c == -1 { if i == 0 { return null_mut(); } break; }
6125 *s.add(i) = c as c_char;
6126 i += 1;
6127 if c == b'\n' as c_int { break; }
6128 }
6129 *s.add(i) = 0;
6130 s
6131}
6132
6133#[no_mangle]
6135pub unsafe extern "C" fn gets(s: *mut c_char) -> *mut c_char {
6136 let mut i = 0usize;
6137 loop {
6138 let c = fgetc(stdin);
6139 if c == -1 { if i == 0 { return null_mut(); } break; }
6140 if c == b'\n' as c_int { break; }
6141 *s.add(i) = c as c_char;
6142 i += 1;
6143 }
6144 *s.add(i) = 0;
6145 s
6146}
6147
6148#[no_mangle]
6149pub unsafe extern "C" fn fopen64(filename: *const c_char, mode: *const c_char) -> *mut FILE {
6150 fopen(filename, mode)
6151}
6152
6153const PERROR_BUF_SIZE: usize = 64;
6155static mut PERROR_BUF: [u8; PERROR_BUF_SIZE] = [0; PERROR_BUF_SIZE];
6156
6157#[no_mangle]
6158pub unsafe extern "C" fn perror(msg: *const c_char) {
6159 let fd = (*stderr).fd;
6160 if !msg.is_null() && *msg != 0 {
6161 let len = strlen(msg as *const c_char);
6162 write_str(fd, msg as *const u8, len);
6163 write_str(fd, b": ".as_ptr(), 2);
6164 }
6165 let e = ERRNO!();
6166 let text = strerror(e) as *const u8;
6167 write_str(fd, text, strlen(text as *const c_char));
6168 write_str(fd, b"\n".as_ptr(), 1);
6169}
6170
6171#[no_mangle]
6172pub unsafe extern "C" fn fread(
6173 ptr: *mut c_void, size: SizeT, nmemb: SizeT, stream: *mut FILE,
6174) -> SizeT {
6175 if size == 0 || nmemb == 0 { return 0; }
6176 let total = size * nmemb;
6177 let mut rd = 0usize;
6178 while rd < total {
6179 let c = fgetc(stream);
6180 if c == -1 { break; }
6181 *(ptr as *mut u8).add(rd) = c as u8;
6182 rd += 1;
6183 }
6184 rd / size
6185}
6186
6187unsafe fn write_str(fd: c_int, s: *const u8, len: usize) {
6192 let mut written = 0usize;
6193 while written < len {
6194 let n = sys_write(fd as i64, s.add(written), len - written);
6195 if n <= 0 { break; }
6196 written += n as usize;
6197 }
6198}
6199
6200#[no_mangle]
6201unsafe fn __overflow(f: *mut FILE, c: c_int) -> c_int {
6202 if (*f).wpos.is_null() {
6203 (*f).wbase = (*f).buf;
6204 (*f).wpos = (*f).buf;
6205 (*f).wend = (*f).buf.add((*f).buf_size);
6206 }
6207 if flush_buf(f) == -1 { return -1; }
6208 if (*f).wpos >= (*f).wend {
6209 if let Some(wfunc) = (*f).write_fn {
6210 let byte = c as u8;
6211 let ret = wfunc(f, &byte as *const u8, 1);
6212 if ret == 0 { return -1; }
6213 }
6214 return c;
6215 }
6216 *(*f).wpos = c as u8;
6217 (*f).wpos = (*f).wpos.add(1);
6218 if c == (*f).lbf || (*f).wpos >= (*f).wend { let _ = flush_buf(f); }
6219 c
6220}
6221
6222#[no_mangle]
6223pub unsafe extern "C" fn puts(s: *const c_char) -> c_int {
6224 let len = strlen(s as *const c_char);
6225 let _ = fwrite(s as *const c_void, 1, len, stdout);
6226 let _ = fwrite(b"\n".as_ptr() as *const c_void, 1, 1, stdout);
6227 let f = &mut *stdout;
6228 if f.lbf >= 0 { let _ = flush_buf(stdout); }
6229 (len + 1) as c_int
6230}
6231
6232#[no_mangle]
6233pub unsafe extern "C" fn fputs(s: *const c_char, stream: *mut FILE) -> c_int {
6234 let len = strlen(s as *const c_char);
6235 fwrite(s as *const c_void, 1, len, stream) as c_int
6236}
6237
6238#[no_mangle]
6239pub unsafe extern "C" fn fputc(c: c_int, stream: *mut FILE) -> c_int {
6240 let f = &mut *stream;
6241 if f.wpos.is_null() || f.wpos >= f.wend {
6242 if __overflow(f, c) == -1 { return -1; }
6243 return c;
6244 }
6245 *f.wpos = c as u8;
6246 f.wpos = f.wpos.add(1);
6247 if c == f.lbf || f.wpos >= f.wend { let _ = flush_buf(f); }
6248 c
6249}
6250
6251#[no_mangle]
6252pub unsafe extern "C" fn putc(c: c_int, stream: *mut FILE) -> c_int { fputc(c, stream) }
6253
6254#[no_mangle]
6255pub unsafe extern "C" fn putchar(c: c_int) -> c_int { fputc(c, stdout) }
6256
6257#[no_mangle]
6258pub unsafe extern "C" fn fwrite(
6259 ptr: *const c_void, size: SizeT, nmemb: SizeT, stream: *mut FILE,
6260) -> SizeT {
6261 if size == 0 || nmemb == 0 { return 0; }
6262 let total = size * nmemb;
6263 let f = &mut *stream;
6264 if f.buf_size == 0 {
6265 if let Some(wfunc) = f.write_fn {
6266 let ret = wfunc(stream, ptr as *const u8, total);
6267 return ret / size;
6268 }
6269 return 0;
6270 }
6271 if f.wpos.is_null() {
6272 f.wbase = f.buf;
6273 f.wpos = f.buf;
6274 f.wend = f.buf.add(f.buf_size);
6275 }
6276 let mut remaining = total;
6277 let mut src = ptr as *const u8;
6278 while remaining > 0 {
6279 let space = f.wend as usize - f.wpos as usize;
6280 if space == 0 {
6281 if flush_buf(f as *mut FILE) == -1 { break; }
6282 continue;
6283 }
6284 let n = if remaining < space { remaining } else { space };
6285 core::ptr::copy_nonoverlapping(src, f.wpos, n);
6286 f.wpos = f.wpos.add(n);
6287 src = src.add(n);
6288 remaining -= n;
6289 if f.wpos >= f.wend { let _ = flush_buf(f as *mut FILE); }
6290 }
6291 if f.lbf >= 0 { let _ = flush_buf(f as *mut FILE); }
6292 (total - remaining) / size
6293}
6294
6295unsafe fn wide_to_mb(dst: *mut u8, cap: usize, src: *const wchar_t) -> usize {
6300 let mut o = 0usize;
6301 let mut i = 0usize;
6302 let mut st: c_uint = 0;
6303 while *src.add(i) != 0 {
6304 let mut tmp = [0u8; 8];
6305 let n = wcrtomb(tmp.as_mut_ptr() as *mut c_char, *src.add(i), &mut st);
6306 if n == !0usize || n == 0 { break; }
6307 if o + n > cap { break; }
6308 core::ptr::copy_nonoverlapping(tmp.as_ptr(), dst.add(o), n);
6309 o += n;
6310 i += 1;
6311 }
6312 o
6313}
6314
6315macro_rules! impl_format {
6316 ($fmt:expr, $args:expr, $write_char:expr, $write_str:expr) => {{
6317 let fmt = $fmt;
6318 let args = &mut $args;
6319 let mut count: usize = 0;
6320 let mut i = 0usize;
6321 loop {
6322 let c = *fmt.add(i) as u8;
6323 if c == 0 { break; }
6324 if c != b'%' {
6325 ($write_char)(c);
6326 count += 1; i += 1; continue;
6327 }
6328 i += 1;
6329 let mut flags: u8 = 0;
6331 loop {
6332 let fc = *fmt.add(i) as u8;
6333 match fc {
6334 b'-' => { flags |= FLAG_MINUS; i += 1; }
6335 b'+' => { flags |= FLAG_PLUS; i += 1; }
6336 b' ' => { flags |= FLAG_SPACE; i += 1; }
6337 b'0' => { flags |= FLAG_ZERO; i += 1; }
6338 b'#' => { flags |= FLAG_HASH; i += 1; }
6339 _ => break,
6340 }
6341 }
6342 let mut width: usize = 0;
6344 if *fmt.add(i) as u8 == b'*' {
6345 width = args.next_arg::<c_int>() as usize; i += 1;
6346 } else {
6347 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
6348 width = width * 10 + ((*fmt.add(i) as u8) - b'0') as usize; i += 1;
6349 }
6350 }
6351 let mut precision: i32 = -1;
6353 if *fmt.add(i) as u8 == b'.' {
6354 i += 1;
6355 if *fmt.add(i) as u8 == b'*' {
6356 precision = args.next_arg::<c_int>(); i += 1;
6357 } else {
6358 precision = 0;
6359 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
6360 precision = precision * 10 + ((*fmt.add(i) as u8) - b'0') as i32; i += 1;
6361 }
6362 }
6363 }
6364 let len_mod = *fmt.add(i) as u8;
6366 let spec: u8;
6367 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' {
6368 i += 1;
6369 let len_mod2 = *fmt.add(i) as u8;
6370 if (len_mod == b'h' && len_mod2 == b'h') || (len_mod == b'l' && len_mod2 == b'l') {
6371 i += 1;
6372 spec = *fmt.add(i) as u8;
6373 match (len_mod, len_mod2, spec) {
6375 (b'h', b'h', b'n') => {
6376 let p = args.next_arg::<*mut c_void>();
6377 if !p.is_null() { *(p as *mut u8) = count as u8; }
6378 }
6379 (b'l', b'l', b'n') => {
6380 let p = args.next_arg::<*mut c_void>();
6381 if !p.is_null() { *(p as *mut c_longlong) = count as c_longlong; }
6382 }
6383 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
6384 let val = args.next_arg::<c_longlong>();
6385 let neg = val < 0;
6386 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
6387 let b = format_u64(abs);
6388 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
6389 let mut fbuf = [0u8; 32];
6390 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
6391 ($write_str)(fbuf.as_ptr(), len); count += len;
6392 }
6393 (b'l', b'l', b'u') => {
6394 let val = args.next_arg::<c_ulonglong>();
6395 let b = format_u64(val as u64);
6396 let mut fbuf = [0u8; 32];
6397 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
6398 ($write_str)(fbuf.as_ptr(), len); count += len;
6399 }
6400 (b'l', b'l', b'o') => {
6401 let val = args.next_arg::<c_ulonglong>();
6402 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
6403 let mut fbuf = [0u8; 32];
6404 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
6405 ($write_str)(fbuf.as_ptr(), len); count += len;
6406 }
6407 (b'l', b'l', b'x') => {
6408 let val = args.next_arg::<c_ulonglong>();
6409 let b = format_hex(val as u64, false);
6410 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
6411 let mut fbuf = [0u8; 32];
6412 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6413 ($write_str)(fbuf.as_ptr(), len); count += len;
6414 }
6415 (b'l', b'l', b'X') => {
6416 let val = args.next_arg::<c_ulonglong>();
6417 let b = format_hex(val as u64, true);
6418 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
6419 let mut fbuf = [0u8; 32];
6420 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6421 ($write_str)(fbuf.as_ptr(), len); count += len;
6422 }
6423 _ => { ($write_char)(b'%'); ($write_char)(len_mod); ($write_char)(len_mod2); ($write_char)(spec); count += 4; }
6424 }
6425 } else {
6426 spec = len_mod2;
6427 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
6430 match (lm, spec) {
6431 (b'h', b'n') => {
6432 let p = args.next_arg::<*mut c_void>();
6433 if !p.is_null() { *(p as *mut u16) = count as u16; }
6434 }
6435 (b'l', b'n') => {
6436 let p = args.next_arg::<*mut c_void>();
6437 if !p.is_null() { *(p as *mut c_long) = count as c_long; }
6438 }
6439 (b'z', b'n') | (b't', b'n') => {
6440 let p = args.next_arg::<*mut c_void>();
6441 if !p.is_null() { *(p as *mut usize) = count; }
6442 }
6443 (b'j', b'n') => {
6444 let p = args.next_arg::<*mut c_void>();
6445 if !p.is_null() { *(p as *mut c_ulonglong) = count as c_ulonglong; }
6446 }
6447 (b'l', b'd') | (b'l', b'i') => {
6448 let val = args.next_arg::<c_long>();
6449 let neg = val < 0;
6450 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
6451 let b = format_u64(abs);
6452 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
6453 let mut fbuf = [0u8; 32];
6454 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
6455 ($write_str)(fbuf.as_ptr(), len); count += len;
6456 }
6457 (b'l', b'u') => {
6458 let val = args.next_arg::<c_ulong>();
6459 let b = format_u64(val as u64);
6460 let mut fbuf = [0u8; 32];
6461 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
6462 ($write_str)(fbuf.as_ptr(), len); count += len;
6463 }
6464 (b'l', b's') => {
6465 let p = args.next_arg::<*const wchar_t>();
6466 if p.is_null() {
6467 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
6468 let pad = width.saturating_sub(slen);
6469 if flags & FLAG_MINUS != 0 { ($write_str)(b"(null)".as_ptr(), slen); for _ in 0..pad { ($write_char)(b' '); } }
6470 else { for _ in 0..pad { ($write_char)(b' '); } ($write_str)(b"(null)".as_ptr(), slen); }
6471 count += slen + pad;
6472 } else {
6473 let mut mb = [0u8; 4096];
6474 let mut n = wide_to_mb(mb.as_mut_ptr(), mb.len(), p);
6475 if precision >= 0 && (precision as usize) < n { n = precision as usize; }
6476 let pad = width.saturating_sub(n);
6477 if flags & FLAG_MINUS != 0 { ($write_str)(mb.as_ptr(), n); for _ in 0..pad { ($write_char)(b' '); } }
6478 else { for _ in 0..pad { ($write_char)(b' '); } ($write_str)(mb.as_ptr(), n); }
6479 count += n + pad;
6480 }
6481 }
6482 (b'l', b'c') => {
6483 let ch = args.next_arg::<c_int>();
6484 let mut mb = [0u8; 8];
6485 let mut st: c_uint = 0;
6486 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, ch, &mut st);
6487 if n != !0usize { ($write_str)(mb.as_ptr(), n); count += n; }
6488 }
6489 (b'l', b'x') => {
6490 let val = args.next_arg::<c_ulong>();
6491 let b = format_hex(val as u64, false);
6492 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
6493 let mut fbuf = [0u8; 32];
6494 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6495 ($write_str)(fbuf.as_ptr(), len); count += len;
6496 }
6497 (b'l', b'X') => {
6498 let val = args.next_arg::<c_ulong>();
6499 let b = format_hex(val as u64, true);
6500 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
6501 let mut fbuf = [0u8; 32];
6502 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6503 ($write_str)(fbuf.as_ptr(), len); count += len;
6504 }
6505 (b'l', b'o') => {
6506 let val = args.next_arg::<c_ulong>();
6507 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
6508 let mut fbuf = [0u8; 32];
6509 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
6510 ($write_str)(fbuf.as_ptr(), len); count += len;
6511 }
6512 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
6513 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
6514 let val = args.next_arg::<f64>();
6515 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
6516 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
6517 let mut fbuf = [0u8; 4224];
6518 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
6519 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
6520 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
6521 ($write_str)(fbuf.as_ptr(), total); count += total;
6522 }
6523 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
6524 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
6525 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
6526 let val = {
6527 let lo: u64 = args.next_arg::<u64>();
6528 let hi: u64 = args.next_arg::<u64>();
6529 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
6530 f128::from_bits(combined) as f64
6531 };
6532 #[cfg(target_arch = "x86_64")]
6533 let val = args.next_arg::<f64>();
6534 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
6535 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
6536 let mut fbuf = [0u8; 4224];
6537 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
6538 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
6539 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
6540 ($write_str)(fbuf.as_ptr(), total); count += total;
6541 }
6542 _ => { ($write_char)(b'%'); ($write_char)(len_mod); ($write_char)(spec); count += 3; }
6543 }
6544 }
6545 } else {
6546 spec = *fmt.add(i) as u8;
6547 match spec {
6548 b's' => {
6549 let s = args.next_arg::<*const c_char>();
6550 if s.is_null() {
6551 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
6552 let padded_len = if width > slen { width } else { slen };
6553 let pad = padded_len - slen;
6554 if flags & FLAG_MINUS != 0 {
6555 ($write_str)(b"(null)".as_ptr(), slen);
6556 for _ in 0..pad { ($write_char)(b' '); }
6557 } else {
6558 for _ in 0..pad { ($write_char)(b' '); }
6559 ($write_str)(b"(null)".as_ptr(), slen);
6560 }
6561 count += padded_len;
6562 } else {
6563 let full_len = strlen(s as *const c_char);
6564 let slen = if precision >= 0 { (precision as usize).min(full_len) } else { full_len };
6565 let padded_len = if width > slen { width } else { slen };
6566 let pad = padded_len - slen;
6567 if flags & FLAG_MINUS != 0 {
6568 ($write_str)(s as *const u8, slen);
6569 for _ in 0..pad { ($write_char)(b' '); }
6570 } else {
6571 for _ in 0..pad { ($write_char)(b' '); }
6572 ($write_str)(s as *const u8, slen);
6573 }
6574 count += padded_len;
6575 }
6576 }
6577 b'd' | b'i' => {
6578 let d = args.next_arg::<c_int>();
6579 let neg = d < 0;
6580 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
6581 let b = format_u64(abs);
6582 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
6583 let mut fbuf = [0u8; 32];
6584 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
6585 ($write_str)(fbuf.as_ptr(), len); count += len;
6586 }
6587 b'u' => {
6588 let u = args.next_arg::<c_uint>();
6589 let b = format_u64(u as u64);
6590 let mut fbuf = [0u8; 32];
6591 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
6592 ($write_str)(fbuf.as_ptr(), len); count += len;
6593 }
6594 b'x' => {
6595 let x = args.next_arg::<c_uint>();
6596 let b = format_hex(x as u64, false);
6597 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
6598 let mut fbuf = [0u8; 32];
6599 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6600 ($write_str)(fbuf.as_ptr(), len); count += len;
6601 }
6602 b'X' => {
6603 let x = args.next_arg::<c_uint>();
6604 let b = format_hex(x as u64, true);
6605 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
6606 let mut fbuf = [0u8; 32];
6607 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
6608 ($write_str)(fbuf.as_ptr(), len); count += len;
6609 }
6610 b'o' => {
6611 let o = args.next_arg::<c_uint>();
6612 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
6613 let mut fbuf = [0u8; 32];
6614 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
6615 ($write_str)(fbuf.as_ptr(), len); count += len;
6616 }
6617 b'c' => {
6618 let ch = args.next_arg::<c_int>();
6619 if width > 1 {
6620 let pad = width - 1;
6621 if flags & FLAG_MINUS != 0 {
6622 ($write_char)(ch as u8); count += 1;
6623 for _ in 0..pad { ($write_char)(b' '); count += 1; }
6624 } else {
6625 for _ in 0..pad { ($write_char)(b' '); count += 1; }
6626 ($write_char)(ch as u8); count += 1;
6627 }
6628 } else {
6629 ($write_char)(ch as u8); count += 1;
6630 }
6631 }
6632 b'p' => {
6633 let p = args.next_arg::<*const c_void>();
6634 let mut fbuf = [0u8; 20];
6635 fbuf[0] = b'0'; fbuf[1] = b'x';
6636 let b = format_hex(p as u64, false);
6637 core::ptr::copy_nonoverlapping(b.0.as_ptr(), fbuf.as_mut_ptr().add(2), b.1);
6638 ($write_str)(fbuf.as_ptr(), b.1 + 2); count += b.1 + 2;
6639 }
6640 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
6641 let val = args.next_arg::<f64>();
6642 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
6643 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
6644 let mut fbuf = [0u8; 4224];
6645 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
6646 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
6647 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
6648 ($write_str)(fbuf.as_ptr(), total); count += total;
6649 }
6650 b'%' => { ($write_char)(b'%'); count += 1; }
6651 b'n' => {
6652 let p = args.next_arg::<*mut c_void>();
6653 if !p.is_null() { *(p as *mut c_int) = count as c_int; }
6654 }
6655 _ => { ($write_char)(b'%'); ($write_char)(spec); count += 2; }
6656 }
6657 }
6658 i += 1;
6659 }
6660 count as c_int
6661 }};
6662}
6663
6664unsafe fn format_u64(mut val: u64) -> ([u8; 20], usize) {
6665 let mut buf = [0u8; 20];
6666 if val == 0 { buf[0] = b'0'; return (buf, 1); }
6667 let mut tmp = [0u8; 20];
6668 let mut pos = 20;
6669 while val > 0 { pos -= 1; tmp[pos] = b'0' + (val % 10) as u8; val /= 10; }
6670 let len = 20 - pos;
6671 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
6672 (buf, len)
6673}
6674
6675unsafe fn format_i64(val: i64) -> ([u8; 21], usize) {
6676 let mut buf = [0u8; 21];
6677 if val < 0 {
6678 buf[0] = b'-';
6679 let (inner, len) = format_u64((-(val as i128)) as u64);
6680 core::ptr::copy_nonoverlapping(inner.as_ptr(), buf.as_mut_ptr().add(1), len);
6681 (buf, len + 1)
6682 } else {
6683 let (inner, len) = format_u64(val as u64);
6684 core::ptr::copy_nonoverlapping(inner.as_ptr(), buf.as_mut_ptr(), len);
6685 (buf, len)
6686 }
6687}
6688
6689unsafe fn format_hex(mut val: u64, uppercase: bool) -> ([u8; 16], usize) {
6690 let digits = if uppercase { b"0123456789ABCDEF" } else { b"0123456789abcdef" };
6691 let mut buf = [0u8; 16];
6692 if val == 0 { buf[0] = b'0'; return (buf, 1); }
6693 let mut tmp = [0u8; 16];
6694 let mut pos = 16;
6695 while val > 0 { pos -= 1; tmp[pos] = digits[(val & 0xf) as usize]; val >>= 4; }
6696 let len = 16 - pos;
6697 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
6698 (buf, len)
6699}
6700
6701unsafe fn format_octal(mut val: u64, alt: bool) -> ([u8; 24], usize) {
6702 let mut buf = [0u8; 24];
6703 if val == 0 {
6704 buf[0] = b'0';
6705 return (buf, 1);
6706 }
6707 let mut tmp = [0u8; 24];
6708 let mut pos = 24;
6709 while val > 0 {
6710 pos -= 1;
6711 tmp[pos] = b'0' + (val & 7) as u8;
6712 val >>= 3;
6713 }
6714 let len = 24 - pos;
6715 if alt {
6716 tmp[pos - 1] = b'0';
6717 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos - 1), buf.as_mut_ptr(), len + 1);
6718 (buf, len + 1)
6719 } else {
6720 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
6721 (buf, len)
6722 }
6723}
6724
6725unsafe fn format_int(
6726 dst: *mut u8,
6727 digits: *const u8,
6728 digits_len: usize,
6729 sign: Option<u8>,
6730 prefix: Option<u8>,
6731 precision: i32,
6732 width: usize,
6733 flags: u8,
6734 octal_alt: bool,
6735) -> usize {
6736 let num_digits = if precision == 0 && digits_len == 1 && *digits == b'0' && !octal_alt {
6737 0
6738 } else {
6739 digits_len
6740 };
6741 let prec = precision as usize;
6742 let zero_pad = if precision >= 0 && prec > num_digits { prec - num_digits } else { 0 };
6743
6744 let sign_len = sign.map_or(0, |_| 1);
6745 let prefix_len = prefix.map_or(0, |_| 2);
6746 let content_len = sign_len + prefix_len + zero_pad + num_digits;
6747
6748 let mut buf = [0u8; 32];
6749 let mut pos = 0usize;
6750 if let Some(c) = sign { buf[pos] = c; pos += 1; }
6751 if let Some(c) = prefix { buf[pos] = b'0'; pos += 1; buf[pos] = c; pos += 1; }
6752 for _ in 0..zero_pad { buf[pos] = b'0'; pos += 1; }
6753 if num_digits > 0 {
6754 core::ptr::copy_nonoverlapping(digits, buf.as_mut_ptr().add(pos), num_digits);
6755 }
6756
6757 if content_len >= width {
6758 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, content_len);
6759 return content_len;
6760 }
6761 let pad = width - content_len;
6762 if flags & FLAG_MINUS != 0 {
6763 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, content_len);
6764 for i in 0..pad { *dst.add(content_len + i) = b' '; }
6765 } else if flags & FLAG_ZERO != 0 && precision < 0 {
6766 let fixed = sign_len + prefix_len;
6767 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, fixed);
6768 for i in fixed..width - num_digits { *dst.add(i) = b'0'; }
6769 if num_digits > 0 {
6770 core::ptr::copy_nonoverlapping(digits, dst.add(width - num_digits), num_digits);
6771 }
6772 } else {
6773 for i in 0..pad { *dst.add(i) = b' '; }
6774 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst.add(pad), content_len);
6775 }
6776 width
6777}
6778
6779unsafe fn format_f64(val: f64) -> ([u8; 64], usize) {
6780 let mut buf = [0u8; 64];
6781 let mut pos = 0usize;
6782 let mut v = val;
6783 if v.is_nan() {
6784 let nan = b"nan";
6785 core::ptr::copy_nonoverlapping(nan.as_ptr(), buf.as_mut_ptr(), 3);
6786 return (buf, 3);
6787 }
6788 if v < 0.0 { buf[pos] = b'-'; pos += 1; v = -v; }
6789 if v.is_infinite() {
6790 let inf = b"inf";
6791 core::ptr::copy_nonoverlapping(inf.as_ptr(), buf.as_mut_ptr().add(pos), 3);
6792 return (buf, pos + 3);
6793 }
6794 let int_part = v as u64;
6795 let frac = v - int_part as f64;
6796 let (ibuf, ilen) = format_u64(int_part);
6797 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), buf.as_mut_ptr().add(pos), ilen);
6798 pos += ilen;
6799 buf[pos] = b'.';
6800 pos += 1;
6801 let mut f = frac;
6802 for _ in 0..6 { f *= 10.0; let digit = f as u8; buf[pos] = b'0' + digit; pos += 1; f -= digit as f64; }
6803 (buf, pos)
6804}
6805
6806const FMT_F: u8 = 0;
6808const FMT_E: u8 = 1;
6809const FMT_G: u8 = 2;
6810const FMT_A: u8 = 3;
6811
6812const FLAG_HASH: u8 = 1;
6813const FLAG_PLUS: u8 = 2;
6814const FLAG_SPACE: u8 = 4;
6815const FLAG_ZERO: u8 = 8;
6816const FLAG_MINUS: u8 = 16;
6817
6818unsafe fn bigint_to_decimal(buf: *mut u8, mant: u64, shift: u32) -> usize {
6823 let nlimbs = (2 + (shift + 31) / 32) as usize;
6825 let mut limbs = [0u32; 36];
6826 limbs[0] = mant as u32;
6827 limbs[1] = (mant >> 32) as u32;
6828
6829 let ws = (shift / 32) as usize;
6830 let bs = shift % 32;
6831
6832 if ws > 0 {
6834 let mut i = 1usize;
6835 loop {
6836 limbs[i + ws] = limbs[i];
6837 if i == 0 { break; }
6838 i -= 1;
6839 }
6840 for j in 0..ws { limbs[j] = 0; }
6841 }
6842 if bs > 0 {
6844 let mut carry = 0u32;
6845 let end = nlimbs.min(ws + 3);
6846 for i in ws..end {
6847 let new_val = (limbs[i] << bs) | carry;
6848 carry = limbs[i] >> (32 - bs);
6849 limbs[i] = new_val;
6850 }
6851 }
6852
6853 let mut used = nlimbs;
6855 while used > 0 && limbs[used - 1] == 0 { used -= 1; }
6856 if used == 0 { *buf = b'0'; return 1; }
6857
6858 let mut digits = [0u8; 400];
6860 let mut nd = 0usize;
6861 loop {
6862 let mut all_zero = true;
6863 for i in 0..used { if limbs[i] != 0 { all_zero = false; break; } }
6864 if all_zero { break; }
6865 let mut rem = 0u64;
6866 for i in (0..used).rev() {
6867 let val = (rem << 32) | limbs[i] as u64;
6868 limbs[i] = (val / 10) as u32;
6869 rem = val % 10;
6870 }
6871 digits[nd] = rem as u8;
6872 nd += 1;
6873 }
6874 for i in 0..nd { *buf.add(i) = b'0' + digits[nd - 1 - i]; }
6876 nd
6877}
6878
6879unsafe fn frac_digits_u128(buf: *mut u8, frac_bits: u64, shift: u32, count: usize) -> bool {
6882 let mask: u128 = (1u128 << shift) - 1;
6883 let mut rem = frac_bits as u128;
6884 for i in 0..count {
6885 rem *= 10;
6886 let digit = (rem >> shift) as u8;
6887 rem &= mask;
6888 *buf.add(i) = digit;
6889 }
6890 rem != 0
6891}
6892
6893unsafe fn frac_digits_bigint(buf: *mut u8, frac_bits: u64, shift: u32, count: usize) -> bool {
6896 let nlimbs = ((shift + 31) / 32) as usize;
6897 let mut rem = [0u32; 36]; rem[0] = frac_bits as u32;
6899 if nlimbs > 1 { rem[1] = (frac_bits >> 32) as u32; }
6900 let hi_word = (shift / 32) as usize;
6902 let hi_bit = shift % 32;
6903 if hi_bit > 0 && hi_word < nlimbs {
6904 rem[hi_word] &= (1u32 << hi_bit) - 1;
6905 }
6906 let clear_from = if hi_bit > 0 { hi_word + 1 } else { hi_word };
6908 for j in clear_from..nlimbs { rem[j] = 0; }
6909
6910 for i in 0..count {
6911 let mut carry = 0u64;
6913 for j in 0..nlimbs {
6914 let val = rem[j] as u64 * 10 + carry;
6915 rem[j] = val as u32;
6916 carry = val >> 32;
6917 }
6918 let digit: u32;
6920 if hi_bit == 0 {
6921 digit = if hi_word < nlimbs { rem[hi_word] } else { carry as u32 };
6922 } else {
6923 let mut d = if hi_word < nlimbs { rem[hi_word] >> hi_bit } else { 0 };
6924 if hi_word + 1 < nlimbs {
6925 d |= rem[hi_word + 1] << (32 - hi_bit);
6926 } else if carry > 0 {
6927 d |= (carry as u32) << (32 - hi_bit);
6928 }
6929 digit = d;
6930 }
6931 *buf.add(i) = digit.min(9) as u8;
6932 if hi_bit == 0 {
6934 if hi_word < nlimbs { rem[hi_word] = 0; }
6935 } else {
6936 if hi_word < nlimbs {
6937 rem[hi_word] &= (1u32 << hi_bit) - 1;
6938 }
6939 for j in (hi_word + 1)..nlimbs { rem[j] = 0; }
6940 }
6941 }
6942 for i in 0..nlimbs { if rem[i] != 0 { return true; } }
6944 false
6945}
6946
6947unsafe fn increment_decimal(buf: *mut u8, len: &mut usize) {
6949 let mut j = *len;
6950 loop {
6951 if j == 0 {
6952 let l = *len;
6954 for i in (0..l).rev() { *buf.add(i + 1) = *buf.add(i); }
6955 *buf = b'1';
6956 *len = l + 1;
6957 return;
6958 }
6959 j -= 1;
6960 let d = *buf.add(j);
6961 if d < b'9' { *buf.add(j) = d + 1; return; }
6962 *buf.add(j) = b'0';
6963 }
6964}
6965
6966unsafe fn format_f64_full(
6968 dst: *mut u8, val: f64, fmt_type: u8, precision: i32, flags: u8, uppercase: bool,
6969) -> usize {
6970 let mut pos = 0usize;
6971
6972 if val.is_nan() {
6974 let nan_s: &[u8] = if uppercase { b"NAN" } else { b"nan" };
6975 core::ptr::copy_nonoverlapping(nan_s.as_ptr(), dst, 3);
6976 return 3;
6977 }
6978 let neg = val.is_sign_negative();
6979 let v = if neg { -val } else { val };
6980
6981 if v.is_infinite() {
6983 if neg { *dst.add(pos) = b'-'; pos += 1; }
6984 else if flags & FLAG_PLUS != 0 { *dst.add(pos) = b'+'; pos += 1; }
6985 else if flags & FLAG_SPACE != 0 { *dst.add(pos) = b' '; pos += 1; }
6986 let inf_s: &[u8] = if uppercase { b"INF" } else { b"inf" };
6987 core::ptr::copy_nonoverlapping(inf_s.as_ptr(), dst.add(pos), 3);
6988 return pos + 3;
6989 }
6990
6991 if neg { *dst.add(pos) = b'-'; pos += 1; }
6993 else if flags & FLAG_PLUS != 0 { *dst.add(pos) = b'+'; pos += 1; }
6994 else if flags & FLAG_SPACE != 0 { *dst.add(pos) = b' '; pos += 1; }
6995
6996 if fmt_type == FMT_A {
6998 return pos + fmt_hex_float(dst.add(pos), val, precision, flags, uppercase);
6999 }
7000
7001 let p: usize;
7003 let mut exp: i32;
7004 let use_f: bool;
7005
7006 match fmt_type {
7007 FMT_G => {
7008 let gp = if precision < 0 { 6usize } else if precision == 0 { 1usize } else { precision as usize };
7009 exp = if v > 0.0 { compute_exp10(v) } else { 0 };
7010 use_f = exp >= -4 && exp < gp as i32;
7011 if use_f {
7012 p = if exp < 0 { gp + ((-exp) as usize - 1) }
7013 else if (exp as usize) < gp { gp - exp as usize - 1 }
7014 else { 0 };
7015 } else {
7016 p = gp - 1;
7017 }
7018 }
7019 FMT_E => {
7020 p = if precision < 0 { 6usize } else { precision as usize };
7021 exp = if v > 0.0 { compute_exp10(v) } else { 0 };
7022 use_f = false;
7023 }
7024 _ => {
7025 p = if precision < 0 { 6usize } else { precision as usize };
7026 exp = 0;
7027 use_f = true;
7028 }
7029 }
7030
7031 if v == 0.0 {
7032 *dst.add(pos) = b'0'; pos += 1;
7033 if !(fmt_type == FMT_G && flags & FLAG_HASH == 0) {
7034 if p > 0 || flags & FLAG_HASH != 0 {
7035 *dst.add(pos) = b'.'; pos += 1;
7036 for _ in 0..p { *dst.add(pos) = b'0'; pos += 1; }
7037 }
7038 }
7039 if !use_f {
7040 let ec = if uppercase { b'E' } else { b'e' };
7041 *dst.add(pos) = ec; pos += 1;
7042 *dst.add(pos) = b'+'; pos += 1;
7043 *dst.add(pos) = b'0'; pos += 1;
7044 *dst.add(pos) = b'0'; pos += 1;
7045 }
7046 return pos;
7047 }
7048
7049 if use_f {
7051 let bits = v.to_bits();
7052 let raw_mant = bits & 0x000FFFFFFFFFFFFF;
7053 let raw_exp_bits = ((bits >> 52) & 0x7FF) as i32;
7054 let (mant_b, bin_exp) = if raw_exp_bits == 0 {
7055 (raw_mant, -1022i32)
7056 } else {
7057 (raw_mant | (1u64 << 52), raw_exp_bits - 1023)
7058 };
7059
7060 let mut ibuf = [0u8; 400];
7062 let mut ilen: usize;
7063 if bin_exp < 0 {
7064 ibuf[0] = b'0'; ilen = 1;
7065 } else if bin_exp <= 63 {
7066 let int_val = if bin_exp <= 52 { mant_b >> (52 - bin_exp) }
7067 else { mant_b << (bin_exp - 52) };
7068 let (buf2, len2) = format_u64(int_val);
7069 ibuf[..len2].copy_from_slice(&buf2[..len2]);
7070 ilen = len2;
7071 } else {
7072 ilen = bigint_to_decimal(ibuf.as_mut_ptr(), mant_b, (bin_exp - 52) as u32);
7073 }
7074
7075 let mut fbuf = [0u8; 1100];
7077 let mut has_rest = false;
7078 if p > 0 && bin_exp < 52 {
7079 let shift = (52 - bin_exp) as u32;
7080 let frac_bits = if bin_exp >= 0 { mant_b & ((1u64 << shift) - 1) } else { mant_b };
7081 if shift <= 124 {
7082 has_rest = frac_digits_u128(fbuf.as_mut_ptr(), frac_bits, shift, p + 1);
7083 } else {
7084 has_rest = frac_digits_bigint(fbuf.as_mut_ptr(), frac_bits, shift, p + 1);
7085 }
7086 }
7087
7088 if p > 0 && bin_exp < 52 {
7090 let next_d = fbuf[p];
7091 let last_d = fbuf[p - 1];
7092 if next_d > 5 || (next_d == 5 && (has_rest || last_d & 1 != 0)) {
7093 let mut carry = true;
7094 for j in (0..p).rev() {
7095 if !carry { break; }
7096 fbuf[j] += 1;
7097 if fbuf[j] < 10 { carry = false; break; }
7098 fbuf[j] = 0;
7099 }
7100 if carry { increment_decimal(ibuf.as_mut_ptr(), &mut ilen); }
7101 }
7102 } else if p == 0 {
7103 if bin_exp >= 0 && bin_exp < 52 {
7105 let shift = (52 - bin_exp) as u32;
7106 let frac_bits = mant_b & ((1u64 << shift) - 1);
7107 let half = 1u64 << (shift - 1);
7108 let last_d = ibuf[ilen - 1] - b'0';
7109 if frac_bits > half || (frac_bits == half && last_d & 1 != 0) {
7110 increment_decimal(ibuf.as_mut_ptr(), &mut ilen);
7111 }
7112 }
7113 }
7114
7115 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), dst.add(pos), ilen);
7117 pos += ilen;
7118 if p > 0 || flags & FLAG_HASH != 0 {
7119 *dst.add(pos) = b'.'; pos += 1;
7120 for i in 0..p { *dst.add(pos) = b'0' + fbuf[i]; pos += 1; }
7121 }
7122 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7123 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7124 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7125 }
7126 return pos;
7127 }
7128
7129 let mut fbuf = [0u8; 20];
7132 let mut int_part: u64;
7133 {
7134 let bits_v = v.to_bits();
7135 let raw_mant_v = bits_v & 0x000FFFFFFFFFFFFF;
7136 let raw_exp_v = ((bits_v >> 52) & 0x7FF) as i32;
7137 let (mant_b_v, bin_exp_v) = if raw_exp_v == 0 {
7138 (raw_mant_v, -1022i32)
7139 } else {
7140 (raw_mant_v | (1u64 << 52), raw_exp_v - 1023)
7141 };
7142
7143 let s: i32 = (p as i32) + 1 - exp;
7144 let bs: i32 = bin_exp_v - 52 + s;
7145
7146 let mut limbs = [0u32; 40];
7147 limbs[0] = mant_b_v as u32;
7148 limbs[1] = (mant_b_v >> 32) as u32;
7149 let mut nlimbs: usize = if limbs[1] != 0 { 2 } else { 1 };
7150
7151 if s > 0 {
7152 for _ in 0..(s as usize) {
7153 let mut carry = 0u64;
7154 for j in 0..nlimbs {
7155 let val = limbs[j] as u64 * 5 + carry;
7156 limbs[j] = val as u32;
7157 carry = val >> 32;
7158 }
7159 if carry > 0 { limbs[nlimbs] = carry as u32; nlimbs += 1; }
7160 }
7161 }
7162
7163 if bs > 0 {
7164 let ws = (bs as u32 / 32) as usize;
7165 let bit = bs as u32 % 32;
7166 if ws > 0 {
7167 let mut i = nlimbs;
7168 while i > 0 { i -= 1; if i + ws < 40 { limbs[i + ws] = limbs[i]; } limbs[i] = 0; }
7169 nlimbs += ws;
7170 }
7171 if bit > 0 {
7172 let mut carry = 0u32;
7173 for i in ws..nlimbs {
7174 let new_val = (limbs[i] << bit) | carry;
7175 carry = limbs[i] >> (32 - bit);
7176 limbs[i] = new_val;
7177 }
7178 if carry > 0 && nlimbs < 40 { limbs[nlimbs] = carry; nlimbs += 1; }
7179 }
7180 }
7181
7182 let mut has_rest = false;
7183 if s < 0 {
7184 for _ in 0..(-s as usize) {
7185 let mut rem = 0u64;
7186 for i in (0..nlimbs).rev() {
7187 let val = (rem << 32) | limbs[i] as u64;
7188 limbs[i] = (val / 5) as u32;
7189 rem = val % 5;
7190 }
7191 if rem != 0 { has_rest = true; }
7192 }
7193 }
7194
7195 if bs < 0 {
7196 let rshift = (-bs) as u32;
7197 let ws = (rshift / 32) as usize;
7198 let bit = rshift % 32;
7199 if ws > 0 {
7200 for j in 0..ws.min(nlimbs) { if limbs[j] != 0 { has_rest = true; } }
7201 for i in ws..nlimbs { limbs[i - ws] = limbs[i]; }
7202 nlimbs = nlimbs.saturating_sub(ws);
7203 }
7204 if bit > 0 && nlimbs > 0 {
7205 let mask = (1u32 << bit) - 1;
7206 if limbs[0] & mask != 0 { has_rest = true; }
7207 for i in 0..nlimbs - 1 {
7208 limbs[i] = (limbs[i] >> bit) | (limbs[i + 1] << (32 - bit));
7209 }
7210 limbs[nlimbs - 1] >>= bit;
7211 }
7212 }
7213
7214 while nlimbs > 0 && limbs[nlimbs - 1] == 0 { nlimbs -= 1; }
7215
7216 let ndigits = p + 2;
7217 let mut all_digits = [0u8; 25];
7218 let mut nd = 0usize;
7219 if nlimbs > 0 {
7220 loop {
7221 let mut all_zero = true;
7222 for i in 0..nlimbs { if limbs[i] != 0 { all_zero = false; break; } }
7223 if all_zero { break; }
7224 let mut rem64 = 0u64;
7225 for i in (0..nlimbs).rev() {
7226 let val = (rem64 << 32) | limbs[i] as u64;
7227 limbs[i] = (val / 10) as u32;
7228 rem64 = val % 10;
7229 }
7230 if nd < 25 { all_digits[nd] = rem64 as u8; }
7231 nd += 1;
7232 }
7233 }
7234
7235 if nd >= ndigits {
7236 for i in 0..ndigits { fbuf[ndigits - 1 - i] = all_digits[i]; }
7237 } else {
7238 for i in 0..nd { fbuf[ndigits - 1 - i] = all_digits[i]; }
7239 for i in nd..ndigits { fbuf[ndigits - 1 - i] = 0; }
7240 }
7241
7242 int_part = fbuf[0] as u64;
7243
7244 if p > 0 {
7246 let next_d = fbuf[p + 1];
7247 let last_d = fbuf[p];
7248 if next_d > 5 || (next_d == 5 && (has_rest || last_d & 1 != 0)) {
7249 let mut carry = true;
7250 for j in (1..=p).rev() {
7251 if !carry { break; }
7252 let d = fbuf[j] + 1;
7253 if d < 10 { fbuf[j] = d; carry = false; break; }
7254 fbuf[j] = 0;
7255 }
7256 if carry { int_part += 1; }
7257 }
7258 } else {
7259 let next_d = fbuf[1];
7260 if next_d > 5 || (next_d == 5 && (has_rest || int_part & 1 != 0)) {
7261 int_part += 1;
7262 }
7263 }
7264
7265 for i in 0..p { fbuf[i] = fbuf[i + 1]; }
7268 }
7269
7270 if !use_f && int_part >= 10 {
7271 exp += 1;
7272 int_part = 1;
7273 }
7274
7275 if use_f {
7277 let (ibuf, ilen) = format_u64(int_part);
7279 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), dst.add(pos), ilen);
7280 pos += ilen;
7281 if p > 0 || flags & FLAG_HASH != 0 {
7282 *dst.add(pos) = b'.'; pos += 1;
7283 for idx in 0..p { *dst.add(pos) = b'0' + fbuf[idx]; pos += 1; }
7284 }
7285 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7286 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7287 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7288 }
7289 } else {
7290 *dst.add(pos) = b'0' + int_part as u8; pos += 1;
7292 if p > 0 || flags & FLAG_HASH != 0 {
7293 *dst.add(pos) = b'.'; pos += 1;
7294 for idx in 0..p { *dst.add(pos) = b'0' + fbuf[idx]; pos += 1; }
7295 }
7296 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7297 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7298 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7299 }
7300 let ec = if uppercase { b'E' } else { b'e' };
7301 *dst.add(pos) = ec; pos += 1;
7302 *dst.add(pos) = if exp < 0 { b'-' } else { b'+' }; pos += 1;
7303 let eabs = if exp < 0 { (-exp) as u32 } else { exp as u32 };
7304 if eabs < 10 { *dst.add(pos) = b'0'; pos += 1; }
7305 let (ebuf, elen) = format_u64(eabs as u64);
7306 core::ptr::copy_nonoverlapping(ebuf.as_ptr(), dst.add(pos), elen);
7307 pos += elen;
7308 }
7309
7310 pos
7311}
7312
7313unsafe fn compute_exp10(v: f64) -> i32 {
7315 let e = libm::floor(libm::log10(v)) as i32;
7316 let probe = v / libm::pow(10.0, e as f64);
7317 if probe >= 10.0 { e + 1 }
7318 else if probe < 1.0 { e - 1 }
7319 else { e }
7320}
7321
7322unsafe fn fmt_hex_float(dst: *mut u8, val: f64, precision: i32, _flags: u8, uppercase: bool) -> usize {
7324 if val.to_bits() & 0x7FFFFFFFFFFFFFFF == 0 {
7326 let lc = !uppercase;
7327 let pfx: &[u8] = if lc { b"0x" } else { b"0X" };
7328 let p = if precision < 0 { 0usize } else { precision as usize };
7329 let mut pos = 0usize;
7330 core::ptr::copy_nonoverlapping(pfx.as_ptr(), dst.add(pos), 2); pos += 2;
7331 *dst.add(pos) = b'0'; pos += 1;
7332 if p > 0 {
7333 *dst.add(pos) = b'.'; pos += 1;
7334 for _ in 0..p { *dst.add(pos) = b'0'; pos += 1; }
7335 }
7336 let pc = if lc { b'p' } else { b'P' };
7337 *dst.add(pos) = pc; pos += 1;
7338 *dst.add(pos) = b'+'; pos += 1;
7339 *dst.add(pos) = b'0'; pos += 1;
7340 return pos;
7341 }
7342 let bits = val.to_bits();
7343 let exp_bits = ((bits >> 52) & 0x7FF) as i32;
7344 let mant_bits = bits & 0x000FFFFFFFFFFFFF;
7345 let (mut e, mut m) = if exp_bits == 0 { (1 - 1023, mant_bits) } else { (exp_bits - 1023, mant_bits | (1u64 << 52)) };
7346 if exp_bits == 0 && m != 0 {
7349 let shift = m.leading_zeros() as i32 - 11;
7350 m <<= shift;
7351 e -= shift;
7352 }
7353 let explicit = precision >= 0;
7354 let p = if explicit { precision as usize } else { 13usize };
7355 let mut pos = 0usize;
7356 let lc = !uppercase;
7357 let pfx: &[u8] = if lc { b"0x" } else { b"0X" };
7358 core::ptr::copy_nonoverlapping(pfx.as_ptr(), dst.add(pos), 2); pos += 2;
7359
7360 let lead_pos = pos;
7362 let mut lead = ((m >> 52) & 0xF) as u8;
7363 *dst.add(pos) = hex_digit_char(lead, lc); pos += 1;
7364 let mut frac_start = pos;
7365 if p > 0 {
7366 *dst.add(pos) = b'.'; pos += 1;
7367 frac_start = pos;
7368 }
7369
7370 let mut rm = m;
7372 for _ in 0..p {
7373 let nib = ((rm >> 48) & 0xF) as u8;
7374 *dst.add(pos) = hex_digit_char(nib, lc); pos += 1;
7375 rm <<= 4;
7376 }
7377
7378 let round_nib = ((rm >> 48) & 0xF) as u8;
7380 let rest = rm & 0x0000FFFFFFFFFFFF;
7381 let last_nib = if p > 0 {
7382 hex_char_val(*dst.add(pos - 1))
7383 } else {
7384 lead
7385 };
7386 let should_round = round_nib > 8 || (round_nib == 8 && (rest != 0 || (last_nib & 1) != 0));
7387 if should_round {
7388 let mut j = pos;
7389 loop {
7390 if j == frac_start {
7391 lead += 1;
7393 *dst.add(lead_pos) = hex_digit_char(lead, lc);
7394 break;
7395 }
7396 j -= 1;
7397 let v = hex_char_val(*dst.add(j));
7398 if v < 15 {
7399 *dst.add(j) = hex_digit_char(v + 1, lc);
7400 break;
7401 }
7402 *dst.add(j) = b'0';
7403 }
7404 }
7405
7406 if !explicit {
7409 while pos > frac_start && *dst.add(pos - 1) == b'0' {
7410 pos -= 1;
7411 }
7412 if pos == frac_start {
7413 pos = frac_start - 1;
7414 }
7415 }
7416
7417 let pc = if lc { b'p' } else { b'P' };
7419 *dst.add(pos) = pc; pos += 1;
7420 *dst.add(pos) = if e < 0 { b'-' } else { b'+' }; pos += 1;
7421 let eabs = if e < 0 { (-e) as u32 } else { e as u32 };
7422 let (ebuf, elen) = format_u64(eabs as u64);
7423 core::ptr::copy_nonoverlapping(ebuf.as_ptr(), dst.add(pos), elen);
7424 pos += elen;
7425 pos
7426}
7427
7428#[inline]
7429fn hex_digit_char(v: u8, lowercase: bool) -> u8 {
7430 if v < 10 { b'0' + v }
7431 else if lowercase { b'a' + v - 10 }
7432 else { b'A' + v - 10 }
7433}
7434
7435#[inline]
7436fn hex_char_val(c: u8) -> u8 {
7437 if c >= b'0' && c <= b'9' { c - b'0' }
7438 else if c >= b'a' && c <= b'f' { c - b'a' + 10 }
7439 else if c >= b'A' && c <= b'F' { c - b'A' + 10 }
7440 else { 0 }
7441}
7442
7443unsafe fn apply_width_flags(
7446 dst: *mut u8, buf: *const u8, len: usize, width: usize, flags: u8,
7447) -> usize {
7448 if len >= width {
7449 core::ptr::copy_nonoverlapping(buf, dst, len);
7450 return len;
7451 }
7452 let pad = width - len;
7453 let pad_char = if flags & FLAG_ZERO != 0 && flags & FLAG_MINUS == 0 { b'0' } else { b' ' };
7454 if flags & FLAG_MINUS != 0 {
7455 core::ptr::copy_nonoverlapping(buf, dst, len);
7457 for i in 0..pad { *dst.add(len + i) = pad_char; }
7458 } else {
7459 if flags & FLAG_ZERO != 0 && len > 0 {
7462 let first = *buf;
7463 if first == b'-' || first == b'+' || first == b' ' {
7464 *dst = first;
7465 for i in 0..pad { *dst.add(1 + i) = pad_char; }
7466 core::ptr::copy_nonoverlapping(buf.add(1), dst.add(1 + pad), len - 1);
7467 return width;
7468 }
7469 }
7470 for i in 0..pad { *dst.add(i) = pad_char; }
7471 core::ptr::copy_nonoverlapping(buf, dst.add(pad), len);
7472 }
7473 width
7474}
7475
7476#[no_mangle]
7477pub unsafe extern "C" fn vprintf(fmt: *const c_char, mut args: VaList) -> c_int {
7478 impl_format!(fmt, args,
7479 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stdout); },
7480 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stdout); }
7481 )
7482}
7483
7484#[no_mangle]
7485pub unsafe extern "C" fn vfprintf(stream: *mut FILE, fmt: *const c_char, mut args: VaList) -> c_int {
7486 impl_format!(fmt, args,
7487 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stream); },
7488 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stream); }
7489 )
7490}
7491
7492#[no_mangle]
7493pub unsafe extern "C" fn printf(fmt: *const c_char, mut args: ...) -> c_int {
7494 impl_format!(fmt, args,
7495 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stdout); },
7496 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stdout); }
7497 )
7498}
7499
7500#[no_mangle]
7501pub unsafe extern "C" fn fprintf(stream: *mut FILE, fmt: *const c_char, mut args: ...) -> c_int {
7502 impl_format!(fmt, args,
7503 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stream); },
7504 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stream); }
7505 )
7506}
7507
7508#[no_mangle]
7509unsafe fn format_write_fd(fd: c_int, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
7510 let mut stack = [0u8; 4096];
7513 let mut a1 = args.clone();
7514 let n = format_to_buf(stack.as_mut_ptr(), stack.len(), fmt, &mut a1);
7515 if n < 0 { return -1; }
7516 if (n as usize) < stack.len() {
7517 let w = crate::write(fd, stack.as_ptr() as *const c_void, n as usize);
7518 if w < 0 { return -1; }
7519 return n;
7520 }
7521 let heap = crate::malloc(n as usize + 1) as *mut u8;
7522 if heap.is_null() { return -1; }
7523 let mut a2 = args.clone();
7524 let n2 = format_to_buf(heap, n as usize + 1, fmt, &mut a2);
7525 if n2 < 0 { crate::free(heap as *mut c_void); return -1; }
7526 let w = crate::write(fd, heap as *const c_void, n2 as usize);
7527 crate::free(heap as *mut c_void);
7528 if w < 0 { return -1; }
7529 n2
7530}
7531
7532#[no_mangle]
7533pub unsafe extern "C" fn dprintf(fd: c_int, fmt: *const c_char, mut args: ...) -> c_int {
7534 format_write_fd(fd, fmt, &mut args)
7535}
7536
7537#[no_mangle]
7538pub unsafe extern "C" fn vdprintf(fd: c_int, fmt: *const c_char, mut args: VaList) -> c_int {
7539 format_write_fd(fd, fmt, &mut args)
7540}
7541
7542unsafe fn format_to_buf(buf: *mut u8, cap: usize, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
7547 let mut pos = 0usize;
7548 let mut i = 0usize;
7549 let mut count = 0usize;
7550 macro_rules! wc {
7551 ($c:expr) => { if pos < cap { *buf.add(pos) = $c; } pos += 1; count += 1; }
7552 }
7553 macro_rules! ws {
7554 ($s:expr, $len:expr) => {{
7555 let __len = $len;
7556 for k in 0..__len { if pos + k < cap { *buf.add(pos + k) = *$s.add(k); } }
7557 pos += __len; count += __len;
7558 }}
7559 }
7560 macro_rules! ws_buf {
7562 ($src:expr, $len:expr) => {{
7563 let __len = $len;
7564 for k in 0..__len { if pos + k < cap { *buf.add(pos + k) = *$src.add(k); } }
7565 pos += __len; count += __len;
7566 }}
7567 }
7568 loop {
7569 let c = *fmt.add(i) as u8;
7570 if c == 0 { break; }
7571 if c != b'%' { wc!(c); i += 1; continue; }
7572 i += 1;
7573 let mut flags: u8 = 0;
7575 loop {
7576 let fc = *fmt.add(i) as u8;
7577 match fc {
7578 b'-' => { flags |= FLAG_MINUS; i += 1; }
7579 b'+' => { flags |= FLAG_PLUS; i += 1; }
7580 b' ' => { flags |= FLAG_SPACE; i += 1; }
7581 b'0' => { flags |= FLAG_ZERO; i += 1; }
7582 b'#' => { flags |= FLAG_HASH; i += 1; }
7583 _ => break,
7584 }
7585 }
7586 let mut width: usize = 0;
7588 if *fmt.add(i) as u8 == b'*' {
7589 width = args.next_arg::<c_int>() as usize; i += 1;
7590 } else {
7591 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
7592 width = width * 10 + ((*fmt.add(i) as u8) - b'0') as usize; i += 1;
7593 }
7594 }
7595 let mut precision: i32 = -1;
7597 if *fmt.add(i) as u8 == b'.' {
7598 i += 1;
7599 if *fmt.add(i) as u8 == b'*' {
7600 precision = args.next_arg::<c_int>(); i += 1;
7601 } else {
7602 precision = 0;
7603 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
7604 precision = precision * 10 + ((*fmt.add(i) as u8) - b'0') as i32; i += 1;
7605 }
7606 }
7607 }
7608 let len_mod = *fmt.add(i) as u8;
7610 let spec: u8;
7611 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' {
7612 i += 1;
7613 let len_mod2 = *fmt.add(i) as u8;
7614 if (len_mod == b'h' && len_mod2 == b'h') || (len_mod == b'l' && len_mod2 == b'l') {
7615 i += 1;
7616 spec = *fmt.add(i) as u8;
7617 match (len_mod, len_mod2, spec) {
7618 (b'h', b'h', b'n') => {
7619 let p = args.next_arg::<*mut c_void>();
7620 if !p.is_null() { *(p as *mut u8) = count as u8; }
7621 }
7622 (b'l', b'l', b'n') => {
7623 let p = args.next_arg::<*mut c_void>();
7624 if !p.is_null() { *(p as *mut c_longlong) = count as c_longlong; }
7625 }
7626 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
7627 let val = args.next_arg::<c_longlong>();
7628 let neg = val < 0;
7629 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
7630 let b = format_u64(abs);
7631 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7632 let mut fbuf = [0u8; 32];
7633 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7634 ws_buf!(fbuf.as_ptr(), len);
7635 }
7636 (b'l', b'l', b'u') => {
7637 let val = args.next_arg::<c_ulonglong>();
7638 let b = format_u64(val as u64);
7639 let mut fbuf = [0u8; 32];
7640 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7641 ws_buf!(fbuf.as_ptr(), len);
7642 }
7643 (b'l', b'l', b'o') => {
7644 let val = args.next_arg::<c_ulonglong>();
7645 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
7646 let mut fbuf = [0u8; 32];
7647 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7648 ws_buf!(fbuf.as_ptr(), len);
7649 }
7650 (b'l', b'l', b'x') | (b'l', b'l', b'X') => {
7651 let val = args.next_arg::<c_ulonglong>();
7652 let b = format_hex(val as u64, spec == b'X');
7653 let pc = if spec == b'X' { b'X' } else { b'x' };
7654 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(pc) } else { None };
7655 let mut fbuf = [0u8; 32];
7656 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7657 ws_buf!(fbuf.as_ptr(), len);
7658 }
7659 _ => { wc!(b'%'); wc!(len_mod); wc!(len_mod2); wc!(spec); }
7660 }
7661 } else {
7662 spec = len_mod2;
7663 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
7664 match (lm, spec) {
7665 (b'h', b'n') => {
7666 let p = args.next_arg::<*mut c_void>();
7667 if !p.is_null() { *(p as *mut u16) = count as u16; }
7668 }
7669 (b'l', b'n') => {
7670 let p = args.next_arg::<*mut c_void>();
7671 if !p.is_null() { *(p as *mut c_long) = count as c_long; }
7672 }
7673 (b'z', b'n') | (b't', b'n') => {
7674 let p = args.next_arg::<*mut c_void>();
7675 if !p.is_null() { *(p as *mut usize) = count; }
7676 }
7677 (b'j', b'n') => {
7678 let p = args.next_arg::<*mut c_void>();
7679 if !p.is_null() { *(p as *mut c_ulonglong) = count as c_ulonglong; }
7680 }
7681 (b'l', b'd') | (b'l', b'i') => {
7682 let val = args.next_arg::<c_long>();
7683 let neg = val < 0;
7684 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
7685 let b = format_u64(abs);
7686 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7687 let mut fbuf = [0u8; 32];
7688 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7689 ws_buf!(fbuf.as_ptr(), len);
7690 }
7691 (b'l', b'u') => {
7692 let val = args.next_arg::<c_ulong>();
7693 let b = format_u64(val as u64);
7694 let mut fbuf = [0u8; 32];
7695 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7696 ws_buf!(fbuf.as_ptr(), len);
7697 }
7698 (b'l', b's') => {
7699 let p = args.next_arg::<*const wchar_t>();
7700 if p.is_null() {
7701 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
7702 let pad = width.saturating_sub(slen);
7703 if flags & FLAG_MINUS != 0 { ws!(b"(null)".as_ptr(), slen); for _ in 0..pad { wc!(b' '); } }
7704 else { for _ in 0..pad { wc!(b' '); } ws!(b"(null)".as_ptr(), slen); }
7705 } else {
7706 let mut mb = [0u8; 4096];
7707 let mut n = wide_to_mb(mb.as_mut_ptr(), mb.len(), p);
7708 if precision >= 0 && (precision as usize) < n { n = precision as usize; }
7709 let pad = width.saturating_sub(n);
7710 if flags & FLAG_MINUS != 0 { ws!(mb.as_ptr(), n); for _ in 0..pad { wc!(b' '); } }
7711 else { for _ in 0..pad { wc!(b' '); } ws!(mb.as_ptr(), n); }
7712 }
7713 }
7714 (b'l', b'c') => {
7715 let ch = args.next_arg::<c_int>();
7716 let mut mb = [0u8; 8];
7717 let mut st: c_uint = 0;
7718 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, ch, &mut st);
7719 if n != !0usize { ws!(mb.as_ptr(), n); }
7720 }
7721 (b'l', b'x') => {
7722 let val = args.next_arg::<c_ulong>();
7723 let b = format_hex(val as u64, false);
7724 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
7725 let mut fbuf = [0u8; 32];
7726 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7727 ws_buf!(fbuf.as_ptr(), len);
7728 }
7729 (b'l', b'X') => {
7730 let val = args.next_arg::<c_ulong>();
7731 let b = format_hex(val as u64, true);
7732 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
7733 let mut fbuf = [0u8; 32];
7734 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7735 ws_buf!(fbuf.as_ptr(), len);
7736 }
7737 (b'l', b'o') => {
7738 let val = args.next_arg::<c_ulong>();
7739 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
7740 let mut fbuf = [0u8; 32];
7741 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7742 ws_buf!(fbuf.as_ptr(), len);
7743 }
7744 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
7745 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
7746 let val = args.next_arg::<f64>();
7747 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7748 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7749 let mut fbuf = [0u8; 4224];
7750 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7751 let mut wbuf = [0u8; 4224];
7752 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
7753 ws_buf!(wbuf.as_ptr(), wlen);
7754 }
7755 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
7756 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
7757 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
7758 let val = {
7759 let lo: u64 = args.next_arg::<u64>();
7760 let hi: u64 = args.next_arg::<u64>();
7761 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
7762 f128::from_bits(combined) as f64
7763 };
7764 #[cfg(target_arch = "x86_64")]
7765 let val = args.next_arg::<f64>();
7766 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7767 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7768 let mut fbuf = [0u8; 4224];
7769 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7770 let mut wbuf = [0u8; 4224];
7771 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
7772 ws_buf!(wbuf.as_ptr(), wlen);
7773 }
7774 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); }
7775 }
7776 }
7777 } else {
7778 spec = *fmt.add(i) as u8;
7779 match spec {
7780 b's' => {
7781 let s = args.next_arg::<*const c_char>();
7782 if s.is_null() {
7783 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
7784 let padded_len = if width > slen { width } else { slen };
7785 let pad = padded_len - slen;
7786 if flags & FLAG_MINUS != 0 {
7787 ws!(b"(null)".as_ptr(), slen);
7788 for _ in 0..pad { wc!(b' '); }
7789 } else {
7790 for _ in 0..pad { wc!(b' '); }
7791 ws!(b"(null)".as_ptr(), slen);
7792 }
7793 } else {
7794 let full_len = strlen(s as *const c_char);
7795 let slen = if precision >= 0 { (precision as usize).min(full_len) } else { full_len };
7796 let padded_len = if width > slen { width } else { slen };
7797 let pad = padded_len - slen;
7798 if flags & FLAG_MINUS != 0 {
7799 ws!(s as *const u8, slen);
7800 for _ in 0..pad { wc!(b' '); }
7801 } else {
7802 for _ in 0..pad { wc!(b' '); }
7803 ws!(s as *const u8, slen);
7804 }
7805 }
7806 }
7807 b'd' | b'i' => {
7808 let d = args.next_arg::<c_int>();
7809 let neg = d < 0;
7810 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
7811 let b = format_u64(abs);
7812 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7813 let mut fbuf = [0u8; 32];
7814 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7815 ws_buf!(fbuf.as_ptr(), len);
7816 }
7817 b'u' => {
7818 let u = args.next_arg::<c_uint>();
7819 let b = format_u64(u as u64);
7820 let mut fbuf = [0u8; 32];
7821 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7822 ws_buf!(fbuf.as_ptr(), len);
7823 }
7824 b'x' => {
7825 let x = args.next_arg::<c_uint>();
7826 let b = format_hex(x as u64, false);
7827 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
7828 let mut fbuf = [0u8; 32];
7829 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7830 ws_buf!(fbuf.as_ptr(), len);
7831 }
7832 b'X' => {
7833 let x = args.next_arg::<c_uint>();
7834 let b = format_hex(x as u64, true);
7835 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
7836 let mut fbuf = [0u8; 32];
7837 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7838 ws_buf!(fbuf.as_ptr(), len);
7839 }
7840 b'o' => {
7841 let o = args.next_arg::<c_uint>();
7842 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
7843 let mut fbuf = [0u8; 32];
7844 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7845 ws_buf!(fbuf.as_ptr(), len);
7846 }
7847 b'c' => {
7848 let ch = args.next_arg::<c_int>();
7849 if width > 1 {
7850 let pad = width - 1;
7851 if flags & FLAG_MINUS != 0 {
7852 wc!(ch as u8);
7853 for _ in 0..pad { wc!(b' '); }
7854 } else {
7855 for _ in 0..pad { wc!(b' '); }
7856 wc!(ch as u8);
7857 }
7858 } else {
7859 wc!(ch as u8);
7860 }
7861 }
7862 b'p' => {
7863 wc!(b'0'); wc!(b'x');
7864 let p = args.next_arg::<*const c_void>();
7865 let b = format_hex(p as u64, false);
7866 ws!(b.0.as_ptr(), b.1);
7867 }
7868 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
7869 let val = args.next_arg::<f64>();
7870 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7871 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7872 let mut fbuf = [0u8; 4224];
7873 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7874 let mut wbuf = [0u8; 4224];
7875 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
7876 ws_buf!(wbuf.as_ptr(), wlen);
7877 }
7878 b'%' => { wc!(b'%'); }
7879 b'n' => {
7880 let p = args.next_arg::<*mut c_void>();
7881 if !p.is_null() { *(p as *mut c_int) = count as c_int; }
7882 }
7883 _ => { wc!(b'%'); wc!(spec); }
7884 }
7885 }
7886 i += 1;
7887 }
7888 if cap > 0 { let null_pos = if pos < cap { pos } else { cap - 1 }; *buf.add(null_pos) = 0; }
7889 count as c_int
7890}
7891
7892#[no_mangle]
7893pub unsafe extern "C" fn vsprintf(buf: *mut c_char, fmt: *const c_char, mut args: VaList) -> c_int {
7894 format_to_buf(buf as *mut u8, usize::MAX, fmt, &mut args)
7895}
7896
7897#[no_mangle]
7898pub unsafe extern "C" fn vsnprintf(buf: *mut c_char, size: usize, fmt: *const c_char, mut args: VaList) -> c_int {
7899 format_to_buf(buf as *mut u8, size, fmt, &mut args)
7900}
7901
7902#[no_mangle]
7903pub unsafe extern "C" fn sprintf(buf: *mut c_char, fmt: *const c_char, mut args: ...) -> c_int {
7904 format_to_buf(buf as *mut u8, usize::MAX, fmt, &mut args)
7905}
7906
7907#[no_mangle]
7908pub unsafe extern "C" fn snprintf(buf: *mut c_char, size: usize, fmt: *const c_char, mut args: ...) -> c_int {
7909 format_to_buf(buf as *mut u8, size, fmt, &mut args)
7910}
7911
7912#[no_mangle]
7913pub unsafe extern "C" fn vasprintf(strp: *mut *mut c_char, fmt: *const c_char, ap: VaList) -> c_int {
7914 let len = vsnprintf(core::ptr::null_mut(), 0, fmt, ap.clone());
7915 if len < 0 {
7916 *strp = core::ptr::null_mut();
7917 return -1;
7918 }
7919 let p = malloc((len as usize) + 1) as *mut c_char;
7920 if p.is_null() {
7921 *strp = core::ptr::null_mut();
7922 return -1;
7923 }
7924 let ret = vsnprintf(p, (len as usize) + 1, fmt, ap.clone());
7925 if ret < 0 {
7926 free(p as *mut c_void);
7927 *strp = core::ptr::null_mut();
7928 return -1;
7929 }
7930 *strp = p;
7931 ret
7932}
7933
7934#[no_mangle]
7935pub unsafe extern "C" fn asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int {
7936 vasprintf(strp, fmt, args)
7937}
7938
7939unsafe fn skip_ws(p: *const u8) -> *const u8 {
7944 let mut q = p;
7945 while *q == b' ' || *q == b'\t' || *q == b'\n' || *q == b'\r' { q = q.add(1); }
7946 q
7947}
7948
7949#[inline]
7950fn is_ws_byte(c: u8) -> bool {
7951 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == 0x0b || c == 0x0c
7952}
7953
7954unsafe fn scan_int_val(
7957 buf: *const u8, pos: &mut usize, buf_len: usize, base: u32, width: usize,
7958) -> (u64, bool, bool) {
7959 let start = *pos;
7960 let max = if width > 0 { (start + width).min(buf_len) } else { buf_len };
7961 let neg = if *pos < max && *buf.add(*pos) == b'-' { *pos += 1; true }
7962 else if *pos < max && *buf.add(*pos) == b'+' { *pos += 1; false }
7963 else { false };
7964 if *pos >= max { *pos = start; return (0, false, false); }
7965 let mut base = base;
7966 let mut val: u64 = 0;
7967 if (base == 0 || base == 16) && *pos < max && *buf.add(*pos) == b'0' {
7969 *pos += 1;
7970 if *pos < max && (*buf.add(*pos) == b'x' || *buf.add(*pos) == b'X') {
7971 *pos += 1;
7972 if *pos < max {
7973 if let Some(d) = hex_val(*buf.add(*pos)) {
7974 val = d as u64; *pos += 1;
7975 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; } }
7976 return (val, neg, true);
7977 }
7978 }
7979 return (0, neg, false);
7980 } else if base == 0 {
7981 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; } }
7982 return (val, neg, true);
7983 } else {
7984 while *pos < max {
7987 if let Some(d) = hex_val(*buf.add(*pos)) {
7988 val = val.wrapping_mul(16).wrapping_add(d as u64);
7989 *pos += 1;
7990 } else {
7991 break;
7992 }
7993 }
7994 return (val, neg, true);
7995 }
7996 }
7997 if base == 0 { base = 10; }
7998 let mut found = false;
7999 while *pos < max {
8000 let c = *buf.add(*pos);
8001 let d: Option<u64> = match base {
8002 8 => if c >= b'0' && c <= b'7' { Some((c - b'0') as u64) } else { None },
8003 10 => if c >= b'0' && c <= b'9' { Some((c - b'0') as u64) } else { None },
8004 16 => hex_val(c).map(|v| v as u64),
8005 _ => None,
8006 };
8007 match d { Some(digit) => { val = val.wrapping_mul(base as u64).wrapping_add(digit); *pos += 1; found = true; } None => break }
8008 }
8009 if !found { *pos = start; return (0, false, false); }
8010 (val, neg, true)
8011}
8012
8013unsafe fn scan_float_val(
8015 buf: *const u8, pos: &mut usize, buf_len: usize, width: usize,
8016) -> (f64, bool) {
8017 let start = *pos;
8018 let max = if width > 0 { (start + width).min(buf_len) } else { buf_len };
8019 let neg = if *pos < max && *buf.add(*pos) == b'-' { *pos += 1; true }
8020 else if *pos < max && *buf.add(*pos) == b'+' { *pos += 1; false }
8021 else { false };
8022 if *pos + 2 < max {
8024 let (c0,c1,c2) = (*buf.add(*pos), *buf.add(*pos+1), *buf.add(*pos+2));
8025 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); }
8026 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); }
8027 }
8028 if *pos+1 < max && *buf.add(*pos)==b'0' && (*buf.add(*pos+1)==b'x'||*buf.add(*pos+1)==b'X') {
8030 *pos += 2;
8031 let mut val: f64 = 0.0; let mut found = false; let mut frac_scale = 1.0f64; let mut in_frac = false;
8032 while *pos < max {
8033 if let Some(d) = hex_val(*buf.add(*pos)) {
8034 if in_frac { frac_scale /= 16.0; val += d as f64 * frac_scale; } else { val = val * 16.0 + d as f64; }
8035 *pos += 1; found = true;
8036 } else if *buf.add(*pos)==b'.' && !in_frac { in_frac = true; *pos += 1; } else { break; }
8037 }
8038 if !found { *pos = start; return (0.0, false); }
8039 if *pos < max && (*buf.add(*pos)==b'p'||*buf.add(*pos)==b'P') {
8041 *pos += 1;
8042 let mut eneg = false;
8043 if *pos<max && *buf.add(*pos)==b'-' { eneg=true; *pos+=1; }
8044 else if *pos<max && *buf.add(*pos)==b'+' { *pos+=1; }
8045 let mut ev: i32 = 0; let mut ef = false;
8046 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; }
8047 if !ef { return (0.0, false); }
8048 if eneg { ev = -ev; }
8049 val *= libm::pow(2.0, ev as f64);
8050 }
8051 return (if neg{-val}else{val}, true);
8052 }
8053 let token_start = start;
8054 let mut i = start;
8055 let mut saw_digit = false;
8056 let mut saw_dot = false;
8057 let mut saw_exp = false;
8058 let mut first = true;
8059 while i < max {
8060 let c = *buf.add(i);
8061 if (c == b'+' || c == b'-') && first {
8062 i += 1; first = false; continue;
8063 }
8064 if c >= b'0' && c <= b'9' {
8065 saw_digit = true; i += 1; first = false; continue;
8066 }
8067 if c == b'.' && !saw_dot && !saw_exp {
8068 saw_dot = true; i += 1; first = false; continue;
8069 }
8070 if (c == b'e' || c == b'E') && !saw_exp && saw_digit {
8071 saw_exp = true; i += 1; first = true; continue;
8072 }
8073 break;
8074 }
8075 if !saw_digit { return (0.0, false); }
8076 let s = core::str::from_utf8_unchecked(core::slice::from_raw_parts(buf.add(token_start), i - token_start));
8077 match <f64 as core::str::FromStr>::from_str(s) {
8078 Ok(v) => { *pos = i; return (v, true); }
8079 Err(_) => { return (0.0, false); }
8080 }
8081}
8082
8083unsafe fn store_scan_int(dest: *mut c_void, len_mod: u8, val: u64, neg: bool) {
8088 let sv: i64 = if neg { (val as i64).wrapping_neg() } else { val as i64 };
8089 match len_mod {
8090 2 => *(dest as *mut i8) = sv as i8,
8091 1 => *(dest as *mut i16) = sv as i16,
8092 3 | 4 => *(dest as *mut i64) = sv,
8093 _ => *(dest as *mut i32) = sv as i32,
8094 }
8095}
8096
8097unsafe fn do_vsscanf(
8098 buf: *const u8, buf_len: usize, fmt: *const c_char, args: &mut VaList<'_>, consumed: *mut usize,
8099) -> c_int {
8100 let mut p = 0usize;
8101 let mut fi = 0usize;
8102 let mut assigned = 0i32;
8103 let mut input_eof = false;
8104 loop {
8105 let fc = *fmt.add(fi) as u8;
8106 if fc == 0 { break; }
8107 if is_ws_byte(fc) {
8108 while is_ws_byte(*fmt.add(fi) as u8) { fi += 1; }
8109 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8110 continue;
8111 }
8112 if fc != b'%' {
8113 if p >= buf_len { input_eof = true; break; }
8114 if *buf.add(p) != fc { break; }
8115 p += 1; fi += 1; continue;
8116 }
8117 fi += 1;
8118 if *fmt.add(fi) as u8 == b'%' {
8120 if p >= buf_len { input_eof = true; break; }
8121 if *buf.add(p) != b'%' { break; }
8122 p += 1; fi += 1; continue;
8123 }
8124 let suppress = if *fmt.add(fi) as u8 == b'*' { fi += 1; true } else { false };
8125 let mut width: usize = 0;
8126 while (*fmt.add(fi) as u8) >= b'0' && (*fmt.add(fi) as u8) <= b'9' {
8127 width = width * 10 + ((*fmt.add(fi) as u8) - b'0') as usize; fi += 1;
8128 }
8129 if *fmt.add(fi) as u8 == b'm' { fi += 1; }
8130 let mut len_mod = 0u8;
8131 match *fmt.add(fi) as u8 {
8132 b'h' => { fi += 1; if *fmt.add(fi) as u8 == b'h' { fi += 1; len_mod = 2; } else { len_mod = 1; } }
8133 b'l' => { fi += 1; if *fmt.add(fi) as u8 == b'l' { fi += 1; len_mod = 4; } else { len_mod = 3; } }
8134 b'j' => { fi += 1; len_mod = 4; }
8135 b'z' | b't' => { fi += 1; len_mod = 3; }
8136 b'L' => { fi += 1; len_mod = 5; }
8137 _ => {}
8138 }
8139 let spec = *fmt.add(fi) as u8;
8140 let (real_spec, _real_len) = if spec==b'C' {(b'c',3u8)} else if spec==b'S' {(b's',3u8)} else {(spec,len_mod)};
8141 match real_spec {
8142 b'n' => {
8143 if !suppress {
8144 let out = args.next_arg::<*mut c_void>();
8145 if !out.is_null() {
8146 match len_mod {
8147 1 => *(out as *mut i16) = p as i16,
8148 2 => *(out as *mut i8) = p as i8,
8149 3 | 4 => *(out as *mut i64) = p as i64,
8150 _ => *(out as *mut c_int) = p as c_int,
8151 }
8152 }
8153 }
8154 }
8155 b'd' | b'u' => {
8156 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8157 if p >= buf_len { input_eof = true; break; }
8158 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8159 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 10, width);
8160 if !ok { break; }
8161 if let Some(out) = dest { if !out.is_null() {
8162 store_scan_int(out, len_mod, val, neg);
8163 }}
8164 if !suppress { assigned += 1; }
8165 }
8166 b'i' => {
8167 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8168 if p >= buf_len { input_eof = true; break; }
8169 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8170 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 0, width);
8171 if !ok { break; }
8172 if let Some(out) = dest { if !out.is_null() { store_scan_int(out, len_mod, val, neg); } }
8173 if !suppress { assigned += 1; }
8174 }
8175 b'o' => {
8176 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8177 if p >= buf_len { input_eof = true; break; }
8178 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8179 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 8, width);
8180 if !ok { break; }
8181 if let Some(out) = dest { if !out.is_null() { store_scan_int(out, len_mod, val, neg); } }
8182 if !suppress { assigned += 1; }
8183 }
8184 b'x' | b'X' => {
8185 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8186 if p >= buf_len { input_eof = true; break; }
8187 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8188 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 16, width);
8189 if !ok { break; }
8190 if let Some(out) = dest { if !out.is_null() { store_scan_int(out, len_mod, val, neg); } }
8191 if !suppress { assigned += 1; }
8192 }
8193 b'p' => {
8194 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8195 if p >= buf_len { input_eof = true; break; }
8196 let dest = if !suppress { Some(args.next_arg::<*mut *mut c_void>()) } else { None };
8197 let (val, _, ok) = scan_int_val(buf, &mut p, buf_len, 16, width);
8198 if !ok { break; }
8199 if let Some(out) = dest { if !out.is_null() { *out = val as usize as *mut c_void; } }
8200 if !suppress { assigned += 1; }
8201 }
8202 b'a' | b'e' | b'f' | b'g' | b'A' | b'E' | b'F' | b'G' => {
8203 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8204 if p >= buf_len { input_eof = true; break; }
8205 let (val, ok) = scan_float_val(buf, &mut p, buf_len, width);
8206 if !ok { break; }
8207 if !suppress {
8208 if _real_len == 3 {
8209 let out = args.next_arg::<*mut f64>(); if !out.is_null() { *out = val; }
8210 } else if _real_len == 5 {
8211 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
8212 { let out = args.next_arg::<*mut f128>(); if !out.is_null() { *out = val as f128; } }
8213 #[cfg(target_arch = "x86_64")]
8214 { let out = args.next_arg::<*mut f64>(); if !out.is_null() { *out = val; } }
8215 } else {
8216 let out = args.next_arg::<*mut f32>(); if !out.is_null() { *out = val as f32; }
8217 }
8218 }
8219 if !suppress { assigned += 1; }
8220 }
8221 b'c' => {
8222 let w = if width > 0 { width } else { 1 };
8223 if p >= buf_len { input_eof = true; break; }
8224 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8225 let start_p = p;
8226 let mut j = 0usize;
8227 while j < w && p < buf_len {
8228 if !dest_ptr.is_null() { *dest_ptr.add(j) = *buf.add(p) as c_char; }
8229 p += 1; j += 1;
8230 }
8231 if j != w { p = start_p; input_eof = true; break; }
8232 if !suppress { assigned += 1; }
8233 }
8234 b's' => {
8235 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8236 if p >= buf_len { input_eof = true; break; }
8237 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8238 let w = if width > 0 { width } else { usize::MAX };
8239 let mut j = 0usize;
8240 while p < buf_len && *buf.add(p) != 0 && !is_ws_byte(*buf.add(p)) && j < w {
8241 if !dest_ptr.is_null() { *dest_ptr.add(j) = *buf.add(p) as c_char; }
8242 p += 1; j += 1;
8243 }
8244 if j == 0 { break; }
8245 if !dest_ptr.is_null() { *dest_ptr.add(j) = 0; }
8246 if !suppress { assigned += 1; }
8247 }
8248 b'[' => {
8249 fi += 1;
8250 let negate = if *fmt.add(fi) as u8 == b'^' { fi += 1; true } else { false };
8251 let mut charset = [0u8; 256];
8252 let mut prev: Option<u8> = None;
8253 if *fmt.add(fi) as u8 == b']' {
8254 charset[b']' as usize] = 1;
8255 prev = Some(b']');
8256 fi += 1;
8257 }
8258 loop {
8259 let c = *fmt.add(fi) as u8;
8260 if c == b']' || c == 0 { break; }
8261 if c == b'-' && prev.is_some() {
8264 let hi = *fmt.add(fi + 1) as u8;
8265 if hi != b']' && hi != 0 {
8266 let lo = prev.unwrap();
8267 let mut k = lo;
8268 while k <= hi {
8269 charset[k as usize] = 1;
8270 if k == 255 { break; }
8271 k += 1;
8272 }
8273 prev = None;
8274 fi += 2;
8275 continue;
8276 }
8277 }
8278 charset[c as usize] = 1;
8279 prev = Some(c);
8280 fi += 1;
8281 }
8282 if *fmt.add(fi) as u8 == b']' { fi += 1; }
8283 fi -= 1; if p >= buf_len { input_eof = true; break; }
8285 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8286 let w = if width > 0 { width } else { usize::MAX };
8287 let mut j = 0usize;
8288 while p < buf_len && *buf.add(p) != 0 && j < w {
8289 let c = *buf.add(p);
8290 let in_set = charset[c as usize] != 0;
8291 if negate { if in_set { break; } } else { if !in_set { break; } }
8292 if !dest_ptr.is_null() { *dest_ptr.add(j) = c as c_char; }
8293 p += 1; j += 1;
8294 }
8295 if j == 0 { break; }
8296 if !dest_ptr.is_null() { *dest_ptr.add(j) = 0; }
8297 if !suppress { assigned += 1; }
8298 }
8299 _ => break,
8300 }
8301 fi += 1;
8302 }
8303 if !consumed.is_null() { *consumed = p; }
8304 if assigned == 0 && input_eof { -1 } else { assigned }
8305}
8306
8307unsafe fn vsscanf_inner(buf: *const u8, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
8308 let len = strlen(buf as *const c_char);
8309 do_vsscanf(buf, len, fmt, args, core::ptr::null_mut())
8310}
8311
8312#[no_mangle]
8313pub unsafe extern "C" fn vsscanf(buf: *const c_char, fmt: *const c_char, mut args: VaList) -> c_int {
8314 vsscanf_inner(buf as *const u8, fmt, &mut args)
8315}
8316
8317#[no_mangle]
8318pub unsafe extern "C" fn vfscanf(stream: *mut FILE, fmt: *const c_char, mut args: VaList) -> c_int {
8319 let f = &mut *stream;
8320 let start_ungotten_count = f.ungotten_count as usize;
8321 let ungotten_saved = f.ungotten;
8322 let sfunc = f.seek_fn;
8323 let start_pos = if sfunc.is_some() { ftello(stream) } else { -1 };
8325
8326 let mut line = [0u8; 4096];
8327 let mut pos = 0usize;
8328
8329 if start_pos >= 0 {
8330 while pos < line.len() - 1 {
8332 let c = fgetc(stream);
8333 if c == -1 { break; }
8334 line[pos] = c as u8;
8335 pos += 1;
8336 if c == b'\n' as c_int { break; }
8337 }
8338 } else {
8339 while f.ungotten_count > 0 && pos < line.len() - 1 {
8344 f.ungotten_count -= 1;
8345 line[pos] = f.ungotten[f.ungotten_count as usize] as u8;
8346 pos += 1;
8347 }
8348 while !f.rpos.is_null() && f.rpos < f.rend && pos < line.len() - 1 {
8350 line[pos] = *f.rpos;
8351 f.rpos = f.rpos.add(1);
8352 pos += 1;
8353 }
8354 let fd = f.fd;
8358 if pos == 0 {
8359 let n = sys_read(fd as i64, line.as_mut_ptr(), 1);
8360 if n == 1 { pos = 1; }
8361 }
8362 let old_flags = sys_fcntl(fd, F_GETFL, 0);
8363 if old_flags >= 0 {
8364 let _ = sys_fcntl(fd, F_SETFL, old_flags | O_NONBLOCK as i64);
8365 }
8366 while pos < line.len() - 1 {
8367 let n = sys_read(fd as i64, line.as_mut_ptr().add(pos), line.len() - 1 - pos);
8368 if n <= 0 { break; }
8369 pos += n as usize;
8370 }
8371 if old_flags >= 0 {
8372 let _ = sys_fcntl(fd, F_SETFL, old_flags);
8373 }
8374 f._eof = 0;
8376 f._err = 0;
8377 f.flags &= !(F_EOF | F_ERR);
8378 }
8379
8380 line[pos] = 0;
8381 if pos == 0 { return 0; }
8382
8383 let mut consumed = 0usize;
8384 let assigned = do_vsscanf(line.as_ptr(), pos, fmt, &mut args, &mut consumed);
8385
8386 if start_pos >= 0 {
8387 let remaining = start_ungotten_count.saturating_sub(consumed);
8390 let target = start_pos + consumed as i64 + remaining as i64;
8393 if let Some(sfunc) = sfunc {
8394 sfunc(stream, target, SEEK_SET);
8395 }
8396 f.rpos = core::ptr::null_mut();
8397 f.rend = core::ptr::null_mut();
8398 if consumed < pos { f._eof = 0; }
8399 f.ungotten_count = 0;
8400 for i in 0..remaining {
8401 f.ungotten[f.ungotten_count as usize] = ungotten_saved[i];
8402 f.ungotten_count += 1;
8403 }
8404 } else {
8405 let unconsumed = pos.saturating_sub(consumed);
8407 if unconsumed > 0 && !f.buf.is_null() {
8408 let copy_count = core::cmp::min(unconsumed, f.buf_size);
8409 core::ptr::copy(
8410 line.as_ptr().add(consumed),
8411 f.buf,
8412 copy_count,
8413 );
8414 f.rpos = f.buf;
8415 f.rend = f.buf.add(copy_count);
8416 }
8417 f.ungotten_count = 0;
8418 f._eof = 0;
8419 f.flags &= !F_EOF;
8420 }
8421 assigned
8422}
8423
8424#[no_mangle]
8425pub unsafe extern "C" fn vscanf(fmt: *const c_char, args: VaList) -> c_int {
8426 vfscanf(stdin, fmt, args)
8427}
8428
8429#[no_mangle]
8430pub unsafe extern "C" fn sscanf(buf: *const c_char, fmt: *const c_char, mut args: ...) -> c_int {
8431 vsscanf_inner(buf as *const u8, fmt, &mut args)
8432}
8433
8434#[no_mangle]
8435pub unsafe extern "C" fn fscanf(stream: *mut FILE, fmt: *const c_char, args: ...) -> c_int {
8436 vfscanf(stream, fmt, args)
8437}
8438
8439#[no_mangle]
8440pub unsafe extern "C" fn scanf(fmt: *const c_char, args: ...) -> c_int {
8441 vfscanf(stdin, fmt, args)
8442}
8443
8444#[no_mangle]
8449pub unsafe extern "C" fn getdelim(
8450 lineptr: *mut *mut c_char, n: *mut usize, delim: c_int, stream: *mut FILE,
8451) -> isize {
8452 if lineptr.is_null() || n.is_null() { return -1; }
8453 let mut cap = *n;
8454 let mut buf = *lineptr;
8455 if buf.is_null() || cap == 0 {
8456 cap = 128;
8457 buf = realloc(buf as *mut c_void, cap) as *mut c_char;
8458 if buf.is_null() { return -1; }
8459 *lineptr = buf;
8460 *n = cap;
8461 }
8462 let mut len = 0usize;
8463 loop {
8464 let c = fgetc(stream);
8465 if c == -1 { if len == 0 { return -1; } break; }
8466 if len + 1 >= cap {
8467 let new_cap = cap.wrapping_mul(2);
8468 let new_buf = realloc(buf as *mut c_void, new_cap) as *mut c_char;
8469 if new_buf.is_null() { return -1; }
8470 buf = new_buf; cap = new_cap;
8471 *lineptr = buf; *n = cap;
8472 }
8473 *buf.add(len) = c as c_char;
8474 len += 1;
8475 if c == delim { break; }
8476 }
8477 *buf.add(len) = 0;
8478 len as isize
8479}
8480
8481#[no_mangle]
8482pub unsafe extern "C" fn getline(lineptr: *mut *mut c_char, n: *mut usize, stream: *mut FILE) -> isize {
8483 getdelim(lineptr, n, b'\n' as c_int, stream)
8484}
8485
8486#[no_mangle]
8491pub unsafe extern "C" fn popen(cmd: *const c_char, mode: *const c_char) -> *mut FILE {
8492 if cmd.is_null() || mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
8493 let m = *mode;
8494 if m != b'r' as c_char && m != b'w' as c_char { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
8495 let mut p: [c_int; 2] = [0; 2];
8496 if sys_pipe2(p.as_mut_ptr(), O_CLOEXEC) < 0 { return core::ptr::null_mut(); }
8497 let op = if m == b'r' as c_char { 0 } else { 1 };
8498 let child_fd = p[1 - op];
8499 let f = fdopen(p[op], mode);
8500 if f.is_null() { sys_close(p[0] as i64); sys_close(p[1] as i64); return core::ptr::null_mut(); }
8501 let pid = sys_fork();
8502 if pid < 0 { fclose(f); sys_close(child_fd as i64); return core::ptr::null_mut(); }
8503 if pid == 0 {
8504 sys_close(p[op] as i64);
8505 if child_fd != (1 - op) as c_int { sys_dup3(child_fd, (1 - op) as c_int, 0); sys_close(child_fd as i64); }
8506 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
8507 let argv = [b"sh\0".as_ptr() as *const c_char, b"-c\0".as_ptr() as *const c_char, cmd, core::ptr::null()];
8508 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
8509 _exit(127);
8510 }
8511 sys_close(child_fd as i64);
8512 (*f).pipe_pid = pid as c_int;
8513 f
8514}
8515
8516#[no_mangle]
8517pub unsafe extern "C" fn pclose(f: *mut FILE) -> c_int {
8518 let pid = (*f).pipe_pid;
8519 let r = fclose(f);
8520 if pid <= 0 { return -1; }
8521 let mut status: c_int = 0;
8522 let mut w: c_int;
8523 loop {
8524 w = waitpid(pid, &mut status, 0);
8525 if w >= 0 || ERRNO!() != EINTR_VAL { break; }
8526 }
8527 if w < 0 || r != 0 { return -1; }
8528 status
8529}
8530
8531const L_TMPNAM: usize = 20;
8536static mut TMPNAM_COUNTER: c_uint = 0;
8537
8538unsafe fn fill_tmpname(out: *mut c_char, seed: c_uint) {
8539 let prefix = b"/tmp/tmp\0";
8540 let mut k = 0;
8541 while k < prefix.len() - 1 { *out.add(k) = prefix[k] as c_char; k += 1; }
8542 let (buf, len) = format_hex(seed as u64, false);
8543 for j in 0..len.min(L_TMPNAM - k - 1) { *out.add(k + j) = buf[j] as c_char; k += 1; }
8544 *out.add(k) = 0;
8545}
8546
8547#[no_mangle]
8548pub unsafe extern "C" fn tmpfile() -> *mut FILE {
8549 let mut name = [0u8; L_TMPNAM];
8550 let mut ctr: c_uint = 0;
8551 loop {
8552 ctr = ctr.wrapping_add(1);
8553 let mut ts: timespec = core::mem::zeroed();
8554 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
8555 let seed = (ts.tv_nsec as c_uint).wrapping_add(ctr);
8556 fill_tmpname(name.as_mut_ptr() as *mut c_char, seed);
8557 let fd = sys_open(name.as_ptr(), (O_RDWR | O_CREAT | O_EXCL) as i64, 0o600);
8558 if fd >= 0 {
8559 sys_unlinkat(AT_FDCWD, name.as_ptr(), 0);
8560 let f = fdopen(fd as c_int, b"w+\0".as_ptr() as *const c_char);
8561 if f.is_null() { sys_close(fd); }
8562 return f;
8563 }
8564 if ctr > 100 { return core::ptr::null_mut(); }
8565 }
8566}
8567
8568#[no_mangle]
8569pub unsafe extern "C" fn tmpnam(s: *mut c_char) -> *mut c_char {
8570 static mut BUF: [c_char; L_TMPNAM] = [0; L_TMPNAM];
8571 let out = if s.is_null() { core::ptr::addr_of_mut!(BUF) as *mut c_char } else { s };
8572 TMPNAM_COUNTER = TMPNAM_COUNTER.wrapping_add(1);
8573 let mut ts: timespec = core::mem::zeroed();
8574 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
8575 let seed = (ts.tv_nsec as c_uint).wrapping_add(TMPNAM_COUNTER);
8576 fill_tmpname(out, seed);
8577 out
8578}
8579
8580#[no_mangle]
8581pub unsafe extern "C" fn remove(path: *const c_char) -> c_int {
8582 if path.is_null() { ERRNO!() = EINVAL; return -1; }
8583 let r = sys_unlinkat(AT_FDCWD, path as *const u8, 0);
8584 if r == 0 {
8585 return 0;
8586 }
8587 if (-r) as c_int == 21 {
8590 return rmdir(path);
8591 }
8592 ERRNO!() = (-r) as c_int;
8593 -1
8594}
8595
8596#[no_mangle]
8597pub unsafe extern "C" fn rename(old: *const c_char, new_: *const c_char) -> c_int {
8598 if old.is_null() || new_.is_null() { ERRNO!() = EINVAL; return -1; }
8599 let r = sys_renameat2(AT_FDCWD, old as *const u8, AT_FDCWD, new_ as *const u8, 0);
8600 if r == 0 { 0 } else { ERRNO!() = (-r) as c_int; -1 }
8601}
8602
8603const MMAP_FAILED: *mut u8 = !0usize as *mut u8;
8608const PAGE: usize = 4096;
8609
8610#[no_mangle]
8615pub unsafe extern "C" fn _exit(code: c_int) -> ! {
8616 sys_exit_group(code)
8617}
8618
8619#[inline]
8620unsafe fn sys_exit_group(code: c_int) -> ! {
8621 <Arch as Syscalls>::syscall_noreturn1(SYS_EXIT_GROUP, code as i64)
8622}
8623
8624#[inline]
8625unsafe fn sys_exit_thread(code: c_int) -> ! {
8626 <Arch as Syscalls>::syscall_noreturn1(SYS_EXIT, code as i64)
8627}
8628
8629#[no_mangle]
8630pub unsafe extern "C" fn _Exit(code: c_int) -> ! {
8631 _exit(code);
8632}
8633
8634#[no_mangle]
8635pub unsafe extern "C" fn exit(code: c_int) -> ! {
8636 fflush(core::ptr::null_mut());
8637 __funcs_on_exit();
8638 _exit(code);
8639}
8640
8641#[no_mangle]
8642pub unsafe extern "C" fn abort() -> ! {
8643 raise(6); _exit(128 + 6);
8645}
8646
8647#[no_mangle]
8650pub static mut __stack_chk_guard: usize = 0;
8651
8652#[no_mangle]
8653pub unsafe extern "C" fn __stack_chk_fail() -> ! {
8654 const MSG: &[u8] = b"*** stack smashing detected ***: terminated\n";
8655 let _ = sys_write(2, MSG.as_ptr(), MSG.len());
8656 abort();
8657}
8658
8659#[no_mangle]
8660pub unsafe extern "C" fn __stack_chk_fail_local() -> ! {
8661 __stack_chk_fail()
8662}
8663
8664type CmpRfn = unsafe extern "C" fn(*const c_void, *const c_void, *mut c_void) -> c_int;
8669
8670const AR_LEN: usize = 16 * core::mem::size_of::<usize>();
8671const AR_MASK: usize = AR_LEN - 1;
8672
8673unsafe fn qsort_pntz(p: &[usize; 2]) -> i32 {
8674 if p[0] != 1 {
8675 p[0].wrapping_sub(1).trailing_zeros() as i32
8676 } else if p[1] != 0 {
8677 (8 * core::mem::size_of::<usize>()) as i32 + p[1].trailing_zeros() as i32
8678 } else {
8679 0
8680 }
8681}
8682
8683unsafe fn qsort_cycle(width: usize, ar: &mut [*mut u8; AR_LEN], n: usize) {
8684 if n < 2 { return; }
8685 let mut tmp = [0u8; 256];
8686 ar[n] = tmp.as_mut_ptr();
8687 let mut w = width;
8688 while w > 0 {
8689 let l = if 256 < w { 256 } else { w };
8690 core::ptr::copy_nonoverlapping(ar[0], ar[n], l);
8691 for i in 0..n {
8692 core::ptr::copy_nonoverlapping(ar[i + 1], ar[i], l);
8693 ar[i] = ar[i].add(l);
8694 }
8695 w -= l;
8696 }
8697}
8698
8699unsafe fn qsort_shl(p: &mut [usize; 2], n: i32) {
8700 let bits = (8 * core::mem::size_of::<usize>()) as i32;
8701 if n >= bits {
8702 p[1] = p[0];
8703 p[0] = 0;
8704 let n = n - bits;
8705 if n == 0 { return; }
8706 }
8707 p[1] = (p[1] << n) | (p[0] >> (bits - n));
8708 p[0] <<= n;
8709}
8710
8711unsafe fn qsort_shr(p: &mut [usize; 2], n: i32) {
8712 let bits = (8 * core::mem::size_of::<usize>()) as i32;
8713 if n >= bits {
8714 p[0] = p[1];
8715 p[1] = 0;
8716 let n = n - bits;
8717 if n == 0 { return; }
8718 }
8719 p[0] = (p[0] >> n) | (p[1] << (bits - n));
8720 p[1] >>= n;
8721}
8722
8723unsafe fn qsort_sift(
8724 head: *mut u8, width: usize,
8725 cmp: CmpRfn, arg: *mut c_void,
8726 pshift: i32, lp: &[usize],
8727) {
8728 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
8729 ar[0] = head;
8730 let mut i = 1usize;
8731 let mut h = head;
8732 let mut ps = pshift;
8733
8734 while ps > 1 {
8735 let rt = h.sub(width);
8736 let lf = h.sub(width + lp[(ps - 2) as usize]);
8737
8738 if cmp(ar[0] as *const c_void, lf as *const c_void, arg) >= 0
8739 && cmp(ar[0] as *const c_void, rt as *const c_void, arg) >= 0
8740 {
8741 break;
8742 }
8743 if cmp(lf as *const c_void, rt as *const c_void, arg) >= 0 {
8744 ar[i & AR_MASK] = lf;
8745 i += 1;
8746 h = lf;
8747 ps -= 1;
8748 } else {
8749 ar[i & AR_MASK] = rt;
8750 i += 1;
8751 h = rt;
8752 ps -= 2;
8753 }
8754 }
8755 qsort_cycle(width, &mut ar, i & AR_MASK);
8756}
8757
8758unsafe fn qsort_trinkle(
8759 head: *mut u8, width: usize,
8760 cmp: CmpRfn, arg: *mut c_void,
8761 pp: &[usize; 2], pshift: i32, trusty: i32,
8762 lp: &[usize],
8763) {
8764 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
8765 let mut p = *pp;
8766 ar[0] = head;
8767 let mut i = 1usize;
8768 let mut h = head;
8769 let mut ps = pshift;
8770 let mut t = trusty;
8771
8772 while p[0] != 1 || p[1] != 0 {
8773 let stepson = h.sub(lp[ps as usize]);
8774 if cmp(stepson as *const c_void, ar[0] as *const c_void, arg) <= 0 {
8775 break;
8776 }
8777 if t == 0 && ps > 1 {
8778 let rt = h.sub(width);
8779 let lf = h.sub(width + lp[(ps - 2) as usize]);
8780 if cmp(rt as *const c_void, stepson as *const c_void, arg) >= 0
8781 || cmp(lf as *const c_void, stepson as *const c_void, arg) >= 0
8782 {
8783 break;
8784 }
8785 }
8786
8787 ar[i & AR_MASK] = stepson;
8788 i += 1;
8789 h = stepson;
8790 let trail = qsort_pntz(&p);
8791 qsort_shr(&mut p, trail);
8792 ps += trail;
8793 t = 0;
8794 }
8795 if t == 0 {
8796 qsort_cycle(width, &mut ar, i & AR_MASK);
8797 qsort_sift(h, width, cmp, arg, ps, lp);
8798 }
8799}
8800
8801#[no_mangle]
8802pub unsafe extern "C" fn __qsort_r(
8803 base: *mut c_void,
8804 nel: usize,
8805 width: usize,
8806 cmp: CmpRfn,
8807 arg: *mut c_void,
8808) {
8809 let size = width * nel;
8810 if size == 0 { return; }
8811
8812 let mut lp = [0usize; 96];
8813 lp[0] = width;
8814 lp[1] = width;
8815 let mut li = 2;
8816 while {
8817 lp[li] = lp[li - 2] + lp[li - 1] + width;
8818 lp[li] < size
8819 } {
8820 li += 1;
8821 }
8822
8823 let mut head = base as *mut u8;
8824 let high = head.add(size - width);
8825 let mut p: [usize; 2] = [1, 0];
8826 let mut pshift: i32 = 1;
8827
8828 while head < high {
8829 if (p[0] & 3) == 3 {
8830 qsort_sift(head, width, cmp, arg, pshift, &lp);
8831 qsort_shr(&mut p, 2);
8832 pshift += 2;
8833 } else {
8834 if lp[(pshift - 1) as usize] >= (high as usize) - (head as usize) {
8835 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
8836 } else {
8837 qsort_sift(head, width, cmp, arg, pshift, &lp);
8838 }
8839
8840 if pshift == 1 {
8841 qsort_shl(&mut p, 1);
8842 pshift = 0;
8843 } else {
8844 qsort_shl(&mut p, pshift - 1);
8845 pshift = 1;
8846 }
8847 }
8848
8849 p[0] |= 1;
8850 head = head.add(width);
8851 }
8852
8853 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
8854
8855 while pshift != 1 || p[0] != 1 || p[1] != 0 {
8856 if pshift <= 1 {
8857 let trail = qsort_pntz(&p);
8858 qsort_shr(&mut p, trail);
8859 pshift += trail;
8860 } else {
8861 qsort_shl(&mut p, 2);
8862 pshift -= 2;
8863 p[0] ^= 7;
8864 qsort_shr(&mut p, 1);
8865 qsort_trinkle(
8866 head.sub(lp[pshift as usize] + width),
8867 width, cmp, arg, &p, pshift + 1, 1, &lp,
8868 );
8869 qsort_shl(&mut p, 1);
8870 p[0] |= 1;
8871 qsort_trinkle(head.sub(width), width, cmp, arg, &p, pshift, 1, &lp);
8872 }
8873 head = head.sub(width);
8874 }
8875}
8876
8877#[no_mangle]
8878pub unsafe extern "C" fn qsort_r(
8879 base: *mut c_void,
8880 nel: usize,
8881 width: usize,
8882 cmp: CmpRfn,
8883 arg: *mut c_void,
8884) {
8885 __qsort_r(base, nel, width, cmp, arg);
8886}
8887
8888unsafe extern "C" fn qsort_wrap_cmp(
8889 a: *const c_void,
8890 b: *const c_void,
8891 cmp_ctx: *mut c_void,
8892) -> c_int {
8893 let cmp: CmpFn = core::mem::transmute(cmp_ctx);
8894 cmp(a, b)
8895}
8896
8897#[no_mangle]
8898pub unsafe extern "C" fn qsort(
8899 base: *mut c_void,
8900 nel: usize,
8901 width: usize,
8902 cmp: CmpFn,
8903) {
8904 __qsort_r(base, nel, width, qsort_wrap_cmp, cmp as *mut c_void);
8905}
8906
8907const ATEXIT_COUNT: usize = 32;
8912
8913#[repr(C)]
8914struct AtExitBlock {
8915 next: *mut AtExitBlock,
8916 f: [Option<unsafe extern "C" fn(*mut c_void)>; ATEXIT_COUNT],
8917 a: [*mut c_void; ATEXIT_COUNT],
8918}
8919
8920static mut ATEXIT_BUILTIN: AtExitBlock = AtExitBlock {
8921 next: core::ptr::null_mut(),
8922 f: [None; ATEXIT_COUNT],
8923 a: [core::ptr::null_mut(); ATEXIT_COUNT],
8924};
8925static mut ATEXIT_HEAD: *mut AtExitBlock = core::ptr::null_mut();
8926static mut ATEXIT_SLOT: usize = 0;
8927static mut ATEXIT_FINISHED: bool = false;
8928
8929#[no_mangle]
8930pub unsafe extern "C" fn __funcs_on_exit() {
8931 while !ATEXIT_HEAD.is_null() {
8932 let head = ATEXIT_HEAD;
8933 while ATEXIT_SLOT > 0 {
8934 ATEXIT_SLOT -= 1;
8935 if let Some(f) = (*head).f[ATEXIT_SLOT] {
8936 let a = (*head).a[ATEXIT_SLOT];
8937 f(a);
8938 }
8939 }
8940 ATEXIT_HEAD = (*head).next;
8941 ATEXIT_SLOT = ATEXIT_COUNT;
8942 }
8943 ATEXIT_FINISHED = true;
8944}
8945
8946#[no_mangle]
8947pub unsafe extern "C" fn __cxa_atexit(
8948 func: unsafe extern "C" fn(*mut c_void),
8949 arg: *mut c_void,
8950 _dso: *mut c_void,
8951) -> c_int {
8952 if ATEXIT_FINISHED {
8953 return -1;
8954 }
8955 if ATEXIT_HEAD.is_null() {
8956 ATEXIT_HEAD = core::ptr::addr_of_mut!(ATEXIT_BUILTIN);
8957 }
8958 if ATEXIT_SLOT == ATEXIT_COUNT {
8959 let new = calloc(1, core::mem::size_of::<AtExitBlock>()) as *mut AtExitBlock;
8960 if new.is_null() {
8961 return -1;
8962 }
8963 (*new).next = ATEXIT_HEAD;
8964 ATEXIT_HEAD = new;
8965 ATEXIT_SLOT = 0;
8966 }
8967 (*ATEXIT_HEAD).f[ATEXIT_SLOT] = Some(func);
8968 (*ATEXIT_HEAD).a[ATEXIT_SLOT] = arg;
8969 ATEXIT_SLOT += 1;
8970 0
8971}
8972
8973unsafe extern "C" fn atexit_caller(arg: *mut c_void) {
8974 let func: unsafe extern "C" fn() = core::mem::transmute(arg);
8975 func();
8976}
8977
8978#[no_mangle]
8979pub unsafe extern "C" fn atexit(func: unsafe extern "C" fn()) -> c_int {
8980 __cxa_atexit(atexit_caller, func as *mut c_void, core::ptr::null_mut())
8981}
8982
8983#[no_mangle]
8984pub unsafe extern "C" fn __cxa_finalize(_dso: *mut c_void) {}
8985
8986#[no_mangle]
8991pub static mut __environ: *mut *mut c_char = core::ptr::null_mut();
8992
8993static mut ENV_ALLOCED: *mut *mut c_char = core::ptr::null_mut();
8996static mut ENV_ALLOCED_N: usize = 0;
8997static mut ENV_ALLOCED_CAP: usize = 0;
8998
8999unsafe fn env_rm_add(old: *mut c_char, mut new: *mut c_char) {
9000 for i in 0..ENV_ALLOCED_N {
9001 if (*ENV_ALLOCED.add(i)) == old {
9002 *ENV_ALLOCED.add(i) = new;
9003 if !old.is_null() {
9004 free(old as *mut c_void);
9005 }
9006 return;
9007 } else if (*ENV_ALLOCED.add(i)).is_null() && !new.is_null() {
9008 *ENV_ALLOCED.add(i) = new;
9009 new = core::ptr::null_mut();
9010 }
9011 }
9012 if !new.is_null() {
9013 if ENV_ALLOCED_N == ENV_ALLOCED_CAP {
9014 let new_cap = if ENV_ALLOCED_CAP == 0 { 16 } else { ENV_ALLOCED_CAP * 2 };
9015 let grown = realloc(
9016 ENV_ALLOCED as *mut c_void,
9017 new_cap * core::mem::size_of::<*mut c_char>(),
9018 ) as *mut *mut c_char;
9019 if grown.is_null() {
9020 return;
9021 }
9022 ENV_ALLOCED = grown;
9023 ENV_ALLOCED_CAP = new_cap;
9024 }
9025 *ENV_ALLOCED.add(ENV_ALLOCED_N) = new;
9026 ENV_ALLOCED_N += 1;
9027 }
9028}
9029
9030unsafe fn strchrnul_u8(s: *const u8, c: u8) -> *const u8 {
9031 let mut p = s;
9032 while *p != 0 && *p != c {
9033 p = p.add(1);
9034 }
9035 p
9036}
9037
9038#[no_mangle]
9039pub unsafe extern "C" fn getenv(name: *const c_char) -> *mut c_char {
9040 if __environ.is_null() || name.is_null() {
9041 return core::ptr::null_mut();
9042 }
9043 let name = name as *const u8;
9044 let l = strchrnul_u8(name, b'=') as usize - name as usize;
9045 if l == 0 || *name.add(l) != 0 {
9046 return core::ptr::null_mut();
9047 }
9048 let mut e = __environ;
9049 while !(*e).is_null() {
9050 let entry = *e as *const u8;
9051 if strncmp(entry, name, l) == 0 && *entry.add(l) == b'=' {
9052 return entry.add(l + 1) as *mut c_char;
9053 }
9054 e = e.add(1);
9055 }
9056 core::ptr::null_mut()
9057}
9058
9059#[no_mangle]
9060pub unsafe extern "C" fn setenv(
9061 var: *const c_char,
9062 value: *const c_char,
9063 overwrite: c_int,
9064) -> c_int {
9065 if var.is_null() || value.is_null() {
9066 ERRNO!() = EINVAL;
9067 return -1;
9068 }
9069 let var = var as *const u8;
9070 let l1 = strchrnul_u8(var, b'=') as usize - var as usize;
9071 if l1 == 0 || *var.add(l1) != 0 {
9072 ERRNO!() = EINVAL;
9073 return -1;
9074 }
9075 if overwrite == 0 && !getenv(var as *const c_char).is_null() {
9076 return 0;
9077 }
9078 let l2 = strlen(value as *const c_char);
9079 let s = malloc(l1 + l2 + 2) as *mut u8;
9080 if s.is_null() {
9081 return -1;
9082 }
9083 core::ptr::copy_nonoverlapping(var, s, l1);
9084 *s.add(l1) = b'=';
9085 core::ptr::copy_nonoverlapping(value as *const u8, s.add(l1 + 1), l2 + 1);
9086 putenv_internal(s as *mut c_char, l1, s as *mut c_char)
9087}
9088
9089unsafe fn putenv_internal(s: *mut c_char, l: usize, r: *mut c_char) -> c_int {
9090 let mut i = 0;
9091 if !__environ.is_null() {
9092 let mut e = __environ;
9093 while !(*e).is_null() {
9094 if strncmp(s as *const u8, *e as *const u8, l + 1) == 0 {
9095 let tmp = *e;
9096 *e = s;
9097 env_rm_add(tmp, r);
9098 return 0;
9099 }
9100 e = e.add(1);
9101 i += 1;
9102 }
9103 }
9104 let newenv = malloc(core::mem::size_of::<*mut c_char>() * (i + 2)) as *mut *mut c_char;
9105 if newenv.is_null() {
9106 if !r.is_null() { free(r as *mut c_void); }
9107 return -1;
9108 }
9109 if i > 0 && !__environ.is_null() {
9110 core::ptr::copy_nonoverlapping(__environ, newenv, i);
9111 }
9112 *newenv.add(i) = s;
9113 *newenv.add(i + 1) = core::ptr::null_mut();
9114 __environ = newenv;
9116 environ = __environ;
9117 if !r.is_null() {
9118 env_rm_add(core::ptr::null_mut(), r);
9119 }
9120 0
9121}
9122
9123#[no_mangle]
9124pub unsafe extern "C" fn putenv(s: *mut c_char) -> c_int {
9125 if s.is_null() { return -1; }
9126 let l = strchrnul_u8(s as *const u8, b'=') as usize - s as *const u8 as usize;
9127 if l == 0 || *s.add(l) as u8 == 0 {
9128 return unsetenv(s);
9129 }
9130 putenv_internal(s, l, core::ptr::null_mut())
9131}
9132
9133#[no_mangle]
9134pub unsafe extern "C" fn unsetenv(name: *const c_char) -> c_int {
9135 if name.is_null() {
9136 ERRNO!() = EINVAL;
9137 return -1;
9138 }
9139 let name = name as *const u8;
9140 let l = strchrnul_u8(name, b'=') as usize - name as usize;
9141 if l == 0 || *name.add(l) != 0 {
9142 ERRNO!() = EINVAL;
9143 return -1;
9144 }
9145 if __environ.is_null() {
9146 return 0;
9147 }
9148 let mut e = __environ;
9149 let mut eo = e;
9150 while !(*e).is_null() {
9151 if strncmp(name, *e as *const u8, l) == 0 && *(*e as *const u8).add(l) == b'=' {
9152 env_rm_add(*e, core::ptr::null_mut());
9153 } else {
9154 if eo != e {
9155 *eo = *e;
9156 }
9157 eo = eo.add(1);
9158 }
9159 e = e.add(1);
9160 }
9161 if eo != e {
9162 *eo = core::ptr::null_mut();
9163 }
9164 environ = __environ;
9165 0
9166}
9167
9168#[no_mangle]
9169pub unsafe extern "C" fn clearenv() -> c_int {
9170 let e = __environ;
9171 __environ = core::ptr::null_mut();
9172 environ = core::ptr::null_mut();
9173 if !e.is_null() {
9174 let mut p = e;
9175 while !(*p).is_null() {
9176 env_rm_add(*p, core::ptr::null_mut());
9177 p = p.add(1);
9178 }
9179 }
9180 0
9181}
9182
9183static mut RANDOM_INIT: [u32; 32] = [
9189 0x00000000,0x5851f42d,0xc0b18ccf,0xcbb5f646,
9190 0xc7033129,0x30705b04,0x20fd5db4,0x9a8b7f78,
9191 0x502959d8,0xab894868,0x6c0356a7,0x88cdb7ff,
9192 0xb477d43f,0x70a3a52b,0xa8e4baf1,0xfd8341fc,
9193 0x8ae16fd9,0x742d2f7a,0x0d1f0796,0x76035e09,
9194 0x40f7702c,0x6fa72ca5,0xaaa84157,0x58a0df74,
9195 0xc74a0364,0xae533cc4,0x04185faf,0x6de3b115,
9196 0x0cab8628,0xf043bfa4,0x398150e9,0x37521657,
9197];
9198
9199static mut RANDOM_N: i32 = 31;
9200static mut RANDOM_I: i32 = 3;
9201static mut RANDOM_J: i32 = 0;
9202static mut RANDOM_X: *mut u32 = unsafe { core::ptr::addr_of_mut!(RANDOM_INIT).cast::<u32>().add(1) };
9203
9204unsafe fn random_lcg31(x: u32) -> u32 {
9205 (1103515245u32.wrapping_mul(x).wrapping_add(12345)) & 0x7fffffff
9206}
9207
9208unsafe fn random_lcg64(x: u64) -> u64 {
9209 6364136223846793005u64.wrapping_mul(x).wrapping_add(1)
9210}
9211
9212unsafe fn random_savestate() -> *mut u8 {
9213 (*RANDOM_X.offset(-1)) = ((RANDOM_N as u32) << 16) | ((RANDOM_I as u32) << 8) | (RANDOM_J as u32);
9214 RANDOM_X.offset(-1) as *mut u8
9215}
9216
9217unsafe fn random_loadstate(state: *mut u32) {
9218 RANDOM_X = state.add(1);
9219 RANDOM_N = ((*RANDOM_X.offset(-1)) >> 16) as i32;
9220 RANDOM_I = (((*RANDOM_X.offset(-1)) >> 8) & 0xff) as i32;
9221 RANDOM_J = ((*RANDOM_X.offset(-1)) & 0xff) as i32;
9222}
9223
9224unsafe fn random_srandom_inner(seed: u32) {
9225 let mut s = seed as u64;
9226 if RANDOM_N == 0 {
9227 *RANDOM_X = s as u32;
9228 return;
9229 }
9230 RANDOM_I = if RANDOM_N == 31 || RANDOM_N == 7 { 3 } else { 1 };
9231 RANDOM_J = 0;
9232 for k in 0..RANDOM_N as usize {
9233 s = random_lcg64(s);
9234 *RANDOM_X.add(k) = (s >> 32) as u32;
9235 }
9236 *RANDOM_X |= 1;
9237}
9238
9239#[no_mangle]
9240pub unsafe extern "C" fn srandom(seed: c_uint) {
9241 random_srandom_inner(seed);
9242}
9243
9244#[no_mangle]
9245pub unsafe extern "C" fn initstate(seed: c_uint, state: *mut c_char, size: usize) -> *mut c_char {
9246 if size < 8 { return core::ptr::null_mut(); }
9247 let old = random_savestate();
9248 RANDOM_N = if size < 32 { 0 }
9249 else if size < 64 { 7 }
9250 else if size < 128 { 15 }
9251 else if size < 256 { 31 }
9252 else { 63 };
9253 RANDOM_X = (state as *mut u32).add(1);
9254 random_srandom_inner(seed);
9255 random_savestate();
9256 old as *mut c_char
9257}
9258
9259#[no_mangle]
9260pub unsafe extern "C" fn setstate(state: *mut c_char) -> *mut c_char {
9261 let old = random_savestate();
9262 random_loadstate(state as *mut u32);
9263 old as *mut c_char
9264}
9265
9266#[no_mangle]
9267pub unsafe extern "C" fn random() -> c_long {
9268 let k: c_long;
9269 if RANDOM_N == 0 {
9270 *RANDOM_X = random_lcg31(*RANDOM_X);
9271 k = *RANDOM_X as c_long;
9272 } else {
9273 *RANDOM_X.add(RANDOM_I as usize) = (*RANDOM_X.add(RANDOM_I as usize)).wrapping_add(*RANDOM_X.add(RANDOM_J as usize));
9274 k = (*RANDOM_X.add(RANDOM_I as usize) >> 1) as c_long;
9275 RANDOM_I += 1;
9276 if RANDOM_I == RANDOM_N { RANDOM_I = 0; }
9277 RANDOM_J += 1;
9278 if RANDOM_J == RANDOM_N { RANDOM_J = 0; }
9279 }
9280 k
9281}
9282
9283const SA: u8 = 0xC2;
9288const SB: u8 = 0xF4;
9289
9290const BITTAB: [u32; 51] = [
9291 0xC000_0002, 0xC000_0003, 0xC000_0004, 0xC000_0005, 0xC000_0006, 0xC000_0007,
9292 0xC000_0008, 0xC000_0009, 0xC000_000A, 0xC000_000B, 0xC000_000C, 0xC000_000D,
9293 0xC000_000E, 0xC000_000F, 0xC000_0010, 0xC000_0011, 0xC000_0012, 0xC000_0013,
9294 0xC000_0014, 0xC000_0015, 0xC000_0016, 0xC000_0017, 0xC000_0018, 0xC000_0019,
9295 0xC000_001A, 0xC000_001B, 0xC000_001C, 0xC000_001D, 0xC000_001E, 0xC000_001F,
9296 0xB300_0000, 0xC300_0001, 0xC300_0002, 0xC300_0003, 0xC300_0004, 0xC300_0005,
9297 0xC300_0006, 0xC300_0007, 0xC300_0008, 0xC300_0009, 0xC300_000A, 0xC300_000B,
9298 0xC300_000C, 0xD300_000D, 0xC300_000E, 0xC300_000F, 0xBB0C_0000, 0xC30C_0001,
9299 0xC30C_0002, 0xC30C_0003, 0xDB0C_0004,
9300];
9301
9302#[inline]
9303fn mb_oob(c: u32, b: u8) -> u32 {
9304 let b3 = (b >> 3) as u32;
9305 ((b3.wrapping_sub(0x10)) | (b3.wrapping_add((c as i32 >> 26) as u32))) & !7
9306}
9307
9308static mut MB_STATE: c_uint = 0;
9309
9310const MB_CUR_MAX_VAL_UTF8: usize = 4;
9311const MB_CUR_MAX_VAL_C: usize = 1;
9312
9313#[no_mangle]
9314pub extern "C" fn __ctype_get_mb_cur_max() -> usize {
9315 unsafe { if LOCALE_CTYPE_UTF8 { MB_CUR_MAX_VAL_UTF8 } else { MB_CUR_MAX_VAL_C } }
9316}
9317
9318#[no_mangle]
9319pub unsafe extern "C" fn mbrtowc(
9320 wc: *mut c_int,
9321 src: *const c_char,
9322 n: usize,
9323 st: *mut c_uint,
9324) -> usize {
9325 let s = src as *const u8;
9326 let n0 = n;
9327 let mut dummy: c_int = 0;
9328 let wc = if wc.is_null() { &mut dummy } else { &mut *wc };
9329 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
9330
9331 let mut c: u32 = *st;
9332 let mut s = s;
9333 let mut n = n;
9334
9335 if s.is_null() {
9336 if c != 0 { *st = 0; ERRNO!() = EILSEQ; return !0usize; }
9337 return 0;
9338 }
9339
9340 if n == 0 { return !1usize; }
9341
9342 if unsafe { !LOCALE_CTYPE_UTF8 } {
9343 let b = *s;
9344 *wc = b as c_int;
9345 return if b == 0 { 0 } else { 1 };
9346 }
9347
9348 if c == 0 {
9349 if *s < 0x80 {
9350 let r = if *s == 0 { 0 } else { 1 };
9351 *wc = *s as c_int;
9352 return r;
9353 }
9354 if (*s).wrapping_sub(SA) as u32 > (SB - SA) as u32 {
9355 *st = 0; ERRNO!() = EILSEQ; return !0usize;
9356 }
9357 c = BITTAB[*s as usize - SA as usize];
9358 s = s.add(1);
9359 n -= 1;
9360 }
9361
9362 if n > 0 {
9363 if mb_oob(c, *s) != 0 {
9364 *st = 0; ERRNO!() = EILSEQ; return !0usize;
9365 }
9366 loop {
9367 c = (c << 6) | (*s as u32).wrapping_sub(0x80);
9368 s = s.add(1);
9369 n -= 1;
9370 if c & (1u32 << 31) == 0 {
9371 *st = 0;
9372 *wc = c as c_int;
9373 return n0 - n;
9374 }
9375 if n == 0 { break; }
9376 if (*s).wrapping_sub(0x80) >= 0x40 {
9377 *st = 0; ERRNO!() = EILSEQ; return !0usize;
9378 }
9379 }
9380 }
9381
9382 *st = c;
9383 !1usize
9384}
9385
9386#[no_mangle]
9387pub unsafe extern "C" fn wcrtomb(
9388 s: *mut c_char,
9389 wc: c_int,
9390 _st: *mut c_uint,
9391) -> usize {
9392 if s.is_null() { return 1; }
9393 let wc_u = wc as u32;
9394 if unsafe { !LOCALE_CTYPE_UTF8 } {
9395 if wc_u > 0xFF {
9396 ERRNO!() = EILSEQ;
9397 return !0usize;
9398 }
9399 *s = wc as c_char;
9400 return 1;
9401 }
9402 if wc_u < 0x80 {
9403 *s = wc as c_char;
9404 return 1;
9405 }
9406 if wc_u < 0x800 {
9407 *s = (0xC0 | (wc_u >> 6)) as c_char;
9408 *s.add(1) = (0x80 | (wc_u & 0x3F)) as c_char;
9409 return 2;
9410 }
9411 if wc_u < 0xD800 || wc_u.wrapping_sub(0xE000) < 0x2000 {
9412 *s = (0xE0 | (wc_u >> 12)) as c_char;
9413 *s.add(1) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
9414 *s.add(2) = (0x80 | (wc_u & 0x3F)) as c_char;
9415 return 3;
9416 }
9417 if wc_u.wrapping_sub(0x10000) < 0x100000 {
9418 *s = (0xF0 | (wc_u >> 18)) as c_char;
9419 *s.add(1) = (0x80 | ((wc_u >> 12) & 0x3F)) as c_char;
9420 *s.add(2) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
9421 *s.add(3) = (0x80 | (wc_u & 0x3F)) as c_char;
9422 return 4;
9423 }
9424 ERRNO!() = EILSEQ;
9425 !0usize
9426}
9427
9428#[no_mangle]
9429pub unsafe extern "C" fn mblen(s: *const c_char, n: usize) -> c_int {
9430 if s.is_null() { return 0; }
9431 mbtowc(core::ptr::null_mut(), s, n)
9432}
9433
9434#[no_mangle]
9435pub unsafe extern "C" fn mbtowc(
9436 wc: *mut c_int,
9437 src: *const c_char,
9438 n: usize,
9439) -> c_int {
9440 if src.is_null() { return 0; }
9441 if n == 0 { ERRNO!() = EILSEQ; return -1; }
9442 let mut state: c_uint = 0;
9443 let mut w: c_int = 0;
9444 let r = mbrtowc(&mut w, src, n, &mut state);
9445 if r == !0usize { return -1; }
9446 if !wc.is_null() { *wc = w; }
9447 r as c_int
9448}
9449
9450#[no_mangle]
9451pub unsafe extern "C" fn wctomb(s: *mut c_char, wc: c_int) -> c_int {
9452 if s.is_null() { return 0; }
9453 wcrtomb(s, wc, core::ptr::null_mut()) as c_int
9454}
9455
9456#[no_mangle]
9457pub unsafe extern "C" fn mbsrtowcs(
9458 ws: *mut c_int,
9459 src: *mut *const c_char,
9460 wn: usize,
9461 st: *mut c_uint,
9462) -> usize {
9463 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
9464 let mut s = *src as *const u8;
9465 let wn0 = wn;
9466 let mut wn = wn;
9467
9468 if ws.is_null() {
9469 while *s != 0 {
9470 if *s < 0x80 {
9471 s = s.add(1);
9472 wn = wn.wrapping_sub(1);
9473 continue;
9474 }
9475 let mut wc: c_int = 0;
9476 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
9477 if r == !0usize { return !0usize; }
9478 if r == !1usize { return wn0 - wn; }
9479 s = s.add(r);
9480 wn = wn.wrapping_sub(1);
9481 }
9482 wn0 - wn
9483 } else {
9484 let mut w = ws;
9485 while wn > 0 {
9486 if *s < 0x80 {
9487 let c = *s as c_int;
9488 *w = c;
9489 if c == 0 {
9490 *src = core::ptr::null();
9491 return wn0 - wn;
9492 }
9493 w = w.add(1);
9494 s = s.add(1);
9495 wn -= 1;
9496 continue;
9497 }
9498 let mut wc: c_int = 0;
9499 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
9500 if r == !0usize {
9501 *src = s as *const c_char;
9502 return !0usize;
9503 }
9504 if r == !1usize {
9505 *src = s as *const c_char;
9506 return wn0 - wn;
9507 }
9508 *w = wc;
9509 w = w.add(1);
9510 s = s.add(r);
9511 wn -= 1;
9512 }
9513 *src = s as *const c_char;
9514 wn0 - wn
9515 }
9516}
9517
9518#[no_mangle]
9519pub unsafe extern "C" fn wcsrtombs(
9520 s: *mut c_char,
9521 ws: *mut *const c_int,
9522 n: usize,
9523 _st: *mut c_uint,
9524) -> usize {
9525 let mut w = *ws;
9526 let n0 = n;
9527 let mut n = n;
9528
9529 if s.is_null() {
9530 let mut count = 0usize;
9531 while *w != 0 {
9532 if (*w as u32) < 0x80 {
9533 count += 1;
9534 } else {
9535 let mut buf = [0u8; 4];
9536 let r = wcrtomb(buf.as_mut_ptr() as *mut c_char, *w, core::ptr::null_mut());
9537 if r == !0usize { return !0usize; }
9538 count += r;
9539 }
9540 w = w.add(1);
9541 }
9542 return count;
9543 }
9544
9545 let mut dst = s;
9546 while n > 0 {
9547 if (*w as u32) < 0x80 {
9548 *dst = *w as c_char;
9549 if *w == 0 {
9550 *ws = core::ptr::null();
9551 return n0 - n;
9552 }
9553 dst = dst.add(1);
9554 n -= 1;
9555 } else {
9556 let r = wcrtomb(dst, *w, core::ptr::null_mut());
9557 if r == !0usize {
9558 *ws = w;
9559 return !0usize;
9560 }
9561 if r > n {
9562 *ws = w;
9563 return n0 - n;
9564 }
9565 dst = dst.add(r);
9566 n -= r;
9567 }
9568 w = w.add(1);
9569 }
9570 *ws = w;
9571 n0
9572}
9573
9574#[no_mangle]
9575pub unsafe extern "C" fn mbstowcs(
9576 ws: *mut c_int,
9577 src: *const c_char,
9578 wn: usize,
9579) -> usize {
9580 let mut src_ptr = src;
9581 mbsrtowcs(ws, &mut src_ptr, wn, core::ptr::null_mut())
9582}
9583
9584#[no_mangle]
9585pub unsafe extern "C" fn wcstombs(
9586 s: *mut c_char,
9587 ws: *const c_int,
9588 n: usize,
9589) -> usize {
9590 let mut ws_ptr = ws;
9591 wcsrtombs(s, &mut ws_ptr, n, core::ptr::null_mut())
9592}
9593
9594#[no_mangle]
9599pub extern "C" fn btowc(c: c_int) -> wint_t {
9600 if c == -1 { return WEOF; }
9601 unsafe {
9602 if LOCALE_CTYPE_UTF8 {
9603 if (c as u32) < 128 { c as wint_t } else { WEOF }
9604 } else {
9605 (c as u8) as wint_t
9606 }
9607 }
9608}
9609
9610#[no_mangle]
9611pub extern "C" fn wctob(c: wint_t) -> c_int {
9612 unsafe {
9613 if LOCALE_CTYPE_UTF8 {
9614 if c < 128 { c as c_int } else { -1 }
9615 } else {
9616 if c <= 0xFF { c as c_int } else { -1 }
9617 }
9618 }
9619}
9620
9621#[no_mangle]
9622pub unsafe extern "C" fn mbsinit(s: *const c_uint) -> c_int {
9623 if s.is_null() || *s == 0 { 1 } else { 0 }
9624}
9625
9626#[no_mangle]
9627pub unsafe extern "C" fn mbrlen(s: *const c_char, n: usize, ps: *mut c_uint) -> usize {
9628 mbrtowc(core::ptr::null_mut(), s, n, ps)
9629}
9630
9631#[no_mangle]
9636pub unsafe extern "C" fn wcslen(s: *const wchar_t) -> usize {
9637 let mut len = 0;
9638 while *s.add(len) != 0 { len += 1; }
9639 len
9640}
9641
9642#[no_mangle]
9643pub unsafe extern "C" fn wcschr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
9644 let mut i = 0;
9645 loop {
9646 let ch = *s.add(i);
9647 if ch == c { return s.add(i) as *mut wchar_t; }
9648 if ch == 0 { return null_mut(); }
9649 i += 1;
9650 }
9651}
9652
9653#[no_mangle]
9654pub unsafe extern "C" fn wcsrchr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
9655 let mut i = 0;
9656 let mut last: *mut wchar_t = null_mut();
9657 loop {
9658 let ch = *s.add(i);
9659 if ch == c { last = s.add(i) as *mut wchar_t; }
9660 if ch == 0 { return last; }
9661 i += 1;
9662 }
9663}
9664
9665#[no_mangle]
9666pub unsafe extern "C" fn wcsstr(haystack: *const wchar_t, needle: *const wchar_t) -> *mut wchar_t {
9667 if *needle == 0 { return haystack as *mut wchar_t; }
9668 let mut i = 0;
9669 loop {
9670 let h = *haystack.add(i);
9671 if h == 0 { return null_mut(); }
9672 if h == *needle {
9673 let mut j = 0;
9674 loop {
9675 let n = *needle.add(j);
9676 if n == 0 { return haystack.add(i) as *mut wchar_t; }
9677 if *haystack.add(i + j) != n { break; }
9678 j += 1;
9679 }
9680 }
9681 i += 1;
9682 }
9683}
9684
9685#[no_mangle]
9686pub unsafe extern "C" fn wcscmp(s1: *const wchar_t, s2: *const wchar_t) -> c_int {
9687 let mut i = 0;
9688 loop {
9689 let a = *s1.add(i);
9690 let b = *s2.add(i);
9691 if a != b { return a - b; }
9692 if a == 0 { return 0; }
9693 i += 1;
9694 }
9695}
9696
9697#[no_mangle]
9698pub unsafe extern "C" fn wcsncmp(s1: *const wchar_t, s2: *const wchar_t, n: usize) -> c_int {
9699 let mut i = 0;
9700 while i < n {
9701 let a = *s1.add(i);
9702 let b = *s2.add(i);
9703 if a != b { return a - b; }
9704 if a == 0 { return 0; }
9705 i += 1;
9706 }
9707 0
9708}
9709
9710#[no_mangle]
9711pub unsafe extern "C" fn wcscpy(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
9712 let mut i = 0;
9713 loop {
9714 let c = *src.add(i);
9715 *dst.add(i) = c;
9716 if c == 0 { break; }
9717 i += 1;
9718 }
9719 dst
9720}
9721
9722#[no_mangle]
9723pub unsafe extern "C" fn wcsncpy(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
9724 let mut i = 0;
9725 while i < n && *src.add(i) != 0 { *dst.add(i) = *src.add(i); i += 1; }
9726 while i < n { *dst.add(i) = 0; i += 1; }
9727 dst
9728}
9729
9730#[no_mangle]
9731pub unsafe extern "C" fn wcscat(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
9732 let mut i = 0;
9733 while *dst.add(i) != 0 { i += 1; }
9734 let mut j = 0;
9735 loop {
9736 let c = *src.add(j);
9737 *dst.add(i + j) = c;
9738 if c == 0 { break; }
9739 j += 1;
9740 }
9741 dst
9742}
9743
9744#[no_mangle]
9745pub unsafe extern "C" fn wcsncat(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
9746 let mut i = 0;
9747 while *dst.add(i) != 0 { i += 1; }
9748 let mut j = 0;
9749 while j < n && *src.add(j) != 0 { *dst.add(i + j) = *src.add(j); j += 1; }
9750 *dst.add(i + j) = 0;
9751 dst
9752}
9753
9754#[no_mangle]
9755pub unsafe extern "C" fn wcsdup(s: *const wchar_t) -> *mut wchar_t {
9756 let len = wcslen(s);
9757 let p = malloc((len + 1) * core::mem::size_of::<wchar_t>()) as *mut wchar_t;
9758 if p.is_null() { return null_mut(); }
9759 core::ptr::copy_nonoverlapping(s, p, len + 1);
9760 p
9761}
9762
9763#[no_mangle]
9764pub unsafe extern "C" fn wcsnlen(s: *const wchar_t, maxlen: usize) -> usize {
9765 let mut i = 0;
9766 while i < maxlen && *s.add(i) != 0 { i += 1; }
9767 i
9768}
9769
9770#[no_mangle]
9771pub unsafe extern "C" fn wcsspn(s: *const wchar_t, accept: *const wchar_t) -> usize {
9772 let mut i = 0;
9773 loop {
9774 let c = *s.add(i);
9775 if c == 0 { return i; }
9776 let mut found = false;
9777 let mut j = 0;
9778 loop {
9779 let a = *accept.add(j);
9780 if a == 0 { break; }
9781 if c == a { found = true; break; }
9782 j += 1;
9783 }
9784 if !found { return i; }
9785 i += 1;
9786 }
9787}
9788
9789#[no_mangle]
9790pub unsafe extern "C" fn wcscspn(s: *const wchar_t, reject: *const wchar_t) -> usize {
9791 let mut i = 0;
9792 loop {
9793 let c = *s.add(i);
9794 if c == 0 { return i; }
9795 let mut j = 0;
9796 loop {
9797 let r = *reject.add(j);
9798 if r == 0 { break; }
9799 if c == r { return i; }
9800 j += 1;
9801 }
9802 i += 1;
9803 }
9804}
9805
9806#[no_mangle]
9807pub unsafe extern "C" fn wcspbrk(s: *const wchar_t, accept: *const wchar_t) -> *mut wchar_t {
9808 let mut i = 0;
9809 loop {
9810 let c = *s.add(i);
9811 if c == 0 { return null_mut(); }
9812 let mut j = 0;
9813 loop {
9814 let a = *accept.add(j);
9815 if a == 0 { break; }
9816 if c == a { return s.add(i) as *mut wchar_t; }
9817 j += 1;
9818 }
9819 i += 1;
9820 }
9821}
9822
9823#[no_mangle]
9824pub unsafe extern "C" fn wcsxfrm(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> usize {
9825 let len = wcslen(src);
9826 if !dst.is_null() {
9827 let copy = if len < n { len } else { if n > 0 { n - 1 } else { 0 } };
9828 for i in 0..copy { *dst.add(i) = *src.add(i); }
9829 if n > 0 { *dst.add(copy) = 0; }
9830 }
9831 len
9832}
9833
9834unsafe fn wcs_to_bytes(ws: *const wchar_t, buf: *mut u8, bufsz: usize) -> usize {
9839 let mut i = 0;
9840 while i < bufsz - 1 {
9841 let c = *ws.add(i);
9842 if c == 0 { break; }
9843 if (c as u32) > 127 { break; }
9844 *buf.add(i) = c as u8;
9845 i += 1;
9846 }
9847 *buf.add(i) = 0;
9848 i
9849}
9850
9851#[no_mangle]
9852pub unsafe extern "C" fn wcstol(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_long {
9853 let mut buf = [0u8; 256];
9854 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
9855 let mut end: *mut c_char = core::ptr::null_mut();
9856 let r = strtol(buf.as_ptr() as *const c_char, &mut end, base);
9857 if !endptr.is_null() {
9858 let offset = end as usize - buf.as_ptr() as usize;
9859 *endptr = s.add(offset) as *mut wchar_t;
9860 }
9861 r
9862}
9863
9864#[no_mangle]
9865pub unsafe extern "C" fn wcstoul(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulong {
9866 let mut buf = [0u8; 256];
9867 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
9868 let mut end: *mut c_char = core::ptr::null_mut();
9869 let r = strtoul(buf.as_ptr() as *const c_char, &mut end, base);
9870 if !endptr.is_null() {
9871 let offset = end as usize - buf.as_ptr() as usize;
9872 *endptr = s.add(offset) as *mut wchar_t;
9873 }
9874 r
9875}
9876
9877#[no_mangle]
9878pub unsafe extern "C" fn wcstoll(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong {
9879 let mut buf = [0u8; 256];
9880 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
9881 let mut end: *mut c_char = core::ptr::null_mut();
9882 let r = strtoll(buf.as_ptr() as *const c_char, &mut end, base);
9883 if !endptr.is_null() {
9884 let offset = end as usize - buf.as_ptr() as usize;
9885 *endptr = s.add(offset) as *mut wchar_t;
9886 }
9887 r
9888}
9889
9890#[no_mangle]
9891pub unsafe extern "C" fn wcstoull(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong {
9892 let mut buf = [0u8; 256];
9893 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
9894 let mut end: *mut c_char = core::ptr::null_mut();
9895 let r = strtoull(buf.as_ptr() as *const c_char, &mut end, base);
9896 if !endptr.is_null() {
9897 let offset = end as usize - buf.as_ptr() as usize;
9898 *endptr = s.add(offset) as *mut wchar_t;
9899 }
9900 r
9901}
9902
9903#[no_mangle]
9904pub unsafe extern "C" fn wcstod(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 {
9905 let mut buf = [0u8; 256];
9906 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
9907 let mut end: *mut c_char = core::ptr::null_mut();
9908 let r = strtod(buf.as_ptr() as *const c_char, &mut end);
9909 if !endptr.is_null() {
9910 let offset = end as usize - buf.as_ptr() as usize;
9911 *endptr = s.add(offset) as *mut wchar_t;
9912 }
9913 r
9914}
9915
9916#[no_mangle]
9917pub unsafe extern "C" fn wcstof(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f32 { wcstod(s, endptr) as f32 }
9918
9919#[no_mangle]
9920#[cfg(target_arch = "x86_64")]
9921pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 { wcstod(s, endptr) }
9922
9923#[no_mangle]
9924#[cfg(target_arch = "aarch64")]
9925pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
9926
9927#[no_mangle]
9928#[cfg(target_arch = "riscv64")]
9929pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
9930
9931#[no_mangle]
9932pub unsafe extern "C" fn wcstoimax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong { wcstoll(s, endptr, base) }
9933
9934#[no_mangle]
9935pub unsafe extern "C" fn wcstoumax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong { wcstoull(s, endptr, base) }
9936
9937const WC_ALPHA: c_int = 1;
9942const WC_DIGIT: c_int = 2;
9943const WC_SPACE: c_int = 4;
9944const WC_UPPER: c_int = 8;
9945const WC_LOWER: c_int = 16;
9946const WC_ALNUM: c_int = WC_ALPHA | WC_DIGIT;
9947const WC_BLANK: c_int = 32;
9948const WC_CNTRL: c_int = 64;
9949const WC_PUNCT: c_int = 128;
9950const WC_GRAPH: c_int = WC_ALNUM | WC_PUNCT;
9951const WC_PRINT: c_int = WC_GRAPH | WC_BLANK;
9952const WC_XDIGIT: c_int = 256;
9953
9954fn wc_flags(c: wint_t) -> c_int {
9955 if c < 128 {
9956 let f = CT_TABLE[c as usize];
9957 let mut r = 0;
9958 if f & (CT_UPPER | CT_LOWER) != 0 { r |= WC_ALPHA; }
9959 if f & CT_DIGIT != 0 { r |= WC_DIGIT; }
9960 if f & CT_SPACE != 0 { r |= WC_SPACE; }
9961 if f & CT_UPPER != 0 { r |= WC_UPPER; }
9962 if f & CT_LOWER != 0 { r |= WC_LOWER; }
9963 if f & CT_BLANK != 0 { r |= WC_BLANK; }
9964 if f & CT_CNTRL != 0 { r |= WC_CNTRL; }
9965 if f & CT_PUNCT != 0 { r |= WC_PUNCT; }
9966 if f & CT_XDIGIT != 0 { r |= WC_XDIGIT; }
9967 r
9968 } else {
9969 if c < 0x100 { 0 }
9970 else { WC_PRINT | WC_ALPHA }
9971 }
9972}
9973
9974#[no_mangle]
9975pub extern "C" fn iswalnum(c: wint_t) -> c_int { (wc_flags(c) & WC_ALNUM != 0) as c_int }
9976#[no_mangle]
9977pub extern "C" fn iswalpha(c: wint_t) -> c_int { (wc_flags(c) & WC_ALPHA != 0) as c_int }
9978#[no_mangle]
9979pub extern "C" fn iswblank(c: wint_t) -> c_int { (wc_flags(c) & WC_BLANK != 0) as c_int }
9980#[no_mangle]
9981pub extern "C" fn iswcntrl(c: wint_t) -> c_int { (wc_flags(c) & WC_CNTRL != 0) as c_int }
9982#[no_mangle]
9983pub extern "C" fn iswdigit(c: wint_t) -> c_int { ((c >= b'0' as wint_t) && (c <= b'9' as wint_t)) as c_int }
9984#[no_mangle]
9985pub extern "C" fn iswgraph(c: wint_t) -> c_int { (wc_flags(c) & WC_GRAPH != 0) as c_int }
9986#[no_mangle]
9987pub extern "C" fn iswlower(c: wint_t) -> c_int { (wc_flags(c) & WC_LOWER != 0) as c_int }
9988#[no_mangle]
9989pub extern "C" fn iswprint(c: wint_t) -> c_int {
9990 if c < 128 { (wc_flags(c) & WC_PRINT != 0) as c_int }
9991 else if c >= 0x100 && c < 0x110000 { 1 }
9992 else { 0 }
9993}
9994#[no_mangle]
9995pub extern "C" fn iswpunct(c: wint_t) -> c_int { (wc_flags(c) & WC_PUNCT != 0) as c_int }
9996#[no_mangle]
9997pub extern "C" fn iswspace(c: wint_t) -> c_int {
9998 if c < 128 { (wc_flags(c) & WC_SPACE != 0) as c_int }
9999 else {
10000 match c {
10001 0x1680 | 0x2000..=0x200A | 0x2028 | 0x2029 | 0x202F | 0x205F | 0x3000 => 1,
10002 _ => 0,
10003 }
10004 }
10005}
10006#[no_mangle]
10007pub extern "C" fn iswupper(c: wint_t) -> c_int { (wc_flags(c) & WC_UPPER != 0) as c_int }
10008#[no_mangle]
10009pub extern "C" fn iswxdigit(c: wint_t) -> c_int { (wc_flags(c) & WC_XDIGIT != 0) as c_int }
10010
10011static WCTYPE_ALNUM: c_int = WC_ALNUM;
10012static WCTYPE_ALPHA: c_int = WC_ALPHA;
10013static WCTYPE_BLANK: c_int = WC_BLANK;
10014static WCTYPE_CNTRL: c_int = WC_CNTRL;
10015static WCTYPE_DIGIT: c_int = WC_DIGIT;
10016static WCTYPE_GRAPH: c_int = WC_GRAPH;
10017static WCTYPE_LOWER: c_int = WC_LOWER;
10018static WCTYPE_PRINT: c_int = WC_PRINT;
10019static WCTYPE_PUNCT: c_int = WC_PUNCT;
10020static WCTYPE_SPACE: c_int = WC_SPACE;
10021static WCTYPE_UPPER: c_int = WC_UPPER;
10022static WCTYPE_XDIGIT: c_int = WC_XDIGIT;
10023
10024#[no_mangle]
10025pub unsafe extern "C" fn wctype(name: *const c_char) -> wctype_t {
10026 if name.is_null() { return core::ptr::null(); }
10027 let n = name as *const u8;
10028 if strcmp(n, b"alnum\0".as_ptr()) == 0 { return &WCTYPE_ALNUM; }
10029 if strcmp(n, b"alpha\0".as_ptr()) == 0 { return &WCTYPE_ALPHA; }
10030 if strcmp(n, b"blank\0".as_ptr()) == 0 { return &WCTYPE_BLANK; }
10031 if strcmp(n, b"cntrl\0".as_ptr()) == 0 { return &WCTYPE_CNTRL; }
10032 if strcmp(n, b"digit\0".as_ptr()) == 0 { return &WCTYPE_DIGIT; }
10033 if strcmp(n, b"graph\0".as_ptr()) == 0 { return &WCTYPE_GRAPH; }
10034 if strcmp(n, b"lower\0".as_ptr()) == 0 { return &WCTYPE_LOWER; }
10035 if strcmp(n, b"print\0".as_ptr()) == 0 { return &WCTYPE_PRINT; }
10036 if strcmp(n, b"punct\0".as_ptr()) == 0 { return &WCTYPE_PUNCT; }
10037 if strcmp(n, b"space\0".as_ptr()) == 0 { return &WCTYPE_SPACE; }
10038 if strcmp(n, b"upper\0".as_ptr()) == 0 { return &WCTYPE_UPPER; }
10039 if strcmp(n, b"xdigit\0".as_ptr()) == 0 { return &WCTYPE_XDIGIT; }
10040 core::ptr::null()
10041}
10042
10043#[no_mangle]
10044pub unsafe extern "C" fn iswctype(c: wint_t, desc: wctype_t) -> c_int {
10045 if desc.is_null() { return 0; }
10046 (wc_flags(c) & *desc != 0) as c_int
10047}
10048
10049static WCTRANS_LOWER: c_int = 1;
10050static WCTRANS_UPPER: c_int = 2;
10051
10052#[no_mangle]
10053pub unsafe extern "C" fn towlower(c: wint_t) -> wint_t {
10054 if c < 128 { tolower(c as c_int) as wint_t } else { c }
10055}
10056
10057#[no_mangle]
10058pub unsafe extern "C" fn towupper(c: wint_t) -> wint_t {
10059 if c < 128 { toupper(c as c_int) as wint_t } else { c }
10060}
10061
10062#[no_mangle]
10063pub unsafe extern "C" fn wctrans(name: *const c_char) -> wctrans_t {
10064 if name.is_null() { return core::ptr::null(); }
10065 let n = name as *const u8;
10066 if strcmp(n, b"tolower\0".as_ptr()) == 0 { return &WCTRANS_LOWER; }
10067 if strcmp(n, b"toupper\0".as_ptr()) == 0 { return &WCTRANS_UPPER; }
10068 core::ptr::null()
10069}
10070
10071#[no_mangle]
10072pub unsafe extern "C" fn towctrans(c: wint_t, desc: wctrans_t) -> wint_t {
10073 if desc.is_null() { return c; }
10074 match *desc {
10075 1 => towlower(c),
10076 2 => towupper(c),
10077 _ => c,
10078 }
10079}
10080
10081#[no_mangle]
10086pub unsafe extern "C" fn fgetwc(f: *mut FILE) -> wint_t {
10087 let mut state: c_uint = 0;
10088 let mut wc: wchar_t = 0;
10089 let mut buf = [0u8; 4];
10090 let c = fgetc(f);
10091 if c == -1 { return WEOF; }
10092 buf[0] = c as u8;
10093 if buf[0] < 0x80 { return buf[0] as wint_t; }
10094 let len = if buf[0] < 0xE0 { 2 } else if buf[0] < 0xF0 { 3 } else { 4 };
10095 let mut n = 1usize;
10096 while n < len {
10097 let c2 = fgetc(f);
10098 if c2 == -1 { return WEOF; }
10099 buf[n] = c2 as u8;
10100 n += 1;
10101 }
10102 let r = mbrtowc(&mut wc, buf.as_ptr() as *const c_char, n, &mut state);
10103 if r == !0usize || r == !1usize { WEOF } else { wc as wint_t }
10104}
10105
10106#[no_mangle]
10107pub unsafe extern "C" fn fputwc(c: wchar_t, f: *mut FILE) -> wint_t {
10108 let mut buf = [0u8; 4];
10109 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c, core::ptr::null_mut());
10110 if n == !0usize || n == 0 { return WEOF; }
10111 if fwrite(buf.as_ptr() as *const c_void, 1, n, f) != n { return WEOF; }
10112 c as wint_t
10113}
10114
10115#[no_mangle]
10116pub unsafe extern "C" fn fputws(s: *const wchar_t, f: *mut FILE) -> c_int {
10117 let mut i = 0;
10118 while *s.add(i) != 0 {
10119 if fputwc(*s.add(i), f) == WEOF { return -1; }
10120 i += 1;
10121 }
10122 0
10123}
10124
10125#[no_mangle]
10126pub unsafe extern "C" fn ungetwc(c: wint_t, f: *mut FILE) -> wint_t {
10127 if c == WEOF { return WEOF; }
10128 let mut buf = [0u8; 4];
10129 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c as wchar_t, core::ptr::null_mut());
10130 if n == !0usize || n == 0 { return WEOF; }
10131 let mut i = n;
10132 while i > 0 {
10133 i -= 1;
10134 if ungetc(buf[i] as c_int, f) == -1 { return WEOF; }
10135 }
10136 c
10137}
10138
10139#[no_mangle]
10140pub unsafe extern "C" fn getwchar() -> wint_t { fgetwc(stdin) }
10141
10142#[no_mangle]
10143pub unsafe extern "C" fn putwchar(c: wchar_t) -> wint_t { fputwc(c, stdout) }
10144
10145unsafe fn wfmt_write_str(dst: *mut wchar_t, pos: usize, cap: usize, s: *const u8, len: usize) -> usize {
10150 let mut i = 0;
10151 while i < len {
10152 if pos + i < cap { *dst.add(pos + i) = *s.add(i) as wchar_t; }
10153 i += 1;
10154 }
10155 pos + len
10156}
10157
10158#[no_mangle]
10159pub unsafe extern "C" fn vswprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, mut args: VaList) -> c_int {
10160 if n == 0 { return -1; }
10161 let cap = n - 1;
10162 let mut pos = 0usize;
10163 let mut fmt_narrow = [0u8; 256];
10165 let mut flen = 0usize;
10166 loop {
10167 let ch = *fmt.add(flen) as u32;
10168 if ch == 0 || flen >= 255 { break; }
10169 fmt_narrow[flen] = if ch < 128 { ch as u8 } else { b'?' };
10170 flen += 1;
10171 }
10172 fmt_narrow[flen] = 0;
10173 let mut fi = 0usize;
10174 macro_rules! wc {
10175 ($c:expr) => { if pos < cap { *s.add(pos) = $c as wchar_t; } pos += 1; }
10176 }
10177 loop {
10178 let c = fmt_narrow[fi];
10179 if c == 0 { break; }
10180 if c != b'%' { wc!(c); fi += 1; continue; }
10181 fi += 1;
10182 let mut flags: u8 = 0;
10183 loop {
10184 match fmt_narrow[fi] {
10185 b'-' => { flags |= FLAG_MINUS; fi += 1; }
10186 b'+' => { flags |= FLAG_PLUS; fi += 1; }
10187 b' ' => { flags |= FLAG_SPACE; fi += 1; }
10188 b'0' => { flags |= FLAG_ZERO; fi += 1; }
10189 b'#' => { flags |= FLAG_HASH; fi += 1; }
10190 _ => break,
10191 }
10192 }
10193 let mut width: usize = 0;
10194 if fmt_narrow[fi] == b'*' {
10195 let w = args.next_arg::<c_int>();
10196 if w < 0 { flags |= FLAG_MINUS; width = (-w) as usize; } else { width = w as usize; }
10197 fi += 1;
10198 } else {
10199 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10200 width = width * 10 + (fmt_narrow[fi] - b'0') as usize; fi += 1;
10201 }
10202 }
10203 let mut precision: i32 = -1;
10204 if fmt_narrow[fi] == b'.' {
10205 fi += 1;
10206 if fmt_narrow[fi] == b'*' {
10207 let p = args.next_arg::<c_int>();
10208 precision = if p < 0 { -1 } else { p }; fi += 1;
10209 } else {
10210 precision = 0;
10211 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10212 precision = precision * 10 + (fmt_narrow[fi] - b'0') as i32; fi += 1;
10213 }
10214 }
10215 }
10216 let len_mod = fmt_narrow[fi];
10217 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' {
10218 fi += 1;
10219 let spec = fmt_narrow[fi];
10220 if (len_mod == b'h' && spec == b'h') || (len_mod == b'l' && spec == b'l') {
10221 fi += 1;
10222 let spec2 = fmt_narrow[fi];
10223 match (len_mod, spec, spec2) {
10224 (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; } }
10225 (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; } }
10226 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
10227 let val = args.next_arg::<c_longlong>();
10228 let neg = val < 0;
10229 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10230 let b = format_u64(abs);
10231 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10232 let mut fbuf = [0u8; 32];
10233 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10234 for k in 0..len { wc!(fbuf[k]); }
10235 }
10236 (b'l', b'l', b'u') => {
10237 let val = args.next_arg::<c_ulonglong>();
10238 let b = format_u64(val as u64);
10239 let mut fbuf = [0u8; 32];
10240 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10241 for k in 0..len { wc!(fbuf[k]); }
10242 }
10243 (b'l', b'l', b'x') => {
10244 let val = args.next_arg::<c_ulonglong>();
10245 let b = format_hex(val as u64, false);
10246 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10247 let mut fbuf = [0u8; 32];
10248 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10249 for k in 0..len { wc!(fbuf[k]); }
10250 }
10251 (b'l', b'l', b'X') => {
10252 let val = args.next_arg::<c_ulonglong>();
10253 let b = format_hex(val as u64, true);
10254 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10255 let mut fbuf = [0u8; 32];
10256 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10257 for k in 0..len { wc!(fbuf[k]); }
10258 }
10259 (b'l', b'l', b'o') => {
10260 let val = args.next_arg::<c_ulonglong>();
10261 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
10262 let mut fbuf = [0u8; 32];
10263 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10264 for k in 0..len { wc!(fbuf[k]); }
10265 }
10266 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); wc!(spec2); }
10267 }
10268 } else {
10269 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
10270 match (lm, spec) {
10271 (b'h', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut u16) = pos as u16; } }
10272 (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; } }
10273 (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; } }
10274 (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; } }
10275 (b'l', b'd') | (b'l', b'i') => {
10276 let val = args.next_arg::<c_long>();
10277 let neg = val < 0;
10278 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10279 let b = format_u64(abs);
10280 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10281 let mut fbuf = [0u8; 32];
10282 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10283 for k in 0..len { wc!(fbuf[k]); }
10284 }
10285 (b'l', b'u') => {
10286 let val = args.next_arg::<c_ulong>();
10287 let b = format_u64(val as u64);
10288 let mut fbuf = [0u8; 32];
10289 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10290 for k in 0..len { wc!(fbuf[k]); }
10291 }
10292 (b'l', b'x') => {
10293 let val = args.next_arg::<c_ulong>();
10294 let b = format_hex(val as u64, false);
10295 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10296 let mut fbuf = [0u8; 32];
10297 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10298 for k in 0..len { wc!(fbuf[k]); }
10299 }
10300 (b'l', b'X') => {
10301 let val = args.next_arg::<c_ulong>();
10302 let b = format_hex(val as u64, true);
10303 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10304 let mut fbuf = [0u8; 32];
10305 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10306 for k in 0..len { wc!(fbuf[k]); }
10307 }
10308 (b'l', b'o') => {
10309 let val = args.next_arg::<c_ulong>();
10310 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
10311 let mut fbuf = [0u8; 32];
10312 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10313 for k in 0..len { wc!(fbuf[k]); }
10314 }
10315 (b'l', b'c') => {
10316 let ch = args.next_arg::<wint_t>();
10317 wc!(ch);
10318 }
10319 (b'l', b's') => {
10320 let ws_arg = args.next_arg::<*const wchar_t>();
10321 if ws_arg.is_null() {
10322 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
10323 if flags & FLAG_MINUS != 0 {
10324 for k in 0..slen { wc!(b"(null)"[k]); }
10325 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10326 } else {
10327 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10328 for k in 0..slen { wc!(b"(null)"[k]); }
10329 }
10330 } else {
10331 let mut wlen = 0usize;
10332 loop {
10333 let ch = *ws_arg.add(wlen);
10334 if ch == 0 { break; }
10335 if precision >= 0 && wlen >= precision as usize { break; }
10336 wlen += 1;
10337 }
10338 if flags & FLAG_MINUS != 0 {
10339 for k in 0..wlen { wc!(*ws_arg.add(k)); }
10340 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
10341 } else {
10342 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
10343 for k in 0..wlen { wc!(*ws_arg.add(k)); }
10344 }
10345 }
10346 }
10347 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
10348 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
10349 let val = args.next_arg::<f64>();
10350 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
10351 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
10352 let mut fbuf = [0u8; 4224];
10353 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
10354 let mut wbuf = [0u8; 4224];
10355 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
10356 for k in 0..wlen { wc!(wbuf[k]); }
10357 }
10358 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
10359 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
10360 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
10361 let val = {
10362 let lo: u64 = args.next_arg::<u64>();
10363 let hi: u64 = args.next_arg::<u64>();
10364 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
10365 f128::from_bits(combined) as f64
10366 };
10367 #[cfg(target_arch = "x86_64")]
10368 let val = args.next_arg::<f64>();
10369 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
10370 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
10371 let mut fbuf = [0u8; 4224];
10372 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
10373 let mut wbuf = [0u8; 4224];
10374 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
10375 for k in 0..wlen { wc!(wbuf[k]); }
10376 }
10377 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); }
10378 }
10379 }
10380 } else {
10381 let spec = fmt_narrow[fi];
10382 match spec {
10383 b'd' | b'i' => {
10384 let d = args.next_arg::<c_int>();
10385 let neg = d < 0;
10386 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
10387 let b = format_u64(abs);
10388 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10389 let mut fbuf = [0u8; 32];
10390 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10391 for k in 0..len { wc!(fbuf[k]); }
10392 }
10393 b'u' => {
10394 let u = args.next_arg::<c_uint>();
10395 let b = format_u64(u as u64);
10396 let mut fbuf = [0u8; 32];
10397 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10398 for k in 0..len { wc!(fbuf[k]); }
10399 }
10400 b'x' => {
10401 let x = args.next_arg::<c_uint>();
10402 let b = format_hex(x as u64, false);
10403 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10404 let mut fbuf = [0u8; 32];
10405 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10406 for k in 0..len { wc!(fbuf[k]); }
10407 }
10408 b'X' => {
10409 let x = args.next_arg::<c_uint>();
10410 let b = format_hex(x as u64, true);
10411 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10412 let mut fbuf = [0u8; 32];
10413 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10414 for k in 0..len { wc!(fbuf[k]); }
10415 }
10416 b'o' => {
10417 let o = args.next_arg::<c_uint>();
10418 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
10419 let mut fbuf = [0u8; 32];
10420 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10421 for k in 0..len { wc!(fbuf[k]); }
10422 }
10423 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
10424 let val = args.next_arg::<f64>();
10425 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
10426 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
10427 let mut fbuf = [0u8; 4224];
10428 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
10429 let mut wbuf = [0u8; 4224];
10430 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
10431 for k in 0..wlen { wc!(wbuf[k]); }
10432 }
10433 b'c' => {
10434 let ch = args.next_arg::<c_int>();
10435 wc!(ch as u8);
10436 }
10437 b's' => {
10438 let p = args.next_arg::<*const c_char>();
10439 if p.is_null() {
10440 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
10441 if flags & FLAG_MINUS != 0 {
10442 for k in 0..slen { wc!(b"(null)"[k]); }
10443 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10444 } else {
10445 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10446 for k in 0..slen { wc!(b"(null)"[k]); }
10447 }
10448 } else {
10449 let mut wbuf_local = [0i32; 256];
10450 let mut wcount = 0usize;
10451 let mut byte_pos = 0usize;
10452 let pbytes = p as *const u8;
10453 loop {
10454 if precision >= 0 && wcount >= precision as usize { break; }
10455 if wcount >= 256 { break; }
10456 let mut wc_val: c_int = 0;
10457 let consumed = mbrtowc(&mut wc_val as *mut c_int, p.add(byte_pos) as *const c_char, 256, core::ptr::null_mut());
10458 if consumed == !0usize || consumed == !1usize {
10459 wbuf_local[wcount] = *pbytes.add(byte_pos) as c_int;
10460 byte_pos += 1;
10461 wcount += 1;
10462 } else if consumed == 0 {
10463 break;
10464 } else {
10465 wbuf_local[wcount] = wc_val;
10466 byte_pos += consumed;
10467 wcount += 1;
10468 }
10469 }
10470 if flags & FLAG_MINUS != 0 {
10471 for k in 0..wcount { wc!(wbuf_local[k]); }
10472 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
10473 } else {
10474 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
10475 for k in 0..wcount { wc!(wbuf_local[k]); }
10476 }
10477 }
10478 }
10479 b'p' => {
10480 wc!(b'0'); wc!(b'x');
10481 let p = args.next_arg::<*const c_void>();
10482 let b = format_hex(p as u64, false);
10483 for k in 0..b.1 { wc!(b.0[k]); }
10484 }
10485 b'n' => {
10486 let p = args.next_arg::<*mut c_void>();
10487 if !p.is_null() { *(p as *mut c_int) = pos as c_int; }
10488 }
10489 b'%' => { wc!(b'%'); }
10490 _ => { wc!(b'%'); wc!(spec); }
10491 }
10492 }
10493 fi += 1;
10494 }
10495 let null_pos = if pos < cap { pos } else { cap };
10496 *s.add(null_pos) = 0;
10497 if pos > cap { -1 } else { pos as c_int }
10498}
10499
10500#[no_mangle]
10501pub unsafe extern "C" fn swprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, args: ...) -> c_int {
10502 vswprintf(s, n, fmt, args)
10503}
10504
10505#[no_mangle]
10506pub unsafe extern "C" fn vfwprintf(f: *mut FILE, fmt: *const wchar_t, args: VaList) -> c_int {
10507 let mut buf = [0i32; 4096];
10508 let r = vswprintf(buf.as_mut_ptr(), 4096, fmt, args);
10509 if r < 0 { return r; }
10510 let mut i = 0;
10511 while i < r as usize {
10512 let mut mb = [0u8; 4];
10513 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, buf[i], core::ptr::null_mut());
10514 if n == !0usize { return -1; }
10515 if fwrite(mb.as_ptr() as *const c_void, 1, n, f) != n { return -1; }
10516 i += 1;
10517 }
10518 r
10519}
10520
10521#[no_mangle]
10522pub unsafe extern "C" fn fwprintf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
10523 vfwprintf(f, fmt, args)
10524}
10525
10526unsafe fn wcsfmt_to_mbs(dst: *mut u8, dst_len: usize, src: *const wchar_t) {
10532 let mut i = 0usize;
10533 loop {
10534 let ch = *src.add(i) as u32;
10535 if ch == 0 || i >= dst_len - 1 { break; }
10536 *dst.add(i) = if ch < 128 { ch as u8 } else { b'?' };
10537 i += 1;
10538 }
10539 *dst.add(i) = 0;
10540}
10541
10542#[no_mangle]
10543pub unsafe extern "C" fn vswscanf(s: *const wchar_t, fmt: *const wchar_t, mut args: VaList) -> c_int {
10544 let mut mbs_buf = [0u8; 4096];
10545 let mut i = 0usize;
10546 let mut mb_pos = 0usize;
10547 loop {
10548 let wc = *s.add(i) as c_int;
10549 if wc == 0 { break; }
10550 let mut mb = [0u8; 4];
10551 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, wc, core::ptr::null_mut());
10552 if n == !0usize || n == 0 { break; }
10553 if mb_pos + n >= mbs_buf.len() { break; }
10554 let mut k = 0usize;
10555 while k < n { mbs_buf[mb_pos + k] = mb[k]; k += 1; }
10556 mb_pos += n;
10557 i += 1;
10558 }
10559 mbs_buf[mb_pos] = 0;
10560 let mut mbs_fmt = [0u8; 4096];
10561 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
10562 do_vsscanf(mbs_buf.as_ptr(), mb_pos, mbs_fmt.as_ptr() as *const c_char, &mut args, core::ptr::null_mut())
10563}
10564
10565#[no_mangle]
10566pub unsafe extern "C" fn swscanf(s: *const wchar_t, fmt: *const wchar_t, args: ...) -> c_int {
10567 vswscanf(s, fmt, args)
10568}
10569
10570#[no_mangle]
10571pub unsafe extern "C" fn vfwscanf(f: *mut FILE, fmt: *const wchar_t, mut args: VaList) -> c_int {
10572 let start_pos = ftello(f);
10573 if start_pos < 0 { return -1; }
10574 let mut buf = [0u8; 4096];
10575 let mut n = 0usize;
10576 loop {
10577 if n >= buf.len() - 1 { break; }
10578 let c = fgetc(f);
10579 if c == -1 { break; }
10580 buf[n] = c as u8;
10581 n += 1;
10582 }
10583 buf[n] = 0;
10584 let mut mbs_fmt = [0u8; 4096];
10585 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
10586 let mut consumed = 0usize;
10587 let hit_eof = (*f)._eof != 0;
10588 let result = do_vsscanf(buf.as_ptr(), n, mbs_fmt.as_ptr() as *const c_char, &mut args, &mut consumed);
10589 let _ = fseeko(f, start_pos + consumed as i64, SEEK_SET);
10590 if hit_eof && consumed == n {
10591 (*f)._eof = 1;
10592 }
10593 result
10594}
10595
10596#[no_mangle]
10597pub unsafe extern "C" fn fwscanf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
10598 vfwscanf(f, fmt, args)
10599}
10600
10601#[no_mangle]
10602pub unsafe extern "C" fn vwscanf(fmt: *const wchar_t, args: VaList) -> c_int {
10603 vfwscanf(stdin, fmt, args)
10604}
10605
10606#[no_mangle]
10607pub unsafe extern "C" fn wscanf(fmt: *const wchar_t, args: ...) -> c_int {
10608 vfwscanf(stdin, fmt, args)
10609}
10610
10611const LEAPOCH: i64 = 946684800 + 86400 * (31 + 29);
10616const DAYS_PER_400Y: i64 = 365 * 400 + 97;
10617const DAYS_PER_100Y: i64 = 365 * 100 + 24;
10618const DAYS_PER_4Y: i64 = 365 * 4 + 1;
10619
10620const SECS_THROUGH_MONTH: [i32; 12] = [
10621 0, 31*86400, 59*86400, 90*86400, 120*86400, 151*86400,
10622 181*86400, 212*86400, 243*86400, 273*86400, 304*86400, 334*86400,
10623];
10624
10625const DAYS_IN_MONTH: [i32; 12] = [31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29];
10626
10627unsafe fn year_to_secs(year: i64, is_leap: &mut bool) -> i64 {
10628 if year - 2 <= 136 {
10629 let y = year as i32;
10630 let mut leaps = (y - 68) >> 2;
10631 if (y - 68) & 3 == 0 { leaps -= 1; *is_leap = true; } else { *is_leap = false; }
10632 return 31536000 * (y as i64 - 70) + 86400 * leaps as i64;
10633 }
10634 let mut cycles = ((year - 100) / 400) as i32;
10635 let mut rem = ((year - 100) % 400) as i32;
10636 if rem < 0 { cycles -= 1; rem += 400; }
10637 let (centuries, leaps);
10638 if rem == 0 { *is_leap = true; centuries = 0; leaps = 0; }
10639 else {
10640 let c;
10641 if rem >= 200 { if rem >= 300 { c = 3; rem -= 300; } else { c = 2; rem -= 200; } }
10642 else { if rem >= 100 { c = 1; rem -= 100; } else { c = 0; } }
10643 centuries = c;
10644 if rem == 0 { *is_leap = false; leaps = 0; }
10645 else { leaps = rem / 4; rem %= 4; *is_leap = rem == 0; }
10646 }
10647 let total_leaps = leaps + 97 * cycles + 24 * centuries - (*is_leap as i32);
10648 (year - 100) * 31536000 + total_leaps as i64 * 86400 + 946684800 + 86400
10649}
10650
10651fn month_to_secs(month: i32, is_leap: bool) -> i32 {
10652 let mut t = SECS_THROUGH_MONTH[month as usize];
10653 if is_leap && month >= 2 { t += 86400; }
10654 t
10655}
10656
10657unsafe fn secs_to_tm(t: i64, tm: &mut tm) -> bool {
10658 if t < (i32::MIN as i64) * 31622400 || t > (i32::MAX as i64) * 31622400 { return false; }
10659 let secs = t - LEAPOCH;
10660 let mut days = secs / 86400;
10661 let mut remsecs = (secs % 86400) as i32;
10662 if remsecs < 0 { remsecs += 86400; days -= 1; }
10663 let mut wday = ((3 + days) % 7) as i32;
10664 if wday < 0 { wday += 7; }
10665 let mut qc_cycles = (days / DAYS_PER_400Y) as i32;
10666 let mut remdays = (days % DAYS_PER_400Y) as i32;
10667 if remdays < 0 { remdays += DAYS_PER_400Y as i32; qc_cycles -= 1; }
10668 let mut c_cycles = remdays / DAYS_PER_100Y as i32;
10669 if c_cycles == 4 { c_cycles -= 1; }
10670 remdays -= c_cycles * DAYS_PER_100Y as i32;
10671 let mut q_cycles = remdays / DAYS_PER_4Y as i32;
10672 if q_cycles == 25 { q_cycles -= 1; }
10673 remdays -= q_cycles * DAYS_PER_4Y as i32;
10674 let mut remyears = remdays / 365;
10675 if remyears == 4 { remyears -= 1; }
10676 remdays -= remyears * 365;
10677 let leap = remyears == 0 && (q_cycles != 0 || c_cycles == 0);
10678 let mut yday = remdays + 31 + 28 + leap as i32;
10679 if yday >= 365 + leap as i32 { yday -= 365 + leap as i32; }
10680 let years = remyears as i64 + 4 * q_cycles as i64 + 100 * c_cycles as i64 + 400 * qc_cycles as i64;
10681 let mut months = 0i32;
10682 let mut rd = remdays;
10683 for m in 0..12 {
10684 if DAYS_IN_MONTH[m] <= rd { rd -= DAYS_IN_MONTH[m]; } else { months = m as i32; break; }
10685 }
10686 let mut adj_years = years;
10687 if months >= 10 { months -= 12; adj_years += 1; }
10688 if adj_years + 100 > i32::MAX as i64 || adj_years + 100 < i32::MIN as i64 { return false; }
10689 tm.tm_year = (adj_years + 100) as c_int;
10690 tm.tm_mon = months + 2;
10691 tm.tm_mday = rd + 1;
10692 tm.tm_wday = wday;
10693 tm.tm_yday = yday;
10694 tm.tm_hour = remsecs / 3600;
10695 tm.tm_min = remsecs / 60 % 60;
10696 tm.tm_sec = remsecs % 60;
10697 true
10698}
10699
10700unsafe fn tm_to_secs(tm: *const tm) -> i64 {
10701 let mut year = (*tm).tm_year as i64;
10702 let mut month = (*tm).tm_mon;
10703 if month >= 12 || month < 0 {
10704 let adj = month / 12;
10705 month %= 12;
10706 if month < 0 { month += 12; }
10707 year += adj as i64;
10708 }
10709 let mut is_leap = false;
10710 let mut t = year_to_secs(year, &mut is_leap);
10711 t += month_to_secs(month, is_leap) as i64;
10712 t += 86400 * ((*tm).tm_mday - 1) as i64;
10713 t += 3600 * (*tm).tm_hour as i64;
10714 t += 60 * (*tm).tm_min as i64;
10715 t += (*tm).tm_sec as i64;
10716 t
10717}
10718
10719static mut TM_BUF: tm = tm {
10720 tm_sec: 0, tm_min: 0, tm_hour: 0, tm_mday: 0, tm_mon: 0,
10721 tm_year: 0, tm_wday: 0, tm_yday: 0, tm_isdst: 0,
10722 tm_gmtoff: 0, tm_zone: core::ptr::null(),
10723};
10724
10725static mut UTC_STR: [c_char; 4] = [b'U' as c_char, b'T' as c_char, b'C' as c_char, 0];
10726
10727const CLOCK_PROCESS_CPUTIME_ID: c_int = 2;
10728
10729#[no_mangle]
10734pub unsafe extern "C" fn time(t: *mut TimeT) -> TimeT {
10735 let mut ts: timespec = core::mem::zeroed();
10736 let _ = clock_gettime(CLOCK_REALTIME, &mut ts);
10737 if !t.is_null() { *t = ts.tv_sec; }
10738 ts.tv_sec
10739}
10740
10741#[no_mangle]
10742pub unsafe extern "C" fn difftime(t1: TimeT, t0: TimeT) -> f64 {
10743 (t1 as i64 - t0 as i64) as f64
10744}
10745
10746#[no_mangle]
10747pub unsafe extern "C" fn clock() -> ClockT {
10748 let mut ts: timespec = core::mem::zeroed();
10749 let _ = sys_clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &mut ts);
10750 ts.tv_sec * 1000000 + ts.tv_nsec / 1000
10751}
10752
10753#[no_mangle]
10754pub unsafe extern "C" fn gmtime(t: *const TimeT) -> *mut tm {
10755 gmtime_r(t, &raw mut TM_BUF)
10756}
10757
10758#[no_mangle]
10759pub unsafe extern "C" fn gmtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm {
10760 if !secs_to_tm(*t as i64, &mut *tm) { ERRNO!() = EOVERFLOW; return core::ptr::null_mut(); }
10761 (*tm).tm_isdst = 0;
10762 (*tm).tm_gmtoff = 0;
10763 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
10764 tm
10765}
10766
10767#[no_mangle]
10768pub unsafe extern "C" fn localtime(t: *const TimeT) -> *mut tm { gmtime(t) }
10769
10770#[no_mangle]
10771pub unsafe extern "C" fn localtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm { gmtime_r(t, tm) }
10772
10773#[no_mangle]
10774pub unsafe extern "C" fn mktime(tm: *mut tm) -> TimeT {
10775 let t = tm_to_secs(tm as *const tm);
10776 if !secs_to_tm(t, &mut *tm) { ERRNO!() = EOVERFLOW; return -1; }
10777 (*tm).tm_isdst = 0;
10778 (*tm).tm_gmtoff = 0;
10779 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
10780 t as TimeT
10781}
10782
10783#[no_mangle]
10784pub unsafe extern "C" fn timegm(tm: *mut tm) -> TimeT {
10785 let t = tm_to_secs(tm as *const tm);
10786 if !secs_to_tm(t, &mut *tm) { ERRNO!() = EOVERFLOW; return -1; }
10787 (*tm).tm_isdst = 0;
10788 (*tm).tm_gmtoff = 0;
10789 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
10790 t as TimeT
10791}
10792
10793static mut ASCTIME_BUF: [c_char; 26] = [0; 26];
10794
10795const 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"];
10796const 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"];
10797
10798#[no_mangle]
10799pub unsafe extern "C" fn asctime(tm: *const tm) -> *mut c_char {
10800 asctime_r(tm, core::ptr::addr_of_mut!(ASCTIME_BUF).cast::<c_char>())
10801}
10802
10803#[no_mangle]
10804pub unsafe extern "C" fn asctime_r(tm: *const tm, buf: *mut c_char) -> *mut c_char {
10805 let wday = if (*tm).tm_wday >= 0 && (*tm).tm_wday < 7 { (*tm).tm_wday as usize } else { 0 };
10806 let mon = if (*tm).tm_mon >= 0 && (*tm).tm_mon < 12 { (*tm).tm_mon as usize } else { 0 };
10807 let dn = DAY_NAMES[wday];
10808 let mn = MON_NAMES[mon];
10809 let mut p = 0;
10810 for k in 0..3 { *buf.add(p) = *dn.as_ptr().add(k) as c_char; p += 1; }
10811 *buf.add(p) = b' ' as c_char; p += 1;
10812 for k in 0..3 { *buf.add(p) = *mn.as_ptr().add(k) as c_char; p += 1; }
10813 *buf.add(p) = b' ' as c_char; p += 1;
10814 let v = (*tm).tm_mday;
10815 *buf.add(p) = (b'0' + (v / 10) as u8) as c_char; p += 1;
10816 *buf.add(p) = (b'0' + (v % 10) as u8) as c_char; p += 1;
10817 *buf.add(p) = b' ' as c_char; p += 1;
10818 let hh = (*tm).tm_hour;
10819 *buf.add(p) = (b'0' + (hh / 10) as u8) as c_char; p += 1;
10820 *buf.add(p) = (b'0' + (hh % 10) as u8) as c_char; p += 1;
10821 *buf.add(p) = b':' as c_char; p += 1;
10822 let mm = (*tm).tm_min;
10823 *buf.add(p) = (b'0' + (mm / 10) as u8) as c_char; p += 1;
10824 *buf.add(p) = (b'0' + (mm % 10) as u8) as c_char; p += 1;
10825 *buf.add(p) = b':' as c_char; p += 1;
10826 let ss = (*tm).tm_sec;
10827 *buf.add(p) = (b'0' + (ss / 10) as u8) as c_char; p += 1;
10828 *buf.add(p) = (b'0' + (ss % 10) as u8) as c_char; p += 1;
10829 *buf.add(p) = b' ' as c_char; p += 1;
10830 let yr = (*tm).tm_year + 1900;
10831 let mut tmp = [0u8; 4];
10832 let mut v2 = yr;
10833 for k in (0..4).rev() { tmp[k] = b'0' + (v2 % 10) as u8; v2 /= 10; }
10834 for k in 0..4 { *buf.add(p) = tmp[k] as c_char; p += 1; }
10835 *buf.add(p) = b'\n' as c_char; p += 1;
10836 *buf.add(p) = 0;
10837 buf
10838}
10839
10840#[no_mangle]
10841pub unsafe extern "C" fn ctime(t: *const TimeT) -> *mut c_char { asctime(gmtime(t)) }
10842
10843#[no_mangle]
10844pub unsafe extern "C" fn ctime_r(t: *const TimeT, buf: *mut c_char) -> *mut c_char {
10845 let mut tmp: tm = core::mem::zeroed();
10846 gmtime_r(t, &mut tmp);
10847 asctime_r(&tmp, buf)
10848}
10849
10850unsafe fn sys_clock_getres(clockid: c_int, ts: *mut timespec) -> i64 {
10855 <Arch as Syscalls>::syscall2(SYS_CLOCK_GETRES, clockid as i64, ts as i64)
10856}
10857
10858unsafe fn sys_clock_settime(clockid: c_int, ts: *const timespec) -> i64 {
10859 <Arch as Syscalls>::syscall2(SYS_CLOCK_SETTIME, clockid as i64, ts as i64)
10860}
10861
10862unsafe fn sys_clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> i64 {
10863 <Arch as Syscalls>::syscall4(SYS_CLOCK_NANOSLEEP, clockid as i64, flags as i64, req as i64, rem as i64)
10864}
10865
10866#[no_mangle]
10867pub unsafe extern "C" fn clock_getres(clockid: c_int, ts: *mut timespec) -> c_int {
10868 let r = sys_clock_getres(clockid, ts);
10869 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
10870}
10871
10872#[no_mangle]
10873pub unsafe extern "C" fn clock_settime(clockid: c_int, ts: *const timespec) -> c_int {
10874 let r = sys_clock_settime(clockid, ts);
10875 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
10876}
10877
10878#[no_mangle]
10879pub unsafe extern "C" fn clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> c_int {
10880 let r = sys_clock_nanosleep(clockid, flags, req, rem);
10881 if r < 0 {
10882 let e = (-r) as c_int;
10883 if clockid == 3 && e == 95 { return 22; }
10886 e
10887 } else {
10888 0
10889 }
10890}
10891
10892#[no_mangle]
10893pub unsafe extern "C" fn gettimeofday(tv: *mut timeval, _tz: *mut c_void) -> c_int {
10894 if tv.is_null() { return 0; }
10895 let mut ts: timespec = core::mem::zeroed();
10896 let _ = clock_gettime(CLOCK_REALTIME, &mut ts);
10897 (*tv).tv_sec = ts.tv_sec;
10898 (*tv).tv_usec = ts.tv_nsec / 1000;
10899 0
10900}
10901
10902fn is_leap_year(y: i32) -> bool {
10907 let yr = if y > i32::MAX - 1900 { y - 2000 } else { y + 1900 };
10908 yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0)
10909}
10910
10911fn week_num(tm: &tm) -> i32 {
10912 let mut val = (tm.tm_yday + 7 - ((tm.tm_wday + 6) % 7)) / 7;
10913 if (tm.tm_wday + 371 - tm.tm_yday - 2).rem_euclid(7) <= 2 { val += 1; }
10914 if val == 0 {
10915 val = 52;
10916 let dec31 = (tm.tm_wday + 7 - tm.tm_yday - 1).rem_euclid(7);
10917 if dec31 == 4 || (dec31 == 5 && is_leap_year(tm.tm_year % 400 - 1)) { val += 1; }
10918 } else if val == 53 {
10919 let jan1 = (tm.tm_wday + 371 - tm.tm_yday).rem_euclid(7);
10920 if jan1 != 4 && (jan1 != 3 || !is_leap_year(tm.tm_year)) { val = 1; }
10921 }
10922 val
10923}
10924
10925const ABDAY_1: c_int = 0x20000;
10927const DAY_1: c_int = 0x20007;
10928const ABMON_1: c_int = 0x2000E;
10929const MON_1: c_int = 0x2001A;
10930const AM_STR_LI: c_int = 0x20026;
10931const PM_STR_LI: c_int = 0x20027;
10932const D_T_FMT: c_int = 0x20028;
10933const D_FMT: c_int = 0x20029;
10934const T_FMT: c_int = 0x2002A;
10935const T_FMT_AMPM: c_int = 0x2002B;
10936
10937unsafe fn num_fmt(buf: &mut [u8; 100], val: i64, pad: u8, width: usize) -> (*const u8, usize) {
10940 let negative = val < 0;
10941 let mut v = if negative { -val as u64 } else { val as u64 };
10942 let mut tmp = [0u8; 24];
10943 let mut pos = 24usize;
10944 if v == 0 { pos -= 1; tmp[pos] = b'0'; }
10945 while v > 0 { pos -= 1; tmp[pos] = b'0' + (v % 10) as u8; v /= 10; }
10946 let digits = 24 - pos;
10947 let sign_chars = if negative { 1 } else { 0 };
10948 let needed = sign_chars + digits;
10949 let fill = if width > needed { width - needed } else { 0 };
10950 let total = fill + needed;
10951 let mut p = 0usize;
10952 match pad {
10953 b'-' => { }
10954 b'_' => {
10955 for _ in 0..fill { buf[p] = b' '; p += 1; }
10956 if negative { buf[p] = b'-'; p += 1; }
10957 }
10958 _ => {
10959 if negative { buf[p] = b'-'; p += 1; }
10960 for _ in 0..fill { buf[p] = b'0'; p += 1; }
10961 }
10962 }
10963 for i in 0..digits { buf[p] = tmp[pos + i]; p += 1; }
10964 (buf.as_ptr(), total)
10965}
10966
10967unsafe fn str_to_buf(buf: &mut [u8; 100], s: *const c_char) -> (*const u8, usize) {
10969 let mut k = 0usize;
10970 while *s.add(k) != 0 {
10971 buf[k] = *s.add(k) as u8;
10972 k += 1;
10973 }
10974 (buf.as_ptr(), k)
10975}
10976
10977unsafe fn __strftime_fmt_1(buf: &mut [u8; 100], f: u8, tm: *const tm, pad: u8) -> (*const u8, usize) {
10980 let mut val: i64;
10981 let mut width: usize = 2;
10982 let mut def_pad: u8 = b'0';
10983 let fmt: *const c_char;
10984
10985 match f {
10986 b'a' => {
10987 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
10988 let p = nl_langinfo(ABDAY_1 + (*tm).tm_wday);
10989 return str_to_buf(buf, p);
10990 }
10991 b'A' => {
10992 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
10993 let p = nl_langinfo(DAY_1 + (*tm).tm_wday);
10994 return str_to_buf(buf, p);
10995 }
10996 b'h' | b'b' => {
10997 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
10998 let p = nl_langinfo(ABMON_1 + (*tm).tm_mon);
10999 return str_to_buf(buf, p);
11000 }
11001 b'B' => {
11002 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
11003 let p = nl_langinfo(MON_1 + (*tm).tm_mon);
11004 return str_to_buf(buf, p);
11005 }
11006 b'c' => {
11007 let p = nl_langinfo(D_T_FMT);
11008 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11009 return (buf.as_ptr(), l);
11010 }
11011 b'C' => {
11012 val = (1900i64 + (*tm).tm_year as i64) / 100;
11013 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11014 }
11015 b'e' => { def_pad = b'_'; }
11016 b'd' => {
11017 val = (*tm).tm_mday as i64;
11018 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11019 }
11020 b'D' => {
11021 fmt = b"%m/%d/%y\0".as_ptr() as *const c_char;
11022 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11023 return (buf.as_ptr(), l);
11024 }
11025 b'F' => {
11026 fmt = b"%Y-%m-%d\0".as_ptr() as *const c_char;
11027 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11028 return (buf.as_ptr(), l);
11029 }
11030 b'g' | b'G' => {
11031 val = (*tm).tm_year as i64 + 1900;
11032 if (*tm).tm_yday < 3 && week_num(&*tm) != 1 { val -= 1; }
11033 else if (*tm).tm_yday > 360 && week_num(&*tm) == 1 { val += 1; }
11034 if f == b'g' { val %= 100; }
11035 else { width = 4; }
11036 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11037 }
11038 b'H' => {
11039 val = (*tm).tm_hour as i64;
11040 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11041 }
11042 b'I' => {
11043 val = (*tm).tm_hour as i64;
11044 if val == 0 { val = 12; }
11045 else if val > 12 { val -= 12; }
11046 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11047 }
11048 b'j' => {
11049 val = (*tm).tm_yday as i64 + 1;
11050 width = 3;
11051 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11052 }
11053 b'm' => {
11054 val = (*tm).tm_mon as i64 + 1;
11055 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11056 }
11057 b'M' => {
11058 val = (*tm).tm_min as i64;
11059 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11060 }
11061 b'n' => { buf[0] = b'\n'; return (buf.as_ptr(), 1); }
11062 b'p' => {
11063 let p = if (*tm).tm_hour >= 12 { nl_langinfo(PM_STR_LI) } else { nl_langinfo(AM_STR_LI) };
11064 return str_to_buf(buf, p);
11065 }
11066 b'r' => {
11067 let p = nl_langinfo(T_FMT_AMPM);
11068 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11069 return (buf.as_ptr(), l);
11070 }
11071 b'R' => {
11072 fmt = b"%H:%M\0".as_ptr() as *const c_char;
11073 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11074 return (buf.as_ptr(), l);
11075 }
11076 b's' => {
11077 val = tm_to_secs(tm) - (*tm).tm_gmtoff as i64;
11078 width = 1;
11079 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11080 }
11081 b'S' => {
11082 val = (*tm).tm_sec as i64;
11083 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11084 }
11085 b't' => { buf[0] = b'\t'; return (buf.as_ptr(), 1); }
11086 b'T' => {
11087 fmt = b"%H:%M:%S\0".as_ptr() as *const c_char;
11088 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11089 return (buf.as_ptr(), l);
11090 }
11091 b'u' => {
11092 val = if (*tm).tm_wday != 0 { (*tm).tm_wday as i64 } else { 7 };
11093 width = 1;
11094 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11095 }
11096 b'U' => {
11097 val = ((*tm).tm_yday as u64 + 7 - (*tm).tm_wday as u64) as i64 / 7;
11098 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11099 }
11100 b'W' => {
11101 val = ((*tm).tm_yday as u64 + 7 - ((*tm).tm_wday as u64 + 6) % 7) as i64 / 7;
11102 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11103 }
11104 b'V' => {
11105 val = week_num(&*tm) as i64;
11106 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11107 }
11108 b'w' => {
11109 val = (*tm).tm_wday as i64;
11110 width = 1;
11111 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11112 }
11113 b'x' => {
11114 let p = nl_langinfo(D_FMT);
11115 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11116 return (buf.as_ptr(), l);
11117 }
11118 b'X' => {
11119 let p = nl_langinfo(T_FMT);
11120 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11121 return (buf.as_ptr(), l);
11122 }
11123 b'y' => {
11124 val = (1900i64 + (*tm).tm_year as i64) % 100;
11125 if val < 0 { val = -val; }
11126 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11127 }
11128 b'Y' => {
11129 val = (*tm).tm_year as i64 + 1900;
11130 if val >= 10000 {
11131 let mut tmp = [0u8; 100];
11132 let (_, k) = num_fmt(&mut tmp, val, b'-', 1);
11133 buf[0] = b'+';
11134 for i in 0..k { buf[1 + i] = tmp[i]; }
11135 return (buf.as_ptr(), 1 + k);
11136 }
11137 width = 4;
11138 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11139 }
11140 b'z' => {
11141 if (*tm).tm_isdst < 0 { return (b"\0".as_ptr(), 0); }
11142 let gmtoff = (*tm).tm_gmtoff as i64;
11143 let sign = if gmtoff >= 0 { b'+' } else { b'-' };
11144 let off = if gmtoff < 0 { -gmtoff } else { gmtoff };
11145 let hh = (off / 3600) as i32;
11146 let mm = ((off % 3600) / 60) as i32;
11147 buf[0] = sign;
11148 buf[1] = b'0' + (hh / 10) as u8;
11149 buf[2] = b'0' + (hh % 10) as u8;
11150 buf[3] = b'0' + (mm / 10) as u8;
11151 buf[4] = b'0' + (mm % 10) as u8;
11152 return (buf.as_ptr(), 5);
11153 }
11154 b'Z' => {
11155 if (*tm).tm_isdst < 0 || (*tm).tm_zone.is_null() { return (b"\0".as_ptr(), 0); }
11156 return str_to_buf(buf, (*tm).tm_zone);
11157 }
11158 b'%' => { buf[0] = b'%'; return (buf.as_ptr(), 1); }
11159 _ => { return (core::ptr::null(), 0); }
11160 }
11161 val = (*tm).tm_mday as i64;
11163 num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width)
11164}
11165
11166unsafe fn __strftime_l(s: *mut c_char, n: usize, f: *const c_char, tm: *const tm) -> usize {
11167 let mut l: usize = 0;
11168 let mut fi: usize = 0;
11169 while l < n {
11170 let ch = *f.add(fi) as u8;
11171 if ch == 0 {
11172 *s.add(l) = 0;
11173 return l;
11174 }
11175 if ch != b'%' {
11176 *s.add(l) = ch as c_char;
11177 l += 1;
11178 fi += 1;
11179 continue;
11180 }
11181 fi += 1;
11182 let mut pad: u8 = 0;
11184 let fc = *f.add(fi) as u8;
11185 if fc == b'-' || fc == b'_' || fc == b'0' { pad = fc; fi += 1; }
11186 let plus = *f.add(fi) as u8 == b'+';
11187 if plus { fi += 1; }
11188 let mut width: usize = 0;
11190 let mut p_idx = fi;
11191 {
11192 let fc2 = *f.add(fi) as u8;
11193 if fc2 >= b'0' && fc2 <= b'9' {
11194 let mut w: usize = 0;
11195 while { let c = *f.add(p_idx) as u8; c >= b'0' && c <= b'9' } {
11196 w = w * 10 + (*f.add(p_idx) as usize - b'0' as usize);
11197 p_idx += 1;
11198 }
11199 width = w;
11200 }
11201 }
11202 let spec_ch = *f.add(p_idx) as u8;
11203 if spec_ch == b'C' || spec_ch == b'F' || spec_ch == b'G' || spec_ch == b'Y' {
11204 if width == 0 && p_idx != fi { width = 1; }
11205 } else {
11206 width = 0;
11207 }
11208 fi = p_idx;
11209 let fc3 = *f.add(fi) as u8;
11211 if fc3 == b'E' || fc3 == b'O' { fi += 1; }
11212 let fch = *f.add(fi) as u8;
11213 let mut buf = [0u8; 100];
11215 let (t, k) = __strftime_fmt_1(&mut buf, fch, tm, pad);
11216 if t.is_null() { break; }
11217 let mut k = k;
11218 let mut t = t;
11219 if width != 0 {
11220 if *t == b'+' || *t == b'-' { t = t.add(1); k -= 1; }
11222 while k > 0 && *t == b'0' && k > 1 && *t.add(1) >= b'0' && *t.add(1) <= b'9' {
11223 t = t.add(1); k -= 1;
11224 }
11225 if width < k { width = k; }
11226 let mut d: usize = 0;
11227 while d < k && *t.add(d) >= b'0' && *t.add(d) <= b'9' { d += 1; }
11228 if (*tm).tm_year < -1900 {
11229 if l < n { *s.add(l) = b'-' as c_char; }
11230 l += 1;
11231 width -= 1;
11232 } else if plus && d + (width - k) >= (if spec_ch == b'C' { 3 } else { 5 }) {
11233 if l < n { *s.add(l) = b'+' as c_char; }
11234 l += 1;
11235 width -= 1;
11236 }
11237 while width > k && l < n {
11238 *s.add(l) = b'0' as c_char;
11239 l += 1;
11240 width -= 1;
11241 }
11242 }
11243 let copy = if k > n - l { n - l } else { k };
11244 core::ptr::copy_nonoverlapping(t, s.add(l) as *mut u8, copy);
11245 l += copy;
11246 fi += 1;
11247 }
11248 if n > 0 {
11249 if l == n { l = n - 1; }
11250 *s.add(l) = 0;
11251 }
11252 0
11253}
11254
11255#[no_mangle]
11256pub unsafe extern "C" fn strftime(s: *mut c_char, maxsize: usize, fmt: *const c_char, tm: *const tm) -> usize {
11257 __strftime_l(s, maxsize, fmt, tm)
11258}
11259
11260unsafe fn match_prefix(s: *const u8, prefix: &[u8]) -> bool {
11265 for i in 0..prefix.len() {
11266 if *s.add(i) == 0 || *s.add(i) != prefix[i] { return false; }
11267 }
11268 true
11269}
11270
11271unsafe fn match_ci_prefix(s: *const u8, prefix: &[u8]) -> bool {
11272 for i in 0..prefix.len() {
11273 let c = *s.add(i);
11274 if c == 0 { return false; }
11275 if c.to_ascii_lowercase() != prefix[i].to_ascii_lowercase() { return false; }
11276 }
11277 true
11278}
11279
11280unsafe fn parse_int(p: *const u8, max_digits: usize) -> (i32, *const u8) {
11281 let mut val = 0i32;
11282 let mut np = p;
11283 let mut count = 0;
11284 while *np >= b'0' && *np <= b'9' && count < max_digits {
11285 val = val * 10 + (*np - b'0') as i32;
11286 np = np.add(1);
11287 count += 1;
11288 }
11289 if count == 0 { (0, p) } else { (val, np) }
11290}
11291
11292unsafe fn parse_range(p: *const u8, min: i32, max: i32) -> (i32, *const u8) {
11293 let (val, np) = parse_int(p, 4);
11294 if np == p || val < min || val > max { (0, p) } else { (val, np) }
11295}
11296
11297fn is_ascii_space(c: u8) -> bool {
11298 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == 0x0c || c == 0x0b
11299}
11300
11301#[no_mangle]
11302pub unsafe extern "C" fn strptime(s: *const c_char, fmt: *const c_char, tm: *mut tm) -> *mut c_char {
11303 let mut p = s as *const u8;
11304 let mut f = fmt as *const u8;
11305 let mut want_century = 0i32;
11306 let mut century = 0i32;
11307 let mut relyear = 0i32;
11308 while *f != 0 {
11309 if *f != b'%' {
11310 if is_ascii_space(*f) {
11311 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
11312 } else {
11313 if *p != *f { return core::ptr::null_mut(); }
11314 p = p.add(1);
11315 }
11316 f = f.add(1);
11317 continue;
11318 }
11319 f = f.add(1);
11320 if *f == b'+' { f = f.add(1); }
11321 while *f >= b'0' && *f <= b'9' { f = f.add(1); }
11322 if *f == b'E' || *f == b'O' { f = f.add(1); }
11323 match *f {
11324 b'a' | b'A' => {
11325 let mut found = false;
11326 for i in 0..7 {
11327 let names: [&[u8]; 7] = [b"Sunday", b"Monday", b"Tuesday", b"Wednesday", b"Thursday", b"Friday", b"Saturday"];
11328 let snames: [&[u8]; 7] = [b"Sun", b"Mon", b"Tue", b"Wed", b"Thu", b"Fri", b"Sat"];
11329 if match_prefix(p, names[i]) { (*tm).tm_wday = i as c_int; p = p.add(names[i].len()); found = true; break; }
11330 if match_prefix(p, snames[i]) { (*tm).tm_wday = i as c_int; p = p.add(snames[i].len()); found = true; break; }
11331 }
11332 if !found { return core::ptr::null_mut(); }
11333 }
11334 b'b' | b'B' | b'h' => {
11335 let mut found = false;
11336 for i in 0..12 {
11337 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"];
11338 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"];
11339 if match_prefix(p, names[i]) { (*tm).tm_mon = i as c_int; p = p.add(names[i].len()); found = true; break; }
11340 if match_prefix(p, snames[i]) { (*tm).tm_mon = i as c_int; p = p.add(snames[i].len()); found = true; break; }
11341 }
11342 if !found { return core::ptr::null_mut(); }
11343 }
11344 b'C' => {
11345 let (v, np) = parse_int(p, 2);
11346 if np == p { return core::ptr::null_mut(); }
11347 century = v;
11348 want_century |= 2;
11349 p = np;
11350 }
11351 b'd' | b'e' => {
11352 let (v, np) = parse_range(p, 1, 31);
11353 if np == p { return core::ptr::null_mut(); }
11354 (*tm).tm_mday = v;
11355 p = np;
11356 }
11357 b'D' => {
11358 let r = strptime(p as *const c_char, b"%m/%d/%y\0".as_ptr() as *const c_char, tm);
11359 if r.is_null() { return core::ptr::null_mut(); }
11360 p = r as *const u8;
11361 }
11362 b'F' => {
11363 let (yv, ynp) = parse_int(p, 4);
11364 if ynp == p { return core::ptr::null_mut(); }
11365 (*tm).tm_year = yv - 1900;
11366 p = ynp;
11367 if *p != b'-' { return core::ptr::null_mut(); }
11368 p = p.add(1);
11369 let (mv, mnp) = parse_range(p, 1, 12);
11370 if mnp == p { return core::ptr::null_mut(); }
11371 (*tm).tm_mon = mv - 1;
11372 p = mnp;
11373 if *p != b'-' { return core::ptr::null_mut(); }
11374 p = p.add(1);
11375 let (dv, dnp) = parse_range(p, 1, 31);
11376 if dnp == p { return core::ptr::null_mut(); }
11377 (*tm).tm_mday = dv;
11378 p = dnp;
11379 }
11380 b'H' | b'I' => {
11381 let (v, np) = parse_range(p, 0, 23);
11382 if np == p { return core::ptr::null_mut(); }
11383 (*tm).tm_hour = v;
11384 p = np;
11385 }
11386 b'j' => {
11387 let (v, np) = parse_range(p, 1, 366);
11388 if np == p { return core::ptr::null_mut(); }
11389 (*tm).tm_yday = v - 1;
11390 p = np;
11391 }
11392 b'm' => {
11393 let (v, np) = parse_range(p, 1, 12);
11394 if np == p { return core::ptr::null_mut(); }
11395 (*tm).tm_mon = v - 1;
11396 p = np;
11397 }
11398 b'M' => {
11399 let (v, np) = parse_range(p, 0, 59);
11400 if np == p { return core::ptr::null_mut(); }
11401 (*tm).tm_min = v;
11402 p = np;
11403 }
11404 b'n' | b't' => {
11405 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
11406 }
11407 b'p' => {
11408 if match_ci_prefix(p, b"AM") {
11409 if (*tm).tm_hour == 12 { (*tm).tm_hour = 0; }
11410 p = p.add(2);
11411 } else if match_ci_prefix(p, b"PM") {
11412 if (*tm).tm_hour < 12 { (*tm).tm_hour += 12; }
11413 p = p.add(2);
11414 } else { return core::ptr::null_mut(); }
11415 }
11416 b'r' => {
11417 let r = strptime(p as *const c_char, b"%I:%M:%S %p\0".as_ptr() as *const c_char, tm);
11418 if r.is_null() { return core::ptr::null_mut(); }
11419 p = r as *const u8;
11420 }
11421 b'R' => {
11422 let r = strptime(p as *const c_char, b"%H:%M\0".as_ptr() as *const c_char, tm);
11423 if r.is_null() { return core::ptr::null_mut(); }
11424 p = r as *const u8;
11425 }
11426 b's' => {
11427 let neg = if *p == b'-' { p = p.add(1); true } else { false };
11428 if *p < b'0' || *p > b'9' { return core::ptr::null_mut(); }
11429 let mut val = 0i64;
11430 while *p >= b'0' && *p <= b'9' {
11431 val = val * 10 + (*p - b'0') as i64;
11432 p = p.add(1);
11433 }
11434 if neg { val = -val; }
11435 secs_to_tm(val, &mut *tm);
11436 }
11437 b'S' => {
11438 let (v, np) = parse_range(p, 0, 60);
11439 if np == p { return core::ptr::null_mut(); }
11440 (*tm).tm_sec = v;
11441 p = np;
11442 }
11443 b'T' => {
11444 let r = strptime(p as *const c_char, b"%H:%M:%S\0".as_ptr() as *const c_char, tm);
11445 if r.is_null() { return core::ptr::null_mut(); }
11446 p = r as *const u8;
11447 }
11448 b'U' | b'W' => {
11449 let (_, np) = parse_range(p, 0, 53);
11450 if np == p { return core::ptr::null_mut(); }
11451 p = np;
11452 }
11453 b'V' => {
11454 let (_, np) = parse_range(p, 1, 53);
11455 if np == p { return core::ptr::null_mut(); }
11456 p = np;
11457 }
11458 b'w' => {
11459 let (v, np) = parse_range(p, 0, 6);
11460 if np == p { return core::ptr::null_mut(); }
11461 (*tm).tm_wday = v;
11462 p = np;
11463 }
11464 b'y' => {
11465 let (v, np) = parse_int(p, 2);
11466 if np == p { return core::ptr::null_mut(); }
11467 relyear = v;
11468 want_century |= 1;
11469 p = np;
11470 }
11471 b'Y' => {
11472 let neg = if *p == b'-' { p = p.add(1); true } else { false };
11473 let (v, np) = parse_int(p, 4);
11474 if np == p { return core::ptr::null_mut(); }
11475 (*tm).tm_year = if neg { -(v + 1900) } else { v - 1900 };
11476 want_century = 0;
11477 p = np;
11478 }
11479 b'z' => {
11480 if *p != b'+' && *p != b'-' { return core::ptr::null_mut(); }
11481 let neg = *p == b'-';
11482 p = p.add(1);
11483 let mut off = 0i64;
11484 let mut digits = 0;
11485 while digits < 4 && *p >= b'0' && *p <= b'9' {
11486 off = off * 10 + (*p - b'0') as i64;
11487 p = p.add(1);
11488 digits += 1;
11489 }
11490 if digits == 0 { return core::ptr::null_mut(); }
11491 let (hh, mm) = if digits <= 2 { (off, 0i64) } else { (off / 100, off % 100) };
11492 (*tm).tm_gmtoff = (hh * 3600 + mm * 60) * if neg { -1 } else { 1 };
11493 }
11494 b'%' => {
11495 if *p != b'%' { return core::ptr::null_mut(); }
11496 p = p.add(1);
11497 }
11498 _ => { return core::ptr::null_mut(); }
11499 }
11500 f = f.add(1);
11501 }
11502 if want_century != 0 {
11503 (*tm).tm_year = relyear;
11504 if want_century & 2 != 0 { (*tm).tm_year += century * 100 - 1900; }
11505 else if (*tm).tm_year <= 68 { (*tm).tm_year += 100; }
11506 }
11507 p as *mut c_char
11508}
11509
11510#[no_mangle]
11515pub static mut daylight: c_int = 0;
11516#[no_mangle]
11517pub static mut timezone: c_long = 0;
11518#[no_mangle]
11519pub 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];
11520
11521#[no_mangle]
11522pub unsafe extern "C" fn tzset() {
11523 daylight = 0;
11524 timezone = 0;
11525}
11526
11527#[no_mangle]
11532pub unsafe extern "C" fn system(cmd: *const c_char) -> c_int {
11533 if cmd.is_null() {
11534 let pid = sys_fork();
11536 if pid == 0 {
11537 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
11538 let dash_c = b"-c\0".as_ptr() as *const c_char;
11539 let exit0 = b"exit 0\0".as_ptr() as *const c_char;
11540 let argv = [b"sh\0".as_ptr() as *const c_char, dash_c, exit0, core::ptr::null()];
11541 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
11542 _exit(127);
11543 }
11544 if pid < 0 { return -1; }
11545 let mut status: c_int = 0;
11546 loop {
11547 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
11548 if r >= 0 { return status; }
11549 if r != -4 { return -1; } }
11551 }
11552
11553 let sa_ignore = KSigAction {
11554 sa_handler: SIG_IGN,
11555 sa_flags: SA_RESTORER,
11556 sa_restorer: sig_restorer as *const () as usize,
11557 sa_mask: [0],
11558 };
11559 let mut oldint: KSigAction = core::mem::zeroed();
11560 let mut oldquit: KSigAction = core::mem::zeroed();
11561
11562 sys_rt_sigaction(SIGINT, &sa_ignore, &mut oldint, 8);
11563 sys_rt_sigaction(SIGQUIT, &sa_ignore, &mut oldquit, 8);
11564
11565 let mut block_set: SigSetT = 0;
11566 block_set |= 1u64 << (SIGCHLD - 1);
11567 let mut oldmask: SigSetT = 0;
11568 sys_rt_sigprocmask(SIG_BLOCK, &block_set, &mut oldmask, 8);
11569
11570 let pid = sys_fork();
11571
11572 if pid == 0 {
11573 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
11574 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
11575 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
11576
11577 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
11578 let argv = [
11579 b"sh\0".as_ptr() as *const c_char,
11580 b"-c\0".as_ptr() as *const c_char,
11581 cmd,
11582 core::ptr::null(),
11583 ];
11584 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
11585 _exit(127);
11586 }
11587
11588 let mut status: c_int = -1;
11589 if pid > 0 {
11590 loop {
11591 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
11592 if r >= 0 { break; }
11593 if r != -4 { break; } }
11595 }
11596
11597 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
11598 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
11599 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
11600
11601 status
11602}
11603
11604const EPERM_VAL: c_int = 1;
11609const ENOENT_VAL: c_int = 2;
11610const ESRCH_VAL: c_int = 3;
11611const EINTR_VAL: c_int = 4;
11612const EIO_VAL: c_int = 5;
11613const ENXIO_VAL: c_int = 6;
11614const E2BIG_VAL: c_int = 7;
11615const ENOEXEC_VAL: c_int = 8;
11616const EBADF_VAL: c_int = 9;
11617const ECHILD_VAL: c_int = 10;
11618const EAGAIN_VAL: c_int = 11;
11619const ENOMEM_VAL: c_int = 12;
11620const EACCES_VAL: c_int = 13;
11621const EFAULT_VAL: c_int = 14;
11622const ENOTBLK_VAL: c_int = 15;
11623const EBUSY_VAL: c_int = 16;
11624const EEXIST_VAL: c_int = 17;
11625const EXDEV_VAL: c_int = 18;
11626const ENODEV_VAL: c_int = 19;
11627const ENOTDIR_VAL: c_int = 20;
11628const EISDIR_VAL: c_int = 21;
11629const EINVAL_VAL: c_int = 22;
11630const ENFILE_VAL: c_int = 23;
11631const EMFILE_VAL: c_int = 24;
11632const ENOTTY_VAL: c_int = 25;
11633const ETXTBSY_VAL: c_int = 26;
11634const EFBIG_VAL: c_int = 27;
11635const ENOSPC_VAL: c_int = 28;
11636const ESPIPE_VAL: c_int = 29;
11637const EROFS_VAL: c_int = 30;
11638const EMLINK_VAL: c_int = 31;
11639const EPIPE_VAL: c_int = 32;
11640const EDOM_VAL: c_int = 33;
11641const ERANGE_VAL: c_int = 34;
11642const EDEADLK_VAL: c_int = 35;
11643const ENAMETOOLONG_VAL: c_int = 36;
11644const ENOLCK_VAL: c_int = 37;
11645const ENOSYS_VAL: c_int = 38;
11646const ENOTEMPTY_VAL: c_int = 39;
11647const ELOOP_VAL: c_int = 40;
11648const EWOULDBLOCK_VAL: c_int = 11;
11649const ENOMSG_VAL: c_int = 42;
11650const EIDRM_VAL: c_int = 43;
11651const ECHRNG_VAL: c_int = 44;
11652const EL2NSYNC_VAL: c_int = 45;
11653const EL3HLT_VAL: c_int = 46;
11654const EL3RST_VAL: c_int = 47;
11655const ELNRNG_VAL: c_int = 48;
11656const EUNATCH_VAL: c_int = 49;
11657const ENOCSI_VAL: c_int = 50;
11658const EL2HLT_VAL: c_int = 51;
11659const EBADE_VAL: c_int = 52;
11660const EBADR_VAL: c_int = 53;
11661const EXFULL_VAL: c_int = 54;
11662const ENOANO_VAL: c_int = 55;
11663const EBADRQC_VAL: c_int = 56;
11664const EBADSLT_VAL: c_int = 57;
11665const EBFONT_VAL: c_int = 59;
11666const ENOSTR_VAL: c_int = 60;
11667const ENODATA_VAL: c_int = 61;
11668const ETIME_VAL: c_int = 62;
11669const ENOSR_VAL: c_int = 63;
11670const ENONET_VAL: c_int = 64;
11671const ENOPKG_VAL: c_int = 65;
11672const EREMOTE_VAL: c_int = 66;
11673const ENOLINK_VAL: c_int = 67;
11674const EADV_VAL: c_int = 68;
11675const ESRMNT_VAL: c_int = 69;
11676const ECOMM_VAL: c_int = 70;
11677const EPROTO_VAL: c_int = 71;
11678const EMULTIHOP_VAL: c_int = 72;
11679const EDOTDOT_VAL: c_int = 73;
11680const EBADMSG_VAL: c_int = 74;
11681const EOVERFLOW_VAL: c_int = 75;
11682const ENOTUNIQ_VAL: c_int = 76;
11683const EBADFD_VAL: c_int = 77;
11684const EREMCHG_VAL: c_int = 78;
11685const ELIBACC_VAL: c_int = 79;
11686const ELIBBAD_VAL: c_int = 80;
11687const ELIBSCN_VAL: c_int = 81;
11688const ELIBMAX_VAL: c_int = 82;
11689const ELIBEXEC_VAL: c_int = 83;
11690const EILSEQ_VAL: c_int = 84;
11691const ERESTART_VAL: c_int = 85;
11692const ESTRPIPE_VAL: c_int = 86;
11693const EUSERS_VAL: c_int = 87;
11694const ENOTSOCK_VAL: c_int = 88;
11695const EDESTADDRREQ_VAL: c_int = 89;
11696const EMSGSIZE_VAL: c_int = 90;
11697const EPROTOTYPE_VAL: c_int = 91;
11698const ENOPROTOOPT_VAL: c_int = 92;
11699const EPROTONOSUPPORT_VAL: c_int = 93;
11700const ESOCKTNOSUPPORT_VAL: c_int = 94;
11701const EOPNOTSUPP_VAL: c_int = 95;
11702const ENOTSUP_VAL: c_int = 95;
11703const EPFNOSUPPORT_VAL: c_int = 96;
11704const EAFNOSUPPORT_VAL: c_int = 97;
11705const EADDRINUSE_VAL: c_int = 98;
11706const EADDRNOTAVAIL_VAL: c_int = 99;
11707const ENETDOWN_VAL: c_int = 100;
11708const ENETUNREACH_VAL: c_int = 101;
11709const ENETRESET_VAL: c_int = 102;
11710const ECONNABORTED_VAL: c_int = 103;
11711const ECONNRESET_VAL: c_int = 104;
11712const ENOBUFS_VAL: c_int = 105;
11713const EISCONN_VAL: c_int = 106;
11714const ENOTCONN_VAL: c_int = 107;
11715const ESHUTDOWN_VAL: c_int = 108;
11716const ETOOMANYREFS_VAL: c_int = 109;
11717const ETIMEDOUT_VAL: c_int = 110;
11718const ECONNREFUSED_VAL: c_int = 111;
11719const EHOSTDOWN_VAL: c_int = 112;
11720const EHOSTUNREACH_VAL: c_int = 113;
11721const EALREADY_VAL: c_int = 114;
11722const EINPROGRESS_VAL: c_int = 115;
11723const ESTALE_VAL: c_int = 116;
11724const EUCLEAN_VAL: c_int = 117;
11725const ENOTNAM_VAL: c_int = 118;
11726const ENAVAIL_VAL: c_int = 119;
11727const EISNAM_VAL: c_int = 120;
11728const EREMOTEIO_VAL: c_int = 121;
11729const EDQUOT_VAL: c_int = 122;
11730const ENOMEDIUM_VAL: c_int = 123;
11731const EMEDIUMTYPE_VAL: c_int = 124;
11732const ECANCELED_VAL: c_int = 125;
11733const ENOKEY_VAL: c_int = 126;
11734const EKEYEXPIRED_VAL: c_int = 127;
11735const EKEYREVOKED_VAL: c_int = 128;
11736const EKEYREJECTED_VAL: c_int = 129;
11737const EOWNERDEAD_VAL: c_int = 130;
11738const ENOTRECOVERABLE_VAL: c_int = 131;
11739const ERFKILL_VAL: c_int = 132;
11740const EHWPOISON_VAL: c_int = 133;
11741
11742static ERR_STRS: [&[u8]; 134] = [
11744 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", ];
11879
11880#[no_mangle]
11881pub unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char {
11882 if errnum < 0 || errnum as usize >= ERR_STRS.len() {
11883 static mut UNKNOWN_BUF: [c_char; 32] = [0; 32];
11885 let prefix = b"Unknown error \0";
11886 let mut i = 0;
11887 while prefix[i] != 0 {
11888 UNKNOWN_BUF[i] = prefix[i] as c_char;
11889 i += 1;
11890 }
11891 let (buf, len) = format_u64(errnum as u64);
11892 for j in 0..len {
11893 UNKNOWN_BUF[i] = buf[20 - len + j] as c_char;
11894 i += 1;
11895 }
11896 UNKNOWN_BUF[i] = 0;
11897 return core::ptr::addr_of_mut!(UNKNOWN_BUF).cast::<c_char>();
11898 }
11899 ERR_STRS[errnum as usize].as_ptr() as *mut c_char
11900}
11901
11902#[no_mangle]
11903pub unsafe extern "C" fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: usize) -> c_int {
11904 let s = strerror(errnum);
11905 let slen = strlen(s as *const c_char);
11906 if slen >= buflen {
11907 if buflen > 0 {
11908 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, buflen - 1);
11909 *buf.add(buflen - 1) = 0;
11910 }
11911 return 34; }
11913 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, slen + 1);
11914 0
11915}
11916
11917#[no_mangle]
11919pub static mut environ: *mut *mut c_char = core::ptr::null_mut();
11920
11921unsafe fn sync_environ() {
11923 environ = __environ;
11924}
11925
11926#[inline]
11931unsafe fn sys_dup(oldfd: i32) -> i64 {
11932 <Arch as Syscalls>::syscall1(SYS_DUP, oldfd as i64)
11933}
11934
11935#[inline]unsafe fn sys_dup2(oldfd: i32, newfd: i32) -> i64 {
11936 sys_dup3(oldfd, newfd, 0)
11938}
11939
11940#[inline]
11941unsafe fn sys_access(path: *const u8, mode: i32) -> i64 {
11942 <Arch as Syscalls>::syscall4(SYS_FACCESSAT, AT_FDCWD as i64, path as i64, mode as i64, 0)
11943}
11944
11945#[inline]unsafe fn sys_unlink(path: *const u8) -> i64 {
11946 sys_unlinkat(AT_FDCWD, path, 0)
11947}
11948
11949#[inline]unsafe fn sys_rmdir(path: *const u8) -> i64 {
11950 sys_unlinkat(AT_FDCWD, path, 512) }
11952
11953#[inline]
11954unsafe fn sys_chdir(path: *const u8) -> i64 {
11955 <Arch as Syscalls>::syscall1(SYS_CHDIR, path as i64)
11956}
11957
11958#[inline]
11959unsafe fn sys_getcwd(buf: *mut u8, size: usize) -> i64 {
11960 <Arch as Syscalls>::syscall2(SYS_GETCWD, buf as i64, size as i64)
11961}
11962
11963#[inline]
11964unsafe fn sys_sethostname(name: *const u8, len: usize) -> i64 {
11965 <Arch as Syscalls>::syscall2(SYS_SETHOSTNAME, name as i64, len as i64)
11966}
11967
11968#[inline]
11969unsafe fn sys_gethostname(buf: *mut u8, len: usize) -> i64 {
11970 #[repr(C)]
11971 struct UtsName {
11972 sysname: [u8; 65],
11973 nodename: [u8; 65],
11974 release: [u8; 65],
11975 version: [u8; 65],
11976 machine: [u8; 65],
11977 domainname: [u8; 65],
11978 }
11979 let mut uts: UtsName = core::mem::zeroed();
11980 let result = <Arch as Syscalls>::syscall1(SYS_UNAME, &mut uts as *mut UtsName as i64);
11981 if result < 0 {
11982 return result;
11983 }
11984 let nlen = strlen(uts.nodename.as_ptr() as *const c_char);
11985 let copylen = if nlen < len { nlen } else { if len > 0 { len - 1 } else { 0 } };
11986 core::ptr::copy_nonoverlapping(uts.nodename.as_ptr(), buf, copylen);
11987 if len > 0 { *buf.add(copylen) = 0; }
11988 0
11989}
11990
11991unsafe fn sys_truncate(path: *const u8, length: i64) -> i64 {
11992 <Arch as Syscalls>::syscall2(SYS_TRUNCATE, path as i64, length as i64)
11993}
11994
11995unsafe fn sys_ftruncate(fd: i32, length: i64) -> i64 {
11996 <Arch as Syscalls>::syscall2(SYS_FTRUNCATE, fd as i64, length as i64)
11997}
11998
11999unsafe fn sys_nanosleep(req: *const timespec, rem: *mut timespec) -> i64 {
12000 <Arch as Syscalls>::syscall2(SYS_NANOSLEEP, req as i64, rem as i64)
12001}
12002
12003const ITIMER_REAL: i32 = 0;
12004
12005#[repr(C)]
12006struct itimerval {
12007 it_interval: timeval,
12008 it_value: timeval,
12009}
12010
12011unsafe fn sys_alarm(seconds: c_uint) -> i64 {
12012 let mut new: itimerval = core::mem::zeroed();
12013 new.it_value.tv_sec = seconds as c_long;
12014 let mut old: itimerval = core::mem::zeroed();
12015 let r = <Arch as Syscalls>::syscall3(
12016 SYS_SETITIMER,
12017 ITIMER_REAL as i64,
12018 &new as *const _ as i64,
12019 &mut old as *mut _ as i64,
12020 );
12021 if r < 0 {
12022 return r;
12023 }
12024 old.it_value.tv_sec as i64 + (old.it_value.tv_usec != 0) as i64
12025}
12026
12027unsafe fn sys_pause() -> i64 {
12028 #[cfg(target_arch = "x86_64")]
12029 { <Arch as Syscalls>::syscall0(SYS_PAUSE) }
12030 #[cfg(target_arch = "aarch64")]
12031 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12032 #[cfg(target_arch = "riscv64")]
12033 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12034}
12035
12036unsafe fn sys_fsync(fd: i32) -> i64 {
12037 <Arch as Syscalls>::syscall1(SYS_FSYNC, fd as i64)
12038}
12039
12040unsafe fn sys_fdatasync(fd: i32) -> i64 {
12041 <Arch as Syscalls>::syscall1(SYS_FDATASYNC, fd as i64)
12042}
12043
12044unsafe fn sys_sync() {
12045 let _ = <Arch as Syscalls>::syscall0(SYS_SYNC);
12046}
12047
12048unsafe fn sys_symlink(target: *const u8, linkpath: *const u8) -> i64 {
12049 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, AT_FDCWD as i64, linkpath as i64)
12050}
12051
12052unsafe fn sys_symlinkat(target: *const u8, newdirfd: i32, linkpath: *const u8) -> i64 {
12053 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, newdirfd as i64, linkpath as i64)
12054}
12055
12056unsafe fn sys_readlinkat(dirfd: i32, path: *const u8, buf: *mut u8, bufsiz: usize) -> i64 {
12057 <Arch as Syscalls>::syscall4(SYS_READLINKAT, dirfd as i64, path as i64, buf as i64, bufsiz as i64)
12058}
12059
12060unsafe fn sys_linkat(olddirfd: i32, oldpath: *const u8, newdirfd: i32, newpath: *const u8, flags: i32) -> i64 {
12061 <Arch as Syscalls>::syscall5(SYS_LINKAT, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)
12062}
12063
12064unsafe fn sys_fchmod(fd: i32, mode: u32) -> i64 {
12065 <Arch as Syscalls>::syscall2(SYS_FCHMOD, fd as i64, mode as i64)
12066}
12067
12068unsafe fn sys_fchmodat(dirfd: i32, path: *const u8, mode: u32, flags: i32) -> i64 {
12069 <Arch as Syscalls>::syscall4(SYS_FCHMODAT, dirfd as i64, path as i64, mode as i64, flags as i64)
12070}
12071
12072unsafe fn sys_umask(mask: u32) -> u32 {
12073 <Arch as Syscalls>::syscall1(SYS_UMASK, mask as i64) as u32
12074}
12075
12076unsafe fn sys_getgroups(size: i32, list: *mut c_uint) -> i64 {
12077 <Arch as Syscalls>::syscall2(SYS_GETGROUPS, size as i64, list as i64)
12078}
12079
12080unsafe fn sys_setuid(uid: c_uint) -> i64 {
12081 <Arch as Syscalls>::syscall1(SYS_SETUID, uid as i64)
12082}
12083
12084unsafe fn sys_setgid(gid: c_uint) -> i64 {
12085 <Arch as Syscalls>::syscall1(SYS_SETGID, gid as i64)
12086}
12087
12088unsafe fn sys_setsid() -> i64 {
12089 <Arch as Syscalls>::syscall0(SYS_SETSID)
12090}
12091
12092unsafe fn sys_setpgid(pid: c_int, pgid: c_int) -> i64 {
12093 <Arch as Syscalls>::syscall2(SYS_SETPGID, pid as i64, pgid as i64)
12094}
12095
12096unsafe fn sys_getpgid(pid: c_int) -> i64 {
12097 <Arch as Syscalls>::syscall1(SYS_GETPGID, pid as i64)
12098}
12099
12100unsafe fn sys_getsid(pid: c_int) -> i64 {
12101 <Arch as Syscalls>::syscall1(SYS_GETSID, pid as i64)
12102}
12103
12104unsafe fn sys_mkdirat(dirfd: i32, path: *const u8, mode: u32) -> i64 {
12105 <Arch as Syscalls>::syscall3(SYS_MKDIRAT, dirfd as i64, path as i64, mode as i64)
12106}
12107
12108#[no_mangle]
12111pub unsafe extern "C" fn pipe(fds: *mut c_int) -> c_int {
12112 let r = sys_pipe2(fds, 0);
12113 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12114 0
12115}
12116
12117#[no_mangle]
12118pub unsafe extern "C" fn pipe2(fds: *mut c_int, flags: c_int) -> c_int {
12119 let r = sys_pipe2(fds, flags);
12120 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12121 0
12122}
12123
12124#[no_mangle]
12125pub unsafe extern "C" fn dup(oldfd: c_int) -> c_int {
12126 let r = sys_dup(oldfd);
12127 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12128 r as c_int
12129}
12130
12131#[no_mangle]
12132pub unsafe extern "C" fn dup2(oldfd: c_int, newfd: c_int) -> c_int {
12133 if oldfd == newfd {
12134 let r = sys_fcntl(oldfd, 1 , 0);
12137 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12138 return newfd;
12139 }
12140 let r = sys_dup2(oldfd, newfd);
12141 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12142 r as c_int
12143}
12144
12145#[no_mangle]
12146pub unsafe extern "C" fn dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int {
12147 let r = sys_dup3(oldfd, newfd, flags);
12148 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12149 r as c_int
12150}
12151
12152#[no_mangle]
12153pub unsafe extern "C" fn fcntl(fd: c_int, cmd: c_int, mut args: ...) -> c_int {
12154 let no_arg = matches!(cmd, 1 | 3 | 9 | 11 | 1025 | 1032 | 1034 );
12159 let r = if no_arg {
12160 sys_fcntl(fd, cmd, 0)
12161 } else {
12162 let arg = args.next_arg::<c_long>();
12163 sys_fcntl(fd, cmd, arg)
12164 };
12165 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12166 r as c_int
12167}
12168
12169#[no_mangle]
12170pub unsafe extern "C" fn access(path: *const c_char, mode: c_int) -> c_int {
12171 let r = sys_access(path as *const u8, mode);
12172 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12173 0
12174}
12175
12176#[no_mangle]
12177pub unsafe extern "C" fn unlink(path: *const c_char) -> c_int {
12178 let r = sys_unlink(path as *const u8);
12179 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12180 0
12181}
12182
12183#[no_mangle]
12184pub unsafe extern "C" fn rmdir(path: *const c_char) -> c_int {
12185 let r = sys_rmdir(path as *const u8);
12186 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12187 0
12188}
12189
12190#[no_mangle]
12191pub unsafe extern "C" fn chdir(path: *const c_char) -> c_int {
12192 let r = sys_chdir(path as *const u8);
12193 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12194 0
12195}
12196
12197#[no_mangle]
12198pub unsafe extern "C" fn getcwd(buf: *mut c_char, size: usize) -> *mut c_char {
12199 if buf.is_null() {
12200 let alloc_size = if size == 0 { 256 } else { size };
12202 let p = malloc(alloc_size) as *mut c_char;
12203 if p.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
12204 let r = sys_getcwd(p as *mut u8, alloc_size);
12205 if r < 0 { free(p as *mut c_void); ERRNO!() = (-r) as c_int; return core::ptr::null_mut(); }
12206 if *p as u8 != b'/' {
12209 free(p as *mut c_void);
12210 ERRNO!() = 2;
12211 return core::ptr::null_mut();
12212 }
12213 return p;
12214 }
12215 if size == 0 { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
12216 let r = sys_getcwd(buf as *mut u8, size);
12217 if r < 0 { ERRNO!() = (-r) as c_int; return core::ptr::null_mut(); }
12218 if *buf as u8 != b'/' {
12219 ERRNO!() = 2;
12220 return core::ptr::null_mut();
12221 }
12222 buf
12223}
12224
12225#[no_mangle]
12226pub unsafe extern "C" fn gethostname(name: *mut c_char, len: usize) -> c_int {
12227 let r = sys_gethostname(name as *mut u8, len);
12228 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12229 0
12230}
12231
12232#[no_mangle]
12234pub extern "C" fn getpagesize() -> c_int {
12235 4096
12236}
12237
12238#[no_mangle]
12239pub unsafe extern "C" fn truncate(path: *const c_char, length: i64) -> c_int {
12240 let r = sys_truncate(path as *const u8, length);
12241 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12242 0
12243}
12244
12245#[no_mangle]
12246pub unsafe extern "C" fn ftruncate(fd: c_int, length: i64) -> c_int {
12247 let r = sys_ftruncate(fd, length);
12248 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12249 0
12250}
12251
12252#[no_mangle]
12253pub unsafe extern "C" fn nanosleep(req: *const timespec, rem: *mut timespec) -> c_int {
12254 pthread_testcancel();
12255 let r = sys_nanosleep(req, rem);
12256 pthread_testcancel();
12257 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12258 0
12259}
12260
12261#[no_mangle]
12262pub unsafe extern "C" fn sleep(seconds: c_uint) -> c_uint {
12263 let req = timespec { tv_sec: seconds as c_long, tv_nsec: 0 };
12264 let mut rem: timespec = core::mem::zeroed();
12265 pthread_testcancel();
12266 let r = sys_nanosleep(&req, &mut rem);
12267 pthread_testcancel();
12268 if r < 0 {
12269 let e = (-r) as c_int;
12270 if e == EINTR { return rem.tv_sec as c_uint; }
12271 }
12272 0
12273}
12274
12275#[no_mangle]
12276pub unsafe extern "C" fn usleep(usec: c_uint) -> c_int {
12277 let req = timespec { tv_sec: (usec / 1000000) as c_long, tv_nsec: ((usec % 1000000) * 1000) as c_long };
12278 pthread_testcancel();
12279 let r = sys_nanosleep(&req, core::ptr::null_mut());
12280 pthread_testcancel();
12281 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12282 0
12283}
12284
12285#[no_mangle]
12286pub unsafe extern "C" fn alarm(seconds: c_uint) -> c_uint {
12287 let r = sys_alarm(seconds);
12290 if r < 0 { 0 } else { r as c_uint }
12291}
12292
12293#[no_mangle]
12294pub unsafe extern "C" fn pause() -> c_int {
12295 pthread_testcancel();
12296 sys_pause();
12297 pthread_testcancel();
12298 ERRNO!() = EINTR;
12299 -1
12300}
12301
12302#[no_mangle]
12303pub unsafe extern "C" fn fsync(fd: c_int) -> c_int {
12304 let r = sys_fsync(fd);
12305 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12306 0
12307}
12308
12309#[no_mangle]
12310pub unsafe extern "C" fn fdatasync(fd: c_int) -> c_int {
12311 let r = sys_fdatasync(fd);
12312 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12313 0
12314}
12315
12316#[no_mangle]
12317pub unsafe extern "C" fn sync() {
12318 sys_sync();
12319}
12320
12321#[no_mangle]
12322pub unsafe extern "C" fn symlink(target: *const c_char, linkpath: *const c_char) -> c_int {
12323 let r = sys_symlinkat(target as *const u8, AT_FDCWD, linkpath as *const u8);
12324 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12325 0
12326}
12327
12328#[no_mangle]
12329pub unsafe extern "C" fn readlink(path: *const c_char, buf: *mut c_char, bufsiz: usize) -> isize {
12330 let r = sys_readlinkat(AT_FDCWD, path as *const u8, buf as *mut u8, bufsiz);
12331 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12332 r as isize
12333}
12334
12335#[no_mangle]
12336pub unsafe extern "C" fn link(oldpath: *const c_char, newpath: *const c_char) -> c_int {
12337 let r = sys_linkat(AT_FDCWD, oldpath as *const u8, AT_FDCWD, newpath as *const u8, 0);
12338 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12339 0
12340}
12341
12342#[no_mangle]
12343pub unsafe extern "C" fn chmod(path: *const c_char, mode: c_uint) -> c_int {
12344 let r = sys_fchmodat(AT_FDCWD, path as *const u8, mode, 0);
12345 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12346 0
12347}
12348
12349#[no_mangle]
12350pub unsafe extern "C" fn fchmod(fd: c_int, mode: c_uint) -> c_int {
12351 let r = sys_fchmod(fd, mode);
12352 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12353 0
12354}
12355
12356#[no_mangle]
12357pub unsafe extern "C" fn umask(mask: c_uint) -> c_uint {
12358 sys_umask(mask) as c_uint
12359}
12360
12361#[no_mangle]
12362pub unsafe extern "C" fn isatty(fd: c_int) -> c_int {
12363 let mut ws: winsize = core::mem::zeroed();
12364 if sys_ioctl(fd, TIOCGWINSZ, &mut ws as *mut winsize as *mut u8) == 0 { 1 } else { 0 }
12365}
12366
12367#[no_mangle]
12368pub unsafe extern "C" fn getlogin() -> *mut c_char {
12369 crate::getenv(b"LOGNAME\0".as_ptr() as *const c_char)
12370}
12371
12372#[no_mangle]
12373pub unsafe extern "C" fn getgroups(size: c_int, list: *mut c_uint) -> c_int {
12374 let r = sys_getgroups(size, list);
12375 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12376 r as c_int
12377}
12378
12379#[no_mangle]
12380pub unsafe extern "C" fn setuid(uid: c_uint) -> c_int {
12381 let r = sys_setuid(uid);
12382 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12383 0
12384}
12385
12386#[no_mangle]
12387pub unsafe extern "C" fn setgid(gid: c_uint) -> c_int {
12388 let r = sys_setgid(gid);
12389 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12390 0
12391}
12392
12393#[no_mangle]
12394pub unsafe extern "C" fn seteuid(euid: c_uint) -> c_int {
12395 setresuid(u32::MAX, euid, u32::MAX)
12399}
12400
12401#[no_mangle]
12402pub unsafe extern "C" fn setegid(egid: c_uint) -> c_int {
12403 setresgid(u32::MAX, egid, u32::MAX)
12404}
12405
12406#[no_mangle]
12407pub unsafe extern "C" fn setreuid(ruid: c_uint, euid: c_uint) -> c_int {
12408 let r = <Arch as Syscalls>::syscall2(sysno(113, 145), ruid as i64, euid as i64);
12409 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
12410}
12411
12412
12413
12414#[no_mangle]
12415pub unsafe extern "C" fn setsid() -> c_int {
12416 let r = sys_setsid();
12417 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12418 r as c_int
12419}
12420
12421#[no_mangle]
12422pub unsafe extern "C" fn setpgid(pid: c_int, pgid: c_int) -> c_int {
12423 let r = sys_setpgid(pid, pgid);
12424 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12425 0
12426}
12427
12428#[no_mangle]
12429pub unsafe extern "C" fn getpgid(pid: c_int) -> c_int {
12430 let r = sys_getpgid(pid);
12431 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12432 r as c_int
12433}
12434
12435#[no_mangle]
12436pub unsafe extern "C" fn getsid(pid: c_int) -> c_int {
12437 let r = sys_getsid(pid);
12438 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12439 r as c_int
12440}
12441
12442#[no_mangle]
12443pub unsafe extern "C" fn getpgrp() -> c_int {
12444 sys_getpgid(0) as c_int
12445}
12446
12447#[no_mangle]
12448pub unsafe extern "C" fn setpgrp() -> c_int {
12449 setpgid(0, 0)
12450}
12451
12452#[no_mangle]
12453unsafe fn mkstemps_impl(template: *mut c_char, suffixlen: i32) -> c_int {
12454 if template.is_null() || suffixlen < 0 {
12455 ERRNO!() = EINVAL;
12456 return -1;
12457 }
12458 let len = strlen(template as *const c_char);
12459 let suffix = suffixlen as usize;
12460 if len < 6 + suffix {
12461 ERRNO!() = EINVAL;
12462 return -1;
12463 }
12464 let x_start = len - suffix - 6;
12465 for i in x_start..x_start + 6 {
12466 if *template.add(i) != b'X' as c_char {
12467 ERRNO!() = EINVAL;
12468 return -1;
12469 }
12470 }
12471 let mut ts: timespec = core::mem::zeroed();
12472 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
12473 let mut ctr: u32 = ts.tv_nsec as u32;
12474 for _ in 0..100 {
12475 ctr = ctr.wrapping_mul(1103515245).wrapping_add(12345);
12476 let mut seed = ctr;
12477 let hex = b"0123456789abcdef";
12478 for i in x_start..x_start + 6 {
12479 *template.add(i) = hex[(seed & 0xf) as usize] as c_char;
12480 seed >>= 4;
12481 }
12482 let fd = sys_open(template as *const u8, (O_RDWR | O_CREAT | O_EXCL) as i64, 0o600);
12483 if fd >= 0 {
12484 return fd as c_int;
12485 }
12486 let e = (-fd) as c_int;
12487 if e != EEXIST_VAL {
12488 ERRNO!() = e;
12489 return -1;
12490 }
12491 }
12492 ERRNO!() = EEXIST_VAL;
12493 -1
12494}
12495
12496#[no_mangle]
12497pub unsafe extern "C" fn mkstemp(template: *mut c_char) -> c_int {
12498 mkstemps_impl(template, 0)
12499}
12500
12501#[no_mangle]
12502pub unsafe extern "C" fn mkdir(path: *const c_char, mode: c_uint) -> c_int {
12503 let r = sys_mkdirat(AT_FDCWD, path as *const u8, mode);
12504 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12505 0
12506}
12507
12508#[no_mangle]
12513pub unsafe extern "C" fn dirname(s: *mut c_char) -> *mut c_char {
12514 if s.is_null() || *s == 0 {
12515 return b".\0".as_ptr() as *mut c_char;
12516 }
12517 let mut i = strlen(s as *const c_char);
12518 i = i.wrapping_sub(1);
12519 while i > 0 && *s.add(i) == b'/' as c_char {
12521 i = i.wrapping_sub(1);
12522 }
12523 if i == 0 && *s.add(0) == b'/' as c_char {
12524 return b"/\0".as_ptr() as *mut c_char;
12525 }
12526 while i > 0 && *s.add(i) != b'/' as c_char {
12528 i = i.wrapping_sub(1);
12529 }
12530 if i == 0 {
12531 if *s.add(0) == b'/' as c_char {
12532 return b"/\0".as_ptr() as *mut c_char;
12533 }
12534 return b".\0".as_ptr() as *mut c_char;
12535 }
12536 while i > 0 && *s.add(i - 1) == b'/' as c_char {
12538 i = i.wrapping_sub(1);
12539 }
12540 if i == 0 {
12541 return b"/\0".as_ptr() as *mut c_char;
12542 }
12543 *s.add(i) = 0;
12544 s
12545}
12546
12547#[no_mangle]
12548pub unsafe extern "C" fn basename(s: *mut c_char) -> *mut c_char {
12549 if s.is_null() || *s == 0 {
12550 return b".\0".as_ptr() as *mut c_char;
12551 }
12552 let mut i = strlen(s as *const c_char);
12553 i = i.wrapping_sub(1);
12554 while i > 0 && *s.add(i) == b'/' as c_char {
12556 *s.add(i) = 0;
12557 i = i.wrapping_sub(1);
12558 }
12559 while i > 0 && *s.add(i - 1) != b'/' as c_char {
12561 i = i.wrapping_sub(1);
12562 }
12563 s.add(i)
12564}
12565
12566const AF_INET_VAL: c_int = 2;
12571const AF_INET6_VAL: c_int = 10;
12572const EAFNOSUPPORT: c_int = 97;
12573const ENOSPC_VAL2: c_int = 28;
12574
12575unsafe fn inet_pton_v4(s: *const u8, a: *mut u8) -> c_int {
12576 let mut p = s;
12577 let mut i = 0;
12578 while i < 4 {
12579 let oct_start = p;
12580 let mut v: u32 = 0;
12581 let mut j: u32 = 0;
12582 while j < 3 && *p >= b'0' && *p <= b'9' {
12583 v = v * 10 + (*p - b'0') as u32;
12584 p = p.add(1);
12585 j += 1;
12586 }
12587 if j == 0 || (j > 1 && *oct_start == b'0') || v > 255 { return 0; }
12588 *a.add(i) = v as u8;
12589 if *p == 0 && i == 3 { return 1; }
12590 if *p != b'.' { return 0; }
12591 p = p.add(1);
12592 i += 1;
12593 }
12594 0
12595}
12596
12597unsafe fn inet_pton_v6(s: *const u8, a: *mut u8) -> c_int {
12598 let mut ip = [0u16; 8];
12599 let mut p = s;
12600 let mut i: usize = 0;
12601 let mut brk: isize = -1;
12602 let mut need_v4 = false;
12603 let mut v4_start: *const u8 = core::ptr::null();
12604
12605 if *p == b':' {
12606 p = p.add(1);
12607 if *p != b':' { return 0; }
12608 }
12609
12610 loop {
12611 if *p == b':' && brk < 0 {
12612 brk = i as isize;
12613 ip[i & 7] = 0;
12614 p = p.add(1);
12615 if *p == 0 { break; }
12616 if i == 7 { return 0; }
12617 i += 1;
12618 continue;
12619 }
12620 v4_start = p;
12621 let mut v: u16 = 0;
12622 let mut j = 0;
12623 while j < 4 {
12624 let d = hex_digit(*p);
12625 if d < 0 { break; }
12626 v = v * 16 + d as u16;
12627 p = p.add(1);
12628 j += 1;
12629 }
12630 if j == 0 { return 0; }
12631 ip[i & 7] = v;
12632 if *p == 0 && (brk >= 0 || i == 7) { break; }
12633 if i == 7 { return 0; }
12634 if *p != b':' {
12635 if *p != b'.' || (i < 6 && brk < 0) { return 0; }
12636 need_v4 = true;
12637 i += 1;
12638 ip[i & 7] = 0;
12639 break;
12640 }
12641 p = p.add(1);
12642 i += 1;
12643 }
12644
12645 if brk >= 0 {
12646 let trail_count = i + 1 - brk as usize;
12648 let dest_start = brk as usize + 7 - i;
12649 for j in (0..trail_count).rev() {
12651 ip[dest_start + j] = ip[brk as usize + j];
12652 }
12653 for j in 0..(7 - i) {
12654 ip[brk as usize + j] = 0;
12655 }
12656 }
12657
12658 for k in 0..8 {
12659 *a.add(k * 2) = (ip[k] >> 8) as u8;
12660 *a.add(k * 2 + 1) = (ip[k] & 0xff) as u8;
12661 }
12662
12663 if need_v4 {
12664 if inet_pton_v4(v4_start, a.add(12)) <= 0 { return 0; }
12665 }
12666 1
12667}
12668
12669unsafe fn hex_digit(c: u8) -> i32 {
12670 if c >= b'0' && c <= b'9' { (c - b'0') as i32 }
12671 else if c >= b'a' && c <= b'f' { (c - b'a' + 10) as i32 }
12672 else if c >= b'A' && c <= b'F' { (c - b'A' + 10) as i32 }
12673 else { -1 }
12674}
12675
12676#[no_mangle]
12677pub unsafe extern "C" fn inet_pton(af: c_int, s: *const c_char, a: *mut c_void) -> c_int {
12678 if af == AF_INET_VAL {
12679 inet_pton_v4(s as *const u8, a as *mut u8)
12680 } else if af == AF_INET6_VAL {
12681 inet_pton_v6(s as *const u8, a as *mut u8)
12682 } else {
12683 ERRNO!() = EAFNOSUPPORT;
12684 -1
12685 }
12686}
12687
12688#[no_mangle]
12689pub unsafe extern "C" fn inet_ntop(af: c_int, a: *const c_void, s: *mut c_char, size: u32) -> *mut c_char {
12690 if af == AF_INET_VAL {
12691 let b = a as *const u8;
12692 let needed = 16; if size < needed as u32 { ERRNO!() = ENOSPC_VAL2; return core::ptr::null_mut(); }
12694 let mut pos = 0;
12695 for i in 0..4 {
12696 if i > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
12697 let (buf, len) = format_u64(*b.add(i) as u64);
12698 for j in 0..len { *s.add(pos) = buf[j] as c_char; pos += 1; }
12699 }
12700 *s.add(pos) = 0;
12701 s
12702 } else if af == AF_INET6_VAL {
12703 let b = a as *const u8;
12704 let needed = 46; if size < needed as u32 { ERRNO!() = ENOSPC_VAL2; return core::ptr::null_mut(); }
12706 let mut words = [0u16; 8];
12707 for i in 0..8 {
12708 words[i] = ((*b.add(i * 2) as u16) << 8) | (*b.add(i * 2 + 1) as u16);
12709 }
12710 let mut pos = 0usize;
12712 if words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0
12713 && words[4] == 0 && words[5] == 0xffff
12714 {
12715 let prefix = b"::ffff:";
12716 for k in 0..prefix.len() { *s.add(pos) = prefix[k] as c_char; pos += 1; }
12717 for idx in 0..4 {
12718 if idx > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
12719 let octet = *b.add(12 + idx);
12720 if octet >= 100 {
12721 *s.add(pos) = (b'0' + octet / 100) as c_char; pos += 1;
12722 *s.add(pos) = (b'0' + (octet / 10) % 10) as c_char; pos += 1;
12723 } else if octet >= 10 {
12724 *s.add(pos) = (b'0' + octet / 10) as c_char; pos += 1;
12725 }
12726 *s.add(pos) = (b'0' + octet % 10) as c_char; pos += 1;
12727 }
12728 *s.add(pos) = 0;
12729 return s;
12730 }
12731 let mut best_start: isize = -1;
12733 let mut best_len: usize = 0;
12734 let mut j: usize = 0;
12735 while j < 8 {
12736 if words[j] == 0 {
12737 let mut k = j;
12738 while k < 8 && words[k] == 0 { k += 1; }
12739 let run = k - j;
12740 if run > best_len { best_start = j as isize; best_len = run; }
12741 j = k;
12742 } else {
12743 j += 1;
12744 }
12745 }
12746 let mut i: usize = 0;
12747 let mut prev_in_run = false;
12748 while i < 8 {
12749 let in_run = best_len >= 2 && i >= best_start as usize && i < best_start as usize + best_len;
12750 if in_run {
12751 if i == best_start as usize {
12752 *s.add(pos) = b':' as c_char; pos += 1;
12753 *s.add(pos) = b':' as c_char; pos += 1;
12754 }
12755 i += 1;
12756 prev_in_run = true;
12757 continue;
12758 }
12759 if i > 0 && !prev_in_run {
12760 *s.add(pos) = b':' as c_char; pos += 1;
12761 }
12762 let (buf, len) = format_hex(words[i] as u64, false);
12763 for k in 0..len { *s.add(pos) = buf[k] as c_char; pos += 1; }
12764 i += 1;
12765 prev_in_run = false;
12766 }
12767 *s.add(pos) = 0;
12768 s
12769 } else {
12770 ERRNO!() = EAFNOSUPPORT;
12771 core::ptr::null_mut()
12772 }
12773}
12774
12775#[no_mangle]
12776pub unsafe extern "C" fn inet_aton(s: *const c_char, dest: *mut c_void) -> c_int {
12777 let a = dest as *mut u8;
12778 let mut p = s as *const u8;
12779 let mut vals = [0u64; 4];
12780 let mut i = 0usize;
12781 while i < 4 {
12782 if *p < b'0' || *p > b'9' { return 0; }
12783 let mut base = 10u32;
12784 if *p == b'0' {
12785 let c = *p.add(1);
12786 if c == b'x' || c == b'X' {
12787 base = 16;
12788 p = p.add(2);
12789 if !((*p >= b'0' && *p <= b'9')
12790 || (*p >= b'a' && *p <= b'f')
12791 || (*p >= b'A' && *p <= b'F')) {
12792 return 0;
12793 }
12794 } else {
12795 base = 8;
12796 }
12797 }
12798 let mut v: u64 = 0;
12799 let start = p;
12800 loop {
12801 let c = *p;
12802 let d = if c >= b'0' && c <= b'9' {
12803 (c - b'0') as u64
12804 } else if base == 16 && c >= b'a' && c <= b'f' {
12805 (c - b'a' + 10) as u64
12806 } else if base == 16 && c >= b'A' && c <= b'F' {
12807 (c - b'A' + 10) as u64
12808 } else {
12809 break;
12810 };
12811 v = v * (base as u64) + d;
12812 p = p.add(1);
12813 }
12814 if p == start { return 0; }
12815 vals[i] = v;
12816 if *p == 0 {
12817 break;
12818 }
12819 if *p != b'.' || i == 3 { return 0; }
12820 p = p.add(1);
12821 i += 1;
12822 }
12823 if i == 4 { return 0; }
12824 if i < 1 { vals[1] = vals[0] & 0xffffff; vals[0] >>= 24; }
12825 if i < 2 { vals[2] = vals[1] & 0xffff; vals[1] >>= 16; }
12826 if i < 3 { vals[3] = vals[2] & 0xff; vals[2] >>= 8; }
12827 for j in 0..4 {
12828 if vals[j] > 255 { return 0; }
12829 *a.add(j) = vals[j] as u8;
12830 }
12831 1
12832}
12833
12834#[no_mangle]
12835pub unsafe extern "C" fn inet_addr(s: *const c_char) -> u32 {
12836 let mut a = [0u8; 4];
12837 if inet_aton(s, a.as_mut_ptr() as *mut c_void) == 1 {
12838 u32::from_ne_bytes(a)
12839 } else {
12840 !0u32 }
12842}
12843
12844#[no_mangle]
12845pub unsafe extern "C" fn inet_ntoa(addr: u32) -> *mut c_char {
12846 static mut NTOA_BUF: [c_char; 16] = [0; 16];
12847 let b = addr.to_ne_bytes();
12848 let mut pos = 0;
12849 for i in 0..4 {
12850 if i > 0 { NTOA_BUF[pos] = b'.' as c_char; pos += 1; }
12851 let (buf, len) = format_u64(b[i] as u64);
12852 for j in 0..len { NTOA_BUF[pos] = buf[j] as c_char; pos += 1; }
12853 }
12854 NTOA_BUF[pos] = 0;
12855 core::ptr::addr_of_mut!(NTOA_BUF).cast::<c_char>()
12856}
12857
12858#[no_mangle]
12860pub unsafe extern "C" fn inet_network(s: *const c_char) -> u32 {
12861 inet_addr(s).to_be()
12862}
12863
12864#[no_mangle]
12865pub extern "C" fn inet_makeaddr(net: c_int, host: c_int) -> u32 {
12866 let addr: u32;
12867 if (net as u32) < 128 {
12868 addr = (net as u32) << 24;
12869 } else if (net as u32) < 0x10000 {
12870 addr = (net as u32) << 16;
12871 } else if (net as u32) < 0x1000000 {
12872 addr = (net as u32) << 8;
12873 } else {
12874 addr = net as u32;
12875 }
12876 addr | (host as u32 & 0xffffffff)
12877}
12878
12879#[no_mangle]
12880pub extern "C" fn inet_lnaof(addr: u32) -> c_int {
12881 let h = u32::from_be(addr);
12882 if h < 0x80000000 { (h & 0x00ffffff) as c_int }
12883 else if h < 0xc0000000 { (h & 0x0000ffff) as c_int }
12884 else { (h & 0x000000ff) as c_int }
12885}
12886
12887#[no_mangle]
12888pub extern "C" fn inet_netof(addr: u32) -> c_int {
12889 let h = u32::from_be(addr);
12890 if h < 0x80000000 { (h >> 24) as c_int }
12891 else if h < 0xc0000000 { (h >> 16) as c_int }
12892 else { (h >> 8) as c_int }
12893}
12894
12895unsafe fn parse_float(s: *const u8, endptr: *mut *mut u8, is_f32: bool) -> f64 {
12904 let mut p = s;
12905 while *p == b' ' || *p == b'\t' || *p == b'\n' || *p == b'\r' { p = p.add(1); }
12907 let mut neg = false;
12908 if *p == b'-' { neg = true; p = p.add(1); }
12909 else if *p == b'+' { p = p.add(1); }
12910
12911 if (*p | 0x20) == b'i'
12913 && (*p.add(1) | 0x20) == b'n'
12914 && (*p.add(2) | 0x20) == b'f'
12915 {
12916 p = p.add(3);
12917 if (*p | 0x20) == b'i'
12919 && (*p.add(1) | 0x20) == b't'
12920 && (*p.add(2) | 0x20) == b'y'
12921 {
12922 p = p.add(3);
12923 }
12924 if !endptr.is_null() { *endptr = p as *mut u8; }
12925 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
12926 }
12927 if (*p | 0x20) == b'n'
12929 && (*p.add(1) | 0x20) == b'a'
12930 && (*p.add(2) | 0x20) == b'n'
12931 {
12932 p = p.add(3);
12933 if *p == b'(' {
12935 p = p.add(1);
12936 while *p != 0 && *p != b')' { p = p.add(1); }
12937 if *p == b')' { p = p.add(1); }
12938 }
12939 if !endptr.is_null() { *endptr = p as *mut u8; }
12940 return if neg { -f64::NAN } else { f64::NAN };
12941 }
12942
12943 if *p == b'0' && (*p.add(1) == b'x' || *p.add(1) == b'X') {
12945 p = p.add(2);
12946 let mut mant: u128 = 0;
12947 let mut frac_hex: u32 = 0;
12948 let mut found = false;
12949 let mut in_frac = false;
12950
12951 loop {
12952 if let Some(d) = hex_val(*p) {
12953 if mant <= u128::MAX / 16 {
12954 mant = mant * 16 + d as u128;
12955 }
12956 if in_frac { frac_hex += 1; }
12957 p = p.add(1);
12958 found = true;
12959 } else if *p == b'.' && !in_frac {
12960 in_frac = true;
12961 p = p.add(1);
12962 } else {
12963 break;
12964 }
12965 }
12966
12967 if !found {
12968 if !endptr.is_null() { *endptr = s as *mut u8; }
12969 return 0.0;
12970 }
12971
12972 let mut bin_exp: i32 = 0;
12974 if *p == b'p' || *p == b'P' {
12975 p = p.add(1);
12976 let mut exp_neg = false;
12977 if *p == b'-' { exp_neg = true; p = p.add(1); }
12978 else if *p == b'+' { p = p.add(1); }
12979 while *p >= b'0' && *p <= b'9' {
12980 if bin_exp < 100000 {
12981 bin_exp = bin_exp * 10 + (*p - b'0') as i32;
12982 }
12983 p = p.add(1);
12984 }
12985 if exp_neg { bin_exp = -bin_exp; }
12986 }
12987
12988 if !endptr.is_null() { *endptr = p as *mut u8; }
12989 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
12990
12991 let total_exp = bin_exp as i64 - 4 * frac_hex as i64;
12992 return hex_mant_to_f64(mant, total_exp, neg);
12993 }
12994
12995 let mut buf = [0u8; 65536];
12997 let mut n = 0usize;
12998 let mut found_digit = false;
12999
13000 while *p >= b'0' && *p <= b'9' {
13001 if n < 65535 { buf[n] = *p; n += 1; }
13002 p = p.add(1);
13003 found_digit = true;
13004 }
13005 if *p == b'.' {
13006 if n < 65535 { buf[n] = b'.'; n += 1; }
13007 p = p.add(1);
13008 while *p >= b'0' && *p <= b'9' {
13009 if n < 65535 { buf[n] = *p; n += 1; }
13010 p = p.add(1);
13011 found_digit = true;
13012 }
13013 }
13014 if !found_digit {
13015 if !endptr.is_null() { *endptr = s as *mut u8; }
13016 return 0.0;
13017 }
13018 if *p == b'e' || *p == b'E' {
13019 if n < 65535 { buf[n] = b'e'; n += 1; }
13020 p = p.add(1);
13021 if *p == b'-' || *p == b'+' {
13022 if n < 65535 { buf[n] = *p; n += 1; }
13023 p = p.add(1);
13024 }
13025 while *p >= b'0' && *p <= b'9' {
13026 if n < 65535 { buf[n] = *p; n += 1; }
13027 p = p.add(1);
13028 }
13029 }
13030
13031 if !endptr.is_null() { *endptr = p as *mut u8; }
13032 let s_str = core::str::from_utf8_unchecked(
13033 core::slice::from_raw_parts(buf.as_ptr(), n),
13034 );
13035 if is_f32 {
13036 match <f32 as core::str::FromStr>::from_str(s_str) {
13037 Ok(v) => { let r = v as f64; if neg { -r } else { r } }
13038 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13039 }
13040 } else {
13041 match <f64 as core::str::FromStr>::from_str(s_str) {
13042 Ok(v) => if neg { -v } else { v },
13043 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13044 }
13045 }
13046}
13047
13048fn hex_mant_to_f64(mant: u128, total_exp: i64, neg: bool) -> f64 {
13052 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
13053
13054 let msb = (127 - mant.leading_zeros()) as i64;
13055 let unbiased_exp = msb + total_exp;
13056 let biased_exp = unbiased_exp + 1023;
13057
13058 if biased_exp >= 2047 {
13060 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13061 }
13062
13063 if biased_exp <= 0 {
13065 let shift = total_exp + 1074;
13068 if shift < 0 {
13069 return if neg { -0.0 } else { 0.0 };
13070 }
13071 if shift > 128 {
13072 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13073 }
13074 let shifted = mant << (shift as u32);
13075 let mantissa52 = (shifted as u64) & 0x000FFFFFFFFFFFFF;
13076 let guard = ((shifted >> 52) & 1) != 0;
13077 let sticky = (shifted >> 53) != 0;
13078 let mut result = mantissa52;
13079 if guard && (sticky || (result & 1) != 0) {
13080 result += 1;
13081 if result > 0x000FFFFFFFFFFFFF {
13082 return if neg { -f64::from_bits(1u64 << 52) } else { f64::from_bits(1u64 << 52) };
13084 }
13085 }
13086 return if neg { -f64::from_bits(result) } else { f64::from_bits(result) };
13087 }
13088
13089 let shift = msb - 52;
13091
13092 if shift <= 0 {
13093 let mantissa = ((mant as u64) & ((1u64 << msb as u32) - 1)) << ((-shift) as u32);
13095 let bits = ((biased_exp as u64) << 52) | mantissa;
13096 return if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) };
13097 }
13098
13099 let mantissa = ((mant >> shift as u32) as u64) & 0x000FFFFFFFFFFFFF;
13101 let guard = ((mant >> (shift as u32 - 1)) & 1) != 0;
13102 let sticky = if shift > 1 {
13103 (mant & ((1u128 << (shift as u32 - 1)) - 1)) != 0
13104 } else { false };
13105
13106 let mut result_mant = mantissa;
13107 let mut result_exp = biased_exp;
13108 if guard && (sticky || (result_mant & 1) != 0) {
13109 result_mant += 1;
13110 if result_mant > 0x000FFFFFFFFFFFFF {
13111 result_mant = 0;
13112 result_exp += 1;
13113 if result_exp >= 2047 {
13114 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13115 }
13116 }
13117 }
13118
13119 let bits = ((result_exp as u64) << 52) | result_mant;
13120 if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) }
13121}
13122
13123unsafe fn hex_val(c: u8) -> Option<u8> {
13124 if c >= b'0' && c <= b'9' { Some(c - b'0') }
13125 else if c >= b'a' && c <= b'f' { Some(c - b'a' + 10) }
13126 else if c >= b'A' && c <= b'F' { Some(c - b'A' + 10) }
13127 else { None }
13128}
13129
13130#[no_mangle]
13131pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13132 let mut end: *mut u8 = s as *mut u8;
13133 let r = parse_float(s as *const u8, &mut end, false);
13134 if !endptr.is_null() { *endptr = end as *mut c_char; }
13135 r
13136}
13137
13138#[no_mangle]
13139pub unsafe extern "C" fn strtof(s: *const c_char, endptr: *mut *mut c_char) -> f32 {
13140 let mut end: *mut u8 = s as *mut u8;
13141 let r = parse_float(s as *const u8, &mut end, true);
13142 if !endptr.is_null() { *endptr = end as *mut c_char; }
13143 r as f32
13144}
13145
13146#[no_mangle]
13147#[cfg(target_arch = "x86_64")]
13148pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13149 strtod(s, endptr)
13150}
13151
13152#[no_mangle]
13153#[cfg(target_arch = "aarch64")]
13154pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13155 strtod(s, endptr) as f128
13156}
13157
13158#[no_mangle]
13159#[cfg(target_arch = "riscv64")]
13160pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13161 strtod(s, endptr) as f128
13162}
13163
13164#[no_mangle]
13165pub unsafe extern "C" fn atof(s: *const c_char) -> f64 {
13166 strtod(s, core::ptr::null_mut())
13167}
13168
13169#[repr(C)]
13174struct MsCookie {
13175 bufp: *mut *mut c_char,
13176 sizep: *mut usize,
13177 pos: usize,
13178 len: usize,
13179 buf: *mut u8,
13180 space: usize,
13181}
13182
13183#[repr(C)]
13184struct MfCookie {
13185 pos: usize,
13186 len: usize,
13187 size: usize,
13188 buf: *mut u8,
13189 mode: c_char,
13190}
13191
13192unsafe extern "C" fn ms_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13193 let c = (*f).cookie as *mut MsCookie;
13194 if whence < 0 || whence > 2 { ERRNO!() = EINVAL; return -1; }
13195 let base: i64 = match whence {
13196 0 => 0,
13197 1 => (*c).pos as i64,
13198 2 => (*c).len as i64,
13199 _ => { ERRNO!() = EINVAL; return -1; }
13200 };
13201 if off < -base || off > isize::MAX as i64 - base { ERRNO!() = EINVAL; return -1; }
13202 (*c).pos = (base + off) as usize;
13203 (*c).pos as i64
13204}
13205
13206unsafe extern "C" fn ms_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13207 let c = (*f).cookie as *mut MsCookie;
13208 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13209 if buffered > 0 {
13210 (*f).wpos = (*f).wbase;
13211 if ms_write(f, (*f).wbase, buffered) < buffered { return 0; }
13212 }
13213 if len == 0 { return 0; }
13214 if (*c).pos + len >= (*c).space {
13215 let new_space = 2 * (*c).space + 1 | (*c).pos + len + 1;
13216 let newbuf = realloc((*c).buf as *mut c_void, new_space) as *mut u8;
13217 if newbuf.is_null() { return 0; }
13218 *(*c).bufp = newbuf as *mut c_char;
13219 core::ptr::write_bytes(newbuf.add((*c).space), 0, new_space - (*c).space);
13220 (*c).buf = newbuf;
13221 (*c).space = new_space;
13222 }
13223 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), len);
13224 (*c).pos += len;
13225 if (*c).pos >= (*c).len { (*c).len = (*c).pos; }
13226 *(*c).sizep = (*c).pos;
13227 len
13228}
13229
13230unsafe extern "C" fn ms_close(_f: *mut FILE) -> c_int {
13231 0
13232}
13233
13234#[no_mangle]
13235pub unsafe extern "C" fn open_memstream(bufp: *mut *mut c_char, sizep: *mut usize) -> *mut FILE {
13236 if bufp.is_null() || sizep.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
13237 let f = calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
13238 if f.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13239 let buf_area = buf_ptr(f);
13240 init_file(f, -1, b"w\0".as_ptr() as *const c_char, Some(ms_close), buf_area, BUFSIZ);
13241 (*f).flags = F_NORD | F_SVB;
13242 (*f).lbf = -1;
13243 let c = calloc(1, core::mem::size_of::<MsCookie>()) as *mut MsCookie;
13244 if c.is_null() { free(f as *mut c_void); ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13245 (*c).bufp = bufp;
13246 (*c).sizep = sizep;
13247 (*c).pos = 0;
13248 (*c).len = 0;
13249 (*c).buf = core::ptr::null_mut();
13250 (*c).space = 0;
13251 (*f).cookie = c as *mut c_void;
13252 (*f).write_fn = Some(ms_write);
13253 (*f).seek_fn = Some(ms_seek);
13254 *bufp = core::ptr::null_mut();
13255 *sizep = 0;
13256 f
13257}
13258
13259unsafe extern "C" fn mseek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13260 let c = (*f).cookie as *mut MfCookie;
13261 if whence < 0 || whence > 2 { ERRNO!() = EINVAL; return -1; }
13262 let base: i64 = match whence {
13263 0 => 0,
13264 1 => (*c).pos as i64,
13265 2 => (*c).len as i64,
13266 _ => { ERRNO!() = EINVAL; return -1; }
13267 };
13268 if off < -base || off > (*c).size as i64 - base { ERRNO!() = EINVAL; return -1; }
13269 (*c).pos = (base + off) as usize;
13270 (*c).pos as i64
13271}
13272
13273unsafe extern "C" fn mread(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
13274 let c = (*f).cookie as *mut MfCookie;
13275 let mut rem = if (*c).pos <= (*c).len { (*c).len - (*c).pos } else { 0 };
13276 let mut l = len;
13277 if l > rem {
13278 l = rem;
13279 (*f).flags |= F_EOF;
13280 }
13281 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), buf, l);
13282 (*c).pos += l;
13283 rem -= l;
13284 if rem > (*f).buf_size { rem = (*f).buf_size; }
13285 (*f).rpos = (*f).buf;
13286 (*f).rend = (*f).buf.add(rem);
13287 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), (*f).rpos, rem);
13288 (*c).pos += rem;
13289 l
13290}
13291
13292unsafe extern "C" fn mwrite(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13293 let c = (*f).cookie as *mut MfCookie;
13294 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13295 if buffered > 0 {
13296 (*f).wpos = (*f).wbase;
13297 if mwrite(f, (*f).wbase, buffered) < buffered { return 0; }
13298 }
13299 if len == 0 { return 0; }
13300 if (*c).mode == b'a' as c_char { (*c).pos = (*c).len; }
13301 let rem = (*c).size - (*c).pos;
13302 let mut l = len;
13303 if l > rem { l = rem; }
13304 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), l);
13305 (*c).pos += l;
13306 if (*c).pos > (*c).len {
13307 (*c).len = (*c).pos;
13308 if (*c).len < (*c).size {
13309 *(*c).buf.add((*c).len) = 0;
13310 } else if ((*f).flags & F_NORD) != 0 && (*c).size > 0 {
13311 *(*c).buf.add((*c).size - 1) = 0;
13312 }
13313 }
13314 l
13315}
13316
13317unsafe extern "C" fn mclose(_f: *mut FILE) -> c_int {
13318 0
13319}
13320
13321#[no_mangle]
13322pub unsafe extern "C" fn fmemopen(buf: *mut c_void, size: usize, mode: *const c_char) -> *mut FILE {
13323 if mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
13324 let m = *mode;
13325 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
13326 ERRNO!() = EINVAL; return core::ptr::null_mut();
13327 }
13328 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
13329 let need_alloc = buf.is_null();
13330 let alloc_size = core::mem::size_of::<FILE>() + UNGET + BUFSIZ + if need_alloc { size } else { 0 };
13331 let f = calloc(1, alloc_size) as *mut FILE;
13332 if f.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13333 let buf_area = buf_ptr(f);
13334 init_file(f, -1, mode, Some(mclose), buf_area, BUFSIZ);
13335 (*f).flags |= F_SVB;
13336 let actual_buf: *mut u8 = if need_alloc {
13337 (f as *mut u8).add(alloc_size - size)
13338 } else {
13339 buf as *mut u8
13340 };
13341 if need_alloc { core::ptr::write_bytes(actual_buf, 0, size); }
13342 let c = calloc(1, core::mem::size_of::<MfCookie>()) as *mut MfCookie;
13343 if c.is_null() { free(f as *mut c_void); ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13344 (*c).buf = actual_buf;
13345 (*c).size = size;
13346 (*c).mode = m;
13347 (*f).cookie = c as *mut c_void;
13348 (*f).read_fn = Some(mread);
13349 (*f).write_fn = Some(mwrite);
13350 (*f).seek_fn = Some(mseek);
13351 if !has_plus { (*f).flags = if m == b'r' as c_char { F_NOWR } else { F_NORD }; }
13352 if m == b'r' as c_char {
13353 (*c).len = size;
13354 } else if m == b'a' as c_char {
13355 (*c).len = strnlen(actual_buf, size);
13356 (*c).pos = (*c).len;
13357 } else if has_plus {
13358 *actual_buf = 0;
13359 }
13360 f
13361}
13362
13363#[repr(C)]
13368struct kernel_stat64 {
13369 st_dev: u64,
13370 st_ino: u64,
13371 st_nlink: u64,
13372 st_mode: u32,
13373 st_uid: u32,
13374 st_gid: u32,
13375 __pad0: c_int,
13376 st_rdev: u64,
13377 st_size: i64,
13378 st_blksize: i64,
13379 st_blocks: i64,
13380 st_atime: i64,
13381 st_atime_nsec: i64,
13382 st_mtime: i64,
13383 st_mtime_nsec: i64,
13384 st_ctime: i64,
13385 st_ctime_nsec: i64,
13386 __unused: [i64; 3],
13387}
13388
13389#[inline]
13391unsafe fn sys_stat(path: *const u8, statbuf: *mut kernel_stat64) -> i64 {
13392 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, AT_FDCWD as i64, path as i64, statbuf as i64, 0)
13393}
13394
13395const HSEARCH_MINSIZE: usize = 8;
13400
13401#[repr(C)]
13402#[derive(Copy, Clone)]
13403pub struct HSearchEntry {
13404 key: *mut c_char,
13405 data: *mut c_void,
13406}
13407
13408#[repr(C)]
13409struct HTab {
13410 entries: *mut HSearchEntry,
13411 mask: usize,
13412 used: usize,
13413}
13414
13415#[repr(C)]
13416pub struct HSearchData {
13417 tab: *mut HTab,
13418 __unused1: c_uint,
13419 __unused2: c_uint,
13420}
13421
13422static mut HTAB_DATA: HSearchData = HSearchData {
13424 tab: core::ptr::null_mut(),
13425 __unused1: 0,
13426 __unused2: 0,
13427};
13428
13429unsafe fn keyhash(k: *const c_char) -> usize {
13430 let mut h: usize = 0;
13431 let mut p = k;
13432 while *p != 0 {
13433 h = h.wrapping_mul(31).wrapping_add(*p as usize);
13434 p = p.add(1);
13435 }
13436 h
13437}
13438
13439unsafe fn htab_lookup(key: *const c_char, hash: usize, htab: *mut HSearchData) -> *mut HSearchEntry {
13440 let tab = (*htab).tab;
13441 let mask = (*tab).mask;
13442 let entries = (*tab).entries;
13443 let mut i = hash;
13444 let mut j: usize = 1;
13445 loop {
13446 let e = entries.add(i & mask);
13447 if (*e).key.is_null() || strcmp((*e).key as *const u8, key as *const u8) == 0 {
13448 return e;
13449 }
13450 i = i.wrapping_add(j);
13451 j += 1;
13452 }
13453}
13454
13455unsafe fn htab_resize(nel: usize, htab: *mut HSearchData) -> c_int {
13456 let tab = (*htab).tab;
13457 let old_entries = (*tab).entries;
13458 let old_size = (*tab).mask + 1;
13459
13460 let mut newsize: usize = HSEARCH_MINSIZE;
13461 while newsize < nel {
13462 let Some(next) = newsize.checked_mul(2) else {
13463 ERRNO!() = ENOMEM;
13464 return 0;
13465 };
13466 newsize = next;
13467 }
13468
13469 let new_entries = calloc(newsize, core::mem::size_of::<HSearchEntry>()) as *mut HSearchEntry;
13470 if new_entries.is_null() {
13471 ERRNO!() = ENOMEM;
13472 return 0;
13473 }
13474 (*tab).entries = new_entries;
13475 (*tab).mask = newsize - 1;
13476
13477 if !old_entries.is_null() {
13478 for idx in 0..old_size {
13479 let old_e = old_entries.add(idx);
13480 if !(*old_e).key.is_null() {
13481 let h = keyhash((*old_e).key);
13482 let mut i = h;
13483 let mut j: usize = 1;
13484 loop {
13485 let e = new_entries.add(i & (*tab).mask);
13486 if (*e).key.is_null() {
13487 *e = *old_e;
13488 break;
13489 }
13490 i = i.wrapping_add(j);
13491 j += 1;
13492 }
13493 }
13494 }
13495 free(old_entries as *mut c_void);
13496 }
13497 1
13498}
13499
13500unsafe fn hcreate_r_impl(nel: usize, htab: *mut HSearchData) -> c_int {
13501 if nel == 0 || nel > (1usize << 30) {
13502 ERRNO!() = ENOMEM;
13503 return 0;
13504 }
13505 (*htab).tab = calloc(1, core::mem::size_of::<HTab>()) as *mut HTab;
13506 if (*htab).tab.is_null() {
13507 ERRNO!() = ENOMEM;
13508 return 0;
13509 }
13510 if htab_resize(nel, htab) == 0 {
13511 free((*htab).tab as *mut c_void);
13512 (*htab).tab = core::ptr::null_mut();
13513 return 0;
13514 }
13515 1
13516}
13517
13518unsafe fn hdestroy_r_impl(htab: *mut HSearchData) {
13519 if !(*htab).tab.is_null() {
13520 if !(*(*htab).tab).entries.is_null() {
13521 free((*(*htab).tab).entries as *mut c_void);
13522 }
13523 free((*htab).tab as *mut c_void);
13524 (*htab).tab = core::ptr::null_mut();
13525 }
13526}
13527
13528unsafe fn hsearch_r_impl(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
13529 let hash = keyhash(item.key);
13530 let e = htab_lookup(item.key, hash, htab);
13531
13532 if !(*e).key.is_null() {
13533 *retval = e;
13534 return 1;
13535 }
13536 if action == 0 { *retval = core::ptr::null_mut();
13538 return 0;
13539 }
13540 let item_key = item.key;
13542 *e = item;
13543 (*(*htab).tab).used += 1;
13544 if (*(*htab).tab).used > (*(*htab).tab).mask - (*(*htab).tab).mask / 4 {
13545 if htab_resize(2 * (*(*htab).tab).used, htab) == 0 {
13546 (*(*htab).tab).used -= 1;
13547 (*e).key = core::ptr::null_mut();
13548 *retval = core::ptr::null_mut();
13549 return 0;
13550 }
13551 let e2 = htab_lookup(item_key, hash, htab);
13552 *retval = e2;
13553 return 1;
13554 }
13555 *retval = e;
13556 1
13557}
13558
13559#[no_mangle]
13560pub unsafe extern "C" fn hcreate(nel: usize) -> c_int {
13561 hcreate_r_impl(nel, core::ptr::addr_of_mut!(HTAB_DATA))
13562}
13563
13564#[no_mangle]
13565pub unsafe extern "C" fn hdestroy() {
13566 hdestroy_r_impl(core::ptr::addr_of_mut!(HTAB_DATA));
13567}
13568
13569#[no_mangle]
13570pub unsafe extern "C" fn hsearch(item: HSearchEntry, action: c_int) -> *mut HSearchEntry {
13571 let mut e: *mut HSearchEntry = core::ptr::null_mut();
13572 hsearch_r_impl(item, action, &mut e, core::ptr::addr_of_mut!(HTAB_DATA));
13573 e
13574}
13575
13576#[no_mangle]
13577pub unsafe extern "C" fn hcreate_r(nel: usize, htab: *mut HSearchData) -> c_int {
13578 hcreate_r_impl(nel, htab)
13579}
13580
13581#[no_mangle]
13582pub unsafe extern "C" fn hdestroy_r(htab: *mut HSearchData) {
13583 hdestroy_r_impl(htab);
13584}
13585
13586#[no_mangle]
13587pub unsafe extern "C" fn hsearch_r(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
13588 hsearch_r_impl(item, action, retval, htab)
13589}
13590
13591#[repr(C)]
13596struct QueNode {
13597 next: *mut QueNode,
13598 prev: *mut QueNode,
13599}
13600
13601#[no_mangle]
13602pub unsafe extern "C" fn insque(element: *mut c_void, pred: *mut c_void) {
13603 let e = element as *mut QueNode;
13604 let p = pred as *mut QueNode;
13605 if p.is_null() {
13606 (*e).next = core::ptr::null_mut();
13607 (*e).prev = core::ptr::null_mut();
13608 return;
13609 }
13610 (*e).next = (*p).next;
13611 (*e).prev = p;
13612 (*p).next = e;
13613 if !(*e).next.is_null() {
13614 (*(*e).next).prev = e;
13615 }
13616}
13617
13618#[no_mangle]
13619pub unsafe extern "C" fn remque(element: *mut c_void) {
13620 let e = element as *mut QueNode;
13621 if !(*e).next.is_null() {
13622 (*(*e).next).prev = (*e).prev;
13623 }
13624 if !(*e).prev.is_null() {
13625 (*(*e).prev).next = (*e).next;
13626 }
13627}
13628
13629#[no_mangle]
13634pub unsafe extern "C" fn lsearch(
13635 key: *const c_void,
13636 base: *mut c_void,
13637 nelp: *mut usize,
13638 width: usize,
13639 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
13640) -> *mut c_void {
13641 let n = *nelp;
13642 let p = base as *mut u8;
13643 for i in 0..n {
13644 let elem = p.add(i * width);
13645 if compar.unwrap()(key, elem as *const c_void) == 0 {
13646 return elem as *mut c_void;
13647 }
13648 }
13649 let dest = p.add(n * width);
13650 memcpy(dest as *mut c_void, key as *const c_void, width);
13651 *nelp = n + 1;
13652 dest as *mut c_void
13653}
13654
13655#[no_mangle]
13656pub unsafe extern "C" fn lfind(
13657 key: *const c_void,
13658 base: *const c_void,
13659 nelp: *mut usize,
13660 width: usize,
13661 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
13662) -> *mut c_void {
13663 let n = *nelp;
13664 let p = base as *const u8;
13665 for i in 0..n {
13666 let elem = p.add(i * width);
13667 if compar.unwrap()(key, elem as *const c_void) == 0 {
13668 return elem as *mut c_void;
13669 }
13670 }
13671 core::ptr::null_mut()
13672}
13673
13674#[repr(C)]
13680pub struct TreeNode {
13681 key: *const c_void,
13682 left: *mut TreeNode,
13683 right: *mut TreeNode,
13684}
13685
13686type ComparFn = Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>;
13687
13688unsafe fn bst_new(key: *const c_void) -> *mut TreeNode {
13689 let n = calloc(1, core::mem::size_of::<TreeNode>()) as *mut TreeNode;
13690 if !n.is_null() {
13691 (*n).key = key;
13692 (*n).left = core::ptr::null_mut();
13693 (*n).right = core::ptr::null_mut();
13694 }
13695 n
13696}
13697
13698#[no_mangle]
13699pub unsafe extern "C" fn tsearch(
13700 key: *const c_void,
13701 rootp: *mut *mut TreeNode,
13702 compar: ComparFn,
13703) -> *mut c_void {
13704 if rootp.is_null() {
13705 return core::ptr::null_mut();
13706 }
13707 let mut pp = rootp;
13708 loop {
13709 let n = *pp;
13710 if n.is_null() {
13711 let r = bst_new(key);
13712 if r.is_null() {
13713 return core::ptr::null_mut();
13714 }
13715 *pp = r;
13716 return r as *mut c_void;
13717 }
13718 let c = compar.unwrap()(key, (*n).key);
13719 if c == 0 {
13720 return n as *mut c_void;
13721 }
13722 if c < 0 {
13723 pp = &mut (*n).left;
13724 } else {
13725 pp = &mut (*n).right;
13726 }
13727 }
13728}
13729
13730#[no_mangle]
13731pub unsafe extern "C" fn tfind(
13732 key: *const c_void,
13733 rootp: *const *mut TreeNode,
13734 compar: ComparFn,
13735) -> *mut c_void {
13736 if rootp.is_null() {
13737 return core::ptr::null_mut();
13738 }
13739 let mut n = *rootp;
13740 loop {
13741 if n.is_null() {
13742 return core::ptr::null_mut();
13743 }
13744 let c = compar.unwrap()(key, (*n).key);
13745 if c == 0 {
13746 return n as *mut c_void;
13747 }
13748 if c < 0 {
13749 n = (*n).left;
13750 } else {
13751 n = (*n).right;
13752 }
13753 }
13754}
13755
13756#[no_mangle]
13757pub unsafe extern "C" fn tdelete(
13758 key: *const c_void,
13759 rootp: *mut *mut TreeNode,
13760 compar: ComparFn,
13761) -> *mut c_void {
13762 if rootp.is_null() {
13763 return core::ptr::null_mut();
13764 }
13765 let mut pp = rootp;
13766 loop {
13767 let n = *pp;
13768 if n.is_null() {
13769 return core::ptr::null_mut();
13770 }
13771 let c = compar.unwrap()(key, (*n).key);
13772 if c == 0 {
13773 break;
13774 }
13775 if c < 0 {
13776 pp = &mut (*n).left;
13777 } else {
13778 pp = &mut (*n).right;
13779 }
13780 }
13781 let n = *pp;
13782 let parent = *rootp;
13784 if !(*n).left.is_null() {
13785 let mut q = &mut (*n).left;
13787 while !(*(*q)).right.is_null() {
13788 q = &mut (*(*q)).right;
13789 }
13790 let pred = *q;
13791 (*n).key = (*pred).key;
13793 *q = (*pred).left;
13795 free(pred as *mut c_void);
13796 } else {
13797 *pp = (*n).right;
13799 free(n as *mut c_void);
13800 }
13801 parent as *mut c_void
13802}
13803
13804#[no_mangle]
13805pub unsafe extern "C" fn twalk(
13806 root: *const TreeNode,
13807 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
13808) {
13809 unsafe fn walk(
13810 node: *const TreeNode,
13811 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
13812 depth: c_int,
13813 ) {
13814 if node.is_null() {
13815 return;
13816 }
13817 let is_leaf = (*node).left.is_null() && (*node).right.is_null();
13818 if is_leaf {
13819 action.unwrap()(node as *const c_void, 3, depth); } else {
13821 action.unwrap()(node as *const c_void, 0, depth); walk((*node).left, action, depth + 1);
13823 action.unwrap()(node as *const c_void, 1, depth); walk((*node).right, action, depth + 1);
13825 action.unwrap()(node as *const c_void, 2, depth); }
13827 }
13828 walk(root, action, 0);
13829}
13830
13831#[no_mangle]
13832pub unsafe extern "C" fn tdestroy(root: *mut TreeNode, freekey: Option<unsafe extern "C" fn(*mut c_void)>) {
13833 if root.is_null() {
13834 return;
13835 }
13836 tdestroy((*root).left, freekey);
13837 tdestroy((*root).right, freekey);
13838 if let Some(f) = freekey {
13839 f((*root).key as *mut c_void);
13840 }
13841 free(root as *mut c_void);
13842}
13843
13844const FNM_PATHNAME: c_int = 0x1;
13849const FNM_NOESCAPE: c_int = 0x2;
13850const FNM_PERIOD: c_int = 0x4;
13851const FNM_LEADING_DIR: c_int = 0x8;
13852const FNM_CASEFOLD: c_int = 0x10;
13853const FNM_NOMATCH: c_int = 1;
13854
13855const FNM_END: c_int = 0;
13856const FNM_STAR: c_int = -5;
13857const FNM_QUESTION: c_int = -4;
13858const FNM_BRACKET: c_int = -3;
13859const FNM_UNMATCHABLE: c_int = -2;
13860
13861fn ascii_tolower(c: u8) -> u8 {
13862 if c >= b'A' && c <= b'Z' { c + 32 } else { c }
13863}
13864
13865fn ascii_toupper(c: u8) -> u8 {
13866 if c >= b'a' && c <= b'z' { c - 32 } else { c }
13867}
13868
13869fn ascii_casefold(k: u8) -> u8 {
13870 let upper = ascii_toupper(k);
13871 if upper != k { upper } else { ascii_tolower(k) }
13872}
13873
13874unsafe fn pat_next(pat: *const u8, m: usize, flags: c_int) -> (c_int, usize) {
13877 if m == 0 || *pat == 0 {
13878 return (FNM_END, 0);
13879 }
13880 let mut p = pat;
13881 let mut step = 1usize;
13882 let mut esc = false;
13883 if *p == b'\\' && !(flags & FNM_NOESCAPE != 0) && *p.add(1) != 0 {
13884 p = p.add(1);
13885 step = 2;
13886 esc = true;
13887 }
13888 if *p == b'[' && !esc {
13889 let mut k = 1usize;
13891 if k < m && (*pat.add(k) == b'^' || *pat.add(k) == b'!') { k += 1; }
13892 if k < m && *pat.add(k) == b']' { k += 1; }
13893 while k < m && *pat.add(k) != 0 && *pat.add(k) != b']' {
13894 if k + 1 < m && *pat.add(k) == b'[' &&
13895 (*pat.add(k+1) == b':' || *pat.add(k+1) == b'.' || *pat.add(k+1) == b'=') {
13896 let z = *pat.add(k+1);
13897 k += 2;
13898 if k < m { k += 1; }
13899 while k < m && *pat.add(k) != 0 && (*pat.add(k-1) != z || *pat.add(k) != b']') { k += 1; }
13900 if k == m || *pat.add(k) == 0 { break; }
13901 }
13902 k += 1;
13903 }
13904 if k == m || *pat.add(k) == 0 {
13905 return (b'[' as c_int, 1);
13907 }
13908 return (FNM_BRACKET, k + 1);
13909 }
13910 if *p == b'*' && !esc {
13911 return (FNM_STAR, 1);
13912 }
13913 if *p == b'?' && !esc {
13914 return (FNM_QUESTION, 1);
13915 }
13916 (*p as c_int, step)
13917}
13918
13919unsafe fn match_class(name: &[u8], k: u8, kfold: u8) -> bool {
13920 let eq = |c: u8| k == c || kfold == c;
13921 let in_range = |lo: u8, hi: u8| (k >= lo && k <= hi) || (kfold >= lo && kfold <= hi);
13922 match name {
13923 b"alnum" => in_range(b'0', b'9') || in_range(b'A', b'Z') || in_range(b'a', b'z'),
13924 b"alpha" => in_range(b'A', b'Z') || in_range(b'a', b'z'),
13925 b"blank" => eq(b' ') || eq(b'\t'),
13926 b"cntrl" => k < 0x20 || k == 0x7f,
13927 b"digit" => in_range(b'0', b'9'),
13928 b"graph" => k >= 0x21 && k <= 0x7e,
13929 b"lower" => in_range(b'a', b'z'),
13930 b"print" => k >= 0x20 && k <= 0x7e,
13931 b"punct" =>
13932 (k >= 0x21 && k <= 0x2f) ||
13933 (k >= 0x3a && k <= 0x40) ||
13934 (k >= 0x5b && k <= 0x60) ||
13935 (k >= 0x7b && k <= 0x7e),
13936 b"space" => eq(b' ') || eq(b'\t') || eq(b'\n') || eq(b'\r') || eq(0x0c) || eq(0x0b),
13937 b"upper" => in_range(b'A', b'Z'),
13938 b"xdigit" => in_range(b'0', b'9') || in_range(b'A', b'F') || in_range(b'a', b'f'),
13939 _ => false,
13940 }
13941}
13942
13943unsafe fn match_bracket(mut p: *const u8, k: u8, kfold: u8) -> bool {
13945 let mut inv = false;
13946 p = p.add(1); if *p == b'^' || *p == b'!' {
13948 inv = true;
13949 p = p.add(1);
13950 }
13951 if *p == b']' {
13953 if k == b']' { return !inv; }
13954 p = p.add(1);
13955 } else if *p == b'-' {
13956 if k == b'-' { return !inv; }
13957 p = p.add(1);
13958 }
13959 while *p != b']' && *p != 0 {
13960 if *p == b'-' && *p.add(1) != b']' && *p.add(1) != 0 {
13961 let lo = *p.sub(1);
13963 let hi = *p.add(1);
13964 if lo <= hi && (k >= lo && k <= hi || kfold >= lo && kfold <= hi) {
13965 return !inv;
13966 }
13967 p = p.add(2);
13968 } else if *p == b'[' && (*p.add(1) == b':' || *p.add(1) == b'.' || *p.add(1) == b'=') {
13969 let z = *p.add(1);
13970 let start = p.add(2);
13971 let mut q = start;
13972 while *q != 0 && (*q != z || *q.add(1) != b']') { q = q.add(1); }
13973 if *q != 0 {
13974 let len = (q as usize) - (start as usize);
13975 if len > 0 {
13976 let inner = core::slice::from_raw_parts(start, len);
13977 let matched =
13978 if z == b':' { match_class(inner, k, kfold) }
13979 else { len == 1 && (inner[0] == k || inner[0] == kfold) };
13980 if matched { return !inv; }
13981 }
13982 p = q.add(2);
13983 continue;
13984 }
13985 } else {
13986 if *p == k || *p == kfold {
13987 return !inv;
13988 }
13989 p = p.add(1);
13990 }
13991 }
13992 inv
13993}
13994
13995unsafe fn fnmatch_internal(pat: *const u8, str: *const u8, flags: c_int) -> c_int {
13997 if flags & FNM_PERIOD != 0 && *str == b'.' && *pat != b'.' {
13999 return FNM_NOMATCH;
14000 }
14001
14002 let mut p = pat;
14003 let mut s = str;
14004
14005 loop {
14007 let (tok, step) = pat_next(p, usize::MAX, flags);
14008 match tok {
14009 FNM_END => {
14010 return if *s == 0 { 0 } else { FNM_NOMATCH };
14011 }
14012 FNM_STAR => {
14013 p = p.add(1);
14014 break;
14015 }
14016 FNM_QUESTION => {
14017 if *s == 0 { return FNM_NOMATCH; }
14018 s = s.add(1);
14019 p = p.add(step);
14020 }
14021 FNM_BRACKET => {
14022 if *s == 0 { return FNM_NOMATCH; }
14023 let k = *s;
14024 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14025 if !match_bracket(p, k, kfold) { return FNM_NOMATCH; }
14026 p = p.add(step);
14027 s = s.add(1);
14028 }
14029 c => {
14030 if *s == 0 { return FNM_NOMATCH; }
14031 let k = *s;
14032 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14033 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14034 p = p.add(step);
14035 s = s.add(1);
14036 }
14037 }
14038 }
14039
14040 let mut ptail = p;
14043 let mut tailcnt: usize = 0;
14044 let mut pp = p;
14045 loop {
14046 let (tok, step) = pat_next(pp, usize::MAX, flags);
14047 if tok == FNM_END { break; }
14048 if tok == FNM_STAR {
14049 tailcnt = 0;
14050 ptail = pp.add(1);
14051 } else {
14052 tailcnt += 1;
14053 }
14054 pp = pp.add(step);
14055 }
14056
14057 let slen = strlen(s as *const c_char);
14059 if slen < tailcnt { return FNM_NOMATCH; }
14060
14061 let stail = s.add(slen - tailcnt);
14063 let mut tp = ptail;
14064 let mut ts = stail;
14065 loop {
14066 let (tok, step) = pat_next(tp, usize::MAX, flags);
14067 tp = tp.add(step);
14068 if tok == FNM_END {
14069 break;
14070 }
14071 let k = *ts;
14072 if k == 0 { return FNM_NOMATCH; }
14073 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14074 match tok {
14075 FNM_QUESTION => { ts = ts.add(1); }
14076 FNM_BRACKET => {
14077 if !match_bracket(tp.sub(step), k, kfold) { return FNM_NOMATCH; }
14078 ts = ts.add(1);
14079 }
14080 c => {
14081 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14082 ts = ts.add(1);
14083 }
14084 }
14085 }
14086
14087 let endstr = stail;
14088 let endpat = ptail;
14089
14090 let mut cp = p;
14091 let mut cs = s;
14092 while cp < endpat {
14093 let (tok, step) = pat_next(cp, usize::MAX, flags);
14094 if tok == FNM_STAR {
14095 cp = cp.add(step);
14096 cs = s;
14097 continue;
14098 }
14099 let comp_start = cp;
14100 let mut ok = false;
14101 let mut try_s = cs;
14102 while try_s < endstr {
14103 let mut tmp_p = comp_start;
14104 let mut tmp_s = try_s;
14105 let mut matched = true;
14106 loop {
14107 let (t, st) = pat_next(tmp_p, usize::MAX, flags);
14108 if t == FNM_STAR || t == FNM_END {
14109 cp = tmp_p;
14110 cs = tmp_s;
14111 ok = true;
14112 break;
14113 }
14114 if *tmp_s == 0 {
14115 matched = false;
14116 break;
14117 }
14118 let k = *tmp_s;
14119 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14120 match t {
14121 FNM_QUESTION => {
14122 tmp_s = tmp_s.add(1);
14123 }
14124 FNM_BRACKET => {
14125 if !match_bracket(tmp_p, k, kfold) {
14126 matched = false;
14127 break;
14128 }
14129 tmp_s = tmp_s.add(1);
14130 }
14131 c => {
14132 if k as c_int != c && kfold as c_int != c {
14133 matched = false;
14134 break;
14135 }
14136 tmp_s = tmp_s.add(1);
14137 }
14138 }
14139 tmp_p = tmp_p.add(st);
14140 }
14141 if ok { break; }
14142 if !matched {
14143 try_s = try_s.add(1);
14144 }
14145 }
14146 if !ok {
14147 return FNM_NOMATCH;
14148 }
14149 }
14150 0
14151}
14152
14153#[no_mangle]
14154pub unsafe extern "C" fn fnmatch(pat: *const c_char, str: *const c_char, flags: c_int) -> c_int {
14155 let pat = pat as *const u8;
14156 let str = str as *const u8;
14157
14158 if flags & FNM_PATHNAME != 0 {
14159 let mut s = str;
14161 let mut p = pat;
14162 loop {
14163 let mut send = s;
14165 while *send != 0 && *send != b'/' { send = send.add(1); }
14166 let mut pend = p;
14168 loop {
14169 let (tok, step) = pat_next(pend, usize::MAX, flags);
14170 if tok == FNM_END || (tok >= 0 && tok as u8 == b'/') {
14171 break;
14172 }
14173 pend = pend.add(step);
14174 }
14175 let (ptok, pstep) = pat_next(pend, usize::MAX, flags);
14176 let pat_is_slash = ptok >= 0 && ptok as u8 == b'/';
14177 let str_is_slash = *send == b'/';
14178 if pat_is_slash != str_is_slash && (*send != 0 || !(flags & FNM_LEADING_DIR != 0)) {
14179 return FNM_NOMATCH;
14180 }
14181 let plen = (pend as usize) - (p as usize);
14184 let slen = (send as usize) - (s as usize);
14185 if plen > 1024 || slen > 1024 { return FNM_NOMATCH; }
14188 let mut pbuf = [0u8; 1025];
14189 let mut sbuf = [0u8; 1025];
14190 core::ptr::copy_nonoverlapping(p, pbuf.as_mut_ptr(), plen);
14191 pbuf[plen] = 0;
14192 core::ptr::copy_nonoverlapping(s, sbuf.as_mut_ptr(), slen);
14193 sbuf[slen] = 0;
14194 if fnmatch_internal(pbuf.as_ptr(), sbuf.as_ptr(), flags & !FNM_LEADING_DIR) != 0 {
14195 return FNM_NOMATCH;
14196 }
14197 if !pat_is_slash {
14198 return 0;
14199 }
14200 s = send.add(1);
14201 p = pend.add(pstep);
14202 }
14203 }
14204
14205 if flags & FNM_LEADING_DIR != 0 {
14206 let mut s = str;
14208 while *s != 0 {
14209 if *s == b'/' {
14210 let len = (s as usize) - (str as usize);
14213 if len < 4096 {
14215 let mut buf = [0u8; 4096];
14216 core::ptr::copy_nonoverlapping(str, buf.as_mut_ptr(), len);
14217 buf[len] = 0;
14218 if fnmatch_internal(pat, buf.as_ptr(), flags) == 0 {
14219 return 0;
14220 }
14221 }
14222 }
14223 s = s.add(1);
14224 }
14225 }
14226
14227 fnmatch_internal(pat, str, flags)
14228}
14229
14230#[no_mangle]
14235pub unsafe extern "C" fn setmntent(name: *const c_char, mode: *const c_char) -> *mut FILE {
14236 fopen(name, mode)
14237}
14238
14239#[no_mangle]
14240pub unsafe extern "C" fn endmntent(f: *mut FILE) -> c_int {
14241 if !f.is_null() {
14242 fclose(f);
14243 }
14244 1
14245}
14246
14247static mut MNTENT_MNT: MntEnt = MntEnt {
14249 mnt_fsname: core::ptr::null_mut(),
14250 mnt_dir: core::ptr::null_mut(),
14251 mnt_type: core::ptr::null_mut(),
14252 mnt_opts: core::ptr::null_mut(),
14253 mnt_freq: 0,
14254 mnt_passno: 0,
14255};
14256
14257#[repr(C)]
14258pub struct MntEnt {
14259 mnt_fsname: *mut c_char,
14260 mnt_dir: *mut c_char,
14261 mnt_type: *mut c_char,
14262 mnt_opts: *mut c_char,
14263 mnt_freq: c_int,
14264 mnt_passno: c_int,
14265}
14266
14267unsafe fn unescape_ent(beg: *mut c_char) -> *mut c_char {
14268 let mut dest = beg;
14269 let mut src = beg;
14270 while *src != 0 {
14271 if *src != b'\\' as c_char {
14272 *dest = *src;
14273 dest = dest.add(1);
14274 src = src.add(1);
14275 continue;
14276 }
14277 if *src.add(1) == b'\\' as c_char {
14279 src = src.add(1);
14280 *dest = *src;
14281 dest = dest.add(1);
14282 src = src.add(1);
14283 continue;
14284 }
14285 let mut val: u8 = 0;
14287 let mut cnt = 0;
14288 let mut sp = src.add(1);
14289 while cnt < 3 && *sp >= b'0' as c_char && *sp <= b'7' as c_char {
14290 val = val * 8 + (*sp as u8 - b'0');
14291 sp = sp.add(1);
14292 cnt += 1;
14293 }
14294 if cnt > 0 {
14295 *dest = val as c_char;
14296 dest = dest.add(1);
14297 src = sp;
14298 } else {
14299 *dest = *src;
14300 dest = dest.add(1);
14301 src = src.add(1);
14302 }
14303 }
14304 *dest = 0;
14305 beg
14306}
14307
14308unsafe fn parse_mntent_line(
14309 linebuf: *mut c_char,
14310 mnt: *mut MntEnt,
14311) -> *mut MntEnt {
14312 let _len = strlen(linebuf as *const c_char);
14313 let mut p = linebuf;
14316 while *p == b' ' as c_char || *p == b'\t' as c_char || *p == b'\n' as c_char || *p == b'\r' as c_char {
14318 p = p.add(1);
14319 }
14320 if *p == 0 || *p == b'#' as c_char {
14321 return core::ptr::null_mut();
14322 }
14323
14324 (*mnt).mnt_fsname = p;
14326 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14327 p = p.add(1);
14328 }
14329 if *p == 0 { return core::ptr::null_mut(); }
14330 *p = 0;
14331 p = p.add(1);
14332 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14333
14334 (*mnt).mnt_dir = p;
14336 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14337 p = p.add(1);
14338 }
14339 if *p == 0 { return core::ptr::null_mut(); }
14340 *p = 0;
14341 p = p.add(1);
14342 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14343
14344 (*mnt).mnt_type = p;
14346 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14347 p = p.add(1);
14348 }
14349 if *p == 0 { return core::ptr::null_mut(); }
14350 *p = 0;
14351 p = p.add(1);
14352 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14353
14354 (*mnt).mnt_opts = p;
14356 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14357 p = p.add(1);
14358 }
14359 if *p != 0 {
14360 *p = 0;
14361 p = p.add(1);
14362 }
14363 if *(*mnt).mnt_opts == 0 {
14364 (*mnt).mnt_opts = b"defaults\0".as_ptr() as *mut c_char;
14365 }
14366
14367 (*mnt).mnt_freq = 0;
14369 (*mnt).mnt_passno = 0;
14370 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14372 if *p >= b'0' as c_char && *p <= b'9' as c_char {
14373 (*mnt).mnt_freq = (*p - b'0' as c_char) as c_int;
14374 p = p.add(1);
14375 while *p >= b'0' as c_char && *p <= b'9' as c_char {
14376 (*mnt).mnt_freq = (*mnt).mnt_freq * 10 + (*p - b'0' as c_char) as c_int;
14377 p = p.add(1);
14378 }
14379 }
14380 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14381 if *p >= b'0' as c_char && *p <= b'9' as c_char {
14382 (*mnt).mnt_passno = (*p - b'0' as c_char) as c_int;
14383 p = p.add(1);
14384 while *p >= b'0' as c_char && *p <= b'9' as c_char {
14385 (*mnt).mnt_passno = (*mnt).mnt_passno * 10 + (*p - b'0' as c_char) as c_int;
14386 p = p.add(1);
14387 }
14388 }
14389
14390 unescape_ent((*mnt).mnt_fsname);
14392 unescape_ent((*mnt).mnt_dir);
14393 unescape_ent((*mnt).mnt_type);
14394 unescape_ent((*mnt).mnt_opts);
14395
14396 mnt
14397}
14398
14399static SENTINEL_PTR: usize = 1;
14402
14403unsafe fn mntent_fgetc(f: *mut FILE) -> c_int {
14405 fgetc(f)
14406}
14407
14408unsafe fn mntent_fgets(buf: *mut c_char, n: usize, f: *mut FILE) -> *mut c_char {
14409 if n == 0 { return core::ptr::null_mut(); }
14410 let max = n - 1;
14411 let mut i = 0usize;
14412 while i < max {
14413 let c = mntent_fgetc(f);
14414 if c == -1 { if i == 0 { return core::ptr::null_mut(); } break; }
14415 *buf.add(i) = c as c_char;
14416 i += 1;
14417 if c == b'\n' as c_int { break; }
14418 }
14419 *buf.add(i) = 0;
14420 buf
14421}
14422
14423#[no_mangle]
14424pub unsafe extern "C" fn getmntent_r(
14425 f: *mut FILE,
14426 mnt: *mut MntEnt,
14427 mut linebuf: *mut c_char,
14428 buflen: c_int,
14429) -> *mut MntEnt {
14430 let use_internal = linebuf as usize == SENTINEL_PTR;
14431
14432 (*mnt).mnt_freq = 0;
14433 (*mnt).mnt_passno = 0;
14434
14435 static mut MNT_LINE: *mut c_char = core::ptr::null_mut();
14436 static mut MNT_LINE_CAP: usize = 0;
14437
14438 loop {
14439 let res = if use_internal {
14440 let n = getline(&raw mut MNT_LINE, &raw mut MNT_LINE_CAP, f);
14441 if n < 0 {
14442 return core::ptr::null_mut();
14443 }
14444 linebuf = MNT_LINE;
14445 MNT_LINE
14446 } else {
14447 if buflen <= 0 {
14448 ERRNO!() = EINVAL;
14449 return core::ptr::null_mut();
14450 }
14451 mntent_fgets(linebuf, buflen as usize, f)
14452 };
14453 if res.is_null() {
14454 return core::ptr::null_mut();
14455 }
14456 let mut has_newline = false;
14457 let mut p = linebuf;
14458 while *p != 0 { if *p == b'\n' as c_char { has_newline = true; break; } p = p.add(1); }
14459 if !has_newline {
14460 ERRNO!() = 34;
14461 return core::ptr::null_mut();
14462 }
14463 let result = parse_mntent_line(linebuf, mnt);
14464 if !result.is_null() {
14465 return result;
14466 }
14467 }
14468}
14469
14470#[no_mangle]
14471pub unsafe extern "C" fn getmntent(f: *mut FILE) -> *mut MntEnt {
14472 getmntent_r(f, core::ptr::addr_of_mut!(MNTENT_MNT), SENTINEL_PTR as *mut c_char, 0)
14473}
14474
14475#[no_mangle]
14476pub unsafe extern "C" fn addmntent(f: *mut FILE, mnt: *const MntEnt) -> c_int {
14477 fseek(f, 0, 2); let written = fprintf(
14479 f,
14480 b"%s\t%s\t%s\t%s\t%d\t%d\n\0".as_ptr() as *const c_char,
14481 (*mnt).mnt_fsname,
14482 (*mnt).mnt_dir,
14483 (*mnt).mnt_type,
14484 (*mnt).mnt_opts,
14485 (*mnt).mnt_freq,
14486 (*mnt).mnt_passno,
14487 );
14488 if written < 0 { 1 } else { 0 }
14489}
14490
14491#[no_mangle]
14492pub unsafe extern "C" fn hasmntopt(mnt: *const MntEnt, opt: *const c_char) -> *mut c_char {
14493 let l = strlen(opt as *const c_char);
14494 let mut p = (*mnt).mnt_opts;
14495 loop {
14496 if strncmp(p as *const u8, opt as *const u8, l) == 0 {
14497 let after = *p.add(l);
14498 if after == 0 || after == b',' as c_char || after == b'=' as c_char {
14499 return p;
14500 }
14501 }
14502 let comma = strchr(p as *const u8, b',' as c_int);
14503 if comma.is_null() {
14504 return core::ptr::null_mut();
14505 }
14506 p = comma.add(1) as *mut c_char;
14507 }
14508}
14509
14510const EEXIST: c_int = 17;
14518const ENAMETOOLONG: c_int = 36;
14519const EMFILE: c_int = 24;
14520const EIDRM: c_int = 43;
14521
14522#[inline]
14523unsafe fn sys_msgget(key: c_int, msgflg: c_int) -> i64 {
14524 <Arch as Syscalls>::syscall2(SYS_MSGGET, key as i64, msgflg as i64)
14525}
14526
14527#[inline]
14528unsafe fn sys_msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> i64 {
14529 <Arch as Syscalls>::syscall4(SYS_MSGSND, msqid as i64, msgp as i64, msgsz as i64, msgflg as i64)
14530}
14531
14532#[inline]
14533unsafe fn sys_msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> i64 {
14534 <Arch as Syscalls>::syscall5(SYS_MSGRCV, msqid as i64, msgp as i64, msgsz as i64, msgtyp as i64, msgflg as i64)
14535}
14536
14537#[inline]
14538unsafe fn sys_msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
14539 <Arch as Syscalls>::syscall3(SYS_MSGCTL, msqid as i64, cmd as i64, buf as i64)
14540}
14541
14542#[inline]
14543unsafe fn sys_semget(key: c_int, nsems: c_int, semflg: c_int) -> i64 {
14544 <Arch as Syscalls>::syscall3(SYS_SEMGET, key as i64, nsems as i64, semflg as i64)
14545}
14546
14547#[inline]
14548unsafe fn sys_semop(semid: c_int, sops: *const c_void, nsops: usize) -> i64 {
14549 <Arch as Syscalls>::syscall3(SYS_SEMOP, semid as i64, sops as i64, nsops as i64)
14550}
14551
14552#[inline]
14553unsafe fn sys_semctl(semid: c_int, semnum: c_int, cmd: c_int, arg: *mut c_void) -> i64 {
14554 <Arch as Syscalls>::syscall4(SYS_SEMCTL, semid as i64, semnum as i64, cmd as i64, arg as i64)
14555}
14556
14557#[inline]
14558unsafe fn sys_shmget(key: c_int, size: usize, shmflg: c_int) -> i64 {
14559 <Arch as Syscalls>::syscall3(SYS_SHMGET, key as i64, size as i64, shmflg as i64)
14560}
14561
14562#[inline]
14563unsafe fn sys_shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> i64 {
14564 <Arch as Syscalls>::syscall3(SYS_SHMAT, shmid as i64, shmaddr as i64, shmflg as i64)
14565}
14566
14567#[inline]
14568unsafe fn sys_shmdt(shmaddr: *const c_void) -> i64 {
14569 <Arch as Syscalls>::syscall1(SYS_SHMDT, shmaddr as i64)
14570}
14571
14572#[inline]
14573unsafe fn sys_shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
14574 <Arch as Syscalls>::syscall3(SYS_SHMCTL, shmid as i64, cmd as i64, buf as i64)
14575}
14576
14577#[no_mangle]
14579pub unsafe extern "C" fn ftok(path: *const c_char, id: c_int) -> c_int {
14580 let mut st: kernel_stat64 = core::mem::zeroed();
14581 let r = sys_stat(path as *const u8, &mut st);
14582 if r < 0 {
14583 ERRNO!() = (-r) as c_int;
14584 return -1;
14585 }
14586 ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16) | (((id as u32 & 0xff) << 24)) as u64) as c_int
14587}
14588
14589#[no_mangle]
14591pub unsafe extern "C" fn msgget(key: c_int, msgflg: c_int) -> c_int {
14592 let r = sys_msgget(key, msgflg);
14593 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
14594}
14595
14596#[no_mangle]
14598pub unsafe extern "C" fn msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> c_int {
14599 let r = sys_msgsnd(msqid, msgp, msgsz, msgflg);
14600 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
14601}
14602
14603#[no_mangle]
14605pub unsafe extern "C" fn msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> isize {
14606 let r = sys_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
14607 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
14608}
14609
14610#[no_mangle]
14612pub unsafe extern "C" fn msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
14613 let r = sys_msgctl(msqid, cmd, buf);
14614 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
14615}
14616
14617#[no_mangle]
14619pub unsafe extern "C" fn semget(key: c_int, nsems: c_int, semflg: c_int) -> c_int {
14620 if nsems > 65535 { ERRNO!() = 22; return -1; }
14621 let r = sys_semget(key, nsems, semflg);
14622 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
14623}
14624
14625#[no_mangle]
14627pub unsafe extern "C" fn semop(semid: c_int, sops: *const c_void, nsops: usize) -> c_int {
14628 let r = sys_semop(semid, sops, nsops);
14629 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
14630}
14631
14632#[no_mangle]
14634pub unsafe extern "C" fn semctl(semid: c_int, semnum: c_int, cmd: c_int, mut args: ...) -> c_int {
14635 let mut arg: *mut c_void = core::ptr::null_mut();
14636 match cmd {
14638 16 | 13 | 17 | 1 | 2 | 3 | 18 | 19 | 20 | 0x102 | 0x104 | 0x106 => {
14642 arg = args.next_arg::<*mut c_void>();
14643 }
14644 _ => {}
14645 }
14646 let r = sys_semctl(semid, semnum, cmd, arg);
14647 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
14648}
14649
14650#[no_mangle]
14652pub unsafe extern "C" fn shmget(key: c_int, size: usize, shmflg: c_int) -> c_int {
14653 let r = sys_shmget(key, size, shmflg);
14654 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
14655}
14656
14657#[no_mangle]
14659pub unsafe extern "C" fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void {
14660 let r = sys_shmat(shmid, shmaddr, shmflg);
14661 if (r as usize) > (-(4096isize as isize)) as usize {
14662 ERRNO!() = (-r) as c_int;
14663 return -1isize as *mut c_void;
14664 }
14665 r as *mut c_void
14666}
14667
14668#[no_mangle]
14670pub unsafe extern "C" fn shmdt(shmaddr: *const c_void) -> c_int {
14671 let r = sys_shmdt(shmaddr);
14672 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
14673}
14674
14675#[no_mangle]
14677pub unsafe extern "C" fn shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
14678 let r = sys_shmctl(shmid, cmd, buf);
14679 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
14680}
14681
14682#[no_mangle]
14692pub static mut __auxv: *const usize = core::ptr::null();
14693#[no_mangle]
14694pub static mut __rc_static_base: usize = 0;
14695static mut RC_STATIC_EXEC: bool = false;
14696
14697#[no_mangle]
14698pub static mut __progname: *mut c_char = core::ptr::null_mut();
14699#[no_mangle]
14700pub static mut __progname_full: *mut c_char = core::ptr::null_mut();
14701#[no_mangle]
14702pub static mut program_invocation_name: *mut c_char = core::ptr::null_mut();
14703#[no_mangle]
14704pub static mut program_invocation_short_name: *mut c_char = core::ptr::null_mut();
14705
14706#[no_mangle]
14707pub static in6addr_any: [u32; 4] = [0; 4];
14708#[no_mangle]
14709pub static in6addr_loopback: [u32; 4] = [0, 0, 0, 0x0100_0000];
14710
14711#[no_mangle]
14712pub static mut __daylight: c_int = 0;
14713#[no_mangle]
14714pub static mut __timezone: c_long = 0;
14715#[no_mangle]
14716pub static mut __tzname: [*mut c_char; 2] = [core::ptr::null_mut(); 2];
14717
14718#[no_mangle]
14719pub unsafe extern "C" fn getauxval(type_: c_ulong) -> c_ulong {
14720 let mut p = __auxv;
14721 if p.is_null() {
14722 return 0;
14723 }
14724 loop {
14725 let tag = *p;
14726 if tag == 0 {
14727 return 0;
14728 }
14729 if tag == type_ as usize {
14730 return *p.add(1) as c_ulong;
14731 }
14732 p = p.add(2);
14733 }
14734}
14735
14736
14737unsafe fn run_static_init() {
14738 if !RC_STATIC_EXEC {
14739 return;
14740 }
14741 extern "C" {
14742 static __preinit_array_start: usize;
14743 static __preinit_array_end: usize;
14744 static __init_array_start: usize;
14745 static __init_array_end: usize;
14746 }
14747 let mut p = core::ptr::addr_of!(__preinit_array_start) as usize;
14748 let end = core::ptr::addr_of!(__preinit_array_end) as usize;
14749 while p < end {
14750 let f = core::ptr::read_unaligned(p as *const usize);
14751 if f != 0 {
14752 let f: unsafe extern "C" fn() = core::mem::transmute(f);
14753 f();
14754 }
14755 p += core::mem::size_of::<usize>();
14756 }
14757 p = core::ptr::addr_of!(__init_array_start) as usize;
14758 let end = core::ptr::addr_of!(__init_array_end) as usize;
14759 while p < end {
14760 let f = core::ptr::read_unaligned(p as *const usize);
14761 if f != 0 {
14762 let f: unsafe extern "C" fn() = core::mem::transmute(f);
14763 f();
14764 }
14765 p += core::mem::size_of::<usize>();
14766 }
14767}
14768
14769type MainFn = unsafe extern "C" fn(c_int, *const *const c_char, *const *const c_char) -> c_int;
14770type InitFn = unsafe extern "C" fn();
14771
14772#[cfg(target_arch = "x86_64")]
14773unsafe fn static_tls_tp() -> usize {
14774 let mut fs: u64 = 0;
14775 if arch_prctl(0x1003, &mut fs as *mut u64 as u64) != 0 {
14776 0
14777 } else {
14778 fs as usize
14779 }
14780}
14781
14782#[cfg(target_arch = "x86_64")]
14783unsafe fn set_static_tls_tp(tp: usize) {
14784 let _ = arch_prctl(0x1002, tp as u64);
14785}
14786
14787#[cfg(target_arch = "aarch64")]
14788unsafe fn static_tls_tp() -> usize {
14789 let tp: usize;
14790 core::arch::asm!("mrs {}, tpidr_el0", out(reg) tp, options(nostack));
14791 tp
14792}
14793
14794#[cfg(target_arch = "aarch64")]
14795unsafe fn set_static_tls_tp(tp: usize) {
14796 core::arch::asm!("msr tpidr_el0, {}", in(reg) tp, options(nostack));
14797}
14798
14799#[cfg(target_arch = "riscv64")]
14800unsafe fn static_tls_tp() -> usize {
14801 let tp: usize;
14802 core::arch::asm!("mv {}, tp", out(reg) tp, options(nostack));
14803 tp
14804}
14805
14806#[cfg(target_arch = "riscv64")]
14807unsafe fn set_static_tls_tp(tp: usize) {
14808 core::arch::asm!("mv tp, {}", in(reg) tp, options(nostack));
14809}
14810
14811static mut STATIC_TLS_BLOCK_SIZE: usize = 0;
14812static mut STATIC_TLS_TP_OFFSET: usize = 0;
14813static mut STATIC_TLS_VAR_OFFSET: usize = 0;
14814static mut STATIC_TLS_TLS_SIZE: usize = 0;
14815static mut STATIC_TLS_IMAGE: *const u8 = core::ptr::null();
14816static mut STATIC_TLS_FILESZ: usize = 0;
14817static mut STATIC_TLS_CANARY: u64 = 0;
14818
14819unsafe fn static_tls_init_block(block: *mut u8) -> *mut u8 {
14820 if block.is_null() || STATIC_TLS_BLOCK_SIZE == 0 {
14821 return core::ptr::null_mut();
14822 }
14823 let var_base = block.add(STATIC_TLS_VAR_OFFSET);
14824 if STATIC_TLS_TLS_SIZE > 0 {
14825 core::ptr::write_bytes(var_base, 0, STATIC_TLS_TLS_SIZE);
14826 }
14827 if STATIC_TLS_FILESZ > 0 && !STATIC_TLS_IMAGE.is_null() {
14828 core::ptr::copy_nonoverlapping(STATIC_TLS_IMAGE, var_base, STATIC_TLS_FILESZ);
14829 }
14830 let tp = block.add(STATIC_TLS_TP_OFFSET);
14831 let tcb = if cfg!(target_arch = "x86_64") {
14832 tp as usize
14833 } else {
14834 block as usize
14835 };
14836 core::ptr::write_unaligned(tcb as *mut u64, tcb as u64);
14837 core::ptr::write_unaligned((tcb as *mut u64).add(1), 1);
14838 core::ptr::write_unaligned((tcb as *mut u64).add(2), STATIC_TLS_TLS_SIZE as u64);
14839 core::ptr::write_unaligned((tcb as *mut u64).add(3), 1);
14840 core::ptr::write_unaligned((tcb as *mut u64).add(4), 0); core::ptr::write_unaligned((tcb as *mut u64).add(5), STATIC_TLS_CANARY); core::ptr::write_unaligned((tcb as *mut u64).add(6), 0); core::ptr::write_unaligned((tcb as *mut u64).add(7), 0); core::ptr::write_unaligned((tcb as *mut u64).add(8), 0); tp
14846}
14847
14848unsafe fn static_tls_create_block() -> *mut u8 {
14849 if STATIC_TLS_BLOCK_SIZE == 0 {
14850 return core::ptr::null_mut();
14851 }
14852 let block = sys_mmap(
14853 core::ptr::null_mut(),
14854 STATIC_TLS_BLOCK_SIZE,
14855 PROT_READ | PROT_WRITE,
14856 MAP_PRIVATE | MAP_ANONYMOUS,
14857 -1,
14858 0,
14859 );
14860 if block.is_null() || block == MMAP_FAILED {
14861 return core::ptr::null_mut();
14862 }
14863 static_tls_init_block(block)
14864}
14865
14866#[repr(C)]
14867pub struct TlsIndex {
14868 pub ti_module: usize,
14869 pub ti_offset: usize,
14870}
14871
14872static mut TLS_GET_ADDR_IMPL: usize = 0;
14877
14878#[no_mangle]
14883pub unsafe extern "C" fn __rc_set_tls_get_addr(f: usize) {
14884 TLS_GET_ADDR_IMPL = f;
14885}
14886
14887#[no_mangle]
14888pub unsafe extern "C" fn __tls_get_addr(ti: *const TlsIndex) -> *mut u8 {
14889 if TLS_GET_ADDR_IMPL != 0 {
14890 let f: unsafe extern "C" fn(*const TlsIndex) -> *mut u8 =
14891 core::mem::transmute(TLS_GET_ADDR_IMPL);
14892 return f(ti);
14893 }
14894 if ti.is_null() || (*ti).ti_module != 0 || !RC_STATIC_EXEC {
14895 return core::ptr::null_mut();
14896 }
14897 let tp = static_tls_tp();
14898 if tp == 0 {
14899 return core::ptr::null_mut();
14900 }
14901 (tp - STATIC_TLS_TP_OFFSET + STATIC_TLS_VAR_OFFSET + (*ti).ti_offset) as *mut u8
14902}
14903
14904unsafe fn init_static_tls() {
14907 if static_tls_tp() != 0 {
14908 return;
14909 }
14910 let phdr = getauxval(3) as usize; let phnum = getauxval(5) as usize; let phent = getauxval(4) as usize; if phdr == 0 || phnum == 0 || phent < 56 {
14914 return;
14915 }
14916
14917 let mut tls_vaddr = 0usize;
14918 let mut tls_filesz = 0usize;
14919 let mut tls_memsz = 0usize;
14920 let mut tls_align = 1usize;
14921 let mut exec_base = __rc_static_base;
14922 let mut i = 0usize;
14923 while i < phnum {
14924 let ph = phdr + i * phent;
14925 let p_type = core::ptr::read_unaligned(ph as *const u32);
14926 if p_type == 3 {
14927 return;
14929 }
14930 if p_type == 6 {
14931 if exec_base == 0 {
14933 let p_vaddr = core::ptr::read_unaligned((ph + 16) as *const u64) as usize;
14934 exec_base = phdr.wrapping_sub(p_vaddr);
14935 }
14936 } else if p_type == 7 {
14937 tls_vaddr = core::ptr::read_unaligned((ph + 16) as *const u64) as usize;
14939 tls_filesz = core::ptr::read_unaligned((ph + 32) as *const u64) as usize;
14940 tls_memsz = core::ptr::read_unaligned((ph + 40) as *const u64) as usize;
14941 let align = core::ptr::read_unaligned((ph + 48) as *const u64) as usize;
14942 if align > 1 {
14943 tls_align = align;
14944 }
14945 }
14946 i += 1;
14947 }
14948
14949 let tcb_size = 256usize;
14950 #[cfg(target_arch = "x86_64")]
14951 let gap = 0usize;
14952 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
14953 let gap = if cfg!(target_arch = "aarch64") { 16usize } else { 0usize };
14954
14955 let tls_size = if tls_align > 1 {
14956 (tls_memsz + tls_align - 1) & !(tls_align - 1)
14957 } else {
14958 tls_memsz
14959 };
14960 let total = tcb_size + gap + tls_size + tls_align;
14961 STATIC_TLS_BLOCK_SIZE = total;
14962 STATIC_TLS_TP_OFFSET = if cfg!(target_arch = "x86_64") {
14963 tls_size
14964 } else {
14965 tcb_size
14966 };
14967 STATIC_TLS_VAR_OFFSET = if cfg!(target_arch = "x86_64") {
14968 0
14969 } else {
14970 tcb_size + gap
14971 };
14972 STATIC_TLS_TLS_SIZE = tls_size;
14973 STATIC_TLS_IMAGE = (exec_base + tls_vaddr) as *const u8;
14974 STATIC_TLS_FILESZ = tls_filesz;
14975 let random = getauxval(25) as *const u8; STATIC_TLS_CANARY = if random.is_null() {
14977 0xdefaced_cafebeefu64
14978 } else {
14979 core::ptr::read_unaligned(random as *const u64)
14980 ^ core::ptr::read_unaligned(random.add(8) as *const u64)
14981 };
14982
14983 let block = sys_mmap(
14984 core::ptr::null_mut(),
14985 total,
14986 PROT_READ | PROT_WRITE,
14987 MAP_PRIVATE | MAP_ANONYMOUS,
14988 -1,
14989 0,
14990 );
14991 if block.is_null() || block == MMAP_FAILED {
14992 return;
14993 }
14994 let tp = static_tls_init_block(block);
14995 if tp.is_null() {
14996 return;
14997 }
14998 set_static_tls_tp(tp as usize);
14999 RC_STATIC_EXEC = true;
15000}
15001
15002
15003#[no_mangle]
15004pub unsafe extern "C" fn __libc_start_main(
15005 main: MainFn,
15006 argc: c_int,
15007 argv: *const *const c_char,
15008 _init: *const c_void,
15009 _fini: *const c_void,
15010 _rtld_fini: *const c_void,
15011 _stack_end: *const c_void,
15012) -> ! {
15013 let envp = argv.add((argc + 1) as usize);
15014 let mut aux = envp;
15015 while !(*aux).is_null() {
15016 aux = aux.add(1);
15017 }
15018 __auxv = aux.add(1) as *const usize;
15019 init_static_tls();
15020 errno_init();
15021 pthread_self();
15026
15027 __environ = envp as *mut *mut c_char;
15028 environ = __environ; ___environ = __environ;
15030 _environ = __environ;
15031
15032 if !argv.is_null() && argc > 0 {
15034 let argv0 = *argv;
15035 __progname_full = argv0 as *mut c_char;
15036 program_invocation_name = argv0 as *mut c_char;
15037 let mut base = argv0;
15038 let mut p = argv0;
15039 while *p != 0 {
15040 if *p == b'/' as c_char { base = p.add(1); }
15041 p = p.add(1);
15042 }
15043 __progname = base as *mut c_char;
15044 program_invocation_short_name = base as *mut c_char;
15045 }
15046
15047 __stdio_init();
15048 run_static_init();
15049
15050 let mut set: SigSetT = 0;
15051 sigemptyset(&mut set);
15052 sigaddset(&mut set, SIGCANCEL);
15053 sigprocmask(SIG_UNBLOCK, &set, core::ptr::null_mut());
15054
15055 if !_init.is_null() {
15056 let init_fn: InitFn = core::mem::transmute(_init);
15057 init_fn();
15058 }
15059
15060 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
15064 {
15065 let random_ptr = getauxval(25) as *const u8; if !random_ptr.is_null() {
15067 let a = core::ptr::read_unaligned(random_ptr as *const u64);
15068 let b = core::ptr::read_unaligned(random_ptr.add(8) as *const u64);
15069 __stack_chk_guard = (a ^ b) as usize;
15070 } else {
15071 __stack_chk_guard = 0xdefaced_cafebeef;
15073 }
15074 }
15075
15076 let result = main(argc, argv, envp);
15077
15078 if !_fini.is_null() {
15079 let fini_fn: InitFn = core::mem::transmute(_fini);
15080 fini_fn();
15081 }
15082
15083 exit(result);
15084}
15085
15086type LdsoDlopenFn = unsafe extern "C" fn(*const c_char, c_int) -> *mut c_void;
15087type LdsoDlsymFn = unsafe extern "C" fn(*mut c_void, *const c_char, *mut c_void) -> *mut c_void;
15088type LdsoDlcloseFn = unsafe extern "C" fn(*mut c_void) -> c_int;
15089type LdsoDlerrorFn = unsafe extern "C" fn() -> *const c_char;
15090
15091static mut LDSO_DLOPEN: Option<LdsoDlopenFn> = None;
15092static mut LDSO_DLSYM: Option<LdsoDlsymFn> = None;
15093static mut LDSO_DLCLOSE: Option<LdsoDlcloseFn> = None;
15094static mut LDSO_DLERROR: Option<LdsoDlerrorFn> = None;
15095
15096#[no_mangle]
15097pub unsafe extern "C" fn __ldso_register_dlopen(f: LdsoDlopenFn) {
15098 LDSO_DLOPEN = Some(f);
15099}
15100
15101#[no_mangle]
15102pub unsafe extern "C" fn __ldso_register_dlsym(f: LdsoDlsymFn) {
15103 LDSO_DLSYM = Some(f);
15104}
15105
15106#[no_mangle]
15107pub unsafe extern "C" fn __ldso_register_dlclose(f: LdsoDlcloseFn) {
15108 LDSO_DLCLOSE = Some(f);
15109}
15110
15111#[no_mangle]
15112pub unsafe extern "C" fn __ldso_register_dlerror(f: LdsoDlerrorFn) {
15113 LDSO_DLERROR = Some(f);
15114}
15115
15116#[no_mangle]
15117pub unsafe extern "C" fn dlopen(filename: *const c_char, flags: c_int) -> *mut c_void {
15118 if let Some(f) = LDSO_DLOPEN {
15119 f(filename, flags)
15120 } else {
15121 null_mut()
15122 }
15123}
15124
15125#[no_mangle]
15126pub unsafe extern "C" fn dlsym_impl(
15127 handle: *mut c_void,
15128 symbol: *const c_char,
15129 ra: *mut c_void,
15130) -> *mut c_void {
15131 if let Some(f) = LDSO_DLSYM {
15132 f(handle, symbol, ra)
15133 } else {
15134 null_mut()
15135 }
15136}
15137
15138#[no_mangle]
15142#[unsafe(naked)]
15143#[cfg(target_arch = "x86_64")]
15144pub unsafe extern "C" fn dlsym(_handle: *mut c_void, _symbol: *const c_char) -> *mut c_void {
15145 core::arch::naked_asm!("mov rdx, [rsp]", "jmp dlsym_impl");
15146}
15147
15148#[no_mangle]
15149#[unsafe(naked)]
15150#[cfg(target_arch = "aarch64")]
15151pub unsafe extern "C" fn dlsym(_handle: *mut c_void, _symbol: *const c_char) -> *mut c_void {
15152 core::arch::naked_asm!("mov x2, x30", "b dlsym_impl");
15153}
15154
15155#[no_mangle]
15156#[unsafe(naked)]
15157#[cfg(target_arch = "riscv64")]
15158pub unsafe extern "C" fn dlsym(_handle: *mut c_void, _symbol: *const c_char) -> *mut c_void {
15159 core::arch::naked_asm!("mv a2, ra", "la t0, dlsym_impl", "jr t0");
15160}
15161
15162#[no_mangle]
15163pub unsafe extern "C" fn dlclose(handle: *mut c_void) -> c_int {
15164 if let Some(f) = LDSO_DLCLOSE {
15165 f(handle)
15166 } else {
15167 0
15168 }
15169}
15170
15171#[no_mangle]
15172pub unsafe extern "C" fn dlerror() -> *const c_char {
15173 if let Some(f) = LDSO_DLERROR {
15174 f()
15175 } else {
15176 core::ptr::null()
15177 }
15178}
15179
15180include!("crypt_impl.rs");
15181include!("statvfs.rs");
15182include!("daemon.rs");
15183include!("dn_expand.rs");
15184include!("lrand48.rs");
15185include!("strverscmp.rs");
15186include!("syscall.rs");
15187include!("pthread_atfork.rs");
15188include!("fenv.rs");
15189include!("locale_ctype.rs");
15190include!("regression_stubs.rs");
15191include!("netdb_extra.rs");
15192include!("compat_extra.rs");
15193include!("stdio_extra.rs");
15194include!("ns_parse.rs");
15195include!("fts.rs");
15196include!("ifaddrs.rs");
15197include!("dl_extra.rs");
15198include!("des.rs");
15199include!("path_extra.rs");
15200include!("wordexp.rs");
15201include!("getopt_impl.rs");
15202
15203type regoff_t = c_int;
15208
15209#[repr(C)]
15210pub struct regex_t {
15211 pub re_nsub: usize,
15212 pub __opaque: *mut c_void,
15213 pub __padding: [*mut c_void; 4],
15214 pub __nsub2: usize,
15215 pub __padding2: c_char,
15216}
15217
15218#[repr(C)]
15219pub struct regmatch_t {
15220 pub rm_so: regoff_t,
15221 pub rm_eo: regoff_t,
15222}
15223
15224include!("regex.rs");
15225
15226#[cfg(test)]
15227mod libc_unit_stub {
15228 #[test]
15229 fn stub() {
15230 assert!(true);
15231 }
15232}
15233
15234#[inline]
15239pub(crate) fn fmax_impl(x: f64, y: f64) -> f64 {
15240 if x.is_nan() { return y; }
15241 if y.is_nan() { return x; }
15242 if x == 0.0 && y == 0.0 {
15243 return if x.is_sign_negative() && y.is_sign_negative() { -0.0 } else { 0.0 };
15244 }
15245 if x > y { x } else { y }
15246}
15247
15248#[inline]
15249pub(crate) fn fmin_impl(x: f64, y: f64) -> f64 {
15250 if x.is_nan() { return y; }
15251 if y.is_nan() { return x; }
15252 if x == 0.0 && y == 0.0 {
15253 return if x.is_sign_negative() || y.is_sign_negative() { -0.0 } else { 0.0 };
15254 }
15255 if x < y { x } else { y }
15256}
15257
15258#[inline]
15259pub(crate) fn fmaxf_impl(x: f32, y: f32) -> f32 {
15260 if x.is_nan() { return y; }
15261 if y.is_nan() { return x; }
15262 if x == 0.0 && y == 0.0 {
15263 return if x.is_sign_negative() && y.is_sign_negative() { -0.0 } else { 0.0 };
15264 }
15265 if x > y { x } else { y }
15266}
15267
15268#[inline]
15269pub(crate) fn fminf_impl(x: f32, y: f32) -> f32 {
15270 if x.is_nan() { return y; }
15271 if y.is_nan() { return x; }
15272 if x == 0.0 && y == 0.0 {
15273 return if x.is_sign_negative() || y.is_sign_negative() { -0.0 } else { 0.0 };
15274 }
15275 if x < y { x } else { y }
15276}
15277
15278#[inline(never)]
15279#[no_mangle]
15280pub unsafe extern "C" fn fmax(x: f64, y: f64) -> f64 {
15281 fmax_impl(x, y)
15282}
15283
15284#[inline(never)]
15285#[no_mangle]
15286pub unsafe extern "C" fn fmin(x: f64, y: f64) -> f64 {
15287 fmin_impl(x, y)
15288}
15289
15290#[no_mangle]
15291pub unsafe extern "C" fn fminf(x: f32, y: f32) -> f32 {
15292 fminf_impl(x, y)
15293}
15294
15295#[no_mangle]
15296pub unsafe extern "C" fn fdim(x: f64, y: f64) -> f64 {
15297 if x.is_nan() || y.is_nan() {
15298 return f64::NAN;
15299 }
15300 if x > y { x - y } else { 0.0 }
15301}
15302
15303#[no_mangle]
15304pub unsafe extern "C" fn fma(x: f64, y: f64, z: f64) -> f64 {
15305 if (x.is_infinite() && y == 0.0) || (y.is_infinite() && x == 0.0) {
15306 feraiseexcept(FE_INVALID);
15307 return f64::NAN;
15308 }
15309 if x.is_nan() || y.is_nan() || z.is_nan() {
15310 return f64::NAN;
15311 }
15312 let r = libm::fma(x, y, z);
15313 if r.is_nan() {
15315 feraiseexcept(FE_INVALID);
15316 }
15317 r
15318}
15319
15320#[no_mangle]
15321pub unsafe extern "C" fn ilogb(x: f64) -> i32 {
15322 if x.is_nan() {
15323 feraiseexcept(FE_INVALID);
15324 return -0x7fffffff - 1; }
15326 if x == 0.0 || x.is_infinite() {
15327 feraiseexcept(FE_INVALID);
15328 return if x == 0.0 { -0x7fffffff - 1 } else { 0x7fffffff };
15329 }
15330 let bits = x.to_bits();
15331 let exp = ((bits >> 52) & 0x7ff) as i32;
15332 if exp == 0 {
15333 let mut v = bits & 0xfffffffffffff;
15335 let mut e = -1022;
15336 while v < (1u64 << 52) { v <<= 1; e -= 1; }
15337 e
15338 } else {
15339 exp - 1023
15340 }
15341}
15342
15343#[no_mangle]
15344pub unsafe extern "C" fn logb(x: f64) -> f64 {
15345 if x.is_nan() { return x; }
15346 if x == 0.0 { return __math_divzero(1); }
15347 let bits = x.to_bits();
15348 let exp = ((bits >> 52) & 0x7ff) as i32;
15349 if exp == 0 {
15350 let mut v = bits & 0xfffffffffffff;
15352 let mut e = -1022i32;
15353 while v < (1u64 << 52) { v <<= 1; e -= 1; }
15354 e as f64
15355 } else if exp == 0x7ff {
15356 x * x } else {
15358 (exp - 1023) as f64
15359 }
15360}
15361
15362#[no_mangle]
15363pub unsafe extern "C" fn nearbyint(x: f64) -> f64 {
15364 let had_inexact = fetestexcept(FE_INEXACT) & FE_INEXACT != 0;
15365 let r = libm::rint(x);
15366 if !had_inexact {
15367 feclearexcept(FE_INEXACT);
15368 }
15369 r
15370}
15371
15372#[no_mangle]
15373pub unsafe extern "C" fn nextafter(x: f64, y: f64) -> f64 {
15374 if x.is_nan() || y.is_nan() { return x + y; }
15375 if x == 0.0 && y == 0.0 { return y; }
15376 if x == y { return x; }
15377 let r = libm::nextafter(x, y);
15378 if r.is_infinite() && x.is_finite() {
15379 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
15380 } else if r != x {
15381 let bits = r.to_bits();
15382 let is_subnormal = (bits & 0x7ff0000000000000) == 0 && (bits & 0xfffffffffffff) != 0;
15383 if r == 0.0 || is_subnormal {
15384 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
15385 }
15386 }
15387 r
15388}
15389
15390#[no_mangle]
15391pub unsafe extern "C" fn nexttoward(x: f64, y: f64) -> f64 {
15392 if x == 0.0 && y == 0.0 {
15394 return if y.is_sign_negative() { -0.0 } else { 0.0 };
15395 }
15396 nextafter(x, y)
15397}
15398
15399#[no_mangle]
15400pub unsafe extern "C" fn remainder(x: f64, y: f64) -> f64 {
15401 if x.is_nan() || y.is_nan() { return x + y; }
15402 if y == 0.0 || x.is_infinite() { return __math_invalid(x); }
15403 libm::remainder(x, y)
15404}
15405
15406#[no_mangle]
15407pub unsafe extern "C" fn remquo(x: f64, y: f64, quo: *mut i32) -> f64 {
15408 if x.is_nan() || y.is_nan() {
15409 if !quo.is_null() { *quo = 0; }
15410 return x + y;
15411 }
15412 if y == 0.0 || x.is_infinite() {
15413 if !quo.is_null() { *quo = 0; }
15414 return __math_invalid(x);
15415 }
15416 let (r, q) = libm::remquo(x, y);
15417 if !quo.is_null() { *quo = q; }
15418 r
15419}
15420
15421#[no_mangle]
15422pub unsafe extern "C" fn exp2(x: f64) -> f64 {
15423 exp2_impl(x)
15424}
15425
15426#[no_mangle]
15427pub unsafe extern "C" fn expm1(x: f64) -> f64 {
15428 let r = libm::expm1(x);
15429 if r != 0.0 && x != 0.0 && libm::fabs(x) < 1e-307 {
15431 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
15432 }
15433 r
15434}
15435
15436#[no_mangle]
15437pub unsafe extern "C" fn log1p(x: f64) -> f64 {
15438 if x == -1.0 {
15439 feraiseexcept(FE_DIVBYZERO);
15440 return f64::NEG_INFINITY;
15441 }
15442 libm::log1p(x)
15443}
15444
15445#[no_mangle]
15446pub unsafe extern "C" fn acosh(x: f64) -> f64 {
15447 if x < 1.0 {
15448 feraiseexcept(FE_INVALID);
15449 return f64::NAN;
15450 }
15451 libm::acosh(x)
15452}
15453
15454#[no_mangle]
15455pub unsafe extern "C" fn asinh(x: f64) -> f64 {
15456 if x == 0.0 { return x; }
15457 libm::asinh(x)
15458}
15459
15460#[no_mangle]
15461pub unsafe extern "C" fn atanh(x: f64) -> f64 {
15462 if x == 0.0 { return x; }
15463 let e = ((x.to_bits() >> 52) & 0x7ff) as i32;
15464 if e < 0x3ff - 32 {
15465 feraiseexcept(FE_INEXACT);
15466 if e == 0 { feraiseexcept(FE_UNDERFLOW); }
15467 return x;
15468 }
15469 if x == 1.0 {
15470 feraiseexcept(FE_DIVBYZERO);
15471 return f64::INFINITY;
15472 }
15473 if x == -1.0 {
15474 feraiseexcept(FE_DIVBYZERO);
15475 return f64::NEG_INFINITY;
15476 }
15477 if x.is_nan() { return x; }
15478 let ax = libm::fabs(x);
15479 if ax > 1.0 {
15480 feraiseexcept(FE_INVALID);
15481 return f64::NAN;
15482 }
15483 if ax < 0.5 {
15484 let r = libm::log1p(2.0 * (ax + ax * ax / (1.0 - ax))) / 2.0;
15486 if x < 0.0 { -r } else { r }
15487 } else {
15488 let r = 0.5 * libm::log((1.0 + ax) / (1.0 - ax));
15490 if x < 0.0 { -r } else { r }
15491 }
15492}
15493
15494#[no_mangle]
15495pub unsafe extern "C" fn cbrt(x: f64) -> f64 {
15496 libm::cbrt(x)
15497}
15498
15499#[no_mangle]
15500pub unsafe extern "C" fn erf(x: f64) -> f64 {
15501 erf_impl(x)
15502}
15503
15504#[no_mangle]
15505pub unsafe extern "C" fn erfc(x: f64) -> f64 {
15506 erfc_impl(x)
15507}
15508
15509#[no_mangle]
15510pub unsafe extern "C" fn lgamma(x: f64) -> f64 {
15511 lgamma_impl(x)
15512}
15513
15514#[no_mangle]
15515pub unsafe extern "C" fn tgamma(x: f64) -> f64 {
15516 tgamma_impl(x)
15517}
15518
15519#[no_mangle]
15520pub unsafe extern "C" fn lround(x: f64) -> core::ffi::c_long {
15521 libm::round(x) as core::ffi::c_long
15522}
15523
15524#[no_mangle]
15525pub unsafe extern "C" fn llround(x: f64) -> i64 {
15526 libm::round(x) as i64
15527}
15528
15529#[no_mangle]
15536pub unsafe extern "C" fn cabs(z: (f64, f64)) -> f64 {
15537 libm::sqrt(z.0 * z.0 + z.1 * z.1)
15538}
15539
15540#[no_mangle]
15541pub unsafe extern "C" fn cabsf(z: (f32, f32)) -> f32 {
15542 libm::sqrtf(z.0 * z.0 + z.1 * z.1)
15543}
15544
15545#[no_mangle]
15546pub unsafe extern "C" fn cabsl(z: (f64, f64)) -> f64 {
15547 cabs(z)
15548}
15549
15550#[no_mangle]
15551pub unsafe extern "C" fn carg(z: (f64, f64)) -> f64 {
15552 libm::atan2(z.1, z.0)
15553}
15554
15555#[no_mangle]
15556pub unsafe extern "C" fn cargf(z: (f32, f32)) -> f32 {
15557 libm::atan2f(z.1, z.0)
15558}
15559
15560#[no_mangle]
15561pub unsafe extern "C" fn cargl(z: (f64, f64)) -> f64 {
15562 carg(z)
15563}
15564
15565#[no_mangle]
15566pub unsafe extern "C" fn cimag(z: (f64, f64)) -> f64 {
15567 z.1
15568}
15569
15570#[no_mangle]
15571pub unsafe extern "C" fn cimagf(z: (f32, f32)) -> f32 {
15572 z.1
15573}
15574
15575#[no_mangle]
15576pub unsafe extern "C" fn cimagl(z: (f64, f64)) -> f64 {
15577 z.1
15578}
15579
15580#[no_mangle]
15581pub unsafe extern "C" fn creal(z: (f64, f64)) -> f64 {
15582 z.0
15583}
15584
15585#[no_mangle]
15586pub unsafe extern "C" fn crealf(z: (f32, f32)) -> f32 {
15587 z.0
15588}
15589
15590#[no_mangle]
15591pub unsafe extern "C" fn creall(z: (f64, f64)) -> f64 {
15592 z.0
15593}
15594
15595#[no_mangle]
15596pub unsafe extern "C" fn conj(z: (f64, f64)) -> (f64, f64) {
15597 (z.0, -z.1)
15598}
15599
15600#[no_mangle]
15601pub unsafe extern "C" fn conjf(z: (f32, f32)) -> (f32, f32) {
15602 (z.0, -z.1)
15603}
15604
15605#[no_mangle]
15606pub unsafe extern "C" fn conjl(z: (f64, f64)) -> (f64, f64) {
15607 conj(z)
15608}
15609
15610#[no_mangle]
15611pub unsafe extern "C" fn cproj(z: (f64, f64)) -> (f64, f64) {
15612 if z.0.is_infinite() || z.1.is_infinite() {
15613 (f64::INFINITY, if z.1.is_sign_positive() { 0.0 } else { -0.0 })
15614 } else {
15615 z
15616 }
15617}
15618
15619#[no_mangle]
15620pub unsafe extern "C" fn cprojf(z: (f32, f32)) -> (f32, f32) {
15621 if z.0.is_infinite() || z.1.is_infinite() {
15622 (f32::INFINITY, if z.1.is_sign_positive() { 0.0 } else { -0.0 })
15623 } else {
15624 z
15625 }
15626}
15627
15628#[no_mangle]
15629pub unsafe extern "C" fn cprojl(z: (f64, f64)) -> (f64, f64) {
15630 cproj(z)
15631}
15632
15633#[no_mangle]
15635pub unsafe extern "C" fn cexp(z: (f64, f64)) -> (f64, f64) {
15636 let r = libm::exp(z.0);
15637 (r * libm::cos(z.1), r * libm::sin(z.1))
15638}
15639
15640#[no_mangle]
15641pub unsafe extern "C" fn cexpf(z: (f32, f32)) -> (f32, f32) {
15642 let r = libm::expf(z.0);
15643 (r * libm::cosf(z.1), r * libm::sinf(z.1))
15644}
15645
15646#[no_mangle]
15647pub unsafe extern "C" fn cexpl(z: (f64, f64)) -> (f64, f64) {
15648 cexp(z)
15649}
15650
15651#[no_mangle]
15653pub unsafe extern "C" fn clog(z: (f64, f64)) -> (f64, f64) {
15654 (libm::log(cabs(z)), carg(z))
15655}
15656
15657#[no_mangle]
15658pub unsafe extern "C" fn clogf(z: (f32, f32)) -> (f32, f32) {
15659 (libm::logf(cabsf(z)), cargf(z))
15660}
15661
15662#[no_mangle]
15663pub unsafe extern "C" fn clogl(z: (f64, f64)) -> (f64, f64) {
15664 clog(z)
15665}
15666
15667#[no_mangle]
15669pub unsafe extern "C" fn csqrt(z: (f64, f64)) -> (f64, f64) {
15670 let r = cabs(z);
15671 let sign = if z.1 < 0.0 { -1.0 } else { 1.0 };
15672 (libm::sqrt((r + z.0) / 2.0), sign * libm::sqrt((r - z.0) / 2.0))
15673}
15674
15675#[no_mangle]
15676pub unsafe extern "C" fn csqrtf(z: (f32, f32)) -> (f32, f32) {
15677 let r = cabsf(z);
15678 let sign = if z.1 < 0.0 { -1.0f32 } else { 1.0f32 };
15679 (libm::sqrtf((r + z.0) / 2.0), sign * libm::sqrtf((r - z.0) / 2.0))
15680}
15681
15682#[no_mangle]
15683pub unsafe extern "C" fn csqrtl(z: (f64, f64)) -> (f64, f64) {
15684 csqrt(z)
15685}
15686
15687#[no_mangle]
15689pub unsafe extern "C" fn cpow(z: (f64, f64), w: (f64, f64)) -> (f64, f64) {
15690 let log_z = clog(z);
15691 let exp_arg = (w.0 * log_z.0 - w.1 * log_z.1, w.0 * log_z.1 + w.1 * log_z.0);
15692 cexp(exp_arg)
15693}
15694
15695#[no_mangle]
15696pub unsafe extern "C" fn cpowf(z: (f32, f32), w: (f32, f32)) -> (f32, f32) {
15697 let log_z = clogf(z);
15698 let exp_arg = (w.0 * log_z.0 - w.1 * log_z.1, w.0 * log_z.1 + w.1 * log_z.0);
15699 cexpf(exp_arg)
15700}
15701
15702#[no_mangle]
15703pub unsafe extern "C" fn cpowl(z: (f64, f64), w: (f64, f64)) -> (f64, f64) {
15704 cpow(z, w)
15705}
15706
15707#[no_mangle]
15709pub unsafe extern "C" fn ccos(z: (f64, f64)) -> (f64, f64) {
15710 (libm::cos(z.0) * libm::cosh(z.1), -libm::sin(z.0) * libm::sinh(z.1))
15711}
15712
15713#[no_mangle]
15714pub unsafe extern "C" fn ccosf(z: (f32, f32)) -> (f32, f32) {
15715 (libm::cosf(z.0) * libm::coshf(z.1), -libm::sinf(z.0) * libm::sinhf(z.1))
15716}
15717
15718#[no_mangle]
15719pub unsafe extern "C" fn ccosl(z: (f64, f64)) -> (f64, f64) {
15720 ccos(z)
15721}
15722
15723#[no_mangle]
15725pub unsafe extern "C" fn csin(z: (f64, f64)) -> (f64, f64) {
15726 (libm::sin(z.0) * libm::cosh(z.1), libm::cos(z.0) * libm::sinh(z.1))
15727}
15728
15729#[no_mangle]
15730pub unsafe extern "C" fn csinf(z: (f32, f32)) -> (f32, f32) {
15731 (libm::sinf(z.0) * libm::coshf(z.1), libm::cosf(z.0) * libm::sinhf(z.1))
15732}
15733
15734#[no_mangle]
15735pub unsafe extern "C" fn csinl(z: (f64, f64)) -> (f64, f64) {
15736 csin(z)
15737}
15738
15739#[no_mangle]
15741pub unsafe extern "C" fn ctan(z: (f64, f64)) -> (f64, f64) {
15742 let d = libm::cos(2.0 * z.0) + libm::cosh(2.0 * z.1);
15743 (libm::sin(2.0 * z.0) / d, libm::sinh(2.0 * z.1) / d)
15744}
15745
15746#[no_mangle]
15747pub unsafe extern "C" fn ctanf(z: (f32, f32)) -> (f32, f32) {
15748 let d = libm::cosf(2.0 * z.0) + libm::coshf(2.0 * z.1);
15749 (libm::sinf(2.0 * z.0) / d, libm::sinhf(2.0 * z.1) / d)
15750}
15751
15752#[no_mangle]
15753pub unsafe extern "C" fn ctanl(z: (f64, f64)) -> (f64, f64) {
15754 ctan(z)
15755}
15756
15757#[no_mangle]
15759pub unsafe extern "C" fn ccosh(z: (f64, f64)) -> (f64, f64) {
15760 (libm::cosh(z.0) * libm::cos(z.1), libm::sinh(z.0) * libm::sin(z.1))
15761}
15762
15763#[no_mangle]
15764pub unsafe extern "C" fn ccoshf(z: (f32, f32)) -> (f32, f32) {
15765 (libm::coshf(z.0) * libm::cosf(z.1), libm::sinhf(z.0) * libm::sinf(z.1))
15766}
15767
15768#[no_mangle]
15769pub unsafe extern "C" fn ccoshl(z: (f64, f64)) -> (f64, f64) {
15770 ccosh(z)
15771}
15772
15773#[no_mangle]
15775pub unsafe extern "C" fn csinh(z: (f64, f64)) -> (f64, f64) {
15776 (libm::sinh(z.0) * libm::cos(z.1), libm::cosh(z.0) * libm::sin(z.1))
15777}
15778
15779#[no_mangle]
15780pub unsafe extern "C" fn csinhf(z: (f32, f32)) -> (f32, f32) {
15781 (libm::sinhf(z.0) * libm::cosf(z.1), libm::coshf(z.0) * libm::sinf(z.1))
15782}
15783
15784#[no_mangle]
15785pub unsafe extern "C" fn csinhl(z: (f64, f64)) -> (f64, f64) {
15786 csinh(z)
15787}
15788
15789#[no_mangle]
15791pub unsafe extern "C" fn ctanh(z: (f64, f64)) -> (f64, f64) {
15792 let d = libm::cosh(2.0 * z.0) + libm::cos(2.0 * z.1);
15793 (libm::sinh(2.0 * z.0) / d, libm::sin(2.0 * z.1) / d)
15794}
15795
15796#[no_mangle]
15797pub unsafe extern "C" fn ctanhf(z: (f32, f32)) -> (f32, f32) {
15798 let d = libm::coshf(2.0 * z.0) + libm::cosf(2.0 * z.1);
15799 (libm::sinhf(2.0 * z.0) / d, libm::sinf(2.0 * z.1) / d)
15800}
15801
15802#[no_mangle]
15803pub unsafe extern "C" fn ctanhl(z: (f64, f64)) -> (f64, f64) {
15804 ctanh(z)
15805}
15806
15807#[no_mangle]
15810pub unsafe extern "C" fn cacos(z: (f64, f64)) -> (f64, f64) {
15811 let asin_z = casin(z);
15812 (3.14159265358979323846264338327950288419716939937510582097494459230781640 / 2.0 - asin_z.0, -asin_z.1)
15813}
15814
15815#[no_mangle]
15816pub unsafe extern "C" fn cacosf(z: (f32, f32)) -> (f32, f32) {
15817 let asin_z = casinf(z);
15818 (3.14159265358979323846264338327950288419716939937510582097494459230781640f32 / 2.0 - asin_z.0, -asin_z.1)
15819}
15820
15821#[no_mangle]
15822pub unsafe extern "C" fn cacosl(z: (f64, f64)) -> (f64, f64) {
15823 cacos(z)
15824}
15825
15826#[no_mangle]
15828pub unsafe extern "C" fn casin(z: (f64, f64)) -> (f64, f64) {
15829 let iz = (-z.1, z.0);
15831 let one_minus_z2 = (1.0 - z.0 * z.0 + z.1 * z.1, -2.0 * z.0 * z.1);
15833 let sqrt_val = csqrt(one_minus_z2);
15834 let arg = clog((iz.0 + sqrt_val.0, iz.1 + sqrt_val.1));
15835 (arg.1, -arg.0)
15837}
15838
15839#[no_mangle]
15840pub unsafe extern "C" fn casinf(z: (f32, f32)) -> (f32, f32) {
15841 let iz = (-z.1, z.0);
15842 let one_minus_z2 = (1.0 - z.0 * z.0 + z.1 * z.1, -2.0 * z.0 * z.1);
15843 let sqrt_val = csqrtf(one_minus_z2);
15844 let arg = clogf((iz.0 + sqrt_val.0, iz.1 + sqrt_val.1));
15845 (arg.1, -arg.0)
15846}
15847
15848#[no_mangle]
15849pub unsafe extern "C" fn casinl(z: (f64, f64)) -> (f64, f64) {
15850 casin(z)
15851}
15852
15853#[no_mangle]
15855pub unsafe extern "C" fn catan(z: (f64, f64)) -> (f64, f64) {
15856 let num = (1.0 + z.1, -z.0);
15860 let den = (1.0 - z.1, z.0);
15861 let ratio = cdiv(num, den);
15862 let log_ratio = clog(ratio);
15863 (-log_ratio.1 / 2.0, log_ratio.0 / 2.0)
15865}
15866
15867#[no_mangle]
15868pub unsafe extern "C" fn catanf(z: (f32, f32)) -> (f32, f32) {
15869 let num = (1.0 + z.1, -z.0);
15870 let den = (1.0 - z.1, z.0);
15871 let ratio = cdivf(num, den);
15872 let log_ratio = clogf(ratio);
15873 (-log_ratio.1 / 2.0, log_ratio.0 / 2.0)
15874}
15875
15876#[no_mangle]
15877pub unsafe extern "C" fn catanl(z: (f64, f64)) -> (f64, f64) {
15878 catan(z)
15879}
15880
15881fn cdiv(a: (f64, f64), b: (f64, f64)) -> (f64, f64) {
15883 let d = b.0 * b.0 + b.1 * b.1;
15884 ((a.0 * b.0 + a.1 * b.1) / d, (a.1 * b.0 - a.0 * b.1) / d)
15885}
15886
15887fn cdivf(a: (f32, f32), b: (f32, f32)) -> (f32, f32) {
15888 let d = b.0 * b.0 + b.1 * b.1;
15889 ((a.0 * b.0 + a.1 * b.1) / d, (a.1 * b.0 - a.0 * b.1) / d)
15890}
15891
15892#[no_mangle]
15894pub unsafe extern "C" fn cacosh(z: (f64, f64)) -> (f64, f64) {
15895 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
15896 let z2_minus_1 = (z2.0 - 1.0, z2.1);
15897 let sqrt_val = csqrt(z2_minus_1);
15898 clog((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
15899}
15900
15901#[no_mangle]
15902pub unsafe extern "C" fn cacoshf(z: (f32, f32)) -> (f32, f32) {
15903 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
15904 let z2_minus_1 = (z2.0 - 1.0, z2.1);
15905 let sqrt_val = csqrtf(z2_minus_1);
15906 clogf((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
15907}
15908
15909#[no_mangle]
15910pub unsafe extern "C" fn cacoshl(z: (f64, f64)) -> (f64, f64) {
15911 cacosh(z)
15912}
15913
15914#[no_mangle]
15916pub unsafe extern "C" fn casinh(z: (f64, f64)) -> (f64, f64) {
15917 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
15918 let z2_plus_1 = (z2.0 + 1.0, z2.1);
15919 let sqrt_val = csqrt(z2_plus_1);
15920 clog((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
15921}
15922
15923#[no_mangle]
15924pub unsafe extern "C" fn casinhf(z: (f32, f32)) -> (f32, f32) {
15925 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
15926 let z2_plus_1 = (z2.0 + 1.0, z2.1);
15927 let sqrt_val = csqrtf(z2_plus_1);
15928 clogf((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
15929}
15930
15931#[no_mangle]
15932pub unsafe extern "C" fn casinhl(z: (f64, f64)) -> (f64, f64) {
15933 casinh(z)
15934}
15935
15936#[no_mangle]
15938pub unsafe extern "C" fn catanh(z: (f64, f64)) -> (f64, f64) {
15939 let num = (1.0 + z.0, z.1);
15940 let den = (1.0 - z.0, -z.1);
15941 let ratio = cdiv(num, den);
15942 let log_ratio = clog(ratio);
15943 (log_ratio.0 / 2.0, log_ratio.1 / 2.0)
15944}
15945
15946#[no_mangle]
15947pub unsafe extern "C" fn catanhf(z: (f32, f32)) -> (f32, f32) {
15948 let num = (1.0 + z.0, z.1);
15949 let den = (1.0 - z.0, -z.1);
15950 let ratio = cdivf(num, den);
15951 let log_ratio = clogf(ratio);
15952 (log_ratio.0 / 2.0, log_ratio.1 / 2.0)
15953}
15954
15955#[no_mangle]
15956pub unsafe extern "C" fn catanhl(z: (f64, f64)) -> (f64, f64) {
15957 catanh(z)
15958}
15959
15960#[inline(never)]
15965#[no_mangle]
15966pub unsafe extern "C" fn fmaxf(x: f32, y: f32) -> f32 {
15967 fmaxf_impl(x, y)
15968}
15969
15970#[no_mangle]
15971pub unsafe extern "C" fn fdimf(x: f32, y: f32) -> f32 {
15972 if x.is_nan() || y.is_nan() {
15973 return f32::NAN;
15974 }
15975 if x > y { x - y } else { 0.0 }
15976}
15977
15978#[no_mangle]
15979pub unsafe extern "C" fn fmaf(x: f32, y: f32, z: f32) -> f32 {
15980 if (x.is_infinite() && y == 0.0) || (y.is_infinite() && x == 0.0) {
15981 feraiseexcept(FE_INVALID);
15982 return f32::NAN;
15983 }
15984 if x.is_nan() || y.is_nan() || z.is_nan() {
15985 return f32::NAN;
15986 }
15987 let r = libm::fmaf(x, y, z);
15988 if r.is_nan() {
15989 feraiseexcept(FE_INVALID);
15990 }
15991 r
15992}
15993
15994#[no_mangle]
15995pub unsafe extern "C" fn ilogbf(x: f32) -> i32 {
15996 if x.is_nan() {
15997 feraiseexcept(FE_INVALID);
15998 return -0x7fffffff - 1;
15999 }
16000 if x == 0.0 || x.is_infinite() {
16001 feraiseexcept(FE_INVALID);
16002 return if x == 0.0 { -0x7fffffff - 1 } else { 0x7fffffff };
16003 }
16004 let bits = x.to_bits();
16005 let exp = ((bits >> 23) & 0xff) as i32;
16006 if exp == 0 {
16007 let mut v = bits & 0x7fffff;
16008 let mut e = -126;
16009 while v < (1u32 << 23) { v <<= 1; e -= 1; }
16010 e
16011 } else {
16012 exp - 127
16013 }
16014}
16015
16016#[no_mangle]
16017pub unsafe extern "C" fn logbf(x: f32) -> f32 {
16018 if x.is_nan() { return x; }
16019 if x == 0.0 { return __math_divzerof(1); }
16020 let bits = x.to_bits();
16021 let exp = ((bits >> 23) & 0xff) as i32;
16022 if exp == 0 {
16023 let mut v = bits & 0x7fffff;
16024 let mut e = -126i32;
16025 while v < (1u32 << 23) { v <<= 1; e -= 1; }
16026 e as f32
16027 } else if exp == 0xff {
16028 x * x
16029 } else {
16030 (exp - 127) as f32
16031 }
16032}
16033
16034#[no_mangle]
16035pub unsafe extern "C" fn nearbyintf(x: f32) -> f32 {
16036 let had_inexact = fetestexcept(FE_INEXACT) & FE_INEXACT != 0;
16037 let r = libm::rintf(x);
16038 if !had_inexact {
16039 feclearexcept(FE_INEXACT);
16040 }
16041 r
16042}
16043
16044#[no_mangle]
16045pub unsafe extern "C" fn nextafterf(x: f32, y: f32) -> f32 {
16046 if x.is_nan() || y.is_nan() { return x + y; }
16047 if x == 0.0 && y == 0.0 { return y; }
16048 if x == y { return x; }
16049 let r = libm::nextafterf(x, y);
16050 if r.is_infinite() && x.is_finite() {
16051 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
16052 } else if r != x {
16053 let bits = r.to_bits();
16054 let is_subnormal = (bits & 0x7f800000) == 0 && (bits & 0x7fffff) != 0;
16055 if r == 0.0 || is_subnormal {
16056 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16057 }
16058 }
16059 r
16060}
16061
16062#[no_mangle]
16063#[cfg(target_arch = "x86_64")]
16064pub unsafe extern "C" fn nexttowardf(x: f32, y: f64) -> f32 {
16065 if y.is_nan() { return (x as f64 + y) as f32; }
16066 if x == 0.0 && y == 0.0 {
16067 return if y.is_sign_negative() { -0.0 } else { 0.0 };
16068 }
16069 if (x as f64) == y { return x; }
16070 nextafterf(x, if y > x as f64 { f32::INFINITY } else { f32::NEG_INFINITY })
16071}
16072
16073#[no_mangle]
16074#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
16075pub unsafe extern "C" fn nexttowardf(x: f32, y: f128) -> f32 {
16076 if y.is_nan() { return (x as f128 + y) as f32; }
16077 if (x as f128) == y { return x; }
16078 nextafterf(x, if y > x as f128 { f32::INFINITY } else { f32::NEG_INFINITY })
16079}
16080
16081#[no_mangle]
16082pub unsafe extern "C" fn remainderf(x: f32, y: f32) -> f32 {
16083 if x.is_nan() || y.is_nan() { return x + y; }
16084 if y == 0.0 || x.is_infinite() { return __math_invalidf(x); }
16085 libm::remainderf(x, y)
16086}
16087
16088#[no_mangle]
16089pub unsafe extern "C" fn remquof(x: f32, y: f32, quo: *mut i32) -> f32 {
16090 if x.is_nan() || y.is_nan() {
16091 if !quo.is_null() { *quo = 0; }
16092 return x + y;
16093 }
16094 if y == 0.0 || x.is_infinite() {
16095 if !quo.is_null() { *quo = 0; }
16096 return __math_invalidf(x);
16097 }
16098 let (r, q) = libm::remquof(x, y);
16099 if !quo.is_null() { *quo = q; }
16100 r
16101}
16102
16103#[no_mangle]
16104pub unsafe extern "C" fn exp2f(x: f32) -> f32 {
16105 if x == f32::INFINITY { return f32::INFINITY; }
16106 if x == f32::NEG_INFINITY { return 0.0; }
16107 if x.is_nan() { return f32::NAN; }
16108 let r = libm::exp2f(x);
16109 if r.is_infinite() && x.is_finite() {
16110 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
16111 } else if r == 0.0 && x < -149.0 {
16112 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16113 } else if r != 0.0 && x != libm::truncf(x) {
16114 let bits = r.to_bits();
16115 if (bits & 0x7f800000) == 0 {
16116 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16117 }
16118 }
16119 r
16120}
16121
16122#[no_mangle]
16123pub unsafe extern "C" fn expm1f(x: f32) -> f32 {
16124 libm::expm1f(x)
16125}
16126
16127#[no_mangle]
16128pub unsafe extern "C" fn log1pf(x: f32) -> f32 {
16129 if x == -1.0 {
16130 feraiseexcept(FE_DIVBYZERO);
16131 return f32::NEG_INFINITY;
16132 }
16133 libm::log1pf(x)
16134}
16135
16136#[no_mangle]
16137pub unsafe extern "C" fn acoshf(x: f32) -> f32 {
16138 if x < 1.0 {
16139 feraiseexcept(FE_INVALID);
16140 return f32::NAN;
16141 }
16142 libm::acoshf(x)
16143}
16144
16145#[no_mangle]
16146pub unsafe extern "C" fn asinhf(x: f32) -> f32 {
16147 if x == 0.0 { return x; }
16148 libm::asinhf(x)
16149}
16150
16151#[no_mangle]
16152pub unsafe extern "C" fn atanhf(x: f32) -> f32 {
16153 if x == 0.0 { return x; }
16154 let e = ((x.to_bits() >> 23) & 0xff) as i32;
16155 if e < 0x7f - 32 {
16156 feraiseexcept(FE_INEXACT);
16157 if e == 0 { feraiseexcept(FE_UNDERFLOW); }
16158 return x;
16159 }
16160 if x == 1.0 {
16161 feraiseexcept(FE_DIVBYZERO);
16162 return f32::INFINITY;
16163 }
16164 if x == -1.0 {
16165 feraiseexcept(FE_DIVBYZERO);
16166 return f32::NEG_INFINITY;
16167 }
16168 if x.is_nan() { return x; }
16169 let ax = libm::fabsf(x);
16170 if ax > 1.0 {
16171 feraiseexcept(FE_INVALID);
16172 return f32::NAN;
16173 }
16174 if ax < 0.5 {
16175 let r = libm::log1pf(2.0 * (ax + ax * ax / (1.0 - ax))) / 2.0;
16176 if x < 0.0 { -r } else { r }
16177 } else {
16178 let r = 0.5 * libm::logf((1.0 + ax) / (1.0 - ax));
16179 if x < 0.0 { -r } else { r }
16180 }
16181}
16182
16183#[no_mangle]
16184pub unsafe extern "C" fn cbrtf(x: f32) -> f32 {
16185 libm::cbrtf(x)
16186}
16187
16188#[no_mangle]
16189pub unsafe extern "C" fn erff(x: f32) -> f32 {
16190 libm::erff(x)
16191}
16192
16193#[no_mangle]
16194pub unsafe extern "C" fn erfcf(x: f32) -> f32 {
16195 libm::erfcf(x)
16196}
16197
16198#[no_mangle]
16199pub unsafe extern "C" fn lgammaf(x: f32) -> f32 {
16200 if x.is_nan() {
16201 crate::signgam = 1;
16202 return x;
16203 }
16204 if x == 0.0 {
16205 crate::signgam = if x.is_sign_negative() { -1 } else { 1 };
16206 feraiseexcept(FE_DIVBYZERO);
16207 return f32::INFINITY;
16208 }
16209 let (r, sign) = libm::lgammaf_r(x);
16210 crate::signgam = sign;
16211 r
16212}
16213
16214#[no_mangle]
16215pub unsafe extern "C" fn tgammaf(x: f32) -> f32 {
16216 if x.is_nan() { return x; }
16217 if x == 0.0 {
16218 feraiseexcept(FE_DIVBYZERO);
16219 return if x.is_sign_negative() { f32::NEG_INFINITY } else { f32::INFINITY };
16220 }
16221 if x.is_infinite() {
16222 return if x.is_sign_negative() { __math_invalidf(x) } else { f32::INFINITY };
16223 }
16224 if x < 0.0 && x == libm::floorf(x) {
16225 feraiseexcept(FE_INVALID);
16226 return f32::NAN;
16227 }
16228 libm::tgammaf(x)
16229}
16230
16231#[no_mangle]
16232pub unsafe extern "C" fn lroundf(x: f32) -> core::ffi::c_long {
16233 libm::roundf(x) as core::ffi::c_long
16234}
16235
16236#[no_mangle]
16237pub unsafe extern "C" fn llroundf(x: f32) -> i64 {
16238 libm::roundf(x) as i64
16239}
16240
16241#[no_mangle]
16246pub unsafe extern "C" fn wcscasecmp(s1: *const u32, s2: *const u32) -> i32 {
16247 let mut i = 0;
16248 loop {
16249 let c1 = *s1.add(i);
16250 let c2 = *s2.add(i);
16251 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16252 let l1 = if c1 >= 'A' as u32 && c1 <= 'Z' as u32 { c1 + 32 } else { c1 };
16253 let l2 = if c2 >= 'A' as u32 && c2 <= 'Z' as u32 { c2 + 32 } else { c2 };
16254 if l1 != l2 { return (l1 as i32) - (l2 as i32); }
16255 i += 1;
16256 }
16257}
16258
16259#[no_mangle]
16260pub unsafe extern "C" fn wcscasecmp_l(s1: *const u32, s2: *const u32, _loc: *mut core::ffi::c_void) -> i32 {
16261 wcscasecmp(s1, s2)
16262}
16263
16264#[no_mangle]
16265pub unsafe extern "C" fn wcsncasecmp(s1: *const u32, s2: *const u32, n: usize) -> i32 {
16266 let mut i = 0;
16267 while i < n {
16268 let c1 = *s1.add(i);
16269 let c2 = *s2.add(i);
16270 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16271 let l1 = if c1 >= 'A' as u32 && c1 <= 'Z' as u32 { c1 + 32 } else { c1 };
16272 let l2 = if c2 >= 'A' as u32 && c2 <= 'Z' as u32 { c2 + 32 } else { c2 };
16273 if l1 != l2 { return (l1 as i32) - (l2 as i32); }
16274 i += 1;
16275 }
16276 0
16277}
16278
16279#[no_mangle]
16280pub unsafe extern "C" fn wcsncasecmp_l(s1: *const u32, s2: *const u32, n: usize, _loc: *mut core::ffi::c_void) -> i32 {
16281 wcsncasecmp(s1, s2, n)
16282}
16283
16284#[no_mangle]
16285pub unsafe extern "C" fn wcscoll(s1: *const u32, s2: *const u32) -> i32 {
16286 let mut i = 0;
16288 loop {
16289 let c1 = *s1.add(i);
16290 let c2 = *s2.add(i);
16291 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16292 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
16293 i += 1;
16294 }
16295}
16296
16297#[no_mangle]
16298pub unsafe extern "C" fn wcstok(s: *mut u32, sep: *const u32, p: *mut *mut u32) -> *mut u32 {
16299 let mut src = if s.is_null() { *p } else { s };
16300 while *src != 0 && *sep.add(0) == *src { src = src.add(1); }
16302 if *src == 0 { return core::ptr::null_mut(); }
16303 let start = src;
16304 while *src != 0 && *sep.add(0) != *src { src = src.add(1); }
16306 if *src != 0 {
16307 *src = 0;
16308 *p = src.add(1);
16309 } else {
16310 *p = src;
16311 }
16312 start
16313}
16314
16315#[no_mangle]
16316pub unsafe extern "C" fn wcswcs(haystack: *const u32, needle: *const u32) -> *mut u32 {
16317 if *needle == 0 { return haystack as *mut u32; }
16318 let mut i = 0;
16319 while *haystack.add(i) != 0 {
16320 let mut j = 0;
16321 while *needle.add(j) != 0 && *haystack.add(i + j) == *needle.add(j) {
16322 j += 1;
16323 }
16324 if *needle.add(j) == 0 { return haystack.add(i) as *mut u32; }
16325 i += 1;
16326 }
16327 core::ptr::null_mut()
16328}
16329
16330#[no_mangle]
16331pub unsafe extern "C" fn wcswidth(s: *const u32, n: usize) -> i32 {
16332 let mut width = 0i32;
16333 let mut i = 0;
16334 while i < n {
16335 let c = *s.add(i);
16336 if c == 0 { break; }
16337 width += 1;
16339 i += 1;
16340 }
16341 width
16342}
16343
16344#[no_mangle]
16345pub unsafe extern "C" fn wcsftime(s: *mut u32, maxsize: usize, fmt: *const u32, tm: *const c_void) -> usize {
16346 if s.is_null() || fmt.is_null() || maxsize == 0 { return 0; }
16347 let mut cfmt = [0u8; 1024];
16350 let mut o = 0usize;
16351 let mut i = 0usize;
16352 let mut st: c_uint = 0;
16353 while *fmt.add(i) != 0 && o + 8 < cfmt.len() {
16354 let n = wcrtomb(
16355 cfmt.as_mut_ptr().add(o) as *mut c_char,
16356 *fmt.add(i) as c_int,
16357 &mut st as *mut c_uint,
16358 );
16359 if n == !0usize { return 0; }
16360 o += n;
16361 i += 1;
16362 }
16363 cfmt[o] = 0;
16364 let mut out = [0u8; 4096];
16365 let mut lim = maxsize.saturating_mul(4);
16366 if lim > out.len() { lim = out.len(); }
16367 let n = strftime(out.as_mut_ptr() as *mut c_char, lim, cfmt.as_ptr() as *const c_char, tm as *const tm);
16368 if n == 0 { return 0; }
16369 let mut ws = 0usize;
16370 let mut p = 0usize;
16371 while p < n && ws + 1 < maxsize {
16372 let mut wc: c_int = 0;
16373 let mut st2: c_uint = 0;
16374 let r = mbrtowc(&mut wc, out.as_ptr().add(p) as *const c_char, n - p, &mut st2);
16375 if r == !0usize { return 0; }
16376 if r == 0 || r == !1usize { break; }
16377 *s.add(ws) = wc as u32;
16378 ws += 1;
16379 p += r;
16380 }
16381 *s.add(ws) = 0;
16382 ws
16383}
16384
16385#[no_mangle]
16386pub unsafe extern "C" fn mbsnrtowcs(
16387 dst: *mut u32,
16388 src: *mut *const u8,
16389 nms: usize,
16390 len: usize,
16391 st: *mut core::ffi::c_void,
16392) -> usize {
16393 if src.is_null() { return 0; }
16394 let mut s = *src;
16395 if s.is_null() { return 0; }
16396 let state = st as *mut c_uint;
16397 let limit = if dst.is_null() { usize::MAX } else { len };
16398 let mut count = 0usize;
16399 let mut n = nms;
16400 while count < limit && n > 0 {
16401 let c = *s;
16402 if c == 0 {
16403 if !dst.is_null() {
16404 if count < len { *dst.add(count) = 0; }
16405 *src = core::ptr::null();
16406 }
16407 return count;
16408 }
16409 let mut wc: c_int = 0;
16410 let r = mbrtowc(&mut wc, s as *const c_char, n, state);
16411 if r == !0usize {
16412 *src = s;
16413 return !0usize;
16414 }
16415 if r == !1usize { break; }
16416 if !dst.is_null() { *dst.add(count) = wc as u32; }
16417 count += 1;
16418 s = s.add(r);
16419 n -= r;
16420 }
16421 *src = s;
16422 count
16423}
16424
16425#[no_mangle]
16426pub unsafe extern "C" fn wcsnrtombs(dst: *mut u8, src: *mut *const u32, nwc: usize, len: usize, _st: *mut core::ffi::c_void) -> usize {
16427 let mut count = 0;
16428 let mut s = *src;
16429 let mut d = dst;
16430 while count < len && count < nwc {
16431 let c = *s;
16432 if c == 0 { break; }
16433 if !d.is_null() {
16434 if c < 0x80 {
16435 *d = c as u8;
16436 d = d.add(1);
16437 count += 1;
16438 } else if c < 0x800 {
16439 if count + 2 > len { break; }
16440 *d = 0xc0 | (c >> 6) as u8;
16441 *d.add(1) = 0x80 | (c & 0x3f) as u8;
16442 d = d.add(2);
16443 count += 2;
16444 } else if c < 0x10000 {
16445 if count + 3 > len { break; }
16446 *d = 0xe0 | (c >> 12) as u8;
16447 *d.add(1) = 0x80 | ((c >> 6) & 0x3f) as u8;
16448 *d.add(2) = 0x80 | (c & 0x3f) as u8;
16449 d = d.add(3);
16450 count += 3;
16451 } else {
16452 if count + 4 > len { break; }
16453 *d = 0xf0 | (c >> 18) as u8;
16454 *d.add(1) = 0x80 | ((c >> 12) & 0x3f) as u8;
16455 *d.add(2) = 0x80 | ((c >> 6) & 0x3f) as u8;
16456 *d.add(3) = 0x80 | (c & 0x3f) as u8;
16457 d = d.add(4);
16458 count += 4;
16459 }
16460 }
16461 s = s.add(1);
16462 }
16463 if !dst.is_null() { *src = s; }
16464 count
16465}
16466
16467pub type thrd_start_t = Option<unsafe extern "C" fn(arg: *mut core::ffi::c_void) -> i32>;
16474
16475#[no_mangle]
16477pub unsafe extern "C" fn thrd_create(thr: *mut usize, func: thrd_start_t, arg: *mut core::ffi::c_void) -> i32 {
16478 let mut thread: u64 = 0;
16479 let r = pthread_create(&mut thread, core::ptr::null(), core::mem::transmute(func), arg);
16480 if r == 0 {
16481 *thr = thread as usize;
16482 0 } else {
16484 -1 }
16486}
16487
16488#[no_mangle]
16489pub unsafe extern "C" fn thrd_join(thr: usize, res: *mut i32) -> i32 {
16490 let mut retval: *mut core::ffi::c_void = core::ptr::null_mut();
16491 let r = pthread_join(thr as u64, &mut retval);
16492 if r == 0 {
16493 if !res.is_null() { *res = retval as i32; }
16494 0
16495 } else {
16496 -1
16497 }
16498}
16499
16500#[no_mangle]
16501pub unsafe extern "C" fn thrd_exit(res: i32) {
16502 pthread_exit(res as *mut core::ffi::c_void);
16503}
16504
16505#[no_mangle]
16506pub unsafe extern "C" fn thrd_detach(thr: usize) -> i32 {
16507 let r = pthread_detach(thr as u64);
16508 if r == 0 { 0 } else { -1 }
16509}
16510
16511#[no_mangle]
16512pub unsafe extern "C" fn thrd_current() -> usize {
16513 pthread_self() as usize
16514}
16515
16516#[no_mangle]
16517pub unsafe extern "C" fn thrd_equal(thr1: usize, thr2: usize) -> i32 {
16518 (thr1 == thr2) as i32
16519}
16520
16521#[no_mangle]
16522pub unsafe extern "C" fn thrd_sleep(duration: *const core::ffi::c_void, remaining: *mut core::ffi::c_void) -> i32 {
16523 nanosleep(duration as *const timespec, remaining as *mut timespec)
16524}
16525
16526#[no_mangle]
16527pub unsafe extern "C" fn thrd_yield() {
16528 sched_yield();
16529}
16530
16531#[no_mangle]
16533pub unsafe extern "C" fn mtx_init(mtx: *mut usize, _mtx_type: i32) -> i32 {
16534 let r = pthread_mutex_init(mtx as *mut pthread_mutex_t, core::ptr::null());
16535 if r == 0 { 0 } else { -1 }
16536}
16537
16538#[no_mangle]
16539pub unsafe extern "C" fn mtx_lock(mtx: *mut usize) -> i32 {
16540 let r = pthread_mutex_lock(mtx as *mut pthread_mutex_t);
16541 if r == 0 { 0 } else { -1 }
16542}
16543
16544#[no_mangle]
16545pub unsafe extern "C" fn mtx_trylock(mtx: *mut usize) -> i32 {
16546 let r = pthread_mutex_trylock(mtx as *mut pthread_mutex_t);
16547 if r == 0 { 0 } else { -1 }
16548}
16549
16550#[no_mangle]
16551pub unsafe extern "C" fn mtx_unlock(mtx: *mut usize) -> i32 {
16552 let r = pthread_mutex_unlock(mtx as *mut pthread_mutex_t);
16553 if r == 0 { 0 } else { -1 }
16554}
16555
16556#[no_mangle]
16557pub unsafe extern "C" fn mtx_destroy(mtx: *mut usize) {
16558 pthread_mutex_destroy(mtx as *mut pthread_mutex_t);
16559}
16560
16561#[no_mangle]
16562pub unsafe extern "C" fn mtx_timedlock(mtx: *mut usize, ts: *const core::ffi::c_void) -> i32 {
16563 let r = pthread_mutex_timedlock(mtx as *mut pthread_mutex_t, ts as *const timespec);
16564 if r == 0 { 0 } else { -1 }
16565}
16566
16567#[no_mangle]
16569pub unsafe extern "C" fn cnd_init(cnd: *mut usize) -> i32 {
16570 let r = pthread_cond_init(cnd as *mut pthread_cond_t, core::ptr::null());
16571 if r == 0 { 0 } else { -1 }
16572}
16573
16574#[no_mangle]
16575pub unsafe extern "C" fn cnd_signal(cnd: *mut usize) -> i32 {
16576 let r = pthread_cond_signal(cnd as *mut pthread_cond_t);
16577 if r == 0 { 0 } else { -1 }
16578}
16579
16580#[no_mangle]
16581pub unsafe extern "C" fn cnd_broadcast(cnd: *mut usize) -> i32 {
16582 let r = pthread_cond_broadcast(cnd as *mut pthread_cond_t);
16583 if r == 0 { 0 } else { -1 }
16584}
16585
16586#[no_mangle]
16587pub unsafe extern "C" fn cnd_wait(cnd: *mut usize, mtx: *mut usize) -> i32 {
16588 let r = pthread_cond_wait(cnd as *mut pthread_cond_t, mtx as *mut pthread_mutex_t);
16589 if r == 0 { 0 } else { -1 }
16590}
16591
16592#[no_mangle]
16593pub unsafe extern "C" fn cnd_timedwait(cnd: *mut usize, mtx: *mut usize, ts: *const core::ffi::c_void) -> i32 {
16594 let r = pthread_cond_timedwait(cnd as *mut pthread_cond_t, mtx as *mut pthread_mutex_t, ts as *const timespec);
16595 if r == 0 { 0 } else { -1 }
16596}
16597
16598#[no_mangle]
16599pub unsafe extern "C" fn cnd_destroy(cnd: *mut usize) {
16600 pthread_cond_destroy(cnd as *mut pthread_cond_t);
16601}
16602
16603#[no_mangle]
16605pub unsafe extern "C" fn tss_create(key: *mut u32, dtor: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>) -> i32 {
16606 let r = pthread_key_create(key, dtor);
16607 if r == 0 { 0 } else { -1 }
16608}
16609
16610#[no_mangle]
16611pub unsafe extern "C" fn tss_delete(key: u32) {
16612 pthread_key_delete(key);
16613}
16614
16615#[no_mangle]
16616pub unsafe extern "C" fn tss_set(key: u32, val: *mut core::ffi::c_void) -> i32 {
16617 let r = pthread_setspecific(key, val);
16618 if r == 0 { 0 } else { -1 }
16619}
16620
16621#[no_mangle]
16622pub unsafe extern "C" fn tss_get(key: u32) -> *mut core::ffi::c_void {
16623 pthread_getspecific(key)
16624}
16625
16626#[no_mangle]
16628pub unsafe extern "C" fn call_once(flag: *mut u32, func: Option<unsafe extern "C" fn()>) {
16629 if *flag == 0 {
16630 if let Some(f) = func { f(); }
16631 *flag = 1;
16632 }
16633}
16634
16635#[no_mangle]
16641pub unsafe extern "C" fn accept4(fd: i32, addr: *mut core::ffi::c_void, addrlen: *mut u32, flags: i32) -> i32 {
16642 syscall_ret(<Arch as Syscalls>::syscall4(SYS_ACCEPT4, fd as i64, addr as i64, addrlen as i64, flags as i64)) as i32
16643}
16644
16645#[no_mangle]
16651pub unsafe extern "C" fn epoll_create(size: i32) -> i32 {
16652 #[cfg(target_arch = "x86_64")]
16653 { syscall_ret(<Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE, size as i64)) as i32 }
16654 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
16655 {
16656 if size < 1 {
16657 ERRNO!() = EINVAL;
16658 return -1;
16659 }
16660 syscall_ret(<Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE1, 0)) as i32
16661 }
16662}
16663
16664#[no_mangle]
16665pub unsafe extern "C" fn epoll_create1(flags: i32) -> i32 {
16666 syscall_ret(<Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE1, flags as i64)) as i32
16667}
16668
16669#[no_mangle]
16670pub unsafe extern "C" fn epoll_ctl(epfd: i32, op: i32, fd: i32, event: *mut core::ffi::c_void) -> i32 {
16671 syscall_ret(<Arch as Syscalls>::syscall4(SYS_EPOLL_CTL, epfd as i64, op as i64, fd as i64, event as i64)) as i32
16672}
16673
16674#[no_mangle]
16675pub unsafe extern "C" fn epoll_wait(epfd: i32, events: *mut core::ffi::c_void, maxevents: i32, timeout: i32) -> i32 {
16676 #[cfg(target_arch = "x86_64")]
16677 {
16678 syscall_ret(<Arch as Syscalls>::syscall4(
16679 SYS_EPOLL_WAIT,
16680 epfd as i64,
16681 events as i64,
16682 maxevents as i64,
16683 timeout as i64,
16684 )) as i32
16685 }
16686 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
16687 {
16688 epoll_pwait(epfd, events, maxevents, timeout, core::ptr::null())
16689 }
16690}
16691
16692#[no_mangle]
16693pub unsafe extern "C" fn epoll_pwait(
16694 epfd: i32,
16695 events: *mut core::ffi::c_void,
16696 maxevents: i32,
16697 timeout: i32,
16698 sigmask: *const u64,
16699) -> i32 {
16700 syscall_ret(<Arch as Syscalls>::syscall6(
16701 SYS_EPOLL_PWAIT,
16702 epfd as i64,
16703 events as i64,
16704 maxevents as i64,
16705 timeout as i64,
16706 sigmask as i64,
16707 8,
16708 )) as i32
16709}
16710
16711#[no_mangle]
16712pub unsafe extern "C" fn eventfd(initval: u32, flags: i32) -> i32 {
16713 syscall_ret(<Arch as Syscalls>::syscall2(SYS_EVENTFD2, initval as i64, flags as i64)) as i32
16714}
16715
16716#[no_mangle]
16717pub unsafe extern "C" fn eventfd_read(fd: i32, value: *mut u64) -> i32 {
16718 let n = crate::read(fd, value as *mut core::ffi::c_void, 8);
16719 if n == 8 { 0 } else { -1 }
16720}
16721
16722#[no_mangle]
16723pub unsafe extern "C" fn eventfd_write(fd: i32, value: u64) -> i32 {
16724 let n = crate::write(fd, &value as *const u64 as *const core::ffi::c_void, 8);
16725 if n == 8 { 0 } else { -1 }
16726}
16727
16728#[no_mangle]
16729pub unsafe extern "C" fn signalfd(fd: i32, mask: *const u64, flags: i32) -> i32 {
16730 syscall_ret(<Arch as Syscalls>::syscall4(SYS_SIGNALFD4, fd as i64, mask as i64, 8, flags as i64)) as i32
16731}
16732
16733#[no_mangle]
16734pub unsafe extern "C" fn timerfd_create(clockid: i32, flags: i32) -> i32 {
16735 syscall_ret(<Arch as Syscalls>::syscall2(SYS_TIMERFD_CREATE, clockid as i64, flags as i64)) as i32
16736}
16737
16738#[no_mangle]
16739pub 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 {
16740 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
16741}
16742
16743#[no_mangle]
16744pub unsafe extern "C" fn timerfd_gettime(fd: i32, curr_value: *mut core::ffi::c_void) -> i32 {
16745 syscall_ret(<Arch as Syscalls>::syscall2(SYS_TIMERFD_GETTIME, fd as i64, curr_value as i64)) as i32
16746}
16747
16748#[no_mangle]
16753pub unsafe extern "C" fn prctl(option: i32, mut args: ...) -> i32 {
16754 let a1 = args.next_arg::<i64>();
16755 let a2 = args.next_arg::<i64>();
16756 let a3 = args.next_arg::<i64>();
16757 let a4 = args.next_arg::<i64>();
16758 syscall_ret(<Arch as Syscalls>::syscall5(SYS_PRCTL, option as i64, a1, a2, a3, a4)) as i32
16759}
16760
16761#[no_mangle]
16762pub unsafe extern "C" fn quotactl(cmd: i32, special: *const core::ffi::c_char, id: i32, addr: *mut core::ffi::c_char) -> i32 {
16763 syscall_ret(<Arch as Syscalls>::syscall4(sysno(179, 60), cmd as i64, special as i64, id as i64, addr as i64)) as i32
16764}
16765
16766#[no_mangle]
16767pub unsafe extern "C" fn klogctl(type_: i32, bufp: *mut core::ffi::c_char, len: i32) -> i32 {
16768 syscall_ret(<Arch as Syscalls>::syscall3(sysno(103, 116), type_ as i64, bufp as i64, len as i64)) as i32
16769}
16770
16771static mut SYSLOG_IDENT: [core::ffi::c_char; 64] = [0; 64];
16772static mut SYSLOG_OPTIONS: i32 = 0;
16773static mut SYSLOG_FACILITY: i32 = 1;
16774
16775#[no_mangle]
16776pub unsafe extern "C" fn openlog(ident: *const core::ffi::c_char, option: i32, facility: i32) {
16777 SYSLOG_OPTIONS = option;
16778 SYSLOG_FACILITY = facility & 0x3f8;
16779 SYSLOG_IDENT[0] = 0;
16780 if !ident.is_null() {
16781 let mut i = 0;
16782 while i < 63 && *ident.add(i) != 0 {
16783 SYSLOG_IDENT[i] = *ident.add(i);
16784 i += 1;
16785 }
16786 SYSLOG_IDENT[i] = 0;
16787 }
16788}
16789
16790#[repr(C)]
16791struct SockAddrUn {
16792 sun_family: u16,
16793 sun_path: [core::ffi::c_char; 108],
16794}
16795
16796unsafe fn syslog_emit(priority: i32, msg: *const core::ffi::c_char, len: usize) {
16797 let mut out = [0u8; 1200];
16798 let mut o = 0usize;
16799 let pri = (SYSLOG_FACILITY | (priority & 7)) as u32;
16800 out[o] = b'<'; o += 1;
16801 if pri >= 100 { out[o] = b'0' + (pri / 100) as u8; o += 1; }
16802 if pri >= 10 { out[o] = b'0' + ((pri / 10) % 10) as u8; o += 1; }
16803 out[o] = b'0' + (pri % 10) as u8; o += 1;
16804 out[o] = b'>'; o += 1;
16805 let mut i = 0;
16806 while i < 63 && SYSLOG_IDENT[i] != 0 && o + 1 < out.len() {
16807 out[o] = SYSLOG_IDENT[i] as u8; o += 1; i += 1;
16808 }
16809 if SYSLOG_OPTIONS & 1 != 0 {
16810 out[o] = b'['; o += 1;
16811 let mut pid = crate::getpid() as u32;
16812 let mut digits = [0u8; 10];
16813 let mut d = 0;
16814 if pid == 0 { digits[0] = b'0'; d = 1; }
16815 while pid > 0 { digits[d] = b'0' + (pid % 10) as u8; pid /= 10; d += 1; }
16816 while d > 0 { d -= 1; out[o] = digits[d]; o += 1; }
16817 out[o] = b']'; o += 1;
16818 }
16819 out[o] = b':'; o += 1; out[o] = b' '; o += 1;
16820 let copy = core::cmp::min(len, out.len() - o - 1);
16821 core::ptr::copy_nonoverlapping(msg as *const u8, out.as_mut_ptr().add(o), copy);
16822 o += copy;
16823 let fd = crate::socket(AF_UNIX, SOCK_DGRAM, 0);
16824 if fd >= 0 {
16825 let mut sa: SockAddrUn = core::mem::zeroed();
16826 sa.sun_family = AF_UNIX as u16;
16827 let path = b"/dev/log";
16828 for i in 0..path.len() { sa.sun_path[i] = path[i] as core::ffi::c_char; }
16829 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);
16830 crate::close(fd);
16831 if r >= 0 { return; }
16832 }
16833 crate::write(2, out.as_ptr() as *const core::ffi::c_void, o);
16834 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
16835}
16836
16837#[no_mangle]
16838pub unsafe extern "C" fn vsyslog(priority: c_int, fmt: *const c_char, ap: VaList) {
16839 let mut msg = [0 as c_char; 1024];
16840 let n = vsnprintf(msg.as_mut_ptr(), msg.len(), fmt, ap);
16841 if n > 0 { syslog_emit(priority, msg.as_ptr(), core::cmp::min(n as usize, msg.len() - 1)); }
16842}
16843
16844#[no_mangle]
16845pub unsafe extern "C" fn syslog(priority: c_int, fmt: *const c_char, args: ...) {
16846 vsyslog(priority, fmt, args);
16847}
16848
16849#[no_mangle]
16850pub unsafe extern "C" fn closelog() {
16851 }
16853
16854#[no_mangle]
16855pub unsafe extern "C" fn setlogmask(mask: i32) -> i32 {
16856 static mut LOG_MASK: i32 = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80;
16857 let old = LOG_MASK;
16858 if mask != 0 { LOG_MASK = mask; }
16859 old
16860}
16861
16862#[no_mangle]
16863pub unsafe extern "C" fn acct(filename: *const core::ffi::c_char) -> i32 {
16864 syscall_ret(<Arch as Syscalls>::syscall1(SYS_ACCT, filename as i64)) as i32
16865}
16866
16867#[no_mangle]
16868pub unsafe extern "C" fn swapon(path: *const core::ffi::c_char, flags: i32) -> i32 {
16869 syscall_ret(<Arch as Syscalls>::syscall2(SYS_SWAPON, path as i64, flags as i64)) as i32
16870}
16871
16872#[no_mangle]
16873pub unsafe extern "C" fn swapoff(path: *const core::ffi::c_char) -> i32 {
16874 syscall_ret(<Arch as Syscalls>::syscall1(SYS_SWAPOFF, path as i64)) as i32
16875}
16876
16877#[no_mangle]
16878pub unsafe extern "C" fn syncfs(fd: i32) -> i32 {
16879 syscall_ret(<Arch as Syscalls>::syscall1(SYS_SYNCFS, fd as i64)) as i32
16880}
16881
16882#[no_mangle]
16883pub unsafe extern "C" fn sync_file_range(fd: i32, offset: i64, nbytes: u64, flags: u32) -> i32 {
16884 syscall_ret(<Arch as Syscalls>::syscall4(sysno(277, 84), fd as i64, offset, nbytes as i64, flags as i64)) as i32
16885}
16886
16887#[no_mangle]
16888pub unsafe extern "C" fn posix_fadvise(fd: i32, offset: i64, len: u64, advice: i32) -> i32 {
16889 let r = <Arch as Syscalls>::syscall4(sysno(221, 223), fd as i64, offset, len as i64, advice as i64);
16891 if r < 0 { (-r) as i32 } else { 0 }
16892}
16893
16894#[no_mangle]
16895pub unsafe extern "C" fn posix_fallocate(fd: i32, offset: i64, len: u64) -> i32 {
16896 let r = <Arch as Syscalls>::syscall3(SYS_FALLOCATE, fd as i64, offset, len as i64);
16897 if r < 0 { (-r) as i32 } else { 0 }
16898}
16899
16900#[no_mangle]
16901pub unsafe extern "C" fn readahead(fd: i32, offset: i64, count: usize) -> isize {
16902 syscall_ret(<Arch as Syscalls>::syscall3(sysno(187, 213), fd as i64, offset, count as i64)) as isize
16905}
16906
16907#[no_mangle]
16908pub unsafe extern "C" fn fallocate(fd: i32, mode: i32, offset: i64, len: u64) -> i32 {
16909 syscall_ret(<Arch as Syscalls>::syscall4(SYS_FALLOCATE, fd as i64, mode as i64, offset, len as i64)) as i32
16910}
16911
16912#[no_mangle]
16917pub unsafe extern "C" fn tcgetattr(fd: i32, termios_p: *mut core::ffi::c_void) -> i32 {
16918 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5401, termios_p as i64)) as i32
16919}
16920
16921#[no_mangle]
16922pub unsafe extern "C" fn tcsetattr(fd: i32, optional_actions: i32, termios_p: *const core::ffi::c_void) -> i32 {
16923 let cmd = match optional_actions {
16924 0 => 0x5402,
16925 1 => 0x5403,
16926 2 => 0x5404,
16927 _ => 0x5402,
16928 };
16929 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, cmd, termios_p as i64)) as i32
16930}
16931
16932#[no_mangle]
16933pub unsafe extern "C" fn tcdrain(fd: i32) -> i32 {
16934 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5409, 1)) as i32
16935}
16936
16937#[no_mangle]
16938pub unsafe extern "C" fn tcflush(fd: i32, queue_selector: i32) -> i32 {
16939 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540B, queue_selector as i64)) as i32
16940}
16941
16942#[no_mangle]
16943pub unsafe extern "C" fn tcflow(fd: i32, action: i32) -> i32 {
16944 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540A, action as i64)) as i32
16945}
16946
16947#[no_mangle]
16948pub unsafe extern "C" fn tcsendbreak(fd: i32, duration: i32) -> i32 {
16949 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5425, duration as i64)) as i32
16950}
16951
16952#[no_mangle]
16953pub unsafe extern "C" fn tcgetsid(fd: i32) -> i32 {
16954 let mut sid: i32 = 0;
16955 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5429, &mut sid as *mut i32 as i64);
16956 if r < 0 { -1 } else { sid }
16957}
16958
16959#[no_mangle]
16960pub unsafe extern "C" fn tcgetpgrp(fd: i32) -> i32 {
16961 let mut pgrp: i32 = 0;
16962 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540F, &mut pgrp as *mut i32 as i64);
16963 if r < 0 { -1 } else { pgrp }
16964}
16965
16966#[no_mangle]
16967pub unsafe extern "C" fn tcsetpgrp(fd: i32, pgrp: i32) -> i32 {
16968 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5410, &pgrp as *const i32 as i64)) as i32
16969}
16970
16971#[no_mangle]
16982pub unsafe extern "C" fn mq_open(name: *const core::ffi::c_char, oflag: i32, mut args: ...) -> i32 {
16983 if name.is_null() { ERRNO!() = EINVAL; return -1; }
16984 let mut p = name as *const u8;
16985 if *p == b'/' { p = p.add(1); }
16986 let mut mode: u32 = 0;
16987 let mut attr: *const core::ffi::c_void = core::ptr::null();
16988 if oflag & 0o100 != 0 {
16989 mode = args.next_arg::<u32>();
16990 attr = args.next_arg::<*const core::ffi::c_void>();
16991 }
16992 syscall_ret(<Arch as Syscalls>::syscall4(
16993 sysno(240, 180),
16994 p as i64,
16995 oflag as i64,
16996 mode as i64,
16997 attr as i64,
16998 )) as i32
16999}
17000
17001#[no_mangle]
17002pub unsafe extern "C" fn mq_close(mqdes: i32) -> i32 {
17003 crate::close(mqdes as i32)
17004}
17005
17006#[no_mangle]
17007pub unsafe extern "C" fn mq_unlink(name: *const core::ffi::c_char) -> i32 {
17008 if name.is_null() { ERRNO!() = EINVAL; return -1; }
17009 let mut p = name as *const u8;
17010 if *p == b'/' { p = p.add(1); }
17011 let r = <Arch as Syscalls>::syscall1(sysno(241, 181), p as i64);
17012 if r < 0 {
17013 let e = if (-r) as c_int == 1 { 13 } else { (-r) as c_int };
17015 ERRNO!() = e;
17016 -1
17017 } else {
17018 0
17019 }
17020}
17021
17022#[no_mangle]
17023pub unsafe extern "C" fn mq_send(mqdes: i32, msg_ptr: *const core::ffi::c_char, msg_len: usize, msg_prio: u32) -> i32 {
17024 mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, core::ptr::null())
17025}
17026
17027#[no_mangle]
17028pub unsafe extern "C" fn mq_receive(mqdes: i32, msg_ptr: *mut core::ffi::c_char, msg_len: usize, msg_prio: *mut u32) -> isize {
17029 mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, core::ptr::null())
17030}
17031
17032#[no_mangle]
17033pub unsafe extern "C" fn mq_timedsend(
17034 mqdes: i32,
17035 msg_ptr: *const core::ffi::c_char,
17036 msg_len: usize,
17037 msg_prio: u32,
17038 abs_timeout: *const core::ffi::c_void,
17039) -> i32 {
17040 syscall_ret(<Arch as Syscalls>::syscall5(
17041 sysno(242, 182),
17042 mqdes as i64,
17043 msg_ptr as i64,
17044 msg_len as i64,
17045 msg_prio as i64,
17046 abs_timeout as i64,
17047 )) as i32
17048}
17049
17050#[no_mangle]
17051pub unsafe extern "C" fn mq_timedreceive(
17052 mqdes: i32,
17053 msg_ptr: *mut core::ffi::c_char,
17054 msg_len: usize,
17055 msg_prio: *mut u32,
17056 abs_timeout: *const core::ffi::c_void,
17057) -> isize {
17058 syscall_ret(<Arch as Syscalls>::syscall5(
17059 sysno(243, 183),
17060 mqdes as i64,
17061 msg_ptr as i64,
17062 msg_len as i64,
17063 msg_prio as i64,
17064 abs_timeout as i64,
17065 )) as isize
17066}
17067
17068#[repr(C)]
17069pub struct SigEventFull {
17070 sigev_value: usize,
17071 sigev_signo: i32,
17072 sigev_notify: i32,
17073 sigev_function: usize,
17074 sigev_attributes: usize,
17075 sigev_pad: [u8; 32],
17076}
17077
17078struct MqNotifyArgs {
17079 sem: sem_t,
17080 sock: i32,
17081 mqd: i32,
17082 err: i32,
17083 func: usize,
17084 value: usize,
17085}
17086
17087unsafe extern "C" fn mq_notify_thread(arg: *mut c_void) -> *mut c_void {
17088 let a = &mut *(arg as *mut MqNotifyArgs);
17089 let sock = a.sock;
17090 let mqd = a.mqd;
17091 let func = a.func;
17092 let value = a.value;
17093 let zeros = [0u8; 32];
17094 let sev2 = SigEventFull {
17095 sigev_value: zeros.as_ptr() as usize,
17096 sigev_signo: sock,
17097 sigev_notify: 2, sigev_function: 0,
17099 sigev_attributes: 0,
17100 sigev_pad: [0; 32],
17101 };
17102 let r = <Arch as Syscalls>::syscall2(sysno(244, 184), mqd as i64, &sev2 as *const SigEventFull as i64);
17103 a.err = if r < 0 { (-r) as i32 } else { 0 };
17104 sem_post(&mut a.sem);
17105 if a.err != 0 { return core::ptr::null_mut(); }
17106 pthread_detach(pthread_self());
17107 let mut buf = [0u8; 32];
17108 let n = recv(sock, buf.as_mut_ptr() as *mut c_void, buf.len(), 0x4000 | 0x100);
17109 crate::close(sock);
17110 if n as usize == buf.len() && buf[buf.len() - 1] == 1 && func != 0 {
17111 let f: extern "C" fn(usize) = core::mem::transmute(func);
17112 f(value);
17113 }
17114 core::ptr::null_mut()
17115}
17116
17117#[no_mangle]
17118pub unsafe extern "C" fn mq_notify(mqdes: i32, sev: *const core::ffi::c_void) -> i32 {
17119 if sev.is_null() {
17120 return syscall_ret(<Arch as Syscalls>::syscall2(sysno(244, 184), mqdes as i64, 0)) as i32;
17121 }
17122 let ev = &*(sev as *const SigEventFull);
17123 if ev.sigev_notify != 2 {
17124 return syscall_ret(<Arch as Syscalls>::syscall2(sysno(244, 184), mqdes as i64, sev as i64)) as i32;
17125 }
17126
17127 let sock = socket(16 , 3 | 0x80000 , 0);
17130 if sock < 0 { return -1; }
17131 let mut a = MqNotifyArgs {
17132 sem: core::mem::zeroed(),
17133 sock,
17134 mqd: mqdes,
17135 err: 0,
17136 func: ev.sigev_function,
17137 value: ev.sigev_value,
17138 };
17139 sem_init(&mut a.sem, 0, 0);
17140
17141 let mut attr: pthread_attr_t = core::mem::zeroed();
17142 if ev.sigev_attributes != 0 {
17143 attr = core::ptr::read(ev.sigev_attributes as *const pthread_attr_t);
17144 } else {
17145 pthread_attr_init(&mut attr);
17146 }
17147 pthread_attr_setdetachstate(&mut attr, PTHREAD_CREATE_JOINABLE);
17148
17149 let mut all: SigSetT = 0;
17150 sigfillset(&mut all);
17151 let mut orig: SigSetT = 0;
17152 pthread_sigmask(0 , &all, &mut orig);
17153
17154 let mut td: PthreadT = 0;
17155 let r = pthread_create(&mut td, &attr, mq_notify_thread as *const () as usize, &mut a as *mut MqNotifyArgs as *mut c_void);
17156 pthread_sigmask(2 , &orig, core::ptr::null_mut());
17157 if r != 0 {
17158 crate::close(sock);
17159 ERRNO!() = 11;
17160 return -1;
17161 }
17162 sem_wait(&mut a.sem);
17163 sem_destroy(&mut a.sem);
17164 if a.err != 0 {
17165 crate::close(sock);
17166 pthread_join(td, core::ptr::null_mut());
17167 ERRNO!() = a.err;
17168 return -1;
17169 }
17170 0
17171}
17172
17173#[no_mangle]
17174pub unsafe extern "C" fn mq_getattr(mqdes: i32, attr: *mut core::ffi::c_void) -> i32 {
17175 mq_setattr(mqdes, core::ptr::null(), attr)
17176}
17177
17178#[no_mangle]
17179pub unsafe extern "C" fn mq_setattr(
17180 mqdes: i32,
17181 new: *const core::ffi::c_void,
17182 old: *mut core::ffi::c_void,
17183) -> i32 {
17184 syscall_ret(<Arch as Syscalls>::syscall3(
17185 sysno(245, 185),
17186 mqdes as i64,
17187 new as i64,
17188 old as i64,
17189 )) as i32
17190}
17191
17192#[no_mangle]
17197pub unsafe extern "C" fn pthread_getaffinity_np(thread: usize, cpusetsize: usize, cpuset: *mut u8) -> i32 {
17198 sched_getaffinity(thread as i32, cpusetsize, cpuset)
17199}
17200
17201#[no_mangle]
17202pub unsafe extern "C" fn pthread_setaffinity_np(thread: usize, cpusetsize: usize, cpuset: *const u8) -> i32 {
17203 sched_setaffinity(thread as i32, cpusetsize, cpuset)
17204}
17205
17206#[no_mangle]
17211pub unsafe extern "C" fn sched_yield() -> i32 {
17212 syscall_ret(<Arch as Syscalls>::syscall0(sysno(24, 124))) as i32
17213}
17214
17215#[no_mangle]
17216pub unsafe extern "C" fn sched_get_priority_max(policy: i32) -> i32 {
17217 syscall_ret(<Arch as Syscalls>::syscall1(sysno(146, 125), policy as i64)) as i32
17218}
17219
17220#[no_mangle]
17221pub unsafe extern "C" fn sched_get_priority_min(policy: i32) -> i32 {
17222 syscall_ret(<Arch as Syscalls>::syscall1(sysno(147, 126), policy as i64)) as i32
17223}
17224
17225#[no_mangle]
17226pub unsafe extern "C" fn sched_getparam(pid: i32, param: *mut core::ffi::c_void) -> i32 {
17227 syscall_ret(<Arch as Syscalls>::syscall2(sysno(143, 121), pid as i64, param as i64)) as i32
17228}
17229
17230#[no_mangle]
17231pub unsafe extern "C" fn sched_setparam(pid: i32, param: *const core::ffi::c_void) -> i32 {
17232 syscall_ret(<Arch as Syscalls>::syscall2(sysno(142, 118), pid as i64, param as i64)) as i32
17233}
17234
17235#[no_mangle]
17236pub unsafe extern "C" fn sched_getscheduler(pid: i32) -> i32 {
17237 syscall_ret(<Arch as Syscalls>::syscall1(sysno(145, 120), pid as i64)) as i32
17238}
17239
17240#[no_mangle]
17241pub unsafe extern "C" fn sched_setscheduler(pid: i32, policy: i32, param: *const core::ffi::c_void) -> i32 {
17242 syscall_ret(<Arch as Syscalls>::syscall3(sysno(144, 119), pid as i64, policy as i64, param as i64)) as i32
17243}
17244
17245#[no_mangle]
17246pub unsafe extern "C" fn sched_setaffinity(pid: i32, cpusetsize: usize, cpuset: *const u8) -> i32 {
17247 syscall_ret(<Arch as Syscalls>::syscall3(sysno(203, 122), pid as i64, cpusetsize as i64, cpuset as i64)) as i32
17248}
17249
17250#[no_mangle]
17251pub unsafe extern "C" fn sched_getaffinity(pid: i32, cpusetsize: usize, cpuset: *mut u8) -> i32 {
17252 let r = <Arch as Syscalls>::syscall3(sysno(204, 123), pid as i64, cpusetsize as i64, cpuset as i64);
17253 if r < 0 {
17254 ERRNO!() = (-r) as c_int;
17255 return -1;
17256 }
17257 0
17259}
17260
17261#[cold]
17262unsafe fn sched_getcpu_syscall(cpu: *mut u32) -> i32 {
17263 let r = <Arch as Syscalls>::syscall3(sysno(309, 168), cpu as i64, 0, 0);
17264 if r == 0 {
17265 core::ptr::read_unaligned(cpu) as i32
17266 } else {
17267 syscall_ret(r) as i32
17268 }
17269}
17270
17271#[no_mangle]
17272pub unsafe extern "C" fn sched_getcpu() -> i32 {
17273 let mut cpu = core::mem::MaybeUninit::<[u64; 2]>::uninit();
17278 let cpu_ptr = cpu.as_mut_ptr() as *mut u32;
17279 if vdso_getcpu(cpu_ptr) {
17280 return core::ptr::read_unaligned(cpu_ptr) as i32;
17281 }
17282 sched_getcpu_syscall(cpu_ptr)
17283}
17284
17285#[no_mangle]
17286pub unsafe extern "C" fn sched_rr_get_interval(pid: i32, tp: *mut core::ffi::c_void) -> i32 {
17287 syscall_ret(<Arch as Syscalls>::syscall2(sysno(148, 127), pid as i64, tp as i64)) as i32
17288}
17289
17290#[no_mangle]
17295pub unsafe extern "C" fn timer_create(clockid: i32, sevp: *mut core::ffi::c_void, timerid: *mut i32) -> i32 {
17296 syscall_ret(<Arch as Syscalls>::syscall3(sysno(222, 107), clockid as i64, sevp as i64, timerid as i64)) as i32
17297}
17298
17299#[no_mangle]
17300pub unsafe extern "C" fn timer_delete(timerid: i32) -> i32 {
17301 syscall_ret(<Arch as Syscalls>::syscall1(sysno(226, 111), timerid as i64)) as i32
17302}
17303
17304#[no_mangle]
17305pub 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 {
17306 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
17307}
17308
17309#[no_mangle]
17310pub unsafe extern "C" fn timer_gettime(timerid: i32, curr_value: *mut core::ffi::c_void) -> i32 {
17311 syscall_ret(<Arch as Syscalls>::syscall2(sysno(224, 108), timerid as i64, curr_value as i64)) as i32
17312}
17313
17314#[no_mangle]
17315pub unsafe extern "C" fn timer_getoverrun(timerid: i32) -> i32 {
17316 syscall_ret(<Arch as Syscalls>::syscall1(sysno(225, 109), timerid as i64)) as i32
17317}
17318
17319#[no_mangle]
17320pub unsafe extern "C" fn clock_adjtime(_clockid: i32, buf: *mut core::ffi::c_void) -> i32 {
17321 syscall_ret(<Arch as Syscalls>::syscall2(SYS_ADJTIMEX, buf as i64, 0)) as i32
17322}
17323
17324#[no_mangle]
17325pub unsafe extern "C" fn clock_getcpuclockid(pid: i32, clockid: *mut i32) -> i32 {
17326 if clockid.is_null() { return EINVAL; }
17327 let id: i32 = ((-(pid as i64) - 1) * 8 + 2) as i32;
17328 let mut ts: timespec = core::mem::zeroed();
17329 let r = <Arch as Syscalls>::syscall2(SYS_CLOCK_GETRES, id as i64, &mut ts as *mut timespec as i64);
17330 if r < 0 {
17331 let e = (-r) as c_int;
17332 return if e == EINVAL { 3 } else { e };
17333 }
17334 *clockid = id;
17335 0
17336}
17337
17338#[no_mangle]
17343pub unsafe extern "C" fn strcoll(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char) -> i32 {
17344 let mut i = 0;
17346 loop {
17347 let c1 = *s1.add(i) as u8;
17348 let c2 = *s2.add(i) as u8;
17349 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
17350 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
17351 i += 1;
17352 }
17353}
17354
17355#[no_mangle]
17356pub unsafe extern "C" fn strxfrm(dest: *mut core::ffi::c_char, src: *const core::ffi::c_char, n: usize) -> usize {
17357 let mut i = 0;
17358 while i < n {
17359 let c = *src.add(i);
17360 *dest.add(i) = c;
17361 if c == 0 { break; }
17362 i += 1;
17363 }
17364 i
17365}
17366
17367#[no_mangle]
17372pub 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 {
17373 let dir = opendir(dirp);
17374 if dir.is_null() { return -1; }
17375 let mut count = 0;
17376 loop {
17377 let ent = readdir(dir);
17378 if ent.is_null() { break; }
17379 count += 1;
17380 }
17381 closedir(dir);
17382 count
17383}
17384
17385#[no_mangle]
17386pub unsafe extern "C" fn alphasort(a: *const *const core::ffi::c_void, b: *const *const core::ffi::c_void) -> i32 {
17387 let s1 = *a as *const core::ffi::c_char;
17388 let s2 = *b as *const core::ffi::c_char;
17389 crate::strcmp(s1 as *const u8, s2 as *const u8)
17390}
17391
17392#[no_mangle]
17393pub unsafe extern "C" fn versionsort(a: *const *const core::ffi::c_void, b: *const *const core::ffi::c_void) -> i32 {
17394 let s1 = *a as *const core::ffi::c_char;
17395 let s2 = *b as *const core::ffi::c_char;
17396 crate::strcmp(s1 as *const u8, s2 as *const u8)
17397}
17398
17399unsafe fn vwarn_impl(fmt: *const c_char, ap: VaList, with_errno: bool) {
17407 let mut buf = [0 as c_char; 1024];
17408 let n = vsnprintf(buf.as_mut_ptr(), buf.len(), fmt, ap);
17409 if n > 0 {
17410 let l = core::cmp::min(n as usize, buf.len() - 1);
17411 crate::write(2, buf.as_ptr() as *const c_void, l);
17412 }
17413 if with_errno {
17414 let e = ERRNO!();
17415 crate::write(2, b": ".as_ptr() as *const c_void, 2);
17416 let msg = strerror(e);
17417 crate::write(2, msg as *const c_void, crate::strlen(msg));
17418 }
17419 crate::write(2, b"\n".as_ptr() as *const c_void, 1);
17420}
17421
17422#[no_mangle]
17423pub unsafe extern "C" fn verr(eval: c_int, fmt: *const c_char, ap: VaList) {
17424 vwarn_impl(fmt, ap, true);
17425 crate::exit(eval);
17426}
17427
17428#[no_mangle]
17429pub unsafe extern "C" fn verrx(eval: c_int, fmt: *const c_char, ap: VaList) {
17430 vwarn_impl(fmt, ap, false);
17431 crate::exit(eval);
17432}
17433
17434#[no_mangle]
17435pub unsafe extern "C" fn vwarn(fmt: *const c_char, ap: VaList) {
17436 vwarn_impl(fmt, ap, true);
17437}
17438
17439#[no_mangle]
17440pub unsafe extern "C" fn vwarnx(fmt: *const c_char, ap: VaList) {
17441 vwarn_impl(fmt, ap, false);
17442}
17443
17444#[no_mangle]
17445pub unsafe extern "C" fn err(eval: c_int, fmt: *const c_char, args: ...) {
17446 verr(eval, fmt, args);
17447}
17448
17449#[no_mangle]
17450pub unsafe extern "C" fn errx(eval: c_int, fmt: *const c_char, args: ...) {
17451 verrx(eval, fmt, args);
17452}
17453
17454#[no_mangle]
17455pub unsafe extern "C" fn warn(fmt: *const c_char, args: ...) {
17456 vwarn(fmt, args);
17457}
17458
17459#[no_mangle]
17460pub unsafe extern "C" fn warnx(fmt: *const c_char, args: ...) {
17461 vwarnx(fmt, args);
17462}
17463
17464#[no_mangle]
17469pub unsafe extern "C" fn ecvt(value: f64, ndigit: i32, decpt: *mut i32, sign: *mut i32) -> *mut core::ffi::c_char {
17470 static mut BUF: [core::ffi::c_char; 80] = [0; 80];
17471 if value < 0.0 { *sign = 1; } else { *sign = 0; }
17472 let v = if value < 0.0 { -value } else { value };
17473 if v == 0.0 { *decpt = 0; BUF[0] = 0; return BUF.as_mut_ptr(); }
17474 let mut d = 0i32;
17475 let mut tmp = v;
17476 while tmp >= 10.0 { tmp /= 10.0; d += 1; }
17477 while tmp < 1.0 { tmp *= 10.0; d -= 1; }
17478 *decpt = d + 1;
17479 let mut i = 0;
17480 let mut val = tmp;
17481 while i < ndigit as usize && i < 79 {
17482 let digit = val as i32;
17483 BUF[i] = (b'0' + digit as u8) as c_char;
17484 val = (val - digit as f64) * 10.0;
17485 i += 1;
17486 }
17487 BUF[i] = 0;
17488 BUF.as_mut_ptr()
17489}
17490
17491#[no_mangle]
17492pub unsafe extern "C" fn fcvt(value: f64, ndigit: i32, decpt: *mut i32, sign: *mut i32) -> *mut core::ffi::c_char {
17493 static mut BUF: [core::ffi::c_char; 80] = [0; 80];
17494 if value < 0.0 { *sign = 1; } else { *sign = 0; }
17495 let v = if value < 0.0 { -value } else { value };
17496 if v == 0.0 { *decpt = 0; BUF[0] = 0; return BUF.as_mut_ptr(); }
17497 let mut d = 0i32;
17498 let mut tmp = v;
17499 while tmp >= 10.0 { tmp /= 10.0; d += 1; }
17500 while tmp < 1.0 { tmp *= 10.0; d -= 1; }
17501 *decpt = d + 1;
17502 let mut val = tmp;
17503 let mut i = 0;
17504 while i < (*decpt) as usize && i < 79 {
17505 let digit = val as i32;
17506 BUF[i] = (b'0' + digit as u8) as c_char;
17507 val = (val - digit as f64) * 10.0;
17508 i += 1;
17509 }
17510 if ndigit > 0 && i < 79 {
17511 BUF[i] = '.' as c_char;
17512 i += 1;
17513 let mut frac = val;
17514 let mut j = 0;
17515 while j < ndigit as usize && i < 79 {
17516 let digit = frac as i32;
17517 BUF[i] = (b'0' + digit as u8) as c_char;
17518 frac = (frac - digit as f64) * 10.0;
17519 i += 1;
17520 j += 1;
17521 }
17522 }
17523 BUF[i] = 0;
17524 BUF.as_mut_ptr()
17525}
17526
17527#[no_mangle]
17528pub unsafe extern "C" fn gcvt(value: f64, _ndigit: i32, buf: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
17529 if value == 0.0 {
17531 *buf = '0' as c_char;
17532 *buf.add(1) = 0;
17533 return buf;
17534 }
17535 let mut i = 0;
17536 let v = if value < 0.0 { *buf = '-' as c_char; i = 1; -value } else { value };
17537 let mut int_part = v as i64;
17539 let mut digits = [0u8; 32];
17540 let mut di = 0;
17541 if int_part == 0 {
17542 digits[0] = 0;
17543 di = 1;
17544 } else {
17545 while int_part > 0 && di < 32 {
17546 digits[di] = (int_part % 10) as u8;
17547 int_part /= 10;
17548 di += 1;
17549 }
17550 }
17551 while di > 0 && i < 79 {
17552 di -= 1;
17553 *buf.add(i) = (b'0' + digits[di]) as c_char;
17554 i += 1;
17555 }
17556 *buf.add(i) = 0;
17557 buf
17558}
17559
17560static mut SHELLS: [*const core::ffi::c_char; 3] = [
17565 b"/bin/sh\0".as_ptr() as *const core::ffi::c_char,
17566 b"/bin/bash\0".as_ptr() as *const core::ffi::c_char,
17567 core::ptr::null(),
17568];
17569static mut SHELL_IDX: usize = 0;
17570
17571#[no_mangle]
17572pub unsafe extern "C" fn getusershell() -> *mut core::ffi::c_char {
17573 let s = SHELLS[SHELL_IDX];
17574 if s.is_null() {
17575 SHELL_IDX = 0;
17576 return core::ptr::null_mut();
17577 }
17578 SHELL_IDX += 1;
17579 s as *mut core::ffi::c_char
17580}
17581
17582#[no_mangle]
17583pub unsafe extern "C" fn setusershell() {
17584 SHELL_IDX = 0;
17585}
17586
17587#[no_mangle]
17588pub unsafe extern "C" fn endusershell() {
17589 SHELL_IDX = 0;
17590}
17591
17592#[no_mangle]
17597pub unsafe extern "C" fn ether_aton(s: *const core::ffi::c_char) -> *mut u8 {
17598 static mut EA: [u8; 6] = [0; 6];
17599 if ether_aton_r(s, EA.as_mut_ptr()).is_null() { core::ptr::null_mut() } else { EA.as_mut_ptr() }
17600}
17601
17602#[no_mangle]
17603pub unsafe extern "C" fn ether_aton_r(s: *const core::ffi::c_char, ea: *mut u8) -> *mut u8 {
17604 if ea.is_null() { return core::ptr::null_mut(); }
17605 let mut i = 0;
17606 let mut j = 0;
17607 let mut val: u32 = 0;
17608 let mut digits = 0;
17609 while *s.add(i) != 0 && j < 6 {
17610 let c = *s.add(i);
17611 if c == ':' as c_char {
17612 if digits == 0 { return core::ptr::null_mut(); }
17613 *ea.add(j) = val as u8;
17614 j += 1;
17615 val = 0;
17616 digits = 0;
17617 } 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) {
17618 let d = if c >= '0' as c_char && c <= '9' as c_char { (c - '0' as c_char) as u32 }
17619 else if c >= 'a' as c_char { (c - 'a' as c_char + 10) as u32 }
17620 else { (c - 'A' as c_char + 10) as u32 };
17621 val = val * 16 + d;
17622 if val > 255 { return core::ptr::null_mut(); }
17623 digits += 1;
17624 if digits > 2 { return core::ptr::null_mut(); }
17625 } else {
17626 return core::ptr::null_mut();
17627 }
17628 i += 1;
17629 }
17630 if digits == 0 || j != 5 { return core::ptr::null_mut(); }
17631 *ea.add(j) = val as u8;
17632 ea
17633}
17634
17635#[no_mangle]
17636pub unsafe extern "C" fn ether_ntoa(ea: *const u8) -> *mut core::ffi::c_char {
17637 static mut BUF: [core::ffi::c_char; 18] = [0; 18];
17638 ether_ntoa_r(ea, BUF.as_mut_ptr());
17639 BUF.as_mut_ptr()
17640}
17641
17642#[no_mangle]
17643pub unsafe extern "C" fn ether_ntoa_r(ea: *const u8, buf: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
17644 let a = *ea.add(0); let b = *ea.add(1); let c = *ea.add(2);
17645 let d = *ea.add(3); let e = *ea.add(4); let f = *ea.add(5);
17646 let hex = b"0123456789abcdef\0".as_ptr() as *const u8;
17647 let mut i = 0;
17648 *buf.add(i) = *hex.add((a >> 4) as usize) as c_char; i += 1;
17649 *buf.add(i) = *hex.add((a & 0xf) as usize) as c_char; i += 1;
17650 *buf.add(i) = ':' as c_char; i += 1;
17651 *buf.add(i) = *hex.add((b >> 4) as usize) as c_char; i += 1;
17652 *buf.add(i) = *hex.add((b & 0xf) as usize) as c_char; i += 1;
17653 *buf.add(i) = ':' as c_char; i += 1;
17654 *buf.add(i) = *hex.add((c >> 4) as usize) as c_char; i += 1;
17655 *buf.add(i) = *hex.add((c & 0xf) as usize) as c_char; i += 1;
17656 *buf.add(i) = ':' as c_char; i += 1;
17657 *buf.add(i) = *hex.add((d >> 4) as usize) as c_char; i += 1;
17658 *buf.add(i) = *hex.add((d & 0xf) as usize) as c_char; i += 1;
17659 *buf.add(i) = ':' as c_char; i += 1;
17660 *buf.add(i) = *hex.add((e >> 4) as usize) as c_char; i += 1;
17661 *buf.add(i) = *hex.add((e & 0xf) as usize) as c_char; i += 1;
17662 *buf.add(i) = ':' as c_char; i += 1;
17663 *buf.add(i) = *hex.add((f >> 4) as usize) as c_char; i += 1;
17664 *buf.add(i) = *hex.add((f & 0xf) as usize) as c_char; i += 1;
17665 *buf.add(i) = 0;
17666 buf
17667}
17668
17669#[no_mangle]
17674pub unsafe extern "C" fn getutxent() -> *mut core::ffi::c_void {
17675 getutent()
17676}
17677
17678#[no_mangle]
17679pub unsafe extern "C" fn getutxid(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
17680 getutid(ut)
17681}
17682
17683#[no_mangle]
17684pub unsafe extern "C" fn getutxline(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
17685 getutline(ut)
17686}
17687
17688#[no_mangle]
17689pub unsafe extern "C" fn pututxline(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
17690 pututline(ut)
17691}
17692
17693#[no_mangle]
17694pub unsafe extern "C" fn setutxent() {
17695 setutent()
17696}
17697
17698#[no_mangle]
17699pub unsafe extern "C" fn endutxent() {
17700 endutent()
17701}
17702
17703#[no_mangle]
17708pub unsafe extern "C" fn execv(path: *const core::ffi::c_char, argv: *const *const core::ffi::c_char) -> i32 {
17709 crate::execve(path, argv, __environ as *const *const core::ffi::c_char)
17710}
17711
17712#[no_mangle]
17713pub unsafe extern "C" fn execlp(file: *const core::ffi::c_char, _args: ...) -> i32 {
17714 let mut cap = 16usize;
17715 let mut argv = malloc(cap * core::mem::size_of::<*const core::ffi::c_char>()) as *mut *const core::ffi::c_char;
17716 if argv.is_null() { ERRNO!() = ENOMEM; return -1; }
17717 let mut i = 0usize;
17718 let mut args = _args;
17719 loop {
17720 let arg = args.next_arg::<*const core::ffi::c_char>();
17721 if arg.is_null() { break; }
17722 if i + 1 >= cap {
17723 cap = match cap.checked_mul(2) { Some(v) => v, None => { free(argv as *mut c_void); ERRNO!() = ENOMEM; return -1; } };
17724 let grown = realloc(argv as *mut c_void, cap * core::mem::size_of::<*const core::ffi::c_char>()) as *mut *const core::ffi::c_char;
17725 if grown.is_null() { free(argv as *mut c_void); ERRNO!() = ENOMEM; return -1; }
17726 argv = grown;
17727 }
17728 *argv.add(i) = arg;
17729 i += 1;
17730 }
17731 *argv.add(i) = core::ptr::null();
17732 let r = execvp(file, argv);
17733 free(argv as *mut c_void);
17734 r
17735}
17736
17737#[no_mangle]
17738pub unsafe extern "C" fn execvp(file: *const core::ffi::c_char, argv: *const *const core::ffi::c_char) -> i32 {
17739 execvpe(file, argv, __environ as *const *const core::ffi::c_char)
17740}
17741
17742#[no_mangle]
17743pub unsafe extern "C" fn fexecve(fd: i32, argv: *const *const core::ffi::c_char, envp: *const *const core::ffi::c_char) -> i32 {
17744 let mut path: [core::ffi::c_char; 64] = [0; 64];
17746 let mut i = 0;
17747 let src = b"/proc/self/fd/\0".as_ptr() as *const core::ffi::c_char;
17748 while i < 63 && *src.add(i) != 0 { path[i] = *src.add(i); i += 1; }
17749 let mut n = fd as usize;
17750 if n == 0 { path[i] = '0' as c_char; i += 1; }
17751 while n > 0 && i < 63 {
17752 path[i] = (b'0' + (n % 10) as u8) as c_char;
17753 n /= 10;
17754 i += 1;
17755 }
17756 path[i] = 0;
17757 crate::execve(path.as_ptr(), argv, envp)
17758}
17759
17760#[no_mangle]
17765pub unsafe extern "C" fn confstr(name: i32, buf: *mut core::ffi::c_char, len: usize) -> usize {
17766 let value: &[u8] = if name == 0 {
17769 b"/bin:/usr/bin"
17770 } else if (1..=37).contains(&name) {
17771 b""
17772 } else {
17773 ERRNO!() = EINVAL;
17774 return 0;
17775 };
17776 let need = value.len() + 1;
17777 if !buf.is_null() && len > 0 {
17778 let n = core::cmp::min(value.len(), len - 1);
17779 core::ptr::copy_nonoverlapping(value.as_ptr(), buf as *mut u8, n);
17780 *buf.add(n) = 0;
17781 }
17782 need
17783}
17784
17785#[no_mangle]
17786pub unsafe extern "C" fn pathconf(_path: *const core::ffi::c_char, name: i32) -> i64 {
17787 match name {
17789 0 => 4096, 1 => 255, 2 => 255, 3 => 255, 4 => 4096, 5 => 4096, 6 => 1, 7 => 0, 8 => 0, _ => -1,
17799 }
17800}
17801
17802#[no_mangle]
17803pub unsafe extern "C" fn fpathconf(_fd: i32, name: i32) -> i64 {
17804 match name {
17806 0 => 4096, 1 => 255, 2 => 255, 3 => 255, 4 => 4096, 5 => 4096, 6 => 1, 7 => 0, 8 => 0, _ => -1,
17816 }
17817}
17818
17819#[no_mangle]
17824pub unsafe extern "C" fn exp10(x: f64) -> f64 {
17825 libm::pow(10.0, x)
17826}
17827
17828#[no_mangle]
17829pub unsafe extern "C" fn exp10f(x: f32) -> f32 {
17830 libm::powf(10.0, x)
17831}
17832
17833#[no_mangle]
17838pub unsafe extern "C" fn explicit_bzero(s: *mut u8, n: usize) {
17839 core::ptr::write_bytes(s, 0, n);
17840 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
17841}
17842
17843#[no_mangle]
17844pub unsafe extern "C" fn memccpy(dest: *mut u8, src: *const u8, c: i32, n: usize) -> *mut u8 {
17845 let mut i = 0;
17846 while i < n {
17847 let byte = *src.add(i);
17848 *dest.add(i) = byte;
17849 if byte == c as u8 {
17850 return dest.add(i + 1);
17851 }
17852 i += 1;
17853 }
17854 core::ptr::null_mut()
17855}
17856
17857#[no_mangle]
17862pub unsafe extern "C" fn faccessat(dirfd: i32, pathname: *const core::ffi::c_char, mode: i32, flags: i32) -> i32 {
17863 syscall_ret(<Arch as Syscalls>::syscall4(SYS_FACCESSAT, dirfd as i64, pathname as i64, mode as i64, flags as i64)) as i32
17864}
17865
17866#[no_mangle]
17867pub unsafe extern "C" fn fchmodat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32, flags: i32) -> i32 {
17868 if flags == 0 {
17869 return syscall_ret(<Arch as Syscalls>::syscall4(SYS_FCHMODAT, dirfd as i64, pathname as i64, mode as i64, 0)) as i32;
17870 }
17871 if flags != 0x100 {
17872 ERRNO!() = EINVAL;
17874 return -1;
17875 }
17876 syscall_ret(<Arch as Syscalls>::syscall4(sysno(452, 452), dirfd as i64, pathname as i64, mode as i64, flags as i64)) as i32
17877}
17878
17879#[no_mangle]
17880pub unsafe extern "C" fn fchownat(dirfd: i32, pathname: *const core::ffi::c_char, uid: u32, gid: u32, flags: i32) -> i32 {
17881 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
17882}
17883
17884#[no_mangle]
17885pub unsafe extern "C" fn linkat(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char, flags: i32) -> i32 {
17886 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
17887}
17888
17889#[no_mangle]
17890pub unsafe extern "C" fn mkdirat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32) -> i32 {
17891 syscall_ret(<Arch as Syscalls>::syscall3(SYS_MKDIRAT, dirfd as i64, pathname as i64, mode as i64)) as i32
17892}
17893
17894#[no_mangle]
17895pub unsafe extern "C" fn mkfifoat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32) -> i32 {
17896 mknodat(dirfd, pathname, mode | 0o010000, 0)
17897}
17898
17899#[no_mangle]
17900pub unsafe extern "C" fn mknodat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32, dev: u64) -> i32 {
17901 syscall_ret(<Arch as Syscalls>::syscall4(sysno(259, 33), dirfd as i64, pathname as i64, mode as i64, dev as i64)) as i32
17902}
17903
17904#[no_mangle]
17905pub unsafe extern "C" fn readlinkat(dirfd: i32, pathname: *const core::ffi::c_char, buf: *mut core::ffi::c_char, bufsiz: usize) -> isize {
17906 syscall_ret(<Arch as Syscalls>::syscall4(SYS_READLINKAT, dirfd as i64, pathname as i64, buf as i64, bufsiz as i64)) as isize
17907}
17908
17909#[no_mangle]
17910pub unsafe extern "C" fn renameat(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char) -> i32 {
17911 syscall_ret(<Arch as Syscalls>::syscall5(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, 0)) as i32
17912}
17913
17914#[no_mangle]
17915pub unsafe extern "C" fn renameat2(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char, flags: u32) -> i32 {
17916 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
17917}
17918
17919#[no_mangle]
17920pub unsafe extern "C" fn symlinkat(target: *const core::ffi::c_char, newdirfd: i32, linkpath: *const core::ffi::c_char) -> i32 {
17921 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, newdirfd as i64, linkpath as i64)) as i32
17922}
17923
17924#[no_mangle]
17925pub unsafe extern "C" fn unlinkat(dirfd: i32, pathname: *const core::ffi::c_char, flags: i32) -> i32 {
17926 syscall_ret(<Arch as Syscalls>::syscall3(SYS_UNLINKAT, dirfd as i64, pathname as i64, flags as i64)) as i32
17927}
17928
17929#[no_mangle]
17930pub unsafe extern "C" fn utimes(filename: *const core::ffi::c_char, times: *const core::ffi::c_void) -> i32 {
17931 utimensat(AT_FDCWD, filename, times as *const timespec, 0)
17932}
17933
17934#[no_mangle]
17935pub unsafe extern "C" fn futimes(fd: i32, times: *const core::ffi::c_void) -> i32 {
17936 utimensat(fd, core::ptr::null(), times as *const timespec, 0)
17937}
17938
17939#[no_mangle]
17944pub unsafe extern "C" fn inotify_init() -> i32 {
17945 syscall_ret(<Arch as Syscalls>::syscall1(sysno(253, 26), 0)) as i32
17946}
17947
17948#[no_mangle]
17949pub unsafe extern "C" fn inotify_init1(flags: i32) -> i32 {
17950 syscall_ret(<Arch as Syscalls>::syscall1(sysno(294, 26), flags as i64)) as i32
17951}
17952
17953#[no_mangle]
17954pub unsafe extern "C" fn inotify_add_watch(fd: i32, pathname: *const core::ffi::c_char, mask: u32) -> i32 {
17955 syscall_ret(<Arch as Syscalls>::syscall3(sysno(254, 27), fd as i64, pathname as i64, mask as i64)) as i32
17956}
17957
17958#[no_mangle]
17959pub unsafe extern "C" fn inotify_rm_watch(fd: i32, wd: i32) -> i32 {
17960 syscall_ret(<Arch as Syscalls>::syscall2(sysno(255, 28), fd as i64, wd as i64)) as i32
17961}
17962
17963#[no_mangle]
17964pub unsafe extern "C" fn fanotify_init(flags: i32, event_f_flags: i32) -> i32 {
17965 syscall_ret(<Arch as Syscalls>::syscall2(sysno(300, 262), flags as i64, event_f_flags as i64)) as i32
17966}
17967
17968#[no_mangle]
17969pub unsafe extern "C" fn fanotify_mark(fd: i32, flags: i32, mask: u64, dirfd: i32, pathname: *const core::ffi::c_char) -> i32 {
17970 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
17971}
17972
17973#[no_mangle]
17978pub unsafe extern "C" fn ffs(x: i32) -> i32 {
17979 if x == 0 { return 0; }
17980 x.trailing_zeros() as i32 + 1
17981}
17982
17983#[no_mangle]
17984pub unsafe extern "C" fn ffsl(x: i64) -> i32 {
17985 if x == 0 { return 0; }
17986 x.trailing_zeros() as i32 + 1
17987}
17988
17989#[no_mangle]
17990pub unsafe extern "C" fn ffsll(x: i64) -> i32 {
17991 if x == 0 { return 0; }
17992 x.trailing_zeros() as i32 + 1
17993}
17994
17995#[no_mangle]
18000pub unsafe extern "C" fn fchdir(fd: i32) -> i32 {
18001 syscall_ret(<Arch as Syscalls>::syscall1(SYS_FCHDIR, fd as i64)) as i32
18002}
18003
18004#[no_mangle]
18005pub unsafe extern "C" fn fchown(fd: i32, uid: u32, gid: u32) -> i32 {
18006 syscall_ret(<Arch as Syscalls>::syscall3(SYS_FCHOWN, fd as i64, uid as i64, gid as i64)) as i32
18007}
18008
18009#[no_mangle]
18010pub unsafe extern "C" fn fdopendir(fd: i32) -> *mut core::ffi::c_void {
18011 if fd < 0 { ERRNO!() = 9; return core::ptr::null_mut(); }
18012 dir_stream_new(fd)
18013}
18014
18015#[no_mangle]
18016pub unsafe extern "C" fn getdtablesize() -> i32 {
18017 let mut rlim: Rlimit = core::mem::zeroed();
18018 if getrlimit(RLIMIT_NOFILE, &mut rlim) == 0 {
18019 rlim.rlim_cur as i32
18020 } else {
18021 1024
18022 }
18023}
18024
18025#[no_mangle]
18026pub unsafe extern "C" fn getentropy(buf: *mut u8, buflen: usize) -> i32 {
18027 if buflen > 256 {
18028 ERRNO!() = EIO_VAL;
18029 return -1;
18030 }
18031 let mut pos = buf;
18032 let mut left = buflen;
18033 while left > 0 {
18034 let r = getrandom(pos, left, 0);
18035 if r < 0 {
18036 if ERRNO!() == EINTR_VAL {
18037 continue;
18038 }
18039 return -1;
18040 }
18041 pos = pos.add(r as usize);
18042 left -= r as usize;
18043 }
18044 0
18045}
18046
18047#[no_mangle]
18048pub unsafe extern "C" fn getrandom(buf: *mut u8, buflen: usize, flags: u32) -> isize {
18049 if let Some(r) = vgetrandom(buf, buflen, flags) {
18050 return if r < 0 {
18051 ERRNO!() = (-r) as c_int;
18052 -1
18053 } else {
18054 r
18055 };
18056 }
18057 let r = <Arch as Syscalls>::syscall3(sysno(318, 278), buf as i64, buflen as i64, flags as i64);
18058 if r < 0 {
18059 ERRNO!() = (-r) as c_int;
18060 -1
18061 } else {
18062 r as isize
18063 }
18064}
18065
18066#[no_mangle]
18067pub unsafe extern "C" fn killpg(pgrp: i32, sig: i32) -> i32 {
18068 syscall_ret(<Arch as Syscalls>::syscall2(SYS_KILL, -pgrp as i64, sig as i64)) as i32
18069}
18070
18071#[no_mangle]
18072pub unsafe extern "C" fn mkfifo(pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18073 mknod(pathname, 0o010000 | mode, 0)
18074}
18075
18076#[no_mangle]
18081pub unsafe extern "C" fn aligned_alloc(alignment: usize, size: usize) -> *mut core::ffi::c_void {
18082 alloc_aligned_impl(alignment, size) as *mut core::ffi::c_void
18083}
18084
18085#[no_mangle]
18086pub unsafe extern "C" fn memalign(alignment: usize, size: usize) -> *mut core::ffi::c_void {
18087 alloc_aligned_impl(alignment, size) as *mut core::ffi::c_void
18088}
18089
18090#[no_mangle]
18091pub unsafe extern "C" fn posix_memalign(memptr: *mut *mut core::ffi::c_void, alignment: usize, size: usize) -> i32 {
18092 if memptr.is_null() { return EINVAL; }
18093 if alignment < core::mem::size_of::<*mut core::ffi::c_void>() || !alignment.is_power_of_two() {
18094 return EINVAL;
18095 }
18096 let p = alloc_aligned_impl(alignment, size);
18097 if p.is_null() { return ENOMEM; }
18098 *memptr = p as *mut core::ffi::c_void;
18099 0
18100}
18101
18102#[no_mangle]
18103pub unsafe extern "C" fn valloc(size: usize) -> *mut core::ffi::c_void {
18104 alloc_aligned_impl(PAGE, size) as *mut core::ffi::c_void
18105}
18106
18107#[no_mangle]
18120pub unsafe extern "C" fn gettext(msgid: *const core::ffi::c_char) -> *const core::ffi::c_char {
18121 msgid
18122}
18123
18124#[no_mangle]
18125pub unsafe extern "C" fn dgettext(_domainname: *const core::ffi::c_char, msgid: *const core::ffi::c_char) -> *const core::ffi::c_char {
18126 msgid
18127}
18128
18129#[no_mangle]
18130pub unsafe extern "C" fn dcgettext(_domainname: *const core::ffi::c_char, msgid: *const core::ffi::c_char, _category: i32) -> *const core::ffi::c_char {
18131 msgid
18132}
18133
18134#[no_mangle]
18135pub unsafe extern "C" fn ngettext(msgid1: *const core::ffi::c_char, msgid2: *const core::ffi::c_char, n: u64) -> *const core::ffi::c_char {
18136 if n == 1 { msgid1 } else { msgid2 }
18137}
18138
18139#[no_mangle]
18140pub 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 {
18141 if n == 1 { msgid1 } else { msgid2 }
18142}
18143
18144#[no_mangle]
18145pub 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 {
18146 if n == 1 { msgid1 } else { msgid2 }
18147}
18148
18149#[no_mangle]
18150pub unsafe extern "C" fn textdomain(domainname: *const core::ffi::c_char) -> *mut core::ffi::c_char {
18151 static mut DOMAIN: [core::ffi::c_char; 256] = [0; 256];
18152 if domainname.is_null() { return DOMAIN.as_mut_ptr(); }
18153 let mut i = 0;
18154 while i < 255 && *domainname.add(i) != 0 {
18155 DOMAIN[i] = *domainname.add(i);
18156 i += 1;
18157 }
18158 DOMAIN[i] = 0;
18159 DOMAIN.as_mut_ptr()
18160}
18161
18162#[no_mangle]
18163pub unsafe extern "C" fn bindtextdomain(_domainname: *const core::ffi::c_char, dirname: *const core::ffi::c_char) -> *mut core::ffi::c_char {
18164 dirname as *mut core::ffi::c_char
18165}
18166
18167#[no_mangle]
18168pub unsafe extern "C" fn bind_textdomain_codeset(_domainname: *const core::ffi::c_char, codeset: *const core::ffi::c_char) -> *mut core::ffi::c_char {
18169 codeset as *mut core::ffi::c_char
18170}
18171
18172#[no_mangle]
18177pub unsafe extern "C" fn wmemcpy(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18178 let mut i = 0;
18179 while i < n {
18180 *dest.add(i) = *src.add(i);
18181 i += 1;
18182 }
18183 dest
18184}
18185
18186#[no_mangle]
18187pub unsafe extern "C" fn wmemmove(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18188 if dest as usize <= src as usize {
18189 let mut i = 0;
18190 while i < n {
18191 *dest.add(i) = *src.add(i);
18192 i += 1;
18193 }
18194 } else {
18195 let mut i = n;
18196 while i > 0 {
18197 i -= 1;
18198 *dest.add(i) = *src.add(i);
18199 }
18200 }
18201 dest
18202}
18203
18204#[no_mangle]
18205pub unsafe extern "C" fn wmemset(dest: *mut u32, c: u32, n: usize) -> *mut u32 {
18206 let mut i = 0;
18207 while i < n {
18208 *dest.add(i) = c;
18209 i += 1;
18210 }
18211 dest
18212}
18213
18214#[no_mangle]
18215pub unsafe extern "C" fn wmemcmp(s1: *const u32, s2: *const u32, n: usize) -> i32 {
18216 let mut i = 0;
18217 while i < n {
18218 let c1 = *s1.add(i);
18219 let c2 = *s2.add(i);
18220 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
18221 i += 1;
18222 }
18223 0
18224}
18225
18226#[no_mangle]
18227pub unsafe extern "C" fn wmemchr(s: *const u32, c: u32, n: usize) -> *mut u32 {
18228 let mut i = 0;
18229 while i < n {
18230 if *s.add(i) == c { return s.add(i) as *mut u32; }
18231 i += 1;
18232 }
18233 core::ptr::null_mut()
18234}
18235
18236#[no_mangle]
18237pub unsafe extern "C" fn wcpcpy(dest: *mut u32, src: *const u32) -> *mut u32 {
18238 let mut i = 0;
18239 loop {
18240 let c = *src.add(i);
18241 *dest.add(i) = c;
18242 if c == 0 { return dest.add(i); }
18243 i += 1;
18244 }
18245}
18246
18247#[no_mangle]
18248pub unsafe extern "C" fn wcpncpy(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18249 let mut i = 0;
18250 while i < n {
18251 let c = *src.add(i);
18252 *dest.add(i) = c;
18253 if c == 0 { return dest.add(i); }
18254 i += 1;
18255 }
18256 dest.add(n)
18257}
18258
18259#[no_mangle]
18260pub unsafe extern "C" fn wprintf(fmt: *const wchar_t, args: ...) -> c_int {
18261 vfwprintf(stdout, fmt, args)
18262}
18263
18264#[no_mangle]
18265pub unsafe extern "C" fn vwprintf(fmt: *const wchar_t, ap: core::ffi::VaList) -> c_int {
18266 vfwprintf(stdout, fmt, ap)
18267}
18268
18269#[no_mangle]
18274pub unsafe extern "C" fn c16rtomb(s: *mut u8, c16: u16, ps: *mut core::ffi::c_void) -> usize {
18275 let state = ps as *mut u32;
18277 let saved: u32 = if state.is_null() { 0 } else { *state };
18278 if s.is_null() {
18279 if !state.is_null() { *state = 0; }
18280 return 1;
18281 }
18282 let cp: u32;
18283 if saved != 0 {
18284 if c16 < 0xdc00 || c16 > 0xdfff {
18285 if !state.is_null() { *state = 0; }
18286 ERRNO!() = EILSEQ;
18287 return !0usize;
18288 }
18289 cp = 0x10000 + (((saved - 0xd800) << 10) | ((c16 as u32) - 0xdc00));
18290 if !state.is_null() { *state = 0; }
18291 } else if c16 >= 0xd800 && c16 <= 0xdbff {
18292 if !state.is_null() { *state = c16 as u32; }
18293 return 0;
18294 } else if c16 >= 0xdc00 && c16 <= 0xdfff {
18295 ERRNO!() = EILSEQ;
18296 return !0usize;
18297 } else {
18298 cp = c16 as u32;
18299 }
18300 if cp < 0x80 {
18301 *s = cp as u8;
18302 1
18303 } else if cp < 0x800 {
18304 *s = (0xc0 | (cp >> 6)) as u8;
18305 *s.add(1) = (0x80 | (cp & 0x3f)) as u8;
18306 2
18307 } else if cp < 0x10000 {
18308 *s = (0xe0 | (cp >> 12)) as u8;
18309 *s.add(1) = (0x80 | ((cp >> 6) & 0x3f)) as u8;
18310 *s.add(2) = (0x80 | (cp & 0x3f)) as u8;
18311 3
18312 } else {
18313 *s = (0xf0 | (cp >> 18)) as u8;
18314 *s.add(1) = (0x80 | ((cp >> 12) & 0x3f)) as u8;
18315 *s.add(2) = (0x80 | ((cp >> 6) & 0x3f)) as u8;
18316 *s.add(3) = (0x80 | (cp & 0x3f)) as u8;
18317 4
18318 }
18319}
18320
18321#[no_mangle]
18322pub unsafe extern "C" fn c32rtomb(s: *mut u8, c32: u32, _ps: *mut core::ffi::c_void) -> usize {
18323 if s.is_null() { return 1; }
18324 if c32 > 0x10ffff || (c32 >= 0xd800 && c32 <= 0xdfff) {
18325 ERRNO!() = EILSEQ;
18326 return !0usize;
18327 }
18328 if c32 < 0x80 {
18329 *s = c32 as u8;
18330 1
18331 } else if c32 < 0x800 {
18332 *s = (0xc0 | (c32 >> 6)) as u8;
18333 *s.add(1) = (0x80 | (c32 & 0x3f)) as u8;
18334 2
18335 } else if c32 < 0x10000 {
18336 *s = (0xe0 | (c32 >> 12)) as u8;
18337 *s.add(1) = (0x80 | ((c32 >> 6) & 0x3f)) as u8;
18338 *s.add(2) = (0x80 | (c32 & 0x3f)) as u8;
18339 3
18340 } else {
18341 *s = (0xf0 | (c32 >> 18)) as u8;
18342 *s.add(1) = (0x80 | ((c32 >> 12) & 0x3f)) as u8;
18343 *s.add(2) = (0x80 | ((c32 >> 6) & 0x3f)) as u8;
18344 *s.add(3) = (0x80 | (c32 & 0x3f)) as u8;
18345 4
18346 }
18347}
18348
18349#[no_mangle]
18350pub unsafe extern "C" fn mbrtoc16(pc16: *mut u16, s: *const u8, n: usize, _ps: *mut core::ffi::c_void) -> usize {
18351 if s.is_null() { return 0; }
18352 if n == 0 { return 1; }
18353 let c = *s;
18354 if c == 0 { return 0; }
18355 if c < 0x80 {
18356 if !pc16.is_null() { *pc16 = c as u16; }
18357 return 1;
18358 }
18359 if c < 0xC2 { return 1; } if c < 0xE0 {
18361 if n < 2 { return 1; }
18362 let c2 = *s.add(1);
18363 if (c2 & 0xC0) != 0x80 { return 1; }
18364 if !pc16.is_null() { *pc16 = ((((c & 0x1F) as u32) << 6) | ((c2 & 0x3F) as u32)) as u16; }
18365 return 2;
18366 }
18367 if c < 0xF0 {
18368 if n < 3 { return 1; }
18369 let c2 = *s.add(1);
18370 let c3 = *s.add(2);
18371 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 { return 1; }
18372 if !pc16.is_null() { *pc16 = ((((c & 0x0F) as u32) << 12) | (((c2 & 0x3F) as u32) << 6) | ((c3 & 0x3F) as u32)) as u16; }
18373 return 3;
18374 }
18375 1
18376}
18377
18378#[no_mangle]
18379pub unsafe extern "C" fn mbrtoc32(pc32: *mut u32, s: *const u8, n: usize, _ps: *mut core::ffi::c_void) -> usize {
18380 if s.is_null() { return 0; }
18381 if n == 0 { return 1; }
18382 let c = *s;
18383 if c == 0 { return 0; }
18384 if c < 0x80 {
18385 if !pc32.is_null() { *pc32 = c as u32; }
18386 return 1;
18387 }
18388 if c < 0xC2 { return 1; } if c < 0xE0 {
18390 if n < 2 { return 1; }
18391 let c2 = *s.add(1);
18392 if (c2 & 0xC0) != 0x80 { return 1; }
18393 if !pc32.is_null() { *pc32 = (((c & 0x1F) as u32) << 6) | ((c2 & 0x3F) as u32); }
18394 return 2;
18395 }
18396 if c < 0xF0 {
18397 if n < 3 { return 1; }
18398 let c2 = *s.add(1);
18399 let c3 = *s.add(2);
18400 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 { return 1; }
18401 if !pc32.is_null() { *pc32 = (((c & 0x0F) as u32) << 12) | (((c2 & 0x3F) as u32) << 6) | ((c3 & 0x3F) as u32); }
18402 return 3;
18403 }
18404 if c < 0xF5 {
18405 if n < 4 { return 1; }
18406 let c2 = *s.add(1);
18407 let c3 = *s.add(2);
18408 let c4 = *s.add(3);
18409 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80 { return 1; }
18410 if !pc32.is_null() { *pc32 = (((c & 0x07) as u32) << 18) | (((c2 & 0x3F) as u32) << 12) | (((c3 & 0x3F) as u32) << 6) | ((c4 & 0x3F) as u32); }
18411 return 4;
18412 }
18413 1
18414}
18415
18416#[no_mangle]
18428pub unsafe extern "C" fn chown(path: *const core::ffi::c_char, uid: u32, gid: u32) -> i32 {
18429 syscall_ret(<Arch as Syscalls>::syscall5(
18430 SYS_FCHOWNAT,
18431 AT_FDCWD as i64,
18432 path as i64,
18433 uid as i64,
18434 gid as i64,
18435 0,
18436 )) as i32
18437}
18438
18439#[no_mangle]
18440pub unsafe extern "C" fn lchown(path: *const core::ffi::c_char, uid: u32, gid: u32) -> i32 {
18441 syscall_ret(<Arch as Syscalls>::syscall5(
18442 SYS_FCHOWNAT,
18443 AT_FDCWD as i64,
18444 path as i64,
18445 uid as i64,
18446 gid as i64,
18447 0x100, )) as i32
18449}
18450
18451#[no_mangle]
18456pub unsafe extern "C" fn chroot(path: *const core::ffi::c_char) -> i32 {
18457 syscall_ret(<Arch as Syscalls>::syscall1(SYS_CHROOT, path as i64)) as i32
18458}
18459
18460#[no_mangle]
18461pub unsafe extern "C" fn get_current_dir_name() -> *mut core::ffi::c_char {
18462 static mut BUF: [core::ffi::c_char; 4096] = [0; 4096];
18463 let r = getcwd(BUF.as_mut_ptr(), 4096);
18464 if r.is_null() { core::ptr::null_mut() } else { BUF.as_mut_ptr() }
18465}
18466
18467#[no_mangle]
18472pub unsafe extern "C" fn creat(pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18473 open(pathname, 1 | 0o100 | 0o1000, mode as i32)
18475}
18476
18477#[no_mangle]
18478pub unsafe extern "C" fn openat(dirfd: i32, pathname: *const core::ffi::c_char, flags: i32, mode: u32) -> i32 {
18479 syscall_ret(<Arch as Syscalls>::syscall4(SYS_OPENAT, dirfd as i64, pathname as i64, flags as i64, mode as i64)) as i32
18480}
18481
18482#[no_mangle]
18483pub unsafe extern "C" fn pwrite(fd: i32, buf: *const u8, count: usize, offset: i64) -> isize {
18484 syscall_ret(<Arch as Syscalls>::syscall4(sysno(18, 68), fd as i64, buf as i64, count as i64, offset)) as isize
18485}
18486
18487#[no_mangle]
18488pub unsafe extern "C" fn readv(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32) -> isize {
18489 syscall_ret(<Arch as Syscalls>::syscall3(sysno(19, 65), fd as i64, iov as i64, iovcnt as i64)) as isize
18490}
18491
18492#[no_mangle]
18493pub unsafe extern "C" fn writev(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32) -> isize {
18494 syscall_ret(<Arch as Syscalls>::syscall3(sysno(20, 66), fd as i64, iov as i64, iovcnt as i64)) as isize
18495}
18496
18497#[no_mangle]
18502pub unsafe extern "C" fn flock(fd: i32, operation: i32) -> i32 {
18503 syscall_ret(<Arch as Syscalls>::syscall2(SYS_FLOCK, fd as i64, operation as i64)) as i32
18504}
18505
18506#[no_mangle]
18507pub unsafe extern "C" fn lockf(fd: i32, cmd: i32, len: i64) -> i32 {
18508 let r = <Arch as Syscalls>::syscall3(SYS_FCNTL, fd as i64, if cmd == 0 { 7 } else if cmd == 1 { 6 } else { 5 } , len);
18509 if r < 0 { return -1; }
18510 0
18511}
18512
18513#[no_mangle]
18518pub unsafe extern "C" fn getdomainname(name: *mut core::ffi::c_char, len: usize) -> i32 {
18519 if name.is_null() || len == 0 {
18520 ERRNO!() = EINVAL;
18521 return -1;
18522 }
18523 let mut uts: UtsName = core::mem::zeroed();
18524 let r = <Arch as Syscalls>::syscall1(SYS_UNAME, &mut uts as *mut UtsName as i64);
18525 if r < 0 {
18526 ERRNO!() = (-r) as c_int;
18527 return -1;
18528 }
18529 let mut n = 0usize;
18530 while n < uts.domainname.len() && uts.domainname[n] != 0 { n += 1; }
18531 if n >= len {
18532 ERRNO!() = EINVAL;
18533 return -1;
18534 }
18535 core::ptr::copy_nonoverlapping(uts.domainname.as_ptr(), name as *mut u8, n);
18536 *name.add(n) = 0;
18537 0
18538}
18539
18540#[no_mangle]
18541pub unsafe extern "C" fn setdomainname(name: *const core::ffi::c_char, len: usize) -> i32 {
18542 syscall_ret(<Arch as Syscalls>::syscall2(sysno(171, 162), name as i64, len as i64)) as i32
18543}
18544
18545#[no_mangle]
18546pub unsafe extern "C" fn sethostname(name: *const core::ffi::c_char, len: usize) -> i32 {
18547 syscall_ret(<Arch as Syscalls>::syscall2(SYS_SETHOSTNAME, name as i64, len as i64)) as i32
18548}
18549
18550#[no_mangle]
18551pub unsafe extern "C" fn getlogin_r(name: *mut core::ffi::c_char, bufsize: usize) -> i32 {
18552 let user = getlogin();
18553 if user.is_null() { return ENXIO_VAL; }
18554 let len = crate::strlen(user);
18555 if len >= bufsize { return 34; } core::ptr::copy_nonoverlapping(user, name, len + 1);
18557 0
18558}
18559
18560#[no_mangle]
18561pub unsafe extern "C" fn cuserid(s: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
18562 let user = crate::getenv(b"USER\0".as_ptr() as *const core::ffi::c_char);
18563 if user.is_null() { return core::ptr::null_mut(); }
18564 if s.is_null() {
18565 static mut BUF: [core::ffi::c_char; 32] = [0; 32];
18566 let mut i = 0;
18567 while i < 31 && *user.add(i) != 0 { BUF[i] = *user.add(i); i += 1; }
18568 BUF[i] = 0;
18569 BUF.as_mut_ptr()
18570 } else {
18571 let mut i = 0;
18572 while i < 31 && *user.add(i) != 0 { *s.add(i) = *user.add(i); i += 1; }
18573 *s.add(i) = 0;
18574 s
18575 }
18576}
18577
18578#[repr(C)]
18583#[derive(Copy, Clone)]
18584pub struct Passwd {
18585 pub pw_name: *mut c_char,
18586 pub pw_passwd: *mut c_char,
18587 pub pw_uid: u32,
18588 pub pw_gid: u32,
18589 pub pw_gecos: *mut c_char,
18590 pub pw_dir: *mut c_char,
18591 pub pw_shell: *mut c_char,
18592}
18593
18594#[repr(C)]
18595#[derive(Copy, Clone)]
18596pub struct Group {
18597 pub gr_name: *mut c_char,
18598 pub gr_passwd: *mut c_char,
18599 pub gr_gid: u32,
18600 pub gr_mem: *mut *mut c_char,
18601}
18602
18603static mut PWD_ENT: Passwd = Passwd {
18604 pw_name: core::ptr::null_mut(), pw_passwd: core::ptr::null_mut(),
18605 pw_uid: 0, pw_gid: 0, pw_gecos: core::ptr::null_mut(),
18606 pw_dir: core::ptr::null_mut(), pw_shell: core::ptr::null_mut(),
18607};
18608static mut PWD_LINE: *mut c_char = core::ptr::null_mut();
18609static mut PWD_LINE_CAP: usize = 0;
18610static mut PWD_BUF: *mut c_char = core::ptr::null_mut();
18611static mut PWD_BUF_CAP: usize = 0;
18612static mut PWD_FILE: *mut FILE = core::ptr::null_mut();
18613
18614unsafe fn ensure_pwd_buf(n: usize) -> bool {
18615 if n <= PWD_BUF_CAP {
18616 return true;
18617 }
18618 let mut cap = if PWD_BUF_CAP == 0 { 1024 } else { PWD_BUF_CAP };
18619 while cap < n {
18620 cap *= 2;
18621 }
18622 let p = realloc(PWD_BUF as *mut c_void, cap) as *mut c_char;
18623 if p.is_null() {
18624 return false;
18625 }
18626 PWD_BUF = p;
18627 PWD_BUF_CAP = cap;
18628 true
18629}
18630
18631static mut GRP_ENT: Group = Group {
18632 gr_name: core::ptr::null_mut(), gr_passwd: core::ptr::null_mut(),
18633 gr_gid: 0, gr_mem: core::ptr::null_mut(),
18634};
18635static mut GRP_LINE: *mut c_char = core::ptr::null_mut();
18636static mut GRP_LINE_CAP: usize = 0;
18637static mut GRP_BUF: *mut c_char = core::ptr::null_mut();
18638static mut GRP_BUF_CAP: usize = 0;
18639static mut GRP_MEM: *mut *mut c_char = core::ptr::null_mut();
18640static mut GRP_MEM_CAP: usize = 0;
18641static mut GRP_FILE: *mut FILE = core::ptr::null_mut();
18642
18643unsafe fn ensure_grp_buf(n: usize) -> bool {
18644 if n <= GRP_BUF_CAP {
18645 return true;
18646 }
18647 let mut cap = if GRP_BUF_CAP == 0 { 2048 } else { GRP_BUF_CAP };
18648 while cap < n {
18649 cap *= 2;
18650 }
18651 let p = realloc(GRP_BUF as *mut c_void, cap) as *mut c_char;
18652 if p.is_null() {
18653 return false;
18654 }
18655 GRP_BUF = p;
18656 GRP_BUF_CAP = cap;
18657 true
18658}
18659
18660unsafe fn ensure_grp_mem(n: usize) -> bool {
18661 if n <= GRP_MEM_CAP {
18662 return true;
18663 }
18664 let mut cap = if GRP_MEM_CAP == 0 { 32 } else { GRP_MEM_CAP };
18665 while cap < n {
18666 cap *= 2;
18667 }
18668 let p = realloc(
18669 GRP_MEM as *mut c_void,
18670 cap * core::mem::size_of::<*mut c_char>(),
18671 ) as *mut *mut c_char;
18672 if p.is_null() {
18673 return false;
18674 }
18675 GRP_MEM = p;
18676 GRP_MEM_CAP = cap;
18677 true
18678}
18679
18680unsafe fn parse_passwd(line: *const c_char, ent: *mut Passwd, buf: *mut c_char, buflen: usize) -> bool {
18681 let mut src = line;
18682 let mut o = 0usize;
18683 let mut fields: [*mut c_char; 7] = [core::ptr::null_mut(); 7];
18684 let mut n = 0usize;
18685 while n < 7 {
18686 let start = o;
18687 while *src != 0 && *src != b':' as c_char {
18688 if o + 1 >= buflen { return false; }
18689 *buf.add(o) = *src;
18690 o += 1;
18691 src = src.add(1);
18692 }
18693 *buf.add(o) = 0;
18694 o += 1;
18695 fields[n] = buf.add(start);
18696 n += 1;
18697 if *src == 0 { break; }
18698 src = src.add(1);
18699 }
18700 if n < 7 { return false; }
18701 (*ent).pw_name = fields[0];
18702 (*ent).pw_passwd = fields[1];
18703 (*ent).pw_uid = crate::strtol(fields[2], core::ptr::null_mut(), 10) as u32;
18704 (*ent).pw_gid = crate::strtol(fields[3], core::ptr::null_mut(), 10) as u32;
18705 (*ent).pw_gecos = fields[4];
18706 (*ent).pw_dir = fields[5];
18707 (*ent).pw_shell = fields[6];
18708 true
18709}
18710
18711unsafe fn parse_group(line: *const c_char, ent: *mut Group, buf: *mut c_char, buflen: usize) -> bool {
18712 let mut src = line;
18713 let mut o = 0usize;
18714 let mut fields: [*mut c_char; 4] = [core::ptr::null_mut(); 4];
18715 let mut n = 0usize;
18716 while n < 4 {
18717 let start = o;
18718 while *src != 0 && *src != b':' as c_char {
18719 if o + 1 >= buflen { return false; }
18720 *buf.add(o) = *src;
18721 o += 1;
18722 src = src.add(1);
18723 }
18724 *buf.add(o) = 0;
18725 o += 1;
18726 fields[n] = buf.add(start);
18727 n += 1;
18728 if *src == 0 { break; }
18729 src = src.add(1);
18730 }
18731 if n < 4 { return false; }
18732 (*ent).gr_name = fields[0];
18733 (*ent).gr_passwd = fields[1];
18734 (*ent).gr_gid = crate::strtol(fields[2], core::ptr::null_mut(), 10) as u32;
18735 let mut count = 1usize;
18736 let mut m = fields[3];
18737 while *m != 0 {
18738 if *m == b',' as c_char { count += 1; }
18739 m = m.add(1);
18740 }
18741 if !ensure_grp_mem(count + 1) { return false; }
18742 let mut mi = 0usize;
18743 m = fields[3];
18744 if *m != 0 {
18745 loop {
18746 *GRP_MEM.add(mi) = m;
18747 mi += 1;
18748 while *m != 0 && *m != b',' as c_char { m = m.add(1); }
18749 if *m == 0 { break; }
18750 *m = 0;
18751 m = m.add(1);
18752 }
18753 }
18754 *GRP_MEM.add(mi) = core::ptr::null_mut();
18755 (*ent).gr_mem = GRP_MEM;
18756 true
18757}
18758
18759#[no_mangle]
18760pub unsafe extern "C" fn getpwnam(name: *const c_char) -> *mut Passwd {
18761 if name.is_null() { return core::ptr::null_mut(); }
18762 setpwent();
18763 loop {
18764 let p = getpwent();
18765 if p.is_null() { break; }
18766 if crate::strcmp((*p).pw_name as *const u8, name as *const u8) == 0 { endpwent(); return p; }
18767 }
18768 endpwent();
18769 core::ptr::null_mut()
18770}
18771
18772#[no_mangle]
18773pub unsafe extern "C" fn getpwuid(uid: u32) -> *mut Passwd {
18774 setpwent();
18775 loop {
18776 let p = getpwent();
18777 if p.is_null() { break; }
18778 if (*p).pw_uid == uid { endpwent(); return p; }
18779 }
18780 endpwent();
18781 core::ptr::null_mut()
18782}
18783
18784#[no_mangle]
18785pub unsafe extern "C" fn setpwent() {
18786 endpwent();
18787 PWD_FILE = crate::fopen(b"/etc/passwd\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
18788}
18789
18790#[no_mangle]
18791pub unsafe extern "C" fn getpwent() -> *mut Passwd {
18792 if PWD_FILE.is_null() { setpwent(); if PWD_FILE.is_null() { return core::ptr::null_mut(); } }
18793 loop {
18794 let n = crate::getline(&raw mut PWD_LINE, &raw mut PWD_LINE_CAP, PWD_FILE);
18795 if n < 0 { return core::ptr::null_mut(); }
18796 let mut len = n as usize;
18797 if len > 0 && *PWD_LINE.add(len - 1) == b'\n' as c_char {
18798 *PWD_LINE.add(len - 1) = 0;
18799 len -= 1;
18800 }
18801 let need = len + 1;
18802 if !ensure_pwd_buf(need) { return core::ptr::null_mut(); }
18803 if parse_passwd(PWD_LINE, &raw mut PWD_ENT, PWD_BUF, need) {
18804 return &raw mut PWD_ENT;
18805 }
18806 }
18807}
18808
18809#[no_mangle]
18810pub unsafe extern "C" fn endpwent() {
18811 if !PWD_FILE.is_null() { crate::fclose(PWD_FILE); PWD_FILE = core::ptr::null_mut(); }
18812}
18813
18814#[no_mangle]
18815pub 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 {
18816 if result.is_null() { return EINVAL; }
18817 let p = getpwnam(name);
18818 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *pwd = *p; *result = pwd; 0 }
18819}
18820
18821#[no_mangle]
18822pub unsafe extern "C" fn getpwuid_r(uid: u32, pwd: *mut Passwd, _buf: *mut c_char, _buflen: usize, result: *mut *mut Passwd) -> c_int {
18823 if result.is_null() { return EINVAL; }
18824 let p = getpwuid(uid);
18825 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *pwd = *p; *result = pwd; 0 }
18826}
18827
18828#[no_mangle]
18829pub unsafe extern "C" fn fgetpwent(f: *mut FILE) -> *mut Passwd {
18830 if f.is_null() { return core::ptr::null_mut(); }
18831 loop {
18832 let n = crate::getline(&raw mut PWD_LINE, &raw mut PWD_LINE_CAP, f);
18833 if n < 0 { return core::ptr::null_mut(); }
18834 let mut len = n as usize;
18835 if len > 0 && *PWD_LINE.add(len - 1) == b'\n' as c_char {
18836 *PWD_LINE.add(len - 1) = 0;
18837 len -= 1;
18838 }
18839 let need = len + 1;
18840 if !ensure_pwd_buf(need) { return core::ptr::null_mut(); }
18841 if parse_passwd(PWD_LINE, &raw mut PWD_ENT, PWD_BUF, need) {
18842 return &raw mut PWD_ENT;
18843 }
18844 }
18845}
18846
18847#[no_mangle]
18848pub unsafe extern "C" fn putpwent(f: *mut FILE, p: *const Passwd) -> c_int {
18849 if f.is_null() || p.is_null() { return -1; }
18850 crate::fprintf(f, b"%s:%s:%u:%u:%s:%s:%s\n\0".as_ptr() as *const c_char,
18851 (*p).pw_name, (*p).pw_passwd, (*p).pw_uid, (*p).pw_gid,
18852 (*p).pw_gecos, (*p).pw_dir, (*p).pw_shell)
18853}
18854
18855#[no_mangle]
18856pub unsafe extern "C" fn getgrnam(name: *const c_char) -> *mut Group {
18857 if name.is_null() { return core::ptr::null_mut(); }
18858 setgrent();
18859 loop {
18860 let g = getgrent();
18861 if g.is_null() { break; }
18862 if crate::strcmp((*g).gr_name as *const u8, name as *const u8) == 0 { endgrent(); return g; }
18863 }
18864 endgrent();
18865 core::ptr::null_mut()
18866}
18867
18868#[no_mangle]
18869pub unsafe extern "C" fn getgrgid(gid: u32) -> *mut Group {
18870 setgrent();
18871 loop {
18872 let g = getgrent();
18873 if g.is_null() { break; }
18874 if (*g).gr_gid == gid { endgrent(); return g; }
18875 }
18876 endgrent();
18877 core::ptr::null_mut()
18878}
18879
18880#[no_mangle]
18881pub unsafe extern "C" fn setgrent() {
18882 endgrent();
18883 GRP_FILE = crate::fopen(b"/etc/group\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
18884}
18885
18886#[no_mangle]
18887pub unsafe extern "C" fn getgrent() -> *mut Group {
18888 if GRP_FILE.is_null() { setgrent(); if GRP_FILE.is_null() { return core::ptr::null_mut(); } }
18889 loop {
18890 let n = crate::getline(&raw mut GRP_LINE, &raw mut GRP_LINE_CAP, GRP_FILE);
18891 if n < 0 { return core::ptr::null_mut(); }
18892 let mut len = n as usize;
18893 if len > 0 && *GRP_LINE.add(len - 1) == b'\n' as c_char {
18894 *GRP_LINE.add(len - 1) = 0;
18895 len -= 1;
18896 }
18897 let need = len + 1;
18898 if !ensure_grp_buf(need) { return core::ptr::null_mut(); }
18899 if parse_group(GRP_LINE, &raw mut GRP_ENT, GRP_BUF, need) {
18900 return &raw mut GRP_ENT;
18901 }
18902 }
18903}
18904
18905#[no_mangle]
18906pub unsafe extern "C" fn endgrent() {
18907 if !GRP_FILE.is_null() { crate::fclose(GRP_FILE); GRP_FILE = core::ptr::null_mut(); }
18908}
18909
18910#[no_mangle]
18911pub 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 {
18912 if result.is_null() { return EINVAL; }
18913 let g = getgrnam(name);
18914 if g.is_null() { *result = core::ptr::null_mut(); 0 } else { *grp = *g; *result = grp; 0 }
18915}
18916
18917#[no_mangle]
18918pub unsafe extern "C" fn getgrgid_r(gid: u32, grp: *mut Group, _buf: *mut c_char, _buflen: usize, result: *mut *mut Group) -> c_int {
18919 if result.is_null() { return EINVAL; }
18920 let g = getgrgid(gid);
18921 if g.is_null() { *result = core::ptr::null_mut(); 0 } else { *grp = *g; *result = grp; 0 }
18922}
18923
18924#[no_mangle]
18925pub unsafe extern "C" fn fgetgrent(f: *mut FILE) -> *mut Group {
18926 if f.is_null() { return core::ptr::null_mut(); }
18927 loop {
18928 let n = crate::getline(&raw mut GRP_LINE, &raw mut GRP_LINE_CAP, f);
18929 if n < 0 { return core::ptr::null_mut(); }
18930 let mut len = n as usize;
18931 if len > 0 && *GRP_LINE.add(len - 1) == b'\n' as c_char {
18932 *GRP_LINE.add(len - 1) = 0;
18933 len -= 1;
18934 }
18935 let need = len + 1;
18936 if !ensure_grp_buf(need) { return core::ptr::null_mut(); }
18937 if parse_group(GRP_LINE, &raw mut GRP_ENT, GRP_BUF, need) {
18938 return &raw mut GRP_ENT;
18939 }
18940 }
18941}
18942
18943#[no_mangle]
18944pub unsafe extern "C" fn putgrent(f: *mut FILE, g: *const Group) -> c_int {
18945 if f.is_null() || g.is_null() { return -1; }
18946 crate::fprintf(f, b"%s:%s:%u:\0".as_ptr() as *const c_char, (*g).gr_name, (*g).gr_passwd, (*g).gr_gid);
18947 if !(*g).gr_mem.is_null() {
18948 let mut i = 0;
18949 while !(*(*g).gr_mem.add(i)).is_null() {
18950 if i > 0 { crate::fputc(b',' as c_int, f); }
18951 crate::fputs(*(*g).gr_mem.add(i), f);
18952 i += 1;
18953 }
18954 }
18955 crate::fputc(b'\n' as c_int, f);
18956 0
18957}
18958
18959#[no_mangle]
18964pub unsafe extern "C" fn setgroups(ngroups: usize, gidset: *const u32) -> i32 {
18965 syscall_ret(<Arch as Syscalls>::syscall2(SYS_SETGROUPS, ngroups as i64, gidset as i64)) as i32
18966}
18967
18968#[no_mangle]
18969pub unsafe extern "C" fn setresuid(ruid: u32, euid: u32, suid: u32) -> i32 {
18970 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SETRESUID, ruid as i64, euid as i64, suid as i64)) as i32
18971}
18972
18973#[no_mangle]
18974pub unsafe extern "C" fn setresgid(rgid: u32, egid: u32, sgid: u32) -> i32 {
18975 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SETRESGID, rgid as i64, egid as i64, sgid as i64)) as i32
18976}
18977
18978#[no_mangle]
18979pub unsafe extern "C" fn getresuid(ruid: *mut u32, euid: *mut u32, suid: *mut u32) -> i32 {
18980 syscall_ret(<Arch as Syscalls>::syscall3(SYS_GETRESUID, ruid as i64, euid as i64, suid as i64)) as i32
18981}
18982
18983#[no_mangle]
18984pub unsafe extern "C" fn getresgid(rgid: *mut u32, egid: *mut u32, sgid: *mut u32) -> i32 {
18985 syscall_ret(<Arch as Syscalls>::syscall3(SYS_GETRESGID, rgid as i64, egid as i64, sgid as i64)) as i32
18986}
18987
18988#[repr(C)]
18996struct KernelMsgHdr {
18997 msg_name: *mut c_void,
18998 msg_namelen: u32,
18999 __pad0: u32,
19000 msg_iov: *mut c_void,
19001 msg_iovlen: u64,
19002 msg_control: *mut c_void,
19003 msg_controllen: u64,
19004 msg_flags: u32,
19005 __pad1: u32,
19006}
19007
19008#[repr(C)]
19009struct UserMsgHdr {
19010 msg_name: *mut c_void,
19011 msg_namelen: u32,
19012 msg_iov: *mut c_void,
19013 msg_iovlen: i32,
19014 __pad1: i32,
19015 msg_control: *mut c_void,
19016 msg_controllen: u32,
19017 __pad2: i32,
19018 msg_flags: i32,
19019}
19020
19021unsafe fn msg_to_kernel(msg: *const UserMsgHdr, out: &mut KernelMsgHdr) {
19022 *out = KernelMsgHdr {
19023 msg_name: (*msg).msg_name,
19024 msg_namelen: (*msg).msg_namelen,
19025 __pad0: 0,
19026 msg_iov: (*msg).msg_iov,
19027 msg_iovlen: (*msg).msg_iovlen as u32 as u64,
19028 msg_control: (*msg).msg_control,
19029 msg_controllen: (*msg).msg_controllen as u64,
19030 msg_flags: (*msg).msg_flags as u32,
19031 __pad1: 0,
19032 };
19033}
19034
19035#[no_mangle]
19036pub unsafe extern "C" fn sendmsg(fd: i32, msg: *const core::ffi::c_void, flags: i32) -> isize {
19037 if msg.is_null() {
19038 ERRNO!() = EINVAL;
19039 return -1;
19040 }
19041 let mut k: KernelMsgHdr = core::mem::zeroed();
19042 msg_to_kernel(msg as *const UserMsgHdr, &mut k);
19043 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SENDMSG, fd as i64, &k as *const KernelMsgHdr as i64, flags as i64)) as isize
19044}
19045
19046#[no_mangle]
19047pub unsafe extern "C" fn recvmsg(fd: i32, msg: *mut core::ffi::c_void, flags: i32) -> isize {
19048 if msg.is_null() {
19049 ERRNO!() = EINVAL;
19050 return -1;
19051 }
19052 let user = msg as *mut UserMsgHdr;
19053 let mut k: KernelMsgHdr = core::mem::zeroed();
19054 msg_to_kernel(user, &mut k);
19055 let r = syscall_ret(<Arch as Syscalls>::syscall3(SYS_RECVMSG, fd as i64, &mut k as *mut KernelMsgHdr as i64, flags as i64));
19056 (*user).msg_flags = k.msg_flags as i32;
19057 (*user).msg_controllen = k.msg_controllen as u32;
19058 r as isize
19059}
19060
19061#[no_mangle]
19062pub unsafe extern "C" fn sendmmsg(fd: i32, msgvec: *mut core::ffi::c_void, vlen: u32, flags: i32) -> i32 {
19063 syscall_ret(<Arch as Syscalls>::syscall4(sysno(307, 269), fd as i64, msgvec as i64, vlen as i64, flags as i64)) as i32
19064}
19065
19066#[no_mangle]
19067pub unsafe extern "C" fn recvmmsg(fd: i32, msgvec: *mut core::ffi::c_void, vlen: u32, flags: i32, timeout: *mut core::ffi::c_void) -> i32 {
19068 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
19069}
19070
19071#[no_mangle]
19072pub unsafe extern "C" fn getpeername(fd: i32, addr: *mut core::ffi::c_void, addrlen: *mut u32) -> i32 {
19073 syscall_ret(<Arch as Syscalls>::syscall3(sysno(52, 205), fd as i64, addr as i64, addrlen as i64)) as i32
19074}
19075
19076#[no_mangle]
19077pub unsafe extern "C" fn getsockopt(fd: i32, level: i32, optname: i32, optval: *mut core::ffi::c_void, optlen: *mut u32) -> i32 {
19078 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
19079}
19080
19081#[no_mangle]
19086pub unsafe extern "C" fn ftrylockfile(file: *mut FILE) -> i32 {
19087 if file.is_null() { return EINVAL; }
19088 if (*file).lock < 0 { return 0; }
19089 let tid = sys_gettid() as c_int;
19090 let v = a_load(&raw const (*file).lock);
19091 if v == tid {
19092 (*file).lockcount += 1;
19093 return 0;
19094 }
19095 if v == 0 && a_cas(&raw mut (*file).lock, 0, tid) == 0 {
19096 (*file).lockcount = 1;
19097 return 0;
19098 }
19099 EBUSY
19100}
19101
19102#[no_mangle]
19103pub unsafe extern "C" fn getc_unlocked(file: *mut core::ffi::c_char) -> i32 {
19104 getc(file as *mut FILE)
19105}
19106
19107#[no_mangle]
19108pub unsafe extern "C" fn getchar_unlocked() -> i32 {
19109 getchar()
19110}
19111
19112#[no_mangle]
19113pub unsafe extern "C" fn putc_unlocked(c: i32, file: *mut core::ffi::c_char) -> i32 {
19114 putc(c, file as *mut FILE)
19115}
19116
19117#[no_mangle]
19118pub unsafe extern "C" fn putchar_unlocked(c: i32) -> i32 {
19119 putchar(c)
19120}
19121
19122#[no_mangle] pub static mut optarg: *mut core::ffi::c_char = core::ptr::null_mut();
19127#[no_mangle] pub static mut optind: i32 = 1;
19128#[no_mangle] pub static mut opterr: i32 = 1;
19129#[no_mangle] pub static mut optopt: i32 = '?' as i32;
19130#[no_mangle] pub static mut optreset: i32 = 0;
19131
19132#[no_mangle]
19137pub unsafe extern "C" fn getitimer(which: i32, curr_value: *mut core::ffi::c_void) -> i32 {
19138 syscall_ret(<Arch as Syscalls>::syscall2(sysno(36, 102), which as i64, curr_value as i64)) as i32
19139}
19140
19141#[no_mangle]
19142pub unsafe extern "C" fn setitimer(which: i32, new_value: *const core::ffi::c_void, old_value: *mut core::ffi::c_void) -> i32 {
19143 syscall_ret(<Arch as Syscalls>::syscall3(sysno(38, 103), which as i64, new_value as i64, old_value as i64)) as i32
19144}
19145
19146#[no_mangle]
19151pub unsafe extern "C" fn getloadavg(loadavg: *mut f64, nelem: i32) -> i32 {
19152 let fd = crate::open(b"/proc/loadavg\0".as_ptr() as *const core::ffi::c_char, 0, 0);
19153 if fd < 0 { return -1; }
19154 let mut buf: [u8; 64] = [0; 64];
19155 let n = crate::read(fd, buf.as_mut_ptr() as *mut core::ffi::c_void, 63);
19156 crate::close(fd);
19157 if n <= 0 { return -1; }
19158 buf[n as usize] = 0;
19159 let mut i = 0;
19160 while i < nelem as usize && i < 3 {
19161 let val = crate::strtod((buf.as_ptr() as *const core::ffi::c_char).add(i * 5), core::ptr::null_mut());
19162 *loadavg.add(i) = val;
19163 i += 1;
19164 }
19165 i as i32
19166}
19167
19168#[no_mangle]
19169pub unsafe extern "C" fn get_nprocs() -> i32 {
19170 sysconf(84) as i32 }
19172
19173#[no_mangle]
19174pub unsafe extern "C" fn get_nprocs_conf() -> i32 {
19175 sysconf(83) as i32 }
19177
19178#[no_mangle]
19179pub unsafe extern "C" fn get_avphys_pages() -> i64 {
19180 sysconf(86) }
19182
19183#[no_mangle]
19184pub unsafe extern "C" fn get_phys_pages() -> i64 {
19185 sysconf(85) }
19187
19188#[no_mangle]
19193pub unsafe extern "C" fn capget(header: *mut core::ffi::c_void, data: *mut core::ffi::c_void) -> i32 {
19194 syscall_ret(<Arch as Syscalls>::syscall2(SYS_CAPGET, header as i64, data as i64)) as i32
19195}
19196
19197#[no_mangle]
19198pub unsafe extern "C" fn capset(header: *const core::ffi::c_void, data: *const core::ffi::c_void) -> i32 {
19199 syscall_ret(<Arch as Syscalls>::syscall2(SYS_CAPSET, header as i64, data as i64)) as i32
19200}
19201
19202#[no_mangle]
19203pub unsafe extern "C" fn arch_prctl(code: i32, addr: u64) -> i32 {
19204 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 }
19205}
19206
19207#[no_mangle]
19212pub unsafe extern "C" fn cfgetospeed(termios_p: *const core::ffi::c_void) -> u32 {
19213 unsafe { *(termios_p as *const u32).add(1) }
19214}
19215
19216#[no_mangle]
19217pub unsafe extern "C" fn cfgetispeed(termios_p: *const core::ffi::c_void) -> u32 {
19218 unsafe { *(termios_p as *const u32).add(2) }
19219}
19220
19221#[no_mangle]
19222pub unsafe extern "C" fn cfsetospeed(termios_p: *mut core::ffi::c_void, speed: u32) -> i32 {
19223 unsafe { *(termios_p as *mut u32).add(1) = speed; }
19224 0
19225}
19226
19227#[no_mangle]
19228pub unsafe extern "C" fn cfsetispeed(termios_p: *mut core::ffi::c_void, speed: u32) -> i32 {
19229 unsafe { *(termios_p as *mut u32).add(2) = speed; }
19230 0
19231}
19232
19233#[no_mangle]
19234pub unsafe extern "C" fn cfmakeraw(termios_p: *mut core::ffi::c_void) {
19235 unsafe {
19236 let p = termios_p as *mut u32;
19237 *p.add(0) &= !0o37;
19238 *p.add(0) &= !(0o4000 | 0o2000 | 0o10000 | 0o20);
19239 *p.add(0) |= 0o60;
19240 *p.add(3) &= !0o17;
19241 *p.add(3) &= !(0o1000 | 0o40000000);
19242 *p.add(1) = 1;
19243 *p.add(2) = 0;
19244 }
19245}
19246
19247#[no_mangle]
19252pub unsafe extern "C" fn getrusage(who: i32, usage: *mut core::ffi::c_void) -> i32 {
19253 syscall_ret(<Arch as Syscalls>::syscall2(sysno(98, 165), who as i64, usage as i64)) as i32
19254}
19255
19256#[no_mangle]
19257pub unsafe extern "C" fn getpriority(which: i32, who: u32) -> i32 {
19258 let r = <Arch as Syscalls>::syscall2(SYS_GETPRIORITY, which as i64, who as i64);
19260 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
19261 20 - r as i32
19262}
19263
19264#[no_mangle]
19265pub unsafe extern "C" fn setpriority(which: i32, who: u32, prio: i32) -> i32 {
19266 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SETPRIORITY, which as i64, who as i64, prio as i64)) as i32
19267}
19268
19269#[no_mangle]
19270pub unsafe extern "C" fn prlimit(pid: u32, resource: i32, new_limit: *const core::ffi::c_void, old_limit: *mut core::ffi::c_void) -> i32 {
19271 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
19272}
19273
19274#[no_mangle]
19279pub unsafe extern "C" fn clone(
19280 func: usize,
19281 stack: *mut u8,
19282 flags: c_int,
19283 arg: *mut c_void,
19284 mut args: ...
19285) -> c_int {
19286 const CLONE_PIDFD_C: c_int = 0x00001000;
19288 const CLONE_VM_C: c_int = 0x00000100;
19289 const CLONE_THREAD_C: c_int = 0x00010000;
19290 const CLONE_SETTLS_C: c_int = 0x00080000;
19291 const CLONE_PARENT_SETTID_C: c_int = 0x00100000;
19292 const CLONE_CHILD_SETTID_C: c_int = 0x01000000;
19293 const CLONE_CHILD_CLEARTID_C: c_int = 0x00200000;
19294 let _ = CLONE_VM_C;
19295 if flags & (CLONE_THREAD_C | CLONE_SETTLS_C | CLONE_CHILD_CLEARTID_C) != 0
19296 || stack.is_null()
19297 {
19298 ERRNO!() = EINVAL;
19299 return -1;
19300 }
19301 let mut ptid: *mut c_int = core::ptr::null_mut();
19302 let mut tls: c_ulong = 0;
19303 let mut ctid: *mut c_int = core::ptr::null_mut();
19304 if flags & (CLONE_PIDFD_C | CLONE_PARENT_SETTID_C | CLONE_CHILD_SETTID_C) != 0 {
19305 ptid = args.next_arg::<*mut c_int>();
19306 }
19307 if flags & CLONE_CHILD_SETTID_C != 0 {
19308 tls = args.next_arg::<c_ulong>();
19309 ctid = args.next_arg::<*mut c_int>();
19310 }
19311 let r = __rc_clone(func, stack, flags as c_ulong, arg, ptid, tls, ctid);
19312 if r < 0 {
19313 ERRNO!() = (-r) as c_int;
19314 -1
19315 } else {
19316 r as c_int
19317 }
19318}
19319
19320#[no_mangle]
19321pub unsafe extern "C" fn _Fork() -> i32 {
19322 crate::fork()
19323}
19324
19325#[no_mangle]
19326pub 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 {
19327 let mut master: i32 = 0;
19328 let mut slave: i32 = 0;
19329 if openpty(&mut master, &mut slave, name, termp, winp) < 0 { return -1; }
19330 let pid = crate::fork();
19331 if pid < 0 { crate::close(master); crate::close(slave); return -1; }
19332 if pid == 0 {
19333 crate::close(master);
19334 crate::setsid();
19335 crate::dup2(slave, 0);
19336 crate::dup2(slave, 1);
19337 crate::dup2(slave, 2);
19338 } else {
19339 crate::close(slave);
19340 if !amaster.is_null() { *amaster = master; }
19341 }
19342 pid
19343}
19344
19345#[no_mangle]
19346pub 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 {
19347 let master = crate::open(b"/dev/ptmx\0".as_ptr() as *const core::ffi::c_char, 0o2000, 0);
19348 if master < 0 { return -1; }
19349 grantpt(master);
19350 unlockpt(master);
19351 let slave_name = ptsname(master);
19352 if slave_name.is_null() { crate::close(master); return -1; }
19353 let slave = crate::open(slave_name, 0o2000, 0);
19354 if slave < 0 { crate::close(master); return -1; }
19355 if !amaster.is_null() { *amaster = master; }
19356 if !aslave.is_null() { *aslave = slave; }
19357 if !name.is_null() { crate::strcpy(name as *mut u8, slave_name as *const u8); }
19358 0
19359}
19360
19361#[no_mangle]
19362pub unsafe extern "C" fn login_tty(fd: i32) -> i32 {
19363 crate::setsid();
19364 crate::dup2(fd, 0);
19365 crate::dup2(fd, 1);
19366 crate::dup2(fd, 2);
19367 0
19368}
19369
19370#[no_mangle]
19375pub unsafe extern "C" fn __dls2b() {}
19376#[no_mangle]
19377pub unsafe extern "C" fn __dls3() {}
19378#[no_mangle]
19379pub unsafe extern "C" fn _dlstart() {}
19380
19381#[no_mangle]
19386pub unsafe extern "C" fn index(s: *const core::ffi::c_char, c: i32) -> *mut core::ffi::c_char {
19387 let mut i = 0;
19388 loop {
19389 let ch = *s.add(i);
19390 if ch == c as core::ffi::c_char { return s.add(i) as *mut core::ffi::c_char; }
19391 if ch == 0 { return core::ptr::null_mut(); }
19392 i += 1;
19393 }
19394}
19395
19396#[no_mangle]
19397pub unsafe extern "C" fn rindex(s: *const core::ffi::c_char, c: i32) -> *mut core::ffi::c_char {
19398 let mut last = core::ptr::null_mut();
19399 let mut i = 0;
19400 loop {
19401 let ch = *s.add(i);
19402 if ch == 0 { return last; }
19403 if ch == c as core::ffi::c_char { last = s.add(i) as *mut core::ffi::c_char; }
19404 i += 1;
19405 }
19406}
19407
19408#[no_mangle]
19413pub unsafe extern "C" fn imaxabs(j: i64) -> i64 {
19414 j.abs()
19415}
19416
19417#[no_mangle]
19418pub unsafe extern "C" fn imaxdiv(numer: i64, denom: i64) -> (i64, i64) {
19419 (numer / denom, numer % denom)
19420}
19421
19422#[no_mangle]
19427pub static mut h_errno: i32 = 0;
19428
19429#[no_mangle]
19430pub unsafe extern "C" fn __h_errno_location() -> *mut i32 {
19431 &mut h_errno
19432}
19433
19434#[no_mangle]
19435pub unsafe extern "C" fn herror(s: *const core::ffi::c_char) {
19436 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
19437 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
19438 crate::write(2, hstrerror(*__h_errno_location()) as *const core::ffi::c_void, crate::strlen(hstrerror(*__h_errno_location())));
19439 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
19440}
19441
19442#[no_mangle]
19443pub unsafe extern "C" fn hstrerror(_err: i32) -> *const core::ffi::c_char {
19444 b"Unknown error\0".as_ptr() as *const core::ffi::c_char
19445}
19446
19447#[no_mangle]
19452pub unsafe extern "C" fn gettid() -> i32 {
19453 syscall_ret(<Arch as Syscalls>::syscall0(SYS_GETTID)) as i32
19454}
19455
19456#[no_mangle]
19461pub unsafe extern "C" fn ioctl(fd: i32, request: u32, mut args: ...) -> i32 {
19462 let arg = args.next_arg::<i64>();
19463 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, request as i64, arg)) as i32
19464}
19465
19466#[no_mangle]
19467pub unsafe extern "C" fn ioperm(from: u64, num: u64, turn_on: i32) -> i32 {
19468 #[cfg(target_arch = "x86_64")]
19469 { syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOPERM, from as i64, num as i64, turn_on as i64)) as i32 }
19470 #[cfg(not(target_arch = "x86_64"))]
19471 {
19472 let _ = (from, num, turn_on);
19473 ERRNO!() = ENOSYS_VAL;
19474 -1
19475 }
19476}
19477
19478#[no_mangle]
19479pub unsafe extern "C" fn iopl(level: i32) -> i32 {
19480 #[cfg(target_arch = "x86_64")]
19481 { syscall_ret(<Arch as Syscalls>::syscall1(SYS_IOPL, level as i64)) as i32 }
19482 #[cfg(not(target_arch = "x86_64"))]
19483 {
19484 let _ = level;
19485 ERRNO!() = ENOSYS_VAL;
19486 -1
19487 }
19488}
19489
19490#[no_mangle]
19495pub unsafe extern "C" fn getxattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19496 syscall_ret(<Arch as Syscalls>::syscall4(sysno(191, 8), path as i64, name as i64, value as i64, size as i64)) as isize
19497}
19498
19499#[no_mangle]
19500pub unsafe extern "C" fn lgetxattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19501 syscall_ret(<Arch as Syscalls>::syscall4(sysno(192, 9), path as i64, name as i64, value as i64, size as i64)) as isize
19502}
19503
19504#[no_mangle]
19505pub unsafe extern "C" fn fgetxattr(fd: i32, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19506 syscall_ret(<Arch as Syscalls>::syscall4(sysno(193, 10), fd as i64, name as i64, value as i64, size as i64)) as isize
19507}
19508
19509#[no_mangle]
19510pub unsafe extern "C" fn listxattr(path: *const core::ffi::c_char, list: *mut u8, size: usize) -> isize {
19511 syscall_ret(<Arch as Syscalls>::syscall3(sysno(194, 11), path as i64, list as i64, size as i64)) as isize
19512}
19513
19514#[no_mangle]
19515pub unsafe extern "C" fn llistxattr(path: *const core::ffi::c_char, list: *mut u8, size: usize) -> isize {
19516 syscall_ret(<Arch as Syscalls>::syscall3(sysno(195, 12), path as i64, list as i64, size as i64)) as isize
19517}
19518
19519#[no_mangle]
19520pub unsafe extern "C" fn flistxattr(fd: i32, list: *mut u8, size: usize) -> isize {
19521 syscall_ret(<Arch as Syscalls>::syscall3(sysno(196, 13), fd as i64, list as i64, size as i64)) as isize
19522}
19523
19524#[no_mangle]
19525pub 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 {
19526 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
19527}
19528
19529#[no_mangle]
19530pub 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 {
19531 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
19532}
19533
19534#[no_mangle]
19535pub unsafe extern "C" fn fsetxattr(fd: i32, name: *const core::ffi::c_char, value: *const u8, size: usize, flags: i32) -> i32 {
19536 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
19537}
19538
19539#[no_mangle]
19540pub unsafe extern "C" fn removexattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char) -> i32 {
19541 syscall_ret(<Arch as Syscalls>::syscall2(sysno(197, 14), path as i64, name as i64)) as i32
19542}
19543
19544#[no_mangle]
19545pub unsafe extern "C" fn lremovexattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char) -> i32 {
19546 syscall_ret(<Arch as Syscalls>::syscall2(sysno(198, 15), path as i64, name as i64)) as i32
19547}
19548
19549#[no_mangle]
19550pub unsafe extern "C" fn fremovexattr(fd: i32, name: *const core::ffi::c_char) -> i32 {
19551 syscall_ret(<Arch as Syscalls>::syscall2(sysno(199, 16), fd as i64, name as i64)) as i32
19552}
19553
19554#[no_mangle]
19559pub unsafe extern "C" fn adjtime(_delta: *const core::ffi::c_void, olddelta: *mut core::ffi::c_void) -> i32 {
19560 syscall_ret(<Arch as Syscalls>::syscall1(SYS_ADJTIMEX, olddelta as i64)) as i32
19561}
19562
19563#[no_mangle]
19564pub unsafe extern "C" fn adjtimex(buf: *mut core::ffi::c_void) -> i32 {
19565 syscall_ret(<Arch as Syscalls>::syscall1(SYS_ADJTIMEX, buf as i64)) as i32
19566}
19567
19568const TIOCGPTN: i64 = 0x80045430;
19577const TIOCSPTLCK: i64 = 0x40045431;
19578
19579#[no_mangle]
19580pub unsafe extern "C" fn grantpt(_fd: i32) -> i32 {
19581 0
19583}
19584
19585#[no_mangle]
19586pub unsafe extern "C" fn unlockpt(fd: i32) -> i32 {
19587 let mut unlock: i32 = 0;
19588 let r = <Arch as Syscalls>::syscall3(
19589 SYS_IOCTL,
19590 fd as i64,
19591 TIOCSPTLCK,
19592 &mut unlock as *mut i32 as i64,
19593 );
19594 if r < 0 { -1 } else { 0 }
19595}
19596
19597#[no_mangle]
19598pub unsafe extern "C" fn ptsname(fd: i32) -> *mut core::ffi::c_char {
19599 static mut BUF: [core::ffi::c_char; 32] = [0; 32];
19600 let mut pty_nr: i32 = 0;
19601 if <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, TIOCGPTN, &mut pty_nr as *mut i32 as i64) < 0 {
19602 return core::ptr::null_mut();
19603 }
19604 BUF[0] = '/' as c_char; BUF[1] = 'd' as c_char; BUF[2] = 'e' as c_char; BUF[3] = 'v' as c_char;
19606 BUF[4] = '/' as c_char; BUF[5] = 'p' as c_char; BUF[6] = 't' as c_char; BUF[7] = 's' as c_char;
19607 BUF[8] = '/' as c_char;
19608 let mut n = pty_nr as usize;
19609 let mut i = 9;
19610 if n == 0 { BUF[i] = '0' as c_char; i += 1; }
19611 while n > 0 && i < 31 {
19612 BUF[i] = (b'0' + (n % 10) as u8) as c_char;
19613 n /= 10;
19614 i += 1;
19615 }
19616 BUF[i] = 0;
19617 BUF.as_mut_ptr()
19618}
19619
19620#[no_mangle]
19625pub unsafe extern "C" fn finite(x: f64) -> i32 {
19626 (!x.is_nan() && !x.is_infinite()) as i32
19627}
19628
19629#[no_mangle]
19630pub unsafe extern "C" fn finitef(x: f32) -> i32 {
19631 (!x.is_nan() && !x.is_infinite()) as i32
19632}
19633
19634#[no_mangle]
19635pub unsafe extern "C" fn __fpclassifyl(x: f64) -> i32 {
19636 __fpclassify(x)
19637}
19638
19639#[no_mangle]
19640pub unsafe extern "C" fn __signbitl(x: f64) -> i32 {
19641 __signbit(x)
19642}
19643
19644#[no_mangle]
19653pub unsafe extern "C" fn j0(x: f64) -> f64 {
19654 j0_impl(x)
19655}
19656
19657#[no_mangle]
19658pub unsafe extern "C" fn j0f(x: f32) -> f32 {
19659 libm::j0f(x)
19660}
19661
19662#[no_mangle]
19663pub unsafe extern "C" fn j1(x: f64) -> f64 {
19664 libm::j1(x)
19665}
19666
19667#[no_mangle]
19668pub unsafe extern "C" fn j1f(x: f32) -> f32 {
19669 libm::j1f(x)
19670}
19671
19672#[no_mangle]
19673pub unsafe extern "C" fn jn(n: i32, x: f64) -> f64 {
19674 libm::jn(n, x)
19675}
19676
19677#[no_mangle]
19678pub unsafe extern "C" fn jnf(n: i32, x: f32) -> f32 {
19679 libm::jnf(n, x)
19680}
19681
19682#[no_mangle]
19683pub unsafe extern "C" fn y0(x: f64) -> f64 {
19684 y0_impl(x)
19685}
19686
19687#[no_mangle]
19688pub unsafe extern "C" fn y0f(x: f32) -> f32 {
19689 if x.is_nan() { return x; }
19690 if x < 0.0 { return __math_invalidf(x); }
19691 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f32::NEG_INFINITY; }
19692 libm::y0f(x)
19693}
19694
19695#[no_mangle]
19696pub unsafe extern "C" fn y1(x: f64) -> f64 {
19697 if x.is_nan() { return x; }
19698 if x < 0.0 { return __math_invalid(x); }
19699 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f64::NEG_INFINITY; }
19700 libm::y1(x)
19701}
19702
19703#[no_mangle]
19704pub unsafe extern "C" fn y1f(x: f32) -> f32 {
19705 if x.is_nan() { return x; }
19706 if x < 0.0 { return __math_invalidf(x); }
19707 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f32::NEG_INFINITY; }
19708 libm::y1f(x)
19709}
19710
19711#[no_mangle]
19712pub unsafe extern "C" fn yn(n: i32, x: f64) -> f64 {
19713 if x.is_nan() { return x; }
19714 if x < 0.0 { return __math_invalid(x); }
19715 if x == 0.0 {
19716 feraiseexcept(FE_DIVBYZERO);
19717 if n >= 0 { return f64::NEG_INFINITY; }
19718 }
19719 libm::yn(n, x)
19720}
19721
19722#[no_mangle]
19723pub unsafe extern "C" fn ynf(n: i32, x: f32) -> f32 {
19724 if x.is_nan() { return x; }
19725 if x < 0.0 { return __math_invalidf(x); }
19726 if x == 0.0 {
19727 feraiseexcept(FE_DIVBYZERO);
19728 if n >= 0 { return f32::NEG_INFINITY; }
19729 }
19730 libm::ynf(n, x)
19731}
19732
19733#[no_mangle]
19738pub unsafe extern "C" fn __ctype_b_loc() -> *mut *const u16 {
19739 static mut TABLE: *const u16 = core::ptr::null();
19740 &mut TABLE
19741}
19742
19743#[no_mangle]
19744pub unsafe extern "C" fn __ctype_tolower_loc() -> *mut *const i32 {
19745 static mut TABLE: *const i32 = core::ptr::null();
19746 &mut TABLE
19747}
19748
19749#[no_mangle]
19750pub unsafe extern "C" fn __ctype_toupper_loc() -> *mut *const i32 {
19751 static mut TABLE: *const i32 = core::ptr::null();
19752 &mut TABLE
19753}
19754
19755#[no_mangle]
19756pub unsafe extern "C" fn __isalnum_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19757 (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
19758}
19759
19760#[no_mangle]
19761pub unsafe extern "C" fn __isalpha_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19762 (c >= 'A' as i32 && c <= 'Z' as i32 || c >= 'a' as i32 && c <= 'z' as i32) as i32
19763}
19764
19765#[no_mangle]
19766pub unsafe extern "C" fn __isblank_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19767 (c == ' ' as i32 || c == '\t' as i32) as i32
19768}
19769
19770#[no_mangle]
19771pub unsafe extern "C" fn __iscntrl_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19772 (c < 0x20 || c == 0x7f) as i32
19773}
19774
19775#[no_mangle]
19776pub unsafe extern "C" fn __isdigit_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19777 (c >= '0' as i32 && c <= '9' as i32) as i32
19778}
19779
19780#[no_mangle]
19781pub unsafe extern "C" fn __isgraph_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19782 (c > 0x20 && c < 0x7f) as i32
19783}
19784
19785#[no_mangle]
19786pub unsafe extern "C" fn __islower_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19787 (c >= 'a' as i32 && c <= 'z' as i32) as i32
19788}
19789
19790#[no_mangle]
19791pub unsafe extern "C" fn __isprint_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19792 (c >= 0x20 && c < 0x7f) as i32
19793}
19794
19795#[no_mangle]
19796pub unsafe extern "C" fn __ispunct_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19797 (c >= 0x21 && c <= 0x2f || c >= 0x3a && c <= 0x40 || c >= 0x5b && c <= 0x60 || c >= 0x7b && c <= 0x7e) as i32
19798}
19799
19800#[no_mangle]
19801pub unsafe extern "C" fn __isspace_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19802 (c == ' ' as i32 || c >= 0x09 && c <= 0x0d) as i32
19803}
19804
19805#[no_mangle]
19806pub unsafe extern "C" fn __isupper_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19807 (c >= 'A' as i32 && c <= 'Z' as i32) as i32
19808}
19809
19810#[no_mangle]
19811pub unsafe extern "C" fn __isxdigit_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19812 (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
19813}
19814
19815#[no_mangle]
19820pub unsafe extern "C" fn __iswalnum_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19821 (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
19822}
19823
19824#[no_mangle]
19825pub unsafe extern "C" fn __iswalpha_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19826 (c >= 'A' as u32 && c <= 'Z' as u32 || c >= 'a' as u32 && c <= 'z' as u32) as i32
19827}
19828
19829#[no_mangle]
19830pub unsafe extern "C" fn __iswblank_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19831 (c == ' ' as u32 || c == '\t' as u32) as i32
19832}
19833
19834#[no_mangle]
19835pub unsafe extern "C" fn __iswcntrl_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19836 (c < 0x20 || c == 0x7f) as i32
19837}
19838
19839#[no_mangle]
19840pub unsafe extern "C" fn __iswdigit_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19841 (c >= '0' as u32 && c <= '9' as u32) as i32
19842}
19843
19844#[no_mangle]
19845pub unsafe extern "C" fn __iswgraph_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19846 (c > 0x20 && c < 0x7f) as i32
19847}
19848
19849#[no_mangle]
19850pub unsafe extern "C" fn __iswlower_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19851 (c >= 'a' as u32 && c <= 'z' as u32) as i32
19852}
19853
19854#[no_mangle]
19855pub unsafe extern "C" fn __iswprint_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19856 (c >= 0x20 && c < 0x7f) as i32
19857}
19858
19859#[no_mangle]
19860pub unsafe extern "C" fn __iswpunct_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19861 (c >= 0x21 && c <= 0x2f || c >= 0x3a && c <= 0x40 || c >= 0x5b && c <= 0x60 || c >= 0x7b && c <= 0x7e) as i32
19862}
19863
19864#[no_mangle]
19865pub unsafe extern "C" fn __iswspace_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19866 (c == ' ' as u32 || c >= 0x09 && c <= 0x0d) as i32
19867}
19868
19869#[no_mangle]
19870pub unsafe extern "C" fn __iswupper_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19871 (c >= 'A' as u32 && c <= 'Z' as u32) as i32
19872}
19873
19874#[no_mangle]
19875pub unsafe extern "C" fn __iswxdigit_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
19876 (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
19877}
19878
19879#[no_mangle]
19880pub unsafe extern "C" fn __iswctype_l(c: u32, ctype: u32, _loc: *mut core::ffi::c_void) -> i32 {
19881 crate::iswctype(c as wint_t, ctype as wctype_t)
19882}
19883
19884#[no_mangle]
19885pub unsafe extern "C" fn __towlower_l(c: u32, _loc: *mut core::ffi::c_void) -> u32 {
19886 crate::towlower(c)
19887}
19888
19889#[no_mangle]
19890pub unsafe extern "C" fn __towupper_l(c: u32, _loc: *mut core::ffi::c_void) -> u32 {
19891 crate::towupper(c)
19892}
19893
19894#[no_mangle]
19895pub unsafe extern "C" fn __towctrans_l(c: u32, _trans: u32, _loc: *mut core::ffi::c_void) -> u32 {
19896 c
19897}
19898
19899#[no_mangle]
19912pub 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) {
19913 crate::write(2, b"Assertion failed: ".as_ptr() as *const core::ffi::c_void, 18);
19914 if !expr.is_null() { crate::write(2, expr as *const core::ffi::c_void, crate::strlen(expr)); }
19915 crate::write(2, b" (".as_ptr() as *const core::ffi::c_void, 2);
19916 if !file.is_null() { crate::write(2, file as *const core::ffi::c_void, crate::strlen(file)); }
19917 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
19918 let mut n = line as usize;
19919 let mut digits: [u8; 32] = [0; 32];
19920 let mut di = 0;
19921 if n == 0 { digits[0] = 0; di = 1; }
19922 while n > 0 && di < 32 { digits[di] = (n % 10) as u8; n /= 10; di += 1; }
19923 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); }
19924 crate::write(2, b")".as_ptr() as *const core::ffi::c_void, 1);
19925 if !func.is_null() { crate::write(2, func as *const core::ffi::c_void, crate::strlen(func)); }
19926 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
19927 crate::abort()
19928}
19929
19930#[no_mangle]
19931pub unsafe extern "C" fn at_quick_exit(_func: Option<unsafe extern "C" fn()>) -> i32 {
19932 0
19934}
19935
19936#[no_mangle]
19937pub unsafe extern "C" fn brk(addr: *mut u8) -> i32 {
19938 syscall_ret(<Arch as Syscalls>::syscall1(sysno(12, 214), addr as i64)) as i32
19939}
19940
19941#[no_mangle]
19942pub 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 {
19943 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
19944}
19945
19946#[no_mangle]
19947pub unsafe extern "C" fn ctermid(s: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
19948 static mut BUF: [core::ffi::c_char; 20] = [0; 20];
19949 let dst = if s.is_null() { BUF.as_mut_ptr() } else { s };
19950 let src = b"/dev/tty\0".as_ptr() as *const core::ffi::c_char;
19951 let mut i = 0;
19952 while i < 9 { *dst.add(i) = *src.add(i); i += 1; }
19953 dst
19954}
19955
19956#[no_mangle]
19957pub unsafe extern "C" fn delete_module(name: *const core::ffi::c_char, flags: u32) -> i32 {
19958 syscall_ret(<Arch as Syscalls>::syscall2(SYS_DELETE_MODULE, name as i64, flags as i64)) as i32
19959}
19960
19961
19962
19963
19964
19965#[no_mangle]
19966pub unsafe extern "C" fn __duplocale(loc: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
19967 loc
19968}
19969
19970#[no_mangle]
19971pub unsafe extern "C" fn euidaccess(pathname: *const core::ffi::c_char, mode: i32) -> i32 {
19972 faccessat(AT_FDCWD, pathname, mode, 0x200)
19973}
19974
19975#[no_mangle]
19976pub unsafe extern "C" fn fgetln(f: *mut core::ffi::c_void, lenp: *mut usize) -> *mut core::ffi::c_char {
19977 static mut BUF: *mut core::ffi::c_char = core::ptr::null_mut();
19978 static mut CAP: usize = 0;
19979 let n = getline(&raw mut BUF, &raw mut CAP, f as *mut FILE);
19980 if n <= 0 {
19981 if !lenp.is_null() { *lenp = 0; }
19982 return core::ptr::null_mut();
19983 }
19984 if !lenp.is_null() { *lenp = n as usize; }
19985 BUF
19986}
19987
19988#[no_mangle]
19989pub unsafe extern "C" fn fgetws(ws: *mut u32, n: i32, f: *mut core::ffi::c_void) -> *mut u32 {
19990 let mut i = 0;
19991 while i < n - 1 {
19992 let c = getwc(f as *mut core::ffi::c_void);
19993 if c == 0 { break; }
19994 *ws.add(i as usize) = c;
19995 i += 1;
19996 if c == '\n' as u32 { break; }
19997 }
19998 *ws.add(i as usize) = 0;
19999 if i == 0 { core::ptr::null_mut() } else { ws }
20000}
20001
20002#[no_mangle]
20003pub 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 {
20004 if !label.is_null() { crate::write(2, label as *const core::ffi::c_void, crate::strlen(label)); }
20005 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
20006 if !text.is_null() { crate::write(2, text as *const core::ffi::c_void, crate::strlen(text)); }
20007 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20008 0
20009}
20010
20011#[no_mangle]
20012pub unsafe extern "C" fn ftime(tp: *mut core::ffi::c_void) -> i32 {
20013 let mut tv: timeval = core::mem::zeroed();
20014 if gettimeofday(&mut tv, core::ptr::null_mut()) == 0 {
20015 let tb = tp as *mut Timeb;
20016 (*tb).time = tv.tv_sec;
20017 (*tb).millitm = (tv.tv_usec / 1000) as u16;
20018 (*tb).timezone = 0;
20019 (*tb).dstflag = 0;
20020 0
20021 } else {
20022 -1
20023 }
20024}
20025
20026#[no_mangle]
20027pub unsafe extern "C" fn getdents(fd: i32, dirp: *mut u8, count: usize) -> isize {
20028 syscall_ret(<Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, dirp as i64, count as i64)) as isize
20029}
20030
20031#[no_mangle]
20032pub unsafe extern "C" fn gethostid() -> i64 {
20033 let fd = crate::open(b"/proc/sys/kernel/random/boot_id\0".as_ptr() as *const core::ffi::c_char, 0, 0);
20035 if fd < 0 { return 0; }
20036 let mut buf: [u8; 64] = [0; 64];
20037 let n = crate::read(fd, buf.as_mut_ptr() as *mut core::ffi::c_void, 63);
20038 crate::close(fd);
20039 if n <= 0 { return 0; }
20040 buf[n as usize] = 0;
20041 crate::strtol(buf.as_ptr() as *const core::ffi::c_char, core::ptr::null_mut(), 16)
20042}
20043
20044#[no_mangle]
20045pub unsafe extern "C" fn getpass(prompt: *const core::ffi::c_char) -> *mut core::ffi::c_char {
20046 static mut BUF: [core::ffi::c_char; 256] = [0; 256];
20047 crate::write(2, prompt as *const core::ffi::c_void, crate::strlen(prompt));
20049 let n = crate::read(0, BUF.as_mut_ptr() as *mut core::ffi::c_void, 255);
20051 if n > 0 {
20052 let end = if BUF[(n - 1) as usize] == '\n' as c_char { n - 1 } else { n };
20053 BUF[end as usize] = 0;
20054 } else {
20055 BUF[0] = 0;
20056 }
20057 BUF.as_mut_ptr()
20058}
20059
20060#[no_mangle]
20061pub 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 {
20062 let s = *optionp;
20063 if s.is_null() { return -1; }
20064 let mut end = s;
20066 while *end != 0 && *end != ',' as c_char && *end != '=' as c_char { end = end.add(1); }
20067 let eq = *end == '=' as c_char;
20068 if eq { *end = 0; *valuep = end.add(1); }
20069 let mut i = 0;
20071 loop {
20072 let tok = *tokens.add(i);
20073 if tok.is_null() { break; }
20074 if crate::strcmp(s as *const u8, tok as *const u8) == 0 {
20075 while *end != 0 && *end != ',' as c_char { end = end.add(1); }
20077 if *end == ',' as c_char { end = end.add(1); }
20078 *optionp = end;
20079 return i as i32;
20080 }
20081 i += 1;
20082 }
20083 -1
20084}
20085
20086#[no_mangle]
20087pub unsafe extern "C" fn getw(f: *mut core::ffi::c_void) -> i32 {
20088 let c0 = getc(f as *mut FILE);
20089 if c0 < 0 { return -1; }
20090 let c1 = getc(f as *mut FILE);
20091 if c1 < 0 { return -1; }
20092 let c2 = getc(f as *mut FILE);
20093 if c2 < 0 { return -1; }
20094 let c3 = getc(f as *mut FILE);
20095 if c3 < 0 { return -1; }
20096 (c0 | (c1 << 8) | (c2 << 16) | (c3 << 24)) as i32
20097}
20098
20099#[no_mangle]
20100pub unsafe extern "C" fn getwc(f: *mut core::ffi::c_void) -> u32 {
20101 getc(f as *mut FILE) as u32
20102}
20103
20104#[no_mangle]
20105pub unsafe extern "C" fn init_module(module_image: *mut u8, len: usize, param_values: *const core::ffi::c_char) -> i32 {
20106 syscall_ret(<Arch as Syscalls>::syscall3(SYS_INIT_MODULE, module_image as i64, len as i64, param_values as i64)) as i32
20107}
20108
20109
20110
20111#[no_mangle]
20112pub unsafe extern "C" fn issetugid() -> i32 {
20113 let ruid = crate::getuid();
20114 let euid = crate::geteuid();
20115 let rgid = crate::getgid();
20116 let egid = crate::getegid();
20117 (ruid != euid || rgid != egid) as i32
20118}
20119
20120#[repr(C)]
20125struct PollTimespec {
20126 tv_sec: i64,
20127 tv_nsec: i64,
20128}
20129
20130#[no_mangle]
20131pub unsafe extern "C" fn poll(fds: *mut core::ffi::c_void, nfds: u32, timeout: i32) -> i32 {
20132 #[cfg(target_arch = "x86_64")]
20133 { syscall_ret(<Arch as Syscalls>::syscall3(SYS_POLL, fds as i64, nfds as i64, timeout as i64)) as i32 }
20134 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
20135 {
20136 let mut ts = PollTimespec { tv_sec: 0, tv_nsec: 0 };
20140 let ts_ptr = if timeout < 0 {
20141 core::ptr::null()
20142 } else {
20143 ts.tv_sec = (timeout / 1000) as i64;
20144 ts.tv_nsec = ((timeout % 1000) as i64) * 1_000_000;
20145 &ts as *const PollTimespec as *const core::ffi::c_void
20146 };
20147 syscall_ret(<Arch as Syscalls>::syscall5(
20148 SYS_PPOLL,
20149 fds as i64,
20150 nfds as i64,
20151 ts_ptr as i64,
20152 0,
20153 8,
20154 )) as i32
20155 }
20156}
20157
20158#[no_mangle]
20159pub unsafe extern "C" fn ppoll(fds: *mut core::ffi::c_void, nfds: u32, timeout: *const core::ffi::c_void, sigmask: *const u64) -> i32 {
20160 syscall_ret(<Arch as Syscalls>::syscall5(SYS_PPOLL, fds as i64, nfds as i64, timeout as i64, sigmask as i64, 8)) as i32
20161}
20162
20163#[no_mangle]
20164pub 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 {
20165 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
20166}
20167
20168#[no_mangle]
20177pub unsafe extern "C" fn quick_exit(status: i32) -> ! {
20178 crate::_exit(status)
20179}
20180
20181#[no_mangle]
20186pub unsafe extern "C" fn lstat(path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
20187 let r = <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, AT_FDCWD as i64, path as i64, buf as i64, 0x100);
20188 if r < 0 {
20189 ERRNO!() = (-r) as c_int;
20190 -1
20191 } else {
20192 0
20193 }
20194}
20195
20196#[no_mangle]
20197pub unsafe extern "C" fn __xstat(_ver: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
20198 crate::stat(path, buf as *mut Stat)
20199}
20200
20201#[no_mangle]
20202pub unsafe extern "C" fn __lxstat(_ver: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
20203 crate::lstat(path, buf)
20204}
20205
20206#[no_mangle]
20207pub unsafe extern "C" fn __fxstat(_ver: i32, fd: i32, buf: *mut core::ffi::c_void) -> i32 {
20208 crate::fstat(fd, buf as *mut Stat)
20209}
20210
20211#[no_mangle]
20212pub unsafe extern "C" fn __fxstatat(_ver: i32, _dirfd: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void, _flags: i32) -> i32 {
20213 crate::stat(path, buf as *mut Stat)
20214}
20215
20216#[no_mangle]
20221pub unsafe extern "C" fn mempcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
20222 core::ptr::copy_nonoverlapping(src, dest, n);
20223 dest.add(n)
20224}
20225
20226#[no_mangle]
20231pub unsafe extern "C" fn mkostemp(template: *mut core::ffi::c_char, _flags: i32) -> i32 {
20232 mkstemp(template)
20233}
20234
20235#[no_mangle]
20236pub unsafe extern "C" fn mkstemps(template: *mut core::ffi::c_char, suffixlen: i32) -> i32 {
20237 mkstemps_impl(template, suffixlen)
20238}
20239
20240#[no_mangle]
20245pub unsafe extern "C" fn ptrace(request: i32, mut args: ...) -> i64 {
20246 let pid = args.next_arg::<c_long>();
20247 let addr = args.next_arg::<c_long>();
20248 let data = args.next_arg::<c_long>();
20249 if (1..=3).contains(&request) {
20252 let mut result: c_long = 0;
20253 let r = <Arch as Syscalls>::syscall4(
20254 sysno(101, 117),
20255 request as i64,
20256 pid,
20257 addr,
20258 &mut result as *mut c_long as i64,
20259 );
20260 if r < 0 {
20261 ERRNO!() = (-r) as c_int;
20262 return -1;
20263 }
20264 return result;
20265 }
20266 syscall_ret(<Arch as Syscalls>::syscall4(sysno(101, 117), request as i64, pid, addr, data))
20267}
20268
20269#[no_mangle]
20270pub unsafe extern "C" fn personality(persona: u64) -> i64 {
20271 <Arch as Syscalls>::syscall1(sysno(135, 92), persona as i64)
20272}
20273
20274#[no_mangle]
20275pub unsafe extern "C" fn reboot(cmd: c_int) -> i32 {
20276 syscall_ret(<Arch as Syscalls>::syscall3(
20278 SYS_REBOOT,
20279 0xfee1dead,
20280 672274793,
20281 cmd as i64,
20282 )) as i32
20283}
20284
20285#[no_mangle]
20286pub unsafe extern "C" fn pivot_root(new_root: *const core::ffi::c_char, put_old: *const core::ffi::c_char) -> i32 {
20287 syscall_ret(<Arch as Syscalls>::syscall2(SYS_PIVOT_ROOT, new_root as i64, put_old as i64)) as i32
20288}
20289
20290#[no_mangle]
20291pub 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 {
20292 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
20293}
20294
20295#[no_mangle]
20296pub unsafe extern "C" fn umount(target: *const core::ffi::c_char) -> i32 {
20297 syscall_ret(<Arch as Syscalls>::syscall2(SYS_UMOUNT2, target as i64, 0)) as i32
20298}
20299
20300#[no_mangle]
20301pub unsafe extern "C" fn umount2(target: *const core::ffi::c_char, flags: i32) -> i32 {
20302 syscall_ret(<Arch as Syscalls>::syscall2(SYS_UMOUNT2, target as i64, flags as i64)) as i32
20303}
20304
20305#[no_mangle]
20315pub unsafe extern "C" fn psiginfo(_pinfo: *const core::ffi::c_void, s: *const core::ffi::c_char) {
20316 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
20317 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20318}
20319
20320#[no_mangle]
20321pub unsafe extern "C" fn psignal(sig: i32, s: *const core::ffi::c_char) {
20322 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
20323 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
20324 crate::write(2, strsignal(sig) as *const core::ffi::c_void, crate::strlen(strsignal(sig)));
20325 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20326}
20327
20328#[no_mangle]
20329pub unsafe extern "C" fn strsignal(sig: c_int) -> *const c_char {
20330 static NAMES: [&[u8]; 32] = [
20331 b"Unknown signal\0",
20332 b"Hangup\0",
20333 b"Interrupt\0",
20334 b"Quit\0",
20335 b"Illegal instruction\0",
20336 b"Trace/breakpoint trap\0",
20337 b"Aborted\0",
20338 b"Bus error\0",
20339 b"Floating point exception\0",
20340 b"Killed\0",
20341 b"User defined signal 1\0",
20342 b"Segmentation fault\0",
20343 b"User defined signal 2\0",
20344 b"Broken pipe\0",
20345 b"Alarm clock\0",
20346 b"Terminated\0",
20347 b"Stack fault\0",
20348 b"Child process status\0",
20349 b"Continued\0",
20350 b"Stopped (signal)\0",
20351 b"Stopped\0",
20352 b"Stopped (tty input)\0",
20353 b"Stopped (tty output)\0",
20354 b"Urgent I/O condition\0",
20355 b"CPU time limit exceeded\0",
20356 b"File size limit exceeded\0",
20357 b"Virtual timer expired\0",
20358 b"Profiling timer expired\0",
20359 b"Window changed\0",
20360 b"I/O possible\0",
20361 b"Power failure\0",
20362 b"Bad system call\0",
20363 ];
20364 static mut RT_BUF: [c_char; 32] = [0; 32];
20365 if sig > 0 && sig < 32 {
20366 return NAMES[sig as usize].as_ptr() as *const c_char;
20367 }
20368 if sig >= 32 && sig < 65 {
20369 let mut o = 0usize;
20370 for &c in b"Real-time signal \0" {
20371 if c == 0 { break; }
20372 RT_BUF[o] = c as c_char;
20373 o += 1;
20374 }
20375 let mut v = (sig - 32) as u32;
20376 let mut digits = [0u8; 10];
20377 let mut d = 0usize;
20378 if v == 0 { digits[0] = b'0'; d = 1; }
20379 while v > 0 { digits[d] = b'0' + (v % 10) as u8; v /= 10; d += 1; }
20380 while d > 0 { d -= 1; RT_BUF[o] = digits[d] as c_char; o += 1; }
20381 RT_BUF[o] = 0;
20382 return RT_BUF.as_ptr();
20383 }
20384 b"Unknown signal\0".as_ptr() as *const c_char
20385}
20386
20387#[no_mangle]
20388pub unsafe extern "C" fn __strerror_l(errnum: i32, _loc: *mut core::ffi::c_void) -> *const core::ffi::c_char {
20389 crate::strerror(errnum)
20390}
20391
20392#[no_mangle]
20397pub unsafe extern "C" fn preadv(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64) -> isize {
20398 syscall_ret(<Arch as Syscalls>::syscall5(
20401 sysno(295, 69),
20402 fd as i64,
20403 iov as i64,
20404 iovcnt as i64,
20405 offset,
20406 offset >> 32,
20407 )) as isize
20408}
20409
20410#[no_mangle]
20411pub unsafe extern "C" fn pwritev(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64) -> isize {
20412 syscall_ret(<Arch as Syscalls>::syscall5(
20413 sysno(296, 70),
20414 fd as i64,
20415 iov as i64,
20416 iovcnt as i64,
20417 offset,
20418 offset >> 32,
20419 )) as isize
20420}
20421
20422#[no_mangle]
20423pub unsafe extern "C" fn preadv2(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64, flags: u32) -> isize {
20424 syscall_ret(<Arch as Syscalls>::syscall6(
20427 sysno(327, 286),
20428 fd as i64,
20429 iov as i64,
20430 iovcnt as i64,
20431 offset,
20432 offset >> 32,
20433 flags as i64,
20434 )) as isize
20435}
20436
20437#[no_mangle]
20438pub unsafe extern "C" fn pwritev2(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64, flags: u32) -> isize {
20439 syscall_ret(<Arch as Syscalls>::syscall6(
20440 sysno(328, 287),
20441 fd as i64,
20442 iov as i64,
20443 iovcnt as i64,
20444 offset,
20445 offset >> 32,
20446 flags as i64,
20447 )) as isize
20448}
20449
20450#[no_mangle]
20455pub unsafe extern "C" fn nice(inc: i32) -> i32 {
20456 let mut prio = inc;
20457 if inc > -40 && inc < 40 {
20458 prio += getpriority(0, 0);
20459 }
20460 if prio > 19 { prio = 19; }
20461 if prio < -20 { prio = -20; }
20462 if setpriority(0, 0, prio) != 0 {
20463 if ERRNO!() == 13 { ERRNO!() = 1; } return -1;
20465 }
20466 prio
20467}
20468
20469#[no_mangle]
20474pub unsafe extern "C" fn l64a(value: i64) -> *mut core::ffi::c_char {
20475 static mut BUF: [core::ffi::c_char; 7] = [0; 7];
20476 let mut v = value as u64;
20477 let mut i = 0;
20478 while v > 0 && i < 6 {
20479 let c = (v & 0x3f) as u8;
20480 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;
20481 v >>= 6;
20482 i += 1;
20483 }
20484 BUF[i] = 0;
20485 BUF.as_mut_ptr()
20486}
20487
20488#[no_mangle]
20489pub unsafe extern "C" fn lchmod(path: *const core::ffi::c_char, mode: u32) -> i32 {
20490 syscall_ret(<Arch as Syscalls>::syscall4(SYS_FCHMODAT, AT_FDCWD as i64, path as i64, mode as i64, 0x100)) as i32
20491}
20492
20493#[no_mangle]
20494pub unsafe extern "C" fn lutimes(filename: *const core::ffi::c_char, times: *const core::ffi::c_void) -> i32 {
20495 utimensat(AT_FDCWD, filename, times as *const timespec, 0x100)
20496}
20497
20498#[no_mangle]
20499pub unsafe extern "C" fn mknod(pathname: *const core::ffi::c_char, mode: u32, dev: u64) -> i32 {
20500 #[cfg(target_arch = "x86_64")]
20501 { syscall_ret(<Arch as Syscalls>::syscall3(SYS_MKNOD, pathname as i64, mode as i64, dev as i64)) as i32 }
20502 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
20503 {
20504 syscall_ret(<Arch as Syscalls>::syscall4(SYS_MKNODAT, AT_FDCWD as i64, pathname as i64, mode as i64, dev as i64)) as i32
20505 }
20506}
20507
20508#[no_mangle]
20509pub unsafe extern "C" fn memfd_create(name: *const core::ffi::c_char, flags: u32) -> i32 {
20510 syscall_ret(<Arch as Syscalls>::syscall2(sysno(319, 279), name as i64, flags as i64)) as i32
20511}
20512
20513#[no_mangle]
20514pub unsafe extern "C" fn mlock2(addr: *const core::ffi::c_void, len: usize, flags: u32) -> i32 {
20515 syscall_ret(<Arch as Syscalls>::syscall3(sysno(325, 284), addr as i64, len as i64, flags as i64)) as i32
20516}
20517
20518
20519
20520#[no_mangle]
20521pub unsafe extern "C" fn remap_file_pages(addr: *mut core::ffi::c_void, size: usize, prot: i32, pgoff: usize, flags: u32) -> i32 {
20522 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
20523}
20524
20525#[no_mangle]
20530pub unsafe extern "C" fn nan(_tagp: *const core::ffi::c_char) -> f64 {
20531 f64::NAN
20532}
20533
20534#[no_mangle]
20535pub unsafe extern "C" fn nanf(_tagp: *const core::ffi::c_char) -> f32 {
20536 f32::NAN
20537}
20538
20539#[no_mangle]
20544pub unsafe extern "C" fn __lgammal_r(x: f64, signgamp: *mut i32) -> f64 {
20545 *signgamp = 1;
20546 lgamma(x)
20547}
20548
20549#[no_mangle]
20550pub unsafe extern "C" fn __libc_current_sigrtmax() -> i32 {
20551 64
20552}
20553
20554#[no_mangle]
20555pub unsafe extern "C" fn _longjmp(env: *mut core::ffi::c_void, val: i32) {
20556 crate::longjmp(env as *mut u64, val)
20557}
20558
20559#[no_mangle]
20560pub unsafe extern "C" fn __newlocale(_mask: i32, _name: *const core::ffi::c_char, base: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
20561 base
20562}
20563
20564#[no_mangle]
20565pub unsafe extern "C" fn __nl_langinfo(_item: i32) -> *mut core::ffi::c_char {
20566 b"\0".as_ptr() as *mut core::ffi::c_char
20567}
20568
20569#[no_mangle]
20570pub unsafe extern "C" fn __nl_langinfo_l(_item: i32, _loc: *mut core::ffi::c_void) -> *mut core::ffi::c_char {
20571 b"\0".as_ptr() as *mut core::ffi::c_char
20572}
20573
20574#[no_mangle]
20575pub unsafe extern "C" fn ns_get16(cp: *const u8) -> u16 {
20576 ((*cp.add(0) as u16) << 8) | *cp.add(1) as u16
20577}
20578
20579#[no_mangle]
20580pub unsafe extern "C" fn ns_get32(cp: *const u8) -> u32 {
20581 ((*cp.add(0) as u32) << 24) | ((*cp.add(1) as u32) << 16) | ((*cp.add(2) as u32) << 8) | *cp.add(3) as u32
20582}
20583
20584#[no_mangle]
20585pub unsafe extern "C" fn ns_put16(s: u16, dst: *mut u8) {
20586 *dst.add(0) = (s >> 8) as u8;
20587 *dst.add(1) = (s & 0xff) as u8;
20588}
20589
20590#[no_mangle]
20591pub unsafe extern "C" fn ns_put32(l: u32, dst: *mut u8) {
20592 *dst.add(0) = (l >> 24) as u8;
20593 *dst.add(1) = ((l >> 16) & 0xff) as u8;
20594 *dst.add(2) = ((l >> 8) & 0xff) as u8;
20595 *dst.add(3) = (l & 0xff) as u8;
20596}
20597
20598#[no_mangle]
20599pub unsafe extern "C" fn posix_close(fd: i32) -> i32 {
20600 crate::close(fd)
20601}
20602
20603#[no_mangle]
20604pub unsafe extern "C" fn posix_openpt(flags: i32) -> i32 {
20605 crate::open(b"/dev/ptmx\0".as_ptr() as *const core::ffi::c_char, flags, 0)
20606}
20607
20608#[no_mangle]
20609pub unsafe extern "C" fn putw(w: i32, f: *mut core::ffi::c_void) {
20610 putc((w & 0xff) as i32, f as *mut FILE);
20611 putc(((w >> 8) & 0xff) as i32, f as *mut FILE);
20612 putc(((w >> 16) & 0xff) as i32, f as *mut FILE);
20613 putc(((w >> 24) & 0xff) as i32, f as *mut FILE);
20614}
20615
20616
20617
20618#[no_mangle]
20619pub unsafe extern "C" fn rand_r(seedp: *mut u32) -> i32 {
20620 let seed = (*seedp).wrapping_mul(1103515245).wrapping_add(12345);
20621 *seedp = seed;
20622 ((seed >> 16) & 0x7fff) as i32
20623}
20624
20625#[no_mangle]
20626pub unsafe extern "C" fn reallocarray(ptr: *mut core::ffi::c_void, nmemb: usize, size: usize) -> *mut core::ffi::c_void {
20627 let total = match nmemb.checked_mul(size) {
20628 Some(v) => v,
20629 None => { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
20630 };
20631 crate::realloc(ptr, total)
20632}
20633
20634#[no_mangle]
20635pub unsafe extern "C" fn __res_state() -> *mut core::ffi::c_void {
20636 static mut STATE: [u8; 512] = [0; 512];
20637 STATE.as_mut_ptr() as *mut core::ffi::c_void
20638}
20639
20640#[no_mangle]
20641pub unsafe extern "C" fn sbrk(increment: isize) -> *mut u8 {
20642 if increment != 0 {
20645 ERRNO!() = ENOMEM;
20646 return -1isize as usize as *mut u8;
20647 }
20648 <Arch as Syscalls>::syscall1(sysno(12, 214), 0) as *mut u8
20649}
20650
20651#[no_mangle]
20652pub unsafe extern "C" fn scalb(x: f64, exp: f64) -> f64 {
20653 if x.is_nan() || exp.is_nan() { return x * exp; }
20654 if !exp.is_finite() {
20655 let r = if exp > 0.0 { x * exp } else { x / (-exp) };
20656 if r.is_nan() && !x.is_nan() {
20657 feraiseexcept(FE_INVALID);
20658 }
20659 return r;
20660 }
20661 if libm::rint(exp) != exp {
20662 return __math_invalid(exp);
20663 }
20664 if exp > 65000.0 { return libm::scalbn(x, 65000); }
20665 if -exp > 65000.0 { return libm::scalbn(x, -65000); }
20666 libm::scalbn(x, exp as i32)
20667}
20668
20669#[no_mangle]
20670pub unsafe extern "C" fn scalbf(x: f32, exp: f32) -> f32 {
20671 if x.is_nan() || exp.is_nan() { return x * exp; }
20672 if !exp.is_finite() {
20673 let r = if exp > 0.0 { x * exp } else { x / (-exp) };
20674 if r.is_nan() && !x.is_nan() {
20675 feraiseexcept(FE_INVALID);
20676 }
20677 return r;
20678 }
20679 if libm::rintf(exp) != exp {
20680 return __math_invalidf(exp);
20681 }
20682 if exp > 65000.0 { return libm::scalbnf(x, 65000); }
20683 if -exp > 65000.0 { return libm::scalbnf(x, -65000); }
20684 libm::scalbnf(x, exp as i32)
20685}
20686
20687#[no_mangle]
20688pub unsafe extern "C" fn __sched_cpucount(setsize: usize, setp: *const u8) -> i32 {
20689 let mut count = 0;
20690 let mut i = 0;
20691 while i < setsize * 8 {
20692 if (*setp.add(i / 8) >> (i % 8)) & 1 != 0 { count += 1; }
20693 i += 1;
20694 }
20695 count
20696}
20697
20698
20699
20700#[no_mangle]
20701pub unsafe extern "C" fn select(nfds: i32, readfds: *mut u8, writefds: *mut u8, exceptfds: *mut u8, timeout: *mut core::ffi::c_void) -> i32 {
20702 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
20703}
20704
20705
20706
20707#[no_mangle]
20708pub unsafe extern "C" fn sendfile(out_fd: i32, in_fd: i32, offset: *mut i64, count: usize) -> isize {
20709 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
20710}
20711
20712
20713
20714
20715
20716#[no_mangle]
20717pub unsafe extern "C" fn __setjmp(env: *mut core::ffi::c_void) -> i32 {
20718 crate::setjmp(env as *mut u64)
20719}
20720
20721#[no_mangle]
20722pub unsafe extern "C" fn _setjmp(env: *mut core::ffi::c_void) -> i32 {
20723 crate::setjmp(env as *mut u64)
20724}
20725
20726#[no_mangle]
20727pub unsafe extern "C" fn setlinebuf(stream: *mut core::ffi::c_void) {
20728 setvbuf(stream as *mut FILE, core::ptr::null_mut(), 1, 0);
20729}
20730
20731
20732
20733
20734
20735
20736
20737
20738
20739
20740
20741
20742
20743
20744
20745#[no_mangle]
20746pub unsafe extern "C" fn significand(x: f64) -> f64 {
20747 let bits = x.to_bits();
20748 let exp = ((bits >> 52) & 0x7ff) as i32;
20749 if exp == 0 || exp == 0x7ff { return x; }
20750 f64::from_bits((bits & 0x000fffffffffffff) | (1023u64 << 52))
20751}
20752
20753#[no_mangle]
20754pub unsafe extern "C" fn significandf(x: f32) -> f32 {
20755 let bits = x.to_bits();
20756 let exp = ((bits >> 23) & 0xff) as i32;
20757 if exp == 0 || exp == 0xff { return x; }
20758 f32::from_bits((bits & 0x007fffff) | (127u32 << 23))
20759}
20760
20761
20762
20763
20764
20765#[no_mangle]
20766pub unsafe extern "C" fn sigset(sig: i32, handler: usize) -> usize {
20767 signal(sig, handler)
20769}
20770
20771#[no_mangle]
20772pub unsafe extern "C" fn sincos(x: f64, sin: *mut f64, cos: *mut f64) {
20773 *sin = libm::sin(x);
20774 *cos = libm::cos(x);
20775}
20776
20777#[no_mangle]
20778pub unsafe extern "C" fn sincosf(x: f32, sin: *mut f32, cos: *mut f32) {
20779 *sin = libm::sinf(x);
20780 *cos = libm::cosf(x);
20781}
20782
20783
20784
20785
20786
20787
20788
20789
20790
20791unsafe fn nd_ascii_lower(c: c_char) -> c_int {
20792 let b = c as u8;
20793 if b >= b'A' && b <= b'Z' { (b + 32) as c_int } else { b as c_int }
20794}
20795
20796unsafe fn nd_strncasecmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int {
20797 let mut i = 0usize;
20798 while i < n {
20799 let c1 = nd_ascii_lower(*s1.add(i));
20800 let c2 = nd_ascii_lower(*s2.add(i));
20801 if c1 != c2 || c1 == 0 { return c1 - c2; }
20802 i += 1;
20803 }
20804 0
20805}
20806
20807#[no_mangle]
20808pub unsafe extern "C" fn strcasecmp(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char) -> i32 {
20809 nd_strncasecmp(s1, s2, usize::MAX)
20810}
20811
20812#[no_mangle]
20813pub 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 {
20814 nd_strncasecmp(s1, s2, usize::MAX)
20815}
20816
20817#[no_mangle]
20818pub unsafe extern "C" fn strcasestr(haystack: *const core::ffi::c_char, needle: *const core::ffi::c_char) -> *mut core::ffi::c_char {
20819 let nlen = crate::strlen(needle);
20820 if nlen == 0 { return haystack as *mut core::ffi::c_char; }
20821 let mut i = 0;
20822 loop {
20823 let h = haystack.add(i);
20824 if *h == 0 { return core::ptr::null_mut(); }
20825 if crate::strncasecmp(h, needle, nlen) == 0 { return h as *mut core::ffi::c_char; }
20826 i += 1;
20827 }
20828}
20829
20830#[no_mangle]
20831pub 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 {
20832 crate::strcmp(s1 as *const u8, s2 as *const u8)
20833}
20834
20835#[no_mangle]
20836pub unsafe extern "C" fn strncasecmp(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char, n: usize) -> i32 {
20837 nd_strncasecmp(s1, s2, n)
20838}
20839
20840#[no_mangle]
20841pub 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 {
20842 nd_strncasecmp(s1, s2, n)
20843}
20844
20845#[no_mangle]
20846pub unsafe extern "C" fn strsep(stringp: *mut *mut core::ffi::c_char, delim: *const core::ffi::c_char) -> *mut core::ffi::c_char {
20847 let s = *stringp;
20848 if s.is_null() { return core::ptr::null_mut(); }
20849 let mut p = s;
20850 while *p != 0 {
20851 let mut d = delim;
20852 while *d != 0 {
20853 if *p == *d { *p = 0; *stringp = p.add(1); return s; }
20854 d = d.add(1);
20855 }
20856 p = p.add(1);
20857 }
20858 *stringp = core::ptr::null_mut();
20859 s
20860}
20861
20862#[no_mangle]
20863pub unsafe extern "C" fn strtoimax(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, base: i32) -> i64 {
20864 crate::strtol(nptr, endptr, base)
20865}
20866
20867#[no_mangle]
20868pub 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 {
20869 let mut s = if s.is_null() { *saveptr } else { s };
20870 if s.is_null() { return core::ptr::null_mut(); }
20871 while *s != 0 {
20873 let mut d = delim;
20874 let mut found = false;
20875 while *d != 0 {
20876 if *s == *d { found = true; break; }
20877 d = d.add(1);
20878 }
20879 if !found { break; }
20880 s = s.add(1);
20881 }
20882 if *s == 0 { *saveptr = s; return core::ptr::null_mut(); }
20883 let start = s;
20884 while *s != 0 {
20886 let mut d = delim;
20887 while *d != 0 {
20888 if *s == *d { *s = 0; *saveptr = s.add(1); return start; }
20889 d = d.add(1);
20890 }
20891 s = s.add(1);
20892 }
20893 *saveptr = s;
20894 start
20895}
20896
20897#[no_mangle]
20898pub unsafe extern "C" fn strtoumax(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, base: i32) -> u64 {
20899 crate::strtoul(nptr, endptr, base) as u64
20900}
20901
20902#[no_mangle]
20903pub 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 {
20904 crate::strlcpy(dest as *mut u8, src as *const u8, n)
20905}
20906
20907#[no_mangle]
20908pub unsafe extern "C" fn swab(src: *const u8, dest: *mut u8, nbytes: isize) {
20909 let mut i = 0;
20910 while i + 1 < nbytes {
20911 let a = *src.add(i as usize);
20912 let b = *src.add(i as usize + 1);
20913 *dest.add(i as usize) = b;
20914 *dest.add(i as usize + 1) = a;
20915 i += 2;
20916 }
20917}
20918
20919
20920
20921
20922
20923
20924
20925
20926
20927
20928
20929#[no_mangle]
20930pub unsafe extern "C" fn __tolower_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20931 if c >= 'A' as i32 && c <= 'Z' as i32 { c + 32 } else { c }
20932}
20933
20934#[no_mangle]
20935pub unsafe extern "C" fn __toupper_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20936 if c >= 'a' as i32 && c <= 'z' as i32 { c - 32 } else { c }
20937}
20938
20939#[no_mangle]
20940pub unsafe extern "C" fn ulimit(cmd: c_int, mut args: ...) -> c_long {
20941 let mut rl: Rlimit = core::mem::zeroed();
20942 if getrlimit(RLIMIT_FSIZE, &mut rl) != 0 { return -1; }
20943 if cmd == 2 {
20944 let val = args.next_arg::<c_long>();
20945 rl.rlim_cur = 512u64.wrapping_mul(val as u64);
20946 if setrlimit(RLIMIT_FSIZE, &rl) != 0 { return -1; }
20947 }
20948 (rl.rlim_cur / 512) as c_long
20949}
20950
20951#[repr(C)]
20952struct UtsName {
20953 sysname: [u8; 65],
20954 nodename: [u8; 65],
20955 release: [u8; 65],
20956 version: [u8; 65],
20957 machine: [u8; 65],
20958 domainname: [u8; 65],
20959}
20960
20961#[no_mangle]
20962pub unsafe extern "C" fn uname(buf: *mut c_void) -> c_int {
20963 let r = <Arch as Syscalls>::syscall1(SYS_UNAME, buf as i64);
20966 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
20967 0
20968}
20969
20970#[no_mangle]
20971pub unsafe extern "C" fn unshare(flags: i32) -> i32 {
20972 let r = <Arch as Syscalls>::syscall1(SYS_UNSHARE, flags as i64);
20973 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
20974}
20975
20976#[no_mangle]
20977pub unsafe extern "C" fn updwtmpx(wtmpx_file: *const core::ffi::c_char, utx: *const core::ffi::c_void) {
20978 updwtmp(wtmpx_file, utx)
20979}
20980
20981#[no_mangle]
20982pub unsafe extern "C" fn __uselocale(loc: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
20983 loc
20984}
20985
20986#[repr(C)]
20987pub struct Utimbuf { actime: i64, modtime: i64 }
20988
20989#[no_mangle]
20990pub unsafe extern "C" fn utime(filename: *const c_char, times: *const Utimbuf) -> c_int {
20991 if times.is_null() {
20992 return utimensat(AT_FDCWD, filename, core::ptr::null(), 0);
20993 }
20994 let ts = [
20995 timespec { tv_sec: (*times).actime, tv_nsec: 0 },
20996 timespec { tv_sec: (*times).modtime, tv_nsec: 0 },
20997 ];
20998 utimensat(AT_FDCWD, filename, ts.as_ptr(), 0)
20999}
21000
21001#[no_mangle]
21002pub unsafe extern "C" fn vhangup() -> c_int {
21003 let r = <Arch as Syscalls>::syscall0(SYS_VHANGUP);
21004 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21005}
21006
21007#[no_mangle]
21008pub unsafe extern "C" fn vmsplice(fd: i32, iov: *const c_void, nr_segs: usize, flags: u32) -> isize {
21009 let r = <Arch as Syscalls>::syscall4(SYS_VMSPLICE, fd as i64, iov as i64, nr_segs as i64, flags as i64);
21010 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
21011}
21012
21013
21014
21015#[no_mangle]
21016pub unsafe extern "C" fn wait4(pid: i32, wstatus: *mut i32, options: i32, rusage: *mut core::ffi::c_void) -> i32 {
21017 syscall_ret(<Arch as Syscalls>::syscall4(SYS_WAIT4, pid as i64, wstatus as i64, options as i64, rusage as i64)) as i32
21018}
21019
21020#[no_mangle]
21021pub unsafe extern "C" fn waitid(idtype: i32, id: u32, infop: *mut core::ffi::c_void, options: i32) -> i32 {
21022 syscall_ret(<Arch as Syscalls>::syscall5(
21025 sysno(247, 95),
21026 idtype as i64,
21027 id as i64,
21028 infop as i64,
21029 options as i64,
21030 0,
21031 )) as i32
21032}
21033
21034#[no_mangle]
21035pub unsafe extern "C" fn __wcscoll_l(s1: *const u32, s2: *const u32, _loc: *mut core::ffi::c_void) -> i32 {
21036 crate::wcscmp(s1 as *const i32, s2 as *const i32)
21037}
21038
21039#[no_mangle]
21040pub unsafe extern "C" fn __wcsxfrm_l(dest: *mut u32, src: *const u32, n: usize, _loc: *mut core::ffi::c_void) -> usize {
21041 crate::wcscpy(dest as *mut i32, src as *const i32);
21042 n
21043}
21044
21045#[no_mangle]
21046pub unsafe extern "C" fn wcwidth(c: u32) -> i32 {
21047 if c == 0 { return 0; }
21048 if c < 32 || (c >= 0x7f && c < 0xa0) { return -1; }
21049 1
21050}
21051
21052
21053
21054
21055
21056#[no_mangle]
21063pub 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 {
21064 crate::strtod(nptr, endptr)
21065}
21066
21067#[no_mangle]
21068pub 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 {
21069 crate::strtof(nptr, endptr)
21070}
21071
21072#[no_mangle]
21073pub 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 {
21074 crate::strtod(nptr, endptr)
21075}
21076
21077#[repr(C)]
21082struct linux_dirent64 {
21083 d_ino: u64,
21084 d_off: i64,
21085 d_reclen: u16,
21086 d_type: u8,
21087 d_name: [u8; 0], }
21089
21090const DIR_BUF_SIZE: usize = 4096;
21094
21095#[repr(C)]
21096struct DirStream {
21097 fd: i32,
21098 pos: usize,
21099 len: usize,
21100 last_off: i64,
21101 buf: [u8; DIR_BUF_SIZE],
21102}
21103
21104unsafe fn dir_stream_new(fd: i32) -> *mut core::ffi::c_void {
21105 let ds = malloc(core::mem::size_of::<DirStream>()) as *mut DirStream;
21106 if ds.is_null() {
21107 crate::close(fd);
21108 ERRNO!() = ENOMEM;
21109 return core::ptr::null_mut();
21110 }
21111 core::ptr::write_bytes(ds, 0, 1);
21112 (*ds).fd = fd;
21113 ds as *mut core::ffi::c_void
21114}
21115
21116#[no_mangle]
21117pub unsafe extern "C" fn opendir(dirname: *const core::ffi::c_char) -> *mut core::ffi::c_void {
21118 let fd = openat(AT_FDCWD, dirname, O_DIRECTORY, 0); if fd < 0 { return core::ptr::null_mut(); }
21120 dir_stream_new(fd)
21121}
21122
21123#[no_mangle]
21124pub unsafe extern "C" fn closedir(dirp: *mut core::ffi::c_void) -> i32 {
21125 if dirp.is_null() { ERRNO!() = 22; return -1; }
21126 let ds = dirp as *mut DirStream;
21127 let r = crate::close((*ds).fd);
21128 free(dirp);
21129 r
21130}
21131
21132#[no_mangle]
21133pub unsafe extern "C" fn readdir(dirp: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
21134 if dirp.is_null() { ERRNO!() = 22; return core::ptr::null_mut(); }
21135 let ds = &mut *(dirp as *mut DirStream);
21136
21137 loop {
21138 if ds.pos >= ds.len {
21139 let nread = syscall_ret(<Arch as Syscalls>::syscall3(
21140 SYS_GETDENTS64,
21141 ds.fd as i64,
21142 ds.buf.as_mut_ptr() as i64,
21143 DIR_BUF_SIZE as i64,
21144 )) as isize;
21145 if nread <= 0 { return core::ptr::null_mut(); }
21146 ds.len = nread as usize;
21147 ds.pos = 0;
21148 }
21149
21150 let ent = ds.buf.as_ptr().add(ds.pos) as *const linux_dirent64;
21151 let ent_ref = &*ent;
21152 if ent_ref.d_reclen as usize == 0 {
21153 ds.len = 0;
21154 return core::ptr::null_mut();
21155 }
21156 ds.pos += ent_ref.d_reclen as usize;
21157 ds.last_off = ent_ref.d_off;
21158
21159 return ent as *mut core::ffi::c_void;
21161 }
21162}
21163
21164#[no_mangle]
21165pub 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 {
21166 let ent = readdir(dirp);
21167 if ent.is_null() {
21168 *result = core::ptr::null_mut();
21169 } else {
21170 *result = ent;
21171 }
21172 0
21173}
21174
21175#[no_mangle]
21176pub unsafe extern "C" fn seekdir(dirp: *mut core::ffi::c_void, loc: i64) {
21177 if dirp.is_null() { return; }
21178 let ds = &mut *(dirp as *mut DirStream);
21179 <Arch as Syscalls>::syscall3(SYS_LSEEK, ds.fd as i64, loc, 0);
21180 ds.pos = 0;
21181 ds.len = 0;
21182}
21183
21184#[no_mangle]
21185pub unsafe extern "C" fn telldir(dirp: *mut core::ffi::c_void) -> i64 {
21186 if dirp.is_null() { return -1; }
21187 (*(dirp as *mut DirStream)).last_off
21188}
21189
21190#[no_mangle]
21191pub unsafe extern "C" fn rewinddir(dirp: *mut core::ffi::c_void) {
21192 if dirp.is_null() { return; }
21193 let ds = &mut *(dirp as *mut DirStream);
21194 <Arch as Syscalls>::syscall3(SYS_LSEEK, ds.fd as i64, 0, 0);
21195 ds.pos = 0;
21196 ds.len = 0;
21197 ds.last_off = 0;
21198}
21199
21200#[no_mangle]
21201pub unsafe extern "C" fn dirfd(dirp: *mut core::ffi::c_void) -> i32 {
21202 if dirp.is_null() { ERRNO!() = 22; return -1; }
21203 (*(dirp as *mut DirStream)).fd
21204}
21205
21206#[no_mangle]
21211pub unsafe extern "C" fn mprotect(addr: *mut u8, len: usize, prot: i32) -> i32 {
21212 syscall_ret(<Arch as Syscalls>::syscall3(SYS_MPROTECT, addr as i64, len as i64, prot as i64)) as i32
21213}
21214
21215#[no_mangle]
21216pub unsafe extern "C" fn msync(addr: *mut u8, len: usize, flags: i32) -> i32 {
21217 syscall_ret(<Arch as Syscalls>::syscall3(sysno(26, 227), addr as i64, len as i64, flags as i64)) as i32
21218}
21219
21220#[no_mangle]
21221pub unsafe extern "C" fn mlock(addr: *const u8, len: usize) -> i32 {
21222 syscall_ret(<Arch as Syscalls>::syscall2(sysno(149, 228), addr as i64, len as i64)) as i32
21223}
21224
21225#[no_mangle]
21226pub unsafe extern "C" fn munlock(addr: *const u8, len: usize) -> i32 {
21227 syscall_ret(<Arch as Syscalls>::syscall2(sysno(150, 229), addr as i64, len as i64)) as i32
21228}
21229
21230#[no_mangle]
21231pub unsafe extern "C" fn mlockall(flags: i32) -> i32 {
21232 syscall_ret(<Arch as Syscalls>::syscall1(sysno(151, 230), flags as i64)) as i32
21233}
21234
21235#[no_mangle]
21236pub unsafe extern "C" fn munlockall() -> i32 {
21237 syscall_ret(<Arch as Syscalls>::syscall0(sysno(152, 231))) as i32
21238}
21239
21240#[no_mangle]
21241pub unsafe extern "C" fn madvise(addr: *mut u8, len: usize, advice: i32) -> i32 {
21242 syscall_ret(<Arch as Syscalls>::syscall3(sysno(28, 233), addr as i64, len as i64, advice as i64)) as i32
21243}
21244
21245#[no_mangle]
21246pub unsafe extern "C" fn mincore(addr: *mut u8, len: usize, vec: *mut u8) -> i32 {
21247 syscall_ret(<Arch as Syscalls>::syscall3(sysno(27, 232), addr as i64, len as i64, vec as i64)) as i32
21248}
21249
21250#[no_mangle]
21257pub unsafe extern "C" fn drem(x: f64, y: f64) -> f64 {
21258 remainder(x, y)
21259}
21260
21261#[no_mangle]
21262pub unsafe extern "C" fn dremf(x: f32, y: f32) -> f32 {
21263 remainderf(x, y)
21264}
21265
21266#[no_mangle]
21267pub unsafe extern "C" fn pow10(x: f64) -> f64 {
21268 libm::pow(10.0, x)
21269}
21270
21271#[no_mangle]
21272pub unsafe extern "C" fn pow10f(x: f32) -> f32 {
21273 libm::powf(10.0, x)
21274}
21275
21276#[no_mangle]
21277pub unsafe extern "C" fn pow10l(x: f64) -> f64 {
21278 libm::pow(10.0, x)
21279}
21280
21281#[no_mangle]
21282pub unsafe extern "C" fn isless(x: f64, y: f64) -> i32 {
21283 if x.is_nan() || y.is_nan() { 0 } else { (x < y) as i32 }
21284}
21285
21286#[no_mangle]
21287pub unsafe extern "C" fn islessf(x: f32, y: f32) -> i32 {
21288 if x.is_nan() || y.is_nan() { 0 } else { (x < y) as i32 }
21289}
21290
21291#[no_mangle]
21292pub unsafe extern "C" fn lgamma_r(x: f64, signgamp: *mut i32) -> f64 {
21293 lgamma_r_impl(x, signgamp)
21294}
21295
21296#[no_mangle]
21297pub unsafe extern "C" fn lgammaf_r(x: f32, signgamp: *mut i32) -> f32 {
21298 if x.is_nan() {
21299 if !signgamp.is_null() { *signgamp = 1; }
21300 return x;
21301 }
21302 if x == 0.0 {
21303 if !signgamp.is_null() { *signgamp = if x.is_sign_negative() { -1 } else { 1 }; }
21304 feraiseexcept(FE_DIVBYZERO);
21305 return f32::INFINITY;
21306 }
21307 let (r, sign) = libm::lgammaf_r(x);
21308 if !signgamp.is_null() { *signgamp = sign; }
21309 r
21310}
21311
21312#[no_mangle]
21313pub unsafe extern "C" fn lgammal_r(x: f64, signgamp: *mut i32) -> f64 {
21314 lgamma_r(x, signgamp)
21315}
21316
21317#[no_mangle]
21322pub unsafe extern "C" fn islessequal(x: f64, y: f64) -> i32 {
21323 if x.is_nan() || y.is_nan() { 0 } else { (x <= y) as i32 }
21324}
21325
21326#[no_mangle]
21327pub unsafe extern "C" fn islessequalf(x: f32, y: f32) -> i32 {
21328 if x.is_nan() || y.is_nan() { 0 } else { (x <= y) as i32 }
21329}
21330
21331#[no_mangle]
21332pub unsafe extern "C" fn islessgreater(x: f64, y: f64) -> i32 {
21333 if x.is_nan() || y.is_nan() { 0 } else { (x < y || x > y) as i32 }
21334}
21335
21336#[no_mangle]
21337pub unsafe extern "C" fn islessgreaterf(x: f32, y: f32) -> i32 {
21338 if x.is_nan() || y.is_nan() { 0 } else { (x < y || x > y) as i32 }
21339}
21340
21341#[no_mangle]
21342pub unsafe extern "C" fn isgreater(x: f64, y: f64) -> i32 {
21343 if x.is_nan() || y.is_nan() { 0 } else { (x > y) as i32 }
21344}
21345
21346#[no_mangle]
21347pub unsafe extern "C" fn isgreaterf(x: f32, y: f32) -> i32 {
21348 if x.is_nan() || y.is_nan() { 0 } else { (x > y) as i32 }
21349}
21350
21351#[no_mangle]
21352pub unsafe extern "C" fn isgreaterequal(x: f64, y: f64) -> i32 {
21353 if x.is_nan() || y.is_nan() { 0 } else { (x >= y) as i32 }
21354}
21355
21356#[no_mangle]
21357pub unsafe extern "C" fn isgreaterequalf(x: f32, y: f32) -> i32 {
21358 if x.is_nan() || y.is_nan() { 0 } else { (x >= y) as i32 }
21359}
21360
21361#[no_mangle]
21366pub unsafe extern "C" fn stpcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char {
21367 let mut d = dest;
21368 let mut s = src;
21369 while *s != 0 {
21370 *d = *s;
21371 d = d.add(1);
21372 s = s.add(1);
21373 }
21374 *d = 0;
21375 d
21376}
21377
21378#[no_mangle]
21379pub unsafe extern "C" fn stpncpy(dest: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
21380 let mut i = 0;
21381 while i < n && *src.add(i) != 0 {
21382 *dest.add(i) = *src.add(i);
21383 i += 1;
21384 }
21385 let end = dest.add(i);
21386 while i < n {
21387 *dest.add(i) = 0;
21388 i += 1;
21389 }
21390 end
21391}
21392
21393#[no_mangle]
21394pub unsafe extern "C" fn strchrnul(s: *const c_char, c: c_int) -> *mut c_char {
21395 let mut p = s;
21396 while *p != 0 && *p as c_int != c {
21397 p = p.add(1);
21398 }
21399 p as *mut c_char
21400}
21401
21402#[no_mangle]
21403pub unsafe extern "C" fn fstatat(dirfd: c_int, path: *const c_char, buf: *mut Stat, flags: c_int) -> c_int {
21404 let r = sys_newfstatat(dirfd, path, buf as *mut u8, flags);
21405 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21406}
21407
21408#[no_mangle]
21409pub unsafe extern "C" fn execvpe(
21410 file: *const c_char,
21411 argv: *const *const c_char,
21412 envp: *const *const c_char,
21413) -> c_int {
21414 ERRNO!() = ENOENT_VAL;
21415 if file.is_null() || *file == 0 {
21416 return -1;
21417 }
21418 let mut p = file;
21419 while *p != 0 {
21420 if *p == b'/' as c_char {
21421 return execve(file, argv, envp);
21422 }
21423 p = p.add(1);
21424 }
21425 let file_len = crate::strlen(file);
21426 let path = crate::getenv(b"PATH\0".as_ptr() as *const c_char);
21427 let default_path = b"/usr/local/bin:/bin:/usr/bin\0";
21428 let path = if path.is_null() { default_path.as_ptr() as *const c_char } else { path };
21429
21430 let mut seen_eacces = false;
21431 let mut buf = [0 as c_char; 4096];
21432 let mut dir = path;
21433 loop {
21434 let mut end = dir;
21435 while *end != 0 && *end != b':' as c_char { end = end.add(1); }
21436 let dlen = end.offset_from(dir) as usize;
21437 let need_slash = dlen > 0;
21439 let total = dlen + need_slash as usize + file_len;
21440 if total < buf.len() {
21441 let mut i = 0;
21442 while i < dlen { buf[i] = *dir.add(i); i += 1; }
21443 if need_slash { buf[i] = b'/' as c_char; i += 1; }
21444 let mut j = 0;
21445 while j < file_len { buf[i + j] = *file.add(j); j += 1; }
21446 buf[i + j] = 0;
21447 execve(buf.as_ptr(), argv, envp);
21448 match ERRNO!() {
21449 13 => seen_eacces = true, 2 | 20 => {} _ => return -1,
21452 }
21453 }
21454 if *end == 0 { break; }
21455 dir = end.add(1);
21456 }
21457 ERRNO!() = if seen_eacces { 13 } else { 2 };
21458 -1
21459}
21460
21461#[no_mangle]
21464pub unsafe extern "C" fn strcoll_l(s1: *const c_char, s2: *const c_char, _loc: locale_t) -> c_int {
21465 strcoll(s1, s2)
21466}
21467
21468#[no_mangle]
21469pub unsafe extern "C" fn strxfrm_l(dest: *mut c_char, src: *const c_char, n: usize, _loc: locale_t) -> usize {
21470 strxfrm(dest, src, n)
21471}
21472
21473#[no_mangle]
21474pub unsafe extern "C" fn strerror_l(errnum: c_int, _loc: locale_t) -> *mut c_char {
21475 strerror(errnum)
21476}
21477
21478#[no_mangle]
21479pub unsafe extern "C" fn strcasecmp_l(s1: *const c_char, s2: *const c_char, _loc: locale_t) -> c_int {
21480 strcasecmp(s1, s2)
21481}
21482
21483#[no_mangle]
21484pub unsafe extern "C" fn strncasecmp_l(s1: *const c_char, s2: *const c_char, n: usize, _loc: locale_t) -> c_int {
21485 strncasecmp(s1, s2, n)
21486}
21487
21488#[no_mangle]
21489pub unsafe extern "C" fn strftime_l(s: *mut c_char, max: usize, fmt: *const c_char, tm: *const tm, _loc: locale_t) -> usize {
21490 strftime(s, max, fmt, tm)
21491}
21492
21493#[no_mangle]
21494pub unsafe extern "C" fn nl_langinfo_l(item: c_int, _loc: locale_t) -> *mut c_char {
21495 nl_langinfo(item)
21496}
21497
21498#[no_mangle]
21499pub unsafe extern "C" fn wcscoll_l(s1: *const u32, s2: *const u32, _loc: locale_t) -> c_int {
21500 wcscoll(s1, s2)
21501}
21502
21503#[no_mangle]
21504pub unsafe extern "C" fn wcsxfrm_l(dst: *mut wchar_t, src: *const wchar_t, n: usize, _loc: locale_t) -> usize {
21505 wcsxfrm(dst, src, n)
21506}
21507
21508#[no_mangle]
21509pub unsafe extern "C" fn wcsftime_l(s: *mut u32, max: usize, fmt: *const u32, tm: *const c_void, _loc: locale_t) -> usize {
21510 wcsftime(s, max, fmt, tm)
21511}
21512
21513#[no_mangle]
21514pub unsafe extern "C" fn wctype_l(name: *const c_char, _loc: locale_t) -> wctype_t {
21515 wctype(name)
21516}
21517
21518#[no_mangle]
21519pub unsafe extern "C" fn wctrans_l(name: *const c_char, _loc: locale_t) -> wctrans_t {
21520 wctrans(name)
21521}
21522
21523#[no_mangle]
21524pub unsafe extern "C" fn towlower_l(c: wint_t, _loc: locale_t) -> wint_t {
21525 towlower(c)
21526}
21527
21528#[no_mangle]
21529pub unsafe extern "C" fn towupper_l(c: wint_t, _loc: locale_t) -> wint_t {
21530 towupper(c)
21531}
21532
21533#[no_mangle]
21534pub unsafe extern "C" fn towctrans_l(c: wint_t, desc: wctrans_t, _loc: locale_t) -> wint_t {
21535 towctrans(c, desc)
21536}
21537
21538#[no_mangle] pub unsafe extern "C" fn iswalnum_l(c: wint_t, _l: locale_t) -> c_int { iswalnum(c) }
21539#[no_mangle] pub unsafe extern "C" fn iswalpha_l(c: wint_t, _l: locale_t) -> c_int { iswalpha(c) }
21540#[no_mangle] pub unsafe extern "C" fn iswblank_l(c: wint_t, _l: locale_t) -> c_int { iswblank(c) }
21541#[no_mangle] pub unsafe extern "C" fn iswcntrl_l(c: wint_t, _l: locale_t) -> c_int { iswcntrl(c) }
21542#[no_mangle] pub unsafe extern "C" fn iswdigit_l(c: wint_t, _l: locale_t) -> c_int { iswdigit(c) }
21543#[no_mangle] pub unsafe extern "C" fn iswgraph_l(c: wint_t, _l: locale_t) -> c_int { iswgraph(c) }
21544#[no_mangle] pub unsafe extern "C" fn iswlower_l(c: wint_t, _l: locale_t) -> c_int { iswlower(c) }
21545#[no_mangle] pub unsafe extern "C" fn iswprint_l(c: wint_t, _l: locale_t) -> c_int { iswprint(c) }
21546#[no_mangle] pub unsafe extern "C" fn iswpunct_l(c: wint_t, _l: locale_t) -> c_int { iswpunct(c) }
21547#[no_mangle] pub unsafe extern "C" fn iswspace_l(c: wint_t, _l: locale_t) -> c_int { iswspace(c) }
21548#[no_mangle] pub unsafe extern "C" fn iswupper_l(c: wint_t, _l: locale_t) -> c_int { iswupper(c) }
21549#[no_mangle] pub unsafe extern "C" fn iswxdigit_l(c: wint_t, _l: locale_t) -> c_int { iswxdigit(c) }
21550#[no_mangle] pub unsafe extern "C" fn iswctype_l(c: wint_t, desc: wctype_t, _l: locale_t) -> c_int { iswctype(c, desc) }
21551
21552#[no_mangle] pub unsafe extern "C" fn __isoc99_scanf(fmt: *const c_char, args: ...) -> c_int { vfscanf(stdin, fmt, args) }
21554#[no_mangle] pub unsafe extern "C" fn __isoc99_fscanf(f: *mut FILE, fmt: *const c_char, args: ...) -> c_int { vfscanf(f, fmt, args) }
21555#[no_mangle] pub unsafe extern "C" fn __isoc99_sscanf(s: *const c_char, fmt: *const c_char, args: ...) -> c_int { vsscanf(s, fmt, args) }
21556#[no_mangle] pub unsafe extern "C" fn __isoc99_vscanf(fmt: *const c_char, args: VaList) -> c_int { vfscanf(stdin, fmt, args) }
21557#[no_mangle] pub unsafe extern "C" fn __isoc99_vfscanf(f: *mut FILE, fmt: *const c_char, args: VaList) -> c_int { vfscanf(f, fmt, args) }
21558#[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) }
21559#[no_mangle] pub unsafe extern "C" fn __isoc99_wscanf(fmt: *const wchar_t, args: ...) -> c_int { vfwscanf(stdin, fmt, args) }
21560#[no_mangle] pub unsafe extern "C" fn __isoc99_fwscanf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int { vfwscanf(f, fmt, args) }
21561#[no_mangle] pub unsafe extern "C" fn __isoc99_swscanf(s: *const wchar_t, fmt: *const wchar_t, args: ...) -> c_int { vswscanf(s, fmt, args) }
21562#[no_mangle] pub unsafe extern "C" fn __isoc99_vwscanf(fmt: *const wchar_t, args: VaList) -> c_int { vfwscanf(stdin, fmt, args) }
21563#[no_mangle] pub unsafe extern "C" fn __isoc99_vfwscanf(f: *mut FILE, fmt: *const wchar_t, args: VaList) -> c_int { vfwscanf(f, fmt, args) }
21564#[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) }
21565
21566#[no_mangle] pub unsafe extern "C" fn clearerr_unlocked(f: *mut FILE) { clearerr(f) }
21569#[no_mangle] pub unsafe extern "C" fn feof_unlocked(f: *mut FILE) -> c_int { feof(f) }
21570#[no_mangle] pub unsafe extern "C" fn ferror_unlocked(f: *mut FILE) -> c_int { ferror(f) }
21571#[no_mangle] pub unsafe extern "C" fn fileno_unlocked(f: *mut FILE) -> c_int { fileno(f) }
21572#[no_mangle] pub unsafe extern "C" fn fflush_unlocked(f: *mut FILE) -> c_int { fflush(f) }
21573#[no_mangle] pub unsafe extern "C" fn fgetc_unlocked(f: *mut FILE) -> c_int { fgetc(f) }
21574#[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) }
21575#[no_mangle] pub unsafe extern "C" fn fputc_unlocked(c: c_int, f: *mut FILE) -> c_int { fputc(c, f) }
21576#[no_mangle] pub unsafe extern "C" fn fputs_unlocked(s: *const c_char, f: *mut FILE) -> c_int { fputs(s, f) }
21577#[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) }
21578#[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) }
21579#[no_mangle] pub unsafe extern "C" fn fgetwc_unlocked(f: *mut FILE) -> wint_t { fgetwc(f) }
21580#[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) }
21581#[no_mangle] pub unsafe extern "C" fn fputwc_unlocked(c: wchar_t, f: *mut FILE) -> wint_t { fputwc(c, f) }
21582#[no_mangle] pub unsafe extern "C" fn fputws_unlocked(s: *const wchar_t, f: *mut FILE) -> c_int { fputws(s, f) }
21583#[no_mangle] pub unsafe extern "C" fn getwc_unlocked(f: *mut c_void) -> wint_t { getwc(f) }
21584#[no_mangle] pub unsafe extern "C" fn putwc_unlocked(c: u32, f: *mut c_void) -> wint_t { putwc(c, f) }
21585#[no_mangle] pub unsafe extern "C" fn getwchar_unlocked() -> wint_t { getwchar() }
21586#[no_mangle] pub unsafe extern "C" fn putwchar_unlocked(c: wchar_t) -> wint_t { putwchar(c) }
21587#[no_mangle] pub unsafe extern "C" fn fpurge(f: *mut FILE) { clearerr(f) }
21588#[no_mangle] pub unsafe extern "C" fn _IO_getc(f: *mut FILE) -> c_int { getc(f) }
21589#[no_mangle] pub unsafe extern "C" fn _IO_putc(c: c_int, f: *mut FILE) -> c_int { putc(c, f) }
21590#[no_mangle] pub unsafe extern "C" fn _IO_getc_unlocked(f: *mut FILE) -> c_int { getc(f) }
21591#[no_mangle] pub unsafe extern "C" fn _IO_putc_unlocked(c: c_int, f: *mut FILE) -> c_int { putc(c, f) }
21592#[no_mangle] pub unsafe extern "C" fn _IO_feof_unlocked(f: *mut FILE) -> c_int { feof(f) }
21593#[no_mangle] pub unsafe extern "C" fn _IO_ferror_unlocked(f: *mut FILE) -> c_int { ferror(f) }
21594
21595#[no_mangle] pub unsafe extern "C" fn __getauxval(t: c_ulong) -> c_ulong { getauxval(t) }
21597#[no_mangle] pub unsafe extern "C" fn __longjmp(env: *const c_ulong, val: c_int) -> ! { longjmp(env, val) }
21598#[no_mangle] pub unsafe extern "C" fn bsd_signal(sig: c_int, handler: usize) -> usize { signal(sig, handler) }
21599#[no_mangle] pub unsafe extern "C" fn __sysv_signal(sig: c_int, handler: usize) -> usize { signal(sig, handler) }
21600#[no_mangle] pub unsafe extern "C" fn eaccess(path: *const c_char, mode: c_int) -> c_int { access(path, mode) }
21601#[no_mangle] pub unsafe extern "C" fn __xpg_basename(path: *mut c_char) -> *mut c_char { basename(path) }
21602#[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) }
21603#[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) }
21604
21605#[no_mangle]
21610pub unsafe extern "C" fn cfsetspeed(termios_p: *mut c_void, speed: u32) -> c_int {
21611 let r = cfsetispeed(termios_p, speed);
21612 if r != 0 { return r; }
21613 cfsetospeed(termios_p, speed)
21614}
21615
21616#[no_mangle]
21617pub unsafe extern "C" fn futimesat(dirfd: c_int, path: *const c_char, times: *const timeval) -> c_int {
21618 if times.is_null() {
21619 return utimensat(dirfd, path, core::ptr::null(), 0);
21620 }
21621 let tv = times as *const [timeval; 2];
21622 let mut ts: [timespec; 2] = [
21623 timespec { tv_sec: (*tv)[0].tv_sec, tv_nsec: (*tv)[0].tv_usec * 1000 },
21624 timespec { tv_sec: (*tv)[1].tv_sec, tv_nsec: (*tv)[1].tv_usec * 1000 },
21625 ];
21626 for t in &mut ts {
21627 if t.tv_nsec < 0 || t.tv_nsec >= 1_000_000_000 {
21628 ERRNO!() = EINVAL;
21629 return -1;
21630 }
21631 }
21632 utimensat(dirfd, path, ts.as_ptr(), 0)
21633}
21634
21635#[no_mangle]
21636pub unsafe extern "C" fn membarrier(cmd: c_int, flags: c_int, cpu_id: c_int) -> c_int {
21637 <Arch as Syscalls>::syscall3(SYS_MEMBARRIER, cmd as i64, flags as i64, cpu_id as i64) as c_int
21638}
21639
21640#[no_mangle]
21641pub unsafe extern "C" fn mremap(
21642 old_address: *mut c_void,
21643 old_size: usize,
21644 new_size: usize,
21645 flags: c_int,
21646 mut args: ...
21647) -> *mut c_void {
21648 let new_address = if flags & 2 != 0 { args.next_arg::<*mut c_void>() } else { core::ptr::null_mut() };
21649 let r = <Arch as Syscalls>::syscall5(
21650 SYS_MREMAP,
21651 old_address as i64,
21652 old_size as i64,
21653 new_size as i64,
21654 flags as i64,
21655 new_address as i64,
21656 );
21657 if r < 0 {
21658 ERRNO!() = (-r) as c_int;
21659 return (-1isize) as *mut c_void;
21660 }
21661 r as *mut c_void
21662}
21663
21664#[no_mangle]
21665pub unsafe extern "C" fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: usize) -> c_int {
21666 let name = ptsname(fd);
21667 if name.is_null() { return -1; }
21668 let n = crate::strlen(name);
21669 if n + 1 > buflen {
21670 ERRNO!() = ERANGE_VAL;
21671 return ERANGE_VAL;
21672 }
21673 core::ptr::copy_nonoverlapping(name, buf, n + 1);
21674 0
21675}
21676
21677#[no_mangle]
21678pub unsafe extern "C" fn posix_getdents(fd: c_int, buf: *mut c_void, len: usize, flags: c_int) -> isize {
21679 if flags != 0 {
21680 ERRNO!() = EINVAL;
21681 return -1;
21682 }
21683 let r = <Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, buf as i64, len as i64);
21684 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
21685}
21686
21687#[no_mangle]
21688pub unsafe extern "C" fn riscv_flush_icache(start: *mut c_void, end: *mut c_void, flags: c_ulong) -> c_int {
21689 #[cfg(target_arch = "riscv64")]
21690 {
21691 let r = <Arch as Syscalls>::syscall3(259, start as i64, end as i64, flags as i64);
21692 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21693 }
21694 #[cfg(not(target_arch = "riscv64"))]
21695 {
21696 let _ = (start, end, flags);
21697 0
21698 }
21699}
21700
21701#[no_mangle]
21702pub unsafe extern "C" fn __riscv_flush_icache(start: *mut c_void, end: *mut c_void, flags: c_ulong) -> c_int {
21703 riscv_flush_icache(start, end, flags)
21704}
21705
21706#[no_mangle]
21707pub unsafe extern "C" fn mkostemps(template: *mut c_char, suffixlen: c_int, flags: c_int) -> c_int {
21708 let fd = mkstemps(template, suffixlen);
21709 if fd >= 0 && flags & O_CLOEXEC != 0 {
21710 sys_fcntl(fd, F_SETFD, FD_CLOEXEC as i64);
21711 }
21712 fd
21713}
21714
21715#[no_mangle]
21716pub unsafe extern "C" fn statfs(path: *const c_char, buf: *mut c_void) -> c_int {
21717 let r = <Arch as Syscalls>::syscall2(SYS_STATFS, path as i64, buf as i64);
21718 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21719}
21720
21721#[no_mangle]
21722pub unsafe extern "C" fn fstatfs(fd: c_int, buf: *mut c_void) -> c_int {
21723 let r = <Arch as Syscalls>::syscall2(SYS_FSTATFS, fd as i64, buf as i64);
21724 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21725}
21726
21727#[no_mangle]
21728pub unsafe extern "C" fn sysinfo(info: *mut c_void) -> c_int {
21729 let r = <Arch as Syscalls>::syscall1(SYS_SYSINFO, info as i64);
21730 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21731}
21732
21733#[no_mangle]
21734pub unsafe extern "C" fn pthread_tryjoin_np(thread: PthreadT, retval: *mut *mut c_void) -> c_int {
21735 let slot = thread as *mut Thread;
21736 if slot.is_null() { return EINVAL; }
21737 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
21738 let tid = core::ptr::read_volatile(&raw const (*slot).tid);
21739 if tid > 0 { return EBUSY; }
21740 if tid < 0 { return EINVAL; }
21741 pthread_join(thread, retval)
21742}
21743
21744#[no_mangle]
21745pub unsafe extern "C" fn pthread_timedjoin_np(thread: PthreadT, retval: *mut *mut c_void, abstime: *const timespec) -> c_int {
21746 let slot = thread as *mut Thread;
21747 if slot.is_null() { return EINVAL; }
21748 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
21749 loop {
21750 let r = pthread_tryjoin_np(thread, retval);
21751 if r != EBUSY { return r; }
21752 let tid = core::ptr::read_volatile(&raw const (*slot).tid);
21753 if tid <= 0 { continue; }
21754 let e = futex_timedwait(&raw mut (*slot).tid, tid, abstime);
21755 if e == ETIMEDOUT { return ETIMEDOUT; }
21756 }
21757}
21758
21759
21760#[repr(C)]
21763pub struct UtmpExit {
21764 pub e_termination: i16,
21765 pub e_exit: i16,
21766}
21767
21768#[repr(C)]
21769pub struct Utmpx {
21770 pub ut_type: i16,
21771 pub __ut_pad1: i16,
21772 pub ut_pid: i32,
21773 pub ut_line: [c_char; 32],
21774 pub ut_id: [c_char; 4],
21775 pub ut_user: [c_char; 32],
21776 pub ut_host: [c_char; 256],
21777 pub ut_exit: UtmpExit,
21778 pub ut_session: i32,
21779 pub __ut_pad2: i32,
21780 pub ut_tv: timeval,
21781 pub ut_addr_v6: [u32; 4],
21782 pub __unused: [u8; 20],
21783}
21784
21785const UTMP_SIZE: usize = 400;
21786const _: [(); UTMP_SIZE] = [(); core::mem::size_of::<Utmpx>()];
21787
21788static mut UTMP_FD: c_int = -1;
21789static mut UTMP_PATH: [u8; 256] = [0; 256];
21790static mut UTMP_PATH_SET: bool = false;
21791#[repr(align(8))]
21792struct UtmpBuf([u8; UTMP_SIZE]);
21793static mut UTMP_BUF: UtmpBuf = UtmpBuf([0; UTMP_SIZE]);
21794
21795unsafe fn utmp_path_ptr() -> *const c_char {
21796 if !UTMP_PATH_SET {
21797 let default = b"/var/run/utmp\0";
21798 let mut i = 0;
21799 while i < default.len() && i < UTMP_PATH.len() {
21800 UTMP_PATH[i] = default[i];
21801 i += 1;
21802 }
21803 UTMP_PATH_SET = true;
21804 }
21805 UTMP_PATH.as_ptr() as *const c_char
21806}
21807
21808unsafe fn utmp_open_read() -> c_int {
21809 if UTMP_FD >= 0 {
21810 crate::close(UTMP_FD);
21811 }
21812 UTMP_FD = crate::open(utmp_path_ptr(), 0, 0);
21813 UTMP_FD
21814}
21815
21816unsafe fn utmp_open_append() -> c_int {
21817 crate::open(utmp_path_ptr(), 1 | 64 | 1024, 0o644)
21818}
21819
21820#[no_mangle]
21821pub unsafe extern "C" fn setutent() {
21822 let _ = utmp_open_read();
21823}
21824
21825#[no_mangle]
21826pub unsafe extern "C" fn endutent() {
21827 if UTMP_FD >= 0 {
21828 crate::close(UTMP_FD);
21829 UTMP_FD = -1;
21830 }
21831}
21832
21833#[no_mangle]
21834pub unsafe extern "C" fn getutent() -> *mut c_void {
21835 if UTMP_FD < 0 && utmp_open_read() < 0 {
21836 return core::ptr::null_mut();
21837 }
21838 let n = crate::read(UTMP_FD, UTMP_BUF.0.as_mut_ptr() as *mut c_void, UTMP_SIZE);
21839 if n == UTMP_SIZE as isize {
21840 UTMP_BUF.0.as_mut_ptr() as *mut c_void
21841 } else {
21842 core::ptr::null_mut()
21843 }
21844}
21845
21846unsafe fn utmp_id_eq(a: &[c_char; 4], b: &[c_char; 4]) -> bool {
21847 a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]
21848}
21849
21850unsafe fn utmp_line_eq(a: &[c_char; 32], b: &[c_char; 32]) -> bool {
21851 let mut i = 0;
21852 while i < 32 {
21853 if a[i] != b[i] { return false; }
21854 if a[i] == 0 { return true; }
21855 i += 1;
21856 }
21857 true
21858}
21859
21860#[no_mangle]
21861pub unsafe extern "C" fn getutid(ut: *const c_void) -> *mut c_void {
21862 if ut.is_null() { return core::ptr::null_mut(); }
21863 let want = &*(ut as *const Utmpx);
21864 loop {
21865 let p = getutent();
21866 if p.is_null() { return p; }
21867 let cur = &*(p as *const Utmpx);
21868 let matched = match want.ut_type {
21869 1 | 2 | 3 | 4 => cur.ut_type == want.ut_type,
21870 _ => utmp_id_eq(&cur.ut_id, &want.ut_id)
21871 && (want.ut_type == 0 || cur.ut_type == want.ut_type),
21872 };
21873 if matched { return p; }
21874 }
21875}
21876
21877#[no_mangle]
21878pub unsafe extern "C" fn getutline(ut: *const c_void) -> *mut c_void {
21879 if ut.is_null() { return core::ptr::null_mut(); }
21880 let want = &*(ut as *const Utmpx);
21881 loop {
21882 let p = getutent();
21883 if p.is_null() { return p; }
21884 if utmp_line_eq(&(*(p as *const Utmpx)).ut_line, &want.ut_line) {
21885 return p;
21886 }
21887 }
21888}
21889
21890#[no_mangle]
21891pub unsafe extern "C" fn pututline(ut: *const c_void) -> *mut c_void {
21892 if ut.is_null() { return core::ptr::null_mut(); }
21893 let fd = utmp_open_append();
21894 if fd < 0 { return core::ptr::null_mut(); }
21895 let n = crate::write(fd, ut, UTMP_SIZE);
21896 crate::close(fd);
21897 if n == UTMP_SIZE as isize { ut as *mut c_void } else { core::ptr::null_mut() }
21898}
21899
21900#[no_mangle]
21901pub unsafe extern "C" fn updwtmp(file: *const c_char, ut: *const c_void) {
21902 if file.is_null() || ut.is_null() { return; }
21903 let fd = crate::open(file, 1 | 64 | 1024, 0o644);
21904 if fd >= 0 {
21905 let _ = crate::write(fd, ut, UTMP_SIZE);
21906 crate::close(fd);
21907 }
21908}
21909
21910unsafe fn utmp_set_name(file: *const c_char) -> c_int {
21911 if file.is_null() { return -1; }
21912 let len = crate::strlen(file);
21913 if len + 1 > UTMP_PATH.len() { return -1; }
21914 if UTMP_FD >= 0 {
21915 crate::close(UTMP_FD);
21916 UTMP_FD = -1;
21917 }
21918 core::ptr::copy_nonoverlapping(file, UTMP_PATH.as_mut_ptr() as *mut c_char, len + 1);
21919 UTMP_PATH_SET = true;
21920 0
21921}
21922
21923#[no_mangle]
21924pub unsafe extern "C" fn utmpname(file: *const c_char) -> c_int { utmp_set_name(file) }
21925
21926#[no_mangle]
21927pub unsafe extern "C" fn utmpxname(file: *const c_char) -> c_int { utmp_set_name(file) }
21928
21929
21930#[no_mangle] pub static mut ___environ: *mut *mut c_char = core::ptr::null_mut();
21932#[no_mangle] pub static mut _environ: *mut *mut c_char = core::ptr::null_mut();
21933#[no_mangle] pub unsafe extern "C" fn __freelocale(loc: locale_t) { freelocale(loc) }
21934#[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) }
21935#[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) }
21936#[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) }
21937#[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) }
21938
21939#[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) }
21940#[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) }
21941#[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) }
21942#[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) }
21943#[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) }
21944#[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) }
21945
21946const MAX_NS: usize = 3;
21951const MAX_SEARCH: usize = 6;
21952const HOST_NOT_FOUND: c_int = 1;
21953const TRY_AGAIN: c_int = 2;
21954const NO_RECOVERY: c_int = 3;
21955const NO_DATA: c_int = 4;
21956
21957static mut NS_COUNT: usize = 0;
21958static mut NS_ADDRS: [u32; MAX_NS] = [0; MAX_NS];
21959static mut SEARCH_COUNT: usize = 0;
21960static mut SEARCH_DOMAINS: [[u8; 256]; MAX_SEARCH] = [[0; 256]; MAX_SEARCH];
21961static mut RESOLV_INITIALIZED: bool = false;
21962
21963#[repr(C)]
21964struct SockAddrIn {
21965 sin_family: u16,
21966 sin_port: u16,
21967 sin_addr: u32,
21968 sin_zero: [u8; 8],
21969}
21970
21971#[repr(C)]
21972struct PollFd {
21973 fd: c_int,
21974 events: i16,
21975 revents: i16,
21976}
21977
21978unsafe fn resolv_skip_ws(line: &[u8], mut i: usize) -> usize {
21979 while i < line.len() && (line[i] == b' ' || line[i] == b'\t') { i += 1; }
21980 i
21981}
21982
21983unsafe fn resolv_token<'a>(line: &'a [u8], mut i: usize) -> (&'a [u8], usize) {
21984 let start = i;
21985 while i < line.len() && line[i] != b' ' && line[i] != b'\t' && line[i] != b'#' { i += 1; }
21986 (&line[start..i], i)
21987}
21988
21989unsafe fn resolv_parse_config() -> c_int {
21990 RESOLV_INITIALIZED = true;
21991 NS_COUNT = 0;
21992 SEARCH_COUNT = 0;
21993 let path = b"/etc/resolv.conf\0";
21994 let fd = crate::open(path.as_ptr() as *const c_char, 0, 0);
21995 if fd < 0 { return -1; }
21996 let mut buf = [0u8; 4096];
21997 let n = crate::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len());
21998 crate::close(fd);
21999 if n <= 0 { return -1; }
22000 let len = n as usize;
22001 let mut i = 0;
22002 while i < len {
22003 let start = i;
22004 while i < len && buf[i] != b'\n' { i += 1; }
22005 let line = &buf[start..i];
22006 i += 1;
22007 let mut j = resolv_skip_ws(line, 0);
22008 if j >= line.len() || line[j] == b'#' { continue; }
22009 let (key, next) = resolv_token(line, j);
22010 j = next;
22011 if key == b"nameserver" {
22012 j = resolv_skip_ws(line, j);
22013 let (tok, _) = resolv_token(line, j);
22014 if !tok.is_empty() && NS_COUNT < MAX_NS {
22015 let mut name = [0u8; 64];
22016 let l = core::cmp::min(tok.len(), 63);
22017 name[..l].copy_from_slice(&tok[..l]);
22018 let addr = crate::inet_addr(name.as_ptr() as *const c_char);
22019 if addr != u32::MAX {
22020 NS_ADDRS[NS_COUNT] = addr;
22021 NS_COUNT += 1;
22022 }
22023 }
22024 } else if key == b"search" || key == b"domain" {
22025 loop {
22026 j = resolv_skip_ws(line, j);
22027 if j >= line.len() || line[j] == b'#' { break; }
22028 let (tok, next) = resolv_token(line, j);
22029 j = next;
22030 if tok.is_empty() { break; }
22031 if SEARCH_COUNT < MAX_SEARCH {
22032 let l = core::cmp::min(tok.len(), 255);
22033 SEARCH_DOMAINS[SEARCH_COUNT][..l].copy_from_slice(&tok[..l]);
22034 SEARCH_DOMAINS[SEARCH_COUNT][l] = 0;
22035 SEARCH_COUNT += 1;
22036 }
22037 if key == b"domain" { break; }
22038 }
22039 }
22040 }
22041 0
22042}
22043
22044#[no_mangle]
22045pub unsafe extern "C" fn res_init() -> c_int {
22046 let _ = resolv_parse_config();
22047 0
22048}
22049
22050#[no_mangle]
22051pub unsafe extern "C" fn res_mkquery(
22052 op: c_int,
22053 dname: *const c_char,
22054 class: c_int,
22055 type_: c_int,
22056 _data: *const u8,
22057 _datalen: c_int,
22058 _newrr: *const u8,
22059 buf: *mut u8,
22060 buflen: c_int,
22061) -> c_int {
22062 if dname.is_null() || buf.is_null() { return -1; }
22063 let mut l = crate::strnlen(dname as *const u8, 255);
22064 if l > 0 && *dname.add(l - 1) == b'.' as c_char { l -= 1; }
22065 if l > 0 && *dname.add(l - 1) == b'.' as c_char { return -1; }
22066 let n = 17 + l + if l != 0 { 1 } else { 0 };
22067 if l > 253 || buflen < n as c_int || op < 0 || op > 15 || class < 0 || class > 255 || type_ < 0 || type_ > 255 {
22068 return -1;
22069 }
22070 let mut q = [0u8; 280];
22071 crate::memset(q.as_mut_ptr() as *mut c_void, 0, n);
22072 q[2] = (op * 8 + 1) as u8;
22073 q[3] = 32;
22074 q[5] = 1;
22075 core::ptr::copy_nonoverlapping(dname as *const u8, q.as_mut_ptr().add(13), l);
22076 let mut i = 13;
22077 while q[i] != 0 {
22078 let mut j = i;
22079 while q[j] != 0 && q[j] != b'.' { j += 1; }
22080 if j - i - 1 > 62 { return -1; }
22081 q[i - 1] = (j - i) as u8;
22082 i = j + 1;
22083 }
22084 q[i + 1] = type_ as u8;
22085 q[i + 3] = class as u8;
22086 let mut ts = timespec { tv_sec: 0, tv_nsec: 0 };
22087 let _ = clock_gettime(CLOCK_REALTIME, &mut ts);
22088 let id = (((ts.tv_nsec as u64) + (ts.tv_nsec as u64) / 65536) & 0xffff) as u16;
22089 q[0] = (id >> 8) as u8;
22090 q[1] = id as u8;
22091 core::ptr::copy_nonoverlapping(q.as_ptr(), buf, n);
22092 n as c_int
22093}
22094
22095unsafe fn res_send_inner(msg: *const u8, msglen: c_int, answer: *mut u8, anslen: c_int) -> c_int {
22096 if msg.is_null() || answer.is_null() || msglen < 12 || anslen < 12 { return -1; }
22097 if !RESOLV_INITIALIZED { let _ = resolv_parse_config(); }
22098 if NS_COUNT == 0 {
22099 h_errno = TRY_AGAIN;
22100 return -1;
22101 }
22102 for n in 0..NS_COUNT {
22103 let fd = crate::socket(AF_INET, SOCK_DGRAM, 0);
22104 if fd < 0 { continue; }
22105 let sa = SockAddrIn {
22106 sin_family: AF_INET as u16,
22107 sin_port: 53u16.to_be(),
22108 sin_addr: NS_ADDRS[n],
22109 sin_zero: [0; 8],
22110 };
22111 let sent = crate::sendto(fd, msg as *const c_void, msglen as usize, 0, &sa as *const SockAddrIn as *const crate::sockaddr, 16);
22112 if sent != msglen as isize {
22113 crate::close(fd);
22114 continue;
22115 }
22116 let mut pfd = PollFd { fd, events: 1, revents: 0 };
22117 let pr = crate::poll(&mut pfd as *mut PollFd as *mut c_void, 1, 5000);
22118 if pr <= 0 {
22119 crate::close(fd);
22120 continue;
22121 }
22122 let r = crate::recvfrom(fd, answer as *mut c_void, anslen as usize, 0, core::ptr::null_mut(), core::ptr::null_mut());
22123 crate::close(fd);
22124 if r >= 12 {
22125 let id_ok = *answer == *msg && *answer.add(1) == *msg.add(1);
22126 let qr = (*answer.add(2) & 0x80) != 0;
22127 if id_ok && qr {
22128 return r as c_int;
22129 }
22130 }
22131 }
22132 h_errno = TRY_AGAIN;
22133 -1
22134}
22135
22136#[no_mangle]
22137pub unsafe extern "C" fn res_send(msg: *const u8, msglen: c_int, answer: *mut u8, anslen: c_int) -> c_int {
22138 if anslen < 512 {
22139 let mut buf = [0u8; 512];
22140 let r = res_send_inner(msg, msglen, buf.as_mut_ptr(), 512);
22141 if r >= 0 {
22142 let copy = core::cmp::min(r, anslen) as usize;
22143 if copy > 0 { core::ptr::copy_nonoverlapping(buf.as_ptr(), answer, copy); }
22144 }
22145 return r;
22146 }
22147 res_send_inner(msg, msglen, answer, anslen)
22148}
22149
22150#[no_mangle]
22151pub unsafe extern "C" fn res_query(
22152 dname: *const c_char,
22153 class: c_int,
22154 type_: c_int,
22155 answer: *mut u8,
22156 anslen: c_int,
22157) -> c_int {
22158 let mut q = [0u8; 280];
22159 let ql = res_mkquery(0, dname, class, type_, core::ptr::null(), 0, core::ptr::null(), q.as_mut_ptr(), q.len() as c_int);
22160 if ql < 0 { return ql; }
22161 let r = res_send(q.as_ptr(), ql, answer, anslen);
22162 if r < 12 {
22163 h_errno = TRY_AGAIN;
22164 return -1;
22165 }
22166 let rcode = answer.add(3).read() & 0x0f;
22167 if rcode == 3 {
22168 h_errno = HOST_NOT_FOUND;
22169 return -1;
22170 }
22171 if rcode == 0 && *answer.add(6) == 0 && *answer.add(7) == 0 {
22172 h_errno = NO_DATA;
22173 return -1;
22174 }
22175 if rcode != 0 {
22176 h_errno = NO_RECOVERY;
22177 return -1;
22178 }
22179 r
22180}
22181
22182#[no_mangle]
22183pub unsafe extern "C" fn res_querydomain(
22184 name: *const c_char,
22185 domain: *const c_char,
22186 class: c_int,
22187 type_: c_int,
22188 answer: *mut u8,
22189 anslen: c_int,
22190) -> c_int {
22191 if domain.is_null() || *domain == 0 { return res_query(name, class, type_, answer, anslen); }
22192 let mut buf = [0u8; 512];
22193 let nl = crate::strlen(name);
22194 let dl = crate::strlen(domain);
22195 if nl + 1 + dl >= buf.len() { return -1; }
22196 core::ptr::copy_nonoverlapping(name, buf.as_mut_ptr() as *mut c_char, nl);
22197 buf[nl] = b'.';
22198 core::ptr::copy_nonoverlapping(domain, buf.as_mut_ptr().add(nl + 1) as *mut c_char, dl);
22199 buf[nl + 1 + dl] = 0;
22200 res_query(buf.as_ptr() as *const c_char, class, type_, answer, anslen)
22201}
22202
22203#[no_mangle]
22204pub unsafe extern "C" fn res_search(
22205 name: *const c_char,
22206 class: c_int,
22207 type_: c_int,
22208 answer: *mut u8,
22209 anslen: c_int,
22210) -> c_int {
22211 if name.is_null() { return -1; }
22212 if !RESOLV_INITIALIZED { let _ = resolv_parse_config(); }
22213 let len = crate::strlen(name);
22214 let mut dots = 0;
22215 for i in 0..len {
22216 if *name.add(i) == b'.' as c_char { dots += 1; }
22217 }
22218 let trailing_dot = len > 0 && *name.add(len - 1) == b'.' as c_char;
22219 if trailing_dot || dots >= 1 {
22220 let r = res_query(name, class, type_, answer, anslen);
22221 if r >= 0 { return r; }
22222 if trailing_dot { return -1; }
22223 }
22224 for i in 0..SEARCH_COUNT {
22225 let dom = SEARCH_DOMAINS[i].as_ptr() as *const c_char;
22226 let r = res_querydomain(name, dom, class, type_, answer, anslen);
22227 if r >= 0 { return r; }
22228 if h_errno != HOST_NOT_FOUND && h_errno != NO_DATA { return -1; }
22229 }
22230 if dots == 0 {
22231 return res_query(name, class, type_, answer, anslen);
22232 }
22233 -1
22234}
22235
22236#[repr(C)]
22241pub struct HostEnt {
22242 pub h_name: *mut c_char,
22243 pub h_aliases: *mut *mut c_char,
22244 pub h_addrtype: c_int,
22245 pub h_length: c_int,
22246 pub h_addr_list: *mut *mut c_char,
22247}
22248
22249#[repr(C)]
22250pub struct AddrInfo {
22251 pub ai_flags: c_int,
22252 pub ai_family: c_int,
22253 pub ai_socktype: c_int,
22254 pub ai_protocol: c_int,
22255 pub ai_addrlen: u32,
22256 pub ai_addr: *mut c_void,
22257 pub ai_canonname: *mut c_char,
22258 pub ai_next: *mut AddrInfo,
22259}
22260
22261static mut HOST_ENT: HostEnt = HostEnt {
22262 h_name: core::ptr::null_mut(),
22263 h_aliases: core::ptr::null_mut(),
22264 h_addrtype: 0,
22265 h_length: 0,
22266 h_addr_list: core::ptr::null_mut(),
22267};
22268static mut HOST_NAME: [c_char; 256] = [0; 256];
22269static mut HOST_ALIASES: [*mut c_char; 1] = [core::ptr::null_mut()];
22270static mut HOST_ADDR: [u8; 16] = [0; 16];
22271static mut HOST_ADDR_PTRS: [*mut c_char; 2] = [core::ptr::null_mut(); 2];
22272
22273unsafe fn dns_skip_name(p: *const u8, end: *const u8) -> *const u8 {
22274 let mut q = p;
22275 while q < end {
22276 let c = *q;
22277 if c == 0 { return q.add(1); }
22278 if c & 0xc0 == 0xc0 { return q.add(2); }
22279 q = q.add(1 + c as usize);
22280 }
22281 end
22282}
22283
22284unsafe fn dns_read_u16(p: *const u8) -> u16 {
22285 ((*p as u16) << 8) | *p.add(1) as u16
22286}
22287
22288unsafe fn dns_expand_name(p: *const u8, msg: *const u8, out: *mut c_char, outlen: usize) -> bool {
22289 let mut q = p;
22290 let mut o = 0usize;
22291 let mut jumps = 0;
22292 loop {
22293 let c = *q;
22294 if c == 0 {
22295 if o < outlen { *out.add(o) = 0; }
22296 return true;
22297 }
22298 if c & 0xc0 == 0xc0 {
22299 let off = (((c & 0x3f) as usize) << 8) | *q.add(1) as usize;
22300 q = msg.add(off);
22301 jumps += 1;
22302 if jumps > 16 { return false; }
22303 continue;
22304 }
22305 let l = c as usize;
22306 if l > 63 { return false; }
22307 if o + l + 1 >= outlen { return false; }
22308 core::ptr::copy_nonoverlapping(q.add(1), out.add(o) as *mut u8, l);
22309 o += l;
22310 *out.add(o) = b'.' as c_char;
22311 o += 1;
22312 q = q.add(1 + l);
22313 }
22314}
22315
22316unsafe fn host_from_answer(answer: *const u8, len: c_int, af: c_int) -> *mut HostEnt {
22317 if len < 12 { return core::ptr::null_mut(); }
22318 let end = answer.add(len as usize);
22319 let qd = dns_read_u16(answer.add(4)) as usize;
22320 let an = dns_read_u16(answer.add(6)) as usize;
22321 let mut p = answer.add(12);
22322 for _ in 0..qd {
22323 p = dns_skip_name(p, end);
22324 p = p.add(4);
22325 }
22326 let want_type: u16 = if af == AF_INET6 { 28 } else { 1 };
22327 let want_len = if af == AF_INET6 { 16 } else { 4 };
22328 for _ in 0..an {
22329 p = dns_skip_name(p, end);
22330 if p.add(10) > end { break; }
22331 let typ = dns_read_u16(p);
22332 let class = dns_read_u16(p.add(2));
22333 let rdlen = dns_read_u16(p.add(8)) as usize;
22334 let rdata = p.add(10);
22335 if rdata.add(rdlen) > end { break; }
22336 if typ == want_type && class == 1 && rdlen == want_len {
22337 core::ptr::copy_nonoverlapping(rdata, HOST_ADDR.as_mut_ptr(), want_len);
22338 HOST_ENT.h_addrtype = af;
22339 HOST_ENT.h_length = want_len as c_int;
22340 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
22341 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
22342 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
22343 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
22344 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
22345 h_errno = 0;
22346 return &raw mut HOST_ENT;
22347 }
22348 p = rdata.add(rdlen);
22349 }
22350 core::ptr::null_mut()
22351}
22352
22353#[no_mangle]
22354pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *mut HostEnt {
22355 gethostbyname2(name, AF_INET)
22356}
22357
22358#[no_mangle]
22359pub unsafe extern "C" fn gethostbyname2(name: *const c_char, af: c_int) -> *mut HostEnt {
22360 if name.is_null() { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
22361 let mut addr = [0u8; 16];
22362 let addrlen = if af == AF_INET6 { 16 } else { 4 };
22363 if inet_pton(af, name, addr.as_mut_ptr() as *mut c_void) == 1 {
22364 core::ptr::copy_nonoverlapping(addr.as_ptr(), HOST_ADDR.as_mut_ptr(), addrlen);
22365 let n = crate::strlen(name);
22366 let l = core::cmp::min(n, 255);
22367 core::ptr::copy_nonoverlapping(name, HOST_NAME.as_mut_ptr(), l);
22368 HOST_NAME[l] = 0;
22369 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
22370 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
22371 HOST_ENT.h_addrtype = af;
22372 HOST_ENT.h_length = addrlen as c_int;
22373 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
22374 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
22375 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
22376 h_errno = 0;
22377 return &raw mut HOST_ENT;
22378 }
22379 let mut answer = [0u8; 512];
22380 let qtype = if af == AF_INET6 { 28 } else { 1 };
22381 let r = res_query(name, 1, qtype, answer.as_mut_ptr(), answer.len() as c_int);
22382 if r < 0 {
22383 if h_errno == 0 { h_errno = TRY_AGAIN; }
22384 return core::ptr::null_mut();
22385 }
22386 let ent = host_from_answer(answer.as_ptr(), r, af);
22387 if !ent.is_null() {
22388 let n = crate::strlen(name);
22389 let l = core::cmp::min(n, 255);
22390 core::ptr::copy_nonoverlapping(name, HOST_NAME.as_mut_ptr(), l);
22391 HOST_NAME[l] = 0;
22392 } else {
22393 h_errno = HOST_NOT_FOUND;
22394 }
22395 ent
22396}
22397
22398#[no_mangle]
22399pub unsafe extern "C" fn gethostbyaddr(addr: *const c_void, len: u32, type_: c_int) -> *mut HostEnt {
22400 if addr.is_null() || type_ != AF_INET || len != 4 { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
22401 let a = addr as *const u8;
22402 let mut name = [0u8; 128];
22403 let mut pos = 0;
22404 for i in 0..4 {
22405 let v = *a.add(3 - i) as u32;
22406 if v >= 100 { name[pos] = b'0' + (v / 100) as u8; pos += 1; }
22407 if v >= 10 { name[pos] = b'0' + ((v / 10) % 10) as u8; pos += 1; }
22408 name[pos] = b'0' + (v % 10) as u8; pos += 1;
22409 name[pos] = b'.'; pos += 1;
22410 }
22411 let suffix = b"in-addr.arpa";
22412 for &c in suffix { name[pos] = c; pos += 1; }
22413 name[pos] = 0;
22414 let mut answer = [0u8; 512];
22415 let r = res_query(name.as_ptr() as *const c_char, 1, 12, answer.as_mut_ptr(), answer.len() as c_int);
22416 if r < 12 { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
22417 let end = answer.as_ptr().add(r as usize);
22418 let qd = dns_read_u16(answer.as_ptr().add(4)) as usize;
22419 let an = dns_read_u16(answer.as_ptr().add(6)) as usize;
22420 let mut p = answer.as_ptr().add(12);
22421 for _ in 0..qd { p = dns_skip_name(p, end); p = p.add(4); }
22422 for _ in 0..an {
22423 p = dns_skip_name(p, end);
22424 if p.add(10) > end { break; }
22425 let typ = dns_read_u16(p);
22426 let rdlen = dns_read_u16(p.add(8)) as usize;
22427 let rdata = p.add(10);
22428 if typ == 12 && dns_expand_name(rdata, answer.as_ptr(), HOST_NAME.as_mut_ptr(), HOST_NAME.len()) {
22429 let mut o = crate::strlen(HOST_NAME.as_ptr());
22430 if o > 0 && HOST_NAME[o - 1] == b'.' as c_char { o -= 1; }
22431 HOST_NAME[o] = 0;
22432 core::ptr::copy_nonoverlapping(a, HOST_ADDR.as_mut_ptr(), 4);
22433 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
22434 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
22435 HOST_ENT.h_addrtype = AF_INET;
22436 HOST_ENT.h_length = 4;
22437 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
22438 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
22439 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
22440 h_errno = 0;
22441 return &raw mut HOST_ENT;
22442 }
22443 p = rdata.add(rdlen);
22444 }
22445 h_errno = HOST_NOT_FOUND;
22446 core::ptr::null_mut()
22447}
22448
22449#[inline]
22454fn sysno(x86_64: i64, generic: i64) -> i64 {
22455 if cfg!(target_arch = "x86_64") { x86_64 } else { generic }
22456}
22457
22458#[no_mangle]
22459pub unsafe extern "C" fn settimeofday(tv: *const c_void, tz: *const c_void) -> c_int {
22460 let r = <Arch as Syscalls>::syscall2(sysno(164, 170), tv as i64, tz as i64);
22461 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22462}
22463
22464#[no_mangle]
22465pub unsafe extern "C" fn stime(t: *const i64) -> c_int {
22466 if t.is_null() { ERRNO!() = EINVAL; return -1; }
22467 let tv = timeval { tv_sec: *t, tv_usec: 0 };
22468 settimeofday(&tv as *const timeval as *const c_void, core::ptr::null())
22469}
22470
22471#[no_mangle]
22472pub unsafe extern "C" fn times(buf: *mut c_void) -> c_long {
22473 let r = <Arch as Syscalls>::syscall1(sysno(100, 153), buf as i64);
22474 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_long }
22475}
22476
22477#[no_mangle]
22478pub 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 {
22479 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);
22480 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22481}
22482
22483#[no_mangle]
22484pub unsafe extern "C" fn tee(fd_in: c_int, fd_out: c_int, len: usize, flags: u32) -> isize {
22485 let r = <Arch as Syscalls>::syscall4(sysno(276, 77), fd_in as i64, fd_out as i64, len as i64, flags as i64);
22486 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22487}
22488
22489#[no_mangle]
22490pub unsafe extern "C" fn statx(dirfd: c_int, path: *const c_char, flags: c_int, mask: u32, buf: *mut c_void) -> c_int {
22491 let r = <Arch as Syscalls>::syscall5(sysno(332, 291), dirfd as i64, path as i64, flags as i64, mask as i64, buf as i64);
22492 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22493}
22494
22495#[no_mangle]
22496pub unsafe extern "C" fn setns(fd: c_int, nstype: c_int) -> c_int {
22497 let r = <Arch as Syscalls>::syscall2(SYS_SETNS, fd as i64, nstype as i64);
22498 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22499}
22500
22501#[no_mangle]
22502pub unsafe extern "C" fn setfsuid(uid: u32) -> c_int {
22503 <Arch as Syscalls>::syscall1(sysno(122, 151), uid as i64) as c_int
22504}
22505
22506#[no_mangle]
22507pub unsafe extern "C" fn setfsgid(gid: u32) -> c_int {
22508 <Arch as Syscalls>::syscall1(sysno(123, 152), gid as i64) as c_int
22509}
22510
22511#[no_mangle]
22512pub unsafe extern "C" fn setregid(rgid: u32, egid: u32) -> c_int {
22513 let r = <Arch as Syscalls>::syscall2(sysno(114, 143), rgid as i64, egid as i64);
22514 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22515}
22516
22517#[no_mangle]
22518pub 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 {
22519 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);
22520 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22521}
22522
22523#[no_mangle]
22524pub 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 {
22525 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);
22526 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22527}
22528
22529#[no_mangle]
22530pub unsafe extern "C" fn tcgetwinsize(fd: c_int, ws: *mut c_void) -> c_int {
22531 if fd < 0 || ws.is_null() { ERRNO!() = EINVAL; return -1; }
22532 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5413, ws as i64);
22533 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22534}
22535
22536#[no_mangle]
22537pub unsafe extern "C" fn tcsetwinsize(fd: c_int, ws: *const c_void) -> c_int {
22538 if fd < 0 || ws.is_null() { ERRNO!() = EINVAL; return -1; }
22539 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5414, ws as i64);
22540 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22541}
22542
22543#[no_mangle]
22544pub unsafe extern "C" fn sockatmark(fd: c_int) -> c_int {
22545 let mut at: c_int = 0;
22546 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x8905, &mut at as *mut c_int as i64);
22547 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { at }
22548}
22549
22550#[no_mangle]
22551pub unsafe extern "C" fn isastream(fd: c_int) -> c_int {
22552 let mut buf = [0u8; 64];
22553 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5401, buf.as_mut_ptr() as i64);
22554 if r < 0 { ERRNO!() = (-r) as c_int; 0 } else { 1 }
22555}
22556
22557#[no_mangle]
22558pub unsafe extern "C" fn posix_madvise(addr: *mut c_void, len: usize, advice: c_int) -> c_int {
22559 madvise(addr as *mut u8, len, advice)
22560}
22561
22562#[no_mangle]
22563pub unsafe extern "C" fn secure_getenv(name: *const c_char) -> *mut c_char {
22564 if getauxval(23) != 0 { return core::ptr::null_mut(); }
22565 getenv(name)
22566}
22567
22568#[no_mangle]
22569pub unsafe extern "C" fn sigandset(dest: *mut c_ulong, left: *const c_ulong, right: *const c_ulong) -> c_int {
22570 if dest.is_null() || left.is_null() || right.is_null() { return -1; }
22571 *dest = *left & *right;
22572 0
22573}
22574
22575#[no_mangle]
22576pub unsafe extern "C" fn sigorset(dest: *mut c_ulong, left: *const c_ulong, right: *const c_ulong) -> c_int {
22577 if dest.is_null() || left.is_null() || right.is_null() { return -1; }
22578 *dest = *left | *right;
22579 0
22580}
22581
22582#[no_mangle]
22583pub unsafe extern "C" fn sigisemptyset(set: *const c_ulong) -> c_int {
22584 if set.is_null() { return 1; }
22585 (*set == 0) as c_int
22586}
22587
22588#[no_mangle]
22589pub unsafe extern "C" fn sighold(sig: c_int) -> c_int {
22590 let set: c_ulong = 1u64 << (sig - 1) as u32;
22591 sigprocmask(0, &set, core::ptr::null_mut());
22592 0
22593}
22594
22595#[no_mangle]
22596pub unsafe extern "C" fn sigignore(sig: c_int) -> c_int {
22597 let _ = signal(sig, 1);
22598 0
22599}
22600
22601#[no_mangle]
22602pub unsafe extern "C" fn sigrelse(sig: c_int) -> c_int {
22603 let set: c_ulong = 1u64 << (sig - 1) as u32;
22604 sigprocmask(1, &set, core::ptr::null_mut());
22605 0
22606}
22607
22608#[no_mangle]
22609pub unsafe extern "C" fn siginterrupt(sig: c_int, flag: c_int) -> c_int {
22610 let mut sa: sigaction = core::mem::zeroed();
22611 if sigaction(sig, core::ptr::null(), &mut sa) != 0 { return -1; }
22612 if flag != 0 { sa.sa_flags &= !(SA_RESTART as c_int); } else { sa.sa_flags |= SA_RESTART as c_int; }
22613 sigaction(sig, &sa, core::ptr::null_mut())
22614}
22615
22616#[no_mangle]
22617pub unsafe extern "C" fn sigpause(sig: c_int) -> c_int {
22618 let set: c_ulong = 1u64 << (sig - 1) as u32;
22619 sigsuspend(&set)
22620}
22621
22622#[no_mangle]
22623pub unsafe extern "C" fn semtimedop(semid: c_int, sops: *mut c_void, nsops: usize, timeout: *const timespec) -> c_int {
22624 let r = <Arch as Syscalls>::syscall4(sysno(220, 192), semid as i64, sops as i64, nsops as i64, timeout as i64);
22625 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
22626}
22627
22628#[no_mangle]
22629pub unsafe extern "C" fn wait3(status: *mut c_int, options: c_int, rusage: *mut c_void) -> i32 {
22630 wait4(-1, status, options, rusage) as i32
22631}
22632
22633#[no_mangle]
22634pub unsafe extern "C" fn tempnam(dir: *const c_char, pfx: *const c_char) -> *mut c_char {
22635 let mut path = [0 as c_char; 256];
22636 let mut i = 0;
22637 if !dir.is_null() {
22638 while *dir.add(i) != 0 && i < 200 { path[i] = *dir.add(i); i += 1; }
22639 if i > 0 && path[i-1] != b'/' as c_char { path[i] = b'/' as c_char; i += 1; }
22640 } else {
22641 for &c in b"/tmp/" { path[i] = c as c_char; i += 1; }
22642 }
22643 if !pfx.is_null() {
22644 let mut j = 0;
22645 while *pfx.add(j) != 0 && i < 220 { path[i] = *pfx.add(j); i += 1; j += 1; }
22646 }
22647 for &c in b"XXXXXX" { path[i] = c as c_char; i += 1; }
22648 path[i] = 0;
22649 let fd = mkstemp(path.as_mut_ptr());
22650 if fd < 0 { return core::ptr::null_mut(); }
22651 close(fd);
22652 unlink(path.as_ptr());
22653 let n = strlen(path.as_ptr());
22654 let out = malloc(n + 1) as *mut c_char;
22655 if out.is_null() { return core::ptr::null_mut(); }
22656 core::ptr::copy_nonoverlapping(path.as_ptr(), out, n + 1);
22657 out
22658}
22659
22660#[no_mangle]
22661pub unsafe extern "C" fn putwc(c: u32, f: *mut c_void) -> u32 {
22662 fputwc(c as c_int, f as *mut FILE) as u32
22663}
22664
22665#[no_mangle]
22666pub unsafe extern "C" fn __uflow(f: *mut c_void) -> c_int {
22667 fgetc(f as *mut FILE)
22668}
22669
22670#[no_mangle]
22671pub unsafe extern "C" fn __xmknod(_ver: c_int, path: *const c_char, mode: c_uint, dev: u64) -> c_int {
22672 mknod(path, mode, dev)
22673}
22674
22675#[no_mangle]
22676pub unsafe extern "C" fn __xmknodat(_ver: c_int, dirfd: c_int, path: *const c_char, mode: c_uint, dev: u64) -> c_int {
22677 mknodat(dirfd, path, mode, dev)
22678}
22679
22680#[no_mangle]
22681pub 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 {
22682 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);
22683 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22684}
22685
22686#[no_mangle]
22687pub unsafe extern "C" fn open_by_handle_at(mount_fd: c_int, handle: *mut c_void, flags: c_int) -> c_int {
22688 let r = <Arch as Syscalls>::syscall3(sysno(304, 265), mount_fd as i64, handle as i64, flags as i64);
22689 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
22690}
22691
22692#[no_mangle]
22693pub unsafe extern "C" fn dn_skipname(comp: *const u8, eom: *const u8) -> c_int {
22694 let p = dns_skip_name(comp, eom);
22695 if p <= eom { (p as isize - comp as isize) as c_int } else { -1 }
22696}
22697
22698#[no_mangle]
22699pub 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 {
22700 if exp.is_null() || dst.is_null() || dstsiz <= 0 { return -1; }
22701 let mut o = 0usize;
22702 let mut p = exp;
22703 loop {
22704 let start = p;
22705 while *p != 0 && *p != b'.' as c_char { p = p.add(1); }
22706 let l = p as usize - start as usize;
22707 if l > 63 || o + l + 2 > dstsiz as usize { return -1; }
22708 *dst.add(o) = l as u8; o += 1;
22709 core::ptr::copy_nonoverlapping(start as *const u8, dst.add(o), l);
22710 o += l;
22711 if *p == 0 { break; }
22712 p = p.add(1);
22713 }
22714 if o + 1 > dstsiz as usize { return -1; }
22715 *dst.add(o) = 0;
22716 (o + 1) as c_int
22717}
22718
22719#[repr(C)]
22724#[derive(Copy, Clone)]
22725pub struct Spwd {
22726 pub sp_namp: *mut c_char,
22727 pub sp_pwdp: *mut c_char,
22728 pub sp_lstchg: c_long,
22729 pub sp_min: c_long,
22730 pub sp_max: c_long,
22731 pub sp_warn: c_long,
22732 pub sp_inact: c_long,
22733 pub sp_expire: c_long,
22734 pub sp_flag: c_ulong,
22735}
22736
22737static mut SPWD_ENT: Spwd = Spwd {
22738 sp_namp: core::ptr::null_mut(), sp_pwdp: core::ptr::null_mut(),
22739 sp_lstchg: 0, sp_min: 0, sp_max: 0, sp_warn: 0, sp_inact: 0,
22740 sp_expire: 0, sp_flag: 0,
22741};
22742static mut SPWD_BUF: [c_char; 1024] = [0; 1024];
22743static mut SPWD_FILE: *mut FILE = core::ptr::null_mut();
22744
22745unsafe fn parse_spwd(line: *const c_char, ent: *mut Spwd, buf: *mut c_char, buflen: usize) -> bool {
22746 let mut src = line;
22747 let mut o = 0usize;
22748 let mut fields: [*mut c_char; 9] = [core::ptr::null_mut(); 9];
22749 let mut n = 0usize;
22750 while n < 9 {
22751 let start = o;
22752 while *src != 0 && *src != b':' as c_char {
22753 if o + 1 >= buflen { return false; }
22754 *buf.add(o) = *src;
22755 o += 1;
22756 src = src.add(1);
22757 }
22758 *buf.add(o) = 0;
22759 o += 1;
22760 fields[n] = buf.add(start);
22761 n += 1;
22762 if *src == 0 { break; }
22763 src = src.add(1);
22764 }
22765 if n < 9 { return false; }
22766 (*ent).sp_namp = fields[0];
22767 (*ent).sp_pwdp = fields[1];
22768 (*ent).sp_lstchg = crate::strtol(fields[2], core::ptr::null_mut(), 10) as c_long;
22769 (*ent).sp_min = crate::strtol(fields[3], core::ptr::null_mut(), 10) as c_long;
22770 (*ent).sp_max = crate::strtol(fields[4], core::ptr::null_mut(), 10) as c_long;
22771 (*ent).sp_warn = crate::strtol(fields[5], core::ptr::null_mut(), 10) as c_long;
22772 (*ent).sp_inact = crate::strtol(fields[6], core::ptr::null_mut(), 10) as c_long;
22773 (*ent).sp_expire = crate::strtol(fields[7], core::ptr::null_mut(), 10) as c_long;
22774 (*ent).sp_flag = crate::strtoul(fields[8], core::ptr::null_mut(), 10) as c_ulong;
22775 true
22776}
22777
22778#[no_mangle]
22779pub unsafe extern "C" fn setspent() {
22780 endspent();
22781 SPWD_FILE = crate::fopen(b"/etc/shadow\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
22782}
22783
22784#[no_mangle]
22785pub unsafe extern "C" fn endspent() {
22786 if !SPWD_FILE.is_null() { crate::fclose(SPWD_FILE); SPWD_FILE = core::ptr::null_mut(); }
22787}
22788
22789#[no_mangle]
22790pub unsafe extern "C" fn getspent() -> *mut Spwd {
22791 if SPWD_FILE.is_null() { setspent(); if SPWD_FILE.is_null() { return core::ptr::null_mut(); } }
22792 let mut line = [0 as c_char; 1024];
22793 loop {
22794 if crate::fgets(line.as_mut_ptr(), 1024, SPWD_FILE).is_null() { return core::ptr::null_mut(); }
22795 if parse_spwd(line.as_ptr(), &raw mut SPWD_ENT, SPWD_BUF.as_mut_ptr(), SPWD_BUF.len()) {
22796 return &raw mut SPWD_ENT;
22797 }
22798 }
22799}
22800
22801#[no_mangle]
22802pub unsafe extern "C" fn fgetspent(f: *mut FILE) -> *mut Spwd {
22803 if f.is_null() { return core::ptr::null_mut(); }
22804 let mut line = [0 as c_char; 1024];
22805 loop {
22806 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
22807 if parse_spwd(line.as_ptr(), &raw mut SPWD_ENT, SPWD_BUF.as_mut_ptr(), SPWD_BUF.len()) {
22808 return &raw mut SPWD_ENT;
22809 }
22810 }
22811}
22812
22813#[no_mangle]
22814pub unsafe extern "C" fn getspnam(name: *const c_char) -> *mut Spwd {
22815 if name.is_null() { return core::ptr::null_mut(); }
22816 setspent();
22817 loop {
22818 let sp = getspent();
22819 if sp.is_null() { break; }
22820 if crate::strcmp((*sp).sp_namp as *const u8, name as *const u8) == 0 { endspent(); return sp; }
22821 }
22822 endspent();
22823 core::ptr::null_mut()
22824}
22825
22826#[no_mangle]
22827pub 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 {
22828 if result.is_null() { return EINVAL; }
22829 let p = getspnam(name);
22830 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *sp = *p; *result = sp; 0 }
22831}
22832
22833#[no_mangle]
22834pub unsafe extern "C" fn putspent(sp: *const Spwd, f: *mut FILE) -> c_int {
22835 if sp.is_null() || f.is_null() { return -1; }
22836 crate::fprintf(f, b"%s:%s:%ld:%ld:%ld:%ld:%ld:%ld:%lu\\n\0".as_ptr() as *const c_char,
22837 (*sp).sp_namp, (*sp).sp_pwdp, (*sp).sp_lstchg, (*sp).sp_min, (*sp).sp_max,
22838 (*sp).sp_warn, (*sp).sp_inact, (*sp).sp_expire, (*sp).sp_flag)
22839}
22840
22841#[no_mangle]
22842pub unsafe extern "C" fn getgrouplist(user: *const c_char, group: u32, groups: *mut u32, ngroups: *mut i32) -> c_int {
22843 if user.is_null() || groups.is_null() || ngroups.is_null() { return -1; }
22844 let max = *ngroups as usize;
22845 let mut n = 0usize;
22846 if n < max { *groups.add(n) = group; }
22847 n += 1;
22848 setgrent();
22849 loop {
22850 let g = getgrent();
22851 if g.is_null() { break; }
22852 if (*g).gr_gid == group { continue; }
22853 let mut found = false;
22854 let mut i = 0;
22855 while !(*(*g).gr_mem.add(i)).is_null() {
22856 if crate::strcmp(*(*g).gr_mem.add(i) as *const u8, user as *const u8) == 0 {
22857 found = true;
22858 break;
22859 }
22860 i += 1;
22861 }
22862 if found {
22863 if n < max { *groups.add(n) = (*g).gr_gid; }
22864 n += 1;
22865 }
22866 }
22867 endgrent();
22868 if n > max { *ngroups = n as i32; return -1; }
22869 *ngroups = n as i32;
22870 n as c_int
22871}