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
9335#[no_mangle]
9336pub unsafe extern "C" fn __stack_chk_fail_local() -> ! {
9337 __stack_chk_fail()
9338}
9339
9340type CmpRfn = unsafe extern "C" fn(*const c_void, *const c_void, *mut c_void) -> c_int;
9345
9346const AR_LEN: usize = 16 * core::mem::size_of::<usize>();
9347const AR_MASK: usize = AR_LEN - 1;
9348
9349unsafe fn qsort_pntz(p: &[usize; 2]) -> i32 {
9350 if p[0] != 1 {
9351 p[0].wrapping_sub(1).trailing_zeros() as i32
9352 } else if p[1] != 0 {
9353 (8 * core::mem::size_of::<usize>()) as i32 + p[1].trailing_zeros() as i32
9354 } else {
9355 0
9356 }
9357}
9358
9359unsafe fn qsort_cycle(width: usize, ar: &mut [*mut u8; AR_LEN], n: usize) {
9360 if n < 2 { return; }
9361 let mut tmp = [0u8; 256];
9362 ar[n] = tmp.as_mut_ptr();
9363 let mut w = width;
9364 while w > 0 {
9365 let l = if 256 < w { 256 } else { w };
9366 core::ptr::copy_nonoverlapping(ar[0], ar[n], l);
9367 for i in 0..n {
9368 core::ptr::copy_nonoverlapping(ar[i + 1], ar[i], l);
9369 ar[i] = ar[i].add(l);
9370 }
9371 w -= l;
9372 }
9373}
9374
9375unsafe fn qsort_shl(p: &mut [usize; 2], n: i32) {
9376 let bits = (8 * core::mem::size_of::<usize>()) as i32;
9377 if n >= bits {
9378 p[1] = p[0];
9379 p[0] = 0;
9380 let n = n - bits;
9381 if n == 0 { return; }
9382 }
9383 p[1] = (p[1] << n) | (p[0] >> (bits - n));
9384 p[0] <<= n;
9385}
9386
9387unsafe fn qsort_shr(p: &mut [usize; 2], n: i32) {
9388 let bits = (8 * core::mem::size_of::<usize>()) as i32;
9389 if n >= bits {
9390 p[0] = p[1];
9391 p[1] = 0;
9392 let n = n - bits;
9393 if n == 0 { return; }
9394 }
9395 p[0] = (p[0] >> n) | (p[1] << (bits - n));
9396 p[1] >>= n;
9397}
9398
9399unsafe fn qsort_sift(
9400 head: *mut u8, width: usize,
9401 cmp: CmpRfn, arg: *mut c_void,
9402 pshift: i32, lp: &[usize],
9403) {
9404 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
9405 ar[0] = head;
9406 let mut i = 1usize;
9407 let mut h = head;
9408 let mut ps = pshift;
9409
9410 while ps > 1 {
9411 let rt = h.sub(width);
9412 let lf = h.sub(width + lp[(ps - 2) as usize]);
9413
9414 if cmp(ar[0] as *const c_void, lf as *const c_void, arg) >= 0
9415 && cmp(ar[0] as *const c_void, rt as *const c_void, arg) >= 0
9416 {
9417 break;
9418 }
9419 if cmp(lf as *const c_void, rt as *const c_void, arg) >= 0 {
9420 ar[i & AR_MASK] = lf;
9421 i += 1;
9422 h = lf;
9423 ps -= 1;
9424 } else {
9425 ar[i & AR_MASK] = rt;
9426 i += 1;
9427 h = rt;
9428 ps -= 2;
9429 }
9430 }
9431 qsort_cycle(width, &mut ar, i & AR_MASK);
9432}
9433
9434unsafe fn qsort_trinkle(
9435 head: *mut u8, width: usize,
9436 cmp: CmpRfn, arg: *mut c_void,
9437 pp: &[usize; 2], pshift: i32, trusty: i32,
9438 lp: &[usize],
9439) {
9440 let mut ar: [*mut u8; AR_LEN] = [core::ptr::null_mut(); AR_LEN];
9441 let mut p = *pp;
9442 ar[0] = head;
9443 let mut i = 1usize;
9444 let mut h = head;
9445 let mut ps = pshift;
9446 let mut t = trusty;
9447
9448 while p[0] != 1 || p[1] != 0 {
9449 let stepson = h.sub(lp[ps as usize]);
9450 if cmp(stepson as *const c_void, ar[0] as *const c_void, arg) <= 0 {
9451 break;
9452 }
9453 if t == 0 && ps > 1 {
9454 let rt = h.sub(width);
9455 let lf = h.sub(width + lp[(ps - 2) as usize]);
9456 if cmp(rt as *const c_void, stepson as *const c_void, arg) >= 0
9457 || cmp(lf as *const c_void, stepson as *const c_void, arg) >= 0
9458 {
9459 break;
9460 }
9461 }
9462
9463 ar[i & AR_MASK] = stepson;
9464 i += 1;
9465 h = stepson;
9466 let trail = qsort_pntz(&p);
9467 qsort_shr(&mut p, trail);
9468 ps += trail;
9469 t = 0;
9470 }
9471 if t == 0 {
9472 qsort_cycle(width, &mut ar, i & AR_MASK);
9473 qsort_sift(h, width, cmp, arg, ps, lp);
9474 }
9475}
9476
9477#[no_mangle]
9478pub unsafe extern "C" fn __qsort_r(
9479 base: *mut c_void,
9480 nel: usize,
9481 width: usize,
9482 cmp: CmpRfn,
9483 arg: *mut c_void,
9484) {
9485 let size = width * nel;
9486 if size == 0 { return; }
9487
9488 let mut lp = [0usize; 96];
9489 lp[0] = width;
9490 lp[1] = width;
9491 let mut li = 2;
9492 while {
9493 lp[li] = lp[li - 2] + lp[li - 1] + width;
9494 lp[li] < size
9495 } {
9496 li += 1;
9497 }
9498
9499 let mut head = base as *mut u8;
9500 let high = head.add(size - width);
9501 let mut p: [usize; 2] = [1, 0];
9502 let mut pshift: i32 = 1;
9503
9504 while head < high {
9505 if (p[0] & 3) == 3 {
9506 qsort_sift(head, width, cmp, arg, pshift, &lp);
9507 qsort_shr(&mut p, 2);
9508 pshift += 2;
9509 } else {
9510 if lp[(pshift - 1) as usize] >= (high as usize) - (head as usize) {
9511 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
9512 } else {
9513 qsort_sift(head, width, cmp, arg, pshift, &lp);
9514 }
9515
9516 if pshift == 1 {
9517 qsort_shl(&mut p, 1);
9518 pshift = 0;
9519 } else {
9520 qsort_shl(&mut p, pshift - 1);
9521 pshift = 1;
9522 }
9523 }
9524
9525 p[0] |= 1;
9526 head = head.add(width);
9527 }
9528
9529 qsort_trinkle(head, width, cmp, arg, &p, pshift, 0, &lp);
9530
9531 while pshift != 1 || p[0] != 1 || p[1] != 0 {
9532 if pshift <= 1 {
9533 let trail = qsort_pntz(&p);
9534 qsort_shr(&mut p, trail);
9535 pshift += trail;
9536 } else {
9537 qsort_shl(&mut p, 2);
9538 pshift -= 2;
9539 p[0] ^= 7;
9540 qsort_shr(&mut p, 1);
9541 qsort_trinkle(
9542 head.sub(lp[pshift as usize] + width),
9543 width, cmp, arg, &p, pshift + 1, 1, &lp,
9544 );
9545 qsort_shl(&mut p, 1);
9546 p[0] |= 1;
9547 qsort_trinkle(head.sub(width), width, cmp, arg, &p, pshift, 1, &lp);
9548 }
9549 head = head.sub(width);
9550 }
9551}
9552
9553#[no_mangle]
9554pub unsafe extern "C" fn qsort_r(
9555 base: *mut c_void,
9556 nel: usize,
9557 width: usize,
9558 cmp: CmpRfn,
9559 arg: *mut c_void,
9560) {
9561 __qsort_r(base, nel, width, cmp, arg);
9562}
9563
9564unsafe extern "C" fn qsort_wrap_cmp(
9565 a: *const c_void,
9566 b: *const c_void,
9567 cmp_ctx: *mut c_void,
9568) -> c_int {
9569 let cmp: CmpFn = core::mem::transmute(cmp_ctx);
9570 cmp(a, b)
9571}
9572
9573#[no_mangle]
9574pub unsafe extern "C" fn qsort(
9575 base: *mut c_void,
9576 nel: usize,
9577 width: usize,
9578 cmp: CmpFn,
9579) {
9580 __qsort_r(base, nel, width, qsort_wrap_cmp, cmp as *mut c_void);
9581}
9582
9583const ATEXIT_COUNT: usize = 32;
9588
9589#[repr(C)]
9590struct AtExitBlock {
9591 next: *mut AtExitBlock,
9592 f: [Option<unsafe extern "C" fn(*mut c_void)>; ATEXIT_COUNT],
9593 a: [*mut c_void; ATEXIT_COUNT],
9594}
9595
9596static mut ATEXIT_BUILTIN: AtExitBlock = AtExitBlock {
9597 next: core::ptr::null_mut(),
9598 f: [None; ATEXIT_COUNT],
9599 a: [core::ptr::null_mut(); ATEXIT_COUNT],
9600};
9601static mut ATEXIT_HEAD: *mut AtExitBlock = core::ptr::null_mut();
9602static mut ATEXIT_SLOT: usize = 0;
9603static mut ATEXIT_FINISHED: bool = false;
9604
9605#[no_mangle]
9606pub unsafe extern "C" fn __funcs_on_exit() {
9607 while !ATEXIT_HEAD.is_null() {
9608 let head = ATEXIT_HEAD;
9609 while ATEXIT_SLOT > 0 {
9610 ATEXIT_SLOT -= 1;
9611 if let Some(f) = (*head).f[ATEXIT_SLOT] {
9612 let a = (*head).a[ATEXIT_SLOT];
9613 f(a);
9614 }
9615 }
9616 ATEXIT_HEAD = (*head).next;
9617 ATEXIT_SLOT = ATEXIT_COUNT;
9618 }
9619 ATEXIT_FINISHED = true;
9620}
9621
9622#[no_mangle]
9623pub unsafe extern "C" fn __cxa_atexit(
9624 func: unsafe extern "C" fn(*mut c_void),
9625 arg: *mut c_void,
9626 _dso: *mut c_void,
9627) -> c_int {
9628 if ATEXIT_FINISHED {
9629 return -1;
9630 }
9631 if ATEXIT_HEAD.is_null() {
9632 ATEXIT_HEAD = core::ptr::addr_of_mut!(ATEXIT_BUILTIN);
9633 }
9634 if ATEXIT_SLOT == ATEXIT_COUNT {
9635 let new = calloc(1, core::mem::size_of::<AtExitBlock>()) as *mut AtExitBlock;
9636 if new.is_null() {
9637 return -1;
9638 }
9639 (*new).next = ATEXIT_HEAD;
9640 ATEXIT_HEAD = new;
9641 ATEXIT_SLOT = 0;
9642 }
9643 (*ATEXIT_HEAD).f[ATEXIT_SLOT] = Some(func);
9644 (*ATEXIT_HEAD).a[ATEXIT_SLOT] = arg;
9645 ATEXIT_SLOT += 1;
9646 0
9647}
9648
9649unsafe extern "C" fn atexit_caller(arg: *mut c_void) {
9650 let func: unsafe extern "C" fn() = core::mem::transmute(arg);
9651 func();
9652}
9653
9654#[no_mangle]
9655pub unsafe extern "C" fn atexit(func: unsafe extern "C" fn()) -> c_int {
9656 __cxa_atexit(atexit_caller, func as *mut c_void, core::ptr::null_mut())
9657}
9658
9659#[no_mangle]
9660pub unsafe extern "C" fn __cxa_finalize(_dso: *mut c_void) {}
9661
9662#[no_mangle]
9667pub static mut __environ: *mut *mut c_char = core::ptr::null_mut();
9668
9669const ENV_MAX_ALLOCED: usize = 256;
9671static mut ENV_ALLOCED: [*mut c_char; ENV_MAX_ALLOCED] = [core::ptr::null_mut(); ENV_MAX_ALLOCED];
9672static mut ENV_ALLOCED_N: usize = 0;
9673
9674unsafe fn env_rm_add(old: *mut c_char, mut new: *mut c_char) {
9675 for i in 0..ENV_ALLOCED_N {
9676 if ENV_ALLOCED[i] == old {
9677 ENV_ALLOCED[i] = new;
9678 if !old.is_null() {
9679 free(old as *mut c_void);
9680 }
9681 return;
9682 } else if ENV_ALLOCED[i].is_null() && !new.is_null() {
9683 ENV_ALLOCED[i] = new;
9684 new = core::ptr::null_mut();
9685 }
9686 }
9687 if !new.is_null() && ENV_ALLOCED_N < ENV_MAX_ALLOCED {
9688 ENV_ALLOCED[ENV_ALLOCED_N] = new;
9689 ENV_ALLOCED_N += 1;
9690 }
9691}
9692
9693unsafe fn strchrnul_u8(s: *const u8, c: u8) -> *const u8 {
9694 let mut p = s;
9695 while *p != 0 && *p != c {
9696 p = p.add(1);
9697 }
9698 p
9699}
9700
9701#[no_mangle]
9702pub unsafe extern "C" fn getenv(name: *const c_char) -> *mut c_char {
9703 if __environ.is_null() || name.is_null() {
9704 return core::ptr::null_mut();
9705 }
9706 let name = name as *const u8;
9707 let l = strchrnul_u8(name, b'=') as usize - name as usize;
9708 if l == 0 || *name.add(l) != 0 {
9709 return core::ptr::null_mut();
9710 }
9711 let mut e = __environ;
9712 while !(*e).is_null() {
9713 let entry = *e as *const u8;
9714 if strncmp(entry, name, l) == 0 && *entry.add(l) == b'=' {
9715 return entry.add(l + 1) as *mut c_char;
9716 }
9717 e = e.add(1);
9718 }
9719 core::ptr::null_mut()
9720}
9721
9722#[no_mangle]
9723pub unsafe extern "C" fn setenv(
9724 var: *const c_char,
9725 value: *const c_char,
9726 overwrite: c_int,
9727) -> c_int {
9728 if var.is_null() || value.is_null() {
9729 ERRNO!() = EINVAL;
9730 return -1;
9731 }
9732 let var = var as *const u8;
9733 let l1 = strchrnul_u8(var, b'=') as usize - var as usize;
9734 if l1 == 0 || *var.add(l1) != 0 {
9735 ERRNO!() = EINVAL;
9736 return -1;
9737 }
9738 if overwrite == 0 && !getenv(var as *const c_char).is_null() {
9739 return 0;
9740 }
9741 let l2 = strlen(value as *const c_char);
9742 let s = malloc(l1 + l2 + 2) as *mut u8;
9743 if s.is_null() {
9744 return -1;
9745 }
9746 core::ptr::copy_nonoverlapping(var, s, l1);
9747 *s.add(l1) = b'=';
9748 core::ptr::copy_nonoverlapping(value as *const u8, s.add(l1 + 1), l2 + 1);
9749 putenv_internal(s as *mut c_char, l1, s as *mut c_char)
9750}
9751
9752unsafe fn putenv_internal(s: *mut c_char, l: usize, r: *mut c_char) -> c_int {
9753 let mut i = 0;
9754 if !__environ.is_null() {
9755 let mut e = __environ;
9756 while !(*e).is_null() {
9757 if strncmp(s as *const u8, *e as *const u8, l + 1) == 0 {
9758 let tmp = *e;
9759 *e = s;
9760 env_rm_add(tmp, r);
9761 return 0;
9762 }
9763 e = e.add(1);
9764 i += 1;
9765 }
9766 }
9767 let newenv = malloc(core::mem::size_of::<*mut c_char>() * (i + 2)) as *mut *mut c_char;
9768 if newenv.is_null() {
9769 if !r.is_null() { free(r as *mut c_void); }
9770 return -1;
9771 }
9772 if i > 0 && !__environ.is_null() {
9773 core::ptr::copy_nonoverlapping(__environ, newenv, i);
9774 }
9775 *newenv.add(i) = s;
9776 *newenv.add(i + 1) = core::ptr::null_mut();
9777 __environ = newenv;
9779 environ = __environ;
9780 if !r.is_null() {
9781 env_rm_add(core::ptr::null_mut(), r);
9782 }
9783 0
9784}
9785
9786#[no_mangle]
9787pub unsafe extern "C" fn putenv(s: *mut c_char) -> c_int {
9788 if s.is_null() { return -1; }
9789 let l = strchrnul_u8(s as *const u8, b'=') as usize - s as *const u8 as usize;
9790 if l == 0 || *s.add(l) as u8 == 0 {
9791 return unsetenv(s);
9792 }
9793 putenv_internal(s, l, core::ptr::null_mut())
9794}
9795
9796#[no_mangle]
9797pub unsafe extern "C" fn unsetenv(name: *const c_char) -> c_int {
9798 if name.is_null() {
9799 ERRNO!() = EINVAL;
9800 return -1;
9801 }
9802 let name = name as *const u8;
9803 let l = strchrnul_u8(name, b'=') as usize - name as usize;
9804 if l == 0 || *name.add(l) != 0 {
9805 ERRNO!() = EINVAL;
9806 return -1;
9807 }
9808 if __environ.is_null() {
9809 return 0;
9810 }
9811 let mut e = __environ;
9812 let mut eo = e;
9813 while !(*e).is_null() {
9814 if strncmp(name, *e as *const u8, l) == 0 && *(*e as *const u8).add(l) == b'=' {
9815 env_rm_add(*e, core::ptr::null_mut());
9816 } else {
9817 if eo != e {
9818 *eo = *e;
9819 }
9820 eo = eo.add(1);
9821 }
9822 e = e.add(1);
9823 }
9824 if eo != e {
9825 *eo = core::ptr::null_mut();
9826 }
9827 environ = __environ;
9828 0
9829}
9830
9831#[no_mangle]
9832pub unsafe extern "C" fn clearenv() -> c_int {
9833 let e = __environ;
9834 __environ = core::ptr::null_mut();
9835 environ = core::ptr::null_mut();
9836 if !e.is_null() {
9837 let mut p = e;
9838 while !(*p).is_null() {
9839 env_rm_add(*p, core::ptr::null_mut());
9840 p = p.add(1);
9841 }
9842 }
9843 0
9844}
9845
9846static mut RANDOM_INIT: [u32; 32] = [
9852 0x00000000,0x5851f42d,0xc0b18ccf,0xcbb5f646,
9853 0xc7033129,0x30705b04,0x20fd5db4,0x9a8b7f78,
9854 0x502959d8,0xab894868,0x6c0356a7,0x88cdb7ff,
9855 0xb477d43f,0x70a3a52b,0xa8e4baf1,0xfd8341fc,
9856 0x8ae16fd9,0x742d2f7a,0x0d1f0796,0x76035e09,
9857 0x40f7702c,0x6fa72ca5,0xaaa84157,0x58a0df74,
9858 0xc74a0364,0xae533cc4,0x04185faf,0x6de3b115,
9859 0x0cab8628,0xf043bfa4,0x398150e9,0x37521657,
9860];
9861
9862static mut RANDOM_N: i32 = 31;
9863static mut RANDOM_I: i32 = 3;
9864static mut RANDOM_J: i32 = 0;
9865static mut RANDOM_X: *mut u32 = unsafe { core::ptr::addr_of_mut!(RANDOM_INIT).cast::<u32>().add(1) };
9866
9867unsafe fn random_lcg31(x: u32) -> u32 {
9868 (1103515245u32.wrapping_mul(x).wrapping_add(12345)) & 0x7fffffff
9869}
9870
9871unsafe fn random_lcg64(x: u64) -> u64 {
9872 6364136223846793005u64.wrapping_mul(x).wrapping_add(1)
9873}
9874
9875unsafe fn random_savestate() -> *mut u8 {
9876 (*RANDOM_X.offset(-1)) = ((RANDOM_N as u32) << 16) | ((RANDOM_I as u32) << 8) | (RANDOM_J as u32);
9877 RANDOM_X.offset(-1) as *mut u8
9878}
9879
9880unsafe fn random_loadstate(state: *mut u32) {
9881 RANDOM_X = state.add(1);
9882 RANDOM_N = ((*RANDOM_X.offset(-1)) >> 16) as i32;
9883 RANDOM_I = (((*RANDOM_X.offset(-1)) >> 8) & 0xff) as i32;
9884 RANDOM_J = ((*RANDOM_X.offset(-1)) & 0xff) as i32;
9885}
9886
9887unsafe fn random_srandom_inner(seed: u32) {
9888 let mut s = seed as u64;
9889 if RANDOM_N == 0 {
9890 *RANDOM_X = s as u32;
9891 return;
9892 }
9893 RANDOM_I = if RANDOM_N == 31 || RANDOM_N == 7 { 3 } else { 1 };
9894 RANDOM_J = 0;
9895 for k in 0..RANDOM_N as usize {
9896 s = random_lcg64(s);
9897 *RANDOM_X.add(k) = (s >> 32) as u32;
9898 }
9899 *RANDOM_X |= 1;
9900}
9901
9902#[no_mangle]
9903pub unsafe extern "C" fn srandom(seed: c_uint) {
9904 random_srandom_inner(seed);
9905}
9906
9907#[no_mangle]
9908pub unsafe extern "C" fn initstate(seed: c_uint, state: *mut c_char, size: usize) -> *mut c_char {
9909 if size < 8 { return core::ptr::null_mut(); }
9910 let old = random_savestate();
9911 RANDOM_N = if size < 32 { 0 }
9912 else if size < 64 { 7 }
9913 else if size < 128 { 15 }
9914 else if size < 256 { 31 }
9915 else { 63 };
9916 RANDOM_X = (state as *mut u32).add(1);
9917 random_srandom_inner(seed);
9918 random_savestate();
9919 old as *mut c_char
9920}
9921
9922#[no_mangle]
9923pub unsafe extern "C" fn setstate(state: *mut c_char) -> *mut c_char {
9924 let old = random_savestate();
9925 random_loadstate(state as *mut u32);
9926 old as *mut c_char
9927}
9928
9929#[no_mangle]
9930pub unsafe extern "C" fn random() -> c_long {
9931 let k: c_long;
9932 if RANDOM_N == 0 {
9933 *RANDOM_X = random_lcg31(*RANDOM_X);
9934 k = *RANDOM_X as c_long;
9935 } else {
9936 *RANDOM_X.add(RANDOM_I as usize) = (*RANDOM_X.add(RANDOM_I as usize)).wrapping_add(*RANDOM_X.add(RANDOM_J as usize));
9937 k = (*RANDOM_X.add(RANDOM_I as usize) >> 1) as c_long;
9938 RANDOM_I += 1;
9939 if RANDOM_I == RANDOM_N { RANDOM_I = 0; }
9940 RANDOM_J += 1;
9941 if RANDOM_J == RANDOM_N { RANDOM_J = 0; }
9942 }
9943 k
9944}
9945
9946const SA: u8 = 0xC2;
9951const SB: u8 = 0xF4;
9952
9953const BITTAB: [u32; 51] = [
9954 0xC000_0002, 0xC000_0003, 0xC000_0004, 0xC000_0005, 0xC000_0006, 0xC000_0007,
9955 0xC000_0008, 0xC000_0009, 0xC000_000A, 0xC000_000B, 0xC000_000C, 0xC000_000D,
9956 0xC000_000E, 0xC000_000F, 0xC000_0010, 0xC000_0011, 0xC000_0012, 0xC000_0013,
9957 0xC000_0014, 0xC000_0015, 0xC000_0016, 0xC000_0017, 0xC000_0018, 0xC000_0019,
9958 0xC000_001A, 0xC000_001B, 0xC000_001C, 0xC000_001D, 0xC000_001E, 0xC000_001F,
9959 0xB300_0000, 0xC300_0001, 0xC300_0002, 0xC300_0003, 0xC300_0004, 0xC300_0005,
9960 0xC300_0006, 0xC300_0007, 0xC300_0008, 0xC300_0009, 0xC300_000A, 0xC300_000B,
9961 0xC300_000C, 0xD300_000D, 0xC300_000E, 0xC300_000F, 0xBB0C_0000, 0xC30C_0001,
9962 0xC30C_0002, 0xC30C_0003, 0xDB0C_0004,
9963];
9964
9965#[inline]
9966fn mb_oob(c: u32, b: u8) -> u32 {
9967 let b3 = (b >> 3) as u32;
9968 ((b3.wrapping_sub(0x10)) | (b3.wrapping_add((c as i32 >> 26) as u32))) & !7
9969}
9970
9971static mut MB_STATE: c_uint = 0;
9972
9973const MB_CUR_MAX_VAL_UTF8: usize = 4;
9974const MB_CUR_MAX_VAL_C: usize = 1;
9975
9976#[no_mangle]
9977pub extern "C" fn __ctype_get_mb_cur_max() -> usize {
9978 unsafe { if LOCALE_CTYPE_UTF8 { MB_CUR_MAX_VAL_UTF8 } else { MB_CUR_MAX_VAL_C } }
9979}
9980
9981#[no_mangle]
9982pub unsafe extern "C" fn mbrtowc(
9983 wc: *mut c_int,
9984 src: *const c_char,
9985 n: usize,
9986 st: *mut c_uint,
9987) -> usize {
9988 let s = src as *const u8;
9989 let n0 = n;
9990 let mut dummy: c_int = 0;
9991 let wc = if wc.is_null() { &mut dummy } else { &mut *wc };
9992 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
9993
9994 let mut c: u32 = *st;
9995 let mut s = s;
9996 let mut n = n;
9997
9998 if s.is_null() {
9999 if c != 0 { *st = 0; ERRNO!() = EILSEQ; return !0usize; }
10000 return 0;
10001 }
10002
10003 if n == 0 { return !1usize; }
10004
10005 if unsafe { !LOCALE_CTYPE_UTF8 } {
10006 let b = *s;
10007 *wc = b as c_int;
10008 return if b == 0 { 0 } else { 1 };
10009 }
10010
10011 if c == 0 {
10012 if *s < 0x80 {
10013 let r = if *s == 0 { 0 } else { 1 };
10014 *wc = *s as c_int;
10015 return r;
10016 }
10017 if (*s).wrapping_sub(SA) as u32 > (SB - SA) as u32 {
10018 *st = 0; ERRNO!() = EILSEQ; return !0usize;
10019 }
10020 c = BITTAB[*s as usize - SA as usize];
10021 s = s.add(1);
10022 n -= 1;
10023 }
10024
10025 if n > 0 {
10026 if mb_oob(c, *s) != 0 {
10027 *st = 0; ERRNO!() = EILSEQ; return !0usize;
10028 }
10029 loop {
10030 c = (c << 6) | (*s as u32).wrapping_sub(0x80);
10031 s = s.add(1);
10032 n -= 1;
10033 if c & (1u32 << 31) == 0 {
10034 *st = 0;
10035 *wc = c as c_int;
10036 return n0 - n;
10037 }
10038 if n == 0 { break; }
10039 if (*s).wrapping_sub(0x80) >= 0x40 {
10040 *st = 0; ERRNO!() = EILSEQ; return !0usize;
10041 }
10042 }
10043 }
10044
10045 *st = c;
10046 !1usize
10047}
10048
10049#[no_mangle]
10050pub unsafe extern "C" fn wcrtomb(
10051 s: *mut c_char,
10052 wc: c_int,
10053 _st: *mut c_uint,
10054) -> usize {
10055 if s.is_null() { return 1; }
10056 let wc_u = wc as u32;
10057 if unsafe { !LOCALE_CTYPE_UTF8 } {
10058 if wc_u > 0xFF {
10059 ERRNO!() = EILSEQ;
10060 return !0usize;
10061 }
10062 *s = wc as c_char;
10063 return 1;
10064 }
10065 if wc_u < 0x80 {
10066 *s = wc as c_char;
10067 return 1;
10068 }
10069 if wc_u < 0x800 {
10070 *s = (0xC0 | (wc_u >> 6)) as c_char;
10071 *s.add(1) = (0x80 | (wc_u & 0x3F)) as c_char;
10072 return 2;
10073 }
10074 if wc_u < 0xD800 || wc_u.wrapping_sub(0xE000) < 0x2000 {
10075 *s = (0xE0 | (wc_u >> 12)) as c_char;
10076 *s.add(1) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
10077 *s.add(2) = (0x80 | (wc_u & 0x3F)) as c_char;
10078 return 3;
10079 }
10080 if wc_u.wrapping_sub(0x10000) < 0x100000 {
10081 *s = (0xF0 | (wc_u >> 18)) as c_char;
10082 *s.add(1) = (0x80 | ((wc_u >> 12) & 0x3F)) as c_char;
10083 *s.add(2) = (0x80 | ((wc_u >> 6) & 0x3F)) as c_char;
10084 *s.add(3) = (0x80 | (wc_u & 0x3F)) as c_char;
10085 return 4;
10086 }
10087 ERRNO!() = EILSEQ;
10088 !0usize
10089}
10090
10091#[no_mangle]
10092pub unsafe extern "C" fn mblen(s: *const c_char, n: usize) -> c_int {
10093 if s.is_null() { return 0; }
10094 mbtowc(core::ptr::null_mut(), s, n)
10095}
10096
10097#[no_mangle]
10098pub unsafe extern "C" fn mbtowc(
10099 wc: *mut c_int,
10100 src: *const c_char,
10101 n: usize,
10102) -> c_int {
10103 if src.is_null() { return 0; }
10104 if n == 0 { ERRNO!() = EILSEQ; return -1; }
10105 let mut state: c_uint = 0;
10106 let mut w: c_int = 0;
10107 let r = mbrtowc(&mut w, src, n, &mut state);
10108 if r == !0usize { return -1; }
10109 if !wc.is_null() { *wc = w; }
10110 r as c_int
10111}
10112
10113#[no_mangle]
10114pub unsafe extern "C" fn wctomb(s: *mut c_char, wc: c_int) -> c_int {
10115 if s.is_null() { return 0; }
10116 wcrtomb(s, wc, core::ptr::null_mut()) as c_int
10117}
10118
10119#[no_mangle]
10120pub unsafe extern "C" fn mbsrtowcs(
10121 ws: *mut c_int,
10122 src: *mut *const c_char,
10123 wn: usize,
10124 st: *mut c_uint,
10125) -> usize {
10126 let st: &mut c_uint = if st.is_null() { &mut *(&raw mut MB_STATE) } else { &mut *st };
10127 let mut s = *src as *const u8;
10128 let wn0 = wn;
10129 let mut wn = wn;
10130
10131 if ws.is_null() {
10132 while *s != 0 {
10133 if *s < 0x80 {
10134 s = s.add(1);
10135 wn = wn.wrapping_sub(1);
10136 continue;
10137 }
10138 let mut wc: c_int = 0;
10139 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
10140 if r == !0usize { return !0usize; }
10141 if r == !1usize { return wn0 - wn; }
10142 s = s.add(r);
10143 wn = wn.wrapping_sub(1);
10144 }
10145 wn0 - wn
10146 } else {
10147 let mut w = ws;
10148 while wn > 0 {
10149 if *s < 0x80 {
10150 let c = *s as c_int;
10151 *w = c;
10152 if c == 0 {
10153 *src = core::ptr::null();
10154 return wn0 - wn;
10155 }
10156 w = w.add(1);
10157 s = s.add(1);
10158 wn -= 1;
10159 continue;
10160 }
10161 let mut wc: c_int = 0;
10162 let r = mbrtowc(&mut wc, s as *const c_char, 4, st);
10163 if r == !0usize {
10164 *src = s as *const c_char;
10165 return !0usize;
10166 }
10167 if r == !1usize {
10168 *src = s as *const c_char;
10169 return wn0 - wn;
10170 }
10171 *w = wc;
10172 w = w.add(1);
10173 s = s.add(r);
10174 wn -= 1;
10175 }
10176 *src = s as *const c_char;
10177 wn0 - wn
10178 }
10179}
10180
10181#[no_mangle]
10182pub unsafe extern "C" fn wcsrtombs(
10183 s: *mut c_char,
10184 ws: *mut *const c_int,
10185 n: usize,
10186 _st: *mut c_uint,
10187) -> usize {
10188 let mut w = *ws;
10189 let n0 = n;
10190 let mut n = n;
10191
10192 if s.is_null() {
10193 let mut count = 0usize;
10194 while *w != 0 {
10195 if (*w as u32) < 0x80 {
10196 count += 1;
10197 } else {
10198 let mut buf = [0u8; 4];
10199 let r = wcrtomb(buf.as_mut_ptr() as *mut c_char, *w, core::ptr::null_mut());
10200 if r == !0usize { return !0usize; }
10201 count += r;
10202 }
10203 w = w.add(1);
10204 }
10205 return count;
10206 }
10207
10208 let mut dst = s;
10209 while n > 0 {
10210 if (*w as u32) < 0x80 {
10211 *dst = *w as c_char;
10212 if *w == 0 {
10213 *ws = core::ptr::null();
10214 return n0 - n;
10215 }
10216 dst = dst.add(1);
10217 n -= 1;
10218 } else {
10219 let r = wcrtomb(dst, *w, core::ptr::null_mut());
10220 if r == !0usize {
10221 *ws = w;
10222 return !0usize;
10223 }
10224 if r > n {
10225 *ws = w;
10226 return n0 - n;
10227 }
10228 dst = dst.add(r);
10229 n -= r;
10230 }
10231 w = w.add(1);
10232 }
10233 *ws = w;
10234 n0
10235}
10236
10237#[no_mangle]
10238pub unsafe extern "C" fn mbstowcs(
10239 ws: *mut c_int,
10240 src: *const c_char,
10241 wn: usize,
10242) -> usize {
10243 let mut src_ptr = src;
10244 mbsrtowcs(ws, &mut src_ptr, wn, core::ptr::null_mut())
10245}
10246
10247#[no_mangle]
10248pub unsafe extern "C" fn wcstombs(
10249 s: *mut c_char,
10250 ws: *const c_int,
10251 n: usize,
10252) -> usize {
10253 let mut ws_ptr = ws;
10254 wcsrtombs(s, &mut ws_ptr, n, core::ptr::null_mut())
10255}
10256
10257#[no_mangle]
10262pub extern "C" fn btowc(c: c_int) -> wint_t {
10263 if c == -1 { return WEOF; }
10264 unsafe {
10265 if LOCALE_CTYPE_UTF8 {
10266 if (c as u32) < 128 { c as wint_t } else { WEOF }
10267 } else {
10268 (c as u8) as wint_t
10269 }
10270 }
10271}
10272
10273#[no_mangle]
10274pub extern "C" fn wctob(c: wint_t) -> c_int {
10275 unsafe {
10276 if LOCALE_CTYPE_UTF8 {
10277 if c < 128 { c as c_int } else { -1 }
10278 } else {
10279 if c <= 0xFF { c as c_int } else { -1 }
10280 }
10281 }
10282}
10283
10284#[no_mangle]
10285pub unsafe extern "C" fn mbsinit(s: *const c_uint) -> c_int {
10286 if s.is_null() || *s == 0 { 1 } else { 0 }
10287}
10288
10289#[no_mangle]
10290pub unsafe extern "C" fn mbrlen(s: *const c_char, n: usize, ps: *mut c_uint) -> usize {
10291 mbrtowc(core::ptr::null_mut(), s, n, ps)
10292}
10293
10294#[no_mangle]
10299pub unsafe extern "C" fn wcslen(s: *const wchar_t) -> usize {
10300 let mut len = 0;
10301 while *s.add(len) != 0 { len += 1; }
10302 len
10303}
10304
10305#[no_mangle]
10306pub unsafe extern "C" fn wcschr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
10307 let mut i = 0;
10308 loop {
10309 let ch = *s.add(i);
10310 if ch == c { return s.add(i) as *mut wchar_t; }
10311 if ch == 0 { return null_mut(); }
10312 i += 1;
10313 }
10314}
10315
10316#[no_mangle]
10317pub unsafe extern "C" fn wcsrchr(s: *const wchar_t, c: wchar_t) -> *mut wchar_t {
10318 let mut i = 0;
10319 let mut last: *mut wchar_t = null_mut();
10320 loop {
10321 let ch = *s.add(i);
10322 if ch == c { last = s.add(i) as *mut wchar_t; }
10323 if ch == 0 { return last; }
10324 i += 1;
10325 }
10326}
10327
10328#[no_mangle]
10329pub unsafe extern "C" fn wcsstr(haystack: *const wchar_t, needle: *const wchar_t) -> *mut wchar_t {
10330 if *needle == 0 { return haystack as *mut wchar_t; }
10331 let mut i = 0;
10332 loop {
10333 let h = *haystack.add(i);
10334 if h == 0 { return null_mut(); }
10335 if h == *needle {
10336 let mut j = 0;
10337 loop {
10338 let n = *needle.add(j);
10339 if n == 0 { return haystack.add(i) as *mut wchar_t; }
10340 if *haystack.add(i + j) != n { break; }
10341 j += 1;
10342 }
10343 }
10344 i += 1;
10345 }
10346}
10347
10348#[no_mangle]
10349pub unsafe extern "C" fn wcscmp(s1: *const wchar_t, s2: *const wchar_t) -> c_int {
10350 let mut i = 0;
10351 loop {
10352 let a = *s1.add(i);
10353 let b = *s2.add(i);
10354 if a != b { return a - b; }
10355 if a == 0 { return 0; }
10356 i += 1;
10357 }
10358}
10359
10360#[no_mangle]
10361pub unsafe extern "C" fn wcsncmp(s1: *const wchar_t, s2: *const wchar_t, n: usize) -> c_int {
10362 let mut i = 0;
10363 while i < n {
10364 let a = *s1.add(i);
10365 let b = *s2.add(i);
10366 if a != b { return a - b; }
10367 if a == 0 { return 0; }
10368 i += 1;
10369 }
10370 0
10371}
10372
10373#[no_mangle]
10374pub unsafe extern "C" fn wcscpy(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
10375 let mut i = 0;
10376 loop {
10377 let c = *src.add(i);
10378 *dst.add(i) = c;
10379 if c == 0 { break; }
10380 i += 1;
10381 }
10382 dst
10383}
10384
10385#[no_mangle]
10386pub unsafe extern "C" fn wcsncpy(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
10387 let mut i = 0;
10388 while i < n && *src.add(i) != 0 { *dst.add(i) = *src.add(i); i += 1; }
10389 while i < n { *dst.add(i) = 0; i += 1; }
10390 dst
10391}
10392
10393#[no_mangle]
10394pub unsafe extern "C" fn wcscat(dst: *mut wchar_t, src: *const wchar_t) -> *mut wchar_t {
10395 let mut i = 0;
10396 while *dst.add(i) != 0 { i += 1; }
10397 let mut j = 0;
10398 loop {
10399 let c = *src.add(j);
10400 *dst.add(i + j) = c;
10401 if c == 0 { break; }
10402 j += 1;
10403 }
10404 dst
10405}
10406
10407#[no_mangle]
10408pub unsafe extern "C" fn wcsncat(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> *mut wchar_t {
10409 let mut i = 0;
10410 while *dst.add(i) != 0 { i += 1; }
10411 let mut j = 0;
10412 while j < n && *src.add(j) != 0 { *dst.add(i + j) = *src.add(j); j += 1; }
10413 *dst.add(i + j) = 0;
10414 dst
10415}
10416
10417#[no_mangle]
10418pub unsafe extern "C" fn wcsdup(s: *const wchar_t) -> *mut wchar_t {
10419 let len = wcslen(s);
10420 let p = malloc((len + 1) * core::mem::size_of::<wchar_t>()) as *mut wchar_t;
10421 if p.is_null() { return null_mut(); }
10422 core::ptr::copy_nonoverlapping(s, p, len + 1);
10423 p
10424}
10425
10426#[no_mangle]
10427pub unsafe extern "C" fn wcsnlen(s: *const wchar_t, maxlen: usize) -> usize {
10428 let mut i = 0;
10429 while i < maxlen && *s.add(i) != 0 { i += 1; }
10430 i
10431}
10432
10433#[no_mangle]
10434pub unsafe extern "C" fn wcsspn(s: *const wchar_t, accept: *const wchar_t) -> usize {
10435 let mut i = 0;
10436 loop {
10437 let c = *s.add(i);
10438 if c == 0 { return i; }
10439 let mut found = false;
10440 let mut j = 0;
10441 loop {
10442 let a = *accept.add(j);
10443 if a == 0 { break; }
10444 if c == a { found = true; break; }
10445 j += 1;
10446 }
10447 if !found { return i; }
10448 i += 1;
10449 }
10450}
10451
10452#[no_mangle]
10453pub unsafe extern "C" fn wcscspn(s: *const wchar_t, reject: *const wchar_t) -> usize {
10454 let mut i = 0;
10455 loop {
10456 let c = *s.add(i);
10457 if c == 0 { return i; }
10458 let mut j = 0;
10459 loop {
10460 let r = *reject.add(j);
10461 if r == 0 { break; }
10462 if c == r { return i; }
10463 j += 1;
10464 }
10465 i += 1;
10466 }
10467}
10468
10469#[no_mangle]
10470pub unsafe extern "C" fn wcspbrk(s: *const wchar_t, accept: *const wchar_t) -> *mut wchar_t {
10471 let mut i = 0;
10472 loop {
10473 let c = *s.add(i);
10474 if c == 0 { return null_mut(); }
10475 let mut j = 0;
10476 loop {
10477 let a = *accept.add(j);
10478 if a == 0 { break; }
10479 if c == a { return s.add(i) as *mut wchar_t; }
10480 j += 1;
10481 }
10482 i += 1;
10483 }
10484}
10485
10486#[no_mangle]
10487pub unsafe extern "C" fn wcsxfrm(dst: *mut wchar_t, src: *const wchar_t, n: usize) -> usize {
10488 let len = wcslen(src);
10489 if !dst.is_null() {
10490 let copy = if len < n { len } else { if n > 0 { n - 1 } else { 0 } };
10491 for i in 0..copy { *dst.add(i) = *src.add(i); }
10492 if n > 0 { *dst.add(copy) = 0; }
10493 }
10494 len
10495}
10496
10497unsafe fn wcs_to_bytes(ws: *const wchar_t, buf: *mut u8, bufsz: usize) -> usize {
10502 let mut i = 0;
10503 while i < bufsz - 1 {
10504 let c = *ws.add(i);
10505 if c == 0 { break; }
10506 if (c as u32) > 127 { break; }
10507 *buf.add(i) = c as u8;
10508 i += 1;
10509 }
10510 *buf.add(i) = 0;
10511 i
10512}
10513
10514#[no_mangle]
10515pub unsafe extern "C" fn wcstol(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_long {
10516 let mut buf = [0u8; 256];
10517 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10518 let mut end: *mut c_char = core::ptr::null_mut();
10519 let r = strtol(buf.as_ptr() as *const c_char, &mut end, base);
10520 if !endptr.is_null() {
10521 let offset = end as usize - buf.as_ptr() as usize;
10522 *endptr = s.add(offset) as *mut wchar_t;
10523 }
10524 r
10525}
10526
10527#[no_mangle]
10528pub unsafe extern "C" fn wcstoul(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulong {
10529 let mut buf = [0u8; 256];
10530 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10531 let mut end: *mut c_char = core::ptr::null_mut();
10532 let r = strtoul(buf.as_ptr() as *const c_char, &mut end, base);
10533 if !endptr.is_null() {
10534 let offset = end as usize - buf.as_ptr() as usize;
10535 *endptr = s.add(offset) as *mut wchar_t;
10536 }
10537 r
10538}
10539
10540#[no_mangle]
10541pub unsafe extern "C" fn wcstoll(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong {
10542 let mut buf = [0u8; 256];
10543 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10544 let mut end: *mut c_char = core::ptr::null_mut();
10545 let r = strtoll(buf.as_ptr() as *const c_char, &mut end, base);
10546 if !endptr.is_null() {
10547 let offset = end as usize - buf.as_ptr() as usize;
10548 *endptr = s.add(offset) as *mut wchar_t;
10549 }
10550 r
10551}
10552
10553#[no_mangle]
10554pub unsafe extern "C" fn wcstoull(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong {
10555 let mut buf = [0u8; 256];
10556 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10557 let mut end: *mut c_char = core::ptr::null_mut();
10558 let r = strtoull(buf.as_ptr() as *const c_char, &mut end, base);
10559 if !endptr.is_null() {
10560 let offset = end as usize - buf.as_ptr() as usize;
10561 *endptr = s.add(offset) as *mut wchar_t;
10562 }
10563 r
10564}
10565
10566#[no_mangle]
10567pub unsafe extern "C" fn wcstod(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 {
10568 let mut buf = [0u8; 256];
10569 wcs_to_bytes(s, buf.as_mut_ptr(), 256);
10570 let mut end: *mut c_char = core::ptr::null_mut();
10571 let r = strtod(buf.as_ptr() as *const c_char, &mut end);
10572 if !endptr.is_null() {
10573 let offset = end as usize - buf.as_ptr() as usize;
10574 *endptr = s.add(offset) as *mut wchar_t;
10575 }
10576 r
10577}
10578
10579#[no_mangle]
10580pub unsafe extern "C" fn wcstof(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f32 { wcstod(s, endptr) as f32 }
10581
10582#[no_mangle]
10583#[cfg(target_arch = "x86_64")]
10584pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f64 { wcstod(s, endptr) }
10585
10586#[no_mangle]
10587#[cfg(target_arch = "aarch64")]
10588pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
10589
10590#[no_mangle]
10591#[cfg(target_arch = "riscv64")]
10592pub unsafe extern "C" fn wcstold(s: *const wchar_t, endptr: *mut *mut wchar_t) -> f128 { wcstod(s, endptr) as f128 }
10593
10594#[no_mangle]
10595pub unsafe extern "C" fn wcstoimax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_longlong { wcstoll(s, endptr, base) }
10596
10597#[no_mangle]
10598pub unsafe extern "C" fn wcstoumax(s: *const wchar_t, endptr: *mut *mut wchar_t, base: c_int) -> c_ulonglong { wcstoull(s, endptr, base) }
10599
10600const WC_ALPHA: c_int = 1;
10605const WC_DIGIT: c_int = 2;
10606const WC_SPACE: c_int = 4;
10607const WC_UPPER: c_int = 8;
10608const WC_LOWER: c_int = 16;
10609const WC_ALNUM: c_int = WC_ALPHA | WC_DIGIT;
10610const WC_BLANK: c_int = 32;
10611const WC_CNTRL: c_int = 64;
10612const WC_PUNCT: c_int = 128;
10613const WC_GRAPH: c_int = WC_ALNUM | WC_PUNCT;
10614const WC_PRINT: c_int = WC_GRAPH | WC_BLANK;
10615const WC_XDIGIT: c_int = 256;
10616
10617fn wc_flags(c: wint_t) -> c_int {
10618 if c < 128 {
10619 let f = CT_TABLE[c as usize];
10620 let mut r = 0;
10621 if f & (CT_UPPER | CT_LOWER) != 0 { r |= WC_ALPHA; }
10622 if f & CT_DIGIT != 0 { r |= WC_DIGIT; }
10623 if f & CT_SPACE != 0 { r |= WC_SPACE; }
10624 if f & CT_UPPER != 0 { r |= WC_UPPER; }
10625 if f & CT_LOWER != 0 { r |= WC_LOWER; }
10626 if f & CT_BLANK != 0 { r |= WC_BLANK; }
10627 if f & CT_CNTRL != 0 { r |= WC_CNTRL; }
10628 if f & CT_PUNCT != 0 { r |= WC_PUNCT; }
10629 if f & CT_XDIGIT != 0 { r |= WC_XDIGIT; }
10630 r
10631 } else {
10632 if c < 0x100 { 0 }
10633 else { WC_PRINT | WC_ALPHA }
10634 }
10635}
10636
10637#[no_mangle]
10638pub extern "C" fn iswalnum(c: wint_t) -> c_int { (wc_flags(c) & WC_ALNUM != 0) as c_int }
10639#[no_mangle]
10640pub extern "C" fn iswalpha(c: wint_t) -> c_int { (wc_flags(c) & WC_ALPHA != 0) as c_int }
10641#[no_mangle]
10642pub extern "C" fn iswblank(c: wint_t) -> c_int { (wc_flags(c) & WC_BLANK != 0) as c_int }
10643#[no_mangle]
10644pub extern "C" fn iswcntrl(c: wint_t) -> c_int { (wc_flags(c) & WC_CNTRL != 0) as c_int }
10645#[no_mangle]
10646pub extern "C" fn iswdigit(c: wint_t) -> c_int { ((c >= b'0' as wint_t) && (c <= b'9' as wint_t)) as c_int }
10647#[no_mangle]
10648pub extern "C" fn iswgraph(c: wint_t) -> c_int { (wc_flags(c) & WC_GRAPH != 0) as c_int }
10649#[no_mangle]
10650pub extern "C" fn iswlower(c: wint_t) -> c_int { (wc_flags(c) & WC_LOWER != 0) as c_int }
10651#[no_mangle]
10652pub extern "C" fn iswprint(c: wint_t) -> c_int {
10653 if c < 128 { (wc_flags(c) & WC_PRINT != 0) as c_int }
10654 else if c >= 0x100 && c < 0x110000 { 1 }
10655 else { 0 }
10656}
10657#[no_mangle]
10658pub extern "C" fn iswpunct(c: wint_t) -> c_int { (wc_flags(c) & WC_PUNCT != 0) as c_int }
10659#[no_mangle]
10660pub extern "C" fn iswspace(c: wint_t) -> c_int {
10661 if c < 128 { (wc_flags(c) & WC_SPACE != 0) as c_int }
10662 else {
10663 match c {
10664 0x1680 | 0x2000..=0x200A | 0x2028 | 0x2029 | 0x202F | 0x205F | 0x3000 => 1,
10665 _ => 0,
10666 }
10667 }
10668}
10669#[no_mangle]
10670pub extern "C" fn iswupper(c: wint_t) -> c_int { (wc_flags(c) & WC_UPPER != 0) as c_int }
10671#[no_mangle]
10672pub extern "C" fn iswxdigit(c: wint_t) -> c_int { (wc_flags(c) & WC_XDIGIT != 0) as c_int }
10673
10674static WCTYPE_ALNUM: c_int = WC_ALNUM;
10675static WCTYPE_ALPHA: c_int = WC_ALPHA;
10676static WCTYPE_BLANK: c_int = WC_BLANK;
10677static WCTYPE_CNTRL: c_int = WC_CNTRL;
10678static WCTYPE_DIGIT: c_int = WC_DIGIT;
10679static WCTYPE_GRAPH: c_int = WC_GRAPH;
10680static WCTYPE_LOWER: c_int = WC_LOWER;
10681static WCTYPE_PRINT: c_int = WC_PRINT;
10682static WCTYPE_PUNCT: c_int = WC_PUNCT;
10683static WCTYPE_SPACE: c_int = WC_SPACE;
10684static WCTYPE_UPPER: c_int = WC_UPPER;
10685static WCTYPE_XDIGIT: c_int = WC_XDIGIT;
10686
10687#[no_mangle]
10688pub unsafe extern "C" fn wctype(name: *const c_char) -> wctype_t {
10689 if name.is_null() { return core::ptr::null(); }
10690 let n = name as *const u8;
10691 if strcmp(n, b"alnum\0".as_ptr()) == 0 { return &WCTYPE_ALNUM; }
10692 if strcmp(n, b"alpha\0".as_ptr()) == 0 { return &WCTYPE_ALPHA; }
10693 if strcmp(n, b"blank\0".as_ptr()) == 0 { return &WCTYPE_BLANK; }
10694 if strcmp(n, b"cntrl\0".as_ptr()) == 0 { return &WCTYPE_CNTRL; }
10695 if strcmp(n, b"digit\0".as_ptr()) == 0 { return &WCTYPE_DIGIT; }
10696 if strcmp(n, b"graph\0".as_ptr()) == 0 { return &WCTYPE_GRAPH; }
10697 if strcmp(n, b"lower\0".as_ptr()) == 0 { return &WCTYPE_LOWER; }
10698 if strcmp(n, b"print\0".as_ptr()) == 0 { return &WCTYPE_PRINT; }
10699 if strcmp(n, b"punct\0".as_ptr()) == 0 { return &WCTYPE_PUNCT; }
10700 if strcmp(n, b"space\0".as_ptr()) == 0 { return &WCTYPE_SPACE; }
10701 if strcmp(n, b"upper\0".as_ptr()) == 0 { return &WCTYPE_UPPER; }
10702 if strcmp(n, b"xdigit\0".as_ptr()) == 0 { return &WCTYPE_XDIGIT; }
10703 core::ptr::null()
10704}
10705
10706#[no_mangle]
10707pub unsafe extern "C" fn iswctype(c: wint_t, desc: wctype_t) -> c_int {
10708 if desc.is_null() { return 0; }
10709 (wc_flags(c) & *desc != 0) as c_int
10710}
10711
10712static WCTRANS_LOWER: c_int = 1;
10713static WCTRANS_UPPER: c_int = 2;
10714
10715#[no_mangle]
10716pub unsafe extern "C" fn towlower(c: wint_t) -> wint_t {
10717 if c < 128 { tolower(c as c_int) as wint_t } else { c }
10718}
10719
10720#[no_mangle]
10721pub unsafe extern "C" fn towupper(c: wint_t) -> wint_t {
10722 if c < 128 { toupper(c as c_int) as wint_t } else { c }
10723}
10724
10725#[no_mangle]
10726pub unsafe extern "C" fn wctrans(name: *const c_char) -> wctrans_t {
10727 if name.is_null() { return core::ptr::null(); }
10728 let n = name as *const u8;
10729 if strcmp(n, b"tolower\0".as_ptr()) == 0 { return &WCTRANS_LOWER; }
10730 if strcmp(n, b"toupper\0".as_ptr()) == 0 { return &WCTRANS_UPPER; }
10731 core::ptr::null()
10732}
10733
10734#[no_mangle]
10735pub unsafe extern "C" fn towctrans(c: wint_t, desc: wctrans_t) -> wint_t {
10736 if desc.is_null() { return c; }
10737 match *desc {
10738 1 => towlower(c),
10739 2 => towupper(c),
10740 _ => c,
10741 }
10742}
10743
10744#[no_mangle]
10749pub unsafe extern "C" fn fgetwc(f: *mut FILE) -> wint_t {
10750 let mut state: c_uint = 0;
10751 let mut wc: wchar_t = 0;
10752 let mut buf = [0u8; 4];
10753 let c = fgetc(f);
10754 if c == -1 { return WEOF; }
10755 buf[0] = c as u8;
10756 if buf[0] < 0x80 { return buf[0] as wint_t; }
10757 let len = if buf[0] < 0xE0 { 2 } else if buf[0] < 0xF0 { 3 } else { 4 };
10758 let mut n = 1usize;
10759 while n < len {
10760 let c2 = fgetc(f);
10761 if c2 == -1 { return WEOF; }
10762 buf[n] = c2 as u8;
10763 n += 1;
10764 }
10765 let r = mbrtowc(&mut wc, buf.as_ptr() as *const c_char, n, &mut state);
10766 if r == !0usize || r == !1usize { WEOF } else { wc as wint_t }
10767}
10768
10769#[no_mangle]
10770pub unsafe extern "C" fn fputwc(c: wchar_t, f: *mut FILE) -> wint_t {
10771 let mut buf = [0u8; 4];
10772 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c, core::ptr::null_mut());
10773 if n == !0usize || n == 0 { return WEOF; }
10774 if fwrite(buf.as_ptr() as *const c_void, 1, n, f) != n { return WEOF; }
10775 c as wint_t
10776}
10777
10778#[no_mangle]
10779pub unsafe extern "C" fn fputws(s: *const wchar_t, f: *mut FILE) -> c_int {
10780 let mut i = 0;
10781 while *s.add(i) != 0 {
10782 if fputwc(*s.add(i), f) == WEOF { return -1; }
10783 i += 1;
10784 }
10785 0
10786}
10787
10788#[no_mangle]
10789pub unsafe extern "C" fn ungetwc(c: wint_t, f: *mut FILE) -> wint_t {
10790 if c == WEOF { return WEOF; }
10791 let mut buf = [0u8; 4];
10792 let n = wcrtomb(buf.as_mut_ptr() as *mut c_char, c as wchar_t, core::ptr::null_mut());
10793 if n == !0usize || n == 0 { return WEOF; }
10794 let mut i = n;
10795 while i > 0 {
10796 i -= 1;
10797 if ungetc(buf[i] as c_int, f) == -1 { return WEOF; }
10798 }
10799 c
10800}
10801
10802#[no_mangle]
10803pub unsafe extern "C" fn getwchar() -> wint_t { fgetwc(stdin) }
10804
10805#[no_mangle]
10806pub unsafe extern "C" fn putwchar(c: wchar_t) -> wint_t { fputwc(c, stdout) }
10807
10808unsafe fn wfmt_write_str(dst: *mut wchar_t, pos: usize, cap: usize, s: *const u8, len: usize) -> usize {
10813 let mut i = 0;
10814 while i < len {
10815 if pos + i < cap { *dst.add(pos + i) = *s.add(i) as wchar_t; }
10816 i += 1;
10817 }
10818 pos + len
10819}
10820
10821#[no_mangle]
10822pub unsafe extern "C" fn vswprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, mut args: VaList) -> c_int {
10823 if n == 0 { return -1; }
10824 let cap = n - 1;
10825 let mut pos = 0usize;
10826 let mut fmt_narrow = [0u8; 256];
10828 let mut flen = 0usize;
10829 loop {
10830 let ch = *fmt.add(flen) as u32;
10831 if ch == 0 || flen >= 255 { break; }
10832 fmt_narrow[flen] = if ch < 128 { ch as u8 } else { b'?' };
10833 flen += 1;
10834 }
10835 fmt_narrow[flen] = 0;
10836 let mut fi = 0usize;
10837 macro_rules! wc {
10838 ($c:expr) => { if pos < cap { *s.add(pos) = $c as wchar_t; } pos += 1; }
10839 }
10840 loop {
10841 let c = fmt_narrow[fi];
10842 if c == 0 { break; }
10843 if c != b'%' { wc!(c); fi += 1; continue; }
10844 fi += 1;
10845 let mut flags: u8 = 0;
10846 loop {
10847 match fmt_narrow[fi] {
10848 b'-' => { flags |= FLAG_MINUS; fi += 1; }
10849 b'+' => { flags |= FLAG_PLUS; fi += 1; }
10850 b' ' => { flags |= FLAG_SPACE; fi += 1; }
10851 b'0' => { flags |= FLAG_ZERO; fi += 1; }
10852 b'#' => { flags |= FLAG_HASH; fi += 1; }
10853 _ => break,
10854 }
10855 }
10856 let mut width: usize = 0;
10857 if fmt_narrow[fi] == b'*' {
10858 let w = args.next_arg::<c_int>();
10859 if w < 0 { flags |= FLAG_MINUS; width = (-w) as usize; } else { width = w as usize; }
10860 fi += 1;
10861 } else {
10862 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10863 width = width * 10 + (fmt_narrow[fi] - b'0') as usize; fi += 1;
10864 }
10865 }
10866 let mut precision: i32 = -1;
10867 if fmt_narrow[fi] == b'.' {
10868 fi += 1;
10869 if fmt_narrow[fi] == b'*' {
10870 let p = args.next_arg::<c_int>();
10871 precision = if p < 0 { -1 } else { p }; fi += 1;
10872 } else {
10873 precision = 0;
10874 while fmt_narrow[fi] >= b'0' && fmt_narrow[fi] <= b'9' {
10875 precision = precision * 10 + (fmt_narrow[fi] - b'0') as i32; fi += 1;
10876 }
10877 }
10878 }
10879 let len_mod = fmt_narrow[fi];
10880 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' {
10881 fi += 1;
10882 let spec = fmt_narrow[fi];
10883 if (len_mod == b'h' && spec == b'h') || (len_mod == b'l' && spec == b'l') {
10884 fi += 1;
10885 let spec2 = fmt_narrow[fi];
10886 match (len_mod, spec, spec2) {
10887 (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; } }
10888 (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; } }
10889 (b'l', b'l', b'd') | (b'l', b'l', b'i') => {
10890 let val = args.next_arg::<c_longlong>();
10891 let neg = val < 0;
10892 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10893 let b = format_u64(abs);
10894 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10895 let mut fbuf = [0u8; 32];
10896 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10897 for k in 0..len { wc!(fbuf[k]); }
10898 }
10899 (b'l', b'l', b'u') => {
10900 let val = args.next_arg::<c_ulonglong>();
10901 let b = format_u64(val as u64);
10902 let mut fbuf = [0u8; 32];
10903 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10904 for k in 0..len { wc!(fbuf[k]); }
10905 }
10906 (b'l', b'l', b'x') => {
10907 let val = args.next_arg::<c_ulonglong>();
10908 let b = format_hex(val as u64, false);
10909 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10910 let mut fbuf = [0u8; 32];
10911 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10912 for k in 0..len { wc!(fbuf[k]); }
10913 }
10914 (b'l', b'l', b'X') => {
10915 let val = args.next_arg::<c_ulonglong>();
10916 let b = format_hex(val as u64, true);
10917 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10918 let mut fbuf = [0u8; 32];
10919 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10920 for k in 0..len { wc!(fbuf[k]); }
10921 }
10922 (b'l', b'l', b'o') => {
10923 let val = args.next_arg::<c_ulonglong>();
10924 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
10925 let mut fbuf = [0u8; 32];
10926 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10927 for k in 0..len { wc!(fbuf[k]); }
10928 }
10929 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); wc!(spec2); }
10930 }
10931 } else {
10932 let lm = if (len_mod == b'z' || len_mod == b't') && spec != b'n' { b'l' } else { len_mod };
10933 match (lm, spec) {
10934 (b'h', b'n') => { let p = args.next_arg::<*mut c_void>(); if !p.is_null() { *(p as *mut u16) = pos as u16; } }
10935 (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; } }
10936 (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; } }
10937 (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; } }
10938 (b'l', b'd') | (b'l', b'i') => {
10939 let val = args.next_arg::<c_long>();
10940 let neg = val < 0;
10941 let abs = if neg { val.wrapping_neg() as u64 } else { val as u64 };
10942 let b = format_u64(abs);
10943 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
10944 let mut fbuf = [0u8; 32];
10945 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
10946 for k in 0..len { wc!(fbuf[k]); }
10947 }
10948 (b'l', b'u') => {
10949 let val = args.next_arg::<c_ulong>();
10950 let b = format_u64(val as u64);
10951 let mut fbuf = [0u8; 32];
10952 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
10953 for k in 0..len { wc!(fbuf[k]); }
10954 }
10955 (b'l', b'x') => {
10956 let val = args.next_arg::<c_ulong>();
10957 let b = format_hex(val as u64, false);
10958 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
10959 let mut fbuf = [0u8; 32];
10960 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10961 for k in 0..len { wc!(fbuf[k]); }
10962 }
10963 (b'l', b'X') => {
10964 let val = args.next_arg::<c_ulong>();
10965 let b = format_hex(val as u64, true);
10966 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
10967 let mut fbuf = [0u8; 32];
10968 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
10969 for k in 0..len { wc!(fbuf[k]); }
10970 }
10971 (b'l', b'o') => {
10972 let val = args.next_arg::<c_ulong>();
10973 let b = format_octal(val as u64, flags & FLAG_HASH != 0);
10974 let mut fbuf = [0u8; 32];
10975 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
10976 for k in 0..len { wc!(fbuf[k]); }
10977 }
10978 (b'l', b'c') => {
10979 let ch = args.next_arg::<wint_t>();
10980 wc!(ch);
10981 }
10982 (b'l', b's') => {
10983 let ws_arg = args.next_arg::<*const wchar_t>();
10984 if ws_arg.is_null() {
10985 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
10986 if flags & FLAG_MINUS != 0 {
10987 for k in 0..slen { wc!(b"(null)"[k]); }
10988 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10989 } else {
10990 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
10991 for k in 0..slen { wc!(b"(null)"[k]); }
10992 }
10993 } else {
10994 let mut wlen = 0usize;
10995 loop {
10996 let ch = *ws_arg.add(wlen);
10997 if ch == 0 { break; }
10998 if precision >= 0 && wlen >= precision as usize { break; }
10999 wlen += 1;
11000 }
11001 if flags & FLAG_MINUS != 0 {
11002 for k in 0..wlen { wc!(*ws_arg.add(k)); }
11003 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
11004 } else {
11005 for _ in 0..width.saturating_sub(wlen) { wc!(b' '); }
11006 for k in 0..wlen { wc!(*ws_arg.add(k)); }
11007 }
11008 }
11009 }
11010 (b'l', b'f') | (b'l', b'F') | (b'l', b'e') | (b'l', b'E')
11011 | (b'l', b'g') | (b'l', b'G') | (b'l', b'a') | (b'l', b'A') => {
11012 let val = args.next_arg::<f64>();
11013 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
11014 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
11015 let mut fbuf = [0u8; 4224];
11016 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
11017 let mut wbuf = [0u8; 4224];
11018 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
11019 for k in 0..wlen { wc!(wbuf[k]); }
11020 }
11021 (b'L', b'f') | (b'L', b'F') | (b'L', b'e') | (b'L', b'E')
11022 | (b'L', b'g') | (b'L', b'G') | (b'L', b'a') | (b'L', b'A') => {
11023 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
11024 let val = {
11025 let lo: u64 = args.next_arg::<u64>();
11026 let hi: u64 = args.next_arg::<u64>();
11027 let combined: u128 = ((hi as u128) << 64) | (lo as u128);
11028 f128::from_bits(combined) as f64
11029 };
11030 #[cfg(target_arch = "x86_64")]
11031 let val = args.next_arg::<f64>();
11032 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
11033 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
11034 let mut fbuf = [0u8; 4224];
11035 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
11036 let mut wbuf = [0u8; 4224];
11037 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
11038 for k in 0..wlen { wc!(wbuf[k]); }
11039 }
11040 _ => { wc!(b'%'); wc!(len_mod); wc!(spec); }
11041 }
11042 }
11043 } else {
11044 let spec = fmt_narrow[fi];
11045 match spec {
11046 b'd' | b'i' => {
11047 let d = args.next_arg::<c_int>();
11048 let neg = d < 0;
11049 let abs = if neg { d.wrapping_neg() as u64 } else { d as u64 };
11050 let b = format_u64(abs);
11051 let sign = if neg { Some(b'-') } else if flags & FLAG_PLUS != 0 { Some(b'+') } else if flags & FLAG_SPACE != 0 { Some(b' ') } else { None };
11052 let mut fbuf = [0u8; 32];
11053 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, sign, None, precision, width, flags, false);
11054 for k in 0..len { wc!(fbuf[k]); }
11055 }
11056 b'u' => {
11057 let u = args.next_arg::<c_uint>();
11058 let b = format_u64(u as u64);
11059 let mut fbuf = [0u8; 32];
11060 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, false);
11061 for k in 0..len { wc!(fbuf[k]); }
11062 }
11063 b'x' => {
11064 let x = args.next_arg::<c_uint>();
11065 let b = format_hex(x as u64, false);
11066 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'x') } else { None };
11067 let mut fbuf = [0u8; 32];
11068 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
11069 for k in 0..len { wc!(fbuf[k]); }
11070 }
11071 b'X' => {
11072 let x = args.next_arg::<c_uint>();
11073 let b = format_hex(x as u64, true);
11074 let prefix = if flags & FLAG_HASH != 0 && !(b.1 == 1 && b.0[0] == b'0') { Some(b'X') } else { None };
11075 let mut fbuf = [0u8; 32];
11076 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, prefix, precision, width, flags, false);
11077 for k in 0..len { wc!(fbuf[k]); }
11078 }
11079 b'o' => {
11080 let o = args.next_arg::<c_uint>();
11081 let b = format_octal(o as u64, flags & FLAG_HASH != 0);
11082 let mut fbuf = [0u8; 32];
11083 let len = format_int(fbuf.as_mut_ptr(), b.0.as_ptr(), b.1, None, None, precision, width, flags, flags & FLAG_HASH != 0);
11084 for k in 0..len { wc!(fbuf[k]); }
11085 }
11086 b'f' | b'F' | b'e' | b'E' | b'g' | b'G' | b'a' | b'A' => {
11087 let val = args.next_arg::<f64>();
11088 let ucase = spec == b'F' || spec == b'E' || spec == b'G' || spec == b'A';
11089 let ftype = match spec | 0x20 { b'f' => FMT_F, b'e' => FMT_E, b'g' => FMT_G, b'a' => FMT_A, _ => FMT_F };
11090 let mut fbuf = [0u8; 4224];
11091 let flen = format_f64_full(fbuf.as_mut_ptr(), val, ftype, precision, flags, ucase);
11092 let mut wbuf = [0u8; 4224];
11093 let wlen = apply_width_flags(wbuf.as_mut_ptr(), fbuf.as_ptr(), flen, width, flags);
11094 for k in 0..wlen { wc!(wbuf[k]); }
11095 }
11096 b'c' => {
11097 let ch = args.next_arg::<c_int>();
11098 wc!(ch as u8);
11099 }
11100 b's' => {
11101 let p = args.next_arg::<*const c_char>();
11102 if p.is_null() {
11103 let slen = if precision >= 0 { (precision as usize).min(6) } else { 6 };
11104 if flags & FLAG_MINUS != 0 {
11105 for k in 0..slen { wc!(b"(null)"[k]); }
11106 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
11107 } else {
11108 for _ in 0..width.saturating_sub(slen) { wc!(b' '); }
11109 for k in 0..slen { wc!(b"(null)"[k]); }
11110 }
11111 } else {
11112 let mut wbuf_local = [0i32; 256];
11113 let mut wcount = 0usize;
11114 let mut byte_pos = 0usize;
11115 let pbytes = p as *const u8;
11116 loop {
11117 if precision >= 0 && wcount >= precision as usize { break; }
11118 if wcount >= 256 { break; }
11119 let mut wc_val: c_int = 0;
11120 let consumed = mbrtowc(&mut wc_val as *mut c_int, p.add(byte_pos) as *const c_char, 256, core::ptr::null_mut());
11121 if consumed == !0usize || consumed == !1usize {
11122 wbuf_local[wcount] = *pbytes.add(byte_pos) as c_int;
11123 byte_pos += 1;
11124 wcount += 1;
11125 } else if consumed == 0 {
11126 break;
11127 } else {
11128 wbuf_local[wcount] = wc_val;
11129 byte_pos += consumed;
11130 wcount += 1;
11131 }
11132 }
11133 if flags & FLAG_MINUS != 0 {
11134 for k in 0..wcount { wc!(wbuf_local[k]); }
11135 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
11136 } else {
11137 for _ in 0..width.saturating_sub(wcount) { wc!(b' '); }
11138 for k in 0..wcount { wc!(wbuf_local[k]); }
11139 }
11140 }
11141 }
11142 b'p' => {
11143 wc!(b'0'); wc!(b'x');
11144 let p = args.next_arg::<*const c_void>();
11145 let b = format_hex(p as u64, false);
11146 for k in 0..b.1 { wc!(b.0[k]); }
11147 }
11148 b'n' => {
11149 let p = args.next_arg::<*mut c_void>();
11150 if !p.is_null() { *(p as *mut c_int) = pos as c_int; }
11151 }
11152 b'%' => { wc!(b'%'); }
11153 _ => { wc!(b'%'); wc!(spec); }
11154 }
11155 }
11156 fi += 1;
11157 }
11158 let null_pos = if pos < cap { pos } else { cap };
11159 *s.add(null_pos) = 0;
11160 if pos > cap { -1 } else { pos as c_int }
11161}
11162
11163#[no_mangle]
11164pub unsafe extern "C" fn swprintf(s: *mut wchar_t, n: usize, fmt: *const wchar_t, args: ...) -> c_int {
11165 vswprintf(s, n, fmt, args)
11166}
11167
11168#[no_mangle]
11169pub unsafe extern "C" fn vfwprintf(f: *mut FILE, fmt: *const wchar_t, args: VaList) -> c_int {
11170 let mut buf = [0i32; 4096];
11171 let r = vswprintf(buf.as_mut_ptr(), 4096, fmt, args);
11172 if r < 0 { return r; }
11173 let mut i = 0;
11174 while i < r as usize {
11175 let mut mb = [0u8; 4];
11176 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, buf[i], core::ptr::null_mut());
11177 if n == !0usize { return -1; }
11178 if fwrite(mb.as_ptr() as *const c_void, 1, n, f) != n { return -1; }
11179 i += 1;
11180 }
11181 r
11182}
11183
11184#[no_mangle]
11185pub unsafe extern "C" fn fwprintf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
11186 vfwprintf(f, fmt, args)
11187}
11188
11189unsafe fn wcsfmt_to_mbs(dst: *mut u8, dst_len: usize, src: *const wchar_t) {
11195 let mut i = 0usize;
11196 loop {
11197 let ch = *src.add(i) as u32;
11198 if ch == 0 || i >= dst_len - 1 { break; }
11199 *dst.add(i) = if ch < 128 { ch as u8 } else { b'?' };
11200 i += 1;
11201 }
11202 *dst.add(i) = 0;
11203}
11204
11205#[no_mangle]
11206pub unsafe extern "C" fn vswscanf(s: *const wchar_t, fmt: *const wchar_t, mut args: VaList) -> c_int {
11207 let mut mbs_buf = [0u8; 4096];
11208 let mut i = 0usize;
11209 let mut mb_pos = 0usize;
11210 loop {
11211 let wc = *s.add(i) as c_int;
11212 if wc == 0 { break; }
11213 let mut mb = [0u8; 4];
11214 let n = wcrtomb(mb.as_mut_ptr() as *mut c_char, wc, core::ptr::null_mut());
11215 if n == !0usize || n == 0 { break; }
11216 if mb_pos + n >= mbs_buf.len() { break; }
11217 let mut k = 0usize;
11218 while k < n { mbs_buf[mb_pos + k] = mb[k]; k += 1; }
11219 mb_pos += n;
11220 i += 1;
11221 }
11222 mbs_buf[mb_pos] = 0;
11223 let mut mbs_fmt = [0u8; 4096];
11224 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
11225 do_vsscanf(mbs_buf.as_ptr(), mb_pos, mbs_fmt.as_ptr() as *const c_char, &mut args, core::ptr::null_mut())
11226}
11227
11228#[no_mangle]
11229pub unsafe extern "C" fn swscanf(s: *const wchar_t, fmt: *const wchar_t, args: ...) -> c_int {
11230 vswscanf(s, fmt, args)
11231}
11232
11233#[no_mangle]
11234pub unsafe extern "C" fn vfwscanf(f: *mut FILE, fmt: *const wchar_t, mut args: VaList) -> c_int {
11235 let start_pos = ftello(f);
11236 if start_pos < 0 { return -1; }
11237 let mut buf = [0u8; 4096];
11238 let mut n = 0usize;
11239 loop {
11240 if n >= buf.len() - 1 { break; }
11241 let c = fgetc(f);
11242 if c == -1 { break; }
11243 buf[n] = c as u8;
11244 n += 1;
11245 }
11246 buf[n] = 0;
11247 let mut mbs_fmt = [0u8; 4096];
11248 wcsfmt_to_mbs(mbs_fmt.as_mut_ptr(), mbs_fmt.len(), fmt);
11249 let mut consumed = 0usize;
11250 let hit_eof = (*f)._eof != 0;
11251 let result = do_vsscanf(buf.as_ptr(), n, mbs_fmt.as_ptr() as *const c_char, &mut args, &mut consumed);
11252 let _ = fseeko(f, start_pos + consumed as i64, SEEK_SET);
11253 if hit_eof && consumed == n {
11254 (*f)._eof = 1;
11255 }
11256 result
11257}
11258
11259#[no_mangle]
11260pub unsafe extern "C" fn fwscanf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int {
11261 vfwscanf(f, fmt, args)
11262}
11263
11264#[no_mangle]
11265pub unsafe extern "C" fn vwscanf(fmt: *const wchar_t, args: VaList) -> c_int {
11266 vfwscanf(stdin, fmt, args)
11267}
11268
11269#[no_mangle]
11270pub unsafe extern "C" fn wscanf(fmt: *const wchar_t, args: ...) -> c_int {
11271 vfwscanf(stdin, fmt, args)
11272}
11273
11274const LEAPOCH: i64 = 946684800 + 86400 * (31 + 29);
11279const DAYS_PER_400Y: i64 = 365 * 400 + 97;
11280const DAYS_PER_100Y: i64 = 365 * 100 + 24;
11281const DAYS_PER_4Y: i64 = 365 * 4 + 1;
11282
11283const SECS_THROUGH_MONTH: [i32; 12] = [
11284 0, 31*86400, 59*86400, 90*86400, 120*86400, 151*86400,
11285 181*86400, 212*86400, 243*86400, 273*86400, 304*86400, 334*86400,
11286];
11287
11288const DAYS_IN_MONTH: [i32; 12] = [31, 30, 31, 30, 31, 31, 30, 31, 30, 31, 31, 29];
11289
11290unsafe fn year_to_secs(year: i64, is_leap: &mut bool) -> i64 {
11291 if year - 2 <= 136 {
11292 let y = year as i32;
11293 let mut leaps = (y - 68) >> 2;
11294 if (y - 68) & 3 == 0 { leaps -= 1; *is_leap = true; } else { *is_leap = false; }
11295 return 31536000 * (y as i64 - 70) + 86400 * leaps as i64;
11296 }
11297 let mut cycles = ((year - 100) / 400) as i32;
11298 let mut rem = ((year - 100) % 400) as i32;
11299 if rem < 0 { cycles -= 1; rem += 400; }
11300 let (centuries, leaps);
11301 if rem == 0 { *is_leap = true; centuries = 0; leaps = 0; }
11302 else {
11303 let c;
11304 if rem >= 200 { if rem >= 300 { c = 3; rem -= 300; } else { c = 2; rem -= 200; } }
11305 else { if rem >= 100 { c = 1; rem -= 100; } else { c = 0; } }
11306 centuries = c;
11307 if rem == 0 { *is_leap = false; leaps = 0; }
11308 else { leaps = rem / 4; rem %= 4; *is_leap = rem == 0; }
11309 }
11310 let total_leaps = leaps + 97 * cycles + 24 * centuries - (*is_leap as i32);
11311 (year - 100) * 31536000 + total_leaps as i64 * 86400 + 946684800 + 86400
11312}
11313
11314fn month_to_secs(month: i32, is_leap: bool) -> i32 {
11315 let mut t = SECS_THROUGH_MONTH[month as usize];
11316 if is_leap && month >= 2 { t += 86400; }
11317 t
11318}
11319
11320unsafe fn secs_to_tm(t: i64, tm: &mut tm) -> bool {
11321 if t < (i32::MIN as i64) * 31622400 || t > (i32::MAX as i64) * 31622400 { return false; }
11322 let secs = t - LEAPOCH;
11323 let mut days = secs / 86400;
11324 let mut remsecs = (secs % 86400) as i32;
11325 if remsecs < 0 { remsecs += 86400; days -= 1; }
11326 let mut wday = ((3 + days) % 7) as i32;
11327 if wday < 0 { wday += 7; }
11328 let mut qc_cycles = (days / DAYS_PER_400Y) as i32;
11329 let mut remdays = (days % DAYS_PER_400Y) as i32;
11330 if remdays < 0 { remdays += DAYS_PER_400Y as i32; qc_cycles -= 1; }
11331 let mut c_cycles = remdays / DAYS_PER_100Y as i32;
11332 if c_cycles == 4 { c_cycles -= 1; }
11333 remdays -= c_cycles * DAYS_PER_100Y as i32;
11334 let mut q_cycles = remdays / DAYS_PER_4Y as i32;
11335 if q_cycles == 25 { q_cycles -= 1; }
11336 remdays -= q_cycles * DAYS_PER_4Y as i32;
11337 let mut remyears = remdays / 365;
11338 if remyears == 4 { remyears -= 1; }
11339 remdays -= remyears * 365;
11340 let leap = remyears == 0 && (q_cycles != 0 || c_cycles == 0);
11341 let mut yday = remdays + 31 + 28 + leap as i32;
11342 if yday >= 365 + leap as i32 { yday -= 365 + leap as i32; }
11343 let years = remyears as i64 + 4 * q_cycles as i64 + 100 * c_cycles as i64 + 400 * qc_cycles as i64;
11344 let mut months = 0i32;
11345 let mut rd = remdays;
11346 for m in 0..12 {
11347 if DAYS_IN_MONTH[m] <= rd { rd -= DAYS_IN_MONTH[m]; } else { months = m as i32; break; }
11348 }
11349 let mut adj_years = years;
11350 if months >= 10 { months -= 12; adj_years += 1; }
11351 if adj_years + 100 > i32::MAX as i64 || adj_years + 100 < i32::MIN as i64 { return false; }
11352 tm.tm_year = (adj_years + 100) as c_int;
11353 tm.tm_mon = months + 2;
11354 tm.tm_mday = rd + 1;
11355 tm.tm_wday = wday;
11356 tm.tm_yday = yday;
11357 tm.tm_hour = remsecs / 3600;
11358 tm.tm_min = remsecs / 60 % 60;
11359 tm.tm_sec = remsecs % 60;
11360 true
11361}
11362
11363unsafe fn tm_to_secs(tm: *const tm) -> i64 {
11364 let mut year = (*tm).tm_year as i64;
11365 let mut month = (*tm).tm_mon;
11366 if month >= 12 || month < 0 {
11367 let adj = month / 12;
11368 month %= 12;
11369 if month < 0 { month += 12; }
11370 year += adj as i64;
11371 }
11372 let mut is_leap = false;
11373 let mut t = year_to_secs(year, &mut is_leap);
11374 t += month_to_secs(month, is_leap) as i64;
11375 t += 86400 * ((*tm).tm_mday - 1) as i64;
11376 t += 3600 * (*tm).tm_hour as i64;
11377 t += 60 * (*tm).tm_min as i64;
11378 t += (*tm).tm_sec as i64;
11379 t
11380}
11381
11382static mut TM_BUF: tm = tm {
11383 tm_sec: 0, tm_min: 0, tm_hour: 0, tm_mday: 0, tm_mon: 0,
11384 tm_year: 0, tm_wday: 0, tm_yday: 0, tm_isdst: 0,
11385 tm_gmtoff: 0, tm_zone: core::ptr::null(),
11386};
11387
11388static mut UTC_STR: [c_char; 4] = [b'U' as c_char, b'T' as c_char, b'C' as c_char, 0];
11389
11390const CLOCK_PROCESS_CPUTIME_ID: c_int = 2;
11391
11392#[no_mangle]
11397pub unsafe extern "C" fn time(t: *mut TimeT) -> TimeT {
11398 let mut ts: timespec = core::mem::zeroed();
11399 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
11400 if !t.is_null() { *t = ts.tv_sec; }
11401 ts.tv_sec
11402}
11403
11404#[no_mangle]
11405pub unsafe extern "C" fn difftime(t1: TimeT, t0: TimeT) -> f64 {
11406 (t1 as i64 - t0 as i64) as f64
11407}
11408
11409#[no_mangle]
11410pub unsafe extern "C" fn clock() -> ClockT {
11411 let mut ts: timespec = core::mem::zeroed();
11412 let _ = sys_clock_gettime(CLOCK_PROCESS_CPUTIME_ID, &mut ts);
11413 ts.tv_sec * 1000000 + ts.tv_nsec / 1000
11414}
11415
11416#[no_mangle]
11417pub unsafe extern "C" fn gmtime(t: *const TimeT) -> *mut tm {
11418 gmtime_r(t, &raw mut TM_BUF)
11419}
11420
11421#[no_mangle]
11422pub unsafe extern "C" fn gmtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm {
11423 if !secs_to_tm(*t as i64, &mut *tm) { ERRNO!() = EOVERFLOW; return core::ptr::null_mut(); }
11424 (*tm).tm_isdst = 0;
11425 (*tm).tm_gmtoff = 0;
11426 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11427 tm
11428}
11429
11430#[no_mangle]
11431pub unsafe extern "C" fn localtime(t: *const TimeT) -> *mut tm { gmtime(t) }
11432
11433#[no_mangle]
11434pub unsafe extern "C" fn localtime_r(t: *const TimeT, tm: *mut tm) -> *mut tm { gmtime_r(t, tm) }
11435
11436#[no_mangle]
11437pub unsafe extern "C" fn mktime(tm: *mut tm) -> TimeT {
11438 let t = tm_to_secs(tm as *const tm);
11439 if !secs_to_tm(t, &mut *tm) { ERRNO!() = EOVERFLOW; return -1; }
11440 (*tm).tm_isdst = 0;
11441 (*tm).tm_gmtoff = 0;
11442 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11443 t as TimeT
11444}
11445
11446#[no_mangle]
11447pub unsafe extern "C" fn timegm(tm: *mut tm) -> TimeT {
11448 let t = tm_to_secs(tm as *const tm);
11449 if !secs_to_tm(t, &mut *tm) { ERRNO!() = EOVERFLOW; return -1; }
11450 (*tm).tm_isdst = 0;
11451 (*tm).tm_gmtoff = 0;
11452 (*tm).tm_zone = core::ptr::addr_of!(UTC_STR).cast::<c_char>();
11453 t as TimeT
11454}
11455
11456static mut ASCTIME_BUF: [c_char; 26] = [0; 26];
11457
11458const 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"];
11459const 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"];
11460
11461#[no_mangle]
11462pub unsafe extern "C" fn asctime(tm: *const tm) -> *mut c_char {
11463 asctime_r(tm, core::ptr::addr_of_mut!(ASCTIME_BUF).cast::<c_char>())
11464}
11465
11466#[no_mangle]
11467pub unsafe extern "C" fn asctime_r(tm: *const tm, buf: *mut c_char) -> *mut c_char {
11468 let wday = if (*tm).tm_wday >= 0 && (*tm).tm_wday < 7 { (*tm).tm_wday as usize } else { 0 };
11469 let mon = if (*tm).tm_mon >= 0 && (*tm).tm_mon < 12 { (*tm).tm_mon as usize } else { 0 };
11470 let dn = DAY_NAMES[wday];
11471 let mn = MON_NAMES[mon];
11472 let mut p = 0;
11473 for k in 0..3 { *buf.add(p) = *dn.as_ptr().add(k) as c_char; p += 1; }
11474 *buf.add(p) = b' ' as c_char; p += 1;
11475 for k in 0..3 { *buf.add(p) = *mn.as_ptr().add(k) as c_char; p += 1; }
11476 *buf.add(p) = b' ' as c_char; p += 1;
11477 let v = (*tm).tm_mday;
11478 *buf.add(p) = (b'0' + (v / 10) as u8) as c_char; p += 1;
11479 *buf.add(p) = (b'0' + (v % 10) as u8) as c_char; p += 1;
11480 *buf.add(p) = b' ' as c_char; p += 1;
11481 let hh = (*tm).tm_hour;
11482 *buf.add(p) = (b'0' + (hh / 10) as u8) as c_char; p += 1;
11483 *buf.add(p) = (b'0' + (hh % 10) as u8) as c_char; p += 1;
11484 *buf.add(p) = b':' as c_char; p += 1;
11485 let mm = (*tm).tm_min;
11486 *buf.add(p) = (b'0' + (mm / 10) as u8) as c_char; p += 1;
11487 *buf.add(p) = (b'0' + (mm % 10) as u8) as c_char; p += 1;
11488 *buf.add(p) = b':' as c_char; p += 1;
11489 let ss = (*tm).tm_sec;
11490 *buf.add(p) = (b'0' + (ss / 10) as u8) as c_char; p += 1;
11491 *buf.add(p) = (b'0' + (ss % 10) as u8) as c_char; p += 1;
11492 *buf.add(p) = b' ' as c_char; p += 1;
11493 let yr = (*tm).tm_year + 1900;
11494 let mut tmp = [0u8; 4];
11495 let mut v2 = yr;
11496 for k in (0..4).rev() { tmp[k] = b'0' + (v2 % 10) as u8; v2 /= 10; }
11497 for k in 0..4 { *buf.add(p) = tmp[k] as c_char; p += 1; }
11498 *buf.add(p) = b'\n' as c_char; p += 1;
11499 *buf.add(p) = 0;
11500 buf
11501}
11502
11503#[no_mangle]
11504pub unsafe extern "C" fn ctime(t: *const TimeT) -> *mut c_char { asctime(gmtime(t)) }
11505
11506#[no_mangle]
11507pub unsafe extern "C" fn ctime_r(t: *const TimeT, buf: *mut c_char) -> *mut c_char {
11508 let mut tmp: tm = core::mem::zeroed();
11509 gmtime_r(t, &mut tmp);
11510 asctime_r(&tmp, buf)
11511}
11512
11513unsafe fn sys_clock_getres(clockid: c_int, ts: *mut timespec) -> i64 {
11518 <Arch as Syscalls>::syscall2(SYS_CLOCK_GETRES, clockid as i64, ts as i64)
11519}
11520
11521unsafe fn sys_clock_settime(clockid: c_int, ts: *const timespec) -> i64 {
11522 <Arch as Syscalls>::syscall2(SYS_CLOCK_SETTIME, clockid as i64, ts as i64)
11523}
11524
11525unsafe fn sys_clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> i64 {
11526 <Arch as Syscalls>::syscall4(SYS_CLOCK_NANOSLEEP, clockid as i64, flags as i64, req as i64, rem as i64)
11527}
11528
11529#[no_mangle]
11530pub unsafe extern "C" fn clock_getres(clockid: c_int, ts: *mut timespec) -> c_int {
11531 let r = sys_clock_getres(clockid, ts);
11532 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
11533}
11534
11535#[no_mangle]
11536pub unsafe extern "C" fn clock_settime(clockid: c_int, ts: *const timespec) -> c_int {
11537 let r = sys_clock_settime(clockid, ts);
11538 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
11539}
11540
11541#[no_mangle]
11542pub unsafe extern "C" fn clock_nanosleep(clockid: c_int, flags: c_int, req: *const timespec, rem: *mut timespec) -> c_int {
11543 let r = sys_clock_nanosleep(clockid, flags, req, rem);
11544 if r < 0 {
11545 let e = (-r) as c_int;
11546 if clockid == 3 && e == 95 { return 22; }
11549 e
11550 } else {
11551 0
11552 }
11553}
11554
11555#[no_mangle]
11556pub unsafe extern "C" fn gettimeofday(tv: *mut timeval, _tz: *mut c_void) -> c_int {
11557 if tv.is_null() { return 0; }
11558 let mut ts: timespec = core::mem::zeroed();
11559 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
11560 (*tv).tv_sec = ts.tv_sec;
11561 (*tv).tv_usec = ts.tv_nsec / 1000;
11562 0
11563}
11564
11565fn is_leap_year(y: i32) -> bool {
11570 let yr = if y > i32::MAX - 1900 { y - 2000 } else { y + 1900 };
11571 yr % 4 == 0 && (yr % 100 != 0 || yr % 400 == 0)
11572}
11573
11574fn week_num(tm: &tm) -> i32 {
11575 let mut val = (tm.tm_yday + 7 - ((tm.tm_wday + 6) % 7)) / 7;
11576 if (tm.tm_wday + 371 - tm.tm_yday - 2).rem_euclid(7) <= 2 { val += 1; }
11577 if val == 0 {
11578 val = 52;
11579 let dec31 = (tm.tm_wday + 7 - tm.tm_yday - 1).rem_euclid(7);
11580 if dec31 == 4 || (dec31 == 5 && is_leap_year(tm.tm_year % 400 - 1)) { val += 1; }
11581 } else if val == 53 {
11582 let jan1 = (tm.tm_wday + 371 - tm.tm_yday).rem_euclid(7);
11583 if jan1 != 4 && (jan1 != 3 || !is_leap_year(tm.tm_year)) { val = 1; }
11584 }
11585 val
11586}
11587
11588const ABDAY_1: c_int = 0x20000;
11590const DAY_1: c_int = 0x20007;
11591const ABMON_1: c_int = 0x2000E;
11592const MON_1: c_int = 0x2001A;
11593const AM_STR_LI: c_int = 0x20026;
11594const PM_STR_LI: c_int = 0x20027;
11595const D_T_FMT: c_int = 0x20028;
11596const D_FMT: c_int = 0x20029;
11597const T_FMT: c_int = 0x2002A;
11598const T_FMT_AMPM: c_int = 0x2002B;
11599
11600unsafe fn num_fmt(buf: &mut [u8; 100], val: i64, pad: u8, width: usize) -> (*const u8, usize) {
11603 let negative = val < 0;
11604 let mut v = if negative { -val as u64 } else { val as u64 };
11605 let mut tmp = [0u8; 24];
11606 let mut pos = 24usize;
11607 if v == 0 { pos -= 1; tmp[pos] = b'0'; }
11608 while v > 0 { pos -= 1; tmp[pos] = b'0' + (v % 10) as u8; v /= 10; }
11609 let digits = 24 - pos;
11610 let sign_chars = if negative { 1 } else { 0 };
11611 let needed = sign_chars + digits;
11612 let fill = if width > needed { width - needed } else { 0 };
11613 let total = fill + needed;
11614 let mut p = 0usize;
11615 match pad {
11616 b'-' => { }
11617 b'_' => {
11618 for _ in 0..fill { buf[p] = b' '; p += 1; }
11619 if negative { buf[p] = b'-'; p += 1; }
11620 }
11621 _ => {
11622 if negative { buf[p] = b'-'; p += 1; }
11623 for _ in 0..fill { buf[p] = b'0'; p += 1; }
11624 }
11625 }
11626 for i in 0..digits { buf[p] = tmp[pos + i]; p += 1; }
11627 (buf.as_ptr(), total)
11628}
11629
11630unsafe fn str_to_buf(buf: &mut [u8; 100], s: *const c_char) -> (*const u8, usize) {
11632 let mut k = 0usize;
11633 while *s.add(k) != 0 {
11634 buf[k] = *s.add(k) as u8;
11635 k += 1;
11636 }
11637 (buf.as_ptr(), k)
11638}
11639
11640unsafe fn __strftime_fmt_1(buf: &mut [u8; 100], f: u8, tm: *const tm, pad: u8) -> (*const u8, usize) {
11643 let mut val: i64;
11644 let mut width: usize = 2;
11645 let mut def_pad: u8 = b'0';
11646 let fmt: *const c_char;
11647
11648 match f {
11649 b'a' => {
11650 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
11651 let p = nl_langinfo(ABDAY_1 + (*tm).tm_wday);
11652 return str_to_buf(buf, p);
11653 }
11654 b'A' => {
11655 if (*tm).tm_wday as u32 > 6 { return (b"\0".as_ptr(), 0); }
11656 let p = nl_langinfo(DAY_1 + (*tm).tm_wday);
11657 return str_to_buf(buf, p);
11658 }
11659 b'h' | b'b' => {
11660 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
11661 let p = nl_langinfo(ABMON_1 + (*tm).tm_mon);
11662 return str_to_buf(buf, p);
11663 }
11664 b'B' => {
11665 if (*tm).tm_mon as u32 > 11 { return (b"\0".as_ptr(), 0); }
11666 let p = nl_langinfo(MON_1 + (*tm).tm_mon);
11667 return str_to_buf(buf, p);
11668 }
11669 b'c' => {
11670 let p = nl_langinfo(D_T_FMT);
11671 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11672 return (buf.as_ptr(), l);
11673 }
11674 b'C' => {
11675 val = (1900i64 + (*tm).tm_year as i64) / 100;
11676 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11677 }
11678 b'e' => { def_pad = b'_'; }
11679 b'd' => {
11680 val = (*tm).tm_mday as i64;
11681 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11682 }
11683 b'D' => {
11684 fmt = b"%m/%d/%y\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'F' => {
11689 fmt = b"%Y-%m-%d\0".as_ptr() as *const c_char;
11690 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11691 return (buf.as_ptr(), l);
11692 }
11693 b'g' | b'G' => {
11694 val = (*tm).tm_year as i64 + 1900;
11695 if (*tm).tm_yday < 3 && week_num(&*tm) != 1 { val -= 1; }
11696 else if (*tm).tm_yday > 360 && week_num(&*tm) == 1 { val += 1; }
11697 if f == b'g' { val %= 100; }
11698 else { width = 4; }
11699 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11700 }
11701 b'H' => {
11702 val = (*tm).tm_hour as i64;
11703 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11704 }
11705 b'I' => {
11706 val = (*tm).tm_hour as i64;
11707 if val == 0 { val = 12; }
11708 else if val > 12 { val -= 12; }
11709 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11710 }
11711 b'j' => {
11712 val = (*tm).tm_yday as i64 + 1;
11713 width = 3;
11714 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11715 }
11716 b'm' => {
11717 val = (*tm).tm_mon as i64 + 1;
11718 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11719 }
11720 b'M' => {
11721 val = (*tm).tm_min as i64;
11722 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11723 }
11724 b'n' => { buf[0] = b'\n'; return (buf.as_ptr(), 1); }
11725 b'p' => {
11726 let p = if (*tm).tm_hour >= 12 { nl_langinfo(PM_STR_LI) } else { nl_langinfo(AM_STR_LI) };
11727 return str_to_buf(buf, p);
11728 }
11729 b'r' => {
11730 let p = nl_langinfo(T_FMT_AMPM);
11731 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11732 return (buf.as_ptr(), l);
11733 }
11734 b'R' => {
11735 fmt = b"%H:%M\0".as_ptr() as *const c_char;
11736 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11737 return (buf.as_ptr(), l);
11738 }
11739 b's' => {
11740 val = tm_to_secs(tm) - (*tm).tm_gmtoff as i64;
11741 width = 1;
11742 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11743 }
11744 b'S' => {
11745 val = (*tm).tm_sec as i64;
11746 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11747 }
11748 b't' => { buf[0] = b'\t'; return (buf.as_ptr(), 1); }
11749 b'T' => {
11750 fmt = b"%H:%M:%S\0".as_ptr() as *const c_char;
11751 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, fmt, tm);
11752 return (buf.as_ptr(), l);
11753 }
11754 b'u' => {
11755 val = if (*tm).tm_wday != 0 { (*tm).tm_wday as i64 } else { 7 };
11756 width = 1;
11757 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11758 }
11759 b'U' => {
11760 val = ((*tm).tm_yday as u64 + 7 - (*tm).tm_wday as u64) as i64 / 7;
11761 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11762 }
11763 b'W' => {
11764 val = ((*tm).tm_yday as u64 + 7 - ((*tm).tm_wday as u64 + 6) % 7) as i64 / 7;
11765 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11766 }
11767 b'V' => {
11768 val = week_num(&*tm) as i64;
11769 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11770 }
11771 b'w' => {
11772 val = (*tm).tm_wday as i64;
11773 width = 1;
11774 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11775 }
11776 b'x' => {
11777 let p = nl_langinfo(D_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'X' => {
11782 let p = nl_langinfo(T_FMT);
11783 let l = __strftime_l(buf.as_mut_ptr() as *mut c_char, 100, p, tm);
11784 return (buf.as_ptr(), l);
11785 }
11786 b'y' => {
11787 val = (1900i64 + (*tm).tm_year as i64) % 100;
11788 if val < 0 { val = -val; }
11789 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11790 }
11791 b'Y' => {
11792 val = (*tm).tm_year as i64 + 1900;
11793 if val >= 10000 {
11794 let mut tmp = [0u8; 100];
11795 let (_, k) = num_fmt(&mut tmp, val, b'-', 1);
11796 buf[0] = b'+';
11797 for i in 0..k { buf[1 + i] = tmp[i]; }
11798 return (buf.as_ptr(), 1 + k);
11799 }
11800 width = 4;
11801 return num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width);
11802 }
11803 b'z' => {
11804 if (*tm).tm_isdst < 0 { return (b"\0".as_ptr(), 0); }
11805 let gmtoff = (*tm).tm_gmtoff as i64;
11806 let sign = if gmtoff >= 0 { b'+' } else { b'-' };
11807 let off = if gmtoff < 0 { -gmtoff } else { gmtoff };
11808 let hh = (off / 3600) as i32;
11809 let mm = ((off % 3600) / 60) as i32;
11810 buf[0] = sign;
11811 buf[1] = b'0' + (hh / 10) as u8;
11812 buf[2] = b'0' + (hh % 10) as u8;
11813 buf[3] = b'0' + (mm / 10) as u8;
11814 buf[4] = b'0' + (mm % 10) as u8;
11815 return (buf.as_ptr(), 5);
11816 }
11817 b'Z' => {
11818 if (*tm).tm_isdst < 0 || (*tm).tm_zone.is_null() { return (b"\0".as_ptr(), 0); }
11819 return str_to_buf(buf, (*tm).tm_zone);
11820 }
11821 b'%' => { buf[0] = b'%'; return (buf.as_ptr(), 1); }
11822 _ => { return (core::ptr::null(), 0); }
11823 }
11824 val = (*tm).tm_mday as i64;
11826 num_fmt(buf, val, if pad != 0 { pad } else { def_pad }, width)
11827}
11828
11829unsafe fn __strftime_l(s: *mut c_char, n: usize, f: *const c_char, tm: *const tm) -> usize {
11830 let mut l: usize = 0;
11831 let mut fi: usize = 0;
11832 while l < n {
11833 let ch = *f.add(fi) as u8;
11834 if ch == 0 {
11835 *s.add(l) = 0;
11836 return l;
11837 }
11838 if ch != b'%' {
11839 *s.add(l) = ch as c_char;
11840 l += 1;
11841 fi += 1;
11842 continue;
11843 }
11844 fi += 1;
11845 let mut pad: u8 = 0;
11847 let fc = *f.add(fi) as u8;
11848 if fc == b'-' || fc == b'_' || fc == b'0' { pad = fc; fi += 1; }
11849 let plus = *f.add(fi) as u8 == b'+';
11850 if plus { fi += 1; }
11851 let mut width: usize = 0;
11853 let mut p_idx = fi;
11854 {
11855 let fc2 = *f.add(fi) as u8;
11856 if fc2 >= b'0' && fc2 <= b'9' {
11857 let mut w: usize = 0;
11858 while { let c = *f.add(p_idx) as u8; c >= b'0' && c <= b'9' } {
11859 w = w * 10 + (*f.add(p_idx) as usize - b'0' as usize);
11860 p_idx += 1;
11861 }
11862 width = w;
11863 }
11864 }
11865 let spec_ch = *f.add(p_idx) as u8;
11866 if spec_ch == b'C' || spec_ch == b'F' || spec_ch == b'G' || spec_ch == b'Y' {
11867 if width == 0 && p_idx != fi { width = 1; }
11868 } else {
11869 width = 0;
11870 }
11871 fi = p_idx;
11872 let fc3 = *f.add(fi) as u8;
11874 if fc3 == b'E' || fc3 == b'O' { fi += 1; }
11875 let fch = *f.add(fi) as u8;
11876 let mut buf = [0u8; 100];
11878 let (t, k) = __strftime_fmt_1(&mut buf, fch, tm, pad);
11879 if t.is_null() { break; }
11880 let mut k = k;
11881 let mut t = t;
11882 if width != 0 {
11883 if *t == b'+' || *t == b'-' { t = t.add(1); k -= 1; }
11885 while k > 0 && *t == b'0' && k > 1 && *t.add(1) >= b'0' && *t.add(1) <= b'9' {
11886 t = t.add(1); k -= 1;
11887 }
11888 if width < k { width = k; }
11889 let mut d: usize = 0;
11890 while d < k && *t.add(d) >= b'0' && *t.add(d) <= b'9' { d += 1; }
11891 if (*tm).tm_year < -1900 {
11892 if l < n { *s.add(l) = b'-' as c_char; }
11893 l += 1;
11894 width -= 1;
11895 } else if plus && d + (width - k) >= (if spec_ch == b'C' { 3 } else { 5 }) {
11896 if l < n { *s.add(l) = b'+' as c_char; }
11897 l += 1;
11898 width -= 1;
11899 }
11900 while width > k && l < n {
11901 *s.add(l) = b'0' as c_char;
11902 l += 1;
11903 width -= 1;
11904 }
11905 }
11906 let copy = if k > n - l { n - l } else { k };
11907 core::ptr::copy_nonoverlapping(t, s.add(l) as *mut u8, copy);
11908 l += copy;
11909 fi += 1;
11910 }
11911 if n > 0 {
11912 if l == n { l = n - 1; }
11913 *s.add(l) = 0;
11914 }
11915 0
11916}
11917
11918#[no_mangle]
11919pub unsafe extern "C" fn strftime(s: *mut c_char, maxsize: usize, fmt: *const c_char, tm: *const tm) -> usize {
11920 __strftime_l(s, maxsize, fmt, tm)
11921}
11922
11923unsafe fn match_prefix(s: *const u8, prefix: &[u8]) -> bool {
11928 for i in 0..prefix.len() {
11929 if *s.add(i) == 0 || *s.add(i) != prefix[i] { return false; }
11930 }
11931 true
11932}
11933
11934unsafe fn match_ci_prefix(s: *const u8, prefix: &[u8]) -> bool {
11935 for i in 0..prefix.len() {
11936 let c = *s.add(i);
11937 if c == 0 { return false; }
11938 if c.to_ascii_lowercase() != prefix[i].to_ascii_lowercase() { return false; }
11939 }
11940 true
11941}
11942
11943unsafe fn parse_int(p: *const u8, max_digits: usize) -> (i32, *const u8) {
11944 let mut val = 0i32;
11945 let mut np = p;
11946 let mut count = 0;
11947 while *np >= b'0' && *np <= b'9' && count < max_digits {
11948 val = val * 10 + (*np - b'0') as i32;
11949 np = np.add(1);
11950 count += 1;
11951 }
11952 if count == 0 { (0, p) } else { (val, np) }
11953}
11954
11955unsafe fn parse_range(p: *const u8, min: i32, max: i32) -> (i32, *const u8) {
11956 let (val, np) = parse_int(p, 4);
11957 if np == p || val < min || val > max { (0, p) } else { (val, np) }
11958}
11959
11960fn is_ascii_space(c: u8) -> bool {
11961 c == b' ' || c == b'\t' || c == b'\n' || c == b'\r' || c == 0x0c || c == 0x0b
11962}
11963
11964#[no_mangle]
11965pub unsafe extern "C" fn strptime(s: *const c_char, fmt: *const c_char, tm: *mut tm) -> *mut c_char {
11966 let mut p = s as *const u8;
11967 let mut f = fmt as *const u8;
11968 let mut want_century = 0i32;
11969 let mut century = 0i32;
11970 let mut relyear = 0i32;
11971 while *f != 0 {
11972 if *f != b'%' {
11973 if is_ascii_space(*f) {
11974 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
11975 } else {
11976 if *p != *f { return core::ptr::null_mut(); }
11977 p = p.add(1);
11978 }
11979 f = f.add(1);
11980 continue;
11981 }
11982 f = f.add(1);
11983 if *f == b'+' { f = f.add(1); }
11984 while *f >= b'0' && *f <= b'9' { f = f.add(1); }
11985 if *f == b'E' || *f == b'O' { f = f.add(1); }
11986 match *f {
11987 b'a' | b'A' => {
11988 let mut found = false;
11989 for i in 0..7 {
11990 let names: [&[u8]; 7] = [b"Sunday", b"Monday", b"Tuesday", b"Wednesday", b"Thursday", b"Friday", b"Saturday"];
11991 let snames: [&[u8]; 7] = [b"Sun", b"Mon", b"Tue", b"Wed", b"Thu", b"Fri", b"Sat"];
11992 if match_prefix(p, names[i]) { (*tm).tm_wday = i as c_int; p = p.add(names[i].len()); found = true; break; }
11993 if match_prefix(p, snames[i]) { (*tm).tm_wday = i as c_int; p = p.add(snames[i].len()); found = true; break; }
11994 }
11995 if !found { return core::ptr::null_mut(); }
11996 }
11997 b'b' | b'B' | b'h' => {
11998 let mut found = false;
11999 for i in 0..12 {
12000 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"];
12001 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"];
12002 if match_prefix(p, names[i]) { (*tm).tm_mon = i as c_int; p = p.add(names[i].len()); found = true; break; }
12003 if match_prefix(p, snames[i]) { (*tm).tm_mon = i as c_int; p = p.add(snames[i].len()); found = true; break; }
12004 }
12005 if !found { return core::ptr::null_mut(); }
12006 }
12007 b'C' => {
12008 let (v, np) = parse_int(p, 2);
12009 if np == p { return core::ptr::null_mut(); }
12010 century = v;
12011 want_century |= 2;
12012 p = np;
12013 }
12014 b'd' | b'e' => {
12015 let (v, np) = parse_range(p, 1, 31);
12016 if np == p { return core::ptr::null_mut(); }
12017 (*tm).tm_mday = v;
12018 p = np;
12019 }
12020 b'D' => {
12021 let r = strptime(p as *const c_char, b"%m/%d/%y\0".as_ptr() as *const c_char, tm);
12022 if r.is_null() { return core::ptr::null_mut(); }
12023 p = r as *const u8;
12024 }
12025 b'F' => {
12026 let (yv, ynp) = parse_int(p, 4);
12027 if ynp == p { return core::ptr::null_mut(); }
12028 (*tm).tm_year = yv - 1900;
12029 p = ynp;
12030 if *p != b'-' { return core::ptr::null_mut(); }
12031 p = p.add(1);
12032 let (mv, mnp) = parse_range(p, 1, 12);
12033 if mnp == p { return core::ptr::null_mut(); }
12034 (*tm).tm_mon = mv - 1;
12035 p = mnp;
12036 if *p != b'-' { return core::ptr::null_mut(); }
12037 p = p.add(1);
12038 let (dv, dnp) = parse_range(p, 1, 31);
12039 if dnp == p { return core::ptr::null_mut(); }
12040 (*tm).tm_mday = dv;
12041 p = dnp;
12042 }
12043 b'H' | b'I' => {
12044 let (v, np) = parse_range(p, 0, 23);
12045 if np == p { return core::ptr::null_mut(); }
12046 (*tm).tm_hour = v;
12047 p = np;
12048 }
12049 b'j' => {
12050 let (v, np) = parse_range(p, 1, 366);
12051 if np == p { return core::ptr::null_mut(); }
12052 (*tm).tm_yday = v - 1;
12053 p = np;
12054 }
12055 b'm' => {
12056 let (v, np) = parse_range(p, 1, 12);
12057 if np == p { return core::ptr::null_mut(); }
12058 (*tm).tm_mon = v - 1;
12059 p = np;
12060 }
12061 b'M' => {
12062 let (v, np) = parse_range(p, 0, 59);
12063 if np == p { return core::ptr::null_mut(); }
12064 (*tm).tm_min = v;
12065 p = np;
12066 }
12067 b'n' | b't' => {
12068 while *p != 0 && is_ascii_space(*p) { p = p.add(1); }
12069 }
12070 b'p' => {
12071 if match_ci_prefix(p, b"AM") {
12072 if (*tm).tm_hour == 12 { (*tm).tm_hour = 0; }
12073 p = p.add(2);
12074 } else if match_ci_prefix(p, b"PM") {
12075 if (*tm).tm_hour < 12 { (*tm).tm_hour += 12; }
12076 p = p.add(2);
12077 } else { return core::ptr::null_mut(); }
12078 }
12079 b'r' => {
12080 let r = strptime(p as *const c_char, b"%I:%M:%S %p\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'R' => {
12085 let r = strptime(p as *const c_char, b"%H:%M\0".as_ptr() as *const c_char, tm);
12086 if r.is_null() { return core::ptr::null_mut(); }
12087 p = r as *const u8;
12088 }
12089 b's' => {
12090 let neg = if *p == b'-' { p = p.add(1); true } else { false };
12091 if *p < b'0' || *p > b'9' { return core::ptr::null_mut(); }
12092 let mut val = 0i64;
12093 while *p >= b'0' && *p <= b'9' {
12094 val = val * 10 + (*p - b'0') as i64;
12095 p = p.add(1);
12096 }
12097 if neg { val = -val; }
12098 secs_to_tm(val, &mut *tm);
12099 }
12100 b'S' => {
12101 let (v, np) = parse_range(p, 0, 60);
12102 if np == p { return core::ptr::null_mut(); }
12103 (*tm).tm_sec = v;
12104 p = np;
12105 }
12106 b'T' => {
12107 let r = strptime(p as *const c_char, b"%H:%M:%S\0".as_ptr() as *const c_char, tm);
12108 if r.is_null() { return core::ptr::null_mut(); }
12109 p = r as *const u8;
12110 }
12111 b'U' | b'W' => {
12112 let (_, np) = parse_range(p, 0, 53);
12113 if np == p { return core::ptr::null_mut(); }
12114 p = np;
12115 }
12116 b'V' => {
12117 let (_, np) = parse_range(p, 1, 53);
12118 if np == p { return core::ptr::null_mut(); }
12119 p = np;
12120 }
12121 b'w' => {
12122 let (v, np) = parse_range(p, 0, 6);
12123 if np == p { return core::ptr::null_mut(); }
12124 (*tm).tm_wday = v;
12125 p = np;
12126 }
12127 b'y' => {
12128 let (v, np) = parse_int(p, 2);
12129 if np == p { return core::ptr::null_mut(); }
12130 relyear = v;
12131 want_century |= 1;
12132 p = np;
12133 }
12134 b'Y' => {
12135 let neg = if *p == b'-' { p = p.add(1); true } else { false };
12136 let (v, np) = parse_int(p, 4);
12137 if np == p { return core::ptr::null_mut(); }
12138 (*tm).tm_year = if neg { -(v + 1900) } else { v - 1900 };
12139 want_century = 0;
12140 p = np;
12141 }
12142 b'z' => {
12143 if *p != b'+' && *p != b'-' { return core::ptr::null_mut(); }
12144 let neg = *p == b'-';
12145 p = p.add(1);
12146 let mut off = 0i64;
12147 let mut digits = 0;
12148 while digits < 4 && *p >= b'0' && *p <= b'9' {
12149 off = off * 10 + (*p - b'0') as i64;
12150 p = p.add(1);
12151 digits += 1;
12152 }
12153 if digits == 0 { return core::ptr::null_mut(); }
12154 let (hh, mm) = if digits <= 2 { (off, 0i64) } else { (off / 100, off % 100) };
12155 (*tm).tm_gmtoff = (hh * 3600 + mm * 60) * if neg { -1 } else { 1 };
12156 }
12157 b'%' => {
12158 if *p != b'%' { return core::ptr::null_mut(); }
12159 p = p.add(1);
12160 }
12161 _ => { return core::ptr::null_mut(); }
12162 }
12163 f = f.add(1);
12164 }
12165 if want_century != 0 {
12166 (*tm).tm_year = relyear;
12167 if want_century & 2 != 0 { (*tm).tm_year += century * 100 - 1900; }
12168 else if (*tm).tm_year <= 68 { (*tm).tm_year += 100; }
12169 }
12170 p as *mut c_char
12171}
12172
12173#[no_mangle]
12178pub static mut daylight: c_int = 0;
12179#[no_mangle]
12180pub static mut timezone: c_long = 0;
12181#[no_mangle]
12182pub 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];
12183
12184#[no_mangle]
12185pub unsafe extern "C" fn tzset() {
12186 daylight = 0;
12187 timezone = 0;
12188}
12189
12190#[no_mangle]
12195pub unsafe extern "C" fn system(cmd: *const c_char) -> c_int {
12196 if cmd.is_null() {
12197 let pid = sys_fork();
12199 if pid == 0 {
12200 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
12201 let dash_c = b"-c\0".as_ptr() as *const c_char;
12202 let exit0 = b"exit 0\0".as_ptr() as *const c_char;
12203 let argv = [b"sh\0".as_ptr() as *const c_char, dash_c, exit0, core::ptr::null()];
12204 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
12205 _exit(127);
12206 }
12207 if pid < 0 { return -1; }
12208 let mut status: c_int = 0;
12209 loop {
12210 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
12211 if r >= 0 { return status; }
12212 if r != -4 { return -1; } }
12214 }
12215
12216 let sa_ignore = KSigAction {
12217 sa_handler: SIG_IGN,
12218 sa_flags: SA_RESTORER,
12219 sa_restorer: sig_restorer as *const () as usize,
12220 sa_mask: [0],
12221 };
12222 let mut oldint: KSigAction = core::mem::zeroed();
12223 let mut oldquit: KSigAction = core::mem::zeroed();
12224
12225 sys_rt_sigaction(SIGINT, &sa_ignore, &mut oldint, 8);
12226 sys_rt_sigaction(SIGQUIT, &sa_ignore, &mut oldquit, 8);
12227
12228 let mut block_set: SigSetT = 0;
12229 block_set |= 1u64 << (SIGCHLD - 1);
12230 let mut oldmask: SigSetT = 0;
12231 sys_rt_sigprocmask(SIG_BLOCK, &block_set, &mut oldmask, 8);
12232
12233 let pid = sys_fork();
12234
12235 if pid == 0 {
12236 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
12237 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
12238 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
12239
12240 let sh = b"/bin/sh\0".as_ptr() as *const c_char;
12241 let argv = [
12242 b"sh\0".as_ptr() as *const c_char,
12243 b"-c\0".as_ptr() as *const c_char,
12244 cmd,
12245 core::ptr::null(),
12246 ];
12247 sys_execve(sh, argv.as_ptr(), __environ as *const *const c_char);
12248 _exit(127);
12249 }
12250
12251 let mut status: c_int = -1;
12252 if pid > 0 {
12253 loop {
12254 let r = sys_wait4(pid as c_int, &mut status, 0, core::ptr::null_mut());
12255 if r >= 0 { break; }
12256 if r != -4 { break; } }
12258 }
12259
12260 sys_rt_sigaction(SIGINT, &oldint, core::ptr::null_mut(), 8);
12261 sys_rt_sigaction(SIGQUIT, &oldquit, core::ptr::null_mut(), 8);
12262 sys_rt_sigprocmask(SIG_SETMASK, &oldmask, core::ptr::null_mut(), 8);
12263
12264 status
12265}
12266
12267const EPERM_VAL: c_int = 1;
12272const ENOENT_VAL: c_int = 2;
12273const ESRCH_VAL: c_int = 3;
12274const EINTR_VAL: c_int = 4;
12275const EIO_VAL: c_int = 5;
12276const ENXIO_VAL: c_int = 6;
12277const E2BIG_VAL: c_int = 7;
12278const ENOEXEC_VAL: c_int = 8;
12279const EBADF_VAL: c_int = 9;
12280const ECHILD_VAL: c_int = 10;
12281const EAGAIN_VAL: c_int = 11;
12282const ENOMEM_VAL: c_int = 12;
12283const EACCES_VAL: c_int = 13;
12284const EFAULT_VAL: c_int = 14;
12285const ENOTBLK_VAL: c_int = 15;
12286const EBUSY_VAL: c_int = 16;
12287const EEXIST_VAL: c_int = 17;
12288const EXDEV_VAL: c_int = 18;
12289const ENODEV_VAL: c_int = 19;
12290const ENOTDIR_VAL: c_int = 20;
12291const EISDIR_VAL: c_int = 21;
12292const EINVAL_VAL: c_int = 22;
12293const ENFILE_VAL: c_int = 23;
12294const EMFILE_VAL: c_int = 24;
12295const ENOTTY_VAL: c_int = 25;
12296const ETXTBSY_VAL: c_int = 26;
12297const EFBIG_VAL: c_int = 27;
12298const ENOSPC_VAL: c_int = 28;
12299const ESPIPE_VAL: c_int = 29;
12300const EROFS_VAL: c_int = 30;
12301const EMLINK_VAL: c_int = 31;
12302const EPIPE_VAL: c_int = 32;
12303const EDOM_VAL: c_int = 33;
12304const ERANGE_VAL: c_int = 34;
12305const EDEADLK_VAL: c_int = 35;
12306const ENAMETOOLONG_VAL: c_int = 36;
12307const ENOLCK_VAL: c_int = 37;
12308const ENOSYS_VAL: c_int = 38;
12309const ENOTEMPTY_VAL: c_int = 39;
12310const ELOOP_VAL: c_int = 40;
12311const EWOULDBLOCK_VAL: c_int = 11;
12312const ENOMSG_VAL: c_int = 42;
12313const EIDRM_VAL: c_int = 43;
12314const ECHRNG_VAL: c_int = 44;
12315const EL2NSYNC_VAL: c_int = 45;
12316const EL3HLT_VAL: c_int = 46;
12317const EL3RST_VAL: c_int = 47;
12318const ELNRNG_VAL: c_int = 48;
12319const EUNATCH_VAL: c_int = 49;
12320const ENOCSI_VAL: c_int = 50;
12321const EL2HLT_VAL: c_int = 51;
12322const EBADE_VAL: c_int = 52;
12323const EBADR_VAL: c_int = 53;
12324const EXFULL_VAL: c_int = 54;
12325const ENOANO_VAL: c_int = 55;
12326const EBADRQC_VAL: c_int = 56;
12327const EBADSLT_VAL: c_int = 57;
12328const EBFONT_VAL: c_int = 59;
12329const ENOSTR_VAL: c_int = 60;
12330const ENODATA_VAL: c_int = 61;
12331const ETIME_VAL: c_int = 62;
12332const ENOSR_VAL: c_int = 63;
12333const ENONET_VAL: c_int = 64;
12334const ENOPKG_VAL: c_int = 65;
12335const EREMOTE_VAL: c_int = 66;
12336const ENOLINK_VAL: c_int = 67;
12337const EADV_VAL: c_int = 68;
12338const ESRMNT_VAL: c_int = 69;
12339const ECOMM_VAL: c_int = 70;
12340const EPROTO_VAL: c_int = 71;
12341const EMULTIHOP_VAL: c_int = 72;
12342const EDOTDOT_VAL: c_int = 73;
12343const EBADMSG_VAL: c_int = 74;
12344const EOVERFLOW_VAL: c_int = 75;
12345const ENOTUNIQ_VAL: c_int = 76;
12346const EBADFD_VAL: c_int = 77;
12347const EREMCHG_VAL: c_int = 78;
12348const ELIBACC_VAL: c_int = 79;
12349const ELIBBAD_VAL: c_int = 80;
12350const ELIBSCN_VAL: c_int = 81;
12351const ELIBMAX_VAL: c_int = 82;
12352const ELIBEXEC_VAL: c_int = 83;
12353const EILSEQ_VAL: c_int = 84;
12354const ERESTART_VAL: c_int = 85;
12355const ESTRPIPE_VAL: c_int = 86;
12356const EUSERS_VAL: c_int = 87;
12357const ENOTSOCK_VAL: c_int = 88;
12358const EDESTADDRREQ_VAL: c_int = 89;
12359const EMSGSIZE_VAL: c_int = 90;
12360const EPROTOTYPE_VAL: c_int = 91;
12361const ENOPROTOOPT_VAL: c_int = 92;
12362const EPROTONOSUPPORT_VAL: c_int = 93;
12363const ESOCKTNOSUPPORT_VAL: c_int = 94;
12364const EOPNOTSUPP_VAL: c_int = 95;
12365const ENOTSUP_VAL: c_int = 95;
12366const EPFNOSUPPORT_VAL: c_int = 96;
12367const EAFNOSUPPORT_VAL: c_int = 97;
12368const EADDRINUSE_VAL: c_int = 98;
12369const EADDRNOTAVAIL_VAL: c_int = 99;
12370const ENETDOWN_VAL: c_int = 100;
12371const ENETUNREACH_VAL: c_int = 101;
12372const ENETRESET_VAL: c_int = 102;
12373const ECONNABORTED_VAL: c_int = 103;
12374const ECONNRESET_VAL: c_int = 104;
12375const ENOBUFS_VAL: c_int = 105;
12376const EISCONN_VAL: c_int = 106;
12377const ENOTCONN_VAL: c_int = 107;
12378const ESHUTDOWN_VAL: c_int = 108;
12379const ETOOMANYREFS_VAL: c_int = 109;
12380const ETIMEDOUT_VAL: c_int = 110;
12381const ECONNREFUSED_VAL: c_int = 111;
12382const EHOSTDOWN_VAL: c_int = 112;
12383const EHOSTUNREACH_VAL: c_int = 113;
12384const EALREADY_VAL: c_int = 114;
12385const EINPROGRESS_VAL: c_int = 115;
12386const ESTALE_VAL: c_int = 116;
12387const EUCLEAN_VAL: c_int = 117;
12388const ENOTNAM_VAL: c_int = 118;
12389const ENAVAIL_VAL: c_int = 119;
12390const EISNAM_VAL: c_int = 120;
12391const EREMOTEIO_VAL: c_int = 121;
12392const EDQUOT_VAL: c_int = 122;
12393const ENOMEDIUM_VAL: c_int = 123;
12394const EMEDIUMTYPE_VAL: c_int = 124;
12395const ECANCELED_VAL: c_int = 125;
12396const ENOKEY_VAL: c_int = 126;
12397const EKEYEXPIRED_VAL: c_int = 127;
12398const EKEYREVOKED_VAL: c_int = 128;
12399const EKEYREJECTED_VAL: c_int = 129;
12400const EOWNERDEAD_VAL: c_int = 130;
12401const ENOTRECOVERABLE_VAL: c_int = 131;
12402const ERFKILL_VAL: c_int = 132;
12403const EHWPOISON_VAL: c_int = 133;
12404
12405static ERR_STRS: [&[u8]; 134] = [
12407 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", ];
12542
12543#[no_mangle]
12544pub unsafe extern "C" fn strerror(errnum: c_int) -> *mut c_char {
12545 if errnum < 0 || errnum as usize >= ERR_STRS.len() {
12546 static mut UNKNOWN_BUF: [c_char; 32] = [0; 32];
12548 let prefix = b"Unknown error \0";
12549 let mut i = 0;
12550 while prefix[i] != 0 {
12551 UNKNOWN_BUF[i] = prefix[i] as c_char;
12552 i += 1;
12553 }
12554 let (buf, len) = format_u64(errnum as u64);
12555 for j in 0..len {
12556 UNKNOWN_BUF[i] = buf[20 - len + j] as c_char;
12557 i += 1;
12558 }
12559 UNKNOWN_BUF[i] = 0;
12560 return core::ptr::addr_of_mut!(UNKNOWN_BUF).cast::<c_char>();
12561 }
12562 ERR_STRS[errnum as usize].as_ptr() as *mut c_char
12563}
12564
12565#[no_mangle]
12566pub unsafe extern "C" fn strerror_r(errnum: c_int, buf: *mut c_char, buflen: usize) -> c_int {
12567 let s = strerror(errnum);
12568 let slen = strlen(s as *const c_char);
12569 if slen >= buflen {
12570 if buflen > 0 {
12571 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, buflen - 1);
12572 *buf.add(buflen - 1) = 0;
12573 }
12574 return 34; }
12576 core::ptr::copy_nonoverlapping(s as *const u8, buf as *mut u8, slen + 1);
12577 0
12578}
12579
12580#[no_mangle]
12582pub static mut environ: *mut *mut c_char = core::ptr::null_mut();
12583
12584unsafe fn sync_environ() {
12586 environ = __environ;
12587}
12588
12589#[inline]
12594unsafe fn sys_dup(oldfd: i32) -> i64 {
12595 <Arch as Syscalls>::syscall1(SYS_DUP, oldfd as i64)
12596}
12597
12598#[inline]unsafe fn sys_dup2(oldfd: i32, newfd: i32) -> i64 {
12599 sys_dup3(oldfd, newfd, 0)
12601}
12602
12603#[inline]
12604unsafe fn sys_access(path: *const u8, mode: i32) -> i64 {
12605 <Arch as Syscalls>::syscall4(SYS_FACCESSAT, AT_FDCWD as i64, path as i64, mode as i64, 0)
12606}
12607
12608#[inline]unsafe fn sys_unlink(path: *const u8) -> i64 {
12609 sys_unlinkat(AT_FDCWD, path, 0)
12610}
12611
12612#[inline]unsafe fn sys_rmdir(path: *const u8) -> i64 {
12613 sys_unlinkat(AT_FDCWD, path, 512) }
12615
12616#[inline]
12617unsafe fn sys_chdir(path: *const u8) -> i64 {
12618 <Arch as Syscalls>::syscall1(SYS_CHDIR, path as i64)
12619}
12620
12621#[inline]
12622unsafe fn sys_getcwd(buf: *mut u8, size: usize) -> i64 {
12623 <Arch as Syscalls>::syscall2(SYS_GETCWD, buf as i64, size as i64)
12624}
12625
12626#[inline]
12627unsafe fn sys_sethostname(name: *const u8, len: usize) -> i64 {
12628 <Arch as Syscalls>::syscall2(SYS_SETHOSTNAME, name as i64, len as i64)
12629}
12630
12631#[inline]
12632unsafe fn sys_gethostname(buf: *mut u8, len: usize) -> i64 {
12633 #[repr(C)]
12634 struct UtsName {
12635 sysname: [u8; 65],
12636 nodename: [u8; 65],
12637 release: [u8; 65],
12638 version: [u8; 65],
12639 machine: [u8; 65],
12640 domainname: [u8; 65],
12641 }
12642 let mut uts: UtsName = core::mem::zeroed();
12643 let result = <Arch as Syscalls>::syscall1(SYS_UNAME, &mut uts as *mut UtsName as i64);
12644 if result < 0 {
12645 return result;
12646 }
12647 let nlen = strlen(uts.nodename.as_ptr() as *const c_char);
12648 let copylen = if nlen < len { nlen } else { if len > 0 { len - 1 } else { 0 } };
12649 core::ptr::copy_nonoverlapping(uts.nodename.as_ptr(), buf, copylen);
12650 if len > 0 { *buf.add(copylen) = 0; }
12651 0
12652}
12653
12654unsafe fn sys_truncate(path: *const u8, length: i64) -> i64 {
12655 <Arch as Syscalls>::syscall2(SYS_TRUNCATE, path as i64, length as i64)
12656}
12657
12658unsafe fn sys_ftruncate(fd: i32, length: i64) -> i64 {
12659 <Arch as Syscalls>::syscall2(SYS_FTRUNCATE, fd as i64, length as i64)
12660}
12661
12662unsafe fn sys_nanosleep(req: *const timespec, rem: *mut timespec) -> i64 {
12663 <Arch as Syscalls>::syscall2(SYS_NANOSLEEP, req as i64, rem as i64)
12664}
12665
12666const ITIMER_REAL: i32 = 0;
12667
12668#[repr(C)]
12669struct itimerval {
12670 it_interval: timeval,
12671 it_value: timeval,
12672}
12673
12674unsafe fn sys_alarm(seconds: c_uint) -> i64 {
12675 let mut new: itimerval = core::mem::zeroed();
12676 new.it_value.tv_sec = seconds as c_long;
12677 let mut old: itimerval = core::mem::zeroed();
12678 let r = <Arch as Syscalls>::syscall3(
12679 SYS_SETITIMER,
12680 ITIMER_REAL as i64,
12681 &new as *const _ as i64,
12682 &mut old as *mut _ as i64,
12683 );
12684 if r < 0 {
12685 return r;
12686 }
12687 old.it_value.tv_sec as i64 + (old.it_value.tv_usec != 0) as i64
12688}
12689
12690unsafe fn sys_pause() -> i64 {
12691 #[cfg(target_arch = "x86_64")]
12692 { <Arch as Syscalls>::syscall0(SYS_PAUSE) }
12693 #[cfg(target_arch = "aarch64")]
12694 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12695 #[cfg(target_arch = "riscv64")]
12696 { <Arch as Syscalls>::syscall4(SYS_PPOLL, 0, 0, 0, 0) }
12697}
12698
12699unsafe fn sys_fsync(fd: i32) -> i64 {
12700 <Arch as Syscalls>::syscall1(SYS_FSYNC, fd as i64)
12701}
12702
12703unsafe fn sys_fdatasync(fd: i32) -> i64 {
12704 <Arch as Syscalls>::syscall1(SYS_FDATASYNC, fd as i64)
12705}
12706
12707unsafe fn sys_sync() {
12708 let _ = <Arch as Syscalls>::syscall0(SYS_SYNC);
12709}
12710
12711unsafe fn sys_symlink(target: *const u8, linkpath: *const u8) -> i64 {
12712 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, AT_FDCWD as i64, linkpath as i64)
12713}
12714
12715unsafe fn sys_symlinkat(target: *const u8, newdirfd: i32, linkpath: *const u8) -> i64 {
12716 <Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, newdirfd as i64, linkpath as i64)
12717}
12718
12719unsafe fn sys_readlinkat(dirfd: i32, path: *const u8, buf: *mut u8, bufsiz: usize) -> i64 {
12720 <Arch as Syscalls>::syscall4(SYS_READLINKAT, dirfd as i64, path as i64, buf as i64, bufsiz as i64)
12721}
12722
12723unsafe fn sys_linkat(olddirfd: i32, oldpath: *const u8, newdirfd: i32, newpath: *const u8, flags: i32) -> i64 {
12724 <Arch as Syscalls>::syscall5(SYS_LINKAT, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, flags as i64)
12725}
12726
12727unsafe fn sys_fchmod(fd: i32, mode: u32) -> i64 {
12728 <Arch as Syscalls>::syscall2(SYS_FCHMOD, fd as i64, mode as i64)
12729}
12730
12731unsafe fn sys_fchmodat(dirfd: i32, path: *const u8, mode: u32, flags: i32) -> i64 {
12732 <Arch as Syscalls>::syscall4(SYS_FCHMODAT, dirfd as i64, path as i64, mode as i64, flags as i64)
12733}
12734
12735unsafe fn sys_umask(mask: u32) -> u32 {
12736 <Arch as Syscalls>::syscall1(SYS_UMASK, mask as i64) as u32
12737}
12738
12739unsafe fn sys_getgroups(size: i32, list: *mut c_uint) -> i64 {
12740 <Arch as Syscalls>::syscall2(SYS_GETGROUPS, size as i64, list as i64)
12741}
12742
12743unsafe fn sys_setuid(uid: c_uint) -> i64 {
12744 <Arch as Syscalls>::syscall1(SYS_SETUID, uid as i64)
12745}
12746
12747unsafe fn sys_setgid(gid: c_uint) -> i64 {
12748 <Arch as Syscalls>::syscall1(SYS_SETGID, gid as i64)
12749}
12750
12751unsafe fn sys_setsid() -> i64 {
12752 <Arch as Syscalls>::syscall0(SYS_SETSID)
12753}
12754
12755unsafe fn sys_setpgid(pid: c_int, pgid: c_int) -> i64 {
12756 <Arch as Syscalls>::syscall2(SYS_SETPGID, pid as i64, pgid as i64)
12757}
12758
12759unsafe fn sys_getpgid(pid: c_int) -> i64 {
12760 <Arch as Syscalls>::syscall1(SYS_GETPGID, pid as i64)
12761}
12762
12763unsafe fn sys_getsid(pid: c_int) -> i64 {
12764 <Arch as Syscalls>::syscall1(SYS_GETSID, pid as i64)
12765}
12766
12767unsafe fn sys_mkdirat(dirfd: i32, path: *const u8, mode: u32) -> i64 {
12768 <Arch as Syscalls>::syscall3(SYS_MKDIRAT, dirfd as i64, path as i64, mode as i64)
12769}
12770
12771#[no_mangle]
12774pub unsafe extern "C" fn pipe(fds: *mut c_int) -> c_int {
12775 let r = sys_pipe2(fds, 0);
12776 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12777 0
12778}
12779
12780#[no_mangle]
12781pub unsafe extern "C" fn pipe2(fds: *mut c_int, flags: c_int) -> c_int {
12782 let r = sys_pipe2(fds, flags);
12783 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12784 0
12785}
12786
12787#[no_mangle]
12788pub unsafe extern "C" fn dup(oldfd: c_int) -> c_int {
12789 let r = sys_dup(oldfd);
12790 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12791 r as c_int
12792}
12793
12794#[no_mangle]
12795pub unsafe extern "C" fn dup2(oldfd: c_int, newfd: c_int) -> c_int {
12796 if oldfd == newfd {
12797 let r = sys_fcntl(oldfd, 1 , 0);
12800 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12801 return newfd;
12802 }
12803 let r = sys_dup2(oldfd, newfd);
12804 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12805 r as c_int
12806}
12807
12808#[no_mangle]
12809pub unsafe extern "C" fn dup3(oldfd: c_int, newfd: c_int, flags: c_int) -> c_int {
12810 let r = sys_dup3(oldfd, newfd, flags);
12811 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12812 r as c_int
12813}
12814
12815#[no_mangle]
12816pub unsafe extern "C" fn fcntl(fd: c_int, cmd: c_int, mut args: ...) -> c_int {
12817 let no_arg = matches!(cmd, 1 | 3 | 9 | 11 | 1025 | 1032 | 1034 );
12822 let r = if no_arg {
12823 sys_fcntl(fd, cmd, 0)
12824 } else {
12825 let arg = args.next_arg::<c_long>();
12826 sys_fcntl(fd, cmd, arg)
12827 };
12828 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12829 r as c_int
12830}
12831
12832#[no_mangle]
12833pub unsafe extern "C" fn access(path: *const c_char, mode: c_int) -> c_int {
12834 let r = sys_access(path as *const u8, mode);
12835 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12836 0
12837}
12838
12839#[no_mangle]
12840pub unsafe extern "C" fn unlink(path: *const c_char) -> c_int {
12841 let r = sys_unlink(path as *const u8);
12842 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12843 0
12844}
12845
12846#[no_mangle]
12847pub unsafe extern "C" fn rmdir(path: *const c_char) -> c_int {
12848 let r = sys_rmdir(path as *const u8);
12849 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12850 0
12851}
12852
12853#[no_mangle]
12854pub unsafe extern "C" fn chdir(path: *const c_char) -> c_int {
12855 let r = sys_chdir(path as *const u8);
12856 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12857 0
12858}
12859
12860#[no_mangle]
12861pub unsafe extern "C" fn getcwd(buf: *mut c_char, size: usize) -> *mut c_char {
12862 if buf.is_null() {
12863 let alloc_size = if size == 0 { 256 } else { size };
12865 let p = malloc(alloc_size) as *mut c_char;
12866 if p.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
12867 let r = sys_getcwd(p as *mut u8, alloc_size);
12868 if r < 0 { free(p as *mut c_void); ERRNO!() = (-r) as c_int; return core::ptr::null_mut(); }
12869 if *p as u8 != b'/' {
12872 free(p as *mut c_void);
12873 ERRNO!() = 2;
12874 return core::ptr::null_mut();
12875 }
12876 return p;
12877 }
12878 if size == 0 { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
12879 let r = sys_getcwd(buf as *mut u8, size);
12880 if r < 0 { ERRNO!() = (-r) as c_int; return core::ptr::null_mut(); }
12881 if *buf as u8 != b'/' {
12882 ERRNO!() = 2;
12883 return core::ptr::null_mut();
12884 }
12885 buf
12886}
12887
12888#[no_mangle]
12889pub unsafe extern "C" fn gethostname(name: *mut c_char, len: usize) -> c_int {
12890 let r = sys_gethostname(name as *mut u8, len);
12891 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12892 0
12893}
12894
12895#[no_mangle]
12897pub extern "C" fn getpagesize() -> c_int {
12898 4096
12899}
12900
12901#[no_mangle]
12902pub unsafe extern "C" fn truncate(path: *const c_char, length: i64) -> c_int {
12903 let r = sys_truncate(path as *const u8, length);
12904 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12905 0
12906}
12907
12908#[no_mangle]
12909pub unsafe extern "C" fn ftruncate(fd: c_int, length: i64) -> c_int {
12910 let r = sys_ftruncate(fd, length);
12911 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12912 0
12913}
12914
12915#[no_mangle]
12916pub unsafe extern "C" fn nanosleep(req: *const timespec, rem: *mut timespec) -> c_int {
12917 pthread_testcancel();
12918 let r = sys_nanosleep(req, rem);
12919 pthread_testcancel();
12920 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12921 0
12922}
12923
12924#[no_mangle]
12925pub unsafe extern "C" fn sleep(seconds: c_uint) -> c_uint {
12926 let req = timespec { tv_sec: seconds as c_long, tv_nsec: 0 };
12927 let mut rem: timespec = core::mem::zeroed();
12928 pthread_testcancel();
12929 let r = sys_nanosleep(&req, &mut rem);
12930 pthread_testcancel();
12931 if r < 0 {
12932 let e = (-r) as c_int;
12933 if e == EINTR { return rem.tv_sec as c_uint; }
12934 }
12935 0
12936}
12937
12938#[no_mangle]
12939pub unsafe extern "C" fn usleep(usec: c_uint) -> c_int {
12940 let req = timespec { tv_sec: (usec / 1000000) as c_long, tv_nsec: ((usec % 1000000) * 1000) as c_long };
12941 pthread_testcancel();
12942 let r = sys_nanosleep(&req, core::ptr::null_mut());
12943 pthread_testcancel();
12944 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12945 0
12946}
12947
12948#[no_mangle]
12949pub unsafe extern "C" fn alarm(seconds: c_uint) -> c_uint {
12950 let r = sys_alarm(seconds);
12953 if r < 0 { 0 } else { r as c_uint }
12954}
12955
12956#[no_mangle]
12957pub unsafe extern "C" fn pause() -> c_int {
12958 pthread_testcancel();
12959 sys_pause();
12960 pthread_testcancel();
12961 ERRNO!() = EINTR;
12962 -1
12963}
12964
12965#[no_mangle]
12966pub unsafe extern "C" fn fsync(fd: c_int) -> c_int {
12967 let r = sys_fsync(fd);
12968 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12969 0
12970}
12971
12972#[no_mangle]
12973pub unsafe extern "C" fn fdatasync(fd: c_int) -> c_int {
12974 let r = sys_fdatasync(fd);
12975 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12976 0
12977}
12978
12979#[no_mangle]
12980pub unsafe extern "C" fn sync() {
12981 sys_sync();
12982}
12983
12984#[no_mangle]
12985pub unsafe extern "C" fn symlink(target: *const c_char, linkpath: *const c_char) -> c_int {
12986 let r = sys_symlinkat(target as *const u8, AT_FDCWD, linkpath as *const u8);
12987 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12988 0
12989}
12990
12991#[no_mangle]
12992pub unsafe extern "C" fn readlink(path: *const c_char, buf: *mut c_char, bufsiz: usize) -> isize {
12993 let r = sys_readlinkat(AT_FDCWD, path as *const u8, buf as *mut u8, bufsiz);
12994 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
12995 r as isize
12996}
12997
12998#[no_mangle]
12999pub unsafe extern "C" fn link(oldpath: *const c_char, newpath: *const c_char) -> c_int {
13000 let r = sys_linkat(AT_FDCWD, oldpath as *const u8, AT_FDCWD, newpath as *const u8, 0);
13001 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13002 0
13003}
13004
13005#[no_mangle]
13006pub unsafe extern "C" fn chmod(path: *const c_char, mode: c_uint) -> c_int {
13007 let r = sys_fchmodat(AT_FDCWD, path as *const u8, mode, 0);
13008 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13009 0
13010}
13011
13012#[no_mangle]
13013pub unsafe extern "C" fn fchmod(fd: c_int, mode: c_uint) -> c_int {
13014 let r = sys_fchmod(fd, mode);
13015 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13016 0
13017}
13018
13019#[no_mangle]
13020pub unsafe extern "C" fn umask(mask: c_uint) -> c_uint {
13021 sys_umask(mask) as c_uint
13022}
13023
13024#[no_mangle]
13025pub unsafe extern "C" fn isatty(fd: c_int) -> c_int {
13026 let mut ws: winsize = core::mem::zeroed();
13027 if sys_ioctl(fd, TIOCGWINSZ, &mut ws as *mut winsize as *mut u8) == 0 { 1 } else { 0 }
13028}
13029
13030#[no_mangle]
13031pub unsafe extern "C" fn getlogin() -> *mut c_char {
13032 static mut LOGIN_BUF: [c_char; 32] = [0; 32];
13033 let pw = getpwuid(crate::getuid());
13034 if pw.is_null() { return core::ptr::null_mut(); }
13035 let n = crate::strlen((*pw).pw_name);
13036 if n + 1 > LOGIN_BUF.len() { return core::ptr::null_mut(); }
13037 core::ptr::copy_nonoverlapping((*pw).pw_name, LOGIN_BUF.as_mut_ptr(), n + 1);
13038 LOGIN_BUF.as_mut_ptr()
13039}
13040
13041#[no_mangle]
13042pub unsafe extern "C" fn getgroups(size: c_int, list: *mut c_uint) -> c_int {
13043 let r = sys_getgroups(size, list);
13044 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13045 r as c_int
13046}
13047
13048#[no_mangle]
13049pub unsafe extern "C" fn setuid(uid: c_uint) -> c_int {
13050 let r = sys_setuid(uid);
13051 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13052 0
13053}
13054
13055#[no_mangle]
13056pub unsafe extern "C" fn setgid(gid: c_uint) -> c_int {
13057 let r = sys_setgid(gid);
13058 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13059 0
13060}
13061
13062#[no_mangle]
13063pub unsafe extern "C" fn seteuid(euid: c_uint) -> c_int {
13064 setresuid(u32::MAX, euid, u32::MAX)
13068}
13069
13070#[no_mangle]
13071pub unsafe extern "C" fn setegid(egid: c_uint) -> c_int {
13072 setresgid(u32::MAX, egid, u32::MAX)
13073}
13074
13075#[no_mangle]
13076pub unsafe extern "C" fn setreuid(ruid: c_uint, euid: c_uint) -> c_int {
13077 let r = <Arch as Syscalls>::syscall2(sysno(113, 145), ruid as i64, euid as i64);
13078 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
13079}
13080
13081
13082
13083#[no_mangle]
13084pub unsafe extern "C" fn setsid() -> c_int {
13085 let r = sys_setsid();
13086 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13087 r as c_int
13088}
13089
13090#[no_mangle]
13091pub unsafe extern "C" fn setpgid(pid: c_int, pgid: c_int) -> c_int {
13092 let r = sys_setpgid(pid, pgid);
13093 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13094 0
13095}
13096
13097#[no_mangle]
13098pub unsafe extern "C" fn getpgid(pid: c_int) -> c_int {
13099 let r = sys_getpgid(pid);
13100 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13101 r as c_int
13102}
13103
13104#[no_mangle]
13105pub unsafe extern "C" fn getsid(pid: c_int) -> c_int {
13106 let r = sys_getsid(pid);
13107 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13108 r as c_int
13109}
13110
13111#[no_mangle]
13112pub unsafe extern "C" fn getpgrp() -> c_int {
13113 sys_getpgid(0) as c_int
13114}
13115
13116#[no_mangle]
13117pub unsafe extern "C" fn setpgrp() -> c_int {
13118 setpgid(0, 0)
13119}
13120
13121#[no_mangle]
13122pub unsafe extern "C" fn mkstemp(template: *mut c_char) -> c_int {
13123 if template.is_null() { ERRNO!() = EINVAL; return -1; }
13124 let len = strlen(template as *const c_char);
13125 if len < 6 { ERRNO!() = EINVAL; return -1; }
13126 let x_start = len - 6;
13127 for i in x_start..len {
13129 if *template.add(i) != b'X' as c_char { ERRNO!() = EINVAL; return -1; }
13130 }
13131 let mut ts: timespec = core::mem::zeroed();
13132 let _ = sys_clock_gettime(CLOCK_REALTIME, &mut ts);
13133 let mut ctr: u32 = ts.tv_nsec as u32;
13134 for _ in 0..100 {
13135 ctr = ctr.wrapping_mul(1103515245).wrapping_add(12345);
13136 let seed = ctr;
13137 let hex = b"0123456789abcdef";
13139 let mut s = seed;
13140 for i in x_start..len {
13141 *template.add(i) = hex[(s & 0xf) as usize] as c_char;
13142 s >>= 4;
13143 }
13144 let fd = sys_open(template as *const u8, (O_RDWR | O_CREAT | O_EXCL) as i64, 0o600);
13145 if fd >= 0 { return fd as c_int; }
13146 let e = (-fd) as c_int;
13147 if e != EEXIST_VAL { ERRNO!() = e; return -1; }
13148 }
13149 ERRNO!() = EEXIST_VAL;
13150 -1
13151}
13152
13153#[no_mangle]
13154pub unsafe extern "C" fn mkdir(path: *const c_char, mode: c_uint) -> c_int {
13155 let r = sys_mkdirat(AT_FDCWD, path as *const u8, mode);
13156 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
13157 0
13158}
13159
13160#[no_mangle]
13165pub unsafe extern "C" fn dirname(s: *mut c_char) -> *mut c_char {
13166 if s.is_null() || *s == 0 {
13167 return b".\0".as_ptr() as *mut c_char;
13168 }
13169 let mut i = strlen(s as *const c_char);
13170 i = i.wrapping_sub(1);
13171 while i > 0 && *s.add(i) == b'/' as c_char {
13173 i = i.wrapping_sub(1);
13174 }
13175 if i == 0 && *s.add(0) == b'/' as c_char {
13176 return b"/\0".as_ptr() as *mut c_char;
13177 }
13178 while i > 0 && *s.add(i) != b'/' as c_char {
13180 i = i.wrapping_sub(1);
13181 }
13182 if i == 0 {
13183 if *s.add(0) == b'/' as c_char {
13184 return b"/\0".as_ptr() as *mut c_char;
13185 }
13186 return b".\0".as_ptr() as *mut c_char;
13187 }
13188 while i > 0 && *s.add(i - 1) == b'/' as c_char {
13190 i = i.wrapping_sub(1);
13191 }
13192 if i == 0 {
13193 return b"/\0".as_ptr() as *mut c_char;
13194 }
13195 *s.add(i) = 0;
13196 s
13197}
13198
13199#[no_mangle]
13200pub unsafe extern "C" fn basename(s: *mut c_char) -> *mut c_char {
13201 if s.is_null() || *s == 0 {
13202 return b".\0".as_ptr() as *mut c_char;
13203 }
13204 let mut i = strlen(s as *const c_char);
13205 i = i.wrapping_sub(1);
13206 while i > 0 && *s.add(i) == b'/' as c_char {
13208 *s.add(i) = 0;
13209 i = i.wrapping_sub(1);
13210 }
13211 while i > 0 && *s.add(i - 1) != b'/' as c_char {
13213 i = i.wrapping_sub(1);
13214 }
13215 s.add(i)
13216}
13217
13218const AF_INET_VAL: c_int = 2;
13223const AF_INET6_VAL: c_int = 10;
13224const EAFNOSUPPORT: c_int = 97;
13225const ENOSPC_VAL2: c_int = 28;
13226
13227unsafe fn inet_pton_v4(s: *const u8, a: *mut u8) -> c_int {
13228 let mut p = s;
13229 let mut i = 0;
13230 while i < 4 {
13231 let oct_start = p;
13232 let mut v: u32 = 0;
13233 let mut j: u32 = 0;
13234 while j < 3 && *p >= b'0' && *p <= b'9' {
13235 v = v * 10 + (*p - b'0') as u32;
13236 p = p.add(1);
13237 j += 1;
13238 }
13239 if j == 0 || (j > 1 && *oct_start == b'0') || v > 255 { return 0; }
13240 *a.add(i) = v as u8;
13241 if *p == 0 && i == 3 { return 1; }
13242 if *p != b'.' { return 0; }
13243 p = p.add(1);
13244 i += 1;
13245 }
13246 0
13247}
13248
13249unsafe fn inet_pton_v6(s: *const u8, a: *mut u8) -> c_int {
13250 let mut ip = [0u16; 8];
13251 let mut p = s;
13252 let mut i: usize = 0;
13253 let mut brk: isize = -1;
13254 let mut need_v4 = false;
13255 let mut v4_start: *const u8 = core::ptr::null();
13256
13257 if *p == b':' {
13258 p = p.add(1);
13259 if *p != b':' { return 0; }
13260 }
13261
13262 loop {
13263 if *p == b':' && brk < 0 {
13264 brk = i as isize;
13265 ip[i & 7] = 0;
13266 p = p.add(1);
13267 if *p == 0 { break; }
13268 if i == 7 { return 0; }
13269 i += 1;
13270 continue;
13271 }
13272 v4_start = p;
13273 let mut v: u16 = 0;
13274 let mut j = 0;
13275 while j < 4 {
13276 let d = hex_digit(*p);
13277 if d < 0 { break; }
13278 v = v * 16 + d as u16;
13279 p = p.add(1);
13280 j += 1;
13281 }
13282 if j == 0 { return 0; }
13283 ip[i & 7] = v;
13284 if *p == 0 && (brk >= 0 || i == 7) { break; }
13285 if i == 7 { return 0; }
13286 if *p != b':' {
13287 if *p != b'.' || (i < 6 && brk < 0) { return 0; }
13288 need_v4 = true;
13289 i += 1;
13290 ip[i & 7] = 0;
13291 break;
13292 }
13293 p = p.add(1);
13294 i += 1;
13295 }
13296
13297 if brk >= 0 {
13298 let trail_count = i + 1 - brk as usize;
13300 let dest_start = brk as usize + 7 - i;
13301 for j in (0..trail_count).rev() {
13303 ip[dest_start + j] = ip[brk as usize + j];
13304 }
13305 for j in 0..(7 - i) {
13306 ip[brk as usize + j] = 0;
13307 }
13308 }
13309
13310 for k in 0..8 {
13311 *a.add(k * 2) = (ip[k] >> 8) as u8;
13312 *a.add(k * 2 + 1) = (ip[k] & 0xff) as u8;
13313 }
13314
13315 if need_v4 {
13316 if inet_pton_v4(v4_start, a.add(12)) <= 0 { return 0; }
13317 }
13318 1
13319}
13320
13321unsafe fn hex_digit(c: u8) -> i32 {
13322 if c >= b'0' && c <= b'9' { (c - b'0') as i32 }
13323 else if c >= b'a' && c <= b'f' { (c - b'a' + 10) as i32 }
13324 else if c >= b'A' && c <= b'F' { (c - b'A' + 10) as i32 }
13325 else { -1 }
13326}
13327
13328#[no_mangle]
13329pub unsafe extern "C" fn inet_pton(af: c_int, s: *const c_char, a: *mut c_void) -> c_int {
13330 if af == AF_INET_VAL {
13331 inet_pton_v4(s as *const u8, a as *mut u8)
13332 } else if af == AF_INET6_VAL {
13333 inet_pton_v6(s as *const u8, a as *mut u8)
13334 } else {
13335 ERRNO!() = EAFNOSUPPORT;
13336 -1
13337 }
13338}
13339
13340#[no_mangle]
13341pub unsafe extern "C" fn inet_ntop(af: c_int, a: *const c_void, s: *mut c_char, size: u32) -> *mut c_char {
13342 if af == AF_INET_VAL {
13343 let b = a as *const u8;
13344 let needed = 16; if size < needed as u32 { ERRNO!() = ENOSPC_VAL2; return core::ptr::null_mut(); }
13346 let mut pos = 0;
13347 for i in 0..4 {
13348 if i > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
13349 let (buf, len) = format_u64(*b.add(i) as u64);
13350 for j in 0..len { *s.add(pos) = buf[j] as c_char; pos += 1; }
13351 }
13352 *s.add(pos) = 0;
13353 s
13354 } else if af == AF_INET6_VAL {
13355 let b = a as *const u8;
13356 let needed = 46; if size < needed as u32 { ERRNO!() = ENOSPC_VAL2; return core::ptr::null_mut(); }
13358 let mut words = [0u16; 8];
13359 for i in 0..8 {
13360 words[i] = ((*b.add(i * 2) as u16) << 8) | (*b.add(i * 2 + 1) as u16);
13361 }
13362 let mut pos = 0usize;
13364 if words[0] == 0 && words[1] == 0 && words[2] == 0 && words[3] == 0
13365 && words[4] == 0 && words[5] == 0xffff
13366 {
13367 let prefix = b"::ffff:";
13368 for k in 0..prefix.len() { *s.add(pos) = prefix[k] as c_char; pos += 1; }
13369 for idx in 0..4 {
13370 if idx > 0 { *s.add(pos) = b'.' as c_char; pos += 1; }
13371 let octet = *b.add(12 + idx);
13372 if octet >= 100 {
13373 *s.add(pos) = (b'0' + octet / 100) as c_char; pos += 1;
13374 *s.add(pos) = (b'0' + (octet / 10) % 10) as c_char; pos += 1;
13375 } else if octet >= 10 {
13376 *s.add(pos) = (b'0' + octet / 10) as c_char; pos += 1;
13377 }
13378 *s.add(pos) = (b'0' + octet % 10) as c_char; pos += 1;
13379 }
13380 *s.add(pos) = 0;
13381 return s;
13382 }
13383 let mut best_start: isize = -1;
13385 let mut best_len: usize = 0;
13386 let mut j: usize = 0;
13387 while j < 8 {
13388 if words[j] == 0 {
13389 let mut k = j;
13390 while k < 8 && words[k] == 0 { k += 1; }
13391 let run = k - j;
13392 if run > best_len { best_start = j as isize; best_len = run; }
13393 j = k;
13394 } else {
13395 j += 1;
13396 }
13397 }
13398 let mut i: usize = 0;
13399 let mut prev_in_run = false;
13400 while i < 8 {
13401 let in_run = best_len >= 2 && i >= best_start as usize && i < best_start as usize + best_len;
13402 if in_run {
13403 if i == best_start as usize {
13404 *s.add(pos) = b':' as c_char; pos += 1;
13405 *s.add(pos) = b':' as c_char; pos += 1;
13406 }
13407 i += 1;
13408 prev_in_run = true;
13409 continue;
13410 }
13411 if i > 0 && !prev_in_run {
13412 *s.add(pos) = b':' as c_char; pos += 1;
13413 }
13414 let (buf, len) = format_hex(words[i] as u64, false);
13415 for k in 0..len { *s.add(pos) = buf[k] as c_char; pos += 1; }
13416 i += 1;
13417 prev_in_run = false;
13418 }
13419 *s.add(pos) = 0;
13420 s
13421 } else {
13422 ERRNO!() = EAFNOSUPPORT;
13423 core::ptr::null_mut()
13424 }
13425}
13426
13427#[no_mangle]
13428pub unsafe extern "C" fn inet_aton(s: *const c_char, dest: *mut c_void) -> c_int {
13429 let a = dest as *mut u8;
13430 let mut p = s as *const u8;
13431 let mut vals = [0u64; 4];
13432 let mut i = 0usize;
13433 while i < 4 {
13434 if *p < b'0' || *p > b'9' { return 0; }
13435 let mut base = 10u32;
13436 if *p == b'0' {
13437 let c = *p.add(1);
13438 if c == b'x' || c == b'X' {
13439 base = 16;
13440 p = p.add(2);
13441 if !((*p >= b'0' && *p <= b'9')
13442 || (*p >= b'a' && *p <= b'f')
13443 || (*p >= b'A' && *p <= b'F')) {
13444 return 0;
13445 }
13446 } else {
13447 base = 8;
13448 }
13449 }
13450 let mut v: u64 = 0;
13451 let start = p;
13452 loop {
13453 let c = *p;
13454 let d = if c >= b'0' && c <= b'9' {
13455 (c - b'0') as u64
13456 } else if base == 16 && c >= b'a' && c <= b'f' {
13457 (c - b'a' + 10) as u64
13458 } else if base == 16 && c >= b'A' && c <= b'F' {
13459 (c - b'A' + 10) as u64
13460 } else {
13461 break;
13462 };
13463 v = v * (base as u64) + d;
13464 p = p.add(1);
13465 }
13466 if p == start { return 0; }
13467 vals[i] = v;
13468 if *p == 0 {
13469 break;
13470 }
13471 if *p != b'.' || i == 3 { return 0; }
13472 p = p.add(1);
13473 i += 1;
13474 }
13475 if i == 4 { return 0; }
13476 if i < 1 { vals[1] = vals[0] & 0xffffff; vals[0] >>= 24; }
13477 if i < 2 { vals[2] = vals[1] & 0xffff; vals[1] >>= 16; }
13478 if i < 3 { vals[3] = vals[2] & 0xff; vals[2] >>= 8; }
13479 for j in 0..4 {
13480 if vals[j] > 255 { return 0; }
13481 *a.add(j) = vals[j] as u8;
13482 }
13483 1
13484}
13485
13486#[no_mangle]
13487pub unsafe extern "C" fn inet_addr(s: *const c_char) -> u32 {
13488 let mut a = [0u8; 4];
13489 if inet_aton(s, a.as_mut_ptr() as *mut c_void) == 1 {
13490 u32::from_ne_bytes(a)
13491 } else {
13492 !0u32 }
13494}
13495
13496#[no_mangle]
13497pub unsafe extern "C" fn inet_ntoa(addr: u32) -> *mut c_char {
13498 static mut NTOA_BUF: [c_char; 16] = [0; 16];
13499 let b = addr.to_ne_bytes();
13500 let mut pos = 0;
13501 for i in 0..4 {
13502 if i > 0 { NTOA_BUF[pos] = b'.' as c_char; pos += 1; }
13503 let (buf, len) = format_u64(b[i] as u64);
13504 for j in 0..len { NTOA_BUF[pos] = buf[j] as c_char; pos += 1; }
13505 }
13506 NTOA_BUF[pos] = 0;
13507 core::ptr::addr_of_mut!(NTOA_BUF).cast::<c_char>()
13508}
13509
13510#[no_mangle]
13512pub unsafe extern "C" fn inet_network(s: *const c_char) -> u32 {
13513 inet_addr(s).to_be()
13514}
13515
13516#[no_mangle]
13517pub extern "C" fn inet_makeaddr(net: c_int, host: c_int) -> u32 {
13518 let addr: u32;
13519 if (net as u32) < 128 {
13520 addr = (net as u32) << 24;
13521 } else if (net as u32) < 0x10000 {
13522 addr = (net as u32) << 16;
13523 } else if (net as u32) < 0x1000000 {
13524 addr = (net as u32) << 8;
13525 } else {
13526 addr = net as u32;
13527 }
13528 addr | (host as u32 & 0xffffffff)
13529}
13530
13531#[no_mangle]
13532pub extern "C" fn inet_lnaof(addr: u32) -> c_int {
13533 let h = u32::from_be(addr);
13534 if h < 0x80000000 { (h & 0x00ffffff) as c_int }
13535 else if h < 0xc0000000 { (h & 0x0000ffff) as c_int }
13536 else { (h & 0x000000ff) as c_int }
13537}
13538
13539#[no_mangle]
13540pub extern "C" fn inet_netof(addr: u32) -> c_int {
13541 let h = u32::from_be(addr);
13542 if h < 0x80000000 { (h >> 24) as c_int }
13543 else if h < 0xc0000000 { (h >> 16) as c_int }
13544 else { (h >> 8) as c_int }
13545}
13546
13547unsafe fn parse_float(s: *const u8, endptr: *mut *mut u8, is_f32: bool) -> f64 {
13556 let mut p = s;
13557 while *p == b' ' || *p == b'\t' || *p == b'\n' || *p == b'\r' { p = p.add(1); }
13559 let mut neg = false;
13560 if *p == b'-' { neg = true; p = p.add(1); }
13561 else if *p == b'+' { p = p.add(1); }
13562
13563 if (*p | 0x20) == b'i'
13565 && (*p.add(1) | 0x20) == b'n'
13566 && (*p.add(2) | 0x20) == b'f'
13567 {
13568 p = p.add(3);
13569 if (*p | 0x20) == b'i'
13571 && (*p.add(1) | 0x20) == b't'
13572 && (*p.add(2) | 0x20) == b'y'
13573 {
13574 p = p.add(3);
13575 }
13576 if !endptr.is_null() { *endptr = p as *mut u8; }
13577 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13578 }
13579 if (*p | 0x20) == b'n'
13581 && (*p.add(1) | 0x20) == b'a'
13582 && (*p.add(2) | 0x20) == b'n'
13583 {
13584 p = p.add(3);
13585 if *p == b'(' {
13587 p = p.add(1);
13588 while *p != 0 && *p != b')' { p = p.add(1); }
13589 if *p == b')' { p = p.add(1); }
13590 }
13591 if !endptr.is_null() { *endptr = p as *mut u8; }
13592 return if neg { -f64::NAN } else { f64::NAN };
13593 }
13594
13595 if *p == b'0' && (*p.add(1) == b'x' || *p.add(1) == b'X') {
13597 p = p.add(2);
13598 let mut mant: u128 = 0;
13599 let mut frac_hex: u32 = 0;
13600 let mut found = false;
13601 let mut in_frac = false;
13602
13603 loop {
13604 if let Some(d) = hex_val(*p) {
13605 if mant <= u128::MAX / 16 {
13606 mant = mant * 16 + d as u128;
13607 }
13608 if in_frac { frac_hex += 1; }
13609 p = p.add(1);
13610 found = true;
13611 } else if *p == b'.' && !in_frac {
13612 in_frac = true;
13613 p = p.add(1);
13614 } else {
13615 break;
13616 }
13617 }
13618
13619 if !found {
13620 if !endptr.is_null() { *endptr = s as *mut u8; }
13621 return 0.0;
13622 }
13623
13624 let mut bin_exp: i32 = 0;
13626 if *p == b'p' || *p == b'P' {
13627 p = p.add(1);
13628 let mut exp_neg = false;
13629 if *p == b'-' { exp_neg = true; p = p.add(1); }
13630 else if *p == b'+' { p = p.add(1); }
13631 while *p >= b'0' && *p <= b'9' {
13632 if bin_exp < 100000 {
13633 bin_exp = bin_exp * 10 + (*p - b'0') as i32;
13634 }
13635 p = p.add(1);
13636 }
13637 if exp_neg { bin_exp = -bin_exp; }
13638 }
13639
13640 if !endptr.is_null() { *endptr = p as *mut u8; }
13641 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
13642
13643 let total_exp = bin_exp as i64 - 4 * frac_hex as i64;
13644 return hex_mant_to_f64(mant, total_exp, neg);
13645 }
13646
13647 let mut buf = [0u8; 65536];
13649 let mut n = 0usize;
13650 let mut found_digit = false;
13651
13652 while *p >= b'0' && *p <= b'9' {
13653 if n < 65535 { buf[n] = *p; n += 1; }
13654 p = p.add(1);
13655 found_digit = true;
13656 }
13657 if *p == b'.' {
13658 if n < 65535 { buf[n] = b'.'; n += 1; }
13659 p = p.add(1);
13660 while *p >= b'0' && *p <= b'9' {
13661 if n < 65535 { buf[n] = *p; n += 1; }
13662 p = p.add(1);
13663 found_digit = true;
13664 }
13665 }
13666 if !found_digit {
13667 if !endptr.is_null() { *endptr = s as *mut u8; }
13668 return 0.0;
13669 }
13670 if *p == b'e' || *p == b'E' {
13671 if n < 65535 { buf[n] = b'e'; n += 1; }
13672 p = p.add(1);
13673 if *p == b'-' || *p == b'+' {
13674 if n < 65535 { buf[n] = *p; n += 1; }
13675 p = p.add(1);
13676 }
13677 while *p >= b'0' && *p <= b'9' {
13678 if n < 65535 { buf[n] = *p; n += 1; }
13679 p = p.add(1);
13680 }
13681 }
13682
13683 if !endptr.is_null() { *endptr = p as *mut u8; }
13684 let s_str = core::str::from_utf8_unchecked(
13685 core::slice::from_raw_parts(buf.as_ptr(), n),
13686 );
13687 if is_f32 {
13688 match <f32 as core::str::FromStr>::from_str(s_str) {
13689 Ok(v) => { let r = v as f64; if neg { -r } else { r } }
13690 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13691 }
13692 } else {
13693 match <f64 as core::str::FromStr>::from_str(s_str) {
13694 Ok(v) => if neg { -v } else { v },
13695 Err(_) => { if !endptr.is_null() { *endptr = s as *mut u8; } 0.0 }
13696 }
13697 }
13698}
13699
13700fn hex_mant_to_f64(mant: u128, total_exp: i64, neg: bool) -> f64 {
13704 if mant == 0 { return if neg { -0.0 } else { 0.0 }; }
13705
13706 let msb = (127 - mant.leading_zeros()) as i64;
13707 let unbiased_exp = msb + total_exp;
13708 let biased_exp = unbiased_exp + 1023;
13709
13710 if biased_exp >= 2047 {
13712 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13713 }
13714
13715 if biased_exp <= 0 {
13717 let shift = total_exp + 1074;
13720 if shift < 0 {
13721 return if neg { -0.0 } else { 0.0 };
13722 }
13723 if shift > 128 {
13724 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13725 }
13726 let shifted = mant << (shift as u32);
13727 let mantissa52 = (shifted as u64) & 0x000FFFFFFFFFFFFF;
13728 let guard = ((shifted >> 52) & 1) != 0;
13729 let sticky = (shifted >> 53) != 0;
13730 let mut result = mantissa52;
13731 if guard && (sticky || (result & 1) != 0) {
13732 result += 1;
13733 if result > 0x000FFFFFFFFFFFFF {
13734 return if neg { -f64::from_bits(1u64 << 52) } else { f64::from_bits(1u64 << 52) };
13736 }
13737 }
13738 return if neg { -f64::from_bits(result) } else { f64::from_bits(result) };
13739 }
13740
13741 let shift = msb - 52;
13743
13744 if shift <= 0 {
13745 let mantissa = ((mant as u64) & ((1u64 << msb as u32) - 1)) << ((-shift) as u32);
13747 let bits = ((biased_exp as u64) << 52) | mantissa;
13748 return if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) };
13749 }
13750
13751 let mantissa = ((mant >> shift as u32) as u64) & 0x000FFFFFFFFFFFFF;
13753 let guard = ((mant >> (shift as u32 - 1)) & 1) != 0;
13754 let sticky = if shift > 1 {
13755 (mant & ((1u128 << (shift as u32 - 1)) - 1)) != 0
13756 } else { false };
13757
13758 let mut result_mant = mantissa;
13759 let mut result_exp = biased_exp;
13760 if guard && (sticky || (result_mant & 1) != 0) {
13761 result_mant += 1;
13762 if result_mant > 0x000FFFFFFFFFFFFF {
13763 result_mant = 0;
13764 result_exp += 1;
13765 if result_exp >= 2047 {
13766 return if neg { f64::NEG_INFINITY } else { f64::INFINITY };
13767 }
13768 }
13769 }
13770
13771 let bits = ((result_exp as u64) << 52) | result_mant;
13772 if neg { -f64::from_bits(bits) } else { f64::from_bits(bits) }
13773}
13774
13775unsafe fn hex_val(c: u8) -> Option<u8> {
13776 if c >= b'0' && c <= b'9' { Some(c - b'0') }
13777 else if c >= b'a' && c <= b'f' { Some(c - b'a' + 10) }
13778 else if c >= b'A' && c <= b'F' { Some(c - b'A' + 10) }
13779 else { None }
13780}
13781
13782#[no_mangle]
13783pub unsafe extern "C" fn strtod(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13784 let mut end: *mut u8 = s as *mut u8;
13785 let r = parse_float(s as *const u8, &mut end, false);
13786 if !endptr.is_null() { *endptr = end as *mut c_char; }
13787 r
13788}
13789
13790#[no_mangle]
13791pub unsafe extern "C" fn strtof(s: *const c_char, endptr: *mut *mut c_char) -> f32 {
13792 let mut end: *mut u8 = s as *mut u8;
13793 let r = parse_float(s as *const u8, &mut end, true);
13794 if !endptr.is_null() { *endptr = end as *mut c_char; }
13795 r as f32
13796}
13797
13798#[no_mangle]
13799#[cfg(target_arch = "x86_64")]
13800pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f64 {
13801 strtod(s, endptr)
13802}
13803
13804#[no_mangle]
13805#[cfg(target_arch = "aarch64")]
13806pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13807 strtod(s, endptr) as f128
13808}
13809
13810#[no_mangle]
13811#[cfg(target_arch = "riscv64")]
13812pub unsafe extern "C" fn strtold(s: *const c_char, endptr: *mut *mut c_char) -> f128 {
13813 strtod(s, endptr) as f128
13814}
13815
13816#[no_mangle]
13817pub unsafe extern "C" fn atof(s: *const c_char) -> f64 {
13818 strtod(s, core::ptr::null_mut())
13819}
13820
13821#[repr(C)]
13826struct MsCookie {
13827 bufp: *mut *mut c_char,
13828 sizep: *mut usize,
13829 pos: usize,
13830 len: usize,
13831 buf: *mut u8,
13832 space: usize,
13833}
13834
13835#[repr(C)]
13836struct MfCookie {
13837 pos: usize,
13838 len: usize,
13839 size: usize,
13840 buf: *mut u8,
13841 mode: c_char,
13842}
13843
13844unsafe extern "C" fn ms_seek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13845 let c = (*f).cookie as *mut MsCookie;
13846 if whence < 0 || whence > 2 { ERRNO!() = EINVAL; return -1; }
13847 let base: i64 = match whence {
13848 0 => 0,
13849 1 => (*c).pos as i64,
13850 2 => (*c).len as i64,
13851 _ => { ERRNO!() = EINVAL; return -1; }
13852 };
13853 if off < -base || off > isize::MAX as i64 - base { ERRNO!() = EINVAL; return -1; }
13854 (*c).pos = (base + off) as usize;
13855 (*c).pos as i64
13856}
13857
13858unsafe extern "C" fn ms_write(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13859 let c = (*f).cookie as *mut MsCookie;
13860 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13861 if buffered > 0 {
13862 (*f).wpos = (*f).wbase;
13863 if ms_write(f, (*f).wbase, buffered) < buffered { return 0; }
13864 }
13865 if len == 0 { return 0; }
13866 if (*c).pos + len >= (*c).space {
13867 let new_space = 2 * (*c).space + 1 | (*c).pos + len + 1;
13868 let newbuf = realloc((*c).buf as *mut c_void, new_space) as *mut u8;
13869 if newbuf.is_null() { return 0; }
13870 *(*c).bufp = newbuf as *mut c_char;
13871 core::ptr::write_bytes(newbuf.add((*c).space), 0, new_space - (*c).space);
13872 (*c).buf = newbuf;
13873 (*c).space = new_space;
13874 }
13875 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), len);
13876 (*c).pos += len;
13877 if (*c).pos >= (*c).len { (*c).len = (*c).pos; }
13878 *(*c).sizep = (*c).pos;
13879 len
13880}
13881
13882unsafe extern "C" fn ms_close(_f: *mut FILE) -> c_int {
13883 0
13884}
13885
13886#[no_mangle]
13887pub unsafe extern "C" fn open_memstream(bufp: *mut *mut c_char, sizep: *mut usize) -> *mut FILE {
13888 if bufp.is_null() || sizep.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
13889 let f = calloc(1, core::mem::size_of::<FILE>() + UNGET + BUFSIZ) as *mut FILE;
13890 if f.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13891 let buf_area = buf_ptr(f);
13892 init_file(f, -1, b"w\0".as_ptr() as *const c_char, Some(ms_close), buf_area, BUFSIZ);
13893 (*f).flags = F_NORD | F_SVB;
13894 (*f).lbf = -1;
13895 let c = calloc(1, core::mem::size_of::<MsCookie>()) as *mut MsCookie;
13896 if c.is_null() { free(f as *mut c_void); ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13897 (*c).bufp = bufp;
13898 (*c).sizep = sizep;
13899 (*c).pos = 0;
13900 (*c).len = 0;
13901 (*c).buf = core::ptr::null_mut();
13902 (*c).space = 0;
13903 (*f).cookie = c as *mut c_void;
13904 (*f).write_fn = Some(ms_write);
13905 (*f).seek_fn = Some(ms_seek);
13906 *bufp = core::ptr::null_mut();
13907 *sizep = 0;
13908 f
13909}
13910
13911unsafe extern "C" fn mseek(f: *mut FILE, off: i64, whence: c_int) -> i64 {
13912 let c = (*f).cookie as *mut MfCookie;
13913 if whence < 0 || whence > 2 { ERRNO!() = EINVAL; return -1; }
13914 let base: i64 = match whence {
13915 0 => 0,
13916 1 => (*c).pos as i64,
13917 2 => (*c).len as i64,
13918 _ => { ERRNO!() = EINVAL; return -1; }
13919 };
13920 if off < -base || off > (*c).size as i64 - base { ERRNO!() = EINVAL; return -1; }
13921 (*c).pos = (base + off) as usize;
13922 (*c).pos as i64
13923}
13924
13925unsafe extern "C" fn mread(f: *mut FILE, buf: *mut u8, len: usize) -> usize {
13926 let c = (*f).cookie as *mut MfCookie;
13927 let mut rem = if (*c).pos <= (*c).len { (*c).len - (*c).pos } else { 0 };
13928 let mut l = len;
13929 if l > rem {
13930 l = rem;
13931 (*f).flags |= F_EOF;
13932 }
13933 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), buf, l);
13934 (*c).pos += l;
13935 rem -= l;
13936 if rem > (*f).buf_size { rem = (*f).buf_size; }
13937 (*f).rpos = (*f).buf;
13938 (*f).rend = (*f).buf.add(rem);
13939 core::ptr::copy_nonoverlapping((*c).buf.add((*c).pos), (*f).rpos, rem);
13940 (*c).pos += rem;
13941 l
13942}
13943
13944unsafe extern "C" fn mwrite(f: *mut FILE, buf: *const u8, len: usize) -> usize {
13945 let c = (*f).cookie as *mut MfCookie;
13946 let buffered = (*f).wpos as usize - (*f).wbase as usize;
13947 if buffered > 0 {
13948 (*f).wpos = (*f).wbase;
13949 if mwrite(f, (*f).wbase, buffered) < buffered { return 0; }
13950 }
13951 if len == 0 { return 0; }
13952 if (*c).mode == b'a' as c_char { (*c).pos = (*c).len; }
13953 let rem = (*c).size - (*c).pos;
13954 let mut l = len;
13955 if l > rem { l = rem; }
13956 core::ptr::copy_nonoverlapping(buf, (*c).buf.add((*c).pos), l);
13957 (*c).pos += l;
13958 if (*c).pos > (*c).len {
13959 (*c).len = (*c).pos;
13960 if (*c).len < (*c).size {
13961 *(*c).buf.add((*c).len) = 0;
13962 } else if ((*f).flags & F_NORD) != 0 && (*c).size > 0 {
13963 *(*c).buf.add((*c).size - 1) = 0;
13964 }
13965 }
13966 l
13967}
13968
13969unsafe extern "C" fn mclose(_f: *mut FILE) -> c_int {
13970 0
13971}
13972
13973#[no_mangle]
13974pub unsafe extern "C" fn fmemopen(buf: *mut c_void, size: usize, mode: *const c_char) -> *mut FILE {
13975 if mode.is_null() { ERRNO!() = EINVAL; return core::ptr::null_mut(); }
13976 let m = *mode;
13977 if m != b'r' as c_char && m != b'w' as c_char && m != b'a' as c_char {
13978 ERRNO!() = EINVAL; return core::ptr::null_mut();
13979 }
13980 let has_plus = !strchr(mode as *const u8, b'+' as c_int).is_null();
13981 let need_alloc = buf.is_null();
13982 let alloc_size = core::mem::size_of::<FILE>() + UNGET + BUFSIZ + if need_alloc { size } else { 0 };
13983 let f = calloc(1, alloc_size) as *mut FILE;
13984 if f.is_null() { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13985 let buf_area = buf_ptr(f);
13986 init_file(f, -1, mode, Some(mclose), buf_area, BUFSIZ);
13987 (*f).flags |= F_SVB;
13988 let actual_buf: *mut u8 = if need_alloc {
13989 (f as *mut u8).add(alloc_size - size)
13990 } else {
13991 buf as *mut u8
13992 };
13993 if need_alloc { core::ptr::write_bytes(actual_buf, 0, size); }
13994 let c = calloc(1, core::mem::size_of::<MfCookie>()) as *mut MfCookie;
13995 if c.is_null() { free(f as *mut c_void); ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
13996 (*c).buf = actual_buf;
13997 (*c).size = size;
13998 (*c).mode = m;
13999 (*f).cookie = c as *mut c_void;
14000 (*f).read_fn = Some(mread);
14001 (*f).write_fn = Some(mwrite);
14002 (*f).seek_fn = Some(mseek);
14003 if !has_plus { (*f).flags = if m == b'r' as c_char { F_NOWR } else { F_NORD }; }
14004 if m == b'r' as c_char {
14005 (*c).len = size;
14006 } else if m == b'a' as c_char {
14007 (*c).len = strnlen(actual_buf, size);
14008 (*c).pos = (*c).len;
14009 } else if has_plus {
14010 *actual_buf = 0;
14011 }
14012 f
14013}
14014
14015#[repr(C)]
14020struct kernel_stat64 {
14021 st_dev: u64,
14022 st_ino: u64,
14023 st_nlink: u64,
14024 st_mode: u32,
14025 st_uid: u32,
14026 st_gid: u32,
14027 __pad0: c_int,
14028 st_rdev: u64,
14029 st_size: i64,
14030 st_blksize: i64,
14031 st_blocks: i64,
14032 st_atime: i64,
14033 st_atime_nsec: i64,
14034 st_mtime: i64,
14035 st_mtime_nsec: i64,
14036 st_ctime: i64,
14037 st_ctime_nsec: i64,
14038 __unused: [i64; 3],
14039}
14040
14041#[inline]
14043unsafe fn sys_stat(path: *const u8, statbuf: *mut kernel_stat64) -> i64 {
14044 <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, AT_FDCWD as i64, path as i64, statbuf as i64, 0)
14045}
14046
14047const HSEARCH_MINSIZE: usize = 8;
14052
14053#[repr(C)]
14054#[derive(Copy, Clone)]
14055pub struct HSearchEntry {
14056 key: *mut c_char,
14057 data: *mut c_void,
14058}
14059
14060#[repr(C)]
14061struct HTab {
14062 entries: *mut HSearchEntry,
14063 mask: usize,
14064 used: usize,
14065}
14066
14067#[repr(C)]
14068pub struct HSearchData {
14069 tab: *mut HTab,
14070 __unused1: c_uint,
14071 __unused2: c_uint,
14072}
14073
14074static mut HTAB_DATA: HSearchData = HSearchData {
14076 tab: core::ptr::null_mut(),
14077 __unused1: 0,
14078 __unused2: 0,
14079};
14080
14081unsafe fn keyhash(k: *const c_char) -> usize {
14082 let mut h: usize = 0;
14083 let mut p = k;
14084 while *p != 0 {
14085 h = h.wrapping_mul(31).wrapping_add(*p as usize);
14086 p = p.add(1);
14087 }
14088 h
14089}
14090
14091unsafe fn htab_lookup(key: *const c_char, hash: usize, htab: *mut HSearchData) -> *mut HSearchEntry {
14092 let tab = (*htab).tab;
14093 let mask = (*tab).mask;
14094 let entries = (*tab).entries;
14095 let mut i = hash;
14096 let mut j: usize = 1;
14097 loop {
14098 let e = entries.add(i & mask);
14099 if (*e).key.is_null() || strcmp((*e).key as *const u8, key as *const u8) == 0 {
14100 return e;
14101 }
14102 i = i.wrapping_add(j);
14103 j += 1;
14104 }
14105}
14106
14107unsafe fn htab_resize(nel: usize, htab: *mut HSearchData) -> c_int {
14108 let tab = (*htab).tab;
14109 let old_entries = (*tab).entries;
14110 let old_size = (*tab).mask + 1;
14111
14112 let mut newsize: usize = HSEARCH_MINSIZE;
14113 while newsize < nel {
14114 let Some(next) = newsize.checked_mul(2) else {
14115 ERRNO!() = ENOMEM;
14116 return 0;
14117 };
14118 newsize = next;
14119 }
14120
14121 let new_entries = calloc(newsize, core::mem::size_of::<HSearchEntry>()) as *mut HSearchEntry;
14122 if new_entries.is_null() {
14123 ERRNO!() = ENOMEM;
14124 return 0;
14125 }
14126 (*tab).entries = new_entries;
14127 (*tab).mask = newsize - 1;
14128
14129 if !old_entries.is_null() {
14130 for idx in 0..old_size {
14131 let old_e = old_entries.add(idx);
14132 if !(*old_e).key.is_null() {
14133 let h = keyhash((*old_e).key);
14134 let mut i = h;
14135 let mut j: usize = 1;
14136 loop {
14137 let e = new_entries.add(i & (*tab).mask);
14138 if (*e).key.is_null() {
14139 *e = *old_e;
14140 break;
14141 }
14142 i = i.wrapping_add(j);
14143 j += 1;
14144 }
14145 }
14146 }
14147 free(old_entries as *mut c_void);
14148 }
14149 1
14150}
14151
14152unsafe fn hcreate_r_impl(nel: usize, htab: *mut HSearchData) -> c_int {
14153 if nel == 0 || nel > (1usize << 30) {
14154 ERRNO!() = ENOMEM;
14155 return 0;
14156 }
14157 (*htab).tab = calloc(1, core::mem::size_of::<HTab>()) as *mut HTab;
14158 if (*htab).tab.is_null() {
14159 ERRNO!() = ENOMEM;
14160 return 0;
14161 }
14162 if htab_resize(nel, htab) == 0 {
14163 free((*htab).tab as *mut c_void);
14164 (*htab).tab = core::ptr::null_mut();
14165 return 0;
14166 }
14167 1
14168}
14169
14170unsafe fn hdestroy_r_impl(htab: *mut HSearchData) {
14171 if !(*htab).tab.is_null() {
14172 if !(*(*htab).tab).entries.is_null() {
14173 free((*(*htab).tab).entries as *mut c_void);
14174 }
14175 free((*htab).tab as *mut c_void);
14176 (*htab).tab = core::ptr::null_mut();
14177 }
14178}
14179
14180unsafe fn hsearch_r_impl(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
14181 let hash = keyhash(item.key);
14182 let e = htab_lookup(item.key, hash, htab);
14183
14184 if !(*e).key.is_null() {
14185 *retval = e;
14186 return 1;
14187 }
14188 if action == 0 { *retval = core::ptr::null_mut();
14190 return 0;
14191 }
14192 let item_key = item.key;
14194 *e = item;
14195 (*(*htab).tab).used += 1;
14196 if (*(*htab).tab).used > (*(*htab).tab).mask - (*(*htab).tab).mask / 4 {
14197 if htab_resize(2 * (*(*htab).tab).used, htab) == 0 {
14198 (*(*htab).tab).used -= 1;
14199 (*e).key = core::ptr::null_mut();
14200 *retval = core::ptr::null_mut();
14201 return 0;
14202 }
14203 let e2 = htab_lookup(item_key, hash, htab);
14204 *retval = e2;
14205 return 1;
14206 }
14207 *retval = e;
14208 1
14209}
14210
14211#[no_mangle]
14212pub unsafe extern "C" fn hcreate(nel: usize) -> c_int {
14213 hcreate_r_impl(nel, core::ptr::addr_of_mut!(HTAB_DATA))
14214}
14215
14216#[no_mangle]
14217pub unsafe extern "C" fn hdestroy() {
14218 hdestroy_r_impl(core::ptr::addr_of_mut!(HTAB_DATA));
14219}
14220
14221#[no_mangle]
14222pub unsafe extern "C" fn hsearch(item: HSearchEntry, action: c_int) -> *mut HSearchEntry {
14223 let mut e: *mut HSearchEntry = core::ptr::null_mut();
14224 hsearch_r_impl(item, action, &mut e, core::ptr::addr_of_mut!(HTAB_DATA));
14225 e
14226}
14227
14228#[no_mangle]
14229pub unsafe extern "C" fn hcreate_r(nel: usize, htab: *mut HSearchData) -> c_int {
14230 hcreate_r_impl(nel, htab)
14231}
14232
14233#[no_mangle]
14234pub unsafe extern "C" fn hdestroy_r(htab: *mut HSearchData) {
14235 hdestroy_r_impl(htab);
14236}
14237
14238#[no_mangle]
14239pub unsafe extern "C" fn hsearch_r(item: HSearchEntry, action: c_int, retval: *mut *mut HSearchEntry, htab: *mut HSearchData) -> c_int {
14240 hsearch_r_impl(item, action, retval, htab)
14241}
14242
14243#[repr(C)]
14248struct QueNode {
14249 next: *mut QueNode,
14250 prev: *mut QueNode,
14251}
14252
14253#[no_mangle]
14254pub unsafe extern "C" fn insque(element: *mut c_void, pred: *mut c_void) {
14255 let e = element as *mut QueNode;
14256 let p = pred as *mut QueNode;
14257 if p.is_null() {
14258 (*e).next = core::ptr::null_mut();
14259 (*e).prev = core::ptr::null_mut();
14260 return;
14261 }
14262 (*e).next = (*p).next;
14263 (*e).prev = p;
14264 (*p).next = e;
14265 if !(*e).next.is_null() {
14266 (*(*e).next).prev = e;
14267 }
14268}
14269
14270#[no_mangle]
14271pub unsafe extern "C" fn remque(element: *mut c_void) {
14272 let e = element as *mut QueNode;
14273 if !(*e).next.is_null() {
14274 (*(*e).next).prev = (*e).prev;
14275 }
14276 if !(*e).prev.is_null() {
14277 (*(*e).prev).next = (*e).next;
14278 }
14279}
14280
14281#[no_mangle]
14286pub unsafe extern "C" fn lsearch(
14287 key: *const c_void,
14288 base: *mut c_void,
14289 nelp: *mut usize,
14290 width: usize,
14291 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
14292) -> *mut c_void {
14293 let n = *nelp;
14294 let p = base as *mut u8;
14295 for i in 0..n {
14296 let elem = p.add(i * width);
14297 if compar.unwrap()(key, elem as *const c_void) == 0 {
14298 return elem as *mut c_void;
14299 }
14300 }
14301 let dest = p.add(n * width);
14302 memcpy(dest as *mut c_void, key as *const c_void, width);
14303 *nelp = n + 1;
14304 dest as *mut c_void
14305}
14306
14307#[no_mangle]
14308pub unsafe extern "C" fn lfind(
14309 key: *const c_void,
14310 base: *const c_void,
14311 nelp: *mut usize,
14312 width: usize,
14313 compar: Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>,
14314) -> *mut c_void {
14315 let n = *nelp;
14316 let p = base as *const u8;
14317 for i in 0..n {
14318 let elem = p.add(i * width);
14319 if compar.unwrap()(key, elem as *const c_void) == 0 {
14320 return elem as *mut c_void;
14321 }
14322 }
14323 core::ptr::null_mut()
14324}
14325
14326#[repr(C)]
14332pub struct TreeNode {
14333 key: *const c_void,
14334 left: *mut TreeNode,
14335 right: *mut TreeNode,
14336}
14337
14338type ComparFn = Option<unsafe extern "C" fn(*const c_void, *const c_void) -> c_int>;
14339
14340unsafe fn bst_new(key: *const c_void) -> *mut TreeNode {
14341 let n = calloc(1, core::mem::size_of::<TreeNode>()) as *mut TreeNode;
14342 if !n.is_null() {
14343 (*n).key = key;
14344 (*n).left = core::ptr::null_mut();
14345 (*n).right = core::ptr::null_mut();
14346 }
14347 n
14348}
14349
14350#[no_mangle]
14351pub unsafe extern "C" fn tsearch(
14352 key: *const c_void,
14353 rootp: *mut *mut TreeNode,
14354 compar: ComparFn,
14355) -> *mut c_void {
14356 if rootp.is_null() {
14357 return core::ptr::null_mut();
14358 }
14359 let mut pp = rootp;
14360 loop {
14361 let n = *pp;
14362 if n.is_null() {
14363 let r = bst_new(key);
14364 if r.is_null() {
14365 return core::ptr::null_mut();
14366 }
14367 *pp = r;
14368 return r as *mut c_void;
14369 }
14370 let c = compar.unwrap()(key, (*n).key);
14371 if c == 0 {
14372 return n as *mut c_void;
14373 }
14374 if c < 0 {
14375 pp = &mut (*n).left;
14376 } else {
14377 pp = &mut (*n).right;
14378 }
14379 }
14380}
14381
14382#[no_mangle]
14383pub unsafe extern "C" fn tfind(
14384 key: *const c_void,
14385 rootp: *const *mut TreeNode,
14386 compar: ComparFn,
14387) -> *mut c_void {
14388 if rootp.is_null() {
14389 return core::ptr::null_mut();
14390 }
14391 let mut n = *rootp;
14392 loop {
14393 if n.is_null() {
14394 return core::ptr::null_mut();
14395 }
14396 let c = compar.unwrap()(key, (*n).key);
14397 if c == 0 {
14398 return n as *mut c_void;
14399 }
14400 if c < 0 {
14401 n = (*n).left;
14402 } else {
14403 n = (*n).right;
14404 }
14405 }
14406}
14407
14408#[no_mangle]
14409pub unsafe extern "C" fn tdelete(
14410 key: *const c_void,
14411 rootp: *mut *mut TreeNode,
14412 compar: ComparFn,
14413) -> *mut c_void {
14414 if rootp.is_null() {
14415 return core::ptr::null_mut();
14416 }
14417 let mut pp = rootp;
14418 loop {
14419 let n = *pp;
14420 if n.is_null() {
14421 return core::ptr::null_mut();
14422 }
14423 let c = compar.unwrap()(key, (*n).key);
14424 if c == 0 {
14425 break;
14426 }
14427 if c < 0 {
14428 pp = &mut (*n).left;
14429 } else {
14430 pp = &mut (*n).right;
14431 }
14432 }
14433 let n = *pp;
14434 let parent = *rootp;
14436 if !(*n).left.is_null() {
14437 let mut q = &mut (*n).left;
14439 while !(*(*q)).right.is_null() {
14440 q = &mut (*(*q)).right;
14441 }
14442 let pred = *q;
14443 (*n).key = (*pred).key;
14445 *q = (*pred).left;
14447 free(pred as *mut c_void);
14448 } else {
14449 *pp = (*n).right;
14451 free(n as *mut c_void);
14452 }
14453 parent as *mut c_void
14454}
14455
14456#[no_mangle]
14457pub unsafe extern "C" fn twalk(
14458 root: *const TreeNode,
14459 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
14460) {
14461 unsafe fn walk(
14462 node: *const TreeNode,
14463 action: Option<unsafe extern "C" fn(*const c_void, c_int, c_int)>,
14464 depth: c_int,
14465 ) {
14466 if node.is_null() {
14467 return;
14468 }
14469 let is_leaf = (*node).left.is_null() && (*node).right.is_null();
14470 if is_leaf {
14471 action.unwrap()(node as *const c_void, 3, depth); } else {
14473 action.unwrap()(node as *const c_void, 0, depth); walk((*node).left, action, depth + 1);
14475 action.unwrap()(node as *const c_void, 1, depth); walk((*node).right, action, depth + 1);
14477 action.unwrap()(node as *const c_void, 2, depth); }
14479 }
14480 walk(root, action, 0);
14481}
14482
14483#[no_mangle]
14484pub unsafe extern "C" fn tdestroy(root: *mut TreeNode, freekey: Option<unsafe extern "C" fn(*mut c_void)>) {
14485 if root.is_null() {
14486 return;
14487 }
14488 tdestroy((*root).left, freekey);
14489 tdestroy((*root).right, freekey);
14490 if let Some(f) = freekey {
14491 f((*root).key as *mut c_void);
14492 }
14493 free(root as *mut c_void);
14494}
14495
14496const FNM_PATHNAME: c_int = 0x1;
14501const FNM_NOESCAPE: c_int = 0x2;
14502const FNM_PERIOD: c_int = 0x4;
14503const FNM_LEADING_DIR: c_int = 0x8;
14504const FNM_CASEFOLD: c_int = 0x10;
14505const FNM_NOMATCH: c_int = 1;
14506
14507const FNM_END: c_int = 0;
14508const FNM_STAR: c_int = -5;
14509const FNM_QUESTION: c_int = -4;
14510const FNM_BRACKET: c_int = -3;
14511const FNM_UNMATCHABLE: c_int = -2;
14512
14513fn ascii_tolower(c: u8) -> u8 {
14514 if c >= b'A' && c <= b'Z' { c + 32 } else { c }
14515}
14516
14517fn ascii_toupper(c: u8) -> u8 {
14518 if c >= b'a' && c <= b'z' { c - 32 } else { c }
14519}
14520
14521fn ascii_casefold(k: u8) -> u8 {
14522 let upper = ascii_toupper(k);
14523 if upper != k { upper } else { ascii_tolower(k) }
14524}
14525
14526unsafe fn pat_next(pat: *const u8, m: usize, flags: c_int) -> (c_int, usize) {
14529 if m == 0 || *pat == 0 {
14530 return (FNM_END, 0);
14531 }
14532 let mut p = pat;
14533 let mut step = 1usize;
14534 let mut esc = false;
14535 if *p == b'\\' && !(flags & FNM_NOESCAPE != 0) && *p.add(1) != 0 {
14536 p = p.add(1);
14537 step = 2;
14538 esc = true;
14539 }
14540 if *p == b'[' && !esc {
14541 let mut k = 1usize;
14543 if k < m && (*pat.add(k) == b'^' || *pat.add(k) == b'!') { k += 1; }
14544 if k < m && *pat.add(k) == b']' { k += 1; }
14545 while k < m && *pat.add(k) != 0 && *pat.add(k) != b']' {
14546 if k + 1 < m && *pat.add(k) == b'[' &&
14547 (*pat.add(k+1) == b':' || *pat.add(k+1) == b'.' || *pat.add(k+1) == b'=') {
14548 let z = *pat.add(k+1);
14549 k += 2;
14550 if k < m { k += 1; }
14551 while k < m && *pat.add(k) != 0 && (*pat.add(k-1) != z || *pat.add(k) != b']') { k += 1; }
14552 if k == m || *pat.add(k) == 0 { break; }
14553 }
14554 k += 1;
14555 }
14556 if k == m || *pat.add(k) == 0 {
14557 return (b'[' as c_int, 1);
14559 }
14560 return (FNM_BRACKET, k + 1);
14561 }
14562 if *p == b'*' && !esc {
14563 return (FNM_STAR, 1);
14564 }
14565 if *p == b'?' && !esc {
14566 return (FNM_QUESTION, 1);
14567 }
14568 (*p as c_int, step)
14569}
14570
14571unsafe fn match_class(name: &[u8], k: u8, kfold: u8) -> bool {
14572 let eq = |c: u8| k == c || kfold == c;
14573 let in_range = |lo: u8, hi: u8| (k >= lo && k <= hi) || (kfold >= lo && kfold <= hi);
14574 match name {
14575 b"alnum" => in_range(b'0', b'9') || in_range(b'A', b'Z') || in_range(b'a', b'z'),
14576 b"alpha" => in_range(b'A', b'Z') || in_range(b'a', b'z'),
14577 b"blank" => eq(b' ') || eq(b'\t'),
14578 b"cntrl" => k < 0x20 || k == 0x7f,
14579 b"digit" => in_range(b'0', b'9'),
14580 b"graph" => k >= 0x21 && k <= 0x7e,
14581 b"lower" => in_range(b'a', b'z'),
14582 b"print" => k >= 0x20 && k <= 0x7e,
14583 b"punct" =>
14584 (k >= 0x21 && k <= 0x2f) ||
14585 (k >= 0x3a && k <= 0x40) ||
14586 (k >= 0x5b && k <= 0x60) ||
14587 (k >= 0x7b && k <= 0x7e),
14588 b"space" => eq(b' ') || eq(b'\t') || eq(b'\n') || eq(b'\r') || eq(0x0c) || eq(0x0b),
14589 b"upper" => in_range(b'A', b'Z'),
14590 b"xdigit" => in_range(b'0', b'9') || in_range(b'A', b'F') || in_range(b'a', b'f'),
14591 _ => false,
14592 }
14593}
14594
14595unsafe fn match_bracket(mut p: *const u8, k: u8, kfold: u8) -> bool {
14597 let mut inv = false;
14598 p = p.add(1); if *p == b'^' || *p == b'!' {
14600 inv = true;
14601 p = p.add(1);
14602 }
14603 if *p == b']' {
14605 if k == b']' { return !inv; }
14606 p = p.add(1);
14607 } else if *p == b'-' {
14608 if k == b'-' { return !inv; }
14609 p = p.add(1);
14610 }
14611 while *p != b']' && *p != 0 {
14612 if *p == b'-' && *p.add(1) != b']' && *p.add(1) != 0 {
14613 let lo = *p.sub(1);
14615 let hi = *p.add(1);
14616 if lo <= hi && (k >= lo && k <= hi || kfold >= lo && kfold <= hi) {
14617 return !inv;
14618 }
14619 p = p.add(2);
14620 } else if *p == b'[' && (*p.add(1) == b':' || *p.add(1) == b'.' || *p.add(1) == b'=') {
14621 let z = *p.add(1);
14622 let start = p.add(2);
14623 let mut q = start;
14624 while *q != 0 && (*q != z || *q.add(1) != b']') { q = q.add(1); }
14625 if *q != 0 {
14626 let len = (q as usize) - (start as usize);
14627 if len > 0 {
14628 let inner = core::slice::from_raw_parts(start, len);
14629 let matched =
14630 if z == b':' { match_class(inner, k, kfold) }
14631 else { len == 1 && (inner[0] == k || inner[0] == kfold) };
14632 if matched { return !inv; }
14633 }
14634 p = q.add(2);
14635 continue;
14636 }
14637 } else {
14638 if *p == k || *p == kfold {
14639 return !inv;
14640 }
14641 p = p.add(1);
14642 }
14643 }
14644 inv
14645}
14646
14647unsafe fn fnmatch_internal(pat: *const u8, str: *const u8, flags: c_int) -> c_int {
14649 if flags & FNM_PERIOD != 0 && *str == b'.' && *pat != b'.' {
14651 return FNM_NOMATCH;
14652 }
14653
14654 let mut p = pat;
14655 let mut s = str;
14656
14657 loop {
14659 let (tok, step) = pat_next(p, usize::MAX, flags);
14660 match tok {
14661 FNM_END => {
14662 return if *s == 0 { 0 } else { FNM_NOMATCH };
14663 }
14664 FNM_STAR => {
14665 p = p.add(1);
14666 break;
14667 }
14668 FNM_QUESTION => {
14669 if *s == 0 { return FNM_NOMATCH; }
14670 s = s.add(1);
14671 p = p.add(step);
14672 }
14673 FNM_BRACKET => {
14674 if *s == 0 { return FNM_NOMATCH; }
14675 let k = *s;
14676 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14677 if !match_bracket(p, k, kfold) { return FNM_NOMATCH; }
14678 p = p.add(step);
14679 s = s.add(1);
14680 }
14681 c => {
14682 if *s == 0 { return FNM_NOMATCH; }
14683 let k = *s;
14684 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14685 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14686 p = p.add(step);
14687 s = s.add(1);
14688 }
14689 }
14690 }
14691
14692 let mut ptail = p;
14695 let mut tailcnt: usize = 0;
14696 let mut pp = p;
14697 loop {
14698 let (tok, step) = pat_next(pp, usize::MAX, flags);
14699 if tok == FNM_END { break; }
14700 if tok == FNM_STAR {
14701 tailcnt = 0;
14702 ptail = pp.add(1);
14703 } else {
14704 tailcnt += 1;
14705 }
14706 pp = pp.add(step);
14707 }
14708
14709 let slen = strlen(s as *const c_char);
14711 if slen < tailcnt { return FNM_NOMATCH; }
14712
14713 let stail = s.add(slen - tailcnt);
14715 let mut tp = ptail;
14716 let mut ts = stail;
14717 loop {
14718 let (tok, step) = pat_next(tp, usize::MAX, flags);
14719 tp = tp.add(step);
14720 if tok == FNM_END {
14721 break;
14722 }
14723 let k = *ts;
14724 if k == 0 { return FNM_NOMATCH; }
14725 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14726 match tok {
14727 FNM_QUESTION => { ts = ts.add(1); }
14728 FNM_BRACKET => {
14729 if !match_bracket(tp.sub(step), k, kfold) { return FNM_NOMATCH; }
14730 ts = ts.add(1);
14731 }
14732 c => {
14733 if k as c_int != c && kfold as c_int != c { return FNM_NOMATCH; }
14734 ts = ts.add(1);
14735 }
14736 }
14737 }
14738
14739 let endstr = stail;
14740 let endpat = ptail;
14741
14742 let mut cp = p;
14743 let mut cs = s;
14744 while cp < endpat {
14745 let (tok, step) = pat_next(cp, usize::MAX, flags);
14746 if tok == FNM_STAR {
14747 cp = cp.add(step);
14748 cs = s;
14749 continue;
14750 }
14751 let comp_start = cp;
14752 let mut ok = false;
14753 let mut try_s = cs;
14754 while try_s < endstr {
14755 let mut tmp_p = comp_start;
14756 let mut tmp_s = try_s;
14757 let mut matched = true;
14758 loop {
14759 let (t, st) = pat_next(tmp_p, usize::MAX, flags);
14760 if t == FNM_STAR || t == FNM_END {
14761 cp = tmp_p;
14762 cs = tmp_s;
14763 ok = true;
14764 break;
14765 }
14766 if *tmp_s == 0 {
14767 matched = false;
14768 break;
14769 }
14770 let k = *tmp_s;
14771 let kfold = if flags & FNM_CASEFOLD != 0 { ascii_casefold(k) } else { k };
14772 match t {
14773 FNM_QUESTION => {
14774 tmp_s = tmp_s.add(1);
14775 }
14776 FNM_BRACKET => {
14777 if !match_bracket(tmp_p, k, kfold) {
14778 matched = false;
14779 break;
14780 }
14781 tmp_s = tmp_s.add(1);
14782 }
14783 c => {
14784 if k as c_int != c && kfold as c_int != c {
14785 matched = false;
14786 break;
14787 }
14788 tmp_s = tmp_s.add(1);
14789 }
14790 }
14791 tmp_p = tmp_p.add(st);
14792 }
14793 if ok { break; }
14794 if !matched {
14795 try_s = try_s.add(1);
14796 }
14797 }
14798 if !ok {
14799 return FNM_NOMATCH;
14800 }
14801 }
14802 0
14803}
14804
14805#[no_mangle]
14806pub unsafe extern "C" fn fnmatch(pat: *const c_char, str: *const c_char, flags: c_int) -> c_int {
14807 let pat = pat as *const u8;
14808 let str = str as *const u8;
14809
14810 if flags & FNM_PATHNAME != 0 {
14811 let mut s = str;
14813 let mut p = pat;
14814 loop {
14815 let mut send = s;
14817 while *send != 0 && *send != b'/' { send = send.add(1); }
14818 let mut pend = p;
14820 loop {
14821 let (tok, step) = pat_next(pend, usize::MAX, flags);
14822 if tok == FNM_END || (tok >= 0 && tok as u8 == b'/') {
14823 break;
14824 }
14825 pend = pend.add(step);
14826 }
14827 let (ptok, pstep) = pat_next(pend, usize::MAX, flags);
14828 let pat_is_slash = ptok >= 0 && ptok as u8 == b'/';
14829 let str_is_slash = *send == b'/';
14830 if pat_is_slash != str_is_slash && (*send != 0 || !(flags & FNM_LEADING_DIR != 0)) {
14831 return FNM_NOMATCH;
14832 }
14833 let plen = (pend as usize) - (p as usize);
14836 let slen = (send as usize) - (s as usize);
14837 if plen > 1024 || slen > 1024 { return FNM_NOMATCH; }
14840 let mut pbuf = [0u8; 1025];
14841 let mut sbuf = [0u8; 1025];
14842 core::ptr::copy_nonoverlapping(p, pbuf.as_mut_ptr(), plen);
14843 pbuf[plen] = 0;
14844 core::ptr::copy_nonoverlapping(s, sbuf.as_mut_ptr(), slen);
14845 sbuf[slen] = 0;
14846 if fnmatch_internal(pbuf.as_ptr(), sbuf.as_ptr(), flags & !FNM_LEADING_DIR) != 0 {
14847 return FNM_NOMATCH;
14848 }
14849 if !pat_is_slash {
14850 return 0;
14851 }
14852 s = send.add(1);
14853 p = pend.add(pstep);
14854 }
14855 }
14856
14857 if flags & FNM_LEADING_DIR != 0 {
14858 let mut s = str;
14860 while *s != 0 {
14861 if *s == b'/' {
14862 let len = (s as usize) - (str as usize);
14865 if len < 4096 {
14867 let mut buf = [0u8; 4096];
14868 core::ptr::copy_nonoverlapping(str, buf.as_mut_ptr(), len);
14869 buf[len] = 0;
14870 if fnmatch_internal(pat, buf.as_ptr(), flags) == 0 {
14871 return 0;
14872 }
14873 }
14874 }
14875 s = s.add(1);
14876 }
14877 }
14878
14879 fnmatch_internal(pat, str, flags)
14880}
14881
14882#[no_mangle]
14887pub unsafe extern "C" fn setmntent(name: *const c_char, mode: *const c_char) -> *mut FILE {
14888 fopen(name, mode)
14889}
14890
14891#[no_mangle]
14892pub unsafe extern "C" fn endmntent(f: *mut FILE) -> c_int {
14893 if !f.is_null() {
14894 fclose(f);
14895 }
14896 1
14897}
14898
14899static mut MNTENT_MNT: MntEnt = MntEnt {
14901 mnt_fsname: core::ptr::null_mut(),
14902 mnt_dir: core::ptr::null_mut(),
14903 mnt_type: core::ptr::null_mut(),
14904 mnt_opts: core::ptr::null_mut(),
14905 mnt_freq: 0,
14906 mnt_passno: 0,
14907};
14908
14909#[repr(C)]
14910pub struct MntEnt {
14911 mnt_fsname: *mut c_char,
14912 mnt_dir: *mut c_char,
14913 mnt_type: *mut c_char,
14914 mnt_opts: *mut c_char,
14915 mnt_freq: c_int,
14916 mnt_passno: c_int,
14917}
14918
14919unsafe fn unescape_ent(beg: *mut c_char) -> *mut c_char {
14920 let mut dest = beg;
14921 let mut src = beg;
14922 while *src != 0 {
14923 if *src != b'\\' as c_char {
14924 *dest = *src;
14925 dest = dest.add(1);
14926 src = src.add(1);
14927 continue;
14928 }
14929 if *src.add(1) == b'\\' as c_char {
14931 src = src.add(1);
14932 *dest = *src;
14933 dest = dest.add(1);
14934 src = src.add(1);
14935 continue;
14936 }
14937 let mut val: u8 = 0;
14939 let mut cnt = 0;
14940 let mut sp = src.add(1);
14941 while cnt < 3 && *sp >= b'0' as c_char && *sp <= b'7' as c_char {
14942 val = val * 8 + (*sp as u8 - b'0');
14943 sp = sp.add(1);
14944 cnt += 1;
14945 }
14946 if cnt > 0 {
14947 *dest = val as c_char;
14948 dest = dest.add(1);
14949 src = sp;
14950 } else {
14951 *dest = *src;
14952 dest = dest.add(1);
14953 src = src.add(1);
14954 }
14955 }
14956 *dest = 0;
14957 beg
14958}
14959
14960unsafe fn parse_mntent_line(
14961 linebuf: *mut c_char,
14962 mnt: *mut MntEnt,
14963) -> *mut MntEnt {
14964 let _len = strlen(linebuf as *const c_char);
14965 let mut p = linebuf;
14968 while *p == b' ' as c_char || *p == b'\t' as c_char || *p == b'\n' as c_char || *p == b'\r' as c_char {
14970 p = p.add(1);
14971 }
14972 if *p == 0 || *p == b'#' as c_char {
14973 return core::ptr::null_mut();
14974 }
14975
14976 (*mnt).mnt_fsname = p;
14978 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14979 p = p.add(1);
14980 }
14981 if *p == 0 { return core::ptr::null_mut(); }
14982 *p = 0;
14983 p = p.add(1);
14984 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14985
14986 (*mnt).mnt_dir = p;
14988 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14989 p = p.add(1);
14990 }
14991 if *p == 0 { return core::ptr::null_mut(); }
14992 *p = 0;
14993 p = p.add(1);
14994 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
14995
14996 (*mnt).mnt_type = p;
14998 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
14999 p = p.add(1);
15000 }
15001 if *p == 0 { return core::ptr::null_mut(); }
15002 *p = 0;
15003 p = p.add(1);
15004 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
15005
15006 (*mnt).mnt_opts = p;
15008 while *p != 0 && *p != b' ' as c_char && *p != b'\t' as c_char && *p != b'\n' as c_char {
15009 p = p.add(1);
15010 }
15011 if *p != 0 {
15012 *p = 0;
15013 p = p.add(1);
15014 }
15015 if *(*mnt).mnt_opts == 0 {
15016 (*mnt).mnt_opts = b"defaults\0".as_ptr() as *mut c_char;
15017 }
15018
15019 (*mnt).mnt_freq = 0;
15021 (*mnt).mnt_passno = 0;
15022 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
15024 if *p >= b'0' as c_char && *p <= b'9' as c_char {
15025 (*mnt).mnt_freq = (*p - b'0' as c_char) as c_int;
15026 p = p.add(1);
15027 while *p >= b'0' as c_char && *p <= b'9' as c_char {
15028 (*mnt).mnt_freq = (*mnt).mnt_freq * 10 + (*p - b'0' as c_char) as c_int;
15029 p = p.add(1);
15030 }
15031 }
15032 while *p == b' ' as c_char || *p == b'\t' as c_char { p = p.add(1); }
15033 if *p >= b'0' as c_char && *p <= b'9' as c_char {
15034 (*mnt).mnt_passno = (*p - b'0' as c_char) as c_int;
15035 p = p.add(1);
15036 while *p >= b'0' as c_char && *p <= b'9' as c_char {
15037 (*mnt).mnt_passno = (*mnt).mnt_passno * 10 + (*p - b'0' as c_char) as c_int;
15038 p = p.add(1);
15039 }
15040 }
15041
15042 unescape_ent((*mnt).mnt_fsname);
15044 unescape_ent((*mnt).mnt_dir);
15045 unescape_ent((*mnt).mnt_type);
15046 unescape_ent((*mnt).mnt_opts);
15047
15048 mnt
15049}
15050
15051static SENTINEL_PTR: usize = 1;
15054
15055unsafe fn mntent_fgetc(f: *mut FILE) -> c_int {
15057 fgetc(f)
15058}
15059
15060unsafe fn mntent_fgets(buf: *mut c_char, n: usize, f: *mut FILE) -> *mut c_char {
15061 if n == 0 { return core::ptr::null_mut(); }
15062 let max = n - 1;
15063 let mut i = 0usize;
15064 while i < max {
15065 let c = mntent_fgetc(f);
15066 if c == -1 { if i == 0 { return core::ptr::null_mut(); } break; }
15067 *buf.add(i) = c as c_char;
15068 i += 1;
15069 if c == b'\n' as c_int { break; }
15070 }
15071 *buf.add(i) = 0;
15072 buf
15073}
15074
15075#[no_mangle]
15076pub unsafe extern "C" fn getmntent_r(
15077 f: *mut FILE,
15078 mnt: *mut MntEnt,
15079 mut linebuf: *mut c_char,
15080 _buflen: c_int,
15081) -> *mut MntEnt {
15082 let use_internal = linebuf as usize == SENTINEL_PTR;
15083
15084 (*mnt).mnt_freq = 0;
15085 (*mnt).mnt_passno = 0;
15086
15087 static mut INTERNAL_BUF: [c_char; 4096] = [0; 4096];
15089
15090 loop {
15091 if use_internal {
15092 linebuf = core::ptr::addr_of_mut!(INTERNAL_BUF).cast::<c_char>();
15093 }
15094 let res = mntent_fgets(linebuf, 4096, f);
15095 if res.is_null() {
15096 return core::ptr::null_mut();
15097 }
15098 let mut has_newline = false;
15099 let mut p = linebuf;
15100 while *p != 0 { if *p == b'\n' as c_char { has_newline = true; break; } p = p.add(1); }
15101 if !has_newline {
15102 ERRNO!() = 34;
15103 return core::ptr::null_mut();
15104 }
15105 let result = parse_mntent_line(linebuf, mnt);
15106 if !result.is_null() {
15107 return result;
15108 }
15109 }
15110}
15111
15112#[no_mangle]
15113pub unsafe extern "C" fn getmntent(f: *mut FILE) -> *mut MntEnt {
15114 getmntent_r(f, core::ptr::addr_of_mut!(MNTENT_MNT), SENTINEL_PTR as *mut c_char, 0)
15115}
15116
15117#[no_mangle]
15118pub unsafe extern "C" fn addmntent(f: *mut FILE, mnt: *const MntEnt) -> c_int {
15119 fseek(f, 0, 2); let written = fprintf(
15121 f,
15122 b"%s\t%s\t%s\t%s\t%d\t%d\n\0".as_ptr() as *const c_char,
15123 (*mnt).mnt_fsname,
15124 (*mnt).mnt_dir,
15125 (*mnt).mnt_type,
15126 (*mnt).mnt_opts,
15127 (*mnt).mnt_freq,
15128 (*mnt).mnt_passno,
15129 );
15130 if written < 0 { 1 } else { 0 }
15131}
15132
15133#[no_mangle]
15134pub unsafe extern "C" fn hasmntopt(mnt: *const MntEnt, opt: *const c_char) -> *mut c_char {
15135 let l = strlen(opt as *const c_char);
15136 let mut p = (*mnt).mnt_opts;
15137 loop {
15138 if strncmp(p as *const u8, opt as *const u8, l) == 0 {
15139 let after = *p.add(l);
15140 if after == 0 || after == b',' as c_char || after == b'=' as c_char {
15141 return p;
15142 }
15143 }
15144 let comma = strchr(p as *const u8, b',' as c_int);
15145 if comma.is_null() {
15146 return core::ptr::null_mut();
15147 }
15148 p = comma.add(1) as *mut c_char;
15149 }
15150}
15151
15152const EEXIST: c_int = 17;
15160const ENAMETOOLONG: c_int = 36;
15161const EMFILE: c_int = 24;
15162const EIDRM: c_int = 43;
15163
15164#[inline]
15165unsafe fn sys_msgget(key: c_int, msgflg: c_int) -> i64 {
15166 <Arch as Syscalls>::syscall2(SYS_MSGGET, key as i64, msgflg as i64)
15167}
15168
15169#[inline]
15170unsafe fn sys_msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> i64 {
15171 <Arch as Syscalls>::syscall4(SYS_MSGSND, msqid as i64, msgp as i64, msgsz as i64, msgflg as i64)
15172}
15173
15174#[inline]
15175unsafe fn sys_msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> i64 {
15176 <Arch as Syscalls>::syscall5(SYS_MSGRCV, msqid as i64, msgp as i64, msgsz as i64, msgtyp as i64, msgflg as i64)
15177}
15178
15179#[inline]
15180unsafe fn sys_msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
15181 <Arch as Syscalls>::syscall3(SYS_MSGCTL, msqid as i64, cmd as i64, buf as i64)
15182}
15183
15184#[inline]
15185unsafe fn sys_semget(key: c_int, nsems: c_int, semflg: c_int) -> i64 {
15186 <Arch as Syscalls>::syscall3(SYS_SEMGET, key as i64, nsems as i64, semflg as i64)
15187}
15188
15189#[inline]
15190unsafe fn sys_semop(semid: c_int, sops: *const c_void, nsops: usize) -> i64 {
15191 <Arch as Syscalls>::syscall3(SYS_SEMOP, semid as i64, sops as i64, nsops as i64)
15192}
15193
15194#[inline]
15195unsafe fn sys_semctl(semid: c_int, semnum: c_int, cmd: c_int, arg: *mut c_void) -> i64 {
15196 <Arch as Syscalls>::syscall4(SYS_SEMCTL, semid as i64, semnum as i64, cmd as i64, arg as i64)
15197}
15198
15199#[inline]
15200unsafe fn sys_shmget(key: c_int, size: usize, shmflg: c_int) -> i64 {
15201 <Arch as Syscalls>::syscall3(SYS_SHMGET, key as i64, size as i64, shmflg as i64)
15202}
15203
15204#[inline]
15205unsafe fn sys_shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> i64 {
15206 <Arch as Syscalls>::syscall3(SYS_SHMAT, shmid as i64, shmaddr as i64, shmflg as i64)
15207}
15208
15209#[inline]
15210unsafe fn sys_shmdt(shmaddr: *const c_void) -> i64 {
15211 <Arch as Syscalls>::syscall1(SYS_SHMDT, shmaddr as i64)
15212}
15213
15214#[inline]
15215unsafe fn sys_shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> i64 {
15216 <Arch as Syscalls>::syscall3(SYS_SHMCTL, shmid as i64, cmd as i64, buf as i64)
15217}
15218
15219#[no_mangle]
15221pub unsafe extern "C" fn ftok(path: *const c_char, id: c_int) -> c_int {
15222 let mut st: kernel_stat64 = core::mem::zeroed();
15223 let r = sys_stat(path as *const u8, &mut st);
15224 if r < 0 {
15225 ERRNO!() = (-r) as c_int;
15226 return -1;
15227 }
15228 ((st.st_ino & 0xffff) | ((st.st_dev & 0xff) << 16) | (((id as u32 & 0xff) << 24)) as u64) as c_int
15229}
15230
15231#[no_mangle]
15233pub unsafe extern "C" fn msgget(key: c_int, msgflg: c_int) -> c_int {
15234 let r = sys_msgget(key, msgflg);
15235 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15236}
15237
15238#[no_mangle]
15240pub unsafe extern "C" fn msgsnd(msqid: c_int, msgp: *const c_void, msgsz: usize, msgflg: c_int) -> c_int {
15241 let r = sys_msgsnd(msqid, msgp, msgsz, msgflg);
15242 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15243}
15244
15245#[no_mangle]
15247pub unsafe extern "C" fn msgrcv(msqid: c_int, msgp: *mut c_void, msgsz: usize, msgtyp: c_long, msgflg: c_int) -> isize {
15248 let r = sys_msgrcv(msqid, msgp, msgsz, msgtyp, msgflg);
15249 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
15250}
15251
15252#[no_mangle]
15254pub unsafe extern "C" fn msgctl(msqid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
15255 let r = sys_msgctl(msqid, cmd, buf);
15256 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15257}
15258
15259#[no_mangle]
15261pub unsafe extern "C" fn semget(key: c_int, nsems: c_int, semflg: c_int) -> c_int {
15262 if nsems > 65535 { ERRNO!() = 22; return -1; }
15263 let r = sys_semget(key, nsems, semflg);
15264 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15265}
15266
15267#[no_mangle]
15269pub unsafe extern "C" fn semop(semid: c_int, sops: *const c_void, nsops: usize) -> c_int {
15270 let r = sys_semop(semid, sops, nsops);
15271 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15272}
15273
15274#[no_mangle]
15276pub unsafe extern "C" fn semctl(semid: c_int, semnum: c_int, cmd: c_int, mut args: ...) -> c_int {
15277 let mut arg: *mut c_void = core::ptr::null_mut();
15278 match cmd {
15280 16 | 13 | 17 | 1 | 2 | 3 | 18 | 19 | 20 | 0x102 | 0x104 | 0x106 => {
15284 arg = args.next_arg::<*mut c_void>();
15285 }
15286 _ => {}
15287 }
15288 let r = sys_semctl(semid, semnum, cmd, arg);
15289 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15290}
15291
15292#[no_mangle]
15294pub unsafe extern "C" fn shmget(key: c_int, size: usize, shmflg: c_int) -> c_int {
15295 let r = sys_shmget(key, size, shmflg);
15296 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15297}
15298
15299#[no_mangle]
15301pub unsafe extern "C" fn shmat(shmid: c_int, shmaddr: *const c_void, shmflg: c_int) -> *mut c_void {
15302 let r = sys_shmat(shmid, shmaddr, shmflg);
15303 if (r as usize) > (-(4096isize as isize)) as usize {
15304 ERRNO!() = (-r) as c_int;
15305 return -1isize as *mut c_void;
15306 }
15307 r as *mut c_void
15308}
15309
15310#[no_mangle]
15312pub unsafe extern "C" fn shmdt(shmaddr: *const c_void) -> c_int {
15313 let r = sys_shmdt(shmaddr);
15314 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15315}
15316
15317#[no_mangle]
15319pub unsafe extern "C" fn shmctl(shmid: c_int, cmd: c_int, buf: *mut c_void) -> c_int {
15320 let r = sys_shmctl(shmid, cmd, buf);
15321 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
15322}
15323
15324#[no_mangle]
15334pub static mut __auxv: *const usize = core::ptr::null();
15335
15336#[no_mangle]
15337pub static mut __progname: *mut c_char = core::ptr::null_mut();
15338#[no_mangle]
15339pub static mut __progname_full: *mut c_char = core::ptr::null_mut();
15340#[no_mangle]
15341pub static mut program_invocation_name: *mut c_char = core::ptr::null_mut();
15342#[no_mangle]
15343pub static mut program_invocation_short_name: *mut c_char = core::ptr::null_mut();
15344
15345#[no_mangle]
15346pub static in6addr_any: [u8; 16] = [0; 16];
15347#[no_mangle]
15348pub static in6addr_loopback: [u8; 16] = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];
15349
15350#[no_mangle]
15351pub static mut __daylight: c_int = 0;
15352#[no_mangle]
15353pub static mut __timezone: c_long = 0;
15354#[no_mangle]
15355pub static mut __tzname: [*mut c_char; 2] = [core::ptr::null_mut(); 2];
15356
15357#[no_mangle]
15358pub unsafe extern "C" fn getauxval(type_: c_ulong) -> c_ulong {
15359 let mut p = __auxv;
15360 if p.is_null() {
15361 return 0;
15362 }
15363 loop {
15364 let tag = *p;
15365 if tag == 0 {
15366 return 0;
15367 }
15368 if tag == type_ as usize {
15369 return *p.add(1) as c_ulong;
15370 }
15371 p = p.add(2);
15372 }
15373}
15374
15375type MainFn = unsafe extern "C" fn(c_int, *const *const c_char, *const *const c_char) -> c_int;
15376type InitFn = unsafe extern "C" fn();
15377
15378#[no_mangle]
15379pub unsafe extern "C" fn __libc_start_main(
15380 main: MainFn,
15381 argc: c_int,
15382 argv: *const *const c_char,
15383 _init: *const c_void,
15384 _fini: *const c_void,
15385 _rtld_fini: *const c_void,
15386 _stack_end: *const c_void,
15387) -> ! {
15388 errno_init();
15389
15390 let envp = argv.add((argc + 1) as usize);
15391 __environ = envp as *mut *mut c_char;
15392 environ = __environ; ___environ = __environ;
15394 _environ = __environ;
15395
15396 if !argv.is_null() && argc > 0 {
15398 let argv0 = *argv;
15399 __progname_full = argv0 as *mut c_char;
15400 program_invocation_name = argv0 as *mut c_char;
15401 let mut base = argv0;
15402 let mut p = argv0;
15403 while *p != 0 {
15404 if *p == b'/' as c_char { base = p.add(1); }
15405 p = p.add(1);
15406 }
15407 __progname = base as *mut c_char;
15408 program_invocation_short_name = base as *mut c_char;
15409 }
15410
15411 __stdio_init();
15412
15413 let mut set: SigSetT = 0;
15414 sigemptyset(&mut set);
15415 sigaddset(&mut set, SIGCANCEL);
15416 sigprocmask(SIG_UNBLOCK, &set, core::ptr::null_mut());
15417
15418 if !_init.is_null() {
15419 let init_fn: InitFn = core::mem::transmute(_init);
15420 init_fn();
15421 }
15422
15423 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
15427 {
15428 let random_ptr = getauxval(25) as *const u8; if !random_ptr.is_null() {
15430 let a = core::ptr::read_unaligned(random_ptr as *const u64);
15431 let b = core::ptr::read_unaligned(random_ptr.add(8) as *const u64);
15432 __stack_chk_guard = (a ^ b) as usize;
15433 } else {
15434 __stack_chk_guard = 0xdefaced_cafebeef;
15436 }
15437 }
15438
15439 let result = main(argc, argv, envp);
15440
15441 if !_fini.is_null() {
15442 let fini_fn: InitFn = core::mem::transmute(_fini);
15443 fini_fn();
15444 }
15445
15446 exit(result);
15447}
15448
15449type LdsoDlopenFn = unsafe extern "C" fn(*const c_char, c_int) -> *mut c_void;
15450type LdsoDlsymFn = unsafe extern "C" fn(*mut c_void, *const c_char, *mut c_void) -> *mut c_void;
15451type LdsoDlcloseFn = unsafe extern "C" fn(*mut c_void) -> c_int;
15452type LdsoDlerrorFn = unsafe extern "C" fn() -> *const c_char;
15453
15454static mut LDSO_DLOPEN: Option<LdsoDlopenFn> = None;
15455static mut LDSO_DLSYM: Option<LdsoDlsymFn> = None;
15456static mut LDSO_DLCLOSE: Option<LdsoDlcloseFn> = None;
15457static mut LDSO_DLERROR: Option<LdsoDlerrorFn> = None;
15458
15459#[no_mangle]
15460pub unsafe extern "C" fn __ldso_register_dlopen(f: LdsoDlopenFn) {
15461 LDSO_DLOPEN = Some(f);
15462}
15463
15464#[no_mangle]
15465pub unsafe extern "C" fn __ldso_register_dlsym(f: LdsoDlsymFn) {
15466 LDSO_DLSYM = Some(f);
15467}
15468
15469#[no_mangle]
15470pub unsafe extern "C" fn __ldso_register_dlclose(f: LdsoDlcloseFn) {
15471 LDSO_DLCLOSE = Some(f);
15472}
15473
15474#[no_mangle]
15475pub unsafe extern "C" fn __ldso_register_dlerror(f: LdsoDlerrorFn) {
15476 LDSO_DLERROR = Some(f);
15477}
15478
15479#[no_mangle]
15480pub unsafe extern "C" fn dlopen(filename: *const c_char, flags: c_int) -> *mut c_void {
15481 if let Some(f) = LDSO_DLOPEN {
15482 f(filename, flags)
15483 } else {
15484 null_mut()
15485 }
15486}
15487
15488#[no_mangle]
15489pub unsafe extern "C" fn dlsym_impl(
15490 handle: *mut c_void,
15491 symbol: *const c_char,
15492 ra: *mut c_void,
15493) -> *mut c_void {
15494 if let Some(f) = LDSO_DLSYM {
15495 f(handle, symbol, ra)
15496 } else {
15497 null_mut()
15498 }
15499}
15500
15501#[no_mangle]
15505#[unsafe(naked)]
15506#[cfg(target_arch = "x86_64")]
15507pub unsafe extern "C" fn dlsym(_handle: *mut c_void, _symbol: *const c_char) -> *mut c_void {
15508 core::arch::naked_asm!("mov rdx, [rsp]", "jmp dlsym_impl");
15509}
15510
15511#[no_mangle]
15512#[unsafe(naked)]
15513#[cfg(target_arch = "aarch64")]
15514pub unsafe extern "C" fn dlsym(_handle: *mut c_void, _symbol: *const c_char) -> *mut c_void {
15515 core::arch::naked_asm!("mov x2, x30", "b dlsym_impl");
15516}
15517
15518#[no_mangle]
15519#[unsafe(naked)]
15520#[cfg(target_arch = "riscv64")]
15521pub unsafe extern "C" fn dlsym(_handle: *mut c_void, _symbol: *const c_char) -> *mut c_void {
15522 core::arch::naked_asm!("mv a2, ra", "la t0, dlsym_impl", "jr t0");
15523}
15524
15525#[no_mangle]
15526pub unsafe extern "C" fn dlclose(handle: *mut c_void) -> c_int {
15527 if let Some(f) = LDSO_DLCLOSE {
15528 f(handle)
15529 } else {
15530 0
15531 }
15532}
15533
15534#[no_mangle]
15535pub unsafe extern "C" fn dlerror() -> *const c_char {
15536 if let Some(f) = LDSO_DLERROR {
15537 f()
15538 } else {
15539 core::ptr::null()
15540 }
15541}
15542
15543include!("crypt_impl.rs");
15544include!("statvfs.rs");
15545include!("daemon.rs");
15546include!("dn_expand.rs");
15547include!("lrand48.rs");
15548include!("strverscmp.rs");
15549include!("syscall.rs");
15550include!("pthread_atfork.rs");
15551include!("fenv.rs");
15552include!("locale_ctype.rs");
15553include!("regression_stubs.rs");
15554include!("netdb_extra.rs");
15555include!("compat_extra.rs");
15556include!("stdio_extra.rs");
15557include!("ns_parse.rs");
15558include!("fts.rs");
15559include!("ifaddrs.rs");
15560include!("dl_extra.rs");
15561include!("des.rs");
15562include!("path_extra.rs");
15563include!("wordexp.rs");
15564include!("getopt_impl.rs");
15565
15566type regoff_t = c_int;
15571
15572#[repr(C)]
15573pub struct regex_t {
15574 pub re_nsub: usize,
15575 pub __opaque: *mut c_void,
15576 pub __padding: [*mut c_void; 4],
15577 pub __nsub2: usize,
15578 pub __padding2: c_char,
15579}
15580
15581#[repr(C)]
15582pub struct regmatch_t {
15583 pub rm_so: regoff_t,
15584 pub rm_eo: regoff_t,
15585}
15586
15587include!("regex.rs");
15588
15589#[cfg(test)]
15590mod libc_unit_stub {
15591 #[test]
15592 fn stub() {
15593 assert!(true);
15594 }
15595}
15596
15597#[inline]
15602pub(crate) fn fmax_impl(x: f64, y: f64) -> f64 {
15603 if x.is_nan() { return y; }
15604 if y.is_nan() { return x; }
15605 if x == 0.0 && y == 0.0 {
15606 return if x.is_sign_negative() && y.is_sign_negative() { -0.0 } else { 0.0 };
15607 }
15608 if x > y { x } else { y }
15609}
15610
15611#[inline]
15612pub(crate) fn fmin_impl(x: f64, y: f64) -> f64 {
15613 if x.is_nan() { return y; }
15614 if y.is_nan() { return x; }
15615 if x == 0.0 && y == 0.0 {
15616 return if x.is_sign_negative() || y.is_sign_negative() { -0.0 } else { 0.0 };
15617 }
15618 if x < y { x } else { y }
15619}
15620
15621#[inline]
15622pub(crate) fn fmaxf_impl(x: f32, y: f32) -> f32 {
15623 if x.is_nan() { return y; }
15624 if y.is_nan() { return x; }
15625 if x == 0.0 && y == 0.0 {
15626 return if x.is_sign_negative() && y.is_sign_negative() { -0.0 } else { 0.0 };
15627 }
15628 if x > y { x } else { y }
15629}
15630
15631#[inline]
15632pub(crate) fn fminf_impl(x: f32, y: f32) -> f32 {
15633 if x.is_nan() { return y; }
15634 if y.is_nan() { return x; }
15635 if x == 0.0 && y == 0.0 {
15636 return if x.is_sign_negative() || y.is_sign_negative() { -0.0 } else { 0.0 };
15637 }
15638 if x < y { x } else { y }
15639}
15640
15641#[inline(never)]
15642#[no_mangle]
15643pub unsafe extern "C" fn fmax(x: f64, y: f64) -> f64 {
15644 fmax_impl(x, y)
15645}
15646
15647#[inline(never)]
15648#[no_mangle]
15649pub unsafe extern "C" fn fmin(x: f64, y: f64) -> f64 {
15650 fmin_impl(x, y)
15651}
15652
15653#[no_mangle]
15654pub unsafe extern "C" fn fminf(x: f32, y: f32) -> f32 {
15655 fminf_impl(x, y)
15656}
15657
15658#[no_mangle]
15659pub unsafe extern "C" fn fdim(x: f64, y: f64) -> f64 {
15660 if x.is_nan() || y.is_nan() {
15661 return f64::NAN;
15662 }
15663 if x > y { x - y } else { 0.0 }
15664}
15665
15666#[no_mangle]
15667pub unsafe extern "C" fn fma(x: f64, y: f64, z: f64) -> f64 {
15668 if (x.is_infinite() && y == 0.0) || (y.is_infinite() && x == 0.0) {
15669 feraiseexcept(FE_INVALID);
15670 return f64::NAN;
15671 }
15672 if x.is_nan() || y.is_nan() || z.is_nan() {
15673 return f64::NAN;
15674 }
15675 let r = libm::fma(x, y, z);
15676 if r.is_nan() {
15678 feraiseexcept(FE_INVALID);
15679 }
15680 r
15681}
15682
15683#[no_mangle]
15684pub unsafe extern "C" fn ilogb(x: f64) -> i32 {
15685 if x.is_nan() {
15686 feraiseexcept(FE_INVALID);
15687 return -0x7fffffff - 1; }
15689 if x == 0.0 || x.is_infinite() {
15690 feraiseexcept(FE_INVALID);
15691 return if x == 0.0 { -0x7fffffff - 1 } else { 0x7fffffff };
15692 }
15693 let bits = x.to_bits();
15694 let exp = ((bits >> 52) & 0x7ff) as i32;
15695 if exp == 0 {
15696 let mut v = bits & 0xfffffffffffff;
15698 let mut e = -1022;
15699 while v < (1u64 << 52) { v <<= 1; e -= 1; }
15700 e
15701 } else {
15702 exp - 1023
15703 }
15704}
15705
15706#[no_mangle]
15707pub unsafe extern "C" fn logb(x: f64) -> f64 {
15708 if x.is_nan() { return x; }
15709 if x == 0.0 { return __math_divzero(1); }
15710 let bits = x.to_bits();
15711 let exp = ((bits >> 52) & 0x7ff) as i32;
15712 if exp == 0 {
15713 let mut v = bits & 0xfffffffffffff;
15715 let mut e = -1022i32;
15716 while v < (1u64 << 52) { v <<= 1; e -= 1; }
15717 e as f64
15718 } else if exp == 0x7ff {
15719 x * x } else {
15721 (exp - 1023) as f64
15722 }
15723}
15724
15725#[no_mangle]
15726pub unsafe extern "C" fn nearbyint(x: f64) -> f64 {
15727 let had_inexact = fetestexcept(FE_INEXACT) & FE_INEXACT != 0;
15728 let r = libm::rint(x);
15729 if !had_inexact {
15730 feclearexcept(FE_INEXACT);
15731 }
15732 r
15733}
15734
15735#[no_mangle]
15736pub unsafe extern "C" fn nextafter(x: f64, y: f64) -> f64 {
15737 if x.is_nan() || y.is_nan() { return x + y; }
15738 if x == 0.0 && y == 0.0 { return y; }
15739 if x == y { return x; }
15740 let r = libm::nextafter(x, y);
15741 if r.is_infinite() && x.is_finite() {
15742 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
15743 } else if r != x {
15744 let bits = r.to_bits();
15745 let is_subnormal = (bits & 0x7ff0000000000000) == 0 && (bits & 0xfffffffffffff) != 0;
15746 if r == 0.0 || is_subnormal {
15747 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
15748 }
15749 }
15750 r
15751}
15752
15753#[no_mangle]
15754pub unsafe extern "C" fn nexttoward(x: f64, y: f64) -> f64 {
15755 if x == 0.0 && y == 0.0 {
15757 return if y.is_sign_negative() { -0.0 } else { 0.0 };
15758 }
15759 nextafter(x, y)
15760}
15761
15762#[no_mangle]
15763pub unsafe extern "C" fn remainder(x: f64, y: f64) -> f64 {
15764 if x.is_nan() || y.is_nan() { return x + y; }
15765 if y == 0.0 || x.is_infinite() { return __math_invalid(x); }
15766 libm::remainder(x, y)
15767}
15768
15769#[no_mangle]
15770pub unsafe extern "C" fn remquo(x: f64, y: f64, quo: *mut i32) -> f64 {
15771 if x.is_nan() || y.is_nan() {
15772 if !quo.is_null() { *quo = 0; }
15773 return x + y;
15774 }
15775 if y == 0.0 || x.is_infinite() {
15776 if !quo.is_null() { *quo = 0; }
15777 return __math_invalid(x);
15778 }
15779 let (r, q) = libm::remquo(x, y);
15780 if !quo.is_null() { *quo = q; }
15781 r
15782}
15783
15784#[no_mangle]
15785pub unsafe extern "C" fn exp2(x: f64) -> f64 {
15786 exp2_impl(x)
15787}
15788
15789#[no_mangle]
15790pub unsafe extern "C" fn expm1(x: f64) -> f64 {
15791 let r = libm::expm1(x);
15792 if r != 0.0 && x != 0.0 && libm::fabs(x) < 1e-307 {
15794 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
15795 }
15796 r
15797}
15798
15799#[no_mangle]
15800pub unsafe extern "C" fn log1p(x: f64) -> f64 {
15801 if x == -1.0 {
15802 feraiseexcept(FE_DIVBYZERO);
15803 return f64::NEG_INFINITY;
15804 }
15805 libm::log1p(x)
15806}
15807
15808#[no_mangle]
15809pub unsafe extern "C" fn acosh(x: f64) -> f64 {
15810 if x < 1.0 {
15811 feraiseexcept(FE_INVALID);
15812 return f64::NAN;
15813 }
15814 libm::acosh(x)
15815}
15816
15817#[no_mangle]
15818pub unsafe extern "C" fn asinh(x: f64) -> f64 {
15819 if x == 0.0 { return x; }
15820 libm::asinh(x)
15821}
15822
15823#[no_mangle]
15824pub unsafe extern "C" fn atanh(x: f64) -> f64 {
15825 if x == 0.0 { return x; }
15826 let e = ((x.to_bits() >> 52) & 0x7ff) as i32;
15827 if e < 0x3ff - 32 {
15828 feraiseexcept(FE_INEXACT);
15829 if e == 0 { feraiseexcept(FE_UNDERFLOW); }
15830 return x;
15831 }
15832 if x == 1.0 {
15833 feraiseexcept(FE_DIVBYZERO);
15834 return f64::INFINITY;
15835 }
15836 if x == -1.0 {
15837 feraiseexcept(FE_DIVBYZERO);
15838 return f64::NEG_INFINITY;
15839 }
15840 if x.is_nan() { return x; }
15841 let ax = libm::fabs(x);
15842 if ax > 1.0 {
15843 feraiseexcept(FE_INVALID);
15844 return f64::NAN;
15845 }
15846 if ax < 0.5 {
15847 let r = libm::log1p(2.0 * (ax + ax * ax / (1.0 - ax))) / 2.0;
15849 if x < 0.0 { -r } else { r }
15850 } else {
15851 let r = 0.5 * libm::log((1.0 + ax) / (1.0 - ax));
15853 if x < 0.0 { -r } else { r }
15854 }
15855}
15856
15857#[no_mangle]
15858pub unsafe extern "C" fn cbrt(x: f64) -> f64 {
15859 libm::cbrt(x)
15860}
15861
15862#[no_mangle]
15863pub unsafe extern "C" fn erf(x: f64) -> f64 {
15864 erf_impl(x)
15865}
15866
15867#[no_mangle]
15868pub unsafe extern "C" fn erfc(x: f64) -> f64 {
15869 erfc_impl(x)
15870}
15871
15872#[no_mangle]
15873pub unsafe extern "C" fn lgamma(x: f64) -> f64 {
15874 lgamma_impl(x)
15875}
15876
15877#[no_mangle]
15878pub unsafe extern "C" fn tgamma(x: f64) -> f64 {
15879 tgamma_impl(x)
15880}
15881
15882#[no_mangle]
15883pub unsafe extern "C" fn lround(x: f64) -> core::ffi::c_long {
15884 libm::round(x) as core::ffi::c_long
15885}
15886
15887#[no_mangle]
15888pub unsafe extern "C" fn llround(x: f64) -> i64 {
15889 libm::round(x) as i64
15890}
15891
15892#[no_mangle]
15899pub unsafe extern "C" fn cabs(z: (f64, f64)) -> f64 {
15900 libm::sqrt(z.0 * z.0 + z.1 * z.1)
15901}
15902
15903#[no_mangle]
15904pub unsafe extern "C" fn cabsf(z: (f32, f32)) -> f32 {
15905 libm::sqrtf(z.0 * z.0 + z.1 * z.1)
15906}
15907
15908#[no_mangle]
15909pub unsafe extern "C" fn cabsl(z: (f64, f64)) -> f64 {
15910 cabs(z)
15911}
15912
15913#[no_mangle]
15914pub unsafe extern "C" fn carg(z: (f64, f64)) -> f64 {
15915 libm::atan2(z.1, z.0)
15916}
15917
15918#[no_mangle]
15919pub unsafe extern "C" fn cargf(z: (f32, f32)) -> f32 {
15920 libm::atan2f(z.1, z.0)
15921}
15922
15923#[no_mangle]
15924pub unsafe extern "C" fn cargl(z: (f64, f64)) -> f64 {
15925 carg(z)
15926}
15927
15928#[no_mangle]
15929pub unsafe extern "C" fn cimag(z: (f64, f64)) -> f64 {
15930 z.1
15931}
15932
15933#[no_mangle]
15934pub unsafe extern "C" fn cimagf(z: (f32, f32)) -> f32 {
15935 z.1
15936}
15937
15938#[no_mangle]
15939pub unsafe extern "C" fn cimagl(z: (f64, f64)) -> f64 {
15940 z.1
15941}
15942
15943#[no_mangle]
15944pub unsafe extern "C" fn creal(z: (f64, f64)) -> f64 {
15945 z.0
15946}
15947
15948#[no_mangle]
15949pub unsafe extern "C" fn crealf(z: (f32, f32)) -> f32 {
15950 z.0
15951}
15952
15953#[no_mangle]
15954pub unsafe extern "C" fn creall(z: (f64, f64)) -> f64 {
15955 z.0
15956}
15957
15958#[no_mangle]
15959pub unsafe extern "C" fn conj(z: (f64, f64)) -> (f64, f64) {
15960 (z.0, -z.1)
15961}
15962
15963#[no_mangle]
15964pub unsafe extern "C" fn conjf(z: (f32, f32)) -> (f32, f32) {
15965 (z.0, -z.1)
15966}
15967
15968#[no_mangle]
15969pub unsafe extern "C" fn conjl(z: (f64, f64)) -> (f64, f64) {
15970 conj(z)
15971}
15972
15973#[no_mangle]
15974pub unsafe extern "C" fn cproj(z: (f64, f64)) -> (f64, f64) {
15975 if z.0.is_infinite() || z.1.is_infinite() {
15976 (f64::INFINITY, if z.1.is_sign_positive() { 0.0 } else { -0.0 })
15977 } else {
15978 z
15979 }
15980}
15981
15982#[no_mangle]
15983pub unsafe extern "C" fn cprojf(z: (f32, f32)) -> (f32, f32) {
15984 if z.0.is_infinite() || z.1.is_infinite() {
15985 (f32::INFINITY, if z.1.is_sign_positive() { 0.0 } else { -0.0 })
15986 } else {
15987 z
15988 }
15989}
15990
15991#[no_mangle]
15992pub unsafe extern "C" fn cprojl(z: (f64, f64)) -> (f64, f64) {
15993 cproj(z)
15994}
15995
15996#[no_mangle]
15998pub unsafe extern "C" fn cexp(z: (f64, f64)) -> (f64, f64) {
15999 let r = libm::exp(z.0);
16000 (r * libm::cos(z.1), r * libm::sin(z.1))
16001}
16002
16003#[no_mangle]
16004pub unsafe extern "C" fn cexpf(z: (f32, f32)) -> (f32, f32) {
16005 let r = libm::expf(z.0);
16006 (r * libm::cosf(z.1), r * libm::sinf(z.1))
16007}
16008
16009#[no_mangle]
16010pub unsafe extern "C" fn cexpl(z: (f64, f64)) -> (f64, f64) {
16011 cexp(z)
16012}
16013
16014#[no_mangle]
16016pub unsafe extern "C" fn clog(z: (f64, f64)) -> (f64, f64) {
16017 (libm::log(cabs(z)), carg(z))
16018}
16019
16020#[no_mangle]
16021pub unsafe extern "C" fn clogf(z: (f32, f32)) -> (f32, f32) {
16022 (libm::logf(cabsf(z)), cargf(z))
16023}
16024
16025#[no_mangle]
16026pub unsafe extern "C" fn clogl(z: (f64, f64)) -> (f64, f64) {
16027 clog(z)
16028}
16029
16030#[no_mangle]
16032pub unsafe extern "C" fn csqrt(z: (f64, f64)) -> (f64, f64) {
16033 let r = cabs(z);
16034 let sign = if z.1 < 0.0 { -1.0 } else { 1.0 };
16035 (libm::sqrt((r + z.0) / 2.0), sign * libm::sqrt((r - z.0) / 2.0))
16036}
16037
16038#[no_mangle]
16039pub unsafe extern "C" fn csqrtf(z: (f32, f32)) -> (f32, f32) {
16040 let r = cabsf(z);
16041 let sign = if z.1 < 0.0 { -1.0f32 } else { 1.0f32 };
16042 (libm::sqrtf((r + z.0) / 2.0), sign * libm::sqrtf((r - z.0) / 2.0))
16043}
16044
16045#[no_mangle]
16046pub unsafe extern "C" fn csqrtl(z: (f64, f64)) -> (f64, f64) {
16047 csqrt(z)
16048}
16049
16050#[no_mangle]
16052pub unsafe extern "C" fn cpow(z: (f64, f64), w: (f64, f64)) -> (f64, f64) {
16053 let log_z = clog(z);
16054 let exp_arg = (w.0 * log_z.0 - w.1 * log_z.1, w.0 * log_z.1 + w.1 * log_z.0);
16055 cexp(exp_arg)
16056}
16057
16058#[no_mangle]
16059pub unsafe extern "C" fn cpowf(z: (f32, f32), w: (f32, f32)) -> (f32, f32) {
16060 let log_z = clogf(z);
16061 let exp_arg = (w.0 * log_z.0 - w.1 * log_z.1, w.0 * log_z.1 + w.1 * log_z.0);
16062 cexpf(exp_arg)
16063}
16064
16065#[no_mangle]
16066pub unsafe extern "C" fn cpowl(z: (f64, f64), w: (f64, f64)) -> (f64, f64) {
16067 cpow(z, w)
16068}
16069
16070#[no_mangle]
16072pub unsafe extern "C" fn ccos(z: (f64, f64)) -> (f64, f64) {
16073 (libm::cos(z.0) * libm::cosh(z.1), -libm::sin(z.0) * libm::sinh(z.1))
16074}
16075
16076#[no_mangle]
16077pub unsafe extern "C" fn ccosf(z: (f32, f32)) -> (f32, f32) {
16078 (libm::cosf(z.0) * libm::coshf(z.1), -libm::sinf(z.0) * libm::sinhf(z.1))
16079}
16080
16081#[no_mangle]
16082pub unsafe extern "C" fn ccosl(z: (f64, f64)) -> (f64, f64) {
16083 ccos(z)
16084}
16085
16086#[no_mangle]
16088pub unsafe extern "C" fn csin(z: (f64, f64)) -> (f64, f64) {
16089 (libm::sin(z.0) * libm::cosh(z.1), libm::cos(z.0) * libm::sinh(z.1))
16090}
16091
16092#[no_mangle]
16093pub unsafe extern "C" fn csinf(z: (f32, f32)) -> (f32, f32) {
16094 (libm::sinf(z.0) * libm::coshf(z.1), libm::cosf(z.0) * libm::sinhf(z.1))
16095}
16096
16097#[no_mangle]
16098pub unsafe extern "C" fn csinl(z: (f64, f64)) -> (f64, f64) {
16099 csin(z)
16100}
16101
16102#[no_mangle]
16104pub unsafe extern "C" fn ctan(z: (f64, f64)) -> (f64, f64) {
16105 let d = libm::cos(2.0 * z.0) + libm::cosh(2.0 * z.1);
16106 (libm::sin(2.0 * z.0) / d, libm::sinh(2.0 * z.1) / d)
16107}
16108
16109#[no_mangle]
16110pub unsafe extern "C" fn ctanf(z: (f32, f32)) -> (f32, f32) {
16111 let d = libm::cosf(2.0 * z.0) + libm::coshf(2.0 * z.1);
16112 (libm::sinf(2.0 * z.0) / d, libm::sinhf(2.0 * z.1) / d)
16113}
16114
16115#[no_mangle]
16116pub unsafe extern "C" fn ctanl(z: (f64, f64)) -> (f64, f64) {
16117 ctan(z)
16118}
16119
16120#[no_mangle]
16122pub unsafe extern "C" fn ccosh(z: (f64, f64)) -> (f64, f64) {
16123 (libm::cosh(z.0) * libm::cos(z.1), libm::sinh(z.0) * libm::sin(z.1))
16124}
16125
16126#[no_mangle]
16127pub unsafe extern "C" fn ccoshf(z: (f32, f32)) -> (f32, f32) {
16128 (libm::coshf(z.0) * libm::cosf(z.1), libm::sinhf(z.0) * libm::sinf(z.1))
16129}
16130
16131#[no_mangle]
16132pub unsafe extern "C" fn ccoshl(z: (f64, f64)) -> (f64, f64) {
16133 ccosh(z)
16134}
16135
16136#[no_mangle]
16138pub unsafe extern "C" fn csinh(z: (f64, f64)) -> (f64, f64) {
16139 (libm::sinh(z.0) * libm::cos(z.1), libm::cosh(z.0) * libm::sin(z.1))
16140}
16141
16142#[no_mangle]
16143pub unsafe extern "C" fn csinhf(z: (f32, f32)) -> (f32, f32) {
16144 (libm::sinhf(z.0) * libm::cosf(z.1), libm::coshf(z.0) * libm::sinf(z.1))
16145}
16146
16147#[no_mangle]
16148pub unsafe extern "C" fn csinhl(z: (f64, f64)) -> (f64, f64) {
16149 csinh(z)
16150}
16151
16152#[no_mangle]
16154pub unsafe extern "C" fn ctanh(z: (f64, f64)) -> (f64, f64) {
16155 let d = libm::cosh(2.0 * z.0) + libm::cos(2.0 * z.1);
16156 (libm::sinh(2.0 * z.0) / d, libm::sin(2.0 * z.1) / d)
16157}
16158
16159#[no_mangle]
16160pub unsafe extern "C" fn ctanhf(z: (f32, f32)) -> (f32, f32) {
16161 let d = libm::coshf(2.0 * z.0) + libm::cosf(2.0 * z.1);
16162 (libm::sinhf(2.0 * z.0) / d, libm::sinf(2.0 * z.1) / d)
16163}
16164
16165#[no_mangle]
16166pub unsafe extern "C" fn ctanhl(z: (f64, f64)) -> (f64, f64) {
16167 ctanh(z)
16168}
16169
16170#[no_mangle]
16173pub unsafe extern "C" fn cacos(z: (f64, f64)) -> (f64, f64) {
16174 let asin_z = casin(z);
16175 (3.14159265358979323846264338327950288419716939937510582097494459230781640 / 2.0 - asin_z.0, -asin_z.1)
16176}
16177
16178#[no_mangle]
16179pub unsafe extern "C" fn cacosf(z: (f32, f32)) -> (f32, f32) {
16180 let asin_z = casinf(z);
16181 (3.14159265358979323846264338327950288419716939937510582097494459230781640f32 / 2.0 - asin_z.0, -asin_z.1)
16182}
16183
16184#[no_mangle]
16185pub unsafe extern "C" fn cacosl(z: (f64, f64)) -> (f64, f64) {
16186 cacos(z)
16187}
16188
16189#[no_mangle]
16191pub unsafe extern "C" fn casin(z: (f64, f64)) -> (f64, f64) {
16192 let iz = (-z.1, z.0);
16194 let one_minus_z2 = (1.0 - z.0 * z.0 + z.1 * z.1, -2.0 * z.0 * z.1);
16196 let sqrt_val = csqrt(one_minus_z2);
16197 let arg = clog((iz.0 + sqrt_val.0, iz.1 + sqrt_val.1));
16198 (arg.1, -arg.0)
16200}
16201
16202#[no_mangle]
16203pub unsafe extern "C" fn casinf(z: (f32, f32)) -> (f32, f32) {
16204 let iz = (-z.1, z.0);
16205 let one_minus_z2 = (1.0 - z.0 * z.0 + z.1 * z.1, -2.0 * z.0 * z.1);
16206 let sqrt_val = csqrtf(one_minus_z2);
16207 let arg = clogf((iz.0 + sqrt_val.0, iz.1 + sqrt_val.1));
16208 (arg.1, -arg.0)
16209}
16210
16211#[no_mangle]
16212pub unsafe extern "C" fn casinl(z: (f64, f64)) -> (f64, f64) {
16213 casin(z)
16214}
16215
16216#[no_mangle]
16218pub unsafe extern "C" fn catan(z: (f64, f64)) -> (f64, f64) {
16219 let num = (1.0 + z.1, -z.0);
16223 let den = (1.0 - z.1, z.0);
16224 let ratio = cdiv(num, den);
16225 let log_ratio = clog(ratio);
16226 (-log_ratio.1 / 2.0, log_ratio.0 / 2.0)
16228}
16229
16230#[no_mangle]
16231pub unsafe extern "C" fn catanf(z: (f32, f32)) -> (f32, f32) {
16232 let num = (1.0 + z.1, -z.0);
16233 let den = (1.0 - z.1, z.0);
16234 let ratio = cdivf(num, den);
16235 let log_ratio = clogf(ratio);
16236 (-log_ratio.1 / 2.0, log_ratio.0 / 2.0)
16237}
16238
16239#[no_mangle]
16240pub unsafe extern "C" fn catanl(z: (f64, f64)) -> (f64, f64) {
16241 catan(z)
16242}
16243
16244fn cdiv(a: (f64, f64), b: (f64, f64)) -> (f64, f64) {
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
16250fn cdivf(a: (f32, f32), b: (f32, f32)) -> (f32, f32) {
16251 let d = b.0 * b.0 + b.1 * b.1;
16252 ((a.0 * b.0 + a.1 * b.1) / d, (a.1 * b.0 - a.0 * b.1) / d)
16253}
16254
16255#[no_mangle]
16257pub unsafe extern "C" fn cacosh(z: (f64, f64)) -> (f64, f64) {
16258 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16259 let z2_minus_1 = (z2.0 - 1.0, z2.1);
16260 let sqrt_val = csqrt(z2_minus_1);
16261 clog((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16262}
16263
16264#[no_mangle]
16265pub unsafe extern "C" fn cacoshf(z: (f32, f32)) -> (f32, f32) {
16266 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16267 let z2_minus_1 = (z2.0 - 1.0, z2.1);
16268 let sqrt_val = csqrtf(z2_minus_1);
16269 clogf((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16270}
16271
16272#[no_mangle]
16273pub unsafe extern "C" fn cacoshl(z: (f64, f64)) -> (f64, f64) {
16274 cacosh(z)
16275}
16276
16277#[no_mangle]
16279pub unsafe extern "C" fn casinh(z: (f64, f64)) -> (f64, f64) {
16280 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16281 let z2_plus_1 = (z2.0 + 1.0, z2.1);
16282 let sqrt_val = csqrt(z2_plus_1);
16283 clog((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16284}
16285
16286#[no_mangle]
16287pub unsafe extern "C" fn casinhf(z: (f32, f32)) -> (f32, f32) {
16288 let z2 = (z.0 * z.0 - z.1 * z.1, 2.0 * z.0 * z.1);
16289 let z2_plus_1 = (z2.0 + 1.0, z2.1);
16290 let sqrt_val = csqrtf(z2_plus_1);
16291 clogf((z.0 + sqrt_val.0, z.1 + sqrt_val.1))
16292}
16293
16294#[no_mangle]
16295pub unsafe extern "C" fn casinhl(z: (f64, f64)) -> (f64, f64) {
16296 casinh(z)
16297}
16298
16299#[no_mangle]
16301pub unsafe extern "C" fn catanh(z: (f64, f64)) -> (f64, f64) {
16302 let num = (1.0 + z.0, z.1);
16303 let den = (1.0 - z.0, -z.1);
16304 let ratio = cdiv(num, den);
16305 let log_ratio = clog(ratio);
16306 (log_ratio.0 / 2.0, log_ratio.1 / 2.0)
16307}
16308
16309#[no_mangle]
16310pub unsafe extern "C" fn catanhf(z: (f32, f32)) -> (f32, f32) {
16311 let num = (1.0 + z.0, z.1);
16312 let den = (1.0 - z.0, -z.1);
16313 let ratio = cdivf(num, den);
16314 let log_ratio = clogf(ratio);
16315 (log_ratio.0 / 2.0, log_ratio.1 / 2.0)
16316}
16317
16318#[no_mangle]
16319pub unsafe extern "C" fn catanhl(z: (f64, f64)) -> (f64, f64) {
16320 catanh(z)
16321}
16322
16323#[inline(never)]
16328#[no_mangle]
16329pub unsafe extern "C" fn fmaxf(x: f32, y: f32) -> f32 {
16330 fmaxf_impl(x, y)
16331}
16332
16333#[no_mangle]
16334pub unsafe extern "C" fn fdimf(x: f32, y: f32) -> f32 {
16335 if x.is_nan() || y.is_nan() {
16336 return f32::NAN;
16337 }
16338 if x > y { x - y } else { 0.0 }
16339}
16340
16341#[no_mangle]
16342pub unsafe extern "C" fn fmaf(x: f32, y: f32, z: f32) -> f32 {
16343 if (x.is_infinite() && y == 0.0) || (y.is_infinite() && x == 0.0) {
16344 feraiseexcept(FE_INVALID);
16345 return f32::NAN;
16346 }
16347 if x.is_nan() || y.is_nan() || z.is_nan() {
16348 return f32::NAN;
16349 }
16350 let r = libm::fmaf(x, y, z);
16351 if r.is_nan() {
16352 feraiseexcept(FE_INVALID);
16353 }
16354 r
16355}
16356
16357#[no_mangle]
16358pub unsafe extern "C" fn ilogbf(x: f32) -> i32 {
16359 if x.is_nan() {
16360 feraiseexcept(FE_INVALID);
16361 return -0x7fffffff - 1;
16362 }
16363 if x == 0.0 || x.is_infinite() {
16364 feraiseexcept(FE_INVALID);
16365 return if x == 0.0 { -0x7fffffff - 1 } else { 0x7fffffff };
16366 }
16367 let bits = x.to_bits();
16368 let exp = ((bits >> 23) & 0xff) as i32;
16369 if exp == 0 {
16370 let mut v = bits & 0x7fffff;
16371 let mut e = -126;
16372 while v < (1u32 << 23) { v <<= 1; e -= 1; }
16373 e
16374 } else {
16375 exp - 127
16376 }
16377}
16378
16379#[no_mangle]
16380pub unsafe extern "C" fn logbf(x: f32) -> f32 {
16381 if x.is_nan() { return x; }
16382 if x == 0.0 { return __math_divzerof(1); }
16383 let bits = x.to_bits();
16384 let exp = ((bits >> 23) & 0xff) as i32;
16385 if exp == 0 {
16386 let mut v = bits & 0x7fffff;
16387 let mut e = -126i32;
16388 while v < (1u32 << 23) { v <<= 1; e -= 1; }
16389 e as f32
16390 } else if exp == 0xff {
16391 x * x
16392 } else {
16393 (exp - 127) as f32
16394 }
16395}
16396
16397#[no_mangle]
16398pub unsafe extern "C" fn nearbyintf(x: f32) -> f32 {
16399 let had_inexact = fetestexcept(FE_INEXACT) & FE_INEXACT != 0;
16400 let r = libm::rintf(x);
16401 if !had_inexact {
16402 feclearexcept(FE_INEXACT);
16403 }
16404 r
16405}
16406
16407#[no_mangle]
16408pub unsafe extern "C" fn nextafterf(x: f32, y: f32) -> f32 {
16409 if x.is_nan() || y.is_nan() { return x + y; }
16410 if x == 0.0 && y == 0.0 { return y; }
16411 if x == y { return x; }
16412 let r = libm::nextafterf(x, y);
16413 if r.is_infinite() && x.is_finite() {
16414 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
16415 } else if r != x {
16416 let bits = r.to_bits();
16417 let is_subnormal = (bits & 0x7f800000) == 0 && (bits & 0x7fffff) != 0;
16418 if r == 0.0 || is_subnormal {
16419 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16420 }
16421 }
16422 r
16423}
16424
16425#[no_mangle]
16426#[cfg(target_arch = "x86_64")]
16427pub unsafe extern "C" fn nexttowardf(x: f32, y: f64) -> f32 {
16428 if y.is_nan() { return (x as f64 + y) as f32; }
16429 if x == 0.0 && y == 0.0 {
16430 return if y.is_sign_negative() { -0.0 } else { 0.0 };
16431 }
16432 if (x as f64) == y { return x; }
16433 nextafterf(x, if y > x as f64 { f32::INFINITY } else { f32::NEG_INFINITY })
16434}
16435
16436#[no_mangle]
16437#[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
16438pub unsafe extern "C" fn nexttowardf(x: f32, y: f128) -> f32 {
16439 if y.is_nan() { return (x as f128 + y) as f32; }
16440 if (x as f128) == y { return x; }
16441 nextafterf(x, if y > x as f128 { f32::INFINITY } else { f32::NEG_INFINITY })
16442}
16443
16444#[no_mangle]
16445pub unsafe extern "C" fn remainderf(x: f32, y: f32) -> f32 {
16446 if x.is_nan() || y.is_nan() { return x + y; }
16447 if y == 0.0 || x.is_infinite() { return __math_invalidf(x); }
16448 libm::remainderf(x, y)
16449}
16450
16451#[no_mangle]
16452pub unsafe extern "C" fn remquof(x: f32, y: f32, quo: *mut i32) -> f32 {
16453 if x.is_nan() || y.is_nan() {
16454 if !quo.is_null() { *quo = 0; }
16455 return x + y;
16456 }
16457 if y == 0.0 || x.is_infinite() {
16458 if !quo.is_null() { *quo = 0; }
16459 return __math_invalidf(x);
16460 }
16461 let (r, q) = libm::remquof(x, y);
16462 if !quo.is_null() { *quo = q; }
16463 r
16464}
16465
16466#[no_mangle]
16467pub unsafe extern "C" fn exp2f(x: f32) -> f32 {
16468 if x == f32::INFINITY { return f32::INFINITY; }
16469 if x == f32::NEG_INFINITY { return 0.0; }
16470 if x.is_nan() { return f32::NAN; }
16471 let r = libm::exp2f(x);
16472 if r.is_infinite() && x.is_finite() {
16473 feraiseexcept(FE_OVERFLOW | FE_INEXACT);
16474 } else if r == 0.0 && x < -149.0 {
16475 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16476 } else if r != 0.0 && x != libm::truncf(x) {
16477 let bits = r.to_bits();
16478 if (bits & 0x7f800000) == 0 {
16479 feraiseexcept(FE_UNDERFLOW | FE_INEXACT);
16480 }
16481 }
16482 r
16483}
16484
16485#[no_mangle]
16486pub unsafe extern "C" fn expm1f(x: f32) -> f32 {
16487 libm::expm1f(x)
16488}
16489
16490#[no_mangle]
16491pub unsafe extern "C" fn log1pf(x: f32) -> f32 {
16492 if x == -1.0 {
16493 feraiseexcept(FE_DIVBYZERO);
16494 return f32::NEG_INFINITY;
16495 }
16496 libm::log1pf(x)
16497}
16498
16499#[no_mangle]
16500pub unsafe extern "C" fn acoshf(x: f32) -> f32 {
16501 if x < 1.0 {
16502 feraiseexcept(FE_INVALID);
16503 return f32::NAN;
16504 }
16505 libm::acoshf(x)
16506}
16507
16508#[no_mangle]
16509pub unsafe extern "C" fn asinhf(x: f32) -> f32 {
16510 if x == 0.0 { return x; }
16511 libm::asinhf(x)
16512}
16513
16514#[no_mangle]
16515pub unsafe extern "C" fn atanhf(x: f32) -> f32 {
16516 if x == 0.0 { return x; }
16517 let e = ((x.to_bits() >> 23) & 0xff) as i32;
16518 if e < 0x7f - 32 {
16519 feraiseexcept(FE_INEXACT);
16520 if e == 0 { feraiseexcept(FE_UNDERFLOW); }
16521 return x;
16522 }
16523 if x == 1.0 {
16524 feraiseexcept(FE_DIVBYZERO);
16525 return f32::INFINITY;
16526 }
16527 if x == -1.0 {
16528 feraiseexcept(FE_DIVBYZERO);
16529 return f32::NEG_INFINITY;
16530 }
16531 if x.is_nan() { return x; }
16532 let ax = libm::fabsf(x);
16533 if ax > 1.0 {
16534 feraiseexcept(FE_INVALID);
16535 return f32::NAN;
16536 }
16537 if ax < 0.5 {
16538 let r = libm::log1pf(2.0 * (ax + ax * ax / (1.0 - ax))) / 2.0;
16539 if x < 0.0 { -r } else { r }
16540 } else {
16541 let r = 0.5 * libm::logf((1.0 + ax) / (1.0 - ax));
16542 if x < 0.0 { -r } else { r }
16543 }
16544}
16545
16546#[no_mangle]
16547pub unsafe extern "C" fn cbrtf(x: f32) -> f32 {
16548 libm::cbrtf(x)
16549}
16550
16551#[no_mangle]
16552pub unsafe extern "C" fn erff(x: f32) -> f32 {
16553 libm::erff(x)
16554}
16555
16556#[no_mangle]
16557pub unsafe extern "C" fn erfcf(x: f32) -> f32 {
16558 libm::erfcf(x)
16559}
16560
16561#[no_mangle]
16562pub unsafe extern "C" fn lgammaf(x: f32) -> f32 {
16563 if x.is_nan() {
16564 crate::signgam = 1;
16565 return x;
16566 }
16567 if x == 0.0 {
16568 crate::signgam = if x.is_sign_negative() { -1 } else { 1 };
16569 feraiseexcept(FE_DIVBYZERO);
16570 return f32::INFINITY;
16571 }
16572 let (r, sign) = libm::lgammaf_r(x);
16573 crate::signgam = sign;
16574 r
16575}
16576
16577#[no_mangle]
16578pub unsafe extern "C" fn tgammaf(x: f32) -> f32 {
16579 if x.is_nan() { return x; }
16580 if x == 0.0 {
16581 feraiseexcept(FE_DIVBYZERO);
16582 return if x.is_sign_negative() { f32::NEG_INFINITY } else { f32::INFINITY };
16583 }
16584 if x.is_infinite() {
16585 return if x.is_sign_negative() { __math_invalidf(x) } else { f32::INFINITY };
16586 }
16587 if x < 0.0 && x == libm::floorf(x) {
16588 feraiseexcept(FE_INVALID);
16589 return f32::NAN;
16590 }
16591 libm::tgammaf(x)
16592}
16593
16594#[no_mangle]
16595pub unsafe extern "C" fn lroundf(x: f32) -> core::ffi::c_long {
16596 libm::roundf(x) as core::ffi::c_long
16597}
16598
16599#[no_mangle]
16600pub unsafe extern "C" fn llroundf(x: f32) -> i64 {
16601 libm::roundf(x) as i64
16602}
16603
16604#[no_mangle]
16609pub unsafe extern "C" fn wcscasecmp(s1: *const u32, s2: *const u32) -> i32 {
16610 let mut i = 0;
16611 loop {
16612 let c1 = *s1.add(i);
16613 let c2 = *s2.add(i);
16614 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16615 let l1 = if c1 >= 'A' as u32 && c1 <= 'Z' as u32 { c1 + 32 } else { c1 };
16616 let l2 = if c2 >= 'A' as u32 && c2 <= 'Z' as u32 { c2 + 32 } else { c2 };
16617 if l1 != l2 { return (l1 as i32) - (l2 as i32); }
16618 i += 1;
16619 }
16620}
16621
16622#[no_mangle]
16623pub unsafe extern "C" fn wcscasecmp_l(s1: *const u32, s2: *const u32, _loc: *mut core::ffi::c_void) -> i32 {
16624 wcscasecmp(s1, s2)
16625}
16626
16627#[no_mangle]
16628pub unsafe extern "C" fn wcsncasecmp(s1: *const u32, s2: *const u32, n: usize) -> i32 {
16629 let mut i = 0;
16630 while i < n {
16631 let c1 = *s1.add(i);
16632 let c2 = *s2.add(i);
16633 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16634 let l1 = if c1 >= 'A' as u32 && c1 <= 'Z' as u32 { c1 + 32 } else { c1 };
16635 let l2 = if c2 >= 'A' as u32 && c2 <= 'Z' as u32 { c2 + 32 } else { c2 };
16636 if l1 != l2 { return (l1 as i32) - (l2 as i32); }
16637 i += 1;
16638 }
16639 0
16640}
16641
16642#[no_mangle]
16643pub unsafe extern "C" fn wcsncasecmp_l(s1: *const u32, s2: *const u32, n: usize, _loc: *mut core::ffi::c_void) -> i32 {
16644 wcsncasecmp(s1, s2, n)
16645}
16646
16647#[no_mangle]
16648pub unsafe extern "C" fn wcscoll(s1: *const u32, s2: *const u32) -> i32 {
16649 let mut i = 0;
16651 loop {
16652 let c1 = *s1.add(i);
16653 let c2 = *s2.add(i);
16654 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
16655 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
16656 i += 1;
16657 }
16658}
16659
16660#[no_mangle]
16661pub unsafe extern "C" fn wcstok(s: *mut u32, sep: *const u32, p: *mut *mut u32) -> *mut u32 {
16662 let mut src = if s.is_null() { *p } else { s };
16663 while *src != 0 && *sep.add(0) == *src { src = src.add(1); }
16665 if *src == 0 { return core::ptr::null_mut(); }
16666 let start = src;
16667 while *src != 0 && *sep.add(0) != *src { src = src.add(1); }
16669 if *src != 0 {
16670 *src = 0;
16671 *p = src.add(1);
16672 } else {
16673 *p = src;
16674 }
16675 start
16676}
16677
16678#[no_mangle]
16679pub unsafe extern "C" fn wcswcs(haystack: *const u32, needle: *const u32) -> *mut u32 {
16680 if *needle == 0 { return haystack as *mut u32; }
16681 let mut i = 0;
16682 while *haystack.add(i) != 0 {
16683 let mut j = 0;
16684 while *needle.add(j) != 0 && *haystack.add(i + j) == *needle.add(j) {
16685 j += 1;
16686 }
16687 if *needle.add(j) == 0 { return haystack.add(i) as *mut u32; }
16688 i += 1;
16689 }
16690 core::ptr::null_mut()
16691}
16692
16693#[no_mangle]
16694pub unsafe extern "C" fn wcswidth(s: *const u32, n: usize) -> i32 {
16695 let mut width = 0i32;
16696 let mut i = 0;
16697 while i < n {
16698 let c = *s.add(i);
16699 if c == 0 { break; }
16700 width += 1;
16702 i += 1;
16703 }
16704 width
16705}
16706
16707#[no_mangle]
16708pub unsafe extern "C" fn wcsftime(s: *mut u32, maxsize: usize, fmt: *const u32, tm: *const c_void) -> usize {
16709 if s.is_null() || fmt.is_null() || maxsize == 0 { return 0; }
16710 let mut cfmt = [0u8; 1024];
16713 let mut o = 0usize;
16714 let mut i = 0usize;
16715 let mut st: c_uint = 0;
16716 while *fmt.add(i) != 0 && o + 8 < cfmt.len() {
16717 let n = wcrtomb(
16718 cfmt.as_mut_ptr().add(o) as *mut c_char,
16719 *fmt.add(i) as c_int,
16720 &mut st as *mut c_uint,
16721 );
16722 if n == !0usize { return 0; }
16723 o += n;
16724 i += 1;
16725 }
16726 cfmt[o] = 0;
16727 let mut out = [0u8; 4096];
16728 let mut lim = maxsize.saturating_mul(4);
16729 if lim > out.len() { lim = out.len(); }
16730 let n = strftime(out.as_mut_ptr() as *mut c_char, lim, cfmt.as_ptr() as *const c_char, tm as *const tm);
16731 if n == 0 { return 0; }
16732 let mut ws = 0usize;
16733 let mut p = 0usize;
16734 while p < n && ws + 1 < maxsize {
16735 let mut wc: c_int = 0;
16736 let mut st2: c_uint = 0;
16737 let r = mbrtowc(&mut wc, out.as_ptr().add(p) as *const c_char, n - p, &mut st2);
16738 if r == !0usize { return 0; }
16739 if r == 0 || r == !1usize { break; }
16740 *s.add(ws) = wc as u32;
16741 ws += 1;
16742 p += r;
16743 }
16744 *s.add(ws) = 0;
16745 ws
16746}
16747
16748#[no_mangle]
16749pub unsafe extern "C" fn mbsnrtowcs(
16750 dst: *mut u32,
16751 src: *mut *const u8,
16752 nms: usize,
16753 len: usize,
16754 st: *mut core::ffi::c_void,
16755) -> usize {
16756 if src.is_null() { return 0; }
16757 let mut s = *src;
16758 if s.is_null() { return 0; }
16759 let state = st as *mut c_uint;
16760 let limit = if dst.is_null() { usize::MAX } else { len };
16761 let mut count = 0usize;
16762 let mut n = nms;
16763 while count < limit && n > 0 {
16764 let c = *s;
16765 if c == 0 {
16766 if !dst.is_null() {
16767 if count < len { *dst.add(count) = 0; }
16768 *src = core::ptr::null();
16769 }
16770 return count;
16771 }
16772 let mut wc: c_int = 0;
16773 let r = mbrtowc(&mut wc, s as *const c_char, n, state);
16774 if r == !0usize {
16775 *src = s;
16776 return !0usize;
16777 }
16778 if r == !1usize { break; }
16779 if !dst.is_null() { *dst.add(count) = wc as u32; }
16780 count += 1;
16781 s = s.add(r);
16782 n -= r;
16783 }
16784 *src = s;
16785 count
16786}
16787
16788#[no_mangle]
16789pub unsafe extern "C" fn wcsnrtombs(dst: *mut u8, src: *mut *const u32, nwc: usize, len: usize, _st: *mut core::ffi::c_void) -> usize {
16790 let mut count = 0;
16791 let mut s = *src;
16792 let mut d = dst;
16793 while count < len && count < nwc {
16794 let c = *s;
16795 if c == 0 { break; }
16796 if !d.is_null() {
16797 if c < 0x80 {
16798 *d = c as u8;
16799 d = d.add(1);
16800 count += 1;
16801 } else if c < 0x800 {
16802 if count + 2 > len { break; }
16803 *d = 0xc0 | (c >> 6) as u8;
16804 *d.add(1) = 0x80 | (c & 0x3f) as u8;
16805 d = d.add(2);
16806 count += 2;
16807 } else if c < 0x10000 {
16808 if count + 3 > len { break; }
16809 *d = 0xe0 | (c >> 12) as u8;
16810 *d.add(1) = 0x80 | ((c >> 6) & 0x3f) as u8;
16811 *d.add(2) = 0x80 | (c & 0x3f) as u8;
16812 d = d.add(3);
16813 count += 3;
16814 } else {
16815 if count + 4 > len { break; }
16816 *d = 0xf0 | (c >> 18) as u8;
16817 *d.add(1) = 0x80 | ((c >> 12) & 0x3f) as u8;
16818 *d.add(2) = 0x80 | ((c >> 6) & 0x3f) as u8;
16819 *d.add(3) = 0x80 | (c & 0x3f) as u8;
16820 d = d.add(4);
16821 count += 4;
16822 }
16823 }
16824 s = s.add(1);
16825 }
16826 if !dst.is_null() { *src = s; }
16827 count
16828}
16829
16830pub type thrd_start_t = Option<unsafe extern "C" fn(arg: *mut core::ffi::c_void) -> i32>;
16837
16838#[no_mangle]
16840pub unsafe extern "C" fn thrd_create(thr: *mut usize, func: thrd_start_t, arg: *mut core::ffi::c_void) -> i32 {
16841 let mut thread: u64 = 0;
16842 let r = pthread_create(&mut thread, core::ptr::null(), core::mem::transmute(func), arg);
16843 if r == 0 {
16844 *thr = thread as usize;
16845 0 } else {
16847 -1 }
16849}
16850
16851#[no_mangle]
16852pub unsafe extern "C" fn thrd_join(thr: usize, res: *mut i32) -> i32 {
16853 let mut retval: *mut core::ffi::c_void = core::ptr::null_mut();
16854 let r = pthread_join(thr as u64, &mut retval);
16855 if r == 0 {
16856 if !res.is_null() { *res = retval as i32; }
16857 0
16858 } else {
16859 -1
16860 }
16861}
16862
16863#[no_mangle]
16864pub unsafe extern "C" fn thrd_exit(res: i32) {
16865 pthread_exit(res as *mut core::ffi::c_void);
16866}
16867
16868#[no_mangle]
16869pub unsafe extern "C" fn thrd_detach(thr: usize) -> i32 {
16870 let r = pthread_detach(thr as u64);
16871 if r == 0 { 0 } else { -1 }
16872}
16873
16874#[no_mangle]
16875pub unsafe extern "C" fn thrd_current() -> usize {
16876 pthread_self() as usize
16877}
16878
16879#[no_mangle]
16880pub unsafe extern "C" fn thrd_equal(thr1: usize, thr2: usize) -> i32 {
16881 (thr1 == thr2) as i32
16882}
16883
16884#[no_mangle]
16885pub unsafe extern "C" fn thrd_sleep(duration: *const core::ffi::c_void, remaining: *mut core::ffi::c_void) -> i32 {
16886 nanosleep(duration as *const timespec, remaining as *mut timespec)
16887}
16888
16889#[no_mangle]
16890pub unsafe extern "C" fn thrd_yield() {
16891 sched_yield();
16892}
16893
16894#[no_mangle]
16896pub unsafe extern "C" fn mtx_init(mtx: *mut usize, _mtx_type: i32) -> i32 {
16897 let r = pthread_mutex_init(mtx as *mut pthread_mutex_t, core::ptr::null());
16898 if r == 0 { 0 } else { -1 }
16899}
16900
16901#[no_mangle]
16902pub unsafe extern "C" fn mtx_lock(mtx: *mut usize) -> i32 {
16903 let r = pthread_mutex_lock(mtx as *mut pthread_mutex_t);
16904 if r == 0 { 0 } else { -1 }
16905}
16906
16907#[no_mangle]
16908pub unsafe extern "C" fn mtx_trylock(mtx: *mut usize) -> i32 {
16909 let r = pthread_mutex_trylock(mtx as *mut pthread_mutex_t);
16910 if r == 0 { 0 } else { -1 }
16911}
16912
16913#[no_mangle]
16914pub unsafe extern "C" fn mtx_unlock(mtx: *mut usize) -> i32 {
16915 let r = pthread_mutex_unlock(mtx as *mut pthread_mutex_t);
16916 if r == 0 { 0 } else { -1 }
16917}
16918
16919#[no_mangle]
16920pub unsafe extern "C" fn mtx_destroy(mtx: *mut usize) {
16921 pthread_mutex_destroy(mtx as *mut pthread_mutex_t);
16922}
16923
16924#[no_mangle]
16925pub unsafe extern "C" fn mtx_timedlock(mtx: *mut usize, ts: *const core::ffi::c_void) -> i32 {
16926 let r = pthread_mutex_timedlock(mtx as *mut pthread_mutex_t, ts as *const timespec);
16927 if r == 0 { 0 } else { -1 }
16928}
16929
16930#[no_mangle]
16932pub unsafe extern "C" fn cnd_init(cnd: *mut usize) -> i32 {
16933 let r = pthread_cond_init(cnd as *mut pthread_cond_t, core::ptr::null());
16934 if r == 0 { 0 } else { -1 }
16935}
16936
16937#[no_mangle]
16938pub unsafe extern "C" fn cnd_signal(cnd: *mut usize) -> i32 {
16939 let r = pthread_cond_signal(cnd as *mut pthread_cond_t);
16940 if r == 0 { 0 } else { -1 }
16941}
16942
16943#[no_mangle]
16944pub unsafe extern "C" fn cnd_broadcast(cnd: *mut usize) -> i32 {
16945 let r = pthread_cond_broadcast(cnd as *mut pthread_cond_t);
16946 if r == 0 { 0 } else { -1 }
16947}
16948
16949#[no_mangle]
16950pub unsafe extern "C" fn cnd_wait(cnd: *mut usize, mtx: *mut usize) -> i32 {
16951 let r = pthread_cond_wait(cnd as *mut pthread_cond_t, mtx as *mut pthread_mutex_t);
16952 if r == 0 { 0 } else { -1 }
16953}
16954
16955#[no_mangle]
16956pub unsafe extern "C" fn cnd_timedwait(cnd: *mut usize, mtx: *mut usize, ts: *const core::ffi::c_void) -> i32 {
16957 let r = pthread_cond_timedwait(cnd as *mut pthread_cond_t, mtx as *mut pthread_mutex_t, ts as *const timespec);
16958 if r == 0 { 0 } else { -1 }
16959}
16960
16961#[no_mangle]
16962pub unsafe extern "C" fn cnd_destroy(cnd: *mut usize) {
16963 pthread_cond_destroy(cnd as *mut pthread_cond_t);
16964}
16965
16966#[no_mangle]
16968pub unsafe extern "C" fn tss_create(key: *mut u32, dtor: Option<unsafe extern "C" fn(*mut core::ffi::c_void)>) -> i32 {
16969 let r = pthread_key_create(key, dtor);
16970 if r == 0 { 0 } else { -1 }
16971}
16972
16973#[no_mangle]
16974pub unsafe extern "C" fn tss_delete(key: u32) {
16975 pthread_key_delete(key);
16976}
16977
16978#[no_mangle]
16979pub unsafe extern "C" fn tss_set(key: u32, val: *mut core::ffi::c_void) -> i32 {
16980 let r = pthread_setspecific(key, val);
16981 if r == 0 { 0 } else { -1 }
16982}
16983
16984#[no_mangle]
16985pub unsafe extern "C" fn tss_get(key: u32) -> *mut core::ffi::c_void {
16986 pthread_getspecific(key)
16987}
16988
16989#[no_mangle]
16991pub unsafe extern "C" fn call_once(flag: *mut u32, func: Option<unsafe extern "C" fn()>) {
16992 if *flag == 0 {
16993 if let Some(f) = func { f(); }
16994 *flag = 1;
16995 }
16996}
16997
16998#[no_mangle]
17004pub unsafe extern "C" fn accept4(fd: i32, addr: *mut core::ffi::c_void, addrlen: *mut u32, flags: i32) -> i32 {
17005 syscall_ret(<Arch as Syscalls>::syscall4(SYS_ACCEPT4, fd as i64, addr as i64, addrlen as i64, flags as i64)) as i32
17006}
17007
17008#[no_mangle]
17014pub unsafe extern "C" fn epoll_create(size: i32) -> i32 {
17015 #[cfg(target_arch = "x86_64")]
17016 { syscall_ret(<Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE, size as i64)) as i32 }
17017 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
17018 {
17019 if size < 1 {
17020 ERRNO!() = EINVAL;
17021 return -1;
17022 }
17023 syscall_ret(<Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE1, 0)) as i32
17024 }
17025}
17026
17027#[no_mangle]
17028pub unsafe extern "C" fn epoll_create1(flags: i32) -> i32 {
17029 syscall_ret(<Arch as Syscalls>::syscall1(SYS_EPOLL_CREATE1, flags as i64)) as i32
17030}
17031
17032#[no_mangle]
17033pub unsafe extern "C" fn epoll_ctl(epfd: i32, op: i32, fd: i32, event: *mut core::ffi::c_void) -> i32 {
17034 syscall_ret(<Arch as Syscalls>::syscall4(SYS_EPOLL_CTL, epfd as i64, op as i64, fd as i64, event as i64)) as i32
17035}
17036
17037#[no_mangle]
17038pub unsafe extern "C" fn epoll_wait(epfd: i32, events: *mut core::ffi::c_void, maxevents: i32, timeout: i32) -> i32 {
17039 #[cfg(target_arch = "x86_64")]
17040 {
17041 syscall_ret(<Arch as Syscalls>::syscall4(
17042 SYS_EPOLL_WAIT,
17043 epfd as i64,
17044 events as i64,
17045 maxevents as i64,
17046 timeout as i64,
17047 )) as i32
17048 }
17049 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
17050 {
17051 epoll_pwait(epfd, events, maxevents, timeout, core::ptr::null())
17052 }
17053}
17054
17055#[no_mangle]
17056pub unsafe extern "C" fn epoll_pwait(
17057 epfd: i32,
17058 events: *mut core::ffi::c_void,
17059 maxevents: i32,
17060 timeout: i32,
17061 sigmask: *const u64,
17062) -> i32 {
17063 syscall_ret(<Arch as Syscalls>::syscall6(
17064 SYS_EPOLL_PWAIT,
17065 epfd as i64,
17066 events as i64,
17067 maxevents as i64,
17068 timeout as i64,
17069 sigmask as i64,
17070 8,
17071 )) as i32
17072}
17073
17074#[no_mangle]
17075pub unsafe extern "C" fn eventfd(initval: u32, flags: i32) -> i32 {
17076 syscall_ret(<Arch as Syscalls>::syscall2(SYS_EVENTFD2, initval as i64, flags as i64)) as i32
17077}
17078
17079#[no_mangle]
17080pub unsafe extern "C" fn eventfd_read(fd: i32, value: *mut u64) -> i32 {
17081 let n = crate::read(fd, value as *mut core::ffi::c_void, 8);
17082 if n == 8 { 0 } else { -1 }
17083}
17084
17085#[no_mangle]
17086pub unsafe extern "C" fn eventfd_write(fd: i32, value: u64) -> i32 {
17087 let n = crate::write(fd, &value as *const u64 as *const core::ffi::c_void, 8);
17088 if n == 8 { 0 } else { -1 }
17089}
17090
17091#[no_mangle]
17092pub unsafe extern "C" fn signalfd(fd: i32, mask: *const u64, flags: i32) -> i32 {
17093 syscall_ret(<Arch as Syscalls>::syscall4(SYS_SIGNALFD4, fd as i64, mask as i64, 8, flags as i64)) as i32
17094}
17095
17096#[no_mangle]
17097pub unsafe extern "C" fn timerfd_create(clockid: i32, flags: i32) -> i32 {
17098 syscall_ret(<Arch as Syscalls>::syscall2(SYS_TIMERFD_CREATE, clockid as i64, flags as i64)) as i32
17099}
17100
17101#[no_mangle]
17102pub 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 {
17103 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
17104}
17105
17106#[no_mangle]
17107pub unsafe extern "C" fn timerfd_gettime(fd: i32, curr_value: *mut core::ffi::c_void) -> i32 {
17108 syscall_ret(<Arch as Syscalls>::syscall2(SYS_TIMERFD_GETTIME, fd as i64, curr_value as i64)) as i32
17109}
17110
17111#[no_mangle]
17116pub unsafe extern "C" fn prctl(option: i32, mut args: ...) -> i32 {
17117 let a1 = args.next_arg::<i64>();
17118 let a2 = args.next_arg::<i64>();
17119 let a3 = args.next_arg::<i64>();
17120 let a4 = args.next_arg::<i64>();
17121 syscall_ret(<Arch as Syscalls>::syscall5(SYS_PRCTL, option as i64, a1, a2, a3, a4)) as i32
17122}
17123
17124#[no_mangle]
17125pub unsafe extern "C" fn quotactl(cmd: i32, special: *const core::ffi::c_char, id: i32, addr: *mut core::ffi::c_char) -> i32 {
17126 syscall_ret(<Arch as Syscalls>::syscall4(sysno(179, 60), cmd as i64, special as i64, id as i64, addr as i64)) as i32
17127}
17128
17129#[no_mangle]
17130pub unsafe extern "C" fn klogctl(type_: i32, bufp: *mut core::ffi::c_char, len: i32) -> i32 {
17131 syscall_ret(<Arch as Syscalls>::syscall3(sysno(103, 116), type_ as i64, bufp as i64, len as i64)) as i32
17132}
17133
17134static mut SYSLOG_IDENT: [core::ffi::c_char; 64] = [0; 64];
17135static mut SYSLOG_OPTIONS: i32 = 0;
17136static mut SYSLOG_FACILITY: i32 = 1;
17137
17138#[no_mangle]
17139pub unsafe extern "C" fn openlog(ident: *const core::ffi::c_char, option: i32, facility: i32) {
17140 SYSLOG_OPTIONS = option;
17141 SYSLOG_FACILITY = facility & 0x3f8;
17142 SYSLOG_IDENT[0] = 0;
17143 if !ident.is_null() {
17144 let mut i = 0;
17145 while i < 63 && *ident.add(i) != 0 {
17146 SYSLOG_IDENT[i] = *ident.add(i);
17147 i += 1;
17148 }
17149 SYSLOG_IDENT[i] = 0;
17150 }
17151}
17152
17153#[repr(C)]
17154struct SockAddrUn {
17155 sun_family: u16,
17156 sun_path: [core::ffi::c_char; 108],
17157}
17158
17159unsafe fn syslog_emit(priority: i32, msg: *const core::ffi::c_char, len: usize) {
17160 let mut out = [0u8; 1200];
17161 let mut o = 0usize;
17162 let pri = (SYSLOG_FACILITY | (priority & 7)) as u32;
17163 out[o] = b'<'; o += 1;
17164 if pri >= 100 { out[o] = b'0' + (pri / 100) as u8; o += 1; }
17165 if pri >= 10 { out[o] = b'0' + ((pri / 10) % 10) as u8; o += 1; }
17166 out[o] = b'0' + (pri % 10) as u8; o += 1;
17167 out[o] = b'>'; o += 1;
17168 let mut i = 0;
17169 while i < 63 && SYSLOG_IDENT[i] != 0 && o + 1 < out.len() {
17170 out[o] = SYSLOG_IDENT[i] as u8; o += 1; i += 1;
17171 }
17172 if SYSLOG_OPTIONS & 1 != 0 {
17173 out[o] = b'['; o += 1;
17174 let mut pid = crate::getpid() as u32;
17175 let mut digits = [0u8; 10];
17176 let mut d = 0;
17177 if pid == 0 { digits[0] = b'0'; d = 1; }
17178 while pid > 0 { digits[d] = b'0' + (pid % 10) as u8; pid /= 10; d += 1; }
17179 while d > 0 { d -= 1; out[o] = digits[d]; o += 1; }
17180 out[o] = b']'; o += 1;
17181 }
17182 out[o] = b':'; o += 1; out[o] = b' '; o += 1;
17183 let copy = core::cmp::min(len, out.len() - o - 1);
17184 core::ptr::copy_nonoverlapping(msg as *const u8, out.as_mut_ptr().add(o), copy);
17185 o += copy;
17186 let fd = crate::socket(AF_UNIX, SOCK_DGRAM, 0);
17187 if fd >= 0 {
17188 let mut sa: SockAddrUn = core::mem::zeroed();
17189 sa.sun_family = AF_UNIX as u16;
17190 let path = b"/dev/log";
17191 for i in 0..path.len() { sa.sun_path[i] = path[i] as core::ffi::c_char; }
17192 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);
17193 crate::close(fd);
17194 if r >= 0 { return; }
17195 }
17196 crate::write(2, out.as_ptr() as *const core::ffi::c_void, o);
17197 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
17198}
17199
17200#[no_mangle]
17201pub unsafe extern "C" fn vsyslog(priority: c_int, fmt: *const c_char, ap: VaList) {
17202 let mut msg = [0 as c_char; 1024];
17203 let n = vsnprintf(msg.as_mut_ptr(), msg.len(), fmt, ap);
17204 if n > 0 { syslog_emit(priority, msg.as_ptr(), core::cmp::min(n as usize, msg.len() - 1)); }
17205}
17206
17207#[no_mangle]
17208pub unsafe extern "C" fn syslog(priority: c_int, fmt: *const c_char, args: ...) {
17209 vsyslog(priority, fmt, args);
17210}
17211
17212#[no_mangle]
17213pub unsafe extern "C" fn closelog() {
17214 }
17216
17217#[no_mangle]
17218pub unsafe extern "C" fn setlogmask(mask: i32) -> i32 {
17219 static mut LOG_MASK: i32 = 0x01 | 0x02 | 0x04 | 0x08 | 0x10 | 0x20 | 0x40 | 0x80;
17220 let old = LOG_MASK;
17221 if mask != 0 { LOG_MASK = mask; }
17222 old
17223}
17224
17225#[no_mangle]
17226pub unsafe extern "C" fn acct(filename: *const core::ffi::c_char) -> i32 {
17227 syscall_ret(<Arch as Syscalls>::syscall1(SYS_ACCT, filename as i64)) as i32
17228}
17229
17230#[no_mangle]
17231pub unsafe extern "C" fn swapon(path: *const core::ffi::c_char, flags: i32) -> i32 {
17232 syscall_ret(<Arch as Syscalls>::syscall2(SYS_SWAPON, path as i64, flags as i64)) as i32
17233}
17234
17235#[no_mangle]
17236pub unsafe extern "C" fn swapoff(path: *const core::ffi::c_char) -> i32 {
17237 syscall_ret(<Arch as Syscalls>::syscall1(SYS_SWAPOFF, path as i64)) as i32
17238}
17239
17240#[no_mangle]
17241pub unsafe extern "C" fn syncfs(fd: i32) -> i32 {
17242 syscall_ret(<Arch as Syscalls>::syscall1(SYS_SYNCFS, fd as i64)) as i32
17243}
17244
17245#[no_mangle]
17246pub unsafe extern "C" fn sync_file_range(fd: i32, offset: i64, nbytes: u64, flags: u32) -> i32 {
17247 syscall_ret(<Arch as Syscalls>::syscall4(sysno(277, 84), fd as i64, offset, nbytes as i64, flags as i64)) as i32
17248}
17249
17250#[no_mangle]
17251pub unsafe extern "C" fn posix_fadvise(fd: i32, offset: i64, len: u64, advice: i32) -> i32 {
17252 let r = <Arch as Syscalls>::syscall4(sysno(221, 223), fd as i64, offset, len as i64, advice as i64);
17254 if r < 0 { (-r) as i32 } else { 0 }
17255}
17256
17257#[no_mangle]
17258pub unsafe extern "C" fn posix_fallocate(fd: i32, offset: i64, len: u64) -> i32 {
17259 let r = <Arch as Syscalls>::syscall3(SYS_FALLOCATE, fd as i64, offset, len as i64);
17260 if r < 0 { (-r) as i32 } else { 0 }
17261}
17262
17263#[no_mangle]
17264pub unsafe extern "C" fn readahead(fd: i32, offset: i64, count: usize) -> isize {
17265 syscall_ret(<Arch as Syscalls>::syscall3(sysno(187, 213), fd as i64, offset, count as i64)) as isize
17268}
17269
17270#[no_mangle]
17271pub unsafe extern "C" fn fallocate(fd: i32, mode: i32, offset: i64, len: u64) -> i32 {
17272 syscall_ret(<Arch as Syscalls>::syscall4(SYS_FALLOCATE, fd as i64, mode as i64, offset, len as i64)) as i32
17273}
17274
17275#[no_mangle]
17280pub unsafe extern "C" fn tcgetattr(fd: i32, termios_p: *mut core::ffi::c_void) -> i32 {
17281 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5401, termios_p as i64)) as i32
17282}
17283
17284#[no_mangle]
17285pub unsafe extern "C" fn tcsetattr(fd: i32, optional_actions: i32, termios_p: *const core::ffi::c_void) -> i32 {
17286 let cmd = match optional_actions {
17287 0 => 0x5402,
17288 1 => 0x5403,
17289 2 => 0x5404,
17290 _ => 0x5402,
17291 };
17292 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, cmd, termios_p as i64)) as i32
17293}
17294
17295#[no_mangle]
17296pub unsafe extern "C" fn tcdrain(fd: i32) -> i32 {
17297 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5409, 1)) as i32
17298}
17299
17300#[no_mangle]
17301pub unsafe extern "C" fn tcflush(fd: i32, queue_selector: i32) -> i32 {
17302 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540B, queue_selector as i64)) as i32
17303}
17304
17305#[no_mangle]
17306pub unsafe extern "C" fn tcflow(fd: i32, action: i32) -> i32 {
17307 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540A, action as i64)) as i32
17308}
17309
17310#[no_mangle]
17311pub unsafe extern "C" fn tcsendbreak(fd: i32, duration: i32) -> i32 {
17312 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5425, duration as i64)) as i32
17313}
17314
17315#[no_mangle]
17316pub unsafe extern "C" fn tcgetsid(fd: i32) -> i32 {
17317 let mut sid: i32 = 0;
17318 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5429, &mut sid as *mut i32 as i64);
17319 if r < 0 { -1 } else { sid }
17320}
17321
17322#[no_mangle]
17323pub unsafe extern "C" fn tcgetpgrp(fd: i32) -> i32 {
17324 let mut pgrp: i32 = 0;
17325 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x540F, &mut pgrp as *mut i32 as i64);
17326 if r < 0 { -1 } else { pgrp }
17327}
17328
17329#[no_mangle]
17330pub unsafe extern "C" fn tcsetpgrp(fd: i32, pgrp: i32) -> i32 {
17331 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5410, &pgrp as *const i32 as i64)) as i32
17332}
17333
17334#[no_mangle]
17345pub unsafe extern "C" fn mq_open(name: *const core::ffi::c_char, oflag: i32, mut args: ...) -> i32 {
17346 if name.is_null() { ERRNO!() = EINVAL; return -1; }
17347 let mut p = name as *const u8;
17348 if *p == b'/' { p = p.add(1); }
17349 let mut mode: u32 = 0;
17350 let mut attr: *const core::ffi::c_void = core::ptr::null();
17351 if oflag & 0o100 != 0 {
17352 mode = args.next_arg::<u32>();
17353 attr = args.next_arg::<*const core::ffi::c_void>();
17354 }
17355 syscall_ret(<Arch as Syscalls>::syscall4(
17356 sysno(240, 180),
17357 p as i64,
17358 oflag as i64,
17359 mode as i64,
17360 attr as i64,
17361 )) as i32
17362}
17363
17364#[no_mangle]
17365pub unsafe extern "C" fn mq_close(mqdes: i32) -> i32 {
17366 crate::close(mqdes as i32)
17367}
17368
17369#[no_mangle]
17370pub unsafe extern "C" fn mq_unlink(name: *const core::ffi::c_char) -> i32 {
17371 if name.is_null() { ERRNO!() = EINVAL; return -1; }
17372 let mut p = name as *const u8;
17373 if *p == b'/' { p = p.add(1); }
17374 let r = <Arch as Syscalls>::syscall1(sysno(241, 181), p as i64);
17375 if r < 0 {
17376 let e = if (-r) as c_int == 1 { 13 } else { (-r) as c_int };
17378 ERRNO!() = e;
17379 -1
17380 } else {
17381 0
17382 }
17383}
17384
17385#[no_mangle]
17386pub unsafe extern "C" fn mq_send(mqdes: i32, msg_ptr: *const core::ffi::c_char, msg_len: usize, msg_prio: u32) -> i32 {
17387 mq_timedsend(mqdes, msg_ptr, msg_len, msg_prio, core::ptr::null())
17388}
17389
17390#[no_mangle]
17391pub unsafe extern "C" fn mq_receive(mqdes: i32, msg_ptr: *mut core::ffi::c_char, msg_len: usize, msg_prio: *mut u32) -> isize {
17392 mq_timedreceive(mqdes, msg_ptr, msg_len, msg_prio, core::ptr::null())
17393}
17394
17395#[no_mangle]
17396pub unsafe extern "C" fn mq_timedsend(
17397 mqdes: i32,
17398 msg_ptr: *const core::ffi::c_char,
17399 msg_len: usize,
17400 msg_prio: u32,
17401 abs_timeout: *const core::ffi::c_void,
17402) -> i32 {
17403 syscall_ret(<Arch as Syscalls>::syscall5(
17404 sysno(242, 182),
17405 mqdes as i64,
17406 msg_ptr as i64,
17407 msg_len as i64,
17408 msg_prio as i64,
17409 abs_timeout as i64,
17410 )) as i32
17411}
17412
17413#[no_mangle]
17414pub unsafe extern "C" fn mq_timedreceive(
17415 mqdes: i32,
17416 msg_ptr: *mut core::ffi::c_char,
17417 msg_len: usize,
17418 msg_prio: *mut u32,
17419 abs_timeout: *const core::ffi::c_void,
17420) -> isize {
17421 syscall_ret(<Arch as Syscalls>::syscall5(
17422 sysno(243, 183),
17423 mqdes as i64,
17424 msg_ptr as i64,
17425 msg_len as i64,
17426 msg_prio as i64,
17427 abs_timeout as i64,
17428 )) as isize
17429}
17430
17431#[repr(C)]
17432pub struct SigEventFull {
17433 sigev_value: usize,
17434 sigev_signo: i32,
17435 sigev_notify: i32,
17436 sigev_function: usize,
17437 sigev_attributes: usize,
17438 sigev_pad: [u8; 32],
17439}
17440
17441struct MqNotifyArgs {
17442 sem: sem_t,
17443 sock: i32,
17444 mqd: i32,
17445 err: i32,
17446 func: usize,
17447 value: usize,
17448}
17449
17450unsafe extern "C" fn mq_notify_thread(arg: *mut c_void) -> *mut c_void {
17451 let a = &mut *(arg as *mut MqNotifyArgs);
17452 let sock = a.sock;
17453 let mqd = a.mqd;
17454 let func = a.func;
17455 let value = a.value;
17456 let zeros = [0u8; 32];
17457 let sev2 = SigEventFull {
17458 sigev_value: zeros.as_ptr() as usize,
17459 sigev_signo: sock,
17460 sigev_notify: 2, sigev_function: 0,
17462 sigev_attributes: 0,
17463 sigev_pad: [0; 32],
17464 };
17465 let r = <Arch as Syscalls>::syscall2(sysno(244, 184), mqd as i64, &sev2 as *const SigEventFull as i64);
17466 a.err = if r < 0 { (-r) as i32 } else { 0 };
17467 sem_post(&mut a.sem);
17468 if a.err != 0 { return core::ptr::null_mut(); }
17469 pthread_detach(pthread_self());
17470 let mut buf = [0u8; 32];
17471 let n = recv(sock, buf.as_mut_ptr() as *mut c_void, buf.len(), 0x4000 | 0x100);
17472 crate::close(sock);
17473 if n as usize == buf.len() && buf[buf.len() - 1] == 1 && func != 0 {
17474 let f: extern "C" fn(usize) = core::mem::transmute(func);
17475 f(value);
17476 }
17477 core::ptr::null_mut()
17478}
17479
17480#[no_mangle]
17481pub unsafe extern "C" fn mq_notify(mqdes: i32, sev: *const core::ffi::c_void) -> i32 {
17482 if sev.is_null() {
17483 return syscall_ret(<Arch as Syscalls>::syscall2(sysno(244, 184), mqdes as i64, 0)) as i32;
17484 }
17485 let ev = &*(sev as *const SigEventFull);
17486 if ev.sigev_notify != 2 {
17487 return syscall_ret(<Arch as Syscalls>::syscall2(sysno(244, 184), mqdes as i64, sev as i64)) as i32;
17488 }
17489
17490 let sock = socket(16 , 3 | 0x80000 , 0);
17493 if sock < 0 { return -1; }
17494 let mut a = MqNotifyArgs {
17495 sem: core::mem::zeroed(),
17496 sock,
17497 mqd: mqdes,
17498 err: 0,
17499 func: ev.sigev_function,
17500 value: ev.sigev_value,
17501 };
17502 sem_init(&mut a.sem, 0, 0);
17503
17504 let mut attr: pthread_attr_t = core::mem::zeroed();
17505 if ev.sigev_attributes != 0 {
17506 attr = core::ptr::read(ev.sigev_attributes as *const pthread_attr_t);
17507 } else {
17508 pthread_attr_init(&mut attr);
17509 }
17510 pthread_attr_setdetachstate(&mut attr, PTHREAD_CREATE_JOINABLE);
17511
17512 let mut all: SigSetT = 0;
17513 sigfillset(&mut all);
17514 let mut orig: SigSetT = 0;
17515 pthread_sigmask(0 , &all, &mut orig);
17516
17517 let mut td: PthreadT = 0;
17518 let r = pthread_create(&mut td, &attr, mq_notify_thread as *const () as usize, &mut a as *mut MqNotifyArgs as *mut c_void);
17519 pthread_sigmask(2 , &orig, core::ptr::null_mut());
17520 if r != 0 {
17521 crate::close(sock);
17522 ERRNO!() = 11;
17523 return -1;
17524 }
17525 sem_wait(&mut a.sem);
17526 sem_destroy(&mut a.sem);
17527 if a.err != 0 {
17528 crate::close(sock);
17529 pthread_join(td, core::ptr::null_mut());
17530 ERRNO!() = a.err;
17531 return -1;
17532 }
17533 0
17534}
17535
17536#[no_mangle]
17537pub unsafe extern "C" fn mq_getattr(mqdes: i32, attr: *mut core::ffi::c_void) -> i32 {
17538 mq_setattr(mqdes, core::ptr::null(), attr)
17539}
17540
17541#[no_mangle]
17542pub unsafe extern "C" fn mq_setattr(
17543 mqdes: i32,
17544 new: *const core::ffi::c_void,
17545 old: *mut core::ffi::c_void,
17546) -> i32 {
17547 syscall_ret(<Arch as Syscalls>::syscall3(
17548 sysno(245, 185),
17549 mqdes as i64,
17550 new as i64,
17551 old as i64,
17552 )) as i32
17553}
17554
17555#[no_mangle]
17560pub unsafe extern "C" fn pthread_getaffinity_np(thread: usize, cpusetsize: usize, cpuset: *mut u8) -> i32 {
17561 sched_getaffinity(thread as i32, cpusetsize, cpuset)
17562}
17563
17564#[no_mangle]
17565pub unsafe extern "C" fn pthread_setaffinity_np(thread: usize, cpusetsize: usize, cpuset: *const u8) -> i32 {
17566 sched_setaffinity(thread as i32, cpusetsize, cpuset)
17567}
17568
17569#[no_mangle]
17574pub unsafe extern "C" fn sched_yield() -> i32 {
17575 syscall_ret(<Arch as Syscalls>::syscall0(sysno(24, 124))) as i32
17576}
17577
17578#[no_mangle]
17579pub unsafe extern "C" fn sched_get_priority_max(policy: i32) -> i32 {
17580 syscall_ret(<Arch as Syscalls>::syscall1(sysno(146, 125), policy as i64)) as i32
17581}
17582
17583#[no_mangle]
17584pub unsafe extern "C" fn sched_get_priority_min(policy: i32) -> i32 {
17585 syscall_ret(<Arch as Syscalls>::syscall1(sysno(147, 126), policy as i64)) as i32
17586}
17587
17588#[no_mangle]
17589pub unsafe extern "C" fn sched_getparam(pid: i32, param: *mut core::ffi::c_void) -> i32 {
17590 syscall_ret(<Arch as Syscalls>::syscall2(sysno(143, 121), pid as i64, param as i64)) as i32
17591}
17592
17593#[no_mangle]
17594pub unsafe extern "C" fn sched_setparam(pid: i32, param: *const core::ffi::c_void) -> i32 {
17595 syscall_ret(<Arch as Syscalls>::syscall2(sysno(142, 118), pid as i64, param as i64)) as i32
17596}
17597
17598#[no_mangle]
17599pub unsafe extern "C" fn sched_getscheduler(pid: i32) -> i32 {
17600 syscall_ret(<Arch as Syscalls>::syscall1(sysno(145, 120), pid as i64)) as i32
17601}
17602
17603#[no_mangle]
17604pub unsafe extern "C" fn sched_setscheduler(pid: i32, policy: i32, param: *const core::ffi::c_void) -> i32 {
17605 syscall_ret(<Arch as Syscalls>::syscall3(sysno(144, 119), pid as i64, policy as i64, param as i64)) as i32
17606}
17607
17608#[no_mangle]
17609pub unsafe extern "C" fn sched_setaffinity(pid: i32, cpusetsize: usize, cpuset: *const u8) -> i32 {
17610 syscall_ret(<Arch as Syscalls>::syscall3(sysno(203, 122), pid as i64, cpusetsize as i64, cpuset as i64)) as i32
17611}
17612
17613#[no_mangle]
17614pub unsafe extern "C" fn sched_getaffinity(pid: i32, cpusetsize: usize, cpuset: *mut u8) -> i32 {
17615 let r = <Arch as Syscalls>::syscall3(sysno(204, 123), pid as i64, cpusetsize as i64, cpuset as i64);
17616 if r < 0 {
17617 ERRNO!() = (-r) as c_int;
17618 return -1;
17619 }
17620 0
17622}
17623
17624#[no_mangle]
17625pub unsafe extern "C" fn sched_getcpu() -> i32 {
17626 let mut cpu: i32 = 0;
17627 <Arch as Syscalls>::syscall3(sysno(309, 168), &mut cpu as *mut i32 as i64, 0, 0);
17628 cpu
17629}
17630
17631#[no_mangle]
17632pub unsafe extern "C" fn sched_rr_get_interval(pid: i32, tp: *mut core::ffi::c_void) -> i32 {
17633 syscall_ret(<Arch as Syscalls>::syscall2(sysno(148, 127), pid as i64, tp as i64)) as i32
17634}
17635
17636#[no_mangle]
17641pub unsafe extern "C" fn timer_create(clockid: i32, sevp: *mut core::ffi::c_void, timerid: *mut i32) -> i32 {
17642 syscall_ret(<Arch as Syscalls>::syscall3(sysno(222, 107), clockid as i64, sevp as i64, timerid as i64)) as i32
17643}
17644
17645#[no_mangle]
17646pub unsafe extern "C" fn timer_delete(timerid: i32) -> i32 {
17647 syscall_ret(<Arch as Syscalls>::syscall1(sysno(226, 111), timerid as i64)) as i32
17648}
17649
17650#[no_mangle]
17651pub 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 {
17652 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
17653}
17654
17655#[no_mangle]
17656pub unsafe extern "C" fn timer_gettime(timerid: i32, curr_value: *mut core::ffi::c_void) -> i32 {
17657 syscall_ret(<Arch as Syscalls>::syscall2(sysno(224, 108), timerid as i64, curr_value as i64)) as i32
17658}
17659
17660#[no_mangle]
17661pub unsafe extern "C" fn timer_getoverrun(timerid: i32) -> i32 {
17662 syscall_ret(<Arch as Syscalls>::syscall1(sysno(225, 109), timerid as i64)) as i32
17663}
17664
17665#[no_mangle]
17666pub unsafe extern "C" fn clock_adjtime(_clockid: i32, buf: *mut core::ffi::c_void) -> i32 {
17667 syscall_ret(<Arch as Syscalls>::syscall2(SYS_ADJTIMEX, buf as i64, 0)) as i32
17668}
17669
17670#[no_mangle]
17671pub unsafe extern "C" fn clock_getcpuclockid(pid: i32, clockid: *mut i32) -> i32 {
17672 if clockid.is_null() { return EINVAL; }
17673 let id: i32 = ((-(pid as i64) - 1) * 8 + 2) as i32;
17674 let mut ts: timespec = core::mem::zeroed();
17675 let r = <Arch as Syscalls>::syscall2(SYS_CLOCK_GETRES, id as i64, &mut ts as *mut timespec as i64);
17676 if r < 0 {
17677 let e = (-r) as c_int;
17678 return if e == EINVAL { 3 } else { e };
17679 }
17680 *clockid = id;
17681 0
17682}
17683
17684#[no_mangle]
17689pub unsafe extern "C" fn strcoll(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char) -> i32 {
17690 let mut i = 0;
17692 loop {
17693 let c1 = *s1.add(i) as u8;
17694 let c2 = *s2.add(i) as u8;
17695 if c1 == 0 || c2 == 0 { return (c1 as i32) - (c2 as i32); }
17696 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
17697 i += 1;
17698 }
17699}
17700
17701#[no_mangle]
17702pub unsafe extern "C" fn strxfrm(dest: *mut core::ffi::c_char, src: *const core::ffi::c_char, n: usize) -> usize {
17703 let mut i = 0;
17704 while i < n {
17705 let c = *src.add(i);
17706 *dest.add(i) = c;
17707 if c == 0 { break; }
17708 i += 1;
17709 }
17710 i
17711}
17712
17713#[no_mangle]
17718pub 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 {
17719 let dir = opendir(dirp);
17720 if dir.is_null() { return -1; }
17721 let mut count = 0;
17722 loop {
17723 let ent = readdir(dir);
17724 if ent.is_null() { break; }
17725 count += 1;
17726 }
17727 closedir(dir);
17728 count
17729}
17730
17731#[no_mangle]
17732pub unsafe extern "C" fn alphasort(a: *const *const core::ffi::c_void, b: *const *const core::ffi::c_void) -> i32 {
17733 let s1 = *a as *const core::ffi::c_char;
17734 let s2 = *b as *const core::ffi::c_char;
17735 crate::strcmp(s1 as *const u8, s2 as *const u8)
17736}
17737
17738#[no_mangle]
17739pub unsafe extern "C" fn versionsort(a: *const *const core::ffi::c_void, b: *const *const core::ffi::c_void) -> i32 {
17740 let s1 = *a as *const core::ffi::c_char;
17741 let s2 = *b as *const core::ffi::c_char;
17742 crate::strcmp(s1 as *const u8, s2 as *const u8)
17743}
17744
17745unsafe fn vwarn_impl(fmt: *const c_char, ap: VaList, with_errno: bool) {
17753 let mut buf = [0 as c_char; 1024];
17754 let n = vsnprintf(buf.as_mut_ptr(), buf.len(), fmt, ap);
17755 if n > 0 {
17756 let l = core::cmp::min(n as usize, buf.len() - 1);
17757 crate::write(2, buf.as_ptr() as *const c_void, l);
17758 }
17759 if with_errno {
17760 let e = ERRNO!();
17761 crate::write(2, b": ".as_ptr() as *const c_void, 2);
17762 let msg = strerror(e);
17763 crate::write(2, msg as *const c_void, crate::strlen(msg));
17764 }
17765 crate::write(2, b"\n".as_ptr() as *const c_void, 1);
17766}
17767
17768#[no_mangle]
17769pub unsafe extern "C" fn verr(eval: c_int, fmt: *const c_char, ap: VaList) {
17770 vwarn_impl(fmt, ap, true);
17771 crate::exit(eval);
17772}
17773
17774#[no_mangle]
17775pub unsafe extern "C" fn verrx(eval: c_int, fmt: *const c_char, ap: VaList) {
17776 vwarn_impl(fmt, ap, false);
17777 crate::exit(eval);
17778}
17779
17780#[no_mangle]
17781pub unsafe extern "C" fn vwarn(fmt: *const c_char, ap: VaList) {
17782 vwarn_impl(fmt, ap, true);
17783}
17784
17785#[no_mangle]
17786pub unsafe extern "C" fn vwarnx(fmt: *const c_char, ap: VaList) {
17787 vwarn_impl(fmt, ap, false);
17788}
17789
17790#[no_mangle]
17791pub unsafe extern "C" fn err(eval: c_int, fmt: *const c_char, args: ...) {
17792 verr(eval, fmt, args);
17793}
17794
17795#[no_mangle]
17796pub unsafe extern "C" fn errx(eval: c_int, fmt: *const c_char, args: ...) {
17797 verrx(eval, fmt, args);
17798}
17799
17800#[no_mangle]
17801pub unsafe extern "C" fn warn(fmt: *const c_char, args: ...) {
17802 vwarn(fmt, args);
17803}
17804
17805#[no_mangle]
17806pub unsafe extern "C" fn warnx(fmt: *const c_char, args: ...) {
17807 vwarnx(fmt, args);
17808}
17809
17810#[no_mangle]
17815pub unsafe extern "C" fn ecvt(value: f64, ndigit: i32, decpt: *mut i32, sign: *mut i32) -> *mut core::ffi::c_char {
17816 static mut BUF: [core::ffi::c_char; 80] = [0; 80];
17817 if value < 0.0 { *sign = 1; } else { *sign = 0; }
17818 let v = if value < 0.0 { -value } else { value };
17819 if v == 0.0 { *decpt = 0; BUF[0] = 0; return BUF.as_mut_ptr(); }
17820 let mut d = 0i32;
17821 let mut tmp = v;
17822 while tmp >= 10.0 { tmp /= 10.0; d += 1; }
17823 while tmp < 1.0 { tmp *= 10.0; d -= 1; }
17824 *decpt = d + 1;
17825 let mut i = 0;
17826 let mut val = tmp;
17827 while i < ndigit as usize && i < 79 {
17828 let digit = val as i32;
17829 BUF[i] = (b'0' + digit as u8) as c_char;
17830 val = (val - digit as f64) * 10.0;
17831 i += 1;
17832 }
17833 BUF[i] = 0;
17834 BUF.as_mut_ptr()
17835}
17836
17837#[no_mangle]
17838pub unsafe extern "C" fn fcvt(value: f64, ndigit: i32, decpt: *mut i32, sign: *mut i32) -> *mut core::ffi::c_char {
17839 static mut BUF: [core::ffi::c_char; 80] = [0; 80];
17840 if value < 0.0 { *sign = 1; } else { *sign = 0; }
17841 let v = if value < 0.0 { -value } else { value };
17842 if v == 0.0 { *decpt = 0; BUF[0] = 0; return BUF.as_mut_ptr(); }
17843 let mut d = 0i32;
17844 let mut tmp = v;
17845 while tmp >= 10.0 { tmp /= 10.0; d += 1; }
17846 while tmp < 1.0 { tmp *= 10.0; d -= 1; }
17847 *decpt = d + 1;
17848 let mut val = tmp;
17849 let mut i = 0;
17850 while i < (*decpt) as usize && i < 79 {
17851 let digit = val as i32;
17852 BUF[i] = (b'0' + digit as u8) as c_char;
17853 val = (val - digit as f64) * 10.0;
17854 i += 1;
17855 }
17856 if ndigit > 0 && i < 79 {
17857 BUF[i] = '.' as c_char;
17858 i += 1;
17859 let mut frac = val;
17860 let mut j = 0;
17861 while j < ndigit as usize && i < 79 {
17862 let digit = frac as i32;
17863 BUF[i] = (b'0' + digit as u8) as c_char;
17864 frac = (frac - digit as f64) * 10.0;
17865 i += 1;
17866 j += 1;
17867 }
17868 }
17869 BUF[i] = 0;
17870 BUF.as_mut_ptr()
17871}
17872
17873#[no_mangle]
17874pub unsafe extern "C" fn gcvt(value: f64, _ndigit: i32, buf: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
17875 if value == 0.0 {
17877 *buf = '0' as c_char;
17878 *buf.add(1) = 0;
17879 return buf;
17880 }
17881 let mut i = 0;
17882 let v = if value < 0.0 { *buf = '-' as c_char; i = 1; -value } else { value };
17883 let mut int_part = v as i64;
17885 let mut digits = [0u8; 32];
17886 let mut di = 0;
17887 if int_part == 0 {
17888 digits[0] = 0;
17889 di = 1;
17890 } else {
17891 while int_part > 0 && di < 32 {
17892 digits[di] = (int_part % 10) as u8;
17893 int_part /= 10;
17894 di += 1;
17895 }
17896 }
17897 while di > 0 && i < 79 {
17898 di -= 1;
17899 *buf.add(i) = (b'0' + digits[di]) as c_char;
17900 i += 1;
17901 }
17902 *buf.add(i) = 0;
17903 buf
17904}
17905
17906static mut SHELLS: [*const core::ffi::c_char; 3] = [
17911 b"/bin/sh\0".as_ptr() as *const core::ffi::c_char,
17912 b"/bin/bash\0".as_ptr() as *const core::ffi::c_char,
17913 core::ptr::null(),
17914];
17915static mut SHELL_IDX: usize = 0;
17916
17917#[no_mangle]
17918pub unsafe extern "C" fn getusershell() -> *mut core::ffi::c_char {
17919 let s = SHELLS[SHELL_IDX];
17920 if s.is_null() {
17921 SHELL_IDX = 0;
17922 return core::ptr::null_mut();
17923 }
17924 SHELL_IDX += 1;
17925 s as *mut core::ffi::c_char
17926}
17927
17928#[no_mangle]
17929pub unsafe extern "C" fn setusershell() {
17930 SHELL_IDX = 0;
17931}
17932
17933#[no_mangle]
17934pub unsafe extern "C" fn endusershell() {
17935 SHELL_IDX = 0;
17936}
17937
17938#[no_mangle]
17943pub unsafe extern "C" fn ether_aton(s: *const core::ffi::c_char) -> *mut u8 {
17944 static mut EA: [u8; 6] = [0; 6];
17945 if ether_aton_r(s, EA.as_mut_ptr()).is_null() { core::ptr::null_mut() } else { EA.as_mut_ptr() }
17946}
17947
17948#[no_mangle]
17949pub unsafe extern "C" fn ether_aton_r(s: *const core::ffi::c_char, ea: *mut u8) -> *mut u8 {
17950 if ea.is_null() { return core::ptr::null_mut(); }
17951 let mut i = 0;
17952 let mut j = 0;
17953 let mut val: u32 = 0;
17954 let mut digits = 0;
17955 while *s.add(i) != 0 && j < 6 {
17956 let c = *s.add(i);
17957 if c == ':' as c_char {
17958 if digits == 0 { return core::ptr::null_mut(); }
17959 *ea.add(j) = val as u8;
17960 j += 1;
17961 val = 0;
17962 digits = 0;
17963 } 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) {
17964 let d = if c >= '0' as c_char && c <= '9' as c_char { (c - '0' as c_char) as u32 }
17965 else if c >= 'a' as c_char { (c - 'a' as c_char + 10) as u32 }
17966 else { (c - 'A' as c_char + 10) as u32 };
17967 val = val * 16 + d;
17968 if val > 255 { return core::ptr::null_mut(); }
17969 digits += 1;
17970 if digits > 2 { return core::ptr::null_mut(); }
17971 } else {
17972 return core::ptr::null_mut();
17973 }
17974 i += 1;
17975 }
17976 if digits == 0 || j != 5 { return core::ptr::null_mut(); }
17977 *ea.add(j) = val as u8;
17978 ea
17979}
17980
17981#[no_mangle]
17982pub unsafe extern "C" fn ether_ntoa(ea: *const u8) -> *mut core::ffi::c_char {
17983 static mut BUF: [core::ffi::c_char; 18] = [0; 18];
17984 ether_ntoa_r(ea, BUF.as_mut_ptr());
17985 BUF.as_mut_ptr()
17986}
17987
17988#[no_mangle]
17989pub unsafe extern "C" fn ether_ntoa_r(ea: *const u8, buf: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
17990 let a = *ea.add(0); let b = *ea.add(1); let c = *ea.add(2);
17991 let d = *ea.add(3); let e = *ea.add(4); let f = *ea.add(5);
17992 let hex = b"0123456789abcdef\0".as_ptr() as *const u8;
17993 let mut i = 0;
17994 *buf.add(i) = *hex.add((a >> 4) as usize) as c_char; i += 1;
17995 *buf.add(i) = *hex.add((a & 0xf) as usize) as c_char; i += 1;
17996 *buf.add(i) = ':' as c_char; i += 1;
17997 *buf.add(i) = *hex.add((b >> 4) as usize) as c_char; i += 1;
17998 *buf.add(i) = *hex.add((b & 0xf) as usize) as c_char; i += 1;
17999 *buf.add(i) = ':' as c_char; i += 1;
18000 *buf.add(i) = *hex.add((c >> 4) as usize) as c_char; i += 1;
18001 *buf.add(i) = *hex.add((c & 0xf) as usize) as c_char; i += 1;
18002 *buf.add(i) = ':' as c_char; i += 1;
18003 *buf.add(i) = *hex.add((d >> 4) as usize) as c_char; i += 1;
18004 *buf.add(i) = *hex.add((d & 0xf) as usize) as c_char; i += 1;
18005 *buf.add(i) = ':' as c_char; i += 1;
18006 *buf.add(i) = *hex.add((e >> 4) as usize) as c_char; i += 1;
18007 *buf.add(i) = *hex.add((e & 0xf) as usize) as c_char; i += 1;
18008 *buf.add(i) = ':' as c_char; i += 1;
18009 *buf.add(i) = *hex.add((f >> 4) as usize) as c_char; i += 1;
18010 *buf.add(i) = *hex.add((f & 0xf) as usize) as c_char; i += 1;
18011 *buf.add(i) = 0;
18012 buf
18013}
18014
18015#[no_mangle]
18020pub unsafe extern "C" fn getutxent() -> *mut core::ffi::c_void {
18021 getutent()
18022}
18023
18024#[no_mangle]
18025pub unsafe extern "C" fn getutxid(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
18026 getutid(ut)
18027}
18028
18029#[no_mangle]
18030pub unsafe extern "C" fn getutxline(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
18031 getutline(ut)
18032}
18033
18034#[no_mangle]
18035pub unsafe extern "C" fn pututxline(ut: *const core::ffi::c_void) -> *mut core::ffi::c_void {
18036 pututline(ut)
18037}
18038
18039#[no_mangle]
18040pub unsafe extern "C" fn setutxent() {
18041 setutent()
18042}
18043
18044#[no_mangle]
18045pub unsafe extern "C" fn endutxent() {
18046 endutent()
18047}
18048
18049#[no_mangle]
18054pub unsafe extern "C" fn execv(path: *const core::ffi::c_char, argv: *const *const core::ffi::c_char) -> i32 {
18055 crate::execve(path, argv, __environ as *const *const core::ffi::c_char)
18056}
18057
18058#[no_mangle]
18059pub unsafe extern "C" fn execlp(file: *const core::ffi::c_char, _args: ...) -> i32 {
18060 let mut argv: [*const core::ffi::c_char; 64] = [core::ptr::null(); 64];
18062 let mut i = 0;
18063 let mut args = _args;
18064 loop {
18065 let arg = args.next_arg::<*const core::ffi::c_char>();
18066 if arg.is_null() { break; }
18067 argv[i] = arg;
18068 i += 1;
18069 if i >= 63 { break; }
18070 }
18071 argv[i] = core::ptr::null();
18072 execvp(file, argv.as_ptr())
18073}
18074
18075#[no_mangle]
18076pub unsafe extern "C" fn execvp(file: *const core::ffi::c_char, argv: *const *const core::ffi::c_char) -> i32 {
18077 execvpe(file, argv, __environ as *const *const core::ffi::c_char)
18078}
18079
18080#[no_mangle]
18081pub unsafe extern "C" fn fexecve(fd: i32, argv: *const *const core::ffi::c_char, envp: *const *const core::ffi::c_char) -> i32 {
18082 let mut path: [core::ffi::c_char; 64] = [0; 64];
18084 let mut i = 0;
18085 let src = b"/proc/self/fd/\0".as_ptr() as *const core::ffi::c_char;
18086 while i < 63 && *src.add(i) != 0 { path[i] = *src.add(i); i += 1; }
18087 let mut n = fd as usize;
18088 if n == 0 { path[i] = '0' as c_char; i += 1; }
18089 while n > 0 && i < 63 {
18090 path[i] = (b'0' + (n % 10) as u8) as c_char;
18091 n /= 10;
18092 i += 1;
18093 }
18094 path[i] = 0;
18095 crate::execve(path.as_ptr(), argv, envp)
18096}
18097
18098#[no_mangle]
18103pub unsafe extern "C" fn confstr(name: i32, buf: *mut core::ffi::c_char, len: usize) -> usize {
18104 let value: &[u8] = if name == 0 {
18107 b"/bin:/usr/bin"
18108 } else if (1..=37).contains(&name) {
18109 b""
18110 } else {
18111 ERRNO!() = EINVAL;
18112 return 0;
18113 };
18114 let need = value.len() + 1;
18115 if !buf.is_null() && len > 0 {
18116 let n = core::cmp::min(value.len(), len - 1);
18117 core::ptr::copy_nonoverlapping(value.as_ptr(), buf as *mut u8, n);
18118 *buf.add(n) = 0;
18119 }
18120 need
18121}
18122
18123#[no_mangle]
18124pub unsafe extern "C" fn pathconf(_path: *const core::ffi::c_char, name: i32) -> i64 {
18125 match name {
18127 0 => 4096, 1 => 255, 2 => 255, 3 => 255, 4 => 4096, 5 => 4096, 6 => 1, 7 => 0, 8 => 0, _ => -1,
18137 }
18138}
18139
18140#[no_mangle]
18141pub unsafe extern "C" fn fpathconf(_fd: i32, name: i32) -> i64 {
18142 match name {
18144 0 => 4096, 1 => 255, 2 => 255, 3 => 255, 4 => 4096, 5 => 4096, 6 => 1, 7 => 0, 8 => 0, _ => -1,
18154 }
18155}
18156
18157#[no_mangle]
18162pub unsafe extern "C" fn exp10(x: f64) -> f64 {
18163 libm::pow(10.0, x)
18164}
18165
18166#[no_mangle]
18167pub unsafe extern "C" fn exp10f(x: f32) -> f32 {
18168 libm::powf(10.0, x)
18169}
18170
18171#[no_mangle]
18176pub unsafe extern "C" fn explicit_bzero(s: *mut u8, n: usize) {
18177 core::ptr::write_bytes(s, 0, n);
18178 core::sync::atomic::compiler_fence(core::sync::atomic::Ordering::SeqCst);
18179}
18180
18181#[no_mangle]
18182pub unsafe extern "C" fn memccpy(dest: *mut u8, src: *const u8, c: i32, n: usize) -> *mut u8 {
18183 let mut i = 0;
18184 while i < n {
18185 let byte = *src.add(i);
18186 *dest.add(i) = byte;
18187 if byte == c as u8 {
18188 return dest.add(i + 1);
18189 }
18190 i += 1;
18191 }
18192 core::ptr::null_mut()
18193}
18194
18195#[no_mangle]
18200pub unsafe extern "C" fn faccessat(dirfd: i32, pathname: *const core::ffi::c_char, mode: i32, flags: i32) -> i32 {
18201 syscall_ret(<Arch as Syscalls>::syscall4(SYS_FACCESSAT, dirfd as i64, pathname as i64, mode as i64, flags as i64)) as i32
18202}
18203
18204#[no_mangle]
18205pub unsafe extern "C" fn fchmodat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32, flags: i32) -> i32 {
18206 if flags == 0 {
18207 return syscall_ret(<Arch as Syscalls>::syscall4(SYS_FCHMODAT, dirfd as i64, pathname as i64, mode as i64, 0)) as i32;
18208 }
18209 if flags != 0x100 {
18210 ERRNO!() = EINVAL;
18212 return -1;
18213 }
18214 syscall_ret(<Arch as Syscalls>::syscall4(sysno(452, 452), dirfd as i64, pathname as i64, mode as i64, flags as i64)) as i32
18215}
18216
18217#[no_mangle]
18218pub unsafe extern "C" fn fchownat(dirfd: i32, pathname: *const core::ffi::c_char, uid: u32, gid: u32, flags: i32) -> i32 {
18219 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
18220}
18221
18222#[no_mangle]
18223pub unsafe extern "C" fn linkat(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char, flags: i32) -> i32 {
18224 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
18225}
18226
18227#[no_mangle]
18228pub unsafe extern "C" fn mkdirat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18229 syscall_ret(<Arch as Syscalls>::syscall3(SYS_MKDIRAT, dirfd as i64, pathname as i64, mode as i64)) as i32
18230}
18231
18232#[no_mangle]
18233pub unsafe extern "C" fn mkfifoat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18234 mknodat(dirfd, pathname, mode | 0o010000, 0)
18235}
18236
18237#[no_mangle]
18238pub unsafe extern "C" fn mknodat(dirfd: i32, pathname: *const core::ffi::c_char, mode: u32, dev: u64) -> i32 {
18239 syscall_ret(<Arch as Syscalls>::syscall4(sysno(259, 33), dirfd as i64, pathname as i64, mode as i64, dev as i64)) as i32
18240}
18241
18242#[no_mangle]
18243pub unsafe extern "C" fn readlinkat(dirfd: i32, pathname: *const core::ffi::c_char, buf: *mut core::ffi::c_char, bufsiz: usize) -> isize {
18244 syscall_ret(<Arch as Syscalls>::syscall4(SYS_READLINKAT, dirfd as i64, pathname as i64, buf as i64, bufsiz as i64)) as isize
18245}
18246
18247#[no_mangle]
18248pub unsafe extern "C" fn renameat(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char) -> i32 {
18249 syscall_ret(<Arch as Syscalls>::syscall5(SYS_RENAMEAT2, olddirfd as i64, oldpath as i64, newdirfd as i64, newpath as i64, 0)) as i32
18250}
18251
18252#[no_mangle]
18253pub unsafe extern "C" fn renameat2(olddirfd: i32, oldpath: *const core::ffi::c_char, newdirfd: i32, newpath: *const core::ffi::c_char, flags: u32) -> i32 {
18254 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
18255}
18256
18257#[no_mangle]
18258pub unsafe extern "C" fn symlinkat(target: *const core::ffi::c_char, newdirfd: i32, linkpath: *const core::ffi::c_char) -> i32 {
18259 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SYMLINKAT, target as i64, newdirfd as i64, linkpath as i64)) as i32
18260}
18261
18262#[no_mangle]
18263pub unsafe extern "C" fn unlinkat(dirfd: i32, pathname: *const core::ffi::c_char, flags: i32) -> i32 {
18264 syscall_ret(<Arch as Syscalls>::syscall3(SYS_UNLINKAT, dirfd as i64, pathname as i64, flags as i64)) as i32
18265}
18266
18267#[no_mangle]
18268pub unsafe extern "C" fn utimes(filename: *const core::ffi::c_char, times: *const core::ffi::c_void) -> i32 {
18269 utimensat(AT_FDCWD, filename, times as *const timespec, 0)
18270}
18271
18272#[no_mangle]
18273pub unsafe extern "C" fn futimes(fd: i32, times: *const core::ffi::c_void) -> i32 {
18274 utimensat(fd, core::ptr::null(), times as *const timespec, 0)
18275}
18276
18277#[no_mangle]
18282pub unsafe extern "C" fn inotify_init() -> i32 {
18283 syscall_ret(<Arch as Syscalls>::syscall1(sysno(253, 26), 0)) as i32
18284}
18285
18286#[no_mangle]
18287pub unsafe extern "C" fn inotify_init1(flags: i32) -> i32 {
18288 syscall_ret(<Arch as Syscalls>::syscall1(sysno(294, 26), flags as i64)) as i32
18289}
18290
18291#[no_mangle]
18292pub unsafe extern "C" fn inotify_add_watch(fd: i32, pathname: *const core::ffi::c_char, mask: u32) -> i32 {
18293 syscall_ret(<Arch as Syscalls>::syscall3(sysno(254, 27), fd as i64, pathname as i64, mask as i64)) as i32
18294}
18295
18296#[no_mangle]
18297pub unsafe extern "C" fn inotify_rm_watch(fd: i32, wd: i32) -> i32 {
18298 syscall_ret(<Arch as Syscalls>::syscall2(sysno(255, 28), fd as i64, wd as i64)) as i32
18299}
18300
18301#[no_mangle]
18302pub unsafe extern "C" fn fanotify_init(flags: i32, event_f_flags: i32) -> i32 {
18303 syscall_ret(<Arch as Syscalls>::syscall2(sysno(300, 262), flags as i64, event_f_flags as i64)) as i32
18304}
18305
18306#[no_mangle]
18307pub unsafe extern "C" fn fanotify_mark(fd: i32, flags: i32, mask: u64, dirfd: i32, pathname: *const core::ffi::c_char) -> i32 {
18308 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
18309}
18310
18311#[no_mangle]
18316pub unsafe extern "C" fn ffs(x: i32) -> i32 {
18317 if x == 0 { return 0; }
18318 x.trailing_zeros() as i32 + 1
18319}
18320
18321#[no_mangle]
18322pub unsafe extern "C" fn ffsl(x: i64) -> i32 {
18323 if x == 0 { return 0; }
18324 x.trailing_zeros() as i32 + 1
18325}
18326
18327#[no_mangle]
18328pub unsafe extern "C" fn ffsll(x: i64) -> i32 {
18329 if x == 0 { return 0; }
18330 x.trailing_zeros() as i32 + 1
18331}
18332
18333#[no_mangle]
18338pub unsafe extern "C" fn fchdir(fd: i32) -> i32 {
18339 syscall_ret(<Arch as Syscalls>::syscall1(SYS_FCHDIR, fd as i64)) as i32
18340}
18341
18342#[no_mangle]
18343pub unsafe extern "C" fn fchown(fd: i32, uid: u32, gid: u32) -> i32 {
18344 syscall_ret(<Arch as Syscalls>::syscall3(SYS_FCHOWN, fd as i64, uid as i64, gid as i64)) as i32
18345}
18346
18347#[no_mangle]
18348pub unsafe extern "C" fn fdopendir(fd: i32) -> *mut core::ffi::c_void {
18349 if fd < 0 { ERRNO!() = 9; return core::ptr::null_mut(); }
18350 dir_stream_new(fd)
18351}
18352
18353#[no_mangle]
18354pub unsafe extern "C" fn getdtablesize() -> i32 {
18355 let mut rlim: Rlimit = core::mem::zeroed();
18356 if getrlimit(RLIMIT_NOFILE, &mut rlim) == 0 {
18357 rlim.rlim_cur as i32
18358 } else {
18359 1024
18360 }
18361}
18362
18363#[no_mangle]
18364pub unsafe extern "C" fn getentropy(buf: *mut u8, buflen: usize) -> i32 {
18365 if buflen > 256 {
18366 ERRNO!() = EIO_VAL;
18367 return -1;
18368 }
18369 let mut pos = buf;
18370 let mut left = buflen;
18371 while left > 0 {
18372 let r = getrandom(pos, left, 0);
18373 if r < 0 {
18374 if ERRNO!() == EINTR_VAL {
18375 continue;
18376 }
18377 return -1;
18378 }
18379 pos = pos.add(r as usize);
18380 left -= r as usize;
18381 }
18382 0
18383}
18384
18385#[no_mangle]
18386pub unsafe extern "C" fn getrandom(buf: *mut u8, buflen: usize, flags: u32) -> isize {
18387 let r = <Arch as Syscalls>::syscall3(sysno(318, 278), buf as i64, buflen as i64, flags as i64);
18388 if r < 0 {
18389 ERRNO!() = (-r) as c_int;
18390 -1
18391 } else {
18392 r as isize
18393 }
18394}
18395
18396#[no_mangle]
18397pub unsafe extern "C" fn killpg(pgrp: i32, sig: i32) -> i32 {
18398 syscall_ret(<Arch as Syscalls>::syscall2(SYS_KILL, -pgrp as i64, sig as i64)) as i32
18399}
18400
18401#[no_mangle]
18402pub unsafe extern "C" fn mkfifo(pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18403 mknod(pathname, 0o010000 | mode, 0)
18404}
18405
18406#[no_mangle]
18411pub unsafe extern "C" fn aligned_alloc(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 memalign(alignment: usize, size: usize) -> *mut core::ffi::c_void {
18417 alloc_aligned_impl(alignment, size) as *mut core::ffi::c_void
18418}
18419
18420#[no_mangle]
18421pub unsafe extern "C" fn posix_memalign(memptr: *mut *mut core::ffi::c_void, alignment: usize, size: usize) -> i32 {
18422 if memptr.is_null() { return EINVAL; }
18423 if alignment < core::mem::size_of::<*mut core::ffi::c_void>() || !alignment.is_power_of_two() {
18424 return EINVAL;
18425 }
18426 let p = alloc_aligned_impl(alignment, size);
18427 if p.is_null() { return ENOMEM; }
18428 *memptr = p as *mut core::ffi::c_void;
18429 0
18430}
18431
18432#[no_mangle]
18433pub unsafe extern "C" fn valloc(size: usize) -> *mut core::ffi::c_void {
18434 alloc_aligned_impl(PAGE, size) as *mut core::ffi::c_void
18435}
18436
18437#[no_mangle]
18450pub unsafe extern "C" fn gettext(msgid: *const core::ffi::c_char) -> *const core::ffi::c_char {
18451 msgid
18452}
18453
18454#[no_mangle]
18455pub unsafe extern "C" fn dgettext(_domainname: *const core::ffi::c_char, msgid: *const core::ffi::c_char) -> *const core::ffi::c_char {
18456 msgid
18457}
18458
18459#[no_mangle]
18460pub unsafe extern "C" fn dcgettext(_domainname: *const core::ffi::c_char, msgid: *const core::ffi::c_char, _category: i32) -> *const core::ffi::c_char {
18461 msgid
18462}
18463
18464#[no_mangle]
18465pub unsafe extern "C" fn ngettext(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 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 {
18471 if n == 1 { msgid1 } else { msgid2 }
18472}
18473
18474#[no_mangle]
18475pub 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 {
18476 if n == 1 { msgid1 } else { msgid2 }
18477}
18478
18479#[no_mangle]
18480pub unsafe extern "C" fn textdomain(domainname: *const core::ffi::c_char) -> *mut core::ffi::c_char {
18481 static mut DOMAIN: [core::ffi::c_char; 256] = [0; 256];
18482 if domainname.is_null() { return DOMAIN.as_mut_ptr(); }
18483 let mut i = 0;
18484 while i < 255 && *domainname.add(i) != 0 {
18485 DOMAIN[i] = *domainname.add(i);
18486 i += 1;
18487 }
18488 DOMAIN[i] = 0;
18489 DOMAIN.as_mut_ptr()
18490}
18491
18492#[no_mangle]
18493pub unsafe extern "C" fn bindtextdomain(_domainname: *const core::ffi::c_char, dirname: *const core::ffi::c_char) -> *mut core::ffi::c_char {
18494 dirname as *mut core::ffi::c_char
18495}
18496
18497#[no_mangle]
18498pub unsafe extern "C" fn bind_textdomain_codeset(_domainname: *const core::ffi::c_char, codeset: *const core::ffi::c_char) -> *mut core::ffi::c_char {
18499 codeset as *mut core::ffi::c_char
18500}
18501
18502#[no_mangle]
18507pub unsafe extern "C" fn wmemcpy(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18508 let mut i = 0;
18509 while i < n {
18510 *dest.add(i) = *src.add(i);
18511 i += 1;
18512 }
18513 dest
18514}
18515
18516#[no_mangle]
18517pub unsafe extern "C" fn wmemmove(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18518 if dest as usize <= src as usize {
18519 let mut i = 0;
18520 while i < n {
18521 *dest.add(i) = *src.add(i);
18522 i += 1;
18523 }
18524 } else {
18525 let mut i = n;
18526 while i > 0 {
18527 i -= 1;
18528 *dest.add(i) = *src.add(i);
18529 }
18530 }
18531 dest
18532}
18533
18534#[no_mangle]
18535pub unsafe extern "C" fn wmemset(dest: *mut u32, c: u32, n: usize) -> *mut u32 {
18536 let mut i = 0;
18537 while i < n {
18538 *dest.add(i) = c;
18539 i += 1;
18540 }
18541 dest
18542}
18543
18544#[no_mangle]
18545pub unsafe extern "C" fn wmemcmp(s1: *const u32, s2: *const u32, n: usize) -> i32 {
18546 let mut i = 0;
18547 while i < n {
18548 let c1 = *s1.add(i);
18549 let c2 = *s2.add(i);
18550 if c1 != c2 { return (c1 as i32) - (c2 as i32); }
18551 i += 1;
18552 }
18553 0
18554}
18555
18556#[no_mangle]
18557pub unsafe extern "C" fn wmemchr(s: *const u32, c: u32, n: usize) -> *mut u32 {
18558 let mut i = 0;
18559 while i < n {
18560 if *s.add(i) == c { return s.add(i) as *mut u32; }
18561 i += 1;
18562 }
18563 core::ptr::null_mut()
18564}
18565
18566#[no_mangle]
18567pub unsafe extern "C" fn wcpcpy(dest: *mut u32, src: *const u32) -> *mut u32 {
18568 let mut i = 0;
18569 loop {
18570 let c = *src.add(i);
18571 *dest.add(i) = c;
18572 if c == 0 { return dest.add(i); }
18573 i += 1;
18574 }
18575}
18576
18577#[no_mangle]
18578pub unsafe extern "C" fn wcpncpy(dest: *mut u32, src: *const u32, n: usize) -> *mut u32 {
18579 let mut i = 0;
18580 while i < n {
18581 let c = *src.add(i);
18582 *dest.add(i) = c;
18583 if c == 0 { return dest.add(i); }
18584 i += 1;
18585 }
18586 dest.add(n)
18587}
18588
18589#[no_mangle]
18590pub unsafe extern "C" fn wprintf(fmt: *const wchar_t, args: ...) -> c_int {
18591 vfwprintf(stdout, fmt, args)
18592}
18593
18594#[no_mangle]
18595pub unsafe extern "C" fn vwprintf(fmt: *const wchar_t, ap: core::ffi::VaList) -> c_int {
18596 vfwprintf(stdout, fmt, ap)
18597}
18598
18599#[no_mangle]
18604pub unsafe extern "C" fn c16rtomb(s: *mut u8, c16: u16, ps: *mut core::ffi::c_void) -> usize {
18605 let state = ps as *mut u32;
18607 let saved: u32 = if state.is_null() { 0 } else { *state };
18608 if s.is_null() {
18609 if !state.is_null() { *state = 0; }
18610 return 1;
18611 }
18612 let cp: u32;
18613 if saved != 0 {
18614 if c16 < 0xdc00 || c16 > 0xdfff {
18615 if !state.is_null() { *state = 0; }
18616 ERRNO!() = EILSEQ;
18617 return !0usize;
18618 }
18619 cp = 0x10000 + (((saved - 0xd800) << 10) | ((c16 as u32) - 0xdc00));
18620 if !state.is_null() { *state = 0; }
18621 } else if c16 >= 0xd800 && c16 <= 0xdbff {
18622 if !state.is_null() { *state = c16 as u32; }
18623 return 0;
18624 } else if c16 >= 0xdc00 && c16 <= 0xdfff {
18625 ERRNO!() = EILSEQ;
18626 return !0usize;
18627 } else {
18628 cp = c16 as u32;
18629 }
18630 if cp < 0x80 {
18631 *s = cp as u8;
18632 1
18633 } else if cp < 0x800 {
18634 *s = (0xc0 | (cp >> 6)) as u8;
18635 *s.add(1) = (0x80 | (cp & 0x3f)) as u8;
18636 2
18637 } else if cp < 0x10000 {
18638 *s = (0xe0 | (cp >> 12)) as u8;
18639 *s.add(1) = (0x80 | ((cp >> 6) & 0x3f)) as u8;
18640 *s.add(2) = (0x80 | (cp & 0x3f)) as u8;
18641 3
18642 } else {
18643 *s = (0xf0 | (cp >> 18)) as u8;
18644 *s.add(1) = (0x80 | ((cp >> 12) & 0x3f)) as u8;
18645 *s.add(2) = (0x80 | ((cp >> 6) & 0x3f)) as u8;
18646 *s.add(3) = (0x80 | (cp & 0x3f)) as u8;
18647 4
18648 }
18649}
18650
18651#[no_mangle]
18652pub unsafe extern "C" fn c32rtomb(s: *mut u8, c32: u32, _ps: *mut core::ffi::c_void) -> usize {
18653 if s.is_null() { return 1; }
18654 if c32 > 0x10ffff || (c32 >= 0xd800 && c32 <= 0xdfff) {
18655 ERRNO!() = EILSEQ;
18656 return !0usize;
18657 }
18658 if c32 < 0x80 {
18659 *s = c32 as u8;
18660 1
18661 } else if c32 < 0x800 {
18662 *s = (0xc0 | (c32 >> 6)) as u8;
18663 *s.add(1) = (0x80 | (c32 & 0x3f)) as u8;
18664 2
18665 } else if c32 < 0x10000 {
18666 *s = (0xe0 | (c32 >> 12)) as u8;
18667 *s.add(1) = (0x80 | ((c32 >> 6) & 0x3f)) as u8;
18668 *s.add(2) = (0x80 | (c32 & 0x3f)) as u8;
18669 3
18670 } else {
18671 *s = (0xf0 | (c32 >> 18)) as u8;
18672 *s.add(1) = (0x80 | ((c32 >> 12) & 0x3f)) as u8;
18673 *s.add(2) = (0x80 | ((c32 >> 6) & 0x3f)) as u8;
18674 *s.add(3) = (0x80 | (c32 & 0x3f)) as u8;
18675 4
18676 }
18677}
18678
18679#[no_mangle]
18680pub unsafe extern "C" fn mbrtoc16(pc16: *mut u16, s: *const u8, n: usize, _ps: *mut core::ffi::c_void) -> usize {
18681 if s.is_null() { return 0; }
18682 if n == 0 { return 1; }
18683 let c = *s;
18684 if c == 0 { return 0; }
18685 if c < 0x80 {
18686 if !pc16.is_null() { *pc16 = c as u16; }
18687 return 1;
18688 }
18689 if c < 0xC2 { return 1; } if c < 0xE0 {
18691 if n < 2 { return 1; }
18692 let c2 = *s.add(1);
18693 if (c2 & 0xC0) != 0x80 { return 1; }
18694 if !pc16.is_null() { *pc16 = ((((c & 0x1F) as u32) << 6) | ((c2 & 0x3F) as u32)) as u16; }
18695 return 2;
18696 }
18697 if c < 0xF0 {
18698 if n < 3 { return 1; }
18699 let c2 = *s.add(1);
18700 let c3 = *s.add(2);
18701 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 { return 1; }
18702 if !pc16.is_null() { *pc16 = ((((c & 0x0F) as u32) << 12) | (((c2 & 0x3F) as u32) << 6) | ((c3 & 0x3F) as u32)) as u16; }
18703 return 3;
18704 }
18705 1
18706}
18707
18708#[no_mangle]
18709pub unsafe extern "C" fn mbrtoc32(pc32: *mut u32, s: *const u8, n: usize, _ps: *mut core::ffi::c_void) -> usize {
18710 if s.is_null() { return 0; }
18711 if n == 0 { return 1; }
18712 let c = *s;
18713 if c == 0 { return 0; }
18714 if c < 0x80 {
18715 if !pc32.is_null() { *pc32 = c as u32; }
18716 return 1;
18717 }
18718 if c < 0xC2 { return 1; } if c < 0xE0 {
18720 if n < 2 { return 1; }
18721 let c2 = *s.add(1);
18722 if (c2 & 0xC0) != 0x80 { return 1; }
18723 if !pc32.is_null() { *pc32 = (((c & 0x1F) as u32) << 6) | ((c2 & 0x3F) as u32); }
18724 return 2;
18725 }
18726 if c < 0xF0 {
18727 if n < 3 { return 1; }
18728 let c2 = *s.add(1);
18729 let c3 = *s.add(2);
18730 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 { return 1; }
18731 if !pc32.is_null() { *pc32 = (((c & 0x0F) as u32) << 12) | (((c2 & 0x3F) as u32) << 6) | ((c3 & 0x3F) as u32); }
18732 return 3;
18733 }
18734 if c < 0xF5 {
18735 if n < 4 { return 1; }
18736 let c2 = *s.add(1);
18737 let c3 = *s.add(2);
18738 let c4 = *s.add(3);
18739 if (c2 & 0xC0) != 0x80 || (c3 & 0xC0) != 0x80 || (c4 & 0xC0) != 0x80 { return 1; }
18740 if !pc32.is_null() { *pc32 = (((c & 0x07) as u32) << 18) | (((c2 & 0x3F) as u32) << 12) | (((c3 & 0x3F) as u32) << 6) | ((c4 & 0x3F) as u32); }
18741 return 4;
18742 }
18743 1
18744}
18745
18746#[no_mangle]
18758pub unsafe extern "C" fn chown(path: *const core::ffi::c_char, uid: u32, gid: u32) -> i32 {
18759 syscall_ret(<Arch as Syscalls>::syscall5(
18760 SYS_FCHOWNAT,
18761 AT_FDCWD as i64,
18762 path as i64,
18763 uid as i64,
18764 gid as i64,
18765 0,
18766 )) as i32
18767}
18768
18769#[no_mangle]
18770pub unsafe extern "C" fn lchown(path: *const core::ffi::c_char, uid: u32, gid: u32) -> i32 {
18771 syscall_ret(<Arch as Syscalls>::syscall5(
18772 SYS_FCHOWNAT,
18773 AT_FDCWD as i64,
18774 path as i64,
18775 uid as i64,
18776 gid as i64,
18777 0x100, )) as i32
18779}
18780
18781#[no_mangle]
18786pub unsafe extern "C" fn chroot(path: *const core::ffi::c_char) -> i32 {
18787 syscall_ret(<Arch as Syscalls>::syscall1(SYS_CHROOT, path as i64)) as i32
18788}
18789
18790#[no_mangle]
18791pub unsafe extern "C" fn get_current_dir_name() -> *mut core::ffi::c_char {
18792 static mut BUF: [core::ffi::c_char; 4096] = [0; 4096];
18793 let r = getcwd(BUF.as_mut_ptr(), 4096);
18794 if r.is_null() { core::ptr::null_mut() } else { BUF.as_mut_ptr() }
18795}
18796
18797#[no_mangle]
18802pub unsafe extern "C" fn creat(pathname: *const core::ffi::c_char, mode: u32) -> i32 {
18803 open(pathname, 1 | 0o100 | 0o1000, mode as i32)
18805}
18806
18807#[no_mangle]
18808pub unsafe extern "C" fn openat(dirfd: i32, pathname: *const core::ffi::c_char, flags: i32, mode: u32) -> i32 {
18809 syscall_ret(<Arch as Syscalls>::syscall4(SYS_OPENAT, dirfd as i64, pathname as i64, flags as i64, mode as i64)) as i32
18810}
18811
18812#[no_mangle]
18813pub unsafe extern "C" fn pwrite(fd: i32, buf: *const u8, count: usize, offset: i64) -> isize {
18814 syscall_ret(<Arch as Syscalls>::syscall4(sysno(18, 68), fd as i64, buf as i64, count as i64, offset)) as isize
18815}
18816
18817#[no_mangle]
18818pub unsafe extern "C" fn readv(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32) -> isize {
18819 syscall_ret(<Arch as Syscalls>::syscall3(sysno(19, 65), fd as i64, iov as i64, iovcnt as i64)) as isize
18820}
18821
18822#[no_mangle]
18823pub unsafe extern "C" fn writev(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32) -> isize {
18824 syscall_ret(<Arch as Syscalls>::syscall3(sysno(20, 66), fd as i64, iov as i64, iovcnt as i64)) as isize
18825}
18826
18827#[no_mangle]
18832pub unsafe extern "C" fn flock(fd: i32, operation: i32) -> i32 {
18833 syscall_ret(<Arch as Syscalls>::syscall2(SYS_FLOCK, fd as i64, operation as i64)) as i32
18834}
18835
18836#[no_mangle]
18837pub unsafe extern "C" fn lockf(fd: i32, cmd: i32, len: i64) -> i32 {
18838 let r = <Arch as Syscalls>::syscall3(SYS_FCNTL, fd as i64, if cmd == 0 { 7 } else if cmd == 1 { 6 } else { 5 } , len);
18839 if r < 0 { return -1; }
18840 0
18841}
18842
18843#[no_mangle]
18848pub unsafe extern "C" fn getdomainname(name: *mut core::ffi::c_char, len: usize) -> i32 {
18849 if name.is_null() || len == 0 {
18850 ERRNO!() = EINVAL;
18851 return -1;
18852 }
18853 let mut uts: UtsName = core::mem::zeroed();
18854 let r = <Arch as Syscalls>::syscall1(SYS_UNAME, &mut uts as *mut UtsName as i64);
18855 if r < 0 {
18856 ERRNO!() = (-r) as c_int;
18857 return -1;
18858 }
18859 let mut n = 0usize;
18860 while n < uts.domainname.len() && uts.domainname[n] != 0 { n += 1; }
18861 if n >= len {
18862 ERRNO!() = EINVAL;
18863 return -1;
18864 }
18865 core::ptr::copy_nonoverlapping(uts.domainname.as_ptr(), name as *mut u8, n);
18866 *name.add(n) = 0;
18867 0
18868}
18869
18870#[no_mangle]
18871pub unsafe extern "C" fn setdomainname(name: *const core::ffi::c_char, len: usize) -> i32 {
18872 syscall_ret(<Arch as Syscalls>::syscall2(sysno(171, 162), name as i64, len as i64)) as i32
18873}
18874
18875#[no_mangle]
18876pub unsafe extern "C" fn sethostname(name: *const core::ffi::c_char, len: usize) -> i32 {
18877 syscall_ret(<Arch as Syscalls>::syscall2(SYS_SETHOSTNAME, name as i64, len as i64)) as i32
18878}
18879
18880#[no_mangle]
18881pub unsafe extern "C" fn getlogin_r(name: *mut core::ffi::c_char, bufsize: usize) -> i32 {
18882 let user = crate::getenv(b"USER\0".as_ptr() as *const core::ffi::c_char);
18884 if user.is_null() { return 2; }
18885 let mut i = 0;
18886 while i < bufsize - 1 && *user.add(i) != 0 {
18887 *name.add(i) = *user.add(i);
18888 i += 1;
18889 }
18890 *name.add(i) = 0;
18891 0
18892}
18893
18894#[no_mangle]
18895pub unsafe extern "C" fn cuserid(s: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
18896 let user = crate::getenv(b"USER\0".as_ptr() as *const core::ffi::c_char);
18897 if user.is_null() { return core::ptr::null_mut(); }
18898 if s.is_null() {
18899 static mut BUF: [core::ffi::c_char; 32] = [0; 32];
18900 let mut i = 0;
18901 while i < 31 && *user.add(i) != 0 { BUF[i] = *user.add(i); i += 1; }
18902 BUF[i] = 0;
18903 BUF.as_mut_ptr()
18904 } else {
18905 let mut i = 0;
18906 while i < 31 && *user.add(i) != 0 { *s.add(i) = *user.add(i); i += 1; }
18907 *s.add(i) = 0;
18908 s
18909 }
18910}
18911
18912#[repr(C)]
18917#[derive(Copy, Clone)]
18918pub struct Passwd {
18919 pub pw_name: *mut c_char,
18920 pub pw_passwd: *mut c_char,
18921 pub pw_uid: u32,
18922 pub pw_gid: u32,
18923 pub pw_gecos: *mut c_char,
18924 pub pw_dir: *mut c_char,
18925 pub pw_shell: *mut c_char,
18926}
18927
18928#[repr(C)]
18929#[derive(Copy, Clone)]
18930pub struct Group {
18931 pub gr_name: *mut c_char,
18932 pub gr_passwd: *mut c_char,
18933 pub gr_gid: u32,
18934 pub gr_mem: *mut *mut c_char,
18935}
18936
18937static mut PWD_ENT: Passwd = Passwd {
18938 pw_name: core::ptr::null_mut(), pw_passwd: core::ptr::null_mut(),
18939 pw_uid: 0, pw_gid: 0, pw_gecos: core::ptr::null_mut(),
18940 pw_dir: core::ptr::null_mut(), pw_shell: core::ptr::null_mut(),
18941};
18942static mut PWD_BUF: [c_char; 1024] = [0; 1024];
18943static mut PWD_FILE: *mut FILE = core::ptr::null_mut();
18944
18945static mut GRP_ENT: Group = Group {
18946 gr_name: core::ptr::null_mut(), gr_passwd: core::ptr::null_mut(),
18947 gr_gid: 0, gr_mem: core::ptr::null_mut(),
18948};
18949static mut GRP_BUF: [c_char; 2048] = [0; 2048];
18950static mut GRP_MEM: [*mut c_char; 32] = [core::ptr::null_mut(); 32];
18951static mut GRP_FILE: *mut FILE = core::ptr::null_mut();
18952
18953unsafe fn parse_passwd(line: *const c_char, ent: *mut Passwd, buf: *mut c_char, buflen: usize) -> bool {
18954 let mut src = line;
18955 let mut o = 0usize;
18956 let mut fields: [*mut c_char; 7] = [core::ptr::null_mut(); 7];
18957 let mut n = 0usize;
18958 while n < 7 {
18959 let start = o;
18960 while *src != 0 && *src != b':' as c_char {
18961 if o + 1 >= buflen { return false; }
18962 *buf.add(o) = *src;
18963 o += 1;
18964 src = src.add(1);
18965 }
18966 *buf.add(o) = 0;
18967 o += 1;
18968 fields[n] = buf.add(start);
18969 n += 1;
18970 if *src == 0 { break; }
18971 src = src.add(1);
18972 }
18973 if n < 7 { return false; }
18974 (*ent).pw_name = fields[0];
18975 (*ent).pw_passwd = fields[1];
18976 (*ent).pw_uid = crate::strtol(fields[2], core::ptr::null_mut(), 10) as u32;
18977 (*ent).pw_gid = crate::strtol(fields[3], core::ptr::null_mut(), 10) as u32;
18978 (*ent).pw_gecos = fields[4];
18979 (*ent).pw_dir = fields[5];
18980 (*ent).pw_shell = fields[6];
18981 true
18982}
18983
18984unsafe fn parse_group(line: *const c_char, ent: *mut Group, buf: *mut c_char, buflen: usize) -> bool {
18985 let mut src = line;
18986 let mut o = 0usize;
18987 let mut fields: [*mut c_char; 4] = [core::ptr::null_mut(); 4];
18988 let mut n = 0usize;
18989 while n < 4 {
18990 let start = o;
18991 while *src != 0 && *src != b':' as c_char {
18992 if o + 1 >= buflen { return false; }
18993 *buf.add(o) = *src;
18994 o += 1;
18995 src = src.add(1);
18996 }
18997 *buf.add(o) = 0;
18998 o += 1;
18999 fields[n] = buf.add(start);
19000 n += 1;
19001 if *src == 0 { break; }
19002 src = src.add(1);
19003 }
19004 if n < 4 { return false; }
19005 (*ent).gr_name = fields[0];
19006 (*ent).gr_passwd = fields[1];
19007 (*ent).gr_gid = crate::strtol(fields[2], core::ptr::null_mut(), 10) as u32;
19008 let mut mi = 0usize;
19009 let mut m = fields[3];
19010 if *m != 0 {
19011 loop {
19012 if mi + 1 >= GRP_MEM.len() { break; }
19013 GRP_MEM[mi] = m;
19014 mi += 1;
19015 while *m != 0 && *m != b',' as c_char { m = m.add(1); }
19016 if *m == 0 { break; }
19017 *m = 0;
19018 m = m.add(1);
19019 }
19020 }
19021 GRP_MEM[mi] = core::ptr::null_mut();
19022 (*ent).gr_mem = GRP_MEM.as_mut_ptr();
19023 true
19024}
19025
19026#[no_mangle]
19027pub unsafe extern "C" fn getpwnam(name: *const c_char) -> *mut Passwd {
19028 if name.is_null() { return core::ptr::null_mut(); }
19029 setpwent();
19030 loop {
19031 let p = getpwent();
19032 if p.is_null() { break; }
19033 if crate::strcmp((*p).pw_name as *const u8, name as *const u8) == 0 { endpwent(); return p; }
19034 }
19035 endpwent();
19036 core::ptr::null_mut()
19037}
19038
19039#[no_mangle]
19040pub unsafe extern "C" fn getpwuid(uid: u32) -> *mut Passwd {
19041 setpwent();
19042 loop {
19043 let p = getpwent();
19044 if p.is_null() { break; }
19045 if (*p).pw_uid == uid { endpwent(); return p; }
19046 }
19047 endpwent();
19048 core::ptr::null_mut()
19049}
19050
19051#[no_mangle]
19052pub unsafe extern "C" fn setpwent() {
19053 endpwent();
19054 PWD_FILE = crate::fopen(b"/etc/passwd\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
19055}
19056
19057#[no_mangle]
19058pub unsafe extern "C" fn getpwent() -> *mut Passwd {
19059 if PWD_FILE.is_null() { setpwent(); if PWD_FILE.is_null() { return core::ptr::null_mut(); } }
19060 let mut line = [0 as c_char; 1024];
19061 loop {
19062 if crate::fgets(line.as_mut_ptr(), 1024, PWD_FILE).is_null() { return core::ptr::null_mut(); }
19063 if parse_passwd(line.as_ptr(), &raw mut PWD_ENT, PWD_BUF.as_mut_ptr(), PWD_BUF.len()) {
19064 return &raw mut PWD_ENT;
19065 }
19066 }
19067}
19068
19069#[no_mangle]
19070pub unsafe extern "C" fn endpwent() {
19071 if !PWD_FILE.is_null() { crate::fclose(PWD_FILE); PWD_FILE = core::ptr::null_mut(); }
19072}
19073
19074#[no_mangle]
19075pub 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 {
19076 if result.is_null() { return EINVAL; }
19077 let p = getpwnam(name);
19078 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *pwd = *p; *result = pwd; 0 }
19079}
19080
19081#[no_mangle]
19082pub unsafe extern "C" fn getpwuid_r(uid: u32, pwd: *mut Passwd, _buf: *mut c_char, _buflen: usize, result: *mut *mut Passwd) -> c_int {
19083 if result.is_null() { return EINVAL; }
19084 let p = getpwuid(uid);
19085 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *pwd = *p; *result = pwd; 0 }
19086}
19087
19088#[no_mangle]
19089pub unsafe extern "C" fn fgetpwent(f: *mut FILE) -> *mut Passwd {
19090 if f.is_null() { return core::ptr::null_mut(); }
19091 let mut line = [0 as c_char; 1024];
19092 loop {
19093 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
19094 if parse_passwd(line.as_ptr(), &raw mut PWD_ENT, PWD_BUF.as_mut_ptr(), PWD_BUF.len()) {
19095 return &raw mut PWD_ENT;
19096 }
19097 }
19098}
19099
19100#[no_mangle]
19101pub unsafe extern "C" fn putpwent(f: *mut FILE, p: *const Passwd) -> c_int {
19102 if f.is_null() || p.is_null() { return -1; }
19103 crate::fprintf(f, b"%s:%s:%u:%u:%s:%s:%s\n\0".as_ptr() as *const c_char,
19104 (*p).pw_name, (*p).pw_passwd, (*p).pw_uid, (*p).pw_gid,
19105 (*p).pw_gecos, (*p).pw_dir, (*p).pw_shell)
19106}
19107
19108#[no_mangle]
19109pub unsafe extern "C" fn getgrnam(name: *const c_char) -> *mut Group {
19110 if name.is_null() { return core::ptr::null_mut(); }
19111 setgrent();
19112 loop {
19113 let g = getgrent();
19114 if g.is_null() { break; }
19115 if crate::strcmp((*g).gr_name as *const u8, name as *const u8) == 0 { endgrent(); return g; }
19116 }
19117 endgrent();
19118 core::ptr::null_mut()
19119}
19120
19121#[no_mangle]
19122pub unsafe extern "C" fn getgrgid(gid: u32) -> *mut Group {
19123 setgrent();
19124 loop {
19125 let g = getgrent();
19126 if g.is_null() { break; }
19127 if (*g).gr_gid == gid { endgrent(); return g; }
19128 }
19129 endgrent();
19130 core::ptr::null_mut()
19131}
19132
19133#[no_mangle]
19134pub unsafe extern "C" fn setgrent() {
19135 endgrent();
19136 GRP_FILE = crate::fopen(b"/etc/group\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
19137}
19138
19139#[no_mangle]
19140pub unsafe extern "C" fn getgrent() -> *mut Group {
19141 if GRP_FILE.is_null() { setgrent(); if GRP_FILE.is_null() { return core::ptr::null_mut(); } }
19142 let mut line = [0 as c_char; 1024];
19143 loop {
19144 if crate::fgets(line.as_mut_ptr(), 1024, GRP_FILE).is_null() { return core::ptr::null_mut(); }
19145 if parse_group(line.as_ptr(), &raw mut GRP_ENT, GRP_BUF.as_mut_ptr(), GRP_BUF.len()) {
19146 return &raw mut GRP_ENT;
19147 }
19148 }
19149}
19150
19151#[no_mangle]
19152pub unsafe extern "C" fn endgrent() {
19153 if !GRP_FILE.is_null() { crate::fclose(GRP_FILE); GRP_FILE = core::ptr::null_mut(); }
19154}
19155
19156#[no_mangle]
19157pub 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 {
19158 if result.is_null() { return EINVAL; }
19159 let g = getgrnam(name);
19160 if g.is_null() { *result = core::ptr::null_mut(); 0 } else { *grp = *g; *result = grp; 0 }
19161}
19162
19163#[no_mangle]
19164pub unsafe extern "C" fn getgrgid_r(gid: u32, grp: *mut Group, _buf: *mut c_char, _buflen: usize, result: *mut *mut Group) -> c_int {
19165 if result.is_null() { return EINVAL; }
19166 let g = getgrgid(gid);
19167 if g.is_null() { *result = core::ptr::null_mut(); 0 } else { *grp = *g; *result = grp; 0 }
19168}
19169
19170#[no_mangle]
19171pub unsafe extern "C" fn fgetgrent(f: *mut FILE) -> *mut Group {
19172 if f.is_null() { return core::ptr::null_mut(); }
19173 let mut line = [0 as c_char; 1024];
19174 loop {
19175 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
19176 if parse_group(line.as_ptr(), &raw mut GRP_ENT, GRP_BUF.as_mut_ptr(), GRP_BUF.len()) {
19177 return &raw mut GRP_ENT;
19178 }
19179 }
19180}
19181
19182#[no_mangle]
19183pub unsafe extern "C" fn putgrent(f: *mut FILE, g: *const Group) -> c_int {
19184 if f.is_null() || g.is_null() { return -1; }
19185 crate::fprintf(f, b"%s:%s:%u:\0".as_ptr() as *const c_char, (*g).gr_name, (*g).gr_passwd, (*g).gr_gid);
19186 if !(*g).gr_mem.is_null() {
19187 let mut i = 0;
19188 while !(*(*g).gr_mem.add(i)).is_null() {
19189 if i > 0 { crate::fputc(b',' as c_int, f); }
19190 crate::fputs(*(*g).gr_mem.add(i), f);
19191 i += 1;
19192 }
19193 }
19194 crate::fputc(b'\n' as c_int, f);
19195 0
19196}
19197
19198#[no_mangle]
19203pub unsafe extern "C" fn setgroups(ngroups: usize, gidset: *const u32) -> i32 {
19204 syscall_ret(<Arch as Syscalls>::syscall2(SYS_SETGROUPS, ngroups as i64, gidset as i64)) as i32
19205}
19206
19207#[no_mangle]
19208pub unsafe extern "C" fn setresuid(ruid: u32, euid: u32, suid: u32) -> i32 {
19209 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SETRESUID, ruid as i64, euid as i64, suid as i64)) as i32
19210}
19211
19212#[no_mangle]
19213pub unsafe extern "C" fn setresgid(rgid: u32, egid: u32, sgid: u32) -> i32 {
19214 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SETRESGID, rgid as i64, egid as i64, sgid as i64)) as i32
19215}
19216
19217#[no_mangle]
19218pub unsafe extern "C" fn getresuid(ruid: *mut u32, euid: *mut u32, suid: *mut u32) -> i32 {
19219 syscall_ret(<Arch as Syscalls>::syscall3(SYS_GETRESUID, ruid as i64, euid as i64, suid as i64)) as i32
19220}
19221
19222#[no_mangle]
19223pub unsafe extern "C" fn getresgid(rgid: *mut u32, egid: *mut u32, sgid: *mut u32) -> i32 {
19224 syscall_ret(<Arch as Syscalls>::syscall3(SYS_GETRESGID, rgid as i64, egid as i64, sgid as i64)) as i32
19225}
19226
19227#[repr(C)]
19235struct KernelMsgHdr {
19236 msg_name: *mut c_void,
19237 msg_namelen: u32,
19238 __pad0: u32,
19239 msg_iov: *mut c_void,
19240 msg_iovlen: u64,
19241 msg_control: *mut c_void,
19242 msg_controllen: u64,
19243 msg_flags: u32,
19244 __pad1: u32,
19245}
19246
19247#[repr(C)]
19248struct UserMsgHdr {
19249 msg_name: *mut c_void,
19250 msg_namelen: u32,
19251 msg_iov: *mut c_void,
19252 msg_iovlen: i32,
19253 __pad1: i32,
19254 msg_control: *mut c_void,
19255 msg_controllen: u32,
19256 __pad2: i32,
19257 msg_flags: i32,
19258}
19259
19260unsafe fn msg_to_kernel(msg: *const UserMsgHdr, out: &mut KernelMsgHdr) {
19261 *out = KernelMsgHdr {
19262 msg_name: (*msg).msg_name,
19263 msg_namelen: (*msg).msg_namelen,
19264 __pad0: 0,
19265 msg_iov: (*msg).msg_iov,
19266 msg_iovlen: (*msg).msg_iovlen as u32 as u64,
19267 msg_control: (*msg).msg_control,
19268 msg_controllen: (*msg).msg_controllen as u64,
19269 msg_flags: (*msg).msg_flags as u32,
19270 __pad1: 0,
19271 };
19272}
19273
19274#[no_mangle]
19275pub unsafe extern "C" fn sendmsg(fd: i32, msg: *const core::ffi::c_void, flags: i32) -> isize {
19276 if msg.is_null() {
19277 ERRNO!() = EINVAL;
19278 return -1;
19279 }
19280 let mut k: KernelMsgHdr = core::mem::zeroed();
19281 msg_to_kernel(msg as *const UserMsgHdr, &mut k);
19282 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SENDMSG, fd as i64, &k as *const KernelMsgHdr as i64, flags as i64)) as isize
19283}
19284
19285#[no_mangle]
19286pub unsafe extern "C" fn recvmsg(fd: i32, msg: *mut core::ffi::c_void, flags: i32) -> isize {
19287 if msg.is_null() {
19288 ERRNO!() = EINVAL;
19289 return -1;
19290 }
19291 let user = msg as *mut UserMsgHdr;
19292 let mut k: KernelMsgHdr = core::mem::zeroed();
19293 msg_to_kernel(user, &mut k);
19294 let r = syscall_ret(<Arch as Syscalls>::syscall3(SYS_RECVMSG, fd as i64, &mut k as *mut KernelMsgHdr as i64, flags as i64));
19295 (*user).msg_flags = k.msg_flags as i32;
19296 (*user).msg_controllen = k.msg_controllen as u32;
19297 r as isize
19298}
19299
19300#[no_mangle]
19301pub unsafe extern "C" fn sendmmsg(fd: i32, msgvec: *mut core::ffi::c_void, vlen: u32, flags: i32) -> i32 {
19302 syscall_ret(<Arch as Syscalls>::syscall4(sysno(307, 269), fd as i64, msgvec as i64, vlen as i64, flags as i64)) as i32
19303}
19304
19305#[no_mangle]
19306pub unsafe extern "C" fn recvmmsg(fd: i32, msgvec: *mut core::ffi::c_void, vlen: u32, flags: i32, timeout: *mut core::ffi::c_void) -> i32 {
19307 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
19308}
19309
19310#[no_mangle]
19311pub unsafe extern "C" fn getpeername(fd: i32, addr: *mut core::ffi::c_void, addrlen: *mut u32) -> i32 {
19312 syscall_ret(<Arch as Syscalls>::syscall3(sysno(52, 205), fd as i64, addr as i64, addrlen as i64)) as i32
19313}
19314
19315#[no_mangle]
19316pub unsafe extern "C" fn getsockopt(fd: i32, level: i32, optname: i32, optval: *mut core::ffi::c_void, optlen: *mut u32) -> i32 {
19317 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
19318}
19319
19320#[no_mangle]
19325pub unsafe extern "C" fn ftrylockfile(file: *mut FILE) -> i32 {
19326 if file.is_null() { return EINVAL; }
19327 if (*file).lock < 0 { return 0; }
19328 let tid = sys_gettid() as c_int;
19329 let v = a_load(&raw const (*file).lock);
19330 if v == tid {
19331 (*file).lockcount += 1;
19332 return 0;
19333 }
19334 if v == 0 && a_cas(&raw mut (*file).lock, 0, tid) == 0 {
19335 (*file).lockcount = 1;
19336 return 0;
19337 }
19338 EBUSY
19339}
19340
19341#[no_mangle]
19342pub unsafe extern "C" fn getc_unlocked(file: *mut core::ffi::c_char) -> i32 {
19343 getc(file as *mut FILE)
19344}
19345
19346#[no_mangle]
19347pub unsafe extern "C" fn getchar_unlocked() -> i32 {
19348 getchar()
19349}
19350
19351#[no_mangle]
19352pub unsafe extern "C" fn putc_unlocked(c: i32, file: *mut core::ffi::c_char) -> i32 {
19353 putc(c, file as *mut FILE)
19354}
19355
19356#[no_mangle]
19357pub unsafe extern "C" fn putchar_unlocked(c: i32) -> i32 {
19358 putchar(c)
19359}
19360
19361#[no_mangle] pub static mut optarg: *mut core::ffi::c_char = core::ptr::null_mut();
19366#[no_mangle] pub static mut optind: i32 = 1;
19367#[no_mangle] pub static mut opterr: i32 = 1;
19368#[no_mangle] pub static mut optopt: i32 = '?' as i32;
19369#[no_mangle] pub static mut optreset: i32 = 0;
19370
19371#[no_mangle]
19376pub unsafe extern "C" fn getitimer(which: i32, curr_value: *mut core::ffi::c_void) -> i32 {
19377 syscall_ret(<Arch as Syscalls>::syscall2(sysno(36, 102), which as i64, curr_value as i64)) as i32
19378}
19379
19380#[no_mangle]
19381pub unsafe extern "C" fn setitimer(which: i32, new_value: *const core::ffi::c_void, old_value: *mut core::ffi::c_void) -> i32 {
19382 syscall_ret(<Arch as Syscalls>::syscall3(sysno(38, 103), which as i64, new_value as i64, old_value as i64)) as i32
19383}
19384
19385#[no_mangle]
19390pub unsafe extern "C" fn getloadavg(loadavg: *mut f64, nelem: i32) -> i32 {
19391 let fd = crate::open(b"/proc/loadavg\0".as_ptr() as *const core::ffi::c_char, 0, 0);
19392 if fd < 0 { return -1; }
19393 let mut buf: [u8; 64] = [0; 64];
19394 let n = crate::read(fd, buf.as_mut_ptr() as *mut core::ffi::c_void, 63);
19395 crate::close(fd);
19396 if n <= 0 { return -1; }
19397 buf[n as usize] = 0;
19398 let mut i = 0;
19399 while i < nelem as usize && i < 3 {
19400 let val = crate::strtod((buf.as_ptr() as *const core::ffi::c_char).add(i * 5), core::ptr::null_mut());
19401 *loadavg.add(i) = val;
19402 i += 1;
19403 }
19404 i as i32
19405}
19406
19407#[no_mangle]
19408pub unsafe extern "C" fn get_nprocs() -> i32 {
19409 sysconf(84) as i32 }
19411
19412#[no_mangle]
19413pub unsafe extern "C" fn get_nprocs_conf() -> i32 {
19414 sysconf(83) as i32 }
19416
19417#[no_mangle]
19418pub unsafe extern "C" fn get_avphys_pages() -> i64 {
19419 sysconf(86) }
19421
19422#[no_mangle]
19423pub unsafe extern "C" fn get_phys_pages() -> i64 {
19424 sysconf(85) }
19426
19427#[no_mangle]
19432pub unsafe extern "C" fn capget(header: *mut core::ffi::c_void, data: *mut core::ffi::c_void) -> i32 {
19433 syscall_ret(<Arch as Syscalls>::syscall2(SYS_CAPGET, header as i64, data as i64)) as i32
19434}
19435
19436#[no_mangle]
19437pub unsafe extern "C" fn capset(header: *const core::ffi::c_void, data: *const core::ffi::c_void) -> i32 {
19438 syscall_ret(<Arch as Syscalls>::syscall2(SYS_CAPSET, header as i64, data as i64)) as i32
19439}
19440
19441#[no_mangle]
19442pub unsafe extern "C" fn arch_prctl(code: i32, addr: u64) -> i32 {
19443 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 }
19444}
19445
19446#[no_mangle]
19451pub unsafe extern "C" fn cfgetospeed(termios_p: *const core::ffi::c_void) -> u32 {
19452 unsafe { *(termios_p as *const u32).add(1) }
19453}
19454
19455#[no_mangle]
19456pub unsafe extern "C" fn cfgetispeed(termios_p: *const core::ffi::c_void) -> u32 {
19457 unsafe { *(termios_p as *const u32).add(2) }
19458}
19459
19460#[no_mangle]
19461pub unsafe extern "C" fn cfsetospeed(termios_p: *mut core::ffi::c_void, speed: u32) -> i32 {
19462 unsafe { *(termios_p as *mut u32).add(1) = speed; }
19463 0
19464}
19465
19466#[no_mangle]
19467pub unsafe extern "C" fn cfsetispeed(termios_p: *mut core::ffi::c_void, speed: u32) -> i32 {
19468 unsafe { *(termios_p as *mut u32).add(2) = speed; }
19469 0
19470}
19471
19472#[no_mangle]
19473pub unsafe extern "C" fn cfmakeraw(termios_p: *mut core::ffi::c_void) {
19474 unsafe {
19475 let p = termios_p as *mut u32;
19476 *p.add(0) &= !0o37;
19477 *p.add(0) &= !(0o4000 | 0o2000 | 0o10000 | 0o20);
19478 *p.add(0) |= 0o60;
19479 *p.add(3) &= !0o17;
19480 *p.add(3) &= !(0o1000 | 0o40000000);
19481 *p.add(1) = 1;
19482 *p.add(2) = 0;
19483 }
19484}
19485
19486#[no_mangle]
19491pub unsafe extern "C" fn getrusage(who: i32, usage: *mut core::ffi::c_void) -> i32 {
19492 syscall_ret(<Arch as Syscalls>::syscall2(sysno(98, 165), who as i64, usage as i64)) as i32
19493}
19494
19495#[no_mangle]
19496pub unsafe extern "C" fn getpriority(which: i32, who: u32) -> i32 {
19497 let r = <Arch as Syscalls>::syscall2(SYS_GETPRIORITY, which as i64, who as i64);
19499 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
19500 20 - r as i32
19501}
19502
19503#[no_mangle]
19504pub unsafe extern "C" fn setpriority(which: i32, who: u32, prio: i32) -> i32 {
19505 syscall_ret(<Arch as Syscalls>::syscall3(SYS_SETPRIORITY, which as i64, who as i64, prio as i64)) as i32
19506}
19507
19508#[no_mangle]
19509pub unsafe extern "C" fn prlimit(pid: u32, resource: i32, new_limit: *const core::ffi::c_void, old_limit: *mut core::ffi::c_void) -> i32 {
19510 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
19511}
19512
19513#[no_mangle]
19518pub unsafe extern "C" fn clone(
19519 func: usize,
19520 stack: *mut u8,
19521 flags: c_int,
19522 arg: *mut c_void,
19523 mut args: ...
19524) -> c_int {
19525 const CLONE_PIDFD_C: c_int = 0x00001000;
19527 const CLONE_VM_C: c_int = 0x00000100;
19528 const CLONE_THREAD_C: c_int = 0x00010000;
19529 const CLONE_SETTLS_C: c_int = 0x00080000;
19530 const CLONE_PARENT_SETTID_C: c_int = 0x00100000;
19531 const CLONE_CHILD_SETTID_C: c_int = 0x01000000;
19532 const CLONE_CHILD_CLEARTID_C: c_int = 0x00200000;
19533 let _ = CLONE_VM_C;
19534 if flags & (CLONE_THREAD_C | CLONE_SETTLS_C | CLONE_CHILD_CLEARTID_C) != 0
19535 || stack.is_null()
19536 {
19537 ERRNO!() = EINVAL;
19538 return -1;
19539 }
19540 let mut ptid: *mut c_int = core::ptr::null_mut();
19541 let mut tls: c_ulong = 0;
19542 let mut ctid: *mut c_int = core::ptr::null_mut();
19543 if flags & (CLONE_PIDFD_C | CLONE_PARENT_SETTID_C | CLONE_CHILD_SETTID_C) != 0 {
19544 ptid = args.next_arg::<*mut c_int>();
19545 }
19546 if flags & CLONE_CHILD_SETTID_C != 0 {
19547 tls = args.next_arg::<c_ulong>();
19548 ctid = args.next_arg::<*mut c_int>();
19549 }
19550 let r = __rc_clone(func, stack, flags as c_ulong, arg, ptid, tls, ctid);
19551 if r < 0 {
19552 ERRNO!() = (-r) as c_int;
19553 -1
19554 } else {
19555 r as c_int
19556 }
19557}
19558
19559#[no_mangle]
19560pub unsafe extern "C" fn _Fork() -> i32 {
19561 crate::fork()
19562}
19563
19564#[no_mangle]
19565pub 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 {
19566 let mut master: i32 = 0;
19567 let mut slave: i32 = 0;
19568 if openpty(&mut master, &mut slave, name, termp, winp) < 0 { return -1; }
19569 let pid = crate::fork();
19570 if pid < 0 { crate::close(master); crate::close(slave); return -1; }
19571 if pid == 0 {
19572 crate::close(master);
19573 crate::setsid();
19574 crate::dup2(slave, 0);
19575 crate::dup2(slave, 1);
19576 crate::dup2(slave, 2);
19577 } else {
19578 crate::close(slave);
19579 if !amaster.is_null() { *amaster = master; }
19580 }
19581 pid
19582}
19583
19584#[no_mangle]
19585pub 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 {
19586 let master = crate::open(b"/dev/ptmx\0".as_ptr() as *const core::ffi::c_char, 0o2000, 0);
19587 if master < 0 { return -1; }
19588 grantpt(master);
19589 unlockpt(master);
19590 let slave_name = ptsname(master);
19591 if slave_name.is_null() { crate::close(master); return -1; }
19592 let slave = crate::open(slave_name, 0o2000, 0);
19593 if slave < 0 { crate::close(master); return -1; }
19594 if !amaster.is_null() { *amaster = master; }
19595 if !aslave.is_null() { *aslave = slave; }
19596 if !name.is_null() { crate::strcpy(name as *mut u8, slave_name as *const u8); }
19597 0
19598}
19599
19600#[no_mangle]
19601pub unsafe extern "C" fn login_tty(fd: i32) -> i32 {
19602 crate::setsid();
19603 crate::dup2(fd, 0);
19604 crate::dup2(fd, 1);
19605 crate::dup2(fd, 2);
19606 0
19607}
19608
19609#[no_mangle]
19614pub unsafe extern "C" fn __dls2b() {}
19615#[no_mangle]
19616pub unsafe extern "C" fn __dls3() {}
19617#[no_mangle]
19618pub unsafe extern "C" fn _dlstart() {}
19619
19620#[no_mangle]
19625pub unsafe extern "C" fn index(s: *const core::ffi::c_char, c: i32) -> *mut core::ffi::c_char {
19626 let mut i = 0;
19627 loop {
19628 let ch = *s.add(i);
19629 if ch == c as core::ffi::c_char { return s.add(i) as *mut core::ffi::c_char; }
19630 if ch == 0 { return core::ptr::null_mut(); }
19631 i += 1;
19632 }
19633}
19634
19635#[no_mangle]
19636pub unsafe extern "C" fn rindex(s: *const core::ffi::c_char, c: i32) -> *mut core::ffi::c_char {
19637 let mut last = core::ptr::null_mut();
19638 let mut i = 0;
19639 loop {
19640 let ch = *s.add(i);
19641 if ch == 0 { return last; }
19642 if ch == c as core::ffi::c_char { last = s.add(i) as *mut core::ffi::c_char; }
19643 i += 1;
19644 }
19645}
19646
19647#[no_mangle]
19652pub unsafe extern "C" fn imaxabs(j: i64) -> i64 {
19653 j.abs()
19654}
19655
19656#[no_mangle]
19657pub unsafe extern "C" fn imaxdiv(numer: i64, denom: i64) -> (i64, i64) {
19658 (numer / denom, numer % denom)
19659}
19660
19661#[no_mangle]
19666pub static mut h_errno: i32 = 0;
19667
19668#[no_mangle]
19669pub unsafe extern "C" fn __h_errno_location() -> *mut i32 {
19670 &mut h_errno
19671}
19672
19673#[no_mangle]
19674pub unsafe extern "C" fn herror(s: *const core::ffi::c_char) {
19675 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
19676 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
19677 crate::write(2, hstrerror(*__h_errno_location()) as *const core::ffi::c_void, crate::strlen(hstrerror(*__h_errno_location())));
19678 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
19679}
19680
19681#[no_mangle]
19682pub unsafe extern "C" fn hstrerror(_err: i32) -> *const core::ffi::c_char {
19683 b"Unknown error\0".as_ptr() as *const core::ffi::c_char
19684}
19685
19686#[no_mangle]
19691pub unsafe extern "C" fn gettid() -> i32 {
19692 syscall_ret(<Arch as Syscalls>::syscall0(SYS_GETTID)) as i32
19693}
19694
19695#[no_mangle]
19700pub unsafe extern "C" fn ioctl(fd: i32, request: u32, mut args: ...) -> i32 {
19701 let arg = args.next_arg::<i64>();
19702 syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, request as i64, arg)) as i32
19703}
19704
19705#[no_mangle]
19706pub unsafe extern "C" fn ioperm(from: u64, num: u64, turn_on: i32) -> i32 {
19707 #[cfg(target_arch = "x86_64")]
19708 { syscall_ret(<Arch as Syscalls>::syscall3(SYS_IOPERM, from as i64, num as i64, turn_on as i64)) as i32 }
19709 #[cfg(not(target_arch = "x86_64"))]
19710 {
19711 let _ = (from, num, turn_on);
19712 ERRNO!() = ENOSYS_VAL;
19713 -1
19714 }
19715}
19716
19717#[no_mangle]
19718pub unsafe extern "C" fn iopl(level: i32) -> i32 {
19719 #[cfg(target_arch = "x86_64")]
19720 { syscall_ret(<Arch as Syscalls>::syscall1(SYS_IOPL, level as i64)) as i32 }
19721 #[cfg(not(target_arch = "x86_64"))]
19722 {
19723 let _ = level;
19724 ERRNO!() = ENOSYS_VAL;
19725 -1
19726 }
19727}
19728
19729#[no_mangle]
19734pub unsafe extern "C" fn getxattr(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(191, 8), path as i64, name as i64, value as i64, size as i64)) as isize
19736}
19737
19738#[no_mangle]
19739pub unsafe extern "C" fn lgetxattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19740 syscall_ret(<Arch as Syscalls>::syscall4(sysno(192, 9), path as i64, name as i64, value as i64, size as i64)) as isize
19741}
19742
19743#[no_mangle]
19744pub unsafe extern "C" fn fgetxattr(fd: i32, name: *const core::ffi::c_char, value: *mut u8, size: usize) -> isize {
19745 syscall_ret(<Arch as Syscalls>::syscall4(sysno(193, 10), fd as i64, name as i64, value as i64, size as i64)) as isize
19746}
19747
19748#[no_mangle]
19749pub unsafe extern "C" fn listxattr(path: *const core::ffi::c_char, list: *mut u8, size: usize) -> isize {
19750 syscall_ret(<Arch as Syscalls>::syscall3(sysno(194, 11), path as i64, list as i64, size as i64)) as isize
19751}
19752
19753#[no_mangle]
19754pub unsafe extern "C" fn llistxattr(path: *const core::ffi::c_char, list: *mut u8, size: usize) -> isize {
19755 syscall_ret(<Arch as Syscalls>::syscall3(sysno(195, 12), path as i64, list as i64, size as i64)) as isize
19756}
19757
19758#[no_mangle]
19759pub unsafe extern "C" fn flistxattr(fd: i32, list: *mut u8, size: usize) -> isize {
19760 syscall_ret(<Arch as Syscalls>::syscall3(sysno(196, 13), fd as i64, list as i64, size as i64)) as isize
19761}
19762
19763#[no_mangle]
19764pub 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 {
19765 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
19766}
19767
19768#[no_mangle]
19769pub 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 {
19770 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
19771}
19772
19773#[no_mangle]
19774pub unsafe extern "C" fn fsetxattr(fd: i32, name: *const core::ffi::c_char, value: *const u8, size: usize, flags: i32) -> i32 {
19775 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
19776}
19777
19778#[no_mangle]
19779pub unsafe extern "C" fn removexattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char) -> i32 {
19780 syscall_ret(<Arch as Syscalls>::syscall2(sysno(197, 14), path as i64, name as i64)) as i32
19781}
19782
19783#[no_mangle]
19784pub unsafe extern "C" fn lremovexattr(path: *const core::ffi::c_char, name: *const core::ffi::c_char) -> i32 {
19785 syscall_ret(<Arch as Syscalls>::syscall2(sysno(198, 15), path as i64, name as i64)) as i32
19786}
19787
19788#[no_mangle]
19789pub unsafe extern "C" fn fremovexattr(fd: i32, name: *const core::ffi::c_char) -> i32 {
19790 syscall_ret(<Arch as Syscalls>::syscall2(sysno(199, 16), fd as i64, name as i64)) as i32
19791}
19792
19793#[no_mangle]
19798pub unsafe extern "C" fn adjtime(_delta: *const core::ffi::c_void, olddelta: *mut core::ffi::c_void) -> i32 {
19799 syscall_ret(<Arch as Syscalls>::syscall1(SYS_ADJTIMEX, olddelta as i64)) as i32
19800}
19801
19802#[no_mangle]
19803pub unsafe extern "C" fn adjtimex(buf: *mut core::ffi::c_void) -> i32 {
19804 syscall_ret(<Arch as Syscalls>::syscall1(SYS_ADJTIMEX, buf as i64)) as i32
19805}
19806
19807const TIOCGPTN: i64 = 0x80045430;
19816const TIOCSPTLCK: i64 = 0x40045431;
19817
19818#[no_mangle]
19819pub unsafe extern "C" fn grantpt(_fd: i32) -> i32 {
19820 0
19822}
19823
19824#[no_mangle]
19825pub unsafe extern "C" fn unlockpt(fd: i32) -> i32 {
19826 let mut unlock: i32 = 0;
19827 let r = <Arch as Syscalls>::syscall3(
19828 SYS_IOCTL,
19829 fd as i64,
19830 TIOCSPTLCK,
19831 &mut unlock as *mut i32 as i64,
19832 );
19833 if r < 0 { -1 } else { 0 }
19834}
19835
19836#[no_mangle]
19837pub unsafe extern "C" fn ptsname(fd: i32) -> *mut core::ffi::c_char {
19838 static mut BUF: [core::ffi::c_char; 32] = [0; 32];
19839 let mut pty_nr: i32 = 0;
19840 if <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, TIOCGPTN, &mut pty_nr as *mut i32 as i64) < 0 {
19841 return core::ptr::null_mut();
19842 }
19843 BUF[0] = '/' as c_char; BUF[1] = 'd' as c_char; BUF[2] = 'e' as c_char; BUF[3] = 'v' as c_char;
19845 BUF[4] = '/' as c_char; BUF[5] = 'p' as c_char; BUF[6] = 't' as c_char; BUF[7] = 's' as c_char;
19846 BUF[8] = '/' as c_char;
19847 let mut n = pty_nr as usize;
19848 let mut i = 9;
19849 if n == 0 { BUF[i] = '0' as c_char; i += 1; }
19850 while n > 0 && i < 31 {
19851 BUF[i] = (b'0' + (n % 10) as u8) as c_char;
19852 n /= 10;
19853 i += 1;
19854 }
19855 BUF[i] = 0;
19856 BUF.as_mut_ptr()
19857}
19858
19859#[no_mangle]
19864pub unsafe extern "C" fn finite(x: f64) -> i32 {
19865 (!x.is_nan() && !x.is_infinite()) as i32
19866}
19867
19868#[no_mangle]
19869pub unsafe extern "C" fn finitef(x: f32) -> i32 {
19870 (!x.is_nan() && !x.is_infinite()) as i32
19871}
19872
19873#[no_mangle]
19874pub unsafe extern "C" fn __fpclassifyl(x: f64) -> i32 {
19875 __fpclassify(x)
19876}
19877
19878#[no_mangle]
19879pub unsafe extern "C" fn __signbitl(x: f64) -> i32 {
19880 __signbit(x)
19881}
19882
19883#[no_mangle]
19892pub unsafe extern "C" fn j0(x: f64) -> f64 {
19893 j0_impl(x)
19894}
19895
19896#[no_mangle]
19897pub unsafe extern "C" fn j0f(x: f32) -> f32 {
19898 libm::j0f(x)
19899}
19900
19901#[no_mangle]
19902pub unsafe extern "C" fn j1(x: f64) -> f64 {
19903 libm::j1(x)
19904}
19905
19906#[no_mangle]
19907pub unsafe extern "C" fn j1f(x: f32) -> f32 {
19908 libm::j1f(x)
19909}
19910
19911#[no_mangle]
19912pub unsafe extern "C" fn jn(n: i32, x: f64) -> f64 {
19913 libm::jn(n, x)
19914}
19915
19916#[no_mangle]
19917pub unsafe extern "C" fn jnf(n: i32, x: f32) -> f32 {
19918 libm::jnf(n, x)
19919}
19920
19921#[no_mangle]
19922pub unsafe extern "C" fn y0(x: f64) -> f64 {
19923 y0_impl(x)
19924}
19925
19926#[no_mangle]
19927pub unsafe extern "C" fn y0f(x: f32) -> f32 {
19928 if x.is_nan() { return x; }
19929 if x < 0.0 { return __math_invalidf(x); }
19930 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f32::NEG_INFINITY; }
19931 libm::y0f(x)
19932}
19933
19934#[no_mangle]
19935pub unsafe extern "C" fn y1(x: f64) -> f64 {
19936 if x.is_nan() { return x; }
19937 if x < 0.0 { return __math_invalid(x); }
19938 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f64::NEG_INFINITY; }
19939 libm::y1(x)
19940}
19941
19942#[no_mangle]
19943pub unsafe extern "C" fn y1f(x: f32) -> f32 {
19944 if x.is_nan() { return x; }
19945 if x < 0.0 { return __math_invalidf(x); }
19946 if x == 0.0 { feraiseexcept(FE_DIVBYZERO); return f32::NEG_INFINITY; }
19947 libm::y1f(x)
19948}
19949
19950#[no_mangle]
19951pub unsafe extern "C" fn yn(n: i32, x: f64) -> f64 {
19952 if x.is_nan() { return x; }
19953 if x < 0.0 { return __math_invalid(x); }
19954 if x == 0.0 {
19955 feraiseexcept(FE_DIVBYZERO);
19956 if n >= 0 { return f64::NEG_INFINITY; }
19957 }
19958 libm::yn(n, x)
19959}
19960
19961#[no_mangle]
19962pub unsafe extern "C" fn ynf(n: i32, x: f32) -> f32 {
19963 if x.is_nan() { return x; }
19964 if x < 0.0 { return __math_invalidf(x); }
19965 if x == 0.0 {
19966 feraiseexcept(FE_DIVBYZERO);
19967 if n >= 0 { return f32::NEG_INFINITY; }
19968 }
19969 libm::ynf(n, x)
19970}
19971
19972#[no_mangle]
19977pub unsafe extern "C" fn __ctype_b_loc() -> *mut *const u16 {
19978 static mut TABLE: *const u16 = core::ptr::null();
19979 &mut TABLE
19980}
19981
19982#[no_mangle]
19983pub unsafe extern "C" fn __ctype_tolower_loc() -> *mut *const i32 {
19984 static mut TABLE: *const i32 = core::ptr::null();
19985 &mut TABLE
19986}
19987
19988#[no_mangle]
19989pub unsafe extern "C" fn __ctype_toupper_loc() -> *mut *const i32 {
19990 static mut TABLE: *const i32 = core::ptr::null();
19991 &mut TABLE
19992}
19993
19994#[no_mangle]
19995pub unsafe extern "C" fn __isalnum_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
19996 (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
19997}
19998
19999#[no_mangle]
20000pub unsafe extern "C" fn __isalpha_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20001 (c >= 'A' as i32 && c <= 'Z' as i32 || c >= 'a' as i32 && c <= 'z' as i32) as i32
20002}
20003
20004#[no_mangle]
20005pub unsafe extern "C" fn __isblank_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20006 (c == ' ' as i32 || c == '\t' as i32) as i32
20007}
20008
20009#[no_mangle]
20010pub unsafe extern "C" fn __iscntrl_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20011 (c < 0x20 || c == 0x7f) as i32
20012}
20013
20014#[no_mangle]
20015pub unsafe extern "C" fn __isdigit_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20016 (c >= '0' as i32 && c <= '9' as i32) as i32
20017}
20018
20019#[no_mangle]
20020pub unsafe extern "C" fn __isgraph_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20021 (c > 0x20 && c < 0x7f) as i32
20022}
20023
20024#[no_mangle]
20025pub unsafe extern "C" fn __islower_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20026 (c >= 'a' as i32 && c <= 'z' as i32) as i32
20027}
20028
20029#[no_mangle]
20030pub unsafe extern "C" fn __isprint_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20031 (c >= 0x20 && c < 0x7f) as i32
20032}
20033
20034#[no_mangle]
20035pub unsafe extern "C" fn __ispunct_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20036 (c >= 0x21 && c <= 0x2f || c >= 0x3a && c <= 0x40 || c >= 0x5b && c <= 0x60 || c >= 0x7b && c <= 0x7e) as i32
20037}
20038
20039#[no_mangle]
20040pub unsafe extern "C" fn __isspace_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20041 (c == ' ' as i32 || c >= 0x09 && c <= 0x0d) as i32
20042}
20043
20044#[no_mangle]
20045pub unsafe extern "C" fn __isupper_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20046 (c >= 'A' as i32 && c <= 'Z' as i32) as i32
20047}
20048
20049#[no_mangle]
20050pub unsafe extern "C" fn __isxdigit_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
20051 (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
20052}
20053
20054#[no_mangle]
20059pub unsafe extern "C" fn __iswalnum_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20060 (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
20061}
20062
20063#[no_mangle]
20064pub unsafe extern "C" fn __iswalpha_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20065 (c >= 'A' as u32 && c <= 'Z' as u32 || c >= 'a' as u32 && c <= 'z' as u32) as i32
20066}
20067
20068#[no_mangle]
20069pub unsafe extern "C" fn __iswblank_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20070 (c == ' ' as u32 || c == '\t' as u32) as i32
20071}
20072
20073#[no_mangle]
20074pub unsafe extern "C" fn __iswcntrl_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20075 (c < 0x20 || c == 0x7f) as i32
20076}
20077
20078#[no_mangle]
20079pub unsafe extern "C" fn __iswdigit_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20080 (c >= '0' as u32 && c <= '9' as u32) as i32
20081}
20082
20083#[no_mangle]
20084pub unsafe extern "C" fn __iswgraph_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20085 (c > 0x20 && c < 0x7f) as i32
20086}
20087
20088#[no_mangle]
20089pub unsafe extern "C" fn __iswlower_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20090 (c >= 'a' as u32 && c <= 'z' as u32) as i32
20091}
20092
20093#[no_mangle]
20094pub unsafe extern "C" fn __iswprint_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20095 (c >= 0x20 && c < 0x7f) as i32
20096}
20097
20098#[no_mangle]
20099pub unsafe extern "C" fn __iswpunct_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20100 (c >= 0x21 && c <= 0x2f || c >= 0x3a && c <= 0x40 || c >= 0x5b && c <= 0x60 || c >= 0x7b && c <= 0x7e) as i32
20101}
20102
20103#[no_mangle]
20104pub unsafe extern "C" fn __iswspace_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20105 (c == ' ' as u32 || c >= 0x09 && c <= 0x0d) as i32
20106}
20107
20108#[no_mangle]
20109pub unsafe extern "C" fn __iswupper_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20110 (c >= 'A' as u32 && c <= 'Z' as u32) as i32
20111}
20112
20113#[no_mangle]
20114pub unsafe extern "C" fn __iswxdigit_l(c: u32, _loc: *mut core::ffi::c_void) -> i32 {
20115 (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
20116}
20117
20118#[no_mangle]
20119pub unsafe extern "C" fn __iswctype_l(c: u32, ctype: u32, _loc: *mut core::ffi::c_void) -> i32 {
20120 crate::iswctype(c as wint_t, ctype as wctype_t)
20121}
20122
20123#[no_mangle]
20124pub unsafe extern "C" fn __towlower_l(c: u32, _loc: *mut core::ffi::c_void) -> u32 {
20125 crate::towlower(c)
20126}
20127
20128#[no_mangle]
20129pub unsafe extern "C" fn __towupper_l(c: u32, _loc: *mut core::ffi::c_void) -> u32 {
20130 crate::towupper(c)
20131}
20132
20133#[no_mangle]
20134pub unsafe extern "C" fn __towctrans_l(c: u32, _trans: u32, _loc: *mut core::ffi::c_void) -> u32 {
20135 c
20136}
20137
20138#[no_mangle]
20151pub 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) {
20152 crate::write(2, b"Assertion failed: ".as_ptr() as *const core::ffi::c_void, 18);
20153 if !expr.is_null() { crate::write(2, expr as *const core::ffi::c_void, crate::strlen(expr)); }
20154 crate::write(2, b" (".as_ptr() as *const core::ffi::c_void, 2);
20155 if !file.is_null() { crate::write(2, file as *const core::ffi::c_void, crate::strlen(file)); }
20156 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
20157 let mut n = line as usize;
20158 let mut digits: [u8; 32] = [0; 32];
20159 let mut di = 0;
20160 if n == 0 { digits[0] = 0; di = 1; }
20161 while n > 0 && di < 32 { digits[di] = (n % 10) as u8; n /= 10; di += 1; }
20162 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); }
20163 crate::write(2, b")".as_ptr() as *const core::ffi::c_void, 1);
20164 if !func.is_null() { crate::write(2, func as *const core::ffi::c_void, crate::strlen(func)); }
20165 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20166 crate::abort()
20167}
20168
20169#[no_mangle]
20170pub unsafe extern "C" fn at_quick_exit(_func: Option<unsafe extern "C" fn()>) -> i32 {
20171 0
20173}
20174
20175#[no_mangle]
20176pub unsafe extern "C" fn brk(addr: *mut u8) -> i32 {
20177 syscall_ret(<Arch as Syscalls>::syscall1(sysno(12, 214), addr as i64)) as i32
20178}
20179
20180#[no_mangle]
20181pub 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 {
20182 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
20183}
20184
20185#[no_mangle]
20186pub unsafe extern "C" fn ctermid(s: *mut core::ffi::c_char) -> *mut core::ffi::c_char {
20187 static mut BUF: [core::ffi::c_char; 20] = [0; 20];
20188 let dst = if s.is_null() { BUF.as_mut_ptr() } else { s };
20189 let src = b"/dev/tty\0".as_ptr() as *const core::ffi::c_char;
20190 let mut i = 0;
20191 while i < 9 { *dst.add(i) = *src.add(i); i += 1; }
20192 dst
20193}
20194
20195#[no_mangle]
20196pub unsafe extern "C" fn delete_module(name: *const core::ffi::c_char, flags: u32) -> i32 {
20197 syscall_ret(<Arch as Syscalls>::syscall2(SYS_DELETE_MODULE, name as i64, flags as i64)) as i32
20198}
20199
20200
20201
20202
20203
20204#[no_mangle]
20205pub unsafe extern "C" fn __duplocale(loc: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
20206 loc
20207}
20208
20209#[no_mangle]
20210pub unsafe extern "C" fn euidaccess(pathname: *const core::ffi::c_char, mode: i32) -> i32 {
20211 faccessat(AT_FDCWD, pathname, mode, 0x200)
20212}
20213
20214#[no_mangle]
20215pub unsafe extern "C" fn fgetln(f: *mut core::ffi::c_void, lenp: *mut usize) -> *mut core::ffi::c_char {
20216 static mut BUF: [core::ffi::c_char; 4096] = [0; 4096];
20217 let mut i = 0;
20218 while i < 4095 {
20219 let c = getc(f as *mut FILE);
20220 if c < 0 { break; }
20221 BUF[i] = c as c_char;
20222 i += 1;
20223 if c == '\n' as i32 { break; }
20224 }
20225 BUF[i] = 0;
20226 if !lenp.is_null() { *lenp = i; }
20227 if i == 0 { core::ptr::null_mut() } else { BUF.as_mut_ptr() }
20228}
20229
20230#[no_mangle]
20231pub unsafe extern "C" fn fgetws(ws: *mut u32, n: i32, f: *mut core::ffi::c_void) -> *mut u32 {
20232 let mut i = 0;
20233 while i < n - 1 {
20234 let c = getwc(f as *mut core::ffi::c_void);
20235 if c == 0 { break; }
20236 *ws.add(i as usize) = c;
20237 i += 1;
20238 if c == '\n' as u32 { break; }
20239 }
20240 *ws.add(i as usize) = 0;
20241 if i == 0 { core::ptr::null_mut() } else { ws }
20242}
20243
20244#[no_mangle]
20245pub 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 {
20246 if !label.is_null() { crate::write(2, label as *const core::ffi::c_void, crate::strlen(label)); }
20247 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
20248 if !text.is_null() { crate::write(2, text as *const core::ffi::c_void, crate::strlen(text)); }
20249 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20250 0
20251}
20252
20253#[no_mangle]
20254pub unsafe extern "C" fn ftime(tp: *mut core::ffi::c_void) -> i32 {
20255 let mut tv: timeval = core::mem::zeroed();
20256 if gettimeofday(&mut tv, core::ptr::null_mut()) == 0 {
20257 let tb = tp as *mut Timeb;
20258 (*tb).time = tv.tv_sec;
20259 (*tb).millitm = (tv.tv_usec / 1000) as u16;
20260 (*tb).timezone = 0;
20261 (*tb).dstflag = 0;
20262 0
20263 } else {
20264 -1
20265 }
20266}
20267
20268#[no_mangle]
20269pub unsafe extern "C" fn getdents(fd: i32, dirp: *mut u8, count: usize) -> isize {
20270 syscall_ret(<Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, dirp as i64, count as i64)) as isize
20271}
20272
20273#[no_mangle]
20274pub unsafe extern "C" fn gethostid() -> i64 {
20275 let fd = crate::open(b"/proc/sys/kernel/random/boot_id\0".as_ptr() as *const core::ffi::c_char, 0, 0);
20277 if fd < 0 { return 0; }
20278 let mut buf: [u8; 64] = [0; 64];
20279 let n = crate::read(fd, buf.as_mut_ptr() as *mut core::ffi::c_void, 63);
20280 crate::close(fd);
20281 if n <= 0 { return 0; }
20282 buf[n as usize] = 0;
20283 crate::strtol(buf.as_ptr() as *const core::ffi::c_char, core::ptr::null_mut(), 16)
20284}
20285
20286#[no_mangle]
20287pub unsafe extern "C" fn getpass(prompt: *const core::ffi::c_char) -> *mut core::ffi::c_char {
20288 static mut BUF: [core::ffi::c_char; 128] = [0; 128];
20289 crate::write(2, prompt as *const core::ffi::c_void, crate::strlen(prompt));
20291 let n = crate::read(0, BUF.as_mut_ptr() as *mut core::ffi::c_void, 127);
20293 if n > 0 {
20294 let end = if BUF[(n - 1) as usize] == '\n' as c_char { n - 1 } else { n };
20295 BUF[end as usize] = 0;
20296 } else {
20297 BUF[0] = 0;
20298 }
20299 BUF.as_mut_ptr()
20300}
20301
20302#[no_mangle]
20303pub 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 {
20304 let s = *optionp;
20305 if s.is_null() { return -1; }
20306 let mut end = s;
20308 while *end != 0 && *end != ',' as c_char && *end != '=' as c_char { end = end.add(1); }
20309 let eq = *end == '=' as c_char;
20310 if eq { *end = 0; *valuep = end.add(1); }
20311 let mut i = 0;
20313 loop {
20314 let tok = *tokens.add(i);
20315 if tok.is_null() { break; }
20316 if crate::strcmp(s as *const u8, tok as *const u8) == 0 {
20317 while *end != 0 && *end != ',' as c_char { end = end.add(1); }
20319 if *end == ',' as c_char { end = end.add(1); }
20320 *optionp = end;
20321 return i as i32;
20322 }
20323 i += 1;
20324 }
20325 -1
20326}
20327
20328#[no_mangle]
20329pub unsafe extern "C" fn getw(f: *mut core::ffi::c_void) -> i32 {
20330 let c0 = getc(f as *mut FILE);
20331 if c0 < 0 { return -1; }
20332 let c1 = getc(f as *mut FILE);
20333 if c1 < 0 { return -1; }
20334 let c2 = getc(f as *mut FILE);
20335 if c2 < 0 { return -1; }
20336 let c3 = getc(f as *mut FILE);
20337 if c3 < 0 { return -1; }
20338 (c0 | (c1 << 8) | (c2 << 16) | (c3 << 24)) as i32
20339}
20340
20341#[no_mangle]
20342pub unsafe extern "C" fn getwc(f: *mut core::ffi::c_void) -> u32 {
20343 getc(f as *mut FILE) as u32
20344}
20345
20346#[no_mangle]
20347pub unsafe extern "C" fn init_module(module_image: *mut u8, len: usize, param_values: *const core::ffi::c_char) -> i32 {
20348 syscall_ret(<Arch as Syscalls>::syscall3(SYS_INIT_MODULE, module_image as i64, len as i64, param_values as i64)) as i32
20349}
20350
20351
20352
20353#[no_mangle]
20354pub unsafe extern "C" fn issetugid() -> i32 {
20355 let ruid = crate::getuid();
20356 let euid = crate::geteuid();
20357 let rgid = crate::getgid();
20358 let egid = crate::getegid();
20359 (ruid != euid || rgid != egid) as i32
20360}
20361
20362#[repr(C)]
20367struct PollTimespec {
20368 tv_sec: i64,
20369 tv_nsec: i64,
20370}
20371
20372#[no_mangle]
20373pub unsafe extern "C" fn poll(fds: *mut core::ffi::c_void, nfds: u32, timeout: i32) -> i32 {
20374 #[cfg(target_arch = "x86_64")]
20375 { syscall_ret(<Arch as Syscalls>::syscall3(SYS_POLL, fds as i64, nfds as i64, timeout as i64)) as i32 }
20376 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
20377 {
20378 let mut ts = PollTimespec { tv_sec: 0, tv_nsec: 0 };
20382 let ts_ptr = if timeout < 0 {
20383 core::ptr::null()
20384 } else {
20385 ts.tv_sec = (timeout / 1000) as i64;
20386 ts.tv_nsec = ((timeout % 1000) as i64) * 1_000_000;
20387 &ts as *const PollTimespec as *const core::ffi::c_void
20388 };
20389 syscall_ret(<Arch as Syscalls>::syscall5(
20390 SYS_PPOLL,
20391 fds as i64,
20392 nfds as i64,
20393 ts_ptr as i64,
20394 0,
20395 8,
20396 )) as i32
20397 }
20398}
20399
20400#[no_mangle]
20401pub unsafe extern "C" fn ppoll(fds: *mut core::ffi::c_void, nfds: u32, timeout: *const core::ffi::c_void, sigmask: *const u64) -> i32 {
20402 syscall_ret(<Arch as Syscalls>::syscall5(SYS_PPOLL, fds as i64, nfds as i64, timeout as i64, sigmask as i64, 8)) as i32
20403}
20404
20405#[no_mangle]
20406pub 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 {
20407 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
20408}
20409
20410#[no_mangle]
20419pub unsafe extern "C" fn quick_exit(status: i32) -> ! {
20420 crate::_exit(status)
20421}
20422
20423#[no_mangle]
20428pub unsafe extern "C" fn lstat(path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
20429 let r = <Arch as Syscalls>::syscall4(SYS_NEWFSTATAT, AT_FDCWD as i64, path as i64, buf as i64, 0x100);
20430 if r < 0 {
20431 ERRNO!() = (-r) as c_int;
20432 -1
20433 } else {
20434 0
20435 }
20436}
20437
20438#[no_mangle]
20439pub unsafe extern "C" fn __xstat(_ver: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
20440 crate::stat(path, buf as *mut Stat)
20441}
20442
20443#[no_mangle]
20444pub unsafe extern "C" fn __lxstat(_ver: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void) -> i32 {
20445 crate::lstat(path, buf)
20446}
20447
20448#[no_mangle]
20449pub unsafe extern "C" fn __fxstat(_ver: i32, fd: i32, buf: *mut core::ffi::c_void) -> i32 {
20450 crate::fstat(fd, buf as *mut Stat)
20451}
20452
20453#[no_mangle]
20454pub unsafe extern "C" fn __fxstatat(_ver: i32, _dirfd: i32, path: *const core::ffi::c_char, buf: *mut core::ffi::c_void, _flags: i32) -> i32 {
20455 crate::stat(path, buf as *mut Stat)
20456}
20457
20458#[no_mangle]
20463pub unsafe extern "C" fn mempcpy(dest: *mut u8, src: *const u8, n: usize) -> *mut u8 {
20464 core::ptr::copy_nonoverlapping(src, dest, n);
20465 dest.add(n)
20466}
20467
20468#[no_mangle]
20473pub unsafe extern "C" fn mkostemp(template: *mut core::ffi::c_char, _flags: i32) -> i32 {
20474 mkstemp(template)
20475}
20476
20477#[no_mangle]
20478pub unsafe extern "C" fn mkstemps(template: *mut core::ffi::c_char, _suffixlen: i32) -> i32 {
20479 mkstemp(template)
20480}
20481
20482#[no_mangle]
20487pub unsafe extern "C" fn ptrace(request: i32, mut args: ...) -> i64 {
20488 let pid = args.next_arg::<c_long>();
20489 let addr = args.next_arg::<c_long>();
20490 let data = args.next_arg::<c_long>();
20491 if (1..=3).contains(&request) {
20494 let mut result: c_long = 0;
20495 let r = <Arch as Syscalls>::syscall4(
20496 sysno(101, 117),
20497 request as i64,
20498 pid,
20499 addr,
20500 &mut result as *mut c_long as i64,
20501 );
20502 if r < 0 {
20503 ERRNO!() = (-r) as c_int;
20504 return -1;
20505 }
20506 return result;
20507 }
20508 syscall_ret(<Arch as Syscalls>::syscall4(sysno(101, 117), request as i64, pid, addr, data))
20509}
20510
20511#[no_mangle]
20512pub unsafe extern "C" fn personality(persona: u64) -> i64 {
20513 <Arch as Syscalls>::syscall1(sysno(135, 92), persona as i64)
20514}
20515
20516#[no_mangle]
20517pub unsafe extern "C" fn reboot(cmd: c_int) -> i32 {
20518 syscall_ret(<Arch as Syscalls>::syscall3(
20520 SYS_REBOOT,
20521 0xfee1dead,
20522 672274793,
20523 cmd as i64,
20524 )) as i32
20525}
20526
20527#[no_mangle]
20528pub unsafe extern "C" fn pivot_root(new_root: *const core::ffi::c_char, put_old: *const core::ffi::c_char) -> i32 {
20529 syscall_ret(<Arch as Syscalls>::syscall2(SYS_PIVOT_ROOT, new_root as i64, put_old as i64)) as i32
20530}
20531
20532#[no_mangle]
20533pub 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 {
20534 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
20535}
20536
20537#[no_mangle]
20538pub unsafe extern "C" fn umount(target: *const core::ffi::c_char) -> i32 {
20539 syscall_ret(<Arch as Syscalls>::syscall2(SYS_UMOUNT2, target as i64, 0)) as i32
20540}
20541
20542#[no_mangle]
20543pub unsafe extern "C" fn umount2(target: *const core::ffi::c_char, flags: i32) -> i32 {
20544 syscall_ret(<Arch as Syscalls>::syscall2(SYS_UMOUNT2, target as i64, flags as i64)) as i32
20545}
20546
20547#[no_mangle]
20557pub unsafe extern "C" fn psiginfo(_pinfo: *const core::ffi::c_void, s: *const core::ffi::c_char) {
20558 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
20559 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20560}
20561
20562#[no_mangle]
20563pub unsafe extern "C" fn psignal(sig: i32, s: *const core::ffi::c_char) {
20564 if !s.is_null() { crate::write(2, s as *const core::ffi::c_void, crate::strlen(s)); }
20565 crate::write(2, b": ".as_ptr() as *const core::ffi::c_void, 2);
20566 crate::write(2, strsignal(sig) as *const core::ffi::c_void, crate::strlen(strsignal(sig)));
20567 crate::write(2, b"\n".as_ptr() as *const core::ffi::c_void, 1);
20568}
20569
20570#[no_mangle]
20571pub unsafe extern "C" fn strsignal(sig: c_int) -> *const c_char {
20572 static NAMES: [&[u8]; 32] = [
20573 b"Unknown signal\0",
20574 b"Hangup\0",
20575 b"Interrupt\0",
20576 b"Quit\0",
20577 b"Illegal instruction\0",
20578 b"Trace/breakpoint trap\0",
20579 b"Aborted\0",
20580 b"Bus error\0",
20581 b"Floating point exception\0",
20582 b"Killed\0",
20583 b"User defined signal 1\0",
20584 b"Segmentation fault\0",
20585 b"User defined signal 2\0",
20586 b"Broken pipe\0",
20587 b"Alarm clock\0",
20588 b"Terminated\0",
20589 b"Stack fault\0",
20590 b"Child process status\0",
20591 b"Continued\0",
20592 b"Stopped (signal)\0",
20593 b"Stopped\0",
20594 b"Stopped (tty input)\0",
20595 b"Stopped (tty output)\0",
20596 b"Urgent I/O condition\0",
20597 b"CPU time limit exceeded\0",
20598 b"File size limit exceeded\0",
20599 b"Virtual timer expired\0",
20600 b"Profiling timer expired\0",
20601 b"Window changed\0",
20602 b"I/O possible\0",
20603 b"Power failure\0",
20604 b"Bad system call\0",
20605 ];
20606 static mut RT_BUF: [c_char; 32] = [0; 32];
20607 if sig > 0 && sig < 32 {
20608 return NAMES[sig as usize].as_ptr() as *const c_char;
20609 }
20610 if sig >= 32 && sig < 65 {
20611 let mut o = 0usize;
20612 for &c in b"Real-time signal \0" {
20613 if c == 0 { break; }
20614 RT_BUF[o] = c as c_char;
20615 o += 1;
20616 }
20617 let mut v = (sig - 32) as u32;
20618 let mut digits = [0u8; 10];
20619 let mut d = 0usize;
20620 if v == 0 { digits[0] = b'0'; d = 1; }
20621 while v > 0 { digits[d] = b'0' + (v % 10) as u8; v /= 10; d += 1; }
20622 while d > 0 { d -= 1; RT_BUF[o] = digits[d] as c_char; o += 1; }
20623 RT_BUF[o] = 0;
20624 return RT_BUF.as_ptr();
20625 }
20626 b"Unknown signal\0".as_ptr() as *const c_char
20627}
20628
20629#[no_mangle]
20630pub unsafe extern "C" fn __strerror_l(errnum: i32, _loc: *mut core::ffi::c_void) -> *const core::ffi::c_char {
20631 crate::strerror(errnum)
20632}
20633
20634#[no_mangle]
20639pub unsafe extern "C" fn preadv(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64) -> isize {
20640 syscall_ret(<Arch as Syscalls>::syscall5(
20643 sysno(295, 69),
20644 fd as i64,
20645 iov as i64,
20646 iovcnt as i64,
20647 offset,
20648 offset >> 32,
20649 )) as isize
20650}
20651
20652#[no_mangle]
20653pub unsafe extern "C" fn pwritev(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64) -> isize {
20654 syscall_ret(<Arch as Syscalls>::syscall5(
20655 sysno(296, 70),
20656 fd as i64,
20657 iov as i64,
20658 iovcnt as i64,
20659 offset,
20660 offset >> 32,
20661 )) as isize
20662}
20663
20664#[no_mangle]
20665pub unsafe extern "C" fn preadv2(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64, flags: u32) -> isize {
20666 syscall_ret(<Arch as Syscalls>::syscall6(
20669 sysno(327, 286),
20670 fd as i64,
20671 iov as i64,
20672 iovcnt as i64,
20673 offset,
20674 offset >> 32,
20675 flags as i64,
20676 )) as isize
20677}
20678
20679#[no_mangle]
20680pub unsafe extern "C" fn pwritev2(fd: i32, iov: *const core::ffi::c_void, iovcnt: i32, offset: i64, flags: u32) -> isize {
20681 syscall_ret(<Arch as Syscalls>::syscall6(
20682 sysno(328, 287),
20683 fd as i64,
20684 iov as i64,
20685 iovcnt as i64,
20686 offset,
20687 offset >> 32,
20688 flags as i64,
20689 )) as isize
20690}
20691
20692#[no_mangle]
20697pub unsafe extern "C" fn nice(inc: i32) -> i32 {
20698 let mut prio = inc;
20699 if inc > -40 && inc < 40 {
20700 prio += getpriority(0, 0);
20701 }
20702 if prio > 19 { prio = 19; }
20703 if prio < -20 { prio = -20; }
20704 if setpriority(0, 0, prio) != 0 {
20705 if ERRNO!() == 13 { ERRNO!() = 1; } return -1;
20707 }
20708 prio
20709}
20710
20711#[no_mangle]
20716pub unsafe extern "C" fn l64a(value: i64) -> *mut core::ffi::c_char {
20717 static mut BUF: [core::ffi::c_char; 7] = [0; 7];
20718 let mut v = value as u64;
20719 let mut i = 0;
20720 while v > 0 && i < 6 {
20721 let c = (v & 0x3f) as u8;
20722 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;
20723 v >>= 6;
20724 i += 1;
20725 }
20726 BUF[i] = 0;
20727 BUF.as_mut_ptr()
20728}
20729
20730#[no_mangle]
20731pub unsafe extern "C" fn lchmod(path: *const core::ffi::c_char, mode: u32) -> i32 {
20732 syscall_ret(<Arch as Syscalls>::syscall4(SYS_FCHMODAT, AT_FDCWD as i64, path as i64, mode as i64, 0x100)) as i32
20733}
20734
20735#[no_mangle]
20736pub unsafe extern "C" fn lutimes(filename: *const core::ffi::c_char, times: *const core::ffi::c_void) -> i32 {
20737 utimensat(AT_FDCWD, filename, times as *const timespec, 0x100)
20738}
20739
20740#[no_mangle]
20741pub unsafe extern "C" fn mknod(pathname: *const core::ffi::c_char, mode: u32, dev: u64) -> i32 {
20742 #[cfg(target_arch = "x86_64")]
20743 { syscall_ret(<Arch as Syscalls>::syscall3(SYS_MKNOD, pathname as i64, mode as i64, dev as i64)) as i32 }
20744 #[cfg(any(target_arch = "aarch64", target_arch = "riscv64"))]
20745 {
20746 syscall_ret(<Arch as Syscalls>::syscall4(SYS_MKNODAT, AT_FDCWD as i64, pathname as i64, mode as i64, dev as i64)) as i32
20747 }
20748}
20749
20750#[no_mangle]
20751pub unsafe extern "C" fn memfd_create(name: *const core::ffi::c_char, flags: u32) -> i32 {
20752 syscall_ret(<Arch as Syscalls>::syscall2(sysno(319, 279), name as i64, flags as i64)) as i32
20753}
20754
20755#[no_mangle]
20756pub unsafe extern "C" fn mlock2(addr: *const core::ffi::c_void, len: usize, flags: u32) -> i32 {
20757 syscall_ret(<Arch as Syscalls>::syscall3(sysno(325, 284), addr as i64, len as i64, flags as i64)) as i32
20758}
20759
20760
20761
20762#[no_mangle]
20763pub unsafe extern "C" fn remap_file_pages(addr: *mut core::ffi::c_void, size: usize, prot: i32, pgoff: usize, flags: u32) -> i32 {
20764 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
20765}
20766
20767#[no_mangle]
20772pub unsafe extern "C" fn nan(_tagp: *const core::ffi::c_char) -> f64 {
20773 f64::NAN
20774}
20775
20776#[no_mangle]
20777pub unsafe extern "C" fn nanf(_tagp: *const core::ffi::c_char) -> f32 {
20778 f32::NAN
20779}
20780
20781#[no_mangle]
20786pub unsafe extern "C" fn __lgammal_r(x: f64, signgamp: *mut i32) -> f64 {
20787 *signgamp = 1;
20788 lgamma(x)
20789}
20790
20791#[no_mangle]
20792pub unsafe extern "C" fn __libc_current_sigrtmax() -> i32 {
20793 64
20794}
20795
20796#[no_mangle]
20797pub unsafe extern "C" fn _longjmp(env: *mut core::ffi::c_void, val: i32) {
20798 crate::longjmp(env as *mut u64, val)
20799}
20800
20801#[no_mangle]
20802pub unsafe extern "C" fn __newlocale(_mask: i32, _name: *const core::ffi::c_char, base: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
20803 base
20804}
20805
20806#[no_mangle]
20807pub unsafe extern "C" fn __nl_langinfo(_item: i32) -> *mut core::ffi::c_char {
20808 b"\0".as_ptr() as *mut core::ffi::c_char
20809}
20810
20811#[no_mangle]
20812pub unsafe extern "C" fn __nl_langinfo_l(_item: i32, _loc: *mut core::ffi::c_void) -> *mut core::ffi::c_char {
20813 b"\0".as_ptr() as *mut core::ffi::c_char
20814}
20815
20816#[no_mangle]
20817pub unsafe extern "C" fn ns_get16(cp: *const u8) -> u16 {
20818 ((*cp.add(0) as u16) << 8) | *cp.add(1) as u16
20819}
20820
20821#[no_mangle]
20822pub unsafe extern "C" fn ns_get32(cp: *const u8) -> u32 {
20823 ((*cp.add(0) as u32) << 24) | ((*cp.add(1) as u32) << 16) | ((*cp.add(2) as u32) << 8) | *cp.add(3) as u32
20824}
20825
20826#[no_mangle]
20827pub unsafe extern "C" fn ns_put16(s: u16, dst: *mut u8) {
20828 *dst.add(0) = (s >> 8) as u8;
20829 *dst.add(1) = (s & 0xff) as u8;
20830}
20831
20832#[no_mangle]
20833pub unsafe extern "C" fn ns_put32(l: u32, dst: *mut u8) {
20834 *dst.add(0) = (l >> 24) as u8;
20835 *dst.add(1) = ((l >> 16) & 0xff) as u8;
20836 *dst.add(2) = ((l >> 8) & 0xff) as u8;
20837 *dst.add(3) = (l & 0xff) as u8;
20838}
20839
20840#[no_mangle]
20841pub unsafe extern "C" fn posix_close(fd: i32) -> i32 {
20842 crate::close(fd)
20843}
20844
20845#[no_mangle]
20846pub unsafe extern "C" fn posix_openpt(flags: i32) -> i32 {
20847 crate::open(b"/dev/ptmx\0".as_ptr() as *const core::ffi::c_char, flags, 0)
20848}
20849
20850#[no_mangle]
20851pub unsafe extern "C" fn putw(w: i32, f: *mut core::ffi::c_void) {
20852 putc((w & 0xff) as i32, f as *mut FILE);
20853 putc(((w >> 8) & 0xff) as i32, f as *mut FILE);
20854 putc(((w >> 16) & 0xff) as i32, f as *mut FILE);
20855 putc(((w >> 24) & 0xff) as i32, f as *mut FILE);
20856}
20857
20858
20859
20860#[no_mangle]
20861pub unsafe extern "C" fn rand_r(seedp: *mut u32) -> i32 {
20862 let seed = (*seedp).wrapping_mul(1103515245).wrapping_add(12345);
20863 *seedp = seed;
20864 ((seed >> 16) & 0x7fff) as i32
20865}
20866
20867#[no_mangle]
20868pub unsafe extern "C" fn reallocarray(ptr: *mut core::ffi::c_void, nmemb: usize, size: usize) -> *mut core::ffi::c_void {
20869 let total = match nmemb.checked_mul(size) {
20870 Some(v) => v,
20871 None => { ERRNO!() = ENOMEM; return core::ptr::null_mut(); }
20872 };
20873 crate::realloc(ptr, total)
20874}
20875
20876#[no_mangle]
20877pub unsafe extern "C" fn __res_state() -> *mut core::ffi::c_void {
20878 static mut STATE: [u8; 512] = [0; 512];
20879 STATE.as_mut_ptr() as *mut core::ffi::c_void
20880}
20881
20882#[no_mangle]
20883pub unsafe extern "C" fn sbrk(increment: isize) -> *mut u8 {
20884 if increment != 0 {
20887 ERRNO!() = ENOMEM;
20888 return -1isize as usize as *mut u8;
20889 }
20890 <Arch as Syscalls>::syscall1(sysno(12, 214), 0) as *mut u8
20891}
20892
20893#[no_mangle]
20894pub unsafe extern "C" fn scalb(x: f64, exp: f64) -> f64 {
20895 if x.is_nan() || exp.is_nan() { return x * exp; }
20896 if !exp.is_finite() {
20897 let r = if exp > 0.0 { x * exp } else { x / (-exp) };
20898 if r.is_nan() && !x.is_nan() {
20899 feraiseexcept(FE_INVALID);
20900 }
20901 return r;
20902 }
20903 if libm::rint(exp) != exp {
20904 return __math_invalid(exp);
20905 }
20906 if exp > 65000.0 { return libm::scalbn(x, 65000); }
20907 if -exp > 65000.0 { return libm::scalbn(x, -65000); }
20908 libm::scalbn(x, exp as i32)
20909}
20910
20911#[no_mangle]
20912pub unsafe extern "C" fn scalbf(x: f32, exp: f32) -> f32 {
20913 if x.is_nan() || exp.is_nan() { return x * exp; }
20914 if !exp.is_finite() {
20915 let r = if exp > 0.0 { x * exp } else { x / (-exp) };
20916 if r.is_nan() && !x.is_nan() {
20917 feraiseexcept(FE_INVALID);
20918 }
20919 return r;
20920 }
20921 if libm::rintf(exp) != exp {
20922 return __math_invalidf(exp);
20923 }
20924 if exp > 65000.0 { return libm::scalbnf(x, 65000); }
20925 if -exp > 65000.0 { return libm::scalbnf(x, -65000); }
20926 libm::scalbnf(x, exp as i32)
20927}
20928
20929#[no_mangle]
20930pub unsafe extern "C" fn __sched_cpucount(setsize: usize, setp: *const u8) -> i32 {
20931 let mut count = 0;
20932 let mut i = 0;
20933 while i < setsize * 8 {
20934 if (*setp.add(i / 8) >> (i % 8)) & 1 != 0 { count += 1; }
20935 i += 1;
20936 }
20937 count
20938}
20939
20940
20941
20942#[no_mangle]
20943pub unsafe extern "C" fn select(nfds: i32, readfds: *mut u8, writefds: *mut u8, exceptfds: *mut u8, timeout: *mut core::ffi::c_void) -> i32 {
20944 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
20945}
20946
20947
20948
20949#[no_mangle]
20950pub unsafe extern "C" fn sendfile(out_fd: i32, in_fd: i32, offset: *mut i64, count: usize) -> isize {
20951 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
20952}
20953
20954
20955
20956
20957
20958#[no_mangle]
20959pub unsafe extern "C" fn __setjmp(env: *mut core::ffi::c_void) -> i32 {
20960 crate::setjmp(env as *mut u64)
20961}
20962
20963#[no_mangle]
20964pub unsafe extern "C" fn _setjmp(env: *mut core::ffi::c_void) -> i32 {
20965 crate::setjmp(env as *mut u64)
20966}
20967
20968#[no_mangle]
20969pub unsafe extern "C" fn setlinebuf(stream: *mut core::ffi::c_void) {
20970 setvbuf(stream as *mut FILE, core::ptr::null_mut(), 1, 0);
20971}
20972
20973
20974
20975
20976
20977
20978
20979
20980
20981
20982
20983
20984
20985
20986
20987#[no_mangle]
20988pub unsafe extern "C" fn significand(x: f64) -> f64 {
20989 let bits = x.to_bits();
20990 let exp = ((bits >> 52) & 0x7ff) as i32;
20991 if exp == 0 || exp == 0x7ff { return x; }
20992 f64::from_bits((bits & 0x000fffffffffffff) | (1023u64 << 52))
20993}
20994
20995#[no_mangle]
20996pub unsafe extern "C" fn significandf(x: f32) -> f32 {
20997 let bits = x.to_bits();
20998 let exp = ((bits >> 23) & 0xff) as i32;
20999 if exp == 0 || exp == 0xff { return x; }
21000 f32::from_bits((bits & 0x007fffff) | (127u32 << 23))
21001}
21002
21003
21004
21005
21006
21007#[no_mangle]
21008pub unsafe extern "C" fn sigset(sig: i32, handler: usize) -> usize {
21009 signal(sig, handler)
21011}
21012
21013#[no_mangle]
21014pub unsafe extern "C" fn sincos(x: f64, sin: *mut f64, cos: *mut f64) {
21015 *sin = libm::sin(x);
21016 *cos = libm::cos(x);
21017}
21018
21019#[no_mangle]
21020pub unsafe extern "C" fn sincosf(x: f32, sin: *mut f32, cos: *mut f32) {
21021 *sin = libm::sinf(x);
21022 *cos = libm::cosf(x);
21023}
21024
21025
21026
21027
21028
21029
21030
21031
21032
21033unsafe fn nd_ascii_lower(c: c_char) -> c_int {
21034 let b = c as u8;
21035 if b >= b'A' && b <= b'Z' { (b + 32) as c_int } else { b as c_int }
21036}
21037
21038unsafe fn nd_strncasecmp(s1: *const c_char, s2: *const c_char, n: usize) -> c_int {
21039 let mut i = 0usize;
21040 while i < n {
21041 let c1 = nd_ascii_lower(*s1.add(i));
21042 let c2 = nd_ascii_lower(*s2.add(i));
21043 if c1 != c2 || c1 == 0 { return c1 - c2; }
21044 i += 1;
21045 }
21046 0
21047}
21048
21049#[no_mangle]
21050pub unsafe extern "C" fn strcasecmp(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char) -> i32 {
21051 nd_strncasecmp(s1, s2, usize::MAX)
21052}
21053
21054#[no_mangle]
21055pub 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 {
21056 nd_strncasecmp(s1, s2, usize::MAX)
21057}
21058
21059#[no_mangle]
21060pub unsafe extern "C" fn strcasestr(haystack: *const core::ffi::c_char, needle: *const core::ffi::c_char) -> *mut core::ffi::c_char {
21061 let nlen = crate::strlen(needle);
21062 if nlen == 0 { return haystack as *mut core::ffi::c_char; }
21063 let mut i = 0;
21064 loop {
21065 let h = haystack.add(i);
21066 if *h == 0 { return core::ptr::null_mut(); }
21067 if crate::strncasecmp(h, needle, nlen) == 0 { return h as *mut core::ffi::c_char; }
21068 i += 1;
21069 }
21070}
21071
21072#[no_mangle]
21073pub 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 {
21074 crate::strcmp(s1 as *const u8, s2 as *const u8)
21075}
21076
21077#[no_mangle]
21078pub unsafe extern "C" fn strncasecmp(s1: *const core::ffi::c_char, s2: *const core::ffi::c_char, n: usize) -> i32 {
21079 nd_strncasecmp(s1, s2, n)
21080}
21081
21082#[no_mangle]
21083pub 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 {
21084 nd_strncasecmp(s1, s2, n)
21085}
21086
21087#[no_mangle]
21088pub unsafe extern "C" fn strsep(stringp: *mut *mut core::ffi::c_char, delim: *const core::ffi::c_char) -> *mut core::ffi::c_char {
21089 let s = *stringp;
21090 if s.is_null() { return core::ptr::null_mut(); }
21091 let mut p = s;
21092 while *p != 0 {
21093 let mut d = delim;
21094 while *d != 0 {
21095 if *p == *d { *p = 0; *stringp = p.add(1); return s; }
21096 d = d.add(1);
21097 }
21098 p = p.add(1);
21099 }
21100 *stringp = core::ptr::null_mut();
21101 s
21102}
21103
21104#[no_mangle]
21105pub unsafe extern "C" fn strtoimax(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, base: i32) -> i64 {
21106 crate::strtol(nptr, endptr, base)
21107}
21108
21109#[no_mangle]
21110pub 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 {
21111 let mut s = if s.is_null() { *saveptr } else { s };
21112 if s.is_null() { return core::ptr::null_mut(); }
21113 while *s != 0 {
21115 let mut d = delim;
21116 let mut found = false;
21117 while *d != 0 {
21118 if *s == *d { found = true; break; }
21119 d = d.add(1);
21120 }
21121 if !found { break; }
21122 s = s.add(1);
21123 }
21124 if *s == 0 { *saveptr = s; return core::ptr::null_mut(); }
21125 let start = s;
21126 while *s != 0 {
21128 let mut d = delim;
21129 while *d != 0 {
21130 if *s == *d { *s = 0; *saveptr = s.add(1); return start; }
21131 d = d.add(1);
21132 }
21133 s = s.add(1);
21134 }
21135 *saveptr = s;
21136 start
21137}
21138
21139#[no_mangle]
21140pub unsafe extern "C" fn strtoumax(nptr: *const core::ffi::c_char, endptr: *mut *mut core::ffi::c_char, base: i32) -> u64 {
21141 crate::strtoul(nptr, endptr, base) as u64
21142}
21143
21144#[no_mangle]
21145pub 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 {
21146 crate::strlcpy(dest as *mut u8, src as *const u8, n)
21147}
21148
21149#[no_mangle]
21150pub unsafe extern "C" fn swab(src: *const u8, dest: *mut u8, nbytes: isize) {
21151 let mut i = 0;
21152 while i + 1 < nbytes {
21153 let a = *src.add(i as usize);
21154 let b = *src.add(i as usize + 1);
21155 *dest.add(i as usize) = b;
21156 *dest.add(i as usize + 1) = a;
21157 i += 2;
21158 }
21159}
21160
21161
21162
21163
21164
21165
21166
21167
21168
21169
21170
21171#[no_mangle]
21172pub unsafe extern "C" fn __tolower_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
21173 if c >= 'A' as i32 && c <= 'Z' as i32 { c + 32 } else { c }
21174}
21175
21176#[no_mangle]
21177pub unsafe extern "C" fn __toupper_l(c: i32, _loc: *mut core::ffi::c_void) -> i32 {
21178 if c >= 'a' as i32 && c <= 'z' as i32 { c - 32 } else { c }
21179}
21180
21181#[no_mangle]
21182pub unsafe extern "C" fn ulimit(cmd: c_int, mut args: ...) -> c_long {
21183 let mut rl: Rlimit = core::mem::zeroed();
21184 if getrlimit(RLIMIT_FSIZE, &mut rl) != 0 { return -1; }
21185 if cmd == 2 {
21186 let val = args.next_arg::<c_long>();
21187 rl.rlim_cur = 512u64.wrapping_mul(val as u64);
21188 if setrlimit(RLIMIT_FSIZE, &rl) != 0 { return -1; }
21189 }
21190 (rl.rlim_cur / 512) as c_long
21191}
21192
21193#[repr(C)]
21194struct UtsName {
21195 sysname: [u8; 65],
21196 nodename: [u8; 65],
21197 release: [u8; 65],
21198 version: [u8; 65],
21199 machine: [u8; 65],
21200 domainname: [u8; 65],
21201}
21202
21203#[no_mangle]
21204pub unsafe extern "C" fn uname(buf: *mut c_void) -> c_int {
21205 let r = <Arch as Syscalls>::syscall1(SYS_UNAME, buf as i64);
21208 if r < 0 { ERRNO!() = (-r) as c_int; return -1; }
21209 0
21210}
21211
21212#[no_mangle]
21213pub unsafe extern "C" fn unshare(flags: i32) -> i32 {
21214 let r = <Arch as Syscalls>::syscall1(SYS_UNSHARE, flags as i64);
21215 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21216}
21217
21218#[no_mangle]
21219pub unsafe extern "C" fn updwtmpx(wtmpx_file: *const core::ffi::c_char, utx: *const core::ffi::c_void) {
21220 updwtmp(wtmpx_file, utx)
21221}
21222
21223#[no_mangle]
21224pub unsafe extern "C" fn __uselocale(loc: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
21225 loc
21226}
21227
21228#[repr(C)]
21229pub struct Utimbuf { actime: i64, modtime: i64 }
21230
21231#[no_mangle]
21232pub unsafe extern "C" fn utime(filename: *const c_char, times: *const Utimbuf) -> c_int {
21233 if times.is_null() {
21234 return utimensat(AT_FDCWD, filename, core::ptr::null(), 0);
21235 }
21236 let ts = [
21237 timespec { tv_sec: (*times).actime, tv_nsec: 0 },
21238 timespec { tv_sec: (*times).modtime, tv_nsec: 0 },
21239 ];
21240 utimensat(AT_FDCWD, filename, ts.as_ptr(), 0)
21241}
21242
21243#[no_mangle]
21244pub unsafe extern "C" fn vhangup() -> c_int {
21245 let r = <Arch as Syscalls>::syscall0(SYS_VHANGUP);
21246 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21247}
21248
21249#[no_mangle]
21250pub unsafe extern "C" fn vmsplice(fd: i32, iov: *const c_void, nr_segs: usize, flags: u32) -> isize {
21251 let r = <Arch as Syscalls>::syscall4(SYS_VMSPLICE, fd as i64, iov as i64, nr_segs as i64, flags as i64);
21252 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
21253}
21254
21255
21256
21257#[no_mangle]
21258pub unsafe extern "C" fn wait4(pid: i32, wstatus: *mut i32, options: i32, rusage: *mut core::ffi::c_void) -> i32 {
21259 syscall_ret(<Arch as Syscalls>::syscall4(SYS_WAIT4, pid as i64, wstatus as i64, options as i64, rusage as i64)) as i32
21260}
21261
21262#[no_mangle]
21263pub unsafe extern "C" fn waitid(idtype: i32, id: u32, infop: *mut core::ffi::c_void, options: i32) -> i32 {
21264 syscall_ret(<Arch as Syscalls>::syscall5(
21267 sysno(247, 95),
21268 idtype as i64,
21269 id as i64,
21270 infop as i64,
21271 options as i64,
21272 0,
21273 )) as i32
21274}
21275
21276#[no_mangle]
21277pub unsafe extern "C" fn __wcscoll_l(s1: *const u32, s2: *const u32, _loc: *mut core::ffi::c_void) -> i32 {
21278 crate::wcscmp(s1 as *const i32, s2 as *const i32)
21279}
21280
21281#[no_mangle]
21282pub unsafe extern "C" fn __wcsxfrm_l(dest: *mut u32, src: *const u32, n: usize, _loc: *mut core::ffi::c_void) -> usize {
21283 crate::wcscpy(dest as *mut i32, src as *const i32);
21284 n
21285}
21286
21287#[no_mangle]
21288pub unsafe extern "C" fn wcwidth(c: u32) -> i32 {
21289 if c == 0 { return 0; }
21290 if c < 32 || (c >= 0x7f && c < 0xa0) { return -1; }
21291 1
21292}
21293
21294
21295
21296
21297
21298#[no_mangle]
21305pub 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 {
21306 crate::strtod(nptr, endptr)
21307}
21308
21309#[no_mangle]
21310pub 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 {
21311 crate::strtof(nptr, endptr)
21312}
21313
21314#[no_mangle]
21315pub 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 {
21316 crate::strtod(nptr, endptr)
21317}
21318
21319#[repr(C)]
21324struct linux_dirent64 {
21325 d_ino: u64,
21326 d_off: i64,
21327 d_reclen: u16,
21328 d_type: u8,
21329 d_name: [u8; 0], }
21331
21332const DIR_BUF_SIZE: usize = 4096;
21336
21337#[repr(C)]
21338struct DirStream {
21339 fd: i32,
21340 pos: usize,
21341 len: usize,
21342 last_off: i64,
21343 buf: [u8; DIR_BUF_SIZE],
21344}
21345
21346unsafe fn dir_stream_new(fd: i32) -> *mut core::ffi::c_void {
21347 let ds = malloc(core::mem::size_of::<DirStream>()) as *mut DirStream;
21348 if ds.is_null() {
21349 crate::close(fd);
21350 ERRNO!() = ENOMEM;
21351 return core::ptr::null_mut();
21352 }
21353 core::ptr::write_bytes(ds, 0, 1);
21354 (*ds).fd = fd;
21355 ds as *mut core::ffi::c_void
21356}
21357
21358#[no_mangle]
21359pub unsafe extern "C" fn opendir(dirname: *const core::ffi::c_char) -> *mut core::ffi::c_void {
21360 let fd = openat(AT_FDCWD, dirname, O_DIRECTORY, 0); if fd < 0 { return core::ptr::null_mut(); }
21362 dir_stream_new(fd)
21363}
21364
21365#[no_mangle]
21366pub unsafe extern "C" fn closedir(dirp: *mut core::ffi::c_void) -> i32 {
21367 if dirp.is_null() { ERRNO!() = 22; return -1; }
21368 let ds = dirp as *mut DirStream;
21369 let r = crate::close((*ds).fd);
21370 free(dirp);
21371 r
21372}
21373
21374#[no_mangle]
21375pub unsafe extern "C" fn readdir(dirp: *mut core::ffi::c_void) -> *mut core::ffi::c_void {
21376 if dirp.is_null() { ERRNO!() = 22; return core::ptr::null_mut(); }
21377 let ds = &mut *(dirp as *mut DirStream);
21378
21379 loop {
21380 if ds.pos >= ds.len {
21381 let nread = syscall_ret(<Arch as Syscalls>::syscall3(
21382 SYS_GETDENTS64,
21383 ds.fd as i64,
21384 ds.buf.as_mut_ptr() as i64,
21385 DIR_BUF_SIZE as i64,
21386 )) as isize;
21387 if nread <= 0 { return core::ptr::null_mut(); }
21388 ds.len = nread as usize;
21389 ds.pos = 0;
21390 }
21391
21392 let ent = ds.buf.as_ptr().add(ds.pos) as *const linux_dirent64;
21393 let ent_ref = &*ent;
21394 if ent_ref.d_reclen as usize == 0 {
21395 ds.len = 0;
21396 return core::ptr::null_mut();
21397 }
21398 ds.pos += ent_ref.d_reclen as usize;
21399 ds.last_off = ent_ref.d_off;
21400
21401 return ent as *mut core::ffi::c_void;
21403 }
21404}
21405
21406#[no_mangle]
21407pub 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 {
21408 let ent = readdir(dirp);
21409 if ent.is_null() {
21410 *result = core::ptr::null_mut();
21411 } else {
21412 *result = ent;
21413 }
21414 0
21415}
21416
21417#[no_mangle]
21418pub unsafe extern "C" fn seekdir(dirp: *mut core::ffi::c_void, loc: i64) {
21419 if dirp.is_null() { return; }
21420 let ds = &mut *(dirp as *mut DirStream);
21421 <Arch as Syscalls>::syscall3(SYS_LSEEK, ds.fd as i64, loc, 0);
21422 ds.pos = 0;
21423 ds.len = 0;
21424}
21425
21426#[no_mangle]
21427pub unsafe extern "C" fn telldir(dirp: *mut core::ffi::c_void) -> i64 {
21428 if dirp.is_null() { return -1; }
21429 (*(dirp as *mut DirStream)).last_off
21430}
21431
21432#[no_mangle]
21433pub unsafe extern "C" fn rewinddir(dirp: *mut core::ffi::c_void) {
21434 if dirp.is_null() { return; }
21435 let ds = &mut *(dirp as *mut DirStream);
21436 <Arch as Syscalls>::syscall3(SYS_LSEEK, ds.fd as i64, 0, 0);
21437 ds.pos = 0;
21438 ds.len = 0;
21439 ds.last_off = 0;
21440}
21441
21442#[no_mangle]
21443pub unsafe extern "C" fn dirfd(dirp: *mut core::ffi::c_void) -> i32 {
21444 if dirp.is_null() { ERRNO!() = 22; return -1; }
21445 (*(dirp as *mut DirStream)).fd
21446}
21447
21448#[no_mangle]
21453pub unsafe extern "C" fn mprotect(addr: *mut u8, len: usize, prot: i32) -> i32 {
21454 syscall_ret(<Arch as Syscalls>::syscall3(SYS_MPROTECT, addr as i64, len as i64, prot as i64)) as i32
21455}
21456
21457#[no_mangle]
21458pub unsafe extern "C" fn msync(addr: *mut u8, len: usize, flags: i32) -> i32 {
21459 syscall_ret(<Arch as Syscalls>::syscall3(sysno(26, 227), addr as i64, len as i64, flags as i64)) as i32
21460}
21461
21462#[no_mangle]
21463pub unsafe extern "C" fn mlock(addr: *const u8, len: usize) -> i32 {
21464 syscall_ret(<Arch as Syscalls>::syscall2(sysno(149, 228), addr as i64, len as i64)) as i32
21465}
21466
21467#[no_mangle]
21468pub unsafe extern "C" fn munlock(addr: *const u8, len: usize) -> i32 {
21469 syscall_ret(<Arch as Syscalls>::syscall2(sysno(150, 229), addr as i64, len as i64)) as i32
21470}
21471
21472#[no_mangle]
21473pub unsafe extern "C" fn mlockall(flags: i32) -> i32 {
21474 syscall_ret(<Arch as Syscalls>::syscall1(sysno(151, 230), flags as i64)) as i32
21475}
21476
21477#[no_mangle]
21478pub unsafe extern "C" fn munlockall() -> i32 {
21479 syscall_ret(<Arch as Syscalls>::syscall0(sysno(152, 231))) as i32
21480}
21481
21482#[no_mangle]
21483pub unsafe extern "C" fn madvise(addr: *mut u8, len: usize, advice: i32) -> i32 {
21484 syscall_ret(<Arch as Syscalls>::syscall3(sysno(28, 233), addr as i64, len as i64, advice as i64)) as i32
21485}
21486
21487#[no_mangle]
21488pub unsafe extern "C" fn mincore(addr: *mut u8, len: usize, vec: *mut u8) -> i32 {
21489 syscall_ret(<Arch as Syscalls>::syscall3(sysno(27, 232), addr as i64, len as i64, vec as i64)) as i32
21490}
21491
21492#[no_mangle]
21499pub unsafe extern "C" fn drem(x: f64, y: f64) -> f64 {
21500 remainder(x, y)
21501}
21502
21503#[no_mangle]
21504pub unsafe extern "C" fn dremf(x: f32, y: f32) -> f32 {
21505 remainderf(x, y)
21506}
21507
21508#[no_mangle]
21509pub unsafe extern "C" fn pow10(x: f64) -> f64 {
21510 libm::pow(10.0, x)
21511}
21512
21513#[no_mangle]
21514pub unsafe extern "C" fn pow10f(x: f32) -> f32 {
21515 libm::powf(10.0, x)
21516}
21517
21518#[no_mangle]
21519pub unsafe extern "C" fn pow10l(x: f64) -> f64 {
21520 libm::pow(10.0, x)
21521}
21522
21523#[no_mangle]
21524pub unsafe extern "C" fn isless(x: f64, y: f64) -> i32 {
21525 if x.is_nan() || y.is_nan() { 0 } else { (x < y) as i32 }
21526}
21527
21528#[no_mangle]
21529pub unsafe extern "C" fn islessf(x: f32, y: f32) -> i32 {
21530 if x.is_nan() || y.is_nan() { 0 } else { (x < y) as i32 }
21531}
21532
21533#[no_mangle]
21534pub unsafe extern "C" fn lgamma_r(x: f64, signgamp: *mut i32) -> f64 {
21535 lgamma_r_impl(x, signgamp)
21536}
21537
21538#[no_mangle]
21539pub unsafe extern "C" fn lgammaf_r(x: f32, signgamp: *mut i32) -> f32 {
21540 if x.is_nan() {
21541 if !signgamp.is_null() { *signgamp = 1; }
21542 return x;
21543 }
21544 if x == 0.0 {
21545 if !signgamp.is_null() { *signgamp = if x.is_sign_negative() { -1 } else { 1 }; }
21546 feraiseexcept(FE_DIVBYZERO);
21547 return f32::INFINITY;
21548 }
21549 let (r, sign) = libm::lgammaf_r(x);
21550 if !signgamp.is_null() { *signgamp = sign; }
21551 r
21552}
21553
21554#[no_mangle]
21555pub unsafe extern "C" fn lgammal_r(x: f64, signgamp: *mut i32) -> f64 {
21556 lgamma_r(x, signgamp)
21557}
21558
21559#[no_mangle]
21564pub unsafe extern "C" fn islessequal(x: f64, y: f64) -> i32 {
21565 if x.is_nan() || y.is_nan() { 0 } else { (x <= y) as i32 }
21566}
21567
21568#[no_mangle]
21569pub unsafe extern "C" fn islessequalf(x: f32, y: f32) -> i32 {
21570 if x.is_nan() || y.is_nan() { 0 } else { (x <= y) as i32 }
21571}
21572
21573#[no_mangle]
21574pub unsafe extern "C" fn islessgreater(x: f64, y: f64) -> i32 {
21575 if x.is_nan() || y.is_nan() { 0 } else { (x < y || x > y) as i32 }
21576}
21577
21578#[no_mangle]
21579pub unsafe extern "C" fn islessgreaterf(x: f32, y: f32) -> i32 {
21580 if x.is_nan() || y.is_nan() { 0 } else { (x < y || x > y) as i32 }
21581}
21582
21583#[no_mangle]
21584pub unsafe extern "C" fn isgreater(x: f64, y: f64) -> i32 {
21585 if x.is_nan() || y.is_nan() { 0 } else { (x > y) as i32 }
21586}
21587
21588#[no_mangle]
21589pub unsafe extern "C" fn isgreaterf(x: f32, y: f32) -> i32 {
21590 if x.is_nan() || y.is_nan() { 0 } else { (x > y) as i32 }
21591}
21592
21593#[no_mangle]
21594pub unsafe extern "C" fn isgreaterequal(x: f64, y: f64) -> i32 {
21595 if x.is_nan() || y.is_nan() { 0 } else { (x >= y) as i32 }
21596}
21597
21598#[no_mangle]
21599pub unsafe extern "C" fn isgreaterequalf(x: f32, y: f32) -> i32 {
21600 if x.is_nan() || y.is_nan() { 0 } else { (x >= y) as i32 }
21601}
21602
21603#[no_mangle]
21608pub unsafe extern "C" fn stpcpy(dest: *mut c_char, src: *const c_char) -> *mut c_char {
21609 let mut d = dest;
21610 let mut s = src;
21611 while *s != 0 {
21612 *d = *s;
21613 d = d.add(1);
21614 s = s.add(1);
21615 }
21616 *d = 0;
21617 d
21618}
21619
21620#[no_mangle]
21621pub unsafe extern "C" fn stpncpy(dest: *mut c_char, src: *const c_char, n: usize) -> *mut c_char {
21622 let mut i = 0;
21623 while i < n && *src.add(i) != 0 {
21624 *dest.add(i) = *src.add(i);
21625 i += 1;
21626 }
21627 let end = dest.add(i);
21628 while i < n {
21629 *dest.add(i) = 0;
21630 i += 1;
21631 }
21632 end
21633}
21634
21635#[no_mangle]
21636pub unsafe extern "C" fn strchrnul(s: *const c_char, c: c_int) -> *mut c_char {
21637 let mut p = s;
21638 while *p != 0 && *p as c_int != c {
21639 p = p.add(1);
21640 }
21641 p as *mut c_char
21642}
21643
21644#[no_mangle]
21645pub unsafe extern "C" fn fstatat(dirfd: c_int, path: *const c_char, buf: *mut Stat, flags: c_int) -> c_int {
21646 let r = sys_newfstatat(dirfd, path, buf as *mut u8, flags);
21647 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21648}
21649
21650#[no_mangle]
21651pub unsafe extern "C" fn execvpe(
21652 file: *const c_char,
21653 argv: *const *const c_char,
21654 envp: *const *const c_char,
21655) -> c_int {
21656 ERRNO!() = ENOENT_VAL;
21657 if file.is_null() || *file == 0 {
21658 return -1;
21659 }
21660 let mut p = file;
21661 while *p != 0 {
21662 if *p == b'/' as c_char {
21663 return execve(file, argv, envp);
21664 }
21665 p = p.add(1);
21666 }
21667 let file_len = crate::strlen(file);
21668 let path = crate::getenv(b"PATH\0".as_ptr() as *const c_char);
21669 let default_path = b"/usr/local/bin:/bin:/usr/bin\0";
21670 let path = if path.is_null() { default_path.as_ptr() as *const c_char } else { path };
21671
21672 let mut seen_eacces = false;
21673 let mut buf = [0 as c_char; 4096];
21674 let mut dir = path;
21675 loop {
21676 let mut end = dir;
21677 while *end != 0 && *end != b':' as c_char { end = end.add(1); }
21678 let dlen = end.offset_from(dir) as usize;
21679 let need_slash = dlen > 0;
21681 let total = dlen + need_slash as usize + file_len;
21682 if total < buf.len() {
21683 let mut i = 0;
21684 while i < dlen { buf[i] = *dir.add(i); i += 1; }
21685 if need_slash { buf[i] = b'/' as c_char; i += 1; }
21686 let mut j = 0;
21687 while j < file_len { buf[i + j] = *file.add(j); j += 1; }
21688 buf[i + j] = 0;
21689 execve(buf.as_ptr(), argv, envp);
21690 match ERRNO!() {
21691 13 => seen_eacces = true, 2 | 20 => {} _ => return -1,
21694 }
21695 }
21696 if *end == 0 { break; }
21697 dir = end.add(1);
21698 }
21699 ERRNO!() = if seen_eacces { 13 } else { 2 };
21700 -1
21701}
21702
21703#[no_mangle]
21706pub unsafe extern "C" fn strcoll_l(s1: *const c_char, s2: *const c_char, _loc: locale_t) -> c_int {
21707 strcoll(s1, s2)
21708}
21709
21710#[no_mangle]
21711pub unsafe extern "C" fn strxfrm_l(dest: *mut c_char, src: *const c_char, n: usize, _loc: locale_t) -> usize {
21712 strxfrm(dest, src, n)
21713}
21714
21715#[no_mangle]
21716pub unsafe extern "C" fn strerror_l(errnum: c_int, _loc: locale_t) -> *mut c_char {
21717 strerror(errnum)
21718}
21719
21720#[no_mangle]
21721pub unsafe extern "C" fn strcasecmp_l(s1: *const c_char, s2: *const c_char, _loc: locale_t) -> c_int {
21722 strcasecmp(s1, s2)
21723}
21724
21725#[no_mangle]
21726pub unsafe extern "C" fn strncasecmp_l(s1: *const c_char, s2: *const c_char, n: usize, _loc: locale_t) -> c_int {
21727 strncasecmp(s1, s2, n)
21728}
21729
21730#[no_mangle]
21731pub unsafe extern "C" fn strftime_l(s: *mut c_char, max: usize, fmt: *const c_char, tm: *const tm, _loc: locale_t) -> usize {
21732 strftime(s, max, fmt, tm)
21733}
21734
21735#[no_mangle]
21736pub unsafe extern "C" fn nl_langinfo_l(item: c_int, _loc: locale_t) -> *mut c_char {
21737 nl_langinfo(item)
21738}
21739
21740#[no_mangle]
21741pub unsafe extern "C" fn wcscoll_l(s1: *const u32, s2: *const u32, _loc: locale_t) -> c_int {
21742 wcscoll(s1, s2)
21743}
21744
21745#[no_mangle]
21746pub unsafe extern "C" fn wcsxfrm_l(dst: *mut wchar_t, src: *const wchar_t, n: usize, _loc: locale_t) -> usize {
21747 wcsxfrm(dst, src, n)
21748}
21749
21750#[no_mangle]
21751pub unsafe extern "C" fn wcsftime_l(s: *mut u32, max: usize, fmt: *const u32, tm: *const c_void, _loc: locale_t) -> usize {
21752 wcsftime(s, max, fmt, tm)
21753}
21754
21755#[no_mangle]
21756pub unsafe extern "C" fn wctype_l(name: *const c_char, _loc: locale_t) -> wctype_t {
21757 wctype(name)
21758}
21759
21760#[no_mangle]
21761pub unsafe extern "C" fn wctrans_l(name: *const c_char, _loc: locale_t) -> wctrans_t {
21762 wctrans(name)
21763}
21764
21765#[no_mangle]
21766pub unsafe extern "C" fn towlower_l(c: wint_t, _loc: locale_t) -> wint_t {
21767 towlower(c)
21768}
21769
21770#[no_mangle]
21771pub unsafe extern "C" fn towupper_l(c: wint_t, _loc: locale_t) -> wint_t {
21772 towupper(c)
21773}
21774
21775#[no_mangle]
21776pub unsafe extern "C" fn towctrans_l(c: wint_t, desc: wctrans_t, _loc: locale_t) -> wint_t {
21777 towctrans(c, desc)
21778}
21779
21780#[no_mangle] pub unsafe extern "C" fn iswalnum_l(c: wint_t, _l: locale_t) -> c_int { iswalnum(c) }
21781#[no_mangle] pub unsafe extern "C" fn iswalpha_l(c: wint_t, _l: locale_t) -> c_int { iswalpha(c) }
21782#[no_mangle] pub unsafe extern "C" fn iswblank_l(c: wint_t, _l: locale_t) -> c_int { iswblank(c) }
21783#[no_mangle] pub unsafe extern "C" fn iswcntrl_l(c: wint_t, _l: locale_t) -> c_int { iswcntrl(c) }
21784#[no_mangle] pub unsafe extern "C" fn iswdigit_l(c: wint_t, _l: locale_t) -> c_int { iswdigit(c) }
21785#[no_mangle] pub unsafe extern "C" fn iswgraph_l(c: wint_t, _l: locale_t) -> c_int { iswgraph(c) }
21786#[no_mangle] pub unsafe extern "C" fn iswlower_l(c: wint_t, _l: locale_t) -> c_int { iswlower(c) }
21787#[no_mangle] pub unsafe extern "C" fn iswprint_l(c: wint_t, _l: locale_t) -> c_int { iswprint(c) }
21788#[no_mangle] pub unsafe extern "C" fn iswpunct_l(c: wint_t, _l: locale_t) -> c_int { iswpunct(c) }
21789#[no_mangle] pub unsafe extern "C" fn iswspace_l(c: wint_t, _l: locale_t) -> c_int { iswspace(c) }
21790#[no_mangle] pub unsafe extern "C" fn iswupper_l(c: wint_t, _l: locale_t) -> c_int { iswupper(c) }
21791#[no_mangle] pub unsafe extern "C" fn iswxdigit_l(c: wint_t, _l: locale_t) -> c_int { iswxdigit(c) }
21792#[no_mangle] pub unsafe extern "C" fn iswctype_l(c: wint_t, desc: wctype_t, _l: locale_t) -> c_int { iswctype(c, desc) }
21793
21794#[no_mangle] pub unsafe extern "C" fn __isoc99_scanf(fmt: *const c_char, args: ...) -> c_int { vfscanf(stdin, fmt, args) }
21796#[no_mangle] pub unsafe extern "C" fn __isoc99_fscanf(f: *mut FILE, fmt: *const c_char, args: ...) -> c_int { vfscanf(f, fmt, args) }
21797#[no_mangle] pub unsafe extern "C" fn __isoc99_sscanf(s: *const c_char, fmt: *const c_char, args: ...) -> c_int { vsscanf(s, fmt, args) }
21798#[no_mangle] pub unsafe extern "C" fn __isoc99_vscanf(fmt: *const c_char, args: VaList) -> c_int { vfscanf(stdin, fmt, args) }
21799#[no_mangle] pub unsafe extern "C" fn __isoc99_vfscanf(f: *mut FILE, fmt: *const c_char, args: VaList) -> c_int { vfscanf(f, fmt, args) }
21800#[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) }
21801#[no_mangle] pub unsafe extern "C" fn __isoc99_wscanf(fmt: *const wchar_t, args: ...) -> c_int { vfwscanf(stdin, fmt, args) }
21802#[no_mangle] pub unsafe extern "C" fn __isoc99_fwscanf(f: *mut FILE, fmt: *const wchar_t, args: ...) -> c_int { vfwscanf(f, fmt, args) }
21803#[no_mangle] pub unsafe extern "C" fn __isoc99_swscanf(s: *const wchar_t, fmt: *const wchar_t, args: ...) -> c_int { vswscanf(s, fmt, args) }
21804#[no_mangle] pub unsafe extern "C" fn __isoc99_vwscanf(fmt: *const wchar_t, args: VaList) -> c_int { vfwscanf(stdin, fmt, args) }
21805#[no_mangle] pub unsafe extern "C" fn __isoc99_vfwscanf(f: *mut FILE, fmt: *const wchar_t, args: VaList) -> c_int { vfwscanf(f, fmt, args) }
21806#[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) }
21807
21808#[no_mangle] pub unsafe extern "C" fn clearerr_unlocked(f: *mut FILE) { clearerr(f) }
21811#[no_mangle] pub unsafe extern "C" fn feof_unlocked(f: *mut FILE) -> c_int { feof(f) }
21812#[no_mangle] pub unsafe extern "C" fn ferror_unlocked(f: *mut FILE) -> c_int { ferror(f) }
21813#[no_mangle] pub unsafe extern "C" fn fileno_unlocked(f: *mut FILE) -> c_int { fileno(f) }
21814#[no_mangle] pub unsafe extern "C" fn fflush_unlocked(f: *mut FILE) -> c_int { fflush(f) }
21815#[no_mangle] pub unsafe extern "C" fn fgetc_unlocked(f: *mut FILE) -> c_int { fgetc(f) }
21816#[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) }
21817#[no_mangle] pub unsafe extern "C" fn fputc_unlocked(c: c_int, f: *mut FILE) -> c_int { fputc(c, f) }
21818#[no_mangle] pub unsafe extern "C" fn fputs_unlocked(s: *const c_char, f: *mut FILE) -> c_int { fputs(s, f) }
21819#[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) }
21820#[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) }
21821#[no_mangle] pub unsafe extern "C" fn fgetwc_unlocked(f: *mut FILE) -> wint_t { fgetwc(f) }
21822#[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) }
21823#[no_mangle] pub unsafe extern "C" fn fputwc_unlocked(c: wchar_t, f: *mut FILE) -> wint_t { fputwc(c, f) }
21824#[no_mangle] pub unsafe extern "C" fn fputws_unlocked(s: *const wchar_t, f: *mut FILE) -> c_int { fputws(s, f) }
21825#[no_mangle] pub unsafe extern "C" fn getwc_unlocked(f: *mut c_void) -> wint_t { getwc(f) }
21826#[no_mangle] pub unsafe extern "C" fn putwc_unlocked(c: u32, f: *mut c_void) -> wint_t { putwc(c, f) }
21827#[no_mangle] pub unsafe extern "C" fn getwchar_unlocked() -> wint_t { getwchar() }
21828#[no_mangle] pub unsafe extern "C" fn putwchar_unlocked(c: wchar_t) -> wint_t { putwchar(c) }
21829#[no_mangle] pub unsafe extern "C" fn fpurge(f: *mut FILE) { clearerr(f) }
21830#[no_mangle] pub unsafe extern "C" fn _IO_getc(f: *mut FILE) -> c_int { getc(f) }
21831#[no_mangle] pub unsafe extern "C" fn _IO_putc(c: c_int, f: *mut FILE) -> c_int { putc(c, f) }
21832#[no_mangle] pub unsafe extern "C" fn _IO_getc_unlocked(f: *mut FILE) -> c_int { getc(f) }
21833#[no_mangle] pub unsafe extern "C" fn _IO_putc_unlocked(c: c_int, f: *mut FILE) -> c_int { putc(c, f) }
21834#[no_mangle] pub unsafe extern "C" fn _IO_feof_unlocked(f: *mut FILE) -> c_int { feof(f) }
21835#[no_mangle] pub unsafe extern "C" fn _IO_ferror_unlocked(f: *mut FILE) -> c_int { ferror(f) }
21836
21837#[no_mangle] pub unsafe extern "C" fn __getauxval(t: c_ulong) -> c_ulong { getauxval(t) }
21839#[no_mangle] pub unsafe extern "C" fn __longjmp(env: *const c_ulong, val: c_int) -> ! { longjmp(env, val) }
21840#[no_mangle] pub unsafe extern "C" fn bsd_signal(sig: c_int, handler: usize) -> usize { signal(sig, handler) }
21841#[no_mangle] pub unsafe extern "C" fn __sysv_signal(sig: c_int, handler: usize) -> usize { signal(sig, handler) }
21842#[no_mangle] pub unsafe extern "C" fn eaccess(path: *const c_char, mode: c_int) -> c_int { access(path, mode) }
21843#[no_mangle] pub unsafe extern "C" fn __xpg_basename(path: *mut c_char) -> *mut c_char { basename(path) }
21844#[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) }
21845#[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) }
21846
21847#[no_mangle]
21852pub unsafe extern "C" fn cfsetspeed(termios_p: *mut c_void, speed: u32) -> c_int {
21853 let r = cfsetispeed(termios_p, speed);
21854 if r != 0 { return r; }
21855 cfsetospeed(termios_p, speed)
21856}
21857
21858#[no_mangle]
21859pub unsafe extern "C" fn futimesat(dirfd: c_int, path: *const c_char, times: *const timeval) -> c_int {
21860 if times.is_null() {
21861 return utimensat(dirfd, path, core::ptr::null(), 0);
21862 }
21863 let tv = times as *const [timeval; 2];
21864 let mut ts: [timespec; 2] = [
21865 timespec { tv_sec: (*tv)[0].tv_sec, tv_nsec: (*tv)[0].tv_usec * 1000 },
21866 timespec { tv_sec: (*tv)[1].tv_sec, tv_nsec: (*tv)[1].tv_usec * 1000 },
21867 ];
21868 for t in &mut ts {
21869 if t.tv_nsec < 0 || t.tv_nsec >= 1_000_000_000 {
21870 ERRNO!() = EINVAL;
21871 return -1;
21872 }
21873 }
21874 utimensat(dirfd, path, ts.as_ptr(), 0)
21875}
21876
21877#[no_mangle]
21878pub unsafe extern "C" fn membarrier(cmd: c_int, flags: c_int, cpu_id: c_int) -> c_int {
21879 <Arch as Syscalls>::syscall3(SYS_MEMBARRIER, cmd as i64, flags as i64, cpu_id as i64) as c_int
21880}
21881
21882#[no_mangle]
21883pub unsafe extern "C" fn mremap(
21884 old_address: *mut c_void,
21885 old_size: usize,
21886 new_size: usize,
21887 flags: c_int,
21888 mut args: ...
21889) -> *mut c_void {
21890 let new_address = if flags & 2 != 0 { args.next_arg::<*mut c_void>() } else { core::ptr::null_mut() };
21891 let r = <Arch as Syscalls>::syscall5(
21892 SYS_MREMAP,
21893 old_address as i64,
21894 old_size as i64,
21895 new_size as i64,
21896 flags as i64,
21897 new_address as i64,
21898 );
21899 if r < 0 {
21900 ERRNO!() = (-r) as c_int;
21901 return (-1isize) as *mut c_void;
21902 }
21903 r as *mut c_void
21904}
21905
21906#[no_mangle]
21907pub unsafe extern "C" fn ptsname_r(fd: c_int, buf: *mut c_char, buflen: usize) -> c_int {
21908 let name = ptsname(fd);
21909 if name.is_null() { return -1; }
21910 let n = crate::strlen(name);
21911 if n + 1 > buflen {
21912 ERRNO!() = ERANGE_VAL;
21913 return ERANGE_VAL;
21914 }
21915 core::ptr::copy_nonoverlapping(name, buf, n + 1);
21916 0
21917}
21918
21919#[no_mangle]
21920pub unsafe extern "C" fn posix_getdents(fd: c_int, buf: *mut c_void, len: usize, flags: c_int) -> isize {
21921 if flags != 0 {
21922 ERRNO!() = EINVAL;
21923 return -1;
21924 }
21925 let r = <Arch as Syscalls>::syscall3(SYS_GETDENTS64, fd as i64, buf as i64, len as i64);
21926 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
21927}
21928
21929#[no_mangle]
21930pub unsafe extern "C" fn riscv_flush_icache(start: *mut c_void, end: *mut c_void, flags: c_ulong) -> c_int {
21931 #[cfg(target_arch = "riscv64")]
21932 {
21933 let r = <Arch as Syscalls>::syscall3(259, start as i64, end as i64, flags as i64);
21934 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21935 }
21936 #[cfg(not(target_arch = "riscv64"))]
21937 {
21938 let _ = (start, end, flags);
21939 0
21940 }
21941}
21942
21943#[no_mangle]
21944pub unsafe extern "C" fn __riscv_flush_icache(start: *mut c_void, end: *mut c_void, flags: c_ulong) -> c_int {
21945 riscv_flush_icache(start, end, flags)
21946}
21947
21948#[no_mangle]
21949pub unsafe extern "C" fn mkostemps(template: *mut c_char, suffixlen: c_int, flags: c_int) -> c_int {
21950 let fd = mkstemps(template, suffixlen);
21951 if fd >= 0 && flags & O_CLOEXEC != 0 {
21952 sys_fcntl(fd, F_SETFD, FD_CLOEXEC as i64);
21953 }
21954 fd
21955}
21956
21957#[no_mangle]
21958pub unsafe extern "C" fn statfs(path: *const c_char, buf: *mut c_void) -> c_int {
21959 let r = <Arch as Syscalls>::syscall2(SYS_STATFS, path as i64, buf as i64);
21960 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21961}
21962
21963#[no_mangle]
21964pub unsafe extern "C" fn fstatfs(fd: c_int, buf: *mut c_void) -> c_int {
21965 let r = <Arch as Syscalls>::syscall2(SYS_FSTATFS, fd as i64, buf as i64);
21966 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21967}
21968
21969#[no_mangle]
21970pub unsafe extern "C" fn sysinfo(info: *mut c_void) -> c_int {
21971 let r = <Arch as Syscalls>::syscall1(SYS_SYSINFO, info as i64);
21972 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
21973}
21974
21975#[no_mangle]
21976pub unsafe extern "C" fn pthread_tryjoin_np(thread: PthreadT, retval: *mut *mut c_void) -> c_int {
21977 let slot = thread as *mut Thread;
21978 if slot.is_null() { return EINVAL; }
21979 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
21980 let tid = core::ptr::read_volatile(&raw const (*slot).tid);
21981 if tid > 0 { return EBUSY; }
21982 if tid < 0 { return EINVAL; }
21983 pthread_join(thread, retval)
21984}
21985
21986#[no_mangle]
21987pub unsafe extern "C" fn pthread_timedjoin_np(thread: PthreadT, retval: *mut *mut c_void, abstime: *const timespec) -> c_int {
21988 let slot = thread as *mut Thread;
21989 if slot.is_null() { return EINVAL; }
21990 if (*slot).detach_state == DT_DETACHED { return EINVAL; }
21991 loop {
21992 let r = pthread_tryjoin_np(thread, retval);
21993 if r != EBUSY { return r; }
21994 let tid = core::ptr::read_volatile(&raw const (*slot).tid);
21995 if tid <= 0 { continue; }
21996 let e = futex_timedwait(&raw mut (*slot).tid, tid, abstime);
21997 if e == ETIMEDOUT { return ETIMEDOUT; }
21998 }
21999}
22000
22001
22002#[repr(C)]
22005pub struct UtmpExit {
22006 pub e_termination: i16,
22007 pub e_exit: i16,
22008}
22009
22010#[repr(C)]
22011pub struct Utmpx {
22012 pub ut_type: i16,
22013 pub __ut_pad1: i16,
22014 pub ut_pid: i32,
22015 pub ut_line: [c_char; 32],
22016 pub ut_id: [c_char; 4],
22017 pub ut_user: [c_char; 32],
22018 pub ut_host: [c_char; 256],
22019 pub ut_exit: UtmpExit,
22020 pub ut_session: i32,
22021 pub __ut_pad2: i32,
22022 pub ut_tv: timeval,
22023 pub ut_addr_v6: [u32; 4],
22024 pub __unused: [u8; 20],
22025}
22026
22027const UTMP_SIZE: usize = 400;
22028const _: [(); UTMP_SIZE] = [(); core::mem::size_of::<Utmpx>()];
22029
22030static mut UTMP_FD: c_int = -1;
22031static mut UTMP_PATH: [u8; 256] = [0; 256];
22032static mut UTMP_PATH_SET: bool = false;
22033#[repr(align(8))]
22034struct UtmpBuf([u8; UTMP_SIZE]);
22035static mut UTMP_BUF: UtmpBuf = UtmpBuf([0; UTMP_SIZE]);
22036
22037unsafe fn utmp_path_ptr() -> *const c_char {
22038 if !UTMP_PATH_SET {
22039 let default = b"/var/run/utmp\0";
22040 let mut i = 0;
22041 while i < default.len() && i < UTMP_PATH.len() {
22042 UTMP_PATH[i] = default[i];
22043 i += 1;
22044 }
22045 UTMP_PATH_SET = true;
22046 }
22047 UTMP_PATH.as_ptr() as *const c_char
22048}
22049
22050unsafe fn utmp_open_read() -> c_int {
22051 if UTMP_FD >= 0 {
22052 crate::close(UTMP_FD);
22053 }
22054 UTMP_FD = crate::open(utmp_path_ptr(), 0, 0);
22055 UTMP_FD
22056}
22057
22058unsafe fn utmp_open_append() -> c_int {
22059 crate::open(utmp_path_ptr(), 1 | 64 | 1024, 0o644)
22060}
22061
22062#[no_mangle]
22063pub unsafe extern "C" fn setutent() {
22064 let _ = utmp_open_read();
22065}
22066
22067#[no_mangle]
22068pub unsafe extern "C" fn endutent() {
22069 if UTMP_FD >= 0 {
22070 crate::close(UTMP_FD);
22071 UTMP_FD = -1;
22072 }
22073}
22074
22075#[no_mangle]
22076pub unsafe extern "C" fn getutent() -> *mut c_void {
22077 if UTMP_FD < 0 && utmp_open_read() < 0 {
22078 return core::ptr::null_mut();
22079 }
22080 let n = crate::read(UTMP_FD, UTMP_BUF.0.as_mut_ptr() as *mut c_void, UTMP_SIZE);
22081 if n == UTMP_SIZE as isize {
22082 UTMP_BUF.0.as_mut_ptr() as *mut c_void
22083 } else {
22084 core::ptr::null_mut()
22085 }
22086}
22087
22088unsafe fn utmp_id_eq(a: &[c_char; 4], b: &[c_char; 4]) -> bool {
22089 a[0] == b[0] && a[1] == b[1] && a[2] == b[2] && a[3] == b[3]
22090}
22091
22092unsafe fn utmp_line_eq(a: &[c_char; 32], b: &[c_char; 32]) -> bool {
22093 let mut i = 0;
22094 while i < 32 {
22095 if a[i] != b[i] { return false; }
22096 if a[i] == 0 { return true; }
22097 i += 1;
22098 }
22099 true
22100}
22101
22102#[no_mangle]
22103pub unsafe extern "C" fn getutid(ut: *const c_void) -> *mut c_void {
22104 if ut.is_null() { return core::ptr::null_mut(); }
22105 let want = &*(ut as *const Utmpx);
22106 loop {
22107 let p = getutent();
22108 if p.is_null() { return p; }
22109 let cur = &*(p as *const Utmpx);
22110 let matched = match want.ut_type {
22111 1 | 2 | 3 | 4 => cur.ut_type == want.ut_type,
22112 _ => utmp_id_eq(&cur.ut_id, &want.ut_id)
22113 && (want.ut_type == 0 || cur.ut_type == want.ut_type),
22114 };
22115 if matched { return p; }
22116 }
22117}
22118
22119#[no_mangle]
22120pub unsafe extern "C" fn getutline(ut: *const c_void) -> *mut c_void {
22121 if ut.is_null() { return core::ptr::null_mut(); }
22122 let want = &*(ut as *const Utmpx);
22123 loop {
22124 let p = getutent();
22125 if p.is_null() { return p; }
22126 if utmp_line_eq(&(*(p as *const Utmpx)).ut_line, &want.ut_line) {
22127 return p;
22128 }
22129 }
22130}
22131
22132#[no_mangle]
22133pub unsafe extern "C" fn pututline(ut: *const c_void) -> *mut c_void {
22134 if ut.is_null() { return core::ptr::null_mut(); }
22135 let fd = utmp_open_append();
22136 if fd < 0 { return core::ptr::null_mut(); }
22137 let n = crate::write(fd, ut, UTMP_SIZE);
22138 crate::close(fd);
22139 if n == UTMP_SIZE as isize { ut as *mut c_void } else { core::ptr::null_mut() }
22140}
22141
22142#[no_mangle]
22143pub unsafe extern "C" fn updwtmp(file: *const c_char, ut: *const c_void) {
22144 if file.is_null() || ut.is_null() { return; }
22145 let fd = crate::open(file, 1 | 64 | 1024, 0o644);
22146 if fd >= 0 {
22147 let _ = crate::write(fd, ut, UTMP_SIZE);
22148 crate::close(fd);
22149 }
22150}
22151
22152unsafe fn utmp_set_name(file: *const c_char) -> c_int {
22153 if file.is_null() { return -1; }
22154 let len = crate::strlen(file);
22155 if len + 1 > UTMP_PATH.len() { return -1; }
22156 if UTMP_FD >= 0 {
22157 crate::close(UTMP_FD);
22158 UTMP_FD = -1;
22159 }
22160 core::ptr::copy_nonoverlapping(file, UTMP_PATH.as_mut_ptr() as *mut c_char, len + 1);
22161 UTMP_PATH_SET = true;
22162 0
22163}
22164
22165#[no_mangle]
22166pub unsafe extern "C" fn utmpname(file: *const c_char) -> c_int { utmp_set_name(file) }
22167
22168#[no_mangle]
22169pub unsafe extern "C" fn utmpxname(file: *const c_char) -> c_int { utmp_set_name(file) }
22170
22171
22172#[no_mangle] pub static mut ___environ: *mut *mut c_char = core::ptr::null_mut();
22174#[no_mangle] pub static mut _environ: *mut *mut c_char = core::ptr::null_mut();
22175#[no_mangle] pub unsafe extern "C" fn __freelocale(loc: locale_t) { freelocale(loc) }
22176#[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) }
22177#[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) }
22178#[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) }
22179#[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) }
22180
22181#[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) }
22182#[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) }
22183#[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) }
22184#[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) }
22185#[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) }
22186#[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) }
22187
22188const MAX_NS: usize = 3;
22193const MAX_SEARCH: usize = 6;
22194const HOST_NOT_FOUND: c_int = 1;
22195const TRY_AGAIN: c_int = 2;
22196const NO_RECOVERY: c_int = 3;
22197const NO_DATA: c_int = 4;
22198
22199static mut NS_COUNT: usize = 0;
22200static mut NS_ADDRS: [u32; MAX_NS] = [0; MAX_NS];
22201static mut SEARCH_COUNT: usize = 0;
22202static mut SEARCH_DOMAINS: [[u8; 256]; MAX_SEARCH] = [[0; 256]; MAX_SEARCH];
22203static mut RESOLV_INITIALIZED: bool = false;
22204
22205#[repr(C)]
22206struct SockAddrIn {
22207 sin_family: u16,
22208 sin_port: u16,
22209 sin_addr: u32,
22210 sin_zero: [u8; 8],
22211}
22212
22213#[repr(C)]
22214struct PollFd {
22215 fd: c_int,
22216 events: i16,
22217 revents: i16,
22218}
22219
22220unsafe fn resolv_skip_ws(line: &[u8], mut i: usize) -> usize {
22221 while i < line.len() && (line[i] == b' ' || line[i] == b'\t') { i += 1; }
22222 i
22223}
22224
22225unsafe fn resolv_token<'a>(line: &'a [u8], mut i: usize) -> (&'a [u8], usize) {
22226 let start = i;
22227 while i < line.len() && line[i] != b' ' && line[i] != b'\t' && line[i] != b'#' { i += 1; }
22228 (&line[start..i], i)
22229}
22230
22231unsafe fn resolv_parse_config() -> c_int {
22232 RESOLV_INITIALIZED = true;
22233 NS_COUNT = 0;
22234 SEARCH_COUNT = 0;
22235 let path = b"/etc/resolv.conf\0";
22236 let fd = crate::open(path.as_ptr() as *const c_char, 0, 0);
22237 if fd < 0 { return -1; }
22238 let mut buf = [0u8; 4096];
22239 let n = crate::read(fd, buf.as_mut_ptr() as *mut c_void, buf.len());
22240 crate::close(fd);
22241 if n <= 0 { return -1; }
22242 let len = n as usize;
22243 let mut i = 0;
22244 while i < len {
22245 let start = i;
22246 while i < len && buf[i] != b'\n' { i += 1; }
22247 let line = &buf[start..i];
22248 i += 1;
22249 let mut j = resolv_skip_ws(line, 0);
22250 if j >= line.len() || line[j] == b'#' { continue; }
22251 let (key, next) = resolv_token(line, j);
22252 j = next;
22253 if key == b"nameserver" {
22254 j = resolv_skip_ws(line, j);
22255 let (tok, _) = resolv_token(line, j);
22256 if !tok.is_empty() && NS_COUNT < MAX_NS {
22257 let mut name = [0u8; 64];
22258 let l = core::cmp::min(tok.len(), 63);
22259 name[..l].copy_from_slice(&tok[..l]);
22260 let addr = crate::inet_addr(name.as_ptr() as *const c_char);
22261 if addr != u32::MAX {
22262 NS_ADDRS[NS_COUNT] = addr;
22263 NS_COUNT += 1;
22264 }
22265 }
22266 } else if key == b"search" || key == b"domain" {
22267 loop {
22268 j = resolv_skip_ws(line, j);
22269 if j >= line.len() || line[j] == b'#' { break; }
22270 let (tok, next) = resolv_token(line, j);
22271 j = next;
22272 if tok.is_empty() { break; }
22273 if SEARCH_COUNT < MAX_SEARCH {
22274 let l = core::cmp::min(tok.len(), 255);
22275 SEARCH_DOMAINS[SEARCH_COUNT][..l].copy_from_slice(&tok[..l]);
22276 SEARCH_DOMAINS[SEARCH_COUNT][l] = 0;
22277 SEARCH_COUNT += 1;
22278 }
22279 if key == b"domain" { break; }
22280 }
22281 }
22282 }
22283 0
22284}
22285
22286#[no_mangle]
22287pub unsafe extern "C" fn res_init() -> c_int {
22288 let _ = resolv_parse_config();
22289 0
22290}
22291
22292#[no_mangle]
22293pub unsafe extern "C" fn res_mkquery(
22294 op: c_int,
22295 dname: *const c_char,
22296 class: c_int,
22297 type_: c_int,
22298 _data: *const u8,
22299 _datalen: c_int,
22300 _newrr: *const u8,
22301 buf: *mut u8,
22302 buflen: c_int,
22303) -> c_int {
22304 if dname.is_null() || buf.is_null() { return -1; }
22305 let mut l = crate::strnlen(dname as *const u8, 255);
22306 if l > 0 && *dname.add(l - 1) == b'.' as c_char { l -= 1; }
22307 if l > 0 && *dname.add(l - 1) == b'.' as c_char { return -1; }
22308 let n = 17 + l + if l != 0 { 1 } else { 0 };
22309 if l > 253 || buflen < n as c_int || op < 0 || op > 15 || class < 0 || class > 255 || type_ < 0 || type_ > 255 {
22310 return -1;
22311 }
22312 let mut q = [0u8; 280];
22313 crate::memset(q.as_mut_ptr() as *mut c_void, 0, n);
22314 q[2] = (op * 8 + 1) as u8;
22315 q[3] = 32;
22316 q[5] = 1;
22317 core::ptr::copy_nonoverlapping(dname as *const u8, q.as_mut_ptr().add(13), l);
22318 let mut i = 13;
22319 while q[i] != 0 {
22320 let mut j = i;
22321 while q[j] != 0 && q[j] != b'.' { j += 1; }
22322 if j - i - 1 > 62 { return -1; }
22323 q[i - 1] = (j - i) as u8;
22324 i = j + 1;
22325 }
22326 q[i + 1] = type_ as u8;
22327 q[i + 3] = class as u8;
22328 let mut ts = timespec { tv_sec: 0, tv_nsec: 0 };
22329 let _ = clock_gettime(CLOCK_REALTIME, &mut ts);
22330 let id = (((ts.tv_nsec as u64) + (ts.tv_nsec as u64) / 65536) & 0xffff) as u16;
22331 q[0] = (id >> 8) as u8;
22332 q[1] = id as u8;
22333 core::ptr::copy_nonoverlapping(q.as_ptr(), buf, n);
22334 n as c_int
22335}
22336
22337unsafe fn res_send_inner(msg: *const u8, msglen: c_int, answer: *mut u8, anslen: c_int) -> c_int {
22338 if msg.is_null() || answer.is_null() || msglen < 12 || anslen < 12 { return -1; }
22339 if !RESOLV_INITIALIZED { let _ = resolv_parse_config(); }
22340 if NS_COUNT == 0 {
22341 h_errno = TRY_AGAIN;
22342 return -1;
22343 }
22344 for n in 0..NS_COUNT {
22345 let fd = crate::socket(AF_INET, SOCK_DGRAM, 0);
22346 if fd < 0 { continue; }
22347 let sa = SockAddrIn {
22348 sin_family: AF_INET as u16,
22349 sin_port: 53u16.to_be(),
22350 sin_addr: NS_ADDRS[n],
22351 sin_zero: [0; 8],
22352 };
22353 let sent = crate::sendto(fd, msg as *const c_void, msglen as usize, 0, &sa as *const SockAddrIn as *const crate::sockaddr, 16);
22354 if sent != msglen as isize {
22355 crate::close(fd);
22356 continue;
22357 }
22358 let mut pfd = PollFd { fd, events: 1, revents: 0 };
22359 let pr = crate::poll(&mut pfd as *mut PollFd as *mut c_void, 1, 5000);
22360 if pr <= 0 {
22361 crate::close(fd);
22362 continue;
22363 }
22364 let r = crate::recvfrom(fd, answer as *mut c_void, anslen as usize, 0, core::ptr::null_mut(), core::ptr::null_mut());
22365 crate::close(fd);
22366 if r >= 12 {
22367 let id_ok = *answer == *msg && *answer.add(1) == *msg.add(1);
22368 let qr = (*answer.add(2) & 0x80) != 0;
22369 if id_ok && qr {
22370 return r as c_int;
22371 }
22372 }
22373 }
22374 h_errno = TRY_AGAIN;
22375 -1
22376}
22377
22378#[no_mangle]
22379pub unsafe extern "C" fn res_send(msg: *const u8, msglen: c_int, answer: *mut u8, anslen: c_int) -> c_int {
22380 if anslen < 512 {
22381 let mut buf = [0u8; 512];
22382 let r = res_send_inner(msg, msglen, buf.as_mut_ptr(), 512);
22383 if r >= 0 {
22384 let copy = core::cmp::min(r, anslen) as usize;
22385 if copy > 0 { core::ptr::copy_nonoverlapping(buf.as_ptr(), answer, copy); }
22386 }
22387 return r;
22388 }
22389 res_send_inner(msg, msglen, answer, anslen)
22390}
22391
22392#[no_mangle]
22393pub unsafe extern "C" fn res_query(
22394 dname: *const c_char,
22395 class: c_int,
22396 type_: c_int,
22397 answer: *mut u8,
22398 anslen: c_int,
22399) -> c_int {
22400 let mut q = [0u8; 280];
22401 let ql = res_mkquery(0, dname, class, type_, core::ptr::null(), 0, core::ptr::null(), q.as_mut_ptr(), q.len() as c_int);
22402 if ql < 0 { return ql; }
22403 let r = res_send(q.as_ptr(), ql, answer, anslen);
22404 if r < 12 {
22405 h_errno = TRY_AGAIN;
22406 return -1;
22407 }
22408 let rcode = answer.add(3).read() & 0x0f;
22409 if rcode == 3 {
22410 h_errno = HOST_NOT_FOUND;
22411 return -1;
22412 }
22413 if rcode == 0 && *answer.add(6) == 0 && *answer.add(7) == 0 {
22414 h_errno = NO_DATA;
22415 return -1;
22416 }
22417 if rcode != 0 {
22418 h_errno = NO_RECOVERY;
22419 return -1;
22420 }
22421 r
22422}
22423
22424#[no_mangle]
22425pub unsafe extern "C" fn res_querydomain(
22426 name: *const c_char,
22427 domain: *const c_char,
22428 class: c_int,
22429 type_: c_int,
22430 answer: *mut u8,
22431 anslen: c_int,
22432) -> c_int {
22433 if domain.is_null() || *domain == 0 { return res_query(name, class, type_, answer, anslen); }
22434 let mut buf = [0u8; 512];
22435 let nl = crate::strlen(name);
22436 let dl = crate::strlen(domain);
22437 if nl + 1 + dl >= buf.len() { return -1; }
22438 core::ptr::copy_nonoverlapping(name, buf.as_mut_ptr() as *mut c_char, nl);
22439 buf[nl] = b'.';
22440 core::ptr::copy_nonoverlapping(domain, buf.as_mut_ptr().add(nl + 1) as *mut c_char, dl);
22441 buf[nl + 1 + dl] = 0;
22442 res_query(buf.as_ptr() as *const c_char, class, type_, answer, anslen)
22443}
22444
22445#[no_mangle]
22446pub unsafe extern "C" fn res_search(
22447 name: *const c_char,
22448 class: c_int,
22449 type_: c_int,
22450 answer: *mut u8,
22451 anslen: c_int,
22452) -> c_int {
22453 if name.is_null() { return -1; }
22454 if !RESOLV_INITIALIZED { let _ = resolv_parse_config(); }
22455 let len = crate::strlen(name);
22456 let mut dots = 0;
22457 for i in 0..len {
22458 if *name.add(i) == b'.' as c_char { dots += 1; }
22459 }
22460 let trailing_dot = len > 0 && *name.add(len - 1) == b'.' as c_char;
22461 if trailing_dot || dots >= 1 {
22462 let r = res_query(name, class, type_, answer, anslen);
22463 if r >= 0 { return r; }
22464 if trailing_dot { return -1; }
22465 }
22466 for i in 0..SEARCH_COUNT {
22467 let dom = SEARCH_DOMAINS[i].as_ptr() as *const c_char;
22468 let r = res_querydomain(name, dom, class, type_, answer, anslen);
22469 if r >= 0 { return r; }
22470 if h_errno != HOST_NOT_FOUND && h_errno != NO_DATA { return -1; }
22471 }
22472 if dots == 0 {
22473 return res_query(name, class, type_, answer, anslen);
22474 }
22475 -1
22476}
22477
22478#[repr(C)]
22483pub struct HostEnt {
22484 pub h_name: *mut c_char,
22485 pub h_aliases: *mut *mut c_char,
22486 pub h_addrtype: c_int,
22487 pub h_length: c_int,
22488 pub h_addr_list: *mut *mut c_char,
22489}
22490
22491#[repr(C)]
22492pub struct AddrInfo {
22493 pub ai_flags: c_int,
22494 pub ai_family: c_int,
22495 pub ai_socktype: c_int,
22496 pub ai_protocol: c_int,
22497 pub ai_addrlen: u32,
22498 pub ai_addr: *mut c_void,
22499 pub ai_canonname: *mut c_char,
22500 pub ai_next: *mut AddrInfo,
22501}
22502
22503static mut HOST_ENT: HostEnt = HostEnt {
22504 h_name: core::ptr::null_mut(),
22505 h_aliases: core::ptr::null_mut(),
22506 h_addrtype: 0,
22507 h_length: 0,
22508 h_addr_list: core::ptr::null_mut(),
22509};
22510static mut HOST_NAME: [c_char; 256] = [0; 256];
22511static mut HOST_ALIASES: [*mut c_char; 1] = [core::ptr::null_mut()];
22512static mut HOST_ADDR: [u8; 16] = [0; 16];
22513static mut HOST_ADDR_PTRS: [*mut c_char; 2] = [core::ptr::null_mut(); 2];
22514
22515unsafe fn dns_skip_name(p: *const u8, end: *const u8) -> *const u8 {
22516 let mut q = p;
22517 while q < end {
22518 let c = *q;
22519 if c == 0 { return q.add(1); }
22520 if c & 0xc0 == 0xc0 { return q.add(2); }
22521 q = q.add(1 + c as usize);
22522 }
22523 end
22524}
22525
22526unsafe fn dns_read_u16(p: *const u8) -> u16 {
22527 ((*p as u16) << 8) | *p.add(1) as u16
22528}
22529
22530unsafe fn dns_expand_name(p: *const u8, msg: *const u8, out: *mut c_char, outlen: usize) -> bool {
22531 let mut q = p;
22532 let mut o = 0usize;
22533 let mut jumps = 0;
22534 loop {
22535 let c = *q;
22536 if c == 0 {
22537 if o < outlen { *out.add(o) = 0; }
22538 return true;
22539 }
22540 if c & 0xc0 == 0xc0 {
22541 let off = (((c & 0x3f) as usize) << 8) | *q.add(1) as usize;
22542 q = msg.add(off);
22543 jumps += 1;
22544 if jumps > 16 { return false; }
22545 continue;
22546 }
22547 let l = c as usize;
22548 if l > 63 { return false; }
22549 if o + l + 1 >= outlen { return false; }
22550 core::ptr::copy_nonoverlapping(q.add(1), out.add(o) as *mut u8, l);
22551 o += l;
22552 *out.add(o) = b'.' as c_char;
22553 o += 1;
22554 q = q.add(1 + l);
22555 }
22556}
22557
22558unsafe fn host_from_answer(answer: *const u8, len: c_int, af: c_int) -> *mut HostEnt {
22559 if len < 12 { return core::ptr::null_mut(); }
22560 let end = answer.add(len as usize);
22561 let qd = dns_read_u16(answer.add(4)) as usize;
22562 let an = dns_read_u16(answer.add(6)) as usize;
22563 let mut p = answer.add(12);
22564 for _ in 0..qd {
22565 p = dns_skip_name(p, end);
22566 p = p.add(4);
22567 }
22568 let want_type: u16 = if af == AF_INET6 { 28 } else { 1 };
22569 let want_len = if af == AF_INET6 { 16 } else { 4 };
22570 for _ in 0..an {
22571 p = dns_skip_name(p, end);
22572 if p.add(10) > end { break; }
22573 let typ = dns_read_u16(p);
22574 let class = dns_read_u16(p.add(2));
22575 let rdlen = dns_read_u16(p.add(8)) as usize;
22576 let rdata = p.add(10);
22577 if rdata.add(rdlen) > end { break; }
22578 if typ == want_type && class == 1 && rdlen == want_len {
22579 core::ptr::copy_nonoverlapping(rdata, HOST_ADDR.as_mut_ptr(), want_len);
22580 HOST_ENT.h_addrtype = af;
22581 HOST_ENT.h_length = want_len as c_int;
22582 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
22583 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
22584 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
22585 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
22586 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
22587 h_errno = 0;
22588 return &raw mut HOST_ENT;
22589 }
22590 p = rdata.add(rdlen);
22591 }
22592 core::ptr::null_mut()
22593}
22594
22595#[no_mangle]
22596pub unsafe extern "C" fn gethostbyname(name: *const c_char) -> *mut HostEnt {
22597 gethostbyname2(name, AF_INET)
22598}
22599
22600#[no_mangle]
22601pub unsafe extern "C" fn gethostbyname2(name: *const c_char, af: c_int) -> *mut HostEnt {
22602 if name.is_null() { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
22603 let mut addr = [0u8; 16];
22604 let addrlen = if af == AF_INET6 { 16 } else { 4 };
22605 if inet_pton(af, name, addr.as_mut_ptr() as *mut c_void) == 1 {
22606 core::ptr::copy_nonoverlapping(addr.as_ptr(), HOST_ADDR.as_mut_ptr(), addrlen);
22607 let n = crate::strlen(name);
22608 let l = core::cmp::min(n, 255);
22609 core::ptr::copy_nonoverlapping(name, HOST_NAME.as_mut_ptr(), l);
22610 HOST_NAME[l] = 0;
22611 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
22612 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
22613 HOST_ENT.h_addrtype = af;
22614 HOST_ENT.h_length = addrlen as c_int;
22615 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
22616 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
22617 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
22618 h_errno = 0;
22619 return &raw mut HOST_ENT;
22620 }
22621 let mut answer = [0u8; 512];
22622 let qtype = if af == AF_INET6 { 28 } else { 1 };
22623 let r = res_query(name, 1, qtype, answer.as_mut_ptr(), answer.len() as c_int);
22624 if r < 0 {
22625 if h_errno == 0 { h_errno = TRY_AGAIN; }
22626 return core::ptr::null_mut();
22627 }
22628 let ent = host_from_answer(answer.as_ptr(), r, af);
22629 if !ent.is_null() {
22630 let n = crate::strlen(name);
22631 let l = core::cmp::min(n, 255);
22632 core::ptr::copy_nonoverlapping(name, HOST_NAME.as_mut_ptr(), l);
22633 HOST_NAME[l] = 0;
22634 } else {
22635 h_errno = HOST_NOT_FOUND;
22636 }
22637 ent
22638}
22639
22640#[no_mangle]
22641pub unsafe extern "C" fn gethostbyaddr(addr: *const c_void, len: u32, type_: c_int) -> *mut HostEnt {
22642 if addr.is_null() || type_ != AF_INET || len != 4 { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
22643 let a = addr as *const u8;
22644 let mut name = [0u8; 128];
22645 let mut pos = 0;
22646 for i in 0..4 {
22647 let v = *a.add(3 - i) as u32;
22648 if v >= 100 { name[pos] = b'0' + (v / 100) as u8; pos += 1; }
22649 if v >= 10 { name[pos] = b'0' + ((v / 10) % 10) as u8; pos += 1; }
22650 name[pos] = b'0' + (v % 10) as u8; pos += 1;
22651 name[pos] = b'.'; pos += 1;
22652 }
22653 let suffix = b"in-addr.arpa";
22654 for &c in suffix { name[pos] = c; pos += 1; }
22655 name[pos] = 0;
22656 let mut answer = [0u8; 512];
22657 let r = res_query(name.as_ptr() as *const c_char, 1, 12, answer.as_mut_ptr(), answer.len() as c_int);
22658 if r < 12 { h_errno = HOST_NOT_FOUND; return core::ptr::null_mut(); }
22659 let end = answer.as_ptr().add(r as usize);
22660 let qd = dns_read_u16(answer.as_ptr().add(4)) as usize;
22661 let an = dns_read_u16(answer.as_ptr().add(6)) as usize;
22662 let mut p = answer.as_ptr().add(12);
22663 for _ in 0..qd { p = dns_skip_name(p, end); p = p.add(4); }
22664 for _ in 0..an {
22665 p = dns_skip_name(p, end);
22666 if p.add(10) > end { break; }
22667 let typ = dns_read_u16(p);
22668 let rdlen = dns_read_u16(p.add(8)) as usize;
22669 let rdata = p.add(10);
22670 if typ == 12 && dns_expand_name(rdata, answer.as_ptr(), HOST_NAME.as_mut_ptr(), HOST_NAME.len()) {
22671 let mut o = crate::strlen(HOST_NAME.as_ptr());
22672 if o > 0 && HOST_NAME[o - 1] == b'.' as c_char { o -= 1; }
22673 HOST_NAME[o] = 0;
22674 core::ptr::copy_nonoverlapping(a, HOST_ADDR.as_mut_ptr(), 4);
22675 HOST_ENT.h_name = HOST_NAME.as_mut_ptr();
22676 HOST_ENT.h_aliases = HOST_ALIASES.as_mut_ptr();
22677 HOST_ENT.h_addrtype = AF_INET;
22678 HOST_ENT.h_length = 4;
22679 HOST_ADDR_PTRS[0] = HOST_ADDR.as_mut_ptr() as *mut c_char;
22680 HOST_ADDR_PTRS[1] = core::ptr::null_mut();
22681 HOST_ENT.h_addr_list = HOST_ADDR_PTRS.as_mut_ptr();
22682 h_errno = 0;
22683 return &raw mut HOST_ENT;
22684 }
22685 p = rdata.add(rdlen);
22686 }
22687 h_errno = HOST_NOT_FOUND;
22688 core::ptr::null_mut()
22689}
22690
22691#[inline]
22696fn sysno(x86_64: i64, generic: i64) -> i64 {
22697 if cfg!(target_arch = "x86_64") { x86_64 } else { generic }
22698}
22699
22700#[no_mangle]
22701pub unsafe extern "C" fn settimeofday(tv: *const c_void, tz: *const c_void) -> c_int {
22702 let r = <Arch as Syscalls>::syscall2(sysno(164, 170), tv as i64, tz as i64);
22703 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22704}
22705
22706#[no_mangle]
22707pub unsafe extern "C" fn stime(t: *const i64) -> c_int {
22708 if t.is_null() { ERRNO!() = EINVAL; return -1; }
22709 let tv = timeval { tv_sec: *t, tv_usec: 0 };
22710 settimeofday(&tv as *const timeval as *const c_void, core::ptr::null())
22711}
22712
22713#[no_mangle]
22714pub unsafe extern "C" fn times(buf: *mut c_void) -> c_long {
22715 let r = <Arch as Syscalls>::syscall1(sysno(100, 153), buf as i64);
22716 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_long }
22717}
22718
22719#[no_mangle]
22720pub 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 {
22721 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);
22722 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22723}
22724
22725#[no_mangle]
22726pub unsafe extern "C" fn tee(fd_in: c_int, fd_out: c_int, len: usize, flags: u32) -> isize {
22727 let r = <Arch as Syscalls>::syscall4(sysno(276, 77), fd_in as i64, fd_out as i64, len as i64, flags as i64);
22728 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22729}
22730
22731#[no_mangle]
22732pub unsafe extern "C" fn statx(dirfd: c_int, path: *const c_char, flags: c_int, mask: u32, buf: *mut c_void) -> c_int {
22733 let r = <Arch as Syscalls>::syscall5(sysno(332, 291), dirfd as i64, path as i64, flags as i64, mask as i64, buf as i64);
22734 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22735}
22736
22737#[no_mangle]
22738pub unsafe extern "C" fn setns(fd: c_int, nstype: c_int) -> c_int {
22739 let r = <Arch as Syscalls>::syscall2(SYS_SETNS, fd as i64, nstype as i64);
22740 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22741}
22742
22743#[no_mangle]
22744pub unsafe extern "C" fn setfsuid(uid: u32) -> c_int {
22745 <Arch as Syscalls>::syscall1(sysno(122, 151), uid as i64) as c_int
22746}
22747
22748#[no_mangle]
22749pub unsafe extern "C" fn setfsgid(gid: u32) -> c_int {
22750 <Arch as Syscalls>::syscall1(sysno(123, 152), gid as i64) as c_int
22751}
22752
22753#[no_mangle]
22754pub unsafe extern "C" fn setregid(rgid: u32, egid: u32) -> c_int {
22755 let r = <Arch as Syscalls>::syscall2(sysno(114, 143), rgid as i64, egid as i64);
22756 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22757}
22758
22759#[no_mangle]
22760pub 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 {
22761 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);
22762 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22763}
22764
22765#[no_mangle]
22766pub 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 {
22767 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);
22768 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as isize }
22769}
22770
22771#[no_mangle]
22772pub unsafe extern "C" fn tcgetwinsize(fd: c_int, ws: *mut c_void) -> c_int {
22773 if fd < 0 || ws.is_null() { ERRNO!() = EINVAL; return -1; }
22774 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5413, ws as i64);
22775 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22776}
22777
22778#[no_mangle]
22779pub unsafe extern "C" fn tcsetwinsize(fd: c_int, ws: *const c_void) -> c_int {
22780 if fd < 0 || ws.is_null() { ERRNO!() = EINVAL; return -1; }
22781 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5414, ws as i64);
22782 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22783}
22784
22785#[no_mangle]
22786pub unsafe extern "C" fn sockatmark(fd: c_int) -> c_int {
22787 let mut at: c_int = 0;
22788 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x8905, &mut at as *mut c_int as i64);
22789 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { at }
22790}
22791
22792#[no_mangle]
22793pub unsafe extern "C" fn isastream(fd: c_int) -> c_int {
22794 let mut buf = [0u8; 64];
22795 let r = <Arch as Syscalls>::syscall3(SYS_IOCTL, fd as i64, 0x5401, buf.as_mut_ptr() as i64);
22796 if r < 0 { ERRNO!() = (-r) as c_int; 0 } else { 1 }
22797}
22798
22799#[no_mangle]
22800pub unsafe extern "C" fn posix_madvise(addr: *mut c_void, len: usize, advice: c_int) -> c_int {
22801 madvise(addr as *mut u8, len, advice)
22802}
22803
22804#[no_mangle]
22805pub unsafe extern "C" fn secure_getenv(name: *const c_char) -> *mut c_char {
22806 if getauxval(23) != 0 { return core::ptr::null_mut(); }
22807 getenv(name)
22808}
22809
22810#[no_mangle]
22811pub unsafe extern "C" fn sigandset(dest: *mut c_ulong, left: *const c_ulong, right: *const c_ulong) -> c_int {
22812 if dest.is_null() || left.is_null() || right.is_null() { return -1; }
22813 *dest = *left & *right;
22814 0
22815}
22816
22817#[no_mangle]
22818pub unsafe extern "C" fn sigorset(dest: *mut c_ulong, left: *const c_ulong, right: *const c_ulong) -> c_int {
22819 if dest.is_null() || left.is_null() || right.is_null() { return -1; }
22820 *dest = *left | *right;
22821 0
22822}
22823
22824#[no_mangle]
22825pub unsafe extern "C" fn sigisemptyset(set: *const c_ulong) -> c_int {
22826 if set.is_null() { return 1; }
22827 (*set == 0) as c_int
22828}
22829
22830#[no_mangle]
22831pub unsafe extern "C" fn sighold(sig: c_int) -> c_int {
22832 let set: c_ulong = 1u64 << (sig - 1) as u32;
22833 sigprocmask(0, &set, core::ptr::null_mut());
22834 0
22835}
22836
22837#[no_mangle]
22838pub unsafe extern "C" fn sigignore(sig: c_int) -> c_int {
22839 let _ = signal(sig, 1);
22840 0
22841}
22842
22843#[no_mangle]
22844pub unsafe extern "C" fn sigrelse(sig: c_int) -> c_int {
22845 let set: c_ulong = 1u64 << (sig - 1) as u32;
22846 sigprocmask(1, &set, core::ptr::null_mut());
22847 0
22848}
22849
22850#[no_mangle]
22851pub unsafe extern "C" fn siginterrupt(sig: c_int, flag: c_int) -> c_int {
22852 let mut sa: sigaction = core::mem::zeroed();
22853 if sigaction(sig, core::ptr::null(), &mut sa) != 0 { return -1; }
22854 if flag != 0 { sa.sa_flags &= !(SA_RESTART as c_int); } else { sa.sa_flags |= SA_RESTART as c_int; }
22855 sigaction(sig, &sa, core::ptr::null_mut())
22856}
22857
22858#[no_mangle]
22859pub unsafe extern "C" fn sigpause(sig: c_int) -> c_int {
22860 let set: c_ulong = 1u64 << (sig - 1) as u32;
22861 sigsuspend(&set)
22862}
22863
22864#[no_mangle]
22865pub unsafe extern "C" fn semtimedop(semid: c_int, sops: *mut c_void, nsops: usize, timeout: *const timespec) -> c_int {
22866 let r = <Arch as Syscalls>::syscall4(sysno(220, 192), semid as i64, sops as i64, nsops as i64, timeout as i64);
22867 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
22868}
22869
22870#[no_mangle]
22871pub unsafe extern "C" fn wait3(status: *mut c_int, options: c_int, rusage: *mut c_void) -> i32 {
22872 wait4(-1, status, options, rusage) as i32
22873}
22874
22875#[no_mangle]
22876pub unsafe extern "C" fn tempnam(dir: *const c_char, pfx: *const c_char) -> *mut c_char {
22877 let mut path = [0 as c_char; 256];
22878 let mut i = 0;
22879 if !dir.is_null() {
22880 while *dir.add(i) != 0 && i < 200 { path[i] = *dir.add(i); i += 1; }
22881 if i > 0 && path[i-1] != b'/' as c_char { path[i] = b'/' as c_char; i += 1; }
22882 } else {
22883 for &c in b"/tmp/" { path[i] = c as c_char; i += 1; }
22884 }
22885 if !pfx.is_null() {
22886 let mut j = 0;
22887 while *pfx.add(j) != 0 && i < 220 { path[i] = *pfx.add(j); i += 1; j += 1; }
22888 }
22889 for &c in b"XXXXXX" { path[i] = c as c_char; i += 1; }
22890 path[i] = 0;
22891 let fd = mkstemp(path.as_mut_ptr());
22892 if fd < 0 { return core::ptr::null_mut(); }
22893 close(fd);
22894 unlink(path.as_ptr());
22895 let n = strlen(path.as_ptr());
22896 let out = malloc(n + 1) as *mut c_char;
22897 if out.is_null() { return core::ptr::null_mut(); }
22898 core::ptr::copy_nonoverlapping(path.as_ptr(), out, n + 1);
22899 out
22900}
22901
22902#[no_mangle]
22903pub unsafe extern "C" fn putwc(c: u32, f: *mut c_void) -> u32 {
22904 fputwc(c as c_int, f as *mut FILE) as u32
22905}
22906
22907#[no_mangle]
22908pub unsafe extern "C" fn __uflow(f: *mut c_void) -> c_int {
22909 fgetc(f as *mut FILE)
22910}
22911
22912#[no_mangle]
22913pub unsafe extern "C" fn __xmknod(_ver: c_int, path: *const c_char, mode: c_uint, dev: u64) -> c_int {
22914 mknod(path, mode, dev)
22915}
22916
22917#[no_mangle]
22918pub unsafe extern "C" fn __xmknodat(_ver: c_int, dirfd: c_int, path: *const c_char, mode: c_uint, dev: u64) -> c_int {
22919 mknodat(dirfd, path, mode, dev)
22920}
22921
22922#[no_mangle]
22923pub 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 {
22924 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);
22925 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { 0 }
22926}
22927
22928#[no_mangle]
22929pub unsafe extern "C" fn open_by_handle_at(mount_fd: c_int, handle: *mut c_void, flags: c_int) -> c_int {
22930 let r = <Arch as Syscalls>::syscall3(sysno(304, 265), mount_fd as i64, handle as i64, flags as i64);
22931 if r < 0 { ERRNO!() = (-r) as c_int; -1 } else { r as c_int }
22932}
22933
22934#[no_mangle]
22935pub unsafe extern "C" fn dn_skipname(comp: *const u8, eom: *const u8) -> c_int {
22936 let p = dns_skip_name(comp, eom);
22937 if p <= eom { (p as isize - comp as isize) as c_int } else { -1 }
22938}
22939
22940#[no_mangle]
22941pub 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 {
22942 if exp.is_null() || dst.is_null() || dstsiz <= 0 { return -1; }
22943 let mut o = 0usize;
22944 let mut p = exp;
22945 loop {
22946 let start = p;
22947 while *p != 0 && *p != b'.' as c_char { p = p.add(1); }
22948 let l = p as usize - start as usize;
22949 if l > 63 || o + l + 2 > dstsiz as usize { return -1; }
22950 *dst.add(o) = l as u8; o += 1;
22951 core::ptr::copy_nonoverlapping(start as *const u8, dst.add(o), l);
22952 o += l;
22953 if *p == 0 { break; }
22954 p = p.add(1);
22955 }
22956 if o + 1 > dstsiz as usize { return -1; }
22957 *dst.add(o) = 0;
22958 (o + 1) as c_int
22959}
22960
22961#[repr(C)]
22966#[derive(Copy, Clone)]
22967pub struct Spwd {
22968 pub sp_namp: *mut c_char,
22969 pub sp_pwdp: *mut c_char,
22970 pub sp_lstchg: c_long,
22971 pub sp_min: c_long,
22972 pub sp_max: c_long,
22973 pub sp_warn: c_long,
22974 pub sp_inact: c_long,
22975 pub sp_expire: c_long,
22976 pub sp_flag: c_ulong,
22977}
22978
22979static mut SPWD_ENT: Spwd = Spwd {
22980 sp_namp: core::ptr::null_mut(), sp_pwdp: core::ptr::null_mut(),
22981 sp_lstchg: 0, sp_min: 0, sp_max: 0, sp_warn: 0, sp_inact: 0,
22982 sp_expire: 0, sp_flag: 0,
22983};
22984static mut SPWD_BUF: [c_char; 1024] = [0; 1024];
22985static mut SPWD_FILE: *mut FILE = core::ptr::null_mut();
22986
22987unsafe fn parse_spwd(line: *const c_char, ent: *mut Spwd, buf: *mut c_char, buflen: usize) -> bool {
22988 let mut src = line;
22989 let mut o = 0usize;
22990 let mut fields: [*mut c_char; 9] = [core::ptr::null_mut(); 9];
22991 let mut n = 0usize;
22992 while n < 9 {
22993 let start = o;
22994 while *src != 0 && *src != b':' as c_char {
22995 if o + 1 >= buflen { return false; }
22996 *buf.add(o) = *src;
22997 o += 1;
22998 src = src.add(1);
22999 }
23000 *buf.add(o) = 0;
23001 o += 1;
23002 fields[n] = buf.add(start);
23003 n += 1;
23004 if *src == 0 { break; }
23005 src = src.add(1);
23006 }
23007 if n < 9 { return false; }
23008 (*ent).sp_namp = fields[0];
23009 (*ent).sp_pwdp = fields[1];
23010 (*ent).sp_lstchg = crate::strtol(fields[2], core::ptr::null_mut(), 10) as c_long;
23011 (*ent).sp_min = crate::strtol(fields[3], core::ptr::null_mut(), 10) as c_long;
23012 (*ent).sp_max = crate::strtol(fields[4], core::ptr::null_mut(), 10) as c_long;
23013 (*ent).sp_warn = crate::strtol(fields[5], core::ptr::null_mut(), 10) as c_long;
23014 (*ent).sp_inact = crate::strtol(fields[6], core::ptr::null_mut(), 10) as c_long;
23015 (*ent).sp_expire = crate::strtol(fields[7], core::ptr::null_mut(), 10) as c_long;
23016 (*ent).sp_flag = crate::strtoul(fields[8], core::ptr::null_mut(), 10) as c_ulong;
23017 true
23018}
23019
23020#[no_mangle]
23021pub unsafe extern "C" fn setspent() {
23022 endspent();
23023 SPWD_FILE = crate::fopen(b"/etc/shadow\0".as_ptr() as *const c_char, b"r\0".as_ptr() as *const c_char);
23024}
23025
23026#[no_mangle]
23027pub unsafe extern "C" fn endspent() {
23028 if !SPWD_FILE.is_null() { crate::fclose(SPWD_FILE); SPWD_FILE = core::ptr::null_mut(); }
23029}
23030
23031#[no_mangle]
23032pub unsafe extern "C" fn getspent() -> *mut Spwd {
23033 if SPWD_FILE.is_null() { setspent(); if SPWD_FILE.is_null() { return core::ptr::null_mut(); } }
23034 let mut line = [0 as c_char; 1024];
23035 loop {
23036 if crate::fgets(line.as_mut_ptr(), 1024, SPWD_FILE).is_null() { return core::ptr::null_mut(); }
23037 if parse_spwd(line.as_ptr(), &raw mut SPWD_ENT, SPWD_BUF.as_mut_ptr(), SPWD_BUF.len()) {
23038 return &raw mut SPWD_ENT;
23039 }
23040 }
23041}
23042
23043#[no_mangle]
23044pub unsafe extern "C" fn fgetspent(f: *mut FILE) -> *mut Spwd {
23045 if f.is_null() { return core::ptr::null_mut(); }
23046 let mut line = [0 as c_char; 1024];
23047 loop {
23048 if crate::fgets(line.as_mut_ptr(), 1024, f).is_null() { return core::ptr::null_mut(); }
23049 if parse_spwd(line.as_ptr(), &raw mut SPWD_ENT, SPWD_BUF.as_mut_ptr(), SPWD_BUF.len()) {
23050 return &raw mut SPWD_ENT;
23051 }
23052 }
23053}
23054
23055#[no_mangle]
23056pub unsafe extern "C" fn getspnam(name: *const c_char) -> *mut Spwd {
23057 if name.is_null() { return core::ptr::null_mut(); }
23058 setspent();
23059 loop {
23060 let sp = getspent();
23061 if sp.is_null() { break; }
23062 if crate::strcmp((*sp).sp_namp as *const u8, name as *const u8) == 0 { endspent(); return sp; }
23063 }
23064 endspent();
23065 core::ptr::null_mut()
23066}
23067
23068#[no_mangle]
23069pub 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 {
23070 if result.is_null() { return EINVAL; }
23071 let p = getspnam(name);
23072 if p.is_null() { *result = core::ptr::null_mut(); 0 } else { *sp = *p; *result = sp; 0 }
23073}
23074
23075#[no_mangle]
23076pub unsafe extern "C" fn putspent(sp: *const Spwd, f: *mut FILE) -> c_int {
23077 if sp.is_null() || f.is_null() { return -1; }
23078 crate::fprintf(f, b"%s:%s:%ld:%ld:%ld:%ld:%ld:%ld:%lu\\n\0".as_ptr() as *const c_char,
23079 (*sp).sp_namp, (*sp).sp_pwdp, (*sp).sp_lstchg, (*sp).sp_min, (*sp).sp_max,
23080 (*sp).sp_warn, (*sp).sp_inact, (*sp).sp_expire, (*sp).sp_flag)
23081}
23082
23083#[no_mangle]
23084pub unsafe extern "C" fn getgrouplist(user: *const c_char, group: u32, groups: *mut u32, ngroups: *mut i32) -> c_int {
23085 if user.is_null() || groups.is_null() || ngroups.is_null() { return -1; }
23086 let max = *ngroups as usize;
23087 let mut n = 0usize;
23088 if n < max { *groups.add(n) = group; }
23089 n += 1;
23090 setgrent();
23091 loop {
23092 let g = getgrent();
23093 if g.is_null() { break; }
23094 if (*g).gr_gid == group { continue; }
23095 let mut found = false;
23096 let mut i = 0;
23097 while !(*(*g).gr_mem.add(i)).is_null() {
23098 if crate::strcmp(*(*g).gr_mem.add(i) as *const u8, user as *const u8) == 0 {
23099 found = true;
23100 break;
23101 }
23102 i += 1;
23103 }
23104 if found {
23105 if n < max { *groups.add(n) = (*g).gr_gid; }
23106 n += 1;
23107 }
23108 }
23109 endgrent();
23110 if n > max { *ngroups = n as i32; return -1; }
23111 *ngroups = n as i32;
23112 n as c_int
23113}