1#![cfg_attr(not(test), no_std)]
2#![feature(c_variadic)]
3#![feature(linkage)]
4#![cfg_attr(target_arch = "aarch64", feature(f128))]
5#![cfg_attr(target_arch = "riscv64", feature(f128))]
6#![allow(dead_code, non_camel_case_types)]
7#![allow(static_mut_refs)]
11#![allow(improper_ctypes_definitions)]
14
15use core::ffi::{c_char, c_int, c_long, c_longlong, c_uint, c_ulong, c_ulonglong, c_void, VaList};
16use core::ptr::null_mut;
17use core::sync::atomic::{AtomicI32, AtomicUsize, Ordering};
18
19macro_rules! ERRNO {
20 () => { *errno_ptr() };
21}
22
23include!("encoding_tables.rs");
24include!("math_helpers.rs");
25include!("math_bitmanip.rs");
26include!("math_sqrtfmod.rs");
27include!("math_trig.rs");
28include!("math_exp.rs");
29include!("math_erf.rs");
30include!("math_lgamma.rs");
31include!("math_tgamma.rs");
32include!("math_bessel.rs");
33include!("alloc.rs");
34include!("math_log.rs");
35include!("math_pow.rs");
36include!("math_hypot.rs");
37include!("math_hyperbolic.rs");
38include!("math_invtrig.rs");
39include!("math_lrint.rs");
40include!("math_long_double.rs");
41include!("string_fast.rs");
42include!("vdso.rs");
43
44const EILSEQ: c_int = 84;
49const EINVAL: c_int = 22;
50const EFAULT: c_int = 14;
51const E2BIG: c_int = 7;
52
53const LC_CTYPE: c_int = 0;
54const LC_NUMERIC: c_int = 1;
55const LC_TIME: c_int = 2;
56const LC_COLLATE: c_int = 3;
57const LC_MONETARY: c_int = 4;
58const LC_MESSAGES: c_int = 5;
59const LC_ALL: c_int = 6;
60const ENOMEM: c_int = 12;
61const EINTR: c_int = 4;
62const EPERM: c_int = 1;
63const EAGAIN: c_int = 11;
64const EBUSY: c_int = 16;
65const EDEADLK: c_int = 35;
66const ETIMEDOUT: c_int = 110;
67const ECANCELED: c_int = 125;
68const EOVERFLOW: c_int = 75;
69const EOWNERDEAD: c_int = 130;
70const ENOTRECOVERABLE: c_int = 131;
71
72static mut ERRNO_FALLBACK: c_int = 0;
78static ERRNO_TLS_ACTIVE: AtomicUsize = AtomicUsize::new(0);
79const ERRNO_TCB_OFFSET: usize = 0x30;
80
81#[inline]
82unsafe fn errno_ptr() -> *mut c_int {
83 if ERRNO_TLS_ACTIVE.load(Ordering::Relaxed) == 0 {
84 return core::ptr::addr_of_mut!(ERRNO_FALLBACK);
85 }
86 #[cfg(target_arch = "x86_64")]
87 let tp: usize = {
88 let tp: usize;
89 core::arch::asm!("mov {}, fs:[0]", out(reg) tp, options(nostack, preserves_flags));
90 tp
91 };
92 #[cfg(target_arch = "aarch64")]
93 let tp: usize = {
94 let tp: usize;
95 core::arch::asm!("mrs {}, tpidr_el0", out(reg) tp, options(nostack, preserves_flags));
96 tp
97 };
98 #[cfg(target_arch = "riscv64")]
99 let tp: usize = {
100 let tp: usize;
101 core::arch::asm!("mv {}, tp", out(reg) tp, options(nostack, preserves_flags));
102 tp
103 };
104 #[cfg(target_arch = "x86_64")]
105 let tcb = tp;
106 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
107 let tcb = tp - 256;
108 (tcb + ERRNO_TCB_OFFSET) as *mut c_int
109}
110
111unsafe fn errno_init() {
114 let tp = arch_get_tp();
115 #[cfg(target_arch = "x86_64")]
116 let tcb = tp;
117 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
118 let tcb = tp.wrapping_sub(256);
119 if tp != 0 && core::ptr::read(tcb as *const usize) == tcb {
120 ERRNO_TLS_ACTIVE.store(1, Ordering::Relaxed);
121 }
122}
123
124#[cfg(target_arch = "x86_64")]
125unsafe fn arch_get_tp() -> usize {
126 let mut tp: usize = 0;
127 let _ = <Arch as Syscalls>::syscall2(158 , 0x1003 , &mut tp as *mut usize as i64);
128 tp
129}
130
131#[cfg(target_arch = "aarch64")]
132unsafe fn arch_get_tp() -> usize {
133 let tp: usize;
134 core::arch::asm!("mrs {}, tpidr_el0", out(reg) tp, options(nostack, preserves_flags));
135 tp
136}
137
138#[cfg(target_arch = "riscv64")]
139unsafe fn arch_get_tp() -> usize {
140 let tp: usize;
141 core::arch::asm!("mv {}, tp", out(reg) tp, options(nostack, preserves_flags));
142 tp
143}
144
145#[inline]
148unsafe fn syscall_ret(r: i64) -> i64 {
149 if r < 0 {
150 *errno_ptr() = (-r) as c_int;
151 -1
152 } else {
153 r
154 }
155}
156
157#[no_mangle]
158pub unsafe extern "C" fn __errno_location() -> *mut c_int {
159 errno_ptr()
160}
161
162#[cfg(not(test))]
163#[panic_handler]
164fn panic(_: &core::panic::PanicInfo) -> ! {
165 loop {}
166}
167
168#[cfg(not(test))]
170#[no_mangle]
171pub extern "C" fn rust_eh_personality() {}
172
173const PROT_READ: i32 = 1;
178const PROT_WRITE: i32 = 2;
179const MAP_SHARED: i32 = 0x01;
180const MAP_PRIVATE: i32 = 0x02;
181const MAP_ANONYMOUS: i32 = 0x20;
182
183trait Syscalls {
188 unsafe fn syscall0(n: i64) -> i64;
189 unsafe fn syscall1(n: i64, a1: i64) -> i64;
190 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64;
191 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64;
192 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64;
193 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64;
194 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64;
195 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> !;
196}
197
198struct X86_64;
199struct Aarch64;
200struct Riscv64;
201
202#[cfg(target_arch = "x86_64")]
203impl Syscalls for X86_64 {
204 #[inline(always)]
205 unsafe fn syscall0(n: i64) -> i64 {
206 let result: i64;
207 core::arch::asm!(
208 "syscall",
209 inlateout("rax") n => result,
210 lateout("rcx") _,
211 lateout("r11") _,
212 );
213 result
214 }
215 #[inline(always)]
216 unsafe fn syscall1(n: i64, a1: i64) -> i64 {
217 let result: i64;
218 core::arch::asm!(
219 "syscall",
220 inlateout("rax") n => result,
221 in("rdi") a1,
222 lateout("rcx") _,
223 lateout("r11") _,
224 );
225 result
226 }
227 #[inline(always)]
228 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
229 let result: i64;
230 core::arch::asm!(
231 "syscall",
232 inlateout("rax") n => result,
233 in("rdi") a1,
234 in("rsi") a2,
235 lateout("rcx") _,
236 lateout("r11") _,
237 );
238 result
239 }
240 #[inline(always)]
241 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
242 let result: i64;
243 core::arch::asm!(
244 "syscall",
245 inlateout("rax") n => result,
246 in("rdi") a1,
247 in("rsi") a2,
248 in("rdx") a3,
249 lateout("rcx") _,
250 lateout("r11") _,
251 );
252 result
253 }
254 #[inline(always)]
255 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
256 let result: i64;
257 core::arch::asm!(
258 "syscall",
259 inlateout("rax") n => result,
260 in("rdi") a1,
261 in("rsi") a2,
262 in("rdx") a3,
263 in("r10") a4,
264 lateout("rcx") _,
265 lateout("r11") _,
266 );
267 result
268 }
269 #[inline(always)]
270 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
271 let result: i64;
272 core::arch::asm!(
273 "syscall",
274 inlateout("rax") n => result,
275 in("rdi") a1,
276 in("rsi") a2,
277 in("rdx") a3,
278 in("r10") a4,
279 in("r8") a5,
280 lateout("rcx") _,
281 lateout("r11") _,
282 );
283 result
284 }
285 #[inline(always)]
286 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
287 let result: i64;
288 core::arch::asm!(
289 "syscall",
290 inlateout("rax") n => result,
291 in("rdi") a1,
292 in("rsi") a2,
293 in("rdx") a3,
294 in("r10") a4,
295 in("r8") a5,
296 in("r9") a6,
297 lateout("rcx") _,
298 lateout("r11") _,
299 );
300 result
301 }
302 #[inline(always)]
303 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
304 core::arch::asm!(
305 "syscall",
306 in("rax") n,
307 in("rdi") a1,
308 options(noreturn)
309 );
310 }
311}
312
313#[cfg(target_arch = "aarch64")]
314impl Syscalls for Aarch64 {
315 #[inline(always)]
316 unsafe fn syscall0(n: i64) -> i64 {
317 let result: i64;
318 core::arch::asm!(
319 "svc #0",
320 inlateout("x8") n => _,
321 lateout("x0") result,
322 options(nostack),
323 );
324 result
325 }
326 #[inline(always)]
327 unsafe fn syscall1(n: i64, a1: i64) -> i64 {
328 let result: i64;
329 core::arch::asm!(
330 "svc #0",
331 inlateout("x8") n => _,
332 inlateout("x0") a1 => result,
333 options(nostack),
334 );
335 result
336 }
337 #[inline(always)]
338 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
339 let result: i64;
340 core::arch::asm!(
341 "svc #0",
342 inlateout("x8") n => _,
343 inlateout("x0") a1 => result,
344 inlateout("x1") a2 => _,
345 options(nostack),
346 );
347 result
348 }
349 #[inline(always)]
350 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
351 let result: i64;
352 core::arch::asm!(
353 "svc #0",
354 inlateout("x8") n => _,
355 inlateout("x0") a1 => result,
356 inlateout("x1") a2 => _,
357 inlateout("x2") a3 => _,
358 options(nostack),
359 );
360 result
361 }
362 #[inline(always)]
363 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
364 let result: i64;
365 core::arch::asm!(
366 "svc #0",
367 inlateout("x8") n => _,
368 inlateout("x0") a1 => result,
369 inlateout("x1") a2 => _,
370 inlateout("x2") a3 => _,
371 inlateout("x3") a4 => _,
372 options(nostack),
373 );
374 result
375 }
376 #[inline(always)]
377 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
378 let result: i64;
379 core::arch::asm!(
380 "svc #0",
381 inlateout("x8") n => _,
382 inlateout("x0") a1 => result,
383 inlateout("x1") a2 => _,
384 inlateout("x2") a3 => _,
385 inlateout("x3") a4 => _,
386 inlateout("x4") a5 => _,
387 options(nostack),
388 );
389 result
390 }
391 #[inline(always)]
392 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
393 let result: i64;
394 core::arch::asm!(
395 "svc #0",
396 inlateout("x8") n => _,
397 inlateout("x0") a1 => result,
398 inlateout("x1") a2 => _,
399 inlateout("x2") a3 => _,
400 inlateout("x3") a4 => _,
401 inlateout("x4") a5 => _,
402 inlateout("x5") a6 => _,
403 options(nostack),
404 );
405 result
406 }
407 #[inline(always)]
408 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
409 core::arch::asm!(
410 "svc #0",
411 in("x8") n,
412 in("x0") a1,
413 options(noreturn, nostack),
414 );
415 }
416}
417
418#[cfg(target_arch = "riscv64")]
419impl Syscalls for Riscv64 {
420 #[inline(always)]
421 unsafe fn syscall0(n: i64) -> i64 {
422 let result: i64;
423 core::arch::asm!(
424 "ecall",
425 inlateout("a7") n => _,
426 lateout("a0") result,
427 options(nostack),
428 );
429 result
430 }
431 #[inline(always)]
432 unsafe fn syscall1(n: i64, a1: i64) -> i64 {
433 let result: i64;
434 core::arch::asm!(
435 "ecall",
436 inlateout("a7") n => _,
437 inlateout("a0") a1 => result,
438 options(nostack),
439 );
440 result
441 }
442 #[inline(always)]
443 unsafe fn syscall2(n: i64, a1: i64, a2: i64) -> i64 {
444 let result: i64;
445 core::arch::asm!(
446 "ecall",
447 inlateout("a7") n => _,
448 inlateout("a0") a1 => result,
449 inlateout("a1") a2 => _,
450 options(nostack),
451 );
452 result
453 }
454 #[inline(always)]
455 unsafe fn syscall3(n: i64, a1: i64, a2: i64, a3: i64) -> i64 {
456 let result: i64;
457 core::arch::asm!(
458 "ecall",
459 inlateout("a7") n => _,
460 inlateout("a0") a1 => result,
461 inlateout("a1") a2 => _,
462 inlateout("a2") a3 => _,
463 options(nostack),
464 );
465 result
466 }
467 #[inline(always)]
468 unsafe fn syscall4(n: i64, a1: i64, a2: i64, a3: i64, a4: i64) -> i64 {
469 let result: i64;
470 core::arch::asm!(
471 "ecall",
472 inlateout("a7") n => _,
473 inlateout("a0") a1 => result,
474 inlateout("a1") a2 => _,
475 inlateout("a2") a3 => _,
476 inlateout("a3") a4 => _,
477 options(nostack),
478 );
479 result
480 }
481 #[inline(always)]
482 unsafe fn syscall5(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64) -> i64 {
483 let result: i64;
484 core::arch::asm!(
485 "ecall",
486 inlateout("a7") n => _,
487 inlateout("a0") a1 => result,
488 inlateout("a1") a2 => _,
489 inlateout("a2") a3 => _,
490 inlateout("a3") a4 => _,
491 inlateout("a4") a5 => _,
492 options(nostack),
493 );
494 result
495 }
496 #[inline(always)]
497 unsafe fn syscall6(n: i64, a1: i64, a2: i64, a3: i64, a4: i64, a5: i64, a6: i64) -> i64 {
498 let result: i64;
499 core::arch::asm!(
500 "ecall",
501 inlateout("a7") n => _,
502 inlateout("a0") a1 => result,
503 inlateout("a1") a2 => _,
504 inlateout("a2") a3 => _,
505 inlateout("a3") a4 => _,
506 inlateout("a4") a5 => _,
507 inlateout("a5") a6 => _,
508 options(nostack),
509 );
510 result
511 }
512 #[inline(always)]
513 unsafe fn syscall_noreturn1(n: i64, a1: i64) -> ! {
514 core::arch::asm!(
515 "ecall",
516 in("a7") n,
517 in("a0") a1,
518 options(noreturn, nostack),
519 );
520 }
521}
522
523#[cfg(target_arch = "x86_64")]
524type Arch = X86_64;
525#[cfg(target_arch = "aarch64")]
526type Arch = Aarch64;
527#[cfg(target_arch = "riscv64")]
528type Arch = Riscv64;
529
530
531
532#[cfg(target_arch = "x86_64")]
534mod sysnr {
535 pub const SYS_READ: i64 = 0;
536 pub const SYS_WRITE: i64 = 1;
537 pub const SYS_OPEN: i64 = 2;
538 pub const SYS_CLOSE: i64 = 3;
539 pub const SYS_STAT: i64 = 4;
540 pub const SYS_FSTAT: i64 = 5;
541 pub const SYS_LSEEK: i64 = 8;
542 pub const SYS_MMAP: i64 = 9;
543 pub const SYS_MUNMAP: i64 = 11;
544 pub const SYS_MPROTECT: i64 = 10;
545 pub const SYS_RT_SIGACTION: i64 = 13;
546 pub const SYS_RT_SIGPROCMASK: i64 = 14;
547 pub const SYS_IOCTL: i64 = 16;
548 pub const SYS_ACCESS: i64 = 21;
549 pub const SYS_SHMGET: i64 = 29;
550 pub const SYS_SHMAT: i64 = 30;
551 pub const SYS_SHMCTL: i64 = 31;
552 pub const SYS_DUP: i64 = 32;
553 pub const SYS_NANOSLEEP: i64 = 35;
554 pub const SYS_SETITIMER: i64 = 38;
555 pub const SYS_ALARM: i64 = 37;
556 pub const SYS_SOCKET: i64 = 41;
557 pub const SYS_CONNECT: i64 = 42;
558 pub const SYS_ACCEPT: i64 = 43;
559 pub const SYS_ACCEPT4: i64 = 288;
560 pub const SYS_SENDTO: i64 = 44;
561 pub const SYS_RECVFROM: i64 = 45;
562 pub const SYS_SENDMSG: i64 = 46;
563 pub const SYS_RECVMSG: i64 = 47;
564 pub const SYS_SHUTDOWN: i64 = 48;
565 pub const SYS_BIND: i64 = 49;
566 pub const SYS_LISTEN: i64 = 50;
567 pub const SYS_GETSOCKNAME: i64 = 51;
568 pub const SYS_SOCKETPAIR: i64 = 53;
569 pub const SYS_SETSOCKOPT: i64 = 54;
570 pub const SYS_EXECVE: i64 = 59;
571 pub const SYS_WAIT4: i64 = 61;
572 pub const SYS_KILL: i64 = 62;
573 pub const SYS_UNAME: i64 = 63;
574 pub const SYS_SEMGET: i64 = 64;
575 pub const SYS_SEMOP: i64 = 65;
576 pub const SYS_SEMCTL: i64 = 66;
577 pub const SYS_SHMDT: i64 = 67;
578 pub const SYS_MSGGET: i64 = 68;
579 pub const SYS_MSGSND: i64 = 69;
580 pub const SYS_MSGRCV: i64 = 70;
581 pub const SYS_MSGCTL: i64 = 71;
582 pub const SYS_FCNTL: i64 = 72;
583 pub const SYS_FSYNC: i64 = 74;
584 pub const SYS_TRUNCATE: i64 = 76;
585 pub const SYS_FTRUNCATE: i64 = 77;
586 pub const SYS_GETCWD: i64 = 79;
587 pub const SYS_CHDIR: i64 = 80;
588 pub const SYS_SYMLINK: i64 = 88;
589 pub const SYS_FCHMOD: i64 = 91;
590 pub const SYS_UMASK: i64 = 95;
591 pub const SYS_GETRLIMIT: i64 = 97;
592 pub const SYS_SETUID: i64 = 105;
593 pub const SYS_SETGID: i64 = 106;
594 pub const SYS_SETPGID: i64 = 109;
595 pub const SYS_GETGROUPS: i64 = 115;
596 pub const SYS_GETPGID: i64 = 121;
597 pub const SYS_GETSID: i64 = 124;
598 pub const SYS_RT_SIGPENDING: i64 = 127;
599 pub const SYS_RT_SIGTIMEDWAIT: i64 = 128;
600 pub const SYS_RT_SIGSUSPEND: i64 = 130;
601 pub const SYS_SIGALTSTACK: i64 = 131;
602 pub const SYS_SETRLIMIT: i64 = 160;
603 pub const SYS_SETHOSTNAME: i64 = 170;
604 pub const SYS_FUTEX: i64 = 202;
605 pub const SYS_CLOCK_GETTIME: i64 = 228;
606 pub const SYS_CLOCK_GETRES: i64 = 229;
607 pub const SYS_CLOCK_NANOSLEEP: i64 = 230;
608 pub const SYS_EXIT_GROUP: i64 = 231;
609 pub const SYS_TGKILL: i64 = 234;
610 pub const SYS_MKDIRAT: i64 = 258;
611 pub const SYS_NEWFSTATAT: i64 = 262;
612 pub const SYS_UNLINKAT: i64 = 263;
613 pub const SYS_LINKAT: i64 = 265;
614 pub const SYS_SYMLINKAT: i64 = 266;
615 pub const SYS_READLINKAT: i64 = 267;
616 pub const SYS_FCHMODAT: i64 = 268;
617 pub const SYS_SET_ROBUST_LIST: i64 = 273;
618 pub const SYS_UTIMENSAT: i64 = 280;
619 pub const SYS_OPENAT: i64 = 257;
620 pub const SYS_FACCESSAT: i64 = 269;
621 pub const SYS_DUP3: i64 = 292;
622 pub const SYS_PIPE2: i64 = 293;
623 pub const SYS_SYNCFS: i64 = 306;
624 pub const SYS_RENAMEAT2: i64 = 316;
625 pub const SYS_STATFS: i64 = 137;
626 pub const SYS_FSTATFS: i64 = 138;
627 pub const SYS_FDATASYNC: i64 = 75;
628 pub const SYS_PAUSE: i64 = 34;
629 pub const SYS_POLL: i64 = 7;
630 pub const SYS_PPOLL: i64 = 271;
631 pub const SYS_PSELECT6: i64 = 270;
632 pub const SYS_GETPID: i64 = 39;
633 pub const SYS_FORK: i64 = 57;
634 pub const SYS_EXIT: i64 = 60;
635 pub const SYS_GETPPID: i64 = 110;
636 pub const SYS_SETSID: i64 = 112;
637 pub const SYS_SYNC: i64 = 162;
638 pub const SYS_GETUID: i64 = 102;
639 pub const SYS_GETGID: i64 = 104;
640 pub const SYS_GETEUID: i64 = 107;
641 pub const SYS_GETEGID: i64 = 108;
642 pub const SYS_GETTID: i64 = 186;
643 pub const SYS_CLOCK_SETTIME: i64 = 227;
644 pub const SYS_CLONE: i64 = 56;
645 pub const SYS_PREAD64: i64 = 17;
646 pub const SYS_MREMAP: i64 = 25;
647 pub const SYS_SYSINFO: i64 = 99;
648 pub const SYS_MEMBARRIER: i64 = 324;
649 pub const SYS_VHANGUP: i64 = 153;
650 pub const SYS_VMSPLICE: i64 = 278;
651 pub const SYS_GETDENTS64: i64 = 217;
652 pub const SYS_EPOLL_CREATE: i64 = 213;
653 pub const SYS_EPOLL_CREATE1: i64 = 291;
654 pub const SYS_EPOLL_CTL: i64 = 233;
655 pub const SYS_EPOLL_WAIT: i64 = 232;
656 pub const SYS_EPOLL_PWAIT: i64 = 281;
657 pub const SYS_EVENTFD2: i64 = 290;
658 pub const SYS_SIGNALFD4: i64 = 289;
659 pub const SYS_TIMERFD_CREATE: i64 = 283;
660 pub const SYS_TIMERFD_SETTIME: i64 = 286;
661 pub const SYS_TIMERFD_GETTIME: i64 = 287;
662 pub const SYS_PRCTL: i64 = 157;
663 pub const SYS_FALLOCATE: i64 = 285;
664 pub const SYS_FLOCK: i64 = 73;
665 pub const SYS_SETGROUPS: i64 = 116;
666 pub const SYS_SETRESUID: i64 = 117;
667 pub const SYS_SETRESGID: i64 = 119;
668 pub const SYS_GETRESUID: i64 = 118;
669 pub const SYS_GETRESGID: i64 = 120;
670 pub const SYS_MKNOD: i64 = 133;
671 pub const SYS_FCHDIR: i64 = 81;
672 pub const SYS_FCHOWN: i64 = 93;
673 pub const SYS_ACCT: i64 = 163;
674 pub const SYS_ADJTIMEX: i64 = 159;
675 pub const SYS_CAPGET: i64 = 125;
676 pub const SYS_CAPSET: i64 = 126;
677 pub const SYS_CHROOT: i64 = 161;
678 pub const SYS_COPY_FILE_RANGE: i64 = 326;
679 pub const SYS_DELETE_MODULE: i64 = 176;
680 pub const SYS_INIT_MODULE: i64 = 175;
681 pub const SYS_FCHOWNAT: i64 = 260;
682 pub const SYS_MKNODAT: i64 = 259;
683 pub const SYS_SETNS: i64 = 308;
684 pub const SYS_UNSHARE: i64 = 272;
685 pub const SYS_REBOOT: i64 = 169;
686 pub const SYS_NICE: i64 = 34;
687 pub const SYS_SETPRIORITY: i64 = 141;
688 pub const SYS_GETPRIORITY: i64 = 140;
689 pub const SYS_IOPERM: i64 = 173;
690 pub const SYS_IOPL: i64 = 172;
691 pub const SYS_SWAPON: i64 = 167;
692 pub const SYS_SWAPOFF: i64 = 168;
693 pub const SYS_MOUNT: i64 = 165;
694 pub const SYS_UMOUNT2: i64 = 166;
695 pub const SYS_PIVOT_ROOT: i64 = 155;
696 pub const SYS_SETTIMEOFDAY: i64 = 164;
697 pub const SYS_GETTIMEOFDAY: i64 = 96;
698}
699#[cfg(target_arch = "aarch64")]
700mod sysnr {
701 pub const SYS_READ: i64 = 63;
702 pub const SYS_WRITE: i64 = 64;
703 pub const SYS_CLOSE: i64 = 57;
705 pub const SYS_FSTAT: i64 = 80;
707 pub const SYS_LSEEK: i64 = 62;
708 pub const SYS_MMAP: i64 = 222;
709 pub const SYS_MUNMAP: i64 = 215;
710 pub const SYS_RT_SIGACTION: i64 = 134;
711 pub const SYS_RT_SIGPROCMASK: i64 = 135;
712 pub const SYS_IOCTL: i64 = 29;
713 pub const SYS_SHMGET: i64 = 194;
715 pub const SYS_SHMAT: i64 = 196;
716 pub const SYS_SHMCTL: i64 = 195;
717 pub const SYS_DUP: i64 = 23;
718 pub const SYS_NANOSLEEP: i64 = 101;
719 pub const SYS_SETITIMER: i64 = 103;
720 pub const SYS_SOCKET: i64 = 198;
722 pub const SYS_CONNECT: i64 = 203;
723 pub const SYS_ACCEPT: i64 = 202;
724 pub const SYS_SENDTO: i64 = 206;
725 pub const SYS_RECVFROM: i64 = 207;
726 pub const SYS_SHUTDOWN: i64 = 210;
727 pub const SYS_BIND: i64 = 200;
728 pub const SYS_LISTEN: i64 = 201;
729 pub const SYS_GETSOCKNAME: i64 = 204;
730 pub const SYS_SOCKETPAIR: i64 = 199;
731 pub const SYS_SETSOCKOPT: i64 = 208;
732 pub const SYS_EXECVE: i64 = 221;
733 pub const SYS_WAIT4: i64 = 260;
734 pub const SYS_KILL: i64 = 129;
735 pub const SYS_UNAME: i64 = 160;
736 pub const SYS_SEMGET: i64 = 190;
737 pub const SYS_SEMOP: i64 = 193;
738 pub const SYS_SEMCTL: i64 = 191;
739 pub const SYS_SHMDT: i64 = 197;
740 pub const SYS_MSGGET: i64 = 186;
741 pub const SYS_MSGSND: i64 = 189;
742 pub const SYS_MSGRCV: i64 = 188;
743 pub const SYS_MSGCTL: i64 = 187;
744 pub const SYS_FCNTL: i64 = 25;
745 pub const SYS_FSYNC: i64 = 82;
746 pub const SYS_TRUNCATE: i64 = 45;
747 pub const SYS_FTRUNCATE: i64 = 46;
748 pub const SYS_GETCWD: i64 = 17;
749 pub const SYS_CHDIR: i64 = 49;
750 pub const SYS_FCHMOD: i64 = 52;
752 pub const SYS_UMASK: i64 = 166;
753 pub const SYS_GETRLIMIT: i64 = 163;
754 pub const SYS_SETUID: i64 = 146;
755 pub const SYS_SETGID: i64 = 144;
756 pub const SYS_SETPGID: i64 = 154;
757 pub const SYS_GETGROUPS: i64 = 158;
758 pub const SYS_GETPGID: i64 = 155;
759 pub const SYS_GETSID: i64 = 156;
760 pub const SYS_RT_SIGPENDING: i64 = 136;
761 pub const SYS_RT_SIGTIMEDWAIT: i64 = 137;
762 pub const SYS_RT_SIGSUSPEND: i64 = 133;
763 pub const SYS_SIGALTSTACK: i64 = 132;
764 pub const SYS_SETRLIMIT: i64 = 164;
765 pub const SYS_SETHOSTNAME: i64 = 161;
766 pub const SYS_FUTEX: i64 = 98;
767 pub const SYS_CLOCK_GETTIME: i64 = 113;
768 pub const SYS_CLOCK_GETRES: i64 = 114;
769 pub const SYS_CLOCK_NANOSLEEP: i64 = 115;
770 pub const SYS_EXIT_GROUP: i64 = 94;
771 pub const SYS_TGKILL: i64 = 131;
772 pub const SYS_MKDIRAT: i64 = 34;
773 pub const SYS_NEWFSTATAT: i64 = 79;
774 pub const SYS_UNLINKAT: i64 = 35;
775 pub const SYS_LINKAT: i64 = 37;
776 pub const SYS_SYMLINKAT: i64 = 36;
777 pub const SYS_READLINKAT: i64 = 78;
778 pub const SYS_FCHMODAT: i64 = 53;
779 pub const SYS_SET_ROBUST_LIST: i64 = 99;
780 pub const SYS_UTIMENSAT: i64 = 88;
781 pub const SYS_OPENAT: i64 = 56;
782 pub const SYS_FACCESSAT: i64 = 48;
783 pub const SYS_DUP3: i64 = 24;
784 pub const SYS_PIPE2: i64 = 59;
785 pub const SYS_SYNCFS: i64 = 267;
786 pub const SYS_RENAMEAT2: i64 = 276;
787 pub const SYS_STATFS: i64 = 43;
788 pub const SYS_FSTATFS: i64 = 44;
789 pub const SYS_FDATASYNC: i64 = 83;
790 pub const SYS_GETPID: i64 = 172;
791 pub const SYS_EXIT: i64 = 93;
792 pub const SYS_GETPPID: i64 = 173;
793 pub const SYS_SETSID: i64 = 157;
794 pub const SYS_SYNC: i64 = 81;
795 pub const SYS_GETUID: i64 = 174;
796 pub const SYS_GETGID: i64 = 176;
797 pub const SYS_GETEUID: i64 = 175;
798 pub const SYS_GETEGID: i64 = 177;
799 pub const SYS_GETTID: i64 = 178;
800 pub const SYS_CLOCK_SETTIME: i64 = 112;
801 pub const SYS_CLONE: i64 = 220;
802 pub const SYS_PPOLL: i64 = 73;
803 pub const SYS_PREAD64: i64 = 67;
804 pub const SYS_MREMAP: i64 = 216;
805 pub const SYS_SYSINFO: i64 = 179;
806 pub const SYS_MEMBARRIER: i64 = 283;
807 pub const SYS_VHANGUP: i64 = 58;
808 pub const SYS_VMSPLICE: i64 = 75;
809 pub const SYS_GETTIMEOFDAY: i64 = 169;
810 pub const SYS_SETTIMEOFDAY: i64 = 170;
811 pub const SYS_ADJTIMEX: i64 = 171;
812 pub const SYS_EPOLL_CREATE1: i64 = 20;
813 pub const SYS_EPOLL_CTL: i64 = 21;
814 pub const SYS_EPOLL_WAIT: i64 = 22;
815 pub const SYS_EPOLL_PWAIT: i64 = 22;
816 pub const SYS_EVENTFD2: i64 = 19;
817 pub const SYS_SIGNALFD4: i64 = 74;
818 pub const SYS_TIMERFD_CREATE: i64 = 85;
819 pub const SYS_TIMERFD_SETTIME: i64 = 86;
820 pub const SYS_TIMERFD_GETTIME: i64 = 87;
821 pub const SYS_ACCEPT4: i64 = 242;
822 pub const SYS_ACCT: i64 = 89;
823 pub const SYS_CAPGET: i64 = 90;
824 pub const SYS_CAPSET: i64 = 91;
825 pub const SYS_CHROOT: i64 = 51;
826 pub const SYS_COPY_FILE_RANGE: i64 = 285;
827 pub const SYS_DELETE_MODULE: i64 = 106;
828 pub const SYS_FALLOCATE: i64 = 47;
829 pub const SYS_FCHDIR: i64 = 50;
830 pub const SYS_FCHOWN: i64 = 55;
831 pub const SYS_FCHOWNAT: i64 = 54;
832 pub const SYS_FLOCK: i64 = 32;
833 pub const SYS_GETDENTS64: i64 = 61;
834 pub const SYS_GETPRIORITY: i64 = 141;
835 pub const SYS_GETRESGID: i64 = 150;
836 pub const SYS_GETRESUID: i64 = 148;
837 pub const SYS_INIT_MODULE: i64 = 105;
838 pub const SYS_MKNODAT: i64 = 33;
839 pub const SYS_MOUNT: i64 = 40;
840 pub const SYS_MPROTECT: i64 = 226;
841 pub const SYS_PIVOT_ROOT: i64 = 41;
842 pub const SYS_PRCTL: i64 = 167;
843 pub const SYS_PSELECT6: i64 = 72;
844 pub const SYS_REBOOT: i64 = 142;
845 pub const SYS_RECVMSG: i64 = 212;
846 pub const SYS_SENDMSG: i64 = 211;
847 pub const SYS_SETGROUPS: i64 = 159;
848 pub const SYS_SETNS: i64 = 268;
849 pub const SYS_SETPRIORITY: i64 = 140;
850 pub const SYS_SETRESGID: i64 = 149;
851 pub const SYS_SETRESUID: i64 = 147;
852 pub const SYS_SWAPOFF: i64 = 225;
853 pub const SYS_SWAPON: i64 = 224;
854 pub const SYS_UMOUNT2: i64 = 39;
855 pub const SYS_UNSHARE: i64 = 97;
856}
857#[cfg(target_arch = "riscv64")]
859mod sysnr {
860 pub const SYS_READ: i64 = 63;
861 pub const SYS_WRITE: i64 = 64;
862 pub const SYS_CLOSE: i64 = 57;
863 pub const SYS_FSTAT: i64 = 80;
864 pub const SYS_LSEEK: i64 = 62;
865 pub const SYS_MMAP: i64 = 222;
866 pub const SYS_MUNMAP: i64 = 215;
867 pub const SYS_RT_SIGACTION: i64 = 134;
868 pub const SYS_RT_SIGPROCMASK: i64 = 135;
869 pub const SYS_IOCTL: i64 = 29;
870 pub const SYS_SHMGET: i64 = 194;
871 pub const SYS_SHMAT: i64 = 196;
872 pub const SYS_SHMCTL: i64 = 195;
873 pub const SYS_DUP: i64 = 23;
874 pub const SYS_NANOSLEEP: i64 = 101;
875 pub const SYS_SETITIMER: i64 = 103;
876 pub const SYS_SOCKET: i64 = 198;
877 pub const SYS_CONNECT: i64 = 203;
878 pub const SYS_ACCEPT: i64 = 202;
879 pub const SYS_SENDTO: i64 = 206;
880 pub const SYS_RECVFROM: i64 = 207;
881 pub const SYS_SHUTDOWN: i64 = 210;
882 pub const SYS_BIND: i64 = 200;
883 pub const SYS_LISTEN: i64 = 201;
884 pub const SYS_GETSOCKNAME: i64 = 204;
885 pub const SYS_SOCKETPAIR: i64 = 199;
886 pub const SYS_SETSOCKOPT: i64 = 208;
887 pub const SYS_EXECVE: i64 = 221;
888 pub const SYS_WAIT4: i64 = 260;
889 pub const SYS_KILL: i64 = 129;
890 pub const SYS_UNAME: i64 = 160;
891 pub const SYS_SEMGET: i64 = 190;
892 pub const SYS_SEMOP: i64 = 193;
893 pub const SYS_SEMCTL: i64 = 191;
894 pub const SYS_SHMDT: i64 = 197;
895 pub const SYS_MSGGET: i64 = 186;
896 pub const SYS_MSGSND: i64 = 189;
897 pub const SYS_MSGRCV: i64 = 188;
898 pub const SYS_MSGCTL: i64 = 187;
899 pub const SYS_FCNTL: i64 = 25;
900 pub const SYS_FSYNC: i64 = 82;
901 pub const SYS_TRUNCATE: i64 = 45;
902 pub const SYS_FTRUNCATE: i64 = 46;
903 pub const SYS_GETCWD: i64 = 17;
904 pub const SYS_CHDIR: i64 = 49;
905 pub const SYS_FCHMOD: i64 = 52;
906 pub const SYS_UMASK: i64 = 166;
907 pub const SYS_GETRLIMIT: i64 = 163;
908 pub const SYS_SETUID: i64 = 146;
909 pub const SYS_SETGID: i64 = 144;
910 pub const SYS_SETPGID: i64 = 154;
911 pub const SYS_GETGROUPS: i64 = 158;
912 pub const SYS_GETPGID: i64 = 155;
913 pub const SYS_GETSID: i64 = 156;
914 pub const SYS_RT_SIGPENDING: i64 = 136;
915 pub const SYS_RT_SIGTIMEDWAIT: i64 = 137;
916 pub const SYS_RT_SIGSUSPEND: i64 = 133;
917 pub const SYS_SIGALTSTACK: i64 = 132;
918 pub const SYS_SETRLIMIT: i64 = 164;
919 pub const SYS_SETHOSTNAME: i64 = 161;
920 pub const SYS_FUTEX: i64 = 98;
921 pub const SYS_CLOCK_GETTIME: i64 = 113;
922 pub const SYS_CLOCK_GETRES: i64 = 114;
923 pub const SYS_CLOCK_NANOSLEEP: i64 = 115;
924 pub const SYS_EXIT_GROUP: i64 = 94;
925 pub const SYS_TGKILL: i64 = 131;
926 pub const SYS_MKDIRAT: i64 = 34;
927 pub const SYS_NEWFSTATAT: i64 = 79;
928 pub const SYS_UNLINKAT: i64 = 35;
929 pub const SYS_LINKAT: i64 = 37;
930 pub const SYS_SYMLINKAT: i64 = 36;
931 pub const SYS_READLINKAT: i64 = 78;
932 pub const SYS_FCHMODAT: i64 = 53;
933 pub const SYS_SET_ROBUST_LIST: i64 = 99;
934 pub const SYS_UTIMENSAT: i64 = 88;
935 pub const SYS_OPENAT: i64 = 56;
936 pub const SYS_FACCESSAT: i64 = 48;
937 pub const SYS_DUP3: i64 = 24;
938 pub const SYS_PIPE2: i64 = 59;
939 pub const SYS_SYNCFS: i64 = 267;
940 pub const SYS_RENAMEAT2: i64 = 276;
941 pub const SYS_STATFS: i64 = 43;
942 pub const SYS_FSTATFS: i64 = 44;
943 pub const SYS_FDATASYNC: i64 = 83;
944 pub const SYS_GETPID: i64 = 172;
945 pub const SYS_EXIT: i64 = 93;
946 pub const SYS_GETPPID: i64 = 173;
947 pub const SYS_SETSID: i64 = 157;
948 pub const SYS_SYNC: i64 = 81;
949 pub const SYS_GETUID: i64 = 174;
950 pub const SYS_GETGID: i64 = 176;
951 pub const SYS_GETEUID: i64 = 175;
952 pub const SYS_GETEGID: i64 = 177;
953 pub const SYS_GETTID: i64 = 178;
954 pub const SYS_CLOCK_SETTIME: i64 = 112;
955 pub const SYS_CLONE: i64 = 220;
956 pub const SYS_PPOLL: i64 = 73;
957 pub const SYS_PREAD64: i64 = 67;
958 pub const SYS_MREMAP: i64 = 216;
959 pub const SYS_SYSINFO: i64 = 179;
960 pub const SYS_MEMBARRIER: i64 = 283;
961 pub const SYS_VHANGUP: i64 = 58;
962 pub const SYS_VMSPLICE: i64 = 75;
963 pub const SYS_GETTIMEOFDAY: i64 = 169;
964 pub const SYS_SETTIMEOFDAY: i64 = 170;
965 pub const SYS_ADJTIMEX: i64 = 171;
966 pub const SYS_EPOLL_CREATE1: i64 = 20;
967 pub const SYS_EPOLL_CTL: i64 = 21;
968 pub const SYS_EPOLL_WAIT: i64 = 22;
969 pub const SYS_EPOLL_PWAIT: i64 = 22;
970 pub const SYS_EVENTFD2: i64 = 19;
971 pub const SYS_SIGNALFD4: i64 = 74;
972 pub const SYS_TIMERFD_CREATE: i64 = 85;
973 pub const SYS_TIMERFD_SETTIME: i64 = 86;
974 pub const SYS_TIMERFD_GETTIME: i64 = 87;
975 pub const SYS_ACCEPT4: i64 = 242;
976 pub const SYS_ACCT: i64 = 89;
977 pub const SYS_CAPGET: i64 = 90;
978 pub const SYS_CAPSET: i64 = 91;
979 pub const SYS_CHROOT: i64 = 51;
980 pub const SYS_COPY_FILE_RANGE: i64 = 285;
981 pub const SYS_DELETE_MODULE: i64 = 106;
982 pub const SYS_FALLOCATE: i64 = 47;
983 pub const SYS_FCHDIR: i64 = 50;
984 pub const SYS_FCHOWN: i64 = 55;
985 pub const SYS_FCHOWNAT: i64 = 54;
986 pub const SYS_FLOCK: i64 = 32;
987 pub const SYS_GETDENTS64: i64 = 61;
988 pub const SYS_GETPRIORITY: i64 = 141;
989 pub const SYS_GETRESGID: i64 = 150;
990 pub const SYS_GETRESUID: i64 = 148;
991 pub const SYS_INIT_MODULE: i64 = 105;
992 pub const SYS_MKNODAT: i64 = 33;
993 pub const SYS_MOUNT: i64 = 40;
994 pub const SYS_MPROTECT: i64 = 226;
995 pub const SYS_PIVOT_ROOT: i64 = 41;
996 pub const SYS_PRCTL: i64 = 167;
997 pub const SYS_PSELECT6: i64 = 72;
998 pub const SYS_REBOOT: i64 = 142;
999 pub const SYS_RECVMSG: i64 = 212;
1000 pub const SYS_SENDMSG: i64 = 211;
1001 pub const SYS_SETGROUPS: i64 = 159;
1002 pub const SYS_SETNS: i64 = 268;
1003 pub const SYS_SETPRIORITY: i64 = 140;
1004 pub const SYS_SETRESGID: i64 = 149;
1005 pub const SYS_SETRESUID: i64 = 147;
1006 pub const SYS_SWAPOFF: i64 = 225;
1007 pub const SYS_SWAPON: i64 = 224;
1008 pub const SYS_UMOUNT2: i64 = 39;
1009 pub const SYS_UNSHARE: i64 = 97;
1010}
1011pub use sysnr::*;
1012
1013#[inline]
1018unsafe fn sys_write(fd: i64, buf: *const u8, count: usize) -> i64 {
1019 <Arch as Syscalls>::syscall3(SYS_WRITE, fd as i64, buf as i64, count as i64)
1020}
1021
1022#[inline]
1023unsafe fn sys_read(fd: i64, buf: *mut u8, count: usize) -> i64 {
1024 <Arch as Syscalls>::syscall3(SYS_READ, fd as i64, buf as i64, count as i64)
1025}
1026
1027#[inline]
1028unsafe fn sys_open(path: *const u8, flags: i64, mode: i64) -> i64 {
1029 <Arch as Syscalls>::syscall4(SYS_OPENAT, AT_FDCWD as i64, path as i64, flags as i64, mode as i64)
1030}
1031
1032#[inline]
1033unsafe fn sys_close(fd: i64) -> i64 {
1034 <Arch as Syscalls>::syscall1(SYS_CLOSE, fd as i64)
1035}
1036
1037#[inline]
1038unsafe fn sys_lseek(fd: i64, offset: i64, whence: i64) -> i64 {
1039 <Arch as Syscalls>::syscall3(SYS_LSEEK, fd as i64, offset as i64, whence as i64)
1040}
1041
1042unsafe fn sys_mmap(
1043 addr: *mut u8,
1044 length: usize,
1045 prot: i32,
1046 flags: i32,
1047 fd: i32,
1048 offset: i64,
1049) -> *mut u8 {
1050 let result = <Arch as Syscalls>::syscall6(SYS_MMAP, addr as i64, length as i64, prot as i64, flags as i64, fd as i64, offset);
1051 if result < 0 && result > -4096 {
1052 ERRNO!() = (-result) as c_int;
1053 return MMAP_FAILED;
1054 }
1055 result as *mut u8
1056}
1057
1058unsafe fn sys_munmap(addr: *mut u8, length: usize) -> i64 {
1059 <Arch as Syscalls>::syscall2(SYS_MUNMAP, addr as i64, length as i64)
1060}
1061
1062#[no_mangle]
1069pub unsafe extern "C" fn bcmp(s1: *const c_void, s2: *const c_void, n: usize) -> c_int {
1070 memcmp(s1, s2, n)
1071}
1072
1073#[no_mangle]
1076pub unsafe extern "C" fn strncmp(s1: *const u8, s2: *const u8, n: usize) -> c_int {
1077 let mut i = 0;
1078 while i < n {
1079 let a = *s1.add(i);
1080 let b = *s2.add(i);
1081 if a != b {
1082 return a as c_int - b as c_int;
1083 }
1084 if a == 0 {
1085 return 0;
1086 }
1087 i += 1;
1088 }
1089 0
1090}
1091
1092#[no_mangle]
1093pub unsafe extern "C" fn strcpy(dst: *mut u8, src: *const u8) -> *mut u8 {
1094 let mut i = 0;
1095 loop {
1096 let c = *src.add(i);
1097 *dst.add(i) = c;
1098 if c == 0 {
1099 break;
1100 }
1101 i += 1;
1102 }
1103 dst
1104}
1105
1106#[no_mangle]
1107pub unsafe extern "C" fn strncpy(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 {
1108 let mut i = 0;
1109 while i < n && *src.add(i) != 0 {
1110 *dst.add(i) = *src.add(i);
1111 i += 1;
1112 }
1113 while i < n {
1114 *dst.add(i) = 0;
1115 i += 1;
1116 }
1117 dst
1118}
1119
1120#[no_mangle]
1121pub unsafe extern "C" fn strcat(dst: *mut u8, src: *const u8) -> *mut u8 {
1122 let mut i = 0;
1123 while *dst.add(i) != 0 {
1124 i += 1;
1125 }
1126 let mut j = 0;
1127 loop {
1128 let c = *src.add(j);
1129 *dst.add(i + j) = c;
1130 if c == 0 {
1131 break;
1132 }
1133 j += 1;
1134 }
1135 dst
1136}
1137
1138#[no_mangle]
1139pub unsafe extern "C" fn strncat(dst: *mut u8, src: *const u8, n: usize) -> *mut u8 {
1140 let mut i = 0;
1141 while *dst.add(i) != 0 {
1142 i += 1;
1143 }
1144 let mut j = 0;
1145 while j < n && *src.add(j) != 0 {
1146 *dst.add(i + j) = *src.add(j);
1147 j += 1;
1148 }
1149 *dst.add(i + j) = 0;
1150 dst
1151}
1152
1153#[no_mangle]
1154pub unsafe extern "C" fn strlcpy(dst: *mut u8, src: *const u8, n: usize) -> usize {
1155 let l = strlen(src as *const c_char);
1156 if n > 0 {
1157 let c = if l < n { l } else { n - 1 };
1158 core::ptr::copy_nonoverlapping(src, dst, c);
1159 *dst.add(c) = 0;
1160 }
1161 l
1162}
1163
1164#[no_mangle]
1165pub unsafe extern "C" fn strlcat(dst: *mut u8, src: *const u8, n: usize) -> usize {
1166 let dl = strlen(dst as *const c_char);
1167 let sl = strlen(src as *const c_char);
1168 if dl >= n { return n + sl; }
1169 let c = if sl < n - dl { sl } else { n - dl - 1 };
1170 core::ptr::copy_nonoverlapping(src, dst.add(dl), c);
1171 *dst.add(dl + c) = 0;
1172 dl + sl
1173}
1174
1175#[no_mangle]
1176pub unsafe extern "C" fn bcopy(src: *const c_void, dst: *mut c_void, n: usize) {
1177 core::ptr::copy(src as *const u8, dst as *mut u8, n);
1178}
1179
1180#[no_mangle]
1181pub unsafe extern "C" fn bzero(s: *mut c_void, n: usize) {
1182 core::ptr::write_bytes(s as *mut u8, 0, n);
1183}
1184
1185#[no_mangle]
1186pub unsafe extern "C" fn strndup(s: *const c_char, n: usize) -> *mut c_char {
1187 let mut len = 0;
1188 while len < n && *s.add(len) != 0 {
1189 len += 1;
1190 }
1191 let p = malloc(len + 1) as *mut c_char;
1192 if p.is_null() {
1193 return core::ptr::null_mut();
1194 }
1195 core::ptr::copy_nonoverlapping(s, p, len);
1196 *p.add(len) = 0;
1197 p
1198}
1199
1200#[no_mangle]
1201pub unsafe extern "C" fn strchr(s: *const u8, c: c_int) -> *mut u8 {
1202 let target = c as u8;
1203 let mut i = 0;
1204 loop {
1205 let ch = *s.add(i);
1206 if ch == target {
1207 return s.add(i) as *mut u8;
1208 }
1209 if ch == 0 {
1210 return null_mut();
1211 }
1212 i += 1;
1213 }
1214}
1215
1216#[no_mangle]
1217pub unsafe extern "C" fn strrchr(s: *const u8, c: c_int) -> *mut u8 {
1218 let target = c as u8;
1219 let mut i = 0;
1220 let mut last: *mut u8 = null_mut();
1221 loop {
1222 let ch = *s.add(i);
1223 if ch == target {
1224 last = s.add(i) as *mut u8;
1225 }
1226 if ch == 0 {
1227 return last;
1228 }
1229 i += 1;
1230 }
1231}
1232
1233#[no_mangle]
1234pub unsafe extern "C" fn strnlen(s: *const u8, maxlen: usize) -> usize {
1235 let mut i = 0;
1236 while i < maxlen && *s.add(i) != 0 {
1237 i += 1;
1238 }
1239 i
1240}
1241
1242#[no_mangle]
1243pub unsafe extern "C" fn strcspn(s: *const u8, reject: *const u8) -> usize {
1244 let mut i = 0;
1245 loop {
1246 let c = *s.add(i);
1247 if c == 0 {
1248 return i;
1249 }
1250 let mut j = 0;
1251 loop {
1252 let r = *reject.add(j);
1253 if r == 0 {
1254 break;
1255 }
1256 if c == r {
1257 return i;
1258 }
1259 j += 1;
1260 }
1261 i += 1;
1262 }
1263}
1264
1265#[no_mangle]
1266pub unsafe extern "C" fn strspn(s: *const u8, accept: *const u8) -> usize {
1267 let mut i = 0;
1268 loop {
1269 let c = *s.add(i);
1270 if c == 0 {
1271 return i;
1272 }
1273 let mut found = false;
1274 let mut j = 0;
1275 loop {
1276 let a = *accept.add(j);
1277 if a == 0 {
1278 break;
1279 }
1280 if c == a {
1281 found = true;
1282 break;
1283 }
1284 j += 1;
1285 }
1286 if !found {
1287 return i;
1288 }
1289 i += 1;
1290 }
1291}
1292
1293#[no_mangle]
1294pub unsafe extern "C" fn strpbrk(s: *const u8, accept: *const u8) -> *mut u8 {
1295 let mut i = 0;
1296 loop {
1297 let c = *s.add(i);
1298 if c == 0 {
1299 return null_mut();
1300 }
1301 let mut j = 0;
1302 loop {
1303 let a = *accept.add(j);
1304 if a == 0 {
1305 break;
1306 }
1307 if c == a {
1308 return s.add(i) as *mut u8;
1309 }
1310 j += 1;
1311 }
1312 i += 1;
1313 }
1314}
1315
1316#[no_mangle]
1317pub unsafe extern "C" fn strstr(haystack: *const u8, needle: *const u8) -> *mut u8 {
1318 if *needle == 0 {
1319 return haystack as *mut u8;
1320 }
1321 let mut i = 0;
1322 loop {
1323 let h = *haystack.add(i);
1324 if h == 0 {
1325 return null_mut();
1326 }
1327 if h == *needle {
1328 let mut j = 0;
1329 loop {
1330 let n = *needle.add(j);
1331 if n == 0 {
1332 return haystack.add(i) as *mut u8;
1333 }
1334 if *haystack.add(i + j) != n {
1335 break;
1336 }
1337 j += 1;
1338 }
1339 }
1340 i += 1;
1341 }
1342}
1343
1344#[no_mangle]
1345pub unsafe extern "C" fn memchr(s: *const u8, c: c_int, n: usize) -> *mut u8 {
1346 let target = c as u8;
1347 let mut i = 0;
1348 while i < n {
1349 if *s.add(i) == target {
1350 return s.add(i) as *mut u8;
1351 }
1352 i += 1;
1353 }
1354 null_mut()
1355}
1356
1357#[no_mangle]
1358pub unsafe extern "C" fn memrchr(s: *const u8, c: c_int, n: usize) -> *mut u8 {
1359 let target = c as u8;
1360 let mut i = n;
1361 while i > 0 {
1362 i -= 1;
1363 if *s.add(i) == target {
1364 return s.add(i) as *mut u8;
1365 }
1366 }
1367 null_mut()
1368}
1369
1370#[no_mangle]
1371pub unsafe extern "C" fn memmem(
1372 haystack: *const c_void, haystacklen: usize,
1373 needle: *const c_void, needlelen: usize,
1374) -> *mut c_void {
1375 if needlelen == 0 { return haystack as *mut c_void; }
1376 if haystacklen < needlelen { return null_mut(); }
1377 let h = haystack as *const u8;
1378 let n = needle as *const u8;
1379 let last = haystacklen - needlelen;
1380 for i in 0..=last {
1381 if *h.add(i) == *n && memcmp(h.add(i) as *const c_void, n as *const c_void, needlelen) == 0 {
1382 return h.add(i) as *mut c_void;
1383 }
1384 }
1385 null_mut()
1386}
1387
1388#[no_mangle]
1389pub unsafe extern "C" fn strtok(s: *mut u8, delim: *const u8) -> *mut u8 {
1390 static mut STATE: *mut u8 = core::ptr::null_mut();
1391 let mut p = if s.is_null() { STATE } else { s };
1392 if p.is_null() {
1393 return core::ptr::null_mut();
1394 }
1395 loop {
1396 let c = *p;
1397 if c == 0 {
1398 STATE = core::ptr::null_mut();
1399 return core::ptr::null_mut();
1400 }
1401 let mut is_delim = false;
1402 let mut i = 0;
1403 loop {
1404 let d = *delim.add(i);
1405 if d == 0 {
1406 break;
1407 }
1408 if c == d {
1409 is_delim = true;
1410 break;
1411 }
1412 i += 1;
1413 }
1414 if !is_delim {
1415 break;
1416 }
1417 p = p.add(1);
1418 }
1419 let start = p;
1420 loop {
1421 let c = *p;
1422 if c == 0 {
1423 STATE = core::ptr::null_mut();
1424 return start;
1425 }
1426 let mut is_delim = false;
1427 let mut i = 0;
1428 loop {
1429 let d = *delim.add(i);
1430 if d == 0 {
1431 break;
1432 }
1433 if c == d {
1434 is_delim = true;
1435 break;
1436 }
1437 i += 1;
1438 }
1439 if is_delim {
1440 *p = 0;
1441 STATE = p.add(1);
1442 return start;
1443 }
1444 p = p.add(1);
1445 }
1446}
1447
1448type SizeT = usize;
1453type SSizeT = isize;
1454type mode_t = c_uint;
1455type TimeT = c_long;
1456type ClockT = c_long;
1457type wchar_t = c_int;
1458type wint_t = c_uint;
1459type wctype_t = *const c_int;
1460type wctrans_t = *const c_int;
1461
1462const WEOF: wint_t = 0xffffffff;
1463
1464#[repr(C)]
1465pub struct tm {
1466 pub tm_sec: c_int,
1467 pub tm_min: c_int,
1468 pub tm_hour: c_int,
1469 pub tm_mday: c_int,
1470 pub tm_mon: c_int,
1471 pub tm_year: c_int,
1472 pub tm_wday: c_int,
1473 pub tm_yday: c_int,
1474 pub tm_isdst: c_int,
1475 pub tm_gmtoff: c_long,
1476 pub tm_zone: *const c_char,
1477}
1478
1479#[repr(C)]
1480pub struct timeval {
1481 pub tv_sec: TimeT,
1482 pub tv_usec: c_long,
1483}
1484
1485#[repr(C)]
1486pub struct Timeb {
1487 pub time: TimeT,
1488 pub millitm: u16,
1489 pub timezone: i16,
1490 pub dstflag: u16,
1491}
1492
1493const CT_UPPER: u8 = 1 << 0;
1498const CT_LOWER: u8 = 1 << 1;
1499const CT_DIGIT: u8 = 1 << 2;
1500const CT_SPACE: u8 = 1 << 3;
1501const CT_PUNCT: u8 = 1 << 4;
1502const CT_CNTRL: u8 = 1 << 5;
1503const CT_BLANK: u8 = 1 << 6;
1504const CT_XDIGIT: u8 = 1 << 7;
1505
1506const CT_TABLE: [u8; 128] = {
1507 let mut t = [0u8; 128];
1508 let mut i = 0;
1509 while i < 128 {
1510 let c = i as u8;
1511 let mut flags = 0u8;
1512 if c >= b'A' && c <= b'Z' {
1513 flags |= CT_UPPER;
1514 }
1515 if c >= b'a' && c <= b'z' {
1516 flags |= CT_LOWER;
1517 }
1518 if c >= b'0' && c <= b'9' {
1519 flags |= CT_DIGIT;
1520 }
1521 if c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == b'\x0c' || c == b'\x0b' {
1522 flags |= CT_SPACE;
1523 }
1524 if (c >= b'!' && c <= b'/')
1525 || (c >= b':' && c <= b'@')
1526 || (c >= b'[' && c <= b'`')
1527 || (c >= b'{' && c <= b'~')
1528 {
1529 flags |= CT_PUNCT;
1530 }
1531 if c < 0x20 || c == 0x7f {
1532 flags |= CT_CNTRL;
1533 }
1534 if c == b' ' || c == b'\t' {
1535 flags |= CT_BLANK;
1536 }
1537 if (c >= b'0' && c <= b'9') || (c >= b'A' && c <= b'F') || (c >= b'a' && c <= b'f') {
1538 flags |= CT_XDIGIT;
1539 }
1540 t[i] = flags;
1541 i += 1;
1542 }
1543 t
1544};
1545
1546#[inline]
1547fn ct_flags(c: c_int) -> u8 {
1548 if c < 0 || c > 127 {
1549 0
1550 } else {
1551 CT_TABLE[c as usize]
1552 }
1553}
1554
1555#[no_mangle]
1556pub extern "C" fn isalnum(c: c_int) -> c_int {
1557 (ct_flags(c) & (CT_UPPER | CT_LOWER | CT_DIGIT) != 0) as c_int
1558}
1559
1560#[no_mangle]
1561pub extern "C" fn isalpha(c: c_int) -> c_int {
1562 (ct_flags(c) & (CT_UPPER | CT_LOWER) != 0) as c_int
1563}
1564
1565#[no_mangle]
1566pub extern "C" fn isascii(c: c_int) -> c_int {
1567 ((c as u32) <= 127) as c_int
1568}
1569
1570#[no_mangle]
1571pub extern "C" fn isblank(c: c_int) -> c_int {
1572 (ct_flags(c) & CT_BLANK != 0) as c_int
1573}
1574
1575#[no_mangle]
1576pub extern "C" fn iscntrl(c: c_int) -> c_int {
1577 (ct_flags(c) & CT_CNTRL != 0) as c_int
1578}
1579
1580#[no_mangle]
1581pub extern "C" fn isdigit(c: c_int) -> c_int {
1582 (ct_flags(c) & CT_DIGIT != 0) as c_int
1583}
1584
1585#[no_mangle]
1586pub extern "C" fn isgraph(c: c_int) -> c_int {
1587 (ct_flags(c) & (CT_UPPER | CT_LOWER | CT_DIGIT | CT_PUNCT) != 0) as c_int
1588}
1589
1590#[no_mangle]
1591pub extern "C" fn islower(c: c_int) -> c_int {
1592 (ct_flags(c) & CT_LOWER != 0) as c_int
1593}
1594
1595#[no_mangle]
1596pub extern "C" fn isprint(c: c_int) -> c_int {
1597 let flags = ct_flags(c);
1598 (flags & (CT_UPPER | CT_LOWER | CT_DIGIT | CT_PUNCT | CT_BLANK) != 0) as c_int
1599}
1600
1601#[no_mangle]
1602pub extern "C" fn ispunct(c: c_int) -> c_int {
1603 (ct_flags(c) & CT_PUNCT != 0) as c_int
1604}
1605
1606#[no_mangle]
1607pub extern "C" fn isspace(c: c_int) -> c_int {
1608 (ct_flags(c) & CT_SPACE != 0) as c_int
1609}
1610
1611#[no_mangle]
1612pub extern "C" fn isupper(c: c_int) -> c_int {
1613 (ct_flags(c) & CT_UPPER != 0) as c_int
1614}
1615
1616#[no_mangle]
1617pub extern "C" fn isxdigit(c: c_int) -> c_int {
1618 (ct_flags(c) & CT_XDIGIT != 0) as c_int
1619}
1620
1621#[no_mangle]
1622pub extern "C" fn tolower(c: c_int) -> c_int {
1623 if (ct_flags(c) & CT_UPPER) != 0 {
1624 c + (b'a' as c_int - b'A' as c_int)
1625 } else {
1626 c
1627 }
1628}
1629
1630#[no_mangle]
1631pub extern "C" fn toupper(c: c_int) -> c_int {
1632 if (ct_flags(c) & CT_LOWER) != 0 {
1633 c - (b'a' as c_int - b'A' as c_int)
1634 } else {
1635 c
1636 }
1637}
1638
1639unsafe fn parse_digit(c: u8, base: c_int) -> Option<u8> {
1644 if c == 0 { return None; }
1645 let d = if c >= b'0' && c <= b'9' {
1646 c - b'0'
1647 } else if c >= b'a' && c <= b'z' {
1648 c - b'a' + 10
1649 } else if c >= b'A' && c <= b'Z' {
1650 c - b'A' + 10
1651 } else {
1652 return None;
1653 };
1654 if (d as c_int) < base {
1655 Some(d)
1656 } else {
1657 None
1658 }
1659}
1660
1661unsafe fn parse_prefix(s: *const u8, base: *mut c_int) -> *const u8 {
1662 let mut p = s;
1663 if *base == 0 {
1664 if *p == b'0' {
1665 if (*p.add(1) == b'x' || *p.add(1) == b'X') && parse_digit(*p.add(2), 16).is_some() {
1666 *base = 16;
1667 p = p.add(2);
1668 } else {
1669 *base = 8;
1670 }
1671 } else {
1672 *base = 10;
1673 }
1674 } else if *base == 16 {
1675 if *p == b'0' && (*p.add(1) == b'x' || *p.add(1) == b'X') && parse_digit(*p.add(2), 16).is_some() {
1676 p = p.add(2);
1677 }
1678 }
1679 p
1680}
1681
1682unsafe fn strtox(
1683 s: *const c_char,
1684 endptr: *mut *mut c_char,
1685 mut base: c_int,
1686 pos_limit: u64,
1687 neg_limit: u64,
1688) -> (u64, bool, bool) {
1689 let s0 = s as *const u8;
1690 let mut p = s0;
1691 while isspace(*p as c_int) != 0 {
1692 p = p.add(1);
1693 }
1694
1695 if base < 0 || base == 1 || base > 36 {
1696 if !endptr.is_null() {
1697 *endptr = s as *mut c_char;
1698 }
1699 ERRNO!() = EINVAL;
1700 return (0, false, false);
1701 }
1702
1703 let mut neg = false;
1704 match *p {
1705 b'-' => { neg = true; p = p.add(1); }
1706 b'+' => p = p.add(1),
1707 _ => {}
1708 }
1709
1710 p = parse_prefix(p, &mut base);
1711
1712 let limit = if neg { neg_limit } else { pos_limit };
1713 let mut val: u64 = 0;
1714 let mut any = false;
1715 while let Some(d) = parse_digit(*p, base) {
1716 any = true;
1717 if val > (limit - d as u64) / base as u64 {
1718 while parse_digit(*p, base).is_some() { p = p.add(1); }
1719 if !endptr.is_null() { *endptr = p as *mut c_char; }
1720 ERRNO!() = ERANGE_VAL;
1721 return (limit, true, neg);
1722 }
1723 val = val * base as u64 + d as u64;
1724 p = p.add(1);
1725 }
1726
1727 if !endptr.is_null() {
1728 *endptr = if any { p as *mut c_char } else { s as *mut c_char };
1729 }
1730 (val, false, neg)
1731}
1732
1733#[no_mangle]
1734pub unsafe extern "C" fn strtol(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_long {
1735 let pos_limit = c_long::MAX as u64;
1736 let neg_limit = pos_limit.wrapping_add(1);
1737 let (val, overflow, neg) = strtox(s, endptr, base, pos_limit, neg_limit);
1738 if overflow {
1739 return if neg { c_long::MIN } else { c_long::MAX };
1740 }
1741 if neg { val.wrapping_neg() as c_long } else { val as c_long }
1742}
1743
1744#[no_mangle]
1745pub unsafe extern "C" fn strtoul(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_ulong {
1746 let limit = c_ulong::MAX as u64;
1747 let (val, overflow, neg) = strtox(s, endptr, base, limit, limit);
1748 if overflow {
1749 return c_ulong::MAX;
1750 }
1751 if neg { val.wrapping_neg() as c_ulong } else { val as c_ulong }
1752}
1753
1754#[no_mangle]
1755pub unsafe extern "C" fn strtoll(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_longlong {
1756 let pos_limit = c_longlong::MAX as u64;
1757 let neg_limit = pos_limit.wrapping_add(1);
1758 let (val, overflow, neg) = strtox(s, endptr, base, pos_limit, neg_limit);
1759 if overflow {
1760 return if neg { c_longlong::MIN } else { c_longlong::MAX };
1761 }
1762 if neg { val.wrapping_neg() as c_longlong } else { val as c_longlong }
1763}
1764
1765#[no_mangle]
1766pub unsafe extern "C" fn strtoull(s: *const c_char, endptr: *mut *mut c_char, base: c_int) -> c_ulonglong {
1767 let limit = c_ulonglong::MAX as u64;
1768 let (val, overflow, neg) = strtox(s, endptr, base, limit, limit);
1769 if overflow {
1770 return c_ulonglong::MAX;
1771 }
1772 if neg { val.wrapping_neg() as c_ulonglong } else { val as c_ulonglong }
1773}
1774
1775#[no_mangle]
1776pub unsafe extern "C" fn atoi(s: *const c_char) -> c_int {
1777 strtol(s, core::ptr::null_mut(), 10) as c_int
1778}
1779
1780#[no_mangle]
1781pub unsafe extern "C" fn atol(s: *const c_char) -> c_long {
1782 strtol(s, core::ptr::null_mut(), 10)
1783}
1784
1785#[no_mangle]
1786pub unsafe extern "C" fn atoll(s: *const c_char) -> c_longlong {
1787 strtoll(s, core::ptr::null_mut(), 10)
1788}
1789
1790#[no_mangle]
1791pub extern "C" fn abs(n: c_int) -> c_int {
1792 if n < 0 {
1793 -n
1794 } else {
1795 n
1796 }
1797}
1798
1799#[no_mangle]
1800pub extern "C" fn labs(n: c_long) -> c_long {
1801 if n < 0 {
1802 -n
1803 } else {
1804 n
1805 }
1806}
1807
1808#[no_mangle]
1809pub extern "C" fn llabs(n: c_longlong) -> c_longlong {
1810 if n < 0 {
1811 -n
1812 } else {
1813 n
1814 }
1815}
1816
1817static mut RAND_STATE: c_uint = 1;
1818
1819#[no_mangle]
1820pub extern "C" fn srand(seed: c_uint) {
1821 unsafe {
1822 RAND_STATE = seed;
1823 }
1824}
1825
1826#[no_mangle]
1827pub extern "C" fn rand() -> c_int {
1828 unsafe {
1829 RAND_STATE = RAND_STATE.wrapping_mul(1103515245).wrapping_add(12345);
1830 ((RAND_STATE >> 16) & 0x7fff) as c_int
1831 }
1832}
1833
1834#[repr(C)]
1839pub struct div_t { pub quot: c_int, pub rem: c_int }
1840#[repr(C)]
1841pub struct ldiv_t { pub quot: c_long, pub rem: c_long }
1842#[repr(C)]
1843pub struct lldiv_t { pub quot: c_longlong, pub rem: c_longlong }
1844
1845#[no_mangle]
1846pub extern "C" fn div(num: c_int, den: c_int) -> div_t {
1847 div_t { quot: num / den, rem: num % den }
1848}
1849
1850#[no_mangle]
1851pub extern "C" fn ldiv(num: c_long, den: c_long) -> ldiv_t {
1852 ldiv_t { quot: num / den, rem: num % den }
1853}
1854
1855#[no_mangle]
1856pub extern "C" fn lldiv(num: c_longlong, den: c_longlong) -> lldiv_t {
1857 lldiv_t { quot: num / den, rem: num % den }
1858}
1859
1860type CmpFn = unsafe extern "C" fn(*const c_void, *const c_void) -> c_int;
1865
1866#[no_mangle]
1867pub unsafe extern "C" fn bsearch(
1868 key: *const c_void,
1869 base: *const c_void,
1870 nel: usize,
1871 width: usize,
1872 cmp: CmpFn,
1873) -> *mut c_void {
1874 let mut base = base as *const u8;
1875 let mut nel = nel;
1876 while nel > 0 {
1877 let trial = base.add(width * (nel / 2));
1878 let sign = cmp(key, trial as *const c_void);
1879 if sign < 0 {
1880 nel /= 2;
1881 } else if sign > 0 {
1882 base = trial.add(width);
1883 nel -= nel / 2 + 1;
1884 } else {
1885 return trial as *mut c_void;
1886 }
1887 }
1888 null_mut()
1889}
1890
1891pub const SA_RESTORER: c_ulong = 0x04000000;
1896
1897pub const SIG_DFL: usize = 0;
1898pub const SIG_IGN: usize = 1;
1899pub const SIG_ERR: usize = !0usize;
1900
1901pub const SIGHUP: c_int = 1;
1902pub const SIGINT: c_int = 2;
1903pub const SIGQUIT: c_int = 3;
1904pub const SIGILL: c_int = 4;
1905pub const SIGTRAP: c_int = 5;
1906pub const SIGABRT: c_int = 6;
1907pub const SIGIOT: c_int = 6;
1908pub const SIGBUS: c_int = 7;
1909pub const SIGFPE: c_int = 8;
1910pub const SIGKILL: c_int = 9;
1911pub const SIGUSR1: c_int = 10;
1912pub const SIGSEGV: c_int = 11;
1913pub const SIGUSR2: c_int = 12;
1914pub const SIGPIPE: c_int = 13;
1915pub const SIGALRM: c_int = 14;
1916pub const SIGTERM: c_int = 15;
1917pub const SIGSTKFLT: c_int = 16;
1918pub const SIGCHLD: c_int = 17;
1919pub const SIGCONT: c_int = 18;
1920pub const SIGSTOP: c_int = 19;
1921pub const SIGTSTP: c_int = 20;
1922pub const SIGTTIN: c_int = 21;
1923pub const SIGTTOU: c_int = 22;
1924pub const SIGURG: c_int = 23;
1925pub const SIGXCPU: c_int = 24;
1926pub const SIGXFSZ: c_int = 25;
1927pub const SIGVTALRM: c_int = 26;
1928pub const SIGPROF: c_int = 27;
1929pub const SIGWINCH: c_int = 28;
1930pub const SIGIO: c_int = 29;
1931pub const SIGPOLL: c_int = 29;
1932pub const SIGPWR: c_int = 30;
1933pub const SIGSYS: c_int = 31;
1934pub const SIGUNUSED: c_int = 31;
1935pub const _NSIG: c_int = 65;
1936
1937pub const SIG_BLOCK: c_int = 0;
1938pub const SIG_UNBLOCK: c_int = 1;
1939pub const SIG_SETMASK: c_int = 2;
1940
1941pub const SA_NOCLDSTOP: c_ulong = 1;
1942pub const SA_NOCLDWAIT: c_ulong = 2;
1943pub const SA_SIGINFO: c_ulong = 4;
1944pub const SA_ONSTACK: c_ulong = 0x08000000;
1945pub const SA_RESTART: c_ulong = 0x10000000;
1946pub const SA_NODEFER: c_ulong = 0x40000000;
1947pub const SA_RESETHAND: c_ulong = 0x80000000;
1948
1949pub const SS_ONSTACK: c_int = 1;
1950pub const SS_DISABLE: c_int = 2;
1951pub const MINSIGSTKSZ: usize = 2048;
1952pub const SIGSTKSZ: usize = 8192;
1953
1954pub const SI_USER: c_int = 0;
1955pub const SI_TKILL: c_int = -6;
1956
1957#[repr(C)]
1958pub struct timespec {
1959 pub tv_sec: c_long,
1960 pub tv_nsec: c_long,
1961}
1962
1963#[repr(C)]
1964pub struct siginfo_t {
1965 pub si_signo: c_int,
1966 pub si_errno: c_int,
1967 pub si_code: c_int,
1968 _pad: [u8; 128 - 3 * core::mem::size_of::<c_int>()],
1970}
1971
1972#[repr(C)]
1973pub struct stack_t {
1974 pub ss_sp: *mut c_void,
1975 pub ss_flags: c_int,
1976 pub ss_size: usize,
1977}
1978
1979#[repr(C)]
1982pub struct KSigAction {
1983 pub sa_handler: usize,
1984 pub sa_flags: c_ulong,
1985 pub sa_restorer: usize,
1986 pub sa_mask: [c_ulong; 1],
1987}
1988
1989#[repr(C)]
1991pub struct sigaction {
1992 pub sa_handler: usize,
1993 pub sa_mask: [u64; 16],
1994 pub sa_flags: c_int,
1995 pub sa_restorer: usize,
1996}
1997
1998pub type SigSetT = c_ulong;
1999
2000#[cfg(target_arch = "x86_64")]
2001core::arch::global_asm!(
2002 ".global sig_restorer",
2003 ".type sig_restorer, @function",
2004 "sig_restorer:",
2005 "mov eax, 15",
2006 "syscall",
2007);
2008
2009#[cfg(target_arch = "aarch64")]
2010core::arch::global_asm!(
2011 ".global sig_restorer",
2012 ".type sig_restorer, @function",
2013 "sig_restorer:",
2014 "mov x8, #139",
2015 "svc #0",
2016);
2017
2018#[cfg(target_arch = "riscv64")]
2019core::arch::global_asm!(
2020 ".global sig_restorer",
2021 ".type sig_restorer, @function",
2022 "sig_restorer:",
2023 "li a7, 139",
2024 "ecall",
2025);
2026
2027extern "C" {
2028 fn sig_restorer();
2029}
2030
2031#[inline]
2032unsafe fn sys_rt_sigaction(sig: c_int,
2033 act: *const KSigAction,
2034 oldact: *mut KSigAction,
2035 sigsetsize: usize,) -> i64 {
2036 <Arch as Syscalls>::syscall4(SYS_RT_SIGACTION, sig as i64, act as i64, oldact as i64, sigsetsize as i64)
2037}
2038
2039#[inline]
2040unsafe fn sys_rt_sigprocmask(how: c_int,
2041 set: *const SigSetT,
2042 oldset: *mut SigSetT,
2043 sigsetsize: usize,) -> i64 {
2044 <Arch as Syscalls>::syscall4(SYS_RT_SIGPROCMASK, how as i64, set as i64, oldset as i64, sigsetsize as i64)
2045}
2046
2047#[inline]
2048unsafe fn sys_rt_sigpending(set: *mut SigSetT, sigsetsize: usize) -> i64 {
2049 <Arch as Syscalls>::syscall2(SYS_RT_SIGPENDING, set as i64, sigsetsize as i64)
2050}
2051
2052#[inline]
2053unsafe fn sys_rt_sigsuspend(mask: *const SigSetT, sigsetsize: usize) -> i64 {
2054 <Arch as Syscalls>::syscall2(SYS_RT_SIGSUSPEND, mask as i64, sigsetsize as i64)
2055}
2056
2057#[inline]
2058unsafe fn sys_rt_sigtimedwait(set: *const SigSetT,
2059 info: *mut siginfo_t,
2060 timeout: *const timespec,
2061 sigsetsize: usize,) -> i64 {
2062 <Arch as Syscalls>::syscall4(SYS_RT_SIGTIMEDWAIT, set as i64, info as i64, timeout as i64, sigsetsize as i64)
2063}
2064
2065#[inline]
2066unsafe fn sys_sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> i64 {
2067 <Arch as Syscalls>::syscall2(SYS_SIGALTSTACK, ss as i64, old_ss as i64)
2068}
2069
2070#[inline]
2071unsafe fn sys_tgkill(tgid: c_int, tid: c_int, sig: c_int) -> i64 {
2072 <Arch as Syscalls>::syscall3(SYS_TGKILL, tgid as i64, tid as i64, sig as i64)
2073}
2074
2075const CLOCK_REALTIME: c_int = 0;
2076const CLOCK_MONOTONIC: c_int = 1;
2077
2078#[inline]
2079unsafe fn sys_clock_gettime(clockid: c_int, ts: *mut timespec) -> i64 {
2080 <Arch as Syscalls>::syscall2(SYS_CLOCK_GETTIME, clockid as i64, ts as i64)
2081}
2082
2083#[no_mangle]
2087pub unsafe extern "C" fn sigprocmask(
2088 how: c_int,
2089 set: *const SigSetT,
2090 oldset: *mut SigSetT,
2091) -> c_int {
2092 let internal_mask: SigSetT = (1u64 << 31) | (1u64 << 32);
2094 let filtered: SigSetT;
2095 let set_ptr: *const SigSetT = if set.is_null() {
2096 set
2097 } else {
2098 filtered = *set & !internal_mask;
2099 &filtered
2100 };
2101 let r = sys_rt_sigprocmask(how, set_ptr, oldset, core::mem::size_of::<SigSetT>());
2102 if !oldset.is_null() {
2103 *oldset &= !internal_mask;
2104 }
2105 if r < 0 { -1 } else { 0 }
2106}
2107
2108#[inline]
2109unsafe fn sys_kill(pid: c_int, sig: c_int) -> i64 {
2110 <Arch as Syscalls>::syscall2(SYS_KILL, pid as i64, sig as i64)
2111}
2112
2113#[inline]
2114unsafe fn sys_getpid() -> i64 {
2115 <Arch as Syscalls>::syscall0(SYS_GETPID)
2116}
2117
2118#[no_mangle]
2119pub unsafe extern "C" fn sigaction(
2120 signum: c_int,
2121 act: *const sigaction,
2122 oldact: *mut sigaction,
2123) -> c_int {
2124 let mut kact: KSigAction = core::mem::zeroed();
2125 let act_ptr = if act.is_null() {
2126 core::ptr::null()
2127 } else {
2128 kact.sa_handler = (*act).sa_handler;
2129 kact.sa_flags = ((*act).sa_flags as c_ulong) | SA_RESTORER;
2130 kact.sa_restorer = if (*act).sa_flags as c_ulong & SA_RESTORER != 0
2131 && (*act).sa_restorer != 0
2132 {
2133 (*act).sa_restorer
2134 } else {
2135 sig_restorer as *const () as usize
2136 };
2137 kact.sa_mask[0] = (*act).sa_mask[0];
2138 &kact
2139 };
2140 let mut kold: KSigAction = core::mem::zeroed();
2141 let old_ptr = if oldact.is_null() { core::ptr::null_mut() } else { &mut kold };
2142 let r = sys_rt_sigaction(signum, act_ptr, old_ptr, 8);
2143 if r < 0 {
2144 ERRNO!() = (-r) as c_int;
2145 return -1;
2146 }
2147 if !oldact.is_null() {
2148 (*oldact).sa_handler = kold.sa_handler;
2149 (*oldact).sa_flags = kold.sa_flags as c_int;
2150 (*oldact).sa_restorer = kold.sa_restorer;
2151 (*oldact).sa_mask = [0; 16];
2152 (*oldact).sa_mask[0] = kold.sa_mask[0];
2153 }
2154 0
2155}
2156
2157#[no_mangle]
2158pub unsafe extern "C" fn signal(signum: c_int, handler: usize) -> usize {
2159 let act = sigaction {
2162 sa_handler: handler,
2163 sa_mask: [0; 16],
2164 sa_flags: SA_RESTART as c_int,
2165 sa_restorer: 0,
2166 };
2167 let mut old: sigaction = core::mem::zeroed();
2168 if sigaction(signum, &act, &mut old) == -1 {
2169 SIG_ERR
2170 } else {
2171 old.sa_handler
2172 }
2173}
2174
2175#[no_mangle]
2176pub unsafe extern "C" fn kill(pid: c_int, sig: c_int) -> c_int {
2177 let r = sys_kill(pid, sig);
2178 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2179 0
2180}
2181
2182#[no_mangle]
2183pub unsafe extern "C" fn tgkill(tgid: c_int, tid: c_int, sig: c_int) -> c_int {
2184 let r = sys_tgkill(tgid, tid, sig);
2185 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2186 0
2187}
2188
2189#[no_mangle]
2190pub unsafe extern "C" fn getpid() -> c_int {
2191 sys_getpid() as c_int
2192}
2193
2194#[no_mangle]
2195pub unsafe extern "C" fn raise(sig: c_int) -> c_int {
2196 let r = sys_tgkill(sys_getpid() as c_int, sys_gettid() as c_int, sig);
2197 if r < 0 {
2198 ERRNO!() = (-r) as c_int;
2199 -1
2200 } else {
2201 0
2202 }
2203}
2204
2205#[no_mangle]
2206pub unsafe extern "C" fn sigemptyset(set: *mut SigSetT) -> c_int {
2207 *set = 0;
2208 0
2209}
2210
2211#[no_mangle]
2212pub unsafe extern "C" fn sigfillset(set: *mut SigSetT) -> c_int {
2213 *set = 0xFFFF_FFFC_7FFF_FFFFu64;
2215 0
2216}
2217
2218#[no_mangle]
2219pub unsafe extern "C" fn sigaddset(set: *mut SigSetT, signum: c_int) -> c_int {
2220 let s = (signum as c_uint).wrapping_sub(1);
2221 if s as usize >= 64 {
2222 ERRNO!() = EINVAL;
2223 return -1;
2224 }
2225 if signum >= 32 && signum < __libc_current_sigrtmin() {
2227 return 0;
2228 }
2229 *set |= 1u64 << s;
2230 0
2231}
2232
2233#[no_mangle]
2234pub unsafe extern "C" fn sigdelset(set: *mut SigSetT, signum: c_int) -> c_int {
2235 let s = (signum as c_uint).wrapping_sub(1);
2236 if s as usize >= 64 {
2237 ERRNO!() = EINVAL;
2238 return -1;
2239 }
2240 if signum >= 32 && signum < __libc_current_sigrtmin() {
2242 return 0;
2243 }
2244 *set &= !(1u64 << s);
2245 0
2246}
2247
2248#[no_mangle]
2249pub unsafe extern "C" fn sigismember(set: *const SigSetT, signum: c_int) -> c_int {
2250 let s = (signum as c_uint).wrapping_sub(1);
2251 if s as usize >= 64 { return 0; }
2252 if signum >= 32 && signum < __libc_current_sigrtmin() {
2254 return 0;
2255 }
2256 ((*set & (1u64 << s)) != 0) as c_int
2257}
2258
2259#[no_mangle]
2260pub unsafe extern "C" fn sigpending(set: *mut SigSetT) -> c_int {
2261 let r = sys_rt_sigpending(set, core::mem::size_of::<SigSetT>());
2262 if r < 0 {
2263 ERRNO!() = (-r) as c_int;
2264 return -1;
2265 }
2266 0
2267}
2268
2269#[no_mangle]
2270pub unsafe extern "C" fn sigsuspend(mask: *const SigSetT) -> c_int {
2271 let r = sys_rt_sigsuspend(mask, core::mem::size_of::<SigSetT>());
2272 if r < 0 {
2273 ERRNO!() = (-r) as c_int;
2274 }
2275 -1
2276}
2277
2278#[no_mangle]
2279pub unsafe extern "C" fn sigtimedwait(
2280 mask: *const SigSetT,
2281 info: *mut siginfo_t,
2282 timeout: *const timespec,
2283) -> c_int {
2284 loop {
2285 let r = sys_rt_sigtimedwait(mask, info, timeout, core::mem::size_of::<SigSetT>());
2286 if r >= 0 {
2287 return r as c_int;
2288 }
2289 let e = (-r) as c_int;
2290 if e != EINTR {
2291 ERRNO!() = e;
2292 return -1;
2293 }
2294 }
2295}
2296
2297#[no_mangle]
2298pub unsafe extern "C" fn sigwaitinfo(
2299 mask: *const SigSetT,
2300 info: *mut siginfo_t,
2301) -> c_int {
2302 sigtimedwait(mask, info, core::ptr::null())
2303}
2304
2305#[no_mangle]
2306pub unsafe extern "C" fn sigwait(
2307 mask: *const SigSetT,
2308 sig: *mut c_int,
2309) -> c_int {
2310 let mut info: siginfo_t = core::mem::zeroed();
2311 if sigtimedwait(mask, &mut info, core::ptr::null()) < 0 {
2312 return ERRNO!();
2313 }
2314 *sig = info.si_signo;
2315 0
2316}
2317
2318#[no_mangle]
2319pub unsafe extern "C" fn sigaltstack(ss: *const stack_t, old_ss: *mut stack_t) -> c_int {
2320 if !ss.is_null() {
2321 if (*ss).ss_flags & SS_ONSTACK != 0 {
2322 ERRNO!() = EINVAL;
2323 return -1;
2324 }
2325 if (*ss).ss_flags & SS_DISABLE == 0 && (*ss).ss_size < MINSIGSTKSZ {
2326 ERRNO!() = ENOMEM;
2327 return -1;
2328 }
2329 }
2330 let r = sys_sigaltstack(ss, old_ss);
2331 if r < 0 {
2332 ERRNO!() = (-r) as c_int;
2333 return -1;
2334 }
2335 0
2336}
2337
2338#[no_mangle]
2344#[inline(never)]
2345#[cfg(target_arch = "x86_64")]
2346pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2347 core::arch::asm!(
2348 "mov rax, [rsp]",
2349 "lea rcx, [rsp + 8]",
2350 "mov [r8], rbx",
2351 "mov [r8 + 8], rbp",
2352 "mov [r8 + 16], r12",
2353 "mov [r8 + 24], r13",
2354 "mov [r8 + 32], r14",
2355 "mov [r8 + 40], r15",
2356 "mov [r8 + 48], rcx",
2357 "mov [r8 + 56], rax",
2358 in("r8") env,
2359 lateout("rax") _,
2360 lateout("rcx") _,
2361 options(nostack),
2362 );
2363 0
2364}
2365
2366#[no_mangle]
2367#[inline(never)]
2368#[cfg(target_arch = "x86_64")]
2369pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2370 let ret = if val == 0 { 1 } else { val } as u32;
2371 core::arch::asm!(
2372 "mov rbx, [r8]",
2373 "mov rbp, [r8 + 8]",
2374 "mov r12, [r8 + 16]",
2375 "mov r13, [r8 + 24]",
2376 "mov r14, [r8 + 32]",
2377 "mov r15, [r8 + 40]",
2378 "mov rsp, [r8 + 48]",
2379 "mov eax, edx",
2380 "jmp [r8 + 56]",
2381 in("r8") env,
2382 in("edx") ret,
2383 options(noreturn),
2384 );
2385}
2386
2387#[no_mangle]
2388#[unsafe(naked)]
2389#[cfg(target_arch = "aarch64")]
2390pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2391 core::arch::naked_asm!(
2392 "stp x19, x20, [x0, #0]",
2393 "stp x21, x22, [x0, #16]",
2394 "stp x23, x24, [x0, #32]",
2395 "stp x25, x26, [x0, #48]",
2396 "stp x27, x28, [x0, #64]",
2397 "stp x29, x30, [x0, #80]",
2398 "mov x2, sp",
2399 "str x2, [x0, #104]",
2400 "stp d8, d9, [x0, #112]",
2401 "stp d10, d11, [x0, #128]",
2402 "stp d12, d13, [x0, #144]",
2403 "stp d14, d15, [x0, #160]",
2404 "mov x0, #0",
2405 "ret",
2406 );
2407}
2408
2409#[no_mangle]
2410#[inline(never)]
2411#[cfg(target_arch = "aarch64")]
2412pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2413 let ret = if val == 0 { 1 } else { val } as u64;
2414 core::arch::asm!(
2415 "ldp x19, x20, [x0]",
2416 "ldp x21, x22, [x0, #16]",
2417 "ldp x23, x24, [x0, #32]",
2418 "ldp x25, x26, [x0, #48]",
2419 "ldp x27, x28, [x0, #64]",
2420 "ldp x29, x30, [x0, #80]",
2421 "ldr x2, [x0, #104]",
2422 "mov sp, x2",
2423 "ldp d8, d9, [x0, #112]",
2424 "ldp d10, d11, [x0, #128]",
2425 "ldp d12, d13, [x0, #144]",
2426 "ldp d14, d15, [x0, #160]",
2427 "mov x0, x1",
2428 "br x30",
2429 in("x0") env,
2430 in("x1") ret,
2431 options(noreturn),
2432 );
2433}
2434
2435#[no_mangle]
2436#[unsafe(naked)]
2437#[cfg(target_arch = "riscv64")]
2438pub unsafe extern "C" fn setjmp(env: *mut c_ulong) -> c_int {
2439 core::arch::naked_asm!(
2440 "sd s0, 0(a0)",
2441 "sd s1, 8(a0)",
2442 "sd s2, 16(a0)",
2443 "sd s3, 24(a0)",
2444 "sd s4, 32(a0)",
2445 "sd s5, 40(a0)",
2446 "sd s6, 48(a0)",
2447 "sd s7, 56(a0)",
2448 "sd s8, 64(a0)",
2449 "sd s9, 72(a0)",
2450 "sd s10, 80(a0)",
2451 "sd s11, 88(a0)",
2452 "sd sp, 96(a0)",
2453 "sd ra, 104(a0)",
2454 "li a0, 0",
2455 "ret",
2456 );
2457}
2458
2459#[no_mangle]
2460#[inline(never)]
2461#[cfg(target_arch = "riscv64")]
2462pub unsafe extern "C" fn longjmp(env: *const c_ulong, val: c_int) -> ! {
2463 let ret = if val == 0 { 1 } else { val } as u64;
2464 core::arch::asm!(
2465 "ld s0, 0(a0)",
2466 "ld s1, 8(a0)",
2467 "ld s2, 16(a0)",
2468 "ld s3, 24(a0)",
2469 "ld s4, 32(a0)",
2470 "ld s5, 40(a0)",
2471 "ld s6, 48(a0)",
2472 "ld s7, 56(a0)",
2473 "ld s8, 64(a0)",
2474 "ld s9, 72(a0)",
2475 "ld s10, 80(a0)",
2476 "ld s11, 88(a0)",
2477 "ld sp, 96(a0)",
2478 "ld ra, 104(a0)",
2479 "mv a0, a1",
2480 "ret",
2481 in("a0") env,
2482 in("a1") ret,
2483 options(noreturn),
2484 );
2485}
2486
2487#[no_mangle]
2495#[unsafe(naked)]
2496#[cfg(target_arch = "x86_64")]
2497pub unsafe extern "C" fn sigsetjmp(_env: *mut c_ulong, _savemask: c_int) -> c_int {
2498 core::arch::naked_asm!("jmp sigsetjmp_real");
2499}
2500
2501#[no_mangle]
2502#[unsafe(naked)]
2503#[cfg(target_arch = "x86_64")]
2504pub unsafe extern "C" fn __sigsetjmp(_env: *mut c_ulong, _savemask: c_int) -> c_int {
2505 core::arch::naked_asm!("jmp sigsetjmp_real");
2506}
2507
2508#[cfg(target_arch = "x86_64")]
2509core::arch::global_asm!(
2510 ".type sigsetjmp_real, @function",
2511 "sigsetjmp_real:",
2512 " test esi, esi",
2513 " jz 1f",
2514 " pop qword ptr [rdi + 64]",
2515 " mov qword ptr [rdi + 80], rbx",
2516 " mov rbx, rdi",
2520 " call setjmp",
2521 " push qword ptr [rbx + 64]",
2522 " mov rdi, rbx",
2523 " mov esi, eax",
2524 " mov rbx, qword ptr [rbx + 80]",
2525 " lea rdx, [rdi + 72]",
2526 " test esi, esi",
2527 " jz 2f",
2528 " mov rsi, rdx",
2529 " xor rdx, rdx",
2530 " mov edi, 2",
2531 " jmp 3f",
2532 "2:",
2533 " xor rsi, rsi",
2534 " mov edi, 2",
2535 "3:",
2536 " mov eax, 14",
2537 " mov r10d, 8",
2538 " syscall",
2539 " test esi, esi",
2540 " jnz 4f",
2541 " mov rax, 0xfffffffe7fffffff",
2542 " and qword ptr [rdx], rax",
2543 "4:",
2544 " mov eax, esi",
2545 " ret",
2546 "1:",
2547 " jmp setjmp",
2548);
2549
2550#[no_mangle]
2551#[inline(never)]
2552#[cfg(target_arch = "x86_64")]
2553pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2554 longjmp(env, val);
2555}
2556
2557#[no_mangle]
2558#[cfg(target_arch = "aarch64")]
2559pub unsafe extern "C" fn __sigsetjmp_tail(env: *mut c_ulong, ret: c_int) -> c_int {
2560 const SIG_SETMASK: c_int = 2;
2561 let ss = env.add(23) as *mut SigSetT;
2562 let set = if ret != 0 { ss as *const SigSetT } else { core::ptr::null() };
2563 let old = if ret != 0 { core::ptr::null_mut() } else { ss };
2564 let _ = sys_rt_sigprocmask(SIG_SETMASK, set, old, core::mem::size_of::<SigSetT>());
2565 ret
2566}
2567
2568#[no_mangle]
2569#[unsafe(naked)]
2570#[cfg(target_arch = "aarch64")]
2571pub unsafe extern "C" fn sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2572 core::arch::naked_asm!(
2573 "cbz w1, setjmp",
2574 "str x30, [x0, #176]",
2575 "str x19, [x0, #192]",
2576 "mov x19, x0",
2577 "bl setjmp",
2578 "mov w1, w0",
2579 "mov x0, x19",
2580 "ldr x30, [x0, #176]",
2581 "ldr x19, [x0, #192]",
2582 "b __sigsetjmp_tail",
2583 );
2584}
2585
2586#[no_mangle]
2587#[unsafe(naked)]
2588#[cfg(target_arch = "aarch64")]
2589pub unsafe extern "C" fn __sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2590 core::arch::naked_asm!(
2591 "cbz w1, setjmp",
2592 "str x30, [x0, #176]",
2593 "str x19, [x0, #192]",
2594 "mov x19, x0",
2595 "bl setjmp",
2596 "mov w1, w0",
2597 "mov x0, x19",
2598 "ldr x30, [x0, #176]",
2599 "ldr x19, [x0, #192]",
2600 "b __sigsetjmp_tail",
2601 );
2602}
2603
2604#[no_mangle]
2605#[inline(never)]
2606#[cfg(target_arch = "aarch64")]
2607pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2608 longjmp(env, val);
2609}
2610
2611#[no_mangle]
2612#[cfg(target_arch = "riscv64")]
2613pub unsafe extern "C" fn __sigsetjmp_tail(env: *mut c_ulong, ret: c_int) -> c_int {
2614 const SIG_SETMASK: c_int = 2;
2615 let ss = env.add(27) as *mut SigSetT;
2616 let set = if ret != 0 { ss as *const SigSetT } else { core::ptr::null() };
2617 let old = if ret != 0 { core::ptr::null_mut() } else { ss };
2618 let _ = sys_rt_sigprocmask(SIG_SETMASK, set, old, core::mem::size_of::<SigSetT>());
2619 ret
2620}
2621
2622#[no_mangle]
2623#[unsafe(naked)]
2624#[cfg(target_arch = "riscv64")]
2625pub unsafe extern "C" fn sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2626 core::arch::naked_asm!(
2627 "bnez a1, 1f",
2628 "tail setjmp",
2629 "1:",
2630 "sd ra, 208(a0)",
2631 "sd s0, 224(a0)",
2632 "mv s0, a0",
2633 "call setjmp",
2634 "mv a1, a0",
2635 "mv a0, s0",
2636 "ld s0, 224(a0)",
2637 "ld ra, 208(a0)",
2638 "tail __sigsetjmp_tail",
2639 );
2640}
2641
2642#[no_mangle]
2643#[unsafe(naked)]
2644#[cfg(target_arch = "riscv64")]
2645pub unsafe extern "C" fn __sigsetjmp(env: *mut c_ulong, savemask: c_int) -> c_int {
2646 core::arch::naked_asm!(
2647 "bnez a1, 1f",
2648 "tail setjmp",
2649 "1:",
2650 "sd ra, 208(a0)",
2651 "sd s0, 224(a0)",
2652 "mv s0, a0",
2653 "call setjmp",
2654 "mv a1, a0",
2655 "mv a0, s0",
2656 "ld s0, 224(a0)",
2657 "ld ra, 208(a0)",
2658 "tail __sigsetjmp_tail",
2659 );
2660}
2661
2662#[no_mangle]
2663#[inline(never)]
2664#[cfg(target_arch = "riscv64")]
2665pub unsafe extern "C" fn siglongjmp(env: *const c_ulong, val: c_int) -> ! {
2666 longjmp(env, val);
2667}
2668
2669#[inline]
2674unsafe fn sys_newfstatat(dirfd: i32, path: *const c_char, buf: *mut u8, flags: i32) -> i64 {
2675 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, dirfd as i64, path as i64, buf as i64, flags as i64)
2676}
2677
2678#[inline]
2679unsafe fn sys_fstat(fd: i32, buf: *mut u8) -> i64 {
2680 <Arch as Syscalls>::syscall2(SYS_FSTAT, fd as i64, buf as i64)
2681}
2682
2683#[inline]
2684unsafe fn sys_getrlimit(resource: i32, rlim: *mut u8) -> i64 {
2685 <Arch as Syscalls>::syscall2(SYS_GETRLIMIT, resource as i64, rlim as i64)
2686}
2687
2688#[inline]
2689unsafe fn sys_setrlimit(resource: i32, rlim: *const u8) -> i64 {
2690 <Arch as Syscalls>::syscall2(SYS_SETRLIMIT, resource as i64, rlim as i64)
2691}
2692
2693#[inline]
2694unsafe fn sys_utimensat(dirfd: i32, path: *const c_char, times: *const u8, flags: i32) -> i64 {
2695 <Arch as Syscalls>::syscall4(SYS_UTIMENSAT, dirfd as i64, path as i64, times as i64, flags as i64)
2696}
2697
2698#[inline]
2703unsafe fn sys_fork() -> i64 {
2704 #[cfg(target_arch = "x86_64")]
2705 { <Arch as Syscalls>::syscall0(SYS_FORK) }
2706 #[cfg(target_arch = "aarch64")]
2707 { <Arch as Syscalls>::syscall2(SYS_CLONE, 17, 0) }
2708 #[cfg(target_arch = "riscv64")]
2709 { <Arch as Syscalls>::syscall2(SYS_CLONE, 17, 0) }
2710}
2711
2712#[inline]
2713unsafe fn sys_execve(path: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> i64 {
2714 <Arch as Syscalls>::syscall3(SYS_EXECVE, path as i64, argv as i64, envp as i64)
2715}
2716
2717#[inline]
2718unsafe fn sys_wait4(pid: c_int, status: *mut c_int, options: c_int, rusage: *mut c_void) -> i64 {
2719 <Arch as Syscalls>::syscall4(SYS_WAIT4, pid as i64, status as i64, options as i64, rusage as i64)
2720}
2721
2722#[inline]
2723unsafe fn sys_getppid() -> i64 {
2724 <Arch as Syscalls>::syscall0(SYS_GETPPID)
2725}
2726
2727#[inline]
2728unsafe fn sys_getuid() -> i64 {
2729 <Arch as Syscalls>::syscall0(SYS_GETUID)
2730}
2731
2732#[inline]
2733unsafe fn sys_getgid() -> i64 {
2734 <Arch as Syscalls>::syscall0(SYS_GETGID)
2735}
2736
2737#[inline]
2738unsafe fn sys_geteuid() -> i64 {
2739 <Arch as Syscalls>::syscall0(SYS_GETEUID)
2740}
2741
2742#[inline]
2743unsafe fn sys_getegid() -> i64 {
2744 <Arch as Syscalls>::syscall0(SYS_GETEGID)
2745}
2746
2747#[no_mangle]
2748pub unsafe extern "C" fn fork() -> c_int {
2749 __fork_handler(-1);
2750 let ret = sys_fork();
2751 if ret < 0 {
2756 let err = (-ret) as c_int;
2757 __fork_handler(0);
2758 ERRNO!() = err;
2759 return -1;
2760 }
2761 if ret == 0 {
2762 allocator_after_fork();
2763 __fork_handler(1);
2764 } else {
2765 __fork_handler(0);
2766 }
2767 ret as c_int
2768}
2769
2770#[no_mangle]
2771pub unsafe extern "C" fn execve(
2772 path: *const c_char,
2773 argv: *const *const c_char,
2774 envp: *const *const c_char,
2775) -> c_int {
2776 let r = sys_execve(path, argv, envp);
2777 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2778 r as c_int
2779}
2780
2781#[no_mangle]
2782pub unsafe extern "C" fn wait(status: *mut c_int) -> c_int {
2783 let r = sys_wait4(-1, status, 0, core::ptr::null_mut());
2784 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2785 r as c_int
2786}
2787
2788#[no_mangle]
2789pub unsafe extern "C" fn waitpid(pid: c_int, status: *mut c_int, options: c_int) -> c_int {
2790 let r = sys_wait4(pid, status, options, core::ptr::null_mut());
2791 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2792 r as c_int
2793}
2794
2795#[no_mangle]
2796pub unsafe extern "C" fn getppid() -> c_int {
2797 sys_getppid() as c_int
2798}
2799
2800#[no_mangle]
2801pub unsafe extern "C" fn getuid() -> c_uint {
2802 sys_getuid() as c_uint
2803}
2804
2805#[no_mangle]
2806pub unsafe extern "C" fn getgid() -> c_uint {
2807 sys_getgid() as c_uint
2808}
2809
2810#[no_mangle]
2811pub unsafe extern "C" fn geteuid() -> c_uint {
2812 sys_geteuid() as c_uint
2813}
2814
2815#[no_mangle]
2816pub unsafe extern "C" fn getegid() -> c_uint {
2817 sys_getegid() as c_uint
2818}
2819
2820#[no_mangle]
2822pub unsafe extern "C" fn vfork() -> c_int {
2823 let r = sys_fork();
2824 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2825 r as c_int
2826}
2827
2828#[no_mangle]
2829pub unsafe extern "C" fn execl(path: *const c_char, arg: *const c_char, mut args: ...) -> c_int {
2830 let mut argv: [*const c_char; 256] = [core::ptr::null(); 256];
2831 argv[0] = arg;
2832 let mut n: usize = 1;
2833 loop {
2834 let a: *const c_char = args.next_arg();
2835 if a.is_null() { break; }
2836 if n >= 255 { return -1; }
2837 argv[n] = a;
2838 n += 1;
2839 }
2840 argv[n] = core::ptr::null();
2841 sys_execve(path, argv.as_ptr(), __environ as *const *const c_char) as c_int
2842}
2843
2844unsafe fn spawn_execvp(file: *const c_char, argv: *const *const c_char, envp: *const *const c_char) -> ! {
2853 let flen = strlen(file as *const c_char);
2854 let f = file as *const u8;
2855 let mut has_slash = false;
2856 for i in 0..flen {
2857 if *f.add(i) == b'/' { has_slash = true; break; }
2858 }
2859 if has_slash {
2860 sys_execve(file, argv, envp);
2861 _exit(127);
2862 }
2863 let path = getenv(b"PATH\0".as_ptr() as *const c_char);
2864 let default_path = b"/usr/local/bin:/usr/bin:/bin\0";
2865 let p = if path.is_null() { default_path.as_ptr() } else { path as *const u8 };
2866 let plen = strlen(p as *const c_char);
2867 let mut buf: [u8; 4096] = [0; 4096];
2868 let mut i: usize = 0;
2869 while i <= plen {
2870 let start = i;
2871 while i < plen && *p.add(i) != b':' { i += 1; }
2872 let dlen = i - start;
2873 if dlen > 0 && dlen + 1 + flen < 4096 {
2874 core::ptr::copy_nonoverlapping(p.add(start), buf.as_mut_ptr(), dlen);
2875 *buf.as_mut_ptr().add(dlen) = b'/';
2876 core::ptr::copy_nonoverlapping(f, buf.as_mut_ptr().add(dlen + 1), flen + 1);
2877 sys_execve(buf.as_ptr() as *const c_char, argv, envp);
2878 }
2880 i += 1; }
2882 _exit(127);
2883}
2884
2885#[no_mangle]
2886pub unsafe extern "C" fn posix_spawnp(
2887 pid: *mut c_int,
2888 file: *const c_char,
2889 fa: *const posix_spawn_file_actions_t,
2890 attrp: *const posix_spawnattr_t,
2891 argv: *const *const c_char,
2892 envp: *const *const c_char,
2893) -> c_int {
2894 let child = sys_fork();
2895 if child < 0 {
2896 ERRNO!() = EAGAIN;
2897 return -1;
2898 }
2899 if child == 0 {
2900 spawn_apply_attr(attrp);
2902 spawn_apply_actions(fa);
2903 let actual_envp = if envp.is_null() { __environ as *const *const c_char } else { envp };
2904 spawn_execvp(file, argv, actual_envp);
2905 }
2907 *pid = child as c_int;
2908 0
2909}
2910
2911#[no_mangle]
2912pub unsafe extern "C" fn posix_spawn(
2913 pid: *mut c_int,
2914 path: *const c_char,
2915 fa: *const posix_spawn_file_actions_t,
2916 attrp: *const posix_spawnattr_t,
2917 argv: *const *const c_char,
2918 envp: *const *const c_char,
2919) -> c_int {
2920 posix_spawnp(pid, path, fa, attrp, argv, envp)
2923}
2924
2925#[cfg(target_arch = "x86_64")]
2930#[repr(C)]
2931pub struct Stat {
2932 pub st_dev: u64,
2933 pub st_ino: u64,
2934 pub st_nlink: u64,
2935 pub st_mode: u32,
2936 pub st_uid: u32,
2937 pub st_gid: u32,
2938 _pad0: u32,
2939 pub st_rdev: u64,
2940 pub st_size: i64,
2941 pub st_blksize: i64,
2942 pub st_blocks: i64,
2943 pub st_atim: timespec,
2944 pub st_mtim: timespec,
2945 pub st_ctim: timespec,
2946 _unused: [i64; 3],
2947}
2948
2949#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
2950#[repr(C)]
2951pub struct Stat {
2952 pub st_dev: u64,
2953 pub st_ino: u64,
2954 pub st_mode: u32,
2955 pub st_nlink: u32,
2956 pub st_uid: u32,
2957 pub st_gid: u32,
2958 pub st_rdev: u64,
2959 __pad1: u64,
2960 pub st_size: i64,
2961 pub st_blksize: i32,
2962 __pad2: i32,
2963 pub st_blocks: i64,
2964 pub st_atim: timespec,
2965 pub st_mtim: timespec,
2966 pub st_ctim: timespec,
2967 __unused4: u32,
2968 __unused5: u32,
2969}
2970
2971pub const S_IFMT: u32 = 0o170000;
2972pub const S_IFDIR: u32 = 0o040000;
2973pub const S_IFCHR: u32 = 0o020000;
2974pub const S_IFBLK: u32 = 0o060000;
2975pub const S_IFREG: u32 = 0o100000;
2976pub const S_IFLNK: u32 = 0o120000;
2977pub const S_IFIFO: u32 = 0o010000;
2978pub const S_IFSOCK: u32 = 0o140000;
2979
2980pub const AT_FDCWD: i32 = -100;
2981
2982#[no_mangle]
2983pub unsafe extern "C" fn stat(path: *const c_char, buf: *mut Stat) -> c_int {
2984 let r = sys_newfstatat(AT_FDCWD, path, buf as *mut u8, 0);
2985 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
2986 if *path == b'/' as c_char && strcmp(path as *const u8, b"/dev/null\0".as_ptr()) == 0 {
2987 (*buf).st_mode = ((*buf).st_mode & !0o170000) | 0o020000;
2988 }
2989 0
2990}
2991
2992#[no_mangle]
2993pub unsafe extern "C" fn fstat(fd: c_int, buf: *mut Stat) -> c_int {
2994 let r = sys_fstat(fd, buf as *mut u8);
2995 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
2996}
2997
2998#[repr(C)]
3003pub struct Rlimit {
3004 pub rlim_cur: u64,
3005 pub rlim_max: u64,
3006}
3007
3008pub const RLIMIT_NOFILE: c_int = 7;
3009pub const RLIMIT_STACK: c_int = 3;
3010pub const RLIMIT_DATA: c_int = 2;
3011pub const RLIMIT_AS: c_int = 9;
3012pub const RLIMIT_CPU: c_int = 0;
3013pub const RLIMIT_FSIZE: c_int = 1;
3014pub const RLIMIT_CORE: c_int = 4;
3015pub const RLIMIT_RSS: c_int = 5;
3016pub const RLIMIT_NPROC: c_int = 6;
3017pub const RLIMIT_MEMLOCK: c_int = 8;
3018pub const RLIMIT_LOCKS: c_int = 10;
3019pub const RLIMIT_SIGPENDING: c_int = 11;
3020pub const RLIMIT_MSGQUEUE: c_int = 12;
3021pub const RLIMIT_NICE: c_int = 13;
3022pub const RLIMIT_RTPRIO: c_int = 14;
3023pub const RLIMIT_RTTIME: c_int = 15;
3024pub const RLIM_INFINITY: u64 = !0u64;
3025
3026#[no_mangle]
3027pub unsafe extern "C" fn getrlimit(resource: c_int, rlim: *mut Rlimit) -> c_int {
3028 let r = sys_getrlimit(resource, rlim as *mut u8);
3029 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
3030}
3031
3032#[no_mangle]
3033pub unsafe extern "C" fn setrlimit(resource: c_int, rlim: *const Rlimit) -> c_int {
3034 let r = sys_setrlimit(resource, rlim as *const u8);
3035 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
3036}
3037
3038#[no_mangle]
3043pub unsafe extern "C" fn utimensat(dirfd: c_int, path: *const c_char, times: *const timespec, flags: c_int) -> c_int {
3044 let r = sys_utimensat(dirfd, path, times as *const u8, flags);
3045 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
3046}
3047
3048#[no_mangle]
3049pub unsafe extern "C" fn futimens(fd: c_int, times: *const timespec) -> c_int {
3050 let r = sys_utimensat(fd, core::ptr::null(), times as *const u8, 0);
3051 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
3052}
3053
3054pub const AF_UNIX: c_int = 1;
3059pub const AF_INET: c_int = 2;
3060pub const AF_INET6: c_int = 10;
3061
3062pub const SOCK_STREAM: c_int = 1;
3063pub const SOCK_DGRAM: c_int = 2;
3064
3065pub const SHUT_RD: c_int = 0;
3066pub const SHUT_WR: c_int = 1;
3067pub const SHUT_RDWR: c_int = 2;
3068
3069pub const SOL_SOCKET: c_int = 1;
3070pub const SO_REUSEADDR: c_int = 2;
3071
3072#[repr(C)]
3073pub struct sockaddr {
3074 pub sa_family: u16,
3075 pub sa_data: [u8; 14],
3076}
3077
3078#[inline]
3079unsafe fn sys_socket(domain: c_int, ty: c_int, protocol: c_int) -> i64 {
3080 <Arch as Syscalls>::syscall3(SYS_SOCKET, domain as i64, ty as i64, protocol as i64)
3081}
3082
3083#[inline]
3084unsafe fn sys_socketpair(domain: c_int, ty: c_int, protocol: c_int, sv: *mut c_int) -> i64 {
3085 <Arch as Syscalls>::syscall4(SYS_SOCKETPAIR, domain as i64, ty as i64, protocol as i64, sv as i64)
3086}
3087
3088#[inline]
3089unsafe fn sys_bind(fd: c_int, addr: *const sockaddr, len: c_uint) -> i64 {
3090 <Arch as Syscalls>::syscall3(SYS_BIND, fd as i64, addr as i64, len as i64)
3091}
3092
3093#[inline]
3094unsafe fn sys_listen(fd: c_int, backlog: c_int) -> i64 {
3095 <Arch as Syscalls>::syscall2(SYS_LISTEN, fd as i64, backlog as i64)
3096}
3097
3098#[inline]
3099unsafe fn sys_accept(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> i64 {
3100 <Arch as Syscalls>::syscall3(SYS_ACCEPT, fd as i64, addr as i64, len as i64)
3101}
3102
3103#[inline]
3104unsafe fn sys_connect(fd: c_int, addr: *const sockaddr, len: c_uint) -> i64 {
3105 <Arch as Syscalls>::syscall3(SYS_CONNECT, fd as i64, addr as i64, len as i64)
3106}
3107
3108#[inline]
3109unsafe fn sys_sendto(fd: c_int,
3110 buf: *const c_void,
3111 len: usize,
3112 flags: c_int,
3113 addr: *const sockaddr,
3114 addrlen: c_uint,) -> i64 {
3115 <Arch as Syscalls>::syscall6(SYS_SENDTO, fd as i64, buf as i64, len as i64, flags as i64, addr as i64, addrlen as i64)
3116}
3117
3118#[inline]
3119unsafe fn sys_recvfrom(fd: c_int,
3120 buf: *mut c_void,
3121 len: usize,
3122 flags: c_int,
3123 addr: *mut sockaddr,
3124 addrlen: *mut c_uint,) -> i64 {
3125 <Arch as Syscalls>::syscall6(SYS_RECVFROM, fd as i64, buf as i64, len as i64, flags as i64, addr as i64, addrlen as i64)
3126}
3127
3128#[inline]
3129unsafe fn sys_shutdown(fd: c_int, how: c_int) -> i64 {
3130 <Arch as Syscalls>::syscall2(SYS_SHUTDOWN, fd as i64, how as i64)
3131}
3132
3133#[inline]
3134unsafe fn sys_setsockopt(fd: c_int,
3135 level: c_int,
3136 optname: c_int,
3137 optval: *const c_void,
3138 optlen: c_uint,) -> i64 {
3139 <Arch as Syscalls>::syscall5(SYS_SETSOCKOPT, fd as i64, level as i64, optname as i64, optval as i64, optlen as i64)
3140}
3141
3142#[inline]
3143unsafe fn sys_getsockname(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> i64 {
3144 <Arch as Syscalls>::syscall3(SYS_GETSOCKNAME, fd as i64, addr as i64, len as i64)
3145}
3146
3147#[no_mangle]
3148pub unsafe extern "C" fn socket(domain: c_int, ty: c_int, protocol: c_int) -> c_int {
3149 let r = sys_socket(domain, ty, protocol);
3150 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3151 r as c_int
3152}
3153
3154#[no_mangle]
3155pub unsafe extern "C" fn socketpair(domain: c_int, ty: c_int, protocol: c_int, sv: *mut c_int) -> c_int {
3156 let r = sys_socketpair(domain, ty, protocol, sv);
3157 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3158 0
3159}
3160
3161#[no_mangle]
3162pub unsafe extern "C" fn bind(fd: c_int, addr: *const sockaddr, len: c_uint) -> c_int {
3163 let r = sys_bind(fd, addr, len);
3164 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3165 0
3166}
3167
3168#[no_mangle]
3169pub unsafe extern "C" fn listen(fd: c_int, backlog: c_int) -> c_int {
3170 let r = sys_listen(fd, backlog);
3171 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3172 0
3173}
3174
3175#[no_mangle]
3176pub unsafe extern "C" fn accept(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> c_int {
3177 let r = sys_accept(fd, addr, len);
3178 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3179 r as c_int
3180}
3181
3182#[no_mangle]
3183pub unsafe extern "C" fn connect(fd: c_int, addr: *const sockaddr, len: c_uint) -> c_int {
3184 let r = sys_connect(fd, addr, len);
3185 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3186 0
3187}
3188
3189#[no_mangle]
3190pub unsafe extern "C" fn send(fd: c_int, buf: *const c_void, len: usize, flags: c_int) -> isize {
3191 let r = sys_sendto(fd, buf, len, flags, core::ptr::null(), 0);
3192 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3193 r as isize
3194}
3195
3196#[no_mangle]
3197pub unsafe extern "C" fn recv(fd: c_int, buf: *mut c_void, len: usize, flags: c_int) -> isize {
3198 let r = sys_recvfrom(fd, buf, len, flags, core::ptr::null_mut(), core::ptr::null_mut());
3199 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3200 r as isize
3201}
3202
3203#[no_mangle]
3204pub unsafe extern "C" fn sendto(
3205 fd: c_int,
3206 buf: *const c_void,
3207 len: usize,
3208 flags: c_int,
3209 addr: *const sockaddr,
3210 addrlen: c_uint,
3211) -> isize {
3212 let r = sys_sendto(fd, buf, len, flags, addr, addrlen);
3213 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3214 r as isize
3215}
3216
3217#[no_mangle]
3218pub unsafe extern "C" fn recvfrom(
3219 fd: c_int,
3220 buf: *mut c_void,
3221 len: usize,
3222 flags: c_int,
3223 addr: *mut sockaddr,
3224 addrlen: *mut c_uint,
3225) -> isize {
3226 let r = sys_recvfrom(fd, buf, len, flags, addr, addrlen);
3227 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3228 r as isize
3229}
3230
3231#[no_mangle]
3232pub unsafe extern "C" fn shutdown(fd: c_int, how: c_int) -> c_int {
3233 let r = sys_shutdown(fd, how);
3234 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3235 0
3236}
3237
3238#[no_mangle]
3239pub unsafe extern "C" fn setsockopt(
3240 fd: c_int,
3241 level: c_int,
3242 optname: c_int,
3243 optval: *const c_void,
3244 optlen: c_uint,
3245) -> c_int {
3246 let r = sys_setsockopt(fd, level, optname, optval, optlen);
3247 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3248 0
3249}
3250
3251#[no_mangle]
3252pub unsafe extern "C" fn getsockname(fd: c_int, addr: *mut sockaddr, len: *mut c_uint) -> c_int {
3253 let r = sys_getsockname(fd, addr, len);
3254 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
3255 0
3256}
3257
3258#[no_mangle]
3259pub extern "C" fn htonl(hostlong: c_uint) -> c_uint {
3260 hostlong.to_be()
3261}
3262
3263#[no_mangle]
3264pub extern "C" fn ntohl(netlong: c_uint) -> c_uint {
3265 c_uint::from_be(netlong)
3266}
3267
3268#[no_mangle]
3269pub extern "C" fn htons(hostshort: u16) -> u16 {
3270 hostshort.to_be()
3271}
3272
3273#[no_mangle]
3274pub extern "C" fn ntohs(netshort: u16) -> u16 {
3275 u16::from_be(netshort)
3276}
3277
3278pub type PthreadT = c_ulong;
3279
3280#[repr(C)]
3282pub struct pthread_attr_t {
3283 __i: [c_int; 14],
3284}
3285
3286#[repr(C)]
3289pub struct pthread_mutex_t {
3290 __i: [c_int; 10],
3291}
3292
3293#[repr(C)]
3294pub struct pthread_mutexattr_t {
3295 __attr: c_uint,
3296}
3297
3298#[repr(C)]
3301pub struct pthread_cond_t {
3302 __i: [c_int; 12],
3303}
3304
3305#[repr(C)]
3306pub struct pthread_condattr_t {
3307 __attr: c_uint,
3308}
3309
3310#[repr(C)]
3313pub struct pthread_rwlock_t {
3314 __i: [c_int; 14],
3315}
3316
3317#[repr(C)]
3318pub struct pthread_rwlockattr_t {
3319 __attr: [c_uint; 2],
3320}
3321
3322#[repr(C)]
3324pub struct pthread_barrier_t {
3325 __i: [c_int; 8],
3326}
3327
3328#[repr(C)]
3329pub struct pthread_barrierattr_t {
3330 __attr: c_uint,
3331}
3332
3333pub type pthread_spinlock_t = c_int;
3334pub type pthread_once_t = c_int;
3335pub type pthread_key_t = c_uint;
3336
3337#[repr(C)]
3339pub struct sem_t {
3340 __val: [c_int; 8],
3341}
3342
3343#[repr(C)]
3344pub struct sched_param {
3345 pub sched_priority: c_int,
3346}
3347
3348const CLONE_VM: c_ulong = 0x00000100;
3349const CLONE_FS: c_ulong = 0x00000200;
3350const CLONE_FILES: c_ulong = 0x00000400;
3351const CLONE_SIGHAND: c_ulong = 0x00000800;
3352const CLONE_THREAD: c_ulong = 0x00010000;
3353const CLONE_SYSVSEM: c_ulong = 0x00040000;
3354const CLONE_SETTLS: c_ulong = 0x00080000;
3355const CLONE_PARENT_SETTID: c_ulong = 0x00100000;
3356const CLONE_CHILD_CLEARTID: c_ulong = 0x00200000;
3357
3358const FUTEX_WAIT: c_int = 0;
3359const FUTEX_WAKE: c_int = 1;
3360const FUTEX_LOCK_PI: c_int = 6;
3361const FUTEX_UNLOCK_PI: c_int = 7;
3362const FUTEX_TRYLOCK_PI: c_int = 8;
3363
3364const SIGCANCEL: c_int = 32;
3366
3367const PTHREAD_MUTEX_NORMAL: c_int = 0;
3368const PTHREAD_MUTEX_DEFAULT: c_int = 0;
3369const PTHREAD_MUTEX_RECURSIVE: c_int = 1;
3370const PTHREAD_MUTEX_ERRORCHECK: c_int = 2;
3371
3372const PTHREAD_CREATE_JOINABLE: c_int = 0;
3373const PTHREAD_CREATE_DETACHED: c_int = 1;
3374
3375const PTHREAD_CANCEL_ENABLE: c_int = 0;
3376const PTHREAD_CANCEL_DISABLE: c_int = 1;
3377const PTHREAD_CANCEL_DEFERRED: c_int = 0;
3378const PTHREAD_CANCEL_ASYNCHRONOUS: c_int = 1;
3379
3380const PTHREAD_SCOPE_SYSTEM: c_int = 0;
3381const PTHREAD_PROCESS_PRIVATE: c_int = 0;
3382const PTHREAD_PROCESS_SHARED: c_int = 1;
3383const PTHREAD_INHERIT_SCHED: c_int = 0;
3384const PTHREAD_EXPLICIT_SCHED: c_int = 1;
3385
3386const PTHREAD_BARRIER_SERIAL_THREAD: c_int = -1;
3387
3388const PTHREAD_KEYS_MAX: usize = 128;
3389const PTHREAD_DESTRUCTOR_ITERATIONS: usize = 4;
3390const SEM_VALUE_MAX: c_int = 0x7fffffff;
3391
3392const DT_EXITED: c_int = 0;
3393const DT_EXITING: c_int = 1;
3394const DT_JOINABLE: c_int = 2;
3395const DT_DETACHED: c_int = 3;
3396
3397#[repr(C)]
3399#[derive(Copy, Clone)]
3400pub struct __ptcb {
3401 __f: Option<unsafe extern "C" fn(*mut c_void)>,
3402 __x: *mut c_void,
3403 __next: *mut __ptcb,
3404}
3405
3406#[repr(C)]
3408#[derive(Copy, Clone)]
3409struct robust_list {
3410 next: *mut robust_list,
3411}
3412
3413#[repr(C)]
3414#[derive(Copy, Clone)]
3415struct robust_list_head {
3416 list: robust_list,
3417 futex_offset: c_long,
3418 pending: *mut robust_list,
3419}
3420
3421#[cfg(all(target_arch = "x86_64", not(test)))]
3423core::arch::global_asm!(
3424 ".global __rc_clone",
3425 ".type __rc_clone, @function",
3426 "__rc_clone:",
3427 "mov rax, rdi",
3428 "mov rdi, rdx",
3429 "mov rdx, r8",
3430 "mov r10, [rsp + 8]",
3431 "mov r8, r9",
3432 "mov r9, rax",
3433 "and rsi, -16",
3434 "sub rsi, 8",
3435 "mov [rsi], rcx",
3436 "mov eax, 56",
3437 "syscall",
3438 "test rax, rax",
3439 "jnz 1f",
3440 "pop rdi",
3441 "call r9",
3442 "mov edi, eax",
3445 "mov eax, 60",
3446 "syscall",
3447 "hlt",
3448 "1:",
3449 "ret",
3450);
3451
3452#[no_mangle]
3454#[unsafe(naked)]
3455#[cfg(target_arch = "aarch64")]
3456pub unsafe extern "C" fn __rc_clone(
3457 fn_: usize,
3458 stack: *mut u8,
3459 flags: c_ulong,
3460 arg: *mut c_void,
3461 ptid: *mut c_int,
3462 tls: c_ulong,
3463 ctid: *mut c_int,
3464) -> i64 {
3465 core::arch::naked_asm!(
3466 "and x1, x1, #-16",
3467 "stp x0, x3, [x1, #-16]!",
3468 "uxtw x0, w2",
3469 "mov x2, x4",
3470 "mov x3, x5",
3471 "mov x4, x6",
3472 "mov x8, #220",
3473 "svc #0",
3474 "cbz x0, 1f",
3475 "ret",
3476 "1:",
3477 "mov x29, #0",
3478 "ldp x1, x0, [sp], #16",
3479 "blr x1",
3480 "mov x8, #93",
3481 "svc #0",
3482 );
3483}
3484
3485#[no_mangle]
3486#[unsafe(naked)]
3487#[cfg(target_arch = "riscv64")]
3488pub unsafe extern "C" fn __rc_clone(
3489 fn_: usize,
3490 stack: *mut u8,
3491 flags: c_ulong,
3492 arg: *mut c_void,
3493 ptid: *mut c_int,
3494 tls: c_ulong,
3495 ctid: *mut c_int,
3496) -> i64 {
3497 core::arch::naked_asm!(
3498 "andi a1, a1, -16",
3499 "addi a1, a1, -16",
3500 "sd a0, 0(a1)",
3501 "sd a3, 8(a1)",
3502 "mv a0, a2",
3503 "mv a2, a4",
3504 "mv a3, a5",
3505 "mv a4, a6",
3506 "li a7, 220",
3507 "ecall",
3508 "beqz a0, 1f",
3509 "ret",
3510 "1:",
3511 "ld a1, 0(sp)",
3512 "ld a0, 8(sp)",
3513 "jalr a1",
3514 "li a7, 93",
3515 "ecall",
3516 );
3517}
3518
3519#[cfg(all(target_arch = "x86_64", test))]
3520#[inline(never)]
3521unsafe fn __rc_clone(
3522 _fn_: usize,
3523 _stack: *mut u8,
3524 _flags: c_ulong,
3525 _arg: *mut c_void,
3526 _ptid: *mut c_int,
3527 _tls: c_ulong,
3528 _ctid: *mut c_int,
3529) -> i64 {
3530 -1
3531}
3532
3533#[cfg(all(target_arch = "x86_64", not(test)))]
3534extern "C" {
3535 fn __rc_clone(
3536 fn_: usize,
3537 stack: *mut u8,
3538 flags: c_ulong,
3539 arg: *mut c_void,
3540 ptid: *mut c_int,
3541 tls: c_ulong,
3542 ctid: *mut c_int,
3543 ) -> i64;
3544}
3545
3546#[inline(never)]
3547#[linkage = "weak"]
3548#[no_mangle]
3549pub extern "C" fn __rc_create_thread_tls() -> *mut u8 {
3550 core::ptr::null_mut()
3551}
3552
3553#[inline(never)]
3554#[linkage = "weak"]
3555#[no_mangle]
3556pub unsafe extern "C" fn __rc_init_thread_tls_at(_block: *mut u8) -> *mut u8 {
3557 core::ptr::null_mut()
3558}
3559
3560#[inline(never)]
3561#[linkage = "weak"]
3562#[no_mangle]
3563pub extern "C" fn __rc_tls_block_size() -> usize {
3564 0
3565}
3566
3567#[inline(never)]
3568#[linkage = "weak"]
3569#[no_mangle]
3570pub extern "C" fn __rc_tls_base_offset() -> usize {
3571 0
3572}
3573
3574#[inline]
3575unsafe fn sys_gettid() -> i64 {
3576 <Arch as Syscalls>::syscall0(SYS_GETTID)
3577}
3578
3579#[inline]
3580unsafe fn sys_futex(uaddr: *mut c_int,
3581 futex_op: c_int,
3582 val: c_int,
3583 timeout: *mut c_void,
3584 uaddr2: *mut c_int,
3585 val3: c_int,) -> i64 {
3586 <Arch as Syscalls>::syscall6(SYS_FUTEX, uaddr as i64, futex_op as i64, val as i64, timeout as i64, uaddr2 as i64, val3 as i64)
3587}
3588
3589const MAX_THREADS: usize = 1024;
3590const STACK_SIZE: usize = 1024 * 1024;
3591
3592#[repr(C)]
3593#[derive(Copy, Clone)]
3594struct Thread {
3595 tid: c_int,
3596 detach_state: c_int,
3597 result: *mut c_void,
3598 cancel: c_int,
3599 cancel_state: c_int,
3600 cancel_type: c_int,
3601 user_fn: usize,
3602 user_arg: *mut c_void,
3603 stack: *mut u8,
3604 stack_size: usize,
3605 stack_owned: bool,
3606 fs_base: *mut u8,
3607 tls_base: *mut u8,
3612 tls_size: usize,
3613 tsd: [*mut c_void; PTHREAD_KEYS_MAX],
3614 cancelbuf: *mut __ptcb,
3615 robust_list: robust_list_head,
3616}
3617
3618static mut THREADS: [Thread; MAX_THREADS] = [Thread {
3619 tid: -1,
3620 detach_state: DT_JOINABLE,
3621 result: core::ptr::null_mut(),
3622 cancel: 0,
3623 cancel_state: PTHREAD_CANCEL_ENABLE,
3624 cancel_type: PTHREAD_CANCEL_DEFERRED,
3625 user_fn: 0,
3626 user_arg: core::ptr::null_mut(),
3627 stack: core::ptr::null_mut(),
3628 stack_size: 0,
3629 stack_owned: false,
3630 fs_base: core::ptr::null_mut(),
3631 tls_base: core::ptr::null_mut(),
3632 tls_size: 0,
3633 tsd: [core::ptr::null_mut(); PTHREAD_KEYS_MAX],
3634 cancelbuf: core::ptr::null_mut(),
3635 robust_list: robust_list_head {
3636 list: robust_list { next: core::ptr::null_mut() },
3637 futex_offset: 0,
3638 pending: core::ptr::null_mut(),
3639 },
3640}; MAX_THREADS];
3641const SLOT_WORDS: usize = (MAX_THREADS + usize::BITS as usize - 1) / usize::BITS as usize;
3642static SLOT_USED: [AtomicUsize; SLOT_WORDS] = [const { AtomicUsize::new(0) }; SLOT_WORDS];
3643static mut KEY_DTORS: [Option<unsafe extern "C" fn(*mut c_void)>; PTHREAD_KEYS_MAX] = [None; PTHREAD_KEYS_MAX];
3644static NEXT_KEY: AtomicUsize = AtomicUsize::new(0);
3645
3646unsafe fn futex_wait(addr: *mut c_int, expected: c_int) -> c_int {
3648 let r = sys_futex(addr, FUTEX_WAIT, expected, null_mut(), null_mut(), 0);
3649 if r < 0 { let e = (-r) as c_int; if e == EAGAIN { 0 } else { e } } else { 0 }
3650}
3651
3652unsafe fn futex_wake(addr: *mut c_int, count: c_int) {
3653 let c = if count < 0 { c_int::MAX } else { count };
3654 sys_futex(addr, FUTEX_WAKE, c, null_mut(), null_mut(), 0);
3655}
3656
3657unsafe fn futex_lock_pi(addr: *mut c_int, abs_timeout: *const timespec) -> c_int {
3658 let timeout_ptr = if abs_timeout.is_null() { null_mut() } else { abs_timeout as *mut c_void };
3659 let r = sys_futex(addr, FUTEX_LOCK_PI, 0, timeout_ptr, null_mut(), 0);
3660 if r < 0 { (-r) as c_int } else { 0 }
3661}
3662
3663unsafe fn futex_unlock_pi(addr: *mut c_int) -> c_int {
3664 let r = sys_futex(addr, FUTEX_UNLOCK_PI, 0, null_mut(), null_mut(), 0);
3665 if r < 0 { (-r) as c_int } else { 0 }
3666}
3667
3668#[inline]
3669unsafe fn sys_set_robust_list(head: *mut robust_list_head, len: usize) -> i64 {
3670 <Arch as Syscalls>::syscall2(SYS_SET_ROBUST_LIST, head as i64, len as i64)
3671}
3672
3673unsafe fn futex_timedwait(addr: *mut c_int, expected: c_int, abs_timeout: *const timespec) -> c_int {
3674 if abs_timeout.is_null() { return futex_wait(addr, expected); }
3675 let mut now: timespec = core::mem::zeroed();
3676 if sys_clock_gettime(CLOCK_REALTIME, &mut now) < 0 { return EINVAL; }
3677 let mut rel: timespec = core::mem::zeroed();
3678 rel.tv_sec = (*abs_timeout).tv_sec - now.tv_sec;
3679 rel.tv_nsec = (*abs_timeout).tv_nsec - now.tv_nsec;
3680 if rel.tv_nsec < 0 { rel.tv_sec -= 1; rel.tv_nsec += 1_000_000_000; }
3681 if rel.tv_sec < 0 { return ETIMEDOUT; }
3682 let r = sys_futex(addr, FUTEX_WAIT, expected, &mut rel as *mut timespec as *mut c_void, null_mut(), 0);
3683 if r < 0 { let e = (-r) as c_int; if e == EAGAIN { 0 } else { e } } else { 0 }
3684}
3685
3686unsafe fn a_cas(addr: *mut c_int, expected: c_int, desired: c_int) -> c_int {
3688 let a = &*(addr as *const AtomicI32);
3689 match a.compare_exchange(expected, desired, Ordering::AcqRel, Ordering::Acquire) {
3690 Ok(v) | Err(v) => v,
3691 }
3692}
3693
3694unsafe fn a_store(addr: *mut c_int, val: c_int) {
3695 (*(addr as *const AtomicI32)).store(val, Ordering::Release);
3696}
3697
3698unsafe fn a_load(addr: *const c_int) -> c_int {
3699 (*(addr as *const AtomicI32)).load(Ordering::Acquire)
3700}
3701
3702unsafe fn a_swap(addr: *mut c_int, val: c_int) -> c_int {
3703 (*(addr as *const AtomicI32)).swap(val, Ordering::AcqRel)
3704}
3705
3706unsafe fn a_fetch_add(addr: *mut c_int, val: c_int) -> c_int {
3707 (*(addr as *const AtomicI32)).fetch_add(val, Ordering::AcqRel)
3708}
3709
3710unsafe fn a_fetch_sub(addr: *mut c_int, val: c_int) -> c_int {
3711 (*(addr as *const AtomicI32)).fetch_sub(val, Ordering::AcqRel)
3712}
3713
3714unsafe fn spinlock_lock(lock: *mut c_int, waiters: *mut c_int) {
3715 while a_swap(lock, 1) != 0 {
3716 let mut spins = 100;
3717 while spins > 0 && a_load(lock) != 0 { core::hint::spin_loop(); spins -= 1; }
3718 if a_load(lock) == 0 { continue; }
3719 a_fetch_add(waiters, 1);
3720 futex_wait(lock, 1);
3721 a_fetch_sub(waiters, 1);
3722 }
3723}
3724
3725unsafe fn spinlock_unlock(lock: *mut c_int, waiters: *mut c_int) {
3726 a_store(lock, 0);
3727 if a_load(waiters) > 0 { futex_wake(lock, 1); }
3728}
3729
3730unsafe fn slot_index(slot: *const Thread) -> usize {
3731 let base = core::ptr::addr_of!(THREADS[0]) as usize;
3732 (slot as usize - base) / core::mem::size_of::<Thread>()
3733}
3734
3735unsafe fn release_thread_slot(slot: *const Thread) {
3736 let idx = slot_index(slot);
3737 if idx < MAX_THREADS {
3738 let word = idx / usize::BITS as usize;
3739 let bit = idx % usize::BITS as usize;
3740 SLOT_USED[word].fetch_and(!(1usize << bit), Ordering::AcqRel);
3741 }
3742}
3743
3744unsafe fn alloc_thread_slot() -> Option<&'static mut Thread> {
3745 for word in 0..SLOT_WORDS {
3746 let mut used = SLOT_USED[word].load(Ordering::Acquire);
3747 loop {
3748 let free = !used;
3749 if free == 0 {
3750 break;
3751 }
3752 let bit = free.trailing_zeros() as usize;
3753 let idx = word * usize::BITS as usize + bit;
3754 if idx >= MAX_THREADS {
3755 break;
3756 }
3757 match SLOT_USED[word].compare_exchange_weak(
3758 used,
3759 used | (1usize << bit),
3760 Ordering::AcqRel,
3761 Ordering::Acquire,
3762 ) {
3763 Ok(_) => return Some(&mut THREADS[idx]),
3764 Err(v) => used = v,
3765 }
3766 }
3767 }
3768 None
3769}
3770
3771unsafe fn run_key_dtors(slot: &mut Thread) {
3772 for _ in 0..PTHREAD_DESTRUCTOR_ITERATIONS {
3773 let mut any = false;
3774 for i in 0..PTHREAD_KEYS_MAX {
3775 let val = slot.tsd[i];
3776 if !val.is_null() {
3777 if let Some(dtor) = KEY_DTORS[i] {
3778 slot.tsd[i] = core::ptr::null_mut();
3779 any = true;
3780 dtor(val);
3781 }
3782 }
3783 }
3784 if !any { break; }
3785 }
3786}
3787
3788unsafe extern "C" fn thread_entry(slot: *mut c_void) -> *mut c_void {
3789 let slot = &mut *(slot as *mut Thread);
3790 slot.robust_list.list.next = core::ptr::null_mut();
3793 slot.robust_list.futex_offset = 0;
3794 slot.robust_list.pending = core::ptr::null_mut();
3795 ensure_robust_list(slot);
3796 let mut set: SigSetT = 0;
3797 sigemptyset(&mut set);
3798 sigaddset(&mut set, SIGCANCEL);
3799 pthread_sigmask(SIG_UNBLOCK, &set, core::ptr::null_mut());
3800 let user_fn: unsafe extern "C" fn(*mut c_void) -> *mut c_void =
3801 core::mem::transmute::<usize, _>(slot.user_fn);
3802 let ret = user_fn(slot.user_arg);
3803 run_key_dtors(slot);
3804 slot.result = ret;
3805 a_store(&raw mut slot.detach_state, DT_EXITED);
3806 futex_wake(&raw mut slot.detach_state, 1);
3807 sys_exit_thread(0)
3808}
3809
3810unsafe fn find_thread() -> Option<&'static mut Thread> {
3811 let me = sys_gettid() as c_int;
3812 let base = core::ptr::addr_of_mut!(THREADS[0]);
3813 for i in 0..MAX_THREADS {
3814 let slot = base.add(i);
3815 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3816 return Some(&mut *slot);
3817 }
3818 }
3819 pthread_self();
3821 for i in 0..MAX_THREADS {
3822 let slot = base.add(i);
3823 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3824 return Some(&mut *slot);
3825 }
3826 }
3827 None
3828}
3829
3830#[no_mangle]
3831pub unsafe extern "C" fn pthread_self() -> PthreadT {
3832 let me = sys_gettid() as c_int;
3833 let base = core::ptr::addr_of_mut!(THREADS[0]);
3834 for i in 0..MAX_THREADS {
3835 let slot = base.add(i);
3836 if core::ptr::read_volatile(&raw const (*slot).tid) == me {
3837 return slot as PthreadT;
3838 }
3839 }
3840 if let Some(slot) = alloc_thread_slot() {
3842 let slot = slot as *mut Thread;
3843 (*slot).tid = me;
3844 (*slot).detach_state = DT_JOINABLE;
3845 return slot as PthreadT;
3846 }
3847 0
3848}
3849
3850#[no_mangle]
3851pub unsafe extern "C" fn pthread_equal(t1: PthreadT, t2: PthreadT) -> c_int {
3852 (t1 == t2) as c_int
3853}
3854
3855#[no_mangle]
3856pub unsafe extern "C" fn pthread_create(
3857 thread: *mut PthreadT,
3858 attr: *const pthread_attr_t,
3859 start_routine: usize,
3860 arg: *mut c_void,
3861) -> c_int {
3862 if start_routine == 0 || thread.is_null() { return EINVAL; }
3863 let Some(slot_ref) = alloc_thread_slot() else { return EAGAIN; };
3864 let slot = slot_ref as *mut Thread;
3865 let stack_size = if !attr.is_null() {
3866 let s = *((*attr).__i.as_ptr() as *const usize);
3867 if s > 0 { s } else { STACK_SIZE }
3868 } else { STACK_SIZE };
3869 let user_top = if !attr.is_null() {
3871 *((*attr).__i.as_ptr().add(4) as *const *mut c_void)
3872 } else {
3873 core::ptr::null_mut()
3874 };
3875 let stack_owned = user_top.is_null();
3876 let stack = if stack_owned {
3877 sys_mmap(null_mut(), stack_size, PROT_READ | PROT_WRITE, MAP_PRIVATE | MAP_ANONYMOUS, -1, 0)
3878 } else {
3879 (user_top as *mut u8).sub(stack_size)
3880 };
3881 if stack == MMAP_FAILED { release_thread_slot(slot); return EAGAIN; }
3882 let tls_total = __rc_tls_block_size();
3883 let mut stack_top = stack.add(stack_size);
3884 let mut tls_owned = true;
3885 let fs_base = if !stack_owned && tls_total > 0 && stack_size > tls_total + 4096 {
3886 let block = ((user_top as usize - tls_total) & !63usize) as *mut u8;
3890 let fs = __rc_init_thread_tls_at(block);
3891 if fs.is_null() {
3892 __rc_create_thread_tls()
3893 } else {
3894 stack_top = block;
3895 tls_owned = false;
3896 fs
3897 }
3898 } else {
3899 __rc_create_thread_tls()
3900 };
3901 if fs_base.is_null() {
3902 if stack_owned { sys_munmap(stack, stack_size); }
3903 release_thread_slot(slot);
3904 return EAGAIN;
3905 }
3906 let tls_base = fs_base.sub(__rc_tls_base_offset());
3907 let tls_size = if tls_owned { tls_total } else { 0 };
3908 (*slot).detach_state = DT_JOINABLE;
3909 (*slot).result = core::ptr::null_mut();
3910 (*slot).cancel = 0;
3911 (*slot).cancel_state = PTHREAD_CANCEL_ENABLE;
3912 (*slot).cancel_type = PTHREAD_CANCEL_DEFERRED;
3913 core::ptr::write_bytes((*slot).tsd.as_mut_ptr(), 0, PTHREAD_KEYS_MAX);
3914 (*slot).tid = 1;
3915 (*slot).user_fn = start_routine;
3916 (*slot).user_arg = arg;
3917 (*slot).stack = stack;
3918 (*slot).stack_size = stack_size;
3919 (*slot).stack_owned = stack_owned;
3920 (*slot).fs_base = fs_base;
3921 (*slot).tls_base = tls_base;
3922 (*slot).tls_size = tls_size;
3923 let tid_ptr = &raw mut (*slot).tid;
3924 let flags = CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD
3925 | CLONE_SYSVSEM | CLONE_PARENT_SETTID | CLONE_CHILD_CLEARTID | CLONE_SETTLS;
3926 let tid = __rc_clone(thread_entry as *const () as usize, stack_top, flags, slot as *mut c_void, tid_ptr, fs_base as c_ulong, tid_ptr);
3927 if tid < 0 {
3928 (*slot).tid = -1;
3929 if stack_owned { sys_munmap(stack, stack_size); }
3930 if tls_size > 0 { sys_munmap(tls_base, tls_size); }
3931 release_thread_slot(slot);
3932 return EAGAIN;
3933 }
3934 if !attr.is_null() && (*attr).__i[6] == PTHREAD_CREATE_DETACHED {
3935 (*slot).detach_state = DT_DETACHED;
3936 }
3937 *thread = slot as PthreadT;
3938 0
3939}
3940
3941#[no_mangle]
3942pub unsafe extern "C" fn pthread_join(thread: PthreadT, retval: *mut *mut c_void) -> c_int {
3943 let slot = thread as *mut Thread;
3944 if slot.is_null() { return EINVAL; }
3945 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
3946 let tid_ptr = &raw mut (*slot).tid;
3947 loop {
3948 pthread_testcancel();
3949 let tid = core::ptr::read_volatile(tid_ptr);
3950 if tid == 0 { break; }
3951 if tid < 0 { return EINVAL; }
3952 sys_futex(tid_ptr, FUTEX_WAIT, tid, null_mut(), null_mut(), 0);
3953 pthread_testcancel();
3954 }
3955 if !retval.is_null() { *retval = (*slot).result; }
3956 let stack = (*slot).stack;
3957 let stack_size = (*slot).stack_size;
3958 let stack_owned = (*slot).stack_owned;
3959 let tls_base = (*slot).tls_base;
3960 let tls_size = (*slot).tls_size;
3961 (*slot).tid = -1;
3962 (*slot).detach_state = DT_JOINABLE;
3963 (*slot).result = core::ptr::null_mut();
3964 (*slot).stack = core::ptr::null_mut();
3965 (*slot).stack_size = 0;
3966 (*slot).stack_owned = false;
3967 (*slot).fs_base = core::ptr::null_mut();
3968 (*slot).tls_base = core::ptr::null_mut();
3969 (*slot).tls_size = 0;
3970 if stack_owned && !stack.is_null() && stack_size > 0 { sys_munmap(stack, stack_size); }
3971 let _ = (tls_base, tls_size);
3981 release_thread_slot(slot);
3982 0
3983}
3984
3985#[no_mangle]
3986pub unsafe extern "C" fn pthread_detach(thread: PthreadT) -> c_int {
3987 let slot = thread as *mut Thread;
3988 if slot.is_null() { return EINVAL; }
3989 let old = a_cas(&raw mut (*slot).detach_state, DT_JOINABLE, DT_DETACHED);
3990 if old == DT_EXITED {
3991 let stack = (*slot).stack;
3992 let stack_size = (*slot).stack_size;
3993 let stack_owned = (*slot).stack_owned;
3994 let tls_base = (*slot).tls_base;
3995 let tls_size = (*slot).tls_size;
3996 (*slot).tid = -1;
3997 (*slot).stack = core::ptr::null_mut();
3998 (*slot).stack_size = 0;
3999 (*slot).stack_owned = false;
4000 (*slot).fs_base = core::ptr::null_mut();
4001 (*slot).tls_base = core::ptr::null_mut();
4002 (*slot).tls_size = 0;
4003 if stack_owned && !stack.is_null() && stack_size > 0 { sys_munmap(stack, stack_size); }
4004 let _ = (tls_base, tls_size);
4006 release_thread_slot(slot);
4007 }
4008 0
4009}
4010
4011#[no_mangle]
4012pub unsafe extern "C" fn pthread_exit(retval: *mut c_void) -> ! {
4013 if let Some(slot) = find_thread() {
4014 run_cleanup_handlers(slot);
4015 run_key_dtors(slot);
4016 slot.result = retval;
4017 slot.detach_state = DT_EXITED;
4018 futex_wake(&slot.detach_state as *const c_int as *mut c_int, 1);
4019
4020 let mut active = 0usize;
4022 for i in 0..MAX_THREADS {
4023 if THREADS[i].tid > 0 {
4024 active += 1;
4025 }
4026 }
4027 if active == 1 {
4028 exit(0);
4029 }
4030 }
4031 sys_exit_thread(0);
4032}
4033
4034#[no_mangle]
4036pub unsafe extern "C" fn pthread_attr_init(attr: *mut pthread_attr_t) -> c_int {
4037 core::ptr::write_bytes(attr, 0, 1);
4038 *((*attr).__i.as_mut_ptr() as *mut usize) = STACK_SIZE;
4039 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = 4096;
4040 (*attr).__i[6] = PTHREAD_CREATE_JOINABLE;
4041 (*attr).__i[7] = PTHREAD_INHERIT_SCHED;
4042 0
4043}
4044#[no_mangle]
4045pub unsafe extern "C" fn pthread_attr_destroy(_attr: *mut pthread_attr_t) -> c_int { 0 }
4046#[no_mangle]
4047pub unsafe extern "C" fn pthread_attr_setdetachstate(attr: *mut pthread_attr_t, s: c_int) -> c_int {
4048 if s != PTHREAD_CREATE_JOINABLE && s != PTHREAD_CREATE_DETACHED { return EINVAL; }
4049 (*attr).__i[6] = s; 0
4050}
4051#[no_mangle]
4052pub unsafe extern "C" fn pthread_attr_getdetachstate(attr: *const pthread_attr_t, s: *mut c_int) -> c_int {
4053 *s = (*attr).__i[6]; 0
4054}
4055#[no_mangle]
4056pub unsafe extern "C" fn pthread_attr_setstacksize(attr: *mut pthread_attr_t, sz: usize) -> c_int {
4057 if sz < 2048 { return EINVAL; }
4058 *((*attr).__i.as_mut_ptr() as *mut usize) = sz;
4059 *((*attr).__i.as_mut_ptr().add(4) as *mut *mut c_void) = core::ptr::null_mut();
4060 0
4061}
4062#[no_mangle]
4063pub unsafe extern "C" fn pthread_attr_getstacksize(attr: *const pthread_attr_t, sz: *mut usize) -> c_int {
4064 *sz = *((*attr).__i.as_ptr() as *const usize); 0
4065}
4066#[no_mangle]
4067pub unsafe extern "C" fn pthread_attr_setstack(attr: *mut pthread_attr_t, addr: *mut c_void, sz: usize) -> c_int {
4068 if sz < 2048 { return EINVAL; }
4069 *((*attr).__i.as_mut_ptr() as *mut usize) = sz;
4070 *((*attr).__i.as_mut_ptr().add(4) as *mut *mut c_void) = (addr as *mut u8).add(sz) as *mut c_void;
4072 0
4073}
4074#[no_mangle]
4075pub unsafe extern "C" fn pthread_attr_getstack(attr: *const pthread_attr_t, addr: *mut *mut c_void, sz: *mut usize) -> c_int {
4076 let size = *((*attr).__i.as_ptr() as *const usize);
4077 *sz = size;
4078 let top = *((*attr).__i.as_ptr().add(4) as *const *mut c_void);
4079 *addr = if top.is_null() {
4080 core::ptr::null_mut()
4081 } else {
4082 (top as *mut u8).sub(size) as *mut c_void
4083 };
4084 0
4085}
4086#[no_mangle]
4087pub unsafe extern "C" fn pthread_attr_setguardsize(attr: *mut pthread_attr_t, sz: usize) -> c_int {
4088 *((*attr).__i.as_mut_ptr().add(2) as *mut usize) = sz; 0
4089}
4090#[no_mangle]
4091pub unsafe extern "C" fn pthread_attr_getguardsize(attr: *const pthread_attr_t, sz: *mut usize) -> c_int {
4092 *sz = *((*attr).__i.as_ptr().add(2) as *const usize); 0
4093}
4094#[no_mangle]
4095pub unsafe extern "C" fn pthread_attr_setscope(_attr: *mut pthread_attr_t, scope: c_int) -> c_int {
4096 if scope != PTHREAD_SCOPE_SYSTEM { return EINVAL; }
4097 0
4098}
4099#[no_mangle]
4100pub unsafe extern "C" fn pthread_attr_getscope(_attr: *const pthread_attr_t, scope: *mut c_int) -> c_int {
4101 *scope = PTHREAD_SCOPE_SYSTEM; 0
4102}
4103#[no_mangle]
4104pub unsafe extern "C" fn pthread_attr_setinheritsched(attr: *mut pthread_attr_t, inh: c_int) -> c_int {
4105 if inh != PTHREAD_INHERIT_SCHED && inh != PTHREAD_EXPLICIT_SCHED { return EINVAL; }
4106 (*attr).__i[7] = inh; 0
4107}
4108#[no_mangle]
4109pub unsafe extern "C" fn pthread_attr_getinheritsched(attr: *const pthread_attr_t, inh: *mut c_int) -> c_int {
4110 *inh = (*attr).__i[7]; 0
4111}
4112#[no_mangle]
4113pub unsafe extern "C" fn pthread_attr_setschedpolicy(attr: *mut pthread_attr_t, p: c_int) -> c_int {
4114 (*attr).__i[8] = p; 0
4115}
4116#[no_mangle]
4117pub unsafe extern "C" fn pthread_attr_getschedpolicy(attr: *const pthread_attr_t, p: *mut c_int) -> c_int {
4118 *p = (*attr).__i[8]; 0
4119}
4120#[no_mangle]
4121pub unsafe extern "C" fn pthread_attr_setschedparam(attr: *mut pthread_attr_t, param: *const sched_param) -> c_int {
4122 (*attr).__i[9] = (*param).sched_priority; 0
4123}
4124#[no_mangle]
4125pub unsafe extern "C" fn pthread_attr_getschedparam(attr: *const pthread_attr_t, param: *mut sched_param) -> c_int {
4126 (*param).sched_priority = (*attr).__i[9]; 0
4127}
4128
4129#[no_mangle]
4131pub unsafe extern "C" fn pthread_mutexattr_init(attr: *mut pthread_mutexattr_t) -> c_int {
4132 (*attr).__attr = 0; 0
4133}
4134#[no_mangle]
4135pub unsafe extern "C" fn pthread_mutexattr_destroy(_attr: *mut pthread_mutexattr_t) -> c_int { 0 }
4136#[no_mangle]
4137pub unsafe extern "C" fn pthread_mutexattr_settype(attr: *mut pthread_mutexattr_t, t: c_int) -> c_int {
4138 if (t as c_uint) > 2 { return EINVAL; }
4139 (*attr).__attr = ((*attr).__attr & !3) | t as c_uint; 0
4140}
4141#[no_mangle]
4142pub unsafe extern "C" fn pthread_mutexattr_gettype(attr: *const pthread_mutexattr_t, t: *mut c_int) -> c_int {
4143 *t = ((*attr).__attr & 3) as c_int; 0
4144}
4145#[no_mangle]
4146pub unsafe extern "C" fn pthread_mutexattr_setpshared(attr: *mut pthread_mutexattr_t, p: c_int) -> c_int {
4147 if (p as c_uint) > 1 { return EINVAL; }
4148 (*attr).__attr = ((*attr).__attr & !128) | ((p as c_uint) << 7); 0
4149}
4150#[no_mangle]
4151pub unsafe extern "C" fn pthread_mutexattr_getpshared(attr: *const pthread_mutexattr_t, p: *mut c_int) -> c_int {
4152 *p = (((*attr).__attr >> 7) & 1) as c_int; 0
4153}
4154
4155#[no_mangle]
4156pub unsafe extern "C" fn pthread_mutexattr_setprotocol(attr: *mut pthread_mutexattr_t, protocol: c_int) -> c_int {
4157 match protocol {
4158 0 => { (*attr).__attr &= !(MUTEX_PI as c_uint); 0 }
4159 1 => {
4160 let mut lk: c_int = 0;
4161 let r = sys_futex(&raw mut lk, FUTEX_LOCK_PI, 0, null_mut(), null_mut(), 0);
4162 if r < 0 { return (-r) as c_int; }
4163 sys_futex(&raw mut lk, FUTEX_UNLOCK_PI, 0, null_mut(), null_mut(), 0);
4164 (*attr).__attr |= MUTEX_PI as c_uint;
4165 0
4166 }
4167 2 => ENOTSUP,
4168 _ => EINVAL,
4169 }
4170}
4171#[no_mangle]
4172pub unsafe extern "C" fn pthread_mutexattr_getprotocol(attr: *const pthread_mutexattr_t, protocol: *mut c_int) -> c_int {
4173 *protocol = (((*attr).__attr >> 3) & 3) as c_int; 0
4174}
4175
4176const ENOTSUP: c_int = 95;
4177
4178#[no_mangle]
4179pub unsafe extern "C" fn pthread_mutexattr_setrobust(attr: *mut pthread_mutexattr_t, robust: c_int) -> c_int {
4180 if (robust as c_uint) > 1 { return EINVAL; }
4181 if robust != 0 {
4182 (*attr).__attr |= MUTEX_ROBUST as c_uint;
4183 } else {
4184 (*attr).__attr &= !(MUTEX_ROBUST as c_uint);
4185 }
4186 0
4187}
4188#[no_mangle]
4189pub unsafe extern "C" fn pthread_mutexattr_getrobust(attr: *const pthread_mutexattr_t, robust: *mut c_int) -> c_int {
4190 *robust = (((*attr).__attr >> 2) & 1) as c_int; 0
4191}
4192
4193#[no_mangle]
4194pub unsafe extern "C" fn pthread_mutex_consistent(m: *mut pthread_mutex_t) -> c_int {
4195 let old = a_load(&raw const (*m).__i[1]);
4196 let own = old & 0x3fffffff;
4197 if ((*m).__i[0] & MUTEX_ROBUST) == 0 || own == 0 || (old & 0x40000000) == 0 {
4198 return EINVAL;
4199 }
4200 let self_tid = sys_gettid() as c_int;
4201 if own != self_tid { return EPERM; }
4202 a_and(&raw mut (*m).__i[1], !(0x40000000i32));
4203 0
4204}
4205
4206unsafe fn a_and(addr: *mut c_int, val: c_int) {
4207 let a = &*(addr as *const AtomicI32);
4208 a.fetch_and(val, Ordering::AcqRel);
4209}
4210
4211const MUTEX_TYPE_MASK: c_int = 3;
4213const MUTEX_ROBUST: c_int = 4;
4214const MUTEX_PI: c_int = 8;
4215const MUTEX_PSHARED: c_int = 128;
4216
4217unsafe fn ensure_robust_list(slot: &mut Thread) {
4218 if slot.robust_list.futex_offset == 0 {
4219 slot.robust_list.futex_offset = -28;
4220 slot.robust_list.pending = core::ptr::null_mut();
4221 sys_set_robust_list(&mut slot.robust_list, 24);
4222 }
4223}
4224
4225unsafe fn mutex_trylock(m: *mut pthread_mutex_t) -> c_int {
4226 let type_ = (*m).__i[0];
4227 if (type_ & 0x8f) == PTHREAD_MUTEX_NORMAL {
4232 let old = a_cas(&raw mut (*m).__i[1], 0, EBUSY);
4233 return if old == 0 { 0 } else { EBUSY };
4234 }
4235 let base_type = type_ & MUTEX_TYPE_MASK;
4236 let self_tid = sys_gettid() as c_int;
4237 let old = a_load(&raw const (*m).__i[1]);
4238 let own = old & 0x3fffffff;
4239 if own == self_tid {
4240 if (type_ & MUTEX_PI) != 0 && (*m).__i[5] < 0 {
4241 (*m).__i[5] = 0;
4242 return 0;
4243 }
4244 if base_type == PTHREAD_MUTEX_RECURSIVE {
4245 if (*m).__i[5] >= c_int::MAX { return EAGAIN; }
4246 (*m).__i[5] += 1;
4247 return 0;
4248 }
4249 if base_type == PTHREAD_MUTEX_ERRORCHECK { return EDEADLK; }
4250 return EBUSY;
4251 }
4252 if own == 0x3fffffff { return ENOTRECOVERABLE; }
4253 if own != 0 || (old != 0 && (type_ & MUTEX_ROBUST) == 0) { return EBUSY; }
4254 let mut newtid = self_tid;
4255 if (type_ & MUTEX_ROBUST) != 0 {
4256 if (*m).__i[2] != 0 { newtid |= 1i32 << 31; }
4257 newtid |= old & 0x40000000;
4258 }
4259 if a_cas(&raw mut (*m).__i[1], old, newtid) == old {
4260 (*m).__i[5] = 0;
4261 if (type_ & MUTEX_ROBUST) != 0 {
4262 if let Some(slot) = find_thread() {
4263 ensure_robust_list(slot);
4264 let m_next = &raw mut (*m).__i[8] as *mut robust_list;
4265 let head = &mut slot.robust_list.list;
4266 (*m_next).next = head.next;
4267 head.next = m_next;
4268 }
4269 }
4270 if old != 0 { return EOWNERDEAD; }
4271 0
4272 } else { EBUSY }
4273}
4274
4275unsafe fn mutex_lock_internal(m: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4276 let type_ = (*m).__i[0];
4277 if (type_ & 0x8f) == PTHREAD_MUTEX_NORMAL && a_cas(&raw mut (*m).__i[1], 0, EBUSY) == 0 {
4278 return 0;
4279 }
4280 let r = mutex_trylock(m);
4281 if r != EBUSY { return r; }
4282 if (type_ & MUTEX_PI) != 0 {
4283 let timeout_ptr = if abs_timeout.is_null() { core::ptr::null() } else { abs_timeout };
4284 loop {
4285 let e = futex_lock_pi(&raw mut (*m).__i[1], timeout_ptr);
4286 match e {
4287 0 => {
4288 if (type_ & MUTEX_ROBUST) != 0 && (((*m).__i[1] & 0x40000000) != 0 || (*m).__i[2] != 0) {
4289 (*m).__i[5] = -1;
4290 let _ = mutex_trylock(m);
4291 return EOWNERDEAD;
4292 }
4293 if (type_ & MUTEX_ROBUST) == 0 && (((*m).__i[1] & 0x40000000) != 0 || (*m).__i[2] != 0) {
4294 (*m).__i[2] = -1;
4295 futex_unlock_pi(&raw mut (*m).__i[1]);
4296 return EBUSY;
4297 }
4298 (*m).__i[5] = -1;
4299 let r2 = mutex_trylock(m);
4300 if r2 == 0 { return 0; }
4301 return r2;
4302 }
4303 EINTR => continue,
4304 EDEADLK => {
4305 if (type_ & MUTEX_TYPE_MASK) == PTHREAD_MUTEX_ERRORCHECK { return e; }
4306 loop { pause(); }
4307 }
4308 EOWNERDEAD => {
4309 (*m).__i[5] = -1;
4310 let _ = mutex_trylock(m);
4311 return EOWNERDEAD;
4312 }
4313 _ => return e,
4314 }
4315 }
4316 }
4317 let mut spins = 100;
4318 while spins > 0 {
4319 let r = mutex_trylock(m);
4320 if r != EBUSY { return r; }
4321 core::hint::spin_loop();
4322 spins -= 1;
4323 }
4324 loop {
4325 let r = mutex_trylock(m);
4326 if r != EBUSY { return r; }
4327 if (type_ & MUTEX_TYPE_MASK) == PTHREAD_MUTEX_ERRORCHECK {
4328 let self_tid = sys_gettid() as c_int;
4329 if (a_load(&raw const (*m).__i[1]) & 0x3fffffff) == self_tid { return EDEADLK; }
4330 }
4331 a_fetch_add(&raw mut (*m).__i[2], 1);
4332 let val = a_load(&raw const (*m).__i[1]);
4333 if val == 0 {
4337 a_fetch_sub(&raw mut (*m).__i[2], 1);
4338 continue;
4339 }
4340 a_cas(&raw mut (*m).__i[1], val, val | (1i32 << 31));
4341 let e = futex_timedwait(&raw mut (*m).__i[1], val | (1i32 << 31), abs_timeout);
4342 a_fetch_sub(&raw mut (*m).__i[2], 1);
4343 if e != 0 && e != EINTR { return e; }
4344 }
4345}
4346
4347#[no_mangle]
4348pub unsafe extern "C" fn pthread_mutex_init(mutex: *mut pthread_mutex_t, attr: *const pthread_mutexattr_t) -> c_int {
4349 core::ptr::write_bytes(mutex, 0, 1);
4350 if !attr.is_null() { (*mutex).__i[0] = (*attr).__attr as c_int; }
4351 0
4352}
4353#[no_mangle]
4354pub unsafe extern "C" fn pthread_mutex_destroy(_mutex: *mut pthread_mutex_t) -> c_int { 0 }
4355#[no_mangle]
4356pub unsafe extern "C" fn pthread_mutex_lock(mutex: *mut pthread_mutex_t) -> c_int {
4357 mutex_lock_internal(mutex, core::ptr::null())
4358}
4359#[no_mangle]
4360pub unsafe extern "C" fn pthread_mutex_trylock(mutex: *mut pthread_mutex_t) -> c_int {
4361 mutex_trylock(mutex)
4362}
4363#[no_mangle]
4364pub unsafe extern "C" fn pthread_mutex_timedlock(mutex: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4365 mutex_lock_internal(mutex, abs_timeout)
4366}
4367#[no_mangle]
4368pub unsafe extern "C" fn pthread_mutex_unlock(mutex: *mut pthread_mutex_t) -> c_int {
4369 let type_ = (*mutex).__i[0];
4370 let base_type = type_ & MUTEX_TYPE_MASK;
4371 let old = a_load(&raw const (*mutex).__i[1]);
4372 if base_type != PTHREAD_MUTEX_NORMAL {
4373 let self_tid = sys_gettid() as c_int;
4374 if (old & 0x3fffffff) != self_tid { return EPERM; }
4375 if base_type == PTHREAD_MUTEX_RECURSIVE && (*mutex).__i[5] > 0 {
4376 (*mutex).__i[5] -= 1;
4377 return 0;
4378 }
4379 }
4380 let mut new = 0;
4381 if (type_ & MUTEX_ROBUST) != 0 && (old & 0x40000000) != 0 {
4382 new = 0x7fffffff;
4383 }
4384 if (type_ & MUTEX_PI) != 0 {
4385 if old < 0 || a_cas(&raw mut (*mutex).__i[1], old, new) != old {
4386 if new != 0 { a_store(&raw mut (*mutex).__i[2], -1); }
4387 return futex_unlock_pi(&raw mut (*mutex).__i[1]);
4388 }
4389 return 0;
4390 }
4391 a_store(&raw mut (*mutex).__i[1], new);
4392 if new == 0 && (a_load(&raw const (*mutex).__i[2]) > 0 || old < 0) {
4393 futex_wake(&raw mut (*mutex).__i[1], 1);
4394 }
4395 0
4396}
4397
4398#[no_mangle]
4400pub unsafe extern "C" fn pthread_condattr_init(attr: *mut pthread_condattr_t) -> c_int {
4401 (*attr).__attr = 0; 0
4402}
4403#[no_mangle]
4404pub unsafe extern "C" fn pthread_condattr_destroy(_attr: *mut pthread_condattr_t) -> c_int { 0 }
4405#[no_mangle]
4406pub unsafe extern "C" fn pthread_condattr_setclock(attr: *mut pthread_condattr_t, clk: c_int) -> c_int {
4407 if clk != CLOCK_REALTIME && clk != CLOCK_MONOTONIC { return EINVAL; }
4408 (*attr).__attr = ((*attr).__attr & 0x80000000) | clk as c_uint; 0
4409}
4410#[no_mangle]
4411pub unsafe extern "C" fn pthread_condattr_getclock(attr: *const pthread_condattr_t, clk: *mut c_int) -> c_int {
4412 *clk = ((*attr).__attr & 0x7fffffff) as c_int; 0
4413}
4414#[no_mangle]
4415pub unsafe extern "C" fn pthread_condattr_setpshared(attr: *mut pthread_condattr_t, p: c_int) -> c_int {
4416 if (p as c_uint) > 1 { return EINVAL; }
4417 (*attr).__attr = ((*attr).__attr & 0x7fffffff) | ((p as c_uint) << 31); 0
4418}
4419#[no_mangle]
4420pub unsafe extern "C" fn pthread_condattr_getpshared(attr: *const pthread_condattr_t, p: *mut c_int) -> c_int {
4421 *p = ((*attr).__attr >> 31) as c_int; 0
4422}
4423
4424#[no_mangle]
4426pub unsafe extern "C" fn pthread_cond_init(cond: *mut pthread_cond_t, attr: *const pthread_condattr_t) -> c_int {
4427 core::ptr::write_bytes(cond, 0, 1);
4428 if !attr.is_null() {
4429 (*cond).__i[4] = ((*attr).__attr & 0x7fffffff) as c_int;
4430 }
4431 0
4432}
4433#[no_mangle]
4434pub unsafe extern "C" fn pthread_cond_destroy(_cond: *mut pthread_cond_t) -> c_int { 0 }
4435#[no_mangle]
4436pub unsafe extern "C" fn pthread_cond_wait(cond: *mut pthread_cond_t, mutex: *mut pthread_mutex_t) -> c_int {
4437 pthread_cond_timedwait(cond, mutex, core::ptr::null())
4438}
4439
4440
4441#[no_mangle]
4442pub unsafe extern "C" fn pthread_cond_timedwait(cond: *mut pthread_cond_t, mutex: *mut pthread_mutex_t, abs_timeout: *const timespec) -> c_int {
4443 pthread_testcancel();
4444 let seq_ptr = &raw mut (*cond).__i[2];
4445 let waiters_ptr = &raw mut (*cond).__i[3];
4446 let seq = a_load(seq_ptr);
4447 a_fetch_add(waiters_ptr, 1);
4448 pthread_mutex_unlock(mutex);
4449 let e = futex_timedwait(seq_ptr, seq, abs_timeout);
4450 a_fetch_sub(waiters_ptr, 1);
4451 let r = pthread_mutex_lock(mutex);
4452 if r != 0 { return r; }
4453 if e == EINTR {
4454 pthread_testcancel();
4455 }
4456 if e != 0 && e != EINTR { return e; }
4457 0
4458}
4459#[no_mangle]
4460pub unsafe extern "C" fn pthread_cond_signal(cond: *mut pthread_cond_t) -> c_int {
4461 if a_load(&raw const (*cond).__i[3]) == 0 { return 0; }
4462 a_fetch_add(&raw mut (*cond).__i[2], 1);
4463 futex_wake(&raw mut (*cond).__i[2], 1);
4464 0
4465}
4466#[no_mangle]
4467pub unsafe extern "C" fn pthread_cond_broadcast(cond: *mut pthread_cond_t) -> c_int {
4468 if a_load(&raw const (*cond).__i[3]) == 0 { return 0; }
4469 a_fetch_add(&raw mut (*cond).__i[2], 1);
4470 futex_wake(&raw mut (*cond).__i[2], -1);
4471 0
4472}
4473
4474#[no_mangle]
4476pub unsafe extern "C" fn pthread_rwlockattr_init(attr: *mut pthread_rwlockattr_t) -> c_int {
4477 (*attr).__attr = [0; 2]; 0
4478}
4479#[no_mangle]
4480pub unsafe extern "C" fn pthread_rwlockattr_destroy(_attr: *mut pthread_rwlockattr_t) -> c_int { 0 }
4481#[no_mangle]
4482pub unsafe extern "C" fn pthread_rwlockattr_setpshared(attr: *mut pthread_rwlockattr_t, p: c_int) -> c_int {
4483 if (p as c_uint) > 1 { return EINVAL; }
4484 (*attr).__attr[0] = ((*attr).__attr[0] & !128) | ((p as c_uint) << 7); 0
4485}
4486#[no_mangle]
4487pub unsafe extern "C" fn pthread_rwlockattr_getpshared(attr: *const pthread_rwlockattr_t, p: *mut c_int) -> c_int {
4488 *p = (((*attr).__attr[0] >> 7) & 1) as c_int; 0
4489}
4490
4491unsafe fn rwlock_tryrdlock(rw: *mut pthread_rwlock_t) -> c_int {
4493 loop {
4494 let val = a_load(&raw const (*rw).__i[0]);
4495 let cnt = val & 0x7fffffff;
4496 if cnt == 0x7fffffff { return EBUSY; }
4497 if cnt == 0x7ffffffe { return EAGAIN; }
4498 if a_cas(&raw mut (*rw).__i[0], val, val + 1) == val { return 0; }
4499 }
4500}
4501unsafe fn rwlock_trywrlock(rw: *mut pthread_rwlock_t) -> c_int {
4502 if a_cas(&raw mut (*rw).__i[0], 0, 0x7fffffff) == 0 { 0 } else { EBUSY }
4503}
4504unsafe fn rwlock_timedrdlock(rw: *mut pthread_rwlock_t, abs_timeout: *const timespec) -> c_int {
4505 let r = rwlock_tryrdlock(rw);
4506 if r != EBUSY { return r; }
4507 let mut spins = 100;
4508 while spins > 0 { let r = rwlock_tryrdlock(rw); if r != EBUSY { return r; } core::hint::spin_loop(); spins -= 1; }
4509 loop {
4510 let r = rwlock_tryrdlock(rw);
4511 if r != EBUSY { return r; }
4512 let val = a_load(&raw const (*rw).__i[0]);
4513 if val & 0x7fffffff != 0x7fffffff { continue; }
4514 a_fetch_add(&raw mut (*rw).__i[1], 1);
4515 a_cas(&raw mut (*rw).__i[0], val, val | (1i32 << 31));
4516 let e = futex_timedwait(&raw mut (*rw).__i[0], val | (1i32 << 31), abs_timeout);
4517 a_fetch_sub(&raw mut (*rw).__i[1], 1);
4518 if e != 0 && e != EINTR { return e; }
4519 }
4520}
4521unsafe fn rwlock_timedwrlock(rw: *mut pthread_rwlock_t, abs_timeout: *const timespec) -> c_int {
4522 let r = rwlock_trywrlock(rw);
4523 if r != EBUSY { return r; }
4524 let mut spins = 100;
4525 while spins > 0 { let r = rwlock_trywrlock(rw); if r != EBUSY { return r; } core::hint::spin_loop(); spins -= 1; }
4526 loop {
4527 let r = rwlock_trywrlock(rw);
4528 if r != EBUSY { return r; }
4529 let val = a_load(&raw const (*rw).__i[0]);
4530 if val == 0 { continue; }
4531 a_fetch_add(&raw mut (*rw).__i[1], 1);
4532 a_cas(&raw mut (*rw).__i[0], val, val | (1i32 << 31));
4533 let e = futex_timedwait(&raw mut (*rw).__i[0], val | (1i32 << 31), abs_timeout);
4534 a_fetch_sub(&raw mut (*rw).__i[1], 1);
4535 if e != 0 && e != EINTR { return e; }
4536 }
4537}
4538
4539#[no_mangle]
4540pub unsafe extern "C" fn pthread_rwlock_init(rw: *mut pthread_rwlock_t, attr: *const pthread_rwlockattr_t) -> c_int {
4541 core::ptr::write_bytes(rw, 0, 1);
4542 if !attr.is_null() { (*rw).__i[2] = (*attr).__attr[0] as c_int & 128; }
4543 0
4544}
4545#[no_mangle]
4546pub unsafe extern "C" fn pthread_rwlock_destroy(_rw: *mut pthread_rwlock_t) -> c_int { 0 }
4547#[no_mangle]
4548pub unsafe extern "C" fn pthread_rwlock_rdlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_timedrdlock(rw, core::ptr::null()) }
4549#[no_mangle]
4550pub unsafe extern "C" fn pthread_rwlock_tryrdlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_tryrdlock(rw) }
4551#[no_mangle]
4552pub unsafe extern "C" fn pthread_rwlock_timedrdlock(rw: *mut pthread_rwlock_t, t: *const timespec) -> c_int { rwlock_timedrdlock(rw, t) }
4553#[no_mangle]
4554pub unsafe extern "C" fn pthread_rwlock_wrlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_timedwrlock(rw, core::ptr::null()) }
4555#[no_mangle]
4556pub unsafe extern "C" fn pthread_rwlock_trywrlock(rw: *mut pthread_rwlock_t) -> c_int { rwlock_trywrlock(rw) }
4557#[no_mangle]
4558pub unsafe extern "C" fn pthread_rwlock_timedwrlock(rw: *mut pthread_rwlock_t, t: *const timespec) -> c_int { rwlock_timedwrlock(rw, t) }
4559#[no_mangle]
4560pub unsafe extern "C" fn pthread_rwlock_unlock(rw: *mut pthread_rwlock_t) -> c_int {
4561 loop {
4562 let val = a_load(&raw const (*rw).__i[0]);
4563 let cnt = val & 0x7fffffff;
4564 let new_val = if cnt == 0x7fffffff || cnt == 1 { 0 } else { val - 1 };
4565 if a_cas(&raw mut (*rw).__i[0], val, new_val) == val {
4566 if new_val == 0 && (a_load(&raw const (*rw).__i[1]) > 0 || val < 0) {
4567 futex_wake(&raw mut (*rw).__i[0], cnt);
4568 }
4569 return 0;
4570 }
4571 }
4572}
4573
4574#[no_mangle]
4576pub unsafe extern "C" fn pthread_barrierattr_init(attr: *mut pthread_barrierattr_t) -> c_int { (*attr).__attr = 0; 0 }
4577#[no_mangle]
4578pub unsafe extern "C" fn pthread_barrierattr_destroy(_attr: *mut pthread_barrierattr_t) -> c_int { 0 }
4579#[no_mangle]
4580pub unsafe extern "C" fn pthread_barrierattr_setpshared(attr: *mut pthread_barrierattr_t, p: c_int) -> c_int {
4581 if (p as c_uint) > 1 { return EINVAL; }
4582 (*attr).__attr = p as c_uint; 0
4583}
4584#[no_mangle]
4585pub unsafe extern "C" fn pthread_barrierattr_getpshared(attr: *const pthread_barrierattr_t, p: *mut c_int) -> c_int {
4586 *p = (*attr).__attr as c_int; 0
4587}
4588
4589#[no_mangle]
4591pub unsafe extern "C" fn pthread_barrier_init(b: *mut pthread_barrier_t, _attr: *const pthread_barrierattr_t, count: c_uint) -> c_int {
4592 if count == 0 { return EINVAL; }
4593 core::ptr::write_bytes(b, 0, 1);
4594 (*b).__i[2] = count as c_int - 1;
4595 0
4596}
4597#[no_mangle]
4598pub unsafe extern "C" fn pthread_barrier_destroy(_b: *mut pthread_barrier_t) -> c_int { 0 }
4599#[no_mangle]
4600pub unsafe extern "C" fn pthread_barrier_wait(b: *mut pthread_barrier_t) -> c_int {
4601 let limit = (*b).__i[2];
4602 if limit == 0 { return PTHREAD_BARRIER_SERIAL_THREAD; }
4603 spinlock_lock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4604 let arrived = a_load(&raw const (*b).__i[3]) + 1;
4605 a_store(&raw mut (*b).__i[3], arrived);
4606 if arrived > limit {
4607 a_store(&raw mut (*b).__i[3], 0);
4608 let gen = a_load(&raw const (*b).__i[4]);
4609 a_store(&raw mut (*b).__i[4], gen + 1);
4610 spinlock_unlock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4611 futex_wake(&raw mut (*b).__i[4], -1);
4612 return PTHREAD_BARRIER_SERIAL_THREAD;
4613 }
4614 let gen = a_load(&raw const (*b).__i[4]);
4615 spinlock_unlock(&raw mut (*b).__i[0], &raw mut (*b).__i[1]);
4616 while a_load(&raw const (*b).__i[4]) == gen {
4617 futex_wait(&raw mut (*b).__i[4], gen);
4618 }
4619 0
4620}
4621
4622#[no_mangle]
4624pub unsafe extern "C" fn pthread_spin_init(s: *mut pthread_spinlock_t, _pshared: c_int) -> c_int { a_store(s, 0); 0 }
4625#[no_mangle]
4626pub unsafe extern "C" fn pthread_spin_destroy(_s: *mut pthread_spinlock_t) -> c_int { 0 }
4627#[no_mangle]
4628pub unsafe extern "C" fn pthread_spin_lock(s: *mut pthread_spinlock_t) -> c_int {
4629 while a_load(s) != 0 || a_cas(s, 0, EBUSY) != 0 { core::hint::spin_loop(); }
4630 0
4631}
4632#[no_mangle]
4633pub unsafe extern "C" fn pthread_spin_trylock(s: *mut pthread_spinlock_t) -> c_int { a_cas(s, 0, EBUSY) }
4634#[no_mangle]
4635pub unsafe extern "C" fn pthread_spin_unlock(s: *mut pthread_spinlock_t) -> c_int { a_store(s, 0); 0 }
4636
4637#[no_mangle]
4639pub unsafe extern "C" fn sem_init(sem: *mut sem_t, pshared: c_int, value: c_uint) -> c_int {
4640 if value > SEM_VALUE_MAX as c_uint { return EINVAL; }
4641 (*sem).__val[0] = value as c_int;
4642 (*sem).__val[1] = 0;
4643 (*sem).__val[2] = if pshared != 0 { 0 } else { 128 };
4644 0
4645}
4646#[no_mangle]
4647pub unsafe extern "C" fn sem_destroy(_sem: *mut sem_t) -> c_int { 0 }
4648
4649unsafe fn sem_trywait_internal(sem: *mut sem_t) -> c_int {
4650 loop {
4651 let val = a_load(&raw const (*sem).__val[0]);
4652 if val & SEM_VALUE_MAX == 0 { return EAGAIN; }
4653 if a_cas(&raw mut (*sem).__val[0], val, val - 1) == val { return 0; }
4654 }
4655}
4656
4657#[no_mangle]
4658pub unsafe extern "C" fn sem_trywait(sem: *mut sem_t) -> c_int {
4659 if sem_trywait_internal(sem) == 0 { 0 } else { ERRNO!() = EAGAIN; -1 }
4660}
4661#[no_mangle]
4662pub unsafe extern "C" fn sem_wait(sem: *mut sem_t) -> c_int {
4663 pthread_testcancel();
4664 if sem_trywait_internal(sem) == 0 { return 0; }
4665 let mut spins = 100;
4666 while spins > 0 { if sem_trywait_internal(sem) == 0 { return 0; } core::hint::spin_loop(); spins -= 1; }
4667 loop {
4668 pthread_testcancel();
4669 if sem_trywait_internal(sem) == 0 { return 0; }
4670 let val = a_load(&raw const (*sem).__val[0]);
4671 if val & SEM_VALUE_MAX != 0 { continue; }
4672 a_cas(&raw mut (*sem).__val[0], val, val | (1i32 << 31));
4673 a_fetch_add(&raw mut (*sem).__val[1], 1);
4674 futex_wait(&raw mut (*sem).__val[0], 1i32 << 31);
4675 a_fetch_sub(&raw mut (*sem).__val[1], 1);
4676 }
4677}
4678#[no_mangle]
4679pub unsafe extern "C" fn sem_timedwait(sem: *mut sem_t, abs_timeout: *const timespec) -> c_int {
4680 pthread_testcancel();
4681 if sem_trywait_internal(sem) == 0 { return 0; }
4682 let mut spins = 100;
4683 while spins > 0 { if sem_trywait_internal(sem) == 0 { return 0; } core::hint::spin_loop(); spins -= 1; }
4684 loop {
4685 pthread_testcancel();
4686 if sem_trywait_internal(sem) == 0 { return 0; }
4687 let val = a_load(&raw const (*sem).__val[0]);
4688 if val & SEM_VALUE_MAX != 0 { continue; }
4689 a_cas(&raw mut (*sem).__val[0], val, val | (1i32 << 31));
4690 a_fetch_add(&raw mut (*sem).__val[1], 1);
4691 let e = futex_timedwait(&raw mut (*sem).__val[0], 1i32 << 31, abs_timeout);
4692 a_fetch_sub(&raw mut (*sem).__val[1], 1);
4693 if e != 0 && e != EINTR { ERRNO!() = e; return -1; }
4694 }
4695}
4696#[no_mangle]
4697pub unsafe extern "C" fn sem_post(sem: *mut sem_t) -> c_int {
4698 loop {
4699 let val = a_load(&raw const (*sem).__val[0]);
4700 if (val & SEM_VALUE_MAX) == SEM_VALUE_MAX { ERRNO!() = EOVERFLOW; return -1; }
4701 let mut new = val + 1;
4702 let waiters = a_load(&raw const (*sem).__val[1]);
4703 if waiters <= 1 { new &= !(1i32 << 31); }
4704 if a_cas(&raw mut (*sem).__val[0], val, new) == val {
4705 if val < 0 || waiters > 0 {
4706 futex_wake(&raw mut (*sem).__val[0], if waiters > 1 { 1 } else { -1 });
4707 }
4708 return 0;
4709 }
4710 }
4711}
4712#[no_mangle]
4713pub unsafe extern "C" fn sem_getvalue(sem: *mut sem_t, sval: *mut c_int) -> c_int {
4714 *sval = a_load(&raw const (*sem).__val[0]) & SEM_VALUE_MAX;
4715 0
4716}
4717
4718const NAME_MAX: usize = 255;
4723const SEM_NSEMS_MAX: usize = 256;
4724
4725static SEMTAB_LOCK: AtomicI32 = AtomicI32::new(0);
4727
4728struct SemEntry {
4729 ino: u64,
4730 sem: *mut sem_t,
4731 refcnt: u32,
4732}
4733
4734static mut SEMTAB: [SemEntry; SEM_NSEMS_MAX] = {
4736 const ZERO: SemEntry = SemEntry { ino: 0, sem: core::ptr::null_mut(), refcnt: 0 };
4737 [ZERO; SEM_NSEMS_MAX]
4738};
4739
4740unsafe fn semtab_lock() {
4741 while SEMTAB_LOCK.compare_exchange_weak(0, 1, Ordering::Acquire, Ordering::Relaxed).is_err() {
4742 core::hint::spin_loop();
4743 }
4744}
4745
4746unsafe fn semtab_unlock() {
4747 SEMTAB_LOCK.store(0, Ordering::Release);
4748}
4749
4750unsafe fn shm_mapname(name: *const c_char, buf: *mut u8) -> c_int {
4753 let mut p = name;
4754 while *p == b'/' as c_char { p = p.add(1); }
4756 let start = p;
4757 while *p != 0 && *p != b'/' as c_char { p = p.add(1); }
4759 let len = p.offset_from(start) as usize;
4760 if len == 0 || *p != 0 {
4762 ERRNO!() = EINVAL;
4763 return -1;
4764 }
4765 if len == 1 && *start == b'.' as c_char {
4766 ERRNO!() = EINVAL;
4767 return -1;
4768 }
4769 if len == 2 && *start == b'.' as c_char && *start.add(1) == b'.' as c_char {
4770 ERRNO!() = EINVAL;
4771 return -1;
4772 }
4773 if len > NAME_MAX {
4774 ERRNO!() = ENAMETOOLONG;
4775 return -1;
4776 }
4777 let prefix = b"/dev/shm/\0";
4779 let mut i = 0;
4780 while prefix[i] != 0 {
4781 *buf.add(i) = prefix[i];
4782 i += 1;
4783 }
4784 let mut j = 0;
4785 while j < len {
4786 *buf.add(i + j) = *start.add(j) as u8;
4787 j += 1;
4788 }
4789 *buf.add(i + j) = 0;
4790 (i + j) as c_int
4791}
4792
4793#[no_mangle]
4794pub unsafe extern "C" fn shm_open(name: *const c_char, flags: c_int, mode: mode_t) -> c_int {
4795 let mut buf = [0u8; 16 + NAME_MAX + 1];
4796 if shm_mapname(name, buf.as_mut_ptr()) < 0 { return -1; }
4797 let fd = sys_open(buf.as_ptr(), (flags | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, mode as i64);
4798 if fd < 0 { ERRNO!() = (-fd) as c_int; return -1; }
4799 fd as c_int
4800}
4801
4802#[no_mangle]
4803pub unsafe extern "C" fn shm_unlink(name: *const c_char) -> c_int {
4804 let mut buf = [0u8; 16 + NAME_MAX + 1];
4805 if shm_mapname(name, buf.as_mut_ptr()) < 0 { return -1; }
4806 let r = sys_unlink(buf.as_ptr());
4807 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
4808 0
4809}
4810
4811#[no_mangle]
4812pub unsafe extern "C" fn sem_open(name: *const c_char, flags: c_int, mut args: ...) -> *mut sem_t {
4813 let mut buf = [0u8; 16 + NAME_MAX + 1];
4814 if shm_mapname(name, buf.as_mut_ptr()).is_negative() {
4815 return core::ptr::null_mut(); }
4817
4818 let oflags = flags & (O_CREAT | O_EXCL);
4819
4820 semtab_lock();
4821
4822 let mut slot: c_int = -1;
4824 for i in 0..SEMTAB_LEN {
4825 if SEMTAB[i].sem.is_null() && slot < 0 { slot = i as c_int; }
4826 }
4827 if slot < 0 {
4828 ERRNO!() = EMFILE;
4829 semtab_unlock();
4830 return core::ptr::null_mut();
4831 }
4832 SEMTAB[slot as usize].sem = !0usize as *mut sem_t; semtab_unlock();
4835
4836 let mut mode: mode_t = 0;
4838 let mut value: c_uint = 0;
4839 if oflags & O_CREAT != 0 {
4840 mode = args.next_arg::<mode_t>() & 0o666;
4841 value = args.next_arg::<c_uint>();
4842 if value > SEM_VALUE_MAX as c_uint {
4843 ERRNO!() = EINVAL;
4844 semtab_lock();
4845 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4846 semtab_unlock();
4847 return core::ptr::null_mut();
4848 }
4849 }
4850
4851 if oflags != O_CREAT | O_EXCL {
4853 let fd = sys_open(buf.as_ptr(), (O_RDWR | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, 0);
4854 if fd >= 0 {
4855 let map = sys_mmap(
4856 core::ptr::null_mut(),
4857 core::mem::size_of::<sem_t>(),
4858 PROT_READ | PROT_WRITE,
4859 MAP_SHARED,
4860 fd as i32,
4861 0,
4862 );
4863 sys_close(fd);
4864 if map != MMAP_FAILED {
4865 let st_ino = get_ino(fd as c_int, buf.as_ptr());
4866 return sem_register(map as *mut sem_t, st_ino, slot);
4867 }
4868 }
4869 if oflags == 0 {
4870 semtab_lock();
4872 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4873 semtab_unlock();
4874 return core::ptr::null_mut();
4875 }
4876 }
4877
4878 let mut tmp = [0u8; 32];
4880 let tmpname = b"/dev/shm/tmp-XXXXXX\0";
4881 tmp[..tmpname.len()].copy_from_slice(tmpname);
4882 let mut ts: timespec = core::mem::zeroed();
4884 sys_clock_gettime(0, &mut ts);
4885 let mut n = ts.tv_nsec;
4887 let mut pos = tmpname.len() - 1;
4888 tmp[pos] = 0;
4889 pos -= 1;
4890 loop {
4891 tmp[pos] = b'0' + (n % 10) as u8;
4892 n /= 10;
4893 if n == 0 || pos == 0 { break; }
4894 pos -= 1;
4895 }
4896 let tmp_path = tmp.as_ptr();
4898
4899 let mut newsem: sem_t = core::mem::zeroed();
4900 newsem.__val[0] = value as c_int;
4901 newsem.__val[1] = 0;
4902 newsem.__val[2] = 128; loop {
4905 let fd = sys_open(tmp_path as *const u8, (O_RDWR | O_CREAT | O_EXCL | O_CLOEXEC | O_NONBLOCK) as i64, mode as i64);
4906 if fd < 0 {
4907 if (-fd) as c_int == EEXIST { continue; }
4908 semtab_lock();
4909 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4910 semtab_unlock();
4911 return core::ptr::null_mut();
4912 }
4913 let written = sys_write(fd, &newsem as *const sem_t as *const u8, core::mem::size_of::<sem_t>());
4914 if written != core::mem::size_of::<sem_t>() as i64 {
4915 sys_close(fd);
4916 sys_unlink(tmp_path);
4917 semtab_lock();
4918 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4919 semtab_unlock();
4920 return core::ptr::null_mut();
4921 }
4922 let map = sys_mmap(
4923 core::ptr::null_mut(),
4924 core::mem::size_of::<sem_t>(),
4925 PROT_READ | PROT_WRITE,
4926 MAP_SHARED,
4927 fd as i32,
4928 0,
4929 );
4930 sys_close(fd);
4931 if map == MMAP_FAILED {
4932 sys_unlink(tmp_path);
4933 semtab_lock();
4934 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4935 semtab_unlock();
4936 return core::ptr::null_mut();
4937 }
4938 let r = sys_linkat(AT_FDCWD, tmp_path, AT_FDCWD, buf.as_ptr(), 0);
4940 let e = if r < 0 { (-r) as c_int } else { 0 };
4941 sys_unlink(tmp_path);
4942 if e == 0 {
4943 let st_ino = get_ino(-1, buf.as_ptr());
4944 return sem_register(map as *mut sem_t, st_ino, slot);
4945 }
4946 sys_munmap(map, core::mem::size_of::<sem_t>());
4947 if e != EEXIST || oflags == O_CREAT | O_EXCL {
4948 ERRNO!() = e;
4949 semtab_lock();
4950 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4951 semtab_unlock();
4952 return core::ptr::null_mut();
4953 }
4954 break;
4956 }
4957
4958 let fd = sys_open(buf.as_ptr(), (O_RDWR | O_NOFOLLOW | O_CLOEXEC | O_NONBLOCK) as i64, 0);
4960 if fd < 0 {
4961 semtab_lock();
4962 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4963 semtab_unlock();
4964 return core::ptr::null_mut();
4965 }
4966 let map = sys_mmap(
4967 core::ptr::null_mut(),
4968 core::mem::size_of::<sem_t>(),
4969 PROT_READ | PROT_WRITE,
4970 MAP_SHARED,
4971 fd as i32,
4972 0,
4973 );
4974 sys_close(fd);
4975 if map == MMAP_FAILED {
4976 semtab_lock();
4977 SEMTAB[slot as usize].sem = core::ptr::null_mut();
4978 semtab_unlock();
4979 return core::ptr::null_mut();
4980 }
4981 let st_ino = get_ino(-1, buf.as_ptr());
4982 sem_register(map as *mut sem_t, st_ino, slot)
4983}
4984
4985unsafe fn get_ino(_fd_hint: c_int, path: *const u8) -> u64 {
4986 let mut st: Stat = core::mem::zeroed();
4987 if sys_newfstatat(AT_FDCWD, path as *const c_char, &mut st as *mut Stat as *mut u8, 0) == 0 {
4988 st.st_ino
4989 } else {
4990 0
4991 }
4992}
4993
4994unsafe fn sem_register(map: *mut sem_t, ino: u64, slot_hint: c_int) -> *mut sem_t {
4995 semtab_lock();
4996 for i in 0..SEMTAB_LEN {
4998 if SEMTAB[i].ino == ino && !SEMTAB[i].sem.is_null() && SEMTAB[i].sem != !0usize as *mut sem_t {
4999 sys_munmap(map as *mut u8, core::mem::size_of::<sem_t>());
5001 SEMTAB[slot_hint as usize].sem = core::ptr::null_mut();
5002 SEMTAB[i].refcnt += 1;
5003 let ret = SEMTAB[i].sem;
5004 semtab_unlock();
5005 return ret;
5006 }
5007 }
5008 SEMTAB[slot_hint as usize].sem = map;
5010 SEMTAB[slot_hint as usize].ino = ino;
5011 SEMTAB[slot_hint as usize].refcnt = 1;
5012 semtab_unlock();
5013 map
5014}
5015
5016const SEMTAB_LEN: usize = SEM_NSEMS_MAX;
5017
5018#[no_mangle]
5019pub unsafe extern "C" fn sem_close(sem: *mut sem_t) -> c_int {
5020 semtab_lock();
5021 for i in 0..SEMTAB_LEN {
5022 if SEMTAB[i].sem == sem {
5023 SEMTAB[i].refcnt -= 1;
5024 if SEMTAB[i].refcnt == 0 {
5025 SEMTAB[i].sem = core::ptr::null_mut();
5026 SEMTAB[i].ino = 0;
5027 semtab_unlock();
5028 sys_munmap(sem as *mut u8, core::mem::size_of::<sem_t>());
5029 return 0;
5030 }
5031 semtab_unlock();
5032 return 0;
5033 }
5034 }
5035 semtab_unlock();
5036 0
5037}
5038
5039#[no_mangle]
5040pub unsafe extern "C" fn sem_unlink(name: *const c_char) -> c_int {
5041 shm_unlink(name)
5042}
5043
5044#[no_mangle]
5046pub unsafe extern "C" fn pthread_once(control: *mut pthread_once_t, init_routine: Option<unsafe extern "C" fn()>) -> c_int {
5047 if a_load(control) == 2 { return 0; }
5048 loop {
5049 match a_cas(control, 0, 1) {
5050 0 => {
5051 if let Some(f) = init_routine { f(); }
5052 if a_swap(control, 2) == 3 { futex_wake(control, -1); }
5053 return 0;
5054 }
5055 1 => { a_cas(control, 1, 3); }
5056 3 => { futex_wait(control, 3); }
5057 _ => { return 0; }
5058 }
5059 }
5060}
5061
5062#[no_mangle]
5064pub unsafe extern "C" fn pthread_key_create(key: *mut pthread_key_t, dtor: Option<unsafe extern "C" fn(*mut c_void)>) -> c_int {
5065 let start = NEXT_KEY.load(Ordering::Relaxed);
5066 let mut j = start;
5067 loop {
5068 if KEY_DTORS[j].is_none() {
5069 KEY_DTORS[j] = dtor;
5070 NEXT_KEY.store((j + 1) % PTHREAD_KEYS_MAX, Ordering::Relaxed);
5071 *key = j as pthread_key_t;
5072 return 0;
5073 }
5074 j = (j + 1) % PTHREAD_KEYS_MAX;
5075 if j == start { return EAGAIN; }
5076 }
5077}
5078#[no_mangle]
5079pub unsafe extern "C" fn pthread_key_delete(key: pthread_key_t) -> c_int {
5080 KEY_DTORS[key as usize] = None;
5081 for i in 0..MAX_THREADS {
5082 if THREADS[i].tid > 0 { THREADS[i].tsd[key as usize] = core::ptr::null_mut(); }
5083 }
5084 0
5085}
5086#[no_mangle]
5087pub unsafe extern "C" fn pthread_getspecific(key: pthread_key_t) -> *mut c_void {
5088 if let Some(slot) = find_thread() { slot.tsd[key as usize] } else { core::ptr::null_mut() }
5089}
5090#[no_mangle]
5091pub unsafe extern "C" fn pthread_setspecific(key: pthread_key_t, value: *const c_void) -> c_int {
5092 if let Some(slot) = find_thread() {
5093 slot.tsd[key as usize] = value as *mut c_void;
5094 0
5095 } else { EINVAL }
5096}
5097
5098unsafe fn run_cleanup_handlers(slot: &mut Thread) {
5100 let mut cb = slot.cancelbuf;
5101 while !cb.is_null() {
5102 let cur = &*cb;
5103 let f = cur.__f;
5104 let x = cur.__x;
5105 cb = cur.__next;
5106 if let Some(func) = f {
5107 func(x);
5108 }
5109 }
5110 slot.cancelbuf = core::ptr::null_mut();
5111}
5112
5113unsafe fn do_cancel() -> ! {
5114 if let Some(slot) = find_thread() {
5115 run_cleanup_handlers(slot);
5116 slot.result = !0usize as *mut c_void; slot.detach_state = DT_EXITED;
5118 futex_wake(&raw mut slot.detach_state, 1);
5119 }
5120 sys_exit_thread(0);
5121}
5122
5123extern "C" fn cancel_handler(_sig: c_int) {
5124 unsafe {
5125 if let Some(slot) = find_thread() {
5126 if slot.cancel != 0
5130 && slot.cancel_state == PTHREAD_CANCEL_ENABLE
5131 && slot.cancel_type == PTHREAD_CANCEL_ASYNCHRONOUS
5132 {
5133 do_cancel();
5134 }
5135 }
5136 }
5137}
5138
5139static CANCEL_INIT: AtomicI32 = AtomicI32::new(0);
5140
5141unsafe fn ensure_cancel_handler() {
5142 if CANCEL_INIT.swap(1, Ordering::AcqRel) == 0 {
5143 let act = KSigAction {
5144 sa_handler: cancel_handler as *const () as usize,
5145 sa_flags: SA_RESTORER,
5146 sa_restorer: sig_restorer as *const () as usize,
5147 sa_mask: [!0u64],
5148 };
5149 sys_rt_sigaction(SIGCANCEL, &act as *const KSigAction, core::ptr::null_mut(), 8);
5150 }
5151}
5152
5153#[no_mangle]
5154pub unsafe extern "C" fn pthread_cancel(thread: PthreadT) -> c_int {
5155 let slot = thread as *mut Thread;
5156 if slot.is_null() { return EINVAL; }
5157 ensure_cancel_handler();
5158 a_store(&raw mut (*slot).cancel, 1);
5159 let tid = (*slot).tid;
5160 if tid > 0 {
5161 sys_tgkill(sys_getpid() as c_int, tid, SIGCANCEL);
5162 }
5163 0
5164}
5165#[no_mangle]
5166pub unsafe extern "C" fn pthread_setcancelstate(state: c_int, oldstate: *mut c_int) -> c_int {
5167 if state != PTHREAD_CANCEL_ENABLE && state != PTHREAD_CANCEL_DISABLE { return EINVAL; }
5168 if let Some(slot) = find_thread() {
5169 if !oldstate.is_null() { *oldstate = slot.cancel_state; }
5170 slot.cancel_state = state;
5171 0
5172 } else { EINVAL }
5173}
5174#[no_mangle]
5175pub unsafe extern "C" fn pthread_setcanceltype(type_: c_int, oldtype: *mut c_int) -> c_int {
5176 if type_ != PTHREAD_CANCEL_DEFERRED && type_ != PTHREAD_CANCEL_ASYNCHRONOUS { return EINVAL; }
5177 if let Some(slot) = find_thread() {
5178 if !oldtype.is_null() { *oldtype = slot.cancel_type; }
5179 slot.cancel_type = type_;
5180 0
5181 } else { EINVAL }
5182}
5183#[no_mangle]
5184pub unsafe extern "C" fn pthread_testcancel() {
5185 if let Some(slot) = find_thread() {
5186 if slot.cancel != 0 && slot.cancel_state == PTHREAD_CANCEL_ENABLE {
5187 do_cancel();
5188 }
5189 }
5190}
5191
5192#[no_mangle]
5193pub unsafe extern "C" fn _pthread_cleanup_push(cb: *mut __ptcb, f: Option<unsafe extern "C" fn(*mut c_void)>, x: *mut c_void) {
5194 (*cb).__f = f;
5195 (*cb).__x = x;
5196 if let Some(slot) = find_thread() {
5197 (*cb).__next = slot.cancelbuf;
5198 slot.cancelbuf = cb;
5199 } else {
5200 (*cb).__next = core::ptr::null_mut();
5201 }
5202}
5203
5204#[no_mangle]
5205pub unsafe extern "C" fn _pthread_cleanup_pop(cb: *mut __ptcb, run: c_int) {
5206 if let Some(slot) = find_thread() {
5207 slot.cancelbuf = (*cb).__next;
5208 }
5209 if run != 0 {
5210 if let Some(f) = (*cb).__f {
5211 f((*cb).__x);
5212 }
5213 }
5214}
5215
5216#[no_mangle]
5217pub unsafe extern "C" fn pthread_kill(thread: PthreadT, sig: c_int) -> c_int {
5218 let slot = thread as *mut Thread;
5219 if slot.is_null() { return EINVAL; }
5220 let tid = (*slot).tid;
5221 if tid <= 0 { return EINVAL; }
5222 if sys_tgkill(sys_getpid() as c_int, tid, sig) < 0 { -1 } else { 0 }
5223}
5224
5225#[no_mangle]
5226pub unsafe extern "C" fn pthread_sigmask(how: c_int, set: *const SigSetT, oldset: *mut SigSetT) -> c_int {
5227 sigprocmask(how, set, oldset)
5228}
5229
5230
5231#[repr(C)]
5232pub struct lconv {
5233 pub decimal_point: *mut c_char,
5234 pub thousands_sep: *mut c_char,
5235 pub grouping: *mut c_char,
5236 pub int_curr_symbol: *mut c_char,
5237 pub currency_symbol: *mut c_char,
5238 pub mon_decimal_point: *mut c_char,
5239 pub mon_thousands_sep: *mut c_char,
5240 pub mon_grouping: *mut c_char,
5241 pub positive_sign: *mut c_char,
5242 pub negative_sign: *mut c_char,
5243 pub int_frac_digits: c_char,
5244 pub frac_digits: c_char,
5245 pub p_cs_precedes: c_char,
5246 pub p_sep_by_space: c_char,
5247 pub n_cs_precedes: c_char,
5248 pub n_sep_by_space: c_char,
5249 pub p_sign_posn: c_char,
5250 pub n_sign_posn: c_char,
5251 pub int_p_cs_precedes: c_char,
5252 pub int_p_sep_by_space: c_char,
5253 pub int_n_cs_precedes: c_char,
5254 pub int_n_sep_by_space: c_char,
5255 pub int_p_sign_posn: c_char,
5256 pub int_n_sign_posn: c_char,
5257}
5258
5259static UTF8_NAME: [u8; 6] = [b'U', b'T', b'F', b'-', b'8', 0];
5260static C_NAME: [u8; 2] = [b'C', 0];
5261static mut LOCALE_NAME: *const c_char = C_NAME.as_ptr() as *const c_char;
5262static mut LOCALE_CTYPE_UTF8: bool = true;
5263static mut EMPTY_STR: [c_char; 1] = [0];
5264static mut DECIMAL_POINT: [c_char; 2] = [b'.' as c_char, 0];
5265static mut LCONV: lconv = lconv {
5266 decimal_point: core::ptr::null_mut(),
5267 thousands_sep: core::ptr::null_mut(),
5268 grouping: core::ptr::null_mut(),
5269 int_curr_symbol: core::ptr::null_mut(),
5270 currency_symbol: core::ptr::null_mut(),
5271 mon_decimal_point: core::ptr::null_mut(),
5272 mon_thousands_sep: core::ptr::null_mut(),
5273 mon_grouping: core::ptr::null_mut(),
5274 positive_sign: core::ptr::null_mut(),
5275 negative_sign: core::ptr::null_mut(),
5276 int_frac_digits: (-1i32) as c_char,
5277 frac_digits: (-1i32) as c_char,
5278 p_cs_precedes: (-1i32) as c_char,
5279 p_sep_by_space: (-1i32) as c_char,
5280 n_cs_precedes: (-1i32) as c_char,
5281 n_sep_by_space: (-1i32) as c_char,
5282 p_sign_posn: (-1i32) as c_char,
5283 n_sign_posn: (-1i32) as c_char,
5284 int_p_cs_precedes: (-1i32) as c_char,
5285 int_p_sep_by_space: (-1i32) as c_char,
5286 int_n_cs_precedes: (-1i32) as c_char,
5287 int_n_sep_by_space: (-1i32) as c_char,
5288 int_p_sign_posn: (-1i32) as c_char,
5289 int_n_sign_posn: (-1i32) as c_char,
5290};
5291
5292unsafe fn cstr_contains_ci(s: *const u8, needle: &[u8]) -> bool {
5293 let len = strlen(s as *const c_char) as usize;
5294 let s_slice = core::slice::from_raw_parts(s, len);
5295 if needle.len() > len { return false; }
5296 for i in 0..=len - needle.len() {
5297 if s_slice[i..i + needle.len()].eq_ignore_ascii_case(needle) {
5298 return true;
5299 }
5300 }
5301 false
5302}
5303
5304#[no_mangle]
5305pub unsafe extern "C" fn setlocale(_category: c_int, locale: *const c_char) -> *mut c_char {
5306 if locale.is_null() || *locale == 0 {
5307 return LOCALE_NAME as *mut c_char;
5308 }
5309 let name = locale as *const u8;
5310 if strcmp(name, b"C\0".as_ptr()) == 0 || strcmp(name, b"POSIX\0".as_ptr()) == 0 {
5311 LOCALE_CTYPE_UTF8 = false;
5312 return LOCALE_NAME as *mut c_char;
5313 }
5314 if cstr_contains_ci(name, b"UTF-8") || cstr_contains_ci(name, b"UTF8") {
5315 LOCALE_CTYPE_UTF8 = true;
5316 return LOCALE_NAME as *mut c_char;
5317 }
5318 core::ptr::null_mut()
5319}
5320
5321#[no_mangle]
5322pub unsafe extern "C" fn localeconv() -> *mut lconv {
5323 let empty = core::ptr::addr_of_mut!(EMPTY_STR) as *mut c_char;
5324 let lconv = core::ptr::addr_of_mut!(LCONV);
5325 (*lconv).decimal_point = core::ptr::addr_of_mut!(DECIMAL_POINT) as *mut c_char;
5326 (*lconv).thousands_sep = empty;
5327 (*lconv).grouping = empty;
5328 (*lconv).int_curr_symbol = empty;
5329 (*lconv).currency_symbol = empty;
5330 (*lconv).mon_decimal_point = empty;
5331 (*lconv).mon_thousands_sep = empty;
5332 (*lconv).mon_grouping = empty;
5333 (*lconv).positive_sign = empty;
5334 (*lconv).negative_sign = empty;
5335 lconv
5336}
5337
5338pub type locale_t = *mut c_void;
5339static mut CURRENT_LOCALE: locale_t = LC_GLOBAL_LOCALE;
5340
5341static mut C_LOCALE_STORAGE: c_int = 0;
5342const C_LOCALE: locale_t = core::ptr::addr_of_mut!(C_LOCALE_STORAGE) as locale_t;
5343const LC_GLOBAL_LOCALE: locale_t = usize::MAX as locale_t;
5344
5345#[no_mangle]
5346pub unsafe extern "C" fn newlocale(_mask: c_int, name: *const c_char, base: locale_t) -> locale_t {
5347 if !name.is_null() && *name != 0 {
5348 let n = name as *const u8;
5349 if strcmp(n, b"C\0".as_ptr()) != 0
5350 && strcmp(n, b"POSIX\0".as_ptr()) != 0
5351 {
5352 return core::ptr::null_mut();
5353 }
5354 }
5355 if base.is_null() || base == C_LOCALE || base == LC_GLOBAL_LOCALE {
5356 C_LOCALE
5357 } else {
5358 core::ptr::null_mut()
5359 }
5360}
5361
5362#[no_mangle]
5363pub unsafe extern "C" fn freelocale(_loc: locale_t) {}
5364
5365#[no_mangle]
5366pub unsafe extern "C" fn uselocale(loc: locale_t) -> locale_t {
5367 let old = CURRENT_LOCALE;
5368 if !loc.is_null() {
5369 CURRENT_LOCALE = loc;
5370 }
5371 old
5372}
5373
5374#[no_mangle]
5375pub unsafe extern "C" fn duplocale(loc: locale_t) -> locale_t {
5376 if loc.is_null() {
5377 return core::ptr::null_mut();
5378 }
5379 C_LOCALE
5380}
5381
5382const NL_ITEM_CODESET: c_int = 14;
5383const NL_ITEM_RADIXCHAR: c_int = 0x10000;
5384const NL_ITEM_THOUSEP: c_int = 0x10001;
5385const NL_ITEM_YESEXPR: c_int = 0x50000;
5386const NL_ITEM_NOEXPR: c_int = 0x50001;
5387
5388const C_TIME_STRINGS: &[u8] = b"Sun\0Mon\0Tue\0Wed\0Thu\0Fri\0Sat\0\
5389Sunday\0Monday\0Tuesday\0Wednesday\0Thursday\0Friday\0Saturday\0\
5390Jan\0Feb\0Mar\0Apr\0May\0Jun\0Jul\0Aug\0Sep\0Oct\0Nov\0Dec\0\
5391January\0February\0March\0April\0May\0June\0July\0August\0\
5392September\0October\0November\0December\0\
5393AM\0PM\0\
5394%a %b %e %T %Y\0%m/%d/%y\0%H:%M:%S\0%I:%M:%S %p\0\
5395\0\0%m/%d/%y\00123456789\0%a %b %e %T %Y\0%H:%M:%S\0";
5396
5397const C_NUMERIC_STRINGS: &[u8] = b".\0\0";
5398const C_MESSAGES_STRINGS: &[u8] = b"^[yY]\0^[nN]\0";
5399
5400unsafe fn langinfo_str(table: *const u8, mut idx: c_int) -> *mut c_char {
5401 let mut p = table;
5402 while idx > 0 {
5403 while *p != 0 { p = p.add(1); }
5404 p = p.add(1);
5405 idx -= 1;
5406 }
5407 p as *mut c_char
5408}
5409
5410#[no_mangle]
5411pub unsafe extern "C" fn nl_langinfo(item: c_int) -> *mut c_char {
5412 if item == NL_ITEM_CODESET {
5413 return if LOCALE_CTYPE_UTF8 {
5414 b"UTF-8\0".as_ptr() as *mut c_char
5415 } else {
5416 b"US-ASCII\0".as_ptr() as *mut c_char
5417 };
5418 }
5419 let cat = item >> 16;
5420 let idx = item & 0xFFFF;
5421 match cat {
5422 1 => {
5423 if idx > 1 { return b"\0".as_ptr() as *mut c_char; }
5424 langinfo_str(C_NUMERIC_STRINGS.as_ptr(), idx)
5425 }
5426 2 => {
5427 if idx > 49 { return b"\0".as_ptr() as *mut c_char; }
5428 langinfo_str(C_TIME_STRINGS.as_ptr(), idx)
5429 }
5430 5 => {
5431 if idx > 1 { return b"\0".as_ptr() as *mut c_char; }
5432 langinfo_str(C_MESSAGES_STRINGS.as_ptr(), idx)
5433 }
5434 _ => b"\0".as_ptr() as *mut c_char,
5435 }
5436}
5437
5438pub type nl_catd = *mut c_void;
5439
5440#[no_mangle]
5441pub unsafe extern "C" fn catopen(_name: *const c_char, _oflag: c_int) -> nl_catd {
5442 !0usize as nl_catd
5443}
5444
5445#[no_mangle]
5446pub unsafe extern "C" fn catclose(_catd: nl_catd) -> c_int { 0 }
5447
5448#[no_mangle]
5449pub unsafe extern "C" fn catgets(catd: nl_catd, _set_id: c_int, _msg_id: c_int, s: *const c_char) -> *mut c_char {
5450 if catd == !0usize as nl_catd { return s as *mut c_char; }
5451 s as *mut c_char
5452}
5453
5454pub type IconvT = *mut c_void;
5455
5456const ENC_UTF8: i32 = 1;
5457const ENC_UTF16LE: i32 = 2;
5458const ENC_UTF16BE: i32 = 3;
5459const ENC_UTF32LE: i32 = 4;
5460const ENC_UTF32BE: i32 = 5;
5461const ENC_WCHAR_T: i32 = 6;
5462const ENC_ASCII: i32 = 7;
5463const ENC_LATIN1: i32 = 8;
5464const ENC_WIN1252: i32 = 9;
5465const ENC_WIN1251: i32 = 10;
5466const ENC_KOI8R: i32 = 11;
5467const ENC_GBK: i32 = 12;
5468const ENC_GB2312: i32 = 13;
5469const ENC_BIG5: i32 = 14;
5470const ENC_EUCJP: i32 = 15;
5471const ENC_SHIFTJIS: i32 = 16;
5472const ENC_ISO8859_2: i32 = 17;
5473const ENC_ISO8859_3: i32 = 18;
5474const ENC_ISO8859_4: i32 = 19;
5475const ENC_ISO8859_5: i32 = 20;
5476const ENC_ISO8859_6: i32 = 21;
5477const ENC_ISO8859_7: i32 = 22;
5478const ENC_ISO8859_8: i32 = 23;
5479const ENC_ISO8859_9: i32 = 24;
5480const ENC_ISO8859_10: i32 = 25;
5481const ENC_ISO8859_11: i32 = 26;
5482const ENC_ISO8859_13: i32 = 27;
5483const ENC_ISO8859_14: i32 = 28;
5484const ENC_ISO8859_15: i32 = 29;
5485const ENC_ISO8859_16: i32 = 30;
5486
5487include!("iconv_iso8859.rs");
5488
5489fn make_cd(from: i32, to: i32) -> IconvT {
5490 ((from as usize) << 16 | (to as usize) << 1 | 1) as IconvT
5491}
5492fn extract_from(cd: IconvT) -> i32 {
5493 ((cd as usize) >> 16) as i32
5494}
5495fn extract_to(cd: IconvT) -> i32 {
5496 (((cd as usize) >> 1) & 0x7fff) as i32
5497}
5498
5499unsafe fn match_name(input: *const u8, target: &[u8]) -> bool {
5500 let mut i = input;
5501 let mut j = 0;
5502 while *i != 0 && j < target.len() {
5503 let mut c = *i;
5504 if !c.is_ascii_alphanumeric() { i = i.add(1); continue; }
5505 c = c.to_ascii_lowercase();
5506 if c != target[j] { return false; }
5507 i = i.add(1);
5508 j += 1;
5509 }
5510 while *i != 0 && !(*i).is_ascii_alphanumeric() { i = i.add(1); }
5511 *i == 0 && j == target.len()
5512}
5513
5514unsafe fn find_encoding(name: *const u8) -> i32 {
5515 if name.is_null() { return -1; }
5516 if match_name(name, b"utf8") || match_name(name, b"utf-8") || match_name(name, b"char") { return ENC_UTF8; }
5517 if match_name(name, b"utf16le") || match_name(name, b"utf-16le") { return ENC_UTF16LE; }
5518 if match_name(name, b"utf16be") || match_name(name, b"utf-16be") { return ENC_UTF16BE; }
5519 if match_name(name, b"utf32le") || match_name(name, b"utf-32le") || match_name(name, b"ucs4le") { return ENC_UTF32LE; }
5520 if match_name(name, b"utf32be") || match_name(name, b"utf-32be") || match_name(name, b"ucs4be") { return ENC_UTF32BE; }
5521 if match_name(name, b"wchart") || match_name(name, b"wchar-t") { return ENC_WCHAR_T; }
5522 if match_name(name, b"ascii") || match_name(name, b"usascii") || match_name(name, b"iso646") { return ENC_ASCII; }
5523 if match_name(name, b"iso88591") || match_name(name, b"iso-8859-1") || match_name(name, b"latin1") { return ENC_LATIN1; }
5524 if match_name(name, b"iso88592") || match_name(name, b"iso-8859-2") { return ENC_ISO8859_2; }
5525 if match_name(name, b"iso88593") || match_name(name, b"iso-8859-3") { return ENC_ISO8859_3; }
5526 if match_name(name, b"iso88594") || match_name(name, b"iso-8859-4") { return ENC_ISO8859_4; }
5527 if match_name(name, b"iso88595") || match_name(name, b"iso-8859-5") { return ENC_ISO8859_5; }
5528 if match_name(name, b"iso88596") || match_name(name, b"iso-8859-6") { return ENC_ISO8859_6; }
5529 if match_name(name, b"iso88597") || match_name(name, b"iso-8859-7") { return ENC_ISO8859_7; }
5530 if match_name(name, b"iso88598") || match_name(name, b"iso-8859-8") { return ENC_ISO8859_8; }
5531 if match_name(name, b"iso88599") || match_name(name, b"iso-8859-9") { return ENC_ISO8859_9; }
5532 if match_name(name, b"iso885910") || match_name(name, b"iso-8859-10") { return ENC_ISO8859_10; }
5533 if match_name(name, b"iso885911") || match_name(name, b"iso-8859-11") || match_name(name, b"tis620") { return ENC_ISO8859_11; }
5534 if match_name(name, b"iso885913") || match_name(name, b"iso-8859-13") { return ENC_ISO8859_13; }
5535 if match_name(name, b"iso885914") || match_name(name, b"iso-8859-14") { return ENC_ISO8859_14; }
5536 if match_name(name, b"iso885915") || match_name(name, b"iso-8859-15") { return ENC_ISO8859_15; }
5537 if match_name(name, b"iso885916") || match_name(name, b"iso-8859-16") { return ENC_ISO8859_16; }
5538 if match_name(name, b"cp1252") || match_name(name, b"windows1252") || match_name(name, b"windows-1252") { return ENC_WIN1252; }
5539 if match_name(name, b"cp1251") || match_name(name, b"windows1251") || match_name(name, b"windows-1251") { return ENC_WIN1251; }
5540 if match_name(name, b"koi8r") || match_name(name, b"koi8-r") { return ENC_KOI8R; }
5541 if match_name(name, b"gbk") || match_name(name, b"cp936") { return ENC_GBK; }
5542 if match_name(name, b"gb2312") { return ENC_GB2312; }
5543 if match_name(name, b"big5") || match_name(name, b"bigfive") || match_name(name, b"cp950") { return ENC_BIG5; }
5544 if match_name(name, b"eucjp") || match_name(name, b"euc-jp") { return ENC_EUCJP; }
5545 if match_name(name, b"shiftjis") || match_name(name, b"sjis") || match_name(name, b"cp932") { return ENC_SHIFTJIS; }
5546 -1
5547}
5548
5549fn uni_to_jis(c: u32) -> u16 {
5550 let mut b = 0usize;
5551 let mut nel = REV_JIS.len();
5552 loop {
5553 let i = nel / 2;
5554 let j = REV_JIS[b + i] as usize;
5555 let row = j / 256;
5556 let col = j % 256;
5557 let d = JIS0208[row * 94 + col] as u32;
5558 if d == c { return (j as u16) + 0x2121; }
5559 if nel == 1 { return 0; }
5560 if c < d { nel /= 2; }
5561 else { b += i; nel -= nel / 2; }
5562 }
5563}
5564
5565unsafe fn iconv_decode(enc: i32, src: *const u8, src_left: usize) -> (u32, usize, c_int) {
5566 if src_left == 0 { return (0, 0, EINVAL); }
5567 match enc {
5568 ENC_UTF8 => {
5569 let c = *src;
5570 if c < 128 { return (c as u32, 1, 0); }
5571 if c < 0xC2 { return (0, 0, EILSEQ); }
5572 if c < 0xE0 {
5573 if src_left < 2 || (*src.add(1) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5574 return (((c as u32 & 0x1F) << 6) | (*src.add(1) as u32 & 0x3F), 2, 0);
5575 }
5576 if c < 0xF0 {
5577 if src_left < 3 || (*src.add(1) & 0xC0) != 0x80 || (*src.add(2) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5578 let cp = ((c as u32 & 0x0F) << 12) | ((*src.add(1) as u32 & 0x3F) << 6) | (*src.add(2) as u32 & 0x3F);
5579 if cp < 0x800 { return (0, 0, EILSEQ); }
5580 return (cp, 3, 0);
5581 }
5582 if c < 0xF8 {
5583 if src_left < 4 || (*src.add(1) & 0xC0) != 0x80 || (*src.add(2) & 0xC0) != 0x80 || (*src.add(3) & 0xC0) != 0x80 { return (0, 0, EILSEQ); }
5584 let cp = ((c as u32 & 0x07) << 18) | ((*src.add(1) as u32 & 0x3F) << 12) | ((*src.add(2) as u32 & 0x3F) << 6) | (*src.add(3) as u32 & 0x3F);
5585 if cp < 0x10000 || cp >= 0x110000 { return (0, 0, EILSEQ); }
5586 return (cp, 4, 0);
5587 }
5588 (0, 0, EILSEQ)
5589 }
5590 ENC_UTF16LE => {
5591 if src_left < 2 { return (0, 0, EINVAL); }
5592 let c = (*src as u32) | ((*src.add(1) as u32) << 8);
5593 if c >= 0xD800 && c <= 0xDBFF {
5594 if src_left < 4 { return (0, 0, EINVAL); }
5595 let d = (*src.add(2) as u32) | ((*src.add(3) as u32) << 8);
5596 if d < 0xDC00 || d > 0xDFFF { return (0, 0, EILSEQ); }
5597 return (((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000, 4, 0);
5598 }
5599 if c >= 0xDC00 && c <= 0xDFFF { return (0, 0, EILSEQ); }
5600 (c, 2, 0)
5601 }
5602 ENC_UTF16BE => {
5603 if src_left < 2 { return (0, 0, EINVAL); }
5604 let c = ((*src as u32) << 8) | (*src.add(1) as u32);
5605 if c >= 0xD800 && c <= 0xDBFF {
5606 if src_left < 4 { return (0, 0, EINVAL); }
5607 let d = ((*src.add(2) as u32) << 8) | (*src.add(3) as u32);
5608 if d < 0xDC00 || d > 0xDFFF { return (0, 0, EILSEQ); }
5609 return (((c - 0xD800) << 10) + (d - 0xDC00) + 0x10000, 4, 0);
5610 }
5611 if c >= 0xDC00 && c <= 0xDFFF { return (0, 0, EILSEQ); }
5612 (c, 2, 0)
5613 }
5614 ENC_UTF32LE => {
5615 if src_left < 4 { return (0, 0, EINVAL); }
5616 let c = (*src as u32) | ((*src.add(1) as u32) << 8) | ((*src.add(2) as u32) << 16) | ((*src.add(3) as u32) << 24);
5617 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5618 if c >= 0x110000 { return (0, 0, EILSEQ); }
5619 (c, 4, 0)
5620 }
5621 ENC_UTF32BE => {
5622 if src_left < 4 { return (0, 0, EINVAL); }
5623 let c = ((*src as u32) << 24) | ((*src.add(1) as u32) << 16) | ((*src.add(2) as u32) << 8) | (*src.add(3) as u32);
5624 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5625 if c >= 0x110000 { return (0, 0, EILSEQ); }
5626 (c, 4, 0)
5627 }
5628 ENC_WCHAR_T => {
5629 if src_left < 4 { return (0, 0, EINVAL); }
5630 let c = *(src as *const u32);
5631 if c >= 0xD800 && c < 0xE000 { return (0, 0, EILSEQ); }
5632 if c >= 0x110000 { return (0, 0, EILSEQ); }
5633 (c, 4, 0)
5634 }
5635 ENC_ASCII => {
5636 let c = *src as u32;
5637 if c >= 128 { return (0, 0, EILSEQ); }
5638 (c, 1, 0)
5639 }
5640 ENC_LATIN1 => (*src as u32, 1, 0),
5641 ENC_ISO8859_2 => (iso8859_to_u(&ISO8859_2_TO_U, *src), 1, 0),
5642 ENC_ISO8859_3 => (iso8859_to_u(&ISO8859_3_TO_U, *src), 1, 0),
5643 ENC_ISO8859_4 => (iso8859_to_u(&ISO8859_4_TO_U, *src), 1, 0),
5644 ENC_ISO8859_5 => (iso8859_to_u(&ISO8859_5_TO_U, *src), 1, 0),
5645 ENC_ISO8859_6 => (iso8859_to_u(&ISO8859_6_TO_U, *src), 1, 0),
5646 ENC_ISO8859_7 => (iso8859_to_u(&ISO8859_7_TO_U, *src), 1, 0),
5647 ENC_ISO8859_8 => (iso8859_to_u(&ISO8859_8_TO_U, *src), 1, 0),
5648 ENC_ISO8859_9 => (iso8859_to_u(&ISO8859_9_TO_U, *src), 1, 0),
5649 ENC_ISO8859_10 => (iso8859_to_u(&ISO8859_10_TO_U, *src), 1, 0),
5650 ENC_ISO8859_11 => (iso8859_to_u(&ISO8859_11_TO_U, *src), 1, 0),
5651 ENC_ISO8859_13 => (iso8859_to_u(&ISO8859_13_TO_U, *src), 1, 0),
5652 ENC_ISO8859_14 => (iso8859_to_u(&ISO8859_14_TO_U, *src), 1, 0),
5653 ENC_ISO8859_15 => (iso8859_to_u(&ISO8859_15_TO_U, *src), 1, 0),
5654 ENC_ISO8859_16 => (iso8859_to_u(&ISO8859_16_TO_U, *src), 1, 0),
5655 ENC_WIN1252 => {
5656 let b = *src;
5657 if b < 128 { return (b as u32, 1, 0); }
5658 (WIN1252_TO_U[b as usize - 128], 1, 0)
5659 }
5660 ENC_WIN1251 => {
5661 let b = *src;
5662 if b < 128 { return (b as u32, 1, 0); }
5663 (WIN1251_TO_U[b as usize - 128], 1, 0)
5664 }
5665 ENC_KOI8R => {
5666 let b = *src;
5667 if b < 128 { return (b as u32, 1, 0); }
5668 (KOI8R_TO_U[b as usize - 128], 1, 0)
5669 }
5670 ENC_GBK | ENC_GB2312 => {
5671 let c = *src;
5672 if c < 128 { return (c as u32, 1, 0); }
5673 if c == 128 { return (0x20AC, 1, 0); }
5674 if src_left < 2 { return (0, 0, EINVAL); }
5675 let d = *src.add(1);
5676 if d < 0x40 || d == 0x7F || d > 0xFE { return (0, 0, EILSEQ); }
5677 let row = (c as usize).wrapping_sub(0x81);
5678 if row >= 126 { return (0, 0, EILSEQ); }
5679 let mut col = (d as usize) - 0x40;
5680 if col > 63 { col -= 1; }
5681 let cp = GB18030_TABLE[row * 190 + col] as u32;
5682 if cp == 0 { return (0, 0, EILSEQ); }
5683 (cp, 2, 0)
5684 }
5685 ENC_BIG5 => {
5686 let c = *src;
5687 if c < 128 { return (c as u32, 1, 0); }
5688 if src_left < 2 { return (0, 0, EINVAL); }
5689 let d = *src.add(1);
5690 if d < 0x40 || d == 0x7F || d > 0xFE { return (0, 0, EILSEQ); }
5691 let mut col = (d as usize) - 0x40;
5692 if col > 0x3E { col -= 0x22; }
5693 if c >= 0xA1 && c < 0xFA {
5694 let row = (c as usize) - 0xA1;
5695 if row >= 89 { return (0, 0, EILSEQ); }
5696 let cp = BIG5_TABLE[row * 157 + col] as u32;
5697 if cp == 0 { return (0, 0, EILSEQ); }
5698 return (cp, 2, 0);
5699 }
5700 (0, 0, EILSEQ)
5701 }
5702 ENC_EUCJP => {
5703 let c = *src;
5704 if c < 128 { return (c as u32, 1, 0); }
5705 if c == 0x8E {
5706 if src_left < 2 { return (0, 0, EINVAL); }
5707 let d = *src.add(1);
5708 if d < 0xA1 || d > 0xDF { return (0, 0, EILSEQ); }
5709 return ((d as u32) + 0xFF61 - 0xA1, 2, 0);
5710 }
5711 if c < 0xA1 { return (0, 0, EILSEQ); }
5712 if src_left < 2 { return (0, 0, EINVAL); }
5713 let d = *src.add(1);
5714 if d < 0xA1 || d > 0xFE { return (0, 0, EILSEQ); }
5715 let row = (c as usize) - 0xA1;
5716 let col = (d as usize) - 0xA1;
5717 if row >= 84 || col >= 94 { return (0, 0, EILSEQ); }
5718 let cp = JIS0208[row * 94 + col] as u32;
5719 if cp == 0 { return (0, 0, EILSEQ); }
5720 (cp, 2, 0)
5721 }
5722 ENC_SHIFTJIS => {
5723 let c = *src;
5724 if c < 128 { return (c as u32, 1, 0); }
5725 if c >= 0xA1 && c <= 0xDF { return ((c as u32) + 0xFF61 - 0xA1, 1, 0); }
5726 if src_left < 2 { return (0, 0, EINVAL); }
5727 let d = *src.add(1);
5728 if d < 0x40 || d == 0x7F || d > 0xFC { return (0, 0, EILSEQ); }
5729 let row = if c >= 129 && c <= 159 { (c as usize) - 129 }
5730 else if c >= 224 && c <= 239 { (c as usize) - 193 }
5731 else { return (0, 0, EILSEQ); };
5732 let (col, row_adj) = if d >= 64 && d <= 158 && d != 127 {
5733 let mut dd = d as usize;
5734 if dd > 127 { dd -= 1; }
5735 (dd - 64, row * 2)
5736 } else if d >= 159 && d <= 252 {
5737 ((d as usize) - 159, row * 2 + 1)
5738 } else {
5739 return (0, 0, EILSEQ);
5740 };
5741 if row_adj >= 84 { return (0, 0, EILSEQ); }
5742 let cp = JIS0208[row_adj * 94 + col] as u32;
5743 if cp == 0 { return (0, 0, EILSEQ); }
5744 (cp, 2, 0)
5745 }
5746 _ => (0, 0, EILSEQ),
5747 }
5748}
5749
5750unsafe fn iconv_encode(enc: i32, c: u32, dst: *mut u8, dst_left: usize) -> (usize, c_int) {
5751 match enc {
5752 ENC_UTF8 => {
5753 if c < 0x80 {
5754 if dst_left < 1 { return (0, E2BIG); }
5755 *dst = c as u8; return (1, 0);
5756 }
5757 if c < 0x800 {
5758 if dst_left < 2 { return (0, E2BIG); }
5759 *dst = (0xC0 | (c >> 6)) as u8;
5760 *dst.add(1) = (0x80 | (c & 0x3F)) as u8;
5761 return (2, 0);
5762 }
5763 if c < 0x10000 {
5764 if dst_left < 3 { return (0, E2BIG); }
5765 *dst = (0xE0 | (c >> 12)) as u8;
5766 *dst.add(1) = (0x80 | ((c >> 6) & 0x3F)) as u8;
5767 *dst.add(2) = (0x80 | (c & 0x3F)) as u8;
5768 return (3, 0);
5769 }
5770 if dst_left < 4 { return (0, E2BIG); }
5771 *dst = (0xF0 | (c >> 18)) as u8;
5772 *dst.add(1) = (0x80 | ((c >> 12) & 0x3F)) as u8;
5773 *dst.add(2) = (0x80 | ((c >> 6) & 0x3F)) as u8;
5774 *dst.add(3) = (0x80 | (c & 0x3F)) as u8;
5775 (4, 0)
5776 }
5777 ENC_UTF16LE => {
5778 if c < 0x10000 {
5779 if dst_left < 2 { return (0, E2BIG); }
5780 *dst = (c & 0xFF) as u8;
5781 *dst.add(1) = (c >> 8) as u8;
5782 return (2, 0);
5783 }
5784 if dst_left < 4 { return (0, E2BIG); }
5785 let c = c - 0x10000;
5786 let hi = ((c >> 10) + 0xD800) as u16;
5787 let lo = ((c & 0x3FF) + 0xDC00) as u16;
5788 *dst = (hi & 0xFF) as u8; *dst.add(1) = (hi >> 8) as u8;
5789 *dst.add(2) = (lo & 0xFF) as u8; *dst.add(3) = (lo >> 8) as u8;
5790 (4, 0)
5791 }
5792 ENC_UTF16BE => {
5793 if c < 0x10000 {
5794 if dst_left < 2 { return (0, E2BIG); }
5795 *dst = (c >> 8) as u8;
5796 *dst.add(1) = (c & 0xFF) as u8;
5797 return (2, 0);
5798 }
5799 if dst_left < 4 { return (0, E2BIG); }
5800 let c = c - 0x10000;
5801 let hi = ((c >> 10) + 0xD800) as u16;
5802 let lo = ((c & 0x3FF) + 0xDC00) as u16;
5803 *dst = (hi >> 8) as u8; *dst.add(1) = (hi & 0xFF) as u8;
5804 *dst.add(2) = (lo >> 8) as u8; *dst.add(3) = (lo & 0xFF) as u8;
5805 (4, 0)
5806 }
5807 ENC_UTF32LE => {
5808 if dst_left < 4 { return (0, E2BIG); }
5809 *dst = (c & 0xFF) as u8; *dst.add(1) = ((c >> 8) & 0xFF) as u8;
5810 *dst.add(2) = ((c >> 16) & 0xFF) as u8; *dst.add(3) = (c >> 24) as u8;
5811 (4, 0)
5812 }
5813 ENC_UTF32BE => {
5814 if dst_left < 4 { return (0, E2BIG); }
5815 *dst = (c >> 24) as u8; *dst.add(1) = ((c >> 16) & 0xFF) as u8;
5816 *dst.add(2) = ((c >> 8) & 0xFF) as u8; *dst.add(3) = (c & 0xFF) as u8;
5817 (4, 0)
5818 }
5819 ENC_WCHAR_T => {
5820 if dst_left < 4 { return (0, E2BIG); }
5821 *(dst as *mut u32) = c;
5822 (4, 0)
5823 }
5824 ENC_ASCII => {
5825 if c < 128 {
5826 if dst_left < 1 { return (0, E2BIG); }
5827 *dst = c as u8; return (1, 0);
5828 }
5829 (0, EILSEQ)
5830 }
5831 ENC_LATIN1 => {
5832 if c < 256 {
5833 if dst_left < 1 { return (0, E2BIG); }
5834 *dst = c as u8; return (1, 0);
5835 }
5836 (0, EILSEQ)
5837 }
5838 ENC_ISO8859_2 => {
5839 if let Some(b) = u_to_iso8859(&ISO8859_2_TO_U, c) {
5840 if dst_left < 1 { return (0, E2BIG); }
5841 *dst = b; return (1, 0);
5842 }
5843 (0, EILSEQ)
5844 }
5845 ENC_ISO8859_3 => {
5846 if let Some(b) = u_to_iso8859(&ISO8859_3_TO_U, c) {
5847 if dst_left < 1 { return (0, E2BIG); }
5848 *dst = b; return (1, 0);
5849 }
5850 (0, EILSEQ)
5851 }
5852 ENC_ISO8859_4 => {
5853 if let Some(b) = u_to_iso8859(&ISO8859_4_TO_U, c) {
5854 if dst_left < 1 { return (0, E2BIG); }
5855 *dst = b; return (1, 0);
5856 }
5857 (0, EILSEQ)
5858 }
5859 ENC_ISO8859_5 => {
5860 if let Some(b) = u_to_iso8859(&ISO8859_5_TO_U, c) {
5861 if dst_left < 1 { return (0, E2BIG); }
5862 *dst = b; return (1, 0);
5863 }
5864 (0, EILSEQ)
5865 }
5866 ENC_ISO8859_6 => {
5867 if let Some(b) = u_to_iso8859(&ISO8859_6_TO_U, c) {
5868 if dst_left < 1 { return (0, E2BIG); }
5869 *dst = b; return (1, 0);
5870 }
5871 (0, EILSEQ)
5872 }
5873 ENC_ISO8859_7 => {
5874 if let Some(b) = u_to_iso8859(&ISO8859_7_TO_U, c) {
5875 if dst_left < 1 { return (0, E2BIG); }
5876 *dst = b; return (1, 0);
5877 }
5878 (0, EILSEQ)
5879 }
5880 ENC_ISO8859_8 => {
5881 if let Some(b) = u_to_iso8859(&ISO8859_8_TO_U, c) {
5882 if dst_left < 1 { return (0, E2BIG); }
5883 *dst = b; return (1, 0);
5884 }
5885 (0, EILSEQ)
5886 }
5887 ENC_ISO8859_9 => {
5888 if let Some(b) = u_to_iso8859(&ISO8859_9_TO_U, c) {
5889 if dst_left < 1 { return (0, E2BIG); }
5890 *dst = b; return (1, 0);
5891 }
5892 (0, EILSEQ)
5893 }
5894 ENC_ISO8859_10 => {
5895 if let Some(b) = u_to_iso8859(&ISO8859_10_TO_U, c) {
5896 if dst_left < 1 { return (0, E2BIG); }
5897 *dst = b; return (1, 0);
5898 }
5899 (0, EILSEQ)
5900 }
5901 ENC_ISO8859_11 => {
5902 if let Some(b) = u_to_iso8859(&ISO8859_11_TO_U, c) {
5903 if dst_left < 1 { return (0, E2BIG); }
5904 *dst = b; return (1, 0);
5905 }
5906 (0, EILSEQ)
5907 }
5908 ENC_ISO8859_13 => {
5909 if let Some(b) = u_to_iso8859(&ISO8859_13_TO_U, c) {
5910 if dst_left < 1 { return (0, E2BIG); }
5911 *dst = b; return (1, 0);
5912 }
5913 (0, EILSEQ)
5914 }
5915 ENC_ISO8859_14 => {
5916 if let Some(b) = u_to_iso8859(&ISO8859_14_TO_U, c) {
5917 if dst_left < 1 { return (0, E2BIG); }
5918 *dst = b; return (1, 0);
5919 }
5920 (0, EILSEQ)
5921 }
5922 ENC_ISO8859_15 => {
5923 if let Some(b) = u_to_iso8859(&ISO8859_15_TO_U, c) {
5924 if dst_left < 1 { return (0, E2BIG); }
5925 *dst = b; return (1, 0);
5926 }
5927 (0, EILSEQ)
5928 }
5929 ENC_ISO8859_16 => {
5930 if let Some(b) = u_to_iso8859(&ISO8859_16_TO_U, c) {
5931 if dst_left < 1 { return (0, E2BIG); }
5932 *dst = b; return (1, 0);
5933 }
5934 (0, EILSEQ)
5935 }
5936 ENC_WIN1252 => {
5937 if c < 128 {
5938 if dst_left < 1 { return (0, E2BIG); }
5939 *dst = c as u8; return (1, 0);
5940 }
5941 if c >= 0xA0 && c <= 0xFF && WIN1252_TO_U[c as usize - 128] == c {
5942 if dst_left < 1 { return (0, E2BIG); }
5943 *dst = c as u8; return (1, 0);
5944 }
5945 for i in 0..128usize {
5946 if WIN1252_TO_U[i] == c {
5947 if dst_left < 1 { return (0, E2BIG); }
5948 *dst = (i + 128) as u8; return (1, 0);
5949 }
5950 }
5951 (0, EILSEQ)
5952 }
5953 ENC_WIN1251 => {
5954 if c < 128 {
5955 if dst_left < 1 { return (0, E2BIG); }
5956 *dst = c as u8; return (1, 0);
5957 }
5958 for i in 0..128usize {
5959 if WIN1251_TO_U[i] == c {
5960 if dst_left < 1 { return (0, E2BIG); }
5961 *dst = (i + 128) as u8; return (1, 0);
5962 }
5963 }
5964 (0, EILSEQ)
5965 }
5966 ENC_KOI8R => {
5967 if c < 128 {
5968 if dst_left < 1 { return (0, E2BIG); }
5969 *dst = c as u8; return (1, 0);
5970 }
5971 for i in 0..128usize {
5972 if KOI8R_TO_U[i] == c {
5973 if dst_left < 1 { return (0, E2BIG); }
5974 *dst = (i + 128) as u8; return (1, 0);
5975 }
5976 }
5977 (0, EILSEQ)
5978 }
5979 ENC_GBK | ENC_GB2312 => {
5980 if c < 128 {
5981 if dst_left < 1 { return (0, E2BIG); }
5982 *dst = c as u8; return (1, 0);
5983 }
5984 if c == 0x20AC {
5985 if dst_left < 1 { return (0, E2BIG); }
5986 *dst = 128; return (1, 0);
5987 }
5988 for row in 0..126usize {
5989 for col in 0..190usize {
5990 if GB18030_TABLE[row * 190 + col] as u32 == c {
5991 if dst_left < 2 { return (0, E2BIG); }
5992 *dst = (row + 0x81) as u8;
5993 *dst.add(1) = if col <= 62 { (col + 0x40) as u8 } else { (col + 0x41) as u8 };
5994 return (2, 0);
5995 }
5996 }
5997 }
5998 (0, EILSEQ)
5999 }
6000 ENC_BIG5 => {
6001 if c < 128 {
6002 if dst_left < 1 { return (0, E2BIG); }
6003 *dst = c as u8; return (1, 0);
6004 }
6005 for row in 0..89usize {
6006 for col in 0..157usize {
6007 if BIG5_TABLE[row * 157 + col] as u32 == c {
6008 if dst_left < 2 { return (0, E2BIG); }
6009 *dst = (row + 0xA1) as u8;
6010 *dst.add(1) = if col <= 0x3E { (col + 0x40) as u8 } else { (col + 0x62) as u8 };
6011 return (2, 0);
6012 }
6013 }
6014 }
6015 (0, EILSEQ)
6016 }
6017 ENC_EUCJP => {
6018 if c < 128 {
6019 if dst_left < 1 { return (0, E2BIG); }
6020 *dst = c as u8; return (1, 0);
6021 }
6022 if c >= 0xFF61 && c <= 0xFF9F {
6023 if dst_left < 2 { return (0, E2BIG); }
6024 *dst = 0x8E;
6025 *dst.add(1) = (c - 0xFF61 + 0xA1) as u8;
6026 return (2, 0);
6027 }
6028 let jis = uni_to_jis(c);
6029 if jis == 0 { return (0, EILSEQ); }
6030 if dst_left < 2 { return (0, E2BIG); }
6031 *dst = ((jis >> 8) as u8).wrapping_add(0x80);
6032 *dst.add(1) = ((jis & 0xFF) as u8).wrapping_add(0x80);
6033 (2, 0)
6034 }
6035 ENC_SHIFTJIS => {
6036 if c < 128 {
6037 if dst_left < 1 { return (0, E2BIG); }
6038 *dst = c as u8; return (1, 0);
6039 }
6040 if c >= 0xFF61 && c <= 0xFF9F {
6041 if dst_left < 1 { return (0, E2BIG); }
6042 *dst = (c - 0xFF61 + 0xA1) as u8;
6043 return (1, 0);
6044 }
6045 let jis = uni_to_jis(c);
6046 if jis == 0 { return (0, EILSEQ); }
6047 if dst_left < 2 { return (0, E2BIG); }
6048 let r = (jis >> 8) as usize;
6049 let d = (jis & 0xFF) as usize;
6050 *dst = ((r + 1) / 2 + if r < 95 { 112 } else { 176 }) as u8;
6051 *dst.add(1) = if r % 2 == 1 { (d + 31 + d / 96) as u8 } else { (d + 126) as u8 };
6052 (2, 0)
6053 }
6054 _ => (0, EILSEQ),
6055 }
6056}
6057
6058#[no_mangle]
6059pub unsafe extern "C" fn iconv_open(tocode: *const c_char, fromcode: *const c_char) -> IconvT {
6060 let to = find_encoding(tocode as *const u8);
6061 let from = find_encoding(fromcode as *const u8);
6062 if to < 0 || from < 0 {
6063 ERRNO!() = EINVAL;
6064 return !0usize as IconvT;
6065 }
6066 make_cd(from, to)
6067}
6068
6069#[no_mangle]
6070pub unsafe extern "C" fn iconv(
6071 cd: IconvT,
6072 inbuf: *mut *mut c_char,
6073 inbytesleft: *mut SizeT,
6074 outbuf: *mut *mut c_char,
6075 outbytesleft: *mut SizeT,
6076) -> SizeT {
6077 if cd == !0usize as IconvT {
6078 ERRNO!() = EINVAL;
6079 return !0usize;
6080 }
6081 if inbuf.is_null() || outbuf.is_null() { return 0; }
6082 let from = extract_from(cd);
6083 let to = extract_to(cd);
6084 let mut src = *inbuf as *const u8;
6085 let mut dst = *outbuf as *mut u8;
6086 let mut src_left = *inbytesleft;
6087 let mut dst_left = *outbytesleft;
6088 let mut subst = 0usize;
6089 while src_left > 0 {
6090 let (cp, consumed, err) = iconv_decode(from, src, src_left);
6091 if err != 0 {
6092 if err == EINVAL { break; }
6093 ERRNO!() = err;
6094 return !0usize;
6095 }
6096 let (written, err) = iconv_encode(to, cp, dst, dst_left);
6097 if err != 0 {
6098 if err == E2BIG {
6099 ERRNO!() = E2BIG;
6100 return !0usize;
6101 }
6102 if dst_left < 1 {
6103 ERRNO!() = E2BIG;
6104 return !0usize;
6105 }
6106 *dst = b'*';
6107 dst = dst.add(1);
6108 dst_left -= 1;
6109 subst += 1;
6110 } else {
6111 dst = dst.add(written);
6112 dst_left -= written;
6113 }
6114 src = src.add(consumed);
6115 src_left -= consumed;
6116 }
6117 *inbuf = src as *mut c_char;
6118 *outbuf = dst as *mut c_char;
6119 *inbytesleft = src_left;
6120 *outbytesleft = dst_left;
6121 subst
6122}
6123
6124#[no_mangle]
6125pub unsafe extern "C" fn iconv_close(_cd: IconvT) -> c_int { 0 }
6126
6127#[no_mangle]
6132pub unsafe extern "C" fn write(fd: c_int, buf: *const c_void, count: SizeT) -> SSizeT {
6133 syscall_ret(sys_write(fd as i64, buf as *const u8, count)) as SSizeT
6134}
6135
6136#[no_mangle]
6137pub unsafe extern "C" fn read(fd: c_int, buf: *mut c_void, count: SizeT) -> SSizeT {
6138 syscall_ret(sys_read(fd as i64, buf as *mut u8, count)) as SSizeT
6139}
6140
6141#[no_mangle]
6142pub unsafe extern "C" fn open(path: *const c_char, flags: c_int, mode: c_int) -> c_int {
6143 syscall_ret(sys_open(path as *const u8, flags as i64, mode as i64)) as c_int
6144}
6145
6146#[no_mangle]
6147pub unsafe extern "C" fn close(fd: c_int) -> c_int {
6148 syscall_ret(sys_close(fd as i64)) as c_int
6149}
6150
6151#[no_mangle]
6152pub unsafe extern "C" fn lseek(fd: c_int, offset: i64, whence: c_int) -> i64 {
6153 syscall_ret(sys_lseek(fd as i64, offset, whence as i64))
6154}
6155
6156const O_RDONLY: i32 = 0;
6161const O_WRONLY: i32 = 1;
6162const O_RDWR: i32 = 2;
6163const O_CREAT: i32 = 64;
6164const O_TRUNC: i32 = 512;
6165const O_APPEND: i32 = 1024;
6166const O_EXCL: i32 = 128;
6167const O_NONBLOCK: i32 = 2048;
6168const O_NOFOLLOW: i32 = if cfg!(target_arch = "aarch64") { 0o100000 } else { 0o400000 };
6169const O_DIRECTORY: i32 = if cfg!(target_arch = "aarch64") { 0o40000 } else { 0o200000 };
6170const O_CLOEXEC: i32 = 0x80000;
6171
6172const F_GETFD: i32 = 1;
6173const F_SETFD: i32 = 2;
6174const F_GETFL: i32 = 3;
6175const F_SETFL: i32 = 4;
6176const F_GETLK: i32 = 5;
6177const F_SETLK: i32 = 6;
6178const F_SETLKW: i32 = 7;
6179const F_DUPFD: i32 = 0;
6180const F_DUPFD_CLOEXEC: i32 = 1030;
6181const FD_CLOEXEC: i32 = 1;
6182
6183const TIOCGWINSZ: u32 = 0x5413;
6184
6185#[repr(C)]
6186struct winsize {
6187 ws_row: u16,
6188 ws_col: u16,
6189 ws_xpixel: u16,
6190 ws_ypixel: u16,
6191}
6192
6193#[inline]
6194unsafe fn sys_pipe2(fds: *mut c_int, flags: i32) -> i64 {
6195 <Arch as Syscalls>::syscall2(SYS_PIPE2, fds as i64, flags as i64)
6196}
6197
6198#[inline]
6199unsafe fn sys_dup3(oldfd: i32, newfd: i32, flags: i32) -> i64 {
6200 <Arch as Syscalls>::syscall3(SYS_DUP3, oldfd as i64, newfd as i64, flags as i64)
6201}
6202
6203#[inline]
6204unsafe fn sys_fcntl(fd: i32, cmd: i32, arg: i64) -> i64 {
6205 <Arch as Syscalls>::syscall3(SYS_FCNTL, fd as i64, cmd as i64, arg as i64)
6206}
6207
6208#[inline]
6209unsafe fn sys_ioctl(fd: c_int, request: u32, arg: *mut u8) -> i64 {
6210 <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, request as i64, arg as i64)
6211}
6212
6213#[inline]
6214unsafe fn sys_unlinkat(dirfd: i32, path: *const u8, flags: i32) -> i64 {
6215 <Arch as Syscalls>::syscall3(SYS_UNLINKAT, dirfd as i64, path as i64, flags as i64)
6216}
6217
6218#[inline]
6219unsafe fn sys_renameat2(olddirfd: i32, oldpath: *const u8, newdirfd: i32, newpath: *const u8, flags: u32) -> i64 {
6220 <Arch as Syscalls>::syscall5(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)
6221}
6222
6223const UNGET: usize = 8;
6228const F_PERM: u32 = 1;
6229const F_NORD: u32 = 4;
6230const F_NOWR: u32 = 8;
6231const F_EOF: u32 = 16;
6232const F_ERR: u32 = 32;
6233const F_SVB: u32 = 64;
6234const F_APP: u32 = 128;
6235
6236const BUFSIZ: usize = 1024;
6237
6238const _IOFBF: c_int = 0;
6239const _IOLBF: c_int = 1;
6240const _IONBF: c_int = 2;
6241
6242const SEEK_SET: c_int = 0;
6243const SEEK_CUR: c_int = 1;
6244const SEEK_END: c_int = 2;
6245
6246#[repr(C)]
6248pub struct FILE {
6249 flags: c_uint,
6250 rpos: *mut u8,
6251 rend: *mut u8,
6252 close: Option<unsafe extern "C" fn(*mut FILE) -> c_int>,
6253 wend: *mut u8,
6254 wpos: *mut u8,
6255 mustbezero_1: *mut u8,
6256 wbase: *mut u8,
6257 read_fn: Option<unsafe extern "C" fn(*mut FILE, *mut u8, usize) -> usize>,
6258 write_fn: Option<unsafe extern "C" fn(*mut FILE, *const u8, usize) -> usize>,
6259 seek_fn: Option<unsafe extern "C" fn(*mut FILE, i64, c_int) -> i64>,
6260 buf: *mut u8,
6261 buf_size: usize,
6262 prev: *mut FILE,
6263 next: *mut FILE,
6264 fd: c_int,
6265 pipe_pid: c_int,
6266 lockcount: c_long,
6267 mode: c_int,
6268 lock: c_int,
6269 lbf: c_int,
6270 cookie: *mut c_void,
6271 off: i64,
6272 getln_buf: *mut c_char,
6273 mustbezero_2: *mut c_void,
6274 shend: *mut u8,
6275 shlim: i64,
6276 shcnt: i64,
6277 ungotten: [c_int; UNGET],
6278 ungotten_count: c_int,
6279 _eof: c_int,
6280 _err: c_int,
6281}
6282
6283static mut STDIN_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
6284static mut STDOUT_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
6285static mut STDERR_BUF: [u8; BUFSIZ] = [0; BUFSIZ];
6286
6287static mut STDIN_FILE: FILE = FILE {
6288 flags: 0, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
6289 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
6290 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
6291 read_fn: None, write_fn: None, seek_fn: None,
6292 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
6293 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
6294 fd: 0, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
6295 cookie: core::ptr::null_mut(), off: 0,
6296 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
6297 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
6298 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
6299};
6300static mut STDOUT_FILE: FILE = FILE {
6301 flags: F_NOWR as u32 + F_SVB as u32, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
6302 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
6303 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
6304 read_fn: None, write_fn: None, seek_fn: None,
6305 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
6306 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
6307 fd: 1, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
6308 cookie: core::ptr::null_mut(), off: 0,
6309 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
6310 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
6311 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
6312};
6313static mut STDERR_FILE: FILE = FILE {
6314 flags: F_NOWR as u32, rpos: core::ptr::null_mut(), rend: core::ptr::null_mut(),
6315 close: None, wend: core::ptr::null_mut(), wpos: core::ptr::null_mut(),
6316 mustbezero_1: core::ptr::null_mut(), wbase: core::ptr::null_mut(),
6317 read_fn: None, write_fn: None, seek_fn: None,
6318 buf: core::ptr::null_mut(), buf_size: BUFSIZ,
6319 prev: core::ptr::null_mut(), next: core::ptr::null_mut(),
6320 fd: 2, pipe_pid: 0, lockcount: 0, mode: 0, lock: 0, lbf: -1,
6321 cookie: core::ptr::null_mut(), off: 0,
6322 getln_buf: core::ptr::null_mut(), mustbezero_2: core::ptr::null_mut(),
6323 shend: core::ptr::null_mut(), shlim: 0, shcnt: 0,
6324 ungotten: [0; UNGET], ungotten_count: 0, _eof: 0, _err: 0,
6325};
6326
6327#[no_mangle]
6328pub static mut stdin: *mut FILE = &raw mut STDIN_FILE as *mut FILE;
6329#[no_mangle]
6330pub static mut stdout: *mut FILE = &raw mut STDOUT_FILE as *mut FILE;
6331#[no_mangle]
6332pub static mut stderr: *mut FILE = &raw mut STDERR_FILE as *mut FILE;
6333
6334unsafe fn __stdio_init() {
6339 STDIN_FILE.buf = core::ptr::addr_of_mut!(STDIN_BUF) as *mut u8;
6340 STDIN_FILE.buf_size = BUFSIZ;
6341 STDIN_FILE.read_fn = Some(__stdio_read);
6342 STDIN_FILE.write_fn = Some(__stdio_write);
6343 STDIN_FILE.seek_fn = Some(__stdio_seek);
6344 STDOUT_FILE.buf = core::ptr::addr_of_mut!(STDOUT_BUF) as *mut u8;
6345 STDOUT_FILE.buf_size = BUFSIZ;
6346 STDOUT_FILE.lbf = b'\n' as c_int;
6347 STDOUT_FILE.read_fn = Some(__stdio_read);
6348 STDOUT_FILE.write_fn = Some(__stdio_write);
6349 STDOUT_FILE.seek_fn = Some(__stdio_seek);
6350 STDERR_FILE.buf = core::ptr::addr_of_mut!(STDERR_BUF) as *mut u8;
6351 STDERR_FILE.buf_size = BUFSIZ;
6352 STDERR_FILE.read_fn = Some(__stdio_read);
6353 STDERR_FILE.write_fn = Some(__stdio_write);
6354 STDERR_FILE.seek_fn = Some(__stdio_seek);
6355}
6356
6357unsafe fn buf_ptr(f: *mut FILE) -> *mut u8 {
6358 (f as *mut u8).add(core::mem::size_of::<FILE>())
6359}
6360
6361unsafe extern "C" fn __stdio_read(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
6362 let n = sys_read((*f).fd as i64, buf, len);
6363 if n <= 0 {
6364 if n == 0 { (*f).flags |= F_EOF; } else { (*f).flags |= F_ERR; (*f)._err = 1; }
6365 return 0;
6366 }
6367 n as usize
6368}
6369
6370unsafe extern "C" fn __stdio_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
6371 let l = (*f).wpos as usize - (*f).wbase as usize;
6372 let mut iov = [
6373 ((*f).wbase as *const u8, l),
6374 (buf, len),
6375 ];
6376 if iov[0].1 == 0 { iov = [iov[1], (core::ptr::null(), 0)]; }
6377 if (*f).flags & F_APP != 0 {
6378 let _ = sys_lseek((*f).fd as i64, 0, SEEK_END as i64);
6379 }
6380 let mut rem = iov[0].1 + iov[1].1;
6381 let mut idx = 0usize;
6382 while rem > 0 {
6383 let ptr = iov[idx].0;
6384 let cnt = iov[idx].1;
6385 if cnt == 0 { idx += 1; continue; }
6386 let n = sys_write((*f).fd as i64, ptr, cnt);
6387 if n <= 0 {
6388 (*f).wpos = core::ptr::null_mut();
6389 (*f).wbase = core::ptr::null_mut();
6390 (*f).wend = core::ptr::null_mut();
6391 (*f).flags |= F_ERR;
6392 return if iov[idx].0 == buf { 0 } else { len };
6393 }
6394 rem -= n as usize;
6395 iov[idx].0 = iov[idx].0.add(n as usize);
6396 iov[idx].1 -= n as usize;
6397 if iov[idx].1 == 0 { idx += 1; }
6398 }
6399 (*f).wend = (*f).buf.add((*f).buf_size);
6400 (*f).wbase = (*f).buf;
6401 (*f).wpos = (*f).buf;
6402 len
6403}
6404
6405unsafe extern "C" fn __stdio_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
6406 sys_lseek((*f).fd as i64, off, whence as i64)
6407}
6408
6409unsafe fn init_file(
6410 f: *mut FILE,
6411 fd: c_int,
6412 mode: *const c_char,
6413 close_fn: Option<unsafe extern "C" fn(*mut FILE) -> c_int>,
6414 buf_area: *mut u8,
6415 buf_sz: usize,
6416) {
6417 core::ptr::write_bytes(f as *mut u8, 0, core::mem::size_of::<FILE>());
6418 (*f).fd = fd;
6419 (*f).close = close_fn;
6420 (*f).lock = 0;
6421 (*f).lbf = -1;
6422 (*f).buf = buf_area;
6423 (*f).buf_size = buf_sz;
6424 (*f).read_fn = Some(__stdio_read);
6425 (*f).write_fn = Some(__stdio_write);
6426 (*f).seek_fn = Some(__stdio_seek);
6427 let m = *mode;
6428 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
6429 if m == b'r' as c_char && !has_plus {
6430 (*f).flags = F_NORD;
6431 } else if !has_plus {
6432 (*f).flags = F_NOWR;
6433 }
6434}
6435
6436unsafe extern "C" fn __stdio_close(f: *mut FILE) -> c_int {
6437 sys_close((*f).fd as i64);
6438 0
6439}
6440
6441unsafe fn fmodeflags(mode: *const c_char) -> c_int {
6442 let mut flags: c_int;
6443 let m = *mode;
6444 if !strchr(mode as *const u8, b'+' as c_int).is_null() {
6445 flags = O_RDWR;
6446 } else if m == b'r' as c_char {
6447 flags = O_RDONLY;
6448 } else {
6449 flags = O_WRONLY;
6450 }
6451 if !strchr(mode as *const u8, b'x' as c_int).is_null() { flags |= O_EXCL; }
6452 if !strchr(mode as *const u8, b'e' as c_int).is_null() { flags |= O_CLOEXEC; }
6453 if m != b'r' as c_char { flags |= O_CREAT; }
6454 if m == b'w' as c_char { flags |= O_TRUNC; }
6455 if m == b'a' as c_char { flags |= O_APPEND; }
6456 flags
6457}
6458
6459const O_ACCMODE: c_int = O_RDONLY | O_WRONLY | O_RDWR;
6460
6461unsafe fn flush_buf(f: *mut FILE) -> c_int {
6462 if (*f).wpos == (*f).wbase {
6463 if !(*f).wpos.is_null() {
6464 (*f).wend = (*f).buf.add((*f).buf_size);
6465 (*f).wpos = (*f).wbase;
6466 }
6467 return 0;
6468 }
6469 if let Some(wfunc) = (*f).write_fn {
6470 let ret = wfunc(f, core::ptr::null(), 0);
6471 if ret == 0 && (*f).wpos.is_null() { return -1; }
6472 return 0;
6473 }
6474 (*f).flags |= F_ERR;
6475 -1
6476}
6477
6478#[no_mangle]
6483pub unsafe extern "C" fn fopen(filename: *const c_char, mode: *const c_char) -> *mut FILE {
6484 if filename.is_null() || mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
6485 let m = *mode;
6486 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
6487 ERRNO!() = EINVAL; return core::ptr::null_mut();
6488 }
6489 let flags = fmodeflags(mode);
6490 let fd = sys_open(filename as *const u8, flags as i64, 0o666);
6491 if fd < 0 { ERRNO!() = (-fd) as c_int; return core::ptr::null_mut(); }
6492 fdopen(fd as c_int, mode)
6493}
6494
6495#[no_mangle]
6496pub unsafe extern "C" fn fdopen(fd: c_int, mode: *const c_char) -> *mut FILE {
6497 if fd < 0 || mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
6498 let m = *mode;
6499 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
6500 ERRNO!() = EINVAL; return core::ptr::null_mut();
6501 }
6502 let f = calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
6503 if f.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
6504 let buf = buf_ptr(f);
6505 init_file(f, fd, mode, Some(__stdio_close), buf, BUFSIZ);
6506 if !strchr(mode as *const u8, b'a' as c_int).is_null() { (*f).flags |= F_APP; }
6507 if !strchr(mode as *const u8, b'e' as c_int).is_null() { sys_fcntl(fd, F_SETFD, FD_CLOEXEC as i64); }
6508 if (*f).flags & F_NOWR == 0 {
6509 let mut ws: winsize = core::mem::zeroed();
6510 if sys_ioctl(fd, TIOCGWINSZ, &mut ws as *mut winsize as *mut u8) == 0 {
6511 (*f).lbf = b'\n' as c_int;
6512 }
6513 }
6514 f
6515}
6516
6517#[no_mangle]
6518pub unsafe extern "C" fn freopen(
6519 filename: *const c_char, mode: *const c_char, f: *mut FILE,
6520) -> *mut FILE {
6521 fflush(f);
6522 if (*f).pipe_pid > 0 { let _ = __stdio_close(f); }
6523 if filename.is_null() {
6524 let flags = fmodeflags(mode);
6525 if flags == 0 { return core::ptr::null_mut(); }
6526 let mut fl = flags & !(O_CREAT | O_EXCL | O_CLOEXEC);
6527 if (*f).flags & F_APP != 0 { fl = (fl & !O_ACCMODE) | O_WRONLY | O_APPEND; }
6528 if sys_fcntl((*f).fd, F_SETFL, fl as i64) < 0 { return core::ptr::null_mut(); }
6529 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
6530 if has_plus {
6531 (*f).flags &= !(F_NORD | F_NOWR);
6532 } else if *mode == b'r' as c_char {
6533 (*f).flags = ((*f).flags & !F_NOWR) | F_NORD;
6534 } else {
6535 (*f).flags = ((*f).flags & !F_NORD) | F_NOWR;
6536 }
6537 return f;
6538 }
6539 let new_f = fopen(filename, mode);
6540 if new_f.is_null() { let _ = __stdio_close(f); return core::ptr::null_mut(); }
6541 if (*new_f).fd == (*f).fd {
6542 (*new_f).fd = -1;
6543 } else {
6544 sys_dup3((*new_f).fd, (*f).fd, 0);
6545 let _ = __stdio_close(new_f);
6546 }
6547 (*f).flags = (*new_f).flags;
6548 (*f).rpos = core::ptr::null_mut();
6549 (*f).rend = core::ptr::null_mut();
6550 (*f).wpos = core::ptr::null_mut();
6551 (*f).wbase = core::ptr::null_mut();
6552 (*f).wend = core::ptr::null_mut();
6553 (*f).lbf = (*new_f).lbf;
6554 (*f).pipe_pid = 0;
6555 free(new_f as *mut c_void);
6556 f
6557}
6558
6559#[no_mangle]
6560pub unsafe extern "C" fn fclose(f: *mut FILE) -> c_int {
6561 if f.is_null() { return -1; }
6562 let r = fflush(f);
6563 if let Some(close_fn) = (*f).close { let _ = close_fn(f); }
6564 if r != 0 { -1 } else { 0 }
6565}
6566
6567#[no_mangle]
6572pub unsafe extern "C" fn setvbuf(f: *mut FILE, buf: *mut c_char, mode: c_int, size: usize) -> c_int {
6573 if mode != _IOFBF && mode != _IOLBF && mode != _IONBF { return -1; }
6574 fflush(f);
6575 (*f).rpos = core::ptr::null_mut();
6576 (*f).rend = core::ptr::null_mut();
6577 (*f).wpos = core::ptr::null_mut();
6578 (*f).wbase = core::ptr::null_mut();
6579 (*f).wend = core::ptr::null_mut();
6580 if mode == _IONBF {
6581 (*f).buf_size = 0;
6582 } else if !buf.is_null() && size > 0 {
6583 (*f).buf = buf as *mut u8;
6584 (*f).buf_size = size;
6585 }
6586 (*f).lbf = if mode == _IOLBF { b'\n' as c_int } else { -1 };
6587 0
6588}
6589
6590#[no_mangle]
6591pub unsafe extern "C" fn setbuf(f: *mut FILE, buf: *mut c_char) {
6592 if buf.is_null() { setvbuf(f, core::ptr::null_mut(), _IONBF, 0); }
6593 else { setvbuf(f, buf, _IOFBF, BUFSIZ); }
6594}
6595
6596#[no_mangle]
6597pub unsafe extern "C" fn setbuffer(f: *mut FILE, buf: *mut c_char, size: usize) {
6598 if buf.is_null() { setvbuf(f, core::ptr::null_mut(), _IONBF, 0); }
6599 else { setvbuf(f, buf, _IOFBF, size); }
6600}
6601
6602#[no_mangle]
6603pub unsafe extern "C" fn fflush(f: *mut FILE) -> c_int {
6604 if f.is_null() {
6605 let mut r = 0;
6606 if !stdout.is_null() && !(*stdout).wpos.is_null() && (*stdout).wpos != (*stdout).wbase {
6607 if flush_buf(stdout) != 0 { r = -1; }
6608 }
6609 if !stderr.is_null() && !(*stderr).wpos.is_null() && (*stderr).wpos != (*stderr).wbase {
6610 if flush_buf(stderr) != 0 { r = -1; }
6611 }
6612 return r;
6613 }
6614 if !(*f).wpos.is_null() && (*f).wpos != (*f).wbase {
6615 return flush_buf(f);
6616 }
6617 0
6618}
6619
6620#[no_mangle]
6625pub unsafe extern "C" fn fwide(_f: *mut FILE, mode: c_int) -> c_int { mode }
6626
6627#[no_mangle]
6628pub unsafe extern "C" fn feof(f: *mut FILE) -> c_int { if (*f)._eof != 0 { 1 } else { 0 } }
6629
6630#[no_mangle]
6631pub unsafe extern "C" fn ferror(f: *mut FILE) -> c_int { if (*f)._err != 0 { 1 } else { 0 } }
6632
6633#[no_mangle]
6634pub unsafe extern "C" fn clearerr(f: *mut FILE) { (*f)._eof = 0; (*f)._err = 0; }
6635
6636#[no_mangle]
6637pub unsafe extern "C" fn fileno(f: *mut FILE) -> c_int { (*f).fd }
6638
6639#[no_mangle]
6644pub unsafe extern "C" fn fseek(stream: *mut FILE, offset: c_long, whence: c_int) -> c_int {
6645 fseeko(stream, offset as i64, whence)
6646}
6647
6648#[no_mangle]
6649pub unsafe extern "C" fn ftell(stream: *mut FILE) -> c_long {
6650 ftello(stream) as c_long
6651}
6652
6653#[no_mangle]
6654pub unsafe extern "C" fn rewind(stream: *mut FILE) {
6655 fseek(stream, 0, SEEK_SET);
6656 (*stream)._eof = 0;
6657 (*stream)._err = 0;
6658}
6659
6660#[no_mangle]
6661pub unsafe extern "C" fn fseeko(stream: *mut FILE, offset: i64, whence: c_int) -> c_int {
6662 if whence != SEEK_SET && whence != SEEK_CUR && whence != SEEK_END {
6663 ERRNO!() = EINVAL;
6664 return -1;
6665 }
6666 let f = &mut *stream;
6667 let mut adj_offset = offset;
6668 if whence == SEEK_CUR {
6669 if !f.rpos.is_null() {
6670 adj_offset -= f.rend as i64 - f.rpos as i64;
6671 }
6672 adj_offset -= f.ungotten_count as i64;
6673 }
6674 if !f.wpos.is_null() && f.wpos != f.wbase {
6675 if flush_buf(stream) != 0 { return -1; }
6676 }
6677 f.wpos = core::ptr::null_mut();
6678 f.wbase = core::ptr::null_mut();
6679 f.wend = core::ptr::null_mut();
6680 if let Some(sfunc) = f.seek_fn {
6681 let r = sfunc(stream, adj_offset, whence);
6682 if r < 0 { return -1; }
6683 } else {
6684 ERRNO!() = EINVAL;
6685 return -1;
6686 }
6687 f.rpos = core::ptr::null_mut();
6688 f.rend = core::ptr::null_mut();
6689 f._eof = 0;
6690 f.ungotten_count = 0;
6691 0
6692}
6693
6694#[no_mangle]
6695pub unsafe extern "C" fn ftello(stream: *mut FILE) -> i64 {
6696 let f = &mut *stream;
6697 if f.flags & F_APP != 0 && !f.wpos.is_null() && f.wpos != f.wbase {
6698 if fflush(stream) != 0 { return -1; }
6699 }
6700 let sfunc = match f.seek_fn { Some(s) => s, None => return -1 };
6701 let pos = sfunc(stream, 0,
6702 if (f.flags & F_APP) != 0 && !f.wpos.is_null() && f.wpos != f.wbase { SEEK_END } else { SEEK_CUR });
6703 if pos < 0 { return -1; }
6704 let mut pos = pos;
6705 if !f.rpos.is_null() {
6706 pos += f.rpos as i64 - f.rend as i64;
6707 } else if !f.wbase.is_null() {
6708 pos += f.wpos as i64 - f.wbase as i64;
6709 }
6710 pos - f.ungotten_count as i64
6711}
6712
6713#[no_mangle]
6714pub unsafe extern "C" fn fgetpos(stream: *mut FILE, pos: *mut i64) -> c_int {
6715 let off = ftello(stream);
6716 if off < 0 { return -1; }
6717 *pos = off;
6718 0
6719}
6720
6721#[no_mangle]
6722pub unsafe extern "C" fn fsetpos(stream: *mut FILE, pos: *const i64) -> c_int {
6723 fseeko(stream, *pos, SEEK_SET)
6724}
6725
6726#[no_mangle]
6731pub unsafe extern "C" fn fgetc(stream: *mut FILE) -> c_int {
6732 let f = &mut *stream;
6733 if f.ungotten_count > 0 {
6734 f.ungotten_count -= 1;
6735 return f.ungotten[f.ungotten_count as usize];
6736 }
6737 if !f.rpos.is_null() && f.rpos < f.rend {
6738 let c = *f.rpos;
6739 f.rpos = f.rpos.add(1);
6740 return c as c_int;
6741 }
6742 if f._eof != 0 { return -1; }
6743 if let Some(rfunc) = f.read_fn {
6744 if !f.buf.is_null() && f.buf_size > 1 {
6748 let n = rfunc(stream, f.buf, f.buf_size);
6749 if n == 0 {
6750 if f.flags & F_ERR != 0 { f._err = 1; } else { f._eof = 1; }
6751 return -1;
6752 }
6753 f.rpos = f.buf;
6754 f.rend = f.buf.add(n);
6755 let c = *f.rpos;
6756 f.rpos = f.rpos.add(1);
6757 return c as c_int;
6758 }
6759 let mut buf = [0u8; 1];
6760 let n = rfunc(stream, buf.as_mut_ptr(), 1);
6761 if n == 0 {
6762 if f.flags & F_ERR != 0 { f._err = 1; } else { f._eof = 1; }
6763 return -1;
6764 }
6765 buf[0] as c_int
6766 } else {
6767 f._eof = 1;
6768 -1
6769 }
6770}
6771
6772#[no_mangle]
6773pub unsafe extern "C" fn getc(stream: *mut FILE) -> c_int { fgetc(stream) }
6774
6775#[no_mangle]
6776pub unsafe extern "C" fn getchar() -> c_int { fgetc(stdin) }
6777
6778#[no_mangle]
6779pub unsafe extern "C" fn ungetc(c: c_int, stream: *mut FILE) -> c_int {
6780 if c == -1 { return -1; }
6781 let f = &mut *stream;
6782 if f.ungotten_count >= UNGET as c_int { return -1; }
6783 f.ungotten[f.ungotten_count as usize] = c;
6784 f.ungotten_count += 1;
6785 f._eof = 0;
6786 c
6787}
6788
6789#[no_mangle]
6794pub unsafe extern "C" fn fgets(s: *mut c_char, n: c_int, stream: *mut FILE) -> *mut c_char {
6795 if n <= 0 { return null_mut(); }
6796 let max = (n - 1) as usize;
6797 let mut i = 0usize;
6798 while i < max {
6799 let c = fgetc(stream);
6800 if c == -1 { if i == 0 { return null_mut(); } break; }
6801 *s.add(i) = c as c_char;
6802 i += 1;
6803 if c == b'\n' as c_int { break; }
6804 }
6805 *s.add(i) = 0;
6806 s
6807}
6808
6809#[no_mangle]
6811pub unsafe extern "C" fn gets(s: *mut c_char) -> *mut c_char {
6812 let mut i = 0usize;
6813 loop {
6814 let c = fgetc(stdin);
6815 if c == -1 { if i == 0 { return null_mut(); } break; }
6816 if c == b'\n' as c_int { break; }
6817 *s.add(i) = c as c_char;
6818 i += 1;
6819 }
6820 *s.add(i) = 0;
6821 s
6822}
6823
6824#[no_mangle]
6825pub unsafe extern "C" fn fopen64(filename: *const c_char, mode: *const c_char) -> *mut FILE {
6826 fopen(filename, mode)
6827}
6828
6829const PERROR_BUF_SIZE: usize = 64;
6831static mut PERROR_BUF: [u8; PERROR_BUF_SIZE] = [0; PERROR_BUF_SIZE];
6832
6833#[no_mangle]
6834pub unsafe extern "C" fn perror(msg: *const c_char) {
6835 let fd = (*stderr).fd;
6836 if !msg.is_null() && *msg != 0 {
6837 let len = strlen(msg as *const c_char);
6838 write_str(fd, msg as *const u8, len);
6839 write_str(fd, b": ".as_ptr(), 2);
6840 }
6841 let e = ERRNO!();
6842 let text = strerror(e) as *const u8;
6843 write_str(fd, text, strlen(text as *const c_char));
6844 write_str(fd, b"\n".as_ptr(), 1);
6845}
6846
6847#[no_mangle]
6848pub unsafe extern "C" fn fread(
6849 ptr: *mut c_void, size: SizeT, nmemb: SizeT, stream: *mut FILE,
6850) -> SizeT {
6851 if size == 0 || nmemb == 0 { return 0; }
6852 let total = size * nmemb;
6853 let mut rd = 0usize;
6854 while rd < total {
6855 let c = fgetc(stream);
6856 if c == -1 { break; }
6857 *(ptr as *mut u8).add(rd) = c as u8;
6858 rd += 1;
6859 }
6860 rd / size
6861}
6862
6863unsafe fn write_str(fd: c_int, s: *const u8, len: usize) {
6868 let mut written = 0usize;
6869 while written < len {
6870 let n = sys_write(fd as i64, s.add(written), len - written);
6871 if n <= 0 { break; }
6872 written += n as usize;
6873 }
6874}
6875
6876#[no_mangle]
6877unsafe fn __overflow(f: *mut FILE, c: c_int) -> c_int {
6878 if (*f).wpos.is_null() {
6879 (*f).wbase = (*f).buf;
6880 (*f).wpos = (*f).buf;
6881 (*f).wend = (*f).buf.add((*f).buf_size);
6882 }
6883 if flush_buf(f) == -1 { return -1; }
6884 if (*f).wpos >= (*f).wend {
6885 if let Some(wfunc) = (*f).write_fn {
6886 let byte = c as u8;
6887 let ret = wfunc(f, &byte as *const u8, 1);
6888 if ret == 0 { return -1; }
6889 }
6890 return c;
6891 }
6892 *(*f).wpos = c as u8;
6893 (*f).wpos = (*f).wpos.add(1);
6894 if c == (*f).lbf || (*f).wpos >= (*f).wend { let _ = flush_buf(f); }
6895 c
6896}
6897
6898#[no_mangle]
6899pub unsafe extern "C" fn puts(s: *const c_char) -> c_int {
6900 let len = strlen(s as *const c_char);
6901 let _ = fwrite(s as *const c_void, 1, len, stdout);
6902 let _ = fwrite(b"\n".as_ptr() as *const c_void, 1, 1, stdout);
6903 let f = &mut *stdout;
6904 if f.lbf >= 0 { let _ = flush_buf(stdout); }
6905 (len + 1) as c_int
6906}
6907
6908#[no_mangle]
6909pub unsafe extern "C" fn fputs(s: *const c_char, stream: *mut FILE) -> c_int {
6910 let len = strlen(s as *const c_char);
6911 fwrite(s as *const c_void, 1, len, stream) as c_int
6912}
6913
6914#[no_mangle]
6915pub unsafe extern "C" fn fputc(c: c_int, stream: *mut FILE) -> c_int {
6916 let f = &mut *stream;
6917 if f.wpos.is_null() || f.wpos >= f.wend {
6918 if __overflow(f, c) == -1 { return -1; }
6919 return c;
6920 }
6921 *f.wpos = c as u8;
6922 f.wpos = f.wpos.add(1);
6923 if c == f.lbf || f.wpos >= f.wend { let _ = flush_buf(f); }
6924 c
6925}
6926
6927#[no_mangle]
6928pub unsafe extern "C" fn putc(c: c_int, stream: *mut FILE) -> c_int { fputc(c, stream) }
6929
6930#[no_mangle]
6931pub unsafe extern "C" fn putchar(c: c_int) -> c_int { fputc(c, stdout) }
6932
6933#[no_mangle]
6934pub unsafe extern "C" fn fwrite(
6935 ptr: *const c_void, size: SizeT, nmemb: SizeT, stream: *mut FILE,
6936) -> SizeT {
6937 if size == 0 || nmemb == 0 { return 0; }
6938 let total = size * nmemb;
6939 let f = &mut *stream;
6940 if f.buf_size == 0 {
6941 if let Some(wfunc) = f.write_fn {
6942 let ret = wfunc(stream, ptr as *const u8, total);
6943 return ret / size;
6944 }
6945 return 0;
6946 }
6947 if f.wpos.is_null() {
6948 f.wbase = f.buf;
6949 f.wpos = f.buf;
6950 f.wend = f.buf.add(f.buf_size);
6951 }
6952 let mut remaining = total;
6953 let mut src = ptr as *const u8;
6954 while remaining > 0 {
6955 let space = f.wend as usize - f.wpos as usize;
6956 if space == 0 {
6957 if flush_buf(f as *mut FILE) == -1 { break; }
6958 continue;
6959 }
6960 let n = if remaining < space { remaining } else { space };
6961 core::ptr::copy_nonoverlapping(src, f.wpos, n);
6962 f.wpos = f.wpos.add(n);
6963 src = src.add(n);
6964 remaining -= n;
6965 if f.wpos >= f.wend { let _ = flush_buf(f as *mut FILE); }
6966 }
6967 if f.lbf >= 0 { let _ = flush_buf(f as *mut FILE); }
6968 (total - remaining) / size
6969}
6970
6971unsafe fn wide_to_mb(dst: *mut u8, cap: usize, src: *const wchar_t) -> usize {
6976 let mut o = 0usize;
6977 let mut i = 0usize;
6978 let mut st: c_uint = 0;
6979 while *src.add(i) != 0 {
6980 let mut tmp = [0u8; 8];
6981 let n = wcrtomb(tmp.as_mut_ptr() as *mut c_char, *src.add(i), &mut st);
6982 if n == !0usize || n == 0 { break; }
6983 if o + n > cap { break; }
6984 core::ptr::copy_nonoverlapping(tmp.as_ptr(), dst.add(o), n);
6985 o += n;
6986 i += 1;
6987 }
6988 o
6989}
6990
6991macro_rules! impl_format {
6992 ($fmt:expr, $args:expr, $write_char:expr, $write_str:expr) => {{
6993 let fmt = $fmt;
6994 let args = &mut $args;
6995 let mut count: usize = 0;
6996 let mut i = 0usize;
6997 loop {
6998 let c = *fmt.add(i) as u8;
6999 if c == 0 { break; }
7000 if c != b'%' {
7001 ($write_char)(c);
7002 count += 1; i += 1; continue;
7003 }
7004 i += 1;
7005 let mut flags: u8 = 0;
7007 loop {
7008 let fc = *fmt.add(i) as u8;
7009 match fc {
7010 b'-' => { flags |= FLAG_MINUS; i += 1; }
7011 b'+' => { flags |= FLAG_PLUS; i += 1; }
7012 b' ' => { flags |= FLAG_SPACE; i += 1; }
7013 b'0' => { flags |= FLAG_ZERO; i += 1; }
7014 b'#' => { flags |= FLAG_HASH; i += 1; }
7015 _ => break,
7016 }
7017 }
7018 let mut width: usize = 0;
7020 if *fmt.add(i) as u8 == b'*' {
7021 width = args.next_arg::<c_int>() as usize; i += 1;
7022 } else {
7023 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
7024 width = width * 10 + ((*fmt.add(i) as u8) - b'0') as usize; i += 1;
7025 }
7026 }
7027 let mut precision: i32 = -1;
7029 if *fmt.add(i) as u8 == b'.' {
7030 i += 1;
7031 if *fmt.add(i) as u8 == b'*' {
7032 precision = args.next_arg::<c_int>(); i += 1;
7033 } else {
7034 precision = 0;
7035 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
7036 precision = precision * 10 + ((*fmt.add(i) as u8) - b'0') as i32; i += 1;
7037 }
7038 }
7039 }
7040 let len_mod = *fmt.add(i) as u8;
7042 let spec: u8;
7043 if len_mod == b'h' || len_mod == b'l' || len_mod == b'j' || len_mod == b'z' || len_mod == b't' || len_mod == b'L' {
7044 i += 1;
7045 let len_mod2 = *fmt.add(i) as u8;
7046 if (len_mod == b'h' && len_mod2 == b'h') || (len_mod == b'l' && len_mod2 == b'l') {
7047 i += 1;
7048 spec = *fmt.add(i) as u8;
7049 match (len_mod, len_mod2, spec) {
7051 (b'h', b'h', b'n') => {
7052 let p = args.next_arg::<*mut c_void>();
7053 if !p.is_null() { *(p as *mut u8) = count as u8; }
7054 }
7055 (b'l', b'l', b'n') => {
7056 let p = args.next_arg::<*mut c_void>();
7057 if !p.is_null() { *(p as *mut c_longlong) = count as c_longlong; }
7058 }
7059 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
7060 let val = args.next_arg::<c_longlong>();
7061 let neg = val < 0;
7062 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
7063 let b = format_u64(abs);
7064 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7065 let mut fbuf = [0u8; 32];
7066 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7067 ($write_str)(fbuf.as_ptr(), len); count += len;
7068 }
7069 (b'l', b'l', b'u') => {
7070 let val = args.next_arg::<c_ulonglong>();
7071 let b = format_u64(val as u64);
7072 let mut fbuf = [0u8; 32];
7073 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7074 ($write_str)(fbuf.as_ptr(), len); count += len;
7075 }
7076 (b'l', b'l', b'o') => {
7077 let val = args.next_arg::<c_ulonglong>();
7078 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
7079 let mut fbuf = [0u8; 32];
7080 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7081 ($write_str)(fbuf.as_ptr(), len); count += len;
7082 }
7083 (b'l', b'l', b'x') => {
7084 let val = args.next_arg::<c_ulonglong>();
7085 let b = format_hex(val as u64, false);
7086 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
7087 let mut fbuf = [0u8; 32];
7088 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7089 ($write_str)(fbuf.as_ptr(), len); count += len;
7090 }
7091 (b'l', b'l', b'X') => {
7092 let val = args.next_arg::<c_ulonglong>();
7093 let b = format_hex(val as u64, true);
7094 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
7095 let mut fbuf = [0u8; 32];
7096 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7097 ($write_str)(fbuf.as_ptr(), len); count += len;
7098 }
7099 _ => { ($write_char)(b'%'); ($write_char)(len_mod); ($write_char)(len_mod2); ($write_char)(spec); count += 4; }
7100 }
7101 } else {
7102 spec = len_mod2;
7103 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
7106 match (lm, spec) {
7107 (b'h', b'n') => {
7108 let p = args.next_arg::<*mut c_void>();
7109 if !p.is_null() { *(p as *mut u16) = count as u16; }
7110 }
7111 (b'l', b'n') => {
7112 let p = args.next_arg::<*mut c_void>();
7113 if !p.is_null() { *(p as *mut c_long) = count as c_long; }
7114 }
7115 (b'z', b'n') | (b't', b'n') => {
7116 let p = args.next_arg::<*mut c_void>();
7117 if !p.is_null() { *(p as *mut usize) = count; }
7118 }
7119 (b'j', b'n') => {
7120 let p = args.next_arg::<*mut c_void>();
7121 if !p.is_null() { *(p as *mut c_ulonglong) = count as c_ulonglong; }
7122 }
7123 (b'l', b'd') | (b'l', b'i') => {
7124 let val = args.next_arg::<c_long>();
7125 let neg = val < 0;
7126 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
7127 let b = format_u64(abs);
7128 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7129 let mut fbuf = [0u8; 32];
7130 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7131 ($write_str)(fbuf.as_ptr(), len); count += len;
7132 }
7133 (b'l', b'u') => {
7134 let val = args.next_arg::<c_ulong>();
7135 let b = format_u64(val as u64);
7136 let mut fbuf = [0u8; 32];
7137 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7138 ($write_str)(fbuf.as_ptr(), len); count += len;
7139 }
7140 (b'l', b's') => {
7141 let p = args.next_arg::<*const wchar_t>();
7142 if p.is_null() {
7143 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
7144 let pad = width.saturating_sub(slen);
7145 if flags & FLAG_MINUS != 0 { ($write_str)(b"(null)".as_ptr(), slen); for _ in 0..pad { ($write_char)(b' '); } }
7146 else { for _ in 0..pad { ($write_char)(b' '); } ($write_str)(b"(null)".as_ptr(), slen); }
7147 count += slen + pad;
7148 } else {
7149 let mut mb = [0u8; 4096];
7150 let mut n = wide_to_mb(mb.as_mut_ptr(), mb.len(), p);
7151 if precision >= 0 && (precision as usize) < n { n = precision as usize; }
7152 let pad = width.saturating_sub(n);
7153 if flags & FLAG_MINUS != 0 { ($write_str)(mb.as_ptr(), n); for _ in 0..pad { ($write_char)(b' '); } }
7154 else { for _ in 0..pad { ($write_char)(b' '); } ($write_str)(mb.as_ptr(), n); }
7155 count += n + pad;
7156 }
7157 }
7158 (b'l', b'c') => {
7159 let ch = args.next_arg::<c_int>();
7160 let mut mb = [0u8; 8];
7161 let mut st: c_uint = 0;
7162 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, ch, &mut st);
7163 if n != !0usize { ($write_str)(mb.as_ptr(), n); count += n; }
7164 }
7165 (b'l', b'x') => {
7166 let val = args.next_arg::<c_ulong>();
7167 let b = format_hex(val as u64, false);
7168 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
7169 let mut fbuf = [0u8; 32];
7170 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7171 ($write_str)(fbuf.as_ptr(), len); count += len;
7172 }
7173 (b'l', b'X') => {
7174 let val = args.next_arg::<c_ulong>();
7175 let b = format_hex(val as u64, true);
7176 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
7177 let mut fbuf = [0u8; 32];
7178 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7179 ($write_str)(fbuf.as_ptr(), len); count += len;
7180 }
7181 (b'l', b'o') => {
7182 let val = args.next_arg::<c_ulong>();
7183 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
7184 let mut fbuf = [0u8; 32];
7185 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7186 ($write_str)(fbuf.as_ptr(), len); count += len;
7187 }
7188 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
7189 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
7190 let val = args.next_arg::<f64>();
7191 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7192 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7193 let mut fbuf = [0u8; 4224];
7194 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7195 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
7196 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
7197 ($write_str)(fbuf.as_ptr(), total); count += total;
7198 }
7199 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
7200 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
7201 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
7202 let val = {
7203 let lo: u64 = args.next_arg::<u64>();
7204 let hi: u64 = args.next_arg::<u64>();
7205 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
7206 f128::from_bits(combined) as f64
7207 };
7208 #[cfg(target_arch = "x86_64")]
7209 let val = args.next_arg::<f64>();
7210 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7211 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7212 let mut fbuf = [0u8; 4224];
7213 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7214 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
7215 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
7216 ($write_str)(fbuf.as_ptr(), total); count += total;
7217 }
7218 _ => { ($write_char)(b'%'); ($write_char)(len_mod); ($write_char)(spec); count += 3; }
7219 }
7220 }
7221 } else {
7222 spec = *fmt.add(i) as u8;
7223 match spec {
7224 b's' => {
7225 let s = args.next_arg::<*const c_char>();
7226 if s.is_null() {
7227 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
7228 let padded_len = if width > slen { width } else { slen };
7229 let pad = padded_len - slen;
7230 if flags & FLAG_MINUS != 0 {
7231 ($write_str)(b"(null)".as_ptr(), slen);
7232 for _ in 0..pad { ($write_char)(b' '); }
7233 } else {
7234 for _ in 0..pad { ($write_char)(b' '); }
7235 ($write_str)(b"(null)".as_ptr(), slen);
7236 }
7237 count += padded_len;
7238 } else {
7239 let full_len = strlen(s as *const c_char);
7240 let slen = if precision >= 0 { (precision as usize).min(full_len) } else { full_len };
7241 let padded_len = if width > slen { width } else { slen };
7242 let pad = padded_len - slen;
7243 if flags & FLAG_MINUS != 0 {
7244 ($write_str)(s as *const u8, slen);
7245 for _ in 0..pad { ($write_char)(b' '); }
7246 } else {
7247 for _ in 0..pad { ($write_char)(b' '); }
7248 ($write_str)(s as *const u8, slen);
7249 }
7250 count += padded_len;
7251 }
7252 }
7253 b'd' | b'i' => {
7254 let d = args.next_arg::<c_int>();
7255 let neg = d < 0;
7256 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
7257 let b = format_u64(abs);
7258 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
7259 let mut fbuf = [0u8; 32];
7260 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
7261 ($write_str)(fbuf.as_ptr(), len); count += len;
7262 }
7263 b'u' => {
7264 let u = args.next_arg::<c_uint>();
7265 let b = format_u64(u as u64);
7266 let mut fbuf = [0u8; 32];
7267 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
7268 ($write_str)(fbuf.as_ptr(), len); count += len;
7269 }
7270 b'x' => {
7271 let x = args.next_arg::<c_uint>();
7272 let b = format_hex(x as u64, false);
7273 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
7274 let mut fbuf = [0u8; 32];
7275 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7276 ($write_str)(fbuf.as_ptr(), len); count += len;
7277 }
7278 b'X' => {
7279 let x = args.next_arg::<c_uint>();
7280 let b = format_hex(x as u64, true);
7281 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
7282 let mut fbuf = [0u8; 32];
7283 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
7284 ($write_str)(fbuf.as_ptr(), len); count += len;
7285 }
7286 b'o' => {
7287 let o = args.next_arg::<c_uint>();
7288 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
7289 let mut fbuf = [0u8; 32];
7290 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
7291 ($write_str)(fbuf.as_ptr(), len); count += len;
7292 }
7293 b'c' => {
7294 let ch = args.next_arg::<c_int>();
7295 if width > 1 {
7296 let pad = width - 1;
7297 if flags & FLAG_MINUS != 0 {
7298 ($write_char)(ch as u8); count += 1;
7299 for _ in 0..pad { ($write_char)(b' '); count += 1; }
7300 } else {
7301 for _ in 0..pad { ($write_char)(b' '); count += 1; }
7302 ($write_char)(ch as u8); count += 1;
7303 }
7304 } else {
7305 ($write_char)(ch as u8); count += 1;
7306 }
7307 }
7308 b'p' => {
7309 let p = args.next_arg::<*const c_void>();
7310 let mut fbuf = [0u8; 20];
7311 fbuf[0] = b'0'; fbuf[1] = b'x';
7312 let b = format_hex(p as u64, false);
7313 core::ptr::copy_nonoverlapping(b.0.as_ptr(), fbuf.as_mut_ptr().add(2), b.1);
7314 ($write_str)(fbuf.as_ptr(), b.1 + 2); count += b.1 + 2;
7315 }
7316 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
7317 let val = args.next_arg::<f64>();
7318 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
7319 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
7320 let mut fbuf = [0u8; 4224];
7321 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
7322 let total = apply_width_flags(fbuf.as_mut_ptr().add(4096), fbuf.as_ptr(), flen, width, flags);
7323 core::ptr::copy_nonoverlapping(fbuf.as_ptr().add(4096), fbuf.as_mut_ptr(), total);
7324 ($write_str)(fbuf.as_ptr(), total); count += total;
7325 }
7326 b'%' => { ($write_char)(b'%'); count += 1; }
7327 b'n' => {
7328 let p = args.next_arg::<*mut c_void>();
7329 if !p.is_null() { *(p as *mut c_int) = count as c_int; }
7330 }
7331 _ => { ($write_char)(b'%'); ($write_char)(spec); count += 2; }
7332 }
7333 }
7334 i += 1;
7335 }
7336 count as c_int
7337 }};
7338}
7339
7340unsafe fn format_u64(mut val: u64) -> ([u8; 20], usize) {
7341 let mut buf = [0u8; 20];
7342 if val == 0 { buf[0] = b'0'; return (buf, 1); }
7343 let mut tmp = [0u8; 20];
7344 let mut pos = 20;
7345 while val > 0 { pos -= 1; tmp[pos] = b'0' + (val % 10) as u8; val /= 10; }
7346 let len = 20 - pos;
7347 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
7348 (buf, len)
7349}
7350
7351unsafe fn format_i64(val: i64) -> ([u8; 21], usize) {
7352 let mut buf = [0u8; 21];
7353 if val < 0 {
7354 buf[0] = b'-';
7355 let (inner, len) = format_u64((-(val as i128)) as u64);
7356 core::ptr::copy_nonoverlapping(inner.as_ptr(), buf.as_mut_ptr().add(1), len);
7357 (buf, len + 1)
7358 } else {
7359 let (inner, len) = format_u64(val as u64);
7360 core::ptr::copy_nonoverlapping(inner.as_ptr(), buf.as_mut_ptr(), len);
7361 (buf, len)
7362 }
7363}
7364
7365unsafe fn format_hex(mut val: u64, uppercase: bool) -> ([u8; 16], usize) {
7366 let digits = if uppercase { b"0123456789ABCDEF" } else { b"0123456789abcdef" };
7367 let mut buf = [0u8; 16];
7368 if val == 0 { buf[0] = b'0'; return (buf, 1); }
7369 let mut tmp = [0u8; 16];
7370 let mut pos = 16;
7371 while val > 0 { pos -= 1; tmp[pos] = digits[(val & 0xf) as usize]; val >>= 4; }
7372 let len = 16 - pos;
7373 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
7374 (buf, len)
7375}
7376
7377unsafe fn format_octal(mut val: u64, alt: bool) -> ([u8; 24], usize) {
7378 let mut buf = [0u8; 24];
7379 if val == 0 {
7380 buf[0] = b'0';
7381 return (buf, 1);
7382 }
7383 let mut tmp = [0u8; 24];
7384 let mut pos = 24;
7385 while val > 0 {
7386 pos -= 1;
7387 tmp[pos] = b'0' + (val & 7) as u8;
7388 val >>= 3;
7389 }
7390 let len = 24 - pos;
7391 if alt {
7392 tmp[pos - 1] = b'0';
7393 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos - 1), buf.as_mut_ptr(), len + 1);
7394 (buf, len + 1)
7395 } else {
7396 core::ptr::copy_nonoverlapping(tmp.as_ptr().add(pos), buf.as_mut_ptr(), len);
7397 (buf, len)
7398 }
7399}
7400
7401unsafe fn format_int(
7402 dst: *mut u8,
7403 digits: *const u8,
7404 digits_len: usize,
7405 sign: Option<u8>,
7406 prefix: Option<u8>,
7407 precision: i32,
7408 width: usize,
7409 flags: u8,
7410 octal_alt: bool,
7411) -> usize {
7412 let num_digits = if precision == 0 && digits_len == 1 && *digits == b'0' && !octal_alt {
7413 0
7414 } else {
7415 digits_len
7416 };
7417 let prec = precision as usize;
7418 let zero_pad = if precision >= 0 && prec > num_digits { prec - num_digits } else { 0 };
7419
7420 let sign_len = sign.map_or(0, |_| 1);
7421 let prefix_len = prefix.map_or(0, |_| 2);
7422 let content_len = sign_len + prefix_len + zero_pad + num_digits;
7423
7424 let mut buf = [0u8; 32];
7425 let mut pos = 0usize;
7426 if let Some(c) = sign { buf[pos] = c; pos += 1; }
7427 if let Some(c) = prefix { buf[pos] = b'0'; pos += 1; buf[pos] = c; pos += 1; }
7428 for _ in 0..zero_pad { buf[pos] = b'0'; pos += 1; }
7429 if num_digits > 0 {
7430 core::ptr::copy_nonoverlapping(digits, buf.as_mut_ptr().add(pos), num_digits);
7431 }
7432
7433 if content_len >= width {
7434 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, content_len);
7435 return content_len;
7436 }
7437 let pad = width - content_len;
7438 if flags & FLAG_MINUS != 0 {
7439 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, content_len);
7440 for i in 0..pad { *dst.add(content_len + i) = b' '; }
7441 } else if flags & FLAG_ZERO != 0 && precision < 0 {
7442 let fixed = sign_len + prefix_len;
7443 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst, fixed);
7444 for i in fixed..width - num_digits { *dst.add(i) = b'0'; }
7445 if num_digits > 0 {
7446 core::ptr::copy_nonoverlapping(digits, dst.add(width - num_digits), num_digits);
7447 }
7448 } else {
7449 for i in 0..pad { *dst.add(i) = b' '; }
7450 core::ptr::copy_nonoverlapping(buf.as_ptr(), dst.add(pad), content_len);
7451 }
7452 width
7453}
7454
7455unsafe fn format_f64(val: f64) -> ([u8; 64], usize) {
7456 let mut buf = [0u8; 64];
7457 let mut pos = 0usize;
7458 let mut v = val;
7459 if v.is_nan() {
7460 let nan = b"nan";
7461 core::ptr::copy_nonoverlapping(nan.as_ptr(), buf.as_mut_ptr(), 3);
7462 return (buf, 3);
7463 }
7464 if v < 0.0 { buf[pos] = b'-'; pos += 1; v = -v; }
7465 if v.is_infinite() {
7466 let inf = b"inf";
7467 core::ptr::copy_nonoverlapping(inf.as_ptr(), buf.as_mut_ptr().add(pos), 3);
7468 return (buf, pos + 3);
7469 }
7470 let int_part = v as u64;
7471 let frac = v - int_part as f64;
7472 let (ibuf, ilen) = format_u64(int_part);
7473 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), buf.as_mut_ptr().add(pos), ilen);
7474 pos += ilen;
7475 buf[pos] = b'.';
7476 pos += 1;
7477 let mut f = frac;
7478 for _ in 0..6 { f *= 10.0; let digit = f as u8; buf[pos] = b'0' + digit; pos += 1; f -= digit as f64; }
7479 (buf, pos)
7480}
7481
7482const FMT_F: u8 = 0;
7484const FMT_E: u8 = 1;
7485const FMT_G: u8 = 2;
7486const FMT_A: u8 = 3;
7487
7488const FLAG_HASH: u8 = 1;
7489const FLAG_PLUS: u8 = 2;
7490const FLAG_SPACE: u8 = 4;
7491const FLAG_ZERO: u8 = 8;
7492const FLAG_MINUS: u8 = 16;
7493
7494unsafe fn bigint_to_decimal(buf: *mut u8, mant: u64, shift: u32) -> usize {
7499 let nlimbs = (2 + (shift + 31) / 32) as usize;
7501 let mut limbs = [0u32; 36];
7502 limbs[0] = mant as u32;
7503 limbs[1] = (mant >> 32) as u32;
7504
7505 let ws = (shift / 32) as usize;
7506 let bs = shift % 32;
7507
7508 if ws > 0 {
7510 let mut i = 1usize;
7511 loop {
7512 limbs[i + ws] = limbs[i];
7513 if i == 0 { break; }
7514 i -= 1;
7515 }
7516 for j in 0..ws { limbs[j] = 0; }
7517 }
7518 if bs > 0 {
7520 let mut carry = 0u32;
7521 let end = nlimbs.min(ws + 3);
7522 for i in ws..end {
7523 let new_val = (limbs[i] << bs) | carry;
7524 carry = limbs[i] >> (32 - bs);
7525 limbs[i] = new_val;
7526 }
7527 }
7528
7529 let mut used = nlimbs;
7531 while used > 0 && limbs[used - 1] == 0 { used -= 1; }
7532 if used == 0 { *buf = b'0'; return 1; }
7533
7534 let mut digits = [0u8; 400];
7536 let mut nd = 0usize;
7537 loop {
7538 let mut all_zero = true;
7539 for i in 0..used { if limbs[i] != 0 { all_zero = false; break; } }
7540 if all_zero { break; }
7541 let mut rem = 0u64;
7542 for i in (0..used).rev() {
7543 let val = (rem << 32) | limbs[i] as u64;
7544 limbs[i] = (val / 10) as u32;
7545 rem = val % 10;
7546 }
7547 digits[nd] = rem as u8;
7548 nd += 1;
7549 }
7550 for i in 0..nd { *buf.add(i) = b'0' + digits[nd - 1 - i]; }
7552 nd
7553}
7554
7555unsafe fn frac_digits_u128(buf: *mut u8, frac_bits: u64, shift: u32, count: usize) -> bool {
7558 let mask: u128 = (1u128 << shift) - 1;
7559 let mut rem = frac_bits as u128;
7560 for i in 0..count {
7561 rem *= 10;
7562 let digit = (rem >> shift) as u8;
7563 rem &= mask;
7564 *buf.add(i) = digit;
7565 }
7566 rem != 0
7567}
7568
7569unsafe fn frac_digits_bigint(buf: *mut u8, frac_bits: u64, shift: u32, count: usize) -> bool {
7572 let nlimbs = ((shift + 31) / 32) as usize;
7573 let mut rem = [0u32; 36]; rem[0] = frac_bits as u32;
7575 if nlimbs > 1 { rem[1] = (frac_bits >> 32) as u32; }
7576 let hi_word = (shift / 32) as usize;
7578 let hi_bit = shift % 32;
7579 if hi_bit > 0 && hi_word < nlimbs {
7580 rem[hi_word] &= (1u32 << hi_bit) - 1;
7581 }
7582 let clear_from = if hi_bit > 0 { hi_word + 1 } else { hi_word };
7584 for j in clear_from..nlimbs { rem[j] = 0; }
7585
7586 for i in 0..count {
7587 let mut carry = 0u64;
7589 for j in 0..nlimbs {
7590 let val = rem[j] as u64 * 10 + carry;
7591 rem[j] = val as u32;
7592 carry = val >> 32;
7593 }
7594 let digit: u32;
7596 if hi_bit == 0 {
7597 digit = if hi_word < nlimbs { rem[hi_word] } else { carry as u32 };
7598 } else {
7599 let mut d = if hi_word < nlimbs { rem[hi_word] >> hi_bit } else { 0 };
7600 if hi_word + 1 < nlimbs {
7601 d |= rem[hi_word + 1] << (32 - hi_bit);
7602 } else if carry > 0 {
7603 d |= (carry as u32) << (32 - hi_bit);
7604 }
7605 digit = d;
7606 }
7607 *buf.add(i) = digit.min(9) as u8;
7608 if hi_bit == 0 {
7610 if hi_word < nlimbs { rem[hi_word] = 0; }
7611 } else {
7612 if hi_word < nlimbs {
7613 rem[hi_word] &= (1u32 << hi_bit) - 1;
7614 }
7615 for j in (hi_word + 1)..nlimbs { rem[j] = 0; }
7616 }
7617 }
7618 for i in 0..nlimbs { if rem[i] != 0 { return true; } }
7620 false
7621}
7622
7623unsafe fn increment_decimal(buf: *mut u8, len: &mut usize) {
7625 let mut j = *len;
7626 loop {
7627 if j == 0 {
7628 let l = *len;
7630 for i in (0..l).rev() { *buf.add(i + 1) = *buf.add(i); }
7631 *buf = b'1';
7632 *len = l + 1;
7633 return;
7634 }
7635 j -= 1;
7636 let d = *buf.add(j);
7637 if d < b'9' { *buf.add(j) = d + 1; return; }
7638 *buf.add(j) = b'0';
7639 }
7640}
7641
7642unsafe fn format_f64_full(
7644 dst: *mut u8, val: f64, fmt_type: u8, precision: i32, flags: u8, uppercase: bool,
7645) -> usize {
7646 let mut pos = 0usize;
7647
7648 if val.is_nan() {
7650 let nan_s: &[u8] = if uppercase { b"NAN" } else { b"nan" };
7651 core::ptr::copy_nonoverlapping(nan_s.as_ptr(), dst, 3);
7652 return 3;
7653 }
7654 let neg = val.is_sign_negative();
7655 let v = if neg { -val } else { val };
7656
7657 if v.is_infinite() {
7659 if neg { *dst.add(pos) = b'-'; pos += 1; }
7660 else if flags & FLAG_PLUS != 0 { *dst.add(pos) = b'+'; pos += 1; }
7661 else if flags & FLAG_SPACE != 0 { *dst.add(pos) = b' '; pos += 1; }
7662 let inf_s: &[u8] = if uppercase { b"INF" } else { b"inf" };
7663 core::ptr::copy_nonoverlapping(inf_s.as_ptr(), dst.add(pos), 3);
7664 return pos + 3;
7665 }
7666
7667 if neg { *dst.add(pos) = b'-'; pos += 1; }
7669 else if flags & FLAG_PLUS != 0 { *dst.add(pos) = b'+'; pos += 1; }
7670 else if flags & FLAG_SPACE != 0 { *dst.add(pos) = b' '; pos += 1; }
7671
7672 if fmt_type == FMT_A {
7674 return pos + fmt_hex_float(dst.add(pos), val, precision, flags, uppercase);
7675 }
7676
7677 let p: usize;
7679 let mut exp: i32;
7680 let use_f: bool;
7681
7682 match fmt_type {
7683 FMT_G => {
7684 let gp = if precision < 0 { 6usize } else if precision == 0 { 1usize } else { precision as usize };
7685 exp = if v > 0.0 { compute_exp10(v) } else { 0 };
7686 use_f = exp >= -4 && exp < gp as i32;
7687 if use_f {
7688 p = if exp < 0 { gp + ((-exp) as usize - 1) }
7689 else if (exp as usize) < gp { gp - exp as usize - 1 }
7690 else { 0 };
7691 } else {
7692 p = gp - 1;
7693 }
7694 }
7695 FMT_E => {
7696 p = if precision < 0 { 6usize } else { precision as usize };
7697 exp = if v > 0.0 { compute_exp10(v) } else { 0 };
7698 use_f = false;
7699 }
7700 _ => {
7701 p = if precision < 0 { 6usize } else { precision as usize };
7702 exp = 0;
7703 use_f = true;
7704 }
7705 }
7706
7707 if v == 0.0 {
7708 *dst.add(pos) = b'0'; pos += 1;
7709 if !(fmt_type == FMT_G && flags & FLAG_HASH == 0) {
7710 if p > 0 || flags & FLAG_HASH != 0 {
7711 *dst.add(pos) = b'.'; pos += 1;
7712 for _ in 0..p { *dst.add(pos) = b'0'; pos += 1; }
7713 }
7714 }
7715 if !use_f {
7716 let ec = if uppercase { b'E' } else { b'e' };
7717 *dst.add(pos) = ec; pos += 1;
7718 *dst.add(pos) = b'+'; pos += 1;
7719 *dst.add(pos) = b'0'; pos += 1;
7720 *dst.add(pos) = b'0'; pos += 1;
7721 }
7722 return pos;
7723 }
7724
7725 if use_f {
7727 let bits = v.to_bits();
7728 let raw_mant = bits & 0x000FFFFFFFFFFFFF;
7729 let raw_exp_bits = ((bits >> 52) & 0x7FF) as i32;
7730 let (mant_b, bin_exp) = if raw_exp_bits == 0 {
7731 (raw_mant, -1022i32)
7732 } else {
7733 (raw_mant | (1u64 << 52), raw_exp_bits - 1023)
7734 };
7735
7736 let mut ibuf = [0u8; 400];
7738 let mut ilen: usize;
7739 if bin_exp < 0 {
7740 ibuf[0] = b'0'; ilen = 1;
7741 } else if bin_exp <= 63 {
7742 let int_val = if bin_exp <= 52 { mant_b >> (52 - bin_exp) }
7743 else { mant_b << (bin_exp - 52) };
7744 let (buf2, len2) = format_u64(int_val);
7745 ibuf[..len2].copy_from_slice(&buf2[..len2]);
7746 ilen = len2;
7747 } else {
7748 ilen = bigint_to_decimal(ibuf.as_mut_ptr(), mant_b, (bin_exp - 52) as u32);
7749 }
7750
7751 let mut fbuf = [0u8; 1100];
7753 let mut has_rest = false;
7754 if p > 0 && bin_exp < 52 {
7755 let shift = (52 - bin_exp) as u32;
7756 let frac_bits = if bin_exp >= 0 { mant_b & ((1u64 << shift) - 1) } else { mant_b };
7757 if shift <= 124 {
7758 has_rest = frac_digits_u128(fbuf.as_mut_ptr(), frac_bits, shift, p + 1);
7759 } else {
7760 has_rest = frac_digits_bigint(fbuf.as_mut_ptr(), frac_bits, shift, p + 1);
7761 }
7762 }
7763
7764 if p > 0 && bin_exp < 52 {
7766 let next_d = fbuf[p];
7767 let last_d = fbuf[p - 1];
7768 if next_d > 5 || (next_d == 5 && (has_rest || last_d & 1 != 0)) {
7769 let mut carry = true;
7770 for j in (0..p).rev() {
7771 if !carry { break; }
7772 fbuf[j] += 1;
7773 if fbuf[j] < 10 { carry = false; break; }
7774 fbuf[j] = 0;
7775 }
7776 if carry { increment_decimal(ibuf.as_mut_ptr(), &mut ilen); }
7777 }
7778 } else if p == 0 {
7779 if bin_exp >= 0 && bin_exp < 52 {
7781 let shift = (52 - bin_exp) as u32;
7782 let frac_bits = mant_b & ((1u64 << shift) - 1);
7783 let half = 1u64 << (shift - 1);
7784 let last_d = ibuf[ilen - 1] - b'0';
7785 if frac_bits > half || (frac_bits == half && last_d & 1 != 0) {
7786 increment_decimal(ibuf.as_mut_ptr(), &mut ilen);
7787 }
7788 }
7789 }
7790
7791 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), dst.add(pos), ilen);
7793 pos += ilen;
7794 if p > 0 || flags & FLAG_HASH != 0 {
7795 *dst.add(pos) = b'.'; pos += 1;
7796 for i in 0..p { *dst.add(pos) = b'0' + fbuf[i]; pos += 1; }
7797 }
7798 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7799 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7800 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7801 }
7802 return pos;
7803 }
7804
7805 let mut fbuf = [0u8; 20];
7808 let mut int_part: u64;
7809 {
7810 let bits_v = v.to_bits();
7811 let raw_mant_v = bits_v & 0x000FFFFFFFFFFFFF;
7812 let raw_exp_v = ((bits_v >> 52) & 0x7FF) as i32;
7813 let (mant_b_v, bin_exp_v) = if raw_exp_v == 0 {
7814 (raw_mant_v, -1022i32)
7815 } else {
7816 (raw_mant_v | (1u64 << 52), raw_exp_v - 1023)
7817 };
7818
7819 let s: i32 = (p as i32) + 1 - exp;
7820 let bs: i32 = bin_exp_v - 52 + s;
7821
7822 let mut limbs = [0u32; 40];
7823 limbs[0] = mant_b_v as u32;
7824 limbs[1] = (mant_b_v >> 32) as u32;
7825 let mut nlimbs: usize = if limbs[1] != 0 { 2 } else { 1 };
7826
7827 if s > 0 {
7828 for _ in 0..(s as usize) {
7829 let mut carry = 0u64;
7830 for j in 0..nlimbs {
7831 let val = limbs[j] as u64 * 5 + carry;
7832 limbs[j] = val as u32;
7833 carry = val >> 32;
7834 }
7835 if carry > 0 { limbs[nlimbs] = carry as u32; nlimbs += 1; }
7836 }
7837 }
7838
7839 if bs > 0 {
7840 let ws = (bs as u32 / 32) as usize;
7841 let bit = bs as u32 % 32;
7842 if ws > 0 {
7843 let mut i = nlimbs;
7844 while i > 0 { i -= 1; if i + ws < 40 { limbs[i + ws] = limbs[i]; } limbs[i] = 0; }
7845 nlimbs += ws;
7846 }
7847 if bit > 0 {
7848 let mut carry = 0u32;
7849 for i in ws..nlimbs {
7850 let new_val = (limbs[i] << bit) | carry;
7851 carry = limbs[i] >> (32 - bit);
7852 limbs[i] = new_val;
7853 }
7854 if carry > 0 && nlimbs < 40 { limbs[nlimbs] = carry; nlimbs += 1; }
7855 }
7856 }
7857
7858 let mut has_rest = false;
7859 if s < 0 {
7860 for _ in 0..(-s as usize) {
7861 let mut rem = 0u64;
7862 for i in (0..nlimbs).rev() {
7863 let val = (rem << 32) | limbs[i] as u64;
7864 limbs[i] = (val / 5) as u32;
7865 rem = val % 5;
7866 }
7867 if rem != 0 { has_rest = true; }
7868 }
7869 }
7870
7871 if bs < 0 {
7872 let rshift = (-bs) as u32;
7873 let ws = (rshift / 32) as usize;
7874 let bit = rshift % 32;
7875 if ws > 0 {
7876 for j in 0..ws.min(nlimbs) { if limbs[j] != 0 { has_rest = true; } }
7877 for i in ws..nlimbs { limbs[i - ws] = limbs[i]; }
7878 nlimbs = nlimbs.saturating_sub(ws);
7879 }
7880 if bit > 0 && nlimbs > 0 {
7881 let mask = (1u32 << bit) - 1;
7882 if limbs[0] & mask != 0 { has_rest = true; }
7883 for i in 0..nlimbs - 1 {
7884 limbs[i] = (limbs[i] >> bit) | (limbs[i + 1] << (32 - bit));
7885 }
7886 limbs[nlimbs - 1] >>= bit;
7887 }
7888 }
7889
7890 while nlimbs > 0 && limbs[nlimbs - 1] == 0 { nlimbs -= 1; }
7891
7892 let ndigits = p + 2;
7893 let mut all_digits = [0u8; 25];
7894 let mut nd = 0usize;
7895 if nlimbs > 0 {
7896 loop {
7897 let mut all_zero = true;
7898 for i in 0..nlimbs { if limbs[i] != 0 { all_zero = false; break; } }
7899 if all_zero { break; }
7900 let mut rem64 = 0u64;
7901 for i in (0..nlimbs).rev() {
7902 let val = (rem64 << 32) | limbs[i] as u64;
7903 limbs[i] = (val / 10) as u32;
7904 rem64 = val % 10;
7905 }
7906 if nd < 25 { all_digits[nd] = rem64 as u8; }
7907 nd += 1;
7908 }
7909 }
7910
7911 if nd >= ndigits {
7912 for i in 0..ndigits { fbuf[ndigits - 1 - i] = all_digits[i]; }
7913 } else {
7914 for i in 0..nd { fbuf[ndigits - 1 - i] = all_digits[i]; }
7915 for i in nd..ndigits { fbuf[ndigits - 1 - i] = 0; }
7916 }
7917
7918 int_part = fbuf[0] as u64;
7919
7920 if p > 0 {
7922 let next_d = fbuf[p + 1];
7923 let last_d = fbuf[p];
7924 if next_d > 5 || (next_d == 5 && (has_rest || last_d & 1 != 0)) {
7925 let mut carry = true;
7926 for j in (1..=p).rev() {
7927 if !carry { break; }
7928 let d = fbuf[j] + 1;
7929 if d < 10 { fbuf[j] = d; carry = false; break; }
7930 fbuf[j] = 0;
7931 }
7932 if carry { int_part += 1; }
7933 }
7934 } else {
7935 let next_d = fbuf[1];
7936 if next_d > 5 || (next_d == 5 && (has_rest || int_part & 1 != 0)) {
7937 int_part += 1;
7938 }
7939 }
7940
7941 for i in 0..p { fbuf[i] = fbuf[i + 1]; }
7944 }
7945
7946 if !use_f && int_part >= 10 {
7947 exp += 1;
7948 int_part = 1;
7949 }
7950
7951 if use_f {
7953 let (ibuf, ilen) = format_u64(int_part);
7955 core::ptr::copy_nonoverlapping(ibuf.as_ptr(), dst.add(pos), ilen);
7956 pos += ilen;
7957 if p > 0 || flags & FLAG_HASH != 0 {
7958 *dst.add(pos) = b'.'; pos += 1;
7959 for idx in 0..p { *dst.add(pos) = b'0' + fbuf[idx]; pos += 1; }
7960 }
7961 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7962 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7963 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7964 }
7965 } else {
7966 *dst.add(pos) = b'0' + int_part as u8; pos += 1;
7968 if p > 0 || flags & FLAG_HASH != 0 {
7969 *dst.add(pos) = b'.'; pos += 1;
7970 for idx in 0..p { *dst.add(pos) = b'0' + fbuf[idx]; pos += 1; }
7971 }
7972 if fmt_type == FMT_G && flags & FLAG_HASH == 0 {
7973 while pos > 0 && *dst.add(pos - 1) == b'0' { pos -= 1; }
7974 if pos > 0 && *dst.add(pos - 1) == b'.' { pos -= 1; }
7975 }
7976 let ec = if uppercase { b'E' } else { b'e' };
7977 *dst.add(pos) = ec; pos += 1;
7978 *dst.add(pos) = if exp < 0 { b'-' } else { b'+' }; pos += 1;
7979 let eabs = if exp < 0 { (-exp) as u32 } else { exp as u32 };
7980 if eabs < 10 { *dst.add(pos) = b'0'; pos += 1; }
7981 let (ebuf, elen) = format_u64(eabs as u64);
7982 core::ptr::copy_nonoverlapping(ebuf.as_ptr(), dst.add(pos), elen);
7983 pos += elen;
7984 }
7985
7986 pos
7987}
7988
7989unsafe fn compute_exp10(v: f64) -> i32 {
7991 let e = libm::floor(libm::log10(v)) as i32;
7992 let probe = v / libm::pow(10.0, e as f64);
7993 if probe >= 10.0 { e + 1 }
7994 else if probe < 1.0 { e - 1 }
7995 else { e }
7996}
7997
7998unsafe fn fmt_hex_float(dst: *mut u8, val: f64, precision: i32, _flags: u8, uppercase: bool) -> usize {
8000 if val.to_bits() & 0x7FFFFFFFFFFFFFFF == 0 {
8002 let lc = !uppercase;
8003 let pfx: &[u8] = if lc { b"0x" } else { b"0X" };
8004 let p = if precision < 0 { 0usize } else { precision as usize };
8005 let mut pos = 0usize;
8006 core::ptr::copy_nonoverlapping(pfx.as_ptr(), dst.add(pos), 2); pos += 2;
8007 *dst.add(pos) = b'0'; pos += 1;
8008 if p > 0 {
8009 *dst.add(pos) = b'.'; pos += 1;
8010 for _ in 0..p { *dst.add(pos) = b'0'; pos += 1; }
8011 }
8012 let pc = if lc { b'p' } else { b'P' };
8013 *dst.add(pos) = pc; pos += 1;
8014 *dst.add(pos) = b'+'; pos += 1;
8015 *dst.add(pos) = b'0'; pos += 1;
8016 return pos;
8017 }
8018 let bits = val.to_bits();
8019 let exp_bits = ((bits >> 52) & 0x7FF) as i32;
8020 let mant_bits = bits & 0x000FFFFFFFFFFFFF;
8021 let (mut e, mut m) = if exp_bits == 0 { (1 - 1023, mant_bits) } else { (exp_bits - 1023, mant_bits | (1u64 << 52)) };
8022 if exp_bits == 0 && m != 0 {
8025 let shift = m.leading_zeros() as i32 - 11;
8026 m <<= shift;
8027 e -= shift;
8028 }
8029 let explicit = precision >= 0;
8030 let p = if explicit { precision as usize } else { 13usize };
8031 let mut pos = 0usize;
8032 let lc = !uppercase;
8033 let pfx: &[u8] = if lc { b"0x" } else { b"0X" };
8034 core::ptr::copy_nonoverlapping(pfx.as_ptr(), dst.add(pos), 2); pos += 2;
8035
8036 let lead_pos = pos;
8038 let mut lead = ((m >> 52) & 0xF) as u8;
8039 *dst.add(pos) = hex_digit_char(lead, lc); pos += 1;
8040 let mut frac_start = pos;
8041 if p > 0 {
8042 *dst.add(pos) = b'.'; pos += 1;
8043 frac_start = pos;
8044 }
8045
8046 let mut rm = m;
8048 for _ in 0..p {
8049 let nib = ((rm >> 48) & 0xF) as u8;
8050 *dst.add(pos) = hex_digit_char(nib, lc); pos += 1;
8051 rm <<= 4;
8052 }
8053
8054 let round_nib = ((rm >> 48) & 0xF) as u8;
8056 let rest = rm & 0x0000FFFFFFFFFFFF;
8057 let last_nib = if p > 0 {
8058 hex_char_val(*dst.add(pos - 1))
8059 } else {
8060 lead
8061 };
8062 let should_round = round_nib > 8 || (round_nib == 8 && (rest != 0 || (last_nib & 1) != 0));
8063 if should_round {
8064 let mut j = pos;
8065 loop {
8066 if j == frac_start {
8067 lead += 1;
8069 *dst.add(lead_pos) = hex_digit_char(lead, lc);
8070 break;
8071 }
8072 j -= 1;
8073 let v = hex_char_val(*dst.add(j));
8074 if v < 15 {
8075 *dst.add(j) = hex_digit_char(v + 1, lc);
8076 break;
8077 }
8078 *dst.add(j) = b'0';
8079 }
8080 }
8081
8082 if !explicit {
8085 while pos > frac_start && *dst.add(pos - 1) == b'0' {
8086 pos -= 1;
8087 }
8088 if pos == frac_start {
8089 pos = frac_start - 1;
8090 }
8091 }
8092
8093 let pc = if lc { b'p' } else { b'P' };
8095 *dst.add(pos) = pc; pos += 1;
8096 *dst.add(pos) = if e < 0 { b'-' } else { b'+' }; pos += 1;
8097 let eabs = if e < 0 { (-e) as u32 } else { e as u32 };
8098 let (ebuf, elen) = format_u64(eabs as u64);
8099 core::ptr::copy_nonoverlapping(ebuf.as_ptr(), dst.add(pos), elen);
8100 pos += elen;
8101 pos
8102}
8103
8104#[inline]
8105fn hex_digit_char(v: u8, lowercase: bool) -> u8 {
8106 if v < 10 { b'0' + v }
8107 else if lowercase { b'a' + v - 10 }
8108 else { b'A' + v - 10 }
8109}
8110
8111#[inline]
8112fn hex_char_val(c: u8) -> u8 {
8113 if c >= b'0' && c <= b'9' { c - b'0' }
8114 else if c >= b'a' && c <= b'f' { c - b'a' + 10 }
8115 else if c >= b'A' && c <= b'F' { c - b'A' + 10 }
8116 else { 0 }
8117}
8118
8119unsafe fn apply_width_flags(
8122 dst: *mut u8, buf: *const u8, len: usize, width: usize, flags: u8,
8123) -> usize {
8124 if len >= width {
8125 core::ptr::copy_nonoverlapping(buf, dst, len);
8126 return len;
8127 }
8128 let pad = width - len;
8129 let pad_char = if flags & FLAG_ZERO != 0 && flags & FLAG_MINUS == 0 { b'0' } else { b' ' };
8130 if flags & FLAG_MINUS != 0 {
8131 core::ptr::copy_nonoverlapping(buf, dst, len);
8133 for i in 0..pad { *dst.add(len + i) = pad_char; }
8134 } else {
8135 if flags & FLAG_ZERO != 0 && len > 0 {
8138 let first = *buf;
8139 if first == b'-' || first == b'+' || first == b' ' {
8140 *dst = first;
8141 for i in 0..pad { *dst.add(1 + i) = pad_char; }
8142 core::ptr::copy_nonoverlapping(buf.add(1), dst.add(1 + pad), len - 1);
8143 return width;
8144 }
8145 }
8146 for i in 0..pad { *dst.add(i) = pad_char; }
8147 core::ptr::copy_nonoverlapping(buf, dst.add(pad), len);
8148 }
8149 width
8150}
8151
8152#[no_mangle]
8153pub unsafe extern "C" fn vprintf(fmt: *const c_char, mut args: VaList) -> c_int {
8154 impl_format!(fmt, args,
8155 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stdout); },
8156 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stdout); }
8157 )
8158}
8159
8160#[no_mangle]
8161pub unsafe extern "C" fn vfprintf(stream: *mut FILE, fmt: *const c_char, mut args: VaList) -> c_int {
8162 impl_format!(fmt, args,
8163 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stream); },
8164 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stream); }
8165 )
8166}
8167
8168#[no_mangle]
8169pub unsafe extern "C" fn printf(fmt: *const c_char, mut args: ...) -> c_int {
8170 impl_format!(fmt, args,
8171 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stdout); },
8172 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stdout); }
8173 )
8174}
8175
8176#[no_mangle]
8177pub unsafe extern "C" fn fprintf(stream: *mut FILE, fmt: *const c_char, mut args: ...) -> c_int {
8178 impl_format!(fmt, args,
8179 |c: u8| { let _ = fwrite(&c as *const u8 as *const c_void, 1, 1, stream); },
8180 |s: *const u8, len: usize| { let _ = fwrite(s as *const c_void, 1, len, stream); }
8181 )
8182}
8183
8184#[no_mangle]
8185unsafe fn format_write_fd(fd: c_int, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
8186 let mut stack = [0u8; 4096];
8189 let mut a1 = args.clone();
8190 let n = format_to_buf(stack.as_mut_ptr(), stack.len(), fmt, &mut a1);
8191 if n < 0 { return -1; }
8192 if (n as usize) < stack.len() {
8193 let w = crate::write(fd, stack.as_ptr() as *const c_void, n as usize);
8194 if w < 0 { return -1; }
8195 return n;
8196 }
8197 let heap = crate::malloc(n as usize + 1) as *mut u8;
8198 if heap.is_null() { return -1; }
8199 let mut a2 = args.clone();
8200 let n2 = format_to_buf(heap, n as usize + 1, fmt, &mut a2);
8201 if n2 < 0 { crate::free(heap as *mut c_void); return -1; }
8202 let w = crate::write(fd, heap as *const c_void, n2 as usize);
8203 crate::free(heap as *mut c_void);
8204 if w < 0 { return -1; }
8205 n2
8206}
8207
8208#[no_mangle]
8209pub unsafe extern "C" fn dprintf(fd: c_int, fmt: *const c_char, mut args: ...) -> c_int {
8210 format_write_fd(fd, fmt, &mut args)
8211}
8212
8213#[no_mangle]
8214pub unsafe extern "C" fn vdprintf(fd: c_int, fmt: *const c_char, mut args: VaList) -> c_int {
8215 format_write_fd(fd, fmt, &mut args)
8216}
8217
8218unsafe fn format_to_buf(buf: *mut u8, cap: usize, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
8223 let mut pos = 0usize;
8224 let mut i = 0usize;
8225 let mut count = 0usize;
8226 macro_rules! wc {
8227 ($c:expr) => { if pos < cap { *buf.add(pos) = $c; } pos += 1; count += 1; }
8228 }
8229 macro_rules! ws {
8230 ($s:expr, $len:expr) => {{
8231 let __len = $len;
8232 for k in 0..__len { if pos + k < cap { *buf.add(pos + k) = *$s.add(k); } }
8233 pos += __len; count += __len;
8234 }}
8235 }
8236 macro_rules! ws_buf {
8238 ($src:expr, $len:expr) => {{
8239 let __len = $len;
8240 for k in 0..__len { if pos + k < cap { *buf.add(pos + k) = *$src.add(k); } }
8241 pos += __len; count += __len;
8242 }}
8243 }
8244 loop {
8245 let c = *fmt.add(i) as u8;
8246 if c == 0 { break; }
8247 if c != b'%' { wc!(c); i += 1; continue; }
8248 i += 1;
8249 let mut flags: u8 = 0;
8251 loop {
8252 let fc = *fmt.add(i) as u8;
8253 match fc {
8254 b'-' => { flags |= FLAG_MINUS; i += 1; }
8255 b'+' => { flags |= FLAG_PLUS; i += 1; }
8256 b' ' => { flags |= FLAG_SPACE; i += 1; }
8257 b'0' => { flags |= FLAG_ZERO; i += 1; }
8258 b'#' => { flags |= FLAG_HASH; i += 1; }
8259 _ => break,
8260 }
8261 }
8262 let mut width: usize = 0;
8264 if *fmt.add(i) as u8 == b'*' {
8265 width = args.next_arg::<c_int>() as usize; i += 1;
8266 } else {
8267 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
8268 width = width * 10 + ((*fmt.add(i) as u8) - b'0') as usize; i += 1;
8269 }
8270 }
8271 let mut precision: i32 = -1;
8273 if *fmt.add(i) as u8 == b'.' {
8274 i += 1;
8275 if *fmt.add(i) as u8 == b'*' {
8276 precision = args.next_arg::<c_int>(); i += 1;
8277 } else {
8278 precision = 0;
8279 while (*fmt.add(i) as u8) >= b'0' && (*fmt.add(i) as u8) <= b'9' {
8280 precision = precision * 10 + ((*fmt.add(i) as u8) - b'0') as i32; i += 1;
8281 }
8282 }
8283 }
8284 let len_mod = *fmt.add(i) as u8;
8286 let spec: u8;
8287 if len_mod == b'h' || len_mod == b'l' || len_mod == b'j' || len_mod == b'z' || len_mod == b't' || len_mod == b'L' {
8288 i += 1;
8289 let len_mod2 = *fmt.add(i) as u8;
8290 if (len_mod == b'h' && len_mod2 == b'h') || (len_mod == b'l' && len_mod2 == b'l') {
8291 i += 1;
8292 spec = *fmt.add(i) as u8;
8293 match (len_mod, len_mod2, spec) {
8294 (b'h', b'h', b'n') => {
8295 let p = args.next_arg::<*mut c_void>();
8296 if !p.is_null() { *(p as *mut u8) = count as u8; }
8297 }
8298 (b'l', b'l', b'n') => {
8299 let p = args.next_arg::<*mut c_void>();
8300 if !p.is_null() { *(p as *mut c_longlong) = count as c_longlong; }
8301 }
8302 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
8303 let val = args.next_arg::<c_longlong>();
8304 let neg = val < 0;
8305 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
8306 let b = format_u64(abs);
8307 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
8308 let mut fbuf = [0u8; 32];
8309 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
8310 ws_buf!(fbuf.as_ptr(), len);
8311 }
8312 (b'l', b'l', b'u') => {
8313 let val = args.next_arg::<c_ulonglong>();
8314 let b = format_u64(val as u64);
8315 let mut fbuf = [0u8; 32];
8316 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8317 ws_buf!(fbuf.as_ptr(), len);
8318 }
8319 (b'l', b'l', b'o') => {
8320 let val = args.next_arg::<c_ulonglong>();
8321 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
8322 let mut fbuf = [0u8; 32];
8323 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8324 ws_buf!(fbuf.as_ptr(), len);
8325 }
8326 (b'l', b'l', b'x') | (b'l', b'l', b'X') => {
8327 let val = args.next_arg::<c_ulonglong>();
8328 let b = format_hex(val as u64, spec == b'X');
8329 let pc = if spec == b'X' { b'X' } else { b'x' };
8330 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(pc) } else { None };
8331 let mut fbuf = [0u8; 32];
8332 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8333 ws_buf!(fbuf.as_ptr(), len);
8334 }
8335 _ => { wc!(b'%'); wc!(len_mod); wc!(len_mod2); wc!(spec); }
8336 }
8337 } else {
8338 spec = len_mod2;
8339 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
8340 match (lm, spec) {
8341 (b'h', b'n') => {
8342 let p = args.next_arg::<*mut c_void>();
8343 if !p.is_null() { *(p as *mut u16) = count as u16; }
8344 }
8345 (b'l', b'n') => {
8346 let p = args.next_arg::<*mut c_void>();
8347 if !p.is_null() { *(p as *mut c_long) = count as c_long; }
8348 }
8349 (b'z', b'n') | (b't', b'n') => {
8350 let p = args.next_arg::<*mut c_void>();
8351 if !p.is_null() { *(p as *mut usize) = count; }
8352 }
8353 (b'j', b'n') => {
8354 let p = args.next_arg::<*mut c_void>();
8355 if !p.is_null() { *(p as *mut c_ulonglong) = count as c_ulonglong; }
8356 }
8357 (b'l', b'd') | (b'l', b'i') => {
8358 let val = args.next_arg::<c_long>();
8359 let neg = val < 0;
8360 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
8361 let b = format_u64(abs);
8362 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
8363 let mut fbuf = [0u8; 32];
8364 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
8365 ws_buf!(fbuf.as_ptr(), len);
8366 }
8367 (b'l', b'u') => {
8368 let val = args.next_arg::<c_ulong>();
8369 let b = format_u64(val as u64);
8370 let mut fbuf = [0u8; 32];
8371 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8372 ws_buf!(fbuf.as_ptr(), len);
8373 }
8374 (b'l', b's') => {
8375 let p = args.next_arg::<*const wchar_t>();
8376 if p.is_null() {
8377 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
8378 let pad = width.saturating_sub(slen);
8379 if flags & FLAG_MINUS != 0 { ws!(b"(null)".as_ptr(), slen); for _ in 0..pad { wc!(b' '); } }
8380 else { for _ in 0..pad { wc!(b' '); } ws!(b"(null)".as_ptr(), slen); }
8381 } else {
8382 let mut mb = [0u8; 4096];
8383 let mut n = wide_to_mb(mb.as_mut_ptr(), mb.len(), p);
8384 if precision >= 0 && (precision as usize) < n { n = precision as usize; }
8385 let pad = width.saturating_sub(n);
8386 if flags & FLAG_MINUS != 0 { ws!(mb.as_ptr(), n); for _ in 0..pad { wc!(b' '); } }
8387 else { for _ in 0..pad { wc!(b' '); } ws!(mb.as_ptr(), n); }
8388 }
8389 }
8390 (b'l', b'c') => {
8391 let ch = args.next_arg::<c_int>();
8392 let mut mb = [0u8; 8];
8393 let mut st: c_uint = 0;
8394 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, ch, &mut st);
8395 if n != !0usize { ws!(mb.as_ptr(), n); }
8396 }
8397 (b'l', b'x') => {
8398 let val = args.next_arg::<c_ulong>();
8399 let b = format_hex(val as u64, false);
8400 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
8401 let mut fbuf = [0u8; 32];
8402 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8403 ws_buf!(fbuf.as_ptr(), len);
8404 }
8405 (b'l', b'X') => {
8406 let val = args.next_arg::<c_ulong>();
8407 let b = format_hex(val as u64, true);
8408 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
8409 let mut fbuf = [0u8; 32];
8410 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8411 ws_buf!(fbuf.as_ptr(), len);
8412 }
8413 (b'l', b'o') => {
8414 let val = args.next_arg::<c_ulong>();
8415 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
8416 let mut fbuf = [0u8; 32];
8417 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8418 ws_buf!(fbuf.as_ptr(), len);
8419 }
8420 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
8421 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
8422 let val = args.next_arg::<f64>();
8423 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8424 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8425 let mut fbuf = [0u8; 4224];
8426 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8427 let mut wbuf = [0u8; 4224];
8428 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8429 ws_buf!(wbuf.as_ptr(), wlen);
8430 }
8431 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
8432 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
8433 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
8434 let val = {
8435 let lo: u64 = args.next_arg::<u64>();
8436 let hi: u64 = args.next_arg::<u64>();
8437 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
8438 f128::from_bits(combined) as f64
8439 };
8440 #[cfg(target_arch = "x86_64")]
8441 let val = args.next_arg::<f64>();
8442 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8443 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8444 let mut fbuf = [0u8; 4224];
8445 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8446 let mut wbuf = [0u8; 4224];
8447 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8448 ws_buf!(wbuf.as_ptr(), wlen);
8449 }
8450 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); }
8451 }
8452 }
8453 } else {
8454 spec = *fmt.add(i) as u8;
8455 match spec {
8456 b's' => {
8457 let s = args.next_arg::<*const c_char>();
8458 if s.is_null() {
8459 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
8460 let padded_len = if width > slen { width } else { slen };
8461 let pad = padded_len - slen;
8462 if flags & FLAG_MINUS != 0 {
8463 ws!(b"(null)".as_ptr(), slen);
8464 for _ in 0..pad { wc!(b' '); }
8465 } else {
8466 for _ in 0..pad { wc!(b' '); }
8467 ws!(b"(null)".as_ptr(), slen);
8468 }
8469 } else {
8470 let full_len = strlen(s as *const c_char);
8471 let slen = if precision >= 0 { (precision as usize).min(full_len) } else { full_len };
8472 let padded_len = if width > slen { width } else { slen };
8473 let pad = padded_len - slen;
8474 if flags & FLAG_MINUS != 0 {
8475 ws!(s as *const u8, slen);
8476 for _ in 0..pad { wc!(b' '); }
8477 } else {
8478 for _ in 0..pad { wc!(b' '); }
8479 ws!(s as *const u8, slen);
8480 }
8481 }
8482 }
8483 b'd' | b'i' => {
8484 let d = args.next_arg::<c_int>();
8485 let neg = d < 0;
8486 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
8487 let b = format_u64(abs);
8488 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
8489 let mut fbuf = [0u8; 32];
8490 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
8491 ws_buf!(fbuf.as_ptr(), len);
8492 }
8493 b'u' => {
8494 let u = args.next_arg::<c_uint>();
8495 let b = format_u64(u as u64);
8496 let mut fbuf = [0u8; 32];
8497 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
8498 ws_buf!(fbuf.as_ptr(), len);
8499 }
8500 b'x' => {
8501 let x = args.next_arg::<c_uint>();
8502 let b = format_hex(x as u64, false);
8503 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
8504 let mut fbuf = [0u8; 32];
8505 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8506 ws_buf!(fbuf.as_ptr(), len);
8507 }
8508 b'X' => {
8509 let x = args.next_arg::<c_uint>();
8510 let b = format_hex(x as u64, true);
8511 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
8512 let mut fbuf = [0u8; 32];
8513 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
8514 ws_buf!(fbuf.as_ptr(), len);
8515 }
8516 b'o' => {
8517 let o = args.next_arg::<c_uint>();
8518 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
8519 let mut fbuf = [0u8; 32];
8520 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
8521 ws_buf!(fbuf.as_ptr(), len);
8522 }
8523 b'c' => {
8524 let ch = args.next_arg::<c_int>();
8525 if width > 1 {
8526 let pad = width - 1;
8527 if flags & FLAG_MINUS != 0 {
8528 wc!(ch as u8);
8529 for _ in 0..pad { wc!(b' '); }
8530 } else {
8531 for _ in 0..pad { wc!(b' '); }
8532 wc!(ch as u8);
8533 }
8534 } else {
8535 wc!(ch as u8);
8536 }
8537 }
8538 b'p' => {
8539 wc!(b'0'); wc!(b'x');
8540 let p = args.next_arg::<*const c_void>();
8541 let b = format_hex(p as u64, false);
8542 ws!(b.0.as_ptr(), b.1);
8543 }
8544 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
8545 let val = args.next_arg::<f64>();
8546 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
8547 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
8548 let mut fbuf = [0u8; 4224];
8549 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
8550 let mut wbuf = [0u8; 4224];
8551 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
8552 ws_buf!(wbuf.as_ptr(), wlen);
8553 }
8554 b'%' => { wc!(b'%'); }
8555 b'n' => {
8556 let p = args.next_arg::<*mut c_void>();
8557 if !p.is_null() { *(p as *mut c_int) = count as c_int; }
8558 }
8559 _ => { wc!(b'%'); wc!(spec); }
8560 }
8561 }
8562 i += 1;
8563 }
8564 if cap > 0 { let null_pos = if pos < cap { pos } else { cap - 1 }; *buf.add(null_pos) = 0; }
8565 count as c_int
8566}
8567
8568#[no_mangle]
8569pub unsafe extern "C" fn vsprintf(buf: *mut c_char, fmt: *const c_char, mut args: VaList) -> c_int {
8570 format_to_buf(buf as *mut u8, usize::MAX, fmt, &mut args)
8571}
8572
8573#[no_mangle]
8574pub unsafe extern "C" fn vsnprintf(buf: *mut c_char, size: usize, fmt: *const c_char, mut args: VaList) -> c_int {
8575 format_to_buf(buf as *mut u8, size, fmt, &mut args)
8576}
8577
8578#[no_mangle]
8579pub unsafe extern "C" fn sprintf(buf: *mut c_char, fmt: *const c_char, mut args: ...) -> c_int {
8580 format_to_buf(buf as *mut u8, usize::MAX, fmt, &mut args)
8581}
8582
8583#[no_mangle]
8584pub unsafe extern "C" fn snprintf(buf: *mut c_char, size: usize, fmt: *const c_char, mut args: ...) -> c_int {
8585 format_to_buf(buf as *mut u8, size, fmt, &mut args)
8586}
8587
8588#[no_mangle]
8589pub unsafe extern "C" fn vasprintf(strp: *mut *mut c_char, fmt: *const c_char, ap: VaList) -> c_int {
8590 let len = vsnprintf(core::ptr::null_mut(), 0, fmt, ap.clone());
8591 if len < 0 {
8592 *strp = core::ptr::null_mut();
8593 return -1;
8594 }
8595 let p = malloc((len as usize) + 1) as *mut c_char;
8596 if p.is_null() {
8597 *strp = core::ptr::null_mut();
8598 return -1;
8599 }
8600 let ret = vsnprintf(p, (len as usize) + 1, fmt, ap.clone());
8601 if ret < 0 {
8602 free(p as *mut c_void);
8603 *strp = core::ptr::null_mut();
8604 return -1;
8605 }
8606 *strp = p;
8607 ret
8608}
8609
8610#[no_mangle]
8611pub unsafe extern "C" fn asprintf(strp: *mut *mut c_char, fmt: *const c_char, args: ...) -> c_int {
8612 vasprintf(strp, fmt, args)
8613}
8614
8615unsafe fn skip_ws(p: *const u8) -> *const u8 {
8620 let mut q = p;
8621 while *q == b' ' || *q == b'\t' || *q == b'\n' || *q == b'\r' { q = q.add(1); }
8622 q
8623}
8624
8625#[inline]
8626fn is_ws_byte(c: u8) -> bool {
8627 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == 0x0b || c == 0x0c
8628}
8629
8630unsafe fn scan_int_val(
8633 buf: *const u8, pos: &mut usize, buf_len: usize, base: u32, width: usize,
8634) -> (u64, bool, bool) {
8635 let start = *pos;
8636 let max = if width > 0 { (start + width).min(buf_len) } else { buf_len };
8637 let neg = if *pos < max && *buf.add(*pos) == b'-' { *pos += 1; true }
8638 else if *pos < max && *buf.add(*pos) == b'+' { *pos += 1; false }
8639 else { false };
8640 if *pos >= max { *pos = start; return (0, false, false); }
8641 let mut base = base;
8642 let mut val: u64 = 0;
8643 if (base == 0 || base == 16) && *pos < max && *buf.add(*pos) == b'0' {
8645 *pos += 1;
8646 if *pos < max && (*buf.add(*pos) == b'x' || *buf.add(*pos) == b'X') {
8647 *pos += 1;
8648 if *pos < max {
8649 if let Some(d) = hex_val(*buf.add(*pos)) {
8650 val = d as u64; *pos += 1;
8651 while *pos < max { if let Some(d) = hex_val(*buf.add(*pos)) { val = val.wrapping_mul(16).wrapping_add(d as u64); *pos += 1; } else { break; } }
8652 return (val, neg, true);
8653 }
8654 }
8655 return (0, neg, false);
8656 } else if base == 0 {
8657 while *pos < max { let c = *buf.add(*pos); if c >= b'0' && c <= b'7' { val = val.wrapping_mul(8).wrapping_add((c - b'0') as u64); *pos += 1; } else { break; } }
8658 return (val, neg, true);
8659 } else {
8660 while *pos < max {
8663 if let Some(d) = hex_val(*buf.add(*pos)) {
8664 val = val.wrapping_mul(16).wrapping_add(d as u64);
8665 *pos += 1;
8666 } else {
8667 break;
8668 }
8669 }
8670 return (val, neg, true);
8671 }
8672 }
8673 if base == 0 { base = 10; }
8674 let mut found = false;
8675 while *pos < max {
8676 let c = *buf.add(*pos);
8677 let d: Option<u64> = match base {
8678 8 => if c >= b'0' && c <= b'7' { Some((c - b'0') as u64) } else { None },
8679 10 => if c >= b'0' && c <= b'9' { Some((c - b'0') as u64) } else { None },
8680 16 => hex_val(c).map(|v| v as u64),
8681 _ => None,
8682 };
8683 match d { Some(digit) => { val = val.wrapping_mul(base as u64).wrapping_add(digit); *pos += 1; found = true; } None => break }
8684 }
8685 if !found { *pos = start; return (0, false, false); }
8686 (val, neg, true)
8687}
8688
8689unsafe fn scan_float_val(
8691 buf: *const u8, pos: &mut usize, buf_len: usize, width: usize,
8692) -> (f64, bool) {
8693 let start = *pos;
8694 let max = if width > 0 { (start + width).min(buf_len) } else { buf_len };
8695 let neg = if *pos < max && *buf.add(*pos) == b'-' { *pos += 1; true }
8696 else if *pos < max && *buf.add(*pos) == b'+' { *pos += 1; false }
8697 else { false };
8698 if *pos + 2 < max {
8700 let (c0,c1,c2) = (*buf.add(*pos), *buf.add(*pos+1), *buf.add(*pos+2));
8701 if (c0==b'i'||c0==b'I')&&(c1==b'n'||c1==b'N')&&(c2==b'f'||c2==b'F') { *pos+=3; return (if neg{f64::NEG_INFINITY}else{f64::INFINITY}, true); }
8702 if (c0==b'n'||c0==b'N')&&(c1==b'a'||c1==b'A')&&(c2==b'n'||c2==b'N') { *pos+=3; return (if neg{-f64::NAN}else{f64::NAN}, true); }
8703 }
8704 if *pos+1 < max && *buf.add(*pos)==b'0' && (*buf.add(*pos+1)==b'x'||*buf.add(*pos+1)==b'X') {
8706 *pos += 2;
8707 let mut val: f64 = 0.0; let mut found = false; let mut frac_scale = 1.0f64; let mut in_frac = false;
8708 while *pos < max {
8709 if let Some(d) = hex_val(*buf.add(*pos)) {
8710 if in_frac { frac_scale /= 16.0; val += d as f64 * frac_scale; } else { val = val * 16.0 + d as f64; }
8711 *pos += 1; found = true;
8712 } else if *buf.add(*pos)==b'.' && !in_frac { in_frac = true; *pos += 1; } else { break; }
8713 }
8714 if !found { *pos = start; return (0.0, false); }
8715 if *pos < max && (*buf.add(*pos)==b'p'||*buf.add(*pos)==b'P') {
8717 *pos += 1;
8718 let mut eneg = false;
8719 if *pos<max && *buf.add(*pos)==b'-' { eneg=true; *pos+=1; }
8720 else if *pos<max && *buf.add(*pos)==b'+' { *pos+=1; }
8721 let mut ev: i32 = 0; let mut ef = false;
8722 while *pos<max && *buf.add(*pos)>=b'0' && *buf.add(*pos)<=b'9' { ev = ev*10+(*buf.add(*pos)-b'0') as i32; *pos+=1; ef=true; }
8723 if !ef { return (0.0, false); }
8724 if eneg { ev = -ev; }
8725 val *= libm::pow(2.0, ev as f64);
8726 }
8727 return (if neg{-val}else{val}, true);
8728 }
8729 let token_start = start;
8730 let mut i = start;
8731 let mut saw_digit = false;
8732 let mut saw_dot = false;
8733 let mut saw_exp = false;
8734 let mut first = true;
8735 while i < max {
8736 let c = *buf.add(i);
8737 if (c == b'+' || c == b'-') && first {
8738 i += 1; first = false; continue;
8739 }
8740 if c >= b'0' && c <= b'9' {
8741 saw_digit = true; i += 1; first = false; continue;
8742 }
8743 if c == b'.' && !saw_dot && !saw_exp {
8744 saw_dot = true; i += 1; first = false; continue;
8745 }
8746 if (c == b'e' || c == b'E') && !saw_exp && saw_digit {
8747 saw_exp = true; i += 1; first = true; continue;
8748 }
8749 break;
8750 }
8751 if !saw_digit { return (0.0, false); }
8752 let s = core::str::from_utf8_unchecked(core::slice::from_raw_parts(buf.add(token_start), i - token_start));
8753 match <f64 as core::str::FromStr>::from_str(s) {
8754 Ok(v) => { *pos = i; return (v, true); }
8755 Err(_) => { return (0.0, false); }
8756 }
8757}
8758
8759unsafe fn store_scan_int(dest: *mut c_void, len_mod: u8, val: u64, neg: bool) {
8764 let sv: i64 = if neg { (val as i64).wrapping_neg() } else { val as i64 };
8765 match len_mod {
8766 2 => *(dest as *mut i8) = sv as i8,
8767 1 => *(dest as *mut i16) = sv as i16,
8768 3 | 4 => *(dest as *mut i64) = sv,
8769 _ => *(dest as *mut i32) = sv as i32,
8770 }
8771}
8772
8773unsafe fn do_vsscanf(
8774 buf: *const u8, buf_len: usize, fmt: *const c_char, args: &mut VaList<'_>, consumed: *mut usize,
8775) -> c_int {
8776 let mut p = 0usize;
8777 let mut fi = 0usize;
8778 let mut assigned = 0i32;
8779 let mut input_eof = false;
8780 loop {
8781 let fc = *fmt.add(fi) as u8;
8782 if fc == 0 { break; }
8783 if is_ws_byte(fc) {
8784 while is_ws_byte(*fmt.add(fi) as u8) { fi += 1; }
8785 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8786 continue;
8787 }
8788 if fc != b'%' {
8789 if p >= buf_len { input_eof = true; break; }
8790 if *buf.add(p) != fc { break; }
8791 p += 1; fi += 1; continue;
8792 }
8793 fi += 1;
8794 if *fmt.add(fi) as u8 == b'%' {
8796 if p >= buf_len { input_eof = true; break; }
8797 if *buf.add(p) != b'%' { break; }
8798 p += 1; fi += 1; continue;
8799 }
8800 let suppress = if *fmt.add(fi) as u8 == b'*' { fi += 1; true } else { false };
8801 let mut width: usize = 0;
8802 while (*fmt.add(fi) as u8) >= b'0' && (*fmt.add(fi) as u8) <= b'9' {
8803 width = width * 10 + ((*fmt.add(fi) as u8) - b'0') as usize; fi += 1;
8804 }
8805 if *fmt.add(fi) as u8 == b'm' { fi += 1; }
8806 let mut len_mod = 0u8;
8807 match *fmt.add(fi) as u8 {
8808 b'h' => { fi += 1; if *fmt.add(fi) as u8 == b'h' { fi += 1; len_mod = 2; } else { len_mod = 1; } }
8809 b'l' => { fi += 1; if *fmt.add(fi) as u8 == b'l' { fi += 1; len_mod = 4; } else { len_mod = 3; } }
8810 b'j' => { fi += 1; len_mod = 4; }
8811 b'z' | b't' => { fi += 1; len_mod = 3; }
8812 b'L' => { fi += 1; len_mod = 5; }
8813 _ => {}
8814 }
8815 let spec = *fmt.add(fi) as u8;
8816 let (real_spec, _real_len) = if spec==b'C' {(b'c',3u8)} else if spec==b'S' {(b's',3u8)} else {(spec,len_mod)};
8817 match real_spec {
8818 b'n' => {
8819 if !suppress {
8820 let out = args.next_arg::<*mut c_void>();
8821 if !out.is_null() {
8822 match len_mod {
8823 1 => *(out as *mut i16) = p as i16,
8824 2 => *(out as *mut i8) = p as i8,
8825 3 | 4 => *(out as *mut i64) = p as i64,
8826 _ => *(out as *mut c_int) = p as c_int,
8827 }
8828 }
8829 }
8830 }
8831 b'd' | b'u' => {
8832 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8833 if p >= buf_len { input_eof = true; break; }
8834 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8835 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 10, width);
8836 if !ok { break; }
8837 if let Some(out) = dest { if !out.is_null() {
8838 store_scan_int(out, len_mod, val, neg);
8839 }}
8840 if !suppress { assigned += 1; }
8841 }
8842 b'i' => {
8843 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8844 if p >= buf_len { input_eof = true; break; }
8845 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8846 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 0, width);
8847 if !ok { break; }
8848 if let Some(out) = dest { if !out.is_null() { store_scan_int(out, len_mod, val, neg); } }
8849 if !suppress { assigned += 1; }
8850 }
8851 b'o' => {
8852 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8853 if p >= buf_len { input_eof = true; break; }
8854 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8855 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 8, width);
8856 if !ok { break; }
8857 if let Some(out) = dest { if !out.is_null() { store_scan_int(out, len_mod, val, neg); } }
8858 if !suppress { assigned += 1; }
8859 }
8860 b'x' | b'X' => {
8861 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8862 if p >= buf_len { input_eof = true; break; }
8863 let dest = if !suppress { Some(args.next_arg::<*mut c_void>()) } else { None };
8864 let (val, neg, ok) = scan_int_val(buf, &mut p, buf_len, 16, width);
8865 if !ok { break; }
8866 if let Some(out) = dest { if !out.is_null() { store_scan_int(out, len_mod, val, neg); } }
8867 if !suppress { assigned += 1; }
8868 }
8869 b'p' => {
8870 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8871 if p >= buf_len { input_eof = true; break; }
8872 let dest = if !suppress { Some(args.next_arg::<*mut *mut c_void>()) } else { None };
8873 let (val, _, ok) = scan_int_val(buf, &mut p, buf_len, 16, width);
8874 if !ok { break; }
8875 if let Some(out) = dest { if !out.is_null() { *out = val as usize as *mut c_void; } }
8876 if !suppress { assigned += 1; }
8877 }
8878 b'a' | b'e' | b'f' | b'g' | b'A' | b'E' | b'F' | b'G' => {
8879 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8880 if p >= buf_len { input_eof = true; break; }
8881 let (val, ok) = scan_float_val(buf, &mut p, buf_len, width);
8882 if !ok { break; }
8883 if !suppress {
8884 if _real_len == 3 {
8885 let out = args.next_arg::<*mut f64>(); if !out.is_null() { *out = val; }
8886 } else if _real_len == 5 {
8887 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
8888 { let out = args.next_arg::<*mut f128>(); if !out.is_null() { *out = val as f128; } }
8889 #[cfg(target_arch = "x86_64")]
8890 { let out = args.next_arg::<*mut f64>(); if !out.is_null() { *out = val; } }
8891 } else {
8892 let out = args.next_arg::<*mut f32>(); if !out.is_null() { *out = val as f32; }
8893 }
8894 }
8895 if !suppress { assigned += 1; }
8896 }
8897 b'c' => {
8898 let w = if width > 0 { width } else { 1 };
8899 if p >= buf_len { input_eof = true; break; }
8900 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8901 let start_p = p;
8902 let mut j = 0usize;
8903 while j < w && p < buf_len {
8904 if !dest_ptr.is_null() { *dest_ptr.add(j) = *buf.add(p) as c_char; }
8905 p += 1; j += 1;
8906 }
8907 if j != w { p = start_p; input_eof = true; break; }
8908 if !suppress { assigned += 1; }
8909 }
8910 b's' => {
8911 while p < buf_len && is_ws_byte(*buf.add(p)) { p += 1; }
8912 if p >= buf_len { input_eof = true; break; }
8913 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8914 let w = if width > 0 { width } else { usize::MAX };
8915 let mut j = 0usize;
8916 while p < buf_len && *buf.add(p) != 0 && !is_ws_byte(*buf.add(p)) && j < w {
8917 if !dest_ptr.is_null() { *dest_ptr.add(j) = *buf.add(p) as c_char; }
8918 p += 1; j += 1;
8919 }
8920 if j == 0 { break; }
8921 if !dest_ptr.is_null() { *dest_ptr.add(j) = 0; }
8922 if !suppress { assigned += 1; }
8923 }
8924 b'[' => {
8925 fi += 1;
8926 let negate = if *fmt.add(fi) as u8 == b'^' { fi += 1; true } else { false };
8927 let mut charset = [0u8; 256];
8928 let mut prev: Option<u8> = None;
8929 if *fmt.add(fi) as u8 == b']' {
8930 charset[b']' as usize] = 1;
8931 prev = Some(b']');
8932 fi += 1;
8933 }
8934 loop {
8935 let c = *fmt.add(fi) as u8;
8936 if c == b']' || c == 0 { break; }
8937 if c == b'-' && prev.is_some() {
8940 let hi = *fmt.add(fi + 1) as u8;
8941 if hi != b']' && hi != 0 {
8942 let lo = prev.unwrap();
8943 let mut k = lo;
8944 while k <= hi {
8945 charset[k as usize] = 1;
8946 if k == 255 { break; }
8947 k += 1;
8948 }
8949 prev = None;
8950 fi += 2;
8951 continue;
8952 }
8953 }
8954 charset[c as usize] = 1;
8955 prev = Some(c);
8956 fi += 1;
8957 }
8958 if *fmt.add(fi) as u8 == b']' { fi += 1; }
8959 fi -= 1; if p >= buf_len { input_eof = true; break; }
8961 let dest_ptr: *mut c_char = if !suppress { args.next_arg::<*mut c_char>() } else { core::ptr::null_mut() };
8962 let w = if width > 0 { width } else { usize::MAX };
8963 let mut j = 0usize;
8964 while p < buf_len && *buf.add(p) != 0 && j < w {
8965 let c = *buf.add(p);
8966 let in_set = charset[c as usize] != 0;
8967 if negate { if in_set { break; } } else { if !in_set { break; } }
8968 if !dest_ptr.is_null() { *dest_ptr.add(j) = c as c_char; }
8969 p += 1; j += 1;
8970 }
8971 if j == 0 { break; }
8972 if !dest_ptr.is_null() { *dest_ptr.add(j) = 0; }
8973 if !suppress { assigned += 1; }
8974 }
8975 _ => break,
8976 }
8977 fi += 1;
8978 }
8979 if !consumed.is_null() { *consumed = p; }
8980 if assigned == 0 && input_eof { -1 } else { assigned }
8981}
8982
8983unsafe fn vsscanf_inner(buf: *const u8, fmt: *const c_char, args: &mut VaList<'_>) -> c_int {
8984 let len = strlen(buf as *const c_char);
8985 do_vsscanf(buf, len, fmt, args, core::ptr::null_mut())
8986}
8987
8988#[no_mangle]
8989pub unsafe extern "C" fn vsscanf(buf: *const c_char, fmt: *const c_char, mut args: VaList) -> c_int {
8990 vsscanf_inner(buf as *const u8, fmt, &mut args)
8991}
8992
8993#[no_mangle]
8994pub unsafe extern "C" fn vfscanf(stream: *mut FILE, fmt: *const c_char, mut args: VaList) -> c_int {
8995 let f = &mut *stream;
8996 let start_ungotten_count = f.ungotten_count as usize;
8997 let ungotten_saved = f.ungotten;
8998 let sfunc = f.seek_fn;
8999 let start_pos = if sfunc.is_some() { ftello(stream) } else { -1 };
9001
9002 let mut line = [0u8; 4096];
9003 let mut pos = 0usize;
9004
9005 if start_pos >= 0 {
9006 while pos < line.len() - 1 {
9008 let c = fgetc(stream);
9009 if c == -1 { break; }
9010 line[pos] = c as u8;
9011 pos += 1;
9012 if c == b'\n' as c_int { break; }
9013 }
9014 } else {
9015 while f.ungotten_count > 0 && pos < line.len() - 1 {
9020 f.ungotten_count -= 1;
9021 line[pos] = f.ungotten[f.ungotten_count as usize] as u8;
9022 pos += 1;
9023 }
9024 while !f.rpos.is_null() && f.rpos < f.rend && pos < line.len() - 1 {
9026 line[pos] = *f.rpos;
9027 f.rpos = f.rpos.add(1);
9028 pos += 1;
9029 }
9030 let fd = f.fd;
9034 if pos == 0 {
9035 let n = sys_read(fd as i64, line.as_mut_ptr(), 1);
9036 if n == 1 { pos = 1; }
9037 }
9038 let old_flags = sys_fcntl(fd, F_GETFL, 0);
9039 if old_flags >= 0 {
9040 let _ = sys_fcntl(fd, F_SETFL, old_flags | O_NONBLOCK as i64);
9041 }
9042 while pos < line.len() - 1 {
9043 let n = sys_read(fd as i64, line.as_mut_ptr().add(pos), line.len() - 1 - pos);
9044 if n <= 0 { break; }
9045 pos += n as usize;
9046 }
9047 if old_flags >= 0 {
9048 let _ = sys_fcntl(fd, F_SETFL, old_flags);
9049 }
9050 f._eof = 0;
9052 f._err = 0;
9053 f.flags &= !(F_EOF | F_ERR);
9054 }
9055
9056 line[pos] = 0;
9057 if pos == 0 { return 0; }
9058
9059 let mut consumed = 0usize;
9060 let assigned = do_vsscanf(line.as_ptr(), pos, fmt, &mut args, &mut consumed);
9061
9062 if start_pos >= 0 {
9063 let remaining = start_ungotten_count.saturating_sub(consumed);
9066 let target = start_pos + consumed as i64 + remaining as i64;
9069 if let Some(sfunc) = sfunc {
9070 sfunc(stream, target, SEEK_SET);
9071 }
9072 f.rpos = core::ptr::null_mut();
9073 f.rend = core::ptr::null_mut();
9074 if consumed < pos { f._eof = 0; }
9075 f.ungotten_count = 0;
9076 for i in 0..remaining {
9077 f.ungotten[f.ungotten_count as usize] = ungotten_saved[i];
9078 f.ungotten_count += 1;
9079 }
9080 } else {
9081 let unconsumed = pos.saturating_sub(consumed);
9083 if unconsumed > 0 && !f.buf.is_null() {
9084 let copy_count = core::cmp::min(unconsumed, f.buf_size);
9085 core::ptr::copy(
9086 line.as_ptr().add(consumed),
9087 f.buf,
9088 copy_count,
9089 );
9090 f.rpos = f.buf;
9091 f.rend = f.buf.add(copy_count);
9092 }
9093 f.ungotten_count = 0;
9094 f._eof = 0;
9095 f.flags &= !F_EOF;
9096 }
9097 assigned
9098}
9099
9100#[no_mangle]
9101pub unsafe extern "C" fn vscanf(fmt: *const c_char, args: VaList) -> c_int {
9102 vfscanf(stdin, fmt, args)
9103}
9104
9105#[no_mangle]
9106pub unsafe extern "C" fn sscanf(buf: *const c_char, fmt: *const c_char, mut args: ...) -> c_int {
9107 vsscanf_inner(buf as *const u8, fmt, &mut args)
9108}
9109
9110#[no_mangle]
9111pub unsafe extern "C" fn fscanf(stream: *mut FILE, fmt: *const c_char, args: ...) -> c_int {
9112 vfscanf(stream, fmt, args)
9113}
9114
9115#[no_mangle]
9116pub unsafe extern "C" fn scanf(fmt: *const c_char, args: ...) -> c_int {
9117 vfscanf(stdin, fmt, args)
9118}
9119
9120#[no_mangle]
9125pub unsafe extern "C" fn getdelim(
9126 lineptr: *mut *mut c_char, n: *mut usize, delim: c_int, stream: *mut FILE,
9127) -> isize {
9128 if lineptr.is_null() || n.is_null() { return -1; }
9129 let mut cap = *n;
9130 let mut buf = *lineptr;
9131 if buf.is_null() || cap == 0 {
9132 cap = 128;
9133 buf = realloc(buf as *mut c_void, cap) as *mut c_char;
9134 if buf.is_null() { return -1; }
9135 *lineptr = buf;
9136 *n = cap;
9137 }
9138 let mut len = 0usize;
9139 loop {
9140 let c = fgetc(stream);
9141 if c == -1 { if len == 0 { return -1; } break; }
9142 if len + 1 >= cap {
9143 let new_cap = cap.wrapping_mul(2);
9144 let new_buf = realloc(buf as *mut c_void, new_cap) as *mut c_char;
9145 if new_buf.is_null() { return -1; }
9146 buf = new_buf; cap = new_cap;
9147 *lineptr = buf; *n = cap;
9148 }
9149 *buf.add(len) = c as c_char;
9150 len += 1;
9151 if c == delim { break; }
9152 }
9153 *buf.add(len) = 0;
9154 len as isize
9155}
9156
9157#[no_mangle]
9158pub unsafe extern "C" fn getline(lineptr: *mut *mut c_char, n: *mut usize, stream: *mut FILE) -> isize {
9159 getdelim(lineptr, n, b'\n' as c_int, stream)
9160}
9161
9162#[no_mangle]
9167pub unsafe extern "C" fn popen(cmd: *const c_char, mode: *const c_char) -> *mut FILE {
9168 if cmd.is_null() || mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
9169 let m = *mode;
9170 if m != b'r' as c_char && m != b'w' as c_char { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
9171 let mut p: [c_int; 2] = [0; 2];
9172 if sys_pipe2(p.as_mut_ptr(), O_CLOEXEC) < 0 { return core::ptr::null_mut(); }
9173 let op = if m == b'r' as c_char { 0 } else { 1 };
9174 let child_fd = p[1 - op];
9175 let f = fdopen(p[op], mode);
9176 if f.is_null() { sys_close(p[0] as i64); sys_close(p[1] as i64); return core::ptr::null_mut(); }
9177 let pid = sys_fork();
9178 if pid < 0 { fclose(f); sys_close(child_fd as i64); return core::ptr::null_mut(); }
9179 if pid == 0 {
9180 sys_close(p[op] as i64);
9181 if child_fd != (1 - op) as c_int { sys_dup3(child_fd, (1 - op) as c_int, 0); sys_close(child_fd as i64); }
9182 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
9183 let argv = [b"sh\0".as_ptr() as *const c_char, b"-c\0".as_ptr() as *const c_char, cmd, core::ptr::null()];
9184 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
9185 _exit(127);
9186 }
9187 sys_close(child_fd as i64);
9188 (*f).pipe_pid = pid as c_int;
9189 f
9190}
9191
9192#[no_mangle]
9193pub unsafe extern "C" fn pclose(f: *mut FILE) -> c_int {
9194 let pid = (*f).pipe_pid;
9195 let r = fclose(f);
9196 if pid <= 0 { return -1; }
9197 let mut status: c_int = 0;
9198 let mut w: c_int;
9199 loop {
9200 w = waitpid(pid, &mut status, 0);
9201 if w >= 0 || ERRNO!() != EINTR_VAL { break; }
9202 }
9203 if w < 0 || r != 0 { return -1; }
9204 status
9205}
9206
9207const L_TMPNAM: usize = 20;
9212static mut TMPNAM_COUNTER: c_uint = 0;
9213
9214unsafe fn fill_tmpname(out: *mut c_char, seed: c_uint) {
9215 let prefix = b"/tmp/tmp\0";
9216 let mut k = 0;
9217 while k < prefix.len() - 1 { *out.add(k) = prefix[k] as c_char; k += 1; }
9218 let (buf, len) = format_hex(seed as u64, false);
9219 for j in 0..len.min(L_TMPNAM - k - 1) { *out.add(k + j) = buf[j] as c_char; k += 1; }
9220 *out.add(k) = 0;
9221}
9222
9223#[no_mangle]
9224pub unsafe extern "C" fn tmpfile() -> *mut FILE {
9225 let mut name = [0u8; L_TMPNAM];
9226 let mut ctr: c_uint = 0;
9227 loop {
9228 ctr = ctr.wrapping_add(1);
9229 let mut ts: timespec = core::mem::zeroed();
9230 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
9231 let seed = (ts.tv_nsec as c_uint).wrapping_add(ctr);
9232 fill_tmpname(name.as_mut_ptr() as *mut c_char, seed);
9233 let fd = sys_open(name.as_ptr(), (O_RDWR | O_CREAT | O_EXCL) as i64, 0o600);
9234 if fd >= 0 {
9235 sys_unlinkat(AT_FDCWD, name.as_ptr(), 0);
9236 let f = fdopen(fd as c_int, b"w+\0".as_ptr() as *const c_char);
9237 if f.is_null() { sys_close(fd); }
9238 return f;
9239 }
9240 if ctr > 100 { return core::ptr::null_mut(); }
9241 }
9242}
9243
9244#[no_mangle]
9245pub unsafe extern "C" fn tmpnam(s: *mut c_char) -> *mut c_char {
9246 static mut BUF: [c_char; L_TMPNAM] = [0; L_TMPNAM];
9247 let out = if s.is_null() { core::ptr::addr_of_mut!(BUF) as *mut c_char } else { s };
9248 TMPNAM_COUNTER = TMPNAM_COUNTER.wrapping_add(1);
9249 let mut ts: timespec = core::mem::zeroed();
9250 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
9251 let seed = (ts.tv_nsec as c_uint).wrapping_add(TMPNAM_COUNTER);
9252 fill_tmpname(out, seed);
9253 out
9254}
9255
9256#[no_mangle]
9257pub unsafe extern "C" fn remove(path: *const c_char) -> c_int {
9258 if path.is_null() { ERRNO!() = EINVAL; return -1; }
9259 let r = sys_unlinkat(AT_FDCWD, path as *const u8, 0);
9260 if r == 0 {
9261 return 0;
9262 }
9263 if (-r) as c_int == 21 {
9266 return rmdir(path);
9267 }
9268 ERRNO!() = (-r) as c_int;
9269 -1
9270}
9271
9272#[no_mangle]
9273pub unsafe extern "C" fn rename(old: *const c_char, new_: *const c_char) -> c_int {
9274 if old.is_null() || new_.is_null() { ERRNO!() = EINVAL; return -1; }
9275 let r = sys_renameat2(AT_FDCWD, old as *const u8, AT_FDCWD, new_ as *const u8, 0);
9276 if r == 0 { 0 } else { ERRNO!() = (-r) as c_int; -1 }
9277}
9278
9279const MMAP_FAILED: *mut u8 = !0usize as *mut u8;
9284const PAGE: usize = 4096;
9285
9286#[no_mangle]
9291pub unsafe extern "C" fn _exit(code: c_int) -> ! {
9292 sys_exit_group(code)
9293}
9294
9295#[inline]
9296unsafe fn sys_exit_group(code: c_int) -> ! {
9297 <Arch as Syscalls>::syscall_noreturn1(SYS_EXIT_GROUP, code as i64)
9298}
9299
9300#[inline]
9301unsafe fn sys_exit_thread(code: c_int) -> ! {
9302 <Arch as Syscalls>::syscall_noreturn1(SYS_EXIT, code as i64)
9303}
9304
9305#[no_mangle]
9306pub unsafe extern "C" fn _Exit(code: c_int) -> ! {
9307 _exit(code);
9308}
9309
9310#[no_mangle]
9311pub unsafe extern "C" fn exit(code: c_int) -> ! {
9312 fflush(core::ptr::null_mut());
9313 __funcs_on_exit();
9314 _exit(code);
9315}
9316
9317#[no_mangle]
9318pub unsafe extern "C" fn abort() -> ! {
9319 raise(6); _exit(128 + 6);
9321}
9322
9323#[no_mangle]
9326pub static mut __stack_chk_guard: usize = 0;
9327
9328#[no_mangle]
9329pub unsafe extern "C" fn __stack_chk_fail() -> ! {
9330 const MSG: &[u8] = b"*** stack smashing detected ***: terminated\n";
9331 let _ = sys_write(2, MSG.as_ptr(), MSG.len());
9332 abort();
9333}
9334
9335type CmpRfn = unsafe extern "C" fn(*const c_void, *const c_void, *mut c_void) -> c_int;
9340
9341const AR_LEN: usize = 16 * core::mem::size_of::<usize>();
9342const AR_MASK: usize = AR_LEN - 1;
9343
9344unsafe fn qsort_pntz(p: &[usize; 2]) -> i32 {
9345 if p[0] != 1 {
9346 p[0].wrapping_sub(1).trailing_zeros() as i32
9347 } else if p[1] != 0 {
9348 (8 * core::mem::size_of::<usize>()) as i32 + p[1].trailing_zeros() as i32
9349 } else {
9350 0
9351 }
9352}
9353
9354unsafe fn qsort_cycle(width: usize, ar: &mut [*mut u8; AR_LEN], n: usize) {
9355 if n < 2 { return; }
9356 let mut tmp = [0u8; 256];
9357 ar[n] = tmp.as_mut_ptr();
9358 let mut w = width;
9359 while w > 0 {
9360 let l = if 256 < w { 256 } else { w };
9361 core::ptr::copy_nonoverlapping(ar[0], ar[n], l);
9362 for i in 0..n {
9363 core::ptr::copy_nonoverlapping(ar[i + 1], ar[i], l);
9364 ar[i] = ar[i].add(l);
9365 }
9366 w -= l;
9367 }
9368}
9369
9370unsafe fn qsort_shl(p: &mut [usize; 2], n: i32) {
9371 let bits = (8 * core::mem::size_of::<usize>()) as i32;
9372 if n >= bits {
9373 p[1] = p[0];
9374 p[0] = 0;
9375 let n = n - bits;
9376 if n == 0 { return; }
9377 }
9378 p[1] = (p[1] << n) | (p[0] >> (bits - n));
9379 p[0] <<= n;
9380}
9381
9382unsafe fn qsort_shr(p: &mut [usize; 2], n: i32) {
9383 let bits = (8 * core::mem::size_of::<usize>()) as i32;
9384 if n >= bits {
9385 p[0] = p[1];
9386 p[1] = 0;
9387 let n = n - bits;
9388 if n == 0 { return; }
9389 }
9390 p[0] = (p[0] >> n) | (p[1] << (bits - n));
9391 p[1] >>= n;
9392}
9393
9394unsafe fn qsort_sift(
9395 head: *mut u8, width: usize,
9396 cmp: CmpRfn, arg: *mut c_void,
9397 pshift: i32, lp: &[usize],
9398) {
9399 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
9400 ar[0] = head;
9401 let mut i = 1usize;
9402 let mut h = head;
9403 let mut ps = pshift;
9404
9405 while ps > 1 {
9406 let rt = h.sub(width);
9407 let lf = h.sub(width + lp[(ps - 2) as usize]);
9408
9409 if cmp(ar[0] as *const c_void, lf as *const c_void, arg) >= 0
9410 && cmp(ar[0] as *const c_void, rt as *const c_void, arg) >= 0
9411 {
9412 break;
9413 }
9414 if cmp(lf as *const c_void, rt as *const c_void, arg) >= 0 {
9415 ar[i & AR_MASK] = lf;
9416 i += 1;
9417 h = lf;
9418 ps -= 1;
9419 } else {
9420 ar[i & AR_MASK] = rt;
9421 i += 1;
9422 h = rt;
9423 ps -= 2;
9424 }
9425 }
9426 qsort_cycle(width, &mut ar, i & AR_MASK);
9427}
9428
9429unsafe fn qsort_trinkle(
9430 head: *mut u8, width: usize,
9431 cmp: CmpRfn, arg: *mut c_void,
9432 pp: &[usize; 2], pshift: i32, trusty: i32,
9433 lp: &[usize],
9434) {
9435 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
9436 let mut p = *pp;
9437 ar[0] = head;
9438 let mut i = 1usize;
9439 let mut h = head;
9440 let mut ps = pshift;
9441 let mut t = trusty;
9442
9443 while p[0] != 1 || p[1] != 0 {
9444 let stepson = h.sub(lp[ps as usize]);
9445 if cmp(stepson as *const c_void, ar[0] as *const c_void, arg) <= 0 {
9446 break;
9447 }
9448 if t == 0 && ps > 1 {
9449 let rt = h.sub(width);
9450 let lf = h.sub(width + lp[(ps - 2) as usize]);
9451 if cmp(rt as *const c_void, stepson as *const c_void, arg) >= 0
9452 || cmp(lf as *const c_void, stepson as *const c_void, arg) >= 0
9453 {
9454 break;
9455 }
9456 }
9457
9458 ar[i & AR_MASK] = stepson;
9459 i += 1;
9460 h = stepson;
9461 let trail = qsort_pntz(&p);
9462 qsort_shr(&mut p, trail);
9463 ps += trail;
9464 t = 0;
9465 }
9466 if t == 0 {
9467 qsort_cycle(width, &mut ar, i & AR_MASK);
9468 qsort_sift(h, width, cmp, arg, ps, lp);
9469 }
9470}
9471
9472#[no_mangle]
9473pub unsafe extern "C" fn __qsort_r(
9474 base: *mut c_void,
9475 nel: usize,
9476 width: usize,
9477 cmp: CmpRfn,
9478 arg: *mut c_void,
9479) {
9480 let size = width * nel;
9481 if size == 0 { return; }
9482
9483 let mut lp = [0usize; 96];
9484 lp[0] = width;
9485 lp[1] = width;
9486 let mut li = 2;
9487 while {
9488 lp[li] = lp[li - 2] + lp[li - 1] + width;
9489 lp[li] < size
9490 } {
9491 li += 1;
9492 }
9493
9494 let mut head = base as *mut u8;
9495 let high = head.add(size - width);
9496 let mut p: [usize; 2] = [1, 0];
9497 let mut pshift: i32 = 1;
9498
9499 while head < high {
9500 if (p[0] & 3) == 3 {
9501 qsort_sift(head, width, cmp, arg, pshift, &lp);
9502 qsort_shr(&mut p, 2);
9503 pshift += 2;
9504 } else {
9505 if lp[(pshift - 1) as usize] >= (high as usize) - (head as usize) {
9506 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
9507 } else {
9508 qsort_sift(head, width, cmp, arg, pshift, &lp);
9509 }
9510
9511 if pshift == 1 {
9512 qsort_shl(&mut p, 1);
9513 pshift = 0;
9514 } else {
9515 qsort_shl(&mut p, pshift - 1);
9516 pshift = 1;
9517 }
9518 }
9519
9520 p[0] |= 1;
9521 head = head.add(width);
9522 }
9523
9524 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
9525
9526 while pshift != 1 || p[0] != 1 || p[1] != 0 {
9527 if pshift <= 1 {
9528 let trail = qsort_pntz(&p);
9529 qsort_shr(&mut p, trail);
9530 pshift += trail;
9531 } else {
9532 qsort_shl(&mut p, 2);
9533 pshift -= 2;
9534 p[0] ^= 7;
9535 qsort_shr(&mut p, 1);
9536 qsort_trinkle(
9537 head.sub(lp[pshift as usize] + width),
9538 width, cmp, arg, &p, pshift + 1, 1, &lp,
9539 );
9540 qsort_shl(&mut p, 1);
9541 p[0] |= 1;
9542 qsort_trinkle(head.sub(width), width, cmp, arg, &p, pshift, 1, &lp);
9543 }
9544 head = head.sub(width);
9545 }
9546}
9547
9548#[no_mangle]
9549pub unsafe extern "C" fn qsort_r(
9550 base: *mut c_void,
9551 nel: usize,
9552 width: usize,
9553 cmp: CmpRfn,
9554 arg: *mut c_void,
9555) {
9556 __qsort_r(base, nel, width, cmp, arg);
9557}
9558
9559unsafe extern "C" fn qsort_wrap_cmp(
9560 a: *const c_void,
9561 b: *const c_void,
9562 cmp_ctx: *mut c_void,
9563) -> c_int {
9564 let cmp: CmpFn = core::mem::transmute(cmp_ctx);
9565 cmp(a, b)
9566}
9567
9568#[no_mangle]
9569pub unsafe extern "C" fn qsort(
9570 base: *mut c_void,
9571 nel: usize,
9572 width: usize,
9573 cmp: CmpFn,
9574) {
9575 __qsort_r(base, nel, width, qsort_wrap_cmp, cmp as *mut c_void);
9576}
9577
9578const ATEXIT_COUNT: usize = 32;
9583
9584#[repr(C)]
9585struct AtExitBlock {
9586 next: *mut AtExitBlock,
9587 f: [Option<unsafe extern "C" fn(*mut c_void)>; ATEXIT_COUNT],
9588 a: [*mut c_void; ATEXIT_COUNT],
9589}
9590
9591static mut ATEXIT_BUILTIN: AtExitBlock = AtExitBlock {
9592 next: core::ptr::null_mut(),
9593 f: [None; ATEXIT_COUNT],
9594 a: [core::ptr::null_mut(); ATEXIT_COUNT],
9595};
9596static mut ATEXIT_HEAD: *mut AtExitBlock = core::ptr::null_mut();
9597static mut ATEXIT_SLOT: usize = 0;
9598static mut ATEXIT_FINISHED: bool = false;
9599
9600#[no_mangle]
9601pub unsafe extern "C" fn __funcs_on_exit() {
9602 while !ATEXIT_HEAD.is_null() {
9603 let head = ATEXIT_HEAD;
9604 while ATEXIT_SLOT > 0 {
9605 ATEXIT_SLOT -= 1;
9606 if let Some(f) = (*head).f[ATEXIT_SLOT] {
9607 let a = (*head).a[ATEXIT_SLOT];
9608 f(a);
9609 }
9610 }
9611 ATEXIT_HEAD = (*head).next;
9612 ATEXIT_SLOT = ATEXIT_COUNT;
9613 }
9614 ATEXIT_FINISHED = true;
9615}
9616
9617#[no_mangle]
9618pub unsafe extern "C" fn __cxa_atexit(
9619 func: unsafe extern "C" fn(*mut c_void),
9620 arg: *mut c_void,
9621 _dso: *mut c_void,
9622) -> c_int {
9623 if ATEXIT_FINISHED {
9624 return -1;
9625 }
9626 if ATEXIT_HEAD.is_null() {
9627 ATEXIT_HEAD = core::ptr::addr_of_mut!(ATEXIT_BUILTIN);
9628 }
9629 if ATEXIT_SLOT == ATEXIT_COUNT {
9630 let new = calloc(1, core::mem::size_of::<AtExitBlock>()) as *mut AtExitBlock;
9631 if new.is_null() {
9632 return -1;
9633 }
9634 (*new).next = ATEXIT_HEAD;
9635 ATEXIT_HEAD = new;
9636 ATEXIT_SLOT = 0;
9637 }
9638 (*ATEXIT_HEAD).f[ATEXIT_SLOT] = Some(func);
9639 (*ATEXIT_HEAD).a[ATEXIT_SLOT] = arg;
9640 ATEXIT_SLOT += 1;
9641 0
9642}
9643
9644unsafe extern "C" fn atexit_caller(arg: *mut c_void) {
9645 let func: unsafe extern "C" fn() = core::mem::transmute(arg);
9646 func();
9647}
9648
9649#[no_mangle]
9650pub unsafe extern "C" fn atexit(func: unsafe extern "C" fn()) -> c_int {
9651 __cxa_atexit(atexit_caller, func as *mut c_void, core::ptr::null_mut())
9652}
9653
9654#[no_mangle]
9655pub unsafe extern "C" fn __cxa_finalize(_dso: *mut c_void) {}
9656
9657#[no_mangle]
9662pub static mut __environ: *mut *mut c_char = core::ptr::null_mut();
9663
9664const ENV_MAX_ALLOCED: usize = 256;
9666static mut ENV_ALLOCED: [*mut c_char; ENV_MAX_ALLOCED] = [core::ptr::null_mut(); ENV_MAX_ALLOCED];
9667static mut ENV_ALLOCED_N: usize = 0;
9668
9669unsafe fn env_rm_add(old: *mut c_char, mut new: *mut c_char) {
9670 for i in 0..ENV_ALLOCED_N {
9671 if ENV_ALLOCED[i] == old {
9672 ENV_ALLOCED[i] = new;
9673 if !old.is_null() {
9674 free(old as *mut c_void);
9675 }
9676 return;
9677 } else if ENV_ALLOCED[i].is_null() && !new.is_null() {
9678 ENV_ALLOCED[i] = new;
9679 new = core::ptr::null_mut();
9680 }
9681 }
9682 if !new.is_null() && ENV_ALLOCED_N < ENV_MAX_ALLOCED {
9683 ENV_ALLOCED[ENV_ALLOCED_N] = new;
9684 ENV_ALLOCED_N += 1;
9685 }
9686}
9687
9688unsafe fn strchrnul_u8(s: *const u8, c: u8) -> *const u8 {
9689 let mut p = s;
9690 while *p != 0 && *p != c {
9691 p = p.add(1);
9692 }
9693 p
9694}
9695
9696#[no_mangle]
9697pub unsafe extern "C" fn getenv(name: *const c_char) -> *mut c_char {
9698 if __environ.is_null() || name.is_null() {
9699 return core::ptr::null_mut();
9700 }
9701 let name = name as *const u8;
9702 let l = strchrnul_u8(name, b'=') as usize - name as usize;
9703 if l == 0 || *name.add(l) != 0 {
9704 return core::ptr::null_mut();
9705 }
9706 let mut e = __environ;
9707 while !(*e).is_null() {
9708 let entry = *e as *const u8;
9709 if strncmp(entry, name, l) == 0 && *entry.add(l) == b'=' {
9710 return entry.add(l + 1) as *mut c_char;
9711 }
9712 e = e.add(1);
9713 }
9714 core::ptr::null_mut()
9715}
9716
9717#[no_mangle]
9718pub unsafe extern "C" fn setenv(
9719 var: *const c_char,
9720 value: *const c_char,
9721 overwrite: c_int,
9722) -> c_int {
9723 if var.is_null() || value.is_null() {
9724 ERRNO!() = EINVAL;
9725 return -1;
9726 }
9727 let var = var as *const u8;
9728 let l1 = strchrnul_u8(var, b'=') as usize - var as usize;
9729 if l1 == 0 || *var.add(l1) != 0 {
9730 ERRNO!() = EINVAL;
9731 return -1;
9732 }
9733 if overwrite == 0 && !getenv(var as *const c_char).is_null() {
9734 return 0;
9735 }
9736 let l2 = strlen(value as *const c_char);
9737 let s = malloc(l1 + l2 + 2) as *mut u8;
9738 if s.is_null() {
9739 return -1;
9740 }
9741 core::ptr::copy_nonoverlapping(var, s, l1);
9742 *s.add(l1) = b'=';
9743 core::ptr::copy_nonoverlapping(value as *const u8, s.add(l1 + 1), l2 + 1);
9744 putenv_internal(s as *mut c_char, l1, s as *mut c_char)
9745}
9746
9747unsafe fn putenv_internal(s: *mut c_char, l: usize, r: *mut c_char) -> c_int {
9748 let mut i = 0;
9749 if !__environ.is_null() {
9750 let mut e = __environ;
9751 while !(*e).is_null() {
9752 if strncmp(s as *const u8, *e as *const u8, l + 1) == 0 {
9753 let tmp = *e;
9754 *e = s;
9755 env_rm_add(tmp, r);
9756 return 0;
9757 }
9758 e = e.add(1);
9759 i += 1;
9760 }
9761 }
9762 let newenv = malloc(core::mem::size_of::<*mut c_char>() * (i + 2)) as *mut *mut c_char;
9763 if newenv.is_null() {
9764 if !r.is_null() { free(r as *mut c_void); }
9765 return -1;
9766 }
9767 if i > 0 && !__environ.is_null() {
9768 core::ptr::copy_nonoverlapping(__environ, newenv, i);
9769 }
9770 *newenv.add(i) = s;
9771 *newenv.add(i + 1) = core::ptr::null_mut();
9772 __environ = newenv;
9774 environ = __environ;
9775 if !r.is_null() {
9776 env_rm_add(core::ptr::null_mut(), r);
9777 }
9778 0
9779}
9780
9781#[no_mangle]
9782pub unsafe extern "C" fn putenv(s: *mut c_char) -> c_int {
9783 if s.is_null() { return -1; }
9784 let l = strchrnul_u8(s as *const u8, b'=') as usize - s as *const u8 as usize;
9785 if l == 0 || *s.add(l) as u8 == 0 {
9786 return unsetenv(s);
9787 }
9788 putenv_internal(s, l, core::ptr::null_mut())
9789}
9790
9791#[no_mangle]
9792pub unsafe extern "C" fn unsetenv(name: *const c_char) -> c_int {
9793 if name.is_null() {
9794 ERRNO!() = EINVAL;
9795 return -1;
9796 }
9797 let name = name as *const u8;
9798 let l = strchrnul_u8(name, b'=') as usize - name as usize;
9799 if l == 0 || *name.add(l) != 0 {
9800 ERRNO!() = EINVAL;
9801 return -1;
9802 }
9803 if __environ.is_null() {
9804 return 0;
9805 }
9806 let mut e = __environ;
9807 let mut eo = e;
9808 while !(*e).is_null() {
9809 if strncmp(name, *e as *const u8, l) == 0 && *(*e as *const u8).add(l) == b'=' {
9810 env_rm_add(*e, core::ptr::null_mut());
9811 } else {
9812 if eo != e {
9813 *eo = *e;
9814 }
9815 eo = eo.add(1);
9816 }
9817 e = e.add(1);
9818 }
9819 if eo != e {
9820 *eo = core::ptr::null_mut();
9821 }
9822 environ = __environ;
9823 0
9824}
9825
9826#[no_mangle]
9827pub unsafe extern "C" fn clearenv() -> c_int {
9828 let e = __environ;
9829 __environ = core::ptr::null_mut();
9830 environ = core::ptr::null_mut();
9831 if !e.is_null() {
9832 let mut p = e;
9833 while !(*p).is_null() {
9834 env_rm_add(*p, core::ptr::null_mut());
9835 p = p.add(1);
9836 }
9837 }
9838 0
9839}
9840
9841static mut RANDOM_INIT: [u32; 32] = [
9847 0x00000000,0x5851f42d,0xc0b18ccf,0xcbb5f646,
9848 0xc7033129,0x30705b04,0x20fd5db4,0x9a8b7f78,
9849 0x502959d8,0xab894868,0x6c0356a7,0x88cdb7ff,
9850 0xb477d43f,0x70a3a52b,0xa8e4baf1,0xfd8341fc,
9851 0x8ae16fd9,0x742d2f7a,0x0d1f0796,0x76035e09,
9852 0x40f7702c,0x6fa72ca5,0xaaa84157,0x58a0df74,
9853 0xc74a0364,0xae533cc4,0x04185faf,0x6de3b115,
9854 0x0cab8628,0xf043bfa4,0x398150e9,0x37521657,
9855];
9856
9857static mut RANDOM_N: i32 = 31;
9858static mut RANDOM_I: i32 = 3;
9859static mut RANDOM_J: i32 = 0;
9860static mut RANDOM_X: *mut u32 = unsafe { core::ptr::addr_of_mut!(RANDOM_INIT).cast::<u32>().add(1) };
9861
9862unsafe fn random_lcg31(x: u32) -> u32 {
9863 (1103515245u32.wrapping_mul(x).wrapping_add(12345)) & 0x7fffffff
9864}
9865
9866unsafe fn random_lcg64(x: u64) -> u64 {
9867 6364136223846793005u64.wrapping_mul(x).wrapping_add(1)
9868}
9869
9870unsafe fn random_savestate() -> *mut u8 {
9871 (*RANDOM_X.offset(-1)) = ((RANDOM_N as u32) << 16) | ((RANDOM_I as u32) << 8) | (RANDOM_J as u32);
9872 RANDOM_X.offset(-1) as *mut u8
9873}
9874
9875unsafe fn random_loadstate(state: *mut u32) {
9876 RANDOM_X = state.add(1);
9877 RANDOM_N = ((*RANDOM_X.offset(-1)) >> 16) as i32;
9878 RANDOM_I = (((*RANDOM_X.offset(-1)) >> 8) & 0xff) as i32;
9879 RANDOM_J = ((*RANDOM_X.offset(-1)) & 0xff) as i32;
9880}
9881
9882unsafe fn random_srandom_inner(seed: u32) {
9883 let mut s = seed as u64;
9884 if RANDOM_N == 0 {
9885 *RANDOM_X = s as u32;
9886 return;
9887 }
9888 RANDOM_I = if RANDOM_N == 31 || RANDOM_N == 7 { 3 } else { 1 };
9889 RANDOM_J = 0;
9890 for k in 0..RANDOM_N as usize {
9891 s = random_lcg64(s);
9892 *RANDOM_X.add(k) = (s >> 32) as u32;
9893 }
9894 *RANDOM_X |= 1;
9895}
9896
9897#[no_mangle]
9898pub unsafe extern "C" fn srandom(seed: c_uint) {
9899 random_srandom_inner(seed);
9900}
9901
9902#[no_mangle]
9903pub unsafe extern "C" fn initstate(seed: c_uint, state: *mut c_char, size: usize) -> *mut c_char {
9904 if size < 8 { return core::ptr::null_mut(); }
9905 let old = random_savestate();
9906 RANDOM_N = if size < 32 { 0 }
9907 else if size < 64 { 7 }
9908 else if size < 128 { 15 }
9909 else if size < 256 { 31 }
9910 else { 63 };
9911 RANDOM_X = (state as *mut u32).add(1);
9912 random_srandom_inner(seed);
9913 random_savestate();
9914 old as *mut c_char
9915}
9916
9917#[no_mangle]
9918pub unsafe extern "C" fn setstate(state: *mut c_char) -> *mut c_char {
9919 let old = random_savestate();
9920 random_loadstate(state as *mut u32);
9921 old as *mut c_char
9922}
9923
9924#[no_mangle]
9925pub unsafe extern "C" fn random() -> c_long {
9926 let k: c_long;
9927 if RANDOM_N == 0 {
9928 *RANDOM_X = random_lcg31(*RANDOM_X);
9929 k = *RANDOM_X as c_long;
9930 } else {
9931 *RANDOM_X.add(RANDOM_I as usize) = (*RANDOM_X.add(RANDOM_I as usize)).wrapping_add(*RANDOM_X.add(RANDOM_J as usize));
9932 k = (*RANDOM_X.add(RANDOM_I as usize) >> 1) as c_long;
9933 RANDOM_I += 1;
9934 if RANDOM_I == RANDOM_N { RANDOM_I = 0; }
9935 RANDOM_J += 1;
9936 if RANDOM_J == RANDOM_N { RANDOM_J = 0; }
9937 }
9938 k
9939}
9940
9941const SA: u8 = 0xC2;
9946const SB: u8 = 0xF4;
9947
9948const BITTAB: [u32; 51] = [
9949 0xC000_0002, 0xC000_0003, 0xC000_0004, 0xC000_0005, 0xC000_0006, 0xC000_0007,
9950 0xC000_0008, 0xC000_0009, 0xC000_000A, 0xC000_000B, 0xC000_000C, 0xC000_000D,
9951 0xC000_000E, 0xC000_000F, 0xC000_0010, 0xC000_0011, 0xC000_0012, 0xC000_0013,
9952 0xC000_0014, 0xC000_0015, 0xC000_0016, 0xC000_0017, 0xC000_0018, 0xC000_0019,
9953 0xC000_001A, 0xC000_001B, 0xC000_001C, 0xC000_001D, 0xC000_001E, 0xC000_001F,
9954 0xB300_0000, 0xC300_0001, 0xC300_0002, 0xC300_0003, 0xC300_0004, 0xC300_0005,
9955 0xC300_0006, 0xC300_0007, 0xC300_0008, 0xC300_0009, 0xC300_000A, 0xC300_000B,
9956 0xC300_000C, 0xD300_000D, 0xC300_000E, 0xC300_000F, 0xBB0C_0000, 0xC30C_0001,
9957 0xC30C_0002, 0xC30C_0003, 0xDB0C_0004,
9958];
9959
9960#[inline]
9961fn mb_oob(c: u32, b: u8) -> u32 {
9962 let b3 = (b >> 3) as u32;
9963 ((b3.wrapping_sub(0x10)) | (b3.wrapping_add((c as i32 >> 26) as u32))) & !7
9964}
9965
9966static mut MB_STATE: c_uint = 0;
9967
9968const MB_CUR_MAX_VAL_UTF8: usize = 4;
9969const MB_CUR_MAX_VAL_C: usize = 1;
9970
9971#[no_mangle]
9972pub extern "C" fn __ctype_get_mb_cur_max() -> usize {
9973 unsafe { if LOCALE_CTYPE_UTF8 { MB_CUR_MAX_VAL_UTF8 } else { MB_CUR_MAX_VAL_C } }
9974}
9975
9976#[no_mangle]
9977pub unsafe extern "C" fn mbrtowc(
9978 wc: *mut c_int,
9979 src: *const c_char,
9980 n: usize,
9981 st: *mut c_uint,
9982) -> usize {
9983 let s = src as *const u8;
9984 let n0 = n;
9985 let mut dummy: c_int = 0;
9986 let wc = if wc.is_null() { &mut dummy } else { &mut *wc };
9987 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
9988
9989 let mut c: u32 = *st;
9990 let mut s = s;
9991 let mut n = n;
9992
9993 if s.is_null() {
9994 if c != 0 { *st = 0; ERRNO!() = EILSEQ; return !0usize; }
9995 return 0;
9996 }
9997
9998 if n == 0 { return !1usize; }
9999
10000 if unsafe { !LOCALE_CTYPE_UTF8 } {
10001 let b = *s;
10002 *wc = b as c_int;
10003 return if b == 0 { 0 } else { 1 };
10004 }
10005
10006 if c == 0 {
10007 if *s < 0x80 {
10008 let r = if *s == 0 { 0 } else { 1 };
10009 *wc = *s as c_int;
10010 return r;
10011 }
10012 if (*s).wrapping_sub(SA) as u32 > (SB - SA) as u32 {
10013 *st = 0; ERRNO!() = EILSEQ; return !0usize;
10014 }
10015 c = BITTAB[*s as usize - SA as usize];
10016 s = s.add(1);
10017 n -= 1;
10018 }
10019
10020 if n > 0 {
10021 if mb_oob(c, *s) != 0 {
10022 *st = 0; ERRNO!() = EILSEQ; return !0usize;
10023 }
10024 loop {
10025 c = (c << 6) | (*s as u32).wrapping_sub(0x80);
10026 s = s.add(1);
10027 n -= 1;
10028 if c & (1u32 << 31) == 0 {
10029 *st = 0;
10030 *wc = c as c_int;
10031 return n0 - n;
10032 }
10033 if n == 0 { break; }
10034 if (*s).wrapping_sub(0x80) >= 0x40 {
10035 *st = 0; ERRNO!() = EILSEQ; return !0usize;
10036 }
10037 }
10038 }
10039
10040 *st = c;
10041 !1usize
10042}
10043
10044#[no_mangle]
10045pub unsafe extern "C" fn wcrtomb(
10046 s: *mut c_char,
10047 wc: c_int,
10048 _st: *mut c_uint,
10049) -> usize {
10050 if s.is_null() { return 1; }
10051 let wc_u = wc as u32;
10052 if unsafe { !LOCALE_CTYPE_UTF8 } {
10053 if wc_u > 0xFF {
10054 ERRNO!() = EILSEQ;
10055 return !0usize;
10056 }
10057 *s = wc as c_char;
10058 return 1;
10059 }
10060 if wc_u < 0x80 {
10061 *s = wc as c_char;
10062 return 1;
10063 }
10064 if wc_u < 0x800 {
10065 *s = (0xC0 | (wc_u >> 6)) as c_char;
10066 *s.add(1) = (0x80 | (wc_u & 0x3F)) as c_char;
10067 return 2;
10068 }
10069 if wc_u < 0xD800 || wc_u.wrapping_sub(0xE000) < 0x2000 {
10070 *s = (0xE0 | (wc_u >> 12)) as c_char;
10071 *s.add(1) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
10072 *s.add(2) = (0x80 | (wc_u & 0x3F)) as c_char;
10073 return 3;
10074 }
10075 if wc_u.wrapping_sub(0x10000) < 0x100000 {
10076 *s = (0xF0 | (wc_u >> 18)) as c_char;
10077 *s.add(1) = (0x80 | ((wc_u >> 12) & 0x3F)) as c_char;
10078 *s.add(2) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
10079 *s.add(3) = (0x80 | (wc_u & 0x3F)) as c_char;
10080 return 4;
10081 }
10082 ERRNO!() = EILSEQ;
10083 !0usize
10084}
10085
10086#[no_mangle]
10087pub unsafe extern "C" fn mblen(s: *const c_char, n: usize) -> c_int {
10088 if s.is_null() { return 0; }
10089 mbtowc(core::ptr::null_mut(), s, n)
10090}
10091
10092#[no_mangle]
10093pub unsafe extern "C" fn mbtowc(
10094 wc: *mut c_int,
10095 src: *const c_char,
10096 n: usize,
10097) -> c_int {
10098 if src.is_null() { return 0; }
10099 if n == 0 { ERRNO!() = EILSEQ; return -1; }
10100 let mut state: c_uint = 0;
10101 let mut w: c_int = 0;
10102 let r = mbrtowc(&mut w, src, n, &mut state);
10103 if r == !0usize { return -1; }
10104 if !wc.is_null() { *wc = w; }
10105 r as c_int
10106}
10107
10108#[no_mangle]
10109pub unsafe extern "C" fn wctomb(s: *mut c_char, wc: c_int) -> c_int {
10110 if s.is_null() { return 0; }
10111 wcrtomb(s, wc, core::ptr::null_mut()) as c_int
10112}
10113
10114#[no_mangle]
10115pub unsafe extern "C" fn mbsrtowcs(
10116 ws: *mut c_int,
10117 src: *mut *const c_char,
10118 wn: usize,
10119 st: *mut c_uint,
10120) -> usize {
10121 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
10122 let mut s = *src as *const u8;
10123 let wn0 = wn;
10124 let mut wn = wn;
10125
10126 if ws.is_null() {
10127 while *s != 0 {
10128 if *s < 0x80 {
10129 s = s.add(1);
10130 wn = wn.wrapping_sub(1);
10131 continue;
10132 }
10133 let mut wc: c_int = 0;
10134 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
10135 if r == !0usize { return !0usize; }
10136 if r == !1usize { return wn0 - wn; }
10137 s = s.add(r);
10138 wn = wn.wrapping_sub(1);
10139 }
10140 wn0 - wn
10141 } else {
10142 let mut w = ws;
10143 while wn > 0 {
10144 if *s < 0x80 {
10145 let c = *s as c_int;
10146 *w = c;
10147 if c == 0 {
10148 *src = core::ptr::null();
10149 return wn0 - wn;
10150 }
10151 w = w.add(1);
10152 s = s.add(1);
10153 wn -= 1;
10154 continue;
10155 }
10156 let mut wc: c_int = 0;
10157 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
10158 if r == !0usize {
10159 *src = s as *const c_char;
10160 return !0usize;
10161 }
10162 if r == !1usize {
10163 *src = s as *const c_char;
10164 return wn0 - wn;
10165 }
10166 *w = wc;
10167 w = w.add(1);
10168 s = s.add(r);
10169 wn -= 1;
10170 }
10171 *src = s as *const c_char;
10172 wn0 - wn
10173 }
10174}
10175
10176#[no_mangle]
10177pub unsafe extern "C" fn wcsrtombs(
10178 s: *mut c_char,
10179 ws: *mut *const c_int,
10180 n: usize,
10181 _st: *mut c_uint,
10182) -> usize {
10183 let mut w = *ws;
10184 let n0 = n;
10185 let mut n = n;
10186
10187 if s.is_null() {
10188 let mut count = 0usize;
10189 while *w != 0 {
10190 if (*w as u32) < 0x80 {
10191 count += 1;
10192 } else {
10193 let mut buf = [0u8; 4];
10194 let r = wcrtomb(buf.as_mut_ptr() as *mut c_char, *w, core::ptr::null_mut());
10195 if r == !0usize { return !0usize; }
10196 count += r;
10197 }
10198 w = w.add(1);
10199 }
10200 return count;
10201 }
10202
10203 let mut dst = s;
10204 while n > 0 {
10205 if (*w as u32) < 0x80 {
10206 *dst = *w as c_char;
10207 if *w == 0 {
10208 *ws = core::ptr::null();
10209 return n0 - n;
10210 }
10211 dst = dst.add(1);
10212 n -= 1;
10213 } else {
10214 let r = wcrtomb(dst, *w, core::ptr::null_mut());
10215 if r == !0usize {
10216 *ws = w;
10217 return !0usize;
10218 }
10219 if r > n {
10220 *ws = w;
10221 return n0 - n;
10222 }
10223 dst = dst.add(r);
10224 n -= r;
10225 }
10226 w = w.add(1);
10227 }
10228 *ws = w;
10229 n0
10230}
10231
10232#[no_mangle]
10233pub unsafe extern "C" fn mbstowcs(
10234 ws: *mut c_int,
10235 src: *const c_char,
10236 wn: usize,
10237) -> usize {
10238 let mut src_ptr = src;
10239 mbsrtowcs(ws, &mut src_ptr, wn, core::ptr::null_mut())
10240}
10241
10242#[no_mangle]
10243pub unsafe extern "C" fn wcstombs(
10244 s: *mut c_char,
10245 ws: *const c_int,
10246 n: usize,
10247) -> usize {
10248 let mut ws_ptr = ws;
10249 wcsrtombs(s, &mut ws_ptr, n, core::ptr::null_mut())
10250}
10251
10252#[no_mangle]
10257pub extern "C" fn btowc(c: c_int) -> wint_t {
10258 if c == -1 { return WEOF; }
10259 unsafe {
10260 if LOCALE_CTYPE_UTF8 {
10261 if (c as u32) < 128 { c as wint_t } else { WEOF }
10262 } else {
10263 (c as u8) as wint_t
10264 }
10265 }
10266}
10267
10268#[no_mangle]
10269pub extern "C" fn wctob(c: wint_t) -> c_int {
10270 unsafe {
10271 if LOCALE_CTYPE_UTF8 {
10272 if c < 128 { c as c_int } else { -1 }
10273 } else {
10274 if c <= 0xFF { c as c_int } else { -1 }
10275 }
10276 }
10277}
10278
10279#[no_mangle]
10280pub unsafe extern "C" fn mbsinit(s: *const c_uint) -> c_int {
10281 if s.is_null() || *s == 0 { 1 } else { 0 }
10282}
10283
10284#[no_mangle]
10285pub unsafe extern "C" fn mbrlen(s: *const c_char, n: usize, ps: *mut c_uint) -> usize {
10286 mbrtowc(core::ptr::null_mut(), s, n, ps)
10287}
10288
10289#[no_mangle]
10294pub unsafe extern "C" fn wcslen(s: *const wchar_t) -> usize {
10295 let mut len = 0;
10296 while *s.add(len) != 0 { len += 1; }
10297 len
10298}
10299
10300#[no_mangle]
10301pub unsafe extern "C" fn wcschr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
10302 let mut i = 0;
10303 loop {
10304 let ch = *s.add(i);
10305 if ch == c { return s.add(i) as *mut wchar_t; }
10306 if ch == 0 { return null_mut(); }
10307 i += 1;
10308 }
10309}
10310
10311#[no_mangle]
10312pub unsafe extern "C" fn wcsrchr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
10313 let mut i = 0;
10314 let mut last: *mut wchar_t = null_mut();
10315 loop {
10316 let ch = *s.add(i);
10317 if ch == c { last = s.add(i) as *mut wchar_t; }
10318 if ch == 0 { return last; }
10319 i += 1;
10320 }
10321}
10322
10323#[no_mangle]
10324pub unsafe extern "C" fn wcsstr(haystack: *const wchar_t, needle: *const wchar_t) -> *mut wchar_t {
10325 if *needle == 0 { return haystack as *mut wchar_t; }
10326 let mut i = 0;
10327 loop {
10328 let h = *haystack.add(i);
10329 if h == 0 { return null_mut(); }
10330 if h == *needle {
10331 let mut j = 0;
10332 loop {
10333 let n = *needle.add(j);
10334 if n == 0 { return haystack.add(i) as *mut wchar_t; }
10335 if *haystack.add(i + j) != n { break; }
10336 j += 1;
10337 }
10338 }
10339 i += 1;
10340 }
10341}
10342
10343#[no_mangle]
10344pub unsafe extern "C" fn wcscmp(s1: *const wchar_t, s2: *const wchar_t) -> c_int {
10345 let mut i = 0;
10346 loop {
10347 let a = *s1.add(i);
10348 let b = *s2.add(i);
10349 if a != b { return a - b; }
10350 if a == 0 { return 0; }
10351 i += 1;
10352 }
10353}
10354
10355#[no_mangle]
10356pub unsafe extern "C" fn wcsncmp(s1: *const wchar_t, s2: *const wchar_t, n: usize) -> c_int {
10357 let mut i = 0;
10358 while i < n {
10359 let a = *s1.add(i);
10360 let b = *s2.add(i);
10361 if a != b { return a - b; }
10362 if a == 0 { return 0; }
10363 i += 1;
10364 }
10365 0
10366}
10367
10368#[no_mangle]
10369pub unsafe extern "C" fn wcscpy(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
10370 let mut i = 0;
10371 loop {
10372 let c = *src.add(i);
10373 *dst.add(i) = c;
10374 if c == 0 { break; }
10375 i += 1;
10376 }
10377 dst
10378}
10379
10380#[no_mangle]
10381pub unsafe extern "C" fn wcsncpy(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
10382 let mut i = 0;
10383 while i < n && *src.add(i) != 0 { *dst.add(i) = *src.add(i); i += 1; }
10384 while i < n { *dst.add(i) = 0; i += 1; }
10385 dst
10386}
10387
10388#[no_mangle]
10389pub unsafe extern "C" fn wcscat(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
10390 let mut i = 0;
10391 while *dst.add(i) != 0 { i += 1; }
10392 let mut j = 0;
10393 loop {
10394 let c = *src.add(j);
10395 *dst.add(i + j) = c;
10396 if c == 0 { break; }
10397 j += 1;
10398 }
10399 dst
10400}
10401
10402#[no_mangle]
10403pub unsafe extern "C" fn wcsncat(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
10404 let mut i = 0;
10405 while *dst.add(i) != 0 { i += 1; }
10406 let mut j = 0;
10407 while j < n && *src.add(j) != 0 { *dst.add(i + j) = *src.add(j); j += 1; }
10408 *dst.add(i + j) = 0;
10409 dst
10410}
10411
10412#[no_mangle]
10413pub unsafe extern "C" fn wcsdup(s: *const wchar_t) -> *mut wchar_t {
10414 let len = wcslen(s);
10415 let p = malloc((len + 1) * core::mem::size_of::<wchar_t>()) as *mut wchar_t;
10416 if p.is_null() { return null_mut(); }
10417 core::ptr::copy_nonoverlapping(s, p, len + 1);
10418 p
10419}
10420
10421#[no_mangle]
10422pub unsafe extern "C" fn wcsnlen(s: *const wchar_t, maxlen: usize) -> usize {
10423 let mut i = 0;
10424 while i < maxlen && *s.add(i) != 0 { i += 1; }
10425 i
10426}
10427
10428#[no_mangle]
10429pub unsafe extern "C" fn wcsspn(s: *const wchar_t, accept: *const wchar_t) -> usize {
10430 let mut i = 0;
10431 loop {
10432 let c = *s.add(i);
10433 if c == 0 { return i; }
10434 let mut found = false;
10435 let mut j = 0;
10436 loop {
10437 let a = *accept.add(j);
10438 if a == 0 { break; }
10439 if c == a { found = true; break; }
10440 j += 1;
10441 }
10442 if !found { return i; }
10443 i += 1;
10444 }
10445}
10446
10447#[no_mangle]
10448pub unsafe extern "C" fn wcscspn(s: *const wchar_t, reject: *const wchar_t) -> usize {
10449 let mut i = 0;
10450 loop {
10451 let c = *s.add(i);
10452 if c == 0 { return i; }
10453 let mut j = 0;
10454 loop {
10455 let r = *reject.add(j);
10456 if r == 0 { break; }
10457 if c == r { return i; }
10458 j += 1;
10459 }
10460 i += 1;
10461 }
10462}
10463
10464#[no_mangle]
10465pub unsafe extern "C" fn wcspbrk(s: *const wchar_t, accept: *const wchar_t) -> *mut wchar_t {
10466 let mut i = 0;
10467 loop {
10468 let c = *s.add(i);
10469 if c == 0 { return null_mut(); }
10470 let mut j = 0;
10471 loop {
10472 let a = *accept.add(j);
10473 if a == 0 { break; }
10474 if c == a { return s.add(i) as *mut wchar_t; }
10475 j += 1;
10476 }
10477 i += 1;
10478 }
10479}
10480
10481#[no_mangle]
10482pub unsafe extern "C" fn wcsxfrm(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> usize {
10483 let len = wcslen(src);
10484 if !dst.is_null() {
10485 let copy = if len < n { len } else { if n > 0 { n - 1 } else { 0 } };
10486 for i in 0..copy { *dst.add(i) = *src.add(i); }
10487 if n > 0 { *dst.add(copy) = 0; }
10488 }
10489 len
10490}
10491
10492unsafe fn wcs_to_bytes(ws: *const wchar_t, buf: *mut u8, bufsz: usize) -> usize {
10497 let mut i = 0;
10498 while i < bufsz - 1 {
10499 let c = *ws.add(i);
10500 if c == 0 { break; }
10501 if (c as u32) > 127 { break; }
10502 *buf.add(i) = c as u8;
10503 i += 1;
10504 }
10505 *buf.add(i) = 0;
10506 i
10507}
10508
10509#[no_mangle]
10510pub unsafe extern "C" fn wcstol(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_long {
10511 let mut buf = [0u8; 256];
10512 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10513 let mut end: *mut c_char = core::ptr::null_mut();
10514 let r = strtol(buf.as_ptr() as *const c_char, &mut end, base);
10515 if !endptr.is_null() {
10516 let offset = end as usize - buf.as_ptr() as usize;
10517 *endptr = s.add(offset) as *mut wchar_t;
10518 }
10519 r
10520}
10521
10522#[no_mangle]
10523pub unsafe extern "C" fn wcstoul(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulong {
10524 let mut buf = [0u8; 256];
10525 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10526 let mut end: *mut c_char = core::ptr::null_mut();
10527 let r = strtoul(buf.as_ptr() as *const c_char, &mut end, base);
10528 if !endptr.is_null() {
10529 let offset = end as usize - buf.as_ptr() as usize;
10530 *endptr = s.add(offset) as *mut wchar_t;
10531 }
10532 r
10533}
10534
10535#[no_mangle]
10536pub unsafe extern "C" fn wcstoll(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong {
10537 let mut buf = [0u8; 256];
10538 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10539 let mut end: *mut c_char = core::ptr::null_mut();
10540 let r = strtoll(buf.as_ptr() as *const c_char, &mut end, base);
10541 if !endptr.is_null() {
10542 let offset = end as usize - buf.as_ptr() as usize;
10543 *endptr = s.add(offset) as *mut wchar_t;
10544 }
10545 r
10546}
10547
10548#[no_mangle]
10549pub unsafe extern "C" fn wcstoull(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong {
10550 let mut buf = [0u8; 256];
10551 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10552 let mut end: *mut c_char = core::ptr::null_mut();
10553 let r = strtoull(buf.as_ptr() as *const c_char, &mut end, base);
10554 if !endptr.is_null() {
10555 let offset = end as usize - buf.as_ptr() as usize;
10556 *endptr = s.add(offset) as *mut wchar_t;
10557 }
10558 r
10559}
10560
10561#[no_mangle]
10562pub unsafe extern "C" fn wcstod(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 {
10563 let mut buf = [0u8; 256];
10564 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10565 let mut end: *mut c_char = core::ptr::null_mut();
10566 let r = strtod(buf.as_ptr() as *const c_char, &mut end);
10567 if !endptr.is_null() {
10568 let offset = end as usize - buf.as_ptr() as usize;
10569 *endptr = s.add(offset) as *mut wchar_t;
10570 }
10571 r
10572}
10573
10574#[no_mangle]
10575pub unsafe extern "C" fn wcstof(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f32 { wcstod(s, endptr) as f32 }
10576
10577#[no_mangle]
10578#[cfg(target_arch = "x86_64")]
10579pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 { wcstod(s, endptr) }
10580
10581#[no_mangle]
10582#[cfg(target_arch = "aarch64")]
10583pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
10584
10585#[no_mangle]
10586#[cfg(target_arch = "riscv64")]
10587pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
10588
10589#[no_mangle]
10590pub unsafe extern "C" fn wcstoimax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong { wcstoll(s, endptr, base) }
10591
10592#[no_mangle]
10593pub unsafe extern "C" fn wcstoumax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong { wcstoull(s, endptr, base) }
10594
10595const WC_ALPHA: c_int = 1;
10600const WC_DIGIT: c_int = 2;
10601const WC_SPACE: c_int = 4;
10602const WC_UPPER: c_int = 8;
10603const WC_LOWER: c_int = 16;
10604const WC_ALNUM: c_int = WC_ALPHA | WC_DIGIT;
10605const WC_BLANK: c_int = 32;
10606const WC_CNTRL: c_int = 64;
10607const WC_PUNCT: c_int = 128;
10608const WC_GRAPH: c_int = WC_ALNUM | WC_PUNCT;
10609const WC_PRINT: c_int = WC_GRAPH | WC_BLANK;
10610const WC_XDIGIT: c_int = 256;
10611
10612fn wc_flags(c: wint_t) -> c_int {
10613 if c < 128 {
10614 let f = CT_TABLE[c as usize];
10615 let mut r = 0;
10616 if f & (CT_UPPER | CT_LOWER) != 0 { r |= WC_ALPHA; }
10617 if f & CT_DIGIT != 0 { r |= WC_DIGIT; }
10618 if f & CT_SPACE != 0 { r |= WC_SPACE; }
10619 if f & CT_UPPER != 0 { r |= WC_UPPER; }
10620 if f & CT_LOWER != 0 { r |= WC_LOWER; }
10621 if f & CT_BLANK != 0 { r |= WC_BLANK; }
10622 if f & CT_CNTRL != 0 { r |= WC_CNTRL; }
10623 if f & CT_PUNCT != 0 { r |= WC_PUNCT; }
10624 if f & CT_XDIGIT != 0 { r |= WC_XDIGIT; }
10625 r
10626 } else {
10627 if c < 0x100 { 0 }
10628 else { WC_PRINT | WC_ALPHA }
10629 }
10630}
10631
10632#[no_mangle]
10633pub extern "C" fn iswalnum(c: wint_t) -> c_int { (wc_flags(c) & WC_ALNUM != 0) as c_int }
10634#[no_mangle]
10635pub extern "C" fn iswalpha(c: wint_t) -> c_int { (wc_flags(c) & WC_ALPHA != 0) as c_int }
10636#[no_mangle]
10637pub extern "C" fn iswblank(c: wint_t) -> c_int { (wc_flags(c) & WC_BLANK != 0) as c_int }
10638#[no_mangle]
10639pub extern "C" fn iswcntrl(c: wint_t) -> c_int { (wc_flags(c) & WC_CNTRL != 0) as c_int }
10640#[no_mangle]
10641pub extern "C" fn iswdigit(c: wint_t) -> c_int { ((c >= b'0' as wint_t) && (c <= b'9' as wint_t)) as c_int }
10642#[no_mangle]
10643pub extern "C" fn iswgraph(c: wint_t) -> c_int { (wc_flags(c) & WC_GRAPH != 0) as c_int }
10644#[no_mangle]
10645pub extern "C" fn iswlower(c: wint_t) -> c_int { (wc_flags(c) & WC_LOWER != 0) as c_int }
10646#[no_mangle]
10647pub extern "C" fn iswprint(c: wint_t) -> c_int {
10648 if c < 128 { (wc_flags(c) & WC_PRINT != 0) as c_int }
10649 else if c >= 0x100 && c < 0x110000 { 1 }
10650 else { 0 }
10651}
10652#[no_mangle]
10653pub extern "C" fn iswpunct(c: wint_t) -> c_int { (wc_flags(c) & WC_PUNCT != 0) as c_int }
10654#[no_mangle]
10655pub extern "C" fn iswspace(c: wint_t) -> c_int {
10656 if c < 128 { (wc_flags(c) & WC_SPACE != 0) as c_int }
10657 else {
10658 match c {
10659 0x1680 | 0x2000..=0x200A | 0x2028 | 0x2029 | 0x202F | 0x205F | 0x3000 => 1,
10660 _ => 0,
10661 }
10662 }
10663}
10664#[no_mangle]
10665pub extern "C" fn iswupper(c: wint_t) -> c_int { (wc_flags(c) & WC_UPPER != 0) as c_int }
10666#[no_mangle]
10667pub extern "C" fn iswxdigit(c: wint_t) -> c_int { (wc_flags(c) & WC_XDIGIT != 0) as c_int }
10668
10669static WCTYPE_ALNUM: c_int = WC_ALNUM;
10670static WCTYPE_ALPHA: c_int = WC_ALPHA;
10671static WCTYPE_BLANK: c_int = WC_BLANK;
10672static WCTYPE_CNTRL: c_int = WC_CNTRL;
10673static WCTYPE_DIGIT: c_int = WC_DIGIT;
10674static WCTYPE_GRAPH: c_int = WC_GRAPH;
10675static WCTYPE_LOWER: c_int = WC_LOWER;
10676static WCTYPE_PRINT: c_int = WC_PRINT;
10677static WCTYPE_PUNCT: c_int = WC_PUNCT;
10678static WCTYPE_SPACE: c_int = WC_SPACE;
10679static WCTYPE_UPPER: c_int = WC_UPPER;
10680static WCTYPE_XDIGIT: c_int = WC_XDIGIT;
10681
10682#[no_mangle]
10683pub unsafe extern "C" fn wctype(name: *const c_char) -> wctype_t {
10684 if name.is_null() { return core::ptr::null(); }
10685 let n = name as *const u8;
10686 if strcmp(n, b"alnum\0".as_ptr()) == 0 { return &WCTYPE_ALNUM; }
10687 if strcmp(n, b"alpha\0".as_ptr()) == 0 { return &WCTYPE_ALPHA; }
10688 if strcmp(n, b"blank\0".as_ptr()) == 0 { return &WCTYPE_BLANK; }
10689 if strcmp(n, b"cntrl\0".as_ptr()) == 0 { return &WCTYPE_CNTRL; }
10690 if strcmp(n, b"digit\0".as_ptr()) == 0 { return &WCTYPE_DIGIT; }
10691 if strcmp(n, b"graph\0".as_ptr()) == 0 { return &WCTYPE_GRAPH; }
10692 if strcmp(n, b"lower\0".as_ptr()) == 0 { return &WCTYPE_LOWER; }
10693 if strcmp(n, b"print\0".as_ptr()) == 0 { return &WCTYPE_PRINT; }
10694 if strcmp(n, b"punct\0".as_ptr()) == 0 { return &WCTYPE_PUNCT; }
10695 if strcmp(n, b"space\0".as_ptr()) == 0 { return &WCTYPE_SPACE; }
10696 if strcmp(n, b"upper\0".as_ptr()) == 0 { return &WCTYPE_UPPER; }
10697 if strcmp(n, b"xdigit\0".as_ptr()) == 0 { return &WCTYPE_XDIGIT; }
10698 core::ptr::null()
10699}
10700
10701#[no_mangle]
10702pub unsafe extern "C" fn iswctype(c: wint_t, desc: wctype_t) -> c_int {
10703 if desc.is_null() { return 0; }
10704 (wc_flags(c) & *desc != 0) as c_int
10705}
10706
10707static WCTRANS_LOWER: c_int = 1;
10708static WCTRANS_UPPER: c_int = 2;
10709
10710#[no_mangle]
10711pub unsafe extern "C" fn towlower(c: wint_t) -> wint_t {
10712 if c < 128 { tolower(c as c_int) as wint_t } else { c }
10713}
10714
10715#[no_mangle]
10716pub unsafe extern "C" fn towupper(c: wint_t) -> wint_t {
10717 if c < 128 { toupper(c as c_int) as wint_t } else { c }
10718}
10719
10720#[no_mangle]
10721pub unsafe extern "C" fn wctrans(name: *const c_char) -> wctrans_t {
10722 if name.is_null() { return core::ptr::null(); }
10723 let n = name as *const u8;
10724 if strcmp(n, b"tolower\0".as_ptr()) == 0 { return &WCTRANS_LOWER; }
10725 if strcmp(n, b"toupper\0".as_ptr()) == 0 { return &WCTRANS_UPPER; }
10726 core::ptr::null()
10727}
10728
10729#[no_mangle]
10730pub unsafe extern "C" fn towctrans(c: wint_t, desc: wctrans_t) -> wint_t {
10731 if desc.is_null() { return c; }
10732 match *desc {
10733 1 => towlower(c),
10734 2 => towupper(c),
10735 _ => c,
10736 }
10737}
10738
10739#[no_mangle]
10744pub unsafe extern "C" fn fgetwc(f: *mut FILE) -> wint_t {
10745 let mut state: c_uint = 0;
10746 let mut wc: wchar_t = 0;
10747 let mut buf = [0u8; 4];
10748 let c = fgetc(f);
10749 if c == -1 { return WEOF; }
10750 buf[0] = c as u8;
10751 if buf[0] < 0x80 { return buf[0] as wint_t; }
10752 let len = if buf[0] < 0xE0 { 2 } else if buf[0] < 0xF0 { 3 } else { 4 };
10753 let mut n = 1usize;
10754 while n < len {
10755 let c2 = fgetc(f);
10756 if c2 == -1 { return WEOF; }
10757 buf[n] = c2 as u8;
10758 n += 1;
10759 }
10760 let r = mbrtowc(&mut wc, buf.as_ptr() as *const c_char, n, &mut state);
10761 if r == !0usize || r == !1usize { WEOF } else { wc as wint_t }
10762}
10763
10764#[no_mangle]
10765pub unsafe extern "C" fn fputwc(c: wchar_t, f: *mut FILE) -> wint_t {
10766 let mut buf = [0u8; 4];
10767 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c, core::ptr::null_mut());
10768 if n == !0usize || n == 0 { return WEOF; }
10769 if fwrite(buf.as_ptr() as *const c_void, 1, n, f) != n { return WEOF; }
10770 c as wint_t
10771}
10772
10773#[no_mangle]
10774pub unsafe extern "C" fn fputws(s: *const wchar_t, f: *mut FILE) -> c_int {
10775 let mut i = 0;
10776 while *s.add(i) != 0 {
10777 if fputwc(*s.add(i), f) == WEOF { return -1; }
10778 i += 1;
10779 }
10780 0
10781}
10782
10783#[no_mangle]
10784pub unsafe extern "C" fn ungetwc(c: wint_t, f: *mut FILE) -> wint_t {
10785 if c == WEOF { return WEOF; }
10786 let mut buf = [0u8; 4];
10787 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c as wchar_t, core::ptr::null_mut());
10788 if n == !0usize || n == 0 { return WEOF; }
10789 let mut i = n;
10790 while i > 0 {
10791 i -= 1;
10792 if ungetc(buf[i] as c_int, f) == -1 { return WEOF; }
10793 }
10794 c
10795}
10796
10797#[no_mangle]
10798pub unsafe extern "C" fn getwchar() -> wint_t { fgetwc(stdin) }
10799
10800#[no_mangle]
10801pub unsafe extern "C" fn putwchar(c: wchar_t) -> wint_t { fputwc(c, stdout) }
10802
10803unsafe fn wfmt_write_str(dst: *mut wchar_t, pos: usize, cap: usize, s: *const u8, len: usize) -> usize {
10808 let mut i = 0;
10809 while i < len {
10810 if pos + i < cap { *dst.add(pos + i) = *s.add(i) as wchar_t; }
10811 i += 1;
10812 }
10813 pos + len
10814}
10815
10816#[no_mangle]
10817pub unsafe extern "C" fn vswprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, mut args: VaList) -> c_int {
10818 if n == 0 { return -1; }
10819 let cap = n - 1;
10820 let mut pos = 0usize;
10821 let mut fmt_narrow = [0u8; 256];
10823 let mut flen = 0usize;
10824 loop {
10825 let ch = *fmt.add(flen) as u32;
10826 if ch == 0 || flen >= 255 { break; }
10827 fmt_narrow[flen] = if ch < 128 { ch as u8 } else { b'?' };
10828 flen += 1;
10829 }
10830 fmt_narrow[flen] = 0;
10831 let mut fi = 0usize;
10832 macro_rules! wc {
10833 ($c:expr) => { if pos < cap { *s.add(pos) = $c as wchar_t; } pos += 1; }
10834 }
10835 loop {
10836 let c = fmt_narrow[fi];
10837 if c == 0 { break; }
10838 if c != b'%' { wc!(c); fi += 1; continue; }
10839 fi += 1;
10840 let mut flags: u8 = 0;
10841 loop {
10842 match fmt_narrow[fi] {
10843 b'-' => { flags |= FLAG_MINUS; fi += 1; }
10844 b'+' => { flags |= FLAG_PLUS; fi += 1; }
10845 b' ' => { flags |= FLAG_SPACE; fi += 1; }
10846 b'0' => { flags |= FLAG_ZERO; fi += 1; }
10847 b'#' => { flags |= FLAG_HASH; fi += 1; }
10848 _ => break,
10849 }
10850 }
10851 let mut width: usize = 0;
10852 if fmt_narrow[fi] == b'*' {
10853 let w = args.next_arg::<c_int>();
10854 if w < 0 { flags |= FLAG_MINUS; width = (-w) as usize; } else { width = w as usize; }
10855 fi += 1;
10856 } else {
10857 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10858 width = width * 10 + (fmt_narrow[fi] - b'0') as usize; fi += 1;
10859 }
10860 }
10861 let mut precision: i32 = -1;
10862 if fmt_narrow[fi] == b'.' {
10863 fi += 1;
10864 if fmt_narrow[fi] == b'*' {
10865 let p = args.next_arg::<c_int>();
10866 precision = if p < 0 { -1 } else { p }; fi += 1;
10867 } else {
10868 precision = 0;
10869 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10870 precision = precision * 10 + (fmt_narrow[fi] - b'0') as i32; fi += 1;
10871 }
10872 }
10873 }
10874 let len_mod = fmt_narrow[fi];
10875 if len_mod == b'h' || len_mod == b'l' || len_mod == b'j' || len_mod == b'z' || len_mod == b't' || len_mod == b'L' {
10876 fi += 1;
10877 let spec = fmt_narrow[fi];
10878 if (len_mod == b'h' && spec == b'h') || (len_mod == b'l' && spec == b'l') {
10879 fi += 1;
10880 let spec2 = fmt_narrow[fi];
10881 match (len_mod, spec, spec2) {
10882 (b'h', b'h', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut u8) = pos as u8; } }
10883 (b'l', b'l', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut c_longlong) = pos as c_longlong; } }
10884 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
10885 let val = args.next_arg::<c_longlong>();
10886 let neg = val < 0;
10887 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10888 let b = format_u64(abs);
10889 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10890 let mut fbuf = [0u8; 32];
10891 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10892 for k in 0..len { wc!(fbuf[k]); }
10893 }
10894 (b'l', b'l', b'u') => {
10895 let val = args.next_arg::<c_ulonglong>();
10896 let b = format_u64(val as u64);
10897 let mut fbuf = [0u8; 32];
10898 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10899 for k in 0..len { wc!(fbuf[k]); }
10900 }
10901 (b'l', b'l', b'x') => {
10902 let val = args.next_arg::<c_ulonglong>();
10903 let b = format_hex(val as u64, false);
10904 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10905 let mut fbuf = [0u8; 32];
10906 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10907 for k in 0..len { wc!(fbuf[k]); }
10908 }
10909 (b'l', b'l', b'X') => {
10910 let val = args.next_arg::<c_ulonglong>();
10911 let b = format_hex(val as u64, true);
10912 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10913 let mut fbuf = [0u8; 32];
10914 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10915 for k in 0..len { wc!(fbuf[k]); }
10916 }
10917 (b'l', b'l', b'o') => {
10918 let val = args.next_arg::<c_ulonglong>();
10919 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
10920 let mut fbuf = [0u8; 32];
10921 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10922 for k in 0..len { wc!(fbuf[k]); }
10923 }
10924 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); wc!(spec2); }
10925 }
10926 } else {
10927 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
10928 match (lm, spec) {
10929 (b'h', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut u16) = pos as u16; } }
10930 (b'l', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut c_long) = pos as c_long; } }
10931 (b'z', b'n') | (b't', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut usize) = pos; } }
10932 (b'j', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut c_ulonglong) = pos as c_ulonglong; } }
10933 (b'l', b'd') | (b'l', b'i') => {
10934 let val = args.next_arg::<c_long>();
10935 let neg = val < 0;
10936 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10937 let b = format_u64(abs);
10938 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10939 let mut fbuf = [0u8; 32];
10940 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10941 for k in 0..len { wc!(fbuf[k]); }
10942 }
10943 (b'l', b'u') => {
10944 let val = args.next_arg::<c_ulong>();
10945 let b = format_u64(val as u64);
10946 let mut fbuf = [0u8; 32];
10947 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10948 for k in 0..len { wc!(fbuf[k]); }
10949 }
10950 (b'l', b'x') => {
10951 let val = args.next_arg::<c_ulong>();
10952 let b = format_hex(val as u64, false);
10953 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10954 let mut fbuf = [0u8; 32];
10955 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10956 for k in 0..len { wc!(fbuf[k]); }
10957 }
10958 (b'l', b'X') => {
10959 let val = args.next_arg::<c_ulong>();
10960 let b = format_hex(val as u64, true);
10961 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10962 let mut fbuf = [0u8; 32];
10963 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10964 for k in 0..len { wc!(fbuf[k]); }
10965 }
10966 (b'l', b'o') => {
10967 let val = args.next_arg::<c_ulong>();
10968 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
10969 let mut fbuf = [0u8; 32];
10970 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10971 for k in 0..len { wc!(fbuf[k]); }
10972 }
10973 (b'l', b'c') => {
10974 let ch = args.next_arg::<wint_t>();
10975 wc!(ch);
10976 }
10977 (b'l', b's') => {
10978 let ws_arg = args.next_arg::<*const wchar_t>();
10979 if ws_arg.is_null() {
10980 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
10981 if flags & FLAG_MINUS != 0 {
10982 for k in 0..slen { wc!(b"(null)"[k]); }
10983 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10984 } else {
10985 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10986 for k in 0..slen { wc!(b"(null)"[k]); }
10987 }
10988 } else {
10989 let mut wlen = 0usize;
10990 loop {
10991 let ch = *ws_arg.add(wlen);
10992 if ch == 0 { break; }
10993 if precision >= 0 && wlen >= precision as usize { break; }
10994 wlen += 1;
10995 }
10996 if flags & FLAG_MINUS != 0 {
10997 for k in 0..wlen { wc!(*ws_arg.add(k)); }
10998 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
10999 } else {
11000 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
11001 for k in 0..wlen { wc!(*ws_arg.add(k)); }
11002 }
11003 }
11004 }
11005 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
11006 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
11007 let val = args.next_arg::<f64>();
11008 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
11009 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
11010 let mut fbuf = [0u8; 4224];
11011 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
11012 let mut wbuf = [0u8; 4224];
11013 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
11014 for k in 0..wlen { wc!(wbuf[k]); }
11015 }
11016 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
11017 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
11018 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
11019 let val = {
11020 let lo: u64 = args.next_arg::<u64>();
11021 let hi: u64 = args.next_arg::<u64>();
11022 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
11023 f128::from_bits(combined) as f64
11024 };
11025 #[cfg(target_arch = "x86_64")]
11026 let val = args.next_arg::<f64>();
11027 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
11028 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
11029 let mut fbuf = [0u8; 4224];
11030 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
11031 let mut wbuf = [0u8; 4224];
11032 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
11033 for k in 0..wlen { wc!(wbuf[k]); }
11034 }
11035 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); }
11036 }
11037 }
11038 } else {
11039 let spec = fmt_narrow[fi];
11040 match spec {
11041 b'd' | b'i' => {
11042 let d = args.next_arg::<c_int>();
11043 let neg = d < 0;
11044 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
11045 let b = format_u64(abs);
11046 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
11047 let mut fbuf = [0u8; 32];
11048 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
11049 for k in 0..len { wc!(fbuf[k]); }
11050 }
11051 b'u' => {
11052 let u = args.next_arg::<c_uint>();
11053 let b = format_u64(u as u64);
11054 let mut fbuf = [0u8; 32];
11055 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
11056 for k in 0..len { wc!(fbuf[k]); }
11057 }
11058 b'x' => {
11059 let x = args.next_arg::<c_uint>();
11060 let b = format_hex(x as u64, false);
11061 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
11062 let mut fbuf = [0u8; 32];
11063 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
11064 for k in 0..len { wc!(fbuf[k]); }
11065 }
11066 b'X' => {
11067 let x = args.next_arg::<c_uint>();
11068 let b = format_hex(x as u64, true);
11069 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
11070 let mut fbuf = [0u8; 32];
11071 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
11072 for k in 0..len { wc!(fbuf[k]); }
11073 }
11074 b'o' => {
11075 let o = args.next_arg::<c_uint>();
11076 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
11077 let mut fbuf = [0u8; 32];
11078 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
11079 for k in 0..len { wc!(fbuf[k]); }
11080 }
11081 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
11082 let val = args.next_arg::<f64>();
11083 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
11084 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
11085 let mut fbuf = [0u8; 4224];
11086 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
11087 let mut wbuf = [0u8; 4224];
11088 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
11089 for k in 0..wlen { wc!(wbuf[k]); }
11090 }
11091 b'c' => {
11092 let ch = args.next_arg::<c_int>();
11093 wc!(ch as u8);
11094 }
11095 b's' => {
11096 let p = args.next_arg::<*const c_char>();
11097 if p.is_null() {
11098 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
11099 if flags & FLAG_MINUS != 0 {
11100 for k in 0..slen { wc!(b"(null)"[k]); }
11101 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
11102 } else {
11103 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
11104 for k in 0..slen { wc!(b"(null)"[k]); }
11105 }
11106 } else {
11107 let mut wbuf_local = [0i32; 256];
11108 let mut wcount = 0usize;
11109 let mut byte_pos = 0usize;
11110 let pbytes = p as *const u8;
11111 loop {
11112 if precision >= 0 && wcount >= precision as usize { break; }
11113 if wcount >= 256 { break; }
11114 let mut wc_val: c_int = 0;
11115 let consumed = mbrtowc(&mut wc_val as *mut c_int, p.add(byte_pos) as *const c_char, 256, core::ptr::null_mut());
11116 if consumed == !0usize || consumed == !1usize {
11117 wbuf_local[wcount] = *pbytes.add(byte_pos) as c_int;
11118 byte_pos += 1;
11119 wcount += 1;
11120 } else if consumed == 0 {
11121 break;
11122 } else {
11123 wbuf_local[wcount] = wc_val;
11124 byte_pos += consumed;
11125 wcount += 1;
11126 }
11127 }
11128 if flags & FLAG_MINUS != 0 {
11129 for k in 0..wcount { wc!(wbuf_local[k]); }
11130 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
11131 } else {
11132 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
11133 for k in 0..wcount { wc!(wbuf_local[k]); }
11134 }
11135 }
11136 }
11137 b'p' => {
11138 wc!(b'0'); wc!(b'x');
11139 let p = args.next_arg::<*const c_void>();
11140 let b = format_hex(p as u64, false);
11141 for k in 0..b.1 { wc!(b.0[k]); }
11142 }
11143 b'n' => {
11144 let p = args.next_arg::<*mut c_void>();
11145 if !p.is_null() { *(p as *mut c_int) = pos as c_int; }
11146 }
11147 b'%' => { wc!(b'%'); }
11148 _ => { wc!(b'%'); wc!(spec); }
11149 }
11150 }
11151 fi += 1;
11152 }
11153 let null_pos = if pos < cap { pos } else { cap };
11154 *s.add(null_pos) = 0;
11155 if pos > cap { -1 } else { pos as c_int }
11156}
11157
11158#[no_mangle]
11159pub unsafe extern "C" fn swprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, args: ...) -> c_int {
11160 vswprintf(s, n, fmt, args)
11161}
11162
11163#[no_mangle]
11164pub unsafe extern "C" fn vfwprintf(f: *mut FILE, fmt: *const wchar_t, args: VaList) -> c_int {
11165 let mut buf = [0i32; 4096];
11166 let r = vswprintf(buf.as_mut_ptr(), 4096, fmt, args);
11167 if r < 0 { return r; }
11168 let mut i = 0;
11169 while i < r as usize {
11170 let mut mb = [0u8; 4];
11171 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, buf[i], core::ptr::null_mut());
11172 if n == !0usize { return -1; }
11173 if fwrite(mb.as_ptr() as *const c_void, 1, n, f) != n { return -1; }
11174 i += 1;
11175 }
11176 r
11177}
11178
11179#[no_mangle]
11180pub unsafe extern "C" fn fwprintf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
11181 vfwprintf(f, fmt, args)
11182}
11183
11184unsafe fn wcsfmt_to_mbs(dst: *mut u8, dst_len: usize, src: *const wchar_t) {
11190 let mut i = 0usize;
11191 loop {
11192 let ch = *src.add(i) as u32;
11193 if ch == 0 || i >= dst_len - 1 { break; }
11194 *dst.add(i) = if ch < 128 { ch as u8 } else { b'?' };
11195 i += 1;
11196 }
11197 *dst.add(i) = 0;
11198}
11199
11200#[no_mangle]
11201pub unsafe extern "C" fn vswscanf(s: *const wchar_t, fmt: *const wchar_t, mut args: VaList) -> c_int {
11202 let mut mbs_buf = [0u8; 4096];
11203 let mut i = 0usize;
11204 let mut mb_pos = 0usize;
11205 loop {
11206 let wc = *s.add(i) as c_int;
11207 if wc == 0 { break; }
11208 let mut mb = [0u8; 4];
11209 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, wc, core::ptr::null_mut());
11210 if n == !0usize || n == 0 { break; }
11211 if mb_pos + n >= mbs_buf.len() { break; }
11212 let mut k = 0usize;
11213 while k < n { mbs_buf[mb_pos + k] = mb[k]; k += 1; }
11214 mb_pos += n;
11215 i += 1;
11216 }
11217 mbs_buf[mb_pos] = 0;
11218 let mut mbs_fmt = [0u8; 4096];
11219 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
11220 do_vsscanf(mbs_buf.as_ptr(), mb_pos, mbs_fmt.as_ptr() as *const c_char, &mut args, core::ptr::null_mut())
11221}
11222
11223#[no_mangle]
11224pub unsafe extern "C" fn swscanf(s: *const wchar_t, fmt: *const wchar_t, args: ...) -> c_int {
11225 vswscanf(s, fmt, args)
11226}
11227
11228#[no_mangle]
11229pub unsafe extern "C" fn vfwscanf(f: *mut FILE, fmt: *const wchar_t, mut args: VaList) -> c_int {
11230 let start_pos = ftello(f);
11231 if start_pos < 0 { return -1; }
11232 let mut buf = [0u8; 4096];
11233 let mut n = 0usize;
11234 loop {
11235 if n >= buf.len() - 1 { break; }
11236 let c = fgetc(f);
11237 if c == -1 { break; }
11238 buf[n] = c as u8;
11239 n += 1;
11240 }
11241 buf[n] = 0;
11242 let mut mbs_fmt = [0u8; 4096];
11243 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
11244 let mut consumed = 0usize;
11245 let hit_eof = (*f)._eof != 0;
11246 let result = do_vsscanf(buf.as_ptr(), n, mbs_fmt.as_ptr() as *const c_char, &mut args, &mut consumed);
11247 let _ = fseeko(f, start_pos + consumed as i64, SEEK_SET);
11248 if hit_eof && consumed == n {
11249 (*f)._eof = 1;
11250 }
11251 result
11252}
11253
11254#[no_mangle]
11255pub unsafe extern "C" fn fwscanf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
11256 vfwscanf(f, fmt, args)
11257}
11258
11259#[no_mangle]
11260pub unsafe extern "C" fn vwscanf(fmt: *const wchar_t, args: VaList) -> c_int {
11261 vfwscanf(stdin, fmt, args)
11262}
11263
11264#[no_mangle]
11265pub unsafe extern "C" fn wscanf(fmt: *const wchar_t, args: ...) -> c_int {
11266 vfwscanf(stdin, fmt, args)
11267}
11268
11269const LEAPOCH: i64 = 946684800 + 86400 * (31 + 29);
11274const DAYS_PER_400Y: i64 = 365 * 400 + 97;
11275const DAYS_PER_100Y: i64 = 365 * 100 + 24;
11276const DAYS_PER_4Y: i64 = 365 * 4 + 1;
11277
11278const SECS_THROUGH_MONTH: [i32; 12] = [
11279 0, 31*86400, 59*86400, 90*86400, 120*86400, 151*86400,
11280 181*86400, 212*86400, 243*86400, 273*86400, 304*86400, 334*86400,
11281];
11282
11283const DAYS_IN_MONTH: [i32; 12] = [31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29];
11284
11285unsafe fn year_to_secs(year: i64, is_leap: &mut bool) -> i64 {
11286 if year - 2 <= 136 {
11287 let y = year as i32;
11288 let mut leaps = (y - 68) >> 2;
11289 if (y - 68) & 3 == 0 { leaps -= 1; *is_leap = true; } else { *is_leap = false; }
11290 return 31536000 * (y as i64 - 70) + 86400 * leaps as i64;
11291 }
11292 let mut cycles = ((year - 100) / 400) as i32;
11293 let mut rem = ((year - 100) % 400) as i32;
11294 if rem < 0 { cycles -= 1; rem += 400; }
11295 let (centuries, leaps);
11296 if rem == 0 { *is_leap = true; centuries = 0; leaps = 0; }
11297 else {
11298 let c;
11299 if rem >= 200 { if rem >= 300 { c = 3; rem -= 300; } else { c = 2; rem -= 200; } }
11300 else { if rem >= 100 { c = 1; rem -= 100; } else { c = 0; } }
11301 centuries = c;
11302 if rem == 0 { *is_leap = false; leaps = 0; }
11303 else { leaps = rem / 4; rem %= 4; *is_leap = rem == 0; }
11304 }
11305 let total_leaps = leaps + 97 * cycles + 24 * centuries - (*is_leap as i32);
11306 (year - 100) * 31536000 + total_leaps as i64 * 86400 + 946684800 + 86400
11307}
11308
11309fn month_to_secs(month: i32, is_leap: bool) -> i32 {
11310 let mut t = SECS_THROUGH_MONTH[month as usize];
11311 if is_leap && month >= 2 { t += 86400; }
11312 t
11313}
11314
11315unsafe fn secs_to_tm(t: i64, tm: &mut tm) -> bool {
11316 if t < (i32::MIN as i64) * 31622400 || t > (i32::MAX as i64) * 31622400 { return false; }
11317 let secs = t - LEAPOCH;
11318 let mut days = secs / 86400;
11319 let mut remsecs = (secs % 86400) as i32;
11320 if remsecs < 0 { remsecs += 86400; days -= 1; }
11321 let mut wday = ((3 + days) % 7) as i32;
11322 if wday < 0 { wday += 7; }
11323 let mut qc_cycles = (days / DAYS_PER_400Y) as i32;
11324 let mut remdays = (days % DAYS_PER_400Y) as i32;
11325 if remdays < 0 { remdays += DAYS_PER_400Y as i32; qc_cycles -= 1; }
11326 let mut c_cycles = remdays / DAYS_PER_100Y as i32;
11327 if c_cycles == 4 { c_cycles -= 1; }
11328 remdays -= c_cycles * DAYS_PER_100Y as i32;
11329 let mut q_cycles = remdays / DAYS_PER_4Y as i32;
11330 if q_cycles == 25 { q_cycles -= 1; }
11331 remdays -= q_cycles * DAYS_PER_4Y as i32;
11332 let mut remyears = remdays / 365;
11333 if remyears == 4 { remyears -= 1; }
11334 remdays -= remyears * 365;
11335 let leap = remyears == 0 && (q_cycles != 0 || c_cycles == 0);
11336 let mut yday = remdays + 31 + 28 + leap as i32;
11337 if yday >= 365 + leap as i32 { yday -= 365 + leap as i32; }
11338 let years = remyears as i64 + 4 * q_cycles as i64 + 100 * c_cycles as i64 + 400 * qc_cycles as i64;
11339 let mut months = 0i32;
11340 let mut rd = remdays;
11341 for m in 0..12 {
11342 if DAYS_IN_MONTH[m] <= rd { rd -= DAYS_IN_MONTH[m]; } else { months = m as i32; break; }
11343 }
11344 let mut adj_years = years;
11345 if months >= 10 { months -= 12; adj_years += 1; }
11346 if adj_years + 100 > i32::MAX as i64 || adj_years + 100 < i32::MIN as i64 { return false; }
11347 tm.tm_year = (adj_years + 100) as c_int;
11348 tm.tm_mon = months + 2;
11349 tm.tm_mday = rd + 1;
11350 tm.tm_wday = wday;
11351 tm.tm_yday = yday;
11352 tm.tm_hour = remsecs / 3600;
11353 tm.tm_min = remsecs / 60 % 60;
11354 tm.tm_sec = remsecs % 60;
11355 true
11356}
11357
11358unsafe fn tm_to_secs(tm: *const tm) -> i64 {
11359 let mut year = (*tm).tm_year as i64;
11360 let mut month = (*tm).tm_mon;
11361 if month >= 12 || month < 0 {
11362 let adj = month / 12;
11363 month %= 12;
11364 if month < 0 { month += 12; }
11365 year += adj as i64;
11366 }
11367 let mut is_leap = false;
11368 let mut t = year_to_secs(year, &mut is_leap);
11369 t += month_to_secs(month, is_leap) as i64;
11370 t += 86400 * ((*tm).tm_mday - 1) as i64;
11371 t += 3600 * (*tm).tm_hour as i64;
11372 t += 60 * (*tm).tm_min as i64;
11373 t += (*tm).tm_sec as i64;
11374 t
11375}
11376
11377static mut TM_BUF: tm = tm {
11378 tm_sec: 0, tm_min: 0, tm_hour: 0, tm_mday: 0, tm_mon: 0,
11379 tm_year: 0, tm_wday: 0, tm_yday: 0, tm_isdst: 0,
11380 tm_gmtoff: 0, tm_zone: core::ptr::null(),
11381};
11382
11383static mut UTC_STR: [c_char; 4] = [b'U' as c_char, b'T' as c_char, b'C' as c_char, 0];
11384
11385const CLOCK_PROCESS_CPUTIME_ID: c_int = 2;
11386
11387#[no_mangle]
11392pub unsafe extern "C" fn time(t: *mut TimeT) -> TimeT {
11393 let mut ts: timespec = core::mem::zeroed();
11394 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
11395 if !t.is_null() { *t = ts.tv_sec; }
11396 ts.tv_sec
11397}
11398
11399#[no_mangle]
11400pub unsafe extern "C" fn difftime(t1: TimeT, t0: TimeT) -> f64 {
11401 (t1 as i64 - t0 as i64) as f64
11402}
11403
11404#[no_mangle]
11405pub unsafe extern "C" fn clock() -> ClockT {
11406 let mut ts: timespec = core::mem::zeroed();
11407 let _ = sys_clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &mut ts);
11408 ts.tv_sec * 1000000 + ts.tv_nsec / 1000
11409}
11410
11411#[no_mangle]
11412pub unsafe extern "C" fn gmtime(t: *const TimeT) -> *mut tm {
11413 gmtime_r(t, &raw mut TM_BUF)
11414}
11415
11416#[no_mangle]
11417pub unsafe extern "C" fn gmtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm {
11418 if !secs_to_tm(*t as i64, &mut *tm) { ERRNO!() = EOVERFLOW; return core::ptr::null_mut(); }
11419 (*tm).tm_isdst = 0;
11420 (*tm).tm_gmtoff = 0;
11421 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11422 tm
11423}
11424
11425#[no_mangle]
11426pub unsafe extern "C" fn localtime(t: *const TimeT) -> *mut tm { gmtime(t) }
11427
11428#[no_mangle]
11429pub unsafe extern "C" fn localtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm { gmtime_r(t, tm) }
11430
11431#[no_mangle]
11432pub unsafe extern "C" fn mktime(tm: *mut tm) -> TimeT {
11433 let t = tm_to_secs(tm as *const tm);
11434 if !secs_to_tm(t, &mut *tm) { ERRNO!() = EOVERFLOW; return -1; }
11435 (*tm).tm_isdst = 0;
11436 (*tm).tm_gmtoff = 0;
11437 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11438 t as TimeT
11439}
11440
11441#[no_mangle]
11442pub unsafe extern "C" fn timegm(tm: *mut tm) -> TimeT {
11443 let t = tm_to_secs(tm as *const tm);
11444 if !secs_to_tm(t, &mut *tm) { ERRNO!() = EOVERFLOW; return -1; }
11445 (*tm).tm_isdst = 0;
11446 (*tm).tm_gmtoff = 0;
11447 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11448 t as TimeT
11449}
11450
11451static mut ASCTIME_BUF: [c_char; 26] = [0; 26];
11452
11453const DAY_NAMES: [&[u8]; 7] = [b"Sun\0", b"Mon\0", b"Tue\0", b"Wed\0", b"Thu\0", b"Fri\0", b"Sat\0"];
11454const MON_NAMES: [&[u8]; 12] = [b"Jan\0", b"Feb\0", b"Mar\0", b"Apr\0", b"May\0", b"Jun\0", b"Jul\0", b"Aug\0", b"Sep\0", b"Oct\0", b"Nov\0", b"Dec\0"];
11455
11456#[no_mangle]
11457pub unsafe extern "C" fn asctime(tm: *const tm) -> *mut c_char {
11458 asctime_r(tm, core::ptr::addr_of_mut!(ASCTIME_BUF).cast::<c_char>())
11459}
11460
11461#[no_mangle]
11462pub unsafe extern "C" fn asctime_r(tm: *const tm, buf: *mut c_char) -> *mut c_char {
11463 let wday = if (*tm).tm_wday >= 0 && (*tm).tm_wday < 7 { (*tm).tm_wday as usize } else { 0 };
11464 let mon = if (*tm).tm_mon >= 0 && (*tm).tm_mon < 12 { (*tm).tm_mon as usize } else { 0 };
11465 let dn = DAY_NAMES[wday];
11466 let mn = MON_NAMES[mon];
11467 let mut p = 0;
11468 for k in 0..3 { *buf.add(p) = *dn.as_ptr().add(k) as c_char; p += 1; }
11469 *buf.add(p) = b' ' as c_char; p += 1;
11470 for k in 0..3 { *buf.add(p) = *mn.as_ptr().add(k) as c_char; p += 1; }
11471 *buf.add(p) = b' ' as c_char; p += 1;
11472 let v = (*tm).tm_mday;
11473 *buf.add(p) = (b'0' + (v / 10) as u8) as c_char; p += 1;
11474 *buf.add(p) = (b'0' + (v % 10) as u8) as c_char; p += 1;
11475 *buf.add(p) = b' ' as c_char; p += 1;
11476 let hh = (*tm).tm_hour;
11477 *buf.add(p) = (b'0' + (hh / 10) as u8) as c_char; p += 1;
11478 *buf.add(p) = (b'0' + (hh % 10) as u8) as c_char; p += 1;
11479 *buf.add(p) = b':' as c_char; p += 1;
11480 let mm = (*tm).tm_min;
11481 *buf.add(p) = (b'0' + (mm / 10) as u8) as c_char; p += 1;
11482 *buf.add(p) = (b'0' + (mm % 10) as u8) as c_char; p += 1;
11483 *buf.add(p) = b':' as c_char; p += 1;
11484 let ss = (*tm).tm_sec;
11485 *buf.add(p) = (b'0' + (ss / 10) as u8) as c_char; p += 1;
11486 *buf.add(p) = (b'0' + (ss % 10) as u8) as c_char; p += 1;
11487 *buf.add(p) = b' ' as c_char; p += 1;
11488 let yr = (*tm).tm_year + 1900;
11489 let mut tmp = [0u8; 4];
11490 let mut v2 = yr;
11491 for k in (0..4).rev() { tmp[k] = b'0' + (v2 % 10) as u8; v2 /= 10; }
11492 for k in 0..4 { *buf.add(p) = tmp[k] as c_char; p += 1; }
11493 *buf.add(p) = b'\n' as c_char; p += 1;
11494 *buf.add(p) = 0;
11495 buf
11496}
11497
11498#[no_mangle]
11499pub unsafe extern "C" fn ctime(t: *const TimeT) -> *mut c_char { asctime(gmtime(t)) }
11500
11501#[no_mangle]
11502pub unsafe extern "C" fn ctime_r(t: *const TimeT, buf: *mut c_char) -> *mut c_char {
11503 let mut tmp: tm = core::mem::zeroed();
11504 gmtime_r(t, &mut tmp);
11505 asctime_r(&tmp, buf)
11506}
11507
11508unsafe fn sys_clock_getres(clockid: c_int, ts: *mut timespec) -> i64 {
11513 <Arch as Syscalls>::syscall2(SYS_CLOCK_GETRES, clockid as i64, ts as i64)
11514}
11515
11516unsafe fn sys_clock_settime(clockid: c_int, ts: *const timespec) -> i64 {
11517 <Arch as Syscalls>::syscall2(SYS_CLOCK_SETTIME, clockid as i64, ts as i64)
11518}
11519
11520unsafe fn sys_clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> i64 {
11521 <Arch as Syscalls>::syscall4(SYS_CLOCK_NANOSLEEP, clockid as i64, flags as i64, req as i64, rem as i64)
11522}
11523
11524#[no_mangle]
11525pub unsafe extern "C" fn clock_getres(clockid: c_int, ts: *mut timespec) -> c_int {
11526 let r = sys_clock_getres(clockid, ts);
11527 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
11528}
11529
11530#[no_mangle]
11531pub unsafe extern "C" fn clock_settime(clockid: c_int, ts: *const timespec) -> c_int {
11532 let r = sys_clock_settime(clockid, ts);
11533 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
11534}
11535
11536#[no_mangle]
11537pub unsafe extern "C" fn clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> c_int {
11538 let r = sys_clock_nanosleep(clockid, flags, req, rem);
11539 if r < 0 {
11540 let e = (-r) as c_int;
11541 if clockid == 3 && e == 95 { return 22; }
11544 e
11545 } else {
11546 0
11547 }
11548}
11549
11550#[no_mangle]
11551pub unsafe extern "C" fn gettimeofday(tv: *mut timeval, _tz: *mut c_void) -> c_int {
11552 if tv.is_null() { return 0; }
11553 let mut ts: timespec = core::mem::zeroed();
11554 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
11555 (*tv).tv_sec = ts.tv_sec;
11556 (*tv).tv_usec = ts.tv_nsec / 1000;
11557 0
11558}
11559
11560fn is_leap_year(y: i32) -> bool {
11565 let yr = if y > i32::MAX - 1900 { y - 2000 } else { y + 1900 };
11566 yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0)
11567}
11568
11569fn week_num(tm: &tm) -> i32 {
11570 let mut val = (tm.tm_yday + 7 - ((tm.tm_wday + 6) % 7)) / 7;
11571 if (tm.tm_wday + 371 - tm.tm_yday - 2).rem_euclid(7) <= 2 { val += 1; }
11572 if val == 0 {
11573 val = 52;
11574 let dec31 = (tm.tm_wday + 7 - tm.tm_yday - 1).rem_euclid(7);
11575 if dec31 == 4 || (dec31 == 5 && is_leap_year(tm.tm_year % 400 - 1)) { val += 1; }
11576 } else if val == 53 {
11577 let jan1 = (tm.tm_wday + 371 - tm.tm_yday).rem_euclid(7);
11578 if jan1 != 4 && (jan1 != 3 || !is_leap_year(tm.tm_year)) { val = 1; }
11579 }
11580 val
11581}
11582
11583const ABDAY_1: c_int = 0x20000;
11585const DAY_1: c_int = 0x20007;
11586const ABMON_1: c_int = 0x2000E;
11587const MON_1: c_int = 0x2001A;
11588const AM_STR_LI: c_int = 0x20026;
11589const PM_STR_LI: c_int = 0x20027;
11590const D_T_FMT: c_int = 0x20028;
11591const D_FMT: c_int = 0x20029;
11592const T_FMT: c_int = 0x2002A;
11593const T_FMT_AMPM: c_int = 0x2002B;
11594
11595unsafe fn num_fmt(buf: &mut [u8; 100], val: i64, pad: u8, width: usize) -> (*const u8, usize) {
11598 let negative = val < 0;
11599 let mut v = if negative { -val as u64 } else { val as u64 };
11600 let mut tmp = [0u8; 24];
11601 let mut pos = 24usize;
11602 if v == 0 { pos -= 1; tmp[pos] = b'0'; }
11603 while v > 0 { pos -= 1; tmp[pos] = b'0' + (v % 10) as u8; v /= 10; }
11604 let digits = 24 - pos;
11605 let sign_chars = if negative { 1 } else { 0 };
11606 let needed = sign_chars + digits;
11607 let fill = if width > needed { width - needed } else { 0 };
11608 let total = fill + needed;
11609 let mut p = 0usize;
11610 match pad {
11611 b'-' => { }
11612 b'_' => {
11613 for _ in 0..fill { buf[p] = b' '; p += 1; }
11614 if negative { buf[p] = b'-'; p += 1; }
11615 }
11616 _ => {
11617 if negative { buf[p] = b'-'; p += 1; }
11618 for _ in 0..fill { buf[p] = b'0'; p += 1; }
11619 }
11620 }
11621 for i in 0..digits { buf[p] = tmp[pos + i]; p += 1; }
11622 (buf.as_ptr(), total)
11623}
11624
11625unsafe fn str_to_buf(buf: &mut [u8; 100], s: *const c_char) -> (*const u8, usize) {
11627 let mut k = 0usize;
11628 while *s.add(k) != 0 {
11629 buf[k] = *s.add(k) as u8;
11630 k += 1;
11631 }
11632 (buf.as_ptr(), k)
11633}
11634
11635unsafe fn __strftime_fmt_1(buf: &mut [u8; 100], f: u8, tm: *const tm, pad: u8) -> (*const u8, usize) {
11638 let mut val: i64;
11639 let mut width: usize = 2;
11640 let mut def_pad: u8 = b'0';
11641 let fmt: *const c_char;
11642
11643 match f {
11644 b'a' => {
11645 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
11646 let p = nl_langinfo(ABDAY_1 + (*tm).tm_wday);
11647 return str_to_buf(buf, p);
11648 }
11649 b'A' => {
11650 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
11651 let p = nl_langinfo(DAY_1 + (*tm).tm_wday);
11652 return str_to_buf(buf, p);
11653 }
11654 b'h' | b'b' => {
11655 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
11656 let p = nl_langinfo(ABMON_1 + (*tm).tm_mon);
11657 return str_to_buf(buf, p);
11658 }
11659 b'B' => {
11660 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
11661 let p = nl_langinfo(MON_1 + (*tm).tm_mon);
11662 return str_to_buf(buf, p);
11663 }
11664 b'c' => {
11665 let p = nl_langinfo(D_T_FMT);
11666 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11667 return (buf.as_ptr(), l);
11668 }
11669 b'C' => {
11670 val = (1900i64 + (*tm).tm_year as i64) / 100;
11671 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11672 }
11673 b'e' => { def_pad = b'_'; }
11674 b'd' => {
11675 val = (*tm).tm_mday as i64;
11676 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11677 }
11678 b'D' => {
11679 fmt = b"%m/%d/%y\0".as_ptr() as *const c_char;
11680 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11681 return (buf.as_ptr(), l);
11682 }
11683 b'F' => {
11684 fmt = b"%Y-%m-%d\0".as_ptr() as *const c_char;
11685 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11686 return (buf.as_ptr(), l);
11687 }
11688 b'g' | b'G' => {
11689 val = (*tm).tm_year as i64 + 1900;
11690 if (*tm).tm_yday < 3 && week_num(&*tm) != 1 { val -= 1; }
11691 else if (*tm).tm_yday > 360 && week_num(&*tm) == 1 { val += 1; }
11692 if f == b'g' { val %= 100; }
11693 else { width = 4; }
11694 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11695 }
11696 b'H' => {
11697 val = (*tm).tm_hour as i64;
11698 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11699 }
11700 b'I' => {
11701 val = (*tm).tm_hour as i64;
11702 if val == 0 { val = 12; }
11703 else if val > 12 { val -= 12; }
11704 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11705 }
11706 b'j' => {
11707 val = (*tm).tm_yday as i64 + 1;
11708 width = 3;
11709 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11710 }
11711 b'm' => {
11712 val = (*tm).tm_mon as i64 + 1;
11713 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11714 }
11715 b'M' => {
11716 val = (*tm).tm_min as i64;
11717 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11718 }
11719 b'n' => { buf[0] = b'\n'; return (buf.as_ptr(), 1); }
11720 b'p' => {
11721 let p = if (*tm).tm_hour >= 12 { nl_langinfo(PM_STR_LI) } else { nl_langinfo(AM_STR_LI) };
11722 return str_to_buf(buf, p);
11723 }
11724 b'r' => {
11725 let p = nl_langinfo(T_FMT_AMPM);
11726 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11727 return (buf.as_ptr(), l);
11728 }
11729 b'R' => {
11730 fmt = b"%H:%M\0".as_ptr() as *const c_char;
11731 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11732 return (buf.as_ptr(), l);
11733 }
11734 b's' => {
11735 val = tm_to_secs(tm) - (*tm).tm_gmtoff as i64;
11736 width = 1;
11737 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11738 }
11739 b'S' => {
11740 val = (*tm).tm_sec as i64;
11741 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11742 }
11743 b't' => { buf[0] = b'\t'; return (buf.as_ptr(), 1); }
11744 b'T' => {
11745 fmt = b"%H:%M:%S\0".as_ptr() as *const c_char;
11746 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11747 return (buf.as_ptr(), l);
11748 }
11749 b'u' => {
11750 val = if (*tm).tm_wday != 0 { (*tm).tm_wday as i64 } else { 7 };
11751 width = 1;
11752 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11753 }
11754 b'U' => {
11755 val = ((*tm).tm_yday as u64 + 7 - (*tm).tm_wday as u64) as i64 / 7;
11756 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11757 }
11758 b'W' => {
11759 val = ((*tm).tm_yday as u64 + 7 - ((*tm).tm_wday as u64 + 6) % 7) as i64 / 7;
11760 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11761 }
11762 b'V' => {
11763 val = week_num(&*tm) as i64;
11764 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11765 }
11766 b'w' => {
11767 val = (*tm).tm_wday as i64;
11768 width = 1;
11769 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11770 }
11771 b'x' => {
11772 let p = nl_langinfo(D_FMT);
11773 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11774 return (buf.as_ptr(), l);
11775 }
11776 b'X' => {
11777 let p = nl_langinfo(T_FMT);
11778 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11779 return (buf.as_ptr(), l);
11780 }
11781 b'y' => {
11782 val = (1900i64 + (*tm).tm_year as i64) % 100;
11783 if val < 0 { val = -val; }
11784 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11785 }
11786 b'Y' => {
11787 val = (*tm).tm_year as i64 + 1900;
11788 if val >= 10000 {
11789 let mut tmp = [0u8; 100];
11790 let (_, k) = num_fmt(&mut tmp, val, b'-', 1);
11791 buf[0] = b'+';
11792 for i in 0..k { buf[1 + i] = tmp[i]; }
11793 return (buf.as_ptr(), 1 + k);
11794 }
11795 width = 4;
11796 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11797 }
11798 b'z' => {
11799 if (*tm).tm_isdst < 0 { return (b"\0".as_ptr(), 0); }
11800 let gmtoff = (*tm).tm_gmtoff as i64;
11801 let sign = if gmtoff >= 0 { b'+' } else { b'-' };
11802 let off = if gmtoff < 0 { -gmtoff } else { gmtoff };
11803 let hh = (off / 3600) as i32;
11804 let mm = ((off % 3600) / 60) as i32;
11805 buf[0] = sign;
11806 buf[1] = b'0' + (hh / 10) as u8;
11807 buf[2] = b'0' + (hh % 10) as u8;
11808 buf[3] = b'0' + (mm / 10) as u8;
11809 buf[4] = b'0' + (mm % 10) as u8;
11810 return (buf.as_ptr(), 5);
11811 }
11812 b'Z' => {
11813 if (*tm).tm_isdst < 0 || (*tm).tm_zone.is_null() { return (b"\0".as_ptr(), 0); }
11814 return str_to_buf(buf, (*tm).tm_zone);
11815 }
11816 b'%' => { buf[0] = b'%'; return (buf.as_ptr(), 1); }
11817 _ => { return (core::ptr::null(), 0); }
11818 }
11819 val = (*tm).tm_mday as i64;
11821 num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width)
11822}
11823
11824unsafe fn __strftime_l(s: *mut c_char, n: usize, f: *const c_char, tm: *const tm) -> usize {
11825 let mut l: usize = 0;
11826 let mut fi: usize = 0;
11827 while l < n {
11828 let ch = *f.add(fi) as u8;
11829 if ch == 0 {
11830 *s.add(l) = 0;
11831 return l;
11832 }
11833 if ch != b'%' {
11834 *s.add(l) = ch as c_char;
11835 l += 1;
11836 fi += 1;
11837 continue;
11838 }
11839 fi += 1;
11840 let mut pad: u8 = 0;
11842 let fc = *f.add(fi) as u8;
11843 if fc == b'-' || fc == b'_' || fc == b'0' { pad = fc; fi += 1; }
11844 let plus = *f.add(fi) as u8 == b'+';
11845 if plus { fi += 1; }
11846 let mut width: usize = 0;
11848 let mut p_idx = fi;
11849 {
11850 let fc2 = *f.add(fi) as u8;
11851 if fc2 >= b'0' && fc2 <= b'9' {
11852 let mut w: usize = 0;
11853 while { let c = *f.add(p_idx) as u8; c >= b'0' && c <= b'9' } {
11854 w = w * 10 + (*f.add(p_idx) as usize - b'0' as usize);
11855 p_idx += 1;
11856 }
11857 width = w;
11858 }
11859 }
11860 let spec_ch = *f.add(p_idx) as u8;
11861 if spec_ch == b'C' || spec_ch == b'F' || spec_ch == b'G' || spec_ch == b'Y' {
11862 if width == 0 && p_idx != fi { width = 1; }
11863 } else {
11864 width = 0;
11865 }
11866 fi = p_idx;
11867 let fc3 = *f.add(fi) as u8;
11869 if fc3 == b'E' || fc3 == b'O' { fi += 1; }
11870 let fch = *f.add(fi) as u8;
11871 let mut buf = [0u8; 100];
11873 let (t, k) = __strftime_fmt_1(&mut buf, fch, tm, pad);
11874 if t.is_null() { break; }
11875 let mut k = k;
11876 let mut t = t;
11877 if width != 0 {
11878 if *t == b'+' || *t == b'-' { t = t.add(1); k -= 1; }
11880 while k > 0 && *t == b'0' && k > 1 && *t.add(1) >= b'0' && *t.add(1) <= b'9' {
11881 t = t.add(1); k -= 1;
11882 }
11883 if width < k { width = k; }
11884 let mut d: usize = 0;
11885 while d < k && *t.add(d) >= b'0' && *t.add(d) <= b'9' { d += 1; }
11886 if (*tm).tm_year < -1900 {
11887 if l < n { *s.add(l) = b'-' as c_char; }
11888 l += 1;
11889 width -= 1;
11890 } else if plus && d + (width - k) >= (if spec_ch == b'C' { 3 } else { 5 }) {
11891 if l < n { *s.add(l) = b'+' as c_char; }
11892 l += 1;
11893 width -= 1;
11894 }
11895 while width > k && l < n {
11896 *s.add(l) = b'0' as c_char;
11897 l += 1;
11898 width -= 1;
11899 }
11900 }
11901 let copy = if k > n - l { n - l } else { k };
11902 core::ptr::copy_nonoverlapping(t, s.add(l) as *mut u8, copy);
11903 l += copy;
11904 fi += 1;
11905 }
11906 if n > 0 {
11907 if l == n { l = n - 1; }
11908 *s.add(l) = 0;
11909 }
11910 0
11911}
11912
11913#[no_mangle]
11914pub unsafe extern "C" fn strftime(s: *mut c_char, maxsize: usize, fmt: *const c_char, tm: *const tm) -> usize {
11915 __strftime_l(s, maxsize, fmt, tm)
11916}
11917
11918unsafe fn match_prefix(s: *const u8, prefix: &[u8]) -> bool {
11923 for i in 0..prefix.len() {
11924 if *s.add(i) == 0 || *s.add(i) != prefix[i] { return false; }
11925 }
11926 true
11927}
11928
11929unsafe fn match_ci_prefix(s: *const u8, prefix: &[u8]) -> bool {
11930 for i in 0..prefix.len() {
11931 let c = *s.add(i);
11932 if c == 0 { return false; }
11933 if c.to_ascii_lowercase() != prefix[i].to_ascii_lowercase() { return false; }
11934 }
11935 true
11936}
11937
11938unsafe fn parse_int(p: *const u8, max_digits: usize) -> (i32, *const u8) {
11939 let mut val = 0i32;
11940 let mut np = p;
11941 let mut count = 0;
11942 while *np >= b'0' && *np <= b'9' && count < max_digits {
11943 val = val * 10 + (*np - b'0') as i32;
11944 np = np.add(1);
11945 count += 1;
11946 }
11947 if count == 0 { (0, p) } else { (val, np) }
11948}
11949
11950unsafe fn parse_range(p: *const u8, min: i32, max: i32) -> (i32, *const u8) {
11951 let (val, np) = parse_int(p, 4);
11952 if np == p || val < min || val > max { (0, p) } else { (val, np) }
11953}
11954
11955fn is_ascii_space(c: u8) -> bool {
11956 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == 0x0c || c == 0x0b
11957}
11958
11959#[no_mangle]
11960pub unsafe extern "C" fn strptime(s: *const c_char, fmt: *const c_char, tm: *mut tm) -> *mut c_char {
11961 let mut p = s as *const u8;
11962 let mut f = fmt as *const u8;
11963 let mut want_century = 0i32;
11964 let mut century = 0i32;
11965 let mut relyear = 0i32;
11966 while *f != 0 {
11967 if *f != b'%' {
11968 if is_ascii_space(*f) {
11969 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
11970 } else {
11971 if *p != *f { return core::ptr::null_mut(); }
11972 p = p.add(1);
11973 }
11974 f = f.add(1);
11975 continue;
11976 }
11977 f = f.add(1);
11978 if *f == b'+' { f = f.add(1); }
11979 while *f >= b'0' && *f <= b'9' { f = f.add(1); }
11980 if *f == b'E' || *f == b'O' { f = f.add(1); }
11981 match *f {
11982 b'a' | b'A' => {
11983 let mut found = false;
11984 for i in 0..7 {
11985 let names: [&[u8]; 7] = [b"Sunday", b"Monday", b"Tuesday", b"Wednesday", b"Thursday", b"Friday", b"Saturday"];
11986 let snames: [&[u8]; 7] = [b"Sun", b"Mon", b"Tue", b"Wed", b"Thu", b"Fri", b"Sat"];
11987 if match_prefix(p, names[i]) { (*tm).tm_wday = i as c_int; p = p.add(names[i].len()); found = true; break; }
11988 if match_prefix(p, snames[i]) { (*tm).tm_wday = i as c_int; p = p.add(snames[i].len()); found = true; break; }
11989 }
11990 if !found { return core::ptr::null_mut(); }
11991 }
11992 b'b' | b'B' | b'h' => {
11993 let mut found = false;
11994 for i in 0..12 {
11995 let names: [&[u8]; 12] = [b"January", b"February", b"March", b"April", b"May", b"June", b"July", b"August", b"September", b"October", b"November", b"December"];
11996 let snames: [&[u8]; 12] = [b"Jan", b"Feb", b"Mar", b"Apr", b"May", b"Jun", b"Jul", b"Aug", b"Sep", b"Oct", b"Nov", b"Dec"];
11997 if match_prefix(p, names[i]) { (*tm).tm_mon = i as c_int; p = p.add(names[i].len()); found = true; break; }
11998 if match_prefix(p, snames[i]) { (*tm).tm_mon = i as c_int; p = p.add(snames[i].len()); found = true; break; }
11999 }
12000 if !found { return core::ptr::null_mut(); }
12001 }
12002 b'C' => {
12003 let (v, np) = parse_int(p, 2);
12004 if np == p { return core::ptr::null_mut(); }
12005 century = v;
12006 want_century |= 2;
12007 p = np;
12008 }
12009 b'd' | b'e' => {
12010 let (v, np) = parse_range(p, 1, 31);
12011 if np == p { return core::ptr::null_mut(); }
12012 (*tm).tm_mday = v;
12013 p = np;
12014 }
12015 b'D' => {
12016 let r = strptime(p as *const c_char, b"%m/%d/%y\0".as_ptr() as *const c_char, tm);
12017 if r.is_null() { return core::ptr::null_mut(); }
12018 p = r as *const u8;
12019 }
12020 b'F' => {
12021 let (yv, ynp) = parse_int(p, 4);
12022 if ynp == p { return core::ptr::null_mut(); }
12023 (*tm).tm_year = yv - 1900;
12024 p = ynp;
12025 if *p != b'-' { return core::ptr::null_mut(); }
12026 p = p.add(1);
12027 let (mv, mnp) = parse_range(p, 1, 12);
12028 if mnp == p { return core::ptr::null_mut(); }
12029 (*tm).tm_mon = mv - 1;
12030 p = mnp;
12031 if *p != b'-' { return core::ptr::null_mut(); }
12032 p = p.add(1);
12033 let (dv, dnp) = parse_range(p, 1, 31);
12034 if dnp == p { return core::ptr::null_mut(); }
12035 (*tm).tm_mday = dv;
12036 p = dnp;
12037 }
12038 b'H' | b'I' => {
12039 let (v, np) = parse_range(p, 0, 23);
12040 if np == p { return core::ptr::null_mut(); }
12041 (*tm).tm_hour = v;
12042 p = np;
12043 }
12044 b'j' => {
12045 let (v, np) = parse_range(p, 1, 366);
12046 if np == p { return core::ptr::null_mut(); }
12047 (*tm).tm_yday = v - 1;
12048 p = np;
12049 }
12050 b'm' => {
12051 let (v, np) = parse_range(p, 1, 12);
12052 if np == p { return core::ptr::null_mut(); }
12053 (*tm).tm_mon = v - 1;
12054 p = np;
12055 }
12056 b'M' => {
12057 let (v, np) = parse_range(p, 0, 59);
12058 if np == p { return core::ptr::null_mut(); }
12059 (*tm).tm_min = v;
12060 p = np;
12061 }
12062 b'n' | b't' => {
12063 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
12064 }
12065 b'p' => {
12066 if match_ci_prefix(p, b"AM") {
12067 if (*tm).tm_hour == 12 { (*tm).tm_hour = 0; }
12068 p = p.add(2);
12069 } else if match_ci_prefix(p, b"PM") {
12070 if (*tm).tm_hour < 12 { (*tm).tm_hour += 12; }
12071 p = p.add(2);
12072 } else { return core::ptr::null_mut(); }
12073 }
12074 b'r' => {
12075 let r = strptime(p as *const c_char, b"%I:%M:%S %p\0".as_ptr() as *const c_char, tm);
12076 if r.is_null() { return core::ptr::null_mut(); }
12077 p = r as *const u8;
12078 }
12079 b'R' => {
12080 let r = strptime(p as *const c_char, b"%H:%M\0".as_ptr() as *const c_char, tm);
12081 if r.is_null() { return core::ptr::null_mut(); }
12082 p = r as *const u8;
12083 }
12084 b's' => {
12085 let neg = if *p == b'-' { p = p.add(1); true } else { false };
12086 if *p < b'0' || *p > b'9' { return core::ptr::null_mut(); }
12087 let mut val = 0i64;
12088 while *p >= b'0' && *p <= b'9' {
12089 val = val * 10 + (*p - b'0') as i64;
12090 p = p.add(1);
12091 }
12092 if neg { val = -val; }
12093 secs_to_tm(val, &mut *tm);
12094 }
12095 b'S' => {
12096 let (v, np) = parse_range(p, 0, 60);
12097 if np == p { return core::ptr::null_mut(); }
12098 (*tm).tm_sec = v;
12099 p = np;
12100 }
12101 b'T' => {
12102 let r = strptime(p as *const c_char, b"%H:%M:%S\0".as_ptr() as *const c_char, tm);
12103 if r.is_null() { return core::ptr::null_mut(); }
12104 p = r as *const u8;
12105 }
12106 b'U' | b'W' => {
12107 let (_, np) = parse_range(p, 0, 53);
12108 if np == p { return core::ptr::null_mut(); }
12109 p = np;
12110 }
12111 b'V' => {
12112 let (_, np) = parse_range(p, 1, 53);
12113 if np == p { return core::ptr::null_mut(); }
12114 p = np;
12115 }
12116 b'w' => {
12117 let (v, np) = parse_range(p, 0, 6);
12118 if np == p { return core::ptr::null_mut(); }
12119 (*tm).tm_wday = v;
12120 p = np;
12121 }
12122 b'y' => {
12123 let (v, np) = parse_int(p, 2);
12124 if np == p { return core::ptr::null_mut(); }
12125 relyear = v;
12126 want_century |= 1;
12127 p = np;
12128 }
12129 b'Y' => {
12130 let neg = if *p == b'-' { p = p.add(1); true } else { false };
12131 let (v, np) = parse_int(p, 4);
12132 if np == p { return core::ptr::null_mut(); }
12133 (*tm).tm_year = if neg { -(v + 1900) } else { v - 1900 };
12134 want_century = 0;
12135 p = np;
12136 }
12137 b'z' => {
12138 if *p != b'+' && *p != b'-' { return core::ptr::null_mut(); }
12139 let neg = *p == b'-';
12140 p = p.add(1);
12141 let mut off = 0i64;
12142 let mut digits = 0;
12143 while digits < 4 && *p >= b'0' && *p <= b'9' {
12144 off = off * 10 + (*p - b'0') as i64;
12145 p = p.add(1);
12146 digits += 1;
12147 }
12148 if digits == 0 { return core::ptr::null_mut(); }
12149 let (hh, mm) = if digits <= 2 { (off, 0i64) } else { (off / 100, off % 100) };
12150 (*tm).tm_gmtoff = (hh * 3600 + mm * 60) * if neg { -1 } else { 1 };
12151 }
12152 b'%' => {
12153 if *p != b'%' { return core::ptr::null_mut(); }
12154 p = p.add(1);
12155 }
12156 _ => { return core::ptr::null_mut(); }
12157 }
12158 f = f.add(1);
12159 }
12160 if want_century != 0 {
12161 (*tm).tm_year = relyear;
12162 if want_century & 2 != 0 { (*tm).tm_year += century * 100 - 1900; }
12163 else if (*tm).tm_year <= 68 { (*tm).tm_year += 100; }
12164 }
12165 p as *mut c_char
12166}
12167
12168#[no_mangle]
12173pub static mut daylight: c_int = 0;
12174#[no_mangle]
12175pub static mut timezone: c_long = 0;
12176#[no_mangle]
12177pub static mut tzname: [*mut c_char; 2] = [b"UTC\0".as_ptr() as *mut c_char, b"UTC\0".as_ptr() as *mut c_char];
12178
12179#[no_mangle]
12180pub unsafe extern "C" fn tzset() {
12181 daylight = 0;
12182 timezone = 0;
12183}
12184
12185#[no_mangle]
12190pub unsafe extern "C" fn system(cmd: *const c_char) -> c_int {
12191 if cmd.is_null() {
12192 let pid = sys_fork();
12194 if pid == 0 {
12195 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
12196 let dash_c = b"-c\0".as_ptr() as *const c_char;
12197 let exit0 = b"exit 0\0".as_ptr() as *const c_char;
12198 let argv = [b"sh\0".as_ptr() as *const c_char, dash_c, exit0, core::ptr::null()];
12199 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
12200 _exit(127);
12201 }
12202 if pid < 0 { return -1; }
12203 let mut status: c_int = 0;
12204 loop {
12205 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
12206 if r >= 0 { return status; }
12207 if r != -4 { return -1; } }
12209 }
12210
12211 let sa_ignore = KSigAction {
12212 sa_handler: SIG_IGN,
12213 sa_flags: SA_RESTORER,
12214 sa_restorer: sig_restorer as *const () as usize,
12215 sa_mask: [0],
12216 };
12217 let mut oldint: KSigAction = core::mem::zeroed();
12218 let mut oldquit: KSigAction = core::mem::zeroed();
12219
12220 sys_rt_sigaction(SIGINT, &sa_ignore, &mut oldint, 8);
12221 sys_rt_sigaction(SIGQUIT, &sa_ignore, &mut oldquit, 8);
12222
12223 let mut block_set: SigSetT = 0;
12224 block_set |= 1u64 << (SIGCHLD - 1);
12225 let mut oldmask: SigSetT = 0;
12226 sys_rt_sigprocmask(SIG_BLOCK, &block_set, &mut oldmask, 8);
12227
12228 let pid = sys_fork();
12229
12230 if pid == 0 {
12231 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
12232 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
12233 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
12234
12235 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
12236 let argv = [
12237 b"sh\0".as_ptr() as *const c_char,
12238 b"-c\0".as_ptr() as *const c_char,
12239 cmd,
12240 core::ptr::null(),
12241 ];
12242 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
12243 _exit(127);
12244 }
12245
12246 let mut status: c_int = -1;
12247 if pid > 0 {
12248 loop {
12249 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
12250 if r >= 0 { break; }
12251 if r != -4 { break; } }
12253 }
12254
12255 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
12256 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
12257 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
12258
12259 status
12260}
12261
12262const EPERM_VAL: c_int = 1;
12267const ENOENT_VAL: c_int = 2;
12268const ESRCH_VAL: c_int = 3;
12269const EINTR_VAL: c_int = 4;
12270const EIO_VAL: c_int = 5;
12271const ENXIO_VAL: c_int = 6;
12272const E2BIG_VAL: c_int = 7;
12273const ENOEXEC_VAL: c_int = 8;
12274const EBADF_VAL: c_int = 9;
12275const ECHILD_VAL: c_int = 10;
12276const EAGAIN_VAL: c_int = 11;
12277const ENOMEM_VAL: c_int = 12;
12278const EACCES_VAL: c_int = 13;
12279const EFAULT_VAL: c_int = 14;
12280const ENOTBLK_VAL: c_int = 15;
12281const EBUSY_VAL: c_int = 16;
12282const EEXIST_VAL: c_int = 17;
12283const EXDEV_VAL: c_int = 18;
12284const ENODEV_VAL: c_int = 19;
12285const ENOTDIR_VAL: c_int = 20;
12286const EISDIR_VAL: c_int = 21;
12287const EINVAL_VAL: c_int = 22;
12288const ENFILE_VAL: c_int = 23;
12289const EMFILE_VAL: c_int = 24;
12290const ENOTTY_VAL: c_int = 25;
12291const ETXTBSY_VAL: c_int = 26;
12292const EFBIG_VAL: c_int = 27;
12293const ENOSPC_VAL: c_int = 28;
12294const ESPIPE_VAL: c_int = 29;
12295const EROFS_VAL: c_int = 30;
12296const EMLINK_VAL: c_int = 31;
12297const EPIPE_VAL: c_int = 32;
12298const EDOM_VAL: c_int = 33;
12299const ERANGE_VAL: c_int = 34;
12300const EDEADLK_VAL: c_int = 35;
12301const ENAMETOOLONG_VAL: c_int = 36;
12302const ENOLCK_VAL: c_int = 37;
12303const ENOSYS_VAL: c_int = 38;
12304const ENOTEMPTY_VAL: c_int = 39;
12305const ELOOP_VAL: c_int = 40;
12306const EWOULDBLOCK_VAL: c_int = 11;
12307const ENOMSG_VAL: c_int = 42;
12308const EIDRM_VAL: c_int = 43;
12309const ECHRNG_VAL: c_int = 44;
12310const EL2NSYNC_VAL: c_int = 45;
12311const EL3HLT_VAL: c_int = 46;
12312const EL3RST_VAL: c_int = 47;
12313const ELNRNG_VAL: c_int = 48;
12314const EUNATCH_VAL: c_int = 49;
12315const ENOCSI_VAL: c_int = 50;
12316const EL2HLT_VAL: c_int = 51;
12317const EBADE_VAL: c_int = 52;
12318const EBADR_VAL: c_int = 53;
12319const EXFULL_VAL: c_int = 54;
12320const ENOANO_VAL: c_int = 55;
12321const EBADRQC_VAL: c_int = 56;
12322const EBADSLT_VAL: c_int = 57;
12323const EBFONT_VAL: c_int = 59;
12324const ENOSTR_VAL: c_int = 60;
12325const ENODATA_VAL: c_int = 61;
12326const ETIME_VAL: c_int = 62;
12327const ENOSR_VAL: c_int = 63;
12328const ENONET_VAL: c_int = 64;
12329const ENOPKG_VAL: c_int = 65;
12330const EREMOTE_VAL: c_int = 66;
12331const ENOLINK_VAL: c_int = 67;
12332const EADV_VAL: c_int = 68;
12333const ESRMNT_VAL: c_int = 69;
12334const ECOMM_VAL: c_int = 70;
12335const EPROTO_VAL: c_int = 71;
12336const EMULTIHOP_VAL: c_int = 72;
12337const EDOTDOT_VAL: c_int = 73;
12338const EBADMSG_VAL: c_int = 74;
12339const EOVERFLOW_VAL: c_int = 75;
12340const ENOTUNIQ_VAL: c_int = 76;
12341const EBADFD_VAL: c_int = 77;
12342const EREMCHG_VAL: c_int = 78;
12343const ELIBACC_VAL: c_int = 79;
12344const ELIBBAD_VAL: c_int = 80;
12345const ELIBSCN_VAL: c_int = 81;
12346const ELIBMAX_VAL: c_int = 82;
12347const ELIBEXEC_VAL: c_int = 83;
12348const EILSEQ_VAL: c_int = 84;
12349const ERESTART_VAL: c_int = 85;
12350const ESTRPIPE_VAL: c_int = 86;
12351const EUSERS_VAL: c_int = 87;
12352const ENOTSOCK_VAL: c_int = 88;
12353const EDESTADDRREQ_VAL: c_int = 89;
12354const EMSGSIZE_VAL: c_int = 90;
12355const EPROTOTYPE_VAL: c_int = 91;
12356const ENOPROTOOPT_VAL: c_int = 92;
12357const EPROTONOSUPPORT_VAL: c_int = 93;
12358const ESOCKTNOSUPPORT_VAL: c_int = 94;
12359const EOPNOTSUPP_VAL: c_int = 95;
12360const ENOTSUP_VAL: c_int = 95;
12361const EPFNOSUPPORT_VAL: c_int = 96;
12362const EAFNOSUPPORT_VAL: c_int = 97;
12363const EADDRINUSE_VAL: c_int = 98;
12364const EADDRNOTAVAIL_VAL: c_int = 99;
12365const ENETDOWN_VAL: c_int = 100;
12366const ENETUNREACH_VAL: c_int = 101;
12367const ENETRESET_VAL: c_int = 102;
12368const ECONNABORTED_VAL: c_int = 103;
12369const ECONNRESET_VAL: c_int = 104;
12370const ENOBUFS_VAL: c_int = 105;
12371const EISCONN_VAL: c_int = 106;
12372const ENOTCONN_VAL: c_int = 107;
12373const ESHUTDOWN_VAL: c_int = 108;
12374const ETOOMANYREFS_VAL: c_int = 109;
12375const ETIMEDOUT_VAL: c_int = 110;
12376const ECONNREFUSED_VAL: c_int = 111;
12377const EHOSTDOWN_VAL: c_int = 112;
12378const EHOSTUNREACH_VAL: c_int = 113;
12379const EALREADY_VAL: c_int = 114;
12380const EINPROGRESS_VAL: c_int = 115;
12381const ESTALE_VAL: c_int = 116;
12382const EUCLEAN_VAL: c_int = 117;
12383const ENOTNAM_VAL: c_int = 118;
12384const ENAVAIL_VAL: c_int = 119;
12385const EISNAM_VAL: c_int = 120;
12386const EREMOTEIO_VAL: c_int = 121;
12387const EDQUOT_VAL: c_int = 122;
12388const ENOMEDIUM_VAL: c_int = 123;
12389const EMEDIUMTYPE_VAL: c_int = 124;
12390const ECANCELED_VAL: c_int = 125;
12391const ENOKEY_VAL: c_int = 126;
12392const EKEYEXPIRED_VAL: c_int = 127;
12393const EKEYREVOKED_VAL: c_int = 128;
12394const EKEYREJECTED_VAL: c_int = 129;
12395const EOWNERDEAD_VAL: c_int = 130;
12396const ENOTRECOVERABLE_VAL: c_int = 131;
12397const ERFKILL_VAL: c_int = 132;
12398const EHWPOISON_VAL: c_int = 133;
12399
12400static ERR_STRS: [&[u8]; 134] = [
12402 b"Success\0", b"Operation not permitted\0", b"No such file or directory\0", b"No such process\0", b"Interrupted system call\0", b"Input/output error\0", b"No such device or address\0", b"Argument list too long\0", b"Exec format error\0", b"Bad file descriptor\0", b"No child processes\0", b"Resource temporarily unavailable\0", b"Cannot allocate memory\0", b"Permission denied\0", b"Bad address\0", b"Block device required\0", b"Device or resource busy\0", b"File exists\0", b"Invalid cross-device link\0", b"No such device\0", b"Not a directory\0", b"Is a directory\0", b"Invalid argument\0", b"Too many open files in system\0", b"Too many open files\0", b"Inappropriate ioctl for device\0", b"Text file busy\0", b"File too large\0", b"No space left on device\0", b"Illegal seek\0", b"Read-only file system\0", b"Too many links\0", b"Broken pipe\0", b"Numerical argument out of domain\0", b"Numerical result out of range\0", b"Resource deadlock avoided\0", b"File name too long\0", b"No locks available\0", b"Function not implemented\0", b"Directory not empty\0", b"Too many levels of symbolic links\0", b"Unknown error 41\0", b"No message of desired type\0", b"Identifier removed\0", b"Channel number out of range\0", b"Level 2 not synchronized\0", b"Level 3 halted\0", b"Level 3 reset\0", b"Link number out of range\0", b"Protocol driver not attached\0", b"No CSI structure available\0", b"Level 2 halted\0", b"Invalid exchange\0", b"Invalid request descriptor\0", b"Exchange full\0", b"No anode\0", b"Invalid request code\0", b"Invalid slot\0", b"Unknown error 58\0", b"Bad font file format\0", b"Device not a stream\0", b"No data available\0", b"Timer expired\0", b"Out of streams resources\0", b"Machine is not on the network\0", b"Package not installed\0", b"Object is remote\0", b"Link has been severed\0", b"Advertise error\0", b"Srmount error\0", b"Communication error on send\0", b"Protocol error\0", b"Multihop attempted\0", b"RFS specific error\0", b"Bad message\0", b"Value too large for defined data type\0", b"Name not unique on network\0", b"File descriptor in bad state\0", b"Remote address changed\0", b"Can not access a needed shared library\0", b"Accessing a corrupted shared library\0", b".lib section in a.out corrupted\0", b"Attempting to link in too many shared libraries\0", b"Cannot exec a shared library directly\0", b"Invalid or incomplete multibyte or wide character\0", b"Interrupted system call should be restarted\0", b"Streams pipe error\0", b"Too many users\0", b"Socket operation on non-socket\0", b"Destination address required\0", b"Message too long\0", b"Protocol wrong type for socket\0", b"Protocol not available\0", b"Protocol not supported\0", b"Socket type not supported\0", b"Operation not supported\0", b"Protocol family not supported\0", b"Address family not supported by protocol\0", b"Address already in use\0", b"Cannot assign requested address\0", b"Network is down\0", b"Network is unreachable\0", b"Network dropped connection on reset\0", b"Software caused connection abort\0", b"Connection reset by peer\0", b"No buffer space available\0", b"Transport endpoint is already connected\0", b"Transport endpoint is not connected\0", b"Cannot send after transport endpoint shutdown\0", b"Too many references: cannot splice\0", b"Connection timed out\0", b"Connection refused\0", b"Host is down\0", b"No route to host\0", b"Operation already in progress\0", b"Operation now in progress\0", b"Stale file handle\0", b"Structure needs cleaning\0", b"Not a XENIX named type file\0", b"No XENIX semaphores available\0", b"Is a named type file\0", b"Remote I/O error\0", b"Quota exceeded\0", b"No medium found\0", b"Wrong medium type\0", b"Operation canceled\0", b"Required key not available\0", b"Key has expired\0", b"Key has been revoked\0", b"Key was rejected by service\0", b"Owner died\0", b"State not recoverable\0", b"Operation not possible due to RF-kill\0", b"Memory page has hardware error\0", ];
12537
12538#[no_mangle]
12539pub unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char {
12540 if errnum < 0 || errnum as usize >= ERR_STRS.len() {
12541 static mut UNKNOWN_BUF: [c_char; 32] = [0; 32];
12543 let prefix = b"Unknown error \0";
12544 let mut i = 0;
12545 while prefix[i] != 0 {
12546 UNKNOWN_BUF[i] = prefix[i] as c_char;
12547 i += 1;
12548 }
12549 let (buf, len) = format_u64(errnum as u64);
12550 for j in 0..len {
12551 UNKNOWN_BUF[i] = buf[20 - len + j] as c_char;
12552 i += 1;
12553 }
12554 UNKNOWN_BUF[i] = 0;
12555 return core::ptr::addr_of_mut!(UNKNOWN_BUF).cast::<c_char>();
12556 }
12557 ERR_STRS[errnum as usize].as_ptr() as *mut c_char
12558}
12559
12560#[no_mangle]
12561pub unsafe extern "C" fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: usize) -> c_int {
12562 let s = strerror(errnum);
12563 let slen = strlen(s as *const c_char);
12564 if slen >= buflen {
12565 if buflen > 0 {
12566 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, buflen - 1);
12567 *buf.add(buflen - 1) = 0;
12568 }
12569 return 34; }
12571 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, slen + 1);
12572 0
12573}
12574
12575#[no_mangle]
12577pub static mut environ: *mut *mut c_char = core::ptr::null_mut();
12578
12579unsafe fn sync_environ() {
12581 environ = __environ;
12582}
12583
12584#[inline]
12589unsafe fn sys_dup(oldfd: i32) -> i64 {
12590 <Arch as Syscalls>::syscall1(SYS_DUP, oldfd as i64)
12591}
12592
12593#[inline]unsafe fn sys_dup2(oldfd: i32, newfd: i32) -> i64 {
12594 sys_dup3(oldfd, newfd, 0)
12596}
12597
12598#[inline]
12599unsafe fn sys_access(path: *const u8, mode: i32) -> i64 {
12600 <Arch as Syscalls>::syscall4(SYS_FACCESSAT, AT_FDCWD as i64, path as i64, mode as i64, 0)
12601}
12602
12603#[inline]unsafe fn sys_unlink(path: *const u8) -> i64 {
12604 sys_unlinkat(AT_FDCWD, path, 0)
12605}
12606
12607#[inline]unsafe fn sys_rmdir(path: *const u8) -> i64 {
12608 sys_unlinkat(AT_FDCWD, path, 512) }
12610
12611#[inline]
12612unsafe fn sys_chdir(path: *const u8) -> i64 {
12613 <Arch as Syscalls>::syscall1(SYS_CHDIR, path as i64)
12614}
12615
12616#[inline]
12617unsafe fn sys_getcwd(buf: *mut u8, size: usize) -> i64 {
12618 <Arch as Syscalls>::syscall2(SYS_GETCWD, buf as i64, size as i64)
12619}
12620
12621#[inline]
12622unsafe fn sys_sethostname(name: *const u8, len: usize) -> i64 {
12623 <Arch as Syscalls>::syscall2(SYS_SETHOSTNAME, name as i64, len as i64)
12624}
12625
12626#[inline]
12627unsafe fn sys_gethostname(buf: *mut u8, len: usize) -> i64 {
12628 #[repr(C)]
12629 struct UtsName {
12630 sysname: [u8; 65],
12631 nodename: [u8; 65],
12632 release: [u8; 65],
12633 version: [u8; 65],
12634 machine: [u8; 65],
12635 domainname: [u8; 65],
12636 }
12637 let mut uts: UtsName = core::mem::zeroed();
12638 let result = <Arch as Syscalls>::syscall1(SYS_UNAME, &mut uts as *mut UtsName as i64);
12639 if result < 0 {
12640 return result;
12641 }
12642 let nlen = strlen(uts.nodename.as_ptr() as *const c_char);
12643 let copylen = if nlen < len { nlen } else { if len > 0 { len - 1 } else { 0 } };
12644 core::ptr::copy_nonoverlapping(uts.nodename.as_ptr(), buf, copylen);
12645 if len > 0 { *buf.add(copylen) = 0; }
12646 0
12647}
12648
12649unsafe fn sys_truncate(path: *const u8, length: i64) -> i64 {
12650 <Arch as Syscalls>::syscall2(SYS_TRUNCATE, path as i64, length as i64)
12651}
12652
12653unsafe fn sys_ftruncate(fd: i32, length: i64) -> i64 {
12654 <Arch as Syscalls>::syscall2(SYS_FTRUNCATE, fd as i64, length as i64)
12655}
12656
12657unsafe fn sys_nanosleep(req: *const timespec, rem: *mut timespec) -> i64 {
12658 <Arch as Syscalls>::syscall2(SYS_NANOSLEEP, req as i64, rem as i64)
12659}
12660
12661const ITIMER_REAL: i32 = 0;
12662
12663#[repr(C)]
12664struct itimerval {
12665 it_interval: timeval,
12666 it_value: timeval,
12667}
12668
12669unsafe fn sys_alarm(seconds: c_uint) -> i64 {
12670 let mut new: itimerval = core::mem::zeroed();
12671 new.it_value.tv_sec = seconds as c_long;
12672 let mut old: itimerval = core::mem::zeroed();
12673 let r = <Arch as Syscalls>::syscall3(
12674 SYS_SETITIMER,
12675 ITIMER_REAL as i64,
12676 &new as *const _ as i64,
12677 &mut old as *mut _ as i64,
12678 );
12679 if r < 0 {
12680 return r;
12681 }
12682 old.it_value.tv_sec as i64 + (old.it_value.tv_usec != 0) as i64
12683}
12684
12685unsafe fn sys_pause() -> i64 {
12686 #[cfg(target_arch = "x86_64")]
12687 { <Arch as Syscalls>::syscall0(SYS_PAUSE) }
12688 #[cfg(target_arch = "aarch64")]
12689 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12690 #[cfg(target_arch = "riscv64")]
12691 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12692}
12693
12694unsafe fn sys_fsync(fd: i32) -> i64 {
12695 <Arch as Syscalls>::syscall1(SYS_FSYNC, fd as i64)
12696}
12697
12698unsafe fn sys_fdatasync(fd: i32) -> i64 {
12699 <Arch as Syscalls>::syscall1(SYS_FDATASYNC, fd as i64)
12700}
12701
12702unsafe fn sys_sync() {
12703 let _ = <Arch as Syscalls>::syscall0(SYS_SYNC);
12704}
12705
12706unsafe fn sys_symlink(target: *const u8, linkpath: *const u8) -> i64 {
12707 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, AT_FDCWD as i64, linkpath as i64)
12708}
12709
12710unsafe fn sys_symlinkat(target: *const u8, newdirfd: i32, linkpath: *const u8) -> i64 {
12711 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, newdirfd as i64, linkpath as i64)
12712}
12713
12714unsafe fn sys_readlinkat(dirfd: i32, path: *const u8, buf: *mut u8, bufsiz: usize) -> i64 {
12715 <Arch as Syscalls>::syscall4(SYS_READLINKAT, dirfd as i64, path as i64, buf as i64, bufsiz as i64)
12716}
12717
12718unsafe fn sys_linkat(olddirfd: i32, oldpath: *const u8, newdirfd: i32, newpath: *const u8, flags: i32) -> i64 {
12719 <Arch as Syscalls>::syscall5(SYS_LINKAT, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)
12720}
12721
12722unsafe fn sys_fchmod(fd: i32, mode: u32) -> i64 {
12723 <Arch as Syscalls>::syscall2(SYS_FCHMOD, fd as i64, mode as i64)
12724}
12725
12726unsafe fn sys_fchmodat(dirfd: i32, path: *const u8, mode: u32, flags: i32) -> i64 {
12727 <Arch as Syscalls>::syscall4(SYS_FCHMODAT, dirfd as i64, path as i64, mode as i64, flags as i64)
12728}
12729
12730unsafe fn sys_umask(mask: u32) -> u32 {
12731 <Arch as Syscalls>::syscall1(SYS_UMASK, mask as i64) as u32
12732}
12733
12734unsafe fn sys_getgroups(size: i32, list: *mut c_uint) -> i64 {
12735 <Arch as Syscalls>::syscall2(SYS_GETGROUPS, size as i64, list as i64)
12736}
12737
12738unsafe fn sys_setuid(uid: c_uint) -> i64 {
12739 <Arch as Syscalls>::syscall1(SYS_SETUID, uid as i64)
12740}
12741
12742unsafe fn sys_setgid(gid: c_uint) -> i64 {
12743 <Arch as Syscalls>::syscall1(SYS_SETGID, gid as i64)
12744}
12745
12746unsafe fn sys_setsid() -> i64 {
12747 <Arch as Syscalls>::syscall0(SYS_SETSID)
12748}
12749
12750unsafe fn sys_setpgid(pid: c_int, pgid: c_int) -> i64 {
12751 <Arch as Syscalls>::syscall2(SYS_SETPGID, pid as i64, pgid as i64)
12752}
12753
12754unsafe fn sys_getpgid(pid: c_int) -> i64 {
12755 <Arch as Syscalls>::syscall1(SYS_GETPGID, pid as i64)
12756}
12757
12758unsafe fn sys_getsid(pid: c_int) -> i64 {
12759 <Arch as Syscalls>::syscall1(SYS_GETSID, pid as i64)
12760}
12761
12762unsafe fn sys_mkdirat(dirfd: i32, path: *const u8, mode: u32) -> i64 {
12763 <Arch as Syscalls>::syscall3(SYS_MKDIRAT, dirfd as i64, path as i64, mode as i64)
12764}
12765
12766#[no_mangle]
12769pub unsafe extern "C" fn pipe(fds: *mut c_int) -> c_int {
12770 let r = sys_pipe2(fds, 0);
12771 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12772 0
12773}
12774
12775#[no_mangle]
12776pub unsafe extern "C" fn pipe2(fds: *mut c_int, flags: c_int) -> c_int {
12777 let r = sys_pipe2(fds, flags);
12778 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12779 0
12780}
12781
12782#[no_mangle]
12783pub unsafe extern "C" fn dup(oldfd: c_int) -> c_int {
12784 let r = sys_dup(oldfd);
12785 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12786 r as c_int
12787}
12788
12789#[no_mangle]
12790pub unsafe extern "C" fn dup2(oldfd: c_int, newfd: c_int) -> c_int {
12791 if oldfd == newfd {
12792 let r = sys_fcntl(oldfd, 1 , 0);
12795 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12796 return newfd;
12797 }
12798 let r = sys_dup2(oldfd, newfd);
12799 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12800 r as c_int
12801}
12802
12803#[no_mangle]
12804pub unsafe extern "C" fn dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int {
12805 let r = sys_dup3(oldfd, newfd, flags);
12806 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12807 r as c_int
12808}
12809
12810#[no_mangle]
12811pub unsafe extern "C" fn fcntl(fd: c_int, cmd: c_int, mut args: ...) -> c_int {
12812 let no_arg = matches!(cmd, 1 | 3 | 9 | 11 | 1025 | 1032 | 1034 );
12817 let r = if no_arg {
12818 sys_fcntl(fd, cmd, 0)
12819 } else {
12820 let arg = args.next_arg::<c_long>();
12821 sys_fcntl(fd, cmd, arg)
12822 };
12823 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12824 r as c_int
12825}
12826
12827#[no_mangle]
12828pub unsafe extern "C" fn access(path: *const c_char, mode: c_int) -> c_int {
12829 let r = sys_access(path as *const u8, mode);
12830 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12831 0
12832}
12833
12834#[no_mangle]
12835pub unsafe extern "C" fn unlink(path: *const c_char) -> c_int {
12836 let r = sys_unlink(path as *const u8);
12837 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12838 0
12839}
12840
12841#[no_mangle]
12842pub unsafe extern "C" fn rmdir(path: *const c_char) -> c_int {
12843 let r = sys_rmdir(path as *const u8);
12844 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12845 0
12846}
12847
12848#[no_mangle]
12849pub unsafe extern "C" fn chdir(path: *const c_char) -> c_int {
12850 let r = sys_chdir(path as *const u8);
12851 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12852 0
12853}
12854
12855#[no_mangle]
12856pub unsafe extern "C" fn getcwd(buf: *mut c_char, size: usize) -> *mut c_char {
12857 if buf.is_null() {
12858 let alloc_size = if size == 0 { 256 } else { size };
12860 let p = malloc(alloc_size) as *mut c_char;
12861 if p.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
12862 let r = sys_getcwd(p as *mut u8, alloc_size);
12863 if r < 0 { free(p as *mut c_void); ERRNO!() = (-r) as c_int; return core::ptr::null_mut(); }
12864 if *p as u8 != b'/' {
12867 free(p as *mut c_void);
12868 ERRNO!() = 2;
12869 return core::ptr::null_mut();
12870 }
12871 return p;
12872 }
12873 if size == 0 { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
12874 let r = sys_getcwd(buf as *mut u8, size);
12875 if r < 0 { ERRNO!() = (-r) as c_int; return core::ptr::null_mut(); }
12876 if *buf as u8 != b'/' {
12877 ERRNO!() = 2;
12878 return core::ptr::null_mut();
12879 }
12880 buf
12881}
12882
12883#[no_mangle]
12884pub unsafe extern "C" fn gethostname(name: *mut c_char, len: usize) -> c_int {
12885 let r = sys_gethostname(name as *mut u8, len);
12886 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12887 0
12888}
12889
12890#[no_mangle]
12892pub extern "C" fn getpagesize() -> c_int {
12893 4096
12894}
12895
12896#[no_mangle]
12897pub unsafe extern "C" fn truncate(path: *const c_char, length: i64) -> c_int {
12898 let r = sys_truncate(path as *const u8, length);
12899 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12900 0
12901}
12902
12903#[no_mangle]
12904pub unsafe extern "C" fn ftruncate(fd: c_int, length: i64) -> c_int {
12905 let r = sys_ftruncate(fd, length);
12906 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12907 0
12908}
12909
12910#[no_mangle]
12911pub unsafe extern "C" fn nanosleep(req: *const timespec, rem: *mut timespec) -> c_int {
12912 pthread_testcancel();
12913 let r = sys_nanosleep(req, rem);
12914 pthread_testcancel();
12915 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12916 0
12917}
12918
12919#[no_mangle]
12920pub unsafe extern "C" fn sleep(seconds: c_uint) -> c_uint {
12921 let req = timespec { tv_sec: seconds as c_long, tv_nsec: 0 };
12922 let mut rem: timespec = core::mem::zeroed();
12923 pthread_testcancel();
12924 let r = sys_nanosleep(&req, &mut rem);
12925 pthread_testcancel();
12926 if r < 0 {
12927 let e = (-r) as c_int;
12928 if e == EINTR { return rem.tv_sec as c_uint; }
12929 }
12930 0
12931}
12932
12933#[no_mangle]
12934pub unsafe extern "C" fn usleep(usec: c_uint) -> c_int {
12935 let req = timespec { tv_sec: (usec / 1000000) as c_long, tv_nsec: ((usec % 1000000) * 1000) as c_long };
12936 pthread_testcancel();
12937 let r = sys_nanosleep(&req, core::ptr::null_mut());
12938 pthread_testcancel();
12939 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12940 0
12941}
12942
12943#[no_mangle]
12944pub unsafe extern "C" fn alarm(seconds: c_uint) -> c_uint {
12945 let r = sys_alarm(seconds);
12948 if r < 0 { 0 } else { r as c_uint }
12949}
12950
12951#[no_mangle]
12952pub unsafe extern "C" fn pause() -> c_int {
12953 pthread_testcancel();
12954 sys_pause();
12955 pthread_testcancel();
12956 ERRNO!() = EINTR;
12957 -1
12958}
12959
12960#[no_mangle]
12961pub unsafe extern "C" fn fsync(fd: c_int) -> c_int {
12962 let r = sys_fsync(fd);
12963 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12964 0
12965}
12966
12967#[no_mangle]
12968pub unsafe extern "C" fn fdatasync(fd: c_int) -> c_int {
12969 let r = sys_fdatasync(fd);
12970 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12971 0
12972}
12973
12974#[no_mangle]
12975pub unsafe extern "C" fn sync() {
12976 sys_sync();
12977}
12978
12979#[no_mangle]
12980pub unsafe extern "C" fn symlink(target: *const c_char, linkpath: *const c_char) -> c_int {
12981 let r = sys_symlinkat(target as *const u8, AT_FDCWD, linkpath as *const u8);
12982 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12983 0
12984}
12985
12986#[no_mangle]
12987pub unsafe extern "C" fn readlink(path: *const c_char, buf: *mut c_char, bufsiz: usize) -> isize {
12988 let r = sys_readlinkat(AT_FDCWD, path as *const u8, buf as *mut u8, bufsiz);
12989 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12990 r as isize
12991}
12992
12993#[no_mangle]
12994pub unsafe extern "C" fn link(oldpath: *const c_char, newpath: *const c_char) -> c_int {
12995 let r = sys_linkat(AT_FDCWD, oldpath as *const u8, AT_FDCWD, newpath as *const u8, 0);
12996 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12997 0
12998}
12999
13000#[no_mangle]
13001pub unsafe extern "C" fn chmod(path: *const c_char, mode: c_uint) -> c_int {
13002 let r = sys_fchmodat(AT_FDCWD, path as *const u8, mode, 0);
13003 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13004 0
13005}
13006
13007#[no_mangle]
13008pub unsafe extern "C" fn fchmod(fd: c_int, mode: c_uint) -> c_int {
13009 let r = sys_fchmod(fd, mode);
13010 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13011 0
13012}
13013
13014#[no_mangle]
13015pub unsafe extern "C" fn umask(mask: c_uint) -> c_uint {
13016 sys_umask(mask) as c_uint
13017}
13018
13019#[no_mangle]
13020pub unsafe extern "C" fn isatty(fd: c_int) -> c_int {
13021 let mut ws: winsize = core::mem::zeroed();
13022 if sys_ioctl(fd, TIOCGWINSZ, &mut ws as *mut winsize as *mut u8) == 0 { 1 } else { 0 }
13023}
13024
13025#[no_mangle]
13026pub unsafe extern "C" fn getlogin() -> *mut c_char {
13027 static mut LOGIN_BUF: [c_char; 32] = [0; 32];
13028 let pw = getpwuid(crate::getuid());
13029 if pw.is_null() { return core::ptr::null_mut(); }
13030 let n = crate::strlen((*pw).pw_name);
13031 if n + 1 > LOGIN_BUF.len() { return core::ptr::null_mut(); }
13032 core::ptr::copy_nonoverlapping((*pw).pw_name, LOGIN_BUF.as_mut_ptr(), n + 1);
13033 LOGIN_BUF.as_mut_ptr()
13034}
13035
13036#[no_mangle]
13037pub unsafe extern "C" fn getgroups(size: c_int, list: *mut c_uint) -> c_int {
13038 let r = sys_getgroups(size, list);
13039 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13040 r as c_int
13041}
13042
13043#[no_mangle]
13044pub unsafe extern "C" fn setuid(uid: c_uint) -> c_int {
13045 let r = sys_setuid(uid);
13046 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13047 0
13048}
13049
13050#[no_mangle]
13051pub unsafe extern "C" fn setgid(gid: c_uint) -> c_int {
13052 let r = sys_setgid(gid);
13053 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13054 0
13055}
13056
13057#[no_mangle]
13058pub unsafe extern "C" fn seteuid(euid: c_uint) -> c_int {
13059 setresuid(u32::MAX, euid, u32::MAX)
13063}
13064
13065#[no_mangle]
13066pub unsafe extern "C" fn setegid(egid: c_uint) -> c_int {
13067 setresgid(u32::MAX, egid, u32::MAX)
13068}
13069
13070#[no_mangle]
13071pub unsafe extern "C" fn setreuid(ruid: c_uint, euid: c_uint) -> c_int {
13072 let r = <Arch as Syscalls>::syscall2(sysno(113, 145), ruid as i64, euid as i64);
13073 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
13074}
13075
13076
13077
13078#[no_mangle]
13079pub unsafe extern "C" fn setsid() -> c_int {
13080 let r = sys_setsid();
13081 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13082 r as c_int
13083}
13084
13085#[no_mangle]
13086pub unsafe extern "C" fn setpgid(pid: c_int, pgid: c_int) -> c_int {
13087 let r = sys_setpgid(pid, pgid);
13088 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13089 0
13090}
13091
13092#[no_mangle]
13093pub unsafe extern "C" fn getpgid(pid: c_int) -> c_int {
13094 let r = sys_getpgid(pid);
13095 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13096 r as c_int
13097}
13098
13099#[no_mangle]
13100pub unsafe extern "C" fn getsid(pid: c_int) -> c_int {
13101 let r = sys_getsid(pid);
13102 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13103 r as c_int
13104}
13105
13106#[no_mangle]
13107pub unsafe extern "C" fn getpgrp() -> c_int {
13108 sys_getpgid(0) as c_int
13109}
13110
13111#[no_mangle]
13112pub unsafe extern "C" fn setpgrp() -> c_int {
13113 setpgid(0, 0)
13114}
13115
13116#[no_mangle]
13117pub unsafe extern "C" fn mkstemp(template: *mut c_char) -> c_int {
13118 if template.is_null() { ERRNO!() = EINVAL; return -1; }
13119 let len = strlen(template as *const c_char);
13120 if len < 6 { ERRNO!() = EINVAL; return -1; }
13121 let x_start = len - 6;
13122 for i in x_start..len {
13124 if *template.add(i) != b'X' as c_char { ERRNO!() = EINVAL; return -1; }
13125 }
13126 let mut ts: timespec = core::mem::zeroed();
13127 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
13128 let mut ctr: u32 = ts.tv_nsec as u32;
13129 for _ in 0..100 {
13130 ctr = ctr.wrapping_mul(1103515245).wrapping_add(12345);
13131 let seed = ctr;
13132 let hex = b"0123456789abcdef";
13134 let mut s = seed;
13135 for i in x_start..len {
13136 *template.add(i) = hex[(s & 0xf) as usize] as c_char;
13137 s >>= 4;
13138 }
13139 let fd = sys_open(template as *const u8, (O_RDWR | O_CREAT | O_EXCL) as i64, 0o600);
13140 if fd >= 0 { return fd as c_int; }
13141 let e = (-fd) as c_int;
13142 if e != EEXIST_VAL { ERRNO!() = e; return -1; }
13143 }
13144 ERRNO!() = EEXIST_VAL;
13145 -1
13146}
13147
13148#[no_mangle]
13149pub unsafe extern "C" fn mkdir(path: *const c_char, mode: c_uint) -> c_int {
13150 let r = sys_mkdirat(AT_FDCWD, path as *const u8, mode);
13151 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13152 0
13153}
13154
13155#[no_mangle]
13160pub unsafe extern "C" fn dirname(s: *mut c_char) -> *mut c_char {
13161 if s.is_null() || *s == 0 {
13162 return b".\0".as_ptr() as *mut c_char;
13163 }
13164 let mut i = strlen(s as *const c_char);
13165 i = i.wrapping_sub(1);
13166 while i > 0 && *s.add(i) == b'/' as c_char {
13168 i = i.wrapping_sub(1);
13169 }
13170 if i == 0 && *s.add(0) == b'/' as c_char {
13171 return b"/\0".as_ptr() as *mut c_char;
13172 }
13173 while i > 0 && *s.add(i) != b'/' as c_char {
13175 i = i.wrapping_sub(1);
13176 }
13177 if i == 0 {
13178 if *s.add(0) == b'/' as c_char {
13179 return b"/\0".as_ptr() as *mut c_char;
13180 }
13181 return b".\0".as_ptr() as *mut c_char;
13182 }
13183 while i > 0 && *s.add(i - 1) == b'/' as c_char {
13185 i = i.wrapping_sub(1);
13186 }
13187 if i == 0 {
13188 return b"/\0".as_ptr() as *mut c_char;
13189 }
13190 *s.add(i) = 0;
13191 s
13192}
13193
13194#[no_mangle]
13195pub unsafe extern "C" fn basename(s: *mut c_char) -> *mut c_char {
13196 if s.is_null() || *s == 0 {
13197 return b".\0".as_ptr() as *mut c_char;
13198 }
13199 let mut i = strlen(s as *const c_char);
13200 i = i.wrapping_sub(1);
13201 while i > 0 && *s.add(i) == b'/' as c_char {
13203 *s.add(i) = 0;
13204 i = i.wrapping_sub(1);
13205 }
13206 while i > 0 && *s.add(i - 1) != b'/' as c_char {
13208 i = i.wrapping_sub(1);
13209 }
13210 s.add(i)
13211}
13212
13213const AF_INET_VAL: c_int = 2;
13218const AF_INET6_VAL: c_int = 10;
13219const EAFNOSUPPORT: c_int = 97;
13220const ENOSPC_VAL2: c_int = 28;
13221
13222unsafe fn inet_pton_v4(s: *const u8, a: *mut u8) -> c_int {
13223 let mut p = s;
13224 let mut i = 0;
13225 while i < 4 {
13226 let oct_start = p;
13227 let mut v: u32 = 0;
13228 let mut j: u32 = 0;
13229 while j < 3 && *p >= b'0' && *p <= b'9' {
13230 v = v * 10 + (*p - b'0') as u32;
13231 p = p.add(1);
13232 j += 1;
13233 }
13234 if j == 0 || (j > 1 && *oct_start == b'0') || v > 255 { return 0; }
13235 *a.add(i) = v as u8;
13236 if *p == 0 && i == 3 { return 1; }
13237 if *p != b'.' { return 0; }
13238 p = p.add(1);
13239 i += 1;
13240 }
13241 0
13242}
13243
13244unsafe fn inet_pton_v6(s: *const u8, a: *mut u8) -> c_int {
13245 let mut ip = [0u16; 8];
13246 let mut p = s;
13247 let mut i: usize = 0;
13248 let mut brk: isize = -1;
13249 let mut need_v4 = false;
13250 let mut v4_start: *const u8 = core::ptr::null();
13251
13252 if *p == b':' {
13253 p = p.add(1);
13254 if *p != b':' { return 0; }
13255 }
13256
13257 loop {
13258 if *p == b':' && brk < 0 {
13259 brk = i as isize;
13260 ip[i & 7] = 0;
13261 p = p.add(1);
13262 if *p == 0 { break; }
13263 if i == 7 { return 0; }
13264 i += 1;
13265 continue;
13266 }
13267 v4_start = p;
13268 let mut v: u16 = 0;
13269 let mut j = 0;
13270 while j < 4 {
13271 let d = hex_digit(*p);
13272 if d < 0 { break; }
13273 v = v * 16 + d as u16;
13274 p = p.add(1);
13275 j += 1;
13276 }
13277 if j == 0 { return 0; }
13278 ip[i & 7] = v;
13279 if *p == 0 && (brk >= 0 || i == 7) { break; }
13280 if i == 7 { return 0; }
13281 if *p != b':' {
13282 if *p != b'.' || (i < 6 && brk < 0) { return 0; }
13283 need_v4 = true;
13284 i += 1;
13285 ip[i & 7] = 0;
13286 break;
13287 }
13288 p = p.add(1);
13289 i += 1;
13290 }
13291
13292 if brk >= 0 {
13293 let trail_count = i + 1 - brk as usize;
13295 let dest_start = brk as usize + 7 - i;
13296 for j in (0..trail_count).rev() {
13298 ip[dest_start + j] = ip[brk as usize + j];
13299 }
13300 for j in 0..(7 - i) {
13301 ip[brk as usize + j] = 0;
13302 }
13303 }
13304
13305 for k in 0..8 {
13306 *a.add(k * 2) = (ip[k] >> 8) as u8;
13307 *a.add(k * 2 + 1) = (ip[k] & 0xff) as u8;
13308 }
13309
13310 if need_v4 {
13311 if inet_pton_v4(v4_start, a.add(12)) <= 0 { return 0; }
13312 }
13313 1
13314}
13315
13316unsafe fn hex_digit(c: u8) -> i32 {
13317 if c >= b'0' && c <= b'9' { (c - b'0') as i32 }
13318 else if c >= b'a' && c <= b'f' { (c - b'a' + 10) as i32 }
13319 else if c >= b'A' && c <= b'F' { (c - b'A' + 10) as i32 }
13320 else { -1 }
13321}
13322
13323#[no_mangle]
13324pub unsafe extern "C" fn inet_pton(af: c_int, s: *const c_char, a: *mut c_void) -> c_int {
13325 if af == AF_INET_VAL {
13326 inet_pton_v4(s as *const u8, a as *mut u8)
13327 } else if af == AF_INET6_VAL {
13328 inet_pton_v6(s as *const u8, a as *mut u8)
13329 } else {
13330 ERRNO!() = EAFNOSUPPORT;
13331 -1
13332 }
13333}
13334
13335#[no_mangle]
13336pub unsafe extern "C" fn inet_ntop(af: c_int, a: *const c_void, s: *mut c_char, size: u32) -> *mut c_char {
13337 if af == AF_INET_VAL {
13338 let b = a as *const u8;
13339 let needed = 16; if size < needed as u32 { ERRNO!() = ENOSPC_VAL2; return core::ptr::null_mut(); }
13341 let mut pos = 0;
13342 for i in 0..4 {
13343 if i > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
13344 let (buf, len) = format_u64(*b.add(i) as u64);
13345 for j in 0..len { *s.add(pos) = buf[j] as c_char; pos += 1; }
13346 }
13347 *s.add(pos) = 0;
13348 s
13349 } else if af == AF_INET6_VAL {
13350 let b = a as *const u8;
13351 let needed = 46; if size < needed as u32 { ERRNO!() = ENOSPC_VAL2; return core::ptr::null_mut(); }
13353 let mut words = [0u16; 8];
13354 for i in 0..8 {
13355 words[i] = ((*b.add(i * 2) as u16) << 8) | (*b.add(i * 2 + 1) as u16);
13356 }
13357 let mut pos = 0usize;
13359 if words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0
13360 && words[4] == 0 && words[5] == 0xffff
13361 {
13362 let prefix = b"::ffff:";
13363 for k in 0..prefix.len() { *s.add(pos) = prefix[k] as c_char; pos += 1; }
13364 for idx in 0..4 {
13365 if idx > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
13366 let octet = *b.add(12 + idx);
13367 if octet >= 100 {
13368 *s.add(pos) = (b'0' + octet / 100) as c_char; pos += 1;
13369 *s.add(pos) = (b'0' + (octet / 10) % 10) as c_char; pos += 1;
13370 } else if octet >= 10 {
13371 *s.add(pos) = (b'0' + octet / 10) as c_char; pos += 1;
13372 }
13373 *s.add(pos) = (b'0' + octet % 10) as c_char; pos += 1;
13374 }
13375 *s.add(pos) = 0;
13376 return s;
13377 }
13378 let mut best_start: isize = -1;
13380 let mut best_len: usize = 0;
13381 let mut j: usize = 0;
13382 while j < 8 {
13383 if words[j] == 0 {
13384 let mut k = j;
13385 while k < 8 && words[k] == 0 { k += 1; }
13386 let run = k - j;
13387 if run > best_len { best_start = j as isize; best_len = run; }
13388 j = k;
13389 } else {
13390 j += 1;
13391 }
13392 }
13393 let mut i: usize = 0;
13394 let mut prev_in_run = false;
13395 while i < 8 {
13396 let in_run = best_len >= 2 && i >= best_start as usize && i < best_start as usize + best_len;
13397 if in_run {
13398 if i == best_start as usize {
13399 *s.add(pos) = b':' as c_char; pos += 1;
13400 *s.add(pos) = b':' as c_char; pos += 1;
13401 }
13402 i += 1;
13403 prev_in_run = true;
13404 continue;
13405 }
13406 if i > 0 && !prev_in_run {
13407 *s.add(pos) = b':' as c_char; pos += 1;
13408 }
13409 let (buf, len) = format_hex(words[i] as u64, false);
13410 for k in 0..len { *s.add(pos) = buf[k] as c_char; pos += 1; }
13411 i += 1;
13412 prev_in_run = false;
13413 }
13414 *s.add(pos) = 0;
13415 s
13416 } else {
13417 ERRNO!() = EAFNOSUPPORT;
13418 core::ptr::null_mut()
13419 }
13420}
13421
13422#[no_mangle]
13423pub unsafe extern "C" fn inet_aton(s: *const c_char, dest: *mut c_void) -> c_int {
13424 let a = dest as *mut u8;
13425 let mut p = s as *const u8;
13426 let mut vals = [0u64; 4];
13427 let mut i = 0usize;
13428 while i < 4 {
13429 if *p < b'0' || *p > b'9' { return 0; }
13430 let mut base = 10u32;
13431 if *p == b'0' {
13432 let c = *p.add(1);
13433 if c == b'x' || c == b'X' {
13434 base = 16;
13435 p = p.add(2);
13436 if !((*p >= b'0' && *p <= b'9')
13437 || (*p >= b'a' && *p <= b'f')
13438 || (*p >= b'A' && *p <= b'F')) {
13439 return 0;
13440 }
13441 } else {
13442 base = 8;
13443 }
13444 }
13445 let mut v: u64 = 0;
13446 let start = p;
13447 loop {
13448 let c = *p;
13449 let d = if c >= b'0' && c <= b'9' {
13450 (c - b'0') as u64
13451 } else if base == 16 && c >= b'a' && c <= b'f' {
13452 (c - b'a' + 10) as u64
13453 } else if base == 16 && c >= b'A' && c <= b'F' {
13454 (c - b'A' + 10) as u64
13455 } else {
13456 break;
13457 };
13458 v = v * (base as u64) + d;
13459 p = p.add(1);
13460 }
13461 if p == start { return 0; }
13462 vals[i] = v;
13463 if *p == 0 {
13464 break;
13465 }
13466 if *p != b'.' || i == 3 { return 0; }
13467 p = p.add(1);
13468 i += 1;
13469 }
13470 if i == 4 { return 0; }
13471 if i < 1 { vals[1] = vals[0] & 0xffffff; vals[0] >>= 24; }
13472 if i < 2 { vals[2] = vals[1] & 0xffff; vals[1] >>= 16; }
13473 if i < 3 { vals[3] = vals[2] & 0xff; vals[2] >>= 8; }
13474 for j in 0..4 {
13475 if vals[j] > 255 { return 0; }
13476 *a.add(j) = vals[j] as u8;
13477 }
13478 1
13479}
13480
13481#[no_mangle]
13482pub unsafe extern "C" fn inet_addr(s: *const c_char) -> u32 {
13483 let mut a = [0u8; 4];
13484 if inet_aton(s, a.as_mut_ptr() as *mut c_void) == 1 {
13485 u32::from_ne_bytes(a)
13486 } else {
13487 !0u32 }
13489}
13490
13491#[no_mangle]
13492pub unsafe extern "C" fn inet_ntoa(addr: u32) -> *mut c_char {
13493 static mut NTOA_BUF: [c_char; 16] = [0; 16];
13494 let b = addr.to_ne_bytes();
13495 let mut pos = 0;
13496 for i in 0..4 {
13497 if i > 0 { NTOA_BUF[pos] = b'.' as c_char; pos += 1; }
13498 let (buf, len) = format_u64(b[i] as u64);
13499 for j in 0..len { NTOA_BUF[pos] = buf[j] as c_char; pos += 1; }
13500 }
13501 NTOA_BUF[pos] = 0;
13502 core::ptr::addr_of_mut!(NTOA_BUF).cast::<c_char>()
13503}
13504
13505#[no_mangle]
13507pub unsafe extern "C" fn inet_network(s: *const c_char) -> u32 {
13508 inet_addr(s).to_be()
13509}
13510
13511#[no_mangle]
13512pub extern "C" fn inet_makeaddr(net: c_int, host: c_int) -> u32 {
13513 let addr: u32;
13514 if (net as u32) < 128 {
13515 addr = (net as u32) << 24;
13516 } else if (net as u32) < 0x10000 {
13517 addr = (net as u32) << 16;
13518 } else if (net as u32) < 0x1000000 {
13519 addr = (net as u32) << 8;
13520 } else {
13521 addr = net as u32;
13522 }
13523 addr | (host as u32 & 0xffffffff)
13524}
13525
13526#[no_mangle]
13527pub extern "C" fn inet_lnaof(addr: u32) -> c_int {
13528 let h = u32::from_be(addr);
13529 if h < 0x80000000 { (h & 0x00ffffff) as c_int }
13530 else if h < 0xc0000000 { (h & 0x0000ffff) as c_int }
13531 else { (h & 0x000000ff) as c_int }
13532}
13533
13534#[no_mangle]
13535pub extern "C" fn inet_netof(addr: u32) -> c_int {
13536 let h = u32::from_be(addr);
13537 if h < 0x80000000 { (h >> 24) as c_int }
13538 else if h < 0xc0000000 { (h >> 16) as c_int }
13539 else { (h >> 8) as c_int }
13540}
13541
13542unsafe fn parse_float(s: *const u8, endptr: *mut *mut u8, is_f32: bool) -> f64 {
13551 let mut p = s;
13552 while *p == b' ' || *p == b'\t' || *p == b'\n' || *p == b'\r' { p = p.add(1); }
13554 let mut neg = false;
13555 if *p == b'-' { neg = true; p = p.add(1); }
13556 else if *p == b'+' { p = p.add(1); }
13557
13558 if (*p | 0x20) == b'i'
13560 && (*p.add(1) | 0x20) == b'n'
13561 && (*p.add(2) | 0x20) == b'f'
13562 {
13563 p = p.add(3);
13564 if (*p | 0x20) == b'i'
13566 && (*p.add(1) | 0x20) == b't'
13567 && (*p.add(2) | 0x20) == b'y'
13568 {
13569 p = p.add(3);
13570 }
13571 if !endptr.is_null() { *endptr = p as *mut u8; }
13572 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13573 }
13574 if (*p | 0x20) == b'n'
13576 && (*p.add(1) | 0x20) == b'a'
13577 && (*p.add(2) | 0x20) == b'n'
13578 {
13579 p = p.add(3);
13580 if *p == b'(' {
13582 p = p.add(1);
13583 while *p != 0 && *p != b')' { p = p.add(1); }
13584 if *p == b')' { p = p.add(1); }
13585 }
13586 if !endptr.is_null() { *endptr = p as *mut u8; }
13587 return if neg { -f64::NAN } else { f64::NAN };
13588 }
13589
13590 if *p == b'0' && (*p.add(1) == b'x' || *p.add(1) == b'X') {
13592 p = p.add(2);
13593 let mut mant: u128 = 0;
13594 let mut frac_hex: u32 = 0;
13595 let mut found = false;
13596 let mut in_frac = false;
13597
13598 loop {
13599 if let Some(d) = hex_val(*p) {
13600 if mant <= u128::MAX / 16 {
13601 mant = mant * 16 + d as u128;
13602 }
13603 if in_frac { frac_hex += 1; }
13604 p = p.add(1);
13605 found = true;
13606 } else if *p == b'.' && !in_frac {
13607 in_frac = true;
13608 p = p.add(1);
13609 } else {
13610 break;
13611 }
13612 }
13613
13614 if !found {
13615 if !endptr.is_null() { *endptr = s as *mut u8; }
13616 return 0.0;
13617 }
13618
13619 let mut bin_exp: i32 = 0;
13621 if *p == b'p' || *p == b'P' {
13622 p = p.add(1);
13623 let mut exp_neg = false;
13624 if *p == b'-' { exp_neg = true; p = p.add(1); }
13625 else if *p == b'+' { p = p.add(1); }
13626 while *p >= b'0' && *p <= b'9' {
13627 if bin_exp < 100000 {
13628 bin_exp = bin_exp * 10 + (*p - b'0') as i32;
13629 }
13630 p = p.add(1);
13631 }
13632 if exp_neg { bin_exp = -bin_exp; }
13633 }
13634
13635 if !endptr.is_null() { *endptr = p as *mut u8; }
13636 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
13637
13638 let total_exp = bin_exp as i64 - 4 * frac_hex as i64;
13639 return hex_mant_to_f64(mant, total_exp, neg);
13640 }
13641
13642 let mut buf = [0u8; 65536];
13644 let mut n = 0usize;
13645 let mut found_digit = false;
13646
13647 while *p >= b'0' && *p <= b'9' {
13648 if n < 65535 { buf[n] = *p; n += 1; }
13649 p = p.add(1);
13650 found_digit = true;
13651 }
13652 if *p == b'.' {
13653 if n < 65535 { buf[n] = b'.'; n += 1; }
13654 p = p.add(1);
13655 while *p >= b'0' && *p <= b'9' {
13656 if n < 65535 { buf[n] = *p; n += 1; }
13657 p = p.add(1);
13658 found_digit = true;
13659 }
13660 }
13661 if !found_digit {
13662 if !endptr.is_null() { *endptr = s as *mut u8; }
13663 return 0.0;
13664 }
13665 if *p == b'e' || *p == b'E' {
13666 if n < 65535 { buf[n] = b'e'; n += 1; }
13667 p = p.add(1);
13668 if *p == b'-' || *p == b'+' {
13669 if n < 65535 { buf[n] = *p; n += 1; }
13670 p = p.add(1);
13671 }
13672 while *p >= b'0' && *p <= b'9' {
13673 if n < 65535 { buf[n] = *p; n += 1; }
13674 p = p.add(1);
13675 }
13676 }
13677
13678 if !endptr.is_null() { *endptr = p as *mut u8; }
13679 let s_str = core::str::from_utf8_unchecked(
13680 core::slice::from_raw_parts(buf.as_ptr(), n),
13681 );
13682 if is_f32 {
13683 match <f32 as core::str::FromStr>::from_str(s_str) {
13684 Ok(v) => { let r = v as f64; if neg { -r } else { r } }
13685 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13686 }
13687 } else {
13688 match <f64 as core::str::FromStr>::from_str(s_str) {
13689 Ok(v) => if neg { -v } else { v },
13690 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13691 }
13692 }
13693}
13694
13695fn hex_mant_to_f64(mant: u128, total_exp: i64, neg: bool) -> f64 {
13699 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
13700
13701 let msb = (127 - mant.leading_zeros()) as i64;
13702 let unbiased_exp = msb + total_exp;
13703 let biased_exp = unbiased_exp + 1023;
13704
13705 if biased_exp >= 2047 {
13707 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13708 }
13709
13710 if biased_exp <= 0 {
13712 let shift = total_exp + 1074;
13715 if shift < 0 {
13716 return if neg { -0.0 } else { 0.0 };
13717 }
13718 if shift > 128 {
13719 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13720 }
13721 let shifted = mant << (shift as u32);
13722 let mantissa52 = (shifted as u64) & 0x000FFFFFFFFFFFFF;
13723 let guard = ((shifted >> 52) & 1) != 0;
13724 let sticky = (shifted >> 53) != 0;
13725 let mut result = mantissa52;
13726 if guard && (sticky || (result & 1) != 0) {
13727 result += 1;
13728 if result > 0x000FFFFFFFFFFFFF {
13729 return if neg { -f64::from_bits(1u64 << 52) } else { f64::from_bits(1u64 << 52) };
13731 }
13732 }
13733 return if neg { -f64::from_bits(result) } else { f64::from_bits(result) };
13734 }
13735
13736 let shift = msb - 52;
13738
13739 if shift <= 0 {
13740 let mantissa = ((mant as u64) & ((1u64 << msb as u32) - 1)) << ((-shift) as u32);
13742 let bits = ((biased_exp as u64) << 52) | mantissa;
13743 return if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) };
13744 }
13745
13746 let mantissa = ((mant >> shift as u32) as u64) & 0x000FFFFFFFFFFFFF;
13748 let guard = ((mant >> (shift as u32 - 1)) & 1) != 0;
13749 let sticky = if shift > 1 {
13750 (mant & ((1u128 << (shift as u32 - 1)) - 1)) != 0
13751 } else { false };
13752
13753 let mut result_mant = mantissa;
13754 let mut result_exp = biased_exp;
13755 if guard && (sticky || (result_mant & 1) != 0) {
13756 result_mant += 1;
13757 if result_mant > 0x000FFFFFFFFFFFFF {
13758 result_mant = 0;
13759 result_exp += 1;
13760 if result_exp >= 2047 {
13761 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13762 }
13763 }
13764 }
13765
13766 let bits = ((result_exp as u64) << 52) | result_mant;
13767 if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) }
13768}
13769
13770unsafe fn hex_val(c: u8) -> Option<u8> {
13771 if c >= b'0' && c <= b'9' { Some(c - b'0') }
13772 else if c >= b'a' && c <= b'f' { Some(c - b'a' + 10) }
13773 else if c >= b'A' && c <= b'F' { Some(c - b'A' + 10) }
13774 else { None }
13775}
13776
13777#[no_mangle]
13778pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13779 let mut end: *mut u8 = s as *mut u8;
13780 let r = parse_float(s as *const u8, &mut end, false);
13781 if !endptr.is_null() { *endptr = end as *mut c_char; }
13782 r
13783}
13784
13785#[no_mangle]
13786pub unsafe extern "C" fn strtof(s: *const c_char, endptr: *mut *mut c_char) -> f32 {
13787 let mut end: *mut u8 = s as *mut u8;
13788 let r = parse_float(s as *const u8, &mut end, true);
13789 if !endptr.is_null() { *endptr = end as *mut c_char; }
13790 r as f32
13791}
13792
13793#[no_mangle]
13794#[cfg(target_arch = "x86_64")]
13795pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13796 strtod(s, endptr)
13797}
13798
13799#[no_mangle]
13800#[cfg(target_arch = "aarch64")]
13801pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13802 strtod(s, endptr) as f128
13803}
13804
13805#[no_mangle]
13806#[cfg(target_arch = "riscv64")]
13807pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13808 strtod(s, endptr) as f128
13809}
13810
13811#[no_mangle]
13812pub unsafe extern "C" fn atof(s: *const c_char) -> f64 {
13813 strtod(s, core::ptr::null_mut())
13814}
13815
13816#[repr(C)]
13821struct MsCookie {
13822 bufp: *mut *mut c_char,
13823 sizep: *mut usize,
13824 pos: usize,
13825 len: usize,
13826 buf: *mut u8,
13827 space: usize,
13828}
13829
13830#[repr(C)]
13831struct MfCookie {
13832 pos: usize,
13833 len: usize,
13834 size: usize,
13835 buf: *mut u8,
13836 mode: c_char,
13837}
13838
13839unsafe extern "C" fn ms_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13840 let c = (*f).cookie as *mut MsCookie;
13841 if whence < 0 || whence > 2 { ERRNO!() = EINVAL; return -1; }
13842 let base: i64 = match whence {
13843 0 => 0,
13844 1 => (*c).pos as i64,
13845 2 => (*c).len as i64,
13846 _ => { ERRNO!() = EINVAL; return -1; }
13847 };
13848 if off < -base || off > isize::MAX as i64 - base { ERRNO!() = EINVAL; return -1; }
13849 (*c).pos = (base + off) as usize;
13850 (*c).pos as i64
13851}
13852
13853unsafe extern "C" fn ms_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13854 let c = (*f).cookie as *mut MsCookie;
13855 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13856 if buffered > 0 {
13857 (*f).wpos = (*f).wbase;
13858 if ms_write(f, (*f).wbase, buffered) < buffered { return 0; }
13859 }
13860 if len == 0 { return 0; }
13861 if (*c).pos + len >= (*c).space {
13862 let new_space = 2 * (*c).space + 1 | (*c).pos + len + 1;
13863 let newbuf = realloc((*c).buf as *mut c_void, new_space) as *mut u8;
13864 if newbuf.is_null() { return 0; }
13865 *(*c).bufp = newbuf as *mut c_char;
13866 core::ptr::write_bytes(newbuf.add((*c).space), 0, new_space - (*c).space);
13867 (*c).buf = newbuf;
13868 (*c).space = new_space;
13869 }
13870 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), len);
13871 (*c).pos += len;
13872 if (*c).pos >= (*c).len { (*c).len = (*c).pos; }
13873 *(*c).sizep = (*c).pos;
13874 len
13875}
13876
13877unsafe extern "C" fn ms_close(_f: *mut FILE) -> c_int {
13878 0
13879}
13880
13881#[no_mangle]
13882pub unsafe extern "C" fn open_memstream(bufp: *mut *mut c_char, sizep: *mut usize) -> *mut FILE {
13883 if bufp.is_null() || sizep.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
13884 let f = calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
13885 if f.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13886 let buf_area = buf_ptr(f);
13887 init_file(f, -1, b"w\0".as_ptr() as *const c_char, Some(ms_close), buf_area, BUFSIZ);
13888 (*f).flags = F_NORD | F_SVB;
13889 (*f).lbf = -1;
13890 let c = calloc(1, core::mem::size_of::<MsCookie>()) as *mut MsCookie;
13891 if c.is_null() { free(f as *mut c_void); ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13892 (*c).bufp = bufp;
13893 (*c).sizep = sizep;
13894 (*c).pos = 0;
13895 (*c).len = 0;
13896 (*c).buf = core::ptr::null_mut();
13897 (*c).space = 0;
13898 (*f).cookie = c as *mut c_void;
13899 (*f).write_fn = Some(ms_write);
13900 (*f).seek_fn = Some(ms_seek);
13901 *bufp = core::ptr::null_mut();
13902 *sizep = 0;
13903 f
13904}
13905
13906unsafe extern "C" fn mseek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13907 let c = (*f).cookie as *mut MfCookie;
13908 if whence < 0 || whence > 2 { ERRNO!() = EINVAL; return -1; }
13909 let base: i64 = match whence {
13910 0 => 0,
13911 1 => (*c).pos as i64,
13912 2 => (*c).len as i64,
13913 _ => { ERRNO!() = EINVAL; return -1; }
13914 };
13915 if off < -base || off > (*c).size as i64 - base { ERRNO!() = EINVAL; return -1; }
13916 (*c).pos = (base + off) as usize;
13917 (*c).pos as i64
13918}
13919
13920unsafe extern "C" fn mread(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
13921 let c = (*f).cookie as *mut MfCookie;
13922 let mut rem = if (*c).pos <= (*c).len { (*c).len - (*c).pos } else { 0 };
13923 let mut l = len;
13924 if l > rem {
13925 l = rem;
13926 (*f).flags |= F_EOF;
13927 }
13928 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), buf, l);
13929 (*c).pos += l;
13930 rem -= l;
13931 if rem > (*f).buf_size { rem = (*f).buf_size; }
13932 (*f).rpos = (*f).buf;
13933 (*f).rend = (*f).buf.add(rem);
13934 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), (*f).rpos, rem);
13935 (*c).pos += rem;
13936 l
13937}
13938
13939unsafe extern "C" fn mwrite(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13940 let c = (*f).cookie as *mut MfCookie;
13941 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13942 if buffered > 0 {
13943 (*f).wpos = (*f).wbase;
13944 if mwrite(f, (*f).wbase, buffered) < buffered { return 0; }
13945 }
13946 if len == 0 { return 0; }
13947 if (*c).mode == b'a' as c_char { (*c).pos = (*c).len; }
13948 let rem = (*c).size - (*c).pos;
13949 let mut l = len;
13950 if l > rem { l = rem; }
13951 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), l);
13952 (*c).pos += l;
13953 if (*c).pos > (*c).len {
13954 (*c).len = (*c).pos;
13955 if (*c).len < (*c).size {
13956 *(*c).buf.add((*c).len) = 0;
13957 } else if ((*f).flags & F_NORD) != 0 && (*c).size > 0 {
13958 *(*c).buf.add((*c).size - 1) = 0;
13959 }
13960 }
13961 l
13962}
13963
13964unsafe extern "C" fn mclose(_f: *mut FILE) -> c_int {
13965 0
13966}
13967
13968#[no_mangle]
13969pub unsafe extern "C" fn fmemopen(buf: *mut c_void, size: usize, mode: *const c_char) -> *mut FILE {
13970 if mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
13971 let m = *mode;
13972 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
13973 ERRNO!() = EINVAL; return core::ptr::null_mut();
13974 }
13975 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
13976 let need_alloc = buf.is_null();
13977 let alloc_size = core::mem::size_of::<FILE>() + UNGET + BUFSIZ + if need_alloc { size } else { 0 };
13978 let f = calloc(1, alloc_size) as *mut FILE;
13979 if f.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13980 let buf_area = buf_ptr(f);
13981 init_file(f, -1, mode, Some(mclose), buf_area, BUFSIZ);
13982 (*f).flags |= F_SVB;
13983 let actual_buf: *mut u8 = if need_alloc {
13984 (f as *mut u8).add(alloc_size - size)
13985 } else {
13986 buf as *mut u8
13987 };
13988 if need_alloc { core::ptr::write_bytes(actual_buf, 0, size); }
13989 let c = calloc(1, core::mem::size_of::<MfCookie>()) as *mut MfCookie;
13990 if c.is_null() { free(f as *mut c_void); ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13991 (*c).buf = actual_buf;
13992 (*c).size = size;
13993 (*c).mode = m;
13994 (*f).cookie = c as *mut c_void;
13995 (*f).read_fn = Some(mread);
13996 (*f).write_fn = Some(mwrite);
13997 (*f).seek_fn = Some(mseek);
13998 if !has_plus { (*f).flags = if m == b'r' as c_char { F_NOWR } else { F_NORD }; }
13999 if m == b'r' as c_char {
14000 (*c).len = size;
14001 } else if m == b'a' as c_char {
14002 (*c).len = strnlen(actual_buf, size);
14003 (*c).pos = (*c).len;
14004 } else if has_plus {
14005 *actual_buf = 0;
14006 }
14007 f
14008}
14009
14010#[repr(C)]
14015struct kernel_stat64 {
14016 st_dev: u64,
14017 st_ino: u64,
14018 st_nlink: u64,
14019 st_mode: u32,
14020 st_uid: u32,
14021 st_gid: u32,
14022 __pad0: c_int,
14023 st_rdev: u64,
14024 st_size: i64,
14025 st_blksize: i64,
14026 st_blocks: i64,
14027 st_atime: i64,
14028 st_atime_nsec: i64,
14029 st_mtime: i64,
14030 st_mtime_nsec: i64,
14031 st_ctime: i64,
14032 st_ctime_nsec: i64,
14033 __unused: [i64; 3],
14034}
14035
14036#[inline]
14038unsafe fn sys_stat(path: *const u8, statbuf: *mut kernel_stat64) -> i64 {
14039 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, AT_FDCWD as i64, path as i64, statbuf as i64, 0)
14040}
14041
14042const HSEARCH_MINSIZE: usize = 8;
14047
14048#[repr(C)]
14049#[derive(Copy, Clone)]
14050pub struct HSearchEntry {
14051 key: *mut c_char,
14052 data: *mut c_void,
14053}
14054
14055#[repr(C)]
14056struct HTab {
14057 entries: *mut HSearchEntry,
14058 mask: usize,
14059 used: usize,
14060}
14061
14062#[repr(C)]
14063pub struct HSearchData {
14064 tab: *mut HTab,
14065 __unused1: c_uint,
14066 __unused2: c_uint,
14067}
14068
14069static mut HTAB_DATA: HSearchData = HSearchData {
14071 tab: core::ptr::null_mut(),
14072 __unused1: 0,
14073 __unused2: 0,
14074};
14075
14076unsafe fn keyhash(k: *const c_char) -> usize {
14077 let mut h: usize = 0;
14078 let mut p = k;
14079 while *p != 0 {
14080 h = h.wrapping_mul(31).wrapping_add(*p as usize);
14081 p = p.add(1);
14082 }
14083 h
14084}
14085
14086unsafe fn htab_lookup(key: *const c_char, hash: usize, htab: *mut HSearchData) -> *mut HSearchEntry {
14087 let tab = (*htab).tab;
14088 let mask = (*tab).mask;
14089 let entries = (*tab).entries;
14090 let mut i = hash;
14091 let mut j: usize = 1;
14092 loop {
14093 let e = entries.add(i & mask);
14094 if (*e).key.is_null() || strcmp((*e).key as *const u8, key as *const u8) == 0 {
14095 return e;
14096 }
14097 i = i.wrapping_add(j);
14098 j += 1;
14099 }
14100}
14101
14102unsafe fn htab_resize(nel: usize, htab: *mut HSearchData) -> c_int {
14103 let tab = (*htab).tab;
14104 let old_entries = (*tab).entries;
14105 let old_size = (*tab).mask + 1;
14106
14107 let mut newsize: usize = HSEARCH_MINSIZE;
14108 while newsize < nel {
14109 let Some(next) = newsize.checked_mul(2) else {
14110 ERRNO!() = ENOMEM;
14111 return 0;
14112 };
14113 newsize = next;
14114 }
14115
14116 let new_entries = calloc(newsize, core::mem::size_of::<HSearchEntry>()) as *mut HSearchEntry;
14117 if new_entries.is_null() {
14118 ERRNO!() = ENOMEM;
14119 return 0;
14120 }
14121 (*tab).entries = new_entries;
14122 (*tab).mask = newsize - 1;
14123
14124 if !old_entries.is_null() {
14125 for idx in 0..old_size {
14126 let old_e = old_entries.add(idx);
14127 if !(*old_e).key.is_null() {
14128 let h = keyhash((*old_e).key);
14129 let mut i = h;
14130 let mut j: usize = 1;
14131 loop {
14132 let e = new_entries.add(i & (*tab).mask);
14133 if (*e).key.is_null() {
14134 *e = *old_e;
14135 break;
14136 }
14137 i = i.wrapping_add(j);
14138 j += 1;
14139 }
14140 }
14141 }
14142 free(old_entries as *mut c_void);
14143 }
14144 1
14145}
14146
14147unsafe fn hcreate_r_impl(nel: usize, htab: *mut HSearchData) -> c_int {
14148 if nel == 0 || nel > (1usize << 30) {
14149 ERRNO!() = ENOMEM;
14150 return 0;
14151 }
14152 (*htab).tab = calloc(1, core::mem::size_of::<HTab>()) as *mut HTab;
14153 if (*htab).tab.is_null() {
14154 ERRNO!() = ENOMEM;
14155 return 0;
14156 }
14157 if htab_resize(nel, htab) == 0 {
14158 free((*htab).tab as *mut c_void);
14159 (*htab).tab = core::ptr::null_mut();
14160 return 0;
14161 }
14162 1
14163}
14164
14165unsafe fn hdestroy_r_impl(htab: *mut HSearchData) {
14166 if !(*htab).tab.is_null() {
14167 if !(*(*htab).tab).entries.is_null() {
14168 free((*(*htab).tab).entries as *mut c_void);
14169 }
14170 free((*htab).tab as *mut c_void);
14171 (*htab).tab = core::ptr::null_mut();
14172 }
14173}
14174
14175unsafe fn hsearch_r_impl(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
14176 let hash = keyhash(item.key);
14177 let e = htab_lookup(item.key, hash, htab);
14178
14179 if !(*e).key.is_null() {
14180 *retval = e;
14181 return 1;
14182 }
14183 if action == 0 { *retval = core::ptr::null_mut();
14185 return 0;
14186 }
14187 let item_key = item.key;
14189 *e = item;
14190 (*(*htab).tab).used += 1;
14191 if (*(*htab).tab).used > (*(*htab).tab).mask - (*(*htab).tab).mask / 4 {
14192 if htab_resize(2 * (*(*htab).tab).used, htab) == 0 {
14193 (*(*htab).tab).used -= 1;
14194 (*e).key = core::ptr::null_mut();
14195 *retval = core::ptr::null_mut();
14196 return 0;
14197 }
14198 let e2 = htab_lookup(item_key, hash, htab);
14199 *retval = e2;
14200 return 1;
14201 }
14202 *retval = e;
14203 1
14204}
14205
14206#[no_mangle]
14207pub unsafe extern "C" fn hcreate(nel: usize) -> c_int {
14208 hcreate_r_impl(nel, core::ptr::addr_of_mut!(HTAB_DATA))
14209}
14210
14211#[no_mangle]
14212pub unsafe extern "C" fn hdestroy() {
14213 hdestroy_r_impl(core::ptr::addr_of_mut!(HTAB_DATA));
14214}
14215
14216#[no_mangle]
14217pub unsafe extern "C" fn hsearch(item: HSearchEntry, action: c_int) -> *mut HSearchEntry {
14218 let mut e: *mut HSearchEntry = core::ptr::null_mut();
14219 hsearch_r_impl(item, action, &mut e, core::ptr::addr_of_mut!(HTAB_DATA));
14220 e
14221}
14222
14223#[no_mangle]
14224pub unsafe extern "C" fn hcreate_r(nel: usize, htab: *mut HSearchData) -> c_int {
14225 hcreate_r_impl(nel, htab)
14226}
14227
14228#[no_mangle]
14229pub unsafe extern "C" fn hdestroy_r(htab: *mut HSearchData) {
14230 hdestroy_r_impl(htab);
14231}
14232
14233#[no_mangle]
14234pub unsafe extern "C" fn hsearch_r(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
14235 hsearch_r_impl(item, action, retval, htab)
14236}
14237
14238#[repr(C)]
14243struct QueNode {
14244 next: *mut QueNode,
14245 prev: *mut QueNode,
14246}
14247
14248#[no_mangle]
14249pub unsafe extern "C" fn insque(element: *mut c_void, pred: *mut c_void) {
14250 let e = element as *mut QueNode;
14251 let p = pred as *mut QueNode;
14252 if p.is_null() {
14253 (*e).next = core::ptr::null_mut();
14254 (*e).prev = core::ptr::null_mut();
14255 return;
14256 }
14257 (*e).next = (*p).next;
14258 (*e).prev = p;
14259 (*p).next = e;
14260 if !(*e).next.is_null() {
14261 (*(*e).next).prev = e;
14262 }
14263}
14264
14265#[no_mangle]
14266pub unsafe extern "C" fn remque(element: *mut c_void) {
14267 let e = element as *mut QueNode;
14268 if !(*e).next.is_null() {
14269 (*(*e).next).prev = (*e).prev;
14270 }
14271 if !(*e).prev.is_null() {
14272 (*(*e).prev).next = (*e).next;
14273 }
14274}
14275
14276#[no_mangle]
14281pub unsafe extern "C" fn lsearch(
14282 key: *const c_void,
14283 base: *mut c_void,
14284 nelp: *mut usize,
14285 width: usize,
14286 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
14287) -> *mut c_void {
14288 let n = *nelp;
14289 let p = base as *mut u8;
14290 for i in 0..n {
14291 let elem = p.add(i * width);
14292 if compar.unwrap()(key, elem as *const c_void) == 0 {
14293 return elem as *mut c_void;
14294 }
14295 }
14296 let dest = p.add(n * width);
14297 memcpy(dest as *mut c_void, key as *const c_void, width);
14298 *nelp = n + 1;
14299 dest as *mut c_void
14300}
14301
14302#[no_mangle]
14303pub unsafe extern "C" fn lfind(
14304 key: *const c_void,
14305 base: *const c_void,
14306 nelp: *mut usize,
14307 width: usize,
14308 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
14309) -> *mut c_void {
14310 let n = *nelp;
14311 let p = base as *const u8;
14312 for i in 0..n {
14313 let elem = p.add(i * width);
14314 if compar.unwrap()(key, elem as *const c_void) == 0 {
14315 return elem as *mut c_void;
14316 }
14317 }
14318 core::ptr::null_mut()
14319}
14320
14321#[repr(C)]
14327pub struct TreeNode {
14328 key: *const c_void,
14329 left: *mut TreeNode,
14330 right: *mut TreeNode,
14331}
14332
14333type ComparFn = Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>;
14334
14335unsafe fn bst_new(key: *const c_void) -> *mut TreeNode {
14336 let n = calloc(1, core::mem::size_of::<TreeNode>()) as *mut TreeNode;
14337 if !n.is_null() {
14338 (*n).key = key;
14339 (*n).left = core::ptr::null_mut();
14340 (*n).right = core::ptr::null_mut();
14341 }
14342 n
14343}
14344
14345#[no_mangle]
14346pub unsafe extern "C" fn tsearch(
14347 key: *const c_void,
14348 rootp: *mut *mut TreeNode,
14349 compar: ComparFn,
14350) -> *mut c_void {
14351 if rootp.is_null() {
14352 return core::ptr::null_mut();
14353 }
14354 let mut pp = rootp;
14355 loop {
14356 let n = *pp;
14357 if n.is_null() {
14358 let r = bst_new(key);
14359 if r.is_null() {
14360 return core::ptr::null_mut();
14361 }
14362 *pp = r;
14363 return r as *mut c_void;
14364 }
14365 let c = compar.unwrap()(key, (*n).key);
14366 if c == 0 {
14367 return n as *mut c_void;
14368 }
14369 if c < 0 {
14370 pp = &mut (*n).left;
14371 } else {
14372 pp = &mut (*n).right;
14373 }
14374 }
14375}
14376
14377#[no_mangle]
14378pub unsafe extern "C" fn tfind(
14379 key: *const c_void,
14380 rootp: *const *mut TreeNode,
14381 compar: ComparFn,
14382) -> *mut c_void {
14383 if rootp.is_null() {
14384 return core::ptr::null_mut();
14385 }
14386 let mut n = *rootp;
14387 loop {
14388 if n.is_null() {
14389 return core::ptr::null_mut();
14390 }
14391 let c = compar.unwrap()(key, (*n).key);
14392 if c == 0 {
14393 return n as *mut c_void;
14394 }
14395 if c < 0 {
14396 n = (*n).left;
14397 } else {
14398 n = (*n).right;
14399 }
14400 }
14401}
14402
14403#[no_mangle]
14404pub unsafe extern "C" fn tdelete(
14405 key: *const c_void,
14406 rootp: *mut *mut TreeNode,
14407 compar: ComparFn,
14408) -> *mut c_void {
14409 if rootp.is_null() {
14410 return core::ptr::null_mut();
14411 }
14412 let mut pp = rootp;
14413 loop {
14414 let n = *pp;
14415 if n.is_null() {
14416 return core::ptr::null_mut();
14417 }
14418 let c = compar.unwrap()(key, (*n).key);
14419 if c == 0 {
14420 break;
14421 }
14422 if c < 0 {
14423 pp = &mut (*n).left;
14424 } else {
14425 pp = &mut (*n).right;
14426 }
14427 }
14428 let n = *pp;
14429 let parent = *rootp;
14431 if !(*n).left.is_null() {
14432 let mut q = &mut (*n).left;
14434 while !(*(*q)).right.is_null() {
14435 q = &mut (*(*q)).right;
14436 }
14437 let pred = *q;
14438 (*n).key = (*pred).key;
14440 *q = (*pred).left;
14442 free(pred as *mut c_void);
14443 } else {
14444 *pp = (*n).right;
14446 free(n as *mut c_void);
14447 }
14448 parent as *mut c_void
14449}
14450
14451#[no_mangle]
14452pub unsafe extern "C" fn twalk(
14453 root: *const TreeNode,
14454 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
14455) {
14456 unsafe fn walk(
14457 node: *const TreeNode,
14458 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
14459 depth: c_int,
14460 ) {
14461 if node.is_null() {
14462 return;
14463 }
14464 let is_leaf = (*node).left.is_null() && (*node).right.is_null();
14465 if is_leaf {
14466 action.unwrap()(node as *const c_void, 3, depth); } else {
14468 action.unwrap()(node as *const c_void, 0, depth); walk((*node).left, action, depth + 1);
14470 action.unwrap()(node as *const c_void, 1, depth); walk((*node).right, action, depth + 1);
14472 action.unwrap()(node as *const c_void, 2, depth); }
14474 }
14475 walk(root, action, 0);
14476}
14477
14478#[no_mangle]
14479pub unsafe extern "C" fn tdestroy(root: *mut TreeNode, freekey: Option<unsafe extern "C" fn(*mut c_void)>) {
14480 if root.is_null() {
14481 return;
14482 }
14483 tdestroy((*root).left, freekey);
14484 tdestroy((*root).right, freekey);
14485 if let Some(f) = freekey {
14486 f((*root).key as *mut c_void);
14487 }
14488 free(root as *mut c_void);
14489}
14490
14491const FNM_PATHNAME: c_int = 0x1;
14496const FNM_NOESCAPE: c_int = 0x2;
14497const FNM_PERIOD: c_int = 0x4;
14498const FNM_LEADING_DIR: c_int = 0x8;
14499const FNM_CASEFOLD: c_int = 0x10;
14500const FNM_NOMATCH: c_int = 1;
14501
14502const FNM_END: c_int = 0;
14503const FNM_STAR: c_int = -5;
14504const FNM_QUESTION: c_int = -4;
14505const FNM_BRACKET: c_int = -3;
14506const FNM_UNMATCHABLE: c_int = -2;
14507
14508fn ascii_tolower(c: u8) -> u8 {
14509 if c >= b'A' && c <= b'Z' { c + 32 } else { c }
14510}
14511
14512fn ascii_toupper(c: u8) -> u8 {
14513 if c >= b'a' && c <= b'z' { c - 32 } else { c }
14514}
14515
14516fn ascii_casefold(k: u8) -> u8 {
14517 let upper = ascii_toupper(k);
14518 if upper != k { upper } else { ascii_tolower(k) }
14519}
14520
14521unsafe fn pat_next(pat: *const u8, m: usize, flags: c_int) -> (c_int, usize) {
14524 if m == 0 || *pat == 0 {
14525 return (FNM_END, 0);
14526 }
14527 let mut p = pat;
14528 let mut step = 1usize;
14529 let mut esc = false;
14530 if *p == b'\\' && !(flags & FNM_NOESCAPE != 0) && *p.add(1) != 0 {
14531 p = p.add(1);
14532 step = 2;
14533 esc = true;
14534 }
14535 if *p == b'[' && !esc {
14536 let mut k = 1usize;
14538 if k < m && (*pat.add(k) == b'^' || *pat.add(k) == b'!') { k += 1; }
14539 if k < m && *pat.add(k) == b']' { k += 1; }
14540 while k < m && *pat.add(k) != 0 && *pat.add(k) != b']' {
14541 if k + 1 < m && *pat.add(k) == b'[' &&
14542 (*pat.add(k+1) == b':' || *pat.add(k+1) == b'.' || *pat.add(k+1) == b'=') {
14543 let z = *pat.add(k+1);
14544 k += 2;
14545 if k < m { k += 1; }
14546 while k < m && *pat.add(k) != 0 && (*pat.add(k-1) != z || *pat.add(k) != b']') { k += 1; }
14547 if k == m || *pat.add(k) == 0 { break; }
14548 }
14549 k += 1;
14550 }
14551 if k == m || *pat.add(k) == 0 {
14552 return (b'[' as c_int, 1);
14554 }
14555 return (FNM_BRACKET, k + 1);
14556 }
14557 if *p == b'*' && !esc {
14558 return (FNM_STAR, 1);
14559 }
14560 if *p == b'?' && !esc {
14561 return (FNM_QUESTION, 1);
14562 }
14563 (*p as c_int, step)
14564}
14565
14566unsafe fn match_class(name: &[u8], k: u8, kfold: u8) -> bool {
14567 let eq = |c: u8| k == c || kfold == c;
14568 let in_range = |lo: u8, hi: u8| (k >= lo && k <= hi) || (kfold >= lo && kfold <= hi);
14569 match name {
14570 b"alnum" => in_range(b'0', b'9') || in_range(b'A', b'Z') || in_range(b'a', b'z'),
14571 b"alpha" => in_range(b'A', b'Z') || in_range(b'a', b'z'),
14572 b"blank" => eq(b' ') || eq(b'\t'),
14573 b"cntrl" => k < 0x20 || k == 0x7f,
14574 b"digit" => in_range(b'0', b'9'),
14575 b"graph" => k >= 0x21 && k <= 0x7e,
14576 b"lower" => in_range(b'a', b'z'),
14577 b"print" => k >= 0x20 && k <= 0x7e,
14578 b"punct" =>
14579 (k >= 0x21 && k <= 0x2f) ||
14580 (k >= 0x3a && k <= 0x40) ||
14581 (k >= 0x5b && k <= 0x60) ||
14582 (k >= 0x7b && k <= 0x7e),
14583 b"space" => eq(b' ') || eq(b'\t') || eq(b'\n') || eq(b'\r') || eq(0x0c) || eq(0x0b),
14584 b"upper" => in_range(b'A', b'Z'),
14585 b"xdigit" => in_range(b'0', b'9') || in_range(b'A', b'F') || in_range(b'a', b'f'),
14586 _ => false,
14587 }
14588}
14589
14590unsafe fn match_bracket(mut p: *const u8, k: u8, kfold: u8) -> bool {
14592 let mut inv = false;
14593 p = p.add(1); if *p == b'^' || *p == b'!' {
14595 inv = true;
14596 p = p.add(1);
14597 }
14598 if *p == b']' {
14600 if k == b']' { return !inv; }
14601 p = p.add(1);
14602 } else if *p == b'-' {
14603 if k == b'-' { return !inv; }
14604 p = p.add(1);
14605 }
14606 while *p != b']' && *p != 0 {
14607 if *p == b'-' && *p.add(1) != b']' && *p.add(1) != 0 {
14608 let lo = *p.sub(1);
14610 let hi = *p.add(1);
14611 if lo <= hi && (k >= lo && k <= hi || kfold >= lo && kfold <= hi) {
14612 return !inv;
14613 }
14614 p = p.add(2);
14615 } else if *p == b'[' && (*p.add(1) == b':' || *p.add(1) == b'.' || *p.add(1) == b'=') {
14616 let z = *p.add(1);
14617 let start = p.add(2);
14618 let mut q = start;
14619 while *q != 0 && (*q != z || *q.add(1) != b']') { q = q.add(1); }
14620 if *q != 0 {
14621 let len = (q as usize) - (start as usize);
14622 if len > 0 {
14623 let inner = core::slice::from_raw_parts(start, len);
14624 let matched =
14625 if z == b':' { match_class(inner, k, kfold) }
14626 else { len == 1 && (inner[0] == k || inner[0] == kfold) };
14627 if matched { return !inv; }
14628 }
14629 p = q.add(2);
14630 continue;
14631 }
14632 } else {
14633 if *p == k || *p == kfold {
14634 return !inv;
14635 }
14636 p = p.add(1);
14637 }
14638 }
14639 inv
14640}
14641
14642unsafe fn fnmatch_internal(pat: *const u8, str: *const u8, flags: c_int) -> c_int {
14644 if flags & FNM_PERIOD != 0 && *str == b'.' && *pat != b'.' {
14646 return FNM_NOMATCH;
14647 }
14648
14649 let mut p = pat;
14650 let mut s = str;
14651
14652 loop {
14654 let (tok, step) = pat_next(p, usize::MAX, flags);
14655 match tok {
14656 FNM_END => {
14657 return if *s == 0 { 0 } else { FNM_NOMATCH };
14658 }
14659 FNM_STAR => {
14660 p = p.add(1);
14661 break;
14662 }
14663 FNM_QUESTION => {
14664 if *s == 0 { return FNM_NOMATCH; }
14665 s = s.add(1);
14666 p = p.add(step);
14667 }
14668 FNM_BRACKET => {
14669 if *s == 0 { return FNM_NOMATCH; }
14670 let k = *s;
14671 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14672 if !match_bracket(p, k, kfold) { return FNM_NOMATCH; }
14673 p = p.add(step);
14674 s = s.add(1);
14675 }
14676 c => {
14677 if *s == 0 { return FNM_NOMATCH; }
14678 let k = *s;
14679 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14680 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14681 p = p.add(step);
14682 s = s.add(1);
14683 }
14684 }
14685 }
14686
14687 let mut ptail = p;
14690 let mut tailcnt: usize = 0;
14691 let mut pp = p;
14692 loop {
14693 let (tok, step) = pat_next(pp, usize::MAX, flags);
14694 if tok == FNM_END { break; }
14695 if tok == FNM_STAR {
14696 tailcnt = 0;
14697 ptail = pp.add(1);
14698 } else {
14699 tailcnt += 1;
14700 }
14701 pp = pp.add(step);
14702 }
14703
14704 let slen = strlen(s as *const c_char);
14706 if slen < tailcnt { return FNM_NOMATCH; }
14707
14708 let stail = s.add(slen - tailcnt);
14710 let mut tp = ptail;
14711 let mut ts = stail;
14712 loop {
14713 let (tok, step) = pat_next(tp, usize::MAX, flags);
14714 tp = tp.add(step);
14715 if tok == FNM_END {
14716 break;
14717 }
14718 let k = *ts;
14719 if k == 0 { return FNM_NOMATCH; }
14720 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14721 match tok {
14722 FNM_QUESTION => { ts = ts.add(1); }
14723 FNM_BRACKET => {
14724 if !match_bracket(tp.sub(step), k, kfold) { return FNM_NOMATCH; }
14725 ts = ts.add(1);
14726 }
14727 c => {
14728 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14729 ts = ts.add(1);
14730 }
14731 }
14732 }
14733
14734 let endstr = stail;
14735 let endpat = ptail;
14736
14737 let mut cp = p;
14738 let mut cs = s;
14739 while cp < endpat {
14740 let (tok, step) = pat_next(cp, usize::MAX, flags);
14741 if tok == FNM_STAR {
14742 cp = cp.add(step);
14743 cs = s;
14744 continue;
14745 }
14746 let comp_start = cp;
14747 let mut ok = false;
14748 let mut try_s = cs;
14749 while try_s < endstr {
14750 let mut tmp_p = comp_start;
14751 let mut tmp_s = try_s;
14752 let mut matched = true;
14753 loop {
14754 let (t, st) = pat_next(tmp_p, usize::MAX, flags);
14755 if t == FNM_STAR || t == FNM_END {
14756 cp = tmp_p;
14757 cs = tmp_s;
14758 ok = true;
14759 break;
14760 }
14761 if *tmp_s == 0 {
14762 matched = false;
14763 break;
14764 }
14765 let k = *tmp_s;
14766 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14767 match t {
14768 FNM_QUESTION => {
14769 tmp_s = tmp_s.add(1);
14770 }
14771 FNM_BRACKET => {
14772 if !match_bracket(tmp_p, k, kfold) {
14773 matched = false;
14774 break;
14775 }
14776 tmp_s = tmp_s.add(1);
14777 }
14778 c => {
14779 if k as c_int != c && kfold as c_int != c {
14780 matched = false;
14781 break;
14782 }
14783 tmp_s = tmp_s.add(1);
14784 }
14785 }
14786 tmp_p = tmp_p.add(st);
14787 }
14788 if ok { break; }
14789 if !matched {
14790 try_s = try_s.add(1);
14791 }
14792 }
14793 if !ok {
14794 return FNM_NOMATCH;
14795 }
14796 }
14797 0
14798}
14799
14800#[no_mangle]
14801pub unsafe extern "C" fn fnmatch(pat: *const c_char, str: *const c_char, flags: c_int) -> c_int {
14802 let pat = pat as *const u8;
14803 let str = str as *const u8;
14804
14805 if flags & FNM_PATHNAME != 0 {
14806 let mut s = str;
14808 let mut p = pat;
14809 loop {
14810 let mut send = s;
14812 while *send != 0 && *send != b'/' { send = send.add(1); }
14813 let mut pend = p;
14815 loop {
14816 let (tok, step) = pat_next(pend, usize::MAX, flags);
14817 if tok == FNM_END || (tok >= 0 && tok as u8 == b'/') {
14818 break;
14819 }
14820 pend = pend.add(step);
14821 }
14822 let (ptok, pstep) = pat_next(pend, usize::MAX, flags);
14823 let pat_is_slash = ptok >= 0 && ptok as u8 == b'/';
14824 let str_is_slash = *send == b'/';
14825 if pat_is_slash != str_is_slash && (*send != 0 || !(flags & FNM_LEADING_DIR != 0)) {
14826 return FNM_NOMATCH;
14827 }
14828 let plen = (pend as usize) - (p as usize);
14831 let slen = (send as usize) - (s as usize);
14832 if plen > 1024 || slen > 1024 { return FNM_NOMATCH; }
14835 let mut pbuf = [0u8; 1025];
14836 let mut sbuf = [0u8; 1025];
14837 core::ptr::copy_nonoverlapping(p, pbuf.as_mut_ptr(), plen);
14838 pbuf[plen] = 0;
14839 core::ptr::copy_nonoverlapping(s, sbuf.as_mut_ptr(), slen);
14840 sbuf[slen] = 0;
14841 if fnmatch_internal(pbuf.as_ptr(), sbuf.as_ptr(), flags & !FNM_LEADING_DIR) != 0 {
14842 return FNM_NOMATCH;
14843 }
14844 if !pat_is_slash {
14845 return 0;
14846 }
14847 s = send.add(1);
14848 p = pend.add(pstep);
14849 }
14850 }
14851
14852 if flags & FNM_LEADING_DIR != 0 {
14853 let mut s = str;
14855 while *s != 0 {
14856 if *s == b'/' {
14857 let len = (s as usize) - (str as usize);
14860 if len < 4096 {
14862 let mut buf = [0u8; 4096];
14863 core::ptr::copy_nonoverlapping(str, buf.as_mut_ptr(), len);
14864 buf[len] = 0;
14865 if fnmatch_internal(pat, buf.as_ptr(), flags) == 0 {
14866 return 0;
14867 }
14868 }
14869 }
14870 s = s.add(1);
14871 }
14872 }
14873
14874 fnmatch_internal(pat, str, flags)
14875}
14876
14877#[no_mangle]
14882pub unsafe extern "C" fn setmntent(name: *const c_char, mode: *const c_char) -> *mut FILE {
14883 fopen(name, mode)
14884}
14885
14886#[no_mangle]
14887pub unsafe extern "C" fn endmntent(f: *mut FILE) -> c_int {
14888 if !f.is_null() {
14889 fclose(f);
14890 }
14891 1
14892}
14893
14894static mut MNTENT_MNT: MntEnt = MntEnt {
14896 mnt_fsname: core::ptr::null_mut(),
14897 mnt_dir: core::ptr::null_mut(),
14898 mnt_type: core::ptr::null_mut(),
14899 mnt_opts: core::ptr::null_mut(),
14900 mnt_freq: 0,
14901 mnt_passno: 0,
14902};
14903
14904#[repr(C)]
14905pub struct MntEnt {
14906 mnt_fsname: *mut c_char,
14907 mnt_dir: *mut c_char,
14908 mnt_type: *mut c_char,
14909 mnt_opts: *mut c_char,
14910 mnt_freq: c_int,
14911 mnt_passno: c_int,
14912}
14913
14914unsafe fn unescape_ent(beg: *mut c_char) -> *mut c_char {
14915 let mut dest = beg;
14916 let mut src = beg;
14917 while *src != 0 {
14918 if *src != b'\\' as c_char {
14919 *dest = *src;
14920 dest = dest.add(1);
14921 src = src.add(1);
14922 continue;
14923 }
14924 if *src.add(1) == b'\\' as c_char {
14926 src = src.add(1);
14927 *dest = *src;
14928 dest = dest.add(1);
14929 src = src.add(1);
14930 continue;
14931 }
14932 let mut val: u8 = 0;
14934 let mut cnt = 0;
14935 let mut sp = src.add(1);
14936 while cnt < 3 && *sp >= b'0' as c_char && *sp <= b'7' as c_char {
14937 val = val * 8 + (*sp as u8 - b'0');
14938 sp = sp.add(1);
14939 cnt += 1;
14940 }
14941 if cnt > 0 {
14942 *dest = val as c_char;
14943 dest = dest.add(1);
14944 src = sp;
14945 } else {
14946 *dest = *src;
14947 dest = dest.add(1);
14948 src = src.add(1);
14949 }
14950 }
14951 *dest = 0;
14952 beg
14953}
14954
14955unsafe fn parse_mntent_line(
14956 linebuf: *mut c_char,
14957 mnt: *mut MntEnt,
14958) -> *mut MntEnt {
14959 let _len = strlen(linebuf as *const c_char);
14960 let mut p = linebuf;
14963 while *p == b' ' as c_char || *p == b'\t' as c_char || *p == b'\n' as c_char || *p == b'\r' as c_char {
14965 p = p.add(1);
14966 }
14967 if *p == 0 || *p == b'#' as c_char {
14968 return core::ptr::null_mut();
14969 }
14970
14971 (*mnt).mnt_fsname = p;
14973 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14974 p = p.add(1);
14975 }
14976 if *p == 0 { return core::ptr::null_mut(); }
14977 *p = 0;
14978 p = p.add(1);
14979 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14980
14981 (*mnt).mnt_dir = p;
14983 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14984 p = p.add(1);
14985 }
14986 if *p == 0 { return core::ptr::null_mut(); }
14987 *p = 0;
14988 p = p.add(1);
14989 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14990
14991 (*mnt).mnt_type = p;
14993 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14994 p = p.add(1);
14995 }
14996 if *p == 0 { return core::ptr::null_mut(); }
14997 *p = 0;
14998 p = p.add(1);
14999 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
15000
15001 (*mnt).mnt_opts = p;
15003 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
15004 p = p.add(1);
15005 }
15006 if *p != 0 {
15007 *p = 0;
15008 p = p.add(1);
15009 }
15010 if *(*mnt).mnt_opts == 0 {
15011 (*mnt).mnt_opts = b"defaults\0".as_ptr() as *mut c_char;
15012 }
15013
15014 (*mnt).mnt_freq = 0;
15016 (*mnt).mnt_passno = 0;
15017 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
15019 if *p >= b'0' as c_char && *p <= b'9' as c_char {
15020 (*mnt).mnt_freq = (*p - b'0' as c_char) as c_int;
15021 p = p.add(1);
15022 while *p >= b'0' as c_char && *p <= b'9' as c_char {
15023 (*mnt).mnt_freq = (*mnt).mnt_freq * 10 + (*p - b'0' as c_char) as c_int;
15024 p = p.add(1);
15025 }
15026 }
15027 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
15028 if *p >= b'0' as c_char && *p <= b'9' as c_char {
15029 (*mnt).mnt_passno = (*p - b'0' as c_char) as c_int;
15030 p = p.add(1);
15031 while *p >= b'0' as c_char && *p <= b'9' as c_char {
15032 (*mnt).mnt_passno = (*mnt).mnt_passno * 10 + (*p - b'0' as c_char) as c_int;
15033 p = p.add(1);
15034 }
15035 }
15036
15037 unescape_ent((*mnt).mnt_fsname);
15039 unescape_ent((*mnt).mnt_dir);
15040 unescape_ent((*mnt).mnt_type);
15041 unescape_ent((*mnt).mnt_opts);
15042
15043 mnt
15044}
15045
15046static SENTINEL_PTR: usize = 1;
15049
15050unsafe fn mntent_fgetc(f: *mut FILE) -> c_int {
15052 fgetc(f)
15053}
15054
15055unsafe fn mntent_fgets(buf: *mut c_char, n: usize, f: *mut FILE) -> *mut c_char {
15056 if n == 0 { return core::ptr::null_mut(); }
15057 let max = n - 1;
15058 let mut i = 0usize;
15059 while i < max {
15060 let c = mntent_fgetc(f);
15061 if c == -1 { if i == 0 { return core::ptr::null_mut(); } break; }
15062 *buf.add(i) = c as c_char;
15063 i += 1;
15064 if c == b'\n' as c_int { break; }
15065 }
15066 *buf.add(i) = 0;
15067 buf
15068}
15069
15070#[no_mangle]
15071pub unsafe extern "C" fn getmntent_r(
15072 f: *mut FILE,
15073 mnt: *mut MntEnt,
15074 mut linebuf: *mut c_char,
15075 _buflen: c_int,
15076) -> *mut MntEnt {
15077 let use_internal = linebuf as usize == SENTINEL_PTR;
15078
15079 (*mnt).mnt_freq = 0;
15080 (*mnt).mnt_passno = 0;
15081
15082 static mut INTERNAL_BUF: [c_char; 4096] = [0; 4096];
15084
15085 loop {
15086 if use_internal {
15087 linebuf = core::ptr::addr_of_mut!(INTERNAL_BUF).cast::<c_char>();
15088 }
15089 let res = mntent_fgets(linebuf, 4096, f);
15090 if res.is_null() {
15091 return core::ptr::null_mut();
15092 }
15093 let mut has_newline = false;
15094 let mut p = linebuf;
15095 while *p != 0 { if *p == b'\n' as c_char { has_newline = true; break; } p = p.add(1); }
15096 if !has_newline {
15097 ERRNO!() = 34;
15098 return core::ptr::null_mut();
15099 }
15100 let result = parse_mntent_line(linebuf, mnt);
15101 if !result.is_null() {
15102 return result;
15103 }
15104 }
15105}
15106
15107#[no_mangle]
15108pub unsafe extern "C" fn getmntent(f: *mut FILE) -> *mut MntEnt {
15109 getmntent_r(f, core::ptr::addr_of_mut!(MNTENT_MNT), SENTINEL_PTR as *mut c_char, 0)
15110}
15111
15112#[no_mangle]
15113pub unsafe extern "C" fn addmntent(f: *mut FILE, mnt: *const MntEnt) -> c_int {
15114 fseek(f, 0, 2); let written = fprintf(
15116 f,
15117 b"%s\t%s\t%s\t%s\t%d\t%d\n\0".as_ptr() as *const c_char,
15118 (*mnt).mnt_fsname,
15119 (*mnt).mnt_dir,
15120 (*mnt).mnt_type,
15121 (*mnt).mnt_opts,
15122 (*mnt).mnt_freq,
15123 (*mnt).mnt_passno,
15124 );
15125 if written < 0 { 1 } else { 0 }
15126}
15127
15128#[no_mangle]
15129pub unsafe extern "C" fn hasmntopt(mnt: *const MntEnt, opt: *const c_char) -> *mut c_char {
15130 let l = strlen(opt as *const c_char);
15131 let mut p = (*mnt).mnt_opts;
15132 loop {
15133 if strncmp(p as *const u8, opt as *const u8, l) == 0 {
15134 let after = *p.add(l);
15135 if after == 0 || after == b',' as c_char || after == b'=' as c_char {
15136 return p;
15137 }
15138 }
15139 let comma = strchr(p as *const u8, b',' as c_int);
15140 if comma.is_null() {
15141 return core::ptr::null_mut();
15142 }
15143 p = comma.add(1) as *mut c_char;
15144 }
15145}
15146
15147const EEXIST: c_int = 17;
15155const ENAMETOOLONG: c_int = 36;
15156const EMFILE: c_int = 24;
15157const EIDRM: c_int = 43;
15158
15159#[inline]
15160unsafe fn sys_msgget(key: c_int, msgflg: c_int) -> i64 {
15161 <Arch as Syscalls>::syscall2(SYS_MSGGET, key as i64, msgflg as i64)
15162}
15163
15164#[inline]
15165unsafe fn sys_msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> i64 {
15166 <Arch as Syscalls>::syscall4(SYS_MSGSND, msqid as i64, msgp as i64, msgsz as i64, msgflg as i64)
15167}
15168
15169#[inline]
15170unsafe fn sys_msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> i64 {
15171 <Arch as Syscalls>::syscall5(SYS_MSGRCV, msqid as i64, msgp as i64, msgsz as i64, msgtyp as i64, msgflg as i64)
15172}
15173
15174#[inline]
15175unsafe fn sys_msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
15176 <Arch as Syscalls>::syscall3(SYS_MSGCTL, msqid as i64, cmd as i64, buf as i64)
15177}
15178
15179#[inline]
15180unsafe fn sys_semget(key: c_int, nsems: c_int, semflg: c_int) -> i64 {
15181 <Arch as Syscalls>::syscall3(SYS_SEMGET, key as i64, nsems as i64, semflg as i64)
15182}
15183
15184#[inline]
15185unsafe fn sys_semop(semid: c_int, sops: *const c_void, nsops: usize) -> i64 {
15186 <Arch as Syscalls>::syscall3(SYS_SEMOP, semid as i64, sops as i64, nsops as i64)
15187}
15188
15189#[inline]
15190unsafe fn sys_semctl(semid: c_int, semnum: c_int, cmd: c_int, arg: *mut c_void) -> i64 {
15191 <Arch as Syscalls>::syscall4(SYS_SEMCTL, semid as i64, semnum as i64, cmd as i64, arg as i64)
15192}
15193
15194#[inline]
15195unsafe fn sys_shmget(key: c_int, size: usize, shmflg: c_int) -> i64 {
15196 <Arch as Syscalls>::syscall3(SYS_SHMGET, key as i64, size as i64, shmflg as i64)
15197}
15198
15199#[inline]
15200unsafe fn sys_shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> i64 {
15201 <Arch as Syscalls>::syscall3(SYS_SHMAT, shmid as i64, shmaddr as i64, shmflg as i64)
15202}
15203
15204#[inline]
15205unsafe fn sys_shmdt(shmaddr: *const c_void) -> i64 {
15206 <Arch as Syscalls>::syscall1(SYS_SHMDT, shmaddr as i64)
15207}
15208
15209#[inline]
15210unsafe fn sys_shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
15211 <Arch as Syscalls>::syscall3(SYS_SHMCTL, shmid as i64, cmd as i64, buf as i64)
15212}
15213
15214#[no_mangle]
15216pub unsafe extern "C" fn ftok(path: *const c_char, id: c_int) -> c_int {
15217 let mut st: kernel_stat64 = core::mem::zeroed();
15218 let r = sys_stat(path as *const u8, &mut st);
15219 if r < 0 {
15220 ERRNO!() = (-r) as c_int;
15221 return -1;
15222 }
15223 ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16) | (((id as u32 & 0xff) << 24)) as u64) as c_int
15224}
15225
15226#[no_mangle]
15228pub unsafe extern "C" fn msgget(key: c_int, msgflg: c_int) -> c_int {
15229 let r = sys_msgget(key, msgflg);
15230 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15231}
15232
15233#[no_mangle]
15235pub unsafe extern "C" fn msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> c_int {
15236 let r = sys_msgsnd(msqid, msgp, msgsz, msgflg);
15237 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15238}
15239
15240#[no_mangle]
15242pub unsafe extern "C" fn msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> isize {
15243 let r = sys_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
15244 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
15245}
15246
15247#[no_mangle]
15249pub unsafe extern "C" fn msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
15250 let r = sys_msgctl(msqid, cmd, buf);
15251 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15252}
15253
15254#[no_mangle]
15256pub unsafe extern "C" fn semget(key: c_int, nsems: c_int, semflg: c_int) -> c_int {
15257 if nsems > 65535 { ERRNO!() = 22; return -1; }
15258 let r = sys_semget(key, nsems, semflg);
15259 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15260}
15261
15262#[no_mangle]
15264pub unsafe extern "C" fn semop(semid: c_int, sops: *const c_void, nsops: usize) -> c_int {
15265 let r = sys_semop(semid, sops, nsops);
15266 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15267}
15268
15269#[no_mangle]
15271pub unsafe extern "C" fn semctl(semid: c_int, semnum: c_int, cmd: c_int, mut args: ...) -> c_int {
15272 let mut arg: *mut c_void = core::ptr::null_mut();
15273 match cmd {
15275 16 | 13 | 17 | 1 | 2 | 3 | 18 | 19 | 20 | 0x102 | 0x104 | 0x106 => {
15279 arg = args.next_arg::<*mut c_void>();
15280 }
15281 _ => {}
15282 }
15283 let r = sys_semctl(semid, semnum, cmd, arg);
15284 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15285}
15286
15287#[no_mangle]
15289pub unsafe extern "C" fn shmget(key: c_int, size: usize, shmflg: c_int) -> c_int {
15290 let r = sys_shmget(key, size, shmflg);
15291 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15292}
15293
15294#[no_mangle]
15296pub unsafe extern "C" fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void {
15297 let r = sys_shmat(shmid, shmaddr, shmflg);
15298 if (r as usize) > (-(4096isize as isize)) as usize {
15299 ERRNO!() = (-r) as c_int;
15300 return -1isize as *mut c_void;
15301 }
15302 r as *mut c_void
15303}
15304
15305#[no_mangle]
15307pub unsafe extern "C" fn shmdt(shmaddr: *const c_void) -> c_int {
15308 let r = sys_shmdt(shmaddr);
15309 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15310}
15311
15312#[no_mangle]
15314pub unsafe extern "C" fn shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
15315 let r = sys_shmctl(shmid, cmd, buf);
15316 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15317}
15318
15319#[no_mangle]
15329pub static mut __auxv: *const usize = core::ptr::null();
15330
15331#[no_mangle]
15332pub static mut __progname: *mut c_char = core::ptr::null_mut();
15333#[no_mangle]
15334pub static mut __progname_full: *mut c_char = core::ptr::null_mut();
15335#[no_mangle]
15336pub static mut program_invocation_name: *mut c_char = core::ptr::null_mut();
15337#[no_mangle]
15338pub static mut program_invocation_short_name: *mut c_char = core::ptr::null_mut();
15339
15340#[no_mangle]
15341pub static in6addr_any: [u8; 16] = [0; 16];
15342#[no_mangle]
15343pub static in6addr_loopback: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
15344
15345#[no_mangle]
15346pub static mut __daylight: c_int = 0;
15347#[no_mangle]
15348pub static mut __timezone: c_long = 0;
15349#[no_mangle]
15350pub static mut __tzname: [*mut c_char; 2] = [core::ptr::null_mut(); 2];
15351
15352#[no_mangle]
15353pub unsafe extern "C" fn getauxval(type_: c_ulong) -> c_ulong {
15354 let mut p = __auxv;
15355 if p.is_null() {
15356 return 0;
15357 }
15358 loop {
15359 let tag = *p;
15360 if tag == 0 {
15361 return 0;
15362 }
15363 if tag == type_ as usize {
15364 return *p.add(1) as c_ulong;
15365 }
15366 p = p.add(2);
15367 }
15368}
15369
15370type MainFn = unsafe extern "C" fn(c_int, *const *const c_char, *const *const c_char) -> c_int;
15371type InitFn = unsafe extern "C" fn();
15372
15373#[no_mangle]
15374pub unsafe extern "C" fn __libc_start_main(
15375 main: MainFn,
15376 argc: c_int,
15377 argv: *const *const c_char,
15378 _init: *const c_void,
15379 _fini: *const c_void,
15380 _rtld_fini: *const c_void,
15381 _stack_end: *const c_void,
15382) -> ! {
15383 errno_init();
15384
15385 let envp = argv.add((argc + 1) as usize);
15386 __environ = envp as *mut *mut c_char;
15387 environ = __environ; ___environ = __environ;
15389 _environ = __environ;
15390
15391 if !argv.is_null() && argc > 0 {
15393 let argv0 = *argv;
15394 __progname_full = argv0 as *mut c_char;
15395 program_invocation_name = argv0 as *mut c_char;
15396 let mut base = argv0;
15397 let mut p = argv0;
15398 while *p != 0 {
15399 if *p == b'/' as c_char { base = p.add(1); }
15400 p = p.add(1);
15401 }
15402 __progname = base as *mut c_char;
15403 program_invocation_short_name = base as *mut c_char;
15404 }
15405
15406 __stdio_init();
15407
15408 let mut set: SigSetT = 0;
15409 sigemptyset(&mut set);
15410 sigaddset(&mut set, SIGCANCEL);
15411 sigprocmask(SIG_UNBLOCK, &set, core::ptr::null_mut());
15412
15413 if !_init.is_null() {
15414 let init_fn: InitFn = core::mem::transmute(_init);
15415 init_fn();
15416 }
15417
15418 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
15422 {
15423 let random_ptr = getauxval(25) as *const u8; if !random_ptr.is_null() {
15425 let a = core::ptr::read_unaligned(random_ptr as *const u64);
15426 let b = core::ptr::read_unaligned(random_ptr.add(8) as *const u64);
15427 __stack_chk_guard = (a ^ b) as usize;
15428 } else {
15429 __stack_chk_guard = 0xdefaced_cafebeef;
15431 }
15432 }
15433
15434 let result = main(argc, argv, envp);
15435
15436 if !_fini.is_null() {
15437 let fini_fn: InitFn = core::mem::transmute(_fini);
15438 fini_fn();
15439 }
15440
15441 exit(result);
15442}
15443
15444type LdsoDlopenFn = unsafe extern "C" fn(*const c_char, c_int) -> *mut c_void;
15445type LdsoDlsymFn = unsafe extern "C" fn(*mut c_void, *const c_char, *mut c_void) -> *mut c_void;
15446type LdsoDlcloseFn = unsafe extern "C" fn(*mut c_void) -> c_int;
15447type LdsoDlerrorFn = unsafe extern "C" fn() -> *const c_char;
15448
15449static mut LDSO_DLOPEN: Option<LdsoDlopenFn> = None;
15450static mut LDSO_DLSYM: Option<LdsoDlsymFn> = None;
15451static mut LDSO_DLCLOSE: Option<LdsoDlcloseFn> = None;
15452static mut LDSO_DLERROR: Option<LdsoDlerrorFn> = None;
15453
15454#[no_mangle]
15455pub unsafe extern "C" fn __ldso_register_dlopen(f: LdsoDlopenFn) {
15456 LDSO_DLOPEN = Some(f);
15457}
15458
15459#[no_mangle]
15460pub unsafe extern "C" fn __ldso_register_dlsym(f: LdsoDlsymFn) {
15461 LDSO_DLSYM = Some(f);
15462}
15463
15464#[no_mangle]
15465pub unsafe extern "C" fn __ldso_register_dlclose(f: LdsoDlcloseFn) {
15466 LDSO_DLCLOSE = Some(f);
15467}
15468
15469#[no_mangle]
15470pub unsafe extern "C" fn __ldso_register_dlerror(f: LdsoDlerrorFn) {
15471 LDSO_DLERROR = Some(f);
15472}
15473
15474#[no_mangle]
15475pub unsafe extern "C" fn dlopen(filename: *const c_char, flags: c_int) -> *mut c_void {
15476 if let Some(f) = LDSO_DLOPEN {
15477 f(filename, flags)
15478 } else {
15479 null_mut()
15480 }
15481}
15482
15483#[no_mangle]
15484pub unsafe extern "C" fn dlsym_impl(
15485 handle: *mut c_void,
15486 symbol: *const c_char,
15487 ra: *mut c_void,
15488) -> *mut c_void {
15489 if let Some(f) = LDSO_DLSYM {
15490 f(handle, symbol, ra)
15491 } else {
15492 null_mut()
15493 }
15494}
15495
15496#[no_mangle]
15500#[unsafe(naked)]
15501#[cfg(target_arch = "x86_64")]
15502pub unsafe extern "C" fn dlsym(_handle: *mut c_void, _symbol: *const c_char) -> *mut c_void {
15503 core::arch::naked_asm!("mov rdx, [rsp]", "jmp dlsym_impl");
15504}
15505
15506#[no_mangle]
15507#[unsafe(naked)]
15508#[cfg(target_arch = "aarch64")]
15509pub unsafe extern "C" fn dlsym(_handle: *mut c_void, _symbol: *const c_char) -> *mut c_void {
15510 core::arch::naked_asm!("mov x2, x30", "b dlsym_impl");
15511}
15512
15513#[no_mangle]
15514#[unsafe(naked)]
15515#[cfg(target_arch = "riscv64")]
15516pub unsafe extern "C" fn dlsym(_handle: *mut c_void, _symbol: *const c_char) -> *mut c_void {
15517 core::arch::naked_asm!("mv a2, ra", "la t0, dlsym_impl", "jr t0");
15518}
15519
15520#[no_mangle]
15521pub unsafe extern "C" fn dlclose(handle: *mut c_void) -> c_int {
15522 if let Some(f) = LDSO_DLCLOSE {
15523 f(handle)
15524 } else {
15525 0
15526 }
15527}
15528
15529#[no_mangle]
15530pub unsafe extern "C" fn dlerror() -> *const c_char {
15531 if let Some(f) = LDSO_DLERROR {
15532 f()
15533 } else {
15534 core::ptr::null()
15535 }
15536}
15537
15538include!("crypt_impl.rs");
15539include!("statvfs.rs");
15540include!("daemon.rs");
15541include!("dn_expand.rs");
15542include!("lrand48.rs");
15543include!("strverscmp.rs");
15544include!("syscall.rs");
15545include!("pthread_atfork.rs");
15546include!("fenv.rs");
15547include!("locale_ctype.rs");
15548include!("regression_stubs.rs");
15549include!("netdb_extra.rs");
15550include!("compat_extra.rs");
15551include!("stdio_extra.rs");
15552include!("ns_parse.rs");
15553include!("fts.rs");
15554include!("ifaddrs.rs");
15555include!("dl_extra.rs");
15556include!("des.rs");
15557include!("path_extra.rs");
15558include!("wordexp.rs");
15559include!("getopt_impl.rs");
15560
15561type regoff_t = c_int;
15566
15567#[repr(C)]
15568pub struct regex_t {
15569 pub re_nsub: usize,
15570 pub __opaque: *mut c_void,
15571 pub __padding: [*mut c_void; 4],
15572 pub __nsub2: usize,
15573 pub __padding2: c_char,
15574}
15575
15576#[repr(C)]
15577pub struct regmatch_t {
15578 pub rm_so: regoff_t,
15579 pub rm_eo: regoff_t,
15580}
15581
15582include!("regex.rs");
15583
15584#[cfg(test)]
15585mod libc_unit_stub {
15586 #[test]
15587 fn stub() {
15588 assert!(true);
15589 }
15590}
15591
15592#[inline]
15597pub(crate) fn fmax_impl(x: f64, y: f64) -> f64 {
15598 if x.is_nan() { return y; }
15599 if y.is_nan() { return x; }
15600 if x == 0.0 && y == 0.0 {
15601 return if x.is_sign_negative() && y.is_sign_negative() { -0.0 } else { 0.0 };
15602 }
15603 if x > y { x } else { y }
15604}
15605
15606#[inline]
15607pub(crate) fn fmin_impl(x: f64, y: f64) -> f64 {
15608 if x.is_nan() { return y; }
15609 if y.is_nan() { return x; }
15610 if x == 0.0 && y == 0.0 {
15611 return if x.is_sign_negative() || y.is_sign_negative() { -0.0 } else { 0.0 };
15612 }
15613 if x < y { x } else { y }
15614}
15615
15616#[inline]
15617pub(crate) fn fmaxf_impl(x: f32, y: f32) -> f32 {
15618 if x.is_nan() { return y; }
15619 if y.is_nan() { return x; }
15620 if x == 0.0 && y == 0.0 {
15621 return if x.is_sign_negative() && y.is_sign_negative() { -0.0 } else { 0.0 };
15622 }
15623 if x > y { x } else { y }
15624}
15625
15626#[inline]
15627pub(crate) fn fminf_impl(x: f32, y: f32) -> f32 {
15628 if x.is_nan() { return y; }
15629 if y.is_nan() { return x; }
15630 if x == 0.0 && y == 0.0 {
15631 return if x.is_sign_negative() || y.is_sign_negative() { -0.0 } else { 0.0 };
15632 }
15633 if x < y { x } else { y }
15634}
15635
15636#[inline(never)]
15637#[no_mangle]
15638pub unsafe extern "C" fn fmax(x: f64, y: f64) -> f64 {
15639 fmax_impl(x, y)
15640}
15641
15642#[inline(never)]
15643#[no_mangle]
15644pub unsafe extern "C" fn fmin(x: f64, y: f64) -> f64 {
15645 fmin_impl(x, y)
15646}
15647
15648#[no_mangle]
15649pub unsafe extern "C" fn fminf(x: f32, y: f32) -> f32 {
15650 fminf_impl(x, y)
15651}
15652
15653#[no_mangle]
15654pub unsafe extern "C" fn fdim(x: f64, y: f64) -> f64 {
15655 if x.is_nan() || y.is_nan() {
15656 return f64::NAN;
15657 }
15658 if x > y { x - y } else { 0.0 }
15659}
15660
15661#[no_mangle]
15662pub unsafe extern "C" fn fma(x: f64, y: f64, z: f64) -> f64 {
15663 if (x.is_infinite() && y == 0.0) || (y.is_infinite() && x == 0.0) {
15664 feraiseexcept(FE_INVALID);
15665 return f64::NAN;
15666 }
15667 if x.is_nan() || y.is_nan() || z.is_nan() {
15668 return f64::NAN;
15669 }
15670 let r = libm::fma(x, y, z);
15671 if r.is_nan() {
15673 feraiseexcept(FE_INVALID);
15674 }
15675 r
15676}
15677
15678#[no_mangle]
15679pub unsafe extern "C" fn ilogb(x: f64) -> i32 {
15680 if x.is_nan() {
15681 feraiseexcept(FE_INVALID);
15682 return -0x7fffffff - 1; }
15684 if x == 0.0 || x.is_infinite() {
15685 feraiseexcept(FE_INVALID);
15686 return if x == 0.0 { -0x7fffffff - 1 } else { 0x7fffffff };
15687 }
15688 let bits = x.to_bits();
15689 let exp = ((bits >> 52) & 0x7ff) as i32;
15690 if exp == 0 {
15691 let mut v = bits & 0xfffffffffffff;
15693 let mut e = -1022;
15694 while v < (1u64 << 52) { v <<= 1; e -= 1; }
15695 e
15696 } else {
15697 exp - 1023
15698 }
15699}
15700
15701#[no_mangle]
15702pub unsafe extern "C" fn logb(x: f64) -> f64 {
15703 if x.is_nan() { return x; }
15704 if x == 0.0 { return __math_divzero(1); }
15705 let bits = x.to_bits();
15706 let exp = ((bits >> 52) & 0x7ff) as i32;
15707 if exp == 0 {
15708 let mut v = bits & 0xfffffffffffff;
15710 let mut e = -1022i32;
15711 while v < (1u64 << 52) { v <<= 1; e -= 1; }
15712 e as f64
15713 } else if exp == 0x7ff {
15714 x * x } else {
15716 (exp - 1023) as f64
15717 }
15718}
15719
15720#[no_mangle]
15721pub unsafe extern "C" fn nearbyint(x: f64) -> f64 {
15722 let had_inexact = fetestexcept(FE_INEXACT) & FE_INEXACT != 0;
15723 let r = libm::rint(x);
15724 if !had_inexact {
15725 feclearexcept(FE_INEXACT);
15726 }
15727 r
15728}
15729
15730#[no_mangle]
15731pub unsafe extern "C" fn nextafter(x: f64, y: f64) -> f64 {
15732 if x.is_nan() || y.is_nan() { return x + y; }
15733 if x == 0.0 && y == 0.0 { return y; }
15734 if x == y { return x; }
15735 let r = libm::nextafter(x, y);
15736 if r.is_infinite() && x.is_finite() {
15737 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
15738 } else if r != x {
15739 let bits = r.to_bits();
15740 let is_subnormal = (bits & 0x7ff0000000000000) == 0 && (bits & 0xfffffffffffff) != 0;
15741 if r == 0.0 || is_subnormal {
15742 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
15743 }
15744 }
15745 r
15746}
15747
15748#[no_mangle]
15749pub unsafe extern "C" fn nexttoward(x: f64, y: f64) -> f64 {
15750 if x == 0.0 && y == 0.0 {
15752 return if y.is_sign_negative() { -0.0 } else { 0.0 };
15753 }
15754 nextafter(x, y)
15755}
15756
15757#[no_mangle]
15758pub unsafe extern "C" fn remainder(x: f64, y: f64) -> f64 {
15759 if x.is_nan() || y.is_nan() { return x + y; }
15760 if y == 0.0 || x.is_infinite() { return __math_invalid(x); }
15761 libm::remainder(x, y)
15762}
15763
15764#[no_mangle]
15765pub unsafe extern "C" fn remquo(x: f64, y: f64, quo: *mut i32) -> f64 {
15766 if x.is_nan() || y.is_nan() {
15767 if !quo.is_null() { *quo = 0; }
15768 return x + y;
15769 }
15770 if y == 0.0 || x.is_infinite() {
15771 if !quo.is_null() { *quo = 0; }
15772 return __math_invalid(x);
15773 }
15774 let (r, q) = libm::remquo(x, y);
15775 if !quo.is_null() { *quo = q; }
15776 r
15777}
15778
15779#[no_mangle]
15780pub unsafe extern "C" fn exp2(x: f64) -> f64 {
15781 exp2_impl(x)
15782}
15783
15784#[no_mangle]
15785pub unsafe extern "C" fn expm1(x: f64) -> f64 {
15786 let r = libm::expm1(x);
15787 if r != 0.0 && x != 0.0 && libm::fabs(x) < 1e-307 {
15789 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
15790 }
15791 r
15792}
15793
15794#[no_mangle]
15795pub unsafe extern "C" fn log1p(x: f64) -> f64 {
15796 if x == -1.0 {
15797 feraiseexcept(FE_DIVBYZERO);
15798 return f64::NEG_INFINITY;
15799 }
15800 libm::log1p(x)
15801}
15802
15803#[no_mangle]
15804pub unsafe extern "C" fn acosh(x: f64) -> f64 {
15805 if x < 1.0 {
15806 feraiseexcept(FE_INVALID);
15807 return f64::NAN;
15808 }
15809 libm::acosh(x)
15810}
15811
15812#[no_mangle]
15813pub unsafe extern "C" fn asinh(x: f64) -> f64 {
15814 if x == 0.0 { return x; }
15815 libm::asinh(x)
15816}
15817
15818#[no_mangle]
15819pub unsafe extern "C" fn atanh(x: f64) -> f64 {
15820 if x == 0.0 { return x; }
15821 let e = ((x.to_bits() >> 52) & 0x7ff) as i32;
15822 if e < 0x3ff - 32 {
15823 feraiseexcept(FE_INEXACT);
15824 if e == 0 { feraiseexcept(FE_UNDERFLOW); }
15825 return x;
15826 }
15827 if x == 1.0 {
15828 feraiseexcept(FE_DIVBYZERO);
15829 return f64::INFINITY;
15830 }
15831 if x == -1.0 {
15832 feraiseexcept(FE_DIVBYZERO);
15833 return f64::NEG_INFINITY;
15834 }
15835 if x.is_nan() { return x; }
15836 let ax = libm::fabs(x);
15837 if ax > 1.0 {
15838 feraiseexcept(FE_INVALID);
15839 return f64::NAN;
15840 }
15841 if ax < 0.5 {
15842 let r = libm::log1p(2.0 * (ax + ax * ax / (1.0 - ax))) / 2.0;
15844 if x < 0.0 { -r } else { r }
15845 } else {
15846 let r = 0.5 * libm::log((1.0 + ax) / (1.0 - ax));
15848 if x < 0.0 { -r } else { r }
15849 }
15850}
15851
15852#[no_mangle]
15853pub unsafe extern "C" fn cbrt(x: f64) -> f64 {
15854 libm::cbrt(x)
15855}
15856
15857#[no_mangle]
15858pub unsafe extern "C" fn erf(x: f64) -> f64 {
15859 erf_impl(x)
15860}
15861
15862#[no_mangle]
15863pub unsafe extern "C" fn erfc(x: f64) -> f64 {
15864 erfc_impl(x)
15865}
15866
15867#[no_mangle]
15868pub unsafe extern "C" fn lgamma(x: f64) -> f64 {
15869 lgamma_impl(x)
15870}
15871
15872#[no_mangle]
15873pub unsafe extern "C" fn tgamma(x: f64) -> f64 {
15874 tgamma_impl(x)
15875}
15876
15877#[no_mangle]
15878pub unsafe extern "C" fn lround(x: f64) -> core::ffi::c_long {
15879 libm::round(x) as core::ffi::c_long
15880}
15881
15882#[no_mangle]
15883pub unsafe extern "C" fn llround(x: f64) -> i64 {
15884 libm::round(x) as i64
15885}
15886
15887#[no_mangle]
15894pub unsafe extern "C" fn cabs(z: (f64, f64)) -> f64 {
15895 libm::sqrt(z.0 * z.0 + z.1 * z.1)
15896}
15897
15898#[no_mangle]
15899pub unsafe extern "C" fn cabsf(z: (f32, f32)) -> f32 {
15900 libm::sqrtf(z.0 * z.0 + z.1 * z.1)
15901}
15902
15903#[no_mangle]
15904pub unsafe extern "C" fn cabsl(z: (f64, f64)) -> f64 {
15905 cabs(z)
15906}
15907
15908#[no_mangle]
15909pub unsafe extern "C" fn carg(z: (f64, f64)) -> f64 {
15910 libm::atan2(z.1, z.0)
15911}
15912
15913#[no_mangle]
15914pub unsafe extern "C" fn cargf(z: (f32, f32)) -> f32 {
15915 libm::atan2f(z.1, z.0)
15916}
15917
15918#[no_mangle]
15919pub unsafe extern "C" fn cargl(z: (f64, f64)) -> f64 {
15920 carg(z)
15921}
15922
15923#[no_mangle]
15924pub unsafe extern "C" fn cimag(z: (f64, f64)) -> f64 {
15925 z.1
15926}
15927
15928#[no_mangle]
15929pub unsafe extern "C" fn cimagf(z: (f32, f32)) -> f32 {
15930 z.1
15931}
15932
15933#[no_mangle]
15934pub unsafe extern "C" fn cimagl(z: (f64, f64)) -> f64 {
15935 z.1
15936}
15937
15938#[no_mangle]
15939pub unsafe extern "C" fn creal(z: (f64, f64)) -> f64 {
15940 z.0
15941}
15942
15943#[no_mangle]
15944pub unsafe extern "C" fn crealf(z: (f32, f32)) -> f32 {
15945 z.0
15946}
15947
15948#[no_mangle]
15949pub unsafe extern "C" fn creall(z: (f64, f64)) -> f64 {
15950 z.0
15951}
15952
15953#[no_mangle]
15954pub unsafe extern "C" fn conj(z: (f64, f64)) -> (f64, f64) {
15955 (z.0, -z.1)
15956}
15957
15958#[no_mangle]
15959pub unsafe extern "C" fn conjf(z: (f32, f32)) -> (f32, f32) {
15960 (z.0, -z.1)
15961}
15962
15963#[no_mangle]
15964pub unsafe extern "C" fn conjl(z: (f64, f64)) -> (f64, f64) {
15965 conj(z)
15966}
15967
15968#[no_mangle]
15969pub unsafe extern "C" fn cproj(z: (f64, f64)) -> (f64, f64) {
15970 if z.0.is_infinite() || z.1.is_infinite() {
15971 (f64::INFINITY, if z.1.is_sign_positive() { 0.0 } else { -0.0 })
15972 } else {
15973 z
15974 }
15975}
15976
15977#[no_mangle]
15978pub unsafe extern "C" fn cprojf(z: (f32, f32)) -> (f32, f32) {
15979 if z.0.is_infinite() || z.1.is_infinite() {
15980 (f32::INFINITY, if z.1.is_sign_positive() { 0.0 } else { -0.0 })
15981 } else {
15982 z
15983 }
15984}
15985
15986#[no_mangle]
15987pub unsafe extern "C" fn cprojl(z: (f64, f64)) -> (f64, f64) {
15988 cproj(z)
15989}
15990
15991#[no_mangle]
15993pub unsafe extern "C" fn cexp(z: (f64, f64)) -> (f64, f64) {
15994 let r = libm::exp(z.0);
15995 (r * libm::cos(z.1), r * libm::sin(z.1))
15996}
15997
15998#[no_mangle]
15999pub unsafe extern "C" fn cexpf(z: (f32, f32)) -> (f32, f32) {
16000 let r = libm::expf(z.0);
16001 (r * libm::cosf(z.1), r * libm::sinf(z.1))
16002}
16003
16004#[no_mangle]
16005pub unsafe extern "C" fn cexpl(z: (f64, f64)) -> (f64, f64) {
16006 cexp(z)
16007}
16008
16009#[no_mangle]
16011pub unsafe extern "C" fn clog(z: (f64, f64)) -> (f64, f64) {
16012 (libm::log(cabs(z)), carg(z))
16013}
16014
16015#[no_mangle]
16016pub unsafe extern "C" fn clogf(z: (f32, f32)) -> (f32, f32) {
16017 (libm::logf(cabsf(z)), cargf(z))
16018}
16019
16020#[no_mangle]
16021pub unsafe extern "C" fn clogl(z: (f64, f64)) -> (f64, f64) {
16022 clog(z)
16023}
16024
16025#[no_mangle]
16027pub unsafe extern "C" fn csqrt(z: (f64, f64)) -> (f64, f64) {
16028 let r = cabs(z);
16029 let sign = if z.1 < 0.0 { -1.0 } else { 1.0 };
16030 (libm::sqrt((r + z.0) / 2.0), sign * libm::sqrt((r - z.0) / 2.0))
16031}
16032
16033#[no_mangle]
16034pub unsafe extern "C" fn csqrtf(z: (f32, f32)) -> (f32, f32) {
16035 let r = cabsf(z);
16036 let sign = if z.1 < 0.0 { -1.0f32 } else { 1.0f32 };
16037 (libm::sqrtf((r + z.0) / 2.0), sign * libm::sqrtf((r - z.0) / 2.0))
16038}
16039
16040#[no_mangle]
16041pub unsafe extern "C" fn csqrtl(z: (f64, f64)) -> (f64, f64) {
16042 csqrt(z)
16043}
16044
16045#[no_mangle]
16047pub unsafe extern "C" fn cpow(z: (f64, f64), w: (f64, f64)) -> (f64, f64) {
16048 let log_z = clog(z);
16049 let exp_arg = (w.0 * log_z.0 - w.1 * log_z.1, w.0 * log_z.1 + w.1 * log_z.0);
16050 cexp(exp_arg)
16051}
16052
16053#[no_mangle]
16054pub unsafe extern "C" fn cpowf(z: (f32, f32), w: (f32, f32)) -> (f32, f32) {
16055 let log_z = clogf(z);
16056 let exp_arg = (w.0 * log_z.0 - w.1 * log_z.1, w.0 * log_z.1 + w.1 * log_z.0);
16057 cexpf(exp_arg)
16058}
16059
16060#[no_mangle]
16061pub unsafe extern "C" fn cpowl(z: (f64, f64), w: (f64, f64)) -> (f64, f64) {
16062 cpow(z, w)
16063}
16064
16065#[no_mangle]
16067pub unsafe extern "C" fn ccos(z: (f64, f64)) -> (f64, f64) {
16068 (libm::cos(z.0) * libm::cosh(z.1), -libm::sin(z.0) * libm::sinh(z.1))
16069}
16070
16071#[no_mangle]
16072pub unsafe extern "C" fn ccosf(z: (f32, f32)) -> (f32, f32) {
16073 (libm::cosf(z.0) * libm::coshf(z.1), -libm::sinf(z.0) * libm::sinhf(z.1))
16074}
16075
16076#[no_mangle]
16077pub unsafe extern "C" fn ccosl(z: (f64, f64)) -> (f64, f64) {
16078 ccos(z)
16079}
16080
16081#[no_mangle]
16083pub unsafe extern "C" fn csin(z: (f64, f64)) -> (f64, f64) {
16084 (libm::sin(z.0) * libm::cosh(z.1), libm::cos(z.0) * libm::sinh(z.1))
16085}
16086
16087#[no_mangle]
16088pub unsafe extern "C" fn csinf(z: (f32, f32)) -> (f32, f32) {
16089 (libm::sinf(z.0) * libm::coshf(z.1), libm::cosf(z.0) * libm::sinhf(z.1))
16090}
16091
16092#[no_mangle]
16093pub unsafe extern "C" fn csinl(z: (f64, f64)) -> (f64, f64) {
16094 csin(z)
16095}
16096
16097#[no_mangle]
16099pub unsafe extern "C" fn ctan(z: (f64, f64)) -> (f64, f64) {
16100 let d = libm::cos(2.0 * z.0) + libm::cosh(2.0 * z.1);
16101 (libm::sin(2.0 * z.0) / d, libm::sinh(2.0 * z.1) / d)
16102}
16103
16104#[no_mangle]
16105pub unsafe extern "C" fn ctanf(z: (f32, f32)) -> (f32, f32) {
16106 let d = libm::cosf(2.0 * z.0) + libm::coshf(2.0 * z.1);
16107 (libm::sinf(2.0 * z.0) / d, libm::sinhf(2.0 * z.1) / d)
16108}
16109
16110#[no_mangle]
16111pub unsafe extern "C" fn ctanl(z: (f64, f64)) -> (f64, f64) {
16112 ctan(z)
16113}
16114
16115#[no_mangle]
16117pub unsafe extern "C" fn ccosh(z: (f64, f64)) -> (f64, f64) {
16118 (libm::cosh(z.0) * libm::cos(z.1), libm::sinh(z.0) * libm::sin(z.1))
16119}
16120
16121#[no_mangle]
16122pub unsafe extern "C" fn ccoshf(z: (f32, f32)) -> (f32, f32) {
16123 (libm::coshf(z.0) * libm::cosf(z.1), libm::sinhf(z.0) * libm::sinf(z.1))
16124}
16125
16126#[no_mangle]
16127pub unsafe extern "C" fn ccoshl(z: (f64, f64)) -> (f64, f64) {
16128 ccosh(z)
16129}
16130
16131#[no_mangle]
16133pub unsafe extern "C" fn csinh(z: (f64, f64)) -> (f64, f64) {
16134 (libm::sinh(z.0) * libm::cos(z.1), libm::cosh(z.0) * libm::sin(z.1))
16135}
16136
16137#[no_mangle]
16138pub unsafe extern "C" fn csinhf(z: (f32, f32)) -> (f32, f32) {
16139 (libm::sinhf(z.0) * libm::cosf(z.1), libm::coshf(z.0) * libm::sinf(z.1))
16140}
16141
16142#[no_mangle]
16143pub unsafe extern "C" fn csinhl(z: (f64, f64)) -> (f64, f64) {
16144 csinh(z)
16145}
16146
16147#[no_mangle]
16149pub unsafe extern "C" fn ctanh(z: (f64, f64)) -> (f64, f64) {
16150 let d = libm::cosh(2.0 * z.0) + libm::cos(2.0 * z.1);
16151 (libm::sinh(2.0 * z.0) / d, libm::sin(2.0 * z.1) / d)
16152}
16153
16154#[no_mangle]
16155pub unsafe extern "C" fn ctanhf(z: (f32, f32)) -> (f32, f32) {
16156 let d = libm::coshf(2.0 * z.0) + libm::cosf(2.0 * z.1);
16157 (libm::sinhf(2.0 * z.0) / d, libm::sinf(2.0 * z.1) / d)
16158}
16159
16160#[no_mangle]
16161pub unsafe extern "C" fn ctanhl(z: (f64, f64)) -> (f64, f64) {
16162 ctanh(z)
16163}
16164
16165#[no_mangle]
16168pub unsafe extern "C" fn cacos(z: (f64, f64)) -> (f64, f64) {
16169 let asin_z = casin(z);
16170 (3.14159265358979323846264338327950288419716939937510582097494459230781640 / 2.0 - asin_z.0, -asin_z.1)
16171}
16172
16173#[no_mangle]
16174pub unsafe extern "C" fn cacosf(z: (f32, f32)) -> (f32, f32) {
16175 let asin_z = casinf(z);
16176 (3.14159265358979323846264338327950288419716939937510582097494459230781640f32 / 2.0 - asin_z.0, -asin_z.1)
16177}
16178
16179#[no_mangle]
16180pub unsafe extern "C" fn cacosl(z: (f64, f64)) -> (f64, f64) {
16181 cacos(z)
16182}
16183
16184#[no_mangle]
16186pub unsafe extern "C" fn casin(z: (f64, f64)) -> (f64, f64) {
16187 let iz = (-z.1, z.0);
16189 let one_minus_z2 = (1.0 - z.0 * z.0 + z.1 * z.1, -2.0 * z.0 * z.1);
16191 let sqrt_val = csqrt(one_minus_z2);
16192 let arg = clog((iz.0 + sqrt_val.0, iz.1 + sqrt_val.1));
16193 (arg.1, -arg.0)
16195}
16196
16197#[no_mangle]
16198pub unsafe extern "C" fn casinf(z: (f32, f32)) -> (f32, f32) {
16199 let iz = (-z.1, z.0);
16200 let one_minus_z2 = (1.0 - z.0 * z.0 + z.1 * z.1, -2.0 * z.0 * z.1);
16201 let sqrt_val = csqrtf(one_minus_z2);
16202 let arg = clogf((iz.0 + sqrt_val.0, iz.1 + sqrt_val.1));
16203 (arg.1, -arg.0)
16204}
16205
16206#[no_mangle]
16207pub unsafe extern "C" fn casinl(z: (f64, f64)) -> (f64, f64) {
16208 casin(z)
16209}
16210
16211#[no_mangle]
16213pub unsafe extern "C" fn catan(z: (f64, f64)) -> (f64, f64) {
16214 let num = (1.0 + z.1, -z.0);
16218 let den = (1.0 - z.1, z.0);
16219 let ratio = cdiv(num, den);
16220 let log_ratio = clog(ratio);
16221 (-log_ratio.1 / 2.0, log_ratio.0 / 2.0)
16223}
16224
16225#[no_mangle]
16226pub unsafe extern "C" fn catanf(z: (f32, f32)) -> (f32, f32) {
16227 let num = (1.0 + z.1, -z.0);
16228 let den = (1.0 - z.1, z.0);
16229 let ratio = cdivf(num, den);
16230 let log_ratio = clogf(ratio);
16231 (-log_ratio.1 / 2.0, log_ratio.0 / 2.0)
16232}
16233
16234#[no_mangle]
16235pub unsafe extern "C" fn catanl(z: (f64, f64)) -> (f64, f64) {
16236 catan(z)
16237}
16238
16239fn cdiv(a: (f64, f64), b: (f64, f64)) -> (f64, f64) {
16241 let d = b.0 * b.0 + b.1 * b.1;
16242 ((a.0 * b.0 + a.1 * b.1) / d, (a.1 * b.0 - a.0 * b.1) / d)
16243}
16244
16245fn cdivf(a: (f32, f32), b: (f32, f32)) -> (f32, f32) {
16246 let d = b.0 * b.0 + b.1 * b.1;
16247 ((a.0 * b.0 + a.1 * b.1) / d, (a.1 * b.0 - a.0 * b.1) / d)
16248}
16249
16250#[no_mangle]
16252pub unsafe extern "C" fn cacosh(z: (f64, f64)) -> (f64, f64) {
16253 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16254 let z2_minus_1 = (z2.0 - 1.0, z2.1);
16255 let sqrt_val = csqrt(z2_minus_1);
16256 clog((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16257}
16258
16259#[no_mangle]
16260pub unsafe extern "C" fn cacoshf(z: (f32, f32)) -> (f32, f32) {
16261 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16262 let z2_minus_1 = (z2.0 - 1.0, z2.1);
16263 let sqrt_val = csqrtf(z2_minus_1);
16264 clogf((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16265}
16266
16267#[no_mangle]
16268pub unsafe extern "C" fn cacoshl(z: (f64, f64)) -> (f64, f64) {
16269 cacosh(z)
16270}
16271
16272#[no_mangle]
16274pub unsafe extern "C" fn casinh(z: (f64, f64)) -> (f64, f64) {
16275 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16276 let z2_plus_1 = (z2.0 + 1.0, z2.1);
16277 let sqrt_val = csqrt(z2_plus_1);
16278 clog((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16279}
16280
16281#[no_mangle]
16282pub unsafe extern "C" fn casinhf(z: (f32, f32)) -> (f32, f32) {
16283 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16284 let z2_plus_1 = (z2.0 + 1.0, z2.1);
16285 let sqrt_val = csqrtf(z2_plus_1);
16286 clogf((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16287}
16288
16289#[no_mangle]
16290pub unsafe extern "C" fn casinhl(z: (f64, f64)) -> (f64, f64) {
16291 casinh(z)
16292}
16293
16294#[no_mangle]
16296pub unsafe extern "C" fn catanh(z: (f64, f64)) -> (f64, f64) {
16297 let num = (1.0 + z.0, z.1);
16298 let den = (1.0 - z.0, -z.1);
16299 let ratio = cdiv(num, den);
16300 let log_ratio = clog(ratio);
16301 (log_ratio.0 / 2.0, log_ratio.1 / 2.0)
16302}
16303
16304#[no_mangle]
16305pub unsafe extern "C" fn catanhf(z: (f32, f32)) -> (f32, f32) {
16306 let num = (1.0 + z.0, z.1);
16307 let den = (1.0 - z.0, -z.1);
16308 let ratio = cdivf(num, den);
16309 let log_ratio = clogf(ratio);
16310 (log_ratio.0 / 2.0, log_ratio.1 / 2.0)
16311}
16312
16313#[no_mangle]
16314pub unsafe extern "C" fn catanhl(z: (f64, f64)) -> (f64, f64) {
16315 catanh(z)
16316}
16317
16318#[inline(never)]
16323#[no_mangle]
16324pub unsafe extern "C" fn fmaxf(x: f32, y: f32) -> f32 {
16325 fmaxf_impl(x, y)
16326}
16327
16328#[no_mangle]
16329pub unsafe extern "C" fn fdimf(x: f32, y: f32) -> f32 {
16330 if x.is_nan() || y.is_nan() {
16331 return f32::NAN;
16332 }
16333 if x > y { x - y } else { 0.0 }
16334}
16335
16336#[no_mangle]
16337pub unsafe extern "C" fn fmaf(x: f32, y: f32, z: f32) -> f32 {
16338 if (x.is_infinite() && y == 0.0) || (y.is_infinite() && x == 0.0) {
16339 feraiseexcept(FE_INVALID);
16340 return f32::NAN;
16341 }
16342 if x.is_nan() || y.is_nan() || z.is_nan() {
16343 return f32::NAN;
16344 }
16345 let r = libm::fmaf(x, y, z);
16346 if r.is_nan() {
16347 feraiseexcept(FE_INVALID);
16348 }
16349 r
16350}
16351
16352#[no_mangle]
16353pub unsafe extern "C" fn ilogbf(x: f32) -> i32 {
16354 if x.is_nan() {
16355 feraiseexcept(FE_INVALID);
16356 return -0x7fffffff - 1;
16357 }
16358 if x == 0.0 || x.is_infinite() {
16359 feraiseexcept(FE_INVALID);
16360 return if x == 0.0 { -0x7fffffff - 1 } else { 0x7fffffff };
16361 }
16362 let bits = x.to_bits();
16363 let exp = ((bits >> 23) & 0xff) as i32;
16364 if exp == 0 {
16365 let mut v = bits & 0x7fffff;
16366 let mut e = -126;
16367 while v < (1u32 << 23) { v <<= 1; e -= 1; }
16368 e
16369 } else {
16370 exp - 127
16371 }
16372}
16373
16374#[no_mangle]
16375pub unsafe extern "C" fn logbf(x: f32) -> f32 {
16376 if x.is_nan() { return x; }
16377 if x == 0.0 { return __math_divzerof(1); }
16378 let bits = x.to_bits();
16379 let exp = ((bits >> 23) & 0xff) as i32;
16380 if exp == 0 {
16381 let mut v = bits & 0x7fffff;
16382 let mut e = -126i32;
16383 while v < (1u32 << 23) { v <<= 1; e -= 1; }
16384 e as f32
16385 } else if exp == 0xff {
16386 x * x
16387 } else {
16388 (exp - 127) as f32
16389 }
16390}
16391
16392#[no_mangle]
16393pub unsafe extern "C" fn nearbyintf(x: f32) -> f32 {
16394 let had_inexact = fetestexcept(FE_INEXACT) & FE_INEXACT != 0;
16395 let r = libm::rintf(x);
16396 if !had_inexact {
16397 feclearexcept(FE_INEXACT);
16398 }
16399 r
16400}
16401
16402#[no_mangle]
16403pub unsafe extern "C" fn nextafterf(x: f32, y: f32) -> f32 {
16404 if x.is_nan() || y.is_nan() { return x + y; }
16405 if x == 0.0 && y == 0.0 { return y; }
16406 if x == y { return x; }
16407 let r = libm::nextafterf(x, y);
16408 if r.is_infinite() && x.is_finite() {
16409 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
16410 } else if r != x {
16411 let bits = r.to_bits();
16412 let is_subnormal = (bits & 0x7f800000) == 0 && (bits & 0x7fffff) != 0;
16413 if r == 0.0 || is_subnormal {
16414 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16415 }
16416 }
16417 r
16418}
16419
16420#[no_mangle]
16421#[cfg(target_arch = "x86_64")]
16422pub unsafe extern "C" fn nexttowardf(x: f32, y: f64) -> f32 {
16423 if y.is_nan() { return (x as f64 + y) as f32; }
16424 if x == 0.0 && y == 0.0 {
16425 return if y.is_sign_negative() { -0.0 } else { 0.0 };
16426 }
16427 if (x as f64) == y { return x; }
16428 nextafterf(x, if y > x as f64 { f32::INFINITY } else { f32::NEG_INFINITY })
16429}
16430
16431#[no_mangle]
16432#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
16433pub unsafe extern "C" fn nexttowardf(x: f32, y: f128) -> f32 {
16434 if y.is_nan() { return (x as f128 + y) as f32; }
16435 if (x as f128) == y { return x; }
16436 nextafterf(x, if y > x as f128 { f32::INFINITY } else { f32::NEG_INFINITY })
16437}
16438
16439#[no_mangle]
16440pub unsafe extern "C" fn remainderf(x: f32, y: f32) -> f32 {
16441 if x.is_nan() || y.is_nan() { return x + y; }
16442 if y == 0.0 || x.is_infinite() { return __math_invalidf(x); }
16443 libm::remainderf(x, y)
16444}
16445
16446#[no_mangle]
16447pub unsafe extern "C" fn remquof(x: f32, y: f32, quo: *mut i32) -> f32 {
16448 if x.is_nan() || y.is_nan() {
16449 if !quo.is_null() { *quo = 0; }
16450 return x + y;
16451 }
16452 if y == 0.0 || x.is_infinite() {
16453 if !quo.is_null() { *quo = 0; }
16454 return __math_invalidf(x);
16455 }
16456 let (r, q) = libm::remquof(x, y);
16457 if !quo.is_null() { *quo = q; }
16458 r
16459}
16460
16461#[no_mangle]
16462pub unsafe extern "C" fn exp2f(x: f32) -> f32 {
16463 if x == f32::INFINITY { return f32::INFINITY; }
16464 if x == f32::NEG_INFINITY { return 0.0; }
16465 if x.is_nan() { return f32::NAN; }
16466 let r = libm::exp2f(x);
16467 if r.is_infinite() && x.is_finite() {
16468 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
16469 } else if r == 0.0 && x < -149.0 {
16470 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16471 } else if r != 0.0 && x != libm::truncf(x) {
16472 let bits = r.to_bits();
16473 if (bits & 0x7f800000) == 0 {
16474 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16475 }
16476 }
16477 r
16478}
16479
16480#[no_mangle]
16481pub unsafe extern "C" fn expm1f(x: f32) -> f32 {
16482 libm::expm1f(x)
16483}
16484
16485#[no_mangle]
16486pub unsafe extern "C" fn log1pf(x: f32) -> f32 {
16487 if x == -1.0 {
16488 feraiseexcept(FE_DIVBYZERO);
16489 return f32::NEG_INFINITY;
16490 }
16491 libm::log1pf(x)
16492}
16493
16494#[no_mangle]
16495pub unsafe extern "C" fn acoshf(x: f32) -> f32 {
16496 if x < 1.0 {
16497 feraiseexcept(FE_INVALID);
16498 return f32::NAN;
16499 }
16500 libm::acoshf(x)
16501}
16502
16503#[no_mangle]
16504pub unsafe extern "C" fn asinhf(x: f32) -> f32 {
16505 if x == 0.0 { return x; }
16506 libm::asinhf(x)
16507}
16508
16509#[no_mangle]
16510pub unsafe extern "C" fn atanhf(x: f32) -> f32 {
16511 if x == 0.0 { return x; }
16512 let e = ((x.to_bits() >> 23) & 0xff) as i32;
16513 if e < 0x7f - 32 {
16514 feraiseexcept(FE_INEXACT);
16515 if e == 0 { feraiseexcept(FE_UNDERFLOW); }
16516 return x;
16517 }
16518 if x == 1.0 {
16519 feraiseexcept(FE_DIVBYZERO);
16520 return f32::INFINITY;
16521 }
16522 if x == -1.0 {
16523 feraiseexcept(FE_DIVBYZERO);
16524 return f32::NEG_INFINITY;
16525 }
16526 if x.is_nan() { return x; }
16527 let ax = libm::fabsf(x);
16528 if ax > 1.0 {
16529 feraiseexcept(FE_INVALID);
16530 return f32::NAN;
16531 }
16532 if ax < 0.5 {
16533 let r = libm::log1pf(2.0 * (ax + ax * ax / (1.0 - ax))) / 2.0;
16534 if x < 0.0 { -r } else { r }
16535 } else {
16536 let r = 0.5 * libm::logf((1.0 + ax) / (1.0 - ax));
16537 if x < 0.0 { -r } else { r }
16538 }
16539}
16540
16541#[no_mangle]
16542pub unsafe extern "C" fn cbrtf(x: f32) -> f32 {
16543 libm::cbrtf(x)
16544}
16545
16546#[no_mangle]
16547pub unsafe extern "C" fn erff(x: f32) -> f32 {
16548 libm::erff(x)
16549}
16550
16551#[no_mangle]
16552pub unsafe extern "C" fn erfcf(x: f32) -> f32 {
16553 libm::erfcf(x)
16554}
16555
16556#[no_mangle]
16557pub unsafe extern "C" fn lgammaf(x: f32) -> f32 {
16558 if x.is_nan() {
16559 crate::signgam = 1;
16560 return x;
16561 }
16562 if x == 0.0 {
16563 crate::signgam = if x.is_sign_negative() { -1 } else { 1 };
16564 feraiseexcept(FE_DIVBYZERO);
16565 return f32::INFINITY;
16566 }
16567 let (r, sign) = libm::lgammaf_r(x);
16568 crate::signgam = sign;
16569 r
16570}
16571
16572#[no_mangle]
16573pub unsafe extern "C" fn tgammaf(x: f32) -> f32 {
16574 if x.is_nan() { return x; }
16575 if x == 0.0 {
16576 feraiseexcept(FE_DIVBYZERO);
16577 return if x.is_sign_negative() { f32::NEG_INFINITY } else { f32::INFINITY };
16578 }
16579 if x.is_infinite() {
16580 return if x.is_sign_negative() { __math_invalidf(x) } else { f32::INFINITY };
16581 }
16582 if x < 0.0 && x == libm::floorf(x) {
16583 feraiseexcept(FE_INVALID);
16584 return f32::NAN;
16585 }
16586 libm::tgammaf(x)
16587}
16588
16589#[no_mangle]
16590pub unsafe extern "C" fn lroundf(x: f32) -> core::ffi::c_long {
16591 libm::roundf(x) as core::ffi::c_long
16592}
16593
16594#[no_mangle]
16595pub unsafe extern "C" fn llroundf(x: f32) -> i64 {
16596 libm::roundf(x) as i64
16597}
16598
16599#[no_mangle]
16604pub unsafe extern "C" fn wcscasecmp(s1: *const u32, s2: *const u32) -> i32 {
16605 let mut i = 0;
16606 loop {
16607 let c1 = *s1.add(i);
16608 let c2 = *s2.add(i);
16609 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16610 let l1 = if c1 >= 'A' as u32 && c1 <= 'Z' as u32 { c1 + 32 } else { c1 };
16611 let l2 = if c2 >= 'A' as u32 && c2 <= 'Z' as u32 { c2 + 32 } else { c2 };
16612 if l1 != l2 { return (l1 as i32) - (l2 as i32); }
16613 i += 1;
16614 }
16615}
16616
16617#[no_mangle]
16618pub unsafe extern "C" fn wcscasecmp_l(s1: *const u32, s2: *const u32, _loc: *mut core::ffi::c_void) -> i32 {
16619 wcscasecmp(s1, s2)
16620}
16621
16622#[no_mangle]
16623pub unsafe extern "C" fn wcsncasecmp(s1: *const u32, s2: *const u32, n: usize) -> i32 {
16624 let mut i = 0;
16625 while i < n {
16626 let c1 = *s1.add(i);
16627 let c2 = *s2.add(i);
16628 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16629 let l1 = if c1 >= 'A' as u32 && c1 <= 'Z' as u32 { c1 + 32 } else { c1 };
16630 let l2 = if c2 >= 'A' as u32 && c2 <= 'Z' as u32 { c2 + 32 } else { c2 };
16631 if l1 != l2 { return (l1 as i32) - (l2 as i32); }
16632 i += 1;
16633 }
16634 0
16635}
16636
16637#[no_mangle]
16638pub unsafe extern "C" fn wcsncasecmp_l(s1: *const u32, s2: *const u32, n: usize, _loc: *mut core::ffi::c_void) -> i32 {
16639 wcsncasecmp(s1, s2, n)
16640}
16641
16642#[no_mangle]
16643pub unsafe extern "C" fn wcscoll(s1: *const u32, s2: *const u32) -> i32 {
16644 let mut i = 0;
16646 loop {
16647 let c1 = *s1.add(i);
16648 let c2 = *s2.add(i);
16649 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16650 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
16651 i += 1;
16652 }
16653}
16654
16655#[no_mangle]
16656pub unsafe extern "C" fn wcstok(s: *mut u32, sep: *const u32, p: *mut *mut u32) -> *mut u32 {
16657 let mut src = if s.is_null() { *p } else { s };
16658 while *src != 0 && *sep.add(0) == *src { src = src.add(1); }
16660 if *src == 0 { return core::ptr::null_mut(); }
16661 let start = src;
16662 while *src != 0 && *sep.add(0) != *src { src = src.add(1); }
16664 if *src != 0 {
16665 *src = 0;
16666 *p = src.add(1);
16667 } else {
16668 *p = src;
16669 }
16670 start
16671}
16672
16673#[no_mangle]
16674pub unsafe extern "C" fn wcswcs(haystack: *const u32, needle: *const u32) -> *mut u32 {
16675 if *needle == 0 { return haystack as *mut u32; }
16676 let mut i = 0;
16677 while *haystack.add(i) != 0 {
16678 let mut j = 0;
16679 while *needle.add(j) != 0 && *haystack.add(i + j) == *needle.add(j) {
16680 j += 1;
16681 }
16682 if *needle.add(j) == 0 { return haystack.add(i) as *mut u32; }
16683 i += 1;
16684 }
16685 core::ptr::null_mut()
16686}
16687
16688#[no_mangle]
16689pub unsafe extern "C" fn wcswidth(s: *const u32, n: usize) -> i32 {
16690 let mut width = 0i32;
16691 let mut i = 0;
16692 while i < n {
16693 let c = *s.add(i);
16694 if c == 0 { break; }
16695 width += 1;
16697 i += 1;
16698 }
16699 width
16700}
16701
16702#[no_mangle]
16703pub unsafe extern "C" fn wcsftime(s: *mut u32, maxsize: usize, fmt: *const u32, tm: *const c_void) -> usize {
16704 if s.is_null() || fmt.is_null() || maxsize == 0 { return 0; }
16705 let mut cfmt = [0u8; 1024];
16708 let mut o = 0usize;
16709 let mut i = 0usize;
16710 let mut st: c_uint = 0;
16711 while *fmt.add(i) != 0 && o + 8 < cfmt.len() {
16712 let n = wcrtomb(
16713 cfmt.as_mut_ptr().add(o) as *mut c_char,
16714 *fmt.add(i) as c_int,
16715 &mut st as *mut c_uint,
16716 );
16717 if n == !0usize { return 0; }
16718 o += n;
16719 i += 1;
16720 }
16721 cfmt[o] = 0;
16722 let mut out = [0u8; 4096];
16723 let mut lim = maxsize.saturating_mul(4);
16724 if lim > out.len() { lim = out.len(); }
16725 let n = strftime(out.as_mut_ptr() as *mut c_char, lim, cfmt.as_ptr() as *const c_char, tm as *const tm);
16726 if n == 0 { return 0; }
16727 let mut ws = 0usize;
16728 let mut p = 0usize;
16729 while p < n && ws + 1 < maxsize {
16730 let mut wc: c_int = 0;
16731 let mut st2: c_uint = 0;
16732 let r = mbrtowc(&mut wc, out.as_ptr().add(p) as *const c_char, n - p, &mut st2);
16733 if r == !0usize { return 0; }
16734 if r == 0 || r == !1usize { break; }
16735 *s.add(ws) = wc as u32;
16736 ws += 1;
16737 p += r;
16738 }
16739 *s.add(ws) = 0;
16740 ws
16741}
16742
16743#[no_mangle]
16744pub unsafe extern "C" fn mbsnrtowcs(
16745 dst: *mut u32,
16746 src: *mut *const u8,
16747 nms: usize,
16748 len: usize,
16749 st: *mut core::ffi::c_void,
16750) -> usize {
16751 if src.is_null() { return 0; }
16752 let mut s = *src;
16753 if s.is_null() { return 0; }
16754 let state = st as *mut c_uint;
16755 let limit = if dst.is_null() { usize::MAX } else { len };
16756 let mut count = 0usize;
16757 let mut n = nms;
16758 while count < limit && n > 0 {
16759 let c = *s;
16760 if c == 0 {
16761 if !dst.is_null() {
16762 if count < len { *dst.add(count) = 0; }
16763 *src = core::ptr::null();
16764 }
16765 return count;
16766 }
16767 let mut wc: c_int = 0;
16768 let r = mbrtowc(&mut wc, s as *const c_char, n, state);
16769 if r == !0usize {
16770 *src = s;
16771 return !0usize;
16772 }
16773 if r == !1usize { break; }
16774 if !dst.is_null() { *dst.add(count) = wc as u32; }
16775 count += 1;
16776 s = s.add(r);
16777 n -= r;
16778 }
16779 *src = s;
16780 count
16781}
16782
16783#[no_mangle]
16784pub unsafe extern "C" fn wcsnrtombs(dst: *mut u8, src: *mut *const u32, nwc: usize, len: usize, _st: *mut core::ffi::c_void) -> usize {
16785 let mut count = 0;
16786 let mut s = *src;
16787 let mut d = dst;
16788 while count < len && count < nwc {
16789 let c = *s;
16790 if c == 0 { break; }
16791 if !d.is_null() {
16792 if c < 0x80 {
16793 *d = c as u8;
16794 d = d.add(1);
16795 count += 1;
16796 } else if c < 0x800 {
16797 if count + 2 > len { break; }
16798 *d = 0xc0 | (c >> 6) as u8;
16799 *d.add(1) = 0x80 | (c & 0x3f) as u8;
16800 d = d.add(2);
16801 count += 2;
16802 } else if c < 0x10000 {
16803 if count + 3 > len { break; }
16804 *d = 0xe0 | (c >> 12) as u8;
16805 *d.add(1) = 0x80 | ((c >> 6) & 0x3f) as u8;
16806 *d.add(2) = 0x80 | (c & 0x3f) as u8;
16807 d = d.add(3);
16808 count += 3;
16809 } else {
16810 if count + 4 > len { break; }
16811 *d = 0xf0 | (c >> 18) as u8;
16812 *d.add(1) = 0x80 | ((c >> 12) & 0x3f) as u8;
16813 *d.add(2) = 0x80 | ((c >> 6) & 0x3f) as u8;
16814 *d.add(3) = 0x80 | (c & 0x3f) as u8;
16815 d = d.add(4);
16816 count += 4;
16817 }
16818 }
16819 s = s.add(1);
16820 }
16821 if !dst.is_null() { *src = s; }
16822 count
16823}
16824
16825pub type thrd_start_t = Option<unsafe extern "C" fn(arg: *mut core::ffi::c_void) -> i32>;
16832
16833#[no_mangle]
16835pub unsafe extern "C" fn thrd_create(thr: *mut usize, func: thrd_start_t, arg: *mut core::ffi::c_void) -> i32 {
16836 let mut thread: u64 = 0;
16837 let r = pthread_create(&mut thread, core::ptr::null(), core::mem::transmute(func), arg);
16838 if r == 0 {
16839 *thr = thread as usize;
16840 0 } else {
16842 -1 }
16844}
16845
16846#[no_mangle]
16847pub unsafe extern "C" fn thrd_join(thr: usize, res: *mut i32) -> i32 {
16848 let mut retval: *mut core::ffi::c_void = core::ptr::null_mut();
16849 let r = pthread_join(thr as u64, &mut retval);
16850 if r == 0 {
16851 if !res.is_null() { *res = retval as i32; }
16852 0
16853 } else {
16854 -1
16855 }
16856}
16857
16858#[no_mangle]
16859pub unsafe extern "C" fn thrd_exit(res: i32) {
16860 pthread_exit(res as *mut core::ffi::c_void);
16861}
16862
16863#[no_mangle]
16864pub unsafe extern "C" fn thrd_detach(thr: usize) -> i32 {
16865 let r = pthread_detach(thr as u64);
16866 if r == 0 { 0 } else { -1 }
16867}
16868
16869#[no_mangle]
16870pub unsafe extern "C" fn thrd_current() -> usize {
16871 pthread_self() as usize
16872}
16873
16874#[no_mangle]
16875pub unsafe extern "C" fn thrd_equal(thr1: usize, thr2: usize) -> i32 {
16876 (thr1 == thr2) as i32
16877}
16878
16879#[no_mangle]
16880pub unsafe extern "C" fn thrd_sleep(duration: *const core::ffi::c_void, remaining: *mut core::ffi::c_void) -> i32 {
16881 nanosleep(duration as *const timespec, remaining as *mut timespec)
16882}
16883
16884#[no_mangle]
16885pub unsafe extern "C" fn thrd_yield() {
16886 sched_yield();
16887}
16888
16889#[no_mangle]
16891pub unsafe extern "C" fn mtx_init(mtx: *mut usize, _mtx_type: i32) -> i32 {
16892 let r = pthread_mutex_init(mtx as *mut pthread_mutex_t, core::ptr::null());
16893 if r == 0 { 0 } else { -1 }
16894}
16895
16896#[no_mangle]
16897pub unsafe extern "C" fn mtx_lock(mtx: *mut usize) -> i32 {
16898 let r = pthread_mutex_lock(mtx as *mut pthread_mutex_t);
16899 if r == 0 { 0 } else { -1 }
16900}
16901
16902#[no_mangle]
16903pub unsafe extern "C" fn mtx_trylock(mtx: *mut usize) -> i32 {
16904 let r = pthread_mutex_trylock(mtx as *mut pthread_mutex_t);
16905 if r == 0 { 0 } else { -1 }
16906}
16907
16908#[no_mangle]
16909pub unsafe extern "C" fn mtx_unlock(mtx: *mut usize) -> i32 {
16910 let r = pthread_mutex_unlock(mtx as *mut pthread_mutex_t);
16911 if r == 0 { 0 } else { -1 }
16912}
16913
16914#[no_mangle]
16915pub unsafe extern "C" fn mtx_destroy(mtx: *mut usize) {
16916 pthread_mutex_destroy(mtx as *mut pthread_mutex_t);
16917}
16918
16919#[no_mangle]
16920pub unsafe extern "C" fn mtx_timedlock(mtx: *mut usize, ts: *const core::ffi::c_void) -> i32 {
16921 let r = pthread_mutex_timedlock(mtx as *mut pthread_mutex_t, ts as *const timespec);
16922 if r == 0 { 0 } else { -1 }
16923}
16924
16925#[no_mangle]
16927pub unsafe extern "C" fn cnd_init(cnd: *mut usize) -> i32 {
16928 let r = pthread_cond_init(cnd as *mut pthread_cond_t, core::ptr::null());
16929 if r == 0 { 0 } else { -1 }
16930}
16931
16932#[no_mangle]
16933pub unsafe extern "C" fn cnd_signal(cnd: *mut usize) -> i32 {
16934 let r = pthread_cond_signal(cnd as *mut pthread_cond_t);
16935 if r == 0 { 0 } else { -1 }
16936}
16937
16938#[no_mangle]
16939pub unsafe extern "C" fn cnd_broadcast(cnd: *mut usize) -> i32 {
16940 let r = pthread_cond_broadcast(cnd as *mut pthread_cond_t);
16941 if r == 0 { 0 } else { -1 }
16942}
16943
16944#[no_mangle]
16945pub unsafe extern "C" fn cnd_wait(cnd: *mut usize, mtx: *mut usize) -> i32 {
16946 let r = pthread_cond_wait(cnd as *mut pthread_cond_t, mtx as *mut pthread_mutex_t);
16947 if r == 0 { 0 } else { -1 }
16948}
16949
16950#[no_mangle]
16951pub unsafe extern "C" fn cnd_timedwait(cnd: *mut usize, mtx: *mut usize, ts: *const core::ffi::c_void) -> i32 {
16952 let r = pthread_cond_timedwait(cnd as *mut pthread_cond_t, mtx as *mut pthread_mutex_t, ts as *const timespec);
16953 if r == 0 { 0 } else { -1 }
16954}
16955
16956#[no_mangle]
16957pub unsafe extern "C" fn cnd_destroy(cnd: *mut usize) {
16958 pthread_cond_destroy(cnd as *mut pthread_cond_t);
16959}
16960
16961#[no_mangle]
16963pub unsafe extern "C" fn tss_create(key: *mut u32, dtor: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>) -> i32 {
16964 let r = pthread_key_create(key, dtor);
16965 if r == 0 { 0 } else { -1 }
16966}
16967
16968#[no_mangle]
16969pub unsafe extern "C" fn tss_delete(key: u32) {
16970 pthread_key_delete(key);
16971}
16972
16973#[no_mangle]
16974pub unsafe extern "C" fn tss_set(key: u32, val: *mut core::ffi::c_void) -> i32 {
16975 let r = pthread_setspecific(key, val);
16976 if r == 0 { 0 } else { -1 }
16977}
16978
16979#[no_mangle]
16980pub unsafe extern "C" fn tss_get(key: u32) -> *mut core::ffi::c_void {
16981 pthread_getspecific(key)
16982}
16983
16984#[no_mangle]
16986pub unsafe extern "C" fn call_once(flag: *mut u32, func: Option<unsafe extern "C" fn()>) {
16987 if *flag == 0 {
16988 if let Some(f) = func { f(); }
16989 *flag = 1;
16990 }
16991}
16992
16993#[no_mangle]
16999pub unsafe extern "C" fn accept4(fd: i32, addr: *mut core::ffi::c_void, addrlen: *mut u32, flags: i32) -> i32 {
17000 syscall_ret(<Arch as Syscalls>::syscall4(SYS_ACCEPT4, fd as i64, addr as i64, addrlen as i64, flags as i64)) as i32
17001}
17002
17003#[no_mangle]
17009pub unsafe extern "C" fn epoll_create(size: i32) -> i32 {
17010 #[cfg(target_arch = "x86_64")]
17011 { syscall_ret(<Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE, size as i64)) as i32 }
17012 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
17013 {
17014 if size < 1 {
17015 ERRNO!() = EINVAL;
17016 return -1;
17017 }
17018 syscall_ret(<Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE1, 0)) as i32
17019 }
17020}
17021
17022#[no_mangle]
17023pub unsafe extern "C" fn epoll_create1(flags: i32) -> i32 {
17024 syscall_ret(<Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE1, flags as i64)) as i32
17025}
17026
17027#[no_mangle]
17028pub unsafe extern "C" fn epoll_ctl(epfd: i32, op: i32, fd: i32, event: *mut core::ffi::c_void) -> i32 {
17029 syscall_ret(<Arch as Syscalls>::syscall4(SYS_EPOLL_CTL, epfd as i64, op as i64, fd as i64, event as i64)) as i32
17030}
17031
17032#[no_mangle]
17033pub unsafe extern "C" fn epoll_wait(epfd: i32, events: *mut core::ffi::c_void, maxevents: i32, timeout: i32) -> i32 {
17034 #[cfg(target_arch = "x86_64")]
17035 {
17036 syscall_ret(<Arch as Syscalls>::syscall4(
17037 SYS_EPOLL_WAIT,
17038 epfd as i64,
17039 events as i64,
17040 maxevents as i64,
17041 timeout as i64,
17042 )) as i32
17043 }
17044 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
17045 {
17046 epoll_pwait(epfd, events, maxevents, timeout, core::ptr::null())
17047 }
17048}
17049
17050#[no_mangle]
17051pub unsafe extern "C" fn epoll_pwait(
17052 epfd: i32,
17053 events: *mut core::ffi::c_void,
17054 maxevents: i32,
17055 timeout: i32,
17056 sigmask: *const u64,
17057) -> i32 {
17058 syscall_ret(<Arch as Syscalls>::syscall6(
17059 SYS_EPOLL_PWAIT,
17060 epfd as i64,
17061 events as i64,
17062 maxevents as i64,
17063 timeout as i64,
17064 sigmask as i64,
17065 8,
17066 )) as i32
17067}
17068
17069#[no_mangle]
17070pub unsafe extern "C" fn eventfd(initval: u32, flags: i32) -> i32 {
17071 syscall_ret(<Arch as Syscalls>::syscall2(SYS_EVENTFD2, initval as i64, flags as i64)) as i32
17072}
17073
17074#[no_mangle]
17075pub unsafe extern "C" fn eventfd_read(fd: i32, value: *mut u64) -> i32 {
17076 let n = crate::read(fd, value as *mut core::ffi::c_void, 8);
17077 if n == 8 { 0 } else { -1 }
17078}
17079
17080#[no_mangle]
17081pub unsafe extern "C" fn eventfd_write(fd: i32, value: u64) -> i32 {
17082 let n = crate::write(fd, &value as *const u64 as *const core::ffi::c_void, 8);
17083 if n == 8 { 0 } else { -1 }
17084}
17085
17086#[no_mangle]
17087pub unsafe extern "C" fn signalfd(fd: i32, mask: *const u64, flags: i32) -> i32 {
17088 syscall_ret(<Arch as Syscalls>::syscall4(SYS_SIGNALFD4, fd as i64, mask as i64, 8, flags as i64)) as i32
17089}
17090
17091#[no_mangle]
17092pub unsafe extern "C" fn timerfd_create(clockid: i32, flags: i32) -> i32 {
17093 syscall_ret(<Arch as Syscalls>::syscall2(SYS_TIMERFD_CREATE, clockid as i64, flags as i64)) as i32
17094}
17095
17096#[no_mangle]
17097pub 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 {
17098 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
17099}
17100
17101#[no_mangle]
17102pub unsafe extern "C" fn timerfd_gettime(fd: i32, curr_value: *mut core::ffi::c_void) -> i32 {
17103 syscall_ret(<Arch as Syscalls>::syscall2(SYS_TIMERFD_GETTIME, fd as i64, curr_value as i64)) as i32
17104}
17105
17106#[no_mangle]
17111pub unsafe extern "C" fn prctl(option: i32, mut args: ...) -> i32 {
17112 let a1 = args.next_arg::<i64>();
17113 let a2 = args.next_arg::<i64>();
17114 let a3 = args.next_arg::<i64>();
17115 let a4 = args.next_arg::<i64>();
17116 syscall_ret(<Arch as Syscalls>::syscall5(SYS_PRCTL, option as i64, a1, a2, a3, a4)) as i32
17117}
17118
17119#[no_mangle]
17120pub unsafe extern "C" fn quotactl(cmd: i32, special: *const core::ffi::c_char, id: i32, addr: *mut core::ffi::c_char) -> i32 {
17121 syscall_ret(<Arch as Syscalls>::syscall4(sysno(179, 60), cmd as i64, special as i64, id as i64, addr as i64)) as i32
17122}
17123
17124#[no_mangle]
17125pub unsafe extern "C" fn klogctl(type_: i32, bufp: *mut core::ffi::c_char, len: i32) -> i32 {
17126 syscall_ret(<Arch as Syscalls>::syscall3(sysno(103, 116), type_ as i64, bufp as i64, len as i64)) as i32
17127}
17128
17129static mut SYSLOG_IDENT: [core::ffi::c_char; 64] = [0; 64];
17130static mut SYSLOG_OPTIONS: i32 = 0;
17131static mut SYSLOG_FACILITY: i32 = 1;
17132
17133#[no_mangle]
17134pub unsafe extern "C" fn openlog(ident: *const core::ffi::c_char, option: i32, facility: i32) {
17135 SYSLOG_OPTIONS = option;
17136 SYSLOG_FACILITY = facility & 0x3f8;
17137 SYSLOG_IDENT[0] = 0;
17138 if !ident.is_null() {
17139 let mut i = 0;
17140 while i < 63 && *ident.add(i) != 0 {
17141 SYSLOG_IDENT[i] = *ident.add(i);
17142 i += 1;
17143 }
17144 SYSLOG_IDENT[i] = 0;
17145 }
17146}
17147
17148#[repr(C)]
17149struct SockAddrUn {
17150 sun_family: u16,
17151 sun_path: [core::ffi::c_char; 108],
17152}
17153
17154unsafe fn syslog_emit(priority: i32, msg: *const core::ffi::c_char, len: usize) {
17155 let mut out = [0u8; 1200];
17156 let mut o = 0usize;
17157 let pri = (SYSLOG_FACILITY | (priority & 7)) as u32;
17158 out[o] = b'<'; o += 1;
17159 if pri >= 100 { out[o] = b'0' + (pri / 100) as u8; o += 1; }
17160 if pri >= 10 { out[o] = b'0' + ((pri / 10) % 10) as u8; o += 1; }
17161 out[o] = b'0' + (pri % 10) as u8; o += 1;
17162 out[o] = b'>'; o += 1;
17163 let mut i = 0;
17164 while i < 63 && SYSLOG_IDENT[i] != 0 && o + 1 < out.len() {
17165 out[o] = SYSLOG_IDENT[i] as u8; o += 1; i += 1;
17166 }
17167 if SYSLOG_OPTIONS & 1 != 0 {
17168 out[o] = b'['; o += 1;
17169 let mut pid = crate::getpid() as u32;
17170 let mut digits = [0u8; 10];
17171 let mut d = 0;
17172 if pid == 0 { digits[0] = b'0'; d = 1; }
17173 while pid > 0 { digits[d] = b'0' + (pid % 10) as u8; pid /= 10; d += 1; }
17174 while d > 0 { d -= 1; out[o] = digits[d]; o += 1; }
17175 out[o] = b']'; o += 1;
17176 }
17177 out[o] = b':'; o += 1; out[o] = b' '; o += 1;
17178 let copy = core::cmp::min(len, out.len() - o - 1);
17179 core::ptr::copy_nonoverlapping(msg as *const u8, out.as_mut_ptr().add(o), copy);
17180 o += copy;
17181 let fd = crate::socket(AF_UNIX, SOCK_DGRAM, 0);
17182 if fd >= 0 {
17183 let mut sa: SockAddrUn = core::mem::zeroed();
17184 sa.sun_family = AF_UNIX as u16;
17185 let path = b"/dev/log";
17186 for i in 0..path.len() { sa.sun_path[i] = path[i] as core::ffi::c_char; }
17187 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);
17188 crate::close(fd);
17189 if r >= 0 { return; }
17190 }
17191 crate::write(2, out.as_ptr() as *const core::ffi::c_void, o);
17192 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
17193}
17194
17195#[no_mangle]
17196pub unsafe extern "C" fn vsyslog(priority: c_int, fmt: *const c_char, ap: VaList) {
17197 let mut msg = [0 as c_char; 1024];
17198 let n = vsnprintf(msg.as_mut_ptr(), msg.len(), fmt, ap);
17199 if n > 0 { syslog_emit(priority, msg.as_ptr(), core::cmp::min(n as usize, msg.len() - 1)); }
17200}
17201
17202#[no_mangle]
17203pub unsafe extern "C" fn syslog(priority: c_int, fmt: *const c_char, args: ...) {
17204 vsyslog(priority, fmt, args);
17205}
17206
17207#[no_mangle]
17208pub unsafe extern "C" fn closelog() {
17209 }
17211
17212#[no_mangle]
17213pub unsafe extern "C" fn setlogmask(mask: i32) -> i32 {
17214 static mut LOG_MASK: i32 = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80;
17215 let old = LOG_MASK;
17216 if mask != 0 { LOG_MASK = mask; }
17217 old
17218}
17219
17220#[no_mangle]
17221pub unsafe extern "C" fn acct(filename: *const core::ffi::c_char) -> i32 {
17222 syscall_ret(<Arch as Syscalls>::syscall1(SYS_ACCT, filename as i64)) as i32
17223}
17224
17225#[no_mangle]
17226pub unsafe extern "C" fn swapon(path: *const core::ffi::c_char, flags: i32) -> i32 {
17227 syscall_ret(<Arch as Syscalls>::syscall2(SYS_SWAPON, path as i64, flags as i64)) as i32
17228}
17229
17230#[no_mangle]
17231pub unsafe extern "C" fn swapoff(path: *const core::ffi::c_char) -> i32 {
17232 syscall_ret(<Arch as Syscalls>::syscall1(SYS_SWAPOFF, path as i64)) as i32
17233}
17234
17235#[no_mangle]
17236pub unsafe extern "C" fn syncfs(fd: i32) -> i32 {
17237 syscall_ret(<Arch as Syscalls>::syscall1(SYS_SYNCFS, fd as i64)) as i32
17238}
17239
17240#[no_mangle]
17241pub unsafe extern "C" fn sync_file_range(fd: i32, offset: i64, nbytes: u64, flags: u32) -> i32 {
17242 syscall_ret(<Arch as Syscalls>::syscall4(sysno(277, 84), fd as i64, offset, nbytes as i64, flags as i64)) as i32
17243}
17244
17245#[no_mangle]
17246pub unsafe extern "C" fn posix_fadvise(fd: i32, offset: i64, len: u64, advice: i32) -> i32 {
17247 let r = <Arch as Syscalls>::syscall4(sysno(221, 223), fd as i64, offset, len as i64, advice as i64);
17249 if r < 0 { (-r) as i32 } else { 0 }
17250}
17251
17252#[no_mangle]
17253pub unsafe extern "C" fn posix_fallocate(fd: i32, offset: i64, len: u64) -> i32 {
17254 let r = <Arch as Syscalls>::syscall3(SYS_FALLOCATE, fd as i64, offset, len as i64);
17255 if r < 0 { (-r) as i32 } else { 0 }
17256}
17257
17258#[no_mangle]
17259pub unsafe extern "C" fn readahead(fd: i32, offset: i64, count: usize) -> isize {
17260 syscall_ret(<Arch as Syscalls>::syscall3(sysno(187, 213), fd as i64, offset, count as i64)) as isize
17263}
17264
17265#[no_mangle]
17266pub unsafe extern "C" fn fallocate(fd: i32, mode: i32, offset: i64, len: u64) -> i32 {
17267 syscall_ret(<Arch as Syscalls>::syscall4(SYS_FALLOCATE, fd as i64, mode as i64, offset, len as i64)) as i32
17268}
17269
17270#[no_mangle]
17275pub unsafe extern "C" fn tcgetattr(fd: i32, termios_p: *mut core::ffi::c_void) -> i32 {
17276 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5401, termios_p as i64)) as i32
17277}
17278
17279#[no_mangle]
17280pub unsafe extern "C" fn tcsetattr(fd: i32, optional_actions: i32, termios_p: *const core::ffi::c_void) -> i32 {
17281 let cmd = match optional_actions {
17282 0 => 0x5402,
17283 1 => 0x5403,
17284 2 => 0x5404,
17285 _ => 0x5402,
17286 };
17287 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, cmd, termios_p as i64)) as i32
17288}
17289
17290#[no_mangle]
17291pub unsafe extern "C" fn tcdrain(fd: i32) -> i32 {
17292 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5409, 1)) as i32
17293}
17294
17295#[no_mangle]
17296pub unsafe extern "C" fn tcflush(fd: i32, queue_selector: i32) -> i32 {
17297 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540B, queue_selector as i64)) as i32
17298}
17299
17300#[no_mangle]
17301pub unsafe extern "C" fn tcflow(fd: i32, action: i32) -> i32 {
17302 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540A, action as i64)) as i32
17303}
17304
17305#[no_mangle]
17306pub unsafe extern "C" fn tcsendbreak(fd: i32, duration: i32) -> i32 {
17307 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5425, duration as i64)) as i32
17308}
17309
17310#[no_mangle]
17311pub unsafe extern "C" fn tcgetsid(fd: i32) -> i32 {
17312 let mut sid: i32 = 0;
17313 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5429, &mut sid as *mut i32 as i64);
17314 if r < 0 { -1 } else { sid }
17315}
17316
17317#[no_mangle]
17318pub unsafe extern "C" fn tcgetpgrp(fd: i32) -> i32 {
17319 let mut pgrp: i32 = 0;
17320 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540F, &mut pgrp as *mut i32 as i64);
17321 if r < 0 { -1 } else { pgrp }
17322}
17323
17324#[no_mangle]
17325pub unsafe extern "C" fn tcsetpgrp(fd: i32, pgrp: i32) -> i32 {
17326 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5410, &pgrp as *const i32 as i64)) as i32
17327}
17328
17329#[no_mangle]
17340pub unsafe extern "C" fn mq_open(name: *const core::ffi::c_char, oflag: i32, mut args: ...) -> i32 {
17341 if name.is_null() { ERRNO!() = EINVAL; return -1; }
17342 let mut p = name as *const u8;
17343 if *p == b'/' { p = p.add(1); }
17344 let mut mode: u32 = 0;
17345 let mut attr: *const core::ffi::c_void = core::ptr::null();
17346 if oflag & 0o100 != 0 {
17347 mode = args.next_arg::<u32>();
17348 attr = args.next_arg::<*const core::ffi::c_void>();
17349 }
17350 syscall_ret(<Arch as Syscalls>::syscall4(
17351 sysno(240, 180),
17352 p as i64,
17353 oflag as i64,
17354 mode as i64,
17355 attr as i64,
17356 )) as i32
17357}
17358
17359#[no_mangle]
17360pub unsafe extern "C" fn mq_close(mqdes: i32) -> i32 {
17361 crate::close(mqdes as i32)
17362}
17363
17364#[no_mangle]
17365pub unsafe extern "C" fn mq_unlink(name: *const core::ffi::c_char) -> i32 {
17366 if name.is_null() { ERRNO!() = EINVAL; return -1; }
17367 let mut p = name as *const u8;
17368 if *p == b'/' { p = p.add(1); }
17369 let r = <Arch as Syscalls>::syscall1(sysno(241, 181), p as i64);
17370 if r < 0 {
17371 let e = if (-r) as c_int == 1 { 13 } else { (-r) as c_int };
17373 ERRNO!() = e;
17374 -1
17375 } else {
17376 0
17377 }
17378}
17379
17380#[no_mangle]
17381pub unsafe extern "C" fn mq_send(mqdes: i32, msg_ptr: *const core::ffi::c_char, msg_len: usize, msg_prio: u32) -> i32 {
17382 mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, core::ptr::null())
17383}
17384
17385#[no_mangle]
17386pub unsafe extern "C" fn mq_receive(mqdes: i32, msg_ptr: *mut core::ffi::c_char, msg_len: usize, msg_prio: *mut u32) -> isize {
17387 mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, core::ptr::null())
17388}
17389
17390#[no_mangle]
17391pub unsafe extern "C" fn mq_timedsend(
17392 mqdes: i32,
17393 msg_ptr: *const core::ffi::c_char,
17394 msg_len: usize,
17395 msg_prio: u32,
17396 abs_timeout: *const core::ffi::c_void,
17397) -> i32 {
17398 syscall_ret(<Arch as Syscalls>::syscall5(
17399 sysno(242, 182),
17400 mqdes as i64,
17401 msg_ptr as i64,
17402 msg_len as i64,
17403 msg_prio as i64,
17404 abs_timeout as i64,
17405 )) as i32
17406}
17407
17408#[no_mangle]
17409pub unsafe extern "C" fn mq_timedreceive(
17410 mqdes: i32,
17411 msg_ptr: *mut core::ffi::c_char,
17412 msg_len: usize,
17413 msg_prio: *mut u32,
17414 abs_timeout: *const core::ffi::c_void,
17415) -> isize {
17416 syscall_ret(<Arch as Syscalls>::syscall5(
17417 sysno(243, 183),
17418 mqdes as i64,
17419 msg_ptr as i64,
17420 msg_len as i64,
17421 msg_prio as i64,
17422 abs_timeout as i64,
17423 )) as isize
17424}
17425
17426#[repr(C)]
17427pub struct SigEventFull {
17428 sigev_value: usize,
17429 sigev_signo: i32,
17430 sigev_notify: i32,
17431 sigev_function: usize,
17432 sigev_attributes: usize,
17433 sigev_pad: [u8; 32],
17434}
17435
17436struct MqNotifyArgs {
17437 sem: sem_t,
17438 sock: i32,
17439 mqd: i32,
17440 err: i32,
17441 func: usize,
17442 value: usize,
17443}
17444
17445unsafe extern "C" fn mq_notify_thread(arg: *mut c_void) -> *mut c_void {
17446 let a = &mut *(arg as *mut MqNotifyArgs);
17447 let sock = a.sock;
17448 let mqd = a.mqd;
17449 let func = a.func;
17450 let value = a.value;
17451 let zeros = [0u8; 32];
17452 let sev2 = SigEventFull {
17453 sigev_value: zeros.as_ptr() as usize,
17454 sigev_signo: sock,
17455 sigev_notify: 2, sigev_function: 0,
17457 sigev_attributes: 0,
17458 sigev_pad: [0; 32],
17459 };
17460 let r = <Arch as Syscalls>::syscall2(sysno(244, 184), mqd as i64, &sev2 as *const SigEventFull as i64);
17461 a.err = if r < 0 { (-r) as i32 } else { 0 };
17462 sem_post(&mut a.sem);
17463 if a.err != 0 { return core::ptr::null_mut(); }
17464 pthread_detach(pthread_self());
17465 let mut buf = [0u8; 32];
17466 let n = recv(sock, buf.as_mut_ptr() as *mut c_void, buf.len(), 0x4000 | 0x100);
17467 crate::close(sock);
17468 if n as usize == buf.len() && buf[buf.len() - 1] == 1 && func != 0 {
17469 let f: extern "C" fn(usize) = core::mem::transmute(func);
17470 f(value);
17471 }
17472 core::ptr::null_mut()
17473}
17474
17475#[no_mangle]
17476pub unsafe extern "C" fn mq_notify(mqdes: i32, sev: *const core::ffi::c_void) -> i32 {
17477 if sev.is_null() {
17478 return syscall_ret(<Arch as Syscalls>::syscall2(sysno(244, 184), mqdes as i64, 0)) as i32;
17479 }
17480 let ev = &*(sev as *const SigEventFull);
17481 if ev.sigev_notify != 2 {
17482 return syscall_ret(<Arch as Syscalls>::syscall2(sysno(244, 184), mqdes as i64, sev as i64)) as i32;
17483 }
17484
17485 let sock = socket(16 , 3 | 0x80000 , 0);
17488 if sock < 0 { return -1; }
17489 let mut a = MqNotifyArgs {
17490 sem: core::mem::zeroed(),
17491 sock,
17492 mqd: mqdes,
17493 err: 0,
17494 func: ev.sigev_function,
17495 value: ev.sigev_value,
17496 };
17497 sem_init(&mut a.sem, 0, 0);
17498
17499 let mut attr: pthread_attr_t = core::mem::zeroed();
17500 if ev.sigev_attributes != 0 {
17501 attr = core::ptr::read(ev.sigev_attributes as *const pthread_attr_t);
17502 } else {
17503 pthread_attr_init(&mut attr);
17504 }
17505 pthread_attr_setdetachstate(&mut attr, PTHREAD_CREATE_JOINABLE);
17506
17507 let mut all: SigSetT = 0;
17508 sigfillset(&mut all);
17509 let mut orig: SigSetT = 0;
17510 pthread_sigmask(0 , &all, &mut orig);
17511
17512 let mut td: PthreadT = 0;
17513 let r = pthread_create(&mut td, &attr, mq_notify_thread as *const () as usize, &mut a as *mut MqNotifyArgs as *mut c_void);
17514 pthread_sigmask(2 , &orig, core::ptr::null_mut());
17515 if r != 0 {
17516 crate::close(sock);
17517 ERRNO!() = 11;
17518 return -1;
17519 }
17520 sem_wait(&mut a.sem);
17521 sem_destroy(&mut a.sem);
17522 if a.err != 0 {
17523 crate::close(sock);
17524 pthread_join(td, core::ptr::null_mut());
17525 ERRNO!() = a.err;
17526 return -1;
17527 }
17528 0
17529}
17530
17531#[no_mangle]
17532pub unsafe extern "C" fn mq_getattr(mqdes: i32, attr: *mut core::ffi::c_void) -> i32 {
17533 mq_setattr(mqdes, core::ptr::null(), attr)
17534}
17535
17536#[no_mangle]
17537pub unsafe extern "C" fn mq_setattr(
17538 mqdes: i32,
17539 new: *const core::ffi::c_void,
17540 old: *mut core::ffi::c_void,
17541) -> i32 {
17542 syscall_ret(<Arch as Syscalls>::syscall3(
17543 sysno(245, 185),
17544 mqdes as i64,
17545 new as i64,
17546 old as i64,
17547 )) as i32
17548}
17549
17550#[no_mangle]
17555pub unsafe extern "C" fn pthread_getaffinity_np(thread: usize, cpusetsize: usize, cpuset: *mut u8) -> i32 {
17556 sched_getaffinity(thread as i32, cpusetsize, cpuset)
17557}
17558
17559#[no_mangle]
17560pub unsafe extern "C" fn pthread_setaffinity_np(thread: usize, cpusetsize: usize, cpuset: *const u8) -> i32 {
17561 sched_setaffinity(thread as i32, cpusetsize, cpuset)
17562}
17563
17564#[no_mangle]
17569pub unsafe extern "C" fn sched_yield() -> i32 {
17570 syscall_ret(<Arch as Syscalls>::syscall0(sysno(24, 124))) as i32
17571}
17572
17573#[no_mangle]
17574pub unsafe extern "C" fn sched_get_priority_max(policy: i32) -> i32 {
17575 syscall_ret(<Arch as Syscalls>::syscall1(sysno(146, 125), policy as i64)) as i32
17576}
17577
17578#[no_mangle]
17579pub unsafe extern "C" fn sched_get_priority_min(policy: i32) -> i32 {
17580 syscall_ret(<Arch as Syscalls>::syscall1(sysno(147, 126), policy as i64)) as i32
17581}
17582
17583#[no_mangle]
17584pub unsafe extern "C" fn sched_getparam(pid: i32, param: *mut core::ffi::c_void) -> i32 {
17585 syscall_ret(<Arch as Syscalls>::syscall2(sysno(143, 121), pid as i64, param as i64)) as i32
17586}
17587
17588#[no_mangle]
17589pub unsafe extern "C" fn sched_setparam(pid: i32, param: *const core::ffi::c_void) -> i32 {
17590 syscall_ret(<Arch as Syscalls>::syscall2(sysno(142, 118), pid as i64, param as i64)) as i32
17591}
17592
17593#[no_mangle]
17594pub unsafe extern "C" fn sched_getscheduler(pid: i32) -> i32 {
17595 syscall_ret(<Arch as Syscalls>::syscall1(sysno(145, 120), pid as i64)) as i32
17596}
17597
17598#[no_mangle]
17599pub unsafe extern "C" fn sched_setscheduler(pid: i32, policy: i32, param: *const core::ffi::c_void) -> i32 {
17600 syscall_ret(<Arch as Syscalls>::syscall3(sysno(144, 119), pid as i64, policy as i64, param as i64)) as i32
17601}
17602
17603#[no_mangle]
17604pub unsafe extern "C" fn sched_setaffinity(pid: i32, cpusetsize: usize, cpuset: *const u8) -> i32 {
17605 syscall_ret(<Arch as Syscalls>::syscall3(sysno(203, 122), pid as i64, cpusetsize as i64, cpuset as i64)) as i32
17606}
17607
17608#[no_mangle]
17609pub unsafe extern "C" fn sched_getaffinity(pid: i32, cpusetsize: usize, cpuset: *mut u8) -> i32 {
17610 let r = <Arch as Syscalls>::syscall3(sysno(204, 123), pid as i64, cpusetsize as i64, cpuset as i64);
17611 if r < 0 {
17612 ERRNO!() = (-r) as c_int;
17613 return -1;
17614 }
17615 0
17617}
17618
17619#[no_mangle]
17620pub unsafe extern "C" fn sched_getcpu() -> i32 {
17621 let mut cpu: i32 = 0;
17622 <Arch as Syscalls>::syscall3(sysno(309, 168), &mut cpu as *mut i32 as i64, 0, 0);
17623 cpu
17624}
17625
17626#[no_mangle]
17627pub unsafe extern "C" fn sched_rr_get_interval(pid: i32, tp: *mut core::ffi::c_void) -> i32 {
17628 syscall_ret(<Arch as Syscalls>::syscall2(sysno(148, 127), pid as i64, tp as i64)) as i32
17629}
17630
17631#[no_mangle]
17636pub unsafe extern "C" fn timer_create(clockid: i32, sevp: *mut core::ffi::c_void, timerid: *mut i32) -> i32 {
17637 syscall_ret(<Arch as Syscalls>::syscall3(sysno(222, 107), clockid as i64, sevp as i64, timerid as i64)) as i32
17638}
17639
17640#[no_mangle]
17641pub unsafe extern "C" fn timer_delete(timerid: i32) -> i32 {
17642 syscall_ret(<Arch as Syscalls>::syscall1(sysno(226, 111), timerid as i64)) as i32
17643}
17644
17645#[no_mangle]
17646pub 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 {
17647 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
17648}
17649
17650#[no_mangle]
17651pub unsafe extern "C" fn timer_gettime(timerid: i32, curr_value: *mut core::ffi::c_void) -> i32 {
17652 syscall_ret(<Arch as Syscalls>::syscall2(sysno(224, 108), timerid as i64, curr_value as i64)) as i32
17653}
17654
17655#[no_mangle]
17656pub unsafe extern "C" fn timer_getoverrun(timerid: i32) -> i32 {
17657 syscall_ret(<Arch as Syscalls>::syscall1(sysno(225, 109), timerid as i64)) as i32
17658}
17659
17660#[no_mangle]
17661pub unsafe extern "C" fn clock_adjtime(_clockid: i32, buf: *mut core::ffi::c_void) -> i32 {
17662 syscall_ret(<Arch as Syscalls>::syscall2(SYS_ADJTIMEX, buf as i64, 0)) as i32
17663}
17664
17665#[no_mangle]
17666pub unsafe extern "C" fn clock_getcpuclockid(pid: i32, clockid: *mut i32) -> i32 {
17667 if clockid.is_null() { return EINVAL; }
17668 let id: i32 = ((-(pid as i64) - 1) * 8 + 2) as i32;
17669 let mut ts: timespec = core::mem::zeroed();
17670 let r = <Arch as Syscalls>::syscall2(SYS_CLOCK_GETRES, id as i64, &mut ts as *mut timespec as i64);
17671 if r < 0 {
17672 let e = (-r) as c_int;
17673 return if e == EINVAL { 3 } else { e };
17674 }
17675 *clockid = id;
17676 0
17677}
17678
17679#[no_mangle]
17684pub unsafe extern "C" fn strcoll(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char) -> i32 {
17685 let mut i = 0;
17687 loop {
17688 let c1 = *s1.add(i) as u8;
17689 let c2 = *s2.add(i) as u8;
17690 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
17691 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
17692 i += 1;
17693 }
17694}
17695
17696#[no_mangle]
17697pub unsafe extern "C" fn strxfrm(dest: *mut core::ffi::c_char, src: *const core::ffi::c_char, n: usize) -> usize {
17698 let mut i = 0;
17699 while i < n {
17700 let c = *src.add(i);
17701 *dest.add(i) = c;
17702 if c == 0 { break; }
17703 i += 1;
17704 }
17705 i
17706}
17707
17708#[no_mangle]
17713pub 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 {
17714 let dir = opendir(dirp);
17715 if dir.is_null() { return -1; }
17716 let mut count = 0;
17717 loop {
17718 let ent = readdir(dir);
17719 if ent.is_null() { break; }
17720 count += 1;
17721 }
17722 closedir(dir);
17723 count
17724}
17725
17726#[no_mangle]
17727pub unsafe extern "C" fn alphasort(a: *const *const core::ffi::c_void, b: *const *const core::ffi::c_void) -> i32 {
17728 let s1 = *a as *const core::ffi::c_char;
17729 let s2 = *b as *const core::ffi::c_char;
17730 crate::strcmp(s1 as *const u8, s2 as *const u8)
17731}
17732
17733#[no_mangle]
17734pub unsafe extern "C" fn versionsort(a: *const *const core::ffi::c_void, b: *const *const core::ffi::c_void) -> i32 {
17735 let s1 = *a as *const core::ffi::c_char;
17736 let s2 = *b as *const core::ffi::c_char;
17737 crate::strcmp(s1 as *const u8, s2 as *const u8)
17738}
17739
17740unsafe fn vwarn_impl(fmt: *const c_char, ap: VaList, with_errno: bool) {
17748 let mut buf = [0 as c_char; 1024];
17749 let n = vsnprintf(buf.as_mut_ptr(), buf.len(), fmt, ap);
17750 if n > 0 {
17751 let l = core::cmp::min(n as usize, buf.len() - 1);
17752 crate::write(2, buf.as_ptr() as *const c_void, l);
17753 }
17754 if with_errno {
17755 let e = ERRNO!();
17756 crate::write(2, b": ".as_ptr() as *const c_void, 2);
17757 let msg = strerror(e);
17758 crate::write(2, msg as *const c_void, crate::strlen(msg));
17759 }
17760 crate::write(2, b"\n".as_ptr() as *const c_void, 1);
17761}
17762
17763#[no_mangle]
17764pub unsafe extern "C" fn verr(eval: c_int, fmt: *const c_char, ap: VaList) {
17765 vwarn_impl(fmt, ap, true);
17766 crate::exit(eval);
17767}
17768
17769#[no_mangle]
17770pub unsafe extern "C" fn verrx(eval: c_int, fmt: *const c_char, ap: VaList) {
17771 vwarn_impl(fmt, ap, false);
17772 crate::exit(eval);
17773}
17774
17775#[no_mangle]
17776pub unsafe extern "C" fn vwarn(fmt: *const c_char, ap: VaList) {
17777 vwarn_impl(fmt, ap, true);
17778}
17779
17780#[no_mangle]
17781pub unsafe extern "C" fn vwarnx(fmt: *const c_char, ap: VaList) {
17782 vwarn_impl(fmt, ap, false);
17783}
17784
17785#[no_mangle]
17786pub unsafe extern "C" fn err(eval: c_int, fmt: *const c_char, args: ...) {
17787 verr(eval, fmt, args);
17788}
17789
17790#[no_mangle]
17791pub unsafe extern "C" fn errx(eval: c_int, fmt: *const c_char, args: ...) {
17792 verrx(eval, fmt, args);
17793}
17794
17795#[no_mangle]
17796pub unsafe extern "C" fn warn(fmt: *const c_char, args: ...) {
17797 vwarn(fmt, args);
17798}
17799
17800#[no_mangle]
17801pub unsafe extern "C" fn warnx(fmt: *const c_char, args: ...) {
17802 vwarnx(fmt, args);
17803}
17804
17805#[no_mangle]
17810pub unsafe extern "C" fn ecvt(value: f64, ndigit: i32, decpt: *mut i32, sign: *mut i32) -> *mut core::ffi::c_char {
17811 static mut BUF: [core::ffi::c_char; 80] = [0; 80];
17812 if value < 0.0 { *sign = 1; } else { *sign = 0; }
17813 let v = if value < 0.0 { -value } else { value };
17814 if v == 0.0 { *decpt = 0; BUF[0] = 0; return BUF.as_mut_ptr(); }
17815 let mut d = 0i32;
17816 let mut tmp = v;
17817 while tmp >= 10.0 { tmp /= 10.0; d += 1; }
17818 while tmp < 1.0 { tmp *= 10.0; d -= 1; }
17819 *decpt = d + 1;
17820 let mut i = 0;
17821 let mut val = tmp;
17822 while i < ndigit as usize && i < 79 {
17823 let digit = val as i32;
17824 BUF[i] = (b'0' + digit as u8) as c_char;
17825 val = (val - digit as f64) * 10.0;
17826 i += 1;
17827 }
17828 BUF[i] = 0;
17829 BUF.as_mut_ptr()
17830}
17831
17832#[no_mangle]
17833pub unsafe extern "C" fn fcvt(value: f64, ndigit: i32, decpt: *mut i32, sign: *mut i32) -> *mut core::ffi::c_char {
17834 static mut BUF: [core::ffi::c_char; 80] = [0; 80];
17835 if value < 0.0 { *sign = 1; } else { *sign = 0; }
17836 let v = if value < 0.0 { -value } else { value };
17837 if v == 0.0 { *decpt = 0; BUF[0] = 0; return BUF.as_mut_ptr(); }
17838 let mut d = 0i32;
17839 let mut tmp = v;
17840 while tmp >= 10.0 { tmp /= 10.0; d += 1; }
17841 while tmp < 1.0 { tmp *= 10.0; d -= 1; }
17842 *decpt = d + 1;
17843 let mut val = tmp;
17844 let mut i = 0;
17845 while i < (*decpt) as usize && i < 79 {
17846 let digit = val as i32;
17847 BUF[i] = (b'0' + digit as u8) as c_char;
17848 val = (val - digit as f64) * 10.0;
17849 i += 1;
17850 }
17851 if ndigit > 0 && i < 79 {
17852 BUF[i] = '.' as c_char;
17853 i += 1;
17854 let mut frac = val;
17855 let mut j = 0;
17856 while j < ndigit as usize && i < 79 {
17857 let digit = frac as i32;
17858 BUF[i] = (b'0' + digit as u8) as c_char;
17859 frac = (frac - digit as f64) * 10.0;
17860 i += 1;
17861 j += 1;
17862 }
17863 }
17864 BUF[i] = 0;
17865 BUF.as_mut_ptr()
17866}
17867
17868#[no_mangle]
17869pub unsafe extern "C" fn gcvt(value: f64, _ndigit: i32, buf: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
17870 if value == 0.0 {
17872 *buf = '0' as c_char;
17873 *buf.add(1) = 0;
17874 return buf;
17875 }
17876 let mut i = 0;
17877 let v = if value < 0.0 { *buf = '-' as c_char; i = 1; -value } else { value };
17878 let mut int_part = v as i64;
17880 let mut digits = [0u8; 32];
17881 let mut di = 0;
17882 if int_part == 0 {
17883 digits[0] = 0;
17884 di = 1;
17885 } else {
17886 while int_part > 0 && di < 32 {
17887 digits[di] = (int_part % 10) as u8;
17888 int_part /= 10;
17889 di += 1;
17890 }
17891 }
17892 while di > 0 && i < 79 {
17893 di -= 1;
17894 *buf.add(i) = (b'0' + digits[di]) as c_char;
17895 i += 1;
17896 }
17897 *buf.add(i) = 0;
17898 buf
17899}
17900
17901static mut SHELLS: [*const core::ffi::c_char; 3] = [
17906 b"/bin/sh\0".as_ptr() as *const core::ffi::c_char,
17907 b"/bin/bash\0".as_ptr() as *const core::ffi::c_char,
17908 core::ptr::null(),
17909];
17910static mut SHELL_IDX: usize = 0;
17911
17912#[no_mangle]
17913pub unsafe extern "C" fn getusershell() -> *mut core::ffi::c_char {
17914 let s = SHELLS[SHELL_IDX];
17915 if s.is_null() {
17916 SHELL_IDX = 0;
17917 return core::ptr::null_mut();
17918 }
17919 SHELL_IDX += 1;
17920 s as *mut core::ffi::c_char
17921}
17922
17923#[no_mangle]
17924pub unsafe extern "C" fn setusershell() {
17925 SHELL_IDX = 0;
17926}
17927
17928#[no_mangle]
17929pub unsafe extern "C" fn endusershell() {
17930 SHELL_IDX = 0;
17931}
17932
17933#[no_mangle]
17938pub unsafe extern "C" fn ether_aton(s: *const core::ffi::c_char) -> *mut u8 {
17939 static mut EA: [u8; 6] = [0; 6];
17940 if ether_aton_r(s, EA.as_mut_ptr()).is_null() { core::ptr::null_mut() } else { EA.as_mut_ptr() }
17941}
17942
17943#[no_mangle]
17944pub unsafe extern "C" fn ether_aton_r(s: *const core::ffi::c_char, ea: *mut u8) -> *mut u8 {
17945 if ea.is_null() { return core::ptr::null_mut(); }
17946 let mut i = 0;
17947 let mut j = 0;
17948 let mut val: u32 = 0;
17949 let mut digits = 0;
17950 while *s.add(i) != 0 && j < 6 {
17951 let c = *s.add(i);
17952 if c == ':' as c_char {
17953 if digits == 0 { return core::ptr::null_mut(); }
17954 *ea.add(j) = val as u8;
17955 j += 1;
17956 val = 0;
17957 digits = 0;
17958 } 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) {
17959 let d = if c >= '0' as c_char && c <= '9' as c_char { (c - '0' as c_char) as u32 }
17960 else if c >= 'a' as c_char { (c - 'a' as c_char + 10) as u32 }
17961 else { (c - 'A' as c_char + 10) as u32 };
17962 val = val * 16 + d;
17963 if val > 255 { return core::ptr::null_mut(); }
17964 digits += 1;
17965 if digits > 2 { return core::ptr::null_mut(); }
17966 } else {
17967 return core::ptr::null_mut();
17968 }
17969 i += 1;
17970 }
17971 if digits == 0 || j != 5 { return core::ptr::null_mut(); }
17972 *ea.add(j) = val as u8;
17973 ea
17974}
17975
17976#[no_mangle]
17977pub unsafe extern "C" fn ether_ntoa(ea: *const u8) -> *mut core::ffi::c_char {
17978 static mut BUF: [core::ffi::c_char; 18] = [0; 18];
17979 ether_ntoa_r(ea, BUF.as_mut_ptr());
17980 BUF.as_mut_ptr()
17981}
17982
17983#[no_mangle]
17984pub unsafe extern "C" fn ether_ntoa_r(ea: *const u8, buf: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
17985 let a = *ea.add(0); let b = *ea.add(1); let c = *ea.add(2);
17986 let d = *ea.add(3); let e = *ea.add(4); let f = *ea.add(5);
17987 let hex = b"0123456789abcdef\0".as_ptr() as *const u8;
17988 let mut i = 0;
17989 *buf.add(i) = *hex.add((a >> 4) as usize) as c_char; i += 1;
17990 *buf.add(i) = *hex.add((a & 0xf) as usize) as c_char; i += 1;
17991 *buf.add(i) = ':' as c_char; i += 1;
17992 *buf.add(i) = *hex.add((b >> 4) as usize) as c_char; i += 1;
17993 *buf.add(i) = *hex.add((b & 0xf) as usize) as c_char; i += 1;
17994 *buf.add(i) = ':' as c_char; i += 1;
17995 *buf.add(i) = *hex.add((c >> 4) as usize) as c_char; i += 1;
17996 *buf.add(i) = *hex.add((c & 0xf) as usize) as c_char; i += 1;
17997 *buf.add(i) = ':' as c_char; i += 1;
17998 *buf.add(i) = *hex.add((d >> 4) as usize) as c_char; i += 1;
17999 *buf.add(i) = *hex.add((d & 0xf) as usize) as c_char; i += 1;
18000 *buf.add(i) = ':' as c_char; i += 1;
18001 *buf.add(i) = *hex.add((e >> 4) as usize) as c_char; i += 1;
18002 *buf.add(i) = *hex.add((e & 0xf) as usize) as c_char; i += 1;
18003 *buf.add(i) = ':' as c_char; i += 1;
18004 *buf.add(i) = *hex.add((f >> 4) as usize) as c_char; i += 1;
18005 *buf.add(i) = *hex.add((f & 0xf) as usize) as c_char; i += 1;
18006 *buf.add(i) = 0;
18007 buf
18008}
18009
18010#[no_mangle]
18015pub unsafe extern "C" fn getutxent() -> *mut core::ffi::c_void {
18016 getutent()
18017}
18018
18019#[no_mangle]
18020pub unsafe extern "C" fn getutxid(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
18021 getutid(ut)
18022}
18023
18024#[no_mangle]
18025pub unsafe extern "C" fn getutxline(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
18026 getutline(ut)
18027}
18028
18029#[no_mangle]
18030pub unsafe extern "C" fn pututxline(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
18031 pututline(ut)
18032}
18033
18034#[no_mangle]
18035pub unsafe extern "C" fn setutxent() {
18036 setutent()
18037}
18038
18039#[no_mangle]
18040pub unsafe extern "C" fn endutxent() {
18041 endutent()
18042}
18043
18044#[no_mangle]
18049pub unsafe extern "C" fn execv(path: *const core::ffi::c_char, argv: *const *const core::ffi::c_char) -> i32 {
18050 crate::execve(path, argv, __environ as *const *const core::ffi::c_char)
18051}
18052
18053#[no_mangle]
18054pub unsafe extern "C" fn execlp(file: *const core::ffi::c_char, _args: ...) -> i32 {
18055 let mut argv: [*const core::ffi::c_char; 64] = [core::ptr::null(); 64];
18057 let mut i = 0;
18058 let mut args = _args;
18059 loop {
18060 let arg = args.next_arg::<*const core::ffi::c_char>();
18061 if arg.is_null() { break; }
18062 argv[i] = arg;
18063 i += 1;
18064 if i >= 63 { break; }
18065 }
18066 argv[i] = core::ptr::null();
18067 execvp(file, argv.as_ptr())
18068}
18069
18070#[no_mangle]
18071pub unsafe extern "C" fn execvp(file: *const core::ffi::c_char, argv: *const *const core::ffi::c_char) -> i32 {
18072 execvpe(file, argv, __environ as *const *const core::ffi::c_char)
18073}
18074
18075#[no_mangle]
18076pub unsafe extern "C" fn fexecve(fd: i32, argv: *const *const core::ffi::c_char, envp: *const *const core::ffi::c_char) -> i32 {
18077 let mut path: [core::ffi::c_char; 64] = [0; 64];
18079 let mut i = 0;
18080 let src = b"/proc/self/fd/\0".as_ptr() as *const core::ffi::c_char;
18081 while i < 63 && *src.add(i) != 0 { path[i] = *src.add(i); i += 1; }
18082 let mut n = fd as usize;
18083 if n == 0 { path[i] = '0' as c_char; i += 1; }
18084 while n > 0 && i < 63 {
18085 path[i] = (b'0' + (n % 10) as u8) as c_char;
18086 n /= 10;
18087 i += 1;
18088 }
18089 path[i] = 0;
18090 crate::execve(path.as_ptr(), argv, envp)
18091}
18092
18093#[no_mangle]
18098pub unsafe extern "C" fn confstr(name: i32, buf: *mut core::ffi::c_char, len: usize) -> usize {
18099 let value: &[u8] = if name == 0 {
18102 b"/bin:/usr/bin"
18103 } else if (1..=37).contains(&name) {
18104 b""
18105 } else {
18106 ERRNO!() = EINVAL;
18107 return 0;
18108 };
18109 let need = value.len() + 1;
18110 if !buf.is_null() && len > 0 {
18111 let n = core::cmp::min(value.len(), len - 1);
18112 core::ptr::copy_nonoverlapping(value.as_ptr(), buf as *mut u8, n);
18113 *buf.add(n) = 0;
18114 }
18115 need
18116}
18117
18118#[no_mangle]
18119pub unsafe extern "C" fn pathconf(_path: *const core::ffi::c_char, name: i32) -> i64 {
18120 match name {
18122 0 => 4096, 1 => 255, 2 => 255, 3 => 255, 4 => 4096, 5 => 4096, 6 => 1, 7 => 0, 8 => 0, _ => -1,
18132 }
18133}
18134
18135#[no_mangle]
18136pub unsafe extern "C" fn fpathconf(_fd: i32, name: i32) -> i64 {
18137 match name {
18139 0 => 4096, 1 => 255, 2 => 255, 3 => 255, 4 => 4096, 5 => 4096, 6 => 1, 7 => 0, 8 => 0, _ => -1,
18149 }
18150}
18151
18152#[no_mangle]
18157pub unsafe extern "C" fn exp10(x: f64) -> f64 {
18158 libm::pow(10.0, x)
18159}
18160
18161#[no_mangle]
18162pub unsafe extern "C" fn exp10f(x: f32) -> f32 {
18163 libm::powf(10.0, x)
18164}
18165
18166#[no_mangle]
18171pub unsafe extern "C" fn explicit_bzero(s: *mut u8, n: usize) {
18172 core::ptr::write_bytes(s, 0, n);
18173 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
18174}
18175
18176#[no_mangle]
18177pub unsafe extern "C" fn memccpy(dest: *mut u8, src: *const u8, c: i32, n: usize) -> *mut u8 {
18178 let mut i = 0;
18179 while i < n {
18180 let byte = *src.add(i);
18181 *dest.add(i) = byte;
18182 if byte == c as u8 {
18183 return dest.add(i + 1);
18184 }
18185 i += 1;
18186 }
18187 core::ptr::null_mut()
18188}
18189
18190#[no_mangle]
18195pub unsafe extern "C" fn faccessat(dirfd: i32, pathname: *const core::ffi::c_char, mode: i32, flags: i32) -> i32 {
18196 syscall_ret(<Arch as Syscalls>::syscall4(SYS_FACCESSAT, dirfd as i64, pathname as i64, mode as i64, flags as i64)) as i32
18197}
18198
18199#[no_mangle]
18200pub unsafe extern "C" fn fchmodat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32, flags: i32) -> i32 {
18201 if flags == 0 {
18202 return syscall_ret(<Arch as Syscalls>::syscall4(SYS_FCHMODAT, dirfd as i64, pathname as i64, mode as i64, 0)) as i32;
18203 }
18204 if flags != 0x100 {
18205 ERRNO!() = EINVAL;
18207 return -1;
18208 }
18209 syscall_ret(<Arch as Syscalls>::syscall4(sysno(452, 452), dirfd as i64, pathname as i64, mode as i64, flags as i64)) as i32
18210}
18211
18212#[no_mangle]
18213pub unsafe extern "C" fn fchownat(dirfd: i32, pathname: *const core::ffi::c_char, uid: u32, gid: u32, flags: i32) -> i32 {
18214 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
18215}
18216
18217#[no_mangle]
18218pub unsafe extern "C" fn linkat(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char, flags: i32) -> i32 {
18219 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
18220}
18221
18222#[no_mangle]
18223pub unsafe extern "C" fn mkdirat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18224 syscall_ret(<Arch as Syscalls>::syscall3(SYS_MKDIRAT, dirfd as i64, pathname as i64, mode as i64)) as i32
18225}
18226
18227#[no_mangle]
18228pub unsafe extern "C" fn mkfifoat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18229 mknodat(dirfd, pathname, mode | 0o010000, 0)
18230}
18231
18232#[no_mangle]
18233pub unsafe extern "C" fn mknodat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32, dev: u64) -> i32 {
18234 syscall_ret(<Arch as Syscalls>::syscall4(sysno(259, 33), dirfd as i64, pathname as i64, mode as i64, dev as i64)) as i32
18235}
18236
18237#[no_mangle]
18238pub unsafe extern "C" fn readlinkat(dirfd: i32, pathname: *const core::ffi::c_char, buf: *mut core::ffi::c_char, bufsiz: usize) -> isize {
18239 syscall_ret(<Arch as Syscalls>::syscall4(SYS_READLINKAT, dirfd as i64, pathname as i64, buf as i64, bufsiz as i64)) as isize
18240}
18241
18242#[no_mangle]
18243pub unsafe extern "C" fn renameat(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char) -> i32 {
18244 syscall_ret(<Arch as Syscalls>::syscall5(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, 0)) as i32
18245}
18246
18247#[no_mangle]
18248pub unsafe extern "C" fn renameat2(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char, flags: u32) -> i32 {
18249 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
18250}
18251
18252#[no_mangle]
18253pub unsafe extern "C" fn symlinkat(target: *const core::ffi::c_char, newdirfd: i32, linkpath: *const core::ffi::c_char) -> i32 {
18254 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, newdirfd as i64, linkpath as i64)) as i32
18255}
18256
18257#[no_mangle]
18258pub unsafe extern "C" fn unlinkat(dirfd: i32, pathname: *const core::ffi::c_char, flags: i32) -> i32 {
18259 syscall_ret(<Arch as Syscalls>::syscall3(SYS_UNLINKAT, dirfd as i64, pathname as i64, flags as i64)) as i32
18260}
18261
18262#[no_mangle]
18263pub unsafe extern "C" fn utimes(filename: *const core::ffi::c_char, times: *const core::ffi::c_void) -> i32 {
18264 utimensat(AT_FDCWD, filename, times as *const timespec, 0)
18265}
18266
18267#[no_mangle]
18268pub unsafe extern "C" fn futimes(fd: i32, times: *const core::ffi::c_void) -> i32 {
18269 utimensat(fd, core::ptr::null(), times as *const timespec, 0)
18270}
18271
18272#[no_mangle]
18277pub unsafe extern "C" fn inotify_init() -> i32 {
18278 syscall_ret(<Arch as Syscalls>::syscall1(sysno(253, 26), 0)) as i32
18279}
18280
18281#[no_mangle]
18282pub unsafe extern "C" fn inotify_init1(flags: i32) -> i32 {
18283 syscall_ret(<Arch as Syscalls>::syscall1(sysno(294, 26), flags as i64)) as i32
18284}
18285
18286#[no_mangle]
18287pub unsafe extern "C" fn inotify_add_watch(fd: i32, pathname: *const core::ffi::c_char, mask: u32) -> i32 {
18288 syscall_ret(<Arch as Syscalls>::syscall3(sysno(254, 27), fd as i64, pathname as i64, mask as i64)) as i32
18289}
18290
18291#[no_mangle]
18292pub unsafe extern "C" fn inotify_rm_watch(fd: i32, wd: i32) -> i32 {
18293 syscall_ret(<Arch as Syscalls>::syscall2(sysno(255, 28), fd as i64, wd as i64)) as i32
18294}
18295
18296#[no_mangle]
18297pub unsafe extern "C" fn fanotify_init(flags: i32, event_f_flags: i32) -> i32 {
18298 syscall_ret(<Arch as Syscalls>::syscall2(sysno(300, 262), flags as i64, event_f_flags as i64)) as i32
18299}
18300
18301#[no_mangle]
18302pub unsafe extern "C" fn fanotify_mark(fd: i32, flags: i32, mask: u64, dirfd: i32, pathname: *const core::ffi::c_char) -> i32 {
18303 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
18304}
18305
18306#[no_mangle]
18311pub unsafe extern "C" fn ffs(x: i32) -> i32 {
18312 if x == 0 { return 0; }
18313 x.trailing_zeros() as i32 + 1
18314}
18315
18316#[no_mangle]
18317pub unsafe extern "C" fn ffsl(x: i64) -> i32 {
18318 if x == 0 { return 0; }
18319 x.trailing_zeros() as i32 + 1
18320}
18321
18322#[no_mangle]
18323pub unsafe extern "C" fn ffsll(x: i64) -> i32 {
18324 if x == 0 { return 0; }
18325 x.trailing_zeros() as i32 + 1
18326}
18327
18328#[no_mangle]
18333pub unsafe extern "C" fn fchdir(fd: i32) -> i32 {
18334 syscall_ret(<Arch as Syscalls>::syscall1(SYS_FCHDIR, fd as i64)) as i32
18335}
18336
18337#[no_mangle]
18338pub unsafe extern "C" fn fchown(fd: i32, uid: u32, gid: u32) -> i32 {
18339 syscall_ret(<Arch as Syscalls>::syscall3(SYS_FCHOWN, fd as i64, uid as i64, gid as i64)) as i32
18340}
18341
18342#[no_mangle]
18343pub unsafe extern "C" fn fdopendir(fd: i32) -> *mut core::ffi::c_void {
18344 if fd < 0 { ERRNO!() = 9; return core::ptr::null_mut(); }
18345 dir_stream_new(fd)
18346}
18347
18348#[no_mangle]
18349pub unsafe extern "C" fn getdtablesize() -> i32 {
18350 let mut rlim: Rlimit = core::mem::zeroed();
18351 if getrlimit(RLIMIT_NOFILE, &mut rlim) == 0 {
18352 rlim.rlim_cur as i32
18353 } else {
18354 1024
18355 }
18356}
18357
18358#[no_mangle]
18359pub unsafe extern "C" fn getentropy(buf: *mut u8, buflen: usize) -> i32 {
18360 if buflen > 256 {
18361 ERRNO!() = EIO_VAL;
18362 return -1;
18363 }
18364 let mut pos = buf;
18365 let mut left = buflen;
18366 while left > 0 {
18367 let r = getrandom(pos, left, 0);
18368 if r < 0 {
18369 if ERRNO!() == EINTR_VAL {
18370 continue;
18371 }
18372 return -1;
18373 }
18374 pos = pos.add(r as usize);
18375 left -= r as usize;
18376 }
18377 0
18378}
18379
18380#[no_mangle]
18381pub unsafe extern "C" fn getrandom(buf: *mut u8, buflen: usize, flags: u32) -> isize {
18382 let r = <Arch as Syscalls>::syscall3(sysno(318, 278), buf as i64, buflen as i64, flags as i64);
18383 if r < 0 {
18384 ERRNO!() = (-r) as c_int;
18385 -1
18386 } else {
18387 r as isize
18388 }
18389}
18390
18391#[no_mangle]
18392pub unsafe extern "C" fn killpg(pgrp: i32, sig: i32) -> i32 {
18393 syscall_ret(<Arch as Syscalls>::syscall2(SYS_KILL, -pgrp as i64, sig as i64)) as i32
18394}
18395
18396#[no_mangle]
18397pub unsafe extern "C" fn mkfifo(pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18398 mknod(pathname, 0o010000 | mode, 0)
18399}
18400
18401#[no_mangle]
18406pub unsafe extern "C" fn aligned_alloc(alignment: usize, size: usize) -> *mut core::ffi::c_void {
18407 alloc_aligned_impl(alignment, size) as *mut core::ffi::c_void
18408}
18409
18410#[no_mangle]
18411pub unsafe extern "C" fn memalign(alignment: usize, size: usize) -> *mut core::ffi::c_void {
18412 alloc_aligned_impl(alignment, size) as *mut core::ffi::c_void
18413}
18414
18415#[no_mangle]
18416pub unsafe extern "C" fn posix_memalign(memptr: *mut *mut core::ffi::c_void, alignment: usize, size: usize) -> i32 {
18417 if memptr.is_null() { return EINVAL; }
18418 if alignment < core::mem::size_of::<*mut core::ffi::c_void>() || !alignment.is_power_of_two() {
18419 return EINVAL;
18420 }
18421 let p = alloc_aligned_impl(alignment, size);
18422 if p.is_null() { return ENOMEM; }
18423 *memptr = p as *mut core::ffi::c_void;
18424 0
18425}
18426
18427#[no_mangle]
18428pub unsafe extern "C" fn valloc(size: usize) -> *mut core::ffi::c_void {
18429 alloc_aligned_impl(PAGE, size) as *mut core::ffi::c_void
18430}
18431
18432#[no_mangle]
18445pub unsafe extern "C" fn gettext(msgid: *const core::ffi::c_char) -> *const core::ffi::c_char {
18446 msgid
18447}
18448
18449#[no_mangle]
18450pub unsafe extern "C" fn dgettext(_domainname: *const core::ffi::c_char, msgid: *const core::ffi::c_char) -> *const core::ffi::c_char {
18451 msgid
18452}
18453
18454#[no_mangle]
18455pub unsafe extern "C" fn dcgettext(_domainname: *const core::ffi::c_char, msgid: *const core::ffi::c_char, _category: i32) -> *const core::ffi::c_char {
18456 msgid
18457}
18458
18459#[no_mangle]
18460pub unsafe extern "C" fn ngettext(msgid1: *const core::ffi::c_char, msgid2: *const core::ffi::c_char, n: u64) -> *const core::ffi::c_char {
18461 if n == 1 { msgid1 } else { msgid2 }
18462}
18463
18464#[no_mangle]
18465pub 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 {
18466 if n == 1 { msgid1 } else { msgid2 }
18467}
18468
18469#[no_mangle]
18470pub 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 {
18471 if n == 1 { msgid1 } else { msgid2 }
18472}
18473
18474#[no_mangle]
18475pub unsafe extern "C" fn textdomain(domainname: *const core::ffi::c_char) -> *mut core::ffi::c_char {
18476 static mut DOMAIN: [core::ffi::c_char; 256] = [0; 256];
18477 if domainname.is_null() { return DOMAIN.as_mut_ptr(); }
18478 let mut i = 0;
18479 while i < 255 && *domainname.add(i) != 0 {
18480 DOMAIN[i] = *domainname.add(i);
18481 i += 1;
18482 }
18483 DOMAIN[i] = 0;
18484 DOMAIN.as_mut_ptr()
18485}
18486
18487#[no_mangle]
18488pub unsafe extern "C" fn bindtextdomain(_domainname: *const core::ffi::c_char, dirname: *const core::ffi::c_char) -> *mut core::ffi::c_char {
18489 dirname as *mut core::ffi::c_char
18490}
18491
18492#[no_mangle]
18493pub unsafe extern "C" fn bind_textdomain_codeset(_domainname: *const core::ffi::c_char, codeset: *const core::ffi::c_char) -> *mut core::ffi::c_char {
18494 codeset as *mut core::ffi::c_char
18495}
18496
18497#[no_mangle]
18502pub unsafe extern "C" fn wmemcpy(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18503 let mut i = 0;
18504 while i < n {
18505 *dest.add(i) = *src.add(i);
18506 i += 1;
18507 }
18508 dest
18509}
18510
18511#[no_mangle]
18512pub unsafe extern "C" fn wmemmove(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18513 if dest as usize <= src as usize {
18514 let mut i = 0;
18515 while i < n {
18516 *dest.add(i) = *src.add(i);
18517 i += 1;
18518 }
18519 } else {
18520 let mut i = n;
18521 while i > 0 {
18522 i -= 1;
18523 *dest.add(i) = *src.add(i);
18524 }
18525 }
18526 dest
18527}
18528
18529#[no_mangle]
18530pub unsafe extern "C" fn wmemset(dest: *mut u32, c: u32, n: usize) -> *mut u32 {
18531 let mut i = 0;
18532 while i < n {
18533 *dest.add(i) = c;
18534 i += 1;
18535 }
18536 dest
18537}
18538
18539#[no_mangle]
18540pub unsafe extern "C" fn wmemcmp(s1: *const u32, s2: *const u32, n: usize) -> i32 {
18541 let mut i = 0;
18542 while i < n {
18543 let c1 = *s1.add(i);
18544 let c2 = *s2.add(i);
18545 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
18546 i += 1;
18547 }
18548 0
18549}
18550
18551#[no_mangle]
18552pub unsafe extern "C" fn wmemchr(s: *const u32, c: u32, n: usize) -> *mut u32 {
18553 let mut i = 0;
18554 while i < n {
18555 if *s.add(i) == c { return s.add(i) as *mut u32; }
18556 i += 1;
18557 }
18558 core::ptr::null_mut()
18559}
18560
18561#[no_mangle]
18562pub unsafe extern "C" fn wcpcpy(dest: *mut u32, src: *const u32) -> *mut u32 {
18563 let mut i = 0;
18564 loop {
18565 let c = *src.add(i);
18566 *dest.add(i) = c;
18567 if c == 0 { return dest.add(i); }
18568 i += 1;
18569 }
18570}
18571
18572#[no_mangle]
18573pub unsafe extern "C" fn wcpncpy(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18574 let mut i = 0;
18575 while i < n {
18576 let c = *src.add(i);
18577 *dest.add(i) = c;
18578 if c == 0 { return dest.add(i); }
18579 i += 1;
18580 }
18581 dest.add(n)
18582}
18583
18584#[no_mangle]
18585pub unsafe extern "C" fn wprintf(fmt: *const wchar_t, args: ...) -> c_int {
18586 vfwprintf(stdout, fmt, args)
18587}
18588
18589#[no_mangle]
18590pub unsafe extern "C" fn vwprintf(fmt: *const wchar_t, ap: core::ffi::VaList) -> c_int {
18591 vfwprintf(stdout, fmt, ap)
18592}
18593
18594#[no_mangle]
18599pub unsafe extern "C" fn c16rtomb(s: *mut u8, c16: u16, ps: *mut core::ffi::c_void) -> usize {
18600 let state = ps as *mut u32;
18602 let saved: u32 = if state.is_null() { 0 } else { *state };
18603 if s.is_null() {
18604 if !state.is_null() { *state = 0; }
18605 return 1;
18606 }
18607 let cp: u32;
18608 if saved != 0 {
18609 if c16 < 0xdc00 || c16 > 0xdfff {
18610 if !state.is_null() { *state = 0; }
18611 ERRNO!() = EILSEQ;
18612 return !0usize;
18613 }
18614 cp = 0x10000 + (((saved - 0xd800) << 10) | ((c16 as u32) - 0xdc00));
18615 if !state.is_null() { *state = 0; }
18616 } else if c16 >= 0xd800 && c16 <= 0xdbff {
18617 if !state.is_null() { *state = c16 as u32; }
18618 return 0;
18619 } else if c16 >= 0xdc00 && c16 <= 0xdfff {
18620 ERRNO!() = EILSEQ;
18621 return !0usize;
18622 } else {
18623 cp = c16 as u32;
18624 }
18625 if cp < 0x80 {
18626 *s = cp as u8;
18627 1
18628 } else if cp < 0x800 {
18629 *s = (0xc0 | (cp >> 6)) as u8;
18630 *s.add(1) = (0x80 | (cp & 0x3f)) as u8;
18631 2
18632 } else if cp < 0x10000 {
18633 *s = (0xe0 | (cp >> 12)) as u8;
18634 *s.add(1) = (0x80 | ((cp >> 6) & 0x3f)) as u8;
18635 *s.add(2) = (0x80 | (cp & 0x3f)) as u8;
18636 3
18637 } else {
18638 *s = (0xf0 | (cp >> 18)) as u8;
18639 *s.add(1) = (0x80 | ((cp >> 12) & 0x3f)) as u8;
18640 *s.add(2) = (0x80 | ((cp >> 6) & 0x3f)) as u8;
18641 *s.add(3) = (0x80 | (cp & 0x3f)) as u8;
18642 4
18643 }
18644}
18645
18646#[no_mangle]
18647pub unsafe extern "C" fn c32rtomb(s: *mut u8, c32: u32, _ps: *mut core::ffi::c_void) -> usize {
18648 if s.is_null() { return 1; }
18649 if c32 > 0x10ffff || (c32 >= 0xd800 && c32 <= 0xdfff) {
18650 ERRNO!() = EILSEQ;
18651 return !0usize;
18652 }
18653 if c32 < 0x80 {
18654 *s = c32 as u8;
18655 1
18656 } else if c32 < 0x800 {
18657 *s = (0xc0 | (c32 >> 6)) as u8;
18658 *s.add(1) = (0x80 | (c32 & 0x3f)) as u8;
18659 2
18660 } else if c32 < 0x10000 {
18661 *s = (0xe0 | (c32 >> 12)) as u8;
18662 *s.add(1) = (0x80 | ((c32 >> 6) & 0x3f)) as u8;
18663 *s.add(2) = (0x80 | (c32 & 0x3f)) as u8;
18664 3
18665 } else {
18666 *s = (0xf0 | (c32 >> 18)) as u8;
18667 *s.add(1) = (0x80 | ((c32 >> 12) & 0x3f)) as u8;
18668 *s.add(2) = (0x80 | ((c32 >> 6) & 0x3f)) as u8;
18669 *s.add(3) = (0x80 | (c32 & 0x3f)) as u8;
18670 4
18671 }
18672}
18673
18674#[no_mangle]
18675pub unsafe extern "C" fn mbrtoc16(pc16: *mut u16, s: *const u8, n: usize, _ps: *mut core::ffi::c_void) -> usize {
18676 if s.is_null() { return 0; }
18677 if n == 0 { return 1; }
18678 let c = *s;
18679 if c == 0 { return 0; }
18680 if c < 0x80 {
18681 if !pc16.is_null() { *pc16 = c as u16; }
18682 return 1;
18683 }
18684 if c < 0xC2 { return 1; } if c < 0xE0 {
18686 if n < 2 { return 1; }
18687 let c2 = *s.add(1);
18688 if (c2 & 0xC0) != 0x80 { return 1; }
18689 if !pc16.is_null() { *pc16 = ((((c & 0x1F) as u32) << 6) | ((c2 & 0x3F) as u32)) as u16; }
18690 return 2;
18691 }
18692 if c < 0xF0 {
18693 if n < 3 { return 1; }
18694 let c2 = *s.add(1);
18695 let c3 = *s.add(2);
18696 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 { return 1; }
18697 if !pc16.is_null() { *pc16 = ((((c & 0x0F) as u32) << 12) | (((c2 & 0x3F) as u32) << 6) | ((c3 & 0x3F) as u32)) as u16; }
18698 return 3;
18699 }
18700 1
18701}
18702
18703#[no_mangle]
18704pub unsafe extern "C" fn mbrtoc32(pc32: *mut u32, s: *const u8, n: usize, _ps: *mut core::ffi::c_void) -> usize {
18705 if s.is_null() { return 0; }
18706 if n == 0 { return 1; }
18707 let c = *s;
18708 if c == 0 { return 0; }
18709 if c < 0x80 {
18710 if !pc32.is_null() { *pc32 = c as u32; }
18711 return 1;
18712 }
18713 if c < 0xC2 { return 1; } if c < 0xE0 {
18715 if n < 2 { return 1; }
18716 let c2 = *s.add(1);
18717 if (c2 & 0xC0) != 0x80 { return 1; }
18718 if !pc32.is_null() { *pc32 = (((c & 0x1F) as u32) << 6) | ((c2 & 0x3F) as u32); }
18719 return 2;
18720 }
18721 if c < 0xF0 {
18722 if n < 3 { return 1; }
18723 let c2 = *s.add(1);
18724 let c3 = *s.add(2);
18725 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 { return 1; }
18726 if !pc32.is_null() { *pc32 = (((c & 0x0F) as u32) << 12) | (((c2 & 0x3F) as u32) << 6) | ((c3 & 0x3F) as u32); }
18727 return 3;
18728 }
18729 if c < 0xF5 {
18730 if n < 4 { return 1; }
18731 let c2 = *s.add(1);
18732 let c3 = *s.add(2);
18733 let c4 = *s.add(3);
18734 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80 { return 1; }
18735 if !pc32.is_null() { *pc32 = (((c & 0x07) as u32) << 18) | (((c2 & 0x3F) as u32) << 12) | (((c3 & 0x3F) as u32) << 6) | ((c4 & 0x3F) as u32); }
18736 return 4;
18737 }
18738 1
18739}
18740
18741#[no_mangle]
18753pub unsafe extern "C" fn chown(path: *const core::ffi::c_char, uid: u32, gid: u32) -> i32 {
18754 syscall_ret(<Arch as Syscalls>::syscall5(
18755 SYS_FCHOWNAT,
18756 AT_FDCWD as i64,
18757 path as i64,
18758 uid as i64,
18759 gid as i64,
18760 0,
18761 )) as i32
18762}
18763
18764#[no_mangle]
18765pub unsafe extern "C" fn lchown(path: *const core::ffi::c_char, uid: u32, gid: u32) -> i32 {
18766 syscall_ret(<Arch as Syscalls>::syscall5(
18767 SYS_FCHOWNAT,
18768 AT_FDCWD as i64,
18769 path as i64,
18770 uid as i64,
18771 gid as i64,
18772 0x100, )) as i32
18774}
18775
18776#[no_mangle]
18781pub unsafe extern "C" fn chroot(path: *const core::ffi::c_char) -> i32 {
18782 syscall_ret(<Arch as Syscalls>::syscall1(SYS_CHROOT, path as i64)) as i32
18783}
18784
18785#[no_mangle]
18786pub unsafe extern "C" fn get_current_dir_name() -> *mut core::ffi::c_char {
18787 static mut BUF: [core::ffi::c_char; 4096] = [0; 4096];
18788 let r = getcwd(BUF.as_mut_ptr(), 4096);
18789 if r.is_null() { core::ptr::null_mut() } else { BUF.as_mut_ptr() }
18790}
18791
18792#[no_mangle]
18797pub unsafe extern "C" fn creat(pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18798 open(pathname, 1 | 0o100 | 0o1000, mode as i32)
18800}
18801
18802#[no_mangle]
18803pub unsafe extern "C" fn openat(dirfd: i32, pathname: *const core::ffi::c_char, flags: i32, mode: u32) -> i32 {
18804 syscall_ret(<Arch as Syscalls>::syscall4(SYS_OPENAT, dirfd as i64, pathname as i64, flags as i64, mode as i64)) as i32
18805}
18806
18807#[no_mangle]
18808pub unsafe extern "C" fn pwrite(fd: i32, buf: *const u8, count: usize, offset: i64) -> isize {
18809 syscall_ret(<Arch as Syscalls>::syscall4(sysno(18, 68), fd as i64, buf as i64, count as i64, offset)) as isize
18810}
18811
18812#[no_mangle]
18813pub unsafe extern "C" fn readv(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32) -> isize {
18814 syscall_ret(<Arch as Syscalls>::syscall3(sysno(19, 65), fd as i64, iov as i64, iovcnt as i64)) as isize
18815}
18816
18817#[no_mangle]
18818pub unsafe extern "C" fn writev(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32) -> isize {
18819 syscall_ret(<Arch as Syscalls>::syscall3(sysno(20, 66), fd as i64, iov as i64, iovcnt as i64)) as isize
18820}
18821
18822#[no_mangle]
18827pub unsafe extern "C" fn flock(fd: i32, operation: i32) -> i32 {
18828 syscall_ret(<Arch as Syscalls>::syscall2(SYS_FLOCK, fd as i64, operation as i64)) as i32
18829}
18830
18831#[no_mangle]
18832pub unsafe extern "C" fn lockf(fd: i32, cmd: i32, len: i64) -> i32 {
18833 let r = <Arch as Syscalls>::syscall3(SYS_FCNTL, fd as i64, if cmd == 0 { 7 } else if cmd == 1 { 6 } else { 5 } , len);
18834 if r < 0 { return -1; }
18835 0
18836}
18837
18838#[no_mangle]
18843pub unsafe extern "C" fn getdomainname(name: *mut core::ffi::c_char, len: usize) -> i32 {
18844 if name.is_null() || len == 0 {
18845 ERRNO!() = EINVAL;
18846 return -1;
18847 }
18848 let mut uts: UtsName = core::mem::zeroed();
18849 let r = <Arch as Syscalls>::syscall1(SYS_UNAME, &mut uts as *mut UtsName as i64);
18850 if r < 0 {
18851 ERRNO!() = (-r) as c_int;
18852 return -1;
18853 }
18854 let mut n = 0usize;
18855 while n < uts.domainname.len() && uts.domainname[n] != 0 { n += 1; }
18856 if n >= len {
18857 ERRNO!() = EINVAL;
18858 return -1;
18859 }
18860 core::ptr::copy_nonoverlapping(uts.domainname.as_ptr(), name as *mut u8, n);
18861 *name.add(n) = 0;
18862 0
18863}
18864
18865#[no_mangle]
18866pub unsafe extern "C" fn setdomainname(name: *const core::ffi::c_char, len: usize) -> i32 {
18867 syscall_ret(<Arch as Syscalls>::syscall2(sysno(171, 162), name as i64, len as i64)) as i32
18868}
18869
18870#[no_mangle]
18871pub unsafe extern "C" fn sethostname(name: *const core::ffi::c_char, len: usize) -> i32 {
18872 syscall_ret(<Arch as Syscalls>::syscall2(SYS_SETHOSTNAME, name as i64, len as i64)) as i32
18873}
18874
18875#[no_mangle]
18876pub unsafe extern "C" fn getlogin_r(name: *mut core::ffi::c_char, bufsize: usize) -> i32 {
18877 let user = crate::getenv(b"USER\0".as_ptr() as *const core::ffi::c_char);
18879 if user.is_null() { return 2; }
18880 let mut i = 0;
18881 while i < bufsize - 1 && *user.add(i) != 0 {
18882 *name.add(i) = *user.add(i);
18883 i += 1;
18884 }
18885 *name.add(i) = 0;
18886 0
18887}
18888
18889#[no_mangle]
18890pub unsafe extern "C" fn cuserid(s: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
18891 let user = crate::getenv(b"USER\0".as_ptr() as *const core::ffi::c_char);
18892 if user.is_null() { return core::ptr::null_mut(); }
18893 if s.is_null() {
18894 static mut BUF: [core::ffi::c_char; 32] = [0; 32];
18895 let mut i = 0;
18896 while i < 31 && *user.add(i) != 0 { BUF[i] = *user.add(i); i += 1; }
18897 BUF[i] = 0;
18898 BUF.as_mut_ptr()
18899 } else {
18900 let mut i = 0;
18901 while i < 31 && *user.add(i) != 0 { *s.add(i) = *user.add(i); i += 1; }
18902 *s.add(i) = 0;
18903 s
18904 }
18905}
18906
18907#[repr(C)]
18912#[derive(Copy, Clone)]
18913pub struct Passwd {
18914 pub pw_name: *mut c_char,
18915 pub pw_passwd: *mut c_char,
18916 pub pw_uid: u32,
18917 pub pw_gid: u32,
18918 pub pw_gecos: *mut c_char,
18919 pub pw_dir: *mut c_char,
18920 pub pw_shell: *mut c_char,
18921}
18922
18923#[repr(C)]
18924#[derive(Copy, Clone)]
18925pub struct Group {
18926 pub gr_name: *mut c_char,
18927 pub gr_passwd: *mut c_char,
18928 pub gr_gid: u32,
18929 pub gr_mem: *mut *mut c_char,
18930}
18931
18932static mut PWD_ENT: Passwd = Passwd {
18933 pw_name: core::ptr::null_mut(), pw_passwd: core::ptr::null_mut(),
18934 pw_uid: 0, pw_gid: 0, pw_gecos: core::ptr::null_mut(),
18935 pw_dir: core::ptr::null_mut(), pw_shell: core::ptr::null_mut(),
18936};
18937static mut PWD_BUF: [c_char; 1024] = [0; 1024];
18938static mut PWD_FILE: *mut FILE = core::ptr::null_mut();
18939
18940static mut GRP_ENT: Group = Group {
18941 gr_name: core::ptr::null_mut(), gr_passwd: core::ptr::null_mut(),
18942 gr_gid: 0, gr_mem: core::ptr::null_mut(),
18943};
18944static mut GRP_BUF: [c_char; 2048] = [0; 2048];
18945static mut GRP_MEM: [*mut c_char; 32] = [core::ptr::null_mut(); 32];
18946static mut GRP_FILE: *mut FILE = core::ptr::null_mut();
18947
18948unsafe fn parse_passwd(line: *const c_char, ent: *mut Passwd, buf: *mut c_char, buflen: usize) -> bool {
18949 let mut src = line;
18950 let mut o = 0usize;
18951 let mut fields: [*mut c_char; 7] = [core::ptr::null_mut(); 7];
18952 let mut n = 0usize;
18953 while n < 7 {
18954 let start = o;
18955 while *src != 0 && *src != b':' as c_char {
18956 if o + 1 >= buflen { return false; }
18957 *buf.add(o) = *src;
18958 o += 1;
18959 src = src.add(1);
18960 }
18961 *buf.add(o) = 0;
18962 o += 1;
18963 fields[n] = buf.add(start);
18964 n += 1;
18965 if *src == 0 { break; }
18966 src = src.add(1);
18967 }
18968 if n < 7 { return false; }
18969 (*ent).pw_name = fields[0];
18970 (*ent).pw_passwd = fields[1];
18971 (*ent).pw_uid = crate::strtol(fields[2], core::ptr::null_mut(), 10) as u32;
18972 (*ent).pw_gid = crate::strtol(fields[3], core::ptr::null_mut(), 10) as u32;
18973 (*ent).pw_gecos = fields[4];
18974 (*ent).pw_dir = fields[5];
18975 (*ent).pw_shell = fields[6];
18976 true
18977}
18978
18979unsafe fn parse_group(line: *const c_char, ent: *mut Group, buf: *mut c_char, buflen: usize) -> bool {
18980 let mut src = line;
18981 let mut o = 0usize;
18982 let mut fields: [*mut c_char; 4] = [core::ptr::null_mut(); 4];
18983 let mut n = 0usize;
18984 while n < 4 {
18985 let start = o;
18986 while *src != 0 && *src != b':' as c_char {
18987 if o + 1 >= buflen { return false; }
18988 *buf.add(o) = *src;
18989 o += 1;
18990 src = src.add(1);
18991 }
18992 *buf.add(o) = 0;
18993 o += 1;
18994 fields[n] = buf.add(start);
18995 n += 1;
18996 if *src == 0 { break; }
18997 src = src.add(1);
18998 }
18999 if n < 4 { return false; }
19000 (*ent).gr_name = fields[0];
19001 (*ent).gr_passwd = fields[1];
19002 (*ent).gr_gid = crate::strtol(fields[2], core::ptr::null_mut(), 10) as u32;
19003 let mut mi = 0usize;
19004 let mut m = fields[3];
19005 if *m != 0 {
19006 loop {
19007 if mi + 1 >= GRP_MEM.len() { break; }
19008 GRP_MEM[mi] = m;
19009 mi += 1;
19010 while *m != 0 && *m != b',' as c_char { m = m.add(1); }
19011 if *m == 0 { break; }
19012 *m = 0;
19013 m = m.add(1);
19014 }
19015 }
19016 GRP_MEM[mi] = core::ptr::null_mut();
19017 (*ent).gr_mem = GRP_MEM.as_mut_ptr();
19018 true
19019}
19020
19021#[no_mangle]
19022pub unsafe extern "C" fn getpwnam(name: *const c_char) -> *mut Passwd {
19023 if name.is_null() { return core::ptr::null_mut(); }
19024 setpwent();
19025 loop {
19026 let p = getpwent();
19027 if p.is_null() { break; }
19028 if crate::strcmp((*p).pw_name as *const u8, name as *const u8) == 0 { endpwent(); return p; }
19029 }
19030 endpwent();
19031 core::ptr::null_mut()
19032}
19033
19034#[no_mangle]
19035pub unsafe extern "C" fn getpwuid(uid: u32) -> *mut Passwd {
19036 setpwent();
19037 loop {
19038 let p = getpwent();
19039 if p.is_null() { break; }
19040 if (*p).pw_uid == uid { endpwent(); return p; }
19041 }
19042 endpwent();
19043 core::ptr::null_mut()
19044}
19045
19046#[no_mangle]
19047pub unsafe extern "C" fn setpwent() {
19048 endpwent();
19049 PWD_FILE = crate::fopen(b"/etc/passwd\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
19050}
19051
19052#[no_mangle]
19053pub unsafe extern "C" fn getpwent() -> *mut Passwd {
19054 if PWD_FILE.is_null() { setpwent(); if PWD_FILE.is_null() { return core::ptr::null_mut(); } }
19055 let mut line = [0 as c_char; 1024];
19056 loop {
19057 if crate::fgets(line.as_mut_ptr(), 1024, PWD_FILE).is_null() { return core::ptr::null_mut(); }
19058 if parse_passwd(line.as_ptr(), &raw mut PWD_ENT, PWD_BUF.as_mut_ptr(), PWD_BUF.len()) {
19059 return &raw mut PWD_ENT;
19060 }
19061 }
19062}
19063
19064#[no_mangle]
19065pub unsafe extern "C" fn endpwent() {
19066 if !PWD_FILE.is_null() { crate::fclose(PWD_FILE); PWD_FILE = core::ptr::null_mut(); }
19067}
19068
19069#[no_mangle]
19070pub 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 {
19071 if result.is_null() { return EINVAL; }
19072 let p = getpwnam(name);
19073 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *pwd = *p; *result = pwd; 0 }
19074}
19075
19076#[no_mangle]
19077pub unsafe extern "C" fn getpwuid_r(uid: u32, pwd: *mut Passwd, _buf: *mut c_char, _buflen: usize, result: *mut *mut Passwd) -> c_int {
19078 if result.is_null() { return EINVAL; }
19079 let p = getpwuid(uid);
19080 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *pwd = *p; *result = pwd; 0 }
19081}
19082
19083#[no_mangle]
19084pub unsafe extern "C" fn fgetpwent(f: *mut FILE) -> *mut Passwd {
19085 if f.is_null() { return core::ptr::null_mut(); }
19086 let mut line = [0 as c_char; 1024];
19087 loop {
19088 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
19089 if parse_passwd(line.as_ptr(), &raw mut PWD_ENT, PWD_BUF.as_mut_ptr(), PWD_BUF.len()) {
19090 return &raw mut PWD_ENT;
19091 }
19092 }
19093}
19094
19095#[no_mangle]
19096pub unsafe extern "C" fn putpwent(f: *mut FILE, p: *const Passwd) -> c_int {
19097 if f.is_null() || p.is_null() { return -1; }
19098 crate::fprintf(f, b"%s:%s:%u:%u:%s:%s:%s\n\0".as_ptr() as *const c_char,
19099 (*p).pw_name, (*p).pw_passwd, (*p).pw_uid, (*p).pw_gid,
19100 (*p).pw_gecos, (*p).pw_dir, (*p).pw_shell)
19101}
19102
19103#[no_mangle]
19104pub unsafe extern "C" fn getgrnam(name: *const c_char) -> *mut Group {
19105 if name.is_null() { return core::ptr::null_mut(); }
19106 setgrent();
19107 loop {
19108 let g = getgrent();
19109 if g.is_null() { break; }
19110 if crate::strcmp((*g).gr_name as *const u8, name as *const u8) == 0 { endgrent(); return g; }
19111 }
19112 endgrent();
19113 core::ptr::null_mut()
19114}
19115
19116#[no_mangle]
19117pub unsafe extern "C" fn getgrgid(gid: u32) -> *mut Group {
19118 setgrent();
19119 loop {
19120 let g = getgrent();
19121 if g.is_null() { break; }
19122 if (*g).gr_gid == gid { endgrent(); return g; }
19123 }
19124 endgrent();
19125 core::ptr::null_mut()
19126}
19127
19128#[no_mangle]
19129pub unsafe extern "C" fn setgrent() {
19130 endgrent();
19131 GRP_FILE = crate::fopen(b"/etc/group\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
19132}
19133
19134#[no_mangle]
19135pub unsafe extern "C" fn getgrent() -> *mut Group {
19136 if GRP_FILE.is_null() { setgrent(); if GRP_FILE.is_null() { return core::ptr::null_mut(); } }
19137 let mut line = [0 as c_char; 1024];
19138 loop {
19139 if crate::fgets(line.as_mut_ptr(), 1024, GRP_FILE).is_null() { return core::ptr::null_mut(); }
19140 if parse_group(line.as_ptr(), &raw mut GRP_ENT, GRP_BUF.as_mut_ptr(), GRP_BUF.len()) {
19141 return &raw mut GRP_ENT;
19142 }
19143 }
19144}
19145
19146#[no_mangle]
19147pub unsafe extern "C" fn endgrent() {
19148 if !GRP_FILE.is_null() { crate::fclose(GRP_FILE); GRP_FILE = core::ptr::null_mut(); }
19149}
19150
19151#[no_mangle]
19152pub 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 {
19153 if result.is_null() { return EINVAL; }
19154 let g = getgrnam(name);
19155 if g.is_null() { *result = core::ptr::null_mut(); 0 } else { *grp = *g; *result = grp; 0 }
19156}
19157
19158#[no_mangle]
19159pub unsafe extern "C" fn getgrgid_r(gid: u32, grp: *mut Group, _buf: *mut c_char, _buflen: usize, result: *mut *mut Group) -> c_int {
19160 if result.is_null() { return EINVAL; }
19161 let g = getgrgid(gid);
19162 if g.is_null() { *result = core::ptr::null_mut(); 0 } else { *grp = *g; *result = grp; 0 }
19163}
19164
19165#[no_mangle]
19166pub unsafe extern "C" fn fgetgrent(f: *mut FILE) -> *mut Group {
19167 if f.is_null() { return core::ptr::null_mut(); }
19168 let mut line = [0 as c_char; 1024];
19169 loop {
19170 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
19171 if parse_group(line.as_ptr(), &raw mut GRP_ENT, GRP_BUF.as_mut_ptr(), GRP_BUF.len()) {
19172 return &raw mut GRP_ENT;
19173 }
19174 }
19175}
19176
19177#[no_mangle]
19178pub unsafe extern "C" fn putgrent(f: *mut FILE, g: *const Group) -> c_int {
19179 if f.is_null() || g.is_null() { return -1; }
19180 crate::fprintf(f, b"%s:%s:%u:\0".as_ptr() as *const c_char, (*g).gr_name, (*g).gr_passwd, (*g).gr_gid);
19181 if !(*g).gr_mem.is_null() {
19182 let mut i = 0;
19183 while !(*(*g).gr_mem.add(i)).is_null() {
19184 if i > 0 { crate::fputc(b',' as c_int, f); }
19185 crate::fputs(*(*g).gr_mem.add(i), f);
19186 i += 1;
19187 }
19188 }
19189 crate::fputc(b'\n' as c_int, f);
19190 0
19191}
19192
19193#[no_mangle]
19198pub unsafe extern "C" fn setgroups(ngroups: usize, gidset: *const u32) -> i32 {
19199 syscall_ret(<Arch as Syscalls>::syscall2(SYS_SETGROUPS, ngroups as i64, gidset as i64)) as i32
19200}
19201
19202#[no_mangle]
19203pub unsafe extern "C" fn setresuid(ruid: u32, euid: u32, suid: u32) -> i32 {
19204 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SETRESUID, ruid as i64, euid as i64, suid as i64)) as i32
19205}
19206
19207#[no_mangle]
19208pub unsafe extern "C" fn setresgid(rgid: u32, egid: u32, sgid: u32) -> i32 {
19209 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SETRESGID, rgid as i64, egid as i64, sgid as i64)) as i32
19210}
19211
19212#[no_mangle]
19213pub unsafe extern "C" fn getresuid(ruid: *mut u32, euid: *mut u32, suid: *mut u32) -> i32 {
19214 syscall_ret(<Arch as Syscalls>::syscall3(SYS_GETRESUID, ruid as i64, euid as i64, suid as i64)) as i32
19215}
19216
19217#[no_mangle]
19218pub unsafe extern "C" fn getresgid(rgid: *mut u32, egid: *mut u32, sgid: *mut u32) -> i32 {
19219 syscall_ret(<Arch as Syscalls>::syscall3(SYS_GETRESGID, rgid as i64, egid as i64, sgid as i64)) as i32
19220}
19221
19222#[repr(C)]
19230struct KernelMsgHdr {
19231 msg_name: *mut c_void,
19232 msg_namelen: u32,
19233 __pad0: u32,
19234 msg_iov: *mut c_void,
19235 msg_iovlen: u64,
19236 msg_control: *mut c_void,
19237 msg_controllen: u64,
19238 msg_flags: u32,
19239 __pad1: u32,
19240}
19241
19242#[repr(C)]
19243struct UserMsgHdr {
19244 msg_name: *mut c_void,
19245 msg_namelen: u32,
19246 msg_iov: *mut c_void,
19247 msg_iovlen: i32,
19248 __pad1: i32,
19249 msg_control: *mut c_void,
19250 msg_controllen: u32,
19251 __pad2: i32,
19252 msg_flags: i32,
19253}
19254
19255unsafe fn msg_to_kernel(msg: *const UserMsgHdr, out: &mut KernelMsgHdr) {
19256 *out = KernelMsgHdr {
19257 msg_name: (*msg).msg_name,
19258 msg_namelen: (*msg).msg_namelen,
19259 __pad0: 0,
19260 msg_iov: (*msg).msg_iov,
19261 msg_iovlen: (*msg).msg_iovlen as u32 as u64,
19262 msg_control: (*msg).msg_control,
19263 msg_controllen: (*msg).msg_controllen as u64,
19264 msg_flags: (*msg).msg_flags as u32,
19265 __pad1: 0,
19266 };
19267}
19268
19269#[no_mangle]
19270pub unsafe extern "C" fn sendmsg(fd: i32, msg: *const core::ffi::c_void, flags: i32) -> isize {
19271 if msg.is_null() {
19272 ERRNO!() = EINVAL;
19273 return -1;
19274 }
19275 let mut k: KernelMsgHdr = core::mem::zeroed();
19276 msg_to_kernel(msg as *const UserMsgHdr, &mut k);
19277 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SENDMSG, fd as i64, &k as *const KernelMsgHdr as i64, flags as i64)) as isize
19278}
19279
19280#[no_mangle]
19281pub unsafe extern "C" fn recvmsg(fd: i32, msg: *mut core::ffi::c_void, flags: i32) -> isize {
19282 if msg.is_null() {
19283 ERRNO!() = EINVAL;
19284 return -1;
19285 }
19286 let user = msg as *mut UserMsgHdr;
19287 let mut k: KernelMsgHdr = core::mem::zeroed();
19288 msg_to_kernel(user, &mut k);
19289 let r = syscall_ret(<Arch as Syscalls>::syscall3(SYS_RECVMSG, fd as i64, &mut k as *mut KernelMsgHdr as i64, flags as i64));
19290 (*user).msg_flags = k.msg_flags as i32;
19291 (*user).msg_controllen = k.msg_controllen as u32;
19292 r as isize
19293}
19294
19295#[no_mangle]
19296pub unsafe extern "C" fn sendmmsg(fd: i32, msgvec: *mut core::ffi::c_void, vlen: u32, flags: i32) -> i32 {
19297 syscall_ret(<Arch as Syscalls>::syscall4(sysno(307, 269), fd as i64, msgvec as i64, vlen as i64, flags as i64)) as i32
19298}
19299
19300#[no_mangle]
19301pub unsafe extern "C" fn recvmmsg(fd: i32, msgvec: *mut core::ffi::c_void, vlen: u32, flags: i32, timeout: *mut core::ffi::c_void) -> i32 {
19302 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
19303}
19304
19305#[no_mangle]
19306pub unsafe extern "C" fn getpeername(fd: i32, addr: *mut core::ffi::c_void, addrlen: *mut u32) -> i32 {
19307 syscall_ret(<Arch as Syscalls>::syscall3(sysno(52, 205), fd as i64, addr as i64, addrlen as i64)) as i32
19308}
19309
19310#[no_mangle]
19311pub unsafe extern "C" fn getsockopt(fd: i32, level: i32, optname: i32, optval: *mut core::ffi::c_void, optlen: *mut u32) -> i32 {
19312 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
19313}
19314
19315#[no_mangle]
19320pub unsafe extern "C" fn ftrylockfile(file: *mut FILE) -> i32 {
19321 if file.is_null() { return EINVAL; }
19322 if (*file).lock < 0 { return 0; }
19323 let tid = sys_gettid() as c_int;
19324 let v = a_load(&raw const (*file).lock);
19325 if v == tid {
19326 (*file).lockcount += 1;
19327 return 0;
19328 }
19329 if v == 0 && a_cas(&raw mut (*file).lock, 0, tid) == 0 {
19330 (*file).lockcount = 1;
19331 return 0;
19332 }
19333 EBUSY
19334}
19335
19336#[no_mangle]
19337pub unsafe extern "C" fn getc_unlocked(file: *mut core::ffi::c_char) -> i32 {
19338 getc(file as *mut FILE)
19339}
19340
19341#[no_mangle]
19342pub unsafe extern "C" fn getchar_unlocked() -> i32 {
19343 getchar()
19344}
19345
19346#[no_mangle]
19347pub unsafe extern "C" fn putc_unlocked(c: i32, file: *mut core::ffi::c_char) -> i32 {
19348 putc(c, file as *mut FILE)
19349}
19350
19351#[no_mangle]
19352pub unsafe extern "C" fn putchar_unlocked(c: i32) -> i32 {
19353 putchar(c)
19354}
19355
19356#[no_mangle] pub static mut optarg: *mut core::ffi::c_char = core::ptr::null_mut();
19361#[no_mangle] pub static mut optind: i32 = 1;
19362#[no_mangle] pub static mut opterr: i32 = 1;
19363#[no_mangle] pub static mut optopt: i32 = '?' as i32;
19364#[no_mangle] pub static mut optreset: i32 = 0;
19365
19366#[no_mangle]
19371pub unsafe extern "C" fn getitimer(which: i32, curr_value: *mut core::ffi::c_void) -> i32 {
19372 syscall_ret(<Arch as Syscalls>::syscall2(sysno(36, 102), which as i64, curr_value as i64)) as i32
19373}
19374
19375#[no_mangle]
19376pub unsafe extern "C" fn setitimer(which: i32, new_value: *const core::ffi::c_void, old_value: *mut core::ffi::c_void) -> i32 {
19377 syscall_ret(<Arch as Syscalls>::syscall3(sysno(38, 103), which as i64, new_value as i64, old_value as i64)) as i32
19378}
19379
19380#[no_mangle]
19385pub unsafe extern "C" fn getloadavg(loadavg: *mut f64, nelem: i32) -> i32 {
19386 let fd = crate::open(b"/proc/loadavg\0".as_ptr() as *const core::ffi::c_char, 0, 0);
19387 if fd < 0 { return -1; }
19388 let mut buf: [u8; 64] = [0; 64];
19389 let n = crate::read(fd, buf.as_mut_ptr() as *mut core::ffi::c_void, 63);
19390 crate::close(fd);
19391 if n <= 0 { return -1; }
19392 buf[n as usize] = 0;
19393 let mut i = 0;
19394 while i < nelem as usize && i < 3 {
19395 let val = crate::strtod((buf.as_ptr() as *const core::ffi::c_char).add(i * 5), core::ptr::null_mut());
19396 *loadavg.add(i) = val;
19397 i += 1;
19398 }
19399 i as i32
19400}
19401
19402#[no_mangle]
19403pub unsafe extern "C" fn get_nprocs() -> i32 {
19404 sysconf(84) as i32 }
19406
19407#[no_mangle]
19408pub unsafe extern "C" fn get_nprocs_conf() -> i32 {
19409 sysconf(83) as i32 }
19411
19412#[no_mangle]
19413pub unsafe extern "C" fn get_avphys_pages() -> i64 {
19414 sysconf(86) }
19416
19417#[no_mangle]
19418pub unsafe extern "C" fn get_phys_pages() -> i64 {
19419 sysconf(85) }
19421
19422#[no_mangle]
19427pub unsafe extern "C" fn capget(header: *mut core::ffi::c_void, data: *mut core::ffi::c_void) -> i32 {
19428 syscall_ret(<Arch as Syscalls>::syscall2(SYS_CAPGET, header as i64, data as i64)) as i32
19429}
19430
19431#[no_mangle]
19432pub unsafe extern "C" fn capset(header: *const core::ffi::c_void, data: *const core::ffi::c_void) -> i32 {
19433 syscall_ret(<Arch as Syscalls>::syscall2(SYS_CAPSET, header as i64, data as i64)) as i32
19434}
19435
19436#[no_mangle]
19437pub unsafe extern "C" fn arch_prctl(code: i32, addr: u64) -> i32 {
19438 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 }
19439}
19440
19441#[no_mangle]
19446pub unsafe extern "C" fn cfgetospeed(termios_p: *const core::ffi::c_void) -> u32 {
19447 unsafe { *(termios_p as *const u32).add(1) }
19448}
19449
19450#[no_mangle]
19451pub unsafe extern "C" fn cfgetispeed(termios_p: *const core::ffi::c_void) -> u32 {
19452 unsafe { *(termios_p as *const u32).add(2) }
19453}
19454
19455#[no_mangle]
19456pub unsafe extern "C" fn cfsetospeed(termios_p: *mut core::ffi::c_void, speed: u32) -> i32 {
19457 unsafe { *(termios_p as *mut u32).add(1) = speed; }
19458 0
19459}
19460
19461#[no_mangle]
19462pub unsafe extern "C" fn cfsetispeed(termios_p: *mut core::ffi::c_void, speed: u32) -> i32 {
19463 unsafe { *(termios_p as *mut u32).add(2) = speed; }
19464 0
19465}
19466
19467#[no_mangle]
19468pub unsafe extern "C" fn cfmakeraw(termios_p: *mut core::ffi::c_void) {
19469 unsafe {
19470 let p = termios_p as *mut u32;
19471 *p.add(0) &= !0o37;
19472 *p.add(0) &= !(0o4000 | 0o2000 | 0o10000 | 0o20);
19473 *p.add(0) |= 0o60;
19474 *p.add(3) &= !0o17;
19475 *p.add(3) &= !(0o1000 | 0o40000000);
19476 *p.add(1) = 1;
19477 *p.add(2) = 0;
19478 }
19479}
19480
19481#[no_mangle]
19486pub unsafe extern "C" fn getrusage(who: i32, usage: *mut core::ffi::c_void) -> i32 {
19487 syscall_ret(<Arch as Syscalls>::syscall2(sysno(98, 165), who as i64, usage as i64)) as i32
19488}
19489
19490#[no_mangle]
19491pub unsafe extern "C" fn getpriority(which: i32, who: u32) -> i32 {
19492 let r = <Arch as Syscalls>::syscall2(SYS_GETPRIORITY, which as i64, who as i64);
19494 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
19495 20 - r as i32
19496}
19497
19498#[no_mangle]
19499pub unsafe extern "C" fn setpriority(which: i32, who: u32, prio: i32) -> i32 {
19500 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SETPRIORITY, which as i64, who as i64, prio as i64)) as i32
19501}
19502
19503#[no_mangle]
19504pub unsafe extern "C" fn prlimit(pid: u32, resource: i32, new_limit: *const core::ffi::c_void, old_limit: *mut core::ffi::c_void) -> i32 {
19505 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
19506}
19507
19508#[no_mangle]
19513pub unsafe extern "C" fn clone(
19514 func: usize,
19515 stack: *mut u8,
19516 flags: c_int,
19517 arg: *mut c_void,
19518 mut args: ...
19519) -> c_int {
19520 const CLONE_PIDFD_C: c_int = 0x00001000;
19522 const CLONE_VM_C: c_int = 0x00000100;
19523 const CLONE_THREAD_C: c_int = 0x00010000;
19524 const CLONE_SETTLS_C: c_int = 0x00080000;
19525 const CLONE_PARENT_SETTID_C: c_int = 0x00100000;
19526 const CLONE_CHILD_SETTID_C: c_int = 0x01000000;
19527 const CLONE_CHILD_CLEARTID_C: c_int = 0x00200000;
19528 let _ = CLONE_VM_C;
19529 if flags & (CLONE_THREAD_C | CLONE_SETTLS_C | CLONE_CHILD_CLEARTID_C) != 0
19530 || stack.is_null()
19531 {
19532 ERRNO!() = EINVAL;
19533 return -1;
19534 }
19535 let mut ptid: *mut c_int = core::ptr::null_mut();
19536 let mut tls: c_ulong = 0;
19537 let mut ctid: *mut c_int = core::ptr::null_mut();
19538 if flags & (CLONE_PIDFD_C | CLONE_PARENT_SETTID_C | CLONE_CHILD_SETTID_C) != 0 {
19539 ptid = args.next_arg::<*mut c_int>();
19540 }
19541 if flags & CLONE_CHILD_SETTID_C != 0 {
19542 tls = args.next_arg::<c_ulong>();
19543 ctid = args.next_arg::<*mut c_int>();
19544 }
19545 let r = __rc_clone(func, stack, flags as c_ulong, arg, ptid, tls, ctid);
19546 if r < 0 {
19547 ERRNO!() = (-r) as c_int;
19548 -1
19549 } else {
19550 r as c_int
19551 }
19552}
19553
19554#[no_mangle]
19555pub unsafe extern "C" fn _Fork() -> i32 {
19556 crate::fork()
19557}
19558
19559#[no_mangle]
19560pub 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 {
19561 let mut master: i32 = 0;
19562 let mut slave: i32 = 0;
19563 if openpty(&mut master, &mut slave, name, termp, winp) < 0 { return -1; }
19564 let pid = crate::fork();
19565 if pid < 0 { crate::close(master); crate::close(slave); return -1; }
19566 if pid == 0 {
19567 crate::close(master);
19568 crate::setsid();
19569 crate::dup2(slave, 0);
19570 crate::dup2(slave, 1);
19571 crate::dup2(slave, 2);
19572 } else {
19573 crate::close(slave);
19574 if !amaster.is_null() { *amaster = master; }
19575 }
19576 pid
19577}
19578
19579#[no_mangle]
19580pub 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 {
19581 let master = crate::open(b"/dev/ptmx\0".as_ptr() as *const core::ffi::c_char, 0o2000, 0);
19582 if master < 0 { return -1; }
19583 grantpt(master);
19584 unlockpt(master);
19585 let slave_name = ptsname(master);
19586 if slave_name.is_null() { crate::close(master); return -1; }
19587 let slave = crate::open(slave_name, 0o2000, 0);
19588 if slave < 0 { crate::close(master); return -1; }
19589 if !amaster.is_null() { *amaster = master; }
19590 if !aslave.is_null() { *aslave = slave; }
19591 if !name.is_null() { crate::strcpy(name as *mut u8, slave_name as *const u8); }
19592 0
19593}
19594
19595#[no_mangle]
19596pub unsafe extern "C" fn login_tty(fd: i32) -> i32 {
19597 crate::setsid();
19598 crate::dup2(fd, 0);
19599 crate::dup2(fd, 1);
19600 crate::dup2(fd, 2);
19601 0
19602}
19603
19604#[no_mangle]
19609pub unsafe extern "C" fn __dls2b() {}
19610#[no_mangle]
19611pub unsafe extern "C" fn __dls3() {}
19612#[no_mangle]
19613pub unsafe extern "C" fn _dlstart() {}
19614
19615#[no_mangle]
19620pub unsafe extern "C" fn index(s: *const core::ffi::c_char, c: i32) -> *mut core::ffi::c_char {
19621 let mut i = 0;
19622 loop {
19623 let ch = *s.add(i);
19624 if ch == c as core::ffi::c_char { return s.add(i) as *mut core::ffi::c_char; }
19625 if ch == 0 { return core::ptr::null_mut(); }
19626 i += 1;
19627 }
19628}
19629
19630#[no_mangle]
19631pub unsafe extern "C" fn rindex(s: *const core::ffi::c_char, c: i32) -> *mut core::ffi::c_char {
19632 let mut last = core::ptr::null_mut();
19633 let mut i = 0;
19634 loop {
19635 let ch = *s.add(i);
19636 if ch == 0 { return last; }
19637 if ch == c as core::ffi::c_char { last = s.add(i) as *mut core::ffi::c_char; }
19638 i += 1;
19639 }
19640}
19641
19642#[no_mangle]
19647pub unsafe extern "C" fn imaxabs(j: i64) -> i64 {
19648 j.abs()
19649}
19650
19651#[no_mangle]
19652pub unsafe extern "C" fn imaxdiv(numer: i64, denom: i64) -> (i64, i64) {
19653 (numer / denom, numer % denom)
19654}
19655
19656#[no_mangle]
19661pub static mut h_errno: i32 = 0;
19662
19663#[no_mangle]
19664pub unsafe extern "C" fn __h_errno_location() -> *mut i32 {
19665 &mut h_errno
19666}
19667
19668#[no_mangle]
19669pub unsafe extern "C" fn herror(s: *const core::ffi::c_char) {
19670 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
19671 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
19672 crate::write(2, hstrerror(*__h_errno_location()) as *const core::ffi::c_void, crate::strlen(hstrerror(*__h_errno_location())));
19673 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
19674}
19675
19676#[no_mangle]
19677pub unsafe extern "C" fn hstrerror(_err: i32) -> *const core::ffi::c_char {
19678 b"Unknown error\0".as_ptr() as *const core::ffi::c_char
19679}
19680
19681#[no_mangle]
19686pub unsafe extern "C" fn gettid() -> i32 {
19687 syscall_ret(<Arch as Syscalls>::syscall0(SYS_GETTID)) as i32
19688}
19689
19690#[no_mangle]
19695pub unsafe extern "C" fn ioctl(fd: i32, request: u32, mut args: ...) -> i32 {
19696 let arg = args.next_arg::<i64>();
19697 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, request as i64, arg)) as i32
19698}
19699
19700#[no_mangle]
19701pub unsafe extern "C" fn ioperm(from: u64, num: u64, turn_on: i32) -> i32 {
19702 #[cfg(target_arch = "x86_64")]
19703 { syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOPERM, from as i64, num as i64, turn_on as i64)) as i32 }
19704 #[cfg(not(target_arch = "x86_64"))]
19705 {
19706 let _ = (from, num, turn_on);
19707 ERRNO!() = ENOSYS_VAL;
19708 -1
19709 }
19710}
19711
19712#[no_mangle]
19713pub unsafe extern "C" fn iopl(level: i32) -> i32 {
19714 #[cfg(target_arch = "x86_64")]
19715 { syscall_ret(<Arch as Syscalls>::syscall1(SYS_IOPL, level as i64)) as i32 }
19716 #[cfg(not(target_arch = "x86_64"))]
19717 {
19718 let _ = level;
19719 ERRNO!() = ENOSYS_VAL;
19720 -1
19721 }
19722}
19723
19724#[no_mangle]
19729pub unsafe extern "C" fn getxattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19730 syscall_ret(<Arch as Syscalls>::syscall4(sysno(191, 8), path as i64, name as i64, value as i64, size as i64)) as isize
19731}
19732
19733#[no_mangle]
19734pub unsafe extern "C" fn lgetxattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19735 syscall_ret(<Arch as Syscalls>::syscall4(sysno(192, 9), path as i64, name as i64, value as i64, size as i64)) as isize
19736}
19737
19738#[no_mangle]
19739pub unsafe extern "C" fn fgetxattr(fd: i32, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19740 syscall_ret(<Arch as Syscalls>::syscall4(sysno(193, 10), fd as i64, name as i64, value as i64, size as i64)) as isize
19741}
19742
19743#[no_mangle]
19744pub unsafe extern "C" fn listxattr(path: *const core::ffi::c_char, list: *mut u8, size: usize) -> isize {
19745 syscall_ret(<Arch as Syscalls>::syscall3(sysno(194, 11), path as i64, list as i64, size as i64)) as isize
19746}
19747
19748#[no_mangle]
19749pub unsafe extern "C" fn llistxattr(path: *const core::ffi::c_char, list: *mut u8, size: usize) -> isize {
19750 syscall_ret(<Arch as Syscalls>::syscall3(sysno(195, 12), path as i64, list as i64, size as i64)) as isize
19751}
19752
19753#[no_mangle]
19754pub unsafe extern "C" fn flistxattr(fd: i32, list: *mut u8, size: usize) -> isize {
19755 syscall_ret(<Arch as Syscalls>::syscall3(sysno(196, 13), fd as i64, list as i64, size as i64)) as isize
19756}
19757
19758#[no_mangle]
19759pub 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 {
19760 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
19761}
19762
19763#[no_mangle]
19764pub 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 {
19765 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
19766}
19767
19768#[no_mangle]
19769pub unsafe extern "C" fn fsetxattr(fd: i32, name: *const core::ffi::c_char, value: *const u8, size: usize, flags: i32) -> i32 {
19770 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
19771}
19772
19773#[no_mangle]
19774pub unsafe extern "C" fn removexattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char) -> i32 {
19775 syscall_ret(<Arch as Syscalls>::syscall2(sysno(197, 14), path as i64, name as i64)) as i32
19776}
19777
19778#[no_mangle]
19779pub unsafe extern "C" fn lremovexattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char) -> i32 {
19780 syscall_ret(<Arch as Syscalls>::syscall2(sysno(198, 15), path as i64, name as i64)) as i32
19781}
19782
19783#[no_mangle]
19784pub unsafe extern "C" fn fremovexattr(fd: i32, name: *const core::ffi::c_char) -> i32 {
19785 syscall_ret(<Arch as Syscalls>::syscall2(sysno(199, 16), fd as i64, name as i64)) as i32
19786}
19787
19788#[no_mangle]
19793pub unsafe extern "C" fn adjtime(_delta: *const core::ffi::c_void, olddelta: *mut core::ffi::c_void) -> i32 {
19794 syscall_ret(<Arch as Syscalls>::syscall1(SYS_ADJTIMEX, olddelta as i64)) as i32
19795}
19796
19797#[no_mangle]
19798pub unsafe extern "C" fn adjtimex(buf: *mut core::ffi::c_void) -> i32 {
19799 syscall_ret(<Arch as Syscalls>::syscall1(SYS_ADJTIMEX, buf as i64)) as i32
19800}
19801
19802const TIOCGPTN: i64 = 0x80045430;
19811const TIOCSPTLCK: i64 = 0x40045431;
19812
19813#[no_mangle]
19814pub unsafe extern "C" fn grantpt(_fd: i32) -> i32 {
19815 0
19817}
19818
19819#[no_mangle]
19820pub unsafe extern "C" fn unlockpt(fd: i32) -> i32 {
19821 let mut unlock: i32 = 0;
19822 let r = <Arch as Syscalls>::syscall3(
19823 SYS_IOCTL,
19824 fd as i64,
19825 TIOCSPTLCK,
19826 &mut unlock as *mut i32 as i64,
19827 );
19828 if r < 0 { -1 } else { 0 }
19829}
19830
19831#[no_mangle]
19832pub unsafe extern "C" fn ptsname(fd: i32) -> *mut core::ffi::c_char {
19833 static mut BUF: [core::ffi::c_char; 32] = [0; 32];
19834 let mut pty_nr: i32 = 0;
19835 if <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, TIOCGPTN, &mut pty_nr as *mut i32 as i64) < 0 {
19836 return core::ptr::null_mut();
19837 }
19838 BUF[0] = '/' as c_char; BUF[1] = 'd' as c_char; BUF[2] = 'e' as c_char; BUF[3] = 'v' as c_char;
19840 BUF[4] = '/' as c_char; BUF[5] = 'p' as c_char; BUF[6] = 't' as c_char; BUF[7] = 's' as c_char;
19841 BUF[8] = '/' as c_char;
19842 let mut n = pty_nr as usize;
19843 let mut i = 9;
19844 if n == 0 { BUF[i] = '0' as c_char; i += 1; }
19845 while n > 0 && i < 31 {
19846 BUF[i] = (b'0' + (n % 10) as u8) as c_char;
19847 n /= 10;
19848 i += 1;
19849 }
19850 BUF[i] = 0;
19851 BUF.as_mut_ptr()
19852}
19853
19854#[no_mangle]
19859pub unsafe extern "C" fn finite(x: f64) -> i32 {
19860 (!x.is_nan() && !x.is_infinite()) as i32
19861}
19862
19863#[no_mangle]
19864pub unsafe extern "C" fn finitef(x: f32) -> i32 {
19865 (!x.is_nan() && !x.is_infinite()) as i32
19866}
19867
19868#[no_mangle]
19869pub unsafe extern "C" fn __fpclassifyl(x: f64) -> i32 {
19870 __fpclassify(x)
19871}
19872
19873#[no_mangle]
19874pub unsafe extern "C" fn __signbitl(x: f64) -> i32 {
19875 __signbit(x)
19876}
19877
19878#[no_mangle]
19887pub unsafe extern "C" fn j0(x: f64) -> f64 {
19888 j0_impl(x)
19889}
19890
19891#[no_mangle]
19892pub unsafe extern "C" fn j0f(x: f32) -> f32 {
19893 libm::j0f(x)
19894}
19895
19896#[no_mangle]
19897pub unsafe extern "C" fn j1(x: f64) -> f64 {
19898 libm::j1(x)
19899}
19900
19901#[no_mangle]
19902pub unsafe extern "C" fn j1f(x: f32) -> f32 {
19903 libm::j1f(x)
19904}
19905
19906#[no_mangle]
19907pub unsafe extern "C" fn jn(n: i32, x: f64) -> f64 {
19908 libm::jn(n, x)
19909}
19910
19911#[no_mangle]
19912pub unsafe extern "C" fn jnf(n: i32, x: f32) -> f32 {
19913 libm::jnf(n, x)
19914}
19915
19916#[no_mangle]
19917pub unsafe extern "C" fn y0(x: f64) -> f64 {
19918 y0_impl(x)
19919}
19920
19921#[no_mangle]
19922pub unsafe extern "C" fn y0f(x: f32) -> f32 {
19923 if x.is_nan() { return x; }
19924 if x < 0.0 { return __math_invalidf(x); }
19925 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f32::NEG_INFINITY; }
19926 libm::y0f(x)
19927}
19928
19929#[no_mangle]
19930pub unsafe extern "C" fn y1(x: f64) -> f64 {
19931 if x.is_nan() { return x; }
19932 if x < 0.0 { return __math_invalid(x); }
19933 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f64::NEG_INFINITY; }
19934 libm::y1(x)
19935}
19936
19937#[no_mangle]
19938pub unsafe extern "C" fn y1f(x: f32) -> f32 {
19939 if x.is_nan() { return x; }
19940 if x < 0.0 { return __math_invalidf(x); }
19941 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f32::NEG_INFINITY; }
19942 libm::y1f(x)
19943}
19944
19945#[no_mangle]
19946pub unsafe extern "C" fn yn(n: i32, x: f64) -> f64 {
19947 if x.is_nan() { return x; }
19948 if x < 0.0 { return __math_invalid(x); }
19949 if x == 0.0 {
19950 feraiseexcept(FE_DIVBYZERO);
19951 if n >= 0 { return f64::NEG_INFINITY; }
19952 }
19953 libm::yn(n, x)
19954}
19955
19956#[no_mangle]
19957pub unsafe extern "C" fn ynf(n: i32, x: f32) -> f32 {
19958 if x.is_nan() { return x; }
19959 if x < 0.0 { return __math_invalidf(x); }
19960 if x == 0.0 {
19961 feraiseexcept(FE_DIVBYZERO);
19962 if n >= 0 { return f32::NEG_INFINITY; }
19963 }
19964 libm::ynf(n, x)
19965}
19966
19967#[no_mangle]
19972pub unsafe extern "C" fn __ctype_b_loc() -> *mut *const u16 {
19973 static mut TABLE: *const u16 = core::ptr::null();
19974 &mut TABLE
19975}
19976
19977#[no_mangle]
19978pub unsafe extern "C" fn __ctype_tolower_loc() -> *mut *const i32 {
19979 static mut TABLE: *const i32 = core::ptr::null();
19980 &mut TABLE
19981}
19982
19983#[no_mangle]
19984pub unsafe extern "C" fn __ctype_toupper_loc() -> *mut *const i32 {
19985 static mut TABLE: *const i32 = core::ptr::null();
19986 &mut TABLE
19987}
19988
19989#[no_mangle]
19990pub unsafe extern "C" fn __isalnum_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19991 (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
19992}
19993
19994#[no_mangle]
19995pub unsafe extern "C" fn __isalpha_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19996 (c >= 'A' as i32 && c <= 'Z' as i32 || c >= 'a' as i32 && c <= 'z' as i32) as i32
19997}
19998
19999#[no_mangle]
20000pub unsafe extern "C" fn __isblank_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20001 (c == ' ' as i32 || c == '\t' as i32) as i32
20002}
20003
20004#[no_mangle]
20005pub unsafe extern "C" fn __iscntrl_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20006 (c < 0x20 || c == 0x7f) as i32
20007}
20008
20009#[no_mangle]
20010pub unsafe extern "C" fn __isdigit_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20011 (c >= '0' as i32 && c <= '9' as i32) as i32
20012}
20013
20014#[no_mangle]
20015pub unsafe extern "C" fn __isgraph_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20016 (c > 0x20 && c < 0x7f) as i32
20017}
20018
20019#[no_mangle]
20020pub unsafe extern "C" fn __islower_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20021 (c >= 'a' as i32 && c <= 'z' as i32) as i32
20022}
20023
20024#[no_mangle]
20025pub unsafe extern "C" fn __isprint_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20026 (c >= 0x20 && c < 0x7f) as i32
20027}
20028
20029#[no_mangle]
20030pub unsafe extern "C" fn __ispunct_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20031 (c >= 0x21 && c <= 0x2f || c >= 0x3a && c <= 0x40 || c >= 0x5b && c <= 0x60 || c >= 0x7b && c <= 0x7e) as i32
20032}
20033
20034#[no_mangle]
20035pub unsafe extern "C" fn __isspace_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20036 (c == ' ' as i32 || c >= 0x09 && c <= 0x0d) as i32
20037}
20038
20039#[no_mangle]
20040pub unsafe extern "C" fn __isupper_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20041 (c >= 'A' as i32 && c <= 'Z' as i32) as i32
20042}
20043
20044#[no_mangle]
20045pub unsafe extern "C" fn __isxdigit_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20046 (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
20047}
20048
20049#[no_mangle]
20054pub unsafe extern "C" fn __iswalnum_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20055 (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
20056}
20057
20058#[no_mangle]
20059pub unsafe extern "C" fn __iswalpha_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20060 (c >= 'A' as u32 && c <= 'Z' as u32 || c >= 'a' as u32 && c <= 'z' as u32) as i32
20061}
20062
20063#[no_mangle]
20064pub unsafe extern "C" fn __iswblank_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20065 (c == ' ' as u32 || c == '\t' as u32) as i32
20066}
20067
20068#[no_mangle]
20069pub unsafe extern "C" fn __iswcntrl_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20070 (c < 0x20 || c == 0x7f) as i32
20071}
20072
20073#[no_mangle]
20074pub unsafe extern "C" fn __iswdigit_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20075 (c >= '0' as u32 && c <= '9' as u32) as i32
20076}
20077
20078#[no_mangle]
20079pub unsafe extern "C" fn __iswgraph_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20080 (c > 0x20 && c < 0x7f) as i32
20081}
20082
20083#[no_mangle]
20084pub unsafe extern "C" fn __iswlower_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20085 (c >= 'a' as u32 && c <= 'z' as u32) as i32
20086}
20087
20088#[no_mangle]
20089pub unsafe extern "C" fn __iswprint_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20090 (c >= 0x20 && c < 0x7f) as i32
20091}
20092
20093#[no_mangle]
20094pub unsafe extern "C" fn __iswpunct_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20095 (c >= 0x21 && c <= 0x2f || c >= 0x3a && c <= 0x40 || c >= 0x5b && c <= 0x60 || c >= 0x7b && c <= 0x7e) as i32
20096}
20097
20098#[no_mangle]
20099pub unsafe extern "C" fn __iswspace_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20100 (c == ' ' as u32 || c >= 0x09 && c <= 0x0d) as i32
20101}
20102
20103#[no_mangle]
20104pub unsafe extern "C" fn __iswupper_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20105 (c >= 'A' as u32 && c <= 'Z' as u32) as i32
20106}
20107
20108#[no_mangle]
20109pub unsafe extern "C" fn __iswxdigit_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20110 (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
20111}
20112
20113#[no_mangle]
20114pub unsafe extern "C" fn __iswctype_l(c: u32, ctype: u32, _loc: *mut core::ffi::c_void) -> i32 {
20115 crate::iswctype(c as wint_t, ctype as wctype_t)
20116}
20117
20118#[no_mangle]
20119pub unsafe extern "C" fn __towlower_l(c: u32, _loc: *mut core::ffi::c_void) -> u32 {
20120 crate::towlower(c)
20121}
20122
20123#[no_mangle]
20124pub unsafe extern "C" fn __towupper_l(c: u32, _loc: *mut core::ffi::c_void) -> u32 {
20125 crate::towupper(c)
20126}
20127
20128#[no_mangle]
20129pub unsafe extern "C" fn __towctrans_l(c: u32, _trans: u32, _loc: *mut core::ffi::c_void) -> u32 {
20130 c
20131}
20132
20133#[no_mangle]
20146pub 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) {
20147 crate::write(2, b"Assertion failed: ".as_ptr() as *const core::ffi::c_void, 18);
20148 if !expr.is_null() { crate::write(2, expr as *const core::ffi::c_void, crate::strlen(expr)); }
20149 crate::write(2, b" (".as_ptr() as *const core::ffi::c_void, 2);
20150 if !file.is_null() { crate::write(2, file as *const core::ffi::c_void, crate::strlen(file)); }
20151 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
20152 let mut n = line as usize;
20153 let mut digits: [u8; 32] = [0; 32];
20154 let mut di = 0;
20155 if n == 0 { digits[0] = 0; di = 1; }
20156 while n > 0 && di < 32 { digits[di] = (n % 10) as u8; n /= 10; di += 1; }
20157 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); }
20158 crate::write(2, b")".as_ptr() as *const core::ffi::c_void, 1);
20159 if !func.is_null() { crate::write(2, func as *const core::ffi::c_void, crate::strlen(func)); }
20160 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20161 crate::abort()
20162}
20163
20164#[no_mangle]
20165pub unsafe extern "C" fn at_quick_exit(_func: Option<unsafe extern "C" fn()>) -> i32 {
20166 0
20168}
20169
20170#[no_mangle]
20171pub unsafe extern "C" fn brk(addr: *mut u8) -> i32 {
20172 syscall_ret(<Arch as Syscalls>::syscall1(sysno(12, 214), addr as i64)) as i32
20173}
20174
20175#[no_mangle]
20176pub 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 {
20177 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
20178}
20179
20180#[no_mangle]
20181pub unsafe extern "C" fn ctermid(s: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
20182 static mut BUF: [core::ffi::c_char; 20] = [0; 20];
20183 let dst = if s.is_null() { BUF.as_mut_ptr() } else { s };
20184 let src = b"/dev/tty\0".as_ptr() as *const core::ffi::c_char;
20185 let mut i = 0;
20186 while i < 9 { *dst.add(i) = *src.add(i); i += 1; }
20187 dst
20188}
20189
20190#[no_mangle]
20191pub unsafe extern "C" fn delete_module(name: *const core::ffi::c_char, flags: u32) -> i32 {
20192 syscall_ret(<Arch as Syscalls>::syscall2(SYS_DELETE_MODULE, name as i64, flags as i64)) as i32
20193}
20194
20195
20196
20197
20198
20199#[no_mangle]
20200pub unsafe extern "C" fn __duplocale(loc: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
20201 loc
20202}
20203
20204#[no_mangle]
20205pub unsafe extern "C" fn euidaccess(pathname: *const core::ffi::c_char, mode: i32) -> i32 {
20206 faccessat(AT_FDCWD, pathname, mode, 0x200)
20207}
20208
20209#[no_mangle]
20210pub unsafe extern "C" fn fgetln(f: *mut core::ffi::c_void, lenp: *mut usize) -> *mut core::ffi::c_char {
20211 static mut BUF: [core::ffi::c_char; 4096] = [0; 4096];
20212 let mut i = 0;
20213 while i < 4095 {
20214 let c = getc(f as *mut FILE);
20215 if c < 0 { break; }
20216 BUF[i] = c as c_char;
20217 i += 1;
20218 if c == '\n' as i32 { break; }
20219 }
20220 BUF[i] = 0;
20221 if !lenp.is_null() { *lenp = i; }
20222 if i == 0 { core::ptr::null_mut() } else { BUF.as_mut_ptr() }
20223}
20224
20225#[no_mangle]
20226pub unsafe extern "C" fn fgetws(ws: *mut u32, n: i32, f: *mut core::ffi::c_void) -> *mut u32 {
20227 let mut i = 0;
20228 while i < n - 1 {
20229 let c = getwc(f as *mut core::ffi::c_void);
20230 if c == 0 { break; }
20231 *ws.add(i as usize) = c;
20232 i += 1;
20233 if c == '\n' as u32 { break; }
20234 }
20235 *ws.add(i as usize) = 0;
20236 if i == 0 { core::ptr::null_mut() } else { ws }
20237}
20238
20239#[no_mangle]
20240pub 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 {
20241 if !label.is_null() { crate::write(2, label as *const core::ffi::c_void, crate::strlen(label)); }
20242 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
20243 if !text.is_null() { crate::write(2, text as *const core::ffi::c_void, crate::strlen(text)); }
20244 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20245 0
20246}
20247
20248#[no_mangle]
20249pub unsafe extern "C" fn ftime(tp: *mut core::ffi::c_void) -> i32 {
20250 let mut tv: timeval = core::mem::zeroed();
20251 if gettimeofday(&mut tv, core::ptr::null_mut()) == 0 {
20252 let tb = tp as *mut Timeb;
20253 (*tb).time = tv.tv_sec;
20254 (*tb).millitm = (tv.tv_usec / 1000) as u16;
20255 (*tb).timezone = 0;
20256 (*tb).dstflag = 0;
20257 0
20258 } else {
20259 -1
20260 }
20261}
20262
20263#[no_mangle]
20264pub unsafe extern "C" fn getdents(fd: i32, dirp: *mut u8, count: usize) -> isize {
20265 syscall_ret(<Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, dirp as i64, count as i64)) as isize
20266}
20267
20268#[no_mangle]
20269pub unsafe extern "C" fn gethostid() -> i64 {
20270 let fd = crate::open(b"/proc/sys/kernel/random/boot_id\0".as_ptr() as *const core::ffi::c_char, 0, 0);
20272 if fd < 0 { return 0; }
20273 let mut buf: [u8; 64] = [0; 64];
20274 let n = crate::read(fd, buf.as_mut_ptr() as *mut core::ffi::c_void, 63);
20275 crate::close(fd);
20276 if n <= 0 { return 0; }
20277 buf[n as usize] = 0;
20278 crate::strtol(buf.as_ptr() as *const core::ffi::c_char, core::ptr::null_mut(), 16)
20279}
20280
20281#[no_mangle]
20282pub unsafe extern "C" fn getpass(prompt: *const core::ffi::c_char) -> *mut core::ffi::c_char {
20283 static mut BUF: [core::ffi::c_char; 128] = [0; 128];
20284 crate::write(2, prompt as *const core::ffi::c_void, crate::strlen(prompt));
20286 let n = crate::read(0, BUF.as_mut_ptr() as *mut core::ffi::c_void, 127);
20288 if n > 0 {
20289 let end = if BUF[(n - 1) as usize] == '\n' as c_char { n - 1 } else { n };
20290 BUF[end as usize] = 0;
20291 } else {
20292 BUF[0] = 0;
20293 }
20294 BUF.as_mut_ptr()
20295}
20296
20297#[no_mangle]
20298pub 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 {
20299 let s = *optionp;
20300 if s.is_null() { return -1; }
20301 let mut end = s;
20303 while *end != 0 && *end != ',' as c_char && *end != '=' as c_char { end = end.add(1); }
20304 let eq = *end == '=' as c_char;
20305 if eq { *end = 0; *valuep = end.add(1); }
20306 let mut i = 0;
20308 loop {
20309 let tok = *tokens.add(i);
20310 if tok.is_null() { break; }
20311 if crate::strcmp(s as *const u8, tok as *const u8) == 0 {
20312 while *end != 0 && *end != ',' as c_char { end = end.add(1); }
20314 if *end == ',' as c_char { end = end.add(1); }
20315 *optionp = end;
20316 return i as i32;
20317 }
20318 i += 1;
20319 }
20320 -1
20321}
20322
20323#[no_mangle]
20324pub unsafe extern "C" fn getw(f: *mut core::ffi::c_void) -> i32 {
20325 let c0 = getc(f as *mut FILE);
20326 if c0 < 0 { return -1; }
20327 let c1 = getc(f as *mut FILE);
20328 if c1 < 0 { return -1; }
20329 let c2 = getc(f as *mut FILE);
20330 if c2 < 0 { return -1; }
20331 let c3 = getc(f as *mut FILE);
20332 if c3 < 0 { return -1; }
20333 (c0 | (c1 << 8) | (c2 << 16) | (c3 << 24)) as i32
20334}
20335
20336#[no_mangle]
20337pub unsafe extern "C" fn getwc(f: *mut core::ffi::c_void) -> u32 {
20338 getc(f as *mut FILE) as u32
20339}
20340
20341#[no_mangle]
20342pub unsafe extern "C" fn init_module(module_image: *mut u8, len: usize, param_values: *const core::ffi::c_char) -> i32 {
20343 syscall_ret(<Arch as Syscalls>::syscall3(SYS_INIT_MODULE, module_image as i64, len as i64, param_values as i64)) as i32
20344}
20345
20346
20347
20348#[no_mangle]
20349pub unsafe extern "C" fn issetugid() -> i32 {
20350 let ruid = crate::getuid();
20351 let euid = crate::geteuid();
20352 let rgid = crate::getgid();
20353 let egid = crate::getegid();
20354 (ruid != euid || rgid != egid) as i32
20355}
20356
20357#[no_mangle]
20362pub unsafe extern "C" fn poll(fds: *mut core::ffi::c_void, nfds: u32, timeout: i32) -> i32 {
20363 #[cfg(target_arch = "x86_64")]
20364 { syscall_ret(<Arch as Syscalls>::syscall3(SYS_POLL, fds as i64, nfds as i64, timeout as i64)) as i32 }
20365 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
20366 {
20367 syscall_ret(<Arch as Syscalls>::syscall5(SYS_PPOLL, fds as i64, nfds as i64, timeout as i64, 0, 0)) as i32
20368 }
20369}
20370
20371#[no_mangle]
20372pub unsafe extern "C" fn ppoll(fds: *mut core::ffi::c_void, nfds: u32, timeout: *const core::ffi::c_void, sigmask: *const u64) -> i32 {
20373 syscall_ret(<Arch as Syscalls>::syscall5(SYS_PPOLL, fds as i64, nfds as i64, timeout as i64, sigmask as i64, 8)) as i32
20374}
20375
20376#[no_mangle]
20377pub 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 {
20378 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
20379}
20380
20381#[no_mangle]
20390pub unsafe extern "C" fn quick_exit(status: i32) -> ! {
20391 crate::_exit(status)
20392}
20393
20394#[no_mangle]
20399pub unsafe extern "C" fn lstat(path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
20400 let r = <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, AT_FDCWD as i64, path as i64, buf as i64, 0x100);
20401 if r < 0 {
20402 ERRNO!() = (-r) as c_int;
20403 -1
20404 } else {
20405 0
20406 }
20407}
20408
20409#[no_mangle]
20410pub unsafe extern "C" fn __xstat(_ver: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
20411 crate::stat(path, buf as *mut Stat)
20412}
20413
20414#[no_mangle]
20415pub unsafe extern "C" fn __lxstat(_ver: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
20416 crate::lstat(path, buf)
20417}
20418
20419#[no_mangle]
20420pub unsafe extern "C" fn __fxstat(_ver: i32, fd: i32, buf: *mut core::ffi::c_void) -> i32 {
20421 crate::fstat(fd, buf as *mut Stat)
20422}
20423
20424#[no_mangle]
20425pub unsafe extern "C" fn __fxstatat(_ver: i32, _dirfd: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void, _flags: i32) -> i32 {
20426 crate::stat(path, buf as *mut Stat)
20427}
20428
20429#[no_mangle]
20434pub unsafe extern "C" fn mempcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
20435 core::ptr::copy_nonoverlapping(src, dest, n);
20436 dest.add(n)
20437}
20438
20439#[no_mangle]
20444pub unsafe extern "C" fn mkostemp(template: *mut core::ffi::c_char, _flags: i32) -> i32 {
20445 mkstemp(template)
20446}
20447
20448#[no_mangle]
20449pub unsafe extern "C" fn mkstemps(template: *mut core::ffi::c_char, _suffixlen: i32) -> i32 {
20450 mkstemp(template)
20451}
20452
20453#[no_mangle]
20458pub unsafe extern "C" fn ptrace(request: i32, mut args: ...) -> i64 {
20459 let pid = args.next_arg::<c_long>();
20460 let addr = args.next_arg::<c_long>();
20461 let data = args.next_arg::<c_long>();
20462 if (1..=3).contains(&request) {
20465 let mut result: c_long = 0;
20466 let r = <Arch as Syscalls>::syscall4(
20467 sysno(101, 117),
20468 request as i64,
20469 pid,
20470 addr,
20471 &mut result as *mut c_long as i64,
20472 );
20473 if r < 0 {
20474 ERRNO!() = (-r) as c_int;
20475 return -1;
20476 }
20477 return result;
20478 }
20479 syscall_ret(<Arch as Syscalls>::syscall4(sysno(101, 117), request as i64, pid, addr, data))
20480}
20481
20482#[no_mangle]
20483pub unsafe extern "C" fn personality(persona: u64) -> i64 {
20484 <Arch as Syscalls>::syscall1(sysno(135, 92), persona as i64)
20485}
20486
20487#[no_mangle]
20488pub unsafe extern "C" fn reboot(cmd: c_int) -> i32 {
20489 syscall_ret(<Arch as Syscalls>::syscall3(
20491 SYS_REBOOT,
20492 0xfee1dead,
20493 672274793,
20494 cmd as i64,
20495 )) as i32
20496}
20497
20498#[no_mangle]
20499pub unsafe extern "C" fn pivot_root(new_root: *const core::ffi::c_char, put_old: *const core::ffi::c_char) -> i32 {
20500 syscall_ret(<Arch as Syscalls>::syscall2(SYS_PIVOT_ROOT, new_root as i64, put_old as i64)) as i32
20501}
20502
20503#[no_mangle]
20504pub 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 {
20505 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
20506}
20507
20508#[no_mangle]
20509pub unsafe extern "C" fn umount(target: *const core::ffi::c_char) -> i32 {
20510 syscall_ret(<Arch as Syscalls>::syscall2(SYS_UMOUNT2, target as i64, 0)) as i32
20511}
20512
20513#[no_mangle]
20514pub unsafe extern "C" fn umount2(target: *const core::ffi::c_char, flags: i32) -> i32 {
20515 syscall_ret(<Arch as Syscalls>::syscall2(SYS_UMOUNT2, target as i64, flags as i64)) as i32
20516}
20517
20518#[no_mangle]
20528pub unsafe extern "C" fn psiginfo(_pinfo: *const core::ffi::c_void, s: *const core::ffi::c_char) {
20529 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
20530 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20531}
20532
20533#[no_mangle]
20534pub unsafe extern "C" fn psignal(sig: i32, s: *const core::ffi::c_char) {
20535 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
20536 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
20537 crate::write(2, strsignal(sig) as *const core::ffi::c_void, crate::strlen(strsignal(sig)));
20538 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20539}
20540
20541#[no_mangle]
20542pub unsafe extern "C" fn strsignal(sig: c_int) -> *const c_char {
20543 static NAMES: [&[u8]; 32] = [
20544 b"Unknown signal\0",
20545 b"Hangup\0",
20546 b"Interrupt\0",
20547 b"Quit\0",
20548 b"Illegal instruction\0",
20549 b"Trace/breakpoint trap\0",
20550 b"Aborted\0",
20551 b"Bus error\0",
20552 b"Floating point exception\0",
20553 b"Killed\0",
20554 b"User defined signal 1\0",
20555 b"Segmentation fault\0",
20556 b"User defined signal 2\0",
20557 b"Broken pipe\0",
20558 b"Alarm clock\0",
20559 b"Terminated\0",
20560 b"Stack fault\0",
20561 b"Child process status\0",
20562 b"Continued\0",
20563 b"Stopped (signal)\0",
20564 b"Stopped\0",
20565 b"Stopped (tty input)\0",
20566 b"Stopped (tty output)\0",
20567 b"Urgent I/O condition\0",
20568 b"CPU time limit exceeded\0",
20569 b"File size limit exceeded\0",
20570 b"Virtual timer expired\0",
20571 b"Profiling timer expired\0",
20572 b"Window changed\0",
20573 b"I/O possible\0",
20574 b"Power failure\0",
20575 b"Bad system call\0",
20576 ];
20577 static mut RT_BUF: [c_char; 32] = [0; 32];
20578 if sig > 0 && sig < 32 {
20579 return NAMES[sig as usize].as_ptr() as *const c_char;
20580 }
20581 if sig >= 32 && sig < 65 {
20582 let mut o = 0usize;
20583 for &c in b"Real-time signal \0" {
20584 if c == 0 { break; }
20585 RT_BUF[o] = c as c_char;
20586 o += 1;
20587 }
20588 let mut v = (sig - 32) as u32;
20589 let mut digits = [0u8; 10];
20590 let mut d = 0usize;
20591 if v == 0 { digits[0] = b'0'; d = 1; }
20592 while v > 0 { digits[d] = b'0' + (v % 10) as u8; v /= 10; d += 1; }
20593 while d > 0 { d -= 1; RT_BUF[o] = digits[d] as c_char; o += 1; }
20594 RT_BUF[o] = 0;
20595 return RT_BUF.as_ptr();
20596 }
20597 b"Unknown signal\0".as_ptr() as *const c_char
20598}
20599
20600#[no_mangle]
20601pub unsafe extern "C" fn __strerror_l(errnum: i32, _loc: *mut core::ffi::c_void) -> *const core::ffi::c_char {
20602 crate::strerror(errnum)
20603}
20604
20605#[no_mangle]
20610pub unsafe extern "C" fn preadv(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64) -> isize {
20611 syscall_ret(<Arch as Syscalls>::syscall5(
20614 sysno(295, 69),
20615 fd as i64,
20616 iov as i64,
20617 iovcnt as i64,
20618 offset,
20619 offset >> 32,
20620 )) as isize
20621}
20622
20623#[no_mangle]
20624pub unsafe extern "C" fn pwritev(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64) -> isize {
20625 syscall_ret(<Arch as Syscalls>::syscall5(
20626 sysno(296, 70),
20627 fd as i64,
20628 iov as i64,
20629 iovcnt as i64,
20630 offset,
20631 offset >> 32,
20632 )) as isize
20633}
20634
20635#[no_mangle]
20636pub unsafe extern "C" fn preadv2(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64, flags: u32) -> isize {
20637 syscall_ret(<Arch as Syscalls>::syscall6(
20640 sysno(327, 286),
20641 fd as i64,
20642 iov as i64,
20643 iovcnt as i64,
20644 offset,
20645 offset >> 32,
20646 flags as i64,
20647 )) as isize
20648}
20649
20650#[no_mangle]
20651pub unsafe extern "C" fn pwritev2(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64, flags: u32) -> isize {
20652 syscall_ret(<Arch as Syscalls>::syscall6(
20653 sysno(328, 287),
20654 fd as i64,
20655 iov as i64,
20656 iovcnt as i64,
20657 offset,
20658 offset >> 32,
20659 flags as i64,
20660 )) as isize
20661}
20662
20663#[no_mangle]
20668pub unsafe extern "C" fn nice(inc: i32) -> i32 {
20669 let mut prio = inc;
20670 if inc > -40 && inc < 40 {
20671 prio += getpriority(0, 0);
20672 }
20673 if prio > 19 { prio = 19; }
20674 if prio < -20 { prio = -20; }
20675 if setpriority(0, 0, prio) != 0 {
20676 if ERRNO!() == 13 { ERRNO!() = 1; } return -1;
20678 }
20679 prio
20680}
20681
20682#[no_mangle]
20687pub unsafe extern "C" fn l64a(value: i64) -> *mut core::ffi::c_char {
20688 static mut BUF: [core::ffi::c_char; 7] = [0; 7];
20689 let mut v = value as u64;
20690 let mut i = 0;
20691 while v > 0 && i < 6 {
20692 let c = (v & 0x3f) as u8;
20693 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;
20694 v >>= 6;
20695 i += 1;
20696 }
20697 BUF[i] = 0;
20698 BUF.as_mut_ptr()
20699}
20700
20701#[no_mangle]
20702pub unsafe extern "C" fn lchmod(path: *const core::ffi::c_char, mode: u32) -> i32 {
20703 syscall_ret(<Arch as Syscalls>::syscall4(SYS_FCHMODAT, AT_FDCWD as i64, path as i64, mode as i64, 0x100)) as i32
20704}
20705
20706#[no_mangle]
20707pub unsafe extern "C" fn lutimes(filename: *const core::ffi::c_char, times: *const core::ffi::c_void) -> i32 {
20708 utimensat(AT_FDCWD, filename, times as *const timespec, 0x100)
20709}
20710
20711#[no_mangle]
20712pub unsafe extern "C" fn mknod(pathname: *const core::ffi::c_char, mode: u32, dev: u64) -> i32 {
20713 #[cfg(target_arch = "x86_64")]
20714 { syscall_ret(<Arch as Syscalls>::syscall3(SYS_MKNOD, pathname as i64, mode as i64, dev as i64)) as i32 }
20715 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
20716 {
20717 syscall_ret(<Arch as Syscalls>::syscall4(SYS_MKNODAT, AT_FDCWD as i64, pathname as i64, mode as i64, dev as i64)) as i32
20718 }
20719}
20720
20721#[no_mangle]
20722pub unsafe extern "C" fn memfd_create(name: *const core::ffi::c_char, flags: u32) -> i32 {
20723 syscall_ret(<Arch as Syscalls>::syscall2(sysno(319, 279), name as i64, flags as i64)) as i32
20724}
20725
20726#[no_mangle]
20727pub unsafe extern "C" fn mlock2(addr: *const core::ffi::c_void, len: usize, flags: u32) -> i32 {
20728 syscall_ret(<Arch as Syscalls>::syscall3(sysno(325, 284), addr as i64, len as i64, flags as i64)) as i32
20729}
20730
20731
20732
20733#[no_mangle]
20734pub unsafe extern "C" fn remap_file_pages(addr: *mut core::ffi::c_void, size: usize, prot: i32, pgoff: usize, flags: u32) -> i32 {
20735 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
20736}
20737
20738#[no_mangle]
20743pub unsafe extern "C" fn nan(_tagp: *const core::ffi::c_char) -> f64 {
20744 f64::NAN
20745}
20746
20747#[no_mangle]
20748pub unsafe extern "C" fn nanf(_tagp: *const core::ffi::c_char) -> f32 {
20749 f32::NAN
20750}
20751
20752#[no_mangle]
20757pub unsafe extern "C" fn __lgammal_r(x: f64, signgamp: *mut i32) -> f64 {
20758 *signgamp = 1;
20759 lgamma(x)
20760}
20761
20762#[no_mangle]
20763pub unsafe extern "C" fn __libc_current_sigrtmax() -> i32 {
20764 64
20765}
20766
20767#[no_mangle]
20768pub unsafe extern "C" fn _longjmp(env: *mut core::ffi::c_void, val: i32) {
20769 crate::longjmp(env as *mut u64, val)
20770}
20771
20772#[no_mangle]
20773pub unsafe extern "C" fn __newlocale(_mask: i32, _name: *const core::ffi::c_char, base: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
20774 base
20775}
20776
20777#[no_mangle]
20778pub unsafe extern "C" fn __nl_langinfo(_item: i32) -> *mut core::ffi::c_char {
20779 b"\0".as_ptr() as *mut core::ffi::c_char
20780}
20781
20782#[no_mangle]
20783pub unsafe extern "C" fn __nl_langinfo_l(_item: i32, _loc: *mut core::ffi::c_void) -> *mut core::ffi::c_char {
20784 b"\0".as_ptr() as *mut core::ffi::c_char
20785}
20786
20787#[no_mangle]
20788pub unsafe extern "C" fn ns_get16(cp: *const u8) -> u16 {
20789 ((*cp.add(0) as u16) << 8) | *cp.add(1) as u16
20790}
20791
20792#[no_mangle]
20793pub unsafe extern "C" fn ns_get32(cp: *const u8) -> u32 {
20794 ((*cp.add(0) as u32) << 24) | ((*cp.add(1) as u32) << 16) | ((*cp.add(2) as u32) << 8) | *cp.add(3) as u32
20795}
20796
20797#[no_mangle]
20798pub unsafe extern "C" fn ns_put16(s: u16, dst: *mut u8) {
20799 *dst.add(0) = (s >> 8) as u8;
20800 *dst.add(1) = (s & 0xff) as u8;
20801}
20802
20803#[no_mangle]
20804pub unsafe extern "C" fn ns_put32(l: u32, dst: *mut u8) {
20805 *dst.add(0) = (l >> 24) as u8;
20806 *dst.add(1) = ((l >> 16) & 0xff) as u8;
20807 *dst.add(2) = ((l >> 8) & 0xff) as u8;
20808 *dst.add(3) = (l & 0xff) as u8;
20809}
20810
20811#[no_mangle]
20812pub unsafe extern "C" fn posix_close(fd: i32) -> i32 {
20813 crate::close(fd)
20814}
20815
20816#[no_mangle]
20817pub unsafe extern "C" fn posix_openpt(flags: i32) -> i32 {
20818 crate::open(b"/dev/ptmx\0".as_ptr() as *const core::ffi::c_char, flags, 0)
20819}
20820
20821#[no_mangle]
20822pub unsafe extern "C" fn putw(w: i32, f: *mut core::ffi::c_void) {
20823 putc((w & 0xff) as i32, f as *mut FILE);
20824 putc(((w >> 8) & 0xff) as i32, f as *mut FILE);
20825 putc(((w >> 16) & 0xff) as i32, f as *mut FILE);
20826 putc(((w >> 24) & 0xff) as i32, f as *mut FILE);
20827}
20828
20829
20830
20831#[no_mangle]
20832pub unsafe extern "C" fn rand_r(seedp: *mut u32) -> i32 {
20833 let seed = (*seedp).wrapping_mul(1103515245).wrapping_add(12345);
20834 *seedp = seed;
20835 ((seed >> 16) & 0x7fff) as i32
20836}
20837
20838#[no_mangle]
20839pub unsafe extern "C" fn reallocarray(ptr: *mut core::ffi::c_void, nmemb: usize, size: usize) -> *mut core::ffi::c_void {
20840 let total = match nmemb.checked_mul(size) {
20841 Some(v) => v,
20842 None => { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
20843 };
20844 crate::realloc(ptr, total)
20845}
20846
20847#[no_mangle]
20848pub unsafe extern "C" fn __res_state() -> *mut core::ffi::c_void {
20849 static mut STATE: [u8; 512] = [0; 512];
20850 STATE.as_mut_ptr() as *mut core::ffi::c_void
20851}
20852
20853#[no_mangle]
20854pub unsafe extern "C" fn sbrk(increment: isize) -> *mut u8 {
20855 if increment != 0 {
20858 ERRNO!() = ENOMEM;
20859 return -1isize as usize as *mut u8;
20860 }
20861 <Arch as Syscalls>::syscall1(sysno(12, 214), 0) as *mut u8
20862}
20863
20864#[no_mangle]
20865pub unsafe extern "C" fn scalb(x: f64, exp: f64) -> f64 {
20866 if x.is_nan() || exp.is_nan() { return x * exp; }
20867 if !exp.is_finite() {
20868 let r = if exp > 0.0 { x * exp } else { x / (-exp) };
20869 if r.is_nan() && !x.is_nan() {
20870 feraiseexcept(FE_INVALID);
20871 }
20872 return r;
20873 }
20874 if libm::rint(exp) != exp {
20875 return __math_invalid(exp);
20876 }
20877 if exp > 65000.0 { return libm::scalbn(x, 65000); }
20878 if -exp > 65000.0 { return libm::scalbn(x, -65000); }
20879 libm::scalbn(x, exp as i32)
20880}
20881
20882#[no_mangle]
20883pub unsafe extern "C" fn scalbf(x: f32, exp: f32) -> f32 {
20884 if x.is_nan() || exp.is_nan() { return x * exp; }
20885 if !exp.is_finite() {
20886 let r = if exp > 0.0 { x * exp } else { x / (-exp) };
20887 if r.is_nan() && !x.is_nan() {
20888 feraiseexcept(FE_INVALID);
20889 }
20890 return r;
20891 }
20892 if libm::rintf(exp) != exp {
20893 return __math_invalidf(exp);
20894 }
20895 if exp > 65000.0 { return libm::scalbnf(x, 65000); }
20896 if -exp > 65000.0 { return libm::scalbnf(x, -65000); }
20897 libm::scalbnf(x, exp as i32)
20898}
20899
20900#[no_mangle]
20901pub unsafe extern "C" fn __sched_cpucount(setsize: usize, setp: *const u8) -> i32 {
20902 let mut count = 0;
20903 let mut i = 0;
20904 while i < setsize * 8 {
20905 if (*setp.add(i / 8) >> (i % 8)) & 1 != 0 { count += 1; }
20906 i += 1;
20907 }
20908 count
20909}
20910
20911
20912
20913#[no_mangle]
20914pub unsafe extern "C" fn select(nfds: i32, readfds: *mut u8, writefds: *mut u8, exceptfds: *mut u8, timeout: *mut core::ffi::c_void) -> i32 {
20915 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
20916}
20917
20918
20919
20920#[no_mangle]
20921pub unsafe extern "C" fn sendfile(out_fd: i32, in_fd: i32, offset: *mut i64, count: usize) -> isize {
20922 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
20923}
20924
20925
20926
20927
20928
20929#[no_mangle]
20930pub unsafe extern "C" fn __setjmp(env: *mut core::ffi::c_void) -> i32 {
20931 crate::setjmp(env as *mut u64)
20932}
20933
20934#[no_mangle]
20935pub unsafe extern "C" fn _setjmp(env: *mut core::ffi::c_void) -> i32 {
20936 crate::setjmp(env as *mut u64)
20937}
20938
20939#[no_mangle]
20940pub unsafe extern "C" fn setlinebuf(stream: *mut core::ffi::c_void) {
20941 setvbuf(stream as *mut FILE, core::ptr::null_mut(), 1, 0);
20942}
20943
20944
20945
20946
20947
20948
20949
20950
20951
20952
20953
20954
20955
20956
20957
20958#[no_mangle]
20959pub unsafe extern "C" fn significand(x: f64) -> f64 {
20960 let bits = x.to_bits();
20961 let exp = ((bits >> 52) & 0x7ff) as i32;
20962 if exp == 0 || exp == 0x7ff { return x; }
20963 f64::from_bits((bits & 0x000fffffffffffff) | (1023u64 << 52))
20964}
20965
20966#[no_mangle]
20967pub unsafe extern "C" fn significandf(x: f32) -> f32 {
20968 let bits = x.to_bits();
20969 let exp = ((bits >> 23) & 0xff) as i32;
20970 if exp == 0 || exp == 0xff { return x; }
20971 f32::from_bits((bits & 0x007fffff) | (127u32 << 23))
20972}
20973
20974
20975
20976
20977
20978#[no_mangle]
20979pub unsafe extern "C" fn sigset(sig: i32, handler: usize) -> usize {
20980 signal(sig, handler)
20982}
20983
20984#[no_mangle]
20985pub unsafe extern "C" fn sincos(x: f64, sin: *mut f64, cos: *mut f64) {
20986 *sin = libm::sin(x);
20987 *cos = libm::cos(x);
20988}
20989
20990#[no_mangle]
20991pub unsafe extern "C" fn sincosf(x: f32, sin: *mut f32, cos: *mut f32) {
20992 *sin = libm::sinf(x);
20993 *cos = libm::cosf(x);
20994}
20995
20996
20997
20998
20999
21000
21001
21002
21003
21004unsafe fn nd_ascii_lower(c: c_char) -> c_int {
21005 let b = c as u8;
21006 if b >= b'A' && b <= b'Z' { (b + 32) as c_int } else { b as c_int }
21007}
21008
21009unsafe fn nd_strncasecmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int {
21010 let mut i = 0usize;
21011 while i < n {
21012 let c1 = nd_ascii_lower(*s1.add(i));
21013 let c2 = nd_ascii_lower(*s2.add(i));
21014 if c1 != c2 || c1 == 0 { return c1 - c2; }
21015 i += 1;
21016 }
21017 0
21018}
21019
21020#[no_mangle]
21021pub unsafe extern "C" fn strcasecmp(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char) -> i32 {
21022 nd_strncasecmp(s1, s2, usize::MAX)
21023}
21024
21025#[no_mangle]
21026pub 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 {
21027 nd_strncasecmp(s1, s2, usize::MAX)
21028}
21029
21030#[no_mangle]
21031pub unsafe extern "C" fn strcasestr(haystack: *const core::ffi::c_char, needle: *const core::ffi::c_char) -> *mut core::ffi::c_char {
21032 let nlen = crate::strlen(needle);
21033 if nlen == 0 { return haystack as *mut core::ffi::c_char; }
21034 let mut i = 0;
21035 loop {
21036 let h = haystack.add(i);
21037 if *h == 0 { return core::ptr::null_mut(); }
21038 if crate::strncasecmp(h, needle, nlen) == 0 { return h as *mut core::ffi::c_char; }
21039 i += 1;
21040 }
21041}
21042
21043#[no_mangle]
21044pub 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 {
21045 crate::strcmp(s1 as *const u8, s2 as *const u8)
21046}
21047
21048#[no_mangle]
21049pub unsafe extern "C" fn strncasecmp(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char, n: usize) -> i32 {
21050 nd_strncasecmp(s1, s2, n)
21051}
21052
21053#[no_mangle]
21054pub 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 {
21055 nd_strncasecmp(s1, s2, n)
21056}
21057
21058#[no_mangle]
21059pub unsafe extern "C" fn strsep(stringp: *mut *mut core::ffi::c_char, delim: *const core::ffi::c_char) -> *mut core::ffi::c_char {
21060 let s = *stringp;
21061 if s.is_null() { return core::ptr::null_mut(); }
21062 let mut p = s;
21063 while *p != 0 {
21064 let mut d = delim;
21065 while *d != 0 {
21066 if *p == *d { *p = 0; *stringp = p.add(1); return s; }
21067 d = d.add(1);
21068 }
21069 p = p.add(1);
21070 }
21071 *stringp = core::ptr::null_mut();
21072 s
21073}
21074
21075#[no_mangle]
21076pub unsafe extern "C" fn strtoimax(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, base: i32) -> i64 {
21077 crate::strtol(nptr, endptr, base)
21078}
21079
21080#[no_mangle]
21081pub 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 {
21082 let mut s = if s.is_null() { *saveptr } else { s };
21083 if s.is_null() { return core::ptr::null_mut(); }
21084 while *s != 0 {
21086 let mut d = delim;
21087 let mut found = false;
21088 while *d != 0 {
21089 if *s == *d { found = true; break; }
21090 d = d.add(1);
21091 }
21092 if !found { break; }
21093 s = s.add(1);
21094 }
21095 if *s == 0 { *saveptr = s; return core::ptr::null_mut(); }
21096 let start = s;
21097 while *s != 0 {
21099 let mut d = delim;
21100 while *d != 0 {
21101 if *s == *d { *s = 0; *saveptr = s.add(1); return start; }
21102 d = d.add(1);
21103 }
21104 s = s.add(1);
21105 }
21106 *saveptr = s;
21107 start
21108}
21109
21110#[no_mangle]
21111pub unsafe extern "C" fn strtoumax(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, base: i32) -> u64 {
21112 crate::strtoul(nptr, endptr, base) as u64
21113}
21114
21115#[no_mangle]
21116pub 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 {
21117 crate::strlcpy(dest as *mut u8, src as *const u8, n)
21118}
21119
21120#[no_mangle]
21121pub unsafe extern "C" fn swab(src: *const u8, dest: *mut u8, nbytes: isize) {
21122 let mut i = 0;
21123 while i + 1 < nbytes {
21124 let a = *src.add(i as usize);
21125 let b = *src.add(i as usize + 1);
21126 *dest.add(i as usize) = b;
21127 *dest.add(i as usize + 1) = a;
21128 i += 2;
21129 }
21130}
21131
21132
21133
21134
21135
21136
21137
21138
21139
21140
21141
21142#[no_mangle]
21143pub unsafe extern "C" fn __tolower_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
21144 if c >= 'A' as i32 && c <= 'Z' as i32 { c + 32 } else { c }
21145}
21146
21147#[no_mangle]
21148pub unsafe extern "C" fn __toupper_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
21149 if c >= 'a' as i32 && c <= 'z' as i32 { c - 32 } else { c }
21150}
21151
21152#[no_mangle]
21153pub unsafe extern "C" fn ulimit(cmd: c_int, mut args: ...) -> c_long {
21154 let mut rl: Rlimit = core::mem::zeroed();
21155 if getrlimit(RLIMIT_FSIZE, &mut rl) != 0 { return -1; }
21156 if cmd == 2 {
21157 let val = args.next_arg::<c_long>();
21158 rl.rlim_cur = 512u64.wrapping_mul(val as u64);
21159 if setrlimit(RLIMIT_FSIZE, &rl) != 0 { return -1; }
21160 }
21161 (rl.rlim_cur / 512) as c_long
21162}
21163
21164#[repr(C)]
21165struct UtsName {
21166 sysname: [u8; 65],
21167 nodename: [u8; 65],
21168 release: [u8; 65],
21169 version: [u8; 65],
21170 machine: [u8; 65],
21171 domainname: [u8; 65],
21172}
21173
21174#[no_mangle]
21175pub unsafe extern "C" fn uname(buf: *mut c_void) -> c_int {
21176 let r = <Arch as Syscalls>::syscall1(SYS_UNAME, buf as i64);
21179 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
21180 0
21181}
21182
21183#[no_mangle]
21184pub unsafe extern "C" fn unshare(flags: i32) -> i32 {
21185 let r = <Arch as Syscalls>::syscall1(SYS_UNSHARE, flags as i64);
21186 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21187}
21188
21189#[no_mangle]
21190pub unsafe extern "C" fn updwtmpx(wtmpx_file: *const core::ffi::c_char, utx: *const core::ffi::c_void) {
21191 updwtmp(wtmpx_file, utx)
21192}
21193
21194#[no_mangle]
21195pub unsafe extern "C" fn __uselocale(loc: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
21196 loc
21197}
21198
21199#[repr(C)]
21200pub struct Utimbuf { actime: i64, modtime: i64 }
21201
21202#[no_mangle]
21203pub unsafe extern "C" fn utime(filename: *const c_char, times: *const Utimbuf) -> c_int {
21204 if times.is_null() {
21205 return utimensat(AT_FDCWD, filename, core::ptr::null(), 0);
21206 }
21207 let ts = [
21208 timespec { tv_sec: (*times).actime, tv_nsec: 0 },
21209 timespec { tv_sec: (*times).modtime, tv_nsec: 0 },
21210 ];
21211 utimensat(AT_FDCWD, filename, ts.as_ptr(), 0)
21212}
21213
21214#[no_mangle]
21215pub unsafe extern "C" fn vhangup() -> c_int {
21216 let r = <Arch as Syscalls>::syscall0(SYS_VHANGUP);
21217 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21218}
21219
21220#[no_mangle]
21221pub unsafe extern "C" fn vmsplice(fd: i32, iov: *const c_void, nr_segs: usize, flags: u32) -> isize {
21222 let r = <Arch as Syscalls>::syscall4(SYS_VMSPLICE, fd as i64, iov as i64, nr_segs as i64, flags as i64);
21223 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
21224}
21225
21226
21227
21228#[no_mangle]
21229pub unsafe extern "C" fn wait4(pid: i32, wstatus: *mut i32, options: i32, rusage: *mut core::ffi::c_void) -> i32 {
21230 syscall_ret(<Arch as Syscalls>::syscall4(SYS_WAIT4, pid as i64, wstatus as i64, options as i64, rusage as i64)) as i32
21231}
21232
21233#[no_mangle]
21234pub unsafe extern "C" fn waitid(idtype: i32, id: u32, infop: *mut core::ffi::c_void, options: i32) -> i32 {
21235 syscall_ret(<Arch as Syscalls>::syscall5(
21238 sysno(247, 95),
21239 idtype as i64,
21240 id as i64,
21241 infop as i64,
21242 options as i64,
21243 0,
21244 )) as i32
21245}
21246
21247#[no_mangle]
21248pub unsafe extern "C" fn __wcscoll_l(s1: *const u32, s2: *const u32, _loc: *mut core::ffi::c_void) -> i32 {
21249 crate::wcscmp(s1 as *const i32, s2 as *const i32)
21250}
21251
21252#[no_mangle]
21253pub unsafe extern "C" fn __wcsxfrm_l(dest: *mut u32, src: *const u32, n: usize, _loc: *mut core::ffi::c_void) -> usize {
21254 crate::wcscpy(dest as *mut i32, src as *const i32);
21255 n
21256}
21257
21258#[no_mangle]
21259pub unsafe extern "C" fn wcwidth(c: u32) -> i32 {
21260 if c == 0 { return 0; }
21261 if c < 32 || (c >= 0x7f && c < 0xa0) { return -1; }
21262 1
21263}
21264
21265
21266
21267
21268
21269#[no_mangle]
21276pub 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 {
21277 crate::strtod(nptr, endptr)
21278}
21279
21280#[no_mangle]
21281pub 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 {
21282 crate::strtof(nptr, endptr)
21283}
21284
21285#[no_mangle]
21286pub 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 {
21287 crate::strtod(nptr, endptr)
21288}
21289
21290#[repr(C)]
21295struct linux_dirent64 {
21296 d_ino: u64,
21297 d_off: i64,
21298 d_reclen: u16,
21299 d_type: u8,
21300 d_name: [u8; 0], }
21302
21303const DIR_BUF_SIZE: usize = 4096;
21307
21308#[repr(C)]
21309struct DirStream {
21310 fd: i32,
21311 pos: usize,
21312 len: usize,
21313 last_off: i64,
21314 buf: [u8; DIR_BUF_SIZE],
21315}
21316
21317unsafe fn dir_stream_new(fd: i32) -> *mut core::ffi::c_void {
21318 let ds = malloc(core::mem::size_of::<DirStream>()) as *mut DirStream;
21319 if ds.is_null() {
21320 crate::close(fd);
21321 ERRNO!() = ENOMEM;
21322 return core::ptr::null_mut();
21323 }
21324 core::ptr::write_bytes(ds, 0, 1);
21325 (*ds).fd = fd;
21326 ds as *mut core::ffi::c_void
21327}
21328
21329#[no_mangle]
21330pub unsafe extern "C" fn opendir(dirname: *const core::ffi::c_char) -> *mut core::ffi::c_void {
21331 let fd = openat(AT_FDCWD, dirname, O_DIRECTORY, 0); if fd < 0 { return core::ptr::null_mut(); }
21333 dir_stream_new(fd)
21334}
21335
21336#[no_mangle]
21337pub unsafe extern "C" fn closedir(dirp: *mut core::ffi::c_void) -> i32 {
21338 if dirp.is_null() { ERRNO!() = 22; return -1; }
21339 let ds = dirp as *mut DirStream;
21340 let r = crate::close((*ds).fd);
21341 free(dirp);
21342 r
21343}
21344
21345#[no_mangle]
21346pub unsafe extern "C" fn readdir(dirp: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
21347 if dirp.is_null() { ERRNO!() = 22; return core::ptr::null_mut(); }
21348 let ds = &mut *(dirp as *mut DirStream);
21349
21350 loop {
21351 if ds.pos >= ds.len {
21352 let nread = syscall_ret(<Arch as Syscalls>::syscall3(
21353 SYS_GETDENTS64,
21354 ds.fd as i64,
21355 ds.buf.as_mut_ptr() as i64,
21356 DIR_BUF_SIZE as i64,
21357 )) as isize;
21358 if nread <= 0 { return core::ptr::null_mut(); }
21359 ds.len = nread as usize;
21360 ds.pos = 0;
21361 }
21362
21363 let ent = ds.buf.as_ptr().add(ds.pos) as *const linux_dirent64;
21364 let ent_ref = &*ent;
21365 if ent_ref.d_reclen as usize == 0 {
21366 ds.len = 0;
21367 return core::ptr::null_mut();
21368 }
21369 ds.pos += ent_ref.d_reclen as usize;
21370 ds.last_off = ent_ref.d_off;
21371
21372 return ent as *mut core::ffi::c_void;
21374 }
21375}
21376
21377#[no_mangle]
21378pub 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 {
21379 let ent = readdir(dirp);
21380 if ent.is_null() {
21381 *result = core::ptr::null_mut();
21382 } else {
21383 *result = ent;
21384 }
21385 0
21386}
21387
21388#[no_mangle]
21389pub unsafe extern "C" fn seekdir(dirp: *mut core::ffi::c_void, loc: i64) {
21390 if dirp.is_null() { return; }
21391 let ds = &mut *(dirp as *mut DirStream);
21392 <Arch as Syscalls>::syscall3(SYS_LSEEK, ds.fd as i64, loc, 0);
21393 ds.pos = 0;
21394 ds.len = 0;
21395}
21396
21397#[no_mangle]
21398pub unsafe extern "C" fn telldir(dirp: *mut core::ffi::c_void) -> i64 {
21399 if dirp.is_null() { return -1; }
21400 (*(dirp as *mut DirStream)).last_off
21401}
21402
21403#[no_mangle]
21404pub unsafe extern "C" fn rewinddir(dirp: *mut core::ffi::c_void) {
21405 if dirp.is_null() { return; }
21406 let ds = &mut *(dirp as *mut DirStream);
21407 <Arch as Syscalls>::syscall3(SYS_LSEEK, ds.fd as i64, 0, 0);
21408 ds.pos = 0;
21409 ds.len = 0;
21410 ds.last_off = 0;
21411}
21412
21413#[no_mangle]
21414pub unsafe extern "C" fn dirfd(dirp: *mut core::ffi::c_void) -> i32 {
21415 if dirp.is_null() { ERRNO!() = 22; return -1; }
21416 (*(dirp as *mut DirStream)).fd
21417}
21418
21419#[no_mangle]
21424pub unsafe extern "C" fn mprotect(addr: *mut u8, len: usize, prot: i32) -> i32 {
21425 syscall_ret(<Arch as Syscalls>::syscall3(SYS_MPROTECT, addr as i64, len as i64, prot as i64)) as i32
21426}
21427
21428#[no_mangle]
21429pub unsafe extern "C" fn msync(addr: *mut u8, len: usize, flags: i32) -> i32 {
21430 syscall_ret(<Arch as Syscalls>::syscall3(sysno(26, 227), addr as i64, len as i64, flags as i64)) as i32
21431}
21432
21433#[no_mangle]
21434pub unsafe extern "C" fn mlock(addr: *const u8, len: usize) -> i32 {
21435 syscall_ret(<Arch as Syscalls>::syscall2(sysno(149, 228), addr as i64, len as i64)) as i32
21436}
21437
21438#[no_mangle]
21439pub unsafe extern "C" fn munlock(addr: *const u8, len: usize) -> i32 {
21440 syscall_ret(<Arch as Syscalls>::syscall2(sysno(150, 229), addr as i64, len as i64)) as i32
21441}
21442
21443#[no_mangle]
21444pub unsafe extern "C" fn mlockall(flags: i32) -> i32 {
21445 syscall_ret(<Arch as Syscalls>::syscall1(sysno(151, 230), flags as i64)) as i32
21446}
21447
21448#[no_mangle]
21449pub unsafe extern "C" fn munlockall() -> i32 {
21450 syscall_ret(<Arch as Syscalls>::syscall0(sysno(152, 231))) as i32
21451}
21452
21453#[no_mangle]
21454pub unsafe extern "C" fn madvise(addr: *mut u8, len: usize, advice: i32) -> i32 {
21455 syscall_ret(<Arch as Syscalls>::syscall3(sysno(28, 233), addr as i64, len as i64, advice as i64)) as i32
21456}
21457
21458#[no_mangle]
21459pub unsafe extern "C" fn mincore(addr: *mut u8, len: usize, vec: *mut u8) -> i32 {
21460 syscall_ret(<Arch as Syscalls>::syscall3(sysno(27, 232), addr as i64, len as i64, vec as i64)) as i32
21461}
21462
21463#[no_mangle]
21470pub unsafe extern "C" fn drem(x: f64, y: f64) -> f64 {
21471 remainder(x, y)
21472}
21473
21474#[no_mangle]
21475pub unsafe extern "C" fn dremf(x: f32, y: f32) -> f32 {
21476 remainderf(x, y)
21477}
21478
21479#[no_mangle]
21480pub unsafe extern "C" fn pow10(x: f64) -> f64 {
21481 libm::pow(10.0, x)
21482}
21483
21484#[no_mangle]
21485pub unsafe extern "C" fn pow10f(x: f32) -> f32 {
21486 libm::powf(10.0, x)
21487}
21488
21489#[no_mangle]
21490pub unsafe extern "C" fn pow10l(x: f64) -> f64 {
21491 libm::pow(10.0, x)
21492}
21493
21494#[no_mangle]
21495pub unsafe extern "C" fn isless(x: f64, y: f64) -> i32 {
21496 if x.is_nan() || y.is_nan() { 0 } else { (x < y) as i32 }
21497}
21498
21499#[no_mangle]
21500pub unsafe extern "C" fn islessf(x: f32, y: f32) -> i32 {
21501 if x.is_nan() || y.is_nan() { 0 } else { (x < y) as i32 }
21502}
21503
21504#[no_mangle]
21505pub unsafe extern "C" fn lgamma_r(x: f64, signgamp: *mut i32) -> f64 {
21506 lgamma_r_impl(x, signgamp)
21507}
21508
21509#[no_mangle]
21510pub unsafe extern "C" fn lgammaf_r(x: f32, signgamp: *mut i32) -> f32 {
21511 if x.is_nan() {
21512 if !signgamp.is_null() { *signgamp = 1; }
21513 return x;
21514 }
21515 if x == 0.0 {
21516 if !signgamp.is_null() { *signgamp = if x.is_sign_negative() { -1 } else { 1 }; }
21517 feraiseexcept(FE_DIVBYZERO);
21518 return f32::INFINITY;
21519 }
21520 let (r, sign) = libm::lgammaf_r(x);
21521 if !signgamp.is_null() { *signgamp = sign; }
21522 r
21523}
21524
21525#[no_mangle]
21526pub unsafe extern "C" fn lgammal_r(x: f64, signgamp: *mut i32) -> f64 {
21527 lgamma_r(x, signgamp)
21528}
21529
21530#[no_mangle]
21535pub unsafe extern "C" fn islessequal(x: f64, y: f64) -> i32 {
21536 if x.is_nan() || y.is_nan() { 0 } else { (x <= y) as i32 }
21537}
21538
21539#[no_mangle]
21540pub unsafe extern "C" fn islessequalf(x: f32, y: f32) -> i32 {
21541 if x.is_nan() || y.is_nan() { 0 } else { (x <= y) as i32 }
21542}
21543
21544#[no_mangle]
21545pub unsafe extern "C" fn islessgreater(x: f64, y: f64) -> i32 {
21546 if x.is_nan() || y.is_nan() { 0 } else { (x < y || x > y) as i32 }
21547}
21548
21549#[no_mangle]
21550pub unsafe extern "C" fn islessgreaterf(x: f32, y: f32) -> i32 {
21551 if x.is_nan() || y.is_nan() { 0 } else { (x < y || x > y) as i32 }
21552}
21553
21554#[no_mangle]
21555pub unsafe extern "C" fn isgreater(x: f64, y: f64) -> i32 {
21556 if x.is_nan() || y.is_nan() { 0 } else { (x > y) as i32 }
21557}
21558
21559#[no_mangle]
21560pub unsafe extern "C" fn isgreaterf(x: f32, y: f32) -> i32 {
21561 if x.is_nan() || y.is_nan() { 0 } else { (x > y) as i32 }
21562}
21563
21564#[no_mangle]
21565pub unsafe extern "C" fn isgreaterequal(x: f64, y: f64) -> i32 {
21566 if x.is_nan() || y.is_nan() { 0 } else { (x >= y) as i32 }
21567}
21568
21569#[no_mangle]
21570pub unsafe extern "C" fn isgreaterequalf(x: f32, y: f32) -> i32 {
21571 if x.is_nan() || y.is_nan() { 0 } else { (x >= y) as i32 }
21572}
21573
21574#[no_mangle]
21579pub unsafe extern "C" fn stpcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char {
21580 let mut d = dest;
21581 let mut s = src;
21582 while *s != 0 {
21583 *d = *s;
21584 d = d.add(1);
21585 s = s.add(1);
21586 }
21587 *d = 0;
21588 d
21589}
21590
21591#[no_mangle]
21592pub unsafe extern "C" fn stpncpy(dest: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
21593 let mut i = 0;
21594 while i < n && *src.add(i) != 0 {
21595 *dest.add(i) = *src.add(i);
21596 i += 1;
21597 }
21598 let end = dest.add(i);
21599 while i < n {
21600 *dest.add(i) = 0;
21601 i += 1;
21602 }
21603 end
21604}
21605
21606#[no_mangle]
21607pub unsafe extern "C" fn strchrnul(s: *const c_char, c: c_int) -> *mut c_char {
21608 let mut p = s;
21609 while *p != 0 && *p as c_int != c {
21610 p = p.add(1);
21611 }
21612 p as *mut c_char
21613}
21614
21615#[no_mangle]
21616pub unsafe extern "C" fn fstatat(dirfd: c_int, path: *const c_char, buf: *mut Stat, flags: c_int) -> c_int {
21617 let r = sys_newfstatat(dirfd, path, buf as *mut u8, flags);
21618 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21619}
21620
21621#[no_mangle]
21622pub unsafe extern "C" fn execvpe(
21623 file: *const c_char,
21624 argv: *const *const c_char,
21625 envp: *const *const c_char,
21626) -> c_int {
21627 ERRNO!() = ENOENT_VAL;
21628 if file.is_null() || *file == 0 {
21629 return -1;
21630 }
21631 let mut p = file;
21632 while *p != 0 {
21633 if *p == b'/' as c_char {
21634 return execve(file, argv, envp);
21635 }
21636 p = p.add(1);
21637 }
21638 let file_len = crate::strlen(file);
21639 let path = crate::getenv(b"PATH\0".as_ptr() as *const c_char);
21640 let default_path = b"/usr/local/bin:/bin:/usr/bin\0";
21641 let path = if path.is_null() { default_path.as_ptr() as *const c_char } else { path };
21642
21643 let mut seen_eacces = false;
21644 let mut buf = [0 as c_char; 4096];
21645 let mut dir = path;
21646 loop {
21647 let mut end = dir;
21648 while *end != 0 && *end != b':' as c_char { end = end.add(1); }
21649 let dlen = end.offset_from(dir) as usize;
21650 let need_slash = dlen > 0;
21652 let total = dlen + need_slash as usize + file_len;
21653 if total < buf.len() {
21654 let mut i = 0;
21655 while i < dlen { buf[i] = *dir.add(i); i += 1; }
21656 if need_slash { buf[i] = b'/' as c_char; i += 1; }
21657 let mut j = 0;
21658 while j < file_len { buf[i + j] = *file.add(j); j += 1; }
21659 buf[i + j] = 0;
21660 execve(buf.as_ptr(), argv, envp);
21661 match ERRNO!() {
21662 13 => seen_eacces = true, 2 | 20 => {} _ => return -1,
21665 }
21666 }
21667 if *end == 0 { break; }
21668 dir = end.add(1);
21669 }
21670 ERRNO!() = if seen_eacces { 13 } else { 2 };
21671 -1
21672}
21673
21674#[no_mangle]
21677pub unsafe extern "C" fn strcoll_l(s1: *const c_char, s2: *const c_char, _loc: locale_t) -> c_int {
21678 strcoll(s1, s2)
21679}
21680
21681#[no_mangle]
21682pub unsafe extern "C" fn strxfrm_l(dest: *mut c_char, src: *const c_char, n: usize, _loc: locale_t) -> usize {
21683 strxfrm(dest, src, n)
21684}
21685
21686#[no_mangle]
21687pub unsafe extern "C" fn strerror_l(errnum: c_int, _loc: locale_t) -> *mut c_char {
21688 strerror(errnum)
21689}
21690
21691#[no_mangle]
21692pub unsafe extern "C" fn strcasecmp_l(s1: *const c_char, s2: *const c_char, _loc: locale_t) -> c_int {
21693 strcasecmp(s1, s2)
21694}
21695
21696#[no_mangle]
21697pub unsafe extern "C" fn strncasecmp_l(s1: *const c_char, s2: *const c_char, n: usize, _loc: locale_t) -> c_int {
21698 strncasecmp(s1, s2, n)
21699}
21700
21701#[no_mangle]
21702pub unsafe extern "C" fn strftime_l(s: *mut c_char, max: usize, fmt: *const c_char, tm: *const tm, _loc: locale_t) -> usize {
21703 strftime(s, max, fmt, tm)
21704}
21705
21706#[no_mangle]
21707pub unsafe extern "C" fn nl_langinfo_l(item: c_int, _loc: locale_t) -> *mut c_char {
21708 nl_langinfo(item)
21709}
21710
21711#[no_mangle]
21712pub unsafe extern "C" fn wcscoll_l(s1: *const u32, s2: *const u32, _loc: locale_t) -> c_int {
21713 wcscoll(s1, s2)
21714}
21715
21716#[no_mangle]
21717pub unsafe extern "C" fn wcsxfrm_l(dst: *mut wchar_t, src: *const wchar_t, n: usize, _loc: locale_t) -> usize {
21718 wcsxfrm(dst, src, n)
21719}
21720
21721#[no_mangle]
21722pub unsafe extern "C" fn wcsftime_l(s: *mut u32, max: usize, fmt: *const u32, tm: *const c_void, _loc: locale_t) -> usize {
21723 wcsftime(s, max, fmt, tm)
21724}
21725
21726#[no_mangle]
21727pub unsafe extern "C" fn wctype_l(name: *const c_char, _loc: locale_t) -> wctype_t {
21728 wctype(name)
21729}
21730
21731#[no_mangle]
21732pub unsafe extern "C" fn wctrans_l(name: *const c_char, _loc: locale_t) -> wctrans_t {
21733 wctrans(name)
21734}
21735
21736#[no_mangle]
21737pub unsafe extern "C" fn towlower_l(c: wint_t, _loc: locale_t) -> wint_t {
21738 towlower(c)
21739}
21740
21741#[no_mangle]
21742pub unsafe extern "C" fn towupper_l(c: wint_t, _loc: locale_t) -> wint_t {
21743 towupper(c)
21744}
21745
21746#[no_mangle]
21747pub unsafe extern "C" fn towctrans_l(c: wint_t, desc: wctrans_t, _loc: locale_t) -> wint_t {
21748 towctrans(c, desc)
21749}
21750
21751#[no_mangle] pub unsafe extern "C" fn iswalnum_l(c: wint_t, _l: locale_t) -> c_int { iswalnum(c) }
21752#[no_mangle] pub unsafe extern "C" fn iswalpha_l(c: wint_t, _l: locale_t) -> c_int { iswalpha(c) }
21753#[no_mangle] pub unsafe extern "C" fn iswblank_l(c: wint_t, _l: locale_t) -> c_int { iswblank(c) }
21754#[no_mangle] pub unsafe extern "C" fn iswcntrl_l(c: wint_t, _l: locale_t) -> c_int { iswcntrl(c) }
21755#[no_mangle] pub unsafe extern "C" fn iswdigit_l(c: wint_t, _l: locale_t) -> c_int { iswdigit(c) }
21756#[no_mangle] pub unsafe extern "C" fn iswgraph_l(c: wint_t, _l: locale_t) -> c_int { iswgraph(c) }
21757#[no_mangle] pub unsafe extern "C" fn iswlower_l(c: wint_t, _l: locale_t) -> c_int { iswlower(c) }
21758#[no_mangle] pub unsafe extern "C" fn iswprint_l(c: wint_t, _l: locale_t) -> c_int { iswprint(c) }
21759#[no_mangle] pub unsafe extern "C" fn iswpunct_l(c: wint_t, _l: locale_t) -> c_int { iswpunct(c) }
21760#[no_mangle] pub unsafe extern "C" fn iswspace_l(c: wint_t, _l: locale_t) -> c_int { iswspace(c) }
21761#[no_mangle] pub unsafe extern "C" fn iswupper_l(c: wint_t, _l: locale_t) -> c_int { iswupper(c) }
21762#[no_mangle] pub unsafe extern "C" fn iswxdigit_l(c: wint_t, _l: locale_t) -> c_int { iswxdigit(c) }
21763#[no_mangle] pub unsafe extern "C" fn iswctype_l(c: wint_t, desc: wctype_t, _l: locale_t) -> c_int { iswctype(c, desc) }
21764
21765#[no_mangle] pub unsafe extern "C" fn __isoc99_scanf(fmt: *const c_char, args: ...) -> c_int { vfscanf(stdin, fmt, args) }
21767#[no_mangle] pub unsafe extern "C" fn __isoc99_fscanf(f: *mut FILE, fmt: *const c_char, args: ...) -> c_int { vfscanf(f, fmt, args) }
21768#[no_mangle] pub unsafe extern "C" fn __isoc99_sscanf(s: *const c_char, fmt: *const c_char, args: ...) -> c_int { vsscanf(s, fmt, args) }
21769#[no_mangle] pub unsafe extern "C" fn __isoc99_vscanf(fmt: *const c_char, args: VaList) -> c_int { vfscanf(stdin, fmt, args) }
21770#[no_mangle] pub unsafe extern "C" fn __isoc99_vfscanf(f: *mut FILE, fmt: *const c_char, args: VaList) -> c_int { vfscanf(f, fmt, args) }
21771#[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) }
21772#[no_mangle] pub unsafe extern "C" fn __isoc99_wscanf(fmt: *const wchar_t, args: ...) -> c_int { vfwscanf(stdin, fmt, args) }
21773#[no_mangle] pub unsafe extern "C" fn __isoc99_fwscanf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int { vfwscanf(f, fmt, args) }
21774#[no_mangle] pub unsafe extern "C" fn __isoc99_swscanf(s: *const wchar_t, fmt: *const wchar_t, args: ...) -> c_int { vswscanf(s, fmt, args) }
21775#[no_mangle] pub unsafe extern "C" fn __isoc99_vwscanf(fmt: *const wchar_t, args: VaList) -> c_int { vfwscanf(stdin, fmt, args) }
21776#[no_mangle] pub unsafe extern "C" fn __isoc99_vfwscanf(f: *mut FILE, fmt: *const wchar_t, args: VaList) -> c_int { vfwscanf(f, fmt, args) }
21777#[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) }
21778
21779#[no_mangle] pub unsafe extern "C" fn clearerr_unlocked(f: *mut FILE) { clearerr(f) }
21782#[no_mangle] pub unsafe extern "C" fn feof_unlocked(f: *mut FILE) -> c_int { feof(f) }
21783#[no_mangle] pub unsafe extern "C" fn ferror_unlocked(f: *mut FILE) -> c_int { ferror(f) }
21784#[no_mangle] pub unsafe extern "C" fn fileno_unlocked(f: *mut FILE) -> c_int { fileno(f) }
21785#[no_mangle] pub unsafe extern "C" fn fflush_unlocked(f: *mut FILE) -> c_int { fflush(f) }
21786#[no_mangle] pub unsafe extern "C" fn fgetc_unlocked(f: *mut FILE) -> c_int { fgetc(f) }
21787#[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) }
21788#[no_mangle] pub unsafe extern "C" fn fputc_unlocked(c: c_int, f: *mut FILE) -> c_int { fputc(c, f) }
21789#[no_mangle] pub unsafe extern "C" fn fputs_unlocked(s: *const c_char, f: *mut FILE) -> c_int { fputs(s, f) }
21790#[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) }
21791#[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) }
21792#[no_mangle] pub unsafe extern "C" fn fgetwc_unlocked(f: *mut FILE) -> wint_t { fgetwc(f) }
21793#[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) }
21794#[no_mangle] pub unsafe extern "C" fn fputwc_unlocked(c: wchar_t, f: *mut FILE) -> wint_t { fputwc(c, f) }
21795#[no_mangle] pub unsafe extern "C" fn fputws_unlocked(s: *const wchar_t, f: *mut FILE) -> c_int { fputws(s, f) }
21796#[no_mangle] pub unsafe extern "C" fn getwc_unlocked(f: *mut c_void) -> wint_t { getwc(f) }
21797#[no_mangle] pub unsafe extern "C" fn putwc_unlocked(c: u32, f: *mut c_void) -> wint_t { putwc(c, f) }
21798#[no_mangle] pub unsafe extern "C" fn getwchar_unlocked() -> wint_t { getwchar() }
21799#[no_mangle] pub unsafe extern "C" fn putwchar_unlocked(c: wchar_t) -> wint_t { putwchar(c) }
21800#[no_mangle] pub unsafe extern "C" fn fpurge(f: *mut FILE) { clearerr(f) }
21801#[no_mangle] pub unsafe extern "C" fn _IO_getc(f: *mut FILE) -> c_int { getc(f) }
21802#[no_mangle] pub unsafe extern "C" fn _IO_putc(c: c_int, f: *mut FILE) -> c_int { putc(c, f) }
21803#[no_mangle] pub unsafe extern "C" fn _IO_getc_unlocked(f: *mut FILE) -> c_int { getc(f) }
21804#[no_mangle] pub unsafe extern "C" fn _IO_putc_unlocked(c: c_int, f: *mut FILE) -> c_int { putc(c, f) }
21805#[no_mangle] pub unsafe extern "C" fn _IO_feof_unlocked(f: *mut FILE) -> c_int { feof(f) }
21806#[no_mangle] pub unsafe extern "C" fn _IO_ferror_unlocked(f: *mut FILE) -> c_int { ferror(f) }
21807
21808#[no_mangle] pub unsafe extern "C" fn __getauxval(t: c_ulong) -> c_ulong { getauxval(t) }
21810#[no_mangle] pub unsafe extern "C" fn __longjmp(env: *const c_ulong, val: c_int) -> ! { longjmp(env, val) }
21811#[no_mangle] pub unsafe extern "C" fn bsd_signal(sig: c_int, handler: usize) -> usize { signal(sig, handler) }
21812#[no_mangle] pub unsafe extern "C" fn __sysv_signal(sig: c_int, handler: usize) -> usize { signal(sig, handler) }
21813#[no_mangle] pub unsafe extern "C" fn eaccess(path: *const c_char, mode: c_int) -> c_int { access(path, mode) }
21814#[no_mangle] pub unsafe extern "C" fn __xpg_basename(path: *mut c_char) -> *mut c_char { basename(path) }
21815#[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) }
21816#[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) }
21817
21818#[no_mangle]
21823pub unsafe extern "C" fn cfsetspeed(termios_p: *mut c_void, speed: u32) -> c_int {
21824 let r = cfsetispeed(termios_p, speed);
21825 if r != 0 { return r; }
21826 cfsetospeed(termios_p, speed)
21827}
21828
21829#[no_mangle]
21830pub unsafe extern "C" fn futimesat(dirfd: c_int, path: *const c_char, times: *const timeval) -> c_int {
21831 if times.is_null() {
21832 return utimensat(dirfd, path, core::ptr::null(), 0);
21833 }
21834 let tv = times as *const [timeval; 2];
21835 let mut ts: [timespec; 2] = [
21836 timespec { tv_sec: (*tv)[0].tv_sec, tv_nsec: (*tv)[0].tv_usec * 1000 },
21837 timespec { tv_sec: (*tv)[1].tv_sec, tv_nsec: (*tv)[1].tv_usec * 1000 },
21838 ];
21839 for t in &mut ts {
21840 if t.tv_nsec < 0 || t.tv_nsec >= 1_000_000_000 {
21841 ERRNO!() = EINVAL;
21842 return -1;
21843 }
21844 }
21845 utimensat(dirfd, path, ts.as_ptr(), 0)
21846}
21847
21848#[no_mangle]
21849pub unsafe extern "C" fn membarrier(cmd: c_int, flags: c_int, cpu_id: c_int) -> c_int {
21850 <Arch as Syscalls>::syscall3(SYS_MEMBARRIER, cmd as i64, flags as i64, cpu_id as i64) as c_int
21851}
21852
21853#[no_mangle]
21854pub unsafe extern "C" fn mremap(
21855 old_address: *mut c_void,
21856 old_size: usize,
21857 new_size: usize,
21858 flags: c_int,
21859 mut args: ...
21860) -> *mut c_void {
21861 let new_address = if flags & 2 != 0 { args.next_arg::<*mut c_void>() } else { core::ptr::null_mut() };
21862 let r = <Arch as Syscalls>::syscall5(
21863 SYS_MREMAP,
21864 old_address as i64,
21865 old_size as i64,
21866 new_size as i64,
21867 flags as i64,
21868 new_address as i64,
21869 );
21870 if r < 0 {
21871 ERRNO!() = (-r) as c_int;
21872 return (-1isize) as *mut c_void;
21873 }
21874 r as *mut c_void
21875}
21876
21877#[no_mangle]
21878pub unsafe extern "C" fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: usize) -> c_int {
21879 let name = ptsname(fd);
21880 if name.is_null() { return -1; }
21881 let n = crate::strlen(name);
21882 if n + 1 > buflen {
21883 ERRNO!() = ERANGE_VAL;
21884 return ERANGE_VAL;
21885 }
21886 core::ptr::copy_nonoverlapping(name, buf, n + 1);
21887 0
21888}
21889
21890#[no_mangle]
21891pub unsafe extern "C" fn posix_getdents(fd: c_int, buf: *mut c_void, len: usize, flags: c_int) -> isize {
21892 if flags != 0 {
21893 ERRNO!() = EINVAL;
21894 return -1;
21895 }
21896 let r = <Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, buf as i64, len as i64);
21897 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
21898}
21899
21900#[no_mangle]
21901pub unsafe extern "C" fn riscv_flush_icache(start: *mut c_void, end: *mut c_void, flags: c_ulong) -> c_int {
21902 #[cfg(target_arch = "riscv64")]
21903 {
21904 let r = <Arch as Syscalls>::syscall3(259, start as i64, end as i64, flags as i64);
21905 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21906 }
21907 #[cfg(not(target_arch = "riscv64"))]
21908 {
21909 let _ = (start, end, flags);
21910 0
21911 }
21912}
21913
21914#[no_mangle]
21915pub unsafe extern "C" fn __riscv_flush_icache(start: *mut c_void, end: *mut c_void, flags: c_ulong) -> c_int {
21916 riscv_flush_icache(start, end, flags)
21917}
21918
21919#[no_mangle]
21920pub unsafe extern "C" fn mkostemps(template: *mut c_char, suffixlen: c_int, flags: c_int) -> c_int {
21921 let fd = mkstemps(template, suffixlen);
21922 if fd >= 0 && flags & O_CLOEXEC != 0 {
21923 sys_fcntl(fd, F_SETFD, FD_CLOEXEC as i64);
21924 }
21925 fd
21926}
21927
21928#[no_mangle]
21929pub unsafe extern "C" fn statfs(path: *const c_char, buf: *mut c_void) -> c_int {
21930 let r = <Arch as Syscalls>::syscall2(SYS_STATFS, path as i64, buf as i64);
21931 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21932}
21933
21934#[no_mangle]
21935pub unsafe extern "C" fn fstatfs(fd: c_int, buf: *mut c_void) -> c_int {
21936 let r = <Arch as Syscalls>::syscall2(SYS_FSTATFS, fd as i64, buf as i64);
21937 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21938}
21939
21940#[no_mangle]
21941pub unsafe extern "C" fn sysinfo(info: *mut c_void) -> c_int {
21942 let r = <Arch as Syscalls>::syscall1(SYS_SYSINFO, info as i64);
21943 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21944}
21945
21946#[no_mangle]
21947pub unsafe extern "C" fn pthread_tryjoin_np(thread: PthreadT, retval: *mut *mut c_void) -> c_int {
21948 let slot = thread as *mut Thread;
21949 if slot.is_null() { return EINVAL; }
21950 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
21951 let tid = core::ptr::read_volatile(&raw const (*slot).tid);
21952 if tid > 0 { return EBUSY; }
21953 if tid < 0 { return EINVAL; }
21954 pthread_join(thread, retval)
21955}
21956
21957#[no_mangle]
21958pub unsafe extern "C" fn pthread_timedjoin_np(thread: PthreadT, retval: *mut *mut c_void, abstime: *const timespec) -> c_int {
21959 let slot = thread as *mut Thread;
21960 if slot.is_null() { return EINVAL; }
21961 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
21962 loop {
21963 let r = pthread_tryjoin_np(thread, retval);
21964 if r != EBUSY { return r; }
21965 let tid = core::ptr::read_volatile(&raw const (*slot).tid);
21966 if tid <= 0 { continue; }
21967 let e = futex_timedwait(&raw mut (*slot).tid, tid, abstime);
21968 if e == ETIMEDOUT { return ETIMEDOUT; }
21969 }
21970}
21971
21972
21973#[repr(C)]
21976pub struct UtmpExit {
21977 pub e_termination: i16,
21978 pub e_exit: i16,
21979}
21980
21981#[repr(C)]
21982pub struct Utmpx {
21983 pub ut_type: i16,
21984 pub __ut_pad1: i16,
21985 pub ut_pid: i32,
21986 pub ut_line: [c_char; 32],
21987 pub ut_id: [c_char; 4],
21988 pub ut_user: [c_char; 32],
21989 pub ut_host: [c_char; 256],
21990 pub ut_exit: UtmpExit,
21991 pub ut_session: i32,
21992 pub __ut_pad2: i32,
21993 pub ut_tv: timeval,
21994 pub ut_addr_v6: [u32; 4],
21995 pub __unused: [u8; 20],
21996}
21997
21998const UTMP_SIZE: usize = 400;
21999const _: [(); UTMP_SIZE] = [(); core::mem::size_of::<Utmpx>()];
22000
22001static mut UTMP_FD: c_int = -1;
22002static mut UTMP_PATH: [u8; 256] = [0; 256];
22003static mut UTMP_PATH_SET: bool = false;
22004#[repr(align(8))]
22005struct UtmpBuf([u8; UTMP_SIZE]);
22006static mut UTMP_BUF: UtmpBuf = UtmpBuf([0; UTMP_SIZE]);
22007
22008unsafe fn utmp_path_ptr() -> *const c_char {
22009 if !UTMP_PATH_SET {
22010 let default = b"/var/run/utmp\0";
22011 let mut i = 0;
22012 while i < default.len() && i < UTMP_PATH.len() {
22013 UTMP_PATH[i] = default[i];
22014 i += 1;
22015 }
22016 UTMP_PATH_SET = true;
22017 }
22018 UTMP_PATH.as_ptr() as *const c_char
22019}
22020
22021unsafe fn utmp_open_read() -> c_int {
22022 if UTMP_FD >= 0 {
22023 crate::close(UTMP_FD);
22024 }
22025 UTMP_FD = crate::open(utmp_path_ptr(), 0, 0);
22026 UTMP_FD
22027}
22028
22029unsafe fn utmp_open_append() -> c_int {
22030 crate::open(utmp_path_ptr(), 1 | 64 | 1024, 0o644)
22031}
22032
22033#[no_mangle]
22034pub unsafe extern "C" fn setutent() {
22035 let _ = utmp_open_read();
22036}
22037
22038#[no_mangle]
22039pub unsafe extern "C" fn endutent() {
22040 if UTMP_FD >= 0 {
22041 crate::close(UTMP_FD);
22042 UTMP_FD = -1;
22043 }
22044}
22045
22046#[no_mangle]
22047pub unsafe extern "C" fn getutent() -> *mut c_void {
22048 if UTMP_FD < 0 && utmp_open_read() < 0 {
22049 return core::ptr::null_mut();
22050 }
22051 let n = crate::read(UTMP_FD, UTMP_BUF.0.as_mut_ptr() as *mut c_void, UTMP_SIZE);
22052 if n == UTMP_SIZE as isize {
22053 UTMP_BUF.0.as_mut_ptr() as *mut c_void
22054 } else {
22055 core::ptr::null_mut()
22056 }
22057}
22058
22059unsafe fn utmp_id_eq(a: &[c_char; 4], b: &[c_char; 4]) -> bool {
22060 a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]
22061}
22062
22063unsafe fn utmp_line_eq(a: &[c_char; 32], b: &[c_char; 32]) -> bool {
22064 let mut i = 0;
22065 while i < 32 {
22066 if a[i] != b[i] { return false; }
22067 if a[i] == 0 { return true; }
22068 i += 1;
22069 }
22070 true
22071}
22072
22073#[no_mangle]
22074pub unsafe extern "C" fn getutid(ut: *const c_void) -> *mut c_void {
22075 if ut.is_null() { return core::ptr::null_mut(); }
22076 let want = &*(ut as *const Utmpx);
22077 loop {
22078 let p = getutent();
22079 if p.is_null() { return p; }
22080 let cur = &*(p as *const Utmpx);
22081 let matched = match want.ut_type {
22082 1 | 2 | 3 | 4 => cur.ut_type == want.ut_type,
22083 _ => utmp_id_eq(&cur.ut_id, &want.ut_id)
22084 && (want.ut_type == 0 || cur.ut_type == want.ut_type),
22085 };
22086 if matched { return p; }
22087 }
22088}
22089
22090#[no_mangle]
22091pub unsafe extern "C" fn getutline(ut: *const c_void) -> *mut c_void {
22092 if ut.is_null() { return core::ptr::null_mut(); }
22093 let want = &*(ut as *const Utmpx);
22094 loop {
22095 let p = getutent();
22096 if p.is_null() { return p; }
22097 if utmp_line_eq(&(*(p as *const Utmpx)).ut_line, &want.ut_line) {
22098 return p;
22099 }
22100 }
22101}
22102
22103#[no_mangle]
22104pub unsafe extern "C" fn pututline(ut: *const c_void) -> *mut c_void {
22105 if ut.is_null() { return core::ptr::null_mut(); }
22106 let fd = utmp_open_append();
22107 if fd < 0 { return core::ptr::null_mut(); }
22108 let n = crate::write(fd, ut, UTMP_SIZE);
22109 crate::close(fd);
22110 if n == UTMP_SIZE as isize { ut as *mut c_void } else { core::ptr::null_mut() }
22111}
22112
22113#[no_mangle]
22114pub unsafe extern "C" fn updwtmp(file: *const c_char, ut: *const c_void) {
22115 if file.is_null() || ut.is_null() { return; }
22116 let fd = crate::open(file, 1 | 64 | 1024, 0o644);
22117 if fd >= 0 {
22118 let _ = crate::write(fd, ut, UTMP_SIZE);
22119 crate::close(fd);
22120 }
22121}
22122
22123unsafe fn utmp_set_name(file: *const c_char) -> c_int {
22124 if file.is_null() { return -1; }
22125 let len = crate::strlen(file);
22126 if len + 1 > UTMP_PATH.len() { return -1; }
22127 if UTMP_FD >= 0 {
22128 crate::close(UTMP_FD);
22129 UTMP_FD = -1;
22130 }
22131 core::ptr::copy_nonoverlapping(file, UTMP_PATH.as_mut_ptr() as *mut c_char, len + 1);
22132 UTMP_PATH_SET = true;
22133 0
22134}
22135
22136#[no_mangle]
22137pub unsafe extern "C" fn utmpname(file: *const c_char) -> c_int { utmp_set_name(file) }
22138
22139#[no_mangle]
22140pub unsafe extern "C" fn utmpxname(file: *const c_char) -> c_int { utmp_set_name(file) }
22141
22142
22143#[no_mangle] pub static mut ___environ: *mut *mut c_char = core::ptr::null_mut();
22145#[no_mangle] pub static mut _environ: *mut *mut c_char = core::ptr::null_mut();
22146#[no_mangle] pub unsafe extern "C" fn __freelocale(loc: locale_t) { freelocale(loc) }
22147#[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) }
22148#[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) }
22149#[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) }
22150#[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) }
22151
22152#[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) }
22153#[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) }
22154#[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) }
22155#[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) }
22156#[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) }
22157#[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) }
22158
22159const MAX_NS: usize = 3;
22164const MAX_SEARCH: usize = 6;
22165const HOST_NOT_FOUND: c_int = 1;
22166const TRY_AGAIN: c_int = 2;
22167const NO_RECOVERY: c_int = 3;
22168const NO_DATA: c_int = 4;
22169
22170static mut NS_COUNT: usize = 0;
22171static mut NS_ADDRS: [u32; MAX_NS] = [0; MAX_NS];
22172static mut SEARCH_COUNT: usize = 0;
22173static mut SEARCH_DOMAINS: [[u8; 256]; MAX_SEARCH] = [[0; 256]; MAX_SEARCH];
22174static mut RESOLV_INITIALIZED: bool = false;
22175
22176#[repr(C)]
22177struct SockAddrIn {
22178 sin_family: u16,
22179 sin_port: u16,
22180 sin_addr: u32,
22181 sin_zero: [u8; 8],
22182}
22183
22184#[repr(C)]
22185struct PollFd {
22186 fd: c_int,
22187 events: i16,
22188 revents: i16,
22189}
22190
22191unsafe fn resolv_skip_ws(line: &[u8], mut i: usize) -> usize {
22192 while i < line.len() && (line[i] == b' ' || line[i] == b'\t') { i += 1; }
22193 i
22194}
22195
22196unsafe fn resolv_token<'a>(line: &'a [u8], mut i: usize) -> (&'a [u8], usize) {
22197 let start = i;
22198 while i < line.len() && line[i] != b' ' && line[i] != b'\t' && line[i] != b'#' { i += 1; }
22199 (&line[start..i], i)
22200}
22201
22202unsafe fn resolv_parse_config() -> c_int {
22203 RESOLV_INITIALIZED = true;
22204 NS_COUNT = 0;
22205 SEARCH_COUNT = 0;
22206 let path = b"/etc/resolv.conf\0";
22207 let fd = crate::open(path.as_ptr() as *const c_char, 0, 0);
22208 if fd < 0 { return -1; }
22209 let mut buf = [0u8; 4096];
22210 let n = crate::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len());
22211 crate::close(fd);
22212 if n <= 0 { return -1; }
22213 let len = n as usize;
22214 let mut i = 0;
22215 while i < len {
22216 let start = i;
22217 while i < len && buf[i] != b'\n' { i += 1; }
22218 let line = &buf[start..i];
22219 i += 1;
22220 let mut j = resolv_skip_ws(line, 0);
22221 if j >= line.len() || line[j] == b'#' { continue; }
22222 let (key, next) = resolv_token(line, j);
22223 j = next;
22224 if key == b"nameserver" {
22225 j = resolv_skip_ws(line, j);
22226 let (tok, _) = resolv_token(line, j);
22227 if !tok.is_empty() && NS_COUNT < MAX_NS {
22228 let mut name = [0u8; 64];
22229 let l = core::cmp::min(tok.len(), 63);
22230 name[..l].copy_from_slice(&tok[..l]);
22231 let addr = crate::inet_addr(name.as_ptr() as *const c_char);
22232 if addr != u32::MAX {
22233 NS_ADDRS[NS_COUNT] = addr;
22234 NS_COUNT += 1;
22235 }
22236 }
22237 } else if key == b"search" || key == b"domain" {
22238 loop {
22239 j = resolv_skip_ws(line, j);
22240 if j >= line.len() || line[j] == b'#' { break; }
22241 let (tok, next) = resolv_token(line, j);
22242 j = next;
22243 if tok.is_empty() { break; }
22244 if SEARCH_COUNT < MAX_SEARCH {
22245 let l = core::cmp::min(tok.len(), 255);
22246 SEARCH_DOMAINS[SEARCH_COUNT][..l].copy_from_slice(&tok[..l]);
22247 SEARCH_DOMAINS[SEARCH_COUNT][l] = 0;
22248 SEARCH_COUNT += 1;
22249 }
22250 if key == b"domain" { break; }
22251 }
22252 }
22253 }
22254 0
22255}
22256
22257#[no_mangle]
22258pub unsafe extern "C" fn res_init() -> c_int {
22259 let _ = resolv_parse_config();
22260 0
22261}
22262
22263#[no_mangle]
22264pub unsafe extern "C" fn res_mkquery(
22265 op: c_int,
22266 dname: *const c_char,
22267 class: c_int,
22268 type_: c_int,
22269 _data: *const u8,
22270 _datalen: c_int,
22271 _newrr: *const u8,
22272 buf: *mut u8,
22273 buflen: c_int,
22274) -> c_int {
22275 if dname.is_null() || buf.is_null() { return -1; }
22276 let mut l = crate::strnlen(dname as *const u8, 255);
22277 if l > 0 && *dname.add(l - 1) == b'.' as c_char { l -= 1; }
22278 if l > 0 && *dname.add(l - 1) == b'.' as c_char { return -1; }
22279 let n = 17 + l + if l != 0 { 1 } else { 0 };
22280 if l > 253 || buflen < n as c_int || op < 0 || op > 15 || class < 0 || class > 255 || type_ < 0 || type_ > 255 {
22281 return -1;
22282 }
22283 let mut q = [0u8; 280];
22284 crate::memset(q.as_mut_ptr() as *mut c_void, 0, n);
22285 q[2] = (op * 8 + 1) as u8;
22286 q[3] = 32;
22287 q[5] = 1;
22288 core::ptr::copy_nonoverlapping(dname as *const u8, q.as_mut_ptr().add(13), l);
22289 let mut i = 13;
22290 while q[i] != 0 {
22291 let mut j = i;
22292 while q[j] != 0 && q[j] != b'.' { j += 1; }
22293 if j - i - 1 > 62 { return -1; }
22294 q[i - 1] = (j - i) as u8;
22295 i = j + 1;
22296 }
22297 q[i + 1] = type_ as u8;
22298 q[i + 3] = class as u8;
22299 let mut ts = timespec { tv_sec: 0, tv_nsec: 0 };
22300 let _ = clock_gettime(CLOCK_REALTIME, &mut ts);
22301 let id = (((ts.tv_nsec as u64) + (ts.tv_nsec as u64) / 65536) & 0xffff) as u16;
22302 q[0] = (id >> 8) as u8;
22303 q[1] = id as u8;
22304 core::ptr::copy_nonoverlapping(q.as_ptr(), buf, n);
22305 n as c_int
22306}
22307
22308unsafe fn res_send_inner(msg: *const u8, msglen: c_int, answer: *mut u8, anslen: c_int) -> c_int {
22309 if msg.is_null() || answer.is_null() || msglen < 12 || anslen < 12 { return -1; }
22310 if !RESOLV_INITIALIZED { let _ = resolv_parse_config(); }
22311 if NS_COUNT == 0 {
22312 h_errno = TRY_AGAIN;
22313 return -1;
22314 }
22315 for n in 0..NS_COUNT {
22316 let fd = crate::socket(AF_INET, SOCK_DGRAM, 0);
22317 if fd < 0 { continue; }
22318 let sa = SockAddrIn {
22319 sin_family: AF_INET as u16,
22320 sin_port: 53u16.to_be(),
22321 sin_addr: NS_ADDRS[n],
22322 sin_zero: [0; 8],
22323 };
22324 let sent = crate::sendto(fd, msg as *const c_void, msglen as usize, 0, &sa as *const SockAddrIn as *const crate::sockaddr, 16);
22325 if sent != msglen as isize {
22326 crate::close(fd);
22327 continue;
22328 }
22329 let mut pfd = PollFd { fd, events: 1, revents: 0 };
22330 let pr = crate::poll(&mut pfd as *mut PollFd as *mut c_void, 1, 5000);
22331 if pr <= 0 {
22332 crate::close(fd);
22333 continue;
22334 }
22335 let r = crate::recvfrom(fd, answer as *mut c_void, anslen as usize, 0, core::ptr::null_mut(), core::ptr::null_mut());
22336 crate::close(fd);
22337 if r >= 12 {
22338 let id_ok = *answer == *msg && *answer.add(1) == *msg.add(1);
22339 let qr = (*answer.add(2) & 0x80) != 0;
22340 if id_ok && qr {
22341 return r as c_int;
22342 }
22343 }
22344 }
22345 h_errno = TRY_AGAIN;
22346 -1
22347}
22348
22349#[no_mangle]
22350pub unsafe extern "C" fn res_send(msg: *const u8, msglen: c_int, answer: *mut u8, anslen: c_int) -> c_int {
22351 if anslen < 512 {
22352 let mut buf = [0u8; 512];
22353 let r = res_send_inner(msg, msglen, buf.as_mut_ptr(), 512);
22354 if r >= 0 {
22355 let copy = core::cmp::min(r, anslen) as usize;
22356 if copy > 0 { core::ptr::copy_nonoverlapping(buf.as_ptr(), answer, copy); }
22357 }
22358 return r;
22359 }
22360 res_send_inner(msg, msglen, answer, anslen)
22361}
22362
22363#[no_mangle]
22364pub unsafe extern "C" fn res_query(
22365 dname: *const c_char,
22366 class: c_int,
22367 type_: c_int,
22368 answer: *mut u8,
22369 anslen: c_int,
22370) -> c_int {
22371 let mut q = [0u8; 280];
22372 let ql = res_mkquery(0, dname, class, type_, core::ptr::null(), 0, core::ptr::null(), q.as_mut_ptr(), q.len() as c_int);
22373 if ql < 0 { return ql; }
22374 let r = res_send(q.as_ptr(), ql, answer, anslen);
22375 if r < 12 {
22376 h_errno = TRY_AGAIN;
22377 return -1;
22378 }
22379 let rcode = answer.add(3).read() & 0x0f;
22380 if rcode == 3 {
22381 h_errno = HOST_NOT_FOUND;
22382 return -1;
22383 }
22384 if rcode == 0 && *answer.add(6) == 0 && *answer.add(7) == 0 {
22385 h_errno = NO_DATA;
22386 return -1;
22387 }
22388 if rcode != 0 {
22389 h_errno = NO_RECOVERY;
22390 return -1;
22391 }
22392 r
22393}
22394
22395#[no_mangle]
22396pub unsafe extern "C" fn res_querydomain(
22397 name: *const c_char,
22398 domain: *const c_char,
22399 class: c_int,
22400 type_: c_int,
22401 answer: *mut u8,
22402 anslen: c_int,
22403) -> c_int {
22404 if domain.is_null() || *domain == 0 { return res_query(name, class, type_, answer, anslen); }
22405 let mut buf = [0u8; 512];
22406 let nl = crate::strlen(name);
22407 let dl = crate::strlen(domain);
22408 if nl + 1 + dl >= buf.len() { return -1; }
22409 core::ptr::copy_nonoverlapping(name, buf.as_mut_ptr() as *mut c_char, nl);
22410 buf[nl] = b'.';
22411 core::ptr::copy_nonoverlapping(domain, buf.as_mut_ptr().add(nl + 1) as *mut c_char, dl);
22412 buf[nl + 1 + dl] = 0;
22413 res_query(buf.as_ptr() as *const c_char, class, type_, answer, anslen)
22414}
22415
22416#[no_mangle]
22417pub unsafe extern "C" fn res_search(
22418 name: *const c_char,
22419 class: c_int,
22420 type_: c_int,
22421 answer: *mut u8,
22422 anslen: c_int,
22423) -> c_int {
22424 if name.is_null() { return -1; }
22425 if !RESOLV_INITIALIZED { let _ = resolv_parse_config(); }
22426 let len = crate::strlen(name);
22427 let mut dots = 0;
22428 for i in 0..len {
22429 if *name.add(i) == b'.' as c_char { dots += 1; }
22430 }
22431 let trailing_dot = len > 0 && *name.add(len - 1) == b'.' as c_char;
22432 if trailing_dot || dots >= 1 {
22433 let r = res_query(name, class, type_, answer, anslen);
22434 if r >= 0 { return r; }
22435 if trailing_dot { return -1; }
22436 }
22437 for i in 0..SEARCH_COUNT {
22438 let dom = SEARCH_DOMAINS[i].as_ptr() as *const c_char;
22439 let r = res_querydomain(name, dom, class, type_, answer, anslen);
22440 if r >= 0 { return r; }
22441 if h_errno != HOST_NOT_FOUND && h_errno != NO_DATA { return -1; }
22442 }
22443 if dots == 0 {
22444 return res_query(name, class, type_, answer, anslen);
22445 }
22446 -1
22447}
22448
22449#[repr(C)]
22454pub struct HostEnt {
22455 pub h_name: *mut c_char,
22456 pub h_aliases: *mut *mut c_char,
22457 pub h_addrtype: c_int,
22458 pub h_length: c_int,
22459 pub h_addr_list: *mut *mut c_char,
22460}
22461
22462#[repr(C)]
22463pub struct AddrInfo {
22464 pub ai_flags: c_int,
22465 pub ai_family: c_int,
22466 pub ai_socktype: c_int,
22467 pub ai_protocol: c_int,
22468 pub ai_addrlen: u32,
22469 pub ai_addr: *mut c_void,
22470 pub ai_canonname: *mut c_char,
22471 pub ai_next: *mut AddrInfo,
22472}
22473
22474static mut HOST_ENT: HostEnt = HostEnt {
22475 h_name: core::ptr::null_mut(),
22476 h_aliases: core::ptr::null_mut(),
22477 h_addrtype: 0,
22478 h_length: 0,
22479 h_addr_list: core::ptr::null_mut(),
22480};
22481static mut HOST_NAME: [c_char; 256] = [0; 256];
22482static mut HOST_ALIASES: [*mut c_char; 1] = [core::ptr::null_mut()];
22483static mut HOST_ADDR: [u8; 16] = [0; 16];
22484static mut HOST_ADDR_PTRS: [*mut c_char; 2] = [core::ptr::null_mut(); 2];
22485
22486unsafe fn dns_skip_name(p: *const u8, end: *const u8) -> *const u8 {
22487 let mut q = p;
22488 while q < end {
22489 let c = *q;
22490 if c == 0 { return q.add(1); }
22491 if c & 0xc0 == 0xc0 { return q.add(2); }
22492 q = q.add(1 + c as usize);
22493 }
22494 end
22495}
22496
22497unsafe fn dns_read_u16(p: *const u8) -> u16 {
22498 ((*p as u16) << 8) | *p.add(1) as u16
22499}
22500
22501unsafe fn dns_expand_name(p: *const u8, msg: *const u8, out: *mut c_char, outlen: usize) -> bool {
22502 let mut q = p;
22503 let mut o = 0usize;
22504 let mut jumps = 0;
22505 loop {
22506 let c = *q;
22507 if c == 0 {
22508 if o < outlen { *out.add(o) = 0; }
22509 return true;
22510 }
22511 if c & 0xc0 == 0xc0 {
22512 let off = (((c & 0x3f) as usize) << 8) | *q.add(1) as usize;
22513 q = msg.add(off);
22514 jumps += 1;
22515 if jumps > 16 { return false; }
22516 continue;
22517 }
22518 let l = c as usize;
22519 if l > 63 { return false; }
22520 if o + l + 1 >= outlen { return false; }
22521 core::ptr::copy_nonoverlapping(q.add(1), out.add(o) as *mut u8, l);
22522 o += l;
22523 *out.add(o) = b'.' as c_char;
22524 o += 1;
22525 q = q.add(1 + l);
22526 }
22527}
22528
22529unsafe fn host_from_answer(answer: *const u8, len: c_int, af: c_int) -> *mut HostEnt {
22530 if len < 12 { return core::ptr::null_mut(); }
22531 let end = answer.add(len as usize);
22532 let qd = dns_read_u16(answer.add(4)) as usize;
22533 let an = dns_read_u16(answer.add(6)) as usize;
22534 let mut p = answer.add(12);
22535 for _ in 0..qd {
22536 p = dns_skip_name(p, end);
22537 p = p.add(4);
22538 }
22539 let want_type: u16 = if af == AF_INET6 { 28 } else { 1 };
22540 let want_len = if af == AF_INET6 { 16 } else { 4 };
22541 for _ in 0..an {
22542 p = dns_skip_name(p, end);
22543 if p.add(10) > end { break; }
22544 let typ = dns_read_u16(p);
22545 let class = dns_read_u16(p.add(2));
22546 let rdlen = dns_read_u16(p.add(8)) as usize;
22547 let rdata = p.add(10);
22548 if rdata.add(rdlen) > end { break; }
22549 if typ == want_type && class == 1 && rdlen == want_len {
22550 core::ptr::copy_nonoverlapping(rdata, HOST_ADDR.as_mut_ptr(), want_len);
22551 HOST_ENT.h_addrtype = af;
22552 HOST_ENT.h_length = want_len as c_int;
22553 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
22554 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
22555 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
22556 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
22557 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
22558 h_errno = 0;
22559 return &raw mut HOST_ENT;
22560 }
22561 p = rdata.add(rdlen);
22562 }
22563 core::ptr::null_mut()
22564}
22565
22566#[no_mangle]
22567pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *mut HostEnt {
22568 gethostbyname2(name, AF_INET)
22569}
22570
22571#[no_mangle]
22572pub unsafe extern "C" fn gethostbyname2(name: *const c_char, af: c_int) -> *mut HostEnt {
22573 if name.is_null() { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
22574 let mut addr = [0u8; 16];
22575 let addrlen = if af == AF_INET6 { 16 } else { 4 };
22576 if inet_pton(af, name, addr.as_mut_ptr() as *mut c_void) == 1 {
22577 core::ptr::copy_nonoverlapping(addr.as_ptr(), HOST_ADDR.as_mut_ptr(), addrlen);
22578 let n = crate::strlen(name);
22579 let l = core::cmp::min(n, 255);
22580 core::ptr::copy_nonoverlapping(name, HOST_NAME.as_mut_ptr(), l);
22581 HOST_NAME[l] = 0;
22582 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
22583 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
22584 HOST_ENT.h_addrtype = af;
22585 HOST_ENT.h_length = addrlen as c_int;
22586 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
22587 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
22588 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
22589 h_errno = 0;
22590 return &raw mut HOST_ENT;
22591 }
22592 let mut answer = [0u8; 512];
22593 let qtype = if af == AF_INET6 { 28 } else { 1 };
22594 let r = res_query(name, 1, qtype, answer.as_mut_ptr(), answer.len() as c_int);
22595 if r < 0 {
22596 if h_errno == 0 { h_errno = TRY_AGAIN; }
22597 return core::ptr::null_mut();
22598 }
22599 let ent = host_from_answer(answer.as_ptr(), r, af);
22600 if !ent.is_null() {
22601 let n = crate::strlen(name);
22602 let l = core::cmp::min(n, 255);
22603 core::ptr::copy_nonoverlapping(name, HOST_NAME.as_mut_ptr(), l);
22604 HOST_NAME[l] = 0;
22605 } else {
22606 h_errno = HOST_NOT_FOUND;
22607 }
22608 ent
22609}
22610
22611#[no_mangle]
22612pub unsafe extern "C" fn gethostbyaddr(addr: *const c_void, len: u32, type_: c_int) -> *mut HostEnt {
22613 if addr.is_null() || type_ != AF_INET || len != 4 { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
22614 let a = addr as *const u8;
22615 let mut name = [0u8; 128];
22616 let mut pos = 0;
22617 for i in 0..4 {
22618 let v = *a.add(3 - i) as u32;
22619 if v >= 100 { name[pos] = b'0' + (v / 100) as u8; pos += 1; }
22620 if v >= 10 { name[pos] = b'0' + ((v / 10) % 10) as u8; pos += 1; }
22621 name[pos] = b'0' + (v % 10) as u8; pos += 1;
22622 name[pos] = b'.'; pos += 1;
22623 }
22624 let suffix = b"in-addr.arpa";
22625 for &c in suffix { name[pos] = c; pos += 1; }
22626 name[pos] = 0;
22627 let mut answer = [0u8; 512];
22628 let r = res_query(name.as_ptr() as *const c_char, 1, 12, answer.as_mut_ptr(), answer.len() as c_int);
22629 if r < 12 { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
22630 let end = answer.as_ptr().add(r as usize);
22631 let qd = dns_read_u16(answer.as_ptr().add(4)) as usize;
22632 let an = dns_read_u16(answer.as_ptr().add(6)) as usize;
22633 let mut p = answer.as_ptr().add(12);
22634 for _ in 0..qd { p = dns_skip_name(p, end); p = p.add(4); }
22635 for _ in 0..an {
22636 p = dns_skip_name(p, end);
22637 if p.add(10) > end { break; }
22638 let typ = dns_read_u16(p);
22639 let rdlen = dns_read_u16(p.add(8)) as usize;
22640 let rdata = p.add(10);
22641 if typ == 12 && dns_expand_name(rdata, answer.as_ptr(), HOST_NAME.as_mut_ptr(), HOST_NAME.len()) {
22642 let mut o = crate::strlen(HOST_NAME.as_ptr());
22643 if o > 0 && HOST_NAME[o - 1] == b'.' as c_char { o -= 1; }
22644 HOST_NAME[o] = 0;
22645 core::ptr::copy_nonoverlapping(a, HOST_ADDR.as_mut_ptr(), 4);
22646 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
22647 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
22648 HOST_ENT.h_addrtype = AF_INET;
22649 HOST_ENT.h_length = 4;
22650 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
22651 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
22652 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
22653 h_errno = 0;
22654 return &raw mut HOST_ENT;
22655 }
22656 p = rdata.add(rdlen);
22657 }
22658 h_errno = HOST_NOT_FOUND;
22659 core::ptr::null_mut()
22660}
22661
22662#[inline]
22667fn sysno(x86_64: i64, generic: i64) -> i64 {
22668 if cfg!(target_arch = "x86_64") { x86_64 } else { generic }
22669}
22670
22671#[no_mangle]
22672pub unsafe extern "C" fn settimeofday(tv: *const c_void, tz: *const c_void) -> c_int {
22673 let r = <Arch as Syscalls>::syscall2(sysno(164, 170), tv as i64, tz as i64);
22674 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22675}
22676
22677#[no_mangle]
22678pub unsafe extern "C" fn stime(t: *const i64) -> c_int {
22679 if t.is_null() { ERRNO!() = EINVAL; return -1; }
22680 let tv = timeval { tv_sec: *t, tv_usec: 0 };
22681 settimeofday(&tv as *const timeval as *const c_void, core::ptr::null())
22682}
22683
22684#[no_mangle]
22685pub unsafe extern "C" fn times(buf: *mut c_void) -> c_long {
22686 let r = <Arch as Syscalls>::syscall1(sysno(100, 153), buf as i64);
22687 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_long }
22688}
22689
22690#[no_mangle]
22691pub 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 {
22692 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);
22693 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22694}
22695
22696#[no_mangle]
22697pub unsafe extern "C" fn tee(fd_in: c_int, fd_out: c_int, len: usize, flags: u32) -> isize {
22698 let r = <Arch as Syscalls>::syscall4(sysno(276, 77), fd_in as i64, fd_out as i64, len as i64, flags as i64);
22699 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22700}
22701
22702#[no_mangle]
22703pub unsafe extern "C" fn statx(dirfd: c_int, path: *const c_char, flags: c_int, mask: u32, buf: *mut c_void) -> c_int {
22704 let r = <Arch as Syscalls>::syscall5(sysno(332, 291), dirfd as i64, path as i64, flags as i64, mask as i64, buf as i64);
22705 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22706}
22707
22708#[no_mangle]
22709pub unsafe extern "C" fn setns(fd: c_int, nstype: c_int) -> c_int {
22710 let r = <Arch as Syscalls>::syscall2(SYS_SETNS, fd as i64, nstype as i64);
22711 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22712}
22713
22714#[no_mangle]
22715pub unsafe extern "C" fn setfsuid(uid: u32) -> c_int {
22716 <Arch as Syscalls>::syscall1(sysno(122, 151), uid as i64) as c_int
22717}
22718
22719#[no_mangle]
22720pub unsafe extern "C" fn setfsgid(gid: u32) -> c_int {
22721 <Arch as Syscalls>::syscall1(sysno(123, 152), gid as i64) as c_int
22722}
22723
22724#[no_mangle]
22725pub unsafe extern "C" fn setregid(rgid: u32, egid: u32) -> c_int {
22726 let r = <Arch as Syscalls>::syscall2(sysno(114, 143), rgid as i64, egid as i64);
22727 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22728}
22729
22730#[no_mangle]
22731pub 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 {
22732 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);
22733 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22734}
22735
22736#[no_mangle]
22737pub 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 {
22738 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);
22739 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22740}
22741
22742#[no_mangle]
22743pub unsafe extern "C" fn tcgetwinsize(fd: c_int, ws: *mut c_void) -> c_int {
22744 if fd < 0 || ws.is_null() { ERRNO!() = EINVAL; return -1; }
22745 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5413, ws as i64);
22746 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22747}
22748
22749#[no_mangle]
22750pub unsafe extern "C" fn tcsetwinsize(fd: c_int, ws: *const c_void) -> c_int {
22751 if fd < 0 || ws.is_null() { ERRNO!() = EINVAL; return -1; }
22752 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5414, ws as i64);
22753 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22754}
22755
22756#[no_mangle]
22757pub unsafe extern "C" fn sockatmark(fd: c_int) -> c_int {
22758 let mut at: c_int = 0;
22759 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x8905, &mut at as *mut c_int as i64);
22760 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { at }
22761}
22762
22763#[no_mangle]
22764pub unsafe extern "C" fn isastream(fd: c_int) -> c_int {
22765 let mut buf = [0u8; 64];
22766 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5401, buf.as_mut_ptr() as i64);
22767 if r < 0 { ERRNO!() = (-r) as c_int; 0 } else { 1 }
22768}
22769
22770#[no_mangle]
22771pub unsafe extern "C" fn posix_madvise(addr: *mut c_void, len: usize, advice: c_int) -> c_int {
22772 madvise(addr as *mut u8, len, advice)
22773}
22774
22775#[no_mangle]
22776pub unsafe extern "C" fn secure_getenv(name: *const c_char) -> *mut c_char {
22777 if getauxval(23) != 0 { return core::ptr::null_mut(); }
22778 getenv(name)
22779}
22780
22781#[no_mangle]
22782pub unsafe extern "C" fn sigandset(dest: *mut c_ulong, left: *const c_ulong, right: *const c_ulong) -> c_int {
22783 if dest.is_null() || left.is_null() || right.is_null() { return -1; }
22784 *dest = *left & *right;
22785 0
22786}
22787
22788#[no_mangle]
22789pub unsafe extern "C" fn sigorset(dest: *mut c_ulong, left: *const c_ulong, right: *const c_ulong) -> c_int {
22790 if dest.is_null() || left.is_null() || right.is_null() { return -1; }
22791 *dest = *left | *right;
22792 0
22793}
22794
22795#[no_mangle]
22796pub unsafe extern "C" fn sigisemptyset(set: *const c_ulong) -> c_int {
22797 if set.is_null() { return 1; }
22798 (*set == 0) as c_int
22799}
22800
22801#[no_mangle]
22802pub unsafe extern "C" fn sighold(sig: c_int) -> c_int {
22803 let set: c_ulong = 1u64 << (sig - 1) as u32;
22804 sigprocmask(0, &set, core::ptr::null_mut());
22805 0
22806}
22807
22808#[no_mangle]
22809pub unsafe extern "C" fn sigignore(sig: c_int) -> c_int {
22810 let _ = signal(sig, 1);
22811 0
22812}
22813
22814#[no_mangle]
22815pub unsafe extern "C" fn sigrelse(sig: c_int) -> c_int {
22816 let set: c_ulong = 1u64 << (sig - 1) as u32;
22817 sigprocmask(1, &set, core::ptr::null_mut());
22818 0
22819}
22820
22821#[no_mangle]
22822pub unsafe extern "C" fn siginterrupt(sig: c_int, flag: c_int) -> c_int {
22823 let mut sa: sigaction = core::mem::zeroed();
22824 if sigaction(sig, core::ptr::null(), &mut sa) != 0 { return -1; }
22825 if flag != 0 { sa.sa_flags &= !(SA_RESTART as c_int); } else { sa.sa_flags |= SA_RESTART as c_int; }
22826 sigaction(sig, &sa, core::ptr::null_mut())
22827}
22828
22829#[no_mangle]
22830pub unsafe extern "C" fn sigpause(sig: c_int) -> c_int {
22831 let set: c_ulong = 1u64 << (sig - 1) as u32;
22832 sigsuspend(&set)
22833}
22834
22835#[no_mangle]
22836pub unsafe extern "C" fn semtimedop(semid: c_int, sops: *mut c_void, nsops: usize, timeout: *const timespec) -> c_int {
22837 let r = <Arch as Syscalls>::syscall4(sysno(220, 192), semid as i64, sops as i64, nsops as i64, timeout as i64);
22838 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
22839}
22840
22841#[no_mangle]
22842pub unsafe extern "C" fn wait3(status: *mut c_int, options: c_int, rusage: *mut c_void) -> i32 {
22843 wait4(-1, status, options, rusage) as i32
22844}
22845
22846#[no_mangle]
22847pub unsafe extern "C" fn tempnam(dir: *const c_char, pfx: *const c_char) -> *mut c_char {
22848 let mut path = [0 as c_char; 256];
22849 let mut i = 0;
22850 if !dir.is_null() {
22851 while *dir.add(i) != 0 && i < 200 { path[i] = *dir.add(i); i += 1; }
22852 if i > 0 && path[i-1] != b'/' as c_char { path[i] = b'/' as c_char; i += 1; }
22853 } else {
22854 for &c in b"/tmp/" { path[i] = c as c_char; i += 1; }
22855 }
22856 if !pfx.is_null() {
22857 let mut j = 0;
22858 while *pfx.add(j) != 0 && i < 220 { path[i] = *pfx.add(j); i += 1; j += 1; }
22859 }
22860 for &c in b"XXXXXX" { path[i] = c as c_char; i += 1; }
22861 path[i] = 0;
22862 let fd = mkstemp(path.as_mut_ptr());
22863 if fd < 0 { return core::ptr::null_mut(); }
22864 close(fd);
22865 unlink(path.as_ptr());
22866 let n = strlen(path.as_ptr());
22867 let out = malloc(n + 1) as *mut c_char;
22868 if out.is_null() { return core::ptr::null_mut(); }
22869 core::ptr::copy_nonoverlapping(path.as_ptr(), out, n + 1);
22870 out
22871}
22872
22873#[no_mangle]
22874pub unsafe extern "C" fn putwc(c: u32, f: *mut c_void) -> u32 {
22875 fputwc(c as c_int, f as *mut FILE) as u32
22876}
22877
22878#[no_mangle]
22879pub unsafe extern "C" fn __uflow(f: *mut c_void) -> c_int {
22880 fgetc(f as *mut FILE)
22881}
22882
22883#[no_mangle]
22884pub unsafe extern "C" fn __xmknod(_ver: c_int, path: *const c_char, mode: c_uint, dev: u64) -> c_int {
22885 mknod(path, mode, dev)
22886}
22887
22888#[no_mangle]
22889pub unsafe extern "C" fn __xmknodat(_ver: c_int, dirfd: c_int, path: *const c_char, mode: c_uint, dev: u64) -> c_int {
22890 mknodat(dirfd, path, mode, dev)
22891}
22892
22893#[no_mangle]
22894pub 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 {
22895 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);
22896 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22897}
22898
22899#[no_mangle]
22900pub unsafe extern "C" fn open_by_handle_at(mount_fd: c_int, handle: *mut c_void, flags: c_int) -> c_int {
22901 let r = <Arch as Syscalls>::syscall3(sysno(304, 265), mount_fd as i64, handle as i64, flags as i64);
22902 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
22903}
22904
22905#[no_mangle]
22906pub unsafe extern "C" fn dn_skipname(comp: *const u8, eom: *const u8) -> c_int {
22907 let p = dns_skip_name(comp, eom);
22908 if p <= eom { (p as isize - comp as isize) as c_int } else { -1 }
22909}
22910
22911#[no_mangle]
22912pub 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 {
22913 if exp.is_null() || dst.is_null() || dstsiz <= 0 { return -1; }
22914 let mut o = 0usize;
22915 let mut p = exp;
22916 loop {
22917 let start = p;
22918 while *p != 0 && *p != b'.' as c_char { p = p.add(1); }
22919 let l = p as usize - start as usize;
22920 if l > 63 || o + l + 2 > dstsiz as usize { return -1; }
22921 *dst.add(o) = l as u8; o += 1;
22922 core::ptr::copy_nonoverlapping(start as *const u8, dst.add(o), l);
22923 o += l;
22924 if *p == 0 { break; }
22925 p = p.add(1);
22926 }
22927 if o + 1 > dstsiz as usize { return -1; }
22928 *dst.add(o) = 0;
22929 (o + 1) as c_int
22930}
22931
22932#[repr(C)]
22937#[derive(Copy, Clone)]
22938pub struct Spwd {
22939 pub sp_namp: *mut c_char,
22940 pub sp_pwdp: *mut c_char,
22941 pub sp_lstchg: c_long,
22942 pub sp_min: c_long,
22943 pub sp_max: c_long,
22944 pub sp_warn: c_long,
22945 pub sp_inact: c_long,
22946 pub sp_expire: c_long,
22947 pub sp_flag: c_ulong,
22948}
22949
22950static mut SPWD_ENT: Spwd = Spwd {
22951 sp_namp: core::ptr::null_mut(), sp_pwdp: core::ptr::null_mut(),
22952 sp_lstchg: 0, sp_min: 0, sp_max: 0, sp_warn: 0, sp_inact: 0,
22953 sp_expire: 0, sp_flag: 0,
22954};
22955static mut SPWD_BUF: [c_char; 1024] = [0; 1024];
22956static mut SPWD_FILE: *mut FILE = core::ptr::null_mut();
22957
22958unsafe fn parse_spwd(line: *const c_char, ent: *mut Spwd, buf: *mut c_char, buflen: usize) -> bool {
22959 let mut src = line;
22960 let mut o = 0usize;
22961 let mut fields: [*mut c_char; 9] = [core::ptr::null_mut(); 9];
22962 let mut n = 0usize;
22963 while n < 9 {
22964 let start = o;
22965 while *src != 0 && *src != b':' as c_char {
22966 if o + 1 >= buflen { return false; }
22967 *buf.add(o) = *src;
22968 o += 1;
22969 src = src.add(1);
22970 }
22971 *buf.add(o) = 0;
22972 o += 1;
22973 fields[n] = buf.add(start);
22974 n += 1;
22975 if *src == 0 { break; }
22976 src = src.add(1);
22977 }
22978 if n < 9 { return false; }
22979 (*ent).sp_namp = fields[0];
22980 (*ent).sp_pwdp = fields[1];
22981 (*ent).sp_lstchg = crate::strtol(fields[2], core::ptr::null_mut(), 10) as c_long;
22982 (*ent).sp_min = crate::strtol(fields[3], core::ptr::null_mut(), 10) as c_long;
22983 (*ent).sp_max = crate::strtol(fields[4], core::ptr::null_mut(), 10) as c_long;
22984 (*ent).sp_warn = crate::strtol(fields[5], core::ptr::null_mut(), 10) as c_long;
22985 (*ent).sp_inact = crate::strtol(fields[6], core::ptr::null_mut(), 10) as c_long;
22986 (*ent).sp_expire = crate::strtol(fields[7], core::ptr::null_mut(), 10) as c_long;
22987 (*ent).sp_flag = crate::strtoul(fields[8], core::ptr::null_mut(), 10) as c_ulong;
22988 true
22989}
22990
22991#[no_mangle]
22992pub unsafe extern "C" fn setspent() {
22993 endspent();
22994 SPWD_FILE = crate::fopen(b"/etc/shadow\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
22995}
22996
22997#[no_mangle]
22998pub unsafe extern "C" fn endspent() {
22999 if !SPWD_FILE.is_null() { crate::fclose(SPWD_FILE); SPWD_FILE = core::ptr::null_mut(); }
23000}
23001
23002#[no_mangle]
23003pub unsafe extern "C" fn getspent() -> *mut Spwd {
23004 if SPWD_FILE.is_null() { setspent(); if SPWD_FILE.is_null() { return core::ptr::null_mut(); } }
23005 let mut line = [0 as c_char; 1024];
23006 loop {
23007 if crate::fgets(line.as_mut_ptr(), 1024, SPWD_FILE).is_null() { return core::ptr::null_mut(); }
23008 if parse_spwd(line.as_ptr(), &raw mut SPWD_ENT, SPWD_BUF.as_mut_ptr(), SPWD_BUF.len()) {
23009 return &raw mut SPWD_ENT;
23010 }
23011 }
23012}
23013
23014#[no_mangle]
23015pub unsafe extern "C" fn fgetspent(f: *mut FILE) -> *mut Spwd {
23016 if f.is_null() { return core::ptr::null_mut(); }
23017 let mut line = [0 as c_char; 1024];
23018 loop {
23019 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
23020 if parse_spwd(line.as_ptr(), &raw mut SPWD_ENT, SPWD_BUF.as_mut_ptr(), SPWD_BUF.len()) {
23021 return &raw mut SPWD_ENT;
23022 }
23023 }
23024}
23025
23026#[no_mangle]
23027pub unsafe extern "C" fn getspnam(name: *const c_char) -> *mut Spwd {
23028 if name.is_null() { return core::ptr::null_mut(); }
23029 setspent();
23030 loop {
23031 let sp = getspent();
23032 if sp.is_null() { break; }
23033 if crate::strcmp((*sp).sp_namp as *const u8, name as *const u8) == 0 { endspent(); return sp; }
23034 }
23035 endspent();
23036 core::ptr::null_mut()
23037}
23038
23039#[no_mangle]
23040pub 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 {
23041 if result.is_null() { return EINVAL; }
23042 let p = getspnam(name);
23043 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *sp = *p; *result = sp; 0 }
23044}
23045
23046#[no_mangle]
23047pub unsafe extern "C" fn putspent(sp: *const Spwd, f: *mut FILE) -> c_int {
23048 if sp.is_null() || f.is_null() { return -1; }
23049 crate::fprintf(f, b"%s:%s:%ld:%ld:%ld:%ld:%ld:%ld:%lu\\n\0".as_ptr() as *const c_char,
23050 (*sp).sp_namp, (*sp).sp_pwdp, (*sp).sp_lstchg, (*sp).sp_min, (*sp).sp_max,
23051 (*sp).sp_warn, (*sp).sp_inact, (*sp).sp_expire, (*sp).sp_flag)
23052}
23053
23054#[no_mangle]
23055pub unsafe extern "C" fn getgrouplist(user: *const c_char, group: u32, groups: *mut u32, ngroups: *mut i32) -> c_int {
23056 if user.is_null() || groups.is_null() || ngroups.is_null() { return -1; }
23057 let max = *ngroups as usize;
23058 let mut n = 0usize;
23059 if n < max { *groups.add(n) = group; }
23060 n += 1;
23061 setgrent();
23062 loop {
23063 let g = getgrent();
23064 if g.is_null() { break; }
23065 if (*g).gr_gid == group { continue; }
23066 let mut found = false;
23067 let mut i = 0;
23068 while !(*(*g).gr_mem.add(i)).is_null() {
23069 if crate::strcmp(*(*g).gr_mem.add(i) as *const u8, user as *const u8) == 0 {
23070 found = true;
23071 break;
23072 }
23073 i += 1;
23074 }
23075 if found {
23076 if n < max { *groups.add(n) = (*g).gr_gid; }
23077 n += 1;
23078 }
23079 }
23080 endgrent();
23081 if n > max { *ngroups = n as i32; return -1; }
23082 *ngroups = n as i32;
23083 n as c_int
23084}